@ai-ecoverse/slicc-bios 1.28.2 → 1.29.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 +18 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,13 +16,23 @@ The page shows six boot steps as they run:
|
|
|
16
16
|
The kernel's root is the OPFS root, so any file a kernel process writes, such as `/home/x.html`, has a URL on seven's origin. The service worker serves only BIOS-managed code as live same-origin content:
|
|
17
17
|
|
|
18
18
|
- `/os/` (the seed: the UI page and its modules and workers), `/node_modules/` (the base set: kernel, spectrum, slicc-cdp and the wasm packages), `/opt/agent/` (the agent and its workers) and `/opt/grammars/`;
|
|
19
|
-
- the aliases `/auth/callback` (→ `/os/callback.html
|
|
20
|
-
- bios's own files (
|
|
19
|
+
- the aliases `/auth/callback` (→ `/os/callback.html`, only on an origin of seven's own) and `/oauth/mcp-callback` (→ the agent's `dist/oauth/mcp-callback.html`), the node builtin stubs under `/__slicc/node/`, and `/os/manifest.json`, a redirect to the BIOS's `manifest.json`, so the manifest's relative icons and `start_url` resolve in the BIOS's folder;
|
|
20
|
+
- bios's own files, in the BIOS's folder (`index.html`, `bios.js`, `bios.css`, `installer.js`, `sw.js`, `manifest.json`, and `sw/`, `seed/`, `packages/` and `icons/`), and `/fonts/`, which always come from the network, even when OPFS has a file of that name.
|
|
21
21
|
|
|
22
22
|
The live content also carries `Content-Security-Policy: frame-ancestors 'self'` and `X-Frame-Options: SAMEORIGIN`, so only seven's own pages can frame it. That leaves no clickjacking and no framed captures of seven by another site. The hosting sends the same headers for the files it serves itself (sliccy-ai#22).
|
|
23
23
|
|
|
24
24
|
Every other OPFS file is served sandboxed: `Content-Security-Policy: sandbox allow-scripts allow-forms allow-popups allow-modals; frame-ancestors 'self'` (without `allow-same-origin`), `X-Content-Type-Options: nosniff`, `Cross-Origin-Resource-Policy: same-origin`, and no COOP or COEP. An HTML page there still renders and runs its scripts, but in an opaque origin, with no access to seven's IndexedDB, `localStorage`, OPFS or keys. JavaScript and TypeScript files there are served as `text/plain` and wasm as `application/octet-stream`, and a request for a script, a worker or a worklet there gets a 403, so none of seven's pages can import, run or instantiate them. Bare imports are resolved only in the live paths. Kernel symlinks live in the kernel's metadata, not in OPFS, so the service worker never follows one. The kernel itself reads binaries from OPFS directly, not through the service worker.
|
|
25
25
|
|
|
26
|
+
### Next to SLICC 6 (`www.sliccy.ai/7`)
|
|
27
|
+
|
|
28
|
+
Seven can share its origin with another app: on `www.sliccy.ai` the BIOS is `/7/` and SLICC 6 keeps the rest of the origin, the first step of the in-place upgrade from six (#648; the routes are sliccy-ai#51).
|
|
29
|
+
|
|
30
|
+
- **The BIOS's folder** is the folder of `sw.js`. On `seven.sliccy.ai` and the previews it's the origin's root, as before. The BIOS always registers `sw.js` at scope `/`, so the UI is `/os/` wherever the BIOS lives; outside the root that needs `Service-Worker-Allowed: /` on `sw.js`.
|
|
31
|
+
- **Pages find the BIOS** through `os/site.js`: the folder of the service worker that controls them (`navigator.serviceWorker.controller.scriptURL`), or the origin's root when none does. The deployed lockfiles (`packages/…`), `certs.json`, the installer worker and every Reload that goes through the BIOS use it. `home()` is the BIOS without its trailing slash, and the base of follow (`#follow=`) and guest seat (`#seat=`) links.
|
|
32
|
+
- **The other app's routes stay its own.** A request for a path with no OPFS file goes to the network, so six's page, its scripts and its relay at `/auth/callback`, which isn't aliased there, still load. An OPFS file is still served sandboxed, and a script request for one still gets a 403. The UI links `manifest.json`, which the service worker redirects to the BIOS's folder, so six's `/manifest.json` stays six's.
|
|
33
|
+
- **Production:** `www.sliccy.ai` is production like `seven.sliccy.ai` (`PRODUCTION_HOSTS` in `os/site.js`), for kernel users and the vault.
|
|
34
|
+
- **Sign-in** goes through six's relay page itself (see Adobe sign-in), and **the tray hub** through the BIOS's folder (see Remote devices).
|
|
35
|
+
|
|
26
36
|
### Integrity
|
|
27
37
|
|
|
28
38
|
A kernel process can still write to `/os/` and `/node_modules/` (any process while the kernel's users are off, root after that). So the service worker checks what it serves from there against the hashes the BIOS recorded, never against bytes on disk:
|
|
@@ -54,9 +64,10 @@ A kernel process can still write to `/os/` and `/node_modules/` (any process whi
|
|
|
54
64
|
- **Freezer:** every conversation in the session database (slicc-agent ≥ 3.23.0, spectrum ≥ 1.39.0). Live cones show **Open**. A cone deleted with **Delete cone** in Agents (which asks first), an earlier chat left by New chat, or a stopped scoop or agent run stays there with its title, model, kind and message count. **Thaw** brings it back as a cone, and the row then says what it was thawed as. **Remove**, which asks first, deletes its working folders; the conversation stays in the database.
|
|
55
65
|
- **Settings:** the theme, the model, thinking, diffs, and the Bedrock and Adobe accounts. Below Accounts, **MCP servers** lists each server in `~/.pi/agent/mcp.json` whose headers use a `${NAME}` placeholder, and **Connect** takes its token (slicc-agent ≥ 3.33.0, spectrum ≥ 1.50.0). A server without an `Authorization` header that answers 401 needs an OAuth sign-in: its row reads *Needs sign-in* with **Sign in**, or *Sign-in expired* (slicc-agent ≥ 3.36.0, spectrum ≥ 1.54.0), which opens a pop-up on the server's authorization server. The agent registers `https://<origin>/oauth/mcp-callback` as its redirect URI, and the service worker serves that path from the agent's `dist/oauth/mcp-callback.html` in `/opt/agent`, which hands the code back over `BroadcastChannel('slicc-mcp-oauth')`, clears its address and closes. Tool cards label MCP calls `server · tool`. The agent's `models` command lists the models of the connected accounts and switches the caller's model (slicc-agent ≥ 3.34.0).
|
|
56
66
|
- **Keeping seven's files:** at the first chat send in a page session, `os/storage.js` calls `navigator.storage.persist()`, unless storage is already persisted. If Chrome declines, every chat panel shows a warning notice (`model.notices`, spectrum ≥ 1.43.0, from `os/notices.js`): *Seven’s files may be cleared*, saying Chrome may clear seven's files and chats when disk space runs low. Chrome grants persistence by engagement, not by a setting, and installing seven as an app is the reliable way. So when Chrome offers to install (`beforeinstallprompt`), the notice says to install seven as an app and offers **Install**, which opens Chrome's install prompt. Otherwise it says to bookmark seven. **Try again** asks again. After `appinstalled`, seven asks by itself and drops the notice once storage is kept. Dismissing the notice is remembered in `localStorage`. The folder-mount request (see [Folder mounts](#folder-mounts)) stays as it is.
|
|
57
|
-
- **Installing as an app:** [`src/manifest.json`](src/manifest.json) makes seven installable. Its name is *SLICC seven* and its launcher label *seven*. It opens standalone, its `id
|
|
67
|
+
- **Installing as an app:** [`src/manifest.json`](src/manifest.json) makes seven installable. Its name is *SLICC seven* and its launcher label *seven*. It opens standalone, its `id` and `scope` are `/` and its `start_url` is the BIOS's folder (`./`), and its icons in `src/icons/` come as `any` and `maskable`, relative to the manifest. The UI links `manifest.json`, which the service worker redirects to the BIOS's. The app starts at the BIOS, which checks the packages and goes on to `os/` as in a tab, so the service worker, COOP/COEP and the boot path are the same. Both pages link the manifest and set `theme-color` (`#f8f8f8` light, `#1b1b1b` dark); `os.css` gives `html` the same background, so nothing flashes before the UI paints. Each `<branch>.sliccy.ai` is its own origin, so a preview installs as an app of its own.
|
|
58
68
|
- **Adobe sign-in:** **Connect** on the Adobe account signs in to Adobe IMS. IMS only redirects to `www.sliccy.ai/auth/callback`, and seven is cross-origin isolated, so the popup has no opener to report back to. Which path seven uses depends on where it runs:
|
|
59
69
|
- **On `https://<label>.sliccy.ai`:** seven asks the relay for its own origin (state `{ source: 'origin', origin, nonce }`). The relay navigates the popup to `<origin>/auth/callback`. The service worker serves that page from `os/callback.html`, which hands the redirect to the tab over the same-origin `BroadcastChannel('slicc-sign-in')`, clears the token from its address and closes. Neither slicc-node nor the extension is needed.
|
|
70
|
+
- **On `https://www.sliccy.ai`,** where seven shares the origin with the relay page (see [Next to SLICC 6](#next-to-slicc-6-wwwsliccyai7)): seven asks the relay for its `opener` delivery (state `{ source: 'opener', nonce }`). The relay page then posts the redirect to every tab of the origin over `BroadcastChannel('slicc-oauth-relay')`, which seven listens on.
|
|
60
71
|
- **Elsewhere, with slicc-extension installed:** the extension signs in with `chrome.identity`.
|
|
61
72
|
- **Elsewhere, through slicc-node:** seven registers a nonce with `POST /api/oauth-state`, sends IMS to the relay's `local` source, and polls `GET /api/oauth-result` once a second.
|
|
62
73
|
|
|
@@ -68,7 +79,7 @@ Each screen class has its own layout, kept in `localStorage` (`slicc-os.layout.<
|
|
|
68
79
|
|
|
69
80
|
The kernel runs with users on (slicc-kernel ≥ 1.81.0): files have owners and modes, agents run as their own users, and `sudo` asks the human.
|
|
70
81
|
|
|
71
|
-
- **The mode:** production seven (`seven.sliccy.ai`) always runs `'enforce'` (`PRODUCTION_USERS` in `os/users.js`). A URL or `localStorage` asking for another mode is ignored there, with a console warning, so nobody can switch seven off from a link. On previews, localhost and in tests the default is `'enforce'` too, and `#users=off`, `#users=report` or `#users=enforce` picks another, remembered in `localStorage['slicc-os.users']`. `'report'` checks every file call and logs what `'enforce'` would refuse, and refuses nothing. `sudo` asks only under `'enforce'`. bios passes the mode to every kernel it creates, `'off'` included, since kernels from K4b on default to `'enforce'`. `<html data-users>` says which mode is on.
|
|
82
|
+
- **The mode:** production seven (`seven.sliccy.ai` and `www.sliccy.ai`) always runs `'enforce'` (`PRODUCTION_USERS` in `os/users.js`). A URL or `localStorage` asking for another mode is ignored there, with a console warning, so nobody can switch seven off from a link. On previews, localhost and in tests the default is `'enforce'` too, and `#users=off`, `#users=report` or `#users=enforce` picks another, remembered in `localStorage['slicc-os.users']`. `'report'` checks every file call and logs what `'enforce'` would refuse, and refuses nothing. `sudo` asks only under `'enforce'`. bios passes the mode to every kernel it creates, `'off'` included, since kernels from K4b on default to `'enforce'`. `<html data-users>` says which mode is on.
|
|
72
83
|
- **Who is who:** the human's panel terminals are root (`/root`, mode 0700). With users on, bios adds the first cone, `cone`, at every boot: in `sudo`, home `0710`, umask `077`. The agent adds further cones and scoops through its `KernelSource`. The file tree skips `~/.local/share/pnpm` and `~/.cache` of every home in `/etc/passwd`.
|
|
73
84
|
- **Folders** bios mounts (picked in the Files panel, remembered, or linked) belong to the first cone, so the agent can write them, and to root while users are off.
|
|
74
85
|
- **Files from before users:** agents start on the new layout; nothing is moved. On the first boot with users on, bios runs `chmod -R go-rwx` as root, once, on what earlier versions left readable to everyone: `/home/.pi`, `/home/.slicc`, `/home/sprinkles`, `/home/.gelatiere`, `/home/.welcomed`, `/home/.welcome.json`, `/home/sessions`, `/home/.local` and `/scoops`. So no cone or scoop reads an old `mcp.json` with its tokens, and root still reads everything. The marker `var/lib/slicc/legacy-locked` keeps it from running again; cone and scoop homes and other files in `/home` aren't touched.
|
|
@@ -246,7 +257,7 @@ Packages are served unbundled, exactly as npm publishes them, so `pnpm upgrade <
|
|
|
246
257
|
## Vault
|
|
247
258
|
|
|
248
259
|
Seven keeps its secrets in the vault, a separate origin (`@ai-ecoverse/slicc-vault`, types only in `devDependencies`; its README's "The embedding API" is the spec). `src/seed/vault.js` brokers it:
|
|
249
|
-
- **The origin** comes from `vaultOrigin()`: production seven (`https://seven.sliccy.ai`) always uses `https://vault.sliccy.ai` and refuses an override with a console error; every other seven uses `https://vault-preview.sliccy.ai`, or the origin in `localStorage['slicc-os.vault-origin']`, which the tests point at a fake vault.
|
|
260
|
+
- **The origin** comes from `vaultOrigin()`: production seven (`https://seven.sliccy.ai` and `https://www.sliccy.ai`) always uses `https://vault.sliccy.ai` and refuses an override with a console error; every other seven uses `https://vault-preview.sliccy.ai`, or the origin in `localStorage['slicc-os.vault-origin']`, which the tests point at a fake vault.
|
|
250
261
|
- **The core frame** is a hidden iframe at that origin. After each `load` (so again after the frame reloads) seven posts the page hello `{ type: 'slicc-vault', v: 1, op: 'hello', role: 'page', sudoGid }`, with the kernel's `sudo` gid from `kernel.groups.list()` (left out under users `off`; the owner tab keeps it in `localStorage['slicc-os.vault-sudo-gid']` for the other tabs), and talks to the vault over that page port only.
|
|
251
262
|
- **`model.vault`** (spectrum's `VaultPort`) gives Settings › Secrets, the value requests and the composer's hold synchronous `status()` and `list()` snapshots (re-listed after every `changed`), `audit`, `availability()` (`connecting` until the welcome, `waiting` without one within 5 s or while an answer is 2 s late, then `locked` or `ready`), and the page ops `put` (with spectrum's `PutOptions` passed through), `cancel`, `remove`, `restore`, `import`, `export`, `lock` and `dismissBackupReminder`. Rejections are `Error`s with the vault's errno as `code`. Values go only through `put` (and `seal`), are never logged, stored or put into an error message, and never reach the agent worker.
|
|
252
263
|
- **`button()`** is a plain iframe of `<vault origin>/button.html`, with no `sandbox`, so it can open the vault's popup. Every `button` message carries seven's current colour scheme as `theme`, and is sent again on the frame's `load` and whenever the scheme changes; spectrum (≥ 1.68.3) gives the iframe the same `color-scheme`, so Chrome doesn't paint it opaque.
|
|
@@ -374,7 +385,7 @@ seven can also join a tailnet, with a patched build of Tailscale's wasm client (
|
|
|
374
385
|
- **Errors:** a destination the CLI refuses under its policy comes back as an unreachable record with `EACCES`, and a send the OS fails with its code. A connected socket's next send or receive fails with it; an unconnected socket is told nothing, as on Linux. ICMP unreachable comes back only from a CLI on Linux.
|
|
375
386
|
- **The Tailscale exit** carries UDP too, with one wasm-tailscale `dial('udp', …)` per destination (at most 256 per socket, the oldest closed first), so tailnet addresses and, with an exit node, public ones.
|
|
376
387
|
- **Network panel:** `status().links.devices` lists the linked devices (name, `<host>.slicc.internal`, address, mode, what they offer, the CLI's policy summary, whether they can be the exit, and their state), `status().exit` is the current choice, and `unlink(id)` drops a device. On `*.sliccy.ai` the panel also has the join URL, `rotateJoinUrl` and `retryLinks`.
|
|
377
|
-
- **Remote devices (the tray hub):** on `*.sliccy.ai`, `os/tray.js` makes seven a **tray leader** on SLICC's tray hub (`slicc-tray-hub`), through the sliccy-ai worker's same-origin proxy for `POST /tray`, `/controller/<token>` and the leader WebSocket, which drops cookies. The hub mints the join URL on `www.sliccy.ai`, and the panel shows `npx sliccy@next <join-url> follow` (`@next` until `sliccy`'s `latest` is the new CLI; `latest` is still six's). Followers then link the same way as a local CLI: seven offers, and the offer, answer and candidates go over the hub's bootstrap messages. TURN comes from the hub.
|
|
388
|
+
- **Remote devices (the tray hub):** on `*.sliccy.ai`, `os/tray.js` makes seven a **tray leader** on SLICC's tray hub (`slicc-tray-hub`), through the sliccy-ai worker's same-origin proxy for `POST /tray`, `/controller/<token>` and the leader WebSocket, which drops cookies. On `www.sliccy.ai` those routes are under the BIOS's folder (`/7/tray`, `/7/controller/<token>`, …), which the worker proxies without the prefix, and seven puts the folder in front of the controller and WebSocket URLs the hub mints. The hub mints the join URL on `www.sliccy.ai`, and the panel shows `npx sliccy@next <join-url> follow` (`@next` until `sliccy`'s `latest` is the new CLI; `latest` is still six's). Followers then link the same way as a local CLI: seven offers, and the offer, answer and candidates go over the hub's bootstrap messages. TURN comes from the hub.
|
|
378
389
|
- **Who may link:** only followers with runtime `slicc-link/1` or `slicc-seven/1` and full trust, and guests on a seat (see Guests below), which never become devices. A device **is its DTLS certificate**: its id is the SHA-256 fingerprint in its answer. The CLI keeps one certificate per hub and mints a new `controllerId` for every connection, which is only a routing id. A device that reconnects replaces its old link and gets its address back, and a new certificate is a new device. Known devices (name, label, address, what they offer) are kept in `localStorage` (`slicc-os.devices`), keyed by fingerprint, so a device that's away shows as reconnecting. The exit choice is keyed the same way.
|
|
379
390
|
- **Unlink:** a connected device is told `OPEN { kind: 'unlink' }` and forgets its join URL and identity. Its fingerprint is refused from then on: an answer that carries it fails the bootstrap with `UNLINKED`. Running the join command again mints a new certificate, so it links as a new device.
|
|
380
391
|
- **New join URL:** seven leads a new tray, tells every connected device that supports it the new URL (`OPEN { kind: 'join', url }`), and only then stops leading the old one, so a leaked URL stops working. A device that was away has to be linked again.
|
|
@@ -554,7 +565,7 @@ Every shard runs the files with a failing test once more and passes when they pa
|
|
|
554
565
|
|
|
555
566
|
## Hosting
|
|
556
567
|
|
|
557
|
-
`main` is live at <https://seven.sliccy.ai/>, and every other branch at `https://<branch>.sliccy.ai/`, where the branch name is lowercased and runs of anything but letters and digits become `-` (`feat/edge-hosting` → <https://feat-edge-hosting.sliccy.ai/>). Each host is its own origin, so a branch gets its own OPFS and service worker and can't disturb `seven`.
|
|
568
|
+
`main` is live at <https://seven.sliccy.ai/>, and every other branch at `https://<branch>.sliccy.ai/`, where the branch name is lowercased and runs of anything but letters and digits become `-` (`feat/edge-hosting` → <https://feat-edge-hosting.sliccy.ai/>). Each host is its own origin, so a branch gets its own OPFS and service worker and can't disturb `seven`. `https://www.sliccy.ai/7/` serves the same `seven/` next to SLICC 6 (sliccy-ai#51, see [Next to SLICC 6](#next-to-slicc-6-wwwsliccyai7)).
|
|
558
569
|
|
|
559
570
|
The hosts are served by the [sliccy-ai](https://github.com/ai-ecoverse/sliccy-ai) worker from the R2 bucket `slicc-bios`. This repo only publishes into that bucket:
|
|
560
571
|
|