@korajs/server 1.0.0-beta.11 → 1.0.0-beta.13

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../src/store/server-backup.ts","../src/index.ts","../src/logging/structured-logger.ts","../src/apply/rejection-taxonomy.ts","../src/store/memory-server-store.ts","../src/store/materialization.ts","../src/store/postgres-server-store.ts","../src/store/drizzle-pg-schema.ts","../src/store/sqlite-server-store.ts","../src/store/drizzle-schema.ts","../src/transport/http-server-transport.ts","../src/transport/ws-server-transport.ts","../src/session/client-session.ts","../src/apply/apply-server-operation.ts","../src/constraints/operation-constraint-validator.ts","../src/constraints/server-constraint-context.ts","../src/constraints/server-referential-context.ts","../src/apply/server-side-effect-operation.ts","../src/auth/no-auth.ts","../src/scopes/resolve-session-scopes.ts","../src/scopes/server-scope-filter.ts","../src/session/operation-validation.ts","../src/session/session-operation-limits.ts","../src/server/kora-sync-server.ts","../src/awareness/awareness-relay.ts","../src/diagnostics/server-metrics-collector.ts","../src/richtext/blob-chunk-relay.ts","../src/richtext/yjs-doc-relay.ts","../src/server/route-context.ts","../src/apply/route-predicate.ts","../src/auth/token-auth.ts","../src/auth/kora-auth-provider.ts","../src/auth/mixed-auth-provider.ts","../src/server/create-server.ts","../src/server/production-server.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import type { Operation } from '@korajs/core'\n\n/**\n * Server-side backup format: same portable section-based format as the client.\n *\n * Sections:\n * manifest — metadata (version, nodeId, operationCount, checksum)\n * version_vector — nodeId → maxSequenceNumber\n * operations — NDJSON of full Operation objects\n * checksum — SHA-256 of all content sections\n */\n\nconst BACKUP_VERSION = 1\n\nfunction encodeSection(name: string, content: Uint8Array): Uint8Array {\n\tconst nameBytes = new TextEncoder().encode(name)\n\tconst header = new Uint8Array(8)\n\tconst dv = new DataView(header.buffer)\n\tdv.setUint32(0, nameBytes.length, true)\n\tdv.setUint32(4, content.length, true)\n\n\tconst result = new Uint8Array(header.length + nameBytes.length + content.length)\n\tresult.set(header, 0)\n\tresult.set(nameBytes, 8)\n\tresult.set(content, 8 + nameBytes.length)\n\treturn result\n}\n\nfunction encodeJsonSection(name: string, data: unknown): Uint8Array {\n\treturn encodeSection(name, new TextEncoder().encode(JSON.stringify(data)))\n}\n\ninterface Section {\n\tname: string\n\tcontent: Uint8Array\n}\n\nfunction parseSections(data: Uint8Array): Section[] {\n\tconst sections: Section[] = []\n\tconst dv = new DataView(data.buffer, data.byteOffset, data.byteLength)\n\tlet offset = 0\n\n\twhile (offset + 8 <= data.byteLength) {\n\t\tconst nameLen = dv.getUint32(offset, true)\n\t\tconst contentLen = dv.getUint32(offset + 4, true)\n\t\toffset += 8\n\n\t\tif (offset + nameLen + contentLen > data.byteLength) break\n\n\t\tconst name = new TextDecoder().decode(data.slice(offset, offset + nameLen))\n\t\toffset += nameLen\n\n\t\tconst content = data.slice(offset, offset + contentLen)\n\t\toffset += contentLen\n\n\t\tsections.push({ name, content })\n\t}\n\n\treturn sections\n}\n\nfunction findSection(sections: Section[], name: string): Uint8Array | null {\n\tfor (const s of sections) {\n\t\tif (s.name === name) return s.content\n\t}\n\treturn null\n}\n\nfunction parseJsonSection<T>(sections: Section[], name: string): T | null {\n\tconst content = findSection(sections, name)\n\tif (!content) return null\n\treturn JSON.parse(new TextDecoder().decode(content)) as T\n}\n\nasync function computeSha256(data: Uint8Array): Promise<string> {\n\tconst digestInput = new Uint8Array(data)\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', digestInput)\n\tconst hashArray = Array.from(new Uint8Array(hashBuffer))\n\treturn hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/**\n * Build a backup binary from server store data.\n */\nexport async function buildServerBackup(\n\tnodeId: string,\n\toperations: Operation[],\n\tversionVector: Map<string, number>,\n): Promise<Uint8Array> {\n\tconst sections: Uint8Array[] = []\n\tlet allContentForChecksum = new Uint8Array(0)\n\n\tconst addSection = (name: string, data: Uint8Array) => {\n\t\tsections.push(data)\n\t\tconst newLen = allContentForChecksum.length + data.length\n\t\tconst combined = new Uint8Array(newLen)\n\t\tcombined.set(allContentForChecksum, 0)\n\t\tcombined.set(data, allContentForChecksum.length)\n\t\tallContentForChecksum = combined\n\t}\n\n\t// Version vector\n\tconst vvObj: Record<string, number> = {}\n\tfor (const [nid, seq] of versionVector) {\n\t\tvvObj[nid] = seq\n\t}\n\taddSection('version_vector', encodeJsonSection('version_vector', vvObj))\n\n\t// Operations\n\tconst opLines = `${operations.map((op) => JSON.stringify(op)).join('\\n')}\\n`\n\taddSection('operations', encodeSection('operations', new TextEncoder().encode(opLines)))\n\n\t// Checksum\n\tconst checksumHex = await computeSha256(allContentForChecksum)\n\n\t// Manifest\n\tconst manifest = {\n\t\tversion: BACKUP_VERSION,\n\t\tcreatedAt: Date.now(),\n\t\tnodeId,\n\t\tschemaVersion: 1,\n\t\toperationCount: operations.length,\n\t\tcollections: [] as string[],\n\t\tincludesRecords: false,\n\t\tchecksum: checksumHex,\n\t}\n\n\tconst manifestSection = encodeJsonSection('manifest', manifest)\n\tconst checksumSection = encodeSection('checksum', new TextEncoder().encode(checksumHex))\n\n\tconst totalLen = manifestSection.length + allContentForChecksum.length + checksumSection.length\n\tconst result = new Uint8Array(totalLen)\n\tlet pos = 0\n\tresult.set(manifestSection, pos)\n\tpos += manifestSection.length\n\tresult.set(allContentForChecksum, pos)\n\tpos += allContentForChecksum.length\n\tresult.set(checksumSection, pos)\n\n\treturn result\n}\n\n/**\n * Parse a backup and return the operations and version vector.\n */\nexport function parseServerBackup(data: Uint8Array): {\n\toperations: Operation[]\n\tversionVector: Map<string, number>\n} {\n\tconst sections = parseSections(data)\n\n\t// Parse operations\n\tconst opsContent = findSection(sections, 'operations')\n\tlet operations: Operation[] = []\n\tif (opsContent) {\n\t\tconst text = new TextDecoder().decode(opsContent)\n\t\tconst lines = text\n\t\t\t.trim()\n\t\t\t.split('\\n')\n\t\t\t.filter((l) => l.length > 0)\n\t\toperations = lines.map((line) => JSON.parse(line) as Operation)\n\t}\n\n\t// Parse version vector\n\tconst vvData = parseJsonSection<Record<string, number>>(sections, 'version_vector')\n\tconst versionVector = new Map<string, number>()\n\tif (vvData) {\n\t\tfor (const [nid, seq] of Object.entries(vvData)) {\n\t\t\tversionVector.set(nid, seq)\n\t\t}\n\t}\n\n\treturn { operations, versionVector }\n}\n","// @korajs/server — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tAuthContext,\n\tAuthProvider,\n\tHttpSyncRequest,\n\tHttpSyncResponse,\n\tKoraSyncServerConfig,\n\tServerStatus,\n} from './types'\n\nexport type { ServerStore, MaterializedRecord, CollectionQueryOptions } from './store/server-store'\n\nexport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './transport/server-transport'\n\nexport type { HttpPollResponse } from './transport/http-server-transport'\n\nexport type {\n\tWsWebSocket,\n\tWsServerTransportOptions,\n} from './transport/ws-server-transport'\n\nexport type {\n\tAwarenessRelayCallback,\n\tClientSessionOptions,\n\tRelayCallback,\n\tSessionState,\n} from './session/client-session'\n\n// === Diagnostics ===\nexport type {\n\tClientMetrics,\n\tServerMetricsCollector,\n\tServerMetricsSnapshot,\n} from './diagnostics/server-metrics-collector'\n\n// === Logging ===\nexport type { LogEntry, LogLevel, Logger } from './logging/structured-logger'\nexport {\n\tcreateDefaultLogger,\n\tcreateJsonLogger,\n\tcreatePrettyLogger,\n\tcreateSilentLogger,\n} from './logging/structured-logger'\n\nexport type {\n\tWsServerConstructor,\n\tWsServerLike,\n} from './server/kora-sync-server'\n\nexport type {\n\tProductionServerConfig,\n\tProductionHttpRoute,\n\tProductionHttpRouteRequest,\n\tProductionHttpRouteResponse,\n\tProductionServer,\n} from './server/production-server'\n\nexport type {\n\tProductionHttpRouteContext,\n\tRouteMutation,\n\tRouteScopeOptions,\n\tRouteApplyResult,\n\tRouteConditionalApply,\n\tRouteConditionalResult,\n} from './server/route-context'\nexport type { RoutePredicate, RoutePredicateOperators } from './apply/route-predicate'\n\nexport type { OperationRejection } from './apply/rejection-taxonomy'\nexport { RETRIABLE_REJECTION_CODES, isRetriableRejection } from './apply/rejection-taxonomy'\n\nexport type {\n\tOperationDecision,\n\tOperationValidationContext,\n\tOperationValidator,\n} from './apply/operation-validator'\n\nexport type { TokenAuthProviderOptions } from './auth/token-auth'\nexport type { KoraAuthProviderOptions } from './auth/kora-auth-provider'\nexport type { MixedAuthProviderOptions } from './auth/mixed-auth-provider'\n\n// === Classes ===\nexport { MemoryServerStore } from './store/memory-server-store'\nexport { PostgresServerStore } from './store/postgres-server-store'\nexport { SqliteServerStore } from './store/sqlite-server-store'\nexport { HttpServerTransport } from './transport/http-server-transport'\nexport { WsServerTransport } from './transport/ws-server-transport'\nexport { ClientSession } from './session/client-session'\nexport { KoraSyncServer } from './server/kora-sync-server'\nexport { NoAuthProvider } from './auth/no-auth'\nexport { TokenAuthProvider } from './auth/token-auth'\nexport { KoraAuthProvider } from './auth/kora-auth-provider'\nexport { MixedAuthProvider } from './auth/mixed-auth-provider'\nexport {\n\tDEFAULT_MAX_SCOPE_PREDICATE_VALUES,\n\tnormalizeScopeMap,\n\toperationMatchesScopes,\n} from './scopes/server-scope-filter'\n\n// === Awareness ===\nexport { AwarenessRelay } from './awareness/awareness-relay'\n\n// === Factory Functions ===\nexport { createKoraServer } from './server/create-server'\nexport { createProductionServer } from './server/production-server'\nexport { createPostgresServerStore } from './store/postgres-server-store'\nexport { createSqliteServerStore } from './store/sqlite-server-store'\n","/**\n * Log severity levels.\n */\nexport type LogLevel = 'info' | 'warn' | 'error'\n\n/**\n * A structured log entry with timestamp and metadata.\n */\nexport interface LogEntry {\n\ttimestamp: number\n\tlevel: LogLevel\n\tevent: string\n\tsessionId?: string\n\tnodeId?: string\n\tduration?: number\n\tcount?: number\n\tbytes?: number\n\terror?: string\n\tdetails?: Record<string, unknown>\n}\n\n/**\n * Logger interface for structured logging.\n * Implementations control output format and destination.\n */\nexport interface Logger {\n\tlog(entry: LogEntry): void\n\tchild?(context: Partial<LogEntry>): Logger\n}\n\n/**\n * Serializes LogEntry to a single log line.\n */\nexport type LogSerializer = (entry: LogEntry) => string\n\nfunction defaultJsonSerializer(entry: LogEntry): string {\n\treturn JSON.stringify(entry)\n}\n\nfunction defaultPrettySerializer(entry: LogEntry): string {\n\tconst time = new Date(entry.timestamp).toISOString().slice(11, 23)\n\tconst levelTag = { info: ' INFO', warn: ' WARN', error: 'ERROR' }[entry.level]\n\tconst node = entry.nodeId ? ` [${entry.nodeId.slice(0, 8)}]` : ''\n\tconst session = entry.sessionId ? ` [session:${entry.sessionId.slice(0, 8)}]` : ''\n\tconst dur = entry.duration !== undefined ? ` +${entry.duration}ms` : ''\n\tconst count = entry.count !== undefined ? ` (${entry.count})` : ''\n\tconst err = entry.error ? ` — ${entry.error}` : ''\n\treturn `${time} ${levelTag}${node}${session} ${entry.event}${count}${dur}${err}`\n}\n\n/**\n * Creates a JSON-lines logger that writes to stdout/stderr.\n * Suitable for production use where log aggregators (Datadog, Loki, etc.) consume JSON.\n */\nexport function createJsonLogger(writer?: {\n\tinfo: (s: string) => void\n\terror: (s: string) => void\n}): Logger {\n\tconst out = writer ?? {\n\t\tinfo: (s: string) => process.stdout.write(`${s}\\n`),\n\t\terror: (s: string) => process.stderr.write(`${s}\\n`),\n\t}\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tconst line = defaultJsonSerializer(entry)\n\t\t\tif (entry.level === 'error') {\n\t\t\t\tout.error(line)\n\t\t\t} else {\n\t\t\t\tout.info(line)\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Creates a pretty-printed logger for development use.\n * Writes human-readable colored output to the terminal.\n */\nexport function createPrettyLogger(writer?: { write: (s: string) => void }): Logger {\n\tconst out = writer ?? { write: (s: string) => process.stdout.write(`${s}\\n`) }\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tout.write(defaultPrettySerializer(entry))\n\t\t},\n\t}\n}\n\n/**\n * A logger that discards all entries (for testing or when logging is disabled).\n */\nexport function createSilentLogger(): Logger {\n\treturn { log() {} }\n}\n\n/**\n * Creates a logger based on the NODE_ENV environment variable.\n * - production: JSON lines to stdout/stderr\n * - test: silent\n * - otherwise: pretty-printed to stdout\n */\nexport function createDefaultLogger(): Logger {\n\tswitch (process.env.NODE_ENV) {\n\t\tcase 'production':\n\t\t\treturn createJsonLogger()\n\t\tcase 'test':\n\t\t\treturn createSilentLogger()\n\t\tdefault:\n\t\t\treturn createPrettyLogger()\n\t}\n}\n","/**\n * Shared vocabulary for why the server refused an operation.\n *\n * The `retriable` flag answers one question for the caller: is it worth\n * submitting this SAME operation again later?\n *\n * - `true` — the rejection is transient (for example a rate limit). The\n * identical operation may succeed once the condition clears, so a\n * client is right to back off and retry the same bytes.\n * - `false` — the rejection is permanent for the operation as written (a\n * constraint violation, a referential conflict, a malformed\n * mutation, a scope violation). Resubmitting the same bytes will\n * always fail; the caller must change the operation or give up.\n *\n * This is deliberately defined once, in one place, so the trusted server\n * data-plane (route context / `server.kora`) and the untrusted client-ingestion\n * path speak the same language. `retriable` (this spelling) matches the wire\n * `ErrorMessage.retriable` field the sync protocol already ships, so a single\n * flag flows from the pipeline out to connected clients unchanged.\n */\nexport interface OperationRejection {\n\t/** Stable, machine-readable reason code (for example `CONSTRAINT_VIOLATION`). */\n\tcode: string\n\t/** Human-readable explanation with enough context to debug without reproduction. */\n\tmessage: string\n\t/** Whether resubmitting the identical operation may later succeed. */\n\tretriable: boolean\n}\n\n/**\n * Reason codes whose underlying condition is transient, so the identical\n * operation may succeed on a later attempt.\n *\n * Everything NOT listed here is treated as permanent. Permanent is the safe\n * default: a client should never be told to keep hammering a genuinely invalid\n * operation, so a new code is non-retriable until it is deliberately added here.\n *\n * `RATE_LIMIT` is the code the session emits when a client exceeds its\n * per-minute operation budget (see `client-session.ts`).\n */\nexport const RETRIABLE_REJECTION_CODES: ReadonlySet<string> = new Set(['RATE_LIMIT'])\n\n/**\n * Classify a reason code as retriable (transient) or not (permanent).\n *\n * @param code - A rejection reason code.\n * @returns `true` when resubmitting the identical operation may later succeed.\n */\nexport function isRetriableRejection(code: string): boolean {\n\treturn RETRIABLE_REJECTION_CODES.has(code)\n}\n","import type { Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { generateUUIDv7 } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport {\n\tdeserializeFieldValue,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n/**\n * In-memory server store for testing and quick prototyping.\n * Not suitable for production — data does not survive process restart.\n *\n * When a schema is set via setSchema(), maintains materialized records\n * in-memory for efficient queries.\n */\nexport class MemoryServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly operations: Operation[] = []\n\tprivate readonly operationIndex = new Map<string, Operation>()\n\tprivate readonly versionVector: Map<string, number> = new Map()\n\t/**\n\t * Server-assigned delivery sequence per operation id. Single-process, so a plain\n\t * counter incremented at insert time gives commit-order delivery sequence with no\n\t * gaps. `operations` is kept in insertion (== delivery) order, so a delivery scan\n\t * is a forward walk.\n\t */\n\tprivate readonly deliverySeqByOpId = new Map<string, number>()\n\tprivate deliverySeqCounter = 0\n\tprivate schema: SchemaDefinition | null = null\n\n\t/** Materialized records: collection -> recordId -> record data */\n\tprivate readonly materializedRecords = new Map<string, Map<string, MaterializedRecord>>()\n\n\tprivate closed = false\n\n\tconstructor(nodeId?: string) {\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\treturn new Map(this.versionVector)\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.schema = schema\n\n\t\t// Initialize collection maps\n\t\tfor (const collectionName of Object.keys(schema.collections)) {\n\t\t\tif (!this.materializedRecords.has(collectionName)) {\n\t\t\t\tthis.materializedRecords.set(collectionName, new Map())\n\t\t\t}\n\t\t}\n\n\t\t// Backfill from existing operations\n\t\tthis.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\t// Content-addressed dedup: same id = same content\n\t\tif (this.operationIndex.has(op.id)) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\tthis.operations.push(op)\n\t\tthis.operationIndex.set(op.id, op)\n\n\t\t// Assign the next delivery sequence in commit order (single-process: no race).\n\t\tthis.deliverySeqCounter += 1\n\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\n\t\t// Advance version vector\n\t\tconst currentSeq = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentSeq) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\t// Dual-write: update materialized records if schema is set\n\t\tif (this.schema?.collections[op.collection]) {\n\t\t\tthis.rebuildMaterializedRecord(op.collection, op.recordId)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\treturn this.operations\n\t\t\t.filter(\n\t\t\t\t(op) => op.nodeId === nodeId && op.sequenceNumber >= fromSeq && op.sequenceNumber <= toSeq,\n\t\t\t)\n\t\t\t.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.operations.length\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.deliverySeqCounter\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst result: DeliveredOperation[] = []\n\t\tif (limit <= 0) return result\n\t\t// operations is in delivery order, so once entries exceed the cursor they all do;\n\t\t// the guard on each entry keeps this correct even if that invariant ever weakens.\n\t\tfor (const op of this.operations) {\n\t\t\tconst deliverySequence = this.deliverySeqByOpId.get(op.id) ?? 0\n\t\t\tif (deliverySequence > afterDeliverySequence) {\n\t\t\t\tresult.push({ operation: op, deliverySequence })\n\t\t\t\tif (result.length >= limit) break\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read from materialized records\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations\n\t\treturn this.materializeFromOps(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\t// Validate field names\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return []\n\n\t\t// Get all non-deleted records\n\t\tlet records = Array.from(collectionMap.values()).filter((r) => {\n\t\t\tif (!options?.includeDeleted && r._deleted === 1) return false\n\t\t\treturn true\n\t\t})\n\n\t\t// Apply WHERE filters\n\t\tif (options?.where) {\n\t\t\tfor (const [key, value] of Object.entries(options.where)) {\n\t\t\t\trecords = records.filter((r) => r[key] === value)\n\t\t\t}\n\t\t}\n\n\t\t// Apply ORDER BY\n\t\tif (options?.orderBy) {\n\t\t\tconst field = options.orderBy\n\t\t\tconst dir = options.orderDirection === 'desc' ? -1 : 1\n\t\t\trecords.sort((a, b) => {\n\t\t\t\tconst aVal = a[field]\n\t\t\t\tconst bVal = b[field]\n\t\t\t\tif (aVal === bVal) return 0\n\t\t\t\tif (aVal === null || aVal === undefined) return 1\n\t\t\t\tif (bVal === null || bVal === undefined) return -1\n\t\t\t\treturn aVal < bVal ? -1 * dir : 1 * dir\n\t\t\t})\n\t\t}\n\n\t\t// Apply OFFSET\n\t\tif (options?.offset !== undefined) {\n\t\t\trecords = records.slice(options.offset)\n\t\t}\n\n\t\t// Apply LIMIT\n\t\tif (options?.limit !== undefined) {\n\t\t\trecords = records.slice(0, options.limit)\n\t\t}\n\n\t\t// Return clean copies without internal fields\n\t\treturn records.map((r) => {\n\t\t\tconst clean: MaterializedRecord = { id: r.id }\n\t\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[\n\t\t\t\tcollection\n\t\t\t] as NonNullable<SchemaDefinition['collections'][string]>\n\t\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\t\tif (fieldName in r) {\n\t\t\t\t\tclean[fieldName] = r[fieldName]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ('_created_at' in r) clean._created_at = r._created_at\n\t\t\tif ('_updated_at' in r) clean._updated_at = r._updated_at\n\t\t\treturn clean\n\t\t})\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return null\n\n\t\tconst record = collectionMap.get(id)\n\t\tif (!record || record._deleted === 1) return null\n\n\t\t// Return clean copy\n\t\tconst clean: MaterializedRecord = { id: record.id }\n\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\tif (fieldName in record) {\n\t\t\t\tclean[fieldName] = record[fieldName]\n\t\t\t}\n\t\t}\n\t\tif ('_created_at' in record) clean._created_at = record._created_at\n\t\tif ('_updated_at' in record) clean._updated_at = record._updated_at\n\t\treturn clean\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return 0\n\n\t\tlet count = 0\n\t\tfor (const record of collectionMap.values()) {\n\t\t\tif (record._deleted === 1) continue\n\t\t\tif (where) {\n\t\t\t\tlet matches = true\n\t\t\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\t\t\tif (record[key] !== value) {\n\t\t\t\t\t\tmatches = false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!matches) continue\n\t\t\t}\n\t\t\tcount++\n\t\t}\n\t\treturn count\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\t/**\n\t * Wipes all in-memory state. For tests and E2E isolation only.\n\t */\n\tresetForTests(): void {\n\t\tthis.assertOpen()\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.materializedRecords.clear()\n\t\tthis.schema = null\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\treturn buildServerBackup(this.nodeId, this.operations, this.versionVector)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\t// Replace mode: clear and reload\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.deliverySeqByOpId.clear()\n\t\tthis.deliverySeqCounter = 0\n\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\n\t\tfor (const op of operations) {\n\t\t\tthis.operations.push(op)\n\t\t\tthis.operationIndex.set(op.id, op)\n\t\t\t// Re-assign delivery sequence in backup order (the order ops were shipped).\n\t\t\tthis.deliverySeqCounter += 1\n\t\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\n\t\t\t// Update materialized records if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tthis.rebuildMaterializedRecord(op.collection, op.recordId)\n\t\t\t}\n\t\t}\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// --- Testing helpers (not on interface) ---\n\n\t/**\n\t * Get all stored operations (for test assertions).\n\t */\n\tgetAllOperations(): Operation[] {\n\t\treturn [...this.operations]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\tprivate rebuildMaterializedRecord(collection: string, recordId: string): void {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Get or create collection map\n\t\tlet collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) {\n\t\t\tcollectionMap = new Map()\n\t\t\tthis.materializedRecords.set(collection, collectionMap)\n\t\t}\n\n\t\t// Get all ops for this record in HLC total order (wallTime, logical, nodeId)\n\t\t// so atomic composition and LWW converge like the merge engine.\n\t\tconst recordOps = this.operations\n\t\t\t.filter((op) => op.collection === collection && op.recordId === recordId)\n\t\t\t.sort((a, b) => {\n\t\t\t\tif (a.timestamp.wallTime !== b.timestamp.wallTime)\n\t\t\t\t\treturn a.timestamp.wallTime - b.timestamp.wallTime\n\t\t\t\tif (a.timestamp.logical !== b.timestamp.logical)\n\t\t\t\t\treturn a.timestamp.logical - b.timestamp.logical\n\t\t\t\treturn a.timestamp.nodeId < b.timestamp.nodeId\n\t\t\t\t\t? -1\n\t\t\t\t\t: a.timestamp.nodeId > b.timestamp.nodeId\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: 0\n\t\t\t})\n\n\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data,\n\t\t\tatomicOps: op.atomicOps ?? null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tif (recordData) {\n\t\t\tconst createdAt =\n\t\t\t\trecordOps.length > 0 ? (recordOps[0] as Operation).timestamp.wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\trecordOps.length > 0\n\t\t\t\t\t? (recordOps[recordOps.length - 1] as Operation).timestamp.wallTime\n\t\t\t\t\t: Date.now()\n\n\t\t\tconst materialized: MaterializedRecord = {\n\t\t\t\tid: recordId,\n\t\t\t\t...recordData,\n\t\t\t\t_created_at: createdAt,\n\t\t\t\t_updated_at: updatedAt,\n\t\t\t\t_deleted: 0,\n\t\t\t}\n\t\t\tcollectionMap.set(recordId, materialized)\n\t\t} else {\n\t\t\t// Record was deleted\n\t\t\tconst existing = collectionMap.get(recordId)\n\t\t\tif (existing) {\n\t\t\t\texisting._deleted = 1\n\t\t\t\texisting._updated_at = Date.now()\n\t\t\t} else {\n\t\t\t\tcollectionMap.set(recordId, {\n\t\t\t\t\tid: recordId,\n\t\t\t\t\t_deleted: 1,\n\t\t\t\t\t_created_at: Date.now(),\n\t\t\t\t\t_updated_at: Date.now(),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate backfillAllCollections(): void {\n\t\tif (!this.schema) return\n\n\t\t// Get all unique (collection, recordId) pairs\n\t\tconst recordKeys = new Set<string>()\n\t\tfor (const op of this.operations) {\n\t\t\tif (this.schema.collections[op.collection]) {\n\t\t\t\trecordKeys.add(`${op.collection}:::${op.recordId}`)\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of recordKeys) {\n\t\t\tconst [collection, recordId] = key.split(':::') as [string, string]\n\t\t\tthis.rebuildMaterializedRecord(collection, recordId)\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOps(collection: string): MaterializedRecord[] {\n\t\tconst collectionOps = this.operations\n\t\t\t.filter((op) => op.collection === collection)\n\t\t\t.sort((a, b) => {\n\t\t\t\tif (a.timestamp.wallTime !== b.timestamp.wallTime)\n\t\t\t\t\treturn a.timestamp.wallTime - b.timestamp.wallTime\n\t\t\t\tif (a.timestamp.logical !== b.timestamp.logical)\n\t\t\t\t\treturn a.timestamp.logical - b.timestamp.logical\n\t\t\t\treturn a.sequenceNumber - b.sequenceNumber\n\t\t\t})\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const op of collectionOps) {\n\t\t\tswitch (op.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (op.data) {\n\t\t\t\t\t\trecords.set(op.recordId, { id: op.recordId, ...op.data })\n\t\t\t\t\t\tdeleted.delete(op.recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (op.data) {\n\t\t\t\t\t\tconst existing = records.get(op.recordId) ?? { id: op.recordId }\n\t\t\t\t\t\trecords.set(op.recordId, { ...existing, ...op.data })\n\t\t\t\t\t\tdeleted.delete(op.recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(op.recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('MemoryServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n","import { StorageError, quoteIdent, replayOperationsForRecord } from '@korajs/core'\nimport type {\n\tCollectionDefinition,\n\tFieldDescriptor,\n\tReplayOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\n\n// Re-exported so existing server-internal imports keep working; the implementation\n// now lives in @korajs/core so the client apply pipeline and the server materialize\n// records through the exact same atomic-aware fold.\nexport { replayOperationsForRecord }\nexport type { ReplayOperation }\n\n/**\n * SQL dialect for DDL generation.\n * SQLite and PostgreSQL differ in some column types.\n */\nexport type SqlDialect = 'sqlite' | 'postgres'\n\n/**\n * Map a Kora field kind to its SQL column type for the given dialect.\n */\nfunction fieldTypeToSql(descriptor: FieldDescriptor, dialect: SqlDialect): string {\n\tswitch (descriptor.kind) {\n\t\tcase 'string':\n\t\t\treturn 'TEXT'\n\t\tcase 'number':\n\t\t\treturn dialect === 'postgres' ? 'DOUBLE PRECISION' : 'REAL'\n\t\tcase 'boolean':\n\t\t\treturn 'INTEGER'\n\t\tcase 'enum':\n\t\t\treturn 'TEXT'\n\t\tcase 'timestamp':\n\t\t\treturn dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\t\tcase 'array':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'object':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'json':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'blob':\n\t\t\t// Content-addressed BlobRef metadata is stored as JSON; the bytes live\n\t\t\t// out of band, so the column is textual, not binary.\n\t\t\treturn 'TEXT'\n\t\tcase 'secret':\n\t\t\treturn 'TEXT'\n\t\tcase 'richtext':\n\t\t\treturn dialect === 'postgres' ? 'BYTEA' : 'BLOB'\n\t}\n}\n\nfunction sqlDefaultLiteral(value: unknown): string {\n\tif (value === null) return 'NULL'\n\tif (typeof value === 'string') return `'${value}'`\n\tif (typeof value === 'number') return String(value)\n\tif (typeof value === 'boolean') return value ? '1' : '0'\n\treturn `'${JSON.stringify(value)}'`\n}\n\n/**\n * Generate DDL statements for creating a materialized collection table.\n * Includes CREATE TABLE, safe ALTER TABLE for schema evolution, and indexes.\n *\n * @param name - Collection/table name\n * @param collection - Collection definition from the schema\n * @param dialect - SQL dialect ('sqlite' or 'postgres')\n * @returns Array of DDL SQL strings\n */\nexport function generateCollectionDDL(\n\tname: string,\n\tcollection: CollectionDefinition,\n\tdialect: SqlDialect,\n): string[] {\n\tconst statements: string[] = []\n\tconst columns: string[] = ['id TEXT PRIMARY KEY NOT NULL']\n\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\tif (descriptor.kind === 'enum' && descriptor.enumValues) {\n\t\t\tconst values = descriptor.enumValues.map((v) => `'${v}'`).join(', ')\n\t\t\tcolDef += ` CHECK (${quoteIdent(fieldName)} IN (${values}))`\n\t\t}\n\t\tcolumns.push(colDef)\n\t}\n\n\tconst tsType = dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\tcolumns.push(`_created_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push(`_updated_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push('_deleted INTEGER NOT NULL DEFAULT 0')\n\n\tstatements.push(`CREATE TABLE IF NOT EXISTS ${quoteIdent(name)} (\\n ${columns.join(',\\n ')}\\n)`)\n\n\t// Safe ALTER TABLE for adding new columns to existing tables\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\tstatements.push(`--kora:safe-alter\\nALTER TABLE ${quoteIdent(name)} ADD COLUMN ${colDef}`)\n\t}\n\n\t// User-defined indexes from schema. The index NAME stays unquoted (only ever\n\t// created/dropped by this construction); the table and column are quoted.\n\tfor (const indexField of collection.indexes) {\n\t\tstatements.push(\n\t\t\t`CREATE INDEX IF NOT EXISTS idx_${name}_${indexField} ON ${quoteIdent(name)} (${quoteIdent(indexField)})`,\n\t\t)\n\t}\n\n\t// Always index _deleted for efficient soft-delete filtering\n\tstatements.push(\n\t\t`CREATE INDEX IF NOT EXISTS idx_${name}__deleted ON ${quoteIdent(name)} (_deleted)`,\n\t)\n\n\treturn statements\n}\n\n/**\n * Generate all collection table DDL from a full schema.\n */\nexport function generateAllCollectionDDL(schema: SchemaDefinition, dialect: SqlDialect): string[] {\n\tconst statements: string[] = []\n\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\tstatements.push(...generateCollectionDDL(name, collection, dialect))\n\t}\n\treturn statements\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst BASE64_REVERSE: ReadonlyMap<string, number> = new Map(\n\tArray.from(BASE64_ALPHABET, (char, index) => [char, index]),\n)\n\nfunction base64ToBytes(base64: string): Uint8Array {\n\tconst cleaned = base64.replace(/=+$/, '')\n\tconst out = new Uint8Array(Math.floor((cleaned.length * 6) / 8))\n\tlet buffer = 0\n\tlet bits = 0\n\tlet index = 0\n\tfor (const char of cleaned) {\n\t\tconst value = BASE64_REVERSE.get(char)\n\t\tif (value === undefined) {\n\t\t\tthrow new StorageError(`Invalid base64 character \"${char}\" in tagged richtext value`, {\n\t\t\t\tchar,\n\t\t\t})\n\t\t}\n\t\tbuffer = (buffer << 6) | value\n\t\tbits += 6\n\t\tif (bits >= 8) {\n\t\t\tbits -= 8\n\t\t\tout[index] = (buffer >> bits) & 0xff\n\t\t\tindex += 1\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Decode a richtext op-data value to something a BLOB/BYTEA column accepts.\n * Client operations carry binary richtext as the canonical tagged\n * `{ $koraBytes: base64 }` form (raw bytes cannot survive the JSON `dataJson`\n * wire field). The server cannot import the store package (dependency rules),\n * so the tiny base64 decode is duplicated here rather than shared.\n * Strings and byte views pass through unchanged.\n */\nfunction decodeRichtextColumnValue(value: unknown): unknown {\n\tif (typeof value !== 'object' || value === null || ArrayBuffer.isView(value)) {\n\t\treturn value\n\t}\n\tconst record = value as Record<string, unknown>\n\tif (Object.keys(record).length === 1 && typeof record.$koraBytes === 'string') {\n\t\treturn base64ToBytes(record.$koraBytes)\n\t}\n\t// Pre-fix operations serialized raw Uint8Arrays as numeric-key objects;\n\t// reconstruct the bytes so old dev databases keep materializing.\n\tconst keys = Object.keys(record)\n\tif (keys.length > 0 && keys.every((k, i) => k === String(i) && typeof record[k] === 'number')) {\n\t\tconst bytes = new Uint8Array(keys.length)\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst byte = record[String(i)]\n\t\t\tbytes[i] = typeof byte === 'number' ? byte & 0xff : 0\n\t\t}\n\t\treturn bytes\n\t}\n\treturn value\n}\n\n/**\n * Serialize a field value for SQL storage.\n * Arrays become JSON strings, booleans become 0/1, etc.\n */\nexport function serializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? value : JSON.stringify(value)\n\t\tcase 'boolean':\n\t\t\treturn value ? 1 : 0\n\t\tcase 'richtext':\n\t\t\treturn decodeRichtextColumnValue(value)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * Deserialize a field value from SQL storage back to JavaScript types.\n */\nexport function deserializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? JSON.parse(value) : value\n\t\tcase 'boolean':\n\t\t\treturn value === 1 || value === true\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * Validate that a field name is a valid column in the given collection schema.\n * Includes system fields (id, _created_at, _updated_at, _deleted).\n */\nexport function validateFieldName(\n\tcollectionName: string,\n\tfieldName: string,\n\tschema: SchemaDefinition,\n): void {\n\tconst collection = schema.collections[collectionName]\n\tif (!collection) {\n\t\tthrow new Error(`Unknown collection: ${collectionName}`)\n\t}\n\tconst validFields = new Set([\n\t\t'id',\n\t\t'_created_at',\n\t\t'_updated_at',\n\t\t'_deleted',\n\t\t...Object.keys(collection.fields),\n\t])\n\tif (!validFields.has(fieldName)) {\n\t\tthrow new Error(\n\t\t\t`Invalid field name \"${fieldName}\" for collection \"${collectionName}\". ` +\n\t\t\t\t`Valid fields: ${Array.from(validFields).join(', ')}`,\n\t\t)\n\t}\n}\n","import type {\n\tAtomicOp,\n\tHLCTimestamp,\n\tOperation,\n\tSchemaDefinition,\n\tTimeSource,\n\tVersionVector,\n} from '@korajs/core'\nimport { HybridLogicalClock, generateUUIDv7, quoteIdent } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, desc, eq, gt, sql } from 'drizzle-orm'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport { pgOperations, pgSyncState } from './drizzle-pg-schema'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n/**\n * PostgreSQL-backed server store using Drizzle ORM.\n * All reads and writes go through Drizzle's typed query builder.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class PostgresServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly db: PostgresJsDatabase\n\tprivate readonly versionVector: VersionVector = new Map()\n\tprivate readonly ready: Promise<void>\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\t/**\n\t * Monotonic counter for this node's server-originated sequence numbers. Lazily\n\t * seeded from the persisted version vector on first use, then advanced in memory\n\t * (a synchronous `++`, atomic on the single JS thread) so concurrent conditional\n\t * applies never receive the same number. Null means \"not yet seeded\"; reset to\n\t * null after a backup import so it re-seeds from the restored version vector.\n\t */\n\tprivate sequenceCounter: number | null = null\n\t/**\n\t * Time source for HLC timestamps on server-originated operations. Injectable so a\n\t * test can freeze wall-clock time and prove the conditional-apply ordering holds\n\t * under same-millisecond commits (the case the advisory lock and clock advance\n\t * exist to make correct). Defaults to the system clock in production.\n\t */\n\tprivate readonly timeSource: TimeSource\n\n\tconstructor(db: PostgresJsDatabase, nodeId?: string, timeSource?: TimeSource) {\n\t\tthis.db = db\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t\tthis.timeSource = timeSource ?? { now: () => Date.now() }\n\t\tthis.ready = this.initialize()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\treturn new Map(this.versionVector)\n\t}\n\n\t/**\n\t * Atomically reserve this node's next server-operation sequence number. The\n\t * synchronous increment cannot interleave on the single JS thread, so two\n\t * concurrent conditional applies are always handed distinct numbers.\n\t */\n\treserveSequenceNumber(): number {\n\t\tif (this.sequenceCounter === null) {\n\t\t\tthis.sequenceCounter = this.versionVector.get(this.nodeId) ?? 0\n\t\t}\n\t\tthis.sequenceCounter += 1\n\t\treturn this.sequenceCounter\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.schema = schema\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'postgres')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tawait this.db.execute(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"already exists\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps the actual DB error in e.cause, so check both.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (\n\t\t\t\t\t\t!msg.includes('already exists') &&\n\t\t\t\t\t\t!msg.includes('duplicate column') &&\n\t\t\t\t\t\t!causeMsg.includes('already exists') &&\n\t\t\t\t\t\t!causeMsg.includes('duplicate column')\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait this.db.execute(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// Backfill materialized tables from existing operations\n\t\tawait this.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\t// Content-addressed dedup check\n\t\tconst existing = await this.db\n\t\t\t.select({ id: pgOperations.id })\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.id, op.id))\n\t\t\t.limit(1)\n\n\t\tif (existing.length > 0) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\tconst now = Date.now()\n\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\t// Assign the delivery sequence in commit order (see nextDeliverySeq). A rare\n\t\t\t// concurrent duplicate insert below no-ops and simply leaves a harmless gap.\n\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\n\t\t\t// Insert operation with dedup\n\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\n\t\t\t// Upsert version vector: advance max sequence number with GREATEST\n\t\t\tawait tx\n\t\t\t\t.insert(pgSyncState)\n\t\t\t\t.values({\n\t\t\t\t\tnodeId: op.nodeId,\n\t\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\t\tlastSeenAt: now,\n\t\t\t\t})\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: pgSyncState.nodeId,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tmaxSequenceNumber: sql`GREATEST(${pgSyncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tawait this.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t}\n\t\t})\n\n\t\t// Update in-memory version vector cache\n\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentMax) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * Conditionally apply operations atomically, serialized across server instances\n\t * on the target record via a transaction-scoped advisory lock. The lock makes\n\t * the read-decide-write cycle atomic against concurrent instances, so a cap\n\t * check like `responseCount < max` cannot be passed by two admissions at once.\n\t */\n\tasync applyConditional(input: ConditionalApplyInput): Promise<ConditionalApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(input.target.collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[input.target.collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst lockKey = `kora:${input.target.collection}:${input.target.id}`\n\n\t\tconst result = await this.db.transaction(async (tx) => {\n\t\t\t// Serialize this target across every server instance sharing the database.\n\t\t\t// hashtextextended maps the key to the bigint pg_advisory_xact_lock expects;\n\t\t\t// the lock releases automatically when the transaction ends.\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended(${lockKey}, 0))`)\n\n\t\t\t// Idempotency: if the key record already exists (from an earlier attempt),\n\t\t\t// this set is already committed. Checked under the lock so a retry racing a\n\t\t\t// first attempt on another instance still resolves to at-most-once.\n\t\t\tif (input.idempotencyKey) {\n\t\t\t\tconst existing = (await tx.execute(\n\t\t\t\t\tsql`SELECT 1 FROM ${sql.raw(quoteIdent(input.idempotencyKey.collection))} WHERE id = ${input.idempotencyKey.id} AND _deleted = 0 LIMIT 1`,\n\t\t\t\t)) as unknown as unknown[]\n\t\t\t\tif (existing.length > 0) {\n\t\t\t\t\treturn { admitted: true, idempotent: true, applied: [] as Operation[] }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rows = (await tx.execute(\n\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(input.target.collection))} WHERE id = ${input.target.id} AND _deleted = 0`,\n\t\t\t)) as unknown as Record<string, unknown>[]\n\t\t\tconst current =\n\t\t\t\trows.length > 0\n\t\t\t\t\t? this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t\t\t\t\t: null\n\n\t\t\tif (!input.admit(current)) {\n\t\t\t\treturn { admitted: false, idempotent: false, applied: [] as Operation[] }\n\t\t\t}\n\n\t\t\t// Seed a clock past the target record's latest committed operation so the\n\t\t\t// operations built next sort strictly after every prior write to it. Under\n\t\t\t// the advisory lock this makes last-write-wins materialization agree with the\n\t\t\t// serialized commit order, so a same-millisecond commit on another instance\n\t\t\t// cannot cause the counter to be undercounted (which would admit past a cap).\n\t\t\tconst clock = new HybridLogicalClock(this.nodeId, this.timeSource)\n\t\t\tconst latest = await this.latestOperationTimestamp(\n\t\t\t\ttx,\n\t\t\t\tinput.target.collection,\n\t\t\t\tinput.target.id,\n\t\t\t)\n\t\t\tif (latest) {\n\t\t\t\tclock.advanceTo(latest)\n\t\t\t}\n\n\t\t\tconst ops = await input.buildOperations(current, { clock })\n\t\t\tconst now = Date.now()\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\t\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\t\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\t\t\t\tawait tx\n\t\t\t\t\t.insert(pgSyncState)\n\t\t\t\t\t.values({ nodeId: op.nodeId, maxSequenceNumber: op.sequenceNumber, lastSeenAt: now })\n\t\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\t\ttarget: pgSyncState.nodeId,\n\t\t\t\t\t\tset: {\n\t\t\t\t\t\t\tmaxSequenceNumber: sql`GREATEST(${pgSyncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\t\tawait this.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { admitted: true, idempotent: false, applied: ops }\n\t\t})\n\n\t\t// Advance the in-memory version vector cache after commit.\n\t\tfor (const op of result.applied) {\n\t\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\t\tif (op.sequenceNumber > currentMax) {\n\t\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(\n\t\t\t\tand(eq(pgOperations.nodeId, nodeId), between(pgOperations.sequenceNumber, fromSeq, toSeq)),\n\t\t\t)\n\t\t\t.orderBy(asc(pgOperations.sequenceNumber))\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst result = await this.db.select({ value: count() }).from(pgOperations)\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT COALESCE(MAX(delivery_seq), 0) AS m FROM operations`,\n\t\t)) as unknown as { m: number | string | bigint }[]\n\t\treturn Number(rows[0]?.m ?? 0)\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(gt(pgOperations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(pgOperations.deliverySeq))\n\t\t\t.limit(limit)\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t}))\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false)\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Array<{ cnt: number | string }>\n\t\tconst cnt = rows[0]?.cnt\n\t\treturn typeof cnt === 'string' ? Number.parseInt(cnt, 10) : (cnt ?? 0)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\n\t\t// Export in delivery-sequence order (commit order), NOT sequenceNumber order.\n\t\t// sequenceNumber is per-node and interleaves nodes arbitrarily, which can place a\n\t\t// dependent operation before its dependency; restoring in that order would then\n\t\t// reassign delivery sequences non-causally, so a resumed client would receive the\n\t\t// dependent first, defer it, advance its watermark past it, and lose it. Delivery\n\t\t// order is commit order and therefore respects causality.\n\t\tconst rows = await this.db.select().from(pgOperations).orderBy(asc(pgOperations.deliverySeq))\n\t\tconst operations = rows.map((row) => this.deserializeOperation(row))\n\n\t\treturn buildServerBackup(this.nodeId, operations, this.versionVector)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\t// Re-seed the sequence counter from the (possibly advanced) version vector,\n\t\t\t// in case the merge restored operations on this node with higher numbers.\n\t\t\tthis.sequenceCounter = null\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.delete(pgOperations)\n\t\t\tawait tx.delete(pgSyncState)\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\tawait tx\n\t\t\t\t\t.insert(pgSyncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: now })\n\t\t\t\t\t.onConflictDoNothing({ target: pgSyncState.nodeId })\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order, then realign the\n\t\t\t// counter so future appends continue above the restored maximum.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\t\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\t\t\t}\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO delivery_counter (id, value) VALUES (1, ${deliverySeq})\n\t\t\t\t\tON CONFLICT (id) DO UPDATE SET value = ${deliverySeq}`,\n\t\t\t)\n\t\t})\n\n\t\t// Rebuild in-memory version vector\n\t\tthis.versionVector.clear()\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\t\t// Re-seed the sequence counter from the restored version vector.\n\t\tthis.sequenceCounter = null\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * The HLC timestamp of the most recent operation on a record, by total order\n\t * (wallTime, logical, nodeId), or null when the record has no operations. Used\n\t * by {@link applyConditional} to advance its clock past the record's latest\n\t * write so newly built operations sort strictly after it.\n\t */\n\tprivate async latestOperationTimestamp(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<HLCTimestamp | null> {\n\t\tconst rows = await txOrDb\n\t\t\t.select({\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t\tlogical: pgOperations.logical,\n\t\t\t\ttimestampNodeId: pgOperations.timestampNodeId,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(and(eq(pgOperations.collection, collection), eq(pgOperations.recordId, recordId)))\n\t\t\t.orderBy(\n\t\t\t\tdesc(pgOperations.wallTime),\n\t\t\t\tdesc(pgOperations.logical),\n\t\t\t\tdesc(pgOperations.timestampNodeId),\n\t\t\t)\n\t\t\t.limit(1)\n\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\t\treturn { wallTime: row.wallTime, logical: row.logical, nodeId: row.timestampNodeId }\n\t}\n\n\t/**\n\t * Rebuild a single record in the materialized collection table by replaying\n\t * all operations for that record.\n\t */\n\tprivate async rebuildMaterializedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this specific record, ordered by HLC\n\t\tconst ops = await txOrDb\n\t\t\t.select({\n\t\t\t\ttype: pgOperations.type,\n\t\t\t\tdata: pgOperations.data,\n\t\t\t\tatomicOps: pgOperations.atomicOps,\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(and(eq(pgOperations.collection, collection), eq(pgOperations.recordId, recordId)))\n\t\t\t// HLC total order (wallTime, logical, nodeId) so atomic composition and LWW\n\t\t\t// see operations in exactly the order the merge engine converges them.\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.timestampNodeId),\n\t\t\t)\n\n\t\t// Replay to get current state\n\t\tconst parsedOps = ops.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\tif (recordData) {\n\t\t\tconst createdAt = ops.length > 0 ? (ops[0] as (typeof ops)[0]).wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\tops.length > 0 ? (ops[ops.length - 1] as (typeof ops)[0]).wallTime : Date.now()\n\n\t\t\tawait this.upsertMaterializedRecord(\n\t\t\t\ttxOrDb,\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\trecordData,\n\t\t\t\tfieldNames,\n\t\t\t\tcollectionDef,\n\t\t\t\tcreatedAt,\n\t\t\t\tupdatedAt,\n\t\t\t)\n\t\t} else {\n\t\t\tawait txOrDb.execute(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1, _updated_at = ${Date.now()} WHERE id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t */\n\tprivate async upsertMaterializedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t): Promise<void> {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor ? serializeFieldValue(recordData[f] ?? null, descriptor) : null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\t0,\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\tawait txOrDb.execute(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * Backfill all materialized collection tables from the existing operation log.\n\t */\n\tprivate async backfillAllCollections(): Promise<void> {\n\t\tif (!this.schema) return\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tawait this.backfillCollection(collectionName)\n\t\t}\n\t}\n\n\t/**\n\t * Backfill a single collection's materialized table from operations.\n\t */\n\tprivate async backfillCollection(collectionName: string): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collectionName]\n\t\tif (!collectionDef) return\n\n\t\tconst allOps = await this.db\n\t\t\t.select({\n\t\t\t\trecordId: pgOperations.recordId,\n\t\t\t\ttype: pgOperations.type,\n\t\t\t\tdata: pgOperations.data,\n\t\t\t\tatomicOps: pgOperations.atomicOps,\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.collection, collectionName))\n\t\t\t// HLC total order (wallTime, logical, nodeId) for correct atomic composition.\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.timestampNodeId),\n\t\t\t)\n\n\t\tif (allOps.length === 0) return\n\n\t\t// Group by recordId\n\t\tconst grouped = new Map<string, typeof allOps>()\n\t\tfor (const op of allOps) {\n\t\t\tlet group = grouped.get(op.recordId)\n\t\t\tif (!group) {\n\t\t\t\tgroup = []\n\t\t\t\tgrouped.set(op.recordId, group)\n\t\t\t}\n\t\t\tgroup.push(op)\n\t\t}\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\t// Rebuild each record\n\t\tfor (const [recordId, recordOps] of grouped) {\n\t\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\t\ttype: op.type,\n\t\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\t\tatomicOps:\n\t\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t\t}))\n\t\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\t\tif (recordData) {\n\t\t\t\tconst createdAt = (recordOps[0] as (typeof recordOps)[0]).wallTime\n\t\t\t\tconst updatedAt = (recordOps[recordOps.length - 1] as (typeof recordOps)[0]).wallTime\n\t\t\t\tawait this.upsertMaterializedRecord(\n\t\t\t\t\tthis.db,\n\t\t\t\t\tcollectionName,\n\t\t\t\t\trecordId,\n\t\t\t\t\trecordData,\n\t\t\t\t\tfieldNames,\n\t\t\t\t\tcollectionDef,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t\tupdatedAt,\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tawait this.db.execute(\n\t\t\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(collectionName))} (id, _deleted, _created_at, _updated_at) VALUES (${recordId}, 1, ${Date.now()}, ${Date.now()}) ON CONFLICT (id) DO UPDATE SET _deleted = 1, _updated_at = ${Date.now()}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(where: Record<string, unknown>, includeDeleted: boolean): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${value}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializeFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate async materializeFromOpsLog(collection: string): Promise<MaterializedRecord[]> {\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.collection, collection))\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.sequenceNumber),\n\t\t\t)\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const row of rows) {\n\t\t\tconst recordId = row.recordId\n\t\t\tconst data = row.data !== null ? JSON.parse(row.data) : null\n\n\t\t\tswitch (row.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\trecords.set(recordId, { id: recordId, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\tconst existing = records.get(recordId) ?? { id: recordId }\n\t\t\t\t\t\trecords.set(recordId, { ...existing, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Initialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate async initialize(): Promise<void> {\n\t\tawait this.ensureTables()\n\n\t\t// Hydrate in-memory version vector cache\n\t\tconst rows = await this.db\n\t\t\t.select({\n\t\t\t\tnodeId: pgSyncState.nodeId,\n\t\t\t\tmaxSequenceNumber: pgSyncState.maxSequenceNumber,\n\t\t\t})\n\t\t\t.from(pgSyncState)\n\n\t\tfor (const row of rows) {\n\t\t\tthis.versionVector.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t}\n\n\tprivate async ensureTables(): Promise<void> {\n\t\t// Serialize all schema setup across instances with an advisory transaction lock.\n\t\t// `CREATE TABLE IF NOT EXISTS` is not atomic in Postgres: two servers cold-starting\n\t\t// against the same empty database race and one fails with a duplicate-type error.\n\t\t// Running every setup statement in one advisory-locked transaction makes concurrent\n\t\t// startup safe and also serializes the delivery-sequence backfill.\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended('kora:ensure-tables', 0))`)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\t\tdata TEXT,\n\t\t\t\t\tprevious_data TEXT,\n\t\t\t\t\tatomic_ops TEXT,\n\t\t\t\t\twall_time BIGINT NOT NULL,\n\t\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\t\treceived_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t\t// ops\" and keep materializing by last-write-wins exactly as before.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS atomic_ops TEXT`)\n\n\t\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t\t// delivery watermark.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS delivery_seq BIGINT`)\n\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)`,\n\t\t\t)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)`)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)`)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)`,\n\t\t\t)\n\t\t\t// Index for efficient per-record operation lookups during materialization\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)`,\n\t\t\t)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\t\tmax_sequence_number INTEGER NOT NULL,\n\t\t\t\t\tlast_seen_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Counter row that assigns delivery sequences in commit order. Every append\n\t\t\t// does `UPDATE ... value = value + 1 RETURNING value` inside its transaction,\n\t\t\t// which holds an exclusive row lock until commit. So a later assigner cannot\n\t\t\t// obtain its number until the earlier one has committed: delivery-sequence\n\t\t\t// order equals commit (visibility) order, which is what makes a `> watermark`\n\t\t\t// stream provably gap-free across instances. This serializes appends through\n\t\t\t// one row (correctness over throughput, per the framework's priorities).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\t\tvalue BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backfill any pre-column rows deterministically, then seed the counter to the\n\t\t\t// resulting maximum. Under the advisory lock two starting servers cannot\n\t\t\t// double-assign. The window scan touches only rows lacking a sequence, so a\n\t\t\t// fresh or already-migrated table does almost no work here.\n\t\t\tawait tx.execute(sql`\n\t\t\t\tWITH ordered AS (\n\t\t\t\t\tSELECT id, ROW_NUMBER() OVER (\n\t\t\t\t\t\tORDER BY received_at ASC, sequence_number ASC, id ASC\n\t\t\t\t\t) + COALESCE((SELECT MAX(delivery_seq) FROM operations), 0) AS rn\n\t\t\t\t\tFROM operations WHERE delivery_seq IS NULL\n\t\t\t\t)\n\t\t\t\tUPDATE operations o SET delivery_seq = ordered.rn\n\t\t\t\tFROM ordered WHERE o.id = ordered.id\n\t\t\t`)\n\t\t\tawait tx.execute(sql`\n\t\t\t\tINSERT INTO delivery_counter (id, value)\n\t\t\t\tVALUES (1, COALESCE((SELECT MAX(delivery_seq) FROM operations), 0))\n\t\t\t\tON CONFLICT (id) DO UPDATE\n\t\t\t\t\tSET value = GREATEST(delivery_counter.value, EXCLUDED.value)\n\t\t\t`)\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside an open append transaction. The\n\t * `UPDATE ... RETURNING` locks the counter row until this transaction commits,\n\t * serializing assignment into commit order (see the counter table comment).\n\t */\n\tprivate async nextDeliverySeq(tx: {\n\t\texecute: (query: SQL) => Promise<unknown>\n\t}): Promise<number> {\n\t\tconst rows = (await tx.execute(\n\t\t\tsql`UPDATE delivery_counter SET value = value + 1 WHERE id = 1 RETURNING value`,\n\t\t)) as unknown as { value: number | string | bigint }[]\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\t// The counter row must always exist (ensureTables seeds it). A missing row would\n\t\t\t// silently return 0 and stamp every op with delivery_seq 0, making them invisible\n\t\t\t// to clients (a `> watermark` scan never returns 0). Fail loudly instead of\n\t\t\t// corrupting the delivery stream.\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn Number(value)\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t): typeof pgOperations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\n\t\t\tnodeId: op.nodeId,\n\t\t\ttype: op.type,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tdata: op.data !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof pgOperations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('PostgresServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a PostgresServerStore from a PostgreSQL connection string.\n */\nexport async function createPostgresServerStore(options: {\n\tconnectionString: string\n\tnodeId?: string\n}): Promise<PostgresServerStore> {\n\tconst { postgresClient, drizzleFn } = await loadPostgresDeps()\n\tconst client = postgresClient(options.connectionString)\n\tconst db = drizzleFn(client)\n\n\treturn new PostgresServerStore(db, options.nodeId)\n}\n\nasync function loadPostgresDeps(): Promise<{\n\tpostgresClient: (connectionString: string) => unknown\n\tdrizzleFn: (client: unknown) => PostgresJsDatabase\n}> {\n\ttry {\n\t\tconst dynamicImport = new Function('specifier', 'return import(specifier)') as (\n\t\t\tspecifier: string,\n\t\t) => Promise<unknown>\n\n\t\tconst postgresMod = (await dynamicImport('postgres')) as { default: (cs: string) => unknown }\n\t\tconst drizzleMod = (await dynamicImport('drizzle-orm/postgres-js')) as {\n\t\t\tdrizzle: (client: unknown) => PostgresJsDatabase\n\t\t}\n\n\t\treturn {\n\t\t\tpostgresClient: postgresMod.default,\n\t\t\tdrizzleFn: drizzleMod.drizzle,\n\t\t}\n\t} catch {\n\t\tthrow new Error(\n\t\t\t'PostgreSQL backend requires the \"postgres\" package. Install it in your project dependencies.',\n\t\t)\n\t}\n}\n","import { bigint, index, integer, pgTable, text } from 'drizzle-orm/pg-core'\n\n/**\n * Drizzle schema for the Kora sync server's PostgreSQL database.\n *\n * Two tables:\n * - `pgOperations` — the append-only operation log (content-addressed by id)\n * - `pgSyncState` — tracks the max sequence number seen per node (version vector)\n *\n * Column structure mirrors the SQLite drizzle-schema.ts but uses pgTable.\n */\n\nexport const pgOperations = pgTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: bigint('wall_time', { mode: 'number' }).notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\tsequenceNumber: integer('sequence_number').notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: bigint('received_at', { mode: 'number' }).notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit (assigned from\n\t\t// a counter row locked inside the append transaction, so delivery order equals\n\t\t// visibility order even across instances). Drives the gap-free server->client\n\t\t// delivery watermark. Nullable only for pre-column rows, backfilled on startup.\n\t\tdeliverySeq: bigint('delivery_seq', { mode: 'number' }),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_pg_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_pg_collection').on(table.collection),\n\t\treceivedIdx: index('idx_pg_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_pg_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const pgSyncState = pgTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: integer('max_sequence_number').notNull(),\n\tlastSeenAt: bigint('last_seen_at', { mode: 'number' }).notNull(),\n})\n","import { createRequire } from 'node:module'\nimport type { AtomicOp, Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { generateUUIDv7, quoteIdent } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, eq, gt, sql } from 'drizzle-orm'\nimport type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'\nimport { deliveryCounter, operations, syncState } from './drizzle-schema'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n// better-sqlite3 is a native CJS addon that cannot be loaded via ESM import().\n// createRequire provides a CJS require() that works in both ESM and CJS contexts.\n// tsup's shims option ensures import.meta.url is available in CJS builds.\nconst esmRequire = createRequire(import.meta.url)\n\n/**\n * SQLite-backed server store using Drizzle ORM.\n * Persists operations and version vectors to a real database file,\n * surviving process restarts.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class SqliteServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly db: BetterSQLite3Database\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\n\tconstructor(db: BetterSQLite3Database, nodeId?: string) {\n\t\tthis.db = db\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t\tthis.ensureTables()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.select().from(syncState).all()\n\t\tconst vv: VersionVector = new Map()\n\t\tfor (const row of rows) {\n\t\t\tvv.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t\treturn vv\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.schema = schema\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'sqlite')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tthis.db.run(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"duplicate column\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps SQLite errors, so check both outer message and cause.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.db.run(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// Backfill materialized tables from existing operations\n\t\tawait this.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\tconst now = Date.now()\n\n\t\t// Use a transaction for atomicity: insert op + update version vector + materialize\n\t\tconst result = this.db.transaction((tx) => {\n\t\t\t// Content-addressed dedup: check before assigning a delivery sequence so a\n\t\t\t// duplicate never burns one (keeps the sequence gap-free on this store).\n\t\t\tconst existing = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE id = ${op.id} LIMIT 1`,\n\t\t\t)\n\t\t\tif (existing.length > 0) {\n\t\t\t\treturn 'duplicate' as const\n\t\t\t}\n\n\t\t\tconst row = this.serializeOperation(op, now, this.nextDeliverySeq(tx))\n\t\t\ttx.insert(operations).values(row).run()\n\n\t\t\t// Advance version vector: upsert with MAX to ensure monotonic progress\n\t\t\ttx.insert(syncState)\n\t\t\t\t.values({\n\t\t\t\t\tnodeId: op.nodeId,\n\t\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\t\tlastSeenAt: now,\n\t\t\t\t})\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: syncState.nodeId,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tmaxSequenceNumber: sql`MAX(${syncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\n\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tthis.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t}\n\n\t\t\treturn 'applied' as const\n\t\t})\n\n\t\treturn result\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(and(eq(operations.nodeId, nodeId), between(operations.sequenceNumber, fromSeq, toSeq)))\n\t\t\t.orderBy(asc(operations.sequenceNumber))\n\t\t\t.all()\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\n\t\tconst result = this.db.select({ value: count() }).from(operations).all()\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ m: number | null }>(\n\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t)\n\t\treturn rows[0]?.m ?? 0\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(gt(operations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(operations.deliverySeq))\n\t\t\t.limit(limit)\n\t\t\t.all()\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t}))\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false)\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = this.db.all<{ cnt: number }>(query)\n\t\treturn rows[0]?.cnt ?? 0\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\t// Export in delivery-sequence (commit) order so a restore reassigns delivery\n\t\t// sequences causally; an implicit scan order must not be relied on.\n\t\tconst rows = this.db.select().from(operations).orderBy(asc(operations.deliverySeq)).all()\n\t\tconst deserialized = rows.map((row) => this.deserializeOperation(row))\n\t\tconst vv = this.getVersionVector()\n\n\t\treturn buildServerBackup(this.nodeId, deserialized, vv)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations: ops, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\t// Replace mode: DROP and recreate\n\t\tthis.db.transaction((tx) => {\n\t\t\ttx.run(sql.raw('DELETE FROM operations'))\n\t\t\ttx.run(sql.raw('DELETE FROM sync_state'))\n\t\t\ttx.update(deliveryCounter).set({ value: 0 }).where(eq(deliveryCounter.id, 1)).run()\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\ttx.insert(syncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: Date.now() })\n\t\t\t\t\t.run()\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of ops) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, Date.now(), deliverySeq)\n\t\t\t\ttx.insert(operations).values(row).run()\n\t\t\t}\n\t\t\ttx.update(deliveryCounter).set({ value: deliverySeq }).where(eq(deliveryCounter.id, 1)).run()\n\t\t})\n\n\t\treturn { operationsRestored: ops.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Rebuild a single record in the materialized collection table by replaying\n\t * all operations for that record. Called within the applyRemoteOperation\n\t * transaction for atomic dual-write.\n\t */\n\tprivate rebuildMaterializedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): void {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this specific record, in HLC total order (wallTime,\n\t\t// logical, nodeId) so atomic composition and LWW converge like the merge engine.\n\t\tconst ops = txOrDb\n\t\t\t.select({\n\t\t\t\ttype: operations.type,\n\t\t\t\tdata: operations.data,\n\t\t\t\tatomicOps: operations.atomicOps,\n\t\t\t\twallTime: operations.wallTime,\n\t\t\t})\n\t\t\t.from(operations)\n\t\t\t.where(and(eq(operations.collection, collection), eq(operations.recordId, recordId)))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.timestampNodeId))\n\t\t\t.all()\n\n\t\t// Replay to get current state\n\t\tconst parsedOps = ops.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\tif (recordData) {\n\t\t\t// Compute timestamps from operations\n\t\t\tconst createdAt = ops.length > 0 ? (ops[0] as (typeof ops)[0]).wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\tops.length > 0 ? (ops[ops.length - 1] as (typeof ops)[0]).wallTime : Date.now()\n\n\t\t\tthis.upsertMaterializedRecord(\n\t\t\t\ttxOrDb,\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\trecordData,\n\t\t\t\tfieldNames,\n\t\t\t\tcollectionDef,\n\t\t\t\tcreatedAt,\n\t\t\t\tupdatedAt,\n\t\t\t)\n\t\t} else {\n\t\t\t// Record was deleted — soft-delete in materialized table\n\t\t\ttxOrDb.run(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1, _updated_at = ${Date.now()} WHERE id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t * Uses INSERT ... ON CONFLICT (id) DO UPDATE SET for atomic upsert.\n\t */\n\tprivate upsertMaterializedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t): void {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor ? serializeFieldValue(recordData[f] ?? null, descriptor) : null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\t0, // _deleted = false\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\ttxOrDb.run(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * Backfill all materialized collection tables from the existing operation log.\n\t * Called when setSchema() is invoked and operations already exist.\n\t */\n\tprivate async backfillAllCollections(): Promise<void> {\n\t\tif (!this.schema) return\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tthis.backfillCollection(collectionName)\n\t\t}\n\t}\n\n\t/**\n\t * Backfill a single collection's materialized table from operations.\n\t */\n\tprivate backfillCollection(collectionName: string): void {\n\t\tconst collectionDef = this.schema?.collections[collectionName]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this collection, in HLC total order (wallTime, logical, nodeId).\n\t\tconst allOps = this.db\n\t\t\t.select({\n\t\t\t\trecordId: operations.recordId,\n\t\t\t\ttype: operations.type,\n\t\t\t\tdata: operations.data,\n\t\t\t\tatomicOps: operations.atomicOps,\n\t\t\t\twallTime: operations.wallTime,\n\t\t\t})\n\t\t\t.from(operations)\n\t\t\t.where(eq(operations.collection, collectionName))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.timestampNodeId))\n\t\t\t.all()\n\n\t\tif (allOps.length === 0) return\n\n\t\t// Group by recordId\n\t\tconst grouped = new Map<string, typeof allOps>()\n\t\tfor (const op of allOps) {\n\t\t\tlet group = grouped.get(op.recordId)\n\t\t\tif (!group) {\n\t\t\t\tgroup = []\n\t\t\t\tgrouped.set(op.recordId, group)\n\t\t\t}\n\t\t\tgroup.push(op)\n\t\t}\n\n\t\t// Rebuild each record inside a single transaction for efficiency\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\t\tthis.db.transaction((tx) => {\n\t\t\tfor (const [recordId, recordOps] of grouped) {\n\t\t\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\t\t\ttype: op.type,\n\t\t\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\t\t\tatomicOps:\n\t\t\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t\t\t}))\n\t\t\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\t\t\tif (recordData) {\n\t\t\t\t\tconst createdAt = (recordOps[0] as (typeof recordOps)[0]).wallTime\n\t\t\t\t\tconst updatedAt = (recordOps[recordOps.length - 1] as (typeof recordOps)[0]).wallTime\n\t\t\t\t\tthis.upsertMaterializedRecord(\n\t\t\t\t\t\ttx,\n\t\t\t\t\t\tcollectionName,\n\t\t\t\t\t\trecordId,\n\t\t\t\t\t\trecordData,\n\t\t\t\t\t\tfieldNames,\n\t\t\t\t\t\tcollectionDef,\n\t\t\t\t\t\tcreatedAt,\n\t\t\t\t\t\tupdatedAt,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\ttx.run(\n\t\t\t\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(collectionName))} (id, _deleted, _created_at, _updated_at) VALUES (${recordId}, 1, ${Date.now()}, ${Date.now()}) ON CONFLICT (id) DO UPDATE SET _deleted = 1, _updated_at = ${Date.now()}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(where: Record<string, unknown>, includeDeleted: boolean): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${value}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializeFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\t// Include metadata fields\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOpsLog(collection: string): MaterializedRecord[] {\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(eq(operations.collection, collection))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.sequenceNumber))\n\t\t\t.all()\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const row of rows) {\n\t\t\tconst recordId = row.recordId\n\t\t\tconst data = row.data !== null ? JSON.parse(row.data) : null\n\n\t\t\tswitch (row.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\trecords.set(recordId, { id: recordId, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\tconst existing = records.get(recordId) ?? { id: recordId }\n\t\t\t\t\t\trecords.set(recordId, { ...existing, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Table setup\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Create the operations and sync_state tables if they don't exist.\n\t */\n\tprivate ensureTables(): void {\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\tdata TEXT,\n\t\t\t\tprevious_data TEXT,\n\t\t\t\tatomic_ops TEXT,\n\t\t\t\twall_time INTEGER NOT NULL,\n\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\treceived_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t// ops\" and keep materializing by last-write-wins exactly as before. SQLite has\n\t\t// no ADD COLUMN IF NOT EXISTS, so tolerate the duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN atomic_ops TEXT`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t// delivery watermark. SQLite has no ADD COLUMN IF NOT EXISTS, so tolerate the\n\t\t// duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN delivery_seq INTEGER`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE UNIQUE INDEX IF NOT EXISTS idx_delivery_seq_unique\n\t\t\tON operations (delivery_seq)\n\t\t\tWHERE delivery_seq IS NOT NULL\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)\n\t\t`)\n\n\t\t// Index for efficient per-record operation lookups during materialization\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\tmax_sequence_number INTEGER NOT NULL,\n\t\t\t\tlast_seen_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\tvalue INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.backfillDeliverySequence()\n\t}\n\n\t/**\n\t * Assign delivery sequences to any operations written before the column existed,\n\t * then seed the durable counter from the current max. Ordered by\n\t * (received_at, sequence_number, id) so the backfill is deterministic and stable\n\t * across restarts. A one-time migration: after it runs, all rows have a value.\n\t */\n\tprivate backfillDeliverySequence(): void {\n\t\tthis.db.transaction((tx) => {\n\t\t\tconst maxRow = tx.all<{ m: number | null }>(\n\t\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t\t)\n\t\t\tlet next = maxRow[0]?.m ?? 0\n\t\t\tconst nullRows = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE delivery_seq IS NULL ORDER BY received_at ASC, sequence_number ASC, id ASC`,\n\t\t\t)\n\t\t\tfor (const row of nullRows) {\n\t\t\t\tnext += 1\n\t\t\t\ttx.run(sql`UPDATE operations SET delivery_seq = ${next} WHERE id = ${row.id}`)\n\t\t\t}\n\t\t\ttx.insert(deliveryCounter)\n\t\t\t\t.values({ id: 1, value: next })\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: deliveryCounter.id,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tvalue: sql`MAX(${deliveryCounter.value}, ${next})`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside the append transaction. SQLite locks\n\t * the database for the write transaction, and this counter row keeps sequence\n\t * allocation shared by every SqliteServerStore instance using the same file.\n\t */\n\tprivate nextDeliverySeq(tx: BetterSQLite3Database): number {\n\t\tconst rows = tx\n\t\t\t.update(deliveryCounter)\n\t\t\t.set({ value: sql`${deliveryCounter.value} + 1` })\n\t\t\t.where(eq(deliveryCounter.id, 1))\n\t\t\t.returning({ value: deliveryCounter.value })\n\t\t\t.all()\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn value\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t): typeof operations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\n\t\t\tnodeId: op.nodeId,\n\t\t\ttype: op.type,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tdata: op.data !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof operations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('SqliteServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a SqliteServerStore with a file-backed or in-memory database.\n * Handles database creation, Drizzle wrapping, and table setup.\n *\n * @param options - Configuration options\n * @param options.filename - Path to SQLite database file. Defaults to ':memory:' for testing.\n * @param options.nodeId - Server node ID. Auto-generated if not provided.\n * @returns A ready-to-use SqliteServerStore\n *\n * @example\n * ```typescript\n * import { createSqliteServerStore } from '@korajs/server'\n *\n * const store = createSqliteServerStore({ filename: './kora-server.db' })\n *\n * // Optional: enable materialized collection tables for fast queries\n * await store.setSchema(mySchema)\n *\n * const server = createKoraServer({ store, port: 3001 })\n * ```\n */\nexport function createSqliteServerStore(options: {\n\tfilename?: string\n\tnodeId?: string\n}): SqliteServerStore {\n\t// better-sqlite3 is a native CJS addon — use esmRequire (from createRequire)\n\t// so this works in both ESM and CJS contexts.\n\tconst Database = esmRequire('better-sqlite3')\n\tconst { drizzle } = esmRequire('drizzle-orm/better-sqlite3')\n\n\tconst filename = options.filename ?? ':memory:'\n\tconst sqlite = new Database(filename)\n\n\t// Enable WAL mode for better concurrent read/write performance\n\tsqlite.pragma('journal_mode = WAL')\n\n\tconst db = drizzle(sqlite)\n\treturn new SqliteServerStore(db, options.nodeId)\n}\n","import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'\n\n/**\n * Drizzle schema for the Kora sync server's SQLite database.\n *\n * Two tables:\n * - `operations` — the append-only operation log (content-addressed by id)\n * - `syncState` — tracks the max sequence number seen per node (version vector)\n */\n\nexport const operations = sqliteTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: integer('wall_time').notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\tsequenceNumber: integer('sequence_number').notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: integer('received_at').notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit. Drives the\n\t\t// gap-free server->client delivery watermark. Nullable only for rows written\n\t\t// before the column existed; those are backfilled on startup.\n\t\tdeliverySeq: integer('delivery_seq'),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_collection').on(table.collection),\n\t\treceivedIdx: index('idx_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const syncState = sqliteTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: integer('max_sequence_number').notNull(),\n\tlastSeenAt: integer('last_seen_at').notNull(),\n})\n\nexport const deliveryCounter = sqliteTable('delivery_counter', {\n\tid: integer('id').primaryKey(),\n\tvalue: integer('value').notNull(),\n})\n","import { SyncError } from '@korajs/core'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\nexport interface HttpPollResponse {\n\tstatus: 200 | 204 | 304 | 410\n\tbody?: string | Uint8Array\n\theaders?: Record<string, string>\n}\n\ninterface QueuedMessage {\n\tetag: string\n\tcontentType: string\n\tpayload: string | Uint8Array\n}\n\n/**\n * Server-side transport for HTTP long-polling clients.\n *\n * Incoming client messages are pushed via POST, while outbound server\n * messages are pulled via GET long-poll requests.\n */\nexport class HttpServerTransport implements ServerTransport {\n\tprivate readonly serializer: MessageSerializer\n\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\n\tprivate connected = true\n\tprivate nextSequence = 1\n\tprivate readonly queue: QueuedMessage[] = []\n\n\tconstructor(serializer: MessageSerializer) {\n\t\tthis.serializer = serializer\n\t}\n\n\tsend(message: import('@korajs/sync').SyncMessage): void {\n\t\tif (!this.connected) return\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tconst isBinary = encoded instanceof Uint8Array\n\t\tthis.queue.push({\n\t\t\tetag: this.makeEtag(this.nextSequence++),\n\t\t\tcontentType: isBinary ? 'application/x-protobuf' : 'application/json',\n\t\t\tpayload: encoded,\n\t\t})\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.connected\n\t}\n\n\tclose(code = 1000, reason = 'transport closed'): void {\n\t\tif (!this.connected) return\n\t\tthis.connected = false\n\t\tthis.queue.length = 0\n\t\tthis.closeHandler?.(code, reason)\n\t}\n\n\treceive(payload: string | Uint8Array): void {\n\t\tif (!this.connected) {\n\t\t\tthrow new SyncError('HTTP server transport is closed')\n\t\t}\n\n\t\ttry {\n\t\t\tconst message = this.serializer.decode(payload)\n\t\t\tthis.messageHandler?.(message)\n\t\t} catch (error) {\n\t\t\tthis.errorHandler?.(error instanceof Error ? error : new Error(String(error)))\n\t\t}\n\t}\n\n\tpoll(ifNoneMatch?: string): HttpPollResponse {\n\t\tif (!this.connected) {\n\t\t\treturn { status: 410 }\n\t\t}\n\n\t\tconst next = this.queue[0]\n\t\tif (!next) {\n\t\t\treturn { status: 204 }\n\t\t}\n\n\t\tif (ifNoneMatch && ifNoneMatch === next.etag) {\n\t\t\treturn {\n\t\t\t\tstatus: 304,\n\t\t\t\theaders: { etag: next.etag },\n\t\t\t}\n\t\t}\n\n\t\tthis.queue.shift()\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\tbody: next.payload,\n\t\t\theaders: {\n\t\t\t\t'content-type': next.contentType,\n\t\t\t\tetag: next.etag,\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate makeEtag(sequence: number): string {\n\t\treturn `W/\"${sequence}\"`\n\t}\n}\n","import { SyncError } from '@korajs/core'\nimport type { SyncMessage } from '@korajs/sync'\nimport { JsonMessageSerializer } from '@korajs/sync'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\n/** WebSocket ready states (mirrors ws constants) */\nconst WS_OPEN = 1\n\n/**\n * Minimal interface for a ws.WebSocket instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsWebSocket {\n\treadyState: number\n\tsend(data: string | Uint8Array, callback?: (err?: Error) => void): void\n\tclose(code?: number, reason?: string): void\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tremoveAllListeners(): void\n}\n\n/**\n * Options for WsServerTransport.\n */\nexport interface WsServerTransportOptions {\n\t/** Message serializer. Defaults to JsonMessageSerializer. */\n\tserializer?: MessageSerializer\n}\n\n/**\n * Server-side transport wrapping a ws.WebSocket connection.\n * Created for each incoming client connection.\n */\nexport class WsServerTransport implements ServerTransport {\n\tprivate readonly ws: WsWebSocket\n\tprivate readonly serializer: MessageSerializer\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\n\tconstructor(ws: WsWebSocket, options?: WsServerTransportOptions) {\n\t\tthis.ws = ws\n\t\tthis.serializer = options?.serializer ?? new JsonMessageSerializer()\n\t\tthis.setupListeners()\n\t}\n\n\tsend(message: SyncMessage): void {\n\t\tif (this.ws.readyState !== WS_OPEN) {\n\t\t\tthrow new SyncError('Cannot send message: WebSocket is not open', {\n\t\t\t\treadyState: this.ws.readyState,\n\t\t\t\tmessageType: message.type,\n\t\t\t})\n\t\t}\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tthis.ws.send(encoded)\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.ws.readyState === WS_OPEN\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.ws.close(code ?? 1000, reason ?? 'server closing')\n\t}\n\n\tprivate setupListeners(): void {\n\t\tthis.ws.on('message', (data: unknown) => {\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\ttypeof data !== 'string' &&\n\t\t\t\t\t!(data instanceof Uint8Array) &&\n\t\t\t\t\t!(data instanceof ArrayBuffer)\n\t\t\t\t) {\n\t\t\t\t\tthrow new SyncError('Unsupported WebSocket payload type', {\n\t\t\t\t\t\tpayloadType: typeof data,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst decoded = this.serializer.decode(data)\n\t\t\t\tthis.messageHandler?.(decoded)\n\t\t\t} catch (err) {\n\t\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t\t}\n\t\t})\n\n\t\tthis.ws.on('close', (code: unknown, reason: unknown) => {\n\t\t\tthis.closeHandler?.(Number(code) || 1006, String(reason || 'connection closed'))\n\t\t})\n\n\t\tthis.ws.on('error', (err: unknown) => {\n\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t})\n\t}\n}\n","import type {\n\tKoraEventEmitter,\n\tOperation,\n\tOperationTransform,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { applyOperationTransforms } from '@korajs/core'\nimport { SyncError, generateUUIDv7, hashBlob } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type {\n\tAwarenessUpdateMessage,\n\tBlobChunkPushMessage,\n\tBlobChunkRequestMessage,\n\tBlobChunkResponseMessage,\n\tHandshakeMessage,\n\tMessageSerializer,\n\tOperationBatchMessage,\n\tSyncMessage,\n\tWireFormat,\n\tYjsDocUpdateMessage,\n} from '@korajs/sync'\nimport { decodeBlobChunkBytes } from '@korajs/sync'\nimport {\n\ttype DeltaCursor,\n\tNegotiatedMessageSerializer,\n\tSCHEMA_MISMATCH_PREFIX,\n\ttype SyncQuerySubset,\n\tcreateDeltaCursorFromBatch,\n\tdecodeDeltaCursor,\n\tdedupeQuerySubsets,\n\tencodeDeltaCursor,\n\tisClientSchemaVersionSupported,\n\toperationMatchesQuerySubsets,\n\tsliceOperationsAfterCursor,\n\tversionVectorToWire,\n\twireToVersionVector,\n} from '@korajs/sync'\nimport { applyServerOperation } from '../apply/apply-server-operation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { NoAuthProvider } from '../auth/no-auth'\nimport type { Logger } from '../logging/structured-logger'\nimport { resolveSessionScopes } from '../scopes/resolve-session-scopes'\nimport {\n\tmissingScopeFields,\n\tnormalizeScopeMap,\n\toperationMatchesScopes,\n} from '../scopes/server-scope-filter'\nimport type { ProductionHttpRouteContext } from '../server/route-context'\nimport type { DeliveredOperation, ServerStore } from '../store/server-store'\nimport type { ServerTransport } from '../transport/server-transport'\nimport type { AuthContext, AuthProvider } from '../types'\nimport { isOperationTimestampValid } from './operation-validation'\nimport {\n\tDEFAULT_MAX_OPERATION_BYTES,\n\tDEFAULT_MAX_OPS_PER_MINUTE,\n\tSessionRateLimiter,\n\tvalidateOperationSize,\n} from './session-operation-limits'\n\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\n\n/**\n * Tracks auth providers we have already warned about, so the multi-tenant\n * no-scopes guardrail fires once per server (keyed by provider instance)\n * rather than once per client connection.\n */\nconst warnedUnscopedProviders = new WeakSet<AuthProvider>()\n\n/**\n * Warn once when a real (multi-user) auth provider is configured but an\n * authenticated session resolves to no sync scopes at all.\n *\n * With no scopes, `operationMatchesScopes` treats every operation as visible,\n * which is the correct zero-config behavior for a single-user local-first app.\n * But once a real auth provider is in play, \"no scopes\" means every user syncs\n * every other user's data — a silent cross-tenant data exposure. We cannot flip\n * the default to deny-all without breaking the zero-config promise, so instead\n * we surface the dangerous configuration loudly and exactly once.\n *\n * `null` auth (local-first, no auth) and `NoAuthProvider` (dev/testing) are\n * intentionally excluded: for those, unscoped sync is the intended behavior.\n */\nfunction warnIfMultiTenantWithoutScopes(\n\tauth: AuthProvider | null,\n\tresolvedScopes: unknown,\n\tschema: SchemaDefinition | null,\n): void {\n\tif (!auth || auth instanceof NoAuthProvider) {\n\t\treturn\n\t}\n\tif (resolvedScopes) {\n\t\treturn\n\t}\n\tif (!schema || Object.keys(schema.collections).length === 0) {\n\t\treturn\n\t}\n\tif (warnedUnscopedProviders.has(auth)) {\n\t\treturn\n\t}\n\twarnedUnscopedProviders.add(auth)\n\tconsole.warn(\n\t\t'[kora] An authenticated session resolved to no sync scopes, so every ' +\n\t\t\t\"user will sync every other user's data. Return per-user sync scopes \" +\n\t\t\t\"from your auth provider (for example KoraAuthProvider's resolveScopes) \" +\n\t\t\t'to isolate tenants. Note: declaring sync rules in your schema is not ' +\n\t\t\t'enough on its own — the per-user values come from the auth provider. ' +\n\t\t\t'(This warning is expected for single-tenant apps where all authenticated ' +\n\t\t\t'users are meant to share the same data.)',\n\t)\n}\n\nfunction stableStringify(value: unknown): string {\n\tif (Array.isArray(value)) {\n\t\treturn `[${value.map((item) => stableStringify(item)).join(',')}]`\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst record = value as Record<string, unknown>\n\t\tconst entries = Object.keys(record)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)\n\t\treturn `{${entries.join(',')}}`\n\t}\n\treturn JSON.stringify(value)\n}\n\nfunction sameScopeMap(a: unknown, b: unknown): boolean {\n\tconst normalize = (value: unknown): unknown =>\n\t\tvalue && typeof value === 'object'\n\t\t\t? normalizeScopeMap(value as Record<string, Record<string, unknown>>)\n\t\t\t: value\n\treturn stableStringify(normalize(a) ?? null) === stableStringify(normalize(b) ?? null)\n}\n\n/**\n * Possible states for a client session.\n */\nexport type SessionState = 'connected' | 'authenticated' | 'syncing' | 'streaming' | 'closed'\n\n/**\n * Callback invoked when a session has new operations to relay to other sessions.\n */\nexport type RelayCallback = (sourceSessionId: string, operations: Operation[]) => void\n\n/**\n * Callback invoked when a session receives an awareness update to relay to other sessions.\n */\nexport type AwarenessRelayCallback = (\n\tsourceSessionId: string,\n\tmessage: AwarenessUpdateMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a Yjs doc channel update to relay.\n */\nexport type YjsDocRelayCallback = (sourceSessionId: string, message: YjsDocUpdateMessage) => void\n\n/**\n * Callback invoked when a session receives a blob chunk request to route.\n */\nexport type BlobChunkRequestCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkRequestMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a blob chunk response to route back.\n */\nexport type BlobChunkResponseCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkResponseMessage,\n) => void\n\n/**\n * Persist a blob chunk (or manifest) uploaded by a client, keyed by its content\n * hash. Provided by the server operator; enables central blob storage so bytes\n * survive the authoring device going offline.\n */\nexport type PersistBlobChunk = (hash: string, bytes: Uint8Array) => Promise<void> | void\n\n/**\n * Options for creating a ClientSession.\n */\nexport interface ClientSessionOptions {\n\t/** Unique session identifier */\n\tsessionId: string\n\t/** Transport for this client connection */\n\ttransport: ServerTransport\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Authentication provider (optional) */\n\tauth?: AuthProvider\n\t/** Message serializer */\n\tserializer?: MessageSerializer\n\t/** Event emitter for DevTools integration */\n\temitter?: KoraEventEmitter\n\t/** Structured logger used for protocol and persistence failures */\n\tlogger?: Logger\n\t/** Max operations per sync batch */\n\tbatchSize?: number\n\t/** Schema version the server expects */\n\tschemaVersion?: number\n\t/** Inclusive client schema versions accepted at handshake */\n\tsupportedSchemaVersions?: { min: number; max: number }\n\t/** Transform accepted legacy operations into the server schema before validation. */\n\toperationTransforms?: OperationTransform[]\n\t/** Called when this session has operations to relay to other sessions */\n\tonRelay?: RelayCallback\n\t/** Called when this session receives an awareness update to broadcast */\n\tonAwarenessUpdate?: AwarenessRelayCallback\n\t/** Called when this session receives a Yjs doc channel update to broadcast */\n\tonYjsDocUpdate?: YjsDocRelayCallback\n\t/** Called when this session receives a blob chunk request to route */\n\tonBlobChunkRequest?: BlobChunkRequestCallback\n\t/** Called when this session receives a blob chunk response to route back */\n\tonBlobChunkResponse?: BlobChunkResponseCallback\n\t/** Persist a client-uploaded blob chunk centrally (keyed by content hash) */\n\tpersistBlobChunk?: PersistBlobChunk\n\t/** Called when this session closes */\n\tonClose?: (sessionId: string) => void\n\t/**\n\t * Called on close with relay operations this client never acknowledged, so the\n\t * server can buffer them per node id and redeliver on the client's next\n\t * connection. Closes the window where a relay dropped just before a reconnect\n\t * would otherwise be lost (the per-session retransmit tick never fires in time).\n\t */\n\tonOrphanedRelays?: (nodeId: string, ops: Operation[]) => void\n\t/**\n\t * Called once this session reaches streaming to pull any relay operations buffered\n\t * for its node id while it was disconnected. They are re-sent through the normal\n\t * relay path (re-filtered by this session's current scope).\n\t */\n\ttakeOrphanedRelays?: (nodeId: string) => Operation[]\n\t/** Maximum serialized operation size in bytes. Defaults to 256 KiB. */\n\tmaxOperationBytes?: number\n\t/** Maximum operations accepted per minute for this session. Defaults to 600. */\n\tmaxOpsPerMinute?: number\n\t/**\n\t * Adjudicate untrusted client operations before materialization. When present,\n\t * each incoming operation is passed to this validator; a `reject` decision\n\t * sends an operation-rejected message and skips materialization.\n\t */\n\tvalidateOperation?: OperationValidator\n\t/** Trusted data-plane context handed to the validator (read state, author derived ops). */\n\tkoraContext?: ProductionHttpRouteContext\n}\n\n/**\n * Handles the sync protocol for a single connected client.\n *\n * Lifecycle: connected → (authenticated) → syncing → streaming → closed\n *\n * The session:\n * 1. Receives a handshake from the client\n * 2. Authenticates if an AuthProvider is configured\n * 3. Sends back a HandshakeResponse with the server's version vector\n * 4. Computes and sends the server's delta to the client (paginated)\n * 5. Processes incoming operation batches from the client\n * 6. Transitions to streaming for real-time bidirectional sync\n * 7. Relays new operations to other sessions via the RelayCallback\n */\nexport class ClientSession {\n\tprivate state: SessionState = 'connected'\n\tprivate clientNodeId: string | null = null\n\tprivate authContext: AuthContext | null = null\n\tprivate syncQuerySubsets: SyncQuerySubset[] = []\n\tprivate resumeDeltaCursor: DeltaCursor | null = null\n\n\t/**\n\t * The delivery watermark the client reported at handshake, or null when the client\n\t * does not use the delivery watermark (old client, or no watermark yet). When set,\n\t * the server drives the gap-free server->client stream from delivery sequences\n\t * instead of the version-vector delta.\n\t */\n\tprivate clientDeliveryWatermark: number | null = null\n\t/**\n\t * The highest delivery sequence this client has ACKNOWLEDGED (its confirmed\n\t * watermark, as reported in acks). Incremental streaming pushes resume from here, not\n\t * from the highest sequence sent, so a dropped or unapplied batch is always\n\t * re-included by the next push (which re-scans from the acknowledged position). This\n\t * is what makes streaming recovery independent of any bounded retransmit buffer: there\n\t * is no sent-but-unacked window that a buffer eviction could strand. Seeded from the\n\t * client's reported watermark at handshake.\n\t */\n\tprivate lastAckedDeliverySeq = 0\n\t/**\n\t * Timestamp of the last delivery-stream send attempt. Periodic retransmission uses\n\t * this as its stale window so a slow client does not receive duplicate full-stream\n\t * batches every server tick while the first batch is still being applied.\n\t */\n\tprivate lastDeliveryPushAttemptAtMs = 0\n\tprivate deliveryStallRepeatCount = 0\n\t/** Serializes incremental delivery pushes so their batches never interleave. */\n\tprivate deliveryPushChain: Promise<void> = Promise.resolve()\n\n\t/**\n\t * Relay batches sent to this client but not yet acknowledged, keyed by messageId.\n\t * The client acks every operation-batch it applies; on ack the entry is cleared.\n\t * {@link retransmitPendingRelays} re-sends anything still unacked, so a relay\n\t * dropped by a lossy transport is redelivered instead of leaving the client with a\n\t * permanent version-vector gap (a lost operation) that delta sync cannot recover.\n\t * Bounded so a silent client cannot grow it without limit.\n\t */\n\tprivate readonly pendingRelays = new Map<\n\t\tstring,\n\t\t{ message: SyncMessage; ops: Operation[]; sentAtMs: number }\n\t>()\n\tprivate static readonly MAX_PENDING_RELAYS = 1000\n\n\tprivate readonly sessionId: string\n\tprivate readonly transport: ServerTransport\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly logger: Logger | null\n\tprivate readonly batchSize: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\tprivate readonly onRelay: RelayCallback | null\n\tprivate readonly onAwarenessUpdate: AwarenessRelayCallback | null\n\tprivate readonly onYjsDocUpdate: YjsDocRelayCallback | null\n\tprivate readonly onBlobChunkRequest: BlobChunkRequestCallback | null\n\tprivate readonly onBlobChunkResponse: BlobChunkResponseCallback | null\n\tprivate readonly persistBlobChunk: PersistBlobChunk | null\n\tprivate readonly onClose: ((sessionId: string) => void) | null\n\tprivate readonly onOrphanedRelays: ((nodeId: string, ops: Operation[]) => void) | null\n\tprivate readonly takeOrphanedRelays: ((nodeId: string) => Operation[]) | null\n\tprivate readonly maxOperationBytes: number\n\tprivate readonly maxOpsPerMinute: number\n\tprivate readonly rateLimiter: SessionRateLimiter\n\tprivate readonly validateOperation: OperationValidator | null\n\tprivate readonly koraContext: ProductionHttpRouteContext | null\n\n\tconstructor(options: ClientSessionOptions) {\n\t\tthis.sessionId = options.sessionId\n\t\tthis.transport = options.transport\n\t\tthis.store = options.store\n\t\tthis.auth = options.auth ?? null\n\t\tthis.serializer = options.serializer ?? new NegotiatedMessageSerializer('json')\n\t\tthis.emitter = options.emitter ?? null\n\t\tthis.logger = options.logger ?? null\n\t\tthis.batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.schemaVersion = options.schemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tconst supported = options.supportedSchemaVersions\n\t\tthis.supportedSchemaVersions = supported ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = options.operationTransforms ?? []\n\t\tthis.onRelay = options.onRelay ?? null\n\t\tthis.onAwarenessUpdate = options.onAwarenessUpdate ?? null\n\t\tthis.onYjsDocUpdate = options.onYjsDocUpdate ?? null\n\t\tthis.onBlobChunkRequest = options.onBlobChunkRequest ?? null\n\t\tthis.onBlobChunkResponse = options.onBlobChunkResponse ?? null\n\t\tthis.persistBlobChunk = options.persistBlobChunk ?? null\n\t\tthis.onClose = options.onClose ?? null\n\t\tthis.onOrphanedRelays = options.onOrphanedRelays ?? null\n\t\tthis.takeOrphanedRelays = options.takeOrphanedRelays ?? null\n\t\tthis.maxOperationBytes = options.maxOperationBytes ?? DEFAULT_MAX_OPERATION_BYTES\n\t\tthis.maxOpsPerMinute = options.maxOpsPerMinute ?? DEFAULT_MAX_OPS_PER_MINUTE\n\t\tthis.rateLimiter = new SessionRateLimiter(this.maxOpsPerMinute)\n\t\tthis.validateOperation = options.validateOperation ?? null\n\t\tthis.koraContext = options.koraContext ?? null\n\t}\n\n\t/**\n\t * Start handling messages from the client transport.\n\t */\n\tstart(): void {\n\t\tthis.transport.onMessage((msg) => this.enqueueMessage(msg))\n\t\tthis.transport.onClose((_code, _reason) => this.handleTransportClose())\n\t\tthis.transport.onError((_err) => {\n\t\t\t// Transport errors during active session cause close\n\t\t\tif (this.state !== 'closed') {\n\t\t\t\tthis.handleTransportClose()\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Relay operations from another session to this client.\n\t * Only relays if the session is in streaming state and transport is connected.\n\t */\n\trelayOperations(operations: Operation[]): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t// A delivery-watermark client is fed by the gap-free delivery stream, resumed from\n\t\t// the last sequence sent to it, so its watermark keeps advancing live and a\n\t\t// reconnect resends only what was genuinely missed. The specific operations from\n\t\t// the fan-out are only a wake-up: the push pulls everything in scope after the send\n\t\t// cursor from the delivery log, which is the authoritative, contiguous order.\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tthis.pushDeliveryStream()\n\t\t\treturn\n\t\t}\n\t\tif (operations.length === 0) return\n\t\t// Visibility now requires an async record lookup (scope/subset backfill); relay\n\t\t// is fire-and-forget, so run it without blocking the caller's fan-out loop.\n\t\tvoid this.relayVisibleOperations(operations)\n\t}\n\n\t/**\n\t * Push newly-available in-scope operations to a delivery-watermark client, resuming\n\t * from the highest delivery sequence already sent. Pushes are serialized so their\n\t * batches never interleave (which would break the base/max chain).\n\t */\n\tprivate pushDeliveryStream(): void {\n\t\tthis.deliveryPushChain = this.deliveryPushChain.then(async () => {\n\t\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t\ttry {\n\t\t\t\tthis.lastDeliveryPushAttemptAtMs = Date.now()\n\t\t\t\t// Resume from the client's last acknowledged sequence, not the last sent, so a\n\t\t\t\t// dropped or unapplied batch is re-included here. Exclude the client's own\n\t\t\t\t// operations during streaming; it already has them.\n\t\t\t\tawait this.sendDeliveryStream(\n\t\t\t\t\tthis.lastAckedDeliverySeq,\n\t\t\t\t\tfalse,\n\t\t\t\t\tthis.clientNodeId ?? undefined,\n\t\t\t\t)\n\t\t\t} catch {\n\t\t\t\t// A failed push (e.g. a transient store read error) must not reject the chain\n\t\t\t\t// and stall all future pushes. The next push, or a reconnect resend from the\n\t\t\t\t// client's watermark, recovers anything this push did not deliver.\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate async relayVisibleOperations(operations: Operation[]): Promise<void> {\n\t\tconst visibleOperations: Operation[] = []\n\t\tfor (const op of operations) {\n\t\t\tif (await this.operationVisibleToClient(op)) {\n\t\t\t\tvisibleOperations.push(op)\n\t\t\t}\n\t\t}\n\t\tif (visibleOperations.length === 0) return\n\t\t// Re-check liveness: an await may have elapsed since the caller's guard.\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\n\t\tconst serializedOps = visibleOperations.map((op) => this.serializer.encodeOperation(op))\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: serializedOps,\n\t\t\tisFinal: true,\n\t\t\tbatchIndex: 0,\n\t\t}\n\t\t// Track this relay until the client acks it, so a drop can be retransmitted.\n\t\tthis.trackPendingRelay(msg, visibleOperations)\n\t\tthis.sendToClient(msg)\n\t}\n\n\t/** Record a relay batch as awaiting acknowledgment, evicting the oldest if full. */\n\tprivate trackPendingRelay(msg: SyncMessage, ops: Operation[]): void {\n\t\tif (this.pendingRelays.size >= ClientSession.MAX_PENDING_RELAYS) {\n\t\t\tconst oldest = this.pendingRelays.keys().next().value\n\t\t\tif (oldest !== undefined) {\n\t\t\t\tthis.pendingRelays.delete(oldest)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.set(msg.messageId, { message: msg, ops, sentAtMs: Date.now() })\n\t}\n\n\t/**\n\t * Retransmit relay batches this client has not acknowledged within `staleMs`.\n\t * Called on a periodic tick by the server (and directly by tests). Redelivering an\n\t * already-applied op is harmless: the client dedups by content-addressed id.\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\treturn\n\t\t}\n\t\tif (this.pendingRelays.size === 0) return\n\t\tconst cutoff = Date.now() - staleMs\n\t\tfor (const { message, sentAtMs } of this.pendingRelays.values()) {\n\t\t\tif (sentAtMs <= cutoff) {\n\t\t\t\tthis.sendToClient(message)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Wake the durable delivery stream for clients that negotiated delivery\n\t * watermarks. This is used both for dropped watermark batches and for operations\n\t * appended by another server/store instance: the session always scans from its\n\t * own acknowledged cursor and applies its visibility filter before sending.\n\t */\n\tpushDeliveryStreamIfSupported(staleMs = 0, options: { trackStall?: boolean } = {}): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark === null) return\n\t\tif (staleMs > 0 && Date.now() - this.lastDeliveryPushAttemptAtMs < staleMs) {\n\t\t\treturn\n\t\t}\n\t\tif (options.trackStall) {\n\t\t\tthis.deliveryStallRepeatCount += 1\n\t\t\tif (this.deliveryStallRepeatCount >= 3) {\n\t\t\t\tthis.emitter?.emit({\n\t\t\t\t\ttype: 'sync:delivery-stalled',\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\twatermark: this.lastAckedDeliverySeq,\n\t\t\t\t\trepeatCount: this.deliveryStallRepeatCount,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tthis.pushDeliveryStream()\n\t}\n\n\t/**\n\t * Close this session.\n\t */\n\t/**\n\t * Hand any unacknowledged relays to the server so they survive this session and are\n\t * redelivered when this client reconnects (per-node buffer), then clear them. Called\n\t * from every session-teardown path (explicit close and transport close).\n\t */\n\tprivate flushOrphanedRelays(): void {\n\t\tif (this.onOrphanedRelays && this.clientNodeId && this.pendingRelays.size > 0) {\n\t\t\tconst ops: Operation[] = []\n\t\t\tfor (const entry of this.pendingRelays.values()) {\n\t\t\t\tops.push(...entry.ops)\n\t\t\t}\n\t\t\tif (ops.length > 0) {\n\t\t\t\tthis.onOrphanedRelays(this.clientNodeId, ops)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.clear()\n\t}\n\n\tclose(reason?: string): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.flushOrphanedRelays()\n\n\t\tif (this.transport.isConnected()) {\n\t\t\tthis.transport.close(1000, reason ?? 'session closed')\n\t\t}\n\n\t\tthis.onClose?.(this.sessionId)\n\t}\n\n\t// --- Getters ---\n\n\tgetState(): SessionState {\n\t\treturn this.state\n\t}\n\n\tgetSessionId(): string {\n\t\treturn this.sessionId\n\t}\n\n\tgetClientNodeId(): string | null {\n\t\treturn this.clientNodeId\n\t}\n\n\tgetAuthContext(): AuthContext | null {\n\t\treturn this.authContext\n\t}\n\n\tisStreaming(): boolean {\n\t\treturn this.state === 'streaming'\n\t}\n\n\t/**\n\t * Get the transport for this session.\n\t * Used by the awareness relay to send messages to this client.\n\t */\n\tgetTransport(): ServerTransport {\n\t\treturn this.transport\n\t}\n\n\t// --- Private protocol handlers ---\n\n\tprivate messageChain: Promise<void> = Promise.resolve()\n\n\t/** Send to the client when the transport is still connected; no-op otherwise. */\n\tprivate sendToClient(message: SyncMessage): boolean {\n\t\tif (!this.transport.isConnected()) {\n\t\t\treturn false\n\t\t}\n\t\ttry {\n\t\t\tthis.transport.send(message)\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tprivate enqueueMessage(message: SyncMessage): void {\n\t\tthis.messageChain = this.messageChain\n\t\t\t.then(() => this.handleMessageAsync(message))\n\t\t\t.catch((error) => this.handleMessageFailure(error))\n\t}\n\n\tprivate async handleMessageAsync(message: SyncMessage): Promise<void> {\n\t\tswitch (message.type) {\n\t\t\tcase 'handshake':\n\t\t\t\tawait this.handleHandshake(message)\n\t\t\t\tbreak\n\t\t\tcase 'operation-batch':\n\t\t\t\tawait this.handleOperationBatch(message)\n\t\t\t\tbreak\n\t\t\tcase 'acknowledgment':\n\t\t\t\tthis.pendingRelays.delete(message.acknowledgedMessageId)\n\t\t\t\tif (message.deliverySequence !== undefined) {\n\t\t\t\t\t// Advance the confirmed watermark; the next streaming push resumes here.\n\t\t\t\t\tthis.lastAckedDeliverySeq = Math.max(this.lastAckedDeliverySeq, message.deliverySequence)\n\t\t\t\t\tthis.deliveryStallRepeatCount = 0\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tbreak\n\t\t\tcase 'awareness-update':\n\t\t\t\tthis.handleAwarenessUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'yjs-doc-update':\n\t\t\t\tthis.handleYjsDocUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-request':\n\t\t\t\tthis.onBlobChunkRequest?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-response':\n\t\t\t\tthis.onBlobChunkResponse?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-push':\n\t\t\t\tawait this.handleBlobChunkPush(message)\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * Persist a client-uploaded blob chunk (or manifest) centrally. The bytes are\n\t * verified to hash to the declared hash before storing, so a corrupt or\n\t * mislabeled upload is rejected rather than served later as trusted content.\n\t */\n\tprivate async handleBlobChunkPush(message: BlobChunkPushMessage): Promise<void> {\n\t\tif (!this.persistBlobChunk) {\n\t\t\treturn\n\t\t}\n\t\tconst bytes = decodeBlobChunkBytes(message.bytes)\n\t\tconst actual = await hashBlob(bytes)\n\t\tif (actual !== message.hash) {\n\t\t\t// Reject a mismatched upload rather than persisting untrusted bytes.\n\t\t\treturn\n\t\t}\n\t\tawait this.persistBlobChunk(message.hash, bytes)\n\t}\n\n\tprivate handleMessageFailure(error: unknown): void {\n\t\tconst reason = error instanceof Error ? error.message : 'Message handling failed'\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'error',\n\t\t\tevent: 'session.message_failed',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId: this.clientNodeId ?? undefined,\n\t\t\terror: reason,\n\t\t\tdetails: {\n\t\t\t\tstate: this.state,\n\t\t\t\terrorName: error instanceof Error ? error.name : typeof error,\n\t\t\t},\n\t\t})\n\t\tthis.sendError('SYNC_ERROR', reason, true)\n\t\tthis.close(reason)\n\t}\n\n\tprivate async handleHandshake(msg: HandshakeMessage): Promise<void> {\n\t\t// Only accept handshake in 'connected' state (prevent duplicate handshakes)\n\t\tif (this.state !== 'connected') {\n\t\t\tthis.sendError('DUPLICATE_HANDSHAKE', 'Handshake already completed', false)\n\t\t\treturn\n\t\t}\n\n\t\tthis.clientNodeId = msg.nodeId\n\n\t\t// Authenticate if provider is configured\n\t\tif (this.auth) {\n\t\t\tconst token = msg.authToken ?? ''\n\t\t\tconst context = await this.auth.authenticate(token)\n\t\t\tif (!context) {\n\t\t\t\tthis.sendError('AUTH_FAILED', 'Authentication failed', false)\n\t\t\t\tthis.close('authentication failed')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.authContext = context\n\t\t\tthis.state = 'authenticated'\n\t\t}\n\n\t\t// Merge handshake sync scopes with auth scopes using schema sync rules.\n\t\tconst rawResolvedScopes = resolveSessionScopes(this.store.getSchema(), {\n\t\t\thandshakeScope: msg.syncScope,\n\t\t\tauthScopes: this.authContext?.scopes,\n\t\t})\n\t\tlet resolvedScopes: typeof rawResolvedScopes\n\t\ttry {\n\t\t\tresolvedScopes = rawResolvedScopes ? normalizeScopeMap(rawResolvedScopes) : undefined\n\t\t} catch (error) {\n\t\t\tthis.sendToClient({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tcode: 'SCOPE_PREDICATE_LIMIT',\n\t\t\t\tmessage: error instanceof Error ? error.message : 'Invalid scope predicate',\n\t\t\t\tretriable: false,\n\t\t\t})\n\t\t\tthis.close('invalid scope predicate')\n\t\t\treturn\n\t\t}\n\n\t\tif (resolvedScopes) {\n\t\t\tif (this.authContext) {\n\t\t\t\tthis.authContext = { ...this.authContext, scopes: resolvedScopes }\n\t\t\t} else {\n\t\t\t\tthis.authContext = { userId: msg.nodeId, scopes: resolvedScopes }\n\t\t\t}\n\t\t}\n\n\t\twarnIfMultiTenantWithoutScopes(this.auth, resolvedScopes, this.store.getSchema())\n\n\t\tif (msg.syncQueries && msg.syncQueries.length > 0) {\n\t\t\tthis.syncQuerySubsets = dedupeQuerySubsets(msg.syncQueries)\n\t\t} else {\n\t\t\tthis.syncQuerySubsets = []\n\t\t}\n\n\t\tthis.resumeDeltaCursor = msg.deltaCursor ? decodeDeltaCursor(msg.deltaCursor) : null\n\t\tthis.clientDeliveryWatermark = msg.lastDeliverySequence ?? null\n\t\t// A delivery watermark is valid only for the exact server-visible view that\n\t\t// earned it. When the server resolves a different scope than the client sent\n\t\t// (common with server-auth scopes, promotions, or invite acceptance), the client\n\t\t// cannot have keyed its local watermark by that authoritative view before this\n\t\t// handshake. Reset to a full scoped backfill instead of trusting a cursor that may\n\t\t// have advanced over previously hidden operations.\n\t\tif (\n\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t!sameScopeMap(msg.syncScope, this.authContext?.scopes)\n\t\t) {\n\t\t\tthis.clientDeliveryWatermark = 0\n\t\t}\n\n\t\t// Only read the server's delivery frontier when the client actually uses the\n\t\t// watermark. If the client's reported watermark exceeds that frontier, the server's\n\t\t// log was rolled back (for example a backup restore reset the sequence), so resync\n\t\t// that client from the beginning rather than let it sit above a frontier that no\n\t\t// longer exists; the server advertises its max so the client resets to match.\n\t\tconst clientUsesWatermark = this.clientDeliveryWatermark !== null\n\t\tlet serverMaxDelivery = 0\n\t\tif (clientUsesWatermark) {\n\t\t\tserverMaxDelivery = await this.store.getMaxDeliverySequence()\n\t\t\tif (\n\t\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t\tthis.clientDeliveryWatermark > serverMaxDelivery\n\t\t\t) {\n\t\t\t\tthis.clientDeliveryWatermark = 0\n\t\t\t}\n\t\t}\n\n\t\tconst serverVector = this.store.getVersionVector()\n\t\tconst selectedWireFormat = selectWireFormat(msg.supportedWireFormats)\n\t\tthis.setSerializerWireFormat(selectedWireFormat)\n\n\t\tif (!isClientSchemaVersionSupported(msg.schemaVersion, this.supportedSchemaVersions)) {\n\t\t\tconst { min, max } = this.supportedSchemaVersions\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:schema-mismatch',\n\t\t\t\tclientSchemaVersion: msg.schemaVersion,\n\t\t\t\tserverSchemaVersion: this.schemaVersion,\n\t\t\t\tsupportedMin: min,\n\t\t\t\tsupportedMax: max,\n\t\t\t\treason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t})\n\t\t\tconst response: SyncMessage = {\n\t\t\t\ttype: 'handshake-response',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tnodeId: this.store.getNodeId(),\n\t\t\t\tversionVector: versionVectorToWire(serverVector),\n\t\t\t\tschemaVersion: this.schemaVersion,\n\t\t\t\taccepted: false,\n\t\t\t\trejectReason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t\tsupportedSchemaMin: min,\n\t\t\t\tsupportedSchemaMax: max,\n\t\t\t\tserverTime: Date.now(),\n\t\t\t}\n\t\t\tthis.sendToClient(response)\n\t\t\tthis.close('schema version mismatch')\n\t\t\treturn\n\t\t}\n\n\t\t// Send handshake response with server's version vector and accepted scope\n\t\tconst response: SyncMessage = {\n\t\t\ttype: 'handshake-response',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tnodeId: this.store.getNodeId(),\n\t\t\tversionVector: versionVectorToWire(serverVector),\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\taccepted: true,\n\t\t\tselectedWireFormat,\n\t\t\tserverTime: Date.now(),\n\t\t\t// The server's highest delivery sequence, so a client whose persisted watermark\n\t\t\t// is ahead of it (server rolled back) can reset to a full resync. Sent only to\n\t\t\t// watermark-using clients.\n\t\t\t...(clientUsesWatermark ? { serverMaxDeliverySequence: serverMaxDelivery } : {}),\n\t\t\t// Advertise central blob storage so the client uploads the bytes behind\n\t\t\t// its blob fields, keeping them available after the author goes offline.\n\t\t\t...(this.persistBlobChunk ? { blobStorageEnabled: true } : {}),\n\t\t\t// Confirm the accepted scope so the client knows what data will be synced.\n\t\t\t// This may differ from what the client requested if auth scopes are narrower.\n\t\t\t...(this.authContext?.scopes ? { acceptedScope: this.authContext.scopes } : {}),\n\t\t}\n\t\tthis.sendToClient(response)\n\n\t\tthis.emitter?.emit({ type: 'sync:connected', nodeId: msg.nodeId })\n\n\t\t// Transition to syncing and send the server->client stream. A client that\n\t\t// reports a delivery watermark gets the gap-free delivery stream (resumed from\n\t\t// that watermark); an older client gets the version-vector delta. Both send only\n\t\t// operations visible in this session's scope.\n\t\tthis.state = 'syncing'\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tthis.lastAckedDeliverySeq = this.clientDeliveryWatermark\n\t\t\t// Resuming from a non-zero watermark: the client already holds its own history,\n\t\t\t// so exclude its own operations. A full resync (watermark 0, e.g. a fresh or\n\t\t\t// recovered client) passes no exclusion so it recovers everything, its own\n\t\t\t// operations included.\n\t\t\tconst excludeOwn =\n\t\t\t\tthis.clientDeliveryWatermark > 0 ? (this.clientNodeId ?? undefined) : undefined\n\t\t\tthis.lastDeliveryPushAttemptAtMs = Date.now()\n\t\t\tawait this.sendDeliveryStream(this.clientDeliveryWatermark, true, excludeOwn)\n\t\t} else {\n\t\t\tconst clientVector = wireToVersionVector(msg.versionVector)\n\t\t\tawait this.sendDelta(clientVector)\n\t\t}\n\n\t\t// Transition to streaming after delta is sent\n\t\tthis.state = 'streaming'\n\n\t\t// Redeliver any relays buffered while this client's node id was disconnected\n\t\t// (dropped just before a prior reconnect). relayOperations re-filters them by\n\t\t// this session's current scope and re-tracks them for acknowledgment.\n\t\tif (this.takeOrphanedRelays && this.clientNodeId) {\n\t\t\tconst buffered = this.takeOrphanedRelays(this.clientNodeId)\n\t\t\tif (buffered.length > 0) {\n\t\t\t\tthis.relayOperations(buffered)\n\t\t\t}\n\t\t}\n\t\t// A delivery-watermark client needs no explicit drain here: an operation committed\n\t\t// during the handshake-scan-to-streaming window is picked up by the next streaming\n\t\t// push (or the retransmit tick), which resumes from the client's acknowledged\n\t\t// position. Draining here would re-scan from the not-yet-advanced acknowledged\n\t\t// position and re-send the whole handshake stream.\n\t}\n\n\tprivate async handleOperationBatch(msg: OperationBatchMessage): Promise<void> {\n\t\tconst operations = msg.operations.map((s) => this.serializer.decodeOperation(s))\n\t\tconst applied: Operation[] = []\n\t\tlet acknowledgedThrough = 0\n\t\tlet canAdvanceAck = true\n\n\t\tfor (const op of operations) {\n\t\t\tif (!canAdvanceAck) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!(await this.operationVisibleToClient(op))) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\t'SCOPE_VIOLATION',\n\t\t\t\t\t`Operation \"${op.id}\" in collection \"${op.collection}\" is outside the client's sync scope. Refresh sync scopes and retry.`,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!isOperationTimestampValid(op)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'INVALID_TIMESTAMP',\n\t\t\t\t\t`Operation \"${op.id}\" timestamp is too far in the future`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!this.rateLimiter.allow(1)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'RATE_LIMIT',\n\t\t\t\t\t`Session exceeded operation rate limit (${String(this.maxOpsPerMinute)} ops/min)`,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst sizeCheck = validateOperationSize(op, this.maxOperationBytes)\n\t\t\tif (!sizeCheck.valid) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'OPERATION_TOO_LARGE',\n\t\t\t\t\tsizeCheck.message ?? `Operation \"${op.id}\" is too large`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst serverOp = this.transformForServerSchema(op)\n\t\t\tif (serverOp === null) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\t'SCHEMA_TRANSFORM_UNAVAILABLE',\n\t\t\t\t\t`Operation \"${op.id}\" cannot be transformed from schema v${op.schemaVersion} to server schema v${this.schemaVersion}.`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Server-side adjudication of untrusted client operations. Runs after\n\t\t\t// the built-in guards and before materialization, so a rejected op never\n\t\t\t// enters the authoritative log and never relays to other clients.\n\t\t\tif (this.validateOperation && this.koraContext) {\n\t\t\t\tlet decision: Awaited<ReturnType<OperationValidator>>\n\t\t\t\ttry {\n\t\t\t\t\tdecision = await this.validateOperation(serverOp, {\n\t\t\t\t\t\tauth: this.authContext,\n\t\t\t\t\t\tkora: this.koraContext,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// A throwing validator must not crash ingestion or silently accept.\n\t\t\t\t\t// Treat it as a retriable rejection so the submitter can try again.\n\t\t\t\t\tconst message = error instanceof Error ? error.message : 'validator error'\n\t\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\t\tserverOp,\n\t\t\t\t\t\t'VALIDATION_ERROR',\n\t\t\t\t\t\t`Validator threw: ${message}`,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'reject') {\n\t\t\t\t\tconst retriable = decision.retriable ?? isRetriableRejection(decision.code)\n\t\t\t\t\tthis.sendOperationRejected(serverOp, decision.code, decision.message, retriable)\n\t\t\t\t\tif (retriable) {\n\t\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\t} else {\n\t\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'ignore') {\n\t\t\t\t\t// The server took responsibility out of band; do not materialize the\n\t\t\t\t\t// raw op and do not reject. The batch ack lets the client drop it.\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// action === 'accept' falls through to normal materialization.\n\t\t\t}\n\n\t\t\tconst applyResult = await applyServerOperation(this.store, serverOp)\n\t\t\tif (applyResult.rejection) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\tserverOp,\n\t\t\t\t\tapplyResult.rejection.code,\n\t\t\t\t\tapplyResult.rejection.message,\n\t\t\t\t\tapplyResult.rejection.retriable,\n\t\t\t\t)\n\t\t\t\tif (applyResult.rejection.retriable) {\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t} else {\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (applyResult.result === 'applied') {\n\t\t\t\tapplied.push(...applyResult.appliedOperations)\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t} else {\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t}\n\t\t}\n\n\t\tif (operations.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:received',\n\t\t\t\toperations,\n\t\t\t\tbatchSize: operations.length,\n\t\t\t})\n\t\t}\n\n\t\t// Send acknowledgment\n\t\tconst lastOp = operations[operations.length - 1]\n\t\tconst ack: SyncMessage = {\n\t\t\ttype: 'acknowledgment',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tacknowledgedMessageId: msg.messageId,\n\t\t\tlastSequenceNumber: lastOp ? Math.min(acknowledgedThrough, lastOp.sequenceNumber) : 0,\n\t\t}\n\t\tthis.sendToClient(ack)\n\n\t\t// Relay only newly applied operations to other sessions\n\t\tif (applied.length > 0) {\n\t\t\tthis.onRelay?.(this.sessionId, applied)\n\t\t}\n\t}\n\n\tprivate transformForServerSchema(op: Operation): Operation | null {\n\t\tif (op.schemaVersion === this.schemaVersion) {\n\t\t\treturn op\n\t\t}\n\t\treturn applyOperationTransforms(op, this.schemaVersion, this.operationTransforms)\n\t}\n\n\tprivate async sendDelta(clientVector: Map<string, number>): Promise<void> {\n\t\tconst serverVector = this.store.getVersionVector()\n\t\tconst missing: Operation[] = []\n\n\t\tfor (const [nodeId, serverSeq] of serverVector) {\n\t\t\tconst clientSeq = clientVector.get(nodeId) ?? 0\n\t\t\tif (serverSeq > clientSeq) {\n\t\t\t\tconst ops = await this.store.getOperationRange(nodeId, clientSeq + 1, serverSeq)\n\t\t\t\tfor (const op of ops) {\n\t\t\t\t\tif (await this.operationVisibleToClient(op)) {\n\t\t\t\t\t\tmissing.push(op)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (missing.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tconst sorted = topologicalSort(missing)\n\t\tconst afterCursor = sliceOperationsAfterCursor(sorted, this.resumeDeltaCursor)\n\t\tconst totalBatches = Math.ceil(afterCursor.length / this.batchSize)\n\n\t\tif (afterCursor.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: this.resumeDeltaCursor?.batchIndex ?? 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst start = i * this.batchSize\n\t\t\tconst batchOps = afterCursor.slice(start, start + this.batchSize)\n\t\t\tconst serializedOps = batchOps.map((op) => this.serializer.encodeOperation(op))\n\t\t\tconst batchCursor = createDeltaCursorFromBatch(batchOps, i)\n\n\t\t\tconst batchMsg: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: serializedOps,\n\t\t\t\tisFinal: i === totalBatches - 1,\n\t\t\t\tbatchIndex: i,\n\t\t\t\ttotalBatches,\n\t\t\t\t...(batchCursor ? { cursor: encodeDeltaCursor(batchCursor) } : {}),\n\t\t\t}\n\t\t\tthis.sendToClient(batchMsg)\n\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: batchOps,\n\t\t\t\tbatchSize: batchOps.length,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Send the gap-free server->client delivery stream, resuming just after\n\t * `fromDeliverySeq`. Operations are scanned in server delivery-sequence order\n\t * (commit order), scope-filtered for this session, and sent in batches that chain:\n\t * each batch's `baseDeliverySequence` equals the previous batch's\n\t * `maxDeliverySequence` (the first batch bases on `fromDeliverySeq`). The client\n\t * applies a batch only when its watermark equals the base and advances the\n\t * watermark to the max, so a dropped batch stalls the watermark and is recovered by\n\t * the next handshake resend. Because delivery-sequence order respects causal order\n\t * (a dependency is always committed, and thus sequenced, before its dependent), no\n\t * topological sort is needed and the client never defers on a missing dependency\n\t * that is itself in this stream.\n\t *\n\t * The final batch advances the watermark to the highest delivery sequence scanned,\n\t * not merely the last in-scope one, so an out-of-scope tail is not re-scanned on the\n\t * next reconnect. Returns the number of operations actually sent.\n\t */\n\tprivate async sendDeliveryStream(\n\t\tfromDeliverySeq: number,\n\t\tfinalizeWhenEmpty: boolean,\n\t\texcludeNodeId?: string,\n\t): Promise<number> {\n\t\tconst scanChunk = Math.max(this.batchSize, 1) * 5\n\t\tlet scanCursor = fromDeliverySeq\n\t\tlet maxScanned = fromDeliverySeq\n\t\tconst visible: DeliveredOperation[] = []\n\n\t\twhile (true) {\n\t\t\tconst chunk = await this.store.getOperationsAfterDelivery(scanCursor, scanChunk)\n\t\t\tconst last = chunk[chunk.length - 1]\n\t\t\tif (last === undefined) break\n\t\t\tscanCursor = last.deliverySequence\n\t\t\t// maxScanned counts every operation scanned, including any excluded (own or\n\t\t\t// out-of-scope) ones, so the batch max advances the client's watermark past\n\t\t\t// them even though they are not sent.\n\t\t\tmaxScanned = scanCursor\n\t\t\tfor (const delivered of chunk) {\n\t\t\t\t// Skip the client's own operations during streaming: it already holds them,\n\t\t\t\t// so echoing them back is pure waste. They are still counted in maxScanned,\n\t\t\t\t// and a full resync (fromDeliverySeq 0) passes no excludeNodeId, so a client\n\t\t\t\t// that lost its local store still recovers its own history.\n\t\t\t\tif (excludeNodeId !== undefined && delivered.operation.nodeId === excludeNodeId) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (await this.operationVisibleToClient(delivered.operation)) {\n\t\t\t\t\tvisible.push(delivered)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (chunk.length < scanChunk) break\n\t\t}\n\n\t\tif (visible.length === 0) {\n\t\t\t// Nothing in scope after the cursor. On a handshake resume, send a single empty\n\t\t\t// final batch so the client advances past an out-of-scope tail and completes\n\t\t\t// initial sync. During streaming, send nothing (an empty batch every relay tick\n\t\t\t// would be pure noise); a reconnect re-scans the small tail if needed.\n\t\t\tif (finalizeWhenEmpty) {\n\t\t\t\tthis.sendDeliveryBatch([], fromDeliverySeq, maxScanned, 0, true)\n\t\t\t}\n\t\t\treturn 0\n\t\t}\n\n\t\tconst totalBatches = Math.ceil(visible.length / this.batchSize)\n\t\tlet base = fromDeliverySeq\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst slice = visible.slice(i * this.batchSize, (i + 1) * this.batchSize)\n\t\t\tconst lastInSlice = slice[slice.length - 1]\n\t\t\tif (lastInSlice === undefined) continue\n\t\t\tconst isFinal = i === totalBatches - 1\n\t\t\tconst lastSeq = lastInSlice.deliverySequence\n\t\t\t// The final batch carries the max scanned sequence (>= lastSeq) so the client\n\t\t\t// skips past any out-of-scope operations above the last in-scope one.\n\t\t\tconst max = isFinal ? Math.max(maxScanned, lastSeq) : lastSeq\n\t\t\tthis.sendDeliveryBatch(slice, base, max, i, isFinal)\n\t\t\tbase = max\n\t\t}\n\t\treturn visible.length\n\t}\n\n\t/** Build, track, and send one chained delivery-stream batch. */\n\tprivate sendDeliveryBatch(\n\t\tslice: DeliveredOperation[],\n\t\tbase: number,\n\t\tmax: number,\n\t\tbatchIndex: number,\n\t\tisFinal: boolean,\n\t): void {\n\t\tconst batchMsg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: slice.map((delivered) => this.serializer.encodeOperation(delivered.operation)),\n\t\t\tisFinal,\n\t\t\tbatchIndex,\n\t\t\tbaseDeliverySequence: base,\n\t\t\tmaxDeliverySequence: max,\n\t\t}\n\t\t// Delivery batches are NOT tracked in the bounded pending-relay buffer: recovery of\n\t\t// a dropped or unapplied batch is by re-scan from the client's acknowledged\n\t\t// position (the next push or the retransmit tick), which cannot be defeated by a\n\t\t// buffer eviction. The client re-acks a duplicate and stalls on a gap, so re-sends\n\t\t// are always safe.\n\t\tthis.sendToClient(batchMsg)\n\t\tif (slice.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: slice.map((delivered) => delivered.operation),\n\t\t\t\tbatchSize: slice.length,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate async operationVisibleToClient(op: Operation): Promise<boolean> {\n\t\tconst scopes = this.authContext?.scopes\n\t\tconst subsets = this.syncQuerySubsets\n\t\t// A partial update (or a delete) may not carry the scope / query-subset fields\n\t\t// in its own data. Judging visibility from the bare op would wrongly hide such\n\t\t// an operation, so backfill those fields from the materialized record (including\n\t\t// a soft-deleted one) whenever they are missing. Only look up when needed so the\n\t\t// common case (inserts, or ops that already carry the fields) stays lookup-free.\n\t\tconst needsBackfill =\n\t\t\tmissingScopeFields(op, scopes).length > 0 || (subsets !== undefined && subsets.length > 0)\n\t\tconst fullRecord = needsBackfill\n\t\t\t? await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\t: undefined\n\n\t\tif (!operationMatchesScopes(op, scopes, fullRecord)) {\n\t\t\treturn false\n\t\t}\n\t\treturn operationMatchesQuerySubsets(op, subsets, fullRecord)\n\t}\n\n\t/**\n\t * Read a record's current field values from the materialized store for scope /\n\t * query-subset backfill. Includes soft-deleted rows so a relayed delete (whose op\n\t * carries no fields) is still judged against the record's actual scope. Returns\n\t * undefined when the record cannot be read (never materialized, or no schema).\n\t */\n\tprivate async lookupRecordFields(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<Record<string, unknown> | undefined> {\n\t\ttry {\n\t\t\tconst rows = await this.store.queryCollection(collection, {\n\t\t\t\twhere: { id: recordId },\n\t\t\t\tincludeDeleted: true,\n\t\t\t\tlimit: 1,\n\t\t\t})\n\t\t\treturn rows[0]\n\t\t} catch {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tprivate handleAwarenessUpdate(msg: AwarenessUpdateMessage): void {\n\t\t// Relay awareness updates to the server for broadcasting to other clients.\n\t\t// Awareness is purely ephemeral -- no persistence.\n\t\tthis.onAwarenessUpdate?.(this.sessionId, msg)\n\t}\n\n\tprivate handleYjsDocUpdate(msg: YjsDocUpdateMessage): void {\n\t\tthis.onYjsDocUpdate?.(this.sessionId, msg)\n\t}\n\n\tprivate sendError(code: string, message: string, retriable: boolean): void {\n\t\tconst errorMsg: SyncMessage = {\n\t\t\ttype: 'error',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(errorMsg)\n\t}\n\n\t/**\n\t * Reject one specific client operation, tied to its id, so the submitter can\n\t * divert it out of its pending queue into a durable rejected store rather than\n\t * losing it or retrying forever. The op is NOT materialized, so no other\n\t * replica ever sees it.\n\t */\n\tprivate sendOperationRejected(\n\t\top: Operation,\n\t\tcode: string,\n\t\tmessage: string,\n\t\tretriable: boolean,\n\t): void {\n\t\tconst rejectedMsg: SyncMessage = {\n\t\t\ttype: 'operation-rejected',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperationId: op.id,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(rejectedMsg)\n\t}\n\n\tprivate setSerializerWireFormat(format: WireFormat): void {\n\t\tif (typeof this.serializer.setWireFormat === 'function') {\n\t\t\tthis.serializer.setWireFormat(format)\n\t\t}\n\t}\n\n\tprivate handleTransportClose(): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.flushOrphanedRelays()\n\t\tthis.emitter?.emit({ type: 'sync:disconnected', reason: 'transport closed' })\n\t\tthis.onClose?.(this.sessionId)\n\t}\n}\n\nfunction selectWireFormat(supportedWireFormats?: WireFormat[]): WireFormat {\n\tif (supportedWireFormats?.includes('protobuf')) {\n\t\treturn 'protobuf'\n\t}\n\n\treturn 'json'\n}\n","import type { Operation } from '@korajs/core'\nimport { buildMergeRelationLookup, checkReferentialIntegrityOnDelete } from '@korajs/merge'\nimport type { ApplyResult } from '@korajs/sync'\nimport { validateIncomingOperationConstraints } from '../constraints/operation-constraint-validator'\nimport { createServerReferentialContext } from '../constraints/server-referential-context'\nimport type { ServerStore } from '../store/server-store'\nimport { type OperationRejection, isRetriableRejection } from './rejection-taxonomy'\nimport {\n\tcreateServerSideEffectOperation,\n\tnextServerSequenceNumber,\n} from './server-side-effect-operation'\n\nexport interface ApplyServerOperationResult {\n\t/** Result of applying the primary operation */\n\tresult: ApplyResult\n\t/** Primary op when applied, plus any server-generated side-effect operations */\n\tappliedOperations: Operation[]\n\t/** Rejection reason when the operation was not applied */\n\trejection?: OperationRejection\n}\n\n/**\n * Applies an incoming client operation with Tier 2 constraints and referential integrity.\n * Cascade/set-null side effects are persisted as server-originated operations in the op log.\n */\nexport async function applyServerOperation(\n\tstore: ServerStore,\n\top: Operation,\n\trelationLookup?: ReturnType<typeof buildMergeRelationLookup>,\n): Promise<ApplyServerOperationResult> {\n\tconst schema = store.getSchema()\n\tconst lookup = relationLookup ?? (schema ? buildMergeRelationLookup(schema) : new Map())\n\n\tconst shapeCheck = validateOperationShape(op, schema)\n\tif (!shapeCheck.valid) {\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode: shapeCheck.code ?? 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\tmessage: shapeCheck.message ?? `Operation \"${op.id}\" does not match the server schema`,\n\t\t\t\tretriable: false,\n\t\t\t},\n\t\t}\n\t}\n\n\tconst constraintCheck = await validateIncomingOperationConstraints(store, op, schema)\n\tif (!constraintCheck.valid) {\n\t\tconst code = constraintCheck.code ?? 'CONSTRAINT_VIOLATION'\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode,\n\t\t\t\tmessage: constraintCheck.message ?? `Operation \"${op.id}\" violates a schema constraint`,\n\t\t\t\tretriable: isRetriableRejection(code),\n\t\t\t},\n\t\t}\n\t}\n\n\tif (op.type === 'delete' && schema) {\n\t\tconst refCtx = createServerReferentialContext(store)\n\t\tconst referential = await checkReferentialIntegrityOnDelete(op, schema, refCtx, lookup)\n\n\t\tif (!referential.allowed) {\n\t\t\treturn {\n\t\t\t\tresult: 'skipped',\n\t\t\t\tappliedOperations: [],\n\t\t\t\trejection: {\n\t\t\t\t\tcode: 'REFERENTIAL_INTEGRITY',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" violates referential integrity on \"${op.collection}\"`,\n\t\t\t\t\tretriable: isRetriableRejection('REFERENTIAL_INTEGRITY'),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\tconst primaryResult = await store.applyRemoteOperation(op)\n\t\tif (primaryResult !== 'applied') {\n\t\t\treturn { result: primaryResult, appliedOperations: [] }\n\t\t}\n\n\t\tconst appliedOperations: Operation[] = [op]\n\n\t\tfor (const effect of referential.sideEffectOps) {\n\t\t\t// Allocate each side-effect's sequence number individually. On a store\n\t\t\t// that reserves atomically (Postgres), this keeps a concurrent conditional\n\t\t\t// apply from being handed the same server sequence number; on a serialized\n\t\t\t// store, each allocation reads the version vector the prior apply advanced.\n\t\t\tconst sideOp = await createServerSideEffectOperation(\n\t\t\t\tstore,\n\t\t\t\top,\n\t\t\t\teffect,\n\t\t\t\top.schemaVersion,\n\t\t\t\tnextServerSequenceNumber(store),\n\t\t\t)\n\t\t\tconst sideResult = await store.applyRemoteOperation(sideOp)\n\t\t\tif (sideResult === 'applied') {\n\t\t\t\tappliedOperations.push(sideOp)\n\t\t\t}\n\t\t}\n\n\t\treturn { result: 'applied', appliedOperations }\n\t}\n\n\tconst result = await store.applyRemoteOperation(op)\n\treturn {\n\t\tresult,\n\t\tappliedOperations: result === 'applied' ? [op] : [],\n\t}\n}\n\nfunction validateOperationShape(\n\top: Operation,\n\tschema: ReturnType<ServerStore['getSchema']>,\n): { valid: true } | { valid: false; code: string; message: string } {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tconst collection = schema.collections[op.collection]\n\tif (!collection) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'UNKNOWN_COLLECTION',\n\t\t\tmessage: `Operation \"${op.id}\" targets unknown collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst declaredFields = new Set(Object.keys(collection.fields))\n\tconst systemPreviousFields = new Set(['id', '_created_at', '_updated_at', '_deleted'])\n\tconst invalidDataField = firstInvalidField(op.data, declaredFields)\n\tif (invalidDataField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidDataField}\" in data for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst invalidPreviousField = firstInvalidField(\n\t\top.previousData,\n\t\tdeclaredFields,\n\t\tsystemPreviousFields,\n\t)\n\tif (invalidPreviousField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidPreviousField}\" in previousData for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tif (op.atomicOps) {\n\t\tfor (const field of Object.keys(op.atomicOps)) {\n\t\t\tif (!declaredFields.has(field)) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" contains undeclared atomic field \"${field}\" for collection \"${op.collection}\".`,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { valid: true }\n}\n\nfunction firstInvalidField(\n\tvalue: unknown,\n\tdeclaredFields: Set<string>,\n\textraAllowedFields?: Set<string>,\n): string | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\tif (typeof value !== 'object' || Array.isArray(value)) {\n\t\treturn null\n\t}\n\tfor (const field of Object.keys(value)) {\n\t\tif (!declaredFields.has(field) && !extraAllowedFields?.has(field)) {\n\t\t\treturn field\n\t\t}\n\t}\n\treturn null\n}\n","import type { Operation, SchemaDefinition } from '@korajs/core'\nimport { checkConstraints } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\nimport { createServerConstraintContext } from './server-constraint-context'\n\nexport interface OperationConstraintValidation {\n\tvalid: boolean\n\tcode?: string\n\tmessage?: string\n}\n\n/**\n * Validates an incoming operation against Tier 2 schema constraints on the server.\n * Deletes are skipped (removal cannot violate capacity/unique on the deleted row).\n */\nexport async function validateIncomingOperationConstraints(\n\tstore: ServerStore,\n\top: Operation,\n\tschema: SchemaDefinition | null,\n): Promise<OperationConstraintValidation> {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tif (op.type === 'delete') {\n\t\treturn { valid: true }\n\t}\n\n\tconst collectionDef = schema.collections[op.collection]\n\tif (!collectionDef || collectionDef.constraints.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst candidate = await projectCandidateRecord(store, op)\n\tif (candidate === null) {\n\t\treturn { valid: true }\n\t}\n\n\tconst ctx = createServerConstraintContext(store)\n\tconst violations = await checkConstraints(\n\t\tcandidate,\n\t\top.recordId,\n\t\top.collection,\n\t\tcollectionDef,\n\t\tctx,\n\t)\n\n\tif (violations.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst first = violations[0]\n\tif (first === undefined) {\n\t\treturn { valid: true }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tcode: 'CONSTRAINT_VIOLATION',\n\t\tmessage: first.message,\n\t}\n}\n\nasync function projectCandidateRecord(\n\tstore: ServerStore,\n\top: Operation,\n): Promise<Record<string, unknown> | null> {\n\tif (op.data === null) {\n\t\treturn null\n\t}\n\n\tconst existing = await store.findRecord(op.collection, op.recordId)\n\tconst base = existing ? { ...existing } : {}\n\n\tif (op.type === 'insert') {\n\t\treturn { ...op.data, id: op.recordId }\n\t}\n\n\treturn { ...base, ...op.data, id: op.recordId }\n}\n","import type { ConstraintContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for Tier 2 constraint checks.\n */\nexport function createServerConstraintContext(store: ServerStore): ConstraintContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync countRecords(collection: string, where: Record<string, unknown>): Promise<number> {\n\t\t\treturn store.countCollection(collection, where)\n\t\t},\n\t}\n}\n","import type { ReferentialMergeContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for referential integrity checks.\n */\nexport function createServerReferentialContext(store: ServerStore): ReferentialMergeContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync recordExists(collection: string, recordId: string): Promise<boolean> {\n\t\t\tconst row = await store.findRecord(collection, recordId)\n\t\t\treturn row !== null && row._deleted !== 1\n\t\t},\n\t}\n}\n","import { HybridLogicalClock, createOperation } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\nimport type { SideEffectOp } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Converts a merge-package referential side effect into a server-originated operation.\n */\nexport async function createServerSideEffectOperation(\n\tstore: ServerStore,\n\tparentOp: Operation,\n\teffect: SideEffectOp,\n\tschemaVersion: number,\n\tsequenceNumber: number,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\tconst clock = new HybridLogicalClock(nodeId)\n\tclock.receive(parentOp.timestamp)\n\n\treturn createOperation(\n\t\t{\n\t\t\tnodeId,\n\t\t\ttype: effect.type === 'delete' ? 'delete' : 'update',\n\t\t\tcollection: effect.collection,\n\t\t\trecordId: effect.recordId,\n\t\t\tdata: effect.data,\n\t\t\tpreviousData: effect.previousData,\n\t\t\tsequenceNumber,\n\t\t\tcausalDeps: [parentOp.id],\n\t\t\tschemaVersion,\n\t\t},\n\t\tclock,\n\t)\n}\n\n/**\n * Allocate the next sequence number for server-originated operations.\n */\nexport function nextServerSequenceNumber(store: ServerStore): number {\n\t// Prefer the store's atomic reservation when it serves writes concurrently (the\n\t// Postgres conditional path), so two in-flight server operations never collide on\n\t// a sequence number. Serialized stores fall back to the version vector, which is\n\t// safe because only one server operation is ever in flight at a time.\n\tif (store.reserveSequenceNumber) {\n\t\treturn store.reserveSequenceNumber()\n\t}\n\tconst nodeId = store.getNodeId()\n\tconst current = store.getVersionVector().get(nodeId) ?? 0\n\treturn current + 1\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Auth provider that accepts all connections.\n * Returns a default anonymous context for any token.\n * Useful for development and testing.\n */\nexport class NoAuthProvider implements AuthProvider {\n\tasync authenticate(_token: string): Promise<AuthContext> {\n\t\treturn { userId: 'anonymous' }\n\t}\n}\n","import type { ScopeMap } from '@korajs/core'\nimport { type SchemaDefinition, buildScopeMap } from '@korajs/core'\n\nexport interface ResolveSessionScopesOptions {\n\t/** Scope map sent by the client during handshake */\n\thandshakeScope?: ScopeMap\n\t/** Scope map from the auth provider (server-controlled) */\n\tauthScopes?: ScopeMap\n\t/** Flat scope values used to derive schema sync rules */\n\tscopeValues?: Record<string, unknown>\n}\n\n/**\n * Resolve the effective per-session sync scope map.\n *\n * Combines schema sync rules, auth scopes, and client handshake scopes into\n * a single unified model. Auth scopes take precedence over handshake scopes\n * per collection; schema sync rules define which collections participate in\n * partial sync.\n */\nexport function resolveSessionScopes(\n\tschema: SchemaDefinition | null,\n\toptions: ResolveSessionScopesOptions,\n): ScopeMap | undefined {\n\tconst { handshakeScope, authScopes, scopeValues } = options\n\n\tlet resolved: ScopeMap | undefined\n\n\tif (schema && scopeValues && Object.keys(scopeValues).length > 0) {\n\t\tresolved = buildScopeMap(schema, scopeValues)\n\t} else if (handshakeScope) {\n\t\tresolved = { ...handshakeScope }\n\t} else if (authScopes) {\n\t\tresolved = { ...authScopes }\n\t}\n\n\tif (schema && !resolved && scopeValues) {\n\t\tresolved = buildScopeMap(schema, scopeValues)\n\t}\n\n\tif (authScopes) {\n\t\tresolved = mergeScopeMaps(resolved, authScopes, 'auth')\n\t}\n\n\tif (handshakeScope) {\n\t\tresolved = mergeScopeMaps(resolved, handshakeScope, 'handshake')\n\t}\n\n\treturn resolved && Object.keys(resolved).length > 0 ? resolved : undefined\n}\n\nfunction mergeScopeMaps(\n\tbase: ScopeMap | undefined,\n\toverlay: ScopeMap,\n\tsource: 'auth' | 'handshake',\n): ScopeMap {\n\tconst merged: ScopeMap = { ...(base ?? {}) }\n\n\tfor (const [collection, overlayScope] of Object.entries(overlay)) {\n\t\tif (source === 'auth') {\n\t\t\tmerged[collection] = { ...(merged[collection] ?? {}), ...overlayScope }\n\t\t} else {\n\t\t\tmerged[collection] = { ...(overlayScope ?? {}), ...(merged[collection] ?? {}) }\n\t\t}\n\t}\n\n\treturn merged\n}\n","import type { Operation } from '@korajs/core'\n\n/**\n * Per-collection scope map from auth context.\n */\nexport type ScopeMap = Record<string, Record<string, unknown>>\n\nexport const DEFAULT_MAX_SCOPE_PREDICATE_VALUES = 100\n\n/** Canonicalize bounded `$in` predicates so equivalent authorization has one signature. */\nexport function normalizeScopeMap(\n\tscopes: ScopeMap,\n\tmaxValues = DEFAULT_MAX_SCOPE_PREDICATE_VALUES,\n): ScopeMap {\n\tconst normalized: ScopeMap = {}\n\tfor (const collection of Object.keys(scopes).sort()) {\n\t\tconst predicate: Record<string, unknown> = {}\n\t\tfor (const field of Object.keys(scopes[collection] ?? {}).sort()) {\n\t\t\tconst expected = scopes[collection]?.[field]\n\t\t\tif (\n\t\t\t\texpected &&\n\t\t\t\ttypeof expected === 'object' &&\n\t\t\t\t!Array.isArray(expected) &&\n\t\t\t\t'$in' in expected\n\t\t\t) {\n\t\t\t\tconst values = (expected as { $in?: unknown }).$in\n\t\t\t\tif (!Array.isArray(values))\n\t\t\t\t\tthrow new Error(`Invalid $in predicate for ${collection}.${field}`)\n\t\t\t\tconst unique = [...new Map(values.map((value) => [stableValueKey(value), value])).values()]\n\t\t\t\tif (unique.length > maxValues)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Scope predicate for ${collection}.${field} exceeds the ${maxValues}-value limit`,\n\t\t\t\t\t)\n\t\t\t\tpredicate[field] = {\n\t\t\t\t\t$in: unique.sort((a, b) => stableValueKey(a).localeCompare(stableValueKey(b))),\n\t\t\t\t}\n\t\t\t} else predicate[field] = expected\n\t\t}\n\t\tnormalized[collection] = predicate\n\t}\n\treturn normalized\n}\n\nfunction stableValueKey(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(stableValueKey).join(',')}]`\n\tif (value && typeof value === 'object')\n\t\treturn `{${Object.keys(value as Record<string, unknown>)\n\t\t\t.sort()\n\t\t\t.map(\n\t\t\t\t(key) =>\n\t\t\t\t\t`${JSON.stringify(key)}:${stableValueKey((value as Record<string, unknown>)[key])}`,\n\t\t\t)\n\t\t\t.join(',')}}`\n\treturn JSON.stringify(value)\n}\n\n/**\n * Returns true if an operation is visible to a session based on its scopes.\n *\n * Rules:\n * - No scopes configured => visible\n * - Collection missing from scope map => hidden\n * - All scoped field/value pairs must match the operation snapshot\n */\nexport function operationMatchesScopes(\n\top: Operation,\n\tscopes: ScopeMap | undefined,\n\tfullRecord?: Record<string, unknown> | null,\n): boolean {\n\tif (!scopes) return true\n\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return false\n\tif (Object.keys(collectionScope).length === 0) return true\n\n\tconst snapshot = buildSnapshot(op, fullRecord)\n\tif (!snapshot) return false\n\n\tfor (const [field, expected] of Object.entries(collectionScope)) {\n\t\tif (!matchesPredicate(snapshot[field], expected)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunction matchesPredicate(actual: unknown, expected: unknown): boolean {\n\tif (expected && typeof expected === 'object' && !Array.isArray(expected) && '$in' in expected) {\n\t\tconst values = (expected as { $in?: unknown }).$in\n\t\treturn Array.isArray(values) && values.some((value) => Object.is(actual, value))\n\t}\n\treturn Object.is(actual, expected)\n}\n\n/**\n * Returns the scope fields (for `op.collection`) that a bare operation does NOT\n * carry in its own `data`/`previousData`. When any are missing, the caller must\n * backfill them from the materialized record before scope-checking, otherwise a\n * partial update (or a delete) that does not restate the scope field is wrongly\n * judged out of scope and dropped from relay/delta — silently diverging tenants.\n */\nexport function missingScopeFields(op: Operation, scopes: ScopeMap | undefined): string[] {\n\tif (!scopes) return []\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return []\n\tif (Object.keys(collectionScope).length === 0) return []\n\tconst snapshot = buildSnapshot(op)\n\treturn Object.keys(collectionScope).filter((field) => !snapshot || !(field in snapshot))\n}\n\nfunction buildSnapshot(\n\top: Operation,\n\tfullRecord?: Record<string, unknown> | null,\n): Record<string, unknown> | null {\n\tconst previous = asRecord(op.previousData)\n\tconst next = asRecord(op.data)\n\n\tif (!previous && !next && !fullRecord) return null\n\n\treturn {\n\t\t...(fullRecord ?? {}),\n\t\t...(previous ?? {}),\n\t\t...(next ?? {}),\n\t}\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\treturn null\n\t}\n\n\treturn value as Record<string, unknown>\n}\n","import { MAX_LOGICAL } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\n\n/** Max allowed future skew for operation timestamps at server ingest (1 minute). */\nexport const SERVER_MAX_TIMESTAMP_FUTURE_MS = 60_000\n\n/**\n * Returns false when an operation's HLC timestamp is structurally invalid or\n * unreasonably far in the future.\n *\n * Structural checks matter because operations are content-addressed and\n * immutable: a timestamp with a non-integer/negative field or a logical\n * counter past the 5-digit serialization cap would poison the shared log\n * forever (its serialized form no longer sorts like HybridLogicalClock.compare),\n * so it must never be accepted at ingest.\n */\nexport function isOperationTimestampValid(op: Operation, now: number = Date.now()): boolean {\n\tconst { wallTime, logical } = op.timestamp\n\tif (!Number.isInteger(wallTime) || wallTime < 0) {\n\t\treturn false\n\t}\n\tif (!Number.isInteger(logical) || logical < 0 || logical > MAX_LOGICAL) {\n\t\treturn false\n\t}\n\treturn wallTime <= now + SERVER_MAX_TIMESTAMP_FUTURE_MS\n}\n","import type { Operation } from '@korajs/core'\n\n/** Default maximum serialized size of a single operation at server ingest (256 KiB). */\nexport const DEFAULT_MAX_OPERATION_BYTES = 256 * 1024\n\n/** Default maximum operations accepted per client session per minute. */\nexport const DEFAULT_MAX_OPS_PER_MINUTE = 600\n\n/**\n * Approximate UTF-8 byte length of an operation payload for rate/size guards.\n */\nexport function measureOperationBytes(op: Operation): number {\n\treturn Buffer.byteLength(JSON.stringify(op), 'utf8')\n}\n\nexport interface OperationSizeValidation {\n\tvalid: boolean\n\tbytes: number\n\tmessage?: string\n}\n\n/**\n * Returns false when an operation exceeds the configured byte limit.\n */\nexport function validateOperationSize(\n\top: Operation,\n\tmaxBytes: number = DEFAULT_MAX_OPERATION_BYTES,\n): OperationSizeValidation {\n\tconst bytes = measureOperationBytes(op)\n\tif (bytes <= maxBytes) {\n\t\treturn { valid: true, bytes }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tbytes,\n\t\tmessage: `Operation \"${op.id}\" exceeds max size (${String(bytes)} > ${String(maxBytes)} bytes)`,\n\t}\n}\n\n/**\n * Simple sliding-window rate limiter for per-session operation ingest.\n */\nexport class SessionRateLimiter {\n\tprivate windowStartMs = Date.now()\n\tprivate count = 0\n\n\tconstructor(private readonly maxOpsPerMinute: number = DEFAULT_MAX_OPS_PER_MINUTE) {}\n\n\tget limit(): number {\n\t\treturn this.maxOpsPerMinute\n\t}\n\n\t/** Record N operations and return false when the limit is exceeded. */\n\tallow(count = 1): boolean {\n\t\tconst now = Date.now()\n\t\tif (now - this.windowStartMs >= 60_000) {\n\t\t\tthis.windowStartMs = now\n\t\t\tthis.count = 0\n\t\t}\n\t\tthis.count += count\n\t\treturn this.count <= this.maxOpsPerMinute\n\t}\n\n\treset(): void {\n\t\tthis.windowStartMs = Date.now()\n\t\tthis.count = 0\n\t}\n}\n","import type { BlobRef, KoraEventEmitter, Operation, OperationTransform } from '@korajs/core'\nimport { SyncError, generateUUIDv7, isBlobRef } from '@korajs/core'\nimport { SimpleEventEmitter } from '@korajs/core/internal'\nimport type { AwarenessUpdateMessage, MessageSerializer, YjsDocUpdateMessage } from '@korajs/sync'\nimport { JsonMessageSerializer } from '@korajs/sync'\nimport {\n\ttype ApplyServerOperationResult,\n\tapplyServerOperation,\n} from '../apply/apply-server-operation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { AwarenessRelay } from '../awareness/awareness-relay'\nimport { ServerMetricsCollector, estimateByteSize } from '../diagnostics/server-metrics-collector'\nimport type { Logger } from '../logging/structured-logger'\nimport { createDefaultLogger } from '../logging/structured-logger'\nimport { BlobChunkRelay } from '../richtext/blob-chunk-relay'\nimport { YjsDocRelay } from '../richtext/yjs-doc-relay'\nimport { ClientSession } from '../session/client-session'\nimport type { ServerStore } from '../store/server-store'\nimport { HttpServerTransport } from '../transport/http-server-transport'\nimport type { ServerTransport } from '../transport/server-transport'\nimport { WsServerTransport } from '../transport/ws-server-transport'\nimport type {\n\tAuthProvider,\n\tHttpSyncRequest,\n\tHttpSyncResponse,\n\tKoraSyncServerConfig,\n\tServerStatus,\n} from '../types'\nimport { type ProductionHttpRouteContext, createRouteContext } from './route-context'\n\nconst DEFAULT_MAX_CONNECTIONS = 0 // unlimited\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\nconst DEFAULT_HOST = '0.0.0.0'\nconst DEFAULT_PATH = '/'\nconst DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS = 2000\nconst DEFAULT_DELIVERY_POLL_INTERVAL_MS = 2000\n\n/**\n * Minimal interface for a ws.WebSocketServer instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsServerLike {\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tclose(callback?: (err?: Error) => void): void\n\taddress(): { port: number } | string | null\n}\n\n/**\n * Constructor type for creating a WebSocket server.\n */\nexport type WsServerConstructor = new (options: {\n\tport?: number\n\thost?: string\n\tpath?: string\n}) => WsServerLike\n\nfunction validateIntervalOption(name: string, value: number): number {\n\tif (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {\n\t\tthrow new SyncError(`${name} must be a non-negative integer number of milliseconds`, {\n\t\t\t[name]: value,\n\t\t})\n\t}\n\treturn value\n}\n\n/**\n * Self-hosted sync server. Accepts WebSocket connections from clients,\n * handles the sync protocol, stores operations, and relays changes\n * between connected clients.\n *\n * Two modes of operation:\n * 1. **Standalone**: Call `start()` with a port — creates its own WebSocket server.\n * 2. **Attach**: Call `handleConnection(transport)` — attach to an existing HTTP server.\n */\nexport class KoraSyncServer {\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly maxConnections: number\n\tprivate readonly batchSize: number\n\tprivate readonly relayRetransmitIntervalMs: number\n\tprivate readonly deliveryPollIntervalMs: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\tprivate readonly port: number | undefined\n\tprivate readonly host: string\n\tprivate readonly path: string\n\tprivate readonly logger: Logger\n\tprivate readonly metrics: ServerMetricsCollector\n\n\tprivate readonly awarenessRelay = new AwarenessRelay()\n\tprivate readonly yjsDocRelay = new YjsDocRelay()\n\tprivate readonly blobChunkRelay: BlobChunkRelay\n\tprivate readonly persistBlobChunk:\n\t\t| ((hash: string, bytes: Uint8Array) => Promise<void> | void)\n\t\t| null\n\tprivate readonly maxOperationBytes: number | undefined\n\tprivate readonly maxOpsPerMinute: number | undefined\n\tprivate readonly validateOperation: OperationValidator | undefined\n\tprivate readonly koraContext: ProductionHttpRouteContext\n\tprivate readonly sessions = new Map<string, ClientSession>()\n\tprivate readonly httpClients = new Map<\n\t\tstring,\n\t\t{ sessionId: string; transport: HttpServerTransport }\n\t>()\n\tprivate readonly httpSessionToClient = new Map<string, string>()\n\t// Informational value reported by getStatus(). Keep in sync with the\n\t// @korajs/server package version on release; it is not used for protocol negotiation.\n\tprivate readonly serverVersion = '1.0.0-beta.0'\n\tprivate wsServer: WsServerLike | null = null\n\tprivate running = false\n\t/**\n\t * Periodic tick that retransmits relay batches connected clients have not\n\t * acknowledged, so a relay dropped by a lossy transport is redelivered instead of\n\t * leaving that client with a permanent version-vector gap (a lost operation).\n\t */\n\tprivate relayRetransmitTimer: ReturnType<typeof setInterval> | null = null\n\tprivate deliveryPollTimer: ReturnType<typeof setInterval> | null = null\n\tprivate lastObservedDeliverySequence = 0\n\tprivate deliveryPollInFlight = false\n\t/**\n\t * Relay operations a client never acknowledged before it disconnected, buffered by\n\t * client node id so they can be redelivered on its next connection. Bounded per\n\t * node and expired by age so a client that never returns cannot grow this forever.\n\t */\n\tprivate readonly orphanedRelaysByNode = new Map<\n\t\tstring,\n\t\t{ ops: Operation[]; bufferedAtMs: number }\n\t>()\n\tprivate static readonly MAX_ORPHANED_RELAY_OPS_PER_NODE = 5000\n\tprivate static readonly ORPHANED_RELAY_TTL_MS = 5 * 60_000\n\n\tconstructor(config: KoraSyncServerConfig) {\n\t\tthis.store = config.store\n\t\tconst storeSchemaVersion = this.store.getSchema()?.version\n\t\tif (\n\t\t\tconfig.schemaVersion !== undefined &&\n\t\t\tstoreSchemaVersion !== undefined &&\n\t\t\tconfig.schemaVersion !== storeSchemaVersion\n\t\t) {\n\t\t\tthrow new SyncError('Sync schema version does not match the configured store schema.', {\n\t\t\t\tsyncSchemaVersion: config.schemaVersion,\n\t\t\t\tstoreSchemaVersion,\n\t\t\t})\n\t\t}\n\t\tthis.auth = config.auth ?? null\n\t\tthis.serializer = config.serializer ?? new JsonMessageSerializer()\n\t\tthis.emitter = config.emitter ?? null\n\t\tthis.maxConnections = config.maxConnections ?? DEFAULT_MAX_CONNECTIONS\n\t\tthis.batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.relayRetransmitIntervalMs = validateIntervalOption(\n\t\t\t'relayRetransmitIntervalMs',\n\t\t\tconfig.relayRetransmitIntervalMs ?? DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS,\n\t\t)\n\t\tthis.deliveryPollIntervalMs = validateIntervalOption(\n\t\t\t'deliveryPollIntervalMs',\n\t\t\tconfig.deliveryPollIntervalMs ?? DEFAULT_DELIVERY_POLL_INTERVAL_MS,\n\t\t)\n\t\tthis.schemaVersion = config.schemaVersion ?? storeSchemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tthis.supportedSchemaVersions = config.supportedSchemaVersions ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = config.operationTransforms ?? []\n\t\tthis.port = config.port\n\t\tthis.host = config.host ?? DEFAULT_HOST\n\t\tthis.path = config.path ?? DEFAULT_PATH\n\t\tthis.logger = config.logger ?? createDefaultLogger()\n\t\tthis.metrics = config.metricsCollector ?? new ServerMetricsCollector()\n\t\tthis.metrics.setSchemaVersion(this.schemaVersion)\n\t\tthis.blobChunkRelay = new BlobChunkRelay(config.resolveBlobChunk)\n\t\tthis.persistBlobChunk = config.persistBlobChunk ?? null\n\t\tthis.maxOperationBytes = config.maxOperationBytes\n\t\tthis.maxOpsPerMinute = config.maxOpsPerMinute\n\t\tthis.validateOperation = config.validateOperation\n\t\t// One trusted data-plane context, shared by custom HTTP routes (via\n\t\t// production-server) and by the operation validator. It holds no per-request\n\t\t// state; the closures only reach back into `this` when actually invoked.\n\t\tthis.koraContext = createRouteContext(this, this.store)\n\n\t\t// If no external emitter was provided, create an internal one for\n\t\t// subscribing to session events for metrics and logging.\n\t\tif (!this.emitter) {\n\t\t\tthis.emitter = new SimpleEventEmitter()\n\t\t}\n\t}\n\n\tprivate ensureBackgroundTimersStarted(): void {\n\t\tif (this.relayRetransmitIntervalMs > 0 && !this.relayRetransmitTimer) {\n\t\t\tthis.relayRetransmitTimer = setInterval(() => {\n\t\t\t\tthis.retransmitPendingRelays(this.relayRetransmitIntervalMs)\n\t\t\t}, this.relayRetransmitIntervalMs)\n\t\t\tthis.relayRetransmitTimer.unref?.()\n\t\t}\n\n\t\tif (this.deliveryPollIntervalMs > 0 && !this.deliveryPollTimer) {\n\t\t\tthis.deliveryPollTimer = setInterval(() => {\n\t\t\t\tvoid this.pollDeliveryLog()\n\t\t\t}, this.deliveryPollIntervalMs)\n\t\t\tthis.deliveryPollTimer.unref?.()\n\t\t}\n\t}\n\n\t/**\n\t * Retransmit relay batches that connected clients have not acknowledged within\n\t * `staleMs`. Called on a periodic tick and directly by tests. Redelivering an\n\t * already-applied operation is harmless (clients dedup by content-addressed id).\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.retransmitPendingRelays(staleMs)\n\t\t}\n\t\tthis.expireOrphanedRelays()\n\t}\n\n\t/**\n\t * Check whether the authoritative delivery log advanced without passing through\n\t * this server instance, then wake delivery-watermark sessions to scan from their\n\t * own acknowledged cursors. Session-level filtering remains the only fan-out path.\n\t */\n\tasync pollDeliveryLog(): Promise<void> {\n\t\tif (this.deliveryPollInFlight) return\n\t\tthis.deliveryPollInFlight = true\n\t\ttry {\n\t\t\tconst maxDeliverySequence = await this.store.getMaxDeliverySequence()\n\t\t\tif (maxDeliverySequence <= this.lastObservedDeliverySequence) {\n\t\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\t\tsession.pushDeliveryStreamIfSupported(this.deliveryPollIntervalMs, {\n\t\t\t\t\t\ttrackStall: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.lastObservedDeliverySequence = maxDeliverySequence\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.pushDeliveryStreamIfSupported(0)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'delivery_poll.failed',\n\t\t\t\tdetails: { error: error instanceof Error ? error.message : String(error) },\n\t\t\t})\n\t\t} finally {\n\t\t\tthis.deliveryPollInFlight = false\n\t\t}\n\t}\n\n\t/**\n\t * Buffer relay operations a disconnected client never acknowledged, keyed by its\n\t * node id, deduped by operation id and bounded by count. Redelivered when the\n\t * client reconnects (see {@link takeOrphanedRelays}).\n\t */\n\tprivate bufferOrphanedRelays(nodeId: string, ops: Operation[]): void {\n\t\tif (ops.length === 0) return\n\t\tconst existing = this.orphanedRelaysByNode.get(nodeId)\n\t\tconst merged = existing ? existing.ops : []\n\t\tconst seen = new Set(merged.map((op) => op.id))\n\t\tfor (const op of ops) {\n\t\t\tif (!seen.has(op.id)) {\n\t\t\t\tmerged.push(op)\n\t\t\t\tseen.add(op.id)\n\t\t\t}\n\t\t}\n\t\t// Keep only the most recent ops if the buffer is oversized.\n\t\tconst bounded =\n\t\t\tmerged.length > KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE\n\t\t\t\t? merged.slice(merged.length - KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE)\n\t\t\t\t: merged\n\t\tthis.orphanedRelaysByNode.set(nodeId, { ops: bounded, bufferedAtMs: Date.now() })\n\t}\n\n\t/** Remove and return a node's buffered orphaned relay operations, if any. */\n\tprivate takeOrphanedRelays(nodeId: string): Operation[] {\n\t\tconst entry = this.orphanedRelaysByNode.get(nodeId)\n\t\tif (!entry) return []\n\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\treturn entry.ops\n\t}\n\n\t/** Drop buffered orphaned relays older than the TTL (client never returned). */\n\tprivate expireOrphanedRelays(): void {\n\t\tif (this.orphanedRelaysByNode.size === 0) return\n\t\tconst cutoff = Date.now() - KoraSyncServer.ORPHANED_RELAY_TTL_MS\n\t\tfor (const [nodeId, entry] of this.orphanedRelaysByNode) {\n\t\t\tif (entry.bufferedAtMs <= cutoff) {\n\t\t\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * The trusted, scoped data-plane context (`apply` / `query` / `findById`).\n\t * Shared with the production server so HTTP routes, the operation validator,\n\t * and `server.kora` are all the same object over the same pipeline.\n\t */\n\tgetKoraContext(): ProductionHttpRouteContext {\n\t\treturn this.koraContext\n\t}\n\n\t/**\n\t * Subscribe to session-level events for metrics collection and logging.\n\t * Called when a new session is created.\n\t */\n\tprivate attachSessionEvents(sessionId: string, sessionEmitter: KoraEventEmitter): void {\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: { reason: event.reason },\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\t}\n\n\t/**\n\t * Get the metrics collector for external access (e.g., HTTP endpoints).\n\t */\n\tgetMetricsCollector(): ServerMetricsCollector {\n\t\treturn this.metrics\n\t}\n\n\t/**\n\t * Get the logger for external access (e.g., event streaming).\n\t */\n\tgetLogger(): Logger {\n\t\treturn this.logger\n\t}\n\n\t/**\n\t * Start the WebSocket server in standalone mode.\n\t *\n\t * @param wsServerImpl - Optional WebSocket server constructor for testing\n\t */\n\tasync start(wsServerImpl?: WsServerConstructor): Promise<void> {\n\t\tif (this.running) {\n\t\t\tthrow new SyncError('Server is already running', { port: this.port })\n\t\t}\n\n\t\tif (!wsServerImpl && this.port === undefined) {\n\t\t\tthrow new SyncError(\n\t\t\t\t'Port is required for standalone mode. Provide port in config or use handleConnection() for attach mode.',\n\t\t\t\t{},\n\t\t\t)\n\t\t}\n\n\t\tif (wsServerImpl) {\n\t\t\tthis.wsServer = new wsServerImpl({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t})\n\t\t} else {\n\t\t\t// Dynamic import of ws — only needed in standalone mode\n\t\t\tconst { WebSocketServer } = await import('ws')\n\t\t\tthis.wsServer = new WebSocketServer({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t})\n\t\t}\n\n\t\tthis.wsServer.on('connection', (ws: unknown) => {\n\t\t\tconst transport = new WsServerTransport(\n\t\t\t\tws as import('../transport/ws-server-transport').WsWebSocket,\n\t\t\t\t{\n\t\t\t\t\tserializer: this.serializer,\n\t\t\t\t},\n\t\t\t)\n\t\t\tthis.handleConnection(transport)\n\t\t})\n\n\t\tthis.running = true\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.started',\n\t\t\tdetails: { port: this.port, host: this.host, path: this.path },\n\t\t})\n\t}\n\n\t/**\n\t * Stop the server. Closes all sessions and the WebSocket server.\n\t */\n\tasync stop(): Promise<void> {\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopping',\n\t\t\tdetails: { connectedClients: this.sessions.size },\n\t\t})\n\n\t\t// Stop the relay retransmit tick and drop buffered orphaned relays.\n\t\tif (this.relayRetransmitTimer) {\n\t\t\tclearInterval(this.relayRetransmitTimer)\n\t\t\tthis.relayRetransmitTimer = null\n\t\t}\n\t\tif (this.deliveryPollTimer) {\n\t\t\tclearInterval(this.deliveryPollTimer)\n\t\t\tthis.deliveryPollTimer = null\n\t\t}\n\t\tthis.orphanedRelaysByNode.clear()\n\n\t\t// Clean up awareness relay\n\t\tthis.awarenessRelay.clear()\n\t\tthis.yjsDocRelay.clear()\n\t\tthis.blobChunkRelay.clear()\n\n\t\t// Close all active sessions (works in both standalone and attach mode)\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.close('server shutting down')\n\t\t}\n\t\tthis.sessions.clear()\n\t\tthis.httpClients.clear()\n\t\tthis.httpSessionToClient.clear()\n\n\t\t// Close WebSocket server (standalone mode only)\n\t\tif (this.wsServer) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tthis.wsServer?.close(() => resolve())\n\t\t\t})\n\t\t\tthis.wsServer = null\n\t\t}\n\n\t\tthis.running = false\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopped',\n\t\t})\n\t}\n\n\t/**\n\t * Handle one HTTP sync request for a long-polling client.\n\t *\n\t * A stable `clientId` identifies the logical connection across requests.\n\t */\n\tasync handleHttpRequest(request: HttpSyncRequest): Promise<HttpSyncResponse> {\n\t\tif (!request.clientId || request.clientId.trim().length === 0) {\n\t\t\treturn { status: 400 }\n\t\t}\n\n\t\tconst client = this.getOrCreateHttpClient(request.clientId)\n\n\t\tif (request.method === 'POST') {\n\t\t\tif (request.body === undefined) {\n\t\t\t\treturn { status: 400 }\n\t\t\t}\n\n\t\t\tconst payload = normalizeHttpBody(request.body, request.contentType)\n\t\t\tclient.transport.receive(payload)\n\t\t\treturn { status: 202 }\n\t\t}\n\n\t\tif (request.method === 'GET') {\n\t\t\tconst polled = client.transport.poll(request.ifNoneMatch)\n\t\t\treturn {\n\t\t\t\tstatus: polled.status,\n\t\t\t\tbody: polled.body,\n\t\t\t\theaders: polled.headers,\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tstatus: 405,\n\t\t\theaders: { allow: 'GET, POST' },\n\t\t}\n\t}\n\n\t/**\n\t * Handle an incoming client connection (attach mode).\n\t * Creates a new ClientSession for the transport.\n\t *\n\t * @param transport - The server transport for the new connection\n\t * @returns The session ID\n\t */\n\thandleConnection(transport: ServerTransport): string {\n\t\t// Check max connections\n\t\tif (this.maxConnections > 0 && this.sessions.size >= this.maxConnections) {\n\t\t\ttransport.send({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tcode: 'MAX_CONNECTIONS',\n\t\t\t\tmessage: `Server has reached maximum connections (${this.maxConnections})`,\n\t\t\t\tretriable: true,\n\t\t\t})\n\t\t\ttransport.close(4029, 'max connections reached')\n\t\t\tthis.metrics.recordError()\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'connection.rejected',\n\t\t\t\tdetails: { reason: 'max_connections', max: this.maxConnections },\n\t\t\t})\n\t\t\tthrow new SyncError('Maximum connections reached', {\n\t\t\t\tcurrent: this.sessions.size,\n\t\t\t\tmax: this.maxConnections,\n\t\t\t})\n\t\t}\n\n\t\tthis.ensureBackgroundTimersStarted()\n\n\t\tconst sessionId = generateUUIDv7()\n\t\tthis.metrics.recordConnection(sessionId)\n\n\t\t// Create a per-session emitter so we can track events with session context.\n\t\t// The session emits events on this emitter, and we listen here for metrics + logging.\n\t\tconst sessionEmitter = new SimpleEventEmitter()\n\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.metrics.updateSessionState(sessionId, 'authenticated')\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', () => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:delivery-stalled', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.delivery_stalled',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\twatermark: event.watermark,\n\t\t\t\t\trepeatCount: event.repeatCount,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tconst session = new ClientSession({\n\t\t\tsessionId,\n\t\t\ttransport,\n\t\t\tstore: this.store,\n\t\t\tauth: this.auth ?? undefined,\n\t\t\tserializer: this.serializer,\n\t\t\temitter: sessionEmitter,\n\t\t\tlogger: this.logger,\n\t\t\tbatchSize: this.batchSize,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tsupportedSchemaVersions: this.supportedSchemaVersions,\n\t\t\toperationTransforms: this.operationTransforms,\n\t\t\tonRelay: (sourceSessionId, operations) => {\n\t\t\t\tthis.handleRelay(sourceSessionId, operations)\n\t\t\t},\n\t\t\tonAwarenessUpdate: (sourceSessionId, message) => {\n\t\t\t\tthis.handleAwarenessRelay(sourceSessionId, message)\n\t\t\t},\n\t\t\tonYjsDocUpdate: (sourceSessionId, message) => {\n\t\t\t\tthis.handleYjsDocRelay(sourceSessionId, message)\n\t\t\t},\n\t\t\tonBlobChunkRequest: (sourceSessionId, message) => {\n\t\t\t\tthis.blobChunkRelay.handleRequest(sourceSessionId, message)\n\t\t\t},\n\t\t\tonBlobChunkResponse: (sourceSessionId, message) => {\n\t\t\t\tthis.blobChunkRelay.handleResponse(sourceSessionId, message)\n\t\t\t},\n\t\t\t...(this.persistBlobChunk ? { persistBlobChunk: this.persistBlobChunk } : {}),\n\t\t\t// Only forward when configured, so an unset server value leaves the\n\t\t\t// session on its own documented default rather than `undefined`.\n\t\t\t...(this.maxOperationBytes !== undefined\n\t\t\t\t? { maxOperationBytes: this.maxOperationBytes }\n\t\t\t\t: {}),\n\t\t\t...(this.maxOpsPerMinute !== undefined ? { maxOpsPerMinute: this.maxOpsPerMinute } : {}),\n\t\t\t...(this.validateOperation\n\t\t\t\t? { validateOperation: this.validateOperation, koraContext: this.koraContext }\n\t\t\t\t: {}),\n\t\t\tonClose: (sid) => {\n\t\t\t\tthis.handleSessionClose(sid)\n\t\t\t},\n\t\t\tonOrphanedRelays: (nodeId, ops) => {\n\t\t\t\tthis.bufferOrphanedRelays(nodeId, ops)\n\t\t\t},\n\t\t\ttakeOrphanedRelays: (nodeId) => this.takeOrphanedRelays(nodeId),\n\t\t})\n\n\t\tthis.sessions.set(sessionId, session)\n\t\tthis.yjsDocRelay.addClient(sessionId, transport)\n\t\tthis.blobChunkRelay.addClient(sessionId, transport)\n\t\tsession.start()\n\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'session.connected',\n\t\t\tsessionId,\n\t\t\tdetails: { totalSessions: this.sessions.size },\n\t\t})\n\n\t\treturn sessionId\n\t}\n\n\t/**\n\t * Get the current server status.\n\t */\n\tasync getStatus(): Promise<ServerStatus> {\n\t\tconst totalOps = await this.store.getOperationCount()\n\t\tconst snapshot = this.metrics.getSnapshot(totalOps)\n\t\treturn {\n\t\t\trunning: this.running,\n\t\t\tconnectedClients: snapshot.connectedClients,\n\t\t\tport: this.port ?? null,\n\t\t\ttotalOperations: snapshot.totalOperations,\n\t\t\tuptime: snapshot.uptime,\n\t\t\tversion: this.serverVersion,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tconnectedNodeIds: snapshot.connectedNodeIds,\n\t\t\tpeakConnections: snapshot.peakConnections,\n\t\t\tconnectionsTotal: snapshot.connectionsTotal,\n\t\t\toperationsReceived: snapshot.operationsReceived,\n\t\t\toperationsSent: snapshot.operationsSent,\n\t\t\terrorCount: snapshot.errorCount,\n\t\t}\n\t}\n\n\t/**\n\t * Apply a server-originated operation (for example one created by a custom\n\t * HTTP route) through the same validated pipeline that incoming client\n\t * operations use — Tier 2 constraints, referential integrity, and cascade\n\t * side effects — then relay every applied operation to connected clients.\n\t *\n\t * Because the operation did not come from a client session, it is relayed to\n\t * ALL sessions (there is no source session to exclude). Each session still\n\t * applies its own per-scope visibility filter in `relayOperations`, so a\n\t * client only receives the operation if it falls within that client's scope.\n\t *\n\t * @param op - A fully-formed, server-originated operation to apply\n\t * @returns The apply result, including any server-generated side-effect ops\n\t */\n\tasync applyLocalOperation(op: Operation): Promise<ApplyServerOperationResult> {\n\t\tconst result = await applyServerOperation(this.store, op)\n\n\t\tif (result.result === 'applied' && result.appliedOperations.length > 0) {\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.relayOperations(result.appliedOperations)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Relay already-applied, server-originated operations to every connected client.\n\t * Used by the conditional route apply, which commits its operations atomically\n\t * through the store (bypassing {@link applyLocalOperation}) and then fans them\n\t * out. Each session still enforces its own per-scope visibility filter.\n\t *\n\t * @param operations - Operations that have already been committed to the store\n\t */\n\trelayServerOperations(operations: Operation[]): void {\n\t\tif (operations.length === 0) {\n\t\t\treturn\n\t\t}\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\t/**\n\t * Collect every blob reference still reachable from live records on the server.\n\t *\n\t * This is the live set for garbage-collecting the server's central blob store:\n\t * pass the result to `collectBlobGarbage(blobStore, liveRefs)` from\n\t * `@korajs/store` to reclaim bytes no record references any more. Only\n\t * collections that declare a `blob` field are scanned.\n\t *\n\t * @returns Every live blob reference across all collections\n\t */\n\tasync getLiveBlobRefs(): Promise<BlobRef[]> {\n\t\tconst schema = this.store.getSchema()\n\t\tif (!schema) {\n\t\t\treturn []\n\t\t}\n\t\tconst refs: BlobRef[] = []\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tconst hasBlobField = Object.values(collection.fields).some((field) => field.kind === 'blob')\n\t\t\tif (!hasBlobField) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst records = await this.store.materializeCollection(name)\n\t\t\tfor (const record of records) {\n\t\t\t\tfor (const value of Object.values(record)) {\n\t\t\t\t\tif (isBlobRef(value)) {\n\t\t\t\t\t\trefs.push(value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn refs\n\t}\n\n\t/**\n\t * Get the number of currently connected clients.\n\t */\n\tgetConnectionCount(): number {\n\t\treturn this.sessions.size\n\t}\n\n\t// --- Private ---\n\n\tprivate handleRelay(sourceSessionId: string, operations: Operation[]): void {\n\t\tconst targetCount = this.sessions.size - 1\n\t\tconst byteSize = estimateOperationByteSize(operations)\n\t\tthis.metrics.recordSent(\n\t\t\tsourceSessionId,\n\t\t\toperations.length * targetCount,\n\t\t\tbyteSize * targetCount,\n\t\t)\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'operations.relayed',\n\t\t\tsessionId: sourceSessionId,\n\t\t\tcount: operations.length,\n\t\t\tbytes: byteSize * targetCount,\n\t\t\tdetails: { targetSessions: targetCount },\n\t\t})\n\n\t\tfor (const [sessionId, session] of this.sessions) {\n\t\t\tif (sessionId === sourceSessionId) continue\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\tprivate handleSessionClose(sessionId: string): void {\n\t\tthis.metrics.recordDisconnection(sessionId)\n\t\tthis.awarenessRelay.removeClient(sessionId)\n\t\tthis.yjsDocRelay.removeClient(sessionId)\n\t\tthis.blobChunkRelay.removeClient(sessionId)\n\n\t\tthis.sessions.delete(sessionId)\n\n\t\tconst clientId = this.httpSessionToClient.get(sessionId)\n\t\tif (clientId) {\n\t\t\tthis.httpSessionToClient.delete(sessionId)\n\t\t\tthis.httpClients.delete(clientId)\n\t\t}\n\t}\n\n\tprivate handleAwarenessRelay(sourceSessionId: string, message: AwarenessUpdateMessage): void {\n\t\t// Register client with awareness relay if not already done\n\t\tconst session = this.sessions.get(sourceSessionId)\n\t\tif (!session) return\n\n\t\tconst transport = session.getTransport()\n\t\tif (!this.awarenessRelay.getClientCount() || !transport) {\n\t\t\t// First awareness update from this client -- register\n\t\t}\n\t\tthis.awarenessRelay.addClient(sourceSessionId, message.clientId, transport)\n\t\tthis.awarenessRelay.handleUpdate(sourceSessionId, message)\n\t}\n\n\tprivate handleYjsDocRelay(sourceSessionId: string, message: YjsDocUpdateMessage): void {\n\t\tif (!this.sessions.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tthis.yjsDocRelay.handleUpdate(sourceSessionId, message)\n\t}\n\n\tprivate getOrCreateHttpClient(clientId: string): {\n\t\tsessionId: string\n\t\ttransport: HttpServerTransport\n\t} {\n\t\tconst existing = this.httpClients.get(clientId)\n\t\tif (existing) {\n\t\t\treturn existing\n\t\t}\n\n\t\tconst transport = new HttpServerTransport(this.serializer)\n\t\tconst sessionId = this.handleConnection(transport)\n\t\tconst client = { sessionId, transport }\n\n\t\tthis.httpClients.set(clientId, client)\n\t\tthis.httpSessionToClient.set(sessionId, clientId)\n\n\t\treturn client\n\t}\n}\n\n/**\n * Estimate the total byte size of serialized operations.\n * Used for bandwidth tracking.\n */\nfunction estimateOperationByteSize(operations: Operation[]): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nfunction normalizeHttpBody(body: string | Uint8Array, contentType?: string): string | Uint8Array {\n\tif (body instanceof Uint8Array) {\n\t\treturn body\n\t}\n\n\tif (contentType?.includes('application/x-protobuf')) {\n\t\treturn new TextEncoder().encode(body)\n\t}\n\n\treturn body\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { AwarenessStateWire, AwarenessUpdateMessage, SyncMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Tracks a single client's awareness registration.\n */\ninterface AwarenessClient {\n\t/** Session ID for this client */\n\tsessionId: string\n\t/** Client-assigned awareness ID (numeric, unique per client) */\n\tclientId: number\n\t/** Transport for sending messages to this client */\n\ttransport: ServerTransport\n\t/** Current awareness state, if any */\n\tstate: AwarenessStateWire | null\n}\n\n/**\n * Server-side awareness relay. Broadcasts ephemeral awareness states\n * (cursor positions, user presence) between connected clients.\n *\n * Awareness data is never persisted. The relay simply forwards awareness\n * updates from one client to all other connected clients, and broadcasts\n * removal notifications when a client disconnects.\n */\nexport class AwarenessRelay {\n\tprivate readonly clients = new Map<string, AwarenessClient>()\n\n\t/**\n\t * Register a client for awareness broadcasting.\n\t *\n\t * @param sessionId - Unique session identifier\n\t * @param clientId - Client-assigned awareness ID\n\t * @param transport - Transport for sending messages to this client\n\t */\n\taddClient(sessionId: string, clientId: number, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tclientId,\n\t\t\ttransport,\n\t\t\tstate: null,\n\t\t})\n\n\t\t// Send this client all existing awareness states so it catches up\n\t\tconst existingStates: Record<string, AwarenessStateWire | null> = {}\n\t\tlet hasStates = false\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === sessionId) continue\n\t\t\tif (client.state) {\n\t\t\t\texistingStates[String(client.clientId)] = client.state\n\t\t\t\thasStates = true\n\t\t\t}\n\t\t}\n\n\t\tif (hasStates) {\n\t\t\tconst catchUpMsg: SyncMessage = {\n\t\t\t\ttype: 'awareness-update',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tclientId: 0, // Server-sourced\n\t\t\t\tstates: existingStates,\n\t\t\t}\n\t\t\ttransport.send(catchUpMsg)\n\t\t}\n\t}\n\n\t/**\n\t * Remove a client and broadcast its removal to all remaining clients.\n\t *\n\t * @param sessionId - Session ID of the disconnecting client\n\t */\n\tremoveClient(sessionId: string): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client) return\n\n\t\tthis.clients.delete(sessionId)\n\n\t\t// Only broadcast removal if the client had an awareness state\n\t\tif (client.state === null) return\n\n\t\tconst removalStates: Record<string, AwarenessStateWire | null> = {\n\t\t\t[String(client.clientId)]: null,\n\t\t}\n\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'awareness-update',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tclientId: client.clientId,\n\t\t\tstates: removalStates,\n\t\t}\n\n\t\tthis.broadcastExcept(sessionId, msg)\n\t}\n\n\t/**\n\t * Handle an incoming awareness update from a client.\n\t * Stores the state and relays to all other connected clients.\n\t *\n\t * @param sessionId - Session ID of the sending client\n\t * @param message - The awareness update message\n\t */\n\thandleUpdate(sessionId: string, message: AwarenessUpdateMessage): void {\n\t\tconst sender = this.clients.get(sessionId)\n\t\tif (!sender) return\n\n\t\t// Update stored state for this client\n\t\tconst senderState = message.states[String(message.clientId)]\n\t\tif (senderState !== undefined) {\n\t\t\tsender.state = senderState\n\t\t}\n\n\t\t// Relay to all other clients\n\t\tthis.broadcastExcept(sessionId, message)\n\t}\n\n\t/**\n\t * Get the number of registered awareness clients.\n\t */\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\t/**\n\t * Remove all clients and clear all state.\n\t */\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\t// --- Private ---\n\n\tprivate broadcastExcept(excludeSessionId: string, message: SyncMessage): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) continue\n\t\t\tif (!client.transport.isConnected()) continue\n\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import type { AuthContext, SessionState } from '../types'\n\n/**\n * Snapshot of server-side sync metrics at a point in time.\n */\nexport interface ServerMetricsSnapshot {\n\tconnectedClients: number\n\tconnectedNodeIds: string[]\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\toperationsSent: number\n\tbytesReceived: number\n\tbytesSent: number\n\tclients: ClientMetrics[]\n\tuptime: number\n\ttotalOperations: number\n\terrorCount: number\n\tschemaVersion: number\n}\n\n/**\n * Per-client metrics tracked by the server.\n */\nexport interface ClientMetrics {\n\tsessionId: string\n\tnodeId: string | null\n\tstate: SessionState\n\tconnectedAt: number\n\toperationsReceived: number\n\toperationsSent: number\n\tauthContext: AuthContext | null\n}\n\n/**\n * Collects and aggregates server-side sync metrics.\n *\n * Tracks connected clients, throughput, error counts, and per-session\n * metadata. Designed to be hooked into KoraSyncServer lifecycle events.\n */\n/**\n * Estimate the byte size of a batch of operations.\n * Used for bandwidth tracking in sync events.\n * Each operation is approximated by JSON-serializing and measuring length.\n */\nexport function estimateByteSize(operations: Array<unknown>): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nexport class ServerMetricsCollector {\n\tprivate startedAt = Date.now()\n\n\tprivate peakConnections = 0\n\tprivate connectionsTotal = 0\n\tprivate operationsReceived = 0\n\tprivate operationsSent = 0\n\tprivate bytesReceived = 0\n\tprivate bytesSent = 0\n\tprivate errorCount = 0\n\tprivate schemaVersion = 1\n\n\tprivate readonly clientMetrics = new Map<string, ClientMetrics>()\n\n\t/** Record a new client connection. */\n\trecordConnection(sessionId: string): void {\n\t\tthis.connectionsTotal++\n\t\tthis.clientMetrics.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tnodeId: null,\n\t\t\tstate: 'connected',\n\t\t\tconnectedAt: Date.now(),\n\t\t\toperationsReceived: 0,\n\t\t\toperationsSent: 0,\n\t\t\tauthContext: null,\n\t\t})\n\t\tthis.peakConnections = Math.max(this.peakConnections, this.clientMetrics.size)\n\t}\n\n\t/** Record a client disconnection. */\n\trecordDisconnection(sessionId: string): void {\n\t\tthis.clientMetrics.delete(sessionId)\n\t}\n\n\t/** Update the node ID after a handshake completes. */\n\trecordHandshake(sessionId: string, nodeId: string): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.nodeId = nodeId\n\t\t}\n\t}\n\n\t/** Update session state. */\n\tupdateSessionState(sessionId: string, state: SessionState): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.state = state\n\t\t}\n\t}\n\n\t/** Record authentication context for a session. */\n\trecordAuth(sessionId: string, authContext: AuthContext | null): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.authContext = authContext\n\t\t}\n\t}\n\n\t/** Record operations received from a client. */\n\trecordReceived(sessionId: string, count: number, byteSize: number): void {\n\t\tthis.operationsReceived += count\n\t\tthis.bytesReceived += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsReceived += count\n\t\t}\n\t}\n\n\t/** Record operations sent to a client. */\n\trecordSent(sessionId: string, count: number, byteSize: number): void {\n\t\tthis.operationsSent += count\n\t\tthis.bytesSent += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsSent += count\n\t\t}\n\t}\n\n\t/** Record an error. */\n\trecordError(): void {\n\t\tthis.errorCount++\n\t}\n\n\t/** Set the schema version. */\n\tsetSchemaVersion(version: number): void {\n\t\tthis.schemaVersion = version\n\t}\n\n\t/** Return a full snapshot of current metrics. */\n\tgetSnapshot(totalOperations: number): ServerMetricsSnapshot {\n\t\treturn {\n\t\t\tconnectedClients: this.clientMetrics.size,\n\t\t\tconnectedNodeIds: Array.from(this.clientMetrics.values())\n\t\t\t\t.filter((c) => c.nodeId !== null)\n\t\t\t\t.map((c) => c.nodeId as string),\n\t\t\tpeakConnections: this.peakConnections,\n\t\t\tconnectionsTotal: this.connectionsTotal,\n\t\t\toperationsReceived: this.operationsReceived,\n\t\t\toperationsSent: this.operationsSent,\n\t\t\tbytesReceived: this.bytesReceived,\n\t\t\tbytesSent: this.bytesSent,\n\t\t\tclients: Array.from(this.clientMetrics.values()),\n\t\t\tuptime: Date.now() - this.startedAt,\n\t\t\ttotalOperations,\n\t\t\terrorCount: this.errorCount,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t}\n\t}\n\n\t/** Reset all metrics. */\n\treset(): void {\n\t\tthis.startedAt = Date.now()\n\t\tthis.peakConnections = 0\n\t\tthis.connectionsTotal = 0\n\t\tthis.operationsReceived = 0\n\t\tthis.operationsSent = 0\n\t\tthis.bytesReceived = 0\n\t\tthis.bytesSent = 0\n\t\tthis.errorCount = 0\n\t\tthis.clientMetrics.clear()\n\t}\n}\n","import {\n\ttype BlobChunkRequestMessage,\n\ttype BlobChunkResponseMessage,\n\tencodeBlobChunkBytes,\n} from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Resolves a blob chunk by content hash from server-side storage. Optional: when\n * provided, the server can answer chunk requests directly from its own store\n * (central-store deployment). When absent, the server acts as a pure relay,\n * forwarding chunk requests to peer sessions and their responses back.\n */\nexport type ResolveBlobChunk = (hash: string) => Promise<Uint8Array | null>\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/**\n * Routes out-of-band blob chunk transfer between connected clients (and,\n * optionally, a server-side blob store).\n *\n * The server never stores or inspects blob bytes on the relay path: a\n * `blob-chunk-request` is forwarded to peer sessions, and the first peer to\n * answer with the bytes has its `blob-chunk-response` routed back to the\n * original requester by `requestId`. Blob bytes never enter the operation log;\n * only the `BlobRef` reference inside a record does.\n *\n * Not persisted — this is an ephemeral side channel, like the Yjs doc relay.\n */\nexport class BlobChunkRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\t/** requestId -> the session that originated the request (to route the answer back). */\n\tprivate readonly pending = new Map<string, string>()\n\tprivate readonly resolveBlobChunk: ResolveBlobChunk | null\n\n\tconstructor(resolveBlobChunk?: ResolveBlobChunk) {\n\t\tthis.resolveBlobChunk = resolveBlobChunk ?? null\n\t}\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t\t// Drop any requests this session was waiting on; their answers can no\n\t\t// longer be delivered.\n\t\tfor (const [requestId, originSessionId] of this.pending) {\n\t\t\tif (originSessionId === sessionId) {\n\t\t\t\tthis.pending.delete(requestId)\n\t\t\t}\n\t\t}\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tgetPendingCount(): number {\n\t\treturn this.pending.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t\tthis.pending.clear()\n\t}\n\n\t/**\n\t * Handle an inbound chunk request from a session. Tries the server's own\n\t * store first (if configured), otherwise forwards the request to peer\n\t * sessions and remembers who to route the answer back to.\n\t */\n\thandleRequest(sourceSessionId: string, message: BlobChunkRequestMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.resolveBlobChunk) {\n\t\t\tvoid this.resolveBlobChunk(message.hash).then(\n\t\t\t\t(bytes) => {\n\t\t\t\t\tif (bytes !== null) {\n\t\t\t\t\t\tthis.sendResponseTo(sourceSessionId, message.requestId, encodeBlobChunkBytes(bytes))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\t// A store read error is treated as \"not held here\": fall back to peers\n\t\t\t\t\t// rather than crashing the connection.\n\t\t\t\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t\t\t\t},\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t}\n\n\t/**\n\t * Handle an inbound chunk response from a peer. Routes it back to the session\n\t * that originally requested it. A \"not held\" answer (bytes === null) is\n\t * ignored so a peer without the chunk does not preempt one that has it; the\n\t * requester's own per-request timeout bounds the wait.\n\t */\n\thandleResponse(sourceSessionId: string, message: BlobChunkResponseMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tif (message.bytes === null) {\n\t\t\treturn\n\t\t}\n\t\tconst originSessionId = this.pending.get(message.requestId)\n\t\tif (!originSessionId) {\n\t\t\treturn\n\t\t}\n\t\tthis.pending.delete(message.requestId)\n\t\tthis.sendResponseTo(originSessionId, message.requestId, message.bytes)\n\t}\n\n\tprivate forwardRequestToPeers(sourceSessionId: string, message: BlobChunkRequestMessage): void {\n\t\tthis.pending.set(message.requestId, sourceSessionId)\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === sourceSessionId) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!client.transport.isConnected()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n\n\tprivate sendResponseTo(sessionId: string, requestId: string, bytes: string): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client || !client.transport.isConnected()) {\n\t\t\treturn\n\t\t}\n\t\tconst response: BlobChunkResponseMessage = {\n\t\t\ttype: 'blob-chunk-response',\n\t\t\tmessageId: generateResponseId(requestId),\n\t\t\trequestId,\n\t\t\tbytes,\n\t\t}\n\t\tclient.transport.send(response)\n\t}\n}\n\n/**\n * Derive a deterministic wire messageId for a routed response. The correlation\n * that matters is `requestId`; `messageId` only needs to be a non-empty string,\n * so deriving it avoids a clock/random dependency in the relay.\n */\nfunction generateResponseId(requestId: string): string {\n\treturn `blob-resp-${requestId}`\n}\n","import type { SyncMessage, YjsDocUpdateMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/**\n * Relays ephemeral Yjs doc channel updates between connected clients.\n * Not persisted — durable richtext state still flows through the operation log.\n */\nexport class YjsDocRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t}\n\n\thandleUpdate(sourceSessionId: string, message: YjsDocUpdateMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tthis.broadcastExcept(sourceSessionId, message)\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\tprivate broadcastExcept(excludeSessionId: string, message: SyncMessage): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!client.transport.isConnected()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import {\n\ttype AtomicOp,\n\tHybridLogicalClock,\n\ttype Operation,\n\tcreateOperation,\n\tgenerateUUIDv7,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n} from '@korajs/core'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { type RoutePredicate, evaluateRoutePredicate } from '../apply/route-predicate'\nimport { nextServerSequenceNumber } from '../apply/server-side-effect-operation'\nimport type { ScopeMap } from '../scopes/server-scope-filter'\nimport { operationMatchesScopes } from '../scopes/server-scope-filter'\nimport type {\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tMaterializedRecord,\n\tServerStore,\n} from '../store/server-store'\nimport type { KoraSyncServer } from './kora-sync-server'\n\n/**\n * A mutation a custom HTTP route asks the server to apply on the data plane.\n *\n * `recordId` is optional for inserts (a UUID v7 is generated when omitted) and\n * required for updates and deletes. For updates, `data` holds only the changed\n * fields; the server reads the current record to capture the previous values so\n * the change three-way merges correctly with concurrent client edits.\n */\nexport interface RouteMutation {\n\tcollection: string\n\ttype: 'insert' | 'update' | 'delete'\n\trecordId?: string\n\tdata?: Record<string, unknown> | null\n}\n\n/**\n * Scope the route derived from the request's authenticated actor. When present,\n * it is enforced exactly like a sync session's scope: `apply()` rejects a\n * mutation whose resulting record falls outside the scope, and `query()` /\n * `findById()` only return records inside it. Omit it for genuinely public\n * routes (for example a signup endpoint) where no per-actor isolation applies.\n */\nexport interface RouteScopeOptions {\n\tscope?: ScopeMap\n}\n\n/** Result of {@link ProductionHttpRouteContext.apply}. */\nexport type RouteApplyResult =\n\t| { ok: true; operation: Operation; record: MaterializedRecord | null }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * A conditional, multi-collection admission gate applied atomically per instance.\n *\n * The gate reads the current state of the target record (`collection` + `id`),\n * checks the `if` predicate against it, and only then applies the `update` to the\n * target plus every mutation in `also` as one set. If the predicate fails it\n * applies nothing and returns the structured `reject`. `idempotencyKey` names a\n * record whose prior existence proves the set already committed, so a retry\n * returns the earlier outcome instead of applying the set (and its non-idempotent\n * counter increments) again.\n *\n * Atomicity note: within one server instance the check and the writes do not\n * interleave with other route mutations. Cross-instance, race-free admission and\n * all-or-nothing across a mid-set crash require the store-level conditional\n * transaction (a Postgres `WHERE ... < cap` commit), which is the next increment.\n */\nexport interface RouteConditionalApply {\n\t/** Collection of the record the predicate reads and the `update` targets. */\n\tcollection: string\n\t/** Id of the target record. */\n\tid: string\n\t/** Admission predicate evaluated against the target's current state. */\n\tif?: RoutePredicate\n\t/** Partial update applied to the target record when the predicate holds. */\n\tupdate?: Record<string, unknown> | null\n\t/** Additional mutations committed atomically with the target update. */\n\talso?: RouteMutation[]\n\t/** Structured rejection returned when the predicate does not hold. */\n\treject?: { code: string; message: string }\n\t/**\n\t * Names a record whose existence means this set already committed. When it is\n\t * present the set is skipped and the prior outcome returned. Use a stable,\n\t * client-generated id (for example the accepted record's own id).\n\t */\n\tidempotencyKey?: { collection: string; id: string }\n}\n\n/** Result of {@link ProductionHttpRouteContext.applyConditional}. */\nexport type RouteConditionalResult =\n\t| {\n\t\t\tok: true\n\t\t\t/** True when the set was already committed and this call was a no-op. */\n\t\t\tidempotent: boolean\n\t\t\toperations: Operation[]\n\t\t\trecords: (MaterializedRecord | null)[]\n\t }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * Scoped, validated data-plane access handed to custom HTTP route handlers.\n *\n * Every mutation goes through the same pipeline as sync (Tier 2 constraints,\n * referential integrity, materialization, and fan-out to connected clients), so\n * REST endpoints cannot accidentally bypass validation, constraints, or tenant\n * isolation the way hand-rolled store writes can.\n */\nexport interface ProductionHttpRouteContext {\n\t/**\n\t * Apply a mutation through the validated server pipeline and relay the\n\t * resulting operation(s) to connected clients.\n\t */\n\tapply(mutation: RouteMutation, options?: RouteScopeOptions): Promise<RouteApplyResult>\n\t/**\n\t * Conditionally apply a multi-collection mutation set as one admission gate:\n\t * read the target, check the predicate, and commit the update plus every `also`\n\t * mutation only if it holds, with at-most-once semantics via `idempotencyKey`.\n\t */\n\tapplyConditional(\n\t\tspec: RouteConditionalApply,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<RouteConditionalResult>\n\t/** Read materialized records from a collection, optionally scoped. */\n\tquery(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions & RouteScopeOptions,\n\t): Promise<MaterializedRecord[]>\n\t/** Read a single materialized record by id, optionally scoped. */\n\tfindById(\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<MaterializedRecord | null>\n}\n\n/**\n * Returns true when a materialized record satisfies the scope declared for its\n * collection. A collection absent from the scope map is treated as out of scope\n * (hidden), mirroring `operationMatchesScopes` on the write path.\n */\nfunction recordMatchesScope(\n\tcollection: string,\n\trecord: MaterializedRecord,\n\tscope: ScopeMap,\n): boolean {\n\tconst collectionScope = scope[collection]\n\tif (!collectionScope) {\n\t\treturn false\n\t}\n\tfor (const [field, expected] of Object.entries(collectionScope)) {\n\t\tif (record[field] !== expected) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/** Picks only the given keys from a record (used to capture previousData). */\nfunction pickFields(record: Record<string, unknown>, keys: string[]): Record<string, unknown> {\n\tconst picked: Record<string, unknown> = {}\n\tfor (const key of keys) {\n\t\tif (key in record) {\n\t\t\tpicked[key] = record[key]\n\t\t}\n\t}\n\treturn picked\n}\n\n/**\n * Build a server-originated operation for a route mutation, reading current\n * materialized state so updates and deletes carry accurate previous values.\n *\n * `currentOverride`, when provided, supplies that current state instead of reading\n * it from the store. The conditional apply passes the record it read under the\n * cross-instance lock, so an atomic-op update (for example `op.increment`) resolves\n * against the authoritative locked value rather than a stale read.\n *\n * `clockOverride`, when provided, stamps the operation instead of a fresh clock. The\n * cross-instance conditional apply passes a clock the store advanced past the target\n * record's latest write, so the operation sorts strictly after it and last-write-wins\n * materialization matches the serialized commit order.\n */\nasync function buildRouteOperation(\n\tstore: ServerStore,\n\tmutation: RouteMutation,\n\tcurrentOverride?: { record: MaterializedRecord | null },\n\tclockOverride?: HybridLogicalClock,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\tconst clock = clockOverride ?? new HybridLogicalClock(nodeId)\n\tconst schemaVersion = store.getSchema()?.version ?? 1\n\tconst sequenceNumber = nextServerSequenceNumber(store)\n\n\tif (mutation.type === 'insert') {\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId ?? generateUUIDv7(),\n\t\t\t\tdata: mutation.data ?? {},\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\tif (!mutation.recordId) {\n\t\tthrow new RouteMutationError(\n\t\t\t'MISSING_RECORD_ID',\n\t\t\t`A ${mutation.type} mutation on \"${mutation.collection}\" requires a recordId.`,\n\t\t)\n\t}\n\n\tconst current = currentOverride\n\t\t? currentOverride.record\n\t\t: await store.findRecord(mutation.collection, mutation.recordId)\n\n\tif (mutation.type === 'update') {\n\t\tconst rawData = mutation.data ?? {}\n\t\t// Resolve atomic-op sentinels (op.increment, op.max, ...) exactly as the\n\t\t// client's update path does: `data` carries the concrete resolved value for\n\t\t// materialization, and `atomicOps` carries the intent so concurrent atomic\n\t\t// writes compose in the merge engine instead of last-write-wins.\n\t\tconst data: Record<string, unknown> = {}\n\t\tconst atomicOps: Record<string, AtomicOp> = {}\n\t\tfor (const key of Object.keys(rawData)) {\n\t\t\tconst value = rawData[key]\n\t\t\tif (isAtomicOp(value)) {\n\t\t\t\tdata[key] = resolveAtomicOp(current ? current[key] : undefined, value)\n\t\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t\t} else {\n\t\t\t\tdata[key] = value\n\t\t\t}\n\t\t}\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId,\n\t\t\t\tdata,\n\t\t\t\tpreviousData: current ? pickFields(current, Object.keys(rawData)) : {},\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t\t...(Object.keys(atomicOps).length > 0 ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\t// delete\n\treturn createOperation(\n\t\t{\n\t\t\tnodeId,\n\t\t\ttype: 'delete',\n\t\t\tcollection: mutation.collection,\n\t\t\trecordId: mutation.recordId,\n\t\t\tdata: null,\n\t\t\tpreviousData: current ? { ...current } : null,\n\t\t\tsequenceNumber,\n\t\t\tcausalDeps: [],\n\t\t\tschemaVersion,\n\t\t},\n\t\tclock,\n\t)\n}\n\n/** Internal error carrying a stable code for route-context failures. */\nclass RouteMutationError extends Error {\n\tconstructor(\n\t\treadonly code: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'RouteMutationError'\n\t}\n}\n\n/**\n * Create the scoped, validated data-plane context handed to custom HTTP route\n * handlers as `request.kora`.\n *\n * Mutations are serialized so concurrent requests cannot race on server\n * sequence-number allocation: each `apply()` builds and applies its operation\n * before the next begins.\n */\nexport function createRouteContext(\n\tserver: KoraSyncServer,\n\tstore: ServerStore,\n): ProductionHttpRouteContext {\n\t// Promise chain that serializes apply() so sequence allocation + apply is\n\t// atomic per mutation, even under concurrent in-flight requests.\n\tlet mutationTail: Promise<unknown> = Promise.resolve()\n\n\tfunction serialize<T>(work: () => Promise<T>): Promise<T> {\n\t\tconst run = mutationTail.then(work, work)\n\t\t// Keep the tail from rejecting so one failed mutation does not poison the\n\t\t// chain for subsequent ones.\n\t\tmutationTail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t)\n\t\treturn run\n\t}\n\n\t// Build a route operation and check scope, WITHOUT applying it. Splitting\n\t// preparation from commit lets applyConditional validate an entire mutation set\n\t// before committing any of it, so a scope violation or malformed mutation in\n\t// `also` cannot leave the target update (for example a counter increment)\n\t// committed while the rest is rejected.\n\ttype RouteRejection = { ok: false; code: string; message: string; retriable: boolean }\n\ttype PreparedMutation = { ok: true; op: Operation } | { ok: false; rejection: RouteRejection }\n\tasync function prepareMutation(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<PreparedMutation> {\n\t\tlet op: Operation\n\t\ttry {\n\t\t\top = await buildRouteOperation(store, mutation)\n\t\t} catch (error) {\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tcode: error.code,\n\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\tif (scope && !operationMatchesScopes(op, scope)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\trejection: {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: 'SCOPE_VIOLATION',\n\t\t\t\t\tmessage: `Mutation on \"${mutation.collection}\" is outside the provided scope.`,\n\t\t\t\t\tretriable: isRetriableRejection('SCOPE_VIOLATION'),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn { ok: true, op }\n\t}\n\n\t// Apply a prepared operation and read back the resulting record.\n\tasync function commitOperation(op: Operation, collection: string): Promise<RouteApplyResult> {\n\t\tconst result = await server.applyLocalOperation(op)\n\t\tif (result.result !== 'applied') {\n\t\t\tconst code = result.rejection?.code ?? 'NOT_APPLIED'\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode,\n\t\t\t\tmessage:\n\t\t\t\t\tresult.rejection?.message ??\n\t\t\t\t\t`Operation on \"${collection}\" was not applied (${result.result}).`,\n\t\t\t\t// Prefer the pipeline's own classification when present; fall back\n\t\t\t\t// to classifying the code so this stays correct if new codes appear.\n\t\t\t\tretriable: result.rejection?.retriable ?? isRetriableRejection(code),\n\t\t\t}\n\t\t}\n\n\t\tconst record = await store.findRecord(collection, op.recordId)\n\t\treturn { ok: true, operation: op, record }\n\t}\n\n\t// The un-serialized core of a single mutation. Both apply() and\n\t// applyConditional() call this inside a serialized block, so it must NOT\n\t// serialize itself (that would deadlock the promise-chain tail).\n\tasync function rawApply(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<RouteApplyResult> {\n\t\tconst prepared = await prepareMutation(mutation, scope)\n\t\tif (!prepared.ok) {\n\t\t\treturn prepared.rejection\n\t\t}\n\t\treturn commitOperation(prepared.op, mutation.collection)\n\t}\n\n\t// Cross-instance conditional apply, delegating admission and atomicity to the\n\t// store (the Postgres advisory-lock transaction). The store owns the\n\t// read-decide-write cycle so a cap check is race-free across instances; this\n\t// bridge translates the route spec into the store's callback shape, validates\n\t// scope on each built operation while still inside the locked transaction (so a\n\t// violation rolls everything back), then relays the committed set to clients.\n\tasync function runConditionalViaStore(\n\t\tstoreApplyConditional: (input: ConditionalApplyInput) => Promise<ConditionalApplyResult>,\n\t\tspec: RouteConditionalApply,\n\t\toptions: RouteScopeOptions | undefined,\n\t): Promise<RouteConditionalResult> {\n\t\tconst scope = options?.scope\n\n\t\t// Assemble the set: the target update (when given) first, then every `also`.\n\t\tconst mutations: RouteMutation[] = []\n\t\tconst hasTargetUpdate = spec.update !== undefined && spec.update !== null\n\t\tif (hasTargetUpdate) {\n\t\t\tmutations.push({\n\t\t\t\tcollection: spec.collection,\n\t\t\t\ttype: 'update',\n\t\t\t\trecordId: spec.id,\n\t\t\t\tdata: spec.update,\n\t\t\t})\n\t\t}\n\t\tif (spec.also) {\n\t\t\tmutations.push(...spec.also)\n\t\t}\n\n\t\tlet result: ConditionalApplyResult\n\t\ttry {\n\t\t\tresult = await storeApplyConditional({\n\t\t\t\ttarget: { collection: spec.collection, id: spec.id },\n\t\t\t\t...(spec.idempotencyKey ? { idempotencyKey: spec.idempotencyKey } : {}),\n\t\t\t\tadmit: (current) =>\n\t\t\t\t\tspec.if && Object.keys(spec.if).length > 0\n\t\t\t\t\t\t? evaluateRoutePredicate(current, spec.if)\n\t\t\t\t\t\t: true,\n\t\t\t\tbuildOperations: async (current, context) => {\n\t\t\t\t\tconst ops: Operation[] = []\n\t\t\t\t\tfor (let i = 0; i < mutations.length; i++) {\n\t\t\t\t\t\tconst mutation = mutations[i] as RouteMutation\n\t\t\t\t\t\t// The target update (index 0 when present) resolves its atomic ops\n\t\t\t\t\t\t// against the locked `current`; `also` mutations address distinct\n\t\t\t\t\t\t// records and read their own current state from the store. Every op\n\t\t\t\t\t\t// is stamped with the store-provided clock so the set sorts strictly\n\t\t\t\t\t\t// after the target's latest committed write.\n\t\t\t\t\t\tconst useLockedCurrent = i === 0 && hasTargetUpdate\n\t\t\t\t\t\tconst op = await buildRouteOperation(\n\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\tmutation,\n\t\t\t\t\t\t\tuseLockedCurrent ? { record: current } : undefined,\n\t\t\t\t\t\t\tcontext.clock,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t// Validate scope inside the locked transaction. Throwing here rolls\n\t\t\t\t\t\t// the transaction back, so a violation in any mutation applies nothing.\n\t\t\t\t\t\tif (scope && !operationMatchesScopes(op, scope)) {\n\t\t\t\t\t\t\tthrow new RouteMutationError(\n\t\t\t\t\t\t\t\t'SCOPE_VIOLATION',\n\t\t\t\t\t\t\t\t`Mutation on \"${mutation.collection}\" is outside the provided scope.`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tops.push(op)\n\t\t\t\t\t}\n\t\t\t\t\treturn ops\n\t\t\t\t},\n\t\t\t})\n\t\t} catch (error) {\n\t\t\t// A malformed mutation or scope violation surfaced from inside the locked\n\t\t\t// transaction (which rolled back) becomes a structured rejection, not a 500.\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: error.code,\n\t\t\t\t\tmessage: error.message,\n\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\t// Predicate failed under the lock: nothing was applied.\n\t\tif (!result.admitted) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode: spec.reject?.code ?? 'CONDITION_NOT_MET',\n\t\t\t\tmessage:\n\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\tretriable: false,\n\t\t\t}\n\t\t}\n\n\t\t// Idempotent hit: the set committed on an earlier attempt. Return the anchor's\n\t\t// committed state without re-applying (so counter increments run at most once).\n\t\tif (result.idempotent) {\n\t\t\tconst records: (MaterializedRecord | null)[] = spec.idempotencyKey\n\t\t\t\t? [await store.findRecord(spec.idempotencyKey.collection, spec.idempotencyKey.id)]\n\t\t\t\t: []\n\t\t\treturn { ok: true, idempotent: true, operations: [], records }\n\t\t}\n\n\t\t// Admitted and committed. Fan the operations out to connected clients (each\n\t\t// session re-applies its own scope filter), then read back each record.\n\t\tserver.relayServerOperations(result.applied)\n\t\tconst records: (MaterializedRecord | null)[] = []\n\t\tfor (const op of result.applied) {\n\t\t\trecords.push(await store.findRecord(op.collection, op.recordId))\n\t\t}\n\t\treturn { ok: true, idempotent: false, operations: result.applied, records }\n\t}\n\n\treturn {\n\t\tapply(mutation, options): Promise<RouteApplyResult> {\n\t\t\treturn serialize(() => rawApply(mutation, options?.scope))\n\t\t},\n\n\t\tapplyConditional(spec, options): Promise<RouteConditionalResult> {\n\t\t\t// Prefer the store's cross-instance conditional apply when available (the\n\t\t\t// Postgres store): it serializes the admission on the target across every\n\t\t\t// server instance via an advisory lock, so a cap check is race-free even\n\t\t\t// under concurrent admissions on different instances. Stores without it\n\t\t\t// (single-process SQLite / in-memory) use the per-instance serialized path\n\t\t\t// below, which is correct because there is only one instance.\n\t\t\tconst storeApplyConditional = store.applyConditional\n\t\t\tif (storeApplyConditional) {\n\t\t\t\treturn runConditionalViaStore(storeApplyConditional.bind(store), spec, options)\n\t\t\t}\n\t\t\treturn serialize(async () => {\n\t\t\t\t// Idempotency: if the anchor record already exists, this set was\n\t\t\t\t// committed by an earlier attempt. Return the prior outcome without\n\t\t\t\t// re-applying (so counter increments run at most once).\n\t\t\t\tif (spec.idempotencyKey) {\n\t\t\t\t\tconst existing = await store.findRecord(\n\t\t\t\t\t\tspec.idempotencyKey.collection,\n\t\t\t\t\t\tspec.idempotencyKey.id,\n\t\t\t\t\t)\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\treturn { ok: true, idempotent: true, operations: [], records: [existing] }\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Admission predicate against the target's current materialized state.\n\t\t\t\tif (spec.if && Object.keys(spec.if).length > 0) {\n\t\t\t\t\tconst target = await store.findRecord(spec.collection, spec.id)\n\t\t\t\t\tif (!evaluateRoutePredicate(target, spec.if)) {\n\t\t\t\t\t\tconst code = spec.reject?.code ?? 'CONDITION_NOT_MET'\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\t\t\t\tretriable: false,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build the atomic set: the target update (when given) then every\n\t\t\t\t// `also` mutation. Mutations in one set should address distinct records;\n\t\t\t\t// a mutation's previous-value capture reads the pre-set state.\n\t\t\t\tconst mutations: RouteMutation[] = []\n\t\t\t\tif (spec.update !== undefined && spec.update !== null) {\n\t\t\t\t\tmutations.push({\n\t\t\t\t\t\tcollection: spec.collection,\n\t\t\t\t\t\ttype: 'update',\n\t\t\t\t\t\trecordId: spec.id,\n\t\t\t\t\t\tdata: spec.update,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (spec.also) {\n\t\t\t\t\tmutations.push(...spec.also)\n\t\t\t\t}\n\n\t\t\t\t// Pre-build and scope-validate the WHOLE set before committing any of\n\t\t\t\t// it, so a validation failure applies nothing.\n\t\t\t\tconst prepared: { op: Operation; collection: string }[] = []\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tconst p = await prepareMutation(mutation, options?.scope)\n\t\t\t\t\tif (!p.ok) {\n\t\t\t\t\t\treturn p.rejection\n\t\t\t\t\t}\n\t\t\t\t\tprepared.push({ op: p.op, collection: mutation.collection })\n\t\t\t\t}\n\n\t\t\t\tconst operations: Operation[] = []\n\t\t\t\tconst records: (MaterializedRecord | null)[] = []\n\t\t\t\tfor (const { op, collection } of prepared) {\n\t\t\t\t\tconst result = await commitOperation(op, collection)\n\t\t\t\t\tif (!result.ok) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode: result.code,\n\t\t\t\t\t\t\tmessage: result.message,\n\t\t\t\t\t\t\tretriable: result.retriable,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\toperations.push(result.operation)\n\t\t\t\t\trecords.push(result.record)\n\t\t\t\t}\n\n\t\t\t\treturn { ok: true, idempotent: false, operations, records }\n\t\t\t})\n\t\t},\n\n\t\tasync query(collection, options): Promise<MaterializedRecord[]> {\n\t\t\tconst { scope, ...queryOptions } = options ?? {}\n\t\t\tconst records = await store.queryCollection(collection, queryOptions)\n\t\t\tif (!scope) {\n\t\t\t\treturn records\n\t\t\t}\n\t\t\treturn records.filter((record) => recordMatchesScope(collection, record, scope))\n\t\t},\n\n\t\tasync findById(collection, id, options): Promise<MaterializedRecord | null> {\n\t\t\tconst record = await store.findRecord(collection, id)\n\t\t\tif (!record) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (options?.scope && !recordMatchesScope(collection, record, options.scope)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn record\n\t\t},\n\t}\n}\n","/**\n * Predicate evaluation for conditional route mutations.\n *\n * A predicate is a small, total comparison language evaluated against the current\n * materialized state of a single record at admission time. It is deliberately not\n * a general query language: it exists so a server route can express an atomic\n * admission guard (for example \"accept this response only while the form is still\n * below its cap\") without pulling a query DSL into the write path.\n */\n\n/**\n * Comparison operators applied to one field. All operators present on a field\n * must hold for the field to match. Numeric operators (`$lt`, `$lte`, `$gt`,\n * `$gte`) require the record value to be a number; a non-numeric value fails.\n */\nexport interface RoutePredicateOperators {\n\t$eq?: unknown\n\t$ne?: unknown\n\t$lt?: number\n\t$lte?: number\n\t$gt?: number\n\t$gte?: number\n\t$in?: readonly unknown[]\n}\n\n/** A predicate: every listed field must satisfy all of its operators. */\nexport type RoutePredicate = Record<string, RoutePredicateOperators>\n\nfunction evaluateField(actual: unknown, operators: RoutePredicateOperators): boolean {\n\tif ('$eq' in operators && !Object.is(actual, operators.$eq)) {\n\t\treturn false\n\t}\n\tif ('$ne' in operators && Object.is(actual, operators.$ne)) {\n\t\treturn false\n\t}\n\tif (\n\t\toperators.$in !== undefined &&\n\t\t!operators.$in.some((candidate) => Object.is(actual, candidate))\n\t) {\n\t\treturn false\n\t}\n\n\tconst numericChecks: [keyof RoutePredicateOperators, (a: number, b: number) => boolean][] = [\n\t\t['$lt', (a, b) => a < b],\n\t\t['$lte', (a, b) => a <= b],\n\t\t['$gt', (a, b) => a > b],\n\t\t['$gte', (a, b) => a >= b],\n\t]\n\tfor (const [operator, compare] of numericChecks) {\n\t\tconst bound = operators[operator]\n\t\tif (bound === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof actual !== 'number' || typeof bound !== 'number') {\n\t\t\treturn false\n\t\t}\n\t\tif (!compare(actual, bound)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n/**\n * Evaluates a predicate against a record. A `null` record (the target does not\n * exist) satisfies only an empty predicate; any field condition fails, since a\n * missing record cannot meet a comparison.\n *\n * @param record - The current materialized record, or `null` if absent\n * @param predicate - The field conditions that must all hold\n * @returns `true` when every field condition is satisfied\n */\nexport function evaluateRoutePredicate(\n\trecord: Record<string, unknown> | null,\n\tpredicate: RoutePredicate,\n): boolean {\n\tconst fields = Object.keys(predicate)\n\tif (fields.length === 0) {\n\t\treturn true\n\t}\n\tif (record === null) {\n\t\treturn false\n\t}\n\tfor (const field of fields) {\n\t\tconst operators = predicate[field]\n\t\tif (operators && !evaluateField(record[field], operators)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Options for creating a TokenAuthProvider.\n */\nexport interface TokenAuthProviderOptions {\n\t/**\n\t * Validate a token and return an AuthContext if valid, or null if rejected.\n\t * This is where you implement your auth logic (JWT verification, database lookup, etc.).\n\t */\n\tvalidate: (token: string) => Promise<AuthContext | null>\n}\n\n/**\n * Token-based auth provider that delegates validation to a user-provided function.\n *\n * @example\n * ```typescript\n * const auth = new TokenAuthProvider({\n * validate: async (token) => {\n * const user = await verifyJWT(token)\n * return user ? { userId: user.id } : null\n * }\n * })\n * ```\n */\nexport class TokenAuthProvider implements AuthProvider {\n\tprivate readonly validate: (token: string) => Promise<AuthContext | null>\n\n\tconstructor(options: TokenAuthProviderOptions) {\n\t\tthis.validate = options.validate\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\treturn this.validate(token)\n\t}\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Validates a Kora auth JWT and returns identity claims.\n * This interface matches the signature of TokenManager.validateToken()\n * from @korajs/auth without requiring a direct import.\n */\ninterface TokenValidator {\n\tvalidateToken(token: string): {\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t} | null\n\tvalidateTokenWithRevocation?(token: string): Promise<{\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t} | null>\n}\n\n/**\n * Looks up a user by ID. Returns null if the user doesn't exist.\n * This interface matches InMemoryUserStore.findById() from @korajs/auth\n * without requiring a direct import.\n */\ninterface UserLookup {\n\tfindById(userId: string): Promise<{\n\t\tid: string\n\t\temail: string\n\t\tname: string\n\t} | null>\n}\n\n/**\n * Optional device touch callback for updating last-seen timestamps.\n */\ninterface DeviceToucher {\n\ttouchDevice(deviceId: string): Promise<void>\n}\n\n/**\n * Configuration for creating a KoraAuthProvider.\n */\nexport interface KoraAuthProviderOptions {\n\t/**\n\t * Token validator that verifies JWT signatures and returns claims.\n\t * Typically a `TokenManager` instance from `@korajs/auth/server`.\n\t * If the validator also implements `validateTokenWithRevocation`, the sync\n\t * server uses it so signed-out sessions and revoked devices are rejected.\n\t */\n\ttokenValidator: TokenValidator\n\n\t/**\n\t * User lookup for verifying the user still exists.\n\t * Typically an `InMemoryUserStore` instance from `@korajs/auth/server`.\n\t */\n\tuserLookup: UserLookup\n\n\t/**\n\t * Optional device tracker for updating last-seen timestamps.\n\t * Typically the same `InMemoryUserStore` if it implements `touchDevice`.\n\t */\n\tdeviceTracker?: DeviceToucher\n\n\t/**\n\t * Optional scope resolver. Called with the user ID to determine\n\t * which collections/records the user can sync.\n\t */\n\tresolveScopes?: (userId: string) => Promise<Record<string, Record<string, unknown>>>\n}\n\n/**\n * Auth provider that bridges `@korajs/auth` token management with the\n * sync server's authentication layer.\n *\n * Validates access tokens issued by `@korajs/auth`'s `TokenManager`,\n * verifies the user still exists, and optionally computes per-user\n * sync scopes. This is the recommended way to connect @korajs/auth\n * to @korajs/server.\n *\n * @example\n * ```typescript\n * import { TokenManager, InMemoryUserStore } from '@korajs/auth/server'\n * import { KoraAuthProvider, KoraSyncServer } from '@korajs/server'\n *\n * const tokenManager = new TokenManager({ secret: 'my-secret' })\n * const userStore = new InMemoryUserStore()\n *\n * const auth = new KoraAuthProvider({\n * tokenValidator: tokenManager,\n * userLookup: userStore,\n * deviceTracker: userStore,\n * resolveScopes: async (userId) => ({\n * forms: { userId },\n * responses: { formOwnerId: userId },\n * }),\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n */\nexport class KoraAuthProvider implements AuthProvider {\n\tprivate readonly tokenValidator: TokenValidator\n\tprivate readonly userLookup: UserLookup\n\tprivate readonly deviceTracker: DeviceToucher | undefined\n\tprivate readonly resolveScopes:\n\t\t| ((userId: string) => Promise<Record<string, Record<string, unknown>>>)\n\t\t| undefined\n\n\tconstructor(options: KoraAuthProviderOptions) {\n\t\tthis.tokenValidator = options.tokenValidator\n\t\tthis.userLookup = options.userLookup\n\t\tthis.deviceTracker = options.deviceTracker\n\t\tthis.resolveScopes = options.resolveScopes\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\t// Validate the JWT signature and expiration\n\t\tconst payload = this.tokenValidator.validateTokenWithRevocation\n\t\t\t? await this.tokenValidator.validateTokenWithRevocation(token)\n\t\t\t: this.tokenValidator.validateToken(token)\n\t\tif (payload === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Only accept access tokens for sync authentication\n\t\tif (payload.type !== 'access') {\n\t\t\treturn null\n\t\t}\n\n\t\t// Verify the user still exists (may have been deleted since token was issued)\n\t\tconst user = await this.userLookup.findById(payload.sub)\n\t\tif (user === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Update device last-seen timestamp\n\t\tif (this.deviceTracker) {\n\t\t\tawait this.deviceTracker.touchDevice(payload.dev)\n\t\t}\n\n\t\t// Compute sync scopes if a resolver is configured\n\t\tconst scopes = this.resolveScopes ? await this.resolveScopes(payload.sub) : undefined\n\n\t\treturn {\n\t\t\tuserId: payload.sub,\n\t\t\tscopes,\n\t\t\tmetadata: {\n\t\t\t\tdeviceId: payload.dev,\n\t\t\t\temail: user.email,\n\t\t\t\tname: user.name,\n\t\t\t},\n\t\t}\n\t}\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Configuration for creating a MixedAuthProvider.\n */\nexport interface MixedAuthProviderOptions {\n\t/**\n\t * Primary auth provider that validates tokens from authenticated users.\n\t * Typically a `KoraAuthProvider`, `TokenAuthProvider`, or the result of\n\t * `authRoutes.toSyncAuthProvider()`.\n\t */\n\tprimary: AuthProvider\n\n\t/**\n\t * Scopes to apply to anonymous connections.\n\t * Each key is a collection name; the value is a filter object\n\t * (use `{}` for unrestricted access to that collection).\n\t *\n\t * @example\n\t * ```typescript\n\t * // Anonymous users can only sync the 'responses' collection\n\t * anonymousScopes: { responses: {} }\n\t *\n\t * // Anonymous users can read published forms\n\t * anonymousScopes: { forms: { status: 'published' } }\n\t * ```\n\t */\n\tanonymousScopes: Record<string, Record<string, unknown>>\n\n\t/**\n\t * Prefix for generated anonymous user IDs.\n\t * A unique suffix is appended to each connection.\n\t * @default 'anon'\n\t */\n\tanonymousPrefix?: string\n}\n\n/**\n * Auth provider that supports both authenticated and anonymous connections.\n *\n * When a client connects with a valid token, the primary auth provider\n * handles authentication normally. When a client connects without a token\n * (or with an invalid one), the connection is accepted as anonymous with\n * restricted sync scopes.\n *\n * This is the recommended pattern for apps that need public data access\n * alongside authenticated users — for example, a form builder where\n * authenticated users create forms but anyone can submit responses.\n *\n * @example\n * ```typescript\n * import { MixedAuthProvider, KoraAuthProvider } from '@korajs/server'\n *\n * const auth = new MixedAuthProvider({\n * primary: authRoutes.toSyncAuthProvider(),\n * anonymousScopes: {\n * // Anonymous users can only sync the 'responses' collection\n * responses: {},\n * },\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n *\n * @example\n * ```typescript\n * // On the client, return an empty token for unauthenticated users:\n * const app = createApp({\n * schema,\n * sync: {\n * url: 'wss://my-server.com/kora',\n * auth: async () => ({\n * token: (await authClient.getAccessToken()) ?? '',\n * }),\n * },\n * })\n * ```\n */\nexport class MixedAuthProvider implements AuthProvider {\n\tprivate readonly primary: AuthProvider\n\tprivate readonly anonymousScopes: Record<string, Record<string, unknown>>\n\tprivate readonly anonymousPrefix: string\n\tprivate anonymousCounter = 0\n\n\tconstructor(options: MixedAuthProviderOptions) {\n\t\tthis.primary = options.primary\n\t\tthis.anonymousScopes = options.anonymousScopes\n\t\tthis.anonymousPrefix = options.anonymousPrefix ?? 'anon'\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext> {\n\t\t// Try authenticated path first when a token is provided\n\t\tif (token) {\n\t\t\tconst ctx = await this.primary.authenticate(token)\n\t\t\tif (ctx) return ctx\n\t\t}\n\n\t\t// Fall back to scoped anonymous access\n\t\tthis.anonymousCounter++\n\t\treturn {\n\t\t\tuserId: `${this.anonymousPrefix}-${Date.now()}-${this.anonymousCounter}`,\n\t\t\tscopes: this.anonymousScopes,\n\t\t}\n\t}\n}\n","import type { KoraSyncServerConfig } from '../types'\nimport { KoraSyncServer } from './kora-sync-server'\n\n/**\n * Factory function to create a KoraSyncServer.\n *\n * @param config - Server configuration\n * @returns A new KoraSyncServer instance\n *\n * @example\n * ```typescript\n * const server = createKoraServer({\n * store: new MemoryServerStore(),\n * port: 3000,\n * })\n * await server.start()\n * ```\n */\nexport function createKoraServer(config: KoraSyncServerConfig): KoraSyncServer {\n\treturn new KoraSyncServer(config)\n}\n","import type { BlobRef } from '@korajs/core'\nimport type { ServerStore } from '../store/server-store'\nimport { WsServerTransport } from '../transport/ws-server-transport'\nimport type { KoraSyncServerConfig } from '../types'\nimport { KoraSyncServer } from './kora-sync-server'\nimport type { ProductionHttpRouteContext } from './route-context'\n\n/**\n * Configuration for the production server that serves both\n * static files and WebSocket sync on a single port.\n */\nexport interface ProductionServerConfig {\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Port to listen on. Defaults to 3001 or process.env.PORT. */\n\tport?: number\n\t/** Directory containing built static files. Defaults to './dist'. */\n\tstaticDir?: string\n\t/** WebSocket sync path. Defaults to '/kora-sync'. */\n\tsyncPath?: string\n\t/** Additional KoraSyncServer options */\n\tsyncOptions?: Omit<KoraSyncServerConfig, 'store' | 'port' | 'host' | 'path'>\n\t/**\n\t * Cross-Origin-Embedder-Policy for static and route responses. Defaults to\n\t * `credentialless`, which keeps third-party embeds usable while allowing\n\t * capable browsers to enable cross-origin isolation. Use `require-corp` only\n\t * when every embedded resource explicitly opts in with CORP/CORS headers.\n\t */\n\tcrossOriginEmbedderPolicy?: 'credentialless' | 'require-corp' | 'unsafe-none'\n\t/**\n\t * Optional HTTP route handlers mounted before static file serving.\n\t *\n\t * This is intentionally framework-agnostic so packages such as\n\t * `@korajs/auth` can plug into the production server without requiring\n\t * Express, Hono, or another HTTP framework.\n\t */\n\thttpRoutes?: ProductionHttpRoute[]\n\t/**\n\t * Optional token protection for operational endpoints.\n\t *\n\t * When a token is omitted, the matching endpoint group remains public for\n\t * backward compatibility. Production apps should set at least adminToken and\n\t * backupToken.\n\t */\n\toperationalAuth?: ProductionOperationalAuth\n}\n\nexport interface ProductionOperationalAuth {\n\t/** Protects /__kora, /__kora/status, and /__kora/events. */\n\tadminToken?: string\n\t/** Protects /__kora/metrics. Falls back to adminToken when omitted. */\n\tmetricsToken?: string\n\t/** Protects /__kora/backup/*. Falls back to adminToken when omitted. */\n\tbackupToken?: string\n}\n\nexport interface ProductionHttpRouteRequest {\n\tmethod: string\n\tpath: string\n\tbody?: unknown\n\theaders?: Record<string, string | string[] | undefined>\n\tquery?: Record<string, string | string[] | undefined>\n\tip?: string\n\t/**\n\t * Scoped, validated data-plane access. Use `kora.apply()` to mutate through\n\t * the same pipeline as sync (constraints, referential integrity, fan-out) and\n\t * `kora.query()` / `kora.findById()` to read materialized state, instead of\n\t * writing to the store directly and bypassing those guarantees.\n\t */\n\tkora: ProductionHttpRouteContext\n}\n\nexport interface ProductionHttpRouteResponse {\n\tstatus: number\n\tbody?: unknown\n\theaders?: Record<string, string>\n}\n\nexport interface ProductionHttpRoute {\n\t/** URL path prefix, for example `/auth`. */\n\tpath: string\n\thandle(request: ProductionHttpRouteRequest): Promise<ProductionHttpRouteResponse>\n}\n\n/**\n * A production server handle returned by createProductionServer.\n */\nexport interface ProductionServer {\n\t/** Start listening. Returns the URL the server is available at. */\n\tstart(): Promise<string>\n\t/** Stop the server gracefully. */\n\tstop(): Promise<void>\n\t/**\n\t * Trusted, scoped data-plane access for server-side callers that have no HTTP\n\t * request — background jobs, scheduled tasks, seeding scripts.\n\t *\n\t * `kora.apply()` runs the mutation through the exact same validated pipeline as\n\t * sync (Tier 2 constraints, referential integrity, materialization, and fan-out\n\t * to connected clients), and `kora.query()` / `kora.findById()` read\n\t * materialized state. This is the same context handed to custom HTTP routes as\n\t * `request.kora`, so a job and a request share one code path and one set of\n\t * guarantees instead of the job writing to the store directly and silently\n\t * bypassing validation.\n\t */\n\tkora: ProductionHttpRouteContext\n\t/**\n\t * Every blob reference still reachable from a live record across all\n\t * collections that declare a `blob` field. This is the live set for\n\t * garbage-collecting the server's central blob store: pass it to\n\t * `collectBlobGarbage(blobStore, refs)` from `@korajs/store` on a schedule to\n\t * reclaim bytes no record points at any more.\n\t *\n\t * @returns Every live blob reference the server can currently see.\n\t */\n\tgetLiveBlobRefs(): Promise<BlobRef[]>\n}\n\n// MIME types for static file serving\nconst MIME_TYPES: Record<string, string> = {\n\t'.html': 'text/html',\n\t'.js': 'text/javascript',\n\t'.css': 'text/css',\n\t'.json': 'application/json',\n\t'.png': 'image/png',\n\t'.jpg': 'image/jpeg',\n\t'.svg': 'image/svg+xml',\n\t'.ico': 'image/x-icon',\n\t'.wasm': 'application/wasm',\n\t'.woff': 'font/woff',\n\t'.woff2': 'font/woff2',\n\t'.map': 'application/json',\n}\n\n/**\n * Creates a production server that serves both static files and WebSocket sync\n * on a single port, plus built-in dashboard and observability endpoints.\n *\n * @param config - Production server configuration\n * @returns A ProductionServer instance\n *\n * @example\n * ```typescript\n * const server = createProductionServer({\n * store: createSqliteServerStore({ filename: './kora-server.db' }),\n * })\n * const url = await server.start()\n * ```\n */\nexport function createProductionServer(config: ProductionServerConfig): ProductionServer {\n\tconst port = config.port ?? (Number(process.env.PORT) || 3001)\n\tconst staticDir = config.staticDir ?? './dist'\n\tconst syncPath = config.syncPath ?? '/kora-sync'\n\tconst crossOriginEmbedderPolicy = config.crossOriginEmbedderPolicy ?? 'credentialless'\n\n\tconst syncServer = new KoraSyncServer({\n\t\tstore: config.store,\n\t\tenableDashboard: true,\n\t\t...config.syncOptions,\n\t})\n\n\t// Scoped, validated data-plane access handed to every custom HTTP route as\n\t// `request.kora`, exposed on the handle as `server.kora`, and used by the\n\t// operation validator. One shared context (it holds no per-request state).\n\tconst routeContext = syncServer.getKoraContext()\n\n\tlet httpServer: import('node:http').Server | null = null\n\n\tfunction getOperationalToken(kind: 'admin' | 'metrics' | 'backup'): string | undefined {\n\t\tconst auth = config.operationalAuth\n\t\tif (!auth) return undefined\n\t\tif (kind === 'metrics') return auth.metricsToken || auth.adminToken\n\t\tif (kind === 'backup') return auth.backupToken || auth.adminToken\n\t\treturn auth.adminToken\n\t}\n\n\tfunction extractRequestToken(req: import('node:http').IncomingMessage): string | null {\n\t\tconst authorization = req.headers.authorization\n\t\tif (authorization?.startsWith('Bearer ')) {\n\t\t\treturn authorization.slice('Bearer '.length).trim()\n\t\t}\n\n\t\tconst headerNames = ['x-kora-admin-token', 'x-kora-metrics-token', 'x-kora-backup-token']\n\t\tfor (const name of headerNames) {\n\t\t\tconst value = req.headers[name]\n\t\t\tif (typeof value === 'string' && value.length > 0) return value\n\t\t\tif (Array.isArray(value) && typeof value[0] === 'string' && value[0].length > 0) {\n\t\t\t\treturn value[0]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tfunction isOperationalRequestAllowed(\n\t\treq: import('node:http').IncomingMessage,\n\t\tkind: 'admin' | 'metrics' | 'backup',\n\t): boolean {\n\t\tconst expected = getOperationalToken(kind)\n\t\tif (!expected) return true\n\t\treturn extractRequestToken(req) === expected\n\t}\n\n\tfunction rejectUnauthorized(res: import('node:http').ServerResponse): void {\n\t\tres.writeHead(401, {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'WWW-Authenticate': 'Bearer realm=\"kora\"',\n\t\t})\n\t\tres.end(JSON.stringify({ error: 'Unauthorized' }))\n\t}\n\n\t/**\n\t * Format the metrics snapshot as Prometheus exposition format.\n\t * Zero-dependency — no prom-client needed.\n\t */\n\tfunction formatPrometheusMetrics(): string {\n\t\tconst status = syncServer.getMetricsCollector().getSnapshot(0)\n\t\tconst lines: string[] = [\n\t\t\t'# HELP kora_connected_clients Current number of connected clients',\n\t\t\t'# TYPE kora_connected_clients gauge',\n\t\t\t`kora_connected_clients ${status.connectedClients}`,\n\t\t\t'',\n\t\t\t'# HELP kora_peak_connections Peak number of simultaneous connections since server start',\n\t\t\t'# TYPE kora_peak_connections gauge',\n\t\t\t`kora_peak_connections ${status.peakConnections}`,\n\t\t\t'',\n\t\t\t'# HELP kora_connections_total Total number of connections handled since server start',\n\t\t\t'# TYPE kora_connections_total counter',\n\t\t\t`kora_connections_total ${status.connectionsTotal}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_received_total Total operations received from clients',\n\t\t\t'# TYPE kora_operations_received_total counter',\n\t\t\t`kora_operations_received_total ${status.operationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_sent_total Total operations sent to clients',\n\t\t\t'# TYPE kora_operations_sent_total counter',\n\t\t\t`kora_operations_sent_total ${status.operationsSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_received_total Total bytes received from clients',\n\t\t\t'# TYPE kora_bytes_received_total counter',\n\t\t\t`kora_bytes_received_total ${status.bytesReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_sent_total Total bytes sent to clients',\n\t\t\t'# TYPE kora_bytes_sent_total counter',\n\t\t\t`kora_bytes_sent_total ${status.bytesSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_errors_total Total errors since server start',\n\t\t\t'# TYPE kora_errors_total counter',\n\t\t\t`kora_errors_total ${status.errorCount}`,\n\t\t\t'',\n\t\t\t'# HELP kora_uptime_seconds Server uptime in seconds',\n\t\t\t'# TYPE kora_uptime_seconds gauge',\n\t\t\t`kora_uptime_seconds ${Math.floor(status.uptime / 1000)}`,\n\t\t\t'',\n\t\t\t'# HELP kora_schema_version Schema version the server expects',\n\t\t\t'# TYPE kora_schema_version gauge',\n\t\t\t`kora_schema_version ${status.schemaVersion}`,\n\t\t\t'',\n\t\t]\n\t\treturn lines.join('\\n')\n\t}\n\n\tfunction readBodyBuffer(req: import('node:http').IncomingMessage): Promise<Buffer> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst chunks: Buffer[] = []\n\t\t\treq.on('data', (chunk: Buffer) => chunks.push(chunk))\n\t\t\treq.on('end', () => resolve(Buffer.concat(chunks)))\n\t\t\t// A raw http.IncomingMessage starts paused: attaching 'data'/'end'\n\t\t\t// listeners alone does not put it in flowing mode. Without an\n\t\t\t// explicit resume(), 'data' never fires, 'end' fires immediately with\n\t\t\t// zero chunks, and every POST body silently reads back as empty —\n\t\t\t// which is exactly what broke httpRoutes handlers (including\n\t\t\t// @korajs/auth's signup/signin) reading `req.body`. Guard with\n\t\t\t// `readableFlowing` so this stays a no-op if the stream is already\n\t\t\t// flowing (e.g. a future caller that reads it differently).\n\t\t\tif (!req.readableFlowing) {\n\t\t\t\treq.resume()\n\t\t\t}\n\t\t\t// If the client disconnects mid-upload, `end` never fires; resolve\n\t\t\t// with whatever arrived instead of leaving the request hung forever.\n\t\t\treq.on('error', () => resolve(Buffer.concat(chunks)))\n\t\t})\n\t}\n\n\tasync function readJsonBody(req: import('node:http').IncomingMessage): Promise<unknown> {\n\t\tconst buffer = await readBodyBuffer(req)\n\t\tif (buffer.byteLength === 0) return undefined\n\t\ttry {\n\t\t\treturn JSON.parse(buffer.toString('utf8')) as unknown\n\t\t} catch {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tfunction matchesRoutePrefix(pathname: string, prefix: string): boolean {\n\t\tconst normalizedPrefix = normalizeRoutePath(prefix)\n\t\treturn pathname === normalizedPrefix || pathname.startsWith(`${normalizedPrefix}/`)\n\t}\n\n\tfunction normalizeRoutePath(path: string): string {\n\t\tconst prefixed = path.startsWith('/') ? path : `/${path}`\n\t\treturn prefixed.length > 1 ? prefixed.replace(/\\/+$/, '') : prefixed\n\t}\n\n\tfunction getClientIp(req: import('node:http').IncomingMessage): string | undefined {\n\t\tconst forwarded = req.headers['x-forwarded-for']\n\t\tif (typeof forwarded === 'string' && forwarded.length > 0) {\n\t\t\treturn forwarded.split(',')[0]?.trim()\n\t\t}\n\t\treturn req.socket.remoteAddress\n\t}\n\n\tfunction getQuery(url: URL): Record<string, string | string[] | undefined> {\n\t\tconst query: Record<string, string | string[] | undefined> = {}\n\t\tfor (const [key, value] of url.searchParams) {\n\t\t\tconst existing = query[key]\n\t\t\tif (existing === undefined) {\n\t\t\t\tquery[key] = value\n\t\t\t} else if (Array.isArray(existing)) {\n\t\t\t\texisting.push(value)\n\t\t\t} else {\n\t\t\t\tquery[key] = [existing, value]\n\t\t\t}\n\t\t}\n\t\treturn query\n\t}\n\n\tfunction writeJsonResponse(\n\t\tres: import('node:http').ServerResponse,\n\t\tresult: ProductionHttpRouteResponse,\n\t): void {\n\t\tconst headers = {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(result.headers ?? {}),\n\t\t}\n\t\tres.writeHead(result.status, headers)\n\t\tres.end(JSON.stringify(result.body ?? null))\n\t}\n\n\treturn {\n\t\tkora: routeContext,\n\n\t\tgetLiveBlobRefs(): Promise<BlobRef[]> {\n\t\t\treturn syncServer.getLiveBlobRefs()\n\t\t},\n\n\t\tasync start(): Promise<string> {\n\t\t\tconst { createServer } = await import('node:http')\n\t\t\tconst { createReadStream, existsSync, statSync } = await import('node:fs')\n\t\t\tconst { extname, join, resolve } = await import('node:path')\n\t\t\tconst { WebSocketServer } = await import('ws')\n\n\t\t\tconst distDir = resolve(staticDir)\n\n\t\t\thttpServer = createServer(async (req, res) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait handleRequest(req, res)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// http.createServer never awaits its request listener, so a\n\t\t\t\t\t// callback that rejects becomes an unhandled promise rejection\n\t\t\t\t\t// process-wide, and Node's default `--unhandled-rejections=throw`\n\t\t\t\t\t// crashes the entire server. One bad request (malformed body,\n\t\t\t\t\t// a buggy custom httpRoute handler, anything unexpected) must\n\t\t\t\t\t// only fail that one response, never take the whole process\n\t\t\t\t\t// down with it.\n\t\t\t\t\tconsole.error('[kora] Unhandled error in HTTP request handler:', error)\n\t\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Internal server error' }))\n\t\t\t\t\t} else if (!res.writableEnded) {\n\t\t\t\t\t\tres.end()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tasync function handleRequest(\n\t\t\t\treq: import('node:http').IncomingMessage,\n\t\t\t\tres: import('node:http').ServerResponse,\n\t\t\t): Promise<void> {\n\t\t\t\t// COOP/COEP headers required for SharedArrayBuffer (OPFS persistence)\n\t\t\t\tres.setHeader('Cross-Origin-Opener-Policy', 'same-origin')\n\t\t\t\tres.setHeader('Cross-Origin-Embedder-Policy', crossOriginEmbedderPolicy)\n\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\n\t\t\t\t// ── Health check ──────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/health') {\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tstatus: 'ok',\n\t\t\t\t\t\t\tversion: status.version,\n\t\t\t\t\t\t\tuptime: status.uptime,\n\t\t\t\t\t\t\tconnectedClients: status.connectedClients,\n\t\t\t\t\t\t\ttotalOperations: status.totalOperations,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Status endpoint ───────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/status') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(JSON.stringify(status, null, 2))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Prometheus metrics endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/metrics') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'metrics')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4' })\n\t\t\t\t\tres.end(formatPrometheusMetrics())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Server-Sent Events endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/events') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t'Content-Type': 'text/event-stream',\n\t\t\t\t\t\t'Cache-Control': 'no-cache',\n\t\t\t\t\t\tConnection: 'keep-alive',\n\t\t\t\t\t\t'X-Accel-Buffering': 'no',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Send initial status event\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(status)}\\n\\n`)\n\n\t\t\t\t\t// Poll metrics periodically and push as SSE events\n\t\t\t\t\tconst interval = setInterval(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst s = await syncServer.getStatus()\n\t\t\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(s)}\\n\\n`)\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Connection may have closed\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 2000)\n\n\t\t\t\t\t// Clean up on connection close\n\t\t\t\t\treq.on('close', () => {\n\t\t\t\t\t\tclearInterval(interval)\n\t\t\t\t\t})\n\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Dashboard HTML ────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora' || url.pathname === '/__kora/') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n\t\t\t\t\tres.end(renderDashboardHtml(status))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup export ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/export' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst backup = await config.store.exportBackup()\n\t\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t\t\t\t\t'Content-Disposition': `attachment; filename=\"kora-backup-${Date.now()}.kora\"`,\n\t\t\t\t\t\t\t'Content-Length': String(backup.byteLength),\n\t\t\t\t\t\t})\n\t\t\t\t\t\tres.end(Buffer.from(backup))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Backup failed', message: (error as Error).message }))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup import ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/import' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst body = await readBodyBuffer(req)\n\t\t\t\t\t\tconst merge = url.searchParams.get('merge') === 'true'\n\t\t\t\t\t\tconst result = await config.store.importBackup(\n\t\t\t\t\t\t\tnew Uint8Array(body.buffer, body.byteOffset, body.byteLength),\n\t\t\t\t\t\t\tmerge,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tres.writeHead(result.success ? 200 : 400, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify(result))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Restore failed', message: (error as Error).message }))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Custom HTTP routes (auth, webhooks, app APIs) ─────────────\n\t\t\t\tconst customRoute = config.httpRoutes?.find((route) =>\n\t\t\t\t\tmatchesRoutePrefix(url.pathname, route.path),\n\t\t\t\t)\n\t\t\t\tif (customRoute) {\n\t\t\t\t\tconst result = await customRoute.handle({\n\t\t\t\t\t\tmethod: req.method ?? 'GET',\n\t\t\t\t\t\tpath: url.pathname,\n\t\t\t\t\t\tbody: await readJsonBody(req),\n\t\t\t\t\t\theaders: req.headers,\n\t\t\t\t\t\tquery: getQuery(url),\n\t\t\t\t\t\tip: getClientIp(req),\n\t\t\t\t\t\tkora: routeContext,\n\t\t\t\t\t})\n\t\t\t\t\twriteJsonResponse(res, result)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Static file serving ───────────────────────────────────────\n\t\t\t\tlet filePath = join(distDir, url.pathname)\n\n\t\t\t\t// SPA fallback: serve index.html for non-file routes\n\t\t\t\tif (!extname(filePath)) {\n\t\t\t\t\tconst indexPath = join(filePath, 'index.html')\n\t\t\t\t\tif (existsSync(indexPath)) {\n\t\t\t\t\t\tfilePath = indexPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!existsSync(filePath)) {\n\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst stat = statSync(filePath)\n\t\t\t\t\tif (stat.isDirectory()) {\n\t\t\t\t\t\tfilePath = join(filePath, 'index.html')\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t}\n\n\t\t\t\tif (!existsSync(filePath)) {\n\t\t\t\t\tres.writeHead(404)\n\t\t\t\t\tres.end('Not Found')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst ext = extname(filePath)\n\t\t\t\tconst contentType = MIME_TYPES[ext] || 'application/octet-stream'\n\t\t\t\tres.writeHead(200, { 'Content-Type': contentType })\n\t\t\t\tcreateReadStream(filePath).pipe(res)\n\t\t\t}\n\n\t\t\tconst wss = new WebSocketServer({ noServer: true })\n\n\t\t\thttpServer.on('upgrade', (req, socket, head) => {\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\t\t\t\tif (url.pathname === syncPath) {\n\t\t\t\t\twss.handleUpgrade(req, socket, head, (ws) => {\n\t\t\t\t\t\tconst transport = new WsServerTransport(ws)\n\t\t\t\t\t\tsyncServer.handleConnection(transport)\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsocket.destroy()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\t\tconst onError = (error: Error) => {\n\t\t\t\t\treject(error)\n\t\t\t\t}\n\t\t\t\thttpServer?.once('error', onError)\n\t\t\t\thttpServer?.listen(port, '0.0.0.0', () => {\n\t\t\t\t\thttpServer?.off('error', onError)\n\t\t\t\t\tresolve(`http://localhost:${port}`)\n\t\t\t\t})\n\t\t\t})\n\t\t},\n\n\t\tasync stop(): Promise<void> {\n\t\t\tawait syncServer.stop()\n\t\t\tif (httpServer) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\thttpServer?.close(() => resolve())\n\t\t\t\t})\n\t\t\t\thttpServer = null\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Render a minimal self-contained dashboard HTML page.\n * Shows server status with live-updating metrics via SSE.\n */\nfunction renderDashboardHtml(status: {\n\tversion: string\n\tuptime: number\n\tconnectedClients: number\n\ttotalOperations: number\n\tschemaVersion: number\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\toperationsSent: number\n\terrorCount: number\n}): string {\n\tconst version = status.version\n\tconst uptime = formatUptime(status.uptime)\n\treturn `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Kora Dashboard</title>\n<style>\n * { box-sizing: border-box; margin: 0; padding: 0 }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0; padding: 2rem }\n h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.25rem }\n .subtitle { color: #64748b; margin-bottom: 2rem; font-size: 0.875rem }\n .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem }\n .card { background: #1e293b; border: 1px solid #334155; border-radius: 0.75rem; padding: 1.25rem }\n .card .label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: #64748b; margin-bottom: 0.5rem }\n .card .value { font-size: 1.75rem; font-weight: 700; color: #38bdf8 }\n .card .value.green { color: #4ade80 }\n .card .value.red { color: #f87171 }\n .card .value.yellow { color: #fbbf24 }\n .section-title { font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; margin-top: 1.5rem }\n table { width: 100%; border-collapse: collapse; font-size: 0.875rem }\n th { text-align: left; padding: 0.5rem 0.75rem; color: #64748b; font-weight: 500; border-bottom: 1px solid #334155 }\n td { padding: 0.5rem 0.75rem; border-bottom: 1px solid #1e293b }\n .status-dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; margin-right: 0.375rem }\n .status-dot.running { background: #4ade80 }\n .status-dot.stopped { background: #f87171 }\n</style>\n</head>\n<body>\n<h1>Kora Sync Server</h1>\n<p class=\"subtitle\">v${version} &middot; <span class=\"status-dot running\"></span>Running</p>\n<div class=\"grid\">\n <div class=\"card\"><div class=\"label\">Uptime</div><div class=\"value\">${uptime}</div></div>\n <div class=\"card\"><div class=\"label\">Connected Clients</div><div class=\"value\" id=\"connectedClients\">${status.connectedClients}</div></div>\n <div class=\"card\"><div class=\"label\">Total Operations</div><div class=\"value\" id=\"totalOperations\">${status.totalOperations}</div></div>\n <div class=\"card\"><div class=\"label\">Peak Connections</div><div class=\"value green\" id=\"peakConnections\">${status.peakConnections}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Received</div><div class=\"value\" id=\"opsReceived\">${status.operationsReceived}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Sent</div><div class=\"value\" id=\"opsSent\">${status.operationsSent}</div></div>\n <div class=\"card\"><div class=\"label\">Errors</div><div class=\"value ${status.errorCount > 0 ? 'red' : 'green'}\" id=\"errors\">${status.errorCount}</div></div>\n <div class=\"card\"><div class=\"label\">Schema Version</div><div class=\"value\">${status.schemaVersion}</div></div>\n</div>\n<script>\n(function() {\n const es = new EventSource('/__kora/events');\n es.addEventListener('status', (e) => {\n const s = JSON.parse(e.data);\n for (const [id, val] of Object.entries({\n connectedClients: s.connectedClients,\n totalOperations: s.totalOperations,\n peakConnections: s.peakConnections,\n opsReceived: s.operationsReceived,\n opsSent: s.operationsSent,\n errors: s.errorCount,\n })) {\n const el = document.getElementById(id);\n if (el) { el.textContent = String(val); el.className = 'value' + (id === 'errors' && val > 0 ? ' red' : id === 'errors' ? ' green' : ''); }\n }\n });\n es.onerror = () => { setTimeout(() => document.location.reload(), 5000); };\n})();\n</script>\n</body>\n</html>`\n}\n\nfunction formatUptime(ms: number): string {\n\tconst seconds = Math.floor(ms / 1000)\n\tconst minutes = Math.floor(seconds / 60)\n\tconst hours = Math.floor(minutes / 60)\n\tconst parts: string[] = []\n\tif (hours > 0) parts.push(`${hours}h`)\n\tif (minutes % 60 > 0) parts.push(`${minutes % 60}m`)\n\tparts.push(`${seconds % 60}s`)\n\treturn parts.join(' ')\n}\n"],"mappings":"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","names":["operations","text","count","import_core","index","count","buildServerBackup","parseServerBackup","operations","import_core","buildServerBackup","operations","parseServerBackup","import_core","import_drizzle_orm","buildServerBackup","parseServerBackup","import_core","import_core","import_core","import_sync","import_merge","import_core","import_core","import_core","count","operations","response","import_core","import_internal","import_sync","import_core","operations","count","import_sync","import_core","records","operations","DEFAULT_BATCH_SIZE","DEFAULT_SCHEMA_VERSION","operations","resolve"]}
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../src/store/server-store.ts","../src/session/operation-validation.ts","../src/apply/ingest-validation.ts","../src/store/server-backup.ts","../src/index.ts","../src/logging/structured-logger.ts","../src/apply/rejection-taxonomy.ts","../src/store/memory-server-store.ts","../src/scopes/server-scope-filter.ts","../src/scopes/scope-predicate-errors.ts","../src/store/materialization.ts","../src/store/record-fold.ts","../src/store/server-identity.ts","../src/store/scope-snapshot.ts","../src/store/postgres-server-store.ts","../src/store/drizzle-pg-schema.ts","../src/store/envelope-column.ts","../src/store/legacy-bodies.ts","../src/store/log-integrity.ts","../src/store/quarantine-base.ts","../src/store/text-codec.ts","../src/store/sqlite-server-store.ts","../src/store/drizzle-schema.ts","../src/transport/http-server-transport.ts","../src/transport/ws-server-transport.ts","../src/session/client-session.ts","../src/apply/apply-server-operation.ts","../src/constraints/constraint-authority.ts","../src/apply/derive-server-op-id.ts","../src/constraints/server-constraint-context.ts","../src/constraints/operation-constraint-validator.ts","../src/constraints/server-referential-context.ts","../src/apply/server-side-effect-operation.ts","../src/auth/no-auth.ts","../src/encryption/key-record-service.ts","../src/scopes/reference-authorization.ts","../src/richtext/blob-access-index.ts","../src/scopes/resolve-session-scopes.ts","../src/session/duplicate-identity.ts","../src/session/scope-entry.ts","../src/session/session-operation-limits.ts","../src/server/kora-sync-server.ts","../src/awareness/awareness-relay.ts","../src/diagnostics/server-metrics-collector.ts","../src/richtext/blob-chunk-relay.ts","../src/richtext/yjs-doc-relay.ts","../src/server/route-context.ts","../src/apply/route-predicate.ts","../src/auth/token-auth.ts","../src/auth/kora-auth-provider.ts","../src/auth/mixed-auth-provider.ts","../src/server/create-server.ts","../src/server/production-server.ts","../src/server/static-files.ts","../src/server/trust-proxy.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import type {\n\tFoldState,\n\tHLCTimestamp,\n\tHybridLogicalClock,\n\tOperation,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n\tVersionVector,\n} from '@korajs/core'\nimport { KoraError } from '@korajs/core'\nimport type { OperationTransform } from '@korajs/core'\nimport type { ApplyResult, SyncStore } from '@korajs/sync'\nimport type { UplinkAuthorizationResult } from '../scopes/server-scope-filter'\n\n/** Rejection code for a second, different operation under an existing (node, sequence). */\nexport const SEQUENCE_CONFLICT_CODE = 'SEQUENCE_CONFLICT'\n\n/**\n * Thrown by a store when an operation claims a `(nodeId, sequenceNumber)` that an\n * operation with a DIFFERENT id already holds (W3 step 4). A node's sequence numbers\n * identify its writes: accepting a second operation under the same number would make\n * one of them invisible to every version-vector delta and to the client's contiguous\n * acknowledged prefix. Nothing was written. Not retriable: the same bytes always fail.\n */\nexport class SequenceConflictError extends KoraError {\n\tconstructor(\n\t\treadonly operation: Pick<Operation, 'id' | 'nodeId' | 'sequenceNumber'>,\n\t\treadonly existingOperationId: string,\n\t) {\n\t\tsuper(\n\t\t\t`Operation \"${operation.id}\" claims sequence ${String(operation.sequenceNumber)} of node \"${operation.nodeId}\", which operation \"${existingOperationId}\" already holds. A node may never reuse a sequence number for different content.`,\n\t\t\tSEQUENCE_CONFLICT_CODE,\n\t\t\t{\n\t\t\t\toperationId: operation.id,\n\t\t\t\tnodeId: operation.nodeId,\n\t\t\t\tsequenceNumber: operation.sequenceNumber,\n\t\t\t\texistingOperationId,\n\t\t\t},\n\t\t)\n\t\tthis.name = 'SequenceConflictError'\n\t}\n}\n\n/** Rejection code for an operation holding a value the store cannot represent. */\nexport const UNSTORABLE_VALUE_CODE = 'UNSTORABLE_VALUE'\n\n/**\n * Thrown by a store when an operation carries a value the database cannot represent\n * (RT-65). Nothing was written. Not retriable: the same bytes always fail, so the\n * session refuses the operation terminally instead of failing the connection (which\n * made the device re-send it forever and blocked every later write of that device).\n */\nexport class UnstorableValueError extends KoraError {\n\tconstructor(\n\t\treadonly operation: Pick<Operation, 'id' | 'collection' | 'recordId'>,\n\t\tdetail: string,\n\t) {\n\t\tsuper(\n\t\t\t`Operation \"${operation.id}\" on ${operation.collection}/${operation.recordId} holds a value this server's database cannot store (${detail}). It is refused; nothing was written.`,\n\t\t\tUNSTORABLE_VALUE_CODE,\n\t\t\t{ operationId: operation.id, collection: operation.collection, recordId: operation.recordId },\n\t\t)\n\t\tthis.name = 'UnstorableValueError'\n\t}\n}\n\n/**\n * `kora_server_meta` key holding the sequence-enforcement epoch: the highest delivery\n * sequence in the log when this release first opened the store. Operations stored at\n * or below it were accepted by a release that allowed a node to reuse a sequence\n * number (beta.12 STORE-1/2); a newly uploaded operation that shares a (node,\n * sequence) only with such legacy operations is accepted as before (the client's\n * sequence repair may keep the OTHER op of a legacy duplicate pair at that number).\n * Above it, a writer that reserves its sequence numbers (see\n * {@link ApplyRemoteOptions.legacySequenceWriter}) is refused a held sequence.\n */\nexport const SEQUENCE_ENFORCEMENT_EPOCH_KEY = 'sequence_enforcement_epoch'\n\n/**\n * `kora_server_meta` key set once the legacy pairs already in the log were indexed in\n * `sequence_pairs` (RT-48); appends maintain the index from then on.\n */\nexport const SEQUENCE_PAIRS_BACKFILLED_KEY = 'sequence_pairs_backfilled'\n\n/**\n * Name of the partial unique index over (node_id, sequence_number) of the rows that\n * were the sole holder of their sequence when stored (`seq_unique = 1`, RT-37).\n *\n * Design: a row is flagged when nothing else held its (node, sequence) at insert, and\n * a row stored as the second of a pair (a legacy duplicate: a pre-epoch holder, or an\n * upload from a client without the `sequenceReservation` capability) is not. So the\n * index can never be violated by an accepted legacy pair, yet two concurrent sole\n * inserts of one (node, sequence) (the race between server instances it backs) still\n * collide. Rows written by a release without the column (older instances during a\n * rolling upgrade, or history) default to 0 and sit outside it; the append check, run\n * under the store's write lock, judges them as holders.\n */\nexport const NODE_SEQ_UNIQUE_INDEX = 'idx_node_seq_unique_sole'\n\n/** Earlier unique indexes over (node_id, sequence_number), dropped at startup. */\nexport const SUPERSEDED_NODE_SEQ_UNIQUE_INDEXES = [\n\t'idx_node_seq_unique',\n\t'idx_node_seq_unique_after_epoch',\n] as const\n\n/** Outcome of {@link judgeSequenceHolders}. */\nexport type SequenceHolderVerdict =\n\t/** No other operation holds the sequence: stored as its sole holder (indexed). */\n\t| { verdict: 'free' }\n\t/** Shares the sequence with `holderIds`, accepted: stored as a legacy pair. */\n\t| { verdict: 'legacy'; holderIds: string[]; legacyWriter: boolean }\n\t/** Refused: `holderId` holds the sequence under enforcement. */\n\t| { verdict: 'conflict'; holderId: string }\n\n/**\n * Decide an append against the operations already holding its (node, sequence):\n * `'conflict'` when any of them was stored after the enforcement epoch and the writer\n * reserves its sequence numbers; `'legacy'` (accepted, with a warning) when all of\n * them predate the epoch, or when the writer is a legacy client (RT-37: Kora <=\n * beta.12 could give two concurrent transactions one number, and refusing the second\n * would drop a write the user made); `'free'` when there are none. Holders with the\n * operation's own id are the caller's duplicate case.\n */\nexport function judgeSequenceHolders(\n\top: Pick<Operation, 'id' | 'nodeId' | 'sequenceNumber'>,\n\tholders: ReadonlyArray<{ id: string; deliverySequence: number }>,\n\tepoch: number,\n\twriter: { legacySequenceWriter?: boolean } = {},\n): SequenceHolderVerdict {\n\tconst others = holders.filter((holder) => holder.id !== op.id)\n\tif (others.length === 0) return { verdict: 'free' }\n\tconst enforced = others.find((holder) => holder.deliverySequence > epoch)\n\tconst holderIds = others.map((holder) => holder.id)\n\tconst list = holderIds.map((id) => `\"${id}\"`).join(', ')\n\tif (enforced) {\n\t\tif (writer.legacySequenceWriter !== true) {\n\t\t\treturn { verdict: 'conflict', holderId: enforced.id }\n\t\t}\n\t\tconsole.warn(\n\t\t\t`[kora] Operation \"${op.id}\" shares sequence ${String(op.sequenceNumber)} of node \"${op.nodeId}\" with operation(s) ${list}. The client does not reserve sequence numbers (no sequenceReservation capability: Kora <= beta.12), so this is a legacy duplicate pair: both are stored and delivered. Upgrade the client.`,\n\t\t)\n\t\treturn { verdict: 'legacy', holderIds, legacyWriter: true }\n\t}\n\tconsole.warn(\n\t\t`[kora] Operation \"${op.id}\" shares sequence ${String(op.sequenceNumber)} of node \"${op.nodeId}\" with operation(s) ${list} stored before sequence enforcement (a duplicate written by Kora <= beta.12). Accepted and stored, as that release did.`,\n\t)\n\treturn { verdict: 'legacy', holderIds, legacyWriter: false }\n}\n\n/** A stored legacy pair, reported to {@link ApplyRemoteOptions.onLegacySequencePair}. */\nexport interface LegacySequencePair {\n\toperationId: string\n\tnodeId: string\n\tsequenceNumber: number\n\t/** The operations that already held the sequence. */\n\tholderIds: string[]\n\t/** True when accepted because the writer is a legacy client (not a pre-epoch holder). */\n\tlegacyWriter: boolean\n}\n\n/**\n * Tell the caller of an append that it committed a legacy pair (see\n * {@link ApplyRemoteOptions.onLegacySequencePair}). Called by the built-in stores\n * after the write committed.\n */\nexport function reportLegacyPair(\n\top: Pick<Operation, 'id' | 'nodeId' | 'sequenceNumber'>,\n\tdecision: SequenceHolderVerdict,\n\toptions: Pick<ApplyRemoteOptions, 'onLegacySequencePair'> | undefined,\n): void {\n\tif (decision.verdict !== 'legacy' || !options?.onLegacySequencePair) return\n\toptions.onLegacySequencePair({\n\t\toperationId: op.id,\n\t\tnodeId: op.nodeId,\n\t\tsequenceNumber: op.sequenceNumber,\n\t\tholderIds: decision.holderIds,\n\t\tlegacyWriter: decision.legacyWriter,\n\t})\n}\n\n/**\n * How the server resolved an uploaded operation it did NOT store under the submitted\n * (node, sequence) (RT-43, RT-47):\n * - `'ignored'`: the validator answered `ignore` (handled out of band, nothing stored);\n * - `'refused'`: a terminal (non-retriable) rejection; the same id is answered with the\n * original rejection forever after;\n * - `'stored-elsewhere'`: the id is stored under another sequence of the same node (a\n * client sequence repair renumbered it), acknowledged as a duplicate.\n * A retriable rejection, and a `SEQUENCE_CONFLICT` (the client renumbers and resubmits\n * under the same id), are never resolutions.\n */\nexport type OperationResolutionOutcome = 'ignored' | 'refused' | 'stored-elsewhere'\n\n/** A durable record of how an uploaded operation was resolved without being stored. */\nexport interface OperationResolution {\n\toperationId: string\n\tnodeId: string\n\tsequenceNumber: number\n\toutcome: OperationResolutionOutcome\n\t/** Rejection code, for `'refused'`. */\n\tcode: string | null\n\t/** Rejection message, for `'refused'`. */\n\tmessage: string | null\n}\n\n/** Longest rejection message kept in an {@link OperationResolution}. */\nexport const MAX_RESOLUTION_MESSAGE_LENGTH = 1024\n\n/** Where a stored operation sits in its node's sequence space. */\nexport interface StoredOperationKey {\n\tnodeId: string\n\tsequenceNumber: number\n}\n\n/**\n * Owner recorded for a node id an admin released (see `ServerStore.releaseNodeClaim`):\n * the next principal to claim the node takes it over. Never a valid principal id.\n */\nexport const RELEASED_NODE_OWNER = ''\n\n/**\n * A materialized record reconstructed from the operation log\n * or read from a materialized collection table.\n */\nexport interface MaterializedRecord {\n\tid: string\n\t[key: string]: unknown\n}\n\n/**\n * A conditional, atomic multi-operation apply. The store reads the target under a\n * cross-instance lock, lets the caller decide admission and build the operations\n * against that locked state, and applies them in one transaction, or applies\n * nothing. `admit` and `buildOperations` run inside the locked transaction so the\n * predicate check and any atomic-op resolution see the authoritative current value\n * even when multiple server instances race on the same target.\n */\nexport interface ConditionalApplyInput {\n\t/** Record the admission lock and predicate are keyed on. */\n\ttarget: { collection: string; id: string }\n\t/** Decides admission against the target's locked current state. */\n\tadmit: (current: MaterializedRecord | null) => boolean\n\t/**\n\t * Builds the operations to apply, given the locked current state and a clock the\n\t * store has already advanced past the target record's latest committed operation.\n\t * Stamping the built operations with this clock guarantees they sort strictly\n\t * after every prior write to the target, so last-write-wins materialization\n\t * reflects the serialized commit order even when two instances commit in the same\n\t * millisecond. Without it, a same-millisecond tie could let materialization pick\n\t * an earlier resolved value and undercount an atomic counter, admitting past a cap.\n\t */\n\tbuildOperations: (\n\t\tcurrent: MaterializedRecord | null,\n\t\tcontext: ConditionalApplyContext,\n\t) => Promise<Operation[]>\n\t/**\n\t * When set, a record whose prior existence proves this set already committed.\n\t * Checked under the same lock as admission, so a retry is idempotent even across\n\t * instances: it returns `idempotent: true` without re-running the operations.\n\t */\n\tidempotencyKey?: { collection: string; id: string }\n}\n\n/** Context passed to {@link ConditionalApplyInput.buildOperations}. */\nexport interface ConditionalApplyContext {\n\t/**\n\t * A clock the store has advanced past the target record's latest committed\n\t * operation. Operations built here must be stamped with it (route context threads\n\t * it into operation creation) so they sort strictly after every prior write.\n\t */\n\tclock: HybridLogicalClock\n\t/**\n\t * Read a record as stored (including a soft-deleted one) inside the store's\n\t * conditional-apply transaction, for authorizing the built operations against the\n\t * same state they commit over. Optional; callers fall back to a plain read.\n\t */\n\treadStoredRow?: (collection: string, id: string) => Promise<MaterializedRecord | null>\n}\n\n/** Result of {@link ServerStore.applyConditional}. */\nexport interface ConditionalApplyResult {\n\t/** True when the predicate held (or the set was already committed). */\n\tadmitted: boolean\n\t/** True when the idempotency key already existed and nothing was re-applied. */\n\tidempotent: boolean\n\t/** The operations that were applied (empty when not admitted or idempotent). */\n\tapplied: Operation[]\n}\n\n/**\n * A stored operation paired with its server-assigned delivery sequence. The\n * delivery sequence is monotonic in commit order, so a batch of these can be\n * chained (each batch's base links to the previous batch's max) to give the\n * client a gap-free, scope-agnostic recovery stream.\n */\nexport interface DeliveredOperation {\n\toperation: Operation\n\tdeliverySequence: number\n\t/**\n\t * The record's scope-relevant values around this operation, captured from the\n\t * server's own rows when it was applied (RT-14, RT-15). Absent (or null) for\n\t * operations stored before snapshots existed that could not be backfilled.\n\t */\n\tscopeSnapshot?: OperationScopeSnapshot | null\n}\n\n/**\n * Scope-relevant field values of a record, captured by the store from its own rows\n * when an operation is applied (never from the writer's `previousData`). Download\n * visibility of a historical operation is judged on `post`, so a later ownership\n * transfer does not disclose the record's earlier history to the new owner (RT-14),\n * and a scope exit is judged from `pre` to `post` (RT-15).\n *\n * Only scalar fields (string, number, boolean, enum, timestamp) and `id` are kept:\n * scope predicates compare with `Object.is`, so other kinds can never match. A\n * string longer than {@link MAX_SCOPE_SNAPSHOT_STRING_LENGTH} is left out (fails\n * closed for a scope on such a field) so a snapshot never copies large text.\n */\nexport interface OperationScopeSnapshot {\n\t/** Values before the operation; null when the record did not exist or was deleted. */\n\tpre: Record<string, unknown> | null\n\t/** Values after it; a delete keeps the record's last values; null when unknown. */\n\tpost: Record<string, unknown> | null\n}\n\n/** Longest string value copied into an {@link OperationScopeSnapshot}. */\nexport const MAX_SCOPE_SNAPSHOT_STRING_LENGTH = 512\n\n/**\n * Options for querying a materialized collection table.\n */\nexport interface CollectionQueryOptions {\n\t/** Exact-match filters on field values */\n\twhere?: Record<string, unknown>\n\t/** Field name to order results by */\n\torderBy?: string\n\t/** Sort direction (default: 'asc') */\n\torderDirection?: 'asc' | 'desc'\n\t/** Maximum number of records to return */\n\tlimit?: number\n\t/** Number of records to skip (for pagination) */\n\toffset?: number\n\t/** Include soft-deleted records (default: false) */\n\tincludeDeleted?: boolean\n}\n\n/**\n * Options for {@link ServerStore.applyRemoteOperation}.\n */\nexport interface ApplyRemoteOptions {\n\t/**\n\t * Authorization re-check for an operation submitted by an untrusted writer.\n\t *\n\t * The store calls it inside its apply critical section (the SQLite write\n\t * transaction, the in-memory store's synchronous apply, or a Postgres\n\t * transaction holding the per-record advisory lock shared with conditional\n\t * applies) with the record as stored at that moment, including a soft-deleted\n\t * one, or null when none exists. Returning a refusal aborts the apply and the\n\t * store throws {@link UplinkAuthorizationError}; nothing is written.\n\t *\n\t * This closes the window between a caller's own pre-check and the write, where an\n\t * ownership change or a same-id insert committed by another writer (or another\n\t * server instance) could otherwise slip in.\n\t */\n\tauthorize?: (storedRow: MaterializedRecord | null) => UplinkAuthorizationResult\n\t/**\n\t * The writer does not reserve its sequence numbers inside the write transaction\n\t * (a client that did not advertise the `sequenceReservation` handshake capability,\n\t * Kora <= beta.12; RT-37). A different operation already holding the\n\t * `(nodeId, sequenceNumber)` then does not refuse this one: both are stored as a\n\t * legacy pair (each keeps its own delivery sequence, so both are delivered) instead\n\t * of throwing {@link SequenceConflictError}. Default false: enforce.\n\t */\n\tlegacySequenceWriter?: boolean\n\t/**\n\t * Called once the operation was committed as the second holder of its sequence (a\n\t * legacy pair), for logging and diagnostics. Never called for a refused write.\n\t */\n\tonLegacySequencePair?: (pair: LegacySequencePair) => void\n}\n\n/** Options of {@link ServerStore.setSchema}. */\nexport interface ServerSchemaOptions {\n\t/** Schema transforms the store folds with (transforms at fold time, RT-84). */\n\toperationTransforms?: readonly OperationTransform[]\n}\n\n/** One stored end-to-end key record (opaque JSON) and its owner, as backups carry it. */\nexport interface EncryptionKeyRecordRow {\n\towner: string\n\tkeyring: string\n\trevision: number\n\t/** The record's JSON, exactly as stored. */\n\trecord: string\n}\n\n/**\n * Server-side store interface. Extends SyncStore with lifecycle,\n * introspection, and materialization methods needed by the sync server.\n */\nexport interface ServerStore extends SyncStore {\n\t/**\n\t * Apply an operation to the log and materialized state. With\n\t * `options.authorize`, the authorization is re-checked atomically with the write\n\t * (see {@link ApplyRemoteOptions}). Stores written before this option existed\n\t * may ignore it; callers always pre-check as well.\n\t *\n\t * Built-in stores throw {@link SequenceConflictError} when a different operation\n\t * already holds the operation's `(nodeId, sequenceNumber)` under enforcement\n\t * (unless `options.legacySequenceWriter`, see {@link judgeSequenceHolders}), and return\n\t * `'duplicate'` (writing nothing) for an operation id already stored, decided\n\t * atomically with the write.\n\t */\n\tapplyRemoteOperation(op: Operation, options?: ApplyRemoteOptions): Promise<ApplyResult>\n\n\t/**\n\t * The version vector as committed in the shared database, read fresh (SRV-4). A\n\t * store shared by several server instances must implement it: its synchronous\n\t * {@link SyncStore.getVersionVector} can only reflect this instance's own writes.\n\t * Optional; callers fall back to `getVersionVector()`.\n\t */\n\treadVersionVector?(): Promise<VersionVector>\n\n\t/**\n\t * Several records of one collection by id, as stored (soft-deleted ones included),\n\t * in one read: `id = ANY(...)` on Postgres, chunked `IN (...)` on SQLite (LMS #11).\n\t * Ids with no row are absent from the result. Optional; the delivery stream falls\n\t * back to one lookup per operation without it.\n\t */\n\tfindRecordsByIds?(collection: string, ids: string[]): Promise<Map<string, MaterializedRecord>>\n\n\t/**\n\t * Which of `ids` the operation log already holds, with the node and sequence each is\n\t * stored under, in one read per batch (chunked `IN (...)`). The sync session asks before any other per-operation check, so a\n\t * device re-uploading history the server already stores (the one-time upgrade\n\t * re-upload, or an op the client's sequence repair renumbered under its original\n\t * id) is acknowledged as a duplicate instead of being re-judged by today's\n\t * authorization and validators. Optional; sessions fall back to a per-operation\n\t * (node, sequence) lookup without it.\n\t */\n\tfindStoredOperations?(ids: string[]): Promise<Map<string, StoredOperationKey>>\n\n\t/**\n\t * Durably record how an uploaded operation was resolved without being stored under\n\t * its sequence (RT-43, RT-47; see {@link OperationResolution}). Idempotent per\n\t * operation id: the first resolution wins. The session awaits it BEFORE answering the\n\t * client, so a client never acts on a resolution the server could forget. Optional\n\t * for custom stores: without it an ignored tail op may be re-validated at reconnect\n\t * and a refused id re-judged on resubmission.\n\t */\n\trecordOperationResolution?(resolution: OperationResolution): Promise<void>\n\n\t/**\n\t * The resolutions recorded for `ids` under `nodeId` (ids resolved under another node\n\t * are absent: the answer never crosses devices or tenants).\n\t */\n\tfindOperationResolutions?(\n\t\tnodeId: string,\n\t\tids: string[],\n\t): Promise<Map<string, OperationResolution>>\n\n\t/** The highest sequence number of `nodeId` with a recorded resolution (0 when none). */\n\tgetResolvedThrough?(nodeId: string): Promise<number>\n\n\t/**\n\t * Forget the resolution recorded for `operationId` under `nodeId` (no-op when none).\n\t * The session calls it for a stale `stored-elsewhere` record: one whose id the batch\n\t * lookup did not find stored (RT-51). The operation is then judged normally, and its\n\t * real outcome is recorded in place of the stale one. Optional for custom stores:\n\t * without it the stale record is ignored but kept.\n\t */\n\tdeleteOperationResolution?(nodeId: string, operationId: string): Promise<void>\n\n\t/**\n\t * Every operation of `nodeId` at or below `throughSequence` that shares its sequence\n\t * with another stored operation (a legacy pair, RT-37), ordered by sequence then\n\t * delivery. A version-vector client reporting `throughSequence` for the node may hold\n\t * only one of a pair, and a range read above its entry can never return the other\n\t * (RT-48). Optional; without it such clients miss the second op of a pair.\n\t */\n\tgetSequencePairOperations?(nodeId: string, throughSequence: number): Promise<Operation[]>\n\n\t/**\n\t * The distinct node ids of the operations with `deliverySequence >\n\t * afterDeliverySequence`. Optional; lets a handshake stop judging which nodes a\n\t * scoped client will hear from as soon as every candidate was found visible.\n\t */\n\tgetNodeIdsAfterDelivery?(afterDeliverySequence: number): Promise<string[]>\n\n\t/**\n\t * Bind a client node id to the authenticated principal that first used it.\n\t * Returns true when the node id is already owned by `userId`, was released by an\n\t * admin (see {@link releaseNodeClaim}; the caller takes it over), or is unclaimed\n\t * AND has no operation history. Returns false when another principal owns it, or\n\t * when it is unclaimed but already has operations in the log: history written\n\t * before node claims existed has no recorded writer, so nobody may adopt it\n\t * until an admin releases it (RT-5). Called at handshake when auth is configured,\n\t * so one user cannot upload operations under another user's device id. Every\n\t * write after this check is preceded by a claim, so going forward the claim row\n\t * records the writer of a node's history. Must be atomic per node id. Optional\n\t * for custom stores; the built-in stores persist the claim.\n\t */\n\tclaimNode?(nodeId: string, userId: string): Promise<boolean>\n\t/**\n\t * Admin release of a node id (RT-5): the next principal to claim it takes it\n\t * over, even when the node has operation history. Returns true when the node had\n\t * a claim or history to release, false when it was unknown.\n\t */\n\treleaseNodeClaim?(nodeId: string): Promise<boolean>\n\t/**\n\t * The owner a node id is currently claimed by, or null when unclaimed (RT-21).\n\t * Optional; anonymous provisional claims need it together with\n\t * {@link replaceNodeClaim}.\n\t */\n\tgetNodeClaimOwner?(nodeId: string): Promise<string | null>\n\t/**\n\t * Atomically replace the owner of a node claim, only if it is still\n\t * `expectedOwner` (compare-and-set, RT-21). Returns true when replaced. Used to\n\t * confirm or re-issue an anonymous device's provisional claim; never creates one.\n\t */\n\treplaceNodeClaim?(nodeId: string, expectedOwner: string, newOwner: string): Promise<boolean>\n\t/**\n\t * The wrapped encryption key record (JSON) of one owner's keyring, or null (ENC-1).\n\t * The record holds only salt, KDF parameters and wrapped keys: never a usable key.\n\t * Optional for custom stores; without it the server answers key requests with\n\t * `unsupported` (it never keeps key records in memory only, which would fork a\n\t * user's keys after a restart).\n\t */\n\tgetEncryptionKeyRecord?(owner: string, keyring: string): Promise<string | null>\n\t/**\n\t * Write a key record with compare-and-set: store `record` at `revision` only when the\n\t * stored revision is `expectedRevision` (0: no record yet). Returns false when\n\t * another write won. Must be atomic per (owner, keyring) across server instances.\n\t */\n\tputEncryptionKeyRecord?(\n\t\towner: string,\n\t\tkeyring: string,\n\t\trecord: string,\n\t\trevision: number,\n\t\texpectedRevision: number,\n\t): Promise<boolean>\n\t/**\n\t * Stored key records: every one (for `exportBackup`; RT-104: a server restored from\n\t * its backup must still hold the records its encrypted history needs), or one owner's\n\t * (the key service tells another keyring's history from a lost record with it).\n\t * Optional.\n\t */\n\tlistEncryptionKeyRecords?(owner?: string): Promise<EncryptionKeyRecordRow[]>\n\t/**\n\t * Key ids named by stored encrypted operations (their envelope's `keyId`), a sample\n\t * of at most `limit` distinct ids (RT-104). `nodeOwner` restricts it to operations of\n\t * nodes claimed by that principal (see {@link claimNode}); null means every node (a\n\t * server without authentication, whose clients share one keyring). The key service\n\t * reports them when an owner has no key record, so a new device can tell a lost\n\t * record (encrypted history exists) from a first one. Optional; without it a new\n\t * device cannot tell, and a fork it creates is merged later by a device holding the\n\t * old ring.\n\t */\n\tgetEncryptedKeyIds?(nodeOwner: string | null, limit: number): Promise<string[]>\n\t/**\n\t * Record that `owner` holds the bytes behind a blob content hash (it pushed them,\n\t * proving possession) (RT-11). Idempotent. Optional; without it the sync server\n\t * keeps ownership in memory (lost on restart, not shared between instances).\n\t */\n\trecordBlobOwner?(hash: string, owner: string): Promise<void>\n\t/** The owners recorded for each hash (an empty list for unowned hashes). */\n\tgetBlobOwners?(hashes: string[]): Promise<Map<string, string[]>>\n\t/**\n\t * Atomically make `owner` the first owner of a hash nobody owns yet. Returns true\n\t * when `owner` owns the hash afterwards (newly, or already), false when someone\n\t * else does. Must be atomic per hash across server instances.\n\t */\n\tclaimBlobIfUnowned?(hash: string, owner: string): Promise<boolean>\n\t/**\n\t * The scope snapshots captured when the given operations were applied (RT-14).\n\t * Operations without one are absent from the result.\n\t */\n\tgetOperationScopeSnapshots?(operationIds: string[]): Promise<Map<string, OperationScopeSnapshot>>\n\t/**\n\t * The greatest HLC timestamp among every stored operation of one record (its\n\t * newest field write), or null when the record has no operations (RT-19). A\n\t * scope-entry operation is stamped with it so it never overrides newer client data.\n\t */\n\tgetRecordLatestTimestamp?(collection: string, recordId: string): Promise<HLCTimestamp | null>\n\t/**\n\t * Per-field versions of one live record, folded from its stored operations exactly\n\t * as the materialization folds its values (RT-27): each field's version is the HLC\n\t * of the write that produced its current value, plus the record's first and newest\n\t * operation. Null when the record is deleted or has no operations. A scope-entry\n\t * operation carries them so a receiver resolves every field on its own.\n\t */\n\tgetRecordFieldVersions?(collection: string, recordId: string): Promise<RecordFieldVersions | null>\n\t/**\n\t * The record's fold state (W7): the per-field CRDT state its row is projected from.\n\t * Null when the record has no operations or its collection is not materialized. A\n\t * scope-entry operation carries it (filtered to the fields the receiver may see) so\n\t * the receiver merges richtext, counter and resolver fields exactly (RT-29).\n\t */\n\tgetRecordFoldState?(collection: string, recordId: string): Promise<FoldState | null>\n\t/** Every stored operation of one record, in delivery (commit) order. */\n\tgetRecordOperations?(collection: string, recordId: string): Promise<Operation[]>\n\t/**\n\t * The record's row as it would be after merging `op` into its fold state, with\n\t * nothing written: the candidate a Tier-2 constraint check judges at ingest. Null\n\t * when the record would not be live (deleted, or never inserted).\n\t */\n\tpreviewOperation?(op: Operation): Promise<MaterializedRecord | null>\n\t/**\n\t * Node ids whose operations win `merge('server-authoritative')` fields in the fold:\n\t * this store's own node id (every server-originated operation is authored by it)\n\t * plus any configured extras. The sync server advertises them in the handshake so\n\t * clients fold with the same authority.\n\t */\n\tgetAuthoritativeNodeIds?(): string[]\n\n\t/** Explicit authoritative ids the deployment revoked (RT-81); advertised at handshake. */\n\tgetRevokedAuthoritativeNodeIds?(): string[]\n\n\t/**\n\t * Every explicit id the deployment ever held authoritative, revoked ones included\n\t * (RT-81). The session never accepts one as a device node id.\n\t */\n\tgetEverAuthoritativeNodeIds?(): string[]\n\t/**\n\t * Keyed id of a server-derived operation (cascade, set-null, constraint correction):\n\t * deterministic across every instance of the deployment, unpredictable to clients\n\t * (RT-64). Built-in stores key it with a persisted deployment secret. A store\n\t * without it falls back to the unkeyed `deriveSideEffectOpId`.\n\t */\n\tderiveServerOperationId?(\n\t\tparentOpId: string,\n\t\truleId: string,\n\t\ttargetRecordId: string,\n\t): Promise<string>\n\t/** Close the store and release resources */\n\tclose(): Promise<void>\n\n\t/** Get the total number of stored operations */\n\tgetOperationCount(): Promise<number>\n\n\t/**\n\t * The highest delivery sequence currently visible in the store (0 when empty).\n\t * Used to initialize a fresh client's watermark baseline and for diagnostics.\n\t */\n\tgetMaxDeliverySequence(): Promise<number>\n\n\t/**\n\t * Operations with `deliverySequence > afterDeliverySequence`, ordered ascending\n\t * by delivery sequence, at most `limit` of them. This is the substrate for the\n\t * gap-free server->client stream: the caller (a client session) applies its own\n\t * scope filter and chains the results into batches, advancing the client's\n\t * durable watermark as batches are acknowledged. Because delivery sequence is\n\t * assigned in commit order, a lower sequence is always visible before any higher\n\t * one, so this scan can never skip an operation that later appears below the\n\t * cursor.\n\t */\n\tgetOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]>\n\n\t/**\n\t * Conditionally apply a set of operations atomically, serialized across server\n\t * instances on the target record. Optional: stores that can only run in a single\n\t * process (or do not back a shared database) may omit it, and callers fall back\n\t * to per-instance serialization. The Postgres store implements it with a\n\t * transaction-scoped advisory lock so concurrent admissions cannot both pass a\n\t * cap check (`applyConditional` returns `admitted: false` for the loser).\n\t */\n\tapplyConditional?(input: ConditionalApplyInput): Promise<ConditionalApplyResult>\n\n\t/**\n\t * Atomically reserve the next sequence number for a server-originated operation\n\t * on this store's own node. Stores that serve conditional applies concurrently\n\t * (the Postgres store, which does not serialize behind a single mutation tail)\n\t * must implement this so two in-flight server operations cannot be handed the\n\t * same sequence number, which would let one shadow the other during version-vector\n\t * delta sync. Stores whose server writes are fully serialized may omit it, and\n\t * callers fall back to reading the version vector.\n\t */\n\treserveSequenceNumber?(): number\n\n\t/**\n\t * Set the schema for materialized collection tables.\n\t * Creates collection tables and indexes based on the schema definition.\n\t * If operations already exist in the store, backfills the materialized\n\t * tables from the operation log.\n\t *\n\t * @param schema - The schema definition describing all collections\n\t * @param options - `operationTransforms`: the schema transforms the store folds with\n\t * (transforms at fold time, RT-84). Pass the same list as the sync server's\n\t * `operationTransforms`, so the startup re-materialization folds with them once.\n\t */\n\tsetSchema(schema: SchemaDefinition, options?: ServerSchemaOptions): Promise<void>\n\n\t/** Schema used for materialized tables and server-side validation, if set. */\n\tgetSchema(): SchemaDefinition | null\n\n\t/**\n\t * Set the schema transforms the store folds with (RT-84). Operations are stored\n\t * exactly as uploaded; the fold merges each operation as\n\t * `operationSchemaView(op, schema.version, transforms)` reads it. Transforms are part\n\t * of the fold plan fingerprint: a change re-folds every record (once). The sync\n\t * server calls this with its `operationTransforms` at construction.\n\t */\n\tsetOperationTransforms?(transforms: readonly OperationTransform[]): Promise<void>\n\n\t/** The schema transforms the store folds with (empty when none). */\n\tgetOperationTransforms?(): readonly OperationTransform[]\n\n\t/**\n\t * Get all records from a materialized collection.\n\t * When schema is set, reads directly from the collection table (O(1) indexed).\n\t * When schema is not set, falls back to replaying the operation log.\n\t * Deleted records are excluded.\n\t *\n\t * @param collection - The collection name to query\n\t * @returns Array of records with their current state\n\t */\n\tmaterializeCollection(collection: string): Promise<MaterializedRecord[]>\n\n\t/**\n\t * Query records from a materialized collection with filtering, ordering,\n\t * and pagination. Requires schema to be set via setSchema().\n\t *\n\t * @param collection - The collection name to query\n\t * @param options - Query options (where, orderBy, limit, offset)\n\t * @returns Array of matching records\n\t */\n\tqueryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]>\n\n\t/**\n\t * Find a single record by ID from a materialized collection.\n\t * Requires schema to be set via setSchema().\n\t *\n\t * @param collection - The collection name\n\t * @param id - The record ID\n\t * @returns The record or null if not found (or deleted)\n\t */\n\tfindRecord(collection: string, id: string): Promise<MaterializedRecord | null>\n\n\t/**\n\t * Count records in a materialized collection, optionally filtered.\n\t * Requires schema to be set via setSchema().\n\t *\n\t * @param collection - The collection name\n\t * @param where - Optional exact-match filters\n\t * @returns Number of matching records\n\t */\n\tcountCollection(collection: string, where?: Record<string, unknown>): Promise<number>\n\n\t/**\n\t * Export all data as a portable backup binary.\n\t * Ships operations, version vector, and metadata in a self-describing format\n\t * with SHA-256 checksum.\n\t */\n\texportBackup(): Promise<Uint8Array>\n\n\t/**\n\t * Restore data from a portable backup binary.\n\t * Operations are applied through applyRemoteOperation for safe merge.\n\t *\n\t * @param data - Backup binary\n\t * @param merge - If true, merge with existing operations; if false, replace all\n\t */\n\timportBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }>\n}\n","import { MAX_LOGICAL } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\n\n/** Max allowed future skew for operation timestamps at server ingest (1 minute). */\nexport const SERVER_MAX_TIMESTAMP_FUTURE_MS = 60_000\n\n/**\n * Returns false when an operation's HLC timestamp is structurally invalid or\n * unreasonably far in the future.\n *\n * Structural checks matter because operations are content-addressed and\n * immutable: a timestamp with a non-integer/negative field or a logical\n * counter past the 5-digit serialization cap would poison the shared log\n * forever (its serialized form no longer sorts like HybridLogicalClock.compare),\n * so it must never be accepted at ingest.\n */\nexport function isOperationTimestampValid(op: Operation, now: number = Date.now()): boolean {\n\tconst { wallTime, logical } = op.timestamp\n\tif (!Number.isInteger(wallTime) || wallTime < 0) {\n\t\treturn false\n\t}\n\tif (!Number.isInteger(logical) || logical < 0 || logical > MAX_LOGICAL) {\n\t\treturn false\n\t}\n\treturn wallTime <= now + SERVER_MAX_TIMESTAMP_FUTURE_MS\n}\n","import type { Operation } from '@korajs/core'\nimport { KoraError } from '@korajs/core'\nimport {\n\tSERVER_MAX_TIMESTAMP_FUTURE_MS,\n\tisOperationTimestampValid,\n} from '../session/operation-validation'\n\n/** Rejection code for an operation stamped too far ahead of server time (SYNC-7). */\nexport const INVALID_TIMESTAMP_CODE = 'INVALID_TIMESTAMP'\n/** Rejection code for a sequence number that is not a safe positive integer (SRV-4). */\nexport const INVALID_SEQUENCE_NUMBER_CODE = 'INVALID_SEQUENCE_NUMBER'\n\n/**\n * Rejection code for an identifier (operation id, node id, collection, record id,\n * causal dependency) holding U+0000 or a lone UTF-16 surrogate (RT-65).\n */\nexport const INVALID_IDENTIFIER_CODE = 'INVALID_IDENTIFIER'\n\n/** Result of {@link validateIngestedOperation}. */\nexport type IngestValidationResult =\n\t| { valid: true }\n\t| {\n\t\t\tvalid: false\n\t\t\tcode:\n\t\t\t\t| typeof INVALID_TIMESTAMP_CODE\n\t\t\t\t| typeof INVALID_SEQUENCE_NUMBER_CODE\n\t\t\t\t| typeof INVALID_IDENTIFIER_CODE\n\t\t\tmessage: string\n\t }\n\n// NUL, or a high surrogate not followed by a low one, or a low surrogate not preceded by a high one.\nconst UNSTORABLE_IDENTIFIER =\n\t// biome-ignore lint/suspicious/noControlCharactersInRegex: U+0000 is exactly what identifiers may not hold (RT-65)\n\t/\\u0000|[\\ud800-\\udbff](?![\\udc00-\\udfff])|(?<![\\ud800-\\udbff])[\\udc00-\\udfff]/\n\n/**\n * True for a string every store can hold as an identifier: no U+0000 (Postgres TEXT\n * refuses it) and no lone surrogate (UTF-8 cannot encode it). Data values may hold\n * both (they are encoded losslessly); identifiers are keys, compared and indexed raw.\n */\nexport function isStorableIdentifier(value: unknown): value is string {\n\treturn typeof value === 'string' && !UNSTORABLE_IDENTIFIER.test(value)\n}\n\n/**\n * True when `sequenceNumber` can identify a node's write: a positive integer no larger\n * than `Number.MAX_SAFE_INTEGER` (beyond it, two numbers collapse into one double).\n */\nexport function isValidSequenceNumber(sequenceNumber: unknown): sequenceNumber is number {\n\treturn (\n\t\ttypeof sequenceNumber === 'number' &&\n\t\tNumber.isSafeInteger(sequenceNumber) &&\n\t\tsequenceNumber >= 1\n\t)\n}\n\n/**\n * The checks every path that brings an operation INTO the server's log runs (sync\n * ingest, route `kora.apply`, `applyLocalOperation`, backup import): identifiers are\n * well-formed strings (RT-65), the HLC\n * timestamp is well formed and not more than {@link SERVER_MAX_TIMESTAMP_FUTURE_MS}\n * ahead of the server's clock, and the sequence number is a safe positive integer.\n *\n * A far-future operation that got in would make every receiver's HLC jump (or refuse\n * it), and every later local edit would lose to it until real time caught up (SYNC-7),\n * so it is stopped at the server, where time is trusted.\n *\n * @param op - The operation entering the log\n * @param now - The server's current time in ms (injectable for tests)\n */\nexport function validateIngestedOperation(\n\top: Operation,\n\tnow: number = Date.now(),\n): IngestValidationResult {\n\tconst identifiers: unknown[] = [\n\t\top.id,\n\t\top.nodeId,\n\t\top.collection,\n\t\top.recordId,\n\t\top.timestamp?.nodeId,\n\t\t...(Array.isArray(op.causalDeps) ? op.causalDeps : []),\n\t]\n\tif (!identifiers.every(isStorableIdentifier)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: INVALID_IDENTIFIER_CODE,\n\t\t\tmessage: `Operation \"${String(op.id)}\" has an identifier (id, node id, collection, record id or causal dependency) that is not a string or holds U+0000 or an unpaired UTF-16 surrogate. Identifiers must be well-formed strings.`,\n\t\t}\n\t}\n\tif (!isValidSequenceNumber(op.sequenceNumber)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: INVALID_SEQUENCE_NUMBER_CODE,\n\t\t\tmessage: `Operation \"${op.id}\" has sequence number ${String(op.sequenceNumber)}; sequence numbers are positive integers no larger than ${String(Number.MAX_SAFE_INTEGER)}.`,\n\t\t}\n\t}\n\tif (\n\t\ttypeof op.timestamp !== 'object' ||\n\t\top.timestamp === null ||\n\t\t!isOperationTimestampValid(op, now)\n\t) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: INVALID_TIMESTAMP_CODE,\n\t\t\tmessage: `Operation \"${op.id}\" has an invalid timestamp or one more than ${String(SERVER_MAX_TIMESTAMP_FUTURE_MS)} ms ahead of server time. Check the clock of the device or server that wrote it.`,\n\t\t}\n\t}\n\treturn { valid: true }\n}\n\n/**\n * Thrown by a backup import whose operations fail {@link validateIngestedOperation}.\n * Nothing is restored: a backup is all-or-nothing, so a far-future (or malformed)\n * operation is reported instead of silently dropped or silently restored.\n */\nexport class BackupValidationError extends KoraError {\n\tconstructor(\n\t\treadonly invalidOperations: Array<{ operationId: string; code: string }>,\n\t\treadonly totalOperations: number,\n\t) {\n\t\tsuper(\n\t\t\t`Backup rejected: ${String(invalidOperations.length)} of ${String(totalOperations)} operations failed ingest validation (first: \"${invalidOperations[0]?.operationId ?? ''}\", ${invalidOperations[0]?.code ?? ''}). A far-future timestamp usually means the exporting server's clock was wrong; fix the clock and re-export, or repair the operations before restoring.`,\n\t\t\t'BACKUP_INVALID_OPERATION',\n\t\t\t{\n\t\t\t\tinvalidCount: invalidOperations.length,\n\t\t\t\ttotalOperations,\n\t\t\t\tsample: invalidOperations.slice(0, 10),\n\t\t\t},\n\t\t)\n\t\tthis.name = 'BackupValidationError'\n\t}\n}\n\n/**\n * Validate every operation of a backup against server time before anything is\n * restored. Throws {@link BackupValidationError} listing the offenders.\n */\nexport function assertBackupOperationsIngestible(\n\toperations: Operation[],\n\tnow: number = Date.now(),\n): void {\n\tconst invalid: Array<{ operationId: string; code: string }> = []\n\tfor (const op of operations) {\n\t\tconst result = validateIngestedOperation(op, now)\n\t\tif (!result.valid) invalid.push({ operationId: String(op.id), code: result.code })\n\t}\n\tif (invalid.length > 0) throw new BackupValidationError(invalid, operations.length)\n}\n","import type { Operation } from '@korajs/core'\nimport { KoraError } from '@korajs/core'\nimport type { WrappedKeyRecord } from '@korajs/sync'\nimport { isKeyRecordSuccessor, validateKeyRecord } from '@korajs/sync'\nimport { assertBackupOperationsIngestible } from '../apply/ingest-validation'\nimport type { EncryptionKeyRecordRow, ServerStore } from './server-store'\nimport { SequenceConflictError } from './server-store'\n\n/**\n * Server-side backup format: same portable section-based format as the client.\n *\n * Sections:\n * manifest — metadata (version, nodeId, operationCount, checksum)\n * version_vector — nodeId → maxSequenceNumber\n * operations — NDJSON of full Operation objects\n * encryption_keys — JSON array of the stored end-to-end key records (optional; RT-104)\n * checksum — SHA-256 of all content sections\n *\n * A reader that predates `encryption_keys` ignores it. Without it, a server restored\n * from its backup would hold encrypted history but no key record to open it with.\n */\n\nconst BACKUP_VERSION = 1\n\nfunction encodeSection(name: string, content: Uint8Array): Uint8Array {\n\tconst nameBytes = new TextEncoder().encode(name)\n\tconst header = new Uint8Array(8)\n\tconst dv = new DataView(header.buffer)\n\tdv.setUint32(0, nameBytes.length, true)\n\tdv.setUint32(4, content.length, true)\n\n\tconst result = new Uint8Array(header.length + nameBytes.length + content.length)\n\tresult.set(header, 0)\n\tresult.set(nameBytes, 8)\n\tresult.set(content, 8 + nameBytes.length)\n\treturn result\n}\n\nfunction encodeJsonSection(name: string, data: unknown): Uint8Array {\n\treturn encodeSection(name, new TextEncoder().encode(JSON.stringify(data)))\n}\n\ninterface Section {\n\tname: string\n\tcontent: Uint8Array\n}\n\nfunction parseSections(data: Uint8Array): Section[] {\n\tconst sections: Section[] = []\n\tconst dv = new DataView(data.buffer, data.byteOffset, data.byteLength)\n\tlet offset = 0\n\n\twhile (offset + 8 <= data.byteLength) {\n\t\tconst nameLen = dv.getUint32(offset, true)\n\t\tconst contentLen = dv.getUint32(offset + 4, true)\n\t\toffset += 8\n\n\t\tif (offset + nameLen + contentLen > data.byteLength) break\n\n\t\tconst name = new TextDecoder().decode(data.slice(offset, offset + nameLen))\n\t\toffset += nameLen\n\n\t\tconst content = data.slice(offset, offset + contentLen)\n\t\toffset += contentLen\n\n\t\tsections.push({ name, content })\n\t}\n\n\treturn sections\n}\n\nfunction findSection(sections: Section[], name: string): Uint8Array | null {\n\tfor (const s of sections) {\n\t\tif (s.name === name) return s.content\n\t}\n\treturn null\n}\n\nfunction parseJsonSection<T>(sections: Section[], name: string): T | null {\n\tconst content = findSection(sections, name)\n\tif (!content) return null\n\treturn JSON.parse(new TextDecoder().decode(content)) as T\n}\n\nasync function computeSha256(data: Uint8Array): Promise<string> {\n\tconst digestInput = new Uint8Array(data)\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', digestInput)\n\tconst hashArray = Array.from(new Uint8Array(hashBuffer))\n\treturn hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/**\n * Build a backup binary from server store data.\n */\nexport async function buildServerBackup(\n\tnodeId: string,\n\toperations: Operation[],\n\tversionVector: Map<string, number>,\n\tkeyRecords: EncryptionKeyRecordRow[] = [],\n): Promise<Uint8Array> {\n\tconst sections: Uint8Array[] = []\n\tlet allContentForChecksum = new Uint8Array(0)\n\n\tconst addSection = (name: string, data: Uint8Array) => {\n\t\tsections.push(data)\n\t\tconst newLen = allContentForChecksum.length + data.length\n\t\tconst combined = new Uint8Array(newLen)\n\t\tcombined.set(allContentForChecksum, 0)\n\t\tcombined.set(data, allContentForChecksum.length)\n\t\tallContentForChecksum = combined\n\t}\n\n\t// Version vector\n\tconst vvObj: Record<string, number> = {}\n\tfor (const [nid, seq] of versionVector) {\n\t\tvvObj[nid] = seq\n\t}\n\taddSection('version_vector', encodeJsonSection('version_vector', vvObj))\n\n\t// Operations\n\tconst opLines = `${operations.map((op) => JSON.stringify(op)).join('\\n')}\\n`\n\taddSection('operations', encodeSection('operations', new TextEncoder().encode(opLines)))\n\n\t// End-to-end key records (opaque: the server cannot open them)\n\tif (keyRecords.length > 0) {\n\t\taddSection('encryption_keys', encodeJsonSection('encryption_keys', keyRecords))\n\t}\n\n\t// Checksum\n\tconst checksumHex = await computeSha256(allContentForChecksum)\n\n\t// Manifest\n\tconst manifest = {\n\t\tversion: BACKUP_VERSION,\n\t\tcreatedAt: Date.now(),\n\t\tnodeId,\n\t\tschemaVersion: 1,\n\t\toperationCount: operations.length,\n\t\tcollections: [] as string[],\n\t\tincludesRecords: false,\n\t\tencryptionKeyRecordCount: keyRecords.length,\n\t\tchecksum: checksumHex,\n\t}\n\n\tconst manifestSection = encodeJsonSection('manifest', manifest)\n\tconst checksumSection = encodeSection('checksum', new TextEncoder().encode(checksumHex))\n\n\tconst totalLen = manifestSection.length + allContentForChecksum.length + checksumSection.length\n\tconst result = new Uint8Array(totalLen)\n\tlet pos = 0\n\tresult.set(manifestSection, pos)\n\tpos += manifestSection.length\n\tresult.set(allContentForChecksum, pos)\n\tpos += allContentForChecksum.length\n\tresult.set(checksumSection, pos)\n\n\treturn result\n}\n\n/**\n * Parse a backup and return the operations, version vector and key records.\n */\nexport function parseServerBackup(data: Uint8Array): {\n\toperations: Operation[]\n\tversionVector: Map<string, number>\n\tkeyRecords: EncryptionKeyRecordRow[]\n} {\n\tconst sections = parseSections(data)\n\n\t// Parse operations\n\tconst opsContent = findSection(sections, 'operations')\n\tlet operations: Operation[] = []\n\tif (opsContent) {\n\t\tconst text = new TextDecoder().decode(opsContent)\n\t\tconst lines = text\n\t\t\t.trim()\n\t\t\t.split('\\n')\n\t\t\t.filter((l) => l.length > 0)\n\t\toperations = lines.map((line) => JSON.parse(line) as Operation)\n\t}\n\n\t// Parse version vector\n\tconst vvData = parseJsonSection<Record<string, number>>(sections, 'version_vector')\n\tconst versionVector = new Map<string, number>()\n\tif (vvData) {\n\t\tfor (const [nid, seq] of Object.entries(vvData)) {\n\t\t\tversionVector.set(nid, seq)\n\t\t}\n\t}\n\n\t// Every ingest path validates against server time (SYNC-7): a backup whose\n\t// operations are far-future or malformed is refused whole, before anything changes.\n\tassertBackupOperationsIngestible(operations)\n\tconst keyRecords = parseKeyRecords(parseJsonSection<unknown>(sections, 'encryption_keys'))\n\n\treturn { operations, versionVector, keyRecords }\n}\n\n/** Validate the `encryption_keys` section: a malformed entry refuses the whole backup. */\nfunction parseKeyRecords(value: unknown): EncryptionKeyRecordRow[] {\n\tif (value === null || value === undefined) return []\n\tconst refuse = (reason: string): never => {\n\t\tthrow new KoraError(\n\t\t\t`Backup rejected: its encryption key records are malformed (${reason}).`,\n\t\t\t'BACKUP_INVALID_KEY_RECORD',\n\t\t\t{ reason },\n\t\t)\n\t}\n\tif (!Array.isArray(value)) return refuse('not an array')\n\treturn value.map((entry: unknown, index): EncryptionKeyRecordRow => {\n\t\tif (typeof entry !== 'object' || entry === null) return refuse(`entry ${index}`)\n\t\tconst { owner, keyring, revision, record } = entry as Record<string, unknown>\n\t\tif (typeof owner !== 'string' || typeof keyring !== 'string' || typeof record !== 'string') {\n\t\t\treturn refuse(`entry ${index} fields`)\n\t\t}\n\t\tlet parsed: unknown\n\t\ttry {\n\t\t\tparsed = JSON.parse(record)\n\t\t} catch {\n\t\t\treturn refuse(`entry ${index} record is not JSON`)\n\t\t}\n\t\tconst validation = validateKeyRecord(parsed, keyring)\n\t\tif (!validation.ok) return refuse(`entry ${index}: ${validation.reason}`)\n\t\tif ((parsed as { revision: unknown }).revision !== revision) {\n\t\t\treturn refuse(`entry ${index} revision does not match its record`)\n\t\t}\n\t\treturn { owner, keyring, revision: revision as number, record }\n\t})\n}\n\n/** Maximum compare-and-set attempts per restored key record (a live write may race it). */\nconst KEY_RESTORE_ATTEMPTS = 8\n\n/** The stored row of one (owner, keyring), with its ring id when the record is readable. */\nasync function readStoredKeyRecord(\n\tstore: Pick<ServerStore, 'getEncryptionKeyRecord' | 'listEncryptionKeyRecords'>,\n\towner: string,\n\tkeyring: string,\n): Promise<{ revision: number; record: WrappedKeyRecord | null } | null> {\n\tif (typeof store.listEncryptionKeyRecords === 'function') {\n\t\tconst rows = await store.listEncryptionKeyRecords(owner)\n\t\tconst row = rows.find((entry) => entry.owner === owner && entry.keyring === keyring)\n\t\tif (row === undefined) return null\n\t\treturn { revision: Number(row.revision), record: parseStoredRecord(row.record) }\n\t}\n\tconst json = await store.getEncryptionKeyRecord?.(owner, keyring)\n\tif (json === null || json === undefined) return null\n\tconst record = parseStoredRecord(json)\n\treturn { revision: record?.revision ?? 0, record }\n}\n\nfunction parseStoredRecord(json: string): WrappedKeyRecord | null {\n\ttry {\n\t\tconst parsed = JSON.parse(json) as WrappedKeyRecord\n\t\treturn typeof parsed === 'object' && parsed !== null ? parsed : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * What a restore does with one backed-up key record, given the stored one (RT-110).\n *\n * - **Replace mode**: the backup's record replaces the stored one, whatever its revision.\n * Replace mode makes the server what the backup was (an operator resetting a damaged\n * or tampered server); the key record the restored history was written under is the\n * backup's.\n * - **Merge mode**: an absent record is inserted. A stored record of the SAME ring is\n * advanced to the backup's only when the backup's is a valid successor (a higher\n * revision that keeps every key version and retired master). An equal or newer stored\n * revision is kept: it already holds every key the backup's does. A stored record of a\n * DIFFERENT ring is kept: the store holds one record per (owner, keyring), so that ring\n * was created after the loss; a device holding both rings merges them (KEY_RING_FORK).\n *\n * The server cannot check a record's MAC (only a holder of the ring's master key can),\n * so neither rule trusts the backup's record more than a device would: every device\n * authenticates a record before using it, refuses a revision below the one it pinned\n * (KEY_RECORD_ROLLBACK, and re-uploads its newer one), and refuses a record its keys do\n * not authenticate. A forged or rolled-back record in a backup can delay a device, never\n * make it adopt a key it did not authenticate.\n */\nfunction keyRestoreDecision(\n\tstored: { revision: number; record: WrappedKeyRecord | null } | null,\n\tincoming: EncryptionKeyRecordRow,\n\tmerge: boolean,\n): 'insert' | 'replace' | 'keep' {\n\tif (stored === null) return 'insert'\n\tif (!merge) {\n\t\treturn stored.revision === incoming.revision &&\n\t\t\tstored.record !== null &&\n\t\t\tJSON.stringify(stored.record) === JSON.stringify(JSON.parse(incoming.record))\n\t\t\t? 'keep'\n\t\t\t: 'replace'\n\t}\n\tif (stored.record === null) return 'replace'\n\tif (stored.record.ringId !== (JSON.parse(incoming.record) as WrappedKeyRecord).ringId) {\n\t\treturn 'keep'\n\t}\n\tif (incoming.revision <= stored.revision) return 'keep'\n\tconst successor = isKeyRecordSuccessor(\n\t\tstored.record,\n\t\tJSON.parse(incoming.record) as WrappedKeyRecord,\n\t)\n\tif (!successor.ok) {\n\t\tconsole.warn(\n\t\t\t`[kora] Backup merge: the key record of ${incoming.owner}/${incoming.keyring} in the backup (revision ${String(incoming.revision)}) is not a successor of the stored revision ${String(stored.revision)} (${successor.reason}); the stored record is kept.`,\n\t\t)\n\t\treturn 'keep'\n\t}\n\treturn 'replace'\n}\n\n/**\n * Restore backed-up key records (RT-104, RT-110) in either restore mode: the key table\n * is not part of the operation log, so it is reconciled record by record. See\n * {@link keyRestoreDecision} for the rules. Records the store holds that the backup does\n * not name are kept (a ring the backup never saw; removing it could only lose keys).\n *\n * @param merge - Merge-mode restore (true) or replace-mode restore (false)\n * @returns The number of records inserted or replaced\n */\nexport async function restoreBackupKeyRecords(\n\tstore: Pick<\n\t\tServerStore,\n\t\t'putEncryptionKeyRecord' | 'getEncryptionKeyRecord' | 'listEncryptionKeyRecords'\n\t>,\n\tkeyRecords: EncryptionKeyRecordRow[],\n\tmerge = true,\n): Promise<number> {\n\tif (keyRecords.length === 0) return 0\n\tif (typeof store.putEncryptionKeyRecord !== 'function') {\n\t\tconsole.warn(\n\t\t\t`[kora] Backup restore: ${String(keyRecords.length)} encryption key record(s) were not restored: this store has no key table.`,\n\t\t)\n\t\treturn 0\n\t}\n\tlet restored = 0\n\tfor (const row of keyRecords) {\n\t\tlet written = false\n\t\tfor (let attempt = 0; attempt < KEY_RESTORE_ATTEMPTS && !written; attempt++) {\n\t\t\tconst stored = await readStoredKeyRecord(store, row.owner, row.keyring)\n\t\t\tconst decision = keyRestoreDecision(stored, row, merge)\n\t\t\tif (decision === 'keep') break\n\t\t\t// Compare-and-set against the revision just read: a key write from a live device\n\t\t\t// in between makes it fail, and the record is decided again.\n\t\t\twritten = await store.putEncryptionKeyRecord(\n\t\t\t\trow.owner,\n\t\t\t\trow.keyring,\n\t\t\t\trow.record,\n\t\t\t\trow.revision,\n\t\t\t\tstored?.revision ?? 0,\n\t\t\t)\n\t\t\tif (written) restored++\n\t\t}\n\t}\n\treturn restored\n}\n\n/**\n * Merge-mode restore shared by the built-in stores: apply every backup operation\n * through the store's normal append (dedup by id). An operation refused for a\n * sequence conflict (another operation holds its node and sequence, W3 step 4) is\n * counted, not thrown, so the rest of the backup still restores; the result is then\n * `success: false` and the conflicts are logged, never silently dropped.\n */\nexport async function mergeBackupOperations(\n\toperations: Operation[],\n\tapply: (op: Operation) => Promise<string>,\n): Promise<{ operationsRestored: number; success: boolean }> {\n\tlet restored = 0\n\tconst conflicts: string[] = []\n\tfor (const op of operations) {\n\t\ttry {\n\t\t\tif ((await apply(op)) === 'applied') restored++\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof SequenceConflictError)) throw error\n\t\t\tconflicts.push(op.id)\n\t\t}\n\t}\n\tif (conflicts.length > 0) {\n\t\tconsole.warn(\n\t\t\t`[kora] Backup merge: ${String(conflicts.length)} operation(s) were not restored because another operation already holds their node and sequence number (SEQUENCE_CONFLICT). First: ${conflicts.slice(0, 5).join(', ')}`,\n\t\t)\n\t}\n\treturn { operationsRestored: restored, success: conflicts.length === 0 }\n}\n","// @korajs/server — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tAuthContext,\n\tAuthProvider,\n\tHttpSyncRequest,\n\tHttpSyncResponse,\n\tKoraSyncServerConfig,\n\tServerStatus,\n\tSessionRevocation,\n\tTerminateSessionsFilter,\n} from './types'\n\nexport type {\n\tApplyRemoteOptions,\n\tServerStore,\n\tMaterializedRecord,\n\tCollectionQueryOptions,\n\tServerSchemaOptions,\n\tStoredOperationKey,\n} from './store/server-store'\nexport type { TrustProxySetting } from './server/trust-proxy'\n\nexport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './transport/server-transport'\n\nexport type { HttpPollResponse } from './transport/http-server-transport'\n\nexport type {\n\tWsWebSocket,\n\tWsServerTransportOptions,\n} from './transport/ws-server-transport'\n\nexport type {\n\tAwarenessRelayCallback,\n\tClientSessionOptions,\n\tRelayCallback,\n\tSessionState,\n} from './session/client-session'\n\n// === Diagnostics ===\nexport type {\n\tClientMetrics,\n\tServerMetricsCollector,\n\tServerMetricsSnapshot,\n} from './diagnostics/server-metrics-collector'\n\n// === Logging ===\nexport type { LogEntry, LogLevel, Logger } from './logging/structured-logger'\nexport {\n\tcreateDefaultLogger,\n\tcreateJsonLogger,\n\tcreatePrettyLogger,\n\tcreateSilentLogger,\n} from './logging/structured-logger'\n\nexport type {\n\tWsServerConstructor,\n\tWsServerLike,\n} from './server/kora-sync-server'\n\nexport type {\n\tProductionServerConfig,\n\tProductionHttpRoute,\n\tProductionHttpRouteRequest,\n\tProductionHttpRouteResponse,\n\tProductionServer,\n} from './server/production-server'\n\nexport type {\n\tProductionHttpRouteContext,\n\tRouteMutation,\n\tRouteScopeOptions,\n\tRouteApplyResult,\n\tRouteConditionalApply,\n\tRouteConditionalResult,\n} from './server/route-context'\nexport type { RoutePredicate, RoutePredicateOperators } from './apply/route-predicate'\n\nexport type { OperationRejection } from './apply/rejection-taxonomy'\nexport { RETRIABLE_REJECTION_CODES, isRetriableRejection } from './apply/rejection-taxonomy'\n\nexport type {\n\tOperationDecision,\n\tOperationValidationContext,\n\tOperationValidator,\n} from './apply/operation-validator'\n\nexport type { TokenAuthProviderOptions } from './auth/token-auth'\nexport type { KoraAuthProviderOptions } from './auth/kora-auth-provider'\nexport type { MixedAuthProviderOptions } from './auth/mixed-auth-provider'\n\n// === Classes ===\nexport { MemoryServerStore, type MemoryServerStoreOptions } from './store/memory-server-store'\nexport type { FoldMigrationReport } from './store/record-fold'\nexport { PostgresServerStore } from './store/postgres-server-store'\nexport { SqliteServerStore } from './store/sqlite-server-store'\nexport {\n\tSERVER_NODE_PREFIX,\n\tServerIdentityError,\n\ttype ServerIdentityOptions,\n\tisServerNodeId,\n} from './store/server-identity'\nexport { HttpServerTransport } from './transport/http-server-transport'\nexport { WsServerTransport } from './transport/ws-server-transport'\nexport { ClientSession, type SessionTerminationCode } from './session/client-session'\nexport { KoraSyncServer } from './server/kora-sync-server'\nexport { NoAuthProvider } from './auth/no-auth'\nexport { TokenAuthProvider } from './auth/token-auth'\nexport { KoraAuthProvider } from './auth/kora-auth-provider'\nexport { MixedAuthProvider } from './auth/mixed-auth-provider'\nexport {\n\tDEFAULT_MAX_SCOPE_PREDICATE_VALUES,\n\tUplinkAuthorizationError,\n\tauthorizeUplinkWrite,\n\tnormalizeScopeMap,\n\toperationMatchesScopes,\n\ttype UplinkAuthorizationCode,\n\ttype UplinkAuthorizationResult,\n} from './scopes/server-scope-filter'\nexport {\n\tInvalidScopePredicateError,\n\tScopePredicateLimitError,\n} from './scopes/scope-predicate-errors'\nexport {\n\tScopeRequiredError,\n\tresolveSessionScopeGrant,\n\tresolveSessionScopes,\n} from './scopes/resolve-session-scopes'\nexport type {\n\tDeniedScopeCollection,\n\tResolveSessionScopesOptions,\n\tResolvedSessionScopeGrant,\n} from './scopes/resolve-session-scopes'\nexport { SCOPE_CLAIMS_KEY, claimScopes } from '@korajs/core'\n\n// === Awareness ===\nexport { AwarenessRelay } from './awareness/awareness-relay'\n\n// === Factory Functions ===\nexport { createKoraServer } from './server/create-server'\nexport { createProductionServer } from './server/production-server'\nexport {\n\tServerStoreUnavailableError,\n\tcreatePostgresServerStore,\n} from './store/postgres-server-store'\nexport { createSqliteServerStore } from './store/sqlite-server-store'\n","/**\n * Log severity levels.\n */\nexport type LogLevel = 'info' | 'warn' | 'error'\n\n/**\n * A structured log entry with timestamp and metadata.\n */\nexport interface LogEntry {\n\ttimestamp: number\n\tlevel: LogLevel\n\tevent: string\n\tsessionId?: string\n\tnodeId?: string\n\tduration?: number\n\tcount?: number\n\tbytes?: number\n\terror?: string\n\tdetails?: Record<string, unknown>\n}\n\n/**\n * Logger interface for structured logging.\n * Implementations control output format and destination.\n */\nexport interface Logger {\n\tlog(entry: LogEntry): void\n\tchild?(context: Partial<LogEntry>): Logger\n}\n\n/**\n * Serializes LogEntry to a single log line.\n */\nexport type LogSerializer = (entry: LogEntry) => string\n\nfunction defaultJsonSerializer(entry: LogEntry): string {\n\treturn JSON.stringify(entry)\n}\n\nfunction defaultPrettySerializer(entry: LogEntry): string {\n\tconst time = new Date(entry.timestamp).toISOString().slice(11, 23)\n\tconst levelTag = { info: ' INFO', warn: ' WARN', error: 'ERROR' }[entry.level]\n\tconst node = entry.nodeId ? ` [${entry.nodeId.slice(0, 8)}]` : ''\n\tconst session = entry.sessionId ? ` [session:${entry.sessionId.slice(0, 8)}]` : ''\n\tconst dur = entry.duration !== undefined ? ` +${entry.duration}ms` : ''\n\tconst count = entry.count !== undefined ? ` (${entry.count})` : ''\n\tconst err = entry.error ? ` — ${entry.error}` : ''\n\treturn `${time} ${levelTag}${node}${session} ${entry.event}${count}${dur}${err}`\n}\n\n/**\n * Creates a JSON-lines logger that writes to stdout/stderr.\n * Suitable for production use where log aggregators (Datadog, Loki, etc.) consume JSON.\n */\nexport function createJsonLogger(writer?: {\n\tinfo: (s: string) => void\n\terror: (s: string) => void\n}): Logger {\n\tconst out = writer ?? {\n\t\tinfo: (s: string) => process.stdout.write(`${s}\\n`),\n\t\terror: (s: string) => process.stderr.write(`${s}\\n`),\n\t}\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tconst line = defaultJsonSerializer(entry)\n\t\t\tif (entry.level === 'error') {\n\t\t\t\tout.error(line)\n\t\t\t} else {\n\t\t\t\tout.info(line)\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Creates a pretty-printed logger for development use.\n * Writes human-readable colored output to the terminal.\n */\nexport function createPrettyLogger(writer?: { write: (s: string) => void }): Logger {\n\tconst out = writer ?? { write: (s: string) => process.stdout.write(`${s}\\n`) }\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tout.write(defaultPrettySerializer(entry))\n\t\t},\n\t}\n}\n\n/**\n * A logger that discards all entries (for testing or when logging is disabled).\n */\nexport function createSilentLogger(): Logger {\n\treturn { log() {} }\n}\n\n/**\n * Creates a logger based on the NODE_ENV environment variable.\n * - production: JSON lines to stdout/stderr\n * - test: silent\n * - otherwise: pretty-printed to stdout\n */\nexport function createDefaultLogger(): Logger {\n\tswitch (process.env.NODE_ENV) {\n\t\tcase 'production':\n\t\t\treturn createJsonLogger()\n\t\tcase 'test':\n\t\t\treturn createSilentLogger()\n\t\tdefault:\n\t\t\treturn createPrettyLogger()\n\t}\n}\n","/**\n * Shared vocabulary for why the server refused an operation.\n *\n * The `retriable` flag answers one question for the caller: is it worth\n * submitting this SAME operation again later?\n *\n * - `true` — the rejection is transient (for example a rate limit). The\n * identical operation may succeed once the condition clears, so a\n * client is right to back off and retry the same bytes.\n * - `false` — the rejection is permanent for the operation as written (a\n * constraint violation, a referential conflict, a malformed\n * mutation, a scope violation). Resubmitting the same bytes will\n * always fail; the caller must change the operation or give up.\n *\n * This is deliberately defined once, in one place, so the trusted server\n * data-plane (route context / `server.kora`) and the untrusted client-ingestion\n * path speak the same language. `retriable` (this spelling) matches the wire\n * `ErrorMessage.retriable` field the sync protocol already ships, so a single\n * flag flows from the pipeline out to connected clients unchanged.\n */\nexport interface OperationRejection {\n\t/** Stable, machine-readable reason code (for example `CONSTRAINT_VIOLATION`). */\n\tcode: string\n\t/** Human-readable explanation with enough context to debug without reproduction. */\n\tmessage: string\n\t/** Whether resubmitting the identical operation may later succeed. */\n\tretriable: boolean\n}\n\n/**\n * Reason codes whose underlying condition is transient, so the identical\n * operation may succeed on a later attempt.\n *\n * Everything NOT listed here is treated as permanent. Permanent is the safe\n * default: a client should never be told to keep hammering a genuinely invalid\n * operation, so a new code is non-retriable until it is deliberately added here.\n *\n * `RATE_LIMIT` is the code the session emits when a client exceeds its\n * per-minute operation budget (see `client-session.ts`).\n */\nexport const RETRIABLE_REJECTION_CODES: ReadonlySet<string> = new Set(['RATE_LIMIT'])\n\n/**\n * Classify a reason code as retriable (transient) or not (permanent).\n *\n * @param code - A rejection reason code.\n * @returns `true` when resubmitting the identical operation may later succeed.\n */\nexport function isRetriableRejection(code: string): boolean {\n\treturn RETRIABLE_REJECTION_CODES.has(code)\n}\n","import type {\n\tFoldState,\n\tHLCTimestamp,\n\tOperation,\n\tOperationTransform,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n\tVersionVector,\n} from '@korajs/core'\nimport { HybridLogicalClock, assertOperationTransformCoverage } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport { UplinkAuthorizationError } from '../scopes/server-scope-filter'\nimport { validateFieldName } from './materialization'\nimport {\n\tEMPTY_FOLD_SCHEMA,\n\tREFOLD_REQUIRED,\n\ttype ServerFoldOptions,\n\tfoldFieldVersions,\n\tmaterializedFieldValue,\n\tmergeIntoFoldState,\n\tprojectFoldState,\n\trefoldRecord,\n\tserverFoldOptions,\n\tserverFoldPlanFingerprint,\n} from './record-fold'\nimport { replayScopeSnapshots, scopeSnapshotFingerprint, scopeValuesOf } from './scope-snapshot'\nimport {\n\ttype AuthorityHistory,\n\tderiveKeyedServerOpId,\n\tgenerateDeploymentId,\n\tgenerateDerivationSecret,\n\tnormalizeLegacyAuthorities,\n\tparseIdentityOptions,\n\tresolveAuthorityHistory,\n\tserverNodeIdFor,\n} from './server-identity'\nimport type {\n\tApplyRemoteOptions,\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tEncryptionKeyRecordRow,\n\tMaterializedRecord,\n\tOperationResolution,\n\tOperationScopeSnapshot,\n\tServerSchemaOptions,\n\tServerStore,\n} from './server-store'\nimport {\n\tMAX_RESOLUTION_MESSAGE_LENGTH,\n\tRELEASED_NODE_OWNER,\n\tSequenceConflictError,\n\tjudgeSequenceHolders,\n\treportLegacyPair,\n} from './server-store'\nimport type { StoredOperationKey } from './server-store'\n\n/**\n * Drop resolutions above their node's entry in `vector` (absent: every one), and every\n * `stored-elsewhere` resolution whose operation is not in the restored log (RT-51).\n */\nfunction pruneResolutionsPastLog(\n\tresolutions: Map<string, OperationResolution>,\n\tvector: ReadonlyMap<string, number>,\n\tstoredIds: ReadonlyMap<string, unknown>,\n): void {\n\tfor (const [id, resolution] of resolutions) {\n\t\tif (resolution.sequenceNumber > (vector.get(resolution.nodeId) ?? 0)) {\n\t\t\tresolutions.delete(id)\n\t\t} else if (resolution.outcome === 'stored-elsewhere' && !storedIds.has(id)) {\n\t\t\tresolutions.delete(id)\n\t\t}\n\t}\n}\n\n/** Key of a node's sequence number in {@link MemoryServerStore}'s sequence index. */\nfunction sequenceKey(nodeId: string, sequenceNumber: number): string {\n\treturn `${nodeId}\\u0000${String(sequenceNumber)}`\n}\n\n/** Key of a record in {@link MemoryServerStore}'s per-record indexes. */\nfunction recordKey(collection: string, recordId: string): string {\n\treturn `${collection}\\u0000${recordId}`\n}\n\n/** Options for {@link MemoryServerStore}. */\nexport interface MemoryServerStoreOptions {\n\t/**\n\t * Node ids, besides this store's own, whose operations win\n\t * `merge('server-authoritative')` fields (legacy server node ids). Every\n\t * `kora:server:` node id is authoritative without being listed.\n\t */\n\tauthoritativeNodeIds?: string[]\n\t/** Revoked explicit authorities (see `ServerIdentityOptions.revokedAuthoritativeNodeIds`). */\n\trevokedAuthoritativeNodeIds?: string[]\n\t/** Instance id within the deployment (see `ServerIdentityOptions.instanceId`). */\n\tinstanceId?: string\n}\n\n/**\n * In-memory server store for testing and quick prototyping.\n * Not suitable for production — data does not survive process restart.\n *\n * When a schema is set via setSchema(), maintains materialized records\n * in-memory for efficient queries.\n */\nexport class MemoryServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly operations: Operation[] = []\n\tprivate readonly operationIndex = new Map<string, Operation>()\n\t/** (nodeId, sequenceNumber) -> the id of the operation holding it (W3 step 4). */\n\t/** (node, sequence) -> ids holding it, in store order (several only for a legacy pair). */\n\tprivate readonly operationIdsBySequence = new Map<string, string[]>()\n\t/** Node -> sequences held by more than one operation (legacy pairs, RT-48). */\n\tprivate readonly pairSequencesByNode = new Map<string, Set<number>>()\n\t/** Operation id -> how it was resolved without being stored (RT-43, RT-47). */\n\tprivate readonly resolutions = new Map<string, OperationResolution>()\n\tprivate readonly versionVector: Map<string, number> = new Map()\n\t/**\n\t * Server-assigned delivery sequence per operation id. Single-process, so a plain\n\t * counter incremented at insert time gives commit-order delivery sequence with no\n\t * gaps. `operations` is kept in insertion (== delivery) order, so a delivery scan\n\t * is a forward walk.\n\t */\n\tprivate readonly deliverySeqByOpId = new Map<string, number>()\n\tprivate deliverySeqCounter = 0\n\tprivate schema: SchemaDefinition | null = null\n\n\t/** Node id -> the authenticated principal that claimed it (see claimNode). */\n\tprivate readonly nodeOwners = new Map<string, string>()\n\t/** Operation id -> scope snapshot captured at apply time (RT-14). */\n\tprivate readonly scopeSnapshots = new Map<string, OperationScopeSnapshot>()\n\t/** Fields the current snapshots were captured with (RT-20). */\n\tprivate snapshotFingerprint: string | null = null\n\t/** Blob content hash -> owners that pushed or first claimed it (RT-11). */\n\tprivate readonly blobOwners = new Map<string, Set<string>>()\n\t/** Wrapped encryption key records (ENC-1): owner + keyring -> record JSON and revision. */\n\tprivate readonly encryptionKeyRecords = new Map<string, EncryptionKeyRecordRow>()\n\n\t/** Materialized records: collection -> recordId -> record data */\n\tprivate readonly materializedRecords = new Map<string, Map<string, MaterializedRecord>>()\n\t/** Fold state per materialized record (W7): rows are projected from it. */\n\tprivate readonly foldStates = new Map<string, FoldState>()\n\t/** Every operation of a record, in store (delivery) order. */\n\tprivate readonly recordOps = new Map<string, Operation[]>()\n\tprivate readonly authoritativeNodeIds: string[]\n\t/** Legacy and configured authorities (the `kora:server:` prefix needs no listing). */\n\tprivate readonly explicitAuthorities: string[]\n\t/** Explicit authority over time: revoked and ever-held ids (RT-81). */\n\tprivate readonly authorityHistory: AuthorityHistory\n\tprivate foldOptions: ServerFoldOptions\n\t/** Schema transforms the fold applies (transforms at fold time, RT-84). */\n\tprivate operationTransforms: readonly OperationTransform[] = []\n\n\tprivate closed = false\n\t/**\n\t * Sequence-enforcement epoch (see SEQUENCE_ENFORCEMENT_EPOCH_KEY). A memory store\n\t * starts empty under this release, so 0: every holder was stored under enforcement.\n\t * A replace-mode backup import moves it to the restored log's end.\n\t */\n\tprivate sequenceEpoch = 0\n\n\t/** Derivation secret of server-derived ids (RT-64). Per process: nothing persists. */\n\tprivate readonly derivationSecret = generateDerivationSecret()\n\n\t/**\n\t * @param nodeId - Deprecated: a plain id is recorded as a legacy authoritative id; a\n\t * `kora:server:` id is used verbatim. Leave unset: the store authors under\n\t * `kora:server:<deployment>:<instance>` (a fresh deployment per process, since a\n\t * memory store persists nothing).\n\t * @param options - Extra authoritative ids and the instance id\n\t */\n\tconstructor(nodeId?: string, options: MemoryServerStoreOptions = {}) {\n\t\tconst configured = parseIdentityOptions({\n\t\t\t...(nodeId !== undefined ? { nodeId } : {}),\n\t\t\t...options,\n\t\t})\n\t\tthis.nodeId =\n\t\t\tconfigured.verbatimNodeId ??\n\t\t\tserverNodeIdFor(generateDeploymentId(), configured.instanceId ?? '1')\n\t\t// A memory store persists nothing: its history is this configuration (RT-81).\n\t\tthis.authorityHistory = resolveAuthorityHistory({\n\t\t\tlegacy: [],\n\t\t\tconfigured,\n\t\t\tpersistedEver: [],\n\t\t\tpersistedRevoked: [],\n\t\t\townNodeId: this.nodeId,\n\t\t})\n\t\tthis.explicitAuthorities = this.authorityHistory.explicitAuthorities\n\t\tthis.authoritativeNodeIds = [this.nodeId, ...this.explicitAuthorities]\n\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities)\n\t}\n\n\tasync deriveServerOperationId(\n\t\tparentOpId: string,\n\t\truleId: string,\n\t\ttargetRecordId: string,\n\t): Promise<string> {\n\t\treturn deriveKeyedServerOpId(this.derivationSecret, parentOpId, ruleId, targetRecordId)\n\t}\n\n\tgetAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.authoritativeNodeIds]\n\t}\n\n\t/** Explicit authoritative ids the deployment revoked (RT-81), advertised at handshake. */\n\tgetRevokedAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.authorityHistory.revoked]\n\t}\n\n\t/**\n\t * Every explicit id the deployment ever held authoritative, revoked ones included\n\t * (RT-81): never accepted as a device node id.\n\t */\n\tgetEverAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.authorityHistory.everAuthoritative]\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\treturn new Map(this.versionVector)\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition, options: ServerSchemaOptions = {}): Promise<void> {\n\t\tthis.assertOpen()\n\t\t// Refuse transforms that cannot read the stored log BEFORE anything changes (RT-103).\n\t\tassertOperationTransformCoverage(\n\t\t\tthis.operations.map((op) => op.schemaVersion),\n\t\t\tschema.version,\n\t\t\toptions.operationTransforms ?? this.operationTransforms,\n\t\t\t'memory server store',\n\t\t)\n\t\tthis.schema = schema\n\t\tif (options.operationTransforms !== undefined) {\n\t\t\tthis.operationTransforms = [...options.operationTransforms]\n\t\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t\t}\n\n\t\t// Initialize collection maps\n\t\tfor (const collectionName of Object.keys(schema.collections)) {\n\t\t\tif (!this.materializedRecords.has(collectionName)) {\n\t\t\t\tthis.materializedRecords.set(collectionName, new Map())\n\t\t\t}\n\t\t}\n\n\t\t// Backfill from existing operations\n\t\tthis.backfillAllCollections()\n\t\t// A change in the fields snapshots capture invalidates every snapshot (RT-20).\n\t\tconst fingerprint = scopeSnapshotFingerprint(schema)\n\t\tif (fingerprint !== this.snapshotFingerprint) {\n\t\t\tthis.scopeSnapshots.clear()\n\t\t\tthis.snapshotFingerprint = fingerprint\n\t\t}\n\t\tthis.backfillScopeSnapshots()\n\t}\n\n\tgetOperationTransforms(): readonly OperationTransform[] {\n\t\treturn this.operationTransforms\n\t}\n\n\tasync setOperationTransforms(transforms: readonly OperationTransform[]): Promise<void> {\n\t\tthis.assertOpen()\n\t\tif (this.schema) {\n\t\t\tassertOperationTransformCoverage(\n\t\t\t\tthis.operations.map((op) => op.schemaVersion),\n\t\t\t\tthis.schema.version,\n\t\t\t\ttransforms,\n\t\t\t\t'memory server store',\n\t\t\t)\n\t\t}\n\t\tconst before = this.schema\n\t\t\t? serverFoldPlanFingerprint(this.schema, this.explicitAuthorities, this.operationTransforms)\n\t\t\t: null\n\t\tthis.operationTransforms = [...transforms]\n\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t\t// The views changed: every record is re-folded from its log (RT-84).\n\t\tif (\n\t\t\tthis.schema &&\n\t\t\tbefore !==\n\t\t\t\tserverFoldPlanFingerprint(this.schema, this.explicitAuthorities, this.operationTransforms)\n\t\t) {\n\t\t\tthis.backfillAllCollections()\n\t\t}\n\t}\n\n\tasync applyRemoteOperation(op: Operation, options?: ApplyRemoteOptions): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\t// Content-addressed dedup: same id = same content\n\t\tif (this.operationIndex.has(op.id)) {\n\t\t\treturn 'duplicate'\n\t\t}\n\t\t// A different operation under the same (node, sequence) is refused (W3 step 4),\n\t\t// unless the writer is a legacy client or every holder predates the epoch (RT-37).\n\t\tconst holders = this.operationIdsBySequence.get(sequenceKey(op.nodeId, op.sequenceNumber)) ?? []\n\t\tconst decision = judgeSequenceHolders(\n\t\t\top,\n\t\t\tholders.map((id) => ({ id, deliverySequence: this.deliverySeqByOpId.get(id) ?? 1 })),\n\t\t\tthis.sequenceEpoch,\n\t\t\t{ legacySequenceWriter: options?.legacySequenceWriter === true },\n\t\t)\n\t\tif (decision.verdict === 'conflict') throw new SequenceConflictError(op, decision.holderId)\n\n\t\t// Authorization re-check against the row as stored right now. Everything from\n\t\t// here to the write is synchronous, so no other writer can interleave.\n\t\tif (options?.authorize) {\n\t\t\tconst decision = options.authorize(this.readStoredRow(op.collection, op.recordId))\n\t\t\tif (!decision.allowed) {\n\t\t\t\tthrow new UplinkAuthorizationError(decision.code, decision.message, {\n\t\t\t\t\toperationId: op.id,\n\t\t\t\t\tcollection: op.collection,\n\t\t\t\t\trecordId: op.recordId,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst materialized = this.schema?.collections[op.collection] !== undefined\n\t\tconst pre = materialized ? this.scopeValuesBefore(op.collection, op.recordId) : null\n\n\t\tthis.operations.push(op)\n\t\tthis.operationIndex.set(op.id, op)\n\t\tthis.addSequenceHolder(op)\n\t\tthis.addRecordOp(op)\n\n\t\t// Assign the next delivery sequence in commit order (single-process: no race).\n\t\tthis.deliverySeqCounter += 1\n\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\n\t\t// Advance version vector\n\t\tconst currentSeq = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentSeq) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\t// Dual-write: update materialized records if schema is set\n\t\tif (materialized) {\n\t\t\tthis.mergeIntoRecord(op)\n\t\t\t// The record's scope values around this write, from the store's own rows.\n\t\t\tconst row = this.materializedRecords.get(op.collection)?.get(op.recordId) ?? null\n\t\t\tthis.scopeSnapshots.set(op.id, {\n\t\t\t\tpre,\n\t\t\t\tpost: scopeValuesOf(this.schema, op.collection, op.recordId, row),\n\t\t\t})\n\t\t}\n\n\t\treportLegacyPair(op, decision, options)\n\t\treturn 'applied'\n\t}\n\n\tprivate addSequenceHolder(op: Operation): void {\n\t\tconst key = sequenceKey(op.nodeId, op.sequenceNumber)\n\t\tconst ids = this.operationIdsBySequence.get(key)\n\t\tif (ids) {\n\t\t\tids.push(op.id)\n\t\t\tlet pairs = this.pairSequencesByNode.get(op.nodeId)\n\t\t\tif (!pairs) {\n\t\t\t\tpairs = new Set()\n\t\t\t\tthis.pairSequencesByNode.set(op.nodeId, pairs)\n\t\t\t}\n\t\t\tpairs.add(op.sequenceNumber)\n\t\t} else this.operationIdsBySequence.set(key, [op.id])\n\t}\n\n\tasync getSequencePairOperations(nodeId: string, throughSequence: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tconst sequences = [...(this.pairSequencesByNode.get(nodeId) ?? [])]\n\t\t\t.filter((seq) => seq <= throughSequence)\n\t\t\t.sort((a, b) => a - b)\n\t\tconst result: Operation[] = []\n\t\tfor (const seq of sequences) {\n\t\t\tfor (const id of this.operationIdsBySequence.get(sequenceKey(nodeId, seq)) ?? []) {\n\t\t\t\tconst op = this.operationIndex.get(id)\n\t\t\t\tif (op) result.push(op)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync recordOperationResolution(resolution: OperationResolution): Promise<void> {\n\t\tthis.assertOpen()\n\t\tif (this.resolutions.has(resolution.operationId)) return\n\t\tthis.resolutions.set(resolution.operationId, {\n\t\t\t...resolution,\n\t\t\tmessage: resolution.message?.slice(0, MAX_RESOLUTION_MESSAGE_LENGTH) ?? null,\n\t\t})\n\t}\n\n\tasync findOperationResolutions(\n\t\tnodeId: string,\n\t\tids: string[],\n\t): Promise<Map<string, OperationResolution>> {\n\t\tthis.assertOpen()\n\t\tconst found = new Map<string, OperationResolution>()\n\t\tfor (const id of ids) {\n\t\t\tconst resolution = this.resolutions.get(id)\n\t\t\tif (resolution && resolution.nodeId === nodeId) found.set(id, { ...resolution })\n\t\t}\n\t\treturn found\n\t}\n\n\tasync deleteOperationResolution(nodeId: string, operationId: string): Promise<void> {\n\t\tthis.assertOpen()\n\t\tif (this.resolutions.get(operationId)?.nodeId === nodeId) this.resolutions.delete(operationId)\n\t}\n\n\tasync getResolvedThrough(nodeId: string): Promise<number> {\n\t\tthis.assertOpen()\n\t\tlet max = 0\n\t\tfor (const resolution of this.resolutions.values()) {\n\t\t\tif (resolution.nodeId === nodeId && resolution.sequenceNumber > max) {\n\t\t\t\tmax = resolution.sequenceNumber\n\t\t\t}\n\t\t}\n\t\treturn max\n\t}\n\n\tasync findStoredOperations(ids: string[]): Promise<Map<string, StoredOperationKey>> {\n\t\tthis.assertOpen()\n\t\tconst found = new Map<string, StoredOperationKey>()\n\t\tfor (const id of ids) {\n\t\t\tconst op = this.operationIndex.get(id)\n\t\t\tif (op) found.set(id, { nodeId: op.nodeId, sequenceNumber: op.sequenceNumber })\n\t\t}\n\t\treturn found\n\t}\n\n\tasync getOperationScopeSnapshots(\n\t\toperationIds: string[],\n\t): Promise<Map<string, OperationScopeSnapshot>> {\n\t\tthis.assertOpen()\n\t\tconst result = new Map<string, OperationScopeSnapshot>()\n\t\tfor (const id of operationIds) {\n\t\t\tconst snapshot = this.scopeSnapshots.get(id)\n\t\t\tif (snapshot) result.set(id, snapshot)\n\t\t}\n\t\treturn result\n\t}\n\n\tasync getRecordLatestTimestamp(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<HLCTimestamp | null> {\n\t\tthis.assertOpen()\n\t\tlet latest: HLCTimestamp | null = null\n\t\tfor (const op of this.recordOps.get(recordKey(collection, recordId)) ?? []) {\n\t\t\tif (latest === null || HybridLogicalClock.compare(op.timestamp, latest) > 0) {\n\t\t\t\tlatest = op.timestamp\n\t\t\t}\n\t\t}\n\t\treturn latest\n\t}\n\n\tasync getRecordFieldVersions(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<RecordFieldVersions | null> {\n\t\tthis.assertOpen()\n\t\treturn foldFieldVersions(this.readFoldState(collection, recordId))\n\t}\n\n\tasync getRecordFoldState(collection: string, recordId: string): Promise<FoldState | null> {\n\t\tthis.assertOpen()\n\t\treturn this.readFoldState(collection, recordId)\n\t}\n\n\tasync getRecordOperations(collection: string, recordId: string): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\treturn [...(this.recordOps.get(recordKey(collection, recordId)) ?? [])]\n\t}\n\n\tasync previewOperation(op: Operation): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tconst schema = this.schema ?? EMPTY_FOLD_SCHEMA\n\t\tconst current = this.readFoldState(op.collection, op.recordId)\n\t\tconst merged = mergeIntoFoldState(current, [op], schema, this.foldOptions)\n\t\tconst state =\n\t\t\tmerged === REFOLD_REQUIRED\n\t\t\t\t? refoldRecord(\n\t\t\t\t\t\t[...(this.recordOps.get(recordKey(op.collection, op.recordId)) ?? []), op],\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\tthis.foldOptions,\n\t\t\t\t\t)\n\t\t\t\t: merged\n\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\tif (!row || row.deleted) return null\n\t\treturn { ...row.values, id: op.recordId }\n\t}\n\n\t/**\n\t * The record's fold state: the stored one for a materialized collection, else\n\t * folded from the record's operations (a collection outside the schema).\n\t */\n\tprivate readFoldState(collection: string, recordId: string): FoldState | null {\n\t\tconst key = recordKey(collection, recordId)\n\t\tconst stored = this.foldStates.get(key)\n\t\tif (stored) return stored\n\t\tconst ops = this.recordOps.get(key)\n\t\tif (!ops || ops.length === 0) return null\n\t\treturn refoldRecord(ops, this.schema ?? EMPTY_FOLD_SCHEMA, this.foldOptions)\n\t}\n\n\tprivate addRecordOp(op: Operation): void {\n\t\tconst key = recordKey(op.collection, op.recordId)\n\t\tconst list = this.recordOps.get(key)\n\t\tif (list) list.push(op)\n\t\telse this.recordOps.set(key, [op])\n\t}\n\n\tasync recordBlobOwner(hash: string, owner: string): Promise<void> {\n\t\tthis.assertOpen()\n\t\tlet owners = this.blobOwners.get(hash)\n\t\tif (!owners) {\n\t\t\towners = new Set()\n\t\t\tthis.blobOwners.set(hash, owners)\n\t\t}\n\t\towners.add(owner)\n\t}\n\n\tasync getBlobOwners(hashes: string[]): Promise<Map<string, string[]>> {\n\t\tthis.assertOpen()\n\t\treturn new Map(hashes.map((hash) => [hash, [...(this.blobOwners.get(hash) ?? [])]]))\n\t}\n\n\tasync claimBlobIfUnowned(hash: string, owner: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tconst owners = this.blobOwners.get(hash)\n\t\tif (owners && owners.size > 0) return owners.has(owner)\n\t\tthis.blobOwners.set(hash, new Set([owner]))\n\t\treturn true\n\t}\n\n\t/** Scope values of a live record before a write; null when absent or deleted. */\n\tprivate scopeValuesBefore(collection: string, recordId: string): Record<string, unknown> | null {\n\t\tconst row = this.materializedRecords.get(collection)?.get(recordId)\n\t\tif (!row || row._deleted === 1) return null\n\t\treturn scopeValuesOf(this.schema, collection, recordId, row)\n\t}\n\n\t/**\n\t * Rebuild missing scope snapshots from the log (migration from a store without\n\t * them, or a replace-mode backup import), replaying each record in commit order.\n\t */\n\tprivate backfillScopeSnapshots(): void {\n\t\tconst schema = this.schema\n\t\tif (!schema) return\n\t\tfor (const ops of this.recordOps.values()) {\n\t\t\tconst first = ops[0]\n\t\t\tif (!first || !schema.collections[first.collection]) continue\n\t\t\tif (ops.every((op) => this.scopeSnapshots.has(op.id))) continue\n\t\t\tconst replayed = replayScopeSnapshots(\n\t\t\t\tschema,\n\t\t\t\tfirst.collection,\n\t\t\t\tfirst.recordId,\n\t\t\t\tops,\n\t\t\t\tthis.foldOptions,\n\t\t\t)\n\t\t\tfor (const [id, snapshot] of replayed) {\n\t\t\t\tif (!this.scopeSnapshots.has(id)) this.scopeSnapshots.set(id, snapshot)\n\t\t\t}\n\t\t}\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\treturn this.operations\n\t\t\t.filter(\n\t\t\t\t(op) => op.nodeId === nodeId && op.sequenceNumber >= fromSeq && op.sequenceNumber <= toSeq,\n\t\t\t)\n\t\t\t.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.operations.length\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.deliverySeqCounter\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst result: DeliveredOperation[] = []\n\t\tif (limit <= 0) return result\n\t\t// `operations` is in delivery order (sequences increase along the array), so seek\n\t\t// the first entry past the cursor by binary search instead of walking from the\n\t\t// head on every chunk (SRV-5: a full scan was quadratic in the log size).\n\t\tlet low = 0\n\t\tlet high = this.operations.length\n\t\twhile (low < high) {\n\t\t\tconst mid = (low + high) >>> 1\n\t\t\tconst candidate = this.operations[mid]\n\t\t\tconst sequence = candidate ? (this.deliverySeqByOpId.get(candidate.id) ?? 0) : 0\n\t\t\tif (sequence > afterDeliverySequence) high = mid\n\t\t\telse low = mid + 1\n\t\t}\n\t\tfor (let index = low; index < this.operations.length; index++) {\n\t\t\tconst op = this.operations[index] as Operation\n\t\t\tconst deliverySequence = this.deliverySeqByOpId.get(op.id) ?? 0\n\t\t\t// The guard keeps this correct even if the ordering invariant ever weakens.\n\t\t\tif (deliverySequence <= afterDeliverySequence) continue\n\t\t\tresult.push({\n\t\t\t\toperation: op,\n\t\t\t\tdeliverySequence,\n\t\t\t\tscopeSnapshot: this.scopeSnapshots.get(op.id) ?? null,\n\t\t\t})\n\t\t\tif (result.length >= limit) break\n\t\t}\n\t\treturn result\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read from materialized records\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations\n\t\treturn this.materializeFromOps(collection)\n\t}\n\n\tasync getNodeIdsAfterDelivery(afterDeliverySequence: number): Promise<string[]> {\n\t\tthis.assertOpen()\n\t\tconst nodes = new Set<string>()\n\t\tfor (const op of this.operations) {\n\t\t\tif ((this.deliverySeqByOpId.get(op.id) ?? 0) > afterDeliverySequence) nodes.add(op.nodeId)\n\t\t}\n\t\treturn [...nodes]\n\t}\n\n\tasync findRecordsByIds(\n\t\tcollection: string,\n\t\tids: string[],\n\t): Promise<Map<string, MaterializedRecord>> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\t\tconst records = this.materializedRecords.get(collection)\n\t\tconst result = new Map<string, MaterializedRecord>()\n\t\tfor (const id of ids) {\n\t\t\tconst record = records?.get(id)\n\t\t\tif (record) result.set(id, { ...record })\n\t\t}\n\t\treturn result\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\t// Validate field names\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return []\n\n\t\t// Get all non-deleted records\n\t\tlet records = Array.from(collectionMap.values()).filter((r) => {\n\t\t\tif (!options?.includeDeleted && r._deleted === 1) return false\n\t\t\treturn true\n\t\t})\n\n\t\t// Apply WHERE filters\n\t\tif (options?.where) {\n\t\t\tfor (const [key, value] of Object.entries(options.where)) {\n\t\t\t\trecords = records.filter((r) => r[key] === value)\n\t\t\t}\n\t\t}\n\n\t\t// Apply ORDER BY\n\t\tif (options?.orderBy) {\n\t\t\tconst field = options.orderBy\n\t\t\tconst dir = options.orderDirection === 'desc' ? -1 : 1\n\t\t\trecords.sort((a, b) => {\n\t\t\t\tconst aVal = a[field]\n\t\t\t\tconst bVal = b[field]\n\t\t\t\tif (aVal === bVal) return 0\n\t\t\t\tif (aVal === null || aVal === undefined) return 1\n\t\t\t\tif (bVal === null || bVal === undefined) return -1\n\t\t\t\treturn aVal < bVal ? -1 * dir : 1 * dir\n\t\t\t})\n\t\t}\n\n\t\t// Apply OFFSET\n\t\tif (options?.offset !== undefined) {\n\t\t\trecords = records.slice(options.offset)\n\t\t}\n\n\t\t// Apply LIMIT\n\t\tif (options?.limit !== undefined) {\n\t\t\trecords = records.slice(0, options.limit)\n\t\t}\n\n\t\t// Return clean copies without internal fields\n\t\treturn records.map((r) => {\n\t\t\tconst clean: MaterializedRecord = { id: r.id }\n\t\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[\n\t\t\t\tcollection\n\t\t\t] as NonNullable<SchemaDefinition['collections'][string]>\n\t\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\t\tif (fieldName in r) {\n\t\t\t\t\tclean[fieldName] = r[fieldName]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ('_created_at' in r) clean._created_at = r._created_at\n\t\t\tif ('_updated_at' in r) clean._updated_at = r._updated_at\n\t\t\t// A soft-deleted row (returned only with includeDeleted) says so.\n\t\t\tif (r._deleted === 1) clean._deleted = 1\n\t\t\treturn clean\n\t\t})\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return null\n\n\t\tconst record = collectionMap.get(id)\n\t\tif (!record || record._deleted === 1) return null\n\n\t\t// Return clean copy\n\t\tconst clean: MaterializedRecord = { id: record.id }\n\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\tif (fieldName in record) {\n\t\t\t\tclean[fieldName] = record[fieldName]\n\t\t\t}\n\t\t}\n\t\tif ('_created_at' in record) clean._created_at = record._created_at\n\t\tif ('_updated_at' in record) clean._updated_at = record._updated_at\n\t\treturn clean\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return 0\n\n\t\tlet count = 0\n\t\tfor (const record of collectionMap.values()) {\n\t\t\tif (record._deleted === 1) continue\n\t\t\tif (where) {\n\t\t\t\tlet matches = true\n\t\t\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\t\t\tif (record[key] !== value) {\n\t\t\t\t\t\tmatches = false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!matches) continue\n\t\t\t}\n\t\t\tcount++\n\t\t}\n\t\treturn count\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync getEncryptionKeyRecord(owner: string, keyring: string): Promise<string | null> {\n\t\tthis.assertOpen()\n\t\treturn this.encryptionKeyRecords.get(keyRecordKey(owner, keyring))?.record ?? null\n\t}\n\n\tasync putEncryptionKeyRecord(\n\t\towner: string,\n\t\tkeyring: string,\n\t\trecord: string,\n\t\trevision: number,\n\t\texpectedRevision: number,\n\t): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tconst key = keyRecordKey(owner, keyring)\n\t\tif ((this.encryptionKeyRecords.get(key)?.revision ?? 0) !== expectedRevision) return false\n\t\tthis.encryptionKeyRecords.set(key, { owner, keyring, record, revision })\n\t\treturn true\n\t}\n\n\tasync listEncryptionKeyRecords(owner?: string): Promise<EncryptionKeyRecordRow[]> {\n\t\tthis.assertOpen()\n\t\treturn [...this.encryptionKeyRecords.values()]\n\t\t\t.filter((row) => owner === undefined || row.owner === owner)\n\t\t\t.map((row) => ({ ...row }))\n\t}\n\n\tasync getEncryptedKeyIds(nodeOwner: string | null, limit: number): Promise<string[]> {\n\t\tthis.assertOpen()\n\t\tconst ids = new Set<string>()\n\t\tfor (const op of this.operations) {\n\t\t\tif (ids.size >= limit) break\n\t\t\tconst keyId = op.encrypted?.keyId\n\t\t\tif (typeof keyId !== 'string') continue\n\t\t\tif (nodeOwner !== null && this.nodeOwners.get(op.nodeId) !== nodeOwner) continue\n\t\t\tids.add(keyId)\n\t\t}\n\t\treturn [...ids]\n\t}\n\n\tasync claimNode(nodeId: string, userId: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tif (userId === RELEASED_NODE_OWNER) return false\n\t\tconst owner = this.nodeOwners.get(nodeId)\n\t\tif (owner === undefined) {\n\t\t\t// History without a claim predates node claims: its writer is unknown, so\n\t\t\t// nobody adopts it until an admin releases it (RT-5).\n\t\t\tif ((this.versionVector.get(nodeId) ?? 0) > 0) return false\n\t\t\tthis.nodeOwners.set(nodeId, userId)\n\t\t\treturn true\n\t\t}\n\t\tif (owner === RELEASED_NODE_OWNER) {\n\t\t\tthis.nodeOwners.set(nodeId, userId)\n\t\t\treturn true\n\t\t}\n\t\treturn owner === userId\n\t}\n\n\tasync getNodeClaimOwner(nodeId: string): Promise<string | null> {\n\t\tthis.assertOpen()\n\t\treturn this.nodeOwners.get(nodeId) ?? null\n\t}\n\n\tasync replaceNodeClaim(\n\t\tnodeId: string,\n\t\texpectedOwner: string,\n\t\tnewOwner: string,\n\t): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tif (this.nodeOwners.get(nodeId) !== expectedOwner) return false\n\t\tthis.nodeOwners.set(nodeId, newOwner)\n\t\treturn true\n\t}\n\n\tasync releaseNodeClaim(nodeId: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tconst known = this.nodeOwners.has(nodeId) || (this.versionVector.get(nodeId) ?? 0) > 0\n\t\tif (!known) return false\n\t\tthis.nodeOwners.set(nodeId, RELEASED_NODE_OWNER)\n\t\treturn true\n\t}\n\n\t/**\n\t * The record as currently stored, including a soft-deleted one (whose last field\n\t * values are kept), or null when it was never written. Without a materialized\n\t * table, the last known values are replayed from the operation log.\n\t */\n\tprivate readStoredRow(collection: string, recordId: string): MaterializedRecord | null {\n\t\tif (this.schema?.collections[collection]) {\n\t\t\tconst record = this.materializedRecords.get(collection)?.get(recordId)\n\t\t\tif (!record) return null\n\t\t\tconst stored: MaterializedRecord = { ...record, id: recordId }\n\t\t\tstored._deleted = undefined\n\t\t\treturn stored\n\t\t}\n\t\tconst recordOps = this.recordOps.get(recordKey(collection, recordId)) ?? []\n\t\tif (recordOps.length === 0) return null\n\t\tconst state = refoldRecord(recordOps, this.schema ?? EMPTY_FOLD_SCHEMA, this.foldOptions)\n\t\tconst lastKnown = state ? projectFoldState(state, this.foldOptions) : null\n\t\treturn { ...(lastKnown?.values ?? {}), id: recordId }\n\t}\n\n\t/**\n\t * Wipes all in-memory state. For tests and E2E isolation only.\n\t */\n\tresetForTests(): void {\n\t\tthis.assertOpen()\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.operationIdsBySequence.clear()\n\t\tthis.pairSequencesByNode.clear()\n\t\tthis.resolutions.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.materializedRecords.clear()\n\t\tthis.foldStates.clear()\n\t\tthis.recordOps.clear()\n\t\tthis.nodeOwners.clear()\n\t\tthis.scopeSnapshots.clear()\n\t\tthis.blobOwners.clear()\n\t\tthis.schema = null\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\treturn buildServerBackup(\n\t\t\tthis.nodeId,\n\t\t\tthis.operations,\n\t\t\tthis.versionVector,\n\t\t\tawait this.listEncryptionKeyRecords(),\n\t\t)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tconst { mergeBackupOperations, parseServerBackup, restoreBackupKeyRecords } = await import(\n\t\t\t'./server-backup'\n\t\t)\n\t\tconst { operations, versionVector, keyRecords } = parseServerBackup(data)\n\t\t// Both modes reconcile the key table (not part of the log), record by record (RT-110).\n\t\tawait restoreBackupKeyRecords(this, keyRecords, merge === true)\n\n\t\tif (merge) {\n\t\t\tconst merged = await mergeBackupOperations(operations, (op) => this.applyRemoteOperation(op))\n\t\t\treturn merged\n\t\t}\n\n\t\t// Replace mode: clear and reload\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.operationIdsBySequence.clear()\n\t\tthis.pairSequencesByNode.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.deliverySeqByOpId.clear()\n\t\tthis.deliverySeqCounter = 0\n\t\tthis.scopeSnapshots.clear()\n\t\tthis.foldStates.clear()\n\t\tthis.recordOps.clear()\n\t\tfor (const collectionMap of this.materializedRecords.values()) collectionMap.clear()\n\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\n\t\tfor (const op of operations) {\n\t\t\tthis.operations.push(op)\n\t\t\tthis.operationIndex.set(op.id, op)\n\t\t\tthis.addSequenceHolder(op)\n\t\t\tthis.addRecordOp(op)\n\t\t\t// Re-assign delivery sequence in backup order (the order ops were shipped).\n\t\t\tthis.deliverySeqCounter += 1\n\t\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\t\t}\n\t\t// Re-materialize every restored record through the fold, once per record.\n\t\tthis.backfillAllCollections()\n\t\t// Resolutions past a node's restored log describe operations decided after the\n\t\t// backup: advertising them would hide stored operations the restore lost (RT-45),\n\t\t// so they go and the devices re-upload that tail.\n\t\tpruneResolutionsPastLog(this.resolutions, this.versionVector, this.operationIndex)\n\t\t// The restored snapshot may hold legacy duplicate sequences; enforcement resumes\n\t\t// above it.\n\t\tthis.sequenceEpoch = this.deliverySeqCounter\n\t\tthis.backfillScopeSnapshots()\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// --- Testing helpers (not on interface) ---\n\n\t/**\n\t * Get all stored operations (for test assertions).\n\t */\n\tgetAllOperations(): Operation[] {\n\t\treturn [...this.operations]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Merge one just-appended operation into its record's fold state and project the\n\t * row: O(fields the operation touches), independent of the record's history\n\t * (SRV-7). Falls back to a full re-fold only when the stored state cannot take the\n\t * operation (a field's fold kind changed with the schema).\n\t */\n\tprivate mergeIntoRecord(op: Operation): void {\n\t\tconst schema = this.schema\n\t\tif (!schema?.collections[op.collection]) return\n\t\tconst key = recordKey(op.collection, op.recordId)\n\t\tconst merged = mergeIntoFoldState(\n\t\t\tthis.foldStates.get(key) ?? null,\n\t\t\t[op],\n\t\t\tschema,\n\t\t\tthis.foldOptions,\n\t\t)\n\t\tconst state =\n\t\t\tmerged === REFOLD_REQUIRED\n\t\t\t\t? refoldRecord(this.recordOps.get(key) ?? [op], schema, this.foldOptions)\n\t\t\t\t: merged\n\t\tthis.writeRecord(op.collection, op.recordId, state)\n\t}\n\n\t/** Persist a record's fold state and project it onto its materialized row. */\n\tprivate writeRecord(collection: string, recordId: string, state: FoldState | null): void {\n\t\tconst key = recordKey(collection, recordId)\n\t\tlet collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) {\n\t\t\tcollectionMap = new Map()\n\t\t\tthis.materializedRecords.set(collection, collectionMap)\n\t\t}\n\t\tif (state) this.foldStates.set(key, state)\n\t\telse this.foldStates.delete(key)\n\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\tif (!row) {\n\t\t\t// Never inserted (an update with no merged insert): no visible row. A row an\n\t\t\t// earlier materialization produced for it is hidden, never resurrected.\n\t\t\tconst existing = collectionMap.get(recordId)\n\t\t\tif (existing) existing._deleted = 1\n\t\t\treturn\n\t\t}\n\t\tconst values: Record<string, unknown> = { ...row.values }\n\t\tfor (const [field, descriptor] of Object.entries(\n\t\t\tthis.schema?.collections[collection]?.fields ?? {},\n\t\t)) {\n\t\t\tvalues[field] = materializedFieldValue(row.values, field, descriptor)\n\t\t}\n\t\tcollectionMap.set(recordId, {\n\t\t\tid: recordId,\n\t\t\t...values,\n\t\t\t_created_at: row.createdAt,\n\t\t\t_updated_at: row.updatedAt,\n\t\t\t_deleted: row.deleted ? 1 : 0,\n\t\t})\n\t}\n\n\t/** Re-fold every record of every materialized collection (schema set, backup restore). */\n\tprivate backfillAllCollections(): void {\n\t\tconst schema = this.schema\n\t\tif (!schema) return\n\t\tfor (const ops of this.recordOps.values()) {\n\t\t\tconst first = ops[0]\n\t\t\tif (!first || !schema.collections[first.collection]) continue\n\t\t\tthis.writeRecord(\n\t\t\t\tfirst.collection,\n\t\t\t\tfirst.recordId,\n\t\t\t\trefoldRecord(ops, schema, this.foldOptions),\n\t\t\t)\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOps(collection: string): MaterializedRecord[] {\n\t\tconst records: MaterializedRecord[] = []\n\t\tfor (const ops of this.recordOps.values()) {\n\t\t\tconst first = ops[0]\n\t\t\tif (!first || first.collection !== collection) continue\n\t\t\tconst state = refoldRecord(ops, this.schema ?? EMPTY_FOLD_SCHEMA, this.foldOptions)\n\t\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\t\tif (row && !row.deleted) records.push({ id: first.recordId, ...row.values })\n\t\t}\n\t\treturn records\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('MemoryServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/** Map key of one owner's keyring (NUL never occurs in either part's meaning). */\nfunction keyRecordKey(owner: string, keyring: string): string {\n\treturn `${owner}\\u0000${keyring}`\n}\n","import type { Operation } from '@korajs/core'\nimport { KoraError } from '@korajs/core'\nimport {\n\tbuildScopeSnapshot,\n\tmatchesScopePredicate,\n\trecordMatchesScopePredicates,\n} from '@korajs/sync/internal'\nimport { ScopePredicateLimitError, assertScopeValuesDefined } from './scope-predicate-errors'\n\n/**\n * Per-collection scope map from auth context.\n */\nexport type ScopeMap = Record<string, Record<string, unknown>>\n\nexport const DEFAULT_MAX_SCOPE_PREDICATE_VALUES = 100\n\n/**\n * Canonicalize bounded `$in` predicates so equivalent authorization has one signature.\n *\n * Fails closed: an `undefined`/`null` predicate value (also inside `$in`) would match\n * every record lacking the field, so it is refused (RT-8).\n *\n * @throws {InvalidScopePredicateError} On an undefined/null predicate value\n * @throws {ScopePredicateLimitError} On a malformed or oversized `$in`\n */\nexport function normalizeScopeMap(\n\tscopes: ScopeMap,\n\tmaxValues = DEFAULT_MAX_SCOPE_PREDICATE_VALUES,\n): ScopeMap {\n\tassertScopeValuesDefined(scopes)\n\tconst normalized: ScopeMap = {}\n\tfor (const collection of Object.keys(scopes).sort()) {\n\t\tconst predicate: Record<string, unknown> = {}\n\t\tfor (const field of Object.keys(scopes[collection] ?? {}).sort()) {\n\t\t\tconst expected = scopes[collection]?.[field]\n\t\t\tif (\n\t\t\t\texpected &&\n\t\t\t\ttypeof expected === 'object' &&\n\t\t\t\t!Array.isArray(expected) &&\n\t\t\t\t'$in' in expected\n\t\t\t) {\n\t\t\t\tconst values = (expected as { $in?: unknown }).$in\n\t\t\t\tif (!Array.isArray(values))\n\t\t\t\t\tthrow new ScopePredicateLimitError(`Invalid $in predicate for ${collection}.${field}`, {\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\tfield,\n\t\t\t\t\t})\n\t\t\t\tconst unique = [...new Map(values.map((value) => [stableValueKey(value), value])).values()]\n\t\t\t\tif (unique.length > maxValues)\n\t\t\t\t\tthrow new ScopePredicateLimitError(\n\t\t\t\t\t\t`Scope predicate for ${collection}.${field} exceeds the ${maxValues}-value limit`,\n\t\t\t\t\t\t{ collection, field, maxValues },\n\t\t\t\t\t)\n\t\t\t\tpredicate[field] = {\n\t\t\t\t\t$in: unique.sort((a, b) => stableValueKey(a).localeCompare(stableValueKey(b))),\n\t\t\t\t}\n\t\t\t} else predicate[field] = expected\n\t\t}\n\t\tnormalized[collection] = predicate\n\t}\n\treturn normalized\n}\n\nfunction stableValueKey(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(stableValueKey).join(',')}]`\n\tif (value && typeof value === 'object')\n\t\treturn `{${Object.keys(value as Record<string, unknown>)\n\t\t\t.sort()\n\t\t\t.map(\n\t\t\t\t(key) =>\n\t\t\t\t\t`${JSON.stringify(key)}:${stableValueKey((value as Record<string, unknown>)[key])}`,\n\t\t\t)\n\t\t\t.join(',')}}`\n\treturn JSON.stringify(value)\n}\n\n/**\n * Returns true if an operation is visible to a session based on its scopes.\n *\n * Rules:\n * - No scopes configured => visible\n * - Collection missing from scope map => hidden\n * - All scoped field/value pairs must match the operation snapshot\n */\nexport function operationMatchesScopes(\n\top: Operation,\n\tscopes: ScopeMap | undefined,\n\tfullRecord?: Record<string, unknown> | null,\n): boolean {\n\tif (!scopes) return true\n\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return false\n\tif (Object.keys(collectionScope).length === 0) return true\n\n\treturn recordMatchesScopePredicates(buildScopeSnapshot(op, fullRecord), collectionScope)\n}\n\n/**\n * True when an update moved a previously visible record outside the scope, judged\n * on the scope values the store captured from its own rows before and after the\n * write (RT-15). The writer's `previousData` is never consulted: it is unverified,\n * so it could inject retractions for its own records into another tenant's stream.\n *\n * @param op - The operation (only updates can exit a scope)\n * @param snapshot - The scope values captured when the operation was applied\n * @param scopes - The session's download scope\n */\nexport function snapshotExitsScopes(\n\top: Operation,\n\tsnapshot: { pre: Record<string, unknown> | null; post: Record<string, unknown> | null },\n\tscopes: ScopeMap | undefined,\n\tcurrent?: Record<string, unknown> | null,\n): boolean {\n\tif (!scopes || op.type !== 'update' || !snapshot.pre || !snapshot.post) return false\n\tconst pre = snapshotValuesWithFallback(op.collection, snapshot.pre, scopes, current)\n\tconst post = snapshotValuesWithFallback(op.collection, snapshot.post, scopes, current)\n\tif (!pre || !post) return false\n\treturn (\n\t\trecordMatchesScopes(op.collection, { ...pre, id: op.recordId }, scopes) &&\n\t\t!recordMatchesScopes(op.collection, { ...post, id: op.recordId }, scopes)\n\t)\n}\n\n/**\n * True when a field value satisfies one scope predicate (exact value or `$in`).\n * Shared by the sync path and the route context so both honour the same operators.\n *\n * @param actual - The record's field value\n * @param expected - The scope predicate for that field\n * @returns Whether the value is inside the predicate\n */\nexport function matchesPredicate(actual: unknown, expected: unknown): boolean {\n\treturn matchesScopePredicate(actual, expected)\n}\n\n/**\n * True when a stored record is inside the scope declared for its collection. A\n * collection absent from the scope map is out of scope; an empty predicate admits\n * every record. The record's `id` is used as stored, so callers must pass a row\n * read by id (never one assembled from client-supplied fields).\n *\n * @param collection - The record's collection\n * @param record - The stored record\n * @param scopes - Scope map, or undefined for no restriction\n * @returns Whether the record is visible under the scope\n */\nexport function recordMatchesScopes(\n\tcollection: string,\n\trecord: Record<string, unknown>,\n\tscopes: ScopeMap | undefined,\n): boolean {\n\tif (!scopes) return true\n\tconst collectionScope = scopes[collection]\n\tif (!collectionScope) return false\n\treturn recordMatchesScopePredicates(record, collectionScope)\n}\n\n/**\n * One side of a scope snapshot, with every scope field the snapshot does not hold\n * taken from the record's current row (RT-20). A snapshot captured before a schema\n * change that added (or renamed) a scope field lacks that field entirely; judging it\n * as \"no value\" would hide the record's whole history from every session. A field\n * that IS present (including null, which an over-long string is recorded as) is\n * kept, so a present-and-mismatched value still fails closed.\n *\n * @param collection - The record's collection\n * @param values - The snapshot side (`pre` or `post`), or null\n * @param scopes - The session's download scope\n * @param current - The record's current stored row, when known\n * @returns The values to judge, or null when `values` is null\n */\nexport function snapshotValuesWithFallback(\n\tcollection: string,\n\tvalues: Record<string, unknown> | null,\n\tscopes: ScopeMap | undefined,\n\tcurrent: Record<string, unknown> | null | undefined,\n): Record<string, unknown> | null {\n\tif (!values) return null\n\tconst predicate = scopes?.[collection]\n\tif (!predicate) return values\n\tlet filled: Record<string, unknown> | null = null\n\tfor (const field of Object.keys(predicate)) {\n\t\tif (field in values) continue\n\t\tif (!current || !(field in current)) continue\n\t\tfilled ??= { ...values }\n\t\tfilled[field] = current[field]\n\t}\n\treturn filled ?? values\n}\n\n/**\n * True when one of the snapshot's scope fields is absent, so a caller must read the\n * current row before judging it (see {@link snapshotValuesWithFallback}).\n */\nexport function snapshotLacksScopeFields(\n\tcollection: string,\n\tsnapshot: { pre: Record<string, unknown> | null; post: Record<string, unknown> | null },\n\tscopes: ScopeMap | undefined,\n): boolean {\n\tconst predicate = scopes?.[collection]\n\tif (!predicate) return false\n\tconst fields = Object.keys(predicate)\n\tconst lacks = (values: Record<string, unknown> | null): boolean =>\n\t\tvalues !== null && fields.some((field) => !(field in values))\n\treturn lacks(snapshot.pre) || lacks(snapshot.post)\n}\n\n/**\n * True when an operation moved an existing record INTO the scope: the store's own\n * pre-image was out of scope and the post-image is in it (RT-19). Inserts (no\n * pre-image) are not entries; they carry the whole record themselves.\n *\n * @param op - The operation\n * @param snapshot - The scope values captured when it was applied\n * @param scopes - The session's download scope\n * @param current - The record's current row, for scope fields a legacy snapshot lacks\n */\nexport function snapshotEntersScopes(\n\top: Operation,\n\tsnapshot: { pre: Record<string, unknown> | null; post: Record<string, unknown> | null },\n\tscopes: ScopeMap | undefined,\n\tcurrent?: Record<string, unknown> | null,\n): boolean {\n\tif (!scopes || op.type !== 'update') return false\n\tconst pre = snapshotValuesWithFallback(op.collection, snapshot.pre, scopes, current)\n\tconst post = snapshotValuesWithFallback(op.collection, snapshot.post, scopes, current)\n\tif (!pre || !post) return false\n\treturn (\n\t\t!recordMatchesScopes(op.collection, { ...pre, id: op.recordId }, scopes) &&\n\t\trecordMatchesScopes(op.collection, { ...post, id: op.recordId }, scopes)\n\t)\n}\n\n/**\n * Returns the scope fields (for `op.collection`) that a bare operation does NOT\n * carry in its own `data`/`previousData`. When any are missing, the caller must\n * backfill them from the materialized record before scope-checking, otherwise a\n * partial update (or a delete) that does not restate the scope field is wrongly\n * judged out of scope and dropped from relay/delta — silently diverging tenants.\n */\nexport function missingScopeFields(op: Operation, scopes: ScopeMap | undefined): string[] {\n\tif (!scopes) return []\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return []\n\tif (Object.keys(collectionScope).length === 0) return []\n\tconst snapshot = buildScopeSnapshot(op)\n\treturn Object.keys(collectionScope).filter((field) => !(field in snapshot))\n}\n\n/** Why {@link authorizeUplinkWrite} refused a write. */\nexport type UplinkAuthorizationCode = 'SCOPE_VIOLATION' | 'INVALID_OPERATION'\n\n/** Result of {@link authorizeUplinkWrite}. */\nexport type UplinkAuthorizationResult =\n\t| { allowed: true }\n\t| { allowed: false; code: UplinkAuthorizationCode; message: string }\n\n/**\n * Thrown by a server store when the uplink authorization re-check, evaluated inside\n * the store's apply critical section against the row as it is at commit time,\n * refuses an operation. Nothing was written.\n */\nexport class UplinkAuthorizationError extends KoraError {\n\tconstructor(\n\t\treadonly rejectionCode: UplinkAuthorizationCode,\n\t\tmessage: string,\n\t\tcontext?: Record<string, unknown>,\n\t) {\n\t\tsuper(message, rejectionCode, context)\n\t\tthis.name = 'UplinkAuthorizationError'\n\t}\n}\n\n/**\n * Decides whether an untrusted writer (a sync session or a scoped route) may apply\n * `op`, given the record as it is currently stored and the writer's scope.\n *\n * This is the single authorization rule for every untrusted write path (sync\n * uploads, `request.kora` routes, the conditional store path and the Yjs doc\n * channel). It never reads `op.previousData` for scope decisions, because it is\n * attacker-controlled, and it never lets op fields name a different record:\n *\n * 1. `op.data` / `op.previousData` must not carry an `id` other than `op.recordId`\n * (`INVALID_OPERATION`), whether or not scopes are configured.\n * 2. Without scopes every (well-formed) write is allowed.\n * 3. If a stored row exists (including a soft-deleted one) it must be in scope,\n * judged on the stored values only, for inserts, updates and deletes alike. This\n * stops editing, deleting or overwriting (same-id insert) another tenant's record.\n * 4. The post-image must be in scope: `{...stored, ...op.data}` for updates,\n * `op.data` for inserts and the stored row for deletes. This stops moving a\n * record out of scope (ownership transfer is a trusted server-route operation).\n *\n * In both images `id` is `op.recordId`, assigned last.\n *\n * @param op - The operation the writer wants to apply\n * @param storedRow - The record as stored now (including soft-deleted), or null\n * @param scopes - The writer's uplink scope map, or undefined for no restriction\n * @returns Whether the write is allowed, and why not when it is refused\n */\nexport function authorizeUplinkWrite(\n\top: Operation,\n\tstoredRow: Record<string, unknown> | null | undefined,\n\tscopes: ScopeMap | undefined,\n): UplinkAuthorizationResult {\n\tconst forgedIn = conflictingIdentity(op)\n\tif (forgedIn !== null) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tcode: 'INVALID_OPERATION',\n\t\t\tmessage: `Operation \"${op.id}\" on \"${op.collection}\" carries ${forgedIn}.id that differs from its recordId \"${op.recordId}\".`,\n\t\t}\n\t}\n\tif (!scopes) return { allowed: true }\n\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) {\n\t\treturn scopeViolation(op, `collection \"${op.collection}\" is not in the writer's scope`)\n\t}\n\tif (Object.keys(collectionScope).length === 0) return { allowed: true }\n\n\tconst stored = storedRow ?? null\n\tif (stored !== null) {\n\t\tconst preImage = { ...stored, id: op.recordId }\n\t\tif (!recordMatchesScopePredicates(preImage, collectionScope)) {\n\t\t\treturn scopeViolation(op, \"the stored record is outside the writer's scope\")\n\t\t}\n\t}\n\n\tconst data = asRecord(op.data) ?? {}\n\tconst postImage =\n\t\top.type === 'insert'\n\t\t\t? { ...data, id: op.recordId }\n\t\t\t: op.type === 'update'\n\t\t\t\t? { ...(stored ?? {}), ...data, id: op.recordId }\n\t\t\t\t: { ...(stored ?? {}), id: op.recordId }\n\tif (!recordMatchesScopePredicates(postImage, collectionScope)) {\n\t\treturn scopeViolation(op, \"the resulting record would be outside the writer's scope\")\n\t}\n\treturn { allowed: true }\n}\n\nfunction scopeViolation(op: Operation, reason: string): UplinkAuthorizationResult {\n\treturn {\n\t\tallowed: false,\n\t\tcode: 'SCOPE_VIOLATION',\n\t\tmessage: `Operation \"${op.id}\" on \"${op.collection}\" record \"${op.recordId}\" is outside the accepted uplink scope: ${reason}.`,\n\t}\n}\n\n/** Returns which op field carries a conflicting `id`, or null when none does. */\nfunction conflictingIdentity(op: Operation): 'data' | 'previousData' | null {\n\tconst data = asRecord(op.data)\n\tif (data && 'id' in data && data.id !== op.recordId) return 'data'\n\tconst previous = asRecord(op.previousData)\n\tif (previous && 'id' in previous && previous.id !== op.recordId) return 'previousData'\n\treturn null\n}\n\n/**\n * Split a collection scope into the equality predicates a store `where` clause can\n * evaluate, and report whether any non-equality predicate (`$in`) remains, which the\n * caller must filter in memory before applying limit/offset.\n *\n * @param collectionScope - Field predicates for one collection\n * @returns The equality subset and whether other operators are present\n */\nexport function splitScopeForQuery(collectionScope: Record<string, unknown>): {\n\tequality: Record<string, unknown>\n\thasNonEquality: boolean\n} {\n\tconst equality: Record<string, unknown> = {}\n\tlet hasNonEquality = false\n\tfor (const [field, expected] of Object.entries(collectionScope)) {\n\t\tif (expected !== null && typeof expected === 'object') {\n\t\t\thasNonEquality = true\n\t\t} else {\n\t\t\tequality[field] = expected\n\t\t}\n\t}\n\treturn { equality, hasNonEquality }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\treturn null\n\t}\n\n\treturn value as Record<string, unknown>\n}\n\n/**\n * Authorization for a write that names a record but carries no field values, such\n * as a Yjs doc-channel update to a richtext field. The record must be inside the\n * writer's scope as stored (with `id` forced to `recordId`); a record that is not\n * stored yet is judged by its id alone, so it only passes id-based or empty scopes.\n *\n * @param collection - The record's collection\n * @param recordId - The record the write targets\n * @param storedRow - The record as stored now (including soft-deleted), or null\n * @param scopes - The writer's uplink scope map, or undefined for no restriction\n * @returns Whether the write is allowed, and why not when it is refused\n */\nexport function authorizeRecordWrite(\n\tcollection: string,\n\trecordId: string,\n\tstoredRow: Record<string, unknown> | null | undefined,\n\tscopes: ScopeMap | undefined,\n): UplinkAuthorizationResult {\n\tif (!scopes) return { allowed: true }\n\tconst image = { ...(storedRow ?? {}), id: recordId }\n\tif (recordMatchesScopes(collection, image, scopes)) return { allowed: true }\n\treturn {\n\t\tallowed: false,\n\t\tcode: 'SCOPE_VIOLATION',\n\t\tmessage: `Write to \"${collection}\" record \"${recordId}\" is outside the accepted uplink scope.`,\n\t}\n}\n","import { KoraError } from '@korajs/core'\n\n/**\n * Thrown when a sync scope predicate value is `undefined` or `null` (also inside a\n * `$in` list). Such a value matches every record that lacks the field, so a grant\n * built from a failed lookup (for example `{ orgId: user.orgId }` with no org)\n * would expose every unowned record. Kora refuses it instead (fail closed).\n */\nexport class InvalidScopePredicateError extends KoraError {\n\tconstructor(\n\t\treadonly collection: string,\n\t\treadonly field: string,\n\t) {\n\t\tsuper(\n\t\t\t`Sync scope predicate for \"${collection}.${field}\" is undefined or null. A missing value would match every record without \"${field}\", so the grant is refused.`,\n\t\t\t'INVALID_SCOPE_PREDICATE',\n\t\t\t{\n\t\t\t\tcollection,\n\t\t\t\tfield,\n\t\t\t\tfix: 'Return a concrete value for this field from your auth provider, or leave the collection out of the grant to deny it.',\n\t\t\t},\n\t\t)\n\t\tthis.name = 'InvalidScopePredicateError'\n\t}\n}\n\n/** Thrown when a `$in` scope predicate is malformed or larger than the configured limit. */\nexport class ScopePredicateLimitError extends KoraError {\n\tconstructor(message: string, context: Record<string, unknown>) {\n\t\tsuper(message, 'SCOPE_PREDICATE_LIMIT', context)\n\t\tthis.name = 'ScopePredicateLimitError'\n\t}\n}\n\n/**\n * Refuse any `undefined`/`null` predicate value in a scope map (fail closed).\n *\n * @param scopes - Per-collection predicates\n * @throws {InvalidScopePredicateError} On the first undefined/null value found\n */\nexport function assertScopeValuesDefined(\n\tscopes: Record<string, Record<string, unknown> | undefined> | undefined,\n): void {\n\tif (!scopes) return\n\tfor (const [collection, predicate] of Object.entries(scopes)) {\n\t\tfor (const [field, expected] of Object.entries(predicate ?? {})) {\n\t\t\tif (expected === undefined || expected === null) {\n\t\t\t\tthrow new InvalidScopePredicateError(collection, field)\n\t\t\t}\n\t\t\tif (typeof expected === 'object' && !Array.isArray(expected) && '$in' in expected) {\n\t\t\t\tconst values = (expected as { $in?: unknown }).$in\n\t\t\t\tif (\n\t\t\t\t\tArray.isArray(values) &&\n\t\t\t\t\tvalues.some((value) => value === undefined || value === null)\n\t\t\t\t) {\n\t\t\t\t\tthrow new InvalidScopePredicateError(collection, field)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","import { StorageError, quoteIdent, replayOperationsForRecord } from '@korajs/core'\nimport type {\n\tCollectionDefinition,\n\tFieldDescriptor,\n\tReplayOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\n// SEC-9b: one DDL literal generator for client and server tables.\nimport { sqlDefaultLiteral } from '@korajs/core/internal'\n\n// Legacy comparison only (W7 Stage B2): the server stores no longer materialize with\n// the pre-fold replay. Every store merges operations into a per-record fold state\n// (see ./record-fold.ts). Kept so tests can compare the old and new results.\nexport { replayOperationsForRecord }\nexport type { ReplayOperation }\n\n/**\n * SQL dialect for DDL generation.\n * SQLite and PostgreSQL differ in some column types.\n */\nexport type SqlDialect = 'sqlite' | 'postgres'\n\n/**\n * Map a Kora field kind to its SQL column type for the given dialect.\n */\nfunction fieldTypeToSql(descriptor: FieldDescriptor, dialect: SqlDialect): string {\n\tswitch (descriptor.kind) {\n\t\tcase 'string':\n\t\t\treturn 'TEXT'\n\t\tcase 'number':\n\t\t\treturn dialect === 'postgres' ? 'DOUBLE PRECISION' : 'REAL'\n\t\tcase 'boolean':\n\t\t\treturn 'INTEGER'\n\t\tcase 'enum':\n\t\t\treturn 'TEXT'\n\t\tcase 'timestamp':\n\t\t\treturn dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\t\tcase 'array':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'object':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'json':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'blob':\n\t\t\t// Content-addressed BlobRef metadata is stored as JSON; the bytes live\n\t\t\t// out of band, so the column is textual, not binary.\n\t\t\treturn 'TEXT'\n\t\tcase 'secret':\n\t\t\treturn 'TEXT'\n\t\tcase 'richtext':\n\t\t\treturn dialect === 'postgres' ? 'BYTEA' : 'BLOB'\n\t}\n}\n\n/**\n * Generate DDL statements for creating a materialized collection table.\n * Includes CREATE TABLE, safe ALTER TABLE for schema evolution, and indexes.\n *\n * @param name - Collection/table name\n * @param collection - Collection definition from the schema\n * @param dialect - SQL dialect ('sqlite' or 'postgres')\n * @returns Array of DDL SQL strings\n */\nexport function generateCollectionDDL(\n\tname: string,\n\tcollection: CollectionDefinition,\n\tdialect: SqlDialect,\n): string[] {\n\tconst statements: string[] = []\n\tconst columns: string[] = ['id TEXT PRIMARY KEY NOT NULL']\n\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\t// No enum CHECK and no NOT NULL: the value domain is enforced at ingest only, so a\n\t\t// schema upgrade (an added enum value, a field made optional) never meets a stale\n\t\t// table constraint (RT-101).\n\t\tcolumns.push(colDef)\n\t}\n\n\tconst tsType = dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\tcolumns.push(`_created_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push(`_updated_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push('_deleted INTEGER NOT NULL DEFAULT 0')\n\n\tstatements.push(`CREATE TABLE IF NOT EXISTS ${quoteIdent(name)} (\\n ${columns.join(',\\n ')}\\n)`)\n\n\t// Safe ALTER TABLE for adding new columns to existing tables\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\tstatements.push(`--kora:safe-alter\\nALTER TABLE ${quoteIdent(name)} ADD COLUMN ${colDef}`)\n\t}\n\n\t// User-defined indexes from schema. The index NAME stays unquoted (only ever\n\t// created/dropped by this construction); the table and column are quoted.\n\tfor (const indexField of collection.indexes) {\n\t\tstatements.push(\n\t\t\t`CREATE INDEX IF NOT EXISTS idx_${name}_${indexField} ON ${quoteIdent(name)} (${quoteIdent(indexField)})`,\n\t\t)\n\t}\n\n\t// Always index _deleted for efficient soft-delete filtering\n\tstatements.push(\n\t\t`CREATE INDEX IF NOT EXISTS idx_${name}__deleted ON ${quoteIdent(name)} (_deleted)`,\n\t)\n\n\treturn statements\n}\n\n/**\n * Generate all collection table DDL from a full schema.\n */\nexport function generateAllCollectionDDL(schema: SchemaDefinition, dialect: SqlDialect): string[] {\n\tconst statements: string[] = []\n\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\tstatements.push(...generateCollectionDDL(name, collection, dialect))\n\t}\n\treturn statements\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst BASE64_REVERSE: ReadonlyMap<string, number> = new Map(\n\tArray.from(BASE64_ALPHABET, (char, index) => [char, index]),\n)\n\nfunction base64ToBytes(base64: string): Uint8Array {\n\tconst cleaned = base64.replace(/=+$/, '')\n\tconst out = new Uint8Array(Math.floor((cleaned.length * 6) / 8))\n\tlet buffer = 0\n\tlet bits = 0\n\tlet index = 0\n\tfor (const char of cleaned) {\n\t\tconst value = BASE64_REVERSE.get(char)\n\t\tif (value === undefined) {\n\t\t\tthrow new StorageError(`Invalid base64 character \"${char}\" in tagged richtext value`, {\n\t\t\t\tchar,\n\t\t\t})\n\t\t}\n\t\tbuffer = (buffer << 6) | value\n\t\tbits += 6\n\t\tif (bits >= 8) {\n\t\t\tbits -= 8\n\t\t\tout[index] = (buffer >> bits) & 0xff\n\t\t\tindex += 1\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Decode a richtext op-data value to something a BLOB/BYTEA column accepts.\n * Client operations carry binary richtext as the canonical tagged\n * `{ $koraBytes: base64 }` form (raw bytes cannot survive the JSON `dataJson`\n * wire field). The server cannot import the store package (dependency rules),\n * so the tiny base64 decode is duplicated here rather than shared.\n * Strings and byte views pass through unchanged.\n */\nfunction decodeRichtextColumnValue(value: unknown): unknown {\n\tif (typeof value !== 'object' || value === null || ArrayBuffer.isView(value)) {\n\t\treturn value\n\t}\n\tconst record = value as Record<string, unknown>\n\tif (Object.keys(record).length === 1 && typeof record.$koraBytes === 'string') {\n\t\treturn base64ToBytes(record.$koraBytes)\n\t}\n\t// Pre-fix operations serialized raw Uint8Arrays as numeric-key objects;\n\t// reconstruct the bytes so old dev databases keep materializing.\n\tconst keys = Object.keys(record)\n\tif (keys.length > 0 && keys.every((k, i) => k === String(i) && typeof record[k] === 'number')) {\n\t\tconst bytes = new Uint8Array(keys.length)\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst byte = record[String(i)]\n\t\t\tbytes[i] = typeof byte === 'number' ? byte & 0xff : 0\n\t\t}\n\t\treturn bytes\n\t}\n\treturn value\n}\n\n/**\n * Serialize a field value for SQL storage.\n * Arrays become JSON strings, booleans become 0/1, etc.\n */\nexport function serializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'json':\n\t\t\t// A json value may itself be a string (\"abc\", \"123\", \"\"): it is stored as JSON\n\t\t\t// like every other json value, so it reads back as that string, never parsed as\n\t\t\t// JSON text (the canonical value is what folds, on every store).\n\t\t\treturn JSON.stringify(value)\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? value : JSON.stringify(value)\n\t\tcase 'boolean':\n\t\t\treturn value ? 1 : 0\n\t\tcase 'richtext':\n\t\t\treturn decodeRichtextColumnValue(value)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * Deserialize a field value from SQL storage back to JavaScript types.\n */\nexport function deserializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'json':\n\t\t\treturn typeof value === 'string' ? parseJsonColumn(value) : value\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? JSON.parse(value) : value\n\t\tcase 'boolean':\n\t\t\treturn value === 1 || value === true\n\t\tcase 'timestamp':\n\t\t\t// A Postgres BIGINT column is read back as a string (or a bigint); the value\n\t\t\t// domain keeps timestamps safe integers, so the number is exact (RT-87).\n\t\t\treturn typeof value === 'string' || typeof value === 'bigint' ? Number(value) : value\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * A json column's text. Rows written before json strings were stored as JSON hold a raw\n * string that is not JSON text; it is read back as that string instead of failing.\n */\nfunction parseJsonColumn(text: string): unknown {\n\ttry {\n\t\treturn JSON.parse(text)\n\t} catch {\n\t\treturn text\n\t}\n}\n\n/**\n * Validate that a field name is a valid column in the given collection schema.\n * Includes system fields (id, _created_at, _updated_at, _deleted).\n */\nexport function validateFieldName(\n\tcollectionName: string,\n\tfieldName: string,\n\tschema: SchemaDefinition,\n): void {\n\tconst collection = schema.collections[collectionName]\n\tif (!collection) {\n\t\tthrow new Error(`Unknown collection: ${collectionName}`)\n\t}\n\tconst validFields = new Set([\n\t\t'id',\n\t\t'_created_at',\n\t\t'_updated_at',\n\t\t'_deleted',\n\t\t...Object.keys(collection.fields),\n\t])\n\tif (!validFields.has(fieldName)) {\n\t\tthrow new Error(\n\t\t\t`Invalid field name \"${fieldName}\" for collection \"${collectionName}\". ` +\n\t\t\t\t`Valid fields: ${Array.from(validFields).join(', ')}`,\n\t\t)\n\t}\n}\n","/**\n * Server materialization through the one deterministic fold (W7 Stage B2).\n *\n * Every server store (memory, SQLite, Postgres) keeps, per materialized record, the\n * record's serialized {@link FoldState} next to its collection row. Applying an\n * operation is \"append, then `mergeOp`\": O(fields the operation touches), never a\n * replay of the record's history (SRV-7). The collection row is a pure projection of\n * the fold state ({@link projectFoldState}), so the server's rows are exactly what a\n * client that holds the same operations materializes (SRV-1).\n *\n * The fold is pure JavaScript: ordering uses HLC stamps compared in JS, never a\n * database collation (the Phase 1 COLLATE \"C\" concern disappears for materialization).\n *\n * Old helpers (`replayOperationsForRecord`, `mergeArraySet`) are no longer used to\n * materialize; they stay exported from core for legacy comparison only.\n */\nimport {\n\tFoldStateError,\n\tHybridLogicalClock,\n\tcreateFoldState,\n\tdeserializeFoldState,\n\tfoldPlanFingerprint,\n\tfoldRecord,\n\tgetFoldFieldVersions,\n\tisFoldStateLive,\n\tmaterialize,\n\tmergeOp,\n\toperationSchemaView,\n\tserializeFoldState,\n} from '@korajs/core'\nimport type {\n\tFieldDescriptor,\n\tFoldOptions,\n\tFoldState,\n\tOperation,\n\tOperationTransform,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { mergeRichtext } from '@korajs/merge'\nimport {\n\tSERVER_NODE_PREFIX,\n\tServerAuthoritySet,\n\tnormalizeLegacyAuthorities,\n} from './server-identity'\n\n/**\n * Fold options as the server passes them. `authoritativeNodeIds` holds the node ids\n * whose operations win `merge('server-authoritative')` fields (the server's own node\n * ids); it is exactly the list the handshake advertises to clients.\n */\nexport type ServerFoldOptions = FoldOptions\n\n/**\n * `kora_server_meta` key holding {@link foldPlanFingerprint} of the schema the stored\n * fold states were built under. A change re-materializes every record.\n */\nexport const FOLD_PLAN_FINGERPRINT_KEY = 'fold_plan_fingerprint'\n\n/** Table holding each materialized record's serialized fold state (SQLite and Postgres). */\nexport const FOLD_STATE_TABLE = 'kora_fold_state'\n\n/** Records re-materialized per transaction by the startup migration. */\nexport const FOLD_MIGRATION_BATCH = 500\n\n/** What a store's startup re-materialization did (W7 step 7). */\nexport interface FoldMigrationReport {\n\t/** False when no schema was set (nothing is materialized). */\n\tran: boolean\n\t/** Records re-folded and rewritten. */\n\trecords: number\n\t/**\n\t * Records that own quarantined operations (see `ServerLogIntegrityReport`): their log\n\t * is incomplete, so their pre-fold rows were kept as a snapshot base with the\n\t * remaining operations folded onto it (RT-70), never re-folded from the log alone.\n\t */\n\tskippedUnclean: number\n\t/** True when the fold plan (field kinds, strategies, resolvers) changed: every record was re-folded. */\n\tfullRefold: boolean\n}\n\n/** A schema with no collections: every field folds as a last-write-wins register. */\nexport const EMPTY_FOLD_SCHEMA: SchemaDefinition = {\n\tversion: 0,\n\tcollections: {},\n\trelations: {},\n\tmigrations: {},\n}\n\n/**\n * Merge the opaque Yjs updates of a richtext field into one update (the fold's\n * `richtext` option). Built on `mergeRichtext`, which applies updates into a fresh\n * Y.Doc; the encoded state depends only on the set of updates, so every server and\n * client produce the same bytes.\n */\nexport function mergeRichtextUpdatesForServer(updates: Uint8Array[]): Uint8Array {\n\tconst [first, ...rest] = updates\n\tif (first === undefined) return mergeRichtext(null, null, null)\n\tlet merged = first\n\tfor (const update of rest) merged = mergeRichtext(merged, update, null)\n\treturn merged\n}\n\n/**\n * The fold options every server store uses: the richtext merger, no traces (the\n * server has no DevTools subscriber), and the server's authority: every node id in\n * the `kora:server:` namespace (the prefix rule, RT-62) plus `explicitAuthorities`\n * (legacy server node ids and configured extras).\n */\nexport function serverFoldOptions(\n\texplicitAuthorities: readonly string[],\n\ttransforms: readonly OperationTransform[] = [],\n): ServerFoldOptions {\n\treturn {\n\t\trichtext: mergeRichtextUpdatesForServer,\n\t\ttraces: 'none',\n\t\tauthoritativeNodeIds: new ServerAuthoritySet(explicitAuthorities),\n\t\t...(transforms.length > 0 ? { transforms } : {}),\n\t}\n}\n\n/**\n * The operation as the server's schema reads it (transforms at fold time, RT-84): what\n * authorization, validators, constraint checks and scope filters judge. The store keeps\n * the operation exactly as uploaded and folds this same view. Null when no transform\n * path exists or a transform drops it.\n *\n * @param store - Anything that knows the server schema and transforms\n * @param op - The operation as stored or uploaded\n */\nexport function serverOperationView(\n\tstore: {\n\t\tgetSchema(): SchemaDefinition | null\n\t\tgetOperationTransforms?(): readonly OperationTransform[]\n\t},\n\top: Operation,\n): Operation | null {\n\tconst schema = store.getSchema()\n\tif (schema === null) return op\n\treturn operationSchemaView(op, schema.version, store.getOperationTransforms?.())\n}\n\n/**\n * Fold plan fingerprint of the server: the schema's plan (with its schema transforms,\n * RT-84) plus the explicit authorities (the prefix rule is constant). A change in the explicit authorities re-folds every\n * record, so a stored fold state never keeps (or lacks) an authority class the current\n * authority set would not give.\n */\nexport function serverFoldPlanFingerprint(\n\tschema: SchemaDefinition,\n\texplicitAuthorities: readonly string[],\n\ttransforms: readonly OperationTransform[] = [],\n): string {\n\tconst explicit = normalizeLegacyAuthorities(explicitAuthorities)\n\treturn `${foldPlanFingerprint(schema, transforms)}|auth:${SERVER_NODE_PREFIX}*${\n\t\texplicit.length > 0 ? `,${explicit.join(',')}` : ''\n\t}`\n}\n\n/**\n * Fingerprint of how `schema` folds each field: field kind, merge strategy and custom\n * resolver (its source text), plus `FOLD_STATE_VERSION`. Stored fold states built\n * under a different fingerprint are re-materialized from the log at startup. This is\n * the core definition (`@korajs/core` `foldPlanFingerprint`), re-exported so clients\n * and the server can never disagree on whether a plan changed.\n */\nexport { foldPlanFingerprint }\n\n/**\n * Parse a stored fold state, or null when it is unreadable (unknown format version,\n * malformed JSON, a different record): the caller then re-folds the record from its\n * operation log.\n */\nexport function parseStoredFoldState(\n\tjson: string | null | undefined,\n\tcollection: string,\n\trecordId: string,\n): FoldState | null {\n\tif (typeof json !== 'string' || json.length === 0) return null\n\ttry {\n\t\tconst state = deserializeFoldState(json)\n\t\treturn state.c === collection && state.r === recordId ? state : null\n\t} catch (error) {\n\t\tif (error instanceof FoldStateError) return null\n\t\tthrow error\n\t}\n}\n\n/** Returned by {@link mergeIntoFoldState} when the stored state cannot take the operations. */\nexport const REFOLD_REQUIRED = Symbol('kora.refold-required')\n\n/**\n * Merge operations into a record's state, incrementally: O(fields the operations\n * touch). Returns {@link REFOLD_REQUIRED} when the stored state cannot take them (a\n * field whose fold kind changed since the state was built raises\n * {@link FoldStateError}); the caller then re-folds the record from its log with\n * {@link refoldRecord}. Synchronous, so SQLite's synchronous write transaction and\n * the memory store's synchronous apply can call it.\n *\n * @param state - The record's current state, or null for none\n * @param ops - The operations to merge (any order; duplicates are no-ops)\n * @param schema - The schema\n * @param options - Server fold options\n */\nexport function mergeIntoFoldState(\n\tstate: FoldState | null,\n\tops: readonly Operation[],\n\tschema: SchemaDefinition,\n\toptions: ServerFoldOptions,\n): FoldState | null | typeof REFOLD_REQUIRED {\n\tconst first = ops[0]\n\tif (first === undefined) return state\n\ttry {\n\t\tlet next = state ?? createFoldState(first.collection, first.recordId)\n\t\tfor (const op of ops) next = mergeOp(next, op, schema, options).state\n\t\treturn next\n\t} catch (error) {\n\t\tif (error instanceof FoldStateError) return REFOLD_REQUIRED\n\t\tthrow error\n\t}\n}\n\n/**\n * Fold a record from scratch: the reference definition of its state.\n *\n * @returns The state, or null when `ops` is empty\n */\nexport function refoldRecord(\n\tops: readonly Operation[],\n\tschema: SchemaDefinition,\n\toptions: ServerFoldOptions,\n): FoldState | null {\n\treturn foldRecord(ops, schema, options).state\n}\n\n/** A fold state projected onto a server collection row. */\nexport interface FoldedRow {\n\t/**\n\t * The record's field values. For a deleted record: the values it had (every\n\t * field's merged value; the server keeps them on the soft-deleted row so scope\n\t * judgments and authorization still see the record's last known fields).\n\t */\n\tvalues: Record<string, unknown>\n\t/** Wall time of the record's creation (its oldest insert). */\n\tcreatedAt: number\n\t/** Wall time of the record's newest operation of any type. */\n\tupdatedAt: number\n\t/** True when the newest delete is later than the newest write. */\n\tdeleted: boolean\n}\n\n/**\n * Project a fold state onto a collection row, or null when the record was never\n * inserted (an update with no merged insert does not materialize a row; W7 semantic\n * change 9).\n *\n * @param state - The record's fold state\n * @param options - Server fold options (the richtext merger)\n */\nexport function projectFoldState(state: FoldState, options: ServerFoldOptions): FoldedRow | null {\n\tif (state.cr === null) return null\n\tconst live = isFoldStateLive(state)\n\t// A deleted record keeps every field's merged value: materialize it as if the\n\t// newest delete were absent (`w` is set, since an insert was merged).\n\tconst values = materialize(live ? state : { ...state, d: null }, options) ?? {}\n\tconst createdAt = HybridLogicalClock.deserialize(state.cr.t).wallTime\n\tconst updatedAt = state.u ? HybridLogicalClock.deserialize(state.u.t).wallTime : createdAt\n\treturn { values, createdAt, updatedAt, deleted: !live }\n}\n\n/**\n * The value a materialized row holds for a schema field (RT-106): the fold's value, or,\n * for a field the fold never wrote (every operation of the record predates the field),\n * the schema default. That is what every device's row holds: the client store writes\n * only the fields its fold holds, so such a column keeps the value it was created or\n * added with.\n *\n * @param values - The projected values ({@link projectFoldState})\n * @param field - The schema field\n * @param descriptor - Its descriptor in the current schema\n */\nexport function materializedFieldValue(\n\tvalues: Readonly<Record<string, unknown>>,\n\tfield: string,\n\tdescriptor: FieldDescriptor,\n): unknown {\n\tif (field in values) return values[field] ?? null\n\treturn descriptor.defaultValue ?? null\n}\n\n/**\n * Per-field versions of a live record, from its fold state (RT-27): each field's\n * newest affecting write, the record's creation and its newest operation. Null when\n * the record is not live.\n */\nexport function foldFieldVersions(state: FoldState | null): RecordFieldVersions | null {\n\tif (!state) return null\n\treturn getFoldFieldVersions(state)\n}\n\n/**\n * A copy of `state` restricted to `fields` (the fields a receiver may see), for a\n * scope-entry operation (RT-29). Record-level stamps are kept: they carry no field\n * values.\n */\nexport function filterFoldStateFields(state: FoldState, fields: Iterable<string>): FoldState {\n\tconst keep = new Set(fields)\n\tconst filtered: FoldState['f'] = {}\n\tfor (const [field, fieldState] of Object.entries(state.f)) {\n\t\tif (keep.has(field)) filtered[field] = fieldState\n\t}\n\treturn { ...state, f: filtered }\n}\n\n/** Serialize a fold state for storage or the wire (canonical JSON). */\nexport function serializeServerFoldState(state: FoldState): string {\n\treturn serializeFoldState(state)\n}\n","/**\n * Stable server identity (RT-61, RT-62, RT-64).\n *\n * Every operation the server authors (route writes, cascades, set-nulls, constraint\n * corrections) is authored by a node id in the reserved namespace\n * `kora:server:<deploymentId>:<instanceId>`:\n *\n * - `deploymentId` is generated once per database and persisted in `kora_server_meta`,\n * so every instance that shares the database (and every restart) belongs to one\n * deployment.\n * - `instanceId` is distinct per running instance, so two instances never author the\n * same `(nodeId, sequenceNumber)`: SQLite persists one (a SQLite database has one\n * writer process), Postgres allocates a fresh one from a counter in the database on\n * every start unless the operator configures a stable `instanceId` per instance.\n *\n * Authority (`merge('server-authoritative')`) is the prefix rule: any operation whose\n * node id starts with {@link SERVER_NODE_PREFIX} is authoritative, on the server and on\n * every device. Devices can never use a `kora:` node id (the session refuses it at\n * handshake). Server node ids written before this release (random per-process ids, or\n * an id the operator configured) are recorded once, at the first start of this release,\n * in a persisted list of legacy authoritative ids that the handshake keeps advertising,\n * so earlier server decisions keep winning everywhere.\n *\n * Server-derived operation ids (cascades, corrections) are keyed with a persisted,\n * deployment-wide secret (HMAC-SHA-256), so a writer cannot predict them and occupy one\n * first; every instance of the deployment derives the same id for the same effect.\n */\nimport { KoraError, generateUUIDv7 } from '@korajs/core'\n\n/** Prefix of every node id the server authors under. */\nexport const SERVER_NODE_PREFIX = 'kora:server:'\n\n/** Prefix reserved for Kora itself; no device may use a node id that starts with it. */\nexport const RESERVED_NODE_PREFIX = 'kora:'\n\n/** `kora_server_meta` key: the deployment id, generated once per database. */\nexport const SERVER_DEPLOYMENT_ID_KEY = 'server_deployment_id'\n\n/** `kora_server_meta` key: the deployment's derivation secret (hex), generated once. */\nexport const SERVER_DERIVATION_SECRET_KEY = 'server_derivation_secret'\n\n/** `kora_server_meta` key: the persisted instance id of a single-writer (SQLite) database. */\nexport const SERVER_INSTANCE_ID_KEY = 'server_instance_id'\n\n/** `kora_server_meta` key: the counter Postgres instances draw their instance ids from. */\nexport const SERVER_INSTANCE_COUNTER_KEY = 'server_instance_counter'\n\n/** `kora_server_meta` key: JSON array of legacy authoritative node ids. */\nexport const SERVER_LEGACY_AUTHORITY_KEY = 'server_legacy_authoritative_node_ids'\n\n/**\n * `kora_server_meta` key: JSON array of every explicit node id the deployment ever held\n * authoritative (RT-81). Such an id stays authoritative until revoked, and is never\n * accepted as a device node id, even after it is revoked.\n */\nexport const SERVER_EVER_AUTHORITY_KEY = 'server_ever_authoritative_node_ids'\n\n/** `kora_server_meta` key: JSON array of revoked explicit authoritative node ids (RT-81). */\nexport const SERVER_REVOKED_AUTHORITY_KEY = 'server_revoked_authoritative_node_ids'\n\n/** `kora_server_meta` key: set once the legacy server node ids were collected from the log. */\nexport const SERVER_LEGACY_SCAN_KEY = 'server_legacy_authority_scan_v1'\n\nconst INSTANCE_ID_PATTERN = /^[A-Za-z0-9._-]{1,64}$/\n\n/** Domain tag of keyed server-derived ids (never equal to a content hash input). */\nconst SERVER_DERIVED_DOMAIN = 'kora/server-derived/v1'\n\n/** Thrown for an invalid server identity configuration. */\nexport class ServerIdentityError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(message, 'INVALID_SERVER_IDENTITY', context)\n\t\tthis.name = 'ServerIdentityError'\n\t}\n}\n\n/** Identity options every server store accepts. */\nexport interface ServerIdentityOptions {\n\t/**\n\t * Deprecated. A plain id (for example one set before beta.13) is no longer the id the\n\t * server authors under: it is recorded as a legacy authoritative id, so operations\n\t * already stored under it keep their authority, and no device may use it. An id in\n\t * the `kora:server:` namespace is used verbatim (it must then be unique per instance).\n\t */\n\tnodeId?: string\n\t/**\n\t * Stable id of this instance within the deployment (`[A-Za-z0-9._-]`, at most 64\n\t * characters). Must be distinct per running instance. SQLite persists one on its own;\n\t * Postgres allocates a new one per start when it is not configured.\n\t */\n\tinstanceId?: string\n\t/**\n\t * Extra node ids whose operations win `merge('server-authoritative')` fields. Every id\n\t * listed here once stays authoritative (devices keep it too) until it is revoked with\n\t * {@link revokedAuthoritativeNodeIds}: removing it from this list does not revoke it.\n\t */\n\tauthoritativeNodeIds?: string[]\n\t/**\n\t * Explicit authoritative node ids to revoke (RT-81): they stop being authoritative on\n\t * the server, the handshake tells every device to drop them (devices re-fold), and they\n\t * are still never accepted as device node ids. Revocation is permanent (persisted); an\n\t * id may not be both listed in `authoritativeNodeIds` and revoked.\n\t */\n\trevokedAuthoritativeNodeIds?: string[]\n}\n\n/** The configuration part of an identity, validated. */\nexport interface ConfiguredIdentity {\n\t/** A `kora:server:` node id configured verbatim, or null. */\n\tverbatimNodeId: string | null\n\t/** A configured plain node id (the id the server authored under before beta.13), or null. */\n\tlegacyNodeId: string | null\n\t/** A configured instance id, or null. */\n\tinstanceId: string | null\n\t/** Configured ids that are explicit (legacy) authorities: a plain `nodeId` and the extras. */\n\texplicitAuthorities: string[]\n\t/** Configured revocations (RT-81). */\n\trevokedAuthorities: string[]\n}\n\n/**\n * Validate the identity options of a store.\n *\n * @throws {ServerIdentityError} For a `kora:` node id outside `kora:server:`, or a malformed instance id\n */\nexport function parseIdentityOptions(options: ServerIdentityOptions): ConfiguredIdentity {\n\tlet verbatimNodeId: string | null = null\n\tlet legacyNodeId: string | null = null\n\tconst explicitAuthorities: string[] = []\n\tconst { nodeId, instanceId } = options\n\tif (nodeId !== undefined) {\n\t\tif (typeof nodeId !== 'string' || nodeId.length === 0) {\n\t\t\tthrow new ServerIdentityError('Server nodeId must be a non-empty string.', { nodeId })\n\t\t}\n\t\tif (nodeId.startsWith(SERVER_NODE_PREFIX)) {\n\t\t\tif (nodeId.length === SERVER_NODE_PREFIX.length) {\n\t\t\t\tthrow new ServerIdentityError(`Server nodeId \"${nodeId}\" has nothing after the prefix.`)\n\t\t\t}\n\t\t\tverbatimNodeId = nodeId\n\t\t} else if (nodeId.startsWith(RESERVED_NODE_PREFIX)) {\n\t\t\tthrow new ServerIdentityError(\n\t\t\t\t`Server nodeId \"${nodeId}\" is in the reserved \"kora:\" namespace. Leave nodeId unset (the server derives \"kora:server:<deployment>:<instance>\"), or set instanceId.`,\n\t\t\t\t{ nodeId },\n\t\t\t)\n\t\t} else {\n\t\t\tlegacyNodeId = nodeId\n\t\t\texplicitAuthorities.push(nodeId)\n\t\t}\n\t}\n\tif (instanceId !== undefined && !INSTANCE_ID_PATTERN.test(instanceId)) {\n\t\tthrow new ServerIdentityError(\n\t\t\t`Server instanceId \"${String(instanceId)}\" must match ${INSTANCE_ID_PATTERN.source}.`,\n\t\t\t{ instanceId },\n\t\t)\n\t}\n\tfor (const extra of options.authoritativeNodeIds ?? []) {\n\t\tif (typeof extra === 'string' && extra.length > 0 && !extra.startsWith(RESERVED_NODE_PREFIX)) {\n\t\t\texplicitAuthorities.push(extra)\n\t\t}\n\t}\n\tconst revokedAuthorities: string[] = []\n\tfor (const revoked of options.revokedAuthoritativeNodeIds ?? []) {\n\t\tif (typeof revoked !== 'string' || revoked.length === 0) {\n\t\t\tthrow new ServerIdentityError(\n\t\t\t\t'revokedAuthoritativeNodeIds entries must be non-empty strings.',\n\t\t\t\t{\n\t\t\t\t\trevoked,\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tif (revoked.startsWith(RESERVED_NODE_PREFIX)) {\n\t\t\tthrow new ServerIdentityError(\n\t\t\t\t`\"${revoked}\" cannot be revoked: ids in the \"kora:\" namespace are the server's own (authoritative by prefix).`,\n\t\t\t\t{ revoked },\n\t\t\t)\n\t\t}\n\t\tif (explicitAuthorities.includes(revoked)) {\n\t\t\tthrow new ServerIdentityError(\n\t\t\t\t`\"${revoked}\" is both configured as authoritative and revoked. Remove it from authoritativeNodeIds (and nodeId); revocation is permanent, so give a new authority a new id.`,\n\t\t\t\t{ revoked },\n\t\t\t)\n\t\t}\n\t\trevokedAuthorities.push(revoked)\n\t}\n\treturn {\n\t\tverbatimNodeId,\n\t\tlegacyNodeId,\n\t\tinstanceId: instanceId ?? null,\n\t\texplicitAuthorities,\n\t\trevokedAuthorities,\n\t}\n}\n\n/** The explicit authority state of a deployment (RT-81). */\nexport interface AuthorityHistory {\n\t/** Authoritative now: every explicit id ever held authoritative, minus the revoked. */\n\texplicitAuthorities: string[]\n\t/** Revoked for good. */\n\trevoked: string[]\n\t/** Every explicit id ever held authoritative, revoked ones included (never a device id). */\n\teverAuthoritative: string[]\n}\n\n/**\n * Resolve the explicit authorities from the persisted history and this start's\n * configuration (RT-81). Authority is a union over time, exactly as devices keep it:\n * an id listed once stays authoritative until it is revoked explicitly, and stays\n * reserved (refused as a device node id) after that.\n *\n * @throws {ServerIdentityError} When a configured authority was revoked earlier\n */\nexport function resolveAuthorityHistory(input: {\n\tlegacy: readonly string[]\n\tconfigured: ConfiguredIdentity\n\tpersistedEver: readonly string[]\n\tpersistedRevoked: readonly string[]\n\townNodeId: string\n}): AuthorityHistory {\n\tconst revoked = normalizeLegacyAuthorities([\n\t\t...input.persistedRevoked,\n\t\t...input.configured.revokedAuthorities,\n\t])\n\tconst conflict = input.configured.explicitAuthorities.find((id) => revoked.includes(id))\n\tif (conflict !== undefined) {\n\t\tthrow new ServerIdentityError(\n\t\t\t`\"${conflict}\" is configured as authoritative but was revoked earlier. Revocation is permanent: give the authority a new id.`,\n\t\t\t{ nodeId: conflict },\n\t\t)\n\t}\n\tconst everAuthoritative = normalizeLegacyAuthorities(\n\t\t[\n\t\t\t...input.persistedEver,\n\t\t\t...input.legacy,\n\t\t\t...input.configured.explicitAuthorities,\n\t\t\t...revoked,\n\t\t].filter((id) => id !== input.ownNodeId),\n\t)\n\treturn {\n\t\texplicitAuthorities: everAuthoritative.filter((id) => !revoked.includes(id)),\n\t\trevoked,\n\t\teverAuthoritative,\n\t}\n}\n\n/** The node id of an instance of a deployment. */\nexport function serverNodeIdFor(deploymentId: string, instanceId: string): string {\n\treturn `${SERVER_NODE_PREFIX}${deploymentId}:${instanceId}`\n}\n\n/** Prefix shared by every instance node id of one deployment. */\nexport function deploymentNodePrefix(deploymentId: string): string {\n\treturn `${SERVER_NODE_PREFIX}${deploymentId}:`\n}\n\n/** True for a node id the server authors under (current or any instance of any deployment). */\nexport function isServerNodeId(nodeId: string): boolean {\n\treturn nodeId.startsWith(SERVER_NODE_PREFIX)\n}\n\n/** A new deployment id (UUID v7, so deployments sort by creation). */\nexport function generateDeploymentId(): string {\n\treturn generateUUIDv7()\n}\n\n/** A new random instance id (memory stores, which persist nothing). */\nexport function generateInstanceId(): string {\n\treturn generateUUIDv7()\n}\n\n/** A new 256-bit derivation secret, hex encoded. */\nexport function generateDerivationSecret(): string {\n\tconst bytes = new Uint8Array(32)\n\tglobalThis.crypto.getRandomValues(bytes)\n\treturn Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/** Parse the persisted legacy list (tolerates a missing or malformed value). */\nexport function parseLegacyAuthorities(value: string | null | undefined): string[] {\n\tif (typeof value !== 'string' || value.length === 0) return []\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(value)\n\t\treturn Array.isArray(parsed)\n\t\t\t? parsed.filter((id): id is string => typeof id === 'string' && id.length > 0)\n\t\t\t: []\n\t} catch {\n\t\treturn []\n\t}\n}\n\n/** Canonical (sorted, unique, no reserved ids) form of a legacy list. */\nexport function normalizeLegacyAuthorities(ids: Iterable<string>): string[] {\n\treturn [\n\t\t...new Set([...ids].filter((id) => id.length > 0 && !id.startsWith(RESERVED_NODE_PREFIX))),\n\t].sort()\n}\n\n/**\n * The authority set the server folds with: every `kora:server:` node id, plus the\n * explicit (legacy and configured) ids. A `Set` whose `has` also applies the prefix\n * rule, so it can be passed as `FoldOptions.authoritativeNodeIds`.\n */\nexport class ServerAuthoritySet extends Set<string> {\n\toverride has(nodeId: string): boolean {\n\t\treturn isServerNodeId(nodeId) || super.has(nodeId)\n\t}\n}\n\n/**\n * The operation ids of every stamp with authority class 1 in a serialized fold state:\n * the writes that won a `merge('server-authoritative')` field because their node was\n * authoritative when the server folded them.\n *\n * Reads stamps only from their positions in the fold-state format (RT-76): the\n * record's `cr`/`w`/`d`/`u` registers and each field kind's stamp members. Values\n * (`v`, element values, key values, resolver bases) are never walked: a device writes\n * them, and a json value shaped like a stamp must not name an authority. The format\n * version is not enforced (the scan reads states a pre-release fold build wrote);\n * anything that does not have the expected shape is skipped.\n */\nexport function authoritativeStampOpIds(stateJson: string): string[] {\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(stateJson)\n\t} catch {\n\t\treturn []\n\t}\n\tif (!isObject(parsed)) return []\n\tconst found = new Set<string>()\n\tconst stamp = (value: unknown): void => {\n\t\tif (\n\t\t\tisObject(value) &&\n\t\t\tvalue.c === 1 &&\n\t\t\ttypeof value.t === 'string' &&\n\t\t\ttypeof value.o === 'string'\n\t\t) {\n\t\t\tfound.add(value.o)\n\t\t}\n\t}\n\t/** `{ s: Stamp, ... }` members (shape registers, base/best/reset registers, map keys). */\n\tconst wrapped = (value: unknown): void => {\n\t\tif (isObject(value)) stamp(value.s)\n\t}\n\tfor (const key of ['cr', 'w', 'd', 'u'] as const) stamp(parsed[key])\n\tconst fields = isObject(parsed.f) ? parsed.f : {}\n\tfor (const field of Object.values(fields)) {\n\t\tif (!isObject(field)) continue\n\t\tswitch (field.k) {\n\t\t\tcase 'reg':\n\t\t\tcase 'res':\n\t\t\t\tfor (const entry of asArray(field.e)) wrapped(entry)\n\t\t\t\tbreak\n\t\t\tcase 'set':\n\t\t\t\twrapped(field.sh)\n\t\t\t\tstamp(field.clr)\n\t\t\t\tfor (const element of Object.values(isObject(field.el) ? field.el : {})) {\n\t\t\t\t\tif (!isObject(element)) continue\n\t\t\t\t\tstamp(element.a)\n\t\t\t\t\twrapped(element.f)\n\t\t\t\t\tstamp(element.r)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'map':\n\t\t\t\twrapped(field.sh)\n\t\t\t\tstamp(field.clr)\n\t\t\t\tfor (const keyState of Object.values(isObject(field.keys) ? field.keys : {})) {\n\t\t\t\t\twrapped(keyState)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'ctr':\n\t\t\t\twrapped(field.base)\n\t\t\t\tfor (const delta of asArray(field.d)) wrapped(delta)\n\t\t\t\tbreak\n\t\t\tcase 'max':\n\t\t\tcase 'min':\n\t\t\t\twrapped(field.best)\n\t\t\t\twrapped(field.reg)\n\t\t\t\tbreak\n\t\t\tcase 'rt':\n\t\t\t\twrapped(field.reset)\n\t\t\t\tfor (const updateStamp of Object.values(isObject(field.u) ? field.u : {})) {\n\t\t\t\t\tstamp(updateStamp)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tbreak\n\t\t}\n\t}\n\treturn [...found]\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction asArray(value: unknown): unknown[] {\n\treturn Array.isArray(value) ? value : []\n}\n\n/** Imported HMAC keys, per secret. */\nconst derivationKeys = new Map<string, Promise<CryptoKey>>()\n\nfunction derivationKey(secretHex: string): Promise<CryptoKey> {\n\tlet key = derivationKeys.get(secretHex)\n\tif (!key) {\n\t\tconst bytes = new Uint8Array(secretHex.length / 2)\n\t\tfor (let i = 0; i < bytes.length; i++) {\n\t\t\tbytes[i] = Number.parseInt(secretHex.slice(i * 2, i * 2 + 2), 16)\n\t\t}\n\t\tkey = globalThis.crypto.subtle.importKey(\n\t\t\t'raw',\n\t\t\tbytes,\n\t\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\t\tfalse,\n\t\t\t['sign'],\n\t\t)\n\t\tderivationKeys.set(secretHex, key)\n\t}\n\treturn key\n}\n\n/**\n * Keyed id of a server-derived operation (a cascade, a set-null, a constraint\n * correction): HMAC-SHA-256 under the deployment's secret over the JSON array\n * `[domain, parent, rule, target]`, hex encoded. Deterministic for every instance of\n * the deployment (idempotent across instances and retries), unpredictable for anyone\n * without the secret (RT-64): no client can store an operation under it first.\n *\n * @param secretHex - The deployment's derivation secret\n * @param parentOpId - Id (or composite key) of the operation whose application produced the effect\n * @param ruleId - Stable id of the rule (for example `server/relation:<name>:cascade`)\n * @param targetRecordId - Id of the record the effect writes\n */\nexport async function deriveKeyedServerOpId(\n\tsecretHex: string,\n\tparentOpId: string,\n\truleId: string,\n\ttargetRecordId: string,\n): Promise<string> {\n\tfor (const [name, value] of [\n\t\t['parentOpId', parentOpId],\n\t\t['ruleId', ruleId],\n\t\t['targetRecordId', targetRecordId],\n\t] as const) {\n\t\tif (typeof value !== 'string' || value.length === 0) {\n\t\t\tthrow new ServerIdentityError(`deriveServerOperationId: ${name} must be a non-empty string`, {\n\t\t\t\t[name]: value,\n\t\t\t})\n\t\t}\n\t}\n\tconst key = await derivationKey(secretHex)\n\t// A JSON array has one serialization: unambiguous framing of the four strings.\n\tconst canonical = JSON.stringify([SERVER_DERIVED_DOMAIN, parentOpId, ruleId, targetRecordId])\n\tconst mac = await globalThis.crypto.subtle.sign('HMAC', key, new TextEncoder().encode(canonical))\n\treturn Array.from(new Uint8Array(mac), (b) => b.toString(16).padStart(2, '0')).join('')\n}\n","import type { FoldState, Operation, SchemaDefinition } from '@korajs/core'\nimport {\n\tREFOLD_REQUIRED,\n\ttype ServerFoldOptions,\n\tmergeIntoFoldState,\n\tprojectFoldState,\n\trefoldRecord,\n} from './record-fold'\nimport { MAX_SCOPE_SNAPSHOT_STRING_LENGTH, type OperationScopeSnapshot } from './server-store'\n\n/** Field kinds a scope predicate can match (compared with `Object.is`). */\nconst SNAPSHOT_KINDS = new Set(['string', 'number', 'boolean', 'enum', 'timestamp'])\n\n/**\n * The scope-relevant values of a stored row: `id` plus every scalar field, with\n * over-long strings left out (see {@link OperationScopeSnapshot}). Returns null when\n * there is no row or the collection is not in the schema.\n *\n * @param schema - The store schema\n * @param collection - The row's collection\n * @param recordId - The row's id (always used as `id`)\n * @param row - The row as stored, or null\n */\nexport function scopeValuesOf(\n\tschema: SchemaDefinition | null,\n\tcollection: string,\n\trecordId: string,\n\trow: Record<string, unknown> | null,\n): Record<string, unknown> | null {\n\tif (!row) return null\n\tconst definition = schema?.collections[collection]\n\tif (!definition) return null\n\tconst values: Record<string, unknown> = { id: recordId }\n\tfor (const [name, field] of Object.entries(definition.fields)) {\n\t\tif (!SNAPSHOT_KINDS.has(field.kind) || !(name in row)) continue\n\t\tconst value = row[name]\n\t\t// An over-long string is recorded as null: present (so the current-row fallback\n\t\t// of RT-20 never applies to it) and never equal to a scope value (fails closed).\n\t\tvalues[name] =\n\t\t\ttypeof value === 'string' && value.length > MAX_SCOPE_SNAPSHOT_STRING_LENGTH ? null : value\n\t}\n\treturn values\n}\n\n/**\n * Fingerprint of the fields scope snapshots capture under `schema` (every scalar\n * field of every collection, with its kind). When it changes (a migration added,\n * renamed or retyped a field), snapshots captured under the old schema no longer\n * describe the records the way the new one would, so the store recomputes them all\n * from the log (RT-20).\n */\nexport function scopeSnapshotFingerprint(schema: SchemaDefinition): string {\n\tconst parts: string[] = []\n\tfor (const collection of Object.keys(schema.collections).sort()) {\n\t\tconst fields = schema.collections[collection]?.fields ?? {}\n\t\tconst captured = Object.keys(fields)\n\t\t\t.filter((name) => SNAPSHOT_KINDS.has(fields[name]?.kind ?? ''))\n\t\t\t.sort()\n\t\t\t.map((name) => `${name}:${fields[name]?.kind ?? ''}`)\n\t\tparts.push(`${collection}(${captured.join(',')})`)\n\t}\n\treturn `v1|${parts.join('|')}`\n}\n\n/** Meta key under which stores persist {@link scopeSnapshotFingerprint}. */\nexport const SCOPE_SNAPSHOT_FINGERPRINT_KEY = 'scope_snapshot_fields'\n\n/** Parse a persisted snapshot column; null for an absent or malformed value. */\nexport function parseScopeSnapshot(raw: unknown): OperationScopeSnapshot | null {\n\tif (typeof raw !== 'string' || raw.length === 0) return null\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as { pre?: unknown; post?: unknown }\n\t\tconst asValues = (value: unknown): Record<string, unknown> | null =>\n\t\t\tvalue && typeof value === 'object' && !Array.isArray(value)\n\t\t\t\t? (value as Record<string, unknown>)\n\t\t\t\t: null\n\t\treturn { pre: asValues(parsed.pre), post: asValues(parsed.post) }\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Rebuild the snapshot each operation of one record would have received when it was\n * applied, from the server's own log (migration backfill, RT-14). `operations` are\n * in delivery (commit) order; each operation's state is the fold of the operations\n * committed up to and including it, exactly what materialization held (W7: the fold\n * depends only on the set of operations, so merging in commit order is that state).\n *\n * Linear in the operations of one record (one incremental merge per operation).\n *\n * @returns Snapshot per operation id\n */\nexport function replayScopeSnapshots(\n\tschema: SchemaDefinition,\n\tcollection: string,\n\trecordId: string,\n\toperations: readonly Operation[],\n\toptions: ServerFoldOptions,\n): Map<string, OperationScopeSnapshot> {\n\tconst result = new Map<string, OperationScopeSnapshot>()\n\tconst committed: Operation[] = []\n\tlet state: FoldState | null = null\n\tlet pre: Record<string, unknown> | null = null\n\tfor (const operation of operations) {\n\t\tcommitted.push(operation)\n\t\tconst merged = mergeIntoFoldState(state, [operation], schema, options)\n\t\tstate = merged === REFOLD_REQUIRED ? refoldRecord(committed, schema, options) : merged\n\t\tconst row = state ? projectFoldState(state, options) : null\n\t\tconst post = row ? scopeValuesOf(schema, collection, recordId, { ...row.values }) : null\n\t\tresult.set(operation.id, { pre, post })\n\t\tpre = row && !row.deleted ? post : null\n\t}\n\treturn result\n}\n","import type {\n\tAtomicOp,\n\tFoldState,\n\tHLCTimestamp,\n\tOperation,\n\tOperationTransform,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n\tTimeSource,\n\tVersionVector,\n} from '@korajs/core'\nimport {\n\tHybridLogicalClock,\n\tKoraError,\n\tassertOperationTransformCoverage,\n\tquoteIdent,\n} from '@korajs/core'\nimport { planPostgresConstraintRelaxation } from '@korajs/core/internal'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, desc, eq, gt, inArray, sql } from 'drizzle-orm'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport { UplinkAuthorizationError } from '../scopes/server-scope-filter'\nimport { pgOperations, pgSyncState } from './drizzle-pg-schema'\nimport {\n\tKEY_ID_SAMPLE_ROWS,\n\tenvelopeColumn,\n\tenvelopeKeyIds,\n\tparseEnvelopeColumn,\n} from './envelope-column'\nimport { LEGACY_BODIES_META_KEY, provenLegacyClears } from './legacy-bodies'\nimport {\n\tSERVER_LOG_INTEGRITY_META_KEY,\n\tSERVER_LOG_QUARANTINE_DDL,\n\ttype ServerLogIntegrityReport,\n\ttype ServerOperationRow,\n\tcheckServerOperationRow,\n\tquarantineRowJson,\n} from './log-integrity'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport {\n\ttype KeptRow,\n\ttype QuarantineScope,\n\tbuildQuarantineScope,\n\temptyQuarantineScope,\n\tisQuarantineAffected,\n\tquarantineKey,\n\trebuildFromSnapshot,\n} from './quarantine-base'\nimport {\n\tEMPTY_FOLD_SCHEMA,\n\tFOLD_MIGRATION_BATCH,\n\tFOLD_PLAN_FINGERPRINT_KEY,\n\ttype FoldMigrationReport,\n\tREFOLD_REQUIRED,\n\ttype ServerFoldOptions,\n\tfoldFieldVersions,\n\tmaterializedFieldValue,\n\tmergeIntoFoldState,\n\tparseStoredFoldState,\n\tprojectFoldState,\n\trefoldRecord,\n\tserializeServerFoldState,\n\tserverFoldOptions,\n\tserverFoldPlanFingerprint,\n} from './record-fold'\nimport {\n\tSCOPE_SNAPSHOT_FINGERPRINT_KEY,\n\tparseScopeSnapshot,\n\treplayScopeSnapshots,\n\tscopeSnapshotFingerprint,\n\tscopeValuesOf,\n} from './scope-snapshot'\nimport {\n\ttype AuthorityHistory,\n\ttype ConfiguredIdentity,\n\tSERVER_DEPLOYMENT_ID_KEY,\n\tSERVER_DERIVATION_SECRET_KEY,\n\tSERVER_EVER_AUTHORITY_KEY,\n\tSERVER_INSTANCE_COUNTER_KEY,\n\tSERVER_LEGACY_AUTHORITY_KEY,\n\tSERVER_LEGACY_SCAN_KEY,\n\tSERVER_REVOKED_AUTHORITY_KEY,\n\tServerIdentityError,\n\ttype ServerIdentityOptions,\n\tauthoritativeStampOpIds,\n\tderiveKeyedServerOpId,\n\tgenerateDeploymentId,\n\tgenerateDerivationSecret,\n\tnormalizeLegacyAuthorities,\n\tparseIdentityOptions,\n\tparseLegacyAuthorities,\n\tresolveAuthorityHistory,\n\tserverNodeIdFor,\n} from './server-identity'\nimport type {\n\tApplyRemoteOptions,\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tDeliveredOperation,\n\tEncryptionKeyRecordRow,\n\tMaterializedRecord,\n\tOperationResolution,\n\tOperationResolutionOutcome,\n\tOperationScopeSnapshot,\n\tServerSchemaOptions,\n\tServerStore,\n} from './server-store'\nimport {\n\tMAX_RESOLUTION_MESSAGE_LENGTH,\n\tNODE_SEQ_UNIQUE_INDEX,\n\tRELEASED_NODE_OWNER,\n\tSEQUENCE_ENFORCEMENT_EPOCH_KEY,\n\tSEQUENCE_PAIRS_BACKFILLED_KEY,\n\tSUPERSEDED_NODE_SEQ_UNIQUE_INDEXES,\n\tSequenceConflictError,\n\ttype SequenceHolderVerdict,\n\tUnstorableValueError,\n\tjudgeSequenceHolders,\n\treportLegacyPair,\n} from './server-store'\nimport type { StoredOperationKey } from './server-store'\nimport {\n\tPG_TEXT_CODEC_MIGRATION_KEY,\n\tdeserializePgFieldValue,\n\tencodePgText,\n\tisPgJsonbKind,\n\tisPgRawTextKind,\n\tpgTextCodecMigrationSql,\n\tserializePgFieldValue,\n} from './text-codec'\n\n/** Thrown inside an append transaction to roll it back when the operation is a duplicate. */\nclass DuplicateOperationRollback extends Error {\n\tconstructor() {\n\t\tsuper('duplicate operation; append rolled back')\n\t\tthis.name = 'DuplicateOperationRollback'\n\t}\n}\n\n/** Index every (node, sequence) the log holds more than once (RT-48). */\nconst BACKFILL_SEQUENCE_PAIRS_SQL = `INSERT INTO sequence_pairs (node_id, sequence_number)\n\tSELECT node_id, sequence_number FROM operations\n\tGROUP BY node_id, sequence_number HAVING COUNT(*) > 1\n\tON CONFLICT DO NOTHING`\n\n/**\n * Drop resolutions above their node's restored log, and every `stored-elsewhere`\n * resolution whose operation the restored log does not hold (RT-51; see importBackup).\n */\nconst PRUNE_RESOLUTIONS_PAST_LOG_SQL = `DELETE FROM operation_resolutions r\n\tWHERE r.sequence_number > COALESCE(\n\t\t(SELECT s.max_sequence_number FROM sync_state s WHERE s.node_id = r.node_id), 0)\n\tOR (r.outcome = 'stored-elsewhere'\n\t\tAND NOT EXISTS (SELECT 1 FROM operations o WHERE o.id = r.op_id))`\n\n/** Postgres unique_violation. */\nconst PG_UNIQUE_VIOLATION = '23505'\n\n/** True when `error` (or its drizzle-wrapped cause) is a Postgres unique violation. */\nfunction isUniqueViolation(error: unknown): boolean {\n\tconst codeOf = (value: unknown): unknown =>\n\t\tvalue && typeof value === 'object' && 'code' in value\n\t\t\t? (value as { code: unknown }).code\n\t\t\t: undefined\n\tif (codeOf(error) === PG_UNIQUE_VIOLATION) return true\n\treturn error instanceof Error && codeOf(error.cause) === PG_UNIQUE_VIOLATION\n}\n\n/**\n * Whether a SQLSTATE is a refusal of the DATA (RT-87), never of the server's state:\n * class 22 (data exception: 22021 NUL in TEXT, 22P05 / 22P02 in JSONB, 22003 numeric\n * out of range, 22007 / 22008 datetime, ...) and class 23 (integrity constraint\n * violation: 23514 an enum CHECK, 23502 NOT NULL, ...) except 23505. A unique violation\n * is the signal of a concurrent writer (another instance inserted the same row first):\n * it is transient and retried, never a reason to refuse the operation for good.\n * Such an operation is refused terminally and per operation (UNSTORABLE_VALUE): the ack\n * moves past it and the device's later writes go on.\n */\nfunction isUnstorableValueCode(code: string): boolean {\n\tif (code.startsWith('22')) return true\n\treturn code.startsWith('23') && code !== PG_UNIQUE_VIOLATION\n}\n\n/**\n * Map a Postgres refusal of a value to {@link UnstorableValueError} (non-retriable).\n * The lossless text encoding keeps ordinary strings from reaching this; it is the\n * safety net that keeps any remaining unrepresentable value from failing the session.\n */\nfunction unstorableValueOr(error: unknown, op: Operation): unknown {\n\tconst codeOf = (value: unknown): unknown =>\n\t\tvalue && typeof value === 'object' && 'code' in value\n\t\t\t? (value as { code: unknown }).code\n\t\t\t: undefined\n\tconst code = codeOf(error) ?? (error instanceof Error ? codeOf(error.cause) : undefined)\n\tif (typeof code === 'string' && isUnstorableValueCode(code)) {\n\t\tconst message =\n\t\t\terror instanceof Error\n\t\t\t\t? error.cause instanceof Error\n\t\t\t\t\t? error.cause.message\n\t\t\t\t\t: error.message\n\t\t\t\t: String(error)\n\t\treturn new UnstorableValueError(op, `SQLSTATE ${code}: ${message}`)\n\t}\n\treturn error\n}\n\n/** One record's re-folded state, for {@link PostgresServerStore}'s batched migration writes. */\ninterface FoldedRecordWrite {\n\trecordId: string\n\tstate: FoldState | null\n\tcoveredSeq: number\n\tcoveredOpId: string\n}\n\n/**\n * PostgreSQL-backed server store using Drizzle ORM.\n * All reads and writes go through Drizzle's typed query builder.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class PostgresServerStore implements ServerStore {\n\t/** This instance's server node id; loaded from the database during startup (RT-62). */\n\tprivate loadedNodeId: string | null = null\n\tprivate readonly configuredIdentity: ConfiguredIdentity\n\t/** Derivation secret of server-derived ids, shared by the deployment (RT-64). */\n\tprivate derivationSecret = ''\n\t/** Legacy and configured authorities (the `kora:server:` prefix needs no listing). */\n\tprivate explicitAuthorities: string[] = []\n\t/** Explicit authority over time: revoked and ever-held ids (RT-81). */\n\tprivate authorityHistory: AuthorityHistory = {\n\t\texplicitAuthorities: [],\n\t\trevoked: [],\n\t\teverAuthoritative: [],\n\t}\n\t/** Other `kora:server:` nodes with stored operations (advertised for older clients). */\n\t/** Records owning quarantined operations: folded onto their kept rows (RT-70). */\n\tprivate quarantine: QuarantineScope = emptyQuarantineScope()\n\tprivate readonly db: PostgresJsDatabase\n\tprivate readonly versionVector: VersionVector = new Map()\n\tprivate readonly ready: Promise<void>\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\t/**\n\t * Monotonic counter for this node's server-originated sequence numbers. Lazily\n\t * seeded from the persisted version vector on first use, then advanced in memory\n\t * (a synchronous `++`, atomic on the single JS thread) so concurrent conditional\n\t * applies never receive the same number. Null means \"not yet seeded\"; reset to\n\t * null after a backup import so it re-seeds from the restored version vector.\n\t */\n\tprivate sequenceCounter: number | null = null\n\t/** See {@link SEQUENCE_ENFORCEMENT_EPOCH_KEY}; fixed per database at first start. */\n\tprivate sequenceEpoch = 0\n\tprivate logIntegrity: ServerLogIntegrityReport = {\n\t\tcheckedRows: 0,\n\t\tquarantined: [],\n\t\tran: false,\n\t\ttotalQuarantined: 0,\n\t}\n\t/**\n\t * Time source for HLC timestamps on server-originated operations. Injectable so a\n\t * test can freeze wall-clock time and prove the conditional-apply ordering holds\n\t * under same-millisecond commits (the case the advisory lock and clock advance\n\t * exist to make correct). Defaults to the system clock in production.\n\t */\n\tprivate readonly timeSource: TimeSource\n\tprivate foldOptions: ServerFoldOptions = serverFoldOptions([])\n\t/** Schema transforms the fold applies (transforms at fold time, RT-84). */\n\tprivate operationTransforms: readonly OperationTransform[] = []\n\tprivate foldMigration: FoldMigrationReport = {\n\t\tran: false,\n\t\trecords: 0,\n\t\tskippedUnclean: 0,\n\t\tfullRefold: false,\n\t}\n\n\t/**\n\t * @param db - The Drizzle database\n\t * @param nodeId - Deprecated: a plain id is recorded as a legacy authoritative id; a\n\t * `kora:server:` id is used verbatim (it must then be unique per instance). Leave\n\t * unset: the store authors under `kora:server:<deployment>:<instance>`, with the\n\t * deployment persisted in the database and a distinct instance per process (RT-62).\n\t * @param timeSource - Clock for server-originated operations (tests)\n\t * @param options - Extra authoritative ids and a stable instance id\n\t */\n\tconstructor(\n\t\tdb: PostgresJsDatabase,\n\t\tnodeId?: string,\n\t\ttimeSource?: TimeSource,\n\t\toptions: Omit<ServerIdentityOptions, 'nodeId'> = {},\n\t) {\n\t\tthis.db = db\n\t\tthis.configuredIdentity = parseIdentityOptions({\n\t\t\t...(nodeId !== undefined ? { nodeId } : {}),\n\t\t\t...options,\n\t\t})\n\t\tthis.timeSource = timeSource ?? { now: () => Date.now() }\n\t\tthis.ready = this.initialize()\n\t\t// RT-88: startup runs before anyone awaits it. The failure is not swallowed: every\n\t\t// method awaits `ready` and rejects with it, `whenReady()` returns it, and\n\t\t// createPostgresServerStore awaits it. Without this handler an unreachable\n\t\t// database would be an unhandled rejection, which terminates Node.\n\t\tthis.ready.catch(() => {})\n\t}\n\n\t/** Resolves once the store's tables and identity are loaded. */\n\twhenReady(): Promise<void> {\n\t\treturn this.ready\n\t}\n\n\t/**\n\t * This store's node id and the legacy and configured ids (explicit authorities).\n\t * Other `kora:server:` instances are not listed: the prefix rule makes every one of\n\t * them authoritative, and a list that grew by one instance id per start would make\n\t * every device re-fold after each deploy (RT-75). Handshakes advertise only the\n\t * explicit (non-prefixed) ids.\n\t */\n\tgetAuthoritativeNodeIds(): string[] {\n\t\treturn [this.nodeId, ...this.explicitAuthorities]\n\t}\n\n\t/** Legacy and configured authorities (beside the `kora:server:` namespace). */\n\tgetLegacyAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.explicitAuthorities]\n\t}\n\n\t/** Explicit authoritative ids the deployment revoked (RT-81), advertised at handshake. */\n\tgetRevokedAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.authorityHistory.revoked]\n\t}\n\n\t/**\n\t * Every explicit id the deployment ever held authoritative, revoked ones included\n\t * (RT-81): never accepted as a device node id.\n\t */\n\tgetEverAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.authorityHistory.everAuthoritative]\n\t}\n\n\tasync deriveServerOperationId(\n\t\tparentOpId: string,\n\t\truleId: string,\n\t\ttargetRecordId: string,\n\t): Promise<string> {\n\t\tawait this.ready\n\t\treturn deriveKeyedServerOpId(this.derivationSecret, parentOpId, ruleId, targetRecordId)\n\t}\n\n\tprivate get nodeId(): string {\n\t\tif (this.loadedNodeId === null) {\n\t\t\tthrow new ServerIdentityError(\n\t\t\t\t'The Postgres server store is still starting: await store.setSchema(...) (or store.whenReady()) before using it.',\n\t\t\t)\n\t\t}\n\t\treturn this.loadedNodeId\n\t}\n\n\t/** Remember another `kora:server:` node that authored stored operations. */\n\n\t/**\n\t * Load (creating on first start) the persisted server identity under an advisory\n\t * lock: the deployment id and derivation secret (one per database, shared by every\n\t * instance), a fresh instance id from the database counter (unless configured), and\n\t * the legacy authoritative ids. At the first start of this release, every node id\n\t * whose operations hold an authority class in a stored fold state (a server decision\n\t * folded under an earlier, per-process server node id) is recorded as a legacy\n\t * authority, before any re-fold could drop that class.\n\t */\n\tprivate async loadIdentity(): Promise<void> {\n\t\tconst configured = this.configuredIdentity\n\t\tconst identity = await this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(\n\t\t\t\tsql`SELECT pg_advisory_xact_lock(hashtextextended('kora:server-identity', 0))`,\n\t\t\t)\n\t\t\tconst meta = async (key: string): Promise<string | undefined> =>\n\t\t\t\t(\n\t\t\t\t\t(await tx.execute(\n\t\t\t\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${key}`,\n\t\t\t\t\t)) as unknown as { value: string }[]\n\t\t\t\t)[0]?.value\n\t\t\tconst setOnce = async (key: string, value: string): Promise<string> => {\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${key}, ${value}) ON CONFLICT (key) DO NOTHING`,\n\t\t\t\t)\n\t\t\t\treturn (await meta(key)) ?? value\n\t\t\t}\n\t\t\tconst deploymentId = await setOnce(SERVER_DEPLOYMENT_ID_KEY, generateDeploymentId())\n\t\t\tconst secret = await setOnce(SERVER_DERIVATION_SECRET_KEY, generateDerivationSecret())\n\t\t\tlet instanceId = configured.instanceId\n\t\t\tif (instanceId === null) {\n\t\t\t\t// Every process start draws a new instance id, so two running instances never\n\t\t\t\t// share a node id (and never collide on its sequence numbers).\n\t\t\t\tawait setOnce(SERVER_INSTANCE_COUNTER_KEY, '0')\n\t\t\t\tconst next = (await tx.execute(\n\t\t\t\t\tsql`UPDATE kora_server_meta SET value = ((value)::bigint + 1)::text WHERE key = ${SERVER_INSTANCE_COUNTER_KEY} RETURNING value`,\n\t\t\t\t)) as unknown as { value: string }[]\n\t\t\t\tinstanceId = String(next[0]?.value ?? '1')\n\t\t\t}\n\t\t\tconst nodeId = configured.verbatimNodeId ?? serverNodeIdFor(deploymentId, instanceId)\n\n\t\t\tlet legacy = parseLegacyAuthorities(await meta(SERVER_LEGACY_AUTHORITY_KEY))\n\t\t\tif ((await meta(SERVER_LEGACY_SCAN_KEY)) === undefined) {\n\t\t\t\tconst stampOpIds = new Set<string>()\n\t\t\t\tlet after = ''\n\t\t\t\tlet afterRecord = ''\n\t\t\t\tfor (;;) {\n\t\t\t\t\tconst page = (await tx.execute(\n\t\t\t\t\t\tsql`SELECT collection, record_id, state FROM kora_fold_state\n\t\t\t\t\t\t\tWHERE (collection, record_id) > (${after}, ${afterRecord})\n\t\t\t\t\t\t\tORDER BY collection, record_id LIMIT 1000`,\n\t\t\t\t\t)) as unknown as { collection: string; record_id: string; state: string }[]\n\t\t\t\t\tfor (const row of page) {\n\t\t\t\t\t\tfor (const id of authoritativeStampOpIds(row.state)) stampOpIds.add(id)\n\t\t\t\t\t}\n\t\t\t\t\tconst last = page[page.length - 1]\n\t\t\t\t\tif (!last || page.length < 1000) break\n\t\t\t\t\tafter = last.collection\n\t\t\t\t\tafterRecord = last.record_id\n\t\t\t\t}\n\t\t\t\tconst ids = [...stampOpIds]\n\t\t\t\tfor (let i = 0; i < ids.length; i += 500) {\n\t\t\t\t\tconst chunk = ids.slice(i, i + 500)\n\t\t\t\t\tconst rows = (await tx.execute(\n\t\t\t\t\t\tsql`SELECT DISTINCT node_id FROM operations WHERE id IN (${sql.join(\n\t\t\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`,\n\t\t\t\t\t)) as unknown as { node_id: string }[]\n\t\t\t\t\tlegacy.push(...rows.map((row) => row.node_id))\n\t\t\t\t}\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${SERVER_LEGACY_SCAN_KEY}, ${String(Date.now())}) ON CONFLICT (key) DO NOTHING`,\n\t\t\t\t)\n\t\t\t}\n\t\t\t// A configured plain node id is the id this server authored under before (RT-62).\n\t\t\tif (configured.legacyNodeId !== null) legacy.push(configured.legacyNodeId)\n\t\t\tlegacy = normalizeLegacyAuthorities(legacy.filter((id) => id !== nodeId))\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${SERVER_LEGACY_AUTHORITY_KEY}, ${JSON.stringify(legacy)})\n\t\t\t\t\tON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,\n\t\t\t)\n\t\t\t// Authority over time (RT-81), under the same lock: every explicit id ever held\n\t\t\t// stays authoritative until revoked, and reserved for good.\n\t\t\tconst history = resolveAuthorityHistory({\n\t\t\t\tlegacy,\n\t\t\t\tconfigured,\n\t\t\t\tpersistedEver: parseLegacyAuthorities(await meta(SERVER_EVER_AUTHORITY_KEY)),\n\t\t\t\tpersistedRevoked: parseLegacyAuthorities(await meta(SERVER_REVOKED_AUTHORITY_KEY)),\n\t\t\t\townNodeId: nodeId,\n\t\t\t})\n\t\t\tfor (const [key, value] of [\n\t\t\t\t[SERVER_EVER_AUTHORITY_KEY, history.everAuthoritative],\n\t\t\t\t[SERVER_REVOKED_AUTHORITY_KEY, history.revoked],\n\t\t\t] as const) {\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${key}, ${JSON.stringify(value)})\n\t\t\t\t\t\tON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn { secret, nodeId, history }\n\t\t})\n\t\tthis.loadedNodeId = identity.nodeId\n\t\tthis.derivationSecret = identity.secret\n\t\tthis.explicitAuthorities = identity.history.explicitAuthorities\n\t\tthis.authorityHistory = identity.history\n\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t}\n\n\t/** What the last startup re-materialization did (W7 step 7). */\n\tgetFoldMigrationReport(): FoldMigrationReport {\n\t\treturn { ...this.foldMigration }\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\treturn new Map(this.versionVector)\n\t}\n\n\t/**\n\t * Atomically reserve this node's next server-operation sequence number. The\n\t * synchronous increment cannot interleave on the single JS thread, so two\n\t * concurrent conditional applies are always handed distinct numbers.\n\t */\n\treserveSequenceNumber(): number {\n\t\tif (this.sequenceCounter === null) {\n\t\t\tthis.sequenceCounter = this.versionVector.get(this.nodeId) ?? 0\n\t\t}\n\t\tthis.sequenceCounter += 1\n\t\treturn this.sequenceCounter\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\t/**\n\t * One-time migration (RT-101): drop the enum `CHECK` constraints (and any `NOT NULL`\n\t * on a schema field) that beta.12 and earlier DDL put on collection tables, in one\n\t * transaction. A check is dropped when it parses as an enum check (one column against\n\t * string literals, in every form Postgres normalizes `IN (...)` to, the single-value\n\t * `col = 'x'` included, RT-108) on an enum field of the schema, or as the multi-value\n\t * `= ANY (ARRAY[...])` shape on another non-internal column; checks added by hand are\n\t * kept. Idempotent and resumable: a later start finds nothing to drop.\n\t */\n\tprivate async relaxValueDomainConstraints(schema: SchemaDefinition): Promise<void> {\n\t\tconst fieldsByTable: Record<string, string[]> = {}\n\t\tconst enumFieldsByTable: Record<string, string[]> = {}\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tfieldsByTable[name] = Object.keys(collection.fields)\n\t\t\tenumFieldsByTable[name] = Object.entries(collection.fields)\n\t\t\t\t.filter(([, descriptor]) => descriptor.kind === 'enum')\n\t\t\t\t.map(([field]) => field)\n\t\t}\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tconst statements = await planPostgresConstraintRelaxation(\n\t\t\t\tasync (text) =>\n\t\t\t\t\t(await tx.execute(sql.raw(text))) as unknown as Array<Record<string, unknown>>,\n\t\t\t\tfieldsByTable,\n\t\t\t\tenumFieldsByTable,\n\t\t\t)\n\t\t\tfor (const statement of statements) await tx.execute(sql.raw(statement))\n\t\t})\n\t}\n\n\t/**\n\t * Throws {@link OperationTransformCoverageError} when a schema version in the stored\n\t * log has no transform path to `version` (RT-103): those operations would fold as\n\t * absent, silently erasing them from their records.\n\t */\n\tprivate async assertTransformCoverage(\n\t\tversion: number,\n\t\ttransforms: readonly OperationTransform[],\n\t): Promise<void> {\n\t\tif (transforms.length === 0) return\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT DISTINCT schema_version AS v FROM operations`,\n\t\t)) as unknown as { v: number | string }[]\n\t\tassertOperationTransformCoverage(\n\t\t\trows.map((row) => Number(row.v)),\n\t\t\tversion,\n\t\t\ttransforms,\n\t\t\t'Postgres server store',\n\t\t)\n\t}\n\n\tgetOperationTransforms(): readonly OperationTransform[] {\n\t\treturn this.operationTransforms\n\t}\n\n\tasync setOperationTransforms(transforms: readonly OperationTransform[]): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tif (this.schema) await this.assertTransformCoverage(this.schema.version, transforms)\n\t\tthis.operationTransforms = [...transforms]\n\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t\t// The fold plan fingerprint includes the transforms: when they changed, every\n\t\t// record is re-folded from its log, once (RT-84).\n\t\tif (this.schema) this.foldMigration = await this.rematerialize()\n\t}\n\n\tasync setSchema(schema: SchemaDefinition, options: ServerSchemaOptions = {}): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\t// Refuse transforms that cannot read the stored log BEFORE anything changes (RT-103).\n\t\tawait this.assertTransformCoverage(\n\t\t\tschema.version,\n\t\t\toptions.operationTransforms ?? this.operationTransforms,\n\t\t)\n\t\tthis.schema = schema\n\t\tif (options.operationTransforms !== undefined) {\n\t\t\tthis.operationTransforms = [...options.operationTransforms]\n\t\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t\t}\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'postgres')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tawait this.db.execute(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"already exists\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps the actual DB error in e.cause, so check both.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (\n\t\t\t\t\t\t!msg.includes('already exists') &&\n\t\t\t\t\t\t!msg.includes('duplicate column') &&\n\t\t\t\t\t\t!causeMsg.includes('already exists') &&\n\t\t\t\t\t\t!causeMsg.includes('duplicate column')\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait this.db.execute(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// beta.12 tables carry enum CHECKs a schema upgrade cannot change: drop them once\n\t\t// (RT-101); the value domain is enforced at ingest only.\n\t\tawait this.relaxValueDomainConstraints(schema)\n\t\tawait this.migrateTextCodec(schema)\n\n\t\t// beta.12 clears stored by an earlier server, made explicit once (RT-85); their\n\t\t// records are re-folded by the re-materialization below.\n\t\tawait this.canonicalizeLegacyBodies()\n\t\t// Re-materialize every record whose fold state is missing or stale (W7 step 7).\n\t\tthis.foldMigration = await this.rematerialize()\n\t\t// A change in the fields snapshots capture invalidates every snapshot: drop them\n\t\t// and rebuild from the log (RT-20). The fingerprint is written last, so a crash\n\t\t// (or a concurrent instance) only repeats the idempotent rebuild.\n\t\tconst fingerprint = scopeSnapshotFingerprint(schema)\n\t\tconst metaRows = (await this.db.execute(\n\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${SCOPE_SNAPSHOT_FINGERPRINT_KEY}`,\n\t\t)) as unknown as { value: string }[]\n\t\tconst stored = metaRows[0]?.value\n\t\tif (stored !== fingerprint) {\n\t\t\tawait this.db.execute(sql`UPDATE operations SET scope_snapshot = NULL`)\n\t\t}\n\t\tawait this.backfillScopeSnapshots()\n\t\tif (stored !== fingerprint) {\n\t\t\tawait this.db.execute(\n\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${SCOPE_SNAPSHOT_FINGERPRINT_KEY}, ${fingerprint})\n\t\t\t\t\tON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * One-time migration of each collection table to the lossless text encoding (RT-65):\n\t * rows written before it that contain U+FFFF (the escape introducer) are re-encoded,\n\t * so the decoder returns them unchanged. Per table, under an advisory lock, recorded\n\t * in `kora_server_meta`.\n\t */\n\tprivate async migrateTextCodec(schema: SchemaDefinition): Promise<void> {\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tconst key = `${PG_TEXT_CODEC_MIGRATION_KEY}${name}`\n\t\t\tawait this.db.transaction(async (tx) => {\n\t\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended('kora:text-codec', 0))`)\n\t\t\t\tconst done = (await tx.execute(\n\t\t\t\t\tsql`SELECT 1 AS one FROM kora_server_meta WHERE key = ${key}`,\n\t\t\t\t)) as unknown as unknown[]\n\t\t\t\tif (done.length > 0) return\n\t\t\t\tconst fields = Object.entries(collection.fields)\n\t\t\t\tconst statements = pgTextCodecMigrationSql(\n\t\t\t\t\tquoteIdent(name),\n\t\t\t\t\tfields.filter(([, d]) => isPgRawTextKind(d.kind)).map(([f]) => quoteIdent(f)),\n\t\t\t\t\tfields.filter(([, d]) => isPgJsonbKind(d.kind)).map(([f]) => quoteIdent(f)),\n\t\t\t\t)\n\t\t\t\tfor (const statement of statements) await tx.execute(sql.raw(statement))\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${key}, ${String(Date.now())}) ON CONFLICT (key) DO NOTHING`,\n\t\t\t\t)\n\t\t\t})\n\t\t}\n\t}\n\n\tasync applyRemoteOperation(op: Operation, options?: ApplyRemoteOptions): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst now = Date.now()\n\t\tlet sequenceDecision: SequenceHolderVerdict = { verdict: 'free' }\n\n\t\ttry {\n\t\t\tawait this.db.transaction(async (tx) => {\n\t\t\t\t// Take the delivery-counter row lock first (see nextDeliverySeq). Every append\n\t\t\t\t// on every instance, conditional applies included, takes it until commit, so\n\t\t\t\t// from here on every earlier append is committed and visible to this READ\n\t\t\t\t// COMMITTED transaction, and no later one can commit before it. That makes\n\t\t\t\t// the dedup and sequence checks below atomic with the write across instances\n\t\t\t\t// (SRV-4): a concurrent duplicate on another instance either committed first\n\t\t\t\t// (and is seen here) or waits for this one. A duplicate rolls back, so it\n\t\t\t\t// neither burns a delivery sequence nor runs any side effect (NEW-SRV-2).\n\t\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\n\t\t\t\tconst inserted = await this.insertOperationRow(tx, op, now, deliverySeq, {\n\t\t\t\t\tlegacySequenceWriter: options?.legacySequenceWriter === true,\n\t\t\t\t})\n\t\t\t\tif (inserted === 'duplicate') throw new DuplicateOperationRollback()\n\t\t\t\tsequenceDecision = inserted\n\n\t\t\t\t// Authorization re-check against the committed row, under the same lock, so\n\t\t\t\t// no write can commit between this read and this transaction's write.\n\t\t\t\t// Throwing rolls back, the operation row included.\n\t\t\t\tif (options?.authorize) {\n\t\t\t\t\tconst stored = await this.readStoredRow(tx, op.collection, op.recordId)\n\t\t\t\t\tconst decision = options.authorize(stored)\n\t\t\t\t\tif (!decision.allowed) {\n\t\t\t\t\t\tthrow new UplinkAuthorizationError(decision.code, decision.message, {\n\t\t\t\t\t\t\toperationId: op.id,\n\t\t\t\t\t\t\tcollection: op.collection,\n\t\t\t\t\t\t\trecordId: op.recordId,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst materialized = this.schema?.collections[op.collection] !== undefined\n\t\t\t\tconst pre = materialized\n\t\t\t\t\t? await this.readScopeValues(tx, op.collection, op.recordId, false)\n\t\t\t\t\t: null\n\n\t\t\t\tawait this.advanceSyncState(tx, op, now)\n\n\t\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\t\tif (materialized) {\n\t\t\t\t\tawait this.mergeIntoRecord(tx, op, deliverySeq)\n\t\t\t\t\tawait this.writeScopeSnapshot(tx, op, pre)\n\t\t\t\t}\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tif (error instanceof DuplicateOperationRollback) return 'duplicate'\n\t\t\tthrow unstorableValueOr(error, op)\n\t\t}\n\n\t\t// Keep this instance's cached vector current for its synchronous readers. The\n\t\t// authoritative, cross-instance vector is readVersionVector().\n\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentMax) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\treportLegacyPair(op, sequenceDecision, options)\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * The version vector as committed in `sync_state`, shared by every instance\n\t * (SRV-4). Also refreshes this instance's cache, which `getVersionVector()` serves.\n\t */\n\tasync readVersionVector(): Promise<VersionVector> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = await this.db\n\t\t\t.select({\n\t\t\t\tnodeId: pgSyncState.nodeId,\n\t\t\t\tmaxSequenceNumber: pgSyncState.maxSequenceNumber,\n\t\t\t})\n\t\t\t.from(pgSyncState)\n\t\tconst vector: VersionVector = new Map()\n\t\tfor (const row of rows) {\n\t\t\tconst seq = Number(row.maxSequenceNumber)\n\t\t\tvector.set(row.nodeId, seq)\n\t\t\tif (seq > (this.versionVector.get(row.nodeId) ?? 0)) this.versionVector.set(row.nodeId, seq)\n\t\t}\n\t\treturn vector\n\t}\n\n\t/**\n\t * Insert one operation row inside an append transaction that already holds the\n\t * delivery-counter lock. Returns `'duplicate'` (writing nothing) when an operation\n\t * with the same id is stored; throws {@link SequenceConflictError} when a DIFFERENT\n\t * operation stored after the sequence-enforcement epoch holds its (node, sequence)\n\t * and the writer reserves its sequences (W3 step 4); a legacy holder or a legacy\n\t * writer (RT-37) is accepted and the row is stored unflagged. Otherwise returns the\n\t * verdict the row was stored under. The partial unique index over sole-holder rows\n\t * backs the check against a writer that bypasses the counter lock.\n\t */\n\tprivate async insertOperationRow(\n\t\ttx: PostgresJsDatabase,\n\t\top: Operation,\n\t\tnow: number,\n\t\tdeliverySeq: number,\n\t\twriter: { legacySequenceWriter?: boolean } = {},\n\t): Promise<Exclude<SequenceHolderVerdict, { verdict: 'conflict' }> | 'duplicate'> {\n\t\tconst holders = (await tx.execute(\n\t\t\tsql`SELECT id, delivery_seq FROM operations WHERE node_id = ${op.nodeId} AND sequence_number = ${op.sequenceNumber}`,\n\t\t)) as unknown as { id: string; delivery_seq: string | number | null }[]\n\t\t// Already stored (a legacy pair may hold the sequence twice: check every holder).\n\t\tif (holders.some((row) => row.id === op.id)) return 'duplicate'\n\t\tconst decision = judgeSequenceHolders(\n\t\t\top,\n\t\t\tholders.map((row) => ({ id: row.id, deliverySequence: Number(row.delivery_seq ?? 0) })),\n\t\t\tthis.sequenceEpoch,\n\t\t\twriter,\n\t\t)\n\t\tif (decision.verdict === 'conflict') {\n\t\t\tthrow new SequenceConflictError(op, decision.holderId)\n\t\t}\n\t\tconst holder = holders[0]\n\t\ttry {\n\t\t\tconst inserted = await tx\n\t\t\t\t.insert(pgOperations)\n\t\t\t\t.values(this.serializeOperation(op, now, deliverySeq, decision.verdict === 'free'))\n\t\t\t\t.onConflictDoNothing({ target: pgOperations.id })\n\t\t\t\t.returning({ id: pgOperations.id })\n\t\t\tif (inserted.length === 0) return 'duplicate'\n\t\t\t// A legacy pair: index its sequence so version-vector clients get both (RT-48).\n\t\t\tif (decision.verdict === 'legacy') {\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql`INSERT INTO sequence_pairs (node_id, sequence_number) VALUES (${op.nodeId}, ${op.sequenceNumber})\n\t\t\t\t\t\tON CONFLICT DO NOTHING`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn decision\n\t\t} catch (error) {\n\t\t\tif (isUniqueViolation(error)) {\n\t\t\t\tthrow new SequenceConflictError(op, holder?.id ?? '(unknown)')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/** Advance `sync_state` (the persisted version vector) for an appended operation. */\n\tprivate async advanceSyncState(\n\t\ttx: PostgresJsDatabase,\n\t\top: Operation,\n\t\tnow: number,\n\t): Promise<void> {\n\t\tawait tx\n\t\t\t.insert(pgSyncState)\n\t\t\t.values({\n\t\t\t\tnodeId: op.nodeId,\n\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\tlastSeenAt: now,\n\t\t\t})\n\t\t\t.onConflictDoUpdate({\n\t\t\t\ttarget: pgSyncState.nodeId,\n\t\t\t\tset: {\n\t\t\t\t\tmaxSequenceNumber: sql`GREATEST(${pgSyncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t},\n\t\t\t})\n\t}\n\n\t/**\n\t * Conditionally apply operations atomically, serialized across server instances\n\t * on the target record via a transaction-scoped advisory lock. The lock makes\n\t * the read-decide-write cycle atomic against concurrent instances, so a cap\n\t * check like `responseCount < max` cannot be passed by two admissions at once.\n\t */\n\tasync applyConditional(input: ConditionalApplyInput): Promise<ConditionalApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(input.target.collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[input.target.collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst lockKey = `kora:${input.target.collection}:${input.target.id}`\n\n\t\tlet attempted: Operation | null = null\n\t\tconst result = await this.db\n\t\t\t.transaction(async (tx) => {\n\t\t\t\t// Serialize this target across every server instance sharing the database.\n\t\t\t\t// hashtextextended maps the key to the bigint pg_advisory_xact_lock expects;\n\t\t\t\t// the lock releases automatically when the transaction ends.\n\t\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended(${lockKey}, 0))`)\n\t\t\t\t// Also take the delivery-counter row lock now (every append takes it until\n\t\t\t\t// commit), so the reads below, including the authorization reads of the\n\t\t\t\t// built operations, see every earlier commit and no append can commit\n\t\t\t\t// between them and this transaction's writes. Lock order (advisory, then\n\t\t\t\t// counter) matches every other path, so this cannot deadlock.\n\t\t\t\tawait tx.execute(sql`SELECT value FROM delivery_counter WHERE id = 1 FOR UPDATE`)\n\n\t\t\t\t// Idempotency: if the key record already exists (from an earlier attempt),\n\t\t\t\t// this set is already committed. Checked under the lock so a retry racing a\n\t\t\t\t// first attempt on another instance still resolves to at-most-once.\n\t\t\t\tif (input.idempotencyKey) {\n\t\t\t\t\tconst existing = (await tx.execute(\n\t\t\t\t\t\tsql`SELECT 1 FROM ${sql.raw(quoteIdent(input.idempotencyKey.collection))} WHERE id = ${input.idempotencyKey.id} AND _deleted = 0 LIMIT 1`,\n\t\t\t\t\t)) as unknown as unknown[]\n\t\t\t\t\tif (existing.length > 0) {\n\t\t\t\t\t\treturn { admitted: true, idempotent: true, applied: [] as Operation[] }\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst rows = (await tx.execute(\n\t\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(input.target.collection))} WHERE id = ${input.target.id} AND _deleted = 0`,\n\t\t\t\t)) as unknown as Record<string, unknown>[]\n\t\t\t\tconst current =\n\t\t\t\t\trows.length > 0\n\t\t\t\t\t\t? this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t\t\t\t\t\t: null\n\n\t\t\t\tif (!input.admit(current)) {\n\t\t\t\t\treturn { admitted: false, idempotent: false, applied: [] as Operation[] }\n\t\t\t\t}\n\n\t\t\t\t// Seed a clock past the target record's latest committed operation so the\n\t\t\t\t// operations built next sort strictly after every prior write to it. Under\n\t\t\t\t// the advisory lock this makes last-write-wins materialization agree with the\n\t\t\t\t// serialized commit order, so a same-millisecond commit on another instance\n\t\t\t\t// cannot cause the counter to be undercounted (which would admit past a cap).\n\t\t\t\tconst clock = new HybridLogicalClock(this.nodeId, this.timeSource)\n\t\t\t\tconst latest = await this.latestOperationTimestamp(\n\t\t\t\t\ttx,\n\t\t\t\t\tinput.target.collection,\n\t\t\t\t\tinput.target.id,\n\t\t\t\t)\n\t\t\t\tif (latest) {\n\t\t\t\t\tclock.advanceTo(latest)\n\t\t\t\t}\n\n\t\t\t\tconst ops = await input.buildOperations(current, {\n\t\t\t\t\tclock,\n\t\t\t\t\treadStoredRow: (collection, id) => this.readStoredRow(tx, collection, id),\n\t\t\t\t})\n\t\t\t\tconst now = Date.now()\n\t\t\t\tfor (const op of ops) {\n\t\t\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\t\t\t\t\tconst materialized = this.schema?.collections[op.collection] !== undefined\n\t\t\t\t\tconst pre = materialized\n\t\t\t\t\t\t? await this.readScopeValues(tx, op.collection, op.recordId, false)\n\t\t\t\t\t\t: null\n\t\t\t\t\t// A built operation is new by construction (fresh id, reserved sequence); a\n\t\t\t\t\t// duplicate would mean it is already committed, so it is not written twice.\n\t\t\t\t\tattempted = op\n\t\t\t\t\tif ((await this.insertOperationRow(tx, op, now, deliverySeq)) === 'duplicate') continue\n\t\t\t\t\tawait this.advanceSyncState(tx, op, now)\n\t\t\t\t\tif (materialized) {\n\t\t\t\t\t\tawait this.mergeIntoRecord(tx, op, deliverySeq)\n\t\t\t\t\t\tawait this.writeScopeSnapshot(tx, op, pre)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { admitted: true, idempotent: false, applied: ops }\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tthrow attempted ? unstorableValueOr(error, attempted) : error\n\t\t\t})\n\n\t\t// Advance the in-memory version vector cache after commit.\n\t\tfor (const op of result.applied) {\n\t\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\t\tif (op.sequenceNumber > currentMax) {\n\t\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(\n\t\t\t\tand(eq(pgOperations.nodeId, nodeId), between(pgOperations.sequenceNumber, fromSeq, toSeq)),\n\t\t\t)\n\t\t\t.orderBy(asc(pgOperations.sequenceNumber))\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst result = await this.db.select({ value: count() }).from(pgOperations)\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT COALESCE(MAX(delivery_seq), 0) AS m FROM operations`,\n\t\t)) as unknown as { m: number | string | bigint }[]\n\t\treturn Number(rows[0]?.m ?? 0)\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(gt(pgOperations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(pgOperations.deliverySeq))\n\t\t\t.limit(limit)\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t\tscopeSnapshot: parseScopeSnapshot(row.scopeSnapshot),\n\t\t}))\n\t}\n\n\tasync getOperationScopeSnapshots(\n\t\toperationIds: string[],\n\t): Promise<Map<string, OperationScopeSnapshot>> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst result = new Map<string, OperationScopeSnapshot>()\n\t\tfor (let i = 0; i < operationIds.length; i += 500) {\n\t\t\tconst ids = operationIds.slice(i, i + 500)\n\t\t\tif (ids.length === 0) continue\n\t\t\tconst rows = (await this.db.execute(\n\t\t\t\tsql`SELECT id, scope_snapshot FROM operations WHERE id IN (${sql.join(\n\t\t\t\t\tids.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)) as unknown as { id: string; scope_snapshot: string | null }[]\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst snapshot = parseScopeSnapshot(row.scope_snapshot)\n\t\t\t\tif (snapshot) result.set(row.id, snapshot)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync getRecordLatestTimestamp(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<HLCTimestamp | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\t// COLLATE \"C\" so the node-id tie-break is the same byte order as HLC.compare.\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT wall_time, logical, timestamp_node_id FROM operations\n\t\t\t\tWHERE collection = ${collection} AND record_id = ${recordId}\n\t\t\t\tORDER BY wall_time DESC, logical DESC, timestamp_node_id COLLATE \"C\" DESC LIMIT 1`,\n\t\t)) as unknown as { wall_time: number | string; logical: number; timestamp_node_id: string }[]\n\t\tconst row = rows[0]\n\t\treturn row\n\t\t\t? {\n\t\t\t\t\twallTime: Number(row.wall_time),\n\t\t\t\t\tlogical: Number(row.logical),\n\t\t\t\t\tnodeId: row.timestamp_node_id,\n\t\t\t\t}\n\t\t\t: null\n\t}\n\n\tasync getRecordFieldVersions(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<RecordFieldVersions | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\treturn foldFieldVersions(await this.readFoldState(this.db, collection, recordId))\n\t}\n\n\tasync getRecordFoldState(collection: string, recordId: string): Promise<FoldState | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\treturn this.readFoldState(this.db, collection, recordId)\n\t}\n\n\tasync getRecordOperations(collection: string, recordId: string): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\treturn this.readRecordOperations(this.db, collection, recordId, 0)\n\t}\n\n\tasync previewOperation(op: Operation): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst schema = this.schema ?? EMPTY_FOLD_SCHEMA\n\t\tconst current = await this.readFoldState(this.db, op.collection, op.recordId)\n\t\tconst merged = mergeIntoFoldState(current, [op], schema, this.foldOptions)\n\t\tconst state =\n\t\t\tmerged === REFOLD_REQUIRED\n\t\t\t\t? refoldRecord(\n\t\t\t\t\t\t[...(await this.readRecordOperations(this.db, op.collection, op.recordId, 0)), op],\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\tthis.foldOptions,\n\t\t\t\t\t)\n\t\t\t\t: merged\n\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\tif (!row || row.deleted) return null\n\t\treturn { ...row.values, id: op.recordId }\n\t}\n\n\tasync recordBlobOwner(hash: string, owner: string): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tawait this.db.execute(\n\t\t\tsql`INSERT INTO blob_owners (hash, owner, created_at) VALUES (${hash}, ${owner}, ${Date.now()})\n\t\t\t\tON CONFLICT (hash, owner) DO NOTHING`,\n\t\t)\n\t}\n\n\tasync getBlobOwners(hashes: string[]): Promise<Map<string, string[]>> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst result = new Map<string, string[]>(hashes.map((hash) => [hash, []]))\n\t\tfor (let i = 0; i < hashes.length; i += 500) {\n\t\t\tconst slice = hashes.slice(i, i + 500)\n\t\t\tif (slice.length === 0) continue\n\t\t\tconst rows = (await this.db.execute(\n\t\t\t\tsql`SELECT hash, owner FROM blob_owners WHERE hash IN (${sql.join(\n\t\t\t\t\tslice.map((hash) => sql`${hash}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)) as unknown as { hash: string; owner: string }[]\n\t\t\tfor (const row of rows) result.get(row.hash)?.push(row.owner)\n\t\t}\n\t\treturn result\n\t}\n\n\tasync claimBlobIfUnowned(hash: string, owner: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\t// A transaction-scoped advisory lock per hash makes \"insert when nobody owns it\"\n\t\t// atomic across instances (two concurrent first claims cannot both win).\n\t\treturn this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(\n\t\t\t\tsql`SELECT pg_advisory_xact_lock(hashtextextended(${`kora:blob:${hash}`}, 0))`,\n\t\t\t)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO blob_owners (hash, owner, created_at)\n\t\t\t\t\tSELECT ${hash}, ${owner}, ${Date.now()}\n\t\t\t\t\tWHERE NOT EXISTS (SELECT 1 FROM blob_owners WHERE hash = ${hash})\n\t\t\t\t\tON CONFLICT (hash, owner) DO NOTHING`,\n\t\t\t)\n\t\t\tconst rows = (await tx.execute(\n\t\t\t\tsql`SELECT 1 AS one FROM blob_owners WHERE hash = ${hash} AND owner = ${owner} LIMIT 1`,\n\t\t\t)) as unknown as unknown[]\n\t\t\treturn rows.length > 0\n\t\t})\n\t}\n\n\t/**\n\t * Scope values of a record as stored, for an operation's scope snapshot. With\n\t * `includeDeleted` false a soft-deleted row counts as absent; with true it keeps\n\t * its last values (a delete's post-image).\n\t */\n\tprivate async readScopeValues(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tincludeDeleted: boolean,\n\t): Promise<Record<string, unknown> | null> {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return null\n\t\tconst rows = (await txOrDb.execute(\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${recordId} LIMIT 1`,\n\t\t)) as unknown as Record<string, unknown>[]\n\t\tconst row = rows[0]\n\t\tif (!row) return null\n\t\tif (!includeDeleted && Number(row._deleted) === 1) return null\n\t\treturn scopeValuesOf(this.schema, collection, recordId, this.deserializeRow(row, collectionDef))\n\t}\n\n\t/** Persist the scope snapshot of a just-applied operation (RT-14). */\n\tprivate async writeScopeSnapshot(\n\t\ttx: PostgresJsDatabase,\n\t\top: Operation,\n\t\tpre: Record<string, unknown> | null,\n\t): Promise<void> {\n\t\tconst snapshot: OperationScopeSnapshot = {\n\t\t\tpre,\n\t\t\tpost: await this.readScopeValues(tx, op.collection, op.recordId, true),\n\t\t}\n\t\tawait tx.execute(\n\t\t\tsql`UPDATE operations SET scope_snapshot = ${JSON.stringify(snapshot)} WHERE id = ${op.id}`,\n\t\t)\n\t}\n\n\t/**\n\t * Rebuild missing scope snapshots from the log (migration from a database written\n\t * before snapshots existed), replaying each affected record in commit order.\n\t */\n\tprivate async backfillScopeSnapshots(): Promise<void> {\n\t\tconst schema = this.schema\n\t\tif (!schema) return\n\t\tconst pending = (await this.db.execute(\n\t\t\tsql`SELECT DISTINCT collection, record_id FROM operations WHERE scope_snapshot IS NULL`,\n\t\t)) as unknown as { collection: string; record_id: string }[]\n\t\tconst byCollection = new Map<string, string[]>()\n\t\tfor (const row of pending) {\n\t\t\tif (schema.collections[row.collection] === undefined) continue\n\t\t\tconst ids = byCollection.get(row.collection)\n\t\t\tif (ids) ids.push(row.record_id)\n\t\t\telse byCollection.set(row.collection, [row.record_id])\n\t\t}\n\t\t// Records in chunks: one read of their operations and one batched update per\n\t\t// chunk, instead of a statement per record and per operation.\n\t\tfor (const [collection, recordIds] of byCollection) {\n\t\t\tfor (let i = 0; i < recordIds.length; i += FOLD_MIGRATION_BATCH) {\n\t\t\t\tconst chunk = recordIds.slice(i, i + FOLD_MIGRATION_BATCH)\n\t\t\t\tconst rows = await this.db\n\t\t\t\t\t.select()\n\t\t\t\t\t.from(pgOperations)\n\t\t\t\t\t.where(\n\t\t\t\t\t\tand(eq(pgOperations.collection, collection), inArray(pgOperations.recordId, chunk)),\n\t\t\t\t\t)\n\t\t\t\t\t.orderBy(asc(pgOperations.deliverySeq))\n\t\t\t\tconst byRecord = new Map<string, Array<(typeof rows)[number]>>()\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst list = byRecord.get(row.recordId)\n\t\t\t\t\tif (list) list.push(row)\n\t\t\t\t\telse byRecord.set(row.recordId, [row])\n\t\t\t\t}\n\t\t\t\tconst updates: Array<[string, string]> = []\n\t\t\t\tfor (const [recordId, recordRows] of byRecord) {\n\t\t\t\t\tconst replayed = replayScopeSnapshots(\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\trecordId,\n\t\t\t\t\t\trecordRows.map((row) => this.deserializeOperation(row)),\n\t\t\t\t\t\tthis.foldOptions,\n\t\t\t\t\t)\n\t\t\t\t\tfor (const row of recordRows) {\n\t\t\t\t\t\tif (row.scopeSnapshot !== null) continue\n\t\t\t\t\t\tconst snapshot = replayed.get(row.id)\n\t\t\t\t\t\tif (snapshot) updates.push([row.id, JSON.stringify(snapshot)])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (let j = 0; j < updates.length; j += 1000) {\n\t\t\t\t\tconst values = updates\n\t\t\t\t\t\t.slice(j, j + 1000)\n\t\t\t\t\t\t.map(([id, snapshot]) => sql`(${id}, ${snapshot})`)\n\t\t\t\t\t// Only fill a still-empty column: a concurrent apply's own snapshot wins.\n\t\t\t\t\tawait this.db.execute(\n\t\t\t\t\t\tsql`UPDATE operations AS o SET scope_snapshot = v.s\n\t\t\t\t\t\t\tFROM (VALUES ${sql.join(values, sql.raw(', '))}) AS v(id, s)\n\t\t\t\t\t\t\tWHERE o.id = v.id AND o.scope_snapshot IS NULL`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync getNodeIdsAfterDelivery(afterDeliverySequence: number): Promise<string[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT DISTINCT node_id FROM operations WHERE delivery_seq > ${afterDeliverySequence}`,\n\t\t)) as unknown as { node_id: string }[]\n\t\treturn rows.map((row) => row.node_id)\n\t}\n\n\tasync getSequencePairOperations(nodeId: string, throughSequence: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(\n\t\t\t\tand(\n\t\t\t\t\teq(pgOperations.nodeId, nodeId),\n\t\t\t\t\tsql`${pgOperations.sequenceNumber} IN (SELECT sequence_number FROM sequence_pairs WHERE node_id = ${nodeId} AND sequence_number <= ${throughSequence})`,\n\t\t\t\t),\n\t\t\t)\n\t\t\t.orderBy(asc(pgOperations.sequenceNumber), asc(pgOperations.deliverySeq))\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync recordOperationResolution(resolution: OperationResolution): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tawait this.db.execute(\n\t\t\tsql`INSERT INTO operation_resolutions\n\t\t\t\t(op_id, node_id, sequence_number, outcome, code, message, resolved_at)\n\t\t\t\tVALUES (${resolution.operationId}, ${resolution.nodeId}, ${resolution.sequenceNumber},\n\t\t\t\t\t${resolution.outcome}, ${resolution.code},\n\t\t\t\t\t${\n\t\t\t\t\t\t// A human-readable message: an unstorable code unit is replaced (RT-65).\n\t\t\t\t\t\tresolution.message?.slice(0, MAX_RESOLUTION_MESSAGE_LENGTH).replace(\n\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noControlCharactersInRegex: U+0000 is what Postgres TEXT refuses (RT-65)\n\t\t\t\t\t\t\t/\\u0000|[\\ud800-\\udbff](?![\\udc00-\\udfff])|(?<![\\ud800-\\udbff])[\\udc00-\\udfff]/g,\n\t\t\t\t\t\t\t'\\ufffd',\n\t\t\t\t\t\t) ?? null\n\t\t\t\t\t}, ${Date.now()})\n\t\t\t\tON CONFLICT (op_id) DO NOTHING`,\n\t\t)\n\t}\n\n\tasync findOperationResolutions(\n\t\tnodeId: string,\n\t\tids: string[],\n\t): Promise<Map<string, OperationResolution>> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst found = new Map<string, OperationResolution>()\n\t\tfor (let i = 0; i < ids.length; i += 1000) {\n\t\t\tconst chunk = ids.slice(i, i + 1000)\n\t\t\tif (chunk.length === 0) continue\n\t\t\tconst rows = (await this.db.execute(\n\t\t\t\tsql`SELECT op_id, node_id, sequence_number, outcome, code, message FROM operation_resolutions\n\t\t\t\t\tWHERE node_id = ${nodeId} AND op_id IN (${sql.join(\n\t\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\t\tsql.raw(', '),\n\t\t\t\t\t)})`,\n\t\t\t)) as unknown as {\n\t\t\t\top_id: string\n\t\t\t\tnode_id: string\n\t\t\t\tsequence_number: number | string\n\t\t\t\toutcome: string\n\t\t\t\tcode: string | null\n\t\t\t\tmessage: string | null\n\t\t\t}[]\n\t\t\tfor (const row of rows) {\n\t\t\t\tfound.set(row.op_id, {\n\t\t\t\t\toperationId: row.op_id,\n\t\t\t\t\tnodeId: row.node_id,\n\t\t\t\t\tsequenceNumber: Number(row.sequence_number),\n\t\t\t\t\toutcome: row.outcome as OperationResolutionOutcome,\n\t\t\t\t\tcode: row.code,\n\t\t\t\t\tmessage: row.message,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn found\n\t}\n\n\tasync deleteOperationResolution(nodeId: string, operationId: string): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tawait this.db.execute(\n\t\t\tsql`DELETE FROM operation_resolutions WHERE node_id = ${nodeId} AND op_id = ${operationId}`,\n\t\t)\n\t}\n\n\tasync getResolvedThrough(nodeId: string): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT MAX(sequence_number) AS m FROM operation_resolutions WHERE node_id = ${nodeId}`,\n\t\t)) as unknown as { m: string | number | null }[]\n\t\treturn Number(rows[0]?.m ?? 0)\n\t}\n\n\tasync findStoredOperations(ids: string[]): Promise<Map<string, StoredOperationKey>> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst found = new Map<string, StoredOperationKey>()\n\t\t// One statement per 1000 ids, well below the bind-parameter limit.\n\t\tfor (let i = 0; i < ids.length; i += 1000) {\n\t\t\tconst chunk = ids.slice(i, i + 1000)\n\t\t\tif (chunk.length === 0) continue\n\t\t\tconst rows = (await this.db.execute(\n\t\t\t\tsql`SELECT id, node_id, sequence_number FROM operations WHERE id IN (${sql.join(\n\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)) as unknown as { id: string; node_id: string; sequence_number: number | string }[]\n\t\t\tfor (const row of rows) {\n\t\t\t\tfound.set(row.id, { nodeId: row.node_id, sequenceNumber: Number(row.sequence_number) })\n\t\t\t}\n\t\t}\n\t\treturn found\n\t}\n\n\tasync findRecordsByIds(\n\t\tcollection: string,\n\t\tids: string[],\n\t): Promise<Map<string, MaterializedRecord>> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst result = new Map<string, MaterializedRecord>()\n\t\t// One statement per 1000 ids (LMS #11), well below the bind-parameter limit.\n\t\tfor (let i = 0; i < ids.length; i += 1000) {\n\t\t\tconst chunk = ids.slice(i, i + 1000)\n\t\t\tif (chunk.length === 0) continue\n\t\t\tconst rows = (await this.db.execute(\n\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id IN (${sql.join(\n\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)) as unknown as Record<string, unknown>[]\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst record = this.deserializeRow(row, collectionDef)\n\t\t\t\tresult.set(record.id, record)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false, schema.collections[collection])\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Array<{ cnt: number | string }>\n\t\tconst cnt = rows[0]?.cnt\n\t\treturn typeof cnt === 'string' ? Number.parseInt(cnt, 10) : (cnt ?? 0)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\n\t\t// Export in delivery-sequence order (commit order), NOT sequenceNumber order.\n\t\t// sequenceNumber is per-node and interleaves nodes arbitrarily, which can place a\n\t\t// dependent operation before its dependency; restoring in that order would then\n\t\t// reassign delivery sequences non-causally, so a resumed client would receive the\n\t\t// dependent first, defer it, advance its watermark past it, and lose it. Delivery\n\t\t// order is commit order and therefore respects causality.\n\t\tconst rows = await this.db.select().from(pgOperations).orderBy(asc(pgOperations.deliverySeq))\n\t\tconst operations = rows.map((row) => this.deserializeOperation(row))\n\n\t\treturn buildServerBackup(\n\t\t\tthis.nodeId,\n\t\t\toperations,\n\t\t\tthis.versionVector,\n\t\t\tawait this.listEncryptionKeyRecords(),\n\t\t)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { mergeBackupOperations, parseServerBackup, restoreBackupKeyRecords } = await import(\n\t\t\t'./server-backup'\n\t\t)\n\t\tconst { operations, versionVector, keyRecords } = parseServerBackup(data)\n\t\t// Both modes reconcile the key table (not part of the log), record by record (RT-110).\n\t\tawait restoreBackupKeyRecords(this, keyRecords, merge === true)\n\n\t\tif (merge) {\n\t\t\tconst merged = await mergeBackupOperations(operations, (op) => this.applyRemoteOperation(op))\n\t\t\t// Re-seed the sequence counter from the (possibly advanced) version vector,\n\t\t\t// in case the merge restored operations on this node with higher numbers.\n\t\t\tthis.sequenceCounter = null\n\t\t\treturn merged\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tconst restoredMax = await this.db.transaction(async (tx) => {\n\t\t\t// Restored rows are inserted unflagged (`seq_unique = 0`: a legacy log may reuse\n\t\t\t// a sequence), so they stay outside the partial unique index; they sit at or\n\t\t\t// below the new epoch and the append check judges them as holders.\n\t\t\tawait tx.delete(pgOperations)\n\t\t\tawait tx.delete(pgSyncState)\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\tawait tx\n\t\t\t\t\t.insert(pgSyncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: now })\n\t\t\t\t\t.onConflictDoNothing({ target: pgSyncState.nodeId })\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order, then realign the\n\t\t\t// counter so future appends continue above the restored maximum.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\t\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\t\t\t}\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO delivery_counter (id, value) VALUES (1, ${deliverySeq})\n\t\t\t\t\tON CONFLICT (id) DO UPDATE SET value = ${deliverySeq}`,\n\t\t\t)\n\t\t\t// The restored log's legacy pairs (RT-48), and only the resolutions it covers:\n\t\t\t// one past a node's restored log was decided after the backup, and advertising\n\t\t\t// it would hide stored operations the restore lost (RT-45).\n\t\t\tawait tx.execute(sql`DELETE FROM sequence_pairs`)\n\t\t\tawait tx.execute(sql.raw(BACKFILL_SEQUENCE_PAIRS_SQL))\n\t\t\tawait tx.execute(sql.raw(PRUNE_RESOLUTIONS_PAST_LOG_SQL))\n\t\t\t// The restored snapshot sits at or below the new epoch (see\n\t\t\t// SEQUENCE_ENFORCEMENT_EPOCH_KEY); enforcement resumes above it.\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${SEQUENCE_ENFORCEMENT_EPOCH_KEY}, ${String(deliverySeq)})\n\t\t\t\t\tON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,\n\t\t\t)\n\t\t\treturn deliverySeq\n\t\t})\n\t\tthis.sequenceEpoch = restoredMax\n\t\t// Every restored record is re-materialized through the fold from the restored log.\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(sql`DELETE FROM kora_fold_state`)\n\t\t\tfor (const collection of Object.keys(this.schema?.collections ?? {})) {\n\t\t\t\tawait tx.execute(sql.raw(`DELETE FROM ${quoteIdent(collection)}`))\n\t\t\t}\n\t\t})\n\t\tif (this.schema) this.foldMigration = await this.rematerialize()\n\t\tawait this.backfillScopeSnapshots()\n\n\t\t// Rebuild in-memory version vector\n\t\tthis.versionVector.clear()\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\t\t// Re-seed the sequence counter from the restored version vector.\n\t\tthis.sequenceCounter = null\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * The HLC timestamp of the most recent operation on a record, by total order\n\t * (wallTime, logical, nodeId), or null when the record has no operations. Used\n\t * by {@link applyConditional} to advance its clock past the record's latest\n\t * write so newly built operations sort strictly after it.\n\t */\n\tprivate async latestOperationTimestamp(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<HLCTimestamp | null> {\n\t\tconst rows = await txOrDb\n\t\t\t.select({\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t\tlogical: pgOperations.logical,\n\t\t\t\ttimestampNodeId: pgOperations.timestampNodeId,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(and(eq(pgOperations.collection, collection), eq(pgOperations.recordId, recordId)))\n\t\t\t.orderBy(\n\t\t\t\tdesc(pgOperations.wallTime),\n\t\t\t\tdesc(pgOperations.logical),\n\t\t\t\t// Byte order (COLLATE \"C\"), like HLC.compare.\n\t\t\t\tsql`${pgOperations.timestampNodeId} COLLATE \"C\" DESC`,\n\t\t\t)\n\t\t\t.limit(1)\n\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\t\treturn { wallTime: row.wallTime, logical: row.logical, nodeId: row.timestampNodeId }\n\t}\n\n\tasync getEncryptionKeyRecord(owner: string, keyring: string): Promise<string | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT record FROM kora_encryption_keys WHERE owner = ${owner} AND keyring = ${keyring} LIMIT 1`,\n\t\t)) as unknown as { record: string }[]\n\t\treturn rows[0]?.record ?? null\n\t}\n\n\tasync putEncryptionKeyRecord(\n\t\towner: string,\n\t\tkeyring: string,\n\t\trecord: string,\n\t\trevision: number,\n\t\texpectedRevision: number,\n\t): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst now = Date.now()\n\t\t// One statement each, atomic on the (owner, keyring) primary key: concurrent writes\n\t\t// from any number of server instances have exactly one winner.\n\t\tconst rows = (expectedRevision === 0\n\t\t\t? await this.db.execute(\n\t\t\t\t\tsql`INSERT INTO kora_encryption_keys (owner, keyring, revision, record, updated_at)\n\t\t\t\t\t\t\tVALUES (${owner}, ${keyring}, ${revision}, ${record}, ${now})\n\t\t\t\t\t\t\tON CONFLICT (owner, keyring) DO NOTHING RETURNING owner`,\n\t\t\t\t)\n\t\t\t: await this.db.execute(\n\t\t\t\t\tsql`UPDATE kora_encryption_keys SET revision = ${revision}, record = ${record}, updated_at = ${now}\n\t\t\t\t\t\t\tWHERE owner = ${owner} AND keyring = ${keyring} AND revision = ${expectedRevision}\n\t\t\t\t\t\t\tRETURNING owner`,\n\t\t\t\t)) as unknown as { owner: string }[]\n\t\treturn rows.length > 0\n\t}\n\n\tasync listEncryptionKeyRecords(owner?: string): Promise<EncryptionKeyRecordRow[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\towner === undefined\n\t\t\t\t? sql`SELECT owner, keyring, revision, record FROM kora_encryption_keys ORDER BY owner, keyring`\n\t\t\t\t: sql`SELECT owner, keyring, revision, record FROM kora_encryption_keys WHERE owner = ${owner} ORDER BY keyring`,\n\t\t)) as unknown as Array<{\n\t\t\towner: string\n\t\t\tkeyring: string\n\t\t\trevision: number | string\n\t\t\trecord: string\n\t\t}>\n\t\t// BIGINT columns may come back as strings.\n\t\treturn rows.map((row) => ({\n\t\t\towner: row.owner,\n\t\t\tkeyring: row.keyring,\n\t\t\trevision: Number(row.revision),\n\t\t\trecord: row.record,\n\t\t}))\n\t}\n\n\tasync getEncryptedKeyIds(nodeOwner: string | null, limit: number): Promise<string[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (nodeOwner === null\n\t\t\t? await this.db.execute(\n\t\t\t\t\tsql`SELECT encrypted FROM operations WHERE encrypted IS NOT NULL LIMIT ${KEY_ID_SAMPLE_ROWS}`,\n\t\t\t\t)\n\t\t\t: await this.db.execute(\n\t\t\t\t\tsql`SELECT o.encrypted AS encrypted FROM node_claims c\n\t\t\t\t\t\t\tJOIN operations o ON o.node_id = c.node_id\n\t\t\t\t\t\t\tWHERE c.user_id = ${nodeOwner} AND o.encrypted IS NOT NULL\n\t\t\t\t\t\t\tLIMIT ${KEY_ID_SAMPLE_ROWS}`,\n\t\t\t\t)) as unknown as { encrypted: string | null }[]\n\t\treturn envelopeKeyIds(\n\t\t\trows.map((row) => row.encrypted),\n\t\t\tlimit,\n\t\t)\n\t}\n\n\tasync claimNode(nodeId: string, userId: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tif (userId === RELEASED_NODE_OWNER) return false\n\t\tconst now = Date.now()\n\t\t// Each statement is atomic on the node_claims primary key. A fresh claim is\n\t\t// only created for a node without history: history with no claim predates\n\t\t// node claims, so its writer is unknown (RT-5).\n\t\tawait this.db.execute(\n\t\t\tsql`INSERT INTO node_claims (node_id, user_id, claimed_at)\n\t\t\t\tSELECT ${nodeId}, ${userId}, ${now}\n\t\t\t\tWHERE NOT EXISTS (SELECT 1 FROM operations WHERE node_id = ${nodeId})\n\t\t\t\tON CONFLICT (node_id) DO NOTHING`,\n\t\t)\n\t\t// An admin-released node is taken over by its next claimant (one winner).\n\t\tawait this.db.execute(\n\t\t\tsql`UPDATE node_claims SET user_id = ${userId}, claimed_at = ${now}\n\t\t\t\tWHERE node_id = ${nodeId} AND user_id = ${RELEASED_NODE_OWNER}`,\n\t\t)\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT user_id FROM node_claims WHERE node_id = ${nodeId} LIMIT 1`,\n\t\t)) as unknown as { user_id: string }[]\n\t\treturn rows[0]?.user_id === userId\n\t}\n\n\tasync getNodeClaimOwner(nodeId: string): Promise<string | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT user_id FROM node_claims WHERE node_id = ${nodeId} LIMIT 1`,\n\t\t)) as unknown as { user_id: string }[]\n\t\treturn rows[0]?.user_id ?? null\n\t}\n\n\tasync replaceNodeClaim(\n\t\tnodeId: string,\n\t\texpectedOwner: string,\n\t\tnewOwner: string,\n\t): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\t// One statement, atomic on the row: concurrent re-issues have one winner.\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`UPDATE node_claims SET user_id = ${newOwner}, claimed_at = ${Date.now()}\n\t\t\t\tWHERE node_id = ${nodeId} AND user_id = ${expectedOwner} RETURNING node_id`,\n\t\t)) as unknown as { node_id: string }[]\n\t\treturn rows.length > 0\n\t}\n\n\tasync releaseNodeClaim(nodeId: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst known = (await this.db.execute(\n\t\t\tsql`SELECT 1 AS one WHERE EXISTS (SELECT 1 FROM node_claims WHERE node_id = ${nodeId})\n\t\t\t\tOR EXISTS (SELECT 1 FROM operations WHERE node_id = ${nodeId})`,\n\t\t)) as unknown as { one: number }[]\n\t\tif (known.length === 0) return false\n\t\tawait this.db.execute(\n\t\t\tsql`INSERT INTO node_claims (node_id, user_id, claimed_at)\n\t\t\t\tVALUES (${nodeId}, ${RELEASED_NODE_OWNER}, ${Date.now()})\n\t\t\t\tON CONFLICT (node_id) DO UPDATE SET user_id = EXCLUDED.user_id, claimed_at = EXCLUDED.claimed_at`,\n\t\t)\n\t\treturn true\n\t}\n\n\t/**\n\t * The record as currently stored, including a soft-deleted one (whose last field\n\t * values are kept), or null when it was never written. Without a materialized\n\t * table, the last known values are replayed from the operation log.\n\t */\n\tprivate async readStoredRow(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<MaterializedRecord | null> {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (collectionDef) {\n\t\t\tconst rows = (await txOrDb.execute(\n\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${recordId} LIMIT 1`,\n\t\t\t)) as unknown as Record<string, unknown>[]\n\t\t\tconst row = rows[0]\n\t\t\treturn row ? this.deserializeRow(row, collectionDef) : null\n\t\t}\n\t\t// The fold orders writes by HLC stamps compared in JavaScript, never by a\n\t\t// database collation, so this needs no ORDER BY.\n\t\tconst ops = await this.readRecordOperations(txOrDb, collection, recordId, 0)\n\t\tif (ops.length === 0) return null\n\t\tconst state = refoldRecord(ops, this.schema ?? EMPTY_FOLD_SCHEMA, this.foldOptions)\n\t\tconst lastKnown = state ? projectFoldState(state, this.foldOptions) : null\n\t\treturn { ...(lastKnown?.values ?? {}), id: recordId }\n\t}\n\n\t/**\n\t * Merge a just-appended operation (stored under `deliverySeq`) into its record's\n\t * fold state and project the row, inside the append transaction. O(fields the\n\t * operation touches): the state is read by primary key and the freshness check is\n\t * one index probe (SRV-7).\n\t *\n\t * Concurrency: every append on every instance holds the delivery-counter row lock\n\t * until commit (see nextDeliverySeq), and applyConditional takes its per-record\n\t * advisory lock before it, so this read-merge-write of one record's state is\n\t * serialized across instances; the `FOR UPDATE` on the state row is defense in\n\t * depth. A record whose log grew without this state (an older release during a\n\t * rolling upgrade) has its missing tail merged first; an unreadable, newer-than-log\n\t * or plan-incompatible state is re-folded from the log.\n\t */\n\tprivate async mergeIntoRecord(\n\t\ttx: PostgresJsDatabase,\n\t\top: Operation,\n\t\tdeliverySeq: number,\n\t): Promise<void> {\n\t\tconst schema = this.schema\n\t\tif (!schema?.collections[op.collection]) return\n\t\tconst stored = (\n\t\t\t(await tx.execute(\n\t\t\t\tsql`SELECT state, covered_seq, covered_op_id FROM kora_fold_state WHERE collection = ${op.collection} AND record_id = ${op.recordId} FOR UPDATE`,\n\t\t\t)) as unknown as { state: string; covered_seq: string | number; covered_op_id: string }[]\n\t\t)[0]\n\t\t// The record's newest operation before this one: the stored state is current iff\n\t\t// it covers exactly that operation (sequence AND id, so a state left behind by a\n\t\t// dropped or restored log is never mistaken for current).\n\t\tconst last = (\n\t\t\t(await tx.execute(\n\t\t\t\tsql`SELECT id, delivery_seq AS d FROM operations WHERE collection = ${op.collection} AND record_id = ${op.recordId} AND delivery_seq < ${deliverySeq} ORDER BY delivery_seq DESC LIMIT 1`,\n\t\t\t)) as unknown as { id: string; d: string | number }[]\n\t\t)[0]\n\t\tconst prior = Number(last?.d ?? 0)\n\t\tconst parsed = stored ? parseStoredFoldState(stored.state, op.collection, op.recordId) : null\n\t\tconst covered = stored ? Number(stored.covered_seq) : 0\n\t\tlet state: FoldState | null | typeof REFOLD_REQUIRED\n\t\tif (parsed && covered === prior && stored?.covered_op_id === (last?.id ?? '')) {\n\t\t\tstate = mergeIntoFoldState(parsed, [op], schema, this.foldOptions)\n\t\t} else if (isQuarantineAffected(this.quarantine, op.collection, op.recordId)) {\n\t\t\t// Incomplete log (RT-70): fold onto the kept row, never from the log alone.\n\t\t\tstate = await this.rebuildAffected(tx, op.collection, op.recordId, parsed)\n\t\t} else if (!stored && !last) {\n\t\t\tstate = mergeIntoFoldState(null, [op], schema, this.foldOptions)\n\t\t} else if (\n\t\t\tparsed &&\n\t\t\tcovered > 0 &&\n\t\t\tcovered < prior &&\n\t\t\t(await this.coversStoredOperation(\n\t\t\t\ttx,\n\t\t\t\top.collection,\n\t\t\t\top.recordId,\n\t\t\t\tcovered,\n\t\t\t\tstored?.covered_op_id,\n\t\t\t))\n\t\t) {\n\t\t\t// Operations appended without folding (an older release during a rolling\n\t\t\t// upgrade): merge the missing tail.\n\t\t\tstate = mergeIntoFoldState(\n\t\t\t\tparsed,\n\t\t\t\tawait this.readRecordOperations(tx, op.collection, op.recordId, covered),\n\t\t\t\tschema,\n\t\t\t\tthis.foldOptions,\n\t\t\t)\n\t\t} else {\n\t\t\tstate = REFOLD_REQUIRED\n\t\t}\n\t\tif (state === REFOLD_REQUIRED) {\n\t\t\tstate = refoldRecord(\n\t\t\t\tawait this.readRecordOperations(tx, op.collection, op.recordId, 0),\n\t\t\t\tschema,\n\t\t\t\tthis.foldOptions,\n\t\t\t)\n\t\t}\n\t\tawait this.writeFoldedRecord(tx, op.collection, op.recordId, state, deliverySeq, op.id)\n\t}\n\n\t/**\n\t * The fold state of a record that owns quarantined operations (RT-70): its stored\n\t * state, or its kept row as a snapshot base, with every remaining operation of the\n\t * record merged on top (`rebuildFromSnapshot`). Nothing is written.\n\t */\n\tprivate async rebuildAffected(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tstored: FoldState | null,\n\t): Promise<FoldState | null> {\n\t\tconst schema = this.schema ?? EMPTY_FOLD_SCHEMA\n\t\tconst collectionDef = schema.collections[collection]\n\t\tconst raw = collectionDef\n\t\t\t? (\n\t\t\t\t\t(await txOrDb.execute(\n\t\t\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${recordId} LIMIT 1`,\n\t\t\t\t\t)) as unknown as Record<string, unknown>[]\n\t\t\t\t)[0]\n\t\t\t: undefined\n\t\tlet row: KeptRow | null = null\n\t\tif (raw && collectionDef) {\n\t\t\tconst record = this.deserializeRow(raw, collectionDef)\n\t\t\tconst values: Record<string, unknown> = {}\n\t\t\tfor (const field of Object.keys(collectionDef.fields)) {\n\t\t\t\tif (record[field] !== undefined) values[field] = record[field]\n\t\t\t}\n\t\t\trow = {\n\t\t\t\tvalues,\n\t\t\t\tcreatedAt: Number(raw._created_at ?? 0),\n\t\t\t\tupdatedAt: Number(raw._updated_at ?? 0),\n\t\t\t\tdeleted: Number(raw._deleted) === 1,\n\t\t\t}\n\t\t}\n\t\treturn rebuildFromSnapshot(\n\t\t\t{\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\tstored,\n\t\t\t\trow,\n\t\t\t\tops: await this.readRecordOperations(txOrDb, collection, recordId, 0),\n\t\t\t\tquarantinedLatest: this.quarantine.latest.get(quarantineKey(collection, recordId)),\n\t\t\t},\n\t\t\tschema,\n\t\t\tthis.foldOptions,\n\t\t)\n\t}\n\n\t/** True when the record's operation at delivery sequence `seq` has id `opId`. */\n\tprivate async coversStoredOperation(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tseq: number,\n\t\topId: string | undefined,\n\t): Promise<boolean> {\n\t\tif (!opId) return false\n\t\tconst rows = (await txOrDb.execute(\n\t\t\tsql`SELECT 1 AS one FROM operations WHERE id = ${opId} AND collection = ${collection} AND record_id = ${recordId} AND delivery_seq = ${seq}`,\n\t\t)) as unknown as unknown[]\n\t\treturn rows.length > 0\n\t}\n\n\t/**\n\t * The record's current fold state for a read: the stored one when it covers the\n\t * record's whole log, else folded from the log (nothing is written).\n\t */\n\tprivate async readFoldState(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<FoldState | null> {\n\t\tconst schema = this.schema ?? EMPTY_FOLD_SCHEMA\n\t\tif (schema.collections[collection]) {\n\t\t\tconst rows = (await txOrDb.execute(\n\t\t\t\tsql`SELECT f.state, f.covered_seq, f.covered_op_id, l.id AS last_id, l.delivery_seq AS last_seq\n\t\t\t\t\tFROM kora_fold_state f\n\t\t\t\t\tLEFT JOIN LATERAL (\n\t\t\t\t\t\tSELECT o.id, o.delivery_seq FROM operations o\n\t\t\t\t\t\tWHERE o.collection = ${collection} AND o.record_id = ${recordId}\n\t\t\t\t\t\tORDER BY o.delivery_seq DESC LIMIT 1\n\t\t\t\t\t) l ON TRUE\n\t\t\t\t\tWHERE f.collection = ${collection} AND f.record_id = ${recordId}`,\n\t\t\t)) as unknown as {\n\t\t\t\tstate: string\n\t\t\t\tcovered_seq: string | number\n\t\t\t\tcovered_op_id: string\n\t\t\t\tlast_id: string | null\n\t\t\t\tlast_seq: string | number | null\n\t\t\t}[]\n\t\t\tconst stored = rows[0]\n\t\t\tconst parsed = stored ? parseStoredFoldState(stored.state, collection, recordId) : null\n\t\t\tif (\n\t\t\t\tparsed &&\n\t\t\t\tNumber(stored?.covered_seq) === Number(stored?.last_seq ?? 0) &&\n\t\t\t\tstored?.covered_op_id === (stored?.last_id ?? '')\n\t\t\t) {\n\t\t\t\treturn parsed\n\t\t\t}\n\t\t\tif (isQuarantineAffected(this.quarantine, collection, recordId)) {\n\t\t\t\treturn this.rebuildAffected(txOrDb, collection, recordId, parsed)\n\t\t\t}\n\t\t}\n\t\tconst ops = await this.readRecordOperations(txOrDb, collection, recordId, 0)\n\t\treturn ops.length > 0 ? refoldRecord(ops, schema, this.foldOptions) : null\n\t}\n\n\t/** A record's operations stored after `afterDeliverySeq`, in delivery order. */\n\tprivate async readRecordOperations(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tafterDeliverySeq: number,\n\t): Promise<Operation[]> {\n\t\tconst rows = await txOrDb\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(\n\t\t\t\tand(\n\t\t\t\t\teq(pgOperations.collection, collection),\n\t\t\t\t\teq(pgOperations.recordId, recordId),\n\t\t\t\t\tgt(pgOperations.deliverySeq, afterDeliverySeq),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.orderBy(asc(pgOperations.deliverySeq))\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\t/**\n\t * Persist a record's fold state (covering the log up to `coveredSeq`) and project\n\t * it onto the materialized row.\n\t */\n\tprivate async writeFoldedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tstate: FoldState | null,\n\t\tcoveredSeq: number,\n\t\tcoveredOpId: string,\n\t): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\t\tif (state) {\n\t\t\tawait txOrDb.execute(\n\t\t\t\tsql`INSERT INTO kora_fold_state (collection, record_id, state, covered_seq, covered_op_id)\n\t\t\t\t\tVALUES (${collection}, ${recordId}, ${serializeServerFoldState(state)}, ${coveredSeq}, ${coveredOpId})\n\t\t\t\t\tON CONFLICT (collection, record_id) DO UPDATE SET state = EXCLUDED.state, covered_seq = EXCLUDED.covered_seq, covered_op_id = EXCLUDED.covered_op_id`,\n\t\t\t)\n\t\t} else {\n\t\t\tawait txOrDb.execute(\n\t\t\t\tsql`DELETE FROM kora_fold_state WHERE collection = ${collection} AND record_id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\tif (!row) {\n\t\t\t// Never inserted (an update with no merged insert): no visible row. A row an\n\t\t\t// earlier (replay) materialization produced for it is hidden.\n\t\t\tawait txOrDb.execute(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1 WHERE id = ${recordId}`,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tawait this.upsertMaterializedRecord(\n\t\t\ttxOrDb,\n\t\t\tcollection,\n\t\t\trecordId,\n\t\t\trow.values,\n\t\t\tObject.keys(collectionDef.fields),\n\t\t\tcollectionDef,\n\t\t\trow.createdAt,\n\t\t\trow.updatedAt,\n\t\t\trow.deleted,\n\t\t)\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t */\n\tprivate async upsertMaterializedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t\tdeleted: boolean,\n\t): Promise<void> {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor\n\t\t\t\t\t? serializePgFieldValue(materializedFieldValue(recordData, f, descriptor), descriptor)\n\t\t\t\t\t: null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\tdeleted ? 1 : 0,\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\tawait txOrDb.execute(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * {@link writeFoldedRecord} for a batch of records of one collection, in a handful\n\t * of multi-row statements (the migration's write path). Rows are chunked so a\n\t * statement never nears the 65,535 bind-parameter limit, however wide the collection.\n\t */\n\tprivate async writeFoldedRecords(\n\t\ttx: PostgresJsDatabase,\n\t\tcollection: string,\n\t\tbatch: FoldedRecordWrite[],\n\t): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef || batch.length === 0) return\n\t\tconst kept = batch.filter((entry) => entry.state !== null)\n\t\tfor (let i = 0; i < kept.length; i += 1000) {\n\t\t\tconst values = kept\n\t\t\t\t.slice(i, i + 1000)\n\t\t\t\t.map(\n\t\t\t\t\t(entry) =>\n\t\t\t\t\t\tsql`(${collection}, ${entry.recordId}, ${serializeServerFoldState(entry.state as FoldState)}, ${entry.coveredSeq}, ${entry.coveredOpId})`,\n\t\t\t\t)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO kora_fold_state (collection, record_id, state, covered_seq, covered_op_id)\n\t\t\t\t\tVALUES ${sql.join(values, sql.raw(', '))}\n\t\t\t\t\tON CONFLICT (collection, record_id) DO UPDATE SET state = EXCLUDED.state, covered_seq = EXCLUDED.covered_seq, covered_op_id = EXCLUDED.covered_op_id`,\n\t\t\t)\n\t\t}\n\t\tconst dropped = batch.filter((entry) => entry.state === null).map((entry) => entry.recordId)\n\t\tif (dropped.length > 0) {\n\t\t\tawait tx.execute(\n\t\t\t\tsql`DELETE FROM kora_fold_state WHERE collection = ${collection} AND record_id IN (${sql.join(\n\t\t\t\t\tdropped.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)\n\t\t}\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\t\tconst columns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst rows: unknown[][] = []\n\t\tconst hidden: string[] = []\n\t\tfor (const entry of batch) {\n\t\t\tconst row = entry.state ? projectFoldState(entry.state, this.foldOptions) : null\n\t\t\tif (!row) {\n\t\t\t\thidden.push(entry.recordId)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\trows.push([\n\t\t\t\tentry.recordId,\n\t\t\t\t...fieldNames.map((field) => {\n\t\t\t\t\tconst descriptor = collectionDef.fields[field]\n\t\t\t\t\treturn descriptor\n\t\t\t\t\t\t? serializePgFieldValue(\n\t\t\t\t\t\t\t\tmaterializedFieldValue(row.values, field, descriptor),\n\t\t\t\t\t\t\t\tdescriptor,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: null\n\t\t\t\t}),\n\t\t\t\trow.createdAt,\n\t\t\t\trow.updatedAt,\n\t\t\t\trow.deleted ? 1 : 0,\n\t\t\t])\n\t\t}\n\t\tconst perStatement = Math.max(1, Math.floor(30_000 / columns.length))\n\t\tconst columnsSql = sql.raw(columns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst updateSet = sql.raw(\n\t\t\tcolumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\t\tfor (let i = 0; i < rows.length; i += perStatement) {\n\t\t\tconst tuples = rows.slice(i, i + perStatement).map(\n\t\t\t\t(values) =>\n\t\t\t\t\tsql`(${sql.join(\n\t\t\t\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\t\t\t\tsql.raw(', '),\n\t\t\t\t\t)})`,\n\t\t\t)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(collection))} (${columnsSql}) VALUES ${sql.join(tuples, sql.raw(', '))} ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t\t)\n\t\t}\n\t\tif (hidden.length > 0) {\n\t\t\tawait tx.execute(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1 WHERE id IN (${sql.join(\n\t\t\t\t\thidden.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Re-materialization migration (W7 step 7), run by setSchema and after a\n\t * replace-mode restore: every record whose fold state is missing, stale or built\n\t * under a different fold plan is re-folded from its log; nothing else is touched.\n\t * See the SQLite store's `rematerialize` for the rules (a record owning quarantined\n\t * operations folds onto its kept row, RT-70; idempotent; resumable).\n\t *\n\t * Postgres specifics: records are paged in batches of\n\t * {@link FOLD_MIGRATION_BATCH} through the (collection, record_id, delivery_seq)\n\t * index, and every batch is one transaction that first takes the delivery-counter\n\t * row lock. Appends on every instance take that lock too, so a batch reads each\n\t * record's complete log and writes its state while no append to it can commit: a\n\t * live write on another instance during a rolling deploy is never overwritten by a\n\t * stale re-fold (NEW-SRV-5), it either committed before the batch (and is folded)\n\t * or commits after it (and is merged into the batch's state).\n\t */\n\t/**\n\t * Write the beta.12 clears the ids prove into the stored bodies, once per database\n\t * (RT-85, see `provenLegacyClears`), and mark their records' fold states stale.\n\t * Idempotent: concurrent first starts write the same bodies.\n\t */\n\tprivate async canonicalizeLegacyBodies(): Promise<void> {\n\t\tconst done = (await this.db.execute(\n\t\t\tsql`SELECT 1 AS one FROM kora_server_meta WHERE key = ${LEGACY_BODIES_META_KEY}`,\n\t\t)) as unknown as unknown[]\n\t\tif (done.length > 0) return\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(\n\t\t\t\tand(\n\t\t\t\t\teq(pgOperations.type, 'update'),\n\t\t\t\t\tsql`${pgOperations.hashVersion} IS NULL`,\n\t\t\t\t\tsql`${pgOperations.previousData} IS NOT NULL`,\n\t\t\t\t),\n\t\t\t)\n\t\tconst changed = await provenLegacyClears(rows.map((row) => this.deserializeOperation(row)))\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tfor (const op of changed) {\n\t\t\t\tawait tx\n\t\t\t\t\t.update(pgOperations)\n\t\t\t\t\t.set({ data: JSON.stringify(op.data) })\n\t\t\t\t\t.where(eq(pgOperations.id, op.id))\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql`UPDATE kora_fold_state SET covered_seq = -1 WHERE collection = ${op.collection} AND record_id = ${op.recordId}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${LEGACY_BODIES_META_KEY}, ${String(changed.length)})\n\t\t\t\t\tON CONFLICT (key) DO NOTHING`,\n\t\t\t)\n\t\t})\n\t}\n\n\tprivate async rematerialize(): Promise<FoldMigrationReport> {\n\t\tconst schema = this.schema\n\t\tconst report: FoldMigrationReport = {\n\t\t\tran: true,\n\t\t\trecords: 0,\n\t\t\tskippedUnclean: 0,\n\t\t\tfullRefold: false,\n\t\t}\n\t\tif (!schema) return { ...report, ran: false }\n\t\tconst clean = this.logIntegrity.totalQuarantined === 0\n\t\tconst fingerprint = serverFoldPlanFingerprint(\n\t\t\tschema,\n\t\t\tthis.explicitAuthorities,\n\t\t\tthis.operationTransforms,\n\t\t)\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended('kora:fold-plan', 0))`)\n\t\t\tconst stored = (\n\t\t\t\t(await tx.execute(\n\t\t\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${FOLD_PLAN_FINGERPRINT_KEY}`,\n\t\t\t\t)) as unknown as { value: string }[]\n\t\t\t)[0]?.value\n\t\t\tif (stored === fingerprint) return\n\t\t\treport.fullRefold = stored !== undefined\n\t\t\tawait tx.execute(sql`UPDATE kora_fold_state SET covered_seq = -1`)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${FOLD_PLAN_FINGERPRINT_KEY}, ${fingerprint})\n\t\t\t\t\tON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,\n\t\t\t)\n\t\t})\n\t\tfor (const collection of Object.keys(schema.collections)) {\n\t\t\tlet cursor = ''\n\t\t\tfor (;;) {\n\t\t\t\tconst page = (await this.db.execute(\n\t\t\t\t\tsql`WITH recs AS (\n\t\t\t\t\t\tSELECT record_id, MAX(delivery_seq) AS max_seq FROM operations\n\t\t\t\t\t\tWHERE collection = ${collection} AND record_id > ${cursor}\n\t\t\t\t\t\tGROUP BY record_id ORDER BY record_id LIMIT ${FOLD_MIGRATION_BATCH}\n\t\t\t\t\t)\n\t\t\t\t\tSELECT r.record_id, r.max_seq, f.covered_seq AS covered,\n\t\t\t\t\t\tEXISTS (SELECT 1 FROM ${sql.raw(quoteIdent(collection))} c WHERE c.id = r.record_id) AS has_row,\n\t\t\t\t\t\tEXISTS (\n\t\t\t\t\t\t\tSELECT 1 FROM operations x\n\t\t\t\t\t\t\tWHERE x.id = f.covered_op_id AND x.delivery_seq = f.covered_seq\n\t\t\t\t\t\t) AS covered_exists\n\t\t\t\t\tFROM recs r LEFT JOIN kora_fold_state f\n\t\t\t\t\t\tON f.collection = ${collection} AND f.record_id = r.record_id\n\t\t\t\t\tORDER BY r.record_id`,\n\t\t\t\t)) as unknown as {\n\t\t\t\t\trecord_id: string\n\t\t\t\t\tmax_seq: string | number\n\t\t\t\t\tcovered: string | number | null\n\t\t\t\t\thas_row: boolean\n\t\t\t\t\tcovered_exists: boolean\n\t\t\t\t}[]\n\t\t\t\tif (page.length === 0) break\n\t\t\t\tcursor = page[page.length - 1]?.record_id ?? cursor\n\t\t\t\tconst stale = page.filter(\n\t\t\t\t\t(row) =>\n\t\t\t\t\t\trow.covered === null ||\n\t\t\t\t\t\tNumber(row.covered) !== Number(row.max_seq) ||\n\t\t\t\t\t\t!row.covered_exists,\n\t\t\t\t)\n\t\t\t\tconst targets = stale.map((row) => row.record_id)\n\t\t\t\tif (targets.length > 0) {\n\t\t\t\t\tawait this.db.transaction(async (tx) => {\n\t\t\t\t\t\t// Serialize with every append (see the method comment).\n\t\t\t\t\t\tawait tx.execute(sql`SELECT value FROM delivery_counter WHERE id = 1 FOR UPDATE`)\n\t\t\t\t\t\tconst rows = await tx\n\t\t\t\t\t\t\t.select()\n\t\t\t\t\t\t\t.from(pgOperations)\n\t\t\t\t\t\t\t.where(\n\t\t\t\t\t\t\t\tand(\n\t\t\t\t\t\t\t\t\teq(pgOperations.collection, collection),\n\t\t\t\t\t\t\t\t\tinArray(pgOperations.recordId, targets),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\tconst byRecord = new Map<string, Array<(typeof rows)[number]>>()\n\t\t\t\t\t\tfor (const row of rows) {\n\t\t\t\t\t\t\tconst list = byRecord.get(row.recordId)\n\t\t\t\t\t\t\tif (list) list.push(row)\n\t\t\t\t\t\t\telse byRecord.set(row.recordId, [row])\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst batch: FoldedRecordWrite[] = []\n\t\t\t\t\t\tfor (const recordId of targets) {\n\t\t\t\t\t\t\tconst recordRows = byRecord.get(recordId) ?? []\n\t\t\t\t\t\t\tlet covered = 0\n\t\t\t\t\t\t\tlet coveredOpId = ''\n\t\t\t\t\t\t\tfor (const row of recordRows) {\n\t\t\t\t\t\t\t\tif (Number(row.deliverySeq ?? 0) > covered) {\n\t\t\t\t\t\t\t\t\tcovered = Number(row.deliverySeq ?? 0)\n\t\t\t\t\t\t\t\t\tcoveredOpId = row.id\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet state: FoldState | null\n\t\t\t\t\t\t\tif (!clean && isQuarantineAffected(this.quarantine, collection, recordId)) {\n\t\t\t\t\t\t\t\t// Incomplete log (RT-70): the kept row is the base, never the log alone.\n\t\t\t\t\t\t\t\tconst storedState = (\n\t\t\t\t\t\t\t\t\t(await tx.execute(\n\t\t\t\t\t\t\t\t\t\tsql`SELECT state FROM kora_fold_state WHERE collection = ${collection} AND record_id = ${recordId}`,\n\t\t\t\t\t\t\t\t\t)) as unknown as { state: string }[]\n\t\t\t\t\t\t\t\t)[0]\n\t\t\t\t\t\t\t\tstate = await this.rebuildAffected(\n\t\t\t\t\t\t\t\t\ttx,\n\t\t\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\t\t\trecordId,\n\t\t\t\t\t\t\t\t\tparseStoredFoldState(storedState?.state, collection, recordId),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treport.skippedUnclean++\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstate = refoldRecord(\n\t\t\t\t\t\t\t\t\trecordRows.map((row) => this.deserializeOperation(row)),\n\t\t\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\t\t\tthis.foldOptions,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbatch.push({ recordId, state, coveredSeq: covered, coveredOpId })\n\t\t\t\t\t\t\treport.records++\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait this.writeFoldedRecords(tx, collection, batch)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (page.length < FOLD_MIGRATION_BATCH) break\n\t\t\t}\n\t\t\t// Affected records with no remaining operation at all (every one quarantined,\n\t\t\t// the insert included): the kept row is their whole history.\n\t\t\tif (!clean) {\n\t\t\t\tawait this.db.transaction(async (tx) => {\n\t\t\t\t\tawait tx.execute(sql`SELECT value FROM delivery_counter WHERE id = 1 FOR UPDATE`)\n\t\t\t\t\tconst orphans = (await tx.execute(\n\t\t\t\t\t\tsql`SELECT c.id AS id FROM ${sql.raw(quoteIdent(collection))} c\n\t\t\t\t\t\t\tWHERE NOT EXISTS (SELECT 1 FROM kora_fold_state f WHERE f.collection = ${collection} AND f.record_id = c.id)\n\t\t\t\t\t\t\tAND NOT EXISTS (SELECT 1 FROM operations o WHERE o.collection = ${collection} AND o.record_id = c.id)`,\n\t\t\t\t\t)) as unknown as { id: string }[]\n\t\t\t\t\tconst batch: FoldedRecordWrite[] = []\n\t\t\t\t\tfor (const { id } of orphans) {\n\t\t\t\t\t\tif (!isQuarantineAffected(this.quarantine, collection, id)) continue\n\t\t\t\t\t\tconst state = await this.rebuildAffected(tx, collection, id, null)\n\t\t\t\t\t\tif (!state) continue\n\t\t\t\t\t\tbatch.push({ recordId: id, state, coveredSeq: 0, coveredOpId: '' })\n\t\t\t\t\t\treport.skippedUnclean++\n\t\t\t\t\t\treport.records++\n\t\t\t\t\t}\n\t\t\t\t\tif (batch.length > 0) await this.writeFoldedRecords(tx, collection, batch)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tif (report.skippedUnclean > 0) {\n\t\t\tconsole.error(\n\t\t\t\t`[kora] Fold re-materialization: ${report.skippedUnclean} record(s) own quarantined operations (${this.logIntegrity.totalQuarantined} quarantined row(s), see operations_quarantine). Their log is incomplete, so their pre-fold rows were kept as the base their remaining and later operations fold onto. Repair or release the quarantined rows to restore their exact history.`,\n\t\t\t)\n\t\t}\n\t\treturn report\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t\tthis.schema?.collections[collection],\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(\n\t\twhere: Record<string, unknown>,\n\t\tincludeDeleted: boolean,\n\t\tcollectionDef?: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\t// Raw-string columns hold the lossless encoding (RT-65): filter on it too.\n\t\t\tconst kind = collectionDef?.fields[key]?.kind\n\t\t\tconst param =\n\t\t\t\tkind && isPgRawTextKind(kind) && typeof value === 'string' ? encodePgText(value) : value\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${param}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializePgFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\t\t// A soft-deleted row (only returned when deleted rows are asked for) says so, so a\n\t\t// caller never mistakes the last values the fold keeps on it for a live record.\n\t\tif (Number(row._deleted) === 1) record._deleted = 1\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate async materializeFromOpsLog(collection: string): Promise<MaterializedRecord[]> {\n\t\tconst ids = (await this.db.execute(\n\t\t\tsql`SELECT DISTINCT record_id FROM operations WHERE collection = ${collection} ORDER BY record_id`,\n\t\t)) as unknown as { record_id: string }[]\n\t\tconst records: MaterializedRecord[] = []\n\t\tfor (const { record_id: recordId } of ids) {\n\t\t\tconst ops = await this.readRecordOperations(this.db, collection, recordId, 0)\n\t\t\tconst state = refoldRecord(ops, this.schema ?? EMPTY_FOLD_SCHEMA, this.foldOptions)\n\t\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\t\tif (row && !row.deleted) records.push({ id: recordId, ...row.values })\n\t\t}\n\t\treturn records\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Initialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate async initialize(): Promise<void> {\n\t\tawait this.ensureTables()\n\t\tawait this.loadIdentity()\n\t\tthis.logIntegrity = await this.scanLogIntegrityOnce()\n\t\tthis.quarantine = buildQuarantineScope(\n\t\t\t(\n\t\t\t\t(await this.db.execute(sql`SELECT row_json FROM operations_quarantine`)) as unknown as {\n\t\t\t\t\trow_json: string\n\t\t\t\t}[]\n\t\t\t).map((row) => row.row_json),\n\t\t)\n\n\t\t// Hydrate in-memory version vector cache\n\t\tconst rows = await this.db\n\t\t\t.select({\n\t\t\t\tnodeId: pgSyncState.nodeId,\n\t\t\t\tmaxSequenceNumber: pgSyncState.maxSequenceNumber,\n\t\t\t})\n\t\t\t.from(pgSyncState)\n\n\t\tfor (const row of rows) {\n\t\t\tthis.versionVector.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t}\n\n\t/**\n\t * The startup log-integrity scan's result (W8 step 0): rows that could not be read\n\t * back into an operation are moved to `operations_quarantine` once per database,\n\t * before any fold reads them.\n\t */\n\tasync getLogIntegrityReport(): Promise<ServerLogIntegrityReport> {\n\t\tawait this.ready\n\t\treturn { ...this.logIntegrity, quarantined: [...this.logIntegrity.quarantined] }\n\t}\n\n\t/**\n\t * One-time scan under the setup advisory lock (concurrent starts run it once). Keyset\n\t * pages by id, so a large log is read in bounded chunks; like the delivery-sequence\n\t * backfill it runs on the first start of this release only.\n\t */\n\tprivate async scanLogIntegrityOnce(): Promise<ServerLogIntegrityReport> {\n\t\tconst report: ServerLogIntegrityReport = {\n\t\t\tcheckedRows: 0,\n\t\t\tquarantined: [],\n\t\t\tran: false,\n\t\t\ttotalQuarantined: 0,\n\t\t}\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended('kora:log-integrity', 0))`)\n\t\t\tawait tx.execute(sql.raw(SERVER_LOG_QUARANTINE_DDL))\n\t\t\tconst done = (await tx.execute(\n\t\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${SERVER_LOG_INTEGRITY_META_KEY}`,\n\t\t\t)) as unknown as { value: string }[]\n\t\t\tif (done.length > 0) return\n\t\t\treport.ran = true\n\t\t\tconst now = Date.now()\n\t\t\tlet after = ''\n\t\t\tfor (;;) {\n\t\t\t\tconst page = (await tx.execute(\n\t\t\t\t\tsql`SELECT id, node_id, type, collection, record_id, data, previous_data, atomic_ops, wall_time, logical, timestamp_node_id, sequence_number, causal_deps, schema_version FROM operations WHERE id > ${after} ORDER BY id LIMIT 2000`,\n\t\t\t\t)) as unknown as ServerOperationRow[]\n\t\t\t\tfor (const row of page) {\n\t\t\t\t\treport.checkedRows++\n\t\t\t\t\tconst verdict = checkServerOperationRow(row)\n\t\t\t\t\tif (!verdict) continue\n\t\t\t\t\tconst id = String(row.id)\n\t\t\t\t\tawait tx.execute(\n\t\t\t\t\t\tsql`INSERT INTO operations_quarantine (id, problem, detail, row_json, quarantined_at) VALUES (${id}, ${verdict.problem}, ${verdict.detail}, ${quarantineRowJson(row)}, ${now}) ON CONFLICT (id) DO NOTHING`,\n\t\t\t\t\t)\n\t\t\t\t\tawait tx.execute(sql`DELETE FROM operations WHERE id = ${id}`)\n\t\t\t\t\treport.quarantined.push({ operationId: id, ...verdict })\n\t\t\t\t}\n\t\t\t\tif (page.length < 2000) break\n\t\t\t\tafter = String(page[page.length - 1]?.id ?? after)\n\t\t\t}\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${SERVER_LOG_INTEGRITY_META_KEY}, ${String(now)}) ON CONFLICT (key) DO NOTHING`,\n\t\t\t)\n\t\t})\n\t\tif (report.quarantined.length > 0) {\n\t\t\tconsole.warn(\n\t\t\t\t`[kora] Log integrity: ${report.quarantined.length} unreadable operation row(s) moved to operations_quarantine.`,\n\t\t\t)\n\t\t}\n\t\tconst total = (await this.db.execute(\n\t\t\tsql`SELECT COUNT(*) AS n FROM operations_quarantine`,\n\t\t)) as unknown as { n: string | number }[]\n\t\treport.totalQuarantined = Number(total[0]?.n ?? 0)\n\t\treturn report\n\t}\n\n\tprivate async ensureTables(): Promise<void> {\n\t\t// Serialize all schema setup across instances with an advisory transaction lock.\n\t\t// `CREATE TABLE IF NOT EXISTS` is not atomic in Postgres: two servers cold-starting\n\t\t// against the same empty database race and one fails with a duplicate-type error.\n\t\t// Running every setup statement in one advisory-locked transaction makes concurrent\n\t\t// startup safe and also serializes the delivery-sequence backfill.\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended('kora:ensure-tables', 0))`)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\t\tdata TEXT,\n\t\t\t\t\tprevious_data TEXT,\n\t\t\t\t\tatomic_ops TEXT,\n\t\t\t\t\twall_time BIGINT NOT NULL,\n\t\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\t\tsequence_number BIGINT NOT NULL,\n\t\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\t\treceived_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t\t// ops\" and keep materializing by last-write-wins exactly as before.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS atomic_ops TEXT`)\n\n\t\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t\t// delivery watermark.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS delivery_seq BIGINT`)\n\n\t\t\t// Backward-compatible migration: the per-operation scope snapshot (RT-14).\n\t\t\t// Rows written before it are backfilled from the log when the schema is set.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS scope_snapshot TEXT`)\n\n\t\t\t// Content-hash version of the stored id (CORE-1, protocol v2). Null means 1.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS hash_version INTEGER`)\n\n\t\t\t// Encryption envelope of the operation (protocol v2), stored opaquely (JSON).\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS encrypted TEXT`)\n\n\t\t\t// Per-record fold state (W7): the materialized row is projected from it.\n\t\t\t// `covered_seq` / `covered_op_id`: the delivery sequence and id of the record's\n\t\t\t// newest operation merged into it (the state covers every operation up to it).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS kora_fold_state (\n\t\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\t\tstate TEXT NOT NULL,\n\t\t\t\t\tcovered_seq BIGINT NOT NULL,\n\t\t\t\t\tcovered_op_id TEXT NOT NULL DEFAULT '',\n\t\t\t\t\tPRIMARY KEY (collection, record_id)\n\t\t\t\t)\n\t\t\t`)\n\t\t\t// A pre-release table may lack it; '' never matches an operation id, so such a\n\t\t\t// state is re-folded on its next use.\n\t\t\tawait tx.execute(\n\t\t\t\tsql`ALTER TABLE kora_fold_state ADD COLUMN IF NOT EXISTS covered_op_id TEXT NOT NULL DEFAULT ''`,\n\t\t\t)\n\t\t\t// A record's newest delivery sequence in one probe (the fold freshness check),\n\t\t\t// and the migration's record paging.\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_collection_record_delivery ON operations (collection, record_id, delivery_seq)`,\n\t\t\t)\n\n\t\t\t// Backward-compatible migration (RT-37): the sole-holder flag behind the partial\n\t\t\t// unique index. Existing rows (and rows an older instance writes during a rolling\n\t\t\t// upgrade) read 0: outside the index, still judged as holders by the append check.\n\t\t\tawait tx.execute(\n\t\t\t\tsql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS seq_unique INTEGER NOT NULL DEFAULT 0`,\n\t\t\t)\n\n\t\t\t// Blob content hash -> principals that pushed (or first claimed) it (RT-11).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS blob_owners (\n\t\t\t\t\thash TEXT NOT NULL,\n\t\t\t\t\towner TEXT NOT NULL,\n\t\t\t\t\tcreated_at BIGINT NOT NULL,\n\t\t\t\t\tPRIMARY KEY (hash, owner)\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)`,\n\t\t\t)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)`)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)`)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)`,\n\t\t\t)\n\t\t\t// Index for efficient per-record operation lookups during materialization\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)`,\n\t\t\t)\n\n\t\t\t// Small key/value store for server-side metadata (snapshot fingerprint, RT-20).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS kora_server_meta (\n\t\t\t\t\tkey TEXT PRIMARY KEY,\n\t\t\t\t\tvalue TEXT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Wrapped end-to-end encryption key records (ENC-1, D4b): salt, KDF parameters\n\t\t\t// and wrapped keys per (owner, keyring). Never a usable key.\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS kora_encryption_keys (\n\t\t\t\t\towner TEXT NOT NULL,\n\t\t\t\t\tkeyring TEXT NOT NULL,\n\t\t\t\t\trevision BIGINT NOT NULL,\n\t\t\t\t\trecord TEXT NOT NULL,\n\t\t\t\t\tupdated_at BIGINT NOT NULL,\n\t\t\t\t\tPRIMARY KEY (owner, keyring)\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Node id -> principal binding (see claimNode). One row per device node id.\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS node_claims (\n\t\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\t\tuser_id TEXT NOT NULL,\n\t\t\t\t\tclaimed_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\t\tmax_sequence_number BIGINT NOT NULL,\n\t\t\t\t\tlast_seen_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Migration (SRV-4): sequence numbers were INTEGER, so a node past 2^31-1 writes\n\t\t\t// failed. Widen both columns once; the type check keeps restarts free (ALTER\n\t\t\t// TYPE rewrites the table under an exclusive lock, so it must not repeat).\n\t\t\tconst narrowColumns = (await tx.execute(sql`\n\t\t\t\tSELECT table_name, column_name FROM information_schema.columns\n\t\t\t\tWHERE table_schema = current_schema() AND data_type = 'integer' AND (\n\t\t\t\t\t(table_name = 'operations' AND column_name = 'sequence_number') OR\n\t\t\t\t\t(table_name = 'sync_state' AND column_name = 'max_sequence_number')\n\t\t\t\t)\n\t\t\t`)) as unknown as { table_name: string; column_name: string }[]\n\t\t\tfor (const column of narrowColumns) {\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql.raw(\n\t\t\t\t\t\t`ALTER TABLE ${quoteIdent(column.table_name)} ALTER COLUMN ${quoteIdent(column.column_name)} TYPE BIGINT`,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Counter row that assigns delivery sequences in commit order. Every append\n\t\t\t// does `UPDATE ... value = value + 1 RETURNING value` inside its transaction,\n\t\t\t// which holds an exclusive row lock until commit. So a later assigner cannot\n\t\t\t// obtain its number until the earlier one has committed: delivery-sequence\n\t\t\t// order equals commit (visibility) order, which is what makes a `> watermark`\n\t\t\t// stream provably gap-free across instances. This serializes appends through\n\t\t\t// one row (correctness over throughput, per the framework's priorities).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\t\tvalue BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backfill any pre-column rows deterministically, then seed the counter to the\n\t\t\t// resulting maximum. Under the advisory lock two starting servers cannot\n\t\t\t// double-assign. The window scan touches only rows lacking a sequence, so a\n\t\t\t// fresh or already-migrated table does almost no work here.\n\t\t\tawait tx.execute(sql`\n\t\t\t\tWITH ordered AS (\n\t\t\t\t\tSELECT id, ROW_NUMBER() OVER (\n\t\t\t\t\t\tORDER BY received_at ASC, sequence_number ASC, id ASC\n\t\t\t\t\t) + COALESCE((SELECT MAX(delivery_seq) FROM operations), 0) AS rn\n\t\t\t\t\tFROM operations WHERE delivery_seq IS NULL\n\t\t\t\t)\n\t\t\t\tUPDATE operations o SET delivery_seq = ordered.rn\n\t\t\t\tFROM ordered WHERE o.id = ordered.id\n\t\t\t`)\n\t\t\tawait tx.execute(sql`\n\t\t\t\tINSERT INTO delivery_counter (id, value)\n\t\t\t\tVALUES (1, COALESCE((SELECT MAX(delivery_seq) FROM operations), 0))\n\t\t\t\tON CONFLICT (id) DO UPDATE\n\t\t\t\t\tSET value = GREATEST(delivery_counter.value, EXCLUDED.value)\n\t\t\t`)\n\n\t\t\t// Sequence enforcement (W3 step 4): record the epoch on the first start of this\n\t\t\t// release (the log's highest delivery sequence then; see\n\t\t\t// SEQUENCE_ENFORCEMENT_EPOCH_KEY), then back the append check with a partial\n\t\t\t// unique index over sole-holder rows (NODE_SEQ_UNIQUE_INDEX), which therefore\n\t\t\t// always exists: a legacy duplicate pair is stored unflagged. It replaces the\n\t\t\t// earlier indexes (a full one, and one over the rows past the epoch, which a\n\t\t\t// legacy client's pair and an older instance's insert would violate, RT-37).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tINSERT INTO kora_server_meta (key, value)\n\t\t\t\tSELECT ${SEQUENCE_ENFORCEMENT_EPOCH_KEY}, COALESCE(MAX(delivery_seq), 0)::text FROM operations\n\t\t\t\tON CONFLICT (key) DO NOTHING\n\t\t\t`)\n\t\t\tconst epochRows = (await tx.execute(\n\t\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${SEQUENCE_ENFORCEMENT_EPOCH_KEY}`,\n\t\t\t)) as unknown as { value: string }[]\n\t\t\t// Absent only if the row could not be written: enforce everything (epoch 0).\n\t\t\tconst epoch = epochRows[0] === undefined ? 0 : Number(epochRows[0].value)\n\t\t\tif (!Number.isSafeInteger(epoch) || epoch < 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`kora_server_meta.${SEQUENCE_ENFORCEMENT_EPOCH_KEY} holds \"${String(epochRows[0]?.value)}\", not a delivery sequence. Restore it from a backup or delete the row to re-derive it.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tthis.sequenceEpoch = epoch\n\t\t\tfor (const superseded of SUPERSEDED_NODE_SEQ_UNIQUE_INDEXES) {\n\t\t\t\tawait tx.execute(sql.raw(`DROP INDEX IF EXISTS ${superseded}`))\n\t\t\t}\n\t\t\t// A row is flagged only when nothing held its sequence at insert, so flagged\n\t\t\t// duplicates can come only from outside writes (a manual edit). Before\n\t\t\t// (re)creating the index, unflag them: they stay stored and judged by the append\n\t\t\t// check, and the index creation cannot fail.\n\t\t\tconst indexed = (await tx.execute(\n\t\t\t\tsql`SELECT 1 FROM pg_indexes WHERE schemaname = current_schema() AND indexname = ${NODE_SEQ_UNIQUE_INDEX}`,\n\t\t\t)) as unknown as unknown[]\n\t\t\tif (indexed.length === 0) {\n\t\t\t\tawait tx.execute(sql`\n\t\t\t\t\tUPDATE operations o SET seq_unique = 0\n\t\t\t\t\tWHERE o.seq_unique = 1 AND EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM operations other\n\t\t\t\t\t\tWHERE other.node_id = o.node_id\n\t\t\t\t\t\t\tAND other.sequence_number = o.sequence_number\n\t\t\t\t\t\t\tAND other.id <> o.id\n\t\t\t\t\t)\n\t\t\t\t`)\n\t\t\t}\n\t\t\tawait tx.execute(\n\t\t\t\tsql.raw(\n\t\t\t\t\t`CREATE UNIQUE INDEX IF NOT EXISTS ${NODE_SEQ_UNIQUE_INDEX} ON operations (node_id, sequence_number) WHERE seq_unique = 1`,\n\t\t\t\t),\n\t\t\t)\n\n\t\t\t// How uploaded operations were resolved without being stored under their\n\t\t\t// sequence (validator `ignore`, terminal refusal, renumbered duplicate; RT-43,\n\t\t\t// RT-47).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS operation_resolutions (\n\t\t\t\t\top_id TEXT PRIMARY KEY,\n\t\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\t\tsequence_number BIGINT NOT NULL,\n\t\t\t\t\toutcome TEXT NOT NULL,\n\t\t\t\t\tcode TEXT,\n\t\t\t\t\tmessage TEXT,\n\t\t\t\t\tresolved_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_resolutions_node_seq ON operation_resolutions (node_id, sequence_number)`,\n\t\t\t)\n\t\t\t// (node, sequence) held by more than one operation: legacy pairs (RT-48),\n\t\t\t// indexed once from the existing log, then maintained by appends.\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS sequence_pairs (\n\t\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\t\tsequence_number BIGINT NOT NULL,\n\t\t\t\t\tPRIMARY KEY (node_id, sequence_number)\n\t\t\t\t)\n\t\t\t`)\n\t\t\tconst pairsBackfilled = (await tx.execute(\n\t\t\t\tsql`SELECT 1 FROM kora_server_meta WHERE key = ${SEQUENCE_PAIRS_BACKFILLED_KEY}`,\n\t\t\t)) as unknown as unknown[]\n\t\t\tif (pairsBackfilled.length === 0) {\n\t\t\t\tawait tx.execute(sql.raw(BACKFILL_SEQUENCE_PAIRS_SQL))\n\t\t\t\tawait tx.execute(\n\t\t\t\t\tsql`INSERT INTO kora_server_meta (key, value) VALUES (${SEQUENCE_PAIRS_BACKFILLED_KEY}, '1')\n\t\t\t\t\t\tON CONFLICT (key) DO NOTHING`,\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside an open append transaction. The\n\t * `UPDATE ... RETURNING` locks the counter row until this transaction commits,\n\t * serializing assignment into commit order (see the counter table comment).\n\t */\n\tprivate async nextDeliverySeq(tx: {\n\t\texecute: (query: SQL) => Promise<unknown>\n\t}): Promise<number> {\n\t\tconst rows = (await tx.execute(\n\t\t\tsql`UPDATE delivery_counter SET value = value + 1 WHERE id = 1 RETURNING value`,\n\t\t)) as unknown as { value: number | string | bigint }[]\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\t// The counter row must always exist (ensureTables seeds it). A missing row would\n\t\t\t// silently return 0 and stamp every op with delivery_seq 0, making them invisible\n\t\t\t// to clients (a `> watermark` scan never returns 0). Fail loudly instead of\n\t\t\t// corrupting the delivery stream.\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn Number(value)\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * @param soleHolder - Nothing else held the (node, sequence) at insert: the row is\n\t * flagged `seq_unique` and covered by {@link NODE_SEQ_UNIQUE_INDEX}. False for a\n\t * legacy pair's second operation and for restored backup rows.\n\t */\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t\tsoleHolder = false,\n\t): typeof pgOperations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\n\t\t\tnodeId: op.nodeId,\n\t\t\ttype: op.type,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tdata: op.data !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t\tseqUnique: soleHolder ? 1 : 0,\n\t\t\thashVersion: op.hashVersion ?? null,\n\t\t\tencrypted: envelopeColumn(op),\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof pgOperations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\tconst encrypted = parseEnvelopeColumn(row.encrypted)\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t\t...(row.hashVersion === 1 || row.hashVersion === 2 ? { hashVersion: row.hashVersion } : {}),\n\t\t\t...(encrypted !== undefined ? { encrypted } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('PostgresServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a PostgresServerStore from a PostgreSQL connection string.\n */\nexport async function createPostgresServerStore(\n\toptions: {\n\t\tconnectionString: string\n\t} & ServerIdentityOptions,\n): Promise<PostgresServerStore> {\n\tconst { postgresClient, drizzleFn } = await loadPostgresDeps()\n\tconst client = postgresClient(options.connectionString)\n\tconst db = drizzleFn(client)\n\n\tconst store = new PostgresServerStore(db, options.nodeId, undefined, {\n\t\t...(options.authoritativeNodeIds ? { authoritativeNodeIds: options.authoritativeNodeIds } : {}),\n\t\t...(options.revokedAuthoritativeNodeIds\n\t\t\t? { revokedAuthoritativeNodeIds: options.revokedAuthoritativeNodeIds }\n\t\t\t: {}),\n\t\t...(options.instanceId !== undefined ? { instanceId: options.instanceId } : {}),\n\t})\n\t// RT-88: fail at startup, where the caller awaits, rather than on the first sync.\n\ttry {\n\t\tawait store.whenReady()\n\t} catch (error) {\n\t\tawait endPostgresClient(client)\n\t\tthrow new ServerStoreUnavailableError(options.connectionString, error)\n\t}\n\treturn store\n}\n\n/**\n * The Postgres server store could not start: the database is unreachable, refused the\n * credentials, or its tables could not be created. `cause` is the driver's error.\n */\nexport class ServerStoreUnavailableError extends KoraError {\n\tconstructor(connectionString: string, cause: unknown) {\n\t\tconst reason = cause instanceof Error ? cause.message : String(cause)\n\t\tsuper(\n\t\t\t`Could not start the PostgreSQL server store (${redactConnectionString(connectionString)}): ${reason}. Check that the database is running and reachable, and that the connection string and credentials are correct.`,\n\t\t\t'SERVER_STORE_UNAVAILABLE',\n\t\t\t{ target: redactConnectionString(connectionString) },\n\t\t)\n\t\tthis.name = 'ServerStoreUnavailableError'\n\t\t;(this as { cause?: unknown }).cause = cause\n\t}\n}\n\n/** host:port/database of a connection string, never its credentials. */\nfunction redactConnectionString(connectionString: string): string {\n\ttry {\n\t\tconst url = new URL(connectionString)\n\t\treturn `${url.hostname}${url.port ? `:${url.port}` : ''}${url.pathname}`\n\t} catch {\n\t\treturn 'invalid connection string'\n\t}\n}\n\nasync function endPostgresClient(client: unknown): Promise<void> {\n\tconst end = (client as { end?: (options?: { timeout?: number }) => Promise<void> }).end\n\tif (typeof end !== 'function') return\n\ttry {\n\t\tawait end.call(client, { timeout: 0 })\n\t} catch {\n\t\t// Best effort: the startup error above is the one that matters.\n\t}\n}\n\nasync function loadPostgresDeps(): Promise<{\n\tpostgresClient: (connectionString: string) => unknown\n\tdrizzleFn: (client: unknown) => PostgresJsDatabase\n}> {\n\t// `postgres` is an optional peer: imported only when this backend is used. The\n\t// specifiers come from an array so no bundler resolves them at build time (an app\n\t// without `postgres` must still bundle), and the import is a real `import()` so it runs\n\t// inside vitest's module runner too. A `new Function('return import(x)')` wrapper did\n\t// neither reliably: it escaped vitest's VM (RT-30) and hid the real error.\n\tconst [postgresSpecifier, drizzleSpecifier] = POSTGRES_DRIVER_SPECIFIERS\n\tlet postgresMod: { default: (cs: string) => unknown }\n\tlet drizzleMod: { drizzle: (client: unknown) => PostgresJsDatabase }\n\ttry {\n\t\tpostgresMod = (await import(/* @vite-ignore */ postgresSpecifier)) as typeof postgresMod\n\t\tdrizzleMod = (await import(/* @vite-ignore */ drizzleSpecifier)) as typeof drizzleMod\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`PostgreSQL backend requires the \"postgres\" package. Install it in your project dependencies. (${error instanceof Error ? error.message : String(error)})`,\n\t\t)\n\t}\n\treturn {\n\t\tpostgresClient: postgresMod.default,\n\t\tdrizzleFn: drizzleMod.drizzle,\n\t}\n}\n\n/** Optional driver modules, loaded on first use of the Postgres backend. */\nconst POSTGRES_DRIVER_SPECIFIERS: readonly [string, string] = [\n\t'postgres',\n\t'drizzle-orm/postgres-js',\n]\n","import { bigint, index, integer, pgTable, text } from 'drizzle-orm/pg-core'\n\n/**\n * Drizzle schema for the Kora sync server's PostgreSQL database.\n *\n * Two tables:\n * - `pgOperations` — the append-only operation log (content-addressed by id)\n * - `pgSyncState` — tracks the max sequence number seen per node (version vector)\n *\n * Column structure mirrors the SQLite drizzle-schema.ts but uses pgTable.\n */\n\nexport const pgOperations = pgTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: bigint('wall_time', { mode: 'number' }).notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\t// BIGINT (SRV-4): a node's sequence numbers are only bounded by Number.MAX_SAFE_INTEGER.\n\t\tsequenceNumber: bigint('sequence_number', { mode: 'number' }).notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: bigint('received_at', { mode: 'number' }).notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit (assigned from\n\t\t// a counter row locked inside the append transaction, so delivery order equals\n\t\t// visibility order even across instances). Drives the gap-free server->client\n\t\t// delivery watermark. Nullable only for pre-column rows, backfilled on startup.\n\t\tdeliverySeq: bigint('delivery_seq', { mode: 'number' }),\n\t\t// JSON { pre, post }: the record's scope values around this operation, captured\n\t\t// from the server's own rows at apply time (RT-14).\n\t\tscopeSnapshot: text('scope_snapshot'),\n\t\t// 1 when this row was the sole holder of its (node_id, sequence_number) when stored;\n\t\t// 0 for the second operation of a legacy duplicate pair and for rows written\n\t\t// before the column existed. The partial unique index NODE_SEQ_UNIQUE_INDEX covers\n\t\t// only flagged rows (RT-37; see server-store.ts).\n\t\tseqUnique: integer('seq_unique').notNull().default(0),\n\t\t// Content-hash version of `id` (CORE-1). Null for v1 rows and rows written before\n\t\t// the column existed.\n\t\thashVersion: integer('hash_version'),\n\t\t// Protocol v2 encryption envelope (JSON), stored opaquely. Null for plaintext.\n\t\tencrypted: text('encrypted'),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_pg_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_pg_collection').on(table.collection),\n\t\treceivedIdx: index('idx_pg_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_pg_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const pgSyncState = pgTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: bigint('max_sequence_number', { mode: 'number' }).notNull(),\n\tlastSeenAt: bigint('last_seen_at', { mode: 'number' }).notNull(),\n})\n","import type { EncryptedOperationEnvelope, Operation } from '@korajs/core'\n\n/**\n * The `encrypted` column value of an operation row (protocol v2 envelope, W9): the\n * envelope as JSON, or null for a plaintext operation. The envelope is opaque to the\n * server; it is stored verbatim so a relayed operation keeps its ciphertext (and the\n * receiver can decrypt it and verify its id).\n *\n * @param op - The operation being stored\n * @returns The column value\n */\nexport function envelopeColumn(op: Operation): string | null {\n\treturn op.encrypted !== undefined ? JSON.stringify(op.encrypted) : null\n}\n\n/**\n * Read the `encrypted` column back. An unreadable value throws, so the startup\n * log-integrity scan quarantines the row instead of relaying a ciphertext-less copy\n * of an encrypted operation as if it were plaintext.\n *\n * @param value - The stored column value\n * @returns The envelope, or undefined for a plaintext operation\n */\nexport function parseEnvelopeColumn(\n\tvalue: string | null | undefined,\n): EncryptedOperationEnvelope | undefined {\n\tif (value === null || value === undefined) return undefined\n\tconst parsed: unknown = JSON.parse(value)\n\tif (\n\t\ttypeof parsed !== 'object' ||\n\t\tparsed === null ||\n\t\t(parsed as { v?: unknown }).v !== 2 ||\n\t\ttypeof (parsed as { keyId?: unknown }).keyId !== 'string'\n\t) {\n\t\tthrow new TypeError(`Unreadable encryption envelope column: ${value.slice(0, 80)}`)\n\t}\n\treturn parsed as EncryptedOperationEnvelope\n}\n\n/**\n * Distinct envelope key ids of stored `encrypted` column values (RT-104), at most\n * `limit`. An unreadable value is skipped here: this is a sample for the key service,\n * and the startup log-integrity scan quarantines such rows.\n *\n * @param values - Stored column values\n * @param limit - Maximum number of key ids\n */\nexport function envelopeKeyIds(\n\tvalues: ReadonlyArray<string | null | undefined>,\n\tlimit: number,\n): string[] {\n\tconst ids = new Set<string>()\n\tfor (const value of values) {\n\t\tif (ids.size >= limit) break\n\t\ttry {\n\t\t\tconst envelope = parseEnvelopeColumn(value)\n\t\t\tif (envelope) ids.add(envelope.keyId)\n\t\t} catch {\n\t\t\t// Not a readable envelope: not evidence of a key either way.\n\t\t}\n\t}\n\treturn [...ids]\n}\n\n/** Rows sampled per key-id query: every ring that sealed history shows up in its first rows. */\nexport const KEY_ID_SAMPLE_ROWS = 512\n","import { canonicalizeLegacyOperation, canonicalizeProvenLegacyClear } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\n\n/**\n * `kora_server_meta` key: the stored log's beta.12 clears were made explicit (RT-85).\n */\nexport const LEGACY_BODIES_META_KEY = 'legacy_bodies_canonical'\n\n/**\n * The stored operations whose body is a beta.12 clear the id PROVES, in their canonical\n * body (every `previousData` key absent from `data` restored as `null`, same id).\n *\n * Every replica folds a stored body as written: the fold has no legacy rule, so a body\n * an earlier release REWROTE under its id (a schema-transformed copy) is never read as a\n * clear (RT-85). A server ingests a protocol-1 upload in this canonical body; operations\n * a beta.12 server stored before the upgrade are made canonical once by this pass, with\n * the same proof devices apply to their logs, so the server and every device fold the\n * same body.\n *\n * @param stored - Stored update operations that declare no hash version\n * @returns The canonical operations that differ from the stored ones\n */\nexport async function provenLegacyClears(stored: readonly Operation[]): Promise<Operation[]> {\n\tconst changed: Operation[] = []\n\tfor (const op of stored) {\n\t\tif (op.type !== 'update' || op.hashVersion !== undefined || op.encrypted !== undefined) continue\n\t\tif (canonicalizeLegacyOperation(op) === op) continue\n\t\tconst canonical = await canonicalizeProvenLegacyClear(op)\n\t\tif (canonical !== op) changed.push(canonical)\n\t}\n\treturn changed\n}\n","/**\n * Server-side log-integrity scan (W8 step 0), run once per database by the SQLite and\n * Postgres stores' startup migration, before anything materializes or re-materializes\n * from the operation log.\n *\n * A stored operation must be readable back into an `Operation`: valid JSON in its JSON\n * columns, a well-formed HLC (non-negative integer wall time, logical counter in range,\n * timestamp node id), a known type and a positive sequence number. The server's typed\n * columns rule out the client's beta.12 restore damage (`NOT NULL` wall time), so there\n * is nothing to repair in place: a row that fails is moved, verbatim, to\n * {@link SERVER_LOG_QUARANTINE_TABLE} and reported, instead of crashing every fold that\n * reads it.\n */\n\n/** Rows moved out of `operations`, kept verbatim. Never cleared automatically. */\nexport const SERVER_LOG_QUARANTINE_TABLE = 'operations_quarantine'\n\n/** `kora_server_meta` key recording that the one-time scan ran. */\nexport const SERVER_LOG_INTEGRITY_META_KEY = 'log_integrity_scan_v1'\n\n/** HLC logical counter bound (matches `HybridLogicalClock.serialize`). */\nconst MAX_LOGICAL = 99_999\n/** Wall times are zero-padded to 15 digits when serialized. */\nconst WALL_TIME_LIMIT = 1e15\n\nconst OPERATION_TYPES = new Set(['insert', 'update', 'delete'])\n\n/** The raw columns of a stored operation row (both SQL dialects). */\nexport interface ServerOperationRow {\n\tid: unknown\n\tnode_id: unknown\n\ttype: unknown\n\tcollection: unknown\n\trecord_id: unknown\n\tdata: unknown\n\tprevious_data: unknown\n\tatomic_ops: unknown\n\twall_time: unknown\n\tlogical: unknown\n\ttimestamp_node_id: unknown\n\tsequence_number: unknown\n\tcausal_deps: unknown\n\tschema_version: unknown\n}\n\n/** A row the scan quarantined. */\nexport interface ServerLogIntegrityRow {\n\toperationId: string\n\tproblem: string\n\tdetail: string\n}\n\n/** Result of the server scan. */\nexport interface ServerLogIntegrityReport {\n\t/** Rows checked by this scan (0 when it already ran on this database). */\n\tcheckedRows: number\n\t/** Rows this scan moved to the quarantine table. */\n\tquarantined: ServerLogIntegrityRow[]\n\t/** False when the one-time scan had already run (only the quarantine is reported). */\n\tran: boolean\n\t/** Every row in the quarantine table. */\n\ttotalQuarantined: number\n}\n\n/** DDL of the quarantine table (portable between SQLite and Postgres). */\nexport const SERVER_LOG_QUARANTINE_DDL = `CREATE TABLE IF NOT EXISTS ${SERVER_LOG_QUARANTINE_TABLE} (\n id TEXT PRIMARY KEY,\n problem TEXT NOT NULL,\n detail TEXT NOT NULL,\n row_json TEXT NOT NULL,\n quarantined_at BIGINT NOT NULL\n)`\n\n/**\n * Judge one stored operation row.\n *\n * @returns null when the row is a readable operation, else what is wrong with it\n */\nexport function checkServerOperationRow(\n\trow: ServerOperationRow,\n): { problem: string; detail: string } | null {\n\tfor (const column of ['id', 'node_id', 'collection', 'record_id', 'timestamp_node_id'] as const) {\n\t\tif (typeof row[column] !== 'string' || (row[column] as string).length === 0) {\n\t\t\treturn { problem: 'identity-malformed', detail: `${column} is missing` }\n\t\t}\n\t}\n\tif (typeof row.type !== 'string' || !OPERATION_TYPES.has(row.type)) {\n\t\treturn { problem: 'type-invalid', detail: `type ${JSON.stringify(row.type)}` }\n\t}\n\tconst sequence = toInteger(row.sequence_number)\n\tif (sequence === null || sequence < 1) {\n\t\treturn { problem: 'sequence-invalid', detail: `sequence_number ${String(row.sequence_number)}` }\n\t}\n\tconst wall = toInteger(row.wall_time)\n\tconst logical = toInteger(row.logical)\n\tif (wall === null || wall < 0 || wall >= WALL_TIME_LIMIT) {\n\t\treturn { problem: 'timestamp-malformed', detail: `wall_time ${String(row.wall_time)}` }\n\t}\n\tif (logical === null || logical < 0 || logical > MAX_LOGICAL) {\n\t\treturn { problem: 'timestamp-malformed', detail: `logical ${String(row.logical)}` }\n\t}\n\tfor (const column of ['data', 'previous_data', 'atomic_ops'] as const) {\n\t\tif (!isJsonObjectOrNull(row[column])) {\n\t\t\treturn { problem: 'data-malformed', detail: `${column} is not a JSON object` }\n\t\t}\n\t}\n\tif (!isJsonStringArray(row.causal_deps)) {\n\t\treturn { problem: 'causal-deps-malformed', detail: 'causal_deps is not a JSON array of ids' }\n\t}\n\treturn null\n}\n\n/** Serialize a row for the quarantine table (bigint-safe). */\nexport function quarantineRowJson(row: ServerOperationRow): string {\n\treturn JSON.stringify(row, (_key, value: unknown) =>\n\t\ttypeof value === 'bigint' ? value.toString() : value,\n\t)\n}\n\nfunction toInteger(value: unknown): number | null {\n\tif (typeof value === 'bigint') return Number(value)\n\tif (typeof value === 'number') return Number.isInteger(value) ? value : null\n\t// Postgres BIGINT columns arrive as strings.\n\tif (typeof value === 'string' && /^-?\\d+$/.test(value)) return Number(value)\n\treturn null\n}\n\nfunction isJsonObjectOrNull(value: unknown): boolean {\n\tif (value === null || value === undefined) return true\n\tif (typeof value !== 'string') return false\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(value)\n\t\treturn parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n\t} catch {\n\t\treturn false\n\t}\n}\n\nfunction isJsonStringArray(value: unknown): boolean {\n\tif (typeof value !== 'string') return false\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(value)\n\t\treturn Array.isArray(parsed) && parsed.every((id) => typeof id === 'string')\n\t} catch {\n\t\treturn false\n\t}\n}\n","/**\n * Records with quarantined history (RT-70).\n *\n * The startup log-integrity scan (W8 step 0) moves unreadable operation rows to\n * `operations_quarantine`. A record that owned such a row has an incomplete log:\n * re-folding it from the remaining operations drops the quarantined operation's effect,\n * and the record itself when its insert was quarantined. Its materialized row (written\n * before the scan, when every operation was still readable) is the only complete view,\n * so the stores keep it as a snapshot base and fold the remaining and later operations\n * onto it, for exactly those records; every other record folds from its (complete) log.\n */\nimport { HybridLogicalClock, createSnapshotState, getFoldFieldVersions } from '@korajs/core'\nimport type { FoldState, HLCTimestamp, Operation, SchemaDefinition } from '@korajs/core'\nimport {\n\tREFOLD_REQUIRED,\n\ttype ServerFoldOptions,\n\tmergeIntoFoldState,\n\trefoldRecord,\n} from './record-fold'\n\n/** A materialized row, as a snapshot base for {@link rebuildFromSnapshot}. */\nexport interface KeptRow {\n\t/** Field values (record form). */\n\tvalues: Record<string, unknown>\n\t/** `_created_at` (wall ms). */\n\tcreatedAt: number\n\t/** `_updated_at` (wall ms). */\n\tupdatedAt: number\n\t/** `_deleted`. */\n\tdeleted: boolean\n}\n\n/** What the log-integrity scan quarantined, by record. */\nexport interface QuarantineScope {\n\t/** Keys ({@link quarantineKey}) of every record owning a quarantined row. */\n\trecords: Set<string>\n\t/** Collections where a quarantined row named no readable record: every record is affected. */\n\tcollections: Set<string>\n\t/** A quarantined row named no readable collection: every record is affected. */\n\tall: boolean\n\t/** Newest readable HLC of the quarantined rows, per record key. */\n\tlatest: Map<string, HLCTimestamp>\n}\n\n/** Key of a record in a {@link QuarantineScope}. */\nexport function quarantineKey(collection: string, recordId: string): string {\n\treturn JSON.stringify([collection, recordId])\n}\n\n/** An empty scope (a clean log). */\nexport function emptyQuarantineScope(): QuarantineScope {\n\treturn { records: new Set(), collections: new Set(), all: false, latest: new Map() }\n}\n\n/** True when the record owns (or may own) a quarantined operation. */\nexport function isQuarantineAffected(\n\tscope: QuarantineScope,\n\tcollection: string,\n\trecordId: string,\n): boolean {\n\treturn (\n\t\tscope.all ||\n\t\tscope.collections.has(collection) ||\n\t\tscope.records.has(quarantineKey(collection, recordId))\n\t)\n}\n\n/**\n * Build the scope from the quarantine table's `row_json` values. A row whose\n * collection or record id is unreadable widens the scope (its collection, or all).\n */\nexport function buildQuarantineScope(rowJsons: Iterable<string>): QuarantineScope {\n\tconst scope = emptyQuarantineScope()\n\tfor (const json of rowJsons) {\n\t\tlet row: Record<string, unknown>\n\t\ttry {\n\t\t\trow = JSON.parse(json) as Record<string, unknown>\n\t\t} catch {\n\t\t\tscope.all = true\n\t\t\tcontinue\n\t\t}\n\t\tconst collection = row.collection\n\t\tconst recordId = row.record_id\n\t\tif (typeof collection !== 'string' || collection.length === 0) {\n\t\t\tscope.all = true\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof recordId !== 'string' || recordId.length === 0) {\n\t\t\tscope.collections.add(collection)\n\t\t\tcontinue\n\t\t}\n\t\tconst key = quarantineKey(collection, recordId)\n\t\tscope.records.add(key)\n\t\tconst wall = Number(row.wall_time)\n\t\tconst logical = Number(row.logical)\n\t\tif (Number.isSafeInteger(wall) && wall >= 0 && Number.isSafeInteger(logical) && logical >= 0) {\n\t\t\tconst ts: HLCTimestamp = {\n\t\t\t\twallTime: wall,\n\t\t\t\tlogical,\n\t\t\t\tnodeId: typeof row.timestamp_node_id === 'string' ? row.timestamp_node_id : '',\n\t\t\t}\n\t\t\tconst prior = scope.latest.get(key)\n\t\t\tif (!prior || HybridLogicalClock.compare(ts, prior) > 0) scope.latest.set(key, ts)\n\t\t}\n\t}\n\treturn scope\n}\n\n/**\n * The fold state of a record whose log is incomplete: never re-folded from the\n * remaining operations alone. The base is the record's stored fold state when it can\n * take the remaining operations, else a snapshot of its kept row (`createSnapshotState`),\n * each field stamped at its newest known version (from the remaining log, and at least\n * the quarantined operations' newest readable HLC, since the row reflects them). The\n * remaining operations are merged onto the base (a no-op for those the row already\n * reflects). Lossy only as snapshots are: a late concurrent write older than a field's\n * version folds against the snapshot value (RT-68's caveat).\n *\n * @returns The state, or null when the record has no kept row, state or operations\n */\nexport function rebuildFromSnapshot(\n\tinput: {\n\t\tcollection: string\n\t\trecordId: string\n\t\tstored: FoldState | null\n\t\trow: KeptRow | null\n\t\tops: readonly Operation[]\n\t\tquarantinedLatest?: HLCTimestamp | undefined\n\t},\n\tschema: SchemaDefinition,\n\toptions: ServerFoldOptions,\n): FoldState | null {\n\tif (input.stored) {\n\t\tconst merged = mergeIntoFoldState(input.stored, input.ops, schema, options)\n\t\tif (merged !== REFOLD_REQUIRED && merged !== null) return merged\n\t}\n\tif (!input.row) return input.ops.length > 0 ? refoldRecord(input.ops, schema, options) : null\n\tconst fromLog = input.ops.length > 0 ? refoldRecord(input.ops, schema, options) : null\n\tconst versions = fromLog ? getFoldFieldVersions(fromLog) : null\n\tconst floor = input.quarantinedLatest\n\tconst atLeast = (ts: HLCTimestamp | undefined): HLCTimestamp | undefined => {\n\t\tif (!ts) return floor\n\t\tif (!floor) return ts\n\t\treturn HybridLogicalClock.compare(ts, floor) >= 0 ? ts : floor\n\t}\n\tconst rowWall = (wall: number): HLCTimestamp => ({ wallTime: wall, logical: 0, nodeId: '' })\n\tconst latest =\n\t\tatLeast(versions?.latest) ?? rowWall(Math.max(input.row.updatedAt, input.row.createdAt))\n\tconst fieldVersions: Record<string, HLCTimestamp> = {}\n\tfor (const field of Object.keys(input.row.values)) {\n\t\tfieldVersions[field] = atLeast(versions?.fields[field]) ?? latest\n\t}\n\tconst base = createSnapshotState(\n\t\t{\n\t\t\tcollection: input.collection,\n\t\t\trecordId: input.recordId,\n\t\t\tvalues: input.row.values,\n\t\t\tfieldVersions,\n\t\t\tcreated: versions?.created ?? rowWall(input.row.createdAt),\n\t\t\tlatest,\n\t\t\tdeleted: input.row.deleted,\n\t\t},\n\t\tschema,\n\t)\n\tconst merged = mergeIntoFoldState(base, input.ops, schema, options)\n\treturn merged === REFOLD_REQUIRED || merged === null ? base : merged\n}\n","/**\n * Lossless string encoding at the SQL boundary of the server stores (RT-65).\n *\n * Every JavaScript string must round-trip through the Postgres server store exactly as\n * it does through the memory and SQLite stores and every client store. Postgres cannot\n * hold two kinds of JS string content:\n *\n * - U+0000: TEXT refuses it (`invalid byte sequence for encoding \"UTF8\": 0x00`) and\n * JSONB refuses the `\\u0000` escape.\n * - A lone UTF-16 surrogate: the driver encodes it to UTF-8 as U+FFFD (silent\n * corruption) and JSONB refuses the unpaired `\\uD800` escape.\n *\n * The codec maps those code units to an escape introduced by U+FFFF, a Unicode\n * noncharacter (valid UTF-8, never assigned):\n *\n * | Input | Stored |\n * |---|---|\n * | U+0000 | U+FFFF `0` |\n * | U+FFFF | U+FFFF `F` |\n * | lone surrogate `\\uXXXX` | U+FFFF `s` + 4 lowercase hex digits |\n *\n * SQLite (better-sqlite3 binds strings as UTF-8) loses lone surrogates the same way,\n * so its raw-string columns use the same codec; its array/object/json columns hold\n * `JSON.stringify` text, which escapes both.\n *\n * Every other string is stored unchanged, so existing rows, equality filters and\n * ordering are unaffected for ordinary text. The map is injective, and decode(encode(s))\n * is s for every JS string. Rows written before the codec that contain U+FFFF are\n * re-encoded once per table by {@link pgTextCodecMigrationSql}.\n *\n * Ordering of escaped strings: range filters (`$gt`, `$lt`, ...) and `orderBy` compare\n * the stored (encoded) form, in the database's collation (UTF-8 byte order on SQLite and\n * on Postgres with `C.UTF-8`). A string containing U+0000, U+FFFF or a lone surrogate\n * therefore sorts by its escape, U+FFFF, at the position of the first such code unit:\n * after every other BMP character there, and before supplementary-plane characters.\n * For example `\"a\\u0000\"` sorts after `\"ab\"` (in JavaScript it sorts before), and a\n * lone surrogate sorts after `\"\\uFFFE\"`. Such strings are rare and equality is exact;\n * do not rely on their relative order in range queries.\n *\n * Operation columns hold `JSON.stringify` output, which already escapes U+0000 and\n * lone surrogates (well-formed JSON.stringify), so they need no codec.\n */\n\nimport {\n\tSTORED_TEXT_ESCAPE,\n\tdecodeStoredJsonValue,\n\tdecodeStoredText,\n\tencodeStoredJsonValue,\n\tencodeStoredText,\n\tneedsStoredTextEncoding,\n} from '@korajs/core'\nimport type { FieldDescriptor } from '@korajs/core'\nimport { deserializeFieldValue, serializeFieldValue } from './materialization'\n\n// The codec itself is core's (`@korajs/core` stored-text), shared with the client\n// stores, so a value escapes identically on every device and server.\n\n/** The escape introducer: U+FFFF, a noncharacter. */\nexport const PG_TEXT_ESCAPE = STORED_TEXT_ESCAPE\n\n/** `kora_server_meta` key prefix marking a table whose legacy U+FFFF rows were re-encoded. */\nexport const PG_TEXT_CODEC_MIGRATION_KEY = 'pg_text_codec_v1:'\n\n/** True when `s` contains a code unit Postgres cannot store as is. */\nexport const needsPgTextEncoding: (s: string) => boolean = needsStoredTextEncoding\n\n/** Encode a JS string for a Postgres TEXT (or JSONB string) value. */\nexport const encodePgText: (s: string) => string = encodeStoredText\n\n/** Decode a string written by {@link encodePgText}. */\nexport const decodePgText: (s: string) => string = decodeStoredText\n\n/** Encode every string (and object key) inside a JSON value. */\nexport const encodePgJsonValue: (value: unknown) => unknown = encodeStoredJsonValue\n\n/** Decode every string (and object key) inside a JSON value. */\nexport const decodePgJsonValue: (value: unknown) => unknown = decodeStoredJsonValue\n\n/**\n * The one-time statements re-encoding rows written before the codec: every U+FFFF in\n * a TEXT or JSONB column becomes U+FFFF `F`, so the decoder returns it unchanged.\n *\n * @param table - Quoted table name\n * @param textColumns - Quoted TEXT columns holding raw strings\n * @param jsonbColumns - Quoted JSONB columns\n */\nexport function pgTextCodecMigrationSql(\n\ttable: string,\n\ttextColumns: string[],\n\tjsonbColumns: string[],\n): string[] {\n\tconst esc = \"U&'\\\\FFFF'\"\n\tconst statements: string[] = []\n\tfor (const column of textColumns) {\n\t\tstatements.push(\n\t\t\t`UPDATE ${table} SET ${column} = replace(${column}, ${esc}, ${esc} || 'F') WHERE strpos(${column}, ${esc}) > 0`,\n\t\t)\n\t}\n\tfor (const column of jsonbColumns) {\n\t\tstatements.push(\n\t\t\t`UPDATE ${table} SET ${column} = replace(${column}::text, ${esc}, ${esc} || 'F')::jsonb WHERE strpos(${column}::text, ${esc}) > 0`,\n\t\t)\n\t}\n\treturn statements\n}\n\n/** Field kinds stored as raw strings in TEXT columns (encoded with {@link encodePgText}). */\nconst RAW_TEXT_KINDS = new Set(['string', 'enum', 'secret'])\n/** Field kinds stored in JSONB columns (strings inside encoded with {@link encodePgJsonValue}). */\nconst JSONB_KINDS = new Set(['array', 'object', 'json'])\n\n/** True for a field kind whose Postgres column holds raw strings. */\nexport function isPgRawTextKind(kind: string): boolean {\n\treturn RAW_TEXT_KINDS.has(kind)\n}\n\n/** True for a field kind whose Postgres column is JSONB. */\nexport function isPgJsonbKind(kind: string): boolean {\n\treturn JSONB_KINDS.has(kind)\n}\n\n/** {@link serializeFieldValue} for a Postgres column: lossless for every JS string. */\nexport function serializePgFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tif (RAW_TEXT_KINDS.has(descriptor.kind) && typeof value === 'string') {\n\t\treturn encodePgText(value)\n\t}\n\t// A json value that is a string is JSON too (a JSONB string), never raw column text.\n\tif (\n\t\tJSONB_KINDS.has(descriptor.kind) &&\n\t\t(typeof value !== 'string' || descriptor.kind === 'json')\n\t) {\n\t\treturn JSON.stringify(encodePgJsonValue(value))\n\t}\n\treturn serializeFieldValue(value, descriptor)\n}\n\n/** {@link deserializeFieldValue} for a Postgres column written by {@link serializePgFieldValue}. */\nexport function deserializePgFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tif (RAW_TEXT_KINDS.has(descriptor.kind) && typeof value === 'string') {\n\t\treturn decodePgText(value)\n\t}\n\t// The driver returns a JSONB column parsed: a json value that is a string arrives as\n\t// that string and must not be parsed again (\"123\" stays \"123\").\n\tif (descriptor.kind === 'json') return decodePgJsonValue(value)\n\tconst parsed = deserializeFieldValue(value, descriptor)\n\treturn JSONB_KINDS.has(descriptor.kind) ? decodePgJsonValue(parsed) : parsed\n}\n\n/** {@link serializeFieldValue} for a SQLite column: lossless for every JS string. */\nexport function serializeSqliteFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (RAW_TEXT_KINDS.has(descriptor.kind) && typeof value === 'string') return encodePgText(value)\n\treturn serializeFieldValue(value, descriptor)\n}\n\n/** {@link deserializeFieldValue} for a SQLite column written by {@link serializeSqliteFieldValue}. */\nexport function deserializeSqliteFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (RAW_TEXT_KINDS.has(descriptor.kind) && typeof value === 'string') return decodePgText(value)\n\treturn deserializeFieldValue(value, descriptor)\n}\n\n/**\n * SQLite form of {@link pgTextCodecMigrationSql}: re-encode the U+FFFF of rows written\n * before the codec in raw-string columns.\n */\nexport function sqliteTextCodecMigrationSql(table: string, textColumns: string[]): string[] {\n\treturn textColumns.map(\n\t\t(column) =>\n\t\t\t`UPDATE ${table} SET ${column} = replace(${column}, char(65535), char(65535) || 'F') WHERE instr(${column}, char(65535)) > 0`,\n\t)\n}\n","import { createRequire } from 'node:module'\nimport type {\n\tAtomicOp,\n\tFoldState,\n\tHLCTimestamp,\n\tOperation,\n\tOperationTransform,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n\tVersionVector,\n} from '@korajs/core'\nimport { assertOperationTransformCoverage, quoteIdent } from '@korajs/core'\nimport { type SqliteQueryFn, planSqliteConstraintRelaxation } from '@korajs/core/internal'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, eq, gt, sql } from 'drizzle-orm'\nimport type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'\nimport { UplinkAuthorizationError } from '../scopes/server-scope-filter'\nimport { deliveryCounter, operations, syncState } from './drizzle-schema'\nimport {\n\tKEY_ID_SAMPLE_ROWS,\n\tenvelopeColumn,\n\tenvelopeKeyIds,\n\tparseEnvelopeColumn,\n} from './envelope-column'\nimport { LEGACY_BODIES_META_KEY, provenLegacyClears } from './legacy-bodies'\nimport {\n\tSERVER_LOG_INTEGRITY_META_KEY,\n\tSERVER_LOG_QUARANTINE_DDL,\n\ttype ServerLogIntegrityReport,\n\ttype ServerOperationRow,\n\tcheckServerOperationRow,\n\tquarantineRowJson,\n} from './log-integrity'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport {\n\ttype KeptRow,\n\ttype QuarantineScope,\n\tbuildQuarantineScope,\n\temptyQuarantineScope,\n\tisQuarantineAffected,\n\tquarantineKey,\n\trebuildFromSnapshot,\n} from './quarantine-base'\nimport {\n\tEMPTY_FOLD_SCHEMA,\n\tFOLD_MIGRATION_BATCH,\n\tFOLD_PLAN_FINGERPRINT_KEY,\n\ttype FoldMigrationReport,\n\tREFOLD_REQUIRED,\n\ttype ServerFoldOptions,\n\tfoldFieldVersions,\n\tmaterializedFieldValue,\n\tmergeIntoFoldState,\n\tparseStoredFoldState,\n\tprojectFoldState,\n\trefoldRecord,\n\tserializeServerFoldState,\n\tserverFoldOptions,\n\tserverFoldPlanFingerprint,\n} from './record-fold'\nimport {\n\tSCOPE_SNAPSHOT_FINGERPRINT_KEY,\n\tparseScopeSnapshot,\n\treplayScopeSnapshots,\n\tscopeSnapshotFingerprint,\n\tscopeValuesOf,\n} from './scope-snapshot'\nimport {\n\ttype AuthorityHistory,\n\ttype ConfiguredIdentity,\n\tSERVER_DEPLOYMENT_ID_KEY,\n\tSERVER_DERIVATION_SECRET_KEY,\n\tSERVER_EVER_AUTHORITY_KEY,\n\tSERVER_INSTANCE_ID_KEY,\n\tSERVER_LEGACY_AUTHORITY_KEY,\n\tSERVER_LEGACY_SCAN_KEY,\n\tSERVER_NODE_PREFIX,\n\tSERVER_REVOKED_AUTHORITY_KEY,\n\ttype ServerIdentityOptions,\n\tauthoritativeStampOpIds,\n\tderiveKeyedServerOpId,\n\tgenerateDeploymentId,\n\tgenerateDerivationSecret,\n\tnormalizeLegacyAuthorities,\n\tparseIdentityOptions,\n\tparseLegacyAuthorities,\n\tresolveAuthorityHistory,\n\tserverNodeIdFor,\n} from './server-identity'\nimport type {\n\tApplyRemoteOptions,\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tEncryptionKeyRecordRow,\n\tMaterializedRecord,\n\tOperationResolution,\n\tOperationResolutionOutcome,\n\tOperationScopeSnapshot,\n\tServerSchemaOptions,\n\tServerStore,\n} from './server-store'\nimport {\n\tMAX_RESOLUTION_MESSAGE_LENGTH,\n\tNODE_SEQ_UNIQUE_INDEX,\n\tRELEASED_NODE_OWNER,\n\tSEQUENCE_ENFORCEMENT_EPOCH_KEY,\n\tSEQUENCE_PAIRS_BACKFILLED_KEY,\n\tSUPERSEDED_NODE_SEQ_UNIQUE_INDEXES,\n\tSequenceConflictError,\n\ttype SequenceHolderVerdict,\n\tUnstorableValueError,\n\tjudgeSequenceHolders,\n\treportLegacyPair,\n} from './server-store'\nimport type { StoredOperationKey } from './server-store'\nimport {\n\tPG_TEXT_CODEC_MIGRATION_KEY,\n\tdeserializeSqliteFieldValue,\n\tencodePgText,\n\tisPgRawTextKind,\n\tserializeSqliteFieldValue,\n\tsqliteTextCodecMigrationSql,\n} from './text-codec'\n\n/** Index every (node, sequence) the log holds more than once (RT-48). */\nconst BACKFILL_SEQUENCE_PAIRS_SQL = `INSERT OR IGNORE INTO sequence_pairs (node_id, sequence_number)\n\tSELECT node_id, sequence_number FROM operations\n\tGROUP BY node_id, sequence_number HAVING COUNT(*) > 1`\n\n/**\n * Drop resolutions above their node's restored log, and every `stored-elsewhere`\n * resolution whose operation the restored log does not hold (RT-51; see importBackup).\n */\nconst PRUNE_RESOLUTIONS_PAST_LOG_SQL = `DELETE FROM operation_resolutions\n\tWHERE sequence_number > COALESCE(\n\t\t(SELECT max_sequence_number FROM sync_state WHERE sync_state.node_id = operation_resolutions.node_id),\n\t\t0)\n\tOR (outcome = 'stored-elsewhere'\n\t\tAND NOT EXISTS (SELECT 1 FROM operations o WHERE o.id = operation_resolutions.op_id))`\n\ninterface ResolutionRow {\n\top_id: string\n\tnode_id: string\n\tsequence_number: number | string\n\toutcome: string\n\tcode: string | null\n\tmessage: string | null\n}\n\nfunction resolutionFromRow(row: ResolutionRow): OperationResolution {\n\treturn {\n\t\toperationId: row.op_id,\n\t\tnodeId: row.node_id,\n\t\tsequenceNumber: Number(row.sequence_number),\n\t\toutcome: row.outcome as OperationResolutionOutcome,\n\t\tcode: row.code,\n\t\tmessage: row.message,\n\t}\n}\n\n// better-sqlite3 is a native CJS addon that cannot be loaded via ESM import().\n// createRequire provides a CJS require() that works in both ESM and CJS contexts.\n// tsup's shims option ensures import.meta.url is available in CJS builds.\nconst esmRequire = createRequire(import.meta.url)\n\n/**\n * SQLite result codes of values the database refuses (RT-87): an enum CHECK, a NOT NULL,\n * a value larger than SQLite's limits. Such an operation is refused terminally and per\n * operation (UNSTORABLE_VALUE), like the Postgres store's class-22/23 errors, so it can\n * never block the session. (The server's value-domain check refuses every such value\n * before it reaches a store; this is the safety net.)\n */\nconst SQLITE_UNSTORABLE_VALUE_CODES = new Set([\n\t'SQLITE_CONSTRAINT_CHECK',\n\t'SQLITE_CONSTRAINT_NOTNULL',\n\t'SQLITE_TOOBIG',\n\t'SQLITE_MISMATCH',\n])\n\nfunction sqliteUnstorableValueOr(error: unknown, op: Operation): unknown {\n\tconst codeOf = (value: unknown): unknown =>\n\t\tvalue && typeof value === 'object' && 'code' in value\n\t\t\t? (value as { code: unknown }).code\n\t\t\t: undefined\n\tconst code = codeOf(error) ?? (error instanceof Error ? codeOf(error.cause) : undefined)\n\tif (typeof code === 'string' && SQLITE_UNSTORABLE_VALUE_CODES.has(code)) {\n\t\treturn new UnstorableValueError(\n\t\t\top,\n\t\t\t`${code}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t)\n\t}\n\treturn error\n}\n\n/**\n * SQLite-backed server store using Drizzle ORM.\n * Persists operations and version vectors to a real database file,\n * surviving process restarts.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class SqliteServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly db: BetterSQLite3Database\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\t/** See {@link SEQUENCE_ENFORCEMENT_EPOCH_KEY}; fixed per database at first start. */\n\tprivate sequenceEpoch = 0\n\tprivate logIntegrity: ServerLogIntegrityReport = {\n\t\tcheckedRows: 0,\n\t\tquarantined: [],\n\t\tran: false,\n\t\ttotalQuarantined: 0,\n\t}\n\t/** Derivation secret of server-derived ids, shared by the deployment (RT-64). */\n\tprivate readonly derivationSecret: string\n\t/** Legacy and configured authorities (the `kora:server:` prefix needs no listing). */\n\tprivate readonly explicitAuthorities: string[]\n\t/** Explicit authority over time: revoked and ever-held ids (RT-81). */\n\tprivate readonly authorityHistory: AuthorityHistory\n\t/** Other `kora:server:` nodes with stored operations (advertised for older clients). */\n\t/** Records owning quarantined operations: folded onto their kept rows (RT-70). */\n\tprivate quarantine: QuarantineScope = emptyQuarantineScope()\n\tprivate foldOptions: ServerFoldOptions\n\t/** Schema transforms the fold applies (transforms at fold time, RT-84). */\n\tprivate operationTransforms: readonly OperationTransform[] = []\n\tprivate foldMigration: FoldMigrationReport = {\n\t\tran: false,\n\t\trecords: 0,\n\t\tskippedUnclean: 0,\n\t\tfullRefold: false,\n\t}\n\n\t/**\n\t * @param db - The Drizzle database\n\t * @param nodeId - Deprecated: a plain id is recorded as a legacy authoritative id; a\n\t * `kora:server:` id is used verbatim. Leave unset: the store authors under\n\t * `kora:server:<deployment>:<instance>`, both persisted in the database (RT-62).\n\t * @param options - Extra authoritative ids and the instance id\n\t */\n\tconstructor(\n\t\tdb: BetterSQLite3Database,\n\t\tnodeId?: string,\n\t\toptions: Omit<ServerIdentityOptions, 'nodeId'> = {},\n\t) {\n\t\tthis.db = db\n\t\tconst configured = parseIdentityOptions({\n\t\t\t...(nodeId !== undefined ? { nodeId } : {}),\n\t\t\t...options,\n\t\t})\n\t\tthis.ensureTables()\n\t\tconst identity = this.loadIdentity(configured)\n\t\tthis.nodeId = identity.nodeId\n\t\tthis.derivationSecret = identity.secret\n\t\tthis.explicitAuthorities = identity.history.explicitAuthorities\n\t\tthis.authorityHistory = identity.history\n\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t\tfor (const row of this.db.all<{ node_id: string }>(\n\t\t\tsql`SELECT node_id FROM sync_state WHERE node_id LIKE ${`${SERVER_NODE_PREFIX}%`}`,\n\t\t)) {\n\t\t}\n\t}\n\n\t/**\n\t * This store's node id and the legacy and configured ids (explicit authorities).\n\t * Other `kora:server:` instances are not listed: the prefix rule makes every one of\n\t * them authoritative, and a list that grew by one instance id per start would make\n\t * every device re-fold after each deploy (RT-75). Handshakes advertise only the\n\t * explicit (non-prefixed) ids.\n\t */\n\tgetAuthoritativeNodeIds(): string[] {\n\t\treturn [this.nodeId, ...this.explicitAuthorities]\n\t}\n\n\t/** Legacy and configured authorities (beside the `kora:server:` namespace). */\n\tgetLegacyAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.explicitAuthorities]\n\t}\n\n\t/** Explicit authoritative ids the deployment revoked (RT-81), advertised at handshake. */\n\tgetRevokedAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.authorityHistory.revoked]\n\t}\n\n\t/**\n\t * Every explicit id the deployment ever held authoritative, revoked ones included\n\t * (RT-81): never accepted as a device node id.\n\t */\n\tgetEverAuthoritativeNodeIds(): string[] {\n\t\treturn [...this.authorityHistory.everAuthoritative]\n\t}\n\n\tasync deriveServerOperationId(\n\t\tparentOpId: string,\n\t\truleId: string,\n\t\ttargetRecordId: string,\n\t): Promise<string> {\n\t\treturn deriveKeyedServerOpId(this.derivationSecret, parentOpId, ruleId, targetRecordId)\n\t}\n\n\t/** Remember another `kora:server:` node that authored stored operations. */\n\n\t/**\n\t * Load (creating on first start) the persisted server identity: the deployment id,\n\t * the derivation secret, this database's instance id and the legacy authoritative\n\t * ids. At the first start of this release, every node id whose operations hold an\n\t * authority class in a stored fold state (a server decision folded under an earlier,\n\t * per-process server node id) is recorded as a legacy authority, before any re-fold\n\t * could drop that class.\n\t */\n\tprivate loadIdentity(configured: ConfiguredIdentity): {\n\t\tnodeId: string\n\t\tsecret: string\n\t\thistory: AuthorityHistory\n\t} {\n\t\tconst meta = (tx: BetterSQLite3Database, key: string): string | undefined =>\n\t\t\ttx.all<{ value: string }>(sql`SELECT value FROM kora_server_meta WHERE key = ${key}`)[0]\n\t\t\t\t?.value\n\t\tconst setOnce = (tx: BetterSQLite3Database, key: string, value: string): string => {\n\t\t\ttx.run(sql`INSERT OR IGNORE INTO kora_server_meta (key, value) VALUES (${key}, ${value})`)\n\t\t\treturn meta(tx, key) ?? value\n\t\t}\n\t\treturn this.db.transaction((tx) => {\n\t\t\tconst deploymentId = setOnce(tx, SERVER_DEPLOYMENT_ID_KEY, generateDeploymentId())\n\t\t\tconst secret = setOnce(tx, SERVER_DERIVATION_SECRET_KEY, generateDerivationSecret())\n\t\t\t// One SQLite database has one writer process, so one persisted instance id.\n\t\t\tconst instanceId = configured.instanceId ?? setOnce(tx, SERVER_INSTANCE_ID_KEY, '1')\n\t\t\tconst nodeId = configured.verbatimNodeId ?? serverNodeIdFor(deploymentId, instanceId)\n\n\t\t\tlet legacy = parseLegacyAuthorities(meta(tx, SERVER_LEGACY_AUTHORITY_KEY))\n\t\t\tif (meta(tx, SERVER_LEGACY_SCAN_KEY) === undefined) {\n\t\t\t\tconst stampOpIds = new Set<string>()\n\t\t\t\tfor (const row of tx.all<{ state: string }>(sql`SELECT state FROM kora_fold_state`)) {\n\t\t\t\t\tfor (const id of authoritativeStampOpIds(row.state)) stampOpIds.add(id)\n\t\t\t\t}\n\t\t\t\tconst ids = [...stampOpIds]\n\t\t\t\tfor (let i = 0; i < ids.length; i += 500) {\n\t\t\t\t\tconst chunk = ids.slice(i, i + 500)\n\t\t\t\t\tconst rows = tx.all<{ node_id: string }>(\n\t\t\t\t\t\tsql`SELECT DISTINCT node_id FROM operations WHERE id IN (${sql.join(\n\t\t\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`,\n\t\t\t\t\t)\n\t\t\t\t\tlegacy.push(...rows.map((row) => row.node_id))\n\t\t\t\t}\n\t\t\t\ttx.run(\n\t\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SERVER_LEGACY_SCAN_KEY}, ${String(Date.now())})`,\n\t\t\t\t)\n\t\t\t}\n\t\t\t// A configured plain node id is the id this server authored under before (RT-62).\n\t\t\tif (configured.legacyNodeId !== null) legacy.push(configured.legacyNodeId)\n\t\t\tlegacy = normalizeLegacyAuthorities(legacy.filter((id) => id !== nodeId))\n\t\t\ttx.run(\n\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SERVER_LEGACY_AUTHORITY_KEY}, ${JSON.stringify(legacy)})`,\n\t\t\t)\n\t\t\t// Authority over time (RT-81): every explicit id ever held stays authoritative\n\t\t\t// until revoked, and reserved for good.\n\t\t\tconst history = resolveAuthorityHistory({\n\t\t\t\tlegacy,\n\t\t\t\tconfigured,\n\t\t\t\tpersistedEver: parseLegacyAuthorities(meta(tx, SERVER_EVER_AUTHORITY_KEY)),\n\t\t\t\tpersistedRevoked: parseLegacyAuthorities(meta(tx, SERVER_REVOKED_AUTHORITY_KEY)),\n\t\t\t\townNodeId: nodeId,\n\t\t\t})\n\t\t\ttx.run(\n\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SERVER_EVER_AUTHORITY_KEY}, ${JSON.stringify(history.everAuthoritative)})`,\n\t\t\t)\n\t\t\ttx.run(\n\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SERVER_REVOKED_AUTHORITY_KEY}, ${JSON.stringify(history.revoked)})`,\n\t\t\t)\n\t\t\treturn { nodeId, secret, history }\n\t\t})\n\t}\n\n\t/** What the last startup re-materialization did (W7 step 7). */\n\tgetFoldMigrationReport(): FoldMigrationReport {\n\t\treturn { ...this.foldMigration }\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.select().from(syncState).all()\n\t\tconst vv: VersionVector = new Map()\n\t\tfor (const row of rows) {\n\t\t\tvv.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t\treturn vv\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition, options: ServerSchemaOptions = {}): Promise<void> {\n\t\tthis.assertOpen()\n\t\t// Refuse transforms that cannot read the stored log BEFORE anything changes (RT-103).\n\t\tthis.assertTransformCoverage(\n\t\t\tschema.version,\n\t\t\toptions.operationTransforms ?? this.operationTransforms,\n\t\t)\n\t\tthis.schema = schema\n\t\tif (options.operationTransforms !== undefined) {\n\t\t\tthis.operationTransforms = [...options.operationTransforms]\n\t\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t\t}\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'sqlite')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tthis.db.run(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"duplicate column\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps SQLite errors, so check both outer message and cause.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.db.run(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// beta.12 tables carry enum CHECKs a schema upgrade cannot change: rebuild them\n\t\t// once without (RT-101); the value domain is enforced at ingest only.\n\t\tawait this.relaxValueDomainConstraints(schema)\n\t\tthis.migrateTextCodec(schema)\n\n\t\t// beta.12 clears stored by an earlier server, made explicit once (RT-85); their\n\t\t// records are re-folded by the re-materialization below.\n\t\tawait this.canonicalizeLegacyBodies()\n\t\t// Re-materialize every record whose fold state is missing or stale (W7 step 7).\n\t\tthis.foldMigration = this.rematerialize()\n\t\t// A change in the fields snapshots capture invalidates every snapshot: drop them\n\t\t// and rebuild from the log (RT-20). The fingerprint is written last, so a crash\n\t\t// mid-way only repeats the rebuild at the next start.\n\t\tconst fingerprint = scopeSnapshotFingerprint(schema)\n\t\tconst stored = this.db.all<{ value: string }>(\n\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${SCOPE_SNAPSHOT_FINGERPRINT_KEY}`,\n\t\t)[0]?.value\n\t\tif (stored !== fingerprint) {\n\t\t\tthis.db.run(sql`UPDATE operations SET scope_snapshot = NULL`)\n\t\t}\n\t\tthis.backfillScopeSnapshots()\n\t\tif (stored !== fingerprint) {\n\t\t\tthis.db.run(\n\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SCOPE_SNAPSHOT_FINGERPRINT_KEY}, ${fingerprint})`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * One-time migration (RT-101): rebuild collection tables that still carry an enum\n\t * `CHECK` (or `NOT NULL` on a schema field), in one transaction, keeping rows, indexes\n\t * and triggers. Idempotent (a relaxed table is left alone) and resumable (an\n\t * interrupted rebuild rolls back and runs again at the next start).\n\t */\n\tprivate async relaxValueDomainConstraints(schema: SchemaDefinition): Promise<void> {\n\t\tconst query: SqliteQueryFn = async (text) => this.db.all<Record<string, unknown>>(sql.raw(text))\n\t\t// Only enum checks on the schema's enum fields are Kora's; a CHECK added by hand\n\t\t// is kept through the rebuild and never triggers one (RT-111).\n\t\tconst enumColumnsByTable: Record<string, string[]> = {}\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tenumColumnsByTable[name] = Object.entries(collection.fields)\n\t\t\t\t.filter(([, descriptor]) => descriptor.kind === 'enum')\n\t\t\t\t.map(([field]) => field)\n\t\t}\n\t\tconst statements = await planSqliteConstraintRelaxation(\n\t\t\tquery,\n\t\t\tObject.keys(schema.collections),\n\t\t\tenumColumnsByTable,\n\t\t)\n\t\tif (statements.length === 0) return\n\t\tthis.db.transaction((tx) => {\n\t\t\tfor (const statement of statements) tx.run(sql.raw(statement))\n\t\t})\n\t}\n\n\t/**\n\t * Throws {@link OperationTransformCoverageError} when a schema version in the stored\n\t * log has no transform path to `version` (RT-103): those operations would fold as\n\t * absent, silently erasing them from their records.\n\t */\n\tprivate assertTransformCoverage(\n\t\tversion: number,\n\t\ttransforms: readonly OperationTransform[],\n\t): void {\n\t\tif (transforms.length === 0) return\n\t\tconst rows = this.db.all<{ v: number }>(\n\t\t\tsql`SELECT DISTINCT schema_version AS v FROM operations`,\n\t\t)\n\t\tassertOperationTransformCoverage(\n\t\t\trows.map((row) => Number(row.v)),\n\t\t\tversion,\n\t\t\ttransforms,\n\t\t\t'SQLite server store',\n\t\t)\n\t}\n\n\tgetOperationTransforms(): readonly OperationTransform[] {\n\t\treturn this.operationTransforms\n\t}\n\n\tasync setOperationTransforms(transforms: readonly OperationTransform[]): Promise<void> {\n\t\tthis.assertOpen()\n\t\tif (this.schema) this.assertTransformCoverage(this.schema.version, transforms)\n\t\tthis.operationTransforms = [...transforms]\n\t\tthis.foldOptions = serverFoldOptions(this.explicitAuthorities, this.operationTransforms)\n\t\t// The fold plan fingerprint includes the transforms: when they changed, every\n\t\t// record is re-folded from its log, once (RT-84).\n\t\tif (this.schema) this.foldMigration = this.rematerialize()\n\t}\n\n\tasync applyRemoteOperation(op: Operation, options?: ApplyRemoteOptions): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\tconst now = Date.now()\n\n\t\tlet sequenceDecision: SequenceHolderVerdict = { verdict: 'free' }\n\t\t// Use a transaction for atomicity: insert op + update version vector + materialize\n\t\tlet result: 'applied' | 'duplicate'\n\t\ttry {\n\t\t\tresult = this.applyInTransaction(op, now, options, (decision) => {\n\t\t\t\tsequenceDecision = decision\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tthrow sqliteUnstorableValueOr(error, op)\n\t\t}\n\n\t\tif (result === 'applied') {\n\t\t\treportLegacyPair(op, sequenceDecision, options)\n\t\t}\n\t\treturn result\n\t}\n\n\tprivate applyInTransaction(\n\t\top: Operation,\n\t\tnow: number,\n\t\toptions: ApplyRemoteOptions | undefined,\n\t\tonSequenceDecision: (decision: SequenceHolderVerdict) => void,\n\t): 'applied' | 'duplicate' {\n\t\treturn this.db.transaction((tx) => {\n\t\t\t// Content-addressed dedup: check before assigning a delivery sequence so a\n\t\t\t// duplicate never burns one (keeps the sequence gap-free on this store).\n\t\t\tconst existing = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE id = ${op.id} LIMIT 1`,\n\t\t\t)\n\t\t\tif (existing.length > 0) {\n\t\t\t\treturn 'duplicate' as const\n\t\t\t}\n\t\t\t// A different operation under the same (node, sequence) is refused (W3 step 4)\n\t\t\t// when it was stored under enforcement and the writer reserves its sequences;\n\t\t\t// a legacy holder (stored before the epoch) or a legacy writer (RT-37) is\n\t\t\t// accepted, as beta.12 did. Inside the write transaction so no concurrent\n\t\t\t// writer can slip one in.\n\t\t\tconst holders = tx.all<{ id: string; delivery_seq: number | null }>(\n\t\t\t\tsql`SELECT id, delivery_seq FROM operations WHERE node_id = ${op.nodeId} AND sequence_number = ${op.sequenceNumber}`,\n\t\t\t)\n\t\t\tconst decision = judgeSequenceHolders(\n\t\t\t\top,\n\t\t\t\tholders.map((row) => ({ id: row.id, deliverySequence: Number(row.delivery_seq ?? 0) })),\n\t\t\t\tthis.sequenceEpoch,\n\t\t\t\t{ legacySequenceWriter: options?.legacySequenceWriter === true },\n\t\t\t)\n\t\t\tif (decision.verdict === 'conflict') {\n\t\t\t\tthrow new SequenceConflictError(op, decision.holderId)\n\t\t\t}\n\t\t\tonSequenceDecision(decision)\n\n\t\t\t// Authorization re-check inside the write transaction: better-sqlite3 runs\n\t\t\t// it synchronously under SQLite's single writer lock, so the row it sees is\n\t\t\t// the row this write commits against. Throwing rolls the transaction back.\n\t\t\tif (options?.authorize) {\n\t\t\t\tconst decision = options.authorize(this.readStoredRow(tx, op.collection, op.recordId))\n\t\t\t\tif (!decision.allowed) {\n\t\t\t\t\tthrow new UplinkAuthorizationError(decision.code, decision.message, {\n\t\t\t\t\t\toperationId: op.id,\n\t\t\t\t\t\tcollection: op.collection,\n\t\t\t\t\t\trecordId: op.recordId,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst materialized = this.schema?.collections[op.collection] !== undefined\n\t\t\tconst pre = materialized ? this.readScopeValues(tx, op.collection, op.recordId, false) : null\n\n\t\t\tconst deliverySeq = this.nextDeliverySeq(tx)\n\t\t\tconst row = this.serializeOperation(op, now, deliverySeq, decision.verdict === 'free')\n\t\t\ttx.insert(operations).values(row).run()\n\t\t\t// A legacy pair: index its sequence so version-vector clients get both (RT-48).\n\t\t\tif (decision.verdict === 'legacy') {\n\t\t\t\ttx.run(\n\t\t\t\t\tsql`INSERT OR IGNORE INTO sequence_pairs (node_id, sequence_number) VALUES (${op.nodeId}, ${op.sequenceNumber})`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Advance version vector: upsert with MAX to ensure monotonic progress\n\t\t\ttx.insert(syncState)\n\t\t\t\t.values({\n\t\t\t\t\tnodeId: op.nodeId,\n\t\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\t\tlastSeenAt: now,\n\t\t\t\t})\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: syncState.nodeId,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tmaxSequenceNumber: sql`MAX(${syncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\n\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\tif (materialized) {\n\t\t\t\tthis.mergeIntoRecord(tx, op, deliverySeq)\n\t\t\t\t// The record's scope values around this write, from the store's own rows.\n\t\t\t\tconst snapshot: OperationScopeSnapshot = {\n\t\t\t\t\tpre,\n\t\t\t\t\tpost: this.readScopeValues(tx, op.collection, op.recordId, true),\n\t\t\t\t}\n\t\t\t\ttx.run(\n\t\t\t\t\tsql`UPDATE operations SET scope_snapshot = ${JSON.stringify(snapshot)} WHERE id = ${op.id}`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn 'applied' as const\n\t\t})\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(and(eq(operations.nodeId, nodeId), between(operations.sequenceNumber, fromSeq, toSeq)))\n\t\t\t.orderBy(asc(operations.sequenceNumber))\n\t\t\t.all()\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\n\t\tconst result = this.db.select({ value: count() }).from(operations).all()\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ m: number | null }>(\n\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t)\n\t\treturn rows[0]?.m ?? 0\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(gt(operations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(operations.deliverySeq))\n\t\t\t.limit(limit)\n\t\t\t.all()\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t\tscopeSnapshot: parseScopeSnapshot(row.scopeSnapshot),\n\t\t}))\n\t}\n\n\tasync getOperationScopeSnapshots(\n\t\toperationIds: string[],\n\t): Promise<Map<string, OperationScopeSnapshot>> {\n\t\tthis.assertOpen()\n\t\tconst result = new Map<string, OperationScopeSnapshot>()\n\t\tfor (let i = 0; i < operationIds.length; i += 500) {\n\t\t\tconst ids = operationIds.slice(i, i + 500)\n\t\t\tif (ids.length === 0) continue\n\t\t\tconst rows = this.db.all<{ id: string; scope_snapshot: string | null }>(\n\t\t\t\tsql`SELECT id, scope_snapshot FROM operations WHERE id IN (${sql.join(\n\t\t\t\t\tids.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst snapshot = parseScopeSnapshot(row.scope_snapshot)\n\t\t\t\tif (snapshot) result.set(row.id, snapshot)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync getRecordLatestTimestamp(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<HLCTimestamp | null> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ wall_time: number; logical: number; timestamp_node_id: string }>(\n\t\t\tsql`SELECT wall_time, logical, timestamp_node_id FROM operations\n\t\t\t\tWHERE collection = ${collection} AND record_id = ${recordId}\n\t\t\t\tORDER BY wall_time DESC, logical DESC, timestamp_node_id DESC LIMIT 1`,\n\t\t)\n\t\tconst row = rows[0]\n\t\treturn row\n\t\t\t? {\n\t\t\t\t\twallTime: Number(row.wall_time),\n\t\t\t\t\tlogical: Number(row.logical),\n\t\t\t\t\tnodeId: row.timestamp_node_id,\n\t\t\t\t}\n\t\t\t: null\n\t}\n\n\tasync getRecordFieldVersions(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<RecordFieldVersions | null> {\n\t\tthis.assertOpen()\n\t\treturn foldFieldVersions(this.readFoldState(this.db, collection, recordId))\n\t}\n\n\tasync getRecordFoldState(collection: string, recordId: string): Promise<FoldState | null> {\n\t\tthis.assertOpen()\n\t\treturn this.readFoldState(this.db, collection, recordId)\n\t}\n\n\tasync getRecordOperations(collection: string, recordId: string): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\treturn this.readRecordOperations(this.db, collection, recordId, 0)\n\t}\n\n\tasync previewOperation(op: Operation): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tconst schema = this.schema ?? EMPTY_FOLD_SCHEMA\n\t\tconst current = this.readFoldState(this.db, op.collection, op.recordId)\n\t\tconst merged = mergeIntoFoldState(current, [op], schema, this.foldOptions)\n\t\tconst state =\n\t\t\tmerged === REFOLD_REQUIRED\n\t\t\t\t? refoldRecord(\n\t\t\t\t\t\t[...this.readRecordOperations(this.db, op.collection, op.recordId, 0), op],\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\tthis.foldOptions,\n\t\t\t\t\t)\n\t\t\t\t: merged\n\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\tif (!row || row.deleted) return null\n\t\treturn { ...row.values, id: op.recordId }\n\t}\n\n\tasync recordBlobOwner(hash: string, owner: string): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.db.run(\n\t\t\tsql`INSERT OR IGNORE INTO blob_owners (hash, owner, created_at) VALUES (${hash}, ${owner}, ${Date.now()})`,\n\t\t)\n\t}\n\n\tasync getBlobOwners(hashes: string[]): Promise<Map<string, string[]>> {\n\t\tthis.assertOpen()\n\t\tconst result = new Map<string, string[]>(hashes.map((hash) => [hash, []]))\n\t\tfor (let i = 0; i < hashes.length; i += 500) {\n\t\t\tconst slice = hashes.slice(i, i + 500)\n\t\t\tif (slice.length === 0) continue\n\t\t\tconst rows = this.db.all<{ hash: string; owner: string }>(\n\t\t\t\tsql`SELECT hash, owner FROM blob_owners WHERE hash IN (${sql.join(\n\t\t\t\t\tslice.map((hash) => sql`${hash}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)\n\t\t\tfor (const row of rows) result.get(row.hash)?.push(row.owner)\n\t\t}\n\t\treturn result\n\t}\n\n\tasync claimBlobIfUnowned(hash: string, owner: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\t// better-sqlite3 runs both statements synchronously under SQLite's writer lock,\n\t\t// so no other claim interleaves (and the file lock covers other processes).\n\t\tthis.db.run(\n\t\t\tsql`INSERT OR IGNORE INTO blob_owners (hash, owner, created_at)\n\t\t\t\tSELECT ${hash}, ${owner}, ${Date.now()}\n\t\t\t\tWHERE NOT EXISTS (SELECT 1 FROM blob_owners WHERE hash = ${hash})`,\n\t\t)\n\t\tconst rows = this.db.all<{ one: number }>(\n\t\t\tsql`SELECT 1 AS one FROM blob_owners WHERE hash = ${hash} AND owner = ${owner} LIMIT 1`,\n\t\t)\n\t\treturn rows.length > 0\n\t}\n\n\t/**\n\t * Scope values of a record as stored, for an operation's scope snapshot. With\n\t * `includeDeleted` false a soft-deleted row counts as absent (the pre-image of a\n\t * write to a deleted record); with true it keeps its last values (a delete's\n\t * post-image).\n\t */\n\tprivate readScopeValues(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tincludeDeleted: boolean,\n\t): Record<string, unknown> | null {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return null\n\t\tconst rows = txOrDb.all<Record<string, unknown>>(\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${recordId} LIMIT 1`,\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) return null\n\t\tif (!includeDeleted && Number(row._deleted) === 1) return null\n\t\treturn scopeValuesOf(this.schema, collection, recordId, this.deserializeRow(row, collectionDef))\n\t}\n\n\t/**\n\t * Rebuild missing scope snapshots from the log (migration from a database written\n\t * before snapshots existed), replaying each affected record in commit order.\n\t */\n\tprivate backfillScopeSnapshots(): void {\n\t\tconst schema = this.schema\n\t\tif (!schema) return\n\t\tconst pending = this.db.all<{ collection: string; record_id: string }>(\n\t\t\tsql`SELECT DISTINCT collection, record_id FROM operations WHERE scope_snapshot IS NULL`,\n\t\t)\n\t\tconst targets = pending.filter((row) => schema.collections[row.collection] !== undefined)\n\t\tif (targets.length === 0) return\n\t\tthis.db.transaction((tx) => {\n\t\t\tfor (const target of targets) {\n\t\t\t\tconst rows = tx\n\t\t\t\t\t.select()\n\t\t\t\t\t.from(operations)\n\t\t\t\t\t.where(\n\t\t\t\t\t\tand(\n\t\t\t\t\t\t\teq(operations.collection, target.collection),\n\t\t\t\t\t\t\teq(operations.recordId, target.record_id),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\t.orderBy(asc(operations.deliverySeq))\n\t\t\t\t\t.all()\n\t\t\t\tconst replayed = replayScopeSnapshots(\n\t\t\t\t\tschema,\n\t\t\t\t\ttarget.collection,\n\t\t\t\t\ttarget.record_id,\n\t\t\t\t\trows.map((row) => this.deserializeOperation(row)),\n\t\t\t\t\tthis.foldOptions,\n\t\t\t\t)\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tif (row.scopeSnapshot !== null) continue\n\t\t\t\t\tconst snapshot = replayed.get(row.id)\n\t\t\t\t\tif (!snapshot) continue\n\t\t\t\t\ttx.run(\n\t\t\t\t\t\tsql`UPDATE operations SET scope_snapshot = ${JSON.stringify(snapshot)} WHERE id = ${row.id}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync getNodeIdsAfterDelivery(afterDeliverySequence: number): Promise<string[]> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ node_id: string }>(\n\t\t\tsql`SELECT DISTINCT node_id FROM operations WHERE delivery_seq > ${afterDeliverySequence}`,\n\t\t)\n\t\treturn rows.map((row) => row.node_id)\n\t}\n\n\tasync getSequencePairOperations(nodeId: string, throughSequence: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(\n\t\t\t\tand(\n\t\t\t\t\teq(operations.nodeId, nodeId),\n\t\t\t\t\tsql`${operations.sequenceNumber} IN (SELECT sequence_number FROM sequence_pairs WHERE node_id = ${nodeId} AND sequence_number <= ${throughSequence})`,\n\t\t\t\t),\n\t\t\t)\n\t\t\t.orderBy(asc(operations.sequenceNumber), asc(operations.deliverySeq))\n\t\t\t.all()\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync recordOperationResolution(resolution: OperationResolution): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.db.run(\n\t\t\tsql`INSERT OR IGNORE INTO operation_resolutions\n\t\t\t\t(op_id, node_id, sequence_number, outcome, code, message, resolved_at)\n\t\t\t\tVALUES (${resolution.operationId}, ${resolution.nodeId}, ${resolution.sequenceNumber},\n\t\t\t\t\t${resolution.outcome}, ${resolution.code},\n\t\t\t\t\t${resolution.message?.slice(0, MAX_RESOLUTION_MESSAGE_LENGTH) ?? null}, ${Date.now()})`,\n\t\t)\n\t}\n\n\tasync findOperationResolutions(\n\t\tnodeId: string,\n\t\tids: string[],\n\t): Promise<Map<string, OperationResolution>> {\n\t\tthis.assertOpen()\n\t\tconst found = new Map<string, OperationResolution>()\n\t\tfor (let i = 0; i < ids.length; i += 500) {\n\t\t\tconst chunk = ids.slice(i, i + 500)\n\t\t\tif (chunk.length === 0) continue\n\t\t\tconst rows = this.db.all<ResolutionRow>(\n\t\t\t\tsql`SELECT op_id, node_id, sequence_number, outcome, code, message FROM operation_resolutions\n\t\t\t\t\tWHERE node_id = ${nodeId} AND op_id IN (${sql.join(\n\t\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\t\tsql.raw(', '),\n\t\t\t\t\t)})`,\n\t\t\t)\n\t\t\tfor (const row of rows) found.set(row.op_id, resolutionFromRow(row))\n\t\t}\n\t\treturn found\n\t}\n\n\tasync deleteOperationResolution(nodeId: string, operationId: string): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.db.run(\n\t\t\tsql`DELETE FROM operation_resolutions WHERE node_id = ${nodeId} AND op_id = ${operationId}`,\n\t\t)\n\t}\n\n\tasync getResolvedThrough(nodeId: string): Promise<number> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ m: number | string | null }>(\n\t\t\tsql`SELECT MAX(sequence_number) AS m FROM operation_resolutions WHERE node_id = ${nodeId}`,\n\t\t)\n\t\treturn Number(rows[0]?.m ?? 0)\n\t}\n\n\tasync findStoredOperations(ids: string[]): Promise<Map<string, StoredOperationKey>> {\n\t\tthis.assertOpen()\n\t\tconst found = new Map<string, StoredOperationKey>()\n\t\t// Chunked to stay far below SQLite's bound-parameter limit.\n\t\tfor (let i = 0; i < ids.length; i += 500) {\n\t\t\tconst chunk = ids.slice(i, i + 500)\n\t\t\tif (chunk.length === 0) continue\n\t\t\tconst rows = this.db.all<{ id: string; node_id: string; sequence_number: number | string }>(\n\t\t\t\tsql`SELECT id, node_id, sequence_number FROM operations WHERE id IN (${sql.join(\n\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)\n\t\t\tfor (const row of rows) {\n\t\t\t\tfound.set(row.id, { nodeId: row.node_id, sequenceNumber: Number(row.sequence_number) })\n\t\t\t}\n\t\t}\n\t\treturn found\n\t}\n\n\tasync findRecordsByIds(\n\t\tcollection: string,\n\t\tids: string[],\n\t): Promise<Map<string, MaterializedRecord>> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst result = new Map<string, MaterializedRecord>()\n\t\t// Chunked to stay far below SQLite's bound-parameter limit.\n\t\tfor (let i = 0; i < ids.length; i += 500) {\n\t\t\tconst chunk = ids.slice(i, i + 500)\n\t\t\tif (chunk.length === 0) continue\n\t\t\tconst rows = this.db.all<Record<string, unknown>>(\n\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id IN (${sql.join(\n\t\t\t\t\tchunk.map((id) => sql`${id}`),\n\t\t\t\t\tsql.raw(', '),\n\t\t\t\t)})`,\n\t\t\t)\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst record = this.deserializeRow(row, collectionDef)\n\t\t\t\tresult.set(record.id, record)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false, schema.collections[collection])\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = this.db.all<{ cnt: number }>(query)\n\t\treturn rows[0]?.cnt ?? 0\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync getEncryptionKeyRecord(owner: string, keyring: string): Promise<string | null> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ record: string }>(\n\t\t\tsql`SELECT record FROM kora_encryption_keys WHERE owner = ${owner} AND keyring = ${keyring} LIMIT 1`,\n\t\t)\n\t\treturn rows[0]?.record ?? null\n\t}\n\n\tasync putEncryptionKeyRecord(\n\t\towner: string,\n\t\tkeyring: string,\n\t\trecord: string,\n\t\trevision: number,\n\t\texpectedRevision: number,\n\t): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tconst now = Date.now()\n\t\t// Compare-and-set on the revision; better-sqlite3 runs it synchronously, and the\n\t\t// primary key makes a concurrent first write from another process fail.\n\t\tif (expectedRevision === 0) {\n\t\t\tconst rows = this.db.all<{ owner: string }>(\n\t\t\t\tsql`INSERT OR IGNORE INTO kora_encryption_keys (owner, keyring, revision, record, updated_at)\n\t\t\t\t\tVALUES (${owner}, ${keyring}, ${revision}, ${record}, ${now}) RETURNING owner`,\n\t\t\t)\n\t\t\treturn rows.length > 0\n\t\t}\n\t\tconst rows = this.db.all<{ owner: string }>(\n\t\t\tsql`UPDATE kora_encryption_keys SET revision = ${revision}, record = ${record}, updated_at = ${now}\n\t\t\t\tWHERE owner = ${owner} AND keyring = ${keyring} AND revision = ${expectedRevision}\n\t\t\t\tRETURNING owner`,\n\t\t)\n\t\treturn rows.length > 0\n\t}\n\n\tasync listEncryptionKeyRecords(owner?: string): Promise<EncryptionKeyRecordRow[]> {\n\t\tthis.assertOpen()\n\t\treturn owner === undefined\n\t\t\t? this.db.all<EncryptionKeyRecordRow>(\n\t\t\t\t\tsql`SELECT owner, keyring, revision, record FROM kora_encryption_keys ORDER BY owner, keyring`,\n\t\t\t\t)\n\t\t\t: this.db.all<EncryptionKeyRecordRow>(\n\t\t\t\t\tsql`SELECT owner, keyring, revision, record FROM kora_encryption_keys WHERE owner = ${owner} ORDER BY keyring`,\n\t\t\t\t)\n\t}\n\n\tasync getEncryptedKeyIds(nodeOwner: string | null, limit: number): Promise<string[]> {\n\t\tthis.assertOpen()\n\t\tconst rows =\n\t\t\tnodeOwner === null\n\t\t\t\t? this.db.all<{ encrypted: string | null }>(\n\t\t\t\t\t\tsql`SELECT encrypted FROM operations WHERE encrypted IS NOT NULL LIMIT ${KEY_ID_SAMPLE_ROWS}`,\n\t\t\t\t\t)\n\t\t\t\t: this.db.all<{ encrypted: string | null }>(\n\t\t\t\t\t\tsql`SELECT o.encrypted AS encrypted FROM node_claims c\n\t\t\t\t\t\t\tJOIN operations o ON o.node_id = c.node_id\n\t\t\t\t\t\t\tWHERE c.user_id = ${nodeOwner} AND o.encrypted IS NOT NULL\n\t\t\t\t\t\t\tLIMIT ${KEY_ID_SAMPLE_ROWS}`,\n\t\t\t\t\t)\n\t\treturn envelopeKeyIds(\n\t\t\trows.map((row) => row.encrypted),\n\t\t\tlimit,\n\t\t)\n\t}\n\n\tasync claimNode(nodeId: string, userId: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tif (userId === RELEASED_NODE_OWNER) return false\n\t\tconst now = Date.now()\n\t\t// better-sqlite3 runs these synchronously, so no other claim interleaves.\n\t\t// A fresh claim is only created for a node without history: history with no\n\t\t// claim predates node claims, so its writer is unknown (RT-5).\n\t\tthis.db.run(\n\t\t\tsql`INSERT OR IGNORE INTO node_claims (node_id, user_id, claimed_at)\n\t\t\t\tSELECT ${nodeId}, ${userId}, ${now}\n\t\t\t\tWHERE NOT EXISTS (SELECT 1 FROM operations WHERE node_id = ${nodeId})`,\n\t\t)\n\t\t// An admin-released node is taken over by its next claimant.\n\t\tthis.db.run(\n\t\t\tsql`UPDATE node_claims SET user_id = ${userId}, claimed_at = ${now}\n\t\t\t\tWHERE node_id = ${nodeId} AND user_id = ${RELEASED_NODE_OWNER}`,\n\t\t)\n\t\tconst rows = this.db.all<{ user_id: string }>(\n\t\t\tsql`SELECT user_id FROM node_claims WHERE node_id = ${nodeId} LIMIT 1`,\n\t\t)\n\t\treturn rows[0]?.user_id === userId\n\t}\n\n\tasync getNodeClaimOwner(nodeId: string): Promise<string | null> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ user_id: string }>(\n\t\t\tsql`SELECT user_id FROM node_claims WHERE node_id = ${nodeId} LIMIT 1`,\n\t\t)\n\t\treturn rows[0]?.user_id ?? null\n\t}\n\n\tasync replaceNodeClaim(\n\t\tnodeId: string,\n\t\texpectedOwner: string,\n\t\tnewOwner: string,\n\t): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ node_id: string }>(\n\t\t\tsql`UPDATE node_claims SET user_id = ${newOwner}, claimed_at = ${Date.now()}\n\t\t\t\tWHERE node_id = ${nodeId} AND user_id = ${expectedOwner} RETURNING node_id`,\n\t\t)\n\t\treturn rows.length > 0\n\t}\n\n\tasync releaseNodeClaim(nodeId: string): Promise<boolean> {\n\t\tthis.assertOpen()\n\t\tconst known = this.db.all<{ one: number }>(\n\t\t\tsql`SELECT 1 AS one WHERE EXISTS (SELECT 1 FROM node_claims WHERE node_id = ${nodeId})\n\t\t\t\tOR EXISTS (SELECT 1 FROM operations WHERE node_id = ${nodeId})`,\n\t\t)\n\t\tif (known.length === 0) return false\n\t\tthis.db.run(\n\t\t\tsql`INSERT INTO node_claims (node_id, user_id, claimed_at)\n\t\t\t\tVALUES (${nodeId}, ${RELEASED_NODE_OWNER}, ${Date.now()})\n\t\t\t\tON CONFLICT (node_id) DO UPDATE SET user_id = excluded.user_id, claimed_at = excluded.claimed_at`,\n\t\t)\n\t\treturn true\n\t}\n\n\t/**\n\t * The record as currently stored, including a soft-deleted one (whose last field\n\t * values are kept), or null when it was never written. Without a materialized\n\t * table, the last known values are replayed from the operation log.\n\t */\n\tprivate readStoredRow(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): MaterializedRecord | null {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (collectionDef) {\n\t\t\tconst rows = txOrDb.all<Record<string, unknown>>(\n\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${recordId} LIMIT 1`,\n\t\t\t)\n\t\t\tconst row = rows[0]\n\t\t\treturn row ? this.deserializeRow(row, collectionDef) : null\n\t\t}\n\t\tconst ops = this.readRecordOperations(txOrDb, collection, recordId, 0)\n\t\tif (ops.length === 0) return null\n\t\tconst state = refoldRecord(ops, this.schema ?? EMPTY_FOLD_SCHEMA, this.foldOptions)\n\t\tconst lastKnown = state ? projectFoldState(state, this.foldOptions) : null\n\t\treturn { ...(lastKnown?.values ?? {}), id: recordId }\n\t}\n\n\t/**\n\t * The fold state of a record that owns quarantined operations (RT-70): its stored\n\t * state, or its kept row as a snapshot base, with every remaining operation of the\n\t * record merged on top (`rebuildFromSnapshot`). Nothing is written.\n\t */\n\tprivate rebuildAffected(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tstored: FoldState | null,\n\t): FoldState | null {\n\t\tconst schema = this.schema ?? EMPTY_FOLD_SCHEMA\n\t\tconst collectionDef = schema.collections[collection]\n\t\tconst raw = collectionDef\n\t\t\t? txOrDb.all<Record<string, unknown>>(\n\t\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${recordId} LIMIT 1`,\n\t\t\t\t)[0]\n\t\t\t: undefined\n\t\tlet row: KeptRow | null = null\n\t\tif (raw && collectionDef) {\n\t\t\tconst record = this.deserializeRow(raw, collectionDef)\n\t\t\tconst values: Record<string, unknown> = {}\n\t\t\tfor (const field of Object.keys(collectionDef.fields)) {\n\t\t\t\tif (record[field] !== undefined) values[field] = record[field]\n\t\t\t}\n\t\t\trow = {\n\t\t\t\tvalues,\n\t\t\t\tcreatedAt: Number(raw._created_at ?? 0),\n\t\t\t\tupdatedAt: Number(raw._updated_at ?? 0),\n\t\t\t\tdeleted: Number(raw._deleted) === 1,\n\t\t\t}\n\t\t}\n\t\treturn rebuildFromSnapshot(\n\t\t\t{\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\tstored,\n\t\t\t\trow,\n\t\t\t\tops: this.readRecordOperations(txOrDb, collection, recordId, 0),\n\t\t\t\tquarantinedLatest: this.quarantine.latest.get(quarantineKey(collection, recordId)),\n\t\t\t},\n\t\t\tschema,\n\t\t\tthis.foldOptions,\n\t\t)\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\t// Export in delivery-sequence (commit) order so a restore reassigns delivery\n\t\t// sequences causally; an implicit scan order must not be relied on.\n\t\tconst rows = this.db.select().from(operations).orderBy(asc(operations.deliverySeq)).all()\n\t\tconst deserialized = rows.map((row) => this.deserializeOperation(row))\n\t\tconst vv = this.getVersionVector()\n\n\t\treturn buildServerBackup(this.nodeId, deserialized, vv, await this.listEncryptionKeyRecords())\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\n\t\tconst { mergeBackupOperations, parseServerBackup, restoreBackupKeyRecords } = await import(\n\t\t\t'./server-backup'\n\t\t)\n\t\tconst { operations: ops, versionVector, keyRecords } = parseServerBackup(data)\n\t\t// Both modes reconcile the key table (not part of the log), record by record (RT-110).\n\t\tawait restoreBackupKeyRecords(this, keyRecords, merge === true)\n\n\t\tif (merge) {\n\t\t\tconst merged = await mergeBackupOperations(ops, (op) => this.applyRemoteOperation(op))\n\t\t\treturn merged\n\t\t}\n\n\t\t// Replace mode: DROP and recreate\n\t\tthis.db.transaction((tx) => {\n\t\t\t// Restored rows are inserted unflagged (`seq_unique = 0`): they may hold legacy\n\t\t\t// duplicate sequences, and they sit at or below the new epoch, so they stay\n\t\t\t// outside the partial unique index and are judged by the append check.\n\t\t\ttx.run(sql.raw('DELETE FROM operations'))\n\t\t\ttx.run(sql.raw('DELETE FROM sync_state'))\n\t\t\ttx.update(deliveryCounter).set({ value: 0 }).where(eq(deliveryCounter.id, 1)).run()\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\ttx.insert(syncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: Date.now() })\n\t\t\t\t\t.run()\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of ops) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, Date.now(), deliverySeq)\n\t\t\t\ttx.insert(operations).values(row).run()\n\t\t\t}\n\t\t\ttx.update(deliveryCounter).set({ value: deliverySeq }).where(eq(deliveryCounter.id, 1)).run()\n\t\t\t// The restored log's legacy pairs (RT-48), and only the resolutions it covers:\n\t\t\t// one past a node's restored log was decided after the backup, and advertising\n\t\t\t// it would hide stored operations the restore lost (RT-45).\n\t\t\ttx.run(sql.raw('DELETE FROM sequence_pairs'))\n\t\t\ttx.run(sql.raw(BACKFILL_SEQUENCE_PAIRS_SQL))\n\t\t\ttx.run(sql.raw(PRUNE_RESOLUTIONS_PAST_LOG_SQL))\n\t\t\t// The restored log is a snapshot that may hold legacy duplicate sequences: it\n\t\t\t// all sits at or below the new epoch, and enforcement resumes above it.\n\t\t\ttx.run(\n\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SEQUENCE_ENFORCEMENT_EPOCH_KEY}, ${String(deliverySeq)})`,\n\t\t\t)\n\t\t})\n\t\tthis.sequenceEpoch = this.ensureSequenceEnforcement()\n\t\t// Every restored record is re-materialized through the fold from the restored log.\n\t\tthis.db.transaction((tx) => {\n\t\t\ttx.run(sql.raw('DELETE FROM kora_fold_state'))\n\t\t\tfor (const collection of Object.keys(this.schema?.collections ?? {})) {\n\t\t\t\ttx.run(sql.raw(`DELETE FROM ${quoteIdent(collection)}`))\n\t\t\t}\n\t\t})\n\t\tif (this.schema) this.foldMigration = this.rematerialize()\n\t\tthis.backfillScopeSnapshots()\n\n\t\treturn { operationsRestored: ops.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Merge a just-appended operation (stored under `deliverySeq`) into its record's\n\t * fold state and project the row, inside the append transaction. O(fields the\n\t * operation touches): the stored state is read by primary key and the freshness\n\t * check is one index probe, never a scan of the record's history (SRV-7).\n\t *\n\t * The stored state records the highest delivery sequence it covers. If another\n\t * writer appended operations to this record without folding them (an older release\n\t * during a rolling upgrade), the missing tail is merged first; if the stored state\n\t * is unreadable, newer than the log, or built under an incompatible field kind,\n\t * the record is re-folded from its log.\n\t */\n\tprivate mergeIntoRecord(tx: BetterSQLite3Database, op: Operation, deliverySeq: number): void {\n\t\tconst schema = this.schema\n\t\tif (!schema?.collections[op.collection]) return\n\t\tconst stored = tx.all<{ state: string; covered_seq: number; covered_op_id: string }>(\n\t\t\tsql`SELECT state, covered_seq, covered_op_id FROM kora_fold_state WHERE collection = ${op.collection} AND record_id = ${op.recordId}`,\n\t\t)[0]\n\t\t// The record's newest operation before this one: the stored state is current iff\n\t\t// it covers exactly that operation (sequence AND id, so a state left behind by a\n\t\t// dropped or restored log is never mistaken for current).\n\t\tconst last = tx.all<{ id: string; d: number }>(\n\t\t\tsql`SELECT id, delivery_seq AS d FROM operations WHERE collection = ${op.collection} AND record_id = ${op.recordId} AND delivery_seq < ${deliverySeq} ORDER BY delivery_seq DESC LIMIT 1`,\n\t\t)[0]\n\t\tconst prior = Number(last?.d ?? 0)\n\t\tconst parsed = stored ? parseStoredFoldState(stored.state, op.collection, op.recordId) : null\n\t\tconst covered = stored ? Number(stored.covered_seq) : 0\n\t\tlet state: FoldState | null | typeof REFOLD_REQUIRED\n\t\tif (parsed && covered === prior && stored?.covered_op_id === (last?.id ?? '')) {\n\t\t\tstate = mergeIntoFoldState(parsed, [op], schema, this.foldOptions)\n\t\t} else if (isQuarantineAffected(this.quarantine, op.collection, op.recordId)) {\n\t\t\t// Incomplete log (RT-70): fold onto the kept row, never from the log alone.\n\t\t\tstate = this.rebuildAffected(tx, op.collection, op.recordId, parsed)\n\t\t} else if (!stored && !last) {\n\t\t\tstate = mergeIntoFoldState(null, [op], schema, this.foldOptions)\n\t\t} else if (\n\t\t\tparsed &&\n\t\t\tcovered > 0 &&\n\t\t\tcovered < prior &&\n\t\t\tthis.coversStoredOperation(tx, op.collection, op.recordId, covered, stored?.covered_op_id)\n\t\t) {\n\t\t\t// Operations appended without folding (an older release during a rolling\n\t\t\t// upgrade): merge the missing tail.\n\t\t\tstate = mergeIntoFoldState(\n\t\t\t\tparsed,\n\t\t\t\tthis.readRecordOperations(tx, op.collection, op.recordId, covered),\n\t\t\t\tschema,\n\t\t\t\tthis.foldOptions,\n\t\t\t)\n\t\t} else {\n\t\t\tstate = REFOLD_REQUIRED\n\t\t}\n\t\tif (state === REFOLD_REQUIRED) {\n\t\t\tstate = refoldRecord(\n\t\t\t\tthis.readRecordOperations(tx, op.collection, op.recordId, 0),\n\t\t\t\tschema,\n\t\t\t\tthis.foldOptions,\n\t\t\t)\n\t\t}\n\t\tthis.writeFoldedRecord(tx, op.collection, op.recordId, state, deliverySeq, op.id)\n\t}\n\n\t/** True when the record's operation at delivery sequence `seq` has id `opId`. */\n\tprivate coversStoredOperation(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tseq: number,\n\t\topId: string | undefined,\n\t): boolean {\n\t\tif (!opId) return false\n\t\treturn (\n\t\t\ttxOrDb.all<{ one: number }>(\n\t\t\t\tsql`SELECT 1 AS one FROM operations WHERE id = ${opId} AND collection = ${collection} AND record_id = ${recordId} AND delivery_seq = ${seq}`,\n\t\t\t).length > 0\n\t\t)\n\t}\n\n\t/**\n\t * The record's current fold state for a read: the stored one when it covers the\n\t * record's whole log, else folded from the log (nothing is written).\n\t */\n\tprivate readFoldState(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): FoldState | null {\n\t\tconst schema = this.schema ?? EMPTY_FOLD_SCHEMA\n\t\tif (schema.collections[collection]) {\n\t\t\tconst stored = txOrDb.all<{ state: string; covered_seq: number; covered_op_id: string }>(\n\t\t\t\tsql`SELECT state, covered_seq, covered_op_id FROM kora_fold_state WHERE collection = ${collection} AND record_id = ${recordId}`,\n\t\t\t)[0]\n\t\t\tconst last = txOrDb.all<{ id: string; d: number }>(\n\t\t\t\tsql`SELECT id, delivery_seq AS d FROM operations WHERE collection = ${collection} AND record_id = ${recordId} ORDER BY delivery_seq DESC LIMIT 1`,\n\t\t\t)[0]\n\t\t\tconst parsed = stored ? parseStoredFoldState(stored.state, collection, recordId) : null\n\t\t\tif (\n\t\t\t\tparsed &&\n\t\t\t\tNumber(stored?.covered_seq) === Number(last?.d ?? 0) &&\n\t\t\t\tstored?.covered_op_id === (last?.id ?? '')\n\t\t\t) {\n\t\t\t\treturn parsed\n\t\t\t}\n\t\t\tif (isQuarantineAffected(this.quarantine, collection, recordId)) {\n\t\t\t\treturn this.rebuildAffected(txOrDb, collection, recordId, parsed)\n\t\t\t}\n\t\t}\n\t\tconst ops = this.readRecordOperations(txOrDb, collection, recordId, 0)\n\t\treturn ops.length > 0 ? refoldRecord(ops, schema, this.foldOptions) : null\n\t}\n\n\t/** A record's operations stored after `afterDeliverySeq`, in delivery order. */\n\tprivate readRecordOperations(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tafterDeliverySeq: number,\n\t): Operation[] {\n\t\treturn txOrDb\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(\n\t\t\t\tand(\n\t\t\t\t\teq(operations.collection, collection),\n\t\t\t\t\teq(operations.recordId, recordId),\n\t\t\t\t\tgt(operations.deliverySeq, afterDeliverySeq),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.orderBy(asc(operations.deliverySeq))\n\t\t\t.all()\n\t\t\t.map((row) => this.deserializeOperation(row))\n\t}\n\n\t/**\n\t * Persist a record's fold state (covering the log up to `coveredSeq`) and project\n\t * it onto the materialized row.\n\t */\n\tprivate writeFoldedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tstate: FoldState | null,\n\t\tcoveredSeq: number,\n\t\tcoveredOpId: string,\n\t): void {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\t\tif (state) {\n\t\t\ttxOrDb.run(\n\t\t\t\tsql`INSERT INTO kora_fold_state (collection, record_id, state, covered_seq, covered_op_id)\n\t\t\t\t\tVALUES (${collection}, ${recordId}, ${serializeServerFoldState(state)}, ${coveredSeq}, ${coveredOpId})\n\t\t\t\t\tON CONFLICT (collection, record_id) DO UPDATE SET state = excluded.state, covered_seq = excluded.covered_seq, covered_op_id = excluded.covered_op_id`,\n\t\t\t)\n\t\t} else {\n\t\t\ttxOrDb.run(\n\t\t\t\tsql`DELETE FROM kora_fold_state WHERE collection = ${collection} AND record_id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\tif (!row) {\n\t\t\t// Never inserted (an update with no merged insert): no visible row. A row an\n\t\t\t// earlier (replay) materialization produced for it is hidden.\n\t\t\ttxOrDb.run(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1 WHERE id = ${recordId}`,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tthis.upsertMaterializedRecord(\n\t\t\ttxOrDb,\n\t\t\tcollection,\n\t\t\trecordId,\n\t\t\trow.values,\n\t\t\tObject.keys(collectionDef.fields),\n\t\t\tcollectionDef,\n\t\t\trow.createdAt,\n\t\t\trow.updatedAt,\n\t\t\trow.deleted,\n\t\t)\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t * Uses INSERT ... ON CONFLICT (id) DO UPDATE SET for atomic upsert.\n\t */\n\tprivate upsertMaterializedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t\tdeleted: boolean,\n\t): void {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor\n\t\t\t\t\t? serializeSqliteFieldValue(materializedFieldValue(recordData, f, descriptor), descriptor)\n\t\t\t\t\t: null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\tdeleted ? 1 : 0,\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\ttxOrDb.run(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * Re-materialization migration (W7 step 7), run by setSchema and after a\n\t * replace-mode restore. Every record whose fold state is missing, stale (it covers\n\t * less, or more, of the log than is stored) or built under a different fold plan\n\t * (field kind, merge strategy, resolver) is re-folded from its log and its row\n\t * rewritten; nothing else is touched, so a restart on an up-to-date database does\n\t * one aggregate read.\n\t *\n\t * - Runs only on a log the W8b integrity scan reports clean. With quarantined rows,\n\t * rows materialized before the fold existed are kept as they are (re-folding a\n\t * log that lost operations would bake the loss in) and the skip is logged loudly;\n\t * such a record is folded from its remaining log on its next write. Records with\n\t * no row yet, and fold states this release already wrote, are still processed.\n\t * - Idempotent and resumable: each batch commits on its own, and staleness is\n\t * re-derived from the tables at every start, so a crash resumes where it stopped.\n\t * A plan change first marks every stored state stale (one statement), then\n\t * records the new fingerprint, so it is resumable too.\n\t */\n\t/**\n\t * One-time migration of each collection table to the lossless text encoding (RT-65):\n\t * rows written before it whose raw-string columns contain U+FFFF (the escape\n\t * introducer) are re-encoded, so the decoder returns them unchanged.\n\t */\n\tprivate migrateTextCodec(schema: SchemaDefinition): void {\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tconst key = `${PG_TEXT_CODEC_MIGRATION_KEY}${name}`\n\t\t\tthis.db.transaction((tx) => {\n\t\t\t\tif (tx.all(sql`SELECT 1 AS one FROM kora_server_meta WHERE key = ${key}`).length > 0) return\n\t\t\t\tconst textColumns = Object.entries(collection.fields)\n\t\t\t\t\t.filter(([, descriptor]) => isPgRawTextKind(descriptor.kind))\n\t\t\t\t\t.map(([field]) => quoteIdent(field))\n\t\t\t\tfor (const statement of sqliteTextCodecMigrationSql(quoteIdent(name), textColumns)) {\n\t\t\t\t\ttx.run(sql.raw(statement))\n\t\t\t\t}\n\t\t\t\ttx.run(\n\t\t\t\t\tsql`INSERT OR IGNORE INTO kora_server_meta (key, value) VALUES (${key}, ${String(Date.now())})`,\n\t\t\t\t)\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Write the beta.12 clears the ids prove into the stored bodies, once per database\n\t * (RT-85, see `provenLegacyClears`), and mark their records' fold states stale.\n\t */\n\tprivate async canonicalizeLegacyBodies(): Promise<void> {\n\t\tconst done = this.db.all(\n\t\t\tsql`SELECT 1 AS one FROM kora_server_meta WHERE key = ${LEGACY_BODIES_META_KEY}`,\n\t\t)\n\t\tif (done.length > 0) return\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(\n\t\t\t\tand(\n\t\t\t\t\teq(operations.type, 'update'),\n\t\t\t\t\tsql`${operations.hashVersion} IS NULL`,\n\t\t\t\t\tsql`${operations.previousData} IS NOT NULL`,\n\t\t\t\t),\n\t\t\t)\n\t\t\t.all()\n\t\tconst changed = await provenLegacyClears(rows.map((row) => this.deserializeOperation(row)))\n\t\tthis.db.transaction((tx) => {\n\t\t\tfor (const op of changed) {\n\t\t\t\ttx.update(operations)\n\t\t\t\t\t.set({ data: JSON.stringify(op.data) })\n\t\t\t\t\t.where(eq(operations.id, op.id))\n\t\t\t\t\t.run()\n\t\t\t\ttx.run(\n\t\t\t\t\tsql`UPDATE kora_fold_state SET covered_seq = -1 WHERE collection = ${op.collection} AND record_id = ${op.recordId}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\ttx.run(\n\t\t\t\tsql`INSERT OR IGNORE INTO kora_server_meta (key, value) VALUES (${LEGACY_BODIES_META_KEY}, ${String(changed.length)})`,\n\t\t\t)\n\t\t})\n\t}\n\n\tprivate rematerialize(): FoldMigrationReport {\n\t\tconst schema = this.schema\n\t\tconst report: FoldMigrationReport = {\n\t\t\tran: true,\n\t\t\trecords: 0,\n\t\t\tskippedUnclean: 0,\n\t\t\tfullRefold: false,\n\t\t}\n\t\tif (!schema) return { ...report, ran: false }\n\t\tconst clean = this.logIntegrity.totalQuarantined === 0\n\t\tconst fingerprint = serverFoldPlanFingerprint(\n\t\t\tschema,\n\t\t\tthis.explicitAuthorities,\n\t\t\tthis.operationTransforms,\n\t\t)\n\t\tconst storedFingerprint = this.db.all<{ value: string }>(\n\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${FOLD_PLAN_FINGERPRINT_KEY}`,\n\t\t)[0]?.value\n\t\tif (storedFingerprint !== fingerprint) {\n\t\t\treport.fullRefold = storedFingerprint !== undefined\n\t\t\tthis.db.transaction((tx) => {\n\t\t\t\ttx.run(sql`UPDATE kora_fold_state SET covered_seq = -1`)\n\t\t\t\ttx.run(\n\t\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${FOLD_PLAN_FINGERPRINT_KEY}, ${fingerprint})`,\n\t\t\t\t)\n\t\t\t})\n\t\t}\n\t\tfor (const collection of Object.keys(schema.collections)) {\n\t\t\tlet cursor = ''\n\t\t\tfor (;;) {\n\t\t\t\tconst page = this.db.all<{\n\t\t\t\t\trecord_id: string\n\t\t\t\t\tmax_seq: number\n\t\t\t\t\tcovered: number | null\n\t\t\t\t\thas_row: number\n\t\t\t\t}>(\n\t\t\t\t\tsql`SELECT o.record_id AS record_id, MAX(o.delivery_seq) AS max_seq,\n\t\t\t\t\t\t(SELECT f.covered_seq FROM kora_fold_state f WHERE f.collection = o.collection AND f.record_id = o.record_id) AS covered,\n\t\t\t\t\t\t(SELECT f.covered_op_id FROM kora_fold_state f WHERE f.collection = o.collection AND f.record_id = o.record_id) AS covered_op_id,\n\t\t\t\t\t\tEXISTS (SELECT 1 FROM ${sql.raw(quoteIdent(collection))} c WHERE c.id = o.record_id) AS has_row\n\t\t\t\t\tFROM operations o\n\t\t\t\t\tWHERE o.collection = ${collection} AND o.record_id > ${cursor}\n\t\t\t\t\tGROUP BY o.record_id\n\t\t\t\t\tHAVING covered IS NULL OR covered <> MAX(o.delivery_seq) OR NOT EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM operations x WHERE x.id = covered_op_id AND x.delivery_seq = covered\n\t\t\t\t\t)\n\t\t\t\t\tORDER BY o.record_id\n\t\t\t\t\tLIMIT ${FOLD_MIGRATION_BATCH}`,\n\t\t\t\t)\n\t\t\t\tif (page.length === 0) break\n\t\t\t\tcursor = page[page.length - 1]?.record_id ?? cursor\n\t\t\t\tthis.db.transaction((tx) => {\n\t\t\t\t\tfor (const candidate of page) {\n\t\t\t\t\t\tconst affected =\n\t\t\t\t\t\t\t!clean && isQuarantineAffected(this.quarantine, collection, candidate.record_id)\n\t\t\t\t\t\tconst rows = tx\n\t\t\t\t\t\t\t.select()\n\t\t\t\t\t\t\t.from(operations)\n\t\t\t\t\t\t\t.where(\n\t\t\t\t\t\t\t\tand(\n\t\t\t\t\t\t\t\t\teq(operations.collection, collection),\n\t\t\t\t\t\t\t\t\teq(operations.recordId, candidate.record_id),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.all()\n\t\t\t\t\t\tlet covered = 0\n\t\t\t\t\t\tlet coveredOpId = ''\n\t\t\t\t\t\tfor (const row of rows) {\n\t\t\t\t\t\t\tif ((row.deliverySeq ?? 0) > covered) {\n\t\t\t\t\t\t\t\tcovered = row.deliverySeq ?? 0\n\t\t\t\t\t\t\t\tcoveredOpId = row.id\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst ops = rows.map((row) => this.deserializeOperation(row))\n\t\t\t\t\t\tif (affected) {\n\t\t\t\t\t\t\t// Incomplete log (RT-70): the kept row is the base, never the log alone.\n\t\t\t\t\t\t\tconst stored = tx.all<{ state: string }>(\n\t\t\t\t\t\t\t\tsql`SELECT state FROM kora_fold_state WHERE collection = ${collection} AND record_id = ${candidate.record_id}`,\n\t\t\t\t\t\t\t)[0]\n\t\t\t\t\t\t\tthis.writeFoldedRecord(\n\t\t\t\t\t\t\t\ttx,\n\t\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\t\tcandidate.record_id,\n\t\t\t\t\t\t\t\tthis.rebuildAffected(\n\t\t\t\t\t\t\t\t\ttx,\n\t\t\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\t\t\tcandidate.record_id,\n\t\t\t\t\t\t\t\t\tparseStoredFoldState(stored?.state, collection, candidate.record_id),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tcovered,\n\t\t\t\t\t\t\t\tcoveredOpId,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\treport.skippedUnclean++\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.writeFoldedRecord(\n\t\t\t\t\t\t\t\ttx,\n\t\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\t\tcandidate.record_id,\n\t\t\t\t\t\t\t\trefoldRecord(ops, schema, this.foldOptions),\n\t\t\t\t\t\t\t\tcovered,\n\t\t\t\t\t\t\t\tcoveredOpId,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treport.records++\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\tif (page.length < FOLD_MIGRATION_BATCH) break\n\t\t\t}\n\t\t\t// Affected records with no remaining operation at all (every one quarantined,\n\t\t\t// the insert included): the kept row is their whole history.\n\t\t\tif (!clean) {\n\t\t\t\tthis.db.transaction((tx) => {\n\t\t\t\t\tconst orphans = tx.all<{ id: string }>(\n\t\t\t\t\t\tsql`SELECT c.id AS id FROM ${sql.raw(quoteIdent(collection))} c\n\t\t\t\t\t\t\tWHERE NOT EXISTS (SELECT 1 FROM kora_fold_state f WHERE f.collection = ${collection} AND f.record_id = c.id)\n\t\t\t\t\t\t\tAND NOT EXISTS (SELECT 1 FROM operations o WHERE o.collection = ${collection} AND o.record_id = c.id)`,\n\t\t\t\t\t)\n\t\t\t\t\tfor (const { id } of orphans) {\n\t\t\t\t\t\tif (!isQuarantineAffected(this.quarantine, collection, id)) continue\n\t\t\t\t\t\tconst state = this.rebuildAffected(tx, collection, id, null)\n\t\t\t\t\t\tif (!state) continue\n\t\t\t\t\t\tthis.writeFoldedRecord(tx, collection, id, state, 0, '')\n\t\t\t\t\t\treport.skippedUnclean++\n\t\t\t\t\t\treport.records++\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tif (report.skippedUnclean > 0) {\n\t\t\tconsole.error(\n\t\t\t\t`[kora] Fold re-materialization: ${report.skippedUnclean} record(s) own quarantined operations (${this.logIntegrity.totalQuarantined} quarantined row(s), see operations_quarantine). Their log is incomplete, so their pre-fold rows were kept as the base their remaining and later operations fold onto. Repair or release the quarantined rows to restore their exact history.`,\n\t\t\t)\n\t\t}\n\t\treturn report\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t\tthis.schema?.collections[collection],\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(\n\t\twhere: Record<string, unknown>,\n\t\tincludeDeleted: boolean,\n\t\tcollectionDef?: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\t// Raw-string columns hold the lossless encoding (RT-65): filter on it too.\n\t\t\tconst kind = collectionDef?.fields[key]?.kind\n\t\t\tconst param =\n\t\t\t\tkind && isPgRawTextKind(kind) && typeof value === 'string' ? encodePgText(value) : value\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${param}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializeSqliteFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\t// Include metadata fields\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\t\t// A soft-deleted row (only returned when deleted rows are asked for) says so, so a\n\t\t// caller never mistakes the last values the fold keeps on it for a live record.\n\t\tif (Number(row._deleted) === 1) record._deleted = 1\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOpsLog(collection: string): MaterializedRecord[] {\n\t\tconst ids = this.db.all<{ record_id: string }>(\n\t\t\tsql`SELECT DISTINCT record_id FROM operations WHERE collection = ${collection} ORDER BY record_id`,\n\t\t)\n\t\tconst records: MaterializedRecord[] = []\n\t\tfor (const { record_id: recordId } of ids) {\n\t\t\tconst ops = this.readRecordOperations(this.db, collection, recordId, 0)\n\t\t\tconst state = refoldRecord(ops, this.schema ?? EMPTY_FOLD_SCHEMA, this.foldOptions)\n\t\t\tconst row = state ? projectFoldState(state, this.foldOptions) : null\n\t\t\tif (row && !row.deleted) records.push({ id: recordId, ...row.values })\n\t\t}\n\t\treturn records\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Table setup\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Create the operations and sync_state tables if they don't exist.\n\t */\n\tprivate ensureTables(): void {\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\tdata TEXT,\n\t\t\t\tprevious_data TEXT,\n\t\t\t\tatomic_ops TEXT,\n\t\t\t\twall_time INTEGER NOT NULL,\n\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\treceived_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t// ops\" and keep materializing by last-write-wins exactly as before. SQLite has\n\t\t// no ADD COLUMN IF NOT EXISTS, so tolerate the duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN atomic_ops TEXT`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t// delivery watermark. SQLite has no ADD COLUMN IF NOT EXISTS, so tolerate the\n\t\t// duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN delivery_seq INTEGER`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Backward-compatible migration: the per-operation scope snapshot (RT-14). Rows\n\t\t// written before it are backfilled from the log when the schema is set.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN scope_snapshot TEXT`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Backward-compatible migration (RT-37): the sole-holder flag behind the partial\n\t\t// unique index. Existing rows read 0 (outside the index; the append check still\n\t\t// judges them as holders).\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN seq_unique INTEGER NOT NULL DEFAULT 0`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Content-hash version of the stored id (CORE-1, protocol v2). Null means 1.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN hash_version INTEGER`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Encryption envelope of the operation (protocol v2), stored opaquely (JSON).\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN encrypted TEXT`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)\n\t\t`)\n\t\t// Per-record fold state (W7): the materialized row is projected from it.\n\t\t// `covered_seq` / `covered_op_id`: the delivery sequence and id of the record's\n\t\t// newest operation merged into it (the state covers every operation up to it).\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS kora_fold_state (\n\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\tstate TEXT NOT NULL,\n\t\t\t\tcovered_seq INTEGER NOT NULL,\n\t\t\t\tcovered_op_id TEXT NOT NULL DEFAULT '',\n\t\t\t\tPRIMARY KEY (collection, record_id)\n\t\t\t)\n\t\t`)\n\t\t// A pre-release table may lack it; '' never matches an operation id, so such a\n\t\t// state is re-folded on its next use.\n\t\ttry {\n\t\t\tthis.db.run(\n\t\t\t\tsql`ALTER TABLE kora_fold_state ADD COLUMN covered_op_id TEXT NOT NULL DEFAULT ''`,\n\t\t\t)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\t// Blob content hash -> principals that pushed (or first claimed) it (RT-11).\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS blob_owners (\n\t\t\t\thash TEXT NOT NULL,\n\t\t\t\towner TEXT NOT NULL,\n\t\t\t\tcreated_at INTEGER NOT NULL,\n\t\t\t\tPRIMARY KEY (hash, owner)\n\t\t\t)\n\t\t`)\n\n\t\t// Small key/value store for server-side metadata (snapshot fingerprint, RT-20).\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS kora_server_meta (\n\t\t\t\tkey TEXT PRIMARY KEY,\n\t\t\t\tvalue TEXT NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\t// Wrapped end-to-end encryption key records (ENC-1, D4b): salt, KDF parameters and\n\t\t// wrapped keys per (owner, keyring). Never a usable key.\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS kora_encryption_keys (\n\t\t\t\towner TEXT NOT NULL,\n\t\t\t\tkeyring TEXT NOT NULL,\n\t\t\t\trevision INTEGER NOT NULL,\n\t\t\t\trecord TEXT NOT NULL,\n\t\t\t\tupdated_at INTEGER NOT NULL,\n\t\t\t\tPRIMARY KEY (owner, keyring)\n\t\t\t)\n\t\t`)\n\n\t\t// Node id -> principal binding (see claimNode). One row per device node id.\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS node_claims (\n\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\tuser_id TEXT NOT NULL,\n\t\t\t\tclaimed_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE UNIQUE INDEX IF NOT EXISTS idx_delivery_seq_unique\n\t\t\tON operations (delivery_seq)\n\t\t\tWHERE delivery_seq IS NOT NULL\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)\n\t\t`)\n\n\t\t// Index for efficient per-record operation lookups during materialization\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)\n\t\t`)\n\t\t// A record's newest delivery sequence in one probe (the fold freshness check).\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection_record_delivery ON operations (collection, record_id, delivery_seq)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\tmax_sequence_number INTEGER NOT NULL,\n\t\t\t\tlast_seen_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\tvalue INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\t// How uploaded operations were resolved without being stored under their sequence\n\t\t// (validator `ignore`, terminal refusal, renumbered duplicate; RT-43, RT-47).\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS operation_resolutions (\n\t\t\t\top_id TEXT PRIMARY KEY,\n\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\toutcome TEXT NOT NULL,\n\t\t\t\tcode TEXT,\n\t\t\t\tmessage TEXT,\n\t\t\t\tresolved_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_resolutions_node_seq\n\t\t\tON operation_resolutions (node_id, sequence_number)\n\t\t`)\n\t\t// (node, sequence) held by more than one operation: legacy pairs (RT-48).\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS sequence_pairs (\n\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\tPRIMARY KEY (node_id, sequence_number)\n\t\t\t)\n\t\t`)\n\n\t\tthis.backfillDeliverySequence()\n\t\tthis.sequenceEpoch = this.ensureSequenceEnforcement()\n\t\tthis.backfillSequencePairs()\n\t\tthis.logIntegrity = this.scanLogIntegrityOnce()\n\t\tthis.quarantine = buildQuarantineScope(\n\t\t\tthis.db\n\t\t\t\t.all<{ row_json: string }>(sql`SELECT row_json FROM operations_quarantine`)\n\t\t\t\t.map((row) => row.row_json),\n\t\t)\n\t}\n\n\t/**\n\t * The startup log-integrity scan's result (W8 step 0): rows that could not be read\n\t * back into an operation are moved to `operations_quarantine` once per database,\n\t * before any fold reads them.\n\t */\n\tgetLogIntegrityReport(): ServerLogIntegrityReport {\n\t\treturn { ...this.logIntegrity, quarantined: [...this.logIntegrity.quarantined] }\n\t}\n\n\tprivate scanLogIntegrityOnce(): ServerLogIntegrityReport {\n\t\tthis.db.run(sql.raw(SERVER_LOG_QUARANTINE_DDL))\n\t\tconst report: ServerLogIntegrityReport = {\n\t\t\tcheckedRows: 0,\n\t\t\tquarantined: [],\n\t\t\tran: false,\n\t\t\ttotalQuarantined: 0,\n\t\t}\n\t\tconst done = this.db.all<{ value: string }>(\n\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${SERVER_LOG_INTEGRITY_META_KEY}`,\n\t\t)\n\t\tif (done.length === 0) {\n\t\t\treport.ran = true\n\t\t\tconst bad: Array<{\n\t\t\t\trowid: number\n\t\t\t\trow: ServerOperationRow\n\t\t\t\tproblem: string\n\t\t\t\tdetail: string\n\t\t\t}> = []\n\t\t\tlet after = 0\n\t\t\tfor (;;) {\n\t\t\t\tconst page = this.db.all<ServerOperationRow & { __rowid: number }>(\n\t\t\t\t\tsql`SELECT rowid AS __rowid, id, node_id, type, collection, record_id, data, previous_data, atomic_ops, wall_time, logical, timestamp_node_id, sequence_number, causal_deps, schema_version FROM operations WHERE rowid > ${after} ORDER BY rowid LIMIT 1000`,\n\t\t\t\t)\n\t\t\t\tfor (const { __rowid, ...row } of page) {\n\t\t\t\t\treport.checkedRows++\n\t\t\t\t\tconst verdict = checkServerOperationRow(row)\n\t\t\t\t\tif (verdict) bad.push({ rowid: __rowid, row, ...verdict })\n\t\t\t\t}\n\t\t\t\tif (page.length < 1000) break\n\t\t\t\tafter = page[page.length - 1]?.__rowid ?? after\n\t\t\t}\n\t\t\tconst now = Date.now()\n\t\t\tthis.db.transaction((tx) => {\n\t\t\t\tfor (const entry of bad) {\n\t\t\t\t\tconst id = typeof entry.row.id === 'string' ? entry.row.id : `rowid:${entry.rowid}`\n\t\t\t\t\ttx.run(\n\t\t\t\t\t\tsql`INSERT OR REPLACE INTO operations_quarantine (id, problem, detail, row_json, quarantined_at) VALUES (${id}, ${entry.problem}, ${entry.detail}, ${quarantineRowJson(entry.row)}, ${now})`,\n\t\t\t\t\t)\n\t\t\t\t\ttx.run(sql`DELETE FROM operations WHERE rowid = ${entry.rowid}`)\n\t\t\t\t\treport.quarantined.push({ operationId: id, problem: entry.problem, detail: entry.detail })\n\t\t\t\t}\n\t\t\t\ttx.run(\n\t\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SERVER_LOG_INTEGRITY_META_KEY}, ${String(now)})`,\n\t\t\t\t)\n\t\t\t})\n\t\t\tif (bad.length > 0) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[kora] Log integrity: ${bad.length} unreadable operation row(s) moved to operations_quarantine.`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tconst total = this.db.all<{ n: number }>(sql`SELECT COUNT(*) AS n FROM operations_quarantine`)\n\t\treport.totalQuarantined = Number(total[0]?.n ?? 0)\n\t\treturn report\n\t}\n\n\t/**\n\t * Index the legacy pairs already in the log once (history written before the\n\t * `sequence_pairs` table existed); appends maintain it from then on.\n\t */\n\tprivate backfillSequencePairs(): void {\n\t\tthis.db.transaction((tx) => {\n\t\t\tconst done = tx.all<{ value: string }>(\n\t\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${SEQUENCE_PAIRS_BACKFILLED_KEY}`,\n\t\t\t)\n\t\t\tif (done.length > 0) return\n\t\t\ttx.run(sql.raw(BACKFILL_SEQUENCE_PAIRS_SQL))\n\t\t\ttx.run(\n\t\t\t\tsql`INSERT OR REPLACE INTO kora_server_meta (key, value) VALUES (${SEQUENCE_PAIRS_BACKFILLED_KEY}, '1')`,\n\t\t\t)\n\t\t})\n\t}\n\n\t/**\n\t * Record the sequence-enforcement epoch on the first start of this release (the log's\n\t * highest delivery sequence then; see {@link SEQUENCE_ENFORCEMENT_EPOCH_KEY}) and\n\t * back the append check with the partial unique index over sole-holder rows\n\t * ({@link NODE_SEQ_UNIQUE_INDEX}), which therefore always exists: a legacy duplicate\n\t * pair is stored unflagged. Replaces the earlier indexes (a full one, created only\n\t * when the log had no duplicates, and one over the rows past the epoch, which a\n\t * legacy client's pair would violate). Runs in one write transaction, so stores\n\t * sharing a file agree on the epoch.\n\t */\n\tprivate ensureSequenceEnforcement(): number {\n\t\treturn this.db.transaction((tx) => {\n\t\t\ttx.run(\n\t\t\t\tsql`INSERT OR IGNORE INTO kora_server_meta (key, value)\n\t\t\t\t\tSELECT ${SEQUENCE_ENFORCEMENT_EPOCH_KEY}, CAST(COALESCE(MAX(delivery_seq), 0) AS TEXT) FROM operations`,\n\t\t\t)\n\t\t\tconst stored = tx.all<{ value: string }>(\n\t\t\t\tsql`SELECT value FROM kora_server_meta WHERE key = ${SEQUENCE_ENFORCEMENT_EPOCH_KEY}`,\n\t\t\t)[0]?.value\n\t\t\t// Absent only if the row could not be written: enforce everything (epoch 0).\n\t\t\tconst epoch = stored === undefined ? 0 : Number(stored)\n\t\t\tif (!Number.isSafeInteger(epoch) || epoch < 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`kora_server_meta.${SEQUENCE_ENFORCEMENT_EPOCH_KEY} holds \"${String(stored)}\", not a delivery sequence. Restore it from a backup or delete the row to re-derive it.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tfor (const superseded of SUPERSEDED_NODE_SEQ_UNIQUE_INDEXES) {\n\t\t\t\ttx.run(sql.raw(`DROP INDEX IF EXISTS ${superseded}`))\n\t\t\t}\n\t\t\t// A row is flagged only when nothing held its sequence at insert, so flagged\n\t\t\t// duplicates can come only from outside writes (a manual edit, an older release\n\t\t\t// writing into this file). Before (re)creating the index, unflag them: they stay\n\t\t\t// stored and judged by the append check, and the index creation cannot fail.\n\t\t\tconst indexed = tx.all<{ name: string }>(\n\t\t\t\tsql`SELECT name FROM sqlite_master WHERE type = 'index' AND name = ${NODE_SEQ_UNIQUE_INDEX}`,\n\t\t\t)\n\t\t\tif (indexed.length === 0) {\n\t\t\t\ttx.run(sql`\n\t\t\t\t\tUPDATE operations SET seq_unique = 0\n\t\t\t\t\tWHERE seq_unique = 1 AND EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM operations other\n\t\t\t\t\t\tWHERE other.node_id = operations.node_id\n\t\t\t\t\t\t\tAND other.sequence_number = operations.sequence_number\n\t\t\t\t\t\t\tAND other.id <> operations.id\n\t\t\t\t\t)\n\t\t\t\t`)\n\t\t\t}\n\t\t\ttx.run(\n\t\t\t\tsql.raw(\n\t\t\t\t\t`CREATE UNIQUE INDEX IF NOT EXISTS ${NODE_SEQ_UNIQUE_INDEX} ON operations (node_id, sequence_number) WHERE seq_unique = 1`,\n\t\t\t\t),\n\t\t\t)\n\t\t\treturn epoch\n\t\t})\n\t}\n\n\t/**\n\t * Assign delivery sequences to any operations written before the column existed,\n\t * then seed the durable counter from the current max. Ordered by\n\t * (received_at, sequence_number, id) so the backfill is deterministic and stable\n\t * across restarts. A one-time migration: after it runs, all rows have a value.\n\t */\n\tprivate backfillDeliverySequence(): void {\n\t\tthis.db.transaction((tx) => {\n\t\t\tconst maxRow = tx.all<{ m: number | null }>(\n\t\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t\t)\n\t\t\tlet next = maxRow[0]?.m ?? 0\n\t\t\tconst nullRows = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE delivery_seq IS NULL ORDER BY received_at ASC, sequence_number ASC, id ASC`,\n\t\t\t)\n\t\t\tfor (const row of nullRows) {\n\t\t\t\tnext += 1\n\t\t\t\ttx.run(sql`UPDATE operations SET delivery_seq = ${next} WHERE id = ${row.id}`)\n\t\t\t}\n\t\t\ttx.insert(deliveryCounter)\n\t\t\t\t.values({ id: 1, value: next })\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: deliveryCounter.id,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tvalue: sql`MAX(${deliveryCounter.value}, ${next})`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside the append transaction. SQLite locks\n\t * the database for the write transaction, and this counter row keeps sequence\n\t * allocation shared by every SqliteServerStore instance using the same file.\n\t */\n\tprivate nextDeliverySeq(tx: BetterSQLite3Database): number {\n\t\tconst rows = tx\n\t\t\t.update(deliveryCounter)\n\t\t\t.set({ value: sql`${deliveryCounter.value} + 1` })\n\t\t\t.where(eq(deliveryCounter.id, 1))\n\t\t\t.returning({ value: deliveryCounter.value })\n\t\t\t.all()\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn value\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * @param soleHolder - Nothing else held the (node, sequence) at insert: the row is\n\t * flagged `seq_unique` and covered by {@link NODE_SEQ_UNIQUE_INDEX}. False for a\n\t * legacy pair's second operation and for restored backup rows.\n\t */\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t\tsoleHolder = false,\n\t): typeof operations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\n\t\t\tnodeId: op.nodeId,\n\t\t\ttype: op.type,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tdata: op.data !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t\tseqUnique: soleHolder ? 1 : 0,\n\t\t\thashVersion: op.hashVersion ?? null,\n\t\t\tencrypted: envelopeColumn(op),\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof operations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\tconst encrypted = parseEnvelopeColumn(row.encrypted)\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t\t...(row.hashVersion === 1 || row.hashVersion === 2 ? { hashVersion: row.hashVersion } : {}),\n\t\t\t...(encrypted !== undefined ? { encrypted } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('SqliteServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a SqliteServerStore with a file-backed or in-memory database.\n * Handles database creation, Drizzle wrapping, and table setup.\n *\n * @param options - Configuration options\n * @param options.filename - Path to SQLite database file. Defaults to ':memory:' for testing.\n * @param options.nodeId - Deprecated (a plain id becomes a legacy authoritative id). Leave\n * unset: the server authors under the persisted `kora:server:<deployment>:<instance>`.\n * @param options.instanceId - Optional stable instance id\n * @returns A ready-to-use SqliteServerStore\n *\n * @example\n * ```typescript\n * import { createSqliteServerStore } from '@korajs/server'\n *\n * const store = createSqliteServerStore({ filename: './kora-server.db' })\n *\n * // Optional: enable materialized collection tables for fast queries\n * await store.setSchema(mySchema)\n *\n * const server = createKoraServer({ store, port: 3001 })\n * ```\n */\nexport function createSqliteServerStore(\n\toptions: {\n\t\tfilename?: string\n\t} & ServerIdentityOptions,\n): SqliteServerStore {\n\t// better-sqlite3 is a native CJS addon — use esmRequire (from createRequire)\n\t// so this works in both ESM and CJS contexts.\n\tconst Database = esmRequire('better-sqlite3')\n\tconst { drizzle } = esmRequire('drizzle-orm/better-sqlite3')\n\n\tconst filename = options.filename ?? ':memory:'\n\tconst sqlite = new Database(filename)\n\n\t// Enable WAL mode for better concurrent read/write performance\n\tsqlite.pragma('journal_mode = WAL')\n\n\tconst db = drizzle(sqlite)\n\treturn new SqliteServerStore(db, options.nodeId, {\n\t\t...(options.authoritativeNodeIds ? { authoritativeNodeIds: options.authoritativeNodeIds } : {}),\n\t\t...(options.revokedAuthoritativeNodeIds\n\t\t\t? { revokedAuthoritativeNodeIds: options.revokedAuthoritativeNodeIds }\n\t\t\t: {}),\n\t\t...(options.instanceId !== undefined ? { instanceId: options.instanceId } : {}),\n\t})\n}\n","import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'\n\n/**\n * Drizzle schema for the Kora sync server's SQLite database.\n *\n * Two tables:\n * - `operations` — the append-only operation log (content-addressed by id)\n * - `syncState` — tracks the max sequence number seen per node (version vector)\n */\n\nexport const operations = sqliteTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: integer('wall_time').notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\tsequenceNumber: integer('sequence_number').notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: integer('received_at').notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit. Drives the\n\t\t// gap-free server->client delivery watermark. Nullable only for rows written\n\t\t// before the column existed; those are backfilled on startup.\n\t\tdeliverySeq: integer('delivery_seq'),\n\t\t// JSON { pre, post }: the record's scope values around this operation, captured\n\t\t// from the server's own rows at apply time (RT-14). Null for legacy rows that\n\t\t// could not be backfilled.\n\t\tscopeSnapshot: text('scope_snapshot'),\n\t\t// 1 when this row was the sole holder of its (node_id, sequence_number) when stored;\n\t\t// 0 for the second operation of a legacy duplicate pair and for rows written\n\t\t// before the column existed. The partial unique index NODE_SEQ_UNIQUE_INDEX covers\n\t\t// only flagged rows (RT-37; see server-store.ts).\n\t\tseqUnique: integer('seq_unique').notNull().default(0),\n\t\t// Content-hash version of `id` (CORE-1). Null for v1 rows and rows written before\n\t\t// the column existed.\n\t\thashVersion: integer('hash_version'),\n\t\t// Protocol v2 encryption envelope (JSON), stored opaquely. Null for plaintext.\n\t\tencrypted: text('encrypted'),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_collection').on(table.collection),\n\t\treceivedIdx: index('idx_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const syncState = sqliteTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: integer('max_sequence_number').notNull(),\n\tlastSeenAt: integer('last_seen_at').notNull(),\n})\n\nexport const deliveryCounter = sqliteTable('delivery_counter', {\n\tid: integer('id').primaryKey(),\n\tvalue: integer('value').notNull(),\n})\n","import { SyncError } from '@korajs/core'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\nexport interface HttpPollResponse {\n\tstatus: 200 | 204 | 304 | 410\n\tbody?: string | Uint8Array\n\theaders?: Record<string, string>\n}\n\ninterface QueuedMessage {\n\tetag: string\n\tcontentType: string\n\tpayload: string | Uint8Array\n\t/** Approximate size of `payload` in bytes. */\n\tbytes: number\n}\n\n/**\n * Default ceiling on bytes queued for an HTTP long-poll client that is not polling\n * (32 MiB). Past it the session is closed instead of growing server memory without\n * bound; the client resumes from its delivery watermark on its next handshake.\n */\nexport const DEFAULT_HTTP_MAX_QUEUED_BYTES = 32 * 1024 * 1024\n\n/**\n * Server-side transport for HTTP long-polling clients.\n *\n * Incoming client messages are pushed via POST, while outbound server\n * messages are pulled via GET long-poll requests.\n */\nexport class HttpServerTransport implements ServerTransport {\n\tprivate readonly serializer: MessageSerializer\n\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\n\tprivate connected = true\n\tprivate nextSequence = 1\n\tprivate readonly queue: QueuedMessage[] = []\n\tprivate queuedBytes = 0\n\tprivate readonly maxQueuedBytes: number\n\n\t/**\n\t * @param serializer - Message serializer\n\t * @param options - `maxQueuedBytes`: close the session once this many bytes wait\n\t * unpolled (default 32 MiB; 0 disables the ceiling)\n\t */\n\tconstructor(serializer: MessageSerializer, options: { maxQueuedBytes?: number } = {}) {\n\t\tthis.serializer = serializer\n\t\tthis.maxQueuedBytes = options.maxQueuedBytes ?? DEFAULT_HTTP_MAX_QUEUED_BYTES\n\t}\n\n\tsend(message: import('@korajs/sync').SyncMessage): void {\n\t\tif (!this.connected) return\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tconst isBinary = encoded instanceof Uint8Array\n\t\t// UTF-16 length is a cheap upper-bound proxy for the UTF-8 size of JSON text.\n\t\tconst bytes = isBinary ? encoded.byteLength : encoded.length\n\t\tthis.queue.push({\n\t\t\tetag: this.makeEtag(this.nextSequence++),\n\t\t\tcontentType: isBinary ? 'application/x-protobuf' : 'application/json',\n\t\t\tpayload: encoded,\n\t\t\tbytes,\n\t\t})\n\t\tthis.queuedBytes += bytes\n\t\tif (this.maxQueuedBytes > 0 && this.queuedBytes > this.maxQueuedBytes) {\n\t\t\t// The client stopped polling: end the session rather than buffer without bound\n\t\t\t// (and drop what it never collected).\n\t\t\tthis.queue.length = 0\n\t\t\tthis.queuedBytes = 0\n\t\t\tthis.close(1001, 'http session queue overflow')\n\t\t}\n\t}\n\n\t/** Bytes queued for the client and not yet polled (delivery-stream backpressure). */\n\tbufferedAmount(): number {\n\t\treturn this.queuedBytes\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.connected\n\t}\n\n\t/**\n\t * Close the session. Messages already queued (typically the final error that\n\t * explains the close, for example a refused handshake) stay pollable, so a\n\t * long-polling client learns why, exactly as a WebSocket client receives the error\n\t * frame before the close; once drained, polls answer 410.\n\t */\n\tclose(code = 1000, reason = 'transport closed'): void {\n\t\tif (!this.connected) return\n\t\tthis.connected = false\n\t\tthis.closeHandler?.(code, reason)\n\t}\n\n\t/** True while messages queued before the close are still waiting to be polled. */\n\thasPending(): boolean {\n\t\treturn this.queue.length > 0\n\t}\n\n\treceive(payload: string | Uint8Array): void {\n\t\tif (!this.connected) {\n\t\t\tthrow new SyncError('HTTP server transport is closed')\n\t\t}\n\n\t\ttry {\n\t\t\tconst message = this.serializer.decode(payload)\n\t\t\tthis.messageHandler?.(message)\n\t\t} catch (error) {\n\t\t\tthis.errorHandler?.(error instanceof Error ? error : new Error(String(error)))\n\t\t}\n\t}\n\n\tpoll(ifNoneMatch?: string): HttpPollResponse {\n\t\tif (!this.connected && this.queue.length === 0) {\n\t\t\treturn { status: 410 }\n\t\t}\n\n\t\tconst next = this.queue[0]\n\t\tif (!next) {\n\t\t\treturn { status: 204 }\n\t\t}\n\n\t\tif (ifNoneMatch && ifNoneMatch === next.etag) {\n\t\t\treturn {\n\t\t\t\tstatus: 304,\n\t\t\t\theaders: { etag: next.etag },\n\t\t\t}\n\t\t}\n\n\t\tthis.queue.shift()\n\t\tthis.queuedBytes = Math.max(0, this.queuedBytes - next.bytes)\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\tbody: next.payload,\n\t\t\theaders: {\n\t\t\t\t'content-type': next.contentType,\n\t\t\t\tetag: next.etag,\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate makeEtag(sequence: number): string {\n\t\treturn `W/\"${sequence}\"`\n\t}\n}\n","import { SyncError } from '@korajs/core'\nimport type { SyncMessage } from '@korajs/sync'\nimport { JsonMessageSerializer } from '@korajs/sync'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\n/** WebSocket ready states (mirrors ws constants) */\nconst WS_OPEN = 1\n\n/**\n * Default interval between WebSocket pings, in ms (SRV-6, LMS #12). Inside the 30-120 s\n * idle windows of carrier NATs, so an idle connection stays mapped, and long enough\n * that a ping rarely wakes a phone's radio on its own.\n */\nexport const DEFAULT_WS_HEARTBEAT_INTERVAL_MS = 25_000\n/** Pings that may go unanswered before the connection is declared dead. */\nexport const DEFAULT_WS_MAX_MISSED_PONGS = 2\n/**\n * Default ceiling on bytes queued for one client and not yet written to the network\n * (32 MiB). Past it the client is too slow (or gone) and the connection is closed\n * instead of growing server memory without bound. The delivery stream itself pauses\n * far below this (backpressure); the ceiling only catches what bypasses it.\n */\nexport const DEFAULT_WS_MAX_BUFFERED_BYTES = 32 * 1024 * 1024\n/** Close code for a connection that missed its pongs or overflowed its send buffer. */\nconst CLOSE_CODE_GOING_AWAY = 1001\n\n/**\n * Minimal interface for a ws.WebSocket instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsWebSocket {\n\treadyState: number\n\tsend(data: string | Uint8Array, callback?: (err?: Error) => void): void\n\tclose(code?: number, reason?: string): void\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tremoveAllListeners(): void\n\t/** Send a ping frame (ws). Without it, no liveness probing happens. */\n\tping?(): void\n\t/** Destroy the socket at once, emitting `close` (ws). Falls back to `close()`. */\n\tterminate?(): void\n\t/** Bytes queued and not yet written to the network (ws). */\n\treadonly bufferedAmount?: number\n}\n\n/**\n * Options for WsServerTransport.\n */\nexport interface WsServerTransportOptions {\n\t/** Message serializer. Defaults to JsonMessageSerializer. */\n\tserializer?: MessageSerializer\n\t/**\n\t * Interval between WebSocket pings, in ms (SRV-6). A connection that leaves\n\t * `maxMissedPongs` pings in a row unanswered (and sends nothing else meanwhile) is\n\t * terminated, which runs Kora's normal close path. Defaults to 25 seconds; 0\n\t * disables probing. Keep it at 15 seconds or more on mobile networks.\n\t */\n\theartbeatIntervalMs?: number\n\t/** Unanswered pings before the connection is terminated. Defaults to 2. */\n\tmaxMissedPongs?: number\n\t/**\n\t * Bytes that may be queued for this client before it is disconnected as a slow\n\t * consumer. Defaults to 32 MiB; 0 disables the ceiling.\n\t */\n\tmaxBufferedBytes?: number\n}\n\n/**\n * Server-side transport wrapping a ws.WebSocket connection.\n * Created for each incoming client connection.\n *\n * It probes liveness with WebSocket pings (both the standalone server and\n * `createProductionServer` create their connections through it), so a half-open\n * connection, a peer that vanished without a FIN, is detected and closed instead of\n * holding a session forever.\n */\nexport class WsServerTransport implements ServerTransport {\n\tprivate readonly ws: WsWebSocket\n\tprivate readonly serializer: MessageSerializer\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\tprivate readonly maxMissedPongs: number\n\tprivate readonly maxBufferedBytes: number\n\tprivate heartbeatTimer: ReturnType<typeof setInterval> | null = null\n\tprivate missedPongs = 0\n\tprivate terminated = false\n\n\tconstructor(ws: WsWebSocket, options?: WsServerTransportOptions) {\n\t\tthis.ws = ws\n\t\tthis.serializer = options?.serializer ?? new JsonMessageSerializer()\n\t\tthis.maxMissedPongs = Math.max(1, options?.maxMissedPongs ?? DEFAULT_WS_MAX_MISSED_PONGS)\n\t\tthis.maxBufferedBytes = options?.maxBufferedBytes ?? DEFAULT_WS_MAX_BUFFERED_BYTES\n\t\tthis.setupListeners()\n\t\tthis.startHeartbeat(options?.heartbeatIntervalMs ?? DEFAULT_WS_HEARTBEAT_INTERVAL_MS)\n\t}\n\n\tsend(message: SyncMessage): void {\n\t\tif (this.ws.readyState !== WS_OPEN) {\n\t\t\tthrow new SyncError('Cannot send message: WebSocket is not open', {\n\t\t\t\treadyState: this.ws.readyState,\n\t\t\t\tmessageType: message.type,\n\t\t\t})\n\t\t}\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tthis.ws.send(encoded)\n\t\tif (this.maxBufferedBytes > 0 && this.bufferedAmount() > this.maxBufferedBytes) {\n\t\t\t// The client is not reading (or reads far slower than the server writes).\n\t\t\t// Disconnect it rather than buffer without bound; it resumes from its\n\t\t\t// delivery watermark on reconnect, so nothing is lost.\n\t\t\tthis.terminate('slow consumer: send buffer exceeded')\n\t\t}\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.ws.readyState === WS_OPEN\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.stopHeartbeat()\n\t\tthis.ws.close(code ?? 1000, reason ?? 'server closing')\n\t}\n\n\tbufferedAmount(): number {\n\t\tconst amount = this.ws.bufferedAmount\n\t\treturn typeof amount === 'number' && Number.isFinite(amount) ? amount : 0\n\t}\n\n\t/**\n\t * Ping every `intervalMs`; terminate once `maxMissedPongs` pings in a row went\n\t * unanswered. A pong or any inbound message proves the peer alive.\n\t */\n\tprivate startHeartbeat(intervalMs: number): void {\n\t\tif (intervalMs <= 0 || typeof this.ws.ping !== 'function') return\n\t\tthis.heartbeatTimer = setInterval(() => {\n\t\t\tif (this.ws.readyState !== WS_OPEN) {\n\t\t\t\tthis.stopHeartbeat()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.missedPongs >= this.maxMissedPongs) {\n\t\t\t\tthis.terminate('heartbeat timeout: no pong')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.missedPongs += 1\n\t\t\ttry {\n\t\t\t\tthis.ws.ping?.()\n\t\t\t} catch {\n\t\t\t\t// A ping on a dying socket throws; the next tick (or its close) settles it.\n\t\t\t}\n\t\t}, intervalMs)\n\t\t// A heartbeat must never keep a Node process alive on its own.\n\t\t;(this.heartbeatTimer as { unref?: () => void }).unref?.()\n\t}\n\n\tprivate stopHeartbeat(): void {\n\t\tif (this.heartbeatTimer !== null) {\n\t\t\tclearInterval(this.heartbeatTimer)\n\t\t\tthis.heartbeatTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Drop the connection at once. ws emits `close` from `terminate()`, which runs\n\t * Kora's normal close path (session, relays and side channels are released).\n\t */\n\tprivate terminate(reason: string): void {\n\t\tif (this.terminated) return\n\t\tthis.terminated = true\n\t\tthis.stopHeartbeat()\n\t\tif (typeof this.ws.terminate === 'function') {\n\t\t\tthis.ws.terminate()\n\t\t} else {\n\t\t\tthis.ws.close(CLOSE_CODE_GOING_AWAY, reason)\n\t\t}\n\t}\n\n\tprivate setupListeners(): void {\n\t\tthis.ws.on('message', (data: unknown) => {\n\t\t\tthis.missedPongs = 0\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\ttypeof data !== 'string' &&\n\t\t\t\t\t!(data instanceof Uint8Array) &&\n\t\t\t\t\t!(data instanceof ArrayBuffer)\n\t\t\t\t) {\n\t\t\t\t\tthrow new SyncError('Unsupported WebSocket payload type', {\n\t\t\t\t\t\tpayloadType: typeof data,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst decoded = this.serializer.decode(data)\n\t\t\t\tthis.messageHandler?.(decoded)\n\t\t\t} catch (err) {\n\t\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t\t}\n\t\t})\n\n\t\tthis.ws.on('pong', () => {\n\t\t\tthis.missedPongs = 0\n\t\t})\n\n\t\tthis.ws.on('close', (code: unknown, reason: unknown) => {\n\t\t\tthis.stopHeartbeat()\n\t\t\tthis.closeHandler?.(Number(code) || 1006, String(reason || 'connection closed'))\n\t\t})\n\n\t\tthis.ws.on('error', (err: unknown) => {\n\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t})\n\t}\n}\n","import type {\n\tKoraEventEmitter,\n\tOperation,\n\tOperationTransform,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n\tVersionVector,\n} from '@korajs/core'\nimport { canonicalizeLegacyOperation, isServerNodeId, operationSchemaView } from '@korajs/core'\nimport { SyncError, generateUUIDv7, hashBlob } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type { SideEffectOp } from '@korajs/merge'\nimport type {\n\tAwarenessUpdateMessage,\n\tBlobChunkPushMessage,\n\tBlobChunkRequestMessage,\n\tBlobChunkResponseMessage,\n\tEncryptionKeyPutMessage,\n\tEncryptionKeyRequestMessage,\n\tHandshakeMessage,\n\tMessageSerializer,\n\tOperationBatchMessage,\n\tSyncMessage,\n\tWireFormat,\n\tWrappedKeyRecord,\n\tYjsDocUpdateMessage,\n} from '@korajs/sync'\nimport { SyncEncryptor, decodeBlobChunkBytes } from '@korajs/sync'\nimport {\n\ttype DeltaCursor,\n\tINVALID_OPERATION_ID,\n\tLEGACY_SYNC_PROTOCOL_VERSION,\n\tNegotiatedMessageSerializer,\n\tPLAINTEXT_REJECTED,\n\tPROTOCOL_V1_DEPRECATED,\n\tProtobufMessageSerializer,\n\tSCHEMA_MISMATCH_PREFIX,\n\tSYNC_PROTOCOL_VERSION,\n\ttype SyncQuerySubset,\n\tcreateDeltaCursorFromBatch,\n\tdeclaredProtocolVersion,\n\tdecodeDeltaCursor,\n\tdedupeQuerySubsets,\n\tencodeDeltaCursor,\n\tisClientSchemaVersionSupported,\n\toperationMatchesQuerySubsets,\n\tsliceOperationsAfterCursor,\n\tversionVectorToWire,\n\twireToVersionVector,\n} from '@korajs/sync'\nimport {\n\trestoreUndefinedFromPrevious,\n\tscopeViewKey,\n\tverifyInboundOperation,\n} from '@korajs/sync/internal'\nimport {\n\tRESTRICTED_REJECTION_CODE,\n\tapplyServerOperation,\n\tderiveServerSideEffects,\n\tisAuthoredCopyOfSideEffect,\n\tundoneSideEffectsOfStoredDelete,\n} from '../apply/apply-server-operation'\nimport { INVALID_IDENTIFIER_CODE, isStorableIdentifier } from '../apply/ingest-validation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { NoAuthProvider } from '../auth/no-auth'\nimport type { EncryptionKeyService } from '../encryption/key-record-service'\nimport { ANONYMOUS_KEY_OWNER, userKeyOwner } from '../encryption/key-record-service'\nimport type { Logger } from '../logging/structured-logger'\nimport type { BlobAccessIndex } from '../richtext/blob-access-index'\nimport {\n\tauthorizeOperationReferences,\n\toperationHasReferences,\n} from '../scopes/reference-authorization'\nimport { ScopeRequiredError, resolveSessionScopes } from '../scopes/resolve-session-scopes'\nimport { InvalidScopePredicateError } from '../scopes/scope-predicate-errors'\nimport {\n\ttype ScopeMap,\n\ttype UplinkAuthorizationResult,\n\tauthorizeRecordWrite,\n\tauthorizeUplinkWrite,\n\tmissingScopeFields,\n\tnormalizeScopeMap,\n\toperationMatchesScopes,\n\trecordMatchesScopes,\n\tsnapshotEntersScopes,\n\tsnapshotExitsScopes,\n\tsnapshotLacksScopeFields,\n\tsnapshotValuesWithFallback,\n} from '../scopes/server-scope-filter'\nimport type { ProductionHttpRouteContext } from '../server/route-context'\nimport type {\n\tDeliveredOperation,\n\tLegacySequencePair,\n\tMaterializedRecord,\n\tOperationResolution,\n\tOperationResolutionOutcome,\n\tOperationScopeSnapshot,\n\tServerStore,\n\tStoredOperationKey,\n} from '../store/server-store'\nimport { SEQUENCE_CONFLICT_CODE } from '../store/server-store'\nimport type { ServerTransport } from '../transport/server-transport'\nimport type { AuthContext, AuthProvider, SessionRevocation } from '../types'\nimport {\n\tFORGED_DUPLICATE_CODE,\n\tisRewrittenEcho,\n\tisSameOperationAsStored,\n} from './duplicate-identity'\nimport { isOperationTimestampValid } from './operation-validation'\nimport { buildScopeEntryOperation } from './scope-entry'\nimport {\n\tBATCH_LOOKUP_RATE_COST,\n\tDEFAULT_MAX_BLOB_REQUESTS_PER_MINUTE,\n\tDEFAULT_MAX_OPERATION_BYTES,\n\tDEFAULT_MAX_OPS_PER_BATCH,\n\tDEFAULT_MAX_OPS_PER_MINUTE,\n\ttype IngestRateLimiter,\n\tSessionRateLimiter,\n\tvalidateOperationSize,\n} from './session-operation-limits'\n\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\n\n/** Refusal of an operation larger than `maxOperationBytes` (RT-86), per operation. */\nexport const OPERATION_TOO_LARGE_CODE = 'OPERATION_TOO_LARGE'\n\n/** Refusal of an operation whose schema transform broke its contract (RT-84). */\nexport const SCHEMA_TRANSFORM_INVALID_CODE = 'SCHEMA_TRANSFORM_INVALID'\n/** Default time a connection has to send its handshake before it is closed (SRV-6). */\nexport const DEFAULT_HANDSHAKE_TIMEOUT_MS = 10_000\n/**\n * Default outbound bytes queued on the socket above which the delivery stream pauses\n * until the client drains it (SRV-5/SRV-6 backpressure): 1 MiB.\n */\nexport const DEFAULT_DELIVERY_HIGH_WATER_BYTES = 1024 * 1024\n/** How often a paused delivery stream re-checks the transport's queued bytes. */\nconst DELIVERY_DRAIN_POLL_MS = 25\n/**\n * Longest wait between re-sends of an unacknowledged delivery (the stale window\n * doubles on every re-send without progress, LMS #12): five minutes.\n */\nexport const MAX_DELIVERY_RETRANSMIT_BACKOFF_MS = 5 * 60_000\n/** Delivery retransmit timeout before any round trip was measured. */\nconst INITIAL_DELIVERY_RTO_MS = 2_000\n/** Floor of the measured delivery retransmit timeout. */\nconst MIN_DELIVERY_RTO_MS = 1_000\n/** Ceiling of the measured delivery retransmit timeout (before backoff). */\nconst MAX_DELIVERY_RTO_MS = 60_000\n/** Unacknowledged batches remembered for round-trip samples. */\nconst MAX_TRACKED_UNACKED_BATCHES = 4096\n/** setTimeout's largest delay; longer credential lifetimes are re-armed in steps. */\nconst MAX_TIMER_DELAY_MS = 2_147_483_647\n/** Revocations remembered for a session whose handshake has not resolved its principal. */\nconst MAX_PENDING_REVOCATIONS = 32\n\n/**\n * Legacy node-claim owner shared by every anonymous principal (RT-5, superseded by\n * RT-12). Claims recorded under it by pre-release builds are not adopted by anyone;\n * an administrator releases them with `KoraSyncServer.releaseNodeClaim`.\n */\nexport const ANONYMOUS_NODE_OWNER = 'kora:anonymous'\n\n/**\n * Prefix reserved for principals Kora itself synthesizes (node-claim owners of\n * anonymous devices). An auth provider may not issue a user id that starts with it,\n * so no real user can ever collide with an anonymous device's claim (RT-12).\n */\nexport const RESERVED_PRINCIPAL_PREFIX = 'kora:'\n\n/** Prefix of the node-claim owner of an anonymous device: `kora:anon-node:<sha256(token)>`. */\nconst ANONYMOUS_NODE_OWNER_PREFIX = 'kora:anon-node:'\n/**\n * Prefix of a PROVISIONAL anonymous claim (RT-21):\n * `kora:anon-pending:<sha256(token)>:<expiresAtMs>`. It becomes the confirmed\n * `kora:anon-node:<sha256(token)>` once the device proves it saved the token.\n */\nconst ANONYMOUS_PENDING_OWNER_PREFIX = 'kora:anon-pending:'\n/** Default time an unconfirmed provisional claim stays re-issuable: 24 hours. */\nexport const DEFAULT_ANONYMOUS_CLAIM_TTL_MS = 24 * 60 * 60 * 1000\n\nfunction pendingOwner(tokenHash: string, expiresAtMs: number): string {\n\treturn `${ANONYMOUS_PENDING_OWNER_PREFIX}${tokenHash}:${String(expiresAtMs)}`\n}\n\nfunction parsePendingOwner(\n\towner: string | null,\n): { tokenHash: string; expiresAtMs: number } | null {\n\tif (owner === null || !owner.startsWith(ANONYMOUS_PENDING_OWNER_PREFIX)) return null\n\tconst rest = owner.slice(ANONYMOUS_PENDING_OWNER_PREFIX.length)\n\tconst separator = rest.lastIndexOf(':')\n\tif (separator <= 0) return null\n\tconst expiresAtMs = Number(rest.slice(separator + 1))\n\tif (!Number.isFinite(expiresAtMs)) return null\n\treturn { tokenHash: rest.slice(0, separator), expiresAtMs }\n}\n\n/** Outcome of an anonymous device's node claim at handshake (RT-12, RT-21). */\ntype AnonymousClaimOutcome =\n\t| {\n\t\t\tok: true\n\t\t\t/** The claim owner now recorded for the node. */\n\t\t\towner: string\n\t\t\t/** The device key (`kora:anon-node:<hash>`), stable across confirmation. */\n\t\t\tdeviceKey: string\n\t\t\t/** A token to hand the device in the response, when one was (re-)issued. */\n\t\t\tissuedToken: string | null\n\t\t\t/** Set while the claim is provisional: what confirmation replaces it with. */\n\t\t\tpending: { owner: string; token: string; confirmedOwner: string } | null\n\t }\n\t| { ok: false }\n/** Longest node token a client may present. */\nconst MAX_NODE_TOKEN_LENGTH = 256\n/** Bytes of randomness in a server-issued node token (256 bits). */\nconst NODE_TOKEN_BYTES = 32\n\n/** 256 random bits, base64url: an unguessable per-device node token. */\nfunction generateNodeToken(): string {\n\tconst bytes = new Uint8Array(NODE_TOKEN_BYTES)\n\tglobalThis.crypto.getRandomValues(bytes)\n\tlet binary = ''\n\tfor (const byte of bytes) binary += String.fromCharCode(byte)\n\treturn btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/**\n * The node-claim owner of an anonymous device holding `nodeToken`. Only the hash is\n * stored, so the claims table never holds a usable secret.\n */\nasync function anonymousNodeOwner(nodeToken: string): Promise<string> {\n\treturn `${ANONYMOUS_NODE_OWNER_PREFIX}${await nodeTokenHash(nodeToken)}`\n}\n\nasync function nodeTokenHash(nodeToken: string): Promise<string> {\n\treturn hashBlob(new TextEncoder().encode(nodeToken))\n}\n\n/**\n * Session-ending error codes, all retriable. `AUTH_REVOKED` / `AUTH_EXPIRED`: the\n * client refreshes its credential and re-handshakes. `SCOPE_CHANGED` (RT-26): the\n * principal's grant changed; the client simply reconnects and gets the new scope.\n */\nexport type SessionTerminationCode = 'AUTH_REVOKED' | 'AUTH_EXPIRED' | 'SCOPE_CHANGED'\n\n/**\n * Same principal for re-validation: the same user and device, or both anonymous\n * (an anonymous principal gets a fresh user id per authentication).\n */\nfunction samePrincipal(a: AuthContext, b: AuthContext): boolean {\n\tif (a.anonymous === true || b.anonymous === true)\n\t\treturn a.anonymous === true && b.anonymous === true\n\treturn a.userId === b.userId && a.metadata?.deviceId === b.metadata?.deviceId\n}\n\nfunction revocationMatches(principal: AuthContext, filter: SessionRevocation): boolean {\n\tif (filter.userId === undefined && filter.deviceId === undefined) return false\n\tif (filter.userId !== undefined && principal.userId !== filter.userId) return false\n\tif (filter.deviceId !== undefined && principal.metadata?.deviceId !== filter.deviceId) {\n\t\treturn false\n\t}\n\treturn true\n}\n\n/**\n * Tracks auth providers we have already warned about, so the multi-tenant\n * no-scopes guardrail fires once per server (keyed by provider instance)\n * rather than once per client connection.\n */\nconst warnedUnscopedProviders = new WeakSet<AuthProvider>()\n\n/**\n * Warn once when a real (multi-user) auth provider is configured but an\n * authenticated session resolves to no sync scopes at all.\n *\n * With no scopes, `operationMatchesScopes` treats every operation as visible,\n * which is the correct zero-config behavior for a single-user local-first app.\n * But once a real auth provider is in play, \"no scopes\" means every user syncs\n * every other user's data — a silent cross-tenant data exposure. We cannot flip\n * the default to deny-all without breaking the zero-config promise, so instead\n * we surface the dangerous configuration loudly and exactly once.\n *\n * `null` auth (local-first, no auth) and `NoAuthProvider` (dev/testing) are\n * intentionally excluded: for those, unscoped sync is the intended behavior.\n */\nfunction warnIfMultiTenantWithoutScopes(\n\tauth: AuthProvider | null,\n\tresolvedScopes: unknown,\n\tschema: SchemaDefinition | null,\n): void {\n\tif (!auth || auth instanceof NoAuthProvider) {\n\t\treturn\n\t}\n\tif (resolvedScopes) {\n\t\treturn\n\t}\n\tif (!schema || Object.keys(schema.collections).length === 0) {\n\t\treturn\n\t}\n\tif (warnedUnscopedProviders.has(auth)) {\n\t\treturn\n\t}\n\twarnedUnscopedProviders.add(auth)\n\tconsole.warn(\n\t\t'[kora] An authenticated session resolved to no sync scopes, so every ' +\n\t\t\t\"user will sync every other user's data. Return per-user sync scopes \" +\n\t\t\t\"from your auth provider (for example KoraAuthProvider's resolveScopes) \" +\n\t\t\t'to isolate tenants. Note: declaring sync rules in your schema is not ' +\n\t\t\t'enough on its own — the per-user values come from the auth provider. ' +\n\t\t\t'(This warning is expected for single-tenant apps where all authenticated ' +\n\t\t\t'users are meant to share the same data.)',\n\t)\n}\n\nfunction stableStringify(value: unknown): string {\n\tif (Array.isArray(value)) {\n\t\treturn `[${value.map((item) => stableStringify(item)).join(',')}]`\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst record = value as Record<string, unknown>\n\t\tconst entries = Object.keys(record)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)\n\t\treturn `{${entries.join(',')}}`\n\t}\n\treturn JSON.stringify(value)\n}\n\nfunction sameScopeMap(a: unknown, b: unknown): boolean {\n\tconst normalize = (value: unknown): unknown =>\n\t\tvalue && typeof value === 'object'\n\t\t\t? normalizeScopeMap(value as Record<string, Record<string, unknown>>)\n\t\t\t: value\n\treturn stableStringify(normalize(a) ?? null) === stableStringify(normalize(b) ?? null)\n}\n\n/**\n * Possible states for a client session.\n */\nexport type SessionState = 'connected' | 'authenticated' | 'syncing' | 'streaming' | 'closed'\n\n/**\n * Callback invoked when a session has new operations to relay to other sessions.\n */\nexport type RelayCallback = (sourceSessionId: string, operations: Operation[]) => void\n\n/**\n * Callback invoked when a session receives an awareness update to relay to other sessions.\n */\nexport type AwarenessRelayCallback = (\n\tsourceSessionId: string,\n\tmessage: AwarenessUpdateMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a Yjs doc channel update to relay.\n */\nexport type YjsDocRelayCallback = (\n\tsourceSessionId: string,\n\tmessage: YjsDocUpdateMessage,\n\tstoredRecord: MaterializedRecord | null,\n) => void\n\n/**\n * Callback invoked when a session receives a blob chunk request to route.\n */\nexport type BlobChunkRequestCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkRequestMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a blob chunk response to route back.\n */\nexport type BlobChunkResponseCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkResponseMessage,\n) => void\n\n/**\n * Persist a blob chunk (or manifest) uploaded by a client, keyed by its content\n * hash. Provided by the server operator; enables central blob storage so bytes\n * survive the authoring device going offline.\n */\nexport type PersistBlobChunk = (hash: string, bytes: Uint8Array) => Promise<void> | void\n\n/** Default largest single blob chunk (or manifest) a session may push: 1 MiB. */\nexport const DEFAULT_MAX_BLOB_CHUNK_BYTES = 1024 * 1024\n/** Default total blob bytes one session may push for central persistence: 256 MiB. */\nexport const DEFAULT_MAX_BLOB_BYTES_PER_SESSION = 256 * 1024 * 1024\n\n/**\n * Options for creating a ClientSession.\n */\nexport interface ClientSessionOptions {\n\t/** Unique session identifier */\n\tsessionId: string\n\t/** Transport for this client connection */\n\ttransport: ServerTransport\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Authentication provider (optional) */\n\tauth?: AuthProvider\n\t/** Message serializer */\n\tserializer?: MessageSerializer\n\t/** Event emitter for DevTools integration */\n\temitter?: KoraEventEmitter\n\t/** Structured logger used for protocol and persistence failures */\n\tlogger?: Logger\n\t/** Max operations per sync batch */\n\tbatchSize?: number\n\t/** Schema version the server expects */\n\tschemaVersion?: number\n\t/** Inclusive client schema versions accepted at handshake */\n\tsupportedSchemaVersions?: { min: number; max: number }\n\t/** Schema transforms: judged views of older operations (transforms at fold time, RT-84). */\n\toperationTransforms?: OperationTransform[]\n\t/** Called when this session has operations to relay to other sessions */\n\tonRelay?: RelayCallback\n\t/** Called when this session receives an awareness update to broadcast */\n\tonAwarenessUpdate?: AwarenessRelayCallback\n\t/** Called when this session receives a Yjs doc channel update to broadcast */\n\tonYjsDocUpdate?: YjsDocRelayCallback\n\t/** Called when this session receives a blob chunk request to route */\n\tonBlobChunkRequest?: BlobChunkRequestCallback\n\t/** Called when this session receives a blob chunk response to route back */\n\tonBlobChunkResponse?: BlobChunkResponseCallback\n\t/** The key service storing wrapped encryption key records (ENC-1). */\n\tencryptionKeys?: EncryptionKeyService\n\t/** Called after this session wrote a key record, to push it to the owner's other sessions. */\n\tonEncryptionKeyWritten?: (\n\t\tsessionId: string,\n\t\towner: string,\n\t\tkeyring: string,\n\t\trecord: WrappedKeyRecord,\n\t) => void\n\t/** Key-service messages allowed per session per minute. Defaults to 60. */\n\tmaxKeyRequestsPerMinute?: number\n\t/** Persist a client-uploaded blob chunk centrally (keyed by content hash) */\n\tpersistBlobChunk?: PersistBlobChunk\n\t/**\n\t * Called once the session completes an accepted handshake and reaches streaming.\n\t * Side channels (Yjs doc, blob and awareness relays) register the session here,\n\t * never at connect time, so an unauthenticated connection is never on a relay.\n\t */\n\tonReady?: (sessionId: string) => void\n\t/** Largest single blob chunk this session may push. Defaults to 1 MiB. */\n\tmaxBlobChunkBytes?: number\n\t/** Total blob bytes this session may push. Defaults to 256 MiB. */\n\tmaxBlobBytesPerSession?: number\n\t/** Called when this session closes */\n\tonClose?: (sessionId: string) => void\n\t/**\n\t * Called on close with relay operations this client never acknowledged, so the\n\t * server can buffer them per node id and redeliver on the client's next\n\t * connection. Closes the window where a relay dropped just before a reconnect\n\t * would otherwise be lost (the per-session retransmit tick never fires in time).\n\t */\n\tonOrphanedRelays?: (nodeId: string, ops: Operation[]) => void\n\t/**\n\t * Called once this session reaches streaming to pull any relay operations buffered\n\t * for its node id while it was disconnected. They are re-sent through the normal\n\t * relay path (re-filtered by this session's current scope).\n\t */\n\ttakeOrphanedRelays?: (nodeId: string) => Operation[]\n\t/** Maximum serialized operation size in bytes. Defaults to 256 KiB. */\n\tmaxOperationBytes?: number\n\t/** Maximum operations accepted per minute for this session. Defaults to 600. */\n\tmaxOpsPerMinute?: number\n\t/**\n\t * Blob chunk requests accepted per minute, separate from the operation budget\n\t * (RT-24). Defaults to 6000.\n\t */\n\tmaxBlobRequestsPerMinute?: number\n\t/** Length of the blob request window in ms. One minute; shorter only in tests. */\n\tblobRequestWindowMs?: number\n\t/**\n\t * Largest operation batch accepted in one message. A larger batch is refused whole\n\t * (`BATCH_TOO_LARGE`) before it is decoded or the store is read. Defaults to 1000.\n\t */\n\tmaxOpsPerBatch?: number\n\t/**\n\t * Adjudicate untrusted client operations before materialization. When present,\n\t * each incoming operation is passed to this validator; a `reject` decision\n\t * sends an operation-rejected message and skips materialization.\n\t */\n\tvalidateOperation?: OperationValidator\n\t/** Trusted data-plane context handed to the validator (read state, author derived ops). */\n\tkoraContext?: ProductionHttpRouteContext\n\t/**\n\t * Blob reference authority (RT-11): decides which content hashes this session may\n\t * reference in blob fields and records the bytes it pushes. Without it, blob\n\t * references are not checked at ingest.\n\t */\n\tblobAccess?: BlobAccessIndex\n\t/** See `KoraSyncServerConfig.allowLegacyAnonymousClaims` (RT-21). Defaults to true. */\n\tallowLegacyAnonymousClaims?: boolean\n\t/** See `KoraSyncServerConfig.anonymousClaimTtlMs` (RT-21). Defaults to 24 hours. */\n\tanonymousClaimTtlMs?: number\n\t/**\n\t * True when another live session (not `exceptSessionId`) is connected as `nodeId`.\n\t * A provisional anonymous claim is never re-issued away from a connected device.\n\t */\n\tisNodeLive?: (nodeId: string, exceptSessionId: string) => boolean\n\t/**\n\t * Time a new connection has to deliver its handshake, in ms (SRV-6). A connection\n\t * that sends none is closed with `HANDSHAKE_TIMEOUT`. Defaults to 10 seconds; 0\n\t * disables the deadline.\n\t */\n\thandshakeTimeoutMs?: number\n\t/**\n\t * Queued outbound bytes above which the delivery stream pauses until the client\n\t * drains its socket (transports that report `bufferedAmount`). Defaults to 1 MiB.\n\t */\n\tdeliveryHighWaterBytes?: number\n\t/**\n\t * The ingest rate limiter for a node, shared across that node's sessions so a\n\t * reconnect does not reset it (SRV-6). Called once the handshake binds the node,\n\t * with the authenticated principal's user id (null for anonymous and\n\t * unauthenticated sessions) so a per-user budget can be layered on top: a user\n\t * minting node ids must not multiply the per-node budget.\n\t * Without it the session keeps a private limiter.\n\t */\n\trateLimiterFor?: (nodeId: string, principal: string | null) => IngestRateLimiter\n\t/**\n\t * Interval of the application-level heartbeat sent to clients that advertised\n\t * support for it, in ms (LMS #12). The handshake response tells the client the\n\t * interval so it can declare the connection dead after missing two. 0 disables it.\n\t */\n\tappHeartbeatIntervalMs?: number\n\t/**\n\t * Node ids whose operations this server authors (protocol v2). Sent to clients in\n\t * the handshake response (`authoritativeNodeIds`); only operations from these nodes\n\t * may carry server-authored metadata (`fieldVersions`, `foldState`). Defaults to the\n\t * ids the store folds with (`ServerStore.getAuthoritativeNodeIds`), which is what\n\t * `KoraSyncServer` always passes. Scope-entry operations (`kora:scope-entry`) are not\n\t * listed: they carry the server's fold state and are joined, never folded as writes.\n\t */\n\tauthoritativeNodeIds?: readonly string[]\n\t/**\n\t * End-to-end encryption policy (protocol v2, ENC-3). With `required`, every uploaded\n\t * data-bearing operation must carry the encryption envelope; a plaintext one is\n\t * refused non-retriably (`PLAINTEXT_REJECTED`), unless `allowPlaintextMigration` is\n\t * set for a migration window. Without it, the server stores whatever it receives\n\t * (envelope operations always opaquely).\n\t */\n\tencryption?: { required: boolean; allowPlaintextMigration?: boolean }\n}\n\n/** A side effect of an applied delete whose server copy waits for the author's own (RT-69). */\ninterface DeferredSideEffect {\n\tparent: Operation\n\teffect: SideEffectOp\n\t/** Ids of the author's operations in the batch that are copies of this effect. */\n\tcopyIds: string[]\n}\n\n/**\n * Handles the sync protocol for a single connected client.\n *\n * Lifecycle: connected → (authenticated) → syncing → streaming → closed\n *\n * The session:\n * 1. Receives a handshake from the client\n * 2. Authenticates if an AuthProvider is configured\n * 3. Sends back a HandshakeResponse with the server's version vector\n * 4. Computes and sends the server's delta to the client (paginated)\n * 5. Processes incoming operation batches from the client\n * 6. Transitions to streaming for real-time bidirectional sync\n * 7. Relays new operations to other sessions via the RelayCallback\n */\nexport class ClientSession {\n\tprivate state: SessionState = 'connected'\n\tprivate clientNodeId: string | null = null\n\tprivate authContext: AuthContext | null = null\n\t/**\n\t * The context the auth provider returned, kept apart from {@link authContext}\n\t * (which an unauthenticated session also gets, keyed by node id) so revocation\n\t * only ever matches a verified principal.\n\t */\n\tprivate principal: AuthContext | null = null\n\t/** Closes the session when its credential expires (AUTH-11). */\n\tprivate expiryTimer: ReturnType<typeof setTimeout> | null = null\n\t/** Revocations that arrived while the handshake was still authenticating. */\n\tprivate readonly pendingRevocations: SessionRevocation[] = []\n\t/** Node token issued by this handshake's first anonymous claim, sent once in the response (RT-12). */\n\tprivate issuedNodeToken: string | null = null\n\t/** The node-claim owner this session holds its node id under (userId, or an anonymous device key). */\n\tprivate nodeOwnerKey: string | null = null\n\t/** A provisional anonymous claim awaiting the device's confirmation (RT-21). */\n\tprivate pendingNodeClaim: { owner: string; token: string; confirmedOwner: string } | null = null\n\tprivate readonly allowLegacyAnonymousClaims: boolean\n\tprivate readonly anonymousClaimTtlMs: number\n\tprivate readonly isNodeLive: ((nodeId: string, exceptSessionId: string) => boolean) | null\n\t/** The credential presented at handshake, kept to re-validate the session (RT-18). */\n\tprivate credential: string | null = null\n\t/** The scope the client asked for at handshake, kept to re-resolve scopes (RT-26). */\n\tprivate handshakeScope: HandshakeMessage['syncScope'] = undefined\n\tprivate syncQuerySubsets: SyncQuerySubset[] = []\n\tprivate scopeExitPolicy: 'retain' | 'retract' = 'retain'\n\tprivate resumeDeltaCursor: DeltaCursor | null = null\n\n\t/**\n\t * The delivery watermark the client reported at handshake, or null when the client\n\t * does not use the delivery watermark (old client, or no watermark yet). When set,\n\t * the server drives the gap-free server->client stream from delivery sequences\n\t * instead of the version-vector delta.\n\t */\n\tprivate clientDeliveryWatermark: number | null = null\n\t/**\n\t * The highest delivery sequence this client has ACKNOWLEDGED (its confirmed\n\t * watermark, as reported in acks). A retransmission rewinds the send cursor to here,\n\t * so a dropped or unapplied batch is always re-included by a re-scan from the\n\t * acknowledged position: recovery never depends on a bounded retransmit buffer.\n\t * Seeded from the client's reported watermark at handshake.\n\t */\n\tprivate lastAckedDeliverySeq = 0\n\t/**\n\t * The delivery send cursor (SRV-3): the max of the last batch sent. Live pushes\n\t * chain from it (base = lastSent), so each operation goes out once per retransmit\n\t * epoch instead of the whole unacknowledged backlog on every write. Invariant:\n\t * lastAcked <= lastSent. It rewinds to lastAcked only when the outstanding delivery\n\t * went unacknowledged for the (backed-off) stale window.\n\t */\n\tprivate lastSentDeliverySeq = 0\n\t/** The highest batch max ever sent to this client (acks are capped by it). */\n\tprivate highestSentDeliverySeq = 0\n\t/**\n\t * Own-node operations at or below this delivery sequence are streamed to this\n\t * client; above it they are skipped (it uploaded them itself). Set at handshake: a\n\t * full resync (watermark 0) recovers the client's own history up to the frontier\n\t * at that moment; a resume excludes all of them.\n\t */\n\tprivate ownOperationsIncludedThrough = 0\n\t/** When the delivery last made progress (an ack advanced, or a fresh send/rewind). */\n\tprivate lastDeliveryProgressAtMs = 0\n\t/** Consecutive rewinds without acknowledgment progress (drives the backoff, LMS #12). */\n\tprivate deliveryRewinds = 0\n\t/**\n\t * Sent, not yet acknowledged delivery batches in send order (their max and send\n\t * time), for round-trip samples. `resent` marks a re-sent range, which yields no\n\t * sample (Karn's rule: its ack cannot be matched to one transmission).\n\t */\n\tprivate readonly unackedBatches: Array<{ max: number; sentAtMs: number; resent: boolean }> = []\n\tprivate smoothedRttMs: number | null = null\n\tprivate rttVarianceMs = 0\n\t/**\n\t * Retransmit timeout of the delivery stream (RFC 6298 style: smoothed round trip\n\t * plus four deviations, floored). An outstanding delivery with no acknowledgment\n\t * progress for this long (doubled per consecutive re-send) is re-sent from the\n\t * acknowledged position. Round trips include the client's apply time, so a slow\n\t * device earns a longer timeout instead of spurious re-sends.\n\t */\n\tprivate retransmitTimeoutMs = INITIAL_DELIVERY_RTO_MS\n\tprivate retransmitTimer: ReturnType<typeof setTimeout> | null = null\n\t/** A delivery push is queued but not started: further wake-ups coalesce into it. */\n\tprivate deliveryPushQueued = false\n\t/** Serializes delivery pushes so their batches never interleave. */\n\tprivate deliveryPushChain: Promise<void> = Promise.resolve()\n\t/**\n\t * Records prefetched for the delivery chunk being filtered (LMS #11: one batched\n\t * lookup per collection per chunk instead of one query per operation). Keyed\n\t * `collection\\u0000id`; null marks a record known to be absent. Only set while a\n\t * chunk is filtered.\n\t */\n\tprivate recordLookupCache: Map<string, MaterializedRecord | null> | null = null\n\tprivate readonly deliveryHighWaterBytes: number\n\tprivate readonly handshakeTimeoutMs: number\n\tprivate handshakeTimer: ReturnType<typeof setTimeout> | null = null\n\tprivate handshakeReceived = false\n\tprivate readonly rateLimiterFor:\n\t\t| ((nodeId: string, principal: string | null) => IngestRateLimiter)\n\t\t| null\n\tprivate readonly appHeartbeatIntervalMs: number\n\tprivate appHeartbeatTimer: ReturnType<typeof setInterval> | null = null\n\t/** Last time anything was sent to the client (a heartbeat is skipped when recent). */\n\tprivate lastClientSendAtMs = 0\n\n\t/**\n\t * Relay batches sent to this client but not yet acknowledged, keyed by messageId.\n\t * The client acks every operation-batch it applies; on ack the entry is cleared.\n\t * {@link retransmitPendingRelays} re-sends anything still unacked, so a relay\n\t * dropped by a lossy transport is redelivered instead of leaving the client with a\n\t * permanent version-vector gap (a lost operation) that delta sync cannot recover.\n\t * Bounded so a silent client cannot grow it without limit.\n\t */\n\tprivate readonly pendingRelays = new Map<\n\t\tstring,\n\t\t{ message: SyncMessage; ops: Operation[]; sentAtMs: number }\n\t>()\n\tprivate static readonly MAX_PENDING_RELAYS = 1000\n\n\tprivate readonly sessionId: string\n\tprivate readonly transport: ServerTransport\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly logger: Logger | null\n\tprivate readonly batchSize: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\tprivate readonly onRelay: RelayCallback | null\n\tprivate readonly onAwarenessUpdate: AwarenessRelayCallback | null\n\tprivate readonly onYjsDocUpdate: YjsDocRelayCallback | null\n\tprivate readonly onBlobChunkRequest: BlobChunkRequestCallback | null\n\tprivate readonly onBlobChunkResponse: BlobChunkResponseCallback | null\n\tprivate readonly encryptionKeys: EncryptionKeyService | null\n\tprivate readonly onEncryptionKeyWritten: ClientSessionOptions['onEncryptionKeyWritten'] | null\n\t/** Budget of key-service messages (each may cost a store read and write). */\n\tprivate readonly keyRateLimiter: SessionRateLimiter\n\tprivate readonly persistBlobChunk: PersistBlobChunk | null\n\tprivate readonly onClose: ((sessionId: string) => void) | null\n\tprivate readonly onReady: ((sessionId: string) => void) | null\n\tprivate readonly maxBlobChunkBytes: number\n\tprivate readonly maxBlobBytesPerSession: number\n\tprivate blobBytesPushed = 0\n\tprivate readonly onOrphanedRelays: ((nodeId: string, ops: Operation[]) => void) | null\n\tprivate readonly takeOrphanedRelays: ((nodeId: string) => Operation[]) | null\n\tprivate readonly maxOperationBytes: number\n\tprivate readonly maxOpsPerMinute: number\n\tprivate readonly maxOpsPerBatch: number\n\tprivate rateLimiter: IngestRateLimiter\n\t/** Separate budget for blob chunk requests (RT-24). */\n\tprivate readonly blobRateLimiter: SessionRateLimiter\n\t/** Operations refused by the rate limiter (RT-6), for diagnostics. */\n\tprivate rateLimitedOperations = 0\n\t/** Batches refused whole for exceeding {@link maxOpsPerBatch} (RT-6). */\n\tprivate rejectedBatches = 0\n\t/** Blob chunk requests answered \"not held\" because the session was over budget (RT-17). */\n\tprivate rateLimitedBlobRequests = 0\n\t/**\n\t * The client advertised the `sequenceReservation` handshake capability (RT-37): it\n\t * reserves sequence numbers in-transaction, so a second operation under a held\n\t * (node, sequence) is refused with SEQUENCE_CONFLICT. False for a legacy client\n\t * (Kora <= beta.12), whose duplicate pairs are stored instead.\n\t */\n\tprivate sequenceReservation = false\n\t/** Legacy duplicate pairs this session stored (RT-37), for diagnostics. */\n\tprivate legacySequencePairs = 0\n\t/** Protocol version the client declared in its handshake (1 when absent). */\n\tprivate clientProtocolVersion = LEGACY_SYNC_PROTOCOL_VERSION\n\tprivate readonly authoritativeNodeIds: readonly string[] | null\n\t/** Hash version an undeclared uploaded id was verified as (RT-64), by operation object. */\n\tprivate readonly matchedHashVersions = new WeakMap<Operation, 1 | 2>()\n\t/** Uploads whose data is stored as the beta.12 writer held it (RT-71). */\n\tprivate readonly restoredLegacyData = new WeakMap<Operation, Operation['data']>()\n\t/** Operations accepted with an unverified legacy (beta.12) id (RT-71). */\n\tprivate unverifiedLegacyOperations = 0\n\tprivate forgedDuplicates = 0\n\tprivate readonly encryptionPolicy: { required: boolean; allowPlaintextMigration: boolean }\n\t/** Uploaded operations refused because their id is not their content hash (CORE-1). */\n\tprivate invalidOperationIds = 0\n\tprivate readonly validateOperation: OperationValidator | null\n\tprivate readonly koraContext: ProductionHttpRouteContext | null\n\tprivate readonly blobAccess: BlobAccessIndex | null\n\n\tconstructor(options: ClientSessionOptions) {\n\t\tthis.sessionId = options.sessionId\n\t\tthis.transport = options.transport\n\t\tthis.store = options.store\n\t\tthis.auth = options.auth ?? null\n\t\tthis.serializer = options.serializer ?? new NegotiatedMessageSerializer('json')\n\t\tthis.emitter = options.emitter ?? null\n\t\tthis.logger = options.logger ?? null\n\t\tthis.batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.schemaVersion = options.schemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tconst supported = options.supportedSchemaVersions\n\t\tthis.supportedSchemaVersions = supported ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = options.operationTransforms ?? []\n\t\tthis.onRelay = options.onRelay ?? null\n\t\tthis.onAwarenessUpdate = options.onAwarenessUpdate ?? null\n\t\tthis.onYjsDocUpdate = options.onYjsDocUpdate ?? null\n\t\tthis.onBlobChunkRequest = options.onBlobChunkRequest ?? null\n\t\tthis.onBlobChunkResponse = options.onBlobChunkResponse ?? null\n\t\tthis.encryptionKeys = options.encryptionKeys ?? null\n\t\tthis.onEncryptionKeyWritten = options.onEncryptionKeyWritten ?? null\n\t\tthis.keyRateLimiter = new SessionRateLimiter(options.maxKeyRequestsPerMinute ?? 60)\n\t\tthis.persistBlobChunk = options.persistBlobChunk ?? null\n\t\tthis.onClose = options.onClose ?? null\n\t\tthis.onReady = options.onReady ?? null\n\t\tthis.maxBlobChunkBytes = options.maxBlobChunkBytes ?? DEFAULT_MAX_BLOB_CHUNK_BYTES\n\t\tthis.maxBlobBytesPerSession =\n\t\t\toptions.maxBlobBytesPerSession ?? DEFAULT_MAX_BLOB_BYTES_PER_SESSION\n\t\tthis.onOrphanedRelays = options.onOrphanedRelays ?? null\n\t\tthis.takeOrphanedRelays = options.takeOrphanedRelays ?? null\n\t\tthis.maxOperationBytes = options.maxOperationBytes ?? DEFAULT_MAX_OPERATION_BYTES\n\t\tthis.authoritativeNodeIds = options.authoritativeNodeIds\n\t\t\t? [...options.authoritativeNodeIds]\n\t\t\t: null\n\t\tthis.encryptionPolicy = {\n\t\t\trequired: options.encryption?.required === true,\n\t\t\tallowPlaintextMigration: options.encryption?.allowPlaintextMigration === true,\n\t\t}\n\t\tthis.maxOpsPerMinute = options.maxOpsPerMinute ?? DEFAULT_MAX_OPS_PER_MINUTE\n\t\tthis.rateLimiter = new SessionRateLimiter(this.maxOpsPerMinute)\n\t\tthis.blobRateLimiter = new SessionRateLimiter(\n\t\t\toptions.maxBlobRequestsPerMinute ?? DEFAULT_MAX_BLOB_REQUESTS_PER_MINUTE,\n\t\t\toptions.blobRequestWindowMs ?? 60_000,\n\t\t)\n\t\tthis.maxOpsPerBatch = options.maxOpsPerBatch ?? DEFAULT_MAX_OPS_PER_BATCH\n\t\tthis.validateOperation = options.validateOperation ?? null\n\t\tthis.koraContext = options.koraContext ?? null\n\t\tthis.blobAccess = options.blobAccess ?? null\n\t\tthis.allowLegacyAnonymousClaims = options.allowLegacyAnonymousClaims ?? true\n\t\tthis.anonymousClaimTtlMs = options.anonymousClaimTtlMs ?? DEFAULT_ANONYMOUS_CLAIM_TTL_MS\n\t\tthis.isNodeLive = options.isNodeLive ?? null\n\t\tthis.deliveryHighWaterBytes =\n\t\t\toptions.deliveryHighWaterBytes ?? DEFAULT_DELIVERY_HIGH_WATER_BYTES\n\t\tthis.handshakeTimeoutMs = options.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS\n\t\tthis.rateLimiterFor = options.rateLimiterFor ?? null\n\t\tthis.appHeartbeatIntervalMs = options.appHeartbeatIntervalMs ?? 0\n\t}\n\n\t/**\n\t * Start handling messages from the client transport.\n\t */\n\tstart(): void {\n\t\t// A connection that never handshakes would hold a session (and a connection\n\t\t// slot) forever (SRV-6): close it once the deadline passes.\n\t\tif (this.handshakeTimeoutMs > 0) {\n\t\t\tthis.handshakeTimer = setTimeout(() => {\n\t\t\t\tthis.handshakeTimer = null\n\t\t\t\tif (this.handshakeReceived || this.state === 'closed') return\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'HANDSHAKE_TIMEOUT',\n\t\t\t\t\t`No handshake within ${String(this.handshakeTimeoutMs)} ms of connecting.`,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tthis.close('handshake timeout')\n\t\t\t}, this.handshakeTimeoutMs)\n\t\t\t;(this.handshakeTimer as { unref?: () => void }).unref?.()\n\t\t}\n\t\tthis.transport.onMessage((msg) => this.enqueueMessage(msg))\n\t\tthis.transport.onClose((_code, _reason) => this.handleTransportClose())\n\t\tthis.transport.onError((_err) => {\n\t\t\t// Transport errors during active session cause close\n\t\t\tif (this.state !== 'closed') {\n\t\t\t\tthis.handleTransportClose()\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Relay operations from another session to this client.\n\t * Only relays if the session is in streaming state and transport is connected.\n\t */\n\trelayOperations(operations: Operation[]): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t// A delivery-watermark client is fed by the gap-free delivery stream, resumed from\n\t\t// the last sequence sent to it, so its watermark keeps advancing live and a\n\t\t// reconnect resends only what was genuinely missed. The specific operations from\n\t\t// the fan-out are only a wake-up: the push pulls everything in scope after the send\n\t\t// cursor from the delivery log, which is the authoritative, contiguous order.\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tthis.pushDeliveryStream('continue')\n\t\t\treturn\n\t\t}\n\t\tif (operations.length === 0) return\n\t\t// Visibility now requires an async record lookup (scope/subset backfill); relay\n\t\t// is fire-and-forget, so run it without blocking the caller's fan-out loop.\n\t\tvoid this.relayVisibleOperations(operations)\n\t}\n\n\t/**\n\t * Push newly-available in-scope operations to a delivery-watermark client, chained\n\t * from the send cursor (SRV-3): only what was not sent yet goes out. `rewind`\n\t * first moves the cursor back to the acknowledged position (a retransmission), and\n\t * `initial` is the handshake stream (it always ends in a final batch, even an empty\n\t * one, so the client completes initial sync). Pushes are serialized so their batches\n\t * never interleave (which would break the base/max chain); wake-ups that arrive\n\t * while one is queued coalesce into it.\n\t */\n\tprivate pushDeliveryStream(mode: 'continue' | 'rewind' | 'initial' = 'continue'): void {\n\t\tif (mode === 'continue') {\n\t\t\tif (this.deliveryPushQueued) return\n\t\t\tthis.deliveryPushQueued = true\n\t\t}\n\t\tthis.deliveryPushChain = this.deliveryPushChain.then(async () => {\n\t\t\tif (mode === 'continue') this.deliveryPushQueued = false\n\t\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t\ttry {\n\t\t\t\tif (mode === 'rewind' && this.lastSentDeliverySeq > this.lastAckedDeliverySeq) {\n\t\t\t\t\tthis.lastSentDeliverySeq = this.lastAckedDeliverySeq\n\t\t\t\t\tthis.lastDeliveryProgressAtMs = Date.now()\n\t\t\t\t\t// Earlier transmissions can no longer be matched to their acks (Karn).\n\t\t\t\t\tthis.unackedBatches.length = 0\n\t\t\t\t}\n\t\t\t\tawait this.streamDelivery(this.lastSentDeliverySeq, mode === 'initial')\n\t\t\t} catch (error) {\n\t\t\t\t// A failed push (for example a transient store read error) must not reject the\n\t\t\t\t// chain and stall every future push. What it did not send stays above the send\n\t\t\t\t// cursor, so the next wake-up (a relay or the delivery poll) sends it.\n\t\t\t\tthis.logger?.log({\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tlevel: 'warn',\n\t\t\t\t\tevent: 'session.delivery_push_failed',\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tnodeId: this.clientNodeId ?? undefined,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate async relayVisibleOperations(operations: Operation[]): Promise<void> {\n\t\tconst visibleOperations: Operation[] = []\n\t\tconst retractions: Array<{ collection: string; recordId: string }> = []\n\t\tconst snapshots = await this.scopeSnapshotsFor(operations)\n\t\tfor (const op of operations) {\n\t\t\tconst snapshot = snapshots.get(op.id) ?? null\n\t\t\tif (await this.operationVisibleToClient(op, snapshot)) {\n\t\t\t\t// A record entering the scope arrives whole, before the op that moved it (RT-19).\n\t\t\t\tconst entry = await this.scopeEntryFor(op, snapshot)\n\t\t\t\tif (entry) visibleOperations.push(entry)\n\t\t\t\tvisibleOperations.push(op)\n\t\t\t} else if (await this.scopeRetractionFor(op, snapshot)) {\n\t\t\t\tretractions.push({ collection: op.collection, recordId: op.recordId })\n\t\t\t}\n\t\t}\n\t\tif (visibleOperations.length === 0 && retractions.length === 0) return\n\t\t// Re-check liveness: an await may have elapsed since the caller's guard.\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\n\t\tconst serializedOps = visibleOperations.map((op) => this.serializer.encodeOperation(op))\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: serializedOps,\n\t\t\t...(retractions.length > 0 ? { retractions } : {}),\n\t\t\tisFinal: true,\n\t\t\tbatchIndex: 0,\n\t\t}\n\t\t// Track this relay until the client acks it, so a drop can be retransmitted.\n\t\tthis.trackPendingRelay(msg, visibleOperations)\n\t\tthis.sendToClient(msg)\n\t}\n\n\t/** Record a relay batch as awaiting acknowledgment, evicting the oldest if full. */\n\tprivate trackPendingRelay(msg: SyncMessage, ops: Operation[]): void {\n\t\tif (this.pendingRelays.size >= ClientSession.MAX_PENDING_RELAYS) {\n\t\t\tconst oldest = this.pendingRelays.keys().next().value\n\t\t\tif (oldest !== undefined) {\n\t\t\t\tthis.pendingRelays.delete(oldest)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.set(msg.messageId, { message: msg, ops, sentAtMs: Date.now() })\n\t}\n\n\t/**\n\t * Retransmit relay batches this client has not acknowledged within `staleMs`.\n\t * Called on a periodic tick by the server (and directly by tests). Redelivering an\n\t * already-applied op is harmless: the client dedups by content-addressed id.\n\t *\n\t * For a delivery-watermark client it re-sends an outstanding (sent, unacknowledged)\n\t * delivery from the acknowledged position, under the same backed-off window as the\n\t * retransmit timer; `staleMs` 0 re-sends at once (a deterministic trigger for tests).\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tif (this.lastSentDeliverySeq > this.lastAckedDeliverySeq) {\n\t\t\t\tthis.pushDeliveryStreamIfSupported(staleMs, { serverFrontier: this.lastSentDeliverySeq })\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif (this.pendingRelays.size === 0) return\n\t\tconst cutoff = Date.now() - staleMs\n\t\tfor (const { message, sentAtMs } of this.pendingRelays.values()) {\n\t\t\tif (sentAtMs <= cutoff) {\n\t\t\t\tthis.sendToClient(message)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Wake the durable delivery stream for clients that negotiated delivery\n\t * watermarks: for operations appended by another server/store instance (sent from\n\t * the send cursor), and for a delivery that went unacknowledged (re-sent from the\n\t * acknowledged position once it made no progress for `staleMs`, backed off while it\n\t * stays stuck). `staleMs` 0 re-sends at once.\n\t *\n\t * @param staleMs - Base stale window before an unacknowledged delivery is re-sent\n\t * @param options - `serverFrontier`: the store's max delivery sequence, when known;\n\t * `trackStall`: emit `sync:delivery-stalled` after repeated re-sends\n\t */\n\tpushDeliveryStreamIfSupported(\n\t\tstaleMs = 0,\n\t\toptions: { trackStall?: boolean; serverFrontier?: number } = {},\n\t): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark === null) return\n\t\tconst frontier = options.serverFrontier\n\t\tif (frontier !== undefined && frontier <= this.lastAckedDeliverySeq) {\n\t\t\t// Everything is acknowledged: nothing to send or re-send.\n\t\t\tthis.deliveryRewinds = 0\n\t\t\treturn\n\t\t}\n\t\tif (frontier !== undefined && frontier > this.lastSentDeliverySeq) {\n\t\t\t// New operations (possibly committed through another instance): send them.\n\t\t\tthis.pushDeliveryStream('continue')\n\t\t\treturn\n\t\t}\n\t\tif (this.lastSentDeliverySeq <= this.lastAckedDeliverySeq) {\n\t\t\t// Nothing outstanding. Without a known frontier, look for anything new.\n\t\t\tif (frontier === undefined) this.pushDeliveryStream('continue')\n\t\t\treturn\n\t\t}\n\t\t// Everything is sent but not all acknowledged. The retransmit timer normally\n\t\t// handles this; the poll is a safety net with the same rule: re-send from the\n\t\t// acknowledged position only once the delivery made no progress for the window\n\t\t// (backed off while it stays stuck), so a client that cannot apply (or a\n\t\t// half-open socket) is not re-sent its backlog forever (LMS #12).\n\t\tif (this.transportBufferedAmount() > 0) return // still draining what was sent\n\t\tconst window =\n\t\t\tstaleMs <= 0\n\t\t\t\t? 0\n\t\t\t\t: Math.max(\n\t\t\t\t\t\tthis.retransmitWindowMs(),\n\t\t\t\t\t\tMath.min(\n\t\t\t\t\t\t\tstaleMs * 2 ** Math.min(this.deliveryRewinds, 16),\n\t\t\t\t\t\t\tMAX_DELIVERY_RETRANSMIT_BACKOFF_MS,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\tif (Date.now() - this.lastDeliveryProgressAtMs < window) return\n\t\tthis.rewindDelivery(options.trackStall === true)\n\t}\n\n\t/** Book-keeping for one sent delivery batch ending at `max`. */\n\tprivate recordDeliverySent(max: number): void {\n\t\tconst now = Date.now()\n\t\tif (max <= this.lastAckedDeliverySeq) return\n\t\tif (this.lastSentDeliverySeq <= this.lastAckedDeliverySeq) {\n\t\t\t// A new outstanding delivery: its retransmit window starts now.\n\t\t\tthis.lastDeliveryProgressAtMs = now\n\t\t}\n\t\tconst resent = max <= this.highestSentDeliverySeq\n\t\tif (max > this.lastSentDeliverySeq) this.lastSentDeliverySeq = max\n\t\tif (max > this.highestSentDeliverySeq) this.highestSentDeliverySeq = max\n\t\tthis.unackedBatches.push({ max, sentAtMs: now, resent })\n\t\tif (this.unackedBatches.length > MAX_TRACKED_UNACKED_BATCHES) this.unackedBatches.shift()\n\t\tthis.armRetransmitTimer()\n\t}\n\n\t/**\n\t * A delivery acknowledgment: advance the confirmed watermark (a retransmission\n\t * rewinds to it), take a round-trip sample, and reset the backoff. The watermark\n\t * never passes what was sent: a client cannot acknowledge what it never received.\n\t */\n\tprivate noteDeliveryAcked(deliverySequence: number): void {\n\t\tconst acked = Math.min(deliverySequence, this.highestSentDeliverySeq)\n\t\tif (acked <= this.lastAckedDeliverySeq) return\n\t\tconst now = Date.now()\n\t\tthis.lastAckedDeliverySeq = acked\n\t\tthis.lastDeliveryProgressAtMs = now\n\t\tthis.deliveryRewinds = 0\n\t\t// An ack of a batch sent before a rewind: the re-send skips what it covers.\n\t\tif (this.lastSentDeliverySeq < acked) this.lastSentDeliverySeq = acked\n\t\tlet sample: number | null = null\n\t\twhile (this.unackedBatches.length > 0) {\n\t\t\tconst first = this.unackedBatches[0]\n\t\t\tif (!first || first.max > acked) break\n\t\t\tthis.unackedBatches.shift()\n\t\t\tsample = first.resent ? null : now - first.sentAtMs\n\t\t}\n\t\tif (sample !== null) this.recordRoundTrip(sample)\n\t\tthis.armRetransmitTimer()\n\t}\n\n\t/** Fold one round-trip sample into the retransmit timeout (RFC 6298). */\n\tprivate recordRoundTrip(sampleMs: number): void {\n\t\tconst sample = Math.max(0, sampleMs)\n\t\tif (this.smoothedRttMs === null) {\n\t\t\tthis.smoothedRttMs = sample\n\t\t\tthis.rttVarianceMs = sample / 2\n\t\t} else {\n\t\t\tthis.rttVarianceMs = 0.75 * this.rttVarianceMs + 0.25 * Math.abs(this.smoothedRttMs - sample)\n\t\t\tthis.smoothedRttMs = 0.875 * this.smoothedRttMs + 0.125 * sample\n\t\t}\n\t\tthis.retransmitTimeoutMs = Math.min(\n\t\t\tMAX_DELIVERY_RTO_MS,\n\t\t\tMath.max(MIN_DELIVERY_RTO_MS, this.smoothedRttMs + 4 * this.rttVarianceMs),\n\t\t)\n\t}\n\n\t/**\n\t * The current retransmit window: the timeout, which each re-send doubled (up to\n\t * five minutes) and which only a fresh round-trip sample brings back down.\n\t */\n\tprivate retransmitWindowMs(): number {\n\t\treturn Math.min(this.retransmitTimeoutMs, MAX_DELIVERY_RETRANSMIT_BACKOFF_MS)\n\t}\n\n\t/**\n\t * (Re)arm the retransmit timer for the outstanding delivery: it fires once no\n\t * acknowledgment progress was made for the retransmit window.\n\t */\n\tprivate armRetransmitTimer(): void {\n\t\tif (this.retransmitTimer !== null) {\n\t\t\tclearTimeout(this.retransmitTimer)\n\t\t\tthis.retransmitTimer = null\n\t\t}\n\t\tif (this.state === 'closed' || this.lastSentDeliverySeq <= this.lastAckedDeliverySeq) return\n\t\tconst due = this.lastDeliveryProgressAtMs + this.retransmitWindowMs() - Date.now()\n\t\tthis.retransmitTimer = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.retransmitTimer = null\n\t\t\t\tthis.onRetransmitTimeout()\n\t\t\t},\n\t\t\tMath.max(0, due),\n\t\t)\n\t\t;(this.retransmitTimer as { unref?: () => void }).unref?.()\n\t}\n\n\t/**\n\t * No acknowledgment progress for the retransmit window: re-send from the\n\t * acknowledged position (the batch was dropped, or the client could not apply it),\n\t * unless the socket is still draining what was sent.\n\t */\n\tprivate onRetransmitTimeout(): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.lastSentDeliverySeq <= this.lastAckedDeliverySeq) return\n\t\tif (Date.now() - this.lastDeliveryProgressAtMs < this.retransmitWindowMs()) {\n\t\t\tthis.armRetransmitTimer()\n\t\t\treturn\n\t\t}\n\t\tif (this.transportBufferedAmount() > 0) {\n\t\t\t// Still writing to a slow link: that is not a loss. Look again later.\n\t\t\tthis.lastDeliveryProgressAtMs = Date.now()\n\t\t\tthis.armRetransmitTimer()\n\t\t\treturn\n\t\t}\n\t\tthis.rewindDelivery(true)\n\t}\n\n\t/** Re-send the outstanding delivery from the acknowledged position. */\n\tprivate rewindDelivery(trackStall: boolean): void {\n\t\tthis.deliveryRewinds += 1\n\t\t// Exponential backoff that survives acknowledgment progress until a fresh\n\t\t// round-trip sample (RFC 6298 5.5-5.7): acks of re-sent batches give no sample.\n\t\tthis.retransmitTimeoutMs = Math.min(\n\t\t\tthis.retransmitTimeoutMs * 2,\n\t\t\tMAX_DELIVERY_RETRANSMIT_BACKOFF_MS,\n\t\t)\n\t\tif (trackStall && this.deliveryRewinds >= 3) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:delivery-stalled',\n\t\t\t\tsessionId: this.sessionId,\n\t\t\t\twatermark: this.lastAckedDeliverySeq,\n\t\t\t\toutstandingMaxDeliverySequence: this.lastSentDeliverySeq,\n\t\t\t\trepeatCount: this.deliveryRewinds,\n\t\t\t\treason: 'unacknowledged-delivery',\n\t\t\t})\n\t\t}\n\t\tthis.pushDeliveryStream('rewind')\n\t}\n\n\t/** Bytes queued on the transport and not yet written to the network (0 if unknown). */\n\tprivate transportBufferedAmount(): number {\n\t\tconst amount = this.transport.bufferedAmount?.()\n\t\treturn typeof amount === 'number' && Number.isFinite(amount) ? amount : 0\n\t}\n\n\t/**\n\t * Wait until the transport's queued bytes drop to the high-water mark (SRV-5\n\t * backpressure), so a slow client never makes the server buffer the whole stream\n\t * in socket memory. Resolves early when the session closes.\n\t */\n\tprivate async waitForSendWindow(): Promise<void> {\n\t\twhile (\n\t\t\tthis.state !== 'closed' &&\n\t\t\tthis.transport.isConnected() &&\n\t\t\tthis.transportBufferedAmount() > this.deliveryHighWaterBytes\n\t\t) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tconst timer = setTimeout(resolve, DELIVERY_DRAIN_POLL_MS)\n\t\t\t\t;(timer as { unref?: () => void }).unref?.()\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Close this session.\n\t */\n\t/**\n\t * Hand any unacknowledged relays to the server so they survive this session and are\n\t * redelivered when this client reconnects (per-node buffer), then clear them. Called\n\t * from every session-teardown path (explicit close and transport close).\n\t */\n\tprivate flushOrphanedRelays(): void {\n\t\tif (this.onOrphanedRelays && this.clientNodeId && this.pendingRelays.size > 0) {\n\t\t\tconst ops: Operation[] = []\n\t\t\tfor (const entry of this.pendingRelays.values()) {\n\t\t\t\tops.push(...entry.ops)\n\t\t\t}\n\t\t\tif (ops.length > 0) {\n\t\t\t\tthis.onOrphanedRelays(this.clientNodeId, ops)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.clear()\n\t}\n\n\tclose(reason?: string): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.clearSessionTimers()\n\t\tthis.flushOrphanedRelays()\n\n\t\tif (this.transport.isConnected()) {\n\t\t\tthis.transport.close(1000, reason ?? 'session closed')\n\t\t}\n\n\t\tthis.onClose?.(this.sessionId)\n\t}\n\n\t/**\n\t * End this session if its verified principal matches a credential revocation\n\t * (AUTH-11): send a retriable `code` error so the client refreshes and\n\t * re-handshakes, then close. A session still authenticating remembers the\n\t * revocation and applies it as soon as its principal is known.\n\t *\n\t * @returns True when the session was closed by this call\n\t */\n\tterminateIfMatches(filter: SessionRevocation, code: SessionTerminationCode): boolean {\n\t\tif (this.state === 'closed') return false\n\t\tif (!this.principal) {\n\t\t\tif (this.state === 'connected' && this.pendingRevocations.length < MAX_PENDING_REVOCATIONS) {\n\t\t\t\tthis.pendingRevocations.push({ ...filter })\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t\tif (!revocationMatches(this.principal, filter)) return false\n\t\tthis.terminate(code)\n\t\treturn true\n\t}\n\n\t/**\n\t * Re-authenticate the credential that opened this session (RT-18). The session is\n\t * ended with a retriable `AUTH_REVOKED` (`AUTH_EXPIRED` once past its expiry) when\n\t * the provider now refuses the credential or resolves it to another principal, for\n\t * example after a revocation persisted by another server instance.\n\t *\n\t * @returns `'terminated'` when this call ended the session, `'error'` when the\n\t * provider threw (nothing is ended; the caller retries later), else `'valid'`\n\t */\n\tasync revalidateCredential(): Promise<'valid' | 'terminated' | 'error'> {\n\t\tif (this.state === 'closed' || !this.auth || !this.principal || this.credential === null) {\n\t\t\treturn 'valid'\n\t\t}\n\t\tconst principal = this.principal\n\t\tlet context: AuthContext | null\n\t\ttry {\n\t\t\tcontext = await this.auth.authenticate(this.credential)\n\t\t} catch {\n\t\t\treturn 'error'\n\t\t}\n\t\t// The session may have closed (or re-authenticated) while the provider ran.\n\t\tif (this.getState() === 'closed' || this.principal !== principal) return 'valid'\n\t\tif (context && samePrincipal(principal, context)) {\n\t\t\t// Same principal: the grant may still have changed (a role or team change).\n\t\t\t// A session whose resolved scopes differ is ended so the client reconnects and\n\t\t\t// is handed its new scope at handshake (RT-26).\n\t\t\tif (this.scopesChangedFor(context)) {\n\t\t\t\tthis.terminate('SCOPE_CHANGED')\n\t\t\t\treturn 'terminated'\n\t\t\t}\n\t\t\treturn 'valid'\n\t\t}\n\t\tconst expired = principal.expiresAt !== undefined && Date.now() >= principal.expiresAt\n\t\tthis.terminate(expired ? 'AUTH_EXPIRED' : 'AUTH_REVOKED')\n\t\treturn 'terminated'\n\t}\n\n\t/**\n\t * True when `context` (a fresh authentication of this session's principal)\n\t * resolves to download or upload scopes other than the ones this session holds.\n\t * A grant that no longer resolves at all counts as changed.\n\t */\n\tprivate scopesChangedFor(context: AuthContext): boolean {\n\t\tif (this.state !== 'streaming' && this.state !== 'syncing') return false\n\t\tconst resolution = this.computeSessionScopes(context, this.handshakeScope)\n\t\tif (!resolution.ok) return true\n\t\treturn (\n\t\t\t!sameScopeMap(resolution.downlink, this.authContext?.downlinkScopes) ||\n\t\t\t!sameScopeMap(resolution.uplink, this.authContext?.uplinkScopes)\n\t\t)\n\t}\n\n\t/**\n\t * End this session because an admin released its node id (RT-5). Retriable: a\n\t * client that still owns the node simply reconnects and claims it again.\n\t */\n\tendForNodeRelease(): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.sendError(\n\t\t\t'NODE_RELEASED',\n\t\t\t'An administrator released this device node id. Reconnect to claim it again.',\n\t\t\ttrue,\n\t\t)\n\t\tthis.close('node id released')\n\t}\n\n\tprivate terminate(code: SessionTerminationCode): void {\n\t\tconst message =\n\t\t\tcode === 'AUTH_EXPIRED'\n\t\t\t\t? 'The credential for this sync session expired. Refresh it and reconnect.'\n\t\t\t\t: code === 'SCOPE_CHANGED'\n\t\t\t\t\t? 'The sync scope granted to this session changed. Reconnect to receive the new scope.'\n\t\t\t\t\t: 'The credential for this sync session was revoked. Refresh it and reconnect.'\n\t\tthis.sendError(code, message, true)\n\t\tthis.close(\n\t\t\tcode === 'AUTH_EXPIRED'\n\t\t\t\t? 'credential expired'\n\t\t\t\t: code === 'SCOPE_CHANGED'\n\t\t\t\t\t? 'sync scope changed'\n\t\t\t\t\t: 'credential revoked',\n\t\t)\n\t}\n\n\t/** Clear every timer this session owns (expiry, handshake deadline, heartbeat). */\n\tprivate clearSessionTimers(): void {\n\t\tthis.clearExpiryTimer()\n\t\tif (this.handshakeTimer !== null) {\n\t\t\tclearTimeout(this.handshakeTimer)\n\t\t\tthis.handshakeTimer = null\n\t\t}\n\t\tif (this.appHeartbeatTimer !== null) {\n\t\t\tclearInterval(this.appHeartbeatTimer)\n\t\t\tthis.appHeartbeatTimer = null\n\t\t}\n\t\tif (this.retransmitTimer !== null) {\n\t\t\tclearTimeout(this.retransmitTimer)\n\t\t\tthis.retransmitTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Start the application-level heartbeat for a client that advertised support for it\n\t * (LMS #12): a `heartbeat` message whenever nothing else was sent for an interval,\n\t * so the client can detect a dead connection it cannot see (browsers never surface\n\t * WebSocket pings).\n\t */\n\tprivate startAppHeartbeat(): void {\n\t\tif (this.appHeartbeatIntervalMs <= 0 || this.appHeartbeatTimer !== null) return\n\t\tconst interval = this.appHeartbeatIntervalMs\n\t\tthis.appHeartbeatTimer = setInterval(() => {\n\t\t\tif (this.state === 'closed') return\n\t\t\tif (Date.now() - this.lastClientSendAtMs < interval / 2) return\n\t\t\tthis.sendToClient({ type: 'heartbeat', messageId: generateUUIDv7() })\n\t\t}, interval)\n\t\t;(this.appHeartbeatTimer as { unref?: () => void }).unref?.()\n\t}\n\n\t/**\n\t * Arm the expiry timer from `AuthContext.expiresAt`. Returns false when the\n\t * credential has already expired (the caller refuses the handshake).\n\t */\n\tprivate armExpiryTimer(expiresAt: number | undefined): boolean {\n\t\tthis.clearExpiryTimer()\n\t\tif (expiresAt === undefined || !Number.isFinite(expiresAt)) return true\n\t\tconst remaining = expiresAt - Date.now()\n\t\tif (remaining <= 0) return false\n\t\tthis.expiryTimer = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.expiryTimer = null\n\t\t\t\tif (this.state === 'closed') return\n\t\t\t\tif (Date.now() >= expiresAt) {\n\t\t\t\t\tthis.terminate('AUTH_EXPIRED')\n\t\t\t\t} else {\n\t\t\t\t\tthis.armExpiryTimer(expiresAt)\n\t\t\t\t}\n\t\t\t},\n\t\t\tMath.min(remaining, MAX_TIMER_DELAY_MS),\n\t\t)\n\t\t// A pending expiry must not keep a Node process alive on its own.\n\t\tconst timer = this.expiryTimer as { unref?: () => void }\n\t\ttimer.unref?.()\n\t\treturn true\n\t}\n\n\tprivate clearExpiryTimer(): void {\n\t\tif (this.expiryTimer !== null) {\n\t\t\tclearTimeout(this.expiryTimer)\n\t\t\tthis.expiryTimer = null\n\t\t}\n\t}\n\n\t// --- Getters ---\n\n\tgetState(): SessionState {\n\t\treturn this.state\n\t}\n\n\tgetSessionId(): string {\n\t\treturn this.sessionId\n\t}\n\n\tgetClientNodeId(): string | null {\n\t\treturn this.clientNodeId\n\t}\n\n\tgetAuthContext(): AuthContext | null {\n\t\treturn this.authContext\n\t}\n\n\t/**\n\t * The principal the auth provider verified at handshake, or null before (or\n\t * without) authentication. Unlike {@link getAuthContext}, never a context\n\t * synthesized for an unauthenticated session.\n\t */\n\tgetPrincipal(): AuthContext | null {\n\t\treturn this.principal\n\t}\n\n\tisStreaming(): boolean {\n\t\treturn this.state === 'streaming'\n\t}\n\n\t/**\n\t * Ingest refusals that happen before any store work (RT-6): operations refused by\n\t * the per-minute rate limiter and batches refused for exceeding the per-batch cap.\n\t */\n\tgetIngestLimitCounts(): {\n\t\trateLimitedOperations: number\n\t\trejectedBatches: number\n\t\trateLimitedBlobRequests: number\n\t} {\n\t\treturn {\n\t\t\trateLimitedOperations: this.rateLimitedOperations,\n\t\t\trejectedBatches: this.rejectedBatches,\n\t\t\trateLimitedBlobRequests: this.rateLimitedBlobRequests,\n\t\t}\n\t}\n\n\t/**\n\t * True when the client did not advertise the `sequenceReservation` capability\n\t * (RT-37): a legacy client (Kora <= beta.12) that may give two operations one\n\t * sequence number. Such a pair is stored and delivered, never refused with\n\t * SEQUENCE_CONFLICT. Meaningful once the handshake was accepted.\n\t */\n\tisLegacySequenceClient(): boolean {\n\t\treturn !this.sequenceReservation\n\t}\n\n\t/** Legacy duplicate (node, sequence) pairs this session stored (RT-37). */\n\tgetLegacySequencePairCount(): number {\n\t\treturn this.legacySequencePairs\n\t}\n\n\t/**\n\t * True when a stored record is inside this session's download scope, so a side\n\t * channel (for example a Yjs doc update) about it may be delivered here. A record\n\t * not stored yet is judged by its id alone.\n\t */\n\tcanReceiveRecord(\n\t\tcollection: string,\n\t\trecordId: string,\n\t\tstoredRecord: Record<string, unknown> | null,\n\t): boolean {\n\t\tif (this.state !== 'streaming') return false\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\treturn recordMatchesScopes(collection, { ...(storedRecord ?? {}), id: recordId }, scopes)\n\t}\n\n\t/**\n\t * A stable key for this session's download scope. Presence (awareness) is only\n\t * relayed between sessions that share exactly the same key, so it never crosses a\n\t * tenant boundary. Unscoped sessions share the key `\"*\"`.\n\t */\n\t/** This session's download scope, or undefined when it is unscoped. */\n\tgetDownlinkScopes(): ScopeMap | undefined {\n\t\treturn this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t}\n\n\tgetScopePartitionKey(): string {\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\treturn scopes ? stableStringify(normalizeScopeMap(scopes)) : '*'\n\t}\n\n\t/**\n\t * Get the transport for this session.\n\t * Used by the awareness relay to send messages to this client.\n\t */\n\tgetTransport(): ServerTransport {\n\t\treturn this.transport\n\t}\n\n\t// --- Private protocol handlers ---\n\n\tprivate messageChain: Promise<void> = Promise.resolve()\n\n\t/** Send to the client when the transport is still connected; no-op otherwise. */\n\tprivate sendToClient(message: SyncMessage): boolean {\n\t\tif (!this.transport.isConnected()) {\n\t\t\treturn false\n\t\t}\n\t\ttry {\n\t\t\tthis.transport.send(message)\n\t\t\tthis.lastClientSendAtMs = Date.now()\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tprivate enqueueMessage(message: SyncMessage): void {\n\t\tif (message.type === 'handshake' && !this.handshakeReceived) {\n\t\t\t// The deadline covers the handshake's arrival, not its (possibly slow) auth.\n\t\t\tthis.handshakeReceived = true\n\t\t\tif (this.handshakeTimer !== null) {\n\t\t\t\tclearTimeout(this.handshakeTimer)\n\t\t\t\tthis.handshakeTimer = null\n\t\t\t}\n\t\t}\n\t\tthis.messageChain = this.messageChain\n\t\t\t.then(() => this.handleMessageAsync(message))\n\t\t\t.catch((error) => this.handleMessageFailure(error))\n\t}\n\n\tprivate async handleMessageAsync(message: SyncMessage): Promise<void> {\n\t\tif (this.state === 'closed') return\n\t\t// Nothing but a handshake is accepted until a handshake has been accepted (and,\n\t\t// with auth configured, authenticated). Operations, acknowledgments and every\n\t\t// side channel from a session that skipped it are refused and the connection is\n\t\t// closed, so an unauthenticated peer can neither write nor reach other sessions.\n\t\tif (message.type !== 'handshake' && this.state !== 'syncing' && this.state !== 'streaming') {\n\t\t\tthis.sendError(\n\t\t\t\t'HANDSHAKE_REQUIRED',\n\t\t\t\t`Received \"${message.type}\" before a successful handshake. Send a handshake first.`,\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\tthis.close('handshake required')\n\t\t\treturn\n\t\t}\n\t\tswitch (message.type) {\n\t\t\tcase 'handshake':\n\t\t\t\tawait this.handleHandshake(message)\n\t\t\t\tbreak\n\t\t\tcase 'operation-batch':\n\t\t\t\tawait this.handleOperationBatch(message)\n\t\t\t\tbreak\n\t\t\tcase 'acknowledgment':\n\t\t\t\tthis.pendingRelays.delete(message.acknowledgedMessageId)\n\t\t\t\tif (typeof message.nodeToken === 'string') {\n\t\t\t\t\tawait this.confirmNodeClaim(message.nodeToken)\n\t\t\t\t}\n\t\t\t\tif (message.deliverySequence !== undefined) {\n\t\t\t\t\t// Advance the confirmed watermark (a retransmission rewinds to it). It never\n\t\t\t\t\t// passes the send cursor: a client cannot acknowledge what was not sent.\n\t\t\t\t\tthis.noteDeliveryAcked(message.deliverySequence)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\tcase 'heartbeat':\n\t\t\t\t// A client liveness probe needs no answer: receiving it is the point.\n\t\t\t\tbreak\n\t\t\tcase 'awareness-update':\n\t\t\t\tthis.handleAwarenessUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'yjs-doc-update':\n\t\t\t\tawait this.handleYjsDocUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-request':\n\t\t\t\t// Every request costs access checks and possibly a central-store read, so it\n\t\t\t\t// is rate-limited (RT-17), on its own budget: a large blob is one request per\n\t\t\t\t// chunk and must not starve (or be starved by) operation sync (RT-24). Over\n\t\t\t\t// budget the answer is a retriable \"throttled\", never \"not held\", so the\n\t\t\t\t// client backs off and retries instead of failing the transfer.\n\t\t\t\tif (!this.blobRateLimiter.allow(1)) {\n\t\t\t\t\tthis.rateLimitedBlobRequests += 1\n\t\t\t\t\tthis.sendToClient({\n\t\t\t\t\t\ttype: 'blob-chunk-response',\n\t\t\t\t\t\tmessageId: `blob-resp-${message.requestId}`,\n\t\t\t\t\t\trequestId: message.requestId,\n\t\t\t\t\t\tbytes: null,\n\t\t\t\t\t\tthrottled: true,\n\t\t\t\t\t\tretryAfterMs: this.blobRateLimiter.retryAfterMs(),\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tthis.onBlobChunkRequest?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-response':\n\t\t\t\tthis.onBlobChunkResponse?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-push':\n\t\t\t\tawait this.handleBlobChunkPush(message)\n\t\t\t\tbreak\n\t\t\tcase 'encryption-key-request':\n\t\t\tcase 'encryption-key-put':\n\t\t\t\tawait this.handleEncryptionKeyMessage(message)\n\t\t\t\tbreak\n\t\t\tcase 'encryption-key-response':\n\t\t\t\t// Server -> client only.\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * The owner of this session's encryption key records (ENC-1), or null when it may\n\t * hold none: the authenticated user, or on a server without auth the one shared\n\t * anonymous owner. An anonymous principal of a mixed provider has no stable\n\t * identity, so it holds no keys.\n\t */\n\tgetEncryptionKeyOwner(): string | null {\n\t\tif (this.state !== 'syncing' && this.state !== 'streaming') return null\n\t\tif (!this.auth || this.auth instanceof NoAuthProvider) return ANONYMOUS_KEY_OWNER\n\t\tif (!this.principal || this.principal.anonymous === true) return null\n\t\treturn userKeyOwner(this.principal.userId)\n\t}\n\n\t/** Push a key record another session of the same owner wrote (rotation, new passphrase). */\n\tpushEncryptionKeyRecord(keyring: string, record: WrappedKeyRecord): void {\n\t\tif (this.state !== 'syncing' && this.state !== 'streaming') return\n\t\tthis.sendToClient({\n\t\t\ttype: 'encryption-key-response',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tkeyring,\n\t\t\tstatus: 'ok',\n\t\t\trecord,\n\t\t})\n\t}\n\n\tprivate async handleEncryptionKeyMessage(\n\t\tmessage: EncryptionKeyRequestMessage | EncryptionKeyPutMessage,\n\t): Promise<void> {\n\t\tconst refuse = (status: 'unsupported' | 'throttled', text: string): void => {\n\t\t\tthis.sendToClient({\n\t\t\t\ttype: 'encryption-key-response',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\trequestId: message.requestId,\n\t\t\t\tkeyring: message.keyring,\n\t\t\t\tstatus,\n\t\t\t\trecord: null,\n\t\t\t\tmessage: text,\n\t\t\t})\n\t\t}\n\t\tif (!this.encryptionKeys) {\n\t\t\trefuse('unsupported', 'This sync server does not serve encryption keys.')\n\t\t\treturn\n\t\t}\n\t\tif (!this.keyRateLimiter.allow(1)) {\n\t\t\trefuse('throttled', 'Too many encryption key requests; retry later.')\n\t\t\treturn\n\t\t}\n\t\tconst owner = this.getEncryptionKeyOwner()\n\t\tconst outcome = await this.encryptionKeys.handle(owner, message)\n\t\tif (this.state === 'closed') return\n\t\tthis.sendToClient(outcome.response)\n\t\tif (outcome.written && owner !== null) {\n\t\t\tthis.onEncryptionKeyWritten?.(this.sessionId, owner, message.keyring, outcome.written)\n\t\t}\n\t}\n\n\t/**\n\t * Persist a client-uploaded blob chunk (or manifest) centrally. The bytes are\n\t * verified to hash to the declared hash before storing, so a corrupt or\n\t * mislabeled upload is rejected rather than served later as trusted content.\n\t */\n\tprivate async handleBlobChunkPush(message: BlobChunkPushMessage): Promise<void> {\n\t\t// Without central persistence a push is still accepted as proof of possession\n\t\t// (RT-23): the bytes are verified and the pusher recorded as an owner, then\n\t\t// dropped. Without either, there is nothing to do with the bytes.\n\t\tif (!this.persistBlobChunk && !this.blobAccess) {\n\t\t\treturn\n\t\t}\n\t\tconst bytes = decodeBlobChunkBytes(message.bytes)\n\t\t// Bound what one session can make the server persist: a per-chunk size cap and a\n\t\t// per-session byte quota, so a client cannot fill the operator's disk.\n\t\tif (bytes.byteLength > this.maxBlobChunkBytes) {\n\t\t\tthis.sendError(\n\t\t\t\t'BLOB_CHUNK_TOO_LARGE',\n\t\t\t\t`Blob chunk ${message.hash} is ${String(bytes.byteLength)} bytes; the limit is ${String(this.maxBlobChunkBytes)}.`,\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tif (this.blobBytesPushed + bytes.byteLength > this.maxBlobBytesPerSession) {\n\t\t\tthis.sendError(\n\t\t\t\t'BLOB_QUOTA_EXCEEDED',\n\t\t\t\t`This session exceeded its blob upload quota of ${String(this.maxBlobBytesPerSession)} bytes.`,\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tconst actual = await hashBlob(bytes)\n\t\tif (actual !== message.hash) {\n\t\t\t// Reject a mismatched upload rather than persisting untrusted bytes.\n\t\t\treturn\n\t\t}\n\t\tconst owner = this.getBlobOwnerKey()\n\t\tconst scopes = this.referenceScopes()\n\t\t// A manifest may only list chunks the pusher may reference itself (RT-11), so a\n\t\t// crafted manifest cannot make another tenant's chunk reachable.\n\t\tif (\n\t\t\tthis.blobAccess &&\n\t\t\tscopes !== undefined &&\n\t\t\t!(await this.blobAccess.authorizeManifestPush(bytes, scopes, owner))\n\t\t) {\n\t\t\tthis.sendError(\n\t\t\t\t'BLOB_REFERENCE_FORBIDDEN',\n\t\t\t\t`Blob manifest ${message.hash} lists content this session cannot read and has not uploaded.`,\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tthis.blobBytesPushed += bytes.byteLength\n\t\tif (this.persistBlobChunk) {\n\t\t\tawait this.persistBlobChunk(message.hash, bytes)\n\t\t}\n\t\t// Pushing the bytes proves possession: the session may reference this hash.\n\t\tawait this.blobAccess?.recordPush(message.hash, bytes, owner)\n\t}\n\n\t/**\n\t * Claim (or re-claim) a node id for an anonymous device (RT-12, RT-21).\n\t *\n\t * A device presenting a token holds the node when the claim is (or can become)\n\t * `kora:anon-node:<hash(token)>`: its confirmed claim, a fresh claim, or its own\n\t * provisional claim, which presenting the token confirms.\n\t *\n\t * A device presenting no token gets a fresh token and a PROVISIONAL claim, which it\n\t * confirms by acknowledging the response with the token once saved (or by\n\t * presenting it next time). Until then the claim may be re-issued to a device that\n\t * again presents no token (the response was lost in transit), but only while no\n\t * session is connected as that node and before the claim expires. Legacy claims\n\t * (expired provisional ones, and nodes of the pre-release shared anonymous owner)\n\t * are re-issued only with `allowLegacyAnonymousClaims`, with a deprecation warning.\n\t */\n\tprivate async claimAnonymousNode(\n\t\tnodeId: string,\n\t\tpresentedToken: string | null,\n\t): Promise<AnonymousClaimOutcome> {\n\t\tconst store = this.store\n\t\tif (!store.claimNode) return { ok: false }\n\t\tif (presentedToken !== null) {\n\t\t\tconst hash = await nodeTokenHash(presentedToken)\n\t\t\tconst confirmed = `${ANONYMOUS_NODE_OWNER_PREFIX}${hash}`\n\t\t\tconst base = { deviceKey: confirmed, issuedToken: null, pending: null }\n\t\t\tif (await store.claimNode(nodeId, confirmed)) return { ok: true, owner: confirmed, ...base }\n\t\t\tconst current = (await store.getNodeClaimOwner?.(nodeId)) ?? null\n\t\t\tconst pending = parsePendingOwner(current)\n\t\t\tif (\n\t\t\t\tcurrent !== null &&\n\t\t\t\tpending?.tokenHash === hash &&\n\t\t\t\t(await store.replaceNodeClaim?.(nodeId, current, confirmed)) === true\n\t\t\t) {\n\t\t\t\treturn { ok: true, owner: confirmed, ...base }\n\t\t\t}\n\t\t\treturn { ok: false }\n\t\t}\n\n\t\tconst token = generateNodeToken()\n\t\tconst hash = await nodeTokenHash(token)\n\t\tconst confirmedOwner = `${ANONYMOUS_NODE_OWNER_PREFIX}${hash}`\n\t\tconst owner = pendingOwner(hash, Date.now() + this.anonymousClaimTtlMs)\n\t\tconst issued = {\n\t\t\tok: true as const,\n\t\t\towner,\n\t\t\tdeviceKey: confirmedOwner,\n\t\t\tissuedToken: token,\n\t\t\tpending: { owner, token, confirmedOwner },\n\t\t}\n\t\tif (await store.claimNode(nodeId, owner)) return issued\n\t\tif (!store.getNodeClaimOwner || !store.replaceNodeClaim) return { ok: false }\n\t\tconst current = await store.getNodeClaimOwner(nodeId)\n\t\tif (current === null) {\n\t\t\t// History with no claim row: written before node claims existed (a database a\n\t\t\t// beta.12 or older server wrote; RT-91). Such an anonymous device is a legacy\n\t\t\t// anonymous claim exactly like the shared `kora:anonymous` owner below: adopted\n\t\t\t// only with allowLegacyAnonymousClaims, provisionally, with a token for clients\n\t\t\t// that can keep one. The release and the claim are separate steps, so of two\n\t\t\t// concurrent claimants one wins and the other is refused (and rotates).\n\t\t\tif (!this.allowLegacyAnonymousClaims || !store.releaseNodeClaim) return { ok: false }\n\t\t\tif (this.isNodeLive?.(nodeId, this.sessionId) === true) return { ok: false }\n\t\t\tif (!(await store.releaseNodeClaim(nodeId))) return { ok: false }\n\t\t\tif (!(await store.claimNode(nodeId, owner))) return { ok: false }\n\t\t\tthis.warnLegacyAnonymousClaim(nodeId)\n\t\t\treturn issued\n\t\t}\n\t\tconst pending = parsePendingOwner(current)\n\t\tlet legacy = false\n\t\tif (pending) {\n\t\t\t// Never take a provisional claim away from a device that is connected now.\n\t\t\tif (this.isNodeLive?.(nodeId, this.sessionId) === true) return { ok: false }\n\t\t\tif (pending.expiresAtMs <= Date.now()) {\n\t\t\t\tif (!this.allowLegacyAnonymousClaims) return { ok: false }\n\t\t\t\tlegacy = true\n\t\t\t}\n\t\t} else if (current === ANONYMOUS_NODE_OWNER) {\n\t\t\tif (!this.allowLegacyAnonymousClaims) return { ok: false }\n\t\t\tlegacy = true\n\t\t} else {\n\t\t\treturn { ok: false }\n\t\t}\n\t\tif (!(await store.replaceNodeClaim(nodeId, current, owner))) return { ok: false }\n\t\tif (legacy) this.warnLegacyAnonymousClaim(nodeId)\n\t\treturn issued\n\t}\n\n\t/** The deprecation warning for an anonymous device adopted under a legacy claim (RT-21, RT-91). */\n\tprivate warnLegacyAnonymousClaim(nodeId: string): void {\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'warn',\n\t\t\tevent: 'session.legacy_anonymous_claim',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId,\n\t\t\tdetails: {\n\t\t\t\tmessage:\n\t\t\t\t\t'An anonymous device re-claimed a node id under a legacy claim (no confirmed node token, or history from before node claims). Upgrade the client; allowLegacyAnonymousClaims will default to false in the next release.',\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * The device proved it saved the node token issued by this handshake: make the\n\t * provisional claim permanent (RT-21). A mismatched token is ignored.\n\t */\n\tprivate async confirmNodeClaim(token: string): Promise<void> {\n\t\tconst pending = this.pendingNodeClaim\n\t\tif (!pending || token !== pending.token || !this.clientNodeId) return\n\t\tthis.pendingNodeClaim = null\n\t\tawait this.store.replaceNodeClaim?.(this.clientNodeId, pending.owner, pending.confirmedOwner)\n\t}\n\n\t/**\n\t * The download scope references are authorized against (RT-11, RT-13), or\n\t * undefined when they are not checked: without a real auth provider there is no\n\t * tenant boundary to protect.\n\t */\n\tprivate referenceScopes(): ScopeMap | undefined {\n\t\tif (!this.auth || this.auth instanceof NoAuthProvider) return undefined\n\t\tif (!this.principal) return {}\n\t\treturn this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t}\n\n\t/**\n\t * Stable blob-ownership key of this session's principal: the user id, or for an\n\t * anonymous device its node-claim owner (never shared by two anonymous devices).\n\t */\n\tgetBlobOwnerKey(): string {\n\t\tif (this.principal?.anonymous === true) {\n\t\t\treturn this.nodeOwnerKey ?? `kora:node:${this.clientNodeId ?? this.sessionId}`\n\t\t}\n\t\treturn this.principal?.userId ?? `kora:node:${this.clientNodeId ?? this.sessionId}`\n\t}\n\n\t/**\n\t * Partition key for peer-to-peer blob forwarding. Sessions with the same download\n\t * scope share a tenant view, except anonymous devices: every anonymous session has\n\t * the same grant but they are unrelated people, so each is its own partition.\n\t */\n\tgetBlobPartitionKey(): string {\n\t\tconst key = this.getScopePartitionKey()\n\t\treturn this.principal?.anonymous === true ? `${this.getBlobOwnerKey()}|${key}` : key\n\t}\n\n\t/** Authorize foreign-key targets and blob references of an untrusted write. */\n\tprivate async authorizeReferences(op: Operation): Promise<UplinkAuthorizationResult> {\n\t\tconst scopes = this.referenceScopes()\n\t\tconst schema = this.store.getSchema()\n\t\tif (scopes === undefined || !schema || !operationHasReferences(op, schema)) {\n\t\t\treturn { allowed: true }\n\t\t}\n\t\tconst stored = (await this.lookupRecordFields(op.collection, op.recordId)) ?? null\n\t\treturn authorizeOperationReferences(op, stored, {\n\t\t\tschema,\n\t\t\tdownlinkScopes: scopes,\n\t\t\tuplinkScopes: this.uplinkScopes(),\n\t\t\treadRow: async (collection, recordId) =>\n\t\t\t\t(await this.lookupRecordFields(collection, recordId)) ?? null,\n\t\t\t...(this.blobAccess ? { blobs: this.blobAccess } : {}),\n\t\t\tblobOwner: this.getBlobOwnerKey(),\n\t\t})\n\t}\n\n\tprivate handleMessageFailure(error: unknown): void {\n\t\tconst reason = error instanceof Error ? error.message : 'Message handling failed'\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'error',\n\t\t\tevent: 'session.message_failed',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId: this.clientNodeId ?? undefined,\n\t\t\terror: reason,\n\t\t\tdetails: {\n\t\t\t\tstate: this.state,\n\t\t\t\terrorName: error instanceof Error ? error.name : typeof error,\n\t\t\t},\n\t\t})\n\t\tthis.sendError('SYNC_ERROR', reason, true)\n\t\tthis.close(reason)\n\t}\n\n\tprivate async handleHandshake(msg: HandshakeMessage): Promise<void> {\n\t\t// Only accept handshake in 'connected' state (prevent duplicate handshakes)\n\t\tif (this.state !== 'connected') {\n\t\t\tthis.sendError('DUPLICATE_HANDSHAKE', 'Handshake already completed', false)\n\t\t\treturn\n\t\t}\n\n\t\tthis.clientNodeId = msg.nodeId\n\t\tthis.scopeExitPolicy = msg.scopeExitPolicy ?? 'retain'\n\t\tthis.sequenceReservation = msg.sequenceReservation === true\n\t\tthis.clientProtocolVersion = declaredProtocolVersion(msg.protocolVersion)\n\n\t\t// Node ids in the `kora:` namespace belong to Kora itself (scope-entry\n\t\t// operations use `kora:scope-entry`, RT-19); no device may use one.\n\t\tif (typeof msg.nodeId !== 'string' || msg.nodeId.startsWith(RESERVED_PRINCIPAL_PREFIX)) {\n\t\t\tthis.sendError(\n\t\t\t\t'INVALID_NODE_ID',\n\t\t\t\t`Node id \"${String(msg.nodeId)}\" is in the reserved \"${RESERVED_PRINCIPAL_PREFIX}\" namespace. Use a generated device node id.`,\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\tthis.close('reserved node id')\n\t\t\treturn\n\t\t}\n\t\tif (!isStorableIdentifier(msg.nodeId)) {\n\t\t\tthis.sendError(\n\t\t\t\t'INVALID_NODE_ID',\n\t\t\t\t'The node id holds U+0000 or an unpaired UTF-16 surrogate. Use a generated device node id.',\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\tthis.close('malformed node id')\n\t\t\treturn\n\t\t}\n\t\t// The server's own node ids, current and legacy (published in the handshake's\n\t\t// `authoritativeNodeIds`), are never a device's: a device presenting one would\n\t\t// author `merge('server-authoritative')` writes as the server (RT-61).\n\t\tif (this.isServerAuthorNodeId(msg.nodeId)) {\n\t\t\tthis.sendError(\n\t\t\t\t'INVALID_NODE_ID',\n\t\t\t\t`Node id \"${msg.nodeId}\" is a server node id (an authoritative node of this deployment). Use a generated device node id.`,\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\tthis.close('server node id')\n\t\t\treturn\n\t\t}\n\n\t\t// Authenticate if provider is configured\n\t\tif (this.auth) {\n\t\t\tconst token = msg.authToken ?? ''\n\t\t\tconst context = await this.auth.authenticate(token)\n\t\t\tif (!context) {\n\t\t\t\tthis.sendError('AUTH_FAILED', 'Authentication failed', false)\n\t\t\t\tthis.close('authentication failed')\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// The `kora:` namespace belongs to principals Kora synthesizes (anonymous node\n\t\t\t// owners). A provider issuing such a user id could collide with them (RT-12).\n\t\t\tif (context.anonymous !== true && context.userId.startsWith(RESERVED_PRINCIPAL_PREFIX)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'AUTH_FAILED',\n\t\t\t\t\t`The auth provider returned the user id \"${context.userId}\", which is in the reserved \"${RESERVED_PRINCIPAL_PREFIX}\" namespace. Issue user ids without that prefix.`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tthis.close('reserved principal id')\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Bind the device node id to this principal. A node id another user already\n\t\t\t// claimed is refused, so nobody can upload operations as someone else's device.\n\t\t\t// Anonymous principals get a fresh userId per connection, so their claim is\n\t\t\t// keyed by a per-device secret instead (RT-12): the server issues a node token\n\t\t\t// at the first claim, the client stores it next to its node id, and only a\n\t\t\t// handshake presenting it may use the node again. NoAuthProvider has no\n\t\t\t// identity at all.\n\t\t\tif (this.store.claimNode && !(this.auth instanceof NoAuthProvider)) {\n\t\t\t\tlet claimed: boolean\n\t\t\t\tif (context.anonymous === true) {\n\t\t\t\t\tconst presented =\n\t\t\t\t\t\ttypeof msg.nodeToken === 'string' &&\n\t\t\t\t\t\tmsg.nodeToken.length > 0 &&\n\t\t\t\t\t\tmsg.nodeToken.length <= MAX_NODE_TOKEN_LENGTH\n\t\t\t\t\t\t\t? msg.nodeToken\n\t\t\t\t\t\t\t: null\n\t\t\t\t\tconst outcome = await this.claimAnonymousNode(msg.nodeId, presented)\n\t\t\t\t\tclaimed = outcome.ok\n\t\t\t\t\tif (outcome.ok) {\n\t\t\t\t\t\tthis.nodeOwnerKey = outcome.deviceKey\n\t\t\t\t\t\tthis.issuedNodeToken = outcome.issuedToken\n\t\t\t\t\t\tthis.pendingNodeClaim = outcome.pending\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.nodeOwnerKey = context.userId\n\t\t\t\t\tclaimed = await this.store.claimNode(msg.nodeId, context.userId)\n\t\t\t\t}\n\t\t\t\tif (!claimed) {\n\t\t\t\t\tthis.issuedNodeToken = null\n\t\t\t\t\tthis.sendError(\n\t\t\t\t\t\t'NODE_ID_CLAIMED',\n\t\t\t\t\t\t`Node id \"${msg.nodeId}\" belongs to another principal, or has operation history with no recorded owner (an administrator can release it with KoraSyncServer.releaseNodeClaim). Use a fresh node id per signed-in user.`,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t)\n\t\t\t\t\tthis.close('node id claimed by another user')\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\t// A revocation that landed while this handshake was authenticating applies now.\n\t\t\tif (this.pendingRevocations.some((filter) => revocationMatches(context, filter))) {\n\t\t\t\tthis.pendingRevocations.length = 0\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'AUTH_REVOKED',\n\t\t\t\t\t'The credential for this sync session was revoked. Refresh it and reconnect.',\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tthis.close('credential revoked')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.pendingRevocations.length = 0\n\t\t\t// The session must not outlive the credential that opened it (AUTH-11).\n\t\t\tif (!this.armExpiryTimer(context.expiresAt)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'AUTH_EXPIRED',\n\t\t\t\t\t'The credential presented at handshake has expired. Refresh it and reconnect.',\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tthis.close('credential expired')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.principal = context\n\t\t\tthis.authContext = context\n\t\t\tthis.credential = token\n\t\t\tthis.state = 'authenticated'\n\t\t}\n\n\t\tconst resolution = this.computeSessionScopes(this.authContext, msg.syncScope)\n\t\tif (!resolution.ok) {\n\t\t\tthis.sendError(resolution.code, resolution.message, false)\n\t\t\tthis.close(resolution.reason)\n\t\t\treturn\n\t\t}\n\t\tthis.handshakeScope = msg.syncScope\n\t\tconst resolvedDownlinkScopes = resolution.downlink\n\t\tconst resolvedUplinkScopes = resolution.uplink\n\t\tconst authenticated = resolution.authenticated\n\t\tconst downlinkAuthScopes = resolution.downlinkAuthScopes\n\n\t\tif (resolvedDownlinkScopes || resolvedUplinkScopes) {\n\t\t\tif (this.authContext) {\n\t\t\t\tthis.authContext = {\n\t\t\t\t\t...this.authContext,\n\t\t\t\t\tscopes: resolvedDownlinkScopes,\n\t\t\t\t\tdownlinkScopes: resolvedDownlinkScopes,\n\t\t\t\t\tuplinkScopes: resolvedUplinkScopes,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.authContext = {\n\t\t\t\t\tuserId: msg.nodeId,\n\t\t\t\t\tscopes: resolvedDownlinkScopes,\n\t\t\t\t\tdownlinkScopes: resolvedDownlinkScopes,\n\t\t\t\t\tuplinkScopes: resolvedUplinkScopes,\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.authContext) {\n\t\t\t// The grant resolved to \"unscoped\" (RT-89: a claims-only grant on a schemaless\n\t\t\t// server). The provider's raw grant must not stay on the context: it names no\n\t\t\t// collection, so the upload and delivery checks, which read the context, would\n\t\t\t// refuse every operation the handshake just accepted.\n\t\t\tconst {\n\t\t\t\tscopes: _scopes,\n\t\t\t\tdownlinkScopes: _down,\n\t\t\t\tuplinkScopes: _up,\n\t\t\t\t...rest\n\t\t\t} = this.authContext\n\t\t\tthis.authContext = rest\n\t\t}\n\n\t\t// Judge the provider's own grant: with `authenticated`, the resolved map is never\n\t\t// empty-handed, but a provider that granted nothing still shares every unscoped\n\t\t// collection across tenants.\n\t\twarnIfMultiTenantWithoutScopes(\n\t\t\tthis.auth,\n\t\t\tauthenticated ? downlinkAuthScopes : resolvedDownlinkScopes,\n\t\t\tthis.store.getSchema(),\n\t\t)\n\n\t\tif (msg.syncQueries && msg.syncQueries.length > 0) {\n\t\t\tthis.syncQuerySubsets = dedupeQuerySubsets(msg.syncQueries)\n\t\t} else {\n\t\t\tthis.syncQuerySubsets = []\n\t\t}\n\n\t\tthis.resumeDeltaCursor = msg.deltaCursor ? decodeDeltaCursor(msg.deltaCursor) : null\n\t\tthis.clientDeliveryWatermark = msg.lastDeliverySequence ?? null\n\t\t// A delivery watermark is valid only for the exact server-visible view that\n\t\t// earned it. `lastDeliverySequence` belongs to the scope the client REQUESTED.\n\t\t// When the server resolves a different scope (server-auth scopes, promotions,\n\t\t// invite acceptance), it resumes from the watermark the client reports for the\n\t\t// accepted scope it last streamed under, if that scope has the same canonical key\n\t\t// as the one resolved now (SYNC-11). Otherwise the resolved view is new to the\n\t\t// client (for example a widened grant): a full scoped backfill from 0, never a\n\t\t// cursor that may have advanced over operations hidden from its earlier view.\n\t\tif (\n\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t!sameScopeMap(msg.syncScope, this.authContext?.downlinkScopes)\n\t\t) {\n\t\t\tconst acceptedWatermark = msg.acceptedScopeWatermark\n\t\t\tconst resumable =\n\t\t\t\ttypeof msg.acceptedScopeKey === 'string' &&\n\t\t\t\ttypeof acceptedWatermark === 'number' &&\n\t\t\t\tNumber.isSafeInteger(acceptedWatermark) &&\n\t\t\t\tacceptedWatermark >= 0 &&\n\t\t\t\tmsg.acceptedScopeKey === scopeViewKey(this.authContext?.downlinkScopes)\n\t\t\tthis.clientDeliveryWatermark = resumable ? acceptedWatermark : 0\n\t\t}\n\n\t\t// Only read the server's delivery frontier when the client actually uses the\n\t\t// watermark. If the client's reported watermark exceeds that frontier, the server's\n\t\t// log was rolled back (for example a backup restore reset the sequence), so resync\n\t\t// that client from the beginning rather than let it sit above a frontier that no\n\t\t// longer exists; the server advertises its max so the client resets to match.\n\t\tconst clientUsesWatermark = this.clientDeliveryWatermark !== null\n\t\tlet serverMaxDelivery = 0\n\t\tif (clientUsesWatermark) {\n\t\t\tserverMaxDelivery = await this.store.getMaxDeliverySequence()\n\t\t\tif (\n\t\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t\tthis.clientDeliveryWatermark > serverMaxDelivery\n\t\t\t) {\n\t\t\t\tthis.clientDeliveryWatermark = 0\n\t\t\t}\n\t\t}\n\n\t\t// Report the format the transport actually frames with, never one the client merely\n\t\t// offered (SYNC-9). The serializer is shared by every session on the server, so a\n\t\t// per-session switch would flip the wire format of every other session too.\n\t\tconst selectedWireFormat = framingWireFormat(this.serializer)\n\n\t\tif (!isClientSchemaVersionSupported(msg.schemaVersion, this.supportedSchemaVersions)) {\n\t\t\tconst { min, max } = this.supportedSchemaVersions\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:schema-mismatch',\n\t\t\t\tclientSchemaVersion: msg.schemaVersion,\n\t\t\t\tserverSchemaVersion: this.schemaVersion,\n\t\t\t\tsupportedMin: min,\n\t\t\t\tsupportedMax: max,\n\t\t\t\treason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t})\n\t\t\tconst response: SyncMessage = {\n\t\t\t\ttype: 'handshake-response',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tnodeId: this.store.getNodeId(),\n\t\t\t\tversionVector: {},\n\t\t\t\tschemaVersion: this.schemaVersion,\n\t\t\t\taccepted: false,\n\t\t\t\trejectReason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t\tsupportedSchemaMin: min,\n\t\t\t\tsupportedSchemaMax: max,\n\t\t\t\tserverTime: Date.now(),\n\t\t\t}\n\t\t\tthis.sendToClient(response)\n\t\t\tthis.close('schema version mismatch')\n\t\t\treturn\n\t\t}\n\n\t\t// The version vector as committed in the store, shared by every server instance\n\t\t// (SRV-4), not this instance's cache.\n\t\tconst serverVector = await this.readServerVector()\n\t\tconst clientVector = wireToVersionVector(msg.versionVector)\n\t\t// A client that reports a delivery watermark gets the gap-free delivery stream,\n\t\t// streamed after the response (SRV-5: never collected whole). An older client gets\n\t\t// the version-vector delta, collected before answering. Both hold only in-scope\n\t\t// operations.\n\t\tconst deltaPlan =\n\t\t\tthis.clientDeliveryWatermark === null ? await this.collectDeltaOperations(clientVector) : []\n\n\t\t// Only reveal vector entries for the client's own node and the nodes whose in-scope\n\t\t// operations it is about to receive. The full vector would leak every device id and\n\t\t// write count across tenants, and echoing the nodes the client names in its own\n\t\t// vector would make the handshake a write-count oracle for any device id (RT-7).\n\t\t// The client merges these entries so the operations it receives are not counted\n\t\t// as its own pending uploads. A delivery-stream client's stream is not collected\n\t\t// in advance (SRV-5): an unscoped session may see every operation, so it gets the\n\t\t// whole vector; a scoped one gets the nodes a metadata pre-pass finds visible.\n\t\t// Clients of this release count pending from their own acks (RT-28) and would not\n\t\t// need the pre-pass, but beta.12 clients count every node ahead of this vector as\n\t\t// pending (and `kora compact` uses the persisted peer entries), so it stays. It\n\t\t// starts at the resumed watermark (SYNC-11), so a reconnect scans only new ops.\n\t\tconst visibleNodes = new Set<string>([msg.nodeId])\n\t\tfor (const op of deltaPlan) {\n\t\t\tvisibleNodes.add(op.nodeId)\n\t\t}\n\t\tconst unscoped = (this.authContext?.downlinkScopes ?? this.authContext?.scopes) === undefined\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tif (unscoped) {\n\t\t\t\tfor (const nodeId of serverVector.keys()) visibleNodes.add(nodeId)\n\t\t\t} else {\n\t\t\t\tfor (const nodeId of await this.collectVisibleNodeIds(this.clientDeliveryWatermark)) {\n\t\t\t\t\tvisibleNodes.add(nodeId)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst visibleServerVector = new Map(\n\t\t\t[...serverVector].filter(([nodeId]) => visibleNodes.has(nodeId)),\n\t\t)\n\t\t// The session's own node is ALWAYS advertised, 0 when the server holds nothing of\n\t\t// it (RT-45): a device must learn that the server lost its operations (restored\n\t\t// from an older backup) to upload them again. The entry is the highest sequence\n\t\t// the server has RESOLVED for the node (stored, validator-ignored, terminally\n\t\t// refused, or stored under another number; RT-43), so an operation the server\n\t\t// decided without storing is never read as lost and re-submitted at every\n\t\t// reconnect. It names only the client's own node, so it discloses nothing (RT-7).\n\t\tvisibleServerVector.set(\n\t\t\tmsg.nodeId,\n\t\t\tMath.max(serverVector.get(msg.nodeId) ?? 0, await this.resolvedThrough(msg.nodeId)),\n\t\t)\n\t\tconst heartbeat = msg.supportsHeartbeat === true && this.appHeartbeatIntervalMs > 0\n\n\t\t// Send handshake response with the visible version vector and accepted scope\n\t\tconst response: SyncMessage = {\n\t\t\ttype: 'handshake-response',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tnodeId: this.store.getNodeId(),\n\t\t\tversionVector: versionVectorToWire(visibleServerVector),\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\taccepted: true,\n\t\t\tselectedWireFormat,\n\t\t\tserverTime: Date.now(),\n\t\t\t// The server's highest delivery sequence, so a client whose persisted watermark\n\t\t\t// is ahead of it (server rolled back) can reset to a full resync. Sent only to\n\t\t\t// watermark-using clients.\n\t\t\t...(clientUsesWatermark ? { serverMaxDeliverySequence: serverMaxDelivery } : {}),\n\t\t\t// Advertise central blob storage so the client uploads the bytes behind\n\t\t\t// its blob fields, keeping them available after the author goes offline.\n\t\t\t...(this.persistBlobChunk ? { blobStorageEnabled: true } : {}),\n\t\t\t// Peer-relay mode: ask the client to push the bytes behind a blob reference\n\t\t\t// anyway, so the server can verify possession (and then drop them) before\n\t\t\t// accepting the reference (RT-23).\n\t\t\t...(!this.persistBlobChunk && this.blobAccess && this.referenceScopes() !== undefined\n\t\t\t\t? { blobPossessionProof: true }\n\t\t\t\t: {}),\n\t\t\t// Confirm the accepted scope so the client knows what data will be synced.\n\t\t\t// This may differ from what the client requested if auth scopes are narrower.\n\t\t\t...(this.authContext?.downlinkScopes\n\t\t\t\t? {\n\t\t\t\t\t\tacceptedScope: this.authContext.downlinkScopes,\n\t\t\t\t\t\tacceptedDownlinkScopes: this.authContext.downlinkScopes,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(this.authContext?.uplinkScopes\n\t\t\t\t? { acceptedUplinkScopes: this.authContext.uplinkScopes }\n\t\t\t\t: {}),\n\t\t\t...(this.issuedNodeToken !== null ? { nodeToken: this.issuedNodeToken } : {}),\n\t\t\t...(heartbeat ? { heartbeatIntervalMs: this.appHeartbeatIntervalMs } : {}),\n\t\t\tprotocolVersion: SYNC_PROTOCOL_VERSION,\n\t\t\tauthoritativeNodeIds: this.advertisedAuthoritativeNodeIds(),\n\t\t\t...this.advertisedRevocations(),\n\t\t}\n\t\tthis.issuedNodeToken = null\n\t\tthis.sendToClient(response)\n\n\t\tthis.emitter?.emit({ type: 'sync:connected', nodeId: msg.nodeId })\n\t\tif (this.clientProtocolVersion < SYNC_PROTOCOL_VERSION) this.warnLegacyProtocol(msg.nodeId)\n\n\t\t// The ingest rate limit follows the node across reconnects (SRV-6): the node id\n\t\t// is bound to this principal by now (claimed when auth is configured).\n\t\tif (this.rateLimiterFor) {\n\t\t\tconst principal =\n\t\t\t\tthis.principal &&\n\t\t\t\tthis.principal.anonymous !== true &&\n\t\t\t\t!(this.auth instanceof NoAuthProvider)\n\t\t\t\t\t? this.principal.userId\n\t\t\t\t\t: null\n\t\t\tthis.rateLimiter = this.rateLimiterFor(msg.nodeId, principal)\n\t\t}\n\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\t// Resuming from a non-zero watermark excludes the client's own operations (it\n\t\t\t// already holds its history); a full resync (watermark 0) includes those\n\t\t\t// committed so far, so it recovers everything.\n\t\t\tconst watermark = this.clientDeliveryWatermark\n\t\t\tthis.lastAckedDeliverySeq = watermark\n\t\t\tthis.lastSentDeliverySeq = watermark\n\t\t\tthis.highestSentDeliverySeq = watermark\n\t\t\tthis.ownOperationsIncludedThrough = watermark === 0 ? serverMaxDelivery : 0\n\t\t\tthis.lastDeliveryProgressAtMs = Date.now()\n\t\t\tthis.deliveryRewinds = 0\n\t\t\t// The stream runs on the delivery chain, so this session keeps processing the\n\t\t\t// client's acknowledgments and uploads while it streams (with backpressure).\n\t\t\tthis.state = 'streaming'\n\t\t\tthis.pushDeliveryStream('initial')\n\t\t} else {\n\t\t\tthis.state = 'syncing'\n\t\t\tthis.sendCollectedDelta(deltaPlan)\n\t\t\t// Transition to streaming after delta is sent\n\t\t\tif (this.state !== 'syncing') return\n\t\t\tthis.state = 'streaming'\n\t\t}\n\t\tthis.onReady?.(this.sessionId)\n\t\tif (heartbeat) this.startAppHeartbeat()\n\n\t\t// Redeliver any relays buffered while this client's node id was disconnected\n\t\t// (dropped just before a prior reconnect). relayOperations re-filters them by\n\t\t// this session's current scope and re-tracks them for acknowledgment.\n\t\tif (this.takeOrphanedRelays && this.clientNodeId) {\n\t\t\tconst buffered = this.takeOrphanedRelays(this.clientNodeId)\n\t\t\tif (buffered.length > 0) {\n\t\t\t\tthis.relayOperations(buffered)\n\t\t\t}\n\t\t}\n\t\t// A delivery-watermark client needs no explicit drain here: the initial stream\n\t\t// scans to the end of the log, and anything committed after its last scan is\n\t\t// above the send cursor, where the next relay wake-up or delivery poll sends it.\n\t}\n\n\t/**\n\t * The nodes whose operations after `fromDeliverySeq` this scoped session will\n\t * receive, for the handshake vector (RT-7). Scans the delivery log without holding\n\t * it (memory is O(nodes)), and judges each node only until one of its operations is\n\t * visible, so most operations cost one scope comparison and no record read.\n\t */\n\tprivate async collectVisibleNodeIds(fromDeliverySeq: number): Promise<Set<string>> {\n\t\tconst visible = new Set<string>()\n\t\t// With the candidate list, the scan stops as soon as every candidate is known\n\t\t// visible (typically after a few chunks); only nodes that never become visible\n\t\t// (other tenants' devices) make it read to the end.\n\t\tlet pending: Set<string> | null = null\n\t\tif (this.store.getNodeIdsAfterDelivery) {\n\t\t\ttry {\n\t\t\t\tpending = new Set(await this.store.getNodeIdsAfterDelivery(fromDeliverySeq))\n\t\t\t} catch {\n\t\t\t\tpending = null\n\t\t\t}\n\t\t}\n\t\tconst scanChunk = Math.max(this.batchSize, 1) * 20\n\t\tlet cursor = fromDeliverySeq\n\t\twhile (this.state !== 'closed' && (pending === null || pending.size > 0)) {\n\t\t\tconst chunk = await this.store.getOperationsAfterDelivery(cursor, scanChunk)\n\t\t\tconst last = chunk[chunk.length - 1]\n\t\t\tif (last === undefined) break\n\t\t\tfor (const delivered of chunk) {\n\t\t\t\tconst op = delivered.operation\n\t\t\t\tif (visible.has(op.nodeId)) continue\n\t\t\t\tif (await this.operationVisibleToClient(op, delivered.scopeSnapshot ?? null)) {\n\t\t\t\t\tvisible.add(op.nodeId)\n\t\t\t\t\tpending?.delete(op.nodeId)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcursor = last.deliverySequence\n\t\t\tif (chunk.length < scanChunk) break\n\t\t}\n\t\treturn visible\n\t}\n\n\t/**\n\t * The version vector as committed in the store (SRV-4). A store shared by several\n\t * instances reads it fresh; others serve their own (complete) vector.\n\t */\n\tprivate async readServerVector(): Promise<VersionVector> {\n\t\tif (this.store.readVersionVector) {\n\t\t\ttry {\n\t\t\t\treturn await this.store.readVersionVector()\n\t\t\t} catch (error) {\n\t\t\t\tthis.logger?.log({\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tlevel: 'warn',\n\t\t\t\t\tevent: 'session.version_vector_read_failed',\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn this.store.getVersionVector()\n\t}\n\n\t/**\n\t * Resolve this session's download and upload scopes from an auth context and the\n\t * scope the client asked for at handshake. Side-effect free, so revalidation can\n\t * recompute it and compare (RT-26). The legacy `scopes` contract remains shorthand\n\t * for both directions.\n\t */\n\tprivate computeSessionScopes(\n\t\tcontext: AuthContext | null,\n\t\thandshakeScope: HandshakeMessage['syncScope'],\n\t):\n\t\t| {\n\t\t\t\tok: true\n\t\t\t\tdownlink: ScopeMap | undefined\n\t\t\t\tuplink: ScopeMap | undefined\n\t\t\t\tdownlinkAuthScopes: ScopeMap | undefined\n\t\t\t\tauthenticated: boolean\n\t\t }\n\t\t| { ok: false; code: string; message: string; reason: string } {\n\t\tconst directionalScopesConfigured =\n\t\t\tcontext?.downlinkScopes !== undefined || context?.uplinkScopes !== undefined\n\t\tconst downlinkAuthScopes = directionalScopesConfigured\n\t\t\t? (context?.downlinkScopes ?? context?.scopes ?? {})\n\t\t\t: context?.scopes\n\t\tconst uplinkAuthScopes = directionalScopesConfigured\n\t\t\t? (context?.uplinkScopes ?? context?.scopes ?? {})\n\t\t\t: context?.scopes\n\t\t// A real auth provider that grants nothing for a schema-scoped collection is\n\t\t// refused, never handed the scope the client asked for (AUTH-1). A schemaless\n\t\t// server has no scoped collections to protect, so it keeps the provider's\n\t\t// (absent) grant as \"unscoped\" and the multi-tenant warning.\n\t\tconst authenticated =\n\t\t\tthis.auth !== null &&\n\t\t\t!(this.auth instanceof NoAuthProvider) &&\n\t\t\tthis.store.getSchema() !== null\n\t\tlet rawDownlink: ReturnType<typeof resolveSessionScopes>\n\t\tlet rawUplink: ReturnType<typeof resolveSessionScopes>\n\t\ttry {\n\t\t\trawDownlink = resolveSessionScopes(this.store.getSchema(), {\n\t\t\t\thandshakeScope,\n\t\t\t\tauthScopes: downlinkAuthScopes,\n\t\t\t\tauthenticated,\n\t\t\t\tonUnresolved: 'throw',\n\t\t\t})\n\t\t\t// A directional uplink grant goes through the same resolver as the downlink one\n\t\t\t// (RT-16): verified `$claims` are bound to the schema, an unresolved binding\n\t\t\t// denies the collection (fail closed; the session may still read), and the\n\t\t\t// handshake can only narrow it, exactly as for a non-directional grant.\n\t\t\trawUplink = directionalScopesConfigured\n\t\t\t\t? resolveSessionScopes(this.store.getSchema(), {\n\t\t\t\t\t\thandshakeScope,\n\t\t\t\t\t\tauthScopes: uplinkAuthScopes,\n\t\t\t\t\t\tauthenticated,\n\t\t\t\t\t\tonUnresolved: 'deny',\n\t\t\t\t\t})\n\t\t\t\t: rawDownlink\n\t\t} catch (error) {\n\t\t\tif (error instanceof InvalidScopePredicateError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: 'INVALID_SCOPE_PREDICATE',\n\t\t\t\t\tmessage: error.message,\n\t\t\t\t\treason: 'invalid scope predicate',\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!(error instanceof ScopeRequiredError)) throw error\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode: 'SCOPE_REQUIRED',\n\t\t\t\tmessage: error.message,\n\t\t\t\treason: 'sync scope required',\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tconst downlink = rawDownlink\n\t\t\t\t? normalizeScopeMap(rawDownlink)\n\t\t\t\t: directionalScopesConfigured\n\t\t\t\t\t? {}\n\t\t\t\t\t: undefined\n\t\t\tconst uplink = rawUplink\n\t\t\t\t? normalizeScopeMap(rawUplink)\n\t\t\t\t: directionalScopesConfigured\n\t\t\t\t\t? {}\n\t\t\t\t\t: undefined\n\t\t\treturn { ok: true, downlink, uplink, downlinkAuthScopes, authenticated }\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode:\n\t\t\t\t\terror instanceof InvalidScopePredicateError\n\t\t\t\t\t\t? 'INVALID_SCOPE_PREDICATE'\n\t\t\t\t\t\t: 'SCOPE_PREDICATE_LIMIT',\n\t\t\t\tmessage: error instanceof Error ? error.message : 'Invalid scope predicate',\n\t\t\t\treason: 'invalid scope predicate',\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async handleOperationBatch(msg: OperationBatchMessage): Promise<void> {\n\t\t// Refuse an oversized batch before decoding it or reading the store (RT-6). The\n\t\t// whole batch is refused and nothing is acknowledged, so a client that sent it\n\t\t// legitimately can split it and resubmit; no operation is lost.\n\t\tif (msg.operations.length > this.maxOpsPerBatch) {\n\t\t\tthis.rejectedBatches += 1\n\t\t\tthis.sendError(\n\t\t\t\t'BATCH_TOO_LARGE',\n\t\t\t\t`Operation batch \"${msg.messageId}\" holds ${String(msg.operations.length)} operations; the limit is ${String(this.maxOpsPerBatch)} per batch. Send smaller batches.`,\n\t\t\t\tfalse,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\t// Per-field versions and fold state are server-authored only (scope-entry\n\t\t// operations, RT-27, W7). A device never sends them; one that does would forge\n\t\t// field precedence on its peers, so they are dropped before anything else sees\n\t\t// the operation.\n\t\tconst operations = msg.operations.map((s) => {\n\t\t\tconst {\n\t\t\t\tfieldVersions: _forged,\n\t\t\t\tfoldState: _forgedFold,\n\t\t\t\t...op\n\t\t\t} = this.serializer.decodeOperation(s)\n\t\t\treturn op\n\t\t})\n\t\tconst applied: Operation[] = []\n\t\tlet acknowledgedThrough = 0\n\t\tlet canAdvanceAck = true\n\t\tlet uniqueOperations = 0\n\t\tlet duplicateOperations = 0\n\t\tlet rejectedOperations = 0\n\t\t// Which of the batch's ids the server already holds, read once per batch and\n\t\t// before any other per-operation check. A device re-uploading its history (the\n\t\t// one-time upgrade re-upload, or an op its sequence repair renumbered under the\n\t\t// same id) must get a duplicate ack, never a rejection from today's authorization\n\t\t// or validators for an operation the server already accepted (RT-31).\n\t\t//\n\t\t// Rate limiting (RT-6, RT-39): the lookup is charged once per batch\n\t\t// (BATCH_LOOKUP_RATE_COST; the batch size is already capped), and an operation\n\t\t// the lookup finds stored costs nothing more: acknowledging it writes nothing and\n\t\t// reads nothing else. Every other operation is charged before anything touches\n\t\t// the store for it. So a device's upgrade re-upload of thousands of stored\n\t\t// operations is not cut off by RATE_LIMIT, while lookups still cost per batch.\n\t\tlet stored: Map<string, StoredOperationKey> = new Map()\n\t\tlet resolved: Map<string, OperationResolution> = new Map()\n\t\tlet lookupCredit = 0\n\t\tif (operations.length > 0) {\n\t\t\tif (this.rateLimiter.allow(BATCH_LOOKUP_RATE_COST)) {\n\t\t\t\tlookupCredit = BATCH_LOOKUP_RATE_COST\n\t\t\t\t// Identifiers a store cannot hold are refused in the loop, never looked up (RT-65).\n\t\t\t\tconst lookupable = operations.filter((op) => operationIdentifiersStorable(op))\n\t\t\t\tstored = await this.findStoredOperations(lookupable)\n\t\t\t\tresolved = await this.findResolutions(lookupable, stored)\n\t\t\t} else {\n\t\t\t\tthis.rateLimitedOperations += operations.length\n\t\t\t\tthis.sendRateLimited()\n\t\t\t\tcanAdvanceAck = false\n\t\t\t}\n\t\t}\n\n\t\t// The author's own cascades / set-nulls of a delete in this batch (RT-69): the\n\t\t// server does not derive a second copy of an effect the author uploads itself.\n\t\tconst authoredCopies = this.indexAuthoredSideEffectCopies(operations)\n\t\tconst deferredEffects: DeferredSideEffect[] = []\n\t\tconst storedInBatch = new Set<string>()\n\n\t\tfor (const op of operations) {\n\t\t\tif (!canAdvanceAck) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// An identifier holding U+0000 or a lone surrogate cannot be stored or looked up\n\t\t\t// (Postgres refuses it). Refused terminally without touching the store, so it\n\t\t\t// never fails the session (RT-65); nothing is recorded under such an id.\n\t\t\tif (!operationIdentifiersStorable(op)) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\tINVALID_IDENTIFIER_CODE,\n\t\t\t\t\t`Operation \"${String(op.id)}\" has an identifier holding U+0000 or an unpaired UTF-16 surrogate. Identifiers must be well-formed strings.`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Already stored (found by the batch lookup): a duplicate ack, free of charge,\n\t\t\t// but only for the SAME operation (RT-77). The stored copy is loaded and compared\n\t\t\t// on every field its id covers; an upload that reuses a stored id with any other\n\t\t\t// content is refused (non-retriable, logged as tampering) with no effect at all.\n\t\t\tconst storedCopy = this.isStoredDuplicate(op, stored)\n\t\t\t\t? await this.loadStoredOperation(op, stored)\n\t\t\t\t: null\n\t\t\tif (storedCopy !== null) {\n\t\t\t\tconst schema = this.store.getSchema()\n\t\t\t\tif (\n\t\t\t\t\t!(await isSameOperationAsStored(op, storedCopy, schema)) &&\n\t\t\t\t\t!(op.nodeId !== this.clientNodeId && (await isRewrittenEcho(op, storedCopy, schema)))\n\t\t\t\t) {\n\t\t\t\t\tthis.refuseForgedDuplicate(op, storedCopy)\n\t\t\t\t\trejectedOperations += 1\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tawait this.noteStoredElsewhere(op, stored)\n\t\t\t\t// A delete sent again (the batch that stored it failed later, or was never\n\t\t\t\t// acknowledged): any referential effect still undone is derived (or deferred\n\t\t\t\t// to the author's copies in this batch) now, so an effect deferred in memory\n\t\t\t\t// by a failed batch is never lost (RT-73). Judged on the STORED delete only.\n\t\t\t\tif (storedCopy.type === 'delete') {\n\t\t\t\t\tapplied.push(\n\t\t\t\t\t\t...(await this.resumeStoredDeleteEffects(storedCopy, authoredCopies, deferredEffects)),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tstoredInBatch.add(op.id)\n\t\t\t\tduplicateOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Already resolved for this device without being stored (RT-43, RT-47): the\n\t\t\t// original answer again, free of charge, and never a second judgement. A refused\n\t\t\t// operation stays refused even when the device lost its rejection marker (a\n\t\t\t// restored copy): re-running authorization and validators against today's state\n\t\t\t// could apply a write the server refused. An ignored one is not handed to the\n\t\t\t// validator again (its out-of-band effect must not repeat).\n\t\t\tconst resolution = resolved.get(op.id)\n\t\t\tif (resolution) {\n\t\t\t\tif (resolution.outcome === 'refused') {\n\t\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\t\top,\n\t\t\t\t\t\tresolution.code ?? RESTRICTED_REJECTION_CODE,\n\t\t\t\t\t\tresolution.message ?? 'This operation was refused earlier.',\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t)\n\t\t\t\t\trejectedOperations += 1\n\t\t\t\t} else {\n\t\t\t\t\tduplicateOperations += 1\n\t\t\t\t}\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Charge the rate limiter before anything that touches the store (RT-6): a\n\t\t\t// refused operation (foreign node, out of scope) still costs a store read, so\n\t\t\t// it must count against the budget like an accepted one. The batch's lookup\n\t\t\t// unit pays for its first such operation, so a batch of N new operations costs\n\t\t\t// N, exactly as before, and a batch of stored duplicates costs one.\n\t\t\tif (lookupCredit > 0) {\n\t\t\t\tlookupCredit -= 1\n\t\t\t} else if (!this.rateLimiter.allow(1)) {\n\t\t\t\tthis.rateLimitedOperations += 1\n\t\t\t\tthis.sendRateLimited()\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// A session may only upload its own device's operations. A foreign nodeId\n\t\t\t// would let one peer advance another device's version-vector entry and make\n\t\t\t// that device skip uploading its real writes. The ack does not advance over a\n\t\t\t// foreign op: its sequence number is not in this client's sequence space.\n\t\t\tif (op.nodeId !== this.clientNodeId || op.timestamp.nodeId !== op.nodeId) {\n\t\t\t\t// A client may echo back another device's operation that the server itself\n\t\t\t\t// delivered (its delta is computed against the handshake-time vector). That\n\t\t\t\t// op is already stored under its id, so accepting it as a duplicate writes\n\t\t\t\t// nothing and cannot advance any vector: treat it exactly like a duplicate.\n\t\t\t\tif (await this.isStoredOperation(op, stored)) {\n\t\t\t\t\tduplicateOperations += 1\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\t'NODE_ID_MISMATCH',\n\t\t\t\t\t`Operation \"${op.id}\" claims node \"${op.nodeId}\" (timestamp node \"${op.timestamp.nodeId}\") but this session is node \"${String(this.clientNodeId)}\". A client may only upload operations it authored.`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// This device's own operation, already stored under its id (content-addressed,\n\t\t\t// so the same write): nothing to judge or write again. It was authorized and\n\t\t\t// validated when first accepted; re-judging it now could refuse a write the\n\t\t\t// server holds and make the device roll it back.\n\t\t\t// The (node, sequence) may differ from the stored one: the client's sequence\n\t\t\t// repair renumbers a legacy duplicate and keeps its id.\n\t\t\t// A custom store without the batch lookup is asked per op by (node, sequence).\n\t\t\tif (\n\t\t\t\tstored.get(op.id)?.nodeId === op.nodeId ||\n\t\t\t\t(!this.store.findStoredOperations && (await this.isStoredOperation(op, stored)))\n\t\t\t) {\n\t\t\t\tawait this.noteStoredElsewhere(op, stored)\n\t\t\t\tstoredInBatch.add(op.id)\n\t\t\t\tduplicateOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst authorization = await this.authorizeClientOperation(op)\n\t\t\tif (!authorization.allowed) {\n\t\t\t\tawait this.refuseTerminally(\n\t\t\t\t\top,\n\t\t\t\t\tauthorization.code,\n\t\t\t\t\tauthorization.code === 'SCOPE_VIOLATION'\n\t\t\t\t\t\t? `${authorization.message} Refresh scopes before creating or explicitly resubmitting an authorized operation.`\n\t\t\t\t\t\t: authorization.message,\n\t\t\t\t)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!isOperationTimestampValid(op)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'INVALID_TIMESTAMP',\n\t\t\t\t\t`Operation \"${op.id}\" timestamp is too far in the future`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// An oversized operation is refused on its own, terminally, and the ack moves\n\t\t\t// past it (RT-86): a session-level error would stop acknowledging the batch, and\n\t\t\t// the device would re-send it every session, so none of its later writes would\n\t\t\t// ever reach the server. The device records the refusal (sync:operation-rejected).\n\t\t\tconst sizeCheck = validateOperationSize(op, this.maxOperationBytes)\n\t\t\tif (!sizeCheck.valid) {\n\t\t\t\tawait this.refuseTerminally(\n\t\t\t\t\top,\n\t\t\t\t\tOPERATION_TOO_LARGE_CODE,\n\t\t\t\t\t`${sizeCheck.message ?? `Operation \"${op.id}\" is too large.`} Store large content as a blob, or raise maxOperationBytes on the server and the client together.`,\n\t\t\t\t)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Content-hash verification (CORE-1, protocol v2) runs on the operation exactly\n\t\t\t// as uploaded, BEFORE any schema transform (which rewrites data) and before any\n\t\t\t// validator or store sees it. Only plaintext version-2 ids are verified here: an\n\t\t\t// envelope's id covers the plaintext, which only the clients can check (they do,\n\t\t\t// after decryption), and a version-1 id never covered every field.\n\t\t\tconst integrity = await this.checkUploadIntegrity(op)\n\t\t\tif (integrity !== null) {\n\t\t\t\tif (integrity.code === INVALID_OPERATION_ID) this.invalidOperationIds += 1\n\t\t\t\tawait this.refuseTerminally(op, integrity.code, integrity.message)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Transforms at fold time (RT-84): the operation is stored exactly as uploaded\n\t\t\t// (plus the hash version the server verified, and a beta.12 clear made explicit,\n\t\t\t// both identical under its id), never as a transformed rewrite under its id.\n\t\t\t// Authorization, validators and constraint checks judge its view in the server\n\t\t\t// schema; every store folds that same view.\n\t\t\tconst storedOp = this.declareVerifiedHashVersion(op)\n\t\t\tconst view = this.schemaView(storedOp)\n\t\t\tif (!view.ok) {\n\t\t\t\tawait this.refuseTerminally(op, view.code, view.message)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst serverOp = view.op\n\n\t\t\t// Server-side adjudication of untrusted client operations. Runs after\n\t\t\t// the built-in guards and before materialization, so a rejected op never\n\t\t\t// enters the authoritative log and never relays to other clients.\n\t\t\tif (this.validateOperation && this.koraContext) {\n\t\t\t\tlet decision: Awaited<ReturnType<OperationValidator>>\n\t\t\t\ttry {\n\t\t\t\t\tdecision = await this.validateOperation(serverOp, {\n\t\t\t\t\t\tauth: this.authContext,\n\t\t\t\t\t\tkora: this.koraContext,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// A throwing validator must not crash ingestion or silently accept.\n\t\t\t\t\t// Treat it as a retriable rejection so the submitter can try again.\n\t\t\t\t\tconst message = error instanceof Error ? error.message : 'validator error'\n\t\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\t\tserverOp,\n\t\t\t\t\t\t'VALIDATION_ERROR',\n\t\t\t\t\t\t`Validator threw: ${message}`,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'reject') {\n\t\t\t\t\tconst retriable = decision.retriable ?? isRetriableRejection(decision.code)\n\t\t\t\t\tif (retriable) {\n\t\t\t\t\t\tthis.sendOperationRejected(serverOp, decision.code, decision.message, true)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.refuseTerminally(serverOp, decision.code, decision.message)\n\t\t\t\t\t}\n\t\t\t\t\trejectedOperations += 1\n\t\t\t\t\tif (retriable) {\n\t\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\t} else {\n\t\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'ignore') {\n\t\t\t\t\t// The server took responsibility out of band; do not materialize the\n\t\t\t\t\t// raw op and do not reject. The batch ack lets the client drop it.\n\t\t\t\t\t// Recorded first, durably: the handshake then counts its sequence as\n\t\t\t\t\t// resolved, and a resubmission is acknowledged without being handed to\n\t\t\t\t\t// the validator again (RT-43).\n\t\t\t\t\tawait this.recordResolution(op, 'ignored', null, null)\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// action === 'accept' falls through to normal materialization.\n\t\t\t}\n\n\t\t\t// What the write points at (foreign-key parents, blob content) must be inside\n\t\t\t// what this writer may read (RT-11, RT-13).\n\t\t\tconst references = await this.authorizeReferences(serverOp)\n\t\t\tif (!references.allowed) {\n\t\t\t\tawait this.refuseTerminally(serverOp, references.code, references.message)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Re-check authorization inside the store's apply critical section against the\n\t\t\t// row as it is at commit time, so a concurrent ownership change or same-id\n\t\t\t// insert cannot slip in between the pre-check above and this write.\n\t\t\tconst uplinkScopes = this.uplinkScopes()\n\t\t\tconst applyResult = await applyServerOperation(this.store, storedOp, undefined, {\n\t\t\t\tview: serverOp,\n\t\t\t\tauthorize: (stored) => authorizeUplinkWrite(serverOp, stored, uplinkScopes),\n\t\t\t\t// Cascades and set-nulls of a delete are judged against the same scope (RT-10).\n\t\t\t\tauthorizeSideEffect: (effect, stored) => authorizeUplinkWrite(effect, stored, uplinkScopes),\n\t\t\t\t// A client without the sequence-reservation capability may legitimately\n\t\t\t\t// produce two operations under one sequence: store the pair (RT-37).\n\t\t\t\tlegacySequenceWriter: !this.sequenceReservation,\n\t\t\t\tonLegacySequencePair: (pair) => this.recordLegacySequencePair(pair),\n\t\t\t\tisAuthoredSideEffect: (effect) =>\n\t\t\t\t\t(authoredCopies.get(serverOp.id) ?? []).some((copy) =>\n\t\t\t\t\t\tisAuthoredCopyOfSideEffect(copy, serverOp.id, effect),\n\t\t\t\t\t),\n\t\t\t})\n\t\t\tfor (const effect of applyResult.deferredSideEffects ?? []) {\n\t\t\t\tconst copyIds = (authoredCopies.get(serverOp.id) ?? [])\n\t\t\t\t\t.filter((copy) => isAuthoredCopyOfSideEffect(copy, serverOp.id, effect))\n\t\t\t\t\t.map((copy) => copy.id)\n\t\t\t\tdeferredEffects.push({ parent: storedOp, effect, copyIds })\n\t\t\t}\n\t\t\tif (applyResult.rejection) {\n\t\t\t\t// A SEQUENCE_CONFLICT is not final: the client renumbers the operation and\n\t\t\t\t// resubmits it under the same id, so it is never remembered as refused.\n\t\t\t\tif (\n\t\t\t\t\tapplyResult.rejection.retriable ||\n\t\t\t\t\tapplyResult.rejection.code === SEQUENCE_CONFLICT_CODE\n\t\t\t\t) {\n\t\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\t\tserverOp,\n\t\t\t\t\t\tapplyResult.rejection.code,\n\t\t\t\t\t\tapplyResult.rejection.message,\n\t\t\t\t\t\tapplyResult.rejection.retriable,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tawait this.refuseTerminally(\n\t\t\t\t\t\tserverOp,\n\t\t\t\t\t\tapplyResult.rejection.code,\n\t\t\t\t\t\tapplyResult.rejection.message,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\trejectedOperations += 1\n\t\t\t\tif (applyResult.rejection.retriable) {\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t} else {\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (applyResult.result === 'applied') {\n\t\t\t\tapplied.push(...applyResult.appliedOperations)\n\t\t\t\tstoredInBatch.add(op.id)\n\t\t\t\tuniqueOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t} else {\n\t\t\t\tstoredInBatch.add(op.id)\n\t\t\t\tduplicateOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t}\n\t\t}\n\n\t\t// Derive the server's copy of every deferred effect whose authored copy did not\n\t\t// end up stored (refused, rate-limited, or not reached in this batch): the\n\t\t// referential effect of an applied delete is never left undone (RT-69).\n\t\tapplied.push(...(await this.deriveUncoveredSideEffects(deferredEffects, storedInBatch)))\n\n\t\tif (operations.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:received',\n\t\t\t\toperations,\n\t\t\t\tbatchSize: operations.length,\n\t\t\t\tuniqueOperations,\n\t\t\t\tduplicateOperations,\n\t\t\t\trejectedOperations,\n\t\t\t})\n\t\t}\n\n\t\t// Send acknowledgment\n\t\tconst lastOp = operations[operations.length - 1]\n\t\tconst ack: SyncMessage = {\n\t\t\ttype: 'acknowledgment',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tacknowledgedMessageId: msg.messageId,\n\t\t\tlastSequenceNumber: lastOp ? Math.min(acknowledgedThrough, lastOp.sequenceNumber) : 0,\n\t\t}\n\t\tthis.sendToClient(ack)\n\n\t\t// Relay only newly applied operations to other sessions\n\t\tif (applied.length > 0) {\n\t\t\tthis.onRelay?.(this.sessionId, applied)\n\t\t}\n\t}\n\n\t/**\n\t * For each delete of this session's node in an upload batch, the batch's later\n\t * operations of the same node that name it as a causal parent: candidates for the\n\t * author's own copies of its cascades and set-nulls (RT-69). Indexed by the delete's\n\t * id, in the server's schema (field names as the server derives effects).\n\t */\n\tprivate indexAuthoredSideEffectCopies(operations: Operation[]): Map<string, Operation[]> {\n\t\tconst copies = new Map<string, Operation[]>()\n\t\tconst deletes = new Set<string>()\n\t\tfor (const op of operations) {\n\t\t\tif (op.nodeId !== this.clientNodeId) continue\n\t\t\tconst parents = op.causalDeps.filter((dep) => deletes.has(dep))\n\t\t\tif (parents.length > 0) {\n\t\t\t\tconst view = this.schemaView(op)\n\t\t\t\tif (view.ok) {\n\t\t\t\t\tfor (const parent of parents) {\n\t\t\t\t\t\tcopies.set(parent, [...(copies.get(parent) ?? []), view.op])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (op.type === 'delete') deletes.add(op.id)\n\t\t}\n\t\treturn copies\n\t}\n\n\t/**\n\t * The referential effects of a delete that arrived again as a stored duplicate and\n\t * are still undone (RT-73): effects the author covers later in this batch are\n\t * deferred like a fresh delete's (derived after the batch unless a copy is stored);\n\t * the rest are derived now. Derived ids are deterministic, so a concurrent retry or\n\t * another instance stores the same operations.\n\t *\n\t * @returns The derived operations (to relay)\n\t */\n\tprivate async resumeStoredDeleteEffects(\n\t\top: Operation,\n\t\tauthoredCopies: Map<string, Operation[]>,\n\t\tdeferredEffects: DeferredSideEffect[],\n\t): Promise<Operation[]> {\n\t\tconst view = this.schemaView(op)\n\t\tif (!view.ok) return []\n\t\tconst serverDelete = view.op\n\t\tconst uplinkScopes = this.uplinkScopes()\n\t\tconst effects = await undoneSideEffectsOfStoredDelete(this.store, serverDelete, (effect, row) =>\n\t\t\tauthorizeUplinkWrite(effect, row, uplinkScopes),\n\t\t)\n\t\tconst derive: SideEffectOp[] = []\n\t\tfor (const effect of effects) {\n\t\t\tconst copyIds = (authoredCopies.get(serverDelete.id) ?? [])\n\t\t\t\t.filter((copy) => isAuthoredCopyOfSideEffect(copy, serverDelete.id, effect))\n\t\t\t\t.map((copy) => copy.id)\n\t\t\tif (copyIds.length > 0) deferredEffects.push({ parent: serverDelete, effect, copyIds })\n\t\t\telse derive.push(effect)\n\t\t}\n\t\treturn derive.length > 0 ? deriveServerSideEffects(this.store, serverDelete, derive) : []\n\t}\n\n\t/**\n\t * Derive the server's copy of each deferred side effect unless one of the author's\n\t * copies is stored (applied or already held). A store with the batch lookup is asked\n\t * again, so a copy stored by a concurrent session counts too.\n\t */\n\tprivate async deriveUncoveredSideEffects(\n\t\tdeferred: DeferredSideEffect[],\n\t\tstoredInBatch: Set<string>,\n\t): Promise<Operation[]> {\n\t\tif (deferred.length === 0) return []\n\t\tconst unresolved = [\n\t\t\t...new Set(deferred.flatMap((d) => d.copyIds).filter((id) => !storedInBatch.has(id))),\n\t\t]\n\t\tconst storedElsewhere: Map<string, unknown> =\n\t\t\tunresolved.length > 0 ? await this.findStoredOperationIds(unresolved) : new Map()\n\t\tconst derived: Operation[] = []\n\t\tfor (const { parent, effect, copyIds } of deferred) {\n\t\t\tif (copyIds.some((id) => storedInBatch.has(id) || storedElsewhere.has(id))) continue\n\t\t\tderived.push(...(await deriveServerSideEffects(this.store, parent, [effect])))\n\t\t}\n\t\treturn derived\n\t}\n\n\t/** {@link ServerStore.findStoredOperations} by id; empty without it or on a failed read. */\n\tprivate async findStoredOperationIds(ids: string[]): Promise<Map<string, unknown>> {\n\t\tif (!this.store.findStoredOperations) return new Map()\n\t\ttry {\n\t\t\treturn await this.store.findStoredOperations(ids)\n\t\t} catch (error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[kora] findStoredOperations failed; deriving the server's side effects: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t)\n\t\t\treturn new Map()\n\t\t}\n\t}\n\n\t/**\n\t * The operation as the server schema reads it (transforms at fold time, RT-84): the\n\t * view authorization, validators, constraint checks and scope filters judge, and the\n\t * one the server stores fold (core `operationSchemaView`, same transforms). Never\n\t * stored: the store keeps the operation as uploaded. An envelope operation is opaque\n\t * to the server (NEW-ENC-1) and judged as is; devices transform after decryption.\n\t */\n\tprivate schemaView(\n\t\top: Operation,\n\t): { ok: true; op: Operation } | { ok: false; code: string; message: string } {\n\t\tlet view: Operation | null\n\t\ttry {\n\t\t\tview = operationSchemaView(op, this.schemaVersion, this.operationTransforms)\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode: SCHEMA_TRANSFORM_INVALID_CODE,\n\t\t\t\tmessage: `Operation \"${op.id}\" cannot be read in server schema v${this.schemaVersion}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t}\n\t\t}\n\t\tif (view === null) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode: 'SCHEMA_TRANSFORM_UNAVAILABLE',\n\t\t\t\tmessage: `Operation \"${op.id}\" cannot be transformed from schema v${op.schemaVersion} to server schema v${this.schemaVersion}.`,\n\t\t\t}\n\t\t}\n\t\treturn { ok: true, op: view }\n\t}\n\n\t/**\n\t * Integrity checks on an uploaded operation before anything else judges it:\n\t * - a version-2 plaintext id must be the content hash (`INVALID_OPERATION_ID`);\n\t * - an unknown declared hash version is refused the same way;\n\t * - with required encryption, a data-bearing plaintext operation is refused\n\t * (`PLAINTEXT_REJECTED`) unless the plaintext migration window is open.\n\t *\n\t * @returns null when the operation passes, or the refusal\n\t */\n\tprivate async checkUploadIntegrity(\n\t\top: Operation,\n\t): Promise<{ code: string; message: string } | null> {\n\t\t// Defense in depth: the handshake already refused a server node id (RT-61).\n\t\tif (this.isServerAuthorNodeId(op.nodeId)) {\n\t\t\treturn {\n\t\t\t\tcode: 'INVALID_NODE_ID',\n\t\t\t\tmessage: `Operation \"${op.id}\" is authored by \"${op.nodeId}\", a server node id. A device may never upload operations under one.`,\n\t\t\t}\n\t\t}\n\t\tconst declared = op.hashVersion\n\t\tif (declared !== undefined && declared !== 1 && declared !== 2) {\n\t\t\treturn {\n\t\t\t\tcode: INVALID_OPERATION_ID,\n\t\t\t\tmessage: `Operation \"${op.id}\" declares unknown content-hash version ${String(declared)}. Upgrade the server or the client so both speak the same protocol version.`,\n\t\t\t}\n\t\t}\n\t\tif (op.encrypted === undefined) {\n\t\t\tif (\n\t\t\t\tthis.encryptionPolicy.required &&\n\t\t\t\t!this.encryptionPolicy.allowPlaintextMigration &&\n\t\t\t\t(op.data !== null || op.previousData !== null)\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tcode: PLAINTEXT_REJECTED,\n\t\t\t\t\tmessage: `Operation \"${op.id}\" is plaintext but this server requires end-to-end encryption. Enable sync encryption on the client, or open a plaintext migration window (encryption.allowPlaintextMigration) on the server.`,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// A protocol-1 encrypted payload: its id covers the plaintext, which the server\n\t\t\t// never sees, so it cannot be checked here (the receivers refuse the format).\n\t\t\tif (\n\t\t\t\tSyncEncryptor.isEncryptedPayload(op.data) ||\n\t\t\t\tSyncEncryptor.isEncryptedPayload(op.previousData)\n\t\t\t) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// Every plaintext id is verified, version 1 included (RT-64): an operation that\n\t\t\t// declares no version must carry its version-1 (or version-2) content hash, so\n\t\t\t// omitting `hashVersion` skips nothing and no client stores an op under a chosen id.\n\t\t\tconst integrity = await verifyInboundOperation(op, {\n\t\t\t\tencrypted: false,\n\t\t\t\tabsentVersion: 'verify-ids',\n\t\t\t\tschema: this.store.getSchema(),\n\t\t\t})\n\t\t\tif (\n\t\t\t\tintegrity.ok &&\n\t\t\t\tintegrity.matchedVersion !== undefined &&\n\t\t\t\tintegrity.declarable !== false\n\t\t\t) {\n\t\t\t\tthis.matchedHashVersions.set(op, integrity.matchedVersion)\n\t\t\t}\n\t\t\tif (integrity.ok && integrity.restoredData !== undefined) {\n\t\t\t\tthis.restoredLegacyData.set(op, integrity.restoredData)\n\t\t\t}\n\t\t\t// Every replica folds a version-1 update in its canonical body: a previousData key\n\t\t\t// absent from data is a clear (core canonicalizeLegacyOperation). beta.12 only\n\t\t\t// ever produced that shape from `undefined` members, whose id covers the clear;\n\t\t\t// an id that verifies WITHOUT the clear names a body no beta.12 wrote, and storing\n\t\t\t// it would let authorization judge one body while every fold applies another.\n\t\t\tif (\n\t\t\t\tintegrity.ok &&\n\t\t\t\tdeclared === undefined &&\n\t\t\t\tintegrity.restoredData === undefined &&\n\t\t\t\tcanonicalizeLegacyOperation(op) !== op\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tcode: INVALID_OPERATION_ID,\n\t\t\t\t\tmessage: `Operation \"${op.id}\" is a version-1 update whose previousData names fields its data lacks, but its id does not cover clearing them. No Kora client writes this shape; it is refused and never stored or relayed.`,\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!integrity.ok && declared === undefined && this.acceptsUnverifiedLegacyId(op)) {\n\t\t\t\t// RT-71: a beta.12 (protocol 1) client hashed `undefined` members as `null`;\n\t\t\t\t// the JSON it uploaded no longer holds them, so the id cannot always be\n\t\t\t\t// rebuilt. The operation is stored unverified (no declared version), as every\n\t\t\t\t// beta.12 operation was before RT-64. This skips no protection RT-64 needs:\n\t\t\t\t// the ids the server derives are keyed (HMAC), so no client can predict and\n\t\t\t\t// pre-store one, and a protocol-2 session never reaches this branch.\n\t\t\t\tthis.reportUnverifiedLegacyOperation(op)\n\t\t\t\tconst restored = restoreUndefinedFromPrevious(op)\n\t\t\t\tif (restored !== op.data) this.restoredLegacyData.set(op, restored)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (!integrity.ok) {\n\t\t\t\treturn {\n\t\t\t\t\tcode: INVALID_OPERATION_ID,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\tdeclared === 2\n\t\t\t\t\t\t\t? `Operation \"${op.id}\" does not match its content hash (hash version 2): its id, data, previousData, sequenceNumber, causalDeps or schemaVersion was altered after it was created. It is refused and never stored or relayed.`\n\t\t\t\t\t\t\t: `Operation \"${op.id}\" does not match its content hash (hash version 1: type, collection, recordId, data, timestamp, nodeId, atomicOps): its id was not computed from its content, or the content was altered. It is refused and never stored or relayed.`,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\t/**\n\t * Whether an undeclared version-1 id that does not verify is accepted unverified\n\t * (RT-71): only from a protocol-1 session (Kora <= beta.12), and only for the\n\t * session's own node.\n\t */\n\tprivate acceptsUnverifiedLegacyId(op: Operation): boolean {\n\t\treturn this.clientProtocolVersion < SYNC_PROTOCOL_VERSION && op.nodeId === this.clientNodeId\n\t}\n\n\t/** Log, count and emit an operation accepted with an unverified legacy id (RT-71). */\n\tprivate reportUnverifiedLegacyOperation(op: Operation): void {\n\t\tthis.unverifiedLegacyOperations++\n\t\tconst message = `Operation \"${op.id}\" from protocol-1 node \"${op.nodeId}\" does not match its version-1 content hash (Kora <= beta.12 hashed undefined members as null, and the JSON upload no longer holds them). It is stored unverified. Upgrade the client.`\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'warn',\n\t\t\tevent: 'session.unverified_legacy_operation',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId: op.nodeId,\n\t\t\tdetails: { operationId: op.id, collection: op.collection, type: op.type, message },\n\t\t})\n\t\tthis.emitter?.emit({\n\t\t\ttype: 'sync:unverified-legacy-operation',\n\t\t\tnodeId: op.nodeId,\n\t\t\toperationId: op.id,\n\t\t\tcollection: op.collection,\n\t\t\tmessage,\n\t\t})\n\t}\n\n\t/** Operations this session accepted with an unverified legacy id (RT-71). */\n\tgetUnverifiedLegacyOperationCount(): number {\n\t\treturn this.unverifiedLegacyOperations\n\t}\n\n\t/**\n\t * The operation as the server stores it: an undeclared plaintext id this server\n\t * verified declares the version it matched (1, or 2 when the declaration was lost),\n\t * so receivers verify it too (RT-64). An absent version is left only on ids nobody\n\t * could verify (protocol-1 encrypted payloads, server-side transforms).\n\t */\n\tprivate declareVerifiedHashVersion(op: Operation): Operation {\n\t\tif (op.hashVersion !== undefined) return op\n\t\tconst matched = this.matchedHashVersions.get(op)\n\t\t// A beta.12 update that cleared fields with `undefined` is stored with those fields\n\t\t// `null` (RT-71): what the writer applied, and the same version-1 hash.\n\t\tconst restored = this.restoredLegacyData.get(op)\n\t\tconst content = restored === undefined ? op : { ...op, data: restored }\n\t\treturn matched === undefined ? content : { ...content, hashVersion: matched }\n\t}\n\n\t/**\n\t * True for a node id that is (or was) the server's own: the `kora:` namespace, the\n\t * store's node id, and every id the server advertises or folds as authoritative\n\t * (other instances, legacy server node ids, configured extras). No device may use one\n\t * (RT-61), whether or not it has history yet.\n\t */\n\tprivate isServerAuthorNodeId(nodeId: string): boolean {\n\t\tif (nodeId.startsWith(RESERVED_PRINCIPAL_PREFIX)) return true\n\t\tif (nodeId === this.store.getNodeId()) return true\n\t\tif (this.serverAuthoritativeNodeIds().includes(nodeId)) return true\n\t\t// Every id the deployment ever held authoritative, revoked ones included (RT-81):\n\t\t// devices may still hold it as authoritative (until they learn the revocation).\n\t\tif (this.store.getEverAuthoritativeNodeIds?.().includes(nodeId)) return true\n\t\treturn this.store.getAuthoritativeNodeIds?.().includes(nodeId) ?? false\n\t}\n\n\t/**\n\t * The authoritative ids a handshake advertises (RT-75): only explicit ones (legacy\n\t * server node ids, configured extras). Every `kora:server:` id is authoritative by\n\t * prefix on every replica, and listing instance ids would make the list differ per\n\t * instance and per start, which devices would have to treat as news.\n\t */\n\t/** The handshake's explicit revocations (RT-81), when the deployment has any. */\n\tprivate advertisedRevocations(): { revokedAuthoritativeNodeIds?: string[] } {\n\t\tconst revoked = (this.store.getRevokedAuthoritativeNodeIds?.() ?? []).filter(\n\t\t\t(id) => !isServerNodeId(id),\n\t\t)\n\t\treturn revoked.length > 0 ? { revokedAuthoritativeNodeIds: revoked } : {}\n\t}\n\n\tprivate advertisedAuthoritativeNodeIds(): string[] {\n\t\treturn [...new Set(this.serverAuthoritativeNodeIds())].filter((id) => !isServerNodeId(id))\n\t}\n\n\t/** Node ids this server authors operations under (protocol v2 handshake response). */\n\tprivate serverAuthoritativeNodeIds(): string[] {\n\t\tif (this.authoritativeNodeIds !== null) return [...this.authoritativeNodeIds]\n\t\t// Exactly the ids the server stores fold with (seam 3): a client that folded with\n\t\t// a different set would resolve `merge('server-authoritative')` differently.\n\t\treturn this.store.getAuthoritativeNodeIds?.() ?? [this.store.getNodeId()]\n\t}\n\n\t/**\n\t * A protocol-1 client (Kora <= beta.12) is served for one release (beta.13) with a\n\t * deprecation warning: its operation ids are version-1 hashes and its encrypted\n\t * payloads have no envelope binding.\n\t */\n\tprivate warnLegacyProtocol(nodeId: string): void {\n\t\tconst message = `Client node \"${nodeId}\" speaks sync protocol ${String(this.clientProtocolVersion)}; this server speaks ${String(SYNC_PROTOCOL_VERSION)}. Protocol 1 clients (Kora <= beta.12) are accepted in beta.13 only and will be refused by the next release. Upgrade the client.`\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'warn',\n\t\t\tevent: 'session.protocol_deprecated',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId,\n\t\t\tdetails: {\n\t\t\t\tcode: PROTOCOL_V1_DEPRECATED,\n\t\t\t\tclientProtocolVersion: this.clientProtocolVersion,\n\t\t\t\tserverProtocolVersion: SYNC_PROTOCOL_VERSION,\n\t\t\t\tmessage,\n\t\t\t},\n\t\t})\n\t\tthis.emitter?.emit({\n\t\t\ttype: 'sync:protocol-deprecated',\n\t\t\tnodeId,\n\t\t\tclientProtocolVersion: this.clientProtocolVersion,\n\t\t\tserverProtocolVersion: SYNC_PROTOCOL_VERSION,\n\t\t\tmessage,\n\t\t})\n\t}\n\n\t/** The in-scope operations a version-vector client is missing (not yet sent). */\n\tprivate async collectDeltaOperations(clientVector: Map<string, number>): Promise<Operation[]> {\n\t\tconst serverVector = await this.readServerVector()\n\t\tconst missing: Operation[] = []\n\n\t\tfor (const [nodeId, serverSeq] of serverVector) {\n\t\t\tconst clientSeq = clientVector.get(nodeId) ?? 0\n\t\t\t// A legacy pair (two operations under one (node, sequence), RT-37) at or below\n\t\t\t// the client's entry: the client may hold only one of them, and the range read\n\t\t\t// below starts above its entry, so both are sent again (RT-48). The client\n\t\t\t// dedups by id; pairs are few (legacy writers only), so the resend is small.\n\t\t\tconst pairs =\n\t\t\t\tclientSeq > 0 && this.store.getSequencePairOperations\n\t\t\t\t\t? await this.store.getSequencePairOperations(nodeId, Math.min(clientSeq, serverSeq))\n\t\t\t\t\t: []\n\t\t\tif (serverSeq > clientSeq || pairs.length > 0) {\n\t\t\t\tconst range =\n\t\t\t\t\tserverSeq > clientSeq\n\t\t\t\t\t\t? await this.store.getOperationRange(nodeId, clientSeq + 1, serverSeq)\n\t\t\t\t\t\t: []\n\t\t\t\tconst ops = [...pairs, ...range]\n\t\t\t\tconst snapshots = await this.scopeSnapshotsFor(ops)\n\t\t\t\tfor (const op of ops) {\n\t\t\t\t\tconst snapshot = snapshots.get(op.id) ?? null\n\t\t\t\t\tif (await this.operationVisibleToClient(op, snapshot)) {\n\t\t\t\t\t\tconst entry = await this.scopeEntryFor(op, snapshot)\n\t\t\t\t\t\tif (entry) missing.push(entry)\n\t\t\t\t\t\tmissing.push(op)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn missing\n\t}\n\n\t/** Send a collected version-vector delta in paginated, cursor-carrying batches. */\n\tprivate sendCollectedDelta(missing: Operation[]): void {\n\t\tif (missing.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tconst sorted = topologicalSort(missing)\n\t\tconst afterCursor = sliceOperationsAfterCursor(sorted, this.resumeDeltaCursor)\n\t\tconst totalBatches = Math.ceil(afterCursor.length / this.batchSize)\n\n\t\tif (afterCursor.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: this.resumeDeltaCursor?.batchIndex ?? 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst start = i * this.batchSize\n\t\t\tconst batchOps = afterCursor.slice(start, start + this.batchSize)\n\t\t\tconst serializedOps = batchOps.map((op) => this.serializer.encodeOperation(op))\n\t\t\tconst batchCursor = createDeltaCursorFromBatch(batchOps, i)\n\n\t\t\tconst batchMsg: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: serializedOps,\n\t\t\t\tisFinal: i === totalBatches - 1,\n\t\t\t\tbatchIndex: i,\n\t\t\t\ttotalBatches,\n\t\t\t\t...(batchCursor ? { cursor: encodeDeltaCursor(batchCursor) } : {}),\n\t\t\t}\n\t\t\tthis.sendToClient(batchMsg)\n\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: batchOps,\n\t\t\t\tbatchSize: batchOps.length,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Stream the gap-free server->client delivery stream, resuming just after\n\t * `fromDeliverySeq`. Operations are scanned in server delivery-sequence order\n\t * (commit order), scope-filtered for this session, and sent in batches that chain:\n\t * each batch's `baseDeliverySequence` equals the previous batch's\n\t * `maxDeliverySequence` (the first batch bases on `fromDeliverySeq`). The client\n\t * applies a batch only when its watermark equals the base and advances the\n\t * watermark to the max, so a dropped batch stalls the watermark and is recovered by\n\t * a re-send from the acknowledged position. Because delivery-sequence order respects\n\t * causal order (a dependency is always committed, and thus sequenced, before its\n\t * dependent), no topological sort is needed.\n\t *\n\t * Batches go out as each scan chunk is filtered (SRV-5): the server holds at most\n\t * one scan chunk plus two batches per stream, never the whole backlog, and the\n\t * first batch reaches the client after one chunk. One full batch is held back so\n\t * the stream's last batch can be marked `isFinal` (one-batch lookahead). The final\n\t * batch carries the highest sequence scanned, not merely the last in-scope one, so\n\t * an out-of-scope tail is not re-scanned. Every sent batch advances the send cursor\n\t * ({@link lastSentDeliverySeq}). Between batches the stream waits for the client to\n\t * drain its socket (backpressure).\n\t *\n\t * @param fromDeliverySeq - The chain base: the client's watermark or the send cursor\n\t * @param finalizeWhenEmpty - Send an empty final batch even when nothing new was\n\t * scanned (the handshake stream, so the client completes initial sync)\n\t */\n\tprivate async streamDelivery(\n\t\tfromDeliverySeq: number,\n\t\tfinalizeWhenEmpty: boolean,\n\t): Promise<{ sentOperations: number; maxScanned: number }> {\n\t\tconst batchSize = Math.max(this.batchSize, 1)\n\t\tconst scanChunk = batchSize * 5\n\t\tlet scanCursor = fromDeliverySeq\n\t\tlet maxScanned = fromDeliverySeq\n\t\tlet base = fromDeliverySeq\n\t\tlet batchIndex = 0\n\t\tlet sentOperations = 0\n\t\tlet pending: DeliverableOperation[] = []\n\t\tlet held: DeliverableOperation[] | null = null\n\n\t\tconst live = (): boolean => this.state !== 'closed' && this.transport.isConnected()\n\t\tconst send = async (slice: DeliverableOperation[], isFinal: boolean): Promise<void> => {\n\t\t\tconst last = slice[slice.length - 1]\n\t\t\tconst lastSeq = last ? last.deliverySequence : base\n\t\t\t// The final batch carries the max scanned sequence (>= lastSeq) so the client\n\t\t\t// skips past any out-of-scope operations above the last in-scope one.\n\t\t\tconst max = isFinal ? Math.max(maxScanned, lastSeq) : lastSeq\n\t\t\tthis.sendDeliveryBatch(slice, base, max, batchIndex, isFinal)\n\t\t\tbatchIndex += 1\n\t\t\tbase = max\n\t\t\tsentOperations += slice.filter((item) => !item.retraction).length\n\t\t\tthis.recordDeliverySent(max)\n\t\t\tawait this.waitForSendWindow()\n\t\t}\n\n\t\twhile (live()) {\n\t\t\tconst chunk = await this.store.getOperationsAfterDelivery(scanCursor, scanChunk)\n\t\t\tconst last = chunk[chunk.length - 1]\n\t\t\tif (last === undefined) break\n\t\t\tconst deliverable = await this.filterDeliveryChunk(chunk)\n\t\t\tpending.push(...deliverable)\n\t\t\t// Cut full batches. A batch never ends on a scope entry: the entry and the\n\t\t\t// operation that triggered it share one delivery sequence, and a batch max of\n\t\t\t// that sequence would claim the trigger was delivered too. (The trigger always\n\t\t\t// follows its entry in the same chunk, so the extension stays in `pending`.)\n\t\t\twhile (pending.length >= batchSize && live()) {\n\t\t\t\tlet end = batchSize\n\t\t\t\twhile (end < pending.length && pending[end - 1]?.scopeEntry === true) end += 1\n\t\t\t\tif (pending[end - 1]?.scopeEntry === true) break\n\t\t\t\tconst slice = pending.slice(0, end)\n\t\t\t\tpending = pending.slice(end)\n\t\t\t\tif (held) await send(held, false)\n\t\t\t\theld = slice\n\t\t\t}\n\t\t\tscanCursor = last.deliverySequence\n\t\t\t// maxScanned counts every operation scanned, including excluded (own or\n\t\t\t// out-of-scope) ones, so the final max advances the watermark past them.\n\t\t\tmaxScanned = scanCursor\n\t\t\tif (chunk.length < scanChunk) break\n\t\t}\n\t\tif (!live()) return { sentOperations, maxScanned }\n\n\t\tif (held && pending.length > 0) {\n\t\t\tawait send(held, false)\n\t\t\tawait send(pending, true)\n\t\t} else if (held) {\n\t\t\tawait send(held, true)\n\t\t} else if (pending.length > 0) {\n\t\t\tawait send(pending, true)\n\t\t} else if (finalizeWhenEmpty || maxScanned > fromDeliverySeq) {\n\t\t\t// Nothing in scope after the cursor. On a handshake, a single empty final batch\n\t\t\t// lets the client advance past an out-of-scope tail and complete initial sync;\n\t\t\t// during streaming it advances the watermark past newly scanned out-of-scope\n\t\t\t// operations. With nothing scanned at all, a live push sends nothing.\n\t\t\tawait send([], true)\n\t\t}\n\t\treturn { sentOperations, maxScanned }\n\t}\n\n\t/**\n\t * Filter one scan chunk of the delivery log down to what this session receives:\n\t * visible operations (each preceded by its scope-entry insert, RT-19) and\n\t * retractions. The records the decisions need are fetched for the whole chunk at\n\t * once (LMS #11), one batched read per collection instead of one query per op.\n\t */\n\tprivate async filterDeliveryChunk(chunk: DeliveredOperation[]): Promise<DeliverableOperation[]> {\n\t\tconst deliverable: DeliverableOperation[] = []\n\t\tconst clientNodeId = this.clientNodeId\n\t\tconst candidates = chunk.filter(\n\t\t\t(delivered) =>\n\t\t\t\t// The client's own operations are skipped above the inclusion point: it\n\t\t\t\t// uploaded them itself. A full resync still recovers its own history.\n\t\t\t\t!(\n\t\t\t\t\tclientNodeId !== null &&\n\t\t\t\t\tdelivered.operation.nodeId === clientNodeId &&\n\t\t\t\t\tdelivered.deliverySequence > this.ownOperationsIncludedThrough\n\t\t\t\t),\n\t\t)\n\t\tthis.recordLookupCache = await this.prefetchRecordsFor(candidates)\n\t\ttry {\n\t\t\tfor (const delivered of candidates) {\n\t\t\t\tconst snapshot = delivered.scopeSnapshot ?? null\n\t\t\t\tif (await this.operationVisibleToClient(delivered.operation, snapshot)) {\n\t\t\t\t\t// The scope-entry shares the trigger's delivery sequence and precedes it,\n\t\t\t\t\t// so a resend from any watermark regenerates it (same id) with its trigger.\n\t\t\t\t\tconst entry = await this.scopeEntryFor(delivered.operation, snapshot)\n\t\t\t\t\tif (entry) {\n\t\t\t\t\t\tdeliverable.push({\n\t\t\t\t\t\t\toperation: entry,\n\t\t\t\t\t\t\tdeliverySequence: delivered.deliverySequence,\n\t\t\t\t\t\t\tscopeEntry: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\tdeliverable.push(delivered)\n\t\t\t\t} else if (await this.scopeRetractionFor(delivered.operation, snapshot)) {\n\t\t\t\t\tdeliverable.push({ ...delivered, retraction: true })\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.recordLookupCache = null\n\t\t}\n\t\treturn deliverable\n\t}\n\n\t/**\n\t * Read, in one batched query per collection, every record the visibility decisions\n\t * for these operations may look up, when the store supports batched reads. Returns\n\t * null (per-operation lookups) otherwise. Over-fetching is harmless: the chunk\n\t * bounds it.\n\t */\n\tprivate async prefetchRecordsFor(\n\t\tdelivered: DeliveredOperation[],\n\t): Promise<Map<string, MaterializedRecord | null> | null> {\n\t\tconst store = this.store\n\t\tif (!store.findRecordsByIds || delivered.length === 0) return null\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\tconst subsets = this.syncQuerySubsets.length > 0\n\t\tconst idsByCollection = new Map<string, Set<string>>()\n\t\tfor (const { operation: op, scopeSnapshot } of delivered) {\n\t\t\tconst snapshot = scopeSnapshot ?? null\n\t\t\tconst needsRecord =\n\t\t\t\tsubsets ||\n\t\t\t\t(snapshot?.post\n\t\t\t\t\t? snapshotLacksScopeFields(op.collection, { pre: null, post: snapshot.post }, scopes)\n\t\t\t\t\t: missingScopeFields(op, scopes).length > 0) ||\n\t\t\t\t(snapshot !== null &&\n\t\t\t\t\tscopes !== undefined &&\n\t\t\t\t\t(snapshotLacksScopeFields(op.collection, snapshot, scopes) ||\n\t\t\t\t\t\t(op.type === 'update' && snapshotEntersScopes(op, snapshot, scopes))))\n\t\t\tif (!needsRecord) continue\n\t\t\tlet ids = idsByCollection.get(op.collection)\n\t\t\tif (!ids) {\n\t\t\t\tids = new Set()\n\t\t\t\tidsByCollection.set(op.collection, ids)\n\t\t\t}\n\t\t\tids.add(op.recordId)\n\t\t}\n\t\tif (idsByCollection.size === 0) return null\n\t\tconst cache = new Map<string, MaterializedRecord | null>()\n\t\ttry {\n\t\t\tfor (const [collection, ids] of idsByCollection) {\n\t\t\t\tconst rows = await store.findRecordsByIds(collection, [...ids])\n\t\t\t\tfor (const id of ids) cache.set(recordCacheKey(collection, id), rows.get(id) ?? null)\n\t\t\t}\n\t\t} catch {\n\t\t\t// A failed batched read falls back to per-operation lookups.\n\t\t\treturn null\n\t\t}\n\t\treturn cache\n\t}\n\n\t/** Build, track, and send one chained delivery-stream batch. */\n\tprivate sendDeliveryBatch(\n\t\tslice: DeliverableOperation[],\n\t\tbase: number,\n\t\tmax: number,\n\t\tbatchIndex: number,\n\t\tisFinal: boolean,\n\t): boolean {\n\t\tconst batchMsg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: slice\n\t\t\t\t.filter((delivered) => !delivered.retraction)\n\t\t\t\t.map((delivered) => this.serializer.encodeOperation(delivered.operation)),\n\t\t\t...(slice.some((delivered) => delivered.retraction)\n\t\t\t\t? {\n\t\t\t\t\t\tretractions: slice\n\t\t\t\t\t\t\t.filter((delivered) => delivered.retraction)\n\t\t\t\t\t\t\t.map((delivered) => ({\n\t\t\t\t\t\t\t\tcollection: delivered.operation.collection,\n\t\t\t\t\t\t\t\trecordId: delivered.operation.recordId,\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\tisFinal,\n\t\t\tbatchIndex,\n\t\t\tbaseDeliverySequence: base,\n\t\t\tmaxDeliverySequence: max,\n\t\t}\n\t\t// Delivery batches are NOT tracked in the bounded pending-relay buffer: recovery of\n\t\t// a dropped or unapplied batch is by re-scan from the client's acknowledged\n\t\t// position (the next push or the retransmit tick), which cannot be defeated by a\n\t\t// buffer eviction. The client re-acks a duplicate and stalls on a gap, so re-sends\n\t\t// are always safe.\n\t\tconst sent = this.sendToClient(batchMsg)\n\t\tconst sentOperations = slice.filter((delivered) => !delivered.retraction)\n\t\tif (sentOperations.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: sentOperations.map((delivered) => delivered.operation),\n\t\t\t\tbatchSize: sentOperations.length,\n\t\t\t})\n\t\t}\n\t\treturn sent\n\t}\n\n\t/** The scope snapshots of these operations, when the store keeps them (RT-14). */\n\tprivate async scopeSnapshotsFor(\n\t\toperations: Operation[],\n\t): Promise<Map<string, OperationScopeSnapshot>> {\n\t\tif (!this.store.getOperationScopeSnapshots || operations.length === 0) return new Map()\n\t\ttry {\n\t\t\treturn await this.store.getOperationScopeSnapshots(operations.map((op) => op.id))\n\t\t} catch {\n\t\t\treturn new Map()\n\t\t}\n\t}\n\n\t/**\n\t * Download visibility of one operation. With a scope snapshot (RT-14) the\n\t * operation is judged on the record's scope values right after it was applied, so\n\t * history written while a record belonged to someone else stays hidden after an\n\t * ownership transfer, and a previous owner still receives its own history. Query\n\t * subsets (a client-chosen narrowing, not an authorization) keep using the current\n\t * row. Operations without a snapshot (legacy rows, custom stores) fall back to the\n\t * current row plus `op.data`.\n\t */\n\tprivate async operationVisibleToClient(\n\t\tstored: Operation,\n\t\tsnapshot: OperationScopeSnapshot | null = null,\n\t): Promise<boolean> {\n\t\t// Judged on the operation as the server schema reads it (RT-84): a stored\n\t\t// operation of an older schema version names its fields as its author did.\n\t\tconst judged = this.schemaView(stored)\n\t\tconst op = judged.ok ? judged.op : stored\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\tconst subsets = this.syncQuerySubsets\n\t\tif (snapshot?.post) {\n\t\t\t// A snapshot captured before a scope field existed lacks it: judge that field\n\t\t\t// on the current row instead of as \"no value\" (RT-20).\n\t\t\tlet current: MaterializedRecord | undefined\n\t\t\tlet post: Record<string, unknown> | null = snapshot.post\n\t\t\tif (snapshotLacksScopeFields(op.collection, { pre: null, post }, scopes)) {\n\t\t\t\tcurrent = await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\t\tpost = snapshotValuesWithFallback(op.collection, post, scopes, current)\n\t\t\t}\n\t\t\tif (!post || !recordMatchesScopes(op.collection, { ...post, id: op.recordId }, scopes)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (subsets.length === 0) return true\n\t\t\tcurrent ??= await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\treturn operationMatchesQuerySubsets(op, subsets, current)\n\t\t}\n\t\t// Visibility is judged on the server-materialized row plus op.data, never on the\n\t\t// writer's previousData (RT-3: it is unverified, so it could push an op into\n\t\t// another tenant's log or hide it from the writer's own devices). A partial\n\t\t// update (or a delete) may not carry the scope / query-subset fields in its own\n\t\t// data, so backfill them from the materialized record (including a soft-deleted\n\t\t// one) whenever they are missing. Only look up when needed so the common case\n\t\t// (inserts, or ops that already carry the fields) stays lookup-free.\n\t\tconst needsBackfill =\n\t\t\tmissingScopeFields(op, scopes).length > 0 || (subsets !== undefined && subsets.length > 0)\n\t\tconst fullRecord = needsBackfill\n\t\t\t? await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\t: undefined\n\n\t\tif (!operationMatchesScopes(op, scopes, fullRecord)) {\n\t\t\treturn false\n\t\t}\n\t\treturn operationMatchesQuerySubsets(op, subsets, fullRecord)\n\t}\n\n\t/**\n\t * Where the store already holds each of `operations` (by id), in one store read.\n\t * Null when the store cannot answer by id (a custom store without\n\t * `findStoredOperations`, or the read failed): callers then fall back to a\n\t * per-operation (node, sequence) lookup and the store's own dedup at apply.\n\t */\n\tprivate async findStoredOperations(\n\t\toperations: Operation[],\n\t): Promise<Map<string, StoredOperationKey>> {\n\t\tif (!this.store.findStoredOperations) return new Map()\n\t\ttry {\n\t\t\treturn await this.store.findStoredOperations(operations.map((op) => op.id))\n\t\t} catch (error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[kora] findStoredOperations failed; judging the batch without it: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t)\n\t\t\treturn new Map()\n\t\t}\n\t}\n\n\t/**\n\t * True when the batch lookup alone shows `op` is already stored and may be\n\t * acknowledged as a duplicate with no further store work (RT-31, RT-39): this\n\t * device's own operation stored under its node (its sequence repair may have\n\t * renumbered it, keeping the id), or any other operation stored under exactly its\n\t * (node, sequence, id), such as one the server itself delivered and the client\n\t * echoed back. Never true for a store without the batch lookup.\n\t */\n\tprivate isStoredDuplicate(op: Operation, batch: Map<string, StoredOperationKey>): boolean {\n\t\tconst known = batch.get(op.id)\n\t\tif (!known || known.nodeId !== op.nodeId) return false\n\t\tconst own = op.nodeId === this.clientNodeId && op.timestamp.nodeId === op.nodeId\n\t\treturn own || known.sequenceNumber === op.sequenceNumber\n\t}\n\n\t/**\n\t * The operation the store holds under `op`'s id (at the node and sequence the batch\n\t * lookup found), or null when it cannot be read (the upload is then judged like any\n\t * other: verified, validated, charged, and deduplicated by the store at apply).\n\t */\n\tprivate async loadStoredOperation(\n\t\top: Operation,\n\t\tbatch: Map<string, StoredOperationKey>,\n\t): Promise<Operation | null> {\n\t\tconst known = batch.get(op.id)\n\t\tif (!known) return null\n\t\ttry {\n\t\t\tconst range = await this.store.getOperationRange(\n\t\t\t\tknown.nodeId,\n\t\t\t\tknown.sequenceNumber,\n\t\t\t\tknown.sequenceNumber,\n\t\t\t)\n\t\t\treturn range.find((candidate) => candidate.id === op.id) ?? null\n\t\t} catch (error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[kora] could not load stored operation ${op.id}; judging the upload as new: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t)\n\t\t\treturn null\n\t\t}\n\t}\n\n\t/**\n\t * Refuse an upload that reuses a stored operation's id with different content (RT-77):\n\t * terminal, nothing recorded or derived, logged and emitted as tampering. An honest\n\t * client never does this (ids are content hashes), so the rejection only reaches a\n\t * forger. No resolution is recorded: the id belongs to the stored operation.\n\t */\n\tprivate refuseForgedDuplicate(op: Operation, storedCopy: Operation): void {\n\t\tthis.forgedDuplicates += 1\n\t\tconst message = `Operation \"${op.id}\" reuses the id of an operation the server stores, with different content (${storedCopy.type} ${storedCopy.collection}/${storedCopy.recordId} is stored; ${op.type} ${op.collection}/${op.recordId} was sent). Operation ids are content hashes, so this upload was altered. It is refused and has no effect.`\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'warn',\n\t\t\tevent: 'session.forged_duplicate',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId: this.clientNodeId ?? undefined,\n\t\t\tdetails: {\n\t\t\t\toperationId: op.id,\n\t\t\t\tuploadedNodeId: op.nodeId,\n\t\t\t\tuploaded: { type: op.type, collection: op.collection, recordId: op.recordId },\n\t\t\t\tstored: {\n\t\t\t\t\ttype: storedCopy.type,\n\t\t\t\t\tcollection: storedCopy.collection,\n\t\t\t\t\trecordId: storedCopy.recordId,\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t\tthis.emitter?.emit({\n\t\t\ttype: 'sync:forged-duplicate',\n\t\t\tnodeId: op.nodeId,\n\t\t\toperationId: op.id,\n\t\t\tcollection: op.collection,\n\t\t\tmessage,\n\t\t})\n\t\tthis.sendOperationRejected(op, FORGED_DUPLICATE_CODE, message, false)\n\t}\n\n\t/** Uploads refused for reusing a stored id with other content (RT-77). */\n\tgetForgedDuplicateCount(): number {\n\t\treturn this.forgedDuplicates\n\t}\n\n\t/**\n\t * The recorded resolutions of the batch's own-node operations that the lookup did\n\t * not find stored (RT-43, RT-47). Asked only for this session's own node, so the\n\t * answer never reveals another device's (or tenant's) refusals.\n\t */\n\tprivate async findResolutions(\n\t\toperations: Operation[],\n\t\tstored: Map<string, StoredOperationKey>,\n\t): Promise<Map<string, OperationResolution>> {\n\t\tconst nodeId = this.clientNodeId\n\t\tif (!this.store.findOperationResolutions || nodeId === null) return new Map()\n\t\tconst ids = operations\n\t\t\t.filter((op) => op.nodeId === nodeId && op.timestamp.nodeId === nodeId && !stored.has(op.id))\n\t\t\t.map((op) => op.id)\n\t\tif (ids.length === 0) return new Map()\n\t\tlet found: Map<string, OperationResolution>\n\t\ttry {\n\t\t\tfound = await this.store.findOperationResolutions(nodeId, ids)\n\t\t} catch (error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[kora] findOperationResolutions failed; judging the batch without it: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t)\n\t\t\treturn new Map()\n\t\t}\n\t\t// Only ids the lookup did NOT find stored are asked for, so a `stored-elsewhere`\n\t\t// hit here is stale: it claims a stored copy the lookup has just disproved (the\n\t\t// copy was lost by a restore, RT-51). Acking on it would drop the operation, so it\n\t\t// is forgotten and the operation is judged normally (its real outcome is then\n\t\t// recorded in its place).\n\t\tfor (const [id, resolution] of found) {\n\t\t\tif (resolution.outcome !== 'stored-elsewhere') continue\n\t\t\tfound.delete(id)\n\t\t\tawait this.store.deleteOperationResolution?.(nodeId, id)\n\t\t}\n\t\treturn found\n\t}\n\n\t/** The highest resolved sequence of `nodeId` (0 without the store method or on error). */\n\tprivate async resolvedThrough(nodeId: string): Promise<number> {\n\t\tif (!this.store.getResolvedThrough) return 0\n\t\ttry {\n\t\t\treturn await this.store.getResolvedThrough(nodeId)\n\t\t} catch (error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[kora] getResolvedThrough failed; advertising the stored maximum: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t)\n\t\t\treturn 0\n\t\t}\n\t}\n\n\t/**\n\t * Durably record how this session's own operation was resolved without being stored\n\t * under its sequence. Awaited before the answer is sent: a failure propagates (the\n\t * batch fails and is not acknowledged), so the client never acts on a resolution the\n\t * server could forget.\n\t */\n\tprivate async recordResolution(\n\t\top: Operation,\n\t\toutcome: OperationResolutionOutcome,\n\t\tcode: string | null,\n\t\tmessage: string | null,\n\t): Promise<void> {\n\t\tif (!this.store.recordOperationResolution || op.nodeId !== this.clientNodeId) return\n\t\tawait this.store.recordOperationResolution({\n\t\t\toperationId: op.id,\n\t\t\tnodeId: op.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\toutcome,\n\t\t\tcode,\n\t\t\tmessage,\n\t\t})\n\t}\n\n\t/**\n\t * Refuse an operation for good (non-retriable): remember the refusal (RT-47), then\n\t * tell the client. A resubmission of the same id is answered with this rejection\n\t * without being judged again.\n\t */\n\tprivate async refuseTerminally(op: Operation, code: string, message: string): Promise<void> {\n\t\tawait this.recordResolution(op, 'refused', code, message)\n\t\tthis.sendOperationRejected(op, code, message, false)\n\t}\n\n\t/**\n\t * An own operation acknowledged as a duplicate of the copy stored under ANOTHER\n\t * sequence (the client's sequence repair renumbered it, keeping its id): record the\n\t * submitted sequence as resolved, so the handshake does not read it as lost (RT-43).\n\t */\n\tprivate async noteStoredElsewhere(\n\t\top: Operation,\n\t\tstored: Map<string, StoredOperationKey>,\n\t): Promise<void> {\n\t\tconst known = stored.get(op.id)\n\t\tif (\n\t\t\t!known ||\n\t\t\tknown.nodeId !== op.nodeId ||\n\t\t\tknown.sequenceNumber === op.sequenceNumber ||\n\t\t\top.nodeId !== this.clientNodeId\n\t\t) {\n\t\t\treturn\n\t\t}\n\t\tawait this.recordResolution(op, 'stored-elsewhere', null, null)\n\t}\n\n\t/** Refuse the rest of a batch for the per-minute ingest budget (retriable). */\n\tprivate sendRateLimited(): void {\n\t\tthis.sendError(\n\t\t\t'RATE_LIMIT',\n\t\t\t`Session exceeded operation rate limit (${String(this.rateLimiter.limit)} ops/min for this device; a signed-in user's devices also share a per-user budget); retry in ${String(this.rateLimiter.retryAfterMs())} ms`,\n\t\t\ttrue,\n\t\t)\n\t}\n\n\t/**\n\t * True when the store already holds exactly this operation (same node, sequence and\n\t * id). Answered from the batch lookup when the store supports it.\n\t */\n\tprivate async isStoredOperation(\n\t\top: Operation,\n\t\tbatch: Map<string, StoredOperationKey>,\n\t): Promise<boolean> {\n\t\tconst known = batch.get(op.id)\n\t\tif (known) return known.nodeId === op.nodeId && known.sequenceNumber === op.sequenceNumber\n\t\tif (this.store.findStoredOperations) return false\n\t\ttry {\n\t\t\tconst stored = await this.store.getOperationRange(\n\t\t\t\top.nodeId,\n\t\t\t\top.sequenceNumber,\n\t\t\t\top.sequenceNumber,\n\t\t\t)\n\t\t\treturn stored.some((candidate) => candidate.id === op.id)\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * The scopes this session may write under. Fails closed: with auth configured but\n\t * no accepted authentication, the session may write nothing (an empty scope map),\n\t * never everything.\n\t */\n\tprivate uplinkScopes(): ScopeMap | undefined {\n\t\tif (this.auth && !this.authContext) return {}\n\t\treturn this.authContext?.uplinkScopes ?? this.authContext?.scopes\n\t}\n\n\t/**\n\t * Upload authorization, independent from the client's downloaded/query view. The\n\t * stored row (including a soft-deleted one) is always loaded when scopes apply and\n\t * is authoritative; client-supplied previousData is never consulted.\n\t */\n\tprivate async authorizeClientOperation(op: Operation): Promise<UplinkAuthorizationResult> {\n\t\tconst scopes = this.uplinkScopes()\n\t\tconst stored = scopes ? await this.lookupRecordFields(op.collection, op.recordId) : undefined\n\t\treturn authorizeUplinkWrite(op, stored ?? null, scopes)\n\t}\n\n\t/**\n\t * True when this update moved the record out of the session's scope, judged on the\n\t * store's own before/after values (RT-15), never on the writer's previousData. An\n\t * operation without a snapshot never produces a retraction (fail quiet: the\n\t * client keeps what it already had, and no other tenant's record id leaks).\n\t */\n\tprivate async scopeRetractionFor(\n\t\top: Operation,\n\t\tsnapshot: OperationScopeSnapshot | null = null,\n\t): Promise<boolean> {\n\t\tif (this.scopeExitPolicy !== 'retract') return false\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\tif (!scopes || !snapshot) return false\n\t\tconst current = snapshotLacksScopeFields(op.collection, snapshot, scopes)\n\t\t\t? await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\t: undefined\n\t\treturn snapshotExitsScopes(op, snapshot, scopes, current)\n\t}\n\n\t/**\n\t * The scope-entry operation to send before `op` when `op` moved an existing record\n\t * into this session's download scope (RT-19), or null. Judged on the store's own\n\t * pre/post snapshot; built from the record's CURRENT row, and only while that row\n\t * is live and still inside the scope (a record that has since left again, or was\n\t * deleted, gets no entry: its later operations retract or delete it anyway).\n\t * Operations without a snapshot (legacy rows, custom stores) never produce one.\n\t */\n\tprivate async scopeEntryFor(\n\t\top: Operation,\n\t\tsnapshot: OperationScopeSnapshot | null,\n\t): Promise<Operation | null> {\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\tconst schema = this.store.getSchema()\n\t\tif (!scopes || !snapshot || !schema || op.type !== 'update') return null\n\t\t// Cheap pre-check on the snapshot alone; the row is read only for a candidate.\n\t\tif (\n\t\t\t!snapshotLacksScopeFields(op.collection, snapshot, scopes) &&\n\t\t\t!snapshotEntersScopes(op, snapshot, scopes)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\t\tconst current = await this.lookupRecordFields(op.collection, op.recordId)\n\t\tif (!current || current._deleted === 1 || current._deleted === true) return null\n\t\tif (!snapshotEntersScopes(op, snapshot, scopes, current)) return null\n\t\tif (!recordMatchesScopes(op.collection, { ...current, id: op.recordId }, scopes)) return null\n\t\tlet fieldVersions: RecordFieldVersions | null = null\n\t\tif (this.store.getRecordFieldVersions) {\n\t\t\ttry {\n\t\t\t\tfieldVersions = await this.store.getRecordFieldVersions(op.collection, op.recordId)\n\t\t\t} catch {\n\t\t\t\t// Fall back to a single whole-row stamp below.\n\t\t\t}\n\t\t}\n\t\t// W7 / RT-29 (B2): the record's fold state rides on the entry (filtered to its fields).\n\t\tconst foldState = await this.store\n\t\t\t.getRecordFoldState?.(op.collection, op.recordId)\n\t\t\t.catch(() => null)\n\t\tlet timestamp = fieldVersions?.latest ?? op.timestamp\n\t\tif (!fieldVersions && this.store.getRecordLatestTimestamp) {\n\t\t\ttry {\n\t\t\t\ttimestamp =\n\t\t\t\t\t(await this.store.getRecordLatestTimestamp(op.collection, op.recordId)) ?? timestamp\n\t\t\t} catch {\n\t\t\t\t// Fall back to the trigger's timestamp: still at or above every field it wrote.\n\t\t\t}\n\t\t}\n\t\treturn buildScopeEntryOperation({\n\t\t\ttrigger: op,\n\t\t\trow: current,\n\t\t\tschema,\n\t\t\ttimestamp,\n\t\t\tfieldVersions,\n\t\t\tfoldState,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t})\n\t}\n\n\t/**\n\t * Read a record's current field values from the materialized store for scope /\n\t * query-subset backfill. Includes soft-deleted rows so a relayed delete (whose op\n\t * carries no fields) is still judged against the record's actual scope. Returns\n\t * undefined when the record cannot be read (never materialized, or no schema).\n\t */\n\tprivate async lookupRecordFields(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<MaterializedRecord | undefined> {\n\t\tconst cached = this.recordLookupCache?.get(recordCacheKey(collection, recordId))\n\t\tif (cached !== undefined) return cached ?? undefined\n\t\ttry {\n\t\t\tconst rows = await this.store.queryCollection(collection, {\n\t\t\t\twhere: { id: recordId },\n\t\t\t\tincludeDeleted: true,\n\t\t\t\tlimit: 1,\n\t\t\t})\n\t\t\treturn rows[0]\n\t\t} catch {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tprivate handleAwarenessUpdate(msg: AwarenessUpdateMessage): void {\n\t\t// Relay awareness updates to the server for broadcasting to other clients.\n\t\t// Awareness is purely ephemeral -- no persistence.\n\t\tthis.onAwarenessUpdate?.(this.sessionId, msg)\n\t}\n\n\t/**\n\t * A Yjs doc-channel update is a write to a richtext field: the sender must be\n\t * allowed to write the stored record (same rule as operation uploads). The stored\n\t * row is handed to the relay so delivery can be limited to sessions whose download\n\t * scope contains the record.\n\t */\n\tprivate async handleYjsDocUpdate(msg: YjsDocUpdateMessage): Promise<void> {\n\t\tif (!this.onYjsDocUpdate) return\n\t\tconst stored = (await this.lookupRecordFields(msg.collection, msg.recordId)) ?? null\n\t\tconst decision = authorizeRecordWrite(msg.collection, msg.recordId, stored, this.uplinkScopes())\n\t\tif (!decision.allowed) {\n\t\t\tthis.logger?.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.yjs_update_rejected',\n\t\t\t\tsessionId: this.sessionId,\n\t\t\t\tnodeId: this.clientNodeId ?? undefined,\n\t\t\t\tdetails: { collection: msg.collection, recordId: msg.recordId, code: decision.code },\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t\tthis.onYjsDocUpdate(this.sessionId, msg, stored)\n\t}\n\n\t/** A legacy client's duplicate pair was stored (RT-37): count it and log it. */\n\tprivate recordLegacySequencePair(pair: LegacySequencePair): void {\n\t\tthis.legacySequencePairs += 1\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'warn',\n\t\t\tevent: 'session.legacy_sequence_pair',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId: pair.nodeId,\n\t\t\tdetails: {\n\t\t\t\toperationId: pair.operationId,\n\t\t\t\tsequenceNumber: pair.sequenceNumber,\n\t\t\t\tholderIds: pair.holderIds,\n\t\t\t\tlegacyWriter: pair.legacyWriter,\n\t\t\t\tmessage: pair.legacyWriter\n\t\t\t\t\t? 'A client without the sequenceReservation capability (Kora <= beta.12) uploaded a second operation under a held sequence number. Both are stored and delivered. Upgrade the client.'\n\t\t\t\t\t: 'An operation shares its sequence number with one stored before sequence enforcement (Kora <= beta.12). Both are stored.',\n\t\t\t},\n\t\t})\n\t}\n\n\tprivate sendError(code: string, message: string, retriable: boolean): void {\n\t\tconst errorMsg: SyncMessage = {\n\t\t\ttype: 'error',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(errorMsg)\n\t}\n\n\t/**\n\t * Reject one specific client operation, tied to its id, so the submitter can\n\t * divert it out of its pending queue into a durable rejected store rather than\n\t * losing it or retrying forever. The op is NOT materialized, so no other\n\t * replica ever sees it.\n\t */\n\tprivate sendOperationRejected(\n\t\top: Operation,\n\t\tcode: string,\n\t\tmessage: string,\n\t\tretriable: boolean,\n\t): void {\n\t\tconst rejectedMsg: SyncMessage = {\n\t\t\ttype: 'operation-rejected',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperationId: op.id,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(rejectedMsg)\n\t}\n\n\tprivate handleTransportClose(): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.clearSessionTimers()\n\t\tthis.flushOrphanedRelays()\n\t\tthis.emitter?.emit({ type: 'sync:disconnected', reason: 'transport closed' })\n\t\tthis.onClose?.(this.sessionId)\n\t}\n}\n\n/** Key of a record in the delivery chunk's prefetch cache. */\nfunction recordCacheKey(collection: string, recordId: string): string {\n\treturn `${collection}\\u0000${recordId}`\n}\n\n/**\n * One item of a session's delivery stream: a stored operation, a retraction of its\n * record, or a synthesized scope entry sharing the triggering operation's sequence.\n */\ntype DeliverableOperation = DeliveredOperation & { retraction?: boolean; scopeEntry?: boolean }\n\n/**\n * The wire format a serializer frames messages with: its own report when it has one, protobuf\n * for the fixed protobuf serializer, and JSON otherwise.\n */\nfunction framingWireFormat(serializer: MessageSerializer): WireFormat {\n\tif (typeof serializer.getWireFormat === 'function') return serializer.getWireFormat()\n\tif (serializer instanceof ProtobufMessageSerializer) return 'protobuf'\n\treturn 'json'\n}\n\n/** True when every identifier of `op` can be stored and looked up by every store (RT-65). */\nfunction operationIdentifiersStorable(op: Operation): boolean {\n\treturn (\n\t\tisStorableIdentifier(op.id) &&\n\t\tisStorableIdentifier(op.nodeId) &&\n\t\tisStorableIdentifier(op.collection) &&\n\t\tisStorableIdentifier(op.recordId) &&\n\t\t(Array.isArray(op.causalDeps) ? op.causalDeps.every(isStorableIdentifier) : true)\n\t)\n}\n","import { operationValueViolation } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\nimport { buildMergeRelationLookup, checkReferentialIntegrityOnDelete } from '@korajs/merge'\nimport type { SideEffectOp } from '@korajs/merge'\nimport type { ApplyResult } from '@korajs/sync'\nimport { enforceCrossRecordRules } from '../constraints/constraint-authority'\nimport { validateIncomingOperationConstraints } from '../constraints/operation-constraint-validator'\nimport { createServerReferentialContext } from '../constraints/server-referential-context'\nimport {\n\tUplinkAuthorizationError,\n\ttype UplinkAuthorizationResult,\n} from '../scopes/server-scope-filter'\nimport { serverOperationView } from '../store/record-fold'\nimport type { ApplyRemoteOptions, MaterializedRecord, ServerStore } from '../store/server-store'\nimport {\n\tSEQUENCE_CONFLICT_CODE,\n\tSequenceConflictError,\n\tUNSTORABLE_VALUE_CODE,\n\tUnstorableValueError,\n} from '../store/server-store'\nimport { validateIngestedOperation } from './ingest-validation'\nimport { type OperationRejection, isRetriableRejection } from './rejection-taxonomy'\nimport {\n\tcreateServerSideEffectOperation,\n\tnextServerSequenceNumber,\n} from './server-side-effect-operation'\n\nexport interface ApplyServerOperationResult {\n\t/** Result of applying the primary operation */\n\tresult: ApplyResult\n\t/** Primary op when applied, plus any server-generated side-effect operations */\n\tappliedOperations: Operation[]\n\t/** Rejection reason when the operation was not applied */\n\trejection?: OperationRejection\n\t/**\n\t * Side effects of an applied delete that were NOT derived because\n\t * {@link ApplyServerOperationOptions.isAuthoredSideEffect} claimed them (RT-69). The\n\t * caller must derive each one with {@link deriveServerSideEffects} unless the\n\t * author's own copy is stored.\n\t */\n\tdeferredSideEffects?: SideEffectOp[]\n}\n\n/**\n * Decides whether an untrusted writer may cause one referential side effect of its\n * delete. `effect` is the side effect shaped as the operation the server would\n * write; `stored` is the affected record as stored now (including soft-deleted).\n */\nexport type SideEffectAuthorizer = (\n\teffect: Operation,\n\tstored: MaterializedRecord | null,\n) => UplinkAuthorizationResult\n\n/** Rejection code for a delete refused because of related records (RT-10). */\nexport const RESTRICTED_REJECTION_CODE = 'RESTRICTED'\n\n/** Options for {@link applyServerOperation}. */\nexport interface ApplyServerOperationOptions {\n\t/**\n\t * Uplink authorization for an untrusted writer, re-evaluated by the store inside\n\t * its apply critical section against the row as stored at commit time (see\n\t * `ApplyRemoteOptions.authorize`). A refusal becomes a non-retriable rejection and\n\t * nothing is written.\n\t */\n\tauthorize?: ApplyRemoteOptions['authorize']\n\t/**\n\t * Authorization of the referential side effects (cascade delete, set-null) an\n\t * untrusted writer's delete would cause (RT-10). Every side effect is checked\n\t * against the writer's own scope BEFORE the delete is applied; if any falls\n\t * outside it, the whole delete is refused and nothing is written.\n\t *\n\t * Design: integrity is judged on ALL children, in every tenant (a restrict or a\n\t * cross-tenant cascade is never silently skipped, which would leave dangling\n\t * references), but the writer learns nothing about children it cannot see: a\n\t * restrict violation and an unauthorized side effect are refused with the same\n\t * generic `RESTRICTED` rejection, with no ids and no counts. Setting `authorize`\n\t * alone also switches restrict refusals to the generic form.\n\t */\n\tauthorizeSideEffect?: SideEffectAuthorizer\n\t/**\n\t * The writer is a legacy client that does not reserve sequence numbers (RT-37): a\n\t * different operation under a held `(nodeId, sequenceNumber)` is stored as a legacy\n\t * pair instead of being refused with `SEQUENCE_CONFLICT`. Applies to the primary\n\t * operation only; server-originated side effects are always enforced.\n\t */\n\tlegacySequenceWriter?: boolean\n\t/** See `ApplyRemoteOptions.onLegacySequencePair`; for the primary operation. */\n\tonLegacySequencePair?: ApplyRemoteOptions['onLegacySequencePair']\n\t/**\n\t * True for a referential side effect of this delete that the writer authored itself\n\t * (its own cascade or set-null, later in the same upload, RT-69). Such an effect is\n\t * not derived now but returned in `deferredSideEffects`, so the log stores one copy\n\t * per child instead of the author's and the server's. Effects it does not claim (a\n\t * child the author did not know, a legacy client that authors no cascades) are\n\t * derived as before.\n\t */\n\tisAuthoredSideEffect?: (effect: SideEffectOp) => boolean\n\t/**\n\t * The operation as the server schema reads it (transforms at fold time, RT-84), when\n\t * the caller already computed it. Shape, constraint and referential checks judge the\n\t * view; the store keeps `op` exactly as given and folds the same view. Default: the\n\t * store's own view (`serverOperationView`).\n\t */\n\tview?: Operation\n}\n\n/**\n * Applies an incoming client operation with Tier 2 constraints and referential integrity.\n * Cascade/set-null side effects are persisted as server-originated operations in the op log.\n *\n * @param store - The server store\n * @param op - The operation to apply\n * @param relationLookup - Optional precomputed relation lookup\n * @param options - Optional in-store authorization for untrusted writers\n * @returns The apply result, applied operations, and rejection (if any)\n */\nexport async function applyServerOperation(\n\tstore: ServerStore,\n\top: Operation,\n\trelationLookup?: ReturnType<typeof buildMergeRelationLookup>,\n\toptions: ApplyServerOperationOptions = {},\n): Promise<ApplyServerOperationResult> {\n\t// Every ingest path (sync, route kora.apply, applyLocalOperation) validates the\n\t// timestamp against server time and the sequence number (SYNC-7, SRV-4).\n\tconst ingest = validateIngestedOperation(op)\n\tif (!ingest.valid) {\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: { code: ingest.code, message: ingest.message, retriable: false },\n\t\t}\n\t}\n\n\tconst schema = store.getSchema()\n\tconst lookup = relationLookup ?? (schema ? buildMergeRelationLookup(schema) : new Map())\n\n\t// Everything below judges the operation as the server schema reads it; only the\n\t// store write (applyPrimary) and the relayed operation are the stored original.\n\tconst stored = op\n\tlet view: Operation | null\n\ttry {\n\t\tview = options.view ?? serverOperationView(store, stored)\n\t} catch (error) {\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode: 'SCHEMA_TRANSFORM_INVALID',\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\tretriable: false,\n\t\t\t},\n\t\t}\n\t}\n\tif (view === null) {\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode: 'SCHEMA_TRANSFORM_UNAVAILABLE',\n\t\t\t\tmessage: `Operation \"${stored.id}\" cannot be transformed from schema v${stored.schemaVersion} to the server schema.`,\n\t\t\t\tretriable: false,\n\t\t\t},\n\t\t}\n\t}\n\treturn applyJudgedOperation(store, stored, view, lookup, schema, options)\n}\n\nasync function applyJudgedOperation(\n\tstore: ServerStore,\n\tstored: Operation,\n\top: Operation,\n\tlookup: ReturnType<typeof buildMergeRelationLookup>,\n\tschema: ReturnType<ServerStore['getSchema']>,\n\toptions: ApplyServerOperationOptions,\n): Promise<ApplyServerOperationResult> {\n\tconst shapeCheck = validateOperationShape(op, schema)\n\tif (!shapeCheck.valid) {\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode: shapeCheck.code ?? 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\tmessage: shapeCheck.message ?? `Operation \"${op.id}\" does not match the server schema`,\n\t\t\t\tretriable: false,\n\t\t\t},\n\t\t}\n\t}\n\n\tconst constraintCheck = await validateIncomingOperationConstraints(store, op, schema)\n\tif (!constraintCheck.valid) {\n\t\tconst code = constraintCheck.code ?? 'CONSTRAINT_VIOLATION'\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode,\n\t\t\t\tmessage: constraintCheck.message ?? `Operation \"${op.id}\" violates a schema constraint`,\n\t\t\t\tretriable: isRetriableRejection(code),\n\t\t\t},\n\t\t}\n\t}\n\n\tif (op.type === 'delete' && schema) {\n\t\tconst refCtx = createServerReferentialContext(store)\n\t\tconst referential = await checkReferentialIntegrityOnDelete(op, schema, refCtx, lookup)\n\n\t\tconst untrusted = options.authorize !== undefined || options.authorizeSideEffect !== undefined\n\t\tif (!referential.allowed) {\n\t\t\tif (untrusted) return restrictedRejection(op)\n\t\t\treturn {\n\t\t\t\tresult: 'skipped',\n\t\t\t\tappliedOperations: [],\n\t\t\t\trejection: {\n\t\t\t\t\tcode: 'REFERENTIAL_INTEGRITY',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" violates referential integrity on \"${op.collection}\"`,\n\t\t\t\t\tretriable: isRetriableRejection('REFERENTIAL_INTEGRITY'),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\t// An untrusted writer may only cause side effects inside its own scope: a\n\t\t// cascade must never delete (or null) another tenant's records (RT-10).\n\t\tif (options.authorizeSideEffect) {\n\t\t\tfor (const effect of referential.sideEffectOps) {\n\t\t\t\tconst stored = await readStoredRow(store, effect.collection, effect.recordId)\n\t\t\t\tconst probe: Operation = {\n\t\t\t\t\t...op,\n\t\t\t\t\tid: `${op.id}:side-effect:${effect.collection}:${effect.recordId}`,\n\t\t\t\t\ttype: effect.type === 'delete' ? 'delete' : 'update',\n\t\t\t\t\tcollection: effect.collection,\n\t\t\t\t\trecordId: effect.recordId,\n\t\t\t\t\tdata: effect.data,\n\t\t\t\t\tpreviousData: effect.previousData,\n\t\t\t\t\tcausalDeps: [op.id],\n\t\t\t\t}\n\t\t\t\tif (!options.authorizeSideEffect(probe, stored).allowed) {\n\t\t\t\t\treturn restrictedRejection(op)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet primaryResult: Awaited<ReturnType<ServerStore['applyRemoteOperation']>>\n\t\ttry {\n\t\t\tprimaryResult = await applyPrimary(store, stored, options)\n\t\t} catch (error) {\n\t\t\tconst rejection = authorizationRejection(error)\n\t\t\tif (rejection) return { result: 'skipped', appliedOperations: [], rejection }\n\t\t\tthrow error\n\t\t}\n\t\tif (primaryResult !== 'applied') {\n\t\t\treturn { result: primaryResult, appliedOperations: [] }\n\t\t}\n\n\t\tconst appliedOperations: Operation[] = [stored]\n\t\tconst deferred: SideEffectOp[] = []\n\t\tconst derive: SideEffectOp[] = []\n\t\tfor (const effect of referential.sideEffectOps) {\n\t\t\tif (options.isAuthoredSideEffect?.(effect)) deferred.push(effect)\n\t\t\telse derive.push(effect)\n\t\t}\n\t\tappliedOperations.push(...(await deriveServerSideEffects(store, op, derive)))\n\t\tappliedOperations.push(...(await enforceAfterCommit(store, op)))\n\n\t\treturn {\n\t\t\tresult: 'applied',\n\t\t\tappliedOperations,\n\t\t\t...(deferred.length > 0 ? { deferredSideEffects: deferred } : {}),\n\t\t}\n\t}\n\n\tlet result: Awaited<ReturnType<ServerStore['applyRemoteOperation']>>\n\ttry {\n\t\tresult = await applyPrimary(store, stored, options)\n\t} catch (error) {\n\t\tconst rejection = authorizationRejection(error)\n\t\tif (rejection) return { result: 'skipped', appliedOperations: [], rejection }\n\t\tthrow error\n\t}\n\tif (result !== 'applied') return { result, appliedOperations: [] }\n\treturn { result, appliedOperations: [stored, ...(await enforceAfterCommit(store, op))] }\n}\n\n/**\n * The referential side effects of an already stored delete that are still undone:\n * children that still reference the deleted record (cascade), or still hold its id\n * (set-null). Used when a delete arrives again as a stored duplicate (RT-73): an effect\n * deferred to the end of a batch that failed after the delete committed (or one the\n * author covered with a copy that was later refused) is found again here, so the\n * referential effect of a committed delete is never lost with an in-memory list.\n *\n * Effects the writer may not cause (`authorizeSideEffect`) are left out: the original\n * delete was only committed when every effect it had was authorized, so such an effect\n * belongs to a child added later, which the cascade-late correction covers.\n *\n * @param store - The server store\n * @param op - The stored delete (in the server's schema)\n * @param authorizeSideEffect - The writer's side-effect authorization, if untrusted\n * @returns The effects to derive (or to defer to the author's copies)\n */\nexport async function undoneSideEffectsOfStoredDelete(\n\tstore: ServerStore,\n\top: Operation,\n\tauthorizeSideEffect?: SideEffectAuthorizer,\n): Promise<SideEffectOp[]> {\n\tconst schema = store.getSchema()\n\tif (op.type !== 'delete' || !schema) return []\n\tconst lookup = buildMergeRelationLookup(schema)\n\tconst referential = await checkReferentialIntegrityOnDelete(\n\t\top,\n\t\tschema,\n\t\tcreateServerReferentialContext(store),\n\t\tlookup,\n\t)\n\tif (!authorizeSideEffect) return referential.sideEffectOps\n\tconst allowed: SideEffectOp[] = []\n\tfor (const effect of referential.sideEffectOps) {\n\t\tconst stored = await readStoredRow(store, effect.collection, effect.recordId)\n\t\tconst probe: Operation = {\n\t\t\t...op,\n\t\t\tid: `${op.id}:side-effect:${effect.collection}:${effect.recordId}`,\n\t\t\ttype: effect.type === 'delete' ? 'delete' : 'update',\n\t\t\tcollection: effect.collection,\n\t\t\trecordId: effect.recordId,\n\t\t\tdata: effect.data,\n\t\t\tpreviousData: effect.previousData,\n\t\t\tcausalDeps: [op.id],\n\t\t}\n\t\tif (authorizeSideEffect(probe, stored).allowed) allowed.push(effect)\n\t}\n\treturn allowed\n}\n\n/**\n * Store the server's own copy of referential side effects (cascade delete, set-null)\n * of the applied delete `parentOp`: deterministic ids and timestamps (see\n * {@link createServerSideEffectOperation}), so a retry or another instance writes the\n * same operations.\n *\n * @param store - The server store\n * @param parentOp - The applied delete\n * @param effects - Its side effects to derive\n * @returns The side-effect operations the store applied (to relay)\n */\nexport async function deriveServerSideEffects(\n\tstore: ServerStore,\n\tparentOp: Operation,\n\teffects: readonly SideEffectOp[],\n): Promise<Operation[]> {\n\tconst applied: Operation[] = []\n\tfor (const effect of effects) {\n\t\t// Allocate each side-effect's sequence number individually. On a store\n\t\t// that reserves atomically (Postgres), this keeps a concurrent conditional\n\t\t// apply from being handed the same server sequence number; on a serialized\n\t\t// store, each allocation reads the version vector the prior apply advanced.\n\t\tconst sideOp = await createServerSideEffectOperation(\n\t\t\tstore,\n\t\t\tparentOp,\n\t\t\teffect,\n\t\t\tparentOp.schemaVersion,\n\t\t\tnextServerSequenceNumber(store),\n\t\t)\n\t\tconst sideResult = await store.applyRemoteOperation(sideOp)\n\t\tif (sideResult === 'applied') applied.push(sideOp)\n\t}\n\treturn applied\n}\n\n/**\n * Whether `op` (an operation of the delete's author) is the author's own copy of the\n * side effect `effect` of the delete `parentId`: same record, causally after the\n * delete, with the same effect (a delete for a cascade; for a set-null, an update\n * writing null to every field the effect nulls). An encrypted update cannot be read,\n * so it never counts as a set-null copy.\n */\nexport function isAuthoredCopyOfSideEffect(\n\top: Operation,\n\tparentId: string,\n\teffect: SideEffectOp,\n): boolean {\n\tif (op.collection !== effect.collection || op.recordId !== effect.recordId) return false\n\tif (!op.causalDeps.includes(parentId)) return false\n\tif (effect.type === 'delete') return op.type === 'delete'\n\tif (op.type !== 'update' || op.encrypted !== undefined || !op.data) return false\n\tconst data = op.data\n\treturn Object.entries(effect.data ?? {}).every(\n\t\t([field, value]) => value === null && field in data && data[field] === null,\n\t)\n}\n\n/**\n * Re-check the cross-record rules the committed `op` touched and store the server's\n * corrections (W7 step 3; see `constraint-authority.ts`). A failure is logged, never\n * thrown: the operation itself is committed, and the next write to the record (or a\n * concurrent detector) re-checks.\n */\nasync function enforceAfterCommit(store: ServerStore, op: Operation): Promise<Operation[]> {\n\ttry {\n\t\treturn await enforceCrossRecordRules(store, op, () => nextServerSequenceNumber(store))\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`[kora] Cross-record rule check after operation \"${op.id}\" on ${op.collection}/${op.recordId} failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t)\n\t\treturn []\n\t}\n}\n\n/**\n * The generic refusal for a delete blocked by related records. It names only the\n * record the writer itself targeted: never the children, their ids or their count.\n */\nfunction restrictedRejection(op: Operation): ApplyServerOperationResult {\n\treturn {\n\t\tresult: 'skipped',\n\t\tappliedOperations: [],\n\t\trejection: {\n\t\t\tcode: RESTRICTED_REJECTION_CODE,\n\t\t\tmessage: `Deleting \"${op.collection}\" record \"${op.recordId}\" is restricted by related records. Remove or reassign them first.`,\n\t\t\tretriable: false,\n\t\t},\n\t}\n}\n\n/** The record as stored (including a soft-deleted one), or null when never written. */\nasync function readStoredRow(\n\tstore: ServerStore,\n\tcollection: string,\n\trecordId: string,\n): Promise<MaterializedRecord | null> {\n\tconst rows = await store.queryCollection(collection, {\n\t\twhere: { id: recordId },\n\t\tincludeDeleted: true,\n\t\tlimit: 1,\n\t})\n\treturn rows[0] ?? null\n}\n\nfunction applyPrimary(\n\tstore: ServerStore,\n\top: Operation,\n\toptions: ApplyServerOperationOptions,\n): ReturnType<ServerStore['applyRemoteOperation']> {\n\tconst storeOptions: ApplyRemoteOptions = {\n\t\t...(options.authorize ? { authorize: options.authorize } : {}),\n\t\t...(options.legacySequenceWriter ? { legacySequenceWriter: true } : {}),\n\t\t...(options.onLegacySequencePair ? { onLegacySequencePair: options.onLegacySequencePair } : {}),\n\t}\n\treturn Object.keys(storeOptions).length > 0\n\t\t? store.applyRemoteOperation(op, storeOptions)\n\t\t: store.applyRemoteOperation(op)\n}\n\n/**\n * Map an in-store refusal to a structured, non-retriable rejection: an authorization\n * refusal, or a sequence conflict (another operation holds the node and sequence).\n */\nfunction authorizationRejection(error: unknown): OperationRejection | null {\n\tif (error instanceof SequenceConflictError) {\n\t\treturn { code: SEQUENCE_CONFLICT_CODE, message: error.message, retriable: false }\n\t}\n\tif (error instanceof UnstorableValueError) {\n\t\treturn { code: UNSTORABLE_VALUE_CODE, message: error.message, retriable: false }\n\t}\n\tif (!(error instanceof UplinkAuthorizationError)) return null\n\treturn { code: error.rejectionCode, message: error.message, retriable: false }\n}\n\nfunction validateOperationShape(\n\top: Operation,\n\tschema: ReturnType<ServerStore['getSchema']>,\n): { valid: true } | { valid: false; code: string; message: string } {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tconst collection = schema.collections[op.collection]\n\tif (!collection) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'UNKNOWN_COLLECTION',\n\t\t\tmessage: `Operation \"${op.id}\" targets unknown collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst declaredFields = new Set(Object.keys(collection.fields))\n\tconst systemPreviousFields = new Set(['id', '_created_at', '_updated_at', '_deleted'])\n\tconst invalidDataField = firstInvalidField(op.data, declaredFields)\n\tif (invalidDataField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidDataField}\" in data for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst invalidPreviousField = firstInvalidField(\n\t\top.previousData,\n\t\tdeclaredFields,\n\t\tsystemPreviousFields,\n\t)\n\tif (invalidPreviousField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidPreviousField}\" in previousData for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\t// One value domain (core value-domain.ts, RT-86, RT-87): every value the server stores\n\t// must be one every server store holds unchanged and every client accepts. Checked on\n\t// the operation as the server schema reads it, before any store sees it, so a value\n\t// outside the domain is refused per operation (non-retriable) on every store alike,\n\t// never by a database half-way through a batch.\n\tif (op.data !== null && op.data !== undefined) {\n\t\tfor (const [field, value] of Object.entries(op.data)) {\n\t\t\tconst descriptor = collection.fields[field]\n\t\t\tif (!descriptor) continue\n\t\t\tconst violation = operationValueViolation(descriptor, value)\n\t\t\tif (violation !== null) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" writes a value outside the domain of \"${op.collection}.${field}\": it ${violation}.`,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (op.atomicOps) {\n\t\tfor (const field of Object.keys(op.atomicOps)) {\n\t\t\tif (!declaredFields.has(field)) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" contains undeclared atomic field \"${field}\" for collection \"${op.collection}\".`,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { valid: true }\n}\n\nfunction firstInvalidField(\n\tvalue: unknown,\n\tdeclaredFields: Set<string>,\n\textraAllowedFields?: Set<string>,\n): string | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\tif (typeof value !== 'object' || Array.isArray(value)) {\n\t\treturn null\n\t}\n\tfor (const field of Object.keys(value)) {\n\t\tif (!declaredFields.has(field) && !extraAllowedFields?.has(field)) {\n\t\t\treturn field\n\t\t}\n\t}\n\treturn null\n}\n","/**\n * Server authority over cross-record rules (W7 step 3).\n *\n * The fold merges ONE record. Rules that span records (Tier-2 `unique` and\n * `capacity` constraints, and referential `restrict` / `cascade` / `set-null`) cannot\n * be folded per record, so the server is their single authority:\n *\n * 1. **Ingest.** An operation that would create a violation against the committed\n * state is refused before it is stored (`validateIncomingOperationConstraints`,\n * judging the record as the fold would materialize it after the operation). A\n * refused operation never enters the log, so no replica folds it.\n * 2. **Race.** Two operations validated concurrently (two sessions, two server\n * instances) can both commit. After every commit, {@link enforceCrossRecordRules}\n * re-checks the written record against committed state and emits **corrections**:\n * ordinary operations authored by the server's node (so they win\n * `server-authoritative` fields and otherwise merge by HLC like any write).\n *\n * Corrections are deterministic: their ids come from `deriveServerOpId` (keyed with the deployment secret, RT-64) over the\n * losing write and the rule, and their timestamps and data are derived from the fold\n * state, so two detectors (two sessions, two instances, a retry) produce the same\n * operation, which the log stores once. Rule ids start with\n * {@link SERVER_RULE_PREFIX}, so they can never collide with a side effect a client\n * derives for its own copy (a client copy has different content: its own node,\n * clock and sequence; it is a separate operation whose effect is idempotent under\n * the fold).\n *\n * What a correction does (exactly one winner per conflict):\n * - **unique / capacity**: the conflicting group keeps one record, chosen by the\n * constraint's `onConflict` over the HLC of each record's write to the constrained\n * fields (`last-write-wins`: the newest; `priority-field`: the highest priority,\n * ties first-write-wins; every other strategy: the oldest, first-write-wins). Every\n * other record has its losing write undone on the constrained fields: the fields go\n * back to the values the record folds to without that write, or the record is\n * deleted when that write created it (or its old values would still conflict).\n * - **referential, child written under a deleted parent**: `cascade` deletes the child,\n * `set-null` clears its foreign key, `restrict` revives the parent (the delete loses:\n * it was only allowed because the reference was not committed yet).\n * - **referential, parent deleted while a restrict child is live**: the parent is\n * revived.\n * A revival is an update with empty data: it is a write (newer than the delete) that\n * changes no field, so the record comes back with every field's merged value.\n */\nimport {\n\tHybridLogicalClock,\n\tfoldRecord,\n\tisFoldStateLive,\n\tmaterialize,\n\toperationSchemaView,\n} from '@korajs/core'\nimport type {\n\tConstraint,\n\tFoldState,\n\tHLCTimestamp,\n\tOperation,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { checkConstraints } from '@korajs/merge'\nimport { deriveServerOpId } from '../apply/derive-server-op-id'\nimport type { MaterializedRecord, ServerStore } from '../store/server-store'\nimport { createServerConstraintContext } from './server-constraint-context'\n\n/** Prefix of every rule id the server derives side-effect and correction ids from. */\nexport const SERVER_RULE_PREFIX = 'server/'\n\n/** HLC logical counter bound (matches `HybridLogicalClock.serialize`). */\nconst MAX_LOGICAL = 99_999\n\n/**\n * The timestamp of a server operation that must order immediately after `base`:\n * same wall time, next logical tick, authored by `nodeId`. Deterministic (no wall\n * clock), so every detector derives the same one.\n */\nexport function timestampAfter(base: HLCTimestamp, nodeId: string): HLCTimestamp {\n\treturn base.logical < MAX_LOGICAL\n\t\t? { wallTime: base.wallTime, logical: base.logical + 1, nodeId }\n\t\t: { wallTime: base.wallTime + 1, logical: 0, nodeId }\n}\n\n/** Allocates the next sequence number of the server's node. */\nexport type ServerSequenceAllocator = () => number\n\ninterface CorrectionSpec {\n\tparent: string\n\trule: string\n\tcollection: string\n\trecordId: string\n\ttype: 'update' | 'delete'\n\tdata: Record<string, unknown> | null\n\tpreviousData: Record<string, unknown> | null\n\tafter: HLCTimestamp\n}\n\nasync function buildCorrection(\n\tstore: ServerStore,\n\tspec: CorrectionSpec,\n\tschemaVersion: number,\n\tnextSequence: ServerSequenceAllocator,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\treturn {\n\t\tid: await deriveServerOpId(\n\t\t\tstore,\n\t\t\tspec.parent,\n\t\t\t`${SERVER_RULE_PREFIX}${spec.rule}`,\n\t\t\tspec.recordId,\n\t\t),\n\t\tnodeId,\n\t\ttype: spec.type,\n\t\tcollection: spec.collection,\n\t\trecordId: spec.recordId,\n\t\tdata: spec.data,\n\t\tpreviousData: spec.previousData,\n\t\ttimestamp: timestampAfter(spec.after, nodeId),\n\t\tsequenceNumber: nextSequence(),\n\t\tcausalDeps: [],\n\t\tschemaVersion,\n\t\tmutationName: `kora:correction:${spec.rule}`,\n\t}\n}\n\nfunction stampTimestamp(stamp: { t: string } | null): HLCTimestamp | null {\n\treturn stamp ? HybridLogicalClock.deserialize(stamp.t) : null\n}\n\nfunction maxTimestamp(values: Array<HLCTimestamp | null | undefined>): HLCTimestamp | null {\n\tlet best: HLCTimestamp | null = null\n\tfor (const value of values) {\n\t\tif (value && (best === null || HybridLogicalClock.compare(value, best) > 0)) best = value\n\t}\n\treturn best\n}\n\n/** The HLC of a record's newest write to any of `fields` (its creation if none). */\nfunction constrainedVersion(versions: RecordFieldVersions, fields: string[]): HLCTimestamp {\n\treturn maxTimestamp(fields.map((field) => versions.fields[field])) ?? versions.created\n}\n\nfunction comparePriority(a: unknown, b: unknown): number {\n\tif (typeof a === 'number' && typeof b === 'number') return a - b\n\tconst left = String(a)\n\tconst right = String(b)\n\treturn left < right ? -1 : left > right ? 1 : 0\n}\n\ninterface GroupMember {\n\trow: MaterializedRecord\n\tversions: RecordFieldVersions\n\tkey: HLCTimestamp\n}\n\n/** Index of the surviving member of a conflicting group under `constraint`. */\nfunction chooseWinner(members: GroupMember[], constraint: Constraint): GroupMember {\n\tconst byStamp = (a: GroupMember, b: GroupMember): number =>\n\t\tHybridLogicalClock.compare(a.key, b.key) || (a.row.id < b.row.id ? -1 : 1)\n\tconst sorted = [...members].sort(byStamp)\n\tif (constraint.onConflict === 'last-write-wins') return sorted[sorted.length - 1] as GroupMember\n\tif (constraint.onConflict === 'priority-field' && constraint.priorityField) {\n\t\tconst field = constraint.priorityField\n\t\tlet best = sorted[0] as GroupMember\n\t\tfor (const member of sorted.slice(1)) {\n\t\t\tif (comparePriority(member.row[field], best.row[field]) > 0) best = member\n\t\t}\n\t\treturn best\n\t}\n\treturn sorted[0] as GroupMember\n}\n\nfunction groupWhere(\n\tconstraint: Constraint,\n\trow: MaterializedRecord,\n): Record<string, unknown> | null {\n\tconst where: Record<string, unknown> =\n\t\tconstraint.type === 'capacity' ? { ...constraint.where } : {}\n\tfor (const field of constraint.fields) {\n\t\tconst value = row[field]\n\t\t// A null value never conflicts (SQL UNIQUE semantics; the checker cannot match it).\n\t\tif (value === null || value === undefined) return null\n\t\twhere[field] = value\n\t}\n\treturn where\n}\n\n/**\n * The correction that undoes `loser`'s newest write to the constrained fields: its\n * fields go back to the values the record folds to without that write, or the record\n * is deleted when it would not exist without it (or the old values still collide with\n * the winner's).\n */\nasync function undoConstrainedWrite(\n\tstore: ServerStore,\n\tschema: SchemaDefinition,\n\tcollection: string,\n\tconstraintIndex: number,\n\tconstraint: Constraint,\n\tloser: GroupMember,\n\twinner: GroupMember,\n): Promise<CorrectionSpec | null> {\n\tconst ops = (await store.getRecordOperations?.(collection, loser.row.id)) ?? []\n\tconst state = await store.getRecordFoldState?.(collection, loser.row.id)\n\tconst newest = stampTimestamp(state?.u ?? null) ?? loser.key\n\tconst parent = `hlc:${HybridLogicalClock.serialize(loser.key)}`\n\tconst rule = `constraint:${collection}:${constraintIndex}:${constraint.type}`\n\t// Stored operations are judged and folded as the server schema reads them (RT-84).\n\tconst transforms = store.getOperationTransforms?.() ?? []\n\tconst losing = new Set(\n\t\tops\n\t\t\t.filter((stored) => {\n\t\t\t\tif (HybridLogicalClock.compare(stored.timestamp, loser.key) !== 0) return false\n\t\t\t\tconst op = operationSchemaView(stored, schema.version, transforms)\n\t\t\t\treturn (\n\t\t\t\t\top !== null &&\n\t\t\t\t\top.data !== null &&\n\t\t\t\t\tconstraint.fields.some((field) => op.data !== null && field in op.data)\n\t\t\t\t)\n\t\t\t})\n\t\t\t.map((op) => op.id),\n\t)\n\tconst without = foldRecord(ops, schema, { exclude: losing, transforms }).state\n\tconst previous = without && isFoldStateLive(without) ? materialize(without as FoldState) : null\n\tconst collides =\n\t\tprevious !== null &&\n\t\tconstraint.fields.every((field) => sameValue(previous[field], winner.row[field]))\n\tif (previous === null || collides) {\n\t\treturn {\n\t\t\tparent,\n\t\t\trule,\n\t\t\tcollection,\n\t\t\trecordId: loser.row.id,\n\t\t\ttype: 'delete',\n\t\t\tdata: null,\n\t\t\tpreviousData: null,\n\t\t\tafter: newest,\n\t\t}\n\t}\n\tconst data: Record<string, unknown> = {}\n\tconst previousData: Record<string, unknown> = {}\n\tfor (const field of constraint.fields) {\n\t\tdata[field] = previous[field] ?? null\n\t\tpreviousData[field] = loser.row[field] ?? null\n\t}\n\treturn {\n\t\tparent,\n\t\trule,\n\t\tcollection,\n\t\trecordId: loser.row.id,\n\t\ttype: 'update',\n\t\tdata,\n\t\tpreviousData,\n\t\tafter: newest,\n\t}\n}\n\nfunction sameValue(a: unknown, b: unknown): boolean {\n\treturn JSON.stringify(a ?? null) === JSON.stringify(b ?? null)\n}\n\n/** Corrections for unique / capacity constraints violated by the record `op` wrote. */\nasync function uniqueAndCapacityCorrections(\n\tstore: ServerStore,\n\tschema: SchemaDefinition,\n\top: Operation,\n): Promise<CorrectionSpec[]> {\n\tconst definition = schema.collections[op.collection]\n\tif (!definition || op.type === 'delete') return []\n\t// Only constraints the operation could have violated: it created the record or wrote\n\t// one of the constrained fields. A write elsewhere never \"fixes\" legacy data.\n\tconst crossRecord = definition.constraints.filter(\n\t\t(constraint) =>\n\t\t\t(constraint.type === 'unique' || constraint.type === 'capacity') &&\n\t\t\t(op.type === 'insert' ||\n\t\t\t\tconstraint.fields.some((field) => op.data !== null && field in op.data)),\n\t)\n\tif (crossRecord.length === 0 || !store.getRecordFieldVersions) return []\n\tconst row = await store.findRecord(op.collection, op.recordId)\n\tif (!row) return []\n\tconst violations = await checkConstraints(\n\t\trow,\n\t\top.recordId,\n\t\top.collection,\n\t\t{ ...definition, constraints: crossRecord },\n\t\tcreateServerConstraintContext(store),\n\t)\n\tconst specs: CorrectionSpec[] = []\n\tfor (const violation of violations) {\n\t\tconst constraint = violation.constraint\n\t\tconst index = definition.constraints.indexOf(constraint)\n\t\tconst where = groupWhere(constraint, row)\n\t\tif (!where) continue\n\t\tconst rows = await store.queryCollection(op.collection, { where })\n\t\tconst members: GroupMember[] = []\n\t\tfor (const candidate of rows) {\n\t\t\tconst versions = await store.getRecordFieldVersions(op.collection, candidate.id)\n\t\t\tif (!versions) continue\n\t\t\tmembers.push({\n\t\t\t\trow: candidate,\n\t\t\t\tversions,\n\t\t\t\tkey: constrainedVersion(versions, constraint.fields),\n\t\t\t})\n\t\t}\n\t\tif (members.length < 2) continue\n\t\tconst winner = chooseWinner(members, constraint)\n\t\tfor (const member of members) {\n\t\t\tif (member === winner) continue\n\t\t\tconst spec = await undoConstrainedWrite(\n\t\t\t\tstore,\n\t\t\t\tschema,\n\t\t\t\top.collection,\n\t\t\t\tindex,\n\t\t\t\tconstraint,\n\t\t\t\tmember,\n\t\t\t\twinner,\n\t\t\t)\n\t\t\tif (spec) specs.push(spec)\n\t\t}\n\t}\n\treturn specs\n}\n\n/** Corrections for referential rules involving the record `op` wrote. */\nasync function referentialCorrections(\n\tstore: ServerStore,\n\tschema: SchemaDefinition,\n\top: Operation,\n): Promise<CorrectionSpec[]> {\n\tif (!store.getRecordFoldState) return []\n\tconst specs: CorrectionSpec[] = []\n\tconst relations = Object.entries(schema.relations ?? {}).sort(([a], [b]) => (a < b ? -1 : 1))\n\n\tif (op.type !== 'delete') {\n\t\t// The written record as a child: does it reference a deleted parent?\n\t\tconst child = await store.findRecord(op.collection, op.recordId)\n\t\tif (child) {\n\t\t\tfor (const [name, relation] of relations) {\n\t\t\t\tif (relation.from !== op.collection || relation.onDelete === 'no-action') continue\n\t\t\t\t// Only a write that created the child or set its reference.\n\t\t\t\tif (op.type !== 'insert' && !(op.data !== null && relation.field in op.data)) continue\n\t\t\t\tconst parentId = child[relation.field]\n\t\t\t\tif (typeof parentId !== 'string' || parentId.length === 0) continue\n\t\t\t\tconst parent = await store.getRecordFoldState(relation.to, parentId)\n\t\t\t\tif (!parent || parent.cr === null || isFoldStateLive(parent)) continue\n\t\t\t\tconst deletedAt = stampTimestamp(parent.d)\n\t\t\t\tconst childState = await store.getRecordFoldState(op.collection, op.recordId)\n\t\t\t\tconst after = maxTimestamp([deletedAt, stampTimestamp(childState?.u ?? null)])\n\t\t\t\tif (!after || !parent.d) continue\n\t\t\t\t// Keyed on the parent's delete AND the child's newest write: a later revival\n\t\t\t\t// of the child under the same deleted parent gets a fresh correction.\n\t\t\t\tconst parentKey = `${parent.d.o}|${childState?.u?.o ?? op.id}`\n\t\t\t\tif (relation.onDelete === 'cascade') {\n\t\t\t\t\tspecs.push({\n\t\t\t\t\t\tparent: parentKey,\n\t\t\t\t\t\trule: `relation:${name}:cascade-late`,\n\t\t\t\t\t\tcollection: op.collection,\n\t\t\t\t\t\trecordId: op.recordId,\n\t\t\t\t\t\ttype: 'delete',\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\tpreviousData: null,\n\t\t\t\t\t\tafter,\n\t\t\t\t\t})\n\t\t\t\t} else if (relation.onDelete === 'set-null') {\n\t\t\t\t\tspecs.push({\n\t\t\t\t\t\tparent: parentKey,\n\t\t\t\t\t\trule: `relation:${name}:set-null-late`,\n\t\t\t\t\t\tcollection: op.collection,\n\t\t\t\t\t\trecordId: op.recordId,\n\t\t\t\t\t\ttype: 'update',\n\t\t\t\t\t\tdata: { [relation.field]: null },\n\t\t\t\t\t\tpreviousData: { [relation.field]: parentId },\n\t\t\t\t\t\tafter,\n\t\t\t\t\t})\n\t\t\t\t} else if (relation.onDelete === 'restrict') {\n\t\t\t\t\tconst parentAfter = maxTimestamp([deletedAt, stampTimestamp(parent.u)])\n\t\t\t\t\tif (!parentAfter) continue\n\t\t\t\t\tspecs.push({\n\t\t\t\t\t\tparent: `${parent.d.o}`,\n\t\t\t\t\t\trule: `relation:${name}:restrict-revive`,\n\t\t\t\t\t\tcollection: relation.to,\n\t\t\t\t\t\trecordId: parentId,\n\t\t\t\t\t\ttype: 'update',\n\t\t\t\t\t\tdata: {},\n\t\t\t\t\t\tpreviousData: null,\n\t\t\t\t\t\tafter: parentAfter,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn specs\n\t}\n\n\t// The deleted record as a parent: a restrict child committed concurrently.\n\tconst deleted = await store.getRecordFoldState(op.collection, op.recordId)\n\tif (!deleted || deleted.cr === null || isFoldStateLive(deleted) || !deleted.d) return specs\n\tfor (const [name, relation] of relations) {\n\t\tif (relation.to !== op.collection || relation.onDelete !== 'restrict') continue\n\t\tconst children = await store.queryCollection(relation.from, {\n\t\t\twhere: { [relation.field]: op.recordId },\n\t\t\tlimit: 1,\n\t\t})\n\t\tif (children.length === 0) continue\n\t\tconst after = maxTimestamp([stampTimestamp(deleted.d), stampTimestamp(deleted.u)])\n\t\tif (!after) continue\n\t\tspecs.push({\n\t\t\tparent: deleted.d.o,\n\t\t\trule: `relation:${name}:restrict-revive`,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\ttype: 'update',\n\t\t\tdata: {},\n\t\t\tpreviousData: null,\n\t\t\tafter,\n\t\t})\n\t}\n\treturn specs\n}\n\n/**\n * Re-check the cross-record rules touched by a committed operation and apply the\n * corrections they need (see the module comment for the contract). Returns the\n * corrections this call stored (a correction another detector already stored is a\n * duplicate and is not returned).\n *\n * @param store - The server store (the operation is already committed)\n * @param op - The committed operation\n * @param nextSequence - Allocates the server node's next sequence number\n */\nexport async function enforceCrossRecordRules(\n\tstore: ServerStore,\n\top: Operation,\n\tnextSequence: ServerSequenceAllocator,\n): Promise<Operation[]> {\n\tconst schema = store.getSchema()\n\tconst definition = schema?.collections[op.collection]\n\tif (!schema || !definition) return []\n\tconst involved =\n\t\tdefinition.constraints.some((c) => c.type === 'unique' || c.type === 'capacity') ||\n\t\tObject.values(schema.relations ?? {}).some(\n\t\t\t(relation) => relation.from === op.collection || relation.to === op.collection,\n\t\t)\n\tif (!involved) return []\n\tconst specs = [\n\t\t...(await uniqueAndCapacityCorrections(store, schema, op)),\n\t\t...(await referentialCorrections(store, schema, op)),\n\t]\n\tconst applied: Operation[] = []\n\tconst seen = new Set<string>()\n\tfor (const spec of specs) {\n\t\tconst correction = await buildCorrection(store, spec, op.schemaVersion, nextSequence)\n\t\tif (seen.has(correction.id)) continue\n\t\tseen.add(correction.id)\n\t\tif ((await store.applyRemoteOperation(correction)) === 'applied') applied.push(correction)\n\t}\n\treturn applied\n}\n","import { deriveSideEffectOpId } from '@korajs/core'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Id of a server-derived operation (cascade, set-null, constraint correction). The\n * built-in stores key it with the deployment's persisted secret (RT-64): every instance\n * derives the same id for the same effect, and no client can predict it, so no client\n * operation can occupy it first and make the store drop the server's as a duplicate.\n * A third-party store without `deriveServerOperationId` gets the unkeyed derivation.\n */\nexport async function deriveServerOpId(\n\tstore: ServerStore,\n\tparentOpId: string,\n\truleId: string,\n\ttargetRecordId: string,\n): Promise<string> {\n\tif (store.deriveServerOperationId) {\n\t\treturn store.deriveServerOperationId(parentOpId, ruleId, targetRecordId)\n\t}\n\treturn deriveSideEffectOpId(parentOpId, ruleId, targetRecordId)\n}\n","import type { ConstraintContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for Tier 2 constraint checks.\n */\nexport function createServerConstraintContext(store: ServerStore): ConstraintContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync countRecords(collection: string, where: Record<string, unknown>): Promise<number> {\n\t\t\treturn store.countCollection(collection, where)\n\t\t},\n\t}\n}\n","import type { Operation, SchemaDefinition } from '@korajs/core'\nimport { checkConstraints } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\nimport { createServerConstraintContext } from './server-constraint-context'\n\nexport interface OperationConstraintValidation {\n\tvalid: boolean\n\tcode?: string\n\tmessage?: string\n}\n\n/**\n * Validates an incoming operation against Tier 2 schema constraints on the server.\n * Deletes are skipped (removal cannot violate capacity/unique on the deleted row).\n */\nexport async function validateIncomingOperationConstraints(\n\tstore: ServerStore,\n\top: Operation,\n\tschema: SchemaDefinition | null,\n): Promise<OperationConstraintValidation> {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tif (op.type === 'delete') {\n\t\treturn { valid: true }\n\t}\n\n\tconst collectionDef = schema.collections[op.collection]\n\tif (!collectionDef || collectionDef.constraints.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst candidate = await projectCandidateRecord(store, op)\n\tif (candidate === null) {\n\t\treturn { valid: true }\n\t}\n\n\tconst ctx = createServerConstraintContext(store)\n\tconst violations = await checkConstraints(\n\t\tcandidate,\n\t\top.recordId,\n\t\top.collection,\n\t\tcollectionDef,\n\t\tctx,\n\t)\n\n\tif (violations.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst first = violations[0]\n\tif (first === undefined) {\n\t\treturn { valid: true }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tcode: 'CONSTRAINT_VIOLATION',\n\t\tmessage: first.message,\n\t}\n}\n\nasync function projectCandidateRecord(\n\tstore: ServerStore,\n\top: Operation,\n): Promise<Record<string, unknown> | null> {\n\tif (op.data === null) {\n\t\treturn null\n\t}\n\n\t// W7: the record exactly as the fold would materialize it after the operation (a\n\t// write that loses last-write-wins, an array delta, a counter...). Null when the\n\t// record would not be live, which nothing can violate.\n\tif (store.previewOperation) {\n\t\tconst preview = await store.previewOperation(op)\n\t\treturn preview ? { ...preview, id: op.recordId } : null\n\t}\n\n\tconst existing = await store.findRecord(op.collection, op.recordId)\n\tconst base = existing ? { ...existing } : {}\n\n\tif (op.type === 'insert') {\n\t\treturn { ...op.data, id: op.recordId }\n\t}\n\n\treturn { ...base, ...op.data, id: op.recordId }\n}\n","import type { ReferentialMergeContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for referential integrity checks.\n */\nexport function createServerReferentialContext(store: ServerStore): ReferentialMergeContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync recordExists(collection: string, recordId: string): Promise<boolean> {\n\t\t\tconst row = await store.findRecord(collection, recordId)\n\t\t\treturn row !== null && row._deleted !== 1\n\t\t},\n\t}\n}\n","import { HybridLogicalClock } from '@korajs/core'\nimport type { HLCTimestamp, Operation } from '@korajs/core'\nimport type { SideEffectOp } from '@korajs/merge'\nimport { SERVER_RULE_PREFIX, timestampAfter } from '../constraints/constraint-authority'\nimport type { ServerStore } from '../store/server-store'\nimport { deriveServerOpId } from './derive-server-op-id'\n\n/**\n * Converts a merge-package referential side effect (cascade delete, set-null) of\n * `parentOp` into a server-originated operation.\n *\n * Deterministic (W7 step 3): the id is `deriveServerOpId(store, parent, rule, target)` (keyed, RT-64)\n * with rule `server/relation:<relation>:<policy>`, and the timestamp is the parent's\n * next HLC tick on the server's node, never the wall clock. Every server instance,\n * session or retry that generates the effect of the same parent on the same record\n * produces the same id, so the log stores it once. The `server/` rule namespace keeps\n * it distinct from a copy a client derives for its own cascade (different node,\n * clock and sequence): both are stored, and the fold makes them idempotent in effect\n * (two deletes of a record, two writes of null).\n *\n * The timestamp sits immediately after the parent's, so a write that is causally\n * later than the delete (for example re-pointing the child to another parent) still\n * wins over the server's copy, exactly as it wins over the client's.\n */\nexport async function createServerSideEffectOperation(\n\tstore: ServerStore,\n\tparentOp: Operation,\n\teffect: SideEffectOp,\n\tschemaVersion: number,\n\tsequenceNumber: number,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\tconst policy = effect.type === 'delete' ? 'cascade' : 'set-null'\n\treturn {\n\t\tid: await deriveServerOpId(\n\t\t\tstore,\n\t\t\tparentOp.id,\n\t\t\t`${SERVER_RULE_PREFIX}relation:${effect.relationName}:${policy}`,\n\t\t\teffect.recordId,\n\t\t),\n\t\tnodeId,\n\t\ttype: effect.type === 'delete' ? 'delete' : 'update',\n\t\tcollection: effect.collection,\n\t\trecordId: effect.recordId,\n\t\tdata: effect.data,\n\t\tpreviousData: effect.previousData,\n\t\ttimestamp: timestampAfter(parentOp.timestamp, nodeId),\n\t\tsequenceNumber,\n\t\tcausalDeps: [parentOp.id],\n\t\tschemaVersion,\n\t\tmutationName: `kora:side-effect:${policy}`,\n\t}\n}\n\n/**\n * Allocate the next sequence number for server-originated operations.\n */\nexport function nextServerSequenceNumber(store: ServerStore): number {\n\t// Prefer the store's atomic reservation when it serves writes concurrently (the\n\t// Postgres conditional path), so two in-flight server operations never collide on\n\t// a sequence number. Serialized stores fall back to the version vector, which is\n\t// safe because only one server operation is ever in flight at a time.\n\tif (store.reserveSequenceNumber) {\n\t\treturn store.reserveSequenceNumber()\n\t}\n\t// Serialized stores: never hand out the same number twice, even when several\n\t// operations are built before any is applied (a conditional route set prepares all\n\t// of its mutations first). The store refuses a second operation under one sequence\n\t// number (SEQUENCE_CONFLICT), so the reservation must run ahead of the vector.\n\tconst nodeId = store.getNodeId()\n\tconst current = store.getVersionVector().get(nodeId) ?? 0\n\tconst next = Math.max(current, reservedServerSequence.get(store) ?? 0) + 1\n\treservedServerSequence.set(store, next)\n\treturn next\n}\n\n/** Highest server sequence number handed out per store (serialized stores only). */\nconst reservedServerSequence = new WeakMap<ServerStore, number>()\n\n/** The clock of each store's server node (see {@link serverClock}). */\nconst serverClocks = new WeakMap<ServerStore, HybridLogicalClock>()\n\n/**\n * The one hybrid logical clock of a store's server node, for server-authored writes\n * (route mutations). One clock per store, never a fresh one per write: two writes in\n * the same millisecond must get increasing timestamps, because the fold orders a\n * record's writes by HLC (then op id), not by arrival. With `after`, the clock is first\n * advanced past that timestamp (the newest write the caller read), so the new write\n * sorts after every write it was based on.\n *\n * @param store - The server store whose node authors the write\n * @param after - The newest timestamp the write must follow, if any\n */\nexport function serverClock(store: ServerStore, after?: HLCTimestamp | null): HybridLogicalClock {\n\tlet clock = serverClocks.get(store)\n\tif (!clock) {\n\t\tclock = new HybridLogicalClock(store.getNodeId())\n\t\tserverClocks.set(store, clock)\n\t}\n\tif (after) clock.advanceTo(after)\n\treturn clock\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Auth provider that accepts all connections.\n * Returns a default anonymous context for any token.\n * Useful for development and testing.\n */\nexport class NoAuthProvider implements AuthProvider {\n\tasync authenticate(_token: string): Promise<AuthContext> {\n\t\treturn { userId: 'anonymous' }\n\t}\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type {\n\tEncryptionKeyPutMessage,\n\tEncryptionKeyRequestMessage,\n\tEncryptionKeyResponseMessage,\n\tWrappedKeyRecord,\n} from '@korajs/sync'\nimport {\n\tMAX_KEY_RECORD_BYTES,\n\tisKeyRecordSuccessor,\n\tisValidKeyringName,\n\tvalidateKeyRecord,\n} from '@korajs/sync'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Owner of the shared keyring of a server without authentication. Every client of\n * such a server shares one data space, so it shares one keyring too.\n */\nexport const ANONYMOUS_KEY_OWNER = '*'\n\n/** Storage owner key of an authenticated user. */\nexport function userKeyOwner(userId: string): string {\n\treturn `u:${userId}`\n}\n\n/** Maximum key ids reported with a missing record (RT-104). */\nconst KNOWN_KEY_IDS_LIMIT = 16\n\n/**\n * The node-claim owner whose operations belong to a key owner: the user id of `u:<id>`,\n * or null (every node) for the shared anonymous owner.\n */\nfunction nodeOwnerOf(owner: string): string | null {\n\tif (owner === ANONYMOUS_KEY_OWNER) return null\n\treturn owner.startsWith('u:') ? owner.slice(2) : owner\n}\n\n/** Outcome of one key-service message. */\nexport interface KeyServiceOutcome {\n\tresponse: EncryptionKeyResponseMessage\n\t/** The record written, when the message was a successful write (to push to siblings). */\n\twritten: WrappedKeyRecord | null\n}\n\n/**\n * The sync server's key service (ENC-1, decision D4b). Stores each owner's wrapped key\n * record and serves it back. It never sees a passphrase or a data key: a record is\n * salt, KDF parameters, AES-GCM-wrapped data keys, key ids and versions.\n *\n * Rules it enforces:\n * - **Owner from the session only.** The owner is the session's authenticated\n * principal (or the shared anonymous owner on a server without auth); a message\n * cannot name a user, so no session reads or writes another user's record.\n * - **Compare-and-set.** A write names the revision it replaces; a concurrent write\n * loses with `conflict` and the current record, so two devices that both create a\n * first key converge on one.\n * - **History is append-only.** A write must raise the revision, keep the ring id and\n * every key version (same key id), so no device can make old operations unreadable\n * for the others. A first write (or a re-upload after the record was lost) keeps the\n * revision it carries, since devices refuse revisions below the one they accepted.\n * - **Lost records are visible.** A fetch with no record reports key ids of the owner's\n * stored encrypted operations, so a new device waits for one holding the ring.\n *\n * It cannot check the record MAC or that wraps open (only a holder of the ring's master\n * key can): devices authenticate every record themselves and act on nothing else. A\n * principal can still overwrite its own record with garbage; devices refuse it and\n * keep their keys.\n */\nexport class EncryptionKeyService {\n\tconstructor(private readonly store: ServerStore) {}\n\n\t/** Whether the store can persist key records (all built-in stores can). */\n\tisSupported(): boolean {\n\t\treturn (\n\t\t\ttypeof this.store.getEncryptionKeyRecord === 'function' &&\n\t\t\ttypeof this.store.putEncryptionKeyRecord === 'function'\n\t\t)\n\t}\n\n\t/**\n\t * Answer one key-service message for `owner`.\n\t *\n\t * @param owner - The session's owner key, or null when the session may not hold keys\n\t * @param message - A request or a write\n\t */\n\tasync handle(\n\t\towner: string | null,\n\t\tmessage: EncryptionKeyRequestMessage | EncryptionKeyPutMessage,\n\t): Promise<KeyServiceOutcome> {\n\t\tconst reply = (\n\t\t\tstatus: EncryptionKeyResponseMessage['status'],\n\t\t\trecord: WrappedKeyRecord | null,\n\t\t\ttext?: string,\n\t\t): KeyServiceOutcome => ({\n\t\t\tresponse: {\n\t\t\t\ttype: 'encryption-key-response',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\trequestId: message.requestId,\n\t\t\t\tkeyring: message.keyring,\n\t\t\t\tstatus,\n\t\t\t\trecord,\n\t\t\t\t...(text ? { message: text } : {}),\n\t\t\t},\n\t\t\twritten: null,\n\t\t})\n\t\tif (!isValidKeyringName(message.keyring)) {\n\t\t\treturn reply('invalid', null, 'Keyring names are 1-128 characters of [A-Za-z0-9._:-].')\n\t\t}\n\t\tif (owner === null) {\n\t\t\treturn reply(\n\t\t\t\t'forbidden',\n\t\t\t\tnull,\n\t\t\t\t'Encryption keys belong to a signed-in user: an anonymous session cannot read or write them.',\n\t\t\t)\n\t\t}\n\t\tconst getRecord = this.store.getEncryptionKeyRecord?.bind(this.store)\n\t\tconst putRecord = this.store.putEncryptionKeyRecord?.bind(this.store)\n\t\tif (!getRecord || !putRecord) {\n\t\t\treturn reply(\n\t\t\t\t'unsupported',\n\t\t\t\tnull,\n\t\t\t\t'This server store cannot persist encryption key records. Use a built-in store (memory, SQLite, Postgres) or implement getEncryptionKeyRecord/putEncryptionKeyRecord.',\n\t\t\t)\n\t\t}\n\t\tconst current = await this.read(owner, message.keyring)\n\t\tif (message.type === 'encryption-key-request') {\n\t\t\tconst outcome = reply('ok', current)\n\t\t\tif (current === null) {\n\t\t\t\toutcome.response.knownKeyIds = await this.knownKeyIds(owner, message.keyring)\n\t\t\t}\n\t\t\treturn outcome\n\t\t}\n\n\t\tconst json = JSON.stringify(message.record)\n\t\tif (json.length > MAX_KEY_RECORD_BYTES) {\n\t\t\treturn reply('invalid', current, `A key record is limited to ${MAX_KEY_RECORD_BYTES} bytes.`)\n\t\t}\n\t\tconst validation = validateKeyRecord(message.record, message.keyring)\n\t\tif (!validation.ok) {\n\t\t\treturn reply('invalid', current, `Malformed key record: ${validation.reason}.`)\n\t\t}\n\t\tif (!Number.isSafeInteger(message.expectedRevision) || message.expectedRevision < 0) {\n\t\t\treturn reply('invalid', current, 'expectedRevision must be a non-negative integer.')\n\t\t}\n\t\tif ((current?.revision ?? 0) !== message.expectedRevision) {\n\t\t\treturn reply('conflict', current)\n\t\t}\n\t\tconst successor = isKeyRecordSuccessor(current, message.record)\n\t\tif (!successor.ok) {\n\t\t\treturn reply('invalid', current, `Refused key record: ${successor.reason}.`)\n\t\t}\n\t\tconst stored = await putRecord(\n\t\t\towner,\n\t\t\tmessage.keyring,\n\t\t\tjson,\n\t\t\tmessage.record.revision,\n\t\t\tmessage.expectedRevision,\n\t\t)\n\t\tif (!stored) {\n\t\t\t// Lost a race with another write between the read and the compare-and-set.\n\t\t\treturn reply('conflict', await this.read(owner, message.keyring))\n\t\t}\n\t\tconst accepted = JSON.parse(json) as WrappedKeyRecord\n\t\treturn { ...reply('ok', accepted), written: accepted }\n\t}\n\n\t/**\n\t * Key ids of the owner's stored encrypted operations (a sample). Reported only while\n\t * no record exists: then non-empty means the record was lost, and a new device must\n\t * wait for one that holds the ring instead of starting another (RT-104).\n\t */\n\tprivate async knownKeyIds(owner: string, keyring: string): Promise<string[]> {\n\t\tif (typeof this.store.getEncryptedKeyIds !== 'function') return []\n\t\ttry {\n\t\t\t// Operations name their key, not their keyring. Key ids held by the owner's OTHER\n\t\t\t// keyrings are not this keyring's history: without excluding them, the first\n\t\t\t// device of a second keyring would wait for a record that never existed.\n\t\t\tconst sampled = await this.store.getEncryptedKeyIds(\n\t\t\t\tnodeOwnerOf(owner),\n\t\t\t\tKNOWN_KEY_IDS_LIMIT * 4,\n\t\t\t)\n\t\t\tif (sampled.length === 0) return []\n\t\t\tconst others = new Set<string>()\n\t\t\tfor (const row of (await this.store.listEncryptionKeyRecords?.(owner)) ?? []) {\n\t\t\t\tif (row.owner !== owner || row.keyring === keyring) continue\n\t\t\t\ttry {\n\t\t\t\t\tconst record = JSON.parse(row.record) as WrappedKeyRecord\n\t\t\t\t\tfor (const key of record.keys ?? []) others.add(key.keyId)\n\t\t\t\t} catch {\n\t\t\t\t\t// An unreadable record names no key.\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn sampled.filter((keyId) => !others.has(keyId)).slice(0, KNOWN_KEY_IDS_LIMIT)\n\t\t} catch {\n\t\t\t// Advisory only: a device that creates a ring anyway is merged later.\n\t\t\treturn []\n\t\t}\n\t}\n\n\tprivate async read(owner: string, keyring: string): Promise<WrappedKeyRecord | null> {\n\t\tconst json = await this.store.getEncryptionKeyRecord?.(owner, keyring)\n\t\tif (json === null || json === undefined) return null\n\t\ttry {\n\t\t\treturn JSON.parse(json) as WrappedKeyRecord\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n}\n","import type { Operation, SchemaDefinition } from '@korajs/core'\nimport { type BlobAccessIndex, asBlobRef, referencedHashes } from '../richtext/blob-access-index'\nimport type { MaterializedRecord } from '../store/server-store'\nimport {\n\ttype ScopeMap,\n\ttype UplinkAuthorizationResult,\n\trecordMatchesScopes,\n} from './server-scope-filter'\n\n/** Reads a record as stored (including a soft-deleted one), or null when never written. */\nexport type StoredRowReader = (\n\tcollection: string,\n\trecordId: string,\n) => Promise<MaterializedRecord | null>\n\n/** What an untrusted write may point at, beyond the record it writes. */\nexport interface ReferenceAuthorizationContext {\n\t/** The server schema (relations and blob fields). */\n\tschema: SchemaDefinition | null\n\t/**\n\t * What the writer may READ (its download scope). A reference is authorized against\n\t * it: a writer may only point at records and content it could receive itself.\n\t * Undefined means an unscoped writer (no tenant boundary): nothing is checked.\n\t */\n\tdownlinkScopes: ScopeMap | undefined\n\t/**\n\t * What the writer may WRITE (its uplink scope), when it differs from what it may\n\t * read. A foreign-key parent inside it is accepted too (RT-22): a respondent may\n\t * attach answers to the submission it just created even though it can never read\n\t * submissions back. Blob references are still judged on the download scope only.\n\t */\n\tuplinkScopes?: ScopeMap | undefined\n\t/** Reads a stored row, inside the writer's transaction when one is available. */\n\treadRow: StoredRowReader\n\t/** Blob reference authority (RT-11). Without it blob fields are not checked. */\n\tblobs?: BlobAccessIndex\n\t/** Ownership key of the writer for blob claims (see `BlobReferenceRequest.owner`). */\n\tblobOwner?: string\n}\n\n/**\n * Authorize the references an untrusted write makes (RT-11, RT-13), after its own\n * record passed `authorizeUplinkWrite`:\n *\n * - **Foreign keys (RT-13).** For an insert, or an update that sets a relation field,\n * the referenced parent must exist (a soft-deleted parent counts, as stored) and be\n * inside the writer's download scope or its upload scope (RT-22: a record the writer\n * was allowed to create, even if it cannot read it back). Otherwise a tenant could hang a child under\n * another tenant's record (leaving its owner unable to delete it under `restrict`,\n * or probing which ids exist).\n * - **Blob references (RT-11).** Every hash a blob field makes readable (its\n * `manifestHash`, or `hash` for a bare reference; see `referencedHashes`) must be\n * one the writer may reference: see `BlobAccessIndex.authorizeReference`. A\n * content hash is not a secret, so naming one grants nothing.\n *\n * Refusals are `SCOPE_VIOLATION` and name only the writer's own record and field.\n *\n * @param op - The (already uplink-authorized) operation\n * @param stored - The written record as stored now, or null\n * @param context - Schema, writer scope, row reader and blob authority\n */\nexport async function authorizeOperationReferences(\n\top: Operation,\n\tstored: MaterializedRecord | null,\n\tcontext: ReferenceAuthorizationContext,\n): Promise<UplinkAuthorizationResult> {\n\tconst { schema, downlinkScopes } = context\n\tif (!schema || downlinkScopes === undefined) return { allowed: true }\n\tif (op.type === 'delete') return { allowed: true }\n\tconst data = asRecord(op.data)\n\tif (!data) return { allowed: true }\n\n\tfor (const relation of Object.values(schema.relations ?? {})) {\n\t\tif (relation.from !== op.collection || !(relation.field in data)) continue\n\t\tconst target = data[relation.field]\n\t\tif (target === null || target === undefined) continue\n\t\t// An unchanged reference was already authorized when it was written.\n\t\tif (stored && Object.is(stored[relation.field], target)) continue\n\t\tif (typeof target !== 'string') {\n\t\t\treturn violation(op, relation.field, 'the referenced record id is not a string')\n\t\t}\n\t\tconst parent = await context.readRow(relation.to, target)\n\t\tconst parentRow = parent ? { ...parent, id: target } : null\n\t\t// The parent must be a record the writer could read OR could have written itself\n\t\t// (RT-22). A parent in neither scope belongs to another tenant (RT-13).\n\t\tconst reachable =\n\t\t\tparentRow !== null &&\n\t\t\t(recordMatchesScopes(relation.to, parentRow, downlinkScopes) ||\n\t\t\t\t(context.uplinkScopes !== undefined &&\n\t\t\t\t\trecordMatchesScopes(relation.to, parentRow, context.uplinkScopes)))\n\t\tif (!reachable) {\n\t\t\treturn violation(\n\t\t\t\top,\n\t\t\t\trelation.field,\n\t\t\t\t`the referenced \"${relation.to}\" record does not exist inside the writer's scope`,\n\t\t\t)\n\t\t}\n\t}\n\n\tconst blobs = context.blobs\n\tconst owner = context.blobOwner\n\tconst collection = schema.collections[op.collection]\n\tif (blobs && owner !== undefined && collection) {\n\t\tconst alreadyReferenced = new Set<string>()\n\t\tfor (const [field, descriptor] of Object.entries(collection.fields)) {\n\t\t\tif (descriptor.kind !== 'blob' || !stored) continue\n\t\t\tconst ref = asBlobRef(stored[field])\n\t\t\tif (ref) for (const hash of referencedHashes(ref)) alreadyReferenced.add(hash)\n\t\t}\n\t\tfor (const [field, descriptor] of Object.entries(collection.fields)) {\n\t\t\tif (descriptor.kind !== 'blob' || !(field in data)) continue\n\t\t\tconst value = data[field]\n\t\t\tif (value === null || value === undefined) continue\n\t\t\tconst ref = asBlobRef(value)\n\t\t\tif (!ref) return violation(op, field, 'the value is not a blob reference')\n\t\t\tfor (const hash of referencedHashes(ref)) {\n\t\t\t\tconst allowed = await blobs.authorizeReference({\n\t\t\t\t\thash,\n\t\t\t\t\tscopes: downlinkScopes,\n\t\t\t\t\towner,\n\t\t\t\t\talreadyReferenced,\n\t\t\t\t})\n\t\t\t\tif (!allowed) {\n\t\t\t\t\treturn violation(\n\t\t\t\t\t\top,\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\t'it references blob content the writer cannot read and has not uploaded',\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn { allowed: true }\n}\n\n/**\n * True when an operation sets a relation field or a blob field, so its references\n * need authorizing (cheap pre-check that avoids a store read for every other write).\n */\nexport function operationHasReferences(op: Operation, schema: SchemaDefinition): boolean {\n\tif (op.type === 'delete') return false\n\tconst data = asRecord(op.data)\n\tif (!data) return false\n\tfor (const relation of Object.values(schema.relations ?? {})) {\n\t\tif (relation.from === op.collection && relation.field in data) return true\n\t}\n\tconst fields = schema.collections[op.collection]?.fields ?? {}\n\treturn Object.entries(fields).some(([name, field]) => field.kind === 'blob' && name in data)\n}\n\nfunction violation(op: Operation, field: string, reason: string): UplinkAuthorizationResult {\n\treturn {\n\t\tallowed: false,\n\t\tcode: 'SCOPE_VIOLATION',\n\t\tmessage: `Operation \"${op.id}\" on \"${op.collection}\" record \"${op.recordId}\" field \"${field}\" is outside the accepted scope: ${reason}.`,\n\t}\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value)\n\t\t? (value as Record<string, unknown>)\n\t\t: null\n}\n","import { hashBlob, isBlobRef } from '@korajs/core'\nimport {\n\ttype ScopeMap,\n\trecordMatchesScopes,\n\tsplitScopeForQuery,\n} from '../scopes/server-scope-filter'\nimport type { ServerStore } from '../store/server-store'\nimport type { ResolveBlobChunk } from './blob-chunk-relay'\n\n/** How long a scope's referenced-hash set is reused before it is rebuilt. */\nexport const DEFAULT_BLOB_ACCESS_CACHE_TTL_MS = 5_000\n/** Most chunk lists remembered from manifests. */\nconst MAX_KNOWN_MANIFESTS = 10_000\n/** Most blob owners remembered when the store cannot persist them. */\nconst MAX_MEMORY_BLOB_OWNERS = 100_000\nconst HEX_HASH = /^[0-9a-f]{64}$/\n\ninterface ScopeEntry {\n\t/** Blob and manifest hashes referenced by live records in the scope. */\n\tdirect: Set<string>\n\tbuiltAtMs: number\n\t/** The invalidation generations this set was built against. */\n\tstamp: GenerationStamp\n}\n\ninterface GenerationStamp {\n\tglobal: number\n\t/** Generation of every blob collection the build scanned. */\n\tcollections: Map<string, number>\n}\n\n/** Input to {@link BlobAccessIndex.authorizeReference}. */\nexport interface BlobReferenceRequest {\n\t/** The content hash (blob, manifest or chunk) the writer wants to reference. */\n\thash: string\n\t/** The writer's download scope, or undefined for an unscoped writer. */\n\tscopes: ScopeMap | undefined\n\t/**\n\t * Stable ownership key of the writer: the user id for a signed-in principal, the\n\t * node-claim owner for an anonymous device, a `kora:route:` key for a scoped route.\n\t */\n\towner: string\n\t/** Hashes the written record already references as stored (unchanged references). */\n\talreadyReferenced?: ReadonlySet<string>\n}\n\n/**\n * Answers \"does a live record inside this download scope reference this blob\n * hash?\" for the blob relay (RT-1), and \"may this writer reference this hash?\" at\n * ingest (RT-11).\n *\n * **A content hash is not a secret.** Hashes of well-known content can be computed\n * by anyone, and they travel in records, manifests and logs. So knowing a hash never\n * grants access: a write may reference a hash only when the writer can already read\n * a record that references it, or has proven possession of the bytes (pushed them).\n * Only in peer-relay mode (no central store, so nothing can be pre-claimed and then\n * read back from the server) may the first writer of a hash nobody references or\n * owns claim it by reference alone.\n *\n * A hash is referenced in a scope when a live (not deleted) record in scope has a\n * blob field whose `BlobRef.manifestHash` (or, for a bare reference without a\n * manifest, `BlobRef.hash`) equals it, or when it is a chunk listed in such a manifest and the chunk is unowned or shares an owner with\n * the manifest (so a crafted manifest listing someone else's chunk hashes exposes\n * nothing). Manifests are read through `resolveBlobChunk` (central store) or learned\n * from manifest bytes verified in transit.\n *\n * Cost: the referenced set of a scope is built by a scoped query over every\n * collection that declares a blob field (O(records in scope with blobs)). It is\n * cached per scope, rebuilt after a write to one of the blob collections it scanned\n * ({@link invalidate}) or after `ttlMs` (writes through another server instance),\n * and concurrent lookups for one scope share a single rebuild (RT-17). A full hash\n * index in the store would make this O(1); this is the interim, correctness-first\n * form.\n */\nexport class BlobAccessIndex {\n\tprivate readonly byScope = new Map<string, ScopeEntry>()\n\t/** Rebuilds in progress per scope key, shared by concurrent lookups (RT-17). */\n\tprivate readonly inflight = new Map<\n\t\tstring,\n\t\t{ promise: Promise<Set<string>>; stamp: GenerationStamp }\n\t>()\n\t/** manifestHash -> chunk hashes it lists (only from bytes verified against the hash). */\n\tprivate readonly manifestChunks = new Map<string, string[]>()\n\t/** chunkHash -> manifests listing it. */\n\tprivate readonly chunkManifests = new Map<string, Set<string>>()\n\t/** Ownership fallback for stores without blob-owner persistence. */\n\tprivate readonly memoryOwners = new Map<string, Set<string>>()\n\tprivate globalGeneration = 0\n\tprivate readonly collectionGeneration = new Map<string, number>()\n\n\tconstructor(\n\t\tprivate readonly store: ServerStore,\n\t\tprivate readonly resolveBlobChunk: ResolveBlobChunk | null,\n\t\tprivate readonly ttlMs: number = DEFAULT_BLOB_ACCESS_CACHE_TTL_MS,\n\t) {}\n\n\t/**\n\t * Forget cached scope sets because records changed. With `collections`, only sets\n\t * built from those collections are dropped (a write to a collection without blob\n\t * fields drops nothing); without, every set is dropped (for example writes made\n\t * through another server instance).\n\t */\n\tinvalidate(collections?: Iterable<string>): void {\n\t\tif (collections === undefined) {\n\t\t\tthis.globalGeneration += 1\n\t\t\tthis.byScope.clear()\n\t\t\treturn\n\t\t}\n\t\tfor (const collection of collections) {\n\t\t\tthis.collectionGeneration.set(\n\t\t\t\tcollection,\n\t\t\t\t(this.collectionGeneration.get(collection) ?? 0) + 1,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * True when a live record inside `scopes` references `hash`.\n\t *\n\t * @param scopes - The session's download scope, or undefined for unscoped\n\t * @param hash - The requested content hash\n\t */\n\tasync isReferenced(scopes: ScopeMap | undefined, hash: string): Promise<boolean> {\n\t\tif (!HEX_HASH.test(hash)) return false\n\t\tconst direct = await this.directHashes(scopes)\n\t\tif (direct.has(hash)) return true\n\t\tconst manifests = this.chunkManifests.get(hash)\n\t\tif (!manifests) return false\n\t\tconst candidates = [...manifests].filter((manifest) => direct.has(manifest))\n\t\tif (candidates.length === 0) return false\n\t\tconst owners = await this.ownersOf([hash, ...candidates])\n\t\tconst chunkOwners = owners.get(hash) ?? []\n\t\t// An unowned chunk (peer-to-peer mode, nothing pushed) is trusted through any\n\t\t// referenced manifest listing it; an owned one only through a manifest that\n\t\t// shares an owner, so a crafted manifest cannot reach someone else's chunk.\n\t\tif (chunkOwners.length === 0) return true\n\t\treturn candidates.some((manifest) =>\n\t\t\t(owners.get(manifest) ?? []).some((owner) => chunkOwners.includes(owner)),\n\t\t)\n\t}\n\n\t/**\n\t * Decide whether a writer may reference `hash` in a blob field (RT-11). Allowed\n\t * when the record already referenced it, when a live record inside the writer's\n\t * download scope references it, when the writer owns it (pushed the bytes, or\n\t * claimed it first), or when nobody references, owns or stores it yet: then the\n\t * writer claims it, atomically, so a later forger cannot.\n\t */\n\tasync authorizeReference(request: BlobReferenceRequest): Promise<boolean> {\n\t\tconst { hash, scopes, owner } = request\n\t\tif (!HEX_HASH.test(hash)) return false\n\t\tif (request.alreadyReferenced?.has(hash)) return true\n\t\tif (await this.isReferenced(scopes, hash)) return true\n\t\tconst owners = (await this.ownersOf([hash])).get(hash) ?? []\n\t\tif (owners.includes(owner)) return true\n\t\tif (owners.length > 0) return false\n\t\tif (scopes !== undefined && (await this.isReferenced(undefined, hash))) return false\n\t\t// With a central store a bare reference never claims a hash (RT-25): the writer\n\t\t// must push the bytes first (the client's outbound preparer does), so a guessed\n\t\t// hash cannot be pre-claimed to read content another tenant uploads later, and\n\t\t// the answer is the same whether or not someone else holds the content.\n\t\tif (this.resolveBlobChunk) return false\n\t\treturn this.claim(hash, owner)\n\t}\n\n\t/** True when `owner` pushed (or first claimed) the bytes behind `hash`. */\n\tasync isOwnedBy(hash: string, owner: string): Promise<boolean> {\n\t\tif (!HEX_HASH.test(hash)) return false\n\t\tconst owners = (await this.ownersOf([hash])).get(hash) ?? []\n\t\treturn owners.includes(owner)\n\t}\n\n\t/**\n\t * Record that `owner` pushed bytes verified to hash to `hash` (proof of\n\t * possession), and learn the chunk list when the bytes are a manifest.\n\t */\n\tasync recordPush(hash: string, bytes: Uint8Array, owner: string): Promise<void> {\n\t\tawait this.addOwner(hash, owner)\n\t\tthis.observeVerifiedBytes(hash, bytes)\n\t}\n\n\t/**\n\t * When `bytes` are a manifest, true only if the pusher may reference every chunk\n\t * it lists (the same rule as {@link authorizeReference}); true for non-manifest\n\t * bytes. A manifest listing someone else's chunks is refused before it is stored.\n\t */\n\tasync authorizeManifestPush(\n\t\tbytes: Uint8Array,\n\t\tscopes: ScopeMap | undefined,\n\t\towner: string,\n\t): Promise<boolean> {\n\t\tconst chunks = parseManifestChunks(bytes)\n\t\tif (!chunks) return true\n\t\tfor (const chunk of new Set(chunks)) {\n\t\t\tif (!(await this.authorizeReference({ hash: chunk, scopes, owner }))) return false\n\t\t}\n\t\treturn true\n\t}\n\n\t/**\n\t * Learn a manifest's chunk list from bytes already verified to hash to `hash`.\n\t * Bytes that are not a manifest are ignored. Unowned chunks of an owned manifest\n\t * are claimed for the manifest's owner, so a manifest crafted later cannot adopt\n\t * them.\n\t */\n\tobserveVerifiedBytes(hash: string, bytes: Uint8Array): void {\n\t\tif (this.manifestChunks.has(hash)) return\n\t\tconst chunks = parseManifestChunks(bytes)\n\t\tif (!chunks) return\n\t\tthis.rememberManifest(hash, chunks)\n\t\tvoid this.claimChunksForManifestOwner(hash, chunks).catch(() => {\n\t\t\t// Best effort: an unowned chunk stays reachable only through manifests in scope.\n\t\t})\n\t}\n\n\tprivate async claimChunksForManifestOwner(manifest: string, chunks: string[]): Promise<void> {\n\t\tconst manifestOwners = (await this.ownersOf([manifest])).get(manifest) ?? []\n\t\tconst first = manifestOwners[0]\n\t\tif (first === undefined) return\n\t\tconst owners = await this.ownersOf(chunks)\n\t\tfor (const chunk of new Set(chunks)) {\n\t\t\tif ((owners.get(chunk) ?? []).length === 0) await this.claim(chunk, first)\n\t\t}\n\t}\n\n\tprivate currentStamp(collections: string[]): GenerationStamp {\n\t\treturn {\n\t\t\tglobal: this.globalGeneration,\n\t\t\tcollections: new Map(collections.map((c) => [c, this.collectionGeneration.get(c) ?? 0])),\n\t\t}\n\t}\n\n\tprivate isCurrent(stamp: GenerationStamp): boolean {\n\t\tif (stamp.global !== this.globalGeneration) return false\n\t\tfor (const [collection, generation] of stamp.collections) {\n\t\t\tif ((this.collectionGeneration.get(collection) ?? 0) !== generation) return false\n\t\t}\n\t\treturn true\n\t}\n\n\tprivate blobCollections(\n\t\tscopes: ScopeMap | undefined,\n\t): Array<{ collection: string; fields: string[] }> {\n\t\tconst schema = this.store.getSchema()\n\t\tconst result: Array<{ collection: string; fields: string[] }> = []\n\t\tfor (const [collection, definition] of Object.entries(schema?.collections ?? {})) {\n\t\t\tconst fields = Object.entries(definition.fields)\n\t\t\t\t.filter(([, field]) => field.kind === 'blob')\n\t\t\t\t.map(([name]) => name)\n\t\t\tif (fields.length === 0) continue\n\t\t\tif (scopes && !scopes[collection]) continue\n\t\t\tresult.push({ collection, fields })\n\t\t}\n\t\treturn result\n\t}\n\n\tprivate async directHashes(scopes: ScopeMap | undefined): Promise<Set<string>> {\n\t\tconst partitionKey = scopes ? stableKey(scopes) : '*'\n\t\tconst collections = this.blobCollections(scopes)\n\t\tconst cached = this.byScope.get(partitionKey)\n\t\tif (cached && this.isCurrent(cached.stamp) && Date.now() - cached.builtAtMs < this.ttlMs) {\n\t\t\treturn cached.direct\n\t\t}\n\t\tconst running = this.inflight.get(partitionKey)\n\t\tif (running && this.isCurrent(running.stamp)) return running.promise\n\n\t\tconst stamp = this.currentStamp(collections.map((c) => c.collection))\n\t\tconst promise = this.build(scopes, collections)\n\t\tconst entry = { promise, stamp }\n\t\tthis.inflight.set(partitionKey, entry)\n\t\ttry {\n\t\t\tconst direct = await promise\n\t\t\t// Only cache a set nothing invalidated while it was being built.\n\t\t\tif (this.isCurrent(stamp)) {\n\t\t\t\tthis.byScope.set(partitionKey, { direct, builtAtMs: Date.now(), stamp })\n\t\t\t}\n\t\t\treturn direct\n\t\t} finally {\n\t\t\tif (this.inflight.get(partitionKey) === entry) this.inflight.delete(partitionKey)\n\t\t}\n\t}\n\n\tprivate async build(\n\t\tscopes: ScopeMap | undefined,\n\t\tcollections: Array<{ collection: string; fields: string[] }>,\n\t): Promise<Set<string>> {\n\t\tconst direct = new Set<string>()\n\t\tconst manifests: string[] = []\n\t\tfor (const { collection, fields } of collections) {\n\t\t\tconst collectionScope = scopes ? (scopes[collection] ?? {}) : {}\n\t\t\tconst { equality } = splitScopeForQuery(collectionScope)\n\t\t\tconst rows = await this.store.queryCollection(collection, { where: equality })\n\t\t\tfor (const row of rows) {\n\t\t\t\tif (row._deleted === 1 || row._deleted === true) continue\n\t\t\t\tif (scopes && !recordMatchesScopes(collection, row, scopes)) continue\n\t\t\t\tfor (const field of fields) {\n\t\t\t\t\tconst ref = asBlobRef(row[field])\n\t\t\t\t\tif (!ref) continue\n\t\t\t\t\tfor (const hash of referencedHashes(ref)) direct.add(hash)\n\t\t\t\t\tif (ref.manifestHash) manifests.push(ref.manifestHash)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait this.loadManifests(manifests)\n\t\treturn direct\n\t}\n\n\t/** Read unknown manifests from the central store, verifying them against their hash. */\n\tprivate async loadManifests(manifestHashes: string[]): Promise<void> {\n\t\tif (!this.resolveBlobChunk) return\n\t\tfor (const manifestHash of manifestHashes) {\n\t\t\tif (this.manifestChunks.has(manifestHash)) continue\n\t\t\tlet bytes: Uint8Array | null = null\n\t\t\ttry {\n\t\t\t\tbytes = await this.resolveBlobChunk(manifestHash)\n\t\t\t} catch {\n\t\t\t\tbytes = null\n\t\t\t}\n\t\t\tif (bytes === null) continue\n\t\t\tif ((await hashBlob(bytes)) !== manifestHash) continue\n\t\t\tthis.observeVerifiedBytes(manifestHash, bytes)\n\t\t}\n\t}\n\n\tprivate async ownersOf(hashes: string[]): Promise<Map<string, string[]>> {\n\t\tif (this.store.getBlobOwners) return this.store.getBlobOwners(hashes)\n\t\tconst result = new Map<string, string[]>()\n\t\tfor (const hash of hashes) result.set(hash, [...(this.memoryOwners.get(hash) ?? [])])\n\t\treturn result\n\t}\n\n\tprivate async addOwner(hash: string, owner: string): Promise<void> {\n\t\tif (this.store.recordBlobOwner) {\n\t\t\tawait this.store.recordBlobOwner(hash, owner)\n\t\t\treturn\n\t\t}\n\t\tthis.rememberMemoryOwner(hash, owner)\n\t}\n\n\tprivate async claim(hash: string, owner: string): Promise<boolean> {\n\t\tif (this.store.claimBlobIfUnowned) return this.store.claimBlobIfUnowned(hash, owner)\n\t\tconst owners = this.memoryOwners.get(hash)\n\t\tif (owners && owners.size > 0) return owners.has(owner)\n\t\tthis.rememberMemoryOwner(hash, owner)\n\t\treturn true\n\t}\n\n\tprivate rememberMemoryOwner(hash: string, owner: string): void {\n\t\tlet owners = this.memoryOwners.get(hash)\n\t\tif (!owners) {\n\t\t\tif (this.memoryOwners.size >= MAX_MEMORY_BLOB_OWNERS) {\n\t\t\t\tconst oldest = this.memoryOwners.keys().next().value\n\t\t\t\tif (oldest !== undefined) this.memoryOwners.delete(oldest)\n\t\t\t}\n\t\t\towners = new Set()\n\t\t\tthis.memoryOwners.set(hash, owners)\n\t\t}\n\t\towners.add(owner)\n\t}\n\n\tprivate rememberManifest(manifestHash: string, chunks: string[]): void {\n\t\tif (this.manifestChunks.size >= MAX_KNOWN_MANIFESTS) {\n\t\t\tconst oldest = this.manifestChunks.keys().next().value\n\t\t\tif (oldest !== undefined) this.forgetManifest(oldest)\n\t\t}\n\t\tthis.manifestChunks.set(manifestHash, chunks)\n\t\tfor (const chunk of chunks) {\n\t\t\tlet owners = this.chunkManifests.get(chunk)\n\t\t\tif (!owners) {\n\t\t\t\towners = new Set()\n\t\t\t\tthis.chunkManifests.set(chunk, owners)\n\t\t\t}\n\t\t\towners.add(manifestHash)\n\t\t}\n\t}\n\n\tprivate forgetManifest(manifestHash: string): void {\n\t\tfor (const chunk of this.manifestChunks.get(manifestHash) ?? []) {\n\t\t\tconst owners = this.chunkManifests.get(chunk)\n\t\t\towners?.delete(manifestHash)\n\t\t\tif (owners && owners.size === 0) this.chunkManifests.delete(chunk)\n\t\t}\n\t\tthis.manifestChunks.delete(manifestHash)\n\t}\n}\n\n/** Deterministic key for a scope map (sorted keys at every level). */\nfunction stableKey(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(stableKey).join(',')}]`\n\tif (value && typeof value === 'object') {\n\t\tconst record = value as Record<string, unknown>\n\t\treturn `{${Object.keys(record)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${stableKey(record[key])}`)\n\t\t\t.join(',')}}`\n\t}\n\treturn JSON.stringify(value) ?? 'undefined'\n}\n\n/**\n * The content hashes a blob reference makes readable. A reference with a manifest\n * is read through the manifest (then its chunks), never by the whole-blob hash, so\n * only `manifestHash` counts: the whole-blob `hash` cannot be verified against the\n * manifest without reassembling every chunk, and must not act as a capability for\n * whatever content hashes to it. A bare reference (no manifest) is read by `hash`.\n *\n * @param ref - A blob reference\n * @returns The hashes a reader of the reference may request\n */\nexport function referencedHashes(ref: { hash: string; manifestHash?: string }): string[] {\n\treturn ref.manifestHash ? [ref.manifestHash] : [ref.hash]\n}\n\n/**\n * The blob reference a field value holds (a `BlobRef`, or its JSON string as some\n * stores keep it), or null.\n */\nexport function asBlobRef(value: unknown): { hash: string; manifestHash?: string } | null {\n\tlet candidate = value\n\tif (typeof candidate === 'string') {\n\t\ttry {\n\t\t\tcandidate = JSON.parse(candidate)\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\treturn isBlobRef(candidate) ? candidate : null\n}\n\n/** The chunk hashes of a canonical blob manifest, or null when the bytes are not one. */\nexport function parseManifestChunks(bytes: Uint8Array): string[] | null {\n\tif (bytes.byteLength > 4 * 1024 * 1024) return null\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(new TextDecoder().decode(bytes))\n\t} catch {\n\t\treturn null\n\t}\n\tif (typeof parsed !== 'object' || parsed === null) return null\n\tconst chunkHashes = (parsed as { chunkHashes?: unknown }).chunkHashes\n\tif (!Array.isArray(chunkHashes)) return null\n\tif (!chunkHashes.every((h): h is string => typeof h === 'string' && HEX_HASH.test(h))) return null\n\treturn chunkHashes\n}\n","import type { ScopeMap } from '@korajs/core'\nimport {\n\tKoraError,\n\tSCOPE_CLAIMS_KEY,\n\ttype SchemaDefinition,\n\tgetCollectionScopeBindings,\n\tgetScopeClaims,\n\thasSchemaSyncRules,\n\tisCollectionSyncScoped,\n} from '@korajs/core'\nimport { assertScopeValuesDefined } from './scope-predicate-errors'\n\nexport interface ResolveSessionScopesOptions {\n\t/** Scope map sent by the client during handshake. It can only NARROW the grant. */\n\thandshakeScope?: ScopeMap\n\t/**\n\t * The server grant from the auth provider. Its collection set is authoritative:\n\t * a collection it does not list is not visible, whatever the handshake asks for.\n\t * It may carry verified claim values under `$claims` (see `claimScopes` in\n\t * `@korajs/core`), which are bound to every schema-scoped collection.\n\t */\n\tauthScopes?: ScopeMap\n\t/**\n\t * Verified, server-derived scope values (for example `{ userId: sub }`). Treated\n\t * exactly like `$claims` in `authScopes`. Never pass client-supplied values here.\n\t */\n\tscopeValues?: Record<string, unknown>\n\t/**\n\t * True when an auth provider authenticated this session. An authenticated\n\t * session whose provider returned no grant at all is denied every\n\t * schema-scoped collection instead of trusting the client handshake.\n\t *\n\t * Leave it false only for servers without an auth provider (or with\n\t * `NoAuthProvider`), where the handshake is a client-side filter, not a grant.\n\t * @default false\n\t */\n\tauthenticated?: boolean\n\t/**\n\t * What to do when a schema-scoped collection's bindings cannot all be resolved\n\t * from the verified claims. `'deny'` hides the collection (fail closed);\n\t * `'throw'` raises {@link ScopeRequiredError} so the caller can reject the\n\t * handshake with `SCOPE_REQUIRED`.\n\t * @default 'deny'\n\t */\n\tonUnresolved?: 'deny' | 'throw'\n}\n\n/** A schema-scoped collection the session was denied because a binding was unresolved. */\nexport interface DeniedScopeCollection {\n\tcollection: string\n\t/** Scope binding keys (for example `orgId`) that had no verified value. */\n\tmissingKeys: string[]\n}\n\n/** Detailed result of {@link resolveSessionScopeGrant}. */\nexport interface ResolvedSessionScopeGrant {\n\t/**\n\t * Effective scope map. `undefined` means \"no scoping\" and is only ever returned\n\t * for unauthenticated servers without a grant. An empty object means \"nothing\n\t * visible\".\n\t */\n\tscopes: ScopeMap | undefined\n\t/** Collections denied because their scope bindings could not be resolved. */\n\tdenied: DeniedScopeCollection[]\n}\n\n/**\n * Thrown (with `onUnresolved: 'throw'`) when an authenticated session cannot be\n * bound to a schema-scoped collection because the server grant lacks a value.\n */\nexport class ScopeRequiredError extends KoraError {\n\tconstructor(public readonly denied: DeniedScopeCollection[]) {\n\t\tsuper(\n\t\t\t`Sync scope required: ${denied\n\t\t\t\t.map((d) => `\"${d.collection}\" needs ${d.missingKeys.map((k) => `\"${k}\"`).join(', ')}`)\n\t\t\t\t.join('; ')}. The server could not derive these values from the verified token.`,\n\t\t\t'SCOPE_REQUIRED',\n\t\t\t{\n\t\t\t\tdenied,\n\t\t\t\tfix: 'Return the missing scope values from your auth provider, for example createKoraAuthServer({ scopeValues: async (claims) => ({ orgId: await lookupOrg(claims.sub) }) }) or a resolveScopes grant.',\n\t\t\t},\n\t\t)\n\t\tthis.name = 'ScopeRequiredError'\n\t}\n}\n\nconst warnedDenials = new Set<string>()\n\n/**\n * Resolve the effective per-session sync scope map.\n *\n * The result is the INTERSECTION of the server grant and the client handshake:\n * - The collection set is the grant's collection set. A handshake can never add\n * a collection.\n * - Per collection, handshake predicates only narrow: grant fields win, a\n * handshake field on an unconstrained field is added, and for an `$in` grant a\n * handshake value is used only when it is a subset of the granted values.\n * - Schema-scoped collections bound from verified claims fail closed: an\n * unresolved binding denies the collection instead of producing `{}`.\n *\n * Invariant: the effective scope is a subset of the server grant, and no\n * schema-scoped collection resolves to `{}` from claims for an authenticated\n * principal.\n *\n * @returns The effective scope map; `undefined` only for unauthenticated servers\n * with neither a grant nor a handshake scope\n */\nexport function resolveSessionScopes(\n\tschema: SchemaDefinition | null,\n\toptions: ResolveSessionScopesOptions,\n): ScopeMap | undefined {\n\treturn resolveSessionScopeGrant(schema, options).scopes\n}\n\n/**\n * Same as {@link resolveSessionScopes}, but also reports which collections were\n * denied for unresolved bindings, so a caller can surface `SCOPE_REQUIRED`.\n */\nexport function resolveSessionScopeGrant(\n\tschema: SchemaDefinition | null,\n\toptions: ResolveSessionScopesOptions,\n): ResolvedSessionScopeGrant {\n\tconst { handshakeScope, authScopes, scopeValues } = options\n\tconst denied: DeniedScopeCollection[] = []\n\n\tlet grant: ScopeMap | undefined\n\tif (authScopes !== undefined || scopeValues !== undefined) {\n\t\tconst claims = mergeClaims(getScopeClaims(authScopes), scopeValues)\n\t\tconst explicit = withoutReservedKeys(authScopes ?? {})\n\t\t// A grant value of undefined/null (a failed lookup) would match every record\n\t\t// lacking the field: refuse it rather than widen the grant (RT-8).\n\t\tassertScopeValuesDefined(explicit)\n\t\tif (!schema && claims && Object.keys(explicit).length === 0) {\n\t\t\t// RT-89: verified claims alone (TokenAuthProvider without explicit scopes) bind to\n\t\t\t// schema-scoped collections, and a schemaless server has none it knows of. Such a\n\t\t\t// grant names no collection, so it is no grant at all: \"unscoped\", exactly like an\n\t\t\t// absent grant on a schemaless server. Treating it as an EMPTY grant hid every\n\t\t\t// collection from the session and refused every upload.\n\t\t\tgrant = undefined\n\t\t\twarnSchemalessClaims()\n\t\t} else {\n\t\t\tgrant = { ...explicit }\n\t\t\tif (claims && schema) {\n\t\t\t\tconst derived = bindClaimsToSchema(schema, claims, denied)\n\t\t\t\tfor (const [collection, predicate] of Object.entries(derived)) {\n\t\t\t\t\tif (!(collection in grant)) grant[collection] = predicate\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (options.authenticated) {\n\t\t// An authenticated principal with no grant is not trusted to choose its own\n\t\t// scope: unscoped collections stay visible, scoped ones are denied.\n\t\tgrant = schema ? bindClaimsToSchema(schema, {}, denied) : {}\n\t}\n\n\t// Explicitly granted collections cover a denial for the same collection.\n\tconst effectiveDenied = grant ? denied.filter((entry) => !(entry.collection in grant)) : denied\n\n\tif (effectiveDenied.length > 0) {\n\t\tif (options.onUnresolved === 'throw') {\n\t\t\tthrow new ScopeRequiredError(effectiveDenied)\n\t\t}\n\t\twarnDenied(effectiveDenied)\n\t}\n\n\tif (grant === undefined) {\n\t\tconst scopes = handshakeScope ? withoutReservedKeys(handshakeScope) : undefined\n\t\tassertScopeValuesDefined(scopes)\n\t\treturn { scopes, denied: effectiveDenied }\n\t}\n\n\tconst scopes = intersectScopes(grant, handshakeScope)\n\tassertScopeValuesDefined(scopes)\n\treturn { scopes, denied: effectiveDenied }\n}\n\n/**\n * Bind verified claim values to every schema collection. Mirrors `buildScopeMap`'s\n * collection selection, but never emits `{}` for a scoped collection whose\n * bindings are unresolved: those are recorded in `denied` and left out.\n */\nfunction bindClaimsToSchema(\n\tschema: SchemaDefinition,\n\tclaims: Record<string, unknown>,\n\tdenied: DeniedScopeCollection[],\n): ScopeMap {\n\tconst result: ScopeMap = {}\n\tconst partialSync = hasSchemaSyncRules(schema)\n\tfor (const collection of Object.keys(schema.collections)) {\n\t\tif (partialSync && !isCollectionSyncScoped(schema, collection)) continue\n\t\tconst bindings = getCollectionScopeBindings(schema, collection)\n\t\tif (!bindings) {\n\t\t\tresult[collection] = {}\n\t\t\tcontinue\n\t\t}\n\t\tconst predicate: Record<string, unknown> = {}\n\t\tconst missingKeys: string[] = []\n\t\tfor (const [field, key] of Object.entries(bindings)) {\n\t\t\tconst value = claims[key]\n\t\t\tif (value === undefined || value === null) {\n\t\t\t\tmissingKeys.push(key)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpredicate[field] = Array.isArray(value) ? { $in: [...value] } : value\n\t\t}\n\t\tif (missingKeys.length > 0) {\n\t\t\tdenied.push({ collection, missingKeys })\n\t\t\tcontinue\n\t\t}\n\t\tresult[collection] = predicate\n\t}\n\treturn result\n}\n\nfunction intersectScopes(grant: ScopeMap, handshake: ScopeMap | undefined): ScopeMap {\n\tconst result: ScopeMap = {}\n\tfor (const [collection, granted] of Object.entries(grant)) {\n\t\tconst requested = handshake?.[collection] ?? {}\n\t\tconst predicate: Record<string, unknown> = { ...granted }\n\t\tfor (const [field, wanted] of Object.entries(requested)) {\n\t\t\tif (!(field in granted)) {\n\t\t\t\tpredicate[field] = wanted\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst allowed = granted[field]\n\t\t\tif (isInPredicate(allowed) && isSubsetOf(wanted, allowed.$in)) {\n\t\t\t\tpredicate[field] = wanted\n\t\t\t}\n\t\t\t// Otherwise the grant wins: a handshake can never widen a granted field.\n\t\t}\n\t\tresult[collection] = predicate\n\t}\n\treturn result\n}\n\nfunction isInPredicate(value: unknown): value is { $in: unknown[] } {\n\treturn (\n\t\tvalue !== null &&\n\t\ttypeof value === 'object' &&\n\t\t!Array.isArray(value) &&\n\t\tArray.isArray((value as { $in?: unknown }).$in)\n\t)\n}\n\nfunction isSubsetOf(wanted: unknown, allowed: unknown[]): boolean {\n\tconst values = isInPredicate(wanted) ? wanted.$in : [wanted]\n\treturn values.every((value) => allowed.some((candidate) => Object.is(candidate, value)))\n}\n\nfunction mergeClaims(\n\tfromGrant: Record<string, unknown> | null,\n\tscopeValues: Record<string, unknown> | undefined,\n): Record<string, unknown> | null {\n\tif (!fromGrant && !scopeValues) return null\n\treturn { ...(scopeValues ?? {}), ...(fromGrant ?? {}) }\n}\n\nfunction withoutReservedKeys(scopes: ScopeMap): ScopeMap {\n\tconst result: ScopeMap = {}\n\tfor (const [collection, predicate] of Object.entries(scopes)) {\n\t\tif (collection === SCOPE_CLAIMS_KEY) continue\n\t\tresult[collection] = { ...(predicate ?? {}) }\n\t}\n\treturn result\n}\n\nlet warnedSchemalessClaims = false\n\nfunction warnSchemalessClaims(): void {\n\tif (warnedSchemalessClaims) return\n\twarnedSchemalessClaims = true\n\tconsole.warn(\n\t\t'[kora] The auth provider returned verified claims but no sync scopes, and this sync ' +\n\t\t\t'server has no schema, so the claims cannot be bound to any collection: sessions sync ' +\n\t\t\t'unscoped (each client chooses its own scope). Give the server store your schema ' +\n\t\t\t'(await store.setSchema(schema)) to bind them, ' +\n\t\t\t'or return explicit `scopes` from the auth provider.',\n\t)\n}\n\nfunction warnDenied(denied: DeniedScopeCollection[]): void {\n\tfor (const entry of denied) {\n\t\tconst key = `${entry.collection}:${entry.missingKeys.join(',')}`\n\t\tif (warnedDenials.has(key)) continue\n\t\twarnedDenials.add(key)\n\t\tconst keys = entry.missingKeys.map((k) => `\"${k}\"`).join(', ')\n\t\tconsole.warn(\n\t\t\t`[kora] SCOPE_REQUIRED: sync access to \"${entry.collection}\" is denied because the server grant has no verified value for ${keys}. Supply it from your auth provider (createKoraAuthServer({ scopeValues }) or resolveScopes). Kora never lets the client choose these values.`,\n\t\t)\n\t}\n}\n","import {\n\tHybridLogicalClock,\n\tcanonicalizeLegacyOperation,\n\tcanonicalizeOperationBody,\n} from '@korajs/core'\nimport type { Operation, SchemaDefinition } from '@korajs/core'\nimport { canonicalize } from '@korajs/core/internal'\nimport { operationIdMatches } from '@korajs/sync/internal'\n\n/** Rejection code for an upload reusing a stored id with other content (RT-77). */\nexport const FORGED_DUPLICATE_CODE = 'FORGED_DUPLICATE'\n\n/**\n * Whether an uploaded operation is the SAME operation as the one the server stores under\n * its id (RT-77): every field the id's hash version covers, in canonical form, is equal.\n * Only then may it be acknowledged as a duplicate (free of validators and rate charges)\n * and only the STORED operation's content ever drives effects.\n *\n * Compared per the stored operation's hash version:\n * - version 1: type, collection, recordId, data, timestamp, nodeId, atomicOps (what a\n * beta.12 id covers; an own operation renumbered by sequence repair keeps its id);\n * - version 2: also previousData, sequenceNumber, causalDeps (as a set) and schemaVersion.\n * Bodies are compared canonical (core canonical-body), version-1 updates in their legacy\n * canonical form (a cleared field stored as null), so a beta.12 client re-sending what\n * the server stored with restored nulls is the same operation. An envelope's ciphertext\n * is not compared (it is re-sealed with a fresh nonce per upload); its header fields,\n * which the envelope's AAD binds, are.\n *\n * An upload that declares no hash version matches a stored one of any version; a\n * declared version must equal the stored one.\n *\n * @param upload - The operation as uploaded (or as the server would store it)\n * @param stored - The operation the store holds under the same id\n * @returns true when they are the same operation\n */\nexport function isSameStoredOperation(upload: Operation, stored: Operation): boolean {\n\tif (upload.id !== stored.id) return false\n\tconst storedVersion = stored.hashVersion ?? 1\n\tif (upload.hashVersion !== undefined && upload.hashVersion !== storedVersion) return false\n\tconst a = contentKey(upload, storedVersion)\n\tconst b = contentKey(stored, storedVersion)\n\treturn a !== null && a === b\n}\n\nfunction contentKey(op: Operation, version: 1 | 2): string | null {\n\tlet body: Operation\n\ttry {\n\t\tbody = canonicalizeOperationBody(\n\t\t\tversion === 1 ? canonicalizeLegacyOperation({ ...op, hashVersion: undefined }) : op,\n\t\t)\n\t} catch {\n\t\t// A body with no canonical form is never the same as a stored (canonical) one.\n\t\treturn null\n\t}\n\tconst atomicOps =\n\t\tbody.atomicOps !== undefined && Object.keys(body.atomicOps).length > 0 ? body.atomicOps : null\n\tconst key: Record<string, unknown> = {\n\t\ttype: op.type,\n\t\tcollection: op.collection,\n\t\trecordId: op.recordId,\n\t\tdata: body.data,\n\t\ttimestamp: HybridLogicalClock.serialize(op.timestamp),\n\t\tnodeId: op.nodeId,\n\t\tatomicOps,\n\t\tsealed: op.encrypted !== undefined,\n\t}\n\tif (version === 2) {\n\t\tkey.previousData = body.previousData\n\t\tkey.sequenceNumber = op.sequenceNumber\n\t\tkey.causalDeps = [...op.causalDeps].sort()\n\t\tkey.schemaVersion = op.schemaVersion\n\t}\n\treturn canonicalize(key)\n}\n\n/**\n * {@link isSameStoredOperation}, plus the stored copies earlier releases REWROTE under\n * the original id (RT-84): before transforms ran at fold time, a server stored a\n * schema-transformed operation (and beta.12 servers stored protocol-1 ciphertext\n * re-encrypted per upload) under the id of what the client sent, without a hash\n * version. Such a copy is not the content its id names, so its body can never equal an\n * honest re-upload. It is recognised by exactly that: it declares no hash version and\n * its id does not verify against its own content (with every beta.12 hash rebuild).\n * For it, identity is the header the id was computed with and the server never\n * rewrote: id, node, type, collection, record and timestamp. Effects of a duplicate are\n * still derived from the STORED copy only (RT-77), so this widens nothing an upload\n * could influence.\n *\n * Copies stored by this release are the operation as uploaded (plus a verified hash\n * version declaration and a beta.12 clear made explicit, both identical under the id),\n * so they always take the exact comparison.\n *\n * @param upload - The operation as uploaded\n * @param stored - The operation the store holds under the same id\n * @param schema - The server schema (for beta.12 nested-member hash rebuilds)\n */\nexport async function isSameOperationAsStored(\n\tupload: Operation,\n\tstored: Operation,\n\tschema: SchemaDefinition | null,\n): Promise<boolean> {\n\tif (isSameStoredOperation(upload, stored)) return true\n\tif (upload.id !== stored.id) return false\n\tif (stored.hashVersion !== undefined || stored.encrypted !== undefined) return false\n\tif (await operationIdMatches(stored, schema)) return false\n\treturn sameHeader(upload, stored)\n}\n\n/**\n * Whether an upload is a device's echo of ANOTHER node's operation that the device's\n * earlier release stored REWRITTEN (RT-84): before transforms ran at fold time, devices\n * stored a delivered operation of another schema version as its transformed copy under\n * the original id (keeping its declared hash version). Such a body does not verify\n * against its id; with the header the id covers equal to the stored operation's, the\n * echo is that operation. The caller acknowledges it as a duplicate (effects come from\n * the stored copy only, RT-77) instead of refusing it, which would make the echoing\n * device record a refusal of someone else's write.\n *\n * @param upload - The echoed operation (of a node other than the session's)\n * @param stored - The operation the store holds under the same id\n * @param schema - The server schema (for beta.12 hash rebuilds)\n */\nexport async function isRewrittenEcho(\n\tupload: Operation,\n\tstored: Operation,\n\tschema: SchemaDefinition | null,\n): Promise<boolean> {\n\tif (upload.id !== stored.id || !sameHeader(upload, stored)) return false\n\tif (upload.encrypted !== undefined) return false\n\treturn !(await operationIdMatches(upload, schema))\n}\n\nfunction sameHeader(a: Operation, b: Operation): boolean {\n\treturn (\n\t\ta.nodeId === b.nodeId &&\n\t\ta.type === b.type &&\n\t\ta.collection === b.collection &&\n\t\ta.recordId === b.recordId &&\n\t\tHybridLogicalClock.serialize(a.timestamp) === HybridLogicalClock.serialize(b.timestamp)\n\t)\n}\n","import type {\n\tFoldState,\n\tHLCTimestamp,\n\tOperation,\n\tRecordFieldVersions,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { getFoldFieldVersions, hashBlob } from '@korajs/core'\nimport { filterFoldStateFields, serializeServerFoldState } from '../store/record-fold'\nimport type { MaterializedRecord } from '../store/server-store'\n\n/**\n * A scope-entry operation. `foldState` is server-authored (RT-29): the record's\n * serialized fold state, restricted to the fields in `data`. A receiver that folds\n * joins it into its own state instead of resolving each field by last-write-wins\n * against `fieldVersions`, so richtext, counter, max/min, element-set, key-map and\n * resolver fields merge exactly as on the server. `fieldVersions` stays for older\n * clients. Declared here as well as on `Operation` (protocol v2) so this module\n * compiles against a core that predates the field.\n */\nexport type ScopeEntryOperation = Operation & { foldState?: string }\n\n/**\n * Node id of server-synthesized scope-entry operations (RT-19). Reserved (`kora:`\n * prefix): no device can claim it, and no device ever uploads it, because every\n * scope-entry operation has sequence number 0, which no version-vector range covers.\n */\nexport const SCOPE_ENTRY_NODE_ID = 'kora:scope-entry'\n\n/** True when an operation is a server-synthesized scope entry. */\nexport function isScopeEntryOperation(op: Operation): boolean {\n\treturn op.nodeId === SCOPE_ENTRY_NODE_ID\n}\n\n/** Input to {@link buildScopeEntryOperation}. */\nexport interface ScopeEntryInput {\n\t/** The stored operation that moved the record into the session's scope. */\n\ttrigger: Operation\n\t/** The record's current materialized row (live, inside the session's scope). */\n\trow: MaterializedRecord\n\t/** The server schema (decides which row columns are record fields). */\n\tschema: SchemaDefinition\n\t/**\n\t * The record's newest stored HLC timestamp (its latest field write). Used as the\n\t * entry's timestamp only when per-field versions are unavailable (a custom store\n\t * without {@link ScopeEntryInput.fieldVersions}): a whole-row stamp is then the\n\t * best the server can do.\n\t */\n\ttimestamp: HLCTimestamp\n\t/**\n\t * Per-field versions folded from the record's stored operations (RT-27). When\n\t * present, the entry carries each field's own version and is stamped with the\n\t * record's creation time, so a receiver resolves every field by last-write-wins\n\t * against its own version of that field and keeps any newer local edit.\n\t */\n\tfieldVersions?: RecordFieldVersions | null\n\t/**\n\t * The record's fold state (W7, RT-29). When present the entry carries it, filtered\n\t * to the fields the entry restates, and per-field versions are derived from it when\n\t * `fieldVersions` is absent.\n\t */\n\tfoldState?: FoldState | null\n\t/** Server schema version stamped on the entry. */\n\tschemaVersion: number\n}\n\n/**\n * Build the scope-entry operation for a record that moved INTO a session's download\n * scope (RT-19, SRV-2, NEW-SRV-3).\n *\n * Since RT-14 a record's earlier operations are judged on the scope values they had\n * when applied, so a new owner never receives the history written while the record\n * belonged to someone else. Without more, the new owner receives only the\n * scope-changing update, which a client cannot materialize (it has no row). The\n * entry closes that gap: an `insert` carrying the record's CURRENT values (never its\n * history), so the client materializes exactly what the server holds now.\n *\n * Properties:\n * - **Deterministic id.** Derived from (collection, recordId, trigger op id), so\n * every path and every resend yields the same id and a client applies it once\n * (content-addressed dedup).\n * - **System node.** {@link SCOPE_ENTRY_NODE_ID}, sequence 0, no causal deps: it\n * never enters a client's version vector or upload delta.\n * - **Per-field versions (RT-27).** Every field carries the version of the write\n * that produced its current value, and the entry's timestamp is the record's\n * creation, so a receiver resolves each field by last-write-wins against its own\n * version of it: a device's newer unsynced edit of a field the server last wrote\n * long ago is kept (it uploads and wins on the server too), and `createdAt` is the\n * record's real creation time. Without versions (a custom store) the entry falls\n * back to one stamp, the record's newest HLC.\n *\n * @param input - Trigger, current row, schema and the record's newest timestamp\n * @returns The synthesized insert\n */\nexport async function buildScopeEntryOperation(\n\tinput: ScopeEntryInput,\n): Promise<ScopeEntryOperation> {\n\tconst { trigger, row, schema } = input\n\tconst definition = schema.collections[trigger.collection]\n\tconst data: Record<string, unknown> = {}\n\tconst foldState = input.foldState ?? null\n\tconst versioned =\n\t\tinput.fieldVersions ?? (foldState ? getFoldFieldVersions(foldState) : null) ?? null\n\tconst fieldVersions: Record<string, HLCTimestamp> = {}\n\tfor (const field of Object.keys(definition?.fields ?? {})) {\n\t\tif (!(field in row)) continue\n\t\tconst value = row[field]\n\t\tif (value === undefined) continue\n\t\tdata[field] = toWireValue(value)\n\t\tif (versioned) {\n\t\t\t// A column no operation ever wrote (a later schema default) is as old as\n\t\t\t// the record itself.\n\t\t\tfieldVersions[field] = { ...(versioned.fields[field] ?? versioned.created) }\n\t\t}\n\t}\n\tconst id = await hashBlob(\n\t\tnew TextEncoder().encode(\n\t\t\t`scope-entry\\u0000${trigger.collection}\\u0000${trigger.recordId}\\u0000${trigger.id}`,\n\t\t),\n\t)\n\tconst entry: ScopeEntryOperation = {\n\t\tid: `scope-entry-${id}`,\n\t\tnodeId: SCOPE_ENTRY_NODE_ID,\n\t\ttype: 'insert',\n\t\tcollection: trigger.collection,\n\t\trecordId: trigger.recordId,\n\t\tdata,\n\t\tpreviousData: null,\n\t\ttimestamp: versioned ? { ...versioned.created } : { ...input.timestamp },\n\t\tsequenceNumber: 0,\n\t\tcausalDeps: [],\n\t\tschemaVersion: input.schemaVersion,\n\t\t...(versioned ? { fieldVersions } : {}),\n\t\t...(foldState\n\t\t\t? { foldState: serializeServerFoldState(filterFoldStateFields(foldState, Object.keys(data))) }\n\t\t\t: {}),\n\t}\n\treturn entry\n}\n\n/**\n * Binary column values (richtext state) travel as the canonical tagged\n * `{ $koraBytes: base64 }` form, like client-authored operations.\n */\nfunction toWireValue(value: unknown): unknown {\n\tif (value instanceof Uint8Array) {\n\t\tlet binary = ''\n\t\tfor (const byte of value) binary += String.fromCharCode(byte)\n\t\treturn { $koraBytes: btoa(binary) }\n\t}\n\treturn value\n}\n","import { DEFAULT_MAX_OPERATION_BYTES as CORE_DEFAULT_MAX_OPERATION_BYTES } from '@korajs/core'\nimport { measureOperationBytes as measureCoreOperationBytes } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\n\n/**\n * Default maximum serialized size of a single operation at server ingest (256 KiB). The\n * same value the local write path enforces by default (core value domain, RT-86).\n */\nexport const DEFAULT_MAX_OPERATION_BYTES = CORE_DEFAULT_MAX_OPERATION_BYTES\n\n/** Default maximum operations accepted per client session per minute. */\nexport const DEFAULT_MAX_OPS_PER_MINUTE = 600\n\n/** Default blob chunk requests accepted per client session per minute (RT-24). */\nexport const DEFAULT_MAX_BLOB_REQUESTS_PER_MINUTE = 6000\n\n/**\n * Rate-limit units one uploaded batch costs for the server's stored-id lookup (RT-39).\n * Operations the lookup finds already stored are acknowledged without further charge,\n * so a device re-uploading its history pays per batch, not per operation; the unit is\n * credited against the batch's first operation that is charged, so a batch of new\n * operations costs exactly one unit per operation.\n */\nexport const BATCH_LOOKUP_RATE_COST = 1\n\n/** Default largest operation batch a session accepts in one message. */\nexport const DEFAULT_MAX_OPS_PER_BATCH = 1000\n\n/**\n * UTF-8 byte length of an operation's JSON, for size guards. The core definition, so the\n * local write path and the server measure an operation identically (RT-86).\n */\nexport function measureOperationBytes(op: Operation): number {\n\treturn measureCoreOperationBytes(op)\n}\n\nexport interface OperationSizeValidation {\n\tvalid: boolean\n\tbytes: number\n\tmessage?: string\n}\n\n/**\n * Returns false when an operation exceeds the configured byte limit.\n */\nexport function validateOperationSize(\n\top: Operation,\n\tmaxBytes: number = DEFAULT_MAX_OPERATION_BYTES,\n): OperationSizeValidation {\n\tconst bytes = measureOperationBytes(op)\n\tif (bytes <= maxBytes) {\n\t\treturn { valid: true, bytes }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tbytes,\n\t\tmessage: `Operation \"${op.id}\" exceeds max size (${String(bytes)} > ${String(maxBytes)} bytes)`,\n\t}\n}\n\n/**\n * Default per-principal ingest budget as a multiple of the per-node budget: a user's\n * devices share it, and one device (bounded by its node budget) never meets it.\n */\nexport const DEFAULT_USER_BUDGET_MULTIPLIER = 4\n\n/** What a session charges uploaded operations to. */\nexport interface IngestRateLimiter {\n\t/** Units allowed per window (the tightest applicable budget). */\n\treadonly limit: number\n\t/** Charge `count` units; false when a budget is exceeded (the units are refused). */\n\tallow(count?: number): boolean\n\t/** Milliseconds until a refused unit may be retried. */\n\tretryAfterMs(): number\n}\n\n/**\n * Simple sliding-window rate limiter for per-session operation ingest.\n */\nexport class SessionRateLimiter implements IngestRateLimiter {\n\tprivate windowStartMs = Date.now()\n\tprivate count = 0\n\n\t/**\n\t * @param maxOpsPerMinute - Units allowed per window\n\t * @param windowMs - Window length (one minute; shorter only in tests)\n\t */\n\tconstructor(\n\t\tprivate readonly maxOpsPerMinute: number = DEFAULT_MAX_OPS_PER_MINUTE,\n\t\tprivate readonly windowMs: number = 60_000,\n\t) {}\n\n\tget limit(): number {\n\t\treturn this.maxOpsPerMinute\n\t}\n\n\t/** Record N operations and return false when the limit is exceeded. */\n\tallow(count = 1): boolean {\n\t\tconst now = Date.now()\n\t\tif (now - this.windowStartMs >= this.windowMs) {\n\t\t\tthis.windowStartMs = now\n\t\t\tthis.count = 0\n\t\t}\n\t\tthis.count += count\n\t\treturn this.count <= this.maxOpsPerMinute\n\t}\n\n\t/** True when `count` more units fit in the current window (charges nothing). */\n\twouldAllow(count = 1): boolean {\n\t\tconst now = Date.now()\n\t\tconst used = now - this.windowStartMs >= this.windowMs ? 0 : this.count\n\t\treturn used + count <= this.maxOpsPerMinute\n\t}\n\n\t/** Milliseconds until the current window resets (when a refused unit may retry). */\n\tretryAfterMs(): number {\n\t\treturn Math.max(0, this.windowStartMs + this.windowMs - Date.now())\n\t}\n\n\treset(): void {\n\t\tthis.windowStartMs = Date.now()\n\t\tthis.count = 0\n\t}\n}\n\n/**\n * A device node's ingest budget combined with its principal's (one user, many nodes).\n * A refusal by the user budget spends none of the node's, and a node over its own\n * budget spends none of the user's, so one runaway node cannot drain its siblings'\n * shared budget beyond its own per-node limit (per-node fairness holds).\n */\nexport class CombinedRateLimiter implements IngestRateLimiter {\n\tconstructor(\n\t\tprivate readonly node: SessionRateLimiter,\n\t\tprivate readonly user: SessionRateLimiter,\n\t) {}\n\n\tget limit(): number {\n\t\treturn Math.min(this.node.limit, this.user.limit)\n\t}\n\n\tallow(count = 1): boolean {\n\t\tif (!this.user.wouldAllow(count)) {\n\t\t\t// Refused by the shared budget: the node keeps its units for later.\n\t\t\treturn false\n\t\t}\n\t\tif (!this.node.allow(count)) return false\n\t\treturn this.user.allow(count)\n\t}\n\n\tretryAfterMs(): number {\n\t\tconst blockers = [this.node, this.user].filter((limiter) => !limiter.wouldAllow(1))\n\t\tif (blockers.length === 0) return 0\n\t\treturn Math.max(...blockers.map((limiter) => limiter.retryAfterMs()))\n\t}\n}\n","import type { BlobRef, KoraEventEmitter, Operation, OperationTransform } from '@korajs/core'\nimport { KoraError, SyncError, generateUUIDv7, isBlobRef } from '@korajs/core'\nimport { SimpleEventEmitter } from '@korajs/core/internal'\nimport type { AwarenessUpdateMessage, MessageSerializer, YjsDocUpdateMessage } from '@korajs/sync'\nimport { HTTP_SYNC_SESSION_HEADER, JsonMessageSerializer } from '@korajs/sync'\nimport {\n\ttype ApplyServerOperationOptions,\n\ttype ApplyServerOperationResult,\n\tapplyServerOperation,\n} from '../apply/apply-server-operation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { NoAuthProvider } from '../auth/no-auth'\nimport { AwarenessRelay } from '../awareness/awareness-relay'\nimport { ServerMetricsCollector, estimateByteSize } from '../diagnostics/server-metrics-collector'\nimport { EncryptionKeyService } from '../encryption/key-record-service'\nimport type { Logger } from '../logging/structured-logger'\nimport { createDefaultLogger } from '../logging/structured-logger'\nimport { BlobAccessIndex } from '../richtext/blob-access-index'\nimport { BlobChunkRelay } from '../richtext/blob-chunk-relay'\nimport { YjsDocRelay } from '../richtext/yjs-doc-relay'\nimport { ClientSession } from '../session/client-session'\nimport {\n\tCombinedRateLimiter,\n\tDEFAULT_MAX_OPS_PER_MINUTE,\n\tDEFAULT_USER_BUDGET_MULTIPLIER,\n\ttype IngestRateLimiter,\n\tSessionRateLimiter,\n} from '../session/session-operation-limits'\nimport type { MaterializedRecord, ServerStore } from '../store/server-store'\nimport { HttpServerTransport } from '../transport/http-server-transport'\nimport type { ServerTransport } from '../transport/server-transport'\nimport {\n\tDEFAULT_WS_HEARTBEAT_INTERVAL_MS,\n\tDEFAULT_WS_MAX_BUFFERED_BYTES,\n\tWsServerTransport,\n\ttype WsWebSocket,\n} from '../transport/ws-server-transport'\nimport type {\n\tAuthContext,\n\tAuthProvider,\n\tHttpSyncRequest,\n\tHttpSyncResponse,\n\tKoraSyncServerConfig,\n\tServerStatus,\n\tTerminateSessionsFilter,\n} from '../types'\nimport { type ProductionHttpRouteContext, createRouteContext } from './route-context'\n\n/**\n * Default connection ceiling (SRV-6). Unlimited before beta.13; a bound keeps a flood\n * of idle or half-open sockets from exhausting memory and file descriptors. 0 means\n * unlimited.\n */\nexport const DEFAULT_MAX_CONNECTIONS = 10_000\n/** Default interval of the application-level heartbeat message (LMS #12). */\nexport const DEFAULT_APP_HEARTBEAT_INTERVAL_MS = 25_000\n/**\n * Upper bound on remembered per-node rate limiters. A flood of fresh node ids cannot\n * grow the map past it; the least recently used entries go first.\n */\nconst MAX_TRACKED_RATE_LIMITERS = 100_000\n/** Window of the per-node ingest rate limiter. */\nconst RATE_LIMIT_WINDOW_MS = 60_000\n\n/**\n * The limiter tracked under `key` in `map`, created on first use. Re-inserted on every\n * use so the map's insertion order is least-recently-used order, and bounded by\n * {@link MAX_TRACKED_RATE_LIMITERS}.\n */\nfunction trackedLimiter(\n\tmap: Map<string, { limiter: SessionRateLimiter; lastUsedAtMs: number }>,\n\tkey: string,\n\tperMinute: number,\n): SessionRateLimiter {\n\tconst now = Date.now()\n\tconst existing = map.get(key)\n\tif (existing) {\n\t\texisting.lastUsedAtMs = now\n\t\tmap.delete(key)\n\t\tmap.set(key, existing)\n\t\treturn existing.limiter\n\t}\n\tconst limiter = new SessionRateLimiter(perMinute, RATE_LIMIT_WINDOW_MS)\n\tmap.set(key, { limiter, lastUsedAtMs: now })\n\twhile (map.size > MAX_TRACKED_RATE_LIMITERS) {\n\t\tconst oldest = map.keys().next().value\n\t\tif (oldest === undefined) break\n\t\tmap.delete(oldest)\n\t}\n\treturn limiter\n}\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\nconst DEFAULT_HOST = '0.0.0.0'\nconst DEFAULT_PATH = '/'\nconst DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS = 2000\nconst DEFAULT_DELIVERY_POLL_INTERVAL_MS = 2000\nconst DEFAULT_HTTP_SESSION_IDLE_TIMEOUT_MS = 2 * 60_000\n/** Default interval between re-validations of live sessions' credentials (RT-18). */\nexport const DEFAULT_SESSION_REVALIDATION_INTERVAL_MS = 30_000\n/** Bytes of randomness in a server-issued HTTP session id (256 bits). */\nconst HTTP_SESSION_ID_BYTES = 32\n/** Default largest WebSocket message accepted (the ws library default is 100 MiB). */\nexport const DEFAULT_MAX_MESSAGE_BYTES = 32 * 1024 * 1024\n\n/**\n * The `ws` permessage-deflate setting for a `perMessageDeflate` config value (LMS #11).\n * `true`/omitted: compress messages of 1 KiB or more with no compression context kept\n * between messages (bounded memory per connection); `false`: off; an object: as is.\n *\n * @internal Shared by the standalone server and `createProductionServer`.\n */\nexport function resolvePerMessageDeflate(\n\toption: boolean | Record<string, unknown> | undefined,\n): false | Record<string, unknown> {\n\tif (option === false) return false\n\tif (option === undefined || option === true) {\n\t\treturn {\n\t\t\tthreshold: 1024,\n\t\t\tserverNoContextTakeover: true,\n\t\t\tclientNoContextTakeover: true,\n\t\t\tzlibDeflateOptions: { level: 6, memLevel: 8 },\n\t\t\tconcurrencyLimit: 10,\n\t\t}\n\t}\n\treturn option\n}\n\n/**\n * Minimal interface for a ws.WebSocketServer instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsServerLike {\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tclose(callback?: (err?: Error) => void): void\n\taddress(): { port: number } | string | null\n}\n\n/**\n * Constructor type for creating a WebSocket server.\n */\nexport type WsServerConstructor = new (options: {\n\tport?: number\n\thost?: string\n\tpath?: string\n\tmaxPayload?: number\n\tperMessageDeflate?: false | Record<string, unknown>\n}) => WsServerLike\n\nfunction validateIntervalOption(name: string, value: number): number {\n\tif (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {\n\t\tthrow new SyncError(`${name} must be a non-negative integer number of milliseconds`, {\n\t\t\t[name]: value,\n\t\t})\n\t}\n\treturn value\n}\n\n/**\n * Self-hosted sync server. Accepts WebSocket connections from clients,\n * handles the sync protocol, stores operations, and relays changes\n * between connected clients.\n *\n * Two modes of operation:\n * 1. **Standalone**: Call `start()` with a port — creates its own WebSocket server.\n * 2. **Attach**: Call `handleConnection(transport)` — attach to an existing HTTP server.\n */\nexport class KoraSyncServer {\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly maxConnections: number\n\tprivate readonly batchSize: number\n\tprivate readonly relayRetransmitIntervalMs: number\n\tprivate readonly deliveryPollIntervalMs: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\t/** The store's re-fold for the configured transforms (RT-84), awaited by start(). */\n\tprivate storeTransformsReady: Promise<void> | undefined\n\tprivate readonly port: number | undefined\n\tprivate readonly host: string\n\tprivate readonly path: string\n\tprivate readonly logger: Logger\n\tprivate readonly metrics: ServerMetricsCollector\n\n\tprivate readonly awarenessRelay = new AwarenessRelay()\n\tprivate readonly yjsDocRelay = new YjsDocRelay()\n\tprivate readonly blobChunkRelay: BlobChunkRelay\n\t/** Wrapped encryption key records (ENC-1, D4b), persisted in the server store. */\n\tprivate readonly encryptionKeys: EncryptionKeyService\n\t/** Which blob hashes each download scope may obtain (RT-1). */\n\tprivate readonly blobAccess: BlobAccessIndex\n\tprivate readonly persistBlobChunk:\n\t\t| ((hash: string, bytes: Uint8Array) => Promise<void> | void)\n\t\t| null\n\tprivate readonly maxOperationBytes: number | undefined\n\tprivate readonly maxOpsPerMinute: number | undefined\n\t/** Per-principal ingest budget per minute; 0 when disabled. */\n\tprivate readonly maxOpsPerMinutePerUser: number\n\tprivate readonly allowLegacyAnonymousClaims: boolean | undefined\n\tprivate readonly anonymousClaimTtlMs: number | undefined\n\tprivate readonly maxOpsPerBatch: number | undefined\n\tprivate readonly maxMessageBytes: number\n\tprivate readonly heartbeatIntervalMs: number\n\tprivate readonly appHeartbeatIntervalMs: number\n\tprivate readonly encryptionPolicy:\n\t\t| { required: boolean; allowPlaintextMigration?: boolean }\n\t\t| undefined\n\tprivate readonly handshakeTimeoutMs: number | undefined\n\tprivate readonly maxBufferedBytes: number\n\tprivate readonly deliveryHighWaterBytes: number | undefined\n\tprivate readonly perMessageDeflate: false | Record<string, unknown>\n\t/**\n\t * Ingest rate limiters by device node id, shared by that node's sessions so a\n\t * reconnect does not reset the budget (SRV-6). Entries idle past the window are\n\t * dropped by the background tick; insertion order doubles as LRU order.\n\t */\n\tprivate readonly rateLimiters = new Map<\n\t\tstring,\n\t\t{ limiter: SessionRateLimiter; lastUsedAtMs: number }\n\t>()\n\t/**\n\t * Ingest budgets by authenticated principal, shared by every node of that user, so\n\t * minting node ids does not multiply the per-node budget. Expired like the node map.\n\t */\n\tprivate readonly userRateLimiters = new Map<\n\t\tstring,\n\t\t{ limiter: SessionRateLimiter; lastUsedAtMs: number }\n\t>()\n\tprivate readonly blobLimits: NonNullable<KoraSyncServerConfig['blobLimits']>\n\tprivate readonly validateOperation: OperationValidator | undefined\n\tprivate readonly koraContext: ProductionHttpRouteContext\n\tprivate readonly sessions = new Map<string, ClientSession>()\n\t/**\n\t * HTTP long-poll sessions by their server-issued, high-entropy id (RT-2). Each is\n\t * bound to the principal that opened it; every request must re-authenticate as it.\n\t */\n\tprivate readonly httpSessions = new Map<string, HttpSessionEntry>()\n\t/** Internal ClientSession id -> HTTP session id, for cleanup on close. */\n\tprivate readonly httpSessionIdBySession = new Map<string, string>()\n\tprivate readonly httpSessionIdleTimeoutMs: number\n\t// Informational value reported by getStatus(). Keep in sync with the\n\t// @korajs/server package version on release; it is not used for protocol negotiation.\n\tprivate readonly serverVersion = '1.0.0-beta.0'\n\tprivate wsServer: WsServerLike | null = null\n\tprivate running = false\n\t/**\n\t * Periodic tick that retransmits relay batches connected clients have not\n\t * acknowledged, so a relay dropped by a lossy transport is redelivered instead of\n\t * leaving that client with a permanent version-vector gap (a lost operation).\n\t */\n\tprivate relayRetransmitTimer: ReturnType<typeof setInterval> | null = null\n\tprivate deliveryPollTimer: ReturnType<typeof setInterval> | null = null\n\tprivate lastObservedDeliverySequence = 0\n\tprivate deliveryPollInFlight = false\n\t/**\n\t * Re-validates every live session's credential against the auth provider, so a\n\t * revocation persisted by ANOTHER server instance (whose in-process revocation\n\t * listeners never reach this one) still ends the session here (RT-18).\n\t */\n\tprivate readonly sessionRevalidationIntervalMs: number\n\tprivate sessionRevalidationTimer: ReturnType<typeof setInterval> | null = null\n\tprivate lastSessionRevalidationAtMs = 0\n\tprivate sessionRevalidationInFlight: Promise<number> | null = null\n\t/** Unsubscribes from the auth provider's revocation feed (AUTH-11). */\n\tprivate revocationUnsubscribe: (() => void) | null = null\n\t/**\n\t * Relay operations a client never acknowledged before it disconnected, buffered by\n\t * client node id so they can be redelivered on its next connection. Bounded per\n\t * node and expired by age so a client that never returns cannot grow this forever.\n\t */\n\tprivate readonly orphanedRelaysByNode = new Map<\n\t\tstring,\n\t\t{ ops: Operation[]; bufferedAtMs: number }\n\t>()\n\tprivate static readonly MAX_ORPHANED_RELAY_OPS_PER_NODE = 5000\n\tprivate static readonly ORPHANED_RELAY_TTL_MS = 5 * 60_000\n\n\tconstructor(config: KoraSyncServerConfig) {\n\t\tthis.store = config.store\n\t\tconst storeSchemaVersion = this.store.getSchema()?.version\n\t\tif (\n\t\t\tconfig.schemaVersion !== undefined &&\n\t\t\tstoreSchemaVersion !== undefined &&\n\t\t\tconfig.schemaVersion !== storeSchemaVersion\n\t\t) {\n\t\t\tthrow new SyncError('Sync schema version does not match the configured store schema.', {\n\t\t\t\tsyncSchemaVersion: config.schemaVersion,\n\t\t\t\tstoreSchemaVersion,\n\t\t\t})\n\t\t}\n\t\tthis.auth = config.auth ?? null\n\t\tthis.serializer = config.serializer ?? new JsonMessageSerializer()\n\t\tthis.emitter = config.emitter ?? null\n\t\tthis.maxConnections = config.maxConnections ?? DEFAULT_MAX_CONNECTIONS\n\t\tthis.batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.relayRetransmitIntervalMs = validateIntervalOption(\n\t\t\t'relayRetransmitIntervalMs',\n\t\t\tconfig.relayRetransmitIntervalMs ?? DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS,\n\t\t)\n\t\tthis.deliveryPollIntervalMs = validateIntervalOption(\n\t\t\t'deliveryPollIntervalMs',\n\t\t\tconfig.deliveryPollIntervalMs ?? DEFAULT_DELIVERY_POLL_INTERVAL_MS,\n\t\t)\n\t\tthis.schemaVersion = config.schemaVersion ?? storeSchemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tthis.supportedSchemaVersions = config.supportedSchemaVersions ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = config.operationTransforms ?? [\n\t\t\t...(this.store.getOperationTransforms?.() ?? []),\n\t\t]\n\t\t// Transforms run at fold time (RT-84): the store folds every operation as the\n\t\t// server schema reads it, with exactly the transforms sessions judge with.\n\t\tif (config.operationTransforms !== undefined && this.store.setOperationTransforms) {\n\t\t\tconst ready = this.store.setOperationTransforms(this.operationTransforms)\n\t\t\tthis.storeTransformsReady = ready\n\t\t\t// Surfaced by start(); logged here for attach mode (handleConnection only).\n\t\t\tready.catch((error: unknown) => {\n\t\t\t\tthis.logger.log({\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tlevel: 'error',\n\t\t\t\t\tevent: 'server.operation_transforms_failed',\n\t\t\t\t\tdetails: { message: error instanceof Error ? error.message : String(error) },\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t\tthis.port = config.port\n\t\tthis.host = config.host ?? DEFAULT_HOST\n\t\tthis.path = config.path ?? DEFAULT_PATH\n\t\tthis.logger = config.logger ?? createDefaultLogger()\n\t\tthis.metrics = config.metricsCollector ?? new ServerMetricsCollector()\n\t\tthis.metrics.setSchemaVersion(this.schemaVersion)\n\t\tthis.blobLimits = config.blobLimits ?? {}\n\t\tthis.blobAccess = new BlobAccessIndex(this.store, config.resolveBlobChunk ?? null)\n\t\tthis.encryptionKeys = new EncryptionKeyService(this.store)\n\t\tthis.blobChunkRelay = new BlobChunkRelay(\n\t\t\tconfig.resolveBlobChunk,\n\t\t\t{\n\t\t\t\tcanReadFromStore: (requesterId, hash) => this.sessionMayReadStoredBlob(requesterId, hash),\n\t\t\t\tcanForward: (requesterId, targetId, hash) =>\n\t\t\t\t\tthis.mayForwardBlobRequest(requesterId, targetId, hash),\n\t\t\t\tobserveVerifiedBytes: (hash, bytes) => this.blobAccess.observeVerifiedBytes(hash, bytes),\n\t\t\t},\n\t\t\t{\n\t\t\t\t...(this.blobLimits.maxPendingRequestsPerSession !== undefined\n\t\t\t\t\t? { maxPendingPerSession: this.blobLimits.maxPendingRequestsPerSession }\n\t\t\t\t\t: {}),\n\t\t\t\t...(this.blobLimits.pendingRequestTtlMs !== undefined\n\t\t\t\t\t? { pendingTtlMs: this.blobLimits.pendingRequestTtlMs }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t)\n\t\tthis.sessionRevalidationIntervalMs = validateIntervalOption(\n\t\t\t'sessionRevalidationIntervalMs',\n\t\t\tconfig.sessionRevalidationIntervalMs ?? DEFAULT_SESSION_REVALIDATION_INTERVAL_MS,\n\t\t)\n\t\tthis.httpSessionIdleTimeoutMs = validateIntervalOption(\n\t\t\t'httpSessionIdleTimeoutMs',\n\t\t\tconfig.httpSessionIdleTimeoutMs ?? DEFAULT_HTTP_SESSION_IDLE_TIMEOUT_MS,\n\t\t)\n\t\tthis.maxMessageBytes = config.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES\n\t\tthis.heartbeatIntervalMs = validateIntervalOption(\n\t\t\t'heartbeatIntervalMs',\n\t\t\tconfig.heartbeatIntervalMs ?? DEFAULT_WS_HEARTBEAT_INTERVAL_MS,\n\t\t)\n\t\tthis.appHeartbeatIntervalMs = validateIntervalOption(\n\t\t\t'appHeartbeatIntervalMs',\n\t\t\tconfig.appHeartbeatIntervalMs ?? DEFAULT_APP_HEARTBEAT_INTERVAL_MS,\n\t\t)\n\t\tthis.encryptionPolicy = config.encryption ? { ...config.encryption } : undefined\n\t\tthis.handshakeTimeoutMs =\n\t\t\tconfig.handshakeTimeoutMs === undefined\n\t\t\t\t? undefined\n\t\t\t\t: validateIntervalOption('handshakeTimeoutMs', config.handshakeTimeoutMs)\n\t\tthis.maxBufferedBytes = config.maxBufferedBytes ?? DEFAULT_WS_MAX_BUFFERED_BYTES\n\t\tthis.deliveryHighWaterBytes = config.deliveryHighWaterBytes\n\t\tthis.perMessageDeflate = resolvePerMessageDeflate(config.perMessageDeflate)\n\t\tthis.persistBlobChunk = config.persistBlobChunk ?? null\n\t\tthis.maxOperationBytes = config.maxOperationBytes\n\t\tthis.maxOpsPerMinute = config.maxOpsPerMinute\n\t\tif (\n\t\t\tconfig.maxOpsPerMinutePerUser !== undefined &&\n\t\t\t(!Number.isSafeInteger(config.maxOpsPerMinutePerUser) || config.maxOpsPerMinutePerUser < 0)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`maxOpsPerMinutePerUser must be a non-negative integer (0 disables the per-user budget), got ${String(config.maxOpsPerMinutePerUser)}.`,\n\t\t\t)\n\t\t}\n\t\tthis.maxOpsPerMinutePerUser =\n\t\t\tconfig.maxOpsPerMinutePerUser ??\n\t\t\t(config.maxOpsPerMinute ?? DEFAULT_MAX_OPS_PER_MINUTE) * DEFAULT_USER_BUDGET_MULTIPLIER\n\t\tthis.allowLegacyAnonymousClaims = config.allowLegacyAnonymousClaims\n\t\tthis.anonymousClaimTtlMs = config.anonymousClaimTtlMs\n\t\tif (\n\t\t\tconfig.maxOpsPerBatch !== undefined &&\n\t\t\t(!Number.isInteger(config.maxOpsPerBatch) || config.maxOpsPerBatch < 1)\n\t\t) {\n\t\t\tthrow new SyncError('maxOpsPerBatch must be a positive integer', {\n\t\t\t\tmaxOpsPerBatch: config.maxOpsPerBatch,\n\t\t\t})\n\t\t}\n\t\tthis.maxOpsPerBatch = config.maxOpsPerBatch\n\t\tthis.validateOperation = config.validateOperation\n\t\t// One trusted data-plane context, shared by custom HTTP routes (via\n\t\t// production-server) and by the operation validator. It holds no per-request\n\t\t// state; the closures only reach back into `this` when actually invoked.\n\t\tthis.koraContext = createRouteContext(this, this.store)\n\n\t\t// If no external emitter was provided, create an internal one for\n\t\t// subscribing to session events for metrics and logging.\n\t\tif (!this.emitter) {\n\t\t\tthis.emitter = new SimpleEventEmitter()\n\t\t}\n\n\t\tthis.ensureRevocationSubscribed()\n\t}\n\n\t/**\n\t * Follow the auth provider's revocation feed, when it has one, so revoking a\n\t * device or user ends its live sessions without any wiring by the app.\n\t */\n\tprivate ensureRevocationSubscribed(): void {\n\t\tif (this.revocationUnsubscribe || !this.auth?.onRevoke) return\n\t\tthis.revocationUnsubscribe = this.auth.onRevoke((event) => {\n\t\t\tthis.terminateSessions({\n\t\t\t\t...(event.userId !== undefined ? { userId: event.userId } : {}),\n\t\t\t\t...(event.deviceId !== undefined ? { deviceId: event.deviceId } : {}),\n\t\t\t})\n\t\t})\n\t}\n\n\t/**\n\t * End live sync sessions whose credential was revoked (AUTH-11).\n\t *\n\t * Each matching session receives a retriable `AUTH_REVOKED` (or `AUTH_EXPIRED`)\n\t * error and is closed. The client refreshes its credentials and re-handshakes,\n\t * so the server authenticates it again: a still-valid device reconnects, a\n\t * revoked one is refused. Sessions still in their handshake are refused as soon\n\t * as their principal is known.\n\t *\n\t * `createKoraAuthServer().bindSyncServer(server)` calls this on device revoke,\n\t * sign-out, password reset or change, and admin revoke. A provider exposing\n\t * `onRevoke` (the built-in one does) is followed automatically.\n\t *\n\t * @param filter - `userId` ends every session of that user; with `deviceId`,\n\t * only that device's sessions. At least one of the two is required.\n\t * @returns The number of established sessions that were closed\n\t *\n\t * @example\n\t * ```typescript\n\t * server.terminateSessions({ userId: 'u1', deviceId: 'laptop' })\n\t * ```\n\t */\n\tterminateSessions(filter: TerminateSessionsFilter): number {\n\t\tif (filter.userId === undefined && filter.deviceId === undefined) {\n\t\t\tthrow new KoraError(\n\t\t\t\t'terminateSessions needs a userId or a deviceId; refusing to end every session.',\n\t\t\t\t'INVALID_TERMINATE_FILTER',\n\t\t\t\t{ fix: 'Pass { userId } to end a user, or { userId, deviceId } to end one device.' },\n\t\t\t)\n\t\t}\n\t\tconst code = filter.code ?? 'AUTH_REVOKED'\n\t\tlet terminated = 0\n\t\tfor (const session of [...this.sessions.values()]) {\n\t\t\tif (session.terminateIfMatches(filter, code)) terminated++\n\t\t}\n\t\tif (terminated > 0) {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'sessions.terminated',\n\t\t\t\tcount: terminated,\n\t\t\t\tdetails: {\n\t\t\t\t\tcode,\n\t\t\t\t\t...(filter.userId !== undefined ? { userId: filter.userId } : {}),\n\t\t\t\t\t...(filter.deviceId !== undefined ? { deviceId: filter.deviceId } : {}),\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\treturn terminated\n\t}\n\n\t/**\n\t * Admin release of a device node id (RT-5). The next principal to handshake with\n\t * this node id claims it, even when the node already has operation history.\n\t *\n\t * Use it to hand over operation history written before node claims existed (an\n\t * upgrade from beta.12, where nobody may adopt such a node until it is released),\n\t * or to reassign a lost device's node id. Live sessions on that node id are ended\n\t * with a retriable `NODE_RELEASED` error so the handover starts clean.\n\t *\n\t * @param nodeId - The device node id to release\n\t * @returns True when the node had a claim or history to release; false when it\n\t * was unknown or the store does not support node claims\n\t *\n\t * @example\n\t * ```typescript\n\t * await server.releaseNodeClaim('0190a1b2-...')\n\t * ```\n\t */\n\tasync releaseNodeClaim(nodeId: string): Promise<boolean> {\n\t\tif (!this.store.releaseNodeClaim) return false\n\t\tconst released = await this.store.releaseNodeClaim(nodeId)\n\t\tif (released) {\n\t\t\tfor (const session of [...this.sessions.values()]) {\n\t\t\t\tif (session.getClientNodeId() === nodeId && session.getState() !== 'connected') {\n\t\t\t\t\tsession.endForNodeRelease()\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'node_claim.released',\n\t\t\t\tnodeId,\n\t\t\t})\n\t\t}\n\t\treturn released\n\t}\n\n\tprivate ensureBackgroundTimersStarted(): void {\n\t\tif (this.relayRetransmitIntervalMs > 0 && !this.relayRetransmitTimer) {\n\t\t\tthis.relayRetransmitTimer = setInterval(() => {\n\t\t\t\tthis.retransmitPendingRelays(this.relayRetransmitIntervalMs)\n\t\t\t}, this.relayRetransmitIntervalMs)\n\t\t\tthis.relayRetransmitTimer.unref?.()\n\t\t}\n\n\t\tif (this.deliveryPollIntervalMs > 0 && !this.deliveryPollTimer) {\n\t\t\tthis.deliveryPollTimer = setInterval(() => {\n\t\t\t\tvoid this.pollDeliveryLog()\n\t\t\t}, this.deliveryPollIntervalMs)\n\t\t\tthis.deliveryPollTimer.unref?.()\n\t\t}\n\n\t\tif (\n\t\t\tthis.sessionRevalidationIntervalMs > 0 &&\n\t\t\t!this.sessionRevalidationTimer &&\n\t\t\tthis.auth !== null &&\n\t\t\t!(this.auth instanceof NoAuthProvider)\n\t\t) {\n\t\t\tthis.sessionRevalidationTimer = setInterval(() => {\n\t\t\t\tvoid this.revalidateSessions()\n\t\t\t}, this.sessionRevalidationIntervalMs)\n\t\t\tthis.sessionRevalidationTimer.unref?.()\n\t\t}\n\t}\n\n\t/**\n\t * Re-validate the credential of every live session with the auth provider and end\n\t * the sessions whose credential is no longer accepted (RT-18).\n\t *\n\t * Revocations are persisted by the auth stores (token, device and per-user\n\t * cut-offs), but `onRevoke` listeners only run in the process that handled the\n\t * revocation. Every instance therefore re-checks its own live sessions\n\t * periodically (`sessionRevalidationIntervalMs`, default 30 seconds, also driven by\n\t * the delivery poll tick) by authenticating the session's credential again. A\n\t * session whose credential is refused, or now resolves to another principal, gets\n\t * a retriable `AUTH_REVOKED` (or `AUTH_EXPIRED`) and is closed. A provider error\n\t * (for example the auth database is unreachable) ends nothing: it is logged and the\n\t * next pass retries, so an outage does not disconnect every client.\n\t *\n\t * @returns The number of sessions ended by this pass\n\t *\n\t * @example\n\t * ```typescript\n\t * // After revoking through another instance's admin API:\n\t * await server.revalidateSessions()\n\t * ```\n\t */\n\trevalidateSessions(): Promise<number> {\n\t\tif (this.sessionRevalidationInFlight) return this.sessionRevalidationInFlight\n\t\tconst run = (async (): Promise<number> => {\n\t\t\tthis.lastSessionRevalidationAtMs = Date.now()\n\t\t\tlet terminated = 0\n\t\t\tfor (const session of [...this.sessions.values()]) {\n\t\t\t\tconst outcome = await session.revalidateCredential()\n\t\t\t\tif (outcome === 'terminated') terminated++\n\t\t\t\tif (outcome === 'error') {\n\t\t\t\t\tthis.logger.log({\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\tlevel: 'warn',\n\t\t\t\t\t\tevent: 'session.revalidation_failed',\n\t\t\t\t\t\tsessionId: session.getSessionId(),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (terminated > 0) {\n\t\t\t\tthis.logger.log({\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tlevel: 'info',\n\t\t\t\t\tevent: 'sessions.terminated',\n\t\t\t\t\tcount: terminated,\n\t\t\t\t\tdetails: { code: 'AUTH_REVOKED', reason: 'revalidation' },\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn terminated\n\t\t})()\n\t\tthis.sessionRevalidationInFlight = run\n\t\tvoid run.finally(() => {\n\t\t\tif (this.sessionRevalidationInFlight === run) this.sessionRevalidationInFlight = null\n\t\t})\n\t\treturn run\n\t}\n\n\t/** Run {@link revalidateSessions} from the delivery poll tick once the interval elapsed. */\n\tprivate maybeRevalidateSessions(now = Date.now()): void {\n\t\tif (this.sessionRevalidationIntervalMs <= 0) return\n\t\tif (this.auth === null || this.auth instanceof NoAuthProvider) return\n\t\tif (now - this.lastSessionRevalidationAtMs < this.sessionRevalidationIntervalMs) return\n\t\tvoid this.revalidateSessions()\n\t}\n\n\t/**\n\t * Retransmit relay batches that connected clients have not acknowledged within\n\t * `staleMs`. Called on a periodic tick and directly by tests. Redelivering an\n\t * already-applied operation is harmless (clients dedup by content-addressed id).\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.retransmitPendingRelays(staleMs)\n\t\t}\n\t\tthis.expireOrphanedRelays()\n\t\tthis.expireIdleHttpSessions()\n\t\tthis.expireIdleRateLimiters()\n\t}\n\n\t/**\n\t * The ingest rate limiter of a device node, created on first use and shared by\n\t * every session of that node, so reconnecting does not buy a fresh budget (SRV-6).\n\t */\n\tprivate rateLimiterFor(nodeId: string, principal: string | null): IngestRateLimiter {\n\t\tconst node = trackedLimiter(\n\t\t\tthis.rateLimiters,\n\t\t\tnodeId,\n\t\t\tthis.maxOpsPerMinute ?? DEFAULT_MAX_OPS_PER_MINUTE,\n\t\t)\n\t\tif (principal === null || this.maxOpsPerMinutePerUser === 0) return node\n\t\tconst user = trackedLimiter(this.userRateLimiters, principal, this.maxOpsPerMinutePerUser)\n\t\treturn new CombinedRateLimiter(node, user)\n\t}\n\n\t/**\n\t * Forget rate limiters of nodes with no live session whose window has long\n\t * passed: their budget would be full again anyway.\n\t */\n\tprivate expireIdleRateLimiters(now = Date.now()): void {\n\t\tif (this.rateLimiters.size === 0) return\n\t\tconst live = new Set<string>()\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tconst nodeId = session.getClientNodeId()\n\t\t\tif (nodeId !== null) live.add(nodeId)\n\t\t}\n\t\tconst cutoff = now - 2 * RATE_LIMIT_WINDOW_MS\n\t\tfor (const [nodeId, entry] of this.rateLimiters) {\n\t\t\tif (entry.lastUsedAtMs <= cutoff && !live.has(nodeId)) this.rateLimiters.delete(nodeId)\n\t\t}\n\t\t// A user budget is touched at every handshake of its nodes; one idle past two\n\t\t// windows would be full again anyway. A live session keeps its own reference.\n\t\tfor (const [principal, entry] of this.userRateLimiters) {\n\t\t\tif (entry.lastUsedAtMs <= cutoff) this.userRateLimiters.delete(principal)\n\t\t}\n\t}\n\n\t/** Close HTTP long-poll sessions that sent no request within the idle timeout. */\n\tprivate expireIdleHttpSessions(now = Date.now()): void {\n\t\tif (this.httpSessionIdleTimeoutMs <= 0 || this.httpSessions.size === 0) return\n\t\tconst cutoff = now - this.httpSessionIdleTimeoutMs\n\t\tfor (const entry of [...this.httpSessions.values()]) {\n\t\t\tif (entry.lastSeenAtMs <= cutoff) {\n\t\t\t\tentry.transport.close(4008, 'http session idle')\n\t\t\t\t// A closed session left only for its final messages is dropped too.\n\t\t\t\tthis.httpSessions.delete(entry.id)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Check whether the authoritative delivery log advanced without passing through\n\t * this server instance, then wake delivery-watermark sessions to scan from their\n\t * own acknowledged cursors. Session-level filtering remains the only fan-out path.\n\t */\n\tasync pollDeliveryLog(): Promise<void> {\n\t\tif (this.deliveryPollInFlight) return\n\t\tthis.deliveryPollInFlight = true\n\t\tthis.maybeRevalidateSessions()\n\t\ttry {\n\t\t\tconst maxDeliverySequence = await this.store.getMaxDeliverySequence()\n\t\t\tif (maxDeliverySequence > this.lastObservedDeliverySequence) {\n\t\t\t\tconst previous = this.lastObservedDeliverySequence\n\t\t\t\tthis.lastObservedDeliverySequence = maxDeliverySequence\n\t\t\t\t// Records may have changed through another instance: drop the blob access\n\t\t\t\t// sets of the collections written since the last poll (RT-17).\n\t\t\t\tawait this.invalidateBlobAccessSince(previous, maxDeliverySequence)\n\t\t\t}\n\t\t\t// Each session sends what is above its send cursor (operations committed\n\t\t\t// through another instance), and re-sends an unacknowledged delivery only once\n\t\t\t// it made no progress for the poll interval, backed off while it stays stuck\n\t\t\t// (SRV-3, LMS #12: a stuck or ghost client is not re-sent its backlog forever).\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.pushDeliveryStreamIfSupported(this.deliveryPollIntervalMs, {\n\t\t\t\t\ttrackStall: true,\n\t\t\t\t\tserverFrontier: maxDeliverySequence,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'delivery_poll.failed',\n\t\t\t\tdetails: { error: error instanceof Error ? error.message : String(error) },\n\t\t\t})\n\t\t} finally {\n\t\t\tthis.deliveryPollInFlight = false\n\t\t}\n\t}\n\n\t/**\n\t * Invalidate cached blob access sets for the collections written between two\n\t * delivery frontiers. Falls back to dropping every set when the gap is large.\n\t */\n\tprivate async invalidateBlobAccessSince(from: number, to: number): Promise<void> {\n\t\tconst MAX_SCANNED = 1000\n\t\tif (to - from > MAX_SCANNED) {\n\t\t\tthis.blobAccess.invalidate()\n\t\t\treturn\n\t\t}\n\t\ttry {\n\t\t\tconst delivered = await this.store.getOperationsAfterDelivery(from, MAX_SCANNED)\n\t\t\tthis.blobAccess.invalidate(collectionsOf(delivered.map((d) => d.operation)))\n\t\t} catch {\n\t\t\tthis.blobAccess.invalidate()\n\t\t}\n\t}\n\n\t/**\n\t * The blob reference authority shared by every session and route (RT-11).\n\t * @internal Used by the route context; not part of the public API.\n\t */\n\tgetBlobAccessIndex(): BlobAccessIndex {\n\t\treturn this.blobAccess\n\t}\n\n\t/**\n\t * Buffer relay operations a disconnected client never acknowledged, keyed by its\n\t * node id, deduped by operation id and bounded by count. Redelivered when the\n\t * client reconnects (see {@link takeOrphanedRelays}).\n\t */\n\tprivate bufferOrphanedRelays(nodeId: string, ops: Operation[]): void {\n\t\tif (ops.length === 0) return\n\t\tconst existing = this.orphanedRelaysByNode.get(nodeId)\n\t\tconst merged = existing ? existing.ops : []\n\t\tconst seen = new Set(merged.map((op) => op.id))\n\t\tfor (const op of ops) {\n\t\t\tif (!seen.has(op.id)) {\n\t\t\t\tmerged.push(op)\n\t\t\t\tseen.add(op.id)\n\t\t\t}\n\t\t}\n\t\t// Keep only the most recent ops if the buffer is oversized.\n\t\tconst bounded =\n\t\t\tmerged.length > KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE\n\t\t\t\t? merged.slice(merged.length - KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE)\n\t\t\t\t: merged\n\t\tthis.orphanedRelaysByNode.set(nodeId, { ops: bounded, bufferedAtMs: Date.now() })\n\t}\n\n\t/** Remove and return a node's buffered orphaned relay operations, if any. */\n\tprivate takeOrphanedRelays(nodeId: string): Operation[] {\n\t\tconst entry = this.orphanedRelaysByNode.get(nodeId)\n\t\tif (!entry) return []\n\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\treturn entry.ops\n\t}\n\n\t/** Drop buffered orphaned relays older than the TTL (client never returned). */\n\tprivate expireOrphanedRelays(): void {\n\t\tif (this.orphanedRelaysByNode.size === 0) return\n\t\tconst cutoff = Date.now() - KoraSyncServer.ORPHANED_RELAY_TTL_MS\n\t\tfor (const [nodeId, entry] of this.orphanedRelaysByNode) {\n\t\t\tif (entry.bufferedAtMs <= cutoff) {\n\t\t\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * The trusted, scoped data-plane context (`apply` / `query` / `findById`).\n\t * Shared with the production server so HTTP routes, the operation validator,\n\t * and `server.kora` are all the same object over the same pipeline.\n\t */\n\tgetKoraContext(): ProductionHttpRouteContext {\n\t\treturn this.koraContext\n\t}\n\n\t/**\n\t * Subscribe to session-level events for metrics collection and logging.\n\t * Called when a new session is created.\n\t */\n\tprivate attachSessionEvents(sessionId: string, sessionEmitter: KoraEventEmitter): void {\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize, {\n\t\t\t\tunique: event.uniqueOperations ?? event.batchSize,\n\t\t\t\tduplicates: event.duplicateOperations ?? 0,\n\t\t\t\trejected: event.rejectedOperations ?? 0,\n\t\t\t})\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:unverified-legacy-operation', () => {\n\t\t\tthis.metrics.recordUnverifiedLegacyOperation()\n\t\t})\n\n\t\tsessionEmitter.on('sync:forged-duplicate', () => {\n\t\t\tthis.metrics.recordForgedDuplicate()\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: { reason: event.reason },\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\t}\n\n\t/**\n\t * Get the metrics collector for external access (e.g., HTTP endpoints).\n\t */\n\tgetMetricsCollector(): ServerMetricsCollector {\n\t\treturn this.metrics\n\t}\n\n\t/**\n\t * Get the logger for external access (e.g., event streaming).\n\t */\n\tgetLogger(): Logger {\n\t\treturn this.logger\n\t}\n\n\t/**\n\t * Start the WebSocket server in standalone mode.\n\t *\n\t * @param wsServerImpl - Optional WebSocket server constructor for testing\n\t */\n\tasync start(wsServerImpl?: WsServerConstructor): Promise<void> {\n\t\tif (this.running) {\n\t\t\tthrow new SyncError('Server is already running', { port: this.port })\n\t\t}\n\t\tawait this.storeTransformsReady\n\n\t\tif (!wsServerImpl && this.port === undefined) {\n\t\t\tthrow new SyncError(\n\t\t\t\t'Port is required for standalone mode. Provide port in config or use handleConnection() for attach mode.',\n\t\t\t\t{},\n\t\t\t)\n\t\t}\n\n\t\tif (wsServerImpl) {\n\t\t\tthis.wsServer = new wsServerImpl({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t\tmaxPayload: this.maxMessageBytes,\n\t\t\t\tperMessageDeflate: this.perMessageDeflate,\n\t\t\t})\n\t\t} else {\n\t\t\t// Dynamic import of ws — only needed in standalone mode\n\t\t\tconst { WebSocketServer } = await import('ws')\n\t\t\tthis.wsServer = new WebSocketServer({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t\tmaxPayload: this.maxMessageBytes,\n\t\t\t\tperMessageDeflate: this.perMessageDeflate,\n\t\t\t})\n\t\t}\n\n\t\tthis.wsServer.on('connection', (ws: unknown) => {\n\t\t\ttry {\n\t\t\t\tthis.handleWebSocket(ws as WsWebSocket)\n\t\t\t} catch {\n\t\t\t\t// Refused (for example the connection limit): handleConnection already\n\t\t\t\t// told the client and closed the socket.\n\t\t\t}\n\t\t})\n\n\t\tthis.running = true\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.started',\n\t\t\tdetails: { port: this.port, host: this.host, path: this.path },\n\t\t})\n\t}\n\n\t/**\n\t * Stop the server. Closes all sessions and the WebSocket server.\n\t */\n\tasync stop(): Promise<void> {\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopping',\n\t\t\tdetails: { connectedClients: this.sessions.size },\n\t\t})\n\n\t\t// Stop the relay retransmit tick and drop buffered orphaned relays.\n\t\tif (this.relayRetransmitTimer) {\n\t\t\tclearInterval(this.relayRetransmitTimer)\n\t\t\tthis.relayRetransmitTimer = null\n\t\t}\n\t\tif (this.deliveryPollTimer) {\n\t\t\tclearInterval(this.deliveryPollTimer)\n\t\t\tthis.deliveryPollTimer = null\n\t\t}\n\t\tif (this.sessionRevalidationTimer) {\n\t\t\tclearInterval(this.sessionRevalidationTimer)\n\t\t\tthis.sessionRevalidationTimer = null\n\t\t}\n\t\tthis.orphanedRelaysByNode.clear()\n\t\tthis.rateLimiters.clear()\n\t\tthis.userRateLimiters.clear()\n\t\tthis.revocationUnsubscribe?.()\n\t\tthis.revocationUnsubscribe = null\n\n\t\t// Clean up awareness relay\n\t\tthis.awarenessRelay.clear()\n\t\tthis.yjsDocRelay.clear()\n\t\tthis.blobChunkRelay.clear()\n\n\t\t// Close all active sessions (works in both standalone and attach mode)\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.close('server shutting down')\n\t\t}\n\t\tthis.sessions.clear()\n\t\tthis.httpSessions.clear()\n\t\tthis.httpSessionIdBySession.clear()\n\n\t\t// Close WebSocket server (standalone mode only)\n\t\tif (this.wsServer) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tthis.wsServer?.close(() => resolve())\n\t\t\t})\n\t\t\tthis.wsServer = null\n\t\t}\n\n\t\tthis.running = false\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopped',\n\t\t})\n\t}\n\n\t/**\n\t * Handle one HTTP sync request for a long-polling client.\n\t *\n\t * The POST that opens a session (the handshake, sent without `sessionId`) creates\n\t * it and answers with a server-issued, high-entropy session id in the\n\t * `x-kora-session` response header. Every later request must name that id.\n\t *\n\t * With an auth provider, EVERY request is authenticated from its `authorization`\n\t * header and must resolve to the same principal (user, device and anonymity) as\n\t * the request that opened the session and as the session's handshake, so knowing\n\t * a session id alone grants nothing (RT-2). Sessions with no request for\n\t * `httpSessionIdleTimeoutMs` are closed.\n\t *\n\t * Responses: 202 (POST accepted), 200/204/304 (GET), 400 (malformed), 401\n\t * (credential missing or invalid), 403 (credential of another principal), 404\n\t * (unknown or expired session), 405 (method), 410 (session closed).\n\t */\n\tasync handleHttpRequest(request: HttpSyncRequest): Promise<HttpSyncResponse> {\n\t\tif (request.method !== 'GET' && request.method !== 'POST') {\n\t\t\treturn { status: 405, headers: { allow: 'GET, POST' } }\n\t\t}\n\t\tthis.expireIdleHttpSessions()\n\n\t\tconst authenticated = await this.authenticateHttpRequest(request.authorization)\n\t\tif (authenticated === 'unauthorized') {\n\t\t\treturn { status: 401, headers: { 'www-authenticate': 'Bearer' } }\n\t\t}\n\n\t\tif (request.sessionId === undefined || request.sessionId.length === 0) {\n\t\t\t// Only the POST carrying the handshake may open a session.\n\t\t\tif (request.method !== 'POST' || request.body === undefined) {\n\t\t\t\treturn { status: 400 }\n\t\t\t}\n\t\t\tconst entry = this.openHttpSession(authenticated)\n\t\t\tentry.transport.receive(normalizeHttpBody(request.body, request.contentType))\n\t\t\treturn {\n\t\t\t\tstatus: 202,\n\t\t\t\theaders: { [HTTP_SYNC_SESSION_HEADER]: entry.id },\n\t\t\t}\n\t\t}\n\n\t\tconst entry = this.httpSessions.get(request.sessionId)\n\t\tif (!entry) {\n\t\t\treturn { status: 404 }\n\t\t}\n\t\tif (!this.httpPrincipalMatches(entry, authenticated)) {\n\t\t\treturn { status: 403 }\n\t\t}\n\t\tentry.lastSeenAtMs = Date.now()\n\n\t\tif (request.method === 'POST') {\n\t\t\tif (request.body === undefined) {\n\t\t\t\treturn { status: 400 }\n\t\t\t}\n\t\t\tif (!entry.transport.isConnected()) {\n\t\t\t\treturn { status: 410 }\n\t\t\t}\n\t\t\tentry.transport.receive(normalizeHttpBody(request.body, request.contentType))\n\t\t\treturn { status: 202 }\n\t\t}\n\n\t\tconst polled = entry.transport.poll(request.ifNoneMatch)\n\t\tif (!entry.transport.isConnected() && !entry.transport.hasPending()) {\n\t\t\tthis.httpSessions.delete(entry.id)\n\t\t}\n\t\treturn {\n\t\t\tstatus: polled.status,\n\t\t\tbody: polled.body,\n\t\t\theaders: polled.headers,\n\t\t}\n\t}\n\n\t/**\n\t * Authenticate one HTTP request. Returns the principal identity, null when the\n\t * server has no real auth provider, or 'unauthorized'.\n\t */\n\tprivate async authenticateHttpRequest(\n\t\tauthorization: string | undefined,\n\t): Promise<HttpPrincipal | null | 'unauthorized'> {\n\t\tif (!this.auth || this.auth instanceof NoAuthProvider) return null\n\t\tconst token = parseBearer(authorization)\n\t\tif (token === null) return 'unauthorized'\n\t\tlet context: AuthContext | null\n\t\ttry {\n\t\t\tcontext = await this.auth.authenticate(token)\n\t\t} catch {\n\t\t\treturn 'unauthorized'\n\t\t}\n\t\treturn context ? principalOf(context) : 'unauthorized'\n\t}\n\n\t/**\n\t * True when a request's principal is the one that opened the session and, once\n\t * the handshake authenticated, the session's own principal.\n\t */\n\tprivate httpPrincipalMatches(entry: HttpSessionEntry, principal: HttpPrincipal | null): boolean {\n\t\tif (!samePrincipal(entry.principal, principal)) return false\n\t\tconst session = this.sessions.get(entry.sessionId)\n\t\tconst handshakePrincipal = session?.getPrincipal()\n\t\tif (handshakePrincipal && !samePrincipal(principalOf(handshakePrincipal), principal)) {\n\t\t\t// The handshake authenticated someone other than the HTTP credential: the\n\t\t\t// session cannot be trusted by either; end it.\n\t\t\tentry.transport.close(4003, 'http principal mismatch')\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t}\n\n\t/**\n\t * Handle an accepted WebSocket (attach mode with `ws`): wraps it in a\n\t * {@link WsServerTransport} configured like the standalone server's (serializer,\n\t * ping/pong liveness probing, send-buffer ceiling) and starts a session.\n\t *\n\t * @param ws - A `ws` WebSocket from `WebSocketServer.handleUpgrade` or `connection`\n\t * @returns The session ID\n\t */\n\thandleWebSocket(ws: WsWebSocket): string {\n\t\treturn this.handleConnection(\n\t\t\tnew WsServerTransport(ws, {\n\t\t\t\tserializer: this.serializer,\n\t\t\t\theartbeatIntervalMs: this.heartbeatIntervalMs,\n\t\t\t\tmaxBufferedBytes: this.maxBufferedBytes,\n\t\t\t}),\n\t\t)\n\t}\n\n\t/**\n\t * Handle an incoming client connection (attach mode).\n\t * Creates a new ClientSession for the transport.\n\t *\n\t * @param transport - The server transport for the new connection\n\t * @returns The session ID\n\t */\n\thandleConnection(transport: ServerTransport): string {\n\t\tthis.ensureRevocationSubscribed()\n\t\t// Check max connections\n\t\tif (this.maxConnections > 0 && this.sessions.size >= this.maxConnections) {\n\t\t\ttransport.send({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tcode: 'MAX_CONNECTIONS',\n\t\t\t\tmessage: `Server has reached maximum connections (${this.maxConnections})`,\n\t\t\t\tretriable: true,\n\t\t\t})\n\t\t\ttransport.close(4029, 'max connections reached')\n\t\t\tthis.metrics.recordError()\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'connection.rejected',\n\t\t\t\tdetails: { reason: 'max_connections', max: this.maxConnections },\n\t\t\t})\n\t\t\tthrow new SyncError('Maximum connections reached', {\n\t\t\t\tcurrent: this.sessions.size,\n\t\t\t\tmax: this.maxConnections,\n\t\t\t})\n\t\t}\n\n\t\tthis.ensureBackgroundTimersStarted()\n\n\t\tconst sessionId = generateUUIDv7()\n\t\tthis.metrics.recordConnection(sessionId)\n\n\t\t// Create a per-session emitter so we can track events with session context.\n\t\t// The session emits events on this emitter, and we listen here for metrics + logging.\n\t\tconst sessionEmitter = new SimpleEventEmitter()\n\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.metrics.updateSessionState(sessionId, 'authenticated')\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize, {\n\t\t\t\tunique: event.uniqueOperations ?? event.batchSize,\n\t\t\t\tduplicates: event.duplicateOperations ?? 0,\n\t\t\t\trejected: event.rejectedOperations ?? 0,\n\t\t\t})\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:unverified-legacy-operation', () => {\n\t\t\tthis.metrics.recordUnverifiedLegacyOperation()\n\t\t})\n\n\t\tsessionEmitter.on('sync:forged-duplicate', () => {\n\t\t\tthis.metrics.recordForgedDuplicate()\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', () => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:delivery-stalled', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.delivery_stalled',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\twatermark: event.watermark,\n\t\t\t\t\toutstandingMaxDeliverySequence: event.outstandingMaxDeliverySequence,\n\t\t\t\t\trepeatCount: event.repeatCount,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tconst session = new ClientSession({\n\t\t\tsessionId,\n\t\t\ttransport,\n\t\t\tstore: this.store,\n\t\t\tauth: this.auth ?? undefined,\n\t\t\tserializer: this.serializer,\n\t\t\temitter: sessionEmitter,\n\t\t\tlogger: this.logger,\n\t\t\tbatchSize: this.batchSize,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tsupportedSchemaVersions: this.supportedSchemaVersions,\n\t\t\toperationTransforms: this.operationTransforms,\n\t\t\tonRelay: (sourceSessionId, operations) => {\n\t\t\t\tthis.handleRelay(sourceSessionId, operations)\n\t\t\t},\n\t\t\tonAwarenessUpdate: (sourceSessionId, message) => {\n\t\t\t\tthis.handleAwarenessRelay(sourceSessionId, message)\n\t\t\t},\n\t\t\tonYjsDocUpdate: (sourceSessionId, message, storedRecord) => {\n\t\t\t\tthis.handleYjsDocRelay(sourceSessionId, message, storedRecord)\n\t\t\t},\n\t\t\tonBlobChunkRequest: (sourceSessionId, message) => {\n\t\t\t\tvoid this.blobChunkRelay.handleRequest(sourceSessionId, message)\n\t\t\t},\n\t\t\tonBlobChunkResponse: (sourceSessionId, message) => {\n\t\t\t\tvoid this.blobChunkRelay.handleResponse(sourceSessionId, message)\n\t\t\t},\n\t\t\t...(this.persistBlobChunk ? { persistBlobChunk: this.persistBlobChunk } : {}),\n\t\t\t...(this.blobLimits.maxChunkBytes !== undefined\n\t\t\t\t? { maxBlobChunkBytes: this.blobLimits.maxChunkBytes }\n\t\t\t\t: {}),\n\t\t\t...(this.blobLimits.maxBytesPerSession !== undefined\n\t\t\t\t? { maxBlobBytesPerSession: this.blobLimits.maxBytesPerSession }\n\t\t\t\t: {}),\n\t\t\tencryptionKeys: this.encryptionKeys,\n\t\t\tonEncryptionKeyWritten: (sourceSessionId, owner, keyring, record) => {\n\t\t\t\t// Every other live device of the same owner learns the new record at once\n\t\t\t\t// (rotation, passphrase change), before the operations sealed under it.\n\t\t\t\tfor (const [sid, other] of this.sessions) {\n\t\t\t\t\tif (sid === sourceSessionId) continue\n\t\t\t\t\tif (other.getEncryptionKeyOwner() === owner) {\n\t\t\t\t\t\tother.pushEncryptionKeyRecord(keyring, record)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t// Side channels are joined only after an accepted handshake, never at connect.\n\t\t\tonReady: (sid) => {\n\t\t\t\tthis.yjsDocRelay.addClient(sid, transport)\n\t\t\t\tthis.blobChunkRelay.addClient(sid, transport)\n\t\t\t},\n\t\t\t// Only forward when configured, so an unset server value leaves the\n\t\t\t// session on its own documented default rather than `undefined`.\n\t\t\t...(this.maxOperationBytes !== undefined\n\t\t\t\t? { maxOperationBytes: this.maxOperationBytes }\n\t\t\t\t: {}),\n\t\t\t...(this.maxOpsPerMinute !== undefined ? { maxOpsPerMinute: this.maxOpsPerMinute } : {}),\n\t\t\t...(this.blobLimits.maxRequestsPerMinute !== undefined\n\t\t\t\t? { maxBlobRequestsPerMinute: this.blobLimits.maxRequestsPerMinute }\n\t\t\t\t: {}),\n\t\t\t...(this.maxOpsPerBatch !== undefined ? { maxOpsPerBatch: this.maxOpsPerBatch } : {}),\n\t\t\t...(this.validateOperation\n\t\t\t\t? { validateOperation: this.validateOperation, koraContext: this.koraContext }\n\t\t\t\t: {}),\n\t\t\tblobAccess: this.blobAccess,\n\t\t\t...(this.allowLegacyAnonymousClaims !== undefined\n\t\t\t\t? { allowLegacyAnonymousClaims: this.allowLegacyAnonymousClaims }\n\t\t\t\t: {}),\n\t\t\t...(this.anonymousClaimTtlMs !== undefined\n\t\t\t\t? { anonymousClaimTtlMs: this.anonymousClaimTtlMs }\n\t\t\t\t: {}),\n\t\t\tisNodeLive: (nodeId, exceptSessionId) => this.isNodeLive(nodeId, exceptSessionId),\n\t\t\trateLimiterFor: (nodeId, principal) => this.rateLimiterFor(nodeId, principal),\n\t\t\tappHeartbeatIntervalMs: this.appHeartbeatIntervalMs,\n\t\t\tauthoritativeNodeIds: this.authoritativeNodeIds,\n\t\t\t...(this.encryptionPolicy ? { encryption: this.encryptionPolicy } : {}),\n\t\t\t...(this.handshakeTimeoutMs !== undefined\n\t\t\t\t? { handshakeTimeoutMs: this.handshakeTimeoutMs }\n\t\t\t\t: {}),\n\t\t\t...(this.deliveryHighWaterBytes !== undefined\n\t\t\t\t? { deliveryHighWaterBytes: this.deliveryHighWaterBytes }\n\t\t\t\t: {}),\n\t\t\tonClose: (sid) => {\n\t\t\t\tthis.handleSessionClose(sid)\n\t\t\t},\n\t\t\tonOrphanedRelays: (nodeId, ops) => {\n\t\t\t\tthis.bufferOrphanedRelays(nodeId, ops)\n\t\t\t},\n\t\t\ttakeOrphanedRelays: (nodeId) => this.takeOrphanedRelays(nodeId),\n\t\t})\n\n\t\tthis.sessions.set(sessionId, session)\n\t\tsession.start()\n\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'session.connected',\n\t\t\tsessionId,\n\t\t\tdetails: { totalSessions: this.sessions.size },\n\t\t})\n\n\t\treturn sessionId\n\t}\n\n\t/**\n\t * Get the current server status.\n\t */\n\tasync getStatus(): Promise<ServerStatus> {\n\t\tconst totalOps = await this.store.getOperationCount()\n\t\tconst snapshot = this.metrics.getSnapshot(totalOps)\n\t\treturn {\n\t\t\trunning: this.running,\n\t\t\tconnectedClients: snapshot.connectedClients,\n\t\t\tport: this.port ?? null,\n\t\t\ttotalOperations: snapshot.totalOperations,\n\t\t\tuptime: snapshot.uptime,\n\t\t\tversion: this.serverVersion,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tconnectedNodeIds: snapshot.connectedNodeIds,\n\t\t\tpeakConnections: snapshot.peakConnections,\n\t\t\tconnectionsTotal: snapshot.connectionsTotal,\n\t\t\toperationsReceived: snapshot.operationsReceived,\n\t\t\toperationsSent: snapshot.operationsSent,\n\t\t\terrorCount: snapshot.errorCount,\n\t\t}\n\t}\n\n\t/**\n\t * Apply a server-originated operation (for example one created by a custom\n\t * HTTP route) through the same validated pipeline that incoming client\n\t * operations use — Tier 2 constraints, referential integrity, and cascade\n\t * side effects — then relay every applied operation to connected clients.\n\t *\n\t * Because the operation did not come from a client session, it is relayed to\n\t * ALL sessions (there is no source session to exclude). Each session still\n\t * applies its own per-scope visibility filter in `relayOperations`, so a\n\t * client only receives the operation if it falls within that client's scope.\n\t *\n\t * @param op - A fully-formed, server-originated operation to apply\n\t * @param options - Optional in-store authorization (used by scoped routes)\n\t * @returns The apply result, including any server-generated side-effect ops\n\t */\n\tasync applyLocalOperation(\n\t\top: Operation,\n\t\toptions: ApplyServerOperationOptions = {},\n\t): Promise<ApplyServerOperationResult> {\n\t\tconst result = await applyServerOperation(this.store, op, undefined, options)\n\n\t\tif (result.result === 'applied' && result.appliedOperations.length > 0) {\n\t\t\tthis.blobAccess.invalidate(collectionsOf(result.appliedOperations))\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.relayOperations(result.appliedOperations)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Relay already-applied, server-originated operations to every connected client.\n\t * Used by the conditional route apply, which commits its operations atomically\n\t * through the store (bypassing {@link applyLocalOperation}) and then fans them\n\t * out. Each session still enforces its own per-scope visibility filter.\n\t *\n\t * @param operations - Operations that have already been committed to the store\n\t */\n\trelayServerOperations(operations: Operation[]): void {\n\t\tif (operations.length === 0) {\n\t\t\treturn\n\t\t}\n\t\tthis.blobAccess.invalidate(collectionsOf(operations))\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\t/**\n\t * Collect every blob reference still reachable from live records on the server.\n\t *\n\t * This is the live set for garbage-collecting the server's central blob store:\n\t * pass the result to `collectBlobGarbage(blobStore, liveRefs)` from\n\t * `@korajs/store` to reclaim bytes no record references any more. Only\n\t * collections that declare a `blob` field are scanned.\n\t *\n\t * @returns Every live blob reference across all collections\n\t */\n\tasync getLiveBlobRefs(): Promise<BlobRef[]> {\n\t\tconst schema = this.store.getSchema()\n\t\tif (!schema) {\n\t\t\treturn []\n\t\t}\n\t\tconst refs: BlobRef[] = []\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tconst hasBlobField = Object.values(collection.fields).some((field) => field.kind === 'blob')\n\t\t\tif (!hasBlobField) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst records = await this.store.materializeCollection(name)\n\t\t\tfor (const record of records) {\n\t\t\t\tfor (const value of Object.values(record)) {\n\t\t\t\t\tif (isBlobRef(value)) {\n\t\t\t\t\t\trefs.push(value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn refs\n\t}\n\n\t/**\n\t * Get the number of currently connected clients.\n\t */\n\tgetConnectionCount(): number {\n\t\treturn this.sessions.size\n\t}\n\n\t/**\n\t * Node ids whose operations win `merge('server-authoritative')` fields in the fold\n\t * (W7): the store's own node id, which authors every server-originated operation\n\t * (side effects, constraint corrections, route writes), plus any extras the store\n\t * was configured with (`authoritativeNodeIds` store option). This is the one source\n\t * of truth: every session advertises exactly this list in the handshake, so clients\n\t * fold with the same authority as the server's stores.\n\t */\n\tget authoritativeNodeIds(): string[] {\n\t\treturn this.store.getAuthoritativeNodeIds?.() ?? [this.store.getNodeId()]\n\t}\n\n\t// --- Private ---\n\n\t/**\n\t * Blob access policy (RT-1): true when the session is streaming and a live record\n\t * inside its download scope references the hash. Gates the central store.\n\t */\n\tprivate async sessionReferencesBlob(sessionId: string, hash: string): Promise<boolean> {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session || !session.isStreaming()) return false\n\t\treturn this.blobAccess.isReferenced(session.getDownlinkScopes(), hash)\n\t}\n\n\t/** True when a session other than `exceptSessionId` is connected as `nodeId`. */\n\tprivate isNodeLive(nodeId: string, exceptSessionId: string): boolean {\n\t\tfor (const [sessionId, session] of this.sessions) {\n\t\t\tif (sessionId === exceptSessionId) continue\n\t\t\tif (session.getState() !== 'closed' && session.getClientNodeId() === nodeId) return true\n\t\t}\n\t\treturn false\n\t}\n\n\t/**\n\t * Central-store read policy (RT-1, RT-25): the session owns the hash (it pushed\n\t * the bytes) or a live record inside its download scope references it.\n\t */\n\tprivate async sessionMayReadStoredBlob(sessionId: string, hash: string): Promise<boolean> {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session || !session.isStreaming()) return false\n\t\tif (await this.blobAccess.isOwnedBy(hash, session.getBlobOwnerKey())) return true\n\t\treturn this.blobAccess.isReferenced(session.getDownlinkScopes(), hash)\n\t}\n\n\t/**\n\t * Blob access policy (RT-1): a request may be forwarded to a peer that shares the\n\t * requester's exact download scope (the same tenant view, as for presence), which\n\t * keeps manifests handed over out of band working; across scopes, only when both\n\t * scopes reference the hash, so neither the hash nor the bytes cross a tenant.\n\t */\n\tprivate async mayForwardBlobRequest(\n\t\trequesterId: string,\n\t\ttargetId: string,\n\t\thash: string,\n\t): Promise<boolean> {\n\t\tconst requester = this.sessions.get(requesterId)\n\t\tconst target = this.sessions.get(targetId)\n\t\tif (!requester?.isStreaming() || !target?.isStreaming()) return false\n\t\t// Same tenant view (anonymous devices are each their own partition, RT-11).\n\t\tif (requester.getBlobPartitionKey() === target.getBlobPartitionKey()) return true\n\t\treturn (\n\t\t\t(await this.sessionReferencesBlob(requesterId, hash)) &&\n\t\t\t(await this.sessionReferencesBlob(targetId, hash))\n\t\t)\n\t}\n\n\tprivate handleRelay(sourceSessionId: string, operations: Operation[]): void {\n\t\tthis.blobAccess.invalidate(collectionsOf(operations))\n\t\tconst targetCount = this.sessions.size - 1\n\t\tconst byteSize = estimateOperationByteSize(operations)\n\t\tthis.metrics.recordSent(\n\t\t\tsourceSessionId,\n\t\t\toperations.length * targetCount,\n\t\t\tbyteSize * targetCount,\n\t\t)\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'operations.relayed',\n\t\t\tsessionId: sourceSessionId,\n\t\t\tcount: operations.length,\n\t\t\tbytes: byteSize * targetCount,\n\t\t\tdetails: { targetSessions: targetCount },\n\t\t})\n\n\t\tfor (const [sessionId, session] of this.sessions) {\n\t\t\tif (sessionId === sourceSessionId) continue\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\tprivate handleSessionClose(sessionId: string): void {\n\t\tthis.metrics.recordDisconnection(sessionId)\n\t\tthis.awarenessRelay.removeClient(sessionId)\n\t\tthis.yjsDocRelay.removeClient(sessionId)\n\t\tthis.blobChunkRelay.removeClient(sessionId)\n\n\t\tthis.sessions.delete(sessionId)\n\n\t\tconst httpSessionId = this.httpSessionIdBySession.get(sessionId)\n\t\tif (httpSessionId) {\n\t\t\tthis.httpSessionIdBySession.delete(sessionId)\n\t\t\t// Keep a closed HTTP session until the client polls what was queued before the\n\t\t\t// close (the error that explains it); the idle sweep drops it otherwise.\n\t\t\tif (!this.httpSessions.get(httpSessionId)?.transport.hasPending()) {\n\t\t\t\tthis.httpSessions.delete(httpSessionId)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleAwarenessRelay(sourceSessionId: string, message: AwarenessUpdateMessage): void {\n\t\t// Only sessions that completed an accepted handshake take part in presence. The\n\t\t// first update binds the session's awareness clientId (later updates must use\n\t\t// it) and its presence partition (its canonical download scope).\n\t\tconst session = this.sessions.get(sourceSessionId)\n\t\tif (!session || !session.isStreaming()) return\n\n\t\tif (!this.awarenessRelay.hasClient(sourceSessionId)) {\n\t\t\tthis.awarenessRelay.addClient(\n\t\t\t\tsourceSessionId,\n\t\t\t\tmessage.clientId,\n\t\t\t\tsession.getTransport(),\n\t\t\t\tsession.getScopePartitionKey(),\n\t\t\t)\n\t\t}\n\t\tthis.awarenessRelay.handleUpdate(sourceSessionId, message)\n\t}\n\n\tprivate handleYjsDocRelay(\n\t\tsourceSessionId: string,\n\t\tmessage: YjsDocUpdateMessage,\n\t\tstoredRecord: MaterializedRecord | null,\n\t): void {\n\t\tif (!this.sessions.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\t// The session already authorized the sender's write. Deliver only to sessions\n\t\t// whose download scope contains the stored record.\n\t\tthis.yjsDocRelay.handleUpdate(sourceSessionId, message, (targetSessionId) => {\n\t\t\tconst target = this.sessions.get(targetSessionId)\n\t\t\treturn target\n\t\t\t\t? target.canReceiveRecord(message.collection, message.recordId, storedRecord)\n\t\t\t\t: false\n\t\t})\n\t}\n\n\t/** Open a new HTTP long-poll session bound to `principal`, under a fresh random id. */\n\tprivate openHttpSession(principal: HttpPrincipal | null): HttpSessionEntry {\n\t\tconst transport = new HttpServerTransport(this.serializer, {\n\t\t\tmaxQueuedBytes: this.maxBufferedBytes,\n\t\t})\n\t\tconst sessionId = this.handleConnection(transport)\n\t\tconst entry: HttpSessionEntry = {\n\t\t\tid: generateHttpSessionId(),\n\t\t\tsessionId,\n\t\t\ttransport,\n\t\t\tprincipal,\n\t\t\tlastSeenAtMs: Date.now(),\n\t\t}\n\t\tthis.httpSessions.set(entry.id, entry)\n\t\tthis.httpSessionIdBySession.set(sessionId, entry.id)\n\t\treturn entry\n\t}\n}\n\n/** The identity an HTTP session is bound to (RT-2). */\ninterface HttpPrincipal {\n\tuserId: string\n\tdeviceId: string | null\n\tanonymous: boolean\n}\n\ninterface HttpSessionEntry {\n\t/** Server-issued, high-entropy id the client presents on every request. */\n\tid: string\n\t/** The ClientSession behind it. */\n\tsessionId: string\n\ttransport: HttpServerTransport\n\t/** Principal of the request that opened it; null without a real auth provider. */\n\tprincipal: HttpPrincipal | null\n\tlastSeenAtMs: number\n}\n\nfunction principalOf(context: AuthContext): HttpPrincipal {\n\tconst deviceId = context.metadata?.deviceId\n\treturn {\n\t\tuserId: context.userId,\n\t\tdeviceId: typeof deviceId === 'string' ? deviceId : null,\n\t\tanonymous: context.anonymous === true,\n\t}\n}\n\n/**\n * Same principal. Anonymous principals get a fresh userId per authentication, so two\n * anonymous principals match on anonymity alone; their session id is their only\n * credential.\n */\nfunction samePrincipal(a: HttpPrincipal | null, b: HttpPrincipal | null): boolean {\n\tif (a === null || b === null) return a === b\n\tif (a.anonymous || b.anonymous) return a.anonymous && b.anonymous\n\treturn a.userId === b.userId && a.deviceId === b.deviceId\n}\n\n/** The token of a `Bearer <token>` header; '' when absent (anonymous); null when malformed. */\nfunction parseBearer(authorization: string | undefined): string | null {\n\tif (authorization === undefined || authorization.trim() === '') return ''\n\tconst match = /^Bearer\\s+(\\S+)\\s*$/i.exec(authorization.trim())\n\treturn match?.[1] ?? null\n}\n\n/** 256 random bits, base64url: an unguessable HTTP session id. */\nfunction generateHttpSessionId(): string {\n\tconst bytes = new Uint8Array(HTTP_SESSION_ID_BYTES)\n\tglobalThis.crypto.getRandomValues(bytes)\n\tlet binary = ''\n\tfor (const byte of bytes) binary += String.fromCharCode(byte)\n\treturn btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/** The distinct collections a set of operations writes. */\nfunction collectionsOf(operations: Operation[]): Set<string> {\n\treturn new Set(operations.map((op) => op.collection))\n}\n\n/**\n * Estimate the total byte size of serialized operations.\n * Used for bandwidth tracking.\n */\nfunction estimateOperationByteSize(operations: Operation[]): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nfunction normalizeHttpBody(body: string | Uint8Array, contentType?: string): string | Uint8Array {\n\tif (body instanceof Uint8Array) {\n\t\treturn body\n\t}\n\n\tif (contentType?.includes('application/x-protobuf')) {\n\t\treturn new TextEncoder().encode(body)\n\t}\n\n\treturn body\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { AwarenessStateWire, AwarenessUpdateMessage, SyncMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Tracks a single client's awareness registration.\n */\ninterface AwarenessClient {\n\t/** Session ID for this client */\n\tsessionId: string\n\t/** Client-assigned awareness ID, bound to the session on its first update */\n\tclientId: number\n\t/** Transport for sending messages to this client */\n\ttransport: ServerTransport\n\t/** Current awareness state, if any */\n\tstate: AwarenessStateWire | null\n\t/**\n\t * Presence partition. Updates are only relayed between clients with the same\n\t * partition (the sync server uses the session's canonical download scope), so\n\t * presence never crosses a tenant boundary.\n\t */\n\tpartition: string\n}\n\n/** Partition used when the caller does not supply one (single-tenant setups). */\nconst DEFAULT_PARTITION = '*'\n\n/**\n * Server-side awareness relay. Broadcasts ephemeral awareness states\n * (cursor positions, user presence) between connected clients.\n *\n * Awareness data is never persisted. Each session's awareness `clientId` is bound on\n * registration: a session may only publish (or clear) its own state, never another\n * client's, and its updates reach only clients in the same partition.\n */\nexport class AwarenessRelay {\n\tprivate readonly clients = new Map<string, AwarenessClient>()\n\n\t/**\n\t * Register a client for awareness broadcasting. A session registers once; later\n\t * calls for an already-registered session are ignored, so a client cannot rebind\n\t * itself to another client's id.\n\t *\n\t * @param sessionId - Unique session identifier\n\t * @param clientId - Client-assigned awareness ID\n\t * @param transport - Transport for sending messages to this client\n\t * @param partition - Presence partition (clients only see their own partition)\n\t */\n\taddClient(\n\t\tsessionId: string,\n\t\tclientId: number,\n\t\ttransport: ServerTransport,\n\t\tpartition: string = DEFAULT_PARTITION,\n\t): void {\n\t\tif (this.clients.has(sessionId)) return\n\t\tthis.clients.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tclientId,\n\t\t\ttransport,\n\t\t\tstate: null,\n\t\t\tpartition,\n\t\t})\n\n\t\t// Send this client all existing awareness states in its partition so it catches up\n\t\tconst existingStates: Record<string, AwarenessStateWire | null> = {}\n\t\tlet hasStates = false\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === sessionId) continue\n\t\t\tif (client.partition !== partition) continue\n\t\t\tif (client.state) {\n\t\t\t\texistingStates[String(client.clientId)] = client.state\n\t\t\t\thasStates = true\n\t\t\t}\n\t\t}\n\n\t\tif (hasStates) {\n\t\t\tconst catchUpMsg: SyncMessage = {\n\t\t\t\ttype: 'awareness-update',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tclientId: 0, // Server-sourced\n\t\t\t\tstates: existingStates,\n\t\t\t}\n\t\t\ttransport.send(catchUpMsg)\n\t\t}\n\t}\n\n\t/**\n\t * True when the session is registered with the relay.\n\t *\n\t * @param sessionId - Session to check\n\t */\n\thasClient(sessionId: string): boolean {\n\t\treturn this.clients.has(sessionId)\n\t}\n\n\t/**\n\t * Remove a client and broadcast its removal to the remaining clients in its partition.\n\t *\n\t * @param sessionId - Session ID of the disconnecting client\n\t */\n\tremoveClient(sessionId: string): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client) return\n\n\t\tthis.clients.delete(sessionId)\n\n\t\t// Only broadcast removal if the client had an awareness state\n\t\tif (client.state === null) return\n\n\t\tconst removalStates: Record<string, AwarenessStateWire | null> = {\n\t\t\t[String(client.clientId)]: null,\n\t\t}\n\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'awareness-update',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tclientId: client.clientId,\n\t\t\tstates: removalStates,\n\t\t}\n\n\t\tthis.broadcastExcept(sessionId, client.partition, msg)\n\t}\n\n\t/**\n\t * Handle an incoming awareness update from a registered client.\n\t *\n\t * Only the sender's own entry is accepted: the message must be stamped with the\n\t * sender's bound `clientId`, and only `states[clientId]` is stored and relayed.\n\t * Entries for other clients are dropped, so a sender cannot overwrite or remove\n\t * anyone else's presence. The sanitized update reaches only the sender's partition.\n\t *\n\t * @param sessionId - Session ID of the sending client\n\t * @param message - The awareness update message\n\t */\n\thandleUpdate(sessionId: string, message: AwarenessUpdateMessage): void {\n\t\tconst sender = this.clients.get(sessionId)\n\t\tif (!sender) return\n\t\tif (message.clientId !== sender.clientId) return\n\n\t\tconst key = String(sender.clientId)\n\t\tif (!(key in message.states)) return\n\t\tconst senderState = message.states[key] ?? null\n\t\tsender.state = senderState\n\n\t\tconst sanitized: SyncMessage = {\n\t\t\ttype: 'awareness-update',\n\t\t\tmessageId: message.messageId,\n\t\t\tclientId: sender.clientId,\n\t\t\tstates: { [key]: senderState },\n\t\t}\n\t\tthis.broadcastExcept(sessionId, sender.partition, sanitized)\n\t}\n\n\t/**\n\t * Get the number of registered awareness clients.\n\t */\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\t/**\n\t * Remove all clients and clear all state.\n\t */\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\t// --- Private ---\n\n\tprivate broadcastExcept(excludeSessionId: string, partition: string, message: SyncMessage): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) continue\n\t\t\tif (client.partition !== partition) continue\n\t\t\tif (!client.transport.isConnected()) continue\n\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import type { AuthContext, SessionState } from '../types'\n\n/**\n * Snapshot of server-side sync metrics at a point in time.\n */\nexport interface ServerMetricsSnapshot {\n\tconnectedClients: number\n\tconnectedNodeIds: string[]\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\tbatchesReceived: number\n\tuniqueOperationsReceived: number\n\tduplicateOperationsReceived: number\n\trejectedOperations: number\n\t/**\n\t * Operations from protocol-1 (beta.12) clients stored with an id that could not be\n\t * verified (RT-71). Non-zero only while beta.12 clients write `undefined` members.\n\t */\n\tunverifiedLegacyOperations: number\n\t/** Uploads refused for reusing a stored operation id with other content (RT-77). */\n\tforgedDuplicates: number\n\toperationsSent: number\n\tbytesReceived: number\n\tbytesSent: number\n\tclients: ClientMetrics[]\n\tuptime: number\n\ttotalOperations: number\n\terrorCount: number\n\tschemaVersion: number\n}\n\n/**\n * Per-client metrics tracked by the server.\n */\nexport interface ClientMetrics {\n\tsessionId: string\n\tnodeId: string | null\n\tstate: SessionState\n\tconnectedAt: number\n\toperationsReceived: number\n\tbatchesReceived: number\n\tuniqueOperationsReceived: number\n\tduplicateOperationsReceived: number\n\trejectedOperations: number\n\toperationsSent: number\n\tauthContext: AuthContext | null\n}\n\n/**\n * Collects and aggregates server-side sync metrics.\n *\n * Tracks connected clients, throughput, error counts, and per-session\n * metadata. Designed to be hooked into KoraSyncServer lifecycle events.\n */\n/**\n * Estimate the byte size of a batch of operations.\n * Used for bandwidth tracking in sync events.\n * Each operation is approximated by JSON-serializing and measuring length.\n */\nexport function estimateByteSize(operations: Array<unknown>): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nexport class ServerMetricsCollector {\n\tprivate startedAt = Date.now()\n\n\tprivate peakConnections = 0\n\tprivate connectionsTotal = 0\n\tprivate operationsReceived = 0\n\tprivate batchesReceived = 0\n\tprivate uniqueOperationsReceived = 0\n\tprivate duplicateOperationsReceived = 0\n\tprivate rejectedOperations = 0\n\tprivate unverifiedLegacyOperations = 0\n\tprivate forgedDuplicates = 0\n\tprivate operationsSent = 0\n\tprivate bytesReceived = 0\n\tprivate bytesSent = 0\n\tprivate errorCount = 0\n\tprivate schemaVersion = 1\n\n\tprivate readonly clientMetrics = new Map<string, ClientMetrics>()\n\n\t/** Record a new client connection. */\n\trecordConnection(sessionId: string): void {\n\t\tthis.connectionsTotal++\n\t\tthis.clientMetrics.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tnodeId: null,\n\t\t\tstate: 'connected',\n\t\t\tconnectedAt: Date.now(),\n\t\t\toperationsReceived: 0,\n\t\t\tbatchesReceived: 0,\n\t\t\tuniqueOperationsReceived: 0,\n\t\t\tduplicateOperationsReceived: 0,\n\t\t\trejectedOperations: 0,\n\t\t\toperationsSent: 0,\n\t\t\tauthContext: null,\n\t\t})\n\t\tthis.peakConnections = Math.max(this.peakConnections, this.clientMetrics.size)\n\t}\n\n\t/** Record a client disconnection. */\n\trecordDisconnection(sessionId: string): void {\n\t\tthis.clientMetrics.delete(sessionId)\n\t}\n\n\t/** Update the node ID after a handshake completes. */\n\trecordHandshake(sessionId: string, nodeId: string): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.nodeId = nodeId\n\t\t}\n\t}\n\n\t/** Update session state. */\n\tupdateSessionState(sessionId: string, state: SessionState): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.state = state\n\t\t}\n\t}\n\n\t/** Record authentication context for a session. */\n\trecordAuth(sessionId: string, authContext: AuthContext | null): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.authContext = authContext\n\t\t}\n\t}\n\n\t/** Record operations received from a client. */\n\trecordReceived(\n\t\tsessionId: string,\n\t\tcount: number,\n\t\tbyteSize: number,\n\t\toutcomes: { unique: number; duplicates: number; rejected: number } = {\n\t\t\tunique: count,\n\t\t\tduplicates: 0,\n\t\t\trejected: 0,\n\t\t},\n\t): void {\n\t\tthis.operationsReceived += count\n\t\tthis.batchesReceived += 1\n\t\tthis.uniqueOperationsReceived += outcomes.unique\n\t\tthis.duplicateOperationsReceived += outcomes.duplicates\n\t\tthis.rejectedOperations += outcomes.rejected\n\t\tthis.bytesReceived += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsReceived += count\n\t\t\tclient.batchesReceived += 1\n\t\t\tclient.uniqueOperationsReceived += outcomes.unique\n\t\t\tclient.duplicateOperationsReceived += outcomes.duplicates\n\t\t\tclient.rejectedOperations += outcomes.rejected\n\t\t}\n\t}\n\n\t/** Record operations sent to a client. */\n\trecordSent(sessionId: string, count: number, byteSize: number): void {\n\t\tthis.operationsSent += count\n\t\tthis.bytesSent += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsSent += count\n\t\t}\n\t}\n\n\t/** Record an operation stored with an unverified legacy id (RT-71). */\n\trecordUnverifiedLegacyOperation(): void {\n\t\tthis.unverifiedLegacyOperations++\n\t}\n\n\t/** Record an upload refused for reusing a stored id with other content (RT-77). */\n\trecordForgedDuplicate(): void {\n\t\tthis.forgedDuplicates++\n\t}\n\n\t/** Record an error. */\n\trecordError(): void {\n\t\tthis.errorCount++\n\t}\n\n\t/** Set the schema version. */\n\tsetSchemaVersion(version: number): void {\n\t\tthis.schemaVersion = version\n\t}\n\n\t/** Return a full snapshot of current metrics. */\n\tgetSnapshot(totalOperations: number): ServerMetricsSnapshot {\n\t\treturn {\n\t\t\tconnectedClients: this.clientMetrics.size,\n\t\t\tconnectedNodeIds: Array.from(this.clientMetrics.values())\n\t\t\t\t.filter((c) => c.nodeId !== null)\n\t\t\t\t.map((c) => c.nodeId as string),\n\t\t\tpeakConnections: this.peakConnections,\n\t\t\tconnectionsTotal: this.connectionsTotal,\n\t\t\toperationsReceived: this.operationsReceived,\n\t\t\tbatchesReceived: this.batchesReceived,\n\t\t\tuniqueOperationsReceived: this.uniqueOperationsReceived,\n\t\t\tduplicateOperationsReceived: this.duplicateOperationsReceived,\n\t\t\trejectedOperations: this.rejectedOperations,\n\t\t\tunverifiedLegacyOperations: this.unverifiedLegacyOperations,\n\t\t\tforgedDuplicates: this.forgedDuplicates,\n\t\t\toperationsSent: this.operationsSent,\n\t\t\tbytesReceived: this.bytesReceived,\n\t\t\tbytesSent: this.bytesSent,\n\t\t\tclients: Array.from(this.clientMetrics.values()),\n\t\t\tuptime: Date.now() - this.startedAt,\n\t\t\ttotalOperations,\n\t\t\terrorCount: this.errorCount,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t}\n\t}\n\n\t/** Reset all metrics. */\n\treset(): void {\n\t\tthis.startedAt = Date.now()\n\t\tthis.peakConnections = 0\n\t\tthis.connectionsTotal = 0\n\t\tthis.operationsReceived = 0\n\t\tthis.batchesReceived = 0\n\t\tthis.uniqueOperationsReceived = 0\n\t\tthis.duplicateOperationsReceived = 0\n\t\tthis.rejectedOperations = 0\n\t\tthis.unverifiedLegacyOperations = 0\n\t\tthis.forgedDuplicates = 0\n\t\tthis.operationsSent = 0\n\t\tthis.bytesReceived = 0\n\t\tthis.bytesSent = 0\n\t\tthis.errorCount = 0\n\t\tthis.clientMetrics.clear()\n\t}\n}\n","import { hashBlob } from '@korajs/core'\nimport {\n\ttype BlobChunkRequestMessage,\n\ttype BlobChunkResponseMessage,\n\tdecodeBlobChunkBytes,\n\tencodeBlobChunkBytes,\n} from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Resolves a blob chunk by content hash from server-side storage. Optional: when\n * provided, the server can answer chunk requests directly from its own store\n * (central-store deployment). When absent, the server acts as a pure relay,\n * forwarding chunk requests to peer sessions and their responses back.\n */\nexport type ResolveBlobChunk = (hash: string) => Promise<Uint8Array | null>\n\n/**\n * Decides who may obtain the bytes behind a content hash, and from whom (RT-1).\n *\n * The server's policy: the central store serves a session only when a live record\n * inside its download scope references the hash (as a blob, a manifest, or a chunk\n * of one). A request is forwarded to a peer only when both share the same download\n * scope (same tenant view), or when both scopes reference the hash.\n */\nexport interface BlobAccessPolicy {\n\t/** Whether the central store may serve `hash` to `requesterId`. */\n\tcanReadFromStore(requesterId: string, hash: string): Promise<boolean>\n\t/** Whether `requesterId`'s request for `hash` may be forwarded to (and answered by) `targetId`. */\n\tcanForward(requesterId: string, targetId: string, hash: string): Promise<boolean>\n\t/**\n\t * Called with bytes the relay has verified to hash to `hash`, so the policy can\n\t * learn a manifest's chunk list. Optional.\n\t */\n\tobserveVerifiedBytes?(hash: string, bytes: Uint8Array): void\n}\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/** Limits that bound the relay's per-session bookkeeping. */\nexport interface BlobChunkRelayLimits {\n\t/** Most unanswered requests one session may have outstanding. Defaults to 256. */\n\tmaxPendingPerSession?: number\n\t/** How long an unanswered request is remembered, in ms. Defaults to 60 seconds. */\n\tpendingTtlMs?: number\n}\n\n/** Default cap on outstanding forwarded requests per session. */\nexport const DEFAULT_MAX_PENDING_BLOB_REQUESTS_PER_SESSION = 256\n/** Default lifetime of an unanswered forwarded request. */\nexport const DEFAULT_BLOB_REQUEST_TTL_MS = 60_000\n\ninterface PendingRequest {\n\toriginSessionId: string\n\t/** The content hash requested; a response must hash to it. */\n\thash: string\n\t/** Sessions the request was forwarded to: the only ones allowed to answer it. */\n\tforwardedTo: Set<string>\n\tcreatedAtMs: number\n}\n\n/**\n * Routes out-of-band blob chunk transfer between connected clients (and,\n * optionally, a server-side blob store), within tenant boundaries (RT-1).\n *\n * - The central store (when configured) answers only requesters the\n * {@link BlobAccessPolicy} admits for that hash.\n * - Otherwise the request is forwarded only to peers the policy admits for that\n * requester and hash, so a hash never reaches another tenant.\n * - When neither applies, the request is answered \"not held\" (`bytes: null`), the\n * same answer as for an unknown hash, so nothing leaks.\n * - A response is accepted only from a session the request was forwarded to, and\n * only when its bytes hash to the requested hash (no poisoning, by another tenant\n * or by a same-tenant peer).\n *\n * Blob bytes never enter the operation log; only the `BlobRef` inside a record does.\n * Not persisted: this is an ephemeral side channel, like the Yjs doc relay.\n */\nexport class BlobChunkRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\t/** requestId -> the session that originated the request (to route the answer back). */\n\tprivate readonly pending = new Map<string, PendingRequest>()\n\tprivate readonly resolveBlobChunk: ResolveBlobChunk | null\n\tprivate readonly policy: BlobAccessPolicy\n\tprivate readonly maxPendingPerSession: number\n\tprivate readonly pendingTtlMs: number\n\n\tconstructor(\n\t\tresolveBlobChunk: ResolveBlobChunk | undefined,\n\t\tpolicy: BlobAccessPolicy,\n\t\tlimits: BlobChunkRelayLimits = {},\n\t) {\n\t\tthis.resolveBlobChunk = resolveBlobChunk ?? null\n\t\tthis.policy = policy\n\t\tthis.maxPendingPerSession =\n\t\t\tlimits.maxPendingPerSession ?? DEFAULT_MAX_PENDING_BLOB_REQUESTS_PER_SESSION\n\t\tthis.pendingTtlMs = limits.pendingTtlMs ?? DEFAULT_BLOB_REQUEST_TTL_MS\n\t}\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t\t// Drop any requests this session was waiting on; their answers can no\n\t\t// longer be delivered.\n\t\tfor (const [requestId, entry] of this.pending) {\n\t\t\tif (entry.originSessionId === sessionId) {\n\t\t\t\tthis.pending.delete(requestId)\n\t\t\t} else {\n\t\t\t\tentry.forwardedTo.delete(sessionId)\n\t\t\t}\n\t\t}\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tgetPendingCount(): number {\n\t\treturn this.pending.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t\tthis.pending.clear()\n\t}\n\n\t/**\n\t * Handle an inbound chunk request from a session. Tries the server's own store\n\t * first (if configured and the policy admits the requester), then forwards the\n\t * request to admitted peers and remembers who to route the answer back to. With\n\t * neither, the requester is told \"not held\".\n\t */\n\tasync handleRequest(sourceSessionId: string, message: BlobChunkRequestMessage): Promise<void> {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (\n\t\t\tthis.resolveBlobChunk &&\n\t\t\t(await this.allowed(() => this.policy.canReadFromStore(sourceSessionId, message.hash)))\n\t\t) {\n\t\t\tlet bytes: Uint8Array | null = null\n\t\t\ttry {\n\t\t\t\tbytes = await this.resolveBlobChunk(message.hash)\n\t\t\t} catch {\n\t\t\t\t// A store read error is treated as \"not held here\": fall back to peers\n\t\t\t\t// rather than crashing the connection.\n\t\t\t\tbytes = null\n\t\t\t}\n\t\t\tif (bytes !== null) {\n\t\t\t\tthis.sendResponseTo(sourceSessionId, message.requestId, encodeBlobChunkBytes(bytes))\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (!(await this.forwardRequestToPeers(sourceSessionId, message))) {\n\t\t\tthis.sendResponseTo(sourceSessionId, message.requestId, null)\n\t\t}\n\t}\n\n\t/**\n\t * Handle an inbound chunk response from a peer. Routes it back to the session\n\t * that originally requested it, but only when the responder was asked and the\n\t * bytes hash to the requested hash. A \"not held\" answer (bytes === null) is\n\t * ignored so a peer without the chunk does not preempt one that has it; the\n\t * requester's own per-request timeout bounds the wait.\n\t */\n\tasync handleResponse(sourceSessionId: string, message: BlobChunkResponseMessage): Promise<void> {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tif (message.bytes === null) {\n\t\t\treturn\n\t\t}\n\t\tconst entry = this.pending.get(message.requestId)\n\t\tif (!entry || !entry.forwardedTo.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tlet decoded: Uint8Array\n\t\ttry {\n\t\t\tdecoded = decodeBlobChunkBytes(message.bytes)\n\t\t} catch {\n\t\t\treturn\n\t\t}\n\t\tif ((await hashBlob(decoded)) !== entry.hash) {\n\t\t\t// Wrong bytes for the hash: ignore them and keep waiting for an honest peer.\n\t\t\treturn\n\t\t}\n\t\t// Re-check after the await: another response may have completed the request.\n\t\tif (this.pending.get(message.requestId) !== entry) {\n\t\t\treturn\n\t\t}\n\t\tthis.pending.delete(message.requestId)\n\t\tthis.policy.observeVerifiedBytes?.(entry.hash, decoded)\n\t\tthis.sendResponseTo(entry.originSessionId, message.requestId, message.bytes)\n\t}\n\n\tprivate async allowed(check: () => Promise<boolean>): Promise<boolean> {\n\t\ttry {\n\t\t\treturn await check()\n\t\t} catch {\n\t\t\t// Fail closed: an authorization error never grants access.\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/** Forward to admitted peers. False when nobody may be asked (answer \"not held\"). */\n\tprivate async forwardRequestToPeers(\n\t\tsourceSessionId: string,\n\t\tmessage: BlobChunkRequestMessage,\n\t): Promise<boolean> {\n\t\tconst now = Date.now()\n\t\tthis.expirePending(now)\n\t\tconst existing = this.pending.get(message.requestId)\n\t\t// A request id already pending for another session is refused, so one session\n\t\t// cannot hijack the answer routed to another by reusing its request id.\n\t\tif (existing && existing.originSessionId !== sourceSessionId) {\n\t\t\treturn true\n\t\t}\n\t\tif (!existing && this.pendingCountFor(sourceSessionId) >= this.maxPendingPerSession) {\n\t\t\t// Over the per-session cap: drop the request. The requester's own timeout\n\t\t\t// bounds its wait; the relay's memory stays bounded per session.\n\t\t\treturn true\n\t\t}\n\t\tconst targets: RelayClient[] = []\n\t\tfor (const client of this.clients.values()) {\n\t\t\tif (client.sessionId === sourceSessionId) continue\n\t\t\tif (!client.transport.isConnected()) continue\n\t\t\t// Only peers that may hold the bytes themselves are asked: the hash never\n\t\t\t// reaches a session outside the requester's tenant.\n\t\t\tif (\n\t\t\t\tawait this.allowed(() =>\n\t\t\t\t\tthis.policy.canForward(sourceSessionId, client.sessionId, message.hash),\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\ttargets.push(client)\n\t\t\t}\n\t\t}\n\t\t// The requester may have left, or a duplicate request id may have registered,\n\t\t// while the policy was consulted.\n\t\tif (!this.clients.has(sourceSessionId)) return true\n\t\tconst current = this.pending.get(message.requestId)\n\t\tif (current && current.originSessionId !== sourceSessionId) return true\n\t\tif (targets.length === 0) return false\n\t\tconst forwardedTo = current?.forwardedTo ?? new Set<string>()\n\t\tfor (const target of targets) forwardedTo.add(target.sessionId)\n\t\tthis.pending.set(message.requestId, {\n\t\t\toriginSessionId: sourceSessionId,\n\t\t\thash: message.hash,\n\t\t\tforwardedTo,\n\t\t\tcreatedAtMs: now,\n\t\t})\n\t\tfor (const target of targets) {\n\t\t\ttarget.transport.send(message)\n\t\t}\n\t\treturn true\n\t}\n\n\tprivate pendingCountFor(sessionId: string): number {\n\t\tlet count = 0\n\t\tfor (const entry of this.pending.values()) {\n\t\t\tif (entry.originSessionId === sessionId) count += 1\n\t\t}\n\t\treturn count\n\t}\n\n\tprivate expirePending(now: number): void {\n\t\tconst cutoff = now - this.pendingTtlMs\n\t\tfor (const [requestId, entry] of this.pending) {\n\t\t\tif (entry.createdAtMs <= cutoff) {\n\t\t\t\tthis.pending.delete(requestId)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sendResponseTo(sessionId: string, requestId: string, bytes: string | null): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client || !client.transport.isConnected()) {\n\t\t\treturn\n\t\t}\n\t\tconst response: BlobChunkResponseMessage = {\n\t\t\ttype: 'blob-chunk-response',\n\t\t\tmessageId: generateResponseId(requestId),\n\t\t\trequestId,\n\t\t\tbytes,\n\t\t}\n\t\tclient.transport.send(response)\n\t}\n}\n\n/**\n * Derive a deterministic wire messageId for a routed response. The correlation\n * that matters is `requestId`; `messageId` only needs to be a non-empty string,\n * so deriving it avoids a clock/random dependency in the relay.\n */\nfunction generateResponseId(requestId: string): string {\n\treturn `blob-resp-${requestId}`\n}\n","import type { SyncMessage, YjsDocUpdateMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/**\n * Relays ephemeral Yjs doc channel updates between connected clients.\n * Not persisted — durable richtext state still flows through the operation log.\n */\nexport class YjsDocRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t}\n\n\t/**\n\t * Relay an update from a registered session to every other registered session\n\t * that `canDeliver` admits. The caller (the sync server) has already authorized\n\t * the sender's write; `canDeliver` limits delivery to sessions whose download\n\t * scope contains the record, so a doc update never crosses a tenant boundary.\n\t *\n\t * @param sourceSessionId - The sending session (never echoed back)\n\t * @param message - The doc-channel update\n\t * @param canDeliver - Per-target delivery check; defaults to deliver-to-all\n\t */\n\thandleUpdate(\n\t\tsourceSessionId: string,\n\t\tmessage: YjsDocUpdateMessage,\n\t\tcanDeliver: (targetSessionId: string) => boolean = () => true,\n\t): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tthis.broadcastExcept(sourceSessionId, message, canDeliver)\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\tprivate broadcastExcept(\n\t\texcludeSessionId: string,\n\t\tmessage: SyncMessage,\n\t\tcanDeliver: (targetSessionId: string) => boolean,\n\t): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!canDeliver(client.sessionId)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!client.transport.isConnected()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import {\n\ttype AtomicOp,\n\ttype HybridLogicalClock,\n\ttype Operation,\n\tcreateOperation,\n\tgenerateUUIDv7,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n} from '@korajs/core'\nimport { validateIngestedOperation } from '../apply/ingest-validation'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { type RoutePredicate, evaluateRoutePredicate } from '../apply/route-predicate'\nimport { nextServerSequenceNumber, serverClock } from '../apply/server-side-effect-operation'\nimport { authorizeOperationReferences } from '../scopes/reference-authorization'\nimport type { ScopeMap, UplinkAuthorizationResult } from '../scopes/server-scope-filter'\nimport {\n\tauthorizeUplinkWrite,\n\trecordMatchesScopes,\n\tsplitScopeForQuery,\n} from '../scopes/server-scope-filter'\nimport type {\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tMaterializedRecord,\n\tServerStore,\n} from '../store/server-store'\nimport type { KoraSyncServer } from './kora-sync-server'\n\n/**\n * A mutation a custom HTTP route asks the server to apply on the data plane.\n *\n * `recordId` is optional for inserts (a UUID v7 is generated when omitted) and\n * required for updates and deletes. For updates, `data` holds only the changed\n * fields; the server reads the current record to capture the previous values so\n * the change three-way merges correctly with concurrent client edits.\n */\nexport interface RouteMutation {\n\tcollection: string\n\ttype: 'insert' | 'update' | 'delete'\n\trecordId?: string\n\tdata?: Record<string, unknown> | null\n}\n\n/**\n * Scope the route derived from the request's authenticated actor. When present,\n * it is enforced exactly like a sync session's scope: `apply()` rejects a\n * mutation whose resulting record falls outside the scope, and `query()` /\n * `findById()` only return records inside it. Omit it for genuinely public\n * routes (for example a signup endpoint) where no per-actor isolation applies.\n */\nexport interface RouteScopeOptions {\n\tscope?: ScopeMap\n}\n\n/** Result of {@link ProductionHttpRouteContext.apply}. */\nexport type RouteApplyResult =\n\t| { ok: true; operation: Operation; record: MaterializedRecord | null }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * A conditional, multi-collection admission gate applied atomically per instance.\n *\n * The gate reads the current state of the target record (`collection` + `id`),\n * checks the `if` predicate against it, and only then applies the `update` to the\n * target plus every mutation in `also` as one set. If the predicate fails it\n * applies nothing and returns the structured `reject`. `idempotencyKey` names a\n * record whose prior existence proves the set already committed, so a retry\n * returns the earlier outcome instead of applying the set (and its non-idempotent\n * counter increments) again.\n *\n * Atomicity note: within one server instance the check and the writes do not\n * interleave with other route mutations. Cross-instance, race-free admission and\n * all-or-nothing across a mid-set crash require the store-level conditional\n * transaction (a Postgres `WHERE ... < cap` commit), which is the next increment.\n */\nexport interface RouteConditionalApply {\n\t/** Collection of the record the predicate reads and the `update` targets. */\n\tcollection: string\n\t/** Id of the target record. */\n\tid: string\n\t/** Admission predicate evaluated against the target's current state. */\n\tif?: RoutePredicate\n\t/** Partial update applied to the target record when the predicate holds. */\n\tupdate?: Record<string, unknown> | null\n\t/** Additional mutations committed atomically with the target update. */\n\talso?: RouteMutation[]\n\t/** Structured rejection returned when the predicate does not hold. */\n\treject?: { code: string; message: string }\n\t/**\n\t * Names a record whose existence means this set already committed. When it is\n\t * present the set is skipped and the prior outcome returned. Use a stable,\n\t * client-generated id (for example the accepted record's own id).\n\t */\n\tidempotencyKey?: { collection: string; id: string }\n}\n\n/** Result of {@link ProductionHttpRouteContext.applyConditional}. */\nexport type RouteConditionalResult =\n\t| {\n\t\t\tok: true\n\t\t\t/** True when the set was already committed and this call was a no-op. */\n\t\t\tidempotent: boolean\n\t\t\toperations: Operation[]\n\t\t\trecords: (MaterializedRecord | null)[]\n\t }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * Scoped, validated data-plane access handed to custom HTTP route handlers.\n *\n * Every mutation goes through the same pipeline as sync (Tier 2 constraints,\n * referential integrity, materialization, and fan-out to connected clients), so\n * REST endpoints cannot accidentally bypass validation, constraints, or tenant\n * isolation the way hand-rolled store writes can.\n */\nexport interface ProductionHttpRouteContext {\n\t/**\n\t * Apply a mutation through the validated server pipeline and relay the\n\t * resulting operation(s) to connected clients.\n\t */\n\tapply(mutation: RouteMutation, options?: RouteScopeOptions): Promise<RouteApplyResult>\n\t/**\n\t * Conditionally apply a multi-collection mutation set as one admission gate:\n\t * read the target, check the predicate, and commit the update plus every `also`\n\t * mutation only if it holds, with at-most-once semantics via `idempotencyKey`.\n\t */\n\tapplyConditional(\n\t\tspec: RouteConditionalApply,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<RouteConditionalResult>\n\t/** Read materialized records from a collection, optionally scoped. */\n\tquery(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions & RouteScopeOptions,\n\t): Promise<MaterializedRecord[]>\n\t/** Read a single materialized record by id, optionally scoped. */\n\tfindById(\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<MaterializedRecord | null>\n}\n\n/**\n * Returns true when a materialized record satisfies the scope declared for its\n * collection. A collection absent from the scope map is treated as out of scope\n * (hidden). Uses the same predicate matcher as the sync path, so `$in` works here too.\n */\nfunction recordMatchesScope(\n\tcollection: string,\n\trecord: MaterializedRecord,\n\tscope: ScopeMap,\n): boolean {\n\treturn recordMatchesScopes(collection, record, scope)\n}\n\n/**\n * Read a record as stored, including a soft-deleted one, for authorization. Returns\n * null when it was never written (or the store cannot read the collection).\n */\nasync function readStoredRecord(\n\tstore: ServerStore,\n\tcollection: string,\n\tid: string,\n): Promise<MaterializedRecord | null> {\n\ttry {\n\t\tconst rows = await store.queryCollection(collection, {\n\t\t\twhere: { id },\n\t\t\tincludeDeleted: true,\n\t\t\tlimit: 1,\n\t\t})\n\t\treturn rows[0] ?? null\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/** Picks only the given keys from a record (used to capture previousData). */\nfunction pickFields(record: Record<string, unknown>, keys: string[]): Record<string, unknown> {\n\tconst picked: Record<string, unknown> = {}\n\tfor (const key of keys) {\n\t\tif (key in record) {\n\t\t\tpicked[key] = record[key]\n\t\t}\n\t}\n\treturn picked\n}\n\n/**\n * Build a server-originated operation for a route mutation, reading current\n * materialized state so updates and deletes carry accurate previous values.\n *\n * `currentOverride`, when provided, supplies that current state instead of reading\n * it from the store. The conditional apply passes the record it read under the\n * cross-instance lock, so an atomic-op update (for example `op.increment`) resolves\n * against the authoritative locked value rather than a stale read.\n *\n * `clockOverride`, when provided, stamps the operation instead of a fresh clock. The\n * cross-instance conditional apply passes a clock the store advanced past the target\n * record's latest write, so the operation sorts strictly after it and last-write-wins\n * materialization matches the serialized commit order.\n */\nasync function buildRouteOperation(\n\tstore: ServerStore,\n\tmutation: RouteMutation,\n\tcurrentOverride?: { record: MaterializedRecord | null },\n\tclockOverride?: HybridLogicalClock,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\t// W7: the server node's one clock, advanced past the record's newest write, so this\n\t// write sorts after every write it read (the fold orders a record's writes by HLC).\n\tconst clock =\n\t\tclockOverride ??\n\t\tserverClock(\n\t\t\tstore,\n\t\t\tmutation.recordId\n\t\t\t\t? await store.getRecordLatestTimestamp?.(mutation.collection, mutation.recordId)\n\t\t\t\t: null,\n\t\t)\n\tconst schemaVersion = store.getSchema()?.version ?? 1\n\tconst sequenceNumber = nextServerSequenceNumber(store)\n\n\tif (mutation.type === 'insert') {\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId ?? generateUUIDv7(),\n\t\t\t\tdata: mutation.data ?? {},\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\tif (!mutation.recordId) {\n\t\tthrow new RouteMutationError(\n\t\t\t'MISSING_RECORD_ID',\n\t\t\t`A ${mutation.type} mutation on \"${mutation.collection}\" requires a recordId.`,\n\t\t)\n\t}\n\n\tconst current = currentOverride\n\t\t? currentOverride.record\n\t\t: await store.findRecord(mutation.collection, mutation.recordId)\n\n\tif (mutation.type === 'update') {\n\t\tconst rawData = mutation.data ?? {}\n\t\t// Resolve atomic-op sentinels (op.increment, op.max, ...) exactly as the\n\t\t// client's update path does: `data` carries the concrete resolved value for\n\t\t// materialization, and `atomicOps` carries the intent so concurrent atomic\n\t\t// writes compose in the merge engine instead of last-write-wins.\n\t\tconst data: Record<string, unknown> = {}\n\t\tconst atomicOps: Record<string, AtomicOp> = {}\n\t\tfor (const key of Object.keys(rawData)) {\n\t\t\tconst value = rawData[key]\n\t\t\tif (isAtomicOp(value)) {\n\t\t\t\tdata[key] = resolveAtomicOp(current ? current[key] : undefined, value)\n\t\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t\t} else {\n\t\t\t\tdata[key] = value\n\t\t\t}\n\t\t}\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId,\n\t\t\t\tdata,\n\t\t\t\tpreviousData: current ? pickFields(current, Object.keys(rawData)) : {},\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t\t...(Object.keys(atomicOps).length > 0 ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\t// delete\n\treturn createOperation(\n\t\t{\n\t\t\tnodeId,\n\t\t\ttype: 'delete',\n\t\t\tcollection: mutation.collection,\n\t\t\trecordId: mutation.recordId,\n\t\t\tdata: null,\n\t\t\tpreviousData: current ? { ...current } : null,\n\t\t\tsequenceNumber,\n\t\t\tcausalDeps: [],\n\t\t\tschemaVersion,\n\t\t},\n\t\tclock,\n\t)\n}\n\n/** Deterministic key for a scope map (sorted keys at every level). */\nfunction stableScopeKey(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(stableScopeKey).join(',')}]`\n\tif (value && typeof value === 'object') {\n\t\tconst record = value as Record<string, unknown>\n\t\treturn `{${Object.keys(record)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${stableScopeKey(record[key])}`)\n\t\t\t.join(',')}}`\n\t}\n\treturn JSON.stringify(value) ?? 'undefined'\n}\n\n/** Internal error carrying a stable code for route-context failures. */\nclass RouteMutationError extends Error {\n\tconstructor(\n\t\treadonly code: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'RouteMutationError'\n\t}\n}\n\n/**\n * Create the scoped, validated data-plane context handed to custom HTTP route\n * handlers as `request.kora`.\n *\n * Mutations are serialized so concurrent requests cannot race on server\n * sequence-number allocation: each `apply()` builds and applies its operation\n * before the next begins.\n */\nexport function createRouteContext(\n\tserver: KoraSyncServer,\n\tstore: ServerStore,\n): ProductionHttpRouteContext {\n\t// Reference authorization for a scoped route write (RT-11, RT-13). The route's\n\t// scope is both what it may write and what it may read; blob claims are keyed by\n\t// the scope, since a route has no device or session of its own.\n\tfunction authorizeRouteReferences(\n\t\top: Operation,\n\t\tstored: MaterializedRecord | null,\n\t\tscope: ScopeMap | undefined,\n\t\treadRow: (collection: string, id: string) => Promise<MaterializedRecord | null>,\n\t): Promise<UplinkAuthorizationResult> {\n\t\tif (!scope) return Promise.resolve({ allowed: true })\n\t\treturn authorizeOperationReferences(op, stored, {\n\t\t\tschema: store.getSchema(),\n\t\t\tdownlinkScopes: scope,\n\t\t\treadRow,\n\t\t\tblobs: server.getBlobAccessIndex(),\n\t\t\tblobOwner: `kora:route:${stableScopeKey(scope)}`,\n\t\t})\n\t}\n\n\t// Promise chain that serializes apply() so sequence allocation + apply is\n\t// atomic per mutation, even under concurrent in-flight requests.\n\tlet mutationTail: Promise<unknown> = Promise.resolve()\n\n\tfunction serialize<T>(work: () => Promise<T>): Promise<T> {\n\t\tconst run = mutationTail.then(work, work)\n\t\t// Keep the tail from rejecting so one failed mutation does not poison the\n\t\t// chain for subsequent ones.\n\t\tmutationTail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t)\n\t\treturn run\n\t}\n\n\t// Build a route operation and check scope, WITHOUT applying it. Splitting\n\t// preparation from commit lets applyConditional validate an entire mutation set\n\t// before committing any of it, so a scope violation or malformed mutation in\n\t// `also` cannot leave the target update (for example a counter increment)\n\t// committed while the rest is rejected.\n\ttype RouteRejection = { ok: false; code: string; message: string; retriable: boolean }\n\ttype PreparedMutation = { ok: true; op: Operation } | { ok: false; rejection: RouteRejection }\n\tasync function prepareMutation(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<PreparedMutation> {\n\t\tlet op: Operation\n\t\ttry {\n\t\t\top = await buildRouteOperation(store, mutation)\n\t\t} catch (error) {\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tcode: error.code,\n\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\t// The same rule as sync uploads: the stored row (including a soft-deleted one)\n\t\t// must be in scope, and so must the record after the write. A scoped route\n\t\t// therefore cannot edit, delete, take over or same-id-overwrite a record that\n\t\t// belongs to someone else.\n\t\tconst stored = scope ? await readStoredRecord(store, op.collection, op.recordId) : null\n\t\tlet decision = authorizeUplinkWrite(op, stored, scope)\n\t\t// A scoped route may only point at parents and blob content inside its scope\n\t\t// (RT-11, RT-13), exactly like a sync session.\n\t\tif (decision.allowed) {\n\t\t\tdecision = await authorizeRouteReferences(op, stored, scope, (collection, id) =>\n\t\t\t\treadStoredRecord(store, collection, id),\n\t\t\t)\n\t\t}\n\t\tif (!decision.allowed) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\trejection: {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: decision.code,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\tdecision.code === 'SCOPE_VIOLATION'\n\t\t\t\t\t\t\t? `Mutation on \"${mutation.collection}\" is outside the provided scope. ${decision.message}`\n\t\t\t\t\t\t\t: decision.message,\n\t\t\t\t\tretriable: isRetriableRejection(decision.code),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn { ok: true, op }\n\t}\n\n\t// Apply a prepared operation and read back the resulting record.\n\tasync function commitOperation(\n\t\top: Operation,\n\t\tcollection: string,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<RouteApplyResult> {\n\t\t// Scoped writes are re-authorized by the store inside its apply critical section,\n\t\t// against the row as it is at commit time.\n\t\tconst result = await server.applyLocalOperation(\n\t\t\top,\n\t\t\tscope\n\t\t\t\t? {\n\t\t\t\t\t\tauthorize: (stored) => authorizeUplinkWrite(op, stored, scope),\n\t\t\t\t\t\t// A scoped route's delete may only cascade inside its scope (RT-10).\n\t\t\t\t\t\tauthorizeSideEffect: (effect, stored) => authorizeUplinkWrite(effect, stored, scope),\n\t\t\t\t\t}\n\t\t\t\t: {},\n\t\t)\n\t\tif (result.result !== 'applied') {\n\t\t\tconst code = result.rejection?.code ?? 'NOT_APPLIED'\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode,\n\t\t\t\tmessage:\n\t\t\t\t\tresult.rejection?.message ??\n\t\t\t\t\t`Operation on \"${collection}\" was not applied (${result.result}).`,\n\t\t\t\t// Prefer the pipeline's own classification when present; fall back\n\t\t\t\t// to classifying the code so this stays correct if new codes appear.\n\t\t\t\tretriable: result.rejection?.retriable ?? isRetriableRejection(code),\n\t\t\t}\n\t\t}\n\n\t\tconst record = await store.findRecord(collection, op.recordId)\n\t\treturn { ok: true, operation: op, record }\n\t}\n\n\t// The un-serialized core of a single mutation. Both apply() and\n\t// applyConditional() call this inside a serialized block, so it must NOT\n\t// serialize itself (that would deadlock the promise-chain tail).\n\tasync function rawApply(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<RouteApplyResult> {\n\t\tconst prepared = await prepareMutation(mutation, scope)\n\t\tif (!prepared.ok) {\n\t\t\treturn prepared.rejection\n\t\t}\n\t\treturn commitOperation(prepared.op, mutation.collection, scope)\n\t}\n\n\t// Cross-instance conditional apply, delegating admission and atomicity to the\n\t// store (the Postgres advisory-lock transaction). The store owns the\n\t// read-decide-write cycle so a cap check is race-free across instances; this\n\t// bridge translates the route spec into the store's callback shape, validates\n\t// scope on each built operation while still inside the locked transaction (so a\n\t// violation rolls everything back), then relays the committed set to clients.\n\tasync function runConditionalViaStore(\n\t\tstoreApplyConditional: (input: ConditionalApplyInput) => Promise<ConditionalApplyResult>,\n\t\tspec: RouteConditionalApply,\n\t\toptions: RouteScopeOptions | undefined,\n\t): Promise<RouteConditionalResult> {\n\t\tconst scope = options?.scope\n\n\t\t// Assemble the set: the target update (when given) first, then every `also`.\n\t\tconst mutations: RouteMutation[] = []\n\t\tconst hasTargetUpdate = spec.update !== undefined && spec.update !== null\n\t\tif (hasTargetUpdate) {\n\t\t\tmutations.push({\n\t\t\t\tcollection: spec.collection,\n\t\t\t\ttype: 'update',\n\t\t\t\trecordId: spec.id,\n\t\t\t\tdata: spec.update,\n\t\t\t})\n\t\t}\n\t\tif (spec.also) {\n\t\t\tmutations.push(...spec.also)\n\t\t}\n\n\t\tlet result: ConditionalApplyResult\n\t\ttry {\n\t\t\tresult = await storeApplyConditional({\n\t\t\t\ttarget: { collection: spec.collection, id: spec.id },\n\t\t\t\t...(spec.idempotencyKey ? { idempotencyKey: spec.idempotencyKey } : {}),\n\t\t\t\tadmit: (current) =>\n\t\t\t\t\tspec.if && Object.keys(spec.if).length > 0\n\t\t\t\t\t\t? evaluateRoutePredicate(current, spec.if)\n\t\t\t\t\t\t: true,\n\t\t\t\tbuildOperations: async (current, context) => {\n\t\t\t\t\tconst ops: Operation[] = []\n\t\t\t\t\tfor (let i = 0; i < mutations.length; i++) {\n\t\t\t\t\t\tconst mutation = mutations[i] as RouteMutation\n\t\t\t\t\t\t// The target update (index 0 when present) resolves its atomic ops\n\t\t\t\t\t\t// against the locked `current`; `also` mutations address distinct\n\t\t\t\t\t\t// records and read their own current state from the store. Every op\n\t\t\t\t\t\t// is stamped with the store-provided clock so the set sorts strictly\n\t\t\t\t\t\t// after the target's latest committed write.\n\t\t\t\t\t\tconst useLockedCurrent = i === 0 && hasTargetUpdate\n\t\t\t\t\t\tconst op = await buildRouteOperation(\n\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\tmutation,\n\t\t\t\t\t\t\tuseLockedCurrent ? { record: current } : undefined,\n\t\t\t\t\t\t\tcontext.clock,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t// The store-provided clock was advanced past the target's latest write;\n\t\t\t\t\t\t// if that write is far-future (a log from a server with a wrong clock),\n\t\t\t\t\t\t// so is this one. Refuse it rather than spread it (SYNC-7).\n\t\t\t\t\t\tconst ingest = validateIngestedOperation(op)\n\t\t\t\t\t\tif (!ingest.valid) {\n\t\t\t\t\t\t\tthrow new RouteMutationError(ingest.code, ingest.message)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Validate inside the locked transaction against the stored row read\n\t\t\t\t\t\t// through the store's transaction when it offers one. Throwing here\n\t\t\t\t\t\t// rolls the transaction back, so a violation applies nothing.\n\t\t\t\t\t\tconst stored = scope\n\t\t\t\t\t\t\t? context.readStoredRow\n\t\t\t\t\t\t\t\t? await context.readStoredRow(op.collection, op.recordId)\n\t\t\t\t\t\t\t\t: await readStoredRecord(store, op.collection, op.recordId)\n\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tlet decision = authorizeUplinkWrite(op, stored, scope)\n\t\t\t\t\t\tif (decision.allowed) {\n\t\t\t\t\t\t\tdecision = await authorizeRouteReferences(op, stored, scope, (collection, id) =>\n\t\t\t\t\t\t\t\tcontext.readStoredRow\n\t\t\t\t\t\t\t\t\t? context.readStoredRow(collection, id)\n\t\t\t\t\t\t\t\t\t: readStoredRecord(store, collection, id),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!decision.allowed) {\n\t\t\t\t\t\t\tthrow new RouteMutationError(\n\t\t\t\t\t\t\t\tdecision.code,\n\t\t\t\t\t\t\t\tdecision.code === 'SCOPE_VIOLATION'\n\t\t\t\t\t\t\t\t\t? `Mutation on \"${mutation.collection}\" is outside the provided scope. ${decision.message}`\n\t\t\t\t\t\t\t\t\t: decision.message,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tops.push(op)\n\t\t\t\t\t}\n\t\t\t\t\treturn ops\n\t\t\t\t},\n\t\t\t})\n\t\t} catch (error) {\n\t\t\t// A malformed mutation or scope violation surfaced from inside the locked\n\t\t\t// transaction (which rolled back) becomes a structured rejection, not a 500.\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: error.code,\n\t\t\t\t\tmessage: error.message,\n\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\t// Predicate failed under the lock: nothing was applied.\n\t\tif (!result.admitted) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode: spec.reject?.code ?? 'CONDITION_NOT_MET',\n\t\t\t\tmessage:\n\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\tretriable: false,\n\t\t\t}\n\t\t}\n\n\t\t// Idempotent hit: the set committed on an earlier attempt. Return the anchor's\n\t\t// committed state without re-applying (so counter increments run at most once).\n\t\tif (result.idempotent) {\n\t\t\tconst records: (MaterializedRecord | null)[] = spec.idempotencyKey\n\t\t\t\t? [await store.findRecord(spec.idempotencyKey.collection, spec.idempotencyKey.id)]\n\t\t\t\t: []\n\t\t\treturn { ok: true, idempotent: true, operations: [], records }\n\t\t}\n\n\t\t// Admitted and committed. Fan the operations out to connected clients (each\n\t\t// session re-applies its own scope filter), then read back each record.\n\t\tserver.relayServerOperations(result.applied)\n\t\tconst records: (MaterializedRecord | null)[] = []\n\t\tfor (const op of result.applied) {\n\t\t\trecords.push(await store.findRecord(op.collection, op.recordId))\n\t\t}\n\t\treturn { ok: true, idempotent: false, operations: result.applied, records }\n\t}\n\n\treturn {\n\t\tapply(mutation, options): Promise<RouteApplyResult> {\n\t\t\treturn serialize(() => rawApply(mutation, options?.scope))\n\t\t},\n\n\t\tapplyConditional(spec, options): Promise<RouteConditionalResult> {\n\t\t\t// Prefer the store's cross-instance conditional apply when available (the\n\t\t\t// Postgres store): it serializes the admission on the target across every\n\t\t\t// server instance via an advisory lock, so a cap check is race-free even\n\t\t\t// under concurrent admissions on different instances. Stores without it\n\t\t\t// (single-process SQLite / in-memory) use the per-instance serialized path\n\t\t\t// below, which is correct because there is only one instance.\n\t\t\tconst storeApplyConditional = store.applyConditional\n\t\t\tif (storeApplyConditional) {\n\t\t\t\treturn runConditionalViaStore(storeApplyConditional.bind(store), spec, options)\n\t\t\t}\n\t\t\treturn serialize(async () => {\n\t\t\t\t// Idempotency: if the anchor record already exists, this set was\n\t\t\t\t// committed by an earlier attempt. Return the prior outcome without\n\t\t\t\t// re-applying (so counter increments run at most once).\n\t\t\t\tif (spec.idempotencyKey) {\n\t\t\t\t\tconst existing = await store.findRecord(\n\t\t\t\t\t\tspec.idempotencyKey.collection,\n\t\t\t\t\t\tspec.idempotencyKey.id,\n\t\t\t\t\t)\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\treturn { ok: true, idempotent: true, operations: [], records: [existing] }\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Admission predicate against the target's current materialized state.\n\t\t\t\tif (spec.if && Object.keys(spec.if).length > 0) {\n\t\t\t\t\tconst target = await store.findRecord(spec.collection, spec.id)\n\t\t\t\t\tif (!evaluateRoutePredicate(target, spec.if)) {\n\t\t\t\t\t\tconst code = spec.reject?.code ?? 'CONDITION_NOT_MET'\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\t\t\t\tretriable: false,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build the atomic set: the target update (when given) then every\n\t\t\t\t// `also` mutation. Mutations in one set should address distinct records;\n\t\t\t\t// a mutation's previous-value capture reads the pre-set state.\n\t\t\t\tconst mutations: RouteMutation[] = []\n\t\t\t\tif (spec.update !== undefined && spec.update !== null) {\n\t\t\t\t\tmutations.push({\n\t\t\t\t\t\tcollection: spec.collection,\n\t\t\t\t\t\ttype: 'update',\n\t\t\t\t\t\trecordId: spec.id,\n\t\t\t\t\t\tdata: spec.update,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (spec.also) {\n\t\t\t\t\tmutations.push(...spec.also)\n\t\t\t\t}\n\n\t\t\t\t// Pre-build and scope-validate the WHOLE set before committing any of\n\t\t\t\t// it, so a validation failure applies nothing.\n\t\t\t\tconst prepared: { op: Operation; collection: string }[] = []\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tconst p = await prepareMutation(mutation, options?.scope)\n\t\t\t\t\tif (!p.ok) {\n\t\t\t\t\t\treturn p.rejection\n\t\t\t\t\t}\n\t\t\t\t\tprepared.push({ op: p.op, collection: mutation.collection })\n\t\t\t\t}\n\n\t\t\t\tconst operations: Operation[] = []\n\t\t\t\tconst records: (MaterializedRecord | null)[] = []\n\t\t\t\tfor (const { op, collection } of prepared) {\n\t\t\t\t\tconst result = await commitOperation(op, collection, options?.scope)\n\t\t\t\t\tif (!result.ok) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode: result.code,\n\t\t\t\t\t\t\tmessage: result.message,\n\t\t\t\t\t\t\tretriable: result.retriable,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\toperations.push(result.operation)\n\t\t\t\t\trecords.push(result.record)\n\t\t\t\t}\n\n\t\t\t\treturn { ok: true, idempotent: false, operations, records }\n\t\t\t})\n\t\t},\n\n\t\tasync query(collection, options): Promise<MaterializedRecord[]> {\n\t\t\tconst { scope, ...queryOptions } = options ?? {}\n\t\t\tif (!scope) {\n\t\t\t\treturn store.queryCollection(collection, queryOptions)\n\t\t\t}\n\t\t\tconst collectionScope = scope[collection]\n\t\t\tif (!collectionScope) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\t// Push equality scope predicates into the store query so limit/offset apply\n\t\t\t// to in-scope records only. A caller filter that contradicts the scope can\n\t\t\t// match nothing.\n\t\t\tconst { equality, hasNonEquality } = splitScopeForQuery(collectionScope)\n\t\t\tconst callerWhere = queryOptions.where ?? {}\n\t\t\tfor (const [field, value] of Object.entries(equality)) {\n\t\t\t\tif (field in callerWhere && !Object.is(callerWhere[field], value)) {\n\t\t\t\t\treturn []\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst where = { ...callerWhere, ...equality }\n\t\t\tconst scopedWhere = Object.keys(where).length > 0 ? { where } : {}\n\t\t\tif (!hasNonEquality) {\n\t\t\t\tconst records = await store.queryCollection(collection, {\n\t\t\t\t\t...queryOptions,\n\t\t\t\t\t...scopedWhere,\n\t\t\t\t})\n\t\t\t\treturn records.filter((record) => recordMatchesScope(collection, record, scope))\n\t\t\t}\n\t\t\t// `$in` predicates cannot be pushed into the store's exact-match filter: fetch\n\t\t\t// without pagination, filter by the full scope, then apply offset and limit.\n\t\t\tconst { limit, offset, ...unpaged } = queryOptions\n\t\t\tconst records = await store.queryCollection(collection, { ...unpaged, ...scopedWhere })\n\t\t\tconst inScope = records.filter((record) => recordMatchesScope(collection, record, scope))\n\t\t\tconst start = offset ?? 0\n\t\t\treturn limit === undefined ? inScope.slice(start) : inScope.slice(start, start + limit)\n\t\t},\n\n\t\tasync findById(collection, id, options): Promise<MaterializedRecord | null> {\n\t\t\tconst record = await store.findRecord(collection, id)\n\t\t\tif (!record) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (options?.scope && !recordMatchesScope(collection, record, options.scope)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn record\n\t\t},\n\t}\n}\n","/**\n * Predicate evaluation for conditional route mutations.\n *\n * A predicate is a small, total comparison language evaluated against the current\n * materialized state of a single record at admission time. It is deliberately not\n * a general query language: it exists so a server route can express an atomic\n * admission guard (for example \"accept this response only while the form is still\n * below its cap\") without pulling a query DSL into the write path.\n */\n\n/**\n * Comparison operators applied to one field. All operators present on a field\n * must hold for the field to match. Numeric operators (`$lt`, `$lte`, `$gt`,\n * `$gte`) require the record value to be a number; a non-numeric value fails.\n */\nexport interface RoutePredicateOperators {\n\t$eq?: unknown\n\t$ne?: unknown\n\t$lt?: number\n\t$lte?: number\n\t$gt?: number\n\t$gte?: number\n\t$in?: readonly unknown[]\n}\n\n/** A predicate: every listed field must satisfy all of its operators. */\nexport type RoutePredicate = Record<string, RoutePredicateOperators>\n\nfunction evaluateField(actual: unknown, operators: RoutePredicateOperators): boolean {\n\tif ('$eq' in operators && !Object.is(actual, operators.$eq)) {\n\t\treturn false\n\t}\n\tif ('$ne' in operators && Object.is(actual, operators.$ne)) {\n\t\treturn false\n\t}\n\tif (\n\t\toperators.$in !== undefined &&\n\t\t!operators.$in.some((candidate) => Object.is(actual, candidate))\n\t) {\n\t\treturn false\n\t}\n\n\tconst numericChecks: [keyof RoutePredicateOperators, (a: number, b: number) => boolean][] = [\n\t\t['$lt', (a, b) => a < b],\n\t\t['$lte', (a, b) => a <= b],\n\t\t['$gt', (a, b) => a > b],\n\t\t['$gte', (a, b) => a >= b],\n\t]\n\tfor (const [operator, compare] of numericChecks) {\n\t\tconst bound = operators[operator]\n\t\tif (bound === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof actual !== 'number' || typeof bound !== 'number') {\n\t\t\treturn false\n\t\t}\n\t\tif (!compare(actual, bound)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n/**\n * Evaluates a predicate against a record. A `null` record (the target does not\n * exist) satisfies only an empty predicate; any field condition fails, since a\n * missing record cannot meet a comparison.\n *\n * @param record - The current materialized record, or `null` if absent\n * @param predicate - The field conditions that must all hold\n * @returns `true` when every field condition is satisfied\n */\nexport function evaluateRoutePredicate(\n\trecord: Record<string, unknown> | null,\n\tpredicate: RoutePredicate,\n): boolean {\n\tconst fields = Object.keys(predicate)\n\tif (fields.length === 0) {\n\t\treturn true\n\t}\n\tif (record === null) {\n\t\treturn false\n\t}\n\tfor (const field of fields) {\n\t\tconst operators = predicate[field]\n\t\tif (operators && !evaluateField(record[field], operators)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n","import { claimScopes } from '@korajs/core'\nimport type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Options for creating a TokenAuthProvider.\n */\nexport interface TokenAuthProviderOptions {\n\t/**\n\t * Validate a token and return an AuthContext if valid, or null if rejected.\n\t * This is where you implement your auth logic (JWT verification, database lookup, etc.).\n\t *\n\t * Return `scopes` to grant sync access explicitly. When the returned context\n\t * has no scopes, schema-scoped collections are bound to `{ userId }` and any\n\t * collection scoped by another key is denied.\n\t */\n\tvalidate: (token: string) => Promise<AuthContext | null>\n}\n\n/**\n * Token-based auth provider that delegates validation to a user-provided function.\n *\n * @example\n * ```typescript\n * const auth = new TokenAuthProvider({\n * validate: async (token) => {\n * const user = await verifyJWT(token)\n * return user ? { userId: user.id } : null\n * }\n * })\n * ```\n */\nexport class TokenAuthProvider implements AuthProvider {\n\tprivate readonly validate: (token: string) => Promise<AuthContext | null>\n\n\tconstructor(options: TokenAuthProviderOptions) {\n\t\tthis.validate = options.validate\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\tconst context = await this.validate(token)\n\t\tif (!context) return null\n\t\tif (\n\t\t\tcontext.scopes === undefined &&\n\t\t\tcontext.downlinkScopes === undefined &&\n\t\t\tcontext.uplinkScopes === undefined\n\t\t) {\n\t\t\t// No explicit grant: bind scoped collections to the verified user id\n\t\t\t// rather than letting the client handshake choose (AUTH-1, fail closed).\n\t\t\treturn { ...context, scopes: claimScopes({ userId: context.userId }) }\n\t\t}\n\t\treturn context\n\t}\n}\n","import { claimScopes } from '@korajs/core'\nimport type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Validates a Kora auth JWT and returns identity claims.\n * This interface matches the signature of TokenManager.validateToken()\n * from @korajs/auth without requiring a direct import.\n */\ninterface TokenValidator {\n\tvalidateToken(token: string): {\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t\texp?: number\n\t} | null\n\tvalidateTokenWithRevocation?(token: string): Promise<{\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t\texp?: number\n\t} | null>\n}\n\n/**\n * Looks up a user by ID. Returns null if the user doesn't exist.\n * This interface matches InMemoryUserStore.findById() from @korajs/auth\n * without requiring a direct import.\n */\ninterface UserLookup {\n\tfindById(userId: string): Promise<{\n\t\tid: string\n\t\temail: string\n\t\tname: string\n\t} | null>\n}\n\n/**\n * Optional device touch callback for updating last-seen timestamps.\n */\ninterface DeviceToucher {\n\ttouchDevice(deviceId: string): Promise<void>\n}\n\n/**\n * Configuration for creating a KoraAuthProvider.\n */\nexport interface KoraAuthProviderOptions {\n\t/**\n\t * Token validator that verifies JWT signatures and returns claims.\n\t * Typically a `TokenManager` instance from `@korajs/auth/server`.\n\t * If the validator also implements `validateTokenWithRevocation`, the sync\n\t * server uses it so signed-out sessions and revoked devices are rejected.\n\t */\n\ttokenValidator: TokenValidator\n\n\t/**\n\t * User lookup for verifying the user still exists.\n\t * Typically an `InMemoryUserStore` instance from `@korajs/auth/server`.\n\t */\n\tuserLookup: UserLookup\n\n\t/**\n\t * Optional device tracker for updating last-seen timestamps.\n\t * Typically the same `InMemoryUserStore` if it implements `touchDevice`.\n\t */\n\tdeviceTracker?: DeviceToucher\n\n\t/**\n\t * Optional scope resolver. Called with the verified user ID to determine\n\t * which collections/records the user can sync. Its result is the complete\n\t * server grant: a collection it omits is not visible, and the client\n\t * handshake can only narrow it. Use `claimScopes({ userId, orgId })` from\n\t * `@korajs/core` to bind every schema-scoped collection from verified values.\n\t *\n\t * When omitted, the grant binds every schema-scoped collection from\n\t * `{ userId: <verified sub> }`; collections scoped by any other key are denied\n\t * until you supply it.\n\t */\n\tresolveScopes?: (userId: string) => Promise<Record<string, Record<string, unknown>>>\n}\n\n/**\n * Auth provider that bridges `@korajs/auth` token management with the\n * sync server's authentication layer.\n *\n * Validates access tokens issued by `@korajs/auth`'s `TokenManager`,\n * verifies the user still exists, and optionally computes per-user\n * sync scopes. This is the recommended way to connect @korajs/auth\n * to @korajs/server.\n *\n * @example\n * ```typescript\n * import { TokenManager, InMemoryUserStore } from '@korajs/auth/server'\n * import { KoraAuthProvider, KoraSyncServer } from '@korajs/server'\n *\n * const tokenManager = new TokenManager({ secret: 'my-secret' })\n * const userStore = new InMemoryUserStore()\n *\n * const auth = new KoraAuthProvider({\n * tokenValidator: tokenManager,\n * userLookup: userStore,\n * deviceTracker: userStore,\n * resolveScopes: async (userId) => ({\n * forms: { userId },\n * responses: { formOwnerId: userId },\n * }),\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n */\nexport class KoraAuthProvider implements AuthProvider {\n\tprivate readonly tokenValidator: TokenValidator\n\tprivate readonly userLookup: UserLookup\n\tprivate readonly deviceTracker: DeviceToucher | undefined\n\tprivate readonly resolveScopes:\n\t\t| ((userId: string) => Promise<Record<string, Record<string, unknown>>>)\n\t\t| undefined\n\n\tconstructor(options: KoraAuthProviderOptions) {\n\t\tthis.tokenValidator = options.tokenValidator\n\t\tthis.userLookup = options.userLookup\n\t\tthis.deviceTracker = options.deviceTracker\n\t\tthis.resolveScopes = options.resolveScopes\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\t// Validate the JWT signature and expiration\n\t\tconst payload = this.tokenValidator.validateTokenWithRevocation\n\t\t\t? await this.tokenValidator.validateTokenWithRevocation(token)\n\t\t\t: this.tokenValidator.validateToken(token)\n\t\tif (payload === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Only accept access tokens for sync authentication\n\t\tif (payload.type !== 'access') {\n\t\t\treturn null\n\t\t}\n\n\t\t// Verify the user still exists (may have been deleted since token was issued)\n\t\tconst user = await this.userLookup.findById(payload.sub)\n\t\tif (user === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Update device last-seen timestamp\n\t\tif (this.deviceTracker) {\n\t\t\tawait this.deviceTracker.touchDevice(payload.dev)\n\t\t}\n\n\t\t// The grant is always server-derived. Without a resolver it binds scoped\n\t\t// collections from the verified subject only, so the client handshake can\n\t\t// never choose whose data it receives (AUTH-1).\n\t\tconst scopes = this.resolveScopes\n\t\t\t? await this.resolveScopes(payload.sub)\n\t\t\t: claimScopes({ userId: payload.sub })\n\n\t\treturn {\n\t\t\tuserId: payload.sub,\n\t\t\tscopes,\n\t\t\t...(typeof payload.exp === 'number' ? { expiresAt: payload.exp * 1000 } : {}),\n\t\t\tmetadata: {\n\t\t\t\tdeviceId: payload.dev,\n\t\t\t\temail: user.email,\n\t\t\t\tname: user.name,\n\t\t\t},\n\t\t}\n\t}\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Configuration for creating a MixedAuthProvider.\n */\nexport interface MixedAuthProviderOptions {\n\t/**\n\t * Primary auth provider that validates tokens from authenticated users.\n\t * Typically a `KoraAuthProvider`, `TokenAuthProvider`, or the result of\n\t * `authRoutes.toSyncAuthProvider()`.\n\t */\n\tprimary: AuthProvider\n\n\t/**\n\t * Scopes to apply to anonymous connections. This is the complete anonymous\n\t * grant: anonymous sessions can sync exactly these collections, and the\n\t * client handshake can only narrow them, never add one.\n\t * Each key is a collection name; the value is a filter object\n\t * (use `{}` for unrestricted access to that collection).\n\t *\n\t * @example\n\t * ```typescript\n\t * // Anonymous users can only sync the 'responses' collection\n\t * anonymousScopes: { responses: {} }\n\t *\n\t * // Anonymous users can read published forms\n\t * anonymousScopes: { forms: { status: 'published' } }\n\t * ```\n\t */\n\tanonymousScopes: Record<string, Record<string, unknown>>\n\n\t/**\n\t * Prefix for generated anonymous user IDs.\n\t * A unique suffix is appended to each connection.\n\t * @default 'anon'\n\t */\n\tanonymousPrefix?: string\n}\n\n/**\n * Auth provider that supports both authenticated and anonymous connections.\n *\n * When a client connects with a token, the primary auth provider decides:\n * a valid token authenticates normally and an invalid, expired or revoked one\n * is rejected (the client refreshes and reconnects). Only a client that sends\n * no token at all is accepted as anonymous, with exactly `anonymousScopes`.\n *\n * This is the recommended pattern for apps that need public data access\n * alongside authenticated users — for example, a form builder where\n * authenticated users create forms but anyone can submit responses.\n *\n * @example\n * ```typescript\n * import { MixedAuthProvider, KoraAuthProvider } from '@korajs/server'\n *\n * const auth = new MixedAuthProvider({\n * primary: authRoutes.toSyncAuthProvider(),\n * anonymousScopes: {\n * // Anonymous users can only sync the 'responses' collection\n * responses: {},\n * },\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n *\n * @example\n * ```typescript\n * // On the client, return an empty token for unauthenticated users:\n * const app = createApp({\n * schema,\n * sync: {\n * url: 'wss://my-server.com/kora',\n * auth: async () => ({\n * token: (await authClient.getAccessToken()) ?? '',\n * }),\n * },\n * })\n * ```\n */\nexport class MixedAuthProvider implements AuthProvider {\n\tprivate readonly primary: AuthProvider\n\tprivate readonly anonymousScopes: Record<string, Record<string, unknown>>\n\tprivate readonly anonymousPrefix: string\n\tprivate anonymousCounter = 0\n\n\tconstructor(options: MixedAuthProviderOptions) {\n\t\tthis.primary = options.primary\n\t\tthis.anonymousScopes = options.anonymousScopes\n\t\tthis.anonymousPrefix = options.anonymousPrefix ?? 'anon'\n\t\t// Forward the primary provider's revocation feed, so wrapping it does not\n\t\t// silently stop revoked sessions from being terminated (AUTH-11).\n\t\tconst primary = this.primary\n\t\tif (primary.onRevoke) {\n\t\t\tthis.onRevoke = (listener) => primary.onRevoke?.(listener) ?? (() => {})\n\t\t}\n\t}\n\n\t/** The primary provider's revocation feed, when it has one. */\n\tonRevoke?: AuthProvider['onRevoke']\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\t// A presented credential is either valid or rejected. It is never silently\n\t\t// downgraded to anonymous: an expired or revoked token from a signed-in\n\t\t// user must make the client refresh, not sync that user's local writes\n\t\t// against the anonymous grant.\n\t\tif (token) {\n\t\t\treturn this.primary.authenticate(token)\n\t\t}\n\n\t\t// Fall back to scoped anonymous access\n\t\tthis.anonymousCounter++\n\t\treturn {\n\t\t\tuserId: `${this.anonymousPrefix}-${Date.now()}-${this.anonymousCounter}`,\n\t\t\t// The userId above is per connection, so node-id claims must not be keyed by\n\t\t\t// it (a reconnecting anonymous device would be locked out of its own node).\n\t\t\tanonymous: true,\n\t\t\t// A fresh copy per session: the grant must not be shared mutable state.\n\t\t\tscopes: Object.fromEntries(\n\t\t\t\tObject.entries(this.anonymousScopes).map(([collection, predicate]) => [\n\t\t\t\t\tcollection,\n\t\t\t\t\t{ ...predicate },\n\t\t\t\t]),\n\t\t\t),\n\t\t}\n\t}\n}\n","import type { KoraSyncServerConfig } from '../types'\nimport { KoraSyncServer } from './kora-sync-server'\n\n/**\n * Factory function to create a KoraSyncServer.\n *\n * @param config - Server configuration\n * @returns A new KoraSyncServer instance\n *\n * @example\n * ```typescript\n * const server = createKoraServer({\n * store: new MemoryServerStore(),\n * port: 3000,\n * })\n * await server.start()\n * ```\n */\nexport function createKoraServer(config: KoraSyncServerConfig): KoraSyncServer {\n\treturn new KoraSyncServer(config)\n}\n","import type { BlobRef } from '@korajs/core'\nimport { BackupValidationError } from '../apply/ingest-validation'\nimport type { ServerStore } from '../store/server-store'\nimport type { WsWebSocket } from '../transport/ws-server-transport'\nimport type { KoraSyncServerConfig } from '../types'\nimport {\n\tDEFAULT_MAX_MESSAGE_BYTES,\n\tKoraSyncServer,\n\tresolvePerMessageDeflate,\n} from './kora-sync-server'\nimport type { ProductionHttpRouteContext } from './route-context'\nimport { createStaticFileHandler } from './static-files'\nimport { type TrustProxySetting, resolveClientIp } from './trust-proxy'\n\n/**\n * Configuration for the production server that serves both\n * static files and WebSocket sync on a single port.\n */\nexport interface ProductionServerConfig {\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Port to listen on. Defaults to 3001 or process.env.PORT. */\n\tport?: number\n\t/** Directory containing built static files. Defaults to './dist'. */\n\tstaticDir?: string\n\t/** WebSocket sync path. Defaults to '/kora-sync'. */\n\tsyncPath?: string\n\t/** Additional KoraSyncServer options */\n\tsyncOptions?: Omit<KoraSyncServerConfig, 'store' | 'port' | 'host' | 'path'>\n\t/**\n\t * Cross-Origin-Embedder-Policy for static and route responses. Defaults to\n\t * `credentialless`, which keeps third-party embeds usable while allowing\n\t * capable browsers to enable cross-origin isolation. Use `require-corp` only\n\t * when every embedded resource explicitly opts in with CORP/CORS headers.\n\t */\n\tcrossOriginEmbedderPolicy?: 'credentialless' | 'require-corp' | 'unsafe-none'\n\t/**\n\t * Optional HTTP route handlers mounted before static file serving.\n\t *\n\t * This is intentionally framework-agnostic so packages such as\n\t * `@korajs/auth` can plug into the production server without requiring\n\t * Express, Hono, or another HTTP framework.\n\t */\n\thttpRoutes?: ProductionHttpRoute[]\n\t/**\n\t * Optional token protection for operational endpoints.\n\t *\n\t * When a token is omitted, the matching endpoint group remains public for\n\t * backward compatibility. Production apps should set at least adminToken and\n\t * backupToken.\n\t */\n\toperationalAuth?: ProductionOperationalAuth\n\t/**\n\t * Reverse proxies trusted to report the client address in `X-Forwarded-For`,\n\t * which becomes `request.ip` (the key `@korajs/auth` rate-limits sign-in by).\n\t * A hop count (`1` for a single load balancer in front) or a list of trusted\n\t * proxy IPs / CIDR ranges. When unset, the header is ignored and `request.ip`\n\t * is the socket address, so a client cannot pick its own rate-limit bucket.\n\t */\n\ttrustProxy?: TrustProxySetting\n\t/**\n\t * Largest request body a custom HTTP route (`httpRoutes`) accepts, in bytes. A\n\t * larger body is refused with 413 before it is buffered (SRV-6), so an\n\t * unauthenticated client cannot make the server hold arbitrary amounts of memory.\n\t * Defaults to 1 MiB.\n\t */\n\tmaxRequestBodyBytes?: number\n\t/**\n\t * Largest backup accepted by `/__kora/backup/import`, in bytes. Defaults to 256 MiB.\n\t */\n\tmaxBackupBytes?: number\n}\n\n/** Default largest custom-route request body: 1 MiB. */\nexport const DEFAULT_MAX_REQUEST_BODY_BYTES = 1024 * 1024\n/** Default largest backup import body: 256 MiB. */\nexport const DEFAULT_MAX_BACKUP_BYTES = 256 * 1024 * 1024\n\nexport interface ProductionOperationalAuth {\n\t/** Protects /__kora, /__kora/status, and /__kora/events. */\n\tadminToken?: string\n\t/** Protects /__kora/metrics. Falls back to adminToken when omitted. */\n\tmetricsToken?: string\n\t/** Protects /__kora/backup/*. Falls back to adminToken when omitted. */\n\tbackupToken?: string\n}\n\nexport interface ProductionHttpRouteRequest {\n\tmethod: string\n\tpath: string\n\tbody?: unknown\n\theaders?: Record<string, string | string[] | undefined>\n\tquery?: Record<string, string | string[] | undefined>\n\tip?: string\n\t/**\n\t * Scoped, validated data-plane access. Use `kora.apply()` to mutate through\n\t * the same pipeline as sync (constraints, referential integrity, fan-out) and\n\t * `kora.query()` / `kora.findById()` to read materialized state, instead of\n\t * writing to the store directly and bypassing those guarantees.\n\t */\n\tkora: ProductionHttpRouteContext\n}\n\nexport interface ProductionHttpRouteResponse {\n\tstatus: number\n\tbody?: unknown\n\theaders?: Record<string, string>\n}\n\nexport interface ProductionHttpRoute {\n\t/** URL path prefix, for example `/auth`. */\n\tpath: string\n\thandle(request: ProductionHttpRouteRequest): Promise<ProductionHttpRouteResponse>\n}\n\n/**\n * A production server handle returned by createProductionServer.\n */\nexport interface ProductionServer {\n\t/**\n\t * Start listening. Returns the URL the server is available at, with the port it\n\t * actually bound (pass `port: 0` to let the OS pick a free one).\n\t */\n\tstart(): Promise<string>\n\t/** Stop the server gracefully. */\n\tstop(): Promise<void>\n\t/**\n\t * Trusted, scoped data-plane access for server-side callers that have no HTTP\n\t * request — background jobs, scheduled tasks, seeding scripts.\n\t *\n\t * `kora.apply()` runs the mutation through the exact same validated pipeline as\n\t * sync (Tier 2 constraints, referential integrity, materialization, and fan-out\n\t * to connected clients), and `kora.query()` / `kora.findById()` read\n\t * materialized state. This is the same context handed to custom HTTP routes as\n\t * `request.kora`, so a job and a request share one code path and one set of\n\t * guarantees instead of the job writing to the store directly and silently\n\t * bypassing validation.\n\t */\n\tkora: ProductionHttpRouteContext\n\t/**\n\t * Every blob reference still reachable from a live record across all\n\t * collections that declare a `blob` field. This is the live set for\n\t * garbage-collecting the server's central blob store: pass it to\n\t * `collectBlobGarbage(blobStore, refs)` from `@korajs/store` on a schedule to\n\t * reclaim bytes no record points at any more.\n\t *\n\t * @returns Every live blob reference the server can currently see.\n\t */\n\tgetLiveBlobRefs(): Promise<BlobRef[]>\n}\n\n/**\n * Creates a production server that serves both static files and WebSocket sync\n * on a single port, plus built-in dashboard and observability endpoints.\n *\n * @param config - Production server configuration\n * @returns A ProductionServer instance\n *\n * @example\n * ```typescript\n * const server = createProductionServer({\n * store: createSqliteServerStore({ filename: './kora-server.db' }),\n * })\n * const url = await server.start()\n * ```\n */\nexport function createProductionServer(config: ProductionServerConfig): ProductionServer {\n\tconst port = config.port ?? (Number(process.env.PORT) || 3001)\n\tconst staticDir = config.staticDir ?? './dist'\n\tconst syncPath = config.syncPath ?? '/kora-sync'\n\tconst crossOriginEmbedderPolicy = config.crossOriginEmbedderPolicy ?? 'credentialless'\n\n\tconst syncServer = new KoraSyncServer({\n\t\tstore: config.store,\n\t\tenableDashboard: true,\n\t\t...config.syncOptions,\n\t})\n\n\t// Scoped, validated data-plane access handed to every custom HTTP route as\n\t// `request.kora`, exposed on the handle as `server.kora`, and used by the\n\t// operation validator. One shared context (it holds no per-request state).\n\tconst routeContext = syncServer.getKoraContext()\n\n\tlet httpServer: import('node:http').Server | null = null\n\n\tfunction getOperationalToken(kind: 'admin' | 'metrics' | 'backup'): string | undefined {\n\t\tconst auth = config.operationalAuth\n\t\tif (!auth) return undefined\n\t\tif (kind === 'metrics') return auth.metricsToken || auth.adminToken\n\t\tif (kind === 'backup') return auth.backupToken || auth.adminToken\n\t\treturn auth.adminToken\n\t}\n\n\tfunction extractRequestToken(req: import('node:http').IncomingMessage): string | null {\n\t\tconst authorization = req.headers.authorization\n\t\tif (authorization?.startsWith('Bearer ')) {\n\t\t\treturn authorization.slice('Bearer '.length).trim()\n\t\t}\n\n\t\tconst headerNames = ['x-kora-admin-token', 'x-kora-metrics-token', 'x-kora-backup-token']\n\t\tfor (const name of headerNames) {\n\t\t\tconst value = req.headers[name]\n\t\t\tif (typeof value === 'string' && value.length > 0) return value\n\t\t\tif (Array.isArray(value) && typeof value[0] === 'string' && value[0].length > 0) {\n\t\t\t\treturn value[0]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tfunction isOperationalRequestAllowed(\n\t\treq: import('node:http').IncomingMessage,\n\t\tkind: 'admin' | 'metrics' | 'backup',\n\t): boolean {\n\t\tconst expected = getOperationalToken(kind)\n\t\tif (!expected) return true\n\t\treturn extractRequestToken(req) === expected\n\t}\n\n\tfunction rejectUnauthorized(res: import('node:http').ServerResponse): void {\n\t\tres.writeHead(401, {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'WWW-Authenticate': 'Bearer realm=\"kora\"',\n\t\t})\n\t\tres.end(JSON.stringify({ error: 'Unauthorized' }))\n\t}\n\n\t/**\n\t * Format the metrics snapshot as Prometheus exposition format.\n\t * Zero-dependency — no prom-client needed.\n\t */\n\tfunction formatPrometheusMetrics(): string {\n\t\tconst status = syncServer.getMetricsCollector().getSnapshot(0)\n\t\tconst lines: string[] = [\n\t\t\t'# HELP kora_connected_clients Current number of connected clients',\n\t\t\t'# TYPE kora_connected_clients gauge',\n\t\t\t`kora_connected_clients ${status.connectedClients}`,\n\t\t\t'',\n\t\t\t'# HELP kora_peak_connections Peak number of simultaneous connections since server start',\n\t\t\t'# TYPE kora_peak_connections gauge',\n\t\t\t`kora_peak_connections ${status.peakConnections}`,\n\t\t\t'',\n\t\t\t'# HELP kora_connections_total Total number of connections handled since server start',\n\t\t\t'# TYPE kora_connections_total counter',\n\t\t\t`kora_connections_total ${status.connectionsTotal}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_received_total Total operations received from clients',\n\t\t\t'# TYPE kora_operations_received_total counter',\n\t\t\t`kora_operations_received_total ${status.operationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operation_batches_received_total Total operation batches received from clients',\n\t\t\t'# TYPE kora_operation_batches_received_total counter',\n\t\t\t`kora_operation_batches_received_total ${status.batchesReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_unique_operations_received_total Newly materialized operations received from clients',\n\t\t\t'# TYPE kora_unique_operations_received_total counter',\n\t\t\t`kora_unique_operations_received_total ${status.uniqueOperationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_duplicate_operations_received_total Duplicate operations received from clients',\n\t\t\t'# TYPE kora_duplicate_operations_received_total counter',\n\t\t\t`kora_duplicate_operations_received_total ${status.duplicateOperationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_rejected_operations_total Operations rejected before authoritative materialization',\n\t\t\t'# TYPE kora_rejected_operations_total counter',\n\t\t\t`kora_rejected_operations_total ${status.rejectedOperations}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_sent_total Total operations sent to clients',\n\t\t\t'# TYPE kora_operations_sent_total counter',\n\t\t\t`kora_operations_sent_total ${status.operationsSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_received_total Total bytes received from clients',\n\t\t\t'# TYPE kora_bytes_received_total counter',\n\t\t\t`kora_bytes_received_total ${status.bytesReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_sent_total Total bytes sent to clients',\n\t\t\t'# TYPE kora_bytes_sent_total counter',\n\t\t\t`kora_bytes_sent_total ${status.bytesSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_errors_total Total errors since server start',\n\t\t\t'# TYPE kora_errors_total counter',\n\t\t\t`kora_errors_total ${status.errorCount}`,\n\t\t\t'',\n\t\t\t'# HELP kora_uptime_seconds Server uptime in seconds',\n\t\t\t'# TYPE kora_uptime_seconds gauge',\n\t\t\t`kora_uptime_seconds ${Math.floor(status.uptime / 1000)}`,\n\t\t\t'',\n\t\t\t'# HELP kora_schema_version Schema version the server expects',\n\t\t\t'# TYPE kora_schema_version gauge',\n\t\t\t`kora_schema_version ${status.schemaVersion}`,\n\t\t\t'',\n\t\t]\n\t\treturn lines.join('\\n')\n\t}\n\n\tconst maxRequestBodyBytes = config.maxRequestBodyBytes ?? DEFAULT_MAX_REQUEST_BODY_BYTES\n\tconst maxBackupBytes = config.maxBackupBytes ?? DEFAULT_MAX_BACKUP_BYTES\n\n\t/**\n\t * Read a request body of at most `limit` bytes. Resolves null when the body (or its\n\t * declared Content-Length) is larger: the caller answers 413, and nothing past the\n\t * limit is buffered (SRV-6).\n\t */\n\tfunction readBodyBuffer(\n\t\treq: import('node:http').IncomingMessage,\n\t\tlimit: number,\n\t): Promise<Buffer | null> {\n\t\tconst declared = Number(req.headers['content-length'])\n\t\tif (Number.isFinite(declared) && declared > limit) return Promise.resolve(null)\n\t\treturn new Promise((resolve) => {\n\t\t\tconst chunks: Buffer[] = []\n\t\t\tlet received = 0\n\t\t\tlet settled = false\n\t\t\tconst finish = (value: Buffer | null): void => {\n\t\t\t\tif (settled) return\n\t\t\t\tsettled = true\n\t\t\t\tresolve(value)\n\t\t\t}\n\t\t\treq.on('data', (chunk: Buffer) => {\n\t\t\t\tif (settled) return\n\t\t\t\treceived += chunk.byteLength\n\t\t\t\tif (received > limit) {\n\t\t\t\t\tchunks.length = 0\n\t\t\t\t\t// Stop reading; the caller replies 413 and then drops the connection.\n\t\t\t\t\treq.pause()\n\t\t\t\t\tfinish(null)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tchunks.push(chunk)\n\t\t\t})\n\t\t\treq.on('end', () => finish(Buffer.concat(chunks)))\n\t\t\t// A raw http.IncomingMessage starts paused: attaching 'data'/'end'\n\t\t\t// listeners alone does not put it in flowing mode. Without an\n\t\t\t// explicit resume(), 'data' never fires, 'end' fires immediately with\n\t\t\t// zero chunks, and every POST body silently reads back as empty —\n\t\t\t// which is exactly what broke httpRoutes handlers (including\n\t\t\t// @korajs/auth's signup/signin) reading `req.body`. Guard with\n\t\t\t// `readableFlowing` so this stays a no-op if the stream is already\n\t\t\t// flowing (e.g. a future caller that reads it differently).\n\t\t\tif (!req.readableFlowing) {\n\t\t\t\treq.resume()\n\t\t\t}\n\t\t\t// If the client disconnects mid-upload, `end` never fires; resolve\n\t\t\t// with whatever arrived instead of leaving the request hung forever.\n\t\t\treq.on('error', () => finish(Buffer.concat(chunks)))\n\t\t})\n\t}\n\n\t/** Answer 413 and drop the connection once the response is written. */\n\tfunction rejectTooLarge(\n\t\treq: import('node:http').IncomingMessage,\n\t\tres: import('node:http').ServerResponse,\n\t\tlimit: number,\n\t): void {\n\t\tres.writeHead(413, { 'Content-Type': 'application/json', Connection: 'close' })\n\t\tres.end(JSON.stringify({ error: 'Payload too large', maxBytes: limit }), () => req.destroy())\n\t}\n\n\tasync function readJsonBody(\n\t\treq: import('node:http').IncomingMessage,\n\t): Promise<{ tooLarge: true } | { tooLarge: false; body: unknown }> {\n\t\tconst buffer = await readBodyBuffer(req, maxRequestBodyBytes)\n\t\tif (buffer === null) return { tooLarge: true }\n\t\tif (buffer.byteLength === 0) return { tooLarge: false, body: undefined }\n\t\ttry {\n\t\t\treturn { tooLarge: false, body: JSON.parse(buffer.toString('utf8')) as unknown }\n\t\t} catch {\n\t\t\treturn { tooLarge: false, body: undefined }\n\t\t}\n\t}\n\n\tfunction matchesRoutePrefix(pathname: string, prefix: string): boolean {\n\t\tconst normalizedPrefix = normalizeRoutePath(prefix)\n\t\treturn pathname === normalizedPrefix || pathname.startsWith(`${normalizedPrefix}/`)\n\t}\n\n\tfunction normalizeRoutePath(path: string): string {\n\t\tconst prefixed = path.startsWith('/') ? path : `/${path}`\n\t\treturn prefixed.length > 1 ? prefixed.replace(/\\/+$/, '') : prefixed\n\t}\n\n\tfunction getClientIp(req: import('node:http').IncomingMessage): string | undefined {\n\t\treturn resolveClientIp(\n\t\t\treq.socket.remoteAddress,\n\t\t\treq.headers['x-forwarded-for'],\n\t\t\tconfig.trustProxy,\n\t\t)\n\t}\n\n\tfunction getQuery(url: URL): Record<string, string | string[] | undefined> {\n\t\tconst query: Record<string, string | string[] | undefined> = {}\n\t\tfor (const [key, value] of url.searchParams) {\n\t\t\tconst existing = query[key]\n\t\t\tif (existing === undefined) {\n\t\t\t\tquery[key] = value\n\t\t\t} else if (Array.isArray(existing)) {\n\t\t\t\texisting.push(value)\n\t\t\t} else {\n\t\t\t\tquery[key] = [existing, value]\n\t\t\t}\n\t\t}\n\t\treturn query\n\t}\n\n\tfunction writeJsonResponse(\n\t\tres: import('node:http').ServerResponse,\n\t\tresult: ProductionHttpRouteResponse,\n\t): void {\n\t\tconst headers = {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(result.headers ?? {}),\n\t\t}\n\t\tres.writeHead(result.status, headers)\n\t\tres.end(JSON.stringify(result.body ?? null))\n\t}\n\n\treturn {\n\t\tkora: routeContext,\n\n\t\tgetLiveBlobRefs(): Promise<BlobRef[]> {\n\t\t\treturn syncServer.getLiveBlobRefs()\n\t\t},\n\n\t\tasync start(): Promise<string> {\n\t\t\tconst { createServer } = await import('node:http')\n\t\t\tconst { WebSocketServer } = await import('ws')\n\n\t\t\tconst serveStatic = createStaticFileHandler(staticDir)\n\n\t\t\thttpServer = createServer(async (req, res) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait handleRequest(req, res)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// http.createServer never awaits its request listener, so a\n\t\t\t\t\t// callback that rejects becomes an unhandled promise rejection\n\t\t\t\t\t// process-wide, and Node's default `--unhandled-rejections=throw`\n\t\t\t\t\t// crashes the entire server. One bad request (malformed body,\n\t\t\t\t\t// a buggy custom httpRoute handler, anything unexpected) must\n\t\t\t\t\t// only fail that one response, never take the whole process\n\t\t\t\t\t// down with it.\n\t\t\t\t\tconsole.error('[kora] Unhandled error in HTTP request handler:', error)\n\t\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Internal server error' }))\n\t\t\t\t\t} else if (!res.writableEnded) {\n\t\t\t\t\t\tres.end()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tasync function handleRequest(\n\t\t\t\treq: import('node:http').IncomingMessage,\n\t\t\t\tres: import('node:http').ServerResponse,\n\t\t\t): Promise<void> {\n\t\t\t\t// COOP/COEP headers required for SharedArrayBuffer (OPFS persistence)\n\t\t\t\tres.setHeader('Cross-Origin-Opener-Policy', 'same-origin')\n\t\t\t\tres.setHeader('Cross-Origin-Embedder-Policy', crossOriginEmbedderPolicy)\n\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\n\t\t\t\t// ── Health check ──────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/health') {\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tstatus: 'ok',\n\t\t\t\t\t\t\tversion: status.version,\n\t\t\t\t\t\t\tuptime: status.uptime,\n\t\t\t\t\t\t\tconnectedClients: status.connectedClients,\n\t\t\t\t\t\t\ttotalOperations: status.totalOperations,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Status endpoint ───────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/status') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(JSON.stringify(status, null, 2))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Prometheus metrics endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/metrics') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'metrics')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4' })\n\t\t\t\t\tres.end(formatPrometheusMetrics())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Server-Sent Events endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/events') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t'Content-Type': 'text/event-stream',\n\t\t\t\t\t\t'Cache-Control': 'no-cache',\n\t\t\t\t\t\tConnection: 'keep-alive',\n\t\t\t\t\t\t'X-Accel-Buffering': 'no',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Send initial status event\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(status)}\\n\\n`)\n\n\t\t\t\t\t// Poll metrics periodically and push as SSE events\n\t\t\t\t\tconst interval = setInterval(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst s = await syncServer.getStatus()\n\t\t\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(s)}\\n\\n`)\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Connection may have closed\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 2000)\n\n\t\t\t\t\t// Clean up on connection close\n\t\t\t\t\treq.on('close', () => {\n\t\t\t\t\t\tclearInterval(interval)\n\t\t\t\t\t})\n\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Dashboard HTML ────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora' || url.pathname === '/__kora/') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n\t\t\t\t\tres.end(renderDashboardHtml(status))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup export ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/export' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst backup = await config.store.exportBackup()\n\t\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t\t\t\t\t'Content-Disposition': `attachment; filename=\"kora-backup-${Date.now()}.kora\"`,\n\t\t\t\t\t\t\t'Content-Length': String(backup.byteLength),\n\t\t\t\t\t\t})\n\t\t\t\t\t\tres.end(Buffer.from(backup))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Backup failed', message: (error as Error).message }))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup import ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/import' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst body = await readBodyBuffer(req, maxBackupBytes)\n\t\t\t\t\t\tif (body === null) {\n\t\t\t\t\t\t\trejectTooLarge(req, res, maxBackupBytes)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst merge = url.searchParams.get('merge') === 'true'\n\t\t\t\t\t\tconst result = await config.store.importBackup(\n\t\t\t\t\t\t\tnew Uint8Array(body.buffer, body.byteOffset, body.byteLength),\n\t\t\t\t\t\t\tmerge,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tres.writeHead(result.success ? 200 : 400, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify(result))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// A backup whose operations fail ingest validation (far-future\n\t\t\t\t\t\t// timestamps, malformed sequence numbers) is the caller's input, not a\n\t\t\t\t\t\t// server fault: 400 with the details (SYNC-7).\n\t\t\t\t\t\tconst invalid = error instanceof BackupValidationError\n\t\t\t\t\t\tres.writeHead(invalid ? 400 : 500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(\n\t\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\t\terror: 'Restore failed',\n\t\t\t\t\t\t\t\tmessage: (error as Error).message,\n\t\t\t\t\t\t\t\t...(invalid ? { code: error.code, details: error.context } : {}),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Custom HTTP routes (auth, webhooks, app APIs) ─────────────\n\t\t\t\tconst customRoute = config.httpRoutes?.find((route) =>\n\t\t\t\t\tmatchesRoutePrefix(url.pathname, route.path),\n\t\t\t\t)\n\t\t\t\tif (customRoute) {\n\t\t\t\t\tconst parsed = await readJsonBody(req)\n\t\t\t\t\tif (parsed.tooLarge) {\n\t\t\t\t\t\trejectTooLarge(req, res, maxRequestBodyBytes)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst result = await customRoute.handle({\n\t\t\t\t\t\tmethod: req.method ?? 'GET',\n\t\t\t\t\t\tpath: url.pathname,\n\t\t\t\t\t\tbody: parsed.body,\n\t\t\t\t\t\theaders: req.headers,\n\t\t\t\t\t\tquery: getQuery(url),\n\t\t\t\t\t\tip: getClientIp(req),\n\t\t\t\t\t\tkora: routeContext,\n\t\t\t\t\t})\n\t\t\t\t\twriteJsonResponse(res, result)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Static file serving (NEW-SRV-8) ───────────────────────────\n\t\t\t\tawait serveStatic(req, res, url.pathname)\n\t\t\t}\n\n\t\t\tconst wss = new WebSocketServer({\n\t\t\t\tnoServer: true,\n\t\t\t\tmaxPayload: config.syncOptions?.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES,\n\t\t\t\tperMessageDeflate: resolvePerMessageDeflate(config.syncOptions?.perMessageDeflate),\n\t\t\t})\n\n\t\t\thttpServer.on('upgrade', (req, socket, head) => {\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\t\t\t\tif (url.pathname === syncPath) {\n\t\t\t\t\twss.handleUpgrade(req, socket, head, (ws) => {\n\t\t\t\t\t\t// The sync server builds the transport, so this path gets the same\n\t\t\t\t\t\t// liveness probing, send-buffer ceiling and serializer as standalone.\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsyncServer.handleWebSocket(ws as unknown as WsWebSocket)\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Refused (for example the connection limit): handleConnection has\n\t\t\t\t\t\t\t// already told the client and closed the socket.\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsocket.destroy()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\t\tconst onError = (error: Error) => {\n\t\t\t\t\treject(error)\n\t\t\t\t}\n\t\t\t\thttpServer?.once('error', onError)\n\t\t\t\thttpServer?.listen(port, '0.0.0.0', () => {\n\t\t\t\t\thttpServer?.off('error', onError)\n\t\t\t\t\t// Report the bound port, so `port: 0` (an OS-assigned free port, as tests\n\t\t\t\t\t// running in parallel use) resolves to a reachable URL.\n\t\t\t\t\tconst address = httpServer?.address()\n\t\t\t\t\tconst bound = address && typeof address === 'object' ? address.port : port\n\t\t\t\t\tresolve(`http://localhost:${bound}`)\n\t\t\t\t})\n\t\t\t})\n\t\t},\n\n\t\tasync stop(): Promise<void> {\n\t\t\tawait syncServer.stop()\n\t\t\tif (httpServer) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\thttpServer?.close(() => resolve())\n\t\t\t\t})\n\t\t\t\thttpServer = null\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Render a minimal self-contained dashboard HTML page.\n * Shows server status with live-updating metrics via SSE.\n */\nfunction renderDashboardHtml(status: {\n\tversion: string\n\tuptime: number\n\tconnectedClients: number\n\ttotalOperations: number\n\tschemaVersion: number\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\toperationsSent: number\n\terrorCount: number\n}): string {\n\tconst version = status.version\n\tconst uptime = formatUptime(status.uptime)\n\treturn `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Kora Dashboard</title>\n<style>\n * { box-sizing: border-box; margin: 0; padding: 0 }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0; padding: 2rem }\n h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.25rem }\n .subtitle { color: #64748b; margin-bottom: 2rem; font-size: 0.875rem }\n .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem }\n .card { background: #1e293b; border: 1px solid #334155; border-radius: 0.75rem; padding: 1.25rem }\n .card .label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: #64748b; margin-bottom: 0.5rem }\n .card .value { font-size: 1.75rem; font-weight: 700; color: #38bdf8 }\n .card .value.green { color: #4ade80 }\n .card .value.red { color: #f87171 }\n .card .value.yellow { color: #fbbf24 }\n .section-title { font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; margin-top: 1.5rem }\n table { width: 100%; border-collapse: collapse; font-size: 0.875rem }\n th { text-align: left; padding: 0.5rem 0.75rem; color: #64748b; font-weight: 500; border-bottom: 1px solid #334155 }\n td { padding: 0.5rem 0.75rem; border-bottom: 1px solid #1e293b }\n .status-dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; margin-right: 0.375rem }\n .status-dot.running { background: #4ade80 }\n .status-dot.stopped { background: #f87171 }\n</style>\n</head>\n<body>\n<h1>Kora Sync Server</h1>\n<p class=\"subtitle\">v${version} &middot; <span class=\"status-dot running\"></span>Running</p>\n<div class=\"grid\">\n <div class=\"card\"><div class=\"label\">Uptime</div><div class=\"value\">${uptime}</div></div>\n <div class=\"card\"><div class=\"label\">Connected Clients</div><div class=\"value\" id=\"connectedClients\">${status.connectedClients}</div></div>\n <div class=\"card\"><div class=\"label\">Total Operations</div><div class=\"value\" id=\"totalOperations\">${status.totalOperations}</div></div>\n <div class=\"card\"><div class=\"label\">Peak Connections</div><div class=\"value green\" id=\"peakConnections\">${status.peakConnections}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Received</div><div class=\"value\" id=\"opsReceived\">${status.operationsReceived}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Sent</div><div class=\"value\" id=\"opsSent\">${status.operationsSent}</div></div>\n <div class=\"card\"><div class=\"label\">Errors</div><div class=\"value ${status.errorCount > 0 ? 'red' : 'green'}\" id=\"errors\">${status.errorCount}</div></div>\n <div class=\"card\"><div class=\"label\">Schema Version</div><div class=\"value\">${status.schemaVersion}</div></div>\n</div>\n<script>\n(function() {\n const es = new EventSource('/__kora/events');\n es.addEventListener('status', (e) => {\n const s = JSON.parse(e.data);\n for (const [id, val] of Object.entries({\n connectedClients: s.connectedClients,\n totalOperations: s.totalOperations,\n peakConnections: s.peakConnections,\n opsReceived: s.operationsReceived,\n opsSent: s.operationsSent,\n errors: s.errorCount,\n })) {\n const el = document.getElementById(id);\n if (el) { el.textContent = String(val); el.className = 'value' + (id === 'errors' && val > 0 ? ' red' : id === 'errors' ? ' green' : ''); }\n }\n });\n es.onerror = () => { setTimeout(() => document.location.reload(), 5000); };\n})();\n</script>\n</body>\n</html>`\n}\n\nfunction formatUptime(ms: number): string {\n\tconst seconds = Math.floor(ms / 1000)\n\tconst minutes = Math.floor(seconds / 60)\n\tconst hours = Math.floor(minutes / 60)\n\tconst parts: string[] = []\n\tif (hours > 0) parts.push(`${hours}h`)\n\tif (minutes % 60 > 0) parts.push(`${minutes % 60}m`)\n\tparts.push(`${seconds % 60}s`)\n\treturn parts.join(' ')\n}\n","import { createHash } from 'node:crypto'\nimport { type Stats, createReadStream } from 'node:fs'\nimport { readFile, realpath, stat } from 'node:fs/promises'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { basename, extname, join, resolve, sep } from 'node:path'\nimport {\n\tbrotliCompress,\n\tbrotliDecompress,\n\tgunzip,\n\tgzip,\n\tconstants as zlibConstants,\n} from 'node:zlib'\n\n/**\n * Static file serving for the production server (NEW-SRV-8).\n *\n * What a production static server for an offline-first app must do, and this does:\n * - Year-long `immutable` caching ONLY for content-hashed file names (Vite's\n * `name-[hash].ext`). Everything else, including `index.html`, the service worker, the\n * web manifest and Kora's own UNHASHED `assets/sqlite3.wasm`, is `no-cache`: always\n * revalidated, so a sqlite upgrade can never pair new JavaScript with stale WASM.\n * - Strong, content-derived validators (RT-99): the `ETag` is a SHA-256 of the file's\n * bytes, computed once per file version (cached by path, size, mtime, inode and ctime,\n * re-hashed when any of them changes), so a redeploy that keeps a file's size and\n * modification time (fixed-length hashes in `index.html`/`sw.js`, reproducible builds\n * with normalised mtimes) is never answered `304`. Revalidated (`no-cache`) files carry\n * no `Last-Modified` and ignore `If-Modified-Since`, since an mtime cannot be trusted.\n * - Brotli or gzip for compressible types: a pre-compressed `file.br` / `file.gz` sibling\n * when the build emitted one and it decompresses to the file's current bytes, otherwise\n * compressed once per content hash and cached in memory.\n * - A 404 for a missing file. The SPA fallback (`index.html`) answers navigations only\n * (`Accept: text/html` or `Sec-Fetch-Mode: navigate`) and never a path under\n * `/assets/`, so a stale tab asking for an old hashed chunk gets a 404, not HTML\n * parsed as JavaScript.\n * - Correct media types, including `.webmanifest`, `.wasm` and `.mjs`.\n * - No path escapes the static directory: lexically (`..`, encoded separators) nor through\n * a symbolic link (RT-112). Every file, directory index and pre-compressed sibling is\n * read from its real path, which must lie inside the static directory's real path; an\n * escape is a 404. Links that stay inside the directory keep working.\n */\n\n/** Media types by extension. Text types carry a charset. */\nexport const STATIC_MIME_TYPES: Readonly<Record<string, string>> = {\n\t'.html': 'text/html; charset=utf-8',\n\t'.htm': 'text/html; charset=utf-8',\n\t'.js': 'text/javascript; charset=utf-8',\n\t'.mjs': 'text/javascript; charset=utf-8',\n\t'.cjs': 'text/javascript; charset=utf-8',\n\t'.css': 'text/css; charset=utf-8',\n\t'.json': 'application/json; charset=utf-8',\n\t'.map': 'application/json; charset=utf-8',\n\t'.webmanifest': 'application/manifest+json; charset=utf-8',\n\t'.txt': 'text/plain; charset=utf-8',\n\t'.xml': 'application/xml; charset=utf-8',\n\t'.svg': 'image/svg+xml',\n\t'.png': 'image/png',\n\t'.jpg': 'image/jpeg',\n\t'.jpeg': 'image/jpeg',\n\t'.gif': 'image/gif',\n\t'.webp': 'image/webp',\n\t'.avif': 'image/avif',\n\t'.ico': 'image/x-icon',\n\t'.wasm': 'application/wasm',\n\t'.woff': 'font/woff',\n\t'.woff2': 'font/woff2',\n\t'.ttf': 'font/ttf',\n\t'.otf': 'font/otf',\n\t'.pdf': 'application/pdf',\n\t'.mp3': 'audio/mpeg',\n\t'.mp4': 'video/mp4',\n\t'.webm': 'video/webm',\n}\n\nconst COMPRESSIBLE_EXTENSIONS = new Set([\n\t'.html',\n\t'.htm',\n\t'.js',\n\t'.mjs',\n\t'.cjs',\n\t'.css',\n\t'.json',\n\t'.map',\n\t'.webmanifest',\n\t'.txt',\n\t'.xml',\n\t'.svg',\n\t'.wasm',\n\t'.ico',\n\t'.ttf',\n\t'.otf',\n])\n\n/** Below this, compression costs more than it saves. */\nconst MIN_COMPRESS_BYTES = 1024\n/** On-the-fly compressed bodies kept in memory, so each file is compressed once per deploy. */\nconst COMPRESSED_CACHE_MAX_BYTES = 32 * 1024 * 1024\n/** URL prefix of Vite's emitted assets: never answered with the SPA shell. */\nconst ASSET_PREFIX = '/assets/'\n\nexport const IMMUTABLE_CACHE_CONTROL = 'public, max-age=31536000, immutable'\nexport const REVALIDATE_CACHE_CONTROL = 'no-cache'\n\n/**\n * Whether a file name carries a content hash in Vite/Rollup's `name-[hash].ext` (or\n * `name.[hash].ext`) form: the token after the last `-` or `.` of the stem is 8 or more\n * `[A-Za-z0-9_]` characters and contains an uppercase letter or a digit. Plain words\n * (`sqlite3-opfs-async-proxy.js`, `my-accounts.js`, `sqlite3.wasm`) do not match, so they\n * are revalidated, never frozen. A real hash this misses (one containing `-`, or all\n * lowercase letters) is merely revalidated with a 304: the safe direction.\n */\nexport function isContentHashedFileName(fileName: string): boolean {\n\tconst ext = extname(fileName)\n\tconst stem = ext ? fileName.slice(0, -ext.length) : fileName\n\tconst match = /[.-]([A-Za-z0-9_]{8,})$/.exec(stem)\n\tif (!match) return false\n\treturn /[A-Z0-9]/.test(match[1] as string)\n}\n\n/** `Cache-Control` for a served static file. */\nexport function cacheControlFor(fileName: string): string {\n\treturn isContentHashedFileName(fileName) ? IMMUTABLE_CACHE_CONTROL : REVALIDATE_CACHE_CONTROL\n}\n\ntype Encoding = 'br' | 'gzip'\n\n/** The best encoding the client accepts (q > 0), brotli first. */\nexport function negotiateEncoding(acceptEncoding: string | undefined): Encoding | null {\n\tif (!acceptEncoding) return null\n\tconst accepted = new Map<string, number>()\n\tfor (const part of acceptEncoding.split(',')) {\n\t\tconst [rawName, ...params] = part.trim().split(';')\n\t\tconst name = (rawName ?? '').trim().toLowerCase()\n\t\tif (!name) continue\n\t\tlet q = 1\n\t\tfor (const param of params) {\n\t\t\tconst [key, value] = param.trim().split('=')\n\t\t\tif (key?.trim() === 'q') q = Number(value)\n\t\t}\n\t\taccepted.set(name, Number.isFinite(q) ? q : 0)\n\t}\n\tconst wildcard = accepted.get('*')\n\tconst allows = (name: string): boolean => {\n\t\tconst q = accepted.get(name) ?? wildcard\n\t\treturn q !== undefined && q > 0\n\t}\n\tif (allows('br')) return 'br'\n\tif (allows('gzip')) return 'gzip'\n\treturn null\n}\n\ninterface CachedBody {\n\tbody: Buffer\n\tsize: number\n}\n\ninterface CachedDigest {\n\t/** Identity of the file version the digest was computed for. */\n\tversion: string\n\tdigest: string\n}\n\n/** Everything that changes when a file is rewritten or replaced (ctime cannot be set). */\nfunction fileVersionKey(stats: Stats): string {\n\treturn `${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeMs}:${stats.ctimeMs}`\n}\n\n/** Most file versions whose digests are remembered (one entry per served path). */\nconst DIGEST_CACHE_MAX_ENTRIES = 4096\n\n/** A request handler that serves files from one directory. */\nexport type StaticFileHandler = (\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tpathname: string,\n) => Promise<void>\n\n/**\n * Create the static file handler for a build directory (`dist/`).\n *\n * @param staticDir - Directory holding the built app\n * @returns A handler answering GET and HEAD for files under `staticDir`\n */\nexport function createStaticFileHandler(staticDir: string): StaticFileHandler {\n\tconst root = resolve(staticDir)\n\tconst compressed = new Map<string, CachedBody>()\n\tlet compressedBytes = 0\n\tconst digests = new Map<string, CachedDigest>()\n\t/** Pre-compressed siblings verified against a source digest: `sibling path -> version|digest`. */\n\tconst verifiedSiblings = new Map<string, string>()\n\n\t/**\n\t * SHA-256 (base64url) of a file's bytes, computed once per file version. The cache key\n\t * only decides when to re-hash; the validator itself is always the content digest.\n\t */\n\tasync function contentDigest(path: string, stats: Stats): Promise<string> {\n\t\tconst version = fileVersionKey(stats)\n\t\tconst cached = digests.get(path)\n\t\tif (cached && cached.version === version) return cached.digest\n\t\tconst hash = createHash('sha256')\n\t\tawait new Promise<void>((done, fail) => {\n\t\t\tconst stream = createReadStream(path)\n\t\t\tstream.on('data', (chunk) => hash.update(chunk))\n\t\t\tstream.on('end', () => done())\n\t\t\tstream.on('error', fail)\n\t\t})\n\t\tconst digest = hash.digest('base64url')\n\t\t// Re-insert so the map's order is least-recently-computed first.\n\t\tdigests.delete(path)\n\t\tif (digests.size >= DIGEST_CACHE_MAX_ENTRIES) {\n\t\t\tconst oldest = digests.keys().next().value\n\t\t\tif (oldest !== undefined) digests.delete(oldest)\n\t\t}\n\t\tdigests.set(path, { version, digest })\n\t\treturn digest\n\t}\n\n\tfunction remember(key: string, body: Buffer): void {\n\t\tif (body.length > COMPRESSED_CACHE_MAX_BYTES / 4) return\n\t\twhile (compressedBytes + body.length > COMPRESSED_CACHE_MAX_BYTES && compressed.size > 0) {\n\t\t\tconst oldest = compressed.keys().next().value as string\n\t\t\tcompressedBytes -= compressed.get(oldest)?.size ?? 0\n\t\t\tcompressed.delete(oldest)\n\t\t}\n\t\tcompressed.set(key, { body, size: body.length })\n\t\tcompressedBytes += body.length\n\t}\n\n\tasync function fileStat(path: string): Promise<Stats | null> {\n\t\ttry {\n\t\t\treturn await stat(path)\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\t/** Resolve a URL path to a file inside the root, or null when it would escape it. */\n\tfunction toFilePath(pathname: string): string | null {\n\t\tlet decoded: string\n\t\ttry {\n\t\t\tdecoded = decodeURIComponent(pathname)\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t\tif (decoded.includes('\\0')) return null\n\t\tconst candidate = resolve(join(root, decoded))\n\t\tif (candidate !== root && !candidate.startsWith(root + sep)) return null\n\t\treturn candidate\n\t}\n\n\t/**\n\t * The real location of `path` when it is inside the real static directory, else null\n\t * (RT-112). The lexical check in {@link toFilePath} cannot see symbolic links, which\n\t * `stat` and `createReadStream` follow: a link inside the directory may point anywhere.\n\t * The root's real path is read per request, so a root that is itself a link (an atomic\n\t * `current -> releases/N` deploy) follows its swaps.\n\t */\n\tasync function containedRealPath(path: string): Promise<string | null> {\n\t\ttry {\n\t\t\tconst [realRoot, real] = await Promise.all([realpath(root), realpath(path)])\n\t\t\treturn real === realRoot || real.startsWith(realRoot + sep) ? real : null\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\t/**\n\t * The file a URL path names (or its directory's `index.html`), read from its real,\n\t * contained location; `name` is the requested path, which decides the headers. A path\n\t * whose real location is outside the static directory is \"not found\", never\n\t * \"forbidden\": the server does not reveal what exists outside it.\n\t */\n\tasync function locate(\n\t\tpathname: string,\n\t): Promise<{ path: string; name: string; stats: Stats } | null> {\n\t\tconst filePath = toFilePath(pathname)\n\t\tif (filePath === null) return null\n\t\tconst real = await containedRealPath(filePath)\n\t\tif (real === null) return null\n\t\tconst stats = await fileStat(real)\n\t\tif (stats?.isFile()) return { path: real, name: filePath, stats }\n\t\tif (stats?.isDirectory()) {\n\t\t\tconst index = join(real, 'index.html')\n\t\t\tconst realIndex = await containedRealPath(index)\n\t\t\tif (realIndex === null) return null\n\t\t\tconst indexStats = await fileStat(realIndex)\n\t\t\tif (indexStats?.isFile()) {\n\t\t\t\treturn { path: realIndex, name: join(filePath, 'index.html'), stats: indexStats }\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\treturn async function serveStatic(req, res, pathname) {\n\t\tconst method = req.method ?? 'GET'\n\t\tif (method !== 'GET' && method !== 'HEAD') {\n\t\t\tres.writeHead(405, { Allow: 'GET, HEAD', 'Content-Type': 'text/plain; charset=utf-8' })\n\t\t\tres.end('Method Not Allowed')\n\t\t\treturn\n\t\t}\n\n\t\tlet found = await locate(pathname)\n\t\tif (!found && isNavigation(req) && !pathname.startsWith(ASSET_PREFIX)) {\n\t\t\tfound = await locate('/index.html')\n\t\t}\n\t\tif (!found) {\n\t\t\tres.writeHead(404, {\n\t\t\t\t'Content-Type': 'text/plain; charset=utf-8',\n\t\t\t\t'Cache-Control': 'no-store',\n\t\t\t})\n\t\t\tres.end(method === 'HEAD' ? undefined : 'Not Found')\n\t\t\treturn\n\t\t}\n\n\t\tconst { path, name, stats } = found\n\t\tconst ext = extname(name).toLowerCase()\n\t\tconst fileName = basename(name)\n\t\tconst cacheControl = cacheControlFor(fileName)\n\t\tconst revalidated = cacheControl === REVALIDATE_CACHE_CONTROL\n\t\tconst headers: Record<string, string | number> = {\n\t\t\t'Content-Type': STATIC_MIME_TYPES[ext] ?? 'application/octet-stream',\n\t\t\t'Cache-Control': cacheControl,\n\t\t\t'X-Content-Type-Options': 'nosniff',\n\t\t}\n\t\t// A revalidated file's mtime says nothing about its content (reproducible builds\n\t\t// normalise it), so it is never a validator for one (RT-99).\n\t\tif (!revalidated) headers['Last-Modified'] = stats.mtime.toUTCString()\n\t\tlet digest: string\n\t\ttry {\n\t\t\tdigest = await contentDigest(path, stats)\n\t\t} catch {\n\t\t\t// Removed or replaced between stat and read: let the client retry.\n\t\t\tres.writeHead(404, {\n\t\t\t\t'Content-Type': 'text/plain; charset=utf-8',\n\t\t\t\t'Cache-Control': 'no-store',\n\t\t\t})\n\t\t\tres.end(method === 'HEAD' ? undefined : 'Not Found')\n\t\t\treturn\n\t\t}\n\n\t\tconst compressible = COMPRESSIBLE_EXTENSIONS.has(ext) && stats.size >= MIN_COMPRESS_BYTES\n\t\tconst encoding = compressible ? negotiateEncoding(headerValue(req, 'accept-encoding')) : null\n\t\tif (compressible) headers.Vary = 'Accept-Encoding'\n\t\tconst etag = `\"${digest}${encoding ? `-${encoding === 'br' ? 'br' : 'gz'}` : ''}\"`\n\t\theaders.ETag = etag\n\n\t\tif (isNotModified(req, etag, revalidated ? null : stats.mtime)) {\n\t\t\tres.writeHead(304, headers)\n\t\t\tres.end()\n\t\t\treturn\n\t\t}\n\n\t\tif (encoding) {\n\t\t\tconst body = await compressedBody(path, name, digest, encoding)\n\t\t\theaders['Content-Encoding'] = encoding\n\t\t\theaders['Content-Length'] = body.length\n\t\t\tres.writeHead(200, headers)\n\t\t\tres.end(method === 'HEAD' ? undefined : body)\n\t\t\treturn\n\t\t}\n\n\t\theaders['Content-Length'] = stats.size\n\t\tres.writeHead(200, headers)\n\t\tif (method === 'HEAD') {\n\t\t\tres.end()\n\t\t\treturn\n\t\t}\n\t\tcreateReadStream(path).pipe(res)\n\t}\n\n\tasync function compressedBody(\n\t\tpath: string,\n\t\tname: string,\n\t\tdigest: string,\n\t\tencoding: Encoding,\n\t): Promise<Buffer> {\n\t\t// A pre-compressed sibling the build emitted wins when it holds exactly the file's\n\t\t// current bytes (checked once per sibling version and source digest: with\n\t\t// normalised mtimes, \"not older than the file\" proves nothing). It is looked up next\n\t\t// to the requested name and read only from a contained real location (RT-112).\n\t\tconst sibling = await containedRealPath(`${name}${encoding === 'br' ? '.br' : '.gz'}`)\n\t\tconst siblingStats = sibling === null ? null : await fileStat(sibling)\n\t\tif (sibling !== null && siblingStats?.isFile()) {\n\t\t\tconst siblingKey = `${fileVersionKey(siblingStats)}|${digest}`\n\t\t\tconst body = await readFile(sibling).catch(() => null)\n\t\t\tif (body) {\n\t\t\t\tif (verifiedSiblings.get(sibling) === siblingKey) return body\n\t\t\t\tconst decoded = await decompress(body, encoding).catch(() => null)\n\t\t\t\tif (decoded && createHash('sha256').update(decoded).digest('base64url') === digest) {\n\t\t\t\t\tverifiedSiblings.set(sibling, siblingKey)\n\t\t\t\t\treturn body\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Keyed by the content digest: replaced content never reuses another version's body.\n\t\tconst key = `${encoding}\\0${path}\\0${digest}`\n\t\tconst cached = compressed.get(key)\n\t\tif (cached) return cached.body\n\t\tconst raw = await readFile(path)\n\t\tif (createHash('sha256').update(raw).digest('base64url') !== digest) {\n\t\t\t// Changed since it was hashed: compress what was read, but do not cache it under\n\t\t\t// the old digest.\n\t\t\treturn compress(raw, encoding)\n\t\t}\n\t\tconst body = await compress(raw, encoding)\n\t\tremember(key, body)\n\t\treturn body\n\t}\n}\n\nfunction compress(raw: Buffer, encoding: Encoding): Promise<Buffer> {\n\treturn new Promise<Buffer>((done, fail) => {\n\t\tconst callback = (error: Error | null, result: Buffer): void => {\n\t\t\tif (error) fail(error)\n\t\t\telse done(result)\n\t\t}\n\t\tif (encoding === 'br') {\n\t\t\tbrotliCompress(\n\t\t\t\traw,\n\t\t\t\t{\n\t\t\t\t\tparams: {\n\t\t\t\t\t\t// Quality 5: close to 9 in size at a fraction of the CPU, for a one-time compress.\n\t\t\t\t\t\t[zlibConstants.BROTLI_PARAM_QUALITY]: 5,\n\t\t\t\t\t\t[zlibConstants.BROTLI_PARAM_SIZE_HINT]: raw.length,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcallback,\n\t\t\t)\n\t\t} else {\n\t\t\tgzip(raw, { level: 6 }, callback)\n\t\t}\n\t})\n}\n\nfunction decompress(body: Buffer, encoding: Encoding): Promise<Buffer> {\n\treturn new Promise<Buffer>((done, fail) => {\n\t\tconst callback = (error: Error | null, result: Buffer): void => {\n\t\t\tif (error) fail(error)\n\t\t\telse done(result)\n\t\t}\n\t\tif (encoding === 'br') brotliDecompress(body, callback)\n\t\telse gunzip(body, callback)\n\t})\n}\n\nfunction headerValue(req: IncomingMessage, name: string): string | undefined {\n\tconst value = req.headers[name]\n\treturn Array.isArray(value) ? value.join(', ') : value\n}\n\n/** A browser navigation: the only request the SPA shell may answer for a missing path. */\nfunction isNavigation(req: IncomingMessage): boolean {\n\tif (headerValue(req, 'sec-fetch-mode') === 'navigate') return true\n\tconst accept = headerValue(req, 'accept') ?? ''\n\treturn /(^|[,\\s])text\\/html\\b/i.test(accept)\n}\n\n/**\n * Conditional GET. `mtime` is null for files whose modification time is not a trusted\n * validator (revalidated files): then only `If-None-Match` can produce a 304.\n */\nfunction isNotModified(req: IncomingMessage, etag: string, mtime: Date | null): boolean {\n\tconst ifNoneMatch = headerValue(req, 'if-none-match')\n\tif (ifNoneMatch !== undefined) {\n\t\t// If-None-Match takes precedence over If-Modified-Since (RFC 9110 13.2.2).\n\t\tif (ifNoneMatch.trim() === '*') return true\n\t\tconst strip = (tag: string): string => tag.trim().replace(/^W\\//, '')\n\t\treturn ifNoneMatch.split(',').some((tag) => strip(tag) === etag)\n\t}\n\tconst ifModifiedSince = headerValue(req, 'if-modified-since')\n\tif (ifModifiedSince !== undefined && mtime !== null) {\n\t\tconst since = Date.parse(ifModifiedSince)\n\t\t// HTTP dates have one-second precision.\n\t\tif (Number.isFinite(since)) return Math.floor(mtime.getTime() / 1000) * 1000 <= since\n\t}\n\treturn false\n}\n","/**\n * Which reverse proxies in front of the server are trusted to report the client\n * address in `X-Forwarded-For`.\n *\n * - `number`: trust that many hops, counting the socket peer as the first. `1` means\n * \"one proxy (for example a load balancer) sits directly in front of the server\".\n * - `string[]`: trust peers whose address is in one of these IPs or CIDR ranges\n * (IPv4 and IPv6, for example `['10.0.0.0/8', '::1']`).\n *\n * When unset, `X-Forwarded-For` is ignored and the socket address is the client\n * address, so a directly connected client cannot choose its own address.\n */\nexport type TrustProxySetting = number | string[]\n\n/**\n * Resolve the client address of a request.\n *\n * The address chain is the socket peer followed by the `X-Forwarded-For` entries\n * from right (nearest proxy) to left. Starting at the socket peer, the walk moves\n * one hop further only while the current hop is trusted; the first untrusted hop\n * (or the last entry) is the client. Entries a client could forge are therefore\n * only believed when every hop between them and the server is a trusted proxy.\n *\n * @param socketAddress - The TCP peer address (`req.socket.remoteAddress`)\n * @param forwardedFor - The raw `X-Forwarded-For` header value(s), if any\n * @param trustProxy - Trusted proxy configuration; undefined trusts none\n * @returns The resolved client address, or undefined when the socket has none\n */\nexport function resolveClientIp(\n\tsocketAddress: string | undefined,\n\tforwardedFor: string | string[] | undefined,\n\ttrustProxy: TrustProxySetting | undefined,\n): string | undefined {\n\tif (trustProxy === undefined || socketAddress === undefined) return socketAddress\n\tconst forwarded = (Array.isArray(forwardedFor) ? forwardedFor.join(',') : (forwardedFor ?? ''))\n\t\t.split(',')\n\t\t.map((entry) => entry.trim())\n\t\t.filter((entry) => entry.length > 0)\n\tconst chain = [socketAddress, ...forwarded.reverse()]\n\tconst isTrusted = compileTrust(trustProxy)\n\tlet index = 0\n\twhile (index < chain.length - 1 && isTrusted(chain[index] ?? '', index)) {\n\t\tindex += 1\n\t}\n\treturn chain[index]\n}\n\nfunction compileTrust(setting: TrustProxySetting): (address: string, hop: number) => boolean {\n\tif (typeof setting === 'number') {\n\t\tconst hops = Number.isInteger(setting) && setting > 0 ? setting : 0\n\t\treturn (_address, hop) => hop < hops\n\t}\n\tconst ranges = setting.map(parseRange).filter((range): range is IpRange => range !== null)\n\treturn (address) => {\n\t\tconst parsed = parseIp(address)\n\t\tif (!parsed) return false\n\t\treturn ranges.some(\n\t\t\t(range) =>\n\t\t\t\trange.version === parsed.version &&\n\t\t\t\tparsed.value >> BigInt(range.bits - range.prefix) ===\n\t\t\t\t\trange.value >> BigInt(range.bits - range.prefix),\n\t\t)\n\t}\n}\n\ninterface ParsedIp {\n\tversion: 4 | 6\n\tvalue: bigint\n}\n\ninterface IpRange extends ParsedIp {\n\tbits: number\n\tprefix: number\n}\n\nfunction parseRange(spec: string): IpRange | null {\n\tconst [addressPart, prefixPart] = spec.trim().split('/')\n\tconst parsed = parseIp(addressPart ?? '')\n\tif (!parsed) return null\n\tconst bits = parsed.version === 4 ? 32 : 128\n\tconst prefix = prefixPart === undefined ? bits : Number(prefixPart)\n\tif (!Number.isInteger(prefix) || prefix < 0 || prefix > bits) return null\n\treturn { ...parsed, bits, prefix }\n}\n\nfunction parseIp(input: string): ParsedIp | null {\n\tconst address = input.trim()\n\t// IPv4-mapped IPv6 (how Node reports IPv4 peers on dual-stack sockets).\n\tconst mapped = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/i.exec(address)\n\tif (mapped?.[1]) return parseIpv4(mapped[1])\n\tif (address.includes(':')) return parseIpv6(address)\n\treturn parseIpv4(address)\n}\n\nfunction parseIpv4(address: string): ParsedIp | null {\n\tconst parts = address.split('.')\n\tif (parts.length !== 4) return null\n\tlet value = 0n\n\tfor (const part of parts) {\n\t\tif (!/^\\d{1,3}$/.test(part)) return null\n\t\tconst octet = Number(part)\n\t\tif (octet > 255) return null\n\t\tvalue = (value << 8n) | BigInt(octet)\n\t}\n\treturn { version: 4, value }\n}\n\nfunction parseIpv6(address: string): ParsedIp | null {\n\tconst zoneless = address.split('%')[0] ?? ''\n\tconst halves = zoneless.split('::')\n\tif (halves.length > 2) return null\n\tconst head = halves[0] ? halves[0].split(':') : []\n\tconst tail = halves.length === 2 && halves[1] ? halves[1].split(':') : []\n\tconst missing = 8 - head.length - tail.length\n\tif ((halves.length === 1 && missing !== 0) || missing < 0) return null\n\tconst groups = [...head, ...Array.from({ length: missing }, () => '0'), ...tail]\n\tlet value = 0n\n\tfor (const group of groups) {\n\t\tif (!/^[0-9a-f]{1,4}$/i.test(group)) return null\n\t\tvalue = (value << 16n) | BigInt(Number.parseInt(group, 16))\n\t}\n\treturn { version: 6, value }\n}\n"],"mappings":"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","names":["import_core","import_core","operations","import_core","operations","text","index","import_core","count","import_core","import_core","import_core","import_internal","index","text","import_core","import_core","operations","decision","index","count","buildServerBackup","mergeBackupOperations","parseServerBackup","restoreBackupKeyRecords","operations","import_core","import_internal","import_core","MAX_LOGICAL","import_core","merged","import_core","text","buildServerBackup","operations","mergeBackupOperations","parseServerBackup","restoreBackupKeyRecords","import_core","import_internal","import_drizzle_orm","BACKFILL_SEQUENCE_PAIRS_SQL","PRUNE_RESOLUTIONS_PAST_LOG_SQL","text","row","decision","rows","buildServerBackup","mergeBackupOperations","parseServerBackup","restoreBackupKeyRecords","import_core","import_core","import_sync","import_core","import_internal","import_sync","import_core","import_merge","import_core","import_merge","import_core","MAX_LOGICAL","violation","index","import_merge","import_core","stored","violation","import_core","import_sync","text","import_core","asRecord","import_core","scopes","import_core","import_internal","import_core","import_core","CORE_DEFAULT_MAX_OPERATION_BYTES","measureCoreOperationBytes","count","operations","resolve","text","hash","current","pending","response","stored","import_core","import_internal","import_sync","import_core","operations","count","import_core","import_sync","count","import_core","records","operations","DEFAULT_BATCH_SIZE","DEFAULT_SCHEMA_VERSION","resolve","entry","samePrincipal","operations","import_core","import_core","import_core","index","body","zlibConstants","index","resolve"]}