@ai-ecoverse/slicc-cdp 1.27.7 → 1.28.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
@@ -24,6 +24,17 @@ Event JSON (NDJSON, one object per line):
24
24
  {"v":1,"standard":"ard","origin":"https://example.com","url":"https://example.com/.well-known/ard.json","via":"well-known","page":"https://example.com/","targetId":"...","status":"valid","summary":{...}}
25
25
  ```
26
26
 
27
+ Payments over HTTP 402: every response in a watched tab, subresources included, with status 402 is decoded as a payment challenge. The watcher never pays, retries, or sends `PAYMENT-SIGNATURE` or `Authorization: Payment`; it only reads the response the page already got. A protected origin's response is never read.
28
+
29
+ - **`x402`** ([x402](https://github.com/coinbase/x402/tree/main/specs)). V2 is read from the base64 JSON `PAYMENT-REQUIRED` header. V1 is read from the JSON body of a 402 with a JSON content type. The body is fetched once with `Network.getResponseBody` after it has loaded, up to 1 MiB. `summary` is `{status: 402, version, resource, offers: [{scheme, network, amount, asset, payTo, expires, maxTimeoutSeconds}]}`. `amount` is V2's `amount` or V1's `maxAmountRequired`, kept as the string the server sent.
30
+ - **`mpp`** ([Machine Payments Protocol](https://datatracker.ietf.org/doc/draft-httpauth-payment/)). It is read from each `WWW-Authenticate: Payment` challenge, whose `request` parameter is decoded as base64url JSON. `summary` is `{status: 402, resource, offers: [{method, intent, realm, amount, asset, expires}]}`, with `amount` and `asset` (the request's `currency`) as sent. One response can carry both standards.
31
+ - **Invalid challenges:** a challenge that doesn't decode is reported with `status: "invalid"` and a `reason`, and the watcher goes on. Its `summary` is only `{status: 402, challenge}`, the raw header capped at 1 KiB. Possible reasons:
32
+ - `PAYMENT-REQUIRED is not base64 JSON`;
33
+ - `request is not base64url JSON`;
34
+ - `no x402 payload`: a legacy `X-Payment` header, or a body without `x402Version`/`accepts`;
35
+ - `body unavailable`: the body was evicted or the load failed.
36
+ - **Limits:** events are deduplicated per origin, standard and resource, since each paid resource has its own price. A tab reports at most 50 events per payment standard, so a page that loops 402s can't flood the output. `--once` waits up to 2 s after the load event for the tab's requests to finish (and 402 bodies to be read), so the 402s of subresources are reported. A `--once` run can therefore take up to 2 s longer than the load.
37
+
27
38
  Sinks:
28
39
 
29
40
  - **stdout** (default): NDJSON. Pipe into `jq` or an agent reader.
@@ -84,6 +95,80 @@ Inside the kernel the browser socket is `SLICC_CDP_URL`: `ws://127.0.0.1:9222/de
84
95
 
85
96
  Routes in the kernel use these CDP methods through the facade, always with a tab's `sessionId`: `Fetch.enable`, `Fetch.disable`, `Fetch.continueRequest`, `Fetch.fulfillRequest`, the `Fetch.requestPaused` event, and `Target.getTargetInfo`. The `slicc-cdp-client` API can also send `Fetch.failRequest`, `Fetch.getResponseBody` and `Fetch.continueResponse`; `playwright-cli` doesn't.
86
97
 
98
+ ## Backend contract
99
+
100
+ This is what `playwright-cli`, `curlwright`, `slicc-cdp-client` and the JS `CDPClient` need from a CDP backend: Chrome, slicc-extension's `sliccExtension.cdp`, bios's link and guard, or slicc-node. `crates/cdp-client/src/contract.rs` holds the same lists. Its unit test scans the production code in `crates/*/src` and fails when a list misses a sessionless call, a handled browser-level event or a session domain, or names one the code no longer uses. It also fails when this section disagrees with the lists or with `shield.rs`, or when a cited function or const no longer holds what it is cited for.
101
+
102
+ One browser WebSocket carries everything. An `http` endpoint is read as `GET /json/version`, which must return `webSocketDebuggerUrl` (`crates/cdp-client/src/connect.rs` `websocket_url_from_version`). When nothing names an endpoint, the host probes the `probe_ports` of the slicc-browsers catalog, `127.0.0.1:9222-9229` (`crates/cdp-client/src/ports.rs` `catalog_from`). Requests are `{id, method, params}` with an optional top-level `sessionId`. Replies are `{id, result}` or `{id, error: {message}}`. The client reports an error as `<method>: <message>` (`crates/cdp-client/src/cdp.rs` `raw_call`). Events are `{method, params}`, with `sessionId` when they come from a session.
103
+
104
+ ### Browser-level methods
105
+
106
+ These are sent with no `sessionId`.
107
+
108
+ - `Target.getTargets` with `{}`. Reads `targetId`, `type`, `url` and `title` from each of `targetInfos`. Only `type: "page"` is a tab. The client never lists a protected tab, and a backend may leave them out (`crates/playwright-cli/src/browser.rs` `list_pages`).
109
+ - `Target.getTargetInfo` with `{targetId}`. Reads `targetInfo.type`, `url`, `openerId`. An error for a `frameId` is fine (`crates/cdp-client/src/cdp.rs` `target_protected`).
110
+ - `Target.setDiscoverTargets` with `{discover: true}`, once per connection before the first guard attach (`crates/cdp-client/src/cdp.rs` `touch`). `discover` sends it with the same params (`crates/playwright-cli/src/agent_discover.rs` `run`).
111
+ - `Target.createTarget` with `{url: "about:blank", background}`. Must return `targetId`. Any other `url` is sent as `Page.navigate` on the guard session once the guard is up (`crates/cdp-client/src/cdp.rs` `create_target`).
112
+ - `Target.attachToTarget` with `{targetId, flatten: true}`. Must return `sessionId` (`crates/cdp-client/src/cdp.rs` `attach`).
113
+ - `Target.detachFromTarget` with `{sessionId}` (`crates/cdp-client/src/cdp.rs` `detach`).
114
+ - `Target.closeTarget` with `{targetId}` (`crates/playwright-cli/src/browser.rs` `close_target`).
115
+ - `Target.activateTarget` with `{targetId}`. `open` ignores an error, `tab-select` reports it (`crates/playwright-cli/src/browser.rs` `activate`).
116
+ - `Browser.getVersion` with `{}`. Optional, `webmcp-call` only. Reads `product` as `Chrome/NNN` or `HeadlessChrome/NNN` (`crates/playwright-cli/src/webmcp.rs` `chrome_major_version`).
117
+ - `Slicc.action` with `{phase, kind, ...}`. An optional notification for the slicc panel that is never awaited, so a backend may ignore it or answer with an error (`crates/playwright-cli/src/action.rs` `begin`).
118
+
119
+ The JS `CDPClient` sends only `Target.getTargets` (`src/page.js` `listTargets`) and `Target.attachToTarget` with `flatten: true` (`src/cdp-client.js` `attach`) without a session.
120
+
121
+ ### Browser-level events
122
+
123
+ A backend may omit any of these.
124
+
125
+ - `Target.attachedToTarget` with `sessionId` and `targetInfo.targetId`. Registers the guard session if it comes before the attach reply (`crates/cdp-client/src/cdp.rs` `adopt_guard_attach`).
126
+ - `Target.targetCreated` with `targetInfo` (`crates/cdp-client/src/cdp.rs` `watch`).
127
+ - `Target.targetInfoChanged` with `targetInfo`. A protected `url` marks the tab protected (`crates/cdp-client/src/cdp.rs` `watch`).
128
+ - `Target.targetDestroyed` with `targetId` (`crates/cdp-client/src/cdp.rs` `watch`).
129
+ - `Target.detachedFromTarget` with `sessionId` (`crates/cdp-client/src/cdp.rs` `watch`).
130
+
131
+ ### Guard
132
+
133
+ - Every attach uses `flatten: true`. A non-flat `Target.attachToTarget` or `Target.setAutoAttach` is refused before it is sent (`crates/cdp-client/src/cdp.rs` `admit`), and so is `autoAttach: true` (`crates/cdp-client/src/cdp.rs` `admit`).
134
+ - Before a tab is used, the client attaches a guard session of its own. It is registered from the `Target.attachToTarget` reply (`crates/cdp-client/src/cdp.rs` `touch`) or from the `Target.attachedToTarget` event (`crates/cdp-client/src/cdp.rs` `adopt_guard_attach`), whichever comes first.
135
+ - `Target.setDiscoverTargets`, the attach and the setup steps share one `GUARD_SETUP` budget of 30 s (`crates/cdp-client/src/cdp.rs` `GUARD_SETUP`).
136
+ - The guard's `Fetch.enable` is `{patterns: [{urlPattern: "*", resourceType: "Document", requestStage: "Request"}]}` and decides per paused request (`crates/cdp-client/src/cdp.rs` `touch`). A backend must accept it. A backend's shield may refuse any interception pattern that names a protected origin, and clients never send one: `route` checks each `pattern` and refuses such a route before `Fetch.enable` is sent (`crates/cdp-client/src/fetch.rs` `enable`). Sending one broke bios and the extension on 2026-10-17.
137
+ - Then `Network.enable` and `Network.setBypassServiceWorker` with `{bypass: true}`, which must succeed (`crates/cdp-client/src/cdp.rs` `touch`).
138
+ - `Page.enable` and `Runtime.enable` are optional. Each gets at most `OPTIONAL_STEP`, 10 s of what is left (`crates/cdp-client/src/cdp.rs` `OPTIONAL_STEP`). An error reply, `<method>: <message>`, is ignored (`crates/cdp-client/src/cdp.rs` `touch`). A timeout prints `slicc: guard: <method> timed out; continuing` (`crates/cdp-client/src/cdp.rs` `touch`).
139
+ - Any other failure detaches the guard and marks the tab unguarded, so every later command on it is refused (`abandon`, `crates/cdp-client/src/cdp.rs` `touch`).
140
+
141
+ ### Refused before sending
142
+
143
+ The client refuses these before sending, so a backend needn't implement them (`crates/cdp-client/src/shield.rs` `browser_wide`).
144
+
145
+ - `Target.exposeDevToolsProtocol`.
146
+ - `Target.sendMessageToTarget`. Attach with `flatten: true` instead.
147
+ - `Target.attachToBrowserTarget`.
148
+ - `Tracing.start`.
149
+ - `Extensions.loadUnpacked`.
150
+ - `Network.clearBrowserCookies`.
151
+ - `Storage.clearCookies` unless its `browserContextId` came from this client's `Target.createBrowserContext`.
152
+ - `Browser.resetPermissions` on the same terms.
153
+ - `Browser.setPermission` with no `origin`, on the same terms.
154
+ - `Browser.grantPermissions` with no `origin`, on the same terms.
155
+ - `Network.setRequestInterception`.
156
+ - `Fetch.*` with no `sessionId`.
157
+
158
+ ### Session-level domains
159
+
160
+ Everything else goes over a flat session, with a top-level `sessionId`.
161
+
162
+ - `Page`
163
+ - `Runtime`
164
+ - `DOM`
165
+ - `Input`
166
+ - `Network`
167
+ - `Fetch`
168
+ - `Accessibility`
169
+
170
+ `slicc-cdp-client` also lets a caller `IO.read` a stream that a session reply handed out (`crates/cdp-client/src/cdp.rs` `admit`).
171
+
87
172
  ## Package
88
173
 
89
174
  Node ≥ 24. `npm run lint` runs `slicc-lint`. Releases use semantic-release on `main`. Git `package.json` stays `0.0.0`. The published version is the release tag.
@@ -169,4 +254,4 @@ The `scripts/cert/pr-*` tools prepare an initially non-required PR certification
169
254
 
170
255
  The model reviewer uses the kernel lane's pinned `claude-code-action/base-action`, but keeps `--tools ""` and does not request `--json-schema`: that combination returned no `structured_output` in the live bootstrap proof. Unlike the kernel's filesystem-writing reviewer, this model cannot read or write files or execute commands. Main-owned `pr-review.mjs` parses only the execution receipt's successful final result: one complete JSON object or one fenced `json` block with nothing else. It validates the exact schema and head/commit binding; malformed output, free-text keywords and missing execution are `INCOMPLETE`, never a substitute verdict.
171
256
 
172
- Mandatory bios evidence uses the producer's canary workflow with `packages-update-cdp` and `guard` shards against both unpublished base and candidate packs, labels `base` and `candidate`, and exact artifact hashes. Inputs are prepared without claiming execution. Until the producer's merge SHA is pinned and both guarded smokes execute completely, the bios slot stays `INCOMPLETE`; candidate code is never substituted for the trusted canary runner. Required checks and rulesets need separate rollout approval. The shared guard's accepted residual is: self-guard catches accidental cert-path edits; not enforced against a deliberate rewrite of the workflow.
257
+ Mandatory bios evidence uses `ai-ecoverse/slicc-bios/.github/workflows/canary.yml` pinned to merged commit `4025d6aabc2c06add216183064d81914a171cd64`, with `packages-update-cdp` and `guard` shards, repeat three, against both unpublished base and candidate packs. Main prepares distinct `base` and `candidate` labels and verifies both pack hashes without executing them. The consumer checks the producer's real `result` output: pinned bios ref, caller run, repeat, labelled artifact URL, exact override version/hash and artifact-source status binding, counts and completion arrays. The producer summary has no structured candidate `source` field; its exact artifact/run/hash status and override hash are checked, not an invented field or `ok` alone. Candidate regressions/failures are `FAIL`; missing calls, unfinished shards, skips, flaky results or malformed output are `INCOMPLETE`. Both-failing rows remain visible as flags rather than being mistaken for new regressions. The final record independently revalidates both result documents against its own byte-checked packs. The pin alone never makes the slot pass: the rollout workflow still needs two literal pinned canary calls and complete results. Required checks and rulesets need separate rollout approval. The shared guard's accepted residual is: self-guard catches accidental cert-path edits; not enforced against a deliberate rewrite of the workflow.
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-cdp",
3
- "version": "1.27.7",
3
+ "version": "1.28.0",
4
4
  "description": "SLICC's CDP layer: client, browser API, transports, HAR, and ARIA snapshot",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -68,7 +68,7 @@
68
68
  "chrome": "156.0.8078.4"
69
69
  },
70
70
  "devDependencies": {
71
- "@ai-ecoverse/slicc-kernel": "1.120.0",
71
+ "@ai-ecoverse/slicc-kernel": "1.122.1",
72
72
  "@ai-ecoverse/slicc-shared-web": "1.23.1",
73
73
  "@biomejs/biome": "2.5.15",
74
74
  "lefthook": "2.2.1",