@adcp/sdk 16.1.0 → 16.2.0

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 (43) hide show
  1. package/dist/lib/governance/authorization.d.mts +66 -0
  2. package/dist/lib/governance/authorization.d.ts +66 -0
  3. package/dist/lib/governance/authorization.js +181 -37
  4. package/dist/lib/governance/authorization.mjs +183 -36
  5. package/dist/lib/governance/index.d.mts +2 -2
  6. package/dist/lib/governance/index.d.ts +2 -2
  7. package/dist/lib/governance/index.js +4 -2
  8. package/dist/lib/governance/index.mjs +3 -1
  9. package/dist/lib/identity-3.3/index.d.mts +1 -0
  10. package/dist/lib/identity-3.3/index.d.ts +1 -0
  11. package/dist/lib/identity-3.3/index.js +3 -1
  12. package/dist/lib/identity-3.3/index.mjs +1 -0
  13. package/dist/lib/identity-3.3/jws-artifacts.d.mts +147 -0
  14. package/dist/lib/identity-3.3/jws-artifacts.d.ts +147 -0
  15. package/dist/lib/identity-3.3/jws-artifacts.js +258 -0
  16. package/dist/lib/identity-3.3/jws-artifacts.mjs +234 -0
  17. package/dist/lib/identity-3.3/revocation.d.mts +7 -0
  18. package/dist/lib/identity-3.3/revocation.d.ts +7 -0
  19. package/dist/lib/identity-3.3/revocation.js +13 -0
  20. package/dist/lib/identity-3.3/revocation.mjs +13 -0
  21. package/dist/lib/index.d.mts +2 -2
  22. package/dist/lib/index.d.ts +2 -2
  23. package/dist/lib/index.js +2 -0
  24. package/dist/lib/index.mjs +2 -0
  25. package/dist/lib/registry/types.generated.d.mts +24 -1
  26. package/dist/lib/registry/types.generated.d.ts +24 -1
  27. package/dist/lib/server/index.d.mts +2 -2
  28. package/dist/lib/server/index.d.ts +2 -2
  29. package/dist/lib/server/index.js +2 -0
  30. package/dist/lib/server/index.mjs +2 -0
  31. package/dist/lib/signing/web-bot-auth.js +5 -0
  32. package/dist/lib/signing/web-bot-auth.mjs +4 -0
  33. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  34. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  35. package/dist/lib/version.d.mts +3 -3
  36. package/dist/lib/version.d.ts +3 -3
  37. package/dist/lib/version.js +3 -3
  38. package/dist/lib/version.mjs +3 -3
  39. package/docs/TYPE-SUMMARY.md +2 -2
  40. package/docs/llms.txt +3 -3
  41. package/docs/migration-14.x-rc-worksheet.md +4 -4
  42. package/docs/migration-agent-identity-3.3.md +51 -6
  43. package/package.json +6 -4
@@ -12,7 +12,9 @@ import type { CheckGovernanceRequest, GovernancePhase, PlannedDelivery } from '.
12
12
  import type { JwksResolver } from '../signing/jwks.mjs';
13
13
  import type { ReplayStore } from '../signing/replay.mjs';
14
14
  import type { RevocationStore } from '../signing/revocation.mjs';
15
+ import type { RevocationDetail } from '../identity-3.3/types.mjs';
15
16
  import { type HttpsJwksResolverOptions } from '../signing/jwks-https.mjs';
17
+ import { type GovernanceKeyArchiveResolver, type JwsArtifactWebBotAuthOptions } from '../identity-3.3/jws-artifacts.mjs';
16
18
  export declare const GOVERNANCE_AUTHORIZATION_CRITICAL_CLAIMS: readonly ["authorized_commitment", "authorized_task", "authorized_payload_hash"];
17
19
  export type GovernanceAuthorizationCriticalClaim = (typeof GOVERNANCE_AUTHORIZATION_CRITICAL_CLAIMS)[number];
18
20
  export type GovernanceEnforcementMode = 'signed_context' | 'online_execution_check';
@@ -51,6 +53,12 @@ export interface GovernanceAuthorizationFailure {
51
53
  ok: false;
52
54
  error: GovernanceAuthorizationErrorCode;
53
55
  message: string;
56
+ /**
57
+ * Set when the failure is an outage (an issuer trust record, key directory,
58
+ * archive or revocation list could not be read), not a verdict on the
59
+ * token: the same token may verify on retry.
60
+ */
61
+ retryable?: true;
54
62
  }
55
63
  export type GovernanceAuthorizationResult = GovernanceAuthorizationSuccess | GovernanceAuthorizationFailure;
56
64
  export interface GovernanceReplayStore {
@@ -127,6 +135,18 @@ export interface VerifyGovernanceAuthorizationOptions {
127
135
  jwks?: JwksResolver;
128
136
  /** When supplied, discover keys from this exact authenticated buyer record. */
129
137
  buyerIdentity?: GovernanceBuyerIdentity;
138
+ /**
139
+ * AdCP 3.3 (`specs/agent-identity-3-3.md` R4): when the trust record derived
140
+ * from the issuer's origin lists that origin, verify the token with a key
141
+ * from the origin's Web Bot Auth key directory (`alg` `EdDSA`, `kid` the
142
+ * key's JWK thumbprint, no `use`/`key_ops`/`adcp_use` checks) and check
143
+ * revocation against the origin's list, never under the 3.2 profile. A
144
+ * trust-record fetch failure rejects the token; it never falls back to 3.2.
145
+ * An issuer no trust record lists stays on the 3.2 profile (`jwks` or
146
+ * `buyerIdentity`). Every other check is unchanged, including the
147
+ * `buyerIdentity` cross-check that the issuer is the buyer's governance agent.
148
+ */
149
+ webBotAuth?: JwsArtifactWebBotAuthOptions;
130
150
  replayStore: GovernanceReplayStore;
131
151
  /** Optional governance-key revocation source. */
132
152
  revocationStore?: RevocationStore;
@@ -187,6 +207,52 @@ export declare function targetDeclaresGovernanceEnforcement(capabilities: unknow
187
207
  export declare function targetDeclaresLegacyGovernanceAwareness(capabilities: unknown, task: string): boolean;
188
208
  /** Verify the published compact-JWS authorization profile and all service bindings. */
189
209
  export declare function verifyGovernanceAuthorization(options: VerifyGovernanceAuthorizationOptions): Promise<GovernanceAuthorizationResult>;
210
+ export interface VerifyHistoricalGovernanceContextOptions {
211
+ token: unknown;
212
+ /** The governance agent the verifier expected to sign, from its own records. */
213
+ expectedIssuer: string;
214
+ /**
215
+ * The WBA components plus the governance key archive at the issuer's
216
+ * origin (`{origin}/.well-known/jwks-archive.json`, `security.mdx`
217
+ * §Revocation), which holds keys rotated out of the directory.
218
+ */
219
+ webBotAuth: JwsArtifactWebBotAuthOptions & {
220
+ archive: GovernanceKeyArchiveResolver;
221
+ };
222
+ }
223
+ export type HistoricalGovernanceContextResult = {
224
+ ok: true;
225
+ claims: GovernanceAuthorizationClaims;
226
+ protectedHeader: Record<string, unknown>;
227
+ /** The key was in the issuer's current directory, or only in its archive. */
228
+ keySource: 'directory' | 'archive';
229
+ /**
230
+ * The issuer origin's revocation status for the signing key: `current`
231
+ * (listed, not revoked), `absent` (the origin serves no list) or
232
+ * `revoked`. Online verification rejects every token a revoked key
233
+ * signed; an audit decides what a revocation means for a retained token
234
+ * from its detail (R9: only `keyCompromise` exposes, from its
235
+ * `invalidity_date`).
236
+ */
237
+ revocation: 'current' | 'absent' | 'revoked';
238
+ revocationDetail?: RevocationDetail;
239
+ } | (GovernanceAuthorizationFailure & {
240
+ /** Set when the issuer is on the 3.2 profile, which this function does not verify. */
241
+ profile?: '3.2';
242
+ });
243
+ /**
244
+ * Historical (audit) verification of a retained governance context from a
245
+ * Web Bot Auth identity (R4): the key comes from the issuer origin's key
246
+ * directory or, once rotated out, from its governance key archive. Checks the
247
+ * token's shape, `typ`, `crit`, issuer, `alg` `EdDSA`, `kid` thumbprint and
248
+ * signature, and reports the origin's revocation status and detail for the
249
+ * key instead of rejecting a revoked one. It does not check expiry, audience,
250
+ * replay or the request binding, which only an online verification can.
251
+ *
252
+ * Profile selection is the same as online: an issuer whose origin no trust
253
+ * record lists is on the 3.2 profile, reported as `profile: '3.2'`.
254
+ */
255
+ export declare function verifyHistoricalGovernanceContext(options: VerifyHistoricalGovernanceContextOptions): Promise<HistoricalGovernanceContextResult>;
190
256
  export declare class GovernanceAuthorizationError extends Error {
191
257
  readonly code: GovernanceAuthorizationErrorCode;
192
258
  constructor(result: GovernanceAuthorizationFailure);
@@ -12,7 +12,9 @@ import type { CheckGovernanceRequest, GovernancePhase, PlannedDelivery } from '.
12
12
  import type { JwksResolver } from '../signing/jwks';
13
13
  import type { ReplayStore } from '../signing/replay';
14
14
  import type { RevocationStore } from '../signing/revocation';
15
+ import type { RevocationDetail } from '../identity-3.3/types';
15
16
  import { type HttpsJwksResolverOptions } from '../signing/jwks-https';
17
+ import { type GovernanceKeyArchiveResolver, type JwsArtifactWebBotAuthOptions } from '../identity-3.3/jws-artifacts';
16
18
  export declare const GOVERNANCE_AUTHORIZATION_CRITICAL_CLAIMS: readonly ["authorized_commitment", "authorized_task", "authorized_payload_hash"];
17
19
  export type GovernanceAuthorizationCriticalClaim = (typeof GOVERNANCE_AUTHORIZATION_CRITICAL_CLAIMS)[number];
18
20
  export type GovernanceEnforcementMode = 'signed_context' | 'online_execution_check';
@@ -51,6 +53,12 @@ export interface GovernanceAuthorizationFailure {
51
53
  ok: false;
52
54
  error: GovernanceAuthorizationErrorCode;
53
55
  message: string;
56
+ /**
57
+ * Set when the failure is an outage (an issuer trust record, key directory,
58
+ * archive or revocation list could not be read), not a verdict on the
59
+ * token: the same token may verify on retry.
60
+ */
61
+ retryable?: true;
54
62
  }
55
63
  export type GovernanceAuthorizationResult = GovernanceAuthorizationSuccess | GovernanceAuthorizationFailure;
56
64
  export interface GovernanceReplayStore {
@@ -127,6 +135,18 @@ export interface VerifyGovernanceAuthorizationOptions {
127
135
  jwks?: JwksResolver;
128
136
  /** When supplied, discover keys from this exact authenticated buyer record. */
129
137
  buyerIdentity?: GovernanceBuyerIdentity;
138
+ /**
139
+ * AdCP 3.3 (`specs/agent-identity-3-3.md` R4): when the trust record derived
140
+ * from the issuer's origin lists that origin, verify the token with a key
141
+ * from the origin's Web Bot Auth key directory (`alg` `EdDSA`, `kid` the
142
+ * key's JWK thumbprint, no `use`/`key_ops`/`adcp_use` checks) and check
143
+ * revocation against the origin's list, never under the 3.2 profile. A
144
+ * trust-record fetch failure rejects the token; it never falls back to 3.2.
145
+ * An issuer no trust record lists stays on the 3.2 profile (`jwks` or
146
+ * `buyerIdentity`). Every other check is unchanged, including the
147
+ * `buyerIdentity` cross-check that the issuer is the buyer's governance agent.
148
+ */
149
+ webBotAuth?: JwsArtifactWebBotAuthOptions;
130
150
  replayStore: GovernanceReplayStore;
131
151
  /** Optional governance-key revocation source. */
132
152
  revocationStore?: RevocationStore;
@@ -187,6 +207,52 @@ export declare function targetDeclaresGovernanceEnforcement(capabilities: unknow
187
207
  export declare function targetDeclaresLegacyGovernanceAwareness(capabilities: unknown, task: string): boolean;
188
208
  /** Verify the published compact-JWS authorization profile and all service bindings. */
189
209
  export declare function verifyGovernanceAuthorization(options: VerifyGovernanceAuthorizationOptions): Promise<GovernanceAuthorizationResult>;
210
+ export interface VerifyHistoricalGovernanceContextOptions {
211
+ token: unknown;
212
+ /** The governance agent the verifier expected to sign, from its own records. */
213
+ expectedIssuer: string;
214
+ /**
215
+ * The WBA components plus the governance key archive at the issuer's
216
+ * origin (`{origin}/.well-known/jwks-archive.json`, `security.mdx`
217
+ * §Revocation), which holds keys rotated out of the directory.
218
+ */
219
+ webBotAuth: JwsArtifactWebBotAuthOptions & {
220
+ archive: GovernanceKeyArchiveResolver;
221
+ };
222
+ }
223
+ export type HistoricalGovernanceContextResult = {
224
+ ok: true;
225
+ claims: GovernanceAuthorizationClaims;
226
+ protectedHeader: Record<string, unknown>;
227
+ /** The key was in the issuer's current directory, or only in its archive. */
228
+ keySource: 'directory' | 'archive';
229
+ /**
230
+ * The issuer origin's revocation status for the signing key: `current`
231
+ * (listed, not revoked), `absent` (the origin serves no list) or
232
+ * `revoked`. Online verification rejects every token a revoked key
233
+ * signed; an audit decides what a revocation means for a retained token
234
+ * from its detail (R9: only `keyCompromise` exposes, from its
235
+ * `invalidity_date`).
236
+ */
237
+ revocation: 'current' | 'absent' | 'revoked';
238
+ revocationDetail?: RevocationDetail;
239
+ } | (GovernanceAuthorizationFailure & {
240
+ /** Set when the issuer is on the 3.2 profile, which this function does not verify. */
241
+ profile?: '3.2';
242
+ });
243
+ /**
244
+ * Historical (audit) verification of a retained governance context from a
245
+ * Web Bot Auth identity (R4): the key comes from the issuer origin's key
246
+ * directory or, once rotated out, from its governance key archive. Checks the
247
+ * token's shape, `typ`, `crit`, issuer, `alg` `EdDSA`, `kid` thumbprint and
248
+ * signature, and reports the origin's revocation status and detail for the
249
+ * key instead of rejecting a revoked one. It does not check expiry, audience,
250
+ * replay or the request binding, which only an online verification can.
251
+ *
252
+ * Profile selection is the same as online: an issuer whose origin no trust
253
+ * record lists is on the 3.2 profile, reported as `profile: '3.2'`.
254
+ */
255
+ export declare function verifyHistoricalGovernanceContext(options: VerifyHistoricalGovernanceContextOptions): Promise<HistoricalGovernanceContextResult>;
190
256
  export declare class GovernanceAuthorizationError extends Error {
191
257
  readonly code: GovernanceAuthorizationErrorCode;
192
258
  constructor(result: GovernanceAuthorizationFailure);
@@ -35,7 +35,8 @@ __export(authorization_exports, {
35
35
  governanceTaskRequiresProposedCommitment: () => governanceTaskRequiresProposedCommitment,
36
36
  targetDeclaresGovernanceEnforcement: () => targetDeclaresGovernanceEnforcement,
37
37
  targetDeclaresLegacyGovernanceAwareness: () => targetDeclaresLegacyGovernanceAwareness,
38
- verifyGovernanceAuthorization: () => verifyGovernanceAuthorization
38
+ verifyGovernanceAuthorization: () => verifyGovernanceAuthorization,
39
+ verifyHistoricalGovernanceContext: () => verifyHistoricalGovernanceContext
39
40
  });
40
41
  module.exports = __toCommonJS(authorization_exports);
41
42
  var import_node_crypto = require("node:crypto");
@@ -44,11 +45,18 @@ var import_jcs = require('../utils/jcs.js');
44
45
  var import_jwks_https = require('../signing/jwks-https.js');
45
46
  var import_select_agent = require('../signing/agent-resolver/select-agent.js');
46
47
  var import_strict_json = require('../signing/agent-resolver/strict-json.js');
48
+ var import_jws_artifacts = require('../identity-3.3/jws-artifacts.js');
47
49
  const GOVERNANCE_AUTHORIZATION_CRITICAL_CLAIMS = Object.freeze([
48
50
  "authorized_commitment",
49
51
  "authorized_task",
50
52
  "authorized_payload_hash"
51
53
  ]);
54
+ const GOVERNANCE_JWS_TYP = "adcp-gov+jws";
55
+ const GOVERNANCE_CRIT = {
56
+ authorized_commitment: true,
57
+ authorized_task: true,
58
+ authorized_payload_hash: true
59
+ };
52
60
  class GovernanceReplayStoreAdapter {
53
61
  constructor(replayStore) {
54
62
  this.replayStore = replayStore;
@@ -282,27 +290,19 @@ function targetDeclaresLegacyGovernanceAwareness(capabilities, task) {
282
290
  const mediaBuy = isRecord(root?.media_buy) ? root.media_buy : void 0;
283
291
  return mediaBuy?.governance_aware === true;
284
292
  }
285
- async function verifyGovernanceAuthorization(options) {
293
+ function parseGovernanceJws(token, expectedIssuer) {
286
294
  const reject = (error, message) => ({
287
295
  ok: false,
288
296
  error,
289
297
  message
290
298
  });
291
- if (!options.authenticatedCaller) {
292
- return reject("governance_token_invalid", "Authenticated caller is required");
293
- }
294
- try {
295
- buildGovernanceCommitment(options.actualCommitment.amount, options.actualCommitment.currency);
296
- } catch (error) {
297
- return reject("governance_token_invalid", error.message);
298
- }
299
- if (typeof options.token !== "string" || options.token.length === 0) {
299
+ if (typeof token !== "string" || token.length === 0) {
300
300
  return reject("governance_token_invalid", "governance_context is required");
301
301
  }
302
- if (options.token.length > 4096) {
302
+ if (token.length > 4096) {
303
303
  return reject("governance_token_invalid", "governance_context exceeds the protocol size limit");
304
304
  }
305
- const parts = options.token.split(".");
305
+ const parts = token.split(".");
306
306
  if (parts.length !== 3 || parts.some((part) => !part || !/^[A-Za-z0-9_-]+$/.test(part))) {
307
307
  return reject("governance_token_invalid", "governance_context is not a compact JWS");
308
308
  }
@@ -315,7 +315,7 @@ async function verifyGovernanceAuthorization(options) {
315
315
  if (alg !== "EdDSA" && alg !== "ES256") {
316
316
  return reject("governance_token_invalid", "Unsupported governance JWS algorithm");
317
317
  }
318
- if (protectedHeader.typ !== "adcp-gov+jws") {
318
+ if (protectedHeader.typ !== GOVERNANCE_JWS_TYP) {
319
319
  return reject("governance_token_invalid", "Invalid governance JWS typ");
320
320
  }
321
321
  const critical = protectedHeader.crit;
@@ -343,35 +343,71 @@ async function verifyGovernanceAuthorization(options) {
343
343
  try {
344
344
  if (typeof decodedClaims.iss !== "string") throw new TypeError("Missing issuer");
345
345
  canonicalIssuer = (0, import_select_agent.canonicalAgentUrl)(decodedClaims.iss);
346
- if (canonicalIssuer !== (0, import_select_agent.canonicalAgentUrl)(options.expectedIssuer)) throw new TypeError("Issuer mismatch");
346
+ if (canonicalIssuer !== (0, import_select_agent.canonicalAgentUrl)(expectedIssuer)) throw new TypeError("Issuer mismatch");
347
347
  } catch {
348
348
  return reject("governance_token_invalid", "Governance token issuer mismatch");
349
349
  }
350
- const kid = typeof protectedHeader.kid === "string" ? protectedHeader.kid : "";
351
- if (!kid) return reject("governance_key_unknown", "Governance signing kid is missing");
352
- let jwk;
350
+ return { ok: true, token, protectedHeader, decodedClaims, canonicalIssuer, alg };
351
+ }
352
+ async function verifyGovernanceAuthorization(options) {
353
+ const reject = (error, message) => ({
354
+ ok: false,
355
+ error,
356
+ message
357
+ });
358
+ if (!options.authenticatedCaller) {
359
+ return reject("governance_token_invalid", "Authenticated caller is required");
360
+ }
353
361
  try {
354
- const resolver = options.buyerIdentity ? createGovernanceAgentJwksResolver(canonicalIssuer, options.buyerIdentity) : options.jwks;
355
- if (!resolver) return reject("governance_key_unknown", "No governance key resolver or buyer identity configured");
356
- jwk = await resolver.resolve(kid);
357
- } catch {
358
- return reject("governance_key_unknown", "Governance signing key could not be resolved");
362
+ buildGovernanceCommitment(options.actualCommitment.amount, options.actualCommitment.currency);
363
+ } catch (error) {
364
+ return reject("governance_token_invalid", error.message);
359
365
  }
360
- if (!jwk || jwk.adcp_use !== "governance-signing" || jwk.use !== "sig" || !jwk.key_ops?.includes("verify") || jwk.alg !== void 0 && jwk.alg !== alg) {
361
- return reject("governance_key_unknown", "Governance signing key is unknown or not authorized");
366
+ const parsed = parseGovernanceJws(options.token, options.expectedIssuer);
367
+ if (!parsed.ok) return parsed;
368
+ const { protectedHeader, decodedClaims, canonicalIssuer, alg } = parsed;
369
+ const kid = typeof protectedHeader.kid === "string" ? protectedHeader.kid : "";
370
+ if (!kid) return reject("governance_key_unknown", "Governance signing kid is missing");
371
+ let profile;
372
+ if (options.webBotAuth) {
373
+ try {
374
+ profile = await (0, import_jws_artifacts.selectJwsArtifactProfile)(options.expectedIssuer, options.webBotAuth.trust);
375
+ } catch {
376
+ return { ...reject("governance_key_unknown", "Governance issuer trust record is unavailable"), retryable: true };
377
+ }
362
378
  }
363
- try {
364
- const key = await (0, import_jose.importJWK)(jwk, alg);
365
- await (0, import_jose.compactVerify)(options.token, key, {
366
- algorithms: [alg],
367
- crit: {
368
- authorized_commitment: true,
369
- authorized_task: true,
370
- authorized_payload_hash: true
379
+ if (profile?.profile === "web-bot-auth") {
380
+ if (options.buyerIdentity) {
381
+ try {
382
+ const record = (0, import_select_agent.relyingPartyAgentRecord)(options.buyerIdentity.brandJson, options.buyerIdentity.brandDomain);
383
+ (0, import_select_agent.selectAgentByUrl)(record, canonicalIssuer, { agentType: "governance" });
384
+ } catch {
385
+ return reject("governance_key_unknown", "Governance issuer is not the buyer's governance agent");
371
386
  }
372
- });
373
- } catch {
374
- return reject("governance_token_invalid", "Governance token signature verification failed");
387
+ }
388
+ const failure = await verifyGovernanceJwsOnWebBotAuth(options.token, profile.origin, options.webBotAuth);
389
+ if (failure) return failure;
390
+ } else {
391
+ let jwk;
392
+ try {
393
+ const resolver = options.buyerIdentity ? createGovernanceAgentJwksResolver(canonicalIssuer, options.buyerIdentity) : options.jwks;
394
+ if (!resolver) return reject("governance_key_unknown", "No governance key resolver or buyer identity configured");
395
+ jwk = await resolver.resolve(kid);
396
+ } catch {
397
+ return reject("governance_key_unknown", "Governance signing key could not be resolved");
398
+ }
399
+ if (!jwk || jwk.adcp_use !== "governance-signing" || jwk.use !== "sig" || !jwk.key_ops?.includes("verify") || jwk.alg !== void 0 && jwk.alg !== alg) {
400
+ return reject("governance_key_unknown", "Governance signing key is unknown or not authorized");
401
+ }
402
+ try {
403
+ const key = await (0, import_jose.importJWK)(jwk, alg);
404
+ await (0, import_jose.compactVerify)(options.token, key, {
405
+ algorithms: [alg],
406
+ crit: GOVERNANCE_CRIT
407
+ });
408
+ } catch {
409
+ return reject("governance_token_invalid", "Governance token signature verification failed");
410
+ }
375
411
  }
376
412
  try {
377
413
  if (options.revocationStore && await options.revocationStore.isRevoked(kid)) {
@@ -529,6 +565,113 @@ async function verifyGovernanceAuthorization(options) {
529
565
  payloadHash
530
566
  };
531
567
  }
568
+ function governanceFailureFromJwsArtifact(error) {
569
+ if (!(error instanceof import_jws_artifacts.JwsArtifactError))
570
+ return {
571
+ ok: false,
572
+ error: "governance_key_unknown",
573
+ message: "Governance signing key could not be resolved",
574
+ retryable: true
575
+ };
576
+ switch (error.code) {
577
+ case "jws_key_revoked":
578
+ return { ok: false, error: "governance_token_revoked", message: "Governance signing key is revoked" };
579
+ case "jws_revocation_unavailable":
580
+ return {
581
+ ok: false,
582
+ error: "governance_token_revoked",
583
+ message: "Governance revocation status could not be established",
584
+ retryable: true
585
+ };
586
+ case "jws_invalid":
587
+ return {
588
+ ok: false,
589
+ error: "governance_token_invalid",
590
+ message: `Governance token verification failed: ${error.message}`
591
+ };
592
+ case "jws_key_unavailable":
593
+ return {
594
+ ok: false,
595
+ error: "governance_key_unknown",
596
+ message: "Governance signing key could not be resolved",
597
+ retryable: true
598
+ };
599
+ default:
600
+ return { ok: false, error: "governance_key_unknown", message: "Governance signing key could not be resolved" };
601
+ }
602
+ }
603
+ const NO_ORIGIN_REVOCATION = Object.freeze({
604
+ ok: false,
605
+ error: "governance_token_revoked",
606
+ message: "No origin revocation source is configured for the Web Bot Auth path"
607
+ });
608
+ async function verifyGovernanceJwsOnWebBotAuth(token, origin, webBotAuth) {
609
+ if (!webBotAuth.revocation) return { ...NO_ORIGIN_REVOCATION };
610
+ try {
611
+ await (0, import_jws_artifacts.verifyWebBotAuthJwsArtifact)(token, origin, {
612
+ typ: GOVERNANCE_JWS_TYP,
613
+ directory: webBotAuth.directory,
614
+ revocation: webBotAuth.revocation,
615
+ // A governance context authorizes spend: an origin that serves no list fails closed.
616
+ revocationAbsent: "reject",
617
+ crit: GOVERNANCE_CRIT
618
+ });
619
+ return void 0;
620
+ } catch (error) {
621
+ return governanceFailureFromJwsArtifact(error);
622
+ }
623
+ }
624
+ async function verifyHistoricalGovernanceContext(options) {
625
+ const parsed = parseGovernanceJws(options.token, options.expectedIssuer);
626
+ if (!parsed.ok) return parsed;
627
+ if (parsed.alg !== "EdDSA")
628
+ return {
629
+ ok: false,
630
+ error: "governance_token_invalid",
631
+ message: "A Web Bot Auth governance context uses alg EdDSA"
632
+ };
633
+ if (!options.webBotAuth.revocation) return { ...NO_ORIGIN_REVOCATION };
634
+ let profile;
635
+ try {
636
+ profile = await (0, import_jws_artifacts.selectJwsArtifactProfile)(options.expectedIssuer, options.webBotAuth.trust);
637
+ } catch {
638
+ return {
639
+ ok: false,
640
+ error: "governance_key_unknown",
641
+ message: "Governance issuer trust record is unavailable",
642
+ retryable: true
643
+ };
644
+ }
645
+ if (profile.profile !== "web-bot-auth")
646
+ return {
647
+ ok: false,
648
+ error: "governance_key_unknown",
649
+ message: "Governance issuer is on the 3.2 profile; its trust record does not list its origin",
650
+ profile: "3.2"
651
+ };
652
+ try {
653
+ const verified = await (0, import_jws_artifacts.verifyWebBotAuthJwsArtifact)(parsed.token, profile.origin, {
654
+ typ: GOVERNANCE_JWS_TYP,
655
+ directory: options.webBotAuth.directory,
656
+ archive: options.webBotAuth.archive,
657
+ revocation: options.webBotAuth.revocation,
658
+ // No spend rides on an audit: an origin that serves no list has revoked nothing.
659
+ revocationAbsent: "accept",
660
+ revokedKey: "report",
661
+ crit: GOVERNANCE_CRIT
662
+ });
663
+ return {
664
+ ok: true,
665
+ claims: parsed.decodedClaims,
666
+ protectedHeader: parsed.protectedHeader,
667
+ keySource: verified.keySource,
668
+ revocation: verified.revocation,
669
+ ...verified.revocationDetail ? { revocationDetail: verified.revocationDetail } : {}
670
+ };
671
+ } catch (error) {
672
+ return governanceFailureFromJwsArtifact(error);
673
+ }
674
+ }
532
675
  class GovernanceAuthorizationError extends Error {
533
676
  code;
534
677
  constructor(result) {
@@ -585,5 +728,6 @@ function decodeJsonObject(segment) {
585
728
  governanceTaskRequiresProposedCommitment,
586
729
  targetDeclaresGovernanceEnforcement,
587
730
  targetDeclaresLegacyGovernanceAwareness,
588
- verifyGovernanceAuthorization
731
+ verifyGovernanceAuthorization,
732
+ verifyHistoricalGovernanceContext
589
733
  });