@adcp/sdk 16.0.0-beta.1 → 16.0.0-beta.3

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 (155) hide show
  1. package/README.md +54 -0
  2. package/dist/lib/core/ConversationTypes.d.mts +8 -3
  3. package/dist/lib/core/ConversationTypes.d.ts +8 -3
  4. package/dist/lib/core/SingleAgentClient.d.mts +15 -4
  5. package/dist/lib/core/SingleAgentClient.d.ts +15 -4
  6. package/dist/lib/core/SingleAgentClient.js +29 -8
  7. package/dist/lib/core/SingleAgentClient.mjs +29 -8
  8. package/dist/lib/core/TaskExecutor.js +5 -1
  9. package/dist/lib/core/TaskExecutor.mjs +5 -1
  10. package/dist/lib/errors/index.d.mts +9 -4
  11. package/dist/lib/errors/index.d.ts +9 -4
  12. package/dist/lib/identity-3.3/generated-compat.d.mts +34 -0
  13. package/dist/lib/identity-3.3/generated-compat.d.ts +34 -0
  14. package/dist/lib/identity-3.3/generated-compat.js +16 -0
  15. package/dist/lib/identity-3.3/generated-compat.mjs +0 -0
  16. package/dist/lib/identity-3.3/index.d.mts +2 -2
  17. package/dist/lib/identity-3.3/index.d.ts +2 -2
  18. package/dist/lib/identity-3.3/index.js +4 -0
  19. package/dist/lib/identity-3.3/index.mjs +5 -1
  20. package/dist/lib/identity-3.3/lifecycle.d.mts +17 -5
  21. package/dist/lib/identity-3.3/lifecycle.d.ts +17 -5
  22. package/dist/lib/identity-3.3/lifecycle.js +32 -5
  23. package/dist/lib/identity-3.3/lifecycle.mjs +38 -6
  24. package/dist/lib/identity-3.3/revocation.d.mts +39 -3
  25. package/dist/lib/identity-3.3/revocation.d.ts +39 -3
  26. package/dist/lib/identity-3.3/revocation.js +88 -18
  27. package/dist/lib/identity-3.3/revocation.mjs +89 -19
  28. package/dist/lib/identity-3.3/server.d.mts +12 -0
  29. package/dist/lib/identity-3.3/server.d.ts +12 -0
  30. package/dist/lib/identity-3.3/server.js +103 -43
  31. package/dist/lib/identity-3.3/server.mjs +111 -45
  32. package/dist/lib/identity-3.3/trust.d.mts +62 -1
  33. package/dist/lib/identity-3.3/trust.d.ts +62 -1
  34. package/dist/lib/identity-3.3/trust.js +126 -21
  35. package/dist/lib/identity-3.3/trust.mjs +124 -21
  36. package/dist/lib/identity-3.3/types.d.mts +39 -11
  37. package/dist/lib/identity-3.3/types.d.ts +39 -11
  38. package/dist/lib/index.d.mts +3 -3
  39. package/dist/lib/index.d.ts +3 -3
  40. package/dist/lib/index.js +8 -0
  41. package/dist/lib/index.mjs +9 -1
  42. package/dist/lib/negotiation/types.d.mts +20 -39
  43. package/dist/lib/negotiation/types.d.ts +20 -39
  44. package/dist/lib/protocols/index.d.mts +61 -25
  45. package/dist/lib/protocols/index.d.ts +61 -25
  46. package/dist/lib/protocols/index.js +11 -6
  47. package/dist/lib/protocols/index.mjs +5 -2
  48. package/dist/lib/protocols/mcp-modern.js +1 -0
  49. package/dist/lib/protocols/mcp-modern.mjs +2 -1
  50. package/dist/lib/protocols/mcp.js +1 -0
  51. package/dist/lib/protocols/mcp.mjs +2 -1
  52. package/dist/lib/protocols/responseSizeLimit.d.mts +91 -5
  53. package/dist/lib/protocols/responseSizeLimit.d.ts +91 -5
  54. package/dist/lib/protocols/responseSizeLimit.js +195 -31
  55. package/dist/lib/protocols/responseSizeLimit.mjs +192 -31
  56. package/dist/lib/reporting/bigquery/index.js +8 -0
  57. package/dist/lib/reporting/bigquery/index.mjs +8 -0
  58. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  59. package/dist/lib/server/auth-signature.d.mts +6 -1
  60. package/dist/lib/server/auth-signature.d.ts +6 -1
  61. package/dist/lib/server/auth-signature.js +24 -13
  62. package/dist/lib/server/auth-signature.mjs +29 -13
  63. package/dist/lib/server/auth.d.mts +2 -2
  64. package/dist/lib/server/auth.d.ts +2 -2
  65. package/dist/lib/server/create-adcp-server.js +31 -10
  66. package/dist/lib/server/create-adcp-server.mjs +37 -11
  67. package/dist/lib/signing/crypto.d.mts +15 -0
  68. package/dist/lib/signing/crypto.d.ts +15 -0
  69. package/dist/lib/signing/crypto.js +83 -3
  70. package/dist/lib/signing/crypto.mjs +86 -3
  71. package/dist/lib/signing/fetch-async.js +1 -1
  72. package/dist/lib/signing/fetch-async.mjs +1 -1
  73. package/dist/lib/signing/fetch.js +1 -1
  74. package/dist/lib/signing/fetch.mjs +1 -1
  75. package/dist/lib/signing/middleware.js +9 -0
  76. package/dist/lib/signing/middleware.mjs +14 -0
  77. package/dist/lib/signing/parser.d.mts +8 -5
  78. package/dist/lib/signing/parser.d.ts +8 -5
  79. package/dist/lib/signing/parser.js +77 -61
  80. package/dist/lib/signing/parser.mjs +77 -61
  81. package/dist/lib/signing/revocation.js +3 -0
  82. package/dist/lib/signing/revocation.mjs +3 -0
  83. package/dist/lib/signing/server.d.mts +1 -1
  84. package/dist/lib/signing/server.d.ts +1 -1
  85. package/dist/lib/signing/server.js +2 -0
  86. package/dist/lib/signing/server.mjs +2 -1
  87. package/dist/lib/signing/signer.js +2 -8
  88. package/dist/lib/signing/signer.mjs +3 -9
  89. package/dist/lib/signing/testing.js +2 -6
  90. package/dist/lib/signing/testing.mjs +3 -7
  91. package/dist/lib/signing/verifier.js +3 -3
  92. package/dist/lib/signing/verifier.mjs +4 -4
  93. package/dist/lib/signing/web-bot-auth.d.mts +84 -10
  94. package/dist/lib/signing/web-bot-auth.d.ts +84 -10
  95. package/dist/lib/signing/web-bot-auth.js +278 -88
  96. package/dist/lib/signing/web-bot-auth.mjs +279 -94
  97. package/dist/lib/signing/webhook-verifier.js +3 -3
  98. package/dist/lib/signing/webhook-verifier.mjs +4 -4
  99. package/dist/lib/substitution/compile.js +2 -1
  100. package/dist/lib/substitution/compile.mjs +2 -1
  101. package/dist/lib/substitution/consent-macros.d.mts +4 -0
  102. package/dist/lib/substitution/consent-macros.d.ts +4 -0
  103. package/dist/lib/substitution/consent-macros.js +45 -0
  104. package/dist/lib/substitution/consent-macros.mjs +20 -0
  105. package/dist/lib/substitution/index.d.mts +1 -1
  106. package/dist/lib/substitution/index.d.ts +1 -1
  107. package/dist/lib/substitution/index.js +2 -0
  108. package/dist/lib/substitution/index.mjs +2 -1
  109. package/dist/lib/substitution/translate.d.mts +15 -2
  110. package/dist/lib/substitution/translate.d.ts +15 -2
  111. package/dist/lib/substitution/translate.js +148 -26
  112. package/dist/lib/substitution/translate.mjs +147 -26
  113. package/dist/lib/testing/client.js +2 -1
  114. package/dist/lib/testing/client.mjs +2 -1
  115. package/dist/lib/testing/scenarios/capabilities.js +1 -1
  116. package/dist/lib/testing/scenarios/capabilities.mjs +1 -1
  117. package/dist/lib/testing/storyboard/request-signing/builder.js +2 -5
  118. package/dist/lib/testing/storyboard/request-signing/builder.mjs +3 -6
  119. package/dist/lib/testing/storyboard/signer-grader/grader.js +2 -7
  120. package/dist/lib/testing/storyboard/signer-grader/grader.mjs +2 -7
  121. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  122. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  123. package/dist/lib/types/enums.generated.d.mts +3 -0
  124. package/dist/lib/types/enums.generated.d.ts +3 -0
  125. package/dist/lib/types/enums.generated.js +9 -0
  126. package/dist/lib/types/enums.generated.mjs +6 -0
  127. package/dist/lib/v2/projection/catalog-snapshot.js +3 -1
  128. package/dist/lib/v2/projection/catalog-snapshot.mjs +3 -1
  129. package/dist/lib/v2/projection/creative-delivery.d.mts +31 -9
  130. package/dist/lib/v2/projection/creative-delivery.d.ts +31 -9
  131. package/dist/lib/v2/projection/index.d.mts +1 -1
  132. package/dist/lib/v2/projection/index.d.ts +1 -1
  133. package/dist/lib/v2/projection/index.js +2 -0
  134. package/dist/lib/v2/projection/index.mjs +2 -0
  135. package/dist/lib/v2/projection/legacy-routes.d.mts +10 -0
  136. package/dist/lib/v2/projection/legacy-routes.d.ts +10 -0
  137. package/dist/lib/v2/projection/legacy-routes.js +7 -0
  138. package/dist/lib/v2/projection/legacy-routes.mjs +6 -0
  139. package/dist/lib/validation/schema-loader.js +25 -0
  140. package/dist/lib/validation/schema-loader.mjs +24 -0
  141. package/dist/lib/version.d.mts +3 -3
  142. package/dist/lib/version.d.ts +3 -3
  143. package/dist/lib/version.js +3 -3
  144. package/dist/lib/version.mjs +3 -3
  145. package/docs/TYPE-SUMMARY.md +7 -2
  146. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +3 -2
  147. package/docs/guides/REPORTING-LEDGER.md +15 -5
  148. package/docs/guides/REPORTING-OPERATIONS.md +17 -11
  149. package/docs/guides/UNIVERSAL-MACRO-COMPILATION.md +38 -0
  150. package/docs/guides/VALIDATE-YOUR-AGENT.md +12 -0
  151. package/docs/llms.txt +2 -2
  152. package/docs/migration-12-to-13.md +8 -0
  153. package/docs/migration-14.x-rc-worksheet.md +4 -4
  154. package/docs/migration-agent-identity-3.3.md +150 -11
  155. package/package.json +4 -1
@@ -1,5 +1,9 @@
1
1
  import { createHash } from "crypto";
2
- import { registerWebBotAuthLegacyOriginGate } from "../signing/web-bot-auth.mjs";
2
+ import {
3
+ registerWebBotAuthLegacyOriginGate,
4
+ registerWebBotAuthRevocationCheck,
5
+ WebBotAuthUnavailableError
6
+ } from "../signing/web-bot-auth.mjs";
3
7
  import { RequestSignatureError } from "../signing/errors.mjs";
4
8
  import { TaskTypeValues } from "../types/enums.generated.mjs";
5
9
  import { AdcpError } from "../server/decisioning/async-outcome.mjs";
@@ -8,7 +12,9 @@ import { markVerifiedHttpSig } from "../server/decisioning/buyer-agent.mjs";
8
12
  import { isVerifiedWebBotSigner, WebBotAuthError } from "../signing/web-bot-auth.mjs";
9
13
  import {
10
14
  authorizeDemandGrant,
11
- IdentityAuthorizationError
15
+ IdentityAuthorizationError,
16
+ TrustMembershipError,
17
+ TrustRecordUnavailableError
12
18
  } from "./trust.mjs";
13
19
  import { MUTATING_TASKS } from "../utils/idempotency.mjs";
14
20
  const IDENTITY_ADMIN_TOOLS = /* @__PURE__ */ new Set(["sync_principal", "sync_agent_notification_configs"]);
@@ -26,6 +32,9 @@ function claimFromContext(ctx) {
26
32
  const claim = ctx.authInfo?.extra?.identity33;
27
33
  return claim && isVerifiedWebBotSigner(claim.signer) ? claim : void 0;
28
34
  }
35
+ function anonymousPrincipalFor(origin, prefix = "anonymous") {
36
+ return `${prefix}:${createHash("sha256").update(origin).digest("hex")}`;
37
+ }
29
38
  function isIdentity33UnboundContext(ctx) {
30
39
  return claimFromContext(ctx)?.state === "identity-established";
31
40
  }
@@ -43,17 +52,44 @@ function createIdentity33PrincipalResolver(options) {
43
52
  if (!signers.length || signers.some((s) => !isVerifiedWebBotSigner(s)))
44
53
  throw new WebBotAuthError(403, "unverified_identity");
45
54
  const signer = signers[signers.length - 1];
55
+ let revocation;
56
+ if (options.revocation) {
57
+ revocation = "current";
58
+ for (const each of signers) {
59
+ let status;
60
+ try {
61
+ status = await options.revocation.status(each.origin, each.keyid);
62
+ } catch (error) {
63
+ throw new WebBotAuthUnavailableError("revocation_persistence_failed", error);
64
+ }
65
+ if (status === "revoked") throw new WebBotAuthError(403, "key_revoked");
66
+ if (status === "unknown") throw new WebBotAuthError(403, "identity_unverified");
67
+ if (status === "absent") revocation = "absent";
68
+ }
69
+ }
46
70
  const revoked = signers.find((s) => s.authorizationFailure);
47
- const { binding } = revoked ? { binding: void 0 } : await options.lifecycle.getPrincipal(signer.origin);
71
+ let { binding } = revoked || revocation === "absent" ? { binding: void 0 } : await options.lifecycle.getPrincipal(signer.origin);
72
+ if (binding) {
73
+ try {
74
+ await options.lifecycle.authorizeBound(signer.origin, { readOnly: true });
75
+ } catch (error) {
76
+ if (error instanceof TrustMembershipError) binding = void 0;
77
+ else if (error instanceof TrustRecordUnavailableError)
78
+ throw new WebBotAuthUnavailableError("trust_record_unavailable", error);
79
+ else throw error;
80
+ }
81
+ }
48
82
  if (!binding && operation !== void 0 && typeof operation !== "string")
49
83
  throw new WebBotAuthError(400, "operation");
50
84
  const authorizationFailure = revoked?.authorizationFailure ?? (!binding && typeof operation === "string" && !anonymousTools.has(operation) ? createWebBotAuthAuthorizationFailure("identity_not_bound") : void 0);
51
85
  return {
52
- principal: binding?.principalId ?? `${options.anonymousPrincipal ?? "anonymous"}:${createHash("sha256").update(signer.origin).digest("hex")}`,
86
+ principal: binding?.principalId ?? anonymousPrincipalFor(signer.origin, options.anonymousPrincipal),
53
87
  extra: {
54
88
  identity33: {
55
89
  state: binding ? "bound" : "identity-established",
56
90
  signer: revoked ?? signer,
91
+ ...revocation && { revocation },
92
+ anonymousPrincipal: anonymousPrincipalFor(signer.origin, options.anonymousPrincipal),
57
93
  ...authorizationFailure && { authorizationFailure }
58
94
  }
59
95
  },
@@ -67,6 +103,7 @@ function createIdentity33PrincipalResolver(options) {
67
103
  } : {}
68
104
  };
69
105
  };
106
+ if (options.revocation) registerWebBotAuthRevocationCheck(resolver);
70
107
  registerWebBotAuthLegacyOriginGate(resolver, async (origin) => {
71
108
  if ((await options.lifecycle.getPrincipal(origin)).binding)
72
109
  throw new RequestSignatureError(
@@ -78,6 +115,37 @@ function createIdentity33PrincipalResolver(options) {
78
115
  return resolver;
79
116
  }
80
117
  function createIdentity33Authorization(options) {
118
+ const anonymousTools = options.anonymousTools ?? [
119
+ "get_principal",
120
+ "get_adcp_capabilities",
121
+ "list_creative_formats",
122
+ "get_products"
123
+ ];
124
+ const authorizeUnbound = async (ctx, identity, tool, params) => {
125
+ if (tool === "sync_principal") {
126
+ if (identity.revocation === "absent")
127
+ throw new AdcpError("PERMISSION_DENIED", { message: "Agent identity cannot be onboarded" });
128
+ const dryRun = !!params && typeof params === "object" && params.dry_run === true;
129
+ const binding = await options.lifecycle.syncOpen(identity.signer.origin, { dryRun });
130
+ if (dryRun) return;
131
+ if (!ctx.authInfo) throw new IdentityAuthorizationError();
132
+ ctx.authInfo.clientId = binding.principalId;
133
+ ctx.authInfo.credential = markVerifiedHttpSig({
134
+ kind: "http_sig",
135
+ keyid: identity.signer.keyid,
136
+ agent_url: identity.signer.origin,
137
+ verified_at: identity.signer.verified_at
138
+ });
139
+ ctx.authInfo.extra = {
140
+ ...ctx.authInfo.extra,
141
+ credential: ctx.authInfo.credential,
142
+ identity33: { ...identity, state: "bound" }
143
+ };
144
+ return;
145
+ }
146
+ if (anonymousTools.includes(tool) && !needsSpendAuthorization(tool, params)) return;
147
+ throw new AdcpError("PERMISSION_DENIED", { message: "Agent identity is not onboarded for this operation" });
148
+ };
81
149
  return async (ctx, tool, params) => {
82
150
  const identity = claimFromContext(ctx);
83
151
  const failure = getWebBotAuthAuthorizationFailure(ctx.authInfo?.extra);
@@ -90,48 +158,43 @@ function createIdentity33Authorization(options) {
90
158
  });
91
159
  return;
92
160
  }
93
- if (identity.state === "identity-established") {
94
- if (tool === "sync_principal") {
95
- const dryRun = !!params && typeof params === "object" && params.dry_run === true;
96
- const binding = await options.lifecycle.syncOpen(identity.signer.origin, { dryRun });
97
- if (dryRun) return;
98
- if (!ctx.authInfo) throw new IdentityAuthorizationError();
99
- ctx.authInfo.clientId = binding.principalId;
100
- ctx.authInfo.credential = markVerifiedHttpSig({
101
- kind: "http_sig",
102
- keyid: identity.signer.keyid,
103
- agent_url: identity.signer.origin,
104
- verified_at: identity.signer.verified_at
105
- });
106
- ctx.authInfo.extra = {
107
- ...ctx.authInfo.extra,
108
- credential: ctx.authInfo.credential,
109
- identity33: { ...identity, state: "bound" }
110
- };
161
+ if (identity.state === "identity-established") return authorizeUnbound(ctx, identity, tool, params);
162
+ const origin = identity.signer.origin;
163
+ const spend = !IDENTITY_ADMIN_TOOLS.has(tool) && needsSpendAuthorization(tool, params) && !(!KNOWN_TOOLS.has(tool) && options.readOnlyTools?.includes(tool));
164
+ try {
165
+ if (IDENTITY_ADMIN_TOOLS.has(tool)) {
166
+ await options.lifecycle.authorizeBound(origin, { identityConfiguration: true });
111
167
  return;
112
168
  }
113
- if ((options.anonymousTools ?? ["get_principal", "get_adcp_capabilities", "list_creative_formats", "get_products"]).includes(tool) && !needsSpendAuthorization(tool, params))
169
+ if (!spend) {
170
+ await options.lifecycle.authorizeBound(origin, { readOnly: true });
114
171
  return;
115
- throw new AdcpError("PERMISSION_DENIED", { message: "Agent identity is not onboarded for this operation" });
116
- }
117
- const origin = identity.signer.origin;
118
- if (IDENTITY_ADMIN_TOOLS.has(tool)) {
119
- await options.lifecycle.authorizeBound(origin, { identityConfiguration: true });
120
- return;
121
- }
122
- if (!needsSpendAuthorization(tool, params) || !KNOWN_TOOLS.has(tool) && options.readOnlyTools?.includes(tool)) {
123
- await options.lifecycle.authorizeBound(origin, { readOnly: true });
124
- return;
125
- }
126
- const claims = await options.resolveClaims(ctx, tool, params);
127
- if (!claims.length) throw new IdentityAuthorizationError();
128
- for (const claim of claims) {
129
- await options.lifecycle.authorizeBound(origin, {
130
- sandbox: claim.sandbox,
131
- billing: claim.billing,
132
- brandDomain: claim.brand.domain
133
- });
134
- await authorizeDemandGrant({ ...claim, signerOrigin: origin }, options.grants);
172
+ }
173
+ const claims = await options.resolveClaims(ctx, tool, params);
174
+ if (!claims.length) throw new IdentityAuthorizationError();
175
+ for (const claim of claims) {
176
+ await options.lifecycle.authorizeBound(origin, {
177
+ sandbox: claim.sandbox,
178
+ billing: claim.billing,
179
+ brandDomain: claim.brand.domain
180
+ });
181
+ await authorizeDemandGrant({ ...claim, signerOrigin: origin }, options.grants);
182
+ }
183
+ } catch (error) {
184
+ if (error instanceof TrustRecordUnavailableError)
185
+ throw new AdcpError("SERVICE_UNAVAILABLE", { message: error.message, recovery: "transient" });
186
+ if (error instanceof TrustMembershipError && !spend) {
187
+ const demoted = { ...identity, state: "identity-established" };
188
+ if (ctx.authInfo) {
189
+ const { credential: _credential, ...extra } = ctx.authInfo.extra ?? {};
190
+ ctx.authInfo.clientId = identity.anonymousPrincipal ?? anonymousPrincipalFor(origin);
191
+ delete ctx.authInfo.credential;
192
+ ctx.authInfo.extra = { ...extra, identity33: demoted };
193
+ }
194
+ delete ctx.agent;
195
+ return authorizeUnbound(ctx, demoted, tool, params);
196
+ }
197
+ throw error;
135
198
  }
136
199
  };
137
200
  }
@@ -152,7 +215,10 @@ function withIdentity33PrincipalHandlers(base, lifecycle) {
152
215
  return base.getPrincipal(params, ctx);
153
216
  }
154
217
  const read = await lifecycle.getPrincipal(identity.signer.origin);
155
- if (!read.binding) return { result: read.result };
218
+ if (!read.binding || identity.state === "identity-established")
219
+ return {
220
+ result: { kind: "unconfigured", ...read.result.relationship && { relationship: read.result.relationship } }
221
+ };
156
222
  if (!base.getPrincipal) return { result: read.result };
157
223
  const response = await base.getPrincipal(params, ctx);
158
224
  if (read.result.relationship && response && typeof response === "object") {
@@ -176,7 +242,7 @@ function createIdentity33PrincipalScopeResolver(options) {
176
242
  return options.legacy(ctx);
177
243
  }
178
244
  const { binding } = await options.lifecycle.getPrincipal(identity.signer.origin);
179
- if (!binding) throw new IdentityAuthorizationError();
245
+ if (!binding || identity.state !== "bound") throw new IdentityAuthorizationError();
180
246
  return {
181
247
  tenant_id: options.tenantId,
182
248
  principal_id: binding.principalId,
@@ -6,6 +6,32 @@ export declare class IdentityAuthorizationError extends Error {
6
6
  readonly details: AgentGrantDeniedDetails | undefined;
7
7
  constructor(reason?: 'authorization_failed' | 'grant_absent');
8
8
  }
9
+ /**
10
+ * The trust record could not be read (transport error, outage, capacity,
11
+ * invalid content). A fetch failure is never absence or delisting: spend
12
+ * fails closed with a retryable SERVICE_UNAVAILABLE, other calls continue
13
+ * under an existing binding.
14
+ */
15
+ export declare class TrustRecordUnavailableError extends IdentityAuthorizationError {
16
+ readonly transient: true;
17
+ /**
18
+ * Set by `match()`: the last record read for this operator listed the origin
19
+ * with the role and is still within the seller's outage bound
20
+ * (`maxOutageContinuationSeconds` past its freshness). Only then may non-spend
21
+ * calls continue under a binding.
22
+ */
23
+ lastKnownListed: boolean;
24
+ constructor();
25
+ }
26
+ /**
27
+ * The operator's last record read does not list the origin with the required
28
+ * role (`unlisted`; operators retire agents by publishing an empty `agents[]`),
29
+ * or the operator has never published one (`absent`).
30
+ */
31
+ export declare class TrustMembershipError extends IdentityAuthorizationError {
32
+ readonly membership: 'unlisted' | 'absent';
33
+ constructor(membership?: 'unlisted' | 'absent');
34
+ }
9
35
  /** Schema plus semantic checks; publication never includes identity keys. */
10
36
  export declare function validateTrustRecord(value: unknown): asserts value is TrustRecord;
11
37
  export declare function createTrustRecord(record: TrustRecord): TrustRecord;
@@ -24,9 +50,30 @@ export type TrustFetchResult = {
24
50
  export interface TrustEvaluatorOptions {
25
51
  /** Matches configured revocation polling: one minute through thirty minutes. */
26
52
  pollingIntervalSeconds?: number;
53
+ /**
54
+ * Seller policy: how long past the last listing record's freshness a bound
55
+ * origin's non-spend calls may continue while its operator's record cannot
56
+ * be read. Spend never continues on an outage. Default four polling
57
+ * intervals.
58
+ */
59
+ maxOutageContinuationSeconds?: number;
27
60
  now?: () => number;
28
61
  fetchOptions?: Pick<SsrfFetchOptions, 'lookup' | 'trustedFetchFn'>;
29
62
  maxEntries?: number;
63
+ /**
64
+ * Process-local authority history only: operators remembered per hosting
65
+ * provider, i.e. per ICANN registrable domain of a PSL PRIVATE-section name
66
+ * (every `*.vercel.app`, `*.s3.<region>.amazonaws.com` or
67
+ * `*.<project>.platformsh.site` operator shares one budget). ICANN
68
+ * registrable domains each count once. Default 32.
69
+ */
70
+ maxAuthoritativeOperatorsPerPrivateSuffix?: number;
71
+ /**
72
+ * Process-local authority history only: total slots all PRIVATE-section
73
+ * operators may hold together, so registrants of ICANN domains always keep
74
+ * headroom. Default half of `maxEntries`.
75
+ */
76
+ maxPrivateAuthoritativeOperators?: number;
30
77
  maxConcurrentFetches?: number;
31
78
  /** Share authoritative-history across restarts/replicas when legacy fallback is enabled. */
32
79
  authorityHistory?: {
@@ -41,10 +88,14 @@ export declare class TrustEvaluator {
41
88
  private readonly negative;
42
89
  private readonly pending;
43
90
  private readonly urlRequests;
91
+ /** Keyed by (operator, host): one operator's authoritative_location hops never spend another's budget. */
44
92
  private readonly hostRates;
45
93
  private readonly authoritativeOperators;
46
- private authorityHistoryOverflowed;
94
+ /** Remembered authoritative operators per budget group (see authorityGroup). */
95
+ private readonly authorityGroups;
96
+ private privateAuthorityOperators;
47
97
  readonly pollingIntervalSeconds: number;
98
+ readonly maxOutageContinuationSeconds: number;
48
99
  constructor(options?: TrustEvaluatorOptions);
49
100
  get(domainOrOrigin: string, force?: boolean): Promise<TrustFetchResult>;
50
101
  match(origin: string, role: string, countries?: readonly string[]): Promise<{
@@ -54,6 +105,16 @@ export declare class TrustEvaluator {
54
105
  freshUntil: number;
55
106
  }>;
56
107
  invalidate(domain: string): void;
108
+ /**
109
+ * Record that `operator` served a trust record. With durable history the
110
+ * in-memory set is only a cache and may evict; without it, nothing is
111
+ * evicted and an operator over its group budget or the total is refused.
112
+ */
113
+ private rememberAuthority;
114
+ /**
115
+ * Process-local view only. With durable `authorityHistory` this set is a
116
+ * cache and may have evicted an operator that durable history still records.
117
+ */
57
118
  hasAuthoritativeRecord(domain: string): boolean;
58
119
  private now;
59
120
  private request;
@@ -6,6 +6,32 @@ export declare class IdentityAuthorizationError extends Error {
6
6
  readonly details: AgentGrantDeniedDetails | undefined;
7
7
  constructor(reason?: 'authorization_failed' | 'grant_absent');
8
8
  }
9
+ /**
10
+ * The trust record could not be read (transport error, outage, capacity,
11
+ * invalid content). A fetch failure is never absence or delisting: spend
12
+ * fails closed with a retryable SERVICE_UNAVAILABLE, other calls continue
13
+ * under an existing binding.
14
+ */
15
+ export declare class TrustRecordUnavailableError extends IdentityAuthorizationError {
16
+ readonly transient: true;
17
+ /**
18
+ * Set by `match()`: the last record read for this operator listed the origin
19
+ * with the role and is still within the seller's outage bound
20
+ * (`maxOutageContinuationSeconds` past its freshness). Only then may non-spend
21
+ * calls continue under a binding.
22
+ */
23
+ lastKnownListed: boolean;
24
+ constructor();
25
+ }
26
+ /**
27
+ * The operator's last record read does not list the origin with the required
28
+ * role (`unlisted`; operators retire agents by publishing an empty `agents[]`),
29
+ * or the operator has never published one (`absent`).
30
+ */
31
+ export declare class TrustMembershipError extends IdentityAuthorizationError {
32
+ readonly membership: 'unlisted' | 'absent';
33
+ constructor(membership?: 'unlisted' | 'absent');
34
+ }
9
35
  /** Schema plus semantic checks; publication never includes identity keys. */
10
36
  export declare function validateTrustRecord(value: unknown): asserts value is TrustRecord;
11
37
  export declare function createTrustRecord(record: TrustRecord): TrustRecord;
@@ -24,9 +50,30 @@ export type TrustFetchResult = {
24
50
  export interface TrustEvaluatorOptions {
25
51
  /** Matches configured revocation polling: one minute through thirty minutes. */
26
52
  pollingIntervalSeconds?: number;
53
+ /**
54
+ * Seller policy: how long past the last listing record's freshness a bound
55
+ * origin's non-spend calls may continue while its operator's record cannot
56
+ * be read. Spend never continues on an outage. Default four polling
57
+ * intervals.
58
+ */
59
+ maxOutageContinuationSeconds?: number;
27
60
  now?: () => number;
28
61
  fetchOptions?: Pick<SsrfFetchOptions, 'lookup' | 'trustedFetchFn'>;
29
62
  maxEntries?: number;
63
+ /**
64
+ * Process-local authority history only: operators remembered per hosting
65
+ * provider, i.e. per ICANN registrable domain of a PSL PRIVATE-section name
66
+ * (every `*.vercel.app`, `*.s3.<region>.amazonaws.com` or
67
+ * `*.<project>.platformsh.site` operator shares one budget). ICANN
68
+ * registrable domains each count once. Default 32.
69
+ */
70
+ maxAuthoritativeOperatorsPerPrivateSuffix?: number;
71
+ /**
72
+ * Process-local authority history only: total slots all PRIVATE-section
73
+ * operators may hold together, so registrants of ICANN domains always keep
74
+ * headroom. Default half of `maxEntries`.
75
+ */
76
+ maxPrivateAuthoritativeOperators?: number;
30
77
  maxConcurrentFetches?: number;
31
78
  /** Share authoritative-history across restarts/replicas when legacy fallback is enabled. */
32
79
  authorityHistory?: {
@@ -41,10 +88,14 @@ export declare class TrustEvaluator {
41
88
  private readonly negative;
42
89
  private readonly pending;
43
90
  private readonly urlRequests;
91
+ /** Keyed by (operator, host): one operator's authoritative_location hops never spend another's budget. */
44
92
  private readonly hostRates;
45
93
  private readonly authoritativeOperators;
46
- private authorityHistoryOverflowed;
94
+ /** Remembered authoritative operators per budget group (see authorityGroup). */
95
+ private readonly authorityGroups;
96
+ private privateAuthorityOperators;
47
97
  readonly pollingIntervalSeconds: number;
98
+ readonly maxOutageContinuationSeconds: number;
48
99
  constructor(options?: TrustEvaluatorOptions);
49
100
  get(domainOrOrigin: string, force?: boolean): Promise<TrustFetchResult>;
50
101
  match(origin: string, role: string, countries?: readonly string[]): Promise<{
@@ -54,6 +105,16 @@ export declare class TrustEvaluator {
54
105
  freshUntil: number;
55
106
  }>;
56
107
  invalidate(domain: string): void;
108
+ /**
109
+ * Record that `operator` served a trust record. With durable history the
110
+ * in-memory set is only a cache and may evict; without it, nothing is
111
+ * evicted and an operator over its group budget or the total is refused.
112
+ */
113
+ private rememberAuthority;
114
+ /**
115
+ * Process-local view only. With durable `authorityHistory` this set is a
116
+ * cache and may have evicted an operator that durable history still records.
117
+ */
57
118
  hasAuthoritativeRecord(domain: string): boolean;
58
119
  private now;
59
120
  private request;