@ai-ecoverse/slicc 1.39.2 → 1.40.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 +60 -9
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`slicc` is SLICC's command line for seven, the SLICC on `*.sliccy.ai`. It is one binary for macOS, Windows and Linux. It launches and links browsers, and shares a machine's network, compute and browsers with a running seven over a WebRTC link. `npx sliccy` and Sliccstart.app run this binary. It replaces slicc-node and slicc-swift (see [Coming from slicc-node](#coming-from-slicc-node)).
|
|
4
4
|
|
|
5
|
-
**Status:** being built. `slicc` (the default flow), `slicc attach` (with the `cdp` capability), `slicc open`, `slicc pair` and `slicc unpair` (seven in your everyday browser, without CDP), `slicc <join-url> follow`, remote control with `prompt`, `watch` and `abort
|
|
5
|
+
**Status:** being built. `slicc` (the default flow), `slicc attach` (with the `cdp` capability), `slicc open`, `slicc pair` and `slicc unpair` (seven in your everyday browser, without CDP), `slicc <join-url> follow`, remote control with `prompt`, `watch` and `abort` (also from inside seven's kernel, see [Inside seven](#inside-seven)), host folders with `--mount`, `slicc browsers`, `slicc launch`, `update`, `install`, `--version` and `--help` work so far, plus a hidden diagnostic, `slicc <join-url> follow --signal-only [--timeout 2m]`. It attaches through the tray hub, prints a summary of the leader's offer (its size, media sections, candidate count and DTLS fingerprint) and the ICE server URLs (credentials are never printed), and exits without answering. The link protocol is drafted alongside seven's link exit and moves into this README once both sides pass a shared test.
|
|
6
6
|
|
|
7
7
|
## Commands (planned)
|
|
8
8
|
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
| `slicc launch` | launch a browser with CDP in a separate SLICC profile and print its CDP URL |
|
|
16
16
|
| `slicc <join-url> follow [--exit] [--runner …] [--cdp <url>] [--mount <path>]` | follow a seven's tray from another machine and offer its network, compute (over SSH), browsers or folders (`--exit`, `--runner`, `--cdp` and `--mount` work now; see [Remote setup](#remote-setup-slicc-join-url-follow)) |
|
|
17
17
|
| `slicc <join-url> prompt <text>`, `watch`, `abort` | send a prompt to seven's agent and stream its answer, follow the agent as it works, or abort its run; `--cdp <url>` instead of a join URL links locally (works now; see [Remote control](#remote-control-slicc-prompt-watch-and-abort)) |
|
|
18
|
+
| `slicc <join-url> prompt`, `watch`, `abort` inside seven | the same commands from seven's kernel, as `@ai-ecoverse/wasi-slicc` (works now; see [Inside seven](#inside-seven)) |
|
|
18
19
|
| `slicc browsers --json` | list running CDP endpoints and installed browsers, ranked |
|
|
19
20
|
| `slicc update [--check]` | replace this binary with the latest release (works now; see [Updates](#updates)) |
|
|
20
21
|
| `slicc install jerk` | install slicc-jerk into slicc's data folder (works now; see [Companion tools](#companion-tools)) |
|
|
@@ -34,7 +35,7 @@ curl -fsSL https://github.com/ai-ecoverse/slicc-cli/releases/latest/download/ins
|
|
|
34
35
|
The alternatives:
|
|
35
36
|
|
|
36
37
|
- **npm:** `npm install -g @ai-ecoverse/slicc`, or `npx @ai-ecoverse/slicc`. The package is a small Node launcher; npm picks one of the platform packages `@ai-ecoverse/slicc-<os>-<arch>` (`darwin`, `linux`, `windows` × `amd64`, `arm64`) through `optionalDependencies` and their `os` and `cpu` fields. The launcher runs that binary with the same arguments, stdio and environment plus `SLICC_LAUNCHER=npm`, forwards `SIGTERM`, `SIGHUP`, `SIGQUIT` and `SIGUSR2` to it, and `SIGINT` too when stdin is not a terminal (a terminal's Ctrl-C already reaches the binary; on Windows the console delivers Ctrl-C and Ctrl-Break to both). It exits with the binary's exit code, or dies of the same signal. An install with `--omit=optional` has no binary, and the launcher says so. slicc-jerk comes the same way; fnox doesn't (see [Companion tools](#companion-tools)).
|
|
37
|
-
- **GitHub releases:** every release of `ai-ecoverse/slicc-cli` carries `slicc-<os>-<arch>` (`.exe` on Windows) for all six targets, plus `install.sh` and `SHA256SUMS` (which lists `install.sh` too). See [Verifying a download](#verifying-a-download).
|
|
38
|
+
- **GitHub releases:** every release of `ai-ecoverse/slicc-cli` carries `slicc-<os>-<arch>` (`.exe` on Windows) for all six targets, `slicc-wasip1-wasm.wasm` for seven's kernel (see [Inside seven](#inside-seven)), plus `install.sh` and `SHA256SUMS` (which lists `install.sh` and the `.wasm` too). See [Verifying a download](#verifying-a-download).
|
|
38
39
|
- **Go:** `go install github.com/ai-ecoverse/slicc-cli/cmd/slicc@latest`. See [Install with Go](#install-with-go).
|
|
39
40
|
|
|
40
41
|
### Install with curl
|
|
@@ -298,6 +299,7 @@ Release builds (a plain `X.Y.Z` version, linked in or, for `go install`, from th
|
|
|
298
299
|
| `SLICC_DISCOVERY` | test-only: limits browser discovery, see [Development](#development) |
|
|
299
300
|
| `SLICC_OPEN_COMMAND` | test-only: `slicc open` runs this program with the pairing URL as its only argument instead of opening the default browser; the integration tests always set it |
|
|
300
301
|
| `SLICC_LOOPBACK_PORTS` | test-only: `<first>-<last>`, the port range of the [loopback listener](#linking-seven-in-your-everyday-browser) instead of 17117-17126 |
|
|
302
|
+
| `SLICC_LINK_URL` | inside seven only: the link facade's address, `tcp://127.0.0.1:<port>` (see [Inside seven](#inside-seven)) |
|
|
301
303
|
| `SLICC_USER_DATA_DIR`, `XDG_STATE_HOME` | read, as SLICC six reads them, only to find six's Chrome profile (see [Using SLICC six's Chrome profile](#using-slicc-sixs-chrome-profile)) |
|
|
302
304
|
|
|
303
305
|
## The default: `slicc`
|
|
@@ -760,7 +762,12 @@ Only browsers the user named are listed: the one seven runs in, `--cdp` and `--c
|
|
|
760
762
|
- **Refused**, with `{"id":…,"sessionId"?:…,"error":{"code":-32000,"message":"slicc: refused: target is on seven's origin"}}`, never forwarded: `Target.createTarget`, `Page.navigate` and anything else whose `url` is protected; `Page.navigateToHistoryEntry` to an entry whose URL is protected (the node looks it up with `Page.getNavigationHistory`); `Target.attachToTarget`, `activateTarget`, `closeTarget`, `autoAttachRelated`, `Browser.getWindowForTarget` and any other command whose `targetId` or `frameId` is a protected target; and every command on a session whose target is protected, or became so. `Target.getTargetInfo` and `Target.detachFromTarget` stay allowed.
|
|
761
763
|
- **Origins and storage.** A command whose `origin`, `securityOrigin`, `ownerOrigin`, `issuerOrigin`, `topLevelOrigin`, `topLevelSite`, `embeddedOrigin`, `requestingOrigin`, `scopeURL` or `manifestId` is protected, or whose `storageKey` or `cacheId` names seven's storage, is refused the same way. This covers `Storage.*`, `IndexedDB.*`, `CacheStorage.*`, `DOMStorage.*`, `FileSystem.*`, `ServiceWorker.*`, `PWA.*`, `Browser.setPermission` and `Browser.grantPermissions`. Free-form values (`expression`, `arguments`, `value`, `headers`, `postData` and the like) aren't searched.
|
|
762
764
|
- **Cookies.** `Network.getCookies`, `Network.getAllCookies`, `Storage.getCookies` and `Page.getCookies` answer without the cookies whose domain is protected (`sliccy.ai` and every subdomain, and each extra origin's host and its parents: cookies ignore ports), and without partitioned cookies whose `partitionKey.topLevelSite` is such a site. `Network.setCookie`, `setCookies`, `deleteCookies`, `Storage.setCookies` and `Page.deleteCookie` for such a domain, a URL on such a host, or a partition key under such a site, are refused with `slicc: refused: cookies on seven's origin`. So are `Network.clearBrowserCookies` and `Storage.clearCookies`, except in a browser context this stream created with `Target.createBrowserContext`.
|
|
763
|
-
- **Requests a page makes to seven.** For a request whose URL is protected, `Network.*` and `Fetch.*` events lose their `Cookie` and `Set-Cookie` headers, their raw header texts and their cookie lists, and `requestWillBeSentExtraInfo` drops seven's cookies from `associatedCookies` for any request. Chrome can send `requestWillBeSentExtraInfo` and `responseReceivedExtraInfo` before the event that names the request's URL, so the node holds them until the request is found to be protected, gets its response, finishes or fails (a WebSocket or WebTransport once it is created); one still held after 2 seconds is passed on stripped, as for a protected request. For a WebSocket, WebTransport or EventSource on a protected origin (`ws:` and `wss:` count as `http:` and `https:`), `webSocketWillSendHandshakeRequest`, `webSocketHandshakeResponseReceived`, `webSocketFrameError`, `eventSourceMessageReceived` and `dataReceived` are dropped. Reading such a request's body (`Network.getResponseBody`, `Fetch.getResponseBody`, `takeResponseBody…AsStream`, `Audits.getEncodedResponse` and the like) is refused. The node also checks the answer, because the page may ask before the node has seen the request. When `Network.getResponseBody`, `searchInResponseBody`, `streamResourceContent`, `getResponseBodyForInterception`, `takeResponseBodyForInterceptionAsStream`, `getRequestPostData`, `Fetch.getResponseBody`, `Fetch.takeResponseBodyAsStream` or `Audits.getEncodedResponse` answers, the node holds the answer until the request has a response (for `getRequestPostData`, until it is sent; for an intercepted request, until it is paused). If the request is protected by then, the answer is refused, and a stream it handed out is closed. If the node still hasn't seen the request after 2 seconds, the answer is refused with `slicc: refused: slicc hasn't seen this request, so it could be seven's`. `Network.replayXHR` is refused with that message too, unless the node has already seen the request; for a protected request it is refused like the body getters. `IO.read` is refused, with `slicc: refused: slicc didn't hand out this stream, so it could be seven's`, unless the node passed that handle to the page in an allowed answer (`take…AsStream`, `Page.printToPDF`, `Network.loadNetworkResource`, or `IO.resolveBlob` as `blob:<uuid>`).
|
|
765
|
+
- **Requests a page makes to seven.** For a request whose URL is protected, `Network.*` and `Fetch.*` events lose their `Cookie` and `Set-Cookie` headers, their raw header texts and their cookie lists, and `requestWillBeSentExtraInfo` drops seven's cookies from `associatedCookies` for any request. Chrome can send `requestWillBeSentExtraInfo` and `responseReceivedExtraInfo` before the event that names the request's URL, so the node holds them until the request is found to be protected, gets its response, finishes or fails (a WebSocket or WebTransport once it is created); one still held after 2 seconds is passed on stripped, as for a protected request. For a WebSocket, WebTransport or EventSource on a protected origin (`ws:` and `wss:` count as `http:` and `https:`), `webSocketWillSendHandshakeRequest`, `webSocketHandshakeResponseReceived`, `webSocketFrameError`, `eventSourceMessageReceived` and `dataReceived` are dropped. Reading such a request's body (`Network.getResponseBody`, `Fetch.getResponseBody`, `takeResponseBody…AsStream`, `Audits.getEncodedResponse` and the like) is refused. The node also checks the answer, because the page may ask before the node has seen the request. When `Network.getResponseBody`, `searchInResponseBody`, `streamResourceContent`, `getResponseBodyForInterception`, `takeResponseBodyForInterceptionAsStream`, `getRequestPostData`, `Fetch.getResponseBody`, `Fetch.takeResponseBodyAsStream` or `Audits.getEncodedResponse` answers, the node holds the answer until the request has a response (for `getRequestPostData`, until it is sent; for an intercepted request, until it is paused). If the request is protected by then, the answer is refused, and a stream it handed out is closed. If the node still hasn't seen the request after 2 seconds, the answer is refused with `slicc: refused: slicc hasn't seen this request, so it could be seven's`. `Network.replayXHR` is refused with that message too, unless the node has already seen the request; for a protected request it is refused like the body getters. `IO.read` is refused, with `slicc: refused: slicc didn't hand out this stream, so it could be seven's`, unless the node passed that handle to the page in an allowed answer (`take…AsStream`, `Page.printToPDF`, `Network.loadNetworkResource`, or `IO.resolveBlob` as `blob:<uuid>`). - **Paused requests to seven.** A page session's own interception never gets to touch a request whose URL is protected, whatever its kind (a document, `fetch()`, XHR, an image or any other subresource), at either stage. The node keeps `Fetch.requestPaused`, `Fetch.authRequired` and the deprecated `Network.requestIntercepted` for such a request from the page and settles it itself:
|
|
766
|
+
- a document request is failed (`Fetch.failRequest` with `BlockedByClient`, or `Network.continueInterceptedRequest` with `errorReason: BlockedByClient`);
|
|
767
|
+
- any other request continues untouched (`Fetch.continueRequest`, or `Network.continueInterceptedRequest` with only its `interceptionId`);
|
|
768
|
+
- an auth challenge gets the browser's own handling (`Fetch.continueWithAuth`, or `Network.continueInterceptedRequest`, with `authChallengeResponse: {"response": "Default"}`).
|
|
769
|
+
|
|
770
|
+
`Fetch.continueRequest`, `continueResponse`, `failRequest`, `fulfillRequest`, `continueWithAuth` and `Network.continueInterceptedRequest` are refused with `slicc: refused: slicc didn't pass this paused request to the page, so it could be seven's` for any `requestId` or `interceptionId` the node hasn't passed to that session in a paused event. So a guessed id can't fulfil, change or fail a protected request, even one that is still paused. The node remembers the last 16 384 ids it passed on; an id older than that is refused too.
|
|
764
771
|
- **Browser-wide commands**, refused with their own reason after `slicc: refused: `: `Target.exposeDevToolsProtocol` (it would give a page the whole browser) and `Target.sendMessageToTarget` (attach with `flatten: true` instead), on any target; `Fetch.enable` on the browser itself (a page session is fine); `Tracing.start`; `Extensions.loadUnpacked`; and `Browser.setPermission`, `Browser.grantPermissions` without an `origin` and `Browser.resetPermissions`, except in a browser context this stream created.
|
|
765
772
|
- **Auto-attach.** With `Target.setAutoAttach`, a session to a protected target is detached by the node at once (`Target.detachFromTarget` on its parent session), and the page never sees its `attachedToTarget` or `detachedFromTarget`.
|
|
766
773
|
- **Navigation by other means.** A script's `location = …`, a link, `window.open` or a server redirect isn't a command the node can refuse, so the node guards the network instead.
|
|
@@ -771,7 +778,7 @@ Only browsers the user named are listed: the one seven runs in, `--cdp` and `--c
|
|
|
771
778
|
- Page commands on a touched target's session wait until the node's own session there is ready. That takes at most 10 s; after that, or when the node's session can't be set up or is lost, they are refused with `slicc: refused: slicc can't keep seven's origin out of this target`.
|
|
772
779
|
- In touched targets, service workers are bypassed for every request, not only for protected ones.
|
|
773
780
|
- The guard covers every frame that shares the touched target's process. A cross-site iframe's navigation pauses in its parent's target, before the iframe becomes a target of its own, with the frame's id as `frameId` (the id the iframe target gets later). A popup's request pauses in the popup's target, with its `targetId` as `frameId`. A redirect into a protected origin pauses again at the request stage, with `redirectedRequestId`, even when the first URL didn't match.
|
|
774
|
-
- The page's own `Fetch.enable` on a page session still works. Chrome chains the interceptors of a target's sessions, the most recently enabled first, so the page's interceptor could see a protected document's request before the node's does, or after the node failed it, at the response stage. The node fails such a
|
|
781
|
+
- The page's own `Fetch.enable` on a page session still works. Chrome chains the interceptors of a target's sessions, the most recently enabled first, so the page's interceptor could see a protected document's request before the node's does, or after the node failed it, at the response stage. The node fails such a request itself, and the page never sees it (see *Paused requests to seven* above).
|
|
775
782
|
- When a target commits a protected origin all the same (see the limits below), the node sees it arrive (`Target.targetInfoChanged`) only after the browser committed it. A request the node failed also leaves the target on the protected URL, showing the error page. Either way the node detaches every page session on the target, drops their events and results, and refuses further commands on them; the page gets `Target.detachedFromTarget`.
|
|
776
783
|
- **Auto-attach of targets without a URL.** A cross-site iframe can attach before its URL is known (`url: ""`, which stays empty while it waits for the debugger), and so can a `window.open` popup. So when an auto-attached session (one that doesn't answer the page's own `Target.attachToTarget`) is to a page or iframe target with an empty URL, the node holds it:
|
|
777
784
|
- The page doesn't get its `attachedToTarget` yet, its events are dropped, and page commands on it are refused.
|
|
@@ -1153,6 +1160,40 @@ Summaries are one line of at most 200 characters. Escape sequences and control c
|
|
|
1153
1160
|
- **Limits:** `summary` is at most 200 characters. Credentials and tool output beyond the summary are never sent.
|
|
1154
1161
|
- **Unknown events:** the node ignores events and fields it doesn't know.
|
|
1155
1162
|
|
|
1163
|
+
## Inside seven
|
|
1164
|
+
|
|
1165
|
+
`slicc` also runs inside seven's kernel, so that one seven's agent or user can prompt, watch and abort another seven's agent. That build is `slicc.wasm`, slicc-cli's client commands compiled with `GOOS=wasip1 GOARCH=wasm` and `CGO_ENABLED=0`, and it ships as the npm package `@ai-ecoverse/wasi-slicc`, at slicc-cli's own version. seven's page holds the WebRTC link; slicc only reaches the page's link facade.
|
|
1166
|
+
|
|
1167
|
+
```
|
|
1168
|
+
slicc <join-url> prompt [--steer | --reject] [--thinking] [--json] [--plain] <text>|@file|-
|
|
1169
|
+
slicc <join-url> watch [--thinking] [--json] [--plain]
|
|
1170
|
+
slicc <join-url> abort
|
|
1171
|
+
slicc --version
|
|
1172
|
+
slicc --help
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
- **Commands:** `prompt`, `watch` and `abort` with a join URL behave as in [Remote control](#remote-control-slicc-prompt-watch-and-abort): the same flags, output, styling, `--json` events, resuming and exit codes, from the same code. The differences:
|
|
1176
|
+
- **Ctrl-C** ends slicc with 130 (the kernel's default for `SIGINT`), `watch` included, and a running prompt goes on in the other seven. `--abort-on-interrupt` isn't offered.
|
|
1177
|
+
- **Exit 3** covers the facade's own refusals too. When the facade gives a message (`unlock the vault to continue`, or the other seven's refusal), slicc prints it instead of the Linked devices hint.
|
|
1178
|
+
- **A terminal** is a standard stream that is a character device. Styling then follows `TERM`, `NO_COLOR` and `--plain` as usual.
|
|
1179
|
+
- **Everything else** exits 2 with `slicc: <command> isn't available inside seven`: `follow`, `attach`, `open`, `browsers`, the default flow, `update`, `install`, and `prompt`, `watch` or `abort` without a join URL. `--help` lists only what works there.
|
|
1180
|
+
- **What the build leaves out** (build constraints): pion and the link, CDP, SSH, mounts, the kernel listener, the policy, browser discovery, telemetry and updates.
|
|
1181
|
+
|
|
1182
|
+
**The link facade.** slicc reads its address from `SLICC_LINK_URL` only, as `tcp://127.0.0.1:<port>` on the kernel's loopback (any `127.x` address, or `localhost`). Without it, or with another shape, slicc exits 1. Each `agent` stream (see [`agent`](#agent-page-cap-agent-node--page)) is one connection, carrying records of a `u8` type, a `u32` big-endian length and the payload, both ways:
|
|
1183
|
+
- **`1`, control:** JSON, at most 64 KiB.
|
|
1184
|
+
- slicc's first record is `{ "v": 1, "join": "<join-url>", "open": { "kind": "agent", "op": … } }`, where `open` is the stream's OPEN, `length` for long prompts included. The join URL goes only there, never in an address, a log or an error.
|
|
1185
|
+
- The page answers `{ "opened": { … } }` (the OPENED) or `{ "reset": "ERRNO: message" }`. A `reset` may also come later, as the stream's RESET.
|
|
1186
|
+
- Without an answer within 1 minute, slicc gives up: `seven's link facade didn't answer within 1m0s`, exit 1 (`watch` reconnects).
|
|
1187
|
+
- **`2`, data:** the stream's DATA: a long prompt's bytes up, and NDJSON events down. slicc sends records of at most 64 KiB, and takes records of up to 16 MiB; record boundaries carry no meaning.
|
|
1188
|
+
- **`3`, end:** that side's END. slicc closes the connection after both ends or a reset.
|
|
1189
|
+
- **Errors:** an unknown type, a control record over 64 KiB, any record over 16 MiB, a control record that isn't JSON, or a later control record that isn't a `reset` makes slicc send `{ "reset": "EPROTO" }` and fail the stream. `ENOTCONN` (the tray can't be reached) fails `prompt` and `abort` with exit 1; `watch` says `lost the link to seven; reconnecting` and retries with its usual backoff, as it does when a connection drops.
|
|
1190
|
+
|
|
1191
|
+
**The host module.** Go on `wasip1` can't open sockets, so the package's `host/slicc-host.mjs` gives `slicc.wasm` the `slicc_host` imports, on the kernel's loopback sockets (the calls the JS program API's `net.connect` uses): `probe`, `connect(host, port)` (loopback only, non-blocking), `connected(fd, timeout)`, `read(fd, buffer, timeout)`, `write(fd, buffer, timeout)` (non-blocking) and `close(fd)`. Connects, reads and writes wait at most 100 ms at a time, so signals, timeouts and a reset that arrives while a long prompt uploads get through. Without the module, slicc exits 1 with `this runtime has no slicc_host module`.
|
|
1192
|
+
|
|
1193
|
+
**The package.** `@ai-ecoverse/wasi-slicc` holds `bin/slicc.wasm`, `host/slicc-host.mjs`, this section as its README, and the LICENSE. Its `package.json` has `"slicc": { "abi": "wasi", "commands": { "slicc": { "wasm": "bin/slicc.wasm", "imports": "host/slicc-host.mjs" } } }` and `engines.slicc-kernel`. The release attaches `slicc.wasm` as `slicc-wasip1-wasm.wasm`, in `SHA256SUMS` and its attestation (see [Releases](#releases)).
|
|
1194
|
+
|
|
1195
|
+
**Tests.** `test/integration/wasi_test.go` builds `slicc.wasm`, stages the package with `npm-stage.mjs --wasi-only`, and runs it in `@ai-ecoverse/slicc-kernel`'s Node kernel (an exact-pinned devDependency, so `npm ci` first) against a fake facade, a kernel JS program in `testdata/wasi/fakefacade/`. `cmd/slicc` builds for both: a file there that needs a native-only package carries `//go:build !wasip1`, and `wasi_test.go` fails when the `wasip1` build breaks or links one of the left-out packages.
|
|
1196
|
+
|
|
1156
1197
|
## Tray hub signaling (remote setup)
|
|
1157
1198
|
|
|
1158
1199
|
A node on another machine sets up its link through the tray hub, the `slicc-tray-hub` worker on `www.sliccy.ai`. seven is the tray leader and the node is a follower. The wire contract is six's `packages/shared-ts/src/tray-signaling.ts`. The node only signals over it and never speaks six's tray-sync messages.
|
|
@@ -1173,7 +1214,7 @@ A node on another machine sets up its link through the tray hub, the `slicc-tray
|
|
|
1173
1214
|
|
|
1174
1215
|
## Development
|
|
1175
1216
|
|
|
1176
|
-
Go 1.26 and Node ≥ 24 (for the lint tools). `npm run build` writes `bin/slicc`. `npm run lint` runs the slicc lint tools, `gofmt`, `go mod tidy -diff`, `go vet` and golangci-lint. `npm test` runs the integration tests in `test/integration/`, which build the binary and drive it
|
|
1217
|
+
Go 1.26 and Node ≥ 24 (for the lint tools). `npm run build` writes `bin/slicc`. `npm run lint` runs the slicc lint tools, `gofmt`, `go mod tidy -diff`, `go vet` and golangci-lint. `npm test` runs the integration tests in `test/integration/`, which build the binary and drive it; run `npm ci` first, since the [Inside seven](#inside-seven) tests need the pinned `@ai-ecoverse/slicc-kernel`. Unit tests stay next to the code and out of git (`npm run test:unit`). `go build` and `npm run build` link no version, so these binaries report `dev`. `npm run dist` cross-builds all six targets into `artifacts/release/` with `SHA256SUMS`, unsigned. `npm run npm:stage` then stages the npm packages into `dist/npm/`, and `npm run npm:check` packs them with `npm publish --dry-run`.
|
|
1177
1218
|
|
|
1178
1219
|
**Test names: `--hosts <file>`** (test-only, left out of `--help`). `slicc attach`, `slicc open`, `slicc pair` and `slicc <join-url> follow` take a hosts file, so tests get deterministic names without public DNS. Each line is `<ip> <name> [<name>…]`, and `#` starts a comment. Names match case-insensitively, with or without a trailing dot, and a name on several lines gets every address, in file order. Wherever the node resolves a name (`resolve`, `tcp` by name, `http`, and the policy's [browser endpoints](#network-policy)), a name in the file gets the file's addresses of the requested family, possibly none, and never the system resolver's. Other names go to the system resolver. The policy applies afterwards as usual: `resolve` drops refused addresses, and a dial to a refused address is `EACCES`. `tcp` and `http` try the addresses in file order. A file that can't be read or parsed exits 2. A name mapped to a loopback address only helps the node's own dials, `http` and `tcp` by name: a seven kernel that gets a loopback address from `resolve` dials its own loopback, because loopback never goes out through an exit. For end-to-end exit tests, map test names to a non-loopback address of the machine.
|
|
1179
1220
|
|
|
@@ -1190,6 +1231,16 @@ In the same process, probe ports, dirs and a process list passed in explicitly (
|
|
|
1190
1231
|
|
|
1191
1232
|
**Port guard.** On CI (`CI` set), or with `SLICC_TEST_PORT_GUARD=1`, `TestMain` holds `127.0.0.1:9222` to `9229` (and `[::1]` where it can) for the whole run, and the run fails if anything connects to them, other than the one test that lends a port to its own fake browser. On CI a port it can't hold fails the run. Off CI it is off by default, so a developer's own Chrome on those ports is never touched; the guarded tests then skip.
|
|
1192
1233
|
|
|
1234
|
+
**Protected-origin vectors.** `test/integration/testdata/link/protect.js` exports `protectVectors`, the attacks the relay must stop, in a shape other guards reuse: `{ id, setup, trigger, control: { origin: 'ordinary', expected }, expected }`. Each runs three times, through the relay, against the same server under three names: an ordinary origin (`ordinary.test`, the control, which must succeed), seven (an `--origin`) and the vault (`vault.sliccy.ai`). A run passes when its observations match `control.expected` or `expected`, and a vector whose control fails fails as a whole. The only run left out is the vault in the same-site iframe cases, since no unprotected page is same-site with a `sliccy.ai` host. The observations come from the test server's log of requests and of the beacons an injected init script sends, and from what the page's own CDP session saw. The cases:
|
|
1235
|
+
- C1, an init script, then `location.href`;
|
|
1236
|
+
- C2, redirect chains through allowed hops (301, 302, 303, 307, 308, and a POST form through 307 and 308), and a chain that passes through the protected origin and back out;
|
|
1237
|
+
- C3, an instrumented popup that navigates itself, and a popup opened on a redirect chain;
|
|
1238
|
+
- C4, static and script-inserted iframes, same-site and cross-site to the page;
|
|
1239
|
+
- C5, the page's own `Fetch.enable` on every request at both stages: a document, `fetch()`, XHR, an image, an auth challenge, and fulfilling guessed request ids;
|
|
1240
|
+
- C6, cookie reads, writes and clears, and storage commands that name the origin or its storage key.
|
|
1241
|
+
|
|
1242
|
+
Chrome 156 no longer has `Network.setRequestInterception`, so the deprecated `Network.requestIntercepted` path is tested against a fake browser instead.
|
|
1243
|
+
|
|
1193
1244
|
**Real browsers in tests.** The Chrome the harness starts itself is `SLICC_TEST_CHROME` (test-only: the path of a Chrome executable), else the machine's Chrome or Chromium, with the real environment, a temporary profile and `--use-mock-keychain --password-store=basic`. The tests that have `slicc` itself launch a real Chrome run it under a temporary home, where its profiles are throwaway ones. Off CI they never launch the machine's own Chrome: they need `SLICC_TEST_CHROME` set to a Chrome for Testing inside its `.app`, which they link into the temporary home's `Applications` folder on macOS and launch by its id (`chrome-for-testing`), and they skip with a notice without it, or on other systems. On CI they launch the runner's Google Chrome. An older Chrome for Testing can fail the tests that read Chrome's own prefs.
|
|
1194
1245
|
|
|
1195
1246
|
On GitHub's Windows runners the system drive `C:` is slow: with Chrome profiles there, Chrome sometimes waited seconds before a new tab's first request (up to past the 15 s page-load limit) or before exiting (`did not exit`). With them on `D:`, the runner's temp drive, those stalls weren't seen and the suite ran about a quarter faster. So CI points `TEMP` and `TMP` at the runner's temp dir, and the tests' temporary homes and Chrome profiles live there. When a test page doesn't load, the failure says where it stopped: the tab's URL and `readyState`, the resources it fetched, and every request the page server saw.
|
|
@@ -1200,9 +1251,9 @@ The real-Chrome tests in `test/integration/` launch headless, so they run the ex
|
|
|
1200
1251
|
|
|
1201
1252
|
semantic-release cuts releases from `main` in `.github/workflows/release.yml`, on a macOS runner:
|
|
1202
1253
|
1. `scripts/release-plan.mjs` asks semantic-release (dry run) for the next version, and stops when there is none.
|
|
1203
|
-
2. `scripts/package.sh <version>` builds `darwin`, `linux` and `windows` × `amd64`, `arm64` with `CGO_ENABLED=0`, `-trimpath` and `-X main.version=<version
|
|
1204
|
-
3. `scripts/npm-stage.mjs` stages `@ai-ecoverse/slicc` and the six platform packages into `dist/npm/`. It also stages the same launcher as `sliccy` (with two bins, `sliccy` and `slicc`, and a short preview README) into `dist/npm-next/`, as version `7.0.0-next.<version>`, with exact `optionalDependencies` on this release's platform packages. `npx sliccy@next` runs the bin named after the package, `sliccy`, and both bins run the same launcher. `--bin <name>` (repeatable) overrides the bins of any staged launcher.
|
|
1205
|
-
4. `actions/attest-build-provenance` attests every binary
|
|
1254
|
+
2. `scripts/package.sh <version>` builds `darwin`, `linux` and `windows` × `amd64`, `arm64` with `CGO_ENABLED=0`, `-trimpath` and `-X main.version=<version>`, and `slicc-wasip1-wasm.wasm` (`GOOS=wasip1 GOARCH=wasm`) the same way. It signs and notarizes the darwin binaries and writes `SHA256SUMS`. The windows and linux binaries are not signed. Without the Apple signing secrets (forks, pull requests) it warns and leaves the darwin binaries unsigned.
|
|
1255
|
+
3. `scripts/npm-stage.mjs` stages `@ai-ecoverse/slicc` and the six platform packages into `dist/npm/`. It also stages the same launcher as `sliccy` (with two bins, `sliccy` and `slicc`, and a short preview README) into `dist/npm-next/`, as version `7.0.0-next.<version>`, with exact `optionalDependencies` on this release's platform packages. `npx sliccy@next` runs the bin named after the package, `sliccy`, and both bins run the same launcher. `--bin <name>` (repeatable) overrides the bins of any staged launcher. `--wasi` also stages `@ai-ecoverse/wasi-slicc` into `dist/npm/wasi-slicc/` from `slicc-wasip1-wasm.wasm` and `npm/wasi-slicc/host/slicc-host.mjs`, with README.md's [Inside seven](#inside-seven) section as its README; `--wasi-only` stages only that package.
|
|
1256
|
+
4. `actions/attest-build-provenance` attests every binary, the `.wasm` included, through `SHA256SUMS`.
|
|
1206
1257
|
5. semantic-release checks the version again (`dist/VERSION`, and `scripts/go-major.mjs`, see below), tags, creates the GitHub release with every binary and `SHA256SUMS`, then `scripts/npm-publish.mjs` publishes the platform packages and the launcher through npm trusted publishing (OIDC, with provenance), and then `sliccy` with `--tag next`. Versions already on npm are skipped. Before publishing `sliccy`, the script checks that every exact-pinned `optionalDependencies` version is on the registry, waits up to `SLICC_REGISTRY_WAIT_SECONDS` (default 900) for freshly published ones to appear, and fails otherwise, so a `sliccy` version never points at missing platform packages.
|
|
1207
1258
|
6. `scripts/go-warm.sh <version>`, once the tag is on `origin`, asks `proxy.golang.org` for the module at `v<version>` (`go list -m` with a scratch module cache) and asks `pkg.go.dev` to fetch it. The proxy fetch is retried briefly; the `pkg.go.dev` fetch is one attempt of at most 10 s, since the proxy fetch already gets the version indexed. Both only warn, and the step can't fail the release.
|
|
1208
1259
|
|
|
@@ -1218,6 +1269,6 @@ The workflow reads these repository secrets. Each group is optional: without the
|
|
|
1218
1269
|
- macOS signing: `APPLE_CERTIFICATE_BASE64`, `APPLE_DEVELOPER_CERTIFICATE_PASSWORD`;
|
|
1219
1270
|
- notarization: `APPLE_API_KEY_ID`, `APPLE_API_KEY_ISSUER_ID`, `APPLE_API_KEY_P8_BASE64`.
|
|
1220
1271
|
|
|
1221
|
-
npm needs no token. `npm run trust` (fledgling) configures trusted publishing for the seven packages listed under `fledgling.include` in `package.json`. Publishing to npm is off until the repository variable `SLICC_NPM_PUBLISH` is `true`,
|
|
1272
|
+
npm needs no token. `npm run trust` (fledgling) configures trusted publishing for the seven packages listed under `fledgling.include` in `package.json`. Publishing to npm is off until the repository variable `SLICC_NPM_PUBLISH` is `true`, `sliccy` stays off until `SLICCY_NEXT_PUBLISH` is `true`, and `@ai-ecoverse/wasi-slicc` until `WASI_SLICC_PUBLISH` is `true` (the facade's kernel side, slicc-kernel#526, comes first); until then a release skips them with a notice. `@ai-ecoverse/wasi-slicc` isn't under `fledgling.include` yet, so its trusted publishing needs setting up before that variable is turned on.
|
|
1222
1273
|
|
|
1223
1274
|
`sliccy` only ever goes to the `next` dist-tag, so `npx sliccy` keeps running SLICC six and `npx sliccy@next` runs this binary. `npm-publish.mjs` refuses, even in a dry run, to publish `sliccy` with any tag but `next` or with a version that doesn't match `^7\.0\.0-next\.`. Nothing here changes `sliccy`'s other dist-tags.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.0",
|
|
4
4
|
"description": "SLICC's command line for seven: links a machine's network, compute and browsers to seven over WebRTC",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"node": ">=18"
|
|
19
19
|
},
|
|
20
20
|
"optionalDependencies": {
|
|
21
|
-
"@ai-ecoverse/slicc-darwin-arm64": "1.
|
|
22
|
-
"@ai-ecoverse/slicc-darwin-amd64": "1.
|
|
23
|
-
"@ai-ecoverse/slicc-linux-arm64": "1.
|
|
24
|
-
"@ai-ecoverse/slicc-linux-amd64": "1.
|
|
25
|
-
"@ai-ecoverse/slicc-windows-arm64": "1.
|
|
26
|
-
"@ai-ecoverse/slicc-windows-amd64": "1.
|
|
27
|
-
"@ai-ecoverse/slicc-jerk": "^0.
|
|
21
|
+
"@ai-ecoverse/slicc-darwin-arm64": "1.40.0",
|
|
22
|
+
"@ai-ecoverse/slicc-darwin-amd64": "1.40.0",
|
|
23
|
+
"@ai-ecoverse/slicc-linux-arm64": "1.40.0",
|
|
24
|
+
"@ai-ecoverse/slicc-linux-amd64": "1.40.0",
|
|
25
|
+
"@ai-ecoverse/slicc-windows-arm64": "1.40.0",
|
|
26
|
+
"@ai-ecoverse/slicc-windows-amd64": "1.40.0",
|
|
27
|
+
"@ai-ecoverse/slicc-jerk": "^0.17.0"
|
|
28
28
|
}
|
|
29
29
|
}
|