@adcp/sdk 16.1.0 → 16.3.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 (126) hide show
  1. package/AGENTS.md +2 -0
  2. package/dist/lib/core/AgentClient.js +17 -1
  3. package/dist/lib/core/AgentClient.mjs +17 -1
  4. package/dist/lib/core/SingleAgentClient.js +13 -0
  5. package/dist/lib/core/SingleAgentClient.mjs +13 -0
  6. package/dist/lib/core/TaskExecutor.js +88 -13
  7. package/dist/lib/core/TaskExecutor.mjs +89 -14
  8. package/dist/lib/errors/index.d.mts +34 -0
  9. package/dist/lib/errors/index.d.ts +34 -0
  10. package/dist/lib/errors/index.js +11 -0
  11. package/dist/lib/errors/index.mjs +10 -0
  12. package/dist/lib/governance/authorization.d.mts +66 -0
  13. package/dist/lib/governance/authorization.d.ts +66 -0
  14. package/dist/lib/governance/authorization.js +181 -37
  15. package/dist/lib/governance/authorization.mjs +183 -36
  16. package/dist/lib/governance/index.d.mts +2 -2
  17. package/dist/lib/governance/index.d.ts +2 -2
  18. package/dist/lib/governance/index.js +4 -2
  19. package/dist/lib/governance/index.mjs +3 -1
  20. package/dist/lib/identity-3.3/index.d.mts +1 -0
  21. package/dist/lib/identity-3.3/index.d.ts +1 -0
  22. package/dist/lib/identity-3.3/index.js +3 -1
  23. package/dist/lib/identity-3.3/index.mjs +1 -0
  24. package/dist/lib/identity-3.3/jws-artifacts.d.mts +147 -0
  25. package/dist/lib/identity-3.3/jws-artifacts.d.ts +147 -0
  26. package/dist/lib/identity-3.3/jws-artifacts.js +258 -0
  27. package/dist/lib/identity-3.3/jws-artifacts.mjs +234 -0
  28. package/dist/lib/identity-3.3/revocation.d.mts +7 -0
  29. package/dist/lib/identity-3.3/revocation.d.ts +7 -0
  30. package/dist/lib/identity-3.3/revocation.js +13 -0
  31. package/dist/lib/identity-3.3/revocation.mjs +13 -0
  32. package/dist/lib/index.d.mts +3 -3
  33. package/dist/lib/index.d.ts +3 -3
  34. package/dist/lib/index.js +4 -0
  35. package/dist/lib/index.mjs +4 -0
  36. package/dist/lib/media-buy/compatibility.d.mts +1 -0
  37. package/dist/lib/media-buy/compatibility.d.ts +1 -0
  38. package/dist/lib/media-buy/compatibility.js +33 -10
  39. package/dist/lib/media-buy/compatibility.mjs +32 -14
  40. package/dist/lib/negotiation/buyer.js +11 -5
  41. package/dist/lib/negotiation/buyer.mjs +11 -5
  42. package/dist/lib/negotiation/types.d.mts +4 -2
  43. package/dist/lib/negotiation/types.d.ts +4 -2
  44. package/dist/lib/negotiation/verification.d.mts +15 -6
  45. package/dist/lib/negotiation/verification.d.ts +15 -6
  46. package/dist/lib/negotiation/verification.js +146 -27
  47. package/dist/lib/negotiation/verification.mjs +146 -28
  48. package/dist/lib/negotiation/version.d.mts +6 -0
  49. package/dist/lib/negotiation/version.d.ts +6 -0
  50. package/dist/lib/negotiation/version.js +60 -0
  51. package/dist/lib/negotiation/version.mjs +33 -0
  52. package/dist/lib/registry/types.generated.d.mts +24 -1
  53. package/dist/lib/registry/types.generated.d.ts +24 -1
  54. package/dist/lib/server/create-adcp-server.js +1 -1
  55. package/dist/lib/server/create-adcp-server.mjs +1 -1
  56. package/dist/lib/server/error-arm-tools.d.mts +10 -10
  57. package/dist/lib/server/error-arm-tools.d.ts +10 -10
  58. package/dist/lib/server/error-arm-tools.js +22 -58
  59. package/dist/lib/server/error-arm-tools.mjs +30 -65
  60. package/dist/lib/server/index.d.mts +2 -2
  61. package/dist/lib/server/index.d.ts +2 -2
  62. package/dist/lib/server/index.js +2 -0
  63. package/dist/lib/server/index.mjs +2 -0
  64. package/dist/lib/signing/web-bot-auth.js +5 -0
  65. package/dist/lib/signing/web-bot-auth.mjs +4 -0
  66. package/dist/lib/testing/compliance/comply.js +17 -0
  67. package/dist/lib/testing/compliance/comply.mjs +17 -0
  68. package/dist/lib/testing/index.d.mts +3 -0
  69. package/dist/lib/testing/index.d.ts +3 -0
  70. package/dist/lib/testing/index.js +44 -2
  71. package/dist/lib/testing/index.mjs +42 -0
  72. package/dist/lib/testing/storyboard/collection-selection.d.mts +259 -0
  73. package/dist/lib/testing/storyboard/collection-selection.d.ts +259 -0
  74. package/dist/lib/testing/storyboard/collection-selection.js +384 -0
  75. package/dist/lib/testing/storyboard/collection-selection.mjs +348 -0
  76. package/dist/lib/testing/storyboard/context.js +12 -6
  77. package/dist/lib/testing/storyboard/context.mjs +12 -6
  78. package/dist/lib/testing/storyboard/fixture-resolution.d.mts +39 -1
  79. package/dist/lib/testing/storyboard/fixture-resolution.d.ts +39 -1
  80. package/dist/lib/testing/storyboard/fixture-resolution.js +216 -12
  81. package/dist/lib/testing/storyboard/fixture-resolution.mjs +218 -12
  82. package/dist/lib/testing/storyboard/index.d.mts +9 -2
  83. package/dist/lib/testing/storyboard/index.d.ts +9 -2
  84. package/dist/lib/testing/storyboard/index.js +51 -2
  85. package/dist/lib/testing/storyboard/index.mjs +49 -1
  86. package/dist/lib/testing/storyboard/prepared-fixtures.d.mts +471 -0
  87. package/dist/lib/testing/storyboard/prepared-fixtures.d.ts +471 -0
  88. package/dist/lib/testing/storyboard/prepared-fixtures.js +434 -0
  89. package/dist/lib/testing/storyboard/prepared-fixtures.mjs +389 -0
  90. package/dist/lib/testing/storyboard/protected-context.d.mts +127 -0
  91. package/dist/lib/testing/storyboard/protected-context.d.ts +127 -0
  92. package/dist/lib/testing/storyboard/protected-context.js +301 -0
  93. package/dist/lib/testing/storyboard/protected-context.mjs +267 -0
  94. package/dist/lib/testing/storyboard/rejection-hints.js +13 -4
  95. package/dist/lib/testing/storyboard/rejection-hints.mjs +13 -4
  96. package/dist/lib/testing/storyboard/runner.d.mts +24 -0
  97. package/dist/lib/testing/storyboard/runner.d.ts +24 -0
  98. package/dist/lib/testing/storyboard/runner.js +1061 -105
  99. package/dist/lib/testing/storyboard/runner.mjs +1075 -106
  100. package/dist/lib/testing/storyboard/seeding.d.mts +15 -1
  101. package/dist/lib/testing/storyboard/seeding.d.ts +15 -1
  102. package/dist/lib/testing/storyboard/seeding.js +272 -12
  103. package/dist/lib/testing/storyboard/seeding.mjs +274 -13
  104. package/dist/lib/testing/storyboard/types.d.mts +207 -10
  105. package/dist/lib/testing/storyboard/types.d.ts +207 -10
  106. package/dist/lib/testing/storyboard/types.js +1 -1
  107. package/dist/lib/testing/storyboard/types.mjs +1 -1
  108. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  109. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  110. package/dist/lib/testing/storyboard/validations.js +95 -0
  111. package/dist/lib/testing/storyboard/validations.mjs +95 -0
  112. package/dist/lib/validation/bundled-schema-store.js +5 -0
  113. package/dist/lib/validation/bundled-schema-store.mjs +4 -0
  114. package/dist/lib/validation/schema-loader.js +19 -2
  115. package/dist/lib/validation/schema-loader.mjs +22 -3
  116. package/dist/lib/version.d.mts +3 -3
  117. package/dist/lib/version.d.ts +3 -3
  118. package/dist/lib/version.js +3 -3
  119. package/dist/lib/version.mjs +3 -3
  120. package/docs/TYPE-SUMMARY.md +2 -2
  121. package/docs/guides/COLLECTION-FIXTURE-FOUNDATION.md +850 -0
  122. package/docs/guides/PROPOSAL-TERMS-VERIFICATION.md +66 -0
  123. package/docs/llms.txt +4 -3
  124. package/docs/migration-14.x-rc-worksheet.md +4 -4
  125. package/docs/migration-agent-identity-3.3.md +51 -6
  126. package/package.json +6 -4
@@ -537,3 +537,37 @@ export declare function extractErrorInfo(error: unknown): {
537
537
  details?: unknown;
538
538
  stack?: string;
539
539
  };
540
+ /**
541
+ * Prepared fixture state was refused by the host authorizer.
542
+ *
543
+ * An authorization failure is an ACCESS-CONTROL error, not a grading
544
+ * outcome, so the refused caller gets this and no `StoryboardResult` —
545
+ * not a partial one, not a redacted one. It carries the machine refusal
546
+ * code and nothing else: no fixture identities, no `seller_ids`, no
547
+ * captures, no binding values, no request/response records, and no
548
+ * results from steps that ran before the grant was revoked.
549
+ *
550
+ * The complete, unredacted record — including the synthesized
551
+ * `prepared_fixtures_authorization` check, `fixture_resolutions` with
552
+ * `seller_ids`, and exact request/response records — is handed to the
553
+ * host's `prepared_fixtures_audit_sink` before this is thrown. Where no
554
+ * sink is configured the record is simply not produced to anyone.
555
+ *
556
+ * Hosted entry points should surface this as a 403-style denial.
557
+ */
558
+ export declare class PreparedFixturesDeniedError extends ADCPError {
559
+ /**
560
+ * Machine refusal code: `authorizer_required` | `untrusted_state` |
561
+ * `contract_version_mismatch` | `authorizer_denied` |
562
+ * `binding_mismatch` | `unauthorized_metadata`.
563
+ */
564
+ readonly refusalCode: string;
565
+ readonly code = "PREPARED_FIXTURES_DENIED";
566
+ constructor(
567
+ /**
568
+ * Machine refusal code: `authorizer_required` | `untrusted_state` |
569
+ * `contract_version_mismatch` | `authorizer_denied` |
570
+ * `binding_mismatch` | `unauthorized_metadata`.
571
+ */
572
+ refusalCode: string);
573
+ }
@@ -39,6 +39,7 @@ __export(errors_exports, {
39
39
  InvalidContextError: () => InvalidContextError,
40
40
  MaxClarificationError: () => MaxClarificationError,
41
41
  MissingInputHandlerError: () => MissingInputHandlerError,
42
+ PreparedFixturesDeniedError: () => PreparedFixturesDeniedError,
42
43
  ProtocolError: () => ProtocolError,
43
44
  ProtocolFeatureUnsupportedError: () => ProtocolFeatureUnsupportedError,
44
45
  ResponseTooLargeError: () => ResponseTooLargeError,
@@ -655,6 +656,15 @@ function extractErrorInfo(error) {
655
656
  message: String(error)
656
657
  };
657
658
  }
659
+ class PreparedFixturesDeniedError extends ADCPError {
660
+ constructor(refusalCode) {
661
+ super(`prepared fixture state was refused by the configured authorizer (${refusalCode})`);
662
+ this.refusalCode = refusalCode;
663
+ this.details = { refusal_code: refusalCode };
664
+ }
665
+ refusalCode;
666
+ code = "PREPARED_FIXTURES_DENIED";
667
+ }
658
668
  // Annotate the CommonJS export names for ESM import in node:
659
669
  0 && (module.exports = {
660
670
  ADCPError,
@@ -678,6 +688,7 @@ function extractErrorInfo(error) {
678
688
  InvalidContextError,
679
689
  MaxClarificationError,
680
690
  MissingInputHandlerError,
691
+ PreparedFixturesDeniedError,
681
692
  ProtocolError,
682
693
  ProtocolFeatureUnsupportedError,
683
694
  ResponseTooLargeError,
@@ -595,6 +595,15 @@ function extractErrorInfo(error) {
595
595
  message: String(error)
596
596
  };
597
597
  }
598
+ class PreparedFixturesDeniedError extends ADCPError {
599
+ constructor(refusalCode) {
600
+ super(`prepared fixture state was refused by the configured authorizer (${refusalCode})`);
601
+ this.refusalCode = refusalCode;
602
+ this.details = { refusal_code: refusalCode };
603
+ }
604
+ refusalCode;
605
+ code = "PREPARED_FIXTURES_DENIED";
606
+ }
598
607
  export {
599
608
  ADCPError,
600
609
  AccountAmbiguousError,
@@ -617,6 +626,7 @@ export {
617
626
  InvalidContextError,
618
627
  MaxClarificationError,
619
628
  MissingInputHandlerError,
629
+ PreparedFixturesDeniedError,
620
630
  ProtocolError,
621
631
  ProtocolFeatureUnsupportedError,
622
632
  ResponseTooLargeError,
@@ -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
  });