@reclaimprotocol/agent 0.1.29 → 0.1.32
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 +28 -9
- package/lib/consts.d.ts +5 -5
- package/lib/consts.js +7 -7
- package/lib/live/tunnel-watchdog.d.ts +1 -0
- package/lib/live/tunnel-watchdog.js +66 -0
- package/lib/live/tunnel.d.ts +30 -7
- package/lib/live/tunnel.js +217 -40
- package/lib/mcp/api/operations.gen.d.ts +12 -0
- package/lib/mcp/api/operations.gen.js +548 -59
- package/lib/mcp/api/tools.js +27 -5
- package/lib/mcp/instructions.js +23 -32
- package/lib/mcp/remap_errors.js +6 -0
- package/lib/mcp/server.js +2 -8
- package/lib/mcp/start.js +3 -5
- package/lib/mcp/success-response.d.ts +5 -0
- package/lib/mcp/success-response.js +21 -0
- package/lib/mcp/tools/agent/attach.js +9 -66
- package/lib/mcp/tools/agent/build.d.ts +0 -3
- package/lib/mcp/tools/agent/build.js +3 -4
- package/lib/mcp/tools/agent/how-it-works.d.ts +5 -15
- package/lib/mcp/tools/agent/how-it-works.js +9 -22
- package/lib/mcp/tools/agent/live-view.d.ts +1 -15
- package/lib/mcp/tools/agent/live-view.js +71 -96
- package/lib/mcp/tools/agent/propose.js +7 -23
- package/lib/mcp/tools/agent/publish.js +80 -18
- package/lib/mcp/tools/agent/session.d.ts +4 -7
- package/lib/mcp/tools/agent/session.js +8 -23
- package/lib/mcp/tools/verification/result.d.ts +2 -1
- package/lib/mcp/tools/verification/result.js +29 -28
- package/lib/old/client.d.ts +2 -2
- package/lib/old/flag.d.ts +2 -5
- package/lib/old/flag.js +2 -5
- package/lib/old/instructions.d.ts +1 -1
- package/lib/old/instructions.js +1 -1
- package/lib/old/to-register.d.ts +4 -3
- package/lib/old/tools/get-provider-info.js +3 -1
- package/lib/old/tools/publish.js +11 -14
- package/lib/proof/attestor-auth.d.ts +9 -1
- package/lib/proof/attestor-auth.js +15 -2
- package/lib/proof/attestor.d.ts +2 -2
- package/lib/proof/attestor.js +20 -2
- package/lib/proof/pod-prover.js +1 -1
- package/lib/proof/proof-core.d.ts +4 -0
- package/lib/proof/proof-core.js +20 -0
- package/lib/provider/injection-doc.d.ts +3 -2
- package/lib/provider/injection-doc.js +12 -10
- package/lib/provider/matcher.js +19 -15
- package/lib/provider/to-version.d.ts +3 -0
- package/lib/provider/to-version.js +2 -1
- package/package.json +3 -3
- package/skill/SKILL.builder.md +44 -86
- package/skill/SKILL.common.md +38 -22
- package/skill/SKILL.old.md +21 -5
- package/skill/builder-mode.md +62 -4
- package/skill/community-contributions.md +12 -3
- package/skill/hash-validation.md +9 -9
- package/skill/interception.md +39 -46
- package/skill/old-mode.md +25 -0
- package/skill/user-script.md +24 -8
- package/skill/verification-client-integration.md +133 -0
- package/src/consts.ts +9 -7
- package/src/mcp/api/operations.gen.ts +550 -59
- package/src/mcp/api/tools.ts +38 -7
- package/src/mcp/instructions.ts +33 -32
- package/src/mcp/remap_errors.ts +6 -0
- package/src/mcp/server.ts +2 -8
- package/src/mcp/start.ts +3 -5
- package/src/mcp/success-response.ts +26 -0
- package/src/mcp/tools/agent/attach.ts +9 -71
- package/src/mcp/tools/agent/build.ts +4 -7
- package/src/mcp/tools/agent/how-it-works.ts +9 -22
- package/src/mcp/tools/agent/live-view.ts +76 -116
- package/src/mcp/tools/agent/propose.ts +7 -23
- package/src/mcp/tools/agent/publish.ts +89 -18
- package/src/mcp/tools/agent/session.ts +6 -23
- package/src/mcp/tools/verification/result.ts +30 -29
- package/src/old/client.ts +2 -2
- package/src/old/flag.ts +2 -5
- package/src/old/instructions.ts +1 -1
- package/src/old/to-register.ts +4 -3
- package/src/old/tools/get-provider-info.ts +3 -1
- package/src/old/tools/publish.ts +16 -14
- package/src/proof/attestor-auth.ts +18 -1
- package/src/proof/attestor.ts +24 -3
- package/src/proof/pod-prover.ts +1 -1
- package/src/proof/proof-core.ts +28 -0
- package/src/provider/injection-doc.ts +12 -10
- package/src/provider/matcher.ts +25 -17
- package/src/provider/to-version.ts +7 -1
- package/src/live/cloudflared.ts +0 -348
- package/src/live/tunnel.ts +0 -254
package/skill/SKILL.common.md
CHANGED
|
@@ -22,6 +22,12 @@ already names it.
|
|
|
22
22
|
<!-- section: browser -->
|
|
23
23
|
## Choosing a browser
|
|
24
24
|
|
|
25
|
+
## Contents
|
|
26
|
+
|
|
27
|
+
- [Sharing a container browser](#sharing-the-containers-live-view-share_browser_view)
|
|
28
|
+
- [Container lifetime and isolation](#how-containers-are-shared-and-when-they-close)
|
|
29
|
+
- [Container startup problems](#when-the-container-will-not-start)
|
|
30
|
+
|
|
25
31
|
**Ask one question first, before you list anything:**
|
|
26
32
|
|
|
27
33
|
> Will you be doing this yourself, or does someone else need to sign in — the
|
|
@@ -92,8 +98,8 @@ persist it. If a `liveViewUrl` comes back, share it full and verbatim.
|
|
|
92
98
|
|
|
93
99
|
A `container` browser serves its own viewer on loopback, so the developer can
|
|
94
100
|
open it the moment `attach_browser` returns. `share_browser_view` puts that same
|
|
95
|
-
viewer behind a public HTTPS URL through a cloudflared quick tunnel
|
|
96
|
-
the person who has to act is not at that machine: a login or 2FA only they can
|
|
101
|
+
viewer behind a public HTTPS URL through a cloudflared quick tunnel that you
|
|
102
|
+
run — for when the person who has to act is not at that machine: a login or 2FA only they can
|
|
97
103
|
complete, or a colleague watching a capture.
|
|
98
104
|
|
|
99
105
|
**Offer it whenever a login is coming and the developer is not the one holding
|
|
@@ -104,8 +110,17 @@ Ask plainly:
|
|
|
104
110
|
> whoever holds the login — they can watch and click in it, including from a
|
|
105
111
|
> phone.
|
|
106
112
|
|
|
107
|
-
If they say yes
|
|
108
|
-
|
|
113
|
+
If they say yes:
|
|
114
|
+
|
|
115
|
+
1. Call `share_browser_view` with no arguments. It returns the viewer `port` and
|
|
116
|
+
the `command` (`cloudflared tunnel --url http://localhost:<port>`). The MCP
|
|
117
|
+
server does not run cloudflared.
|
|
118
|
+
2. Run `command` yourself in the background. If `cloudflared` is not installed,
|
|
119
|
+
ask the developer to install it; do not install it without their approval.
|
|
120
|
+
3. Read its output for the `https://<words>.trycloudflare.com` URL. Never guess
|
|
121
|
+
or reconstruct the hostname.
|
|
122
|
+
4. Call `share_browser_view({ publicUrl })` with that URL. **Relay the returned
|
|
123
|
+
`url` verbatim, on its own line.** It includes `liveview.html?magnify=1`.
|
|
109
124
|
|
|
110
125
|
- **`container` is the only mode this applies to.** `builder` returns a hosted
|
|
111
126
|
`liveViewUrl` from `attach_browser` — relay that instead, full and verbatim.
|
|
@@ -123,24 +138,16 @@ verbatim, on its own line.** It includes `liveview.html?magnify=1`.
|
|
|
123
138
|
- **Opening it on a phone lays the page out for that phone**, with touch,
|
|
124
139
|
pinch-zoom and the soft keyboard. That is the reason to reach for `container`
|
|
125
140
|
when a site only works on mobile.
|
|
126
|
-
- **
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
- **
|
|
130
|
-
|
|
131
|
-
few seconds, and reload; don't start a second tunnel while it propagates.
|
|
132
|
-
`cloudflaredLog` contains bounded diagnostic output. If it still fails after
|
|
133
|
-
60 seconds, call `stop_browser_view`, then retry `share_browser_view` once.
|
|
134
|
-
- **cloudflared is handled for you.** An existing install on PATH wins;
|
|
135
|
-
otherwise it's fetched once into `~/.reclaim/bin` on the first share, never at
|
|
136
|
-
install time. Tell the developer when the download starts.
|
|
137
|
-
`RECLAIM_CLOUDFLARED_PATH` points at their own copy instead.
|
|
141
|
+
- **Stop the cloudflared process you started as soon as they're done.** The
|
|
142
|
+
browser keeps running. `dispose_browser` and `reset_session` stop the
|
|
143
|
+
container itself, but not your cloudflared process.
|
|
144
|
+
- **Expose only the viewer port** that `share_browser_view` returns, never the
|
|
145
|
+
browser's CDP port.
|
|
138
146
|
|
|
139
147
|
### How containers are shared, and when they close
|
|
140
148
|
|
|
141
|
-
- **Closing the agent releases the browser.** The server stops the container
|
|
142
|
-
|
|
143
|
-
session that made it. `dispose_browser` does the same on demand.
|
|
149
|
+
- **Closing the agent releases the browser.** The server stops the container
|
|
150
|
+
when its connection drops. `dispose_browser` does the same on demand.
|
|
144
151
|
- **Re-attaching in one session reuses the same browser** — under a second,
|
|
145
152
|
rather than the twenty a fresh one costs — so whatever it is signed into is
|
|
146
153
|
still there.
|
|
@@ -151,9 +158,10 @@ verbatim, on its own line.** It includes `liveview.html?magnify=1`.
|
|
|
151
158
|
own profile, and starts out signed in to nothing.
|
|
152
159
|
- **Four at once is the ceiling**, because each is about 2 GB of RAM. Past that,
|
|
153
160
|
`attach_browser` says so and points at `dedicated`.
|
|
154
|
-
- **A crash cannot strand one for long.** A killed session runs no
|
|
155
|
-
the next `container` attach removes any container whose owning
|
|
156
|
-
|
|
161
|
+
- **A crash cannot strand one for long.** A killed session runs no normal
|
|
162
|
+
cleanup, so the next `container` attach removes any container whose owning
|
|
163
|
+
process is gone. Resources belonging to a live session are
|
|
164
|
+
never touched.
|
|
157
165
|
|
|
158
166
|
### When the container will not start
|
|
159
167
|
|
|
@@ -270,6 +278,10 @@ anything the developer wouldn't post publicly), put the four options to them.
|
|
|
270
278
|
`hash` or capture a request whose URL doesn't carry it.
|
|
271
279
|
3. Never pass `hash` for a free-form target (unicode / spaces / punctuation).
|
|
272
280
|
|
|
281
|
+
**Disambiguate repeated JSON values.** `propose_provider` rejects a target
|
|
282
|
+
found at multiple JSON paths instead of guessing which field the user meant.
|
|
283
|
+
Choose a target that identifies one field.
|
|
284
|
+
|
|
273
285
|
`propose_provider` throws a clean error on all three — retrying the same call
|
|
274
286
|
won't help.
|
|
275
287
|
|
|
@@ -297,6 +309,8 @@ won't help.
|
|
|
297
309
|
`propose_provider` again with different inputs instead.
|
|
298
310
|
|
|
299
311
|
<!-- section: secrets -->
|
|
312
|
+
### Protect secret values
|
|
313
|
+
|
|
300
314
|
**Marking a value secret.** Name ANY param with `SECRET` anywhere in the key
|
|
301
315
|
(case-insensitive) — a bare `{{SECRET_x}}` as much as a consumer-supplied
|
|
302
316
|
`{{%CTX%SECRET_apiKey}}` — and it routes to `secretParams.paramValues`
|
|
@@ -323,6 +337,8 @@ captured secret *header* whose value also sits in the URL, which is already
|
|
|
323
337
|
known and so gets checked at draft time (`assertNoSecretUrlConflict`).
|
|
324
338
|
|
|
325
339
|
<!-- section: no-rename-param -->
|
|
340
|
+
### Hide internal fields from claimant UI
|
|
341
|
+
|
|
326
342
|
**Keep internal claim-construction fields out of claimant-facing UI.** When a
|
|
327
343
|
named regex group or `{{parameter}}` only helps construct another claim request,
|
|
328
344
|
consider an internal prefix:
|
package/skill/SKILL.old.md
CHANGED
|
@@ -109,8 +109,18 @@ it. Don't assume `authenticate_builder` fixes it.
|
|
|
109
109
|
<!-- topic: draft -->
|
|
110
110
|
## Draft the provider
|
|
111
111
|
|
|
112
|
+
## Contents
|
|
113
|
+
|
|
114
|
+
- [Choose a privacy mode](#choose-a-privacy-mode)
|
|
115
|
+
- [Draft and inspect the request](#draft-and-inspect-the-request)
|
|
116
|
+
- [Preserve the canonical shape](#preserve-the-canonical-shape)
|
|
117
|
+
|
|
118
|
+
### Choose a privacy mode
|
|
119
|
+
|
|
112
120
|
<!-- common: oprf -->
|
|
113
121
|
|
|
122
|
+
### Draft and inspect the request
|
|
123
|
+
|
|
114
124
|
**Call `propose_provider`.** It returns a **`draftId`** — the handle for
|
|
115
125
|
`replay_request` and `run_proof` — plus the secret-free `provider` and
|
|
116
126
|
`secretRefs`. The recipe **and the captured secret values** live server-side
|
|
@@ -171,6 +181,8 @@ field they control. The synthesizer does this for you.
|
|
|
171
181
|
With `hash: 'oprf-raw'`, the redaction gains `"hash": "oprf-raw"`. Nothing else
|
|
172
182
|
changes.
|
|
173
183
|
|
|
184
|
+
### Preserve the canonical shape
|
|
185
|
+
|
|
174
186
|
<!-- common: rewrite-shape-block -->
|
|
175
187
|
|
|
176
188
|
<!-- topic: params -->
|
|
@@ -271,7 +283,7 @@ Call `create_provider_version_from_capture`:
|
|
|
271
283
|
- **Login/navigation-gated data:** supply `customInjection` (plain page JS) and
|
|
272
284
|
`allowedInjectedRequestData` (extra requests the script may fire).
|
|
273
285
|
→ topic `user-script`. Before populating `allowedInjectedRequestData` for a
|
|
274
|
-
`
|
|
286
|
+
`verifyRequestProof({ providerId })` use case, read topic `hash-validation`.
|
|
275
287
|
|
|
276
288
|
**Ownership — you can only add a version to a provider YOU own.** The
|
|
277
289
|
`providerId` must come from `get_me_providers`. Versioning a public provider you
|
|
@@ -306,8 +318,10 @@ applies them.
|
|
|
306
318
|
would fetch. Reads the public production SDK backend directly, no auth.
|
|
307
319
|
|
|
308
320
|
There's no create-then-version step and no org / public-review workflow here.
|
|
309
|
-
When done, tell the developer the version is live
|
|
310
|
-
|
|
321
|
+
When done, tell the developer the version is live, then ask once how they want
|
|
322
|
+
to use it — try it now, integrate it into an existing backend or frontend, or
|
|
323
|
+
create a new app — unless they already said (see "Using a provider" in the
|
|
324
|
+
server instructions).
|
|
311
325
|
|
|
312
326
|
**If the response includes `_notes` for an attached browser, follow them for an
|
|
313
327
|
optional authenticated-state retest.** Only when its profile is still signed in,
|
|
@@ -365,8 +379,10 @@ turn
|
|
|
365
379
|
document replay off and keep the interceptor (`disableRequestReplay: true`, or
|
|
366
380
|
`isDocumentRequestReplayEnabled: false` on builder) — often that alone is what
|
|
367
381
|
breaks the page, and it's the smallest change. Only if that doesn't help, turn
|
|
368
|
-
interception off
|
|
369
|
-
`interceptorOptions`).
|
|
382
|
+
interception off temporarily to confirm it is the cause (`injectionType: NONE`,
|
|
383
|
+
or omit `interceptorOptions`). If that fixes the provider, keep interception
|
|
384
|
+
off and replace intercepted claims with `window.Reclaim.requestClaim`. Full
|
|
385
|
+
checklist and remedies: topic `interception`.
|
|
370
386
|
|
|
371
387
|
**A session stalled, matched nothing, or produced no claim.** Read it with
|
|
372
388
|
two tools, coarse to fine. `session_analytics_logs` returns the milestone
|
package/skill/builder-mode.md
CHANGED
|
@@ -6,10 +6,55 @@ authoring tools.
|
|
|
6
6
|
|
|
7
7
|
## Claimant-facing Builder sessions
|
|
8
8
|
|
|
9
|
-
This integration is separate from provider authoring.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
This integration is separate from provider authoring.
|
|
10
|
+
|
|
11
|
+
**Using a provider.** A provider found with `providers`, `discover_resolve`, or
|
|
12
|
+
another lookup is published and usable as-is. Don't capture, `replay_request`,
|
|
13
|
+
or `run_proof` against it unless the developer asks you to check or test it.
|
|
14
|
+
Before using a provider, found or just created, ask once whether they just want
|
|
15
|
+
to try it or want it in an app (skip this if they already said):
|
|
16
|
+
|
|
17
|
+
> Want to (1) just try it right now, (2) integrate it into an existing backend
|
|
18
|
+
> or frontend (this directory or another path), or (3) create a new app for it?
|
|
19
|
+
|
|
20
|
+
- **Just try it:** no app, callback, or client package. Create the session the
|
|
21
|
+
HTTP way (`create_verification_session`, i.e. `POST /verifications/sessions`
|
|
22
|
+
with the org secret as `Authorization: Bearer`; `issue_org_token` if there is
|
|
23
|
+
none), give the developer `verificationUrl` to open, then check the session
|
|
24
|
+
yourself (`get_verification_session`) until it is terminal and report the
|
|
25
|
+
outcome with `get_verification_result`.
|
|
26
|
+
- **Integrate, or new app:** follow the setup below in the path they named.
|
|
27
|
+
|
|
28
|
+
**Prefer the HTTP API over `@reclaimprotocol/client`** for every option:
|
|
29
|
+
create sessions with `POST /verifications/sessions`, open `verificationUrl`,
|
|
30
|
+
poll `GET /verifications/sessions/{sessionId}`, and take the result on the
|
|
31
|
+
callback. Use the client package only when the developer asks for it — the one
|
|
32
|
+
exception is `results.receive`, to verify the result on your callback.
|
|
33
|
+
|
|
34
|
+
When integrating into an app, read `how_it_works({ topic: "integration" })`,
|
|
35
|
+
then configure the organization with generated tools (`list_orgs`,
|
|
36
|
+
`create_org`, `create_org_callback_subscription`, and owner-only
|
|
37
|
+
`issue_org_token`) and edit the app's frontend and backend with the coding
|
|
38
|
+
agent's file tools. The guide
|
|
39
|
+
covers the HTTP session workflow, exact `api=2` boundary, result
|
|
40
|
+
verification, request-proof contract, and optional TEE binding. A URL without
|
|
41
|
+
`api=2` stays on its existing legacy path.
|
|
42
|
+
|
|
43
|
+
**Existing `@reclaimprotocol/js-sdk` projects.** If the app's `package.json`
|
|
44
|
+
depends on `@reclaimprotocol/js-sdk`, ask the developer before doing anything
|
|
45
|
+
else:
|
|
46
|
+
|
|
47
|
+
> This project uses `@reclaimprotocol/js-sdk`. Keep it (I switch this MCP
|
|
48
|
+
> server to legacy devtools mode), or migrate to the Builder integration
|
|
49
|
+
> (Builder HTTP API)?
|
|
50
|
+
|
|
51
|
+
- **Keep js-sdk:** call `set_devtools_mode({ mode: "old" })`, then tell them to
|
|
52
|
+
restart or reconnect the MCP server; the switch applies on the next start. An
|
|
53
|
+
explicit `USE_OLD_DEVTOOLS` env var overrides it. After the restart, read
|
|
54
|
+
`get_js_sdk_integration_guide`.
|
|
55
|
+
- **Migrate:** stay in Builder mode. Follow `how_it_works({ topic:
|
|
56
|
+
"integration" })` to replace `@reclaimprotocol/js-sdk` with the Builder
|
|
57
|
+
HTTP session flow and update the app's code.
|
|
13
58
|
|
|
14
59
|
**A `provider` is a recipe for extracting a data point from a site. A
|
|
15
60
|
`verification` is an end-user session that proves a data point using one. Never
|
|
@@ -20,6 +65,19 @@ configuration change creates a new semantic version. Default to a patch bump;
|
|
|
20
65
|
use a major/minor bump or exact higher version when the user directs it. Never
|
|
21
66
|
use an in-place provider-version update or archive tool.
|
|
22
67
|
|
|
68
|
+
## Evidence contract
|
|
69
|
+
|
|
70
|
+
Tool results are the source of truth. Never say that a browser attached, a user
|
|
71
|
+
logged in, a request was captured, a proof passed, or a version was created or
|
|
72
|
+
published unless the corresponding tool result says it happened. A planned tool
|
|
73
|
+
call is not a completed action.
|
|
74
|
+
|
|
75
|
+
Treat every ID, semantic version, URL, request value, and error as opaque: copy
|
|
76
|
+
it from the latest tool result exactly. Never invent, autocomplete, reconstruct,
|
|
77
|
+
shorten, or reuse one from memory. When state is missing or ambiguous, inspect
|
|
78
|
+
it with the relevant get/list/status tool or call `how_it_works` before
|
|
79
|
+
answering. State uncertainty plainly instead of guessing.
|
|
80
|
+
|
|
23
81
|
**Use the guide as needed.** Call `how_it_works({})` for its topic index, then
|
|
24
82
|
fetch only the topic relevant to the next tool call.
|
|
25
83
|
|
|
@@ -5,6 +5,14 @@ enabled. It is a topic guide for `SKILL.builder.md`, not a standalone skill.
|
|
|
5
5
|
The app workflow and volunteer-facing contract are documented in
|
|
6
6
|
`packages/app/docs/community-contributions.md`.
|
|
7
7
|
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
10
|
+
- [Required sequence](#required-sequence)
|
|
11
|
+
- [Generalization gates](#generalization-gates)
|
|
12
|
+
- [Asynchronous attempts](#asynchronous-attempts)
|
|
13
|
+
- [Stop conditions](#stop-conditions)
|
|
14
|
+
- [Uber driver example](#uber-driver-example)
|
|
15
|
+
|
|
8
16
|
## Required sequence
|
|
9
17
|
|
|
10
18
|
Follow this order. Keep the attempt ID, provider ID, field key, and candidate
|
|
@@ -60,9 +68,10 @@ attempt.
|
|
|
60
68
|
|
|
61
69
|
## Asynchronous attempts
|
|
62
70
|
|
|
63
|
-
Treat a reconnect at the active verification URL as the same attempt. Read the
|
|
64
|
-
before taking another action. Do not start a second browser
|
|
65
|
-
waiting or retryable attempt. On a terminal failure, preserve
|
|
71
|
+
Treat a reconnect at the active verification URL as the same attempt. Read the
|
|
72
|
+
latest valid state before taking another action. Do not start a second browser
|
|
73
|
+
session for a waiting or retryable attempt. On a terminal failure, preserve
|
|
74
|
+
the history and
|
|
66
75
|
stop until a maintainer changes the requirement or explicitly requests a new
|
|
67
76
|
attempt. Use absolute event timestamps and server-side status; do not infer
|
|
68
77
|
state from the volunteer's timezone or a closed tab.
|
package/skill/hash-validation.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Spec hashing: `bodySniff` and `
|
|
1
|
+
# Spec hashing: `bodySniff` and `verifyRequestProof({ providerId })`
|
|
2
2
|
|
|
3
3
|
## Contents
|
|
4
4
|
|
|
5
5
|
- The one fact everything follows from
|
|
6
6
|
- `bodySniff` — when to enable it, how to template a partly dynamic body
|
|
7
|
-
- How `
|
|
7
|
+
- How `verifyRequestProof(proof, { providerId })` gates a proof
|
|
8
8
|
- Why `url` is hashed verbatim, and when that makes
|
|
9
9
|
`allowedJsRequests`/`allowedInjectedRequestData` unusable
|
|
10
10
|
- Optional fields, and the `dangerouslyDisableContentValidation` fallback
|
|
@@ -83,7 +83,7 @@ match (`(.*)`, including embedded delimiters) instead of the default non-greedy
|
|
|
83
83
|
body. Strictly a fallback — nothing about the body's structure is pinned by the
|
|
84
84
|
hash anymore (any body at all hashes the same).
|
|
85
85
|
|
|
86
|
-
## How `
|
|
86
|
+
## How `verifyRequestProof(proof, { providerId })` gates
|
|
87
87
|
|
|
88
88
|
Traced from `@reclaimprotocol/js-sdk`
|
|
89
89
|
(`src/utils/proofValidationUtils.ts`, `src/utils/providerUtils.ts`,
|
|
@@ -104,7 +104,7 @@ Traced from `@reclaimprotocol/js-sdk`
|
|
|
104
104
|
present or absent. **That expansion only touches match/redaction pairs, never
|
|
105
105
|
`url`.**
|
|
106
106
|
4. `assertValidProofsByHash` requires the real proof's hash to equal exactly ONE
|
|
107
|
-
expected hash. No match → `
|
|
107
|
+
expected hash. No match → `verifyRequestProof` rejects, even for a perfectly valid,
|
|
108
108
|
correctly signed proof whose `responseMatches` are 100% right.
|
|
109
109
|
|
|
110
110
|
### `url` is hashed VERBATIM — zero template/regex resolution
|
|
@@ -116,7 +116,7 @@ touches `url`. `urlType` is consumed by a different validation path entirely
|
|
|
116
116
|
(matching a live request against the spec at capture time), never by this hash.
|
|
117
117
|
|
|
118
118
|
**So, before populating `allowedInjectedRequestData`/`allowedJsRequests` for a
|
|
119
|
-
`
|
|
119
|
+
`verifyRequestProof({ providerId })` use case:** if the real captured URL contains ANY
|
|
120
120
|
component that varies between two otherwise-identical sessions — a tracking
|
|
121
121
|
nonce, a CSRF token, a cache-busting timestamp, a per-request trace id — the
|
|
122
122
|
hash from your declared spec can NEVER equal any real future proof's, no matter
|
|
@@ -126,14 +126,14 @@ regenerates `_x_id`, `_x_csid` and `fp` on every API call, so a captured
|
|
|
126
126
|
|
|
127
127
|
Populating the field for such a provider is **actively worse than leaving it
|
|
128
128
|
empty**: it converts "no provider-hash check was attempted" into
|
|
129
|
-
"`
|
|
129
|
+
"`verifyRequestProof({ providerId })` rejects every real proof, unconditionally."
|
|
130
130
|
|
|
131
131
|
**Verify first:** capture the same endpoint twice in two separate sessions
|
|
132
132
|
(ideally two users, or the same user on two days) and diff the full URL byte for
|
|
133
133
|
byte.
|
|
134
134
|
|
|
135
135
|
- Identical every time → safe to populate (`urlType: CONSTANT`, literal URL).
|
|
136
|
-
- Not identical → do not populate it expecting it to gate `
|
|
136
|
+
- Not identical → do not populate it expecting it to gate `verifyRequestProof`. No
|
|
137
137
|
amount of care with `responseMatches`/`responseRedactions`/`body` fixes it on
|
|
138
138
|
either backend; it's a property of the hashing itself.
|
|
139
139
|
|
|
@@ -155,7 +155,7 @@ compatibility rule does not pair the lists generally.
|
|
|
155
155
|
|
|
156
156
|
Whether it's an unstable `url`, an unmarked optional field, or any other
|
|
157
157
|
persistent mismatch, the way out is on the VERIFYING side:
|
|
158
|
-
`
|
|
158
|
+
`verifyRequestProof(proof, { dangerouslyDisableContentValidation: true })`. That skips
|
|
159
159
|
steps 1–4 entirely and trusts only the attestor's cryptographic signature; it
|
|
160
160
|
does NOT check that the proof's url/method/body/matches/redactions match
|
|
161
161
|
anything you declared. A caller-supplied `{ hashes: [...] }` computed some other
|
|
@@ -170,4 +170,4 @@ spec says.
|
|
|
170
170
|
- `user-script` — `allowedJsRequests` / `allowedInjectedRequestData`, the fields
|
|
171
171
|
this page's `url` constraint applies to.
|
|
172
172
|
- `prove` — `run_proof` and diagnosing a proof that fails before it ever reaches
|
|
173
|
-
`
|
|
173
|
+
`verifyRequestProof`.
|
package/skill/interception.md
CHANGED
|
@@ -32,11 +32,11 @@ parameter.
|
|
|
32
32
|
**`HAWKEYE`, not `NONE`** — harmless for the standard flow, since with no
|
|
33
33
|
interceptor script installed nothing calls `addResponseMiddleware`.
|
|
34
34
|
`create_provider_version_from_capture` exposes it as an author-settable input
|
|
35
|
-
with no forced default: omit it and the backend default applies
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
with no forced default: omit it and the backend default applies. Use `NONE`
|
|
36
|
+
only for a controlled diagnostic after observed behavior suggests interception
|
|
37
|
+
is breaking the provider. When passed, the value is sent on both register and
|
|
38
|
+
add-version, and the tool's always-on add-version follow-up (see
|
|
39
|
+
`disableRequestReplay` below) reapplies it.
|
|
40
40
|
- **builder:** `webSettings.inapp.interceptorOptions.interceptorType`, one of
|
|
41
41
|
`HAWKEYE | MSWJS | CDP`. There is no `NONE` here — **omit
|
|
42
42
|
`interceptorOptions` entirely to disable interception**, and the
|
|
@@ -91,16 +91,16 @@ strictest row below as the answer.
|
|
|
91
91
|
| `portals` | Browser level, over CDP | No |
|
|
92
92
|
| `builder` | Server-side CDP, out of band | No |
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
`
|
|
96
|
-
|
|
97
|
-
first.
|
|
94
|
+
A session created with no `verificationClientUrl` runs in `portals`.
|
|
95
|
+
`builder` is the row for authoring and for Builder's own "Test this provider"
|
|
96
|
+
runs. Reaching it means you are diagnosing the authoring tool, not what the
|
|
97
|
+
author's users will hit — which is exactly why you ask first.
|
|
98
98
|
|
|
99
99
|
The `reclaim-browser-extension` row supports both modes. The extension selects
|
|
100
|
-
the Builder
|
|
100
|
+
the Builder API only for the exact `api=2` query and keeps its legacy
|
|
101
101
|
interception, `init` / `fromJsonString`, and direct-callback path for missing or
|
|
102
|
-
unknown API versions. In Builder mode,
|
|
103
|
-
attestor authorization; the extension still forwards raw
|
|
102
|
+
unknown API versions. In Builder mode, Builder supplies the session-bound
|
|
103
|
+
attestor authorization; the extension still forwards raw proofs and
|
|
104
104
|
does not perform client-side `allowedJsRequests` validation.
|
|
105
105
|
|
|
106
106
|
**If production is only `portals` or `builder`, stop here and look elsewhere.**
|
|
@@ -138,13 +138,15 @@ Copy this checklist and work down it:
|
|
|
138
138
|
- [ ] 2. **Retry the verification.** Reload, then sign in as a real end-user
|
|
139
139
|
would. Works now → stop here. This is the cheapest fix and you keep the
|
|
140
140
|
interceptor.
|
|
141
|
-
- [ ] 3. **Still broken?
|
|
141
|
+
- [ ] 3. **Still broken? Temporarily turn interception off to test it.**
|
|
142
|
+
Old-devtools:
|
|
142
143
|
publish with `injectionType: NONE`. Builder: omit `interceptorOptions`
|
|
143
144
|
entirely — there is no `NONE` there, and omitting it disables interception.
|
|
144
145
|
- [ ] 4. **Retry again, and compare.** Loads and signs in now → interception
|
|
145
|
-
itself was the cause;
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
itself was the cause; keep interception disabled and replace the
|
|
147
|
+
intercepted claim path with `window.Reclaim.requestClaim`. Still broken →
|
|
148
|
+
restore the previous interception setting and investigate the recipe
|
|
149
|
+
(topic `prove`) or browser (topic `browser`).
|
|
148
150
|
|
|
149
151
|
If step 2 fixed it, you are done — the interceptor stays and only the document
|
|
150
152
|
request stops being replayed. Note that under `CDP` the flag is inert, so a
|
|
@@ -152,35 +154,26 @@ request stops being replayed. Note that under `CDP` the flag is inert, so a
|
|
|
152
154
|
|
|
153
155
|
### Remedies
|
|
154
156
|
|
|
155
|
-
If
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
`allowedJsRequests` / `allowedInjectedRequestData` for result verification,
|
|
176
|
-
and read topic `hash-validation` first — a session-unique URL there makes
|
|
177
|
-
`verifyProof({ providerId })` reject every real proof.
|
|
178
|
-
|
|
179
|
-
⚠️ **Remedy 3 needs a client that consumes `window.Reclaim`.** The InApp
|
|
180
|
-
SDK, browser extension, portals, and Builder's built-in client do. The built-in
|
|
181
|
-
client uses the page-supplied request to generate the proof; verification of
|
|
182
|
-
its recipe hash belongs to `verifyProof`/`verifyResultFull`. See topic
|
|
183
|
-
`user-script`.
|
|
157
|
+
If step 3 confirmed interception is the cause, keep it disabled. Most providers
|
|
158
|
+
can use the standard capture-and-replay flow without an interceptor. Where the
|
|
159
|
+
data only exists in a live page, replace `addResponseMiddleware` with a user
|
|
160
|
+
script that navigates to the page holding the value and calls
|
|
161
|
+
`window.Reclaim.requestClaim`. Declare anything the script fires in
|
|
162
|
+
`allowedJsRequests` / `allowedInjectedRequestData` for result verification, and
|
|
163
|
+
read topic `hash-validation` first — a session-unique URL there makes
|
|
164
|
+
`verifyRequestProof({ providerId })` reject every real proof.
|
|
165
|
+
|
|
166
|
+
If direct `requestClaim` does not fit the client or provider, a different
|
|
167
|
+
interceptor is a fallback, not the first recommendation. The mechanisms patch
|
|
168
|
+
the page differently: old-devtools supports `HAWKEYE`, `MSWJS`, `XHOOK`, and
|
|
169
|
+
`CDP`; Builder supports `HAWKEYE`, `MSWJS`, and `CDP`. `CDP` operates below the
|
|
170
|
+
page's JavaScript but is not supported by every in-page client.
|
|
171
|
+
|
|
172
|
+
⚠️ **The direct-claim remedy needs a client that consumes `window.Reclaim`.**
|
|
173
|
+
The InApp SDK, browser extension, portals, and Builder's built-in client do. The
|
|
174
|
+
built-in client uses the page-supplied request to generate the proof;
|
|
175
|
+
verification of its recipe hash belongs to `verifyRequestProof`/`verifyResultFull`.
|
|
176
|
+
See topic `user-script`.
|
|
184
177
|
|
|
185
178
|
## The document-replay flag
|
|
186
179
|
|
|
@@ -244,6 +237,6 @@ oversight.
|
|
|
244
237
|
- `user-script` — what the script itself does with intercepted traffic, and how
|
|
245
238
|
Builder's built-in client handles `window.Reclaim.requestClaim`.
|
|
246
239
|
- `hash-validation` — declaring script-fired requests without breaking
|
|
247
|
-
`
|
|
240
|
+
`verifyRequestProof({ providerId })`.
|
|
248
241
|
- `browser` — the modes with a live view (`container`, `builder`), for handing
|
|
249
242
|
a stuck sign-in to a human.
|
package/skill/old-mode.md
CHANGED
|
@@ -11,6 +11,19 @@ creates a new semantic version. Default to a patch bump; use a major/minor bump
|
|
|
11
11
|
or exact higher version when the user directs it. Never edit an existing
|
|
12
12
|
version.
|
|
13
13
|
|
|
14
|
+
## Evidence contract
|
|
15
|
+
|
|
16
|
+
Tool results are the source of truth. Never say that a browser attached, a user
|
|
17
|
+
logged in, a request was captured, a proof passed, or a version was created or
|
|
18
|
+
published unless the corresponding tool result says it happened. A planned tool
|
|
19
|
+
call is not a completed action.
|
|
20
|
+
|
|
21
|
+
Treat every ID, semantic version, URL, request value, and error as opaque: copy
|
|
22
|
+
it from the latest tool result exactly. Never invent, autocomplete, reconstruct,
|
|
23
|
+
shorten, or reuse one from memory. When state is missing or ambiguous, inspect
|
|
24
|
+
it with the relevant get/list/status tool or call `how_it_works` before
|
|
25
|
+
answering. State uncertainty plainly instead of guessing.
|
|
26
|
+
|
|
14
27
|
**Use the guide as needed.** Call `how_it_works({})` for its topic index, then
|
|
15
28
|
fetch only the topic relevant to the next tool call.
|
|
16
29
|
|
|
@@ -42,6 +55,18 @@ existing provider instead; you can only version a provider you own. For a
|
|
|
42
55
|
multi-request provider pass `providers: [draftA, draftB, …]` so each becomes a
|
|
43
56
|
parallel `requestData` entry on the one version.
|
|
44
57
|
|
|
58
|
+
**Using a provider.** A provider found with `get_me_providers` or
|
|
59
|
+
`get_provider_info` is published and usable as-is. Don't capture,
|
|
60
|
+
`replay_request`, or `run_proof` against it unless the developer asks you to
|
|
61
|
+
check or test it. Before using a provider, found or just created, ask once how
|
|
62
|
+
they want to use it (skip this if they already said):
|
|
63
|
+
|
|
64
|
+
> Want to (1) try it right now here, (2) integrate it into an existing backend
|
|
65
|
+
> or frontend (this directory or another path), or (3) create a new app for it?
|
|
66
|
+
|
|
67
|
+
Try it now → `scaffold_reclaim_demo_server` with its `providerId`. Integrate,
|
|
68
|
+
or new app → `get_js_sdk_integration_guide`, then work in the path they named.
|
|
69
|
+
|
|
45
70
|
**Two independent auth systems — don't confuse them.** `reclaim_authenticate`
|
|
46
71
|
authorizes everything in this mode; its Firebase token is short-lived (~1h), so
|
|
47
72
|
an auth error on publish or `get_me_providers` means re-run it.
|
package/skill/user-script.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A provider can inject **plain JavaScript** that runs in the page before every
|
|
4
4
|
page load. Builder stores it as `webSettings.jsUserScripts`; old-devtools stores
|
|
5
|
-
it as `customInjection`.
|
|
5
|
+
it as `customInjection`. The injection timing and purpose match; available
|
|
6
|
+
`window.Reclaim` bridge methods depend on the Verification Client.
|
|
6
7
|
|
|
7
8
|
## What the script is for
|
|
8
9
|
|
|
@@ -54,7 +55,7 @@ browser APIs above for that.
|
|
|
54
55
|
|
|
55
56
|
The Builder verification client drains `window.Reclaim.requestClaim` through
|
|
56
57
|
CDP and uses the page-supplied request to generate the proof. It does not
|
|
57
|
-
authorize the request against `allowedJsRequests`; `
|
|
58
|
+
authorize the request against `allowedJsRequests`; `verifyRequestProof`/
|
|
58
59
|
`verifyResultFull` validates the resulting proof's recipe hash. The built-in
|
|
59
60
|
client doesn't deliver traffic to
|
|
60
61
|
`reclaimInterceptor.addResponseMiddleware`, so response middleware remains
|
|
@@ -69,24 +70,39 @@ them. Do not read cookies in the script or copy a `Cookie` value into public
|
|
|
69
70
|
parameters; the client supplies it as private claim input.
|
|
70
71
|
|
|
71
72
|
Don't reach for it by default. When an edge case genuinely requires it, consult
|
|
72
|
-
the
|
|
73
|
-
|
|
73
|
+
the [provider web-script API types](https://github.com/reclaimprotocol/provider-web-script-dev/blob/main/src/support/env.d.ts)
|
|
74
|
+
rather than guessing.
|
|
75
|
+
|
|
76
|
+
### Portal-only request APIs
|
|
77
|
+
|
|
78
|
+
The portal client also exposes two methods that the built-in Builder client,
|
|
79
|
+
in-app SDK, and browser extension do not:
|
|
80
|
+
|
|
81
|
+
- `Reclaim.refetch(request)` sends a bounded request through the portal worker.
|
|
82
|
+
- `Reclaim.browserRequest(actionId, input)` runs a declared same-origin action
|
|
83
|
+
in an isolated page that shares the portal browser's cookie jar. Declare its
|
|
84
|
+
action in `browserRequestActions` when creating the provider version. The
|
|
85
|
+
declaration can set the isolated page's User-Agent or omit a fetch action's
|
|
86
|
+
automatic Origin header when the target requires it.
|
|
87
|
+
|
|
88
|
+
Use them only when the provider is explicitly portal-only. For the current
|
|
89
|
+
client matrix, see `docs/verification-client-capabilities.md` in Builder.
|
|
74
90
|
|
|
75
91
|
## Declaring the requests the script fires
|
|
76
92
|
|
|
77
93
|
Requests the script triggers beyond the proven one (for example, pagination) are
|
|
78
94
|
declared as `allowedJsRequests` (Builder) / `allowedInjectedRequestData`
|
|
79
|
-
(old-devtools) for `
|
|
95
|
+
(old-devtools) for `verifyRequestProof`/`verifyResultFull`. They express the same
|
|
80
96
|
policy with different field names.
|
|
81
97
|
|
|
82
|
-
⚠️ **Before populating them to gate `
|
|
98
|
+
⚠️ **Before populating them to gate `verifyRequestProof(proof, { providerId })`**, read
|
|
83
99
|
topic `hash-validation` — the declared `url` is hashed VERBATIM, so a
|
|
84
|
-
session-unique URL there makes `
|
|
100
|
+
session-unique URL there makes `verifyRequestProof` reject every real proof. Leaving
|
|
85
101
|
the field empty is better than populating it wrong.
|
|
86
102
|
|
|
87
103
|
## Related topics
|
|
88
104
|
|
|
89
105
|
- `interception` — `injectionType`/`interceptorType`, live interception, and the
|
|
90
106
|
document-replay flag.
|
|
91
|
-
- `hash-validation` — `bodySniff`, and how `
|
|
107
|
+
- `hash-validation` — `bodySniff`, and how `verifyRequestProof({ providerId })` gates
|
|
92
108
|
on the provider's declared spec.
|