@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/src/old/flag.ts
CHANGED
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
* `USE_OLD_DEVTOOLS` — single source of truth for which backend the MCP
|
|
3
3
|
* server targets.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* EXPLICITLY by setting `USE_OLD_DEVTOOLS=false`. Anything else — unset,
|
|
8
|
-
* empty, `true`, `1`, a typo — keeps old mode on, so a forgotten env var
|
|
9
|
-
* can never silently route a developer at the half-built builder backend.
|
|
5
|
+
* Builder is the default. Only `true` or `1` explicitly selects old devtools;
|
|
6
|
+
* an unset value or typo stays on Builder.
|
|
10
7
|
*
|
|
11
8
|
* The actual env read lives in `../consts.ts` (the single env-access module);
|
|
12
9
|
* this widely-imported path re-exports it for back-compat.
|
package/src/old/instructions.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP server instructions shown to the LLM when running in OLD-devtools mode
|
|
3
|
-
* (`USE_OLD_DEVTOOLS`
|
|
3
|
+
* (`USE_OLD_DEVTOOLS=true` or `1`). Describes the REDUCED tool
|
|
4
4
|
* surface — there are no org/credential-link/review flows and no generated
|
|
5
5
|
* API tools here. Both modes' instructions load together in
|
|
6
6
|
* `mcp/instructions` (alongside the topic-split authoring guide); re-exported
|
package/src/old/to-register.ts
CHANGED
|
@@ -72,9 +72,10 @@ export interface OldProviderOpts {
|
|
|
72
72
|
* .interceptorOptions.isDocumentRequestReplayEnabled`, is likewise always
|
|
73
73
|
* force-disabled by `providerToCreateVersionRequest`. */
|
|
74
74
|
disableRequestReplay?: boolean
|
|
75
|
-
/** Interception mechanism
|
|
76
|
-
*
|
|
77
|
-
*
|
|
75
|
+
/** Interception mechanism. Omit it to use the backend's `HAWKEYE` default;
|
|
76
|
+
* use `NONE` only when disabling interception after diagnosis.
|
|
77
|
+
* `HAWKEYE`/`MSWJS`/`XHOOK`/`CDP` enable live interception. Old-devtools
|
|
78
|
+
* calls this
|
|
78
79
|
* `injectionType`; builder's equivalent is `webSettings.clientOptions
|
|
79
80
|
* .inapp.interceptorOptions.interceptorType` (no `NONE` value there —
|
|
80
81
|
* omitting the whole object is builder's no-interception signal
|
|
@@ -41,7 +41,9 @@ export function getProviderInfoTool(client: ReclaimSdkClient): RegisteredTool {
|
|
|
41
41
|
'Read a PUBLISHED provider from the public production SDK backend ' +
|
|
42
42
|
'(api.reclaimprotocol.org — what the verification SDK/attestor ' +
|
|
43
43
|
'itself fetches at runtime), for ANY provider, no auth required. ' +
|
|
44
|
-
'This is the provider-read tool for old-devtools mode.
|
|
44
|
+
'This is the provider-read tool for old-devtools mode. A ' +
|
|
45
|
+
'published provider is usable as-is: don\'t re-verify it ' +
|
|
46
|
+
'(capture/replay/proof) unless the user asks to test it.\n\n' +
|
|
45
47
|
'Returns two complementary reads for the given version (latest ' +
|
|
46
48
|
'when `versionNumber` is omitted): `provider` (the FULL provider ' +
|
|
47
49
|
'+ providerConfig — `customInjection`, `userAgent`, ' +
|
package/src/old/tools/publish.ts
CHANGED
|
@@ -455,20 +455,12 @@ export function createVersionFromCaptureTool(
|
|
|
455
455
|
type: 'string',
|
|
456
456
|
enum: ['NONE', 'MSWJS', 'XHOOK', 'CDP', 'HAWKEYE'],
|
|
457
457
|
description:
|
|
458
|
-
'
|
|
459
|
-
'
|
|
460
|
-
'
|
|
461
|
-
'
|
|
462
|
-
'
|
|
463
|
-
|
|
464
|
-
'`window.reclaimInterceptor.addResponseMiddleware(...)` for ' +
|
|
465
|
-
'genuine live interception, or set `NONE` explicitly to be ' +
|
|
466
|
-
'certain none is configured. Builder calls the equivalent ' +
|
|
467
|
-
'concept `interceptorType` (no `NONE` there — omitting the ' +
|
|
468
|
-
'whole `interceptorOptions` object is its no-interception ' +
|
|
469
|
-
'signal instead). ' + COOKIE_ATTACHMENT_HINT +
|
|
470
|
-
'What each value actually does: ' +
|
|
471
|
-
'how_it_works({ topic: "interception" }).',
|
|
458
|
+
'Live-interception mechanism. Omit it for the standard flow. ' +
|
|
459
|
+
'Use `NONE` only to confirm a suspected interception problem; ' +
|
|
460
|
+
'if that fixes the provider, keep `NONE` and use ' +
|
|
461
|
+
'`window.Reclaim.requestClaim(...)`. For selection rules, call ' +
|
|
462
|
+
'how_it_works({ topic: "interception" }). ' +
|
|
463
|
+
COOKIE_ATTACHMENT_HINT,
|
|
472
464
|
},
|
|
473
465
|
disableRequestReplay: {
|
|
474
466
|
type: 'boolean',
|
|
@@ -499,6 +491,16 @@ export function createVersionFromCaptureTool(
|
|
|
499
491
|
'registration starts at the backend-defined version.',
|
|
500
492
|
),
|
|
501
493
|
)
|
|
494
|
+
assert(
|
|
495
|
+
args.injectionType !== 'NONE'
|
|
496
|
+
|| !args.customInjection?.includes('addResponseMiddleware'),
|
|
497
|
+
badRequest(
|
|
498
|
+
'`injectionType: NONE` cannot deliver ' +
|
|
499
|
+
'`addResponseMiddleware` traffic. Use an interceptor type, or ' +
|
|
500
|
+
'keep `NONE` and replace intercepted requests with ' +
|
|
501
|
+
'`window.Reclaim.requestClaim(...)`.',
|
|
502
|
+
),
|
|
503
|
+
)
|
|
502
504
|
// `provider` / `providers` are just two spellings of the same input —
|
|
503
505
|
// fold them into one array. Zero drafts is allowed ONLY when adding a
|
|
504
506
|
// version to an EXISTING provider (`providerId` set): that publishes
|
|
@@ -11,16 +11,33 @@ export interface AttestorAuthentication {
|
|
|
11
11
|
/**
|
|
12
12
|
* Create legacy-compatible attestor authorization when the deployment has an
|
|
13
13
|
* auth private key. An absent key intentionally means authentication is off.
|
|
14
|
+
*
|
|
15
|
+
* `expiresInSeconds` overrides the attestor library's default lifetime. A
|
|
16
|
+
* zkFetch authorization uses a very short one: the attestor validates expiry
|
|
17
|
+
* once, when it authenticates the connection, and never again for the life of
|
|
18
|
+
* that connection — so the window only has to cover the caller receiving the
|
|
19
|
+
* token and opening its socket, not the proof that follows.
|
|
14
20
|
*/
|
|
15
21
|
export async function createAttestorAuthentication(
|
|
16
22
|
sessionId: string,
|
|
17
23
|
privateKey: string | undefined,
|
|
24
|
+
opts: { expiresInSeconds?: number } = {},
|
|
18
25
|
): Promise<AttestorAuthentication | undefined> {
|
|
19
26
|
if(!privateKey?.trim()) {
|
|
20
27
|
return undefined
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
const request = await createAuthRequest(
|
|
30
|
+
const request = await createAuthRequest(
|
|
31
|
+
{
|
|
32
|
+
id: sessionId,
|
|
33
|
+
...(opts.expiresInSeconds === undefined
|
|
34
|
+
? {}
|
|
35
|
+
: {
|
|
36
|
+
expiresAt: Math.floor(Date.now() / 1000) + opts.expiresInSeconds,
|
|
37
|
+
}),
|
|
38
|
+
},
|
|
39
|
+
privateKey,
|
|
40
|
+
)
|
|
24
41
|
const token = Buffer.from(
|
|
25
42
|
JSON.stringify({
|
|
26
43
|
...request,
|
package/src/proof/attestor.ts
CHANGED
|
@@ -22,6 +22,7 @@ import type { ReclaimProvider } from '../provider/schema.ts'
|
|
|
22
22
|
import { installResponseDump } from './debug-response-dump.ts'
|
|
23
23
|
import {
|
|
24
24
|
buildHttpParams,
|
|
25
|
+
claimRejection,
|
|
25
26
|
ensureAttestorCrypto,
|
|
26
27
|
parseClaim,
|
|
27
28
|
resolveAttestorUrl
|
|
@@ -65,7 +66,7 @@ export interface RunAttestorProofOptions {
|
|
|
65
66
|
* want gnark's speed pin it explicitly (for example, the verify runner). */
|
|
66
67
|
zkEngine?: 'gnark' | 'snarkjs' | 'stwo'
|
|
67
68
|
/** Extract the structured {@link AttestorClaim} (claim + attestor signature)
|
|
68
|
-
* onto the result for
|
|
69
|
+
* onto the result for Proof construction. */
|
|
69
70
|
includeAttestorClaim?: boolean
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -77,7 +78,7 @@ export interface ProofResult {
|
|
|
77
78
|
owner?: string
|
|
78
79
|
verified: boolean
|
|
79
80
|
error?: string
|
|
80
|
-
/** Structured claim + signature for
|
|
81
|
+
/** Structured claim + signature for Proof verification. Set only when
|
|
81
82
|
* `includeAttestorClaim` was requested and the claim carries signatures. */
|
|
82
83
|
attestorClaim?: AttestorClaim
|
|
83
84
|
/** Set to `'missing-owner-key'` when no credential was available to
|
|
@@ -300,6 +301,26 @@ export async function runAttestorProof(
|
|
|
300
301
|
return errorResult
|
|
301
302
|
}
|
|
302
303
|
|
|
304
|
+
// The attestor reports a rejected claim (for example, an invalid ZK proof)
|
|
305
|
+
// in the response rather than by throwing, so a returned value alone is
|
|
306
|
+
// not a proof: it needs a claim, a claim signature, and no error.
|
|
307
|
+
const rejection = claimRejection(claim)
|
|
308
|
+
if(rejection !== undefined) {
|
|
309
|
+
const rejected: ProofResult = {
|
|
310
|
+
proof: claim,
|
|
311
|
+
extractedValue: '',
|
|
312
|
+
extractedParameters: {},
|
|
313
|
+
verified: false,
|
|
314
|
+
error: rejection,
|
|
315
|
+
sentParams: params,
|
|
316
|
+
}
|
|
317
|
+
if(attestorLogs !== undefined) {
|
|
318
|
+
rejected.attestorLogs = attestorLogs
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return rejected
|
|
322
|
+
}
|
|
323
|
+
|
|
303
324
|
const { extractedValue, extractedParameters, identifier, owner, claimData }
|
|
304
325
|
= parseClaim(claim)
|
|
305
326
|
|
|
@@ -318,7 +339,7 @@ export async function runAttestorProof(
|
|
|
318
339
|
}
|
|
319
340
|
|
|
320
341
|
// Structured claim + signature so the result JWS can carry the exact
|
|
321
|
-
//
|
|
342
|
+
// Proof the Consumer verifies independently.
|
|
322
343
|
if(opts.includeAttestorClaim) {
|
|
323
344
|
const sigs = (claim as {
|
|
324
345
|
signatures?: { attestorAddress?: unknown, claimSignature?: unknown }
|
package/src/proof/pod-prover.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* The pod API is unauthenticated (gateway/session is the trust boundary); call
|
|
28
28
|
* it over the same internal host used for CDP. Consumers verify
|
|
29
29
|
* `claim_signature` with the legacy SDK's `verifyProof`, so this hands back an
|
|
30
|
-
* {@link AttestorClaim} that the app places in the exact
|
|
30
|
+
* {@link AttestorClaim} that the app places in the exact `Proof` shape.
|
|
31
31
|
* `result_signature` is unused by consumers.
|
|
32
32
|
*/
|
|
33
33
|
import { bytesToHex } from '@noble/hashes/utils.js'
|
package/src/proof/proof-core.ts
CHANGED
|
@@ -75,6 +75,34 @@ export interface ParsedClaim {
|
|
|
75
75
|
owner?: string
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/** Why the attestor did not sign `claim`, or `undefined` when it did. The
|
|
79
|
+
* attestor returns rejections (for example, an invalid ZK proof) as a
|
|
80
|
+
* response with `error` set and no claim signature, not by throwing. */
|
|
81
|
+
export function claimRejection(claim: unknown): string | undefined {
|
|
82
|
+
const response = claim as {
|
|
83
|
+
claim?: unknown
|
|
84
|
+
error?: { code?: unknown, message?: unknown }
|
|
85
|
+
signatures?: { claimSignature?: unknown }
|
|
86
|
+
} | null | undefined
|
|
87
|
+
const error = response?.error
|
|
88
|
+
if(error?.message || error?.code) {
|
|
89
|
+
return typeof error.message === 'string' && error.message
|
|
90
|
+
? error.message
|
|
91
|
+
: `attestor error code ${String(error.code)}`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if(!response?.claim) {
|
|
95
|
+
return 'attestor returned no claim'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const signature = response.signatures?.claimSignature
|
|
99
|
+
if(!(signature instanceof Uint8Array) || !signature.length) {
|
|
100
|
+
return 'attestor did not sign the claim'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return undefined
|
|
104
|
+
}
|
|
105
|
+
|
|
78
106
|
/** Pull claimData + decoded `context.extractedParameters` (plus identifier /
|
|
79
107
|
* owner) out of a `createClaimOnAttestor` result. The full result still
|
|
80
108
|
* carries signatures the caller may need for nested-proof building. */
|
|
@@ -33,17 +33,19 @@ export const USER_SCRIPT_HINT =
|
|
|
33
33
|
|
|
34
34
|
/** Prefixes the `allowedJsRequests` / `allowedInjectedRequestData` field. The
|
|
35
35
|
* trap it describes is silent and total — a mis-declared entry makes
|
|
36
|
-
* `
|
|
37
|
-
* itself stays in the schema even though its explanation moved to a
|
|
36
|
+
* `verifyRequestProof({ providerId })` reject EVERY real proof — so the
|
|
37
|
+
* warning itself stays in the schema even though its explanation moved to a
|
|
38
|
+
* topic. */
|
|
38
39
|
export const ALLOWED_REQUESTS_HINT =
|
|
39
40
|
'⚠️ Only populate this if you intend to gate '
|
|
40
|
-
+ '`
|
|
41
|
-
+ 'hash-equality check and its `url` is hashed VERBATIM (no
|
|
42
|
-
+ 'resolution, even with urlType REGEX/TEMPLATE). If the
|
|
43
|
-
+ 'carries ANY per-session part (nonce, CSRF token,
|
|
44
|
-
+ 'timestamp), no declared spec can ever hash-match a real
|
|
45
|
-
+ 'populating it then makes
|
|
46
|
-
+ 'worse than leaving it empty. Diff the same endpoint\'s
|
|
47
|
-
+ 'across two sessions first. Mechanics, the
|
|
41
|
+
+ '`verifyRequestProof(proof, { providerId })`: each entry feeds a '
|
|
42
|
+
+ 'client-side hash-equality check and its `url` is hashed VERBATIM (no '
|
|
43
|
+
+ 'regex/template resolution, even with urlType REGEX/TEMPLATE). If the '
|
|
44
|
+
+ 'real captured URL carries ANY per-session part (nonce, CSRF token, '
|
|
45
|
+
+ 'cache-busting timestamp), no declared spec can ever hash-match a real '
|
|
46
|
+
+ 'proof — populating it then makes verifyRequestProof reject every real '
|
|
47
|
+
+ 'proof, which is worse than leaving it empty. Diff the same endpoint\'s '
|
|
48
|
+
+ 'captured URL across two sessions first. Mechanics, the '
|
|
49
|
+
+ 'body-templating rules and the '
|
|
48
50
|
+ 'dangerouslyDisableContentValidation fallback: '
|
|
49
51
|
+ 'how_it_works({ topic: "hash-validation" }).'
|
package/src/provider/matcher.ts
CHANGED
|
@@ -327,16 +327,32 @@ function findJsonPath(body: string, target: string): string | undefined {
|
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
const candidates = normalizeCandidates(target)
|
|
330
|
-
|
|
330
|
+
const paths: string[] = []
|
|
331
|
+
collectJsonPaths(parsed, '$', candidates, paths)
|
|
332
|
+
if(paths.length > 1) {
|
|
333
|
+
throw new Error(
|
|
334
|
+
`target value "${target}" occurs at multiple JSON paths `
|
|
335
|
+
+ `(${paths.join(', ')}) — choose a value that identifies one field`,
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return paths[0]
|
|
331
340
|
}
|
|
332
341
|
|
|
333
|
-
function
|
|
342
|
+
function collectJsonPaths(
|
|
334
343
|
node: unknown,
|
|
335
344
|
path: string,
|
|
336
345
|
candidates: string[],
|
|
337
|
-
|
|
346
|
+
paths: string[],
|
|
347
|
+
): void {
|
|
348
|
+
// Two paths are enough to prove ambiguity and keep traversal bounded for a
|
|
349
|
+
// response containing the same primitive many times.
|
|
350
|
+
if(paths.length > 1) {
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
|
|
338
354
|
if(node === null || node === undefined) {
|
|
339
|
-
return
|
|
355
|
+
return
|
|
340
356
|
}
|
|
341
357
|
|
|
342
358
|
if(
|
|
@@ -346,21 +362,18 @@ function walk(
|
|
|
346
362
|
) {
|
|
347
363
|
const str = String(node)
|
|
348
364
|
if(candidates.includes(str)) {
|
|
349
|
-
|
|
365
|
+
paths.push(path)
|
|
350
366
|
}
|
|
351
367
|
|
|
352
|
-
return
|
|
368
|
+
return
|
|
353
369
|
}
|
|
354
370
|
|
|
355
371
|
if(Array.isArray(node)) {
|
|
356
372
|
for(const [i, element] of node.entries()) {
|
|
357
|
-
|
|
358
|
-
if(found) {
|
|
359
|
-
return found
|
|
360
|
-
}
|
|
373
|
+
collectJsonPaths(element, `${path}[${i}]`, candidates, paths)
|
|
361
374
|
}
|
|
362
375
|
|
|
363
|
-
return
|
|
376
|
+
return
|
|
364
377
|
}
|
|
365
378
|
|
|
366
379
|
if(typeof node === 'object') {
|
|
@@ -368,14 +381,9 @@ function walk(
|
|
|
368
381
|
const childPath = /^[A-Za-z_][A-Za-z0-9_]*$/.test(k)
|
|
369
382
|
? `${path}.${k}`
|
|
370
383
|
: `${path}["${k}"]`
|
|
371
|
-
|
|
372
|
-
if(found) {
|
|
373
|
-
return found
|
|
374
|
-
}
|
|
384
|
+
collectJsonPaths(v, childPath, candidates, paths)
|
|
375
385
|
}
|
|
376
386
|
}
|
|
377
|
-
|
|
378
|
-
return undefined
|
|
379
387
|
}
|
|
380
388
|
|
|
381
389
|
// ---------------------------------------------------------------------------
|
|
@@ -74,6 +74,11 @@ export interface CreateVersionOptions {
|
|
|
74
74
|
jsUserScripts?: string
|
|
75
75
|
/** Requests the injection script may fire, as `RequestSelectionTemplate`s. */
|
|
76
76
|
allowedJsRequests?: AllowedJsRequest[]
|
|
77
|
+
/** Portal-only authenticated actions exposed as
|
|
78
|
+
* `window.Reclaim.browserRequest`. */
|
|
79
|
+
browserRequestActions?: NonNullable<
|
|
80
|
+
CreateProviderVersionRequest['webSettings']['browserRequestActions']
|
|
81
|
+
>
|
|
77
82
|
/** In-app interception options, mapped to
|
|
78
83
|
* `webSettings.clientOptions.inapp.interceptorOptions` — ONLY when this
|
|
79
84
|
* is explicitly passed (builder's schema has no `NONE` interceptorType;
|
|
@@ -218,7 +223,7 @@ export function providerToCreateVersionRequest(
|
|
|
218
223
|
): CreateProviderVersionRequest {
|
|
219
224
|
const {
|
|
220
225
|
notes, version, requiredContext: requestedContext, jsUserScripts,
|
|
221
|
-
allowedJsRequests, interceptorOptions,
|
|
226
|
+
allowedJsRequests, browserRequestActions, interceptorOptions,
|
|
222
227
|
} = opts
|
|
223
228
|
const requiredContext = requestedContext ?? deriveRequiredContext(
|
|
224
229
|
providers,
|
|
@@ -279,6 +284,7 @@ export function providerToCreateVersionRequest(
|
|
|
279
284
|
},
|
|
280
285
|
// Only set when non-empty; an empty string would store a no-op script.
|
|
281
286
|
...(script ? { jsUserScripts: script } : {}),
|
|
287
|
+
...(browserRequestActions?.length ? { browserRequestActions } : {}),
|
|
282
288
|
},
|
|
283
289
|
// Derived from `{{context.<name>}}` placeholders only — a captured
|
|
284
290
|
// provider's `paramValues` are extracted response parameters, not
|