@reclaimprotocol/agent 0.1.1-dev.1 → 0.1.1
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 +1 -1
- package/lib/cdp/capture-engine.d.ts +66 -0
- package/lib/cdp/capture-engine.js +153 -0
- package/lib/cdp/capture.d.ts +9 -20
- package/lib/cdp/capture.js +14 -138
- package/lib/cdp/index.d.ts +3 -0
- package/lib/cdp/index.js +6 -0
- package/lib/config/store.d.ts +7 -6
- package/lib/config/store.js +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/lib/mcp/api/operations.gen.d.ts +101 -45
- package/lib/mcp/api/operations.gen.js +996 -126
- package/lib/mcp/api/to-zod.d.ts +24 -0
- package/lib/mcp/api/to-zod.js +94 -0
- package/lib/mcp/api/tools.js +1 -1
- package/lib/mcp/credentials/authenticate.d.ts +3 -0
- package/lib/mcp/{tools/credentials → credentials}/authenticate.js +3 -3
- package/lib/mcp/credentials/build.d.ts +5 -0
- package/lib/mcp/credentials/build.js +18 -0
- package/lib/mcp/{tools/credentials → credentials}/cache.d.ts +9 -9
- package/lib/mcp/{tools/credentials → credentials}/cache.js +36 -19
- package/lib/mcp/credentials/import.d.ts +2 -0
- package/lib/mcp/{tools/credentials → credentials}/import.js +2 -2
- package/lib/mcp/credentials/issue.d.ts +2 -0
- package/lib/mcp/{tools/credentials → credentials}/issue.js +4 -4
- package/lib/mcp/credentials/keypair.d.ts +17 -0
- package/lib/mcp/credentials/keypair.js +48 -0
- package/lib/mcp/credentials/link.d.ts +3 -0
- package/lib/mcp/credentials/link.js +107 -0
- package/lib/mcp/{tools/credentials → credentials}/list-cached.d.ts +1 -1
- package/lib/mcp/{tools/credentials → credentials}/list-cached.js +5 -5
- package/lib/mcp/credentials/owner-key.d.ts +23 -0
- package/lib/mcp/credentials/owner-key.js +58 -0
- package/lib/mcp/credentials/paths.d.ts +12 -0
- package/lib/mcp/credentials/paths.js +35 -0
- package/lib/mcp/credentials/poll.d.ts +27 -0
- package/lib/mcp/credentials/poll.js +61 -0
- package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.d.ts +1 -1
- package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.js +2 -2
- package/lib/mcp/credentials/session-cache.d.ts +14 -0
- package/lib/mcp/credentials/session-cache.js +42 -0
- package/lib/mcp/{tools/credentials → credentials}/status.d.ts +1 -1
- package/lib/mcp/credentials/status.js +76 -0
- package/lib/mcp/instructions.d.ts +1 -0
- package/lib/mcp/instructions.js +11 -0
- package/lib/mcp/register.d.ts +38 -0
- package/lib/mcp/register.js +80 -0
- package/lib/mcp/server.d.ts +2 -2
- package/lib/mcp/server.js +3 -3
- package/lib/mcp/start.js +10 -4
- package/lib/mcp/tools/agent/build.js +2 -15
- package/lib/mcp/tools/agent/index.d.ts +2 -0
- package/lib/mcp/tools/agent/index.js +3 -0
- package/lib/mcp/tools/agent/proof.js +1 -6
- package/lib/mcp/tools/agent/propose.js +13 -2
- package/lib/mcp/tools/agent/publish.js +10 -2
- package/lib/mcp/tools/agent/replay.js +0 -5
- package/lib/mcp/tools/analyze.d.ts +3 -0
- package/lib/mcp/tools/analyze.js +26 -0
- package/lib/mcp/tools/attach.d.ts +11 -0
- package/lib/mcp/tools/attach.js +72 -0
- package/lib/mcp/tools/authenticate/authenticate.js +107 -0
- package/lib/mcp/tools/authenticate/build.d.ts +15 -0
- package/lib/mcp/tools/authenticate/build.js +28 -0
- package/lib/mcp/tools/authenticate/decrypt-key.d.ts +32 -0
- package/lib/mcp/tools/authenticate/decrypt-key.js +49 -0
- package/lib/mcp/tools/authenticate/eth-key.d.ts +38 -0
- package/lib/mcp/tools/authenticate/eth-key.js +130 -0
- package/lib/mcp/tools/authenticate/import.js +57 -0
- package/lib/mcp/tools/authenticate/index.d.ts +2 -0
- package/lib/mcp/tools/authenticate/index.js +4 -0
- package/lib/mcp/tools/authenticate/issue.js +42 -0
- package/lib/mcp/tools/authenticate/resolve-owner-key.d.ts +13 -0
- package/lib/mcp/tools/authenticate/resolve-owner-key.js +53 -0
- package/lib/mcp/tools/capture.d.ts +10 -0
- package/lib/mcp/tools/capture.js +142 -0
- package/lib/mcp/tools/eval.d.ts +5 -0
- package/lib/mcp/tools/eval.js +127 -0
- package/lib/mcp/tools/find.d.ts +3 -0
- package/lib/mcp/tools/find.js +60 -0
- package/lib/mcp/tools/index.d.ts +3 -0
- package/lib/mcp/tools/index.js +6 -0
- package/lib/mcp/tools/owner-key.d.ts +2 -0
- package/lib/mcp/tools/owner-key.js +63 -0
- package/lib/mcp/tools/proof.d.ts +3 -0
- package/lib/mcp/tools/proof.js +214 -0
- package/lib/mcp/tools/propose.d.ts +9 -0
- package/lib/mcp/tools/propose.js +75 -0
- package/lib/mcp/tools/publish.d.ts +3 -0
- package/lib/mcp/tools/publish.js +59 -0
- package/lib/mcp/tools/replay.d.ts +3 -0
- package/lib/mcp/tools/replay.js +46 -0
- package/lib/mcp/tools/session.d.ts +10 -0
- package/lib/mcp/tools/session.js +29 -0
- package/lib/mcp/tools/verification/build.d.ts +12 -0
- package/lib/mcp/tools/verification/build.js +14 -0
- package/lib/mcp/tools/verification/diagnose.d.ts +11 -0
- package/lib/mcp/tools/verification/diagnose.js +132 -0
- package/lib/mcp/tools/verification/index.d.ts +1 -0
- package/lib/mcp/tools/verification/index.js +2 -0
- package/lib/mcp/tools/verification/result.d.ts +12 -0
- package/lib/mcp/tools/verification/result.js +126 -0
- package/lib/mcp/verifications/build.d.ts +5 -0
- package/lib/mcp/verifications/build.js +14 -0
- package/lib/mcp/verifications/create.d.ts +3 -0
- package/lib/mcp/verifications/create.js +57 -0
- package/lib/mcp/verifications/find.d.ts +3 -0
- package/lib/mcp/verifications/find.js +37 -0
- package/lib/mcp/verifications/get.d.ts +3 -0
- package/lib/mcp/verifications/get.js +26 -0
- package/lib/mcp/verifications/update.d.ts +3 -0
- package/lib/mcp/verifications/update.js +78 -0
- package/lib/old/client.d.ts +3 -0
- package/lib/old/instructions.d.ts +0 -6
- package/lib/old/instructions.js +6 -24
- package/lib/old/to-register.d.ts +3 -0
- package/lib/old/to-register.js +35 -7
- package/lib/old/tools/publish.js +13 -1
- package/lib/proof/attestor.d.ts +33 -1
- package/lib/proof/attestor.js +65 -63
- package/lib/proof/index.d.ts +5 -0
- package/lib/proof/index.js +6 -0
- package/lib/proof/proof-core.d.ts +35 -0
- package/lib/proof/proof-core.js +73 -0
- package/lib/provider/index.d.ts +5 -0
- package/lib/provider/index.js +9 -0
- package/lib/provider/to-version.d.ts +9 -12
- package/lib/provider/to-version.js +38 -4
- package/lib/provider/verification-checks.d.ts +12 -0
- package/lib/provider/verification-checks.js +30 -0
- package/lib/routes.gen.d.ts +271 -0
- package/lib/routes.gen.js +73 -0
- package/lib/types/openapi.gen.d.ts +3967 -0
- package/lib/types/openapi.gen.js +5 -0
- package/package.json +16 -7
- package/skill/SKILL.md +35 -14
- package/skill/builder-mode.md +9 -0
- package/skill/old-mode.md +13 -0
- package/src/cdp/capture-engine.ts +256 -0
- package/src/cdp/capture.ts +25 -185
- package/src/cdp/index.ts +6 -0
- package/src/config/store.ts +7 -6
- package/src/index.ts +2 -4
- package/src/mcp/api/operations.gen.ts +1023 -121
- package/src/mcp/api/to-zod.ts +115 -0
- package/src/mcp/api/tools.ts +9 -3
- package/src/mcp/instructions.ts +15 -0
- package/src/mcp/server.ts +5 -4
- package/src/mcp/start.ts +14 -4
- package/src/mcp/tools/agent/build.ts +2 -18
- package/src/mcp/tools/agent/index.ts +4 -0
- package/src/mcp/tools/agent/proof.ts +1 -7
- package/src/mcp/tools/agent/propose.ts +13 -2
- package/src/mcp/tools/agent/publish.ts +10 -2
- package/src/mcp/tools/agent/replay.ts +0 -5
- package/src/mcp/tools/{credentials → authenticate}/authenticate.ts +9 -8
- package/src/mcp/tools/authenticate/build.ts +32 -0
- package/src/mcp/tools/authenticate/decrypt-key.ts +64 -0
- package/src/mcp/tools/authenticate/eth-key.ts +182 -0
- package/src/mcp/tools/authenticate/import.ts +73 -0
- package/src/mcp/tools/authenticate/index.ts +4 -0
- package/src/mcp/tools/authenticate/issue.ts +50 -0
- package/src/mcp/tools/authenticate/resolve-owner-key.ts +60 -0
- package/src/mcp/tools/index.ts +6 -0
- package/src/mcp/tools/verification/build.ts +16 -0
- package/src/mcp/tools/verification/index.ts +2 -0
- package/src/mcp/tools/verification/result.ts +155 -0
- package/src/old/client.ts +3 -0
- package/src/old/instructions.ts +10 -25
- package/src/old/to-register.ts +62 -27
- package/src/old/tools/publish.ts +17 -1
- package/src/proof/attestor.ts +112 -71
- package/src/proof/index.ts +21 -0
- package/src/proof/proof-core.ts +109 -0
- package/src/provider/index.ts +20 -0
- package/src/provider/to-version.ts +52 -11
- package/src/provider/verification-checks.ts +36 -0
- package/lib/mcp/tools/credentials/build.d.ts +0 -16
- package/lib/mcp/tools/credentials/build.js +0 -33
- package/lib/mcp/tools/credentials/status.js +0 -62
- package/src/mcp/tools/credentials/build.ts +0 -37
- package/src/mcp/tools/credentials/cache.ts +0 -161
- package/src/mcp/tools/credentials/env-file.ts +0 -101
- package/src/mcp/tools/credentials/import.ts +0 -72
- package/src/mcp/tools/credentials/issue.ts +0 -107
- package/src/mcp/tools/credentials/list-cached.ts +0 -66
- package/src/mcp/tools/credentials/register.ts +0 -49
- package/src/mcp/tools/credentials/resolve-owner-key.ts +0 -78
- package/src/mcp/tools/credentials/status.ts +0 -82
- package/src/types/openapi.ts +0 -7
- /package/lib/mcp/{tools/credentials → credentials}/env-file.d.ts +0 -0
- /package/lib/mcp/{tools/credentials → credentials}/env-file.js +0 -0
- /package/lib/mcp/{tools/credentials → credentials}/register.d.ts +0 -0
- /package/lib/mcp/{tools/credentials → credentials}/register.js +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/authenticate.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/import.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/issue.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/session-cache.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/session-cache.js +0 -0
- /package/src/mcp/tools/{credentials → authenticate}/session-cache.ts +0 -0
package/src/old/to-register.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import type { ReclaimProvider } from '../provider/schema.ts'
|
|
1
|
+
import type { ReclaimProvider, ResponseRedaction } from '../provider/schema.ts'
|
|
2
2
|
import type {
|
|
3
3
|
RegisterProviderBody,
|
|
4
4
|
UpdateProviderConfigBody,
|
|
5
5
|
} from './client.ts'
|
|
6
6
|
|
|
7
|
+
/** Default web settings, mirroring the builder openapi defaults
|
|
8
|
+
* (`ProviderWebSettings.geoLocation`, `PortalClientOptions.useProxy`). The old
|
|
9
|
+
* backend accepts both: `geoLocation` lives on the providerConfig, `useProxy`
|
|
10
|
+
* is a Provider-level flag (register only). */
|
|
11
|
+
const DEFAULT_GEO_LOCATION = '{{DYNAMIC_GEO}}'
|
|
12
|
+
const DEFAULT_USE_PROXY = true
|
|
13
|
+
|
|
7
14
|
/**
|
|
8
15
|
* Translate a drafted `ReclaimProvider` (from `propose_provider`) into the
|
|
9
16
|
* OLD devtools backend shapes. Deliberately a SEPARATE module from
|
|
@@ -22,7 +29,10 @@ import type {
|
|
|
22
29
|
export interface OldProviderOpts {
|
|
23
30
|
initialUrl: string
|
|
24
31
|
description?: string
|
|
32
|
+
/** Defaults to `{{DYNAMIC_GEO}}` when omitted. */
|
|
25
33
|
geoLocation?: string
|
|
34
|
+
/** Defaults to `true` when omitted. Register only (Provider-level flag). */
|
|
35
|
+
useProxy?: boolean
|
|
26
36
|
providerType?: 'PRIVATE' | 'PUBLIC'
|
|
27
37
|
}
|
|
28
38
|
|
|
@@ -63,6 +73,20 @@ function requestDataFromProvider(provider: ReclaimProvider): OldRequestData {
|
|
|
63
73
|
)
|
|
64
74
|
}
|
|
65
75
|
|
|
76
|
+
// The old backend has no dotted interpolation: consumer-supplied params
|
|
77
|
+
// must use the `{{context_<name>}}` form here, not the builder's
|
|
78
|
+
// `{{context.<name>}}`. Catch the mix-up at publish with a clear error
|
|
79
|
+
// instead of a template that silently never resolves.
|
|
80
|
+
const dotted = `${provider.url}\n${provider.body ?? ''}`
|
|
81
|
+
.match(/\{\{context\.[A-Za-z_][A-Za-z0-9_]*\}\}/)
|
|
82
|
+
if(dotted) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`Old devtools does not support ${dotted[0]} — rename ` +
|
|
85
|
+
'consumer-supplied params to the {{context_<name>}} form ' +
|
|
86
|
+
'for this backend.',
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
66
90
|
const responseMatches: OldResponseMatch[] = provider.responseMatches.map(
|
|
67
91
|
(m, i) => ({
|
|
68
92
|
value: m.value,
|
|
@@ -72,29 +96,40 @@ function requestDataFromProvider(provider: ReclaimProvider): OldRequestData {
|
|
|
72
96
|
}),
|
|
73
97
|
)
|
|
74
98
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
99
|
+
// Old devtools wants `responseMatches` and `responseRedactions` as PARALLEL
|
|
100
|
+
// arrays. A drafted provider may instead carry each redaction nested in its
|
|
101
|
+
// match's `extract` (the builder shape). Prefer the explicit parallel array;
|
|
102
|
+
// fall back to the nested `extract`s so redactions are never dropped.
|
|
103
|
+
const nestedRedactions = provider.responseMatches
|
|
104
|
+
.map((m) => (m as { extract?: ResponseRedaction }).extract)
|
|
105
|
+
.filter((e): e is ResponseRedaction => Boolean(e))
|
|
106
|
+
const sourceRedactions = provider.responseRedactions?.length
|
|
107
|
+
? provider.responseRedactions
|
|
108
|
+
: nestedRedactions
|
|
82
109
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
110
|
+
const responseRedactions: OldResponseRedaction[] = sourceRedactions.map(
|
|
111
|
+
(r, i) => {
|
|
112
|
+
const out: OldResponseRedaction = { order: i }
|
|
113
|
+
if(r.xPath !== undefined) {
|
|
114
|
+
out.xPath = r.xPath
|
|
115
|
+
}
|
|
86
116
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
117
|
+
if(r.jsonPath !== undefined) {
|
|
118
|
+
out.jsonPath = r.jsonPath
|
|
119
|
+
}
|
|
90
120
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
121
|
+
if(r.regex !== undefined) {
|
|
122
|
+
out.regex = r.regex
|
|
123
|
+
}
|
|
95
124
|
|
|
96
|
-
|
|
97
|
-
|
|
125
|
+
// OPRF redactions are supported — pass the mode through unchanged.
|
|
126
|
+
if(r.hash !== undefined) {
|
|
127
|
+
out.hash = r.hash
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return out
|
|
131
|
+
},
|
|
132
|
+
)
|
|
98
133
|
|
|
99
134
|
const requestData: OldRequestData = {
|
|
100
135
|
url: provider.url,
|
|
@@ -127,16 +162,15 @@ export function providerToRegisterBody(
|
|
|
127
162
|
name: provider.name,
|
|
128
163
|
loginUrl: opts.initialUrl,
|
|
129
164
|
providerType: opts.providerType ?? 'PRIVATE',
|
|
165
|
+
// Web-settings defaults mirror the builder openapi defaults.
|
|
166
|
+
geoLocation: opts.geoLocation ?? DEFAULT_GEO_LOCATION,
|
|
167
|
+
useProxy: opts.useProxy ?? DEFAULT_USE_PROXY,
|
|
130
168
|
requestData: [requestDataFromProvider(provider)],
|
|
131
169
|
}
|
|
132
170
|
if(opts.description !== undefined) {
|
|
133
171
|
body.description = opts.description
|
|
134
172
|
}
|
|
135
173
|
|
|
136
|
-
if(opts.geoLocation !== undefined) {
|
|
137
|
-
body.geoLocation = opts.geoLocation
|
|
138
|
-
}
|
|
139
|
-
|
|
140
174
|
return body
|
|
141
175
|
}
|
|
142
176
|
|
|
@@ -149,13 +183,14 @@ export function providerToConfigBody(
|
|
|
149
183
|
version: string,
|
|
150
184
|
versionInfo: string,
|
|
151
185
|
): UpdateProviderConfigBody {
|
|
186
|
+
// `useProxy` is a Provider-level flag on the old backend, not part of a
|
|
187
|
+
// version's providerConfig — so the config (new-version) path only carries
|
|
188
|
+
// `geoLocation`. It defaults the same way as register.
|
|
152
189
|
const providerConfig: Record<string, unknown> = {
|
|
153
190
|
loginUrl: opts.initialUrl,
|
|
191
|
+
geoLocation: opts.geoLocation ?? DEFAULT_GEO_LOCATION,
|
|
154
192
|
requestData: [requestDataFromProvider(provider)],
|
|
155
193
|
}
|
|
156
|
-
if(opts.geoLocation !== undefined) {
|
|
157
|
-
providerConfig.geoLocation = opts.geoLocation
|
|
158
|
-
}
|
|
159
194
|
|
|
160
195
|
return { providerConfig, version, versionInfo }
|
|
161
196
|
}
|
package/src/old/tools/publish.ts
CHANGED
|
@@ -33,6 +33,7 @@ export function createVersionFromCaptureTool(
|
|
|
33
33
|
providerId?: string
|
|
34
34
|
description?: string
|
|
35
35
|
geoLocation?: string
|
|
36
|
+
useProxy?: boolean
|
|
36
37
|
providerType?: 'PRIVATE' | 'PUBLIC'
|
|
37
38
|
notes?: string
|
|
38
39
|
}>(
|
|
@@ -83,7 +84,18 @@ export function createVersionFromCaptureTool(
|
|
|
83
84
|
type: 'string',
|
|
84
85
|
description: 'Provider description (new-provider register only).',
|
|
85
86
|
},
|
|
86
|
-
geoLocation: {
|
|
87
|
+
geoLocation: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
description:
|
|
90
|
+
'Geo the verification appears to originate from. Defaults to ' +
|
|
91
|
+
"'{{DYNAMIC_GEO}}' (the user's geo) when omitted.",
|
|
92
|
+
},
|
|
93
|
+
useProxy: {
|
|
94
|
+
type: 'boolean',
|
|
95
|
+
description:
|
|
96
|
+
'Route portal/attestation traffic through a proxy. Defaults to ' +
|
|
97
|
+
'true when omitted. Applied on register only.',
|
|
98
|
+
},
|
|
87
99
|
providerType: { type: 'string', enum: ['PRIVATE', 'PUBLIC'] },
|
|
88
100
|
notes: {
|
|
89
101
|
type: 'string',
|
|
@@ -105,6 +117,10 @@ export function createVersionFromCaptureTool(
|
|
|
105
117
|
opts.geoLocation = args.geoLocation
|
|
106
118
|
}
|
|
107
119
|
|
|
120
|
+
if(args.useProxy !== undefined) {
|
|
121
|
+
opts.useProxy = args.useProxy
|
|
122
|
+
}
|
|
123
|
+
|
|
108
124
|
if(args.providerType !== undefined) {
|
|
109
125
|
opts.providerType = args.providerType
|
|
110
126
|
}
|
package/src/proof/attestor.ts
CHANGED
|
@@ -6,11 +6,15 @@
|
|
|
6
6
|
// revealed slice; jsonPath/xPath live on responseRedactions (what the prover
|
|
7
7
|
// reveals), never on responseMatches.
|
|
8
8
|
|
|
9
|
+
import { bytesToHex } from '@noble/hashes/utils.js'
|
|
9
10
|
import {
|
|
10
|
-
createClaimOnAttestor, type Logger,
|
|
11
|
+
createClaimOnAttestor, type Logger,
|
|
11
12
|
} from '@reclaimprotocol/attestor-core'
|
|
12
|
-
import {
|
|
13
|
+
import { resolveEthKey } from '../mcp/tools/authenticate/eth-key.ts'
|
|
13
14
|
import type { ReclaimProvider } from '../provider/schema.ts'
|
|
15
|
+
import {
|
|
16
|
+
buildHttpParams, ensureAttestorCrypto, parseClaim, resolveAttestorUrl,
|
|
17
|
+
} from './proof-core.ts'
|
|
14
18
|
import { ensureZkFiles } from './zk-files.ts'
|
|
15
19
|
|
|
16
20
|
export interface AttestorLogEntry {
|
|
@@ -19,6 +23,37 @@ export interface AttestorLogEntry {
|
|
|
19
23
|
ctx?: Record<string, unknown>
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
/** The attestor's signed claim data + signature, for building the nested proof
|
|
27
|
+
* JWS a Consumer verifies against the attestor's key. Populated when
|
|
28
|
+
* `includeAttestorClaim` is set (the app's verification runner needs it; the
|
|
29
|
+
* MCP `run_proof` tool ignores it). */
|
|
30
|
+
export interface AttestorClaim {
|
|
31
|
+
/** ProviderClaimData: provider, parameters, context (JSON string), owner,
|
|
32
|
+
* timestampS, epoch, identifier. */
|
|
33
|
+
claim: Record<string, unknown>
|
|
34
|
+
/** Hex (0x) attestor ETH address that signed the claim (the nested `kid`). */
|
|
35
|
+
attestorAddress: string
|
|
36
|
+
/** Hex (0x) attestor claim signature (EIP-191 over the claim sign-data). */
|
|
37
|
+
claimSignature: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Options for {@link runAttestorProof}. */
|
|
41
|
+
export interface RunAttestorProofOptions {
|
|
42
|
+
attestorUrl?: string
|
|
43
|
+
/** When resolving the key from env/.env/file, the address the caller expects
|
|
44
|
+
* to sign with (sanity check). Ignored when `ownerPrivateKey` is given. */
|
|
45
|
+
ownerAddress?: string
|
|
46
|
+
/** Sign with this key directly (e.g. the app/VC's ephemeral per-session key)
|
|
47
|
+
* instead of resolving from env/.env/file. */
|
|
48
|
+
ownerPrivateKey?: string
|
|
49
|
+
/** ZK engine for `createClaimOnAttestor`. Defaults to `'gnark'`; the app's
|
|
50
|
+
* server-side verification runner uses `'snarkjs'`. */
|
|
51
|
+
zkEngine?: 'gnark' | 'snarkjs'
|
|
52
|
+
/** Extract the structured {@link AttestorClaim} (claim + attestor signature)
|
|
53
|
+
* onto the result for nested-proof construction. */
|
|
54
|
+
includeAttestorClaim?: boolean
|
|
55
|
+
}
|
|
56
|
+
|
|
22
57
|
export interface ProofResult {
|
|
23
58
|
proof: unknown
|
|
24
59
|
extractedValue: string
|
|
@@ -27,6 +62,9 @@ export interface ProofResult {
|
|
|
27
62
|
owner?: string
|
|
28
63
|
verified: boolean
|
|
29
64
|
error?: string
|
|
65
|
+
/** Structured claim + signature for nested-proof verification. Set only when
|
|
66
|
+
* `includeAttestorClaim` was requested and the claim carries signatures. */
|
|
67
|
+
attestorClaim?: AttestorClaim
|
|
30
68
|
/** Set to `'missing-owner-key'` when no credential was available to
|
|
31
69
|
* sign with — distinguishes this recoverable case from other proof
|
|
32
70
|
* errors so the skill can point the dev at `issue_credentials` /
|
|
@@ -139,16 +177,6 @@ function makeCaptureLogger(): {
|
|
|
139
177
|
return { logger: make({}), entries }
|
|
140
178
|
}
|
|
141
179
|
|
|
142
|
-
/** Default public attestor websocket URL. Resolved per-call so an env-var
|
|
143
|
-
* change or per-request override takes effect without restarting the
|
|
144
|
-
* MCP server. */
|
|
145
|
-
const FALLBACK_ATTESTOR_URL = 'wss://attestor.reclaimprotocol.org:444/ws'
|
|
146
|
-
function resolveAttestorUrl(override?: string): string {
|
|
147
|
-
return (
|
|
148
|
-
override ?? process.env['RECLAIM_ATTESTOR_URL'] ?? FALLBACK_ATTESTOR_URL
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
180
|
// ---------------------------------------------------------------------------
|
|
153
181
|
// Main entry point
|
|
154
182
|
// ---------------------------------------------------------------------------
|
|
@@ -156,45 +184,60 @@ function resolveAttestorUrl(override?: string): string {
|
|
|
156
184
|
export async function runAttestorProof(
|
|
157
185
|
provider: ReclaimProvider,
|
|
158
186
|
secrets: Record<string, string>,
|
|
159
|
-
|
|
160
|
-
ownerAddress?: string,
|
|
187
|
+
opts: RunAttestorProofOptions = {},
|
|
161
188
|
): Promise<ProofResult> {
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
189
|
+
// Sign with the caller-supplied key (the app/VC's ephemeral per-session
|
|
190
|
+
// key) when given; otherwise resolve env/.env/file. `ownerAddress` is a
|
|
191
|
+
// sanity check on the resolved key (ignored when a key is supplied).
|
|
192
|
+
let ownerPrivateKey: string
|
|
193
|
+
if(opts.ownerPrivateKey) {
|
|
194
|
+
ownerPrivateKey = opts.ownerPrivateKey
|
|
195
|
+
} else {
|
|
196
|
+
const resolved = resolveEthKey()
|
|
197
|
+
if(!resolved) {
|
|
198
|
+
return {
|
|
199
|
+
proof: undefined,
|
|
200
|
+
extractedValue: '',
|
|
201
|
+
extractedParameters: {},
|
|
202
|
+
verified: false,
|
|
203
|
+
error:
|
|
204
|
+
'No eth proof-owner key available (no RECLAIM_PRIVATE_KEY in env, ' +
|
|
205
|
+
'.env, or RECLAIM_PRIVATE_KEY_FILE). Call resolve_owner_key, then ' +
|
|
206
|
+
'issue_credentials (generate) or import_credentials (provide one), ' +
|
|
207
|
+
'and retry run_proof.',
|
|
208
|
+
errorKind: 'missing-owner-key',
|
|
209
|
+
}
|
|
179
210
|
}
|
|
211
|
+
|
|
212
|
+
if(
|
|
213
|
+
opts.ownerAddress
|
|
214
|
+
&& opts.ownerAddress.toLowerCase() !== resolved.address
|
|
215
|
+
) {
|
|
216
|
+
return {
|
|
217
|
+
proof: undefined,
|
|
218
|
+
extractedValue: '',
|
|
219
|
+
extractedParameters: {},
|
|
220
|
+
verified: false,
|
|
221
|
+
error:
|
|
222
|
+
`Requested ownerAddress "${opts.ownerAddress}" does not match ` +
|
|
223
|
+
`the resolved eth key (${resolved.address}, source: ` +
|
|
224
|
+
`${resolved.source}). ` +
|
|
225
|
+
'Call resolve_owner_key to get the current address, or update the ' +
|
|
226
|
+
'configured key.',
|
|
227
|
+
errorKind: 'missing-owner-key',
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
ownerPrivateKey = resolved.privateKey
|
|
180
232
|
}
|
|
181
233
|
|
|
182
234
|
try {
|
|
183
|
-
//
|
|
184
|
-
//
|
|
235
|
+
// Init the TLS crypto backend (idempotent), then fetch ZK circuits
|
|
236
|
+
// lazily on the first proof (not at install time).
|
|
237
|
+
ensureAttestorCrypto()
|
|
185
238
|
await ensureZkFiles()
|
|
186
239
|
|
|
187
|
-
const params
|
|
188
|
-
url: provider.url,
|
|
189
|
-
method: provider.method,
|
|
190
|
-
...(provider.headers !== undefined && { headers: provider.headers }),
|
|
191
|
-
...(provider.body !== undefined && { body: provider.body }),
|
|
192
|
-
responseMatches: provider.responseMatches,
|
|
193
|
-
responseRedactions: provider.responseRedactions ?? [],
|
|
194
|
-
...(provider.paramValues !== undefined && {
|
|
195
|
-
paramValues: provider.paramValues,
|
|
196
|
-
}),
|
|
197
|
-
}
|
|
240
|
+
const params = buildHttpParams(provider)
|
|
198
241
|
|
|
199
242
|
// Diagnostic logger capture is gated behind RECLAIM_AGENT_TRACE so the
|
|
200
243
|
// happy path doesn't pay the cost (the attestor SDK emits a *lot* of
|
|
@@ -214,8 +257,8 @@ export async function runAttestorProof(
|
|
|
214
257
|
headers: secrets,
|
|
215
258
|
},
|
|
216
259
|
ownerPrivateKey,
|
|
217
|
-
client: { url: resolveAttestorUrl(attestorUrl) },
|
|
218
|
-
zkEngine: '
|
|
260
|
+
client: { url: resolveAttestorUrl(opts.attestorUrl) },
|
|
261
|
+
zkEngine: opts.zkEngine ?? 'gnark',
|
|
219
262
|
...(capture !== undefined && { logger: capture.logger as Logger }),
|
|
220
263
|
})
|
|
221
264
|
} catch(err) {
|
|
@@ -234,27 +277,8 @@ export async function runAttestorProof(
|
|
|
234
277
|
return errorResult
|
|
235
278
|
}
|
|
236
279
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const claimData =
|
|
240
|
-
claimRecord['claim'] as Record<string, unknown> | undefined
|
|
241
|
-
|
|
242
|
-
// claimData.context is a JSON-encoded string carrying
|
|
243
|
-
// { extractedParameters: {...}, providerHash, ... }.
|
|
244
|
-
let context: Record<string, unknown> = {}
|
|
245
|
-
const rawContext = claimData?.['context']
|
|
246
|
-
if(typeof rawContext === 'string') {
|
|
247
|
-
try {
|
|
248
|
-
context = JSON.parse(rawContext) as Record<string, unknown>
|
|
249
|
-
} catch{
|
|
250
|
-
// Leave context empty if it isn't valid JSON.
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const extractedParameters =
|
|
255
|
-
(context['extractedParameters'] as Record<string, string> | undefined) ??
|
|
256
|
-
{}
|
|
257
|
-
const extractedValue = Object.values(extractedParameters)[0] ?? ''
|
|
280
|
+
const { extractedValue, extractedParameters, identifier, owner, claimData }
|
|
281
|
+
= parseClaim(claim)
|
|
258
282
|
|
|
259
283
|
const result: ProofResult = {
|
|
260
284
|
proof: claim,
|
|
@@ -262,16 +286,33 @@ export async function runAttestorProof(
|
|
|
262
286
|
extractedParameters,
|
|
263
287
|
verified: true,
|
|
264
288
|
}
|
|
265
|
-
|
|
266
|
-
if(typeof identifier === 'string') {
|
|
289
|
+
if(identifier !== undefined) {
|
|
267
290
|
result.identifier = identifier
|
|
268
291
|
}
|
|
269
292
|
|
|
270
|
-
|
|
271
|
-
if(typeof owner === 'string') {
|
|
293
|
+
if(owner !== undefined) {
|
|
272
294
|
result.owner = owner
|
|
273
295
|
}
|
|
274
296
|
|
|
297
|
+
// Structured claim + signature so the result JWS can carry a nested,
|
|
298
|
+
// attestor-signed proof the Consumer verifies independently.
|
|
299
|
+
if(opts.includeAttestorClaim) {
|
|
300
|
+
const sigs = (claim as {
|
|
301
|
+
signatures?: { attestorAddress?: unknown, claimSignature?: unknown }
|
|
302
|
+
}).signatures
|
|
303
|
+
if(
|
|
304
|
+
claimData
|
|
305
|
+
&& typeof sigs?.attestorAddress === 'string'
|
|
306
|
+
&& sigs.claimSignature instanceof Uint8Array
|
|
307
|
+
) {
|
|
308
|
+
result.attestorClaim = {
|
|
309
|
+
claim: claimData,
|
|
310
|
+
attestorAddress: sigs.attestorAddress,
|
|
311
|
+
claimSignature: '0x' + bytesToHex(sigs.claimSignature),
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
275
316
|
// Only set when RECLAIM_AGENT_TRACE=1. Full stream — the MCP layer
|
|
276
317
|
// trims for the LLM-visible response; the on-disk dump gets it all.
|
|
277
318
|
if(attestorLogs !== undefined && attestorLogs.length > 0) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Proof primitives shared with the app's verification runner: the attestor
|
|
2
|
+
// param/claim plumbing, the ZK-file bootstrap, and the agent's own
|
|
3
|
+
// `runAttestorProof`. Exposed as `@reclaimprotocol/agent/proof`.
|
|
4
|
+
export type {
|
|
5
|
+
AttestorClaim,
|
|
6
|
+
AttestorLogEntry,
|
|
7
|
+
ProofResult,
|
|
8
|
+
RunAttestorProofOptions,
|
|
9
|
+
} from './attestor.ts'
|
|
10
|
+
export { runAttestorProof, tailLogs, warnsAndErrors } from './attestor.ts'
|
|
11
|
+
export {
|
|
12
|
+
buildHttpParams,
|
|
13
|
+
ensureAttestorCrypto,
|
|
14
|
+
type ParsedClaim,
|
|
15
|
+
parseClaim,
|
|
16
|
+
resolveAttestorUrl,
|
|
17
|
+
} from './proof-core.ts'
|
|
18
|
+
export { ensureZkFiles } from './zk-files.ts'
|
|
19
|
+
// Re-exported attestor-core claim primitive so the agent is the single
|
|
20
|
+
// integration point with @reclaimprotocol/attestor-core across the builder.
|
|
21
|
+
export { createClaimOnAttestor } from '@reclaimprotocol/attestor-core'
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared attestor-claim plumbing used by both proof callers: the agent's MCP
|
|
3
|
+
* `run_proof` (which resolves the owner key from the credential cache and
|
|
4
|
+
* captures trace logs) and the app's verification runner (which signs with an
|
|
5
|
+
* ephemeral per-session key and builds a nested-proof claim). Only those
|
|
6
|
+
* concerns differ — building the HTTP params, resolving the attestor URL, and
|
|
7
|
+
* parsing the claim response are identical, so they live here.
|
|
8
|
+
*/
|
|
9
|
+
import type { ProviderParams } from '@reclaimprotocol/attestor-core'
|
|
10
|
+
import { setCryptoImplementation } from '@reclaimprotocol/tls'
|
|
11
|
+
import { webcryptoCrypto } from '@reclaimprotocol/tls/webcrypto'
|
|
12
|
+
import type { ReclaimProvider } from '../provider/schema.ts'
|
|
13
|
+
|
|
14
|
+
const FALLBACK_ATTESTOR_URL = 'wss://attestor.reclaimprotocol.org:444/ws'
|
|
15
|
+
|
|
16
|
+
let cryptoInitialized = false
|
|
17
|
+
|
|
18
|
+
/** One-time crypto backend init for `@reclaimprotocol/tls` (idempotent). The
|
|
19
|
+
* package ships with an empty `crypto = {}` and defers the backend to the
|
|
20
|
+
* caller; without this the first proof dies inside the TLS client with
|
|
21
|
+
* `crypto.randomBytes is not a function`. Shared by every attestor caller —
|
|
22
|
+
* the agent MCP `run_proof` tool and the app's verification runner. */
|
|
23
|
+
export function ensureAttestorCrypto(): void {
|
|
24
|
+
if(cryptoInitialized) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setCryptoImplementation(webcryptoCrypto)
|
|
29
|
+
cryptoInitialized = true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Resolve the attestor websocket URL: explicit override → env → public
|
|
33
|
+
* default. Resolved per-call so an env change or per-request override takes
|
|
34
|
+
* effect without restarting. */
|
|
35
|
+
export function resolveAttestorUrl(override?: string): string {
|
|
36
|
+
return (
|
|
37
|
+
override ?? process.env['RECLAIM_ATTESTOR_URL'] ?? FALLBACK_ATTESTOR_URL
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Map a verification's provider recipe straight to the attestor's HTTP
|
|
42
|
+
* params — never synthesized from captured traffic. */
|
|
43
|
+
export function buildHttpParams(
|
|
44
|
+
provider: ReclaimProvider,
|
|
45
|
+
): ProviderParams<'http'> {
|
|
46
|
+
return {
|
|
47
|
+
url: provider.url,
|
|
48
|
+
method: provider.method,
|
|
49
|
+
...(provider.headers !== undefined && { headers: provider.headers }),
|
|
50
|
+
...(provider.body !== undefined && { body: provider.body }),
|
|
51
|
+
responseMatches: provider.responseMatches,
|
|
52
|
+
responseRedactions: provider.responseRedactions ?? [],
|
|
53
|
+
...(provider.paramValues !== undefined && {
|
|
54
|
+
paramValues: provider.paramValues,
|
|
55
|
+
}),
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ParsedClaim {
|
|
60
|
+
/** ProviderClaimData: provider, parameters, context, owner, identifier, … */
|
|
61
|
+
claimData?: Record<string, unknown>
|
|
62
|
+
extractedParameters: Record<string, string>
|
|
63
|
+
extractedValue: string
|
|
64
|
+
identifier?: string
|
|
65
|
+
owner?: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Pull claimData + decoded `context.extractedParameters` (plus identifier /
|
|
69
|
+
* owner) out of a `createClaimOnAttestor` result. The full result still
|
|
70
|
+
* carries signatures the caller may need for nested-proof building. */
|
|
71
|
+
export function parseClaim(claim: unknown): ParsedClaim {
|
|
72
|
+
const claimRecord = claim as Record<string, unknown>
|
|
73
|
+
const claimData = claimRecord['claim'] as Record<string, unknown> | undefined
|
|
74
|
+
|
|
75
|
+
// claimData.context is a JSON-encoded string carrying
|
|
76
|
+
// { extractedParameters: {...}, providerHash, ... }.
|
|
77
|
+
let context: Record<string, unknown> = {}
|
|
78
|
+
const rawContext = claimData?.['context']
|
|
79
|
+
if(typeof rawContext === 'string') {
|
|
80
|
+
try {
|
|
81
|
+
context = JSON.parse(rawContext) as Record<string, unknown>
|
|
82
|
+
} catch{
|
|
83
|
+
// Leave context empty if it isn't valid JSON.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const extractedParameters =
|
|
88
|
+
(context['extractedParameters'] as Record<string, string> | undefined) ?? {}
|
|
89
|
+
|
|
90
|
+
const parsed: ParsedClaim = {
|
|
91
|
+
extractedParameters,
|
|
92
|
+
extractedValue: Object.values(extractedParameters)[0] ?? '',
|
|
93
|
+
}
|
|
94
|
+
if(claimData) {
|
|
95
|
+
parsed.claimData = claimData
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const identifier = claimData?.['identifier']
|
|
99
|
+
if(typeof identifier === 'string') {
|
|
100
|
+
parsed.identifier = identifier
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const owner = claimData?.['owner']
|
|
104
|
+
if(typeof owner === 'string') {
|
|
105
|
+
parsed.owner = owner
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return parsed
|
|
109
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Provider primitives shared with the app's capture pipeline:
|
|
2
|
+
// the attestor-derived recipe types, secret classification, and the GraphQL
|
|
3
|
+
// op parser. Exposed as `@reclaimprotocol/agent/provider`.
|
|
4
|
+
export { extractGraphqlOp, looksLikeGraphqlEndpoint } from './graphql.ts'
|
|
5
|
+
export type {
|
|
6
|
+
CapturedRequest,
|
|
7
|
+
HttpMethod,
|
|
8
|
+
OprfMode,
|
|
9
|
+
ReclaimProvider,
|
|
10
|
+
RequestConcern,
|
|
11
|
+
ResponseMatch,
|
|
12
|
+
ResponseRedaction,
|
|
13
|
+
SecretParamRef,
|
|
14
|
+
} from './schema.ts'
|
|
15
|
+
export { classifyHeader, splitSecrets } from './secrets.ts'
|
|
16
|
+
// Re-exported attestor-core provider primitives (the registry, the param hash,
|
|
17
|
+
// and the param type) so the builder imports them via the agent rather than
|
|
18
|
+
// depending on @reclaimprotocol/attestor-core directly.
|
|
19
|
+
export { hashProviderParams, providers } from '@reclaimprotocol/attestor-core'
|
|
20
|
+
export type { ProviderParams } from '@reclaimprotocol/attestor-core'
|