Skip to content

feat(templating): vetted npm libraries in the sandbox — uuid + ajv (M3) - #10244

Merged
jackkav merged 4 commits into
developfrom
claude/sandbox-pr7-vetted-libs
Jul 16, 2026
Merged

feat(templating): vetted npm libraries in the sandbox — uuid + ajv (M3)#10244
jackkav merged 4 commits into
developfrom
claude/sandbox-pr7-vetted-libs

Conversation

@jackkav

@jackkav jackkav commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

PR 7 of the sandbox plan (https://gist.github.com/jackkav/4bbf717954a18a6753b64f33ab678ad4) — ticket M3, batch 1. Stacked on #10242 (PR 6); only the last commit is new.

What

Makes real, vetted npm libraries available inside the QuickJS sandbox as require()-able registry modules — bundled once, pinned, and granted like any other module.

  • scripts/generate-sandbox-vendored.ts (npm run generate:sandbox-vendored -w insomnia): esbuild-bundles each vetted lib (platform=browser, target=es2020) into a CJS factory-source string, written to src/templating/sandbox/vendored/<name>.generated.ts with its pinned version. Checked in (reviewable, deterministic).
  • uuid + ajv shipped. Both verified running end-to-end in QuickJS: uuid generates/validates v4s (its browser build uses crypto.getRandomValues, provided by M2); ajv compiles a schema and validates payloads (its logger uses the bootstrap console).
  • Grant-filtered registry: buildModuleRegistrySource(grantedModules) includes a heavy lib's bundle only when the plugin declared it, so a render that doesn't use ajv never parses its ~247KB.
  • lodash deferred — it isn't a dependency and adds bulk; add in a later batch when a plugin needs it.

User-verifiable value

A community plugin with a real npm dependency (schema validation via ajv, ids via uuid) works under the sandbox once it declares the module — the first PR where a non-trivial plugin can run fully sandboxed.

Tests

  • vendored-libs.test.ts (6): uuid.v4() shape + validate/version round-trip, ajv compile + validate two payloads (compiled-validator state), heavy-lib-registered-only-when-granted, and a version-pin drift guard (the recorded version must equal the installed dependency — a dep bump without regenerating fails it).
  • E2E: a plugin declaring uuid renders uuid=ok; one declaring ajv renders valid,invalid; a plugin that requires ajv without declaring it is denied "Module 'ajv' not permitted by manifest" (registry presence ≠ grant).
  • Repo-wide npm run lint && npm run type-check && npm test — clean.

Notes for review

  • vendored/ajv.generated.ts is a ~247KB checked-in bundle (few lines, one big string) — a deliberate vendored artifact, regenerable via the script, parsed at runtime only when a plugin grants ajv.
  • "Add a vetted lib" checklist lives in the generator's header comment.
  • The canary (test 1) is borderline against the 20s local per-test cap when the full suite runs (test 5 now parses the ajv bundle); it passes standalone and CI uses a 60s cap. Flagging it as a future split candidate — not introduced here.

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

✅ Circular References Report

Generated at: 2026-07-16T04:01:00.488Z
Status: ✅ NO CHANGE

Summary

Metric Base (develop) PR Change
Total Circular References 9 9 0 (0.00%)
Click to view all circular references in PR (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx
Click to view all circular references in base branch (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx

Analysis

No Change: This PR does not introduce or remove any circular references.


This report was generated automatically by comparing against the develop branch.

@jackkav
jackkav force-pushed the claude/sandbox-pr6-profiles branch from 91aabf8 to 00274d8 Compare July 14, 2026 16:36
@jackkav
jackkav force-pushed the claude/sandbox-pr7-vetted-libs branch from 8284704 to f0da42a Compare July 14, 2026 16:43
Base automatically changed from claude/sandbox-pr6-profiles to develop July 14, 2026 16:45
@jackkav
jackkav marked this pull request as ready for review July 14, 2026 17:51
Copilot AI review requested due to automatic review settings July 14, 2026 17:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for shipping vetted npm libraries into the QuickJS template-tag sandbox as grant-gated registry modules, plus a generator + tests/docs to keep the vendored bundles deterministic and pinned.

Changes:

  • Introduces “heavy” sandbox modules (uuid, ajv) and generates vendored factory bundles via generate:sandbox-vendored, registering them only when granted.
  • Adds per-surface profiles (template-tag vs scripting) to enforce capability ceilings while keeping module gating at the registry/require layer.
  • Adds unit + smoke coverage and user-facing permissions documentation/migration warning behavior.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/insomnia/src/templating/sandbox/vendored/uuid.generated.ts Adds generated, pinned uuid bundle factory source for sandbox registration.
packages/insomnia/src/templating/sandbox/vendored-libs.test.ts Unit tests for vendored libs (runtime smoke in QuickJS + version drift guard).
packages/insomnia/src/templating/sandbox/surface-profiles.ts Adds surface profiles and grant resolution helpers (capability ceiling enforcement).
packages/insomnia/src/templating/sandbox/surface-profiles.test.ts Tests profile invariants and grant resolution rules.
packages/insomnia/src/templating/sandbox/plugin-tag-sandbox.ts Builds module registry source per-run based on granted modules; enriches denial errors.
packages/insomnia/src/templating/sandbox/plugin-tag-sandbox.test.ts Updates tests to use surface profiles and adjusts capability-shape assertions.
packages/insomnia/src/templating/sandbox/PERMISSIONS.md Documents insomnia.permissions modules/capabilities and new vendored libs + migration notes.
packages/insomnia/src/templating/sandbox/module-registry.ts Adds heavy vendored module definitions, version pins, and buildModuleRegistrySource.
packages/insomnia/src/templating/sandbox/in-sandbox-bootstrap.ts Adds structured error metadata (code, moduleName) for module denials.
packages/insomnia/src/main/templating-worker-database.ts Adds manifest-less migration toast logic and routes grants through surface profiles.
packages/insomnia/src/main/tests/templating-worker-database.test.ts Tests migration warning deduping and non-warning cases.
packages/insomnia/scripts/generate-sandbox-vendored.ts New esbuild-based generator for checked-in vendored factory sources.
packages/insomnia/package.json Adds generate:sandbox-vendored script.
packages/insomnia-smoke-test/tests/smoke/sandbox-template-tags.test.ts Adds E2E coverage for profile ceilings, migration warning, and vendored libs.
packages/insomnia-smoke-test/fixtures/sandbox-vendored-collection.yaml New smoke-test fixture for vendored-lib tags.
packages/insomnia-smoke-test/fixtures/sandbox-profile-collection.yaml New smoke-test fixture for profile/migration tests.
examples/insomnia-plugin-sandbox-demo/README.md Updates demo docs for capability ceiling + migration warning behavior.
examples/insomnia-plugin-sandbox-demo/package.json Adds uuid to demo plugin’s declared module permissions.
examples/insomnia-plugin-sandbox-demo/index.js Adds a demo template tag that uses the vendored uuid module.
Comments suppressed due to low confidence (1)

packages/insomnia/src/templating/sandbox/module-registry.ts:142

  • This comment says surface profiles will intersect module grants with a ceiling, but the current template-tag module resolution intentionally does not enforce a resolve-time ceiling (the registry + __require are the gate). The comment should be updated to match the new behavior to avoid future confusion.
/**
 * The floor of module access every template-tag plugin receives, even with no manifest. Surface
 * profiles (P1) will intersect the resolved grant with a ceiling; for now the effective grant is
 * simply `baseline ∪ manifest.modules` (see `resolveTemplateTagModules`).
 */

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/insomnia/scripts/generate-sandbox-vendored.ts Outdated
Comment thread packages/insomnia/scripts/generate-sandbox-vendored.ts
@jackkav
jackkav force-pushed the claude/sandbox-pr7-vetted-libs branch from f0da42a to 5a2dd5a Compare July 14, 2026 18:25
Comment thread packages/insomnia/scripts/sandbox-vendored-lib.ts
Comment thread packages/insomnia/scripts/sandbox-vendored-lib.ts
kwburns-kong
kwburns-kong previously approved these changes Jul 14, 2026
Comment thread packages/insomnia/scripts/sandbox-vendored-lib.ts
@jackkav
jackkav enabled auto-merge (squash) July 15, 2026 05:27
@jackkav
jackkav force-pushed the claude/sandbox-pr7-vetted-libs branch 2 times, most recently from a74c5a6 to 1ae3bde Compare July 15, 2026 22:04
kwburns-kong
kwburns-kong previously approved these changes Jul 15, 2026

@kwburns-kong kwburns-kong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No notes on the changes. Given the size/eval of the bundle thats paid per render, perhaps we use minify? #10264

ajv
size (from 251,504 to 117,163 bytes) 53% smaller
eval median (from 14.25ms to 10.46ms) 1.36x improvement

uuid
size (from 32,218 to 14,855 bytes) 54% smaller
eval median (from 1.84ms to 1.34ms) 1.37x improvement

jackkav and others added 4 commits July 16, 2026 05:54
Real npm libraries, bundled once and pinned, made available inside the QuickJS
sandbox as require()-able registry modules (granted like any other module).

- scripts/generate-sandbox-vendored.ts: esbuild-bundles each vetted lib
  (platform=browser, target=es2020) into a CJS factory-source string, written
  to src/templating/sandbox/vendored/<name>.generated.ts with its pinned
  version. npm run generate:sandbox-vendored -w insomnia.
- module-registry: uuid + ajv entries (heavy: true). buildModuleRegistrySource
  now includes a heavy lib only when the plugin's grant names it, so a render
  that doesn't use it never parses its (25KB/247KB) bundle.
- uuid picks its browser build (crypto.getRandomValues, provided by M2); ajv's
  logger uses the bootstrap console. Both verified running end-to-end in QuickJS.
- lodash deferred (not a dep; add in a later batch when a plugin needs it).

Tests: vendored-libs.test.ts (uuid v4 + validate round-trip, ajv compile/validate,
grant-filtered registration, version-pin drift guard vs installed dep). E2E: a
plugin declaring uuid/ajv runs the lib; ajv-in-registry-but-undeclared is denied
(registry presence ≠ grant). Docs: PERMISSIONS.md + generator checklist; demo
declares uuid + vendoredprobe tag.
* fix(templating): isolate sandbox-vendored ajv/uuid from the app's own dependencies

The sandbox previously bundled ajv/uuid from the app's ambient node_modules,
so a routine app dependency bump could silently drift the sandbox's vetted
versions with no way to distinguish an intentional upgrade from tampering.

Give the sandbox its own exact-pinned install, isolated from npm workspace
hoisting, with a guardrail ensuring its pin never exceeds the app's resolved
version, a one-command upgrade path with chain-of-custody verification, and
CI checks that catch staleness or hand-edits to the generated bundles.

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

* chore(ci): harden ci

* dep(uuid): bump uuid 9.0.1 to 11.1.1

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
The snapshot ids asserted throughout vcs.test.ts are sha1 hashes of the
backend project id, which comes from generateId('prj') -> uuid.v4(). The
shared setup mock (setup-vitest.ts) that replaces uuid.v4 with a fixed
pool is declared *after* a top-level `await` that loads the cross-package
insomnia-data graph, so in CI that mock is applied non-deterministically:
when it misses, generateId returns a real random uuid, every asserted hash
changes, and the file fails — which is why the same commit passed on one
Test run and failed on another (the failing runs' backend project ids are
real uuids absent from the mock array; the passing runs' are from it).

Pin generateId deterministically at its in-package module boundary with a
test-file-local vi.mock of insomnia's own ~/common/misc (the reliable mock
pattern, unaffected by the setup mock's cross-package race), backed by a
private counter over the same id array (now exported). generateId('prj')
is the only uuid consumer these tests exercise, so drawing the array in
order reproduces the exact sequence the assertions were recorded against.
@jackkav
jackkav force-pushed the claude/sandbox-pr7-vetted-libs branch from 8d264fc to c008fbd Compare July 16, 2026 03:54
@jackkav
jackkav merged commit 3842690 into develop Jul 16, 2026
27 of 28 checks passed
@jackkav
jackkav deleted the claude/sandbox-pr7-vetted-libs branch July 16, 2026 09:53
arora-r added a commit that referenced this pull request Aug 10, 2026
* fix: large responses now download correctly

* fix: linting

* chore: add e2e testing to prevent future regressions

* fix: cloud sync test flaky (#10238)

* fix: cloud sync test flaky

* fix

* fix args to be more concrete

* Feat/basic components m0 (#10230)

* refactor: components infra

* fix

* fix: data-* class

* rename cn to cls

* chore: emit and upload junit test results per shard (#10253)

* chore: emit junit reports per e2e tests shard

* chore: include retries in junit reporter

* chore: test some stuff

* chore: test again

* chore: revert test

* fix(import): always show collection picker (#10262)

* feat(undo): broaden undo-history persistence via a stable historyKey (#10233)

* feat: add a tooltip for show/hide secret on auth tab (#10263)

* feat(templating): vetted npm libraries in the sandbox — uuid + ajv (M3) (#10244)

* fix: stop reusing blank-row ids in key-value editors [INS-2598] (#10260)

* fix: ensure unique blank IDs for environment key-value pairs to prevent stale state

* test: add validation for blank row behavior after deleting committed rows in environment table editor

* fix: restore visible keyboard focus indicators across the app (#10268)

* feat: enhance focus-visible styles for input elements

* feat: simplify focus-visible styles for form elements

* update test

* fix: route v3 spaces SDK through proxy-aware fetch (#10265)

* feat: show error when fails download

---------

Co-authored-by: Curry Yang <163384738+CurryYangxx@users.noreply.github.com>
Co-authored-by: Fares Osman <43153226+fiosman@users.noreply.github.com>
Co-authored-by: Ryan Willis <ryan.willis@konghq.com>
Co-authored-by: Jack Kavanagh <jackkav@gmail.com>
Co-authored-by: Shelby <13246465+shelby-moore@users.noreply.github.com>
Co-authored-by: Pavlos Koutoglou <pkoutoglou@gmail.com>
Co-authored-by: Alison Sabuwala <alison.sabuwala1024@gmail.com>
cwangsmv pushed a commit that referenced this pull request Aug 11, 2026
* fix: large responses now download correctly

* fix: linting

* chore: add e2e testing to prevent future regressions

* fix: cloud sync test flaky (#10238)

* fix: cloud sync test flaky

* fix

* fix args to be more concrete

* Feat/basic components m0 (#10230)

* refactor: components infra

* fix

* fix: data-* class

* rename cn to cls

* chore: emit and upload junit test results per shard (#10253)

* chore: emit junit reports per e2e tests shard

* chore: include retries in junit reporter

* chore: test some stuff

* chore: test again

* chore: revert test

* fix(import): always show collection picker (#10262)

* feat(undo): broaden undo-history persistence via a stable historyKey (#10233)

* feat: add a tooltip for show/hide secret on auth tab (#10263)

* feat(templating): vetted npm libraries in the sandbox — uuid + ajv (M3) (#10244)

* fix: stop reusing blank-row ids in key-value editors [INS-2598] (#10260)

* fix: ensure unique blank IDs for environment key-value pairs to prevent stale state

* test: add validation for blank row behavior after deleting committed rows in environment table editor

* fix: restore visible keyboard focus indicators across the app (#10268)

* feat: enhance focus-visible styles for input elements

* feat: simplify focus-visible styles for form elements

* update test

* fix: route v3 spaces SDK through proxy-aware fetch (#10265)

* feat: show error when fails download

---------

Co-authored-by: Curry Yang <163384738+CurryYangxx@users.noreply.github.com>
Co-authored-by: Fares Osman <43153226+fiosman@users.noreply.github.com>
Co-authored-by: Ryan Willis <ryan.willis@konghq.com>
Co-authored-by: Jack Kavanagh <jackkav@gmail.com>
Co-authored-by: Shelby <13246465+shelby-moore@users.noreply.github.com>
Co-authored-by: Pavlos Koutoglou <pkoutoglou@gmail.com>
Co-authored-by: Alison Sabuwala <alison.sabuwala1024@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants