Commit Graph
4461 Commits
Author SHA1 Message Date
xiaodemen a3e0eead8a feat: remove ipcMainOn for sync 2026-09-16 10:45:18 +08:00
xiaodemen ffecd9d5ae fix: just use two channels 2026-09-11 14:00:19 +08:00
xiaodemen 124f9a3443 fix: fix test 2026-09-07 15:02:55 +08:00
xiaodemen f269f6a639 refactor: easy way to use IPC
feat: use handler-trigger pattern for cloud sync IPC

fix: use generated handler to create trigger

fix: use proxy to trigger IPC for sync
2026-09-07 15:02:55 +08:00
Bingbing 4f916ae8ae fix: prevent environment blank row focus race (#10473)
## Problem

When editing a project environment in Table View with no key/value entries, the trailing blank row could freeze the UI after renaming the environment in the header and immediately clicking the blank `Input Name` field.

The blank row was simultaneously managed by React Aria's `ListBox autoFocus="last"`, an imperative `ListBoxItem.onFocus` handoff, and `OneLineEditor` autofocus/retry logic. In the single-item boundary case these focus owners could race with `FocusScope` restoration and async environment revalidation.

## Fix

- Keep the trailing blank row inside the existing React Aria `ListBox` so row semantics, styling, keyboard navigation, drag-and-drop, and state behavior remain unchanged.
- Remove `ListBox autoFocus="last"` and the blank-row `ListBoxItem` focus handoff.
- Give the blank row's `OneLineEditor` one-shot autofocus on initial editor mount. This works for both empty and non-empty lists and is cleared after the initial autofocus.
- Track editor refs by distinct name/value editor ids.
- Restore focus once to the editor that was active when a blank row was converted into a persisted pair, after the persisted data update has mounted the new editor.

This prevents repeated focus stealing while preserving focus through the blank-row-to-persisted-row transition.
2026-09-07 14:44:54 +08:00
Curry Yang e446fef646 fix(git): enable bidirectional sync for local projects without a remote (#10471) 2026-09-04 03:56:33 +00:00
Bingbing 3b77d58829 fix(ui): hide project environment picker in scratchpad (#10472) 2026-09-03 10:06:26 +00:00
Bingbing 1b9c08d007 feat(ui): split environment picker into project/collection dropdowns (#10446)
## 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.
2026-09-03 08:52:20 +00:00
yaoweiprc 3e97ba7bfe One VCS instance per workspace [INS-2026] (#10458)
* 1

* One VCS instance per workspace

* Remove cloud sync doc.
2026-09-03 16:18:36 +08:00
Bingbing 8ea672ab01 fix(ui): re-render pane templates on project environment switch (#10467)
[INS-2791](https://konghq.atlassian.net/browse/INS-2791)

## Summary
- Switching a request's project environment (activeGlobalEnvironment) left the request pane's template values stale, since its remount `key` only tracked the workspace environment (activeEnvironment). 
- Added the project environment id/modified timestamp to the URL bar's remount key so it also refreshes on project environment switch.
2026-09-02 08:41:27 +00:00
Bingbing baaaf6ab1a chore: fix playwright port detect (#10462)
## Background

- In the latest vite up gradation, the log is `VITE v7.3.1  ready in 1145 ms` instead of `VITE ready in`
- Playwright SIGKILLs the process by default, which leaves a stale .vite-port file

## Changes

- Update the wait pattern
- Use gracefulShutdown
- Always try to cleanup when receive any exit event
2026-09-02 07:24:13 +00:00
Bingbing d285404f50 fix: use unique id for remote files in command search to avoid the list jammed (#10461)
## Background

- Cloud Sync workspace uses local workspace id as its id, which may duplicate with the workspace id in the local db. (Clone a github repo -> convert to cloud sync -> clone it again)

## Changes

- Use team project id + project id as the unique id
2026-09-01 07:24:20 +00:00
Curry Yang 0c2559df36 fix: initial entry (#10456) 2026-08-31 06:29:00 +00:00
yaoweiprc fdd06c9f4e fix(mock-response-extractor): await patchMockRoute and navigate to updated route (#10397) 2026-08-31 03:23:46 +00:00
George dea84ed772 docs: add a skill file for scripting feature bug fix (#10418)
* docs: add a skill file for scripting feature bug fix

* chore: improvements

* fix: comments
2026-08-27 08:46:14 +00:00
Kent Wang e28f9f84af fix expand issue when no request group meta (#10453) 2026-08-27 08:18:03 +00:00
Bob Qiu 393dcebbf1 fix(test): improve cloud sync tests to handle asynchronous loading and increase timeout (#10440) 2026-08-27 15:16:17 +08:00
kwburns-kong 1f7559cb7a fix(main): compare full origin, not string prefix, for renderer nav guard (#10442)
* fix(main): compare full origin, not string prefix, for renderer nav guard (INS-3622)

Use isTrustedAppOrigin (parsed origin comparison) instead of
url.startsWith(appUrl) for will-navigate and will-redirect on the main
window.

* fix(main): restrict trusted-origin check to http/https schemes (INS-3622)

blob:/data: URLs report an origin derived from embedded text, not
actual creation context, so they could spoof isTrustedAppOrigin.
2026-08-27 06:34:41 +00:00
Bingbing d9bb2b0142 fix(network): send fully rendered request for SSE connections (#10445)
[INS-3637](https://konghq.atlassian.net/browse/INS-3637)

## Summary
- SSE ("Event Stream") sends re-fetched the raw, unrendered request from the database instead of using the already-rendered/de-duplicated/interpolated request the renderer had computed, so headers/authentication/body reaching curl could diverge from what the user configured.
- `openCurlConnection` now takes one fully-rendered request object (`{ workspaceId, renderedRequest, initialPayload? }`) instead of piecemeal fields, drops the redundant DB read, and computes the auth header in-process via `getAuthHeader` instead of a separate IPC round trip.
- Fixed `createConfiguredCurlInstance`'s manual-proxy branch, which resolved protocol/hostname from the raw stored URL instead of the request's actual URL.
- Added `curl.test.ts` and `libcurl-promise.test.ts`; patched shared test infra (`setup-vitest.ts`, `src/__mocks__/electron.ts`) so named imports from `electron` resolve under the mock and `electron.app.on(...)` doesn't throw.

## Test plan
- [x] `npx tsc --noEmit` clean on changed files
- [x] `npx eslint` clean on changed files
- [x] `npx vitest run` — full suite: 162 files / 2244 passed, 15 pre-existing skips
- [x] Manually verify an SSE request (e.g. POST with `Accept: text/event-stream` to a streaming API) sends the expected single Accept header and correct body/auth

[INS-3637]: https://konghq.atlassian.net/browse/INS-3637?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2026-08-26 17:47:48 +08:00
yaoweiprcandClaude Sonnet 5 5101512701 fix(cloud-sync): surface stale/reverted staged changes instead of silently committing them [INS-3520] (#10438)
* fix(cloud-sync): surface stale/reverted staged changes instead of silently committing them

status() diffed the working tree against HEAD only, so a key whose content
returned to HEAD while still staged (or was staged-then-deleted before ever
being committed) was invisible to both the staged and unstaged views —
takeSnapshot() would then commit the stale staged content unnoticed
(INS-3520).

- status() now diffs against the index (HEAD with the stage overlaid via a
  new applyStageToState helper, also reused by takeSnapshot()) so these
  cases surface as actionable unstaged entries, with explicit branches for
  every stage/entry combination instead of a single blobId comparison that
  was tautological for deletions.
- stage() drops an entry instead of storing it when the incoming content is
  a no-op relative to HEAD, keeping the sparse stage map from accumulating
  entries that would otherwise still show as staged and produce empty
  commits.
- Removed the unused key field from status()'s return (and the Status
  type), which was computed but never read anywhere.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix type check

* rm doc

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 16:29:58 +08:00
xdm 4b121c89f6 refactor(vcs): move vcs to insomnia-vcs (#10427)
refactor(vcs): move vcs to insomnia-vcs

fix: fix comments
2026-08-26 14:37:16 +08:00
Insomnia 1755d42406 Bump app version to 13.2.0 (#10439) 2026-08-25 09:30:13 +00:00
xdm bf982e7895 refactor: move organization to service layer (#10390) 2026-08-25 09:13:41 +00:00
Bingbing ccefed1d2e chore: support dynamic port for dev (#10308)
* chore: support dynamic port

* fix: handle missing .vite-port and prevent stale file race

- window-utils.ts: wrap .vite-port read in try/catch with fallback to
  default port 3334, preventing crash when file is missing
- esbuild.entrypoints.ts: delete .vite-port at start of dev build so
  wait-on doesn't pick up a stale port from a previous run

* fix: derive smoke-test webServer port from per-worktree .vite-port

Hardcoded url: 'http://localhost:3334' made playwright's webServer
reuse-detection cross-worktree: if another worktree's dev server was
already answering on 3334, this worktree's tests silently reused it
instead of starting their own. Read the worktree's own .vite-port file
(written by vite.config.ts) instead, falling back to plain stdout-regex
readiness when no port file exists yet.
2026-08-25 16:42:14 +08:00
yaoweiprc 3724a9d88a Update localstorage key (#10401) 2026-08-25 06:34:26 +00:00
Kent Wang 01fe9b7c7f fix shortcut creation issue & workspace dropdown context menu issue (#10432)
fix action issue

remove use less codes

modify optimistic way to toggle request folder
2026-08-25 01:30:23 +00:00
Bingbing ca4620789d fix(ui): restore h-fit on cookies modal (#10437)
PR #10097 dropped h-fit from the Modal className as an unrelated
side effect of a class rewrite, leaving the modal stretched to the
overlay's full height with empty space below the content.
2026-08-24 10:20:52 -04:00
Bob Qiu 89df8f6a84 fix(test): impove test stability of git repository relocation tests (#10436)
* fix(test): ensure scoped selection for storage type and improve click reliability in project creation

* fix(test): expand shard matrix for smoke tests and repeat each test for git-local-repos

* fix(test): adjust shard matrix for smoke tests to match total shards

* fix(test): update shard matrix for smoke tests to include additional runs

* fix(test): update smoke test sharding to improve parallel execution and reliability

* fix(test): update smoke test configuration for improved execution and reporting

* fix(test): update smoke test configuration to use sharding for improved execution

* fix(test): refactor git repository relocation tests to use dedicated method for moving repositories
2026-08-24 16:26:52 +08:00
Bob Qiu 3e83fe2768 fix(test): improve stability of git local repo tests (#10433) 2026-08-24 03:45:19 +00:00
Bingbing 71fc333264 fix(git): don't write empty git author identity when opening local git projects (#10430)
Opening an existing local folder as a git project could leave an empty
[user] name/email in the repo's .git/config, which blocks git's fallback
to the machine's global identity and breaks `git commit` outside Insomnia.

- Pass repoPath into GitVCS.init() for openGitRepoAction so the "native"
  credentials provider can actually read user.name/user.email via
  `git config` in that directory instead of always resolving empty.
- setAuthor() now skips writing config when no author name/email can be
  resolved, instead of writing empty user.name/user.email keys.
2026-08-24 03:27:17 +00:00
Curry Yang 13f94cb3b2 refactor: remote files fetching (#10429)
* refactor: remote files fetching

* update

* update

* fix

* rename
2026-08-24 03:06:23 +00:00
Jay Wu 0ec6861bb4 fix(ui): wrap runner message (#10434) 2026-08-21 10:04:21 +00:00
Bob Qiu 73c4de2357 fix(smoke-test): handle stale overlay click handling in project page interactions (#10415)
* fix: handle stale overlay clicks in project page interactions
2026-08-21 06:21:21 +00:00
Curry Yang 1c0e16c624 fix: prevent overwritting by empty content (#10411) 2026-08-21 11:27:40 +08:00
Pavlos Koutoglou d693ea90a0 fix(git): fix folder naming, relocation, and resurrection bugs for git-synced projects (#10428) 2026-08-20 15:16:27 +02:00
Bingbing 2d6c58eaa8 fix(ui): re-render url bar templates on project environment switch (#10425)
* fix(ui): re-render url bar templates on project environment switch

The request URL bar's remount key only tracked the workspace
environment (activeEnvironment), so switching the project
environment (activeGlobalEnvironment) left stale nunjucks tag
values in the URL bar. The URL preview was unaffected since it
re-renders on any loader revalidation and refetches the render
context fresh from the DB.

* fix(ui): re-render mcp url bar templates on project environment switch

Same issue as the request URL bar: the remount key only tracked
the workspace environment, so switching the project environment
left stale nunjucks tag values.
2026-08-20 08:43:47 +00:00
Curry Yang 62e892f53c fix: change tanstack query option (#10426)
* fix: change tanstack query option

* feat: update db query option
2026-08-20 08:01:32 +00:00
Kent Wang a3d327f930 Fix: Secret type environment input hanging and data update issue (#10420)
* fix secret editor issue
* hide tooltip when change one line editor type
* support re-calculate size after switch editor type
* add one more comment
2026-08-20 07:32:57 +00:00
Kent Wang 2a77e17394 fix: Plugin action no loaded in request/requestGroup context menu when right click (#10416)
* fix plugin action no loaded in context menu issue

* add error handling when failed to get plugin actions
2026-08-20 06:37:06 +00:00
Bob Qiu a6ac92db9a fix(smoke-test): implement graceful close for WebSocket connections (#10417)
* fix(websocket): implement graceful close for WebSocket connections
2026-08-20 05:54:59 +00:00
Jay WuandCopilot Autofix powered by AI 99e9ce74af fix(ui): fix button alignment (#10285)
* fix button alignment

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-20 05:40:15 +00:00
Jay Wu a9eeb1ab63 fix(ui): prevent button label shrunk (#10423)
* fix(ui): prevent button label shrunk

* shorten pre-request
2026-08-20 13:25:57 +08:00
Curry Yang b312759099 refactor: learning feature fetching (#10421) 2026-08-20 12:10:26 +08:00
Curry Yang 575766bce2 refactor: storage fetching (#10409) 2026-08-20 03:08:32 +00:00
Shelby 53c5541423 chore: templating, var and scripting tests (#10275) 2026-08-19 11:45:41 -04:00
Ryan Willis 4bdd37f29b fix: default project selection on import modal (#10414) 2026-08-18 18:07:44 +00:00
Ryan Willis 95c39c730e fix: apply proxy setting to SSE requests (#10413) 2026-08-18 13:49:35 -04:00
Jack Kavanaghandkwburns-kong 7ddf333610 feat(quickjs): insomnia.sendRequest() bridge for the QuickJS script sandbox (#10392)
* wip: sendRequest bridge fixes for QuickJS sandbox — known unresolved crash

Not working yet. insomnia.sendRequest() consistently crashes under the
real Electron/Worker/QuickJS environment with:

  Aborted(Assertion failed: list_empty(&rt->gc_obj_list), at:
  ../../vendor/quickjs/quickjs.c,2036,JS_FreeRuntime)

on the FIRST real network round trip (via the
insomnia-templating-worker-database:// fetch bridge to
network.sendRequestWithoutSideEffects). This never reproduces in vitest
(mocked fetch, or a real Node http server) — only under real Electron
fetch() timing inside the dedicated Worker.

This commit includes three targeted fixes attempted so far, none of
which resolved it on their own or together:

1. insomnia.sendRequest('url string') omitted `headers` entirely; the
   host handler doesn't default it, crashing
   createConfiguredCurlInstance's `headers.find(...)` user-agent lookup.
   This one IS a real, confirmed bug (unit-tested regression added) —
   just not sufficient by itself to fix the crash above.
2. Deferred sendRequestViaFetch by one Promise.resolve().then() tick so
   it doesn't run nested inside the QuickJS C-to-JS callback frame
   (matching host-bridge.ts's installHostBridge pattern for the
   template-tag sandbox).
3. executePendingJobs() returns a DisposableResult that must itself be
   disposed — discarding it leaked a handle. Fixed in both
   installSendRequestBridge and driveTaskToCompletion.
4. Added a disposedRef guard so a late-arriving fetch response after
   vm.dispose() is a safe no-op instead of touching a dead context.

Also includes the smoke test (quickjs-script-sandbox.test.ts) that
reproduces the crash reliably — the second test in that file (worker
UI-responsiveness) passes; the sendRequest round-trip test does not.

Branched off PR 2 (37d19c1da8) per the rollout plan —
https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354 — so
this can be picked up independently without blocking PR 0/PR 1 landing.

Next step for whoever picks this up: bisect further with instrumented
console.error tracing of vm.alive at each step (deferred here, not
committed) to find exactly which call touches vm after disposal — my
three fixes were reasonable hypotheses but didn't close it.

* test: add __sendRequest to the globalThis allowlist after rebase

The merged globalThis-leak test's ALLOWED_EXTRA_GLOBALS predates this
branch's sendRequest bridge landing back on top of develop's rebase target;
without this the merged test fails since __sendRequest is now a real
bridged global.

* fix(quickjs): free bridge promise resolvers before disposing the VM

`vm.newPromise()` allocates three JSValues — the promise plus its `resolve`
and `reject` functions — and quickjs-emscripten frees the two functions only
from inside `resolve()`/`reject()`. `installSendRequestBridge` returned the
promise handle but could skip both (the `disposedRef` guard did exactly that),
so a `sendRequest()` still in flight at teardown left two live function objects
in the runtime and `JS_FreeRuntime` aborted on
`assert(list_empty(&rt->gc_obj_list))` — a native Emscripten abort that takes
down the Worker and the WASM module shared with the template-tag sandbox.

Track every unsettled deferred and dispose it before `vm.dispose()`, which is
the cleanup the library documents for this case. Guard the late-response path
on `vm.alive`/`deferred.alive` instead of a hand-rolled flag.

Also plumb the templating-db auth token from `run-script-quickjs.ts` through
the worker into the engine — it was accepted but never passed, so every bridge
fetch was rejected 401 by the protocol's auth gate.

The crash reproduces in vitest after all: the mocked fetch in the existing
tests settles in the same microtask checkpoint as the call, so the deferred was
always settled before teardown. Settling it on a later macrotask reproduces the
exact production abort, so the smoke test no longer needs `test.fail()`.

* fix(quickjs): return the response value from sendRequestWithoutSideEffects

The handler returned `new Response(JSON.stringify(result))` while every other
handler in `pluginToMainAPI` returns a plain value and lets the caller wrap it.
`resolveDbByKey` does `JSON.stringify(await handler(body))`, so a `Response`
stringified to `"{}"` — the sendRequest bridge received an empty object, and
`response.code` / `response.body` were undefined. The template-tag sandbox's
`network.sendRequestWithoutSideEffects` path was broken the same way.

Also record a second, unrelated `gc_obj_list` abort that the teardown fix does
not address and that predates this branch: allocation-heavy work performed
inside `executePendingJobs()` (anything after the script's first `await`) leaves
live GC objects and aborts at `JS_FreeRuntime`, from ~100k objects up. Reduced
to a reproducer with no bridge, no host functions, no interrupt handler, no
memory limit and no `resolvePromise`; unaffected by every host-side mitigation
tried, and present on both quickjs-emscripten sync variants. Tracked as a
`.fails()` test so it flips red when an engine bump fixes it.

The sendRequest bridge is what makes that latent engine bug routine — it is the
first thing to put multi-megabyte host data into the VM.

Corrects the "later run proves the module survived" comment: a fresh context on
the same WASM module succeeds even after an abort, so that assertion never
detected anything.

* fix(quickjs): address Copilot review feedback on sendRequest bridge

- Normalize request.header (singular, per RequestOptions) as well as
  request.headers, and accept {key, value} header entries alongside
  {name, value}.
- Coerce request.url to a string, since RequestOptions allows a
  Url-like object there and the host handler needs a plain string.
- sendRequestViaFetch no longer unconditionally JSON.parses the
  response body — a non-JSON body (empty response, HTML error page,
  etc.) now surfaces a clear "non-JSON response"/status-based error
  instead of an opaque SyntaxError masking the real failure.
- The callback-style rejection handler no longer assumes err is an
  Error instance (guards on err && err.message).

The authToken concern from the same review round was already fixed by
5ad0278188 on this branch (plumbed from run-script-quickjs.ts through
the worker into the engine) before this commit.

Added unit test coverage for all four fixes.

* fix(quickjs): survive the WASM teardown abort instead of losing the run

Allocating ~100k+ objects after a script's first `await` — which a multi-MB
`insomnia.sendRequest()` response body does on its own — leaves QuickJS's
runtime un-freeable, and `JS_FreeRuntime` aborts the WASM module. The script
has already finished by then and everything we return is plain host-side JS, so
the abort was destroying a run whose result was intact.

Catch it at teardown, warn into the script's logs, and report it through a new
`onEngineFault` callback. Catching inside `finally` means a genuine script error
or timeout still wins. The worker forwards the fault as `engineFaulted` and the
client retires that worker, so no later script runs on a module that aborted.

Retirement is drain-aware: `self.onmessage` doesn't serialize, so a second
script can be mid-execution. The worker leaves rotation immediately but is only
terminated once its in-flight runs settle, and the crash handler now rejects
only its own worker's runs rather than every pending call.

Verified before implementing: the abort is catchable, host-collected data
survives it intact, and the module is still *correct* afterwards — arithmetic,
JSON, string and global operations all check out across repeated runs. Retiring
the worker anyway is defensive, since that only samples the behaviour we
happened to test.

This is containment, not a fix. The underlying defect is in quickjs-emscripten's
WASM build, not in QuickJS: the identical vendored engine source built natively
is clean well past the failing size at every optimization level, with and
without -fwrapv, with CONFIG_STACK_CHECK, and with the same raw-context
intrinsic subset the shim uses — while both WASM engines abort at both
optimization levels. Tracked upstream as
https://github.com/justjake/quickjs-emscripten/issues/269.

* fix(quickjs): close three sendRequest bridge findings (#10404)

* fix(quickjs): reject caller-controlled caCertficatePath/authentication in sendRequestWithoutSideEffects

* fix(quickjs): bound the script sandbox's runtime stack size

Unbounded guest recursion overflowed the host WASM stack before QuickJS's own
depth check could fire, masking the real error behind a fatal gc_obj_list
assertion at vm.dispose(). setMaxStackSize(256KB) lets QuickJS's own check win.

* fix(quickjs): deny multipart/file-upload bodies in the sendRequest bridge

network.sendRequestWithoutSideEffects's cacert/authentication fields are already
pinned regardless of caller input, but its `body` was forwarded unvalidated. A
multipart/form-data body's file parts (body.params[].fileName) reach
buildMultipart, which reads each part's fileName off disk with no ownership/
allowlist check -- unlike every other local-file read reachable from a request
definition. A script reaches this by calling the raw __sendRequest bridge global
directly, bypassing insomnia.sendRequest()'s wrapper, which only ever builds a
text/plain body.

Scoped the fix to the QuickJS bridge itself (assertSupportedSendRequestBody,
run before the bridge's fetch() is dispatched) rather than the shared handler,
since that handler is also used by the legacy hidden-window script sandbox and
the template-tag sandbox, each with its own already-privileged execution model
that should keep working as-is.

Two regression tests: one drives the real QuickJS bridge end-to-end and confirms
the request is now denied before it ever reaches curlRequest; the other drives
the legacy (non-QuickJS) sendRequestWithoutSideEffects implementation directly
and confirms it's unaffected -- the same multipart body still goes through.

---------

Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
2026-08-17 17:50:59 +08:00
Jay WuandVivek Thuravupala afaaec6f8d fix(build): macos latest (#10400)
* Revert "fix: revert electron-builder to previous version to fix macos build (#10394)"

This reverts commit 34c5010a81.

* use macos-15-large

---------

Co-authored-by: Vivek Thuravupala <2700229+godfrzero@users.noreply.github.com>
2026-08-14 06:26:12 -07:00
Jack Kavanaghandkwburns-kong 28e306bb0a PoC: opt-in QuickJS sandbox for pre-request/after-response scripts (#10382)
* 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>
2026-08-14 17:13:45 +08:00