@atlasauth/emulator-core 0.1.0 → 0.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 (300) hide show
  1. package/dist/adopt.d.ts +50 -0
  2. package/dist/adopt.js +57 -0
  3. package/dist/adopt.js.map +1 -0
  4. package/dist/coverage.d.ts +15 -0
  5. package/dist/coverage.js +31 -0
  6. package/dist/coverage.js.map +1 -0
  7. package/dist/crypto-util.d.ts +10 -0
  8. package/dist/crypto-util.js +76 -0
  9. package/dist/crypto-util.js.map +1 -0
  10. package/dist/custom-html.d.ts +57 -0
  11. package/dist/custom-html.js +491 -0
  12. package/dist/custom-html.js.map +1 -0
  13. package/dist/engine.d.ts +34 -3
  14. package/dist/engine.js +57 -8
  15. package/dist/engine.js.map +1 -1
  16. package/dist/error-catalog.js +16 -0
  17. package/dist/error-catalog.js.map +1 -1
  18. package/dist/event-gate.d.ts +3 -0
  19. package/dist/event-gate.js +430 -0
  20. package/dist/event-gate.js.map +1 -0
  21. package/dist/generic.js +14 -2
  22. package/dist/generic.js.map +1 -1
  23. package/dist/handlers/access-signals.d.ts +48 -0
  24. package/dist/handlers/access-signals.js +76 -0
  25. package/dist/handlers/access-signals.js.map +1 -0
  26. package/dist/handlers/approvals.d.ts +2 -0
  27. package/dist/handlers/approvals.js +418 -0
  28. package/dist/handlers/approvals.js.map +1 -0
  29. package/dist/handlers/authz-data.d.ts +2 -0
  30. package/dist/handlers/authz-data.js +627 -0
  31. package/dist/handlers/authz-data.js.map +1 -0
  32. package/dist/handlers/authz-layers.d.ts +229 -0
  33. package/dist/handlers/authz-layers.js +786 -0
  34. package/dist/handlers/authz-layers.js.map +1 -0
  35. package/dist/handlers/authz-state.d.ts +80 -0
  36. package/dist/handlers/authz-state.js +175 -0
  37. package/dist/handlers/authz-state.js.map +1 -0
  38. package/dist/handlers/authz.d.ts +2 -0
  39. package/dist/handlers/authz.js +410 -0
  40. package/dist/handlers/authz.js.map +1 -0
  41. package/dist/handlers/billing.d.ts +100 -0
  42. package/dist/handlers/billing.js +877 -0
  43. package/dist/handlers/billing.js.map +1 -0
  44. package/dist/handlers/cedar-ext.d.ts +35 -0
  45. package/dist/handlers/cedar-ext.js +174 -0
  46. package/dist/handlers/cedar-ext.js.map +1 -0
  47. package/dist/handlers/cedar.d.ts +146 -0
  48. package/dist/handlers/cedar.js +689 -0
  49. package/dist/handlers/cedar.js.map +1 -0
  50. package/dist/handlers/connections.d.ts +5 -0
  51. package/dist/handlers/connections.js +561 -0
  52. package/dist/handlers/connections.js.map +1 -0
  53. package/dist/handlers/control.js +6 -1
  54. package/dist/handlers/control.js.map +1 -1
  55. package/dist/handlers/device.d.ts +47 -0
  56. package/dist/handlers/device.js +665 -0
  57. package/dist/handlers/device.js.map +1 -0
  58. package/dist/handlers/emu3-misc.d.ts +38 -0
  59. package/dist/handlers/emu3-misc.js +1056 -0
  60. package/dist/handlers/emu3-misc.js.map +1 -0
  61. package/dist/handlers/emu4-actions-access.d.ts +46 -0
  62. package/dist/handlers/emu4-actions-access.js +107 -0
  63. package/dist/handlers/emu4-actions-access.js.map +1 -0
  64. package/dist/handlers/emu4-actions-catalog-extra.d.ts +3 -0
  65. package/dist/handlers/emu4-actions-catalog-extra.js +204 -0
  66. package/dist/handlers/emu4-actions-catalog-extra.js.map +1 -0
  67. package/dist/handlers/emu4-actions-catalog.d.ts +3 -0
  68. package/dist/handlers/emu4-actions-catalog.js +143 -0
  69. package/dist/handlers/emu4-actions-catalog.js.map +1 -0
  70. package/dist/handlers/emu4-actions-def.d.ts +50 -0
  71. package/dist/handlers/emu4-actions-def.js +250 -0
  72. package/dist/handlers/emu4-actions-def.js.map +1 -0
  73. package/dist/handlers/emu4-actions-sandbox.d.ts +36 -0
  74. package/dist/handlers/emu4-actions-sandbox.js +318 -0
  75. package/dist/handlers/emu4-actions-sandbox.js.map +1 -0
  76. package/dist/handlers/emu4-actions-typegen.d.ts +5 -0
  77. package/dist/handlers/emu4-actions-typegen.js +73 -0
  78. package/dist/handlers/emu4-actions-typegen.js.map +1 -0
  79. package/dist/handlers/emu4-actions.d.ts +2 -0
  80. package/dist/handlers/emu4-actions.js +506 -0
  81. package/dist/handlers/emu4-actions.js.map +1 -0
  82. package/dist/handlers/emu4-authz-trust.d.ts +40 -0
  83. package/dist/handlers/emu4-authz-trust.js +488 -0
  84. package/dist/handlers/emu4-authz-trust.js.map +1 -0
  85. package/dist/handlers/emu4-authz.d.ts +2 -0
  86. package/dist/handlers/emu4-authz.js +752 -0
  87. package/dist/handlers/emu4-authz.js.map +1 -0
  88. package/dist/handlers/emu4-billing-core.d.ts +23 -0
  89. package/dist/handlers/emu4-billing-core.js +22 -0
  90. package/dist/handlers/emu4-billing-core.js.map +1 -0
  91. package/dist/handlers/emu4-billing-x.d.ts +2 -0
  92. package/dist/handlers/emu4-billing-x.js +489 -0
  93. package/dist/handlers/emu4-billing-x.js.map +1 -0
  94. package/dist/handlers/emu4-billing.d.ts +14 -0
  95. package/dist/handlers/emu4-billing.js +846 -0
  96. package/dist/handlers/emu4-billing.js.map +1 -0
  97. package/dist/handlers/emu4-clones.d.ts +2 -0
  98. package/dist/handlers/emu4-clones.js +322 -0
  99. package/dist/handlers/emu4-clones.js.map +1 -0
  100. package/dist/handlers/emu4-compliance.d.ts +8 -0
  101. package/dist/handlers/emu4-compliance.js +39 -0
  102. package/dist/handlers/emu4-compliance.js.map +1 -0
  103. package/dist/handlers/emu4-config.d.ts +14 -0
  104. package/dist/handlers/emu4-config.js +148 -0
  105. package/dist/handlers/emu4-config.js.map +1 -0
  106. package/dist/handlers/emu4-cookies.d.ts +8 -0
  107. package/dist/handlers/emu4-cookies.js +248 -0
  108. package/dist/handlers/emu4-cookies.js.map +1 -0
  109. package/dist/handlers/emu4-erasure.d.ts +2 -0
  110. package/dist/handlers/emu4-erasure.js +587 -0
  111. package/dist/handlers/emu4-erasure.js.map +1 -0
  112. package/dist/handlers/emu4-federation.d.ts +8 -0
  113. package/dist/handlers/emu4-federation.js +18 -0
  114. package/dist/handlers/emu4-federation.js.map +1 -0
  115. package/dist/handlers/emu4-journey-math.d.ts +42 -0
  116. package/dist/handlers/emu4-journey-math.js +99 -0
  117. package/dist/handlers/emu4-journey-math.js.map +1 -0
  118. package/dist/handlers/emu4-messaging.d.ts +21 -0
  119. package/dist/handlers/emu4-messaging.js +595 -0
  120. package/dist/handlers/emu4-messaging.js.map +1 -0
  121. package/dist/handlers/emu4-minors.d.ts +7 -0
  122. package/dist/handlers/emu4-minors.js +408 -0
  123. package/dist/handlers/emu4-minors.js.map +1 -0
  124. package/dist/handlers/emu4-oauth-audit.d.ts +5 -0
  125. package/dist/handlers/emu4-oauth-audit.js +17 -0
  126. package/dist/handlers/emu4-oauth-audit.js.map +1 -0
  127. package/dist/handlers/emu4-oauth-auth.d.ts +83 -0
  128. package/dist/handlers/emu4-oauth-auth.js +363 -0
  129. package/dist/handlers/emu4-oauth-auth.js.map +1 -0
  130. package/dist/handlers/emu4-oauth-delivery.d.ts +68 -0
  131. package/dist/handlers/emu4-oauth-delivery.js +207 -0
  132. package/dist/handlers/emu4-oauth-delivery.js.map +1 -0
  133. package/dist/handlers/emu4-oauth-keys.d.ts +11 -0
  134. package/dist/handlers/emu4-oauth-keys.js +268 -0
  135. package/dist/handlers/emu4-oauth-keys.js.map +1 -0
  136. package/dist/handlers/emu4-oauth-pub.d.ts +36 -0
  137. package/dist/handlers/emu4-oauth-pub.js +420 -0
  138. package/dist/handlers/emu4-oauth-pub.js.map +1 -0
  139. package/dist/handlers/emu4-oauth.d.ts +10 -0
  140. package/dist/handlers/emu4-oauth.js +23 -0
  141. package/dist/handlers/emu4-oauth.js.map +1 -0
  142. package/dist/handlers/emu4-policies.d.ts +2 -0
  143. package/dist/handlers/emu4-policies.js +408 -0
  144. package/dist/handlers/emu4-policies.js.map +1 -0
  145. package/dist/handlers/emu4-region.d.ts +2 -0
  146. package/dist/handlers/emu4-region.js +189 -0
  147. package/dist/handlers/emu4-region.js.map +1 -0
  148. package/dist/handlers/emu4-saml.d.ts +12 -0
  149. package/dist/handlers/emu4-saml.js +532 -0
  150. package/dist/handlers/emu4-saml.js.map +1 -0
  151. package/dist/handlers/emu4-shared.d.ts +44 -0
  152. package/dist/handlers/emu4-shared.js +90 -0
  153. package/dist/handlers/emu4-shared.js.map +1 -0
  154. package/dist/handlers/emu4-snapshots.d.ts +38 -0
  155. package/dist/handlers/emu4-snapshots.js +231 -0
  156. package/dist/handlers/emu4-snapshots.js.map +1 -0
  157. package/dist/handlers/emu4-sns.d.ts +9 -0
  158. package/dist/handlers/emu4-sns.js +21 -0
  159. package/dist/handlers/emu4-sns.js.map +1 -0
  160. package/dist/handlers/emu4-trust-binding.d.ts +27 -0
  161. package/dist/handlers/emu4-trust-binding.js +344 -0
  162. package/dist/handlers/emu4-trust-binding.js.map +1 -0
  163. package/dist/handlers/emu4-trust.d.ts +35 -0
  164. package/dist/handlers/emu4-trust.js +543 -0
  165. package/dist/handlers/emu4-trust.js.map +1 -0
  166. package/dist/handlers/federation.d.ts +2 -0
  167. package/dist/handlers/federation.js +481 -0
  168. package/dist/handlers/federation.js.map +1 -0
  169. package/dist/handlers/fga-engine.d.ts +78 -0
  170. package/dist/handlers/fga-engine.js +663 -0
  171. package/dist/handlers/fga-engine.js.map +1 -0
  172. package/dist/handlers/governance.d.ts +2 -0
  173. package/dist/handlers/governance.js +460 -0
  174. package/dist/handlers/governance.js.map +1 -0
  175. package/dist/handlers/hooks.js +17 -1
  176. package/dist/handlers/hooks.js.map +1 -1
  177. package/dist/handlers/index.d.ts +5 -1
  178. package/dist/handlers/index.js +45 -3
  179. package/dist/handlers/index.js.map +1 -1
  180. package/dist/handlers/keys.js +6 -1
  181. package/dist/handlers/keys.js.map +1 -1
  182. package/dist/handlers/machines.js +61 -8
  183. package/dist/handlers/machines.js.map +1 -1
  184. package/dist/handlers/messaging.d.ts +6 -0
  185. package/dist/handlers/messaging.js +893 -0
  186. package/dist/handlers/messaging.js.map +1 -0
  187. package/dist/handlers/oauth-adv.d.ts +191 -0
  188. package/dist/handlers/oauth-adv.js +1305 -0
  189. package/dist/handlers/oauth-adv.js.map +1 -0
  190. package/dist/handlers/oauth-flows.d.ts +52 -0
  191. package/dist/handlers/oauth-flows.js +480 -0
  192. package/dist/handlers/oauth-flows.js.map +1 -0
  193. package/dist/handlers/oauth.d.ts +96 -0
  194. package/dist/handlers/oauth.js +793 -0
  195. package/dist/handlers/oauth.js.map +1 -0
  196. package/dist/handlers/orgs.js +6 -0
  197. package/dist/handlers/orgs.js.map +1 -1
  198. package/dist/handlers/passkeys.d.ts +3 -0
  199. package/dist/handlers/passkeys.js +293 -0
  200. package/dist/handlers/passkeys.js.map +1 -0
  201. package/dist/handlers/platform.d.ts +20 -0
  202. package/dist/handlers/platform.js +472 -0
  203. package/dist/handlers/platform.js.map +1 -0
  204. package/dist/handlers/round2.d.ts +8 -0
  205. package/dist/handlers/round2.js +372 -0
  206. package/dist/handlers/round2.js.map +1 -0
  207. package/dist/handlers/scim.d.ts +4 -0
  208. package/dist/handlers/scim.js +595 -0
  209. package/dist/handlers/scim.js.map +1 -0
  210. package/dist/handlers/sessions.d.ts +9 -3
  211. package/dist/handlers/sessions.js +76 -38
  212. package/dist/handlers/sessions.js.map +1 -1
  213. package/dist/handlers/support.d.ts +20 -0
  214. package/dist/handlers/support.js +62 -0
  215. package/dist/handlers/support.js.map +1 -0
  216. package/dist/handlers/users.js +7 -0
  217. package/dist/handlers/users.js.map +1 -1
  218. package/dist/handlers/workflows.d.ts +2 -0
  219. package/dist/handlers/workflows.js +428 -0
  220. package/dist/handlers/workflows.js.map +1 -0
  221. package/dist/index.d.ts +8 -0
  222. package/dist/index.js +23 -1
  223. package/dist/index.js.map +1 -1
  224. package/dist/jwe.d.ts +18 -0
  225. package/dist/jwe.js +101 -0
  226. package/dist/jwe.js.map +1 -0
  227. package/dist/jws.d.ts +41 -0
  228. package/dist/jws.js +135 -0
  229. package/dist/jws.js.map +1 -0
  230. package/dist/messages.d.ts +7 -0
  231. package/dist/messages.js +8 -4
  232. package/dist/messages.js.map +1 -1
  233. package/dist/messaging-callbacks.d.ts +100 -0
  234. package/dist/messaging-callbacks.js +767 -0
  235. package/dist/messaging-callbacks.js.map +1 -0
  236. package/dist/openapi.js +41 -1
  237. package/dist/openapi.js.map +1 -1
  238. package/dist/parity-bin.js +3 -1
  239. package/dist/parity-bin.js.map +1 -1
  240. package/dist/parity-emu3-authz.d.ts +3 -0
  241. package/dist/parity-emu3-authz.js +61 -0
  242. package/dist/parity-emu3-authz.js.map +1 -0
  243. package/dist/parity-emu3-billing.d.ts +3 -0
  244. package/dist/parity-emu3-billing.js +25 -0
  245. package/dist/parity-emu3-billing.js.map +1 -0
  246. package/dist/parity-emu3-messaging.d.ts +3 -0
  247. package/dist/parity-emu3-messaging.js +27 -0
  248. package/dist/parity-emu3-messaging.js.map +1 -0
  249. package/dist/parity-emu3-misc.d.ts +2 -0
  250. package/dist/parity-emu3-misc.js +63 -0
  251. package/dist/parity-emu3-misc.js.map +1 -0
  252. package/dist/parity-emu3-oauth.d.ts +2 -0
  253. package/dist/parity-emu3-oauth.js +39 -0
  254. package/dist/parity-emu3-oauth.js.map +1 -0
  255. package/dist/parity-emu4-actions.d.ts +2 -0
  256. package/dist/parity-emu4-actions.js +38 -0
  257. package/dist/parity-emu4-actions.js.map +1 -0
  258. package/dist/parity-emu4-authz.d.ts +3 -0
  259. package/dist/parity-emu4-authz.js +68 -0
  260. package/dist/parity-emu4-authz.js.map +1 -0
  261. package/dist/parity-emu4-billing.d.ts +6 -0
  262. package/dist/parity-emu4-billing.js +44 -0
  263. package/dist/parity-emu4-billing.js.map +1 -0
  264. package/dist/parity-emu4-compliance.d.ts +2 -0
  265. package/dist/parity-emu4-compliance.js +92 -0
  266. package/dist/parity-emu4-compliance.js.map +1 -0
  267. package/dist/parity-emu4-federation.d.ts +2 -0
  268. package/dist/parity-emu4-federation.js +33 -0
  269. package/dist/parity-emu4-federation.js.map +1 -0
  270. package/dist/parity-emu4-messaging.d.ts +3 -0
  271. package/dist/parity-emu4-messaging.js +42 -0
  272. package/dist/parity-emu4-messaging.js.map +1 -0
  273. package/dist/parity-emu4-oauth.d.ts +2 -0
  274. package/dist/parity-emu4-oauth.js +55 -0
  275. package/dist/parity-emu4-oauth.js.map +1 -0
  276. package/dist/parity-emu4-trust.d.ts +2 -0
  277. package/dist/parity-emu4-trust.js +41 -0
  278. package/dist/parity-emu4-trust.js.map +1 -0
  279. package/dist/parity-routes.d.ts +14 -0
  280. package/dist/parity-routes.js +439 -0
  281. package/dist/parity-routes.js.map +1 -0
  282. package/dist/parity.d.ts +10 -3
  283. package/dist/parity.js +14 -5
  284. package/dist/parity.js.map +1 -1
  285. package/dist/sns-cert.d.ts +9 -0
  286. package/dist/sns-cert.js +101 -0
  287. package/dist/sns-cert.js.map +1 -0
  288. package/dist/tokens.d.ts +85 -3
  289. package/dist/tokens.js +196 -24
  290. package/dist/tokens.js.map +1 -1
  291. package/dist/webauthn-virtual.d.ts +70 -0
  292. package/dist/webauthn-virtual.js +186 -0
  293. package/dist/webauthn-virtual.js.map +1 -0
  294. package/dist/webhook-ext.d.ts +16 -0
  295. package/dist/webhook-ext.js +218 -0
  296. package/dist/webhook-ext.js.map +1 -0
  297. package/dist/webhooks.d.ts +3 -0
  298. package/dist/webhooks.js +37 -3
  299. package/dist/webhooks.js.map +1 -1
  300. package/package.json +2 -2
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_ATTEMPTS = exports.RETRY_SCHEDULE_MS = void 0;
4
+ exports.enqueueBackchannelLogout = enqueueBackchannelLogout;
5
+ exports.enqueueCiba = enqueueCiba;
6
+ exports.runDueDeliveries = runDueDeliveries;
7
+ exports.emu4DeliveryHandlers = emu4DeliveryHandlers;
8
+ const errors_1 = require("../errors");
9
+ const store_1 = require("../store");
10
+ const emu4_oauth_audit_1 = require("./emu4-oauth-audit");
11
+ const emu4_oauth_auth_1 = require("./emu4-oauth-auth");
12
+ const oauth_flows_1 = require("./oauth-flows");
13
+ const support_1 = require("./support");
14
+ /**
15
+ * Queued, retried delivery of back-channel logout tokens and CIBA ping/push notifications, on the engine clock.
16
+ *
17
+ * The first attempt is made at once (the request that caused the delivery waits for it); a failure is retried on the
18
+ * real schedule (5 s, 5 min, 30 min, 2 h, 5 h, 10 h: six attempts in all) when the clock reaches it. Time moves with
19
+ * `POST /__emulator/time/advance` (which runs everything that came due) or `POST /__emulator/oauth/deliveries/run`;
20
+ * every attempt is kept so a test can read what the receiver saw. An OIDC relying party that answers and refuses
21
+ * (4xx other than 408 and 429) is not retried (back-channel logout section 2.5), nor is a test send.
22
+ */
23
+ exports.RETRY_SCHEDULE_MS = [5_000, 5 * 60_000, 30 * 60_000, 2 * 3_600_000, 5 * 3_600_000, 10 * 3_600_000];
24
+ exports.MAX_ATTEMPTS = exports.RETRY_SCHEDULE_MS.length;
25
+ const LOGOUT_EVENT = 'http://schemas.openid.net/event/backchannel-logout';
26
+ const SNIPPET_CHARS = 512;
27
+ const queue = (0, support_1.engineState)(() => []);
28
+ const ids = (0, support_1.engineState)(() => ({ n: 0 }));
29
+ const isSuccess = (s) => s >= 200 && s < 300;
30
+ const recoverable = (s) => s >= 500 || s === 408 || s === 429;
31
+ async function body(e, d) {
32
+ if (d.kind === 'backchannel_logout') {
33
+ const client = e.db.oauthClients.get(d.client_id);
34
+ // The token is minted again for every attempt (a fresh jti), like the real dispatcher.
35
+ const sub = d.is_test || !d.user_id ? (d.user_id ?? `sub_test_${(0, store_1.randomToken)(9)}`) : await (0, emu4_oauth_auth_1.subjectFor)(e, client, d.user_id);
36
+ const token = await e.tokens.signClaims({ aud: d.client_id, jti: e.db.newId('ologout'), events: { [LOGOUT_EVENT]: {} }, sub, sid: d.sid ?? undefined, ...(d.is_test ? { atlas_test: true } : {}) }, 120);
37
+ return { headers: { 'content-type': 'application/x-www-form-urlencoded' }, text: `logout_token=${encodeURIComponent(token)}` };
38
+ }
39
+ return { headers: { 'content-type': 'application/json', authorization: `Bearer ${d.bearer}` }, text: JSON.stringify(d.payload) };
40
+ }
41
+ /** One HTTP attempt; records it and schedules the next on the real schedule. */
42
+ async function attempt(e, d) {
43
+ const started = e.clock.now();
44
+ const { headers, text } = await body(e, d);
45
+ let status = null;
46
+ let snippet = null;
47
+ let location = null;
48
+ let error = null;
49
+ try {
50
+ const res = await (e.options.fetch ?? fetch)(d.endpoint, { method: 'POST', headers, body: text, redirect: 'manual' });
51
+ status = res.status;
52
+ snippet = ((await res.text().catch(() => '')) || '').slice(0, SNIPPET_CHARS) || null;
53
+ if (status >= 300 && status < 400)
54
+ location = res.headers.get('location');
55
+ if (!isSuccess(status))
56
+ error = d.kind === 'backchannel_logout' ? (location !== null || (status >= 300 && status < 400) ? 'backchannel_redirect_not_followed' : 'backchannel_http_error') : `http_${status}`;
57
+ }
58
+ catch (err) {
59
+ error = d.kind === 'backchannel_logout' ? (err?.name === 'TimeoutError' || err?.name === 'AbortError' ? 'backchannel_timeout' : 'backchannel_network_error') : (err instanceof Error ? err.message : String(err));
60
+ }
61
+ const now = e.clock.now();
62
+ const n = d.attempt_number + 1;
63
+ const ok = status !== null && isSuccess(status);
64
+ d.attempt_number = n;
65
+ d.attempted_at = now;
66
+ d.http_status = status;
67
+ d.latency_ms = Math.max(0, now - started);
68
+ d.error = error;
69
+ d.location = location;
70
+ d.response_snippet = snippet;
71
+ d.attempts.push({ attempt: n, at: now, http_status: status, error, success: ok, location });
72
+ if (ok) {
73
+ d.status = 'success';
74
+ d.delivered_at = now;
75
+ d.next_retry_at = null;
76
+ return;
77
+ }
78
+ d.status = 'failed';
79
+ // An OIDC relying party that answered and refused is final (section 2.5); a test is never retried.
80
+ const refused = d.kind === 'backchannel_logout' && status !== null && !recoverable(status);
81
+ d.next_retry_at = refused || d.is_test || n >= exports.MAX_ATTEMPTS ? null : now + exports.RETRY_SCHEDULE_MS[n - 1];
82
+ }
83
+ function enqueue(e, row) {
84
+ const d = { id: `bld_${String(++ids(e).n).padStart(6, '0')}_${(0, store_1.randomToken)(6)}`, user_id: null, sid: null, request_id: null, bearer: null, payload: null, is_test: false, status: 'pending', attempt_number: 0, http_status: null, latency_ms: null, error: null, location: null, response_snippet: null, next_retry_at: null, attempted_at: null, delivered_at: null, created_at: e.clock.now(), attempts: [], ...row };
85
+ queue(e).push(d);
86
+ return d;
87
+ }
88
+ /** Queue a back-channel logout for a client's session and make the first attempt. */
89
+ async function enqueueBackchannelLogout(e, client, input) {
90
+ const d = enqueue(e, { kind: 'backchannel_logout', client_id: client.id, endpoint: client.backchannel_logout_uri, user_id: input.userId, sid: input.sid });
91
+ await attempt(e, d);
92
+ return d;
93
+ }
94
+ /** Queue a CIBA ping (only the `auth_req_id`) or push (the token response or the refusal) and make the first attempt. */
95
+ async function enqueueCiba(e, input) {
96
+ const d = enqueue(e, { kind: input.kind, client_id: input.clientId, endpoint: input.endpoint, request_id: input.requestId, bearer: input.token, payload: input.payload });
97
+ await attempt(e, d);
98
+ return d;
99
+ }
100
+ /**
101
+ * Everything the clock made due: push requests that expired undecided are announced (`expired_token`), then every
102
+ * delivery whose retry time has come is attempted, oldest first. Returns how many attempts ran.
103
+ */
104
+ async function runDueDeliveries(e) {
105
+ const now = e.clock.now();
106
+ for (const rec of (0, oauth_flows_1.cibaRecords)(e).values()) {
107
+ if (rec.mode !== 'push' || rec.status !== 'pending' || rec.expiresAt > now || rec.expiredNotified)
108
+ continue;
109
+ const client = e.db.oauthClients.get(rec.clientId);
110
+ rec.expiredNotified = true;
111
+ if (!client || client.deleted || !client.backchannel_client_notification_endpoint || !rec.notificationToken)
112
+ continue;
113
+ await enqueueCiba(e, { kind: 'ciba_push', clientId: client.id, requestId: rec.id, endpoint: client.backchannel_client_notification_endpoint, token: rec.notificationToken, payload: { auth_req_id: rec.id, error: 'expired_token', error_description: 'The authentication request expired.' } });
114
+ }
115
+ let ran = 0;
116
+ for (const d of queue(e)) {
117
+ if (d.status !== 'failed' || d.next_retry_at === null || d.next_retry_at > e.clock.now())
118
+ continue;
119
+ // The target may be gone since the delivery was queued: nothing to deliver to, so it leaves the queue.
120
+ const client = e.db.oauthClients.get(d.client_id);
121
+ if (!client || client.deleted || (d.kind === 'backchannel_logout' && !client.backchannel_logout_uri)) {
122
+ d.next_retry_at = null;
123
+ d.error = d.kind === 'backchannel_logout' ? 'client_missing' : 'client_missing';
124
+ continue;
125
+ }
126
+ if (d.kind === 'backchannel_logout')
127
+ d.endpoint = client.backchannel_logout_uri;
128
+ await attempt(e, d);
129
+ ran++;
130
+ }
131
+ return ran;
132
+ }
133
+ const present = (d) => ({
134
+ object: 'backchannel_logout_delivery',
135
+ id: d.id,
136
+ oauth_client_id: d.client_id,
137
+ sid: d.sid,
138
+ trace_id: null,
139
+ test: d.is_test,
140
+ status: d.status,
141
+ attempt_number: d.attempt_number,
142
+ max_attempts: d.is_test ? 1 : exports.MAX_ATTEMPTS,
143
+ http_status: d.http_status,
144
+ latency_ms: d.latency_ms,
145
+ error: d.error,
146
+ location: d.location,
147
+ response_snippet: d.response_snippet,
148
+ next_retry_at: d.next_retry_at,
149
+ attempted_at: d.attempted_at,
150
+ delivered_at: d.delivered_at,
151
+ created_at: d.created_at,
152
+ });
153
+ const rawView = (d) => ({ ...present(d), object: 'oauth_delivery', kind: d.kind, endpoint: d.endpoint, request_id: d.request_id, user_id: d.user_id, attempts: d.attempts });
154
+ function emu4DeliveryHandlers() {
155
+ const clientOf = (e, id) => {
156
+ const c = e.db.oauthClients.get(id);
157
+ if (!c || c.deleted)
158
+ throw new errors_1.EmulatorError('NOT_FOUND', 'Unknown OAuth client.');
159
+ return c;
160
+ };
161
+ return [
162
+ {
163
+ method: 'GET',
164
+ pattern: '/v1/oauth_clients/:id/backchannel_deliveries',
165
+ scope: 'oauth_clients:read',
166
+ handler: async (c) => {
167
+ const e = c.engine;
168
+ const client = clientOf(e, c.params.id);
169
+ await runDueDeliveries(e);
170
+ const limit = Math.min(Math.max(Math.floor(Number(c.query.get('limit') ?? 20)) || 20, 1), 100);
171
+ const rows = queue(e).filter((d) => d.kind === 'backchannel_logout' && d.client_id === client.id).reverse();
172
+ const page = (0, store_1.paginate)(rows, { limit, startingAfter: c.query.get('starting_after') ?? undefined });
173
+ return { body: { object: 'list', data: page.data.map(present), has_more: page.has_more, next_cursor: page.has_more ? (page.data[page.data.length - 1]?.id ?? null) : null } };
174
+ },
175
+ },
176
+ {
177
+ method: 'POST',
178
+ pattern: '/v1/oauth_clients/:id/backchannel_logout/test',
179
+ scope: 'oauth_clients:write',
180
+ handler: async (c) => {
181
+ const e = c.engine;
182
+ const client = clientOf(e, c.params.id);
183
+ if (!client.backchannel_logout_uri)
184
+ throw new errors_1.EmulatorError('CONFLICT', 'This client has no backchannel_logout_uri. Set one first, then send a test.');
185
+ const sid = `sid_test_${(0, store_1.randomToken)(9)}`;
186
+ const d = enqueue(e, { kind: 'backchannel_logout', client_id: client.id, endpoint: client.backchannel_logout_uri, user_id: `sub_test_${(0, store_1.randomToken)(9)}`, sid, is_test: true });
187
+ await attempt(e, d);
188
+ (0, emu4_oauth_audit_1.recordAudit)(e, 'oauth_client.backchannel_logout_test_sent', 'api_key', 'oauth_client', client.id, { client_id: client.id, delivery_id: d.id, ok: d.status === 'success' });
189
+ return { body: { object: 'backchannel_logout_test', delivery_id: d.id, ok: d.status === 'success', sid, status: d.http_status, latency_ms: d.latency_ms, error: d.error, location: d.location, blocked_reason: null, body_excerpt: d.response_snippet } };
190
+ },
191
+ },
192
+ {
193
+ // Every queued delivery with its attempts: `kind` (backchannel_logout, ciba_ping, ciba_push) and `client_id` narrow it.
194
+ method: 'GET',
195
+ pattern: '/__emulator/oauth/deliveries',
196
+ public: true,
197
+ handler: async (c) => {
198
+ await runDueDeliveries(c.engine);
199
+ const kind = c.query.get('kind');
200
+ const client = c.query.get('client_id');
201
+ return { body: { object: 'list', data: queue(c.engine).filter((d) => (!kind || d.kind === kind) && (!client || d.client_id === client)).map(rawView) } };
202
+ },
203
+ },
204
+ { method: 'POST', pattern: '/__emulator/oauth/deliveries/run', public: true, handler: async (c) => ({ body: { object: 'delivery_sweep', attempted: await runDueDeliveries(c.engine) } }) },
205
+ ];
206
+ }
207
+ //# sourceMappingURL=emu4-oauth-delivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emu4-oauth-delivery.js","sourceRoot":"","sources":["../../src/handlers/emu4-oauth-delivery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Engine, RouteDef } from '../engine';
2
+ import { SIGNING_ALGS } from '../tokens';
3
+ /** The shortest the previous key may stay published: the longest token lifetime plus the key set cache. */
4
+ export declare const minimumGraceSeconds: () => number;
5
+ /**
6
+ * The worker's rotation sweep, on the engine clock: when the schedule is due it STAGES a new key (published
7
+ * `prepublish_hours` before it signs); it waits while a previous key is still published or another key is staged.
8
+ */
9
+ export declare function runSigningSchedule(e: Engine): Promise<'idle' | 'staged' | 'waiting' | 'failed'>;
10
+ export declare function signingKeyHandlers(): RouteDef[];
11
+ export { SIGNING_ALGS };
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SIGNING_ALGS = exports.minimumGraceSeconds = void 0;
4
+ exports.runSigningSchedule = runSigningSchedule;
5
+ exports.signingKeyHandlers = signingKeyHandlers;
6
+ const errors_1 = require("../errors");
7
+ const tokens_1 = require("../tokens");
8
+ Object.defineProperty(exports, "SIGNING_ALGS", { enumerable: true, get: function () { return tokens_1.SIGNING_ALGS; } });
9
+ const emu4_oauth_audit_1 = require("./emu4-oauth-audit");
10
+ const support_1 = require("./support");
11
+ /**
12
+ * Signing algorithm choice, staged rotation and the rotation schedule of the instance key, with the real routes and
13
+ * rules: `GET /v1/instance/signing_keys`, `POST .../rotate`, `DELETE .../next`, `GET|PATCH .../signing_key_policy` and
14
+ * `GET|PUT|DELETE /v1/instance/signing_key_schedule`. The JWKS reflects every change; the engine clock drives staging,
15
+ * activation, retirement and the schedule (`runSigningSchedule` runs on every clock advance and on every schedule read).
16
+ */
17
+ const DAY_MS = 86_400_000;
18
+ const MIN_STAGE_LEAD_MS = 3_600_000;
19
+ const MAX_STAGE_LEAD_MS = 90 * DAY_MS;
20
+ const DEFAULT_STAGE_DAYS = 14;
21
+ const MAX_GRACE_S = 30 * 86_400;
22
+ const DEFAULT_SCHEDULE_GRACE_S = 86_400;
23
+ /** Verifiers cache a key set for up to an hour; it is added to the longest token lifetime. */
24
+ const JWKS_CACHE_MARGIN_S = 3600;
25
+ /** The longest token the emulator signs lives an hour (access and ID tokens). */
26
+ const LONGEST_TOKEN_S = 3600;
27
+ const ALGS_LABEL = 'RS256, ES256, ES384, PS256 or EdDSA';
28
+ const ks = (0, support_1.engineState)(() => ({ policyDays: null, schedule: null }));
29
+ const bad = (message, param) => new errors_1.EmulatorError('VALIDATION_FAILED', message, param);
30
+ const conflict = (message) => new errors_1.EmulatorError('CONFLICT', message);
31
+ /** The shortest the previous key may stay published: the longest token lifetime plus the key set cache. */
32
+ const minimumGraceSeconds = () => LONGEST_TOKEN_S + JWKS_CACHE_MARGIN_S;
33
+ exports.minimumGraceSeconds = minimumGraceSeconds;
34
+ function scheduleView(e, s) {
35
+ return {
36
+ object: 'signing_key_schedule',
37
+ enabled: s?.enabled ?? false,
38
+ interval_days: s?.interval_days ?? null,
39
+ alg: s?.alg ?? null,
40
+ grace_period_seconds: s?.grace_period_seconds ?? null,
41
+ prepublish_hours: s?.prepublish_hours ?? null,
42
+ effective_grace_seconds: Math.max(s?.grace_period_seconds ?? 0, (0, exports.minimumGraceSeconds)(), DEFAULT_SCHEDULE_GRACE_S),
43
+ next_rotation_at: s?.next_rotation_at ?? null,
44
+ last_rotated_at: s?.last_rotated_at ?? null,
45
+ last_error: s?.last_error ?? null,
46
+ last_error_at: s?.last_error_at ?? null,
47
+ };
48
+ }
49
+ function parseSchedule(body) {
50
+ const days = body.interval_days;
51
+ if (typeof days !== 'number' || !Number.isInteger(days) || days < 1 || days > 365)
52
+ throw bad('interval_days must be a whole number of days from 1 to 365.', 'interval_days');
53
+ if (body.enabled !== undefined && typeof body.enabled !== 'boolean')
54
+ throw bad('enabled must be true or false.', 'enabled');
55
+ let alg = null;
56
+ if (body.alg !== undefined && body.alg !== null) {
57
+ if (!(0, tokens_1.isSigningAlg)(body.alg))
58
+ throw bad(`alg must be ${ALGS_LABEL}.`, 'alg');
59
+ alg = body.alg;
60
+ }
61
+ const g = body.grace_period_seconds;
62
+ let grace = null;
63
+ if (g !== undefined && g !== null) {
64
+ if (typeof g !== 'number' || !Number.isInteger(g) || g < 0 || g > MAX_GRACE_S)
65
+ throw bad('grace_period_seconds must be a whole number of seconds from 0 to 2592000.', 'grace_period_seconds');
66
+ if (g < (0, exports.minimumGraceSeconds)())
67
+ throw bad(`grace_period_seconds must be at least ${(0, exports.minimumGraceSeconds)()}: the longest token this instance signs lives that long (plus the key set cache), and the previous key must stay published until it has expired.`, 'grace_period_seconds');
68
+ grace = g;
69
+ }
70
+ const p = body.prepublish_hours;
71
+ if (p !== undefined && (typeof p !== 'number' || !Number.isInteger(p) || p < 2 || p > 720))
72
+ throw bad('prepublish_hours must be a whole number of hours from 2 to 720.', 'prepublish_hours');
73
+ const prepublish = p ?? 24;
74
+ const effective = Math.max(grace ?? 0, (0, exports.minimumGraceSeconds)(), DEFAULT_SCHEDULE_GRACE_S);
75
+ if (days * 86_400 <= prepublish * 3600 + effective)
76
+ throw bad('interval_days is too short: one rotation (the new key published prepublish_hours before it signs, the old key kept for the grace period) must finish before the next starts.', 'interval_days');
77
+ return { enabled: body.enabled !== false, interval_days: days, alg, grace_period_seconds: grace, prepublish_hours: prepublish };
78
+ }
79
+ /**
80
+ * The worker's rotation sweep, on the engine clock: when the schedule is due it STAGES a new key (published
81
+ * `prepublish_hours` before it signs); it waits while a previous key is still published or another key is staged.
82
+ */
83
+ async function runSigningSchedule(e) {
84
+ const s = ks(e).schedule;
85
+ // No key is made just to look at the clock: an engine that never signed has nothing to activate or retire.
86
+ if (!s)
87
+ return (await e.tokens.settleIfStarted(), 'idle');
88
+ await e.tokens.ready();
89
+ const now = e.clock.now();
90
+ if (!s.enabled || now < s.next_rotation_at)
91
+ return 'idle';
92
+ const st = await e.tokens.keyState();
93
+ const blockedUntil = Math.max(st.previousRetiresAt !== null && st.previousRetiresAt > now ? st.previousRetiresAt : 0, st.staged ? st.staged.activatesAt + 60_000 : 0);
94
+ if (blockedUntil > now) {
95
+ s.next_rotation_at = blockedUntil + 60_000;
96
+ return 'waiting';
97
+ }
98
+ const grace = Math.max(s.grace_period_seconds ?? 0, (0, exports.minimumGraceSeconds)(), DEFAULT_SCHEDULE_GRACE_S);
99
+ try {
100
+ const r = await e.tokens.rotate(s.alg ?? undefined, { staged: true, activatesAt: now + s.prepublish_hours * 3_600_000, graceSeconds: grace, trigger: 'schedule' });
101
+ const data = { object: 'signing_key', kid: r.kid, alg: r.alg, activates_at: r.activates_at, trigger: 'schedule' };
102
+ e.webhooks.emit('signing_key.staged', data);
103
+ (0, emu4_oauth_audit_1.recordAudit)(e, 'signing_key.staged', 'system', 'instance', e.instanceId, { ...data, grace_period_seconds: grace });
104
+ s.last_rotated_at = now;
105
+ s.next_rotation_at = now + s.interval_days * DAY_MS;
106
+ s.last_error = null;
107
+ s.last_error_at = null;
108
+ return 'staged';
109
+ }
110
+ catch (err) {
111
+ const message = err instanceof Error ? err.message : String(err);
112
+ s.last_error = message.slice(0, 300);
113
+ s.last_error_at = now;
114
+ s.next_rotation_at = now + 3_600_000;
115
+ e.webhooks.emit('signing_key.rotation_failed', { object: 'signing_key_schedule', error: message.slice(0, 300), retry_at: s.next_rotation_at });
116
+ (0, emu4_oauth_audit_1.recordAudit)(e, 'signing_key.rotation_failed', 'system', 'instance', e.instanceId, { error: message.slice(0, 300) });
117
+ return 'failed';
118
+ }
119
+ }
120
+ function parseStaging(body, now) {
121
+ if (body.staged !== undefined && typeof body.staged !== 'boolean')
122
+ throw bad('staged must be true or false.', 'staged');
123
+ let activatesAt;
124
+ if (body.activates_at !== undefined) {
125
+ const raw = body.activates_at;
126
+ const at = typeof raw === 'number' && Number.isFinite(raw) ? raw : typeof raw === 'string' && raw.trim() ? Date.parse(raw) : NaN;
127
+ if (Number.isNaN(at))
128
+ throw bad('activates_at must be an ISO 8601 date-time or epoch milliseconds.', 'activates_at');
129
+ const lead = at - now;
130
+ if (lead < MIN_STAGE_LEAD_MS || lead > MAX_STAGE_LEAD_MS)
131
+ throw bad('activates_at must be at least 1 hour and at most 90 days from now.', 'activates_at');
132
+ if (body.staged === false)
133
+ throw bad('activates_at applies to a staged rotation (staged: true).', 'activates_at');
134
+ activatesAt = at;
135
+ }
136
+ return { ...(body.staged !== undefined ? { staged: body.staged } : {}), ...(activatesAt !== undefined ? { activatesAt } : {}) };
137
+ }
138
+ function signingKeyHandlers() {
139
+ return [
140
+ { method: 'GET', pattern: '/v1/instance/signing_keys', scope: 'instance:read', handler: async (c) => ({ body: { object: 'list', data: await c.engine.tokens.signingKeys() } }) },
141
+ {
142
+ method: 'POST',
143
+ pattern: '/v1/instance/signing_keys/rotate',
144
+ scope: 'instance:write',
145
+ handler: async (c) => {
146
+ const e = c.engine;
147
+ const b = c.body;
148
+ if (b.key !== undefined && b.key !== 'main' && b.key !== 'secondary')
149
+ throw bad('key must be "main" or "secondary".', 'key');
150
+ if (b.alg !== undefined && !(0, tokens_1.isSigningAlg)(b.alg))
151
+ throw bad(`alg must be ${ALGS_LABEL}.`, 'alg');
152
+ if (b.emergency !== undefined && typeof b.emergency !== 'boolean')
153
+ throw bad('emergency must be true or false.', 'emergency');
154
+ let grace = 86_400;
155
+ if (b.grace_period_seconds !== undefined) {
156
+ const g = b.grace_period_seconds;
157
+ if (typeof g !== 'number' || !Number.isInteger(g) || g < 0 || g > MAX_GRACE_S)
158
+ throw bad(`grace_period_seconds must be a whole number of seconds from 0 to ${MAX_GRACE_S}.`, 'grace_period_seconds');
159
+ grace = g;
160
+ }
161
+ // The emulator holds its keys locally: `key` only applies to keys in a key management service.
162
+ if (b.key !== undefined)
163
+ throw bad('key applies to keys held in a key management service.', 'key');
164
+ const emergency = b.emergency === true;
165
+ const now = e.clock.now();
166
+ const staging = parseStaging(b, now);
167
+ if (staging.staged === true && emergency)
168
+ throw bad('An emergency rotation cannot be staged: it replaces the key now.', 'staged');
169
+ const st = await e.tokens.keyState();
170
+ const staged = !emergency && (staging.staged ?? Boolean(ks(e).policyDays));
171
+ if (!staged) {
172
+ if (!emergency && st.staged)
173
+ throw conflict(`Key ${st.staged.kid} is staged to start signing at ${new Date(st.staged.activatesAt).toISOString()}. Only one key can be staged: cancel it first (DELETE /v1/instance/signing_keys/next), or pass emergency: true to discard it and rotate now.`);
174
+ if (!emergency && st.previousRetiresAt !== null && st.previousRetiresAt > now)
175
+ throw conflict(`The previous key is still published until ${new Date(st.previousRetiresAt).toISOString()}. Rotate again after that, or pass emergency: true to revoke it now.`);
176
+ }
177
+ if (staged) {
178
+ if (b.grace_period_seconds !== undefined)
179
+ throw bad('grace_period_seconds does not apply to a staged rotation: the previous key stays published for 24 hours after the new key activates.', 'grace_period_seconds');
180
+ if (st.staged)
181
+ throw conflict(`Key ${st.staged.kid} is already staged to start signing at ${new Date(st.staged.activatesAt).toISOString()}. Only one key can be staged: cancel it first (DELETE /v1/instance/signing_keys/next).`);
182
+ const at = staging.activatesAt ?? now + (ks(e).policyDays || DEFAULT_STAGE_DAYS) * DAY_MS;
183
+ if (st.previousRetiresAt !== null && st.previousRetiresAt > now && st.previousRetiresAt > at)
184
+ throw conflict(`The previous key is still published until ${new Date(st.previousRetiresAt).toISOString()}. Stage the next key to activate after that (activates_at), or rotate again once it is retired.`);
185
+ const r = await e.tokens.rotate(b.alg, { staged: true, activatesAt: at, trigger: 'request' });
186
+ const data = { object: 'signing_key', kid: r.kid, alg: r.alg, activates_at: r.activates_at };
187
+ e.webhooks.emit('signing_key.staged', data);
188
+ (0, emu4_oauth_audit_1.recordAudit)(e, 'signing_key.staged', 'api_key', 'instance', e.instanceId, { kid: r.kid, alg: r.alg, current_kid: st.currentKid, activates_at: r.activates_at, staged: true, provider: 'local' });
189
+ return { status: 201, body: { object: 'signing_key_rotation', kid: r.kid, alg: r.alg, previous_kid: r.previous_kid, previous_retires_at: r.previous_retires_at, emergency: false, provider: 'local', staged: true, activates_at: r.activates_at } };
190
+ }
191
+ const discarded = emergency ? (st.staged?.kid ?? null) : null;
192
+ const r = await e.tokens.rotate(b.alg, { graceSeconds: grace, emergency });
193
+ e.webhooks.emit('signing_key.rotated', { object: 'signing_key', kid: r.kid, alg: r.alg, previous_kid: r.previous_kid, emergency, retires_at: emergency ? null : r.previous_retires_at, provider: 'local' });
194
+ (0, emu4_oauth_audit_1.recordAudit)(e, 'signing_key.rotated', 'api_key', 'instance', e.instanceId, { kid: r.kid, alg: r.alg, previous_kid: r.previous_kid, grace_period_seconds: emergency ? 0 : grace, emergency, provider: 'local', ...(discarded ? { discarded_staged_kid: discarded } : {}) });
195
+ return { status: 201, body: { object: 'signing_key_rotation', kid: r.kid, alg: r.alg, previous_kid: r.previous_kid, previous_retires_at: r.previous_retires_at, emergency, provider: 'local' } };
196
+ },
197
+ },
198
+ {
199
+ method: 'DELETE',
200
+ pattern: '/v1/instance/signing_keys/next',
201
+ scope: 'instance:write',
202
+ handler: async (c) => {
203
+ const kid = await c.engine.tokens.cancelStaged();
204
+ if (!kid)
205
+ throw new errors_1.EmulatorError('NOT_FOUND', 'No signing key is staged.');
206
+ (0, emu4_oauth_audit_1.recordAudit)(c.engine, 'signing_key.staged_canceled', 'api_key', 'instance', c.engine.instanceId, { kid });
207
+ return { body: { object: 'signing_key', kid, status: 'next', deleted: true } };
208
+ },
209
+ },
210
+ { method: 'GET', pattern: '/v1/instance/signing_key_policy', scope: 'instance:read', handler: (c) => ({ body: { object: 'signing_key_policy', prepublish_days: ks(c.engine).policyDays || null } }) },
211
+ {
212
+ method: 'PATCH',
213
+ pattern: '/v1/instance/signing_key_policy',
214
+ scope: 'instance:write',
215
+ handler: (c) => {
216
+ const d = c.body.prepublish_days;
217
+ if (d === undefined)
218
+ throw bad('prepublish_days is required (null or 0 turns it off).', 'prepublish_days');
219
+ if (d !== null && (typeof d !== 'number' || !Number.isInteger(d) || d < 0 || d > 90))
220
+ throw bad('prepublish_days must be a whole number of days from 1 to 90, or null / 0 to turn it off.', 'prepublish_days');
221
+ const state = ks(c.engine);
222
+ const before = state.policyDays || null;
223
+ state.policyDays = d ? d : null;
224
+ (0, emu4_oauth_audit_1.recordAudit)(c.engine, 'signing_key.policy_updated', 'api_key', 'instance', c.engine.instanceId, { before, after: state.policyDays });
225
+ return { body: { object: 'signing_key_policy', prepublish_days: state.policyDays } };
226
+ },
227
+ },
228
+ {
229
+ method: 'GET',
230
+ pattern: '/v1/instance/signing_key_schedule',
231
+ scope: 'instance:read',
232
+ handler: async (c) => {
233
+ await runSigningSchedule(c.engine);
234
+ return { body: scheduleView(c.engine, ks(c.engine).schedule) };
235
+ },
236
+ },
237
+ {
238
+ method: 'PUT',
239
+ pattern: '/v1/instance/signing_key_schedule',
240
+ scope: 'instance:write',
241
+ handler: (c) => {
242
+ const e = c.engine;
243
+ // The real route also asks for a recent MFA check; the emulator has no step-up state for the key.
244
+ const p = parseSchedule(c.body);
245
+ const state = ks(e);
246
+ const before = state.schedule;
247
+ state.schedule = { ...p, next_rotation_at: e.clock.now() + p.interval_days * DAY_MS, last_rotated_at: before?.last_rotated_at ?? null, last_error: null, last_error_at: null };
248
+ (0, emu4_oauth_audit_1.recordAudit)(e, 'signing_key_schedule.set', 'api_key', 'instance', e.instanceId, { interval_days: p.interval_days, alg: p.alg, grace_period_seconds: p.grace_period_seconds, prepublish_hours: p.prepublish_hours, enabled: p.enabled, previous_interval_days: before?.interval_days ?? null });
249
+ return { body: scheduleView(e, state.schedule) };
250
+ },
251
+ },
252
+ {
253
+ method: 'DELETE',
254
+ pattern: '/v1/instance/signing_key_schedule',
255
+ scope: 'instance:write',
256
+ handler: (c) => {
257
+ const state = ks(c.engine);
258
+ if (!state.schedule)
259
+ throw new errors_1.EmulatorError('NOT_FOUND', 'No rotation schedule is set.');
260
+ state.schedule = null;
261
+ (0, emu4_oauth_audit_1.recordAudit)(c.engine, 'signing_key_schedule.removed', 'api_key', 'instance', c.engine.instanceId);
262
+ return { body: { object: 'signing_key_schedule', enabled: false, deleted: true } };
263
+ },
264
+ },
265
+ { method: 'POST', pattern: '/__emulator/oauth/signing/run', public: true, handler: async (c) => ({ body: { object: 'signing_key_sweep', result: await runSigningSchedule(c.engine) } }) },
266
+ ];
267
+ }
268
+ //# sourceMappingURL=emu4-oauth-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emu4-oauth-keys.js","sourceRoot":"","sources":["../../src/handlers/emu4-oauth-keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { Engine, Reply, RouteContext, RouteDef } from '../engine';
2
+ import type { Obj } from '../openapi';
3
+ /**
4
+ * Verified OAuth publishers (`/v1/oauth_publishers`) and the Google access-token exchange, with the real rules.
5
+ *
6
+ * Publishers: a DNS TXT record (`_atlas-publisher.<domain>`, value `atlas-publisher-verification=...`) proves the
7
+ * domain; the emulator has no DNS, so `POST /__emulator/oauth/dns` plays the zone (a TXT record, or a transient
8
+ * lookup failure). Verified status is only ever set by `POST /v1/oauth_publishers/{id}/verify`.
9
+ *
10
+ * Google exchange: a first-party client trades a Google access token for an Atlas session at the token endpoint
11
+ * (`subject_token_type=urn:atlas:token-type:google_access_token`). The emulator has no Google; `POST
12
+ * /__emulator/google/tokens` registers the token Google would vouch for, and the checks Atlas makes against Google's
13
+ * tokeninfo and userinfo answers are the real ones.
14
+ */
15
+ export declare const MAX_PUBLISHERS = 50;
16
+ export declare const MAX_PUBLISHER_APPS = 200;
17
+ export declare const PUBLISHER_SKIP_SCOPES: Set<string>;
18
+ export declare const GOOGLE_ACCESS_TOKEN_TYPE = "urn:atlas:token-type:google_access_token";
19
+ /** Does an https homepage live on `domain` (or a subdomain of it)? */
20
+ export declare function homepageOnDomain(url: unknown, domain: string): boolean;
21
+ /** The verified publisher an app belongs to, or undefined. */
22
+ export declare function publisherOf(e: Engine, client: Obj): Obj | undefined;
23
+ /** The shared sector of the publisher an app belongs to (its subject settings are then the publisher's). */
24
+ export declare const publisherSectorOf: (e: Engine, client: Obj) => string | null;
25
+ /**
26
+ * The consent step for an app of a verified publisher: the name to show, and whether one consent covers the publisher's
27
+ * other apps (the publisher opted in, only openid/email/profile asked, and the user already consented to another
28
+ * enabled app of the publisher for at least those scopes).
29
+ */
30
+ export declare function publisherDecision(e: Engine, client: Obj, userId: string, requested: string[]): {
31
+ publisherName: string | null;
32
+ skipConsent: boolean;
33
+ };
34
+ /** The `urn:atlas:token-type:google_access_token` branch of the token-exchange grant. */
35
+ export declare function googleTokenExchange(c: RouteContext, client: Obj): Promise<Reply>;
36
+ export declare function emu4PublisherHandlers(): RouteDef[];