experimental-a2 0.7.0 → 0.8.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 (58) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/ai-server.d.ts +1 -1
  3. package/dist/ai-server.d.ts.map +1 -1
  4. package/dist/ai-server.js +13 -11
  5. package/dist/ai-server.js.map +1 -1
  6. package/dist/ai.d.ts +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/scheduler-qstash.d.ts +2 -2
  9. package/dist/scheduler-qstash.js +1 -1
  10. package/dist/scheduler-vercel.d.ts +2 -2
  11. package/dist/scheduler-vercel.js +1 -1
  12. package/dist/{server-286j79Mt.js → server-B2XNevQA.js} +123 -53
  13. package/dist/server-B2XNevQA.js.map +1 -0
  14. package/dist/{server-DgXmORIq.d.ts → server-DjPhHnbI.d.ts} +7 -4
  15. package/dist/server-DjPhHnbI.d.ts.map +1 -0
  16. package/dist/server.d.ts +3 -3
  17. package/dist/server.js +1 -1
  18. package/dist/store-N8PXxDAS.js.map +1 -1
  19. package/dist/{store-flRz1OWh.d.ts → store-RJO35BMj.d.ts} +25 -8
  20. package/dist/store-RJO35BMj.d.ts.map +1 -0
  21. package/dist/store-memory.d.ts +1 -1
  22. package/dist/store-memory.d.ts.map +1 -1
  23. package/dist/store-memory.js +79 -19
  24. package/dist/store-memory.js.map +1 -1
  25. package/dist/store-postgres.d.ts +1 -1
  26. package/dist/store-postgres.d.ts.map +1 -1
  27. package/dist/store-postgres.js +230 -101
  28. package/dist/store-postgres.js.map +1 -1
  29. package/dist/{store-redis-core-DEYO8Ryv.js → store-redis-core-DT01r4GZ.js} +167 -29
  30. package/dist/store-redis-core-DT01r4GZ.js.map +1 -0
  31. package/dist/store-redis-http.d.ts +1 -1
  32. package/dist/store-redis-http.js +2 -2
  33. package/dist/store-redis-http.js.map +1 -1
  34. package/dist/store-redis.d.ts +1 -1
  35. package/dist/store-redis.js +2 -2
  36. package/dist/store-redis.js.map +1 -1
  37. package/dist/store-sqlite.d.ts +1 -1
  38. package/dist/store-sqlite.d.ts.map +1 -1
  39. package/dist/store-sqlite.js +103 -19
  40. package/dist/store-sqlite.js.map +1 -1
  41. package/docs/concepts/02-handlers.mdx +4 -0
  42. package/docs/concepts/04-state.mdx +57 -9
  43. package/docs/guides/06-ai-agents.mdx +2 -1
  44. package/docs/reference/01-api.mdx +39 -16
  45. package/package.json +1 -1
  46. package/src/ai-server.ts +27 -10
  47. package/src/server.ts +242 -87
  48. package/src/store-memory.ts +138 -20
  49. package/src/store-postgres.ts +355 -138
  50. package/src/store-redis-core.ts +201 -27
  51. package/src/store-redis-http.ts +1 -1
  52. package/src/store-redis.ts +1 -1
  53. package/src/store-sqlite.ts +191 -34
  54. package/src/store.ts +27 -9
  55. package/dist/server-286j79Mt.js.map +0 -1
  56. package/dist/server-DgXmORIq.d.ts.map +0 -1
  57. package/dist/store-flRz1OWh.d.ts.map +0 -1
  58. package/dist/store-redis-core-DEYO8Ryv.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-B2XNevQA.js","names":[],"sources":["../src/platform.ts","../src/push-envelope.ts","../src/session-socket.ts","../src/sse.ts","../src/server-fetch.ts","../src/deterministic-id.ts","../src/telemetry.ts","../src/server.ts"],"sourcesContent":["/**\n * Platform seams, read from the ambient request context — the same\n * channel `@vercel/functions` uses (`Symbol.for('@vercel/request-context')`)\n * — with no dependency on that package. Where no context exists (local\n * dev, long-lived servers, other clouds) everything degrades cleanly:\n * `waitUntil` becomes a no-op (background work is tracked in-process\n * anyway) and the deadline is unknown (claim watchdogs use their ordinary\n * TTL window).\n *\n * Tests exercise these paths by installing a real context object on the\n * symbol — simulating the platform contract, not mocking a2.\n */\n\ntype RequestContext = {\n headers?: Readonly<Record<string, string>>\n waitUntil?: (promise: Promise<unknown>) => void\n /**\n * When the platform will terminate this invocation (epoch ms, ISO\n * string, or Date) — on Vercel this includes `waitUntil` work.\n */\n deadline?: number | string | Date\n}\n\nconst SYMBOL_FOR_REQ_CONTEXT = Symbol.for('@vercel/request-context')\n\nfunction requestContext(): RequestContext {\n try {\n const holder = Reflect.get(globalThis, SYMBOL_FOR_REQ_CONTEXT) as\n { get?: () => RequestContext | undefined } | undefined\n return holder?.get?.() ?? {}\n } catch {\n return {}\n }\n}\n\n/** The current invocation's Vercel deployment identity, when available. */\nexport function platformVercelOidcToken(): string | null {\n try {\n const token = requestContext().headers?.['x-vercel-oidc-token']\n return typeof token === 'string' && token.length > 0 ? token : null\n } catch {\n return null\n }\n}\n\nexport function platformWaitUntil(promise: Promise<unknown>): void {\n try {\n requestContext().waitUntil?.(promise)\n } catch {\n // Best-effort — the promise is tracked in-process either way.\n }\n}\n\n/** The invocation's termination time in epoch ms, or null if unknowable. */\nexport function invocationDeadlineMs(): number | null {\n const deadline = requestContext().deadline\n if (deadline === undefined || deadline === null) return null\n const ms = new Date(deadline as number | string | Date).getTime()\n return Number.isNaN(ms) ? null : ms\n}\n","/**\n * The push envelope's trust boundary for `{ sessionId, events, presence? }`,\n * shared verbatim by the HTTP\n * POST lane and the socket's push/presence frames so INVALID_PAYLOAD\n * shapes are one implementation. Internal module, not public API.\n */\n\nimport { A2Error } from './errors.ts'\nimport { MAX_DATE_MS, RESERVED_PARTICIPANT_IDS } from './internal.ts'\n\nexport type ParsedPushEvent = {\n type: string\n payload: unknown\n id?: string\n}\n\nexport type ParsedPushPresence = {\n participant: string\n values: Record<string, unknown>\n seen?: number\n at?: number\n}\n\nexport const invalidPushBody = (message: string): A2Error =>\n new A2Error('INVALID_PAYLOAD', `malformed push body: ${message}`)\n\nconst invalid = invalidPushBody\n\nexport type PushBody = {\n sessionId: string\n events: ParsedPushEvent[]\n presence?: ParsedPushPresence\n}\n\nexport function parsePresenceSibling(\n value: unknown,\n): ParsedPushPresence | undefined {\n if (value === undefined) return undefined\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw invalid('presence must be an object when present')\n }\n const { participant, values, seen, at } = value as Record<string, unknown>\n if (typeof participant !== 'string' || participant.length === 0) {\n throw invalid('presence.participant must be a non-empty string')\n }\n if (RESERVED_PARTICIPANT_IDS.has(participant)) {\n throw invalid(`presence.participant must not be '${participant}'`)\n }\n if (values === null || typeof values !== 'object' || Array.isArray(values)) {\n throw invalid('presence.values must be an object')\n }\n if (\n seen !== undefined &&\n (typeof seen !== 'number' || !Number.isFinite(seen) || seen < 0)\n ) {\n throw invalid('presence.seen must be a non-negative number when present')\n }\n if (\n at !== undefined &&\n (typeof at !== 'number' ||\n !Number.isFinite(at) ||\n at < 0 ||\n at > MAX_DATE_MS)\n ) {\n throw invalid(\n 'presence.at must be a non-negative epoch-milliseconds timestamp within the Date range when present',\n )\n }\n const out: {\n participant: string\n values: Record<string, unknown>\n seen?: number\n at?: number\n } = { participant, values: values as Record<string, unknown> }\n if (seen !== undefined) out.seen = seen\n if (at !== undefined) out.at = at\n return out\n}\n\n/** The events half of the envelope, shared by the POST body and socket\n * `push` frames so INVALID_PAYLOAD shapes have one implementation. */\nexport function parsePushEvents(events: unknown): ParsedPushEvent[] {\n if (!Array.isArray(events) || events.length === 0) {\n throw invalid('events must be a non-empty array')\n }\n return events.map((event, i) => {\n if (event === null || typeof event !== 'object') {\n throw invalid(`events[${i}] must be an object`)\n }\n const { type, payload, id } = event as Record<string, unknown>\n if (typeof type !== 'string' || type.length === 0) {\n throw invalid(`events[${i}].type must be a non-empty string`)\n }\n if (id !== undefined && typeof id !== 'string') {\n throw invalid(`events[${i}].id must be a string when present`)\n }\n const out: { type: string; payload: unknown; id?: string } = {\n type,\n payload,\n }\n if (id !== undefined) out.id = id\n return out\n })\n}\n\n/**\n * Validate the push envelope — `{ sessionId, events, presence? }` —\n * throwing `INVALID_PAYLOAD` on a malformed body. Payload validation\n * against the machine's schemas happens in `append` and `setPresence`,\n * not here. Either plane may appear alone: a presence-only push has no\n * (or empty) `events`.\n */\nexport async function parsePushBody(req: Request): Promise<PushBody> {\n let body: unknown\n try {\n body = await req.json()\n } catch (cause) {\n throw new A2Error('INVALID_PAYLOAD', 'push body is not valid JSON', {\n cause,\n })\n }\n if (body === null || typeof body !== 'object') {\n throw invalid('expected an object')\n }\n const { sessionId, events, presence } = body as Record<string, unknown>\n if (typeof sessionId !== 'string' || sessionId.length === 0) {\n throw invalid('sessionId must be a non-empty string')\n }\n const parsedPresence = parsePresenceSibling(presence)\n if (\n parsedPresence !== undefined &&\n (events === undefined || (Array.isArray(events) && events.length === 0))\n ) {\n return { sessionId, events: [], presence: parsedPresence }\n }\n const parsed = parsePushEvents(events)\n return parsedPresence !== undefined\n ? { sessionId, events: parsed, presence: parsedPresence }\n : { sessionId, events: parsed }\n}\n","/**\n * The A2 socket protocol's server half (specs/a2-api.md §13): the\n * per-socket shell — teardown, backpressure, heartbeat, the malformed\n * budget, the in-flight bound — and `sessionsSocket`, the multiplexed\n * frame handler riding it. Internal module: `handle`'s upgrade lane is\n * the sanctioned mount; only `A2Socket` (the structural socket the\n * platform hands over) is re-exported as public surface.\n */\n\nimport { A2Error } from './errors.ts'\nimport { SOCKET_TIMINGS, STREAM_TIMINGS } from './internal.ts'\nimport type { Event } from './store.ts'\nimport type { EventDefs, PresencePatch, PresenceSnapshot } from './contract.ts'\nimport type { ParsedPushEvent, ParsedPushPresence } from './push-envelope.ts'\nimport type { Session } from './server.ts'\nimport { parsePresenceSibling, parsePushEvents } from './push-envelope.ts'\nimport {\n SOCKET_PING_FRAME,\n asA2Error,\n socketAckFor,\n socketErrorAckFor,\n socketFrameFor,\n socketSubscribedFor,\n socketUnsubscribedFor,\n} from './wire.ts'\n\n// ── the ws wire ───────────────────────────────────────────────────────\n\n/**\n * The structural socket `sessionsSocket` speaks against — satisfied\n * by `ws` and by `@vercel/functions`' upgraded socket alike, so the\n * platform upgrade API stays out of the library. `message` data\n * arrives as whatever the platform delivers (string, Buffer,\n * ArrayBuffer, or fragments); the handler normalizes defensively.\n */\nexport type A2Socket = {\n send(data: string): void\n on(event: 'message', listener: (data: unknown) => void): void\n on(event: 'close', listener: () => void): void\n on(event: 'error', listener: (error: unknown) => void): void\n close(code?: number, reason?: string): void\n /** Bytes queued but not yet transmitted — when exposed, the down\n * pump uses it for backpressure (`SOCKET_TIMINGS`). */\n bufferedAmount?: number\n}\n\nconst messageText = (data: unknown): string | null => {\n if (typeof data === 'string') return data\n if (data instanceof ArrayBuffer) return new TextDecoder().decode(data)\n if (ArrayBuffer.isView(data)) return new TextDecoder().decode(data)\n if (Array.isArray(data) && data.every(ArrayBuffer.isView)) {\n // ws delivers fragmented messages as a Buffer array; stream-decode\n // so multi-byte characters can span fragment boundaries.\n const decoder = new TextDecoder()\n let text = ''\n for (const part of data) text += decoder.decode(part, { stream: true })\n return text + decoder.decode()\n }\n return null\n}\n\n/**\n * How many unparseable or invalid frames a socket may send before it\n * is closed (1008): the budget absorbs isolated client bugs without\n * letting a broken peer spin the validation path forever. Push frames\n * with a usable `req` never count — their failures are answered with\n * error acks, exactly like the POST path's 4xx bodies.\n */\nconst MAX_MALFORMED_FRAMES = 5\n\n/**\n * The pump's runtime view of a session. The presence members are\n * conditional on the public surface (`WithPresence`) and therefore\n * invisible on a generic `Session<D>`, so capability is checked at\n * runtime (`setPresence` present). The cast stays inside the transport.\n */\nexport type SocketSession = {\n stream(opts: {\n startAfter: number\n presence?: boolean\n }): AsyncIterable<Event | PresencePatch | PresenceSnapshot>\n append(...events: ParsedPushEvent[]): Promise<Event[]>\n setPresence?(patch: ParsedPushPresence): Promise<void>\n}\n\n/**\n * The per-socket machinery `sessionsSocket` builds on: the torn flag\n * with a release-once teardown, the backpressure-aware send with its\n * non-reader ceiling, the malformed budget, the in-flight bound, the\n * message normalization, the heartbeat, and the optional deadline.\n */\ntype SocketShell = {\n torn(): boolean\n send(data: string): void\n shutdown(code: number, reason?: string): void\n malformedFrame(reason: string): void\n buffered(): number\n overCap(): boolean\n track(work: Promise<void>): void\n}\n\nfunction socketShell(\n socket: A2Socket,\n release: () => void,\n onFrame: (frame: Record<string, unknown>) => void,\n deadlineAt: number | undefined,\n): SocketShell {\n let torn = false\n let malformed = 0\n let heartbeat: ReturnType<typeof setInterval> | undefined\n let deadline: ReturnType<typeof setTimeout> | undefined\n\n const teardown = (): void => {\n if (torn) return\n torn = true\n if (heartbeat !== undefined) clearInterval(heartbeat)\n if (deadline !== undefined) clearTimeout(deadline)\n release()\n }\n\n const shutdown = (code: number, reason?: string): void => {\n if (torn) return\n teardown()\n try {\n socket.close(code, reason)\n } catch {\n // Already closed underneath us — teardown has run either way.\n }\n }\n\n const send = (data: string): void => {\n if (torn) return\n // The pump parks at the high-water mark, but acks and pings are\n // exempt (small, correctness-relevant) — so a peer that never\n // reads while it keeps uploading grows the buffer through its own\n // acks. The ceiling closes the class: past it, the peer is not a\n // slow reader, it is a non-reader (adversarial F4).\n if (\n typeof socket.bufferedAmount === 'number' &&\n socket.bufferedAmount > SOCKET_TIMINGS.disconnectWaterMarkBytes\n ) {\n shutdown(1008, 'backpressure: peer not reading')\n return\n }\n try {\n socket.send(data)\n } catch {\n // The platform closed the socket without an event; closing it\n // again would throw the same way, so just tear down.\n teardown()\n }\n }\n\n const malformedFrame = (reason: string): void => {\n malformed += 1\n if (malformed >= MAX_MALFORMED_FRAMES) {\n shutdown(1008, `too many malformed frames (last: ${reason})`)\n }\n }\n\n // The up-lane bound (adversarial F3): one socket must not hold\n // unbounded concurrent appends. Shedding is per-plane semantics —\n // pushes are TOLD (retryable error ack, ids make the retry safe),\n // presence is silently dropped (a lost update is repainted by the\n // next one). Sheds are our load decision, never the peer's\n // malformedness, so they spend no budget.\n let inFlight = 0\n const track = (work: Promise<void>): void => {\n inFlight += 1\n void work.finally(() => {\n inFlight -= 1\n })\n }\n\n const handleMessage = (data: unknown): void => {\n if (torn) return\n const text = messageText(data)\n if (text === null) {\n malformedFrame('non-text frame')\n return\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n malformedFrame('frame is not valid JSON')\n return\n }\n if (\n parsed === null ||\n typeof parsed !== 'object' ||\n Array.isArray(parsed)\n ) {\n malformedFrame('frame is not an object')\n return\n }\n onFrame(parsed as Record<string, unknown>)\n }\n\n socket.on('message', handleMessage)\n socket.on('close', teardown)\n socket.on('error', teardown)\n\n heartbeat = setInterval(\n () => send(SOCKET_PING_FRAME),\n STREAM_TIMINGS.sseHeartbeatMs,\n )\n ;(heartbeat as { unref?: () => void }).unref?.()\n\n if (deadlineAt !== undefined) {\n deadline = setTimeout(\n () => shutdown(1000, 'deadline'),\n Math.max(0, deadlineAt - Date.now()),\n )\n ;(deadline as { unref?: () => void }).unref?.()\n }\n\n return {\n torn: () => torn,\n send,\n shutdown,\n malformedFrame,\n buffered: () =>\n typeof socket.bufferedAmount === 'number' ? socket.bufferedAmount : 0,\n overCap: () => inFlight >= SOCKET_TIMINGS.maxInFlightMessages,\n track,\n }\n}\n\n/**\n * The per-session authorization seam of `sessionsSocket`: called once\n * per `subscribe` entry (and never for the pushes and presence that\n * ride an accepted subscription). `null` rejects that session — the\n * socket answers `unsubscribed` with a rejection reason and every\n * other session on it is untouched.\n */\nexport type SessionsSocketResolve<D extends EventDefs> = (\n sessionId: string,\n /** The entry's resume frontier — `stream({ startAfter })`. */\n startAfter: number,\n) =>\n Pick<Session<D>, 'stream'> | null | Promise<Pick<Session<D>, 'stream'> | null>\n\nexport type SessionsSocketOptions = {\n /** The `stream()` presence opt-in for every session on the socket —\n * the server decides, same rule as the SSE route. */\n presence?: boolean\n /** Epoch ms: close cleanly (code 1000) at this time, ahead of a known\n * platform deadline, so clients reconnect on our schedule. */\n deadline?: number\n /** Runs after frame parsing and before append or presence I/O. */\n gatePush?(\n sessionId: string,\n events: ParsedPushEvent[],\n presence?: ParsedPushPresence,\n ): A2Error | null | Promise<A2Error | null>\n}\n\ntype SocketSubscription = {\n target: SocketSession\n iterator: AsyncIterator<Event | PresencePatch | PresenceSnapshot>\n stopped: boolean\n}\n\nconst stopSubscription = (subscription: SocketSubscription): void => {\n subscription.stopped = true\n void subscription.iterator.return?.()?.catch(() => {})\n}\n\nconst parseSubscribeEntries = (\n value: unknown,\n): Array<{ id: string; index: number }> | null => {\n if (!Array.isArray(value) || value.length === 0) return null\n const entries: Array<{ id: string; index: number }> = []\n for (const entry of value) {\n if (entry === null || typeof entry !== 'object') return null\n const { id, index } = entry as Record<string, unknown>\n if (typeof id !== 'string' || id.length === 0) return null\n if (typeof index !== 'number' || !Number.isInteger(index) || index < 0) {\n return null\n }\n entries.push({ id, index })\n }\n return entries\n}\n\n/**\n * Speak the multiplexed A2 socket protocol (specs/a2-api.md §13)\n * against many sessions on one socket. `subscribe` frames open a\n * per-session pump at that session's own resume frontier; push and\n * presence frames route by `sessionId` through the same validation\n * seams as the POST lane; every down frame carries the `sessionId` it\n * belongs to. One heartbeat, one\n * malformed budget, one in-flight bound, one backpressure gauge — per\n * socket, shared by all sessions. A session's stream ending or failing\n * answers `unsubscribed` for that session; only the peer, the\n * deadline, the malformed budget, or backpressure closes the socket.\n */\nexport function sessionsSocket<D extends EventDefs>(\n resolve: SessionsSocketResolve<D>,\n socket: A2Socket,\n options?: SessionsSocketOptions,\n): void {\n const presence = options?.presence === true\n const subscriptions = new Map<string, SocketSubscription>()\n\n const retire = (id: string, subscription: SocketSubscription): void => {\n if (subscriptions.get(id) === subscription) subscriptions.delete(id)\n }\n\n const pump = async (\n id: string,\n subscription: SocketSubscription,\n ): Promise<void> => {\n for (;;) {\n for (;;) {\n if (\n shell.torn() ||\n subscription.stopped ||\n shell.buffered() <= SOCKET_TIMINGS.highWaterMarkBytes\n )\n break\n // oxlint-disable-next-line no-await-in-loop -- backpressure park\n await new Promise((wake) =>\n setTimeout(wake, SOCKET_TIMINGS.resumePollMs),\n )\n }\n if (shell.torn() || subscription.stopped) return\n // oxlint-disable-next-line no-await-in-loop -- stream pump\n const { value, done } = await subscription.iterator.next()\n if (shell.torn() || subscription.stopped) return\n if (done) return\n shell.send(socketFrameFor(value, id))\n }\n }\n\n const runSubscription = async (\n id: string,\n subscription: SocketSubscription,\n ): Promise<void> => {\n try {\n await pump(id, subscription)\n if (shell.torn() || subscription.stopped) return\n retire(id, subscription)\n shell.send(socketUnsubscribedFor(id))\n } catch {\n if (shell.torn() || subscription.stopped) return\n retire(id, subscription)\n shell.send(socketUnsubscribedFor(id, 'stream failed'))\n }\n }\n\n const startSubscription = async (\n id: string,\n index: number,\n ): Promise<void> => {\n let session: Pick<Session<D>, 'stream'> | null\n try {\n session = await resolve(id, index)\n } catch {\n if (!shell.torn()) {\n shell.send(socketUnsubscribedFor(id, 'stream failed'))\n }\n return\n }\n if (shell.torn()) return\n if (session === null) {\n shell.send(socketUnsubscribedFor(id, 'subscribe rejected'))\n return\n }\n const target = session as unknown as SocketSession\n const existing = subscriptions.get(id)\n if (existing) stopSubscription(existing)\n const iterator = (\n presence\n ? target.stream({ startAfter: index, presence: true })\n : target.stream({ startAfter: index })\n )[Symbol.asyncIterator]()\n const subscription: SocketSubscription = {\n target,\n iterator,\n stopped: false,\n }\n subscriptions.set(id, subscription)\n shell.send(socketSubscribedFor(id))\n void runSubscription(id, subscription)\n }\n\n // Control frames (subscribe/unsubscribe) run in arrival order — an\n // unsubscribe can never overtake the subscribe it targets while the\n // resolve hook is still pending.\n let controlTail: Promise<void> = Promise.resolve()\n const control = (work: () => Promise<void> | void): void => {\n controlTail = controlTail.then(work).catch(() => {})\n }\n\n const handlePush = async (\n frame: Record<string, unknown>,\n req: number,\n sessionId: string,\n ): Promise<void> => {\n const subscription = subscriptions.get(sessionId)\n if (subscription === undefined) {\n // Retryable: the client re-subscribes on reconnect and the retry\n // rides the same client-generated event ids.\n shell.send(\n socketErrorAckFor(\n req,\n new A2Error(\n 'STORE_UNAVAILABLE',\n 'session is not subscribed on this socket',\n ),\n sessionId,\n ),\n )\n return\n }\n try {\n const events = parsePushEvents(frame['events'])\n const denial =\n (await options?.gatePush?.(sessionId, events, undefined)) ?? null\n if (denial !== null) {\n shell.send(socketErrorAckFor(req, denial, sessionId))\n return\n }\n const appended = await subscription.target.append(...events)\n shell.send(socketAckFor(req, appended, sessionId))\n } catch (err) {\n shell.send(socketErrorAckFor(req, asA2Error(err), sessionId))\n }\n }\n\n const handlePresence = async (\n frame: Record<string, unknown>,\n sessionId: string,\n ): Promise<void> => {\n const subscription = subscriptions.get(sessionId)\n // An unsubscribe race, not malformedness — the plane repaints.\n if (subscription === undefined) return\n if (typeof subscription.target.setPresence !== 'function') {\n shell.malformedFrame('presence frame on a presence-less session')\n return\n }\n let patch: ParsedPushPresence | undefined\n try {\n patch = parsePresenceSibling(frame)\n } catch {\n shell.malformedFrame('invalid presence frame')\n return\n }\n if (!patch) return\n try {\n const denial = (await options?.gatePush?.(sessionId, [], patch)) ?? null\n if (denial !== null) return\n await subscription.target.setPresence(patch)\n } catch (error) {\n const failure = asA2Error(error)\n if (\n failure.code === 'INVALID_PAYLOAD' ||\n failure.code === 'UNKNOWN_PRESENCE_FIELD'\n ) {\n shell.malformedFrame('invalid presence frame')\n return\n }\n shell.shutdown(1011, 'internal error')\n }\n }\n\n const handleFrame = (frame: Record<string, unknown>): void => {\n switch (frame['kind']) {\n case 'subscribe': {\n const entries = parseSubscribeEntries(frame['sessions'])\n if (entries === null) {\n shell.malformedFrame('malformed subscribe frame')\n return\n }\n for (const entry of entries) {\n control(() => startSubscription(entry.id, entry.index))\n }\n return\n }\n case 'unsubscribe': {\n const ids = frame['sessions']\n if (\n !Array.isArray(ids) ||\n ids.length === 0 ||\n !ids.every((id) => typeof id === 'string')\n ) {\n shell.malformedFrame('malformed unsubscribe frame')\n return\n }\n for (const id of ids as string[]) {\n control(() => {\n const subscription = subscriptions.get(id)\n if (subscription === undefined) return\n stopSubscription(subscription)\n subscriptions.delete(id)\n })\n }\n return\n }\n case 'push': {\n const req = frame['req']\n const sessionId = frame['sessionId']\n if (shell.overCap()) {\n if (typeof req === 'number') {\n shell.send(\n socketErrorAckFor(\n req,\n new A2Error(\n 'STORE_UNAVAILABLE',\n 'push shed: too many in flight on this socket',\n ),\n typeof sessionId === 'string' ? sessionId : undefined,\n ),\n )\n } else {\n shell.malformedFrame('push frame without a numeric req')\n }\n return\n }\n if (typeof req !== 'number') {\n shell.malformedFrame('push frame without a numeric req')\n return\n }\n if (typeof sessionId !== 'string' || sessionId.length === 0) {\n shell.send(\n socketErrorAckFor(\n req,\n new A2Error('INVALID_PAYLOAD', 'push frame without a sessionId'),\n ),\n )\n return\n }\n shell.track(handlePush(frame, req, sessionId))\n return\n }\n case 'presence': {\n if (shell.overCap()) return\n const sessionId = frame['sessionId']\n if (typeof sessionId !== 'string' || sessionId.length === 0) {\n shell.malformedFrame('presence frame without a sessionId')\n return\n }\n shell.track(handlePresence(frame, sessionId))\n return\n }\n default:\n return // unknown kinds are skipped — the forward-compatibility rule\n }\n }\n\n const shell = socketShell(\n socket,\n () => {\n for (const subscription of subscriptions.values()) {\n stopSubscription(subscription)\n }\n subscriptions.clear()\n },\n (frame) => handleFrame(frame),\n options?.deadline,\n )\n}\n","/**\n * The SSE response protocol — framing, heartbeat, deadline, and\n * teardown for the live stream lane. Internal module: `server.fetch` is\n * the sanctioned caller; the framing rules stay\n * documented on `sseResponse` because the client's parser (and the\n * stall watchdog) depend on them.\n */\n\nimport { STREAM_TIMINGS } from './internal.ts'\nimport type { Event } from './store.ts'\nimport type { PresencePatch, PresenceSnapshot } from './contract.ts'\nimport { invocationDeadlineMs } from './platform.ts'\nimport {\n eventToWire,\n presencePatchToWire,\n presenceSnapshotToWire,\n} from './wire.ts'\n\n/**\n * Pipe a live event iterable into an SSE `Response`. Each event is one\n * frame — `id:` carries the event-log index, `data:` the JSON event. A\n * `stream({ presence: true })` iterable also yields presence items,\n * which ride as named frames old clients skip: `event:\n * presence-snapshot` first (the map, ISO dates), then `event: presence`\n * per patch — no `id:`, presence never advances the resume frontier. A\n * disconnecting client cancels the stream, which closes the underlying\n * subscription. Two kinds of comment frames ride along: a `: connected`\n * prelude that flushes headers immediately, and a `: ping` heartbeat\n * every 15 seconds so clients (and proxies) can tell a quiet stream\n * from a dead connection — the session client's stall watchdog counts\n * on it. When the platform exposes an invocation deadline, the response\n * closes cleanly one second before it so the client reconnects without\n * a platform-timeout failure.\n */\nexport function sseResponse(\n iterable: AsyncIterable<Event | PresencePatch | PresenceSnapshot>,\n): Response {\n const iterator = iterable[Symbol.asyncIterator]()\n const encoder = new TextEncoder()\n let heartbeat: ReturnType<typeof setInterval> | undefined\n let deadlineTimer: ReturnType<typeof setTimeout> | undefined\n let closed = false\n let iteratorReturned = false\n const stopTimers = (): void => {\n if (heartbeat !== undefined) clearInterval(heartbeat)\n if (deadlineTimer !== undefined) clearTimeout(deadlineTimer)\n heartbeat = undefined\n deadlineTimer = undefined\n }\n const returnIterator = async (): Promise<void> => {\n if (iteratorReturned) return\n iteratorReturned = true\n await iterator.return?.()\n }\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n // Prelude comment frame: flushes headers immediately (a fresh\n // session may otherwise send nothing for a long time — some\n // servers buffer headers until the first byte, and clients can't\n // report \"live\" until they see the response), and gives proxies\n // early proof this is a stream. Comment frames are invisible to\n // SSE consumers.\n controller.enqueue(encoder.encode(': connected\\n\\n'))\n // Heartbeat: comment frames are ignored by SSE parsers but are\n // bytes on the wire — liveness proof for the client's watchdog\n // and for idle-timeout-happy intermediaries.\n heartbeat = setInterval(() => {\n try {\n controller.enqueue(encoder.encode(': ping\\n\\n'))\n } catch {\n // The stream closed underneath the timer.\n stopTimers()\n }\n }, STREAM_TIMINGS.sseHeartbeatMs)\n ;(heartbeat as { unref?: () => void }).unref?.()\n\n const invocationDeadline = invocationDeadlineMs()\n if (invocationDeadline !== null) {\n const delay = Math.max(\n 0,\n invocationDeadline - Date.now() - STREAM_TIMINGS.sseDeadlineGraceMs,\n )\n deadlineTimer = setTimeout(() => {\n if (closed) return\n closed = true\n stopTimers()\n void returnIterator().catch(() => {})\n try {\n controller.close()\n } catch {\n // The response already closed underneath the timer.\n }\n }, delay)\n ;(deadlineTimer as { unref?: () => void }).unref?.()\n }\n },\n async pull(controller) {\n try {\n const { value, done } = await iterator.next()\n if (closed) return\n if (done) {\n closed = true\n stopTimers()\n controller.close()\n return\n }\n controller.enqueue(encoder.encode(frameFor(value)))\n } catch (error) {\n if (closed) return\n closed = true\n stopTimers()\n void returnIterator().catch(() => {})\n throw error\n }\n },\n async cancel() {\n if (closed) return\n closed = true\n stopTimers()\n await returnIterator()\n },\n })\n return new Response(stream, {\n status: 200,\n headers: {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache, no-transform',\n connection: 'keep-alive',\n },\n })\n}\n\nfunction frameFor(item: Event | PresencePatch | PresenceSnapshot): string {\n if ('snapshot' in item) {\n return `event: presence-snapshot\\ndata: ${JSON.stringify(presenceSnapshotToWire(item))}\\n\\n`\n }\n if ('participant' in item) {\n return `event: presence\\ndata: ${JSON.stringify(presencePatchToWire(item))}\\n\\n`\n }\n return `id: ${item.index}\\ndata: ${JSON.stringify(eventToWire(item))}\\n\\n`\n}\n","import type {\n AppendInput,\n ContractEvent,\n EventDefs,\n PresenceDefs,\n} from './contract.ts'\nimport { A2Error } from './errors.ts'\nimport { invocationDeadlineMs } from './platform.ts'\nimport {\n invalidPushBody,\n parsePushBody,\n type ParsedPushEvent,\n type ParsedPushPresence,\n} from './push-envelope.ts'\nimport type { A2Server } from './server.ts'\nimport {\n sessionsSocket,\n type A2Socket,\n type SocketSession,\n} from './session-socket.ts'\nimport { sseResponse } from './sse.ts'\nimport { asA2Error, errorStatus, errorToWire, eventToWire } from './wire.ts'\n\ntype SuggestedEventType<D extends EventDefs> =\n (keyof D & string) | (string & Record<never, never>)\n\ntype SuggestedPresenceValues<P extends PresenceDefs> = Readonly<\n { [F in keyof P & string]?: unknown } & Record<string, unknown>\n>\n\nexport type A2PushEvent<D extends EventDefs = EventDefs> = {\n readonly type: SuggestedEventType<D>\n readonly payload: unknown\n readonly id?: string\n}\n\nexport type A2PushPresence<P extends PresenceDefs = PresenceDefs> = {\n readonly participant: string\n readonly values: SuggestedPresenceValues<P>\n readonly seen?: number\n readonly at?: number\n}\n\nexport type A2Operation<\n D extends EventDefs = EventDefs,\n P extends PresenceDefs = Record<never, never>,\n> =\n | {\n readonly type: 'stream'\n readonly sessionId: string\n readonly startAfter: number\n readonly transport: 'http' | 'websocket'\n }\n | {\n readonly type: 'history'\n readonly sessionId: string\n readonly gte: number\n readonly lte: number\n readonly transport: 'http'\n }\n | {\n readonly type: 'push'\n readonly sessionId: string\n readonly events: readonly A2PushEvent<D>[]\n readonly presence?: A2PushPresence<P>\n readonly transport: 'http' | 'websocket'\n }\n\nexport type UpgradeWebSocket = (\n attach: (socket: A2Socket) => void,\n) => Response | Promise<Response>\n\nexport type ServerFetchOptions<\n D extends EventDefs = EventDefs,\n P extends PresenceDefs = Record<never, never>,\n> = {\n authorize?: (operation: A2Operation<D, P>) => boolean | Promise<boolean>\n upgradeWebSocket?: UpgradeWebSocket\n}\n\nexport type ServerIngressContext = {\n sessionId: string\n events: readonly ParsedPushEvent[]\n presence?: ParsedPushPresence\n}\n\ntype ServerFetchHooks = {\n validateIngress?(context: ServerIngressContext): void | PromiseLike<void>\n}\n\nconst serverFetchHooks = new WeakMap<object, ServerFetchHooks>()\n\nexport function setServerFetchHooks<\n D extends EventDefs,\n P extends PresenceDefs,\n>(server: Pick<A2Server<D, P>, 'fetch'>, hooks: ServerFetchHooks): void {\n serverFetchHooks.set(server.fetch, hooks)\n}\n\ntype FetchServer<D extends EventDefs, P extends PresenceDefs> = Pick<\n A2Server<D, P>,\n 'contract' | 'session'\n>\n\ntype ServerFetch<D extends EventDefs, P extends PresenceDefs> = {\n (request: Request): Promise<Response>\n (request: Request, options: ServerFetchOptions<D, P>): Promise<Response>\n}\n\nconst parseHistoryBounds = (\n gte: string | null,\n lte: string | null,\n): { gte: number; lte: number } => {\n if (gte === null || lte === null) {\n throw new A2Error(\n 'INVALID_PAYLOAD',\n 'a history read takes both gte and lte',\n )\n }\n const bounds = { gte: Number(gte), lte: Number(lte) }\n for (const [name, value] of Object.entries(bounds)) {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new A2Error(\n 'INVALID_PAYLOAD',\n `history ${name} must be a non-negative safe integer`,\n )\n }\n }\n if (bounds.gte > bounds.lte) {\n throw new A2Error(\n 'INVALID_PAYLOAD',\n 'history gte must be less than or equal to lte',\n )\n }\n return bounds\n}\n\nconst parseResumeIndex = (raw: string | null): number => {\n if (raw === null) return 0\n const index = Number(raw)\n if (!Number.isSafeInteger(index) || index < 0) {\n throw new A2Error(\n 'INVALID_PAYLOAD',\n 'stream index must be a non-negative safe integer',\n )\n }\n return index\n}\n\nconst errorResponse = (error: unknown): Response => {\n const a2error = asA2Error(error)\n return Response.json(errorToWire(a2error), {\n status: errorStatus(a2error.code),\n })\n}\n\nconst forbidden = (): A2Error =>\n new A2Error('FORBIDDEN', 'the operation is not authorized')\n\nconst freezePush = <D extends EventDefs, P extends PresenceDefs>(\n sessionId: string,\n events: ParsedPushEvent[],\n presence: ParsedPushPresence | undefined,\n transport: 'http' | 'websocket',\n): A2Operation<D, P> & { type: 'push' } => {\n for (const event of events) Object.freeze(event)\n Object.freeze(events)\n if (presence !== undefined) {\n Object.freeze(presence.values)\n Object.freeze(presence)\n }\n return {\n type: 'push',\n sessionId,\n events,\n ...(presence === undefined\n ? {}\n : { presence: presence as A2PushPresence<P> }),\n transport,\n }\n}\n\nexport function createServerFetch<\n D extends EventDefs,\n P extends PresenceDefs = Record<never, never>,\n>(server: FetchServer<D, P>): ServerFetch<D, P> {\n const presence = Object.keys(server.contract.presence).length > 0\n\n const fetch = async (\n request: Request,\n options?: ServerFetchOptions<D, P>,\n ): Promise<Response> => {\n const authorized = async (\n operation: A2Operation<D, P>,\n ): Promise<boolean> => {\n try {\n return (await options?.authorize?.(Object.freeze(operation))) !== false\n } catch (cause) {\n throw new A2Error('STORE_UNAVAILABLE', 'authorization failed', {\n cause,\n })\n }\n }\n\n const authorize = async (operation: A2Operation<D, P>): Promise<void> => {\n if (!(await authorized(operation))) throw forbidden()\n }\n\n const validateIngress = async (\n context: ServerIngressContext,\n ): Promise<void> => {\n await serverFetchHooks.get(fetch)?.validateIngress?.(context)\n }\n\n const attach = (socket: A2Socket): void => {\n const deadline = invocationDeadlineMs()\n sessionsSocket<D>(\n async (sessionId, startAfter) => {\n const operation: A2Operation<D, P> = {\n type: 'stream',\n sessionId,\n startAfter,\n transport: 'websocket',\n }\n return (await authorized(operation))\n ? server.session(sessionId)\n : null\n },\n socket,\n {\n presence,\n ...(deadline === null ? {} : { deadline }),\n gatePush: async (sessionId, events, pushedPresence) => {\n try {\n await authorize(\n freezePush<D, P>(\n sessionId,\n events,\n pushedPresence,\n 'websocket',\n ),\n )\n await validateIngress({\n sessionId,\n events,\n ...(pushedPresence === undefined\n ? {}\n : { presence: pushedPresence }),\n })\n return null\n } catch (error) {\n return asA2Error(error)\n }\n },\n },\n )\n }\n\n try {\n if (request.method === 'GET') {\n if (request.headers.get('upgrade')?.toLowerCase() === 'websocket') {\n if (options?.upgradeWebSocket === undefined) {\n return new Response(\n 'WebSocket upgrade requested, but server.fetch() has no upgrade implementation',\n { status: 426 },\n )\n }\n return await options.upgradeWebSocket(attach)\n }\n\n const { searchParams } = new URL(request.url)\n const sessionId = searchParams.get('sessionId')\n if (sessionId === null || sessionId.length === 0) {\n throw new A2Error('INVALID_PAYLOAD', 'missing sessionId')\n }\n const gteRaw = searchParams.get('gte')\n const lteRaw = searchParams.get('lte')\n if (gteRaw !== null || lteRaw !== null) {\n const bounds = parseHistoryBounds(gteRaw, lteRaw)\n await authorize({\n type: 'history',\n sessionId,\n ...bounds,\n transport: 'http',\n })\n const events = await server.session(sessionId).history(bounds)\n const covered = events.length === bounds.lte - bounds.gte + 1\n return Response.json(events.map(eventToWire), {\n headers: { 'a2-history-covered': String(covered) },\n })\n }\n\n const startAfter = parseResumeIndex(searchParams.get('index'))\n await authorize({\n type: 'stream',\n sessionId,\n startAfter,\n transport: 'http',\n })\n const target = server.session(sessionId) as unknown as SocketSession\n return sseResponse(\n presence\n ? target.stream({ startAfter, presence: true })\n : target.stream({ startAfter }),\n )\n }\n\n if (request.method === 'POST') {\n const body = await parsePushBody(request)\n await authorize(\n freezePush<D, P>(body.sessionId, body.events, body.presence, 'http'),\n )\n await validateIngress({\n sessionId: body.sessionId,\n events: body.events,\n ...(body.presence === undefined ? {} : { presence: body.presence }),\n })\n const session = server.session(body.sessionId)\n if (body.presence !== undefined) {\n const target = session as unknown as SocketSession\n if (typeof target.setPresence !== 'function') {\n throw invalidPushBody('presence is not declared by this contract')\n }\n await target.setPresence(body.presence)\n }\n const appended: ContractEvent<D>[] =\n body.events.length === 0\n ? []\n : await session.append(\n ...(body.events as unknown as AppendInput<D>[]),\n )\n return Response.json(appended.map(eventToWire))\n }\n\n return new Response('Method Not Allowed', {\n status: 405,\n headers: { allow: 'GET, POST' },\n })\n } catch (error) {\n return errorResponse(error)\n }\n }\n return fetch\n}\n","/**\n * Deterministic default ids for handler `session.append` calls. A handler\n * re-run after a crash calls `session.append` again; giving\n * each call a deterministic id — derived from the triggering event's id\n * and the caller's stable name — makes the re-run a no-op via the store's\n * unique index on event ids.\n *\n * The id is a UUIDv5-shaped SHA-1 over\n * `(namespace, triggerEventId, name, itemOrdinal)`, computed with\n * WebCrypto so it runs on any platform a2 core targets.\n */\n\nconst APPEND_NAMESPACE = 'a2:handler-append:v2'\nconst RETURN_NAMESPACE = 'a2:handler-return:v1'\nconst SCHEDULE_NAMESPACE = 'a2:schedule:v1'\nconst SCHEDULED_EVENT_NAMESPACE = 'a2:scheduled-event:v1'\n\nasync function deterministicIdFromInput(input: string): Promise<string> {\n const digest = await crypto.subtle.digest(\n 'SHA-1',\n new TextEncoder().encode(input),\n )\n const bytes = new Uint8Array(digest).slice(0, 16)\n bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x50\n bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nasync function deterministicId(parts: Array<string | number>): Promise<string> {\n return deterministicIdFromInput(parts.join('\\u0000'))\n}\n\nexport async function deterministicEventId(\n triggerEventId: string,\n name: string,\n itemOrdinal: number,\n): Promise<string> {\n if (name.length === 0) throw new TypeError('append name must not be empty')\n return deterministicId([APPEND_NAMESPACE, triggerEventId, name, itemOrdinal])\n}\n\nexport async function deterministicReturnedEventId(\n triggerEventId: string,\n itemOrdinal: number,\n): Promise<string> {\n return deterministicId([RETURN_NAMESPACE, triggerEventId, itemOrdinal])\n}\n\nexport async function deterministicScheduleId(\n contract: string,\n sessionId: string,\n triggerEventId: string | null,\n name: string,\n): Promise<string> {\n return deterministicIdFromInput(\n JSON.stringify([\n SCHEDULE_NAMESPACE,\n contract,\n sessionId,\n triggerEventId,\n name,\n ]),\n )\n}\n\nexport async function deterministicScheduledEventId(\n scheduleId: string,\n itemOrdinal: number,\n): Promise<string> {\n return deterministicId([SCHEDULED_EVENT_NAMESPACE, scheduleId, itemOrdinal])\n}\n","/**\n * The A2Telemetry interface — the instrumentation seam. Same philosophy\n * as store backends: the interface lives in core, implementations ship as\n * entry points (`experimental-a2/otel` adapts it to OpenTelemetry). Without\n * one, spans are free and swallowed errors print to the console.\n */\n\n/** Attribute values a2 emits. */\nexport type A2AttributeValue = string | number | boolean\n\n/** The spans a2 emits today. The catalogue grows with the surface. */\nexport type A2SpanName = 'a2.append' | 'a2.drain' | 'a2.event' | 'a2.state'\n\nexport type A2SpanHandle = {\n /** Attach or update an attribute mid-span (e.g. the outcome). */\n setAttribute(key: string, value: A2AttributeValue): void\n /**\n * Mark the span failed without a2's control flow throwing — used for\n * handler failures, which a2 swallows by design (they go into the\n * retry machinery, not up the stack) but telemetry must still see.\n */\n recordError(error: unknown): void\n}\n\nexport type A2Telemetry = {\n /**\n * Wrap one unit of a2 work. Implementations should time it, record a\n * thrown error as a failure, propagate context so nested spans tree\n * up, and always return `fn`'s result (or rethrow its error) —\n * telemetry observes, it never alters behavior.\n */\n span<T>(\n name: A2SpanName,\n attributes: Record<string, A2AttributeValue>,\n fn: (span: A2SpanHandle) => Promise<T>,\n ): Promise<T>\n}\n\n/**\n * The default when no telemetry is configured. Spans cost nothing, but\n * `recordError` prints: it only ever receives errors a2 swallows by\n * design, so without a configured sink the console is the one place\n * they can surface. Passing `telemetry` replaces this sink wholesale.\n */\nexport const CONSOLE_TELEMETRY: A2Telemetry = {\n span: (name, attributes, fn) =>\n fn({\n setAttribute: () => {},\n recordError: (error) => {\n // oxlint-disable-next-line no-console -- the whole point: swallowed errors must surface without configuration\n console.error(`[a2] error in ${name}`, attributes, error)\n },\n }),\n}\n","// oxlint-disable no-await-in-loop -- scheduler advances after durable outcomes\n/**\n * experimental-a2/server — where a contract is implemented. `createServer({\n * contract, store, handlers, ... })` binds the vocabulary to storage and\n * reactions; sessions, drains, claims, and scheduler all live here.\n * Server-only by construction: this entry point is the only one that\n * can reach a store backend, and its exports map fails loudly in browser\n * bundles.\n */\n\nimport type {\n AppendInput,\n Contract,\n ContractEvent,\n EventDefs,\n PresenceDefs,\n PresenceMap,\n PresencePatch,\n PresenceSnapshot,\n WithPresence,\n} from './contract.ts'\nimport { A2Error, asStoreUnavailable } from './errors.ts'\nimport {\n DRAIN_TIMINGS,\n POLL_TIMINGS,\n MAX_DATE_MS,\n RESERVED_PARTICIPANT_IDS,\n markSchedulerSendFailure,\n nullProtoRecord,\n serverInternals,\n type DrainOutcome,\n type DrainResult,\n} from './internal.ts'\nimport { defaultSleep } from './store-polling.ts'\nimport type {\n A2Store,\n AppendEvent,\n Event,\n EventCause,\n StoreClaimAvailableResult,\n StoreSnapshotWrite,\n StoreStateRead,\n PresenceRow,\n ReturnedEvent,\n StoredEvent,\n} from './store.ts'\nimport type { Reducer } from './reducer.ts'\nimport {\n createServerFetch,\n type A2Operation,\n type A2PushEvent,\n type A2PushPresence,\n type ServerFetchOptions,\n type UpgradeWebSocket,\n} from './server-fetch.ts'\nimport { validateSync } from './validate.ts'\nimport {\n deterministicEventId,\n deterministicReturnedEventId,\n deterministicScheduledEventId,\n deterministicScheduleId,\n} from './deterministic-id.ts'\nimport { invocationDeadlineMs, platformWaitUntil } from './platform.ts'\nimport { retryableLazy } from './retryable-lazy.ts'\nimport type {\n ScheduledEvent,\n SchedulerAppendTask,\n SchedulerTask,\n} from './scheduler-task.ts'\nimport {\n CONSOLE_TELEMETRY,\n type A2SpanHandle,\n type A2Telemetry,\n} from './telemetry.ts'\n\n/** What every handler receives. */\nexport type HandlerContext<\n D extends EventDefs,\n K extends keyof D & string = keyof D & string,\n P extends PresenceDefs = Record<never, never>,\n> = {\n /** The triggering event. */\n event: ContractEvent<D, K>\n /** Durable, 1-based dispatch ordinal for this event. */\n attempt: number\n /** This session, with handler-scoped idempotent append. */\n session: Session<D, HandlerAppend<D>, P>\n /** Fires on `abortOn` events (cancellation slice); dormant otherwise. */\n signal: AbortSignal\n}\n\nexport type Handler<\n D extends EventDefs,\n K extends keyof D & string = keyof D & string,\n P extends PresenceDefs = Record<never, never>,\n> = (\n ctx: HandlerContext<D, K, P>,\n) => Promise<void | AppendInput<D> | readonly AppendInput<D>[]>\n\nexport type LaneContext<\n D extends EventDefs,\n K extends keyof D & string = keyof D & string,\n> = {\n sessionId: string\n event: Pick<ContractEvent<D, K>, 'type' | 'payload'> & { id?: string }\n}\n\nexport type Lane<\n D extends EventDefs,\n K extends keyof D & string = keyof D & string,\n> = string | ((context: LaneContext<D, K>) => string)\n\nexport type SessionDispatch<D extends EventDefs> = (\n ...events: AppendInput<D>[]\n) => Promise<ContractEvent<D>[]>\n\nexport type SessionAppend<D extends EventDefs> = SessionDispatch<D> & {\n /** Commit, then hand pending work directly to configured scheduler. */\n dispatch: SessionDispatch<D>\n}\n\nexport type HandlerAppend<D extends EventDefs> = (\n name: string,\n ...events: AppendInput<D>[]\n) => Promise<ContractEvent<D>[]>\n\nexport type ScheduleDelay = `${number}${'ms' | 's' | 'm' | 'h' | 'd'}`\n\nexport type ScheduleTiming =\n { delay: ScheduleDelay; at?: never } | { at: Date; delay?: never }\n\nexport type SessionSchedule<D extends EventDefs> = (\n name: string,\n timing: ScheduleTiming,\n ...events: AppendInput<D>[]\n) => Promise<void>\n\nexport type StateOptions = {\n through?: number | 'latest'\n}\n\n/**\n * The presence members of a session — intersected in via\n * `WithPresence`, so they exist exactly when the contract declares\n * presence fields. Intersected before the base members so the widened\n * `stream` overload is tried first: the literal `presence: true`\n * selects it, everything else falls through to the events-only base.\n */\nexport type SessionPresence<D extends EventDefs, P extends PresenceDefs> = {\n /**\n * The two-plane feed: one snapshot of the current pruned map first\n * (per-field stamps exact), then presence patches interleaved with\n * events.\n */\n stream(opts: {\n startAfter?: number\n presence: true\n }): AsyncIterable<ContractEvent<D> | PresencePatch<P> | PresenceSnapshot<P>>\n /**\n * Validate against the contract's presence schemas, then broadcast.\n * Never an append: no log row, no dispatch, no scheduler arm. `at`\n * is the sender's LWW stamp in epoch ms; omitted, receipt time\n * stands in (single writer, so receipt order is sender order).\n */\n setPresence(patch: {\n participant: string\n values: PresencePatch<P>['values']\n seen?: number\n at?: number\n }): Promise<void>\n /** The current map, expired values pruned — a point-in-time read. */\n presence(): Promise<PresenceMap<P>>\n}\n\n/** A handle on one instance of the machine. Creating it does no I/O. */\nexport type Session<\n D extends EventDefs,\n Append = SessionAppend<D>,\n P extends PresenceDefs = Record<never, never>,\n> = WithPresence<P, SessionPresence<D, P>> & {\n readonly id: string\n append: Append\n schedule: SessionSchedule<D>\n history(options?: { gte?: number; lte?: number }): Promise<ContractEvent<D>[]>\n state<S>(\n reducer: Reducer<D, S>,\n options?: StateOptions,\n ): Promise<{ state: S; index: number }>\n /**\n * A live feed of this session's events, starting after `startAfter`\n * (exclusive). Server-side only. `server.fetch` exposes it over SSE.\n */\n stream(opts?: { startAfter?: number }): AsyncIterable<ContractEvent<D>>\n}\n\n/**\n * The public server shape scheduler handlers accept. It stays structural so\n * servers of any contract mix in one route; A2's private server internals add\n * delayed-append delivery without exposing an untyped append method here.\n */\nexport type DrainableServer = {\n readonly contract: { readonly name: string }\n drain(sessionId: string): Promise<{ settled: boolean }>\n}\n\n/**\n * The scheduler seam (a2-implementation.md §7, §9). `schedule` puts a\n * versioned drain or delayed append task on durable infrastructure;\n * `handler` returns the route the transport delivers to. Claim holders\n * move the watchdog alongside their renewable execution window.\n * Implementations ship as\n * entry points (`experimental-a2/scheduler-vercel`); core never imports a\n * transport.\n */\nexport type A2Scheduler = {\n schedule(task: SchedulerTask): Promise<void>\n handler(...servers: DrainableServer[]): (req: Request) => Promise<Response>\n}\n\nexport type A2Server<\n D extends EventDefs,\n P extends PresenceDefs = Record<never, never>,\n> = {\n /** The contract this server implements. */\n readonly contract: Contract<D, P>\n readonly fetch: {\n (request: Request): Promise<Response>\n (request: Request, options: ServerFetchOptions<D, P>): Promise<Response>\n }\n session(id: string): Session<D, SessionAppend<D>, P>\n /**\n * Process every currently eligible event. `settled` means nothing\n * actionable remains, including work blocked behind a dead letter.\n */\n drain(sessionId: string): Promise<{ settled: boolean }>\n}\n\nexport type {\n A2Operation,\n A2PushEvent,\n A2PushPresence,\n ServerFetchOptions,\n UpgradeWebSocket,\n}\nexport type { A2Socket } from './session-socket.ts'\n\n/**\n * Deliver one authenticated scheduler append through an A2 server's ordinary\n * top-level append path. Custom scheduler adapters call this after validating\n * their transport envelope; application code normally uses `session.schedule`.\n */\nexport async function deliverSchedulerAppend(\n server: DrainableServer,\n task: SchedulerAppendTask,\n): Promise<void> {\n if (server.contract.name !== task.contract) {\n throw new TypeError(\n `a2 scheduler: append task for contract '${task.contract}' cannot be delivered to '${server.contract.name}'`,\n )\n }\n const internals = serverInternals.get(server)\n if (!internals) {\n throw new TypeError(\n `a2 scheduler: server for contract '${task.contract}' cannot receive scheduled appends`,\n )\n }\n await internals.schedulerAppend(task.sessionId, task.events)\n}\n\n/**\n * Which events fire `ctx.signal` while a handler runs — the preemption\n * channel for user cancellation. The array form matches by type; the\n * object form takes per-type predicates for targeted cancellation\n * (`(event, trigger) => event.payload.of === trigger.id`). Handlers\n * without `abortOn` pay nothing. An aborted handler should catch and\n * return normally; throwing means \"retry me\".\n */\nexport type AbortSpec<D extends EventDefs, K extends keyof D & string> =\n | Array<keyof D & string>\n | {\n [T in keyof D & string]?:\n | true\n | ((\n event: ContractEvent<D, T>,\n trigger: ContractEvent<D, K>,\n context: { attempt: number },\n ) => boolean)\n }\n\nexport type HandlerEntry<\n D extends EventDefs,\n K extends keyof D & string = keyof D & string,\n P extends PresenceDefs = Record<never, never>,\n> =\n | Handler<D, K, P>\n | {\n abortOn?: AbortSpec<D, K>\n /** Session-scoped FIFO key, resolved and persisted when the event lands. */\n lane?: Lane<D, K>\n handler: Handler<D, K, P>\n }\n\nexport type ServerOptions<\n D extends EventDefs,\n P extends PresenceDefs = Record<never, never>,\n> = {\n /** The contract this server implements (see `a2.contract`). */\n contract: Contract<D, P>\n /** Where events live. Defaults: sqlite in dev, memory in tests, required in prod. */\n store?: A2Store\n /**\n * Queue-backed scheduler — e.g. `vercelQueues()` from\n * `experimental-a2/scheduler-vercel`. Absent means append-driven healing only: a\n * working configuration, but a clockless one. Recommended in\n * production.\n */\n scheduler?: A2Scheduler\n /** Optional instrumentation — e.g. `otel()` from `experimental-a2/otel`. */\n telemetry?: A2Telemetry\n /**\n * Presence-plane policy — valid only when the contract declares\n * presence fields (TypeError at construction otherwise). `ttlMs` is\n * how long a value survives without a refreshing set; default 60s.\n */\n presence?: { ttlMs?: number }\n /**\n * The reactions, keyed by event type — all present at construction,\n * so a handler can never be silently missing because its module\n * wasn't imported. Compose across files by spreading objects (note:\n * a duplicate key under spread silently last-wins).\n */\n handlers?: { [K in keyof D & string]?: HandlerEntry<D, K, P> }\n}\n\nconst MAX_FAILURES = 10\n\n/** Default: how long a presence value survives without a refreshing set. */\nconst PRESENCE_TTL_MS = 60_000\n\ntype ClaimWindow = {\n ttlMs: number\n expiresAtMs: number\n watchdogAtMs: number\n deadlineCapped: boolean\n}\n\ntype DrainSignal = {\n version: number\n closed: boolean\n notify(): void\n wait(version: number): { promise: Promise<void>; cancel(): void }\n}\n\ntype AbortSubscription = {\n controller: AbortController\n triggerIndex: number\n types: Set<string>\n matches(event: Event): boolean\n}\n\ntype AbortHub = {\n subscriptions: Set<AbortSubscription>\n seen: Map<number, Event>\n startAfter: number\n ready: Promise<void>\n watch: Promise<void> | null\n error: unknown\n iterator: AsyncIterator<Event> | null\n stopped: boolean\n}\n\nfunction createDrainSignal(): DrainSignal {\n const listeners = new Set<() => void>()\n return {\n version: 0,\n closed: false,\n notify() {\n this.version += 1\n for (const listener of listeners) listener()\n listeners.clear()\n },\n wait(version) {\n if (this.version !== version) {\n return { promise: Promise.resolve(), cancel: () => {} }\n }\n let resolve!: () => void\n const promise = new Promise<void>((done) => {\n resolve = done\n })\n listeners.add(resolve)\n return { promise, cancel: () => listeners.delete(resolve) }\n },\n }\n}\n\nfunction dispatchAbortEvent(hub: AbortHub, event: Event): void {\n let relevant = false\n for (const subscription of hub.subscriptions) {\n if (!subscription.types.has(event.type)) continue\n relevant = true\n if (subscription.matches(event)) subscription.controller.abort()\n }\n if (relevant) hub.seen.set(event.index, event)\n}\n\nfunction pruneAbortHub(hub: AbortHub): void {\n let minimum = Infinity\n const types = new Set<string>()\n for (const subscription of hub.subscriptions) {\n minimum = Math.min(minimum, subscription.triggerIndex)\n for (const type of subscription.types) types.add(type)\n }\n for (const [index, event] of hub.seen) {\n if (index <= minimum || !types.has(event.type)) hub.seen.delete(index)\n }\n}\n\n/**\n * Deadlines tighten the claim/watchdog window; they never decide whether a\n * handler starts. A platform timeout therefore follows the same path as any\n * other process death: the in-flight event remains pending and is retried.\n */\nfunction nextClaimWindow(): ClaimWindow {\n const nowMs = Date.now()\n const deadlineMs = invocationDeadlineMs()\n const deadlineTtlMs =\n deadlineMs === null ? DRAIN_TIMINGS.claimTtlMs : deadlineMs - nowMs\n const deadlineCapped =\n deadlineMs !== null && deadlineTtlMs <= DRAIN_TIMINGS.claimTtlMs\n const ttlMs = Math.max(1, Math.min(DRAIN_TIMINGS.claimTtlMs, deadlineTtlMs))\n const expiresAtMs = nowMs + ttlMs\n return {\n ttlMs,\n expiresAtMs,\n watchdogAtMs: expiresAtMs + DRAIN_TIMINGS.watchdogGraceMs,\n deadlineCapped,\n }\n}\n\nfunction schedulerSlot(dueAt: number): number {\n return Math.ceil(dueAt / 1_000) * 1_000\n}\n\nfunction currentSchedulerSlot(now: number): number {\n return Math.floor(now / 1_000) * 1_000\n}\n\n/**\n * The namespace separator between machine name and session id in\n * storage. Machines sharing one store backend (the dev-default sqlite\n * file, a shared Postgres) must not collide on session ids; the machine\n * name is what makes multi-machine apps unambiguous (a2-api.md §1), so\n * it prefixes every storage key.\n */\nconst NS = '\\u001f'\n\nconst devDefaultStore = retryableLazy(() =>\n import('./store-sqlite.ts').then((m) => m.sqlite()),\n)\n\nfunction environment(): 'development' | 'test' | 'production' {\n const env =\n typeof process === 'undefined' ? undefined : process.env?.['NODE_ENV']\n if (env === 'test') return 'test'\n if (env === 'production') return 'production'\n return 'development'\n}\n\nfunction describeError(err: unknown): string {\n if (err instanceof Error) return err.stack ?? `${err.name}: ${err.message}`\n return String(err)\n}\n\n/**\n * Comparison key for a presence value in the degraded-tier diff — an\n * LWW tie can replace a value without moving its `seen`/`at` stamp.\n */\nfunction fingerprint(value: unknown): string {\n return JSON.stringify(value) ?? ''\n}\n\nfunction foldPresenceRows(\n rows: PresenceRow[],\n): Record<string, Record<string, { value: unknown; seen: number; at: Date }>> {\n // Null-prototype at both levels: participants and fields are caller\n // strings, and a '__proto__' key on a normal object rewrites its\n // prototype instead of setting an own property.\n const map =\n nullProtoRecord<\n Record<string, Record<string, { value: unknown; seen: number; at: Date }>>\n >()\n for (const row of rows) {\n ;(map[row.participant] ??= nullProtoRecord())[row.field] = {\n value: row.value,\n seen: row.seen,\n at: row.at,\n }\n }\n return map\n}\n\n/** Implement a contract: bind its vocabulary to storage and reactions. */\nexport function createServer<\n D extends EventDefs,\n P extends PresenceDefs = Record<never, never>,\n>(options: ServerOptions<D, P>): A2Server<D, P> {\n const serverContract = options?.contract\n if (\n serverContract === null ||\n typeof serverContract !== 'object' ||\n typeof serverContract.name !== 'string' ||\n serverContract.events === null\n ) {\n throw new TypeError(\n 'createServer expects options with a contract (see a2.contract)',\n )\n }\n const name = serverContract.name\n const defs = serverContract.events\n const presenceDefs: Readonly<PresenceDefs> = serverContract.presence\n const declaresPresence = Object.keys(presenceDefs).length > 0\n const presenceNotSupported = (): A2Error =>\n new A2Error(\n 'PRESENCE_NOT_SUPPORTED',\n `the contract '${name}' declares presence but the store backend for its server has no presence capability (A2Store.presence)`,\n )\n\n if (options.presence !== undefined) {\n // An option for a plane the contract doesn't declare is a mistake\n // worth failing loud at construction.\n if (!declaresPresence) {\n throw new TypeError(\n `the presence option requires a contract that declares presence fields — '${name}' has none`,\n )\n }\n const { ttlMs } = options.presence\n if (ttlMs !== undefined && (!Number.isInteger(ttlMs) || ttlMs <= 0)) {\n throw new TypeError(\n 'presence.ttlMs must be a positive integer of milliseconds',\n )\n }\n }\n const presenceTtlMs = options.presence?.ttlMs ?? PRESENCE_TTL_MS\n\n // Resolve where events live. Explicit store wins; otherwise the\n // environment decides — and production refuses to guess\n // (a2-implementation.md §8): a failed boot beats events written to an\n // ephemeral filesystem.\n let makeStore: () => Promise<A2Store>\n if (options.store) {\n const explicit = options.store\n // Fail at boot, not first use (a2-api.md §12).\n if (declaresPresence && !explicit.presence) throw presenceNotSupported()\n makeStore = () => Promise.resolve(explicit)\n } else {\n const env = environment()\n if (env === 'production') {\n const error = (): A2Error =>\n new A2Error(\n 'STORE_NOT_CONFIGURED',\n `the server for '${name}' has no store configured and NODE_ENV is 'production' — pass an explicit store backend (e.g. postgres from 'experimental-a2/store-postgres')`,\n )\n // `next build` evaluates route modules with NODE_ENV=production\n // to collect page data — in a CI without the runtime env vars, a\n // construction-time throw fails the build for nothing (the store is\n // never used during collection). During that phase only, defer\n // the failure to first use; a real production boot still fails at\n // construction, before any event can land somewhere ephemeral.\n if (process.env['NEXT_PHASE'] !== 'phase-production-build') {\n throw error()\n }\n makeStore = () => Promise.reject(error())\n } else {\n makeStore =\n env === 'test'\n ? () => import('./store-memory.ts').then((m) => m.memory())\n : devDefaultStore.get\n }\n }\n\n // Environment-resolved stores arrive lazily; assert the capability the\n // moment one resolves — the closest available moment to construction.\n if (declaresPresence && !options.store) {\n const inner = makeStore\n makeStore = async () => {\n const store = await inner()\n if (!store.presence) throw presenceNotSupported()\n return store\n }\n }\n\n const resolveStore = retryableLazy(makeStore).get\n\n const telemetry = options.telemetry ?? CONSOLE_TELEMETRY\n const scheduler = options.scheduler\n\n type AbortMatcher = Map<\n string,\n | true\n | ((\n event: ContractEvent<D>,\n trigger: ContractEvent<D>,\n context: { attempt: number },\n ) => boolean)\n >\n const handlers = new Map<\n string,\n { handler: Handler<D>; abortOn: AbortMatcher | null; lane: Lane<D> | null }\n >()\n for (const [type, entry] of Object.entries(options.handlers ?? {})) {\n if (entry === undefined) continue\n if (!Object.hasOwn(defs, type)) {\n throw new TypeError(\n `contract '${name}' has no event type '${type}' — cannot register a handler for it`,\n )\n }\n const handler = typeof entry === 'function' ? entry : entry?.handler\n if (typeof handler !== 'function') {\n throw new TypeError(`handler for '${type}' must be a function`)\n }\n let abortOn: AbortMatcher | null = null\n const spec = typeof entry === 'function' ? undefined : entry.abortOn\n if (spec !== undefined) {\n abortOn = new Map()\n const pairs = Array.isArray(spec)\n ? spec.map((abortType) => [abortType, true as const] as const)\n : (Object.entries(spec) as Array<\n [\n string,\n (\n | true\n | ((\n e: never,\n t: never,\n context: { attempt: number },\n ) => boolean)\n ),\n ]\n >)\n for (const [abortType, matcher] of pairs) {\n if (matcher === undefined) continue\n if (!Object.hasOwn(defs, abortType)) {\n throw new TypeError(\n `contract '${name}' has no event type '${String(abortType)}' — cannot abort on it`,\n )\n }\n abortOn.set(String(abortType), matcher as never)\n }\n if (abortOn.size === 0) abortOn = null\n }\n const lane = typeof entry === 'function' ? null : (entry.lane ?? null)\n if (\n lane !== null &&\n typeof lane !== 'function' &&\n (typeof lane !== 'string' || lane.length === 0)\n ) {\n throw new TypeError(\n `lane for '${type}' must be a non-empty string or a function`,\n )\n }\n handlers.set(type, {\n handler: handler as Handler<D>,\n abortOn,\n lane: lane as Lane<D> | null,\n })\n }\n\n const prefix = `${name}${NS}`\n const nsId = (sessionId: string): string => `${prefix}${sessionId}`\n const stripNs = (stored: string): string => stored.slice(prefix.length)\n\n const toPublic = (row: Event): ContractEvent<D> =>\n ({\n id: row.id,\n type: row.type,\n payload: row.payload,\n index: row.index,\n sessionId: stripNs(row.sessionId),\n createdAt: row.createdAt,\n }) as ContractEvent<D>\n\n // ── background work tracking ─────────────────────────────────────\n // Every fire-and-forget operation is tracked so (a) platforms with\n // waitUntil keep the invocation alive and (b) tests can flush\n // deterministically via serverInternals.\n const inFlight = new Set<Promise<unknown>>()\n const track = (p: Promise<unknown>): void => {\n inFlight.add(p)\n const drop = (): void => {\n inFlight.delete(p)\n }\n p.then(drop, drop)\n }\n\n type SchedulerArmSlot = {\n promise: Promise<void>\n forget: ReturnType<typeof setTimeout>\n }\n const schedulerArmSlots = new Map<string, SchedulerArmSlot>()\n\n /**\n * Start an optional scheduler arm without putting it on the execution path.\n * The returned raw promise lets the initial append report failure; the\n * tracked copy is always rejection-safe for heartbeat callers.\n */\n const startSchedulerArm = (\n sessionId: string,\n dueAt: number,\n ): Promise<void> | null => {\n if (!scheduler) return null\n const slottedDueAt = schedulerSlot(dueAt)\n const slotKey = JSON.stringify([sessionId, slottedDueAt])\n const existing = schedulerArmSlots.get(slotKey)\n if (existing) return existing.promise\n // Normalize even a custom adapter's synchronous throw into a rejected\n // promise. Optional scheduler must never stop inline claiming.\n const raw = Promise.resolve().then(() =>\n scheduler.schedule({\n version: 1,\n kind: 'drain',\n contract: name,\n sessionId,\n dueAt: slottedDueAt,\n }),\n )\n const forget = setTimeout(\n () => {\n if (schedulerArmSlots.get(slotKey)?.promise === raw) {\n schedulerArmSlots.delete(slotKey)\n }\n },\n Math.max(0, slottedDueAt - Date.now()) + 1_000,\n )\n ;(forget as { unref?: () => void }).unref?.()\n schedulerArmSlots.set(slotKey, { promise: raw, forget })\n void raw.then(undefined, () => {\n const current = schedulerArmSlots.get(slotKey)\n if (current?.promise !== raw) return\n clearTimeout(current.forget)\n schedulerArmSlots.delete(slotKey)\n })\n const safe = raw.catch(() => {})\n track(safe)\n platformWaitUntil(safe)\n return raw\n }\n\n const scheduledDrains = new Map<\n string,\n { signal: DrainSignal; promise: Promise<void> }\n >()\n\n const scheduleDrain = (sessionId: string, watchdogDueAt?: number): void => {\n const existing = scheduledDrains.get(sessionId)\n if (existing && !existing.signal.closed) {\n existing.signal.notify()\n return\n }\n if (existing) scheduledDrains.delete(sessionId)\n const signal = createDrainSignal()\n const p = new Promise<void>((resolve) => {\n queueMicrotask(() => {\n void drainSession(sessionId, watchdogDueAt, signal)\n .then(() => resolve())\n .catch(() => resolve())\n })\n }).finally(() => {\n if (scheduledDrains.get(sessionId)?.promise === p) {\n scheduledDrains.delete(sessionId)\n }\n })\n scheduledDrains.set(sessionId, { signal, promise: p })\n track(p)\n platformWaitUntil(p)\n }\n\n // ── append ───────────────────────────────────────────────────────\n\n const validateEvents = (\n sessionId: string,\n events: AppendInput<D>[],\n resolveDispatchMetadata = true,\n ): AppendEvent[] => {\n if (events.length === 0) {\n throw new TypeError('append requires at least one event')\n }\n return events.map((e) => {\n const schema = Object.hasOwn(defs, e.type) ? defs[e.type] : undefined\n if (!schema) {\n throw new A2Error(\n 'UNKNOWN_EVENT_TYPE',\n `contract '${name}' has no event type '${String(e.type)}'`,\n )\n }\n const result = validateSync(schema, e.payload, `event '${e.type}'`)\n if (result.issues) {\n throw new A2Error(\n 'INVALID_PAYLOAD',\n `invalid payload for event '${e.type}' on machine '${name}'`,\n { details: result.issues },\n )\n }\n const validated: AppendEvent = { type: e.type, payload: result.value }\n if (e.id !== undefined) validated.id = e.id\n if (!resolveDispatchMetadata) return validated\n const registration = handlers.get(e.type)\n if (!registration) {\n validated.settled = true\n } else if (registration.lane !== null) {\n const lane =\n typeof registration.lane === 'function'\n ? registration.lane({\n sessionId,\n event: {\n type: e.type,\n payload: structuredClone(result.value),\n ...(e.id === undefined ? {} : { id: e.id }),\n } as never,\n })\n : registration.lane\n if (typeof lane !== 'string' || lane.length === 0) {\n throw new TypeError(\n `lane for '${e.type}' must resolve to a non-empty string`,\n )\n }\n validated.lane = lane\n }\n return validated\n })\n }\n\n /**\n * Validate + write. `onAppended` runs inside the telemetry span, so\n * the drain it schedules is created in the append's active context —\n * with a real tracer, causal work remains connected.\n */\n const appendCore = (\n sessionId: string,\n events: AppendInput<D>[],\n source: 'external' | 'handler',\n mode: 'inline' | 'dispatch',\n onAppended: (rows: ContractEvent<D>[], watchdogDueAt?: number) => void,\n cause?: EventCause,\n generatedIds?: readonly boolean[],\n requireDurableInitialArm = false,\n ): Promise<ContractEvent<D>[]> =>\n telemetry.span(\n 'a2.append',\n {\n 'a2.contract': name,\n 'a2.session_id': sessionId,\n 'a2.append.source': source,\n 'a2.append.mode': mode,\n 'a2.append.types': events.map((e) => String(e.type)).join(','),\n 'a2.append.count': events.length,\n },\n async (span) => {\n if (mode === 'dispatch' && !scheduler) {\n throw new TypeError(\n 'append.dispatch requires a configured scheduler adapter',\n )\n }\n assertSessionId(sessionId)\n const validated = validateEvents(sessionId, events)\n if (cause) {\n for (const [index, event] of validated.entries()) {\n event.cause = generatedIds?.[index]\n ? { ...cause, batchSize: events.length }\n : cause\n }\n }\n const store = await resolveStore()\n let rows: StoredEvent[]\n let shouldHealSession: boolean\n try {\n const result = await store.append(nsId(sessionId), validated)\n rows = result.events\n shouldHealSession = result.hasPending\n } catch (err) {\n throw asStoreUnavailable(err)\n }\n const appended = rows.map(toPublic)\n\n const initialWatchdogAt =\n shouldHealSession &&\n scheduler &&\n source === 'external' &&\n mode === 'inline'\n ? schedulerSlot(nextClaimWindow().watchdogAtMs)\n : undefined\n const initialArm =\n initialWatchdogAt !== undefined\n ? startSchedulerArm(sessionId, initialWatchdogAt)\n : null\n const dispatchArm =\n shouldHealSession && mode === 'dispatch'\n ? startSchedulerArm(sessionId, currentSchedulerSlot(Date.now()))\n : null\n if (shouldHealSession && mode === 'inline') {\n onAppended(appended, initialWatchdogAt)\n }\n if (dispatchArm) {\n await dispatchArm\n }\n if (initialArm) {\n let timeout: ReturnType<typeof setTimeout> | null = null\n try {\n await Promise.race([\n initialArm,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n reject(\n new Error(\n `a2 scheduler arm timed out after ${DRAIN_TIMINGS.schedulerArmTimeoutMs}ms`,\n ),\n )\n }, DRAIN_TIMINGS.schedulerArmTimeoutMs)\n }),\n ])\n } catch (err) {\n span.setAttribute('a2.append.armed', false)\n span.recordError(err)\n if (requireDurableInitialArm) throw err\n } finally {\n if (timeout) clearTimeout(timeout)\n }\n }\n return appended\n },\n )\n\n const readHistory = async (\n sessionId: string,\n bounds?: { gte?: number; lte?: number },\n ): Promise<StoredEvent[]> => {\n const gte = bounds?.gte\n const lte = bounds?.lte\n assertHistoryIndex('gte', gte)\n assertHistoryIndex('lte', lte)\n if (gte !== undefined && lte !== undefined && gte > lte) {\n throw new RangeError(\n 'history.gte must be less than or equal to history.lte',\n )\n }\n if (lte === 0) return []\n\n const store = await resolveStore()\n try {\n const readOptions =\n gte === undefined && lte === undefined\n ? undefined\n : {\n ...(gte === undefined\n ? {}\n : { afterIndex: Math.max(0, gte - 1) }),\n ...(lte === undefined ? {} : { throughIndex: lte }),\n }\n const rows = await store.read(nsId(sessionId), readOptions)\n return rows.filter(\n (row) =>\n (gte === undefined || row.index >= gte) &&\n (lte === undefined || row.index <= lte),\n )\n } catch (err) {\n throw asStoreUnavailable(err)\n }\n }\n\n // Snapshot plus tail is one adapter operation. A cache-path failure is\n // not load-bearing: fall back to the raw store, which still reports a\n // real storage failure.\n const readCachedState = async (\n store: A2Store,\n sessionId: string,\n reducerName: string,\n throughIndex?: number,\n snapshotThroughIndex?: number,\n ): Promise<StoreStateRead> => {\n try {\n return await store.readState(\n nsId(sessionId),\n reducerName,\n throughIndex === undefined && snapshotThroughIndex === undefined\n ? undefined\n : {\n ...(throughIndex === undefined ? {} : { throughIndex }),\n ...(snapshotThroughIndex === undefined\n ? {}\n : { snapshotThroughIndex }),\n },\n )\n } catch {\n try {\n return {\n headIndex: null,\n snapshot: null,\n events: await store.read(\n nsId(sessionId),\n throughIndex === undefined ? undefined : { throughIndex },\n ),\n }\n } catch (err) {\n throw asStoreUnavailable(err)\n }\n }\n }\n\n type PendingStateRead = {\n sessionId: string\n throughIndex?: number\n pinEventIndex?: number\n span: A2SpanHandle\n resolve: (result: { state: unknown; index: number }) => void\n reject: (reason: unknown) => void\n }\n\n type StateReadPlan = {\n sessionId: string\n entries: PendingStateRead[]\n throughIndex?: number\n snapshotThroughIndex?: number\n }\n\n const planStateReads = (batch: PendingStateRead[]): StateReadPlan[] => {\n const bySession = new Map<string, PendingStateRead[]>()\n for (const entry of batch) {\n const entries = bySession.get(entry.sessionId)\n if (entries) entries.push(entry)\n else bySession.set(entry.sessionId, [entry])\n }\n const plans: StateReadPlan[] = []\n for (const [sessionId, entries] of bySession) {\n const boundaries = entries.flatMap((entry) =>\n entry.throughIndex === undefined ? [] : [entry.throughIndex],\n )\n const plan: StateReadPlan = { sessionId, entries }\n if (boundaries.length === entries.length) {\n plan.throughIndex = Math.max(...boundaries)\n }\n if (boundaries.length > 0) {\n plan.snapshotThroughIndex = Math.min(...boundaries)\n }\n plans.push(plan)\n }\n return plans\n }\n\n // The cache is untrusted: schema rejection refolds from the raw store.\n const foldStatePlan = async (\n store: A2Store,\n reducer: Reducer<D, unknown>,\n plan: StateReadPlan,\n stateRead: StoreStateRead,\n ): Promise<void> => {\n let state = cloneInitial(reducer.initialState)\n let index = 0\n let snapshotOutcome = 'miss'\n const snap = stateRead.snapshot\n let rows = stateRead.events\n if (snap) {\n if (reducer.stateSchema) {\n const result = validateSync(\n reducer.stateSchema,\n snap.state,\n 'the stateSchema',\n )\n if (result.issues) {\n snapshotOutcome = 'rejected'\n } else {\n state = result.value\n index = snap.index\n snapshotOutcome = 'hit'\n }\n } else {\n state = snap.state\n index = snap.index\n snapshotOutcome = 'hit'\n }\n }\n if (snapshotOutcome === 'rejected') {\n try {\n rows = await store.read(\n nsId(plan.sessionId),\n plan.throughIndex === undefined\n ? undefined\n : { throughIndex: plan.throughIndex },\n )\n } catch (err) {\n throw asStoreUnavailable(err)\n }\n }\n const ordered = plan.entries.toSorted(\n (a, b) =>\n (a.throughIndex ?? Number.POSITIVE_INFINITY) -\n (b.throughIndex ?? Number.POSITIVE_INFINITY),\n )\n const writes = new Map<\n number,\n { state: unknown; pinEventIndexes: Set<number> }\n >()\n let rowPosition = 0\n for (const entry of ordered) {\n const target = entry.throughIndex ?? Number.POSITIVE_INFINITY\n while (rowPosition < rows.length && rows[rowPosition]!.index <= target) {\n const row = rows[rowPosition]!\n state = reducer.fold(state, toPublic(row) as never)\n index = row.index\n rowPosition += 1\n }\n const resultState = cloneInitial(state)\n const folded = rowPosition\n entry.span.setAttribute('a2.state.snapshot', snapshotOutcome)\n entry.span.setAttribute('a2.state.folded', folded)\n entry.span.setAttribute('a2.state.index', index)\n if (index > 0 && (folded > 0 || entry.pinEventIndex !== undefined)) {\n const advancesHead =\n stateRead.headIndex === null || index > stateRead.headIndex\n const repairsHead =\n snapshotOutcome === 'rejected' && index === stateRead.headIndex\n if (\n !advancesHead &&\n !repairsHead &&\n entry.pinEventIndex === undefined\n ) {\n entry.resolve({ state: resultState, index })\n continue\n }\n let write = writes.get(index)\n if (!write) {\n write = {\n state: cloneInitial(resultState),\n pinEventIndexes: new Set(),\n }\n writes.set(index, write)\n }\n if (entry.pinEventIndex !== undefined) {\n write.pinEventIndexes.add(entry.pinEventIndex)\n }\n }\n entry.resolve({ state: resultState, index })\n }\n if (writes.size > 0) {\n const snapshots: StoreSnapshotWrite[] = []\n for (const [snapshotIndex, write] of writes) {\n const snapshot: StoreSnapshotWrite = {\n index: snapshotIndex,\n state: write.state,\n }\n if (write.pinEventIndexes.size > 0) {\n snapshot.pinEventIndexes = [...write.pinEventIndexes]\n }\n snapshots.push(snapshot)\n }\n const persistence = Promise.resolve()\n .then(() =>\n store.putSnapshots(nsId(plan.sessionId), reducer.name, snapshots),\n )\n .catch(() => {})\n track(persistence)\n platformWaitUntil(persistence)\n }\n }\n\n // ── same-tick state-read coalescing ──────────────────────────────\n const pendingStateReads = new Map<string, PendingStateRead[]>()\n\n // The flush microtask voids this promise, so the function must be\n // total: never reject, never leave an entry unresolved — even for a\n // synchronously throwing adapter or a read structuredClone rejects.\n const flushStateReads = async (\n store: A2Store,\n reducer: Reducer<D, unknown>,\n batch: PendingStateRead[],\n ): Promise<void> => {\n const plans = planStateReads(batch)\n let reads: StoreStateRead[] | null\n try {\n reads = store.readStates\n ? await store.readStates(\n plans.map((plan) => ({\n sessionId: nsId(plan.sessionId),\n ...(plan.throughIndex === undefined\n ? {}\n : { throughIndex: plan.throughIndex }),\n ...(plan.snapshotThroughIndex === undefined\n ? {}\n : { snapshotThroughIndex: plan.snapshotThroughIndex }),\n })),\n reducer.name,\n )\n : await Promise.all(\n plans.map((plan) =>\n readCachedState(\n store,\n plan.sessionId,\n reducer.name,\n plan.throughIndex,\n plan.snapshotThroughIndex,\n ),\n ),\n )\n } catch {\n reads = null\n }\n if (!reads || reads.length !== plans.length) {\n try {\n reads = await Promise.all(\n plans.map((plan) =>\n readCachedState(\n store,\n plan.sessionId,\n reducer.name,\n plan.throughIndex,\n plan.snapshotThroughIndex,\n ),\n ),\n )\n } catch (err) {\n for (const entry of batch) entry.reject(err)\n return\n }\n }\n for (const [position, plan] of plans.entries()) {\n try {\n await foldStatePlan(store, reducer, plan, reads[position]!)\n } catch (err) {\n for (const entry of plan.entries) entry.reject(err)\n }\n }\n }\n\n const enqueueStateRead = (\n store: A2Store,\n sessionId: string,\n reducer: Reducer<D, unknown>,\n throughIndex?: number,\n pinEventIndex?: number,\n span?: A2SpanHandle,\n ): Promise<{ state: unknown; index: number }> =>\n new Promise((resolve, reject) => {\n const reducerName = reducer.name\n let batch = pendingStateReads.get(reducerName)\n if (!batch) {\n const opened: PendingStateRead[] = []\n pendingStateReads.set(reducerName, opened)\n // One microtask is the whole batching window — deliberately NOT\n // DataLoader's post-promise-job nextTick, which would defer\n // handler-internal reads past the entire microtask cascade and\n // reorder drain interleaving (and has no edge-runtime primitive).\n // It still coalesces reliably: siblings of one Promise.all\n // traverse identical awaits (store resolution, span wrapper), so\n // their enqueues sit at consecutive queue positions — cold or\n // warm — and this flush, queued by the first of them, runs after\n // the last. A deeper-staggered caller just opens the next batch.\n queueMicrotask(() => {\n pendingStateReads.delete(reducerName)\n void flushStateReads(store, reducer, opened)\n })\n batch = opened\n }\n batch.push({\n sessionId,\n ...(throughIndex === undefined ? {} : { throughIndex }),\n ...(pinEventIndex === undefined ? {} : { pinEventIndex }),\n span: span!,\n resolve,\n reject,\n })\n })\n\n const readState = async <S>(\n sessionId: string,\n reducer: Reducer<D, S>,\n throughIndex?: number,\n pinEventIndex?: number,\n ): Promise<{ state: S; index: number }> => {\n const store = await resolveStore()\n return telemetry.span(\n 'a2.state',\n {\n 'a2.contract': name,\n 'a2.session_id': sessionId,\n 'a2.state.reducer': reducer.name,\n },\n (span) =>\n enqueueStateRead(\n store,\n sessionId,\n reducer as Reducer<D, unknown>,\n throughIndex,\n pinEventIndex,\n span,\n ) as Promise<{ state: S; index: number }>,\n )\n }\n\n const makeSchedule = (\n sessionId: string,\n trigger: Pick<StoredEvent, 'id' | 'createdAt'> | null,\n ): SessionSchedule<D> => {\n const triggerEventId = trigger?.id ?? null\n const triggerCreatedAt = trigger?.createdAt.getTime()\n return async (scheduleName, timing, ...events) => {\n if (!scheduler) {\n throw new TypeError(\n 'session.schedule requires a configured scheduler adapter',\n )\n }\n assertScheduleName(scheduleName)\n if (events.length === 0) {\n throw new TypeError('schedule requires at least one event')\n }\n const dueAt = scheduleDueAt(timing, triggerCreatedAt ?? Date.now())\n const payloads = events.map((event) =>\n cloneScheduledPayload(event.payload),\n )\n const snapshottedEvents = events.map((event, index) =>\n event.id === undefined\n ? { type: event.type, payload: payloads[index] }\n : { type: event.type, payload: payloads[index], id: event.id },\n ) as AppendInput<D>[]\n const validated = validateEvents(\n sessionId,\n structuredClone(snapshottedEvents),\n false,\n )\n const scheduleId = await deterministicScheduleId(\n name,\n sessionId,\n triggerEventId,\n scheduleName,\n )\n const scheduledEvents: ScheduledEvent[] = await Promise.all(\n validated.map(async (event, item) => ({\n id:\n event.id ?? (await deterministicScheduledEventId(scheduleId, item)),\n type: event.type,\n payload: payloads[item],\n })),\n )\n if (\n new Set(scheduledEvents.map((event) => event.id)).size !==\n scheduledEvents.length\n ) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'scheduled batch contains the same event id more than once',\n )\n }\n try {\n await scheduler.schedule({\n version: 1,\n kind: 'append',\n id: scheduleId,\n contract: name,\n sessionId,\n dueAt,\n events: scheduledEvents,\n })\n } catch (error) {\n throw markSchedulerSendFailure(error)\n }\n }\n }\n\n const toSessionEvent = (id: string, event: Event): ContractEvent<D> =>\n ({\n id: event.id,\n type: event.type,\n payload: event.payload,\n index: event.index,\n sessionId: id,\n createdAt: event.createdAt,\n }) as ContractEvent<D>\n\n const streamEvents = (\n id: string,\n startAfter: number,\n ): AsyncIterable<ContractEvent<D>> => {\n const store = resolveStore()\n const outer = async function* (): AsyncGenerator<ContractEvent<D>> {\n const inner = (await store).stream(nsId(id), { startAfter })\n for await (const event of inner) yield toSessionEvent(id, event)\n }\n return outer()\n }\n\n // ── presence ──────────────────────────────────────────────\n\n const requirePresence = (\n store: A2Store,\n ): NonNullable<A2Store['presence']> => {\n if (!store.presence) throw presenceNotSupported()\n return store.presence\n }\n\n const setPresence = async (\n sessionId: string,\n patch: {\n participant: string\n values: Record<string, unknown>\n seen?: number\n at?: number\n },\n fallbackSeen: number,\n ): Promise<void> => {\n if (\n typeof patch.participant !== 'string' ||\n patch.participant.length === 0\n ) {\n throw new TypeError('presence participant must be a non-empty string')\n }\n if (RESERVED_PARTICIPANT_IDS.has(patch.participant)) {\n throw new TypeError(\n `presence participant must not be '${patch.participant}'`,\n )\n }\n if (\n patch.at !== undefined &&\n (typeof patch.at !== 'number' ||\n !Number.isFinite(patch.at) ||\n patch.at < 0 ||\n patch.at > MAX_DATE_MS)\n ) {\n throw new TypeError(\n 'presence at must be non-negative epoch milliseconds within the Date range',\n )\n }\n // Validate the whole patch before the adapter sees any of it — a\n // bad field means nothing is broadcast.\n const validated: Record<string, unknown> = nullProtoRecord()\n for (const [field, value] of Object.entries(patch.values)) {\n if (value === undefined) continue\n const schema = Object.hasOwn(presenceDefs, field)\n ? presenceDefs[field]\n : undefined\n if (!schema) {\n throw new A2Error(\n 'UNKNOWN_PRESENCE_FIELD',\n `contract '${name}' has no presence field '${field}'`,\n )\n }\n if (value === null) {\n validated[field] = null\n continue\n }\n const result = validateSync(schema, value, `presence field '${field}'`)\n if (result.issues) {\n throw new A2Error(\n 'INVALID_PAYLOAD',\n `invalid value for presence field '${field}' on machine '${name}'`,\n { details: result.issues },\n )\n }\n validated[field] = result.value\n }\n const store = await resolveStore()\n try {\n await requirePresence(store).set(\n nsId(sessionId),\n patch.participant,\n validated,\n {\n seen: patch.seen ?? fallbackSeen,\n // The sender's stamp is the LWW order; receipt time is the\n // fallback for stampless callers (handlers, old wire\n // clients), where receipt order is sender order — single\n // writer. Storage anchors expiry on its own clock either way.\n at: new Date(patch.at ?? Date.now()),\n ttlMs: presenceTtlMs,\n },\n )\n } catch (err) {\n throw asStoreUnavailable(err)\n }\n }\n\n const readPresenceMap = async (\n sessionId: string,\n ): Promise<PresenceMap<P>> => {\n const store = await resolveStore()\n let rows: PresenceRow[]\n try {\n rows = await requirePresence(store).read(nsId(sessionId))\n } catch (err) {\n throw asStoreUnavailable(err)\n }\n return foldPresenceRows(rows) as PresenceMap<P>\n }\n\n /**\n * The two-plane feed. Patches ride `subscribe` when the adapter has\n * the push tier; without it the map is re-read and diffed whenever\n * the event feed wakes, and at the poll idle ceiling while it is\n * silent — degraded means later, not lost while watched.\n */\n const streamWithPresence = (\n id: string,\n startAfter: number,\n ): AsyncIterable<ContractEvent<D> | PresencePatch | PresenceSnapshot> => {\n const ns = nsId(id)\n const outer = async function* (): AsyncGenerator<\n ContractEvent<D> | PresencePatch | PresenceSnapshot\n > {\n const store = await resolveStore()\n const api = requirePresence(store)\n\n const readRows = async (): Promise<PresenceRow[]> => {\n try {\n return await api.read(ns)\n } catch (err) {\n throw asStoreUnavailable(err)\n }\n }\n\n // What this feed has already painted, per (participant, field) —\n // the comparison state for re-read diffs.\n const painted = new Map<\n string,\n Map<string, { seen: number; atMs: number; value: string }>\n >()\n\n // One patch per (participant, field), never merged — a merged\n // stamp would let a stale field inherit a fresher sibling's\n // `seen` and survive the documented frontier reconciliation.\n const diffRows = (rows: PresenceRow[]): PresencePatch[] => {\n const patches: PresencePatch[] = []\n const live = new Map<string, Set<string>>()\n for (const row of rows) {\n let liveFields = live.get(row.participant)\n if (!liveFields) {\n liveFields = new Set()\n live.set(row.participant, liveFields)\n }\n liveFields.add(row.field)\n const stamp = {\n seen: row.seen,\n atMs: row.at.getTime(),\n value: fingerprint(row.value),\n }\n const prior = painted.get(row.participant)?.get(row.field)\n if (\n prior &&\n prior.seen === stamp.seen &&\n prior.atMs === stamp.atMs &&\n prior.value === stamp.value\n ) {\n continue\n }\n let paintedFields = painted.get(row.participant)\n if (!paintedFields) {\n paintedFields = new Map()\n painted.set(row.participant, paintedFields)\n }\n paintedFields.set(row.field, stamp)\n patches.push({\n participant: row.participant,\n values: { [row.field]: row.value },\n seen: row.seen,\n at: row.at,\n })\n }\n for (const [participant, fields] of painted) {\n for (const [field, prior] of fields) {\n if (live.get(participant)?.has(field)) continue\n fields.delete(field)\n patches.push({\n participant,\n values: { [field]: null },\n // A cleared field has no surviving row; its last painted\n // `seen` and the observation time are the honest stamps.\n seen: prior.seen,\n at: new Date(),\n })\n }\n if (fields.size === 0) painted.delete(participant)\n }\n return patches\n }\n\n const paint = (patch: PresencePatch): void => {\n let fields = painted.get(patch.participant)\n for (const [field, value] of Object.entries(patch.values)) {\n if (value === null || value === undefined) {\n fields?.delete(field)\n continue\n }\n if (!fields) {\n fields = new Map()\n painted.set(patch.participant, fields)\n }\n fields.set(field, {\n seen: patch.seen,\n atMs: patch.at.getTime(),\n value: fingerprint(value),\n })\n }\n if (fields?.size === 0) painted.delete(patch.participant)\n }\n\n // Arrivals coalesce per (participant, field): latest value wins,\n // each field keeps its own seen/at stamps (never merged — a stale\n // field must not inherit a fresher sibling's `seen`), one patch\n // per (participant, field) on drain. A stalled consumer therefore\n // holds at most the live presence cardinality, never the arrival\n // history.\n const queue = new Map<\n string,\n Map<string, { value: unknown; seen: number; at: Date }>\n >()\n let wakeQueue: (() => void) | null = null\n const enqueue = (patch: PresencePatch): void => {\n for (const [field, value] of Object.entries(patch.values)) {\n if (value === undefined) continue\n let fields = queue.get(patch.participant)\n if (!fields) {\n fields = new Map()\n queue.set(patch.participant, fields)\n }\n // Per-field LWW in the queue itself: pub/sub delivery order\n // is not apply order (two instances' PUBLISHes race), and an\n // unconditional overwrite would let an older patch swallow a\n // newer queued value that then never reaches the subscriber.\n // Ties go to the incoming patch, like every other comparator.\n const queued = fields.get(field)\n if (queued && queued.at.getTime() > patch.at.getTime()) continue\n fields.set(field, { value, seen: patch.seen, at: patch.at })\n }\n wakeQueue?.()\n }\n const dequeue = (): PresencePatch | null => {\n for (const [participant, fields] of queue) {\n for (const [field, stamp] of fields) {\n fields.delete(field)\n if (fields.size === 0) queue.delete(participant)\n return {\n participant,\n values: { [field]: stamp.value },\n seen: stamp.seen,\n at: stamp.at,\n }\n }\n queue.delete(participant)\n }\n return null\n }\n // Subscribe before the snapshot read: a patch landing between\n // the two is painted twice, never lost — repaints are idempotent.\n const unsubscribe = api.subscribe?.(ns, enqueue)\n\n const events = store.stream(ns, { startAfter })[Symbol.asyncIterator]()\n let pendingEvent: Promise<IteratorResult<Event>> | null = null\n try {\n // Exactly one snapshot before any live item: the pruned map,\n // per-field stamps exact — a reconnecting client replaces its\n // foreign entries wholesale from it.\n const snapshotRows = await readRows()\n for (const row of snapshotRows) {\n let fields = painted.get(row.participant)\n if (!fields) {\n fields = new Map()\n painted.set(row.participant, fields)\n }\n fields.set(row.field, {\n seen: row.seen,\n atMs: row.at.getTime(),\n value: fingerprint(row.value),\n })\n }\n yield { snapshot: foldPresenceRows(snapshotRows) }\n\n for (;;) {\n for (;;) {\n const patch = dequeue()\n if (!patch) break\n paint(patch)\n yield patch\n }\n pendingEvent ??= events.next()\n let woke: 'event' | 'patch' | 'tick'\n if (unsubscribe) {\n const arrival = new Promise<void>((resolve) => {\n wakeQueue = resolve\n })\n woke = await Promise.race([\n pendingEvent.then(() => 'event' as const),\n arrival.then(() => 'patch' as const),\n ])\n wakeQueue = null\n if (woke === 'patch') continue\n } else {\n const sleeper = defaultSleep(POLL_TIMINGS.idleCeilingMs)\n woke = await Promise.race([\n pendingEvent.then(() => 'event' as const),\n sleeper.promise.then(() => 'tick' as const),\n ])\n sleeper.cancel()\n }\n if (woke === 'event') {\n const result = await pendingEvent\n pendingEvent = null\n if (result.done) return\n yield toSessionEvent(id, result.value)\n }\n if (!unsubscribe) {\n for (const patch of diffRows(await readRows())) yield patch\n }\n }\n } finally {\n wakeQueue = null\n unsubscribe?.()\n // The consumer may close while an event read is in flight; its\n // settlement is no longer anyone's business.\n pendingEvent?.catch(() => {})\n await events.return?.()\n }\n }\n return outer()\n }\n\n const makeSession = <Append>(\n id: string,\n append: Append,\n trigger: Pick<StoredEvent, 'id' | 'createdAt' | 'index'> | null,\n ): Session<D, Append, P> =>\n ({\n id,\n append,\n schedule: makeSchedule(id, trigger),\n history: async (bounds?: { gte?: number; lte?: number }) =>\n (await readHistory(id, bounds)).map(toPublic),\n state: <S>(reducer: Reducer<D, S>, stateOptions?: StateOptions) => {\n const through = stateOptions?.through ?? trigger?.index\n if (through !== undefined && through !== 'latest') {\n assertStateIndex(through)\n }\n return readState(\n id,\n reducer,\n through === 'latest' ? undefined : through,\n trigger && through !== 'latest' ? trigger.index : undefined,\n )\n },\n stream: (opts?: { startAfter?: number; presence?: boolean }) => {\n const startAfter = opts?.startAfter ?? 0\n assertStreamIndex(startAfter)\n return opts?.presence === true\n ? streamWithPresence(id, startAfter)\n : streamEvents(id, startAfter)\n },\n // Only on presence-declaring contracts — the type surface promises\n // no runtime-inert members (a2-api.md §12).\n ...(declaresPresence\n ? {\n setPresence: (patch: {\n participant: string\n values: Record<string, unknown>\n seen?: number\n at?: number\n }) => setPresence(id, patch, trigger?.index ?? 0),\n presence: () => readPresenceMap(id),\n }\n : {}),\n }) as Session<D, Append, P>\n\n // ── drain ────────────────────────────────────────────────────────\n\n const makeCtx = (\n trigger: StoredEvent,\n attempt: number,\n signal: AbortSignal,\n ): HandlerContext<D> => {\n const publicSessionId = stripNs(trigger.sessionId)\n const append: HandlerAppend<D> = async (appendName, ...events) => {\n assertAppendName(appendName)\n const generatedIds = events.map((event) => event.id === undefined)\n const withIds = await Promise.all(\n // oxlint-disable-next-line no-map-spread\n events.map(async (event, item) => {\n if (event.id !== undefined) return event\n const id = await deterministicEventId(trigger.id, appendName, item)\n return { ...event, id }\n }),\n )\n return appendCore(\n publicSessionId,\n withIds,\n 'handler',\n 'inline',\n (_rows, watchdogDueAt) => scheduleDrain(publicSessionId, watchdogDueAt),\n { index: trigger.index, attempt },\n generatedIds,\n )\n }\n return {\n event: toPublic(trigger),\n attempt,\n // The handler-scoped `setPresence` stamps `seen` with the\n // triggering event's index by default — the frontier the handler\n // provably reflects.\n session: makeSession(publicSessionId, append, trigger),\n signal,\n }\n }\n\n const abortHubs = new Map<string, AbortHub>()\n\n const createAbortHub = (\n store: A2Store,\n ns: string,\n startAfter: number,\n ): AbortHub => {\n const hub: AbortHub = {\n subscriptions: new Set(),\n seen: new Map(),\n startAfter,\n ready: Promise.resolve(),\n watch: null,\n error: null,\n iterator: null,\n stopped: false,\n }\n hub.ready = (async () => {\n const existing = await store.read(ns, { afterIndex: startAfter })\n for (const event of existing) dispatchAbortEvent(hub, event)\n const tail = existing.at(-1)?.index ?? startAfter\n const feed = store.stream(ns, { startAfter: tail })\n const iterator = feed[Symbol.asyncIterator]()\n hub.iterator = iterator\n hub.watch = (async () => {\n for (;;) {\n const { value, done } = await iterator.next()\n if (done || value === undefined || hub.stopped) return\n dispatchAbortEvent(hub, value)\n }\n })().catch((error: unknown) => {\n hub.error = error\n })\n })().catch((error: unknown) => {\n hub.error = error\n if (abortHubs.get(ns) === hub) abortHubs.delete(ns)\n throw error\n })\n abortHubs.set(ns, hub)\n return hub\n }\n\n const subscribeAbort = async (\n store: A2Store,\n ns: string,\n trigger: StoredEvent,\n abortOn: AbortMatcher,\n attempt: number,\n ): Promise<{\n signal: AbortSignal\n monitor<T>(operation: Promise<T>): Promise<T>\n close(): Promise<void>\n }> => {\n let hub = abortHubs.get(ns)\n if (!hub) hub = createAbortHub(store, ns, trigger.index)\n const activeTypes = new Set<string>()\n for (const active of hub.subscriptions) {\n for (const type of active.types) activeTypes.add(type)\n }\n const publicTrigger = toPublic(trigger)\n const subscription: AbortSubscription = {\n controller: new AbortController(),\n triggerIndex: trigger.index,\n types: new Set(abortOn.keys()),\n matches: (event) => {\n if (event.index <= trigger.index) return false\n const matcher = abortOn.get(event.type)\n if (matcher === undefined) return false\n return matcher === true\n ? true\n : matcher(toPublic(event as StoredEvent), publicTrigger, { attempt })\n },\n }\n hub.subscriptions.add(subscription)\n const needsCatchup =\n trigger.index < hub.startAfter ||\n [...subscription.types].some((type) => !activeTypes.has(type))\n if (needsCatchup) {\n const earlier = await store.read(ns, { afterIndex: trigger.index })\n hub.startAfter = Math.min(hub.startAfter, trigger.index)\n for (const event of earlier) dispatchAbortEvent(hub, event)\n }\n for (const event of hub.seen.values()) {\n if (subscription.matches(event)) subscription.controller.abort()\n }\n await hub.ready\n if (hub.error !== null) throw hub.error\n return {\n signal: subscription.controller.signal,\n monitor: async <T>(operation: Promise<T>): Promise<T> => {\n const outcome = await Promise.race([\n operation.then(\n (value) => ({ type: 'completed' as const, value }),\n (error: unknown) => ({ type: 'handler-failed' as const, error }),\n ),\n hub.watch!.then(() =>\n hub.error === null\n ? { type: 'monitor-closed' as const }\n : { type: 'monitor-failed' as const, error: hub.error },\n ),\n ])\n if (outcome.type === 'completed') return outcome.value\n if (outcome.type === 'handler-failed') throw outcome.error\n if (outcome.type === 'monitor-failed') {\n for (const active of hub.subscriptions) {\n active.controller.abort(outcome.error)\n }\n await operation.catch(() => {})\n throw outcome.error\n }\n await operation.catch(() => {})\n throw new Error('abort monitor closed while handlers were active')\n },\n close: async () => {\n hub.subscriptions.delete(subscription)\n if (hub.subscriptions.size > 0) {\n pruneAbortHub(hub)\n return\n }\n hub.stopped = true\n abortHubs.delete(ns)\n await hub.ready\n await hub.iterator?.return?.()\n await hub.watch\n },\n }\n }\n\n const returnedEvents = async (\n sessionId: string,\n trigger: StoredEvent,\n result: void | AppendInput<D> | readonly AppendInput<D>[],\n ): Promise<ReturnedEvent[]> => {\n if (result === undefined) return []\n const events = Array.isArray(result) ? [...result] : [result]\n if (events.length === 0) return []\n const withIds = await Promise.all(\n // oxlint-disable-next-line oxc/no-map-spread -- handler results remain caller-owned\n events.map(async (event, item) => {\n const withId = { ...event }\n withId.id =\n event.id ?? (await deterministicReturnedEventId(trigger.id, item))\n return withId\n }),\n )\n return validateEvents(sessionId, withIds).map((event) =>\n Object.assign(event, {\n id: event.id!,\n cause: {\n index: trigger.index,\n attempt: trigger.attemptCount,\n },\n }),\n )\n }\n\n type EventStatus =\n 'processed' | 'failed' | 'dead_lettered' | 'superseded' | 'surrendered'\n\n type EventOutcome = {\n status: EventStatus\n opensLane: boolean\n appendsEvents: boolean\n }\n\n const drainSession = (\n sessionId: string,\n watchdogDueAt?: number,\n signal?: DrainSignal,\n ): Promise<DrainResult> =>\n telemetry.span(\n 'a2.drain',\n { 'a2.contract': name, 'a2.session_id': sessionId },\n async (span) => {\n const store = await resolveStore()\n const ns = nsId(sessionId)\n const holder = crypto.randomUUID()\n type ActiveEvent = {\n attempt: number\n execution: Promise<EventOutcome>\n supersede: AbortController\n /** Resolves the tracked execution early once supersession is durable. */\n fence: (outcome: EventOutcome) => void\n /** Local lease estimate: request time + ttl — at or before the store's. */\n expiresAtMs: number\n lapsed: boolean\n }\n const active = new Map<number, ActiveEvent>()\n const excluded = new Set<number>()\n let processed = 0\n let sawFailure = false\n let schedulerArm: Promise<void> | undefined\n let heartbeat: ReturnType<typeof setInterval> | null = null\n let lapseTimer: ReturnType<typeof setTimeout> | null = null\n let retryTimer: ReturnType<typeof setTimeout> | null = null\n let renewal: Promise<void> | null = null\n let stopRenewing = false\n\n // Self-fencing at local lease lapse: the drain wrote every expiry it\n // holds (request time + ttl, at or before the store's own stamp), so\n // it can conclude \"assume a successor\" with zero I/O — including\n // while the store is unreachable or in the first tick after a stall.\n const lapseDue = (): void => {\n lapseTimer = null\n const nowMs = Date.now()\n for (const [index, entry] of active) {\n if (entry.lapsed || entry.expiresAtMs > nowMs) continue\n entry.lapsed = true\n entry.supersede.abort(\n new A2Error(\n 'CLAIM_EXPIRED',\n `the claim on event ${index} in session '${sessionId}' lapsed without renewal`,\n ),\n )\n }\n scheduleLapse()\n }\n const scheduleLapse = (): void => {\n if (lapseTimer) {\n clearTimeout(lapseTimer)\n lapseTimer = null\n }\n let next = Number.POSITIVE_INFINITY\n for (const entry of active.values()) {\n if (!entry.lapsed) next = Math.min(next, entry.expiresAtMs)\n }\n if (next === Number.POSITIVE_INFINITY) return\n lapseTimer = setTimeout(lapseDue, Math.max(0, next - Date.now()))\n ;(lapseTimer as { unref?: () => void }).unref?.()\n }\n\n // A missed beat spends lease slack; the next scheduled beat may be\n // provably too late. Retry promptly (jittered against fleet-wide\n // synchronization on a struggling store) while a lease can still be\n // saved — the lapse ends the retries naturally.\n const scheduleRenewRetry = (): void => {\n if (stopRenewing || retryTimer) return\n const nowMs = Date.now()\n const saveable = [...active.values()].some(\n (entry) => !entry.lapsed && entry.expiresAtMs > nowMs,\n )\n if (!saveable) return\n const delay = DRAIN_TIMINGS.renewRetryMs * (0.5 + Math.random() * 0.5)\n retryTimer = setTimeout(() => {\n retryTimer = null\n void renew()\n }, delay)\n ;(retryTimer as { unref?: () => void }).unref?.()\n }\n\n const alignWatchdogAt = (minimumDueAt: number): number => {\n if (watchdogDueAt === undefined) return minimumDueAt\n const beats = Math.max(\n 0,\n Math.ceil(\n (minimumDueAt - watchdogDueAt) / DRAIN_TIMINGS.claimHeartbeatMs,\n ),\n )\n return watchdogDueAt + beats * DRAIN_TIMINGS.claimHeartbeatMs\n }\n\n const requestWatchdog = (dueAt: number): void => {\n const arm = startSchedulerArm(sessionId, alignWatchdogAt(dueAt))\n if (arm) schedulerArm = arm\n }\n\n const renew = (): Promise<void> => {\n if (stopRenewing || renewal || active.size === 0) {\n return renewal ?? Promise.resolve()\n }\n const window = nextClaimWindow()\n requestWatchdog(window.watchdogAtMs)\n const claims = [...active.entries()].map(([index, entry]) => ({\n index,\n attempt: entry.attempt,\n }))\n const operation = store\n .renewClaims({\n sessionId: ns,\n holder,\n claims,\n ttlMs: window.ttlMs,\n ...(window.deadlineCapped\n ? { expiresAtMs: window.expiresAtMs }\n : {}),\n })\n .then(\n (result) => {\n for (const index of result.renewed) {\n const entry = active.get(index)\n if (entry && !entry.lapsed) {\n entry.expiresAtMs = window.expiresAtMs\n }\n }\n for (const index of result.superseded) {\n const entry = active.get(index)\n if (!entry) continue\n // Idempotent: the local lapse normally aborted this signal\n // already — this is the proof, whose job is the release.\n entry.supersede.abort(\n new A2Error(\n 'SUPERSEDED_ATTEMPT',\n `a newer attempt owns event ${index} in session '${sessionId}'`,\n ),\n )\n entry.fence({\n status: 'superseded',\n opensLane: false,\n appendsEvents: false,\n })\n }\n if (window.deadlineCapped) stopRenewing = true\n scheduleLapse()\n return undefined\n },\n () => {\n scheduleRenewRetry()\n return undefined\n },\n )\n let tracked!: Promise<void>\n tracked = operation.finally(() => {\n if (renewal === tracked) renewal = null\n })\n renewal = tracked\n return tracked\n }\n\n const runEvent = async (\n event: StoredEvent,\n supersedeSignal: AbortSignal,\n ): Promise<EventOutcome> => {\n const registration = handlers.get(event.type)\n return telemetry.span(\n 'a2.event',\n {\n 'a2.contract': name,\n 'a2.session_id': sessionId,\n 'a2.event.type': event.type,\n 'a2.event.index': event.index,\n 'a2.event.id': event.id,\n 'a2.event.attempt': event.attemptCount,\n 'a2.event.handled': registration !== undefined,\n ...(event.lane === null ? {} : { 'a2.event.lane': event.lane }),\n },\n async (eventSpan) => {\n let subscription:\n | {\n signal: AbortSignal\n monitor<T>(operation: Promise<T>): Promise<T>\n close(): Promise<void>\n }\n | undefined\n let handlerSignal = supersedeSignal\n let returned: ReturnedEvent[]\n try {\n if (registration?.abortOn) {\n subscription = await subscribeAbort(\n store,\n ns,\n event,\n registration.abortOn,\n event.attemptCount,\n )\n handlerSignal = AbortSignal.any([\n supersedeSignal,\n subscription.signal,\n ])\n }\n const operation = registration?.handler(\n makeCtx(event, event.attemptCount, handlerSignal),\n )\n const result = operation\n ? await (subscription\n ? subscription.monitor(operation)\n : operation)\n : undefined\n if (subscription) {\n await subscription.close()\n subscription = undefined\n }\n returned = await returnedEvents(sessionId, event, result)\n } catch (err) {\n if (supersedeSignal.aborted && err === supersedeSignal.reason) {\n // The handler surrendered to its own abort — identity, not\n // code, so it cannot arrive from another context. A lapse\n // is not a handler failure: no completion, no failure\n // budget spent; the claim simply expires and recovery\n // retries.\n eventSpan.setAttribute('a2.event.outcome', 'surrendered')\n return {\n status: 'surrendered',\n opensLane: false,\n appendsEvents: false,\n }\n }\n // Everything else — including a store fence rejection — is\n // adjudicated by failAttempt, which is itself fenced: a\n // genuinely superseded attempt gets 'superseded' back with\n // no mutation. One adjudicator, not two.\n eventSpan.recordError(err)\n const failure = await store.failAttempt({\n sessionId: ns,\n index: event.index,\n attempt: event.attemptCount,\n error: describeError(err),\n maxFailures: MAX_FAILURES,\n })\n eventSpan.setAttribute('a2.event.outcome', failure.outcome)\n return {\n status: failure.outcome,\n opensLane: false,\n appendsEvents: false,\n }\n } finally {\n await subscription?.close()\n }\n await renewal\n const completion = await store.completeAttempt({\n sessionId: ns,\n index: event.index,\n attempt: event.attemptCount,\n events: returned,\n })\n eventSpan.setAttribute(\n 'a2.event.outcome',\n completion.outcome === 'completed'\n ? 'processed'\n : completion.outcome,\n )\n if (completion.outcome === 'superseded') {\n return {\n status: 'superseded',\n opensLane: false,\n appendsEvents: false,\n }\n }\n if (handlerSignal.aborted) {\n eventSpan.setAttribute('a2.event.aborted', true)\n }\n return {\n status: 'processed',\n opensLane: event.lane !== null,\n appendsEvents: returned.length > 0,\n }\n },\n )\n }\n\n let claimAgain = false\n\n const start = (event: StoredEvent, expiresAtMs: number): void => {\n // Re-claiming an index this drain still tracks is durable proof\n // that the old attempt lost: our own new claim advanced the\n // ordinal. Fence the old entry before it can be confused with\n // the new one.\n const previous = active.get(event.index)\n if (previous) {\n previous.supersede.abort(\n new A2Error(\n 'SUPERSEDED_ATTEMPT',\n `a newer attempt owns event ${event.index} in session '${sessionId}'`,\n ),\n )\n previous.fence({\n status: 'superseded',\n opensLane: false,\n appendsEvents: false,\n })\n }\n const supersede = new AbortController()\n let fence!: (outcome: EventOutcome) => void\n const fenced = new Promise<EventOutcome>((resolve) => {\n fence = resolve\n })\n // The race lets a durable supersession release this slot while the\n // zombie handler keeps running — its completion and failure are\n // fenced by the store, so nothing it does from here is counted.\n let entry!: ActiveEvent\n const execution = Promise.race([\n runEvent(event, supersede.signal),\n fenced,\n ]).then((eventOutcome) => {\n // Identity-guarded: a fenced predecessor's continuation must\n // not delete the entry of the attempt that replaced it.\n if (active.get(event.index) === entry) active.delete(event.index)\n if (eventOutcome.status === 'processed') processed += 1\n if (eventOutcome.status === 'failed') {\n excluded.add(event.index)\n sawFailure = true\n }\n claimAgain ||= eventOutcome.opensLane || eventOutcome.appendsEvents\n return eventOutcome\n })\n entry = {\n attempt: event.attemptCount,\n execution,\n supersede,\n fence,\n expiresAtMs,\n lapsed: false,\n }\n active.set(event.index, entry)\n scheduleLapse()\n if (!heartbeat && !stopRenewing) {\n heartbeat = setInterval(\n () => void renew(),\n DRAIN_TIMINGS.claimHeartbeatMs,\n )\n ;(heartbeat as { unref?: () => void }).unref?.()\n }\n }\n\n let outcome: DrainOutcome = 'settled'\n let shouldClaim = true\n try {\n for (;;) {\n const signalVersion = signal?.version ?? 0\n let claim: StoreClaimAvailableResult | undefined\n if (shouldClaim) {\n const window = nextClaimWindow()\n claim = await store.claimAvailable({\n sessionId: ns,\n holder,\n ttlMs: window.ttlMs,\n ...(window.deadlineCapped\n ? { expiresAtMs: window.expiresAtMs }\n : {}),\n ...(excluded.size === 0\n ? {}\n : { excludeIndexes: [...excluded] }),\n })\n if (claim.outcome === 'claimed') {\n requestWatchdog(window.watchdogAtMs)\n if (window.deadlineCapped) stopRenewing = true\n for (const event of claim.events) {\n start(event, window.expiresAtMs)\n }\n shouldClaim = false\n }\n }\n if (\n claim?.outcome === 'claimed' &&\n [...active.values()].some((entry) => entry.lapsed)\n ) {\n shouldClaim = true\n continue\n }\n if (active.size > 0) {\n const wake = signal?.wait(signalVersion)\n const hasLapsed = [...active.values()].some(\n (entry) => entry.lapsed,\n )\n const retry =\n claim?.outcome === 'busy' && hasLapsed\n ? defaultSleep(\n Math.max(0, claim.retryAt.getTime() - Date.now()),\n )\n : undefined\n const retryDue = await Promise.race([\n ...[...active.values()].map((entry) =>\n entry.execution.then(() => false),\n ),\n ...(wake ? [wake.promise.then(() => false)] : []),\n ...(retry ? [retry.promise.then(() => true)] : []),\n ])\n wake?.cancel()\n retry?.cancel()\n shouldClaim =\n retryDue ||\n claimAgain ||\n active.size === 0 ||\n hasLapsed ||\n (signal !== undefined && signal.version !== signalVersion)\n claimAgain = false\n continue\n }\n if (!shouldClaim) {\n shouldClaim = true\n continue\n }\n if (claim === undefined) continue\n if (signal && signal.version !== signalVersion) continue\n if (claim.outcome === 'busy') {\n requestWatchdog(\n claim.retryAt.getTime() + DRAIN_TIMINGS.watchdogGraceMs,\n )\n outcome = 'busy'\n } else if (sawFailure) {\n outcome = 'stalled'\n }\n if (signal) signal.closed = true\n break\n }\n } finally {\n if (signal) signal.closed = true\n stopRenewing = true\n if (heartbeat) clearInterval(heartbeat)\n if (retryTimer) clearTimeout(retryTimer)\n await renewal\n await Promise.allSettled(\n [...active.values()].map((entry) => entry.execution),\n )\n if (lapseTimer) clearTimeout(lapseTimer)\n }\n span.setAttribute('a2.drain.processed', processed)\n span.setAttribute('a2.drain.outcome', outcome)\n return {\n settled: outcome === 'settled',\n outcome,\n processed,\n ...(schedulerArm ? { schedulerArm } : {}),\n }\n },\n )\n\n // ── public surface ───────────────────────────────────────────────\n\n const appendExternal = async (\n sessionId: string,\n mode: 'inline' | 'dispatch',\n events: AppendInput<D>[],\n requireDurableInitialArm = false,\n ): Promise<ContractEvent<D>[]> => {\n return appendCore(\n sessionId,\n events,\n 'external',\n mode,\n (_rows, watchdogDueAt) => scheduleDrain(sessionId, watchdogDueAt),\n undefined,\n undefined,\n requireDurableInitialArm,\n )\n }\n\n const session = (id: string): Session<D, SessionAppend<D>, P> => {\n assertSessionId(id)\n const appendInline = async (...events: AppendInput<D>[]) =>\n appendExternal(id, 'inline', events)\n const appendDispatch = async (...events: AppendInput<D>[]) =>\n appendExternal(id, 'dispatch', events)\n const append = Object.assign(appendInline, {\n dispatch: appendDispatch,\n }) as SessionAppend<D>\n return makeSession(id, append, null)\n }\n\n const fetch = createServerFetch({ contract: serverContract, session })\n const self: A2Server<D, P> = {\n contract: serverContract,\n fetch,\n session,\n\n async drain(sessionId) {\n assertSessionId(sessionId)\n const { settled } = await drainSession(sessionId)\n return { settled }\n },\n }\n\n serverInternals.set(self, {\n settle: async () => {\n while (inFlight.size > 0) {\n await Promise.allSettled(inFlight)\n }\n },\n schedulerDrain: (sessionId, opts) => {\n assertSessionId(sessionId)\n return drainSession(sessionId, opts?.watchdogDueAt)\n },\n schedulerAppend: async (sessionId, events) => {\n if (!scheduler) {\n throw new TypeError(\n 'scheduled append delivery requires a configured scheduler adapter',\n )\n }\n assertSessionId(sessionId)\n await appendExternal(sessionId, 'inline', [...events], true)\n },\n })\n return self\n}\n\nfunction assertSessionId(id: string): void {\n if (typeof id !== 'string' || id.length === 0) {\n throw new TypeError('session id must be a non-empty string')\n }\n if (id.includes(NS)) {\n throw new TypeError('session id contains a reserved control character')\n }\n}\n\nfunction assertHistoryIndex(name: 'gte' | 'lte', value?: number): void {\n if (value !== undefined && (!Number.isSafeInteger(value) || value < 0)) {\n throw new TypeError(`history.${name} must be a non-negative safe integer`)\n }\n}\n\nfunction assertStreamIndex(value: number): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new TypeError('stream.startAfter must be a non-negative safe integer')\n }\n}\n\nfunction assertStateIndex(value: number): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new TypeError('state.through must be a non-negative safe integer')\n }\n}\n\nfunction assertAppendName(name: string): void {\n if (typeof name !== 'string' || name.length === 0) {\n throw new TypeError('handler append name must be a non-empty string')\n }\n}\n\nfunction assertScheduleName(name: string): void {\n if (typeof name !== 'string' || name.length === 0) {\n throw new TypeError('schedule name must be a non-empty string')\n }\n}\n\nconst SCHEDULE_DELAY = /^(?:0|[1-9]\\d*)(?:\\.\\d+)?(ms|s|m|h|d)$/\nconst SCHEDULE_DELAY_MULTIPLIER: Record<'ms' | 's' | 'm' | 'h' | 'd', number> =\n {\n ms: 1,\n s: 1_000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n }\n\nfunction scheduleDueAt(timing: ScheduleTiming, baseTime: number): number {\n if (timing === null || typeof timing !== 'object' || Array.isArray(timing)) {\n throw new TypeError(\n \"schedule timing must contain exactly one of 'delay' or 'at'\",\n )\n }\n const record = timing as Record<string, unknown>\n const hasDelay = Object.hasOwn(record, 'delay')\n const hasAt = Object.hasOwn(record, 'at')\n if (hasDelay === hasAt) {\n throw new TypeError(\n \"schedule timing must contain exactly one of 'delay' or 'at'\",\n )\n }\n\n let dueAt: number\n if (hasAt) {\n const at = record['at']\n if (!(at instanceof Date) || !Number.isFinite(at.getTime())) {\n throw new TypeError('schedule at must be a valid Date')\n }\n dueAt = at.getTime()\n } else {\n const delay = record['delay']\n if (typeof delay !== 'string') {\n throw new TypeError(\n \"schedule delay must use ms, s, m, h, or d (for example '30s')\",\n )\n }\n const match = SCHEDULE_DELAY.exec(delay)\n const amount = match ? Number(delay.slice(0, -match[1]!.length)) : NaN\n if (!match || !Number.isFinite(amount) || amount <= 0) {\n throw new TypeError(\n \"schedule delay must be positive and use ms, s, m, h, or d (for example '30s')\",\n )\n }\n dueAt =\n baseTime +\n amount *\n SCHEDULE_DELAY_MULTIPLIER[\n match[1] as keyof typeof SCHEDULE_DELAY_MULTIPLIER\n ]\n }\n if (!Number.isFinite(dueAt)) {\n throw new TypeError('schedule due time must be a finite epoch time')\n }\n return dueAt\n}\n\nfunction assertScheduledPayload(payload: unknown): void {\n try {\n if (isJsonValue(payload, new WeakSet())) return\n } catch {\n // Proxies and hostile accessors are not stable transport values either.\n }\n throw new TypeError(\n 'session.schedule event payload must be JSON-serializable',\n )\n}\n\nfunction cloneScheduledPayload(payload: unknown): unknown {\n assertScheduledPayload(payload)\n try {\n const cloned = structuredClone(payload)\n const encoded = JSON.stringify(cloned)\n if (encoded === undefined) throw new TypeError()\n return JSON.parse(encoded) as unknown\n } catch {\n throw new TypeError(\n 'session.schedule event payload must be JSON-serializable',\n )\n }\n}\n\nfunction isJsonValue(value: unknown, ancestors: WeakSet<object>): boolean {\n if (value === null) return true\n if (typeof value === 'string' || typeof value === 'boolean') return true\n if (typeof value === 'number') {\n return Number.isFinite(value) && !Object.is(value, -0)\n }\n if (typeof value !== 'object') return false\n if (ancestors.has(value)) return false\n ancestors.add(value)\n try {\n if (Array.isArray(value)) {\n const keys = Reflect.ownKeys(value)\n if (keys.length !== value.length + 1 || !keys.includes('length')) {\n return false\n }\n for (let index = 0; index < value.length; index += 1) {\n const descriptor = Object.getOwnPropertyDescriptor(value, String(index))\n if (\n !descriptor ||\n !descriptor.enumerable ||\n !('value' in descriptor) ||\n !isJsonValue(descriptor.value, ancestors)\n ) {\n return false\n }\n }\n return true\n }\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype) return false\n for (const key of Reflect.ownKeys(value)) {\n if (typeof key !== 'string') return false\n const descriptor = Object.getOwnPropertyDescriptor(value, key)\n if (\n !descriptor ||\n !descriptor.enumerable ||\n !('value' in descriptor) ||\n !isJsonValue(descriptor.value, ancestors)\n ) {\n return false\n }\n }\n return true\n } finally {\n ancestors.delete(value)\n }\n}\n\nfunction cloneInitial<S>(initial: S): S {\n // Defensive: a reducer that mutates state in place must not corrupt\n // the shared initialState across folds. Fall back to the original for\n // non-cloneable values (functions, class instances).\n try {\n return structuredClone(initial)\n } catch {\n return initial\n }\n}\n\n// Server-side types users need when passing custom stores or building\n// transports — re-exported so experimental-a2/server is self-sufficient.\nexport type {\n A2Store,\n AppendEvent,\n Clock,\n Event,\n EventCause,\n FailAttemptResult,\n IdSource,\n StoreAppendResult,\n StoreClaimAvailableResult,\n StoreStateRead,\n PresenceRow,\n StoredEvent,\n} from './store.ts'\nexport type {\n ScheduledEvent,\n SchedulerAppendTask,\n SchedulerDrainTask,\n SchedulerTask,\n} from './scheduler-task.ts'\nexport type {\n AppendInput,\n Contract,\n ContractEvent,\n EventDefs,\n PresenceDefs,\n PresenceMap,\n PresencePatch,\n PresenceSnapshot,\n} from './contract.ts'\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { a as EventDefs, c as PresencePatch, d as WithPresence, l as PresenceSnapshot, n as Contract, o as PresenceDefs, p as Reducer, r as ContractEvent, s as PresenceMap, t as AppendInput } from "./contract-jIfaR085.js";
2
- import { t as A2Store } from "./store-flRz1OWh.js";
2
+ import { t as A2Store } from "./store-RJO35BMj.js";
3
3
  import { i as A2Telemetry } from "./telemetry-CpeclqB2.js";
4
4
  //#region src/session-socket.d.ts
5
5
  /**
@@ -124,6 +124,9 @@ type ScheduleTiming = {
124
124
  delay?: never;
125
125
  };
126
126
  type SessionSchedule<D extends EventDefs> = (name: string, timing: ScheduleTiming, ...events: AppendInput<D>[]) => Promise<void>;
127
+ type StateOptions = {
128
+ through?: number | "latest";
129
+ };
127
130
  /**
128
131
  * The presence members of a session — intersected in via
129
132
  * `WithPresence`, so they exist exactly when the contract declares
@@ -165,7 +168,7 @@ type Session<D extends EventDefs, Append = SessionAppend<D>, P extends PresenceD
165
168
  gte?: number;
166
169
  lte?: number;
167
170
  }): Promise<ContractEvent<D>[]>;
168
- state<S>(reducer: Reducer<D, S>): Promise<{
171
+ state<S>(reducer: Reducer<D, S>, options?: StateOptions): Promise<{
169
172
  state: S;
170
173
  index: number;
171
174
  }>;
@@ -275,5 +278,5 @@ type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, n
275
278
  /** Implement a contract: bind its vocabulary to storage and reactions. */
276
279
  declare function createServer<D extends EventDefs, P extends PresenceDefs = Record<never, never>>(options: ServerOptions<D, P>): A2Server<D, P>;
277
280
  //#endregion
278
- export { A2Socket as A, SchedulerDrainTask as C, A2PushPresence as D, A2PushEvent as E, ServerFetchOptions as O, SchedulerAppendTask as S, A2Operation as T, SessionPresence as _, Handler as a, deliverSchedulerAppend as b, HandlerEntry as c, ScheduleDelay as d, ScheduleTiming as f, SessionDispatch as g, SessionAppend as h, DrainableServer as i, UpgradeWebSocket as k, Lane as l, Session as m, A2Server as n, HandlerAppend as o, ServerOptions as p, AbortSpec as r, HandlerContext as s, A2Scheduler as t, LaneContext as u, SessionSchedule as v, SchedulerTask as w, ScheduledEvent as x, createServer as y };
279
- //# sourceMappingURL=server-DgXmORIq.d.ts.map
281
+ export { UpgradeWebSocket as A, SchedulerAppendTask as C, A2PushEvent as D, A2Operation as E, A2PushPresence as O, ScheduledEvent as S, SchedulerTask as T, SessionPresence as _, Handler as a, createServer as b, HandlerEntry as c, ScheduleDelay as d, ScheduleTiming as f, SessionDispatch as g, SessionAppend as h, DrainableServer as i, A2Socket as j, ServerFetchOptions as k, Lane as l, Session as m, A2Server as n, HandlerAppend as o, ServerOptions as p, AbortSpec as r, HandlerContext as s, A2Scheduler as t, LaneContext as u, SessionSchedule as v, SchedulerDrainTask as w, deliverSchedulerAppend as x, StateOptions as y };
282
+ //# sourceMappingURL=server-DjPhHnbI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-DjPhHnbI.d.ts","names":[],"sources":["../src/session-socket.ts","../src/server-fetch.ts","../src/scheduler-task.ts","../src/server.ts"],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { a as EventDefs, c as PresencePatch, l as PresenceSnapshot, n as Contract, o as PresenceDefs, r as ContractEvent, s as PresenceMap, t as AppendInput } from "./contract-jIfaR085.js";
2
- import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-flRz1OWh.js";
3
- import { A as A2Socket, C as SchedulerDrainTask, D as A2PushPresence, E as A2PushEvent, O as ServerFetchOptions, S as SchedulerAppendTask, T as A2Operation, _ as SessionPresence, a as Handler, b as deliverSchedulerAppend, c as HandlerEntry, d as ScheduleDelay, f as ScheduleTiming, g as SessionDispatch, h as SessionAppend, i as DrainableServer, k as UpgradeWebSocket, l as Lane, m as Session, n as A2Server, o as HandlerAppend, p as ServerOptions, r as AbortSpec, s as HandlerContext, t as A2Scheduler, u as LaneContext, v as SessionSchedule, w as SchedulerTask, x as ScheduledEvent, y as createServer } from "./server-DgXmORIq.js";
4
- export { type A2Operation, type A2PushEvent, type A2PushPresence, A2Scheduler, A2Server, type A2Socket, type A2Store, AbortSpec, type AppendEvent, type AppendInput, type Clock, type Contract, type ContractEvent, DrainableServer, type Event, type EventCause, type EventDefs, type FailAttemptResult, Handler, HandlerAppend, HandlerContext, HandlerEntry, type IdSource, Lane, LaneContext, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceRow, type PresenceSnapshot, ScheduleDelay, ScheduleTiming, type ScheduledEvent, type SchedulerAppendTask, type SchedulerDrainTask, type SchedulerTask, type ServerFetchOptions, ServerOptions, Session, SessionAppend, SessionDispatch, SessionPresence, SessionSchedule, type StoreAppendResult, type StoreClaimAvailableResult, type StoreStateRead, type StoredEvent, type UpgradeWebSocket, createServer, deliverSchedulerAppend };
2
+ import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-RJO35BMj.js";
3
+ import { A as UpgradeWebSocket, C as SchedulerAppendTask, D as A2PushEvent, E as A2Operation, O as A2PushPresence, S as ScheduledEvent, T as SchedulerTask, _ as SessionPresence, a as Handler, b as createServer, c as HandlerEntry, d as ScheduleDelay, f as ScheduleTiming, g as SessionDispatch, h as SessionAppend, i as DrainableServer, j as A2Socket, k as ServerFetchOptions, l as Lane, m as Session, n as A2Server, o as HandlerAppend, p as ServerOptions, r as AbortSpec, s as HandlerContext, t as A2Scheduler, u as LaneContext, v as SessionSchedule, w as SchedulerDrainTask, x as deliverSchedulerAppend, y as StateOptions } from "./server-DjPhHnbI.js";
4
+ export { type A2Operation, type A2PushEvent, type A2PushPresence, A2Scheduler, A2Server, type A2Socket, type A2Store, AbortSpec, type AppendEvent, type AppendInput, type Clock, type Contract, type ContractEvent, DrainableServer, type Event, type EventCause, type EventDefs, type FailAttemptResult, Handler, HandlerAppend, HandlerContext, HandlerEntry, type IdSource, Lane, LaneContext, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceRow, type PresenceSnapshot, ScheduleDelay, ScheduleTiming, type ScheduledEvent, type SchedulerAppendTask, type SchedulerDrainTask, type SchedulerTask, type ServerFetchOptions, ServerOptions, Session, SessionAppend, SessionDispatch, SessionPresence, SessionSchedule, StateOptions, type StoreAppendResult, type StoreClaimAvailableResult, type StoreStateRead, type StoredEvent, type UpgradeWebSocket, createServer, deliverSchedulerAppend };
package/dist/server.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as deliverSchedulerAppend, t as createServer } from "./server-286j79Mt.js";
1
+ import { n as deliverSchedulerAppend, t as createServer } from "./server-B2XNevQA.js";
2
2
  export { createServer, deliverSchedulerAppend };
@@ -1 +1 @@
1
- {"version":3,"file":"store-N8PXxDAS.js","names":[],"sources":["../src/store.ts"],"sourcesContent":["/**\n * The A2Store interface — the storage contract every store backend\n * implements. See specs/a2-implementation.md §2–3.\n *\n * This is the whole storage contract: append, read, dispatch claims,\n * failure markers, snapshots, and the live stream. The scheduler\n * needs nothing extra — the armed queue message is its own state, and\n * the store is the only thing it consults.\n */\n\nimport type { PresencePatch } from './contract.ts'\n\n/** A stored event, as the public API exposes it. */\nexport type Event = {\n id: string\n type: string\n payload: unknown\n /** Position in the session's event log, from 1. */\n index: number\n sessionId: string\n createdAt: Date\n}\n\n/** The handler dispatch whose append first persisted a child event. */\nexport type EventCause = {\n index: number\n attempt: number\n /** Size of one named handler append, used to reject truncated retries. */\n batchSize?: number\n}\n\n/**\n * What the store persists: immutable event history, including its causal edge,\n * plus derived dispatch and failure bookkeeping. The bookkeeping is disposable;\n * the event and its cause are not.\n */\nexport type StoredEvent = Event & {\n /** Same-session handler dispatch that appended this event; null means root. */\n cause: EventCause | null\n /** Session-scoped serial execution key resolved when the event is appended. */\n lane: string | null\n /** Adapter clock time recorded by append settlement, completion, or manual skip; null while pending. */\n processedAt: Date | null\n /** Dispatch attempt that completed this event; null without dispatch or while pending. */\n processedByAttempt: number | null\n /** Exact ordered child ids atomically returned by the completing attempt. */\n returnedEventIds: string[] | null\n /** Adapter clock time recorded by the first durable dispatch claim. */\n firstClaimedAt: Date | null\n /** Adapter clock time recorded by the most recent durable dispatch claim. */\n lastClaimedAt: Date | null\n /** Durable dispatch claims, including claims abandoned by hard kills. */\n attemptCount: number\n /** Current dispatch holder; null when the event is not claimed. */\n claimHolder: string | null\n /** Adapter clock expiry for the current dispatch claim. */\n claimExpiresAt: Date | null\n /** Caught handler failures. This alone drives dead-lettering. */\n failureCount: number\n /** Adapter clock time recorded by the most recent caught handler failure. */\n lastFailedAt: Date | null\n /** Dispatch attempt that produced the most recent caught handler failure. */\n lastFailedAttempt: number | null\n /** The last handler failure, stringified. */\n lastError: string | null\n /** Adapter clock time recorded when dead-lettered; null otherwise. */\n failedAt: Date | null\n}\n\n/**\n * One live presence value, as `A2Store.presence.read` returns it. The\n * row is the LWW unit — one participant's one field. `at` is the\n * sender's stamp, the LWW comparator. `expiresAt` is the storage's\n * own clock at the applied set plus its `ttlMs` — never derived from\n * the sender stamp; a row is live strictly before it.\n */\nexport type PresenceRow = {\n participant: string\n field: string\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\n/** One consistent cache-plus-tail read for a reducer fold. */\nexport type StoreStateRead = {\n /** The latest cached fold for this reducer, if one exists. */\n snapshot: { index: number; state: unknown } | null\n /** Immutable events strictly after `snapshot.index`, or the full log on a miss. */\n events: Event[]\n}\n\n/** The result of atomically claiming every currently eligible event. */\nexport type StoreClaimAvailableResult =\n | { outcome: 'claimed'; events: StoredEvent[] }\n | { outcome: 'busy'; retryAt: Date }\n | { outcome: 'settled' }\n\n/** A completion may lose to a newer claim or an earlier completion. */\nexport type CompleteAttemptResult =\n { outcome: 'completed'; events: StoredEvent[] } | { outcome: 'superseded' }\n\n/** The result of one claim-renewal heartbeat, both lists in append order. */\nexport type RenewClaimsResult = {\n /** Listed claims that remain owned by the holder. */\n renewed: number[]\n /** Listed claims whose event a newer attempt has durably taken. */\n superseded: number[]\n}\n\n/** The result of atomically recording a caught handler failure. */\nexport type FailAttemptResult = {\n outcome: 'failed' | 'dead_lettered' | 'superseded'\n failureCount: number\n}\n\n/** Input to `A2Store.append` — already validated by the machine. */\nexport type AppendEvent = {\n type: string\n payload: unknown\n /** Caller-supplied idempotency key; generated when absent. */\n id?: string\n /** Internal causal edge supplied atomically by handler `session.append`. */\n cause?: EventCause\n /** Session-scoped serial execution key resolved before persistence. */\n lane?: string\n /** Internal hint: settle this event in the append transaction; no handler is registered. */\n settled?: true\n}\n\n/** A handler-returned event with the deterministic id retries require. */\nexport type ReturnedEvent = AppendEvent & { id: string }\n\n/** The rows written by an append and the session's pending state. */\nexport type StoreAppendResult = {\n events: StoredEvent[]\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\n/**\n * An injectable clock. Adapters take one so tests can drive claim\n * expiry, failure timestamps, and (later) stuck-session detection\n * deterministically — against real storage, no mocking.\n */\nexport type Clock = {\n now(): Date\n}\n\n/** An injectable id source for generated event ids. */\nexport type IdSource = () => string\n\nexport const SYSTEM_CLOCK: Clock = {\n now: () => new Date(),\n}\n\nexport const RANDOM_IDS: IdSource = () => crypto.randomUUID()\n\nexport interface A2Store {\n /**\n * Accepts a batch; the batch is atomic — one transaction, consecutive\n * `index`es, all-or-nothing. The idempotency key covers the whole\n * operation, not each item: if *every* event's `id` already exists in\n * this session, this is a retry of a committed batch whose ack was\n * lost — return the existing rows as success. If only *some* ids\n * exist, the caller mixed an already-sent batch with fresh events —\n * always a caller bug — so throw `A2Error('PARTIAL_DUPLICATE_BATCH')`.\n * Events carrying `settled: true` get `processedAt` in this same atomic\n * operation, with no dispatch claim or `processedByAttempt`. The result's\n * `hasPending` reflects the whole session in the same atomic operation,\n * including older events and idempotent retries.\n *\n * An event carrying `cause` is a handler append, fenced by attempt\n * currency: accept it only while `cause.attempt` is still the parent\n * event's latest attempt and the parent is not dead-lettered; otherwise\n * throw `A2Error('SUPERSEDED_ATTEMPT')` and write nothing. The check is\n * part of this atomic operation and must serialize against a concurrent\n * `claimAvailable` — an unlocked read of the parent admits write skew.\n * The idempotent-replay path runs first, so a batch whose ids all exist\n * replays regardless of the current attempt.\n */\n append(sessionId: string, events: AppendEvent[]): Promise<StoreAppendResult>\n\n /** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */\n read(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<StoredEvent[]>\n\n /**\n * Atomically claims every eligible pending event. Unlaned events are all\n * independently eligible. Within a lane, only the lowest-index unfinished\n * event is eligible. A live claim produces `busy` only when it is the sole\n * remaining obstacle to actionable work. Claimed events are returned in event-log\n * order. Excluded rows remain lane barriers.\n */\n claimAvailable(options: {\n sessionId: string\n holder: string\n ttlMs: number\n expiresAtMs?: number\n excludeIndexes?: readonly number[]\n }): Promise<StoreClaimAvailableResult>\n\n /**\n * Renews the listed live claims still owned by `holder`. Each listed claim\n * carries the attempt ordinal the holder owns. `renewed` lists the claims\n * that remain owned after the operation; `superseded` lists the claims\n * whose event's `attemptCount` has durably passed the listed attempt. An\n * expired claim no successor has taken appears in neither list — its\n * attempt may still complete (`completeAttempt` is the fence), so it is\n * not reported as lost. Renewal never revives an expired claim.\n */\n renewClaims(options: {\n sessionId: string\n holder: string\n claims: readonly { index: number; attempt: number }[]\n ttlMs: number\n expiresAtMs?: number\n }): Promise<RenewClaimsResult>\n\n /**\n * Atomically completes one current attempt and appends its returned events.\n * Retrying a committed completion with the same attempt and deterministic\n * child ids returns the existing children. A stale attempt never appends.\n */\n completeAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n events: ReturnedEvent[]\n }): Promise<CompleteAttemptResult>\n\n /**\n * Atomically records a caught failure for one claimed attempt. A stale\n * attempt cannot poison a processed event or a newer dispatch. Accepted\n * failures record the operation's clock time.\n */\n failAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n error: string\n maxFailures: number\n }): Promise<FailAttemptResult>\n\n /**\n * Reads a reducer snapshot and its event tail as one consistent adapter\n * operation. On a cache miss, `snapshot` is null and `events` is the full\n * log. The snapshot is untrusted; core may reject it and issue a full\n * `read()` when its state schema no longer accepts the cached value.\n */\n readState(sessionId: string, reducerName: string): Promise<StoreStateRead>\n\n /**\n * Optional batched `readState` — one consistent snapshot-plus-tail read\n * per session id, aligned positionally with the input (duplicates\n * allowed). Each element has its own frontier; the batch makes no\n * cross-session consistency claim. Core falls back to parallel\n * `readState` calls when absent.\n */\n readStates?(\n sessionIds: string[],\n reducerName: string,\n ): Promise<StoreStateRead[]>\n\n /**\n * Writes a disposable reducer cache. Guard this operation so a slower\n * concurrent writer can never clobber a further-along snapshot\n * (`where up_to_index < excluded.up_to_index`).\n */\n putSnapshot(\n sessionId: string,\n reducerName: string,\n index: number,\n state: unknown,\n ): Promise<void>\n\n /**\n * Optional ephemeral-plane capability (specs/a2-implementation.md\n * §15.1) — optional like snapshots are. Values arrive already\n * validated by core; adapters store them opaquely. Presence never\n * touches the event log: no index, no history row, no recovery arm.\n */\n presence?: {\n /**\n * Field-wise last-writer-wins merge of one participant's values:\n * a field whose existing row has a strictly newer `at` (the\n * sender's stamp) is left untouched; `null` deletes the row. Every\n * applied write refreshes that field's expiry to the storage's own\n * clock plus `ttlMs` — the sender stamp orders writes but never\n * anchors their lifetime.\n */\n set(\n ns: string,\n participant: string,\n values: Record<string, unknown | null>,\n meta: { seen: number; at: Date; ttlMs: number },\n ): Promise<void>\n\n /** The current map, pruned of rows at or past their `expiresAt`. */\n read(ns: string): Promise<PresenceRow[]>\n\n /**\n * Push-tier patch delivery; present only on backends with a real\n * broadcast primitive. Without it the backend is the degraded\n * tier: live feeds surface presence by re-reading on their\n * existing poll cadence.\n */\n subscribe?(ns: string, onPatch: (patch: PresencePatch) => void): () => void\n }\n\n /**\n * A live feed of one session's events, starting after `startAfter`\n * (exclusive). Transport is the backend's choice — in-process pub/sub,\n * polling, LISTEN/NOTIFY — callers never branch on which. The iterable\n * ends when the consumer calls `return()` (e.g. a disconnecting SSE\n * client) and must deliver events appended after subscription.\n */\n stream(\n sessionId: string,\n opts?: { startAfter?: number },\n ): AsyncIterable<Event>\n}\n"],"mappings":";AAyJA,MAAa,eAAsB,EACjC,2BAAW,IAAI,KAAK,EACtB;AAEA,MAAa,mBAA6B,OAAO,WAAW"}
1
+ {"version":3,"file":"store-N8PXxDAS.js","names":[],"sources":["../src/store.ts"],"sourcesContent":["/**\n * The A2Store interface — the storage contract every store backend\n * implements. See specs/a2-implementation.md §2–3.\n *\n * This is the whole storage contract: append, read, dispatch claims,\n * failure markers, snapshots, and the live stream. The scheduler\n * needs nothing extra — the armed queue message is its own state, and\n * the store is the only thing it consults.\n */\n\nimport type { PresencePatch } from './contract.ts'\n\n/** A stored event, as the public API exposes it. */\nexport type Event = {\n id: string\n type: string\n payload: unknown\n /** Position in the session's event log, from 1. */\n index: number\n sessionId: string\n createdAt: Date\n}\n\n/** The handler dispatch whose append first persisted a child event. */\nexport type EventCause = {\n index: number\n attempt: number\n /** Size of one named handler append, used to reject truncated retries. */\n batchSize?: number\n}\n\n/**\n * What the store persists: immutable event history, including its causal edge,\n * plus derived dispatch and failure bookkeeping. The bookkeeping is disposable;\n * the event and its cause are not.\n */\nexport type StoredEvent = Event & {\n /** Same-session handler dispatch that appended this event; null means root. */\n cause: EventCause | null\n /** Session-scoped serial execution key resolved when the event is appended. */\n lane: string | null\n /** Adapter clock time recorded by append settlement, completion, or manual skip; null while pending. */\n processedAt: Date | null\n /** Dispatch attempt that completed this event; null without dispatch or while pending. */\n processedByAttempt: number | null\n /** Exact ordered child ids atomically returned by the completing attempt. */\n returnedEventIds: string[] | null\n /** Adapter clock time recorded by the first durable dispatch claim. */\n firstClaimedAt: Date | null\n /** Adapter clock time recorded by the most recent durable dispatch claim. */\n lastClaimedAt: Date | null\n /** Durable dispatch claims, including claims abandoned by hard kills. */\n attemptCount: number\n /** Current dispatch holder; null when the event is not claimed. */\n claimHolder: string | null\n /** Adapter clock expiry for the current dispatch claim. */\n claimExpiresAt: Date | null\n /** Caught handler failures. This alone drives dead-lettering. */\n failureCount: number\n /** Adapter clock time recorded by the most recent caught handler failure. */\n lastFailedAt: Date | null\n /** Dispatch attempt that produced the most recent caught handler failure. */\n lastFailedAttempt: number | null\n /** The last handler failure, stringified. */\n lastError: string | null\n /** Adapter clock time recorded when dead-lettered; null otherwise. */\n failedAt: Date | null\n}\n\n/**\n * One live presence value, as `A2Store.presence.read` returns it. The\n * row is the LWW unit — one participant's one field. `at` is the\n * sender's stamp, the LWW comparator. `expiresAt` is the storage's\n * own clock at the applied set plus its `ttlMs` — never derived from\n * the sender stamp; a row is live strictly before it.\n */\nexport type PresenceRow = {\n participant: string\n field: string\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\n/** One consistent cache-plus-tail read for a reducer fold. */\nexport type StoreStateRead = {\n /** The current head checkpoint, even when an older historical snapshot is selected. */\n headIndex: number | null\n /** The greatest cached fold at or before the requested snapshot frontier. */\n snapshot: { index: number; state: unknown } | null\n /** Immutable events strictly after `snapshot.index`, or the full log on a miss. */\n events: Event[]\n}\n\nexport type StoreSnapshotWrite = {\n index: number\n state: unknown\n /** Unfinished trigger events that durably retain this exact checkpoint. */\n pinEventIndexes?: readonly number[]\n}\n\nexport type StoreStateReadRequest = {\n sessionId: string\n throughIndex?: number\n snapshotThroughIndex?: number\n}\n/** The result of atomically claiming every currently eligible event. */\nexport type StoreClaimAvailableResult =\n | { outcome: 'claimed'; events: StoredEvent[] }\n | { outcome: 'busy'; retryAt: Date }\n | { outcome: 'settled' }\n\n/** A completion may lose to a newer claim or an earlier completion. */\nexport type CompleteAttemptResult =\n { outcome: 'completed'; events: StoredEvent[] } | { outcome: 'superseded' }\n\n/** The result of one claim-renewal heartbeat, both lists in append order. */\nexport type RenewClaimsResult = {\n /** Listed claims that remain owned by the holder. */\n renewed: number[]\n /** Listed claims whose event a newer attempt has durably taken. */\n superseded: number[]\n}\n\n/** The result of atomically recording a caught handler failure. */\nexport type FailAttemptResult = {\n outcome: 'failed' | 'dead_lettered' | 'superseded'\n failureCount: number\n}\n\n/** Input to `A2Store.append` — already validated by the machine. */\nexport type AppendEvent = {\n type: string\n payload: unknown\n /** Caller-supplied idempotency key; generated when absent. */\n id?: string\n /** Internal causal edge supplied atomically by handler `session.append`. */\n cause?: EventCause\n /** Session-scoped serial execution key resolved before persistence. */\n lane?: string\n /** Internal hint: settle this event in the append transaction; no handler is registered. */\n settled?: true\n}\n\n/** A handler-returned event with the deterministic id retries require. */\nexport type ReturnedEvent = AppendEvent & { id: string }\n\n/** The rows written by an append and the session's pending state. */\nexport type StoreAppendResult = {\n events: StoredEvent[]\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\n/**\n * An injectable clock. Adapters take one so tests can drive claim\n * expiry, failure timestamps, and (later) stuck-session detection\n * deterministically — against real storage, no mocking.\n */\nexport type Clock = {\n now(): Date\n}\n\n/** An injectable id source for generated event ids. */\nexport type IdSource = () => string\n\nexport const SYSTEM_CLOCK: Clock = {\n now: () => new Date(),\n}\n\nexport const RANDOM_IDS: IdSource = () => crypto.randomUUID()\n\nexport interface A2Store {\n /**\n * Accepts a batch; the batch is atomic — one transaction, consecutive\n * `index`es, all-or-nothing. The idempotency key covers the whole\n * operation, not each item: if *every* event's `id` already exists in\n * this session, this is a retry of a committed batch whose ack was\n * lost — return the existing rows as success. If only *some* ids\n * exist, the caller mixed an already-sent batch with fresh events —\n * always a caller bug — so throw `A2Error('PARTIAL_DUPLICATE_BATCH')`.\n * Events carrying `settled: true` get `processedAt` in this same atomic\n * operation, with no dispatch claim or `processedByAttempt`. The result's\n * `hasPending` reflects the whole session in the same atomic operation,\n * including older events and idempotent retries.\n *\n * An event carrying `cause` is a handler append, fenced by attempt\n * currency: accept it only while `cause.attempt` is still the parent\n * event's latest attempt and the parent is not dead-lettered; otherwise\n * throw `A2Error('SUPERSEDED_ATTEMPT')` and write nothing. The check is\n * part of this atomic operation and must serialize against a concurrent\n * `claimAvailable` — an unlocked read of the parent admits write skew.\n * The idempotent-replay path runs first, so a batch whose ids all exist\n * replays regardless of the current attempt.\n */\n append(sessionId: string, events: AppendEvent[]): Promise<StoreAppendResult>\n\n /** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */\n read(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<StoredEvent[]>\n\n /**\n * Atomically claims every eligible pending event. Unlaned events are all\n * independently eligible. Within a lane, only the lowest-index unfinished\n * event is eligible. A live claim produces `busy` only when it is the sole\n * remaining obstacle to actionable work. Claimed events are returned in event-log\n * order. Excluded rows remain lane barriers.\n */\n claimAvailable(options: {\n sessionId: string\n holder: string\n ttlMs: number\n expiresAtMs?: number\n excludeIndexes?: readonly number[]\n }): Promise<StoreClaimAvailableResult>\n\n /**\n * Renews the listed live claims still owned by `holder`. Each listed claim\n * carries the attempt ordinal the holder owns. `renewed` lists the claims\n * that remain owned after the operation; `superseded` lists the claims\n * whose event's `attemptCount` has durably passed the listed attempt. An\n * expired claim no successor has taken appears in neither list — its\n * attempt may still complete (`completeAttempt` is the fence), so it is\n * not reported as lost. Renewal never revives an expired claim.\n */\n renewClaims(options: {\n sessionId: string\n holder: string\n claims: readonly { index: number; attempt: number }[]\n ttlMs: number\n expiresAtMs?: number\n }): Promise<RenewClaimsResult>\n\n /**\n * Atomically completes one current attempt and appends its returned events.\n * Retrying a committed completion with the same attempt and deterministic\n * child ids returns the existing children. A stale attempt never appends.\n */\n completeAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n events: ReturnedEvent[]\n }): Promise<CompleteAttemptResult>\n\n /**\n * Atomically records a caught failure for one claimed attempt. A stale\n * attempt cannot poison a processed event or a newer dispatch. Accepted\n * failures record the operation's clock time.\n */\n failAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n error: string\n maxFailures: number\n }): Promise<FailAttemptResult>\n\n /**\n * Reads a reducer snapshot and its event tail as one consistent adapter\n * operation. On a cache miss, `snapshot` is null and `events` is the full\n * log. The snapshot is untrusted; core may reject it and issue a full\n * `read()` when its state schema no longer accepts the cached value.\n */\n readState(\n sessionId: string,\n reducerName: string,\n options?: { throughIndex?: number; snapshotThroughIndex?: number },\n ): Promise<StoreStateRead>\n\n /**\n * Optional batched `readState` — one consistent snapshot-plus-tail read\n * per session id, aligned positionally with the input (duplicates\n * allowed). Each element has its own frontier; the batch makes no\n * cross-session consistency claim. Core falls back to parallel\n * `readState` calls when absent.\n */\n readStates?(\n requests: readonly StoreStateReadRequest[],\n reducerName: string,\n ): Promise<StoreStateRead[]>\n\n /**\n * Atomically writes disposable reducer checkpoints. The greatest index\n * advances the head cache. Older checkpoints survive only when at least one\n * listed trigger event is still unfinished; completion and dead-lettering\n * release that event's pins and collect unreferenced historical checkpoints.\n */\n putSnapshots(\n sessionId: string,\n reducerName: string,\n snapshots: readonly StoreSnapshotWrite[],\n ): Promise<void>\n\n /**\n * Optional ephemeral-plane capability (specs/a2-implementation.md\n * §15.1) — optional like snapshots are. Values arrive already\n * validated by core; adapters store them opaquely. Presence never\n * touches the event log: no index, no history row, no recovery arm.\n */\n presence?: {\n /**\n * Field-wise last-writer-wins merge of one participant's values:\n * a field whose existing row has a strictly newer `at` (the\n * sender's stamp) is left untouched; `null` deletes the row. Every\n * applied write refreshes that field's expiry to the storage's own\n * clock plus `ttlMs` — the sender stamp orders writes but never\n * anchors their lifetime.\n */\n set(\n ns: string,\n participant: string,\n values: Record<string, unknown | null>,\n meta: { seen: number; at: Date; ttlMs: number },\n ): Promise<void>\n\n /** The current map, pruned of rows at or past their `expiresAt`. */\n read(ns: string): Promise<PresenceRow[]>\n\n /**\n * Push-tier patch delivery; present only on backends with a real\n * broadcast primitive. Without it the backend is the degraded\n * tier: live feeds surface presence by re-reading on their\n * existing poll cadence.\n */\n subscribe?(ns: string, onPatch: (patch: PresencePatch) => void): () => void\n }\n\n /**\n * A live feed of one session's events, starting after `startAfter`\n * (exclusive). Transport is the backend's choice — in-process pub/sub,\n * polling, LISTEN/NOTIFY — callers never branch on which. The iterable\n * ends when the consumer calls `return()` (e.g. a disconnecting SSE\n * client) and must deliver events appended after subscription.\n */\n stream(\n sessionId: string,\n opts?: { startAfter?: number },\n ): AsyncIterable<Event>\n}\n"],"mappings":";AAuKA,MAAa,eAAsB,EACjC,2BAAW,IAAI,KAAK,EACtB;AAEA,MAAa,mBAA6B,OAAO,WAAW"}