Skip to content

Conversation

@rekmarks
Copy link
Member

@rekmarks rekmarks commented Feb 3, 2026

Summary

Adds support for "system vats" - statically declared vats that are launched at kernel initialization and can receive powerful kernel services not available to normal vats. This enables the core application logic of Omnium—currently just the CapletController—to run inside the kernel as a vat.

Key changes

  • KernelFacet: New privileged API for system vats to interact with the kernel (launch subclusters, queue messages, etc.)
  • System vats config: VatConfig extended with name, services, and globals fields for system vat configuration
  • Controller vat: Moved Omnium controllers to a TypeScript controller-vat that runs inside the kernel
    • Deleted dead code in Omnium as a result of this move
  • Globals endowments: Added globals config to allow vats to receive specific globals (like Date) in their SES Compartment
  • callCapletMethod API: Added console API for invoking methods on installed caplets

Note

High Risk
High risk because it changes kernel initialization/run-loop ordering, kernel service invocation semantics (now fire-and-forget with async promise resolution), and adds privileged system-vat launch/config and new endowments into SES compartments.

Overview
Adds system vats: Kernel.make() now accepts systemVats and, after the run queue starts, registers a privileged kernelFacet service and launches configured vats, tracking their bootstrap root krefs for later lookup.

Extends the browser runtime/Omnium wiring to use this: kernel-worker parses a system-vats URL param, the CapTP KernelFacade gains getSystemVatRoot() and reset(), and Omnium now boots a controller-vat system vat (bundle copied into the extension) and routes caplet install/list/get/uninstall calls through it, adding a callCapletMethod console API.

Fixes potential crank deadlocks by making KernelServiceManager.invokeKernelService() non-await (promise-chained resolution) and updating KernelRouter accordingly, and adds VatConfig.globals with a small allowlist (e.g. Date) to endow SES vats. Also tweaks vat bundling to define process.env.NODE_ENV, and updates/tests/docs and the echo caplet ID/output to match the new flow.

Written by Cursor Bugbot for commit 052ebb0. This will update automatically on new commits. Configure here.

rekmarks and others added 8 commits February 3, 2026 12:07
Implement system vats that are launched at kernel initialization and have
access to privileged kernel services. Key changes:

- Add SystemVatConfig type and getSystemVatRoot method to Kernel
- Launch system vats after queue starts to avoid deadlock
- Terminate and relaunch existing system vat subclusters on restart
- Add bootstrap-vat.js for Omnium system services with CapletController
- Add baggage-backed storage adapter for vat persistence
- Pass systemVats config via URL params from offscreen to kernel worker
- Update background.ts to use system vat for caplet operations
- Add process.env.NODE_ENV replacement in vat bundler for SES compatibility
- Simplify kernel-facet.ts by removing SystemVatManager
- Add duplicate name check in KernelServiceManager.registerKernelServiceObject

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Rename bootstrap-vat.js to bootstrap-vat.ts with full type annotations
- Export Baggage type from baggage-adapter.ts
- Make logger optional throughout controller hierarchy
- Simplify defineMethods to take array of method names instead of object map
- Update background.ts to use simplified method names (install, uninstall, etc.)
- Update package.json build script to reference .ts file

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Expose the kernel's reset method via CapTP so it can be called from
the background script.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The vat hosts controllers, which better describes its purpose than
the generic "bootstrap" name.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…cranks

Changed invokeKernelService to not await the service method result. Instead,
it uses Promise chaining to resolve the kernel promise when the method
eventually completes. This allows service methods to internally use
waitForCrank() without causing deadlock - the crank can complete, and the
resolution happens in a future turn of the event loop.

Key changes:
- KernelServiceManager.invokeKernelService() now returns void instead of
  Promise<void> and uses Promise.resolve().then().catch() for async handling
- KernelRouter.#deliverKernelServiceMessage() is now synchronous
- Updated tests to use delay() for microtask flushing

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add a `globals` field to VatConfig that allows specifying which globals
should be available in the vat's SES Compartment. This fixes the
`Date.now()` error when the controller-vat runs under SES lockdown.

VatSupervisor reads the globals list and adds requested globals from an
allowlist to the compartment endowments. Currently only `Date` is allowed.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add `callCapletMethod` to the omnium.caplet API for invoking methods on
installed caplets directly from the console. Simplify the echo caplet ID
from 'com.example.echo' to 'echo' and update the response format.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@rekmarks rekmarks force-pushed the rekm/system-vats-redux branch from f58f8c0 to 079a10a Compare February 3, 2026 20:08
@rekmarks
Copy link
Member Author

rekmarks commented Feb 3, 2026

@cursor review

Remove `initializeControllers` and `makeChromeStorageAdapter` which are
no longer used now that the caplet controller runs inside the vat with
baggage-backed storage instead of chrome.storage.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 86.98%
⬇️ -0.75%
6037 / 6940
🔵 Statements 86.85%
⬇️ -0.75%
6134 / 7062
🔵 Functions 85.46%
⬇️ -0.62%
1558 / 1823
🔵 Branches 83.25%
⬇️ -0.72%
2187 / 2627
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/cli/src/vite/vat-bundler.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
18-58
packages/kernel-browser-runtime/src/types.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/kernel-browser-runtime/src/kernel-worker/kernel-worker.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
26-109
packages/kernel-browser-runtime/src/kernel-worker/captp/kernel-facade.ts 60%
⬇️ -30.00%
0%
⬇️ -100.00%
70%
⬇️ -17.50%
60%
⬇️ -30.00%
43-55
packages/ocap-kernel/src/Kernel.ts 76.28%
⬇️ -14.85%
65.38%
⬇️ -17.95%
83.72%
⬇️ -8.58%
76.28%
⬇️ -14.85%
118-120, 125, 239-242, 249-303, 425, 493, 563
packages/ocap-kernel/src/KernelRouter.ts 90.16%
🟰 ±0%
75.38%
🟰 ±0%
100%
🟰 ±0%
90.16%
🟰 ±0%
110, 163, 175, 225, 252-261, 268, 314, 329, 332
packages/ocap-kernel/src/KernelServiceManager.ts 93.87%
⬇️ -6.13%
88.88%
⬇️ -11.12%
100%
🟰 ±0%
93.87%
⬇️ -6.13%
178-183
packages/ocap-kernel/src/index.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/kernel-facet.ts 90.9% 100% 87.5% 90.9% 172
packages/ocap-kernel/src/types.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/vats/VatSupervisor.ts 72.72%
⬇️ -1.92%
42.42%
⬇️ -2.40%
58.33%
🟰 ±0%
72.72%
⬇️ -1.92%
122, 133, 141, 179, 217-221, 232, 241-242, 263-265, 268, 272-274, 306-308, 325, 342-350
packages/omnium-gatherum/src/background.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
19-270
packages/omnium-gatherum/src/offscreen.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
17-97
packages/omnium-gatherum/src/controllers/base-controller.ts 88.88%
🟰 ±0%
100%
🟰 ±0%
83.33%
🟰 ±0%
88.88%
🟰 ±0%
88
packages/omnium-gatherum/src/controllers/index.ts 100%
⬆️ +100.00%
100%
🟰 ±0%
100%
⬆️ +100.00%
100%
⬆️ +100.00%
packages/omnium-gatherum/src/controllers/caplet/caplet-controller.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/omnium-gatherum/src/controllers/storage/controller-storage.ts 100%
🟰 ±0%
87.5%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/omnium-gatherum/src/controllers/storage/index.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/omnium-gatherum/src/vats/controller-vat.ts 0% 0% 0% 0% 56-148
packages/omnium-gatherum/src/vats/storage/baggage-adapter.ts 100% 100% 100% 100%
Generated in workflow #3545 for commit 052ebb0 by the Vitest Coverage Report Action

rekmarks and others added 2 commits February 3, 2026 12:22
Use proper return type from KernelFacade['queueMessage'] instead of
generic type parameter. Add error handling for missing root kref.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Fix callBootstrap type annotations to use proper return type
- Handle null tombstones in baggage adapter get() method
- Add promise rejection handling to controller-vat bootstrap()

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@rekmarks
Copy link
Member Author

rekmarks commented Feb 3, 2026

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

baggage.init(key, harden(value));
keys.add(key);
saveKeys(keys);
}
Copy link

Choose a reason for hiding this comment

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

Deleted keys not re-added to tracking on set

Medium Severity

The set() method fails to re-add a previously deleted key to the tracking list. When delete() is called, the key is removed from the keys tracking set but remains in baggage as a null tombstone. On subsequent set() calls for that key, baggage.has(key) returns true (due to the tombstone), so the code takes the update branch which doesn't call keys.add(key) or saveKeys(). This results in the value being stored correctly but keys() not returning the key, causing data to be invisible to iteration-based operations.

Fix in Cursor Fix in Web

getSystemVatRoot(name: string): KRef | undefined {
return this.#systemVatRoots.get(name);
}

Copy link

Choose a reason for hiding this comment

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

System vat roots not cleared on kernel reset

Medium Severity

The #systemVatRoots map is never cleared when reset() is called. After reset() terminates all vats (including system vats) and resets the kernel store, the #systemVatRoots map still contains stale krefs referencing terminated vats. Subsequent calls to getSystemVatRoot() return these invalid references, which would cause failures when attempting to use them.

Additional Locations (1)

Fix in Cursor Fix in Web

rekmarks and others added 4 commits February 3, 2026 22:08
Add console forwarding to omnium-gatherum to match the extension implementation. This prevents "Unexpected message" errors in the background script when receiving console-forward messages, and ensures console output from the offscreen document and vat iframes is visible in the background devtools console.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Fix baggage adapter to re-add deleted keys to tracking on set
- Clear system vat roots map on kernel reset

Co-Authored-By: Claude Opus 4.5 <[email protected]>
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.

2 participants