@ai-ecoverse/slicc-browsers 1.1.0 → 1.3.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 +77 -14
- package/catalog.json +31 -2
- package/corpus.json +559 -0
- package/package.json +8 -3
- package/protected.json +141 -0
- package/protected.mjs +77 -0
- package/schema/browsers.schema.json +9 -3
- package/schema/catalog.schema.json +69 -5
- package/schema/corpus.schema.json +7 -2
- package/schema/protected.schema.json +62 -0
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@ The browser catalog, JSON schemas and conformance corpus shared by the two progr
|
|
|
4
4
|
- `slicc browsers` and `slicc launch` in [slicc-cli](https://github.com/ai-ecoverse/slicc-cli) (Go, `CGO_ENABLED=0`);
|
|
5
5
|
- `playwright-cli list` and `open` in [slicc-cdp](https://github.com/ai-ecoverse/slicc-cdp) (Rust, also built for `wasm32-wasip1`).
|
|
6
6
|
|
|
7
|
+
It also holds the [protected origins](#protected-origins): the origins browser control must never reach, which slicc-agent checks too.
|
|
8
|
+
|
|
7
9
|
They can't share code, so they share data. Three packages wrap the same files, at one version:
|
|
8
10
|
|
|
9
11
|
| package | what it gives you |
|
|
@@ -20,6 +22,8 @@ They can't share code, so they share data. Three packages wrap the same files, a
|
|
|
20
22
|
| `schema/corpus.schema.json` | JSON Schema for `corpus.json` |
|
|
21
23
|
| `corpus/<case>/case.json`, `corpus/<case>/expected.json` | the conformance cases |
|
|
22
24
|
| `corpus.json` | every case in one file, generated from `corpus/` by `npm run corpus` |
|
|
25
|
+
| `protected.json`, `schema/protected.schema.json` | the protected-origin test vectors and their schema |
|
|
26
|
+
| `protected.mjs` | the reference protected-origin matcher, in JavaScript (npm only) |
|
|
23
27
|
|
|
24
28
|
## Go
|
|
25
29
|
|
|
@@ -32,7 +36,8 @@ b, ok := c.Browser("chrome")
|
|
|
32
36
|
|
|
33
37
|
- `Default() *Catalog` parses the embedded `catalog.json` once and panics if it doesn't parse (CI makes sure it does). `Load() (*Catalog, error)` is the same without the panic. Treat the result as read-only. `Parse([]byte)` parses another copy and rejects a `schema` other than 1.
|
|
34
38
|
- `(*Catalog).Browser(id)` and `(*Catalog).Priority(id)`, the index in `browsers` (its length for an unknown id).
|
|
35
|
-
- `CatalogJSON()`, `CatalogSchemaJSON()`, `BrowsersSchemaJSON()` and `
|
|
39
|
+
- `CatalogJSON()`, `CatalogSchemaJSON()`, `BrowsersSchemaJSON()`, `CorpusJSON()`, `ProtectedJSON()` and `ProtectedSchemaJSON()` return copies of the embedded files.
|
|
40
|
+
- `(*Catalog).ProtectedOrigins` is `catalog.json`'s `protectedOrigins`. `Protected() (*ProtectedVectors, error)` parses `protected.json` (`Origins`, `URLs`, `Targets`, `CookieDomains`, `StorageKeys`; a target's `Opener` is `""`, `OpenerProtected`, `OpenerUnprotected` or `OpenerUnknown`).
|
|
36
41
|
- `Corpus() ([]Case, error)` returns the cases. See [Running the corpus](#running-the-corpus) for the helpers.
|
|
37
42
|
|
|
38
43
|
## Rust
|
|
@@ -45,15 +50,17 @@ slicc-browsers = "1"
|
|
|
45
50
|
slicc-browsers = { version = "1", features = ["corpus"] }
|
|
46
51
|
```
|
|
47
52
|
|
|
48
|
-
- Always: `CATALOG`, `CATALOG_SCHEMA`, `BROWSERS_SCHEMA` and `
|
|
49
|
-
- Feature `serde`: `Catalog` and the other types, `Catalog::parse(&str)`, `catalog()` (parses `CATALOG`), `Catalog::browser` and `Catalog::priority`. It pulls in `serde` and `serde_json`.
|
|
50
|
-
- Feature `corpus` (implies `serde`): `CORPUS`, the text of `corpus.json
|
|
53
|
+
- Always: `CATALOG`, `CATALOG_SCHEMA`, `BROWSERS_SCHEMA`, `CORPUS_SCHEMA` and `PROTECTED_SCHEMA`, each the file's text via `include_str!`, and `SCHEMA` (1). No dependencies.
|
|
54
|
+
- Feature `serde`: `Catalog` and the other types (`protected_origins` is a `ProtectedOrigins`), `Catalog::parse(&str)`, `catalog()` (parses `CATALOG`), `Catalog::browser` and `Catalog::priority`. It pulls in `serde` and `serde_json`.
|
|
55
|
+
- Feature `corpus` (implies `serde`): `CORPUS` and `PROTECTED`, the text of `corpus.json` and `protected.json`; the module `corpus` with `corpus()`, `Case`, `Layout` and the helpers below; and the module `protected` with `vectors()`, `Vectors` and the `OPENER_*` constants. Use it from `[dev-dependencies]` only; with resolver 2 it stays out of normal builds.
|
|
51
56
|
|
|
52
57
|
Every feature builds for `wasm32-wasip1`.
|
|
53
58
|
|
|
54
59
|
## npm
|
|
55
60
|
|
|
56
|
-
`import catalog from '@ai-ecoverse/slicc-browsers' with { type: 'json' }`. The exports are `.` (`catalog.json`), `./catalog.json`, `./corpus.json`, `./schema/catalog.schema.json`, `./schema/browsers.schema.json` and `./schema/
|
|
61
|
+
`import catalog from '@ai-ecoverse/slicc-browsers' with { type: 'json' }`. The exports are `.` (`catalog.json`), `./catalog.json`, `./corpus.json`, `./protected.json`, `./protected.mjs`, `./schema/catalog.schema.json`, `./schema/browsers.schema.json`, `./schema/corpus.schema.json` and `./schema/protected.schema.json`.
|
|
62
|
+
|
|
63
|
+
`protected.mjs` is the reference matcher for [protected origins](#protected-origins): `import { protectedOrigins } from '@ai-ecoverse/slicc-browsers/protected.mjs'`, then `protectedOrigins(catalog.protectedOrigins, extraOrigins)` returns `{ url(text), target({ url, previous, opener }), cookieDomain(domain), storageKey(key) }`, each a boolean. It needs only the WHATWG `URL`, so it runs in Node and in a browser.
|
|
57
64
|
|
|
58
65
|
## `catalog.json`
|
|
59
66
|
|
|
@@ -66,7 +73,7 @@ Every feature builds for `wasm32-wasip1`.
|
|
|
66
73
|
- `windows?`: `roots` (names from `platforms.windows.roots`, searched in order) and `executables` (each tried under each root); `dataRoot` and `dataDir`, the default user-data dir; `startMenuInternet?`, the browser's key names under the `StartMenuInternet` registry keys.
|
|
67
74
|
- `linux?`: `bins` (names on `PATH`), `desktopIds` (`.desktop` file names without the suffix), `flatpak?` (the app id), `snap?` (the snap name), `snapDataDir?` (the user-data dir under `~/snap/<snap>/common`), `configDir` (the user-data dir under the config dir, also under `~/.var/app/<flatpak>/config` for a flatpak), and `debs` (dpkg package names for the version).
|
|
68
75
|
- `electron`: `macosApps` (known Electron apps by bundle id, with display names), `debugBlocked` (app names that block remote debugging; they're listed with `debugSupport: "disabled"` and never launched), and `idPrefix` (`electron:`, followed by the slug of the name: lower case, runs of other characters as one `-`).
|
|
69
|
-
- `rank`: `tiers`, 1 to
|
|
76
|
+
- `rank`: `tiers`, 1 to 6: `sevenOpen` (an endpoint with a seven tab), `endpoint` (any other endpoint), `chrome` (installed `chromeId`), `chromium` (other installed Chromium browsers), `electron` (installed Electron apps), `six` (an endpoint in SLICC six's profile, with or without a seven tab; see [SLICC six's profiles](#slicc-sixs-profiles)).
|
|
70
77
|
- `discovery`:
|
|
71
78
|
- `activePortFile` (`DevToolsActivePort`): its first line is the port (1 to 65535) and its second the browser's websocket path, which starts with `/`. A file without both is ignored. A file is live only when its port answers `/json/version` with a `webSocketDebuggerUrl` whose path is that websocket path; otherwise it's stale and ignored. When the port accepts connections but serves no `/json/version`, the endpoint is listed as `wsOnly`, with `ws://127.0.0.1:<port><path>`;
|
|
72
79
|
- `probePorts` (9222 to 9229, probed by `slicc` only);
|
|
@@ -82,10 +89,38 @@ Every feature builds for `wasm32-wasip1`.
|
|
|
82
89
|
- `discardExceptions`: where the site pattern and the extra origins' hosts go, as a `list` of strings or as a `chrome-time-map`, a map from site to the time it was added (microseconds since 1601-01-01 UTC, as a decimal string);
|
|
83
90
|
- `cleanExit`: values that mark the last exit clean;
|
|
84
91
|
- `form` says where a key comes from: `six` (SLICC six's keys) or `chrome-154` (what Chrome 154 reads).
|
|
85
|
-
- `
|
|
92
|
+
- `protectedOrigins`: what browser control must never reach, see [Protected origins](#protected-origins). `domains` (`sliccy.ai`), `schemes` (`https`, `http`), `innerSchemes` (`blob`, `filesystem`, `view-source`), `anySchemes` (`devtools`), `inheriting` (`about:blank`, `about:srcdoc`), and `refusal`, the text of a refusal.
|
|
93
|
+
- `profiles`: SLICC profiles live in `<config dir>/<root>/<name>`, and a snap's in `~/snap/<snap>/common/<snapRoot>/<name>`. `legacyRoot` is the old root, never scanned; on macOS's case-insensitive volume it is SLICC six's root too. `sixProfilePattern` matches six's profile names, case-insensitively. `namePattern` is a valid profile name. `six` describes SLICC six's Chrome profiles (see [SLICC six's profiles](#slicc-sixs-profiles)):
|
|
94
|
+
- `roots`: six's profile root per OS (`macos`, `linux`, `windows`), a `base` location followed by the `path` segments. The base is its `env` when that is set and not empty (any value, as six takes it), else `home` under the home dir.
|
|
95
|
+
- `defaultName` (`browser-coding-agent-chrome`), `defaultPort` (5710) and `portSuffix` (`-{port}`): six's profile for its serve port `<port>` is `<root>/<defaultName>`, with `portSuffix` added for any port other than `defaultPort`.
|
|
96
|
+
- `userDataDirEnv` (`SLICC_USER_DATA_DIR`): when set, its value, trimmed of whitespace, is six's profile for every port, unless it is empty.
|
|
86
97
|
- `launch`: `chromiumArgs` (with `{profile}` for the profile dir), then the seven flags, then `headless` with `--headless`. Electron apps get `electron.portFlag` with the first free port from `electron.minPort` up that isn't in `electron.reservedPorts`.
|
|
87
98
|
- `platforms`: the config dir per OS, the Windows roots, and the Windows registry keys. A location is the environment variable `env` when it's set (on Linux only an absolute path counts), else `absolute`, else `home` under the home dir. `registry`: under each of `hives`, every subkey of each `startMenuInternet` key, with its `openCommand` default value, and the default value of `appPaths\<name>` for each of `appPathNames`.
|
|
88
99
|
|
|
100
|
+
## Protected origins
|
|
101
|
+
|
|
102
|
+
Browser control must never navigate to, open or attach to a target on seven's own origin, or read or write its cookies or storage: not slicc-cli's `cdp` relay, not slicc-cdp's `playwright-cli`, not slicc-agent. `protectedOrigins` in `catalog.json` says what is protected, and every implementation runs the vectors in `protected.json`.
|
|
103
|
+
|
|
104
|
+
**URLs.** A URL is parsed the way the WHATWG URL Standard (and so the browser) parses it, so `https:\\seven.sliccy.ai`, a tab or newline inside the URL, `%2E`, `。` and full-width letters all reach seven. In Go and Rust that takes a WHATWG parser, not `net/url`. A URL that doesn't parse isn't protected; the browser doesn't load it either. Then:
|
|
105
|
+
1. While its scheme is one of `innerSchemes`, the rest of the URL after `<scheme>:` takes its place, at most 8 times: `blob:https://seven.sliccy.ai/<uuid>` is `https://seven.sliccy.ai/<uuid>`.
|
|
106
|
+
2. A scheme in `anySchemes` is protected whatever follows: a DevTools front end (`devtools://`) can be inspecting seven.
|
|
107
|
+
3. A scheme in `schemes` is protected when its host is one of `domains` or under one, at any depth and on any port. The host is lower-cased, and one trailing dot is dropped.
|
|
108
|
+
4. Any other URL is protected when its origin is one of the program's **extra origins**: the seven origins it accepts besides `sliccy.ai` (slicc-cli's `--origin` and `--page` origins), compared as `scheme://host[:port]` without the scheme's default port, with the host as in 3.
|
|
109
|
+
|
|
110
|
+
This is wider than the rule for finding seven (`seven.originHostPattern`, which leaves out `www`). Every `sliccy.ai` host shares the `sliccy.ai` cookies, and cookies ignore the port and, without `Secure`, the scheme. SLICC six lives on `www.sliccy.ai` and the apex, and its cookies matter. `*.kernel.localhost` is not protected: each port is its own origin, and the agent's own servers live there. An extra origin is matched exactly, so `http://127.0.0.1:5710` doesn't protect `http://127.0.0.1:5711`.
|
|
111
|
+
|
|
112
|
+
**Targets.** A target's effective origin is its URL's (`TargetInfo.url`), except when the URL inherits the origin of whoever made the document: the empty URL, and `inheriting` with any query or fragment. Such a target is protected when it was protected before this URL (a seven tab that went to `about:blank` keeps seven's origin), or when its opener (`openerId`, else `openerFrameId`) is protected or unknown, for an opener closed before the program saw it. The URL, `openerFrameId` and `browserContextId` alone can't tell: a blank popup that seven opens has seven's origin and the URL `about:blank`. A program that holds a session to the target also has the document's real origin: the main frame's `securityOrigin` in `Page.frameNavigated`, and the default context's `origin` in `Runtime.executionContextCreated`. When one of those is protected, the target is protected too, until a URL with an origin of its own replaces it.
|
|
113
|
+
|
|
114
|
+
A same-site frame shares its parent's process and has no target of its own. Every `sliccy.ai` host is protected, and site isolation gives a seven frame inside any other site its own target, so this only matters for an extra origin whose site has other origins (another port of `127.0.0.1`, say).
|
|
115
|
+
|
|
116
|
+
**Cookies.** A cookie domain, lower-cased and without a leading or trailing dot, is protected when it is one of `domains` or under one, or when it is the host of a protected domain or an extra origin, or a parent of one: a cookie on `.example.test` reaches `https://seven.example.test`.
|
|
117
|
+
|
|
118
|
+
**Storage keys** (`Storage`, `IndexedDB`, `CacheStorage` and `FileSystem` in CDP): a key is protected when its origin (up to the first `^`) or its top-level site (a part after `^0`) is a protected URL.
|
|
119
|
+
|
|
120
|
+
**Refusals** carry the text in `refusal`, `slicc: refused: target is on seven's origin`.
|
|
121
|
+
|
|
122
|
+
**`protected.json`** (schema `schema/protected.schema.json`): `origins`, the extra origins every vector runs with; `urls` (`url`, `protected`); `targets` (`url`, `previous?`, whether the target was protected before; `opener?`, `protected`, `unprotected` or `unknown`, and no `opener` for a target without one; `protected`); `cookieDomains` (`domain`, `protected`); `storageKeys` (`key`, `protected`). `npm run validate` runs every vector through `protected.mjs`, and no vector uses a port from 9222 to 9229.
|
|
123
|
+
|
|
89
124
|
## The process source
|
|
90
125
|
|
|
91
126
|
The process scan finds browsers started with a debugging port by something else:
|
|
@@ -93,13 +128,40 @@ The process scan finds browsers started with a debugging port by something else:
|
|
|
93
128
|
- **What's skipped:** pid 0, the scanning process itself, and commands whose first token is a wrapper. The first token is the quoted string when the command starts with a quote. A wrapper is a token whose base name, without `.exe`, `.cmd` or `.bat`, is one of `wrappers`, case-insensitively. A command with no executable before its first `-` token is skipped too.
|
|
94
129
|
- **The port** comes from the first `--remote-debugging-port` followed by `=` or whitespace and then digits. A port above 65535 drops the process.
|
|
95
130
|
- **The dir** is the value of `--user-data-dir` at the start of a token, followed by `=` or by whitespace (which is skipped). A value that starts with one of `valueQuotes` (`"` or `'`) runs to the matching quote. Any other value runs up to the first whitespace that is followed by `valueStop` (`--`), or to the end of the command, without trailing whitespace. So `--user-data-dir=/Users/me/Library/Application Support/x --no-first-run` gives `/Users/me/Library/Application Support/x`. A value that would start with `--` is empty.
|
|
96
|
-
- **Port 0** means the port is in the dir's `DevToolsActivePort`, checked like any other. With no dir, or a dir under the legacy profile root (a `slicc` segment followed by `profiles`, case-insensitively), the process is skipped.
|
|
131
|
+
- **Port 0** means the port is in the dir's `DevToolsActivePort`, checked like any other. With no dir, or a dir under the legacy profile root (a `slicc` segment followed by `profiles`, case-insensitively) that isn't one of [six's profile dirs](#slicc-sixs-profiles), the process is skipped.
|
|
97
132
|
- **Any other port** is probed on `127.0.0.1`. An endpoint from the process scan has `source: "process"` and `userDataDir` set to the dir when there is one.
|
|
98
133
|
- **Tests** must fake the process list: never scan the real one in a test.
|
|
99
134
|
|
|
135
|
+
## SLICC six's profiles
|
|
136
|
+
|
|
137
|
+
SLICC six launches Chrome in a profile of its own, and slicc-cli can use that profile in place (`slicc --profile six`). Discovery never chooses it: its endpoints are listed, marked and ranked last.
|
|
138
|
+
|
|
139
|
+
| | macOS | Linux | Windows |
|
|
140
|
+
| --- | --- | --- | --- |
|
|
141
|
+
| six's root | `~/Library/Application Support/Slicc/profiles` | `$XDG_STATE_HOME/slicc/profiles`, else `~/.local/state/slicc/profiles` | `%LOCALAPPDATA%\Slicc\profiles`, else `~\AppData\Local\Slicc\profiles` |
|
|
142
|
+
|
|
143
|
+
Taken from [ai-ecoverse/slicc](https://github.com/ai-ecoverse/slicc) at `65c5a79b4` (v6.247.17-8):
|
|
144
|
+
|
|
145
|
+
| what | where |
|
|
146
|
+
| --- | --- |
|
|
147
|
+
| the root per OS | `packages/node-server/src/chrome-launch.ts:119-136` (`resolveProfilesDir`); `packages/swift-server/Sources/Browser/ChromeLauncher.swift:314-322` (macOS only) |
|
|
148
|
+
| `browser-coding-agent-chrome` | `chrome-launch.ts:27`; `ChromeLauncher.swift:5` |
|
|
149
|
+
| the `-<port>` suffix for a serve port other than 5710 | `chrome-launch.ts:147`; `ChromeLauncher.swift:6`, `:323` |
|
|
150
|
+
| `SLICC_USER_DATA_DIR`, trimmed | `chrome-launch.ts:143-146` (node-server only) |
|
|
151
|
+
| six's own `--remote-debugging-port` (9222 by default) | `chrome-launch.ts:283`, `packages/node-server/src/runtime-flags.ts:47`; `ChromeLauncher.swift:213` |
|
|
152
|
+
|
|
153
|
+
**Six's profile dirs** are the dirs in six's root whose name matches `sixProfilePattern` case-insensitively, and the `SLICC_USER_DATA_DIR` dir. A dir found anywhere is six's when it is one of them: the paths are compared case-insensitively, with `/` and `\` alike, and after resolving symlinks where the program can (so a symlink to six's profile, or a symlinked root, is six's too).
|
|
154
|
+
|
|
155
|
+
**Discovery** marks an endpoint `six: true` when one of its sources found it in six's profile:
|
|
156
|
+
- `DevToolsActivePort` in each of six's profile dirs, checked like any other. No other dir in six's root is read.
|
|
157
|
+
- The process list: a process whose `--user-data-dir` is six's. With port 0 its `DevToolsActivePort` is read, which the legacy-root rule would otherwise skip.
|
|
158
|
+
- Merging: an endpoint is six's when any source that found it, and whose checks passed, is six's. So a port probe hit or a `--cdp` URL that the process list maps to six's profile is six's, while a stale `DevToolsActivePort` in six's profile marks nothing. Its `userDataDir` is six's dir when the source that wins has none.
|
|
159
|
+
|
|
160
|
+
A six endpoint has tier `six`, whatever its seven tabs. **A program never chooses it by itself**: a default choice, an "attach to the best" rule, or a non-interactive mode skips it. Only an explicit request for six's profile unlocks it, such as `slicc --profile six` or picking it in a picker.
|
|
161
|
+
|
|
100
162
|
## Output schema 1
|
|
101
163
|
|
|
102
|
-
`schema/browsers.schema.json` describes `slicc browsers --json`, which `playwright-cli list --json` also prints. [slicc-cli's README](https://github.com/ai-ecoverse/slicc-cli#slicc-browsers---json---cdp-url---no-bundle-scan) is the authoritative spec for it; this schema is a copy and follows it. Fields can be added; `source` is one of `devtools-active-port`, `flag`, `probe` and `process`.
|
|
164
|
+
`schema/browsers.schema.json` describes `slicc browsers --json`, which `playwright-cli list --json` also prints. [slicc-cli's README](https://github.com/ai-ecoverse/slicc-cli#slicc-browsers---json---cdp-url---no-bundle-scan) is the authoritative spec for it; this schema is a copy and follows it. Fields can be added; `source` is one of `devtools-active-port`, `flag`, `probe` and `process`. `tier` is 1 to 6, and `six: true` marks an endpoint in SLICC six's profile (tier 6).
|
|
103
165
|
|
|
104
166
|
## The corpus
|
|
105
167
|
|
|
@@ -107,15 +169,16 @@ Each case is a fake machine: a home tree, `DevToolsActivePort` files, fake `/jso
|
|
|
107
169
|
|
|
108
170
|
**`case.json`:**
|
|
109
171
|
- `description`, and `os?`: the OSes the case runs on (`darwin`, `linux`, `windows`; default all).
|
|
110
|
-
- `needs`: what a program must support to run the case: `user-data-dirs` (`DevToolsActivePort` in browsers' default user-data dirs), `seven-profiles` (in the profile roots), `flag` (`--cdp` URLs), `process`, `probe` (port probes, `slicc` only), `origins` (extra seven origins), `installed` (ranking installed browsers). A program skips a case that needs something it doesn't do.
|
|
172
|
+
- `needs`: what a program must support to run the case: `user-data-dirs` (`DevToolsActivePort` in browsers' default user-data dirs), `seven-profiles` (in the profile roots), `flag` (`--cdp` URLs), `process`, `probe` (port probes, `slicc` only), `origins` (extra seven origins), `installed` (ranking installed browsers), `six` (finding and marking SLICC six's profiles). A program skips a case that needs something it doesn't do.
|
|
111
173
|
- `env?`: environment variables for discovery, which sees nothing else from the real environment.
|
|
112
174
|
- `files?`: file contents by path. Every path starts with a token.
|
|
113
175
|
- `cdp?`, `origins?`, `probePorts?`: `--cdp` URLs, extra seven origins, and the ports to probe.
|
|
114
176
|
- `processes?`: `{ "pid", "command" }`, or `{ "self": true, "command" }` for the scanning process, whose pid the harness fills in.
|
|
115
177
|
- `http?`: fake servers by `host:port`. `localhost` and `[::1]` are `127.0.0.1`. A listed port accepts TCP connections. `/json/version` answers 200 with `version`, `/json/list` (and `/json`) with `list`. A missing body, or any other path, answers 404. An unlisted port refuses connections.
|
|
116
178
|
- `installed?`: installed browsers in the shape of output schema 1's `installed`, ranked along with the endpoints.
|
|
179
|
+
- `auto`: exactly in the cases that need `six`, the id of the first entry in `expected.json` that isn't six's, or `null` when every entry is. A program that chooses without being asked must choose no entry before it, and never a six entry.
|
|
117
180
|
|
|
118
|
-
**Tokens.** `{home}` (the fake home), `{config}` (the config dir), `{sevenProfiles}` (the profile root) and `{userData:<id>}` (the browser's first default user-data dir on this OS) stand for directories. In `files`, `env`, `cdp`, process commands and `expected.json`, a token and the path characters after it (up to whitespace, `"`, `'` or `,`) become a path on the OS under test, with `\` on Windows. The token values come from `catalog.json`, with the case's `env`.
|
|
181
|
+
**Tokens.** `{home}` (the fake home), `{config}` (the config dir), `{sevenProfiles}` (the profile root), `{sixProfiles}` (SLICC six's root) and `{userData:<id>}` (the browser's first default user-data dir on this OS) stand for directories. In `files`, `env`, `cdp`, process commands and `expected.json`, a token and the path characters after it (up to whitespace, `"`, `'` or `,`) become a path on the OS under test, with `\` on Windows. The token values come from `catalog.json`, with the case's `env`.
|
|
119
182
|
|
|
120
183
|
**Never 9222 to 9229.** A developer's own Chrome listens there. The corpus schema refuses those ports, `npm run validate` refuses them anywhere in the corpus, and the fakes never serve them.
|
|
121
184
|
|
|
@@ -161,13 +224,13 @@ for case in corpus().cases {
|
|
|
161
224
|
}
|
|
162
225
|
```
|
|
163
226
|
|
|
164
|
-
`Layout` also gives `Config`, `SevenProfiles`, `UserDataDirs(id)`, `Token(name)` and `Expand(text)` (Rust: `config`, `seven_profiles`, `user_data_dirs`, `token`, `expand`). Their results for a few homes are pinned in `test/integration/layout.json`, which the Go and Rust tests both check.
|
|
227
|
+
`Layout` also gives `Config`, `SevenProfiles`, `SixProfiles`, `UserDataDirs(id)`, `Token(name)` and `Expand(text)` (Rust: `config`, `seven_profiles`, `six_profiles`, `user_data_dirs`, `token`, `expand`). Their results for a few homes are pinned in `test/integration/layout.json`, which the Go and Rust tests both check.
|
|
165
228
|
|
|
166
229
|
## Development
|
|
167
230
|
|
|
168
231
|
Go 1.26, Rust stable with `wasm32-wasip1`, Node ≥ 24.
|
|
169
232
|
- `npm run corpus` regenerates `corpus.json` from `corpus/`; the pre-commit hook and CI fail when it's stale.
|
|
170
|
-
- `npm run validate` checks `catalog.json` and `
|
|
233
|
+
- `npm run validate` checks `catalog.json`, `corpus.json` and `protected.json` against the schemas, runs the protected-origin vectors through `protected.mjs`, and checks what a schema can't say: unique ids, bundle ids and names, known Windows roots, rising tiers, compiling patterns, known tokens, tier order, `sevenOpen`, `six` and `auto` in each `expected.json`, and no port from 9222 to 9229.
|
|
171
234
|
- `npm run lint`: the slicc lint tools (Biome, no comments, no unit tests in git, `AGENTS.md`), `gofmt`, `go mod tidy -diff`, `go vet`, golangci-lint, `cargo fmt --check` and clippy.
|
|
172
235
|
- `npm test`: `validate`, the Go tests in `test/integration/`, and `cargo test --all-features`.
|
|
173
236
|
- `npm run build`: the Go module, the crate (also for `wasm32-wasip1`), and `npm pack --dry-run`.
|
|
@@ -181,7 +244,7 @@ semantic-release cuts one version from `main` for all three packages (`.github/w
|
|
|
181
244
|
2. **npm:** with the repository variable `SLICC_BROWSERS_NPM_PUBLISH` set to `true`, the package is stamped with the version and published through npm trusted publishing (OIDC, with provenance). A version that is already on npm is skipped.
|
|
182
245
|
3. **crates.io:** with the repository variable `SLICC_BROWSERS_CRATES_PUBLISH` set to `true`, `Cargo.toml` is stamped with the version and `cargo publish` runs with a short-lived token from crates.io trusted publishing (`rust-lang/crates-io-auth-action`). A version that is already on crates.io is skipped.
|
|
183
246
|
|
|
184
|
-
A run started by hand
|
|
247
|
+
A run started by hand publishes what's missing without a new release: `gh workflow run release.yml --ref main` when `main`'s head has its tag, or `gh workflow run release.yml --ref main -f tag=vX.Y.Z` for any existing tag.
|
|
185
248
|
|
|
186
249
|
**Go module versions.** A pushed tag is the release: `proxy.golang.org` caches it and `sum.golang.org` records its hash for good. Never move or delete a pushed tag; retract a bad version in `go.mod` and release anew. A `BREAKING CHANGE` needs a `/vN` module path first.
|
|
187
250
|
|
package/catalog.json
CHANGED
|
@@ -580,7 +580,8 @@
|
|
|
580
580
|
"endpoint": 2,
|
|
581
581
|
"chrome": 3,
|
|
582
582
|
"chromium": 4,
|
|
583
|
-
"electron": 5
|
|
583
|
+
"electron": 5,
|
|
584
|
+
"six": 6
|
|
584
585
|
},
|
|
585
586
|
"chromeId": "chrome"
|
|
586
587
|
},
|
|
@@ -700,12 +701,40 @@
|
|
|
700
701
|
}
|
|
701
702
|
]
|
|
702
703
|
},
|
|
704
|
+
"protectedOrigins": {
|
|
705
|
+
"domains": ["sliccy.ai"],
|
|
706
|
+
"schemes": ["https", "http"],
|
|
707
|
+
"innerSchemes": ["blob", "filesystem", "view-source"],
|
|
708
|
+
"anySchemes": ["devtools"],
|
|
709
|
+
"inheriting": ["about:blank", "about:srcdoc"],
|
|
710
|
+
"refusal": "slicc: refused: target is on seven's origin"
|
|
711
|
+
},
|
|
703
712
|
"profiles": {
|
|
704
713
|
"root": ["slicc", "seven-profiles"],
|
|
705
714
|
"snapRoot": ["slicc", "seven-profiles"],
|
|
706
715
|
"legacyRoot": ["slicc", "profiles"],
|
|
707
716
|
"sixProfilePattern": "^browser-coding-agent-chrome(-[0-9]+)?$",
|
|
708
|
-
"namePattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$"
|
|
717
|
+
"namePattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$",
|
|
718
|
+
"six": {
|
|
719
|
+
"roots": {
|
|
720
|
+
"macos": {
|
|
721
|
+
"base": { "home": ["Library", "Application Support"] },
|
|
722
|
+
"path": ["Slicc", "profiles"]
|
|
723
|
+
},
|
|
724
|
+
"linux": {
|
|
725
|
+
"base": { "env": "XDG_STATE_HOME", "home": [".local", "state"] },
|
|
726
|
+
"path": ["slicc", "profiles"]
|
|
727
|
+
},
|
|
728
|
+
"windows": {
|
|
729
|
+
"base": { "env": "LOCALAPPDATA", "home": ["AppData", "Local"] },
|
|
730
|
+
"path": ["Slicc", "profiles"]
|
|
731
|
+
}
|
|
732
|
+
},
|
|
733
|
+
"defaultName": "browser-coding-agent-chrome",
|
|
734
|
+
"defaultPort": 5710,
|
|
735
|
+
"portSuffix": "-{port}",
|
|
736
|
+
"userDataDirEnv": "SLICC_USER_DATA_DIR"
|
|
737
|
+
}
|
|
709
738
|
},
|
|
710
739
|
"launch": {
|
|
711
740
|
"chromiumArgs": [
|