@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/lib/proof/attestor.js
CHANGED
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
// responseMatches are the regex/contains checks the attestor runs on the
|
|
6
6
|
// revealed slice; jsonPath/xPath live on responseRedactions (what the prover
|
|
7
7
|
// reveals), never on responseMatches.
|
|
8
|
+
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
8
9
|
import { createClaimOnAttestor, } from '@reclaimprotocol/attestor-core';
|
|
9
|
-
import {
|
|
10
|
+
import { resolveEthKey } from "../mcp/tools/authenticate/eth-key.js";
|
|
11
|
+
import { buildHttpParams, ensureAttestorCrypto, parseClaim, resolveAttestorUrl, } from "./proof-core.js";
|
|
10
12
|
import { ensureZkFiles } from "./zk-files.js";
|
|
11
13
|
/** Trim a captured log stream to the last N entries — for shrinking the
|
|
12
14
|
* LLM-visible response while the full stream stays in the on-disk dump. */
|
|
@@ -80,50 +82,55 @@ function makeCaptureLogger() {
|
|
|
80
82
|
};
|
|
81
83
|
return { logger: make({}), entries };
|
|
82
84
|
}
|
|
83
|
-
/** Default public attestor websocket URL. Resolved per-call so an env-var
|
|
84
|
-
* change or per-request override takes effect without restarting the
|
|
85
|
-
* MCP server. */
|
|
86
|
-
const FALLBACK_ATTESTOR_URL = 'wss://attestor.reclaimprotocol.org:444/ws';
|
|
87
|
-
function resolveAttestorUrl(override) {
|
|
88
|
-
return (override ?? process.env['RECLAIM_ATTESTOR_URL'] ?? FALLBACK_ATTESTOR_URL);
|
|
89
|
-
}
|
|
90
85
|
// ---------------------------------------------------------------------------
|
|
91
86
|
// Main entry point
|
|
92
87
|
// ---------------------------------------------------------------------------
|
|
93
|
-
export async function runAttestorProof(provider, secrets,
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
88
|
+
export async function runAttestorProof(provider, secrets, opts = {}) {
|
|
89
|
+
// Sign with the caller-supplied key (the app/VC's ephemeral per-session
|
|
90
|
+
// key) when given; otherwise resolve env/.env/file. `ownerAddress` is a
|
|
91
|
+
// sanity check on the resolved key (ignored when a key is supplied).
|
|
92
|
+
let ownerPrivateKey;
|
|
93
|
+
if (opts.ownerPrivateKey) {
|
|
94
|
+
ownerPrivateKey = opts.ownerPrivateKey;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const resolved = resolveEthKey();
|
|
98
|
+
if (!resolved) {
|
|
99
|
+
return {
|
|
100
|
+
proof: undefined,
|
|
101
|
+
extractedValue: '',
|
|
102
|
+
extractedParameters: {},
|
|
103
|
+
verified: false,
|
|
104
|
+
error: 'No eth proof-owner key available (no RECLAIM_PRIVATE_KEY in env, ' +
|
|
105
|
+
'.env, or RECLAIM_PRIVATE_KEY_FILE). Call resolve_owner_key, then ' +
|
|
106
|
+
'issue_credentials (generate) or import_credentials (provide one), ' +
|
|
107
|
+
'and retry run_proof.',
|
|
108
|
+
errorKind: 'missing-owner-key',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (opts.ownerAddress
|
|
112
|
+
&& opts.ownerAddress.toLowerCase() !== resolved.address) {
|
|
113
|
+
return {
|
|
114
|
+
proof: undefined,
|
|
115
|
+
extractedValue: '',
|
|
116
|
+
extractedParameters: {},
|
|
117
|
+
verified: false,
|
|
118
|
+
error: `Requested ownerAddress "${opts.ownerAddress}" does not match ` +
|
|
119
|
+
`the resolved eth key (${resolved.address}, source: ` +
|
|
120
|
+
`${resolved.source}). ` +
|
|
121
|
+
'Call resolve_owner_key to get the current address, or update the ' +
|
|
122
|
+
'configured key.',
|
|
123
|
+
errorKind: 'missing-owner-key',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
ownerPrivateKey = resolved.privateKey;
|
|
111
127
|
}
|
|
112
128
|
try {
|
|
113
|
-
//
|
|
114
|
-
//
|
|
129
|
+
// Init the TLS crypto backend (idempotent), then fetch ZK circuits
|
|
130
|
+
// lazily on the first proof (not at install time).
|
|
131
|
+
ensureAttestorCrypto();
|
|
115
132
|
await ensureZkFiles();
|
|
116
|
-
const params =
|
|
117
|
-
url: provider.url,
|
|
118
|
-
method: provider.method,
|
|
119
|
-
...(provider.headers !== undefined && { headers: provider.headers }),
|
|
120
|
-
...(provider.body !== undefined && { body: provider.body }),
|
|
121
|
-
responseMatches: provider.responseMatches,
|
|
122
|
-
responseRedactions: provider.responseRedactions ?? [],
|
|
123
|
-
...(provider.paramValues !== undefined && {
|
|
124
|
-
paramValues: provider.paramValues,
|
|
125
|
-
}),
|
|
126
|
-
};
|
|
133
|
+
const params = buildHttpParams(provider);
|
|
127
134
|
// Diagnostic logger capture is gated behind RECLAIM_AGENT_TRACE so the
|
|
128
135
|
// happy path doesn't pay the cost (the attestor SDK emits a *lot* of
|
|
129
136
|
// trace/debug entries during ZK setup). Flip RECLAIM_AGENT_TRACE=1 to
|
|
@@ -141,8 +148,8 @@ export async function runAttestorProof(provider, secrets, attestorUrl, ownerAddr
|
|
|
141
148
|
headers: secrets,
|
|
142
149
|
},
|
|
143
150
|
ownerPrivateKey,
|
|
144
|
-
client: { url: resolveAttestorUrl(attestorUrl) },
|
|
145
|
-
zkEngine: '
|
|
151
|
+
client: { url: resolveAttestorUrl(opts.attestorUrl) },
|
|
152
|
+
zkEngine: opts.zkEngine ?? 'gnark',
|
|
146
153
|
...(capture !== undefined && { logger: capture.logger }),
|
|
147
154
|
});
|
|
148
155
|
}
|
|
@@ -160,38 +167,33 @@ export async function runAttestorProof(provider, secrets, attestorUrl, ownerAddr
|
|
|
160
167
|
}
|
|
161
168
|
return errorResult;
|
|
162
169
|
}
|
|
163
|
-
|
|
164
|
-
const claimRecord = claim;
|
|
165
|
-
const claimData = claimRecord['claim'];
|
|
166
|
-
// claimData.context is a JSON-encoded string carrying
|
|
167
|
-
// { extractedParameters: {...}, providerHash, ... }.
|
|
168
|
-
let context = {};
|
|
169
|
-
const rawContext = claimData?.['context'];
|
|
170
|
-
if (typeof rawContext === 'string') {
|
|
171
|
-
try {
|
|
172
|
-
context = JSON.parse(rawContext);
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
// Leave context empty if it isn't valid JSON.
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
const extractedParameters = context['extractedParameters'] ??
|
|
179
|
-
{};
|
|
180
|
-
const extractedValue = Object.values(extractedParameters)[0] ?? '';
|
|
170
|
+
const { extractedValue, extractedParameters, identifier, owner, claimData } = parseClaim(claim);
|
|
181
171
|
const result = {
|
|
182
172
|
proof: claim,
|
|
183
173
|
extractedValue,
|
|
184
174
|
extractedParameters,
|
|
185
175
|
verified: true,
|
|
186
176
|
};
|
|
187
|
-
|
|
188
|
-
if (typeof identifier === 'string') {
|
|
177
|
+
if (identifier !== undefined) {
|
|
189
178
|
result.identifier = identifier;
|
|
190
179
|
}
|
|
191
|
-
|
|
192
|
-
if (typeof owner === 'string') {
|
|
180
|
+
if (owner !== undefined) {
|
|
193
181
|
result.owner = owner;
|
|
194
182
|
}
|
|
183
|
+
// Structured claim + signature so the result JWS can carry a nested,
|
|
184
|
+
// attestor-signed proof the Consumer verifies independently.
|
|
185
|
+
if (opts.includeAttestorClaim) {
|
|
186
|
+
const sigs = claim.signatures;
|
|
187
|
+
if (claimData
|
|
188
|
+
&& typeof sigs?.attestorAddress === 'string'
|
|
189
|
+
&& sigs.claimSignature instanceof Uint8Array) {
|
|
190
|
+
result.attestorClaim = {
|
|
191
|
+
claim: claimData,
|
|
192
|
+
attestorAddress: sigs.attestorAddress,
|
|
193
|
+
claimSignature: '0x' + bytesToHex(sigs.claimSignature),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
195
197
|
// Only set when RECLAIM_AGENT_TRACE=1. Full stream — the MCP layer
|
|
196
198
|
// trims for the LLM-visible response; the on-disk dump gets it all.
|
|
197
199
|
if (attestorLogs !== undefined && attestorLogs.length > 0) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { AttestorClaim, AttestorLogEntry, ProofResult, RunAttestorProofOptions, } from './attestor.ts';
|
|
2
|
+
export { runAttestorProof, tailLogs, warnsAndErrors } from './attestor.ts';
|
|
3
|
+
export { buildHttpParams, ensureAttestorCrypto, type ParsedClaim, parseClaim, resolveAttestorUrl, } from './proof-core.ts';
|
|
4
|
+
export { ensureZkFiles } from './zk-files.ts';
|
|
5
|
+
export { createClaimOnAttestor } from '@reclaimprotocol/attestor-core';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { runAttestorProof, tailLogs, warnsAndErrors } from "./attestor.js";
|
|
2
|
+
export { buildHttpParams, ensureAttestorCrypto, parseClaim, resolveAttestorUrl, } from "./proof-core.js";
|
|
3
|
+
export { ensureZkFiles } from "./zk-files.js";
|
|
4
|
+
// Re-exported attestor-core claim primitive so the agent is the single
|
|
5
|
+
// integration point with @reclaimprotocol/attestor-core across the builder.
|
|
6
|
+
export { createClaimOnAttestor } from '@reclaimprotocol/attestor-core';
|
|
@@ -0,0 +1,35 @@
|
|
|
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 type { ReclaimProvider } from '../provider/schema.ts';
|
|
11
|
+
/** One-time crypto backend init for `@reclaimprotocol/tls` (idempotent). The
|
|
12
|
+
* package ships with an empty `crypto = {}` and defers the backend to the
|
|
13
|
+
* caller; without this the first proof dies inside the TLS client with
|
|
14
|
+
* `crypto.randomBytes is not a function`. Shared by every attestor caller —
|
|
15
|
+
* the agent MCP `run_proof` tool and the app's verification runner. */
|
|
16
|
+
export declare function ensureAttestorCrypto(): void;
|
|
17
|
+
/** Resolve the attestor websocket URL: explicit override → env → public
|
|
18
|
+
* default. Resolved per-call so an env change or per-request override takes
|
|
19
|
+
* effect without restarting. */
|
|
20
|
+
export declare function resolveAttestorUrl(override?: string): string;
|
|
21
|
+
/** Map a verification's provider recipe straight to the attestor's HTTP
|
|
22
|
+
* params — never synthesized from captured traffic. */
|
|
23
|
+
export declare function buildHttpParams(provider: ReclaimProvider): ProviderParams<'http'>;
|
|
24
|
+
export interface ParsedClaim {
|
|
25
|
+
/** ProviderClaimData: provider, parameters, context, owner, identifier, … */
|
|
26
|
+
claimData?: Record<string, unknown>;
|
|
27
|
+
extractedParameters: Record<string, string>;
|
|
28
|
+
extractedValue: string;
|
|
29
|
+
identifier?: string;
|
|
30
|
+
owner?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Pull claimData + decoded `context.extractedParameters` (plus identifier /
|
|
33
|
+
* owner) out of a `createClaimOnAttestor` result. The full result still
|
|
34
|
+
* carries signatures the caller may need for nested-proof building. */
|
|
35
|
+
export declare function parseClaim(claim: unknown): ParsedClaim;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { setCryptoImplementation } from '@reclaimprotocol/tls';
|
|
2
|
+
import { webcryptoCrypto } from '@reclaimprotocol/tls/webcrypto';
|
|
3
|
+
const FALLBACK_ATTESTOR_URL = 'wss://attestor.reclaimprotocol.org:444/ws';
|
|
4
|
+
let cryptoInitialized = false;
|
|
5
|
+
/** One-time crypto backend init for `@reclaimprotocol/tls` (idempotent). The
|
|
6
|
+
* package ships with an empty `crypto = {}` and defers the backend to the
|
|
7
|
+
* caller; without this the first proof dies inside the TLS client with
|
|
8
|
+
* `crypto.randomBytes is not a function`. Shared by every attestor caller —
|
|
9
|
+
* the agent MCP `run_proof` tool and the app's verification runner. */
|
|
10
|
+
export function ensureAttestorCrypto() {
|
|
11
|
+
if (cryptoInitialized) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
setCryptoImplementation(webcryptoCrypto);
|
|
15
|
+
cryptoInitialized = true;
|
|
16
|
+
}
|
|
17
|
+
/** Resolve the attestor websocket URL: explicit override → env → public
|
|
18
|
+
* default. Resolved per-call so an env change or per-request override takes
|
|
19
|
+
* effect without restarting. */
|
|
20
|
+
export function resolveAttestorUrl(override) {
|
|
21
|
+
return (override ?? process.env['RECLAIM_ATTESTOR_URL'] ?? FALLBACK_ATTESTOR_URL);
|
|
22
|
+
}
|
|
23
|
+
/** Map a verification's provider recipe straight to the attestor's HTTP
|
|
24
|
+
* params — never synthesized from captured traffic. */
|
|
25
|
+
export function buildHttpParams(provider) {
|
|
26
|
+
return {
|
|
27
|
+
url: provider.url,
|
|
28
|
+
method: provider.method,
|
|
29
|
+
...(provider.headers !== undefined && { headers: provider.headers }),
|
|
30
|
+
...(provider.body !== undefined && { body: provider.body }),
|
|
31
|
+
responseMatches: provider.responseMatches,
|
|
32
|
+
responseRedactions: provider.responseRedactions ?? [],
|
|
33
|
+
...(provider.paramValues !== undefined && {
|
|
34
|
+
paramValues: provider.paramValues,
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Pull claimData + decoded `context.extractedParameters` (plus identifier /
|
|
39
|
+
* owner) out of a `createClaimOnAttestor` result. The full result still
|
|
40
|
+
* carries signatures the caller may need for nested-proof building. */
|
|
41
|
+
export function parseClaim(claim) {
|
|
42
|
+
const claimRecord = claim;
|
|
43
|
+
const claimData = claimRecord['claim'];
|
|
44
|
+
// claimData.context is a JSON-encoded string carrying
|
|
45
|
+
// { extractedParameters: {...}, providerHash, ... }.
|
|
46
|
+
let context = {};
|
|
47
|
+
const rawContext = claimData?.['context'];
|
|
48
|
+
if (typeof rawContext === 'string') {
|
|
49
|
+
try {
|
|
50
|
+
context = JSON.parse(rawContext);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Leave context empty if it isn't valid JSON.
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const extractedParameters = context['extractedParameters'] ?? {};
|
|
57
|
+
const parsed = {
|
|
58
|
+
extractedParameters,
|
|
59
|
+
extractedValue: Object.values(extractedParameters)[0] ?? '',
|
|
60
|
+
};
|
|
61
|
+
if (claimData) {
|
|
62
|
+
parsed.claimData = claimData;
|
|
63
|
+
}
|
|
64
|
+
const identifier = claimData?.['identifier'];
|
|
65
|
+
if (typeof identifier === 'string') {
|
|
66
|
+
parsed.identifier = identifier;
|
|
67
|
+
}
|
|
68
|
+
const owner = claimData?.['owner'];
|
|
69
|
+
if (typeof owner === 'string') {
|
|
70
|
+
parsed.owner = owner;
|
|
71
|
+
}
|
|
72
|
+
return parsed;
|
|
73
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { extractGraphqlOp, looksLikeGraphqlEndpoint } from './graphql.ts';
|
|
2
|
+
export type { CapturedRequest, HttpMethod, OprfMode, ReclaimProvider, RequestConcern, ResponseMatch, ResponseRedaction, SecretParamRef, } from './schema.ts';
|
|
3
|
+
export { classifyHeader, splitSecrets } from './secrets.ts';
|
|
4
|
+
export { hashProviderParams, providers } from '@reclaimprotocol/attestor-core';
|
|
5
|
+
export type { ProviderParams } from '@reclaimprotocol/attestor-core';
|
|
@@ -0,0 +1,9 @@
|
|
|
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.js";
|
|
5
|
+
export { classifyHeader, splitSecrets } from "./secrets.js";
|
|
6
|
+
// Re-exported attestor-core provider primitives (the registry, the param hash,
|
|
7
|
+
// and the param type) so the builder imports them via the agent rather than
|
|
8
|
+
// depending on @reclaimprotocol/attestor-core directly.
|
|
9
|
+
export { hashProviderParams, providers } from '@reclaimprotocol/attestor-core';
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import type { ReclaimClient } from '@reclaimprotocol/client';
|
|
2
|
-
import type { CreateProviderVersionRequest
|
|
2
|
+
import type { CreateProviderVersionRequest, ProviderVersionRef } from '@reclaimprotocol/client/openapi';
|
|
3
3
|
import type { ReclaimProvider } from './schema.ts';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* API URL the attestor replays.
|
|
11
|
-
*
|
|
12
|
-
* Secrets are NOT persisted — the verification client re-supplies
|
|
13
|
-
* them at runtime via `credentials: 'include'`.
|
|
5
|
+
* Derive the version's `requiredContext` JSON Schema from the
|
|
6
|
+
* `{{context.<name>}}` placeholders in the provider's url/body — mechanical,
|
|
7
|
+
* so a published recipe can never reference a context value the Builder
|
|
8
|
+
* doesn't require. Returns undefined when the recipe has none (the field is
|
|
9
|
+
* optional). Authors can refine types/descriptions in the version editor.
|
|
14
10
|
*/
|
|
15
|
-
export declare function
|
|
11
|
+
export declare function deriveRequiredContext(provider: ReclaimProvider): CreateProviderVersionRequest['requiredContext'];
|
|
12
|
+
export declare function providerToCreateVersionRequest(provider: ReclaimProvider, initialUrl: string, notes?: string, version?: ProviderVersionRef): CreateProviderVersionRequest;
|
|
16
13
|
/**
|
|
17
14
|
* Fetch the current versions for a provider and return the next version above
|
|
18
15
|
* the highest existing one (bumping the patch number), or 1.0.0 when the
|
|
19
16
|
* provider has no versions yet. A failed lookup propagates — silently
|
|
20
17
|
* resetting to 1.0.0 would re-publish a v3 provider as v1.0.0.
|
|
21
18
|
*/
|
|
22
|
-
export declare function nextVersion(client: ReclaimClient, providerId: string): Promise<
|
|
19
|
+
export declare function nextVersion(client: ReclaimClient, providerId: string): Promise<ProviderVersionRef>;
|
|
@@ -9,7 +9,35 @@
|
|
|
9
9
|
* Secrets are NOT persisted — the verification client re-supplies
|
|
10
10
|
* them at runtime via `credentials: 'include'`.
|
|
11
11
|
*/
|
|
12
|
+
/** `{{context.<name>}}` placeholders in a request URL/body: values the
|
|
13
|
+
* CONSUMER supplies at verification time via the session `context`. Bare
|
|
14
|
+
* `{{name}}` placeholders (extraction params) are not consumer-supplied
|
|
15
|
+
* and are ignored. */
|
|
16
|
+
const CONTEXT_PARAM_RE = /\{\{context\.([A-Za-z_][A-Za-z0-9_]*)\}\}/g;
|
|
17
|
+
/**
|
|
18
|
+
* Derive the version's `requiredContext` JSON Schema from the
|
|
19
|
+
* `{{context.<name>}}` placeholders in the provider's url/body — mechanical,
|
|
20
|
+
* so a published recipe can never reference a context value the Builder
|
|
21
|
+
* doesn't require. Returns undefined when the recipe has none (the field is
|
|
22
|
+
* optional). Authors can refine types/descriptions in the version editor.
|
|
23
|
+
*/
|
|
24
|
+
export function deriveRequiredContext(provider) {
|
|
25
|
+
const haystack = `${provider.url}\n${provider.body ?? ''}`;
|
|
26
|
+
const names = new Set();
|
|
27
|
+
for (const m of haystack.matchAll(CONTEXT_PARAM_RE)) {
|
|
28
|
+
names.add(m[1]);
|
|
29
|
+
}
|
|
30
|
+
if (!names.size) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const properties = {};
|
|
34
|
+
for (const name of names) {
|
|
35
|
+
properties[name] = { type: 'string' };
|
|
36
|
+
}
|
|
37
|
+
return { type: 'object', required: [...names], properties };
|
|
38
|
+
}
|
|
12
39
|
export function providerToCreateVersionRequest(provider, initialUrl, notes, version) {
|
|
40
|
+
const requiredContext = deriveRequiredContext(provider);
|
|
13
41
|
// Inline responseRedactions into matches[*].extract (1-to-1 by index).
|
|
14
42
|
const matches = (provider.responseMatches ?? []).map((match, i) => {
|
|
15
43
|
const redaction = provider.responseRedactions?.[i];
|
|
@@ -33,10 +61,16 @@ export function providerToCreateVersionRequest(provider, initialUrl, notes, vers
|
|
|
33
61
|
},
|
|
34
62
|
],
|
|
35
63
|
allowedJsRequests: [],
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
: {}
|
|
64
|
+
// Mirror the builder openapi defaults explicitly — the server does not
|
|
65
|
+
// apply schema defaults to request bodies.
|
|
66
|
+
webSettings: {
|
|
67
|
+
geoLocation: '{{DYNAMIC_GEO}}',
|
|
68
|
+
clientOptions: { portal: { useProxy: true } },
|
|
69
|
+
},
|
|
70
|
+
// Derived from `{{context.<name>}}` placeholders only — a captured
|
|
71
|
+
// provider's `paramValues` are extracted response parameters, not
|
|
72
|
+
// consumer context, and never become requiredContext.
|
|
73
|
+
...(requiredContext ? { requiredContext } : {}),
|
|
40
74
|
...(notes ? { notes } : {}),
|
|
41
75
|
};
|
|
42
76
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReclaimProvider } from './schema.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Advisory pre-publish lint for a drafted provider — never a gate. Surfaces
|
|
4
|
+
* only what the AUTHOR must decide; everything testable is tested by the
|
|
5
|
+
* verification client itself (CDP capture sees all traffic — navigations,
|
|
6
|
+
* XHRs, fetches — and `checkCandidate` in packages/app src/verify/run.ts
|
|
7
|
+
* selects the captured request that satisfies the recipe, skipping the
|
|
8
|
+
* rest). Interpolation and matching are plain text and work for any
|
|
9
|
+
* captured content; extract selectors apply client-side in spec order
|
|
10
|
+
* xPath → jsonPath → regex, each to the prior selection.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verificationWarnings(provider: ReclaimProvider): string[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advisory pre-publish lint for a drafted provider — never a gate. Surfaces
|
|
3
|
+
* only what the AUTHOR must decide; everything testable is tested by the
|
|
4
|
+
* verification client itself (CDP capture sees all traffic — navigations,
|
|
5
|
+
* XHRs, fetches — and `checkCandidate` in packages/app src/verify/run.ts
|
|
6
|
+
* selects the captured request that satisfies the recipe, skipping the
|
|
7
|
+
* rest). Interpolation and matching are plain text and work for any
|
|
8
|
+
* captured content; extract selectors apply client-side in spec order
|
|
9
|
+
* xPath → jsonPath → regex, each to the prior selection.
|
|
10
|
+
*/
|
|
11
|
+
export function verificationWarnings(provider) {
|
|
12
|
+
const out = [];
|
|
13
|
+
// Untemplated user-specific URL parts: any captured param value baked
|
|
14
|
+
// literally into the URL makes the provider user-specific. Only the dev
|
|
15
|
+
// can decide: consumer-supplied → {{context.<name>}} (declared in
|
|
16
|
+
// requiredContext; consumers then send the exact value and the VC matches
|
|
17
|
+
// only that value), bare {{<name>}} (resolved from the end-user's own
|
|
18
|
+
// traffic), or re-capture a non-user-specific endpoint.
|
|
19
|
+
for (const [name, value] of Object.entries(provider.paramValues ?? {})) {
|
|
20
|
+
if (value.length >= 3 && provider.url.includes(value)) {
|
|
21
|
+
out.push(`The URL contains the captured value "${value}" (param ` +
|
|
22
|
+
`"${name}") as a literal. Decide with the dev: if consumers ` +
|
|
23
|
+
'supply it, replace with {{context.' + name + '}} (published ' +
|
|
24
|
+
'requiredContext will require it; verification matches only ' +
|
|
25
|
+
'the supplied value). Leaving it literal pins the provider ' +
|
|
26
|
+
'to this user.');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|