* Move Konnect projects into a global Control Planes organization
* fix: break new circular dependency in Konnect organization utils
useKonnectOrganization() imported useRootLoaderData from ~/root to read
accountId, but organization-utils.ts is itself reached from root.tsx via
the settings modal chain, closing a new import cycle flagged by CI's
dependency-cruiser check. Pass accountId in from the caller
(useOrganizations), which already has it, instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Konnect moved onboarding nudge.
* Can sync when the konnect org is empty.
* fix: guard two develop-introduced hooks against the Konnect organization
use-organization-storage-rule.ts and use-remote-files.ts's
useRemoteBackendProjects were added by develop's account-data refactor
after this plan's original API-guard audit, and both issued real
network/IPC calls for the local-only Konnect organization:
- useOrganizationStorageRule called the raw API directly and only
checked isScratchpadOrganizationId, missing Konnect. Fixed by
delegating to fetchAndCacheOrganizationStorageRule (which already
returns the correct local-only rules with no network call) instead
of gating with `enabled`, since a naive gate would fall back to the
permissive DEFAULT_STORAGE_RULES and surface Cloud Sync/Git Sync
inside Control Planes.
- useRemoteBackendProjects had no organization guard at all, firing
window.main.sync.remoteBackendProjectsOfTeam for an org whose
projects never have a remoteId. Fixed with an isLocalOrganizationId
check on its `enabled` gate.
Re-audited every other organizationId-scoped API guard in the plan;
no further gaps found. Plan doc updated with both findings.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix: disable Connect & Sync in Konnect settings modal without entitlement
The modal let a user validate and store a PAT even when the account
lacks the Konnect control-planes entitlement, even though syncing
could never run in that state — the sidebar's Sync button was already
disabled here but the modal's own Connect & Sync button was not.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix: re-fetch Konnect entitlements after logging back into the same account
refreshKonnectAccess deduped by accountId, but signing in never
reloads the renderer, so its module-level guard survives a logout —
and a fresh login into the same account keeps the same accountId,
silently skipping the re-fetch of /v1/user/entitlements.
Key the guard on sessionId instead: a new login always mints a new
session token even for the same account, so this still dedupes the
normal cold-start case (startup call and post-login loader share one
session) while correctly re-resolving after logout/login.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix: navigate away when the Konnect organization becomes invisible
Deleting a user's last Konnect project (one at a time via the project
delete action, or in bulk via Disconnect) could leave them stranded on
a URL for an organization that no longer appears in the dropdown, with
no automatic navigation elsewhere.
Add getKonnectOrganizationEscapeRoute(organizationId), which re-checks
visibility with a fresh local project count (no network call — only
that half can change from a plain NeDB delete) combined with the
last-resolved entitlement, updates the shared access store so
useOrganizations() reflects it immediately, and returns the account's
first real organization to redirect to when the org just went dark.
Call it from both places that can remove the last Konnect project:
- organization.$organizationId._index.tsx's loader, which every
"no reachable project" fallback already redirects through
- organization.$organizationId.project.$projectId.delete.tsx's
action, which previously short-circuited straight back into the
same (now invisible) organization instead of going through that
loader
Extracted the shared "recompute + store update" logic into
reconcileKonnectAccess() to avoid duplicating it between
refreshKonnectAccess() and the new escape-route check.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Migrate after login
* Force fetch storage rule
* Replace Konnect sync module-var trigger with event bus
Swaps the register/run module variable in konnect-sync-trigger.ts for
uiEventBus so the sync callback is subscribed/unsubscribed via useEffect
instead of being reassigned on every render with no cleanup.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Remove plan
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* fix: limit cookie template rendering to manually-set cookies and narrow template file access
* fix: only expand nested templates for variable substitution, not direct tag output
* test: cover OAuth2 access token exposure via the request tag for nested-template regression
* sec: exclude response-sourced cookies from WebSocket/Socket.IO connect rendering
* test: fix mTLS/cert smoke tests relying on secure-read-file path-prefix bug
* test: scope mtls smoke test locator to avoid strict-mode collision
* sec: close hard-link bypass of reserved NeDB database file check
* fix: avoid doubled path separator when allowlisted folder is a filesystem root
add initial settings for legacy test
add initial check for legacy unit test suites
show dropdown
remove spec route and merged with default debug page
showing document as collection
remove document term in UI
fix lint issue
fix ut failures
[INS-3702](https://konghq.atlassian.net/browse/INS-3702)
## Summary
- Extracts a JSONPath from each streaming SSE message and concatenates it into one readable transcript, shown in a new "Summary" tab next to Events — useful for debugging LLM streaming APIs (OpenAI, Anthropic, Gemini) without scrolling through raw chunks.
- Auto-infers the JSONPath from the request URL for known provider endpoints (OpenAI Chat Completions/legacy Completions/Responses, Anthropic Messages, Google Gemini streamGenerateContent), matched by pathname only (not full URL/host), so self-hosted or reverse-proxied endpoints that keep the same path shape still match. Falls back to a manually-editable path otherwise.
- Handles curl's SSE event log being chunk-granular rather than frame-granular (a JSON payload can span multiple raw network reads, or multiple SSE frames can land in one chunk) by reconstructing the raw wire text and re-parsing `data:` frames properly.
- Handles Gemini's default `streamGenerateContent` response (no `?alt=sse`), which is a single top-level JSON array with no `data:` frames and no blank lines between elements, by scanning the array's bracket/brace depth by hand and pulling out whichever elements have fully closed so far — including mid-stream, before the array's closing `]` (or even the last element's own closing `}`) has arrived — so the summary renders progressively instead of only after the full response finishes.
- Summary tab defaults to selected when the URL matches a known provider, otherwise Events stays default. Plain text/Markdown render toggle for the summary output.
- Scoped to `curl` (SSE) responses only — WebSocket, `socketIO`, and `mcp` responses are untouched.
## Summary
- Splits the single "Manage Environments" popover into two independent dropdowns — project-level and collection-level — each with a scope tooltip and an inheritance-order hint (folder overrides collection, which overrides project).
- Replaces the hidden "+" menu in the collection environment editor and the project-level full-page environment editor with explicit, always-visible "Add Sub Environment" / "Add Private Sub Environment" buttons.
- Adds an "Add Project Environment" action to the project dropdown (does not auto-select the new environment).
- Adds a keyboard shortcut for the project dropdown (Cmd/Ctrl+Alt+E), alongside the existing collection-environment shortcut (Cmd/Ctrl+Shift+E).
- Fixes smoke tests broken by removing the old single-picker trigger, and adds new coverage for the split dropdowns and create flows.
* poc: opt-in QuickJS sandbox for pre-request/after-response scripts
Adds settings.useQuickJsScriptSandbox (default off) and wires it into the
existing hidden-BrowserWindow dispatch point in concurrency.renderer.ts, so
scripts can optionally run in the QuickJS-WASM sandbox already used for
plugin template tags instead of the hidden window.
This PoC supports console, insomnia.environment/variables get/set, and
read-only insomnia.request; insomnia.sendRequest() and insomnia.test()/
pm.test() are not yet bridged and throw a clear error.
Full rollout plan (worker-boundary move, async host bridge, test-lifecycle
and request-mutation parity, security verification, telemetry/soak, and
eventually flipping the default to opt-out) is written up here:
https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* fix: address Copilot review feedback on QuickJS script sandbox PoC
- Timeout error now reports the configured duration instead of an epoch
deadline timestamp.
- insomnia.request is deep-frozen so mutation attempts are silently
no-ops consistently, rather than appearing to succeed inside the
script while never reaching the host.
- Fix operator-precedence bug in a test script (?? binds looser than +).
- Add an aria-label to the new sandbox toggle Switch for screen readers.
* poc: move QuickJS script execution to a dedicated Web Worker (PR 1)
Splits run-script-quickjs.ts into:
- quickjs-script-engine.ts: the pure QuickJS execution logic (unchanged
behavior), runnable from anywhere.
- quickjs-script.worker.ts: a Web Worker entry point that runs the engine
off the renderer's main thread.
- run-script-quickjs.ts: now a thin client that lazily creates the worker
(only when useQuickJsScriptSandbox is actually used) and correlates
postMessage/response pairs by id, matching the existing
templating-handler.ts/templating.worker.ts pattern used for template
tags.
A runaway script (e.g. an infinite loop) now blocks only the disposable
worker instead of the renderer's UI thread. A worker-level crash rejects
every in-flight call and the next call gets a fresh worker.
concurrency.renderer.ts is unchanged apart from continuing to import
runScriptInQuickJs by the same name/path.
Ref: PR 1 of the rollout plan — https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* style: formatting pass on quickjs worker-client test
* poc: async host bridge + insomnia.sendRequest() parity for QuickJS sandbox (PR 2)
Bridges insomnia.sendRequest() to a real HTTP request instead of throwing,
reusing the existing insomnia-templating-worker-database:// fetch protocol
and its network.sendRequestWithoutSideEffects handler (the same one the
template-tag sandbox already uses) rather than adding a second protocol
scheme. This is the same fetch-to-custom-protocol pattern
templating.worker.ts uses to reach the main process from a dedicated Web
Worker, generalized to a second async host bridge inside
quickjs-script-engine.ts (a VM promise resolved off a real fetch(),
settled via executePendingJobs() — no asyncify).
- quickjs-script-engine.ts: installSendRequestBridge() + BOOTSTRAP's
insomnia.sendRequest() now normalizes a URL string or a plain
{url, method, headers, body} object, calls the bridge, and rebuilds a
response object ({code, status, headers, body, responseTime, json(),
text()}) — supports both the Postman-style (error, response) callback
and awaiting the returned promise. insomnia.test()/pm.test() still
throws (unchanged).
- run-script-quickjs.ts (client): fetches the templating-db auth token
once via window.main.templatingDb.getAuthToken() (same pattern as
ui/worker/templating-handler.ts) and forwards it on every postMessage.
- quickjs-script.worker.ts: passes the auth token through to the engine.
Known gaps (documented in quickjs-script-engine.ts, deferred to a later
parity PR): no auth/client-certs/cookies/multipart-or-urlencoded bodies,
and the response object doesn't yet match the hidden-window Response
class's full surface (chai assertions, originalRequest, cookies).
Ref: PR 2 of the rollout plan — https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* Revert "poc: async host bridge + insomnia.sendRequest() parity for QuickJS sandbox (PR 2)"
This reverts commit 37d19c1da8.
* test: add e2e smoke test for QuickJS sandbox (PR 0 + PR 1 only)
Proves the opt-in QuickJS engine and Web Worker boundary work end to
end in the real Electron app, not just in vitest's mocked unit tests:
- console.log, insomnia.environment.get/set, and read-only
insomnia.request all work through the real Worker/QuickJS pipeline
(canary: `typeof require` confirms the script actually ran in
QuickJS, not the legacy hidden-window engine).
- A runaway (`while(true){}`) script blocks only its dedicated Worker —
the app UI stays responsive and interactive while it churns.
insomnia.sendRequest() (PR 2) is intentionally not exercised — it's
been split into its own WIP branch/PR (#10392) pending a real fix for
a QuickJSUseAfterFree crash that only reproduces under real Electron
timing.
Uses "testQueryParams", a request at the workspace root with no body
and no folder-inherited scripts. Every other candidate in this fixture
either references environment variables undefined until a script runs
(triggering Insomnia's "N environment variables are missing"
confirmation dialog) or inherits a folder-level after-response script
calling an API this minimal engine doesn't bridge, which turns an
otherwise-successful send into a displayed "Error" status. Asserting
via the Console tab (console.log output) instead of an echoed response
body sidesteps template rendering entirely.
Ref: PR 0/1 of the rollout plan — https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* fix(scripting): guard __proto__/constructor/prototype keys in QuickJS env/var bridge (#10395)
A script-supplied "__proto__"/"constructor"/"prototype" key reaching the bridge's store object could rewire its prototype or shadow those names; the bridge now rejects these keys before assignment.
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
* fix(deps): bump fast-uri to patch host-confusion SSRF vulnerabilities
fast-uri <3.1.5 is vulnerable to host confusion via backslash authority
delimiters and failed IDN canonicalization (GHSA advisories), which can
enable SSRF. ajv and @rjsf/utils already permit fast-uri ^3.x, so this
only required refreshing the lockfile resolution, no parent bump needed.
* fix(deps): bump undici to patch cookie/cache/desync vulnerabilities
undici <7.29.0 is affected by several advisories: Set-Cookie SameSite
downgrade via permissive substring matching, cross-user cache leakage
via whitespace bypass, downstream response desync via retry
interceptor, CRLF injection via blob-like body 'type', and cookie
attribute injection via unsanitized domain fields. The direct
dependency's existing ^7.25.0 range already permitted the fix, so this
only required refreshing the lockfile resolution.
Note: @connectrpc/connect-node@1.7.0 still bundles its own pinned
undici@^5.28.4 (resolves to 5.29.0), which remains vulnerable to the
older <6.24.0 advisories. Fixing that requires a major bump of
connect-node to 2.x, which needs its own review for breaking API
changes - tracked as a follow-up.
* fix(deps): bump builder-util-runtime to patch credential-leak vulnerability
builder-util-runtime <9.7.0 leaks PRIVATE-TOKEN and mixed-case
Authorization credentials on cross-origin redirects during
electron-updater's auto-update flow. electron-builder and
electron-builder-squirrel-windows pinned it exactly at 9.5.1, so
those parents needed bumping (26.8.1 -> 26.15.7) to pull the fix.
electron-updater's existing ^6.6.2 range already permitted 6.8.9,
which resolves the same fixed builder-util-runtime.
* fix(deps): bump liquidjs to patch memoryLimit bypass
liquidjs <=10.27.0's pop filter bypasses the memoryLimit accounting
enforced by its array-filter siblings, allowing a DoS via unbounded
memory growth in template rendering. Both consumers already declare
^10.27.0, which permits the fix, so this only required a lockfile
refresh (resolved to 10.28.0).
* fix(deps): bump ip-address to patch octal/decimal parsing SSRF
ip-address <=10.3.0 decodes Address4 leading-zero octets as decimal
while WHATWG URL host parsing, inet_aton, and getaddrinfo decode them
as octal, letting an attacker bypass IP-based trust boundaries and
achieve SSRF. express-rate-limit@8.3.2 pinned ip-address at an exact
10.1.0, so it needed bumping to 8.6.2 (still within @modelcontextprotocol/sdk's
^8.2.1 range) which declares ip-address ^10.2.0 and resolves to 10.4.0.
* fix(deps): bump tar to patch PAX parsing and recursion DoS issues
tar <=7.5.20 has multiple issues: process crash via PAX numeric path
type confusion, decompression/parse DoS via unlimited input, infinite
loop on negative entry size during archive replace, uncaught exception
via NUL bytes in PAX path/linkpath records, and uncontrolled recursion
in mapHas/filesFilter enabling stack-overflow DoS via crafted long-path
entries. node-gyp and @mapbox/node-pre-gyp already declare tar ^7.5.4 /
^7.4.0, which permit the fix, so this only required a lockfile refresh
(resolved to 7.5.22).
* fix(deps): bump ws to patch tiny-fragment memory exhaustion DoS
ws 8.0.0-8.20.1 bounds retained WebSocket message fragments via
maxFragments/maxBufferedChunks, but the defaults were set too high,
letting an attacker exhaust memory with many tiny fragments/chunks.
The direct ws dependency's ^8.18.1 range already permitted the fix;
socket.io/socket.io-client's bundled engine.io, engine.io-client, and
socket.io-adapter pinned ws with a `~8.20.1` tilde range that excluded
it, so those three needed bumping to pull in `~8.21.0` (still within
socket.io@4.8.3's own ~6.6.0/~6.6.1 ranges). All ws instances now
resolve to 8.21.2.
* fix(deps): bump hono to patch 33 advisories (cookie/CORS/routing/XSS)
hono <=4.12.33 accumulates a long list of fixes: cookie name validation
bypass on write/read paths, path traversal in toSSG() and serve-static
(including Windows backslash encoding), IP restriction bypass for
IPv4-mapped/non-canonical IPv6, JWT NumericDate/Bearer-scheme
validation gaps, cache middleware Vary header leakage, CORS wildcard
credential reflection, JSX SSR XSS via cx(), and a ReDoS in CORS's
Access-Control-Request-Headers handling, among others.
@modelcontextprotocol/sdk's existing ^1.17.5 range already permits
the fix; bumping it to 1.30.0 resolves hono to 4.13.0.
* fix(deps): bump valibot to patch flatten() TypeError on inherited keys
valibot <=1.4.1's flatten() helper throws a TypeError when validation
issues contain attacker-controlled object keys such as toString,
valueOf, or hasOwnProperty. @react-router/dev's existing ^1.2.0 range
already permits the fix, so this only required a lockfile refresh.
* fix(deps): bump dompurify to 3.4.13 (direct dep, lockfile refresh)
Direct dependency's existing ^3.4.10 range already permitted the fix;
this only required a lockfile refresh.
* fix(deps): bump morgan to 1.11.0 (transitive via @react-router/serve)
@react-router/serve@7.15.0's existing ^1.10.1 range already permitted
the fix, so this only required a lockfile refresh. Brings on-finished
along from ~2.3.0 to ~2.4.1 as a nested dependency bump.
* fix(deps): bump uuid from v9 to v11 to patch buffer bounds check
uuid <11.1.1 is missing a buffer bounds check in v3/v5/v6 when a buf
is provided, which can lead to memory corruption. insomnia-data,
insomnia-scripting-environment, and insomnia-smoke-test were still on
^9.0.1 (packages/insomnia already used ^11.1.1). This is a major
version bump, but the only APIs in use across these packages are v4()
and validate(), whose signatures are unchanged between v9 and v11, so
no code changes were needed. All three now resolve to uuid@11.1.1.
* fix(deps): bump csv-parse from v6 to v7
csv-parse 6.x is flagged for update to 7.0.2. This is a major version
bump (ESM/CJS dual-package modernization), but the sync `parse()` API
that packages/insomnia-scripting-environment and the sandbox's
require-interceptor (exposing it to user scripts as
'csv-parse/lib/sync') both rely on is unchanged - verified with an
identical before/after parse() smoke test. No code changes needed.
* fix(deps): bump react-router family to 7.18.2 to patch CSRF/XSS/DoS advisories
react-router 6.0.0-7.18.0 accumulates several advisories: CSRF via
PUT/PATCH/DELETE document requests, open redirect via backslash in
<Link>/useNavigate, RSCErrorHandler missing protocol validation (XSS),
arbitrary constructor injection via deserializeErrors() in SSR
hydration, and unauthenticated DoS via inefficient route matching.
react-router, @react-router/dev, @react-router/fs-routes,
@react-router/node, and @react-router/serve were all exact-pinned at
7.15.0 and needed bumping together (they're a version-locked family)
to 7.18.2 - a non-major fix version per npm audit.
One additional react-router advisory (RSC Mode CSRF Bypass, fixed only
in 8.3.0+) doesn't apply here: this app doesn't use React Server
Components (no react-server-dom-webpack/@vitejs/plugin-rsc usage in
the codebase), so the RSC-specific code path is never exercised.
As a side effect, @react-router/serve's bundled express moved from
4.22.1 to 4.22.2, which also fixes a body-parser DoS advisory
(silently-disabled size limit on invalid `limit` values) for that one
instance. Two other body-parser instances (smoke-test's own express,
and the MCP SDK's bundled express) remain on vulnerable body-parser
versions - tracked as a follow-up.
* fix(deps): bump socket.io-parser to patch zero-attachment memory exhaustion
socket.io-parser 4.0.0-4.2.6 lets a specially crafted packet make the
server wait for a large number of binary attachments and buffer them,
exhausting memory. socket.io@4.8.3's existing ~4.2.4 range already
permitted the fix, so this only required a lockfile refresh.
* fix(deps): bump body-parser (via smoke-test's express) to patch limit-bypass DoS
body-parser <1.20.6 silently disables its size-limit enforcement when
given an invalid `limit` value, allowing a DoS via unbounded request
bodies. insomnia-smoke-test's express (^4.21.2) already permitted the
fix; bumping it to 4.22.2 resolves body-parser to 1.20.6.
Note: @modelcontextprotocol/sdk still bundles express@5.2.1 with a
vulnerable body-parser@2.2.2 (needs >=2.3.0). Left unfixed for now -
Insomnia only uses the SDK's client-side StreamableHTTPClientTransport
(packages/insomnia/src/main/mcp/transport-streamable-http.ts), never
the SDK's server/express code path, so this instance is unreachable
in practice. A prior attempt to patch it via manual lockfile surgery
left package-lock.json in an inconsistent state (a resolved package
missing its "packages" entry, so `npm ci` wouldn't reproduce it) and
was reverted. Tracked as a follow-up to fix through a supported
mechanism (e.g. once @modelcontextprotocol/sdk relaxes its body-parser
range, or via a clean full lockfile regeneration reviewed on its own).
* fix(deps): bump form-data to patch CRLF injection (2 of 3 instances)
form-data <2.5.6 and >=4.0.0 <4.0.6 are vulnerable to CRLF injection
via unescaped multipart field names/filenames. @types/request's
^2.5.5 and jsdom's ^4.0.0 ranges already permitted the fix, resolving
to 2.5.6 and 4.0.6 respectively via lockfile refresh.
Note: httpsnippet@3.0.10 (the latest available release) exactly pins
form-data at 4.0.4, which stays vulnerable. There's no newer
httpsnippet version to bump to yet - this is upstream-blocked, not
fixable without an override. Tracked as a follow-up to revisit once
httpsnippet ships a fix.
* fix(deps): bump @customerio/cdp-analytics-browser to patch nested js-cookie + uuid
Bumps the pinned ^0.3.9 to ^0.5.9. This single bump fixes two
findings that were previously nested inside this analytics SDK and
not independently reachable:
- js-cookie: was exactly pinned at 3.0.1 (<=3.0.5 is vulnerable to a
per-instance prototype hijack in assign() enabling cookie-attribute
injection); now ^3.0.7, resolving to 3.0.8.
- uuid: customerio-gist-web bundled uuid@^8.3.2 (missing buffer bounds
check in v3/v5/v6, <11.1.1); now declares ^14.0.0, resolving to
14.0.1. This was the residual instance noted as a follow-up in the
earlier uuid v9->v11 commit.
The AnalyticsBrowser API surface used in use-cio.tsx (load/track/
identify/page/reset) is unchanged between 0.3.19 and 0.5.9.
* fix(deps): bump body-parser to 2.3.0 for the MCP SDK's bundled express
Fixes the remaining body-parser instance (via @modelcontextprotocol/sdk's
express@5.2.1, which declares ^2.2.1 - already permitted the fix).
This is the instance noted as unreachable/deferred in the prior
body-parser commit; the dependency graph has since shifted (from the
react-router and customerio bumps) enough that a plain `npm update
body-parser` now resolves it cleanly via a proper lockfile entry,
unlike the earlier attempt that left a broken lockfile via manual
surgery. All three body-parser instances are now fixed.
* refactor(templating): retire templateTagSandboxEnabled, unify on pluginSandboxEnabled
The experimental `templateTagSandboxEnabled` toggle only ever gated
template-tag execution and had been superseded by `pluginSandboxEnabled`,
which sandboxes every untrusted plugin surface. Retire the legacy flag:
- drop it from the Settings type + defaults
- simplify `isSandboxEnabled` to read only `pluginSandboxEnabled`
- bundle plugins are trusted, so their tags always run in-process (the
legacy all-modules/all-caps bundle sandbox branch is removed)
- remove the "Run template tags in sandbox" Preferences toggle
- carry a user's prior opt-in forward via a settings migration
(templateTagSandboxEnabled === true -> pluginSandboxEnabled = true),
then delete the stale field
Smoke helpers repointed to the surviving `toggle-plugin-sandbox`; the now
-duplicate `enablePluginSandbox` helper is folded into `enableSandbox`.
* refactor(plugins): rename 'trusted' execution mode to 'internal'
'trusted' is an internal-only PluginExecutionMode label for built-in
bundled plugins the user can't install or change; it's never surfaced in
the UI (the Plugins badge shows 'In-process'). Rename it to the more
neutral, descriptive 'internal' to match the docs. Distinct from the
plugin *registry* trust concept (resolveTrustedPlugin, the 'trusted-plugin'
guard), which is unchanged.
* sandbox: reject bundle-plugin name impersonation, remove stale doc (#10376)
* docs(settings): simplify 'Sandbox all plugin code' toggle description
Address review nit: drop implementation jargon (QuickJS-WASM, default-deny)
from the Preferences copy in favour of plain language, keeping the coverage
list and the full-host-access escape-hatch pointer.
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
* feat(settings): add proxyIntegrations option for first-party integrations
* fix(proxy): improve handling of integration host URLs in insomniaIntegrationHosts function
* feat(proxy): enhance proxy integration handling for various services and update settings help text
* feat(proxy): introduce ProxyScope to manage proxy usage for requests and all traffic
* refactor(proxy): rename ProxyScope to ProxyScopes and update references throughout the codebase
* feat: add sidebar focus setting for collections in General settings
* feat: add depthOffset prop to EmptyNode and RequestNode for sidebar focus adjustment
* feat: add sidebar collection-focus-mode swipe transitions animations
* feat: clear focus state when exiting collection focus mode
* feat: implement backToAllProjects method and update tests for sidebar navigation
* feat: enhance workspace active state check with polling mechanism
* feat: update cloud sync test to include navigation back to all projects before branch actions
* feat: add sidebar focus mode onboarding with dismissal persistence
* feat: update onboarding text for sidebar focus mode to clarify navigation
* fix: correct typo in onboarding text for sidebar focus mode
* feat: implement seedSettings function to pre-seed settings for tests and update sidebar focus mode onboarding tests
* add package
remove workspaceCount from rootLoaderData
move unrelevant loaders out
add query context
adapt tanstack query
fix som issues
add new ways to load data
initial changes
clean code
remove and fix code
add a method to get organization data in main
refine the way to get data from tanstack
fix issue
fix issues
fix duplicate calling issue
fix unsubscribe issue
fix merge issue
fix listen issue
fix find organization issue for workspace
support workspatemeta in tanstack query
update types
move logic to insomnia-data services
remove things
change to use service
fix the loader bug
remove a file
fix type issues
refine code for workspace-children
change style import
fix main type issue
fix type issue
fix data fetching
fix delete project issue
cache the sidebar data in main
add unit tests
update cache and cache service
fix issues from comment
revert organization change
fix issues from comment
fix test failures
fix test failures
add comments and refine way to get workspace children
fix dedup and import issue
remove useless code
add duplicate id check
fix type failures
fix mock server issue
resolve conflict
1.remove main process cache
add renderer level app data
fix issues
* fix issues from review
* feat(templating): (T1) pluginSandboxEnabled + per-plugin elevated opt-in, centralized gate
Introduces the trust-model flip's core logic and wires every untrusted-execution surface to it.
- New setting `pluginSandboxEnabled` (default off) that supersedes/absorbs `templateTagSandboxEnabled`:
either flag on activates the sandbox, so existing template-tag opt-ins keep working (migration bridge).
- New per-plugin `pluginConfig.elevated` escape hatch: a user plugin marked elevated runs in-process
with full host access even while the sandbox is on. Widened PluginConfig/PluginConfigMap/Plugin.config.
- New pure resolver `common/plugins/sandbox-mode.ts` (isSandboxEnabled / resolvePluginExecutionMode /
shouldSandboxPlugin) — the single source of truth replacing the 7 duplicated
`templateTagSandboxEnabled && directory !== ''` conditions. Dependency-free so main, the plugin
window, and the inso CLI node runtime all share it. Unit-tested (12 cases).
- Wired all surfaces to shouldSandboxPlugin: load-time discovery (now per-plugin, so an elevated
plugin is nodeRequire-d for live functions), request/response hooks (plugin-window + node runtime),
actions, and user template tags. Bundle-tag path reads isSandboxEnabled (bundle stays trusted).
No UI yet (next commit); default-off means no behavior change until a flag is toggled.
* feat(templating): (T1) Preferences UI — plugin-sandbox toggle + per-plugin elevated + mode indicator
- Scripting settings: new "Sandbox all plugin code (experimental)" toggle for pluginSandboxEnabled
(data-testid toggle-plugin-sandbox), beside the existing template-tag toggle.
- Plugins settings: each user plugin card now shows its resolved execution mode
(Sandboxed / Elevated / In-process, data-testid plugin-mode-<name>) and a "Full host access"
checkbox (data-testid plugin-elevated-<name>) that writes pluginConfig.<name>.elevated. Mode +
toggle read from live settings so they update immediately, before the plugin list reloads.
- Widened SerializablePlugin.config to carry the optional `elevated` flag through the bridge.
* test(templating): (T1) e2e — pluginSandboxEnabled sandboxes a user plugin; elevating runs it in-process
Composes the trust-flip's two user-visible behaviors on one action-probe plugin:
- Enabling the new pluginSandboxEnabled toggle (not the legacy template-tag flag) routes the user
plugin's action into the sandbox (canary reports ranin-sandboxed).
- Toggling "Full host access" in Preferences → Plugins flips the mode indicator to "Elevated" and the
same action then runs in-process (marker absent, ranin-mainprocess) — the per-plugin escape hatch.
Reuses the sandbox-action-collection.yaml fixture and the established writePlugin/clearPluginToast
helpers; adds enablePluginSandbox + setPluginElevated helpers.
* fix(templating): (T1) close two plugin-registry trust-cache gaps (#10326)
* fix(templating): close two plugin-registry trust-cache gaps
- pluginConfig.elevated is keyed by declared plugin name, not by folder;
a same-named folder placed alongside an already-elevated plugin
inherited its trust grant and ran in-process before any collision was
even noticed. traversePluginPath now pre-scans for duplicate names
(order-independent) and refuses to load any colliding folder.
- applyRequestHooks/applyResponseHooks tagged a caught error with
`error.plugin = plugin`, a plain assignment that a plugin-thrown Error
could intercept via its own `plugin` property setter, handing the hook
a live, mutable reference to its own cached registry entry and letting
it flip `directory`/`config.elevated` to defeat later sandboxing.
Switched to Object.defineProperty, which bypasses any such setter.
* fix(plugins): use relative-path containment check instead of startsWith
A bare .startsWith(base) on a resolved path accepts a sibling directory
whose name happens to prefix-match the base (e.g. /plugins-evil vs
/plugins). Added a shared isContainedIn helper (path.relative, rejects
.. or an absolute result) and applied it to both the existing
plugin-path containment check and the new duplicate-name pre-pass.
* fix(templating): (T1) address Copilot review — skip CLI settings read, scope bundle-tag sandbox to legacy flag
- network-adapter.node.ts: only read services.settings.get() when canSandbox (Electron). The pure-Node
inso CLI can never reach the sandbox host, so the read was wasted work; pass undefined otherwise
(shouldSandboxPlugin treats it as off). Both applyRequestHooks and applyResponseHooks.
- templating-worker-database.ts: bundle (first-party/trusted) template tags now sandbox only under the
legacy templateTagSandboxEnabled experiment, not the new pluginSandboxEnabled. The T1 flag isolates
*untrusted* plugins; sandboxing trusted bundle tags under it was an unintended behavior change.
Dropped the now-unused isSandboxEnabled import.
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
* feat(templating): (H1) in-sandbox response-hook API + marshaling
First increment of PR 10b (response hooks). Adds the sandbox-side machinery to
run a user plugin's response hook, without yet wiring the network adapters:
- __buildResponseApi(resp): faithful ES5 rebuild of plugins/context/response.ts
getters (status/headers/time, case-insensitive getHeader returning
string|string[]|null). getBody() bridges to the existing response.getBodyBuffer
path; getBodyStream() throws (a Node Readable can't cross the sandbox); setBody()
base64-encodes the bytes over a new response.setBody bridge path (no fs in the
sandbox) and updates bytesContent locally.
- __invokeHook: for response hooks, attaches context.response and a READ-ONLY
context.request (matches pluginRequest.init(..., true)), and marshals both the
request and response back out.
- host-bridge: response.setBody mapped at baseline (models.read, grouped with the
other response ops) — a bounded write to the host-set bodyPath, matching the
ungated in-process behavior; not a general fs write.
Unit test drives a response hook that reads status/headers, reads the body via
the bridge, and rewrites it via setBody (asserting the base64 round-trip and the
read-only request). Host runner + adapter integration + e2e are the next increment.
* feat(templating): (H1) route user-plugin response hooks through the sandbox
Wires the response-hook sandbox core into both hook paths so a user plugin's
response hook runs in QuickJS (bundle plugins and the flag-off path unchanged).
- templating-worker-database: runResponseHookInSandbox + the
plugin.runUserResponseHook handler; the response.setBody bridge handler
(base64-decode -> fs.writeFileSync) guarded to the responses directory as
defense in depth (bodyPath is host-set); pickHookResponseFields.
- network-adapter.node.ts (main/CLI): runs the response hook in the sandbox for
user plugins, merging the returned response fields onto newResponse.
- invoke-method.ts (plugin window): reaches the same runner over the protocol.
E2E: a user plugin response hook rewrites the body via setBody; the echo
response pane shows the rewrite. Flag off it reports ranin-mainprocess (control),
flag on ranin-sandboxed. Completes H1 (request hooks in PR 10a).
* fix(templating): (H1) revive bridged Buffer in response getBody + reject empty setBody
Addresses Copilot review on #10286:
- in-sandbox-bootstrap.ts: context.response.getBody() now revives the JSON-marshaled
Buffer shape ({ type: 'Buffer', data: [...] }) back into a (shimmed) Buffer, so hooks
consume it exactly like the in-process response API instead of a plain object.
- templating-worker-database.ts: response.setBody rejects a missing/non-string bodyBase64
(TypeError) instead of defaulting to '' — a write primitive must not silently truncate
the body to zero bytes. An empty string stays a valid empty body.
- sandbox-hooks.test.ts: the getBodyBuffer stub now returns the real marshaled Buffer
shape and the hook decodes with toString('utf8'), exercising the revive end-to-end.
* perf: rewrite command palette search to eliminate UI freezes and stale results
Problems fixed:
- clientLoader blocked navigation on every palette open, freezing the UI during
full sequential DB scan
- no AbortController: stale searches could overwrite newer results mid-type
- no debounce: every keystroke triggered a full DB traversal immediately
- React Aria's default contains filter re-filtered server-side fuzzy results,
silently dropping valid matches and making fuzzy work redundant
- no warm baseline: palette started blank until the entire load completed
Changes:
- move fuzzyMatch/fuzzyMatchAll → insomnia-data/common-src/search.ts (shared,
testable in node)
- move search logic → insomnia-data/node-src/services/helpers/command-search.ts
- per-request AbortController cancellation via abort(requestId)
- recursion depth guard (max 20) on request group traversal
- safeParent() replaces non-null assertions, safe against orphaned documents
- add CommandSearchResult type in insomnia-data/src/command-search-types.ts
- add useCommandSearch hook: 250ms debounce + abort on filter change + warm
baseline on mount
- add defaultFilter={() => true} to ComboBox, delegating all filtering to the
service
- delete routes/commands.tsx
* fix
* fix
* tech_design
* tech-doc
* add directory to git repo model
* tech doc
* tech doc
* use directory picker to select an existing repo to clone from/to
* tech doc
* Open git repo
* tech doc
* Implement Git project local storage features and add e2e tests
* tech doc
* Implement folder opening as Git projects with user trust confirmation
* Add Git credential selection to project creation form and enhance repo file watcher for directory availability
* tech doc
* refactor: clean up code and remove references to GIT_LOCAL_REPOS_DESIGN.md
* fix: handle optional author name in Git credential display
* feat: enhance Git credential handling for local repositories
* feat: enhance Git project folder handling and improve test descriptions
* fix: update Git project mode button copy
Rename 'Clone from URL' to 'Clone from Remote' and 'Open existing
folder' to 'Open local folder'. Update the smoke test selector and a
stale comment accordingly.
* fix: align control heights and styling in Git clone form
Standardize the credential select, author email select, and clone
location box to match the repository/branch comboboxes: shared
--line-height-xs height, consistent label spacing, and input-sized
value text and padding.
* feat: show clone target path and remember last clone folder
Default the clone parent directory to the folder the user last cloned
into, and render the resulting target path middle-truncated with a full
path tooltip via a new MiddleTruncate component.
* fix: reorder and align Open local folder input layout
Move the helper text directly below the Folder label, and align the
folder box and Choose folder button to the shared control height with
middle-truncated path display.
* feat: warn when opening a folder already used by a project
Add a git.checkGitRepoDirectory IPC that resolves the project adopting
a folder. The Open local folder flow checks at folder-pick time and
shows a red, no-background warning below the input offering to open the
existing project, and blocks continuing while the warning is present.
* fix: top-align empty organization view and scroll the full page
Replace the vertically centered grid with a top-aligned, page-scrolling
layout so the new project form no longer jumps when switching project
types and the scrollbar spans the whole pane.
* fix: align project modal to top and match folder description color
Top-align the project modal overlay so it no longer jumps as the form
height changes, and drop the dimmer color override on the Open local
folder helper text so it matches the repository URL field description.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: always use getRepoBaseDir
* fix comment
* delete duplicate code
* fix: test
* test: add Git repository relocation tests
* fix: ensure selection change handler converts key to string
---------
Co-authored-by: Pavlos Koutoglou <pkoutoglou@gmail.com>
Co-authored-by: Curry Yang <163384738+CurryYangxx@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Curry Yang <1019yanglu@gmail.com>
* feat(templating): PoC run plugin template tags in a QuickJS-WASM sandbox
Behind a new `templateTagSandboxEnabled` setting (default off), route plugin
template-tag execution through a QuickJS-WASM sandbox instead of invoking the
plugin's `run()` directly in the main process.
Approach (per PR #10072): bulk-copy render state into the sandbox as JSON,
rebuild the plugin `context` API in pure JS inside the sandbox, and bridge only
async work back to the host via the existing `pluginToMainAPI` handlers.
`node:crypto` is exposed as synchronous host functions so `require('crypto')`
works without a sync/async mismatch.
- templating/sandbox/: quickjs-runtime, marshal, host-bridge, in-sandbox-bootstrap,
plugin-tag-sandbox (+ parity tests vs in-process tags and node:crypto)
- main/templating-worker-database.ts: route execute handlers through the sandbox
when the flag is on; legacy path unchanged otherwise
- esbuild: keep quickjs-emscripten external so its .wasm resolves at runtime
- settings + scripting-settings UI toggle
- examples/insomnia-plugin-sandbox-demo: manual E2E fixture
Scope: template tags only; sandbox runs in main. require shim covers path + crypto
(other modules throw a clear error — follow-up work).
* test(smoke): e2e canary for the template-tag sandbox flag
Installs an inline probe plugin, renders its tags via the tag editor Live
Preview, and asserts the execution path flips main-process -> sandbox when
templateTagSandboxEnabled is toggled in Preferences > Scripting, with a
require('crypto') sha256 workload staying byte-identical across both paths.
* test(sandbox): suppress hardcoded-hmac-key semgrep finding on parity fixture
The HMAC key is a test vector for sandbox-vs-node:crypto parity, not a
credential; rename it to make that self-evident and add the repo-standard
nosemgrep suppression.
* fix(templating): contain sandbox plugin entry resolution to the plugin directory
Reject a package.json "main" that resolves outside the plugin's own folder
and bundled-plugin names that look like paths, so the sandbox source loader
cannot be steered into reading arbitrary files.
* fix(review): inline nosemgrep placement, plugin-load error context, cross-arch-safe canary
- Move the hardcoded-hmac-key suppression onto the flagged line (line-above
placement was not honored by the scanner).
- Wrap getPluginEntrySource failures with the plugin name for diagnosability.
- Derive the canary's expected arch from the Electron main process instead of
the Playwright runner so cross-arch setups can't flake the assertion.
* sec(templating): QuickJS template-tag sandbox additions (#10209)
* fix(sandbox): enforce timeout on synchronous plugin loops
QuickJS's executePendingJobs() blocks the host thread until a synchronous
call returns, so the wall-clock deadline in drivePromiseToString was never
checked during a tight sync loop in plugin code, hanging the Electron main
process indefinitely. Add a QuickJS interrupt handler, which is polled
during synchronous execution, to enforce the deadline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): clamp crypto.randomBytes size to prevent OOM
hostCrypto.randomBytes(size) passed the sandboxed number straight to
Node's crypto.randomBytes with no upper bound, letting a plugin request
a multi-GB allocation (e.g. crypto.randomBytes(2 ** 31)) and crash the
host process. Clamp to 64KB before the call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): cap QuickJS heap to prevent unbounded allocation
QuickJS.newContext() had no memory limit, so a plugin allocating without
bound could exhaust the WASM heap and crash the host process. Set a 32MB
ceiling via ctx.runtime.setMemoryLimit().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): resolve symlinks before validating plugin entry path
getPluginEntrySource's containment check compared raw path strings, so a
plugin directory with a symlinked entry (e.g. index.js -> ../../../etc/secret)
passed the check while fs.readFileSync followed the symlink and read the
out-of-directory target. Re-run the check against fs.realpathSync'd paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): close util.render sandbox escape
context.util.render() bridged to the shared render() pipeline, whose Liquid
engine dispatches any registered tag's real run() directly, in-process,
regardless of templateTagSandboxEnabled. A sandboxed plugin could hand it a
string containing "{% anyTag %}" (including its own tag) and have that tag
execute completely unsandboxed. Verified with a PoC that reached
child_process execution from inside a plugin tag with no require() or Node
access.
util.render is now restricted to plain {{ variable }} interpolation (the
only real existing use, confirmed against all built-in tag call sites) via
a second Liquid engine with no tags registered; {% tag %} syntax now fails
to parse instead of dispatching. Default render() behavior is unchanged for
every other caller.
Also drops the dead renderDepth field's misleading doc comment: within one
sandboxed execution the envelope's renderDepth is always 0, so depth could
never exceed 1 regardless of enforcement — it couldn't have caught this
recursion anyway.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): fixed linting issue
* fix(sandbox): fixed linting issue
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add native git credential provider and update related components
- Introduced a new NativeGitCredential type to support system git credential manager.
- Updated GitCredentials model to include native provider type.
- Implemented NativeProvider class to handle authentication via OS git credential manager.
- Refactored git service and utils to accommodate new repoPath parameter for native credentials.
- Enhanced UI components to support native credential setup and display.
- Updated migrations to ensure native credential singleton exists on startup.
- Adjusted various components to handle optional chaining for author fields.
* feat: enhance git credential migration and improve native provider path handling
* fixup: address feedback
* fix spawn error pipe on windows
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* refactor: update import path for GitCredentials type in NativeProvider
* feat: update project page to explicitly select custom Git credentials during project creation
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Close konnect configure modal after validating PAT.
* Remove unused file
* refactor: update delete/remove terminology for projects and workspaces based on konnect control plane presence
* Prevent users from changing the sync type for konnect projects
* Show Konnect tab when their are no projects under org.
* tmp
* Only create necessary konnect proxy env vars (#10005)
* Apply icons for konnect projects
* fix: remove Buffer class usage in renderer code (#10031)
* Streamline workspace create & settings form [INS-2621] (#9940)
* fix: skip file name collision validation when file name is unchanged
The validate callback parameter shadowed the outer `fileName` variable
(which holds the original name with extension). The folder-children
filter compared against the bare input value instead of the full
`fileName`, so the current file was never excluded — causing a false
"already exists" error whenever only the workspace name was edited.
Renaming the parameter to `inputValue` restores access to the outer
`fileName` so the filter correctly excludes the existing file before
checking for collisions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: make .yaml extension shift with input text in workspace settings
The invisible sizer span that drives the CSS grid column width had
static content (the initial filename), so the column never resized
as the user typed and the .yaml suffix stayed at a fixed position.
Switching the TextField to controlled mode (value + onChange) lets
the sizer span reflect the live input value, causing the .yaml label
to follow the text as characters are added or removed. Also removed
the excess pr-7 right-padding since the extension is now positioned
by the grid rather than by padding offset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: allow workspace filename input to adapt down to zero width inputs
* fix: sanitize file name value in workspace settings modal
Apply safeToUseInsomniaFileName to the TextField value prop so the
displayed and submitted value is always sanitized, matching the pattern
used in new-workspace-modal. Previously the controlled value reflected
raw input directly, bypassing character replacement.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: minor right padding correction for consistency between new/edit workspace settings filename input
* fix: remove unnecessary w-min from new workspace modal as well
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: enhance konnect sync UX with tooltip for last synced time
* feat: enhance konnect sync UX by navigating to the first project after sync
* feat: add onboarding modal for Konnect environment setup after first sync
* feat: refactor getKonnectDeploymentType for improved control plane type handling
* Fix flaky Konnect smoke test sync assertion
* Update packages/insomnia/src/ui/components/sidebar/project-navigation-sidebar/konnect-env-onboarding.tsx
Co-authored-by: Missy Turco <60163079+mcturco@users.noreply.github.com>
* Update packages/insomnia/src/ui/components/sidebar/project-navigation-sidebar/konnect-env-onboarding.tsx
Co-authored-by: Missy Turco <60163079+mcturco@users.noreply.github.com>
* refactor: remove click and escape handlers from KonnectEnvOnboarding component
* fix: remove unnecessary filter for proxy defaults in upsertProjectEnvVars function
* Keep in Konnect tab after deleting konnect projects.
* Fix Konnect proxy env var creation on sync
* Add Kubernetes Ingress Controller SVG icon to project navigation sidebar
* feat: add k8sIngressController deployment type and corresponding icon
- Updated getKonnectDeploymentType to return 'k8sIngressController' for K8SIngressController control plane type.
- Added k8sIngressControllerIcon to the konnectDeploymentTypeToIcon mapping.
- Fixed the path for serverless.svg and added a new serverless.svg file with the appropriate SVG content.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* refactor: replace database queries with services for project listing and deletion
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* refactor: update control plane configuration to enforce cloud_gateway property and improve deployment type handling
* fix: memoize createInProjectActionList to prevent DOM detachment in menu
* fix: remove proxy defaults check in upsertProjectEnvVars function
* fix: update sync logic to handle environment onboarding and navigation for first successful sync
* fix: add LastSyncedLabel component for improved sync status display
* fix: simplify active tab update logic in project navigation sidebar
* fix: update environment variable mapping tests for proxy vars handling
---------
Co-authored-by: Ryan Willis <ryan.willis@konghq.com>
Co-authored-by: Vivek Thuravupala <2700229+godfrzero@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Missy Turco <60163079+mcturco@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Move insomnia-data models, services, database code, and common utilities into a dedicated workspace package. Update consumers to import from the new package entrypoints and declare workspace dependencies for the extracted package.