@adcp/sdk 15.9.1 → 16.0.0-beta.2

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 (321) hide show
  1. package/bin/adcp-identity.js +74 -0
  2. package/bin/adcp.js +2 -0
  3. package/dist/lib/adapters/keyed-account-backend.d.mts +37 -0
  4. package/dist/lib/adapters/keyed-account-backend.d.ts +37 -0
  5. package/dist/lib/adapters/keyed-account-backend.js +121 -0
  6. package/dist/lib/adapters/keyed-account-backend.mjs +94 -0
  7. package/dist/lib/adapters/keyed-account-store.d.mts +28 -0
  8. package/dist/lib/adapters/keyed-account-store.d.ts +28 -0
  9. package/dist/lib/adapters/keyed-account-store.js +227 -0
  10. package/dist/lib/adapters/keyed-account-store.mjs +203 -0
  11. package/dist/lib/core/SingleAgentClient.d.mts +25 -2
  12. package/dist/lib/core/SingleAgentClient.d.ts +25 -2
  13. package/dist/lib/core/SingleAgentClient.js +280 -62
  14. package/dist/lib/core/SingleAgentClient.mjs +282 -57
  15. package/dist/lib/core/TaskExecutor.d.mts +6 -0
  16. package/dist/lib/core/TaskExecutor.d.ts +6 -0
  17. package/dist/lib/core/TaskExecutor.js +66 -5
  18. package/dist/lib/core/TaskExecutor.mjs +71 -5
  19. package/dist/lib/core/postgres-webhook-registration-store.js +32 -5
  20. package/dist/lib/core/postgres-webhook-registration-store.mjs +32 -5
  21. package/dist/lib/core/redis-webhook-registration-store.js +23 -1
  22. package/dist/lib/core/redis-webhook-registration-store.mjs +23 -1
  23. package/dist/lib/core/webhook-registration.d.mts +7 -1
  24. package/dist/lib/core/webhook-registration.d.ts +7 -1
  25. package/dist/lib/core/webhook-registration.js +24 -2
  26. package/dist/lib/core/webhook-registration.mjs +23 -2
  27. package/dist/lib/identity-3.3/generated-compat.d.mts +34 -0
  28. package/dist/lib/identity-3.3/generated-compat.d.ts +34 -0
  29. package/dist/lib/identity-3.3/generated-compat.js +16 -0
  30. package/dist/lib/identity-3.3/generated-compat.mjs +0 -0
  31. package/dist/lib/identity-3.3/index.d.mts +10 -0
  32. package/dist/lib/identity-3.3/index.d.ts +10 -0
  33. package/dist/lib/identity-3.3/index.js +79 -0
  34. package/dist/lib/identity-3.3/index.mjs +50 -0
  35. package/dist/lib/identity-3.3/lifecycle.d.mts +125 -0
  36. package/dist/lib/identity-3.3/lifecycle.d.ts +125 -0
  37. package/dist/lib/identity-3.3/lifecycle.js +294 -0
  38. package/dist/lib/identity-3.3/lifecycle.mjs +272 -0
  39. package/dist/lib/identity-3.3/revocation.d.mts +86 -0
  40. package/dist/lib/identity-3.3/revocation.d.ts +86 -0
  41. package/dist/lib/identity-3.3/revocation.js +308 -0
  42. package/dist/lib/identity-3.3/revocation.mjs +286 -0
  43. package/dist/lib/identity-3.3/schemas.draft.d.mts +2472 -0
  44. package/dist/lib/identity-3.3/schemas.draft.d.ts +2472 -0
  45. package/dist/lib/identity-3.3/schemas.draft.js +1448 -0
  46. package/dist/lib/identity-3.3/schemas.draft.mjs +1428 -0
  47. package/dist/lib/identity-3.3/server.d.mts +46 -0
  48. package/dist/lib/identity-3.3/server.d.ts +46 -0
  49. package/dist/lib/identity-3.3/server.js +279 -0
  50. package/dist/lib/identity-3.3/server.mjs +260 -0
  51. package/dist/lib/identity-3.3/store.d.mts +24 -0
  52. package/dist/lib/identity-3.3/store.d.ts +24 -0
  53. package/dist/lib/identity-3.3/store.js +191 -0
  54. package/dist/lib/identity-3.3/store.mjs +169 -0
  55. package/dist/lib/identity-3.3/trust.d.mts +155 -0
  56. package/dist/lib/identity-3.3/trust.d.ts +155 -0
  57. package/dist/lib/identity-3.3/trust.js +383 -0
  58. package/dist/lib/identity-3.3/trust.mjs +342 -0
  59. package/dist/lib/identity-3.3/types.d.mts +155 -0
  60. package/dist/lib/identity-3.3/types.d.ts +155 -0
  61. package/dist/lib/identity-3.3/types.js +16 -0
  62. package/dist/lib/identity-3.3/types.mjs +0 -0
  63. package/dist/lib/identity-3.3/validation.d.mts +2 -0
  64. package/dist/lib/identity-3.3/validation.d.ts +2 -0
  65. package/dist/lib/identity-3.3/validation.js +125 -0
  66. package/dist/lib/identity-3.3/validation.mjs +91 -0
  67. package/dist/lib/index.d.mts +1 -1
  68. package/dist/lib/index.d.ts +1 -1
  69. package/dist/lib/index.js +2 -0
  70. package/dist/lib/index.mjs +2 -0
  71. package/dist/lib/protocols/index.d.mts +1 -1
  72. package/dist/lib/protocols/index.d.ts +1 -1
  73. package/dist/lib/protocols/index.js +2 -2
  74. package/dist/lib/protocols/index.mjs +2 -2
  75. package/dist/lib/reporting/azure/index.d.mts +5 -0
  76. package/dist/lib/reporting/azure/index.d.ts +5 -0
  77. package/dist/lib/reporting/azure/index.js +26 -7
  78. package/dist/lib/reporting/azure/index.mjs +26 -7
  79. package/dist/lib/reporting/bigquery/index.d.mts +39 -5
  80. package/dist/lib/reporting/bigquery/index.d.ts +39 -5
  81. package/dist/lib/reporting/bigquery/index.js +26 -20
  82. package/dist/lib/reporting/bigquery/index.mjs +26 -20
  83. package/dist/lib/reporting/gcs/adapter.d.mts +8 -1
  84. package/dist/lib/reporting/gcs/adapter.d.ts +8 -1
  85. package/dist/lib/reporting/gcs/errors.d.mts +6 -0
  86. package/dist/lib/reporting/gcs/errors.d.ts +6 -0
  87. package/dist/lib/reporting/gcs/fence.d.mts +5 -0
  88. package/dist/lib/reporting/gcs/fence.d.ts +5 -0
  89. package/dist/lib/reporting/gcs/index.d.mts +9 -0
  90. package/dist/lib/reporting/gcs/index.d.ts +9 -0
  91. package/dist/lib/reporting/gcs/reader.d.mts +27 -3
  92. package/dist/lib/reporting/gcs/reader.d.ts +27 -3
  93. package/dist/lib/reporting/gcs/row-provider.d.mts +7 -0
  94. package/dist/lib/reporting/gcs/row-provider.d.ts +7 -0
  95. package/dist/lib/reporting/gcs/row-provider.js +34 -14
  96. package/dist/lib/reporting/gcs/row-provider.mjs +34 -14
  97. package/dist/lib/reporting/ledger/change-feed.d.mts +22 -1
  98. package/dist/lib/reporting/ledger/change-feed.d.ts +22 -1
  99. package/dist/lib/reporting/ledger/index.d.mts +11 -0
  100. package/dist/lib/reporting/ledger/index.d.ts +11 -0
  101. package/dist/lib/reporting/ledger/managed-postgres.d.mts +8 -0
  102. package/dist/lib/reporting/ledger/managed-postgres.d.ts +8 -0
  103. package/dist/lib/reporting/ledger/managed-router.d.mts +27 -2
  104. package/dist/lib/reporting/ledger/managed-router.d.ts +27 -2
  105. package/dist/lib/reporting/ledger/managed.d.mts +86 -6
  106. package/dist/lib/reporting/ledger/managed.d.ts +86 -6
  107. package/dist/lib/reporting/ledger/notification-activity.d.mts +65 -3
  108. package/dist/lib/reporting/ledger/notification-activity.d.ts +65 -3
  109. package/dist/lib/reporting/ledger/object-writes.d.mts +64 -5
  110. package/dist/lib/reporting/ledger/object-writes.d.ts +64 -5
  111. package/dist/lib/reporting/ledger/postgres.d.mts +43 -9
  112. package/dist/lib/reporting/ledger/postgres.d.ts +43 -9
  113. package/dist/lib/reporting/ledger/postgres.js +43 -27
  114. package/dist/lib/reporting/ledger/postgres.mjs +43 -27
  115. package/dist/lib/reporting/ledger/row-encoding.d.mts +92 -6
  116. package/dist/lib/reporting/ledger/row-encoding.d.ts +92 -6
  117. package/dist/lib/reporting/ledger/row-encoding.js +8 -4
  118. package/dist/lib/reporting/ledger/row-encoding.mjs +6 -3
  119. package/dist/lib/reporting/ledger/row-storage-errors.d.mts +11 -1
  120. package/dist/lib/reporting/ledger/row-storage-errors.d.ts +11 -1
  121. package/dist/lib/reporting/ledger/row-storage-migration.d.mts +19 -1
  122. package/dist/lib/reporting/ledger/row-storage-migration.d.ts +19 -1
  123. package/dist/lib/reporting/ledger/row-storage-migration.js +133 -18
  124. package/dist/lib/reporting/ledger/row-storage-migration.mjs +133 -18
  125. package/dist/lib/reporting/ledger/row-storage-object.d.mts +103 -12
  126. package/dist/lib/reporting/ledger/row-storage-object.d.ts +103 -12
  127. package/dist/lib/reporting/ledger/row-storage-object.js +106 -31
  128. package/dist/lib/reporting/ledger/row-storage-object.mjs +104 -31
  129. package/dist/lib/reporting/ledger/row-storage.d.mts +87 -20
  130. package/dist/lib/reporting/ledger/row-storage.d.ts +87 -20
  131. package/dist/lib/reporting/ledger/row-storage.js +126 -66
  132. package/dist/lib/reporting/ledger/row-storage.mjs +129 -67
  133. package/dist/lib/reporting/ledger/schedule.d.mts +13 -0
  134. package/dist/lib/reporting/ledger/schedule.d.ts +13 -0
  135. package/dist/lib/reporting/ledger/schedule.js +24 -0
  136. package/dist/lib/reporting/ledger/schedule.mjs +23 -0
  137. package/dist/lib/reporting/ledger/types.d.mts +23 -1
  138. package/dist/lib/reporting/ledger/types.d.ts +23 -1
  139. package/dist/lib/reporting/s3/index.d.mts +5 -0
  140. package/dist/lib/reporting/s3/index.d.ts +5 -0
  141. package/dist/lib/reporting/s3/index.js +37 -14
  142. package/dist/lib/reporting/s3/index.mjs +37 -14
  143. package/dist/lib/reporting/service/index.d.mts +10 -0
  144. package/dist/lib/reporting/service/index.d.ts +10 -0
  145. package/dist/lib/reporting/service/maintenance.d.mts +28 -2
  146. package/dist/lib/reporting/service/maintenance.d.ts +28 -2
  147. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  148. package/dist/lib/server/account-sync-contract.d.mts +14 -0
  149. package/dist/lib/server/account-sync-contract.d.ts +14 -0
  150. package/dist/lib/server/account-sync-contract.js +225 -0
  151. package/dist/lib/server/account-sync-contract.mjs +197 -0
  152. package/dist/lib/server/adcp-server.js +5 -0
  153. package/dist/lib/server/adcp-server.mjs +10 -0
  154. package/dist/lib/server/auth-signature.d.mts +15 -0
  155. package/dist/lib/server/auth-signature.d.ts +15 -0
  156. package/dist/lib/server/auth-signature.js +72 -2
  157. package/dist/lib/server/auth-signature.mjs +81 -2
  158. package/dist/lib/server/auth.d.mts +6 -0
  159. package/dist/lib/server/auth.d.ts +6 -0
  160. package/dist/lib/server/auth.js +6 -0
  161. package/dist/lib/server/auth.mjs +6 -0
  162. package/dist/lib/server/create-adcp-server.d.mts +19 -5
  163. package/dist/lib/server/create-adcp-server.d.ts +19 -5
  164. package/dist/lib/server/create-adcp-server.js +259 -19
  165. package/dist/lib/server/create-adcp-server.mjs +266 -10
  166. package/dist/lib/server/decisioning/account.d.mts +24 -1
  167. package/dist/lib/server/decisioning/account.d.ts +24 -1
  168. package/dist/lib/server/decisioning/index.d.mts +1 -1
  169. package/dist/lib/server/decisioning/index.d.ts +1 -1
  170. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +0 -50
  171. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +0 -50
  172. package/dist/lib/server/decisioning/runtime/from-platform.js +61 -11
  173. package/dist/lib/server/decisioning/runtime/from-platform.mjs +65 -12
  174. package/dist/lib/server/index.d.mts +2 -0
  175. package/dist/lib/server/index.d.ts +2 -0
  176. package/dist/lib/server/index.js +12 -0
  177. package/dist/lib/server/index.mjs +12 -0
  178. package/dist/lib/server/notification-subscriptions/runtime.js +9 -1
  179. package/dist/lib/server/notification-subscriptions/runtime.mjs +9 -1
  180. package/dist/lib/server/notification-subscriptions/types.d.mts +5 -0
  181. package/dist/lib/server/notification-subscriptions/types.d.ts +5 -0
  182. package/dist/lib/server/principal/types.d.mts +1 -1
  183. package/dist/lib/server/principal/types.d.ts +1 -1
  184. package/dist/lib/server/serve.js +5 -0
  185. package/dist/lib/server/serve.mjs +5 -0
  186. package/dist/lib/server/webhook-delivery/recovery.d.mts +1 -0
  187. package/dist/lib/server/webhook-delivery/recovery.d.ts +1 -0
  188. package/dist/lib/server/webhook-delivery/recovery.js +4 -0
  189. package/dist/lib/server/webhook-delivery/recovery.mjs +4 -0
  190. package/dist/lib/server/webhook-emitter.d.mts +10 -0
  191. package/dist/lib/server/webhook-emitter.d.ts +10 -0
  192. package/dist/lib/server/webhook-emitter.js +22 -0
  193. package/dist/lib/server/webhook-emitter.mjs +22 -0
  194. package/dist/lib/signing/agent-context.d.mts +0 -5
  195. package/dist/lib/signing/agent-context.d.ts +0 -5
  196. package/dist/lib/signing/agent-context.js +9 -1
  197. package/dist/lib/signing/agent-context.mjs +9 -1
  198. package/dist/lib/signing/agent-fetch.js +27 -2
  199. package/dist/lib/signing/agent-fetch.mjs +32 -2
  200. package/dist/lib/signing/agent-resolver/canonicalize.d.mts +10 -15
  201. package/dist/lib/signing/agent-resolver/canonicalize.d.ts +10 -15
  202. package/dist/lib/signing/agent-resolver/canonicalize.js +17 -5
  203. package/dist/lib/signing/agent-resolver/canonicalize.mjs +16 -5
  204. package/dist/lib/signing/agent-resolver/index.d.mts +1 -0
  205. package/dist/lib/signing/agent-resolver/index.d.ts +1 -0
  206. package/dist/lib/signing/agent-resolver/index.js +5 -0
  207. package/dist/lib/signing/agent-resolver/index.mjs +3 -0
  208. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.mts +3 -2
  209. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.ts +3 -2
  210. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.js +30 -3
  211. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.mjs +30 -3
  212. package/dist/lib/signing/agent-resolver/strict-json.d.mts +2 -2
  213. package/dist/lib/signing/agent-resolver/strict-json.d.ts +2 -2
  214. package/dist/lib/signing/agent-resolver/strict-json.js +5 -3
  215. package/dist/lib/signing/agent-resolver/strict-json.mjs +5 -3
  216. package/dist/lib/signing/brand-jwks.d.mts +2 -2
  217. package/dist/lib/signing/brand-jwks.d.ts +2 -2
  218. package/dist/lib/signing/brand-jwks.js +4 -4
  219. package/dist/lib/signing/brand-jwks.mjs +4 -4
  220. package/dist/lib/signing/client.d.mts +1 -0
  221. package/dist/lib/signing/client.d.ts +1 -0
  222. package/dist/lib/signing/client.js +5 -0
  223. package/dist/lib/signing/client.mjs +3 -0
  224. package/dist/lib/signing/crypto.js +8 -0
  225. package/dist/lib/signing/crypto.mjs +9 -1
  226. package/dist/lib/signing/fetch-async.js +1 -1
  227. package/dist/lib/signing/fetch-async.mjs +1 -1
  228. package/dist/lib/signing/fetch.js +1 -1
  229. package/dist/lib/signing/fetch.mjs +1 -1
  230. package/dist/lib/signing/jwks-https.d.mts +1 -1
  231. package/dist/lib/signing/jwks-https.d.ts +1 -1
  232. package/dist/lib/signing/jwks-https.js +1 -1
  233. package/dist/lib/signing/jwks-https.mjs +1 -1
  234. package/dist/lib/signing/jwks.d.mts +11 -3
  235. package/dist/lib/signing/jwks.d.ts +11 -3
  236. package/dist/lib/signing/jwks.js +1 -1
  237. package/dist/lib/signing/jwks.mjs +1 -1
  238. package/dist/lib/signing/middleware.js +9 -0
  239. package/dist/lib/signing/middleware.mjs +14 -0
  240. package/dist/lib/signing/parser.d.mts +9 -6
  241. package/dist/lib/signing/parser.d.ts +9 -6
  242. package/dist/lib/signing/parser.js +82 -64
  243. package/dist/lib/signing/parser.mjs +83 -65
  244. package/dist/lib/signing/revocation.d.mts +4 -1
  245. package/dist/lib/signing/revocation.d.ts +4 -1
  246. package/dist/lib/signing/revocation.js +36 -3
  247. package/dist/lib/signing/revocation.mjs +34 -2
  248. package/dist/lib/signing/server.d.mts +1 -1
  249. package/dist/lib/signing/server.d.ts +1 -1
  250. package/dist/lib/signing/server.js +4 -0
  251. package/dist/lib/signing/server.mjs +4 -0
  252. package/dist/lib/signing/types.d.mts +3 -0
  253. package/dist/lib/signing/types.d.ts +3 -0
  254. package/dist/lib/signing/verifier.js +1 -1
  255. package/dist/lib/signing/verifier.mjs +1 -1
  256. package/dist/lib/signing/web-bot-auth.d.mts +191 -0
  257. package/dist/lib/signing/web-bot-auth.d.ts +191 -0
  258. package/dist/lib/signing/web-bot-auth.js +837 -0
  259. package/dist/lib/signing/web-bot-auth.mjs +796 -0
  260. package/dist/lib/signing/webhook-verifier.js +1 -1
  261. package/dist/lib/signing/webhook-verifier.mjs +1 -1
  262. package/dist/lib/testing/client.d.mts +1 -4
  263. package/dist/lib/testing/client.d.ts +1 -4
  264. package/dist/lib/testing/client.js +141 -20
  265. package/dist/lib/testing/client.mjs +137 -19
  266. package/dist/lib/testing/compliance/comply.js +29 -10
  267. package/dist/lib/testing/compliance/comply.mjs +37 -11
  268. package/dist/lib/testing/storyboard/account-sync-contract.d.mts +3 -0
  269. package/dist/lib/testing/storyboard/account-sync-contract.d.ts +3 -0
  270. package/dist/lib/testing/storyboard/account-sync-contract.js +79 -0
  271. package/dist/lib/testing/storyboard/account-sync-contract.mjs +55 -0
  272. package/dist/lib/testing/storyboard/default-invariants.js +2 -0
  273. package/dist/lib/testing/storyboard/default-invariants.mjs +2 -0
  274. package/dist/lib/testing/storyboard/runner.js +23 -8
  275. package/dist/lib/testing/storyboard/runner.mjs +24 -8
  276. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  277. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  278. package/dist/lib/types/adcp.d.mts +4 -0
  279. package/dist/lib/types/adcp.d.ts +4 -0
  280. package/dist/lib/types/schemas.generated.d.ts +6 -6
  281. package/dist/lib/utils/capabilities.d.mts +1 -0
  282. package/dist/lib/utils/capabilities.d.ts +1 -0
  283. package/dist/lib/utils/capabilities.js +5 -0
  284. package/dist/lib/utils/capabilities.mjs +5 -0
  285. package/dist/lib/v2/projection/catalog-snapshot.js +3 -1
  286. package/dist/lib/v2/projection/catalog-snapshot.mjs +3 -1
  287. package/dist/lib/v2/projection/creative-delivery.d.mts +34 -10
  288. package/dist/lib/v2/projection/creative-delivery.d.ts +34 -10
  289. package/dist/lib/v2/projection/creative-delivery.js +26 -10
  290. package/dist/lib/v2/projection/creative-delivery.mjs +26 -10
  291. package/dist/lib/v2/projection/index.d.mts +1 -1
  292. package/dist/lib/v2/projection/index.d.ts +1 -1
  293. package/dist/lib/v2/projection/index.js +2 -0
  294. package/dist/lib/v2/projection/index.mjs +2 -0
  295. package/dist/lib/v2/projection/legacy-routes.d.mts +34 -2
  296. package/dist/lib/v2/projection/legacy-routes.d.ts +34 -2
  297. package/dist/lib/v2/projection/legacy-routes.js +35 -2
  298. package/dist/lib/v2/projection/legacy-routes.mjs +32 -2
  299. package/dist/lib/validation/schema-loader.d.mts +2 -0
  300. package/dist/lib/validation/schema-loader.d.ts +2 -0
  301. package/dist/lib/validation/schema-loader.js +43 -4
  302. package/dist/lib/validation/schema-loader.mjs +39 -3
  303. package/dist/lib/version.d.mts +3 -3
  304. package/dist/lib/version.d.ts +3 -3
  305. package/dist/lib/version.js +3 -3
  306. package/dist/lib/version.mjs +3 -3
  307. package/docs/TYPE-SUMMARY.md +2 -2
  308. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +4 -0
  309. package/docs/guides/REPORTING-LEDGER-CUTOVER.md +1 -1
  310. package/docs/guides/REPORTING-LEDGER.md +99 -29
  311. package/docs/guides/REPORTING-OPERATIONS.md +29 -13
  312. package/docs/guides/REPORTING-STABILITY.md +76 -0
  313. package/docs/guides/account-resolution.md +101 -0
  314. package/docs/llms.txt +3 -2
  315. package/docs/migration-12-to-13.md +15 -0
  316. package/docs/migration-14.x-rc-worksheet.md +4 -4
  317. package/docs/migration-agent-identity-3.3.md +494 -0
  318. package/docs/migration-agent-resolution-3.3.md +5 -0
  319. package/docs/migration-reporting-row-storage-alignment.md +137 -0
  320. package/examples/storyboards/account-sync-contract.yaml +57 -0
  321. package/package.json +17 -1
@@ -0,0 +1,86 @@
1
+ import { type JWK } from 'jose';
2
+ import { type SsrfFetchOptions } from '../net';
3
+ import type { RevocationDetail } from './types';
4
+ export interface OriginRevocationSnapshot {
5
+ issuer: string;
6
+ updated: string;
7
+ next_update: string;
8
+ revoked_kids: string[];
9
+ revoked_jtis?: string[];
10
+ revocation_details?: Record<string, RevocationDetail>;
11
+ }
12
+ export interface MonotonicOriginRevocationStore {
13
+ /** Merge atomically and persist forever. Never replace with a new snapshot. */
14
+ merge(origin: string, snapshot: OriginRevocationSnapshot): Promise<void>;
15
+ get(origin: string, keyid: string): Promise<RevocationDetail | undefined>;
16
+ }
17
+ /**
18
+ * Process-local revocation history for development and tests. Public
19
+ * deployments need durable history (`createIdentity33StateStores`) so a
20
+ * restart never forgets a revocation.
21
+ *
22
+ * Capacity is bounded per origin, per operator (registrable domain) and in
23
+ * total. The operator budget stops one registrable domain's wildcard
24
+ * subdomains from filling the store alone; it does not reserve capacity for
25
+ * anyone else, so several operators together can still exhaust the total.
26
+ * Facts are never evicted to regain capacity; a refused merge fails closed.
27
+ */
28
+ export declare class InMemoryOriginRevocationStore implements MonotonicOriginRevocationStore {
29
+ readonly durability: "process-local";
30
+ private readonly revoked;
31
+ private readonly originKeys;
32
+ private readonly operatorKeys;
33
+ private readonly limits;
34
+ constructor(limits?: {
35
+ perOrigin?: number;
36
+ perOperator?: number;
37
+ total?: number;
38
+ });
39
+ merge(origin: string, snapshot: OriginRevocationSnapshot): Promise<void>;
40
+ get(origin: string, keyid: string): Promise<RevocationDetail | undefined>;
41
+ }
42
+ /** See {@link OriginRevocationResolver.status}. */
43
+ export type OriginRevocationStatus = 'revoked' | 'current' | 'absent' | 'unknown';
44
+ export declare class OriginRevocationResolver {
45
+ private readonly options;
46
+ private readonly freshness;
47
+ private readonly updated;
48
+ private readonly graceUntil;
49
+ private readonly pending;
50
+ private readonly failures;
51
+ private readonly persistenceFailures;
52
+ private readonly absentUntil;
53
+ constructor(options: {
54
+ directory: import('../signing/web-bot-auth').SignatureDirectoryResolver;
55
+ store: MonotonicOriginRevocationStore;
56
+ pollingIntervalSeconds?: number;
57
+ now?: () => number;
58
+ fetchOptions?: Pick<SsrfFetchOptions, 'lookup' | 'trustedFetchFn'>;
59
+ maxOrigins?: number;
60
+ });
61
+ /**
62
+ * Compatibility wrapper over {@link status}: `true` when revoked, `false`
63
+ * when the list is current, and `revocation_unavailable` when the identity
64
+ * publishes no list (`absent`) or its status is not known (`unknown`).
65
+ */
66
+ isRevoked(originUrl: string, keyid: string): Promise<boolean>;
67
+ /**
68
+ * Revocation status of `keyid` at `origin`:
69
+ * - `revoked`: a stored (permanent) revocation covers the key.
70
+ * - `current`: a signed list is current, or within `next_update` + grace.
71
+ * - `absent`: the origin serves no list (404/410). The identity is still
72
+ * established but cannot be bound for spend.
73
+ * - `unknown`: no list could be verified and grace has passed (or there was
74
+ * never a list). The identity is not established.
75
+ * Throws {@link WebBotAuthUnavailableError} (`revocation_persistence_failed`)
76
+ * when the history store fails: an infrastructure outage, never a
77
+ * revocation outcome.
78
+ */
79
+ status(originUrl: string, keyid: string): Promise<OriginRevocationStatus>;
80
+ private currentStatus;
81
+ private readStored;
82
+ private refresh;
83
+ private now;
84
+ }
85
+ /** Publish a signed list even when there are no revoked keys; refresh before next_update. */
86
+ export declare function createSignedOriginRevocationList(snapshot: OriginRevocationSnapshot, privateKey: JWK): Promise<string>;
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var revocation_exports = {};
20
+ __export(revocation_exports, {
21
+ InMemoryOriginRevocationStore: () => InMemoryOriginRevocationStore,
22
+ OriginRevocationResolver: () => OriginRevocationResolver,
23
+ createSignedOriginRevocationList: () => createSignedOriginRevocationList,
24
+ mergeRevocationDetail: () => import_revocation.mergeRevocationDetails
25
+ });
26
+ module.exports = __toCommonJS(revocation_exports);
27
+ var import_etld = require('../signing/agent-resolver/etld.js');
28
+ var import_jose = require("jose");
29
+ var import_net = require('../net/index.js');
30
+ var import_canonicalize = require('../signing/agent-resolver/canonicalize.js');
31
+ var import_strict_json = require('../signing/agent-resolver/strict-json.js');
32
+ var import_web_bot_auth = require('../signing/web-bot-auth.js');
33
+ var import_revocation = require('../signing/revocation.js');
34
+ var import_revocation2 = require('../signing/revocation.js');
35
+ const REASONS = [
36
+ "removeFromCRL",
37
+ "unspecified",
38
+ "superseded",
39
+ "cessationOfOperation",
40
+ "affiliationChanged",
41
+ "certificateHold",
42
+ "privilegeWithdrawn",
43
+ "aACompromise",
44
+ "cACompromise",
45
+ "keyCompromise"
46
+ ];
47
+ class InMemoryOriginRevocationStore {
48
+ durability = "process-local";
49
+ revoked = /* @__PURE__ */ new Map();
50
+ originKeys = /* @__PURE__ */ new Map();
51
+ operatorKeys = /* @__PURE__ */ new Map();
52
+ limits;
53
+ constructor(limits = {}) {
54
+ this.limits = {
55
+ perOrigin: limits.perOrigin ?? 16384,
56
+ perOperator: limits.perOperator ?? 16384,
57
+ total: limits.total ?? 1e5
58
+ };
59
+ if (Object.values(this.limits).some((value) => !Number.isSafeInteger(value) || value < 1))
60
+ throw new TypeError("Revocation limits must be positive safe integers");
61
+ }
62
+ async merge(origin, snapshot) {
63
+ origin = (0, import_canonicalize.canonicalAgentOrigin)(origin);
64
+ const operator = operatorOf(origin);
65
+ const additions = new Set(snapshot.revoked_kids.filter((kid) => !this.revoked.has(JSON.stringify([origin, kid]))));
66
+ const originCount = this.originKeys.get(origin) ?? 0, operatorCount = this.operatorKeys.get(operator) ?? 0;
67
+ if (originCount + additions.size > this.limits.perOrigin || operatorCount + additions.size > this.limits.perOperator || this.revoked.size + additions.size > this.limits.total)
68
+ throw new import_web_bot_auth.WebBotAuthError(403, "revocation_storage_limit");
69
+ for (const kid of snapshot.revoked_kids) {
70
+ const key = JSON.stringify([origin, kid]), prior = this.revoked.get(key), detail = snapshot.revocation_details?.[kid] ?? {};
71
+ this.revoked.set(key, (0, import_revocation2.mergeRevocationDetails)(prior, detail));
72
+ }
73
+ if (additions.size) {
74
+ this.originKeys.set(origin, originCount + additions.size);
75
+ this.operatorKeys.set(operator, operatorCount + additions.size);
76
+ }
77
+ }
78
+ async get(origin, keyid) {
79
+ const entry = this.revoked.get(JSON.stringify([(0, import_canonicalize.canonicalAgentOrigin)(origin), keyid]));
80
+ return entry && { ...entry };
81
+ }
82
+ }
83
+ function operatorOf(origin) {
84
+ try {
85
+ return (0, import_etld.eTldPlusOne)(origin);
86
+ } catch {
87
+ return new URL(origin).hostname;
88
+ }
89
+ }
90
+ const MAX_POLLING_SECONDS = 1800;
91
+ class RevocationListAbsentError extends Error {
92
+ }
93
+ class OriginRevocationResolver {
94
+ constructor(options) {
95
+ this.options = options;
96
+ if (!(options.directory instanceof import_web_bot_auth.SignatureDirectoryResolver))
97
+ throw new TypeError("Origin revocation requires a verified SignatureDirectoryResolver");
98
+ if (!Number.isFinite(options.pollingIntervalSeconds ?? 300) || (options.pollingIntervalSeconds ?? 300) < 60 || (options.pollingIntervalSeconds ?? 300) > 1800)
99
+ throw new TypeError("Invalid revocation polling interval");
100
+ }
101
+ options;
102
+ freshness = /* @__PURE__ */ new Map();
103
+ updated = /* @__PURE__ */ new Map();
104
+ graceUntil = /* @__PURE__ */ new Map();
105
+ pending = /* @__PURE__ */ new Map();
106
+ failures = /* @__PURE__ */ new Map();
107
+ persistenceFailures = /* @__PURE__ */ new Set();
108
+ absentUntil = /* @__PURE__ */ new Map();
109
+ /**
110
+ * Compatibility wrapper over {@link status}: `true` when revoked, `false`
111
+ * when the list is current, and `revocation_unavailable` when the identity
112
+ * publishes no list (`absent`) or its status is not known (`unknown`).
113
+ */
114
+ async isRevoked(originUrl, keyid) {
115
+ const state = await this.status(originUrl, keyid);
116
+ if (state === "revoked") return true;
117
+ if (state === "current") return false;
118
+ throw new import_web_bot_auth.WebBotAuthError(403, state === "absent" ? "revocation_absent" : "revocation_unavailable");
119
+ }
120
+ /**
121
+ * Revocation status of `keyid` at `origin`:
122
+ * - `revoked`: a stored (permanent) revocation covers the key.
123
+ * - `current`: a signed list is current, or within `next_update` + grace.
124
+ * - `absent`: the origin serves no list (404/410). The identity is still
125
+ * established but cannot be bound for spend.
126
+ * - `unknown`: no list could be verified and grace has passed (or there was
127
+ * never a list). The identity is not established.
128
+ * Throws {@link WebBotAuthUnavailableError} (`revocation_persistence_failed`)
129
+ * when the history store fails: an infrastructure outage, never a
130
+ * revocation outcome.
131
+ */
132
+ async status(originUrl, keyid) {
133
+ try {
134
+ return await this.currentStatus(originUrl, keyid);
135
+ } catch (error) {
136
+ if (error instanceof import_web_bot_auth.WebBotAuthError && error.reason === "revocation_persistence_failed")
137
+ throw new import_web_bot_auth.WebBotAuthUnavailableError("revocation_persistence_failed", error);
138
+ throw error;
139
+ }
140
+ }
141
+ async currentStatus(originUrl, keyid) {
142
+ const origin = (0, import_canonicalize.canonicalAgentOrigin)(originUrl), now = this.now();
143
+ if (await this.readStored(origin, keyid)) return "revoked";
144
+ const settled = async () => {
145
+ if (await this.readStored(origin, keyid)) return "revoked";
146
+ if ((this.absentUntil.get(origin) ?? 0) > now) return "absent";
147
+ return (this.freshness.get(origin) ?? 0) > now || (this.graceUntil.get(origin) ?? 0) > now ? "current" : "unknown";
148
+ };
149
+ if ((this.freshness.get(origin) ?? 0) <= now) {
150
+ if ((this.failures.get(origin) ?? 0) > now) {
151
+ if (this.persistenceFailures.has(origin)) throw new import_web_bot_auth.WebBotAuthError(403, "revocation_persistence_failed");
152
+ return settled();
153
+ }
154
+ let promise = this.pending.get(origin);
155
+ if (!promise) {
156
+ if (this.pending.size >= 16 || [...this.pending.keys()].filter((pendingOrigin) => operatorOf(pendingOrigin) === operatorOf(origin)).length >= 2) {
157
+ return settled();
158
+ }
159
+ promise = this.refresh(origin).catch((error) => {
160
+ if (this.failures.size >= (this.options.maxOrigins ?? 1e3)) {
161
+ const oldest = this.failures.keys().next().value;
162
+ this.failures.delete(oldest);
163
+ this.persistenceFailures.delete(oldest);
164
+ this.absentUntil.delete(oldest);
165
+ }
166
+ this.failures.set(origin, now + 60);
167
+ if (error instanceof import_web_bot_auth.WebBotAuthError && error.reason === "revocation_persistence_failed") {
168
+ this.persistenceFailures.add(origin);
169
+ this.graceUntil.delete(origin);
170
+ }
171
+ if (error.cause instanceof RevocationListAbsentError) {
172
+ this.absentUntil.set(origin, now + 60);
173
+ this.graceUntil.delete(origin);
174
+ }
175
+ throw error;
176
+ });
177
+ this.pending.set(origin, promise);
178
+ }
179
+ try {
180
+ await promise;
181
+ } catch (error) {
182
+ if (error instanceof import_web_bot_auth.WebBotAuthError && error.reason === "revocation_persistence_failed") throw error;
183
+ } finally {
184
+ if (this.pending.get(origin) === promise) this.pending.delete(origin);
185
+ }
186
+ }
187
+ return settled();
188
+ }
189
+ async readStored(origin, keyid) {
190
+ try {
191
+ return await this.options.store.get(origin, keyid);
192
+ } catch (cause) {
193
+ const error = new import_web_bot_auth.WebBotAuthError(403, "revocation_persistence_failed");
194
+ Object.defineProperty(error, "cause", { value: cause });
195
+ throw error;
196
+ }
197
+ }
198
+ async refresh(origin) {
199
+ try {
200
+ const response = await (0, import_net.ssrfSafeFetch)(origin + "/.well-known/governance-revocations.json", {
201
+ ...this.options.fetchOptions,
202
+ maxBodyBytes: 256 * 1024,
203
+ timeoutMs: 1e4
204
+ });
205
+ if (response.status === 404 || response.status === 410) throw new RevocationListAbsentError();
206
+ if (response.status !== 200) throw new Error("Unavailable revocation list");
207
+ const body = new TextDecoder("utf-8", { fatal: true }).decode(response.body);
208
+ let tokens;
209
+ if (body.trim().startsWith("{")) {
210
+ const envelope = (0, import_strict_json.parseStrictJson)(body, 32);
211
+ if (typeof envelope.jws === "string") tokens = [envelope.jws];
212
+ else {
213
+ if ("header" in envelope) throw new Error("Revocation metadata must be protected");
214
+ const signatures = envelope.signatures ?? (envelope.protected && envelope.signature ? [{ protected: envelope.protected, signature: envelope.signature }] : []);
215
+ if (typeof envelope.payload !== "string" || !Array.isArray(signatures) || !signatures.length || signatures.length > 64)
216
+ throw new Error("Invalid JWS revocation envelope");
217
+ tokens = signatures.map((signature) => {
218
+ if (typeof signature.protected !== "string" || typeof signature.signature !== "string" || signature.header !== void 0)
219
+ throw new Error("Revocation metadata must be protected");
220
+ return `${signature.protected}.${envelope.payload}.${signature.signature}`;
221
+ });
222
+ }
223
+ } else tokens = [body.trim()];
224
+ let verifiedPayload;
225
+ for (const token of tokens) {
226
+ try {
227
+ const header = (0, import_jose.decodeProtectedHeader)(token);
228
+ if (header.typ !== "adcp-gov-revocation+jws" || typeof header.kid !== "string" || typeof header.alg !== "string" || !["EdDSA", "ES256"].includes(header.alg))
229
+ continue;
230
+ await this.options.directory.resolve(header.kid, origin);
231
+ const checked = this.options.directory.getVerifiedDirectory(origin);
232
+ if (!checked || new URL(checked.proof.request.url).origin !== origin || checked.expires <= this.now())
233
+ continue;
234
+ const jwk = checked.keys.find((key) => key.kid === header.kid);
235
+ if (!jwk) continue;
236
+ const result = await (0, import_jose.compactVerify)(token, await (0, import_jose.importJWK)(jwk, header.alg), {
237
+ algorithms: ["EdDSA", "ES256"]
238
+ });
239
+ verifiedPayload = result.payload;
240
+ break;
241
+ } catch {
242
+ }
243
+ }
244
+ if (!verifiedPayload) throw new Error("No valid protected revocation signature");
245
+ const snapshot = (0, import_strict_json.parseStrictJson)(
246
+ new TextDecoder("utf-8", { fatal: true }).decode(verifiedPayload),
247
+ 32
248
+ );
249
+ const updated = Date.parse(snapshot.updated) / 1e3, next = Date.parse(snapshot.next_update) / 1e3, now = this.now();
250
+ if (snapshot.issuer !== origin || !Number.isFinite(updated) || !Number.isFinite(next) || // Tolerate a publisher clock slightly ahead, as for request `created`.
251
+ updated > now + 60 || next <= now || next <= updated || !Array.isArray(snapshot.revoked_kids) || snapshot.revoked_kids.length > 4096 || snapshot.revoked_kids.some((k) => typeof k !== "string" || k.length > 256) || updated < (this.updated.get(origin) ?? 0))
252
+ throw new Error("Invalid revocation snapshot");
253
+ for (const [kid, detail] of Object.entries(snapshot.revocation_details ?? {}))
254
+ if (!snapshot.revoked_kids.includes(kid) || !detail || detail.reason && !REASONS.includes(detail.reason) || detail.invalidity_date && !Number.isFinite(Date.parse(detail.invalidity_date)))
255
+ throw new Error("Invalid revocation detail");
256
+ try {
257
+ await this.options.store.merge(origin, snapshot);
258
+ } catch (cause) {
259
+ const error = new import_web_bot_auth.WebBotAuthError(403, "revocation_persistence_failed");
260
+ Object.defineProperty(error, "cause", { value: cause });
261
+ throw error;
262
+ }
263
+ if (!this.freshness.has(origin) && this.freshness.size >= (this.options.maxOrigins ?? 1e3)) {
264
+ const oldest = this.freshness.keys().next().value;
265
+ this.freshness.delete(oldest);
266
+ this.updated.delete(oldest);
267
+ this.graceUntil.delete(oldest);
268
+ }
269
+ this.graceUntil.set(
270
+ origin,
271
+ Math.min(next, now + MAX_POLLING_SECONDS) + 4 * (this.options.pollingIntervalSeconds ?? 300)
272
+ );
273
+ this.updated.set(origin, updated);
274
+ this.freshness.set(origin, Math.min(next, now + (this.options.pollingIntervalSeconds ?? 300)));
275
+ this.failures.delete(origin);
276
+ this.persistenceFailures.delete(origin);
277
+ this.absentUntil.delete(origin);
278
+ } catch (cause) {
279
+ if (cause instanceof import_web_bot_auth.WebBotAuthError && cause.reason === "revocation_persistence_failed") throw cause;
280
+ const error = new import_web_bot_auth.WebBotAuthError(403, "revocation_unavailable");
281
+ Object.defineProperty(error, "cause", { value: cause });
282
+ throw error;
283
+ }
284
+ }
285
+ now() {
286
+ const now = (this.options.now ?? (() => Date.now() / 1e3))();
287
+ if (!Number.isFinite(now)) throw new import_web_bot_auth.WebBotAuthError(403, "revocation_unavailable");
288
+ return now;
289
+ }
290
+ }
291
+ async function createSignedOriginRevocationList(snapshot, privateKey) {
292
+ const issuer = (0, import_canonicalize.canonicalAgentOrigin)(snapshot.issuer), now = Date.now() / 1e3;
293
+ if (issuer !== snapshot.issuer || !Number.isFinite(Date.parse(snapshot.updated)) || !Number.isFinite(Date.parse(snapshot.next_update)) || Date.parse(snapshot.updated) / 1e3 > now || Date.parse(snapshot.next_update) / 1e3 <= now || Date.parse(snapshot.next_update) / 1e3 > now + 1800 || !Array.isArray(snapshot.revoked_kids))
294
+ throw new TypeError("Invalid origin revocation snapshot");
295
+ const kid = (0, import_web_bot_auth.jwkThumbprint)(privateKey);
296
+ if (privateKey.kid && privateKey.kid !== kid)
297
+ throw new TypeError("Revocation signing kid must be the JWK thumbprint");
298
+ const alg = privateKey.crv === "Ed25519" ? "EdDSA" : privateKey.crv === "P-256" ? "ES256" : void 0;
299
+ if (!alg || !privateKey.d) throw new TypeError("Revocations require a private Ed25519 or P-256 key");
300
+ return new import_jose.CompactSign(Buffer.from(JSON.stringify(snapshot))).setProtectedHeader({ alg, kid, typ: "adcp-gov-revocation+jws" }).sign(await (0, import_jose.importJWK)(privateKey, alg));
301
+ }
302
+ // Annotate the CommonJS export names for ESM import in node:
303
+ 0 && (module.exports = {
304
+ InMemoryOriginRevocationStore,
305
+ OriginRevocationResolver,
306
+ createSignedOriginRevocationList,
307
+ mergeRevocationDetail
308
+ });
@@ -0,0 +1,286 @@
1
+ import { eTldPlusOne } from "../signing/agent-resolver/etld.mjs";
2
+ import { CompactSign, compactVerify, decodeProtectedHeader, importJWK } from "jose";
3
+ import { ssrfSafeFetch } from "../net/index.mjs";
4
+ import { canonicalAgentOrigin } from "../signing/agent-resolver/canonicalize.mjs";
5
+ import { parseStrictJson } from "../signing/agent-resolver/strict-json.mjs";
6
+ import {
7
+ SignatureDirectoryResolver,
8
+ WebBotAuthError,
9
+ WebBotAuthUnavailableError,
10
+ jwkThumbprint
11
+ } from "../signing/web-bot-auth.mjs";
12
+ const REASONS = [
13
+ "removeFromCRL",
14
+ "unspecified",
15
+ "superseded",
16
+ "cessationOfOperation",
17
+ "affiliationChanged",
18
+ "certificateHold",
19
+ "privilegeWithdrawn",
20
+ "aACompromise",
21
+ "cACompromise",
22
+ "keyCompromise"
23
+ ];
24
+ import { mergeRevocationDetails } from "../signing/revocation.mjs";
25
+ import { mergeRevocationDetails as mergeRevocationDetail } from "../signing/revocation.mjs";
26
+ class InMemoryOriginRevocationStore {
27
+ durability = "process-local";
28
+ revoked = /* @__PURE__ */ new Map();
29
+ originKeys = /* @__PURE__ */ new Map();
30
+ operatorKeys = /* @__PURE__ */ new Map();
31
+ limits;
32
+ constructor(limits = {}) {
33
+ this.limits = {
34
+ perOrigin: limits.perOrigin ?? 16384,
35
+ perOperator: limits.perOperator ?? 16384,
36
+ total: limits.total ?? 1e5
37
+ };
38
+ if (Object.values(this.limits).some((value) => !Number.isSafeInteger(value) || value < 1))
39
+ throw new TypeError("Revocation limits must be positive safe integers");
40
+ }
41
+ async merge(origin, snapshot) {
42
+ origin = canonicalAgentOrigin(origin);
43
+ const operator = operatorOf(origin);
44
+ const additions = new Set(snapshot.revoked_kids.filter((kid) => !this.revoked.has(JSON.stringify([origin, kid]))));
45
+ const originCount = this.originKeys.get(origin) ?? 0, operatorCount = this.operatorKeys.get(operator) ?? 0;
46
+ if (originCount + additions.size > this.limits.perOrigin || operatorCount + additions.size > this.limits.perOperator || this.revoked.size + additions.size > this.limits.total)
47
+ throw new WebBotAuthError(403, "revocation_storage_limit");
48
+ for (const kid of snapshot.revoked_kids) {
49
+ const key = JSON.stringify([origin, kid]), prior = this.revoked.get(key), detail = snapshot.revocation_details?.[kid] ?? {};
50
+ this.revoked.set(key, mergeRevocationDetail(prior, detail));
51
+ }
52
+ if (additions.size) {
53
+ this.originKeys.set(origin, originCount + additions.size);
54
+ this.operatorKeys.set(operator, operatorCount + additions.size);
55
+ }
56
+ }
57
+ async get(origin, keyid) {
58
+ const entry = this.revoked.get(JSON.stringify([canonicalAgentOrigin(origin), keyid]));
59
+ return entry && { ...entry };
60
+ }
61
+ }
62
+ function operatorOf(origin) {
63
+ try {
64
+ return eTldPlusOne(origin);
65
+ } catch {
66
+ return new URL(origin).hostname;
67
+ }
68
+ }
69
+ const MAX_POLLING_SECONDS = 1800;
70
+ class RevocationListAbsentError extends Error {
71
+ }
72
+ class OriginRevocationResolver {
73
+ constructor(options) {
74
+ this.options = options;
75
+ if (!(options.directory instanceof SignatureDirectoryResolver))
76
+ throw new TypeError("Origin revocation requires a verified SignatureDirectoryResolver");
77
+ if (!Number.isFinite(options.pollingIntervalSeconds ?? 300) || (options.pollingIntervalSeconds ?? 300) < 60 || (options.pollingIntervalSeconds ?? 300) > 1800)
78
+ throw new TypeError("Invalid revocation polling interval");
79
+ }
80
+ options;
81
+ freshness = /* @__PURE__ */ new Map();
82
+ updated = /* @__PURE__ */ new Map();
83
+ graceUntil = /* @__PURE__ */ new Map();
84
+ pending = /* @__PURE__ */ new Map();
85
+ failures = /* @__PURE__ */ new Map();
86
+ persistenceFailures = /* @__PURE__ */ new Set();
87
+ absentUntil = /* @__PURE__ */ new Map();
88
+ /**
89
+ * Compatibility wrapper over {@link status}: `true` when revoked, `false`
90
+ * when the list is current, and `revocation_unavailable` when the identity
91
+ * publishes no list (`absent`) or its status is not known (`unknown`).
92
+ */
93
+ async isRevoked(originUrl, keyid) {
94
+ const state = await this.status(originUrl, keyid);
95
+ if (state === "revoked") return true;
96
+ if (state === "current") return false;
97
+ throw new WebBotAuthError(403, state === "absent" ? "revocation_absent" : "revocation_unavailable");
98
+ }
99
+ /**
100
+ * Revocation status of `keyid` at `origin`:
101
+ * - `revoked`: a stored (permanent) revocation covers the key.
102
+ * - `current`: a signed list is current, or within `next_update` + grace.
103
+ * - `absent`: the origin serves no list (404/410). The identity is still
104
+ * established but cannot be bound for spend.
105
+ * - `unknown`: no list could be verified and grace has passed (or there was
106
+ * never a list). The identity is not established.
107
+ * Throws {@link WebBotAuthUnavailableError} (`revocation_persistence_failed`)
108
+ * when the history store fails: an infrastructure outage, never a
109
+ * revocation outcome.
110
+ */
111
+ async status(originUrl, keyid) {
112
+ try {
113
+ return await this.currentStatus(originUrl, keyid);
114
+ } catch (error) {
115
+ if (error instanceof WebBotAuthError && error.reason === "revocation_persistence_failed")
116
+ throw new WebBotAuthUnavailableError("revocation_persistence_failed", error);
117
+ throw error;
118
+ }
119
+ }
120
+ async currentStatus(originUrl, keyid) {
121
+ const origin = canonicalAgentOrigin(originUrl), now = this.now();
122
+ if (await this.readStored(origin, keyid)) return "revoked";
123
+ const settled = async () => {
124
+ if (await this.readStored(origin, keyid)) return "revoked";
125
+ if ((this.absentUntil.get(origin) ?? 0) > now) return "absent";
126
+ return (this.freshness.get(origin) ?? 0) > now || (this.graceUntil.get(origin) ?? 0) > now ? "current" : "unknown";
127
+ };
128
+ if ((this.freshness.get(origin) ?? 0) <= now) {
129
+ if ((this.failures.get(origin) ?? 0) > now) {
130
+ if (this.persistenceFailures.has(origin)) throw new WebBotAuthError(403, "revocation_persistence_failed");
131
+ return settled();
132
+ }
133
+ let promise = this.pending.get(origin);
134
+ if (!promise) {
135
+ if (this.pending.size >= 16 || [...this.pending.keys()].filter((pendingOrigin) => operatorOf(pendingOrigin) === operatorOf(origin)).length >= 2) {
136
+ return settled();
137
+ }
138
+ promise = this.refresh(origin).catch((error) => {
139
+ if (this.failures.size >= (this.options.maxOrigins ?? 1e3)) {
140
+ const oldest = this.failures.keys().next().value;
141
+ this.failures.delete(oldest);
142
+ this.persistenceFailures.delete(oldest);
143
+ this.absentUntil.delete(oldest);
144
+ }
145
+ this.failures.set(origin, now + 60);
146
+ if (error instanceof WebBotAuthError && error.reason === "revocation_persistence_failed") {
147
+ this.persistenceFailures.add(origin);
148
+ this.graceUntil.delete(origin);
149
+ }
150
+ if (error.cause instanceof RevocationListAbsentError) {
151
+ this.absentUntil.set(origin, now + 60);
152
+ this.graceUntil.delete(origin);
153
+ }
154
+ throw error;
155
+ });
156
+ this.pending.set(origin, promise);
157
+ }
158
+ try {
159
+ await promise;
160
+ } catch (error) {
161
+ if (error instanceof WebBotAuthError && error.reason === "revocation_persistence_failed") throw error;
162
+ } finally {
163
+ if (this.pending.get(origin) === promise) this.pending.delete(origin);
164
+ }
165
+ }
166
+ return settled();
167
+ }
168
+ async readStored(origin, keyid) {
169
+ try {
170
+ return await this.options.store.get(origin, keyid);
171
+ } catch (cause) {
172
+ const error = new WebBotAuthError(403, "revocation_persistence_failed");
173
+ Object.defineProperty(error, "cause", { value: cause });
174
+ throw error;
175
+ }
176
+ }
177
+ async refresh(origin) {
178
+ try {
179
+ const response = await ssrfSafeFetch(origin + "/.well-known/governance-revocations.json", {
180
+ ...this.options.fetchOptions,
181
+ maxBodyBytes: 256 * 1024,
182
+ timeoutMs: 1e4
183
+ });
184
+ if (response.status === 404 || response.status === 410) throw new RevocationListAbsentError();
185
+ if (response.status !== 200) throw new Error("Unavailable revocation list");
186
+ const body = new TextDecoder("utf-8", { fatal: true }).decode(response.body);
187
+ let tokens;
188
+ if (body.trim().startsWith("{")) {
189
+ const envelope = parseStrictJson(body, 32);
190
+ if (typeof envelope.jws === "string") tokens = [envelope.jws];
191
+ else {
192
+ if ("header" in envelope) throw new Error("Revocation metadata must be protected");
193
+ const signatures = envelope.signatures ?? (envelope.protected && envelope.signature ? [{ protected: envelope.protected, signature: envelope.signature }] : []);
194
+ if (typeof envelope.payload !== "string" || !Array.isArray(signatures) || !signatures.length || signatures.length > 64)
195
+ throw new Error("Invalid JWS revocation envelope");
196
+ tokens = signatures.map((signature) => {
197
+ if (typeof signature.protected !== "string" || typeof signature.signature !== "string" || signature.header !== void 0)
198
+ throw new Error("Revocation metadata must be protected");
199
+ return `${signature.protected}.${envelope.payload}.${signature.signature}`;
200
+ });
201
+ }
202
+ } else tokens = [body.trim()];
203
+ let verifiedPayload;
204
+ for (const token of tokens) {
205
+ try {
206
+ const header = decodeProtectedHeader(token);
207
+ if (header.typ !== "adcp-gov-revocation+jws" || typeof header.kid !== "string" || typeof header.alg !== "string" || !["EdDSA", "ES256"].includes(header.alg))
208
+ continue;
209
+ await this.options.directory.resolve(header.kid, origin);
210
+ const checked = this.options.directory.getVerifiedDirectory(origin);
211
+ if (!checked || new URL(checked.proof.request.url).origin !== origin || checked.expires <= this.now())
212
+ continue;
213
+ const jwk = checked.keys.find((key) => key.kid === header.kid);
214
+ if (!jwk) continue;
215
+ const result = await compactVerify(token, await importJWK(jwk, header.alg), {
216
+ algorithms: ["EdDSA", "ES256"]
217
+ });
218
+ verifiedPayload = result.payload;
219
+ break;
220
+ } catch {
221
+ }
222
+ }
223
+ if (!verifiedPayload) throw new Error("No valid protected revocation signature");
224
+ const snapshot = parseStrictJson(
225
+ new TextDecoder("utf-8", { fatal: true }).decode(verifiedPayload),
226
+ 32
227
+ );
228
+ const updated = Date.parse(snapshot.updated) / 1e3, next = Date.parse(snapshot.next_update) / 1e3, now = this.now();
229
+ if (snapshot.issuer !== origin || !Number.isFinite(updated) || !Number.isFinite(next) || // Tolerate a publisher clock slightly ahead, as for request `created`.
230
+ updated > now + 60 || next <= now || next <= updated || !Array.isArray(snapshot.revoked_kids) || snapshot.revoked_kids.length > 4096 || snapshot.revoked_kids.some((k) => typeof k !== "string" || k.length > 256) || updated < (this.updated.get(origin) ?? 0))
231
+ throw new Error("Invalid revocation snapshot");
232
+ for (const [kid, detail] of Object.entries(snapshot.revocation_details ?? {}))
233
+ if (!snapshot.revoked_kids.includes(kid) || !detail || detail.reason && !REASONS.includes(detail.reason) || detail.invalidity_date && !Number.isFinite(Date.parse(detail.invalidity_date)))
234
+ throw new Error("Invalid revocation detail");
235
+ try {
236
+ await this.options.store.merge(origin, snapshot);
237
+ } catch (cause) {
238
+ const error = new WebBotAuthError(403, "revocation_persistence_failed");
239
+ Object.defineProperty(error, "cause", { value: cause });
240
+ throw error;
241
+ }
242
+ if (!this.freshness.has(origin) && this.freshness.size >= (this.options.maxOrigins ?? 1e3)) {
243
+ const oldest = this.freshness.keys().next().value;
244
+ this.freshness.delete(oldest);
245
+ this.updated.delete(oldest);
246
+ this.graceUntil.delete(oldest);
247
+ }
248
+ this.graceUntil.set(
249
+ origin,
250
+ Math.min(next, now + MAX_POLLING_SECONDS) + 4 * (this.options.pollingIntervalSeconds ?? 300)
251
+ );
252
+ this.updated.set(origin, updated);
253
+ this.freshness.set(origin, Math.min(next, now + (this.options.pollingIntervalSeconds ?? 300)));
254
+ this.failures.delete(origin);
255
+ this.persistenceFailures.delete(origin);
256
+ this.absentUntil.delete(origin);
257
+ } catch (cause) {
258
+ if (cause instanceof WebBotAuthError && cause.reason === "revocation_persistence_failed") throw cause;
259
+ const error = new WebBotAuthError(403, "revocation_unavailable");
260
+ Object.defineProperty(error, "cause", { value: cause });
261
+ throw error;
262
+ }
263
+ }
264
+ now() {
265
+ const now = (this.options.now ?? (() => Date.now() / 1e3))();
266
+ if (!Number.isFinite(now)) throw new WebBotAuthError(403, "revocation_unavailable");
267
+ return now;
268
+ }
269
+ }
270
+ async function createSignedOriginRevocationList(snapshot, privateKey) {
271
+ const issuer = canonicalAgentOrigin(snapshot.issuer), now = Date.now() / 1e3;
272
+ if (issuer !== snapshot.issuer || !Number.isFinite(Date.parse(snapshot.updated)) || !Number.isFinite(Date.parse(snapshot.next_update)) || Date.parse(snapshot.updated) / 1e3 > now || Date.parse(snapshot.next_update) / 1e3 <= now || Date.parse(snapshot.next_update) / 1e3 > now + 1800 || !Array.isArray(snapshot.revoked_kids))
273
+ throw new TypeError("Invalid origin revocation snapshot");
274
+ const kid = jwkThumbprint(privateKey);
275
+ if (privateKey.kid && privateKey.kid !== kid)
276
+ throw new TypeError("Revocation signing kid must be the JWK thumbprint");
277
+ const alg = privateKey.crv === "Ed25519" ? "EdDSA" : privateKey.crv === "P-256" ? "ES256" : void 0;
278
+ if (!alg || !privateKey.d) throw new TypeError("Revocations require a private Ed25519 or P-256 key");
279
+ return new CompactSign(Buffer.from(JSON.stringify(snapshot))).setProtectedHeader({ alg, kid, typ: "adcp-gov-revocation+jws" }).sign(await importJWK(privateKey, alg));
280
+ }
281
+ export {
282
+ InMemoryOriginRevocationStore,
283
+ OriginRevocationResolver,
284
+ createSignedOriginRevocationList,
285
+ mergeRevocationDetails as mergeRevocationDetail
286
+ };