@reclaimprotocol/client 0.1.26 → 0.1.28

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.
Files changed (73) hide show
  1. package/README.md +634 -42
  2. package/lib/api-client.d.ts +31 -0
  3. package/lib/api-client.js +112 -0
  4. package/lib/api-consts.d.ts +4 -0
  5. package/lib/api-consts.js +4 -0
  6. package/lib/api-errors.d.ts +13 -0
  7. package/lib/api-errors.js +30 -0
  8. package/lib/api.d.ts +7 -0
  9. package/lib/api.js +3 -0
  10. package/lib/attestor-proof.d.ts +6 -0
  11. package/lib/attestor-proof.js +45 -18
  12. package/lib/client.d.ts +1 -6
  13. package/lib/client.js +12 -33
  14. package/lib/consts.d.ts +1 -1
  15. package/lib/consts.js +1 -1
  16. package/lib/eip191.d.ts +4 -2
  17. package/lib/eip191.js +17 -1
  18. package/lib/errors.d.ts +38 -4
  19. package/lib/errors.js +99 -16
  20. package/lib/index.d.ts +9 -7
  21. package/lib/index.js +8 -4
  22. package/lib/jwks.d.ts +25 -1
  23. package/lib/jwks.js +69 -4
  24. package/lib/legacy-proof.d.ts +57 -0
  25. package/lib/legacy-proof.js +211 -0
  26. package/lib/proof-hash.d.ts +35 -0
  27. package/lib/proof-hash.js +216 -0
  28. package/lib/proof-recipe.d.ts +18 -0
  29. package/lib/proof-recipe.js +37 -0
  30. package/lib/proof-trust-constants.d.ts +3 -0
  31. package/lib/proof-trust-constants.js +43 -0
  32. package/lib/proof-types.d.ts +62 -0
  33. package/lib/proof-types.js +1 -0
  34. package/lib/proof-verification-error.d.ts +13 -0
  35. package/lib/proof-verification-error.js +11 -0
  36. package/lib/reclaim.d.ts +27 -5
  37. package/lib/reclaim.js +140 -14
  38. package/lib/result.d.ts +58 -6
  39. package/lib/result.js +252 -61
  40. package/lib/routes.gen.d.ts +58 -6
  41. package/lib/routes.gen.js +16 -3
  42. package/lib/tee-binding.d.ts +82 -0
  43. package/lib/tee-binding.js +112 -0
  44. package/lib/types/openapi.gen.d.ts +1412 -193
  45. package/lib/verification-clients.d.ts +17 -0
  46. package/lib/verification-clients.js +14 -0
  47. package/lib/verify-attestor-tee.d.ts +76 -0
  48. package/lib/verify-attestor-tee.js +243 -0
  49. package/lib/verify-tee.d.ts +32 -0
  50. package/lib/verify-tee.js +347 -0
  51. package/package.json +5 -1
  52. package/src/api.ts +15 -0
  53. package/src/attestor-proof.ts +57 -20
  54. package/src/client.ts +15 -38
  55. package/src/consts.ts +1 -2
  56. package/src/eip191.ts +31 -3
  57. package/src/errors.ts +132 -18
  58. package/src/index.ts +50 -5
  59. package/src/jwks.ts +128 -5
  60. package/src/legacy-proof.ts +367 -0
  61. package/src/proof-hash.ts +316 -0
  62. package/src/proof-recipe.ts +75 -0
  63. package/src/proof-trust-constants.ts +45 -0
  64. package/src/proof-types.ts +57 -0
  65. package/src/proof-verification-error.ts +13 -0
  66. package/src/reclaim.ts +206 -19
  67. package/src/result.ts +403 -68
  68. package/src/routes.gen.ts +16 -3
  69. package/src/tee-binding.ts +192 -0
  70. package/src/types/openapi.gen.ts +1412 -193
  71. package/src/verification-clients.ts +22 -0
  72. package/src/verify-attestor-tee.ts +365 -0
  73. package/src/verify-tee.ts +507 -0
package/lib/result.js CHANGED
@@ -2,20 +2,20 @@
2
2
  * Consumer-side handling of a delivered callback. Two entry points:
3
3
  * - {@link verifyResult}: the offline primitive — decrypt + decode + optional
4
4
  * ES256K signature check (caller-supplied key) + `reclaimSessionId` nonce.
5
- * - {@link verifyResultFull}: the full async verification — discovers the
6
- * Verification Client's key via JWKS, verifies the top-level JWS, checks
7
- * `reclaimSessionId`/`aud`/`exp`, and verifies each result's nested attestor
8
- * proof + `content_hash` (see ./attestor-proof.ts and ./jwks.ts).
5
+ * - {@link verifyResultFull}: the recommended server-side verification —
6
+ * resolves a registered issuer, discovers the Verification Client's key
7
+ * via JWKS, checks
8
+ * `reclaimSessionId`/`aud` and any legacy `exp`, and passes every exact
9
+ * legacy proof to the in-package, legacy-compatible `verifyProof` verifier.
9
10
  *
10
11
  * See docs/verification-session.md → "Verification by Consumer".
11
12
  */
12
13
  import { sha256 } from '@noble/hashes/sha2.js';
13
- import { keccak_256 } from '@noble/hashes/sha3.js';
14
14
  import { decrypt as eciesDecrypt, encrypt as eciesEncrypt } from 'eciesjs';
15
- import { verifyNestedProof } from "./attestor-proof.js";
16
- import { canonicalJson } from "./canonical.js";
17
- import { b64url, base64urlToBytes, bytesToHex, hexToBytes } from "./encoding.js";
18
- import { fetchJwks, jwkToUncompressedPublicKey, selectKey, } from "./jwks.js";
15
+ import { b64url, base64urlToBytes, hexToBytes } from "./encoding.js";
16
+ import { fetchReclaimJwks, jwkToUncompressedPublicKey, selectVerificationResultKey, } from "./jwks.js";
17
+ import { verifyProof, } from "./legacy-proof.js";
18
+ import { proofHashesFromBuilderRecipe, } from "./proof-recipe.js";
19
19
  import { addressFromUncompressedPubkey, secp } from "./secp.js";
20
20
  /**
21
21
  * ECIES-encrypt `plaintext` for the holder of `publicJwk` (the org's secp256k1
@@ -134,13 +134,6 @@ export function verifyJwsSignature(jws, signerPublicKey) {
134
134
  }
135
135
  });
136
136
  }
137
- /** Content hash binding extracted parameters — MUST mirror the Verification
138
- * Client's `contentHash` exactly (keccak256 of the RFC 8785 canonical JSON,
139
- * via the shared `canonicalJson`). */
140
- function contentHash(params) {
141
- const canonical = canonicalJson(params);
142
- return '0x' + bytesToHex(keccak_256(new TextEncoder().encode(canonical)));
143
- }
144
137
  /**
145
138
  * Thrown by {@link verifyResult} / {@link verifyResultFull} (and therefore
146
139
  * `reclaim.results.verify`/`receive`) when a result fails verification. Carries
@@ -165,15 +158,17 @@ export class ResultVerificationError extends Error {
165
158
  }
166
159
  }
167
160
  /**
168
- * Full consumer verification: discovers the Verification Client's signing key
169
- * via JWKS (header `iss`/`kid`), verifies the top-level JWS, checks
170
- * `reclaimSessionId`/`aud`/`exp`, then verifies each result's nested attestor
171
- * proof and its `content_hash`. Network access (JWKS) makes this async; use
172
- * {@link verifyResult} for the offline primitive.
161
+ * Full consumer verification: resolves a trusted, registered issuer before
162
+ * using JWKS (header `iss`/`kid`), verifies the top-level JWS, checks
163
+ * `reclaimSessionId`/`aud` and any legacy `exp`, then verifies each exact
164
+ * legacy proof.
165
+ * Network access (JWKS and optional provider resolution) makes this async.
166
+ * Use {@link verifyResult} for the offline primitive.
173
167
  */
174
168
  export async function verifyResultFull(jws, opts = {}) {
175
169
  const payload = decodeJwsPayload(jws);
176
170
  const reclaimSessionId = payload.reclaimSessionId;
171
+ let jwksAttestorAddresses = [];
177
172
  /** Throw with the full invalid outcome — verification never *returns* an
178
173
  * invalid result. */
179
174
  const fail = (reason, extra = {}) => {
@@ -185,7 +180,8 @@ export async function verifyResultFull(jws, opts = {}) {
185
180
  ...extra,
186
181
  });
187
182
  };
188
- // 1. Resolve the VC signer key: explicit override, else JWKS via header iss.
183
+ // 1. Resolve the VC signer key. Never use the signed header's `iss` as a
184
+ // network destination until it has matched an explicit or registered issuer.
189
185
  let signerPublicKey = opts.signerPublicKey;
190
186
  let header = {};
191
187
  const sig0 = jws.signatures[0];
@@ -198,12 +194,37 @@ export async function verifyResultFull(jws, opts = {}) {
198
194
  }
199
195
  }
200
196
  if (!signerPublicKey) {
197
+ const verificationClientId = getVerificationClientId(payload) ?? '';
198
+ let configuredIssuers;
199
+ try {
200
+ configuredIssuers = await resolveTrustedIssuers(opts, verificationClientId);
201
+ }
202
+ catch {
203
+ return fail('issuer-resolution-failed');
204
+ }
205
+ if (!configuredIssuers.length) {
206
+ return fail('issuer-not-configured');
207
+ }
201
208
  const iss = String(header.iss ?? '');
202
209
  if (!iss) {
203
210
  return fail('no-issuer');
204
211
  }
205
- const keys = await fetchJwks(iss, opts.fetchImpl);
206
- const jwk = selectKey(keys, String(header.kid ?? ''));
212
+ const trustedIssuer = configuredIssuers.find((candidate) => (normalizeIssuer(candidate) === normalizeIssuer(iss)));
213
+ if (!trustedIssuer) {
214
+ return fail('issuer-not-trusted');
215
+ }
216
+ let keys;
217
+ try {
218
+ const jwksUrl = await resolveTrustedJwksUrl(opts, verificationClientId);
219
+ const registry = await fetchReclaimJwks(jwksUrl
220
+ ?? `${trustedIssuer.replace(/\/+$/, '')}/.well-known/jwks.json`, opts.fetchImpl);
221
+ keys = registry.keys;
222
+ jwksAttestorAddresses = registry['x-reclaim-attestors'] ?? [];
223
+ }
224
+ catch {
225
+ return fail('jwks-fetch-failed');
226
+ }
227
+ const jwk = selectVerificationResultKey(keys, String(header.kid ?? ''), verificationClientId);
207
228
  if (!jwk) {
208
229
  return fail('signer-key-not-found');
209
230
  }
@@ -212,78 +233,248 @@ export async function verifyResultFull(jws, opts = {}) {
212
233
  if (!verifyJwsSignature(jws, signerPublicKey)) {
213
234
  return fail('bad-signature');
214
235
  }
215
- // 2. Freshness / audience / expiry.
216
- if (opts.expectedReclaimSessionId &&
217
- reclaimSessionId !== opts.expectedReclaimSessionId) {
236
+ if (typeof payload.iss === 'string'
237
+ && typeof header.iss === 'string'
238
+ && normalizeIssuer(payload.iss) !== normalizeIssuer(header.iss)) {
239
+ return fail('issuer-mismatch');
240
+ }
241
+ // 2. Session binding, audience, and optional legacy result expiry.
242
+ const expectedResultSessionId = opts.sessionId
243
+ ?? opts.expectedReclaimSessionId;
244
+ if (expectedResultSessionId && reclaimSessionId !== expectedResultSessionId) {
218
245
  return fail('reclaimSessionId-mismatch');
219
246
  }
220
247
  if (opts.expectedAud && payload.aud !== opts.expectedAud) {
221
248
  return fail('aud-mismatch');
222
249
  }
223
250
  const now = opts.now ?? Math.floor(Date.now() / 1000);
224
- if (typeof payload.exp === 'number' && payload.exp < now) {
251
+ if (!opts.ignoreExpiration
252
+ && typeof payload.exp === 'number'
253
+ && payload.exp < now) {
225
254
  return fail('expired');
226
255
  }
227
- // 3. Per-provider, per-request nested attestor proof + content_hash binding.
228
- // `results` is grouped by provider: [{ provider_id, resolved_version,
229
- // requests: [...] }]. Every request across every provider must verify.
256
+ // 3. Verify every exact legacy proof carried by the signed result. The outer
257
+ // envelope groups proofs by provider, but it never changes the proof shape.
230
258
  const providerResults = Array.isArray(payload.results)
231
259
  ? payload.results
232
260
  : [];
233
261
  const proofs = [];
262
+ const proofGroups = [];
234
263
  for (const prov of providerResults) {
235
264
  const providerId = typeof prov.provider_id === 'string' ? prov.provider_id : undefined;
265
+ const providerVersion = typeof prov.resolved_version === 'string'
266
+ ? prov.resolved_version
267
+ : undefined;
236
268
  const requests = Array.isArray(prov.requests)
237
269
  ? prov.requests
238
270
  : [];
239
271
  for (const r of requests) {
240
272
  const requestId = typeof r.request_id === 'string' ? r.request_id : undefined;
241
- if (typeof r.proof !== 'string') {
273
+ if (!isLegacyProof(r.proof)) {
242
274
  proofs.push({
243
275
  providerId, requestId, proofValid: false, reason: 'proof-missing',
244
276
  });
245
277
  continue;
246
278
  }
247
- const np = verifyNestedProof(r.proof, {
248
- attestorAddresses: opts.attestorAddresses,
249
- });
250
- if (!np.valid) {
251
- proofs.push({
252
- providerId,
253
- requestId,
254
- proofValid: false,
255
- reason: np.reason,
256
- attestorAddress: np.attestorAddress,
257
- });
258
- continue;
259
- }
260
- if (typeof r.content_hash === 'string' &&
261
- r.extracted_parameters &&
262
- typeof r.extracted_parameters === 'object') {
263
- const params = r.extracted_parameters;
264
- if (contentHash(params).toLowerCase() !== r.content_hash.toLowerCase()) {
265
- proofs.push({
266
- providerId,
267
- requestId,
268
- proofValid: false,
269
- reason: 'content-hash-mismatch',
270
- attestorAddress: np.attestorAddress,
271
- });
272
- continue;
273
- }
274
- }
275
279
  proofs.push({
276
280
  providerId,
277
281
  requestId,
278
282
  proofValid: true,
279
- attestorAddress: np.attestorAddress,
283
+ attestorAddress: r.proof.witnesses[0]?.id,
284
+ });
285
+ proofGroups.push({
286
+ providerId,
287
+ providerVersion,
288
+ proof: r.proof,
289
+ outcomeIndex: proofs.length - 1,
280
290
  });
281
291
  }
282
292
  }
293
+ const verificationStatus = getVerificationStatus(payload);
294
+ if (verificationStatus === 'success' && !proofGroups.length) {
295
+ return fail('proof-missing', { proofs });
296
+ }
297
+ if (proofGroups.length) {
298
+ const expectedSessionId = expectedResultSessionId;
299
+ const configuredProofValidation = opts.proofValidation
300
+ ?? opts.proofVerification;
301
+ const attestorAddresses = [...new Set([
302
+ ...(configuredProofValidation?.attestorAddresses ?? []),
303
+ ...(opts.attestorAddresses ?? []),
304
+ ...jwksAttestorAddresses,
305
+ ])];
306
+ const commonValidation = {
307
+ ...configuredProofValidation,
308
+ ...(opts.hashes ? { hashes: opts.hashes } : {}),
309
+ ...(attestorAddresses.length
310
+ ? { attestorAddresses }
311
+ : {}),
312
+ ...(expectedSessionId
313
+ ? { expectedSessionId }
314
+ : {}),
315
+ };
316
+ if (hasContentValidation(commonValidation)) {
317
+ await verifyLegacyProofGroup(proofGroups, commonValidation);
318
+ }
319
+ else {
320
+ await verifyByResolvedRecipes(commonValidation, expectedSessionId);
321
+ }
322
+ }
283
323
  if (!proofs.every((p) => p.proofValid)) {
284
324
  return fail('invalid-proof', { proofs });
285
325
  }
286
326
  return { valid: true, payload, reclaimSessionId, proofs };
327
+ async function verifyLegacyProofGroup(group, validation) {
328
+ const legacyOutcome = await verifyProof(group.map(({ proof }) => proof), validation);
329
+ if (legacyOutcome.valid) {
330
+ for (const [index, item] of group.entries()) {
331
+ proofs[item.outcomeIndex].data = legacyOutcome.data?.[index];
332
+ proofs[item.outcomeIndex].publicData =
333
+ legacyOutcome.publicData?.[index];
334
+ }
335
+ return;
336
+ }
337
+ for (const { outcomeIndex } of group) {
338
+ proofs[outcomeIndex].proofValid = false;
339
+ proofs[outcomeIndex].reason = legacyOutcome.reason;
340
+ }
341
+ }
342
+ async function verifyByResolvedRecipes(common, expectedSessionId) {
343
+ let recipes = opts.proofRecipes;
344
+ if (!recipes && expectedSessionId && opts.resolveSession) {
345
+ try {
346
+ const resolved = await opts.resolveSession(expectedSessionId);
347
+ recipes = resolved.recipes;
348
+ }
349
+ catch {
350
+ return fail('session-resolution-failed', { proofs });
351
+ }
352
+ }
353
+ const groups = Map.groupBy(proofGroups, proofGroupKey);
354
+ if (recipes && !recipeGroupsMatch(recipes, groups)) {
355
+ markInvalid(proofGroups, 'recipe-mismatch');
356
+ return fail('invalid-proof', { proofs });
357
+ }
358
+ for (const group of groups.values()) {
359
+ await verifyResolvedGroup(group, recipes, common);
360
+ }
361
+ }
362
+ async function verifyResolvedGroup(group, recipes, common) {
363
+ const providerId = group[0]?.providerId;
364
+ const providerVersion = group[0]?.providerVersion;
365
+ const providerValidation = providerId
366
+ ? opts.proofValidationByProviderId?.[providerId]
367
+ : undefined;
368
+ const recipe = recipes?.find((candidate) => (candidate.providerId === providerId
369
+ && candidate.resolvedVersion === providerVersion));
370
+ let hashes;
371
+ if (recipe) {
372
+ try {
373
+ hashes = proofHashesFromBuilderRecipe(recipe, group.map(({ proof }) => proof));
374
+ }
375
+ catch {
376
+ markInvalid(group, 'recipe-hash-failed');
377
+ return;
378
+ }
379
+ }
380
+ await verifyLegacyProofGroup(group, {
381
+ ...common,
382
+ ...(recipe
383
+ ? { hashes }
384
+ : providerId
385
+ ? { providerId, providerVersion }
386
+ : {}),
387
+ ...providerValidation,
388
+ });
389
+ }
390
+ function markInvalid(group, reason) {
391
+ for (const { outcomeIndex } of group) {
392
+ proofs[outcomeIndex].proofValid = false;
393
+ proofs[outcomeIndex].reason = reason;
394
+ }
395
+ }
396
+ }
397
+ function hasContentValidation(config) {
398
+ return Boolean(config.hashes
399
+ || config.providerId
400
+ || config.dangerouslyDisableContentValidation);
401
+ }
402
+ function proofGroupKey(group) {
403
+ return `${group.providerId ?? ''}\u0000${group.providerVersion ?? ''}`;
404
+ }
405
+ function recipeGroupsMatch(recipes, groups) {
406
+ const expected = new Set(recipes.map((recipe) => (`${recipe.providerId}\u0000${recipe.resolvedVersion}`)));
407
+ return expected.size === groups.size
408
+ && [...groups.keys()].every((key) => expected.has(key));
409
+ }
410
+ function isLegacyProof(value) {
411
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
412
+ return false;
413
+ }
414
+ const proof = value;
415
+ return typeof proof.identifier === 'string'
416
+ && !!proof.claimData
417
+ && typeof proof.claimData === 'object'
418
+ && Array.isArray(proof.signatures)
419
+ && Array.isArray(proof.witnesses)
420
+ && 'extractedParameterValues' in proof;
421
+ }
422
+ function getVerificationStatus(payload) {
423
+ const session = payload.verification_session;
424
+ if (!session || typeof session !== 'object' || Array.isArray(session)) {
425
+ return undefined;
426
+ }
427
+ const status = session.status;
428
+ return typeof status === 'string' ? status : undefined;
429
+ }
430
+ function normalizeIssuer(issuer) {
431
+ return issuer.trim().replace(/\/+$/, '').toLowerCase();
432
+ }
433
+ function getVerificationClientId(payload) {
434
+ if (typeof payload.verificationClientId === 'string') {
435
+ return payload.verificationClientId;
436
+ }
437
+ if (typeof payload.verification_client_id === 'string') {
438
+ return payload.verification_client_id;
439
+ }
440
+ const session = payload.verification_session;
441
+ if (!session || typeof session !== 'object' || Array.isArray(session)) {
442
+ return undefined;
443
+ }
444
+ const sessionRecord = session;
445
+ const id = sessionRecord.verificationClientId
446
+ ?? sessionRecord.verification_client_id;
447
+ return typeof id === 'string' ? id : undefined;
448
+ }
449
+ async function resolveTrustedIssuers(opts, verificationClientId) {
450
+ const explicit = [
451
+ opts.issuer,
452
+ opts.trustedIssuer,
453
+ ...(opts.issuers ?? []),
454
+ ...(opts.trustedIssuers ?? []),
455
+ ].filter((issuer) => typeof issuer === 'string');
456
+ if (explicit.length) {
457
+ return [...new Set(explicit.map(normalizeIssuer))];
458
+ }
459
+ if (!verificationClientId) {
460
+ return [];
461
+ }
462
+ const registered = opts.issuersByVerificationClientId?.[verificationClientId] ?? [];
463
+ const resolve = opts.resolveIssuers ?? opts.issuerResolver;
464
+ const resolved = resolve
465
+ ? await resolve(verificationClientId)
466
+ : [];
467
+ return [...new Set([...registered, ...resolved].map(normalizeIssuer))];
468
+ }
469
+ async function resolveTrustedJwksUrl(opts, verificationClientId) {
470
+ if (opts.jwksUrl) {
471
+ return opts.jwksUrl;
472
+ }
473
+ if (!verificationClientId) {
474
+ return undefined;
475
+ }
476
+ const registered = opts.jwksUrlsByVerificationClientId?.[verificationClientId];
477
+ return registered ?? await opts.resolveJwksUrl?.(verificationClientId);
287
478
  }
288
479
  /** Decrypt-and-verify in one step. */
289
480
  export function verifyResult(jws, opts = {}) {
@@ -11,6 +11,10 @@ export declare const ROUTES: {
11
11
  readonly method: "post";
12
12
  readonly path: "/orgs/{orgId}/members";
13
13
  };
14
+ readonly AddProviderContributionComment: {
15
+ readonly method: "post";
16
+ readonly path: "/providers/{providerId}/contributions/{campaignId}/comments";
17
+ };
14
18
  readonly AddStaffMember: {
15
19
  readonly method: "post";
16
20
  readonly path: "/admin/staff";
@@ -83,6 +87,10 @@ export declare const ROUTES: {
83
87
  readonly method: "post";
84
88
  readonly path: "/admin/orgs/{orgId}/credits/{grantId}/void";
85
89
  };
90
+ readonly BindVerificationSessionTeeNonce: {
91
+ readonly method: "put";
92
+ readonly path: "/verifications/sessions/{sessionId}/tee-nonce";
93
+ };
86
94
  readonly CancelBillingSubscription: {
87
95
  readonly method: "delete";
88
96
  readonly path: "/orgs/{orgId}/billing/subscription";
@@ -143,10 +151,22 @@ export declare const ROUTES: {
143
151
  readonly method: "post";
144
152
  readonly path: "/providers";
145
153
  };
154
+ readonly CreateProviderContributionCampaign: {
155
+ readonly method: "post";
156
+ readonly path: "/providers/{providerId}/contributions";
157
+ };
158
+ readonly CreateProviderContributionRequirementRevision: {
159
+ readonly method: "post";
160
+ readonly path: "/providers/{providerId}/contributions/{campaignId}/requirements";
161
+ };
146
162
  readonly CreateProviderVersion: {
147
163
  readonly method: "post";
148
164
  readonly path: "/providers/{providerId}/versions";
149
165
  };
166
+ readonly CreatePublicContributionAttempt: {
167
+ readonly method: "post";
168
+ readonly path: "/contribute/{publicId}";
169
+ };
150
170
  readonly CreateTheme: {
151
171
  readonly method: "post";
152
172
  readonly path: "/orgs/{orgId}/themes";
@@ -279,6 +299,10 @@ export declare const ROUTES: {
279
299
  readonly method: "get";
280
300
  readonly path: "/providers/{providerId}/versions/{version}";
281
301
  };
302
+ readonly GetPublicContributionCampaign: {
303
+ readonly method: "get";
304
+ readonly path: "/contribute/{publicId}";
305
+ };
282
306
  readonly GetTheme: {
283
307
  readonly method: "get";
284
308
  readonly path: "/orgs/{orgId}/themes/{themeId}";
@@ -287,6 +311,10 @@ export declare const ROUTES: {
287
311
  readonly method: "get";
288
312
  readonly path: "/users/{userId}";
289
313
  };
314
+ readonly GetVerificationFunnel: {
315
+ readonly method: "get";
316
+ readonly path: "/orgs/{orgId}/verification-funnel";
317
+ };
290
318
  readonly GetVerificationRecipe: {
291
319
  readonly method: "get";
292
320
  readonly path: "/verifications/sessions/{sessionId}/recipe";
@@ -299,6 +327,10 @@ export declare const ROUTES: {
299
327
  readonly method: "get";
300
328
  readonly path: "/verifications/sessions/{sessionId}";
301
329
  };
330
+ readonly ImportDevtoolsProvider: {
331
+ readonly method: "post";
332
+ readonly path: "/providers/import/devtools";
333
+ };
302
334
  readonly Index: {
303
335
  readonly method: "get";
304
336
  readonly path: "/";
@@ -347,6 +379,10 @@ export declare const ROUTES: {
347
379
  readonly method: "get";
348
380
  readonly path: "/orgs/{orgId}/sessions";
349
381
  };
382
+ readonly ListProviderContributionCampaigns: {
383
+ readonly method: "get";
384
+ readonly path: "/providers/{providerId}/contributions";
385
+ };
350
386
  readonly ListProviderVersions: {
351
387
  readonly method: "get";
352
388
  readonly path: "/providers/{providerId}/versions";
@@ -391,6 +427,10 @@ export declare const ROUTES: {
391
427
  readonly method: "get";
392
428
  readonly path: "/orgs/{orgId}/invite";
393
429
  };
430
+ readonly PatchVerificationClaimant: {
431
+ readonly method: "patch";
432
+ readonly path: "/verifications/sessions/{sessionId}/claimant";
433
+ };
394
434
  readonly ProviderPreviewImage: {
395
435
  readonly method: "get";
396
436
  readonly path: "/providers/{providerId}/preview.png";
@@ -467,18 +507,22 @@ export declare const ROUTES: {
467
507
  readonly method: "post";
468
508
  readonly path: "/admin/billing/plans/{planId}/default";
469
509
  };
470
- readonly SetOrgCreditGrace: {
471
- readonly method: "post";
472
- readonly path: "/admin/orgs/{orgId}/credits/grace";
473
- };
474
- readonly SetOrgGrace: {
510
+ readonly SetOrgCreditAllowance: {
475
511
  readonly method: "post";
476
- readonly path: "/admin/orgs/{orgId}/billing/grace";
512
+ readonly path: "/admin/orgs/{orgId}/credits/allowance";
477
513
  };
478
514
  readonly SetOrgKeypair: {
479
515
  readonly method: "put";
480
516
  readonly path: "/orgs/{orgId}/keypair";
481
517
  };
518
+ readonly SetOrgPaymentAllowance: {
519
+ readonly method: "post";
520
+ readonly path: "/admin/orgs/{orgId}/billing/allowance";
521
+ };
522
+ readonly SetProviderContributionCampaignStatus: {
523
+ readonly method: "post";
524
+ readonly path: "/providers/{providerId}/contributions/{campaignId}";
525
+ };
482
526
  readonly SetupBillingPlan: {
483
527
  readonly method: "post";
484
528
  readonly path: "/admin/billing/plans/setup";
@@ -539,6 +583,10 @@ export declare const ROUTES: {
539
583
  readonly method: "post";
540
584
  readonly path: "/providers/{providerId}/versions/{version}/review";
541
585
  };
586
+ readonly SubmitPublicContributionFeedback: {
587
+ readonly method: "post";
588
+ readonly path: "/contribute/{publicId}/feedback";
589
+ };
542
590
  readonly SubmitVerificationResult: {
543
591
  readonly method: "post";
544
592
  readonly path: "/verifications/sessions/{sessionId}/result";
@@ -567,6 +615,10 @@ export declare const ROUTES: {
567
615
  readonly method: "patch";
568
616
  readonly path: "/providers/{providerId}";
569
617
  };
618
+ readonly UpdateProviderContributionCampaign: {
619
+ readonly method: "patch";
620
+ readonly path: "/providers/{providerId}/contributions/{campaignId}";
621
+ };
570
622
  readonly UpdateProviderVersion: {
571
623
  readonly method: "patch";
572
624
  readonly path: "/providers/{providerId}/versions/{version}";
package/lib/routes.gen.js CHANGED
@@ -1,11 +1,12 @@
1
1
  // AUTO-GENERATED by packages/app/scripts/mcp-tools-gen.ts
2
2
  // from packages/app/openapi.yaml.
3
- // Run `npm run openapi:typegen --workspace=packages/client`
3
+ // Run `npm run openapi:gen --workspace=packages/app`
4
4
  // to regenerate. Do not edit by hand.
5
5
  export const ROUTES = {
6
6
  "AcceptOrgInvite": { "method": "post", "path": "/orgs/{orgId}/invite" },
7
7
  "ActivateFixWithAiRepair": { "method": "post", "path": "/v/{sessionId}/fix-with-ai/activate" },
8
8
  "AddOrgMember": { "method": "post", "path": "/orgs/{orgId}/members" },
9
+ "AddProviderContributionComment": { "method": "post", "path": "/providers/{providerId}/contributions/{campaignId}/comments" },
9
10
  "AddStaffMember": { "method": "post", "path": "/admin/staff" },
10
11
  "AddVerificationClientKey": { "method": "post", "path": "/admin/verification-clients/{clientId}/keys" },
11
12
  "AdminBillingPlans": { "method": "get", "path": "/admin/billing/plans" },
@@ -24,6 +25,7 @@ export const ROUTES = {
24
25
  "AdminUsers": { "method": "get", "path": "/admin/users" },
25
26
  "AdminVerificationClients": { "method": "get", "path": "/admin/verification-clients" },
26
27
  "AdminVoidOrgCredit": { "method": "post", "path": "/admin/orgs/{orgId}/credits/{grantId}/void" },
28
+ "BindVerificationSessionTeeNonce": { "method": "put", "path": "/verifications/sessions/{sessionId}/tee-nonce" },
27
29
  "CancelBillingSubscription": { "method": "delete", "path": "/orgs/{orgId}/billing/subscription" },
28
30
  "CancelPublicListingRequest": { "method": "post", "path": "/providers/{providerId}/versions/{version}/cancel-review" },
29
31
  "ChangeOrgPlan": { "method": "post", "path": "/orgs/{orgId}/billing/change-plan" },
@@ -39,7 +41,10 @@ export const ROUTES = {
39
41
  "CreateOrg": { "method": "post", "path": "/orgs" },
40
42
  "CreateOrgCallbackSubscription": { "method": "post", "path": "/orgs/{orgId}/callback-subscriptions" },
41
43
  "CreateProvider": { "method": "post", "path": "/providers" },
44
+ "CreateProviderContributionCampaign": { "method": "post", "path": "/providers/{providerId}/contributions" },
45
+ "CreateProviderContributionRequirementRevision": { "method": "post", "path": "/providers/{providerId}/contributions/{campaignId}/requirements" },
42
46
  "CreateProviderVersion": { "method": "post", "path": "/providers/{providerId}/versions" },
47
+ "CreatePublicContributionAttempt": { "method": "post", "path": "/contribute/{publicId}" },
43
48
  "CreateTheme": { "method": "post", "path": "/orgs/{orgId}/themes" },
44
49
  "CreateVerificationClient": { "method": "post", "path": "/admin/verification-clients" },
45
50
  "CreateVerificationSession": { "method": "post", "path": "/verifications/sessions" },
@@ -73,11 +78,14 @@ export const ROUTES = {
73
78
  "GetProvider": { "method": "get", "path": "/providers/{providerId}" },
74
79
  "GetProviderBySlug": { "method": "get", "path": "/providers/{providerId}/{slug}" },
75
80
  "GetProviderVersion": { "method": "get", "path": "/providers/{providerId}/versions/{version}" },
81
+ "GetPublicContributionCampaign": { "method": "get", "path": "/contribute/{publicId}" },
76
82
  "GetTheme": { "method": "get", "path": "/orgs/{orgId}/themes/{themeId}" },
77
83
  "GetUser": { "method": "get", "path": "/users/{userId}" },
84
+ "GetVerificationFunnel": { "method": "get", "path": "/orgs/{orgId}/verification-funnel" },
78
85
  "GetVerificationRecipe": { "method": "get", "path": "/verifications/sessions/{sessionId}/recipe" },
79
86
  "GetVerificationResult": { "method": "get", "path": "/verifications/sessions/{sessionId}/result" },
80
87
  "GetVerificationSession": { "method": "get", "path": "/verifications/sessions/{sessionId}" },
88
+ "ImportDevtoolsProvider": { "method": "post", "path": "/providers/import/devtools" },
81
89
  "Index": { "method": "get", "path": "/" },
82
90
  "IssueOrgToken": { "method": "post", "path": "/orgs/{orgId}/token" },
83
91
  "IssueVerificationClientToken": { "method": "post", "path": "/admin/verification-clients/{clientId}/tokens" },
@@ -90,6 +98,7 @@ export const ROUTES = {
90
98
  "ListOrgTokens": { "method": "get", "path": "/orgs/{orgId}/token" },
91
99
  "ListOrgTransactions": { "method": "get", "path": "/orgs/{orgId}/billing/transactions" },
92
100
  "ListOrgVerificationSessions": { "method": "get", "path": "/orgs/{orgId}/sessions" },
101
+ "ListProviderContributionCampaigns": { "method": "get", "path": "/providers/{providerId}/contributions" },
93
102
  "ListProviderVersions": { "method": "get", "path": "/providers/{providerId}/versions" },
94
103
  "ListSessionCallbackKeys": { "method": "get", "path": "/verifications/sessions/{sessionId}/callback-keys" },
95
104
  "ListStaffMembers": { "method": "get", "path": "/admin/staff" },
@@ -101,6 +110,7 @@ export const ROUTES = {
101
110
  "MakePrivate": { "method": "post", "path": "/providers/{providerId}/make-private" },
102
111
  "OpenApiSpec": { "method": "get", "path": "/openapi.yaml" },
103
112
  "OrgInvitePage": { "method": "get", "path": "/orgs/{orgId}/invite" },
113
+ "PatchVerificationClaimant": { "method": "patch", "path": "/verifications/sessions/{sessionId}/claimant" },
104
114
  "ProviderPreviewImage": { "method": "get", "path": "/providers/{providerId}/preview.png" },
105
115
  "Providers": { "method": "get", "path": "/providers" },
106
116
  "PublishProviderVersion": { "method": "post", "path": "/providers/{providerId}/versions/{version}/publish" },
@@ -120,9 +130,10 @@ export const ROUTES = {
120
130
  "Robots": { "method": "get", "path": "/robots.txt" },
121
131
  "SearchOrgMembers": { "method": "get", "path": "/orgs/{orgId}/members" },
122
132
  "SetDefaultBillingPlan": { "method": "post", "path": "/admin/billing/plans/{planId}/default" },
123
- "SetOrgCreditGrace": { "method": "post", "path": "/admin/orgs/{orgId}/credits/grace" },
124
- "SetOrgGrace": { "method": "post", "path": "/admin/orgs/{orgId}/billing/grace" },
133
+ "SetOrgCreditAllowance": { "method": "post", "path": "/admin/orgs/{orgId}/credits/allowance" },
125
134
  "SetOrgKeypair": { "method": "put", "path": "/orgs/{orgId}/keypair" },
135
+ "SetOrgPaymentAllowance": { "method": "post", "path": "/admin/orgs/{orgId}/billing/allowance" },
136
+ "SetProviderContributionCampaignStatus": { "method": "post", "path": "/providers/{providerId}/contributions/{campaignId}" },
126
137
  "SetupBillingPlan": { "method": "post", "path": "/admin/billing/plans/setup" },
127
138
  "SetupProviderCreate": { "method": "post", "path": "/providers/setup" },
128
139
  "SiteAiProvider": { "method": "post", "path": "/site/{domain}/ai-provider" },
@@ -138,6 +149,7 @@ export const ROUTES = {
138
149
  "StripeWebhook": { "method": "post", "path": "/billing/stripe/webhook" },
139
150
  "SubmitConsent": { "method": "post", "path": "/oauth/consent" },
140
151
  "SubmitProviderVersionForReview": { "method": "post", "path": "/providers/{providerId}/versions/{version}/review" },
152
+ "SubmitPublicContributionFeedback": { "method": "post", "path": "/contribute/{publicId}/feedback" },
141
153
  "SubmitVerificationResult": { "method": "post", "path": "/verifications/sessions/{sessionId}/result" },
142
154
  "TransferProvider": { "method": "post", "path": "/providers/{providerId}/transfer" },
143
155
  "UpdateBillingPlan": { "method": "put", "path": "/admin/billing/plans/{planId}" },
@@ -145,6 +157,7 @@ export const ROUTES = {
145
157
  "UpdateOrgIcon": { "method": "put", "path": "/orgs/{orgId}/icon" },
146
158
  "UpdateOrgMember": { "method": "patch", "path": "/orgs/{orgId}/members/{memberId}" },
147
159
  "UpdateProvider": { "method": "patch", "path": "/providers/{providerId}" },
160
+ "UpdateProviderContributionCampaign": { "method": "patch", "path": "/providers/{providerId}/contributions/{campaignId}" },
148
161
  "UpdateProviderVersion": { "method": "patch", "path": "/providers/{providerId}/versions/{version}" },
149
162
  "UpdateTheme": { "method": "patch", "path": "/orgs/{orgId}/themes/{themeId}" },
150
163
  "UpdateVerificationClient": { "method": "put", "path": "/admin/verification-clients/{clientId}" },