@fitzzero/quickdraw-core 5.0.0 → 5.1.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 (68) hide show
  1. package/README.md +343 -49
  2. package/dist/{admin-BiU4LRZS.d.ts → admin-DKwkIh5i.d.ts} +25 -10
  3. package/dist/{adminSchemas-k5a1Ov7b.d.ts → adminSchemas-2DUA_hZ8.d.ts} +15 -9
  4. package/dist/{auth-CMyRkfjZ.d.ts → auth-BhWqdyb-.d.ts} +2 -2
  5. package/dist/{caller-DHzK3oiI.d.ts → caller-CXTFswBO.d.ts} +28 -6
  6. package/dist/{chunk-2XJFNVHW.js → chunk-2PWMUVC7.js} +1 -1
  7. package/dist/{chunk-2XJFNVHW.js.map → chunk-2PWMUVC7.js.map} +1 -1
  8. package/dist/{chunk-5IC5VZ7T.js → chunk-2UELNHDD.js} +3 -3
  9. package/dist/{chunk-XFDOGTMC.js → chunk-3674EIRT.js} +4 -4
  10. package/dist/{chunk-DNCAI3KY.js → chunk-4DIQHASK.js} +1 -1
  11. package/dist/chunk-4DIQHASK.js.map +1 -0
  12. package/dist/{chunk-LLLYILEP.js → chunk-A6DJBGOG.js} +411 -43
  13. package/dist/chunk-A6DJBGOG.js.map +1 -0
  14. package/dist/{chunk-B2UQ27GH.js → chunk-CDKG4TFA.js} +25 -5
  15. package/dist/{chunk-B2UQ27GH.js.map → chunk-CDKG4TFA.js.map} +1 -1
  16. package/dist/{chunk-IRGAGRVG.js → chunk-JZBCLNDU.js} +4 -4
  17. package/dist/{chunk-XUSN5WKU.js → chunk-KNDDCVQJ.js} +4 -4
  18. package/dist/{chunk-5YRQ26LF.js → chunk-RT6OILOI.js} +1 -1
  19. package/dist/chunk-RT6OILOI.js.map +1 -0
  20. package/dist/{chunk-7QIY2DDX.js → chunk-VJTFXHOK.js} +2 -2
  21. package/dist/{chunk-7QIY2DDX.js.map → chunk-VJTFXHOK.js.map} +1 -1
  22. package/dist/chunk-XNLWBZIG.js +9 -0
  23. package/dist/chunk-XNLWBZIG.js.map +1 -0
  24. package/dist/cli/quickdraw-docs.js +241 -27
  25. package/dist/cli/quickdraw-docs.js.map +1 -1
  26. package/dist/client/index.d.ts +7 -7
  27. package/dist/client/index.js +5 -5
  28. package/dist/{clientTypes-B3o_99Xq.d.ts → clientTypes-Bc-G8n-U.d.ts} +3 -3
  29. package/dist/{connection-DuN8GvcD.d.ts → connection-Cr1BU07W.d.ts} +2 -2
  30. package/dist/{createServer-DUacdfKl.d.ts → createServer-CP9eDHZZ.d.ts} +30 -9
  31. package/dist/{createTestApp-DFLXoTKm.d.ts → createTestApp-UKVGEmOf.d.ts} +6 -6
  32. package/dist/{envelope-nf5eGB-a.d.ts → envelope-Cp3YcVxC.d.ts} +1 -1
  33. package/dist/{http--uoooIH5.d.ts → http-Djj2Inuu.d.ts} +6 -6
  34. package/dist/index.d.ts +6 -6
  35. package/dist/index.js +27 -7
  36. package/dist/index.js.map +1 -1
  37. package/dist/{infer-Dw21kmLw.d.ts → infer-Teo1xpsd.d.ts} +17 -0
  38. package/dist/{metrics-C0WvB7-I.d.ts → metrics-BdBu5o8G.d.ts} +2 -2
  39. package/dist/prisma/index.d.ts +4 -4
  40. package/dist/prisma/index.js +1 -1
  41. package/dist/server/auth/index.d.ts +14 -5
  42. package/dist/server/auth/index.js +0 -5
  43. package/dist/server/auth/index.js.map +1 -1
  44. package/dist/server/index.d.ts +120 -33
  45. package/dist/server/index.js +146 -193
  46. package/dist/server/index.js.map +1 -1
  47. package/dist/server/mcp/index.d.ts +51 -11
  48. package/dist/server/mcp/index.js +129 -8
  49. package/dist/server/mcp/index.js.map +1 -1
  50. package/dist/server/otel.d.ts +3 -3
  51. package/dist/{sharing-n4ss-ONM.d.ts → sharing-DVa8W-yR.d.ts} +3 -3
  52. package/dist/testing/client.d.ts +13 -13
  53. package/dist/testing/client.js +6 -6
  54. package/dist/testing/index.d.ts +156 -12
  55. package/dist/testing/index.js +1037 -22
  56. package/dist/testing/index.js.map +1 -1
  57. package/dist/testing/mock.d.ts +5 -5
  58. package/dist/testing/mock.js +5 -5
  59. package/dist/{types-Bwg3kIEc.d.ts → types-Cu0vmx7c.d.ts} +8 -2
  60. package/dist/utils/index.d.ts +1 -1
  61. package/package.json +1 -1
  62. package/dist/chunk-5YRQ26LF.js.map +0 -1
  63. package/dist/chunk-DNCAI3KY.js.map +0 -1
  64. package/dist/chunk-LLLYILEP.js.map +0 -1
  65. /package/dist/{chunk-5IC5VZ7T.js.map → chunk-2UELNHDD.js.map} +0 -0
  66. /package/dist/{chunk-XFDOGTMC.js.map → chunk-3674EIRT.js.map} +0 -0
  67. /package/dist/{chunk-IRGAGRVG.js.map → chunk-JZBCLNDU.js.map} +0 -0
  68. /package/dist/{chunk-XUSN5WKU.js.map → chunk-KNDDCVQJ.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/access/forms.ts","../src/server/access/levels.ts","../src/server/collections/buffer.ts","../src/server/emit/tiers.ts","../src/server/emit/projection.ts","../src/server/collections/items.ts","../src/server/collections/cursor.ts","../src/server/collections/index.ts","../src/server/access/cache.ts","../src/server/access/policy.ts","../src/server/access/tools.ts","../src/server/emit/pending.ts","../src/server/emit/subscriptions.ts","../src/server/realtime/validate.ts","../src/server/realtime/channels.ts","../src/server/cluster/acks.ts","../src/server/cluster/lastSeen.ts","../src/server/realtime/presence.ts","../src/server/realtime/seeds.ts","../src/server/pipeline/concurrency.ts","../src/server/emit/lane.ts","../src/server/emit/answer.ts","../src/server/realtime/streamIndex.ts","../src/server/realtime/streamTargets.ts","../src/server/realtime/streamSubscriptions.ts","../src/server/access/basicEngine.ts","../src/server/collections/scopes.ts","../src/server/collections/bind.ts","../src/server/emit/affects.ts","../src/server/emit/frames.ts","../src/server/collections/deltas.ts","../src/server/collections/moves.ts","../src/server/collections/unnamed.ts","../src/server/collections/send.ts","../src/server/collections/collectionSink.ts","../src/server/cluster/counter.ts","../src/server/cluster/revisions.ts","../src/server/emit/changeLog.ts","../src/server/emit/hub.ts","../src/server/collections/requests.ts","../src/server/emit/resolve.ts","../src/server/emit/versions.ts","../src/server/emit/subscribe.ts","../src/server/collections/access.ts","../src/server/collections/snapshot.ts","../src/server/collections/subscribe.ts","../src/server/collections/extension.ts","../src/server/collections/revocation.ts","../src/server/collections/live.ts","../src/server/realtime/events.ts","../src/server/realtime/roomFrames.ts","../src/server/realtime/roomNames.ts","../src/server/realtime/leaving.ts","../src/server/realtime/rooms.ts","../src/server/realtime/streamRevocation.ts","../src/server/realtime/streamFeeds.ts","../src/server/realtime/streams.ts","../src/server/realtime/realtime.ts","../src/server/collections/changed.ts","../src/server/topicIndex.ts","../src/server/topicRevocation.ts","../src/server/topics.ts","../src/server/emit/entitySink.ts","../src/server/emit/extension.ts","../src/server/emit/revocation.ts","../src/server/emit/live.ts","../src/server/service.ts","../src/server/emit/tieredOutputs.ts","../src/server/access/api.ts","../src/server/access/bindings.ts","../src/server/access/changes.ts","../src/server/access/rowAccess.ts","../src/server/access/engine.ts","../src/server/pipeline/accessSettings.ts","../src/server/uow/untracked.ts","../src/server/pipeline/tracking.ts","../src/server/pipeline/settings.ts","../src/server/pipeline/run.ts","../src/server/pipeline/share.ts","../src/server/pipeline/replies.ts","../src/server/pipeline/execute.ts","../src/server/pipeline/notModified.ts","../src/server/pipeline/stages.ts","../src/server/pipeline/pipeline.ts","../src/server/registry.ts","../src/server/dispatcher.ts","../src/server/observability/stallWatchdog.ts","../src/server/transports/http.ts","../src/server/rateLimit.ts","../src/server/createServer.ts","../src/server/lifecycle.ts","../src/server/transports/socketServer.ts","../src/server/transports/legacy.ts","../src/server/transports/middleware.ts","../src/server/cluster/adapterClients.ts","../src/server/cluster/broadcasts.ts","../src/server/transports/pushes.ts","../src/server/transports/socketio.ts"],"sourcesContent":["// Run-time side of the access forms: the `custom(fn)` builder, the shape\n// check `defineService` runs on every method's form, and the row ids an\n// `entry` or `scope` form refers to.\n\nimport { isAccessLevel } from \"../../contract/access\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { AccessForm, CustomAccess, EntryAccess, ScopeAccess } from \"./types\";\n\n/**\n * A custom access check: the call passes when `check(ctx, input)` resolves\n * `true`. The caller must be authenticated first, so `ctx.principal` is\n * never `null` in `check`. A service-wide `Admin` grant passes without\n * running it (unless the service sets `adminBypass: false`). A method with\n * custom access cannot `share: \"all\"`, because its result may depend on who\n * asks.\n *\n * @example\n * access: custom((ctx, input) => ctx.principal.userId === input.ownerId),\n */\nexport function custom<Input, Ctx>(\n check: (ctx: Ctx, input: Input) => boolean | PromiseLike<boolean>,\n): CustomAccess<Input, Ctx> {\n if (typeof check !== \"function\") {\n throw new TypeError(\"custom(check): check must be a function\");\n }\n return Object.freeze({ kind: \"custom\", check });\n}\n\ntype UnknownForm = Readonly<Record<string, unknown>>;\n\nfunction isRecord(value: unknown): value is UnknownForm {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** True when `form` is a `custom(fn)` form. */\nexport function isCustomAccess(form: AccessForm): form is CustomAccess {\n return typeof form === \"object\" && form.kind === \"custom\";\n}\n\nfunction isIdSelector(value: unknown): boolean {\n return (typeof value === \"string\" && value.length > 0) || typeof value === \"function\";\n}\n\nconst OBJECT_FORM_KEYS = new Set([\"service\", \"entry\", \"scope\", \"of\", \"id\"]);\n\nfunction objectFormProblem(form: UnknownForm): string | undefined {\n const unknownKey = Object.keys(form).find((key) => !OBJECT_FORM_KEYS.has(key));\n if (unknownKey !== undefined) {\n return `has an unknown key \"${unknownKey}\"`;\n }\n const levels = [\"service\", \"entry\", \"scope\"].filter((key) => form[key] !== undefined);\n if (levels.length === 0 || !levels.every((key) => isAccessLevel(form[key]))) {\n return \"needs service, entry or scope set to an access level\";\n }\n if (form.scope !== undefined) {\n const valid = levels.length === 1 && isRecord(form.of) && isIdSelector(form.id);\n return valid ? undefined : \"a scope form is { scope, of: contract, id } and nothing else\";\n }\n if (form.of !== undefined || (form.id !== undefined && !isIdSelector(form.id))) {\n return \"id must be an input key or a function, and of belongs to scope forms\";\n }\n return form.entry === undefined && form.id !== undefined\n ? \"id belongs to entry and scope forms\"\n : undefined;\n}\n\n/**\n * Why `form` is not an access form, or `undefined` when it is one. Run by\n * `defineService` so a JavaScript caller or a cast fails at definition time\n * rather than on the first call.\n */\nexport function accessFormProblem(form: unknown): string | undefined {\n if (form === \"public\" || form === \"authenticated\") {\n return undefined;\n }\n if (!isRecord(form)) {\n return 'must be \"public\", \"authenticated\", { service }, { entry }, { scope, of, id } or custom(fn)';\n }\n if (form.kind === \"custom\") {\n return typeof form.check === \"function\" ? undefined : \"custom access needs a check function\";\n }\n return objectFormProblem(form);\n}\n\nfunction idsFrom(value: unknown): readonly string[] | undefined {\n if (typeof value === \"string\" && value.length > 0) {\n return [value];\n }\n const isIdList =\n Array.isArray(value) &&\n value.length > 0 &&\n value.every((id) => typeof id === \"string\" && id.length > 0);\n return isIdList ? (value as readonly string[]) : undefined;\n}\n\n/**\n * The row ids an `entry` or `scope` form refers to, read from the parsed\n * input: `id` names an input key or is a function of the input, and an\n * `entry` form without `id` reads `input.id`. A missing or empty id is a\n * `FORBIDDEN` call: a failed lookup denies.\n */\nexport function accessIds(form: EntryAccess | ScopeAccess, input: unknown): readonly string[] {\n const { id } = form;\n let value: unknown;\n if (typeof id === \"function\") {\n value = (id as (input: unknown) => unknown)(input);\n } else if (isRecord(input)) {\n value = input[id ?? \"id\"];\n }\n const ids = idsFrom(value);\n if (ids === undefined) {\n throw new QuickdrawError(\"FORBIDDEN\", \"Insufficient permissions\");\n }\n return ids;\n}\n","// Access level ordering, ported from 4.1's `isLevelSufficient`\n// (4.1 `src/server/BaseService.ts:554-562`): Public < Read < Moderate < Admin.\n\nimport { ACCESS_LEVELS, isAccessLevel, type AccessLevel } from \"../../contract/access\";\nimport type { Principal } from \"../types\";\n\nconst RANK: Readonly<Record<AccessLevel, number>> = Object.freeze({\n Public: 0,\n Read: 1,\n Moderate: 2,\n Admin: 3,\n});\n\n/**\n * True when `level` is at least `required`. A missing level (no grant) meets\n * nothing, not even `\"Public\"`: a grant has to exist to count.\n */\nexport function meetsLevel(level: AccessLevel | null | undefined, required: AccessLevel): boolean {\n if (level === null || level === undefined) {\n return false;\n }\n return (RANK[level] ?? -1) >= RANK[required];\n}\n\n/**\n * The higher of two levels; `null` (no level) is below every level. A value\n * that is not an access level counts as `null`, so it never raises a level.\n */\nexport function maxLevel(\n a: AccessLevel | null | undefined,\n b: AccessLevel | null | undefined,\n): AccessLevel | null {\n const left = isAccessLevel(a) ? a : null;\n const right = isAccessLevel(b) ? b : null;\n if (left === null || right === null) {\n return left ?? right;\n }\n return RANK[right] > RANK[left] ? right : left;\n}\n\n/** Every level that meets `required`, lowest first: `levelsAtLeast(\"Moderate\")` is `[\"Moderate\", \"Admin\"]`. */\nexport function levelsAtLeast(required: AccessLevel): readonly AccessLevel[] {\n return ACCESS_LEVELS.filter((level) => RANK[level] >= RANK[required]);\n}\n\n/** The principal's service-wide grant on `service`, from `serviceAccess`. */\nexport function serviceGrant(principal: Principal, service: string): AccessLevel | undefined {\n const grants = principal.serviceAccess;\n if (grants === null || grants === undefined || !Object.hasOwn(grants, service)) {\n return undefined;\n }\n return grants[service];\n}\n","// The recent deltas of each collection scope (RFC 0003 section 7.3): a client\n// that reconnects sends the revision it holds the scope at (`since`), and\n// while this process still holds every change made since then it gets those\n// deltas instead of the scope again. Bounded per scope at 500 deltas or 5\n// minutes, and per process; 4.1 had no resume at all.\n//\n// Each scope has a floor: the oldest revision a client may hold and still be\n// answered from here. Whatever this process cannot replay raises it:\n//\n// - a frame dropped for age or size: the floor rises to its revision;\n// - a flush that changed the scope without building its deltas (nobody here\n// subscribed to it): to that revision;\n// - a `reset`: past its revision, since a client must load the scope again;\n// - a frame recorded after a newer one (flushes can finish out of order):\n// past the newest, since a client holding the newer revision may not have\n// received the older frame;\n// - the process starting, and the state of an idle scope being forgotten,\n// which raises the floor every scope without state starts from. A scope\n// with subscribers here is pinned and never forgotten, so a client that\n// checks an unchanged scope now and then keeps resuming it;\n// - a flush that changed a collection nobody here subscribes to, in scopes\n// it would have had to read to name: past every revision taken so far, for\n// every scope of that collection (`skipAll`).\n//\n// Deltas of one frame share its revision, and frames are kept in the order\n// they went out, so a resume replays them in that order and never sorts.\n\nimport type { CollectionDelta, Revision } from \"../../protocol/envelope\";\nimport { currentRev, nextRev } from \"../rev\";\n\n/** Deltas kept per scope. */\nexport const RESUME_MAX_DELTAS = 500;\n\n/** How long a delta is kept, in milliseconds. */\nexport const RESUME_MAX_AGE_MS = 300_000;\n\n/** Scopes without subscribers whose state is kept; past it the least recently changed is forgotten. */\nexport const RESUME_MAX_SCOPES = 10_000;\n\n/** Options of {@link createDeltaBuffer}; the defaults are the RFC's bounds. */\nexport interface DeltaBufferOptions {\n readonly maxDeltas?: number;\n readonly maxAgeMs?: number;\n readonly maxScopes?: number;\n /** The clock, in milliseconds. Default `Date.now`. */\n readonly now?: () => number;\n}\n\ninterface Frame {\n readonly rev: Revision;\n readonly at: number;\n readonly deltas: readonly CollectionDelta[];\n}\n\ninterface ScopeLog {\n frames: Frame[];\n /** How many deltas `frames` hold. */\n size: number;\n /** The oldest revision a client may hold and resume from. */\n floor: Revision;\n /** The newest revision of a change to the scope this process saw. */\n newest: Revision;\n /** When the scope last changed, or lost its last subscriber. */\n at: number;\n}\n\n/** What a covered resume replays: the deltas since the client's revision, and the revision after them. */\nexport interface Replay {\n readonly rev: Revision;\n readonly deltas: readonly CollectionDelta[];\n}\n\n/**\n * The recent deltas of every scope, keyed by the scope's room name. A scope's\n * collection (its group, `service\\0collection`) may have a floor of its own.\n */\nexport interface DeltaBuffer {\n /** Keeps a frame this process sent to the scope. */\n record(key: string, rev: Revision, deltas: readonly CollectionDelta[]): void;\n /** A flush at `rev` changed the scope, and its deltas were not built: no resume from before it. */\n skip(key: string, rev: Revision): void;\n /** A flush changed scopes of the group it did not name: no resume of any from before now. */\n skipAll(group: string): void;\n /** The scope was reset (or closed) at `rev`: no resume from before it. */\n reset(key: string, rev: Revision): void;\n /**\n * The deltas after `since`, in the order they went out, when every change\n * since then is still held; `undefined` when the client must load the scope.\n */\n since(key: string, since: Revision, group?: string): Replay | undefined;\n /** The oldest revision a client may hold and still resume the scope from. */\n floor(key: string, group?: string): Revision;\n /** The revision of the scope's last change this process saw, or the floor when it knows of none. */\n lastChange(key: string, group?: string): Revision;\n /** The scope has a subscriber here: keep its state. */\n pin(key: string): void;\n /** The scope's last subscriber here left: its state may be forgotten once idle. */\n unpin(key: string): void;\n}\n\ninterface Logs {\n /** Scopes without subscribers here, least recently changed first. */\n readonly idle: Map<string, ScopeLog>;\n readonly pinned: Map<string, ScopeLog>;\n /** The floor of every scope of a group, past a change no scope of it named. */\n readonly groups: Map<string, Revision>;\n /** The floor of a scope without state. */\n base: Revision;\n}\n\nfunction logOf(logs: Logs, key: string): ScopeLog | undefined {\n return logs.pinned.get(key) ?? logs.idle.get(key);\n}\n\n/** Drops the oldest frames while the scope holds too many deltas or old ones. */\nfunction expire(log: ScopeLog, at: number, maxDeltas: number, maxAgeMs: number): void {\n for (let first = log.frames[0]; first !== undefined; first = log.frames[0]) {\n if (log.size <= maxDeltas && first.at >= at - maxAgeMs) {\n return;\n }\n log.frames.shift();\n log.size -= first.deltas.length;\n log.floor = Math.max(log.floor, first.rev);\n }\n}\n\n/** Forgets idle scopes changed too long ago, and the least recently changed past the cap. */\nfunction forget(logs: Logs, at: number, maxScopes: number, maxAgeMs: number): void {\n for (const [key, log] of logs.idle) {\n if (logs.idle.size <= maxScopes && log.at >= at - maxAgeMs) {\n return;\n }\n logs.idle.delete(key);\n logs.base = Math.max(logs.base, log.floor, log.newest);\n }\n}\n\n/** The scope's log, made when missing; an idle one moves to the most recently changed end. */\nfunction changed(logs: Logs, key: string, rev: Revision, at: number): ScopeLog {\n const pinned = logs.pinned.get(key);\n const log = pinned ??\n logs.idle.get(key) ?? { frames: [], size: 0, floor: logs.base, newest: logs.base, at };\n if (pinned === undefined) {\n logs.idle.delete(key);\n logs.idle.set(key, log);\n }\n if (rev < log.newest) {\n log.floor = Math.max(log.floor, log.newest + 1);\n }\n log.newest = Math.max(log.newest, rev);\n log.at = at;\n return log;\n}\n\n/** Creates the delta buffer of one dispatcher. */\nexport function createDeltaBuffer(options: DeltaBufferOptions = {}): DeltaBuffer {\n const maxDeltas = options.maxDeltas ?? RESUME_MAX_DELTAS;\n const maxAgeMs = options.maxAgeMs ?? RESUME_MAX_AGE_MS;\n const maxScopes = options.maxScopes ?? RESUME_MAX_SCOPES;\n const now = options.now ?? Date.now;\n const logs: Logs = { idle: new Map(), pinned: new Map(), groups: new Map(), base: nextRev() };\n const groupFloor = (group: string | undefined): Revision =>\n group === undefined ? 0 : (logs.groups.get(group) ?? 0);\n const floor = (key: string, group?: string): Revision =>\n Math.max(logOf(logs, key)?.floor ?? logs.base, groupFloor(group));\n return Object.freeze({\n record(key: string, rev: Revision, deltas: readonly CollectionDelta[]): void {\n const at = now();\n const log = changed(logs, key, rev, at);\n log.frames.push({ rev, at, deltas: [...deltas] });\n log.size += deltas.length;\n expire(log, at, maxDeltas, maxAgeMs);\n forget(logs, at, maxScopes, maxAgeMs);\n },\n skip(key: string, rev: Revision): void {\n const at = now();\n const log = changed(logs, key, rev, at);\n log.floor = Math.max(log.floor, rev);\n forget(logs, at, maxScopes, maxAgeMs);\n },\n skipAll(group: string): void {\n // Every revision a client may hold was taken by now: none of them is covered.\n logs.groups.set(group, Math.max(groupFloor(group), currentRev() + 1));\n },\n reset(key: string, rev: Revision): void {\n const at = now();\n const log = changed(logs, key, rev, at);\n log.floor = Math.max(log.floor, rev + 1);\n log.frames = [];\n log.size = 0;\n forget(logs, at, maxScopes, maxAgeMs);\n },\n since(key: string, since: Revision, group?: string): Replay | undefined {\n const log = logOf(logs, key);\n if (log !== undefined) {\n expire(log, now(), maxDeltas, maxAgeMs);\n }\n if (since < floor(key, group)) {\n return undefined;\n }\n const frames = (log?.frames ?? []).filter((frame) => frame.rev > since);\n return {\n rev: Math.max(since, log?.newest ?? since),\n deltas: frames.flatMap((frame) => frame.deltas),\n };\n },\n floor,\n lastChange: (key: string, group?: string) =>\n Math.max(logOf(logs, key)?.newest ?? logs.base, groupFloor(group) - 1),\n pin(key: string): void {\n if (logs.pinned.has(key)) {\n return;\n }\n const log = logs.idle.get(key) ?? {\n frames: [],\n size: 0,\n floor: logs.base,\n newest: logs.base,\n at: now(),\n };\n logs.idle.delete(key);\n logs.pinned.set(key, log);\n },\n unpin(key: string): void {\n const log = logs.pinned.get(key);\n if (log === undefined) {\n return;\n }\n const at = now();\n logs.pinned.delete(key);\n log.at = at;\n logs.idle.set(key, log);\n forget(logs, at, maxScopes, maxAgeMs);\n },\n });\n}\n","// Field tiers (RFC 0003 section 6). A contract's `fields` map names the\n// minimum level a reader needs to receive a field (`{ notes: \"Admin\" }`);\n// every other field goes to anyone who may read the row. An entity frame is\n// built once and stripped once per occupied tier: subscribers join the room\n// of their own level, and levels that see the same fields share one stripped\n// frame. A method's result is stripped per caller, after any shared run\n// (section 9, step 6). 4.1 had two fixed tiers, \"elevated\" and everyone else\n// (4.1 `src/server/BaseService.ts:630-692`), and decided which by\n// overridable methods rather than by declared levels.\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport { meetsLevel } from \"../access/levels\";\nimport type { RowLevel } from \"../access/policy\";\n\n/** The lowest level that may subscribe to a row, as in 4.1 (`requiredLevel = \"Read\"`). */\nexport const SUBSCRIBE_LEVEL: AccessLevel = \"Read\";\n\n/** The levels a subscriber can hold, lowest first: one entity room per level. */\nexport const SUBSCRIBER_LEVELS: readonly AccessLevel[] = Object.freeze([\n \"Read\",\n \"Moderate\",\n \"Admin\",\n]);\n\n/** Subscriber levels that receive the same fields, so one stripped frame serves them all. */\nexport interface TierGroup {\n readonly levels: readonly AccessLevel[];\n /** The projection's keys these levels do not receive. */\n readonly hidden: ReadonlySet<string>;\n}\n\n/** The contract's field tiers over one projection's keys. */\nexport interface Tiers {\n /** True when some key of the projection has a minimum level, so a reader's level matters. */\n readonly tiered: boolean;\n /** The keys a reader at `level` does not receive; `null` is no level, which meets no tier. */\n hidden(level: RowLevel): ReadonlySet<string>;\n /**\n * A one-letter name for the keys `hidden(level)` gives: two levels have the\n * same name exactly when they hide the same keys. Readers of a method's\n * result whose names agree on every row get the same stripped copy.\n */\n label(level: RowLevel): string;\n /** The subscriber levels, grouped by the keys they do not receive. */\n readonly groups: readonly TierGroup[];\n}\n\n/** What a reader at one level does not receive, and its name among the projection's hidden sets. */\ninterface Hiding {\n readonly hidden: ReadonlySet<string>;\n readonly label: string;\n}\n\nconst NOTHING: ReadonlySet<string> = Object.freeze(new Set<string>());\n\nfunction hiddenAt(\n fields: Readonly<Record<string, AccessLevel>>,\n keys: readonly string[],\n level: RowLevel,\n): ReadonlySet<string> {\n const hidden = keys.filter((key) => {\n const required = Object.hasOwn(fields, key) ? fields[key] : undefined;\n return required !== undefined && !meetsLevel(level, required);\n });\n return hidden.length === 0 ? NOTHING : Object.freeze(new Set(hidden));\n}\n\n/** The tiers of `fields` over `keys`. */\nexport function tiersOf(\n fields: Readonly<Record<string, AccessLevel>>,\n keys: readonly string[],\n): Tiers {\n const byLevel = new Map<RowLevel, Hiding>();\n // One name per distinct hidden set: `a`, `b`, ... (at most one per level).\n const labels = new Map<string, string>();\n const hiding = (level: RowLevel): Hiding => {\n let found = byLevel.get(level);\n if (found === undefined) {\n const set = hiddenAt(fields, keys, level);\n const signature = [...set].join(\"\\u0000\");\n const label = labels.get(signature) ?? String.fromCodePoint(97 + labels.size);\n labels.set(signature, label);\n found = { hidden: set, label };\n byLevel.set(level, found);\n }\n return found;\n };\n const hidden = (level: RowLevel): ReadonlySet<string> => hiding(level).hidden;\n const groups = new Map<string, { levels: AccessLevel[]; hidden: ReadonlySet<string> }>();\n for (const level of SUBSCRIBER_LEVELS) {\n const set = hidden(level);\n const signature = [...set].join(\"\\u0000\");\n const group = groups.get(signature);\n if (group === undefined) {\n groups.set(signature, { levels: [level], hidden: set });\n } else {\n group.levels.push(level);\n }\n }\n return Object.freeze({\n tiered: keys.some((key) => Object.hasOwn(fields, key)),\n hidden,\n label: (level: RowLevel) => hiding(level).label,\n groups: Object.freeze([...groups.values()].map((group) => Object.freeze(group))),\n });\n}\n\n/** `row` without the `hidden` keys: a copy when there are any, the row itself otherwise. */\nexport function strip<Row extends Readonly<Record<string, unknown>>>(\n row: Row,\n hidden: ReadonlySet<string>,\n): Row {\n if (hidden.size === 0) {\n return row;\n }\n const kept: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n if (!hidden.has(key)) {\n kept[key] = value;\n }\n }\n return kept as Row;\n}\n","// Projections (RFC 0003 sections 2 and 6): the wire shape of a row. A\n// projection's keys decide what a read selects, so a row is never loaded\n// wider than what is sent, and `Date` values go out as ISO strings. This\n// replaces 4.1's `toDto` (4.1 `src/server/BaseService.ts:615-617`), an\n// identity mapping that sent every column a handler happened to read.\n//\n// The keys come from the schema's Standard JSON Schema (Zod 4.2 or later):\n// the `properties` of its output's object schema. A schema that cannot\n// describe itself names its keys in the service's `project` option instead,\n// or the service fails when it is defined (section 2). `project` also gives a\n// projection a `select` of its own and a `map`, for relations and computed\n// fields: reads use that select, and `map` turns the row read into the\n// projection's row. The rowless check reads an input's keys here too, more\n// widely (`inputKeys`).\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { MethodOutput } from \"../../contract/methods\";\nimport { hasJsonSchema, type StandardSchemaV1 } from \"../../contract/standardSchema\";\nimport type { RowLevel, RowLevels } from \"../access/policy\";\nimport type { StorageRow } from \"../storage\";\nimport { strip, tiersOf, type Tiers } from \"./tiers\";\n\ntype Fail = (message: string) => never;\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\n/** A projection as a service compiles it once, from its schema and its `project` option. */\nexport interface Projection {\n /** `\"entity\"`, or the name of one of the contract's projections. */\n readonly name: string;\n /** Its keys, `id` first. */\n readonly keys: readonly string[];\n /** The `select` its rows are read with: the one `project` gives it, or its keys. */\n readonly select: UnknownRecord;\n /** Turns a row read with `select` into the projection's row; absent for a plain projection. */\n readonly map: ((row: StorageRow) => unknown) | undefined;\n /** The contract's field tiers over the projection's keys. */\n readonly tiers: Tiers;\n}\n\n/** How a method's output names a projection: one row, one row or `null`, or a list. */\nexport interface ProjectedOutput {\n readonly projection: Projection;\n readonly kind: \"one\" | \"nullable\" | \"list\";\n}\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** A plain object or an array: what a projected value is made of. */\nfunction isPlain(value: unknown): value is object {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n return Array.isArray(value) || prototype === Object.prototype || prototype === null;\n}\n\n/**\n * The node a JSON Schema node stands for: the one its `$ref` names in the\n * document `root` (`#`, `#/definitions/<name>` or `#/$defs/<name>`), or\n * itself without one; `undefined` for a reference it cannot follow.\n */\nfunction referenced(node: UnknownRecord, root: UnknownRecord): UnknownRecord | undefined {\n const ref = node.$ref;\n if (typeof ref !== \"string\") {\n return node;\n }\n if (ref === \"#\") {\n return root;\n }\n const match = /^#\\/(definitions|\\$defs)\\/(.+)$/.exec(ref);\n const defs = match === null ? undefined : root[match[1] ?? \"\"];\n const target = isRecord(defs) ? defs[match?.[2] ?? \"\"] : undefined;\n return isRecord(target) ? target : undefined;\n}\n\n/**\n * The keys a schema's output has, read from its Standard JSON Schema, or\n * `undefined` when it cannot say: no JSON Schema (a Zod 3 schema), a value\n * JSON Schema cannot write (a `Date`, a transform), or a value that is not\n * one object (a union).\n */\nexport function schemaKeys(schema: StandardSchemaV1): readonly string[] | undefined {\n if (!hasJsonSchema(schema)) {\n return undefined;\n }\n let json: unknown;\n try {\n json = schema[\"~standard\"].jsonSchema.output({ target: \"draft-07\" });\n } catch {\n return undefined;\n }\n const described = isRecord(json) ? referenced(json, json) : undefined;\n const properties = described?.properties;\n return isRecord(properties) ? Object.keys(properties) : undefined;\n}\n\n/** The keywords whose members are the alternatives (`anyOf`, `oneOf`) or the parts (`allOf`) of a value. */\nconst BRANCHES = [\"anyOf\", \"oneOf\", \"allOf\"] as const;\n\n/** Writes values JSON Schema has no form for as `{}` (any value), keeping the keys beside them (Zod 4). */\nconst UNREPRESENTABLE_AS_ANY = Object.freeze({ unrepresentable: \"any\" });\n\n/** Adds to `keys` the top-level keys of every object `node` may be: its own and its branches'. */\nfunction addBranchKeys(\n node: unknown,\n root: UnknownRecord,\n keys: Set<string>,\n seen: Set<UnknownRecord>,\n): void {\n const target = isRecord(node) ? referenced(node, root) : undefined;\n if (target === undefined || seen.has(target)) {\n return;\n }\n seen.add(target);\n if (isRecord(target.properties)) {\n for (const key of Object.keys(target.properties)) {\n keys.add(key);\n }\n }\n for (const keyword of BRANCHES) {\n const members = target[keyword];\n if (Array.isArray(members)) {\n for (const member of members) {\n addBranchKeys(member, root, keys, seen);\n }\n }\n }\n}\n\n/**\n * The keys an input may have at its top level, read from its Standard JSON\n * Schema more widely than {@link schemaKeys}, for the rowless check\n * (`../access/rowless.ts`): a key that any branch of a union or an\n * intersection has counts (`anyOf`, `oneOf`, `allOf`, through `$ref`s and\n * past a `null` branch), since that branch may carry it, and a value JSON\n * Schema cannot write (a `Date`, a `Set`, a `bigint`, a custom type) is\n * written as any value rather than hiding the keys beside it. Empty for an\n * input that is no object (a bare string, an array, a record); `undefined`\n * when the schema has no JSON Schema (a Zod 3 schema) or cannot write one.\n */\nexport function inputKeys(schema: StandardSchemaV1): readonly string[] | undefined {\n if (!hasJsonSchema(schema)) {\n return undefined;\n }\n let json: unknown;\n try {\n json = schema[\"~standard\"].jsonSchema.input({\n target: \"draft-07\",\n libraryOptions: UNREPRESENTABLE_AS_ANY,\n });\n } catch {\n return undefined;\n }\n if (!isRecord(json)) {\n return undefined;\n }\n const keys = new Set<string>();\n addBranchKeys(json, json, keys, new Set());\n return [...keys];\n}\n\nconst OPTION_KEYS = new Set([\"keys\", \"select\", \"map\"]);\n\nfunction checkKeyList(owner: string, keys: unknown, fail: Fail): readonly string[] {\n const valid =\n Array.isArray(keys) &&\n keys.every((key) => typeof key === \"string\" && key.length > 0) &&\n new Set(keys).size === keys.length;\n if (!valid) {\n fail(`${owner}: keys must be a list of distinct field names`);\n }\n if (!keys.includes(\"id\")) {\n fail(`${owner}: keys must include \"id\"; every row is keyed by it`);\n }\n return keys as readonly string[];\n}\n\n/** One projection's `project` entry, checked: unknown options, keys, select and map. */\nfunction checkOption(owner: string, option: unknown, fail: Fail): UnknownRecord {\n if (option === undefined) {\n return {};\n }\n if (!isRecord(option)) {\n fail(`${owner} must be { keys?, select?, map? }`);\n }\n const unknownKey = Object.keys(option).find((key) => !OPTION_KEYS.has(key));\n if (unknownKey !== undefined) {\n fail(`${owner} has an unknown option \"${unknownKey}\"; the options are keys, select and map`);\n }\n if (option.select !== undefined && !isRecord(option.select)) {\n fail(`${owner}: select must be a select object, as in { id: true, labels: { select: ... } }`);\n }\n if (option.map !== undefined && typeof option.map !== \"function\") {\n fail(`${owner}: map must be a function of the row its select reads`);\n }\n return option;\n}\n\nfunction keysFor(\n name: string,\n schema: StandardSchemaV1,\n option: UnknownRecord,\n fail: Fail,\n): readonly string[] {\n const owner = `projection \"${name}\"`;\n if (option.keys !== undefined) {\n return checkKeyList(owner, option.keys, fail);\n }\n const keys = schemaKeys(schema);\n if (keys === undefined) {\n fail(\n `${owner}: its schema cannot list its keys (it has no Standard JSON Schema the framework can read); use Zod 4.2 or later for it, or declare them with project: { ${name}: { keys: [...] } }`,\n );\n }\n return keys;\n}\n\nfunction compileOne(\n name: string,\n schema: StandardSchemaV1,\n option: unknown,\n fields: Readonly<Record<string, AccessLevel>>,\n fail: Fail,\n): Projection {\n const checked = checkOption(`projection \"${name}\"`, option, fail);\n const keys = keysFor(name, schema, checked, fail);\n const ordered = [\"id\", ...keys.filter((key) => key !== \"id\")];\n const select = isRecord(checked.select)\n ? { id: true, ...checked.select }\n : Object.fromEntries(ordered.map((key) => [key, true]));\n return Object.freeze({\n name,\n keys: Object.freeze(ordered),\n select: Object.freeze(select),\n map: checked.map as Projection[\"map\"],\n tiers: tiersOf(fields, ordered),\n });\n}\n\n/**\n * Compiles every projection of `contract` (the entity and its named\n * projections) with the service's `project` option. Fails, through `fail`,\n * for a projection whose keys cannot be found, a `project` entry naming no\n * projection, and a malformed entry.\n */\nexport function compileProjections(\n contract: AnyContract,\n option: unknown,\n fail: Fail,\n): ReadonlyMap<string, Projection> {\n if (option !== undefined && !isRecord(option)) {\n fail(\"project must map projection names to { keys?, select?, map? }\");\n }\n const options = option ?? {};\n const schemas = new Map<string, StandardSchemaV1>(Object.entries(contract.projections));\n if (contract.entity !== undefined) {\n schemas.set(\"entity\", contract.entity);\n }\n const unknownName = Object.keys(options).find((name) => !schemas.has(name));\n if (unknownName !== undefined) {\n fail(\n `project names \"${unknownName}\", which is not a projection of the contract; the projections are ${[...schemas.keys()].map((name) => `\"${name}\"`).join(\", \") || \"none\"}`,\n );\n }\n const compiled = new Map<string, Projection>();\n for (const [name, schema] of schemas) {\n compiled.set(name, compileOne(name, schema, options[name], contract.fields, fail));\n }\n return compiled;\n}\n\n/** The projection a method output names, or `undefined` when the output is a schema. */\nexport function projectedOutput(\n output: MethodOutput,\n projections: ReadonlyMap<string, Projection>,\n): ProjectedOutput | undefined {\n if (typeof output === \"string\") {\n const projection = projections.get(output);\n return projection === undefined ? undefined : { projection, kind: \"one\" };\n }\n if (!(\"kind\" in output)) {\n return undefined;\n }\n const projection = projections.get(output.projection);\n const kind = output.kind === \"nullable\" ? \"nullable\" : \"list\";\n return projection === undefined ? undefined : { projection, kind };\n}\n\n/**\n * `value` with every `Date` in it, at any depth of plain objects and arrays,\n * replaced by its ISO string. Anything else is kept as it is.\n */\nexport function isoDates(value: unknown): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (!isPlain(value)) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(isoDates);\n }\n const copy: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n copy[key] = isoDates(item);\n }\n return copy;\n}\n\n/** The members of `row` named by `keys` that it has, with their dates as ISO strings. */\nexport function pickKeys(row: UnknownRecord, keys: Iterable<string>): Record<string, unknown> {\n const picked: Record<string, unknown> = {};\n for (const key of keys) {\n if (Object.hasOwn(row, key)) {\n picked[key] = isoDates(row[key]);\n }\n }\n return picked;\n}\n\n/**\n * One row in the projection's shape: `map` applied (when the projection has\n * one), then its keys picked, dates as ISO strings. A value that is not an\n * object is returned as it is, for output validation to report.\n */\nexport function projectRow(projection: Projection, row: unknown): unknown {\n if (!isRecord(row)) {\n return row;\n }\n const source = projection.map === undefined ? row : projection.map(row);\n return isRecord(source) ? pickKeys(source, projection.keys) : source;\n}\n\n/** A method's result in its projection's shape: one row, `null`, or a list of rows. */\nexport function projectOutput(output: ProjectedOutput, value: unknown): unknown {\n if (output.kind === \"list\") {\n return Array.isArray(value)\n ? value.map((row: unknown) => projectRow(output.projection, row))\n : value;\n }\n if (value === null && output.kind === \"nullable\") {\n return null;\n }\n return projectRow(output.projection, value);\n}\n\n/** The ids of the rows in a projected value: one row, `null`, or a list. */\nexport function rowIds(value: unknown): string[] {\n const rows: readonly unknown[] = Array.isArray(value) ? value : [value];\n const ids: string[] = [];\n for (const row of rows) {\n if (isRecord(row) && typeof row.id === \"string\" && row.id.length > 0) {\n ids.push(row.id);\n }\n }\n return ids;\n}\n\n/** What one reader may see of a method's result, from {@link readerView}. */\nexport interface ReaderView {\n /**\n * Equal for two readers of one result exactly when every row hides the\n * same fields from both, so they may share one stripped copy.\n */\n readonly key: string;\n /** The result without the fields this reader does not receive: a copy of each row that hides any. */\n strip(): unknown;\n}\n\n/** The view of a reader who sees the whole value: a schema output, or a projection without tiers. */\nexport function wholeView(value: unknown): ReaderView {\n return { key: \"\", strip: () => value };\n}\n\n/**\n * A projected method result as one reader may see it: each row without the\n * fields its reader's level on that row does not reach (RFC 0003 section 6).\n * `levelsOf` answers the reader's level per row id; it is asked only when the\n * projection has tiered keys. Rows are copied, never changed in place, so a\n * shared run's result stays whole for the other callers.\n */\nexport async function readerView(\n output: ProjectedOutput,\n value: unknown,\n levelsOf: (ids: readonly string[]) => Promise<RowLevels>,\n): Promise<ReaderView> {\n const { tiers } = output.projection;\n if (!tiers.tiered || value === null || value === undefined) {\n return wholeView(value);\n }\n const ids = [...new Set(rowIds(value))];\n const levels: RowLevels = ids.length === 0 ? new Map() : await levelsOf(ids);\n const levelOf = (row: UnknownRecord): RowLevel =>\n typeof row.id === \"string\" ? (levels.get(row.id) ?? null) : null;\n const rows: readonly unknown[] = Array.isArray(value) ? value : [value];\n // A value that is not a row goes to every reader as it is.\n const key = rows.map((row) => (isRecord(row) ? tiers.label(levelOf(row)) : \"-\")).join(\"\");\n const one = (row: unknown): unknown =>\n isRecord(row) ? strip(row, tiers.hidden(levelOf(row))) : row;\n return { key, strip: () => (Array.isArray(value) ? value.map(one) : one(value)) };\n}\n","// Collection items and membership (RFC 0003 sections 7.1 and 7.2). An item is\n// the row in the collection's item projection, the same for everyone in the\n// scope: collections have no per-subscriber field tiers, so a field the\n// contract's `fields` reserves for a level above the collection's `access` is\n// left out of every item and patch. Membership is the declared scope plus the\n// equality filter `where`, read from a row's values.\n//\n// `qd:col:items` (section 7.4) loads items by id: a client holding a scope's\n// index asks for the members it shows. The read applies the scope and\n// `where`, so an id that is not a member is simply absent from the answer.\n\nimport type { Revision } from \"../../protocol/envelope\";\nimport { pickKeys, projectRow } from \"../emit/projection\";\nimport { strip } from \"../emit/tiers\";\nimport type { StorageAdapter, StorageRow, StorageWhere } from \"../storage\";\nimport type { BoundCollection } from \"./bind\";\nimport type { ServiceCollection } from \"./define\";\n\n/** The most ids one `qd:col:items` may name. */\nexport const MAX_ITEM_IDS = 200;\n\ntype Values = Readonly<Record<string, unknown>>;\n\nfunction isRecord(value: unknown): value is Values {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** The keys of the item projection a subscriber at the collection's `access` level does not receive. */\nfunction hiddenOf(collection: ServiceCollection): ReadonlySet<string> {\n return collection.item.tiers.hidden(collection.access);\n}\n\n/** One row as a collection item. */\nexport function itemOf(collection: ServiceCollection, row: StorageRow): unknown {\n const item = projectRow(collection.item, row);\n return isRecord(item) ? strip(item, hiddenOf(collection)) : item;\n}\n\n/** The fields of a `patched` delta: the patched item keys the row has, without hidden ones. */\nexport function patchOf(\n collection: ServiceCollection,\n row: StorageRow,\n fields: readonly string[],\n): Record<string, unknown> {\n const hidden = hiddenOf(collection);\n return pickKeys(\n row,\n fields.filter((field) => !hidden.has(field)),\n );\n}\n\n/** The columns besides `id` that decide membership of a column-scoped collection: its scope column and `where`. */\nexport function membershipColumns(collection: ServiceCollection): readonly string[] {\n const where = Object.keys(collection.where);\n return collection.scope.kind === \"column\" ? [collection.scope.column, ...where] : where;\n}\n\n/** True when `values` match the collection's `where`. */\nexport function matchesWhere(collection: ServiceCollection, values: Values): boolean {\n return Object.entries(collection.where).every(\n ([column, expected]) => values[column] === expected,\n );\n}\n\n/**\n * The scope `values` put a row in, for a column-scoped collection: its scope\n * value when `where` matches, `null` when the row is in no scope, and\n * `undefined` when `values` lack a column that decides it.\n */\nexport function scopeIn(\n collection: ServiceCollection,\n values: Values | undefined,\n): string | null | undefined {\n if (values === undefined || collection.scope.kind !== \"column\") {\n return undefined;\n }\n if (membershipColumns(collection).some((column) => !Object.hasOwn(values, column))) {\n return undefined;\n }\n const scope = values[collection.scope.column];\n const valid = typeof scope === \"string\" && scope.length > 0;\n return valid && matchesWhere(collection, values) ? scope : null;\n}\n\n/** What a read for items selects: the item's select, plus `extra` columns (order or membership). */\nexport function selectWith(\n base: Readonly<Record<string, unknown>>,\n extra: readonly string[],\n): Readonly<Record<string, unknown>> {\n const select: Record<string, unknown> = { ...base, id: true };\n for (const column of extra) {\n if (select[column] === undefined) {\n select[column] = true;\n }\n }\n return select;\n}\n\n/**\n * The filter matching the members of `scope` among `ids`: its scope column,\n * or the ids among them its `via` junction links to it, and `where`.\n * `undefined` when none can be a member.\n */\nasync function membersAmong(\n storage: StorageAdapter,\n collection: BoundCollection,\n scope: string,\n ids: readonly string[],\n): Promise<StorageWhere | undefined> {\n const { where } = collection;\n const filtered = (filter: StorageWhere): StorageWhere =>\n Object.keys(where).length === 0 ? filter : { AND: [filter, where] };\n if (collection.scope.kind === \"column\") {\n return filtered({ [collection.scope.column]: scope, id: { in: [...ids] } });\n }\n const { model, entry, scope: column } = collection.scope;\n const links = await storage.findMany(model, {\n where: { [column]: scope, [entry]: { in: [...ids] } },\n select: { [entry]: true },\n });\n const linked = links.map((link) => link[entry]).filter((id) => typeof id === \"string\");\n return linked.length === 0 ? undefined : filtered({ id: { in: [...new Set(linked)] } });\n}\n\n/**\n * The items of the members of `scope` among `ids`, in the order of `ids`,\n * each once, and the revision they were read at (`rev`, claimed before the\n * first read): one read for a column scope, two for a `via` scope (its\n * links among `ids`, then the rows). An id that is not a member is left out.\n */\nexport async function readItemsById(\n storage: StorageAdapter,\n collection: BoundCollection,\n scope: string,\n ids: readonly string[],\n rev: Revision,\n): Promise<{ readonly rev: Revision; readonly items: unknown[] }> {\n const wanted = [...new Set(ids)];\n const members =\n wanted.length === 0 ? undefined : await membersAmong(storage, collection, scope, wanted);\n if (members === undefined) {\n return { rev, items: [] };\n }\n const rows = await storage.findMany(collection.model, {\n where: members,\n select: collection.item.select,\n });\n const found = new Map(rows.flatMap((row) => (typeof row.id === \"string\" ? [[row.id, row]] : [])));\n const items = wanted.flatMap((id) => {\n const row = found.get(id);\n return row === undefined ? [] : [itemOf(collection, row)];\n });\n return { rev, items };\n}\n","// Keyset cursors over a collection's `order` (RFC 0003 section 7.3). A\n// cursor holds the last row's value of each order column, `id` last, as\n// base64url JSON; the next page is the rows after those values in `order`.\n// Unlike an offset, it stays on its row when rows are inserted or removed\n// before it. 4.1 left paging to each collection's own `snapshot` function\n// (4.1 `src/server/collections.ts:51-55`), which in practice used offsets.\n//\n// Nulls sort last in ascending order and first in descending order (as\n// PostgreSQL does by default); a nullable column is ordered that way\n// explicitly, so the database's own default does not matter. Prisma refuses\n// a null filter or null ordering on a required column, so which columns may\n// be null comes from the storage adapter (`StorageAdapter.nullable`).\n//\n// order [ordinal asc, id asc], cursor (3, \"t9\"):\n// ordinal > 3 OR ordinal IS NULL (when nullable) OR (ordinal = 3 AND id > \"t9\")\n\nimport type { OrderBy, SortDirection } from \"../../contract/collections\";\nimport type { StorageRow, StorageWhere } from \"../storage\";\nimport { unreadable } from \"../transports/ack\";\n\n/** A cursor's values: the value of each order column of the row it follows, `id` last. */\nexport type CursorValues = readonly unknown[];\n\nconst DATE = \"$date\";\nconst BIGINT = \"$bigint\";\n\nconst INVALID = \"cursor is not a cursor of this collection\";\n\nfunction isTagged(value: unknown, tag: string): value is Readonly<Record<string, string>> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.keys(value).length === 1 &&\n typeof (value as Readonly<Record<string, unknown>>)[tag] === \"string\"\n );\n}\n\n/** A column value as JSON can carry it: dates and big integers tagged. */\nfunction pack(value: unknown): unknown {\n if (value instanceof Date) {\n return { [DATE]: value.toISOString() };\n }\n if (typeof value === \"bigint\") {\n return { [BIGINT]: value.toString() };\n }\n return value ?? null;\n}\n\n/** A packed value back, or `undefined` for one no cursor holds. */\nfunction unpack(value: unknown): unknown {\n if (isTagged(value, DATE)) {\n const date = new Date(value[DATE] ?? \"\");\n return Number.isNaN(date.getTime()) ? undefined : date;\n }\n if (isTagged(value, BIGINT)) {\n const digits = value[BIGINT] ?? \"\";\n return /^-?\\d+$/.test(digits) ? BigInt(digits) : undefined;\n }\n const plain = value === null || [\"string\", \"number\", \"boolean\"].includes(typeof value);\n return plain ? value : undefined;\n}\n\n/** The cursor that follows `row`: its value of each order column. */\nexport function encodeCursor(order: OrderBy, row: StorageRow): string {\n const values = order.map(([column]) => pack(row[column]));\n return Buffer.from(JSON.stringify(values), \"utf8\").toString(\"base64url\");\n}\n\n/** The values a cursor holds, or a `VALIDATION` error for a string that is not a cursor of `order`. */\nexport function decodeCursor(order: OrderBy, cursor: string): CursorValues {\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf8\"));\n } catch {\n throw unreadable(INVALID, [\"cursor\"]);\n }\n if (!Array.isArray(parsed) || parsed.length !== order.length) {\n throw unreadable(INVALID, [\"cursor\"]);\n }\n const values = parsed.map(unpack);\n const id = values.at(-1);\n if (values.includes(undefined) || typeof id !== \"string\" || id.length === 0) {\n throw unreadable(INVALID, [\"cursor\"]);\n }\n return values;\n}\n\n/** Prisma's `orderBy` for `order`: nulls last ascending and first descending, where a column may hold them. */\nexport function orderByOf(\n order: OrderBy,\n nullable: ReadonlySet<string>,\n): Readonly<Record<string, unknown>>[] {\n return order.map(([column, direction]) => ({\n [column]: nullable.has(column)\n ? { sort: direction, nulls: direction === \"asc\" ? \"last\" : \"first\" }\n : direction,\n }));\n}\n\n/** The rows strictly after `value` in one column, or `undefined` when none can be. */\nfunction beyond(\n column: string,\n direction: SortDirection,\n value: unknown,\n nullable: boolean,\n): StorageWhere | undefined {\n if (direction === \"desc\") {\n return value === null ? { [column]: { not: null } } : { [column]: { lt: value } };\n }\n if (value === null) {\n return undefined;\n }\n const greater = { [column]: { gt: value } };\n return nullable ? { OR: [greater, { [column]: null }] } : greater;\n}\n\n/**\n * The filter matching the rows after `values` in `order`: for each column, the\n * rows equal on every column before it and after it on that one.\n */\nexport function afterCursor(\n order: OrderBy,\n values: CursorValues,\n nullable: ReadonlySet<string>,\n): StorageWhere {\n const branches: StorageWhere[] = [];\n const equal: StorageWhere[] = [];\n for (const [index, [column, direction]] of order.entries()) {\n const value = values[index] ?? null;\n const after = beyond(column, direction, value, nullable.has(column) || value === null);\n if (after !== undefined) {\n branches.push(equal.length === 0 ? after : { AND: [...equal, after] });\n }\n equal.push({ [column]: value });\n }\n return branches.length === 1 ? (branches[0] ?? {}) : { OR: branches };\n}\n","// The collection index (RFC 0003 section 7.4): one small row per member of a\n// scope, `[id, rev, ...index fields]` in `order`, sent whole with the first\n// page of the scope. A client then knows the scope's membership and order at\n// once, filters it by views without asking the server, and loads full items\n// by window, by id (`qd:col:items`) or all at once. 4.1 had nothing like it:\n// a board loaded page after page, and mirrored the server's filters to know\n// what it held.\n//\n// Deltas keep the index live, from the same flush batch as the items: an\n// `added` delta carries its member's index row, built from the very item it\n// sends (`deltas.ts`), and `patched` and `updated` deltas carry every changed\n// index field, since index fields are item fields the items carry\n// (`define.ts`). So an index row and its item never disagree.\n//\n// An index row's `rev` is the time in the service's `versionColumn` when it\n// declares one, else the revision the snapshot (or the flush, for an `added`\n// delta) was read at. Index fields are read with the item's own select for\n// them (the item's whole select when it has a `map`) and projected and\n// stripped as items are.\n//\n// A snapshot's index is one more statement, run beside the page and the\n// count. It holds at most {@link INDEX_MAX_ROWS} rows: a larger scope gets\n// `indexTruncated: true` instead, and is loaded by pages.\n\nimport type { Revision, WireIndexRow } from \"../../protocol/envelope\";\nimport { versionTime } from \"../rev\";\nimport type { StorageAdapter, StorageRow, StorageWhere } from \"../storage\";\nimport type { BoundCollection } from \"./bind\";\nimport { orderByOf } from \"./cursor\";\nimport { itemOf, selectWith } from \"./items\";\n\n/** The most members a scope's index holds; a larger scope's first page says `indexTruncated`. */\nexport const INDEX_MAX_ROWS = 50_000;\n\n/** What a first page carries besides its items: the scope's index, or that it was too large for one. */\nexport type IndexPart =\n | { readonly index: readonly WireIndexRow[] }\n | { readonly indexTruncated: true };\n\ntype Values = Readonly<Record<string, unknown>>;\n\nfunction isRecord(value: unknown): value is Values {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The columns a read of an indexed collection's rows adds to the item's\n * select, so the index rows built from them carry their version: the\n * service's `versionColumn`, or none.\n */\nexport function indexColumns(collection: BoundCollection): readonly string[] {\n const { versionColumn } = collection.service;\n return collection.index === undefined || versionColumn === undefined ? [] : [versionColumn];\n}\n\n/** What an index read selects: `id` and the item's select for each index field, or its whole select when it maps. */\nfunction indexSelect(collection: BoundCollection, fields: readonly string[]): Values {\n const { item } = collection;\n const select =\n item.map === undefined\n ? Object.fromEntries(\n fields.flatMap((field) =>\n item.select[field] === undefined ? [] : [[field, item.select[field]]],\n ),\n )\n : item.select;\n return selectWith(select, indexColumns(collection));\n}\n\n/**\n * The index row of a member, from the item it is sent as (`item`, built from\n * `row`) and `rev`, the revision `row` was read at: its version column's time\n * instead, when the service declares one. A field the item lacks is `null`.\n */\nexport function indexRowFrom(\n collection: BoundCollection,\n item: unknown,\n row: StorageRow,\n rev: Revision,\n): WireIndexRow {\n const values = isRecord(item) ? item : {};\n const { versionColumn } = collection.service;\n const version = versionColumn === undefined ? undefined : versionTime(row[versionColumn]);\n const id = typeof row.id === \"string\" ? row.id : \"\";\n return [id, version ?? rev, ...(collection.index ?? []).map((field) => values[field] ?? null)];\n}\n\n/**\n * Reads the index of the scope `members` matches, in `order` (`nullable`\n * holds the order columns that may hold null), at revision `rev`: one\n * statement. More than `max` members give `indexTruncated` instead.\n */\nexport async function readIndex(\n storage: StorageAdapter,\n collection: BoundCollection,\n members: StorageWhere,\n nullable: ReadonlySet<string>,\n rev: Revision,\n max = INDEX_MAX_ROWS,\n): Promise<IndexPart> {\n const fields = collection.index ?? [];\n const rows = await storage.findMany(collection.model, {\n where: members,\n select: indexSelect(collection, fields),\n orderBy: orderByOf(collection.order, nullable),\n take: max + 1,\n });\n if (rows.length > max) {\n return { indexTruncated: true };\n }\n return {\n index: rows.flatMap((row) =>\n typeof row.id === \"string\"\n ? [indexRowFrom(collection, itemOf(collection, row), row, rev)]\n : [],\n ),\n };\n}\n","// Memoized and cached policy lookups (RFC 0003 section 4.2): \"results are\n// memoized per request; an optional `cacheMs` keeps them across requests;\n// tracked writes to the membership model, the access column or the owner\n// column evict the affected entries\".\n//\n// Values are kept per namespace (one per service's rows, one per membership\n// table a service's policy reads, one per service's levels), per scope (the\n// user id for per-user values, `\"\"` for a row's columns) and per row id.\n//\n// - The request memo holds promises, so two lookups of one row in a request,\n// even concurrent ones, share one query. It lives for one engine call: an\n// authorization, or one `levelsFor` / `accessWhere` of the dispatcher.\n// - The cross-request cache holds settled values until `cacheMs` passes or a\n// tracked write evicts them (`changes.ts`). Only the database reads are\n// kept (row columns and membership levels), never a level computed from\n// them, so a change to a parent row needs no cascade: the child's level is\n// recomputed from the parent's freshly read values.\n// - A lookup is kept across requests only when no eviction of its namespace\n// happened while it ran (the namespace's generation is unchanged), and\n// only when it did not read inside a transaction, whose uncommitted rows\n// may yet roll back. A deny is kept like a grant, under the same eviction.\n\n/** A namespace of cached values; compared by identity. */\nexport interface Namespace {\n /** For debugging: what the namespace holds. */\n readonly label: string;\n}\n\n/** Creates a namespace. */\nexport function namespace(label: string): Namespace {\n return Object.freeze({ label });\n}\n\ntype Scoped<V> = Map<string, Map<string, V>>;\n\nfunction getIn<V>(\n store: Map<Namespace, Scoped<V>>,\n ns: Namespace,\n scope: string,\n id: string,\n): V | undefined {\n return store.get(ns)?.get(scope)?.get(id);\n}\n\nfunction setIn<V>(\n store: Map<Namespace, Scoped<V>>,\n ns: Namespace,\n scope: string,\n id: string,\n value: V,\n): boolean {\n let scopes = store.get(ns);\n if (scopes === undefined) {\n scopes = new Map();\n store.set(ns, scopes);\n }\n let ids = scopes.get(scope);\n if (ids === undefined) {\n ids = new Map();\n scopes.set(scope, ids);\n }\n const added = !ids.has(id);\n ids.set(id, value);\n return added;\n}\n\n/** One engine call's memo: lookups in flight or settled, by namespace, scope and id. */\nexport interface RequestMemo {\n get(ns: Namespace, scope: string, id: string): Promise<unknown> | undefined;\n set(ns: Namespace, scope: string, id: string, value: Promise<unknown>): void;\n}\n\n/** Creates the memo of one engine call. */\nexport function createRequestMemo(): RequestMemo {\n const store = new Map<Namespace, Scoped<Promise<unknown>>>();\n return {\n get: (ns, scope, id) => getIn(store, ns, scope, id),\n set(ns, scope, id, value) {\n setIn(store, ns, scope, id, value);\n },\n };\n}\n\ninterface Entry {\n readonly value: unknown;\n readonly expiresAt: number;\n}\n\n/** Options of {@link createAccessCache}. */\nexport interface AccessCacheOptions {\n /** How long a value is kept, in milliseconds. */\n readonly ttlMs: number;\n /** At most this many values are kept; past it, expired ones are dropped, then all. Default 100,000. */\n readonly maxEntries?: number;\n /** The clock. Default `Date.now`. */\n readonly now?: () => number;\n}\n\n/** The cross-request cache of policy lookups. */\nexport interface AccessCache {\n /** The value kept for the row, or `undefined` when none is (a kept value may be `null`). */\n get(ns: Namespace, scope: string, id: string): { readonly value: unknown } | undefined;\n set(ns: Namespace, scope: string, id: string, value: unknown): void;\n /**\n * Drops kept values: one (`scope` and `id`), the row's in every scope\n * (`id` only), a scope's (`scope` only: a user's levels), or the whole\n * namespace (neither). Every eviction moves the namespace to its next\n * generation.\n */\n evict(ns: Namespace, scope?: string, id?: string): void;\n /** Changes on every eviction in `ns`; a lookup that saw it change while running is not kept. */\n generation(ns: Namespace): number;\n /** How many values are kept. */\n readonly size: number;\n}\n\nconst DEFAULT_MAX_ENTRIES = 100_000;\n\n/** Drops one scope's values, or every scope's without `scope`; returns how many values went. */\nfunction dropScopes(scopes: Scoped<Entry>, scope: string | undefined): number {\n const names = scope === undefined ? [...scopes.keys()] : [scope];\n let dropped = 0;\n for (const name of names) {\n dropped += scopes.get(name)?.size ?? 0;\n scopes.delete(name);\n }\n return dropped;\n}\n\n/** Creates the cross-request cache. */\nexport function createAccessCache(options: AccessCacheOptions): AccessCache {\n const { ttlMs } = options;\n const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const now = options.now ?? Date.now;\n const store = new Map<Namespace, Scoped<Entry>>();\n const generations = new Map<Namespace, number>();\n let size = 0;\n\n const bump = (ns: Namespace): void => {\n generations.set(ns, (generations.get(ns) ?? 0) + 1);\n };\n const sweep = (): void => {\n const time = now();\n for (const scopes of store.values()) {\n for (const ids of scopes.values()) {\n for (const [id, entry] of ids) {\n if (entry.expiresAt <= time) {\n ids.delete(id);\n size -= 1;\n }\n }\n }\n }\n };\n const evictRow = (scopes: Scoped<Entry>, scope: string | undefined, id: string): void => {\n const targets = scope === undefined ? [...scopes.values()] : [scopes.get(scope)];\n for (const ids of targets) {\n if (ids?.delete(id) === true) {\n size -= 1;\n }\n }\n };\n\n return {\n get(ns, scope, id) {\n const entry = getIn(store, ns, scope, id);\n if (entry === undefined) {\n return undefined;\n }\n if (entry.expiresAt <= now()) {\n store.get(ns)?.get(scope)?.delete(id);\n size -= 1;\n return undefined;\n }\n return { value: entry.value };\n },\n set(ns, scope, id, value) {\n if (size >= maxEntries) {\n sweep();\n }\n if (size >= maxEntries) {\n store.clear();\n size = 0;\n }\n if (setIn(store, ns, scope, id, { value, expiresAt: now() + ttlMs })) {\n size += 1;\n }\n },\n evict(ns, scope, id) {\n bump(ns);\n const scopes = store.get(ns);\n if (scopes === undefined) {\n return;\n }\n if (id !== undefined) {\n evictRow(scopes, scope, id);\n return;\n }\n size -= dropScopes(scopes, scope);\n if (scopes.size === 0) {\n store.delete(ns);\n }\n },\n generation: (ns) => generations.get(ns) ?? 0,\n get size() {\n return size;\n },\n };\n}\n\n/** Where a lookup reads through: the call's memo, and the cache when one is on. */\nexport interface LookupScope {\n readonly memo: RequestMemo;\n readonly cache: AccessCache | undefined;\n /** Whether a lookup starting now may be kept across requests (it is not inside a transaction). */\n keepable(): boolean;\n}\n\n/**\n * The values of `ids` in `ns` and `scope`: from the memo, then the cache, and\n * the rest from one call of `load`. An id `load` does not return is `null`.\n * Rejects when `load` does; the memo then holds the failure for the rest of\n * the call, and nothing is cached.\n */\nexport async function lookup<V>(\n where: LookupScope,\n ns: Namespace,\n scope: string,\n ids: readonly string[],\n load: (missing: readonly string[]) => Promise<ReadonlyMap<string, V>>,\n): Promise<Map<string, V | null>> {\n const pending = new Map<string, Promise<V | null>>();\n const missing: string[] = [];\n for (const id of new Set(ids)) {\n const memoized = where.memo.get(ns, scope, id) as Promise<V | null> | undefined;\n const cached = memoized === undefined ? where.cache?.get(ns, scope, id) : undefined;\n if (memoized !== undefined) {\n pending.set(id, memoized);\n } else if (cached === undefined) {\n missing.push(id);\n } else {\n const value = Promise.resolve(cached.value as V | null);\n where.memo.set(ns, scope, id, value);\n pending.set(id, value);\n }\n }\n if (missing.length > 0) {\n const keepIn = where.cache !== undefined && where.keepable() ? where.cache : undefined;\n const generation = keepIn?.generation(ns);\n const batch = load(missing).then((loaded) => {\n if (keepIn !== undefined && keepIn.generation(ns) === generation) {\n for (const id of missing) {\n keepIn.set(ns, scope, id, loaded.get(id) ?? null);\n }\n }\n return loaded;\n });\n for (const id of missing) {\n const value = batch.then((loaded) => loaded.get(id) ?? null);\n where.memo.set(ns, scope, id, value);\n pending.set(id, value);\n }\n }\n const settled = await Promise.all(\n [...pending].map(async ([id, value]) => [id, await value] as const),\n );\n return new Map(settled);\n}\n","// Access policies (RFC 0003 section 4.2): how a principal's level on a row of\n// a service is found. A service declares one with `defineService(contract,\n// { model, access })`, and every surface (method calls, list filters, and\n// later subscriptions and collections) asks it the same two questions:\n//\n// - `levelsFor(principal, ids)`: the principal's level on each row, in one\n// batched lookup. A row that is not found, a malformed column or an\n// unknown level gives `null`: no access.\n// - `accessWhere(principal, level)`: a filter matching exactly the rows on\n// which the principal has at least `level`, or `\"none\"`.\n//\n// The builders (`owner`, `jsonAcl`, `members`, `inherit`, `anyOf`,\n// `resolver`, `everyone`) live in `policies/`. A policy reads the database only through\n// the `PolicyTools` it is given, which batch, memoize per request and, when\n// the dispatcher enables it, cache across requests; `reads` tells the engine\n// which columns and models a policy depends on, so tracked writes to them\n// evict the cache (`changes.ts`). It replaces 4.1's `checkAccess`,\n// `checkEntryACL` and `checkBatchSubscriptionAccess`\n// (4.1 `src/server/BaseService.ts:292-306, 513-547`).\n//\n// The framework never imports generated Prisma types. A policy's type\n// carries the column names it reads, and `defineService` checks them against\n// the app's database client structurally, through each model delegate's\n// `fields` (`ModelColumn`); with a client that has no such members any name\n// passes.\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { StorageAdapter, StorageRow, StorageWhere } from \"../storage\";\nimport type { Principal } from \"../types\";\n\n/** A principal's level on one row: an access level, or `null` for none. */\nexport type RowLevel = AccessLevel | null;\n\n/** Levels by row id. An id missing from the map has no level. */\nexport type RowLevels = ReadonlyMap<string, RowLevel>;\n\n/** A storage filter matching the rows a principal may see, or `\"none\"` when no row matches. */\nexport type AccessFilter = StorageWhere | \"none\";\n\n/** A membership table a `members` policy reads: one row per user and entry. */\nexport interface MembershipRead {\n /** The membership model, named as the client names it: `\"projectMember\"`. */\n readonly model: string;\n /** The column holding the id of the row the membership is on: `\"projectId\"`. */\n readonly entry: string;\n /** The column holding the member's user id: `\"userId\"`. */\n readonly user: string;\n /** The column holding the member's role. */\n readonly level: string;\n /** Maps stored roles to access levels; without it a role must be a level name. */\n readonly levels: Readonly<Record<string, AccessLevel>> | undefined;\n}\n\n/** A parent row a policy takes its level from: `inherit({ from, via })`. */\nexport interface ParentLink {\n /** The parent service's contract. */\n readonly from: AnyContract;\n /** The column of the service's model holding the parent row's id. */\n readonly via: string;\n}\n\n/**\n * What a policy reads, so the engine can register interest in those columns\n * with the storage adapter (tracked writes then carry their `before` and\n * `after` values) and evict cached lookups when they are written.\n */\nexport interface PolicyReads {\n /** Columns of the service's own model. */\n readonly columns: readonly string[];\n /** Membership tables. */\n readonly memberships: readonly MembershipRead[];\n /** The services whose policies this one asks (`inherit`). */\n readonly inherits: readonly AnyContract[];\n /**\n * The parent rows a level comes from (`inherit`), with the column naming\n * each: the rows a live subscription's access is anchored on besides its\n * own (RFC 0003 section 4.4).\n */\n readonly parents?: readonly ParentLink[];\n /** Whether the policy reads the database through the storage adapter. */\n readonly storage: boolean;\n}\n\n/** What a policy reads the database with: batched, memoized per request, and cached when enabled. */\nexport interface PolicyTools {\n /** The dispatcher's storage adapter. */\n readonly storage: StorageAdapter;\n /** The database model of the service the policy guards, named as the client names it. */\n readonly model: string;\n /**\n * The service's rows `ids`, with the columns its policy reads (`reads.columns`),\n * in one query for every id not read yet in this request. `null` for a row\n * that does not exist.\n */\n rows(ids: readonly string[]): Promise<ReadonlyMap<string, StorageRow | null>>;\n /** The level each of `userId`'s memberships in `read` gives on the rows `ids`, in one query. */\n memberships(read: MembershipRead, userId: string, ids: readonly string[]): Promise<RowLevels>;\n /** The principal's level on rows of another service, from that service's policy. */\n levelsOf(contract: AnyContract, principal: Principal, ids: readonly string[]): Promise<RowLevels>;\n /** Another service's filter for the principal and `level`, from that service's policy. */\n whereOf(contract: AnyContract, principal: Principal, level: AccessLevel): Promise<AccessFilter>;\n /** The ids of the rows of another service the principal has at least `level` on. */\n idsWhere(\n contract: AnyContract,\n principal: Principal,\n level: AccessLevel,\n ): Promise<readonly string[]>;\n}\n\n/** The other models a policy reads, and their columns: `{ model: \"projectMember\", columns: \"projectId\" | \"userId\" | \"role\" }`. */\nexport interface ForeignColumns {\n readonly model: string;\n readonly columns: string;\n}\n\n/** The builder a policy came from. */\nexport type PolicyKind =\n | \"owner\"\n | \"jsonAcl\"\n | \"members\"\n | \"inherit\"\n | \"anyOf\"\n | \"resolver\"\n | \"everyone\";\n\n/**\n * A service's access policy, from one of the builders. `Columns` names the\n * columns of the service's own model it reads and `Foreign` the other models\n * and columns; `defineService` checks both against the app's database client.\n */\nexport interface AccessPolicy<\n Columns extends string = string,\n Foreign extends ForeignColumns = ForeignColumns,\n> {\n readonly kind: PolicyKind;\n /** The columns and models the policy depends on. */\n readonly reads: PolicyReads;\n /** The principal's level on each of `ids`, from one batched lookup. */\n levelsFor(principal: Principal, ids: readonly string[], tools: PolicyTools): Promise<RowLevels>;\n /** A filter matching exactly the rows on which the principal has at least `level`. */\n accessWhere(principal: Principal, level: AccessLevel, tools: PolicyTools): Promise<AccessFilter>;\n /** Type-only: the columns of the service's model this policy reads. Never set. */\n readonly \"~columns\"?: Columns;\n /** Type-only: the other models and columns this policy reads. Never set. */\n readonly \"~foreign\"?: Foreign;\n}\n\n/** Any access policy. */\nexport type AnyAccessPolicy = AccessPolicy<string, ForeignColumns>;\n\n/** The own-model columns an access policy type reads. */\nexport type PolicyColumns<P> =\n P extends AccessPolicy<infer Columns, ForeignColumns> ? Columns : never;\n\n/** The other models and columns an access policy type reads. */\nexport type PolicyForeign<P> = P extends AccessPolicy<string, infer Foreign> ? Foreign : never;\n\n// ---------------------------------------------------------------------------\n// The app's models, read structurally from its database client: a model\n// delegate (`db.project`) lists its scalar fields in `fields`, as Prisma's\n// generated client does. Nothing here names a Prisma type.\n// ---------------------------------------------------------------------------\n\ninterface ModelDelegateLike {\n readonly fields: object;\n findMany(...args: never[]): unknown;\n}\n\ntype DelegateNames<Db> = {\n [Name in keyof Db]-?: Db[Name] extends ModelDelegateLike ? Name : never;\n}[keyof Db] &\n string;\n\n/** The model names of the app's database client, or any string when the client lists none. */\nexport type ModelName<Db> = [DelegateNames<Db>] extends [never] ? string : DelegateNames<Db>;\n\ntype FieldsOf<Db, Model> = Model extends keyof Db\n ? Db[Model] extends { readonly fields: infer Fields }\n ? Fields\n : never\n : never;\n\n/** The columns of `Model` in the app's database client, or any string when the client does not list them. */\nexport type ModelColumn<Db, Model extends string> = [FieldsOf<Db, Model>] extends [never]\n ? string\n : keyof FieldsOf<Db, Model> & string;\n\n/** Every model of the app's database client with its columns: what a policy may read besides its own model. */\nexport type ForeignColumnsOf<Db> = [DelegateNames<Db>] extends [never]\n ? ForeignColumns\n : {\n [Name in DelegateNames<Db>]: {\n readonly model: Name;\n readonly columns: ModelColumn<Db, Name>;\n };\n }[DelegateNames<Db>];\n\n/** The access policies a service of `Model` may declare, given the app's database client. */\nexport type PolicyFor<Db, Model> = Model extends string\n ? AccessPolicy<ModelColumn<Db, Model>, ForeignColumnsOf<Db>>\n : never;\n\n// ---------------------------------------------------------------------------\n// Run time: the builders brand what they return, so `defineService` can tell\n// a policy from a look-alike object.\n// ---------------------------------------------------------------------------\n\nconst POLICIES = new WeakSet<object>();\n\n/** What a builder provides; `definePolicy` freezes and brands it. */\nexport type PolicySpec = Omit<AnyAccessPolicy, \"~columns\" | \"~foreign\"> & Record<string, unknown>;\n\n/** Freezes and brands a policy made by one of the builders. */\nexport function definePolicy<P extends AnyAccessPolicy>(spec: PolicySpec): P {\n const policy = Object.freeze({ ...spec, reads: Object.freeze(spec.reads) });\n POLICIES.add(policy);\n return policy as unknown as P;\n}\n\n/** True when `value` is a policy from one of the builders (`owner`, `members`, ...). */\nexport function isAccessPolicy(value: unknown): value is AnyAccessPolicy {\n return typeof value === \"object\" && value !== null && POLICIES.has(value);\n}\n\n/** Throws a `TypeError` unless `value` is a non-empty string: a column or model name. */\nexport function checkName(builder: string, option: string, value: unknown): string {\n if (typeof value !== \"string\" || value.length === 0) {\n throw new TypeError(\n `${builder}: ${option} must be a ${option === \"model\" ? \"model\" : \"column\"} name`,\n );\n }\n return value;\n}\n\n/** A map holding the level `levelOf(id)` gives each of `ids`. */\nexport function levelsById(\n ids: readonly string[],\n levelOf: (id: string) => RowLevel,\n): Map<string, RowLevel> {\n return new Map(ids.map((id) => [id, levelOf(id)]));\n}\n\n/** `{ id: { in: ids } }`, or `\"none\"` for no ids. */\nexport function idFilter(ids: readonly string[]): AccessFilter {\n return ids.length === 0 ? \"none\" : { id: { in: [...new Set(ids)] } };\n}\n\n/** The id list of a filter `idFilter` made, or `undefined` for any other filter. */\nexport function idsOfFilter(filter: StorageWhere): readonly string[] | undefined {\n const keys = Object.keys(filter);\n const { id } = filter;\n if (keys.length !== 1 || typeof id !== \"object\" || id === null) {\n return undefined;\n }\n const list: unknown = (id as Readonly<Record<string, unknown>>).in;\n const onlyIn = Object.keys(id).length === 1;\n return onlyIn && Array.isArray(list) && list.every((item) => typeof item === \"string\")\n ? (list as readonly string[])\n : undefined;\n}\n","// One engine call's policy evaluation: the `PolicyTools` a policy reads the\n// database with, and the levels and filters of the bound policies. Every\n// lookup goes through the call's memo, and the database reads through the\n// cross-request cache when it is on (`cache.ts`): the service's rows, read\n// once with every column its policy uses, and each membership table's levels\n// per user.\n\nimport { isAccessLevel, type AccessLevel } from \"../../contract/access\";\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { StorageAdapter, StorageRow } from \"../storage\";\nimport type { Principal } from \"../types\";\nimport type { Binding } from \"./bindings\";\nimport {\n createRequestMemo,\n lookup,\n namespace,\n type AccessCache,\n type LookupScope,\n type Namespace,\n} from \"./cache\";\nimport { maxLevel } from \"./levels\";\nimport {\n idsOfFilter,\n type AccessFilter,\n type MembershipRead,\n type PolicyTools,\n type RowLevel,\n type RowLevels,\n} from \"./policy\";\n\n/** What every call of one dispatcher's engine shares. */\nexport interface EngineState {\n /** The bound policies, by service name. */\n readonly bindings: ReadonlyMap<string, Binding>;\n readonly storage: StorageAdapter | undefined;\n /** The cross-request cache, when `cacheMs` turned it on. */\n readonly cache: AccessCache | undefined;\n}\n\n/** One engine call: its lookups share a memo. */\nexport interface PolicyCall {\n /** The policy's level on each of `ids`: no service grants. */\n levels(binding: Binding, principal: Principal, ids: readonly string[]): Promise<RowLevels>;\n /** The policy's filter for `level`: no service grants. */\n where(binding: Binding, principal: Principal, level: AccessLevel): Promise<AccessFilter>;\n /**\n * The rows each of `ids`'s level is derived from, as `anchorKey`s: the row\n * itself, then its `inherit` parents up the chain. After `levels` in the\n * same call, the parents' ids come from the rows it already read.\n */\n anchors(binding: Binding, ids: readonly string[]): Promise<Map<string, string[]>>;\n}\n\n/** The key of the anchor `id` of `service`: a row a level is derived from. */\nexport function anchorKey(service: string, id: string): string {\n return `${service}\\u0000${id}`;\n}\n\n/** What one call's tools share. */\ninterface CallScope {\n readonly state: EngineState;\n readonly storage: StorageAdapter;\n /** Memo, then cache: for reads with eviction rules. */\n readonly cached: LookupScope;\n /** Memo only: for everything else. */\n readonly memoOnly: LookupScope;\n readonly undeclared: Map<MembershipRead, Namespace>;\n readonly tools: Map<Binding, PolicyTools>;\n readonly call: PolicyCall;\n}\n\nfunction storageMissing(): never {\n throw new QuickdrawError(\n \"INTERNAL\",\n \"An access policy read the database, but the dispatcher has no storage adapter: pass db as trackPrisma(prisma), or pass storage\",\n );\n}\n\n/** Stands in for a storage adapter the dispatcher does not have: any use fails with `INTERNAL`. */\nconst NO_STORAGE = new Proxy(Object.freeze({}) as StorageAdapter, {\n get: (_target, key) => (key === \"then\" ? undefined : storageMissing()),\n});\n\nfunction roleLevel(read: MembershipRead, role: unknown): RowLevel {\n if (read.levels === undefined) {\n return isAccessLevel(role) ? role : null;\n }\n return typeof role === \"string\" && Object.hasOwn(read.levels, role)\n ? (read.levels[role] ?? null)\n : null;\n}\n\nasync function readRows(\n storage: StorageAdapter,\n binding: Binding,\n ids: readonly string[],\n): Promise<Map<string, StorageRow>> {\n const select = Object.fromEntries([\"id\", ...binding.columns].map((column) => [column, true]));\n const rows = await storage.findMany(binding.model, { where: { id: { in: [...ids] } }, select });\n const byId = new Map<string, StorageRow>();\n for (const row of rows) {\n if (typeof row.id === \"string\") {\n byId.set(row.id, row);\n }\n }\n return byId;\n}\n\nasync function readMemberships(\n storage: StorageAdapter,\n read: MembershipRead,\n userId: string,\n ids: readonly string[],\n): Promise<Map<string, RowLevel>> {\n const rows = await storage.findMany(read.model, {\n where: { [read.entry]: { in: [...ids] }, [read.user]: userId },\n select: { [read.entry]: true, [read.level]: true },\n });\n const levels = new Map<string, RowLevel>();\n for (const row of rows) {\n const entry = row[read.entry];\n if (typeof entry === \"string\") {\n levels.set(entry, maxLevel(levels.get(entry), roleLevel(read, row[read.level])));\n }\n }\n return levels;\n}\n\nfunction bindingOf(state: EngineState, contract: AnyContract): Binding {\n const binding = state.bindings.get(contract.name);\n if (binding === undefined) {\n throw new QuickdrawError(\n \"INTERNAL\",\n `An access policy asked about ${contract.name}, which this dispatcher serves without an access policy`,\n );\n }\n return binding;\n}\n\n/** Memo and cache for a membership table the policy declared; memo only for one it did not (a resolver's). */\nfunction membershipScope(\n scope: CallScope,\n binding: Binding,\n read: MembershipRead,\n): [LookupScope, Namespace] {\n const declared = binding.memberships.get(read);\n if (declared !== undefined) {\n return [scope.cached, declared];\n }\n let ns = scope.undeclared.get(read);\n if (ns === undefined) {\n ns = namespace(`${read.model} (undeclared)`);\n scope.undeclared.set(read, ns);\n }\n return [scope.memoOnly, ns];\n}\n\nasync function idsWhere(\n scope: CallScope,\n contract: AnyContract,\n principal: Principal,\n level: AccessLevel,\n): Promise<readonly string[]> {\n const target = bindingOf(scope.state, contract);\n const filter = await scope.call.where(target, principal, level);\n if (filter === \"none\") {\n return [];\n }\n const listed = idsOfFilter(filter);\n if (listed !== undefined) {\n return listed;\n }\n const rows = await scope.storage.findMany(target.model, { where: filter, select: { id: true } });\n return rows.map((row) => row.id).filter((id): id is string => typeof id === \"string\");\n}\n\n/** The tools `binding`'s policy gets in this call. */\nfunction toolsFor(scope: CallScope, binding: Binding): PolicyTools {\n const made = scope.tools.get(binding);\n if (made !== undefined) {\n return made;\n }\n const { storage, state, call } = scope;\n const tools: PolicyTools = {\n storage,\n model: binding.model,\n rows: (ids) =>\n lookup(scope.cached, binding.rows, \"\", ids, (missing) => readRows(storage, binding, missing)),\n memberships(read, userId, ids) {\n const [where, ns] = membershipScope(scope, binding, read);\n return lookup(where, ns, userId, ids, (missing) =>\n readMemberships(storage, read, userId, missing),\n );\n },\n levelsOf: (contract, principal, ids) => call.levels(bindingOf(state, contract), principal, ids),\n whereOf: (contract, principal, level) =>\n call.where(bindingOf(state, contract), principal, level),\n idsWhere: (contract, principal, level) => idsWhere(scope, contract, principal, level),\n };\n scope.tools.set(binding, tools);\n return tools;\n}\n\n/** `PolicyCall.anchors`: each row, then the anchors of its `inherit` parents. */\nasync function anchorsOf(\n scope: CallScope,\n binding: Binding,\n ids: readonly string[],\n): Promise<Map<string, string[]>> {\n const anchors = new Map(ids.map((id) => [id, [anchorKey(binding.service.name, id)]]));\n for (const link of binding.policy.reads.parents ?? []) {\n const rows = await toolsFor(scope, binding).rows(ids);\n const parentOf = new Map<string, string>();\n for (const id of ids) {\n const parent = rows.get(id)?.[link.via];\n if (typeof parent === \"string\" && parent.length > 0) {\n parentOf.set(id, parent);\n }\n }\n const parents = await anchorsOf(scope, bindingOf(scope.state, link.from), [\n ...new Set(parentOf.values()),\n ]);\n for (const [id, parent] of parentOf) {\n anchors.get(id)?.push(...(parents.get(parent) ?? []));\n }\n }\n return anchors;\n}\n\n/** `where`, computing each service's filter for a principal and a level once. */\nfunction memoized(where: PolicyCall[\"where\"]): PolicyCall[\"where\"] {\n const made = new Map<string, Promise<AccessFilter>>();\n const principals = new Map<Principal, number>();\n return (binding, principal, level) => {\n let index = principals.get(principal);\n if (index === undefined) {\n index = principals.size;\n principals.set(principal, index);\n }\n const key = `${binding.service.name}\\u0000${String(index)}\\u0000${level}`;\n let filter = made.get(key);\n if (filter === undefined) {\n filter = where(binding, principal, level);\n made.set(key, filter);\n }\n return filter;\n };\n}\n\n/** Starts one engine call over `state`: its lookups share one memo. */\nexport function startCall(state: EngineState): PolicyCall {\n const memo = createRequestMemo();\n const memoOnly: LookupScope = { memo, cache: undefined, keepable: () => false };\n const scope: CallScope = {\n state,\n storage: state.storage ?? NO_STORAGE,\n cached: {\n memo,\n cache: state.cache,\n keepable: () => state.storage?.inTransaction?.() === false,\n },\n memoOnly,\n undeclared: new Map(),\n tools: new Map(),\n call: {\n levels: (binding, principal, ids) =>\n lookup(memoOnly, binding.levels, principal.userId, ids, (missing) =>\n binding.policy.levelsFor(principal, missing, toolsFor(scope, binding)),\n ),\n // Once per service, principal and level: `inherit` asks its parent's filter, then its ids.\n where: memoized((binding, principal, level) =>\n binding.policy.accessWhere(principal, level, toolsFor(scope, binding)),\n ),\n anchors: (binding, ids) => anchorsOf(scope, binding, ids),\n },\n };\n return scope.call;\n}\n","// The subscribes and watches a socket has in flight (RFC 0003 sections 6, 7.3\n// and 11.3), and how often its client unsubscribed from each while one ran.\n// A subscribe reads before it joins, so an unsubscribe that arrives while it\n// runs must stop its join: the subscribe notes the count when it begins and\n// joins only if the count did not move. The count matters only while a\n// subscribe of the key is in flight, so nothing is kept for any other key:\n// a client unsubscribing from keys it never subscribed to costs no memory.\n\nimport type { QuickdrawServerSocket } from \"../transports/types\";\n\ninterface Pending {\n /** Subscribes of the key in flight. */\n running: number;\n /** Unsubscribes from the key since the first of them began. */\n unsubscribes: number;\n}\n\n/** In-flight subscribes per socket and key: a row (`anchorKey`), a scope's room or a topic's room. */\nexport class PendingKeys {\n readonly #sockets = new WeakMap<QuickdrawServerSocket, Map<string, Pending>>();\n\n /** A subscribe of `keys` begins; returns how often each was unsubscribed from so far. */\n begin(socket: QuickdrawServerSocket, keys: Iterable<string>): Map<string, number> {\n const pending = this.#sockets.get(socket) ?? new Map<string, Pending>();\n this.#sockets.set(socket, pending);\n const counts = new Map<string, number>();\n for (const key of new Set(keys)) {\n const entry = pending.get(key) ?? { running: 0, unsubscribes: 0 };\n entry.running += 1;\n pending.set(key, entry);\n counts.set(key, entry.unsubscribes);\n }\n return counts;\n }\n\n /** The subscribe of `keys` that `begin` started has ended. */\n end(socket: QuickdrawServerSocket, keys: Iterable<string>): void {\n const pending = this.#sockets.get(socket);\n if (pending === undefined) {\n return;\n }\n for (const key of new Set(keys)) {\n const entry = pending.get(key);\n if (entry === undefined) {\n continue;\n }\n entry.running -= 1;\n if (entry.running === 0) {\n pending.delete(key);\n }\n }\n if (pending.size === 0) {\n this.#sockets.delete(socket);\n }\n }\n\n /** The client unsubscribed from `key`: counted only while a subscribe of it is in flight. */\n unsubscribed(socket: QuickdrawServerSocket, key: string): void {\n const entry = this.#sockets.get(socket)?.get(key);\n if (entry !== undefined) {\n entry.unsubscribes += 1;\n }\n }\n\n /** How often the client unsubscribed from `key` while a subscribe of it was in flight. */\n count(socket: QuickdrawServerSocket, key: string): number {\n return this.#sockets.get(socket)?.get(key)?.unsubscribes ?? 0;\n }\n\n /** How many keys the socket has a subscribe in flight for. */\n size(socket: QuickdrawServerSocket): number {\n return this.#sockets.get(socket)?.size ?? 0;\n }\n}\n","// The live entity subscriptions of this process's sockets (RFC 0003 sections\n// 4.4 and 6). Each socket keeps its own on `socket.data.entities`: the level\n// it joined the row's tier room at, and the rows that level is derived from\n// (its anchors). The index here finds the sockets an access change can\n// concern by anchor, so revocation re-resolves only theirs. Rooms stay the\n// source of truth for who receives frames: nothing here is read to emit, and\n// 4.1's per-entity `subscribers` map (4.1 `src/server/BaseService.ts:86-89`)\n// is not kept.\n//\n// Services and ids come from client frames, so the records are kept in\n// objects without a prototype and read only through their own keys: a frame\n// naming `__proto__` or `constructor` finds nothing (`ownRecord`).\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport { entityRoom } from \"../../contract/names\";\nimport type { AccessChange } from \"../access/changes\";\nimport { anchorKey } from \"../access/tools\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport { PendingKeys } from \"./pending\";\n\n/**\n * `records[key]` when `records` holds `key` itself, never through its\n * prototype: client frames name the keys of per-socket records, and a key\n * like `__proto__`, `constructor` or `toString` must find nothing.\n */\nexport function ownRecord<T>(\n records: Readonly<Record<string, T>> | undefined,\n key: string,\n): T | undefined {\n return records !== undefined && Object.hasOwn(records, key) ? records[key] : undefined;\n}\n\n/** An empty record map without a prototype, so no key a client names is found on it. */\nexport function emptyRecords<T>(): Record<string, T> {\n return Object.create(null) as Record<string, T>;\n}\n\n/** One live subscription, as `socket.data.entities[service][id]` records it. */\nexport interface EntitySubscription {\n /** The level the socket holds on the row: it is in the row's room for this level. */\n readonly level: AccessLevel;\n /** The rows the level is derived from (`anchorKey`s): the row, then its `inherit` parents. */\n readonly anchors: readonly string[];\n}\n\n/**\n * `socket.data.entities`: a socket's subscriptions, by service, then row id.\n * Plain data, in objects without a prototype; read it with `ownRecord`.\n */\nexport type EntitySubscriptions = Record<string, Record<string, EntitySubscription>>;\n\n/** One subscription of a socket, with the row it is on. */\nexport interface SubscriptionEntry {\n readonly service: string;\n readonly id: string;\n readonly subscription: EntitySubscription;\n}\n\n/** How many of a socket's records each socket has under one key of an index. */\nexport type Counts = Map<QuickdrawServerSocket, number>;\n\n/** The service an `anchorKey` names. */\nexport function serviceOf(anchor: string): string {\n return anchor.slice(0, anchor.indexOf(\"\\u0000\"));\n}\n\n/** Counts one more (`1`) or one fewer (`-1`) record of the socket under `key`; drops what reaches zero. */\nexport function count(\n index: Map<string, Counts>,\n key: string,\n socket: QuickdrawServerSocket,\n by: 1 | -1,\n): void {\n const counts = index.get(key) ?? new Map<QuickdrawServerSocket, number>();\n const next = (counts.get(socket) ?? 0) + by;\n if (next > 0) {\n counts.set(socket, next);\n index.set(key, counts);\n return;\n }\n counts.delete(socket);\n if (counts.size === 0) {\n index.delete(key);\n }\n}\n\n/** This process's entity subscriptions, indexed by anchor. */\nexport class SubscriptionIndex {\n /** Moves on every access change this process handles; a subscribe that saw it move checks again. */\n accessChanges = 0;\n readonly #byAnchor = new Map<string, Counts>();\n readonly #byService = new Map<string, Counts>();\n /** The rows each socket has a `qd:sub` batch in flight for, by `anchorKey`. */\n readonly pending = new PendingKeys();\n\n #index(socket: QuickdrawServerSocket, anchors: readonly string[], by: 1 | -1): void {\n for (const anchor of anchors) {\n count(this.#byAnchor, anchor, socket, by);\n count(this.#byService, serviceOf(anchor), socket, by);\n }\n }\n\n /** The socket's subscription to a row, or `undefined`. */\n get(socket: QuickdrawServerSocket, service: string, id: string): EntitySubscription | undefined {\n return ownRecord(ownRecord(socket.data.entities, service), id);\n }\n\n /** Every subscription of the socket. */\n *entries(socket: QuickdrawServerSocket): Generator<SubscriptionEntry> {\n for (const [service, rows] of Object.entries(socket.data.entities ?? {})) {\n for (const [id, subscription] of Object.entries(rows)) {\n yield { service, id, subscription };\n }\n }\n }\n\n /** Records a subscription and puts the socket in the row's room for its level, replacing any earlier one. */\n set(\n socket: QuickdrawServerSocket,\n service: string,\n id: string,\n subscription: EntitySubscription,\n ): void {\n const previous = this.get(socket, service, id);\n if (previous !== undefined) {\n this.#index(socket, previous.anchors, -1);\n if (previous.level !== subscription.level) {\n void socket.leave(entityRoom(service, id, previous.level));\n }\n }\n const services = (socket.data.entities ??= emptyRecords());\n const rows = ownRecord(services, service) ?? emptyRecords<EntitySubscription>();\n services[service] = rows;\n rows[id] = subscription;\n this.#index(socket, subscription.anchors, 1);\n void socket.join(entityRoom(service, id, subscription.level));\n }\n\n /** Ends a subscription: the socket leaves the row's room. Returns what it was. */\n delete(\n socket: QuickdrawServerSocket,\n service: string,\n id: string,\n ): EntitySubscription | undefined {\n const previous = this.get(socket, service, id);\n if (previous === undefined) {\n return undefined;\n }\n this.#index(socket, previous.anchors, -1);\n void socket.leave(entityRoom(service, id, previous.level));\n const rows = ownRecord(socket.data.entities, service);\n if (rows !== undefined) {\n delete rows[id];\n }\n return previous;\n }\n\n /** A `qd:sub` batch of these rows begins; returns how often each was unsubscribed from so far. */\n begin(\n socket: QuickdrawServerSocket,\n service: string,\n ids: readonly string[],\n ): Map<string, number> {\n const counts = this.pending.begin(\n socket,\n ids.map((id) => anchorKey(service, id)),\n );\n return new Map(ids.map((id) => [id, counts.get(anchorKey(service, id)) ?? 0]));\n }\n\n /** The batch `begin` started has ended. */\n end(socket: QuickdrawServerSocket, service: string, ids: readonly string[]): void {\n this.pending.end(\n socket,\n ids.map((id) => anchorKey(service, id)),\n );\n }\n\n /** A client unsubscribed: forget its subscription, and stop one still being made from joining. */\n unsubscribe(socket: QuickdrawServerSocket, service: string, id: string): void {\n this.pending.unsubscribed(socket, anchorKey(service, id));\n this.delete(socket, service, id);\n }\n\n /** How often the client unsubscribed from the row while a batch of it ran; a batch joins only if that did not move. */\n unsubscribes(socket: QuickdrawServerSocket, service: string, id: string): number {\n return this.pending.count(socket, anchorKey(service, id));\n }\n\n /** A socket disconnected: Socket.IO has emptied its rooms; drop it from the index. */\n drop(socket: QuickdrawServerSocket): void {\n for (const { subscription } of this.entries(socket)) {\n this.#index(socket, subscription.anchors, -1);\n }\n socket.data.entities = emptyRecords();\n }\n\n /**\n * The subscriptions an access change can concern: those anchored on the\n * changed row (any row of the service when `id` is absent), of the changed\n * user's sockets (every user's when `userId` is absent).\n */\n matching(change: AccessChange): Map<QuickdrawServerSocket, SubscriptionEntry[]> {\n const key = change.id === undefined ? undefined : anchorKey(change.service, change.id);\n const sockets =\n key === undefined ? this.#byService.get(change.service) : this.#byAnchor.get(key);\n const found = new Map<QuickdrawServerSocket, SubscriptionEntry[]>();\n for (const socket of sockets?.keys() ?? []) {\n if (change.userId !== undefined && socket.data.principal?.userId !== change.userId) {\n continue;\n }\n const entries = [...this.entries(socket)].filter(({ subscription }) =>\n subscription.anchors.some((anchor) =>\n key === undefined ? serviceOf(anchor) === change.service : anchor === key,\n ),\n );\n if (entries.length > 0) {\n found.set(socket, entries);\n }\n }\n return found;\n }\n}\n","// Synchronous schema checks for the realtime paths (RFC 0003 section 12.5):\n// a channel message, a pushed stream item and an emitted event are checked\n// where they happen, with no promise per message. A Standard Schema may\n// validate asynchronously (an async refinement); such a schema cannot be\n// used on these paths, and `validateNow` says so instead of awaiting it.\n\nimport type { StandardSchemaV1, ValidationIssue } from \"../../contract/standardSchema\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { toWireIssues } from \"../pipeline/validation\";\n\n/** What a synchronous check found: the parsed value, the issues, or that the schema is asynchronous. */\nexport type SyncValidation =\n | { readonly value: unknown; readonly issues?: undefined }\n | { readonly issues: readonly ValidationIssue[] }\n | \"async\";\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\n/** Validates `value` against `schema` without awaiting: `\"async\"` when the schema answers with a promise. */\nexport function validateNow(schema: StandardSchemaV1, value: unknown): SyncValidation {\n const result = schema[\"~standard\"].validate(value);\n if (isThenable(result)) {\n // Not awaited: keep a rejection from going unhandled.\n Promise.resolve(result).catch(() => undefined);\n return \"async\";\n }\n return result.issues === undefined ? { value: result.value } : { issues: result.issues };\n}\n\n/**\n * Whether a stream's items are checked: always, unless it declared\n * `validate: \"development\"` and the dispatcher does not check outputs\n * (`outputValidation`, off in production).\n */\nexport function checksItems(\n stream: { readonly validate: \"always\" | \"development\" },\n outputValidation: boolean,\n): boolean {\n return stream.validate === \"always\" || outputValidation;\n}\n\n/**\n * Checks what the server is about to send (a stream item, an event payload)\n * against its schema and returns the validated value, which is what goes\n * out: streams and events have no projections, so the schema is what keeps\n * the app's other keys off the wire (a Zod object strips them). A mismatch\n * is the app's bug, so it throws `INTERNAL` with the issues (logged, never\n * sent), and nothing is sent.\n */\nexport function checkOutgoing(schema: StandardSchemaV1, value: unknown, label: string): unknown {\n const result = validateNow(schema, value);\n if (result === \"async\") {\n throw new TypeError(\n `${label}: its schema validates asynchronously; streams and events are checked synchronously, so use a synchronous schema`,\n );\n }\n if (result.issues !== undefined) {\n throw new QuickdrawError(\"INTERNAL\", `${label} does not match its contract schema`, {\n issues: toWireIssues(result.issues),\n });\n }\n return result.value;\n}\n","// Channels (RFC 0003 section 12.5): fire-and-forget client-to-server input\n// such as cursors or typing, on one `qd:ch` listener per v5 socket. A message\n// is one array argument, `[service, channel, payload]`, sent volatile and\n// never acknowledged. Ported from 4.1's `registerChannelListener`\n// (4.1 `src/server/ServiceRegistry.ts:209-266`) and `checkChannelAccess`\n// (4.1 `src/server/BaseService.ts:956-983`).\n//\n// This is the hot path: no acknowledgement, no logging and no asynchronous\n// work per message. In order: a malformed frame or an unknown service or\n// channel is dropped; the socket's token bucket for that service and channel\n// (refilled at `ratePerSecond`, holding at most `burst`) drops a message over\n// the rate; an anonymous socket's message is dropped; the payload is checked\n// against the channel's schema, synchronously, and dropped when it fails; the\n// access check runs in memory (the service-wide grant a `{ service }` access\n// names, then the contract's `requires`: the socket must already hold the\n// entity or collection subscription the payload names, or be in the app room\n// the requirement names (or in one whose name starts with its `prefix`),\n// joined by a call over this very socket); then the handler runs with the\n// parsed payload, and the room that matched as `ctx.room`. 4.1's\n// `requireRoom` skipped its check\n// when it named no room; every form here drops the message instead. A socket\n// whose dropped messages within 10 s exceed 100 times the channel's rate is\n// disconnected: sustained flooding, not a burst. The rate limiter never\n// counts `qd:ch` (`transports/middleware.ts`).\n//\n// A handler's throw or rejection is logged and does not stop the channel:\n// at error, or at debug for a `QuickdrawError` the client caused (any code\n// but `INTERNAL` and `TIMEOUT`), as the pipeline logs calls. A schema that\n// validates asynchronously cannot be used here: its messages are dropped,\n// with one warning per channel.\n\nimport { CLIENT_EVENTS, collectionRoom } from \"../../contract/names\";\nimport { meetsLevel, serviceGrant } from \"../access/levels\";\nimport type { Hub } from \"../emit/hub\";\nimport { ownRecord } from \"../emit/subscriptions\";\nimport { describeError, failureLevel } from \"../pipeline/metrics\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport type { Principal } from \"../types\";\nimport type { Rooms } from \"./rooms\";\nimport type { ChannelContext, Presence, ServiceChannel } from \"./types\";\nimport { validateNow } from \"./validate\";\n\n/** How long the abuse guard counts a socket's messages dropped for one channel's rate before it starts over. */\nexport const CHANNEL_ABUSE_WINDOW_MS = 10_000;\n\n/** A socket is disconnected once its drops within the window exceed this many times the channel's rate. */\nexport const CHANNEL_ABUSE_MULTIPLIER = 100;\n\n/** One socket's token bucket for one channel, and its abuse window. */\ninterface Bucket {\n tokens: number;\n refilledAt: number;\n windowStart: number;\n dropped: number;\n}\n\n/** What one socket's channel messages share. */\ninterface SocketChannels {\n readonly socket: QuickdrawServerSocket;\n /** Bounded by the channels the services declare: unknown names never get one. */\n readonly buckets: Map<ServiceChannel, Bucket>;\n /** The handlers' context, made again when the socket's principal (new grants) or the matched room changes. */\n ctx: ChannelContext | undefined;\n}\n\n/** What every socket's channel messages share. */\nexport interface ChannelDeps {\n readonly hub: Hub;\n readonly rooms: Rooms;\n readonly presence: Presence;\n /** Channels already warned about for an asynchronous schema. */\n readonly warned: WeakSet<ServiceChannel>;\n}\n\n/** Takes one token, refilling first; false when the bucket is empty. */\nfunction take(bucket: Bucket, channel: ServiceChannel, now: number): boolean {\n const refill = ((now - bucket.refilledAt) / 1000) * channel.ratePerSecond;\n bucket.tokens = Math.min(channel.burst, bucket.tokens + refill);\n bucket.refilledAt = now;\n if (bucket.tokens < 1) {\n return false;\n }\n bucket.tokens -= 1;\n return true;\n}\n\n/** Counts a drop; true once the window's drops pass the abuse threshold. */\nfunction abusive(bucket: Bucket, channel: ServiceChannel, now: number): boolean {\n if (now - bucket.windowStart > CHANNEL_ABUSE_WINDOW_MS) {\n bucket.windowStart = now;\n bucket.dropped = 0;\n }\n bucket.dropped += 1;\n return bucket.dropped > channel.ratePerSecond * CHANNEL_ABUSE_MULTIPLIER;\n}\n\nfunction bucketOf(state: SocketChannels, channel: ServiceChannel, now: number): Bucket {\n let bucket = state.buckets.get(channel);\n if (bucket === undefined) {\n bucket = { tokens: channel.burst, refilledAt: now, windowStart: now, dropped: 0 };\n state.buckets.set(channel, bucket);\n }\n return bucket;\n}\n\n/** The parsed payload, or `undefined` when the message is dropped. */\nfunction parse(\n deps: ChannelDeps,\n channel: ServiceChannel,\n payload: unknown,\n): { readonly value: unknown } | undefined {\n const result = validateNow(channel.payload, payload);\n if (result === \"async\") {\n if (!deps.warned.has(channel)) {\n deps.warned.add(channel);\n deps.hub.logger.warn(\n `Channel ${channel.service}.${channel.name} has a payload schema that validates asynchronously; its messages are dropped, since channels validate synchronously`,\n { category: \"quickdraw.channel\" },\n );\n }\n return undefined;\n }\n return result.issues === undefined ? { value: result.value } : undefined;\n}\n\n/**\n * Whether the socket holds what `requires` names for `key`: the entity\n * subscription, the collection scope subscription, or the app room (one a\n * call over this socket joined with `ctx.rooms.join`). All three are the\n * socket's own records, kept on the node it is connected to, so the check\n * holds behind a cluster adapter without asking another node.\n */\nfunction holds(\n requires: NonNullable<ServiceChannel[\"requires\"]>,\n socket: QuickdrawServerSocket,\n service: string,\n key: string,\n): boolean {\n switch (requires.kind) {\n case \"entity\":\n return ownRecord(ownRecord(socket.data.entities, service), key) !== undefined;\n case \"collection\":\n return (\n ownRecord(socket.data.collections, collectionRoom(service, requires.collection, key)) !==\n undefined\n );\n default:\n return ownRecord(socket.data.appRooms, key) !== undefined;\n }\n}\n\n/**\n * The first app room the socket joined whose name starts with `prefix`\n * (the room it joined earliest, when there are several), or `undefined`.\n * `appRooms` has no prototype, so `for...in` sees its own rooms only.\n */\nfunction roomWithPrefix(socket: QuickdrawServerSocket, prefix: string): string | undefined {\n const joined = socket.data.appRooms;\n for (const room in joined) {\n if (room.startsWith(prefix)) {\n return room;\n }\n }\n return undefined;\n}\n\n/**\n * The in-memory access check: the service grant `access` names, then the\n * contract's `requires`. `false` when the message is dropped; else the app\n * room a room requirement matched, which the handler gets as `ctx.room`\n * (`undefined` for the other forms, and for a channel that requires none).\n */\nfunction allowed(\n channel: ServiceChannel,\n socket: QuickdrawServerSocket,\n principal: Principal,\n value: unknown,\n): string | undefined | false {\n const { access, requires } = channel;\n if (\n access !== \"authenticated\" &&\n !meetsLevel(serviceGrant(principal, channel.service), access.service)\n ) {\n return false;\n }\n if (requires === undefined) {\n return undefined;\n }\n if (requires.kind === \"roomPrefix\") {\n return roomWithPrefix(socket, requires.prefix) ?? false;\n }\n const key = requires.select(value);\n if (key === undefined || !holds(requires, socket, channel.service, key)) {\n return false;\n }\n return requires.kind === \"room\" ? key : undefined;\n}\n\n/** The handlers' context for the socket's principal and the room a message matched: made again only when either changes. */\nfunction contextOf(\n deps: ChannelDeps,\n state: SocketChannels,\n principal: Principal,\n room: string | undefined,\n): ChannelContext {\n if (state.ctx?.principal !== principal || state.ctx.room !== room) {\n state.ctx = Object.freeze({\n principal,\n socketId: state.socket.id,\n room,\n log: deps.hub.logger,\n rooms: deps.rooms.of(state.socket),\n presence: deps.presence,\n });\n }\n return state.ctx;\n}\n\n/** Logs a handler's failure: at debug when the client caused it, as the pipeline logs calls (RFC 0003 section 9). */\nfunction failed(\n deps: ChannelDeps,\n channel: ServiceChannel,\n ctx: ChannelContext,\n error: unknown,\n): void {\n const level = failureLevel(error);\n deps.hub.logger[level](`The handler of channel ${channel.service}.${channel.name} failed`, {\n category: \"quickdraw.channel\",\n userId: ctx.principal.userId,\n socketId: ctx.socketId,\n error: describeError(error),\n });\n}\n\nfunction run(\n deps: ChannelDeps,\n channel: ServiceChannel,\n value: unknown,\n ctx: ChannelContext,\n): void {\n try {\n const result: unknown = channel.handler(value, ctx);\n if (typeof result === \"object\" && result !== null && \"then\" in result) {\n Promise.resolve(result).catch((error: unknown) => {\n failed(deps, channel, ctx, error);\n });\n }\n } catch (error) {\n failed(deps, channel, ctx, error);\n }\n}\n\nfunction flooded(\n deps: ChannelDeps,\n state: SocketChannels,\n channel: ServiceChannel,\n bucket: Bucket,\n): void {\n deps.hub.logger.warn(\n `Disconnecting socket ${state.socket.id} for sustained flooding of channel ${channel.service}.${channel.name}`,\n {\n category: \"quickdraw.channel\",\n userId: state.socket.data.principal?.userId,\n dropped: bucket.dropped,\n },\n );\n state.socket.disconnect(true);\n}\n\n/** One `qd:ch` message, through every check to the handler. */\nfunction receive(deps: ChannelDeps, state: SocketChannels, frame: unknown): void {\n if (!Array.isArray(frame)) {\n return;\n }\n const [service, name, payload] = frame as readonly unknown[];\n const channel =\n typeof service === \"string\" && typeof name === \"string\"\n ? deps.hub.registry.services.get(service)?.channels.get(name)\n : undefined;\n if (channel === undefined) {\n return;\n }\n const now = Date.now();\n const bucket = bucketOf(state, channel, now);\n if (!take(bucket, channel, now)) {\n if (abusive(bucket, channel, now)) {\n flooded(deps, state, channel, bucket);\n }\n return;\n }\n const { principal } = state.socket.data;\n const parsed = principal === null ? undefined : parse(deps, channel, payload);\n if (principal === null || parsed === undefined) {\n return;\n }\n const room = allowed(channel, state.socket, principal, parsed.value);\n if (room !== false) {\n run(deps, channel, parsed.value, contextOf(deps, state, principal, room));\n }\n}\n\n/** The socket extension that serves `qd:ch` for one dispatcher's channels. */\nexport function channelMessages(deps: ChannelDeps): (socket: QuickdrawServerSocket) => void {\n return (socket) => {\n const state: SocketChannels = { socket, buckets: new Map(), ctx: undefined };\n socket.on(CLIENT_EVENTS.channel, (frame: unknown) => {\n try {\n receive(deps, state, frame);\n } catch (error) {\n // A schema or selector that throws must not end the process: Socket.IO runs listeners from nextTick.\n deps.hub.logger.error(\"A channel message failed\", {\n category: \"quickdraw.channel\",\n socketId: socket.id,\n error: describeError(error),\n });\n }\n });\n };\n}\n","// Waiting on the rest of a cluster, bounded (pack H's multi-node proof): a\n// command to the cluster's Valkey (the revision counter, last-seen times),\n// and a server-to-server event that is answered. A node that broadcasts an\n// access change or a user's reloaded grants waits until every other node has\n// applied it, so the flush that caused it sends its frames only once no node\n// still holds what it revoked. Socket.IO hands the listener the\n// acknowledgement as the event's last argument when the sender asked for\n// answers (`serverSideEmitWithAck`).\n\n/** How long a node waits on the rest of the cluster by default: `cluster.timeoutMs`. */\nexport const DEFAULT_CLUSTER_TIMEOUT_MS = 1000;\n\nclass Timeout extends Error {\n constructor(ms: number) {\n super(`no answer within ${ms} ms`);\n }\n}\n\n/** `promise`, or a rejection once `ms` passed. */\nexport async function within<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Timeout(ms));\n }, ms);\n timer.unref?.();\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** The acknowledgement a server-to-server event came with (its last argument), or one that does nothing. */\nexport function answerOf(rest: readonly unknown[]): (done: boolean) => void {\n const last = rest.at(-1);\n return typeof last === \"function\" ? (last as (done: boolean) => void) : () => undefined;\n}\n","// Users' last-seen times across a cluster (RFC 0003 section 12.5, and the gap\n// section 17 recorded for pack E): `presence.lastSeen(userId)` is now while\n// any node holds a socket of the user, else the last time a node saw the\n// user's last socket there disconnect. Each process keeps its own (bounded,\n// `PresenceRecords`); behind a cluster's Valkey a node also writes it to\n// `{keyPrefix}:seen:{userId}`, kept for `LAST_SEEN_TTL_MS` and never moved\n// back, and an answer takes the later of the two. When Valkey does not\n// answer, a node answers from its own records.\n\nimport type { Hub } from \"../emit/hub\";\nimport { DEFAULT_CLUSTER_TIMEOUT_MS, within } from \"./acks\";\n\n/** How long a user's last-seen time is kept in the cluster's Valkey: 30 days. */\nexport const LAST_SEEN_TTL_MS = 30 * 24 * 60 * 60 * 1000;\n\n/** Writes the time unless a later one is there; keeps it `ARGV[2]` ms. */\nconst LAST_SEEN_SCRIPT = [\n \"local kept = tonumber(redis.call('GET', KEYS[1]) or '0')\",\n \"if tonumber(ARGV[1]) > kept then\",\n \" redis.call('SET', KEYS[1], ARGV[1], 'PX', ARGV[2])\",\n \"end\",\n \"return 1\",\n].join(\"\\n\");\n\nfunction keyOf(prefix: string, userId: string): string {\n return `${prefix}:seen:${userId}`;\n}\n\n/** Records in the cluster's Valkey that `userId`'s last socket on this node disconnected `at`. */\nexport function recordLastSeen(hub: Hub, userId: string, at: number): void {\n const target = hub.revisions.counterClient();\n if (target === undefined || target.client.isReady === false) {\n return;\n }\n const key = keyOf(target.keyPrefix, userId);\n const args = [\"EVAL\", LAST_SEEN_SCRIPT, \"1\", key, String(at), String(LAST_SEEN_TTL_MS)];\n target.client.sendCommand(args).catch((error: unknown) => {\n hub.logger.debug(\"Recording a user's last-seen time in the cluster failed\", {\n category: \"quickdraw.presence\",\n userId,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n}\n\n/** The last time any node of the cluster saw `userId` leave, or `undefined` (one server, none kept, no answer). */\nexport async function readLastSeen(hub: Hub, userId: string): Promise<number | undefined> {\n const target = hub.revisions.counterClient();\n if (target === undefined || target.client.isReady === false) {\n return undefined;\n }\n const timeoutMs = hub.cluster?.timeoutMs ?? DEFAULT_CLUSTER_TIMEOUT_MS;\n try {\n const reply = await within(\n target.client.sendCommand([\"GET\", keyOf(target.keyPrefix, userId)]),\n timeoutMs,\n );\n const value = typeof reply === \"string\" ? Number(reply) : Number.NaN;\n return Number.isSafeInteger(value) ? value : undefined;\n } catch {\n return undefined;\n }\n}\n","// Presence (RFC 0003 section 12.5): who is online, when they were last seen,\n// and who is in a room. 4.1 apps read `io.sockets` themselves for this.\n//\n// This process keeps, for every app room a method joined with\n// `ctx.rooms.join`, how many sockets of each user are in it (so a join and a\n// leave know at once whether they change who is there), and the time each\n// user's last socket disconnected. Both are bounded: a socket is in at most\n// `MAX_APP_ROOMS` app rooms, and the last-seen times are kept for the\n// `PRESENCE_MAX_LAST_SEEN` users seen last. Both live in `Map`s, so a user id\n// or room named `__proto__` is an ordinary key.\n//\n// `count` and `users` answer for app rooms only: a framework room (`qd:`,\n// `user:`) is `VALIDATION`, as for `ctx.rooms.join`.\n//\n// The answers come from this process's rooms while the server runs the\n// in-memory adapter it was created with. Behind a cluster adapter (Redis)\n// other nodes' sockets are not visible here, so `isOnline`, `count` and\n// `users` ask every node through `io.in(room).fetchSockets()`, and\n// `lastSeen` also reads the last disconnect any node recorded in the\n// cluster's Valkey (`../cluster/lastSeen.ts`).\n\nimport { RESERVED_ROOM_PREFIXES, userRoom } from \"../../contract/names\";\nimport { readLastSeen, recordLastSeen } from \"../cluster/lastSeen\";\nimport type { Hub } from \"../emit/hub\";\nimport { unreadable } from \"../transports/ack\";\nimport type { QuickdrawIo } from \"../transports/types\";\nimport type { Presence } from \"./types\";\n\n/** How many users' last-seen times one process keeps; the least recently seen go first. */\nexport const PRESENCE_MAX_LAST_SEEN = 100_000;\n\n/** The most app rooms (`ctx.rooms.join`) one socket may be in at once. */\nexport const MAX_APP_ROOMS = 100;\n\n/** This process's app-room occupancy by user, and its users' last-seen times. */\nexport class PresenceRecords {\n /** Per app room, how many sockets of each user are in it. */\n readonly #rooms = new Map<string, Map<string, number>>();\n /** When each user's last socket disconnected, oldest first. */\n readonly #lastSeen = new Map<string, number>();\n\n /** A socket of `userId` entered `room`; true when it is the user's first socket there. */\n entered(room: string, userId: string): boolean {\n const users = this.#rooms.get(room) ?? new Map<string, number>();\n this.#rooms.set(room, users);\n const sockets = (users.get(userId) ?? 0) + 1;\n users.set(userId, sockets);\n return sockets === 1;\n }\n\n /** A socket of `userId` left `room`; true when it was the user's last socket there. */\n exited(room: string, userId: string): boolean {\n const users = this.#rooms.get(room);\n const sockets = users?.get(userId);\n if (users === undefined || sockets === undefined) {\n return false;\n }\n if (sockets > 1) {\n users.set(userId, sockets - 1);\n return false;\n }\n users.delete(userId);\n if (users.size === 0) {\n this.#rooms.delete(room);\n }\n return true;\n }\n\n /** The users with a socket of this process in app room `room`, or `undefined` for a room no user joined here. */\n users(room: string): string[] | undefined {\n const users = this.#rooms.get(room);\n return users === undefined ? undefined : [...users.keys()];\n }\n\n /** The user's last socket disconnected at `at`. */\n seen(userId: string, at: number): void {\n this.#lastSeen.delete(userId);\n this.#lastSeen.set(userId, at);\n if (this.#lastSeen.size > PRESENCE_MAX_LAST_SEEN) {\n const oldest = this.#lastSeen.keys().next();\n if (oldest.done !== true) {\n this.#lastSeen.delete(oldest.value);\n }\n }\n }\n\n /** When the user's last socket here disconnected, or `undefined`. */\n lastSeen(userId: string): number | undefined {\n return this.#lastSeen.get(userId);\n }\n}\n\n/**\n * The user's last socket on this process disconnected at `at`: kept here,\n * and behind a cluster's Valkey for every node (`../cluster/lastSeen.ts`).\n */\nexport function markSeen(hub: Hub, records: PresenceRecords, userId: string, at: number): void {\n records.seen(userId, at);\n recordLastSeen(hub, userId, at);\n}\n\n/** The distinct user ids of these principals, in order; anonymous sockets have none. */\nfunction distinctUsers(\n principals: Iterable<{ readonly userId?: unknown } | null | undefined>,\n): string[] {\n const users = new Set<string>();\n for (const principal of principals) {\n const userId = principal?.userId;\n if (typeof userId === \"string\" && userId !== \"\") {\n users.add(userId);\n }\n }\n return [...users];\n}\n\n/** The users of this process's sockets in `room`, read from the app-room records or the adapter's rooms. */\nfunction localUsers(io: QuickdrawIo, records: PresenceRecords, room: string): string[] {\n const tracked = records.users(room);\n if (tracked !== undefined) {\n return tracked;\n }\n const socketIds = io.sockets.adapter.rooms.get(room) ?? [];\n return distinctUsers(\n [...socketIds].map((socketId) => io.sockets.sockets.get(socketId)?.data.principal),\n );\n}\n\n/**\n * The users with a socket in `room` on any node: through every node's sockets\n * behind a cluster adapter. This node's own are read once the other nodes\n * answered, not when they were asked: a socket that joined here meanwhile\n * sent its `joined` to the room already, and a list that left it out would\n * undo it.\n */\nexport async function usersInRoom(\n hub: Hub,\n records: PresenceRecords,\n room: string,\n): Promise<string[]> {\n const { io } = hub;\n if (io === undefined) {\n return [];\n }\n if (hub.probe.local()) {\n return localUsers(io, records, room);\n }\n const sockets = await io.in(room).fetchSockets();\n const remote = sockets.filter((socket) => !io.sockets.sockets.has(socket.id));\n return distinctUsers([\n ...remote.map((socket) => socket.data.principal),\n ...localUsers(io, records, room).map((userId) => ({ userId })),\n ]);\n}\n\n/** True while some socket of `userId` is in `room`, on any node. */\nexport async function inRoom(\n hub: Hub,\n records: PresenceRecords,\n room: string,\n userId: string,\n): Promise<boolean> {\n return (await usersInRoom(hub, records, room)).includes(userId);\n}\n\nfunction checkName(member: string, value: unknown): asserts value is string {\n if (typeof value !== \"string\" || value === \"\") {\n throw new TypeError(`presence.${member}: pass a non-empty string`);\n }\n}\n\n/**\n * Throws `VALIDATION` for a framework room (`qd:` entity, collection, topic\n * and stream rooms, `user:` rooms), as `ctx.rooms.join` does: who sits in\n * one would tell who is subscribed to a row, or which sockets a user has.\n * Presence answers for app rooms only.\n */\nfunction checkRoom(member: string, room: unknown): asserts room is string {\n checkName(member, room);\n if (RESERVED_ROOM_PREFIXES.some((prefix) => room.startsWith(prefix))) {\n throw unreadable(\n `presence.${member}: room \"${room}\" is reserved; presence answers for app rooms, not for rooms starting with ${RESERVED_ROOM_PREFIXES.join(\" or \")}`,\n );\n }\n}\n\n/** The presence API of one dispatcher, answered from its server's sockets (none before a server attaches). */\nexport function createPresence(hub: Hub, records: PresenceRecords): Presence {\n const isOnline = async (userId: string): Promise<boolean> => {\n checkName(\"isOnline\", userId);\n const { io } = hub;\n if (io === undefined) {\n return false;\n }\n if (hub.probe.local()) {\n return (io.sockets.adapter.rooms.get(userRoom(userId))?.size ?? 0) > 0;\n }\n return (await io.in(userRoom(userId)).fetchSockets()).length > 0;\n };\n const users = async (room: string): Promise<string[]> => {\n checkRoom(\"users\", room);\n return await usersInRoom(hub, records, room);\n };\n return Object.freeze({\n isOnline,\n async lastSeen(userId: string): Promise<number | null> {\n checkName(\"lastSeen\", userId);\n if (await isOnline(userId)) {\n return Date.now();\n }\n const seen = Math.max(records.lastSeen(userId) ?? 0, (await readLastSeen(hub, userId)) ?? 0);\n return seen > 0 ? seen : null;\n },\n async count(room: string): Promise<number> {\n checkRoom(\"count\", room);\n return (await usersInRoom(hub, records, room)).length;\n },\n users,\n });\n}\n","// The seeds of streams (RFC 0003 section 12.5): the latest `seed` items of\n// each scope of each stream, kept in memory on this process so a new\n// subscriber starts with recent history. A restart empties them, and each\n// node of a cluster keeps its own from the pushes it received since it\n// started (every node receives every push of a stream that keeps a seed:\n// `streams.ts`), so a node that started after the pushes has none of them.\n// A stream whose service computes its seed (`streams: { <name>: { seed } }`)\n// keeps nothing here: each subscribe asks the app for the current state, on\n// whichever node it arrives. Durable history is the app's: store the rows\n// and expose a collection.\n//\n// Bounded twice: a scope keeps at most its stream's `seed` items (at most\n// 1,000), and a stream keeps at most `STREAM_MAX_SCOPES` scopes, dropping the\n// one pushed to least recently. Scopes are `Map` keys, so a scope named\n// `__proto__` is an ordinary one.\n\nimport type { ServiceStream, StreamSeedContext } from \"./types\";\nimport { checkOutgoing, checksItems } from \"./validate\";\n\n/** The most scopes one stream keeps a seed for; the scope pushed to least recently goes first. */\nexport const STREAM_MAX_SCOPES = 10_000;\n\n/**\n * The seed `stream`'s service computes for one subscriber (`streams: {\n * <name>: { seed } }`), each item checked against the stream's schema, and\n * the checked items are what is sent, as `push` sends (unchecked as `push`\n * leaves them, for a stream that validates in development only). The function is\n * called before this awaits anything: in the caller's tick, the one it\n * joined the socket to the feed in. A function that returns something other\n * than an array, or an item that does not fit, throws for `INTERNAL`.\n */\nexport async function computeSeed(\n service: string,\n stream: ServiceStream,\n scope: string | undefined,\n ctx: StreamSeedContext,\n outputValidation: boolean,\n): Promise<unknown[]> {\n const compute = stream.computeSeed;\n const items: unknown = await compute?.(scope, ctx);\n const label = `The seed of ${service}.${stream.name}`;\n if (!Array.isArray(items)) {\n throw new TypeError(`${label}: its seed function must return an array of items`);\n }\n if (!checksItems(stream, outputValidation)) {\n return items as unknown[];\n }\n return items.map((item: unknown, index) =>\n checkOutgoing(stream.item, item, `Item ${String(index)} of ${label}`),\n );\n}\n\n/** The key of a global stream's one feed among a stream's scopes. */\nconst GLOBAL_FEED = \"\";\n\n/** The key of one stream among a dispatcher's streams. */\nexport function streamKey(service: string, stream: string): string {\n return `${service}\\u0000${stream}`;\n}\n\n/** The seeds of one dispatcher's streams. */\nexport class StreamSeeds {\n /** Per stream (`service\\0stream`), each scope's latest items, the scope pushed to last at the end. */\n readonly #streams = new Map<string, Map<string, unknown[]>>();\n\n /** Keeps `item` as the newest of a scope's seed of at most `size` items. */\n push(stream: string, scope: string | undefined, item: unknown, size: number): void {\n if (size <= 0) {\n return;\n }\n const scopes = this.#streams.get(stream) ?? new Map<string, unknown[]>();\n this.#streams.set(stream, scopes);\n const key = scope ?? GLOBAL_FEED;\n const items = scopes.get(key) ?? [];\n // Moved to the end: the scope pushed to last.\n scopes.delete(key);\n scopes.set(key, items);\n items.push(item);\n if (items.length > size) {\n items.splice(0, items.length - size);\n }\n if (scopes.size > STREAM_MAX_SCOPES) {\n const oldest = scopes.keys().next();\n if (oldest.done !== true) {\n scopes.delete(oldest.value);\n }\n }\n }\n\n /** A scope's seed, oldest first: a copy. */\n seed(stream: string, scope: string | undefined): unknown[] {\n return [...(this.#streams.get(stream)?.get(scope ?? GLOBAL_FEED) ?? [])];\n }\n\n /** How many scopes of a stream have a seed. */\n scopes(stream: string): number {\n return this.#streams.get(stream)?.size ?? 0;\n }\n}\n","// Per-connection query concurrency (RFC 0003 section 9, step 2): at most\n// `maxInFlight` queries of one connection run at once, up to `maxQueued`\n// more wait in order, and past that a query fails with `RATE_LIMITED`.\n// Mutations never come here, so they are never queued behind queries. 4.1\n// had no cap: every event ran as soon as it arrived.\n\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { cancelledError } from \"./errors\";\n\n/** The limits of {@link createConcurrencyLimiter}. */\nexport interface ConcurrencyLimits {\n /** Queries of one connection that may run at once. */\n readonly maxInFlight: number;\n /** Queries of one connection that may wait for a slot. */\n readonly maxQueued: number;\n /** The `retryAfterMs` sent with `RATE_LIMITED` when the queue is full. */\n readonly retryAfterMs: number;\n /** What a lane runs, for the `RATE_LIMITED` message. Default `\"queries\"`. */\n readonly work?: string;\n}\n\n/** A held query slot. */\nexport interface QuerySlot {\n /** How long the query waited in the queue, in milliseconds. */\n readonly queueMs: number;\n /** Frees the slot for the next queued query. Calling it again does nothing. */\n release(): void;\n}\n\n/** Hands out query slots per connection. */\nexport interface ConcurrencyLimiter {\n /**\n * Resolves with a slot of `connectionId`'s lane once one is free. Rejects\n * with `RATE_LIMITED` when the lane's queue is full, and with `CANCELLED`\n * when `signal` aborts first.\n */\n acquire(connectionId: string, signal?: AbortSignal): Promise<QuerySlot>;\n /** Connections that have queries running or queued. */\n readonly connections: number;\n}\n\ninterface Waiter {\n readonly grant: () => void;\n}\n\ninterface Lane {\n running: number;\n readonly queue: Waiter[];\n}\n\nexport function createConcurrencyLimiter(limits: ConcurrencyLimits): ConcurrencyLimiter {\n const lanes = new Map<string, Lane>();\n\n function dropIfIdle(connectionId: string, lane: Lane): void {\n if (lane.running === 0 && lane.queue.length === 0) {\n lanes.delete(connectionId);\n }\n }\n\n function slot(connectionId: string, lane: Lane, queueMs: number): QuerySlot {\n let released = false;\n return {\n queueMs,\n release() {\n if (released) {\n return;\n }\n released = true;\n lane.running -= 1;\n const next = lane.queue.shift();\n if (next === undefined) {\n dropIfIdle(connectionId, lane);\n return;\n }\n lane.running += 1;\n next.grant();\n },\n };\n }\n\n function enqueue(connectionId: string, lane: Lane, signal?: AbortSignal): Promise<QuerySlot> {\n return new Promise((resolve, reject) => {\n const enqueuedAt = performance.now();\n const waiter: Waiter = { grant };\n function grant(): void {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(slot(connectionId, lane, performance.now() - enqueuedAt));\n }\n function onAbort(): void {\n const index = lane.queue.indexOf(waiter);\n if (index >= 0) {\n lane.queue.splice(index, 1);\n }\n dropIfIdle(connectionId, lane);\n reject(cancelledError());\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n lane.queue.push(waiter);\n });\n }\n\n return {\n acquire(connectionId, signal) {\n if (signal?.aborted === true) {\n return Promise.reject(cancelledError());\n }\n let lane = lanes.get(connectionId);\n if (lane === undefined) {\n lane = { running: 0, queue: [] };\n lanes.set(connectionId, lane);\n }\n if (lane.running < limits.maxInFlight) {\n lane.running += 1;\n return Promise.resolve(slot(connectionId, lane, 0));\n }\n if (lane.queue.length >= limits.maxQueued) {\n const message = `Too many ${limits.work ?? \"queries\"} in flight on this connection`;\n return Promise.reject(\n new QuickdrawError(\"RATE_LIMITED\", message, { retryAfterMs: limits.retryAfterMs }),\n );\n }\n return enqueue(connectionId, lane, signal);\n },\n get connections() {\n return lanes.size;\n },\n };\n}\n","// Each socket's lane of subscription events (RFC 0003 sections 6, 7 and 9):\n// `qd:sub`, `qd:col:sub`, `qd:col:items` and `qd:watch` read the database,\n// and the socket rate limiter does not count them (a page mounts many at\n// once, `transports/middleware.ts`). Without a cap, one socket could start\n// any number of 500-id batches together. They run through the concurrency\n// stage's limiter instead (`pipeline/concurrency.ts`), one lane per socket\n// shared by the four events: `limits.subscriptions.maxInFlight` (8) at once,\n// `maxQueued` (64) waiting in order, then `RATE_LIMITED`. A socket's queued\n// work is dropped when it disconnects; work already running finishes, and\n// frees its slot.\n\nimport { createConcurrencyLimiter } from \"../pipeline/concurrency\";\nimport type { QuickdrawServerSocket, SocketContext } from \"../transports/types\";\n\n/** Runs one subscription event's work in its socket's lane; rejects `RATE_LIMITED` when the lane is full. */\nexport type Lane = <T>(work: () => Promise<T>) => Promise<T>;\n\nconst LANES = new WeakMap<QuickdrawServerSocket, Lane>();\n\n/** The socket's lane, made on first use with the dispatcher's `limits.subscriptions`. */\nexport function laneOf(\n socket: QuickdrawServerSocket,\n context: Pick<SocketContext, \"dispatcher\">,\n): Lane {\n const existing = LANES.get(socket);\n if (existing !== undefined) {\n return existing;\n }\n const { subscriptions, retryAfterMs } = context.dispatcher.limits;\n const limiter = createConcurrencyLimiter({\n maxInFlight: subscriptions.maxInFlight,\n maxQueued: subscriptions.maxQueued,\n retryAfterMs,\n work: \"subscription requests\",\n });\n const closed = new AbortController();\n socket.on(\"disconnect\", () => {\n closed.abort();\n });\n const lane: Lane = async (work) => {\n const slot = await limiter.acquire(socket.id, closed.signal);\n try {\n return await work();\n } finally {\n slot.release();\n }\n };\n LANES.set(socket, lane);\n return lane;\n}\n","// How the live data's socket listeners answer (RFC 0003 section 8.2): the\n// entity, collection and topic events share these, so none of them throws.\n// Socket.IO runs listeners from `process.nextTick`, where an exception ends\n// the process: whatever a frame makes go wrong is logged and answered\n// `INTERNAL` instead. The events that read the database (`qd:sub`,\n// `qd:col:sub`, `qd:col:items`, `qd:watch`) run in the socket's lane of\n// subscription work (`lane.ts`).\n\nimport type { Failure } from \"../../protocol/envelope\";\nimport { toWire } from \"../../protocol/errors\";\nimport { toQuickdrawError } from \"../pipeline/errors\";\nimport { describeError } from \"../pipeline/metrics\";\nimport { acknowledge, INTERNAL_FAILURE, type Acknowledge } from \"../transports/ack\";\nimport type { QuickdrawServerSocket, SocketContext } from \"../transports/types\";\nimport { laneOf } from \"./lane\";\n\n/** Acknowledges a subscription event, when the client asked for an acknowledgement. Never throws. */\nexport function reply(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n ack: unknown,\n message: unknown,\n): void {\n if (typeof ack !== \"function\") {\n return;\n }\n acknowledge(context.meter, ack as Acknowledge, message, INTERNAL_FAILURE, (error) => {\n context.logger.error(\n \"A subscription reply could not be encoded; it was answered with INTERNAL\",\n {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n error: describeError(error),\n },\n );\n });\n}\n\n/** The failure a frame's handler answers with for what it threw; an `INTERNAL` one is logged. */\nexport function failureOf(\n context: Pick<SocketContext, \"logger\">,\n socket: QuickdrawServerSocket,\n event: string,\n error: unknown,\n): Failure {\n const failure = toQuickdrawError(error);\n if (failure.code === \"INTERNAL\") {\n context.logger.error(`A ${event} failed`, {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n error: describeError(failure.cause ?? failure),\n });\n }\n return { ok: false, e: toWire(failure) };\n}\n\n/**\n * Answers a frame whose handler is synchronous with what `work` returns, or\n * with the failure what it threw maps to (`INTERNAL`, logged, for anything\n * but a `QuickdrawError`). Never throws.\n */\nexport function answerNow(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n event: string,\n ack: unknown,\n work: () => unknown,\n): void {\n let answer: unknown;\n try {\n answer = work();\n } catch (error) {\n answer = failureOf(context, socket, event, error);\n }\n reply(socket, context, ack, answer);\n}\n\n/**\n * Answers a frame whose handler is asynchronous with what `work` resolves\n * with, or with the failure its rejection maps to. Never throws, and the\n * promise it starts never rejects.\n */\nexport function answerLater(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n event: string,\n ack: unknown,\n work: () => Promise<unknown>,\n): void {\n const settled = (async () => {\n try {\n return await work();\n } catch (error) {\n return failureOf(context, socket, event, error);\n }\n })();\n void settled.then((answer) => {\n reply(socket, context, ack, answer);\n });\n}\n\n/** Runs `cleanup` when the socket disconnects; what it throws is logged, never thrown. */\nexport function onDisconnect(\n socket: QuickdrawServerSocket,\n context: Pick<SocketContext, \"logger\">,\n cleanup: () => void,\n): void {\n socket.on(\"disconnect\", () => {\n try {\n cleanup();\n } catch (error) {\n context.logger.error(\"Cleaning up a disconnected socket's live data failed\", {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n error: describeError(error),\n });\n }\n });\n}\n\n/**\n * Registers a listener for a subscription event a client sends with an\n * acknowledgement, answered by `work` run in the socket's lane\n * (`answerLater`): `RATE_LIMITED` when the lane is full. An event sent\n * without an acknowledgement is ignored.\n */\nexport function answerEvent(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n event: string,\n work: (frame: unknown) => Promise<unknown>,\n): void {\n const lane = laneOf(socket, context);\n socket.on(event, (frame: unknown, ack: unknown) => {\n if (typeof ack !== \"function\") {\n context.logger.debug(`Ignored a ${event} sent without an acknowledgement`, {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n });\n return;\n }\n answerLater(socket, context, event, ack, () => lane(() => work(frame)));\n });\n}\n","// The stream feeds this process's sockets subscribe to (RFC 0003 sections\n// 4.4 and 12.5), beside the collection scopes of `collections/scopes.ts`. Each\n// socket keeps its own on `socket.data.streams`, by room: the feed, and the\n// rows its access is derived from (its anchors). The index finds the\n// subscriptions an access change can concern by anchor, so revocation\n// (`streamRevocation.ts`) authorizes only those again. Rooms stay the source\n// of truth for who receives `qd:stream` frames.\n\nimport { streamRoom } from \"../../contract/names\";\nimport type { AccessChange } from \"../access/changes\";\nimport { anchorKey } from \"../access/tools\";\nimport { count, emptyRecords, ownRecord, serviceOf, type Counts } from \"../emit/subscriptions\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport type { StreamSubscription } from \"./types\";\n\n/** The room of a stream subscription. */\nexport function streamRoomOf(subscription: StreamSubscription): string {\n return streamRoom(subscription.s, subscription.stream, subscription.scope);\n}\n\n/** The record of a subscription to `target`'s feed, with the rows its access is derived from. */\nexport function subscriptionOf(\n target: {\n readonly service: { readonly name: string };\n readonly stream: { readonly name: string };\n readonly scope: string | undefined;\n },\n anchors: readonly string[],\n): StreamSubscription {\n const { service, stream, scope } = target;\n return scope === undefined\n ? { s: service.name, stream: stream.name, anchors }\n : { s: service.name, stream: stream.name, scope, anchors };\n}\n\n/** This process's stream subscriptions, indexed by anchor. */\nexport class StreamIndex {\n readonly #byAnchor = new Map<string, Counts>();\n readonly #byService = new Map<string, Counts>();\n\n #index(socket: QuickdrawServerSocket, subscription: StreamSubscription, by: 1 | -1): void {\n for (const anchor of subscription.anchors) {\n count(this.#byAnchor, anchor, socket, by);\n count(this.#byService, serviceOf(anchor), socket, by);\n }\n }\n\n /** The socket's subscription to a feed, by room, or `undefined`. */\n get(socket: QuickdrawServerSocket, room: string): StreamSubscription | undefined {\n return ownRecord(socket.data.streams, room);\n }\n\n /** Every stream subscription of the socket. */\n entries(socket: QuickdrawServerSocket): StreamSubscription[] {\n return Object.values(socket.data.streams ?? {});\n }\n\n /** How many feeds the socket subscribes to. */\n size(socket: QuickdrawServerSocket): number {\n return Object.keys(socket.data.streams ?? {}).length;\n }\n\n /** Records a subscription and puts the socket in the feed's room, replacing any earlier one. */\n set(socket: QuickdrawServerSocket, subscription: StreamSubscription): void {\n const room = streamRoomOf(subscription);\n const previous = this.get(socket, room);\n socket.data.streams ??= emptyRecords();\n socket.data.streams[room] = subscription;\n this.#index(socket, subscription, 1);\n if (previous !== undefined) {\n this.#index(socket, previous, -1);\n }\n void socket.join(room);\n }\n\n /** Ends a subscription: the socket leaves the feed's room. Returns what it was. */\n delete(socket: QuickdrawServerSocket, room: string): StreamSubscription | undefined {\n const previous = this.get(socket, room);\n if (previous !== undefined && socket.data.streams !== undefined) {\n delete socket.data.streams[room];\n this.#index(socket, previous, -1);\n }\n void socket.leave(room);\n return previous;\n }\n\n /** A socket disconnected: Socket.IO has emptied its rooms; drop it from the index. */\n drop(socket: QuickdrawServerSocket): void {\n for (const subscription of this.entries(socket)) {\n this.#index(socket, subscription, -1);\n }\n socket.data.streams = emptyRecords();\n }\n\n /**\n * The subscriptions an access change can concern: those anchored on the\n * changed row (any row of the service when `id` is absent), of the changed\n * user's sockets (every user's when `userId` is absent).\n */\n matching(change: AccessChange): Map<QuickdrawServerSocket, StreamSubscription[]> {\n const key = change.id === undefined ? undefined : anchorKey(change.service, change.id);\n const sockets =\n key === undefined ? this.#byService.get(change.service) : this.#byAnchor.get(key);\n const found = new Map<QuickdrawServerSocket, StreamSubscription[]>();\n for (const socket of sockets?.keys() ?? []) {\n if (change.userId !== undefined && socket.data.principal?.userId !== change.userId) {\n continue;\n }\n const entries = this.entries(socket).filter(({ anchors }) =>\n anchors.some((anchor) =>\n key === undefined ? serviceOf(anchor) === change.service : anchor === key,\n ),\n );\n if (entries.length > 0) {\n found.set(socket, entries);\n }\n }\n return found;\n }\n}\n","// Which stream feed a `qd:stream:sub` or `qd:stream:unsub` frame names, and\n// whether the socket may subscribe to it (RFC 0003 sections 8.2 and 12.5).\n//\n// A frame is `{ s, stream, scope? }`: `VALIDATION` when it is malformed or\n// its scope does not fit the stream (a scoped stream needs a scope of 1 to\n// 256 characters, a global stream takes none), `NOT_FOUND` for an unknown\n// service or stream. A subscriber is authorized with the stream's access\n// form through the dispatcher's access engine, as a method call with input\n// `{ scope }` would be: the scope is the row an `entry` or `scope` form\n// checks. `access: { room }` asks no engine: the subscribing socket must be\n// in that app room (a method joined it), signed in or not. A stream whose\n// contract declares no access is closed: `FORBIDDEN` for everyone.\n\nimport { streamRoom } from \"../../contract/names\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { MAX_SCOPE_LENGTH } from \"../../protocol/version\";\nimport { anchorKey } from \"../access/tools\";\nimport { createContext, NEVER_ABORTED } from \"../context\";\nimport type { Hub } from \"../emit/hub\";\nimport type { AnyService } from \"../service\";\nimport { unreadable } from \"../transports/ack\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport type { ServiceStream, StreamRoomAccess } from \"./types\";\n\n/** One feed of a served stream: one scope of a scoped stream, or a global stream. */\nexport interface StreamTarget {\n readonly service: AnyService;\n readonly stream: ServiceStream;\n /** The scope of a scoped stream; `undefined` for a global stream. */\n readonly scope: string | undefined;\n /** The feed's room: `streamRoom(service, stream, scope)`. */\n readonly room: string;\n}\n\nfunction isName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\n/** Why `scope` cannot name a feed of `stream`, or `undefined` when it can. */\nexport function scopeProblem(stream: ServiceStream, scope: unknown): string | undefined {\n if (!stream.scoped) {\n return scope === undefined ? undefined : `${stream.name} is a global stream: it takes no scope`;\n }\n return isName(scope) && scope.length <= MAX_SCOPE_LENGTH\n ? undefined\n : `${stream.name} is scoped: its scope is a string of 1 to ${MAX_SCOPE_LENGTH} characters`;\n}\n\n/**\n * The feed a `qd:stream:sub` or `qd:stream:unsub` frame names. Throws\n * `VALIDATION` for a malformed frame or a scope that does not fit, and\n * `NOT_FOUND` for an unknown service or stream (also one named `__proto__`:\n * services and streams are `Map`s).\n */\nexport function streamTarget(hub: Hub, value: unknown, event: string): StreamTarget {\n const frame =\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Readonly<Record<string, unknown>>)\n : {};\n if (!isName(frame.s) || !isName(frame.stream)) {\n throw unreadable(\n `A ${event} frame needs { s, stream, scope? } with s and stream non-empty strings`,\n );\n }\n const service = hub.registry.services.get(frame.s);\n if (service === undefined) {\n throw new QuickdrawError(\"NOT_FOUND\", `Unknown service \"${frame.s}\"`);\n }\n const stream = service.streams.get(frame.stream);\n if (stream === undefined) {\n throw new QuickdrawError(\"NOT_FOUND\", `${frame.s} has no stream \"${frame.stream}\"`);\n }\n const problem = scopeProblem(stream, frame.scope);\n if (problem !== undefined) {\n throw unreadable(problem, [\"scope\"]);\n }\n const scope = frame.scope as string | undefined;\n return { service, stream, scope, room: streamRoom(service.name, stream.name, scope) };\n}\n\n/**\n * Whether `socket` is in the app room a stream's `access: { room }` names for\n * `scope`: one its own calls joined (`socket.data.appRooms`, which has no\n * prototype), the named one, any with the prefix, or the one computed from\n * the scope.\n */\nexport function inStreamRoom(\n socket: QuickdrawServerSocket,\n access: StreamRoomAccess,\n scope: string | undefined,\n): boolean {\n const joined = socket.data.appRooms;\n if (access.kind === \"prefix\") {\n for (const room in joined) {\n if (room.startsWith(access.prefix)) {\n return true;\n }\n }\n return false;\n }\n const room = access.kind === \"name\" ? access.room : access.select(scope);\n return room !== undefined && joined !== undefined && Object.hasOwn(joined, room);\n}\n\n/**\n * Authorizes a subscriber of `target`: rejects with `FORBIDDEN` for a closed\n * stream, or for a socket outside the app room `access: { room }` names, and\n * otherwise as the access engine decides the stream's form\n * (`UNAUTHENTICATED` for an anonymous socket unless the form is `\"public\"`).\n */\nexport async function authorizeStream(\n hub: Hub,\n socket: QuickdrawServerSocket,\n target: StreamTarget,\n): Promise<void> {\n const { room } = target.stream;\n if (room !== undefined) {\n if (!inStreamRoom(socket, room, target.scope)) {\n throw new QuickdrawError(\n \"FORBIDDEN\",\n `${target.service.name}.${target.stream.name} is open to the sockets in its app room: join the room first`,\n );\n }\n return;\n }\n const form = target.stream.access;\n if (form === undefined) {\n throw new QuickdrawError(\n \"FORBIDDEN\",\n `${target.service.name}.${target.stream.name} is closed: its contract declares no access`,\n );\n }\n const { principal } = socket.data;\n const ctx = createContext({\n principal,\n signal: NEVER_ABORTED,\n log: hub.logger,\n requestId: crypto.randomUUID(),\n transport: \"socket\",\n });\n const input = { scope: target.scope };\n await hub.access.authorize(form, {\n service: target.service,\n method: target.stream.name,\n principal,\n input,\n ctx,\n });\n}\n\n/**\n * The rows a subscriber's access to `target` is derived from (its anchors,\n * `anchorKey`s), for revocation: under an `entry` form, the feed's row of\n * the stream's service and its `inherit` parents; under a `scope` form, the\n * row of `of` the scope names and its parents. None for `\"public\"`,\n * `\"authenticated\"` or `{ service }`, which no row decides (a changed grant\n * authorizes every feed of the user again). Call it once the subscriber is\n * authorized; a lookup that fails rejects.\n */\nexport async function streamAnchors(\n hub: Hub,\n socket: QuickdrawServerSocket,\n target: StreamTarget,\n): Promise<readonly string[]> {\n const form = target.stream.access;\n const { principal } = socket.data;\n const { scope } = target;\n if (principal === null || scope === undefined || typeof form !== \"object\" || \"kind\" in form) {\n return [];\n }\n if (form.entry !== undefined && target.service.access !== undefined) {\n const resolved = await hub.policies.resolve(target.service.name, principal, [scope]);\n return resolved.anchors.get(scope) ?? [anchorKey(target.service.name, scope)];\n }\n if (form.scope !== undefined) {\n const resolved = await hub.policies.resolve(form.of.name, principal, [scope], {\n grants: false,\n });\n return resolved.anchors.get(scope) ?? [anchorKey(form.of.name, scope)];\n }\n return [];\n}\n\n/** An unsubscribe needs a principal, unless the stream is public or open to an app room's sockets. */\nexport function checkUnsubscriber(socket: QuickdrawServerSocket, target: StreamTarget): void {\n const { access, room } = target.stream;\n if (socket.data.principal === null && access !== \"public\" && room === undefined) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n}\n","// The socket listeners of stream subscriptions (RFC 0003 sections 8.2 and\n// 12.5): `qd:stream:sub { s, stream, scope? }`, answered `{ ok: true, seed }`\n// or `{ ok: false, e }`, and `qd:stream:unsub`, optionally acknowledged\n// `{ ok: true }`. One listener per event on every v5 socket, routed by the\n// frame. Neither counts against the socket rate limiter\n// (`transports/middleware.ts`); `qd:stream:sub` runs in the socket's lane of\n// subscription work (`emit/lane.ts`), and no listener throws\n// (`emit/answer.ts`).\n//\n// A subscribe is authorized (`streamTargets.ts`), then joins the feed's room\n// and reads its seed in the same tick, so every item pushed after the seed\n// reaches the socket as a `qd:stream` frame (possibly before the\n// acknowledgement). A stream whose service computes its seed (`streams: {\n// <name>: { seed } }`) calls that function in the tick the socket joined,\n// under the subscriber's principal, instead of reading the kept items: one\n// that returns at once keeps the same guarantee; one that returns a promise\n// may also see items pushed while it runs, which then arrive both ways. What\n// it returns is checked against the item schema, and what it throws (or a\n// mismatch) answers the subscribe and takes the socket out of the feed. An\n// unsubscribe that arrives while a subscribe of the same feed is being\n// authorized stops it from joining (and from computing a seed nobody would\n// read). A socket holds at most `MAX_STREAMS_PER_SOCKET` feeds (`CONFLICT`\n// past that), recorded on `socket.data.streams` with the rows their access\n// is derived from (`streamIndex.ts`), so an access change revokes them\n// (`streamRevocation.ts`); Socket.IO empties its rooms when it disconnects.\n\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { answerEvent, answerNow, onDisconnect } from \"../emit/answer\";\nimport type { Hub } from \"../emit/hub\";\nimport { PendingKeys } from \"../emit/pending\";\nimport type { QuickdrawServerSocket, SocketContext } from \"../transports/types\";\nimport { computeSeed, streamKey, type StreamSeeds } from \"./seeds\";\nimport { subscriptionOf, type StreamIndex } from \"./streamIndex\";\nimport { authorizeStream, checkUnsubscriber, streamAnchors, streamTarget } from \"./streamTargets\";\nimport type { StreamSubscription } from \"./types\";\n\n/** The acknowledgement of `qd:stream:sub` (`StreamSubscribeReply` in `envelope.ts`). */\ninterface SeedReply {\n readonly ok: true;\n readonly seed: readonly unknown[];\n}\n\n/** The most stream feeds one socket may subscribe to at once. */\nexport const MAX_STREAMS_PER_SOCKET = 500;\n\ninterface StreamState {\n readonly hub: Hub;\n readonly seeds: StreamSeeds;\n readonly index: StreamIndex;\n readonly pending: PendingKeys;\n}\n\nasync function subscribe(\n state: StreamState,\n socket: QuickdrawServerSocket,\n value: unknown,\n): Promise<SeedReply> {\n const target = streamTarget(state.hub, value, CLIENT_EVENTS.streamSub);\n const { room } = target;\n const unsubscribes = state.pending.begin(socket, [room]).get(room) ?? 0;\n let joined: StreamSubscription | undefined;\n try {\n await authorizeStream(state.hub, socket, target);\n const anchors = await streamAnchors(state.hub, socket, target);\n const known = state.index.get(socket, room) !== undefined;\n if (!known && state.index.size(socket) >= MAX_STREAMS_PER_SOCKET) {\n throw new QuickdrawError(\n \"CONFLICT\",\n `A socket may subscribe to at most ${MAX_STREAMS_PER_SOCKET} stream feeds; unsubscribe from one first`,\n );\n }\n if (socket.connected && state.pending.count(socket, room) === unsubscribes) {\n joined = subscriptionOf(target, anchors);\n state.index.set(socket, joined);\n }\n } finally {\n state.pending.end(socket, [room]);\n }\n if (target.stream.computeSeed === undefined) {\n const key = streamKey(target.service.name, target.stream.name);\n return { ok: true, seed: state.seeds.seed(key, target.scope) };\n }\n if (joined === undefined) {\n // An unsubscribe or a disconnect overtook the subscribe: nobody reads this seed.\n return { ok: true, seed: [] };\n }\n try {\n const ctx = Object.freeze({\n principal: socket.data.principal ?? null,\n socketId: socket.id,\n log: state.hub.logger,\n });\n // Called in this tick, the one the socket joined the feed in.\n return {\n ok: true,\n seed: await computeSeed(\n target.service.name,\n target.stream,\n target.scope,\n ctx,\n state.hub.outputValidation,\n ),\n };\n } catch (error) {\n // The subscriber is answered the failure, so it hears none of the items that follow.\n if (state.index.get(socket, room) === joined) {\n state.index.delete(socket, room);\n }\n throw error;\n }\n}\n\nfunction unsubscribe(\n state: StreamState,\n socket: QuickdrawServerSocket,\n value: unknown,\n): { readonly ok: true } {\n const target = streamTarget(state.hub, value, CLIENT_EVENTS.streamUnsub);\n checkUnsubscriber(socket, target);\n state.pending.unsubscribed(socket, target.room);\n state.index.delete(socket, target.room);\n return { ok: true };\n}\n\n/**\n * The socket extension (`transports/socketio.ts`) that serves\n * `qd:stream:sub` and `qd:stream:unsub` for one dispatcher's streams, and\n * drops a disconnected socket's feeds from `index`.\n */\nexport function streamSubscriptions(\n hub: Hub,\n seeds: StreamSeeds,\n index: StreamIndex,\n): (socket: QuickdrawServerSocket, context: SocketContext) => void {\n const state: StreamState = { hub, seeds, index, pending: new PendingKeys() };\n return (socket, context) => {\n answerEvent(socket, context, CLIENT_EVENTS.streamSub, (frame) =>\n subscribe(state, socket, frame),\n );\n socket.on(CLIENT_EVENTS.streamUnsub, (frame: unknown, ack: unknown) => {\n answerNow(socket, context, CLIENT_EVENTS.streamUnsub, ack, () =>\n unsubscribe(state, socket, frame),\n );\n });\n onDisconnect(socket, context, () => {\n index.drop(socket);\n });\n };\n}\n","// The default `AccessEngine`. It decides the forms that need no row lookup\n// (`\"public\"`, `\"authenticated\"`, `{ service }`, `custom(fn)`) and hands the\n// row-level forms (`entry`, `scope`) to a `RowAccess`, which the access\n// policies card provides. Without one, a row-level form fails with\n// `INTERNAL`: a configuration mistake, never a silent pass.\n\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { AnyContext } from \"../context\";\nimport type { MaybePromise } from \"../types\";\nimport { isCustomAccess } from \"./forms\";\nimport { meetsLevel, serviceGrant } from \"./levels\";\nimport type { AccessEngine, AccessForm, AccessRequest, RowAccess } from \"./types\";\n\n/** Options of {@link createBasicAccessEngine}. */\nexport interface BasicAccessEngineOptions {\n /**\n * Decides `entry` and `scope` forms. Without it they fail with `INTERNAL`,\n * naming the service, because no access policy is configured.\n */\n readonly rows?: RowAccess;\n}\n\nfunction forbidden(): QuickdrawError {\n return new QuickdrawError(\"FORBIDDEN\", \"Insufficient permissions\");\n}\n\nconst NO_ROW_POLICY: RowAccess = {\n allows(form, request) {\n const kind = form.scope === undefined ? \"entry\" : \"scope\";\n throw new QuickdrawError(\n \"INTERNAL\",\n `${request.service.name}.${request.method} uses ${kind} access, but no access policy is configured for ${request.service.name}`,\n );\n },\n};\n\nasync function decide(form: AccessForm, request: AccessRequest, rows: RowAccess): Promise<void> {\n if (form === \"public\") {\n return;\n }\n const { principal, service } = request;\n if (principal === null) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n const grant = serviceGrant(principal, service.name);\n if (form === \"authenticated\" || (service.adminBypass && grant === \"Admin\")) {\n return;\n }\n if (isCustomAccess(form)) {\n // The check was typed for this method's input and context, which are\n // what the dispatcher passes.\n const check = form.check as (ctx: AnyContext, input: unknown) => MaybePromise<boolean>;\n if ((await check(request.ctx, request.input)) === true) {\n return;\n }\n throw forbidden();\n }\n if (form.service !== undefined && meetsLevel(grant, form.service)) {\n return;\n }\n if (\n (form.entry !== undefined || form.scope !== undefined) &&\n (await rows.allows(form, request)) === true\n ) {\n return;\n }\n throw forbidden();\n}\n\n/**\n * The default access engine:\n *\n * - `\"public\"` always passes.\n * - Every other form needs a principal; without one the call fails with\n * `UNAUTHENTICATED`.\n * - A service-wide `Admin` grant passes every check on its service, unless\n * the service sets `adminBypass: false`.\n * - `\"authenticated\"` passes for any principal.\n * - `custom(fn)` passes when `fn(ctx, input)` resolves `true`.\n * - `{ service: L }` passes when the principal's grant on the service is at\n * least `L`. A lower grant counts only where `service` is named, so a\n * `Read` grant does not read every row.\n * - `{ entry }` and `{ scope }` ask `options.rows`; `{ service, entry }`\n * passes on either.\n *\n * Anything else fails with `FORBIDDEN`.\n */\nexport function createBasicAccessEngine(options: BasicAccessEngineOptions = {}): AccessEngine {\n const rows = options.rows ?? NO_ROW_POLICY;\n return Object.freeze({\n authorize: (form: AccessForm, request: AccessRequest) => decide(form, request, rows),\n });\n}\n","// The live collection subscriptions of this process's sockets (RFC 0003\n// sections 4.4 and 7), beside the entity subscriptions of\n// `emit/subscriptions.ts`. Each socket keeps its own on\n// `socket.data.collections`, by room: the scope, and the rows its access is\n// derived from (its anchors). The index finds the sockets an access change\n// can concern by anchor, and the scopes of a collection that have\n// subscribers here. Rooms stay the source of truth for who receives frames.\n// 4.1 kept nothing (4.1 `src/server/collections.ts:141-187`), so it could\n// not revoke a scope a user lost access to.\n\nimport { collectionRoom } from \"../../contract/names\";\nimport type { AccessChange } from \"../access/changes\";\nimport { anchorKey } from \"../access/tools\";\nimport { PendingKeys } from \"../emit/pending\";\nimport { emptyRecords, ownRecord } from \"../emit/subscriptions\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\n\n/** One live collection subscription, as `socket.data.collections[room]` records it. */\nexport interface ScopeSubscription {\n /** The service name. */\n readonly s: string;\n /** The collection name. */\n readonly c: string;\n readonly scope: string;\n /** The rows its access is derived from (`anchorKey`s): the anchor row, then its `inherit` parents. */\n readonly anchors: readonly string[];\n}\n\n/**\n * `socket.data.collections`: a socket's collection subscriptions, by room\n * name. Plain data, in an object without a prototype, read by own keys only.\n */\nexport type ScopeSubscriptions = Record<string, ScopeSubscription>;\n\n/** Told when a scope gains its first subscriber here, and loses its last. */\nexport interface ScopeListener {\n pin(room: string): void;\n unpin(room: string): void;\n}\n\ntype Counts = Map<QuickdrawServerSocket, number>;\n\nfunction serviceOf(anchor: string): string {\n return anchor.slice(0, anchor.indexOf(\"\\u0000\"));\n}\n\nfunction count(index: Map<string, Counts>, key: string, socket: QuickdrawServerSocket, by: 1 | -1) {\n const counts = index.get(key) ?? new Map<QuickdrawServerSocket, number>();\n const next = (counts.get(socket) ?? 0) + by;\n if (next > 0) {\n counts.set(socket, next);\n index.set(key, counts);\n return;\n }\n counts.delete(socket);\n if (counts.size === 0) {\n index.delete(key);\n }\n}\n\n/** The room of a subscription. */\nexport function roomOf(subscription: Pick<ScopeSubscription, \"s\" | \"c\" | \"scope\">): string {\n return collectionRoom(subscription.s, subscription.c, subscription.scope);\n}\n\n/** The key of one collection of one service, among all of a process's collections. */\nexport function groupOf(service: string, collection: string): string {\n return `${service}\\u0000${collection}`;\n}\n\n/** This process's collection subscriptions, indexed by anchor and by collection. */\nexport class ScopeIndex {\n readonly #byAnchor = new Map<string, Counts>();\n readonly #byService = new Map<string, Counts>();\n /** Per collection (`service\\0collection`), how many sockets here subscribe to each scope. */\n readonly #scopes = new Map<string, Map<string, number>>();\n /** The scopes each socket has a `qd:col:sub` in flight for, by room. */\n readonly #pending = new PendingKeys();\n readonly #listener: ScopeListener | undefined;\n\n constructor(listener?: ScopeListener) {\n this.#listener = listener;\n }\n\n #index(socket: QuickdrawServerSocket, subscription: ScopeSubscription, by: 1 | -1): void {\n for (const anchor of subscription.anchors) {\n count(this.#byAnchor, anchor, socket, by);\n count(this.#byService, serviceOf(anchor), socket, by);\n }\n const key = groupOf(subscription.s, subscription.c);\n const scopes = this.#scopes.get(key) ?? new Map<string, number>();\n const next = (scopes.get(subscription.scope) ?? 0) + by;\n if (next > 0) {\n scopes.set(subscription.scope, next);\n this.#scopes.set(key, scopes);\n } else {\n scopes.delete(subscription.scope);\n if (scopes.size === 0) {\n this.#scopes.delete(key);\n }\n }\n if (next === 1 && by === 1) {\n this.#listener?.pin(roomOf(subscription));\n } else if (next === 0) {\n this.#listener?.unpin(roomOf(subscription));\n }\n }\n\n /** The socket's subscription to a scope, by room, or `undefined`. */\n get(socket: QuickdrawServerSocket, room: string): ScopeSubscription | undefined {\n return ownRecord(socket.data.collections, room);\n }\n\n /** Every collection subscription of the socket. */\n entries(socket: QuickdrawServerSocket): ScopeSubscription[] {\n return Object.values(socket.data.collections ?? {});\n }\n\n /** Records a subscription and puts the socket in the scope's room, replacing any earlier one. */\n set(socket: QuickdrawServerSocket, subscription: ScopeSubscription): void {\n const room = roomOf(subscription);\n const previous = this.get(socket, room);\n socket.data.collections ??= emptyRecords();\n socket.data.collections[room] = subscription;\n this.#index(socket, subscription, 1);\n if (previous !== undefined) {\n this.#index(socket, previous, -1);\n }\n void socket.join(room);\n }\n\n /** Ends a subscription: the socket leaves the scope's room. Returns what it was. */\n delete(socket: QuickdrawServerSocket, room: string): ScopeSubscription | undefined {\n const previous = this.get(socket, room);\n if (previous === undefined) {\n return undefined;\n }\n const subscriptions = socket.data.collections;\n if (subscriptions !== undefined) {\n delete subscriptions[room];\n }\n this.#index(socket, previous, -1);\n void socket.leave(room);\n return previous;\n }\n\n /** A `qd:col:sub` of the scope begins; returns how often it was unsubscribed from so far. */\n begin(socket: QuickdrawServerSocket, room: string): number {\n return this.#pending.begin(socket, [room]).get(room) ?? 0;\n }\n\n /** The subscribe `begin` started has ended. */\n end(socket: QuickdrawServerSocket, room: string): void {\n this.#pending.end(socket, [room]);\n }\n\n /** A client unsubscribed: forget its subscription, and stop one still being made from joining. */\n unsubscribe(socket: QuickdrawServerSocket, room: string): void {\n this.#pending.unsubscribed(socket, room);\n this.delete(socket, room);\n }\n\n /** How often the client unsubscribed from the scope while a subscribe of it ran; it joins only if that did not move. */\n unsubscribes(socket: QuickdrawServerSocket, room: string): number {\n return this.#pending.count(socket, room);\n }\n\n /** A socket disconnected: Socket.IO has emptied its rooms; drop it from the index. */\n drop(socket: QuickdrawServerSocket): void {\n for (const subscription of this.entries(socket)) {\n this.#index(socket, subscription, -1);\n }\n socket.data.collections = emptyRecords();\n }\n\n /** The scopes of a collection that sockets of this process subscribe to. */\n scopes(service: string, collection: string): string[] {\n return [...(this.#scopes.get(groupOf(service, collection))?.keys() ?? [])];\n }\n\n /**\n * The subscriptions an access change can concern: those anchored on the\n * changed row (any row of the service when `id` is absent), of the changed\n * user's sockets (every user's when `userId` is absent).\n */\n matching(change: AccessChange): Map<QuickdrawServerSocket, ScopeSubscription[]> {\n const key = change.id === undefined ? undefined : anchorKey(change.service, change.id);\n const sockets =\n key === undefined ? this.#byService.get(change.service) : this.#byAnchor.get(key);\n const found = new Map<QuickdrawServerSocket, ScopeSubscription[]>();\n for (const socket of sockets?.keys() ?? []) {\n if (change.userId !== undefined && socket.data.principal?.userId !== change.userId) {\n continue;\n }\n const entries = this.entries(socket).filter(({ anchors }) =>\n anchors.some((anchor) =>\n key === undefined ? serviceOf(anchor) === change.service : anchor === key,\n ),\n );\n if (entries.length > 0) {\n found.set(socket, entries);\n }\n }\n return found;\n }\n}\n","// The collections of a dispatcher's services, bound to what serves them\n// (RFC 0003 sections 5.1 and 7.1): each anchor resolved to the served service\n// whose policy authorizes its scopes, and the columns that decide membership\n// registered with the storage adapter, so a write reports their values\n// (`before` and `after`) and a write that sets one reads the old value first.\n// Those are the scope column, the `where` columns, and a `via` junction's\n// entry and scope columns: every other write cannot move a row between\n// scopes, and costs no extra read. Order columns are not registered: no\n// collection change depends on their old values.\n\nimport type { Hub } from \"../emit/hub\";\nimport type { Registry } from \"../registry\";\nimport type { AnyService } from \"../service\";\nimport { modelKey, type StorageAdapter } from \"../storage\";\nimport type { WriteRecord } from \"../uow/types\";\nimport { createDeltaBuffer, type DeltaBuffer } from \"./buffer\";\nimport type { ServiceCollection } from \"./define\";\nimport type { FlushMoves } from \"./moves\";\nimport { ScopeIndex } from \"./scopes\";\n\n/** A collection of a served service, with its anchor's service. */\nexport interface BoundCollection extends ServiceCollection {\n /** The service the collection is a member of. */\n readonly service: AnyService;\n /** The service's model, as the client names it. */\n readonly model: string;\n /** The service whose policy authorizes the scopes; `undefined` for a `\"self\"` scope. */\n readonly anchorService: AnyService | undefined;\n}\n\n/** How writes find collections. */\nexport interface CollectionRoutes {\n /** The collections whose items are rows of each model. */\n readonly byModel: ReadonlyMap<string, readonly BoundCollection[]>;\n /** The `via` collections whose junction is each model. */\n readonly byJunction: ReadonlyMap<string, readonly BoundCollection[]>;\n /** The collections anchored on a service of each model: deleting such a row closes their scopes. */\n readonly byAnchorModel: ReadonlyMap<string, readonly BoundCollection[]>;\n /** The collection `name` of service `service`. */\n find(service: string, name: string): BoundCollection | undefined;\n}\n\n/** What a dispatcher keeps for its collections. */\nexport interface CollectionState {\n readonly routes: CollectionRoutes;\n readonly scopes: ScopeIndex;\n readonly buffer: DeltaBuffer;\n /** Each flush's moves, found once for the collection and topic sinks. */\n readonly moves: FlushMoves;\n}\n\n/** A dispatcher's live data with its collections: the same hub object, so the server it attaches is shared. */\nexport interface CollectionHub extends Hub {\n readonly collections: CollectionState;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`createDispatcher: ${message}`);\n}\n\nfunction anchorOf(\n registry: Registry,\n service: AnyService,\n collection: ServiceCollection,\n): AnyService | undefined {\n const { anchor } = collection;\n if (anchor === undefined) {\n return undefined;\n }\n const owner = `${service.name}.${collection.name}`;\n const target = registry.services.get(anchor.name);\n if (target === undefined) {\n fail(`${owner} is anchored on ${anchor.name}, which this dispatcher does not serve`);\n }\n if (target.model === undefined || target.access === undefined) {\n fail(\n `${owner} is anchored on ${target.name}, which declares no model and access policy to authorize its scopes with`,\n );\n }\n return target;\n}\n\nfunction add(\n index: Map<string, BoundCollection[]>,\n model: string,\n collection: BoundCollection,\n): void {\n index.set(model, [...(index.get(model) ?? []), collection]);\n}\n\n/** Registers the columns that decide membership: the scope column or junction, and the `where` columns. */\nfunction registerInterest(storage: StorageAdapter | undefined, bound: BoundCollection): void {\n const { scope } = bound;\n const where = Object.keys(bound.where);\n if (scope.kind === \"column\") {\n storage?.registerInterest(bound.model, [scope.column, ...where]);\n return;\n }\n storage?.registerInterest(modelKey(scope.model), [scope.entry, scope.scope]);\n if (where.length > 0) {\n storage?.registerInterest(bound.model, where);\n }\n}\n\n/**\n * The routes of `registry`'s collections. Registers their membership columns\n * with the storage adapter. Throws a `TypeError` for an anchor this\n * dispatcher cannot authorize a scope through.\n */\nexport function bindCollections(\n registry: Registry,\n storage: StorageAdapter | undefined,\n): CollectionRoutes {\n const byModel = new Map<string, BoundCollection[]>();\n const byJunction = new Map<string, BoundCollection[]>();\n const byAnchorModel = new Map<string, BoundCollection[]>();\n const byName = new Map<string, BoundCollection>();\n for (const service of registry.services.values()) {\n for (const collection of service.collections.values()) {\n if (service.model === undefined) {\n continue;\n }\n const anchorService = anchorOf(registry, service, collection);\n const bound: BoundCollection = Object.freeze({\n ...collection,\n service,\n model: modelKey(service.model),\n anchorService,\n });\n byName.set(`${service.name}\\u0000${collection.name}`, bound);\n add(byModel, bound.model, bound);\n if (bound.scope.kind === \"via\") {\n add(byJunction, modelKey(bound.scope.model), bound);\n }\n if (anchorService?.model !== undefined) {\n add(byAnchorModel, modelKey(anchorService.model), bound);\n }\n registerInterest(storage, bound);\n }\n }\n return Object.freeze({\n byModel,\n byJunction,\n byAnchorModel,\n find: (service: string, name: string) => byName.get(`${service}\\u0000${name}`),\n });\n}\n\n/**\n * The scopes keyed by each row `writes` deleted that collections are\n * anchored on, with their collections: deleting a chat closes its messages'\n * scope (RFC 0003 section 7.2).\n */\nexport function anchoredScopes(\n routes: CollectionRoutes,\n writes: readonly WriteRecord[],\n): (readonly [BoundCollection, string])[] {\n const scopes: (readonly [BoundCollection, string])[] = [];\n for (const write of writes) {\n const anchored = routes.byAnchorModel.get(modelKey(write.model));\n if (write.op !== \"delete\" || anchored === undefined) {\n continue;\n }\n for (const collection of anchored) {\n scopes.push([collection, write.id]);\n }\n }\n return scopes;\n}\n\n/** The collection state of a dispatcher: its routes, its subscriptions and its resume buffer. */\nexport function createCollectionState(\n registry: Registry,\n storage: StorageAdapter | undefined,\n): CollectionState {\n const buffer = createDeltaBuffer();\n return {\n routes: bindCollections(registry, storage),\n scopes: new ScopeIndex(buffer),\n buffer,\n moves: new WeakMap(),\n };\n}\n","// Which rows a flush touched, per service (RFC 0003 section 5.3, steps 1 and\n// 3). A write to a model touches its row in every service declaring that\n// model; then each service's `affects` adds the rows its written rows point\n// at, one hop and without duplicates: a task written with `affects: [{\n// service: task, id: \"parentTaskId\" }]` touches its parent task as well, which\n// is then sent whole. 4.1 left this to lifecycle hooks and hand-written emits\n// (4.1 `src/server/BaseService.ts:741-827`).\n\nimport type { Registry } from \"../registry\";\nimport type { AffectsLink, AnyService } from \"../service\";\nimport { modelKey, type StorageAdapter } from \"../storage\";\nimport { ANY_FIELD, type WriteRecord } from \"../uow/types\";\n\n/** What a flush did to one row of one service. */\nexport interface Touch {\n readonly op: WriteRecord[\"op\"];\n /** The fields written; `[ANY_FIELD]` when they are unknown, as for a touch or an affected row. */\n readonly fields: readonly string[];\n}\n\n/** The rows a flush touched, by service, then by row id. */\nexport type TouchedRows = ReadonlyMap<AnyService, ReadonlyMap<string, Touch>>;\n\n/** How writes find services: by model, and through each `affects` link. */\nexport interface Routes {\n /** The services declaring each model, by the client's model name. */\n readonly byModel: ReadonlyMap<string, readonly AnyService[]>;\n /** The service each `affects` link points at. */\n readonly targets: ReadonlyMap<AffectsLink, AnyService>;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`createDispatcher: ${message}`);\n}\n\nfunction targetOf(registry: Registry, service: AnyService, link: AffectsLink): AnyService {\n const target = registry.services.get(link.service.name);\n if (target === undefined) {\n fail(`${service.name} affects ${link.service.name}, which this dispatcher does not serve`);\n }\n if (target.model === undefined || target.contract.entity === undefined) {\n fail(\n `${service.name} affects ${target.name}, which has no model and entity, so it has no rows to send again`,\n );\n }\n return target;\n}\n\n/**\n * The routes of `registry`'s services. Registers each `affects` link's\n * columns with the storage adapter, so writes report them. Throws a\n * `TypeError` for a link to a service this dispatcher cannot send rows of.\n */\nexport function routesOf(registry: Registry, storage: StorageAdapter | undefined): Routes {\n const byModel = new Map<string, AnyService[]>();\n const targets = new Map<AffectsLink, AnyService>();\n for (const service of registry.services.values()) {\n if (service.model === undefined) {\n continue;\n }\n const key = modelKey(service.model);\n byModel.set(key, [...(byModel.get(key) ?? []), service]);\n for (const link of service.affects) {\n targets.set(link, targetOf(registry, service, link));\n storage?.registerInterest(key, link.columns);\n }\n }\n return { byModel, targets };\n}\n\ntype Touched = Map<AnyService, Map<string, Touch>>;\n\nfunction rowsOf(touched: Touched, service: AnyService): Map<string, Touch> {\n let rows = touched.get(service);\n if (rows === undefined) {\n rows = new Map();\n touched.set(service, rows);\n }\n return rows;\n}\n\n/** The ids a written row points at through `link`: before and after the write. */\nfunction linkedIds(link: AffectsLink, write: WriteRecord): Set<string> {\n const ids = new Set<string>();\n for (const values of [write.before, write.after]) {\n for (const id of values === undefined ? [] : link.ids(values)) {\n ids.add(id);\n }\n }\n return ids;\n}\n\n/** Marks the rows `write` affects through `service`'s links: sent whole, unless the flush deleted them. */\nfunction affect(touched: Touched, routes: Routes, service: AnyService, write: WriteRecord): void {\n for (const link of service.affects) {\n const target = routes.targets.get(link);\n const ids = linkedIds(link, write);\n if (target === undefined || ids.size === 0) {\n continue;\n }\n const rows = rowsOf(touched, target);\n for (const id of ids) {\n const touch = rows.get(id);\n if (touch?.op !== \"delete\") {\n rows.set(id, { op: touch?.op ?? \"update\", fields: [ANY_FIELD] });\n }\n }\n }\n}\n\n/** The rows `writes` touched per service, `affects` expanded one hop. */\nexport function touchedRows(writes: readonly WriteRecord[], routes: Routes): TouchedRows {\n const touched: Touched = new Map();\n for (const write of writes) {\n for (const service of routes.byModel.get(modelKey(write.model)) ?? []) {\n rowsOf(touched, service).set(write.id, { op: write.op, fields: write.fields });\n }\n }\n for (const write of writes) {\n for (const service of routes.byModel.get(modelKey(write.model)) ?? []) {\n affect(touched, routes, service, write);\n }\n }\n return touched;\n}\n","// Entity frames (RFC 0003 section 6), all on the event `qd:e`:\n//\n// | Write | Frame | Payload |\n// |--------------------------------------------------------|-------|---------------------|\n// | delete | `r` | none |\n// | create | `u` | the full projection |\n// | update of plain projection fields only (no `map`) | `p` | the changed fields |\n// | any other update: unknown fields (a touch, `affects`), | `u` | the full projection |\n// | a field outside the projection, a projection with `map`| | |\n//\n// A create is never a patch: a patch of a row the client never had could not\n// be applied. A patch also carries the service's `versionColumn` when the\n// projection has it, since tracked writes do not report `@updatedAt` columns.\n// Every frame of a flush carries the flush's revision.\n\nimport type { EntityFrame, Revision } from \"../../protocol/envelope\";\nimport type { StorageRow } from \"../storage\";\nimport { ANY_FIELD } from \"../uow/types\";\nimport type { Touch } from \"./affects\";\nimport { pickKeys, projectRow, type Projection } from \"./projection\";\n\n/** How a touched row goes out: whole, as a patch of `fields`, or as a removal. */\nexport type FrameKind =\n | { readonly t: \"u\" }\n | { readonly t: \"p\"; readonly fields: readonly string[] }\n | { readonly t: \"r\" };\n\nconst WHOLE: FrameKind = Object.freeze({ t: \"u\" });\n\nconst REMOVED: FrameKind = Object.freeze({ t: \"r\" });\n\n/** The frame a row's touch makes; see the table above. */\nexport function frameKind(\n projection: Projection,\n touch: Touch,\n versionColumn: string | undefined,\n): FrameKind {\n if (touch.op === \"delete\") {\n return REMOVED;\n }\n const { fields } = touch;\n const plain =\n touch.op === \"update\" &&\n projection.map === undefined &&\n fields.length > 0 &&\n !fields.includes(ANY_FIELD) &&\n fields.every((field) => projection.keys.includes(field));\n if (!plain) {\n return WHOLE;\n }\n const patched = new Set(fields);\n if (versionColumn !== undefined && projection.keys.includes(versionColumn)) {\n patched.add(versionColumn);\n }\n patched.delete(\"id\");\n return patched.size === 0 ? WHOLE : { t: \"p\", fields: [...patched] };\n}\n\n/**\n * What one read of a flush's rows selects: the projection's own select when\n * any row goes out whole, and only the patched fields when every row is a\n * patch, so a row is read no wider than what is sent.\n */\nexport function selectFor(\n projection: Projection,\n kinds: readonly FrameKind[],\n): Readonly<Record<string, unknown>> {\n if (kinds.some((kind) => kind.t === \"u\")) {\n return projection.select;\n }\n const select: Record<string, true> = { id: true };\n for (const kind of kinds) {\n if (kind.t === \"p\") {\n for (const field of kind.fields) {\n select[field] = true;\n }\n }\n }\n return select;\n}\n\n/** The frame of one row, before tiers are stripped: `row` is the row read, absent for a removal. */\nexport function buildFrame(\n service: string,\n id: string,\n kind: FrameKind,\n row: StorageRow | undefined,\n rev: Revision,\n projection: Projection,\n): EntityFrame | undefined {\n if (kind.t === \"r\") {\n return { t: \"r\", s: service, id, rev };\n }\n if (row === undefined) {\n return undefined;\n }\n if (kind.t === \"p\") {\n return { t: \"p\", s: service, id, rev, d: pickKeys(row, kind.fields) };\n }\n return { t: \"u\", s: service, id, rev, d: projectRow(projection, row) };\n}\n","// A flush's deltas per scope (RFC 0003 section 7.2): every move of the flush\n// that concerns a scope, in the order the rows were first written, batched\n// into the one frame the scope gets for the flush. More rows than the\n// collection's `bulkThreshold` for one scope make that frame a single\n// `reset`, read nothing, and let its clients load the scope again. 4.1 sent\n// one event per row per scope (4.1 `src/server/collections.ts:338-352`)\n// and left bulk writes to a hand-written `emitReset`.\n//\n// Items come from rows the moves already read, or from one read for the\n// rest, with the item's select (only the patched fields when every delta is\n// a patch). A row read as missing was deleted since: its own flush removes\n// it, so its `added` or `updated` is dropped here.\n//\n// In a collection that declares `index`, an `added` delta also carries its\n// member's index row, built from the item it sends (`index.ts`), with the\n// service's `versionColumn` read alongside the item for the row's `rev`.\n//\n// Behind a cluster adapter (`cluster`) a change that would be `patched` goes\n// out `updated`, with the whole item: frames from two nodes can reach a\n// client out of revision order, and a patch it dropped as older would lose\n// its fields. One that would be dropped as empty is still dropped.\n//\n// Behind a cluster adapter each delta is also decided by its row as read\n// for the frame, not by the write's own values alone. A flush takes its\n// revision when it flushes, after its handler settled and (behind a\n// cluster) once the counter answered, so a write that committed first can\n// flush last: a move out of a scope, or a delete, then carries a higher\n// revision than a later move back in, or a later create of its id, and a\n// client would apply it over them. The read is made after the flush took\n// its revision, so it sees every write whose flush took a lower one: a row\n// in the scope at the read goes out (`removed` becomes `updated`, or\n// `added` for a row that left scopes nobody could name), and one that is\n// not there is `removed`. Every frame a scope gets about a row is then right\n// as of a read made after its revision, and the newest one wins on the\n// client. The rows of `removed` deltas are read for it, with the membership\n// columns. One server keeps its cheaper rule (no read for a removal): a\n// write that commits first and flushes last can still leave a client\n// without a member there until the row's next write.\n\nimport { collectionRoom } from \"../../contract/names\";\nimport type { CollectionDelta, Revision } from \"../../protocol/envelope\";\nimport { selectFor, type FrameKind } from \"../emit/frames\";\nimport type { StorageAdapter, StorageRow } from \"../storage\";\nimport type { BoundCollection } from \"./bind\";\nimport { indexColumns, indexRowFrom } from \"./index\";\nimport { itemOf, membershipColumns, patchOf, scopeIn, selectWith } from \"./items\";\nimport type { Moves } from \"./moves\";\n\n/** A delta whose item is not read yet. */\ntype Pending =\n | { readonly t: \"added\" | \"updated\"; readonly id: string }\n | {\n readonly t: \"removed\";\n readonly id: string;\n /** The row left scopes nobody could name: this scope may never have held it. */\n readonly unnamed?: true;\n }\n | { readonly t: \"patched\"; readonly id: string; readonly fields: readonly string[] };\n\n/** What one scope gets from one flush. */\nexport interface ScopePlan {\n readonly scope: string;\n readonly room: string;\n readonly deltas: Pending[];\n /** Too many rows changed, or junction rows went unseen: one `reset` instead. */\n reset: boolean;\n}\n\n/**\n * The plan of every scope the moves concern, in the order rows were first\n * written. `subscribed` are the collection's scopes with subscribers on this\n * process: a row that left scopes nobody can name is removed from them.\n */\nexport function planScopes(\n collection: BoundCollection,\n moves: Moves,\n subscribed: readonly string[],\n): ScopePlan[] {\n const plans = new Map<string, ScopePlan>();\n const planOf = (scope: string): ScopePlan => {\n let plan = plans.get(scope);\n if (plan === undefined) {\n const room = collectionRoom(collection.service.name, collection.name, scope);\n plan = { scope, room, deltas: [], reset: false };\n plans.set(scope, plan);\n }\n return plan;\n };\n for (const move of moves.moves) {\n const { id, kind } = move;\n for (const scope of move.left) {\n planOf(scope).deltas.push({ t: \"removed\", id });\n }\n for (const scope of move.entered) {\n planOf(scope).deltas.push({ t: \"added\", id });\n }\n for (const scope of move.stayed) {\n planOf(scope).deltas.push(\n kind.t === \"p\" ? { t: \"patched\", id, fields: kind.fields } : { t: \"updated\", id },\n );\n }\n const named = new Set([...move.left, ...move.entered, ...move.stayed]);\n for (const scope of move.unknownLeft ? subscribed : []) {\n if (!named.has(scope)) {\n planOf(scope).deltas.push({ t: \"removed\", id, unnamed: true });\n }\n }\n }\n for (const scope of moves.resetAll ? subscribed : []) {\n planOf(scope).reset = true;\n }\n for (const plan of plans.values()) {\n plan.reset ||= plan.deltas.length > collection.bulkThreshold;\n }\n return [...plans.values()];\n}\n\nconst WHOLE: FrameKind = Object.freeze({ t: \"u\" });\n\n/**\n * The rows the plans' deltas take items from: those the moves read, and one\n * read for the others. Behind a cluster adapter (`cluster`) every change\n * reads its whole item, and the rows of `removed` deltas and of `also` are\n * read too, with the membership columns, so the deltas are decided at the\n * read (`buildDeltas`).\n */\nexport async function readItems(\n storage: StorageAdapter,\n collection: BoundCollection,\n plans: readonly ScopePlan[],\n read: ReadonlyMap<string, StorageRow>,\n cluster = false,\n also: readonly string[] = [],\n): Promise<ReadonlyMap<string, StorageRow>> {\n const kinds = new Map<string, FrameKind>();\n for (const plan of plans.filter(({ reset }) => !reset)) {\n for (const delta of plan.deltas) {\n if (read.has(delta.id) || (delta.t === \"removed\" && !cluster)) {\n continue;\n }\n const item = cluster || delta.t !== \"patched\" || kinds.get(delta.id)?.t === \"u\";\n kinds.set(delta.id, item ? WHOLE : { t: \"p\", fields: delta.fields });\n }\n }\n for (const id of cluster ? also : []) {\n if (!read.has(id)) {\n kinds.set(id, WHOLE);\n }\n }\n if (kinds.size === 0) {\n return read;\n }\n const select = selectFor(collection.item, [...kinds.values()]);\n const whole = [...kinds.values()].some((kind) => kind.t === \"u\");\n const columns = [...indexColumns(collection), ...(cluster ? membershipColumns(collection) : [])];\n const rows = await storage.findMany(collection.model, {\n where: { id: { in: [...kinds.keys()] } },\n select: whole ? selectWith(select, columns) : select,\n });\n const all = new Map(read);\n for (const row of rows) {\n if (typeof row.id === \"string\") {\n all.set(row.id, row);\n }\n }\n return all;\n}\n\n/** An `added` delta: the member's item, and in an indexed collection its index row, built from that item. */\nfunction added(collection: BoundCollection, row: StorageRow, rev: Revision): CollectionDelta {\n const item = itemOf(collection, row);\n return collection.index === undefined\n ? { t: \"added\", item }\n : { t: \"added\", item, index: indexRowFrom(collection, item, row, rev) };\n}\n\n/**\n * Behind a cluster adapter, a pending delta of `scope` as the row read for\n * the frame decides it (`row` absent: the row is gone). In a column-scoped\n * collection a row not in the scope at the read is `removed`, and one in it\n * is not: a removal becomes `updated` (`added` for a row that left scopes\n * nobody could name, which this scope may never have held). A `via` scope's\n * links were already read at flush time (`moves.ts`), so there only a row\n * gone since is `removed`.\n */\nfunction decided(\n collection: BoundCollection,\n scope: string,\n pending: Pending,\n row: StorageRow | undefined,\n): Pending {\n if (collection.scope.kind !== \"column\") {\n return row === undefined && pending.t !== \"removed\"\n ? { t: \"removed\", id: pending.id }\n : pending;\n }\n if (row === undefined || scopeIn(collection, row) !== scope) {\n return pending.t === \"removed\" ? pending : { t: \"removed\", id: pending.id };\n }\n if (pending.t !== \"removed\") {\n return pending;\n }\n return { t: pending.unnamed === true ? \"added\" : \"updated\", id: pending.id };\n}\n\n/**\n * The deltas of one scope's frame for the flush at `rev`, from its plan and\n * the rows read. Behind a cluster adapter (`cluster`) each delta is decided\n * by its row as read (`decided`), and goes out `updated`, whole, where a\n * patch would go.\n */\nexport function buildDeltas(\n collection: BoundCollection,\n plan: ScopePlan,\n rows: ReadonlyMap<string, StorageRow>,\n rev: Revision,\n cluster = false,\n): CollectionDelta[] {\n if (plan.reset) {\n return [{ t: \"reset\" }];\n }\n const deltas: CollectionDelta[] = [];\n for (const pending of plan.deltas) {\n const row = rows.get(pending.id);\n const delta = cluster ? decided(collection, plan.scope, pending, row) : pending;\n if (delta.t === \"removed\") {\n deltas.push({ t: \"removed\", id: delta.id });\n continue;\n }\n if (row === undefined) {\n continue;\n }\n if (delta.t === \"patched\") {\n const d = patchOf(collection, row, delta.fields);\n if (Object.keys(d).length > 0) {\n deltas.push(\n cluster\n ? { t: \"updated\", item: itemOf(collection, row) }\n : { t: \"patched\", id: delta.id, d },\n );\n }\n continue;\n }\n deltas.push(\n delta.t === \"added\"\n ? added(collection, row, rev)\n : { t: \"updated\", item: itemOf(collection, row) },\n );\n }\n return deltas;\n}\n","// Which scopes a flush moved each row out of, into, or changed it in (RFC\n// 0003 section 7.2). Membership is declared, so it is read from the values a\n// write reports for the registered membership columns (`bind.ts`): a scope\n// before the write and a scope after it. The rules, ported from 4.1's\n// `notifyOne` (4.1 `src/server/collections.ts:220-270`), which compared\n// `resolveScopeId` before and after on full rows it read first:\n//\n// | Write | Before | After |\n// |--------------------------------|---------------------------|----------------|\n// | create | none | its values |\n// | create of a row the same unit | the deleted row's values | its values |\n// | deleted first (`before`) | (`before`) | |\n// | update | its old values (`before`, | its values |\n// | | over the new ones) | |\n// | delete | its old values | none |\n// | touch (`ctx.touch`) | unknown: none | read |\n// | touch merged with a tracked | the tracked write's old | its values, or |\n// | write that carried `before` | values (`before`) | read |\n// | an `affects` hop | the same as after | read |\n// | `via` junction create / delete | the entry's links without | its links now |\n// | | this flush's, with the | (read) |\n// | | ones it removed | |\n// | `via` entry created or touched | the same (its links | its links now |\n// | | before this flush) | (read) |\n//\n// Left gives `removed`, entered `added` with the full item (never a patch: a\n// client cannot patch a row it never had), stayed `patched` or `updated` as\n// entity frames decide (`emit/frames.ts`); a row created again in the same\n// scope is `updated`, whole. A touched row's old scope is unknown, so it is\n// `added` to its scope now and its old scope is not told (a touch carries no\n// `before`), unless a tracked write merged with it says where it was: then\n// it moves, or stays `updated`, whole. A deleted row whose old scope the\n// write does not carry (a touch with `removed`, or a `via` entry whose links\n// a cascade removed) left scopes nobody can name: every scope of the\n// collection subscribed on this process gets `removed`.\n//\n// A `via` entry's scopes before the flush are known whatever wrote the\n// entry: its links now, without the ones this flush's junction writes made,\n// with the ones they removed. So an entry created or touched (an `upsert`\n// that may have updated it is recorded as a create) is `added`, whole, to\n// every scope it is in now (a client upserts it where it already was, which\n// also covers links an untracked write made), and `removed` from the scopes\n// this flush's junction writes took it out of: a touch beside the removal of\n// a member's link no longer leaves the chat in that member's list.\n//\n// A `via` collection whose item reads the junction (`via`'s `refreshEntry`,\n// a member count) also sends every entry a junction write named again,\n// whole, to the scopes it stayed in: the count changed there too.\n//\n// Behind a cluster adapter (`current`) a write that committed first can\n// flush last (`deltas.ts`), so membership comes from what is read at flush\n// time: a column-scoped row's deltas are decided by its row read for the\n// frame (`deltas.ts`), and a `via` entry's links are read here anyway, so a\n// deleted entry linked to scopes again at that read (its id created again\n// by a write whose flush went first) stays in them, whole.\n\nimport { frameKind, type FrameKind } from \"../emit/frames\";\nimport { modelKey, type StorageAdapter, type StorageRow } from \"../storage\";\nimport { ANY_FIELD, type WriteRecord } from \"../uow/types\";\nimport type { BoundCollection } from \"./bind\";\nimport type { CollectionScope } from \"./define\";\nimport { indexColumns } from \"./index\";\nimport { matchesWhere, membershipColumns, scopeIn, selectWith } from \"./items\";\n\ntype Values = Readonly<Record<string, unknown>>;\n\ntype Via = Extract<CollectionScope, { readonly kind: \"via\" }>;\n\n/** What one flush did to one row of one collection. */\nexport interface Move {\n readonly id: string;\n /** Scopes it left: `removed`. */\n readonly left: readonly string[];\n /** Scopes it entered: `added`, with the full item. */\n readonly entered: readonly string[];\n /** Scopes it stayed in and changed in: `patched` or `updated`. */\n readonly stayed: readonly string[];\n /** How it goes out to the scopes it stayed in. */\n readonly kind: FrameKind;\n /** It left scopes the flush cannot name: every scope subscribed here gets `removed`. */\n readonly unknownLeft: boolean;\n}\n\n/** The moves of one flush in one collection, and the rows read to find them. */\nexport interface Moves {\n readonly moves: readonly Move[];\n /** Rows read with the item's select, by id; deltas take their items from them. */\n readonly rows: ReadonlyMap<string, StorageRow>;\n /** Junction rows were removed without values: every scope subscribed here gets `reset`. */\n readonly resetAll: boolean;\n}\n\nconst WHOLE: FrameKind = Object.freeze({ t: \"u\" });\n\nconst NONE: ReadonlySet<string> = Object.freeze(new Set<string>());\n\nfunction moveOf(\n id: string,\n before: ReadonlySet<string>,\n after: ReadonlySet<string>,\n kind: FrameKind | undefined,\n unknownLeft = false,\n): Move {\n return {\n id,\n left: [...before].filter((scope) => !after.has(scope)),\n entered: [...after].filter((scope) => !before.has(scope)),\n stayed: kind === undefined ? [] : [...after].filter((scope) => before.has(scope)),\n kind: kind ?? WHOLE,\n unknownLeft,\n };\n}\n\n/**\n * The move of a row the write took out of `before` (and put in `after`), as\n * the scopes it is in at the flush's read (`now`) decide it: it leaves every\n * scope the write named that it is not in now, and goes out whole to the\n * ones it is in now.\n */\nfunction movedTo(\n id: string,\n before: ReadonlySet<string>,\n after: ReadonlySet<string>,\n now: ReadonlySet<string>,\n unknownLeft: boolean,\n): Move {\n const named = new Set([...before, ...after]);\n return {\n id,\n left: [...named].filter((scope) => !now.has(scope)),\n entered: [...now].filter((scope) => !before.has(scope)),\n stayed: [...now].filter((scope) => before.has(scope)),\n kind: WHOLE,\n unknownLeft,\n };\n}\n\nfunction isEmpty(move: Move): boolean {\n return (\n move.left.length === 0 &&\n move.entered.length === 0 &&\n move.stayed.length === 0 &&\n !move.unknownLeft\n );\n}\n\nfunction setOf(scope: string | null | undefined): ReadonlySet<string> {\n return typeof scope === \"string\" ? new Set([scope]) : NONE;\n}\n\n/**\n * Reads rows of the collection's model with the item's select, the\n * membership columns, and the version column an indexed collection's index\n * rows take their `rev` from.\n */\nasync function readRows(\n storage: StorageAdapter,\n collection: BoundCollection,\n ids: readonly string[],\n): Promise<Map<string, StorageRow>> {\n if (ids.length === 0) {\n return new Map();\n }\n const rows = await storage.findMany(collection.model, {\n where: { id: { in: [...ids] } },\n select: selectWith(collection.item.select, [\n ...membershipColumns(collection),\n ...indexColumns(collection),\n ]),\n });\n return new Map(rows.flatMap((row) => (typeof row.id === \"string\" ? [[row.id, row]] : [])));\n}\n\n/** A column-scoped row's move, or `undefined` while its write lacks the values that decide it and no row was read. */\nfunction columnMove(\n collection: BoundCollection,\n write: WriteRecord,\n current: StorageRow | undefined,\n): Move | undefined {\n if (write.op === \"delete\") {\n const before = scopeIn(collection, write.before);\n return moveOf(write.id, setOf(before), NONE, undefined, before === undefined);\n }\n const values =\n scopeIn(collection, write.after) === undefined ? current : (write.after ?? current);\n const after = scopeIn(collection, values);\n if (after === undefined) {\n return undefined;\n }\n const whole = write.op === \"create\" || write.fields.includes(ANY_FIELD);\n if (whole && write.before !== undefined) {\n // Its old scope is known after all: deleted and created again in one unit,\n // or a tracked move merged with a touch. It moved from there, and goes out whole.\n const before = scopeIn(collection, { ...values, ...write.before });\n return moveOf(write.id, setOf(before), setOf(after), WHOLE);\n }\n if (whole) {\n return moveOf(write.id, NONE, setOf(after), undefined);\n }\n const before = scopeIn(collection, { ...values, ...write.before });\n const kind = frameKind(collection.item, write, collection.service.versionColumn);\n return moveOf(write.id, setOf(before), setOf(after), kind);\n}\n\n/** The moves of a column-scoped collection: `refresh` holds rows only an `affects` hop touched. */\nexport async function columnMoves(\n storage: StorageAdapter,\n collection: BoundCollection,\n writes: readonly WriteRecord[],\n refresh: readonly string[],\n): Promise<Moves> {\n const own = writes.filter((write) => modelKey(write.model) === collection.model);\n const known = own.map((write) => columnMove(collection, write, undefined));\n const unresolved = own.filter((_, index) => known[index] === undefined).map(({ id }) => id);\n const rows = await readRows(storage, collection, [...unresolved, ...refresh]);\n const moves: Move[] = [];\n for (const [index, write] of own.entries()) {\n // A row read as missing was deleted since: its own flush removes it.\n const move = known[index] ?? columnMove(collection, write, rows.get(write.id));\n if (move !== undefined) {\n moves.push(move);\n }\n }\n for (const id of refresh) {\n const scope = setOf(scopeIn(collection, rows.get(id)));\n moves.push(moveOf(id, scope, scope, WHOLE));\n }\n return { moves: moves.filter((move) => !isEmpty(move)), rows, resetAll: false };\n}\n\n/** The links a junction write made and removed, by entry. */\ninterface LinkEvents {\n readonly linked: Map<string, Set<string>>;\n readonly unlinked: Map<string, Set<string>>;\n /** Every entry a junction write named, whatever it changed: `refreshEntry` sends them again. */\n readonly named: Set<string>;\n /** Junction rows whose link the write does not carry: read them. */\n readonly unknown: string[];\n /** A junction row was removed without values. */\n resetAll: boolean;\n}\n\nfunction linkOf(via: Via, values: Values | undefined): readonly [string, string] | undefined {\n const entry = values?.[via.entry];\n const scope = values?.[via.scope];\n const valid = typeof entry === \"string\" && entry !== \"\" && typeof scope === \"string\";\n return valid && scope !== \"\" ? [entry, scope] : undefined;\n}\n\nfunction addLink(\n links: Map<string, Set<string>>,\n link: readonly [string, string] | undefined,\n): void {\n if (link !== undefined) {\n links.set(link[0], new Set([...(links.get(link[0]) ?? []), link[1]]));\n }\n}\n\nfunction linkEvents(via: Via, writes: readonly WriteRecord[]): LinkEvents {\n const events: LinkEvents = {\n linked: new Map(),\n unlinked: new Map(),\n named: new Set(),\n unknown: [],\n resetAll: false,\n };\n const name = (link: readonly [string, string] | undefined): void => {\n if (link !== undefined) {\n events.named.add(link[0]);\n }\n };\n for (const write of writes) {\n if (write.op === \"delete\") {\n const link = linkOf(via, write.before);\n addLink(events.unlinked, link);\n name(link);\n events.resetAll ||= link === undefined;\n continue;\n }\n const now = linkOf(via, write.after);\n if (now === undefined || write.fields.includes(ANY_FIELD)) {\n events.unknown.push(write.id);\n continue;\n }\n name(now);\n const moved = write.fields.some((field) => field === via.entry || field === via.scope);\n if (write.op === \"create\" || moved) {\n addLink(events.linked, now);\n }\n if (write.op === \"update\" && moved) {\n const old = linkOf(via, { ...write.after, ...write.before });\n addLink(events.unlinked, old);\n name(old);\n }\n }\n return events;\n}\n\n/** The current links of `ids` (rows of the junction), by entry. */\nasync function readLinks(\n storage: StorageAdapter,\n via: Via,\n where: Readonly<Record<string, unknown>>,\n): Promise<Map<string, Set<string>>> {\n const rows = await storage.findMany(modelKey(via.model), {\n where,\n select: { [via.entry]: true, [via.scope]: true },\n });\n const links = new Map<string, Set<string>>();\n for (const row of rows) {\n addLink(links, linkOf(via, row));\n }\n return links;\n}\n\ninterface ViaRow {\n readonly id: string;\n readonly write: WriteRecord | undefined;\n readonly links: ReadonlySet<string>;\n readonly row: StorageRow | undefined;\n readonly refreshed: boolean;\n}\n\n/** True when the collection declares a `where`: membership then needs the entry's values too. */\nfunction filtered(collection: BoundCollection): boolean {\n return Object.keys(collection.where).length > 0;\n}\n\n/**\n * A `via` entry's move: its links before the flush against its links now,\n * both filtered by `where`. A deleted entry left scopes nobody can name;\n * with `current` (behind a cluster adapter), the scopes it is linked to at\n * the read keep it. An entry created or touched is `added` to every scope it\n * is in now and `removed` from the ones it left.\n */\nfunction viaMove(\n collection: BoundCollection,\n events: LinkEvents,\n entry: ViaRow,\n current: boolean,\n): Move {\n const { id, write, links, row } = entry;\n const unlinked = events.unlinked.get(id) ?? NONE;\n const matches = (values: Values | undefined): boolean =>\n !filtered(collection) || (values !== undefined && matchesWhere(collection, values));\n const after = matches(row) ? links : NONE;\n if (write?.op === \"delete\") {\n return current\n ? movedTo(id, unlinked, NONE, after, true)\n : moveOf(id, unlinked, NONE, undefined, true);\n }\n const linked = events.linked.get(id) ?? NONE;\n const linksBefore = new Set([...[...links].filter((scope) => !linked.has(scope)), ...unlinked]);\n const before = matches(row === undefined ? undefined : { ...row, ...write?.before })\n ? linksBefore\n : NONE;\n if (write?.op === \"create\" || write?.fields.includes(ANY_FIELD) === true) {\n // Whole wherever it is now (an upsert where a client held it), gone where it left.\n return {\n id,\n left: [...before].filter((scope) => !after.has(scope)),\n entered: [...after],\n stayed: [],\n kind: WHOLE,\n unknownLeft: false,\n };\n }\n const changed = write !== undefined || entry.refreshed;\n // A refreshed entry's item changed beyond its own write (a count over the junction): whole.\n const kind =\n write === undefined || entry.refreshed\n ? WHOLE\n : frameKind(collection.item, write, collection.service.versionColumn);\n return moveOf(id, before, after, changed ? kind : undefined);\n}\n\n/**\n * One flush's moves per collection. The collection sink and the topic sink\n * (`../topics.ts`) both need them, and the rows a flush's moves read are read\n * once: the moves are kept by the flush's batch of writes, which every sink\n * of a flush receives as the same array, until it is garbage.\n */\nexport type FlushMoves = WeakMap<readonly WriteRecord[], Map<BoundCollection, Promise<Moves>>>;\n\n/**\n * The moves of `collection` in the flush of `writes`, found on the first\n * call for that flush and shared by every later one. `refresh` holds the\n * collection's rows only an `affects` hop touched; `current` is true behind\n * a cluster adapter.\n */\nexport function movesOf(\n memo: FlushMoves,\n storage: StorageAdapter,\n collection: BoundCollection,\n writes: readonly WriteRecord[],\n refresh: readonly string[],\n current = false,\n): Promise<Moves> {\n let flush = memo.get(writes);\n if (flush === undefined) {\n flush = new Map();\n memo.set(writes, flush);\n }\n let moves = flush.get(collection);\n if (moves === undefined) {\n moves =\n collection.scope.kind === \"column\"\n ? columnMoves(storage, collection, writes, refresh)\n : viaMoves(storage, collection, writes, refresh, current);\n flush.set(collection, moves);\n }\n return moves;\n}\n\n/**\n * The moves of a `via` collection: from its entry rows' writes, its\n * junction's writes and `affects` hops. With `current`, a deleted entry\n * linked to scopes at the read stays in them. With `refreshEntry`, every\n * entry a junction write named is sent again to the scopes it stayed in.\n */\nexport async function viaMoves(\n storage: StorageAdapter,\n collection: BoundCollection,\n writes: readonly WriteRecord[],\n refresh: readonly string[],\n current = false,\n): Promise<Moves> {\n const via = collection.scope as Via;\n const entries = new Map(\n writes.filter((write) => modelKey(write.model) === collection.model).map((w) => [w.id, w]),\n );\n const events = linkEvents(\n via,\n writes.filter((write) => modelKey(write.model) === modelKey(via.model)),\n );\n if (events.unknown.length > 0) {\n for (const [entry, scopes] of await readLinks(storage, via, { id: { in: events.unknown } })) {\n events.named.add(entry);\n for (const scope of scopes) {\n addLink(events.linked, [entry, scope]);\n }\n }\n }\n const refreshed = new Set([...refresh, ...(via.refreshEntry ? events.named : [])]);\n const ids = [\n ...new Set([\n ...entries.keys(),\n ...events.linked.keys(),\n ...events.unlinked.keys(),\n ...refreshed,\n ]),\n ];\n if (ids.length === 0) {\n return { moves: [], rows: new Map(), resetAll: events.resetAll };\n }\n // Without a `where`, links alone decide membership: items are read later, for subscribed scopes only.\n const [links, rows] = await Promise.all([\n readLinks(storage, via, { [via.entry]: { in: ids } }),\n filtered(collection) ? readRows(storage, collection, ids) : new Map<string, StorageRow>(),\n ]);\n const moves = ids.map((id) =>\n viaMove(\n collection,\n events,\n {\n id,\n write: entries.get(id),\n links: links.get(id) ?? NONE,\n row: rows.get(id),\n refreshed: refreshed.has(id),\n },\n current,\n ),\n );\n return { moves: moves.filter((move) => !isEmpty(move)), rows, resetAll: events.resetAll };\n}\n","// The collection deltas a flush cannot address to a scope, across a cluster\n// (RFC 0003 section 7.2, and the gap section 17 recorded for pack C): a row\n// removed without the values that place it (a `ctx.touch` with `removed`, a\n// `via` entry whose links a database cascade removed) left scopes nobody can\n// name, and junction rows removed without values make every scope of their\n// collection unsure. The flushing node sends `removed` (or `reset`) to every\n// scope it has subscribers in; other nodes' scopes are not visible to it.\n// Behind a cluster adapter it therefore also broadcasts what it could not\n// address, and every other node sends the same deltas to its own subscribed\n// scopes of the collection, to its own sockets only (a scope subscribed on\n// both nodes may get them twice; a `removed` or `reset` repeated changes\n// nothing on the client). A row that exists again when the flushing node\n// reads it (its id created again by a write whose flush went first) is not\n// removed from the scopes it is in at that read (`kept`): that node sends\n// it there itself.\n\nimport { collectionRoom, SERVER_EVENTS } from \"../../contract/names\";\nimport type { CollectionDelta, CollectionFrame, Revision } from \"../../protocol/envelope\";\nimport type { StorageRow } from \"../storage\";\nimport type { CollectionHub } from \"./bind\";\nimport type { BoundCollection } from \"./bind\";\nimport { scopeIn } from \"./items\";\nimport type { Move, Moves } from \"./moves\";\n\n/** The server-to-server event unaddressed deltas are broadcast on behind a cluster adapter. */\nexport const UNNAMED_EVENT = \"quickdraw:collection-unnamed\";\n\n/** What a flush could not address to a scope of one collection. */\nexport interface UnnamedDeltas {\n readonly s: string;\n readonly c: string;\n readonly rev: Revision;\n /** Rows that left scopes nobody can name: `removed` in every subscribed scope. */\n readonly removed: readonly string[];\n /** `[id, scope]`: a scope one of those rows is in at the flush's read, which keeps it. */\n readonly kept?: readonly (readonly [string, string])[];\n /** Junction rows went unseen: every subscribed scope resets. */\n readonly reset: boolean;\n}\n\n/**\n * The scopes a row that left scopes nobody can name is in at the flush's\n * read: its column's scope, or the `via` links its move found; none when the\n * row is gone.\n */\nfunction keptScopes(\n collection: BoundCollection,\n move: Move,\n row: StorageRow | undefined,\n): readonly string[] {\n if (row === undefined) {\n return [];\n }\n if (collection.scope.kind !== \"column\") {\n return [...move.entered, ...move.stayed];\n }\n const scope = scopeIn(collection, row);\n return typeof scope === \"string\" ? [scope] : [];\n}\n\n/**\n * What the moves of one collection could not address, or `undefined` when\n * they addressed everything. `rows`, the rows read for the flush's frames\n * behind a cluster adapter, name the scopes such a row is in again.\n */\nexport function unnamedOf(\n collection: BoundCollection,\n moves: Moves,\n rev: Revision,\n rows?: ReadonlyMap<string, StorageRow>,\n): UnnamedDeltas | undefined {\n const unknown = moves.moves.filter((move) => move.unknownLeft);\n if (unknown.length === 0 && !moves.resetAll) {\n return undefined;\n }\n const kept = unknown.flatMap((move) =>\n keptScopes(collection, move, rows?.get(move.id)).map((scope) => [move.id, scope] as const),\n );\n return {\n s: collection.service.name,\n c: collection.name,\n rev,\n removed: unknown.map((move) => move.id),\n ...(kept.length > 0 ? { kept } : {}),\n reset: moves.resetAll,\n };\n}\n\n/** Behind a cluster adapter, tells the other nodes what the flush could not address. */\nexport function broadcastUnnamed(hub: CollectionHub, unnamed: UnnamedDeltas | undefined): void {\n if (unnamed !== undefined && hub.io !== undefined && !hub.probe.local()) {\n hub.io.serverSideEmit(UNNAMED_EVENT, unnamed);\n }\n}\n\nfunction isPair(value: unknown): value is readonly [string, string] {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n typeof value[0] === \"string\" &&\n typeof value[1] === \"string\"\n );\n}\n\n/** A broadcast read, or `undefined` for anything malformed. */\nfunction readUnnamed(value: unknown): UnnamedDeltas | undefined {\n const { s, c, rev, removed, kept, reset } = (value ?? {}) as Readonly<Record<string, unknown>>;\n const ids = Array.isArray(removed) && removed.every((id) => typeof id === \"string\");\n const pairs = kept === undefined || (Array.isArray(kept) && kept.every(isPair));\n const valid = typeof s === \"string\" && typeof c === \"string\" && Number.isSafeInteger(rev) && ids;\n return valid && pairs && typeof reset === \"boolean\"\n ? {\n s,\n c,\n rev: rev as number,\n removed: removed as string[],\n ...(kept === undefined ? {} : { kept: kept as [string, string][] }),\n reset,\n }\n : undefined;\n}\n\n/** The deltas one scope gets of another node's unaddressed ones: none for a row it keeps. */\nfunction deltasFor(\n unnamed: UnnamedDeltas,\n kept: ReadonlySet<string>,\n scope: string,\n): CollectionDelta[] {\n if (unnamed.reset) {\n return [{ t: \"reset\" }];\n }\n return unnamed.removed\n .filter((id) => !kept.has(`${id}\\u0000${scope}`))\n .map((id) => ({ t: \"removed\", id }));\n}\n\n/** Sends another node's unaddressed deltas to every scope of the collection subscribed on this process. */\nfunction sendHere(hub: CollectionHub, unnamed: UnnamedDeltas): void {\n const { io } = hub;\n const collection = hub.collections.routes.find(unnamed.s, unnamed.c);\n if (io === undefined || collection === undefined) {\n return;\n }\n const kept = new Set((unnamed.kept ?? []).map(([id, scope]) => `${id}\\u0000${scope}`));\n for (const scope of hub.collections.scopes.scopes(unnamed.s, unnamed.c)) {\n const deltas = deltasFor(unnamed, kept, scope);\n if (deltas.length === 0) {\n continue;\n }\n const room = collectionRoom(unnamed.s, unnamed.c, scope);\n const frame: CollectionFrame = { s: unnamed.s, c: unnamed.c, scope, rev: unnamed.rev, deltas };\n io.local.to(room).emit(SERVER_EVENTS.collection, frame);\n if (unnamed.reset) {\n hub.collections.buffer.reset(room, unnamed.rev);\n } else {\n hub.collections.buffer.record(room, unnamed.rev, deltas);\n }\n }\n}\n\n/** Listens for the deltas other nodes could not address, on the server the live data was given. */\nexport function listenForUnnamed(hub: CollectionHub): void {\n hub.io?.on(UNNAMED_EVENT, (broadcast: unknown) => {\n const unnamed = readUnnamed(broadcast);\n if (unnamed !== undefined && (unnamed.reset || unnamed.removed.length > 0)) {\n sendHere(hub, unnamed);\n }\n });\n}\n","// Sending collection frames (RFC 0003 sections 5.3 and 7.2), and the scopes a\n// flush closes or resets rather than updates:\n//\n// - every frame goes to the scope's room as `qd:c { s, c, scope, rev,\n// deltas }`, and into the scope's resume buffer;\n// - deleting the row a scope is anchored on (a chat, for its messages) sends\n// `qd:revoked { kind: \"collection\", reason: \"anchor-deleted\" }` to every\n// scope room keyed by that row's id and empties those rooms: the rows a\n// database cascade removed with it produce no tracked writes, so closing\n// the scope is the whole answer, and nothing else goes to it;\n// - when the flush failed (this sink or another one), every scope its writes\n// name gets a `reset`, and a collection whose writes name no scope (a\n// touch, a `via` entry) resets every scope subscribed on this process, and\n// behind a cluster adapter on every other node (`unnamed.ts`);\n// - a collection nobody on this process subscribes to (with rooms visible\n// here) reads and sends nothing: the scopes its writes name lose their\n// resume from before the flush, and a write that names none (a touch, a\n// `via` entry, an `affects` hop) costs the whole collection its resume.\n//\n// 4.1 offered these as hand-written calls (`emitCollectionReset`,\n// `kickFromCollection`; 4.1 `src/server/collections.ts:300-318`).\n\nimport { collectionRoom, SERVER_EVENTS } from \"../../contract/names\";\nimport type { CollectionDelta, CollectionFrame, Revision } from \"../../protocol/envelope\";\nimport { modelKey } from \"../storage\";\nimport type { WriteRecord } from \"../uow/types\";\nimport { anchoredScopes, type BoundCollection, type CollectionHub } from \"./bind\";\nimport { groupOf } from \"./scopes\";\nimport { broadcastUnnamed } from \"./unnamed\";\n\ntype Io = NonNullable<CollectionHub[\"io\"]>;\n\n/** Sends one scope's frame for a flush and keeps it for resumes; a `reset` frame resets the buffer. */\nexport function sendFrame(\n hub: CollectionHub,\n io: Io | undefined,\n collection: BoundCollection,\n scope: string,\n rev: Revision,\n deltas: readonly CollectionDelta[],\n): void {\n if (deltas.length === 0) {\n return;\n }\n const s = collection.service.name;\n const room = collectionRoom(s, collection.name, scope);\n const frame: CollectionFrame = { s, c: collection.name, scope, rev, deltas };\n io?.to(room).emit(SERVER_EVENTS.collection, frame);\n if (deltas.some((delta) => delta.t === \"reset\")) {\n hub.collections.buffer.reset(room, rev);\n } else {\n hub.collections.buffer.record(room, rev, deltas);\n }\n}\n\n/** Revokes every subscription to one scope whose anchor row was deleted, and empties its room. */\nfunction closeScope(\n hub: CollectionHub,\n io: Io,\n collection: BoundCollection,\n scope: string,\n rev: Revision,\n): void {\n const s = collection.service.name;\n const room = collectionRoom(s, collection.name, scope);\n hub.collections.buffer.reset(room, rev);\n const local = [...(io.sockets.adapter.rooms.get(room) ?? [])];\n if (local.length === 0 && hub.probe.local()) {\n return;\n }\n io.to(room).emit(SERVER_EVENTS.revoked, {\n kind: \"collection\",\n reason: \"anchor-deleted\",\n s,\n c: collection.name,\n scope,\n });\n for (const socketId of local) {\n const socket = io.sockets.sockets.get(socketId);\n if (socket !== undefined) {\n hub.collections.scopes.delete(socket, room);\n }\n }\n // Behind a cluster adapter, the other nodes' sockets leave too.\n io.in(room).socketsLeave(room);\n}\n\n/** Closes the scopes keyed by each row the flush deleted that collections are anchored on; returns their rooms. */\nexport function closeAnchors(\n hub: CollectionHub,\n io: Io,\n writes: readonly WriteRecord[],\n rev: Revision,\n): Set<string> {\n const closed = new Set<string>();\n for (const [collection, scope] of anchoredScopes(hub.collections.routes, writes)) {\n closed.add(collectionRoom(collection.service.name, collection.name, scope));\n closeScope(hub, io, collection, scope, rev);\n }\n return closed;\n}\n\n/**\n * The scopes a write's values name in a collection, or `undefined` when they\n * name none: an entry's own write in a `via` collection, and with\n * `refreshEntry` a junction write too, which changes its entry in every\n * scope that holds it.\n */\nfunction namedScopes(collection: BoundCollection, write: WriteRecord): string[] | undefined {\n const { scope } = collection;\n const junction = scope.kind === \"via\" && modelKey(write.model) === modelKey(scope.model);\n if (scope.kind === \"via\" && (!junction || scope.refreshEntry)) {\n return undefined;\n }\n const column = scope.kind === \"column\" ? scope.column : scope.scope;\n const named = [write.before?.[column], write.after?.[column]].filter(\n (value): value is string => typeof value === \"string\" && value.length > 0,\n );\n return named.length === 0 ? undefined : named;\n}\n\n/**\n * The flush changed a collection nobody here subscribes to: no frame, and no\n * resume from before it of the scopes it changed. `refresh` are rows only an\n * `affects` hop touched.\n */\nexport function skipTouched(\n hub: CollectionHub,\n collection: BoundCollection,\n writes: readonly WriteRecord[],\n refresh: readonly string[],\n rev: Revision,\n): void {\n const s = collection.service.name;\n const { scope } = collection;\n const junction = scope.kind === \"via\" ? modelKey(scope.model) : undefined;\n const concerns = (write: WriteRecord): boolean => {\n const model = modelKey(write.model);\n return model === collection.model || model === junction;\n };\n let unnamed = refresh.length > 0;\n for (const write of writes.filter(concerns)) {\n const named = namedScopes(collection, write);\n unnamed ||= named === undefined;\n for (const value of named ?? []) {\n hub.collections.buffer.skip(collectionRoom(s, collection.name, value), rev);\n }\n }\n if (unnamed) {\n hub.collections.buffer.skipAll(groupOf(s, collection.name));\n }\n}\n\n/** Sends a `reset` to every scope the flush's writes touched: the flush failed. */\nexport function resetTouched(\n hub: CollectionHub,\n io: Io,\n writes: readonly WriteRecord[],\n rev: Revision,\n): void {\n const touched = new Map<BoundCollection, Set<string>>();\n const unnamed = new Set<BoundCollection>();\n const { routes } = hub.collections;\n for (const write of writes) {\n const key = modelKey(write.model);\n for (const collection of [\n ...(routes.byModel.get(key) ?? []),\n ...(routes.byJunction.get(key) ?? []),\n ]) {\n const named = namedScopes(collection, write);\n if (named === undefined) {\n unnamed.add(collection);\n }\n const scopes =\n named ?? hub.collections.scopes.scopes(collection.service.name, collection.name);\n touched.set(collection, new Set([...(touched.get(collection) ?? []), ...scopes]));\n }\n }\n for (const [collection, scopes] of touched) {\n for (const scope of scopes) {\n sendFrame(hub, io, collection, scope, rev, [{ t: \"reset\" }]);\n }\n }\n for (const collection of unnamed) {\n const { name: s } = collection.service;\n broadcastUnnamed(hub, { s, c: collection.name, rev, removed: [], reset: true });\n }\n}\n","// The collection sink (RFC 0003 sections 5.3 and 7.2): what a flush does for\n// collection subscribers. It goes after the access and entity sinks on the\n// dispatcher's list, so a socket a flush revoked never gets its deltas. It\n// replaces 4.1's `notify` (4.1 `src/server/collections.ts:205-270`), which\n// only `this.create/update/delete` called, after reading the whole row first\n// (4.1 `src/server/BaseService.ts:741-751`).\n//\n// Per flush:\n//\n// 1. close the scopes anchored on rows the flush deleted (`send.ts`);\n// 2. per collection the writes concern (its model, its `via` junction, or an\n// `affects` hop onto its service), find each row's moves (`moves.ts`),\n// reading only rows whose write does not carry the values that decide\n// membership; the topic sink (`../topics.ts`) reuses them;\n// 3. per scope, batch the moves' deltas into one plan, or one `reset` past\n// `bulkThreshold` (`deltas.ts`);\n// 4. leave out scopes nobody here subscribes to, which raises their resume\n// floor instead; behind a cluster adapter other nodes' rooms are not\n// visible, so every scope is sent, and what no scope could be named for\n// (a removal without its scope, junction rows removed without values) is\n// broadcast for the other nodes' subscribed scopes (`unnamed.ts`);\n// 5. read the items the remaining deltas need, in one query per collection,\n// and send one `qd:c` frame per scope, which the resume buffer keeps. An\n// indexed collection's `added` deltas carry index rows built from those\n// items (`index.ts`). Behind a cluster adapter the same read also takes\n// the rows of removals, and each delta is decided by its row as read\n// then (`deltas.ts`): a write that committed first can flush last.\n//\n// A collection with no subscriber on this process (and rooms visible here)\n// skips steps 2 to 5 and reads nothing (`skipTouched`).\n//\n// A failure sends a `reset` to the touched scopes and is rethrown to be\n// logged; another sink's failure does the same through `onFlushError`.\n\nimport { touchedRows, type TouchedRows } from \"../emit/affects\";\nimport { modelKey, type StorageAdapter } from \"../storage\";\nimport type { FlushInfo, FlushSink } from \"../uow/flushSink\";\nimport type { WriteRecord } from \"../uow/types\";\nimport type { BoundCollection, CollectionHub } from \"./bind\";\nimport { buildDeltas, planScopes, readItems, type ScopePlan } from \"./deltas\";\nimport { movesOf } from \"./moves\";\nimport { closeAnchors, resetTouched, sendFrame, skipTouched } from \"./send\";\nimport { broadcastUnnamed, unnamedOf } from \"./unnamed\";\n\ntype Io = NonNullable<CollectionHub[\"io\"]>;\n\n/** One collection's share of a flush. */\nexport interface Work {\n readonly collection: BoundCollection;\n /** Rows of its service only an `affects` hop touched: their items are sent again. */\n readonly refresh: readonly string[];\n}\n\n/** The collections the flush concerns, with the rows of each that only an `affects` hop touched. */\nexport function workOf(\n hub: CollectionHub,\n writes: readonly WriteRecord[],\n touched: TouchedRows,\n): Work[] {\n const { routes } = hub.collections;\n const concerned = new Set<BoundCollection>();\n for (const write of writes) {\n const key = modelKey(write.model);\n for (const collection of [\n ...(routes.byModel.get(key) ?? []),\n ...(routes.byJunction.get(key) ?? []),\n ]) {\n concerned.add(collection);\n }\n }\n for (const service of touched.keys()) {\n for (const name of service.collections.keys()) {\n const collection = routes.find(service.name, name);\n if (collection !== undefined) {\n concerned.add(collection);\n }\n }\n }\n return [...concerned].map((collection) => {\n const written = new Set(\n writes.filter((write) => modelKey(write.model) === collection.model).map(({ id }) => id),\n );\n const rows = touched.get(collection.service)?.keys() ?? [];\n return { collection, refresh: [...rows].filter((id) => !written.has(id)) };\n });\n}\n\n/** True when a socket of this process is in the room, or rooms cannot be seen here (a cluster adapter). */\nfunction occupied(hub: CollectionHub, io: Io, room: string): boolean {\n return !hub.probe.local() || (io.sockets.adapter.rooms.get(room)?.size ?? 0) > 0;\n}\n\n/** Steps 2 to 5 for one collection. */\nasync function emitCollection(\n hub: CollectionHub,\n io: Io,\n storage: StorageAdapter,\n work: Work,\n writes: readonly WriteRecord[],\n rev: number,\n closed: ReadonlySet<string>,\n): Promise<void> {\n const { collection, refresh } = work;\n const subscribed = hub.collections.scopes.scopes(collection.service.name, collection.name);\n const cluster = !hub.probe.local();\n if (subscribed.length === 0 && !cluster) {\n skipTouched(hub, collection, writes, refresh, rev);\n return;\n }\n const moves = await movesOf(hub.collections.moves, storage, collection, writes, refresh, cluster);\n const sending: ScopePlan[] = [];\n for (const plan of planScopes(collection, moves, subscribed)) {\n if (closed.has(plan.room)) {\n continue;\n }\n if (occupied(hub, io, plan.room)) {\n sending.push(plan);\n } else {\n hub.collections.buffer.skip(plan.room, rev);\n }\n }\n // Behind a cluster adapter, changes go out whole (frames of two nodes can arrive out of\n // order), decided by the rows read now; the rows of removals no scope could be named for\n // are read too, so the other nodes keep such a row where it is again.\n const unnamed = cluster ? moves.moves.filter((move) => move.unknownLeft) : [];\n if (sending.length === 0 && unnamed.length === 0) {\n broadcastUnnamed(hub, unnamedOf(collection, moves, rev));\n return;\n }\n const also = unnamed.map((move) => move.id);\n const rows = await readItems(storage, collection, sending, moves.rows, cluster, also);\n // What no scope could be named for reaches the scopes subscribed on the other nodes too.\n broadcastUnnamed(hub, unnamedOf(collection, moves, rev, cluster ? rows : undefined));\n for (const plan of sending) {\n const deltas = buildDeltas(collection, plan, rows, rev, cluster);\n sendFrame(hub, io, collection, plan.scope, rev, deltas);\n }\n}\n\nasync function emitFlush(\n hub: CollectionHub,\n io: Io,\n storage: StorageAdapter,\n writes: readonly WriteRecord[],\n rev: number,\n): Promise<void> {\n const closed = closeAnchors(hub, io, writes, rev);\n const work = workOf(hub, writes, touchedRows(writes, hub.routes));\n await Promise.all(work.map((one) => emitCollection(hub, io, storage, one, writes, rev, closed)));\n}\n\n/** The collection sink of a dispatcher. */\nexport function createCollectionSink(hub: CollectionHub): FlushSink {\n return Object.freeze({\n async flush(writes: readonly WriteRecord[], info: FlushInfo): Promise<void> {\n const { io, storage } = hub;\n if (io === undefined || storage === undefined) {\n return;\n }\n try {\n await emitFlush(hub, io, storage, writes, info.rev);\n } catch (error) {\n resetTouched(hub, io, writes, info.rev);\n throw error;\n }\n },\n onFlushError(writes: readonly WriteRecord[], info: FlushInfo): void {\n if (hub.io !== undefined) {\n resetTouched(hub, hub.io, writes, info.rev);\n }\n },\n });\n}\n","// The shared revision counter of a cluster (pack H, child 2): one key in the\n// Valkey (or Redis) behind the Socket.IO adapter, which every node takes its\n// flush revisions from, so revisions from different nodes are one total\n// order instead of clocks that agree only within their skew.\n//\n// The counter keeps to the clock revisions are read against: a script makes\n// it `max(last + 1, the server's time in microseconds, the caller's floor +\n// 1)` in one round trip. In microseconds it moves past the clock only above\n// a million flushes a second across the cluster, so revisions a client\n// holds and the `versionColumn` times \"not modified\" compares them with\n// stay comparable (`../rev.ts`), and a node never gets a revision below one\n// it issued. Reading it (`current`) is one GET; a key Valkey does not have\n// is unknown, never 0.\n//\n// The key has no TTL and must survive Valkey restarts and failovers\n// (persistence or replication). When it is lost anyway, the script starts\n// it again at the server's clock, above the node's floor: since the counter\n// kept to the clock, that is above every revision issued before, unless the\n// clock stepped back. A node that sees the key gone after it had seen it\n// logs a warning.\n//\n// Valkey may stop answering. A command that fails, or does not answer within\n// `timeoutMs`, makes the counter answer `undefined` (the caller falls back to\n// its own clock) and logs one error. While it is degraded no call sends a\n// command or waits: a call made once `RETRY_MS` passed (with the client\n// connected) starts one probe in the background (a GET), and the probe that\n// answers ends the outage, logging that the counter is back.\n\nimport { createHash } from \"node:crypto\";\nimport type { Logger } from \"../../contract/logger\";\nimport type { Revision } from \"../../protocol/envelope\";\nimport { describeError } from \"../pipeline/metrics\";\nimport { DEFAULT_CLUSTER_TIMEOUT_MS, within } from \"./acks\";\n\n/**\n * A Valkey or Redis client the cluster helpers send commands through: a\n * node-redis client (`redis` 4 to 6) as it is, or an ioredis one through\n * {@link clusterClientOf}.\n */\nexport interface ClusterClient {\n /** Sends one command, `[\"GET\", key]`, and resolves with its reply. */\n sendCommand(args: string[]): Promise<unknown>;\n /** False while the client is not connected; commands sent then would wait in its queue. */\n readonly isReady?: boolean;\n}\n\n/**\n * The counter script: the next revision, above the caller's floor and never\n * below the server's clock in microseconds, and whether the key was there\n * (`[revision, 1 | 0]`).\n */\nexport const REVISION_SCRIPT = [\n \"if redis.replicate_commands then redis.replicate_commands() end\",\n \"local time = redis.call('TIME')\",\n \"local now = tonumber(time[1]) * 1000000 + tonumber(time[2])\",\n \"local held = redis.call('GET', KEYS[1])\",\n \"local last = tonumber(held or '0')\",\n \"local floor = tonumber(ARGV[1]) or 0\",\n \"local rev = math.max(last + 1, now, floor + 1)\",\n \"return { redis.call('INCRBY', KEYS[1], rev - last), held and 1 or 0 }\",\n].join(\"\\n\");\n\nconst REVISION_SCRIPT_SHA = createHash(\"sha1\").update(REVISION_SCRIPT).digest(\"hex\");\n\n/** How long a degraded counter waits before it probes Valkey again. */\nexport const RETRY_MS = 1000;\n\n/** A cluster's shared revision counter, as one node sees it. */\nexport interface SharedCounter {\n /**\n * A new revision: the counter, moved past `floor` (the last revision this\n * node issued) and the server's clock. `undefined` when Valkey did not\n * answer: the node then uses its own clock.\n */\n next(floor: Revision): Promise<Revision | undefined>;\n /**\n * The counter's last revision; `null` when Valkey does not have the key\n * (no flush took one since the key was made or lost: unknown), and\n * `undefined` when Valkey did not answer.\n */\n current(): Promise<Revision | null | undefined>;\n /** True while Valkey is not answering. */\n degraded(): boolean;\n}\n\n/** Options of {@link createSharedCounter}. */\nexport interface SharedCounterOptions {\n readonly client: ClusterClient;\n readonly key: string;\n readonly logger: Logger;\n readonly timeoutMs?: number;\n /** The clock retries are timed with; tests pass their own. */\n readonly now?: () => number;\n}\n\n/** A reply that should be a whole number of microseconds, read. */\nfunction revisionIn(reply: unknown): Revision {\n const value = typeof reply === \"string\" ? Number(reply) : reply;\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n throw new TypeError(`the counter answered ${String(reply)}, not a revision`);\n }\n return value;\n}\n\n/** The script's reply, read: the revision, and whether the key was there. */\nfunction scriptReply(reply: unknown): { readonly rev: Revision; readonly held: boolean } {\n if (!Array.isArray(reply) || reply.length !== 2) {\n throw new TypeError(`the counter answered ${String(reply)}, not [revision, held]`);\n }\n return { rev: revisionIn(reply[0]), held: Number(reply[1]) === 1 };\n}\n\nfunction noScript(error: unknown): boolean {\n return error instanceof Error && error.message.startsWith(\"NOSCRIPT\");\n}\n\n/** A counter's outages: one error each, a probe in the background, one info at the end. */\ninterface Outages {\n /** True while Valkey is not answering. */\n readonly down: () => boolean;\n /** A command failed or did not answer: the counter is degraded (logged once). */\n failed(error: unknown): undefined;\n /** While degraded: one GET in the background once the retry delay passed; nothing waits on it. */\n probe(): void;\n}\n\nfunction createOutages(\n options: SharedCounterOptions,\n timeoutMs: number,\n now: () => number,\n): Outages {\n const { client, key, logger } = options;\n let down = false;\n let retryAt = 0;\n let probing = false;\n const recovered = (): void => {\n if (down) {\n down = false;\n logger.info(\"The shared revision counter answers again\", {\n category: \"quickdraw.cluster\",\n key,\n });\n }\n };\n return {\n down: () => down,\n failed(error: unknown): undefined {\n retryAt = now() + RETRY_MS;\n if (!down) {\n down = true;\n logger.error(\n \"The shared revision counter did not answer; this node takes revisions from its own clock until it does\",\n { category: \"quickdraw.cluster\", key, error: describeError(error) },\n );\n }\n return undefined;\n },\n probe(): void {\n if (probing || now() < retryAt || client.isReady === false) {\n return;\n }\n probing = true;\n retryAt = now() + RETRY_MS;\n void within(\n Promise.resolve().then(() => client.sendCommand([\"GET\", key])),\n timeoutMs,\n )\n .then(recovered, () => {\n retryAt = now() + RETRY_MS;\n })\n .finally(() => {\n probing = false;\n });\n },\n };\n}\n\n/** Creates the counter at `key`, sending its commands through `client`. */\nexport function createSharedCounter(options: SharedCounterOptions): SharedCounter {\n const { client, key, logger } = options;\n const timeoutMs = options.timeoutMs ?? DEFAULT_CLUSTER_TIMEOUT_MS;\n const outages = createOutages(options, timeoutMs, options.now ?? Date.now);\n /** This node saw the key: a script that finds it missing means it was lost. */\n let seen = false;\n\n const send = async (args: string[]): Promise<unknown> => {\n if (outages.down()) {\n outages.probe();\n return undefined;\n }\n if (client.isReady === false) {\n return outages.failed(new Error(\"the client is not connected\"));\n }\n try {\n return await within(\n Promise.resolve().then(() => client.sendCommand(args)),\n timeoutMs,\n );\n } catch (error) {\n if (noScript(error)) {\n throw error;\n }\n return outages.failed(error);\n }\n };\n\n /** A revision from the script's reply, saying when the key it saw was lost. */\n const revisionOf = (reply: unknown): Revision | undefined => {\n try {\n const { rev, held } = scriptReply(reply);\n if (!held && seen) {\n logger.warn(\n \"The revision counter key was lost; configure persistence or replication for it\",\n { category: \"quickdraw.cluster\", key, rev },\n );\n }\n seen = true;\n return rev;\n } catch (error) {\n return outages.failed(error);\n }\n };\n\n return Object.freeze({\n async next(floor: Revision): Promise<Revision | undefined> {\n const floorArg = String(Math.max(0, Math.floor(floor)));\n let reply: unknown;\n try {\n reply = await send([\"EVALSHA\", REVISION_SCRIPT_SHA, \"1\", key, floorArg]);\n } catch {\n // The script is not cached on this server yet (or any more): send it whole.\n reply = await send([\"EVAL\", REVISION_SCRIPT, \"1\", key, floorArg]);\n }\n return reply === undefined ? undefined : revisionOf(reply);\n },\n async current(): Promise<Revision | null | undefined> {\n const reply = await send([\"GET\", key]);\n if (reply === undefined || reply === null) {\n return reply;\n }\n try {\n const rev = revisionIn(reply);\n seen = true;\n return rev;\n } catch (error) {\n return outages.failed(error);\n }\n },\n degraded: () => outages.down(),\n });\n}\n\n/**\n * The client `value` stands for, or `undefined`: a node-redis client (it has\n * `sendCommand(args)` and `isReady`), or an ioredis one (`call` and\n * `status`), wrapped to look the same.\n */\nexport function clusterClientOf(value: unknown): ClusterClient | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const candidate = value as {\n readonly call?: unknown;\n readonly status?: unknown;\n readonly sendCommand?: unknown;\n };\n if (typeof candidate.call === \"function\" && typeof candidate.status === \"string\") {\n const call = candidate.call as (command: string, ...args: string[]) => Promise<unknown>;\n return {\n sendCommand: ([command = \"\", ...args]) => call.call(value, command, ...args),\n get isReady() {\n return (value as { readonly status: unknown }).status === \"ready\";\n },\n };\n }\n if (typeof candidate.sendCommand === \"function\") {\n return value as ClusterClient;\n }\n return undefined;\n}\n","// The revisions of one dispatcher's live data (RFC 0003 section 5.3, step 2,\n// and pack H's shared flush order). On one server they are the process's\n// clock (`../rev.ts`), as they always were. Behind a cluster adapter whose\n// Valkey (or Redis) client the server can reach (the Socket.IO Redis\n// adapter's publishing client, or `cluster.client`), they come from the\n// cluster's shared counter (`counter.ts`) instead:\n//\n// - a flush asks the counter for its revision the moment it is handed to\n// the dispatcher's sinks, one round trip, and its sinks run once it\n// answered, still in arrival order (`../uow/flush.ts`), so a payload is\n// never older than its revision claims and frames leave each process in\n// revision order; across nodes, revisions are one total order;\n// - a read that claims a revision (a subscription's rows, a page, a search,\n// a row sent again after a level change) reads the counter first: the\n// last revision any node took, so a write with a revision up to it\n// committed before the read, and any later one gets a greater one. The\n// process's own last revision would not do: a quiet node's is old, and a\n// client holding a newer frame from another node would keep its stale row;\n// - when Valkey does not answer, the node falls back to its own clock (one\n// error logged per outage), still never below a revision it issued, and\n// reads claim its clock too (`max(now, the last revision this process\n// took, the last it issued)`): comparisons with other nodes' hold within\n// the skew between this node's clock and Valkey's (the counter keeps to\n// Valkey's clock) until the counter answers again. A key Valkey does not\n// have (none taken since it was made or lost) is read the same way, never\n// as 0.\n\nimport type { Logger } from \"../../contract/logger\";\nimport type { Revision } from \"../../protocol/envelope\";\nimport { clockRev, currentRev, nextRev, observeRev } from \"../rev\";\nimport type { QuickdrawIo } from \"../transports/types\";\nimport {\n clusterClientOf,\n createSharedCounter,\n type ClusterClient,\n type SharedCounter,\n} from \"./counter\";\n\nexport type { ClusterBroadcasts } from \"./broadcasts\";\nexport type { ClusterClient } from \"./counter\";\n\n/** An ioredis client, as the cluster helpers use one. */\nexport interface IoRedisLike {\n call(command: string, ...args: string[]): Promise<unknown>;\n readonly status: string;\n}\n\n/** `createServer`'s `cluster` option: where a cluster's shared state lives, behind a cluster adapter. */\nexport interface ClusterOptions {\n /**\n * The Valkey or Redis client of the shared revision counter and of the\n * users' last-seen times: a node-redis or ioredis client. Default: the\n * publishing client of the Socket.IO Redis adapter (`setupRedisAdapter`,\n * or `createAdapter(pub, sub)` in `socket.adapter`). Without one, behind\n * another adapter, revisions stay per process.\n */\n readonly client?: ClusterClient | IoRedisLike;\n /** The prefix of the cluster's keys (`{keyPrefix}:rev`, `{keyPrefix}:seen:{userId}`). Default `\"quickdraw\"`. */\n readonly keyPrefix?: string;\n /**\n * How long a counter command may take before the node takes its revision\n * from its own clock, in milliseconds. Default 1,000.\n */\n readonly timeoutMs?: number;\n}\n\n/** What the revisions read of the hub they belong to. */\nexport interface RevisionHub {\n readonly io: QuickdrawIo | undefined;\n readonly probe: { local(): boolean };\n readonly logger: Logger;\n cluster: ClusterOptions | undefined;\n}\n\n/** The revisions of one dispatcher. */\nexport interface Revisions {\n /**\n * Called when a flush is handed to the sinks: `undefined` when revisions\n * are the process's (the flush keeps the one it took), else a function to\n * call when the flush's turn comes, which resolves with its revision.\n */\n forFlush(): (() => Promise<Revision>) | undefined;\n /**\n * The revision a read made from now on is no older than: at once on one\n * server; behind a counter its last revision, or the clock's when it does\n * not answer or has no key. Never 0.\n */\n claim(): Revision | Promise<Revision>;\n /** Behind a counter, the counter's revision when it moved past `rev`; `undefined` otherwise. */\n movedPast(rev: Revision): Promise<Revision | undefined>;\n /** True when revisions come from the cluster's counter: the process's change log sees only its own flushes. */\n shared(): boolean;\n /** The counter, when there is one: a user's last-seen time lives beside it. */\n counterClient(): { readonly client: ClusterClient; readonly keyPrefix: string } | undefined;\n}\n\n/** The default prefix of a cluster's keys. */\nexport const DEFAULT_KEY_PREFIX = \"quickdraw\";\n\n/** A cluster client found for the hub: as given, and as the helpers use it. */\ninterface Found {\n readonly raw: object;\n readonly client: ClusterClient;\n readonly keyPrefix: string;\n}\n\n/** Creates the revisions of the hub. */\nexport function createRevisions(hub: RevisionHub): Revisions {\n const found = new WeakMap<object, Found>();\n const counters = new WeakMap<object, SharedCounter>();\n /** The highest revision this dispatcher gave a flush: the floor of its next one. */\n let issued = 0;\n\n /** The cluster's client: `cluster.client`, or the Redis adapter's publishing client. */\n const target = (): Found | undefined => {\n if (hub.probe.local()) {\n return undefined;\n }\n const adapter = hub.io?.sockets.adapter as { readonly pubClient?: unknown } | undefined;\n const raw: unknown = hub.cluster?.client ?? adapter?.pubClient;\n if (typeof raw !== \"object\" || raw === null) {\n return undefined;\n }\n let entry = found.get(raw);\n const client = entry === undefined ? clusterClientOf(raw) : entry.client;\n if (entry === undefined && client !== undefined) {\n entry = { raw, client, keyPrefix: hub.cluster?.keyPrefix ?? DEFAULT_KEY_PREFIX };\n found.set(raw, entry);\n }\n return entry;\n };\n\n const counterOf = (): SharedCounter | undefined => {\n const entry = target();\n if (entry === undefined) {\n return undefined;\n }\n let counter = counters.get(entry.raw);\n if (counter === undefined) {\n counter = createSharedCounter({\n client: entry.client,\n key: `${entry.keyPrefix}:rev`,\n logger: hub.logger,\n timeoutMs: hub.cluster?.timeoutMs,\n });\n counters.set(entry.raw, counter);\n }\n return counter;\n };\n\n /** The flush's revision: the counter's answer, or the clock's; above every one issued before. */\n const assign = (answer: Revision | undefined): Revision => {\n const rev = Math.max(answer ?? nextRev(), issued + 1);\n issued = rev;\n observeRev(rev);\n return rev;\n };\n\n /** The revision a read claims: the counter's, or without one (no answer, no key) the clock's. */\n const fresh = (value: Revision | null | undefined): Revision => {\n const rev = Math.max(value ?? Math.max(clockRev(), currentRev()), issued);\n observeRev(rev);\n return rev;\n };\n\n return Object.freeze({\n forFlush() {\n const counter = counterOf();\n if (counter === undefined) {\n return undefined;\n }\n // Asked now, in arrival order: one connection answers in order.\n const answer = counter.next(issued);\n return async () => assign(await answer);\n },\n claim() {\n const counter = counterOf();\n return counter === undefined ? currentRev() : counter.current().then(fresh);\n },\n async movedPast(rev: Revision) {\n // No answer: nothing reaches this node from the others either. No key: no node took a\n // revision since it was made or lost.\n const value = await counterOf()?.current();\n return typeof value === \"number\" && value > rev ? fresh(value) : undefined;\n },\n shared: () => counterOf() !== undefined,\n counterClient: () => {\n const entry = target();\n return entry === undefined ? undefined : { client: entry.client, keyPrefix: entry.keyPrefix };\n },\n });\n}\n","// The in-process change log (RFC 0003 section 6): the revision of the last\n// flush that touched each row, since the process started. It answers \"not\n// modified\" for services without a `versionColumn`: a caller holding a row\n// at revision `v` gets \"not modified\" when no flush since `v` touched it.\n//\n// It is bounded: past `maxEntries` rows the least recently changed one is\n// dropped, and the log then knows only that the dropped row did not change\n// after the newest revision it has dropped (its floor). It starts with a\n// floor of the revision current when it was made, so a revision from before\n// the process started is never answered \"not modified\".\n//\n// It sees the writes this process flushes and nothing else: not raw SQL\n// without `ctx.touch`, not database cascades, not other processes. A\n// deployment of several processes behind a load balancer stops it answering\n// (`changeLog: false`) or gives its services a `versionColumn`; behind a\n// Socket.IO cluster adapter it never answers. It is kept either way:\n// subscriptions also use it to tell a deleted row from a forbidden one, and\n// to catch a flush that raced a subscribe.\n\nimport type { Revision } from \"../../protocol/envelope\";\nimport { nextRev } from \"../rev\";\n\n/** The change log's options: `false` turns it off. */\nexport interface ChangeLogOptions {\n /** How many rows it keeps. Default 100,000. */\n readonly maxEntries?: number;\n}\n\ninterface Entry {\n readonly rev: Revision;\n /** The row's last recorded write deleted it. */\n readonly removed: boolean;\n}\n\n/** The last flush revision per row. */\nexport interface ChangeLog {\n /** Records that the flush at `rev` wrote the row; `removed` when that write deleted it. */\n record(service: string, id: string, rev: Revision, removed: boolean): void;\n /** The revision of the row's last recorded change, or the floor when none is kept. */\n lastChange(service: string, id: string): Revision;\n /** True when the row's last recorded change deleted it. */\n removed(service: string, id: string): boolean;\n /** True when no flush this process saw since `rev` touched the row. */\n unchangedSince(service: string, id: string, rev: Revision): boolean;\n}\n\nconst DEFAULT_MAX_ENTRIES = 100_000;\n\nfunction keyOf(service: string, id: string): string {\n return `${service}\\u0000${id}`;\n}\n\n/** Creates a change log, starting at the revision current now. */\nexport function createChangeLog(options: ChangeLogOptions = {}): ChangeLog {\n const max = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n if (!Number.isSafeInteger(max) || max < 1) {\n throw new TypeError(\"createDispatcher: changeLog.maxEntries must be a positive whole number\");\n }\n const entries = new Map<string, Entry>();\n let floor = nextRev();\n const lastChange = (service: string, id: string): Revision =>\n entries.get(keyOf(service, id))?.rev ?? floor;\n return Object.freeze({\n record(service: string, id: string, rev: Revision, removed: boolean): void {\n const key = keyOf(service, id);\n const kept = entries.get(key);\n // Flushes can finish out of order; the newest revision wins.\n const entry = kept !== undefined && kept.rev > rev ? kept : { rev, removed };\n entries.delete(key);\n entries.set(key, entry);\n const first = entries.size > max ? entries.entries().next() : undefined;\n if (first !== undefined && first.done !== true) {\n const [oldest, dropped] = first.value;\n entries.delete(oldest);\n floor = Math.max(floor, dropped.rev);\n }\n },\n lastChange,\n removed: (service: string, id: string) => entries.get(keyOf(service, id))?.removed === true,\n unchangedSince: (service: string, id: string, rev: Revision) => lastChange(service, id) <= rev,\n });\n}\n","// What the live-data modules of one dispatcher share (RFC 0003 sections 4.4,\n// 5.3 and 6): the services and how writes reach them, the storage adapter\n// rows are read through, the policies levels come from, the change log, the\n// index of this process's subscriptions, and, once a server attaches it, the\n// Socket.IO server frames go out on.\n\nimport type { Logger } from \"../../contract/logger\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { AccessEngine, PolicyEngine } from \"../access/api\";\nimport {\n createRevisions,\n type ClusterBroadcasts,\n type ClusterOptions,\n type Revisions,\n} from \"../cluster/revisions\";\nimport type { Registry } from \"../registry\";\nimport type { StorageAdapter } from \"../storage\";\nimport type { QuickdrawIo } from \"../transports/types\";\nimport { routesOf, type Routes } from \"./affects\";\nimport { createChangeLog, type ChangeLog, type ChangeLogOptions } from \"./changeLog\";\nimport { SubscriptionIndex } from \"./subscriptions\";\n\n/** Whether every subscriber of this server is a socket of this process. */\nexport interface AdapterProbe {\n /**\n * True while the server's Socket.IO adapter is the in-memory one it was\n * created with. Behind a cluster adapter (Redis) rooms on other nodes are\n * not visible here, so room occupancy cannot skip a read, and access\n * changes are broadcast to the other nodes.\n */\n local(): boolean;\n}\n\n/** Options of {@link createHub}. */\nexport interface HubOptions {\n readonly registry: Registry;\n readonly storage: StorageAdapter | undefined;\n readonly policies: PolicyEngine;\n /** The dispatcher's access engine, which decides who may subscribe to a stream. */\n readonly access: AccessEngine;\n readonly logger: Logger;\n /** The change log's options, or `false` for none. */\n readonly changeLog: ChangeLogOptions | false | undefined;\n /**\n * The dispatcher's `outputValidation` (on unless `NODE_ENV` is\n * `\"production\"`): whether a stream declared `validate: \"development\"`\n * checks what is pushed to it.\n */\n readonly outputValidation?: boolean;\n}\n\n/** The live-data state of one dispatcher. */\nexport interface Hub {\n readonly registry: Registry;\n readonly storage: StorageAdapter | undefined;\n readonly policies: PolicyEngine;\n /** The dispatcher's access engine (RFC 0003 section 4.1): stream subscribers are authorized through it. */\n readonly access: AccessEngine;\n readonly logger: Logger;\n /** Whether a stream declared `validate: \"development\"` checks its items: the dispatcher's `outputValidation`. */\n readonly outputValidation: boolean;\n readonly routes: Routes;\n /**\n * The rows recent flushes touched. Always kept: subscriptions use it to\n * tell a deleted row from a forbidden one and to catch a flush racing a\n * subscribe. It answers \"not modified\" only when `answers` is on.\n */\n readonly changeLog: ChangeLog;\n /** Whether the change log answers \"not modified\" (the dispatcher's `changeLog` is not `false`). */\n readonly answers: boolean;\n readonly subscriptions: SubscriptionIndex;\n /** The Socket.IO server, once `createServer` attached one. */\n io: QuickdrawIo | undefined;\n probe: AdapterProbe;\n /** `createServer`'s `cluster` option: where the cluster's shared state lives, behind a cluster adapter. */\n cluster: ClusterOptions | undefined;\n /** The server's answered broadcasts to the other nodes, once `createServer` attached them. */\n broadcasts: ClusterBroadcasts | undefined;\n /**\n * The revisions flushes take and reads claim: the process's clock, or\n * behind a cluster adapter the cluster's shared counter (`cluster/revisions.ts`).\n */\n readonly revisions: Revisions;\n /**\n * Work started for a socket's event that may still send frames once it\n * settles (a room's presence read from every node): a server's `close()`\n * waits for it, so nothing is sent through an adapter the app is about to\n * close.\n */\n readonly inFlight: Set<Promise<unknown>>;\n}\n\nconst ALWAYS_LOCAL: AdapterProbe = Object.freeze({ local: () => true });\n\n/** Creates the live-data state of a dispatcher. Throws a `TypeError` for an `affects` it cannot follow. */\nexport function createHub(options: HubOptions): Hub {\n const hub: Omit<Hub, \"revisions\"> = {\n registry: options.registry,\n storage: options.storage,\n policies: options.policies,\n access: options.access,\n logger: options.logger,\n outputValidation: options.outputValidation ?? process.env.NODE_ENV !== \"production\",\n routes: routesOf(options.registry, options.storage),\n changeLog: createChangeLog(options.changeLog === false ? undefined : options.changeLog),\n answers: options.changeLog !== false,\n subscriptions: new SubscriptionIndex(),\n io: undefined,\n probe: ALWAYS_LOCAL,\n cluster: undefined,\n broadcasts: undefined,\n inFlight: new Set(),\n };\n return Object.assign(hub, { revisions: createRevisions(hub) });\n}\n\n/** Keeps `work` in the hub's work in flight until it settles. */\nexport function track(hub: Pick<Hub, \"inFlight\">, work: Promise<unknown>): void {\n hub.inFlight.add(work);\n const done = (): void => {\n hub.inFlight.delete(work);\n };\n work.then(done, done);\n}\n\n/** Resolves once the hub's work in flight, and any it started meanwhile, has settled. */\nexport async function drain(hub: Pick<Hub, \"inFlight\">): Promise<void> {\n while (hub.inFlight.size > 0) {\n await Promise.allSettled([...hub.inFlight]);\n }\n}\n\n/**\n * The change log, when it may answer \"not modified\": it is on, and, since it\n * sees only this process's writes, the server is not behind a cluster adapter.\n */\nexport function usableChangeLog(hub: Hub): ChangeLog | undefined {\n return hub.answers && hub.probe.local() ? hub.changeLog : undefined;\n}\n\n/** A service the registry holds. */\ntype RegisteredService = Registry[\"services\"] extends ReadonlyMap<string, infer S> ? S : never;\n\n/** A service whose rows can be subscribed to and sent: it has an entity and a model. */\nexport interface LiveService {\n readonly service: RegisteredService;\n readonly model: string;\n}\n\n/** The service `name` names, if its rows can be sent; `NOT_FOUND` otherwise. */\nexport function liveService(hub: Hub, name: string): LiveService {\n const service = hub.registry.services.get(name);\n if (service === undefined) {\n throw new QuickdrawError(\"NOT_FOUND\", `Unknown service \"${name}\"`);\n }\n if (service.model === undefined || service.contract.entity === undefined) {\n throw new QuickdrawError(\n \"NOT_FOUND\",\n `${name} has no entity rows to subscribe to: it declares no model or its contract no entity`,\n );\n }\n return { service, model: service.model };\n}\n","// Reading the collection frames a client sends (RFC 0003 sections 7.3, 7.4\n// and 8.2), which `envelope.ts` defines: `qd:col:sub { s, c, scope, since?,\n// limit?, cursor? }`, `qd:col:unsub { s, c, scope }` and `qd:col:items { s,\n// c, scope, ids }`. A malformed frame is `VALIDATION`, naming the field; an\n// unknown service or collection is `NOT_FOUND`; an anonymous socket is\n// `UNAUTHENTICATED`.\n//\n// `qd:col:items` serves a socket that subscribed to the scope already: its\n// subscription is the authorization, kept current by revocation, so it reads\n// no access and costs one statement (two for a `via` scope). A socket that\n// has not subscribed is `FORBIDDEN`, and more than 200 ids are `VALIDATION`,\n// as more than 500 are for `qd:sub`. A scope value longer than 256\n// characters is `VALIDATION` in every frame.\n\nimport type { CollectionItemsReply, Ok } from \"../../protocol/envelope\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { MAX_SCOPE_LENGTH } from \"../../protocol/version\";\nimport { liveService } from \"../emit/hub\";\nimport { unreadable } from \"../transports/ack\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport type { BoundCollection, CollectionHub } from \"./bind\";\nimport { MAX_ITEM_IDS, readItemsById } from \"./items\";\nimport { roomOf, type ScopeSubscription } from \"./scopes\";\nimport type { ScopeRequest } from \"./subscribe\";\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\ntype ScopeRef = Pick<ScopeSubscription, \"s\" | \"c\" | \"scope\">;\n\n/** A `qd:col:items` frame, read. */\nexport interface ItemsRequest extends ScopeRef {\n readonly ids: readonly string[];\n}\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\n/** Reads `{ s, c, scope }`, or throws `VALIDATION`. */\nfunction readRef(frame: unknown, event: string): ScopeRef & { readonly frame: UnknownRecord } {\n if (!isRecord(frame) || !isName(frame.s) || !isName(frame.c) || !isName(frame.scope)) {\n throw unreadable(`A ${event} frame needs { s, c, scope } with each a non-empty string`);\n }\n if (frame.scope.length > MAX_SCOPE_LENGTH) {\n throw unreadable(`scope must be at most ${MAX_SCOPE_LENGTH} characters`, [\"scope\"]);\n }\n return { s: frame.s, c: frame.c, scope: frame.scope, frame };\n}\n\n/** Reads a `qd:col:sub` frame, or throws `VALIDATION`. */\nexport function readSubscribe(value: unknown): ScopeRequest {\n const { s, c, scope, frame } = readRef(value, \"qd:col:sub\");\n const { since, limit, cursor } = frame;\n if (since !== undefined && (typeof since !== \"number\" || !Number.isFinite(since))) {\n throw unreadable(\"since must be the revision the client holds the scope at\", [\"since\"]);\n }\n if (\n limit !== undefined &&\n (typeof limit !== \"number\" || !Number.isSafeInteger(limit) || limit < 1)\n ) {\n throw unreadable(\"limit must be a positive whole number\", [\"limit\"]);\n }\n if (cursor !== undefined && !isName(cursor)) {\n throw unreadable(\"cursor must be the cursor of a page this collection sent\", [\"cursor\"]);\n }\n if (since !== undefined && cursor !== undefined) {\n throw unreadable(\n \"A qd:col:sub frame resumes (since) or reads a later page (cursor), not both\",\n [\"cursor\"],\n );\n }\n return {\n s,\n c,\n scope,\n ...(since === undefined ? {} : { since }),\n ...(limit === undefined ? {} : { limit }),\n ...(cursor === undefined ? {} : { cursor }),\n };\n}\n\n/** Reads a `qd:col:items` frame, or throws `VALIDATION`. */\nexport function readItemsRequest(value: unknown): ItemsRequest {\n const { s, c, scope, frame } = readRef(value, \"qd:col:items\");\n const { ids } = frame;\n if (!Array.isArray(ids) || !ids.every(isName)) {\n throw unreadable(\"ids must be a list of row ids\", [\"ids\"]);\n }\n if (ids.length > MAX_ITEM_IDS) {\n throw unreadable(`A qd:col:items frame names at most ${MAX_ITEM_IDS} ids`, [\"ids\"]);\n }\n return { s, c, scope, ids };\n}\n\n/** The collection a frame names, or `NOT_FOUND`. */\nexport function collectionOf(hub: CollectionHub, service: string, name: string): BoundCollection {\n liveService(hub, service);\n const collection = hub.collections.routes.find(service, name);\n if (collection === undefined) {\n throw new QuickdrawError(\"NOT_FOUND\", `${service} has no collection \"${name}\"`);\n }\n return collection;\n}\n\n/**\n * The collection a request names and the storage it is read through: the\n * checks every collection request makes first. Throws `NOT_FOUND` for an\n * unknown service or collection, `UNAUTHENTICATED` for an anonymous socket,\n * and `INTERNAL` when the dispatcher has no storage adapter.\n */\nexport function servedCollection(\n hub: CollectionHub,\n socket: QuickdrawServerSocket,\n ref: Pick<ScopeRef, \"s\" | \"c\">,\n): {\n readonly collection: BoundCollection;\n readonly storage: NonNullable<CollectionHub[\"storage\"]>;\n} {\n const collection = collectionOf(hub, ref.s, ref.c);\n if (socket.data.principal === null) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n if (hub.storage === undefined) {\n throw new QuickdrawError(\n \"INTERNAL\",\n \"Collections read rows through the dispatcher's storage adapter: pass db as trackPrisma(prisma)\",\n );\n }\n return { collection, storage: hub.storage };\n}\n\n/**\n * Serves one `qd:col:items`: the items of the requested ids that are members\n * of the scope, in request order. Throws what `servedCollection` throws, and\n * `FORBIDDEN` when the socket is not subscribed to the scope.\n */\nexport async function loadItems(\n hub: CollectionHub,\n socket: QuickdrawServerSocket,\n request: ItemsRequest,\n): Promise<CollectionItemsReply> {\n const { collection, storage } = servedCollection(hub, socket, request);\n if (hub.collections.scopes.get(socket, roomOf(request)) === undefined) {\n throw new QuickdrawError(\n \"FORBIDDEN\",\n \"qd:col:items needs the scope subscribed with qd:col:sub\",\n );\n }\n // The revision is claimed before any read: behind a cluster's counter, the counter's.\n const rev = await hub.revisions.claim();\n return {\n ok: true,\n ...(await readItemsById(storage, collection, request.scope, request.ids, rev)),\n };\n}\n\n/**\n * Serves `qd:col:unsub`: the socket leaves the scope, and a subscribe still\n * being made will not join it. Throws `VALIDATION` for a malformed frame,\n * `NOT_FOUND` for an unknown service or collection, and `UNAUTHENTICATED`\n * for an anonymous socket, which subscribes to nothing.\n */\nexport function unsubscribeScope(\n hub: CollectionHub,\n socket: QuickdrawServerSocket,\n value: unknown,\n): Ok {\n const ref = readRef(value, \"qd:col:unsub\");\n collectionOf(hub, ref.s, ref.c);\n if (socket.data.principal === null) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n hub.collections.scopes.unsubscribe(socket, roomOf(ref));\n return { ok: true };\n}\n","// A subscriber's level on rows, and what it is derived from (RFC 0003\n// sections 4.3 and 4.4): the service's policy through the dispatcher's\n// engine, counted as `dispatcher.access.levelsFor` counts it, with the rows\n// each level is anchored on. A service without a policy has no row levels:\n// only a service-wide `Admin` grant (with `adminBypass`) reaches its rows.\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport type { ResolvedAccess } from \"../access/api\";\nimport { meetsLevel, serviceGrant } from \"../access/levels\";\nimport { anchorKey } from \"../access/tools\";\nimport type { AnyService } from \"../service\";\nimport type { Principal } from \"../types\";\nimport type { Hub } from \"./hub\";\nimport { SUBSCRIBE_LEVEL } from \"./tiers\";\n\n/** The principal's levels on `ids` of `service` and their anchors, in one engine call. */\nexport async function resolveAccess(\n hub: Hub,\n service: AnyService,\n principal: Principal,\n ids: readonly string[],\n): Promise<ResolvedAccess> {\n if (service.access !== undefined && service.model !== undefined) {\n return await hub.policies.resolve(service.name, principal, ids);\n }\n const bypass = service.adminBypass && serviceGrant(principal, service.name) === \"Admin\";\n return {\n levels: new Map(ids.map((id) => [id, bypass ? \"Admin\" : null])),\n anchors: new Map(ids.map((id) => [id, [anchorKey(service.name, id)]])),\n };\n}\n\n/** The level a subscription to the row holds, or `undefined` when the level is too low to subscribe. */\nexport function subscriberLevel(access: ResolvedAccess, id: string): AccessLevel | undefined {\n const level = access.levels.get(id) ?? null;\n return level !== null && meetsLevel(level, SUBSCRIBE_LEVEL) ? level : undefined;\n}\n\n/** The anchors of the row's level; the row itself when the engine named none. */\nexport function anchorsOf(access: ResolvedAccess, service: string, id: string): readonly string[] {\n return access.anchors.get(id) ?? [anchorKey(service, id)];\n}\n","// Row versions for \"not modified\" answers (RFC 0003 sections 6 and 9, step 5).\n// A row's version is the time in its service's `versionColumn` when the\n// service declares one (read in one narrow query), or else the revision of\n// the last flush the in-process change log saw touch it. The version is taken\n// before the row itself is read, so an answer is never older than the version\n// it claims.\n//\n// - A call to a query whose output is one projection row (`\"entity\"`,\n// `nullable(\"card\")`) and whose input has an `id` gets that row's version,\n// when the row it returns is that row: a caller that sends it back as `v`\n// gets `{ ok: true, nm: true, v }` while the row is unchanged. A query\n// keyed by another id (the latest task of project `id`) returns some other\n// row, whose changes that version does not follow, and gets none. This is\n// the dispatcher's default `versions`.\n// - `qd:sub` answers \"not modified\" for an id whose held revision is no\n// older than the row's version.\n\nimport type { Revision } from \"../../protocol/envelope\";\nimport type { VersionSource } from \"../pipeline/notModified\";\nimport type { AnyService } from \"../service\";\nimport { versionTime } from \"../rev\";\nimport { usableChangeLog, type Hub } from \"./hub\";\n\n/** The versions of some rows of a service. */\nexport interface RowVersions {\n /** Each row's version; a row without one is absent. */\n readonly versions: ReadonlyMap<string, number>;\n /** Rows the version column's read found missing; empty when nothing was read. */\n readonly missing: ReadonlySet<string>;\n}\n\nconst NONE: RowVersions = Object.freeze({\n versions: new Map<string, number>(),\n missing: new Set<string>(),\n});\n\n/**\n * The versions of `ids` of `service`: from its `versionColumn` in one query,\n * or from the change log (behind a cluster adapter it has none), or none.\n */\nexport async function rowVersions(\n hub: Hub,\n service: AnyService,\n ids: readonly string[],\n): Promise<RowVersions> {\n const { model, versionColumn } = service;\n if (ids.length === 0 || model === undefined) {\n return NONE;\n }\n if (versionColumn === undefined) {\n const log = usableChangeLog(hub);\n return log === undefined\n ? NONE\n : {\n versions: new Map(ids.map((id) => [id, log.lastChange(service.name, id)])),\n missing: new Set(),\n };\n }\n const rows =\n (await hub.storage?.findMany(model, {\n where: { id: { in: [...ids] } },\n select: { id: true, [versionColumn]: true },\n })) ?? [];\n const versions = new Map<string, number>();\n for (const row of rows) {\n const time = versionTime(row[versionColumn]);\n if (typeof row.id === \"string\" && time !== undefined) {\n versions.set(row.id, time);\n }\n }\n const found = new Set(rows.map((row) => row.id));\n return { versions, missing: new Set(ids.filter((id) => !found.has(id))) };\n}\n\n/** The ids whose held revision is no older than their row's version: \"not modified\". */\nexport function unchangedRows(\n versions: RowVersions,\n held: ReadonlyMap<string, Revision>,\n): Set<string> {\n const unchanged = new Set<string>();\n for (const [id, rev] of held) {\n const version = versions.versions.get(id);\n if (version !== undefined && version <= rev) {\n unchanged.add(id);\n }\n }\n return unchanged;\n}\n\nfunction inputId(input: unknown): string | undefined {\n if (typeof input !== \"object\" || input === null) {\n return undefined;\n }\n const { id } = input as { readonly id?: unknown };\n return typeof id === \"string\" && id.length > 0 ? id : undefined;\n}\n\n/**\n * The dispatcher's default `versions`: the version of the row a query\n * returns, for a query whose output is one projection row and whose input\n * has an `id`, attached only when the row returned is row `id`. Any other\n * query has none, and always runs.\n */\nexport function createVersionSource(hub: Hub): VersionSource {\n return Object.freeze({\n async versionOf({ service, method, input }) {\n const id = inputId(input);\n if (\n id === undefined ||\n method.projection === undefined ||\n method.projection.kind === \"list\"\n ) {\n return undefined;\n }\n const { versions } = await rowVersions(hub, service, [id]);\n return versions.get(id);\n },\n describes({ input }, result) {\n const id = inputId(input);\n const returned =\n typeof result === \"object\" && result !== null\n ? (result as { readonly id?: unknown }).id\n : undefined;\n return id !== undefined && returned === id;\n },\n } satisfies VersionSource);\n}\n","// One `qd:sub` batch (RFC 0003 sections 4.3 and 6). It replaces 4.1's\n// `subscribe` and `batchSubscribe` (4.1 `src/server/BaseService.ts:176-283`),\n// which joined a row's rooms before reading the row (`:204-213`, `:252-264`),\n// so a socket could sit in the room of a row that did not exist. Here a batch\n// goes, in this order:\n//\n// 1. authorize every id in one engine call, which also gives the rows each\n// level is anchored on; an id below `Read` is `FORBIDDEN` and never read;\n// 2. take the revision before any row is read: the last one taken, so reads\n// do not push revisions ahead of the clock (`currentRev`); behind a\n// cluster's counter, the counter's last one (`cluster/revisions.ts`);\n// 3. find which held rows are unchanged (\"not modified\"): one narrow read of\n// the service's `versionColumn`, or the change log;\n// 4. read the other allowed rows in one `findMany` with the entity\n// projection's select;\n// 5. put the socket in the room of each row found, for its level, and record\n// the subscription and its anchors on `socket.data`;\n// 6. settle the races: an access change while the batch ran re-resolves the\n// joined rows, and a flush that touched a joined row after the revision\n// (its frame may have gone out before the join) re-reads that row (behind\n// a cluster's counter, any flush on any node: every joined row). Then,\n// while access keeps changing, the joined rows are resolved again, at most\n// `MAX_RECHECKS` times; a row whose anchors were still moving is denied.\n// A subscription the batch recorded and someone else ended meanwhile\n// (revocation, a disconnect) is `FORBIDDEN`; one someone else replaced (a\n// newer resolution) is answered at that one's level;\n// 7. answer each id: its row stripped for its level, \"not modified\", or why\n// not.\n//\n// Revocation finds a socket through the anchors its subscriptions record, so\n// an access change made after a row was joined with its current anchors\n// reaches the batch's subscription by itself; the rechecks cover changes\n// made before that, on anchors the batch had not recorded yet.\n\nimport type { EntityResult, Revision } from \"../../protocol/envelope\";\nimport { currentRev } from \"../rev\";\nimport type { StorageRow } from \"../storage\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport type { Hub, LiveService } from \"./hub\";\nimport { projectRow } from \"./projection\";\nimport { anchorsOf, resolveAccess, subscriberLevel } from \"./resolve\";\nimport type { EntitySubscription } from \"./subscriptions\";\nimport { strip } from \"./tiers\";\nimport { rowVersions, unchangedRows } from \"./versions\";\n\n/** How often a subscribe resolves access again after its reads, while access keeps changing. */\nexport const MAX_RECHECKS = 3;\n\n/** A `qd:sub` frame, read. */\nexport interface SubscribeRequest {\n readonly s: string;\n /** The ids, in request order; an id may repeat. */\n readonly ids: readonly string[];\n /** The revision the client holds, for each id it sent one for. */\n readonly held: ReadonlyMap<string, Revision>;\n}\n\n/** One answered id: its level, the row read (none for \"not modified\"), and the revision. */\ninterface Answer {\n readonly level: EntitySubscription[\"level\"];\n readonly row: StorageRow | undefined;\n readonly rev: Revision;\n}\n\ninterface Batch {\n readonly hub: Hub;\n readonly socket: QuickdrawServerSocket;\n readonly target: LiveService;\n readonly principal: NonNullable<QuickdrawServerSocket[\"data\"][\"principal\"]>;\n /** The access changes the process had seen when the batch last resolved access. */\n checkedAt: number;\n /** Per id, how often the socket had unsubscribed from it when the batch began. */\n readonly unsubscribes: ReadonlyMap<string, number>;\n readonly denied: Set<string>;\n readonly answers: Map<string, Answer>;\n /** The subscription the batch recorded for each row it joined, while the batch manages it. */\n readonly joined: Map<string, EntitySubscription>;\n /** The joined rows whose level or anchors the last recheck changed. */\n moving: ReadonlySet<string>;\n}\n\nconst FORBIDDEN: EntityResult = Object.freeze({\n ok: false,\n e: Object.freeze({ code: \"FORBIDDEN\", message: \"Insufficient permissions\" }),\n});\n\nconst NOT_FOUND: EntityResult = Object.freeze({\n ok: false,\n e: Object.freeze({ code: \"NOT_FOUND\", message: \"No such row\" }),\n});\n\n/** The rows `ids`, read in one query with the entity projection's select. */\nasync function readRows(\n hub: Hub,\n target: LiveService,\n ids: readonly string[],\n): Promise<Map<string, StorageRow>> {\n const projection = target.service.projections.get(\"entity\");\n if (ids.length === 0 || projection === undefined || hub.storage === undefined) {\n return new Map();\n }\n const rows = await hub.storage.findMany(target.model, {\n where: { id: { in: [...ids] } },\n select: projection.select,\n });\n return new Map(rows.flatMap((row) => (typeof row.id === \"string\" ? [[row.id, row]] : [])));\n}\n\n/** True while the socket's subscription to the row is still the one the batch recorded. */\nfunction isOwn(batch: Batch, id: string): boolean {\n const own = batch.joined.get(id);\n const current = batch.hub.subscriptions.get(batch.socket, batch.target.service.name, id);\n return own !== undefined && current === own;\n}\n\n/**\n * True while the batch may put the socket in the row's room: the socket is\n * still connected (a socket indexed after its disconnect would stay in the\n * index forever), and the client has not unsubscribed from the row since the\n * batch began.\n */\nfunction joinable(batch: Batch, id: string): boolean {\n const { hub, socket, target } = batch;\n const unsubscribes = hub.subscriptions.unsubscribes(socket, target.service.name, id);\n return socket.connected && unsubscribes === batch.unsubscribes.get(id);\n}\n\n/** Step 5: joins the room of each answered row the socket may still join (`joinable`). */\nfunction join(batch: Batch, anchors: (id: string) => readonly string[]): void {\n const { hub, socket, target } = batch;\n const service = target.service.name;\n for (const [id, answer] of batch.answers) {\n if (!joinable(batch, id)) {\n continue;\n }\n const subscription: EntitySubscription = { level: answer.level, anchors: anchors(id) };\n hub.subscriptions.set(socket, service, id, subscription);\n batch.joined.set(id, subscription);\n }\n}\n\n/** Gives up a joined row the socket may no longer join; the answer stands, as for a row never joined. */\nfunction abandon(batch: Batch, id: string): void {\n if (isOwn(batch, id)) {\n batch.hub.subscriptions.delete(batch.socket, batch.target.service.name, id);\n }\n batch.joined.delete(id);\n}\n\n/** Ends a subscription the batch made, and answers the id with `result`; another's is left alone. */\nfunction retract(batch: Batch, id: string, result: \"denied\" | \"missing\"): void {\n if (isOwn(batch, id)) {\n batch.hub.subscriptions.delete(batch.socket, batch.target.service.name, id);\n }\n batch.joined.delete(id);\n batch.answers.delete(id);\n if (result === \"denied\") {\n batch.denied.add(id);\n }\n}\n\n/**\n * A joined row whose subscription is no longer the batch's. Ended by\n * someone else (revocation, a disconnect): `FORBIDDEN`, unless the client\n * unsubscribed, which leaves the answer as it was. Replaced by a newer\n * resolution (revocation's, or another batch's): answered at its level.\n */\nfunction release(batch: Batch, id: string): void {\n const { hub, socket, target } = batch;\n const service = target.service.name;\n const current = hub.subscriptions.get(socket, service, id);\n const answer = batch.answers.get(id);\n batch.joined.delete(id);\n if (current !== undefined) {\n if (answer !== undefined) {\n batch.answers.set(id, { ...answer, level: current.level });\n }\n return;\n }\n if (hub.subscriptions.unsubscribes(socket, service, id) === batch.unsubscribes.get(id)) {\n batch.answers.delete(id);\n batch.denied.add(id);\n }\n}\n\n/** Releases every joined row whose subscription someone else ended or replaced. */\nfunction releaseTaken(batch: Batch): void {\n for (const id of [...batch.joined.keys()]) {\n if (!isOwn(batch, id)) {\n release(batch, id);\n }\n }\n}\n\nfunction sameSubscription(a: EntitySubscription | undefined, b: EntitySubscription): boolean {\n return (\n a !== undefined &&\n a.level === b.level &&\n a.anchors.length === b.anchors.length &&\n a.anchors.every((anchor, index) => anchor === b.anchors[index])\n );\n}\n\n/** True when access changed since the batch last resolved it. */\nfunction accessMoved(batch: Batch): boolean {\n return batch.hub.subscriptions.accessChanges !== batch.checkedAt;\n}\n\n/** Step 6: access changed since the batch last resolved it, so the joined rows are resolved again. */\nasync function recheckAccess(batch: Batch): Promise<void> {\n const { hub, target, principal, socket } = batch;\n if (!accessMoved(batch)) {\n return;\n }\n batch.checkedAt = hub.subscriptions.accessChanges;\n batch.moving = new Set();\n if (batch.joined.size === 0) {\n return;\n }\n const service = target.service.name;\n const ids = [...batch.joined.keys()];\n const access = await resolveAccess(hub, target.service, principal, ids);\n const moving = new Set<string>();\n for (const id of ids) {\n if (!isOwn(batch, id)) {\n release(batch, id);\n continue;\n }\n // The guards `join` applies, since this may join the row's room again.\n if (!joinable(batch, id)) {\n abandon(batch, id);\n continue;\n }\n const level = subscriberLevel(access, id);\n const answer = batch.answers.get(id);\n if (level === undefined || answer === undefined) {\n retract(batch, id, \"denied\");\n continue;\n }\n const subscription: EntitySubscription = { level, anchors: anchorsOf(access, service, id) };\n if (!sameSubscription(batch.joined.get(id), subscription)) {\n moving.add(id);\n hub.subscriptions.set(socket, service, id, subscription);\n batch.joined.set(id, subscription);\n batch.answers.set(id, { ...answer, level });\n }\n }\n batch.moving = moving;\n}\n\n/**\n * The joined rows a flush may have touched after the revision, and the\n * revision to read them again at. This process's change log names them; it\n * sees only this process's flushes, so behind a cluster's counter every\n * joined row is read again once any node took a revision after `rev`.\n */\nasync function touchedSince(\n batch: Batch,\n rev: Revision,\n): Promise<{ readonly stale: string[]; readonly fresh: Revision }> {\n const { hub, target } = batch;\n const joined = [...batch.joined.keys()];\n if (hub.revisions.shared()) {\n const moved = await hub.revisions.movedPast(rev);\n return { stale: moved === undefined ? [] : joined, fresh: moved ?? rev };\n }\n const service = target.service.name;\n const stale = joined.filter((id) => hub.changeLog.lastChange(service, id) > rev);\n return { stale, fresh: stale.length === 0 ? rev : currentRev() };\n}\n\n/** Step 6: rows a flush touched after the revision are read again, at the newer one. */\nasync function rereadTouched(batch: Batch, rev: Revision): Promise<void> {\n const { hub, target } = batch;\n const { stale, fresh } = await touchedSince(batch, rev);\n if (stale.length === 0) {\n return;\n }\n const rows = await readRows(hub, target, stale);\n for (const id of stale) {\n const row = rows.get(id);\n const answer = batch.answers.get(id);\n if (row === undefined || answer === undefined) {\n retract(batch, id, \"missing\");\n continue;\n }\n batch.answers.set(id, { level: answer.level, row, rev: fresh });\n }\n}\n\n/** Step 6. */\nasync function settleRaces(batch: Batch, rev: Revision): Promise<void> {\n await recheckAccess(batch);\n await rereadTouched(batch, rev);\n for (let round = 0; round < MAX_RECHECKS && accessMoved(batch); round += 1) {\n await recheckAccess(batch);\n }\n if (accessMoved(batch)) {\n // Access changed during the last check too: a row it gave new anchors may have missed a change on them.\n for (const id of batch.moving) {\n if (batch.joined.has(id)) {\n retract(batch, id, \"denied\");\n }\n }\n }\n releaseTaken(batch);\n}\n\n/** Steps 1 to 5. */\nasync function answerBatch(batch: Batch, held: ReadonlyMap<string, Revision>): Promise<Revision> {\n const { hub, target, principal } = batch;\n const service = target.service.name;\n const ids = [...batch.unsubscribes.keys()];\n const access = await resolveAccess(hub, target.service, principal, ids);\n const allowed = new Set(ids.filter((id) => subscriberLevel(access, id) !== undefined));\n for (const id of ids) {\n if (!allowed.has(id)) {\n batch.denied.add(id);\n }\n }\n const claimed = hub.revisions.claim();\n const rev = typeof claimed === \"number\" ? claimed : await claimed;\n const heldAllowed = new Map([...held].filter(([id]) => allowed.has(id)));\n const versions = await rowVersions(hub, target.service, [...heldAllowed.keys()]);\n const unchanged = unchangedRows(versions, heldAllowed);\n const toRead = [...allowed].filter((id) => !unchanged.has(id) && !versions.missing.has(id));\n const rows = await readRows(hub, target, toRead);\n for (const id of allowed) {\n const level = subscriberLevel(access, id);\n const row = rows.get(id);\n if (level !== undefined && (row !== undefined || unchanged.has(id))) {\n batch.answers.set(id, { level, row, rev });\n }\n }\n join(batch, (id) => anchorsOf(access, service, id));\n return rev;\n}\n\nfunction resultOf(batch: Batch, id: string): EntityResult {\n if (batch.denied.has(id)) {\n return FORBIDDEN;\n }\n const found = batch.answers.get(id);\n if (found === undefined) {\n return NOT_FOUND;\n }\n if (found.row === undefined) {\n return { ok: true, nm: true, rev: found.rev };\n }\n const projection = batch.target.service.projections.get(\"entity\");\n const data = projection === undefined ? found.row : projectRow(projection, found.row);\n const hidden = projection?.tiers.hidden(found.level);\n const isRow = typeof data === \"object\" && data !== null && hidden !== undefined;\n return {\n ok: true,\n d: isRow ? strip(data as Readonly<Record<string, unknown>>, hidden) : data,\n rev: found.rev,\n };\n}\n\n/**\n * Answers one `qd:sub` batch of a socket with a principal, one result per\n * requested id in request order. Rejects when a lookup or read fails; the\n * subscriptions the batch made are then ended.\n */\nexport async function subscribe(\n hub: Hub,\n socket: QuickdrawServerSocket,\n target: LiveService,\n request: SubscribeRequest,\n): Promise<EntityResult[]> {\n const { principal } = socket.data;\n if (principal === null) {\n throw new TypeError(\"subscribe: the socket has no principal\");\n }\n const service = target.service.name;\n const batch: Batch = {\n hub,\n socket,\n target,\n principal,\n checkedAt: hub.subscriptions.accessChanges,\n unsubscribes: hub.subscriptions.begin(socket, service, request.ids),\n denied: new Set(),\n answers: new Map(),\n joined: new Map(),\n moving: new Set(),\n };\n try {\n const rev = await answerBatch(batch, request.held);\n await settleRaces(batch, rev);\n } catch (error) {\n for (const id of [...batch.joined.keys()]) {\n retract(batch, id, \"missing\");\n }\n throw error;\n } finally {\n hub.subscriptions.end(socket, service, request.ids);\n }\n return request.ids.map((id) => resultOf(batch, id));\n}\n","// Who may subscribe to a collection scope (RFC 0003 sections 4.3 and 7.1),\n// decided as the `{ scope: access, of: anchor, id: scope }` method form is\n// decided (`access/engine.ts`): a service-wide `Admin` grant on the\n// collection's own service passes while it keeps `adminBypass`; otherwise\n// the anchor's policy must give the principal at least the collection's\n// `access` level (default `Read`) on the anchor row, and grants on the\n// anchor's service do not count, as they do not flow through `inherit`. A\n// missing anchor row has no level, so it is `FORBIDDEN` unless the grant\n// passes. A `\"self\"` scope passes when it is the principal's own user id.\n// 4.1 asked each collection's `checkScopeAccess` (4.1 `src/server/collections.ts:45-49`).\n//\n// A change topic (RFC 0003 section 11.3) is watched on the same terms: a\n// collection scope's topic exactly as a subscribe to that scope, and a\n// service's topic by the service's `watchAccess`, closed to everyone when\n// the service declares none. A search kept to a scope (the search kit, RFC\n// 0003 section 12.2) is decided by the same rule (`allowedScopes`).\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { PolicyEngine } from \"../access/api\";\nimport { meetsLevel, serviceGrant } from \"../access/levels\";\nimport { anchorKey } from \"../access/tools\";\nimport type { AnyService } from \"../service\";\nimport type { Principal } from \"../types\";\nimport type { BoundCollection, CollectionHub } from \"./bind\";\n\n/** What a `qd:watch` names: a service's topic, or the topic of one scope of a collection. */\nexport type WatchTarget =\n | { readonly kind: \"service\"; readonly service: BoundCollection[\"service\"] }\n | {\n readonly kind: \"collection\";\n readonly collection: BoundCollection;\n readonly scope: string;\n };\n\n/**\n * What deciding a collection's scopes needs, wherever the scope arrives\n * from: a `qd:col:sub`, a topic watch, or a search kept to the scope.\n */\nexport interface ScopeRule {\n /** The collection's own service: its service-wide `Admin` grant passes while it keeps `adminBypass`. */\n readonly service: Pick<AnyService, \"name\" | \"adminBypass\">;\n /** The name of the service whose policy authorizes the scopes; `undefined` for a `\"self\"` scope. */\n readonly anchor: string | undefined;\n /** The level a subscriber needs on the scope's anchor row. */\n readonly access: AccessLevel;\n}\n\n/**\n * The scopes of `scopes` the principal may subscribe to under `rule`, each\n * with the rows its access is derived from (its anchors): the anchor row and\n * its `inherit` parents, none for a `\"self\"` scope. One engine call; a lookup\n * that fails rejects.\n */\nexport async function allowedScopes(\n policies: Pick<PolicyEngine, \"resolve\">,\n rule: ScopeRule,\n principal: Principal,\n scopes: readonly string[],\n): Promise<Map<string, readonly string[]>> {\n const allowed = new Map<string, readonly string[]>();\n const { anchor, service } = rule;\n const anchorRow = (scope: string): readonly string[] =>\n anchor === undefined ? [] : [anchorKey(anchor, scope)];\n if (service.adminBypass && serviceGrant(principal, service.name) === \"Admin\") {\n for (const scope of scopes) {\n allowed.set(scope, anchorRow(scope));\n }\n return allowed;\n }\n if (anchor === undefined) {\n for (const scope of scopes.filter((candidate) => candidate === principal.userId)) {\n allowed.set(scope, []);\n }\n return allowed;\n }\n const access = await policies.resolve(anchor, principal, scopes, { grants: false });\n for (const scope of scopes) {\n if (meetsLevel(access.levels.get(scope), rule.access)) {\n allowed.set(scope, access.anchors.get(scope) ?? anchorRow(scope));\n }\n }\n return allowed;\n}\n\n/** The scopes of `scopes` the principal may subscribe to in a served collection: {@link allowedScopes}. */\nexport async function authorizeScopes(\n hub: CollectionHub,\n collection: BoundCollection,\n principal: Principal,\n scopes: readonly string[],\n): Promise<Map<string, readonly string[]>> {\n const rule: ScopeRule = {\n service: collection.service,\n anchor: collection.anchorService?.name,\n access: collection.access,\n };\n return await allowedScopes(hub.policies, rule, principal, scopes);\n}\n\n/** True when the service's `watchAccess` lets the principal watch its topic; never without one. */\nfunction mayWatchService(service: BoundCollection[\"service\"], principal: Principal): boolean {\n const form = service.watchAccess;\n if (form === undefined) {\n return false;\n }\n if (form === \"public\" || form === \"authenticated\") {\n return true;\n }\n return meetsLevel(serviceGrant(principal, service.name), form.service);\n}\n\n/**\n * Authorizes a watch of `target` by `principal` (`null` when anonymous): a\n * collection scope's topic as a subscribe to that scope, and a service's\n * topic by its `watchAccess`. Resolves with the rows a scope's access is\n * derived from (its anchors; none for the service topic). Throws\n * `UNAUTHENTICATED` or `FORBIDDEN`; a lookup that fails rejects.\n */\nexport async function authorizeWatch(\n hub: CollectionHub,\n principal: Principal | null,\n target: WatchTarget,\n): Promise<readonly string[]> {\n if (target.kind === \"service\" && target.service.watchAccess === undefined) {\n throw new QuickdrawError(\n \"FORBIDDEN\",\n `${target.service.name} keeps its service topic closed: it declares no watchAccess`,\n );\n }\n if (target.kind === \"service\" && target.service.watchAccess === \"public\") {\n return [];\n }\n if (principal === null) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n const anchors =\n target.kind === \"service\"\n ? mayWatchService(target.service, principal)\n ? []\n : undefined\n : (await authorizeScopes(hub, target.collection, principal, [target.scope])).get(\n target.scope,\n );\n if (anchors === undefined) {\n throw new QuickdrawError(\"FORBIDDEN\", \"Insufficient permissions\");\n }\n return anchors;\n}\n","// One page of a collection scope (RFC 0003 section 7.3): the rows of the\n// scope (its scope column, or its `via` junction's links, and `where`) in\n// `order`, after the cursor when there is one, at most `limit` of them; the\n// scope's member count; the cursor of the next page; and, on a first page\n// (no cursor) of a collection that declares `index`, the scope's index\n// (section 7.4, `index.ts`). The revision is taken by the caller before any\n// read, so the page is never older than the revision it claims. 4.1 left all\n// of it to each collection's `snapshot` function and clamped only the page\n// size (4.1 `src/server/collections.ts:160-171`).\n//\n// A page costs two statements, the rows and the count, run together, and a\n// first page of an indexed collection a third beside them, the index; a\n// `via` scope reads its links first. The first page of a scope through an\n// adapter that answers `nullable` also asks it about each order column, once\n// per process (`StorageAdapter.nullable`).\n//\n// A cursor is the client's: when the read that applies it fails while the\n// count of the same scope succeeds, the cursor's values did not fit the\n// order columns, and the request is `VALIDATION`, not a server fault.\n\nimport type { CollectionSnapshot, Revision } from \"../../protocol/envelope\";\nimport type { StorageAdapter, StorageRow, StorageWhere } from \"../storage\";\nimport { unreadable } from \"../transports/ack\";\nimport type { BoundCollection } from \"./bind\";\nimport { afterCursor, decodeCursor, encodeCursor, orderByOf, type CursorValues } from \"./cursor\";\nimport type { ServiceCollection } from \"./define\";\nimport { readIndex } from \"./index\";\nimport { itemOf, selectWith } from \"./items\";\n\nconst NOT_A_CURSOR = \"cursor is not a cursor of this collection\";\n\n/** What a page asks for. */\nexport interface PageRequest {\n readonly scope: string;\n /** The page size; the collection's `limit` when absent. */\n readonly limit?: number;\n /** The cursor of the page before; the first page when absent. */\n readonly cursor?: string;\n}\n\n/** The page size used: the request's or the collection's, lowered to `maxLimit` when above it. */\nexport function pageSize(\n collection: BoundCollection,\n requested: number | undefined,\n): { readonly limit: number; readonly clamped: boolean } {\n const limit = requested ?? collection.limit;\n return limit > collection.maxLimit\n ? { limit: collection.maxLimit, clamped: true }\n : { limit, clamped: false };\n}\n\nfunction isId(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\n/**\n * The filter matching the members of a scope: its scope column, or the ids\n * its `via` junction links to it, and `where`. `undefined` for a `via` scope\n * with no links: it has no members. The search kit reads a scope's members\n * with it too, through its database client, and passes `maxLinks`: then at\n * most that many links are read, the first by the linked row's id, so one\n * call never reads a scope's every link.\n */\nexport async function membersWhere(\n storage: Pick<StorageAdapter, \"findMany\">,\n collection: Pick<ServiceCollection, \"scope\" | \"where\">,\n scope: string,\n maxLinks?: number,\n): Promise<StorageWhere | undefined> {\n const { where } = collection;\n const filtered = (filter: StorageWhere): StorageWhere =>\n Object.keys(where).length === 0 ? filter : { AND: [filter, where] };\n if (collection.scope.kind === \"column\") {\n return filtered({ [collection.scope.column]: scope });\n }\n const { model, entry, scope: column } = collection.scope;\n const links = await storage.findMany(model, {\n where: { [column]: scope },\n select: { [entry]: true },\n ...(maxLinks === undefined ? {} : { orderBy: { [entry]: \"asc\" }, take: maxLinks }),\n });\n const ids = [...new Set(links.map((link) => link[entry]).filter(isId))];\n return ids.length === 0 ? undefined : filtered({ id: { in: ids } });\n}\n\n/**\n * The order columns that may hold null, as the adapter answers. A cursor\n * holding null for a column the adapter says cannot hold it is not a cursor\n * of this collection.\n */\nasync function nullableColumns(\n storage: StorageAdapter,\n collection: BoundCollection,\n values: CursorValues | undefined,\n): Promise<Set<string>> {\n const columns = collection.order.map(([column]) => column);\n const answers = await Promise.all(\n columns.map(async (column) =>\n column === \"id\" ? false : ((await storage.nullable?.(collection.model, column)) ?? false),\n ),\n );\n const nullable = new Set<string>();\n for (const [index, column] of columns.entries()) {\n const known = storage.nullable !== undefined;\n if (values?.[index] === null && known && answers[index] !== true) {\n throw unreadable(NOT_A_CURSOR, [\"cursor\"]);\n }\n if (answers[index] === true || values?.[index] === null) {\n nullable.add(column);\n }\n }\n return nullable;\n}\n\n/** How one page's rows are read: the scope's filter, the cursor's values and the page size. */\ninterface RowsRead {\n readonly members: StorageWhere;\n readonly values: CursorValues | undefined;\n readonly nullable: ReadonlySet<string>;\n readonly limit: number;\n}\n\n/**\n * The page's rows (one more than `limit`, to tell whether a page follows)\n * and the scope's member count. A rows read that applied a cursor and failed\n * while the count succeeded throws `VALIDATION`: the cursor's values do not\n * fit the order columns.\n */\nasync function readRows(\n storage: StorageAdapter,\n collection: BoundCollection,\n read: RowsRead,\n): Promise<{ readonly rows: StorageRow[]; readonly total: number }> {\n const { members, values, nullable, limit } = read;\n const { order } = collection;\n const where =\n values === undefined ? members : { AND: [members, afterCursor(order, values, nullable)] };\n const [rows, total] = await Promise.allSettled([\n storage.findMany(collection.model, {\n where,\n select: selectWith(\n collection.item.select,\n order.map(([column]) => column),\n ),\n orderBy: orderByOf(order, nullable),\n take: limit + 1,\n }),\n storage.count(collection.model, { where: members }),\n ]);\n if (total.status === \"rejected\") {\n throw total.reason;\n }\n if (rows.status === \"fulfilled\") {\n return { rows: rows.value, total: total.value };\n }\n if (values === undefined) {\n throw rows.reason;\n }\n const refused = unreadable(NOT_A_CURSOR, [\"cursor\"]);\n refused.cause = rows.reason;\n throw refused;\n}\n\n/**\n * Reads one page of `request.scope` at revision `rev`: its items, the\n * scope's member count, and the next page's cursor (`null` on the last\n * page); on a first page of a collection that declares `index`, its index\n * too. A request above `maxLimit` gets `maxLimit` items and `clamped`.\n * Throws `VALIDATION` for a cursor that is not one of this collection.\n */\nexport async function readPage(\n storage: StorageAdapter,\n collection: BoundCollection,\n request: PageRequest,\n rev: Revision,\n): Promise<CollectionSnapshot> {\n const { limit, clamped } = pageSize(collection, request.limit);\n const { order } = collection;\n const values = request.cursor === undefined ? undefined : decodeCursor(order, request.cursor);\n const nullable = await nullableColumns(storage, collection, values);\n const members = await membersWhere(storage, collection, request.scope);\n const page = { ok: true, rev, limit, ...(clamped ? { clamped: true as const } : {}) } as const;\n const indexed = values === undefined && collection.index !== undefined;\n if (members === undefined) {\n return { ...page, items: [], total: 0, cursor: null, ...(indexed ? { index: [] } : {}) };\n }\n const [{ rows, total }, index] = await Promise.all([\n readRows(storage, collection, { members, values, nullable, limit }),\n indexed ? readIndex(storage, collection, members, nullable, rev) : undefined,\n ]);\n const shown = rows.slice(0, limit);\n const last = shown.at(-1);\n return {\n ...page,\n items: shown.map((row) => itemOf(collection, row)),\n total,\n cursor: rows.length > limit && last !== undefined ? encodeCursor(order, last) : null,\n ...index,\n };\n}\n","// One `qd:col:sub` (RFC 0003 sections 4.3 and 7.3), in the order entity\n// subscriptions go (`emit/subscribe.ts`). 4.1 joined the scope's room before\n// reading (4.1 `src/server/collections.ts:155-158`) and answered an\n// unknown collection and a denied scope alike. Here:\n//\n// 1. authorize the scope (`access.ts`): a denied scope is `FORBIDDEN`, and\n// nothing is read;\n// 2. take the revision before any read: the last one taken (`currentRev`),\n// or a new one when the last is below the scope's resume floor (just\n// after a reset), so the client can resume from the page it gets;\n// 3. with a cursor, read that page and answer it: paging never joins;\n// 4. with `since`, when this process sees every change (no cluster adapter,\n// the change log on): join the scope's room, then answer the buffered\n// deltas since `since` when the buffer covers it. Joining first means a\n// change recorded after the buffer is read reaches the socket as a frame;\n// 5. otherwise read the first page, then join;\n// 6. settle the races: an access change while the subscribe ran authorizes\n// again (a denied scope leaves its room), and a flush that changed the\n// scope after the revision (its frame may have gone out before the join)\n// reads the page again, at a newer revision. Then, while access keeps\n// changing, the scope is authorized again, at most `MAX_RECHECKS` times,\n// and refused when its anchors were still moving. A subscription the\n// subscribe recorded and revocation ended meanwhile is `FORBIDDEN`.\n\nimport type { CollectionSubscribeReply, Revision } from \"../../protocol/envelope\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { usableChangeLog } from \"../emit/hub\";\nimport { MAX_RECHECKS } from \"../emit/subscribe\";\nimport { currentRev, nextRev } from \"../rev\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport { authorizeScopes } from \"./access\";\nimport type { BoundCollection, CollectionHub } from \"./bind\";\nimport { groupOf, roomOf, type ScopeSubscription } from \"./scopes\";\nimport { readPage, type PageRequest } from \"./snapshot\";\n\n/** A `qd:col:sub` frame, read. */\nexport interface ScopeRequest extends PageRequest {\n readonly s: string;\n readonly c: string;\n /** The revision the client holds the scope at. */\n readonly since?: Revision;\n}\n\ninterface Attempt {\n readonly hub: CollectionHub;\n readonly storage: NonNullable<CollectionHub[\"storage\"]>;\n readonly socket: QuickdrawServerSocket;\n readonly collection: BoundCollection;\n readonly principal: NonNullable<QuickdrawServerSocket[\"data\"][\"principal\"]>;\n readonly request: ScopeRequest;\n readonly room: string;\n /** The access changes the process had seen when the subscribe last authorized the scope. */\n checkedAt: number;\n /** How often the socket had unsubscribed from the scope when the subscribe began. */\n readonly unsubscribes: number;\n /** The subscription this subscribe recorded, while it manages it. */\n record: ScopeSubscription | undefined;\n /** Whether the last recheck gave the scope new anchors. */\n moving: boolean;\n}\n\nfunction forbidden(): QuickdrawError {\n return new QuickdrawError(\"FORBIDDEN\", \"Insufficient permissions\");\n}\n\n/** The anchors of the scope, or `undefined` when the principal may not subscribe to it. */\nasync function anchorsOf(attempt: Attempt): Promise<readonly string[] | undefined> {\n const { hub, collection, principal, request } = attempt;\n const allowed = await authorizeScopes(hub, collection, principal, [request.scope]);\n return allowed.get(request.scope);\n}\n\n/** True while the socket's subscription to the scope is still the one this subscribe recorded. */\nfunction isOwn(attempt: Attempt): boolean {\n const { hub, socket, room, record } = attempt;\n return record !== undefined && hub.collections.scopes.get(socket, room) === record;\n}\n\n/** Joins the scope's room, unless the socket has gone or the client unsubscribed meanwhile. */\nfunction join(attempt: Attempt, anchors: readonly string[]): void {\n const { hub, socket, request, room } = attempt;\n if (\n !socket.connected ||\n hub.collections.scopes.unsubscribes(socket, room) !== attempt.unsubscribes\n ) {\n return;\n }\n const record: ScopeSubscription = { s: request.s, c: request.c, scope: request.scope, anchors };\n hub.collections.scopes.set(socket, record);\n attempt.record = record;\n}\n\n/** Ends the subscription this subscribe made; another's is left alone. */\nfunction leave(attempt: Attempt): void {\n if (isOwn(attempt)) {\n attempt.hub.collections.scopes.delete(attempt.socket, attempt.room);\n }\n attempt.record = undefined;\n}\n\n/**\n * The subscription this subscribe recorded is no longer the socket's: ended\n * by revocation (or a disconnect), which is `FORBIDDEN` unless the client\n * unsubscribed, or replaced by a newer authorization, which stands.\n */\nfunction releaseTaken(attempt: Attempt): void {\n if (attempt.record === undefined || isOwn(attempt)) {\n return;\n }\n const { hub, socket, room } = attempt;\n attempt.record = undefined;\n const ended = hub.collections.scopes.get(socket, room) === undefined;\n if (ended && hub.collections.scopes.unsubscribes(socket, room) === attempt.unsubscribes) {\n throw forbidden();\n }\n}\n\nfunction sameAnchors(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((anchor, index) => anchor === b[index]);\n}\n\n/** True when access changed since the subscribe last authorized the scope. */\nfunction accessMoved(attempt: Attempt): boolean {\n return attempt.hub.subscriptions.accessChanges !== attempt.checkedAt;\n}\n\n/** Step 6: access changed since the subscribe last authorized the scope, so it is authorized again. */\nasync function recheckAccess(attempt: Attempt): Promise<void> {\n if (!accessMoved(attempt)) {\n return;\n }\n attempt.checkedAt = attempt.hub.subscriptions.accessChanges;\n attempt.moving = false;\n const anchors = await anchorsOf(attempt);\n if (anchors === undefined) {\n leave(attempt);\n throw forbidden();\n }\n releaseTaken(attempt);\n const { record } = attempt;\n if (record !== undefined && !sameAnchors(record.anchors, anchors)) {\n const moved: ScopeSubscription = { ...record, anchors };\n attempt.hub.collections.scopes.set(attempt.socket, moved);\n attempt.record = moved;\n attempt.moving = true;\n }\n}\n\n/** Step 6, once the reads are done: authorize again while access keeps changing, at most `MAX_RECHECKS` times. */\nasync function settleRaces(attempt: Attempt): Promise<void> {\n for (let round = 0; round < MAX_RECHECKS && accessMoved(attempt); round += 1) {\n await recheckAccess(attempt);\n }\n if (accessMoved(attempt) && attempt.moving) {\n // Access changed during the last check too, and the scope's anchors moved: they may have missed it.\n leave(attempt);\n throw forbidden();\n }\n releaseTaken(attempt);\n}\n\n/**\n * Step 2: the revision a page is read at. The last one taken, unless it is\n * below the scope's resume floor (a reset or a change nobody here received\n * was the last thing to happen): then a new one, so a client resuming from\n * the page is covered. Behind a cluster's counter, the counter's last one:\n * a resume there always reads a page, and the floor is this process's.\n */\nfunction pageRev(attempt: Attempt): Revision | Promise<Revision> {\n const { hub, request, room } = attempt;\n if (hub.revisions.shared()) {\n return hub.revisions.claim();\n }\n const rev = currentRev();\n const floor = hub.collections.buffer.floor(room, groupOf(request.s, request.c));\n return rev < floor ? nextRev() : rev;\n}\n\n/**\n * Step 6: the revision to read the page again at when a flush changed the\n * scope after `rev` (its frame may have gone out before the join), or\n * `undefined`. This process's buffer knows its own flushes only, so behind\n * a cluster's counter any revision any node took after `rev` counts.\n */\nasync function changedSince(attempt: Attempt, rev: Revision): Promise<Revision | undefined> {\n const { hub, request, room } = attempt;\n if (hub.revisions.shared()) {\n return await hub.revisions.movedPast(rev);\n }\n return hub.collections.buffer.lastChange(room, groupOf(request.s, request.c)) > rev\n ? pageRev(attempt)\n : undefined;\n}\n\n/** Steps 4 to 6. */\nasync function answer(\n attempt: Attempt,\n anchors: readonly string[],\n): Promise<CollectionSubscribeReply> {\n const { hub, storage, collection, request, room } = attempt;\n const group = groupOf(request.s, request.c);\n if (request.since !== undefined && usableChangeLog(hub) !== undefined) {\n join(attempt, anchors);\n const replay = hub.collections.buffer.since(room, request.since, group);\n if (replay !== undefined) {\n await recheckAccess(attempt);\n await settleRaces(attempt);\n return { ok: true, resumed: true, rev: replay.rev, deltas: replay.deltas };\n }\n }\n const claimed = pageRev(attempt);\n const rev = typeof claimed === \"number\" ? claimed : await claimed;\n let page = await readPage(storage, collection, request, rev);\n join(attempt, anchors);\n await recheckAccess(attempt);\n const again = attempt.record === undefined ? undefined : await changedSince(attempt, rev);\n if (again !== undefined) {\n page = await readPage(storage, collection, request, again);\n }\n await settleRaces(attempt);\n return page;\n}\n\n/**\n * Answers one `qd:col:sub` of a socket with a principal: a page, or the\n * deltas since `since`. Throws `FORBIDDEN` for a scope the principal may not\n * subscribe to, `VALIDATION` for a cursor of another collection, and the\n * error of a lookup or read that failed; a room the subscribe joined is then\n * left.\n */\nexport async function subscribeScope(\n hub: CollectionHub,\n socket: QuickdrawServerSocket,\n collection: BoundCollection,\n request: ScopeRequest,\n): Promise<CollectionSubscribeReply> {\n const { principal } = socket.data;\n const { storage } = hub;\n if (principal === null || storage === undefined) {\n throw new TypeError(\"subscribeScope: the socket has no principal, or the hub no storage\");\n }\n const room = roomOf(request);\n const attempt: Attempt = {\n hub,\n storage,\n socket,\n collection,\n principal,\n request,\n room,\n checkedAt: hub.subscriptions.accessChanges,\n unsubscribes: hub.collections.scopes.begin(socket, room),\n record: undefined,\n moving: false,\n };\n try {\n const anchors = await anchorsOf(attempt);\n if (anchors === undefined) {\n throw forbidden();\n }\n if (request.cursor !== undefined) {\n return await readPage(storage, collection, request, await pageRev(attempt));\n }\n return await answer(attempt, anchors);\n } catch (error) {\n leave(attempt);\n throw error;\n } finally {\n hub.collections.scopes.end(socket, room);\n }\n}\n","// The socket listeners of collection subscriptions (RFC 0003 sections 7.3,\n// 7.4 and 8.2): `qd:col:sub`, answered with a page (`{ ok: true, rev, items,\n// total, cursor, limit, clamped?, index? | indexTruncated? }`), with the\n// deltas since `since` (`{ ok: true, resumed: true, rev, deltas }`), or\n// `{ ok: false, e }`; `qd:col:items`, answered `{ ok: true, rev, items }` or\n// `{ ok: false, e }`; and `qd:col:unsub`, optionally acknowledged. One\n// listener per event on every v5 socket, routed by the frame, never one per\n// service or scope. None of them counts against the socket rate limiter\n// (`transports/middleware.ts`), like `qd:sub`.\n//\n// A request fails with `VALIDATION` for a malformed frame, `NOT_FOUND` for an\n// unknown service or collection, `UNAUTHENTICATED` for an anonymous socket,\n// `FORBIDDEN` for a scope the principal may not subscribe to (4.1 answered an\n// unknown collection and a denied scope alike) or, for `qd:col:items`, one\n// the socket has not subscribed to; and `INTERNAL`, logged, for a lookup or\n// read that failed. No listener throws (`emit/answer.ts`).\n\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport { answerEvent, answerNow, onDisconnect } from \"../emit/answer\";\nimport type { QuickdrawServerSocket, SocketContext } from \"../transports/types\";\nimport type { CollectionHub } from \"./bind\";\nimport {\n loadItems,\n readItemsRequest,\n readSubscribe,\n servedCollection,\n unsubscribeScope,\n} from \"./requests\";\nimport { subscribeScope } from \"./subscribe\";\n\n/**\n * The socket extension (`transports/socketio.ts`) that serves `qd:col:sub`,\n * `qd:col:items` and `qd:col:unsub` for one dispatcher's collections.\n */\nexport function collectionSubscriptions(\n hub: CollectionHub,\n): (socket: QuickdrawServerSocket, context: SocketContext) => void {\n return (socket, context) => {\n answerEvent(socket, context, CLIENT_EVENTS.collectionSub, async (frame) => {\n const request = readSubscribe(frame);\n const { collection } = servedCollection(hub, socket, request);\n return await subscribeScope(hub, socket, collection, request);\n });\n answerEvent(socket, context, CLIENT_EVENTS.collectionItems, async (frame) => {\n return await loadItems(hub, socket, readItemsRequest(frame));\n });\n socket.on(CLIENT_EVENTS.collectionUnsub, (frame: unknown, ack: unknown) => {\n answerNow(socket, context, CLIENT_EVENTS.collectionUnsub, ack, () =>\n unsubscribeScope(hub, socket, frame),\n );\n });\n onDisconnect(socket, context, () => {\n hub.collections.scopes.drop(socket);\n });\n };\n}\n","// Revoking collection subscriptions (RFC 0003 section 4.4), beside the\n// entity revocation of `emit/revocation.ts`, which calls this on every access\n// change it handles. Each scope subscription records the rows its access is\n// derived from (its anchors); when a flush may have changed someone's level\n// on one, the scopes anchored there are authorized again (`access.ts`), for\n// the user the change names or for everyone, one engine call per socket and\n// collection:\n//\n// - no longer allowed: the socket leaves the scope's room and gets\n// `qd:revoked { kind: \"collection\", reason: \"access\", s, c, scope }`;\n// - the flush deleted the anchor row: left alone, since the collection sink\n// closes that scope next with `reason: \"anchor-deleted\"`;\n// - a lookup that fails denies, as everywhere else.\n//\n// A changed `serviceAccess` re-authorizes every scope of the user's sockets.\n// 4.1 left this to a hand-written `kickFromCollection`\n// (4.1 `src/server/collections.ts:305-318`).\n\nimport { SERVER_EVENTS } from \"../../contract/names\";\nimport type { RevocationHook } from \"../emit/revocation\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport { authorizeScopes } from \"./access\";\nimport type { BoundCollection, CollectionHub } from \"./bind\";\nimport { roomOf, type ScopeSubscription } from \"./scopes\";\n\ntype Found = ReadonlyMap<QuickdrawServerSocket, readonly ScopeSubscription[]>;\n\n/** The scopes the principal may still subscribe to, or `undefined` when the lookup failed. */\nasync function allowedScopes(\n hub: CollectionHub,\n socket: QuickdrawServerSocket,\n collection: BoundCollection | undefined,\n scopes: readonly string[],\n): Promise<Map<string, readonly string[]> | undefined> {\n const { principal } = socket.data;\n if (principal === null || collection === undefined) {\n return undefined;\n }\n try {\n return await authorizeScopes(hub, collection, principal, scopes);\n } catch (error) {\n hub.logger.error(\"Authorizing subscribers' collection scopes again failed; they are revoked\", {\n category: \"quickdraw.access\",\n service: collection.service.name,\n collection: collection.name,\n error: describeError(error),\n });\n return undefined;\n }\n}\n\n/** True when the flush deleted the scope's anchor row, whose own revocation goes out next. */\nfunction anchorDeleted(\n hub: CollectionHub,\n collection: BoundCollection | undefined,\n scope: string,\n): boolean {\n const anchor = collection?.anchorService;\n return anchor !== undefined && hub.changeLog.removed(anchor.name, scope);\n}\n\n/** Authorizes one socket's subscriptions to one collection again, and applies the answer. */\nasync function reauthorize(\n hub: CollectionHub,\n socket: QuickdrawServerSocket,\n subscriptions: readonly ScopeSubscription[],\n): Promise<void> {\n const [first] = subscriptions;\n if (first === undefined) {\n return;\n }\n const collection = hub.collections.routes.find(first.s, first.c);\n const scopes = subscriptions.map(({ scope }) => scope);\n const allowed = await allowedScopes(hub, socket, collection, scopes);\n for (const subscription of subscriptions) {\n const room = roomOf(subscription);\n // Unsubscribed, subscribed again or authorized again meanwhile: that is newer than this.\n const current = hub.collections.scopes.get(socket, room) === subscription;\n if (!socket.connected || !current || anchorDeleted(hub, collection, subscription.scope)) {\n continue;\n }\n const anchors = allowed?.get(subscription.scope);\n if (anchors !== undefined) {\n hub.collections.scopes.set(socket, { ...subscription, anchors });\n continue;\n }\n hub.collections.scopes.delete(socket, room);\n const { s, c, scope } = subscription;\n socket.emit(SERVER_EVENTS.revoked, { kind: \"collection\", reason: \"access\", s, c, scope });\n }\n}\n\n/** Authorizes the given subscriptions again, one engine call per socket and collection. */\nasync function reauthorizeAll(hub: CollectionHub, found: Found): Promise<void> {\n const work: Promise<void>[] = [];\n for (const [socket, subscriptions] of found) {\n const byCollection = new Map<string, ScopeSubscription[]>();\n for (const subscription of subscriptions) {\n const key = `${subscription.s}\\u0000${subscription.c}`;\n byCollection.set(key, [...(byCollection.get(key) ?? []), subscription]);\n }\n for (const own of byCollection.values()) {\n work.push(reauthorize(hub, socket, own));\n }\n }\n await Promise.all(work);\n}\n\n/** The collection half of a dispatcher's revocation. */\nexport function createScopeRevocation(hub: CollectionHub): RevocationHook {\n return Object.freeze({\n changed: async (change) => await reauthorizeAll(hub, hub.collections.scopes.matching(change)),\n regranted: async (sockets) =>\n await reauthorizeAll(\n hub,\n new Map(sockets.map((socket) => [socket, hub.collections.scopes.entries(socket)])),\n ),\n } satisfies RevocationHook);\n}\n","// The collections of one dispatcher's live data (RFC 0003 section 7): the\n// state they keep on the hub, the flush sink that sends their deltas, the\n// socket listeners of `qd:col:sub`, `qd:col:items` and `qd:col:unsub`, their\n// half of revocation, and `dispatcher.collections.reset` for the rare change\n// tracked writes cannot describe. Change topics (`../topics.ts`) are built on\n// the same state.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { Hub } from \"../emit/hub\";\nimport { nextRev } from \"../rev\";\nimport { createCollectionState, type CollectionHub } from \"./bind\";\nimport { createCollectionSink } from \"./collectionSink\";\nimport { collectionSubscriptions } from \"./extension\";\nimport { createScopeRevocation } from \"./revocation\";\nimport { sendFrame } from \"./send\";\nimport { listenForUnnamed } from \"./unnamed\";\n\n/** What a dispatcher's live data gets from its collections. */\nexport interface LiveCollections {\n /** The hub, now holding the collections' state. */\n readonly hub: CollectionHub;\n /** Sends the flush's collection deltas: after the entity sink on the dispatcher's list. */\n readonly sink: ReturnType<typeof createCollectionSink>;\n /** Serves `qd:col:sub`, `qd:col:items` and `qd:col:unsub` on every v5 socket. */\n readonly extension: ReturnType<typeof collectionSubscriptions>;\n /** Re-authorizes collection scopes on access changes. */\n readonly revocation: ReturnType<typeof createScopeRevocation>;\n /** Sends one scope a `reset`, so its clients load it again. */\n reset(contract: AnyContract, collection: string, scope: string): void;\n /** Listens on the server the hub was given for what other nodes' flushes could not address. */\n listen(): void;\n}\n\n/** Gives `hub` its collections. Throws a `TypeError` for an anchor the dispatcher cannot authorize through. */\nexport function createLiveCollections(hub: Hub): LiveCollections {\n const withCollections: CollectionHub = Object.assign(hub, {\n collections: createCollectionState(hub.registry, hub.storage),\n });\n return Object.freeze({\n hub: withCollections,\n sink: createCollectionSink(withCollections),\n extension: collectionSubscriptions(withCollections),\n revocation: createScopeRevocation(withCollections),\n reset(contract: AnyContract, collection: string, scope: string): void {\n const service = (contract as { readonly name?: unknown } | null)?.name;\n const found =\n typeof service === \"string\"\n ? withCollections.collections.routes.find(service, collection)\n : undefined;\n if (found === undefined) {\n throw new TypeError(\n `collections.reset: ${String(service)} has no collection \"${collection}\" this dispatcher serves`,\n );\n }\n if (typeof scope !== \"string\" || scope.length === 0) {\n throw new TypeError(\"collections.reset: scope must be the scope's value, as in its room\");\n }\n sendFrame(withCollections, withCollections.io, found, scope, nextRev(), [{ t: \"reset\" }]);\n },\n listen: () => {\n listenForUnnamed(withCollections);\n },\n });\n}\n","// Typed custom room events (RFC 0003 sections 8.3 and 15): `ctx.rooms.emit(room,\n// contract, event, payload)` and `emitToUser` (also `qd.rooms.emit`, from\n// code that is not a handler), which replace 4.1's\n// `emitToRoom` and `emitToUserRoom` and the augmentable `QuickdrawEventMap`\n// (4.1 `src/server/BaseService.ts:378-441`). The event must be one the\n// contract declares, and its payload is checked against the event's schema\n// before anything is sent: a payload that fails it throws `INTERNAL` (the\n// app's bug, logged by the pipeline when a handler emits it) and no socket\n// receives a frame. What goes out is the validated payload (a Zod object\n// strips keys its schema does not name: events have no projections), as one\n// `qd:event` frame, `[service, event, payload]`, to every socket in the room\n// (on every node, through the adapter). Without a server there is nobody to\n// send to.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport { SERVER_EVENTS, userRoom } from \"../../contract/names\";\nimport type { EventFrame } from \"../../protocol/envelope\";\nimport type { Hub } from \"../emit/hub\";\nimport type { ContextRooms } from \"./types\";\nimport { checkOutgoing } from \"./validate\";\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** The event's payload schema, or a `TypeError` for an event the contract does not declare. */\nfunction payloadSchemaOf(contract: AnyContract, event: string): AnyContract[\"events\"][string] {\n const events: unknown = isRecord(contract) ? contract.events : undefined;\n if (!isRecord(events) || typeof event !== \"string\" || !Object.hasOwn(events, event)) {\n const name = isRecord(contract) ? String(contract.name) : \"the contract\";\n throw new TypeError(`ctx.rooms.emit: ${name} declares no event \"${String(event)}\"`);\n }\n return events[event] as AnyContract[\"events\"][string];\n}\n\n/** The emitting half of `ctx.rooms`, which needs no socket. */\nexport type RoomEvents = Pick<ContextRooms, \"emit\" | \"emitToUser\">;\n\n/** `ctx.rooms.emit` and `emitToUser` for one dispatcher, sending through its server once one is attached. */\nexport function createRoomEvents(hub: Hub): RoomEvents {\n const send = (room: unknown, contract: AnyContract, event: string, payload: unknown): void => {\n if (typeof room !== \"string\" || room === \"\") {\n throw new TypeError(\"ctx.rooms.emit: room must be a non-empty string\");\n }\n const def = payloadSchemaOf(contract, event);\n const checked = checkOutgoing(\n def.payload,\n payload,\n `The payload of the ${contract.name}.${event} event`,\n );\n const frame: EventFrame = [contract.name, event, checked];\n hub.io?.to(room).emit(SERVER_EVENTS.event, frame);\n };\n return Object.freeze({\n emit: (room: string, contract: AnyContract, event: string, payload: unknown) => {\n send(room, contract, event, payload);\n },\n emitToUser: (userId: string, contract: AnyContract, event: string, payload: unknown) => {\n if (typeof userId !== \"string\" || userId === \"\") {\n throw new TypeError(\"ctx.rooms.emitToUser: userId must be a non-empty string\");\n }\n send(userRoom(userId), contract, event, payload);\n },\n }) as RoomEvents;\n}\n","// The `qd:presence` frames of app rooms (RFC 0003 section 12.5): a socket\n// that joins gets `{ room, users }`, the whole list (its own user included);\n// the room's other sockets get `{ room, joined }` when it is its user's first\n// socket there, and `{ room, left }` when a user's last socket leaves or\n// disconnects; a socket that leaves, or is taken out, gets `{ room, users: [] }`.\n//\n// On the in-memory adapter the list comes from this process's records, sent\n// in order with the join. Behind a cluster adapter it is read from every node\n// (`fetchSockets`, asynchronously, and dropped when the socket left the room\n// before it arrived), and a user's last socket here leaving sends `left` only\n// when no node still has one of theirs in the room. A `joined` may then\n// repeat for a user already there on another node; a client keeps a set, so a\n// repeat changes nothing. A removal (`rooms.leave(room, { userId })`) reaches\n// every node, so each sends `left` for its last socket of the user without\n// asking the others: it may repeat, and is never missed.\n//\n// The same decision, whether a socket was its user's last in the room, is\n// what `onRoomLeave` hears as `last` (`leaving.ts`).\n\nimport { SERVER_EVENTS } from \"../../contract/names\";\nimport type { PresenceFrame } from \"../../protocol/envelope\";\nimport { track, type Hub } from \"../emit/hub\";\nimport { ownRecord } from \"../emit/subscriptions\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport { inRoom, usersInRoom, type PresenceRecords } from \"./presence\";\n\n/** Whether a socket that left a room was its user's last one there: known now, or once the other nodes answered. */\nexport type LastInRoom = boolean | Promise<boolean>;\n\n/** What the app rooms of one dispatcher share. */\nexport interface RoomState {\n readonly hub: Hub;\n readonly records: PresenceRecords;\n}\n\nfunction logFailure(state: RoomState, room: string, error: unknown): void {\n state.hub.logger.error(\"Reading a room's presence from the cluster failed\", {\n category: \"quickdraw.presence\",\n room,\n error: describeError(error),\n });\n}\n\nfunction sendList(socket: QuickdrawServerSocket, room: string, users: readonly string[]): void {\n const frame: PresenceFrame = { room, users };\n socket.emit(SERVER_EVENTS.presence, frame);\n}\n\n/** A socket entered app room `room`: it gets the list, the room hears of a new user. */\nexport function entered(state: RoomState, socket: QuickdrawServerSocket, room: string): void {\n const userId = socket.data.principal?.userId;\n const first = typeof userId === \"string\" && userId !== \"\" && state.records.entered(room, userId);\n if (first) {\n const frame: PresenceFrame = { room, joined: userId };\n socket.to(room).emit(SERVER_EVENTS.presence, frame);\n }\n if (state.hub.probe.local()) {\n sendList(socket, room, state.records.users(room) ?? []);\n return;\n }\n track(\n state.hub,\n usersInRoom(state.hub, state.records, room).then(\n (users) => {\n // A socket that left (or was taken out) meanwhile was told it sees nobody: keep it so.\n if (socket.connected && ownRecord(socket.data.appRooms, room) !== undefined) {\n sendList(socket, room, users);\n }\n },\n (error: unknown) => {\n logFailure(state, room, error);\n },\n ),\n );\n}\n\n/**\n * A socket left app room `room` (`told`: it asked to, or was taken out, and\n * is told it sees nobody now) or disconnected: the room hears when its user\n * is gone. Returns whether it was its user's last socket in the room (true\n * for an anonymous socket): on one server at once; behind a cluster adapter\n * once every node was asked (true when they cannot be), unless `everywhere`\n * says the user is being taken out on every node anyway (a removal), when\n * this node's last socket is last without asking.\n */\nexport function exited(\n state: RoomState,\n socket: QuickdrawServerSocket,\n room: string,\n told: boolean,\n everywhere = false,\n): LastInRoom {\n if (told) {\n sendList(socket, room, []);\n }\n const userId = socket.data.principal?.userId;\n if (typeof userId !== \"string\" || userId === \"\") {\n return true;\n }\n const { io } = state.hub;\n if (!state.records.exited(room, userId)) {\n return false;\n }\n if (io === undefined) {\n return true;\n }\n const frame: PresenceFrame = { room, left: userId };\n if (state.hub.probe.local() || everywhere) {\n io.to(room).emit(SERVER_EVENTS.presence, frame);\n return true;\n }\n const last = inRoom(state.hub, state.records, room, userId).then(\n (still) => {\n if (!still) {\n io.to(room).emit(SERVER_EVENTS.presence, frame);\n }\n return !still;\n },\n (error: unknown) => {\n logFailure(state, room, error);\n return true;\n },\n );\n track(state.hub, last);\n return last;\n}\n","// The names an app room may have (RFC 0003 section 12.5): `ctx.rooms` and\n// `qd.rooms` refuse the framework's own rooms (`qd:` entity, collection,\n// topic and stream rooms, and `user:` rooms), which a socket enters only\n// through their authorized paths, so a method cannot be talked into putting\n// a socket in another user's room or taking it out of one.\n\nimport { RESERVED_ROOM_PREFIXES } from \"../../contract/names\";\nimport { MAX_SCOPE_LENGTH } from \"../../protocol/version\";\nimport { unreadable } from \"../transports/ack\";\n\n/** Throws `VALIDATION` unless `room` can name an app room. */\nexport function checkRoom(room: unknown): asserts room is string {\n if (typeof room !== \"string\" || room === \"\" || room.length > MAX_SCOPE_LENGTH) {\n throw unreadable(`A room name is a string of 1 to ${MAX_SCOPE_LENGTH} characters`);\n }\n if (RESERVED_ROOM_PREFIXES.some((prefix) => room.startsWith(prefix))) {\n throw unreadable(\n `Room \"${room}\" is reserved: rooms starting with ${RESERVED_ROOM_PREFIXES.join(\" or \")} are joined only through their own subscriptions`,\n );\n }\n}\n","// Leaving app rooms (RFC 0003 section 12.5, pack H child 3's open questions):\n// a socket's own leave, a disconnect, a user taken out of a room from\n// anywhere, and the `onRoomLeave` hook that hears each of them.\n//\n// `leave(room, { userId })` takes every socket of a user out of a room, from\n// a handler or from code that is not one (`qd.rooms`): this node's sockets at\n// once, and behind a cluster adapter every other node's through an answered\n// broadcast (`ROOM_LEAVE_EVENT`, as access changes are:\n// `../cluster/broadcasts.ts`), so once it resolves the user hears nothing\n// more of the room on any node, and a channel that requires the room drops\n// their messages (the requirement reads `socket.data.appRooms`).\n//\n// Whenever a socket leaves app rooms the hooks hear of it once, on the node\n// that held the socket, with each room and whether the socket was its user's\n// last one there (`roomFrames.ts` decides it with the room's `left` frame).\n// The hooks are every service's own `onRoomLeave` (`defineService`) and the\n// server's (`createServer`), composed by `createServer` so no server root\n// can forget a service's. Each runs in a detached unit of work of its own\n// (`qd.run(fn, { detached: true })`): a leave a handler causes never joins\n// that handler's unit, and one hook's writes never flush with another's.\n// What one throws is logged with whose hook it is, and the others run all\n// the same; the hub keeps their runs in flight, so a server's `close()`\n// waits for them.\n\nimport { userRoom } from \"../../contract/names\";\nimport { answerOf } from \"../cluster/acks\";\nimport { track, type Hub } from \"../emit/hub\";\nimport { emptyRecords, ownRecord } from \"../emit/subscriptions\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport { exited, type LastInRoom, type RoomState } from \"./roomFrames\";\nimport { checkRoom } from \"./roomNames\";\nimport type { RoomLeave, RoomLeaveHandler, RoomLeaveReason, RoomLeft } from \"./types\";\n\n/** The server-to-server event `rooms.leave(room, { userId })` is broadcast on behind a cluster adapter. */\nexport const ROOM_LEAVE_EVENT = \"quickdraw:room-leave\";\n\n/** Hears every socket that left app rooms: the app's `onRoomLeave` hooks, wrapped by {@link leaveListener}. */\nexport type RoomLeaveListener = (leave: RoomLeave) => Promise<void>;\n\n/** Runs a function in a detached unit of work of the dispatcher: `dispatcher.run(fn, { detached: true })`. */\nexport type DetachedRun = (\n fn: (ctx: Parameters<RoomLeaveHandler>[1]) => Promise<void>,\n) => Promise<void>;\n\n/** One `onRoomLeave` hook, and whose it is for the logs: a service's name, or `\"createServer\"`. */\nexport interface RoomLeaveHook {\n readonly owner: string;\n readonly handler: RoomLeaveHandler;\n}\n\n/** What the app rooms of one dispatcher share, with who hears sockets leave. */\nexport interface LeavingState extends RoomState {\n listener: RoomLeaveListener | undefined;\n /** Hears a socket that left an app room and is still connected, before the hooks do. */\n readonly left?: ((socket: QuickdrawServerSocket) => void) | undefined;\n}\n\n/**\n * The app's `onRoomLeave` hooks as one listener: for each leave, every hook\n * in a detached unit of work of its own, all at once, each with what it\n * throws logged, so one failing hook stops none of the others.\n */\nexport function leaveListener(\n hooks: readonly RoomLeaveHook[],\n run: DetachedRun,\n logger: Hub[\"logger\"],\n): RoomLeaveListener {\n return async (leave) => {\n await Promise.all(\n hooks.map(async ({ owner, handler }) => {\n try {\n await run(async (ctx) => {\n await handler(leave, ctx);\n });\n } catch (error) {\n logger.error(\"onRoomLeave threw\", {\n category: \"quickdraw.rooms\",\n owner,\n socketId: leave.socketId,\n reason: leave.reason,\n rooms: leave.rooms.map(({ room }) => room),\n error: describeError(error),\n });\n }\n }),\n );\n };\n}\n\n/**\n * Tells the listener that `socket` left `left` (each room with whether it was\n * its user's last socket there, known now or once the other nodes answered).\n */\nfunction heard(\n state: LeavingState,\n socket: QuickdrawServerSocket,\n reason: RoomLeaveReason,\n left: readonly (readonly [string, LastInRoom])[],\n): void {\n const { listener } = state;\n if (listener === undefined || left.length === 0) {\n return;\n }\n const principal = socket.data.principal ?? null;\n const deliver = (rooms: readonly RoomLeft[]): void => {\n track(state.hub, listener({ principal, socketId: socket.id, reason, rooms }));\n };\n if (left.every(([, last]) => typeof last === \"boolean\")) {\n deliver(left.map(([room, last]) => ({ room, last: last as boolean })));\n return;\n }\n track(\n state.hub,\n Promise.all(left.map(async ([room, last]) => ({ room, last: await last }))).then(deliver),\n );\n}\n\n/**\n * Takes `socket` out of app room `room` (its own leave, or a removal): it is\n * told it sees nobody now, the room hears its user left when it was their\n * last socket, and the listener hears of it. `false` when it was not in it.\n */\nexport function leaveRoom(\n state: LeavingState,\n socket: QuickdrawServerSocket,\n room: string,\n reason: Exclude<RoomLeaveReason, \"disconnect\">,\n): boolean {\n const joined = socket.data.appRooms;\n if (joined === undefined || ownRecord(joined, room) === undefined) {\n return false;\n }\n delete joined[room];\n void socket.leave(room);\n if (socket.connected) {\n state.left?.(socket);\n }\n const last = exited(state, socket, room, socket.connected, reason === \"removed\");\n heard(state, socket, reason, [[room, last]]);\n return true;\n}\n\n/** A socket disconnected (Socket.IO has emptied its rooms): it leaves every app room it was in. */\nexport function leaveAll(state: LeavingState, socket: QuickdrawServerSocket): void {\n const left = Object.keys(socket.data.appRooms ?? {}).map(\n (room) => [room, exited(state, socket, room, false)] as const,\n );\n socket.data.appRooms = emptyRecords();\n heard(state, socket, \"disconnect\", left);\n}\n\n/** The user `rooms.leave(room, target)` names; a `TypeError` for anything else. */\nfunction targetUser(target: unknown): string {\n const userId: unknown =\n typeof target === \"object\" && target !== null\n ? (target as { readonly userId?: unknown }).userId\n : undefined;\n if (typeof userId !== \"string\" || userId === \"\") {\n throw new TypeError(\"rooms.leave: pass { userId } to take a user's sockets out of a room\");\n }\n return userId;\n}\n\n/** Takes this node's sockets of `userId` out of app room `room`. */\nfunction removeHere(state: LeavingState, room: string, userId: string): void {\n const { io } = state.hub;\n for (const socketId of [...(io?.sockets.adapter.rooms.get(userRoom(userId)) ?? [])]) {\n const socket = io?.sockets.sockets.get(socketId);\n if (socket?.data.principal?.userId === userId) {\n leaveRoom(state, socket, room, \"removed\");\n }\n }\n}\n\n/**\n * `rooms.leave(room, { userId })`: this node's sockets of the user at once,\n * and behind a cluster adapter every other node's, resolving once they\n * answered (at most `cluster.timeoutMs`; at once while the broadcasts are\n * degraded).\n */\nexport async function removeUser(\n state: LeavingState,\n room: unknown,\n target: unknown,\n): Promise<void> {\n checkRoom(room);\n const userId = targetUser(target);\n const { hub } = state;\n const others =\n hub.io === undefined || hub.probe.local()\n ? undefined\n : hub.broadcasts?.broadcast(ROOM_LEAVE_EVENT, { room, userId });\n removeHere(state, room, userId);\n await others;\n}\n\n/** Takes this node's sockets out of the rooms other nodes' `leave(room, { userId })` name, and answers. */\nexport function listenForRemovals(state: LeavingState): void {\n state.hub.io?.on(ROOM_LEAVE_EVENT, (broadcast: unknown, ...rest: unknown[]) => {\n const answer = answerOf(rest);\n const { room, userId } = (broadcast ?? {}) as Readonly<Record<string, unknown>>;\n try {\n checkRoom(room);\n removeHere(state, room, targetUser({ userId }));\n answer(true);\n } catch {\n answer(false);\n }\n });\n}\n","// `ctx.rooms` and `qd.rooms` (RFC 0003 sections 3 and 12.5): app-defined\n// rooms a method puts its calling socket in (a lobby, a document's viewers),\n// the typed events sent to rooms (`events.ts`), taking a user's sockets out\n// of a room from anywhere and hearing sockets leave (`leaving.ts`).\n//\n// Joining works for calls that arrived over a v5 socket; any other call gets\n// `false` back. The framework's own rooms (`qd:` entity, collection, topic\n// and stream rooms, and `user:` rooms) are refused (`roomNames.ts`).\n//\n// Each socket keeps the app rooms it joined on `socket.data.appRooms` (at\n// most `MAX_APP_ROOMS`, in an object without a prototype), so presence knows\n// what a disconnect leaves; `qd:presence` frames tell each room who comes and\n// goes (`roomFrames.ts`).\n\nimport { userRoom } from \"../../contract/names\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { emptyRecords, ownRecord } from \"../emit/subscriptions\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport { createRoomEvents } from \"./events\";\nimport {\n leaveAll,\n leaveListener,\n leaveRoom,\n listenForRemovals,\n removeUser,\n type DetachedRun,\n type LeavingState,\n type RoomLeaveHook,\n} from \"./leaving\";\nimport { markSeen, MAX_APP_ROOMS } from \"./presence\";\nimport { entered, type RoomState } from \"./roomFrames\";\nimport { checkRoom } from \"./roomNames\";\nimport type { ContextRooms, RoomTarget, ServerRooms } from \"./types\";\n\nexport { ROOM_LEAVE_EVENT, type DetachedRun, type RoomLeaveHook } from \"./leaving\";\n\nfunction join(state: LeavingState, socket: QuickdrawServerSocket, room: string): boolean {\n checkRoom(room);\n if (!socket.connected) {\n return false;\n }\n const joined = (socket.data.appRooms ??= emptyRecords<true>());\n if (ownRecord(joined, room) !== undefined) {\n return true;\n }\n if (Object.keys(joined).length >= MAX_APP_ROOMS) {\n throw new QuickdrawError(\n \"CONFLICT\",\n `A socket may be in at most ${MAX_APP_ROOMS} rooms; leave one before joining another`,\n );\n }\n joined[room] = true;\n void socket.join(room);\n entered(state, socket, room);\n return true;\n}\n\n/**\n * `rooms.size(room)`: this node's sockets in app room `room`, anonymous ones\n * included, read from the adapter's own room at once.\n */\nfunction sizeOf(state: LeavingState, room: string): number {\n checkRoom(room);\n return state.hub.io?.sockets.adapter.rooms.get(room)?.size ?? 0;\n}\n\n/** The `ctx.rooms` of each socket, of calls without one, and `qd.rooms`, for one dispatcher. */\nexport interface Rooms {\n /** The `ctx.rooms` of calls and channel messages from `socket`: made once per socket. */\n of(socket: QuickdrawServerSocket): ContextRooms;\n /** The `ctx.rooms` of calls without a socket: `join` and `leave(room)` answer `false`. */\n readonly detached: ContextRooms;\n /** `qd.rooms`, `server.rooms`, `dispatcher.rooms`: what needs no calling socket. */\n readonly server: ServerRooms;\n /** A socket disconnected (Socket.IO has emptied its rooms): its users leave its app rooms. */\n disconnected(socket: QuickdrawServerSocket): void;\n /**\n * Runs `hooks` for every socket that leaves app rooms from now on (each\n * service's `onRoomLeave` and `createServer`'s), each through `run`, a\n * detached unit of work of its own.\n */\n onLeave(hooks: readonly RoomLeaveHook[], run: DetachedRun): void;\n /** Takes this node's sockets out of rooms other nodes' `leave(room, { userId })` name. */\n listen(): void;\n}\n\n/** `leave(room)` and `leave(room, target)` in one function: `own` leaves the calling socket, if any. */\nfunction leaveOf(\n own: (room: string) => boolean,\n removal: (room: string, target: RoomTarget) => Promise<void>,\n): ContextRooms[\"leave\"] {\n return ((room: string, target?: RoomTarget) => {\n if (target !== undefined) {\n return removal(room, target);\n }\n checkRoom(room);\n return own(room);\n }) as ContextRooms[\"leave\"];\n}\n\n/**\n * Creates the rooms of one dispatcher, and their typed events (`events.ts`).\n * `left` hears each socket that left an app room and is still connected\n * (the streams open to a room's sockets check it again).\n */\nexport function createRooms(\n base: RoomState,\n left?: (socket: QuickdrawServerSocket) => void,\n): Rooms {\n const state: LeavingState = { ...base, listener: undefined, left };\n const events = createRoomEvents(state.hub);\n const removal = (room: string, target: RoomTarget): Promise<void> =>\n removeUser(state, room, target);\n const size = (room: string): number => sizeOf(state, room);\n const server: ServerRooms = Object.freeze({ ...events, leave: removal, size });\n const bySocket = new WeakMap<QuickdrawServerSocket, ContextRooms>();\n const detached: ContextRooms = Object.freeze({\n ...events,\n size,\n join: (room: string) => {\n checkRoom(room);\n return false;\n },\n leave: leaveOf(() => false, removal),\n });\n return Object.freeze({\n of(socket: QuickdrawServerSocket): ContextRooms {\n let rooms = bySocket.get(socket);\n if (rooms === undefined) {\n rooms = Object.freeze({\n ...events,\n size,\n join: (room: string) => join(state, socket, room),\n leave: leaveOf((room) => leaveRoom(state, socket, room, \"leave\"), removal),\n });\n bySocket.set(socket, rooms);\n }\n return rooms;\n },\n detached,\n server,\n disconnected(socket: QuickdrawServerSocket): void {\n leaveAll(state, socket);\n const userId = socket.data.principal?.userId;\n const sockets =\n typeof userId === \"string\"\n ? state.hub.io?.sockets.adapter.rooms.get(userRoom(userId))\n : undefined;\n if (typeof userId === \"string\" && userId !== \"\" && (sockets?.size ?? 0) === 0) {\n markSeen(state.hub, state.records, userId, Date.now());\n }\n },\n onLeave(hooks: readonly RoomLeaveHook[], run: DetachedRun): void {\n state.listener = hooks.length === 0 ? undefined : leaveListener(hooks, run, state.hub.logger);\n },\n listen(): void {\n listenForRemovals(state);\n },\n });\n}\n\n/**\n * `rooms` whose `join` and own `leave` throw `INTERNAL`: the `ctx.rooms` of\n * a method that shares its runs (`share`). A shared run serves several\n * callers with the first one's `ctx`, so it would join or leave that\n * caller's socket only. Its events (`emit`, `emitToUser`) and\n * `leave(room, { userId })` stay: they name their room or user.\n */\nexport function unjoinable(rooms: ContextRooms, share: string): ContextRooms {\n const refuse = (member: string): never => {\n throw new QuickdrawError(\n \"INTERNAL\",\n `ctx.rooms.${member} cannot run in a method that shares its runs (share: \"${share}\"): a shared run serves several callers and would ${member} only the first caller's socket; join rooms from a method without share`,\n );\n };\n return Object.freeze({\n ...rooms,\n join: () => refuse(\"join\"),\n leave: ((room: string, target?: RoomTarget) =>\n target === undefined ? refuse(\"leave\") : rooms.leave(room, target)) as ContextRooms[\"leave\"],\n });\n}\n","// Revoking stream subscriptions (RFC 0003 sections 4.4 and 12.5), beside the\n// entity, collection and topic revocations (`emit/revocation.ts`, which calls\n// this on every access change it handles). Each feed's subscription records\n// the rows its access is derived from (its anchors, `streamIndex.ts`); when a\n// flush may have changed someone's level on one, the feeds anchored there are\n// authorized again through the access engine, as a subscribe is\n// (`streamTargets.ts`), for the user the change names or for everyone. A\n// changed `serviceAccess` (`server.access.refresh`, or another node's\n// `quickdraw:grants`) authorizes every feed of the user's sockets again, so\n// a `{ service }` stream is checked against the new grants.\n//\n// - no longer allowed: the socket leaves the feed's room and gets\n// `qd:revoked { kind: \"stream\", reason: \"access\", s, stream, scope? }`, and\n// no item pushed after that reaches it;\n// - still allowed: the subscription keeps its room, with its anchors read\n// again;\n// - a lookup that fails denies, as everywhere else.\n//\n// A feed open to an app room's sockets (`access: { room }`) is checked again\n// when its socket leaves an app room, by its own leave or a removal: one it\n// no longer meets is revoked the same way, at once.\n\nimport { SERVER_EVENTS } from \"../../contract/names\";\nimport type { RevokedFrame } from \"../../protocol/envelope\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { Hub } from \"../emit/hub\";\nimport type { RevocationHook } from \"../emit/revocation\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport { streamRoomOf, subscriptionOf, type StreamIndex } from \"./streamIndex\";\nimport { authorizeStream, inStreamRoom, streamAnchors, streamTarget } from \"./streamTargets\";\nimport type { StreamSubscription } from \"./types\";\n\ntype Found = Iterable<readonly [QuickdrawServerSocket, readonly StreamSubscription[]]>;\n\n/** The anchors the subscription may keep, or `undefined` when it may no longer read the feed. */\nasync function anchorsNow(\n hub: Hub,\n socket: QuickdrawServerSocket,\n subscription: StreamSubscription,\n): Promise<readonly string[] | undefined> {\n try {\n const target = streamTarget(hub, subscription, SERVER_EVENTS.revoked);\n await authorizeStream(hub, socket, target);\n return await streamAnchors(hub, socket, target);\n } catch (error) {\n if (!(error instanceof QuickdrawError) || error.code === \"INTERNAL\") {\n hub.logger.error(\n \"Authorizing a stream subscriber again failed; the subscription is revoked\",\n {\n category: \"quickdraw.access\",\n service: subscription.s,\n stream: subscription.stream,\n error: describeError(error),\n },\n );\n }\n return undefined;\n }\n}\n\n/** Authorizes one subscription again, and applies the answer. */\nasync function reauthorize(\n hub: Hub,\n index: StreamIndex,\n socket: QuickdrawServerSocket,\n subscription: StreamSubscription,\n): Promise<void> {\n const anchors = await anchorsNow(hub, socket, subscription);\n const room = streamRoomOf(subscription);\n // Unsubscribed, subscribed again or authorized again meanwhile: that is newer than this.\n if (!socket.connected || index.get(socket, room) !== subscription) {\n return;\n }\n if (anchors !== undefined) {\n const target = streamTarget(hub, subscription, SERVER_EVENTS.revoked);\n index.set(socket, subscriptionOf(target, anchors));\n return;\n }\n revoke(index, socket, subscription);\n}\n\n/** Takes the socket out of a feed it may no longer read, and tells it: `qd:revoked`. */\nfunction revoke(\n index: StreamIndex,\n socket: QuickdrawServerSocket,\n subscription: StreamSubscription,\n): void {\n index.delete(socket, streamRoomOf(subscription));\n const { s, stream, scope } = subscription;\n const frame: RevokedFrame =\n scope === undefined\n ? { kind: \"stream\", reason: \"access\", s, stream }\n : { kind: \"stream\", reason: \"access\", s, stream, scope };\n socket.emit(SERVER_EVENTS.revoked, frame);\n}\n\n/**\n * The socket left an app room (its own leave, or taken out): each feed it\n * holds whose `access: { room }` it no longer meets is revoked at once, so\n * nothing pushed after the leave reaches it.\n */\nexport function revokeOutsideRooms(\n hub: Hub,\n index: StreamIndex,\n socket: QuickdrawServerSocket,\n): void {\n for (const subscription of index.entries(socket)) {\n const service = hub.registry.services.get(subscription.s);\n const room = service?.streams.get(subscription.stream)?.room;\n if (room !== undefined && !inStreamRoom(socket, room, subscription.scope)) {\n revoke(index, socket, subscription);\n }\n }\n}\n\n/** Authorizes the given subscriptions again, all at once. */\nasync function reauthorizeAll(hub: Hub, index: StreamIndex, found: Found): Promise<void> {\n const work: Promise<void>[] = [];\n for (const [socket, subscriptions] of found) {\n for (const subscription of subscriptions) {\n work.push(reauthorize(hub, index, socket, subscription));\n }\n }\n await Promise.all(work);\n}\n\n/** The stream half of a dispatcher's revocation. */\nexport function createStreamRevocation(hub: Hub, index: StreamIndex): RevocationHook {\n return Object.freeze({\n changed: async (change) => await reauthorizeAll(hub, index, index.matching(change)),\n regranted: async (sockets) =>\n await reauthorizeAll(\n hub,\n index,\n sockets.map((socket) => [socket, index.entries(socket)] as const),\n ),\n } satisfies RevocationHook);\n}\n","// The stream feeds of one dispatcher (RFC 0003 sections 4.4 and 12.5): the\n// index of its sockets' subscriptions (`streamIndex.ts`), the socket\n// listeners that subscribe and unsubscribe (`streamSubscriptions.ts`), and\n// the revocation hook that authorizes them again when access changes\n// (`streamRevocation.ts`), all over one index.\n\nimport type { Hub } from \"../emit/hub\";\nimport type { RevocationHook } from \"../emit/revocation\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport type { StreamSeeds } from \"./seeds\";\nimport { StreamIndex } from \"./streamIndex\";\nimport { createStreamRevocation, revokeOutsideRooms } from \"./streamRevocation\";\nimport { streamSubscriptions } from \"./streamSubscriptions\";\n\n/** One dispatcher's stream feeds. */\nexport interface StreamFeeds {\n /** Serves `qd:stream:sub` and `qd:stream:unsub` on a v5 socket. */\n readonly extension: ReturnType<typeof streamSubscriptions>;\n /** Authorizes the feeds an access change or a changed grant concerns again. */\n readonly revocation: RevocationHook;\n /** The socket left an app room: revokes its feeds open to a room it is no longer in. */\n leftRooms(socket: QuickdrawServerSocket): void;\n}\n\n/** Creates the feeds of the dispatcher whose hub this is, over its streams' seeds. */\nexport function createStreamFeeds(hub: Hub, seeds: StreamSeeds): StreamFeeds {\n const index = new StreamIndex();\n return Object.freeze({\n extension: streamSubscriptions(hub, seeds, index),\n revocation: createStreamRevocation(hub, index),\n leftRooms: (socket: QuickdrawServerSocket) => {\n revokeOutsideRooms(hub, index, socket);\n },\n });\n}\n","// Pushing to streams (RFC 0003 section 12.5): `qd.stream(contract,\n// name).push(scope, item)` (`push(item)` for a global stream). The item is\n// checked against the stream's item schema (a mismatch throws `INTERNAL`,\n// nothing is kept or sent); the validated item (a Zod object strips keys its\n// schema does not name) is kept in the scope's seed when the stream declares\n// one (`seeds.ts`), and sent to the feed's room as `qd:stream [service,\n// stream, scope, item]` (`scope` null for a global stream: positional, so a\n// frame at a game's tick rate carries no key names), volatile when the stream\n// says so. A push is synchronous and logs nothing: it may run at a game\n// loop's tick rate.\n//\n// `pushMany(scope, items)` (`pushMany(items)`) is the batch form: every item\n// is checked before any is kept or sent, then each goes out as its own frame\n// through one room operator, in order, so the client applies them exactly as\n// it applies single pushes.\n//\n// Behind a cluster adapter a stream that keeps a seed is pushed to every\n// node instead (`serverSideEmit`, the same one publish a room broadcast\n// costs), and each node keeps the items in its own seed and sends them to its\n// own sockets in the feed's room, in one step: a subscriber on any node gets\n// the latest items as its seed, and an item is either in the seed a\n// subscriber gets or sent to it after, never both and never neither. A stream\n// without a seed goes out through the adapter's room broadcast as before.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport { SERVER_EVENTS, streamRoom } from \"../../contract/names\";\nimport type { StreamFrame } from \"../../protocol/envelope\";\nimport type { Hub } from \"../emit/hub\";\nimport type { AnyService } from \"../service\";\nimport { StreamSeeds, streamKey } from \"./seeds\";\nimport { createStreamFeeds, type StreamFeeds } from \"./streamFeeds\";\nimport { scopeProblem } from \"./streamTargets\";\nimport type { ServiceStream, StreamHandle } from \"./types\";\nimport { checkOutgoing, checksItems } from \"./validate\";\n\ninterface Served {\n readonly service: AnyService;\n readonly stream: ServiceStream;\n}\n\n/** The stream `name` of the service the dispatcher serves for `contract`, or a `TypeError`. */\nfunction servedStream(hub: Hub, contract: AnyContract, name: string): Served {\n const serviceName: unknown =\n typeof contract === \"object\" && contract !== null ? contract.name : undefined;\n const service =\n typeof serviceName === \"string\" ? hub.registry.services.get(serviceName) : undefined;\n if (service === undefined) {\n throw new TypeError(\n `stream: the dispatcher serves no service named ${String(serviceName)}; pass a contract of one of its services`,\n );\n }\n const stream = typeof name === \"string\" ? service.streams.get(name) : undefined;\n if (stream === undefined) {\n throw new TypeError(`stream: ${service.name} has no stream \"${String(name)}\"`);\n }\n return { service, stream };\n}\n\n/**\n * The feed and the value `push(scope, value)` or `push(value)` names, or a\n * `TypeError`; `what` names the value in the message (`item`, `items`).\n */\nfunction feedOf(\n served: Served,\n method: string,\n what: string,\n args: readonly unknown[],\n): { readonly feed: string | undefined; readonly value: unknown } {\n const { service, stream } = served;\n const scope = stream.scoped ? args[0] : undefined;\n const problem = scopeProblem(stream, scope);\n if (problem !== undefined || args.length !== (stream.scoped ? 2 : 1)) {\n const usage = stream.scoped ? `pass (scope, ${what})` : `pass (${what})`;\n throw new TypeError(`${service.name}.${stream.name}.${method}: ${problem ?? usage}`);\n }\n return { feed: scope as string | undefined, value: stream.scoped ? args[1] : args[0] };\n}\n\n/** The server-to-server event a seeded stream's items are pushed to every node on, behind a cluster adapter. */\nexport const STREAM_PUSH_EVENT = \"quickdraw:stream-push\";\n\n/** A push another node broadcast: `{ s, stream, scope?, items }`. */\ninterface PushedItems {\n readonly s: string;\n readonly stream: string;\n readonly scope?: string;\n readonly items: readonly unknown[];\n}\n\n/**\n * Keeps `items` (already checked) in the feed's seed and sends each as a\n * frame, in order: to every node's sockets in the feed's room, or with\n * `local` (a push another node broadcast) to this node's only.\n */\nfunction send(\n hub: Hub,\n seeds: StreamSeeds,\n served: Served,\n feed: string | undefined,\n items: readonly unknown[],\n local = false,\n): void {\n const { service, stream } = served;\n for (const item of items) {\n seeds.push(streamKey(service.name, stream.name), feed, item, stream.seed);\n }\n const { io } = hub;\n if (io === undefined) {\n return;\n }\n const replicated = local || (stream.seed > 0 && !hub.probe.local());\n if (replicated && !local) {\n const pushed: PushedItems = { s: service.name, stream: stream.name, items };\n io.serverSideEmit(STREAM_PUSH_EVENT, feed === undefined ? pushed : { ...pushed, scope: feed });\n }\n const room = (replicated ? io.local : io).to(streamRoom(service.name, stream.name, feed));\n const target = stream.volatile ? room.volatile : room;\n const scope = feed ?? null;\n for (const item of items) {\n const frame: StreamFrame = [service.name, stream.name, scope, item];\n target.emit(SERVER_EVENTS.stream, frame);\n }\n}\n\nfunction push(hub: Hub, seeds: StreamSeeds, served: Served, args: readonly unknown[]): void {\n const { feed, value } = feedOf(served, \"push\", \"item\", args);\n const label = `${served.service.name}.${served.stream.name}`;\n // What is kept and sent is the validated item: streams have no projections.\n const checked = checksItems(served.stream, hub.outputValidation)\n ? checkOutgoing(served.stream.item, value, `An item pushed to ${label}`)\n : value;\n send(hub, seeds, served, feed, [checked]);\n}\n\nfunction pushMany(hub: Hub, seeds: StreamSeeds, served: Served, args: readonly unknown[]): void {\n const { feed, value } = feedOf(served, \"pushMany\", \"items\", args);\n const label = `${served.service.name}.${served.stream.name}`;\n if (!Array.isArray(value)) {\n throw new TypeError(`${label}.pushMany: pass the items as an array`);\n }\n if (!checksItems(served.stream, hub.outputValidation)) {\n send(hub, seeds, served, feed, value);\n return;\n }\n // Every item is checked before any is kept or sent.\n const checked = value.map((item: unknown, index) =>\n checkOutgoing(served.stream.item, item, `Item ${String(index)} pushed to ${label}`),\n );\n send(hub, seeds, served, feed, checked);\n}\n\n/** A push another node broadcast, read; `undefined` for anything malformed or a stream not served here. */\nfunction readPush(hub: Hub, value: unknown): { served: Served; pushed: PushedItems } | undefined {\n const { s, stream, scope, items } = (value ?? {}) as Readonly<Record<string, unknown>>;\n const service = typeof s === \"string\" ? hub.registry.services.get(s) : undefined;\n const found = typeof stream === \"string\" ? service?.streams.get(stream) : undefined;\n if (service === undefined || found === undefined || !Array.isArray(items)) {\n return undefined;\n }\n if (found.scoped ? typeof scope !== \"string\" : scope !== undefined) {\n return undefined;\n }\n const pushed: PushedItems = { s: service.name, stream: found.name, items: items as unknown[] };\n return {\n served: { service, stream: found },\n pushed: typeof scope === \"string\" ? { ...pushed, scope } : pushed,\n };\n}\n\n/** One dispatcher's streams: their seeds, the handles that push to them, and their socket listeners. */\nexport interface Streams {\n /**\n * The handle of stream `name` of `contract`'s service on this dispatcher.\n * Throws a `TypeError` when the dispatcher does not serve that stream.\n */\n handle(contract: AnyContract, name: string): StreamHandle<AnyContract, string>;\n /** Serves `qd:stream:sub` and `qd:stream:unsub` on a v5 socket. */\n readonly extension: Feeds[\"extension\"];\n /** Authorizes the feeds an access change or a changed grant concerns again (`streamRevocation.ts`). */\n readonly revocation: Feeds[\"revocation\"];\n /** Keeps and sends the items other nodes push to seeded streams, on the server the hub was given. */\n listen(): void;\n /** The socket left an app room: revokes its feeds open to a room it is no longer in. */\n readonly leftRooms: Feeds[\"leftRooms\"];\n}\n\ntype Feeds = StreamFeeds;\n\n/** Creates the streams of the dispatcher whose hub this is. */\nexport function createStreams(hub: Hub): Streams {\n const seeds = new StreamSeeds();\n const feeds = createStreamFeeds(hub, seeds);\n return Object.freeze({\n handle(contract: AnyContract, name: string): StreamHandle<AnyContract, string> {\n const served = servedStream(hub, contract, name);\n return Object.freeze({\n push: (...args: unknown[]) => {\n push(hub, seeds, served, args);\n },\n pushMany: (...args: unknown[]) => {\n pushMany(hub, seeds, served, args);\n },\n }) as StreamHandle<AnyContract, string>;\n },\n extension: feeds.extension,\n revocation: feeds.revocation,\n leftRooms: feeds.leftRooms,\n listen: () => {\n hub.io?.on(STREAM_PUSH_EVENT, (broadcast: unknown) => {\n const received = readPush(hub, broadcast);\n if (received !== undefined) {\n const { served, pushed } = received;\n send(hub, seeds, served, pushed.scope, pushed.items, true);\n }\n });\n },\n });\n}\n","// Presence, streams, channels and typed room events for one dispatcher (RFC\n// 0003 section 12.5), made with its live data (`emit/live.ts`): the socket\n// listeners they add to every v5 socket, `ctx.rooms` and `ctx.presence` for\n// each call, and the stream handles `qd.stream(contract, name)` returns.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { RoomOccupancy } from \"../context\";\nimport { onDisconnect } from \"../emit/answer\";\nimport type { Hub } from \"../emit/hub\";\nimport type { QuickdrawServerSocket, SocketContext } from \"../transports/types\";\nimport { channelMessages } from \"./channels\";\nimport { createPresence, PresenceRecords } from \"./presence\";\nimport { createRooms, unjoinable, type DetachedRun, type RoomLeaveHook } from \"./rooms\";\nimport { createStreams, type Streams } from \"./streams\";\nimport type {\n ContextRooms,\n Presence,\n RoomLeave,\n RoomLeaveHandler,\n ServerRooms,\n StreamHandle,\n} from \"./types\";\n\nexport type {\n DetachedRun,\n Presence,\n RoomLeave,\n RoomLeaveHandler,\n RoomLeaveHook,\n ServerRooms,\n StreamHandle,\n};\n\n/** The realtime half of one dispatcher's live data. */\nexport interface Realtime {\n /** Serves `qd:ch`, `qd:stream:sub` and `qd:stream:unsub`, and leaves app rooms on disconnect. */\n extension(socket: QuickdrawServerSocket, context: SocketContext): void;\n /** `ctx.presence`, `dispatcher.presence` and `server.presence`. */\n readonly presence: Presence;\n /** `qd.rooms`, `dispatcher.rooms` and `server.rooms`: app rooms from code that is not a handler. */\n readonly rooms: ServerRooms;\n /**\n * Runs `hooks` for every socket that leaves app rooms, each through `run`,\n * a detached unit of work of the dispatcher: every service's `onRoomLeave`\n * and `createServer`'s.\n */\n onRoomLeave(hooks: readonly RoomLeaveHook[], run: DetachedRun): void;\n /**\n * The `ctx.rooms` of a call: its socket's for a call over a v5 socket, else\n * one that joins nothing. For a method that shares its runs (`share`),\n * `join` and `leave` throw `INTERNAL`: a shared run serves several callers,\n * and would join or leave only the first one's socket.\n */\n roomsFor(transport: string, connectionId: string | undefined, share?: string): ContextRooms;\n /** The handle of a stream this dispatcher serves; a `TypeError` for any other. */\n stream(contract: AnyContract, name: string): StreamHandle<AnyContract, string>;\n /** The sockets in a room of the attached server, for the kits (`KitRuntime.occupancy`). */\n readonly occupancy: RoomOccupancy;\n /** Revokes stream subscriptions on access changes and changed grants. */\n readonly revocation: Streams[\"revocation\"];\n /**\n * Listens on the server the hub was given for the items other nodes push\n * to seeded streams, and for their `rooms.leave(room, { userId })`.\n */\n listen(): void;\n}\n\n/** Creates the realtime half of a dispatcher's live data, on its hub. */\nexport function createRealtime(hub: Hub): Realtime {\n const records = new PresenceRecords();\n const presence = createPresence(hub, records);\n const streams = createStreams(hub);\n const rooms = createRooms({ hub, records }, streams.leftRooms);\n const channels = channelMessages({ hub, rooms, presence, warned: new WeakSet() });\n return Object.freeze({\n extension(socket: QuickdrawServerSocket, context: SocketContext): void {\n channels(socket);\n streams.extension(socket, context);\n onDisconnect(socket, context, () => {\n rooms.disconnected(socket);\n });\n },\n presence,\n rooms: rooms.server,\n onRoomLeave: (hooks: readonly RoomLeaveHook[], run: DetachedRun) => {\n rooms.onLeave(hooks, run);\n },\n roomsFor(transport: string, connectionId: string | undefined, share?: string): ContextRooms {\n const socket =\n transport === \"socket\" && connectionId !== undefined\n ? hub.io?.sockets.sockets.get(connectionId)\n : undefined;\n const own = socket === undefined ? rooms.detached : rooms.of(socket);\n return share === undefined ? own : unjoinable(own, share);\n },\n stream: (contract: AnyContract, name: string) => streams.handle(contract, name),\n occupancy: Object.freeze({\n sockets: (room: string) => hub.io?.sockets.adapter.rooms.get(room)?.size ?? 0,\n complete: () => hub.io === undefined || hub.probe.local(),\n }),\n revocation: streams.revocation,\n listen: () => {\n streams.listen();\n rooms.listen();\n },\n });\n}\n","// The change topics a flush changed (RFC 0003 sections 5.3 and 11.3), and the\n// sink that tells their watchers: `qd:changed { s, topic, rev }`, once per\n// flush per topic, to the topic's room. It carries no data; a client\n// invalidates the queries that watch the topic and reads them again. It\n// replaces 4.1's `invalidateOn`, which named hand-written events.\n//\n// Per flush:\n//\n// - the service topic of every service the flush changed: one of its rows\n// (written, touched, or reached by an `affects` hop), a junction link of\n// one of its `via` collections, a row of a model it lists in `writes` (a\n// game's high scores: a query over them watches the service), or a scope\n// it lost when the row it was anchored on was deleted. Its frame names\n// those models (`models`, finding F7.3 of the quickdraw-chat review), so\n// a query that watches only some (`watch: { service: [models] }`) ignores\n// a flush that wrote none of them: the service's model for its own rows\n// and lost scopes, the junction's for a link, the written one for\n// `writes`;\n// - the topic of every collection scope a touched row was in before or after\n// the flush, from the same moves the collection sink finds (`moves.ts`,\n// shared, so a flush reads their rows once); a row that left scopes nobody\n// can name, or junction rows removed without values, change every scope\n// watched here; and a scope closed by deleting its anchor row changed too.\n//\n// Only topics a socket here watches are computed, and a collection none of\n// whose topics is watched here reads nothing. Behind a cluster adapter other\n// nodes' rooms are not visible, so every changed topic is sent.\n//\n// A failure while finding the moves still tells the watchers: every topic\n// watched here that the flush may have changed gets `qd:changed`, and the\n// error is rethrown to be logged.\n\nimport { collectionTopic, SERVER_EVENTS, SERVICE_TOPIC, topicRoom } from \"../../contract/names\";\nimport type { ChangedFrame, Revision } from \"../../protocol/envelope\";\nimport { touchedRows, type TouchedRows } from \"../emit/affects\";\nimport { modelKey, type StorageAdapter } from \"../storage\";\nimport type { TopicIndex } from \"../topicIndex\";\nimport type { FlushInfo, FlushSink } from \"../uow/flushSink\";\nimport type { WriteRecord } from \"../uow/types\";\nimport { anchoredScopes, type BoundCollection, type CollectionHub } from \"./bind\";\nimport { workOf } from \"./collectionSink\";\nimport { movesOf, type Moves } from \"./moves\";\n\ntype Io = NonNullable<CollectionHub[\"io\"]>;\n\n/** The `qd:changed` frames of one flush, by topic room: one per topic. */\ntype Frames = Map<string, ChangedFrame>;\n\n/** Per model (`modelKey`), the services that list it in their `writes`. */\ntype Writers = ReadonlyMap<string, readonly BoundCollection[\"service\"][]>;\n\n/** What finding a flush's topics needs. */\ninterface Flush {\n readonly hub: CollectionHub;\n readonly index: TopicIndex;\n readonly writers: Writers;\n readonly writes: readonly WriteRecord[];\n readonly touched: TouchedRows;\n readonly rev: Revision;\n /** Whether every subscriber is a socket of this process (no cluster adapter). */\n readonly local: boolean;\n readonly frames: Frames;\n}\n\nfunction mark(flush: Flush, s: string, topic: string): void {\n flush.frames.set(topicRoom(s, topic), { s, topic, rev: flush.rev });\n}\n\n/** Marks a service's topic with the models whose writes changed it, sorted (finding F7.3). */\nfunction markService(flush: Flush, s: string, models: ReadonlySet<string>): void {\n const topic = SERVICE_TOPIC;\n flush.frames.set(topicRoom(s, topic), { s, topic, rev: flush.rev, models: [...models].sort() });\n}\n\n/** Marks one collection scope's topic when it may be watched: here, or anywhere behind a cluster adapter. */\nfunction markScope(flush: Flush, collection: BoundCollection, scope: string): void {\n const s = collection.service.name;\n if (!flush.local || flush.index.watchesScope(s, collection.name, scope)) {\n mark(flush, s, collectionTopic(collection.name, scope));\n }\n}\n\n/** The services that list each model in their `writes`, by `modelKey`. */\nfunction writersOf(hub: CollectionHub): Writers {\n const writers = new Map<string, BoundCollection[\"service\"][]>();\n for (const service of hub.registry.services.values()) {\n for (const model of service.writes) {\n const key = modelKey(model);\n writers.set(key, [...(writers.get(key) ?? []), service]);\n }\n }\n return writers;\n}\n\ntype Service = BoundCollection[\"service\"];\n\n/** Adds `model` to the models that changed `service`'s topic. */\nfunction changedBy(changed: Map<Service, Set<string>>, service: Service, model: string): void {\n const models = changed.get(service) ?? new Set<string>();\n models.add(modelKey(model));\n changed.set(service, models);\n}\n\n/**\n * The services whose rows or collection scopes the flush changed, and those\n * that list a written model in their `writes` (a query over such a model\n * watches the writing service's topic), each with the models that changed\n * it: the service's own model for its rows (written, touched, reached by\n * an `affects` hop) and for scopes a deleted anchor closed, which took its\n * rows with them; the junction model for a `via` link; the written model\n * for one in `writes`.\n */\nfunction changedServices(flush: Flush): Map<Service, Set<string>> {\n const changed = new Map<Service, Set<string>>();\n for (const service of flush.touched.keys()) {\n if (service.model !== undefined) {\n changedBy(changed, service, service.model);\n }\n }\n const { routes } = flush.hub.collections;\n for (const write of flush.writes) {\n const key = modelKey(write.model);\n for (const collection of routes.byJunction.get(key) ?? []) {\n changedBy(changed, collection.service, key);\n }\n for (const writer of flush.writers.get(key) ?? []) {\n changedBy(changed, writer, key);\n }\n }\n for (const [collection] of anchoredScopes(routes, flush.writes)) {\n const { service } = collection;\n if (service.model !== undefined) {\n changedBy(changed, service, service.model);\n }\n }\n return changed;\n}\n\n/** Marks the service topics and the scopes closed by a deleted anchor row: neither needs a read. */\nfunction markUnread(flush: Flush): void {\n for (const [service, models] of changedServices(flush)) {\n if (!flush.local || flush.index.watchesService(service.name)) {\n markService(flush, service.name, models);\n }\n }\n for (const [collection, scope] of anchoredScopes(flush.hub.collections.routes, flush.writes)) {\n markScope(flush, collection, scope);\n }\n}\n\n/** The scopes one collection's moves changed: every scope a row left, entered or changed in. */\nfunction scopesOf(moves: Moves, watched: ReadonlySet<string>): Set<string> {\n const scopes = new Set<string>();\n for (const move of moves.moves) {\n for (const scope of [...move.left, ...move.entered, ...move.stayed]) {\n scopes.add(scope);\n }\n for (const scope of move.unknownLeft ? watched : []) {\n scopes.add(scope);\n }\n }\n for (const scope of moves.resetAll ? watched : []) {\n scopes.add(scope);\n }\n return scopes;\n}\n\n/** Finds the topics `writes` changed, reading what their collections' moves need. */\nasync function findTopics(flush: Flush, storage: StorageAdapter): Promise<void> {\n markUnread(flush);\n const { hub, writes } = flush;\n await Promise.all(\n workOf(hub, writes, flush.touched).map(async ({ collection, refresh }) => {\n const watched = flush.index.scopes(collection.service.name, collection.name);\n if (flush.local && watched.size === 0) {\n return;\n }\n const moves = await movesOf(\n hub.collections.moves,\n storage,\n collection,\n writes,\n refresh,\n !flush.local,\n );\n for (const scope of scopesOf(moves, watched)) {\n markScope(flush, collection, scope);\n }\n }),\n );\n}\n\n/** Marks every watched topic the flush may have changed, without reading: the moves could not be found. */\nfunction markWatched(flush: Flush): void {\n markUnread(flush);\n for (const { collection } of workOf(flush.hub, flush.writes, flush.touched)) {\n for (const scope of flush.index.scopes(collection.service.name, collection.name)) {\n markScope(flush, collection, scope);\n }\n }\n}\n\nfunction send(io: Io, frames: Frames): void {\n for (const [room, frame] of frames) {\n io.to(room).emit(SERVER_EVENTS.changed, frame);\n }\n}\n\n/** The topic sink of a dispatcher: after the collection sink on the dispatcher's list. */\nexport function createTopicSink(hub: CollectionHub, index: TopicIndex): FlushSink {\n const writers = writersOf(hub);\n return Object.freeze({\n async flush(writes: readonly WriteRecord[], info: FlushInfo): Promise<void> {\n const { io, storage } = hub;\n if (io === undefined || storage === undefined) {\n return;\n }\n const flush: Flush = {\n hub,\n index,\n writers,\n writes,\n touched: touchedRows(writes, hub.routes),\n rev: info.rev,\n local: hub.probe.local(),\n frames: new Map(),\n };\n try {\n await findTopics(flush, storage);\n } catch (error) {\n markWatched(flush);\n throw error;\n } finally {\n send(io, flush.frames);\n }\n },\n });\n}\n","// The change topics this process's sockets watch (RFC 0003 section 11.3). A\n// query whose contract declares `watch` makes the client join that topic\n// with `qd:watch { s, topic }`: `{collection}:{scope}` for one scope of a\n// collection, or `service` for the whole service. Each socket keeps its own\n// watches on `socket.data.topics`, by room; the index counts them per scope\n// and per service, so a flush computes only the topics someone here watches,\n// and finds the watches an access change can concern by the rows a scope's\n// access is derived from (its anchors), as `collections/scopes.ts` does.\n// Rooms stay the source of truth for who receives `qd:changed`.\n\nimport { SERVICE_TOPIC, topicRoom } from \"../contract/names\";\nimport { MAX_SCOPE_LENGTH } from \"../protocol/version\";\nimport type { AccessChange } from \"./access/changes\";\nimport { anchorKey } from \"./access/tools\";\nimport { PendingKeys } from \"./emit/pending\";\nimport { count, emptyRecords, ownRecord, serviceOf, type Counts } from \"./emit/subscriptions\";\nimport { unreadable } from \"./transports/ack\";\nimport type { QuickdrawServerSocket } from \"./transports/types\";\n\n/** One watched topic, as `socket.data.topics[room]` records it. */\nexport interface TopicWatch {\n /** The service name. */\n readonly s: string;\n /** The topic as the frame names it: `service`, or `{collection}:{scope}`. */\n readonly topic: string;\n /** The collection of a collection scope's topic; absent for the service topic. */\n readonly c?: string;\n /** The scope of a collection scope's topic; absent for the service topic. */\n readonly scope?: string;\n /**\n * The rows a collection scope's watch is authorized through (`anchorKey`s):\n * the anchor row, then its `inherit` parents. None for the service topic\n * or a `\"self\"` scope.\n */\n readonly anchors?: readonly string[];\n}\n\n/**\n * `socket.data.topics`: a socket's watched topics, by room. Plain data, in an\n * object without a prototype, read by own keys only.\n */\nexport type TopicWatches = Record<string, TopicWatch>;\n\nfunction isName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\n/**\n * Reads a `qd:watch` or `qd:unwatch` frame, `{ s, topic }`, or throws\n * `VALIDATION`. A topic other than `service` is `{collection}:{scope}`,\n * split at its first colon: the collection name holds none, the scope may.\n */\nexport function readWatch(value: unknown, event: string): TopicWatch {\n const frame =\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Readonly<Record<string, unknown>>)\n : {};\n const { s, topic } = frame;\n if (!isName(s) || !isName(topic)) {\n throw unreadable(`A ${event} frame needs { s, topic } with each a non-empty string`);\n }\n if (topic.length > MAX_SCOPE_LENGTH) {\n throw unreadable(`topic must be at most ${MAX_SCOPE_LENGTH} characters`, [\"topic\"]);\n }\n if (topic === SERVICE_TOPIC) {\n return { s, topic };\n }\n const colon = topic.indexOf(\":\");\n if (colon <= 0 || colon === topic.length - 1) {\n throw unreadable(`topic must be \"${SERVICE_TOPIC}\" or {collection}:{scope}`, [\"topic\"]);\n }\n return { s, topic, c: topic.slice(0, colon), scope: topic.slice(colon + 1) };\n}\n\nfunction groupOf(service: string, collection: string): string {\n return `${service}\\u0000${collection}`;\n}\n\nconst NONE: ReadonlySet<string> = Object.freeze(new Set<string>());\n\n/** The topics sockets of this process watch, counted per service and per collection scope. */\nexport class TopicIndex {\n /** Per service, how many sockets here watch its service topic. */\n readonly #services = new Map<string, number>();\n /** Per collection (`service\\0collection`), how many sockets here watch each scope's topic. */\n readonly #scopes = new Map<string, Map<string, number>>();\n /** The topics each socket has a `qd:watch` in flight for, by room. */\n readonly #pending = new PendingKeys();\n readonly #byAnchor = new Map<string, Counts>();\n readonly #byAnchorService = new Map<string, Counts>();\n\n #index(socket: QuickdrawServerSocket, watch: TopicWatch, by: 1 | -1): void {\n for (const anchor of watch.anchors ?? []) {\n count(this.#byAnchor, anchor, socket, by);\n count(this.#byAnchorService, serviceOf(anchor), socket, by);\n }\n }\n\n #count(watch: TopicWatch, by: 1 | -1): void {\n const { c, scope } = watch;\n if (c === undefined || scope === undefined) {\n const next = (this.#services.get(watch.s) ?? 0) + by;\n if (next > 0) {\n this.#services.set(watch.s, next);\n } else {\n this.#services.delete(watch.s);\n }\n return;\n }\n const key = groupOf(watch.s, c);\n const scopes = this.#scopes.get(key) ?? new Map<string, number>();\n const next = (scopes.get(scope) ?? 0) + by;\n if (next > 0) {\n scopes.set(scope, next);\n this.#scopes.set(key, scopes);\n return;\n }\n scopes.delete(scope);\n if (scopes.size === 0) {\n this.#scopes.delete(key);\n }\n }\n\n /** Records a watch and puts the socket in the topic's room; watching a topic again records its anchors anew. */\n watch(socket: QuickdrawServerSocket, watch: TopicWatch): void {\n const room = topicRoom(watch.s, watch.topic);\n const watches = (socket.data.topics ??= emptyRecords());\n const previous = ownRecord(watches, room);\n watches[room] = watch;\n this.#index(socket, watch, 1);\n if (previous === undefined) {\n this.#count(watch, 1);\n } else {\n this.#index(socket, previous, -1);\n }\n void socket.join(room);\n }\n\n /** The socket's watch of a topic, by room, or `undefined`. */\n get(socket: QuickdrawServerSocket, room: string): TopicWatch | undefined {\n return ownRecord(socket.data.topics, room);\n }\n\n /** Every topic the socket watches. */\n entries(socket: QuickdrawServerSocket): TopicWatch[] {\n return Object.values(socket.data.topics ?? {});\n }\n\n /** Ends a watch the socket may no longer hold: it leaves the topic's room. */\n leave(socket: QuickdrawServerSocket, room: string): void {\n const watches = socket.data.topics;\n const watch = ownRecord(watches, room);\n if (watches !== undefined && watch !== undefined) {\n delete watches[room];\n this.#count(watch, -1);\n this.#index(socket, watch, -1);\n }\n void socket.leave(room);\n }\n\n /** A `qd:watch` of the topic begins; returns how often it was unwatched so far. */\n begin(socket: QuickdrawServerSocket, room: string): number {\n return this.#pending.begin(socket, [room]).get(room) ?? 0;\n }\n\n /** The watch `begin` started has ended. */\n end(socket: QuickdrawServerSocket, room: string): void {\n this.#pending.end(socket, [room]);\n }\n\n /** A client unwatched: the socket leaves the topic's room, and a watch still being authorized will not join it. */\n unwatch(socket: QuickdrawServerSocket, room: string): void {\n this.#pending.unsubscribed(socket, room);\n this.leave(socket, room);\n }\n\n /** How often the client unwatched the topic while a watch of it ran; it joins only if that did not move. */\n unwatches(socket: QuickdrawServerSocket, room: string): number {\n return this.#pending.count(socket, room);\n }\n\n /** A socket disconnected: Socket.IO has emptied its rooms; drop its watches from the counts. */\n drop(socket: QuickdrawServerSocket): void {\n for (const watch of this.entries(socket)) {\n this.#count(watch, -1);\n this.#index(socket, watch, -1);\n }\n socket.data.topics = emptyRecords();\n }\n\n /**\n * The watches an access change can concern: those of collection scopes\n * anchored on the changed row (any row of the service when `id` is\n * absent), of the changed user's sockets (every user's when `userId` is\n * absent).\n */\n matching(change: AccessChange): Map<QuickdrawServerSocket, TopicWatch[]> {\n const key = change.id === undefined ? undefined : anchorKey(change.service, change.id);\n const sockets =\n key === undefined ? this.#byAnchorService.get(change.service) : this.#byAnchor.get(key);\n const found = new Map<QuickdrawServerSocket, TopicWatch[]>();\n for (const socket of sockets?.keys() ?? []) {\n if (change.userId !== undefined && socket.data.principal?.userId !== change.userId) {\n continue;\n }\n const watches = this.entries(socket).filter(({ anchors = [] }) =>\n anchors.some((anchor) =>\n key === undefined ? serviceOf(anchor) === change.service : anchor === key,\n ),\n );\n if (watches.length > 0) {\n found.set(socket, watches);\n }\n }\n return found;\n }\n\n /** True when a socket of this process watches the service's topic. */\n watchesService(service: string): boolean {\n return this.#services.has(service);\n }\n\n /** The scopes of a collection whose topics sockets of this process watch. */\n scopes(service: string, collection: string): ReadonlySet<string> {\n const scopes = this.#scopes.get(groupOf(service, collection));\n return scopes === undefined ? NONE : new Set(scopes.keys());\n }\n\n /** True when a socket of this process watches the topic of one scope of a collection. */\n watchesScope(service: string, collection: string, scope: string): boolean {\n return this.#scopes.get(groupOf(service, collection))?.has(scope) ?? false;\n }\n}\n","// Revoking change topic watches (RFC 0003 sections 4.4 and 11.3), beside the\n// entity and collection revocations (`emit/revocation.ts`, which calls this\n// on every access change it handles). A `qd:changed` carries no data, but it\n// still tells a watcher when a scope changes: a socket that lost access to a\n// scope must stop hearing about it. Each watch of a collection scope records\n// the rows its access is derived from (its anchors); when a flush may have\n// changed someone's level on one, the watches anchored there are authorized\n// again, and a changed `serviceAccess` authorizes every watch of the user's\n// sockets again, service topics included (`watchAccess: { service }`).\n//\n// A watch no longer allowed leaves the topic's room. No new frame kind says\n// so: the socket gets one last `qd:changed` for the topic, its client reads\n// the watching query again, and that read is refused. A lookup that fails\n// denies, as everywhere else.\n\nimport { SERVER_EVENTS, topicRoom } from \"../contract/names\";\nimport { QuickdrawError } from \"../protocol/errors\";\nimport { authorizeWatch, type WatchTarget } from \"./collections/access\";\nimport type { CollectionHub } from \"./collections/bind\";\nimport type { RevocationHook } from \"./emit/revocation\";\nimport { describeError } from \"./pipeline/metrics\";\nimport { currentRev } from \"./rev\";\nimport type { TopicIndex, TopicWatch } from \"./topicIndex\";\nimport type { QuickdrawServerSocket } from \"./transports/types\";\n\n/** What a watch names, or `NOT_FOUND`. */\nexport function targetOf(hub: CollectionHub, watch: TopicWatch): WatchTarget {\n const service = hub.registry.services.get(watch.s);\n if (service === undefined) {\n throw new QuickdrawError(\"NOT_FOUND\", `Unknown service \"${watch.s}\"`);\n }\n const { c, scope } = watch;\n if (service.model === undefined && (c !== undefined || service.writes.length === 0)) {\n throw new QuickdrawError(\n \"NOT_FOUND\",\n `${watch.s} has no rows whose changes could be watched: it declares no model and writes nothing`,\n );\n }\n if (c === undefined || scope === undefined) {\n return { kind: \"service\", service };\n }\n const collection = hub.collections.routes.find(watch.s, c);\n if (collection === undefined) {\n throw new QuickdrawError(\"NOT_FOUND\", `${watch.s} has no collection \"${c}\"`);\n }\n return { kind: \"collection\", collection, scope };\n}\n\n/** The anchors the watch may keep, or `undefined` when it may no longer watch its topic. */\nasync function anchorsNow(\n hub: CollectionHub,\n socket: QuickdrawServerSocket,\n watch: TopicWatch,\n): Promise<readonly string[] | undefined> {\n try {\n return await authorizeWatch(hub, socket.data.principal, targetOf(hub, watch));\n } catch (error) {\n if (!(error instanceof QuickdrawError) || error.code === \"INTERNAL\") {\n hub.logger.error(\"Authorizing a watched topic again failed; the watch is revoked\", {\n category: \"quickdraw.access\",\n service: watch.s,\n topic: watch.topic,\n error: describeError(error),\n });\n }\n return undefined;\n }\n}\n\n/** Authorizes one watch again, and applies the answer. */\nasync function rewatch(\n hub: CollectionHub,\n index: TopicIndex,\n socket: QuickdrawServerSocket,\n watch: TopicWatch,\n): Promise<void> {\n const anchors = await anchorsNow(hub, socket, watch);\n const room = topicRoom(watch.s, watch.topic);\n // Unwatched, watched again or authorized again meanwhile: that is newer than this.\n if (!socket.connected || index.get(socket, room) !== watch) {\n return;\n }\n if (anchors !== undefined) {\n index.watch(socket, { ...watch, anchors });\n return;\n }\n index.leave(socket, room);\n socket.emit(SERVER_EVENTS.changed, { s: watch.s, topic: watch.topic, rev: currentRev() });\n}\n\n/** Authorizes the given watches again, each socket's one by one. */\nasync function rewatchAll(\n hub: CollectionHub,\n index: TopicIndex,\n found: Iterable<readonly [QuickdrawServerSocket, readonly TopicWatch[]]>,\n): Promise<void> {\n const work: Promise<void>[] = [];\n for (const [socket, watches] of found) {\n for (const watch of watches) {\n work.push(rewatch(hub, index, socket, watch));\n }\n }\n await Promise.all(work);\n}\n\n/** The topic half of a dispatcher's revocation. */\nexport function createTopicRevocation(hub: CollectionHub, index: TopicIndex): RevocationHook {\n return Object.freeze({\n changed: async (change) => await rewatchAll(hub, index, index.matching(change)),\n regranted: async (sockets) =>\n await rewatchAll(\n hub,\n index,\n sockets.map((socket) => [socket, index.entries(socket)] as const),\n ),\n } satisfies RevocationHook);\n}\n","// Change topics (RFC 0003 section 11.3): how a query learns that the data it\n// read has changed without hand-written event names. A query whose contract\n// declares `watch: { collection, scope }` makes the client join the topic\n// `{collection}:{scope}` of its service; a query that depends on the whole\n// service joins `service`. The server then sends `qd:changed { s, topic, rev\n// }` once per flush that changed the topic (`collections/changed.ts`), and\n// the client invalidates the query. The frame carries no data: rows travel\n// as entity frames and collection deltas, never as a change signal. Topics\n// reuse collection scopes, so nothing is declared twice.\n//\n// `qd:watch { s, topic }` is answered `{ ok: true }` or `{ ok: false, e }`,\n// and joins the topic's room. It is authorized, and sends no snapshot:\n//\n// - `{collection}:{scope}` exactly as `qd:col:sub` of that scope is\n// (`collections/access.ts`): `UNAUTHENTICATED` for an anonymous socket,\n// `FORBIDDEN` for a scope the principal may not subscribe to;\n// - `service` by the service's `watchAccess` (`\"public\"`, `\"authenticated\"`\n// or `{ service: level }`); without one the topic is closed, `FORBIDDEN`\n// for everyone, since it changes whenever any row of the service does.\n//\n// A malformed frame is `VALIDATION`, an unknown service or collection (or a\n// service without a model that writes nothing, whose topic never changes)\n// `NOT_FOUND`. A service's topic also changes with every write to a model it\n// lists in `writes`, so a query over such a model declares `watch:\n// \"service\"`.\n// `qd:unwatch { s, topic }` is checked the same way, leaves the room,\n// optionally acknowledged, and stops a watch still being authorized from\n// joining. Neither counts against the socket rate limiter\n// (`transports/middleware.ts`), and neither listener throws\n// (`emit/answer.ts`). A watch whose access the socket loses leaves its room,\n// after one last `qd:changed` (`topicRevocation.ts`).\n\nimport { CLIENT_EVENTS, topicRoom } from \"../contract/names\";\nimport type { Ok } from \"../protocol/envelope\";\nimport { QuickdrawError } from \"../protocol/errors\";\nimport { authorizeWatch } from \"./collections/access\";\nimport type { CollectionHub } from \"./collections/bind\";\nimport { createTopicSink } from \"./collections/changed\";\nimport { answerEvent, answerNow, onDisconnect } from \"./emit/answer\";\nimport { readWatch, TopicIndex } from \"./topicIndex\";\nimport { createTopicRevocation, targetOf } from \"./topicRevocation\";\nimport type { QuickdrawServerSocket, SocketContext } from \"./transports/types\";\n\n/** Serves one `qd:watch`: authorizes it, then joins the topic's room unless the client unwatched meanwhile. */\nasync function watchTopic(\n hub: CollectionHub,\n index: TopicIndex,\n socket: QuickdrawServerSocket,\n frame: unknown,\n): Promise<Ok> {\n const watch = readWatch(frame, CLIENT_EVENTS.watch);\n const target = targetOf(hub, watch);\n if (hub.storage === undefined) {\n throw new QuickdrawError(\n \"INTERNAL\",\n \"Change topics follow tracked writes: pass db as trackPrisma(prisma)\",\n );\n }\n const room = topicRoom(watch.s, watch.topic);\n const unwatches = index.begin(socket, room);\n try {\n const anchors = await authorizeWatch(hub, socket.data.principal, target);\n if (socket.connected && index.unwatches(socket, room) === unwatches) {\n index.watch(socket, { ...watch, anchors });\n }\n } finally {\n index.end(socket, room);\n }\n return { ok: true };\n}\n\n/**\n * Serves one `qd:unwatch`: the socket leaves the topic's room. Throws\n * `VALIDATION` for a malformed frame, `NOT_FOUND` for an unknown service or\n * collection, and `UNAUTHENTICATED` for an anonymous socket, which can watch\n * nothing but a public service topic.\n */\nfunction unwatchTopic(\n hub: CollectionHub,\n index: TopicIndex,\n socket: QuickdrawServerSocket,\n frame: unknown,\n): Ok {\n const watch = readWatch(frame, CLIENT_EVENTS.unwatch);\n const target = targetOf(hub, watch);\n const open = target.kind === \"service\" && target.service.watchAccess === \"public\";\n if (socket.data.principal === null && !open) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n index.unwatch(socket, topicRoom(watch.s, watch.topic));\n return { ok: true };\n}\n\n/** The change topics of one dispatcher. */\nexport interface Topics {\n /** Sends `qd:changed` for the flush's topics: after the collection sink on the dispatcher's list. */\n readonly sink: ReturnType<typeof createTopicSink>;\n /** Serves `qd:watch` and `qd:unwatch` on every v5 socket. */\n readonly extension: (socket: QuickdrawServerSocket, context: SocketContext) => void;\n /** Authorizes watches again on access changes: a watch a socket lost leaves its room (`topicRevocation.ts`). */\n readonly revocation: ReturnType<typeof createTopicRevocation>;\n}\n\n/** Creates the change topics of a dispatcher whose hub holds its collections. */\nexport function createTopics(hub: CollectionHub): Topics {\n const index = new TopicIndex();\n return Object.freeze({\n sink: createTopicSink(hub, index),\n revocation: createTopicRevocation(hub, index),\n extension: (socket: QuickdrawServerSocket, context: SocketContext): void => {\n answerEvent(socket, context, CLIENT_EVENTS.watch, (frame) =>\n watchTopic(hub, index, socket, frame),\n );\n socket.on(CLIENT_EVENTS.unwatch, (frame: unknown, ack: unknown) => {\n answerNow(socket, context, CLIENT_EVENTS.unwatch, ack, () =>\n unwatchTopic(hub, index, socket, frame),\n );\n });\n onDisconnect(socket, context, () => {\n index.drop(socket);\n });\n },\n });\n}\n","// The entity sinks (RFC 0003 sections 5.3 and 6): what a flush does for\n// entity subscribers. It replaces 4.1's `emitUpdate`\n// (4.1 `src/server/BaseService.ts:454-466`), which only `this.update` and\n// hand-written code called.\n//\n// Two sinks, on either side of the access sink on the dispatcher's list:\n//\n// - `intake` works out which rows of which services the flush touched\n// (`affects` included) and records them in the change log, before access\n// is evicted and revoked, so revocation knows a deleted row from a\n// forbidden one;\n// - `emit` runs once revocation has moved or removed sockets, so a socket\n// whose access the flush removed never gets its frames. Per service with\n// touched rows it skips rows whose rooms are all empty, reads the rest in\n// one query with the entity projection's select (a patch reads only the\n// patched fields), builds each frame once and strips it once per group of\n// occupied tiers that see the same fields.\n//\n// Room occupancy is read from this process's adapter. Behind a cluster\n// adapter (Redis) other nodes' rooms are invisible, so every touched row is\n// read and its frame sent to every tier. Frames sent there go out whole\n// (`u`, never `p`): frames from two nodes can reach a client out of revision\n// order, and a patch it dropped as older would lose its fields, while an\n// older whole row is rightly dropped (the newer one was read after the older\n// write). A tier that would have got an empty patch still gets nothing.\n//\n// Behind a cluster adapter a deleted row is read too: a flush takes its\n// revision when it flushes, so a delete that committed first can flush after\n// a later create of the same id, and its `r` would win over that row on the\n// client. A row this flush deleted that exists at the read goes out whole\n// (`u`) instead, and the change log records it as existing. One server keeps\n// sending `r` without a read.\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport { entityRoom, SERVER_EVENTS } from \"../../contract/names\";\nimport type { EntityFrame, Revision } from \"../../protocol/envelope\";\nimport type { AnyService } from \"../service\";\nimport type { FlushInfo, FlushSink } from \"../uow/flushSink\";\nimport type { WriteRecord } from \"../uow/types\";\nimport { touchedRows, type Touch, type TouchedRows } from \"./affects\";\nimport { buildFrame, frameKind, selectFor, type FrameKind } from \"./frames\";\nimport type { Hub } from \"./hub\";\nimport { strip, SUBSCRIBER_LEVELS } from \"./tiers\";\n\ntype Io = NonNullable<Hub[\"io\"]>;\n\n/** A touched row with subscribers: how it goes out, and the rooms of the tiers it goes to. */\ninterface Target {\n readonly id: string;\n readonly kind: FrameKind;\n readonly rooms: ReadonlyMap<AccessLevel, string>;\n /** Behind a cluster adapter, the fields a patch would have carried: the row goes out whole. */\n readonly patched?: readonly string[];\n}\n\nconst WHOLE: FrameKind = Object.freeze({ t: \"u\" });\n\n/** How a row goes out: as `frameKind` says, but whole instead of a patch behind a cluster adapter. */\nfunction targetOf(\n id: string,\n kind: FrameKind,\n rooms: ReadonlyMap<AccessLevel, string>,\n local: boolean,\n): Target {\n return local || kind.t !== \"p\"\n ? { id, kind, rooms }\n : { id, kind: WHOLE, rooms, patched: kind.fields };\n}\n\n/** True when the tier sees none of the fields the write changed: it gets no frame, as it would get no patch. */\nfunction seesNoChange(target: Target, hidden: ReadonlySet<string>): boolean {\n return target.patched !== undefined && target.patched.every((field) => hidden.has(field));\n}\n\n/** The tier rooms of a row that have subscribers here; behind a cluster adapter, every tier room. */\nfunction occupiedRooms(\n io: Io,\n service: string,\n id: string,\n local: boolean,\n): Map<AccessLevel, string> {\n const rooms = new Map<AccessLevel, string>();\n const known = io.sockets.adapter.rooms;\n for (const level of SUBSCRIBER_LEVELS) {\n const room = entityRoom(service, id, level);\n if (!local || (known.get(room)?.size ?? 0) > 0) {\n rooms.set(level, room);\n }\n }\n return rooms;\n}\n\n/** Sends a frame to its rooms: a removal once to all, data once per group of tiers that see the same fields. */\nfunction send(io: Io, frame: EntityFrame, target: Target, service: AnyService): void {\n if (frame.t === \"r\") {\n io.to([...target.rooms.values()]).emit(SERVER_EVENTS.entity, frame);\n return;\n }\n const tiers = service.projections.get(\"entity\")?.tiers;\n for (const group of tiers?.groups ?? []) {\n const rooms = group.levels.flatMap((level) => target.rooms.get(level) ?? []);\n const data = strip(frame.d as Readonly<Record<string, unknown>>, group.hidden);\n const empty =\n frame.t === \"p\" ? Object.keys(data).length === 0 : seesNoChange(target, group.hidden);\n if (rooms.length === 0 || empty) {\n continue;\n }\n io.to(rooms).emit(SERVER_EVENTS.entity, { ...frame, d: data });\n }\n}\n\n/** Reads the rows of `targets` that need data, in one query: behind a cluster adapter, removed rows too. */\nasync function readTargets(\n hub: Hub,\n service: AnyService,\n targets: readonly Target[],\n local: boolean,\n): Promise<Map<string, Readonly<Record<string, unknown>>>> {\n const projection = service.projections.get(\"entity\");\n const reading = local ? targets.filter((target) => target.kind.t !== \"r\") : targets;\n if (projection === undefined || service.model === undefined || reading.length === 0) {\n return new Map();\n }\n const rows =\n (await hub.storage?.findMany(service.model, {\n where: { id: { in: reading.map((target) => target.id) } },\n select: selectFor(\n projection,\n reading.map((target) => (target.kind.t === \"r\" ? WHOLE : target.kind)),\n ),\n })) ?? [];\n return new Map(rows.flatMap((row) => (typeof row.id === \"string\" ? [[row.id, row]] : [])));\n}\n\n/** One service's frames for one flush. */\nasync function emitService(\n hub: Hub,\n io: Io,\n service: AnyService,\n touched: ReadonlyMap<string, Touch>,\n rev: Revision,\n): Promise<void> {\n const projection = service.projections.get(\"entity\");\n if (projection === undefined || service.model === undefined) {\n return;\n }\n const local = hub.probe.local();\n const targets: Target[] = [];\n for (const [id, touch] of touched) {\n const rooms = occupiedRooms(io, service.name, id, local);\n if (rooms.size > 0) {\n targets.push(targetOf(id, frameKind(projection, touch, service.versionColumn), rooms, local));\n }\n }\n if (targets.length === 0) {\n return;\n }\n const rows = await readTargets(hub, service, targets, local);\n for (const target of targets) {\n const row = rows.get(target.id);\n // Behind a cluster adapter, a row this flush deleted that exists at the read was created\n // again by a write whose flush went first: it goes out whole, not removed.\n const again = target.kind.t === \"r\" && row !== undefined;\n if (again) {\n hub.changeLog.record(service.name, target.id, rev, false);\n }\n // A row read as missing was deleted since: its own flush sends the removal.\n const kind = again ? WHOLE : target.kind;\n const frame = buildFrame(service.name, target.id, kind, row, rev, projection);\n if (frame !== undefined) {\n send(io, frame, target, service);\n }\n }\n}\n\n/** The intake and emit sinks of a dispatcher's entity subscriptions. */\nexport function createEntitySinks(hub: Hub): { intake: FlushSink; emit: FlushSink } {\n const flushes = new WeakMap<readonly WriteRecord[], TouchedRows>();\n return {\n intake: Object.freeze({\n flush(writes: readonly WriteRecord[], info: FlushInfo): Promise<void> {\n const touched = touchedRows(writes, hub.routes);\n flushes.set(writes, touched);\n for (const [service, rows] of touched) {\n for (const [id, touch] of rows) {\n hub.changeLog.record(service.name, id, info.rev, touch.op === \"delete\");\n }\n }\n return Promise.resolve();\n },\n }),\n emit: Object.freeze({\n async flush(writes: readonly WriteRecord[], info: FlushInfo): Promise<void> {\n const { io } = hub;\n if (io === undefined) {\n return;\n }\n const touched = flushes.get(writes) ?? touchedRows(writes, hub.routes);\n await Promise.all(\n [...touched].map(([service, rows]) => emitService(hub, io, service, rows, info.rev)),\n );\n },\n }),\n };\n}\n","// The socket listeners of entity subscriptions (RFC 0003 sections 6 and 8.2):\n// `qd:sub { s, ids, revs? }`, answered `{ ok: true, r }` with one result per\n// id or `{ ok: false, e }` for the whole batch, and `qd:unsub { s, ids }`,\n// optionally acknowledged. One listener per event on every v5 socket, routed\n// by the frame's service, never one per service or row. The rate limiter\n// does not count either event (`transports/middleware.ts`): a board mounting\n// sixty rows would otherwise trip it.\n//\n// The whole batch fails when the frame is malformed or holds more than 500\n// ids (`VALIDATION`), names an unknown service or one without rows\n// (`NOT_FOUND`), or comes from an anonymous socket (`UNAUTHENTICATED`); a\n// failed lookup or read is `INTERNAL`, logged. `qd:unsub` is checked the same\n// way.\n//\n// No listener of the live data throws (`answer.ts`), and `qd:sub` runs in\n// the socket's lane of subscription work (`lane.ts`).\n\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport type { EntitySubscribeReply, Ok, Revision } from \"../../protocol/envelope\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { MAX_SUBSCRIBE_IDS } from \"../../protocol/version\";\nimport { unreadable } from \"../transports/ack\";\nimport type { QuickdrawServerSocket, SocketContext } from \"../transports/types\";\nimport { answerEvent, answerNow, onDisconnect } from \"./answer\";\nimport { liveService, type Hub } from \"./hub\";\nimport { subscribe, type SubscribeRequest } from \"./subscribe\";\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isIdList(value: unknown): value is readonly string[] {\n return Array.isArray(value) && value.every((id) => typeof id === \"string\" && id.length > 0);\n}\n\nfunction isHeld(value: unknown): value is Revision | null {\n return value === null || (typeof value === \"number\" && Number.isFinite(value));\n}\n\n/** Reads the `{ s, ids }` of a `qd:sub` or `qd:unsub` frame, or throws `VALIDATION`. */\nfunction readIds(\n frame: unknown,\n event: string,\n shape: string,\n): { readonly s: string; readonly ids: readonly string[]; readonly frame: UnknownRecord } {\n if (!isRecord(frame) || typeof frame.s !== \"string\" || frame.s === \"\" || !isIdList(frame.ids)) {\n throw unreadable(`A ${event} frame needs ${shape} with ids a list of row ids`);\n }\n if (frame.ids.length > MAX_SUBSCRIBE_IDS) {\n throw unreadable(`A ${event} frame names at most ${MAX_SUBSCRIBE_IDS} ids`, [\"ids\"]);\n }\n return { s: frame.s, ids: frame.ids, frame };\n}\n\n/** Reads a `qd:sub` frame, or throws `VALIDATION`. */\nfunction readSubscribe(value: unknown): SubscribeRequest {\n const { s, ids, frame } = readIds(value, CLIENT_EVENTS.sub, \"{ s, ids, revs? }\");\n const { revs } = frame;\n const listed = revs === undefined || (Array.isArray(revs) && revs.length === ids.length);\n if (!listed || (revs !== undefined && !revs.every(isHeld))) {\n throw unreadable(\"revs must hold a revision or null for each id, by position\", [\"revs\"]);\n }\n const held = new Map<string, Revision>();\n ids.forEach((id, index) => {\n const rev: unknown = revs?.[index];\n if (typeof rev === \"number\") {\n held.set(id, rev);\n }\n });\n return { s, ids, held };\n}\n\nasync function onSubscribe(\n hub: Hub,\n socket: QuickdrawServerSocket,\n frame: unknown,\n): Promise<EntitySubscribeReply> {\n const request = readSubscribe(frame);\n const target = liveService(hub, request.s);\n if (socket.data.principal === null) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n if (hub.storage === undefined) {\n throw new QuickdrawError(\n \"INTERNAL\",\n \"Entity subscriptions read rows through the dispatcher's storage adapter: pass db as trackPrisma(prisma)\",\n );\n }\n return { ok: true, r: await subscribe(hub, socket, target, request) };\n}\n\n/** Serves `qd:unsub`: checked as `qd:sub` is, then each row's subscription ends. */\nfunction onUnsubscribe(hub: Hub, socket: QuickdrawServerSocket, frame: unknown): Ok {\n const { s, ids } = readIds(frame, CLIENT_EVENTS.unsub, \"{ s, ids }\");\n liveService(hub, s);\n if (socket.data.principal === null) {\n throw new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication required\");\n }\n for (const id of ids) {\n hub.subscriptions.unsubscribe(socket, s, id);\n }\n return { ok: true };\n}\n\n/**\n * The socket extension (`transports/socketio.ts`) that serves `qd:sub` and\n * `qd:unsub` for one dispatcher's services.\n */\nexport function entitySubscriptions(\n hub: Hub,\n): (socket: QuickdrawServerSocket, context: SocketContext) => void {\n return (socket, context) => {\n answerEvent(socket, context, CLIENT_EVENTS.sub, (frame) => onSubscribe(hub, socket, frame));\n socket.on(CLIENT_EVENTS.unsub, (frame: unknown, ack: unknown) => {\n answerNow(socket, context, CLIENT_EVENTS.unsub, ack, () => onUnsubscribe(hub, socket, frame));\n });\n onDisconnect(socket, context, () => {\n hub.subscriptions.drop(socket);\n });\n };\n}\n","// Revocation (RFC 0003 section 4.4). Each live subscription records the rows\n// its level is derived from: its anchors. When a flush may have changed\n// someone's level on an anchor (`dispatcher.access.onAccessChanged`), the\n// subscriptions anchored there are resolved again, for the user the change\n// names or for everyone:\n//\n// - below `Read` now: the socket leaves the row's room and gets\n// `qd:revoked { kind: \"entity\", reason: \"access\", s, id }`; a row this\n// process's flush deleted is left alone, since its own removal frame (`r`)\n// goes out next. Its subscribers stay in its room, and a create of that id\n// (reported as an access change too) resolves them again before the new\n// row's first frame;\n// - another level: the socket moves to that level's room, and gets the row\n// again (`u`) when the two levels see different fields;\n// - a lookup that fails denies, as everywhere else.\n//\n// In 4.1 a subscriber's tier was fixed when it subscribed and an access\n// change took effect on re-subscribe (4.1 `src/server/BaseService.ts:171-175`).\n// The access sink runs before the entity sink, so a socket a flush revokes\n// never gets that flush's frames.\n//\n// Several nodes behind a cluster adapter each index their own sockets: a\n// node broadcasts every access change it flushes (`serverSideEmit`), and each\n// node re-resolves its own sockets. A changed `serviceAccess`\n// (`server.access.refresh`) re-resolves the user's subscriptions the same way.\n// Collection scopes, change topic watches and stream feeds are authorized\n// again alongside, through the hooks they give (`collections/revocation.ts`,\n// `topicRevocation.ts`, `realtime/streamRevocation.ts`).\n\nimport { SERVER_EVENTS, userRoom } from \"../../contract/names\";\nimport type { AccessChange } from \"../access/changes\";\nimport { answerOf } from \"../cluster/acks\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { QuickdrawServerSocket } from \"../transports/types\";\nimport type { Hub } from \"./hub\";\nimport { projectRow } from \"./projection\";\nimport { anchorsOf, resolveAccess, subscriberLevel } from \"./resolve\";\nimport type { SubscriptionEntry } from \"./subscriptions\";\nimport { strip } from \"./tiers\";\n\n/** The server-to-server event an access change is broadcast on behind a cluster adapter. */\nexport const ACCESS_CHANGED_EVENT = \"quickdraw:access-changed\";\n\ntype Entries = readonly SubscriptionEntry[];\n\n/** Sends rows whose subscriber moved to a level that sees other fields again, whole, at a new revision. */\nasync function resend(\n hub: Hub,\n socket: QuickdrawServerSocket,\n service: string,\n ids: readonly string[],\n): Promise<void> {\n const target = hub.registry.services.get(service);\n const projection = target?.projections.get(\"entity\");\n if (ids.length === 0 || target?.model === undefined || projection === undefined) {\n return;\n }\n // Claimed before the read: behind a cluster's counter, no older than any frame the client holds.\n const rev = await hub.revisions.claim();\n const rows =\n (await hub.storage?.findMany(target.model, {\n where: { id: { in: [...ids] } },\n select: projection.select,\n })) ?? [];\n for (const row of rows) {\n const id = typeof row.id === \"string\" ? row.id : \"\";\n const subscription = hub.subscriptions.get(socket, service, id);\n const data = projectRow(projection, row);\n if (subscription !== undefined && typeof data === \"object\" && data !== null) {\n const hidden = projection.tiers.hidden(subscription.level);\n const d = strip(data as Readonly<Record<string, unknown>>, hidden);\n socket.emit(SERVER_EVENTS.entity, { t: \"u\", s: service, id, rev, d });\n }\n }\n}\n\n/**\n * Ends a subscription the principal may no longer read, unless the row is\n * deleted as far as this process's change log knows: the intake sink records\n * each flush before access is resolved, so a row created again counts as\n * existing. For a change another node broadcast, the log is trusted only\n * when the broadcast carried its row's state (`trustLog`), which was\n * recorded first: otherwise this process's log may be behind that node's\n * writes, and the change is never skipped.\n */\nfunction revoke(\n hub: Hub,\n socket: QuickdrawServerSocket,\n entry: { readonly service: string; readonly id: string },\n trustLog: boolean,\n): void {\n const { service, id } = entry;\n if (trustLog && hub.changeLog.removed(service, id)) {\n return;\n }\n if (hub.subscriptions.delete(socket, service, id) !== undefined) {\n socket.emit(SERVER_EVENTS.revoked, { kind: \"entity\", reason: \"access\", s: service, id });\n }\n}\n\n/** True when two levels see different fields of the service's entity. */\nfunction seesOther(hub: Hub, service: string, a: string, b: string): boolean {\n const tiers = hub.registry.services.get(service)?.projections.get(\"entity\")?.tiers;\n if (tiers === undefined || a === b) {\n return false;\n }\n const group = (level: string) =>\n tiers.groups.findIndex((tier) => tier.levels.some((l) => l === level));\n return group(a) !== group(b);\n}\n\n/** The levels of `entries` resolved again, or `undefined` when there is no principal or the lookup failed. */\nasync function resolveAgain(\n hub: Hub,\n socket: QuickdrawServerSocket,\n service: string,\n entries: Entries,\n) {\n const { principal } = socket.data;\n const target = hub.registry.services.get(service);\n if (principal === null || target === undefined) {\n return undefined;\n }\n const ids = entries.map((entry) => entry.id);\n try {\n return await resolveAccess(hub, target, principal, ids);\n } catch (error) {\n hub.logger.error(\n \"Resolving subscribers' access again failed; their subscriptions are revoked\",\n {\n category: \"quickdraw.access\",\n service,\n error: describeError(error),\n },\n );\n return undefined;\n }\n}\n\n/** Resolves one socket's subscriptions to one service again, and applies the new levels. */\nasync function reresolve(\n hub: Hub,\n socket: QuickdrawServerSocket,\n service: string,\n entries: Entries,\n trustLog: boolean,\n): Promise<void> {\n const access = await resolveAgain(hub, socket, service, entries);\n const moved: string[] = [];\n for (const { id, subscription } of entries) {\n // Unsubscribed, subscribed again or resolved again meanwhile: that is newer than this.\n if (!socket.connected || hub.subscriptions.get(socket, service, id) !== subscription) {\n continue;\n }\n const level = access === undefined ? undefined : subscriberLevel(access, id);\n if (access === undefined || level === undefined) {\n revoke(hub, socket, { service, id }, trustLog);\n continue;\n }\n hub.subscriptions.set(socket, service, id, { level, anchors: anchorsOf(access, service, id) });\n if (seesOther(hub, service, level, subscription.level)) {\n moved.push(id);\n }\n }\n await resend(hub, socket, service, moved);\n}\n\n/**\n * Resolves the given subscriptions again, one engine call per socket and\n * service. `trustLog` unless the change came from another node without its\n * row's state.\n */\nasync function reresolveAll(\n hub: Hub,\n found: ReadonlyMap<QuickdrawServerSocket, Entries>,\n trustLog: boolean,\n): Promise<void> {\n const work: Promise<void>[] = [];\n for (const [socket, entries] of found) {\n const byService = new Map<string, SubscriptionEntry[]>();\n for (const entry of entries) {\n byService.set(entry.service, [...(byService.get(entry.service) ?? []), entry]);\n }\n for (const [service, own] of byService) {\n work.push(reresolve(hub, socket, service, own, trustLog));\n }\n }\n await Promise.all(work);\n}\n\n/**\n * An access change as it travels between nodes: with its row's state as the\n * flushing node's change log has it (the revision of its last write, and\n * whether that write deleted it), which the receiving node records in its\n * own log before resolving anything.\n */\nexport interface BroadcastChange extends AccessChange {\n readonly rev?: number;\n readonly removed?: boolean;\n}\n\n/** `change` with its row's state from this process's change log, for the other nodes. */\nfunction withRowState(hub: Hub, change: AccessChange): BroadcastChange {\n const { service, id } = change;\n if (id === undefined) {\n return change;\n }\n return {\n ...change,\n rev: hub.changeLog.lastChange(service, id),\n removed: hub.changeLog.removed(service, id),\n };\n}\n\n/**\n * Broadcasts a change this process flushed and waits until every other node\n * has re-resolved what it concerns (each answers once it is done), at most\n * `cluster.timeoutMs`: the access sinks run before the frame sinks, so a\n * flush that revokes a subscription on another node sends that flush's\n * frames only once the subscription is gone there too. The wait holds this\n * node's later flushes too, so it is skipped while Valkey is not connected,\n * and after a node failed to answer in time until every node answers a\n * probe again (`../cluster/broadcasts.ts`): the frames then go out at once,\n * and a slower node may still hold a socket the change revoked.\n */\nasync function broadcastChange(hub: Hub, change: BroadcastChange): Promise<void> {\n await hub.broadcasts?.broadcast(ACCESS_CHANGED_EVENT, change);\n}\n\n/** What the subscriptions of a dispatcher do when access changes. */\nexport interface Revocation {\n /**\n * Re-resolves the subscriptions `change` concerns on this process. A change\n * this process flushed (`remote` false) is also broadcast to the other\n * nodes, behind a cluster adapter, with its row's state, and resolves once\n * they re-resolved theirs too (`broadcastChange`).\n */\n changed(change: BroadcastChange, remote: boolean): Promise<void>;\n /** Re-resolves every subscription of `userId`'s sockets on this process: their grants changed. */\n regranted(userId: string): Promise<void>;\n}\n\n/** More subscriptions an access change re-resolves: the collection scopes, the change topics, the stream feeds. */\nexport interface RevocationHook {\n /** Re-resolves the subscriptions `change` concerns on this process. */\n changed(change: AccessChange): Promise<void>;\n /** Re-resolves every subscription of these sockets, whose user's grants changed. */\n regranted(sockets: readonly QuickdrawServerSocket[]): Promise<void>;\n}\n\n/**\n * The revocation of one dispatcher's subscriptions; `hooks` re-resolve the\n * collection scopes and the change topics alongside.\n */\nexport function createRevocation(hub: Hub, hooks: readonly RevocationHook[] = []): Revocation {\n return Object.freeze({\n async changed(change: BroadcastChange, remote: boolean): Promise<void> {\n hub.subscriptions.accessChanges += 1;\n const others =\n !remote && hub.io !== undefined && !hub.probe.local()\n ? broadcastChange(hub, withRowState(hub, change))\n : undefined;\n const trustLog = !remote || change.removed !== undefined;\n await Promise.all([\n others,\n reresolveAll(hub, hub.subscriptions.matching(change), trustLog),\n ...hooks.map(async (hook) => await hook.changed(change)),\n ]);\n },\n async regranted(userId: string): Promise<void> {\n hub.subscriptions.accessChanges += 1;\n const { io } = hub;\n const found = new Map<QuickdrawServerSocket, Entries>();\n for (const socketId of io?.sockets.adapter.rooms.get(userRoom(userId)) ?? []) {\n const socket = io?.sockets.sockets.get(socketId);\n if (socket?.data.principal?.userId === userId) {\n found.set(socket, [...hub.subscriptions.entries(socket)]);\n }\n }\n const sockets = [...found.keys()];\n await Promise.all([\n reresolveAll(hub, found, true),\n ...hooks.map(async (hook) => await hook.regranted(sockets)),\n ]);\n },\n });\n}\n\n/** The row state a broadcast change carries, `{ rev, removed }`, when both are well formed. */\nfunction rowStateOf(value: Readonly<Record<string, unknown>>): Partial<BroadcastChange> {\n const { rev, removed } = value;\n return Number.isSafeInteger(rev) && typeof removed === \"boolean\"\n ? { rev: rev as number, removed }\n : {};\n}\n\n/**\n * The access change another node broadcast, `{ service, id?, userId? }` with\n * its row's state when it names a row, or `undefined` for anything else.\n */\nfunction readChange(value: unknown): BroadcastChange | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const fields = value as Readonly<Record<string, unknown>>;\n const { service, id, userId } = fields;\n if (typeof service !== \"string\" || service.length === 0) {\n return undefined;\n }\n const named = typeof id === \"string\" && id.length > 0;\n return {\n service,\n ...(named ? { id, ...rowStateOf(fields) } : {}),\n ...(typeof userId === \"string\" && userId.length > 0 ? { userId } : {}),\n };\n}\n\n/** Records the row state a broadcast change carries in this process's change log. */\nfunction recordRowState(hub: Hub, change: BroadcastChange): void {\n if (change.id !== undefined && change.rev !== undefined && change.removed !== undefined) {\n hub.changeLog.record(change.service, change.id, change.rev, change.removed);\n }\n}\n\n/**\n * Listens for the access changes other nodes broadcast, on the server the\n * hub was given: each records its row's state in this process's change log,\n * has `forget` evict what it names from the access cache (that node's write\n * changed it), is resolved again, and is answered once it is (the flushing\n * node waits for every node's answer before it sends the flush's frames).\n */\nexport function listenForChanges(\n hub: Hub,\n revocation: Revocation,\n forget: (change: AccessChange) => void,\n): void {\n hub.io?.on(ACCESS_CHANGED_EVENT, (broadcast: unknown, ...rest: unknown[]) => {\n const answer = answerOf(rest);\n const change = readChange(broadcast);\n if (change === undefined) {\n answer(false);\n return;\n }\n recordRowState(hub, change);\n forget(change);\n revocation.changed(change, true).then(\n () => {\n answer(true);\n },\n (error: unknown) => {\n answer(false);\n hub.logger.error(\"Revoking for an access change another node broadcast failed\", {\n category: \"quickdraw.access\",\n service: change.service,\n error: describeError(error),\n });\n },\n );\n });\n}\n","// The live data of one dispatcher (RFC 0003 sections 4.4, 5.3, 6, 7, 11.3\n// and 12.5): entity subscriptions, collection scopes and change topics, the\n// frames flushes send them, revocation, \"not modified\" versions, and the\n// realtime half (presence, streams, channels and typed room events). A\n// dispatcher makes one; `createServer` attaches its Socket.IO server and\n// serves `qd:sub`, `qd:col:sub`, `qd:col:items`, `qd:watch`, `qd:stream:sub`\n// and `qd:ch` with it. Without a server the sinks still keep the change log,\n// so in-process callers get versions too.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport { createLiveCollections } from \"../collections/live\";\nimport {\n createRealtime,\n type Presence,\n type Realtime,\n type RoomLeave,\n type RoomLeaveHandler,\n type RoomLeaveHook,\n type ServerRooms,\n type StreamHandle,\n} from \"../realtime/realtime\";\nimport { createTopics } from \"../topics\";\nimport { createEntitySinks } from \"./entitySink\";\nimport { entitySubscriptions } from \"./extension\";\nimport { createHub, drain, type AdapterProbe, type Hub, type HubOptions } from \"./hub\";\nimport { createRevocation, listenForChanges } from \"./revocation\";\nimport { createVersionSource } from \"./versions\";\n\nexport type { Presence, RoomLeave, RoomLeaveHandler, RoomLeaveHook, ServerRooms, StreamHandle };\nexport type { ChangeLogOptions } from \"./changeLog\";\n\ntype Sinks = ReturnType<typeof createEntitySinks>;\n\ntype Collections = ReturnType<typeof createLiveCollections>;\n\n/** The live data of one dispatcher. */\nexport interface Live {\n /** Records the rows a flush touched in the change log; goes before the access sink. */\n readonly intake: Sinks[\"intake\"];\n /** Sends the flush's entity frames; goes after the access sink. */\n readonly emit: Sinks[\"emit\"];\n /** Sends the flush's collection deltas; goes after `emit`. */\n readonly collections: Collections[\"sink\"];\n /** Sends `qd:changed` for the flush's change topics; goes after `collections`. */\n readonly topics: ReturnType<typeof createTopics>[\"sink\"];\n /** \"Not modified\" for queries returning one projection row: the dispatcher's default `versions`. */\n readonly versions: ReturnType<typeof createVersionSource>;\n /**\n * Serves `qd:sub`, `qd:unsub`, `qd:col:sub`, `qd:col:items`,\n * `qd:col:unsub`, `qd:watch`, `qd:unwatch`, `qd:stream:sub`,\n * `qd:stream:unsub` and `qd:ch` on every v5 socket.\n */\n readonly extension: ReturnType<typeof entitySubscriptions>;\n /** Presence, streams, channels and typed room events: `ctx.rooms`, `ctx.presence`, `qd.stream`. */\n readonly realtime: Realtime;\n /** The revisions flushes take and reads claim: the process's clock, or a cluster's shared counter. */\n readonly revisions: Hub[\"revisions\"];\n /**\n * Gives the live data its Socket.IO server: frames go out on it, and\n * access changes broadcast by other nodes arrive on it. What such a change\n * names is evicted from the access cache (`cacheMs`) before it is resolved\n * again. `cluster` says where a cluster's shared state lives, and\n * `broadcasts` sends access changes to the other nodes.\n */\n attach(\n io: NonNullable<Hub[\"io\"]>,\n probe: AdapterProbe,\n cluster?: Hub[\"cluster\"],\n broadcasts?: Hub[\"broadcasts\"],\n ): void;\n /**\n * Re-resolves the subscriptions of `userId`'s sockets on this process after\n * their grants changed, reading the user's levels afresh.\n */\n regranted(userId: string): Promise<void>;\n /** Sends a `reset` to one scope of a collection: `dispatcher.collections.reset`. */\n resetCollection(contract: AnyContract, collection: string, scope: string): void;\n /** Resolves once the work the live data started for sockets' events has settled: a server's `close()`. */\n drain(): Promise<void>;\n /** The sockets in a room of the attached server, for the kits (`KitRuntime.occupancy`). */\n readonly occupancy: Realtime[\"occupancy\"];\n}\n\n/**\n * Creates a dispatcher's live data. Throws a `TypeError` for an `affects` it\n * cannot follow, or a collection anchor it cannot authorize through.\n */\nexport function createLive(options: HubOptions): Live {\n const hub = createHub(options);\n const collections = createLiveCollections(hub);\n const topics = createTopics(collections.hub);\n const sinks = createEntitySinks(hub);\n const realtime = createRealtime(hub);\n const revocation = createRevocation(hub, [\n collections.revocation,\n topics.revocation,\n realtime.revocation,\n ]);\n const entities = entitySubscriptions(hub);\n options.policies.onAccessChanged((change) => revocation.changed(change, false));\n return Object.freeze({\n intake: sinks.intake,\n emit: sinks.emit,\n collections: collections.sink,\n topics: topics.sink,\n versions: createVersionSource(hub),\n extension: (...args: Parameters<typeof entities>): void => {\n entities(...args);\n collections.extension(...args);\n topics.extension(...args);\n realtime.extension(...args);\n },\n realtime,\n revisions: hub.revisions,\n attach(\n io: NonNullable<Hub[\"io\"]>,\n probe: AdapterProbe,\n cluster?: Hub[\"cluster\"],\n broadcasts?: Hub[\"broadcasts\"],\n ): void {\n hub.io = io;\n hub.probe = probe;\n hub.cluster = cluster;\n hub.broadcasts = broadcasts;\n collections.listen();\n realtime.listen();\n listenForChanges(hub, revocation, (change) => {\n options.policies.forget(change);\n });\n },\n regranted: (userId: string) => {\n // The grants may come with writes this node's cache has not seen: read the user's levels afresh.\n options.policies.forget({ userId });\n return revocation.regranted(userId);\n },\n resetCollection: (contract: AnyContract, collection: string, scope: string) => {\n collections.reset(contract, collection, scope);\n },\n occupancy: realtime.occupancy,\n drain: () => drain(hub),\n });\n}\n\nconst LIVES = new WeakMap<object, Live>();\n\n/** Marks `dispatcher` as having `live` for its live data. */\nexport function registerLive(dispatcher: object, live: Live): void {\n LIVES.set(dispatcher, live);\n}\n\n/** The live data of a dispatcher `createDispatcher` returned. */\nexport function liveOf(dispatcher: object): Live | undefined {\n return LIVES.get(dispatcher);\n}\n","// A defined service as the pipeline reads it: its contract, and one checked\n// record per method holding the handler, the access form and the options.\n// `defineService.ts` builds these; the registry and the dispatcher read them.\n\nimport type { AnyContract } from \"../contract/defineContract\";\nimport type { MethodKind } from \"../contract/methods\";\nimport type { StandardSchemaV1 } from \"../contract/standardSchema\";\nimport type { Version } from \"../protocol/envelope\";\nimport type { AccessForm, AnyAccessPolicy, WatchAccess } from \"./access/types\";\nimport type { ServiceCollection } from \"./collections/define\";\nimport type { AnyContext, ContextExtender } from \"./context\";\nimport type { ProjectedOutput, Projection } from \"./emit/projection\";\nimport type { RoomLeaveHandler, ServiceChannel, ServiceStream } from \"./realtime/types\";\nimport type { MaybePromise, QuickdrawTypes } from \"./types\";\n\n/**\n * How identical concurrent calls of a query share one handler run (RFC 0003\n * section 9, step 6): `\"caller\"` among one principal's calls, `\"all\"` across\n * principals.\n */\nexport type ShareMode = \"caller\" | \"all\";\n\n/** A handler as the pipeline calls it, whatever its declared types. */\nexport type AnyHandler = (args: {\n readonly input: unknown;\n readonly ctx: AnyContext;\n readonly db: unknown;\n}) => unknown;\n\n/**\n * A method's own output schema, compiled from its JSON Schema when the\n * service is defined (`pipeline/schemaOutput.ts`).\n */\nexport interface SchemaOutput {\n /** The value reduced to what the schema declares; the value itself when nothing is dropped. */\n pick(value: unknown): unknown;\n /**\n * Each key the schema declares, at any depth, with the first path that\n * declares it (`email`, `user.email`, `[].email`; `{}` stands for any key\n * of a record): what the `tiered-field-in-output` warning reads.\n */\n keyPaths(): ReadonlyMap<string, string>;\n}\n\n/** One method of a defined service, checked and ready to dispatch. */\nexport interface ServiceMethod {\n readonly name: string;\n readonly kind: MethodKind;\n /** The contract's input schema. */\n readonly input: StandardSchemaV1;\n /**\n * The schema the handler's result is checked against in development and\n * tests, derived from the contract's `output`: the schema itself, or the\n * projection's schema, wrapped for `nullable` and `listOf`.\n */\n readonly output: StandardSchemaV1;\n /**\n * The projection the contract's `output` names, when it names one: the\n * handler's rows are projected through it before the output check, and\n * its field tiers are stripped per caller.\n */\n readonly projection: ProjectedOutput | undefined;\n /**\n * A schema output, compiled from its JSON Schema when the service was\n * defined (`pipeline/schemaOutput.ts`): the handler's result is reduced to\n * what the schema declares before the output check, on every transport.\n * `undefined` for a projection output, and for a schema without JSON\n * Schema (Zod 3), which is sent as the handler returns it.\n */\n readonly schemaOutput: SchemaOutput | undefined;\n readonly access: AccessForm;\n readonly handler: AnyHandler;\n readonly share: ShareMode | undefined;\n /** How long a shared result is reused after its run, in milliseconds. */\n readonly ttlMs: number | undefined;\n /** The method's time limit; the dispatcher's `callTimeoutMs` when unset. */\n readonly timeoutMs: number | undefined;\n /** The query's current version for \"not modified\" replies. */\n readonly version: ((input: unknown, ctx: AnyContext) => MaybePromise<Version>) | undefined;\n /**\n * True when the method said `rowless: true`: its access form is its whole\n * check on purpose, so every caller the form admits may reach any row its\n * input names (`defineService` refuses such a method otherwise; see\n * `buildService.ts`).\n */\n readonly rowless: boolean;\n}\n\n/**\n * One `affects` declaration of a service, checked (RFC 0003 sections 3 and\n * 5.3): a write to a row of the service's model also changes rows of\n * `service`, whose ids the written row's `columns` hold.\n */\nexport interface AffectsLink {\n /** The contract of the service whose rows the write affects. */\n readonly service: AnyContract;\n /** The columns of the service's own model the link reads; tracked writes report them. */\n readonly columns: readonly string[];\n /** The ids of the affected rows, from a written row's values of `columns`. */\n ids(values: Readonly<Record<string, unknown>>): readonly string[];\n}\n\n/**\n * A service defined with `qd.defineService(contract, definition)`. Pass it\n * to `qd.createServer` or to a dispatcher.\n */\nexport interface Service<\n T extends QuickdrawTypes = QuickdrawTypes,\n C extends AnyContract = AnyContract,\n> {\n /** The service name from the contract, unchanged on the wire and in stored grants. */\n readonly name: C[\"name\"];\n readonly contract: C;\n /** The database model the service's rows live in, named as the client names it: `\"task\"`. */\n readonly model: string | undefined;\n /** How a principal's level on one of the service's rows is found (RFC 0003 section 4.2). */\n readonly access: AnyAccessPolicy | undefined;\n /** Other models the service's handlers write, besides its own. */\n readonly writes: readonly string[];\n /** Rows of other services that a write to one of this service's rows changes too. */\n readonly affects: readonly AffectsLink[];\n /** The column whose time says when a row last changed, for \"not modified\" answers. */\n readonly versionColumn: string | undefined;\n /** The contract's projections (`\"entity\"` and the named ones), compiled with the service's `project` option. */\n readonly projections: ReadonlyMap<string, Projection>;\n /** The contract's collections, compiled with the service's `collections` option (RFC 0003 section 7.1). */\n readonly collections: ReadonlyMap<string, ServiceCollection>;\n /**\n * Who may watch the service's change topic (RFC 0003 section 11.3);\n * `undefined` when the service set none: the topic is closed to everyone.\n */\n readonly watchAccess: WatchAccess | undefined;\n /** Whether a service-wide `Admin` grant passes every access check of this service. */\n readonly adminBypass: boolean;\n /** The checked method records, by method name. */\n readonly methods: Readonly<Record<string, ServiceMethod>>;\n /** The contract's channels with the handlers `defineService` gave them (RFC 0003 section 12.5). */\n readonly channels: ReadonlyMap<string, ServiceChannel>;\n /** The contract's streams, with their access forms as the access engine decides them. */\n readonly streams: ReadonlyMap<string, ServiceStream>;\n /**\n * The service's own `onRoomLeave`: `createServer` runs it, beside every\n * other service's and its own option's, for each socket that leaves app\n * rooms. `undefined` when the service declares none.\n */\n readonly onRoomLeave: RoomLeaveHandler | undefined;\n /** Type-only: the app types the service was defined with. Never set. */\n readonly \"~types\"?: T;\n}\n\n/** Any defined service. */\nexport type AnyService = Service<QuickdrawTypes, AnyContract>;\n\n/** What a service keeps from the `initQuickdraw` call that defined it. */\nexport interface ServiceRuntime {\n /** The app's `context` option, or `undefined`. */\n readonly extendContext: ContextExtender | undefined;\n /**\n * Makes `dispatcher` the one the instance's `qd.caller`, `qd.run`,\n * `qd.stream` and `qd.presence` go through, as its own `createServer`\n * does: for `createTestApp`, which creates its server itself.\n */\n readonly adopt?: (dispatcher: object) => void;\n}\n\nconst runtimes = new WeakMap<object, ServiceRuntime>();\n\n/** Marks `service` as defined by `defineService` with the given runtime. */\nexport function registerRuntime(service: AnyService, runtime: ServiceRuntime): void {\n runtimes.set(service, runtime);\n}\n\n/** The runtime of a service `defineService` returned, or `undefined` for anything else. */\nexport function runtimeOf(service: unknown): ServiceRuntime | undefined {\n return typeof service === \"object\" && service !== null ? runtimes.get(service) : undefined;\n}\n\n/** Why a service cannot run a handler, or `undefined` when it can. */\nexport type HandlerCheck = (service: AnyService) => string | undefined;\n\nconst handlerChecks = new WeakMap<object, HandlerCheck>();\n\n/**\n * Makes `defineService` run `check` on the service `handler` is given to, so\n * a handler that needs something of its service (a kit's need a model) fails\n * when the service is defined, not on its first call. Only the kits register\n * checks, so a handler with one is framework code (`isKitHandler`).\n */\nexport function checkWhenDefined(handler: object, check: HandlerCheck): void {\n handlerChecks.set(handler, check);\n}\n\n/** The kit handlers that write users' service-wide grants (`admin.handlers(c, { grants: true })`). */\nconst grantsEditors = new WeakSet<object>();\n\n/** Marks `handler` as one that writes users' service-wide grants: `createServer` checks where they are stored. */\nexport function markGrantsEditor(handler: object): void {\n grantsEditors.add(handler);\n}\n\n/** True for a handler that writes users' service-wide grants (`markGrantsEditor`). */\nexport function editsGrants(handler: object): boolean {\n return grantsEditors.has(handler);\n}\n\n/** Why `service` cannot run `handler`, from the check `checkWhenDefined` attached. */\nexport function handlerProblem(handler: object, service: AnyService): string | undefined {\n return handlerChecks.get(handler)?.(service);\n}\n\n/**\n * True for a handler a kit made (it registered a check with\n * `checkWhenDefined`): framework code, whose statements the development\n * checks leave alone, because an app cannot change them.\n */\nexport function isKitHandler(handler: object): boolean {\n return handlerChecks.has(handler);\n}\n\nconst rowChecked = new WeakSet<object>();\n\n/**\n * Marks a kit handler that never reaches an existing row its input's `id`\n * names without checking the caller's level on that row itself, whatever its\n * access form says: the read/write kit's `update`, `delete` and `reorder`\n * (they need the method's row level on the row) and `create` (its `id`, when\n * it has one, names a new row). `defineService`'s rowless check leaves such\n * a handler alone.\n */\nexport function checksRowsItself(handler: object): void {\n rowChecked.add(handler);\n}\n\n/** True for a handler marked with {@link checksRowsItself}. */\nexport function isRowChecked(handler: object): boolean {\n return rowChecked.has(handler);\n}\n","// The `tiered-field-in-output` development warning (finding F7.4 of the\n// quickdraw-chat review, widened by the final review of the release\n// candidates). Field tiers (RFC 0003 section 6) strip what a reader may not\n// receive from projection outputs only: `\"entity\"`, a named projection, and\n// `nullable(...)` or `listOf(...)` of one. A method whose output is a schema\n// of its own is sent as that schema declares it (section 9, step 8;\n// `pipeline/schemaOutput.ts`), so a key the schema declares and the contract\n// tiers reaches every caller the method's access admits: the template's\n// `updateUser` answered `email`, an `Admin` field, to a service-wide\n// `Moderate` grant. Two checks say so:\n//\n// - When a dispatcher is made, each tiered key a method's output schema\n// declares, at any depth (a nested `{ user: { id, email } }`, the rows of\n// a list, the values of a record), raises the warning once, naming the\n// method, the key, where the schema declares it, and the fix: answer\n// `\"entity\"` (or a projection), which is stripped per caller, or drop the\n// key from the schema. A key the schema does not declare needs no warning:\n// it is dropped before the reply leaves.\n// - An output without JSON Schema (a Zod 3 schema) cannot be reduced and is\n// sent as the handler returns it. In development its replies are checked\n// instead: the first reply that carries a tiered key, at any depth, raises\n// the warning for that key.\n//\n// A method whose access admits no caller below the field's level is left\n// alone: a service-wide `Admin` grant (`{ service: \"Admin\" }`, while the\n// service's Admin bypass is on, as it is by default), and `{ entry: L }`\n// with `L` at or above the field's level, whose caller holds that level on\n// the row its input names (the row such a method answers with). A form with\n// both halves must pass on both. Every other form warns: `\"public\"`,\n// `\"authenticated\"`, `{ service: L }` below `Admin`, `{ scope }` (a level on\n// another service's row) and `custom`. A kit's methods are left alone too:\n// a kit strips what its readers may not see itself.\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport { isCustomAccess } from \"../access/forms\";\nimport { meetsLevel } from \"../access/levels\";\nimport type { AccessForm } from \"../access/types\";\nimport type { DevWarning, DevWarnings } from \"../devWarnings\";\nimport type { Registry, RegisteredMethod } from \"../registry\";\nimport { isKitHandler, type AnyService, type ServiceMethod } from \"../service\";\n\n/** True when every caller `form` admits holds `level` on the row the method answers about. */\nfunction admitsOnlyAt(form: AccessForm, level: AccessLevel, adminBypass: boolean): boolean {\n if (typeof form !== \"object\" || isCustomAccess(form) || form.scope !== undefined) {\n return false;\n }\n const serviceHalf = form.service === undefined || (form.service === \"Admin\" && adminBypass);\n const entryHalf =\n form.entry === undefined ? form.service !== undefined : meetsLevel(form.entry, level);\n return serviceHalf && entryHalf;\n}\n\n/** The tiered keys a method's access may hand to a caller below their level, with those levels. */\nfunction exposedTiers(\n service: AnyService,\n method: ServiceMethod,\n): ReadonlyMap<string, AccessLevel> {\n const exposed = new Map<string, AccessLevel>();\n if (isKitHandler(method.handler)) {\n return exposed;\n }\n for (const [key, level] of Object.entries(service.contract.fields)) {\n if (!admitsOnlyAt(method.access, level, service.adminBypass)) {\n exposed.set(key, level);\n }\n }\n return exposed;\n}\n\n/** ` (at user.email)`, or nothing for a key at the top level. */\nfunction where(key: string, path: string): string {\n return path === key ? \"\" : ` (at ${path})`;\n}\n\nfunction schemaWarning(\n service: AnyService,\n method: string,\n key: string,\n path: string,\n level: AccessLevel,\n): DevWarning {\n return {\n kind: \"tiered-field-in-output\",\n service: service.name,\n method,\n subject: key,\n message:\n `its output schema names \"${key}\"${where(key, path)}, which the contract gives only to readers with ` +\n `${level} on the row (fields: { ${key}: \"${level}\" }), but a schema output is sent as its schema declares ` +\n `it to every caller the method's access admits: field tiers strip only projection outputs. Answer ` +\n `\"entity\" or a projection (or nullable(...) or listOf(...) of one), which is stripped per caller, or drop ` +\n `\"${key}\" from the schema`,\n meta: { field: key, level, path },\n };\n}\n\nfunction replyWarning(\n service: AnyService,\n method: string,\n key: string,\n path: string,\n level: AccessLevel,\n): DevWarning {\n return {\n kind: \"tiered-field-in-output\",\n service: service.name,\n method,\n subject: key,\n message:\n `its reply carries \"${key}\"${where(key, path)}, which the contract gives only to readers with ${level} on ` +\n `the row (fields: { ${key}: \"${level}\" }), and was sent as the handler returned it to every caller the ` +\n `method's access admits: its output schema has no JSON Schema (a Zod 3 schema), so the reply cannot be ` +\n `reduced to it. Answer \"entity\" or a projection, which is stripped per caller, give the output a schema ` +\n `with JSON Schema (Zod 4.2 or later), or leave \"${key}\" out of what the handler returns`,\n meta: { field: key, level, path },\n };\n}\n\n/** The warnings `service`'s methods raise: one per tiered key an output schema declares. */\nexport function tieredOutputWarnings(service: AnyService): DevWarning[] {\n const warnings: DevWarning[] = [];\n for (const [name, method] of Object.entries(service.methods)) {\n const { schemaOutput } = method;\n if (schemaOutput === undefined) {\n continue;\n }\n const exposed = exposedTiers(service, method);\n if (exposed.size === 0) {\n continue;\n }\n const paths = schemaOutput.keyPaths();\n for (const [key, level] of exposed) {\n const path = paths.get(key);\n if (path !== undefined) {\n warnings.push(schemaWarning(service, name, key, path, level));\n }\n }\n }\n return warnings;\n}\n\n/**\n * Raises the `tiered-field-in-output` warnings of every service a\n * dispatcher serves: logged once each, or thrown by a test app made with\n * `strictWarnings`, failing its creation.\n */\nexport function warnTieredOutputs(registry: Registry, warnings: DevWarnings): void {\n if (!warnings.enabled) {\n return;\n }\n for (const service of registry.services.values()) {\n for (const warning of tieredOutputWarnings(service)) {\n warnings.warn(warning);\n }\n }\n}\n\n/** The plain objects and arrays a reply check reads at most: a development check, never a reply's cost. */\nconst MAX_CHECKED = 10_000;\n\n/** Where `value` carries each of `keys`, at any depth of plain objects and arrays: the first path found. */\nfunction carried(value: unknown, keys: ReadonlyMap<string, unknown>): Map<string, string> {\n const found = new Map<string, string>();\n const seen = new Set<object>();\n const queue: { readonly value: unknown; readonly path: string }[] = [{ value, path: \"\" }];\n for (let index = 0; index < queue.length && seen.size < MAX_CHECKED; index += 1) {\n const { value: item, path } = queue[index] as {\n readonly value: unknown;\n readonly path: string;\n };\n if (typeof item !== \"object\" || item === null || seen.has(item)) {\n continue;\n }\n seen.add(item);\n if (Array.isArray(item)) {\n for (const member of item) {\n queue.push({ value: member, path: `${path}[]` });\n }\n continue;\n }\n for (const [key, member] of Object.entries(item)) {\n const at = path === \"\" ? key : `${path}.${key}`;\n if (keys.has(key) && !found.has(key)) {\n found.set(key, at);\n }\n queue.push({ value: member, path: at });\n }\n }\n return found;\n}\n\n/** Each method's exposed tiers, for the reply check: worked out on its first reply. */\nconst replyChecks = new WeakMap<ServiceMethod, ReadonlyMap<string, AccessLevel>>();\n\n/**\n * The development check of a reply whose output schema has no JSON Schema\n * (see the top of this file): raises the warning for each exposed tiered key\n * the reply carries. Every other output is reduced to its schema, or\n * stripped per caller, and needs none.\n */\nexport function warnTieredReply(\n target: RegisteredMethod,\n value: unknown,\n warnings: DevWarnings,\n): void {\n const { service, method } = target;\n if (method.projection !== undefined || method.schemaOutput !== undefined) {\n return;\n }\n let exposed = replyChecks.get(method);\n if (exposed === undefined) {\n exposed = exposedTiers(service, method);\n replyChecks.set(method, exposed);\n }\n if (exposed.size === 0) {\n return;\n }\n for (const [key, path] of carried(value, exposed)) {\n warnings.warn(replyWarning(service, method.name, key, path, exposed.get(key) as AccessLevel));\n }\n}\n","// `dispatcher.access` (RFC 0003 sections 4.2 and 4.3): one policy, every\n// surface. The levels and list filters a dispatcher's services' policies\n// give, counted the way an `{ entry }` check counts them, for the framework's\n// later surfaces (subscriptions, collections, kits) and for handlers that\n// filter a list themselves; plus the access-change events revocation\n// listens to.\n\nimport { isAccessLevel, type AccessLevel } from \"../../contract/access\";\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { FlushSink } from \"../uow/flushSink\";\nimport type { Principal } from \"../types\";\nimport type { Binding } from \"./bindings\";\nimport type { AccessChangeListener, Forgotten } from \"./changes\";\nimport { serviceGrant } from \"./levels\";\nimport type { AccessFilter, RowLevels } from \"./policy\";\nimport { anchorKey, startCall, type EngineState } from \"./tools\";\nimport type { AccessEngine, RowAccess } from \"./types\";\n\n/** Re-exported for the live data, which authorizes stream subscribers through the engine. */\nexport type { AccessEngine };\n\n/** The dispatcher's view of its services' access policies: `dispatcher.access`. */\nexport interface DispatcherAccess {\n /**\n * The principal's level on each of `ids` of `service`, as an `{ entry }`\n * check counts it: the service's policy, or `Admin` on every row when the\n * principal holds a service-wide `Admin` grant and the service keeps\n * `adminBypass` on. A grant below `Admin` does not count. A row that is\n * not found has no level. One batched lookup per policy.\n */\n levelsFor(\n service: AnyContract | string,\n principal: Principal,\n ids: readonly string[],\n ): Promise<RowLevels>;\n /**\n * A filter for `db.<model>.findMany({ where })` matching exactly the rows of\n * `service` on which `levelsFor` gives the principal at least `level`:\n * `{}` (every row) for a service-wide `Admin` with `adminBypass`, or\n * `\"none\"` when no row matches.\n */\n accessWhere(\n service: AnyContract | string,\n principal: Principal,\n level: AccessLevel,\n ): Promise<AccessFilter>;\n /**\n * Calls `listener` after each flush whose tracked writes may have changed\n * someone's access to a row (`AccessChange`), once the cache no longer\n * holds what they changed. A promise it returns is awaited before the\n * dispatcher's other flush sinks run. Returns a function that removes it.\n */\n onAccessChanged(listener: AccessChangeListener): () => void;\n}\n\n/** A principal's levels on rows, and the rows each level is derived from. */\nexport interface ResolvedAccess {\n readonly levels: RowLevels;\n /**\n * Per id, the `anchorKey`s of the rows its level is derived from (RFC 0003\n * section 4.4): the row itself, then its `inherit` parents. A service-wide\n * `Admin` grant anchors on the row only.\n */\n readonly anchors: ReadonlyMap<string, readonly string[]>;\n}\n\n/** Options of {@link PolicyEngine.resolve}. */\nexport interface ResolveOptions {\n /**\n * Whether the principal's service-wide `Admin` grant on the service counts,\n * as it does for `levelsFor`. Default `true`. A collection scope asks its\n * anchor's policy with `false`, as a `{ scope, of }` form asks `of`'s: the\n * grants that count there are those on the collection's own service.\n */\n readonly grants?: boolean;\n}\n\n/** What a dispatcher's policy engine provides. */\nexport interface PolicyEngine extends DispatcherAccess {\n /** Decides `entry` and `scope` forms for the basic engine. */\n readonly rows: RowAccess;\n /** Evicts the cache and reports access changes: first on the sink list. `undefined` without policies. */\n readonly sink: FlushSink | undefined;\n /**\n * `levelsFor` and the anchors of each level, from one engine call: the\n * anchors reuse the rows the levels read. Live subscriptions record them.\n */\n resolve(\n service: string,\n principal: Principal,\n ids: readonly string[],\n options?: ResolveOptions,\n ): Promise<ResolvedAccess>;\n /**\n * Evicts from the cross-request cache what an access change this process\n * did not flush names (another node broadcast it), or a regranted user's\n * levels, so the re-resolution that follows reads afresh (`forgetAccess`).\n */\n forget(forgotten: Forgotten): void;\n}\n\nfunction bindingFor(state: EngineState, service: AnyContract | string): Binding {\n const name =\n typeof service === \"string\" ? service : (service as { readonly name?: unknown })?.name;\n const binding = typeof name === \"string\" ? state.bindings.get(name) : undefined;\n if (binding === undefined) {\n throw new TypeError(\n `dispatcher.access: ${String(name)} is not a service of this dispatcher with an access policy`,\n );\n }\n return binding;\n}\n\nfunction checkPrincipal(principal: unknown): Principal {\n const userId = (principal as { readonly userId?: unknown } | null | undefined)?.userId;\n if (typeof userId !== \"string\" || userId.length === 0) {\n throw new TypeError(\"dispatcher.access: principal must be a principal with a userId\");\n }\n return principal as Principal;\n}\n\n/** True when the principal's service-wide `Admin` grant passes every check on the service. */\nfunction bypasses(binding: Binding, principal: Principal): boolean {\n const { service } = binding;\n return service.adminBypass && serviceGrant(principal, service.name) === \"Admin\";\n}\n\nfunction checkIds(ids: unknown): readonly string[] {\n const valid = Array.isArray(ids) && ids.every((id) => typeof id === \"string\" && id !== \"\");\n if (!valid) {\n throw new TypeError(\"dispatcher.access.levelsFor: ids must be an array of row ids\");\n }\n return ids as readonly string[];\n}\n\n/** The levels, filters and anchors of a dispatcher's policies. */\nexport function createAccessApi(\n state: EngineState,\n): Pick<PolicyEngine, \"levelsFor\" | \"accessWhere\" | \"resolve\"> {\n return {\n async levelsFor(service, principal, ids) {\n const binding = bindingFor(state, service);\n const who = checkPrincipal(principal);\n checkIds(ids);\n if (bypasses(binding, who)) {\n return new Map(ids.map((id) => [id, \"Admin\"]));\n }\n return await startCall(state).levels(binding, who, ids);\n },\n async resolve(service, principal, ids, options) {\n const binding = bindingFor(state, service);\n const who = checkPrincipal(principal);\n checkIds(ids);\n if (options?.grants !== false && bypasses(binding, who)) {\n return {\n levels: new Map(ids.map((id) => [id, \"Admin\"])),\n anchors: new Map(ids.map((id) => [id, [anchorKey(binding.service.name, id)]])),\n };\n }\n const call = startCall(state);\n const levels = await call.levels(binding, who, ids);\n return { levels, anchors: await call.anchors(binding, ids) };\n },\n async accessWhere(service, principal, level) {\n const binding = bindingFor(state, service);\n const who = checkPrincipal(principal);\n if (!isAccessLevel(level)) {\n throw new TypeError(\"dispatcher.access.accessWhere: level must be an access level\");\n }\n if (bypasses(binding, who)) {\n return {};\n }\n return await startCall(state).where(binding, who, level);\n },\n };\n}\n","// Binding the services' access policies to a dispatcher (RFC 0003 section\n// 4.2). A policy is plain data until a dispatcher serves its service: then\n// it gets the service's model, the storage adapter it reads through, and the\n// cache namespaces its lookups are kept in. Binding also checks, once, what\n// would otherwise fail on the first call:\n//\n// - every `inherit({ from })` and every `{ scope, of }` names a service this\n// dispatcher serves, and that service declares a policy;\n// - no chain of `inherit` comes back to where it started;\n// - a policy that reads the database has a storage adapter to read through;\n//\n// and registers the columns policies read with the storage adapter\n// (`registerInterest`), so tracked writes carry their `before` and `after`.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { Registry } from \"../registry\";\nimport type { AnyService } from \"../service\";\nimport { modelKey, type StorageAdapter } from \"../storage\";\nimport { isCustomAccess } from \"./forms\";\nimport { namespace, type Namespace } from \"./cache\";\nimport type { AnyAccessPolicy, MembershipRead } from \"./policy\";\n\n/** A served service's policy, ready to evaluate. */\nexport interface Binding {\n readonly service: AnyService;\n /** The service's model, named as the client names it. */\n readonly model: string;\n readonly policy: AnyAccessPolicy;\n /** The columns of the model the policy reads; one query reads them all. */\n readonly columns: readonly string[];\n /** Where the rows' columns are memoized and cached. */\n readonly rows: Namespace;\n /** Where the policy's levels are memoized for one call. */\n readonly levels: Namespace;\n /** Where each membership table's levels are memoized and cached. */\n readonly memberships: ReadonlyMap<MembershipRead, Namespace>;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`createDispatcher: ${message}`);\n}\n\nfunction bind(service: AnyService, policy: AnyAccessPolicy, model: string): Binding {\n const { reads } = policy;\n return Object.freeze({\n service,\n model: modelKey(model),\n policy,\n columns: Object.freeze([...new Set(reads.columns)].filter((column) => column !== \"id\")),\n rows: namespace(`${service.name} rows`),\n levels: namespace(`${service.name} levels`),\n memberships: new Map(\n reads.memberships.map((read) => [read, namespace(`${service.name} ${read.model}`)]),\n ),\n });\n}\n\n/** The served service with a policy that `contract` names, or a `TypeError` saying why there is none. */\nfunction target(\n bindings: ReadonlyMap<string, Binding>,\n registry: Registry,\n contract: AnyContract,\n what: string,\n): Binding {\n const binding = bindings.get(contract.name);\n if (binding !== undefined) {\n return binding;\n }\n return registry.services.has(contract.name)\n ? fail(`${what} ${contract.name}, which declares no access policy`)\n : fail(`${what} ${contract.name}, which this dispatcher does not serve`);\n}\n\n/** Refuses an `inherit` chain that comes back to a service already on it. */\nfunction checkCycles(bindings: ReadonlyMap<string, Binding>, registry: Registry): void {\n const visit = (binding: Binding, path: readonly string[]): void => {\n for (const parent of binding.policy.reads.inherits) {\n const next = target(\n bindings,\n registry,\n parent,\n `${binding.service.name}'s access policy inherits from`,\n );\n if (path.includes(next.service.name)) {\n fail(\n `the access policies of ${[...path, next.service.name].join(\" -> \")} inherit in a cycle`,\n );\n }\n visit(next, [...path, next.service.name]);\n }\n };\n for (const binding of bindings.values()) {\n visit(binding, [binding.service.name]);\n }\n}\n\n/** Every `{ scope, of }` form must name a served service with a policy. */\nfunction checkScopeForms(bindings: ReadonlyMap<string, Binding>, registry: Registry): void {\n for (const service of registry.services.values()) {\n for (const method of Object.values(service.methods)) {\n const form = method.access;\n if (typeof form === \"object\" && !isCustomAccess(form) && form.scope !== undefined) {\n target(bindings, registry, form.of, `${service.name}.${method.name} uses scope access of`);\n }\n }\n }\n}\n\nfunction registerInterest(bindings: ReadonlyMap<string, Binding>, storage: StorageAdapter): void {\n for (const binding of bindings.values()) {\n if (binding.columns.length > 0) {\n storage.registerInterest(binding.model, binding.columns);\n }\n for (const read of binding.memberships.keys()) {\n storage.registerInterest(read.model, [read.entry, read.user, read.level]);\n }\n }\n}\n\n/**\n * Binds the policies of the services in `registry`, by service name. Throws\n * a `TypeError` for a policy the dispatcher could not evaluate.\n */\nexport function bindPolicies(\n registry: Registry,\n storage: StorageAdapter | undefined,\n): ReadonlyMap<string, Binding> {\n const bindings = new Map<string, Binding>();\n for (const service of registry.services.values()) {\n const { access, model } = service;\n if (access === undefined || model === undefined) {\n continue;\n }\n if (access.reads.storage && storage === undefined) {\n fail(\n `${service.name}'s access policy reads the database, so the dispatcher needs a storage adapter: pass db as trackPrisma(prisma), or pass storage`,\n );\n }\n bindings.set(service.name, bind(service, access, model));\n }\n checkCycles(bindings, registry);\n checkScopeForms(bindings, registry);\n if (storage !== undefined) {\n registerInterest(bindings, storage);\n }\n return bindings;\n}\n","// What tracked writes do to access (RFC 0003 sections 4.2 and 4.4): a flush\n// sink, first on the dispatcher's sink list, that evicts the cached lookups a\n// write may have changed and then tells `onAccessChanged` listeners which\n// rows' access may have changed and for whom. The revocation of live\n// subscriptions (section 4.4) listens here.\n//\n// Per write, from the bindings' policies:\n//\n// | Write | Evicts | Reports |\n// |-------------------------------------------|-------------------------------|---------------------------|\n// | a create or delete of a policy's row, or | the row's columns, for every | `{ service, id }` |\n// | an update setting a column it reads | user | |\n// | a membership row | the member's level on its row | `{ service, id, userId }` |\n// | | before and after the write | for each |\n// | a membership row whose row or user is not | the whole membership table | `{ service }`: any row |\n// | known (`ctx.touch`, array transactions) | | |\n// | the create or delete of a row with | every member's level on it | `{ service, id }` |\n// | memberships | | |\n//\n// A create is reported because an id can come back: a deleted row's\n// subscribers stay in its room (they get its removal), and a row created\n// again with that id must authorize them again before its first frame. A new\n// id concerns no subscription, so its report costs a lookup in an index.\n// An update that sets none of the columns a policy reads changes nothing.\n// Evictions all happen before the first listener is told.\n\nimport type { Logger } from \"../../contract/logger\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { FlushSink } from \"../uow/flushSink\";\nimport { ANY_FIELD, type WriteRecord } from \"../uow/types\";\nimport type { Binding } from \"./bindings\";\nimport type { AccessCache, Namespace } from \"./cache\";\nimport type { MembershipRead } from \"./policy\";\nimport { modelKey } from \"../storage\";\n\n/**\n * A row whose access may have changed: who may now see more or less of it.\n * `id` is the row (the anchor subscriptions record); without it, any row of\n * the service. `userId` is the user whose level may have changed; without it,\n * anyone's.\n */\nexport interface AccessChange {\n /** The service name. */\n readonly service: string;\n readonly id?: string;\n readonly userId?: string;\n}\n\n/** Receives access changes; a promise it returns is awaited before the flush moves on. */\nexport type AccessChangeListener = (change: AccessChange) => void | PromiseLike<void>;\n\ntype Rule =\n | { readonly kind: \"rows\"; readonly binding: Binding }\n | { readonly kind: \"anchor\"; readonly binding: Binding; readonly ns: Namespace }\n | {\n readonly kind: \"members\";\n readonly binding: Binding;\n readonly read: MembershipRead;\n readonly ns: Namespace;\n };\n\nfunction sets(write: WriteRecord, columns: readonly string[]): boolean {\n return (\n write.op !== \"update\" ||\n write.fields.includes(ANY_FIELD) ||\n write.fields.some((field) => columns.includes(field))\n );\n}\n\nfunction rulesByModel(bindings: ReadonlyMap<string, Binding>): Map<string, Rule[]> {\n const rules = new Map<string, Rule[]>();\n const add = (model: string, rule: Rule): void => {\n const key = modelKey(model);\n rules.set(key, [...(rules.get(key) ?? []), rule]);\n };\n for (const binding of bindings.values()) {\n if (binding.columns.length > 0) {\n add(binding.model, { kind: \"rows\", binding });\n }\n for (const [read, ns] of binding.memberships) {\n add(binding.model, { kind: \"anchor\", binding, ns });\n add(read.model, { kind: \"members\", binding, read, ns });\n }\n }\n return rules;\n}\n\ntype Values = WriteRecord[\"before\"];\n\nfunction stringIn(values: Values, key: string): string | undefined {\n const value = values?.[key];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/** The (user, row) pair in `values`, taking a column `values` lacks from `fallback`. */\nfunction keyIn(\n read: MembershipRead,\n values: Values,\n fallback: Values,\n): [string, string] | undefined {\n const user = stringIn(values, read.user) ?? stringIn(fallback, read.user);\n const entry = stringIn(values, read.entry) ?? stringIn(fallback, read.entry);\n return user === undefined || entry === undefined ? undefined : [user, entry];\n}\n\n/**\n * The (user, row) pairs a membership write touched: the old pair (from\n * `before`, which holds only the columns an update changed, then `after`)\n * unless the row was created, and the new pair (from `after`) unless it was\n * deleted. `undefined` when the write does not say: then any member's level\n * on any row may have changed.\n */\nfunction membershipKeys(write: WriteRecord, read: MembershipRead): [string, string][] | undefined {\n const old = write.op === \"create\" ? undefined : keyIn(read, write.before, write.after);\n const now = write.op === \"delete\" ? undefined : keyIn(read, write.after, undefined);\n if (\n (write.op !== \"create\" && old === undefined) ||\n (write.op !== \"delete\" && now === undefined)\n ) {\n return undefined;\n }\n const keys = new Map<string, [string, string]>();\n for (const key of [old, now]) {\n if (key !== undefined) {\n keys.set(`${key[0]}\\u0000${key[1]}`, key);\n }\n }\n return [...keys.values()];\n}\n\n/** Collects the access changes of one flush, without duplicates. */\nclass Changes {\n readonly #changes = new Map<string, AccessChange>();\n\n add(change: AccessChange): void {\n this.#changes.set(\n `${change.service}\\u0000${change.id ?? \"\"}\\u0000${change.userId ?? \"\"}`,\n change,\n );\n }\n\n get all(): AccessChange[] {\n return [...this.#changes.values()];\n }\n}\n\nfunction apply(\n rule: Rule,\n write: WriteRecord,\n cache: AccessCache | undefined,\n changes: Changes,\n): void {\n const service = rule.binding.service.name;\n if (rule.kind === \"rows\") {\n if (sets(write, rule.binding.columns)) {\n cache?.evict(rule.binding.rows, \"\", write.id);\n changes.add({ service, id: write.id });\n }\n return;\n }\n if (rule.kind === \"anchor\") {\n if (write.op !== \"update\") {\n cache?.evict(rule.ns, undefined, write.id);\n changes.add({ service, id: write.id });\n }\n return;\n }\n if (!sets(write, [rule.read.entry, rule.read.user, rule.read.level])) {\n return;\n }\n const keys = membershipKeys(write, rule.read);\n if (keys === undefined) {\n cache?.evict(rule.ns);\n changes.add({ service });\n return;\n }\n for (const [userId, id] of keys) {\n cache?.evict(rule.ns, userId, id);\n changes.add({ service, id, userId });\n }\n}\n\nasync function notify(\n listeners: ReadonlySet<AccessChangeListener>,\n changes: readonly AccessChange[],\n logger: Logger,\n): Promise<void> {\n const running: Promise<void>[] = [];\n for (const change of changes) {\n for (const listener of listeners) {\n running.push(\n (async () => {\n await listener(change);\n })().catch((error: unknown) => {\n logger.error(\"An onAccessChanged listener failed\", {\n category: \"quickdraw.access\",\n service: change.service,\n id: change.id,\n error: describeError(error),\n });\n }),\n );\n }\n }\n await Promise.all(running);\n}\n\n/** What {@link forgetAccess} evicts: an access change, or a user whose grants were reloaded. */\nexport interface Forgotten {\n readonly service?: string;\n readonly id?: string;\n readonly userId?: string;\n}\n\n/**\n * Evicts from this process's cache what an access change names, for a\n * change this process did not flush (another node broadcast it), or a user\n * whose grants were reloaded: the revocation that follows must read afresh.\n * `{ service, id }` drops the row's columns and every member's level on it,\n * with `userId` that member's level only; `{ service }` drops everything the\n * service's policy kept; `{ userId }` alone drops that user's levels in every\n * membership table.\n */\nexport function forgetAccess(\n bindings: ReadonlyMap<string, Binding>,\n cache: AccessCache | undefined,\n forgotten: Forgotten,\n): void {\n const { service, id, userId } = forgotten;\n const binding = service === undefined ? undefined : bindings.get(service);\n if (cache === undefined || (service !== undefined && binding === undefined)) {\n return;\n }\n for (const each of binding === undefined ? bindings.values() : [binding]) {\n if (service !== undefined) {\n cache.evict(each.rows, id === undefined ? undefined : \"\", id);\n }\n for (const ns of each.memberships.values()) {\n cache.evict(ns, service !== undefined && id === undefined ? undefined : userId, id);\n }\n }\n}\n\n/**\n * The flush sink that evicts cached lookups and reports access changes, or\n * `undefined` when no served service has a policy.\n */\nexport function createChangeSink(\n bindings: ReadonlyMap<string, Binding>,\n cache: AccessCache | undefined,\n listeners: ReadonlySet<AccessChangeListener>,\n logger: Logger,\n): FlushSink | undefined {\n const rules = rulesByModel(bindings);\n if (rules.size === 0) {\n return undefined;\n }\n return Object.freeze({\n async flush(writes: readonly WriteRecord[]): Promise<void> {\n const changes = new Changes();\n for (const write of writes) {\n for (const rule of rules.get(modelKey(write.model)) ?? []) {\n apply(rule, write, cache, changes);\n }\n }\n if (listeners.size > 0) {\n await notify(listeners, changes.all, logger);\n }\n },\n });\n}\n","// The row access the policy engine gives the basic engine: `{ entry: L }`\n// asks the service's own policy, `{ scope: L, of }` the policy of `of`'s\n// service, about every id the form names, in one batched lookup. The basic\n// engine has already let `\"public\"` through, answered `UNAUTHENTICATED` for\n// an anonymous caller, applied the service-wide `Admin` bypass and the\n// `service` half of a combined form; a `false` here becomes `FORBIDDEN`.\n\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { accessIds } from \"./forms\";\nimport { meetsLevel } from \"./levels\";\nimport { startCall, type EngineState } from \"./tools\";\nimport type { RowAccess } from \"./types\";\n\n/** Decides `entry` and `scope` forms from the bound policies. */\nexport function createRowAccess(state: EngineState): RowAccess {\n return Object.freeze({\n async allows(form, request) {\n const asks = form.scope === undefined ? request.service.name : form.of.name;\n const binding = state.bindings.get(asks);\n if (binding === undefined) {\n const kind = form.scope === undefined ? \"entry\" : \"scope\";\n throw new QuickdrawError(\n \"INTERNAL\",\n `${request.service.name}.${request.method} uses ${kind} access, but no access policy is configured for ${asks}`,\n );\n }\n const { principal } = request;\n // Policies compare user ids: a principal without one has no level anywhere.\n if (principal === null || typeof principal.userId !== \"string\" || principal.userId === \"\") {\n return false;\n }\n // A missing or empty id is FORBIDDEN: a failed lookup denies.\n const ids = accessIds(form, request.input);\n const required = form.scope === undefined ? form.entry : form.scope;\n const levels = await startCall(state).levels(binding, principal, ids);\n return ids.every((id) => meetsLevel(levels.get(id), required));\n },\n } satisfies RowAccess);\n}\n","// The policy engine (RFC 0003 section 4): one per dispatcher, over the\n// access policies its services declare. The dispatcher's default access\n// engine is the basic engine with this one's row access, so every form is\n// decided in one place:\n//\n// | Form | No principal | Passes when |\n// |------------------------------|-------------------|--------------------------------------------------|\n// | `\"public\"` | passes | always |\n// | `\"authenticated\"` | `UNAUTHENTICATED` | a principal exists |\n// | `{ service: L }` | `UNAUTHENTICATED` | the service grant is at least `L` |\n// | `{ entry: L, id? }` | `UNAUTHENTICATED` | the policy's level on every row is at least `L` |\n// | `{ service: L1, entry: L2 }` | `UNAUTHENTICATED` | either of the two |\n// | `{ scope: L, of, id }` | `UNAUTHENTICATED` | `of`'s policy gives at least `L` on the row |\n// | `custom(fn)` | `UNAUTHENTICATED` | `fn(ctx, input)` resolves `true` |\n//\n// A service-wide `Admin` grant on the method's service passes every form but\n// `\"public\"` when the service keeps `adminBypass` on; a grant below `Admin`\n// counts only where the form names `service`. A principal that fails gets\n// `FORBIDDEN`. Everything fails closed: a missing grant, an unknown level, a\n// missing id, a row that is not found and a malformed access column deny,\n// and a lookup that throws fails the call with `INTERNAL`. 4.1 let any\n// signed-in user call a `Read` method with no row id, and let a service\n// grant satisfy row checks at the same level\n// (4.1 `src/server/BaseService.ts:581-600`); neither survives.\n\nimport type { Logger } from \"../../contract/logger\";\nimport type { Registry } from \"../registry\";\nimport type { StorageAdapter } from \"../storage\";\nimport { createAccessApi, type PolicyEngine } from \"./api\";\nimport { bindPolicies } from \"./bindings\";\nimport { createAccessCache } from \"./cache\";\nimport {\n createChangeSink,\n forgetAccess,\n type AccessChangeListener,\n type Forgotten,\n} from \"./changes\";\nimport { createRowAccess } from \"./rowAccess\";\n\n/** The access options of a dispatcher: its `access` option, when it is not an engine. */\nexport interface AccessOptions {\n /**\n * Keep the database reads of access policies (row columns and membership\n * levels) across requests for this long, in milliseconds. Tracked writes to\n * the columns and models the policies read evict what they change; writes\n * the tracked client cannot see (raw SQL without `ctx.touch`, database\n * cascades, other processes) are seen only once the time passes. Default:\n * off, every request reads afresh (lookups are always memoized within one).\n */\n readonly cacheMs?: number;\n}\n\n/** Options of {@link createPolicyEngine}. */\nexport interface PolicyEngineOptions extends AccessOptions {\n readonly registry: Registry;\n readonly storage: StorageAdapter | undefined;\n readonly logger: Logger;\n}\n\nfunction checkCacheMs(cacheMs: unknown): number | undefined {\n if (cacheMs === undefined || cacheMs === 0) {\n return undefined;\n }\n if (typeof cacheMs !== \"number\" || !Number.isFinite(cacheMs) || cacheMs < 0) {\n throw new TypeError(\"createDispatcher: access.cacheMs must be a number of milliseconds\");\n }\n return cacheMs;\n}\n\n/**\n * Binds the services' access policies (`bindings.ts`; throws a `TypeError`\n * for one that could not be evaluated) and returns the engine that\n * evaluates them.\n */\nexport function createPolicyEngine(options: PolicyEngineOptions): PolicyEngine {\n const cacheMs = checkCacheMs(options.cacheMs);\n const bindings = bindPolicies(options.registry, options.storage);\n const state = {\n bindings,\n storage: options.storage,\n cache: cacheMs === undefined ? undefined : createAccessCache({ ttlMs: cacheMs }),\n };\n const listeners = new Set<AccessChangeListener>();\n return Object.freeze({\n ...createAccessApi(state),\n onAccessChanged(listener: AccessChangeListener): () => void {\n if (typeof listener !== \"function\") {\n throw new TypeError(\"dispatcher.access.onAccessChanged: listener must be a function\");\n }\n // A listener added twice is called twice and removed one at a time.\n const entry: AccessChangeListener = (change) => listener(change);\n listeners.add(entry);\n return () => {\n listeners.delete(entry);\n };\n },\n rows: createRowAccess(state),\n sink: createChangeSink(bindings, state.cache, listeners, options.logger),\n forget: (forgotten: Forgotten) => forgetAccess(bindings, state.cache, forgotten),\n });\n}\n","// The dispatcher's `access` option, resolved (RFC 0003 section 4): the policy\n// engine over the services' policies, and the access engine that decides each\n// method's form, the app's own or the basic engine with the policies' row\n// access.\n\nimport type { Logger } from \"../../contract/logger\";\nimport type { PolicyEngine } from \"../access/api\";\nimport { createBasicAccessEngine } from \"../access/basicEngine\";\nimport { createPolicyEngine, type AccessOptions } from \"../access/engine\";\nimport type { AccessEngine } from \"../access/types\";\nimport type { Registry } from \"../registry\";\nimport type { StorageAdapter } from \"../storage\";\n\nexport type { AccessEngine, AccessOptions, PolicyEngine };\n\nfunction isAccessEngine(value: unknown): value is AccessEngine {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as Partial<AccessEngine>).authorize === \"function\"\n );\n}\n\n/** The policy engine, and the access engine: the app's own, or the basic engine with the policies' row access. */\nexport function resolveAccess(\n access: AccessEngine | AccessOptions | undefined,\n registry: Registry,\n storage: StorageAdapter | undefined,\n logger: Logger,\n): { access: AccessEngine; policies: PolicyEngine } {\n if (access !== undefined && (typeof access !== \"object\" || access === null)) {\n throw new TypeError(\"createDispatcher: access must be an access engine or { cacheMs }\");\n }\n const engine = isAccessEngine(access) ? access : undefined;\n const accessOptions: AccessOptions = isAccessEngine(access) ? {} : (access ?? {});\n const policies = createPolicyEngine({\n registry,\n storage,\n logger,\n cacheMs: accessOptions.cacheMs,\n });\n return { access: engine ?? createBasicAccessEngine({ rows: policies.rows }), policies };\n}\n","// The default unit of work: it records no writes, but it already has the\n// shape tracked writes need. `run` awaits the handler's result inside its\n// own frame (RFC 0003 section 5.1), so swapping in the tracked implementation\n// changes no call site.\n\nimport type { UnitOfWork, UnitOfWorkFactory } from \"./types\";\n\nconst UNTRACKED: UnitOfWork = Object.freeze({\n sqlStatements: undefined,\n async run<T>(fn: () => T | PromiseLike<T>): Promise<T> {\n return await fn();\n },\n flush: (): Promise<void> => Promise.resolve(),\n});\n\n/** Units of work that record nothing. The dispatcher's default until writes are tracked. */\nexport const untrackedUnitOfWork: UnitOfWorkFactory = Object.freeze({\n begin: (): UnitOfWork => UNTRACKED,\n});\n","// Tracked writes in the dispatcher (RFC 0003 sections 5.1 and 5.3): the\n// units of work handler runs open, where they flush, and `ctx.touch`. A\n// tracked database client (`trackPrisma` on `./prisma`) carries its storage\n// adapter, so passing it as `db` is all an app does:\n//\n// export const db = trackPrisma(new PrismaClient({ adapter }));\n// qd.createServer({ app, services, db });\n//\n// Without one, units of work record nothing and `ctx.touch` does nothing.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { Logger } from \"../../contract/logger\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { BaseContext } from \"../context\";\nimport type { Registry } from \"../registry\";\nimport { modelKey, storageOf, type StorageAdapter } from \"../storage\";\nimport { combineSinks, inRevisionOrder, type FlushRevisions } from \"../uow/flush\";\nimport type { FlushSink } from \"../uow/flushSink\";\nimport type { UnitOfWorkFactory } from \"../uow/types\";\nimport { untrackedUnitOfWork } from \"../uow/untracked\";\n\n/** The dispatcher's tracked-writes options. */\nexport interface TrackingOptions {\n /**\n * How the server reads the database and learns of writes. Default: the\n * adapter a tracked `db` carries (`storageOf(db)`), or none.\n */\n readonly storage?: StorageAdapter;\n /** Opens the unit of work of each handler run. Default: the storage adapter's, or units that track nothing. */\n readonly unitOfWork?: UnitOfWorkFactory;\n /**\n * Where units of work flush their writes, in order: each flush goes to\n * every sink, and a sink that throws is logged and reported to the others\n * (`FlushSink.onFlushError`). Default: nowhere.\n */\n readonly flushSink?: FlushSink | readonly FlushSink[];\n}\n\n/** The tracked-writes part of the pipeline's settings. */\nexport interface Tracking {\n readonly storage: StorageAdapter | undefined;\n readonly unitOfWork: UnitOfWorkFactory;\n /** The sinks, combined into one that runs flushes in revision order. */\n readonly flushSink: FlushSink;\n /** Every call's `ctx.touch`. */\n readonly touch: BaseContext[\"touch\"];\n /**\n * Runs `fn` in a detached unit of work of the dispatcher, flushed once\n * `fn` settles, whatever unit or transaction is open where it starts:\n * `dispatcher.run(fn, { detached: true })` for a kit's work after a call\n * (the admin kit's `onCommitted`). Rejects with what `fn` throws.\n */\n readonly runDetached: (fn: () => unknown) => Promise<unknown>;\n}\n\nfunction sinksOf(option: TrackingOptions[\"flushSink\"]): readonly FlushSink[] {\n if (option === undefined) {\n return [];\n }\n const sinks: readonly unknown[] = Array.isArray(option) ? option : [option];\n for (const sink of sinks) {\n if (typeof (sink as Partial<FlushSink> | null)?.flush !== \"function\") {\n throw new TypeError(\"createDispatcher: flushSink must be a flush sink or an array of them\");\n }\n }\n return sinks as readonly FlushSink[];\n}\n\n/**\n * The model `ctx.touch` names: a model name as is, or a contract's model,\n * which its service declares with `model` (RFC 0003 section 3).\n */\nfunction modelOf(registry: Registry, target: string | AnyContract): string {\n if (typeof target === \"string\" && target.length > 0) {\n return modelKey(target);\n }\n if (typeof target !== \"object\" || target === null) {\n throw new TypeError('ctx.touch: name the model, as in ctx.touch(\"task\", ids)');\n }\n for (const service of registry.services.values()) {\n if (service.contract === target && service.model !== undefined) {\n return modelKey(service.model);\n }\n }\n throw new QuickdrawError(\n \"INTERNAL\",\n `ctx.touch: no service of this dispatcher declares the database model of ${target.name}; pass the model name, as in ctx.touch(\"task\", ids)`,\n );\n}\n\nfunction idsOf(ids: string | readonly string[]): readonly string[] {\n const list: unknown = typeof ids === \"string\" ? [ids] : ids;\n if (!Array.isArray(list) || list.some((id) => typeof id !== \"string\" || id.length === 0)) {\n throw new TypeError(\"ctx.touch: ids must be a row id or an array of row ids\");\n }\n return list as readonly string[];\n}\n\n/** The storage adapter the dispatcher reads through: the one given, or the one a tracked `db` carries. */\nexport function storageFor(options: TrackingOptions, db: unknown): StorageAdapter | undefined {\n return options.storage ?? storageOf(db);\n}\n\n/**\n * Resolves the dispatcher's tracked-writes options. The framework's own\n * sinks go first on the sink list, in the order given (the live data's\n * intake, the access cache's evictions and access-change events,\n * `createServer`'s grants refresh, the entity frames, the collection deltas,\n * the change topics), so nothing a flush revokes gets its frames, and the\n * app's sinks after them read access afresh. `revisions` hand flushes the\n * cluster's shared revisions when the server is behind a counter.\n */\nexport function resolveTracking(\n options: TrackingOptions,\n registry: Registry,\n db: unknown,\n logger: Logger,\n framework: readonly (FlushSink | undefined)[] = [],\n revisions?: FlushRevisions,\n): Tracking {\n const storage = storageFor(options, db);\n const unitOfWork = options.unitOfWork ?? storage?.unitOfWork ?? untrackedUnitOfWork;\n const touch: BaseContext[\"touch\"] = (target, ids, touchOptions) => {\n const model = modelOf(registry, target);\n const rows = idsOf(ids);\n unitOfWork.touch?.(model, rows, touchOptions);\n };\n const own = framework.filter((sink): sink is FlushSink => sink !== undefined);\n const flushSink = inRevisionOrder(\n combineSinks([...own, ...sinksOf(options.flushSink)], logger),\n revisions,\n );\n const runDetached = async (fn: () => unknown): Promise<unknown> => {\n const unit = unitOfWork.begin({\n requestId: crypto.randomUUID(),\n transport: \"internal\",\n sink: flushSink,\n detached: true,\n });\n try {\n return await unit.run(fn);\n } finally {\n // A flush never rejects: its failures are logged where it runs.\n await unit.flush();\n }\n };\n return { storage, unitOfWork, flushSink, touch, runDetached };\n}\n","// The dispatcher's options and their defaults, resolved once into the\n// settings every pipeline stage reads.\n\nimport { consoleLogger, type Logger } from \"../../contract/logger\";\nimport {\n createDevWarnings,\n createLoopWatch,\n strictWarningsOf,\n type DevWarnings,\n type LoopWatch,\n} from \"../devWarnings\";\nimport { createLive, type ChangeLogOptions, type Live } from \"../emit/live\";\nimport { warnTieredOutputs } from \"../emit/tieredOutputs\";\nimport type { Registry } from \"../registry\";\nimport type { FlushSink } from \"../uow/flushSink\";\nimport {\n resolveAccess,\n type AccessEngine,\n type AccessOptions,\n type PolicyEngine,\n} from \"./accessSettings\";\nimport { createRecorder, type CallRecord, type RecordDetails } from \"./metrics\";\nimport type { VersionSource } from \"./notModified\";\nimport { resolveTracking, storageFor, type Tracking, type TrackingOptions } from \"./tracking\";\n\n/**\n * The lane each socket's subscription events (`qd:sub`, `qd:col:sub`,\n * `qd:col:items`, `qd:watch`) run in, as queries run in theirs: the socket\n * rate limiter does not count those events, so this caps them instead.\n */\nexport interface SubscriptionLimits {\n /** Subscription events one socket may have running at once. Default 8. */\n readonly maxInFlight: number;\n /** Subscription events one socket may have waiting; past that, `RATE_LIMITED`. Default 64. */\n readonly maxQueued: number;\n}\n\n/**\n * The dispatcher's limits. The first three are what a server announces to\n * clients in `qd:hello` (`HelloLimits`).\n */\nexport interface DispatcherLimits {\n /** Queries one connection may run at once. Default 16. */\n readonly maxInFlightQueries: number;\n /** Queries one connection may have waiting; past that, `RATE_LIMITED`. Default 64. */\n readonly maxQueuedQueries: number;\n /** A handler's time limit when its method sets no `timeoutMs`, in milliseconds. Default 30,000. */\n readonly callTimeoutMs: number;\n /** The `retryAfterMs` of the `RATE_LIMITED` error a full queue answers with. Default 1,000. */\n readonly retryAfterMs: number;\n /** Each socket's lane of subscription events. Default 8 in flight and 64 queued. */\n readonly subscriptions: SubscriptionLimits;\n}\n\n/** The dispatcher's `limits` option: any of the limits, and any part of `subscriptions`. */\nexport type LimitsOptions = Partial<Omit<DispatcherLimits, \"subscriptions\">> & {\n readonly subscriptions?: Partial<SubscriptionLimits>;\n};\n\n/** The defaults of RFC 0003 section 9, and the subscription lane's. */\nexport const DEFAULT_LIMITS: DispatcherLimits = Object.freeze({\n maxInFlightQueries: 16,\n maxQueuedQueries: 64,\n callTimeoutMs: 30_000,\n retryAfterMs: 1_000,\n subscriptions: Object.freeze({ maxInFlight: 8, maxQueued: 64 }),\n});\n\n/** The longest time limit `setTimeout` honours, in milliseconds. */\nexport const MAX_TIMEOUT_MS = 2_147_483_647;\n\n/** The pipeline's options: every seam and limit has a default. */\nexport interface PipelineOptions extends TrackingOptions {\n /** Receives one entry per call, and the original error of every `INTERNAL` failure. Default: the console. */\n readonly logger?: Logger;\n /**\n * The access options (`{ cacheMs }`), or an engine of the app's own that\n * decides each method's access form. Default: the basic engine with the\n * row access of the services' policies (RFC 0003 section 4), no cache.\n */\n readonly access?: AccessEngine | AccessOptions;\n /**\n * Answers query versions for \"not modified\" replies, for queries that\n * declare no `version` of their own. Default: the version of the row a\n * query returns, for a query whose output is one projection row and whose\n * input has an `id`: the service's `versionColumn`, or the change log.\n */\n readonly versions?: VersionSource;\n /**\n * The in-process change log (RFC 0003 section 6): the revision of the last\n * flush that touched each row, which answers \"not modified\" for services\n * without a `versionColumn`. It sees only this process's writes, so an app\n * running several processes behind a load balancer passes `false` (the log\n * then answers nothing) or declares `versionColumn`s; behind a Socket.IO\n * cluster adapter it answers nothing either. Default: answering, keeping\n * 100,000 rows.\n */\n readonly changeLog?: ChangeLogOptions | false;\n readonly limits?: LimitsOptions;\n /** Calls slower than this are logged at `warn`, in milliseconds. Default 1,000. */\n readonly slowMs?: number;\n /**\n * Replies larger than this are logged at `warn`, in bytes, and raise the\n * `oversized-response` development warning. Default 1 MiB.\n */\n readonly maxResponseBytes?: number;\n /**\n * Check every handler result against its method's contract output; a\n * mismatch fails the call with `INTERNAL`. Default: on unless `NODE_ENV`\n * is `\"production\"`, so always on in tests. A stream that declares\n * `validate: \"development\"` checks its items only while this is on.\n */\n readonly outputValidation?: boolean;\n /** Deep-freeze the results of sharing queries. Default: on unless `NODE_ENV` is `\"production\"`. */\n readonly freezeSharedResults?: boolean;\n /** Receives every call's completion record. An error it throws is logged and ignored. */\n readonly onCall?: (record: CallRecord) => void;\n}\n\n/** Everything the pipeline stages read, resolved from the dispatcher's options. */\nexport interface PipelineSettings extends Tracking {\n readonly registry: Registry;\n readonly db: unknown;\n readonly logger: Logger;\n readonly access: AccessEngine;\n /** The services' access policies, evaluated: `dispatcher.access`. */\n readonly policies: PolicyEngine;\n readonly versions: VersionSource | undefined;\n /** Entity subscriptions, collections, their frames and revocation (RFC 0003 sections 4.4, 6 and 7). */\n readonly live: Live;\n readonly limits: DispatcherLimits;\n readonly outputValidation: boolean;\n readonly freezeSharedResults: boolean;\n /** The development warnings of this dispatcher and of the write tracker it attaches to (`../devWarnings.ts`). */\n readonly warnings: DevWarnings;\n /** Counts each connection's calls and refusals, and warns when they look like a client loop (`../devWarnings.ts`). */\n readonly loops: LoopWatch;\n readonly record: (record: CallRecord, details: RecordDetails) => void;\n}\n\nfunction checkCount(name: string, value: number, max: number): number {\n if (!Number.isInteger(value) || value < 0 || value > max) {\n throw new TypeError(`createDispatcher: ${name} must be an integer from 0 to ${max}`);\n }\n return value;\n}\n\nfunction resolveSubscriptionLimits(\n limits: Partial<SubscriptionLimits> | undefined,\n): SubscriptionLimits {\n if (limits !== undefined && (typeof limits !== \"object\" || limits === null)) {\n throw new TypeError(\n \"createDispatcher: limits.subscriptions must be { maxInFlight, maxQueued }\",\n );\n }\n const merged = { ...DEFAULT_LIMITS.subscriptions, ...limits };\n checkCount(\"limits.subscriptions.maxQueued\", merged.maxQueued, Number.MAX_SAFE_INTEGER);\n const inFlight = merged.maxInFlight;\n if (checkCount(\"limits.subscriptions.maxInFlight\", inFlight, Number.MAX_SAFE_INTEGER) === 0) {\n throw new TypeError(\"createDispatcher: limits.subscriptions.maxInFlight must be at least 1\");\n }\n return Object.freeze(merged);\n}\n\nfunction resolveLimits(limits: LimitsOptions = {}): DispatcherLimits {\n const subscriptions = resolveSubscriptionLimits(limits.subscriptions);\n const merged = { ...DEFAULT_LIMITS, ...limits, subscriptions };\n checkCount(\"limits.maxInFlightQueries\", merged.maxInFlightQueries, Number.MAX_SAFE_INTEGER);\n checkCount(\"limits.maxQueuedQueries\", merged.maxQueuedQueries, Number.MAX_SAFE_INTEGER);\n checkCount(\"limits.retryAfterMs\", merged.retryAfterMs, MAX_TIMEOUT_MS);\n if (checkCount(\"limits.callTimeoutMs\", merged.callTimeoutMs, MAX_TIMEOUT_MS) === 0) {\n throw new TypeError(\"createDispatcher: limits.callTimeoutMs must be at least 1\");\n }\n if (merged.maxInFlightQueries === 0) {\n throw new TypeError(\"createDispatcher: limits.maxInFlightQueries must be at least 1\");\n }\n return Object.freeze(merged);\n}\n\n/**\n * Applies the defaults to the dispatcher's options. `accessSinks` run right\n * after the access sink, before any frame of a flush is sent.\n */\nexport function resolveSettings(\n options: PipelineOptions,\n registry: Registry,\n db: unknown,\n accessSinks: readonly FlushSink[] = [],\n): PipelineSettings {\n const development = process.env.NODE_ENV !== \"production\";\n const logger = options.logger ?? consoleLogger;\n const warnings = createDevWarnings({ logger, development, strict: strictWarningsOf(options) });\n warnTieredOutputs(registry, warnings);\n const storage = storageFor(options, db);\n const { access, policies } = resolveAccess(options.access, registry, storage, logger);\n const outputValidation = options.outputValidation ?? development;\n const live = createLive({\n registry,\n storage,\n policies,\n access,\n logger,\n changeLog: options.changeLog,\n outputValidation,\n });\n return Object.freeze({\n registry,\n db,\n logger,\n access,\n policies,\n ...resolveTracking(\n options,\n registry,\n db,\n logger,\n [live.intake, policies.sink, ...accessSinks, live.emit, live.collections, live.topics],\n live.revisions,\n ),\n versions: options.versions ?? live.versions,\n live,\n limits: resolveLimits(options.limits),\n outputValidation,\n freezeSharedResults: options.freezeSharedResults ?? development,\n warnings,\n loops: createLoopWatch(warnings, logger),\n record: createRecorder({\n logger,\n onCall: options.onCall,\n slowMs: options.slowMs ?? 1_000,\n maxResponseBytes: options.maxResponseBytes ?? 1_048_576,\n warnings,\n }),\n });\n}\n","// One handler run (RFC 0003 section 9, step 7): the handler inside its unit\n// of work, with an abort signal and a time limit. Callers join a run; a\n// shared query run has several. The run settles every caller exactly once:\n// with the handler's outcome, with `TIMEOUT` when the time limit of the call\n// that started the run passes first, or with `CANCELLED` (or `TIMEOUT`) for a\n// caller whose own signal aborts first. The time limit covers the output\n// check too, not the handler alone. The handler's signal aborts on the time\n// limit, or when every caller has left. A result that arrives after that is\n// dropped.\n\nimport type { QuickdrawError } from \"../../protocol/errors\";\nimport { quietly } from \"../devWarnings\";\nimport type { UnitOfWork } from \"../uow/types\";\nimport { abortError, toQuickdrawError } from \"./errors\";\n\n/** How a run, or one caller's share of it, ended. */\nexport type Outcome =\n | { readonly ok: true; readonly value: unknown }\n | { readonly ok: false; readonly error: QuickdrawError };\n\n/** Options of {@link startRun}. */\nexport interface RunOptions {\n /**\n * The time limit of the call that starts the run: it aborts, with the\n * `TIMEOUT` error as its reason, once the limit passes, and the run then\n * settles every caller with that error and aborts the handler.\n */\n readonly timeLimit: AbortSignal;\n readonly unit: UnitOfWork;\n /** Calls the handler with the run's signal. */\n readonly invoke: (signal: AbortSignal) => unknown;\n /** Run the handler `quietly`: no development checks of its statements (a kit's handler). */\n readonly quiet?: boolean;\n /** Turns the handler's value into the run's outcome: output validation, freezing. */\n readonly accept: (value: unknown) => Promise<Outcome>;\n}\n\n/** A handler run in progress, or finished. */\nexport interface Run {\n /** The run's own outcome. It never rejects. */\n readonly outcome: Promise<Outcome>;\n /** The run's outcome once it has one, read synchronously. */\n readonly settled: Outcome | undefined;\n readonly unit: UnitOfWork;\n /** Resolves once the handler itself has settled, which may be after the run timed out. Never rejects. */\n readonly handlerDone: Promise<void>;\n /** True once the handler itself has settled. */\n readonly handlerSettled: boolean;\n /**\n * Adds a caller. Resolves with the run's outcome, or, when `signal` aborts\n * first, with `TIMEOUT` if the caller's time limit aborted it and\n * `CANCELLED` otherwise. A caller without a signal waits for the outcome.\n */\n join(signal: AbortSignal | undefined): Promise<Outcome>;\n}\n\n/** How a caller whose signal aborted leaves the run. */\nfunction stopped(signal: AbortSignal): Outcome {\n return { ok: false, error: abortError(signal) };\n}\n\n/** The mutable state of one run, shared by its helpers. */\ninterface RunState {\n final: Outcome | undefined;\n handlerSettled: boolean;\n participants: number;\n readonly outcome: Promise<Outcome>;\n /** Settles the run unless it already settled; aborts the handler for an error that ends it early. */\n readonly end: (result: Outcome, abort: boolean) => void;\n}\n\nfunction createState(options: RunOptions, controller: AbortController): RunState {\n let resolveOutcome: (outcome: Outcome) => void = () => undefined;\n const outcome = new Promise<Outcome>((resolve) => {\n resolveOutcome = resolve;\n });\n const { timeLimit } = options;\n const onTimeLimit = (): void => state.end(stopped(timeLimit), true);\n const state: RunState = {\n final: undefined,\n handlerSettled: false,\n participants: 0,\n outcome,\n end(result, abort) {\n if (state.final !== undefined) {\n return;\n }\n state.final = result;\n timeLimit.removeEventListener(\"abort\", onTimeLimit);\n resolveOutcome(result);\n if (abort && !result.ok) {\n controller.abort(result.error);\n }\n },\n };\n if (timeLimit.aborted) {\n onTimeLimit();\n } else {\n timeLimit.addEventListener(\"abort\", onTimeLimit, { once: true });\n }\n return state;\n}\n\nfunction runHandler(options: RunOptions, state: RunState, signal: AbortSignal): Promise<void> {\n const invoke = (): unknown => options.invoke(signal);\n let started: Promise<unknown>;\n try {\n started = options.unit.run(options.quiet === true ? () => quietly(invoke) : invoke);\n } catch (error) {\n started = Promise.reject(error);\n }\n return started.then(\n async (value) => {\n state.handlerSettled = true;\n if (state.final !== undefined) {\n return;\n }\n try {\n state.end(await options.accept(value), false);\n } catch (error) {\n state.end({ ok: false, error: toQuickdrawError(error) }, false);\n }\n },\n (error: unknown) => {\n state.handlerSettled = true;\n state.end({ ok: false, error: toQuickdrawError(error) }, false);\n },\n );\n}\n\nfunction joinRun(state: RunState, signal: AbortSignal | undefined): Promise<Outcome> {\n if (signal?.aborted === true) {\n return Promise.resolve(stopped(signal));\n }\n state.participants += 1;\n if (signal === undefined) {\n return state.outcome;\n }\n return new Promise<Outcome>((resolve) => {\n const onAbort = (): void => {\n state.participants -= 1;\n const left = stopped(signal);\n resolve(left);\n // The last caller to leave ends the run with its reason, and aborts the handler.\n if (state.participants === 0) {\n state.end(left, true);\n }\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n void state.outcome.then((result) => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(result);\n });\n });\n}\n\n/** Starts the handler inside its unit of work, with a time limit. Add callers with `join`. */\nexport function startRun(options: RunOptions): Run {\n const controller = new AbortController();\n const state = createState(options, controller);\n const handlerDone = runHandler(options, state, controller.signal);\n return {\n outcome: state.outcome,\n get settled() {\n return state.final;\n },\n unit: options.unit,\n handlerDone,\n get handlerSettled() {\n return state.handlerSettled;\n },\n join: (signal) => joinRun(state, signal),\n };\n}\n","// Sharing identical reads (RFC 0003 section 9, step 6). A query that declares\n// `share` runs its handler once for every identical call in flight: same\n// service, method, input and, for `share: \"caller\"`, the same principal over\n// the same transport with the same `ctx.mcp`. The key is built from the\n// parsed input, after validation and after each caller was authorized, so a\n// bad payload never joins a good run and a joiner never skips its own access\n// check. With `ttlMs`, a successful result is reused for that long after the\n// run; an error is never kept.\n//\n// Two calls share only when their keys are equal, so a key must tell apart\n// everything a handler can tell apart. JSON does not: it drops function\n// members and symbol keys, and it writes whatever a `toJSON` returns. Two\n// sessions of one user whose principals differ only in a `can()` method, or\n// in claims a `toJSON` leaves out, would share a run computed with the first\n// one's rights. The key writer below is strict instead: it writes plain data\n// only, and a value it cannot write in full makes the call run unshared.\n\nimport type { McpContext, Principal, Transport } from \"../types\";\n\nclass NotShareable extends Error {}\n\nfunction refuse(): never {\n throw new NotShareable();\n}\n\n/** The own members of a plain object or array, by name; anything else in it is refused. */\nfunction ownValues(value: object): Map<string, unknown> {\n if (Object.getOwnPropertySymbols(value).length > 0) {\n refuse();\n }\n const values = new Map<string, unknown>();\n for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {\n // A getter could answer differently for each caller; only data is keyed.\n if (!(\"value\" in descriptor)) {\n refuse();\n }\n values.set(key, descriptor.value);\n }\n return values;\n}\n\nfunction writeArray(value: readonly unknown[], seen: Set<object>): string {\n const values = ownValues(value);\n // Dense, with no members besides its items and `length`.\n if (values.size !== value.length + 1) {\n refuse();\n }\n const items: string[] = [];\n for (let index = 0; index < value.length; index += 1) {\n const key = String(index);\n if (!values.has(key)) {\n refuse();\n }\n items.push(write(values.get(key), seen));\n }\n return `[${items.join(\",\")}]`;\n}\n\nfunction writeRecord(value: object, seen: Set<object>): string {\n const values = ownValues(value);\n const entries = [...values.keys()]\n .sort()\n .map((key) => `${JSON.stringify(key)}:${write(values.get(key), seen)}`);\n return `{${entries.join(\",\")}}`;\n}\n\n/** A plain object, an array, or a `Date`; anything else (a class instance, a `Map`, a `toJSON`) is refused. */\nfunction writeObject(value: object, seen: Set<object>): string {\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype === Date.prototype && Reflect.ownKeys(value).length === 0) {\n return `Date(${(value as Date).getTime()})`;\n }\n const array = prototype === Array.prototype && Array.isArray(value);\n if (!array && prototype !== Object.prototype && prototype !== null) {\n refuse();\n }\n if (seen.has(value)) {\n refuse();\n }\n seen.add(value);\n const written = array ? writeArray(value as unknown[], seen) : writeRecord(value, seen);\n seen.delete(value);\n return written;\n}\n\nfunction write(value: unknown, seen: Set<object>): string {\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return JSON.stringify(value);\n case \"number\":\n if (Object.is(value, -0)) {\n return \"-0\";\n }\n return Number.isFinite(value) ? JSON.stringify(value) : String(value);\n case \"bigint\":\n return `${value}n`;\n case \"undefined\":\n return \"undefined\";\n case \"object\":\n return value === null ? \"null\" : writeObject(value, seen);\n default:\n // A function or a symbol: nothing a key could compare.\n return refuse();\n }\n}\n\n/**\n * Writes a value as a share key: object keys sorted, so equal values give\n * equal strings whatever their key order, and two values that differ in any\n * member give different strings. It writes strings, numbers (`-0`, `NaN` and\n * the infinities included), booleans, `null`, `undefined`, bigints (`12n`),\n * dates (`Date(0)`), arrays and plain objects. It returns `undefined` for\n * anything else, so the call runs unshared: a function or symbol anywhere, a\n * symbol key, a getter, a sparse array, a cycle, or an object that is not\n * plain (a class instance, with or without `toJSON`, a `Map`, a `Buffer`).\n */\nexport function stableStringify(value: unknown): string | undefined {\n try {\n return write(value, new Set());\n } catch (error) {\n if (error instanceof NotShareable) {\n return undefined;\n }\n throw error;\n }\n}\n\n/** Who a `share: \"caller\"` run belongs to. */\nexport interface ShareCaller {\n readonly principal: Principal | null;\n readonly transport: Transport;\n /** The call's `ctx.mcp`, when the MCP bridge set one. */\n readonly mcp: McpContext | undefined;\n}\n\n/**\n * The key one call's share run is stored under, or `undefined` when the\n * input or the caller cannot be keyed (the call then runs unshared). A\n * `\"caller\"` key includes the whole principal, the transport and the call's\n * `ctx.mcp`, so two sessions of one user with different claims, grants or\n * MCP token scopes never share, and neither do one principal's calls over two\n * transports; an `\"all\"` key uses `*`.\n */\nexport function shareKey(\n service: string,\n method: string,\n caller: ShareCaller | \"*\",\n input: unknown,\n): string | undefined {\n const who =\n caller === \"*\" ? \"*\" : stableStringify([caller.principal, caller.transport, caller.mcp]);\n const what = stableStringify(input);\n if (who === undefined || what === undefined) {\n return undefined;\n }\n return JSON.stringify([service, method, who, what]);\n}\n\n/** Recursively freezes plain objects and arrays, the way a shared result is frozen in development. */\nexport function deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) {\n return value;\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) {\n return value;\n }\n Object.freeze(value);\n for (const member of Object.values(value)) {\n deepFreeze(member);\n }\n return value;\n}\n\n/** A run in the share table: anything with a settled-or-pending outcome. */\nexport interface ShareEntry<Outcome> {\n readonly outcome: Promise<Outcome>;\n}\n\n/** Runs in flight, and successful results kept for their `ttlMs`, by share key. */\nexport interface ShareTable<Entry extends ShareEntry<{ readonly ok: boolean }>> {\n get(key: string): Entry | undefined;\n /**\n * Stores a run under `key` until it settles. A failed run is removed at\n * once; a successful one after `ttlMs`, or at once without it.\n */\n add(key: string, entry: Entry, ttlMs: number | undefined): void;\n readonly size: number;\n}\n\nexport function createShareTable<\n Entry extends ShareEntry<{ readonly ok: boolean }>,\n>(): ShareTable<Entry> {\n const entries = new Map<string, Entry>();\n const remove = (key: string, entry: Entry): void => {\n if (entries.get(key) === entry) {\n entries.delete(key);\n }\n };\n return {\n get: (key) => entries.get(key),\n add(key, entry, ttlMs) {\n entries.set(key, entry);\n void entry.outcome.then((outcome) => {\n if (!outcome.ok || ttlMs === undefined) {\n remove(key, entry);\n return;\n }\n const timer = setTimeout(() => remove(key, entry), ttlMs);\n (timer as { unref?: () => void }).unref?.();\n });\n },\n get size() {\n return entries.size;\n },\n };\n}\n","// Each caller's reply after the run (RFC 0003 sections 6 and 9): a projection\n// output's rows without the fields the caller's level on each row does not\n// reach. It runs on each caller's copy, never inside the run, so a shared\n// run's `Admin` result is never handed to a `Read` joiner whole.\n//\n// Every caller of a shared run reads its own levels, but callers whose levels\n// hide the same fields on every row get one copy, stripped once, and its JSON\n// text is written once for all of them: a transport that writes JSON sends\n// the same text to each. Encoded per caller instead, a board query shared by\n// twenty viewers is encoded twenty times back to back, holding the event loop\n// for the whole stretch (the 5.0 benchmark, `bench/reports/5.0.0.md`).\n\nimport { serviceGrant } from \"../access/levels\";\nimport type { RowLevels } from \"../access/policy\";\nimport { readerView, wholeView, type ReaderView } from \"../emit/projection\";\nimport type { RegisteredMethod } from \"../registry\";\nimport type { Principal } from \"../types\";\nimport type { SharedData } from \"./request\";\nimport type { Run } from \"./run\";\nimport type { PipelineSettings } from \"./settings\";\nimport { deepFreeze } from \"./share\";\n\n/** A caller's result, with its group's shared JSON text when it came from a shared run. */\nexport interface CallerReply {\n readonly data: unknown;\n readonly shared: SharedData | undefined;\n}\n\n/** A group's copy of a run's result; its JSON text is written on first use. */\nfunction variant(data: unknown): SharedData {\n let written = false;\n let text: string | undefined;\n return {\n data,\n json() {\n if (!written) {\n // `JSON.stringify` returns `undefined` for `undefined` and functions, whatever its type says.\n text = JSON.stringify(data) as string | undefined;\n written = true;\n }\n return text;\n },\n };\n}\n\n/** The copies of each shared run's result, by reader view key, for as long as the run is kept. */\nconst variants = new WeakMap<Run, Map<string, SharedData>>();\n\n/**\n * The reply of a caller who took its result from `run` and sees it as `view`\n * shows: the copy made for the first caller with the same view, or a new one.\n * Views are equal only when they hide the same fields on every row, so a\n * caller never gets a copy made for a level above its own. Copies are frozen\n * when shared results are (`freezeSharedResults`), since callers share them.\n */\nfunction sharedReply(run: Run, view: ReaderView, freeze: boolean): CallerReply {\n let copies = variants.get(run);\n if (copies === undefined) {\n copies = new Map();\n variants.set(run, copies);\n }\n let copy = copies.get(view.key);\n if (copy === undefined) {\n const data = view.strip();\n copy = variant(freeze ? deepFreeze(data) : data);\n copies.set(view.key, copy);\n }\n return { data: copy.data, shared: copy };\n}\n\n/**\n * The caller's level on each row: the one `dispatcher.access.levelsFor`\n * gives; without a policy, only a service-wide `Admin` grant (with\n * `adminBypass`) reaches tiered fields.\n */\nfunction levelsReader(\n settings: PipelineSettings,\n target: RegisteredMethod,\n principal: Principal | null,\n): (ids: readonly string[]) => Promise<RowLevels> {\n const { service } = target;\n return async (ids) => {\n if (principal === null) {\n return new Map();\n }\n if (service.access !== undefined && service.model !== undefined) {\n return await settings.policies.levelsFor(service.name, principal, ids);\n }\n const bypass = service.adminBypass && serviceGrant(principal, service.name) === \"Admin\";\n return new Map(ids.map((id) => [id, bypass ? \"Admin\" : null]));\n };\n}\n\n/**\n * The caller's result: the run's value as the caller's levels let it see it,\n * shared with the other callers of `call.source` (the shared run the call\n * started or joined) who see the same fields.\n */\nexport async function forCaller(\n settings: PipelineSettings,\n target: RegisteredMethod,\n call: { readonly principal: Principal | null; readonly source: Run | undefined },\n value: unknown,\n): Promise<CallerReply> {\n const { projection } = target.method;\n const view =\n projection === undefined\n ? wholeView(value)\n : await readerView(projection, value, levelsReader(settings, target, call.principal));\n return call.source === undefined\n ? { data: view.strip(), shared: undefined }\n : sharedReply(call.source, view, settings.freezeSharedResults);\n}\n","// The pipeline stages that run the handler (RFC 0003 section 9, steps 6 to\n// 8): join an identical run in flight when the query shares, otherwise start\n// one inside a unit of work, then project a projection output's rows, or\n// reduce a schema output to what its schema declares (`schemaOutput.ts`),\n// and check the result against the contract. Field tiers are stripped later,\n// per caller (`tiers.ts`), because a shared run's result goes to every\n// caller; callers who see the same fields share one copy (`replies.ts`).\n\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { NEVER_ABORTED, withSignal, type AnyContext } from \"../context\";\nimport { projectOutput } from \"../emit/projection\";\nimport { warnTieredReply } from \"../emit/tieredOutputs\";\nimport type { RegisteredMethod } from \"../registry\";\nimport { isKitHandler } from \"../service\";\nimport { startRun, type Outcome, type Run } from \"./run\";\nimport { deepFreeze, shareKey, type ShareTable } from \"./share\";\nimport type { PipelineSettings } from \"./settings\";\nimport { outputIssues } from \"./validation\";\n\nexport { forCaller } from \"./replies\";\n\n/** What `execute` needs to know about the call, and what it reports back. */\nexport interface ExecuteCall {\n readonly requestId: string;\n readonly transport: AnyContext[\"transport\"];\n readonly principal: AnyContext[\"principal\"];\n /**\n * Aborts when the caller cancels (a query; a mutation cannot be cancelled)\n * or the call's time limit passes. The call then leaves the run it joined.\n */\n readonly signal: AbortSignal | undefined;\n /** Aborts when the call's time limit passes. A run this call starts ends with it. */\n readonly expired: AbortSignal | undefined;\n /** Set when the result came from another call's run. */\n shared: boolean;\n /** Set when this call started the run, and so flushes it. */\n run: Run | undefined;\n /** The shared run this call takes its result from, started or joined; unset when it runs unshared. */\n source: Run | undefined;\n}\n\n/** The handler's result in the shape its output sends: a projection's rows, or what a schema declares. */\nfunction shaped(target: RegisteredMethod, returned: unknown): unknown {\n const { projection, schemaOutput } = target.method;\n if (projection !== undefined) {\n return projectOutput(projection, returned);\n }\n return schemaOutput === undefined ? returned : schemaOutput.pick(returned);\n}\n\n/**\n * Step 8: projects a projection output's rows (RFC 0003 section 6: the\n * projection's keys only, dates as ISO strings) or reduces a schema output\n * to what its schema declares (`schemaOutput.ts`), on every transport and\n * whatever `outputValidation` is; checks the result against the method's\n * output, and freezes shared results.\n */\nasync function accept(\n settings: PipelineSettings,\n target: RegisteredMethod,\n returned: unknown,\n): Promise<Outcome> {\n const { service, method } = target;\n const value = shaped(target, returned);\n if (settings.warnings.enabled) {\n warnTieredReply(target, value, settings.warnings);\n }\n if (settings.outputValidation) {\n const issues = await outputIssues(method.output, value);\n if (issues !== undefined) {\n const error = new QuickdrawError(\n \"INTERNAL\",\n `${service.name}.${method.name} returned a value that does not match its contract output`,\n { issues },\n );\n return { ok: false, error };\n }\n }\n const freeze = method.share !== undefined && settings.freezeSharedResults;\n return { ok: true, value: freeze ? deepFreeze(value) : value };\n}\n\n/** Steps 6 to 8 for one authorized call with its parsed input. */\nexport function execute(\n settings: PipelineSettings,\n shares: ShareTable<Run>,\n target: RegisteredMethod,\n call: ExecuteCall,\n input: unknown,\n ctx: AnyContext,\n): Promise<Outcome> {\n const { service, method } = target;\n const key =\n method.share === undefined\n ? undefined\n : shareKey(\n service.name,\n method.name,\n method.share === \"all\"\n ? \"*\"\n : { principal: call.principal, transport: call.transport, mcp: ctx.mcp },\n input,\n );\n const existing = key === undefined ? undefined : shares.get(key);\n if (existing !== undefined && existing.settled?.ok !== false) {\n call.shared = true;\n call.source = existing;\n return existing.join(call.signal);\n }\n const unit = settings.unitOfWork.begin({\n service: service.name,\n method: method.name,\n kind: method.kind,\n requestId: call.requestId,\n transport: call.transport,\n sink: settings.flushSink,\n warnings: settings.warnings,\n });\n const run = startRun({\n // The pipeline starts every call's time limit at admission, before this.\n timeLimit: call.expired ?? NEVER_ABORTED,\n unit,\n invoke: (signal) => method.handler({ input, ctx: withSignal(ctx, signal), db: settings.db }),\n // A kit's handler is framework code: the development checks of statements are for the app's.\n quiet: settings.warnings.enabled && isKitHandler(method.handler),\n accept: (value) => accept(settings, target, value),\n });\n call.run = run;\n if (key !== undefined) {\n shares.add(key, run, method.ttlMs);\n call.source = run;\n }\n return run.join(call.signal);\n}\n","// The \"not modified\" seam (RFC 0003 section 9, step 5). Before a query runs,\n// the dispatcher asks for the current version of its result. When the caller\n// sent that same version as `v`, the call answers `{ ok: true, nm: true, v }`\n// without running the handler; otherwise the reply carries the version so the\n// caller can send it next time.\n//\n// A query that declares `version(input, ctx)` answers for itself. For every\n// other query the dispatcher asks its `versions` option, which the entity\n// subscriptions card implements for queries whose output is one projection\n// row (from the service's `versionColumn` or the in-process change log).\n\nimport type { Version } from \"../../protocol/envelope\";\nimport type { AnyContext } from \"../context\";\nimport type { AnyService, ServiceMethod } from \"../service\";\nimport type { MaybePromise } from \"../types\";\n\n/** The query a version is asked for. */\nexport interface VersionRequest {\n readonly service: AnyService;\n readonly method: ServiceMethod;\n /** The input after its schema ran. */\n readonly input: unknown;\n /** The call's context; the caller has already been authorized. */\n readonly ctx: AnyContext;\n}\n\n/**\n * Answers the current version of a query's result, or `undefined` when it\n * does not know one (the query then always runs). Called after access was\n * checked, for queries that declare no `version` of their own. It must take\n * the version before any row is read, so a reply is never older than the\n * version it claims.\n */\nexport interface VersionSource {\n versionOf(request: VersionRequest): MaybePromise<Version | undefined>;\n /**\n * Whether the version `versionOf` answered describes `result`, the\n * caller's result of the query once it ran: the reply carries the version\n * only when it does, so a caller never holds a version of something else.\n * Absent: always.\n */\n describes?(request: VersionRequest, result: unknown): boolean;\n}\n\n/** True when `value` can be a call's version: a finite number or a string. */\nexport function isVersion(value: unknown): value is Version {\n return typeof value === \"string\" || (typeof value === \"number\" && Number.isFinite(value));\n}\n","// The pipeline stages before the handler runs (RFC 0003 section 9, steps 1\n// to 5): look the method up, take a query slot, start the call's time limit,\n// build the context, and ask for the result's current version.\n\nimport type { Version } from \"../../protocol/envelope\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { createContext, NEVER_ABORTED, type AnyContext, type ContextFields } from \"../context\";\nimport type { RegisteredMethod, Registry } from \"../registry\";\nimport { runtimeOf } from \"../service\";\nimport type { QuerySlot, ConcurrencyLimiter } from \"./concurrency\";\nimport { abortError, timeoutError } from \"./errors\";\nimport { isVersion } from \"./notModified\";\nimport type { DispatchRequest } from \"./request\";\nimport type { PipelineSettings } from \"./settings\";\n\n/** Step 1: the method a call names, or `NOT_FOUND`. */\nexport function lookup(registry: Registry, request: DispatchRequest): RegisteredMethod {\n const found = registry.find(request.service, request.method);\n if (found !== undefined) {\n return found;\n }\n const message = registry.services.has(request.service)\n ? `Unknown method \"${request.method}\" on service \"${request.service}\"`\n : `Unknown service \"${request.service}\"`;\n throw new QuickdrawError(\"NOT_FOUND\", message);\n}\n\n/**\n * Step 2: a query slot on the call's connection. Mutations and calls without\n * a connection are not capped, so they get no slot.\n */\nexport function admit(\n limiter: ConcurrencyLimiter,\n request: DispatchRequest,\n target: RegisteredMethod,\n signal: AbortSignal | undefined,\n): Promise<QuerySlot | undefined> {\n if (target.method.kind !== \"query\" || request.connectionId === undefined) {\n return Promise.resolve(undefined);\n }\n return limiter.acquire(request.connectionId, signal);\n}\n\n/** A call's time limit, from {@link startTimeLimit}. */\nexport interface TimeLimit {\n /** Aborts when the caller cancels (a query) or the time limit passes. */\n readonly signal: AbortSignal;\n /** Aborts when the time limit passes, with the call's `TIMEOUT` error as its reason. */\n readonly expired: AbortSignal;\n /** Stops the clock. */\n stop(): void;\n}\n\n/**\n * Starts a call's time limit (RFC 0003 section 9, step 7) once the call is\n * admitted, so it covers every stage after step 2: validation, the access\n * check, `version()`, the handler and the output check. Time spent waiting\n * for a query slot does not count. `cancel` is the caller's own signal,\n * which only a query has.\n */\nexport function startTimeLimit(timeoutMs: number, cancel: AbortSignal | undefined): TimeLimit {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(timeoutError(timeoutMs)), timeoutMs);\n return {\n signal: cancel === undefined ? controller.signal : AbortSignal.any([cancel, controller.signal]),\n expired: controller.signal,\n stop: () => clearTimeout(timer),\n };\n}\n\n/**\n * Waits for `work`, or rejects as soon as `signal` aborts: with `TIMEOUT`\n * when the call's time limit aborted it, and `CANCELLED` otherwise. `work`\n * keeps running; its late result is ignored.\n */\nexport function untilStopped<T>(work: PromiseLike<T>, signal: AbortSignal | undefined): Promise<T> {\n if (signal === undefined) {\n return Promise.resolve(work);\n }\n return new Promise<T>((resolve, reject) => {\n const onAbort = (): void => reject(abortError(signal));\n if (signal.aborted) {\n onAbort();\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n work.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(error);\n },\n );\n });\n}\n\n/**\n * The context of one call: the framework's fields, then the app's from\n * `initQuickdraw({ context })`. `dispatch` is the dispatcher's own, which\n * `ctx.services` calls through.\n */\nexport function contextFor(\n settings: PipelineSettings,\n request: DispatchRequest,\n requestId: string,\n target: RegisteredMethod,\n signal: AbortSignal | undefined,\n dispatch: NonNullable<ContextFields[\"dispatch\"]>,\n): AnyContext {\n const log = settings.logger.child({\n service: target.service.name,\n method: target.method.name,\n requestId,\n });\n const { realtime } = settings.live;\n const fields = {\n principal: request.principal,\n signal: signal ?? NEVER_ABORTED,\n log,\n requestId,\n transport: request.transport,\n ...(request.transport === \"socket\" && request.connectionId !== undefined\n ? { socketId: request.connectionId }\n : {}),\n ...(request.mcp === undefined ? {} : { mcp: request.mcp }),\n touch: settings.touch,\n rooms: realtime.roomsFor(request.transport, request.connectionId, target.method.share),\n presence: realtime.presence,\n // `ctx.services` calls the app's services as this principal through this\n // dispatcher; their units of work join this call's, so their writes flush with it.\n dispatch,\n kit: {\n service: target.service,\n access: settings.policies,\n storage: settings.storage,\n occupancy: settings.live.occupancy,\n claimRevision: settings.live.revisions.claim,\n runDetached: settings.runDetached,\n },\n };\n return createContext(fields, runtimeOf(target.service)?.extendContext);\n}\n\n/**\n * Step 5: the current version of a query's result, from the method's own\n * `version`, or else the dispatcher's `versions` source. Mutations have none.\n */\nexport async function currentVersion(\n settings: PipelineSettings,\n target: RegisteredMethod,\n input: unknown,\n ctx: AnyContext,\n): Promise<Version | undefined> {\n const { service, method } = target;\n if (method.kind !== \"query\") {\n return undefined;\n }\n const version =\n method.version === undefined\n ? await settings.versions?.versionOf({ service, method, input, ctx })\n : await method.version(input, ctx);\n return isVersion(version) ? version : undefined;\n}\n\n/**\n * The version a query's reply carries once it ran: the one step 5 took,\n * when it describes the caller's result. A method's own `version` always\n * does; the dispatcher's `versions` source is asked (`describes`).\n */\nexport function versionOfResult(\n settings: PipelineSettings,\n target: RegisteredMethod,\n call: {\n readonly input: unknown;\n readonly ctx: AnyContext;\n readonly version: Version | undefined;\n },\n result: unknown,\n): Version | undefined {\n const { service, method } = target;\n const { input, ctx, version } = call;\n if (version === undefined || method.version !== undefined) {\n return version;\n }\n const request = { service, method, input, ctx };\n return settings.versions?.describes?.(request, result) === false ? undefined : version;\n}\n","// The method pipeline: the one path every call takes, whatever transport it\n// arrived on (RFC 0003 section 9). It replaces 4.1's per-method socket\n// listener (4.1 `src/server/ServiceRegistry.ts:271-407`):\n//\n// 1. look up the method NOT_FOUND\n// 2. take a query slot on the connection RATE_LIMITED, CANCELLED\n// 3. validate the input VALIDATION\n// 4. authorize UNAUTHENTICATED, FORBIDDEN\n// 5. answer \"not modified\" when the caller's version is current\n// 6. join an identical shared run in flight\n// 7. run the handler in a unit of work TIMEOUT, CANCELLED\n// 8. project and check the output INTERNAL\n// then strip field tiers for this caller (one copy, encoded\n// once, per group of a shared run's callers who see the same fields)\n// 9. respond, flush, and emit one completion record\n//\n// The time limit starts once the call is admitted (after step 2) and covers\n// steps 3 to 8; a query's cancel signal does too. Either answers the caller\n// at once, and work already started (a slow access check, a handler that\n// ignores its signal) runs on unanswered. A query keeps its slot until that\n// work has settled, so a connection never runs more of it than its cap.\n\nimport { createConcurrencyLimiter, type ConcurrencyLimiter, type QuerySlot } from \"./concurrency\";\nimport { throwIfCancelled, toQuickdrawError } from \"./errors\";\nimport { execute, forCaller, type ExecuteCall } from \"./execute\";\nimport { describeError, type CallOutcome, type CallRecord } from \"./metrics\";\nimport type { DispatchRequest, DispatchResult, SharedData } from \"./request\";\nimport type { Run } from \"./run\";\nimport type { PipelineSettings } from \"./settings\";\nimport { createShareTable, type ShareTable } from \"./share\";\nimport {\n admit,\n contextFor,\n currentVersion,\n lookup,\n startTimeLimit,\n untilStopped,\n versionOfResult,\n type TimeLimit,\n} from \"./stages\";\nimport { parseInput } from \"./validation\";\n\nexport type { DispatchRequest, DispatchResult };\n\n/**\n * Runs one call through the pipeline. Resolves once the reply was sent,\n * flushed and recorded. It never rejects, except in a test app made with\n * `strictWarnings`, where an oversized reply, or a call one connection\n * repeats in a loop (`../devWarnings.ts`), rejects with its `DevWarningError` once it\n * was sent and recorded.\n */\nexport type Dispatch = (request: DispatchRequest) => Promise<DispatchResult>;\n\ninterface Pipeline {\n readonly settings: PipelineSettings;\n readonly limiter: ConcurrencyLimiter;\n readonly shares: ShareTable<Run>;\n /** The pipeline's own dispatch function, which `ctx.services` calls through. */\n dispatch: Dispatch;\n}\n\ninterface CallState extends ExecuteCall {\n readonly request: DispatchRequest;\n signal: AbortSignal | undefined;\n expired: AbortSignal | undefined;\n kind: CallRecord[\"kind\"];\n queueMs: number;\n /** The work of the stage the call is in, or last finished. It may outlive the call's answer. */\n stageWork: Promise<unknown> | undefined;\n /** The shared copy the call's data is, handed to `respond` with its result. */\n sharedData: SharedData | undefined;\n}\n\n/**\n * One of steps 3 to 5: waits for `work` until the call's signal stops it\n * (`CANCELLED` or `TIMEOUT`), and keeps it as the call's stage work.\n */\nfunction stage<T>(call: CallState, work: T | PromiseLike<T>): Promise<T> {\n const running = Promise.resolve(work);\n call.stageWork = running;\n return untilStopped(running, call.signal);\n}\n\n/** Steps 3 to 8, for a call that has its method, its time limit and, for a query, its slot. */\nasync function proceed(\n pipeline: Pipeline,\n call: CallState,\n target: ReturnType<typeof lookup>,\n): Promise<DispatchResult> {\n const { settings } = pipeline;\n const { request } = call;\n const label = `${target.service.name}.${target.method.name}`;\n const input = await stage(call, parseInput(target.method.input, request.input, label));\n const ctx = contextFor(settings, request, call.requestId, target, call.signal, pipeline.dispatch);\n const access = {\n service: target.service,\n method: target.method.name,\n principal: request.principal,\n input,\n ctx,\n };\n await stage(call, settings.access.authorize(target.method.access, access));\n const version = await stage(call, currentVersion(settings, target, input, ctx));\n if (version !== undefined && request.v === version) {\n return { ok: true, notModified: true, version };\n }\n const outcome = await execute(settings, pipeline.shares, target, call, input, ctx);\n if (!outcome.ok) {\n return { ok: false, error: outcome.error };\n }\n const { data, shared } = await stage(call, forCaller(settings, target, call, outcome.value));\n call.sharedData = shared;\n const reported = versionOfResult(settings, target, { input, ctx, version }, data);\n return reported === undefined ? { ok: true, data } : { ok: true, data, version: reported };\n}\n\n/**\n * Frees what a call held. The slot goes back to its connection once nothing\n * the call started is still running: the stage it was answered in the middle\n * of, or the handler run it started. The clock stops now, or, for a call that\n * started a run, once that run settles: the run ends at this call's time\n * limit, whichever of its callers is still waiting.\n */\nfunction release(call: CallState, slot: QuerySlot | undefined, limit: TimeLimit | undefined): void {\n const { run } = call;\n if (run === undefined) {\n limit?.stop();\n } else if (limit !== undefined) {\n void run.outcome.then(limit.stop);\n }\n if (slot === undefined) {\n return;\n }\n // The handler run this call started, and the stage it is in or last\n // finished (for a call that started a run, the per-caller strip after it).\n const running = [run?.handlerDone, call.stageWork].filter(\n (work): work is Promise<unknown> => work !== undefined,\n );\n if (running.length === 0) {\n slot.release();\n return;\n }\n void Promise.allSettled(running).then(slot.release);\n}\n\n/** Steps 1 to 8. Every failure becomes a result; the slot is freed however the call ends. */\nasync function settle(pipeline: Pipeline, call: CallState): Promise<DispatchResult> {\n let slot: QuerySlot | undefined;\n let limit: TimeLimit | undefined;\n try {\n const target = lookup(pipeline.settings.registry, call.request);\n call.kind = target.method.kind;\n // Only a query can be cancelled.\n const cancel = target.method.kind === \"query\" ? call.request.signal : undefined;\n throwIfCancelled(cancel);\n slot = await admit(pipeline.limiter, call.request, target, cancel);\n call.queueMs = slot?.queueMs ?? 0;\n limit = startTimeLimit(\n target.method.timeoutMs ?? pipeline.settings.limits.callTimeoutMs,\n cancel,\n );\n call.signal = limit.signal;\n call.expired = limit.expired;\n return await proceed(pipeline, call, target);\n } catch (error) {\n return { ok: false, error: toQuickdrawError(error) };\n } finally {\n release(call, slot, limit);\n }\n}\n\n/**\n * Step 9a: hands the result to the transport, which reports the reply's\n * size, with the shared copy its data is when it came from a shared run.\n */\nfunction respond(settings: PipelineSettings, call: CallState, result: DispatchResult): number {\n const { respond: send } = call.request;\n if (send === undefined) {\n return 0;\n }\n const { sharedData } = call;\n const shared =\n result.ok && result.notModified !== true && sharedData?.data === result.data\n ? sharedData\n : undefined;\n try {\n const bytes = shared === undefined ? send(result) : send(result, shared);\n return typeof bytes === \"number\" && Number.isFinite(bytes) && bytes > 0 ? bytes : 0;\n } catch (error) {\n settings.logger.error(\"A transport failed to send a reply\", {\n category: \"quickdraw.call\",\n requestId: call.requestId,\n error: describeError(error),\n });\n return 0;\n }\n}\n\n/**\n * Step 9b: flushes the run this call started, once its handler has settled.\n * A handler still running after `TIMEOUT` or `CANCELLED` is flushed when it\n * settles, without holding up this call.\n */\nasync function flushRun(settings: PipelineSettings, call: CallState): Promise<void> {\n const { run } = call;\n if (run === undefined) {\n return;\n }\n const flush = async (): Promise<void> => {\n try {\n await run.unit.flush();\n } catch (error) {\n settings.logger.error(\"Flushing a call's writes failed; its reply was already sent\", {\n category: \"quickdraw.call\",\n requestId: call.requestId,\n error: describeError(error),\n });\n }\n };\n if (run.handlerSettled) {\n await flush();\n return;\n }\n void run.handlerDone.then(flush);\n}\n\nfunction outcomeOf(result: DispatchResult): CallOutcome {\n if (!result.ok) {\n return result.error.code;\n }\n return result.notModified === true ? \"not-modified\" : \"ok\";\n}\n\nfunction recordOf(\n call: CallState,\n result: DispatchResult,\n durationMs: number,\n bytes: number,\n): CallRecord {\n const { request } = call;\n return {\n service: request.service,\n method: request.method,\n kind: call.kind,\n transport: request.transport,\n requestId: call.requestId,\n outcome: outcomeOf(result),\n durationMs,\n queueMs: call.queueMs,\n bytes,\n shared: call.shared,\n sqlStatements: call.run?.unit.sqlStatements,\n };\n}\n\n/** Builds the pipeline's `Dispatch` function over the resolved settings. */\nexport function createPipeline(settings: PipelineSettings): Dispatch {\n const pipeline: Pipeline = {\n settings,\n limiter: createConcurrencyLimiter({\n maxInFlight: settings.limits.maxInFlightQueries,\n maxQueued: settings.limits.maxQueuedQueries,\n retryAfterMs: settings.limits.retryAfterMs,\n }),\n shares: createShareTable<Run>(),\n dispatch: () => Promise.reject(new Error(\"the pipeline is being created\")),\n };\n pipeline.dispatch = async (request) => {\n const startedAt = performance.now();\n const call: CallState = {\n request,\n requestId: request.requestId ?? crypto.randomUUID(),\n transport: request.transport,\n principal: request.principal,\n signal: undefined,\n expired: undefined,\n kind: undefined,\n queueMs: 0,\n stageWork: undefined,\n shared: false,\n run: undefined,\n source: undefined,\n sharedData: undefined,\n };\n const result = await settle(pipeline, call);\n const durationMs = performance.now() - startedAt;\n const bytes = respond(settings, call, result);\n await flushRun(settings, call);\n const record = recordOf(call, result, durationMs, bytes);\n settings.record(record, {\n error: result.ok ? undefined : result.error,\n userId: request.principal?.userId,\n });\n settings.loops.call(request, record.outcome);\n return result;\n };\n return pipeline.dispatch;\n}\n","// The services a dispatcher serves, by name. 4.1's `ServiceRegistry` also\n// wired one Socket.IO listener per method per socket\n// (4.1 `src/server/ServiceRegistry.ts:118-136`); in 5.0 the registry only\n// resolves names, and the transports keep a fixed listener set.\n\nimport { runtimeOf, type AnyService, type ServiceMethod } from \"./service\";\n\n/** A method found by name, with the service it belongs to. */\nexport interface RegisteredMethod {\n readonly service: AnyService;\n readonly method: ServiceMethod;\n}\n\n/** The services of one dispatcher, by service name. */\nexport interface Registry {\n /** Every service, by name. */\n readonly services: ReadonlyMap<string, AnyService>;\n /** The method `method` of service `service`, or `undefined` when either is unknown. */\n find(service: string, method: string): RegisteredMethod | undefined;\n}\n\n/**\n * Indexes services by name. Throws when two services share a name, or when\n * a value is not a service `defineService` returned.\n */\nexport function createRegistry(services: readonly AnyService[]): Registry {\n if (!Array.isArray(services)) {\n throw new TypeError(\"createRegistry: services must be an array of services\");\n }\n const byName = new Map<string, AnyService>();\n for (const service of services) {\n if (runtimeOf(service) === undefined) {\n throw new TypeError(\"createRegistry: every service must come from qd.defineService\");\n }\n if (byName.has(service.name)) {\n throw new TypeError(`createRegistry: two services are named \"${service.name}\"`);\n }\n byName.set(service.name, service);\n }\n return Object.freeze({\n services: byName,\n find(serviceName: string, methodName: string): RegisteredMethod | undefined {\n const service = byName.get(serviceName);\n if (service === undefined || !Object.hasOwn(service.methods, methodName)) {\n return undefined;\n }\n const method = service.methods[methodName];\n return method === undefined ? undefined : { service, method };\n },\n });\n}\n","// The dispatcher: a registry of services plus the method pipeline, with one\n// `call(request)` for every transport and a typed in-process caller.\n// `qd.createServer` builds one; tests, jobs and the MCP bridge can build one\n// directly.\n\nimport type { AnyContract } from \"../contract/defineContract\";\nimport type { DispatcherAccess } from \"./access/api\";\nimport { callerGrantsOf, createCaller, type Caller } from \"./caller\";\nimport type { RunContext, RunOptions } from \"./context\";\nimport { registerLive, type Presence, type ServerRooms, type StreamHandle } from \"./emit/live\";\nimport { createPipeline, type DispatchRequest, type DispatchResult } from \"./pipeline/pipeline\";\nimport {\n resolveSettings,\n type DispatcherLimits,\n type PipelineOptions,\n type PipelineSettings,\n} from \"./pipeline/settings\";\nimport { createRegistry, type Registry } from \"./registry\";\nimport type { AnyService, Service } from \"./service\";\nimport type { DbOf, Principal, PrincipalOf } from \"./types\";\n\nexport type { Presence, ServerRooms, Service, StreamHandle };\n\ntype TypesOf<S extends readonly AnyService[]> = NonNullable<S[number][\"~types\"]>;\n\n/** The database client the services of `S` were declared with. */\nexport type DbOfServices<S extends readonly AnyService[]> = [S[number]] extends [never]\n ? unknown\n : DbOf<TypesOf<S>>;\n\n/** The principal type the services of `S` were declared with. */\nexport type PrincipalOfServices<S extends readonly AnyService[]> = [S[number]] extends [never]\n ? Principal\n : PrincipalOf<TypesOf<S>>;\n\n/** The contracts the services of `S` were defined from. */\nexport type ContractOfServices<S extends readonly AnyService[]> = [S[number]] extends [never]\n ? AnyContract\n : S[number][\"contract\"];\n\n/**\n * Options of {@link createDispatcher}: the services and the database client\n * handlers receive, plus the pipeline's seams and limits. `db` may be left\n * out only when the services declared no database type.\n */\nexport type DispatcherOptions<S extends readonly AnyService[]> = PipelineOptions & {\n /** The services to serve. Two services with one name are an error. */\n readonly services: S;\n} & (unknown extends DbOfServices<S>\n ? { readonly db?: DbOfServices<S> }\n : { readonly db: DbOfServices<S> });\n\n/** `dispatcher.collections` and `qd.collections`: the services' collections (RFC 0003 section 7). */\nexport interface DispatcherCollections {\n /**\n * Sends one scope of a collection a `reset`, so its clients load it again:\n * for a change tracked writes cannot describe, such as a raw SQL write the\n * app did not `ctx.touch`. Throws a `TypeError` for a collection this\n * dispatcher does not serve.\n *\n * @example\n * qd.collections.reset(task, \"byProject\", projectId);\n */\n reset<C extends AnyContract>(\n contract: C,\n collection: keyof C[\"collections\"] & string,\n scope: string,\n ): void;\n}\n\n/** A registry of services and the method pipeline that serves them. */\nexport interface Dispatcher<S extends readonly AnyService[] = readonly AnyService[]> {\n /**\n * Runs one call through the pipeline. Resolves once the result was handed\n * to `request.respond`, the run flushed and the completion record emitted.\n * Never rejects: a failure is a result with `ok: false`.\n */\n call(request: DispatchRequest): Promise<DispatchResult>;\n /**\n * A typed in-process caller acting as `principal`, `null` for anonymous:\n * `dispatcher.caller(user).taskService.rename(input)`. Calls go through the\n * whole pipeline with transport `\"internal\"` and no connection, so they are\n * not capped. Through a server's dispatcher, a principal that carries no\n * `serviceAccess` gets the grants `auth.loadServiceAccess` loads, once per\n * caller and again after the server applied new grants, as a socket's\n * handshake does; one that carries grants keeps exactly those.\n */\n caller(principal: PrincipalOfServices<S> | null): Caller<ContractOfServices<S>>;\n /**\n * Runs `fn` inside a unit of work, as a method's handler runs (RFC 0003\n * section 5.1): the tracked writes it makes flush to the dispatcher's\n * sinks once it settles, whether it resolved or threw, and before `run`\n * returns. Inside an open unit of work or transaction, `fn` joins it\n * instead, unless `detached` (see {@link RunOptions}) gives it a unit of\n * its own. For jobs, scripts and webhooks that write outside a method, and\n * a handler's background work. `fn` gets a {@link RunContext}: `ctx.touch`\n * records the rows a raw SQL write changed.\n */\n run<T>(fn: (ctx: RunContext) => T | PromiseLike<T>, options?: RunOptions): Promise<T>;\n /**\n * The services' access policies (RFC 0003 section 4): a principal's levels\n * on rows, list filters, and access-change events.\n */\n readonly access: DispatcherAccess;\n /** The services' collections: a manual `reset`. Deltas themselves come from tracked writes. */\n readonly collections: DispatcherCollections;\n /**\n * Who is online, when they were last seen, and who is in a room (RFC 0003\n * section 12.5), from the sockets of the server `createServer` attached;\n * without a server nobody is online.\n */\n readonly presence: Presence;\n /**\n * App rooms from code that is not a handler (RFC 0003 section 12.5): typed\n * room events (`emit`, `emitToUser`) and `leave(room, { userId })`, on\n * every node of the attached server; without a server nothing is sent.\n */\n readonly rooms: ServerRooms;\n /**\n * The handle of one of the services' streams (RFC 0003 section 12.5), whose\n * `push` appends an item: `dispatcher.stream(task, \"logs\").push(taskId,\n * line)`. Throws a `TypeError` for a stream the dispatcher does not serve.\n */\n stream<C extends AnyContract, K extends keyof C[\"streams\"] & string>(\n contract: C,\n name: K,\n ): StreamHandle<C, K>;\n readonly registry: Registry;\n /** The resolved limits, for a server to announce in `qd:hello`. */\n readonly limits: DispatcherLimits;\n}\n\nconst ACCESS_SINKS = new WeakMap<object, readonly PipelineSettings[\"flushSink\"][]>();\n\n/**\n * A copy of `options` whose dispatcher runs `sinks` right after its access\n * sink, before any frame of a flush is sent: `createServer`'s grants\n * refresh, so a flush that lowers a user's grants revokes what they held\n * before that flush's frames reach them.\n */\nexport function withAccessSinks<O extends object>(\n options: O,\n sinks: readonly PipelineSettings[\"flushSink\"][],\n): O {\n const copy = { ...options };\n ACCESS_SINKS.set(copy, sinks);\n return copy;\n}\n\n/** `run`'s `detached` option, checked. */\nfunction detachedOf(options: RunOptions | undefined): boolean {\n if (options === undefined) {\n return false;\n }\n if (typeof options !== \"object\" || options === null) {\n throw new TypeError(\"run: options must be an object, { detached?: boolean }\");\n }\n const { detached } = options;\n if (detached !== undefined && typeof detached !== \"boolean\") {\n throw new TypeError(\"run: detached must be true or false\");\n }\n return detached === true;\n}\n\n/** `dispatcher.run`: a unit of work around `fn`, flushed once `fn` settles. */\nexport async function runInUnit<T>(\n settings: PipelineSettings,\n fn: (ctx: RunContext) => T | PromiseLike<T>,\n options?: RunOptions,\n): Promise<T> {\n if (typeof fn !== \"function\") {\n throw new TypeError(\"run: pass the function to run inside a unit of work\");\n }\n const detached = detachedOf(options);\n const requestId = crypto.randomUUID();\n const unit = settings.unitOfWork.begin({\n requestId,\n transport: \"internal\",\n sink: settings.flushSink,\n ...(detached ? { detached } : {}),\n });\n const ctx: RunContext = Object.freeze({\n touch: settings.touch,\n log: settings.logger.child({ requestId }),\n principal: null,\n });\n try {\n return await unit.run(() => fn(ctx));\n } finally {\n try {\n await unit.flush();\n } catch (error) {\n settings.logger.error(\"Flushing a run's writes failed\", {\n category: \"quickdraw.flush\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n}\n\n/**\n * Creates a dispatcher for `services`.\n *\n * @example\n * const dispatcher = createDispatcher({ services: [taskService], db: prisma });\n * await dispatcher.caller(user).taskService.rename({ id, title });\n */\nexport function createDispatcher<const S extends readonly AnyService[]>(\n options: DispatcherOptions<S>,\n): Dispatcher<S> {\n if (typeof options !== \"object\" || options === null) {\n throw new TypeError(\"createDispatcher: options must be an object with services and db\");\n }\n const registry = createRegistry(options.services);\n const settings = resolveSettings(options, registry, options.db, ACCESS_SINKS.get(options));\n // Writes made outside any unit of work flush to this dispatcher's sinks,\n // and the tracker's development warnings go out as this dispatcher's,\n // until a server's `close()` detaches it.\n const detach = settings.unitOfWork.attach?.(\n settings.flushSink,\n settings.logger,\n settings.warnings,\n );\n const call = createPipeline(settings);\n const { levelsFor, accessWhere, onAccessChanged } = settings.policies;\n const dispatcher: Dispatcher<S> = Object.freeze({\n call,\n caller: (principal: PrincipalOfServices<S> | null) =>\n createCaller(() => call, principal, {\n grants: () => callerGrantsOf(dispatcher),\n }) as Caller<ContractOfServices<S>>,\n run: <T>(fn: (ctx: RunContext) => T | PromiseLike<T>, runOptions?: RunOptions) =>\n runInUnit(settings, fn, runOptions),\n access: Object.freeze({ levelsFor, accessWhere, onAccessChanged }),\n collections: Object.freeze({\n reset: (contract: AnyContract, collection: string, scope: string) => {\n settings.live.resetCollection(contract, collection, scope);\n },\n }),\n presence: settings.live.realtime.presence,\n rooms: settings.live.realtime.rooms,\n stream: <C extends AnyContract, K extends keyof C[\"streams\"] & string>(contract: C, name: K) =>\n settings.live.realtime.stream(contract, name) as unknown as StreamHandle<C, K>,\n registry,\n limits: settings.limits,\n });\n // `createServer` attaches its Socket.IO server to the dispatcher's live data.\n registerLive(dispatcher, settings.live);\n LOOPS.set(dispatcher, settings.loops);\n if (typeof detach === \"function\") {\n DETACHES.set(dispatcher, detach);\n }\n return dispatcher;\n}\n\nconst DETACHES = new WeakMap<object, () => void>();\n\nconst LOOPS = new WeakMap<object, PipelineSettings[\"loops\"]>();\n\n/**\n * The loop watch of a dispatcher `createDispatcher` returned: `createServer`\n * counts its socket rate limiter's refusals there too (`devWarnings.ts`).\n */\nexport function loopsOf(dispatcher: object): PipelineSettings[\"loops\"] | undefined {\n return LOOPS.get(dispatcher);\n}\n\n/**\n * Detaches `dispatcher` from its tracked database client: ambient writes\n * and the warnings outside calls go back to the dispatcher attached before\n * it (or nowhere). A server's `close()` calls it once the server stopped.\n */\nexport function detachDispatcher(dispatcher: object): void {\n DETACHES.get(dispatcher)?.();\n}\n","// The event-loop stall watchdog (`createServer({ stallWatchdog })`). A server\n// whose event loop is blocked (a long synchronous loop, a huge\n// `JSON.stringify`, synchronous crypto) answers nobody until it is free\n// again, and nothing in a call's own record says so. The watchdog samples the\n// loop's delay with Node's histogram (`perf_hooks.monitorEventLoopDelay`) at\n// a 20 ms resolution, reads it every 10 s, and logs a warning when the 99th\n// percentile delay of that window is above the threshold (200 ms), or when\n// its longest delay is above `maxMs` (1 s), naming the window's slowest\n// methods from the calls' completion records.\n//\n// Cost: the histogram is one libuv timer firing every 20 ms, and the read is\n// one timer every 10 s; recording a call is one map update. A watchdog that\n// samples much more finely becomes a load of its own, which is why the\n// resolution is fixed. On an idle process it costs about 5 ms of CPU per\n// 10 s, 0.05% of one CPU (`scripts/stall-watchdog-overhead.mjs`).\n//\n// A percentile needs repeated stalls to move: at the default window one\n// 300 ms block is one sample of about 500, and the 99th percentile stays\n// low; that warning is about a loop that keeps stalling, not one slow tick.\n// One block long enough to be felt by every caller at once, 1 s by default,\n// warns through the window's maximum instead.\n\nimport { monitorEventLoopDelay, type ELDHistogram } from \"node:perf_hooks\";\nimport type { Logger } from \"../../contract/logger\";\nimport type { CallRecord } from \"../pipeline/metrics\";\n\n/** The histogram's sampling resolution, in milliseconds. Fixed: finer sampling costs CPU. */\nexport const STALL_RESOLUTION_MS = 20;\n\n/** The default threshold for the window's 99th percentile delay, in milliseconds. */\nexport const DEFAULT_STALL_THRESHOLD_MS = 200;\n\n/** The default threshold for the window's single longest delay, in milliseconds. */\nexport const DEFAULT_STALL_MAX_MS = 1_000;\n\n/** The default window: how often the delay is read, in milliseconds. */\nexport const DEFAULT_STALL_INTERVAL_MS = 10_000;\n\n/** The shortest window the watchdog accepts, in milliseconds. */\nexport const MIN_STALL_INTERVAL_MS = 1_000;\n\nconst DEFAULT_SLOWEST = 5;\n\nconst MAX_INTERVAL_MS = 2_147_483_647;\n\n/** Options of `createServer({ stallWatchdog })`. */\nexport interface StallWatchdogOptions {\n /** Warn when the window's 99th percentile event-loop delay is above this, in milliseconds. Default 200. */\n readonly thresholdMs?: number;\n /** Warn when the window's single longest event-loop delay is above this, in milliseconds. Default 1,000. */\n readonly maxMs?: number;\n /** How often the delay is read and a new window starts, in milliseconds; at least 1,000. Default 10,000. */\n readonly intervalMs?: number;\n /** How many of the window's slowest methods a warning names. Default 5. */\n readonly slowest?: number;\n}\n\n/** One method among a window's slowest, by its slowest call. */\nexport interface SlowMethod {\n /** `\"taskService.list\"`. */\n readonly method: string;\n readonly calls: number;\n readonly maxMs: number;\n readonly meanMs: number;\n}\n\n/** What one read of the window found. */\nexport interface StallReport {\n /** How long the window ran, in milliseconds. */\n readonly windowMs: number;\n /** The event loop's delays over the window, in milliseconds; 0 when nothing was sampled. */\n readonly p50Ms: number;\n readonly p99Ms: number;\n readonly maxMs: number;\n readonly meanMs: number;\n /** True when `p99Ms` was above the threshold or `maxMs` above its limit, and so a warning was logged. */\n readonly stalled: boolean;\n /** The window's slowest methods, slowest first. */\n readonly slowest: readonly SlowMethod[];\n}\n\n/** A running watchdog. */\nexport interface StallWatchdog {\n /** Counts one call of the window: give it every completion record (the dispatcher's `onCall`). */\n observe(record: CallRecord): void;\n /** Reads the window, starts a new one, and logs a warning when the window stalled. Its timer calls it. */\n check(): StallReport;\n /** Stops sampling and reading. */\n stop(): void;\n}\n\ninterface MethodWindow {\n calls: number;\n maxMs: number;\n totalMs: number;\n}\n\ninterface Settings {\n readonly thresholdMs: number;\n readonly maxMs: number;\n readonly intervalMs: number;\n readonly slowest: number;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`createServer: stallWatchdog.${message}`);\n}\n\n/** The watchdog's settings from `createServer`'s option; `undefined` when it is off. */\nexport function stallWatchdogSettings(\n option: boolean | StallWatchdogOptions | undefined,\n): Settings | undefined {\n if (option === undefined || option === false) {\n return undefined;\n }\n const given: StallWatchdogOptions = option === true ? {} : option;\n if (typeof given !== \"object\" || given === null) {\n throw new TypeError(\"createServer: stallWatchdog must be true, false or its options\");\n }\n const thresholdMs = given.thresholdMs ?? DEFAULT_STALL_THRESHOLD_MS;\n const maxMs = given.maxMs ?? DEFAULT_STALL_MAX_MS;\n const intervalMs = given.intervalMs ?? DEFAULT_STALL_INTERVAL_MS;\n const slowest = given.slowest ?? DEFAULT_SLOWEST;\n if (!(Number.isFinite(thresholdMs) && thresholdMs > 0)) {\n fail(\"thresholdMs must be a positive number of milliseconds\");\n }\n if (!(Number.isFinite(maxMs) && maxMs > 0)) {\n fail(\"maxMs must be a positive number of milliseconds\");\n }\n if (\n !(\n Number.isSafeInteger(intervalMs) &&\n intervalMs >= MIN_STALL_INTERVAL_MS &&\n intervalMs <= MAX_INTERVAL_MS\n )\n ) {\n fail(`intervalMs must be a whole number of milliseconds, at least ${MIN_STALL_INTERVAL_MS}`);\n }\n if (!(Number.isSafeInteger(slowest) && slowest >= 0)) {\n fail(\"slowest must be a whole number, 0 or more\");\n }\n return { thresholdMs, maxMs, intervalMs, slowest };\n}\n\nconst NS_PER_MS = 1e6;\n\nfunction toMs(nanoseconds: number): number {\n return Math.round((nanoseconds / NS_PER_MS) * 10) / 10;\n}\n\nfunction rank(methods: ReadonlyMap<string, MethodWindow>, slowest: number): SlowMethod[] {\n return [...methods]\n .map(([method, window]) => ({\n method,\n calls: window.calls,\n maxMs: Math.round(window.maxMs),\n meanMs: Math.round(window.totalMs / window.calls),\n }))\n .sort((a, b) => b.maxMs - a.maxMs)\n .slice(0, slowest);\n}\n\n/** Reads `histogram` for the window that started at `startedAt`. */\nfunction readWindow(\n histogram: ELDHistogram,\n startedAt: number,\n): Omit<StallReport, \"stalled\" | \"slowest\"> {\n const windowMs = Math.round(performance.now() - startedAt);\n if (histogram.count === 0) {\n return { windowMs, p50Ms: 0, p99Ms: 0, maxMs: 0, meanMs: 0 };\n }\n return {\n windowMs,\n p50Ms: toMs(histogram.percentile(50)),\n p99Ms: toMs(histogram.percentile(99)),\n maxMs: toMs(histogram.max),\n meanMs: toMs(histogram.mean),\n };\n}\n\n/**\n * The warning a window gives, or `undefined` when it did not stall: the\n * 99th percentile above the threshold (a loop that keeps stalling), else one\n * delay above `maxMs` (one long block).\n */\nfunction stallMessage(\n read: Omit<StallReport, \"stalled\" | \"slowest\">,\n settings: Settings,\n): string | undefined {\n if (read.p99Ms > settings.thresholdMs) {\n return `The event loop stalled: its 99th percentile delay was ${read.p99Ms} ms over the last ${read.windowMs} ms (threshold ${settings.thresholdMs} ms)`;\n }\n if (read.maxMs > settings.maxMs) {\n return `The event loop stalled: one delay of ${read.maxMs} ms over the last ${read.windowMs} ms (max ${settings.maxMs} ms)`;\n }\n return undefined;\n}\n\n/**\n * Starts sampling the event loop's delay, reading it every `intervalMs`. The\n * timer does not keep the process alive. `createServer({ stallWatchdog })`\n * starts one and stops it on `close()`.\n */\nexport function startStallWatchdog(settings: Settings, logger: Logger): StallWatchdog {\n const histogram = monitorEventLoopDelay({ resolution: STALL_RESOLUTION_MS });\n const methods = new Map<string, MethodWindow>();\n let startedAt = performance.now();\n histogram.enable();\n const check = (): StallReport => {\n const read = readWindow(histogram, startedAt);\n const slowest = rank(methods, settings.slowest);\n histogram.reset();\n methods.clear();\n startedAt = performance.now();\n const message = stallMessage(read, settings);\n if (message !== undefined) {\n logger.warn(message, {\n category: \"quickdraw.stall\",\n ...read,\n thresholdMs: settings.thresholdMs,\n maxThresholdMs: settings.maxMs,\n slowest,\n });\n }\n return { ...read, stalled: message !== undefined, slowest };\n };\n const timer = setInterval(check, settings.intervalMs);\n timer.unref();\n return {\n observe(record) {\n // A method that does not exist is named by the client: never a key.\n if (record.kind === undefined) {\n return;\n }\n const key = `${record.service}.${record.method}`;\n const window = methods.get(key);\n if (window === undefined) {\n methods.set(key, { calls: 1, maxMs: record.durationMs, totalMs: record.durationMs });\n return;\n }\n window.calls += 1;\n window.totalMs += record.durationMs;\n window.maxMs = Math.max(window.maxMs, record.durationMs);\n },\n check,\n stop() {\n clearInterval(timer);\n histogram.disable();\n },\n };\n}\n","// The HTTP transport (RFC 0003 section 10): `POST {path}/{service}/{method}`\n// with the input as the JSON body, through the same pipeline and the same\n// `authenticate` as sockets, for server-side prefetch, load tests and\n// webhooks. The principal comes from the session cookie or a bearer token\n// (`httpCredentialOf`), and `authenticate` is told which one it was, so the\n// ambient cookie's `Origin` can be checked (`socketAuth` does; finding F7.1\n// of the quickdraw-chat review); the reply is the `qd:call` acknowledgement\n// shape, `{ ok: true, d }` or `{ ok: false, e }`, with the error code's HTTP\n// status (`httpStatus`). The call is cancelled when the client goes away.\n//\n// The router is a plain Node request handler rather than an `express.Router`,\n// so it never imports Express: it mounts with `app.use(router)` on Express 4\n// or 5 alike, whichever the app installed, and also serves a bare Node HTTP\n// server.\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { consoleLogger, type Logger } from \"../../contract/logger\";\nimport { httpStatus, INTERNAL_MESSAGE, QuickdrawError, toWire } from \"../../protocol/errors\";\nimport type { Dispatcher } from \"../dispatcher\";\nimport { describeError } from \"../pipeline/metrics\";\nimport { toCallReply, type DispatchResult } from \"../pipeline/request\";\nimport type { Principal } from \"../types\";\nimport { INTERNAL_FAILURE, unreadable } from \"./ack\";\nimport {\n createPrincipalResolver,\n isForbiddenCredential,\n isRefusal,\n type ResolvePrincipal,\n type ServerAuth,\n} from \"./auth\";\nimport {\n httpCredentialOf,\n isJsonRequest,\n readJsonInput,\n transportCookieNaming,\n type HttpRequest,\n type SessionCookieNaming,\n} from \"./body\";\n\n/**\n * A Node request handler that serves calls: mount it with `app.use(router)`\n * on an Express app, or pass it to `http.createServer`. A request it does not\n * serve goes to `next`, or gets a 404 when there is no `next`.\n */\nexport type HttpRouter = (\n req: IncomingMessage,\n res: ServerResponse,\n next?: (error?: unknown) => void,\n) => void;\n\n/**\n * An Express-style middleware, such as an `express-rate-limit` limiter: it\n * answers the request itself, or calls `next()` to let it through.\n */\nexport type HttpMiddleware = (req: never, res: never, next: (error?: unknown) => void) => unknown;\n\n/** How the HTTP transport serves calls. */\nexport interface HttpTransportOptions {\n /** The path calls are served under: `POST {path}/{service}/{method}`. Default `\"/qd\"`. */\n readonly path?: string;\n /**\n * The largest request body read, in bytes. Default 1 MiB. A body the app's\n * own JSON parser already read (`express.json()`) is used as it is.\n */\n readonly maxBodyBytes?: number;\n /**\n * The session cookie a token is read from. Default: the name the auth\n * routes set on the same request: `\"session\"` when `COOKIE_DOMAIN` gives\n * the cookie a domain; else `\"__Host-session\"` on a request over HTTPS\n * (`req.secure`, `X-Forwarded-Proto: https` or an `https:` `Origin`),\n * which never reads the plain name a sibling site could plant, and\n * `\"session\"` (then `\"__Host-session\"`) on a plain HTTP one. A name given\n * here is the only one read, on any request. A name the request repeats\n * counts as no cookie.\n */\n readonly cookieName?: string;\n /**\n * A rate limiter run before each call the transport serves, and only\n * those: `createCallLimiter()` from `./server/express`, which refuses in\n * the transport's own `RATE_LIMITED` reply. It runs on the app's Express\n * request and response, so the transport must be mounted on Express.\n * Default: none (the socket rate limiter does not see HTTP calls).\n */\n readonly rateLimit?: HttpMiddleware;\n}\n\n/** Options of {@link createHttpRouter}. */\nexport interface HttpRouterOptions<P extends Principal = Principal> extends HttpTransportOptions {\n /** The dispatcher whose methods the router serves. */\n readonly dispatcher: Pick<Dispatcher, \"call\">;\n /** Authenticates each request, with the same hooks as `createServer`'s `auth`. */\n readonly auth?: ServerAuth<P>;\n /** Default: the console. */\n readonly logger?: Logger;\n}\n\n/** What the router runs on, resolved from its options. */\nexport interface HttpRouterSettings {\n readonly call: Dispatcher[\"call\"];\n readonly resolvePrincipal: ResolvePrincipal;\n readonly logger: Logger;\n readonly prefix: string;\n readonly maxBodyBytes: number;\n /** `cookieName`, and `COOKIE_DOMAIN` read when the router is made: a cookie with a domain is `session`. */\n readonly cookieNaming: SessionCookieNaming;\n readonly rateLimit: HttpMiddleware | undefined;\n}\n\nconst DEFAULT_MAX_BODY_BYTES = 1_048_576;\n\ninterface Target {\n readonly service: string;\n readonly method: string;\n}\n\nfunction decodeSegment(segment: string): string | undefined {\n try {\n return decodeURIComponent(segment);\n } catch {\n return undefined;\n }\n}\n\n/** The service and method a `POST {prefix}/{service}/{method}` request names, or `undefined`. */\nfunction targetOf(req: IncomingMessage, prefix: string): Target | undefined {\n const path = (req.url ?? \"\").split(\"?\", 1)[0] ?? \"\";\n if (req.method !== \"POST\" || !path.startsWith(`${prefix}/`)) {\n return undefined;\n }\n const segments = path.slice(prefix.length + 1).split(\"/\");\n const [service, method] = segments.map(decodeSegment);\n if (segments.length !== 2 || !service || !method) {\n return undefined;\n }\n return { service, method };\n}\n\nfunction retryAfterSeconds(result: DispatchResult): number | undefined {\n if (result.ok || result.error.code !== \"RATE_LIMITED\") {\n return undefined;\n }\n const { retryAfterMs } = (result.error.data ?? {}) as { readonly retryAfterMs?: unknown };\n return typeof retryAfterMs === \"number\" && retryAfterMs > 0\n ? Math.ceil(retryAfterMs / 1000)\n : undefined;\n}\n\nfunction encode(settings: HttpRouterSettings, result: DispatchResult): [number, string] {\n // The status of the code the reply carries, which `toWire` keeps to the known codes.\n const status = result.ok ? 200 : httpStatus(toWire(result.error).code);\n try {\n return [status, JSON.stringify(toCallReply(result))];\n } catch (error) {\n settings.logger.error(\"A call's reply could not be encoded; it was answered with INTERNAL\", {\n category: \"quickdraw.http\",\n error: describeError(error),\n });\n return [500, JSON.stringify(INTERNAL_FAILURE)];\n }\n}\n\n/** Writes a call's reply, unless the response already ended; returns its size in bytes. */\nfunction sendResult(\n settings: HttpRouterSettings,\n res: ServerResponse,\n result: DispatchResult,\n): number | undefined {\n if (res.headersSent || res.writableEnded || res.destroyed) {\n return undefined;\n }\n const [status, body] = encode(settings, result);\n const bytes = Buffer.byteLength(body);\n res.statusCode = status;\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.setHeader(\"content-length\", bytes);\n const retryAfter = retryAfterSeconds(result);\n if (retryAfter !== undefined) {\n res.setHeader(\"retry-after\", String(retryAfter));\n }\n res.end(body);\n return bytes;\n}\n\nfunction failure(error: QuickdrawError): DispatchResult {\n return { ok: false, error };\n}\n\nasync function authenticate(\n settings: HttpRouterSettings,\n req: HttpRequest,\n): Promise<Principal | null | QuickdrawError> {\n const credential = httpCredentialOf(req, settings.cookieNaming);\n try {\n return await settings.resolvePrincipal({\n transport: \"http\",\n auth: credential === null ? {} : { token: credential.token },\n // The session cookie is ambient: `socketAuth` checks such a call's Origin (F7.1).\n ...(credential === null ? {} : { credential: credential.from }),\n headers: req.headers,\n req,\n });\n } catch (error) {\n const forbidden = isForbiddenCredential(error);\n settings.logger[isRefusal(error) || forbidden ? \"debug\" : \"error\"](\n \"HTTP authentication failed\",\n { category: \"quickdraw.http\", error: describeError(error) },\n );\n return forbidden\n ? new QuickdrawError(\"FORBIDDEN\", error.message)\n : new QuickdrawError(\"UNAUTHENTICATED\", \"Authentication failed\");\n }\n}\n\nasync function serve(\n settings: HttpRouterSettings,\n req: HttpRequest,\n res: ServerResponse,\n target: Target,\n): Promise<void> {\n const controller = new AbortController();\n // `req` closes once its body was read; `res` closes when the client leaves.\n res.once(\"close\", () => {\n if (!res.writableFinished) {\n controller.abort();\n }\n });\n if (!isJsonRequest(req)) {\n const message = \"Send the input as a JSON body with Content-Type: application/json\";\n sendResult(settings, res, failure(unreadable(message)));\n return;\n }\n const principal = await authenticate(settings, req);\n if (principal instanceof QuickdrawError) {\n sendResult(settings, res, failure(principal));\n return;\n }\n let input: unknown;\n try {\n input = await readJsonInput(req, settings.maxBodyBytes);\n } catch (error) {\n const reason =\n error instanceof QuickdrawError ? error : unreadable(\"The request body could not be read\");\n sendResult(settings, res, failure(reason));\n return;\n }\n await settings.call({\n ...target,\n input,\n principal,\n transport: \"http\",\n signal: controller.signal,\n respond: (result) => sendResult(settings, res, result),\n });\n}\n\nfunction notFound(settings: HttpRouterSettings, res: ServerResponse): void {\n sendResult(settings, res, failure(new QuickdrawError(\"NOT_FOUND\", \"Not found\")));\n}\n\n/** Serves a call, answering `INTERNAL` when serving it fails. */\nfunction serveCall(\n settings: HttpRouterSettings,\n req: IncomingMessage,\n res: ServerResponse,\n target: Target,\n): void {\n const fail = (error: unknown): void => {\n settings.logger.error(\"The HTTP transport failed to serve a call\", {\n category: \"quickdraw.http\",\n error: describeError(error),\n });\n sendResult(settings, res, failure(new QuickdrawError(\"INTERNAL\", INTERNAL_MESSAGE)));\n };\n const { rateLimit } = settings;\n if (rateLimit === undefined) {\n serve(settings, req, res, target).catch(fail);\n return;\n }\n // The limiter answers a refused call itself; it calls `next` to let one through.\n const next = (error?: unknown): void => {\n if (error === undefined) {\n serve(settings, req, res, target).catch(fail);\n } else {\n fail(error);\n }\n };\n try {\n Promise.resolve(rateLimit(req as never, res as never, next)).catch(fail);\n } catch (error) {\n fail(error);\n }\n}\n\n/** The router over resolved settings; `createServer` builds it with its own principal resolver. */\nexport function httpRouter(settings: HttpRouterSettings): HttpRouter {\n return (req, res, next) => {\n const target = targetOf(req, settings.prefix);\n if (target === undefined) {\n if (next === undefined) {\n notFound(settings, res);\n } else {\n next();\n }\n return;\n }\n serveCall(settings, req, res, target);\n };\n}\n\n/** `\"/qd/\"` and `\"qd\"` become `\"/qd\"`; `\"/\"` becomes `\"\"`, serving `/{service}/{method}`. */\nfunction normalizePath(path: string): string {\n const trimmed = path.replace(/^\\/+|\\/+$/g, \"\");\n return trimmed === \"\" ? \"\" : `/${trimmed}`;\n}\n\n/** Resolves the HTTP transport's options. */\nexport function httpRouterSettings(\n options: HttpTransportOptions,\n base: Pick<HttpRouterSettings, \"call\" | \"resolvePrincipal\" | \"logger\">,\n): HttpRouterSettings {\n const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;\n if (!Number.isSafeInteger(maxBodyBytes) || maxBodyBytes < 1) {\n throw new TypeError(\"http.maxBodyBytes must be a whole number of bytes, 1 or more\");\n }\n const { rateLimit } = options;\n if (rateLimit !== undefined && typeof rateLimit !== \"function\") {\n throw new TypeError(\n \"http.rateLimit must be an Express middleware, such as createCallLimiter()\",\n );\n }\n return {\n ...base,\n prefix: normalizePath(options.path ?? \"/qd\"),\n maxBodyBytes,\n cookieNaming: transportCookieNaming(options.cookieName),\n rateLimit,\n };\n}\n\n/**\n * Creates the HTTP transport for a dispatcher: `POST /qd/{service}/{method}`\n * with a JSON body. `createServer` mounts one on the app's Express app; use\n * this to serve calls from an app without sockets, or under another path.\n *\n * @example\n * app.use(createHttpRouter({ dispatcher, auth: { authenticate } }));\n */\nexport function createHttpRouter<P extends Principal = Principal>(\n options: HttpRouterOptions<P>,\n): HttpRouter {\n return httpRouter(\n httpRouterSettings(options, {\n call: options.dispatcher.call,\n resolvePrincipal: createPrincipalResolver(options.auth),\n logger: options.logger ?? consoleLogger,\n }),\n );\n}\n","/**\n * Rate limiting middleware for Socket.io events.\n *\n * Provides per-socket rate limiting to prevent abuse and ensure\n * fair resource usage across clients.\n *\n * @example\n * ```typescript\n * import { createRateLimiter, applyRateLimitMiddleware } from '@fitzzero/quickdraw-core/server';\n *\n * // Create a rate limiter\n * const rateLimiter = createRateLimiter({\n * windowMs: 60000, // 1 minute window\n * maxRequests: 100, // 100 requests per window\n * });\n *\n * // Apply to Socket.io server\n * applyRateLimitMiddleware(io, rateLimiter);\n * ```\n */\n\nimport type { Server as SocketIOServer, Socket } from \"socket.io\";\nimport type { Logger } from \"../contract/logger\";\nimport { consoleLogger } from \"../contract/logger\";\n\n/**\n * Rate limiter configuration options.\n */\nexport interface RateLimitOptions {\n /**\n * Time window in milliseconds (default: 60000 = 1 minute)\n */\n windowMs?: number;\n\n /**\n * Maximum number of requests per window (default: 600, which `createServer`'s\n * socket limiter uses too; 4.x defaulted to 100)\n */\n maxRequests?: number;\n\n /**\n * Events to exclude from rate limiting (e.g., ['ping', 'pong'])\n */\n excludeEvents?: string[];\n\n /**\n * Event-name prefixes to exclude from rate limiting.\n * Pass `[CHANNEL_EVENT_PREFIX]` (\"channel:\") so channel traffic bypasses\n * the global limiter — channels enforce their own per-socket token buckets.\n */\n excludePrefixes?: string[];\n\n /**\n * Custom key generator for grouping requests.\n * Default uses socket.id.\n */\n keyGenerator?: (socket: Socket, eventName: string) => string;\n\n /**\n * Callback when rate limit is exceeded.\n */\n onRateLimitExceeded?: (socket: Socket, eventName: string) => void;\n\n /**\n * The acknowledgement a dropped event's callback receives, given the socket,\n * the event name and the milliseconds until the limit resets. Default: the\n * 4.x `{ success: false, error: \"Rate limit exceeded\", code: 429 }`.\n */\n ackPayload?: (socket: Socket, eventName: string, retryAfterMs: number) => unknown;\n\n /**\n * Logger instance\n */\n logger?: Logger;\n}\n\n/**\n * Requests allowed per window by default: 600 a minute, so a socket can\n * refetch a watched query four times a second (the coordinator's window)\n * with room to spare. 4.x allowed 100, which refused part of a busy\n * board's work in the 5.0 benchmark (`bench/reports/5.0.0.md`).\n */\nconst DEFAULT_MAX_REQUESTS = 600;\n\n/**\n * Rate limit entry tracking requests in a window.\n */\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\n/**\n * Rate limiter instance.\n */\nexport interface RateLimiter {\n /**\n * Check if a request should be allowed.\n * Returns true if allowed, false if rate limited.\n */\n check: (key: string) => boolean;\n\n /**\n * Get remaining requests for a key.\n */\n getRemaining: (key: string) => number;\n\n /**\n * Get time until rate limit resets for a key.\n */\n getResetTime: (key: string) => number;\n\n /**\n * Clear all rate limit entries (useful for testing).\n */\n clear: () => void;\n\n /**\n * Configuration options.\n */\n options: Required<\n Pick<RateLimitOptions, \"windowMs\" | \"maxRequests\" | \"excludeEvents\" | \"excludePrefixes\">\n >;\n}\n\n/**\n * Create a rate limiter instance.\n *\n * @param options - Rate limiter configuration\n * @returns Rate limiter instance\n *\n * @example\n * ```typescript\n * const limiter = createRateLimiter({\n * windowMs: 60000,\n * maxRequests: 100,\n * });\n *\n * if (limiter.check('user-123')) {\n * // Request allowed\n * } else {\n * // Rate limited\n * }\n * ```\n */\nexport function createRateLimiter(options: RateLimitOptions = {}): RateLimiter {\n const {\n windowMs = 60000,\n maxRequests = DEFAULT_MAX_REQUESTS,\n excludeEvents = [],\n excludePrefixes = [],\n } = options;\n\n const entries = new Map<string, RateLimitEntry>();\n\n // Cleanup old entries periodically\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of entries) {\n if (entry.resetAt <= now) {\n entries.delete(key);\n }\n }\n }, windowMs);\n\n // Prevent the interval from keeping the process alive\n if (cleanupInterval.unref) {\n cleanupInterval.unref();\n }\n\n return {\n check(key: string): boolean {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n // New window\n entries.set(key, {\n count: 1,\n resetAt: now + windowMs,\n });\n return true;\n }\n\n if (entry.count >= maxRequests) {\n return false;\n }\n\n entry.count++;\n return true;\n },\n\n getRemaining(key: string): number {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n return maxRequests;\n }\n\n return Math.max(0, maxRequests - entry.count);\n },\n\n getResetTime(key: string): number {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n return 0;\n }\n\n return entry.resetAt - now;\n },\n\n clear(): void {\n entries.clear();\n },\n\n options: {\n windowMs,\n maxRequests,\n excludeEvents,\n excludePrefixes,\n },\n };\n}\n\n/**\n * Apply rate limiting middleware to a Socket.io server.\n *\n * This intercepts all incoming events and checks them against\n * the rate limiter before allowing them to proceed.\n *\n * @param io - Socket.io server instance\n * @param rateLimiter - Rate limiter instance\n * @param options - Additional options\n *\n * @example\n * ```typescript\n * const rateLimiter = createRateLimiter({ maxRequests: 100 });\n *\n * applyRateLimitMiddleware(io, rateLimiter, {\n * keyGenerator: (socket) => socket.userId ?? socket.id,\n * onRateLimitExceeded: (socket, event) => {\n * socket.emit('error', { code: 'RATE_LIMITED', event });\n * },\n * });\n * ```\n */\nexport function applyRateLimitMiddleware(\n io: SocketIOServer,\n rateLimiter: RateLimiter,\n options: Pick<\n RateLimitOptions,\n \"keyGenerator\" | \"onRateLimitExceeded\" | \"logger\" | \"ackPayload\"\n > = {},\n): void {\n const logger =\n options.logger?.child({ service: \"RateLimiter\" }) ??\n consoleLogger.child({ service: \"RateLimiter\" });\n\n const keyGenerator = options.keyGenerator ?? ((socket) => socket.id);\n const onRateLimitExceeded =\n options.onRateLimitExceeded ??\n ((socket, eventName) => {\n socket.emit(\"error\", {\n code: \"RATE_LIMITED\",\n message: `Rate limit exceeded for event: ${eventName}`,\n retryAfter: rateLimiter.getResetTime(keyGenerator(socket, eventName)),\n });\n });\n\n const ackPayload =\n options.ackPayload ??\n (() => ({\n success: false,\n error: \"Rate limit exceeded\",\n code: 429,\n }));\n\n const { excludeEvents, excludePrefixes } = rateLimiter.options;\n\n io.on(\"connection\", (socket) => {\n // Use Socket.io's built-in middleware for incoming packets\n socket.use(([eventName, ...args], next) => {\n // A client may name an event with a number, which Socket.IO accepts;\n // no listener serves one, so it passes uncounted.\n if (typeof eventName !== \"string\") {\n next();\n return;\n }\n\n // Skip excluded events\n if (excludeEvents.includes(eventName)) {\n next();\n return;\n }\n\n // Skip excluded prefixes (e.g., \"channel:\" — channels self-limit)\n if (excludePrefixes.some((prefix) => eventName.startsWith(prefix))) {\n next();\n return;\n }\n\n // Skip internal Socket.io events\n if (eventName.startsWith(\"$\")) {\n next();\n return;\n }\n\n const key = keyGenerator(socket, eventName);\n\n if (rateLimiter.check(key)) {\n next();\n } else {\n logger.warn(`Rate limit exceeded for socket ${socket.id} on event ${eventName}`);\n onRateLimitExceeded(socket, eventName);\n\n // Don't call next() - this drops the event\n // If there's a callback, call it with an error\n const lastArg = args[args.length - 1];\n if (typeof lastArg === \"function\") {\n lastArg(ackPayload(socket, eventName, rateLimiter.getResetTime(key)));\n }\n }\n });\n });\n\n logger.info(\n `Rate limiting enabled: ${rateLimiter.options.maxRequests} requests per ${rateLimiter.options.windowMs}ms`,\n );\n}\n\n/**\n * Create a tiered rate limiter with different limits for different event types.\n *\n * @param tiers - Map of event patterns to rate limit options\n * @param defaultOptions - Default options for events not matching any tier\n * @returns Rate limiter that applies different limits based on event name\n *\n * @example\n * ```typescript\n * const tieredLimiter = createTieredRateLimiter(\n * {\n * // Strict limits for write operations\n * 'create*': { maxRequests: 10, windowMs: 60000 },\n * 'update*': { maxRequests: 20, windowMs: 60000 },\n * 'delete*': { maxRequests: 5, windowMs: 60000 },\n * // Generous limits for reads\n * 'list*': { maxRequests: 200, windowMs: 60000 },\n * 'get*': { maxRequests: 200, windowMs: 60000 },\n * },\n * { maxRequests: 100, windowMs: 60000 } // Default\n * );\n * ```\n */\nexport function createTieredRateLimiter(\n tiers: Record<string, RateLimitOptions>,\n defaultOptions: RateLimitOptions = {},\n): {\n check: (key: string, eventName: string) => boolean;\n getRemaining: (key: string, eventName: string) => number;\n clear: () => void;\n} {\n // Create a limiter for each tier\n const tierLimiters = new Map<string, RateLimiter>();\n const tierPatterns: Array<{ pattern: RegExp; limiter: RateLimiter }> = [];\n\n for (const [pattern, options] of Object.entries(tiers)) {\n const limiter = createRateLimiter({ ...defaultOptions, ...options });\n tierLimiters.set(pattern, limiter);\n\n // Convert glob-like pattern to regex\n const regexPattern = pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\");\n tierPatterns.push({\n pattern: new RegExp(`^${regexPattern}$`),\n limiter,\n });\n }\n\n const defaultLimiter = createRateLimiter(defaultOptions);\n\n function getLimiterForEvent(eventName: string): RateLimiter {\n for (const { pattern, limiter } of tierPatterns) {\n if (pattern.test(eventName)) {\n return limiter;\n }\n }\n return defaultLimiter;\n }\n\n return {\n check(key: string, eventName: string): boolean {\n const limiter = getLimiterForEvent(eventName);\n // Include event name in key to separate limits per event type\n return limiter.check(`${key}:${eventName}`);\n },\n\n getRemaining(key: string, eventName: string): number {\n const limiter = getLimiterForEvent(eventName);\n return limiter.getRemaining(`${key}:${eventName}`);\n },\n\n clear(): void {\n for (const limiter of tierLimiters.values()) {\n limiter.clear();\n }\n defaultLimiter.clear();\n },\n };\n}\n","// `createServer` (RFC 0003 sections 3, 8 and 10): serves a dispatcher over\n// Socket.IO and HTTP, on the Express app and HTTP server the app already\n// owns. It replaces 4.1's `createQuickdrawServer`, which built its own\n// Express app and listened itself (4.1 `src/server/createServer.ts:57-67`),\n// so every app that needed its own middleware copied the whole bootstrap\n// instead, and which called `process.exit` on shutdown (`:195-204`). This one\n// creates the HTTP server only when none is passed, never listens, never exits\n// the process, and handles signals only when asked.\n\nimport {\n createServer as createHttpServer,\n type IncomingMessage,\n type Server as HttpServer,\n type ServerResponse,\n} from \"node:http\";\nimport { consoleLogger, type Logger } from \"../contract/logger\";\nimport {\n createDispatcher,\n detachDispatcher,\n loopsOf,\n withAccessSinks,\n type Dispatcher,\n type DispatcherOptions,\n type PrincipalOfServices,\n} from \"./dispatcher\";\nimport { liveOf, type RoomLeaveHandler, type RoomLeaveHook } from \"./emit/live\";\nimport {\n closer,\n prepareWatchdog,\n trackCalls,\n watchSignals,\n type StallWatchdogOptions,\n} from \"./lifecycle\";\nimport { editsGrants, type AnyService } from \"./service\";\nimport {\n createGrantsSink,\n createPrincipalResolver,\n type ServerAuth,\n type ServiceGrants,\n} from \"./transports/auth\";\nimport {\n httpRouter,\n httpRouterSettings,\n type HttpRouter,\n type HttpTransportOptions,\n} from \"./transports/http\";\nimport {\n createSocketServer,\n type ClusterOptions,\n type DisconnectUserOptions,\n type QuickdrawIo,\n type SocketCors,\n type SocketOptions,\n type SocketRateLimitOptions,\n} from \"./transports/socketServer\";\nimport type { Principal } from \"./types\";\n\n/**\n * The parts of an Express app (4 or 5) `createServer` uses: it is a request\n * listener, and `use` mounts the HTTP transport.\n */\nexport interface HttpApp {\n (req: IncomingMessage, res: ServerResponse): void;\n use(router: HttpRouter): unknown;\n}\n\n/** `createServer`'s own options, besides the dispatcher's. */\nexport interface ServerOnlyOptions<P extends Principal = Principal> {\n /**\n * The app's Express app. The HTTP transport is mounted on it with\n * `app.use`, and when `httpServer` is not given the HTTP server is created\n * from it. Mount the app's own routes and parsers first.\n */\n readonly app?: HttpApp;\n /**\n * The app's HTTP server, for Socket.IO to attach to; pass the one made from\n * `app`, and `app` with it (or `http: false`): the HTTP transport is\n * mounted on `app`. Without it one is created, from `app` when given.\n * Either way the app calls `server.httpServer.listen(...)` itself.\n */\n readonly httpServer?: HttpServer;\n /** Authenticates sockets and HTTP calls. Without it every caller is anonymous. */\n readonly auth?: ServerAuth<P>;\n /** Socket.IO's CORS for its handshake. The app configures CORS for its own routes. */\n readonly cors?: SocketCors;\n /** Other Socket.IO server options, such as `path` or `pingInterval`. */\n readonly socket?: SocketOptions;\n /**\n * Use the stock Socket.IO parser, so events may carry binary. Default\n * `false`: the JSON-only parser, which also measures each reply's size.\n */\n readonly binary?: boolean;\n /**\n * Serve 4.x clients, which connect without `auth.qd`, through the legacy\n * shim: request/response calls only. Default `false`: they are refused with\n * `PROTOCOL_MISMATCH`.\n */\n readonly legacyWire?: boolean;\n /**\n * The socket rate limiter (`createRateLimiter`'s options), or `false` for\n * none. Default: 600 events per minute per socket. `qd:ch` (channels keep\n * their own per-socket token buckets), `qd:cancel`, the entity and\n * collection subscription events (`qd:sub`, `qd:unsub`, `qd:col:sub`,\n * `qd:col:unsub`, `qd:col:items`), the topic watches (`qd:watch`,\n * `qd:unwatch`) and the stream subscriptions (`qd:stream:sub`,\n * `qd:stream:unsub`) are never counted; the ones that read run in a\n * per-socket lane instead (`limits.subscriptions`: 8 at once, 64 waiting,\n * then `RATE_LIMITED`).\n */\n readonly rateLimit?: SocketRateLimitOptions | false;\n /**\n * The HTTP transport's options, or `false` to serve no HTTP calls. It has\n * no rate limit unless `rateLimit` is given: `http: { rateLimit:\n * createCallLimiter() }` (from `./server/express`).\n */\n readonly http?: HttpTransportOptions | false;\n /** Close the server on `SIGTERM` and `SIGINT`. Default `false`. The process is never exited. */\n readonly handleSignals?: boolean;\n /**\n * Watch the event loop for stalls: sample its delay (every 20 ms), read it\n * every `intervalMs` (10 s), and log a warning naming the window's slowest\n * methods when the 99th percentile delay is above `thresholdMs` (200 ms)\n * or one delay is above `maxMs` (1 s). `true` for the defaults. Default\n * `false`. Stops on `close()`.\n */\n readonly stallWatchdog?: boolean | StallWatchdogOptions;\n /**\n * How long `close()` waits for calls and HTTP requests in flight before it\n * stops waiting and closes their connections, in milliseconds. Default\n * 10,000.\n */\n readonly shutdownTimeoutMs?: number;\n /**\n * Behind a cluster adapter: where the cluster's shared state lives (the\n * revision counter every node's flushes take their revision from, and\n * users' last-seen times). By default the Socket.IO Redis adapter's own\n * Valkey or Redis client, under keys prefixed `quickdraw:`; see\n * `docs/deploying.md`.\n */\n readonly cluster?: ClusterOptions;\n /**\n * Called once for every socket that leaves app rooms: its own\n * `ctx.rooms.leave(room)` (`reason: \"leave\"`), `rooms.leave(room, { userId })`\n * (`\"removed\"`), or a disconnect, which leaves every app room it was in\n * (`\"disconnect\"`). It gets the socket's principal (`null` when\n * anonymous), its id and the rooms it left, each with `last`: true when\n * no socket of that user is in the room any more, on any node (a second\n * tab keeps it false; a socket reconnecting after `qd:rotate` is a new\n * socket, so the old one's disconnect is the user's last only if they had\n * no other). It runs on the node that held the socket, after the room\n * heard the socket go, in a unit of work of its own (`qd.run` with\n * `detached`: never the unit of the handler that left), with that run's\n * `ctx`; an error it throws is logged, and `close()` waits for it.\n *\n * A service that joins sockets to rooms declares its own hook instead\n * (`defineService`'s `onRoomLeave`), so no server root can forget it:\n * every service's hook runs beside this one, each in a unit of work of\n * its own, and one that throws stops none of the others.\n *\n * @example\n * onRoomLeave: ({ principal, rooms }) => {\n * if (principal !== null && rooms.some(({ room, last }) => room === WORLD_ROOM && last)) {\n * removePlayer(principal.userId);\n * qd.rooms.emit(WORLD_ROOM, gameContract, \"playerLeft\", { id: principal.userId });\n * }\n * },\n */\n readonly onRoomLeave?: RoomLeaveHandler<P>;\n}\n\n/**\n * Options of {@link createServer}: the dispatcher's (`services`, `db`,\n * `logger`, `limits`, `onCall` and the pipeline seams) and the server's own.\n */\nexport type ServerOptions<S extends readonly AnyService[]> = DispatcherOptions<S> &\n ServerOnlyOptions<PrincipalOfServices<S>>;\n\n/** Options of `server.rotate`. */\nexport interface RotateOptions {\n /** Each client reconnects at a random moment within this many milliseconds. */\n readonly withinMs: number;\n}\n\n/** A running quickdraw server: what {@link createServer} returns. */\nexport interface QuickdrawServer<S extends readonly AnyService[] = readonly AnyService[]> {\n /** The Socket.IO server, attached to `httpServer`. */\n readonly io: QuickdrawIo<PrincipalOfServices<S>>;\n /** The HTTP server: the app's, or the one created. Not listening until the app says so. */\n readonly httpServer: HttpServer;\n /**\n * The dispatcher every transport calls; `dispatcher.caller(principal)`\n * calls in process, giving a principal that carries no grants the ones\n * `auth.loadServiceAccess` loads, as a socket's handshake does (once per\n * caller, and again after the server applied new grants). `close()` waits\n * for its calls in flight.\n */\n readonly dispatcher: Dispatcher<S>;\n /**\n * Graceful shutdown: removes the signal handlers, disconnects every socket\n * (cancelling its queries; a mutation runs to its end), waits for the calls\n * still in flight, and closes the HTTP server once its requests finish.\n * After `shutdownTimeoutMs` it stops waiting and closes the remaining\n * connections. Resolves when it is done, so an app can then close its\n * database; calling it again returns the same promise. It never exits the\n * process.\n */\n close(): Promise<void>;\n /**\n * Sends `qd:rotate` to every client: reconnect at a random moment within\n * `withinMs`, for platforms that cap a connection's lifetime.\n */\n rotate(options: RotateOptions): void;\n readonly access: {\n /**\n * Reloads `userId`'s grants with `auth.loadServiceAccess`, puts them in the\n * principal of that user's sockets (on every node: behind a cluster\n * adapter the grants are broadcast), sends them `qd:access`, and resolves\n * the user's entity subscriptions again. Resolves with the grants.\n */\n refresh(userId: string): Promise<ServiceGrants>;\n /**\n * Disconnects every socket of `userId` (only those that authenticated\n * with `sessionId`, when given), on every node: behind a cluster adapter\n * the request is broadcast. For a session the app revoked (wire\n * `createAuthRoutes`' `onRevoke` to it): an open socket keeps the\n * principal it authenticated with, and its reconnect is authenticated\n * afresh. Returns how many sockets this node disconnected.\n */\n disconnectUser(userId: string, options?: DisconnectUserOptions): number;\n };\n /**\n * Who is online, when they were last seen, and who is in a room (RFC 0003\n * section 12.5); the same as `ctx.presence`. Behind a cluster adapter it\n * asks every node.\n */\n readonly presence: Dispatcher<S>[\"presence\"];\n /** The handle of one of the services' streams: `server.stream(task, \"logs\").push(taskId, line)`. */\n readonly stream: Dispatcher<S>[\"stream\"];\n /**\n * App rooms from code that is not a handler (RFC 0003 section 12.5): typed\n * room events and `leave(room, { userId })`, on every node; the same as\n * `qd.rooms` and the socket-free half of `ctx.rooms`.\n */\n readonly rooms: Dispatcher<S>[\"rooms\"];\n}\n\nconst DEFAULT_SHUTDOWN_TIMEOUT_MS = 10_000;\n\nfunction checkOptions<P extends Principal>(options: ServerOnlyOptions<P>): void {\n if (options.app !== undefined && typeof options.app.use !== \"function\") {\n throw new TypeError(\"createServer: app must be an Express app\");\n }\n if (options.httpServer !== undefined && typeof options.httpServer.listen !== \"function\") {\n throw new TypeError(\"createServer: httpServer must be a Node HTTP server\");\n }\n // The HTTP transport is mounted on `app`; a server passed without it would\n // build the transport, attach it nowhere, and answer every call with the\n // app's own handler.\n if (options.httpServer !== undefined && options.app === undefined && options.http !== false) {\n throw new TypeError(\n \"createServer: httpServer was given without app, so the HTTP transport has nowhere to mount; pass the Express app the server was created from as app, or set http: false to serve sockets only\",\n );\n }\n const timeout = options.shutdownTimeoutMs;\n if (timeout !== undefined && !(Number.isSafeInteger(timeout) && timeout >= 0)) {\n throw new TypeError(\"createServer: shutdownTimeoutMs must be a whole number of milliseconds\");\n }\n if (options.onRoomLeave !== undefined && typeof options.onRoomLeave !== \"function\") {\n throw new TypeError(\n \"createServer: onRoomLeave must be a function of the leave and a run context\",\n );\n }\n}\n\n/**\n * Runs every service's `onRoomLeave` and the server's own for every socket\n * that leaves app rooms, each in a detached unit of work of the dispatcher\n * of its own; what one throws is logged, and the others still run.\n */\nfunction listenForLeaves<P extends Principal>(\n dispatcher: Dispatcher,\n handler: RoomLeaveHandler<P> | undefined,\n): void {\n const services = [...dispatcher.registry.services.values()];\n const hooks: RoomLeaveHook[] = services.flatMap((service) =>\n service.onRoomLeave === undefined\n ? []\n : [{ owner: service.name, handler: service.onRoomLeave }],\n );\n if (handler !== undefined) {\n hooks.push({ owner: \"createServer\", handler: handler as RoomLeaveHandler });\n }\n liveOf(dispatcher)?.realtime.onRoomLeave(\n hooks,\n async (fn) => await dispatcher.run(fn, { detached: true }),\n );\n}\n\n/** The HTTP transport, mounted on `app` when there is one. */\nfunction mountRouter<P extends Principal>(\n options: ServerOnlyOptions<P>,\n base: Parameters<typeof httpRouterSettings>[1],\n): HttpRouter | undefined {\n if (options.http === false) {\n return undefined;\n }\n const router = httpRouter(httpRouterSettings(options.http ?? {}, base));\n options.app?.use(router);\n return router;\n}\n\nfunction notFound(_req: IncomingMessage, res: ServerResponse): void {\n res.statusCode = 404;\n res.end();\n}\n\n/**\n * Warns, once at startup, when an admin screen edits users' service-wide\n * grants (`admin.handlers(c, { grants: true })`) but `auth.serviceAccessSource`\n * does not say where they are stored: a lowered grant then stays on the\n * user's open sockets until they connect again (the final review of the\n * release candidates).\n */\nfunction warnUnsourcedGrants(\n services: readonly AnyService[],\n sourced: boolean,\n logger: Logger,\n): void {\n if (sourced) {\n return;\n }\n const editors = services\n .filter((service) =>\n Object.values(service.methods).some((method) => editsGrants(method.handler)),\n )\n .map((service) => service.name);\n if (editors.length > 0) {\n logger.warn(\n `createServer: ${editors.join(\", \")} edit users' service-wide grants (the admin kit's grants: true), but auth.serviceAccessSource does not name where they are stored, so a user whose grant is lowered keeps it on open sockets until they connect again. Set auth.serviceAccessSource: { model, column }`,\n { category: \"quickdraw.access\", services: editors },\n );\n }\n}\n\n/**\n * Serves `services` over Socket.IO and HTTP on the app's own Express app and\n * HTTP server: socket authentication, the `user:{id}` room, `qd:hello`, the\n * v5 transport (or the 4.x shim), the HTTP transport at `POST /qd/{service}/{method}`,\n * disconnect cleanup and graceful shutdown. It does not listen: the app calls\n * `server.httpServer.listen(port)`.\n *\n * @example\n * const app = express();\n * app.use(express.json());\n * const server = createServer({ app, services: [taskService], db: prisma, auth: { authenticate } });\n * server.httpServer.listen(4000);\n */\nexport function createServer<const S extends readonly AnyService[]>(\n options: ServerOptions<S>,\n): QuickdrawServer<S> {\n checkOptions(options);\n const logger = options.logger ?? consoleLogger;\n warnUnsourcedGrants(options.services, options.auth?.serviceAccessSource !== undefined, logger);\n const watchdog = prepareWatchdog(options, options.stallWatchdog);\n let refresh: ((userId: string) => Promise<ServiceGrants>) | undefined;\n const grants = createGrantsSink(options.auth, () => refresh, logger);\n // Right after the access sink: a flush that lowers grants revokes before its frames go out.\n const created = createDispatcher(\n grants === undefined ? watchdog.options : withAccessSinks(watchdog.options, [grants]),\n );\n const calls = trackCalls(created);\n const { dispatcher } = calls;\n listenForLeaves(created as Dispatcher, options.onRoomLeave);\n const resolvePrincipal = createPrincipalResolver(options.auth);\n const router = mountRouter(options, { call: dispatcher.call, resolvePrincipal, logger });\n const httpServer = options.httpServer ?? createHttpServer(options.app ?? router ?? notFound);\n const sockets = createSocketServer(httpServer, {\n dispatcher,\n logger,\n resolvePrincipal,\n loadServiceAccess: options.auth?.loadServiceAccess,\n binary: options.binary === true,\n legacyWire: options.legacyWire === true,\n cors: options.cors,\n socket: options.socket,\n rateLimit: options.rateLimit ?? {},\n extensions: [],\n live: liveOf(created),\n loops: loopsOf(created),\n cluster: options.cluster,\n });\n refresh = (userId) => sockets.refresh(userId);\n // In-process callers (`dispatcher.caller`, `qd.caller`) load a principal's grants as the\n // handshake does, and again once this node applied new grants to a user.\n const load = options.auth?.loadServiceAccess;\n if (load !== undefined) {\n calls.loadGrantsWith({ load, version: () => sockets.regrants() });\n }\n const shutdown = closer(\n sockets,\n httpServer,\n () => calls.idle(),\n options.shutdownTimeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS,\n {\n drain: () => liveOf(created)?.drain() ?? Promise.resolve(),\n timeoutMs: options.cluster?.timeoutMs,\n },\n );\n const { onClose } = shutdown;\n onClose(sockets.stop);\n // Once stopped (its sockets leave first, and what their last events started settles while the\n // adapter still reaches the other nodes: `closer`), and once anything started after that has\n // settled too, the tracked client goes back to the dispatcher attached before.\n let closing: Promise<void> | undefined;\n const close = (): Promise<void> =>\n (closing ??= shutdown.close().then(async () => {\n await liveOf(created)?.drain();\n detachDispatcher(created);\n }));\n if (options.handleSignals === true) {\n onClose(watchSignals(close, logger));\n }\n if (watchdog.start !== undefined) {\n onClose(watchdog.start(logger).stop);\n }\n return Object.freeze({\n io: sockets.io as QuickdrawIo<PrincipalOfServices<S>>,\n httpServer,\n dispatcher,\n close,\n rotate: ({ withinMs }: RotateOptions) => sockets.rotate(withinMs),\n access: Object.freeze({\n refresh: (userId: string) => sockets.refresh(userId),\n disconnectUser: (userId: string, disconnect?: DisconnectUserOptions) =>\n sockets.disconnectUser(userId, disconnect),\n }),\n presence: dispatcher.presence,\n stream: dispatcher.stream,\n rooms: dispatcher.rooms,\n });\n}\n","// The parts of `createServer` that outlive one call (RFC 0003 section 3): the\n// calls in flight `close()` waits for, the one shutdown however often\n// `close()` is called, the opt-in signal handlers, and the opt-in event-loop\n// stall watchdog (`observability/stallWatchdog.ts`).\n\nimport type { Server as HttpServer } from \"node:http\";\nimport type { Logger } from \"../contract/logger\";\nimport {\n callerGrantsOf,\n createCaller,\n setCallerGrants,\n type Caller,\n type CallerGrants,\n} from \"./caller\";\nimport { DEFAULT_CLUSTER_TIMEOUT_MS, within } from \"./cluster/acks\";\nimport type { ContractOfServices, Dispatcher, PrincipalOfServices } from \"./dispatcher\";\nimport {\n stallWatchdogSettings,\n startStallWatchdog,\n type StallWatchdog,\n type StallWatchdogOptions,\n} from \"./observability/stallWatchdog\";\nimport type { CallRecord } from \"./pipeline/metrics\";\nimport type { AnyService } from \"./service\";\nimport type { SocketServer } from \"./transports/socketServer\";\n\nexport type { StallWatchdogOptions };\n\n/** Watches `SIGTERM` and `SIGINT` until the server closes; returns the function that stops watching. */\nexport function watchSignals(close: () => Promise<void>, logger: Logger): () => void {\n const onSignal = (signal: NodeJS.Signals): void => {\n logger.info(`Received ${signal}; closing the quickdraw server`, {\n category: \"quickdraw.server\",\n });\n close().catch((error: unknown) => {\n logger.error(\"Closing the quickdraw server failed\", {\n category: \"quickdraw.server\",\n error: error instanceof Error ? error.message : String(error),\n });\n });\n };\n process.once(\"SIGTERM\", onSignal);\n process.once(\"SIGINT\", onSignal);\n return () => {\n process.off(\"SIGTERM\", onSignal);\n process.off(\"SIGINT\", onSignal);\n };\n}\n\n/** A dispatcher whose calls in flight can be awaited. */\nexport interface TrackedDispatcher<S extends readonly AnyService[]> {\n readonly dispatcher: Dispatcher<S>;\n /** Resolves once no call is in flight. */\n idle(): Promise<void>;\n /**\n * Makes the in-process callers of both dispatchers, the tracked one and\n * the one it wraps (and `qd.caller` through either), load the grants of a\n * principal that carries none through `grants`.\n */\n loadGrantsWith(grants: CallerGrants): void;\n}\n\n/**\n * Counts the calls in flight through `dispatcher`, the transports' and the\n * in-process caller's alike, so `close()` can wait for them. Its caller loads\n * grants once `loadGrantsWith` gave it where from.\n */\nexport function trackCalls<S extends readonly AnyService[]>(\n dispatcher: Dispatcher<S>,\n): TrackedDispatcher<S> {\n const running = new Set<Promise<unknown>>();\n const call: Dispatcher<S>[\"call\"] = (request) => {\n const result = dispatcher.call(request);\n running.add(result);\n const done = (): void => {\n running.delete(result);\n };\n void result.then(done, done);\n return result;\n };\n const tracked: Dispatcher<S> = Object.freeze({\n ...dispatcher,\n call,\n caller: (principal: PrincipalOfServices<S> | null) =>\n createCaller(() => call, principal, {\n grants: () => callerGrantsOf(tracked),\n }) as Caller<ContractOfServices<S>>,\n });\n return {\n dispatcher: tracked,\n async idle() {\n while (running.size > 0) {\n await Promise.allSettled([...running]);\n }\n },\n loadGrantsWith(grants) {\n setCallerGrants(tracked, grants);\n setCallerGrants(dispatcher, grants);\n },\n };\n}\n\n/** The server's `close`, and what else stops when it runs. */\nexport interface Closer {\n /** One shutdown, however often it is called. */\n readonly close: () => Promise<void>;\n /** Adds something to stop as the shutdown starts: the signal handlers, the watchdog. */\n readonly onClose: (stop: () => void) => void;\n}\n\n/** What a closing server lets settle before Socket.IO closes: the work its sockets' last events start. */\nexport interface Departure {\n /** Resolves once the live data's work in flight settled (a room's presence read from every node). */\n readonly drain: () => Promise<void>;\n /** How long it is waited for at most: `cluster.timeoutMs`. Default 1,000. */\n readonly timeoutMs?: number;\n}\n\n/** The server's `close`: one shutdown, however often it is called. */\nexport function closer(\n sockets: SocketServer,\n httpServer: HttpServer,\n idle: () => Promise<void>,\n timeoutMs: number,\n departure?: Departure,\n): Closer {\n let closing: Promise<void> | undefined;\n const stops: (() => void)[] = [];\n const shutdown = async (): Promise<void> => {\n for (const stop of stops) {\n stop();\n }\n let expire = (): void => undefined;\n const expired = new Promise<void>((resolve) => {\n expire = resolve;\n });\n const timer = setTimeout(() => {\n httpServer.closeAllConnections();\n expire();\n }, timeoutMs);\n try {\n // This node's sockets go first, while a cluster adapter still reaches the\n // other nodes: each app room a socket was in asks them whether its user\n // is still there and tells them it left, which settles (bounded) before\n // the adapter closes, instead of waiting out its `requestsTimeout`. Each\n // socket's connection is closed, as `io.close()` closes them, rather than\n // disconnected: a client told \"io server disconnect\" would not reconnect\n // (to another node, in a rolling deploy).\n for (const socket of sockets.io.sockets.sockets.values()) {\n socket.conn.close();\n }\n if (departure !== undefined) {\n const bound = departure.timeoutMs ?? DEFAULT_CLUSTER_TIMEOUT_MS;\n await within(departure.drain(), bound).catch(() => undefined);\n }\n // Closes `httpServer` once its requests end, while the calls still\n // running finish: a mutation runs to its end.\n await Promise.all([sockets.io.close(), Promise.race([idle(), expired])]);\n } finally {\n clearTimeout(timer);\n }\n };\n return {\n close: () => (closing ??= shutdown()),\n onClose: (stop) => {\n stops.push(stop);\n },\n };\n}\n\n/** The stall watchdog `createServer({ stallWatchdog })` asked for, wired to the dispatcher's records. */\nexport interface ServerWatchdog<O> {\n /** `options` with an `onCall` that gives the watchdog every record first, then the app's `onCall`. */\n readonly options: O;\n /** Starts sampling, once the server is built; `undefined` when the watchdog is off. */\n readonly start: ((logger: Logger) => StallWatchdog) | undefined;\n}\n\n/**\n * Checks the `stallWatchdog` option at once (a bad one throws before anything\n * starts) and routes the completion records to the watchdog started later.\n */\nexport function prepareWatchdog<O extends { readonly onCall?: (record: CallRecord) => void }>(\n options: O,\n option: boolean | StallWatchdogOptions | undefined,\n): ServerWatchdog<O> {\n const settings = stallWatchdogSettings(option);\n if (settings === undefined) {\n return { options, start: undefined };\n }\n let watchdog: StallWatchdog | undefined;\n const { onCall } = options;\n return {\n options: {\n ...options,\n onCall: (record: CallRecord) => {\n watchdog?.observe(record);\n onCall?.(record);\n },\n },\n start: (logger) => {\n watchdog = startStallWatchdog(settings, logger);\n return watchdog;\n },\n };\n}\n","// The Socket.IO server of a quickdraw server: the parser, the protocol and\n// authentication middlewares, the rate limiter and the connection handler,\n// the dispatcher's live data (entity subscriptions), plus the two pushes a\n// server sends on the app's request, `qd:rotate` and `qd:access`.\n\nimport type { Server as HttpServer } from \"node:http\";\nimport { Server, type ServerOptions } from \"socket.io\";\nimport { MAX_SUBSCRIBE_IDS, PROTOCOL_VERSION } from \"../../protocol/version\";\nimport { QUICKDRAW_VERSION } from \"../../version\";\nimport { createReplyMeter } from \"./ack\";\nimport type { ResolvePrincipal, ServerAuth, ServiceGrants } from \"./auth\";\nimport {\n applySocketRateLimit,\n authMiddleware,\n protocolMiddleware,\n type SocketLimitContext,\n type SocketRateLimitOptions,\n} from \"./middleware\";\nimport {\n adapterProbe,\n disconnectUser,\n listenForDisconnects,\n listenForGrants,\n refreshGrants,\n regrantsOf,\n rotate,\n serveBroadcasts,\n type ClusterOptions,\n type DisconnectUserOptions,\n type LiveData,\n} from \"./pushes\";\nimport { onConnection, type ServerHello, type SocketExtension } from \"./socketio\";\nimport type { QuickdrawIo, SocketContext } from \"./types\";\n\nexport type { SocketRateLimitOptions } from \"./middleware\";\nexport type { ClusterOptions, DisconnectUserOptions } from \"./pushes\";\nexport type { QuickdrawIo } from \"./types\";\n\n/** Socket.IO server options `createServer` passes through; it sets `parser` and `cors` itself. */\nexport type SocketOptions = Partial<Omit<ServerOptions, \"parser\" | \"cors\">>;\n\n/** Socket.IO's CORS setting for the handshake and polling requests. */\nexport type SocketCors = Partial<ServerOptions>[\"cors\"];\n\n/** Settings of {@link createSocketServer}. */\nexport interface SocketServerSettings extends Omit<SocketContext, \"meter\"> {\n readonly resolvePrincipal: ResolvePrincipal;\n readonly loadServiceAccess: ServerAuth[\"loadServiceAccess\"];\n readonly binary: boolean;\n readonly legacyWire: boolean;\n readonly cors: SocketCors;\n readonly socket: SocketOptions | undefined;\n readonly rateLimit: SocketRateLimitOptions | false;\n readonly extensions: readonly SocketExtension[];\n /** The dispatcher's live data: its extension serves `qd:sub`, and it is given the server. */\n readonly live?: LiveData;\n /** Where a cluster's shared state lives, behind a cluster adapter (`createServer`'s `cluster`). */\n readonly cluster?: ClusterOptions;\n /** The dispatcher's loop watch, which counts the rate limiter's refusals too. */\n readonly loops?: SocketLimitContext[\"loops\"];\n}\n\n/** The Socket.IO side of a quickdraw server. */\nexport interface SocketServer {\n readonly io: QuickdrawIo;\n /** Tells every client to reconnect at a random moment within `withinMs`. */\n rotate(withinMs: number): void;\n /** Reloads `userId`'s service grants into their sockets' principals and sends them `qd:access`. */\n refresh(userId: string): Promise<ServiceGrants>;\n /**\n * How many times this process applied new grants to a user (`refresh`,\n * another node's broadcast): the server's in-process callers load the\n * grants they hold again once it rises.\n */\n regrants(): number;\n /** Disconnects `userId`'s sockets (of one session) on every node; returns how many this node ended. */\n disconnectUser(userId: string, options?: DisconnectUserOptions): number;\n /** Stops what runs in the background (a degraded node's probes): the server closes. */\n stop(): void;\n}\n\n/** The part of `qd:hello` every socket of the server shares; `onConnection` adds the principal's. */\nfunction helloFrame(settings: SocketServerSettings): ServerHello {\n const { limits } = settings.dispatcher;\n return Object.freeze({\n protocol: PROTOCOL_VERSION,\n server: QUICKDRAW_VERSION,\n // New each time a server starts: a client tells a restart from a blip by it.\n serverId: crypto.randomUUID(),\n limits: Object.freeze({\n maxInFlightQueries: limits.maxInFlightQueries,\n maxQueuedQueries: limits.maxQueuedQueries,\n maxSubscribeIds: MAX_SUBSCRIBE_IDS,\n callTimeoutMs: limits.callTimeoutMs,\n subscriptions: Object.freeze({\n maxInFlight: limits.subscriptions.maxInFlight,\n maxQueued: limits.subscriptions.maxQueued,\n }),\n }),\n features: Object.freeze(settings.binary ? [\"binary\"] : []),\n });\n}\n\n/** Attaches a Socket.IO server to `httpServer` and serves the dispatcher over it. */\nexport function createSocketServer(\n httpServer: HttpServer,\n settings: SocketServerSettings,\n): SocketServer {\n const meter = createReplyMeter(settings.binary);\n const io: QuickdrawIo = new Server(httpServer, {\n ...settings.socket,\n ...(settings.cors === undefined ? {} : { cors: settings.cors }),\n ...(meter.parser === undefined ? {} : { parser: meter.parser }),\n });\n const context: SocketContext = {\n dispatcher: settings.dispatcher,\n logger: settings.logger,\n meter,\n };\n const probe = adapterProbe(io, settings.socket?.adapter !== undefined);\n const broadcasts = serveBroadcasts(io, settings.logger, settings.cluster?.timeoutMs);\n settings.live?.attach(io, probe, settings.cluster, broadcasts);\n listenForGrants(io, settings.live, settings.logger);\n listenForDisconnects(io);\n io.use(protocolMiddleware(settings.legacyWire, context));\n io.use(authMiddleware(settings.resolvePrincipal, context));\n // Before the connection handler: the limiter's `socket.use` middleware must\n // come before the legacy shim's, so it counts each 4.x call before it runs.\n if (settings.rateLimit !== false) {\n applySocketRateLimit(io, settings.rateLimit, { ...context, loops: settings.loops });\n }\n io.on(\n \"connection\",\n onConnection({\n ...context,\n hello: helloFrame(settings),\n extensions:\n settings.live === undefined\n ? settings.extensions\n : [...settings.extensions, settings.live.extension],\n legacyCallers: new Set(),\n }),\n );\n return {\n io,\n rotate: (withinMs) => rotate(io, withinMs),\n refresh: (userId) =>\n refreshGrants(\n {\n io,\n load: settings.loadServiceAccess,\n live: settings.live,\n probe,\n broadcasts,\n },\n userId,\n ),\n regrants: () => regrantsOf(io),\n disconnectUser: (userId, options) =>\n disconnectUser(io, probe, settings.logger, userId, options),\n stop: () => {\n broadcasts.close();\n },\n };\n}\n","// The 4.x legacy shim (RFC 0003 section 8.5). A 4.x client connects without\n// `auth.qd` and calls a method by emitting `\"{service}:{method}\"` with its\n// payload and an acknowledgement (4.1 `src/server/ServiceRegistry.ts:277-406`).\n// With `legacyWire: true` such a socket gets one `socket.use` middleware\n// instead of the v5 listeners: it maps each call onto the dispatcher with\n// transport `\"legacy\"` and answers in the 4.x `ServiceResponse` shape\n// (4.1 `src/shared/types.ts:88-90`), with the error code's HTTP status as\n// the numeric `code`.\n//\n// The shim is a middleware, not an `onAny` listener, because Socket.IO runs\n// `onAny` listeners before any middleware: the rate limiter, whose middleware\n// is registered first, would count a call only after the shim had started it,\n// and its 429 would then take the call's acknowledgement.\n//\n// The shim serves request/response calls only. 4.x subscriptions,\n// collections and channels are not served: their events match no method, so\n// the shim passes them on to whatever else listens. The stock decoder reads\n// both protocols, so the shim needs no parser of its own.\n\nimport { httpStatus, toWire, type ErrorCode } from \"../../protocol/errors\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { DispatchResult } from \"../pipeline/request\";\nimport type { Registry } from \"../registry\";\nimport type { Principal } from \"../types\";\nimport { acknowledge, type Acknowledge } from \"./ack\";\nimport type { QuickdrawServerSocket, SocketContext } from \"./types\";\n\n/** 4.x's `ServiceResponse`, the shape every reply of the shim takes. */\nexport type LegacyReply =\n | { readonly success: true; readonly data: unknown }\n | { readonly success: false; readonly error: string; readonly code: number };\n\n/** A 4.x failure with the HTTP status of `code`. */\nexport function legacyFailure(code: ErrorCode, error: string): LegacyReply {\n return { success: false, error, code: httpStatus(code) };\n}\n\n/** A dispatch result in the 4.x reply shape. An `INTERNAL` failure keeps the generic message. */\nexport function toLegacyReply(result: DispatchResult): LegacyReply {\n if (!result.ok) {\n const wire = toWire(result.error);\n return legacyFailure(wire.code, wire.message);\n }\n return { success: true, data: result.notModified === true ? undefined : result.data };\n}\n\nconst LEGACY_INTERNAL: LegacyReply = Object.freeze(legacyFailure(\"INTERNAL\", \"Internal error\"));\n\n/**\n * The 4.x callers seen so far, one key per service, method and principal\n * kind. Each is logged once, so the clients still on 4.x can be found.\n */\nexport type LegacyCallers = Set<string>;\n\ninterface LegacyTarget {\n readonly service: string;\n readonly method: string;\n}\n\n/** The registered method a 4.x event names, or `undefined`. */\nfunction targetOf(event: unknown, registry: Registry): LegacyTarget | undefined {\n if (typeof event !== \"string\") {\n return undefined;\n }\n const colon = event.indexOf(\":\");\n const service = event.slice(0, colon);\n const method = event.slice(colon + 1);\n if (colon <= 0 || registry.find(service, method) === undefined) {\n return undefined;\n }\n return { service, method };\n}\n\nfunction principalKind(principal: Principal | null): string {\n if (principal === null) {\n return \"anonymous\";\n }\n return principal.kind ?? \"unspecified\";\n}\n\nfunction noteCaller(\n context: SocketContext,\n seen: LegacyCallers,\n target: LegacyTarget,\n principal: Principal | null,\n): void {\n const kind = principalKind(principal);\n const key = `${target.service}\\u0000${target.method}\\u0000${kind}`;\n if (seen.has(key)) {\n return;\n }\n seen.add(key);\n context.logger.warn(\n `A 4.x client called ${target.service}.${target.method} through the legacy shim`,\n { category: \"quickdraw.legacy\", ...target, principalKind: kind },\n );\n}\n\nfunction serve(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n calls: Set<AbortController>,\n call: LegacyTarget & { readonly input: unknown; readonly ack: Acknowledge },\n): void {\n const controller = new AbortController();\n calls.add(controller);\n const report = (error: unknown): void => {\n context.logger.error(\"A 4.x call's reply could not be encoded; it was answered with 500\", {\n category: \"quickdraw.legacy\",\n socketId: socket.id,\n error: describeError(error),\n });\n };\n const release = (): void => {\n calls.delete(controller);\n };\n void context.dispatcher\n .call({\n service: call.service,\n method: call.method,\n input: call.input,\n principal: socket.data.principal,\n transport: \"legacy\",\n connectionId: socket.id,\n signal: controller.signal,\n respond: (result) =>\n acknowledge(context.meter, call.ack, toLegacyReply(result), LEGACY_INTERNAL, report),\n })\n .then(release, release);\n}\n\n/**\n * Serves a 4.x socket: one `socket.use` middleware for its calls, the\n * `auth:info` event 4.x clients read their identity from\n * (4.1 `src/server/createServer.ts:134-140`), and cancellation of its\n * calls on disconnect. Call it from the `connection` handler, after the rate\n * limiter's middleware is in place, so the limiter sees each call first. A\n * call the shim serves goes no further; any other event passes on.\n */\nexport function attachLegacyShim(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n seen: LegacyCallers,\n): void {\n const calls = new Set<AbortController>();\n socket.use((packet: unknown[], next) => {\n const [event, ...args] = packet;\n const ack = args.at(-1);\n const target = targetOf(event, context.dispatcher.registry);\n if (target === undefined || typeof ack !== \"function\") {\n next();\n return;\n }\n noteCaller(context, seen, target, socket.data.principal);\n const input = args.length > 1 ? args[0] : undefined;\n serve(socket, context, calls, { ...target, input, ack: ack as Acknowledge });\n });\n socket.on(\"disconnect\", () => {\n for (const controller of calls) {\n controller.abort();\n }\n calls.clear();\n });\n const { principal } = socket.data;\n socket.emit(\"auth:info\", {\n userId: principal?.userId ?? null,\n serviceAccess: principal?.serviceAccess ?? {},\n principalType: principal?.kind,\n });\n}\n","// What every socket passes before `connection` (RFC 0003 section 8.1): the\n// protocol check, then authentication. And the socket rate limiter carried\n// over from 4.1 (`../rateLimit.ts`), which answers each socket in its own\n// protocol's reply shape.\n\nimport type { ExtendedError } from \"socket.io\";\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport type { Failure } from \"../../protocol/envelope\";\nimport {\n PROTOCOL_MISMATCH,\n PROTOCOL_VERSION,\n isQdHandshake,\n type AuthenticationRefused,\n type ProtocolMismatch,\n} from \"../../protocol/version\";\nimport type { LoopWatch } from \"../devWarnings\";\nimport { describeError } from \"../pipeline/metrics\";\nimport {\n applyRateLimitMiddleware,\n createRateLimiter,\n type RateLimiter,\n type RateLimitOptions,\n} from \"../rateLimit\";\nimport { isRefusal, type ResolvePrincipal } from \"./auth\";\nimport { legacyFailure } from \"./legacy\";\nimport type { QuickdrawIo, QuickdrawServerSocket, SocketContext } from \"./types\";\n\ntype Next = (error?: ExtendedError) => void;\n\n/** A refused handshake: Socket.IO sends `message` and `data` as the client's `connect_error`. */\nfunction refusal(message: string, data: ProtocolMismatch | AuthenticationRefused): ExtendedError {\n const error: ExtendedError = new Error(message);\n error.data = data;\n return error;\n}\n\nconst MISMATCH: ProtocolMismatch = Object.freeze({\n code: PROTOCOL_MISMATCH,\n expected: PROTOCOL_VERSION,\n});\n\nconst UNAUTHENTICATED: AuthenticationRefused = Object.freeze({ code: \"UNAUTHENTICATED\" });\n\n/**\n * Reads the handshake's `auth.qd`. Protocol 5 is served. A client without\n * `auth.qd` is a 4.x client: the legacy shim serves it when `legacyWire` is\n * on, and otherwise it is refused, like a client that names another protocol\n * or sends a malformed `qd`, with `{ code: \"PROTOCOL_MISMATCH\", expected: 5 }`\n * as the `connect_error` data.\n */\nexport function protocolMiddleware(\n legacyWire: boolean,\n context: Pick<SocketContext, \"logger\">,\n): (socket: QuickdrawServerSocket, next: Next) => void {\n return (socket, next) => {\n const auth: unknown = socket.handshake.auth;\n const qd =\n typeof auth === \"object\" && auth !== null ? (auth as { qd?: unknown }).qd : undefined;\n if (isQdHandshake(qd) && qd.protocol === PROTOCOL_VERSION) {\n socket.data.protocol = PROTOCOL_VERSION;\n socket.data.client = qd.client;\n next();\n return;\n }\n if (qd === undefined && legacyWire) {\n socket.data.protocol = \"legacy\";\n next();\n return;\n }\n const spoke = qd === undefined ? \"a 4.x client (no auth.qd)\" : \"another protocol\";\n context.logger.debug(`Refused a socket that speaks ${spoke}`, {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n });\n next(refusal(`This server speaks quickdraw protocol ${PROTOCOL_VERSION}`, MISMATCH));\n };\n}\n\n/**\n * Authenticates the socket and keeps its principal on `socket.data`. A\n * failure refuses the connection with \"Authentication failed\", as 4.1 did,\n * and `{ code: \"UNAUTHENTICATED\" }` as the `connect_error` data, so a client\n * can tell it from a protocol mismatch. A refusal `authenticate` makes on\n * purpose, by throwing a `QuickdrawError` with that code (a revoked session,\n * say), is the client's doing and logs at debug; any other failure at error.\n */\nexport function authMiddleware(\n resolvePrincipal: ResolvePrincipal,\n context: Pick<SocketContext, \"logger\">,\n): (socket: QuickdrawServerSocket, next: Next) => void {\n return (socket, next) => {\n const request = {\n transport: \"socket\",\n auth: socket.handshake.auth as Readonly<Record<string, unknown>>,\n headers: socket.handshake.headers,\n socket,\n } as const;\n resolvePrincipal(request).then(\n (principal) => {\n socket.data.principal = principal;\n next();\n },\n (error: unknown) => {\n const level = isRefusal(error) ? \"debug\" : \"error\";\n context.logger[level](\"Socket authentication failed\", {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n error: describeError(error),\n });\n next(refusal(\"Authentication failed\", UNAUTHENTICATED));\n },\n );\n };\n}\n\n/** The socket rate limiter's options, as `createServer` takes them. */\nexport type SocketRateLimitOptions = Omit<RateLimitOptions, \"logger\" | \"ackPayload\">;\n\n/**\n * Events the limiter never counts: channel messages, which carry their own\n * per-socket token buckets; cancellations, since dropping one only keeps a\n * call running; entity subscriptions, which a page sends once per row it\n * mounts in batches of up to 500 ids, so a board of sixty rows would trip the\n * limiter; collection subscriptions, which a page sends once per list it\n * mounts and again to page through it, and item loads, which a board holding\n * a scope's index sends per window of up to 200 ids; topic watches, which a\n * page sends once per watching query it mounts; and stream subscriptions,\n * which a page sends once per feed it shows (RFC 0003 section 3). The ones\n * that read or authorize (`qd:sub`, `qd:col:sub`, `qd:col:items`,\n * `qd:watch`, `qd:stream:sub`) run in each socket's lane of subscription\n * work instead (`emit/lane.ts`, `limits.subscriptions`).\n */\nconst UNLIMITED_EVENTS: readonly string[] = [\n CLIENT_EVENTS.channel,\n CLIENT_EVENTS.cancel,\n CLIENT_EVENTS.sub,\n CLIENT_EVENTS.unsub,\n CLIENT_EVENTS.collectionSub,\n CLIENT_EVENTS.collectionUnsub,\n CLIENT_EVENTS.collectionItems,\n CLIENT_EVENTS.watch,\n CLIENT_EVENTS.unwatch,\n CLIENT_EVENTS.streamSub,\n CLIENT_EVENTS.streamUnsub,\n];\n\nfunction rateLimited(retryAfterMs: number): Failure {\n return {\n ok: false,\n e: { code: \"RATE_LIMITED\", message: \"Rate limit exceeded\", data: { retryAfterMs } },\n };\n}\n\nfunction isLegacy(socket: { readonly data: unknown }): boolean {\n return (socket.data as Partial<QuickdrawServerSocket[\"data\"]>).protocol === \"legacy\";\n}\n\n/** 4.1's default notice, which 4.x clients listen for; v5 clients read the acknowledgement instead. */\nfunction noticeForLegacyClients(\n limiter: RateLimiter,\n options: SocketRateLimitOptions,\n): NonNullable<RateLimitOptions[\"onRateLimitExceeded\"]> {\n const keyOf = options.keyGenerator ?? ((socket) => socket.id);\n return (socket, eventName) => {\n if (isLegacy(socket)) {\n socket.emit(\"error\", {\n code: \"RATE_LIMITED\",\n message: `Rate limit exceeded for event: ${eventName}`,\n retryAfter: limiter.getResetTime(keyOf(socket, eventName)),\n });\n }\n };\n}\n\n/** What the socket rate limiter is given: the logger, and the dispatcher's loop watch. */\nexport interface SocketLimitContext extends Pick<SocketContext, \"logger\"> {\n /** Counts each refusal, and warns in development when one socket keeps getting refused. */\n readonly loops?: Pick<LoopWatch, \"refused\">;\n}\n\n/**\n * Applies the socket rate limiter, answering a dropped call in its client's\n * reply shape. Each refusal is counted by the dispatcher's loop watch\n * (`../devWarnings.ts`).\n */\nexport function applySocketRateLimit(\n io: QuickdrawIo,\n options: SocketRateLimitOptions,\n context: SocketLimitContext,\n): void {\n const limiter = createRateLimiter({\n ...options,\n excludeEvents: [...UNLIMITED_EVENTS, ...(options.excludeEvents ?? [])],\n });\n const notice = options.onRateLimitExceeded ?? noticeForLegacyClients(limiter, options);\n applyRateLimitMiddleware(io, limiter, {\n logger: context.logger,\n keyGenerator: options.keyGenerator,\n onRateLimitExceeded: (socket, eventName) => {\n context.loops?.refused(socket.id, eventName);\n notice(socket, eventName);\n },\n ackPayload: (socket, _eventName, retryAfterMs) =>\n isLegacy(socket)\n ? legacyFailure(\"RATE_LIMITED\", \"Rate limit exceeded\")\n : rateLimited(retryAfterMs),\n });\n}\n","// The Valkey (or Redis) clients of a node's Socket.IO Redis adapter, when\n// their connection drops and comes back (the pack H finale review):\n//\n// - while the subscribing client is disconnected, nothing other nodes\n// publish reaches this node: their frames to its sockets are gone, and\n// Valkey does not keep them. So when that client is ready again, this\n// node's sockets get `qd:rotate` with a window of `RESYNC_WITHIN_MS`: each\n// client reconnects at a random moment within it and subscribes again,\n// holding its revisions, and behind a cluster a subscription always reads\n// (a collection resume reads a page), so it catches up;\n// - the adapter publishes without waiting for the result, and node-redis 5\n// and later reject a command that waited in the queue of a disconnected\n// client past their command timeout (5 seconds): an outage longer than\n// that would turn every frame published meanwhile into an unhandled\n// rejection, which ends a Node process by default. A failed publish is\n// logged once per outage instead (the other nodes miss that message; their\n// own subscriptions coming back re-sync their clients the same way).\n//\n// Both wirings are watched: an adapter given as `socket.adapter`, from\n// `createServer`, and `setupRedisAdapter`'s, once it is set. An adapter an\n// app sets later with `io.adapter(...)` itself is not.\n\nimport type { Logger } from \"../../contract/logger\";\nimport { SERVER_EVENTS } from \"../../contract/names\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { QuickdrawIo } from \"../transports/types\";\n\n/** The window this node's clients reconnect within once its Valkey subscription is back. */\nexport const RESYNC_WITHIN_MS = 2000;\n\ninterface Emitter {\n on(event: string, listener: (...args: unknown[]) => void): unknown;\n}\n\nfunction isEmitter(value: unknown): value is Emitter {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { readonly on?: unknown }).on === \"function\"\n );\n}\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { readonly then?: unknown }).then === \"function\"\n );\n}\n\n/** Clients already watched: a server and `setupRedisAdapter` may both find one. */\nconst watched = new WeakSet<object>();\n\n/** Sends this node's sockets `qd:rotate` each time the subscribing client is ready again. */\nfunction resyncOnReady(io: QuickdrawIo, subClient: Emitter, logger: Logger): void {\n subClient.on(\"ready\", () => {\n logger.info(\n \"This node's Valkey subscription is back; its clients reconnect to catch up on what it missed\",\n { category: \"quickdraw.cluster\", withinMs: RESYNC_WITHIN_MS },\n );\n io.local.emit(SERVER_EVENTS.rotate, { withinMs: RESYNC_WITHIN_MS });\n });\n}\n\n/** Logs a publish the client failed, once per outage, instead of leaving its rejection unhandled. */\nfunction guardPublishes(pubClient: object, logger: Logger): void {\n const target = pubClient as { publish?: unknown };\n const publish = target.publish;\n if (typeof publish !== \"function\") {\n return;\n }\n let reported = false;\n target.publish = function guardedPublish(this: unknown, ...args: unknown[]): unknown {\n const sent: unknown = Reflect.apply(publish, this, args);\n if (isThenable(sent)) {\n sent.then(undefined, (error: unknown) => {\n if (!reported) {\n reported = true;\n logger.warn(\n \"Valkey did not take a message for the other nodes in time; it was dropped, and they catch up once their own subscriptions are back\",\n { category: \"quickdraw.cluster\", error: describeError(error) },\n );\n }\n });\n }\n return sent;\n };\n if (isEmitter(pubClient)) {\n pubClient.on(\"ready\", () => {\n reported = false;\n });\n }\n}\n\n/**\n * Watches the clients of `io`'s Socket.IO Redis adapter, when it has one\n * (`pubClient` and `subClient`): a subscription that comes back re-syncs\n * this node's sockets, and a failed publish is logged, not left unhandled.\n * Does nothing for another adapter, and watches a client once.\n */\nexport function watchAdapterClients(io: QuickdrawIo, logger: Logger): void {\n const adapter = io.sockets.adapter as {\n readonly pubClient?: unknown;\n readonly subClient?: unknown;\n };\n const { pubClient, subClient } = adapter;\n if (isEmitter(subClient) && !watched.has(subClient)) {\n watched.add(subClient);\n resyncOnReady(io, subClient, logger);\n }\n if (typeof pubClient === \"object\" && pubClient !== null && !watched.has(pubClient)) {\n watched.add(pubClient);\n guardPublishes(pubClient, logger);\n }\n}\n","// Answered broadcasts to the other nodes of a cluster (the pack H finale\n// review): an access change, or a user's reloaded grants, is broadcast and\n// waited for until every other node has applied it, so the flush that caused\n// it sends its frames only once no node still holds what it revoked.\n//\n// That wait is in line with the node's flushes: they run one after another\n// (`../uow/flush.ts`), so every flush behind an access change waits with it.\n// A node that does not answer (frozen, killed without its Valkey connection\n// closing yet, an old version during a rolling deploy) would put\n// `cluster.timeoutMs` on every access-changing flush, and Valkey down would\n// hold even the frames to a node's own sockets. So:\n//\n// - while the publishing client is not connected, nothing waits: the\n// broadcast is sent unanswered (it waits in the client's queue);\n// - after one broadcast was not answered in time, broadcasts stop waiting\n// (one error logged, \"degraded\"), and a probe is broadcast every second\n// until every node answers one, which ends it (one info logged).\n//\n// Broadcasts sent unanswered stay fail-open, as a timed-out wait always was:\n// a slower node may hold a revoked socket in a room until it applies the\n// change, and that socket may get the flush's frames meanwhile.\n\nimport type { Logger } from \"../../contract/logger\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { QuickdrawIo } from \"../transports/types\";\nimport { answerOf, DEFAULT_CLUSTER_TIMEOUT_MS, within } from \"./acks\";\nimport { watchAdapterClients } from \"./adapterClients\";\nimport { clusterClientOf } from \"./counter\";\n\n/** The server-to-server event a degraded node probes the others with; each answers it at once. */\nexport const PROBE_EVENT = \"quickdraw:probe\";\n\n/** How often a degraded node probes the others. */\nexport const PROBE_MS = 1000;\n\n/** A node's answered broadcasts to the rest of its cluster. */\nexport interface ClusterBroadcasts {\n /**\n * Broadcasts `event` with `payload` and resolves once every other node\n * answered, at most `timeoutMs`; at once, unanswered, while the publishing\n * client is not connected or the broadcasts are degraded.\n */\n broadcast(event: string, payload: unknown): Promise<void>;\n /** True while broadcasts do not wait for answers. */\n degraded(): boolean;\n /** Stops probing: the server closes. */\n close(): void;\n}\n\n/** Options of {@link createClusterBroadcasts}. */\nexport interface ClusterBroadcastsOptions {\n readonly io: QuickdrawIo;\n readonly logger: Logger;\n /** How long a broadcast waits for every node's answer. Default 1,000. */\n readonly timeoutMs?: number;\n /** How often a degraded node probes. Default {@link PROBE_MS}; tests pass their own. */\n readonly probeMs?: number;\n}\n\n/** False while the adapter's publishing client says it is not connected. */\nfunction publisherReady(io: QuickdrawIo): boolean {\n const adapter = io.sockets.adapter as { readonly pubClient?: unknown };\n return clusterClientOf(adapter.pubClient)?.isReady !== false;\n}\n\n/** Creates the answered broadcasts of the server `io`. */\nexport function createClusterBroadcasts(options: ClusterBroadcastsOptions): ClusterBroadcasts {\n const { io, logger } = options;\n const timeoutMs = options.timeoutMs ?? DEFAULT_CLUSTER_TIMEOUT_MS;\n const probeMs = options.probeMs ?? PROBE_MS;\n let down = false;\n let probing = false;\n let closed = false;\n let timer: ReturnType<typeof setInterval> | undefined;\n\n const stopProbing = (): void => {\n clearInterval(timer);\n timer = undefined;\n };\n\n const probe = async (): Promise<void> => {\n if (probing || !publisherReady(io)) {\n return;\n }\n probing = true;\n try {\n await within(io.serverSideEmitWithAck(PROBE_EVENT), timeoutMs);\n if (down) {\n down = false;\n stopProbing();\n logger.info(\"Every node answers broadcasts again; access changes wait for them again\", {\n category: \"quickdraw.cluster\",\n });\n }\n } catch {\n // Still degraded: the next probe tries again.\n } finally {\n probing = false;\n }\n };\n\n const degrade = (error: unknown): void => {\n if (down) {\n return;\n }\n down = true;\n logger.error(\n \"A node did not answer a broadcast in time; this node sends access changes without waiting for the other nodes until every node answers a probe\",\n { category: \"quickdraw.cluster\", timeoutMs, error: describeError(error) },\n );\n if (!closed) {\n timer = setInterval(() => {\n void probe();\n }, probeMs);\n timer.unref?.();\n }\n };\n\n return Object.freeze({\n async broadcast(event: string, payload: unknown): Promise<void> {\n if (down || !publisherReady(io)) {\n io.serverSideEmit(event, payload);\n return;\n }\n try {\n await within(io.serverSideEmitWithAck(event, payload), timeoutMs);\n } catch (error) {\n degrade(error);\n }\n },\n degraded: () => down,\n close(): void {\n closed = true;\n stopProbing();\n },\n });\n}\n\n/** Answers other nodes' probes on `io`: at once, as a node that is up does. */\nexport function answerProbes(io: QuickdrawIo): void {\n io.on(PROBE_EVENT, (...rest: unknown[]) => {\n answerOf(rest)(true);\n });\n}\n\n/**\n * What a server keeps with the other nodes of its cluster: its answered\n * broadcasts, its answers to their probes, and a watch on its adapter's\n * Valkey clients (`./adapterClients.ts`).\n */\nexport function serveBroadcasts(\n io: QuickdrawIo,\n logger: Logger,\n timeoutMs: number | undefined,\n): ClusterBroadcasts {\n answerProbes(io);\n watchAdapterClients(io, logger);\n return createClusterBroadcasts({ io, logger, timeoutMs });\n}\n","// What a quickdraw server pushes on the app's request, and how the other\n// nodes of a cluster hear of it (RFC 0003 sections 4.4 and 8.3):\n//\n// - `qd:rotate`: every client reconnects within a jitter window;\n// - `server.access.refresh(userId)`: the user's grants are reloaded, put in\n// the principal of their sockets, sent to them as `qd:access`, and their\n// entity subscriptions are resolved again (a lost `Admin` grant can end\n// them). Behind a cluster adapter the reloaded grants are broadcast, so\n// every node updates its own sockets of the user;\n// - `server.access.disconnectUser(userId, { sessionId? })`: the user's\n// sockets (of one session) are disconnected, on every node.\n//\n// The adapter probe tells the live data whether rooms are local: true while\n// the server runs the in-memory adapter it was created with.\n\nimport type { Logger } from \"../../contract/logger\";\nimport { SERVER_EVENTS, userRoom } from \"../../contract/names\";\nimport { answerOf } from \"../cluster/acks\";\nimport type { ClusterBroadcasts } from \"../cluster/broadcasts\";\nimport type { ClusterOptions } from \"../cluster/revisions\";\nimport type { AdapterProbe } from \"../emit/hub\";\nimport { describeError } from \"../pipeline/metrics\";\nimport { socketSessionOf, type ServerAuth, type ServiceGrants } from \"./auth\";\nimport type { SocketExtension } from \"./socketio\";\nimport type { QuickdrawIo } from \"./types\";\n\nexport type { ClusterOptions } from \"../cluster/revisions\";\nexport { serveBroadcasts } from \"../cluster/broadcasts\";\n\n/** The server-to-server event reloaded grants are broadcast on behind a cluster adapter. */\nexport const GRANTS_EVENT = \"quickdraw:grants\";\n\n/** The server-to-server event `server.access.disconnectUser` is broadcast on behind a cluster adapter. */\nexport const DISCONNECT_USER_EVENT = \"quickdraw:disconnect-user\";\n\n/** Options of `server.access.disconnectUser`. */\nexport interface DisconnectUserOptions {\n /** End only the sockets that authenticated with this session (`recordSocketSession`). */\n readonly sessionId?: string;\n /** Why, for the log. */\n readonly reason?: string;\n}\n\n/** What the socket server needs of its dispatcher's live data (`emit/live.ts`). */\nexport interface LiveData {\n readonly extension: SocketExtension;\n attach(\n io: QuickdrawIo,\n probe: AdapterProbe,\n cluster?: ClusterOptions,\n broadcasts?: ClusterBroadcasts,\n ): void;\n regranted(userId: string): Promise<void>;\n}\n\n/**\n * The adapter probe of `io`: local while the server's adapter is the\n * in-memory one it was created with. An adapter given in the Socket.IO\n * options (`configured`) counts as a cluster adapter, like one an app sets\n * later with `io.adapter(...)` (`setupRedisAdapter`).\n */\nexport function adapterProbe(io: QuickdrawIo, configured: boolean): AdapterProbe {\n const initial = configured ? undefined : io.adapter();\n return Object.freeze({ local: () => initial !== undefined && io.adapter() === initial });\n}\n\n/** Sends `qd:rotate` to every client. */\nexport function rotate(io: QuickdrawIo, withinMs: number): void {\n if (typeof withinMs !== \"number\" || !Number.isFinite(withinMs) || withinMs < 0) {\n throw new TypeError(\"rotate: withinMs must be a number of milliseconds, 0 or more\");\n }\n io.emit(SERVER_EVENTS.rotate, { withinMs });\n}\n\nconst REGRANTS = new WeakMap<object, number>();\n\n/**\n * How many times this process applied new grants to a user of the server\n * `io` serves (`access.refresh`, a written grant, another node's broadcast):\n * the server's in-process callers load the grants they hold again once it\n * rises (`../caller.ts`).\n */\nexport function regrantsOf(io: object): number {\n return REGRANTS.get(io) ?? 0;\n}\n\n/** Puts `serviceAccess` in the principal of this process's sockets of `userId`. */\nfunction regrant(io: QuickdrawIo, userId: string, serviceAccess: ServiceGrants): void {\n REGRANTS.set(io, regrantsOf(io) + 1);\n for (const socketId of io.sockets.adapter.rooms.get(userRoom(userId)) ?? []) {\n const socket = io.sockets.sockets.get(socketId);\n const principal = socket?.data.principal;\n if (socket !== undefined && principal?.userId === userId) {\n socket.data.principal = { ...principal, serviceAccess };\n }\n }\n}\n\n/** Disconnects this process's sockets of `userId` (of one session, with `sessionId`); returns how many. */\nfunction disconnectHere(io: QuickdrawIo, userId: string, sessionId: string | undefined): number {\n let ended = 0;\n for (const socketId of [...(io.sockets.adapter.rooms.get(userRoom(userId)) ?? [])]) {\n const socket = io.sockets.sockets.get(socketId);\n const own = socket?.data.principal?.userId === userId;\n if (\n socket !== undefined &&\n own &&\n (sessionId === undefined || socketSessionOf(socket) === sessionId)\n ) {\n socket.disconnect(true);\n ended += 1;\n }\n }\n return ended;\n}\n\n/** A broadcast `disconnectUser`, read; `undefined` for anything else. */\nfunction readDisconnect(\n value: unknown,\n): { readonly userId: string; readonly sessionId: string | undefined } | undefined {\n const { userId, sessionId } = (value ?? {}) as {\n readonly userId?: unknown;\n readonly sessionId?: unknown;\n };\n if (typeof userId !== \"string\" || userId.length === 0) {\n return undefined;\n }\n return { userId, sessionId: typeof sessionId === \"string\" ? sessionId : undefined };\n}\n\n/**\n * `server.access.disconnectUser(userId, options)`: disconnects every socket\n * of the user on this node (only those of one session with `sessionId`), and,\n * behind a cluster adapter, tells every other node to do the same. For a\n * session the app revoked (`createAuthRoutes`' `onRevoke`): a socket keeps\n * the principal it authenticated with until it reconnects, and its\n * reconnect is authenticated afresh. Returns how many sockets this node ended.\n */\nexport function disconnectUser(\n io: QuickdrawIo,\n probe: AdapterProbe,\n logger: Logger,\n userId: string,\n options: DisconnectUserOptions = {},\n): number {\n if (typeof userId !== \"string\" || userId.length === 0) {\n throw new TypeError(\"access.disconnectUser: pass the user's id\");\n }\n const { sessionId, reason } = options;\n if (!probe.local()) {\n io.serverSideEmit(\n DISCONNECT_USER_EVENT,\n sessionId === undefined ? { userId } : { userId, sessionId },\n );\n }\n const ended = disconnectHere(io, userId, sessionId);\n logger.info(\"Disconnected a user's sockets\", {\n category: \"quickdraw.socket\",\n userId,\n sockets: ended,\n ...(sessionId === undefined ? {} : { sessionId }),\n ...(reason === undefined ? {} : { reason }),\n });\n return ended;\n}\n\n/** Listens for `disconnectUser` broadcasts from other nodes, and ends this node's sockets they name. */\nexport function listenForDisconnects(io: QuickdrawIo): void {\n io.on(DISCONNECT_USER_EVENT, (broadcast: unknown) => {\n const request = readDisconnect(broadcast);\n if (request !== undefined) {\n disconnectHere(io, request.userId, request.sessionId);\n }\n });\n}\n\n/**\n * Listens for grants other nodes reloaded, and applies them to this node's\n * sockets; the node that reloaded them waits for the answer, sent once this\n * node's subscriptions of the user are resolved again.\n */\nexport function listenForGrants(io: QuickdrawIo, live: LiveData | undefined, logger: Logger): void {\n io.on(GRANTS_EVENT, (broadcast: unknown, ...rest: unknown[]) => {\n const answer = answerOf(rest);\n const { userId, serviceAccess } = (broadcast ?? {}) as {\n readonly userId?: unknown;\n readonly serviceAccess?: unknown;\n };\n const grants = typeof serviceAccess === \"object\" && serviceAccess !== null;\n if (typeof userId !== \"string\" || userId.length === 0 || !grants) {\n answer(false);\n return;\n }\n regrant(io, userId, serviceAccess as ServiceGrants);\n (live?.regranted(userId) ?? Promise.resolve()).then(\n () => answer(true),\n (error: unknown) => {\n answer(false);\n logger.error(\"Resolving the subscriptions of a user another node regranted failed\", {\n category: \"quickdraw.access\",\n userId,\n error: describeError(error),\n });\n },\n );\n });\n}\n\n/** What `refreshGrants` works with besides the user. */\nexport interface GrantsContext {\n readonly io: QuickdrawIo;\n readonly load: ServerAuth[\"loadServiceAccess\"];\n readonly live: LiveData | undefined;\n readonly probe: AdapterProbe;\n /** Sends the reloaded grants to the other nodes, behind a cluster adapter. */\n readonly broadcasts: ClusterBroadcasts;\n}\n\n/**\n * `server.access.refresh(userId)`: reloads the user's grants, applies them on\n * every node (broadcast behind a cluster adapter, resolving once every node\n * applied them, at most `cluster.timeoutMs`, and without waiting while the\n * broadcasts are degraded: `../cluster/broadcasts.ts`), sends them to the\n * user's sockets as `qd:access`, and resolves this node's subscriptions of\n * the user again.\n */\nexport async function refreshGrants(\n context: GrantsContext,\n userId: string,\n): Promise<ServiceGrants> {\n const { io, load, live, probe } = context;\n if (load === undefined) {\n throw new TypeError(\"access.refresh needs auth.loadServiceAccess to reload a user's grants\");\n }\n const serviceAccess = (await load(userId)) ?? {};\n const others = probe.local()\n ? undefined\n : context.broadcasts.broadcast(GRANTS_EVENT, { userId, serviceAccess });\n regrant(io, userId, serviceAccess);\n io.to(userRoom(userId)).emit(SERVER_EVENTS.access, { serviceAccess });\n await Promise.all([others, live?.regranted(userId)]);\n return serviceAccess;\n}\n","// The Socket.IO transport (RFC 0003 sections 8 and 10). A v5 socket gets a\n// fixed set of listeners, whatever the number of services and methods:\n// `qd:call` and `qd:cancel` here, plus one per event from each registered\n// `SocketExtension`. 4.1 registered one listener per method, and five more per\n// service, on every socket (4.1 `src/server/ServiceRegistry.ts:118-136`).\n//\n// A call becomes one `DispatchRequest`: the connection is the socket, so its\n// queries share the socket's concurrency lane; `qd:cancel` and a disconnect\n// abort the call's signal; the reply goes out through the acknowledgement,\n// written from a shared run's encoded copy when there is one, and its size\n// comes back from the parser.\n\nimport { CLIENT_EVENTS, SERVER_EVENTS, userRoom } from \"../../contract/names\";\nimport { isCallEnvelope, isCancel, type CallId } from \"../../protocol/envelope\";\nimport { toWire } from \"../../protocol/errors\";\nimport type { HelloFrame } from \"../../protocol/version\";\nimport { describeError } from \"../pipeline/metrics\";\nimport type { Principal } from \"../types\";\nimport {\n acknowledge,\n callAcknowledgement,\n INTERNAL_FAILURE,\n unreadable,\n type Acknowledge,\n} from \"./ack\";\nimport { attachLegacyShim, type LegacyCallers } from \"./legacy\";\nimport type { QuickdrawServerSocket, SocketContext } from \"./types\";\n\n/**\n * Adds listeners to every v5 socket, after `qd:call` and `qd:cancel`. This is\n * the registration hook for the entity, collection, watch, stream and channel\n * events that later packs serve: an extension registers one listener per\n * event, never one per method or service, and routes by the frame's fields.\n */\nexport type SocketExtension = (socket: QuickdrawServerSocket, context: SocketContext) => void;\n\n/** The part of `qd:hello` every socket of a server shares: all but who the socket acts for. */\nexport type ServerHello = Omit<HelloFrame, \"userId\" | \"serviceAccess\">;\n\n/** The connection handler's settings. */\nexport interface ConnectionSettings extends SocketContext {\n /**\n * Sent to every v5 socket once its listeners are in place, with the\n * socket's user id and service grants added.\n */\n readonly hello: ServerHello;\n readonly extensions: readonly SocketExtension[];\n /** The 4.x callers already logged, shared by every socket of the server. */\n readonly legacyCallers: LegacyCallers;\n}\n\ntype Calls = Map<CallId, AbortController>;\n\nconst MALFORMED_CALL = \"A qd:call frame needs { id, s, m, i?, v? } and an acknowledgement\";\n\nfunction reply(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n ack: Acknowledge,\n message: unknown,\n): number | undefined {\n return acknowledge(context.meter, ack, message, INTERNAL_FAILURE, (error) => {\n context.logger.error(\"A call's reply could not be encoded; it was answered with INTERNAL\", {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n error: describeError(error),\n });\n });\n}\n\nfunction startCall(\n socket: QuickdrawServerSocket,\n context: SocketContext,\n calls: Calls,\n envelope: unknown,\n ack: Acknowledge,\n): void {\n if (!isCallEnvelope(envelope)) {\n reply(socket, context, ack, { ok: false, e: toWire(unreadable(MALFORMED_CALL)) });\n return;\n }\n const { id } = envelope;\n if (calls.has(id)) {\n const duplicate = unreadable(`Call ${id} is already in flight on this socket`, [\"id\"]);\n reply(socket, context, ack, { ok: false, e: toWire(duplicate) });\n return;\n }\n const controller = new AbortController();\n calls.set(id, controller);\n // Freed before the reply goes out, so the client may reuse the id at once.\n const release = (): void => {\n if (calls.get(id) === controller) {\n calls.delete(id);\n }\n };\n void context.dispatcher\n .call({\n service: envelope.s,\n method: envelope.m,\n input: envelope.i,\n principal: socket.data.principal,\n transport: \"socket\",\n connectionId: socket.id,\n signal: controller.signal,\n v: envelope.v,\n respond: (result, shared) => {\n release();\n return reply(socket, context, ack, callAcknowledgement(context.meter, result, shared));\n },\n })\n .then(release, (error: unknown) => {\n // The reply went out already; only a strict test app's warning gets here.\n release();\n context.logger.error(\"A call failed after its reply was sent\", {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n error: describeError(error),\n });\n });\n}\n\n/** Registers `qd:call` and `qd:cancel` on a v5 socket, and cancels its calls when it disconnects. */\nexport function attachCallListeners(socket: QuickdrawServerSocket, context: SocketContext): void {\n const calls: Calls = new Map();\n socket.on(CLIENT_EVENTS.call, (envelope: unknown, ack: unknown) => {\n if (typeof ack !== \"function\") {\n context.logger.debug(\"Ignored a qd:call sent without an acknowledgement\", {\n category: \"quickdraw.socket\",\n socketId: socket.id,\n });\n return;\n }\n startCall(socket, context, calls, envelope, ack as Acknowledge);\n });\n socket.on(CLIENT_EVENTS.cancel, (frame: unknown) => {\n if (isCancel(frame)) {\n calls.get(frame.id)?.abort();\n }\n });\n socket.on(\"disconnect\", () => {\n for (const controller of calls.values()) {\n controller.abort();\n }\n calls.clear();\n });\n}\n\n/**\n * The server's `connection` handler: joins the socket's user room, then\n * gives a v5 socket its listeners and `qd:hello`, or a 4.x socket the legacy\n * shim. Only sockets the handshake middleware admitted get here.\n */\nexport function onConnection(\n settings: ConnectionSettings,\n): (socket: QuickdrawServerSocket) => void {\n return (socket) => {\n const { principal } = socket.data;\n if (principal !== null) {\n void socket.join(userRoom(principal.userId));\n }\n if (socket.data.protocol === \"legacy\") {\n attachLegacyShim(socket, settings, settings.legacyCallers);\n return;\n }\n attachCallListeners(socket, settings);\n for (const extension of settings.extensions) {\n extension(socket, settings);\n }\n socket.emit(SERVER_EVENTS.hello, helloFor(settings.hello, principal));\n };\n}\n\n/** The `qd:hello` of a socket acting for `principal`: the server's part, its user id and its grants. */\nfunction helloFor(hello: ServerHello, principal: Principal | null): HelloFrame {\n return {\n ...hello,\n userId: principal?.userId ?? null,\n serviceAccess: principal?.serviceAccess ?? {},\n };\n}\n"],"mappings":"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","names":["isIdList","isRecord","target","fail","projection","isRecord","where","filtered","isRecord","added","where","memoized","target","where","target","reply","checkName","failure","answer","target","room","target","target","serviceOf","count","target","where","write","fail","target","write","WHOLE","WHOLE","readRows","write","before","where","changed","write","write","reply","send","target","answer","DEFAULT_MAX_ENTRIES","keyOf","isRecord","isName","anchorsOf","NONE","readRows","target","answer","anchorsOf","allowed","subscribe","allowed","target","where","filtered","readRows","forbidden","anchorsOf","allowed","isOwn","join","releaseTaken","accessMoved","recheckAccess","settleRaces","allowedScopes","allowed","isRecord","send","checkRoom","run","leave","target","checkRoom","answer","join","checkRoom","target","run","refuse","target","reauthorize","reauthorizeAll","target","run","changed","write","watched","send","isName","groupOf","NONE","next","targetOf","anchorsNow","target","targetOf","WHOLE","targetOf","target","send","isRecord","readSubscribe","target","subscribe","target","revoke","anchorsOf","forget","answer","target","fail","registerInterest","write","add","resolveAccess","target","resolveAccess","run","target","target","run","lookup","target","target","release","run","lookup","send","fail","targetOf","forbidden","target","fail","expire","targetOf","target","serve","release","keyOf","isThenable","target","answer","reply","startCall","release","notFound"]}