@ai-ecoverse/slicc-bios 1.44.11 → 1.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,9 +42,9 @@ On a shared origin, the BIOS moves SLICC 6 into seven in this browser once, afte
42
42
  - **When it asks:** `/slicc-fs` in OPFS has an entry, `localStorage['slicc-os.six']` isn't `upgraded`, and `/upgrade-to-seven.html` answers within 10 s, without a redirect, and carries `<meta name="slicc-six-upgrade">`. Without the meta (www's fallback answers unknown paths with six's own page) nothing is framed and nobody is asked. One tab asks at a time (Web Lock `slicc-six-upgrade`).
43
43
  - **The question:** *Move SLICC 6 into seven in this browser?*, saying that files move as they are, including any keys or passwords written inside them, and that SLICC 6 and its Chrome extension then stop working in this browser. It's a modal dialog with focus on **Not now**, so Enter and Escape decline; **Not now** leaves both alone and boots seven, and the next boot asks again. There's no setting.
44
44
  - **Moving:** the BIOS frames `/upgrade-to-seven.html` hidden, on the same origin. The page starts on load, stops six's tabs and posts `{ type: 'slicc-six-upgrade', … }` to its parent. The BIOS listens only to messages whose `origin` is its own and whose `source` is that frame. Progress shows under the question: *Stopping SLICC 6 tabs…*, then *Reading files: 120 of 1,240* (`reading` counts the files under `/slicc-fs` it reads) and *Writing the export: 3 of 9* (`writing` counts the entries it writes, `manifest.json` last); two minutes without a message fail the move.
45
- - **Success** (`done: true`, `exportId`, `dir = /slicc-v6-upgrade/<exportId>/`): while the frame still holds six's `slicc-six-kernel` lock, the BIOS sets `slicc-os.six = upgraded` and `slicc-os.six-import = <dir>`, creates the cache `slicc-bios.six-retired`, unregisters every service worker under `/preview/`, and removes every other directory under `/slicc-v6-upgrade/` (interrupted runs). Only then does the frame go, so a six tab opened in between sees the marker and stays down.
45
+ - **Success** (`done: true`, `exportId`, `dir = /slicc-v6-upgrade/<exportId>/`): while the frame still holds six's `slicc-six-kernel` lock, the BIOS sets `slicc-os.six = upgraded` and `slicc-os.six-import = <dir>`, sets the cookie `__Host-slicc-six-retired` (`Path=/`, `Secure`, `SameSite=Strict`), unregisters every service worker under `/preview/`, and removes every other directory under `/slicc-v6-upgrade/` (interrupted runs). Only then does the frame go, so a six tab opened in between sees the marker and stays down.
46
46
  - **Failure** (`error`) removes the frame and sets nothing, so six keeps working. The BIOS shows the error with **Try again** and **Not now**.
47
- - **Retired:** every later BIOS boot opens the cache and unregisters `/preview/` again, and so does every start of `/os/` while the marker is set (`/` no longer reaches the BIOS). The service worker answers a navigation to `/` (whatever its query, so six's extension's `?slicc=leader&ext=…` and `?cherry=1&ui-only=1` too) with a redirect to `/os/` once the cache exists. The extension's leader tab then shows seven; its side panel can't show `/os/` in its frame, so it just stops working. It always passes `/upgrade-to-seven.html` and `/assets/*` to the network on a shared origin, even when OPFS has files there: on www, `/assets/` belongs to SLICC 6 (its exporter's hashed chunks), so seven keeps nothing of its own there, and a kernel process can't plant an exporter page or script for the BIOS to frame.
47
+ - **Retired:** every later BIOS boot sets the cookie and unregisters `/preview/` again, and so does every start of `/os/` while the marker is set (`/` no longer reaches the BIOS). That also renews the cookie, which Chrome keeps for at most 400 days. The service worker answers a navigation to `/` (whatever its query, so six's extension's `?slicc=leader&ext=…` and `?cherry=1&ui-only=1` too) with a redirect to `/os/` once the cookie is set, reading it with `cookieStore` on every such navigation. Only a window can set that cookie: kernel processes run in dedicated workers, which have neither `document.cookie` nor `cookieStore`. The extension's leader tab then shows seven; its side panel can't show `/os/` in its frame, so it just stops working. It always passes `/upgrade-to-seven.html` and `/assets/*` to the network on a shared origin, even when OPFS has files there: on www, `/assets/` belongs to SLICC 6 (its exporter's hashed chunks), so seven keeps nothing of its own there, and a kernel process can't plant an exporter page or script for the BIOS to frame.
48
48
  - **The import:** once the agent runs on `/os/`, `os/six.js` hands `slicc-os.six-import` to it with `control.importProfile({ inPlace })`. The agent moves the files out of `/slicc-fs`, and deletes the directory on success; the key goes then. An import that fails or throws keeps the key and shows a notice, and the next start tries again. A key whose directory has no readable `manifest.json` stays too, with the same notice, and nothing moves; only leftover directories that no key names are ignored. Tabs take turns under the Web Lock `slicc-os.six-import` and read the key again once they hold it.
49
49
 
50
50
  ### Integrity
@@ -332,8 +332,10 @@ Programs ask seven's page for what only a page can do through the kernel's `/dev
332
332
  - **Who answers:** the tab whose session started the process. The owner's `createKernel({ requests })` answers the page's own processes. Each tab's terminals attach with `attachKernel(port, { requests })` on a port the owner made with `connect({ requests: 'attach' })`. The agent's ports carry the owner page's hook (`kernel.connect({ tag, user, requests })`). A remote follower's shell, served by the leader, carries none, so its requests are `ENOTSUP` (`no page answers requests for this session`); they never open in the leader's browser.
333
333
  - **Gestures:** a request from a terminal tag (`{ kind: 'user', where: 'terminal:…' }`) in a tab that has just had a keystroke or click (`navigator.userActivation.isActive`) goes ahead at once. Any other request, the agent's always, waits for seven's own prompt: Cancel, or 60 s without an answer, refuses it with `EACCES`, and a signal or closed request withdraws the prompt. A session (its uid and tags) has at most one prompt up: another request from it meanwhile is refused with `EACCES`, `another request is waiting for you`. After a Cancel or a timeout the session rests for 10 s: its requests are refused with the dismissed text and no prompt, unless they come typed in an active tab. Withdrawing or timing out the prompt gives focus back to what had it.
334
334
  - **`open.url`** (`{"kind":"open.url","url":"…"}`, an empty reply) opens the URL in a new tab with `noopener,noreferrer`; `background` is ignored. Refusals, all `EACCES`, with this first line: `that isn't a URL`; `seven opens only http and https URLs` (`javascript:`, `data:`, `blob:`, `file:` and the rest); `seven doesn't open its own pages or the vault for a program` (the guard's protected origins: seven's own origin, `*.sliccy.ai` and the vault); `the request to open the page was dismissed`; `nobody answered the request to open the page within 60 s`. For example: `printf '{"kind":"open.url","url":"%s"}\n' "$url" | cat > /dev/embedder`.
335
- - **Tool modules** (capture, audio) export the kernel's hook object `{ kinds, handle }`. `plugged(hook, prompts)` wraps one: only kinds seven lists and gives a prompt for reach it, and its `handle` runs only after seven's gesture check, with the request unchanged. A module is a pinned dependency, since it runs as seven.
336
- - Kinds seven doesn't list (`open.file`, `open.download`, `open.reveal`, `clipboard.*`, capture and audio for now) are `ENOTSUP` before the page sees them.
335
+ - **Tool modules** (capture, audio) export the kernel's hook object `{ kinds, handle }`. `plugged(hook, prompts, extra)` wraps one: only kinds seven lists and gives a prompt for reach it, and its `handle` runs only after seven's gesture check, with the request plus seven's `extra`. A module is a pinned, gated dependency in the base set, since it runs as seven.
336
+ - **`capture.screen`** (`screencapture`, `@ai-ecoverse/slicc-capture/page`): the same gesture check as `open.url`, with the prompt "Capture the screen?". The prompt's action is Choose, and Chrome's picker comes next. The module captures only through seven's `request.display(constraints)`, which calls `getDisplayMedia` with `audio: false`, `selfBrowserSurface: 'exclude'`, `surfaceSwitching: 'exclude'` and `preferCurrentTab: false`. When the picked surface's capture handle is seven's or the vault's (`slicc-vault`; every seven page sets `setCaptureHandleConfig({ handle: 'slicc-seven', exposeOrigin: true })` for its own origin, first thing at boot), or its origin is protected, seven stops every track and refuses with `EACCES`, `seven doesn't capture its own pages or the vault`. For a tab, seven waits up to 1 s for a handle that arrives after the capture starts. A tab whose handle is still missing, or any surface Chrome doesn't name as a window or a screen, is refused too (`seven can't tell this tab isn't its own or the vault's (it sets no capture handle), so it doesn't capture it; share a window or the screen`): Chrome hides handles in off-the-record profiles, and an older vault sets none, so a missing handle can't prove the tab is safe. That costs every ordinary tab that sets no capture handle, which is most of them; share a window or the screen to capture one. A captured tab that navigates to a page without a handle is stopped the same way. Seven watches for handle changes from the moment the capture starts, so a change during that wait isn't lost. The same holds while the capture is live: when the captured tab's handle changes to seven's, a protected one or none (`capturehandlechange`), seven stops every track, ends the module's capture and refuses, even if a frame was already taken. A cross-origin navigation clears the handle first, so a tab that navigates to seven is usually refused with the missing-handle text. A window or a whole screen that shows seven, and a protected page that sets no capture handle, are the user's choice in the picker. The vault's top-level pages set `slicc-vault` for seven's production origins (slicc-vault ≥ 1.17.0), so they're refused too. A local seven gets no handle from vault-preview. A page that paints before it sets its capture handle can land in a frame taken in that moment, before seven sees the handle. The dismissed texts are `the request to capture the screen was dismissed` and `nobody answered the request to capture the screen within 60 s`.
337
+ - **`clipboard.write`** (`{"kind":"clipboard.write","type":"image/png"}`, the bytes as the body, an empty reply; `screencapture -c`): `src/seed/clipboard.js` writes one `ClipboardItem` of `image/png`, `text/plain` or `text/html`, with `/dev/clipboard`'s focus rule and refusal text. Other types are `ENOTSUP`. The body is read up to 16 MB; beyond that seven cancels the rest and fails with `EIO`, `seven copies at most 16 MB to the clipboard`.
338
+ - Kinds seven doesn't list (`open.file`, `open.download`, `open.reveal`, `clipboard.read`, and audio for now) are `ENOTSUP` before the page sees them.
337
339
 
338
340
  ## Network
339
341
 
@@ -584,9 +586,9 @@ Limits:
584
586
 
585
587
  ## Certified packages
586
588
 
587
- Seven certifies a gated package (slicc-kernel, slicc-cdp, slicc-clipboard, slicc-jsh, mcpcat, and the `wasi-*`, `wasix-*`, `wasm-*` and `py-*` packages) by its integrity: a version is certified when [`src/packages/certs.json`](src/packages/certs.json) (the historic list, with its recorded `exception`s) or one of the lockfiles seven ships (the base set, `/opt/agent`, Tailscale and the catalog's projects) carries it with that integrity. `src/seed/layer.js`'s `certifiedSet()` reads that union in the page, and a user's or a project's install that needs anything else is refused, except an optional catalog package that passes [the gate](#optional-packages), with the dependencies it pins exactly, so a user's own add of a catalog package passes or fails as the panel's Install does. homescoop's certification exceptions apply to every version there, a `certs.json` or lockfile match included, and when they can't be read the version is refused. A pin on main is certified because it reached main through the merge queue, where every integration test ran on it, and because `pins.test.mjs` checks every gated pin is its own repository's release from main. `test/integration/pins.test.mjs` checks the union covers every gated pin with its integrity (Tailscale's project included), and fails when a pinned package's `engines.slicc-kernel` or kernel peer range isn't met by the pinned kernel.
589
+ Seven certifies a gated package (slicc-kernel, slicc-cdp, slicc-capture, slicc-clipboard, slicc-jsh, mcpcat, and the `wasi-*`, `wasix-*`, `wasm-*` and `py-*` packages) by its integrity: a version is certified when [`src/packages/certs.json`](src/packages/certs.json) (the historic list, with its recorded `exception`s) or one of the lockfiles seven ships (the base set, `/opt/agent`, Tailscale and the catalog's projects) carries it with that integrity. `src/seed/layer.js`'s `certifiedSet()` reads that union in the page, and a user's or a project's install that needs anything else is refused, except an optional catalog package that passes [the gate](#optional-packages), with the dependencies it pins exactly, so a user's own add of a catalog package passes or fails as the panel's Install does. homescoop's certification exceptions apply to every version there, a `certs.json` or lockfile match included, and when they can't be read the version is refused. A pin on main is certified because it reached main through the merge queue, where every integration test ran on it, and because `pins.test.mjs` checks every gated pin is its own repository's release from main. `test/integration/pins.test.mjs` checks the union covers every gated pin with its integrity (Tailscale's project included), and fails when a pinned package's `engines.slicc-kernel` or kernel peer range isn't met by the pinned kernel.
588
590
 
589
- **Provenance** (`pins.test.mjs`, an ordinary integration test): every gated pin in a lockfile seven ships has npm's SLSA provenance for that exact tarball (its subject's sha512 is the lockfile's integrity), built on `refs/heads/main` of its own repository: slicc-kernel, slicc-jsh, slicc-cdp, slicc-clipboard, mcpcat, wasm-tailscale, slicc-cli for wasi-slicc, and homescoop for the other `wasm-*`, `wasi-*`, `wasix-*` and `py-*`. A homescoop pin that the bundled `certification-exceptions.json` withdraws, or whose `requires` the pins don't meet, fails it too. The test names each pin that fails and why.
591
+ **Provenance** (`pins.test.mjs`, an ordinary integration test): every gated pin in a lockfile seven ships has npm's SLSA provenance for that exact tarball (its subject's sha512 is the lockfile's integrity), built on `refs/heads/main` of its own repository: slicc-kernel, slicc-jsh, slicc-cdp, slicc-capture, slicc-clipboard, mcpcat, wasm-tailscale, slicc-cli for wasi-slicc, and homescoop for the other `wasm-*`, `wasi-*`, `wasix-*` and `py-*`. A homescoop pin that the bundled `certification-exceptions.json` withdraws, or whose `requires` the pins don't meet, fails it too. The test names each pin that fails and why.
590
592
 
591
593
  ### Renovate keeps the pins current
592
594
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-bios",
3
- "version": "1.44.11",
3
+ "version": "1.45.0",
4
4
  "description": "Slim loader that boots SLICC into OPFS and serves the UI from there",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -46,7 +46,7 @@
46
46
  "@ai-ecoverse/slicc-browsers": "1.18.14",
47
47
  "@ai-ecoverse/slicc-cdp": "1.41.20",
48
48
  "@ai-ecoverse/slicc-node": "2.5.1",
49
- "@ai-ecoverse/slicc-shared-web": "2.12.3",
49
+ "@ai-ecoverse/slicc-shared-web": "2.12.4",
50
50
  "@ai-ecoverse/slicc-spectrum": "1.104.1",
51
51
  "@ai-ecoverse/slicc-vault": "1.17.0",
52
52
  "@biomejs/biome": "2.5.15",
@@ -7,6 +7,7 @@
7
7
  "name": "slicc-bios-packages",
8
8
  "dependencies": {
9
9
  "@ai-ecoverse/slicc-browsers": "1.18.14",
10
+ "@ai-ecoverse/slicc-capture": "1.3.4",
10
11
  "@ai-ecoverse/slicc-cdp": "1.41.20",
11
12
  "@ai-ecoverse/slicc-clipboard": "1.1.1",
12
13
  "@ai-ecoverse/slicc-kernel": "1.165.1",
@@ -46,6 +47,19 @@
46
47
  "node": ">=24"
47
48
  }
48
49
  },
50
+ "node_modules/@ai-ecoverse/slicc-capture": {
51
+ "version": "1.3.4",
52
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-capture/-/slicc-capture-1.3.4.tgz",
53
+ "integrity": "sha512-CQFMLG2XcoR01oYBjiQrd4JsAmS+entMcamit7/a+Lg2MnnQBZMlfc31Wvjc20RsvtcVtakZIVt1UVBFtovfDQ==",
54
+ "license": "Apache-2.0",
55
+ "bin": {
56
+ "sccapture": "host/sccapture.mjs"
57
+ },
58
+ "engines": {
59
+ "node": ">=24",
60
+ "slicc-kernel": ">=1.153.0"
61
+ }
62
+ },
49
63
  "node_modules/@ai-ecoverse/slicc-cdp": {
50
64
  "version": "1.41.20",
51
65
  "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-cdp/-/slicc-cdp-1.41.20.tgz",
@@ -4,6 +4,7 @@
4
4
  "description": "Packages the BIOS installs from npm into OPFS, pinned by package-lock.json and pnpm-lock.yaml",
5
5
  "dependencies": {
6
6
  "@ai-ecoverse/slicc-browsers": "1.18.14",
7
+ "@ai-ecoverse/slicc-capture": "1.3.4",
7
8
  "@ai-ecoverse/slicc-cdp": "1.41.20",
8
9
  "@ai-ecoverse/slicc-clipboard": "1.1.1",
9
10
  "@ai-ecoverse/slicc-kernel": "1.165.1",
@@ -11,6 +11,9 @@ importers:
11
11
  '@ai-ecoverse/slicc-browsers':
12
12
  specifier: 1.18.14
13
13
  version: 1.18.14
14
+ '@ai-ecoverse/slicc-capture':
15
+ specifier: 1.3.4
16
+ version: 1.3.4
14
17
  '@ai-ecoverse/slicc-cdp':
15
18
  specifier: 1.41.20
16
19
  version: 1.41.20
@@ -102,6 +105,11 @@ packages:
102
105
  resolution: {integrity: sha512-BJAYu1tPJETsQFJEWdCyxWYU5oYaRwMdH1u4sJMvtBLVegkoRrEo5ruEAbIfzx63OJryzTylVYQ8FPVSVomxNA==}
103
106
  engines: {node: '>=24'}
104
107
 
108
+ '@ai-ecoverse/slicc-capture@1.3.4':
109
+ resolution: {integrity: sha512-CQFMLG2XcoR01oYBjiQrd4JsAmS+entMcamit7/a+Lg2MnnQBZMlfc31Wvjc20RsvtcVtakZIVt1UVBFtovfDQ==}
110
+ engines: {node: '>=24', slicc-kernel: '>=1.153.0'}
111
+ hasBin: true
112
+
105
113
  '@ai-ecoverse/slicc-cdp@1.41.20':
106
114
  resolution: {integrity: sha512-gStUfQJD/p9nXDbPWV75hCHqz1AbCGAvESIzAswVB2N/HH3IOHSaXJoN0/0YSSbxcfd4wlCuiOaE61N5Q3aeeQ==}
107
115
  engines: {node: '>=24'}
@@ -217,6 +225,8 @@ snapshots:
217
225
 
218
226
  '@ai-ecoverse/slicc-browsers@1.18.14': {}
219
227
 
228
+ '@ai-ecoverse/slicc-capture@1.3.4': {}
229
+
220
230
  '@ai-ecoverse/slicc-cdp@1.41.20': {}
221
231
 
222
232
  '@ai-ecoverse/slicc-clipboard@1.1.1': {}