@powerhousedao/reactor-hypercore 6.2.3-dev.50 → 6.2.3-dev.51

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.
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ declare global {
13
13
  }
14
14
  }
15
15
  //#endregion
16
- //#region ../reactor/dist/index-CNhT69De.d.ts
16
+ //#region ../reactor/dist/index-dDm0fUBT.d.ts
17
17
  /**
18
18
  * Describes the options for paging.
19
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../node_modules/.pnpm/kysely@0.28.16/node_modules/kysely/dist/esm/kysely.d.ts","../../reactor/dist/index-CNhT69De.d.ts","../src/hypercore-operation-store.ts","../src/types.ts","../src/hypercore-atomic-transaction.ts","../src/storage-manager.ts","../src/key-encoding.ts"],"x_google_ignoreList":[0],"mappings":";;;;;;;;QAoBQ;YACM;YAEA;aACG;;;;;;;;KC4NZ;EACH;EACA;;;;;KAKG,aAAa;EAChB,SAAS;EACT,SAAS;EACT,aAAa,QAAQ,aAAa;EAClC;;;;;;KAigBG;EACH;EACA;EACA;EACA;;;;;;KAMG;EACH,SAAS;;;;;;UAmBD;;EAER,iBAAiB,YAAY;;;;;;KAM1B;;EAEH,UAAU;;EAEV;;;;;;UAMQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BR,MAAM,oBAAoB,sBAAsB,eAAe,gBAAgB,kBAAkB,KAAK,KAAK,qBAAqB,eAAe,SAAS,aAAa,YAAY,kBAAkB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;EAuB3M,SAAS,oBAAoB,eAAe,gBAAgB,kBAAkB,SAAS,iBAAiB,SAAS,eAAe,SAAS,cAAc,QAAQ,aAAa;;;;;;;;;;EAU5K,WAAW,YAAY,SAAS,eAAe,SAAS,cAAc,QAAQ,aAAa;;;;;;;;;;;;;;;;;;;;;;EAsB3F,eAAe,oBAAoB,eAAe,gBAAgB,sBAAsB,SAAS,eAAe,SAAS,cAAc,QAAQ,aAAa;;;;;;;;;;;EAW5J,aAAa,oBAAoB,gBAAgB,SAAS,cAAc,QAAQ;;;;;;;;;;EAUhF,yBAAyB,oBAAoB,eAAe,gBAAgB,SAAS,cAAc;;;;;EAKnG,iBAAiB,oBAAoB,eAAe,gBAAgB,iBAAiB,SAAS,cAAc,QAAQ;;EAEpH,mBAAmB,oBAAoB,eAAe,gBAAgB,iBAAiB,SAAS,cAAc,QAAQ;;;;;;UA2E9G;;EAER;;EAEA;;EAEA;;EAEA;;;;qBC98BW,mCAAmC;UAG1B;UAFZ;EAER,YAAoB,KAAK;EAEnB,MACJ,oBACA,sBACA,eACA,gBACA,kBACA,KAAK,KAAK,qBAAqB,eAC/B,SAAS,aACT,YAAY,kBACX,QAAQ;;UA8BG;UAoBA;;UAuGA;UAkBN;;;;;;;;;EAYF,SACJ,oBACA,eACA,gBACA,kBACA,SAAS,iBACT,SAAS,eACT,SAAS,cACR,QAAQ,aAAa;;;;;;;;;EAiGlB,WACJ,YACA,SAAS,eACT,SAAS,cACR,QAAQ,aAAa;;;;;;;EA2ElB,eACJ,oBACA,eACA,gBACA,sBACA,SAAS,eACT,SAAS,cACR,QAAQ,aAAa;EAwElB,aACJ,oBACA,gBACA,SAAS,cACR,QAAQ;;;;;;EAuCL,yBACJ,oBACA,eACA,gBACA,SAAS,cACR;EAyBG,iBACJ,oBACA,eACA,gBACA,iBACA,SAAS,cACR,QAAQ;EA6BL,mBACJ,oBACA,eACA,gBACA,iBACA,SAAS,cACR,QAAQ;UA2BH;UAiBA;;;;KC9oBE,kBAAkB;EAC5B;EACA;EACA;EACA;;KAGU;EACV;;;;qBCNW,sCAAsC;UAIvC;UACA;UACA;UACA;UANF;EAER,YACU,oBACA,sBACA,eACA;EAGV,iBAAiB,YAAY;EAY7B,iBAAiB;;;;qBCvBN;UACH;UACA;EAER,YAAY;EAIN,QAAQ;EAUR,SAAS;EAOf,UAAU;;;;qBCxBC;wBAEG,IAAI;wBAIJ,aACd,oBACA,eACA,gBACA;wBAKc,gBACd,oBACA,eACA;wBAKc,WAAW;wBAIX;wBAIA,aACd,cACA,eACA;wBAKc,QACd,oBACA,eACA;wBAKc,WAAW;qBAId;KAED;EACV;EACA;EACA;EACA;;wBAGc,kBAAkB,cAAc;KAUpC;EACV;EACA;EACA;EACA;EACA;EACA,WAAW;;KAGD;EACV;EACA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../node_modules/.pnpm/kysely@0.28.16/node_modules/kysely/dist/esm/kysely.d.ts","../../reactor/dist/index-dDm0fUBT.d.ts","../src/hypercore-operation-store.ts","../src/types.ts","../src/hypercore-atomic-transaction.ts","../src/storage-manager.ts","../src/key-encoding.ts"],"x_google_ignoreList":[0],"mappings":";;;;;;;;QAoBQ;YACM;YAEA;aACG;;;;;;;;KC0NZ;EACH;EACA;;;;;KAKG,aAAa;EAChB,SAAS;EACT,SAAS;EACT,aAAa,QAAQ,aAAa;EAClC;;;;;;KAkhBG;EACH;EACA;EACA;EACA;;;;;;KAMG;EACH,SAAS;;;;;;UAmBD;;EAER,iBAAiB,YAAY;;;;;;KAM1B;;EAEH,UAAU;;EAEV;;;;;;UAMQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BR,MAAM,oBAAoB,sBAAsB,eAAe,gBAAgB,kBAAkB,KAAK,KAAK,qBAAqB,eAAe,SAAS,aAAa,YAAY,kBAAkB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;EAuB3M,SAAS,oBAAoB,eAAe,gBAAgB,kBAAkB,SAAS,iBAAiB,SAAS,eAAe,SAAS,cAAc,QAAQ,aAAa;;;;;;;;;;EAU5K,WAAW,YAAY,SAAS,eAAe,SAAS,cAAc,QAAQ,aAAa;;;;;;;;;;;;;;;;;;;;;;EAsB3F,eAAe,oBAAoB,eAAe,gBAAgB,sBAAsB,SAAS,eAAe,SAAS,cAAc,QAAQ,aAAa;;;;;;;;;;;EAW5J,aAAa,oBAAoB,gBAAgB,SAAS,cAAc,QAAQ;;;;;;;;;;EAUhF,yBAAyB,oBAAoB,eAAe,gBAAgB,SAAS,cAAc;;;;;EAKnG,iBAAiB,oBAAoB,eAAe,gBAAgB,iBAAiB,SAAS,cAAc,QAAQ;;EAEpH,mBAAmB,oBAAoB,eAAe,gBAAgB,iBAAiB,SAAS,cAAc,QAAQ;;;;;;UA2E9G;;EAER;;EAEA;;EAEA;;EAEA;;;;qBC79BW,mCAAmC;UAG1B;UAFZ;EAER,YAAoB,KAAK;EAEnB,MACJ,oBACA,sBACA,eACA,gBACA,kBACA,KAAK,KAAK,qBAAqB,eAC/B,SAAS,aACT,YAAY,kBACX,QAAQ;;UA8BG;UAoBA;;UAuGA;UAkBN;;;;;;;;;EAYF,SACJ,oBACA,eACA,gBACA,kBACA,SAAS,iBACT,SAAS,eACT,SAAS,cACR,QAAQ,aAAa;;;;;;;;;EAiGlB,WACJ,YACA,SAAS,eACT,SAAS,cACR,QAAQ,aAAa;;;;;;;EA2ElB,eACJ,oBACA,eACA,gBACA,sBACA,SAAS,eACT,SAAS,cACR,QAAQ,aAAa;EAwElB,aACJ,oBACA,gBACA,SAAS,cACR,QAAQ;;;;;;EAuCL,yBACJ,oBACA,eACA,gBACA,SAAS,cACR;EAyBG,iBACJ,oBACA,eACA,gBACA,iBACA,SAAS,cACR,QAAQ;EA6BL,mBACJ,oBACA,eACA,gBACA,iBACA,SAAS,cACR,QAAQ;UA2BH;UAiBA;;;;KC9oBE,kBAAkB;EAC5B;EACA;EACA;EACA;;KAGU;EACV;;;;qBCNW,sCAAsC;UAIvC;UACA;UACA;UACA;UANF;EAER,YACU,oBACA,sBACA,eACA;EAGV,iBAAiB,YAAY;EAY7B,iBAAiB;;;;qBCvBN;UACH;UACA;EAER,YAAY;EAIN,QAAQ;EAUR,SAAS;EAOf,UAAU;;;;qBCxBC;wBAEG,IAAI;wBAIJ,aACd,oBACA,eACA,gBACA;wBAKc,gBACd,oBACA,eACA;wBAKc,WAAW;wBAIX;wBAIA,aACd,cACA,eACA;wBAKc,QACd,oBACA,eACA;wBAKc,WAAW;qBAId;KAED;EACV;EACA;EACA;EACA;;wBAGc,kBAAkB,cAAc;KAUpC;EACV;EACA;EACA;EACA;EACA;EACA,WAAW;;KAGD;EACV;EACA"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { DOCUMENT_SCOPE_ACTION_TYPES, isPurgeMarker } from "@powerhousedao/shared/document-model";
2
2
  import Corestore from "corestore";
3
3
  import Hyperbee from "hyperbee";
4
- //#region ../reactor/dist/forwarding-logger-ByfBFgMS.js
4
+ //#region ../reactor/dist/forwarding-logger-B9LLXItm.js
5
5
  /**
6
6
  * Error thrown when a document is not found (no operations exist for the document ID).
7
7
  */
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../reactor/dist/forwarding-logger-ByfBFgMS.js","../src/hypercore-atomic-transaction.ts","../src/key-encoding.ts","../src/hypercore-operation-store.ts","../src/storage-manager.ts"],"sourcesContent":["import { DOCUMENT_DELETED_REASON, DOCUMENT_SCOPE_ACTION_TYPES, PURGE_DOCUMENT, appendWithoutApplying, applyDeleteDocumentAction, applyDeleteDocumentAction as applyDeleteDocumentAction$1, applyUpgradeDocumentAction, applyUpgradeDocumentAction as applyUpgradeDocumentAction$1, baseReducerVersion, createDocumentState, createPresignedHeader, defaultBaseState, deriveOperationId, isDenied, isPurgeMarker, mentionedGroupIds, normalizeDocumentModelVersion, operationOutcome, purgedProtocolVersions, targetDocumentId, withProtocolVersions } from \"@powerhousedao/shared/document-model\";\nimport { v4 } from \"uuid\";\nimport { Migrator, TableNode, sql } from \"kysely\";\n//#region \\0rolldown/runtime.js\nvar __defProp = Object.defineProperty;\nvar __exportAll = (all, no_symbols) => {\n\tlet target = {};\n\tfor (var name in all) __defProp(target, name, {\n\t\tget: all[name],\n\t\tenumerable: true\n\t});\n\tif (!no_symbols) __defProp(target, Symbol.toStringTag, { value: \"Module\" });\n\treturn target;\n};\n//#endregion\n//#region src/shared/utils.ts\nfunction matchesScope(view = {}, scope) {\n\tif (view.scopes) return view.scopes.includes(scope);\n\treturn true;\n}\nfunction yieldToMain() {\n\tconst s = globalThis.scheduler;\n\tif (s?.yield) return s.yield();\n\treturn new Promise((resolve) => setTimeout(resolve, 0));\n}\nconst defaultAbortError = () => /* @__PURE__ */ new Error(\"Operation aborted\");\nfunction throwIfAborted(signal, makeError = defaultAbortError) {\n\tif (signal?.aborted) throw makeError();\n}\n/**\n* Validates PagingOptions and returns a normalized offset and limit.\n* Throws if the cursor is not empty and not a non-negative integer, or if\n* limit is less than 1. When `paging` is undefined, returns offset 0 and\n* the caller-supplied `defaultLimit`.\n*/\nfunction parsePagingOptions(paging, defaultLimit) {\n\tif (paging === void 0) return {\n\t\toffset: 0,\n\t\tlimit: defaultLimit\n\t};\n\tif (!Number.isInteger(paging.limit) || paging.limit < 1) throw new Error(`Invalid paging limit: ${String(paging.limit)} (must be an integer >= 1)`);\n\tif (paging.cursor === \"\") return {\n\t\toffset: 0,\n\t\tlimit: paging.limit\n\t};\n\tconst parsed = Number(paging.cursor);\n\tif (!Number.isInteger(parsed) || parsed < 0) throw new Error(`Invalid paging cursor: ${JSON.stringify(paging.cursor)} (must be empty or a non-negative integer)`);\n\treturn {\n\t\toffset: parsed,\n\t\tlimit: paging.limit\n\t};\n}\n//#endregion\n//#region src/events/types.ts\n/**\n* Custom error class that aggregates multiple errors from event subscribers.\n*/\nvar EventBusAggregateError = class extends Error {\n\terrors;\n\tconstructor(errors) {\n\t\tconst message = `EventBus emit failed with ${errors.length} error(s): ${errors.map((e) => {\n\t\t\tif (e && typeof e === \"object\" && \"message\" in e) return e.message;\n\t\t\treturn String(e);\n\t\t}).join(\"; \")}`;\n\t\tsuper(message);\n\t\tthis.name = \"EventBusAggregateError\";\n\t\tthis.errors = errors;\n\t}\n};\n/**\n* Event types for reactor lifecycle events.\n*/\nconst ReactorEventTypes = {\n\tJOB_PENDING: 10001,\n\tJOB_RUNNING: 10002,\n\tJOB_WRITE_READY: 10003,\n\tJOB_READ_READY: 10004,\n\tJOB_FAILED: 10005,\n\tREADMODEL_BATCH_COMPLETED: 10006,\n\tREADMODEL_INDEXED: 10007,\n\tMODEL_LOADED: 10008,\n\tSIGNATURE_REFUSED: 10009,\n\tCATCHUP_SWEPT: 10010\n};\n//#endregion\n//#region src/shared/errors.ts\n/**\n* Error thrown when attempting to access a deleted document.\n*/\nvar DocumentDeletedError = class DocumentDeletedError extends Error {\n\tdocumentId;\n\tdeletedAtUtcIso;\n\tconstructor(documentId, deletedAtUtcIso = null) {\n\t\tconst message = deletedAtUtcIso ? `Document ${documentId} was deleted at ${deletedAtUtcIso}` : `Document ${documentId} has been deleted`;\n\t\tsuper(message);\n\t\tthis.name = \"DocumentDeletedError\";\n\t\tthis.documentId = documentId;\n\t\tthis.deletedAtUtcIso = deletedAtUtcIso;\n\t\tError.captureStackTrace(this, DocumentDeletedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentDeletedError\";\n\t}\n};\n/**\n* Error thrown when the auth policy denies an action at the executor gate.\n*/\nvar AuthorizationDeniedError = class AuthorizationDeniedError extends Error {\n\tdocumentId;\n\tscope;\n\toperation;\n\tsubject;\n\tconstructor(documentId, scope, operation, subject) {\n\t\tsuper(`Authorization denied: ${subject ?? \"anonymous\"} may not execute ${operation} in scope \"${scope}\" of document ${documentId}`);\n\t\tthis.name = \"AuthorizationDeniedError\";\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.operation = operation;\n\t\tthis.subject = subject;\n\t\tError.captureStackTrace(this, AuthorizationDeniedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AuthorizationDeniedError\";\n\t}\n};\n/**\n* An auth operation did not strictly exceed the newest timestamp in its stream.\n*\n* Terminal and asymmetric by design: no ordering rule can reconcile two replicas\n* that each accepted an auth operation offline, because either order hands one\n* authority the other never granted, so the replica ahead holds the arrival.\n*/\nvar AuthTimestampNotMonotonicError = class AuthTimestampNotMonotonicError extends Error {\n\tdocumentId;\n\tbranch;\n\ttimestampUtcMs;\n\tnewestTimestampUtcMs;\n\tconstructor(documentId, branch, timestampUtcMs, newestTimestampUtcMs) {\n\t\tsuper(`Auth timestamp not monotonic: ${timestampUtcMs} does not exceed ${newestTimestampUtcMs} in the auth stream of document ${documentId} on branch ${branch}`);\n\t\tthis.name = \"AuthTimestampNotMonotonicError\";\n\t\tthis.documentId = documentId;\n\t\tthis.branch = branch;\n\t\tthis.timestampUtcMs = timestampUtcMs;\n\t\tthis.newestTimestampUtcMs = newestTimestampUtcMs;\n\t\tError.captureStackTrace(this, AuthTimestampNotMonotonicError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AuthTimestampNotMonotonicError\";\n\t}\n};\n/**\n* An operation or action carried a timestamp that is not an ISO-8601 UTC\n* instant.\n*\n* Terminal rather than retryable: the value does not change between attempts,\n* so a retry re-runs the whole job to fail identically. Quarantining, unlike a\n* held auth operation — this is malformed data rather than two replicas\n* disagreeing, and nothing further from that source should be trusted until it\n* is looked at.\n*/\nvar InvalidOperationTimestampError = class InvalidOperationTimestampError extends Error {\n\tdocumentId;\n\tscope;\n\ttimestampUtcMs;\n\tconstructor(documentId, scope, timestampUtcMs, context) {\n\t\tsuper(`Invalid timestamp \"${timestampUtcMs}\" on ${context} in scope \"${scope}\" of document ${documentId}`);\n\t\tthis.name = \"InvalidOperationTimestampError\";\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.timestampUtcMs = timestampUtcMs;\n\t\tError.captureStackTrace(this, InvalidOperationTimestampError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"InvalidOperationTimestampError\";\n\t}\n};\n/** A document requires a protocol version this reactor does not run. Terminal. */\nvar UnsupportedProtocolVersionError = class UnsupportedProtocolVersionError extends Error {\n\tdocumentId;\n\tprotocol;\n\tversion;\n\tconstructor(documentId, protocol, version) {\n\t\tsuper(`Document ${documentId} requires ${protocol} ${version}, which this reactor does not support`);\n\t\tthis.name = \"UnsupportedProtocolVersionError\";\n\t\tthis.documentId = documentId;\n\t\tthis.protocol = protocol;\n\t\tthis.version = version;\n\t\tError.captureStackTrace(this, UnsupportedProtocolVersionError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"UnsupportedProtocolVersionError\";\n\t}\n};\n/**\n* A load would move more operations than the bound allows, indicating a real\n* divergence between local and incoming history. Counts only first-time moves,\n* so a re-evaluation pass's re-appends do not make busy documents\n* revocation-proof. Terminal: the condition is deterministic.\n*/\nvar ExcessiveReshuffleError = class ExcessiveReshuffleError extends Error {\n\tdocumentId;\n\tscope;\n\tcount;\n\tthreshold;\n\tconstructor(documentId, scope, count, threshold) {\n\t\tsuper(`Excessive reshuffle detected: ${count} operations in scope \"${scope}\" of document ${documentId} exceeds the threshold of ${threshold}. This indicates a significant divergence between local and incoming operations.`);\n\t\tthis.name = \"ExcessiveReshuffleError\";\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.count = count;\n\t\tthis.threshold = threshold;\n\t\tError.captureStackTrace(this, ExcessiveReshuffleError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"ExcessiveReshuffleError\";\n\t}\n};\n/** The message carries the code: only name and message cross the queue. */\nvar InvalidSignatureError = class InvalidSignatureError extends Error {\n\tdocumentId;\n\tcode;\n\treason;\n\tconstructor(documentId, code, reason) {\n\t\tsuper(`Invalid signature in document ${documentId} [${code}]: ${reason}`);\n\t\tthis.name = \"InvalidSignatureError\";\n\t\tthis.documentId = documentId;\n\t\tthis.code = code;\n\t\tthis.reason = reason;\n\t\tError.captureStackTrace(this, InvalidSignatureError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"InvalidSignatureError\";\n\t}\n};\n/**\n* An UPGRADE_DOCUMENT action's preconditions (fromVersion and the per-scope\n* revision snapshot) did not match the document state the executor loaded.\n*\n* Terminal rather than retryable: the action carries the client's snapshot,\n* which stays stale no matter how often the job re-runs. The client is\n* expected to re-read the document and submit a fresh action instead.\n*/\nvar UpgradePreconditionFailedError = class UpgradePreconditionFailedError extends Error {\n\tdocumentId;\n\tdetail;\n\tconstructor(documentId, detail) {\n\t\tsuper(`Upgrade precondition failed for document ${documentId}: ${detail}`);\n\t\tthis.name = \"UpgradePreconditionFailedError\";\n\t\tthis.documentId = documentId;\n\t\tthis.detail = detail;\n\t\tError.captureStackTrace(this, UpgradePreconditionFailedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"UpgradePreconditionFailedError\";\n\t}\n};\n/**\n* Error thrown when a document is not found (no operations exist for the document ID).\n*/\nvar DocumentNotFoundError = class DocumentNotFoundError extends Error {\n\tdocumentId;\n\t/**\n\t* @param message Overrides the default text. A handler that knows which of\n\t* several documents an action reads - a relationship's source, say - says so\n\t* here rather than rewrapping in a bare Error, which would strip the name the\n\t* executor classifies by.\n\t*/\n\tconstructor(documentId, message) {\n\t\tsuper(message ?? `Document ${documentId} not found`);\n\t\tthis.name = \"DocumentNotFoundError\";\n\t\tthis.documentId = documentId;\n\t\tError.captureStackTrace(this, DocumentNotFoundError);\n\t}\n\t/** Also true for DocumentPurgedError: only the name crosses the queue. */\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && (error.name === \"DocumentNotFoundError\" || error.name === \"DocumentPurgedError\");\n\t}\n};\n/** The document was purged; readers treat it as absent. Terminal. */\nvar DocumentPurgedError = class DocumentPurgedError extends DocumentNotFoundError {\n\tpurged = true;\n\tconstructor(documentId, message) {\n\t\tsuper(documentId, message ?? `Document ${documentId} was purged`);\n\t\tthis.name = \"DocumentPurgedError\";\n\t\tError.captureStackTrace(this, DocumentPurgedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentPurgedError\";\n\t}\n};\n/** A purge was asked for a document that is not deleted. Terminal. */\nvar DocumentNotDeletedError = class DocumentNotDeletedError extends Error {\n\tdocumentId;\n\tconstructor(documentId, message) {\n\t\tsuper(message ?? `Document ${documentId} is not deleted`);\n\t\tthis.name = \"DocumentNotDeletedError\";\n\t\tthis.documentId = documentId;\n\t\tError.captureStackTrace(this, DocumentNotDeletedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentNotDeletedError\";\n\t}\n};\n/** A surviving document's accepted auth history names the group. Terminal. */\nvar GroupInUseError = class GroupInUseError extends Error {\n\tgroupId;\n\treferencingDocumentIds;\n\tconstructor(groupId, referencingDocumentIds) {\n\t\tsuper(`Group ${groupId} cannot be purged: the auth history of ${referencingDocumentIds.join(\", \")} names it`);\n\t\tthis.name = \"GroupInUseError\";\n\t\tthis.groupId = groupId;\n\t\tthis.referencingDocumentIds = referencingDocumentIds;\n\t\tError.captureStackTrace(this, GroupInUseError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"GroupInUseError\";\n\t}\n};\n/** A purge above maxPurgeOperations without allowLarge. Terminal. */\nvar PurgeTooLargeError = class PurgeTooLargeError extends Error {\n\tdocumentId;\n\toperationCount;\n\tmaxPurgeOperations;\n\tconstructor(documentId, operationCount, maxPurgeOperations) {\n\t\tsuper(`Document ${documentId} has ${operationCount} operations, above the purge limit of ${maxPurgeOperations}; request it with allowLarge`);\n\t\tthis.name = \"PurgeTooLargeError\";\n\t\tthis.documentId = documentId;\n\t\tthis.operationCount = operationCount;\n\t\tthis.maxPurgeOperations = maxPurgeOperations;\n\t\tError.captureStackTrace(this, PurgeTooLargeError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"PurgeTooLargeError\";\n\t}\n};\n/** A regular write carried an action type only the reactor issues. Terminal. */\nvar ReservedActionError = class ReservedActionError extends Error {\n\tdocumentId;\n\tactionType;\n\tconstructor(documentId, actionType) {\n\t\tsuper(`Action ${actionType} is reserved and cannot be submitted to document ${documentId}`);\n\t\tthis.name = \"ReservedActionError\";\n\t\tthis.documentId = documentId;\n\t\tthis.actionType = actionType;\n\t\tError.captureStackTrace(this, ReservedActionError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"ReservedActionError\";\n\t}\n};\n/**\n* An authorization preflight was asked for while the reactor's decision model\n* is off, so there is no model to answer from.\n*\n* Thrown rather than answered from the legacy host-side permission tables. The\n* two systems do not compose: the tables record which addresses a host lets\n* near a drive, the policy records what a document's own grants permit, and an\n* answer stitched from both would report an admission verdict neither system\n* would reach. A caller that cannot get a prediction disables nothing, which\n* leaves the submit path -- and its real gate -- as the only authority.\n*\n* Detection is by `name`, not `instanceof`: the SharedWorker RPC boundary\n* rebuilds a thrown error from `{ name, message, stack, cause }` alone\n* (`reactor-browser/src/rpc/error-info.ts`), so the class identity and any\n* custom field are lost in transit. This error therefore carries no fields.\n*/\nvar AuthEnforcementDisabledError = class AuthEnforcementDisabledError extends Error {\n\tconstructor() {\n\t\tsuper(\"Authorization evaluation requires the authEnforcement feature flag; this reactor holds no decision model, and the legacy host-table permission system cannot answer for one\");\n\t\tthis.name = \"AuthEnforcementDisabledError\";\n\t\tError.captureStackTrace(this, AuthEnforcementDisabledError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AuthEnforcementDisabledError\";\n\t}\n};\n/**\n* Error thrown when a relationship edge an operation names does not exist.\n*\n* Detection is by `name`, not `instanceof`: the SharedWorker RPC boundary\n* rebuilds a thrown error from `{ name, message, stack, cause }` alone\n* (`reactor-browser/src/rpc/error-info.ts`), so the class identity is lost in\n* transit.\n*/\nvar RelationshipNotFoundError = class RelationshipNotFoundError extends Error {\n\tsourceId;\n\ttargetId;\n\trelationshipType;\n\tconstructor(sourceId, targetId, relationshipType) {\n\t\tsuper(`No ${relationshipType} relationship from ${sourceId} to ${targetId}`);\n\t\tthis.name = \"RelationshipNotFoundError\";\n\t\tthis.sourceId = sourceId;\n\t\tthis.targetId = targetId;\n\t\tthis.relationshipType = relationshipType;\n\t\tError.captureStackTrace(this, RelationshipNotFoundError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"RelationshipNotFoundError\";\n\t}\n};\n/** The store holds documents at protocol versions this reactor does not run. */\nvar UnsupportedStoredProtocolError = class UnsupportedStoredProtocolError extends Error {\n\tversions;\n\tdocuments;\n\tconstructor(versions, documents) {\n\t\tconst named = versions.map(({ protocol, version }) => `${protocol} ${version}`).join(\", \");\n\t\tsuper(`${documents} stored document(s) require ${named}, which this reactor does not run. Start a build that runs them, or accept them read-only with withUnsupportedStoredDocuments(\"read-only\")`);\n\t\tthis.name = \"UnsupportedStoredProtocolError\";\n\t\tthis.versions = versions;\n\t\tthis.documents = documents;\n\t\tError.captureStackTrace(this, UnsupportedStoredProtocolError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"UnsupportedStoredProtocolError\";\n\t}\n};\n/**\n* A batch job failed. A batch is not atomic, so `jobs` holds every job's final\n* state, keyed by plan key; `cause` carries the failed job's own error name.\n*\n* The SharedWorker RPC boundary rebuilds a thrown error from `{ name, message,\n* stack, cause }` alone (`src/rpc/error-info.ts`), so `key` and\n* `jobs` do not survive it. `isError` therefore checks for them, not only the\n* name; across that boundary, classify by the `cause` chain's names instead.\n*/\nvar BatchJobFailedError = class BatchJobFailedError extends Error {\n\tkey;\n\tjobs;\n\tconstructor(key, jobs) {\n\t\tconst failure = jobs[key].error;\n\t\tconst cause = new Error(failure?.message ?? \"Job failed\");\n\t\tcause.name = failure?.name ?? \"Error\";\n\t\tsuper(failure?.message ?? \"Job failed\", { cause });\n\t\tthis.name = \"BatchJobFailedError\";\n\t\tthis.key = key;\n\t\tthis.jobs = jobs;\n\t\tError.captureStackTrace(this, BatchJobFailedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"BatchJobFailedError\" && typeof error.key === \"string\" && typeof error.jobs === \"object\";\n\t}\n};\n//#endregion\n//#region src/storage/interfaces.ts\n/**\n* Thrown when an operation with the same identity already exists in the store.\n*/\nvar DuplicateOperationError = class extends Error {\n\tconstructor(description) {\n\t\tsuper(`Duplicate operation: ${description}`);\n\t\tthis.name = \"DuplicateOperationError\";\n\t}\n};\n/**\n* Thrown when a concurrent write conflict is detected during an atomic apply.\n*/\nvar OptimisticLockError = class extends Error {\n\tconstructor(message) {\n\t\tsuper(message);\n\t\tthis.name = \"OptimisticLockError\";\n\t}\n};\n/**\n* Thrown when the caller-provided revision does not match the current\n* stored revision, indicating a stale read.\n*/\nvar RevisionMismatchError = class extends Error {\n\tconstructor(expected, actual) {\n\t\tsuper(`Revision mismatch: expected ${expected}, got ${actual}`);\n\t\tthis.name = \"RevisionMismatchError\";\n\t}\n};\n/**\n* A create based on an empty stream that already has operations: the id is\n* taken, and no retry can resolve it. Matched by `name`, all the RPC boundary keeps.\n*/\nvar DocumentAlreadyExistsError = class extends Error {\n\tdocumentId;\n\tconstructor(documentId, scope, headRevision) {\n\t\tsuper(`Document ${documentId} already exists: create requested revision 0 but the \"${scope}\" stream is at revision ${headRevision}`);\n\t\tthis.name = \"DocumentAlreadyExistsError\";\n\t\tthis.documentId = documentId;\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentAlreadyExistsError\";\n\t}\n};\n/** Error history keeps messages, not classes, so failures match by prefix. */\nconst APPEND_CONDITION_FAILED_PREFIX = \"Append condition failed: \";\n/**\n* A read-set stream grew before the append committed. A concurrency\n* conflict, not a fault: the caller retries against the new stream heads.\n*/\nvar AppendConditionFailedError = class extends Error {\n\tcondition;\n\tconstructor(condition) {\n\t\tconst streams = condition.streams.map((s) => `${s.documentId}:${s.scope}:${s.branch}@${s.revision}`).join(\", \");\n\t\tsuper(`${APPEND_CONDITION_FAILED_PREFIX}a read-set stream advanced [${streams}]`);\n\t\tthis.condition = condition;\n\t\tthis.name = \"AppendConditionFailedError\";\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AppendConditionFailedError\";\n\t}\n\t/** True when a recorded error message is an append-condition failure. */\n\tstatic isFailureMessage(message) {\n\t\treturn message.startsWith(APPEND_CONDITION_FAILED_PREFIX);\n\t}\n};\n/**\n* Which sense of \"exists\" a caller of {@link IDocumentView.exists} means.\n*/\nlet DocumentExistence = /* @__PURE__ */ function(DocumentExistence) {\n\t/**\n\t* A document that is present and not deleted. This is the question a read\n\t* asks: a deleted document is not readable, so it does not exist.\n\t*/\n\tDocumentExistence[\"LiveOnly\"] = \"LiveOnly\";\n\t/**\n\t* Whether the id is taken, deleted or not. This is the question a write\n\t* asks: a deleted document keeps its operation stream, so its id can never\n\t* be reused, and answering from snapshots alone would say otherwise whenever\n\t* a snapshot row is missing while the stream is intact.\n\t*/\n\tDocumentExistence[\"IncludingDeleted\"] = \"IncludingDeleted\";\n\treturn DocumentExistence;\n}({});\n//#endregion\n//#region src/executor/util.ts\n/** Actions the reactor reduces itself, onto the document scope. */\nconst DOCUMENT_SCOPE_ACTIONS = DOCUMENT_SCOPE_ACTION_TYPES;\n/**\n* `CREATE_DOCUMENT` is exempt by necessity: it runs before the document exists,\n* so building a decision model would throw and defer the job forever.\n*/\nconst GATED_DOCUMENT_ACTIONS = new Set([...DOCUMENT_SCOPE_ACTIONS].filter((type) => type !== \"CREATE_DOCUMENT\"));\n/**\n* Creates a PHDocument from a CREATE_DOCUMENT action input.\n* Reconstructs the document header and initializes the base state.\n*\n* @param action - The CREATE_DOCUMENT action containing the document parameters\n* @returns A newly constructed PHDocument with initialized header and base state\n*/\nfunction createDocumentFromAction(action) {\n\tconst input = action.input;\n\tconst header = createPresignedHeader();\n\theader.id = input.documentId;\n\theader.documentType = input.model;\n\tif (input.signing) {\n\t\theader.createdAtUtcIso = input.signing.createdAtUtcIso;\n\t\theader.lastModifiedAtUtcIso = input.signing.createdAtUtcIso;\n\t\theader.sig = {\n\t\t\tpublicKey: input.signing.publicKey,\n\t\t\tnonce: input.signing.nonce\n\t\t};\n\t}\n\tif (input.slug !== void 0) header.slug = input.slug;\n\tif (!header.slug) header.slug = input.documentId;\n\tif (input.name !== void 0) header.name = input.name;\n\tif (input.branch !== void 0) header.branch = input.branch;\n\tif (input.meta !== void 0) header.meta = input.meta;\n\tif (input.protocolVersions !== void 0) header.protocolVersions = input.protocolVersions;\n\tconst baseState = defaultBaseState();\n\treturn {\n\t\theader,\n\t\toperations: {},\n\t\tstate: baseState,\n\t\tinitialState: baseState,\n\t\tclipboard: []\n\t};\n}\n/**\n* Calculate the next operation index for a specific scope.\n* Each scope maintains its own independent index sequence.\n*\n* Per-scope indexing means:\n* - Each scope (document, global, local, etc.) has independent indexes\n* - Indexes start at 0 for each scope\n* - Different scopes can have operations with the same index value\n*\n* This function uses header.revision which is populated by the cache/storage layer\n* and contains the next available index for each scope. This design avoids requiring\n* the full operation history to be loaded, which is crucial for snapshot-based caching.\n*\n* @param document - The document whose header.revision to inspect\n* @param scope - The scope to calculate the next index for\n* @returns The next available index in the specified scope\n*/\nconst getNextIndexForScope = (document, scope) => {\n\treturn document.header.revision[scope] || 0;\n};\n/**\n* Creates an empty consistency token with no coordinates.\n* Used when a job is registered or fails without writing operations.\n*\n* @returns A consistency token with an empty coordinates array\n*/\nfunction createEmptyConsistencyToken() {\n\treturn {\n\t\tversion: 1,\n\t\tcreatedAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tcoordinates: []\n\t};\n}\n/**\n* Creates a consistency token from operations written during job execution.\n* Maps each operation to a consistency coordinate tracking (documentId, scope, branch, operationIndex).\n* If no operations are provided, returns an empty token.\n*\n* @param operationsWithContext - Array of operations with their execution context\n* @returns A consistency token representing all operations written\n*/\nfunction createConsistencyToken(operationsWithContext) {\n\tif (operationsWithContext.length === 0) return createEmptyConsistencyToken();\n\tconst coordinates = [];\n\tfor (let i = 0; i < operationsWithContext.length; i++) {\n\t\tconst opWithContext = operationsWithContext[i];\n\t\tcoordinates.push({\n\t\t\tdocumentId: opWithContext.context.documentId,\n\t\t\tscope: opWithContext.context.scope,\n\t\t\tbranch: opWithContext.context.branch,\n\t\t\toperationIndex: opWithContext.operation.index\n\t\t});\n\t}\n\treturn {\n\t\tversion: 1,\n\t\tcreatedAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tcoordinates\n\t};\n}\nfunction createOperation(action, index, skip, context) {\n\treturn {\n\t\tid: deriveOperationId(context.documentId, context.scope, context.branch, action.id),\n\t\tindex,\n\t\ttimestampUtcMs: action.timestampUtcMs || (/* @__PURE__ */ new Date()).toISOString(),\n\t\thash: \"\",\n\t\tskip,\n\t\taction\n\t};\n}\nfunction updateDocumentRevision(document, scope, operationIndex) {\n\tdocument.header.revision = {\n\t\t...document.header.revision,\n\t\t[scope]: operationIndex + 1\n\t};\n}\nfunction buildSuccessResult(job, operation, documentId, documentType, resultingState, startTime) {\n\treturn {\n\t\tjob,\n\t\tsuccess: true,\n\t\toperations: [operation],\n\t\toperationsWithContext: [{\n\t\t\toperation,\n\t\t\tcontext: {\n\t\t\t\tdocumentId,\n\t\t\t\tscope: job.scope,\n\t\t\t\tbranch: job.branch,\n\t\t\t\tdocumentType,\n\t\t\t\tresultingState,\n\t\t\t\tordinal: 0\n\t\t\t}\n\t\t}],\n\t\tduration: Date.now() - startTime\n\t};\n}\nfunction buildErrorResult(job, error, startTime) {\n\treturn {\n\t\tjob,\n\t\tsuccess: false,\n\t\terror,\n\t\tduration: Date.now() - startTime\n\t};\n}\n/**\n* The error a refusal surfaces as. Both classes are already terminal in the job\n* result handler, so a refusal never burns a retry.\n*/\nfunction refusalError(reason, documentId, deletedAtUtcIso, action) {\n\tif (reason === DOCUMENT_DELETED_REASON) return new DocumentDeletedError(documentId, deletedAtUtcIso);\n\treturn new AuthorizationDeniedError(documentId, action.scope, action.type, action.context?.signer?.user.address);\n}\n/**\n* Whether this operation is part of the document's creation. The create and the\n* upgrade from version zero hold the first two indexes for the life of the\n* document, so a reshuffle has to leave them where they are.\n*/\nfunction isGenesisOperation(operation) {\n\tif (operation.action.type === \"CREATE_DOCUMENT\") return true;\n\tif (operation.action.type !== \"UPGRADE_DOCUMENT\") return false;\n\treturn operation.action.input.fromVersion === 0;\n}\n/**\n* The distinct streams a job wrote, collected so a rollback knows what to evict.\n*\n* A write records its stream on every apply, and a long run applies the same\n* stream hundreds of times, so this keeps one entry per stream rather than one\n* per write: the eviction only cares which streams were touched, and the\n* successful jobs that never read this back pay for a lookup instead of an\n* allocation.\n*/\nvar TouchedStreams = class {\n\tstreams = /* @__PURE__ */ new Map();\n\tadd(documentId, scope, branch) {\n\t\tconst key = `${documentId}\\u0000${scope}\\u0000${branch}`;\n\t\tif (this.streams.has(key)) return;\n\t\tthis.streams.set(key, {\n\t\t\tdocumentId,\n\t\t\tscope,\n\t\t\tbranch\n\t\t});\n\t}\n\t[Symbol.iterator]() {\n\t\treturn this.streams.values();\n\t}\n};\n/**\n* The ids of the actions the caller handed to a job. Load and reevaluation\n* jobs write operations nobody submitted, so they report none.\n*/\nfunction submittedActionIds(job) {\n\treturn job.kind === \"mutation\" ? job.actions.map((action) => action.id) : [];\n}\n/**\n* Reports what became of each submitted action.\n*\n* A job's operations can include ones it only moved to a new index, so only\n* those carrying a submitted action are reported. Returns undefined when the\n* job submitted nothing, which keeps `JobInfo.result` null for the jobs that\n* have no caller to answer to.\n*/\nfunction summarizeSubmittedActions(operations, submitted) {\n\tif (!submitted || submitted.length === 0) return;\n\tconst ids = new Set(submitted);\n\tconst actions = [];\n\tfor (const { operation, context } of operations) {\n\t\tif (!ids.has(operation.action.id)) continue;\n\t\tactions.push({\n\t\t\tactionId: operation.action.id,\n\t\t\tscope: context.scope,\n\t\t\tindex: operation.index,\n\t\t\t...operationOutcome(operation)\n\t\t});\n\t}\n\tif (actions.length === 0) return;\n\treturn {\n\t\tactions,\n\t\tallApplied: actions.every((action) => action.kind === \"applied\")\n\t};\n}\n/** Tombstones a job has read, each under the shared lock it took first. */\nvar PurgeFence = class {\n\tlocks;\n\tchecked;\n\tpurged;\n\tconstructor(locks, checked, purged) {\n\t\tthis.locks = locks;\n\t\tthis.checked = checked;\n\t\tthis.purged = purged;\n\t}\n\t/** Locks and reads an id the job start did not resolve. */\n\tasync isPurged(documentId) {\n\t\tawait this.isPurgedMany([documentId]);\n\t\treturn this.purged.has(documentId);\n\t}\n\t/** Locks and reads the unresolved ids in one lock and one lookup. */\n\tasync isPurgedMany(documentIds) {\n\t\tconst unchecked = [...new Set(documentIds)].filter((id) => !this.checked.has(id));\n\t\tif (unchecked.length > 0) {\n\t\t\tawait this.locks.shared(unchecked);\n\t\t\tconst found = await this.locks.purged(unchecked);\n\t\t\tfor (const id of unchecked) this.checked.add(id);\n\t\t\tfor (const id of found) this.purged.add(id);\n\t\t}\n\t\treturn new Set(documentIds.filter((id) => this.purged.has(id)));\n\t}\n};\n/** Locks and checks an id on its first read; a purged id reads as purged. */\nvar FencedWriteCache = class {\n\tinner;\n\tpurgeFence;\n\tevict;\n\tevicted = /* @__PURE__ */ new Set();\n\tconstructor(inner, purgeFence, evict) {\n\t\tthis.inner = inner;\n\t\tthis.purgeFence = purgeFence;\n\t\tthis.evict = evict;\n\t}\n\t/** Fences ids known before their reads in one round trip. */\n\tasync fence(documentIds) {\n\t\tawait this.purgeFence.isPurgedMany(documentIds);\n\t}\n\tasync getState(documentId, scope, branch, targetRevision, signal) {\n\t\tif (await this.purgeFence.isPurged(documentId)) {\n\t\t\tif (!this.evicted.has(documentId)) {\n\t\t\t\tthis.evicted.add(documentId);\n\t\t\t\tthis.evict(documentId);\n\t\t\t}\n\t\t\tthrow new DocumentPurgedError(documentId);\n\t\t}\n\t\treturn this.inner.getState(documentId, scope, branch, targetRevision, signal);\n\t}\n\tputState(documentId, scope, branch, revision, document, position) {\n\t\tthis.inner.putState(documentId, scope, branch, revision, document, position);\n\t}\n\tputRun(documentId, scope, branch, run) {\n\t\tthis.inner.putRun(documentId, scope, branch, run);\n\t}\n\tinvalidate(documentId, scope, branch) {\n\t\treturn this.inner.invalidate(documentId, scope, branch);\n\t}\n\tclear() {\n\t\tthis.inner.clear();\n\t}\n\tstartup() {\n\t\treturn this.inner.startup();\n\t}\n\tshutdown() {\n\t\treturn this.inner.shutdown();\n\t}\n};\n/** The target whose membership an ADD or REMOVE_RELATIONSHIP writes. */\nfunction relationshipTarget(action) {\n\tif (action.type !== \"ADD_RELATIONSHIP\" && action.type !== \"REMOVE_RELATIONSHIP\") return;\n\tconst target = action.input?.targetId;\n\treturn typeof target === \"string\" && target.length > 0 ? target : void 0;\n}\n/** The ids a job's locks cover, sorted: its write ids and groups it names. */\nfunction jobWriteIds(job) {\n\tconst ids = /* @__PURE__ */ new Set([job.documentId]);\n\tconst actions = [...job.actions, ...job.operations.map((operation) => operation.action)];\n\tfor (const action of actions) {\n\t\tif (DOCUMENT_SCOPE_ACTIONS.has(action.type)) ids.add(targetDocumentId(action, job.documentId));\n\t\tconst target = relationshipTarget(action);\n\t\tif (target !== void 0) ids.add(target);\n\t\tif (action.scope === \"auth\") for (const groupId of mentionedGroupIds(action)) ids.add(groupId);\n\t}\n\treturn [...ids].sort();\n}\n//#endregion\n//#region src/cache/collection-membership-cache.ts\nvar CollectionMembershipCache = class CollectionMembershipCache {\n\toperationIndex;\n\tcache = /* @__PURE__ */ new Map();\n\tconstructor(operationIndex) {\n\t\tthis.operationIndex = operationIndex;\n\t}\n\twithScopedIndex(operationIndex) {\n\t\tconst scoped = new CollectionMembershipCache(operationIndex);\n\t\tscoped.cache = this.cache;\n\t\treturn scoped;\n\t}\n\tasync getCollectionsForDocuments(documentIds) {\n\t\tconst result = {};\n\t\tconst missing = [];\n\t\tfor (const docId of documentIds) {\n\t\t\tconst cached = this.cache.get(docId);\n\t\t\tif (cached !== void 0) result[docId] = cached;\n\t\t\telse missing.push(docId);\n\t\t}\n\t\tif (missing.length > 0) {\n\t\t\tconst fromDb = await this.operationIndex.getCollectionsForDocuments(missing);\n\t\t\tfor (const docId of missing) {\n\t\t\t\tconst collections = fromDb[docId] ?? [];\n\t\t\t\tresult[docId] = collections;\n\t\t\t\tthis.cache.set(docId, collections);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\tinvalidate(documentId) {\n\t\tthis.cache.delete(documentId);\n\t}\n};\n//#endregion\n//#region src/cache/lru/lru-tracker.ts\nvar LRUNode = class {\n\tkey;\n\tprev;\n\tnext;\n\tconstructor(key) {\n\t\tthis.key = key;\n\t\tthis.prev = void 0;\n\t\tthis.next = void 0;\n\t}\n};\nvar LRUTracker = class {\n\tmap;\n\thead;\n\ttail;\n\tconstructor() {\n\t\tthis.map = /* @__PURE__ */ new Map();\n\t\tthis.head = void 0;\n\t\tthis.tail = void 0;\n\t}\n\tget size() {\n\t\treturn this.map.size;\n\t}\n\ttouch(key) {\n\t\tconst node = this.map.get(key);\n\t\tif (node) this.moveToFront(node);\n\t\telse this.addToFront(key);\n\t}\n\tevict() {\n\t\tif (!this.tail) return;\n\t\tconst key = this.tail.key;\n\t\tthis.remove(key);\n\t\treturn key;\n\t}\n\tremove(key) {\n\t\tconst node = this.map.get(key);\n\t\tif (!node) return;\n\t\tthis.removeNode(node);\n\t\tthis.map.delete(key);\n\t}\n\tclear() {\n\t\tthis.map.clear();\n\t\tthis.head = void 0;\n\t\tthis.tail = void 0;\n\t}\n\taddToFront(key) {\n\t\tconst node = new LRUNode(key);\n\t\tthis.map.set(key, node);\n\t\tif (!this.head) {\n\t\t\tthis.head = node;\n\t\t\tthis.tail = node;\n\t\t} else {\n\t\t\tnode.next = this.head;\n\t\t\tthis.head.prev = node;\n\t\t\tthis.head = node;\n\t\t}\n\t}\n\tmoveToFront(node) {\n\t\tif (node === this.head) return;\n\t\tthis.removeNode(node);\n\t\tnode.prev = void 0;\n\t\tnode.next = this.head;\n\t\tif (this.head) this.head.prev = node;\n\t\tthis.head = node;\n\t\tif (!this.tail) this.tail = node;\n\t}\n\tremoveNode(node) {\n\t\tif (node.prev) node.prev.next = node.next;\n\t\telse this.head = node.next;\n\t\tif (node.next) node.next.prev = node.prev;\n\t\telse this.tail = node.prev;\n\t}\n};\n//#endregion\n//#region src/cache/document-meta-cache.ts\n/**\n* In-memory document metadata cache with LRU eviction.\n*\n* Caches PHDocumentState per (documentId, branch) key. On cache miss,\n* rebuilds from document scope operations. Provides an explicit cross-scope\n* contract for accessing document scope metadata.\n*\n* **Thread Safety:**\n* Not thread-safe. Designed for single-threaded job executor environment.\n*/\nvar DocumentMetaCache = class DocumentMetaCache {\n\tcache;\n\tlruTracker;\n\toperationStore;\n\tconfig;\n\tconstructor(operationStore, config) {\n\t\tthis.operationStore = operationStore;\n\t\tthis.config = { maxDocuments: config.maxDocuments };\n\t\tthis.cache = /* @__PURE__ */ new Map();\n\t\tthis.lruTracker = new LRUTracker();\n\t}\n\twithScopedStore(operationStore) {\n\t\tconst scoped = new DocumentMetaCache(operationStore, this.config);\n\t\tscoped.cache = this.cache;\n\t\tscoped.lruTracker = this.lruTracker;\n\t\treturn scoped;\n\t}\n\tasync startup() {\n\t\treturn Promise.resolve();\n\t}\n\tasync shutdown() {\n\t\treturn Promise.resolve();\n\t}\n\tasync getDocumentMeta(documentId, branch, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst key = this.makeKey(documentId, branch);\n\t\tconst cached = this.cache.get(key);\n\t\tif (cached) {\n\t\t\tthis.lruTracker.touch(key);\n\t\t\treturn cached;\n\t\t}\n\t\tconst meta = await this.rebuildLatest(documentId, branch, signal);\n\t\tthis.putDocumentMeta(documentId, branch, meta);\n\t\treturn meta;\n\t}\n\tasync rebuildAtRevision(documentId, branch, targetRevision, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\treturn this.rebuildFromOperations(documentId, branch, targetRevision, signal);\n\t}\n\tputDocumentMeta(documentId, branch, meta) {\n\t\tconst key = this.makeKey(documentId, branch);\n\t\tif (!this.cache.has(key) && this.cache.size >= this.config.maxDocuments) {\n\t\t\tconst evictKey = this.lruTracker.evict();\n\t\t\tif (evictKey) this.cache.delete(evictKey);\n\t\t}\n\t\tthis.cache.set(key, structuredClone(meta));\n\t\tthis.lruTracker.touch(key);\n\t}\n\tinvalidate(documentId, branch) {\n\t\tlet evicted = 0;\n\t\tif (branch === void 0) {\n\t\t\tfor (const key of this.cache.keys()) if (key.startsWith(`${documentId}:`)) {\n\t\t\t\tthis.cache.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t} else {\n\t\t\tconst key = this.makeKey(documentId, branch);\n\t\t\tif (this.cache.has(key)) {\n\t\t\t\tthis.cache.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted = 1;\n\t\t\t}\n\t\t}\n\t\treturn evicted;\n\t}\n\tclear() {\n\t\tthis.cache.clear();\n\t\tthis.lruTracker.clear();\n\t}\n\tmakeKey(documentId, branch) {\n\t\treturn `${documentId}:${branch}`;\n\t}\n\tasync rebuildLatest(documentId, branch, signal) {\n\t\treturn this.rebuildFromOperations(documentId, branch, void 0, signal);\n\t}\n\tasync rebuildFromOperations(documentId, branch, targetRevision, signal) {\n\t\tconst docScopeOps = await this.operationStore.getSince(documentId, \"document\", branch, -1, void 0, void 0, signal);\n\t\tif (docScopeOps.results.length === 0) throw new DocumentNotFoundError(documentId);\n\t\tconst createOp = docScopeOps.results[0];\n\t\tif (isPurgeMarker(createOp)) return purgedMeta(createOp.action);\n\t\tif (createOp.action.type !== \"CREATE_DOCUMENT\") throw new Error(`Invalid document: first operation must be CREATE_DOCUMENT, found ${createOp.action.type}`);\n\t\tconst createAction = createOp.action;\n\t\tconst documentType = createAction.input.model;\n\t\tlet document = createDocumentFromAction(createAction);\n\t\tlet documentScopeRevision = 0;\n\t\tlet purged = false;\n\t\tfor (const op of docScopeOps.results) {\n\t\t\tif (targetRevision !== void 0 && op.index > targetRevision) break;\n\t\t\tdocumentScopeRevision = op.index;\n\t\t\tif (op.action.type === \"UPGRADE_DOCUMENT\") {\n\t\t\t\tconst upgradeAction = op.action;\n\t\t\t\tdocument = applyUpgradeDocumentAction$1(document, upgradeAction);\n\t\t\t} else if (op.action.type === \"DELETE_DOCUMENT\" || op.action.type === PURGE_DOCUMENT) {\n\t\t\t\tdocument = applyDeleteDocumentAction$1(document, op.action);\n\t\t\t\tpurged ||= op.action.type === PURGE_DOCUMENT;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tstate: document.state.document,\n\t\t\tdocumentType,\n\t\t\tprotocolVersions: purged ? purgedProtocolVersions() : createAction.input.protocolVersions,\n\t\t\tdocumentScopeRevision: documentScopeRevision + 1\n\t\t};\n\t}\n};\n/** A lone marker has no CREATE_DOCUMENT; the marker describes the stream. */\nfunction purgedMeta(action) {\n\treturn {\n\t\tstate: createDocumentState({\n\t\t\tisDeleted: true,\n\t\t\tdeletedAtUtcIso: action.input.purgedAtUtcIso\n\t\t}),\n\t\tdocumentType: action.input.documentType,\n\t\tprotocolVersions: purgedProtocolVersions(),\n\t\tdocumentScopeRevision: 1\n\t};\n}\n//#endregion\n//#region src/catch-up/settled-watermark.ts\nconst MAX_PENDING_PROBES = 64;\n/** pg_sequence_last_value needs 10; pg_current_* replaced txid_* in 13. */\nfunction snapshotFunctionsFor(serverVersionNum) {\n\tif (serverVersionNum >= 13e4) return {\n\t\tsnapshot: \"pg_current_snapshot\",\n\t\tcurrentXid: \"pg_current_xact_id\",\n\t\txidIfAssigned: \"pg_current_xact_id_if_assigned\"\n\t};\n\tif (serverVersionNum >= 1e5) return {\n\t\tsnapshot: \"txid_current_snapshot\",\n\t\tcurrentXid: \"txid_current\",\n\t\txidIfAssigned: \"txid_current_if_assigned\"\n\t};\n\tthrow new Error(`PostgreSQL server_version_num ${serverVersionNum} is not supported: read-side catch-up needs 10 or later`);\n}\n/** Parses the `xmin:xmax:xip,...` text form of a snapshot. */\nfunction parseSnapshot(text) {\n\tconst parts = text.split(\":\");\n\tif (parts.length !== 3) throw new Error(`Malformed snapshot: ${text}`);\n\tconst [xmin, xmax, xip] = parts;\n\treturn {\n\t\txmin: BigInt(xmin),\n\t\txmax: BigInt(xmax),\n\t\txip: xip === \"\" ? [] : xip.split(\",\").map((xid) => BigInt(xid))\n\t};\n}\nasync function readSnapshotFunctions(db) {\n\tconst result = await sql`select current_setting('server_version_num') as version`.execute(db);\n\treturn snapshotFunctionsFor(Number(result.rows[0].version));\n}\n/** A probe settles once an xmin passes the xid it took after its head. */\nvar ProbeSettler = class {\n\tsettled = 0;\n\tlastHead = 0;\n\tcovered = 0;\n\tlastXip = [];\n\tpending = [];\n\tget settledThrough() {\n\t\treturn this.settled;\n\t}\n\tget head() {\n\t\treturn this.lastHead;\n\t}\n\t/** The highest head a settled or pending probe covers. */\n\tget probedHead() {\n\t\treturn this.covered;\n\t}\n\tobserve(head, xid, snapshot, nowUtcMs) {\n\t\tthis.lastHead = Math.max(this.lastHead, head);\n\t\tthis.lastXip = snapshot.xip;\n\t\tif (xid !== null && head > this.covered) {\n\t\t\tthis.covered = head;\n\t\t\tthis.pending.push({\n\t\t\t\thead,\n\t\t\t\txid,\n\t\t\t\ttakenAtUtcMs: nowUtcMs\n\t\t\t});\n\t\t\tif (this.pending.length > MAX_PENDING_PROBES) this.pending.shift();\n\t\t}\n\t\tconst stillPending = [];\n\t\tfor (const probe of this.pending) if (snapshot.xmin > probe.xid) this.settled = Math.max(this.settled, probe.head);\n\t\telse stillPending.push(probe);\n\t\tthis.pending = stillPending.filter((probe) => probe.head > this.settled);\n\t\treturn this.settled;\n\t}\n\t/** Xids an unsettled probe still waits on. */\n\twaitingOn() {\n\t\tif (this.pending.length === 0) return [];\n\t\tconst xid = this.pending[0].xid;\n\t\treturn this.lastXip.filter((open) => open < xid).map((open) => open.toString());\n\t}\n\tstalledSinceUtcMs() {\n\t\treturn this.pending[0]?.takenAtUtcMs;\n\t}\n};\nfunction operationIndexTableName(db) {\n\tconst from = db.selectFrom(\"operation_index_operations\").selectAll().toOperationNode().from?.froms[0];\n\tconst schema = from !== void 0 && TableNode.is(from) ? from.table.schema?.name : void 0;\n\tconst quote = (identifier) => `\"${identifier.replace(/\"/g, \"\\\"\\\"\")}\"`;\n\treturn schema === void 0 ? quote(\"operation_index_operations\") : `${quote(schema)}.${quote(\"operation_index_operations\")}`;\n}\n/** Reads the head, takes and commits an xid, then reads a snapshot, in order. */\nfunction createKyselyWatermarkProbe(db) {\n\tlet resolved = null;\n\tconst resolve = async () => {\n\t\tconst fns = await readSnapshotFunctions(db);\n\t\tconst table = operationIndexTableName(db);\n\t\tconst sequence = (await sql`select pg_get_serial_sequence(${table}, 'ordinal') as sequence`.execute(db)).rows[0]?.sequence;\n\t\tif (!sequence) throw new Error(`No ordinal sequence found for ${table}`);\n\t\treturn {\n\t\t\tfns,\n\t\t\tsequence\n\t\t};\n\t};\n\treturn async (probedHead) => {\n\t\tresolved ??= resolve().catch((error) => {\n\t\t\tresolved = null;\n\t\t\tthrow error;\n\t\t});\n\t\tconst { fns, sequence } = await resolved;\n\t\tconst headRow = (await sql`select coalesce(pg_sequence_last_value(${sequence}::regclass), 0) as head, ${sql.raw(fns.xidIfAssigned)}() is null as outside_write`.execute(db)).rows[0];\n\t\tconst head = Number(headRow.head);\n\t\tlet xid = null;\n\t\tif (headRow.outside_write && head > probedHead) {\n\t\t\tconst xidResult = await sql`select ${sql.raw(fns.currentXid)}()::text as xid`.execute(db);\n\t\t\txid = BigInt(xidResult.rows[0].xid);\n\t\t}\n\t\tconst row = (await sql`select ${sql.raw(fns.snapshot)}()::text as snapshot, ${sql.raw(fns.xidIfAssigned)}() is null as outside_write`.execute(db)).rows[0];\n\t\treturn {\n\t\t\thead,\n\t\t\txid,\n\t\t\tsnapshot: parseSnapshot(row.snapshot),\n\t\t\toutsideWrite: headRow.outside_write && row.outside_write\n\t\t};\n\t};\n}\n/** Knows when an ordinal gap is final by asking which transactions are open. */\nvar SettledWatermark = class {\n\tprobe;\n\tlogger;\n\tnow;\n\tsettler = new ProbeSettler();\n\tlisteners = /* @__PURE__ */ new Set();\n\tcurrent;\n\tnext;\n\twarnedInsideWrite = false;\n\tconstructor(probe, logger, now = Date.now) {\n\t\tthis.probe = probe;\n\t\tthis.logger = logger;\n\t\tthis.now = now;\n\t}\n\tget settledThrough() {\n\t\treturn this.settler.settledThrough;\n\t}\n\trefresh(signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (this.next !== void 0) return this.next;\n\t\tif (this.current === void 0) return this.start();\n\t\tconst next = this.current.catch(() => this.settledThrough).then(() => {\n\t\t\tthis.next = void 0;\n\t\t\treturn this.start();\n\t\t});\n\t\tthis.next = next;\n\t\treturn next;\n\t}\n\tonAdvance(listener) {\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\tstatus() {\n\t\tconst stalledSinceUtcMs = this.settler.head > this.settledThrough ? this.settler.stalledSinceUtcMs() : void 0;\n\t\treturn {\n\t\t\thead: this.settler.head,\n\t\t\tsettledThrough: this.settledThrough,\n\t\t\twaitingOn: this.settler.waitingOn(),\n\t\t\t...stalledSinceUtcMs !== void 0 ? { stalledSinceUtcMs } : {}\n\t\t};\n\t}\n\tstart() {\n\t\tconst run = this.probeOnce().finally(() => {\n\t\t\tif (this.current === run) this.current = void 0;\n\t\t});\n\t\tthis.current = run;\n\t\treturn run;\n\t}\n\tasync probeOnce() {\n\t\tconst reading = await this.probe(this.settler.probedHead);\n\t\tif (!reading.outsideWrite) {\n\t\t\tif (!this.warnedInsideWrite) {\n\t\t\t\tthis.warnedInsideWrite = true;\n\t\t\t\tthis.logger.warn(\"settled watermark probe ran inside another session's write transaction; discarded\");\n\t\t\t}\n\t\t\treturn this.settledThrough;\n\t\t}\n\t\tconst before = this.settledThrough;\n\t\tconst after = this.settler.observe(reading.head, reading.xid, reading.snapshot, this.now());\n\t\tif (after > before) for (const listener of this.listeners) try {\n\t\t\tlistener(after);\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\"settled watermark listener failed: @error\", error);\n\t\t}\n\t\treturn after;\n\t}\n};\n/** Sessions holding these xids open; empty without pg_stat_activity. */\nasync function describeWaitingSessions(db, xids) {\n\tif (xids.length === 0) return [];\n\tconst epochless = xids.map((xid) => (BigInt(xid) % 2n ** 32n).toString());\n\ttry {\n\t\treturn (await sql`select pid, application_name, state, xact_start, backend_xid::text as xid\n from pg_stat_activity\n where backend_xid::text in (${sql.join(epochless)})`.execute(db)).rows.map((row) => ({\n\t\t\tpid: Number(row.pid),\n\t\t\tapplicationName: row.application_name ?? \"\",\n\t\t\tstate: row.state ?? \"\",\n\t\t\txactStart: row.xact_start === null ? null : new Date(row.xact_start).toISOString(),\n\t\t\txid: row.xid\n\t\t}));\n\t} catch {\n\t\treturn [];\n\t}\n}\n//#endregion\n//#region src/storage/kysely/document-purges.ts\n/** Class key of every purge lock; the stream locks use the single-key space. */\nconst PURGE_NS = 1347571013;\n/** Ids share this many lock keys, so a job's lock count stays bounded. */\nconst PURGE_LOCK_BUCKETS = 1024;\nasync function acquirePurgeLocks(trx, ids, mode) {\n\tconst unique = [...new Set(ids)];\n\tif (unique.length === 0) return;\n\tconst lock = sql.raw(mode === \"shared\" ? \"pg_advisory_xact_lock_shared\" : \"pg_advisory_xact_lock\");\n\tawait sql`\n with keys as materialized (\n select distinct hashtext(id) & ${sql.lit(1023)} as key\n from unnest(${unique}::text[]) as t(id)\n order by key\n )\n select ${lock}(${sql.lit(PURGE_NS)}, key) from keys order by key\n `.execute(trx);\n}\n/** The ids among `ids` that have a tombstone, read in the handle's schema. */\nasync function findPurged(db, ids) {\n\tconst unique = [...new Set(ids)];\n\tif (unique.length === 0) return /* @__PURE__ */ new Set();\n\tconst rows = await db.selectFrom(\"document_purges\").select(\"documentId\").where(sql`\"documentId\" = any(${unique}::text[])`).execute();\n\treturn new Set(rows.map((row) => row.documentId));\n}\n/** Every tombstoned id, read in the handle's schema. */\nasync function listPurged(db) {\n\treturn (await db.selectFrom(\"document_purges\").select(\"documentId\").orderBy(\"documentId\").execute()).map((row) => row.documentId);\n}\n/** Bind slots per statement: 16-bit on the wire, read signed in-process. */\nconst MAX_BIND_PARAMETERS = 32767;\n/** Splits rows into runs that each bind at most MAX_BIND_PARAMETERS. */\nfunction chunkRows(rows) {\n\tif (rows.length === 0) return [];\n\tconst columnsPerRow = Math.max(1, Object.keys(rows[0]).length);\n\tconst perChunk = Math.max(1, Math.floor(MAX_BIND_PARAMETERS / columnsPerRow));\n\tif (rows.length <= perChunk) return [rows];\n\tconst chunks = [];\n\tfor (let i = 0; i < rows.length; i += perChunk) chunks.push(rows.slice(i, i + perChunk));\n\treturn chunks;\n}\n/** Per database: the function that assigns the transaction's xid. */\nconst xidFunctions = /* @__PURE__ */ new WeakMap();\nvar KyselyOperationIndexTxn = class {\n\tcollections = [];\n\tcollectionMemberships = [];\n\tcollectionRemovals = [];\n\tgroupReferences = [];\n\toperations = [];\n\tmembershipInvalidations = /* @__PURE__ */ new Set();\n\t/** Called by the commit as it writes each document_collections row. */\n\trecordMembershipInvalidation(documentId) {\n\t\tthis.membershipInvalidations.add(documentId);\n\t}\n\tgetMembershipInvalidations() {\n\t\treturn [...this.membershipInvalidations];\n\t}\n\tcreateCollection(collectionId) {\n\t\tthis.collections.push(collectionId);\n\t}\n\taddToCollection(collectionId, documentId) {\n\t\tconst lastOpIndex = this.operations.length - 1;\n\t\tif (lastOpIndex < 0) throw new Error(\"addToCollection must be called after write() - no operations in transaction\");\n\t\tthis.collectionMemberships.push({\n\t\t\tcollectionId,\n\t\t\tdocumentId,\n\t\t\toperationIndex: lastOpIndex\n\t\t});\n\t}\n\tremoveFromCollection(collectionId, documentId) {\n\t\tconst lastOpIndex = this.operations.length - 1;\n\t\tif (lastOpIndex < 0) throw new Error(\"removeFromCollection must be called after write() - no operations in transaction\");\n\t\tthis.collectionRemovals.push({\n\t\t\tcollectionId,\n\t\t\tdocumentId,\n\t\t\toperationIndex: lastOpIndex\n\t\t});\n\t}\n\trecordGroupReferences(documentId, groupIds) {\n\t\tconst lastOpIndex = this.operations.length - 1;\n\t\tif (lastOpIndex < 0) throw new Error(\"recordGroupReferences must be called after write() - no operations in transaction\");\n\t\tif (groupIds.length === 0) return;\n\t\tthis.groupReferences.push({\n\t\t\tdocumentId,\n\t\t\tgroupIds,\n\t\t\toperationIndex: lastOpIndex\n\t\t});\n\t}\n\twrite(operations) {\n\t\tthis.operations.push(...operations);\n\t}\n\tgetCollections() {\n\t\treturn this.collections;\n\t}\n\tgetGroupReferenceRecords() {\n\t\treturn this.groupReferences;\n\t}\n\tgetCollectionMembershipRecords() {\n\t\treturn this.collectionMemberships;\n\t}\n\tgetCollectionRemovals() {\n\t\treturn this.collectionRemovals;\n\t}\n\tgetOperations() {\n\t\treturn this.operations;\n\t}\n};\nvar KyselyOperationIndex = class KyselyOperationIndex {\n\tdb;\n\ttrx;\n\tliveIds;\n\tconstructor(db) {\n\t\tthis.db = db;\n\t}\n\tget queryExecutor() {\n\t\treturn this.trx ?? this.db;\n\t}\n\t/** `liveIds`: ids the transaction read untombstoned under its shared lock. */\n\twithTransaction(trx, liveIds) {\n\t\tconst instance = new KyselyOperationIndex(this.db);\n\t\tinstance.trx = trx;\n\t\tinstance.liveIds = liveIds;\n\t\treturn instance;\n\t}\n\tstart() {\n\t\treturn new KyselyOperationIndexTxn();\n\t}\n\tasync commit(txn, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst kyselyTxn = txn;\n\t\tif (this.trx) return this.executeCommit(this.trx, kyselyTxn);\n\t\tlet resultOrdinals = [];\n\t\tawait this.db.transaction().execute(async (trx) => {\n\t\t\tresultOrdinals = await this.executeCommit(trx, kyselyTxn);\n\t\t});\n\t\treturn resultOrdinals;\n\t}\n\t/**\n\t* A policy-driven join: keeps the earliest join so a rediscovered reference\n\t* never shrinks a backfill window remotes already rely on, and reopens a\n\t* closed membership because a policy reference is not a removable one.\n\t*/\n\tasync joinKeepingEarliest(trx, kyselyTxn, documentId, collectionId, ordinal) {\n\t\tkyselyTxn.recordMembershipInvalidation(documentId);\n\t\tawait trx.insertInto(\"document_collections\").values({\n\t\t\tdocumentId,\n\t\t\tcollectionId,\n\t\t\tjoinedOrdinal: ordinal,\n\t\t\tleftOrdinal: null\n\t\t}).onConflict((oc) => oc.columns([\"documentId\", \"collectionId\"]).doUpdateSet({\n\t\t\tjoinedOrdinal: sql`LEAST(\"document_collections\".\"joinedOrdinal\", EXCLUDED.\"joinedOrdinal\")`,\n\t\t\tleftOrdinal: null\n\t\t})).execute();\n\t}\n\tasync executeCommit(trx, kyselyTxn) {\n\t\tconst collections = kyselyTxn.getCollections();\n\t\tconst memberships = kyselyTxn.getCollectionMembershipRecords();\n\t\tconst removals = kyselyTxn.getCollectionRemovals();\n\t\tconst groupReferences = kyselyTxn.getGroupReferenceRecords();\n\t\tconst operations = kyselyTxn.getOperations();\n\t\tif (collections.length > 0) {\n\t\t\tconst collectionRows = collections.map((collectionId) => ({\n\t\t\t\tdocumentId: collectionId,\n\t\t\t\tcollectionId,\n\t\t\t\tjoinedOrdinal: BigInt(0),\n\t\t\t\tleftOrdinal: null\n\t\t\t}));\n\t\t\tfor (const collectionId of collections) kyselyTxn.recordMembershipInvalidation(collectionId);\n\t\t\tfor (const chunk of chunkRows(collectionRows)) await trx.insertInto(\"document_collections\").values(chunk).onConflict((oc) => oc.doNothing()).execute();\n\t\t}\n\t\tlet operationOrdinals = [];\n\t\tif (operations.length > 0) {\n\t\t\tawait this.refusePurgedOperations(trx, operations);\n\t\t\tawait this.assignXid(trx);\n\t\t\tconst operationRows = operations.map((op) => ({\n\t\t\t\topId: op.id || \"\",\n\t\t\t\tdocumentId: op.documentId,\n\t\t\t\tdocumentType: op.documentType,\n\t\t\t\tscope: op.scope,\n\t\t\t\tbranch: op.branch,\n\t\t\t\ttimestampUtcMs: op.timestampUtcMs,\n\t\t\t\tindex: op.index,\n\t\t\t\tskip: op.skip,\n\t\t\t\thash: op.hash,\n\t\t\t\taction: op.action,\n\t\t\t\tdeniedReason: op.deniedReason ?? null,\n\t\t\t\tsourceRemote: op.sourceRemote\n\t\t\t}));\n\t\t\tfor (const chunk of chunkRows(operationRows)) {\n\t\t\t\tconst insertedOps = await trx.insertInto(\"operation_index_operations\").values(chunk).returning(\"ordinal\").execute();\n\t\t\t\toperationOrdinals = operationOrdinals.concat(insertedOps.map((row) => row.ordinal));\n\t\t\t}\n\t\t}\n\t\tif (memberships.length > 0) for (const m of memberships) {\n\t\t\tconst ordinal = operationOrdinals[m.operationIndex];\n\t\t\tkyselyTxn.recordMembershipInvalidation(m.documentId);\n\t\t\tawait trx.insertInto(\"document_collections\").values({\n\t\t\t\tdocumentId: m.documentId,\n\t\t\t\tcollectionId: m.collectionId,\n\t\t\t\tjoinedOrdinal: BigInt(ordinal),\n\t\t\t\tleftOrdinal: null\n\t\t\t}).onConflict((oc) => oc.columns([\"documentId\", \"collectionId\"]).doUpdateSet({\n\t\t\t\tjoinedOrdinal: BigInt(ordinal),\n\t\t\t\tleftOrdinal: null\n\t\t\t})).execute();\n\t\t\tconst references = await trx.selectFrom(\"group_references\").select(\"groupId\").where(\"documentId\", \"=\", m.documentId).execute();\n\t\t\tfor (const { groupId } of references) await this.joinKeepingEarliest(trx, kyselyTxn, groupId, m.collectionId, BigInt(ordinal));\n\t\t}\n\t\tif (removals.length > 0) for (const r of removals) {\n\t\t\tconst ordinal = operationOrdinals[r.operationIndex];\n\t\t\tkyselyTxn.recordMembershipInvalidation(r.documentId);\n\t\t\tawait trx.updateTable(\"document_collections\").set({ leftOrdinal: BigInt(ordinal) }).where(\"collectionId\", \"=\", r.collectionId).where(\"documentId\", \"=\", r.documentId).where(\"leftOrdinal\", \"is\", null).execute();\n\t\t}\n\t\tif (groupReferences.length > 0) for (const record of groupReferences) {\n\t\t\tconst ordinal = operationOrdinals[record.operationIndex];\n\t\t\tawait trx.insertInto(\"group_references\").values(record.groupIds.map((groupId) => ({\n\t\t\t\tdocumentId: record.documentId,\n\t\t\t\tgroupId\n\t\t\t}))).onConflict((oc) => oc.doNothing()).execute();\n\t\t\tconst rows = await trx.selectFrom(\"document_collections\").select(\"collectionId\").where(\"documentId\", \"=\", record.documentId).execute();\n\t\t\tfor (const groupId of record.groupIds) for (const { collectionId } of rows) await this.joinKeepingEarliest(trx, kyselyTxn, groupId, collectionId, BigInt(ordinal));\n\t\t}\n\t\treturn operationOrdinals;\n\t}\n\tasync getCollectionsInRange(after, through, among, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (through <= after || among?.length === 0) return [];\n\t\tlet query = this.queryExecutor.selectFrom(\"operation_index_operations as oi\").innerJoin(\"document_collections as dc\", \"oi.documentId\", \"dc.documentId\").select(\"dc.collectionId\").distinct().where(\"oi.ordinal\", \">\", after).where(\"oi.ordinal\", \"<=\", through);\n\t\tif (among !== void 0) query = query.where(\"dc.collectionId\", \"in\", [...among]);\n\t\treturn (await query.execute()).map((row) => row.collectionId);\n\t}\n\tasync getOrdinalsInRange(after, through, limit, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (through <= after || limit <= 0) return [];\n\t\treturn (await this.queryExecutor.selectFrom(\"operation_index_operations\").select(\"ordinal\").where(\"ordinal\", \">\", after).where(\"ordinal\", \"<=\", through).orderBy(\"ordinal\", \"asc\").limit(limit).execute()).map((row) => Number(row.ordinal));\n\t}\n\tasync getByOrdinals(ordinals, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (ordinals.length === 0) return [];\n\t\tconst results = [];\n\t\tfor (let i = 0; i < ordinals.length; i += MAX_BIND_PARAMETERS) {\n\t\t\tconst chunk = ordinals.slice(i, i + MAX_BIND_PARAMETERS);\n\t\t\tconst rows = await this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"ordinal\", \"in\", chunk).orderBy(\"ordinal\", \"asc\").execute();\n\t\t\tfor (const row of rows) results.push(this.rowToOperationWithContext(row));\n\t\t}\n\t\tresults.sort((a, b) => a.context.ordinal - b.context.ordinal);\n\t\treturn results;\n\t}\n\tasync getStreamAfter(stream, after, signal, limit) {\n\t\tsignal?.throwIfAborted();\n\t\treturn (await this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"documentId\", \"=\", stream.documentId).where(\"branch\", \"=\", stream.branch).where(\"scope\", \"=\", stream.scope).where(\"ordinal\", \">\", after).orderBy(\"ordinal\", \"asc\").$if(limit !== void 0, (qb) => qb.limit(limit)).execute()).map((row) => this.rowToOperationWithContext(row));\n\t}\n\tasync getGroupReferencers(groupId, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\treturn (await this.queryExecutor.selectFrom(\"group_references\").select(\"documentId\").where(\"groupId\", \"=\", groupId).orderBy(\"documentId\").execute()).map((row) => row.documentId);\n\t}\n\tasync getOrdinalsByOpIds(documentId, scope, branch, opIds, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (opIds.length === 0) return /* @__PURE__ */ new Map();\n\t\tconst rows = await this.queryExecutor.selectFrom(\"operation_index_operations\").select(\"opId\").select((eb) => eb.fn.max(\"ordinal\").as(\"ordinal\")).where(\"documentId\", \"=\", documentId).where(\"branch\", \"=\", branch).where(\"scope\", \"=\", scope).where(\"opId\", \"in\", opIds).groupBy(\"opId\").execute();\n\t\treturn new Map(rows.map((row) => [row.opId, Number(row.ordinal)]));\n\t}\n\tasync find(collectionId, cursor, view, paging, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst outerCursor = cursor ?? -1;\n\t\tconst limit = paging?.limit ?? 500;\n\t\tconst pagingCursorOrdinal = paging?.cursor !== void 0 ? Number.parseInt(paging.cursor, 10) : -1;\n\t\tconst buildBranch = (kind) => {\n\t\t\tlet qb = this.queryExecutor.selectFrom(\"operation_index_operations as oi\").innerJoin(\"document_collections as dc\", \"oi.documentId\", \"dc.documentId\").selectAll(\"oi\").select([\"dc.documentId\", \"dc.collectionId\"]).where(\"dc.collectionId\", \"=\", collectionId).where(sql`(dc.\"leftOrdinal\" IS NULL OR oi.ordinal < dc.\"leftOrdinal\")`);\n\t\t\tif (kind === \"joiner\") qb = qb.where(\"dc.joinedOrdinal\", \">\", BigInt(outerCursor)).where(\"oi.ordinal\", \"<=\", outerCursor);\n\t\t\telse qb = qb.where(\"oi.ordinal\", \">\", outerCursor);\n\t\t\tqb = qb.where(\"oi.ordinal\", \">\", pagingCursorOrdinal);\n\t\t\tif (view?.branch) qb = qb.where(\"oi.branch\", \"=\", view.branch);\n\t\t\tif (view?.scopes && view.scopes.length > 0) qb = qb.where(\"oi.scope\", \"in\", view.scopes);\n\t\t\tif (view?.excludeSourceRemote) qb = qb.where(\"oi.sourceRemote\", \"!=\", view.excludeSourceRemote);\n\t\t\tif (view?.throughOrdinal !== void 0) qb = qb.where(\"oi.ordinal\", \"<=\", view.throughOrdinal).where(\"dc.joinedOrdinal\", \"<=\", BigInt(view.throughOrdinal));\n\t\t\treturn qb;\n\t\t};\n\t\tconst rows = await buildBranch(\"joiner\").unionAll(buildBranch(\"newOps\")).orderBy(\"ordinal\", \"asc\").limit(limit + 1).execute();\n\t\tlet hasMore = false;\n\t\tlet items = rows;\n\t\tif (rows.length > limit) {\n\t\t\thasMore = true;\n\t\t\titems = rows.slice(0, limit);\n\t\t}\n\t\tconst nextCursor = hasMore && items.length > 0 ? items[items.length - 1].ordinal.toString() : void 0;\n\t\tconst cursorValue = paging?.cursor || \"0\";\n\t\treturn {\n\t\t\tresults: items.map((row) => this.rowToOperationIndexEntry(row)),\n\t\t\toptions: {\n\t\t\t\tcursor: cursorValue,\n\t\t\t\tlimit\n\t\t\t},\n\t\t\tnextCursor,\n\t\t\tnext: hasMore ? () => this.find(collectionId, cursor, view, {\n\t\t\t\tcursor: nextCursor,\n\t\t\t\tlimit\n\t\t\t}, signal) : void 0\n\t\t};\n\t}\n\tasync get(documentId, view, paging, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst limit = paging?.limit ?? 500;\n\t\tlet query = this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"documentId\", \"=\", documentId).orderBy(\"ordinal\", \"asc\");\n\t\tif (view?.branch) query = query.where(\"branch\", \"=\", view.branch);\n\t\tif (view?.scopes && view.scopes.length > 0) query = query.where(\"scope\", \"in\", view.scopes);\n\t\tif (paging?.cursor) {\n\t\t\tconst cursorOrdinal = Number.parseInt(paging.cursor, 10);\n\t\t\tquery = query.where(\"ordinal\", \">\", cursorOrdinal);\n\t\t}\n\t\tquery = query.limit(limit + 1);\n\t\tconst rows = await query.execute();\n\t\tlet hasMore = false;\n\t\tlet items = rows;\n\t\tif (rows.length > limit) {\n\t\t\thasMore = true;\n\t\t\titems = rows.slice(0, limit);\n\t\t}\n\t\tconst nextCursor = hasMore && items.length > 0 ? items[items.length - 1].ordinal.toString() : void 0;\n\t\tconst cursorValue = paging?.cursor || \"0\";\n\t\treturn {\n\t\t\tresults: items.map((row) => this.rowToOperationIndexEntry(row)),\n\t\t\toptions: {\n\t\t\t\tcursor: cursorValue,\n\t\t\t\tlimit\n\t\t\t},\n\t\t\tnextCursor,\n\t\t\tnext: hasMore ? () => this.get(documentId, view, {\n\t\t\t\tcursor: nextCursor,\n\t\t\t\tlimit\n\t\t\t}, signal) : void 0\n\t\t};\n\t}\n\tasync getSinceOrdinal(ordinal, paging, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst limit = paging?.limit ?? 500;\n\t\tlet query = this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"ordinal\", \">\", ordinal).orderBy(\"ordinal\", \"asc\");\n\t\tif (paging?.cursor) {\n\t\t\tconst cursorOrdinal = Number.parseInt(paging.cursor, 10);\n\t\t\tquery = query.where(\"ordinal\", \">\", cursorOrdinal);\n\t\t}\n\t\tquery = query.limit(limit + 1);\n\t\tconst rows = await query.execute();\n\t\tlet hasMore = false;\n\t\tlet items = rows;\n\t\tif (rows.length > limit) {\n\t\t\thasMore = true;\n\t\t\titems = rows.slice(0, limit);\n\t\t}\n\t\tconst nextCursor = hasMore && items.length > 0 ? items[items.length - 1].ordinal.toString() : void 0;\n\t\tconst cursorValue = paging?.cursor || \"0\";\n\t\treturn {\n\t\t\tresults: items.map((row) => this.rowToOperationWithContext(row)),\n\t\t\toptions: {\n\t\t\t\tcursor: cursorValue,\n\t\t\t\tlimit\n\t\t\t},\n\t\t\tnextCursor,\n\t\t\tnext: hasMore ? () => this.getSinceOrdinal(ordinal, {\n\t\t\t\tcursor: nextCursor,\n\t\t\t\tlimit\n\t\t\t}, signal) : void 0\n\t\t};\n\t}\n\t/** Backstop to the store's refusal: only a marker indexes a purged id. */\n\tasync refusePurgedOperations(trx, operations) {\n\t\tconst ids = new Set(operations.filter((operation) => !isPurgeMarker(operation)).map((operation) => operation.documentId).filter((id) => !this.liveIds?.has(id)));\n\t\tconst purged = await findPurged(trx, ids);\n\t\tfor (const id of ids) if (purged.has(id)) throw new DocumentPurgedError(id);\n\t}\n\t/** Takes the xid before the first ordinal, as the settled watermark needs. */\n\tasync assignXid(trx) {\n\t\tlet fn = xidFunctions.get(this.db);\n\t\tif (fn === void 0) {\n\t\t\tfn = readSnapshotFunctions(trx).then((fns) => fns.currentXid);\n\t\t\txidFunctions.set(this.db, fn);\n\t\t\tfn.catch(() => xidFunctions.delete(this.db));\n\t\t}\n\t\tconst name = await fn;\n\t\tawait sql`select ${sql.raw(name)}()`.execute(trx);\n\t}\n\trowToOperationWithContext(row) {\n\t\treturn {\n\t\t\toperation: {\n\t\t\t\tindex: row.index,\n\t\t\t\ttimestampUtcMs: row.timestampUtcMs,\n\t\t\t\thash: row.hash,\n\t\t\t\tskip: row.skip,\n\t\t\t\taction: row.action,\n\t\t\t\tdeniedReason: row.deniedReason ?? void 0,\n\t\t\t\tid: row.opId\n\t\t\t},\n\t\t\tcontext: {\n\t\t\t\tdocumentId: row.documentId,\n\t\t\t\tdocumentType: row.documentType,\n\t\t\t\tscope: row.scope,\n\t\t\t\tbranch: row.branch,\n\t\t\t\tordinal: row.ordinal\n\t\t\t}\n\t\t};\n\t}\n\trowToOperationIndexEntry(row) {\n\t\treturn {\n\t\t\tordinal: row.ordinal,\n\t\t\tdocumentId: row.documentId,\n\t\t\tdocumentType: row.documentType,\n\t\t\tbranch: row.branch,\n\t\t\tscope: row.scope,\n\t\t\tindex: row.index,\n\t\t\ttimestampUtcMs: row.timestampUtcMs,\n\t\t\thash: row.hash,\n\t\t\tskip: row.skip,\n\t\t\taction: row.action,\n\t\t\tdeniedReason: row.deniedReason ?? void 0,\n\t\t\tid: row.opId,\n\t\t\tsourceRemote: row.sourceRemote\n\t\t};\n\t}\n\tasync getLatestTimestampForCollection(collectionId, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\treturn (await this.queryExecutor.selectFrom(\"operation_index_operations as oi\").innerJoin(\"document_collections as dc\", \"oi.documentId\", \"dc.documentId\").select(\"oi.timestampUtcMs\").where(\"dc.collectionId\", \"=\", collectionId).where(sql`(dc.\"leftOrdinal\" IS NULL OR oi.ordinal < dc.\"leftOrdinal\")`).orderBy(\"oi.ordinal\", \"desc\").limit(1).executeTakeFirst())?.timestampUtcMs ?? null;\n\t}\n\tasync getCollectionsForDocuments(documentIds) {\n\t\tif (documentIds.length === 0) return {};\n\t\tconst rows = await this.queryExecutor.selectFrom(\"document_collections\").select([\"documentId\", \"collectionId\"]).where(\"documentId\", \"in\", documentIds).where(\"leftOrdinal\", \"is\", null).execute();\n\t\tconst result = {};\n\t\tfor (const row of rows) {\n\t\t\tif (!(row.documentId in result)) result[row.documentId] = [];\n\t\t\tresult[row.documentId].push(row.collectionId);\n\t\t}\n\t\treturn result;\n\t}\n};\n//#endregion\n//#region src/cache/buffer/ring-buffer.ts\n/**\n* RingBuffer is a generic circular buffer implementation that stores a fixed number\n* of items. When the buffer is full, new items overwrite the oldest items.\n*\n* This implementation maintains O(1) time complexity for push operations and provides\n* items in chronological order (oldest to newest) via getAll().\n*\n* @template T - The type of items stored in the buffer\n*/\nvar RingBuffer = class {\n\tbuffer;\n\thead = 0;\n\tsize = 0;\n\tcapacity;\n\tconstructor(capacity) {\n\t\tif (capacity <= 0) throw new Error(\"Ring buffer capacity must be greater than 0\");\n\t\tthis.capacity = capacity;\n\t\tthis.buffer = new Array(capacity);\n\t}\n\t/**\n\t* Adds an item to the buffer. If the buffer is full, overwrites the oldest item.\n\t*\n\t* @param item - The item to add\n\t*/\n\tpush(item) {\n\t\tconst index = (this.head + this.size) % this.capacity;\n\t\tif (this.size < this.capacity) {\n\t\t\tthis.buffer[index] = item;\n\t\t\tthis.size++;\n\t\t} else {\n\t\t\tthis.buffer[this.head] = item;\n\t\t\tthis.head = (this.head + 1) % this.capacity;\n\t\t}\n\t}\n\t/**\n\t* Returns all items in the buffer in chronological order (oldest to newest).\n\t*\n\t* @returns Array of items in insertion order\n\t*/\n\tgetAll() {\n\t\tif (this.size === 0) return [];\n\t\tconst result = [];\n\t\tfor (let i = 0; i < this.size; i++) {\n\t\t\tconst index = (this.head + i) % this.capacity;\n\t\t\tresult.push(this.buffer[index]);\n\t\t}\n\t\treturn result;\n\t}\n\t/**\n\t* Clears all items from the buffer.\n\t*/\n\tclear() {\n\t\tthis.buffer = new Array(this.capacity);\n\t\tthis.head = 0;\n\t\tthis.size = 0;\n\t}\n\t/**\n\t* Gets the current number of items in the buffer.\n\t*/\n\tget length() {\n\t\treturn this.size;\n\t}\n};\n//#endregion\n//#region src/cache/kysely-write-cache.ts\n/**\n* The last operation index a keyframe's document reflects for the scope. A\n* keyframe only exists for a scope that has operations, so a missing entry\n* means the stored row is corrupt.\n*/\nfunction keyframeRevision(keyframe, documentId, scope) {\n\tconst nextIndex = keyframe.document.header.revision[scope];\n\tif (typeof nextIndex !== \"number\") throw new Error(`Corrupt keyframe for document ${documentId} at revision ${keyframe.revision}: header carries no ${scope} revision`);\n\treturn nextIndex - 1;\n}\nfunction extractModuleVersion(doc) {\n\tconst v = doc.state.document.version;\n\treturn normalizeDocumentModelVersion(v);\n}\n/** The highest revision held, latest push winning a tie. */\nfunction highestRevision(snapshots) {\n\tlet newest = void 0;\n\tfor (const snapshot of snapshots) if (!newest || snapshot.revision >= newest.revision) newest = snapshot;\n\treturn newest;\n}\n/**\n* Copies a document far enough that the caller cannot write through it. Inside\n* this class, callers only ever replace whole fields on these four, so one\n* level each is enough.\n*/\nfunction copyDocument(document) {\n\treturn {\n\t\t...document,\n\t\theader: { ...document.header },\n\t\tstate: { ...document.state },\n\t\toperations: { ...document.operations }\n\t};\n}\nvar KyselyWriteCache = class KyselyWriteCache {\n\tstreams;\n\tlruTracker;\n\tkeyframeStore;\n\toperationStore;\n\tregistry;\n\tconfig;\n\treads = /* @__PURE__ */ new Map();\n\tconstructor(keyframeStore, operationStore, registry, config) {\n\t\tthis.keyframeStore = keyframeStore;\n\t\tthis.operationStore = operationStore;\n\t\tthis.registry = registry;\n\t\tthis.config = {\n\t\t\tmaxDocuments: config.maxDocuments,\n\t\t\tringBufferSize: config.ringBufferSize,\n\t\t\tkeyframeInterval: config.keyframeInterval\n\t\t};\n\t\tthis.streams = /* @__PURE__ */ new Map();\n\t\tthis.lruTracker = new LRUTracker();\n\t}\n\twithScopedStores(operationStore, keyframeStore) {\n\t\tconst scoped = new KyselyWriteCache(keyframeStore, operationStore, this.registry, this.config);\n\t\tscoped.streams = this.streams;\n\t\tscoped.lruTracker = this.lruTracker;\n\t\tscoped.reads = this.reads;\n\t\treturn scoped;\n\t}\n\t/**\n\t* Initializes the write cache.\n\t* Currently a no-op as keyframe store lifecycle is managed externally.\n\t*/\n\tasync startup() {\n\t\treturn Promise.resolve();\n\t}\n\t/**\n\t* Shuts down the write cache.\n\t* Currently a no-op as keyframe store lifecycle is managed externally.\n\t*/\n\tasync shutdown() {\n\t\treturn Promise.resolve();\n\t}\n\t/**\n\t* Retrieves document state at a specific revision from cache or rebuilds it.\n\t*\n\t* Note: this returns a _shallow_ copy of the document.\n\t*\n\t* Cache hit path: Returns cached snapshot if available (O(1))\n\t* Warm miss path: Rebuilds from cached base revision + incremental ops\n\t* Cold miss path: Rebuilds from keyframe or from scratch using all operations\n\t*\n\t* @param documentId - The document identifier\n\t* @param scope - The operation scope\n\t* @param branch - The operation branch\n\t* @param targetRevision - The target revision, or undefined for newest\n\t* @param signal - Optional abort signal to cancel the operation\n\t* @returns The document at the target revision\n\t* @throws {Error} \"Operation aborted\" if signal is aborted\n\t* @throws {ModuleNotFoundError} If document type not registered in registry\n\t* @throws {DocumentPurgedError} If the stream's only row is a purge marker\n\t* @throws {Error} \"Failed to rebuild document\" if operation store fails\n\t* @throws {Error} If reducer throws during operation application\n\t* @throws {Error} If document serialization fails\n\t*/\n\tasync getState(documentId, scope, branch, targetRevision, signal) {\n\t\tconst read = { evicted: false };\n\t\tlet pending = this.reads.get(documentId);\n\t\tif (!pending) {\n\t\t\tpending = /* @__PURE__ */ new Set();\n\t\t\tthis.reads.set(documentId, pending);\n\t\t}\n\t\tpending.add(read);\n\t\ttry {\n\t\t\treturn await this.readState(documentId, scope, branch, targetRevision, signal, read);\n\t\t} finally {\n\t\t\tpending.delete(read);\n\t\t\tif (pending.size === 0) this.reads.delete(documentId);\n\t\t}\n\t}\n\tasync readState(documentId, scope, branch, targetRevision, signal, read) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst streamKey = this.makeStreamKey(documentId, scope, branch);\n\t\tconst stream = this.streams.get(streamKey);\n\t\tif (stream) {\n\t\t\tconst snapshots = stream.ringBuffer.getAll();\n\t\t\tif (targetRevision === void 0) {\n\t\t\t\tconst newest = highestRevision(snapshots);\n\t\t\t\tif (newest?.position === \"head\") {\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn copyDocument(newest.document);\n\t\t\t\t}\n\t\t\t\tif (newest) {\n\t\t\t\t\tconst document = await this.warmMissRebuild(newest.document, newest.revision, documentId, scope, branch, void 0, signal);\n\t\t\t\t\tthis.storeUnlessEvicted(read, documentId, scope, branch, (document.header.revision[scope] ?? 0) - 1, document, \"head\");\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn document;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst exactMatch = snapshots.findLast((s) => s.revision === targetRevision);\n\t\t\t\tif (exactMatch) {\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn copyDocument(exactMatch.document);\n\t\t\t\t}\n\t\t\t\tconst newestOlder = this.findNearestOlderSnapshot(snapshots, targetRevision);\n\t\t\t\tif (newestOlder) {\n\t\t\t\t\tconst document = await this.warmMissRebuild(newestOlder.document, newestOlder.revision, documentId, scope, branch, targetRevision, signal);\n\t\t\t\t\tthis.storeUnlessEvicted(read, documentId, scope, branch, targetRevision, document, \"historical\");\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn document;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst document = await this.coldMissRebuild(documentId, scope, branch, targetRevision, signal);\n\t\tconst revision = targetRevision ?? (document.header.revision[scope] ?? 0) - 1;\n\t\tthis.storeUnlessEvicted(read, documentId, scope, branch, revision, document, targetRevision === void 0 ? \"head\" : \"historical\");\n\t\treturn document;\n\t}\n\t/**\n\t* Stores a document snapshot in the cache at a specific revision.\n\t*\n\t* The cached document is a shallow copy of the input with its operation history\n\t* truncated to the last operation per scope and its clipboard cleared. This keeps\n\t* memory use and copy costs constant regardless of operation count. Consumers of\n\t* getState() must not rely on the full operation history being present; the only\n\t* guaranteed invariant is that operations[scope].at(-1) reflects the latest\n\t* operation index for each scope.\n\t*\n\t* Updates LRU tracker and may evict least recently used stream if at capacity.\n\t* Asynchronously persists keyframes at configured intervals (fire-and-forget).\n\t*\n\t* @param documentId - The document identifier\n\t* @param scope - The operation scope\n\t* @param branch - The operation branch\n\t* @param revision - The revision number\n\t* @param document - The document to cache\n\t* @throws {Error} If document serialization fails\n\t*/\n\tputState(documentId, scope, branch, revision, document, position) {\n\t\tthis.store(documentId, scope, branch, revision, document, position);\n\t}\n\t/**\n\t* Stores the run's head and mints a keyframe for every interval the run\n\t* crossed on its way there. Only the head enters the ring buffer; the\n\t* earlier revisions are keyframe candidates and nothing more.\n\t*/\n\tputRun(documentId, scope, branch, run) {\n\t\tif (run.length === 0) return;\n\t\tfor (const entry of run.slice(0, -1)) this.persistKeyframe(documentId, scope, branch, entry.revision, entry.document);\n\t\tconst head = run[run.length - 1];\n\t\tthis.store(documentId, scope, branch, head.revision, head.document, \"head\");\n\t}\n\tstoreUnlessEvicted(read, documentId, scope, branch, revision, document, position) {\n\t\tif (!read.evicted) this.store(documentId, scope, branch, revision, document, position);\n\t}\n\tstore(documentId, scope, branch, revision, document, position) {\n\t\tconst streamKey = this.makeStreamKey(documentId, scope, branch);\n\t\tconst stream = this.getOrCreateStream(streamKey);\n\t\tconst snapshot = {\n\t\t\trevision,\n\t\t\tdocument: {\n\t\t\t\t...copyDocument(document),\n\t\t\t\toperations: Object.fromEntries(Object.entries(document.operations).map(([k, ops]) => [k, ops.length ? [ops.at(-1)] : []])),\n\t\t\t\tclipboard: []\n\t\t\t},\n\t\t\tposition\n\t\t};\n\t\tstream.ringBuffer.push(snapshot);\n\t\tthis.persistKeyframe(documentId, scope, branch, revision, document);\n\t}\n\t/** Persists the snapshot if this revision is one the interval falls on. */\n\tpersistKeyframe(documentId, scope, branch, revision, document) {\n\t\tif (!this.isKeyframeRevision(revision)) return;\n\t\tthis.keyframeStore.putKeyframe(documentId, scope, branch, revision, {\n\t\t\t...document,\n\t\t\toperations: {},\n\t\t\tclipboard: []\n\t\t}).catch((err) => {\n\t\t\tconsole.error(`Failed to persist keyframe ${documentId}@${revision}:`, err);\n\t\t});\n\t}\n\t/**\n\t* Invalidates cached document streams.\n\t*\n\t* Supports three invalidation scopes:\n\t* - Document-level: invalidate(documentId) - removes all streams for document\n\t* - Scope-level: invalidate(documentId, scope) - removes all branches for scope\n\t* - Stream-level: invalidate(documentId, scope, branch) - removes specific stream\n\t*\n\t* @param documentId - The document identifier\n\t* @param scope - Optional scope to narrow invalidation\n\t* @param branch - Optional branch to narrow invalidation (requires scope)\n\t* @returns The number of streams evicted\n\t*/\n\tinvalidate(documentId, scope, branch) {\n\t\tfor (const read of this.reads.get(documentId) ?? []) read.evicted = true;\n\t\tlet evicted = 0;\n\t\tif (scope === void 0 && branch === void 0) {\n\t\t\tfor (const [key] of this.streams.entries()) if (key.startsWith(`${documentId}:`)) {\n\t\t\t\tthis.streams.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t} else if (scope !== void 0 && branch === void 0) {\n\t\t\tfor (const [key] of this.streams.entries()) if (key.startsWith(`${documentId}:${scope}:`)) {\n\t\t\t\tthis.streams.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t} else if (scope !== void 0 && branch !== void 0) {\n\t\t\tconst key = this.makeStreamKey(documentId, scope, branch);\n\t\t\tif (this.streams.has(key)) {\n\t\t\t\tthis.streams.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted = 1;\n\t\t\t}\n\t\t}\n\t\treturn evicted;\n\t}\n\t/**\n\t* Clears the entire cache, removing all cached document streams.\n\t* Resets LRU tracking state. This operation always succeeds.\n\t*/\n\tclear() {\n\t\tfor (const pending of this.reads.values()) for (const read of pending) read.evicted = true;\n\t\tthis.streams.clear();\n\t\tthis.lruTracker.clear();\n\t}\n\t/**\n\t* Retrieves a specific stream for a document. Exposed on the implementation\n\t* for testing, but not on the interface.\n\t*\n\t* @internal\n\t*/\n\tgetStream(documentId, scope, branch) {\n\t\tconst key = this.makeStreamKey(documentId, scope, branch);\n\t\treturn this.streams.get(key);\n\t}\n\tasync findNearestKeyframe(documentId, scope, branch, targetRevision, signal) {\n\t\tif (targetRevision === Number.MAX_SAFE_INTEGER || targetRevision <= 0) return;\n\t\tconst keyframe = await this.keyframeStore.findNearestKeyframe(documentId, scope, branch, targetRevision, signal);\n\t\tif (!keyframe) return;\n\t\treturn {\n\t\t\trevision: Math.min(keyframeRevision(keyframe, documentId, scope), keyframe.revision),\n\t\t\tdocument: keyframe.document\n\t\t};\n\t}\n\t/**\n\t* Rebuilds a scope from a keyframe or from the whole operation history.\n\t*\n\t* The document scope is always rebuilt first, because it carries the type,\n\t* the upgrades and the deletion marker. Its version-changing upgrades are not\n\t* applied there though: an upgrade reducer must see the state the requested\n\t* scope has reached at that upgrade's boundary, so each one is held back and\n\t* applied when the replay below crosses the boundary that\n\t* resolveModuleVersionForOp derives from it. Upgrades whose boundary lies past\n\t* the last replayed operation are applied at the end. Creation-time 0->N seed\n\t* upgrades carry the initial state, so they still apply immediately.\n\t*/\n\tasync coldMissRebuild(documentId, scope, branch, targetRevision, signal, fromKeyframe = true) {\n\t\tconst effectiveTargetRevision = targetRevision || Number.MAX_SAFE_INTEGER;\n\t\tconst keyframe = fromKeyframe ? await this.findNearestKeyframe(documentId, scope, branch, effectiveTargetRevision, signal) : void 0;\n\t\tconst documentScopeBound = scope === \"document\" ? targetRevision : void 0;\n\t\tlet document;\n\t\tlet startRevision;\n\t\tlet documentType;\n\t\tconst validatedUpgrades = [];\n\t\tconst pendingUpgrades = [];\n\t\tlet lastDocumentScopeOperation;\n\t\tif (keyframe) {\n\t\t\tdocument = keyframe.document;\n\t\t\tstartRevision = keyframe.revision;\n\t\t\tdocumentType = keyframe.document.header.documentType;\n\t\t\tconst documentScopeResume = scope === \"document\" ? keyframe.revision : keyframeRevision(keyframe, documentId, \"document\");\n\t\t\tconst docScopeOpsAfterKeyframe = await this.operationStore.getSince(documentId, \"document\", branch, documentScopeResume, void 0, void 0, signal);\n\t\t\tfor (const operation of docScopeOpsAfterKeyframe.results) {\n\t\t\t\tif (documentScopeBound !== void 0 && operation.index > documentScopeBound) break;\n\t\t\t\tlastDocumentScopeOperation = operation;\n\t\t\t\tif (operation.error || isDenied(operation)) continue;\n\t\t\t\tif (operation.action.type === \"UPGRADE_DOCUMENT\") {\n\t\t\t\t\tconst upgradeAction = operation.action;\n\t\t\t\t\tconst fromVersion = upgradeAction.input.fromVersion;\n\t\t\t\t\tconst toVersion = upgradeAction.input.toVersion;\n\t\t\t\t\tif (fromVersion > 0 && fromVersion < toVersion) {\n\t\t\t\t\t\tlet upgradePath;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tupgradePath = this.registry.computeUpgradePath(documentType, fromVersion, toVersion);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tif (upgradeAction.input.initialState !== void 0) upgradePath = void 0;\n\t\t\t\t\t\t\telse throw new Error(`Failed to rebuild document ${documentId}: no upgrade manifest for ${documentType} v${fromVersion}→v${toVersion} and no initialState snapshot. ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvalidatedUpgrades.push({\n\t\t\t\t\t\t\tfromVersion,\n\t\t\t\t\t\t\ttoVersion,\n\t\t\t\t\t\t\trevision: upgradeAction.input.revision,\n\t\t\t\t\t\t\ttimestampUtcMs: operation.timestampUtcMs\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpendingUpgrades.push({\n\t\t\t\t\t\t\taction: upgradeAction,\n\t\t\t\t\t\t\tupgradePath,\n\t\t\t\t\t\t\tindex: operation.index,\n\t\t\t\t\t\t\tsubsequentDeletes: []\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (operation.action.type === \"DELETE_DOCUMENT\" || operation.action.type === PURGE_DOCUMENT) {\n\t\t\t\t\tapplyDeleteDocumentAction(document, operation.action);\n\t\t\t\t\tfor (const pending of pendingUpgrades) pending.subsequentDeletes.push(operation.action);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tstartRevision = -1;\n\t\t\tconst createOpResult = await this.operationStore.getSince(documentId, \"document\", branch, -1, void 0, {\n\t\t\t\tcursor: \"0\",\n\t\t\t\tlimit: 1\n\t\t\t}, signal);\n\t\t\tif (createOpResult.results.length === 0) throw new DocumentNotFoundError(documentId);\n\t\t\tconst createOp = createOpResult.results[0];\n\t\t\tif (isPurgeMarker(createOp)) throw new DocumentPurgedError(documentId);\n\t\t\tif (createOp.action.type !== \"CREATE_DOCUMENT\") throw new Error(`Failed to rebuild document ${documentId}: first operation in document scope must be CREATE_DOCUMENT, found ${createOp.action.type}`);\n\t\t\tconst documentCreateAction = createOp.action;\n\t\t\tdocumentType = documentCreateAction.input.model;\n\t\t\tif (!documentType) throw new Error(`Failed to rebuild document ${documentId}: CREATE_DOCUMENT action missing model in input`);\n\t\t\tdocument = createDocumentFromAction(documentCreateAction);\n\t\t\tlastDocumentScopeOperation = createOp;\n\t\t\tlet docModule = this.registry.getModule(documentType, extractModuleVersion(document));\n\t\t\tconst docScopeOps = await this.operationStore.getSince(documentId, \"document\", branch, 0, void 0, void 0, signal);\n\t\t\tfor (const operation of docScopeOps.results) {\n\t\t\t\tif (documentScopeBound !== void 0 && operation.index > documentScopeBound) break;\n\t\t\t\tlastDocumentScopeOperation = operation;\n\t\t\t\tif (operation.index === 0) continue;\n\t\t\t\tif (operation.error || isDenied(operation)) continue;\n\t\t\t\tif (operation.action.type === \"UPGRADE_DOCUMENT\") {\n\t\t\t\t\tconst upgradeAction = operation.action;\n\t\t\t\t\tconst fromVersion = upgradeAction.input.fromVersion;\n\t\t\t\t\tconst toVersion = upgradeAction.input.toVersion;\n\t\t\t\t\tif (fromVersion > 0 && fromVersion < toVersion) {\n\t\t\t\t\t\tlet upgradePath;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tupgradePath = this.registry.computeUpgradePath(documentType, fromVersion, toVersion);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tif (upgradeAction.input.initialState !== void 0) upgradePath = void 0;\n\t\t\t\t\t\t\telse throw new Error(`Failed to rebuild document ${documentId}: no upgrade manifest for ${documentType} v${fromVersion}→v${toVersion} and no initialState snapshot. ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvalidatedUpgrades.push({\n\t\t\t\t\t\t\tfromVersion,\n\t\t\t\t\t\t\ttoVersion,\n\t\t\t\t\t\t\trevision: upgradeAction.input.revision,\n\t\t\t\t\t\t\ttimestampUtcMs: operation.timestampUtcMs\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpendingUpgrades.push({\n\t\t\t\t\t\t\taction: upgradeAction,\n\t\t\t\t\t\t\tupgradePath,\n\t\t\t\t\t\t\tindex: operation.index,\n\t\t\t\t\t\t\tsubsequentDeletes: []\n\t\t\t\t\t\t});\n\t\t\t\t\t} else document = applyUpgradeDocumentAction(document, upgradeAction, void 0);\n\t\t\t\t\tdocModule = this.registry.getModule(documentType, normalizeDocumentModelVersion(toVersion));\n\t\t\t\t} else if (operation.action.type === \"DELETE_DOCUMENT\" || operation.action.type === PURGE_DOCUMENT) {\n\t\t\t\t\tapplyDeleteDocumentAction(document, operation.action);\n\t\t\t\t\tfor (const pending of pendingUpgrades) pending.subsequentDeletes.push(operation.action);\n\t\t\t\t} else {\n\t\t\t\t\tconst protocolVersion = baseReducerVersion(document.header);\n\t\t\t\t\tdocument = withProtocolVersions(docModule.reducer(document, operation.action, void 0, {\n\t\t\t\t\t\tskip: operation.skip,\n\t\t\t\t\t\tprotocolVersion\n\t\t\t\t\t}), document.header.protocolVersions);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (scope === \"document\") {\n\t\t\tdocument = this.applyPendingUpgrades(document, pendingUpgrades, Number.MAX_SAFE_INTEGER);\n\t\t\tconst last = lastDocumentScopeOperation ?? await this.operationAt(documentId, \"document\", branch, startRevision, signal);\n\t\t\tdocument.operations = {\n\t\t\t\t...document.operations,\n\t\t\t\tdocument: last ? [last] : []\n\t\t\t};\n\t\t\treturn this.stampRevisions(document, documentId, scope, branch, targetRevision, signal);\n\t\t}\n\t\tif (keyframe) {\n\t\t\tconst resumeOperation = await this.operationAt(documentId, scope, branch, startRevision, signal);\n\t\t\tif (resumeOperation) document.operations = {\n\t\t\t\t...document.operations,\n\t\t\t\t[scope]: [resumeOperation]\n\t\t\t};\n\t\t}\n\t\tconst moduleCache = /* @__PURE__ */ new Map();\n\t\tconst getModuleCached = (version) => {\n\t\t\tconst key = version ?? 0;\n\t\t\tlet mod = moduleCache.get(key);\n\t\t\tif (!mod) {\n\t\t\t\tmod = this.registry.getModule(documentType, version);\n\t\t\t\tmoduleCache.set(key, mod);\n\t\t\t}\n\t\t\treturn mod;\n\t\t};\n\t\tconst finalVersion = validatedUpgrades.at(-1)?.toVersion ?? extractModuleVersion(document);\n\t\tlet cursor = void 0;\n\t\tconst pageSize = 100;\n\t\tlet hasMorePages;\n\t\tlet needsFullReplay = false;\n\t\tdo {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tconst paging = {\n\t\t\t\tcursor: cursor || \"0\",\n\t\t\t\tlimit: pageSize\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tconst result = await this.operationStore.getSince(documentId, scope, branch, startRevision, void 0, paging, signal);\n\t\t\t\tfor (const operation of result.results) {\n\t\t\t\t\tif (targetRevision !== void 0 && operation.index > targetRevision) break;\n\t\t\t\t\tif (keyframe && operation.skip > 0) {\n\t\t\t\t\t\tneedsFullReplay = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst moduleVersion = this.resolveModuleVersionForOp(operation.index, operation.timestampUtcMs, scope, validatedUpgrades, finalVersion);\n\t\t\t\t\tdocument = this.applyPendingUpgrades(document, pendingUpgrades, moduleVersion ?? Number.MAX_SAFE_INTEGER);\n\t\t\t\t\tif (isDenied(operation)) document = appendWithoutApplying(document, operation, scope);\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst protocolVersion = baseReducerVersion(document.header);\n\t\t\t\t\t\tdocument = withProtocolVersions(getModuleCached(moduleVersion).reducer(document, operation.action, void 0, {\n\t\t\t\t\t\t\tskip: operation.skip,\n\t\t\t\t\t\t\tprotocolVersion,\n\t\t\t\t\t\t\treplayOptions: { operation },\n\t\t\t\t\t\t\tskipIndexValidation: true\n\t\t\t\t\t\t}), document.header.protocolVersions);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst reachedTarget = targetRevision !== void 0 && result.results.some((op) => op.index >= targetRevision);\n\t\t\t\thasMorePages = Boolean(result.nextCursor) && !reachedTarget && !needsFullReplay;\n\t\t\t\tif (hasMorePages) cursor = result.nextCursor;\n\t\t\t} catch (err) {\n\t\t\t\tthrow new Error(`Failed to rebuild document ${documentId}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t\t}\n\t\t} while (hasMorePages);\n\t\tif (needsFullReplay) return this.coldMissRebuild(documentId, scope, branch, targetRevision, signal, false);\n\t\tdocument = this.applyTailPendingUpgrades(document, pendingUpgrades, scope, targetRevision);\n\t\tdocument = await this.stampRevisions(document, documentId, scope, branch, targetRevision, signal);\n\t\tif (pendingUpgrades.length > 0) {\n\t\t\tconst firstHeldBack = pendingUpgrades[0];\n\t\t\tconst stamped = document.header.revision[\"document\"] ?? 0;\n\t\t\tdocument.header.revision = {\n\t\t\t\t...document.header.revision,\n\t\t\t\tdocument: Math.min(stamped, firstHeldBack.index)\n\t\t\t};\n\t\t}\n\t\treturn document;\n\t}\n\t/**\n\t* Applies and removes every held-back upgrade whose target version is at or\n\t* below `throughVersion`, in the order the document scope recorded them.\n\t*/\n\tapplyPendingUpgrades(document, pendingUpgrades, throughVersion) {\n\t\twhile (pendingUpgrades.length > 0) {\n\t\t\tconst pending = pendingUpgrades[0];\n\t\t\tif (throughVersion < pending.action.input.toVersion) break;\n\t\t\tpendingUpgrades.shift();\n\t\t\tdocument = this.applyPendingUpgrade(document, pending);\n\t\t}\n\t\treturn document;\n\t}\n\t/**\n\t* Applies the remaining held-back upgrades after the requested scope's\n\t* replay has finished. A head read applies them all. A positional read\n\t* applies only those whose boundary for this scope lies at or before the\n\t* target position: applying a later one would label migrated state with a\n\t* pre-upgrade revision, and a keyframe stored from that poisons every\n\t* rebuild that resumes from it. Boundaries come from the upgrade's revision\n\t* snapshot; an upgrade without one records no position for this scope, and\n\t* the replay loop not having crossed it already places it past the target.\n\t*/\n\tapplyTailPendingUpgrades(document, pendingUpgrades, scope, targetRevision) {\n\t\twhile (pendingUpgrades.length > 0) {\n\t\t\tconst pending = pendingUpgrades[0];\n\t\t\tif (targetRevision !== void 0) {\n\t\t\t\tconst snapshot = pending.action.input.revision;\n\t\t\t\tif (snapshot === void 0) break;\n\t\t\t\tif ((snapshot[scope] ?? 0) > targetRevision) break;\n\t\t\t}\n\t\t\tpendingUpgrades.shift();\n\t\t\tdocument = this.applyPendingUpgrade(document, pending);\n\t\t}\n\t\treturn document;\n\t}\n\t/**\n\t* Applies one held-back upgrade, then re-applies the deletes the document\n\t* scope recorded after it so the hold-back cannot invert their order.\n\t*/\n\tapplyPendingUpgrade(document, pending) {\n\t\tdocument = applyUpgradeDocumentAction(document, pending.action, pending.upgradePath);\n\t\tfor (const deleteAction of pending.subsequentDeletes) document = applyDeleteDocumentAction(document, deleteAction);\n\t\treturn document;\n\t}\n\t/**\n\t* Copies the current document revisions onto the document. Overwrites the\n\t* requested scope revision with the target revision, if provided.\n\t*/\n\tasync stampRevisions(document, documentId, scope, branch, targetRevision, signal) {\n\t\tconst revisions = await this.operationStore.getRevisions(documentId, branch, signal);\n\t\tdocument.header.revision = revisions.revision;\n\t\tif (targetRevision !== void 0) document.header.revision = {\n\t\t\t...document.header.revision,\n\t\t\t[scope]: targetRevision + 1\n\t\t};\n\t\tdocument.header.lastModifiedAtUtcIso = revisions.latestTimestamp;\n\t\treturn document;\n\t}\n\t/** The stored operation at `index`, or undefined if it is no longer there. */\n\tasync operationAt(documentId, scope, branch, index, signal) {\n\t\tif (index < 0) return;\n\t\tconst operation = (await this.operationStore.getSince(documentId, scope, branch, index - 1, void 0, {\n\t\t\tcursor: \"0\",\n\t\t\tlimit: 1\n\t\t}, signal)).results[0];\n\t\treturn operation && operation.index === index ? operation : void 0;\n\t}\n\t/**\n\t* Resolves which module version to use for a given operation in phase 2.\n\t*\n\t* Uses the validated-upgrade boundary rules from D7:\n\t* - If `input.revision` is present: op.index < revision[scope] → before the upgrade boundary\n\t* - Otherwise: timestamp fallback\n\t* - Falls back to final module version when neither is decidable\n\t*/\n\tresolveModuleVersionForOp(opIndex, opTimestamp, scope, validatedUpgrades, finalVersion) {\n\t\tif (validatedUpgrades.length === 0) return finalVersion;\n\t\tlet currentVersion = validatedUpgrades[0]?.fromVersion;\n\t\tfor (const upgrade of validatedUpgrades) {\n\t\t\tlet beforeUpgrade;\n\t\t\tif (upgrade.revision !== void 0) beforeUpgrade = opIndex < (upgrade.revision[scope] ?? 0);\n\t\t\telse beforeUpgrade = opTimestamp < upgrade.timestampUtcMs;\n\t\t\tif (beforeUpgrade) return currentVersion;\n\t\t\tcurrentVersion = upgrade.toVersion;\n\t\t}\n\t\treturn currentVersion;\n\t}\n\tasync warmMissRebuild(baseDocument, baseRevision, documentId, scope, branch, targetRevision, signal) {\n\t\tconst documentType = baseDocument.header.documentType;\n\t\tconst docScopeNextIndex = baseDocument.header.revision[\"document\"] ?? 0;\n\t\tif ((await this.operationStore.getSince(documentId, \"document\", branch, docScopeNextIndex - 1, void 0, void 0, signal)).results.length > 0) return this.coldMissRebuild(documentId, scope, branch, targetRevision, signal);\n\t\tconst module = this.registry.getModule(documentType, extractModuleVersion(baseDocument));\n\t\tlet document = copyDocument(baseDocument);\n\t\tlet needsFullReplay = false;\n\t\ttry {\n\t\t\tconst pagedResults = await this.operationStore.getSince(documentId, scope, branch, baseRevision, void 0, void 0, signal);\n\t\t\tfor (const operation of pagedResults.results) {\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tif (targetRevision !== void 0 && operation.index > targetRevision) break;\n\t\t\t\tif (operation.skip > 0) {\n\t\t\t\t\tneedsFullReplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (isDenied(operation)) document = appendWithoutApplying(document, operation, scope);\n\t\t\t\telse {\n\t\t\t\t\tconst protocolVersion = baseReducerVersion(document.header);\n\t\t\t\t\tdocument = withProtocolVersions(module.reducer(document, operation.action, void 0, {\n\t\t\t\t\t\tskip: operation.skip,\n\t\t\t\t\t\tprotocolVersion,\n\t\t\t\t\t\treplayOptions: { operation },\n\t\t\t\t\t\tskipIndexValidation: true\n\t\t\t\t\t}), document.header.protocolVersions);\n\t\t\t\t}\n\t\t\t\tif (targetRevision !== void 0 && operation.index === targetRevision) break;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Failed to rebuild document ${documentId}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t}\n\t\tif (needsFullReplay) return this.coldMissRebuild(documentId, scope, branch, targetRevision, signal, false);\n\t\tconst revisions = await this.operationStore.getRevisions(documentId, branch, signal);\n\t\tdocument.header.revision = revisions.revision;\n\t\tif (targetRevision !== void 0) document.header.revision = {\n\t\t\t...document.header.revision,\n\t\t\t[scope]: targetRevision + 1\n\t\t};\n\t\tdocument.header.lastModifiedAtUtcIso = revisions.latestTimestamp;\n\t\treturn document;\n\t}\n\tfindNearestOlderSnapshot(snapshots, targetRevision) {\n\t\tlet nearest = void 0;\n\t\tfor (const snapshot of snapshots) if (snapshot.revision < targetRevision) {\n\t\t\tif (!nearest || snapshot.revision > nearest.revision) nearest = snapshot;\n\t\t}\n\t\treturn nearest;\n\t}\n\tmakeStreamKey(documentId, scope, branch) {\n\t\treturn `${documentId}:${scope}:${branch}`;\n\t}\n\tgetOrCreateStream(key) {\n\t\tlet stream = this.streams.get(key);\n\t\tif (!stream) {\n\t\t\tif (this.streams.size >= this.config.maxDocuments) {\n\t\t\t\tconst evictKey = this.lruTracker.evict();\n\t\t\t\tif (evictKey) this.streams.delete(evictKey);\n\t\t\t}\n\t\t\tstream = {\n\t\t\t\tkey,\n\t\t\t\tringBuffer: new RingBuffer(this.config.ringBufferSize)\n\t\t\t};\n\t\t\tthis.streams.set(key, stream);\n\t\t}\n\t\tthis.lruTracker.touch(key);\n\t\treturn stream;\n\t}\n\tisKeyframeRevision(revision) {\n\t\treturn revision > 0 && revision % this.config.keyframeInterval === 0;\n\t}\n};\n//#endregion\n//#region src/events/event-bus.ts\nvar EventBus = class {\n\teventTypeToSubscribers = /* @__PURE__ */ new Map();\n\tsubscribe(type, subscriber) {\n\t\tlet list = this.eventTypeToSubscribers.get(type);\n\t\tif (!list) {\n\t\t\tlist = [];\n\t\t\tthis.eventTypeToSubscribers.set(type, list);\n\t\t}\n\t\tlist.push(subscriber);\n\t\tlet done = false;\n\t\treturn () => {\n\t\t\tif (done) return;\n\t\t\tdone = true;\n\t\t\tconst arr = this.eventTypeToSubscribers.get(type);\n\t\t\tif (!arr) return;\n\t\t\tconst idx = arr.indexOf(subscriber);\n\t\t\tif (idx !== -1) arr.splice(idx, 1);\n\t\t\tif (arr.length === 0) this.eventTypeToSubscribers.delete(type);\n\t\t};\n\t}\n\tasync emit(type, data) {\n\t\tconst list = this.eventTypeToSubscribers.get(type);\n\t\tif (!list || list.length === 0) return;\n\t\tconst snapshot = list.slice();\n\t\tconst errors = [];\n\t\tfor (const fn of snapshot) try {\n\t\t\tawait Promise.resolve(fn(type, data));\n\t\t} catch (err) {\n\t\t\terrors.push(err);\n\t\t}\n\t\tif (errors.length > 0) throw new EventBusAggregateError(errors);\n\t}\n};\n//#endregion\n//#region src/storage/kysely/keyframe-store.ts\nvar KyselyKeyframeStore = class KyselyKeyframeStore {\n\tdb;\n\ttrx;\n\tconstructor(db) {\n\t\tthis.db = db;\n\t}\n\tget queryExecutor() {\n\t\treturn this.trx ?? this.db;\n\t}\n\twithTransaction(trx) {\n\t\tconst instance = new KyselyKeyframeStore(this.db);\n\t\tinstance.trx = trx;\n\t\treturn instance;\n\t}\n\tasync putKeyframe(documentId, scope, branch, revision, document, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst write = async (trx) => {\n\t\t\tawait acquirePurgeLocks(trx, [documentId], \"shared\");\n\t\t\tif ((await findPurged(trx, [documentId])).has(documentId)) return;\n\t\t\tawait trx.insertInto(\"Keyframe\").values({\n\t\t\t\tdocumentId,\n\t\t\t\tdocumentType: document.header.documentType,\n\t\t\t\tscope,\n\t\t\t\tbranch,\n\t\t\t\trevision,\n\t\t\t\tdocument\n\t\t\t}).onConflict((oc) => oc.columns([\n\t\t\t\t\"documentId\",\n\t\t\t\t\"scope\",\n\t\t\t\t\"branch\",\n\t\t\t\t\"revision\"\n\t\t\t]).doUpdateSet({ document })).execute();\n\t\t};\n\t\tif (this.trx) {\n\t\t\tawait write(this.trx);\n\t\t\treturn;\n\t\t}\n\t\tawait this.db.transaction().execute(write);\n\t}\n\tasync findNearestKeyframe(documentId, scope, branch, targetRevision, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst row = await this.queryExecutor.selectFrom(\"Keyframe\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"revision\", \"<=\", targetRevision).orderBy(\"revision\", \"desc\").limit(1).executeTakeFirst();\n\t\tif (!row) return;\n\t\treturn {\n\t\t\trevision: row.revision,\n\t\t\tdocument: row.document\n\t\t};\n\t}\n\tasync listKeyframes(documentId, scope, branch, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tlet query = this.queryExecutor.selectFrom(\"Keyframe\").selectAll().where(\"documentId\", \"=\", documentId).orderBy(\"revision\", \"asc\");\n\t\tif (scope !== void 0) query = query.where(\"scope\", \"=\", scope);\n\t\tif (branch !== void 0) query = query.where(\"branch\", \"=\", branch);\n\t\treturn (await query.execute()).map((row) => ({\n\t\t\tscope: row.scope,\n\t\t\tbranch: row.branch,\n\t\t\trevision: row.revision,\n\t\t\tdocument: row.document\n\t\t}));\n\t}\n\tasync deleteKeyframes(documentId, scope, branch, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tlet query = this.queryExecutor.deleteFrom(\"Keyframe\").where(\"documentId\", \"=\", documentId);\n\t\tif (scope !== void 0 && branch !== void 0) query = query.where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch);\n\t\telse if (scope !== void 0) query = query.where(\"scope\", \"=\", scope);\n\t\tconst result = await query.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows || 0n);\n\t}\n};\n//#endregion\n//#region src/storage/kysely/pagination.ts\nconst DEFAULT_LIMIT = 100;\nfunction paginateRows(rows, paging, cursorOf, toItem, refetch) {\n\tlet hasMore = false;\n\tlet items = rows;\n\tif (paging?.limit && rows.length > paging.limit) {\n\t\thasMore = true;\n\t\titems = rows.slice(0, paging.limit);\n\t}\n\tconst nextCursor = hasMore && items.length > 0 ? cursorOf(items[items.length - 1]).toString() : void 0;\n\tconst cursor = paging?.cursor || \"0\";\n\tconst limit = paging?.limit || DEFAULT_LIMIT;\n\treturn {\n\t\tresults: items.map(toItem),\n\t\toptions: {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t},\n\t\tnextCursor,\n\t\tnext: hasMore ? () => refetch(nextCursor, limit) : void 0\n\t};\n}\n//#endregion\n//#region src/storage/txn.ts\nvar AtomicTransaction = class {\n\tdocumentId;\n\tdocumentType;\n\tscope;\n\tbranch;\n\tbaseRevision;\n\toperations = [];\n\tconstructor(documentId, documentType, scope, branch, baseRevision) {\n\t\tthis.documentId = documentId;\n\t\tthis.documentType = documentType;\n\t\tthis.scope = scope;\n\t\tthis.branch = branch;\n\t\tthis.baseRevision = baseRevision;\n\t}\n\taddOperations(...operations) {\n\t\tfor (const op of operations) this.operations.push({\n\t\t\tjobId: v4(),\n\t\t\topId: op.id,\n\t\t\tprevOpId: \"\",\n\t\t\tdocumentId: this.documentId,\n\t\t\tdocumentType: this.documentType,\n\t\t\tscope: this.scope,\n\t\t\tbranch: this.branch,\n\t\t\ttimestampUtcMs: new Date(op.timestampUtcMs),\n\t\t\tindex: op.index,\n\t\t\taction: JSON.stringify(op.action),\n\t\t\tskip: op.skip,\n\t\t\terror: op.error || null,\n\t\t\tdeniedReason: op.deniedReason || null,\n\t\t\thash: op.hash\n\t\t});\n\t}\n\tgetOperations() {\n\t\treturn this.operations;\n\t}\n};\n//#endregion\n//#region src/storage/kysely/store.ts\nvar _UniqueConstraintContext = class extends Error {\n\tdocumentId;\n\tscope;\n\tbranch;\n\trevision;\n\tstagedOps;\n\tconstructor(documentId, scope, branch, revision, stagedOps) {\n\t\tsuper(\"unique constraint\");\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.branch = branch;\n\t\tthis.revision = revision;\n\t\tthis.stagedOps = stagedOps;\n\t\tthis.name = \"UniqueConstraintContext\";\n\t}\n};\nfunction duplicateOf(ctx) {\n\tconst op = ctx.stagedOps[0];\n\treturn new DuplicateOperationError(`${op.opId} at index ${op.index} with skip ${op.skip}`);\n}\nvar KyselyOperationStore = class KyselyOperationStore {\n\tdb;\n\ttrx;\n\tliveIds;\n\tconstructor(db) {\n\t\tthis.db = db;\n\t}\n\tget queryExecutor() {\n\t\treturn this.trx ?? this.db;\n\t}\n\t/** `liveIds`: ids the transaction read untombstoned under its shared lock. */\n\twithTransaction(trx, liveIds) {\n\t\tconst instance = new KyselyOperationStore(this.db);\n\t\tinstance.trx = trx;\n\t\tinstance.liveIds = liveIds;\n\t\treturn instance;\n\t}\n\tasync apply(documentId, documentType, scope, branch, revision, fn, signal, condition) {\n\t\tif (this.trx) {\n\t\t\tlet executeResult = null;\n\t\t\tlet uniqueCtx = null;\n\t\t\ttry {\n\t\t\t\texecuteResult = await this.executeApply(this.trx, documentId, documentType, scope, branch, revision, fn, signal, condition);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof _UniqueConstraintContext) uniqueCtx = error;\n\t\t\t\telse throw error;\n\t\t\t}\n\t\t\tif (uniqueCtx !== null) throw duplicateOf(uniqueCtx);\n\t\t\treturn executeResult;\n\t\t} else {\n\t\t\tlet transactionResult = null;\n\t\t\tlet uniqueCtx = null;\n\t\t\ttry {\n\t\t\t\ttransactionResult = await this.db.transaction().execute(async (trx) => {\n\t\t\t\t\treturn this.executeApply(trx, documentId, documentType, scope, branch, revision, fn, signal, condition);\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof _UniqueConstraintContext) uniqueCtx = error;\n\t\t\t\telse throw error;\n\t\t\t}\n\t\t\tif (uniqueCtx !== null) return this.resolveUniqueConstraint(uniqueCtx);\n\t\t\treturn transactionResult;\n\t\t}\n\t}\n\tasync resolveUniqueConstraint(ctx) {\n\t\tlet replayOps = null;\n\t\ttry {\n\t\t\treplayOps = await this.findIdempotentReplay(this.db, ctx.documentId, ctx.scope, ctx.branch, ctx.revision, ctx.stagedOps);\n\t\t} catch {}\n\t\tif (replayOps !== null) return replayOps;\n\t\tthrow duplicateOf(ctx);\n\t}\n\tasync executeApply(trx, documentId, documentType, scope, branch, revision, fn, signal, condition) {\n\t\tthrowIfAborted(signal);\n\t\tconst atomicTxn = new AtomicTransaction(documentId, documentType, scope, branch, revision);\n\t\tawait fn(atomicTxn);\n\t\tconst operations = atomicTxn.getOperations();\n\t\tif (operations.length === 0) return [];\n\t\tconst purgedHead = this.liveIds?.has(documentId) ? void 0 : await this.refusePurgedAppend(trx, documentId, operations);\n\t\tif (purgedHead !== void 0) return purgedHead;\n\t\tif (condition) await this.acquireStreamLocks(trx, documentId, scope, branch, condition);\n\t\tconst latestOp = await trx.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).orderBy(\"index\", \"desc\").limit(1).executeTakeFirst();\n\t\tconst currentRevision = latestOp ? latestOp.index : -1;\n\t\tif (currentRevision !== revision - 1) {\n\t\t\tlet replayOps = null;\n\t\t\ttry {\n\t\t\t\treplayOps = await this.findIdempotentReplay(trx, documentId, scope, branch, revision, operations);\n\t\t\t} catch {}\n\t\t\tif (replayOps !== null) return replayOps;\n\t\t\tif (revision === 0 && this.isCreate(operations)) throw new DocumentAlreadyExistsError(documentId, scope, currentRevision);\n\t\t\tthrow new RevisionMismatchError(currentRevision + 1, revision);\n\t\t}\n\t\tlet prevOpId = latestOp?.opId || \"\";\n\t\tfor (const op of operations) {\n\t\t\top.prevOpId = prevOpId;\n\t\t\tprevOpId = op.opId;\n\t\t}\n\t\tlet insertedCount = operations.length;\n\t\ttry {\n\t\t\tif (condition && condition.streams.length > 0) insertedCount = await this.insertGuarded(trx, operations, condition);\n\t\t\telse await trx.insertInto(\"Operation\").values(operations).execute();\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && error.message.includes(\"unique constraint\")) throw new _UniqueConstraintContext(documentId, scope, branch, revision, operations);\n\t\t\tthrow error;\n\t\t}\n\t\tif (insertedCount !== operations.length) throw new AppendConditionFailedError(condition);\n\t\treturn operations.map((op) => ({\n\t\t\tindex: op.index,\n\t\t\ttimestampUtcMs: op.timestampUtcMs.toISOString(),\n\t\t\thash: op.hash,\n\t\t\tskip: op.skip,\n\t\t\terror: op.error || void 0,\n\t\t\tdeniedReason: op.deniedReason || void 0,\n\t\t\tid: op.opId,\n\t\t\taction: JSON.parse(op.action)\n\t\t}));\n\t}\n\t/**\n\t* Locks the written stream and every read-set stream, in sorted key order\n\t* so that overlapping concurrent appends serialize rather than deadlock.\n\t* The locks are still taken one row at a time, so the query preserves that\n\t* order. It must stay separate from the guarded insert, which would\n\t* otherwise read a snapshot taken before the locks were held.\n\t*/\n\tasync acquireStreamLocks(trx, documentId, scope, branch, condition) {\n\t\tconst keys = /* @__PURE__ */ new Set([`${documentId}:${scope}:${branch}`]);\n\t\tfor (const stream of condition.streams) keys.add(`${stream.documentId}:${stream.scope}:${stream.branch}`);\n\t\tconst sortedKeys = sql.join([...keys].sort());\n\t\tawait sql`\n with ordered as materialized (\n select key\n from unnest(array[${sortedKeys}]::text[]) with ordinality as t(key, ord)\n order by ord\n )\n select pg_advisory_xact_lock(hashtext(key)) from ordered\n `.execute(trx);\n\t}\n\t/**\n\t* Inserts the staged operations with the condition compiled in as a WHERE\n\t* NOT EXISTS guard, making the check and the append one statement. Returns\n\t* the rows inserted; zero means the guard failed and nothing was written.\n\t*/\n\tasync insertGuarded(trx, operations, condition) {\n\t\tconst branches = operations.map((op) => trx.selectNoFrom([\n\t\t\tsql`${op.jobId}::text`.as(\"jobId\"),\n\t\t\tsql`${op.opId}::text`.as(\"opId\"),\n\t\t\tsql`${op.prevOpId}::text`.as(\"prevOpId\"),\n\t\t\tsql`${op.documentId}::text`.as(\"documentId\"),\n\t\t\tsql`${op.documentType}::text`.as(\"documentType\"),\n\t\t\tsql`${op.scope}::text`.as(\"scope\"),\n\t\t\tsql`${op.branch}::text`.as(\"branch\"),\n\t\t\tsql`${op.timestampUtcMs}::timestamptz`.as(\"timestampUtcMs\"),\n\t\t\tsql`${op.index}::integer`.as(\"index\"),\n\t\t\tsql`${op.action}::jsonb`.as(\"action\"),\n\t\t\tsql`${op.skip}::integer`.as(\"skip\"),\n\t\t\tsql`${op.error ?? null}::text`.as(\"error\"),\n\t\t\tsql`${op.deniedReason ?? null}::text`.as(\"deniedReason\"),\n\t\t\tsql`${op.hash}::text`.as(\"hash\")\n\t\t]).where((eb) => eb.not(eb.exists(eb.selectFrom(\"Operation\").select(\"Operation.id\").where((web) => web.or(condition.streams.map((s) => web.and([\n\t\t\tweb(\"Operation.documentId\", \"=\", s.documentId),\n\t\t\tweb(\"Operation.scope\", \"=\", s.scope),\n\t\t\tweb(\"Operation.branch\", \"=\", s.branch),\n\t\t\tweb(\"Operation.index\", \">\", s.revision)\n\t\t]))))))));\n\t\tlet expression = branches[0];\n\t\tfor (let i = 1; i < branches.length; i++) expression = expression.unionAll(branches[i]);\n\t\treturn (await trx.insertInto(\"Operation\").columns([\n\t\t\t\"jobId\",\n\t\t\t\"opId\",\n\t\t\t\"prevOpId\",\n\t\t\t\"documentId\",\n\t\t\t\"documentType\",\n\t\t\t\"scope\",\n\t\t\t\"branch\",\n\t\t\t\"timestampUtcMs\",\n\t\t\t\"index\",\n\t\t\t\"action\",\n\t\t\t\"skip\",\n\t\t\t\"error\",\n\t\t\t\"deniedReason\",\n\t\t\t\"hash\"\n\t\t]).expression(expression).returning(\"id\").execute()).length;\n\t}\n\tasync findIdempotentReplay(executor, documentId, scope, branch, revision, stagedOps) {\n\t\tconst minIndex = revision;\n\t\tconst maxIndex = revision + stagedOps.length - 1;\n\t\tconst storedRows = await executor.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"index\", \">=\", minIndex).where(\"index\", \"<=\", maxIndex).orderBy(\"index\", \"asc\").execute();\n\t\tif (storedRows.length !== stagedOps.length) return null;\n\t\tfor (let i = 0; i < stagedOps.length; i++) {\n\t\t\tconst staged = stagedOps[i];\n\t\t\tconst stored = storedRows[i];\n\t\t\tif (stored.opId !== staged.opId || stored.index !== staged.index || stored.skip !== staged.skip) return null;\n\t\t}\n\t\treturn storedRows.map((row) => this.rowToOperation(row));\n\t}\n\t/** A purged stream refuses appends; a marker gets the stored one back. */\n\tasync refusePurgedAppend(trx, documentId, operations) {\n\t\tif (!(await findPurged(trx, [documentId])).has(documentId)) return;\n\t\tif (!operations.every((operation) => this.isMarker(operation))) throw new DocumentPurgedError(documentId);\n\t\treturn (await trx.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(sql`action->>'type' = ${PURGE_DOCUMENT}`).orderBy(\"index\", \"asc\").execute()).map((row) => this.rowToOperation(row));\n\t}\n\tisMarker(operation) {\n\t\treturn this.actionType(operation) === PURGE_DOCUMENT;\n\t}\n\tactionType(operation) {\n\t\tlet action = operation.action;\n\t\tif (typeof action === \"string\") try {\n\t\t\taction = JSON.parse(action);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (typeof action === \"object\" && action !== null && \"type\" in action && typeof action.type === \"string\") return action.type;\n\t}\n\t/** True when the staged write creates a document rather than appending to one. */\n\tisCreate(operations) {\n\t\tfor (const operation of operations) {\n\t\t\tlet action = operation.action;\n\t\t\tif (typeof action === \"string\") try {\n\t\t\t\taction = JSON.parse(action);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (typeof action === \"object\" && action !== null && \"type\" in action && typeof action.type === \"string\" && action.type === \"CREATE_DOCUMENT\") return true;\n\t\t}\n\t\treturn false;\n\t}\n\t/**\n\t* The paging cursor here encodes the index to resume from (one past the\n\t* last row returned), not the last row's own index. This keeps \"0\" an\n\t* unambiguous start-of-stream sentinel even when a page ends at index 0\n\t* (e.g. `limit: 1` on a fresh stream), which would otherwise make\n\t* `nextCursor` equal the start cursor and loop a caller that walks pages\n\t* forever.\n\t*/\n\tasync getSince(documentId, scope, branch, revision, filter, paging, signal) {\n\t\tthrowIfAborted(signal);\n\t\tlet query = this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"index\", \">\", revision).orderBy(\"index\", \"asc\");\n\t\tif (filter) {\n\t\t\tif (filter.actionTypes && filter.actionTypes.length > 0) {\n\t\t\t\tconst actionTypesArray = filter.actionTypes.map((t) => `'${t.replace(/'/g, \"''\")}'`).join(\",\");\n\t\t\t\tquery = query.where(sql`action->>'type' = ANY(ARRAY[${sql.raw(actionTypesArray)}]::text[])`);\n\t\t\t}\n\t\t\tif (filter.timestampFrom) query = query.where(\"timestampUtcMs\", \">=\", new Date(filter.timestampFrom));\n\t\t\tif (filter.timestampTo) query = query.where(\"timestampUtcMs\", \"<=\", new Date(filter.timestampTo));\n\t\t\tif (filter.sinceRevision !== void 0) query = query.where(\"index\", \">=\", filter.sinceRevision);\n\t\t}\n\t\tif (paging) {\n\t\t\tconst cursorValue = Number.parseInt(paging.cursor, 10);\n\t\t\tif (Number.isFinite(cursorValue) && cursorValue > 0) query = query.where(\"index\", \">=\", cursorValue);\n\t\t\tif (paging.limit) query = query.limit(paging.limit + 1);\n\t\t}\n\t\treturn paginateRows(await query.execute(), paging, (row) => row.index + 1, (row) => this.rowToOperation(row), (cursor, limit) => this.getSince(documentId, scope, branch, revision, filter, {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t}, signal));\n\t}\n\tasync getSinceId(id, paging, signal) {\n\t\tthrowIfAborted(signal);\n\t\tlet query = this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"id\", \">\", id).orderBy(\"id\", \"asc\");\n\t\tif (paging) {\n\t\t\tconst cursorValue = Number.parseInt(paging.cursor, 10);\n\t\t\tif (cursorValue > 0) query = query.where(\"id\", \">\", cursorValue);\n\t\t\tif (paging.limit) query = query.limit(paging.limit + 1);\n\t\t}\n\t\treturn paginateRows(await query.execute(), paging, (row) => row.id, (row) => this.rowToOperationWithContext(row), (cursor, limit) => this.getSinceId(id, {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t}, signal));\n\t}\n\t/**\n\t* The paging cursor here encodes the index to resume from (one past the\n\t* last row returned), not the last row's own index, for the same reason as\n\t* `getSince`: a page ending at index 0 must not produce a cursor that is\n\t* indistinguishable from the start-of-stream sentinel.\n\t*/\n\tasync getConflicting(documentId, scope, branch, minTimestamp, paging, signal) {\n\t\tthrowIfAborted(signal);\n\t\tlet query = this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"timestampUtcMs\", \">=\", new Date(minTimestamp)).orderBy(\"index\", \"asc\");\n\t\tif (paging) {\n\t\t\tconst cursorValue = Number.parseInt(paging.cursor, 10);\n\t\t\tif (Number.isFinite(cursorValue) && cursorValue > 0) query = query.where(\"index\", \">=\", cursorValue);\n\t\t\tif (paging.limit) query = query.limit(paging.limit + 1);\n\t\t}\n\t\treturn paginateRows(await query.execute(), paging, (row) => row.index + 1, (row) => this.rowToOperation(row), (cursor, limit) => this.getConflicting(documentId, scope, branch, minTimestamp, {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t}, signal));\n\t}\n\tasync getRevisions(documentId, branch, signal) {\n\t\tthrowIfAborted(signal);\n\t\tconst scopeRevisions = await this.queryExecutor.selectFrom(\"Operation\").select(\"scope\").select((eb) => eb.fn.max(\"index\").as(\"index\")).where(\"documentId\", \"=\", documentId).where(\"branch\", \"=\", branch).groupBy(\"scope\").execute();\n\t\tconst latest = await this.queryExecutor.selectFrom(\"Operation\").select((eb) => eb.fn.max(\"timestampUtcMs\").as(\"latestTimestamp\")).where(\"documentId\", \"=\", documentId).where(\"branch\", \"=\", branch).executeTakeFirst();\n\t\tconst revision = {};\n\t\tfor (const row of scopeRevisions) revision[row.scope] = row.index + 1;\n\t\treturn {\n\t\t\trevision,\n\t\t\tlatestTimestamp: latest?.latestTimestamp ? new Date(latest.latestTimestamp).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString()\n\t\t};\n\t}\n\tasync getStreamLatestTimestamp(documentId, scope, branch, signal) {\n\t\tconst latest = await this.queryExecutor.selectFrom(\"Operation\").select((eb) => eb.fn.max(\"timestampUtcMs\").as(\"latestTimestamp\")).where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).executeTakeFirst();\n\t\treturn latest?.latestTimestamp ? new Date(latest.latestTimestamp).toISOString() : void 0;\n\t}\n\tasync findOperationIds(documentId, scope, branch, opIds, signal) {\n\t\tthrowIfAborted(signal);\n\t\tif (opIds.length === 0) return /* @__PURE__ */ new Set();\n\t\tconst rows = await this.queryExecutor.selectFrom(\"Operation\").select(\"opId\").distinct().where(\"opId\", \"in\", opIds).where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).execute();\n\t\treturn new Set(rows.map((row) => row.opId));\n\t}\n\tasync getOperationsByIds(documentId, scope, branch, opIds, signal) {\n\t\tthrowIfAborted(signal);\n\t\tif (opIds.length === 0) return [];\n\t\tconst rows = await this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"opId\", \"in\", opIds).where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).orderBy(\"index\", \"asc\").execute();\n\t\tconst latest = /* @__PURE__ */ new Map();\n\t\tfor (const row of rows) latest.set(row.opId, this.rowToOperation(row));\n\t\treturn [...latest.values()];\n\t}\n\trowToOperation(row) {\n\t\treturn {\n\t\t\tindex: row.index,\n\t\t\ttimestampUtcMs: row.timestampUtcMs.toISOString(),\n\t\t\thash: row.hash,\n\t\t\tskip: row.skip,\n\t\t\terror: row.error || void 0,\n\t\t\tdeniedReason: row.deniedReason || void 0,\n\t\t\tid: row.opId,\n\t\t\taction: row.action\n\t\t};\n\t}\n\trowToOperationWithContext(row) {\n\t\treturn {\n\t\t\toperation: this.rowToOperation(row),\n\t\t\tcontext: {\n\t\t\t\tdocumentId: row.documentId,\n\t\t\t\tdocumentType: row.documentType,\n\t\t\t\tscope: row.scope,\n\t\t\t\tbranch: row.branch,\n\t\t\t\tordinal: row.id\n\t\t\t}\n\t\t};\n\t}\n};\n//#endregion\n//#region src/storage/pool-instrumentation.ts\n/**\n* Wraps an existing pg.Pool with acquire-wait timing and an event\n* subscription surface. The pool is mutated in place: pool.connect()\n* is replaced with a timing wrapper so all callers (Kysely included)\n* pick up the instrumentation transparently.\n*/\nfunction instrumentPgPool(pool, name) {\n\tconst listeners = /* @__PURE__ */ new Set();\n\tconst originalConnect = pool.connect.bind(pool);\n\tconst wrappedConnect = async () => {\n\t\tconst start = performance.now();\n\t\tconst client = await originalConnect();\n\t\tconst durationMs = performance.now() - start;\n\t\tfor (const listener of listeners) try {\n\t\t\tlistener(durationMs);\n\t\t} catch {}\n\t\treturn client;\n\t};\n\tpool.connect = wrappedConnect;\n\treturn {\n\t\tname,\n\t\tgetStats() {\n\t\t\treturn {\n\t\t\t\tsize: pool.totalCount,\n\t\t\t\tidle: pool.idleCount,\n\t\t\t\twaiting: pool.waitingCount\n\t\t\t};\n\t\t},\n\t\tonAcquire(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t}\n\t};\n}\nfunction createForwardingPoolInstrumentation(name) {\n\tconst listeners = /* @__PURE__ */ new Set();\n\tlet stats = {\n\t\tsize: 0,\n\t\tidle: 0,\n\t\twaiting: 0\n\t};\n\treturn {\n\t\tname,\n\t\tgetStats() {\n\t\t\treturn stats;\n\t\t},\n\t\tonAcquire(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tpushSamples(durations) {\n\t\t\tfor (const durationMs of durations) for (const listener of listeners) try {\n\t\t\t\tlistener(durationMs);\n\t\t\t} catch {}\n\t\t},\n\t\tupdateStats(next) {\n\t\t\tstats = next;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/storage/migrations/001_create_operation_table.ts\nvar _001_create_operation_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$25 });\nasync function up$25(db) {\n\tawait db.schema.createTable(\"Operation\").addColumn(\"id\", \"serial\", (col) => col.primaryKey()).addColumn(\"jobId\", \"text\", (col) => col.notNull()).addColumn(\"opId\", \"text\", (col) => col.notNull()).addColumn(\"prevOpId\", \"text\", (col) => col.notNull()).addColumn(\"writeTimestampUtcMs\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"timestampUtcMs\", \"timestamptz\", (col) => col.notNull()).addColumn(\"index\", \"integer\", (col) => col.notNull()).addColumn(\"action\", \"jsonb\", (col) => col.notNull()).addColumn(\"skip\", \"integer\", (col) => col.notNull()).addColumn(\"error\", \"text\").addColumn(\"hash\", \"text\", (col) => col.notNull()).addUniqueConstraint(\"unique_revision\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"index\"\n\t]).addUniqueConstraint(\"unique_operation_instance\", [\n\t\t\"opId\",\n\t\t\"index\",\n\t\t\"skip\"\n\t]).execute();\n\tawait db.schema.createIndex(\"streamOperations\").on(\"Operation\").columns([\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"id\"\n\t]).execute();\n\tawait db.schema.createIndex(\"branchlessStreamOperations\").on(\"Operation\").columns([\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"id\"\n\t]).execute();\n}\n//#endregion\n//#region src/storage/migrations/002_create_keyframe_table.ts\nvar _002_create_keyframe_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$24 });\nasync function up$24(db) {\n\tawait db.schema.createTable(\"Keyframe\").addColumn(\"id\", \"serial\", (col) => col.primaryKey()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"revision\", \"integer\", (col) => col.notNull()).addColumn(\"document\", \"jsonb\", (col) => col.notNull()).addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addUniqueConstraint(\"unique_keyframe\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"revision\"\n\t]).execute();\n\tawait db.schema.createIndex(\"keyframe_lookup\").on(\"Keyframe\").columns([\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"revision\"\n\t]).execute();\n}\n//#endregion\n//#region src/storage/migrations/003_create_document_table.ts\nvar _003_create_document_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$23 });\nasync function up$23(db) {\n\tawait db.schema.createTable(\"Document\").addColumn(\"id\", \"text\", (col) => col.primaryKey()).addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/004_create_document_relationship_table.ts\nvar _004_create_document_relationship_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$22 });\nasync function up$22(db) {\n\tawait db.schema.createTable(\"DocumentRelationship\").addColumn(\"id\", \"text\", (col) => col.primaryKey()).addColumn(\"sourceId\", \"text\", (col) => col.notNull().references(\"Document.id\").onDelete(\"cascade\")).addColumn(\"targetId\", \"text\", (col) => col.notNull().references(\"Document.id\").onDelete(\"cascade\")).addColumn(\"relationshipType\", \"text\", (col) => col.notNull()).addColumn(\"metadata\", \"jsonb\").addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addUniqueConstraint(\"unique_source_target_type\", [\n\t\t\"sourceId\",\n\t\t\"targetId\",\n\t\t\"relationshipType\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_relationship_source\").on(\"DocumentRelationship\").column(\"sourceId\").execute();\n\tawait db.schema.createIndex(\"idx_relationship_target\").on(\"DocumentRelationship\").column(\"targetId\").execute();\n\tawait db.schema.createIndex(\"idx_relationship_type\").on(\"DocumentRelationship\").column(\"relationshipType\").execute();\n}\n//#endregion\n//#region src/storage/migrations/005_create_indexer_state_table.ts\nvar _005_create_indexer_state_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$21 });\nasync function up$21(db) {\n\tawait db.schema.createTable(\"IndexerState\").addColumn(\"id\", \"integer\", (col) => col.primaryKey().generatedAlwaysAsIdentity()).addColumn(\"lastOperationId\", \"integer\", (col) => col.notNull()).addColumn(\"lastOperationTimestamp\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/006_create_document_snapshot_table.ts\nvar _006_create_document_snapshot_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$20 });\nasync function up$20(db) {\n\tawait db.schema.createTable(\"DocumentSnapshot\").addColumn(\"id\", \"text\", (col) => col.primaryKey()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"slug\", \"text\").addColumn(\"name\", \"text\").addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"content\", \"jsonb\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"lastOperationIndex\", \"integer\", (col) => col.notNull()).addColumn(\"lastOperationHash\", \"text\", (col) => col.notNull()).addColumn(\"lastUpdatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"snapshotVersion\", \"integer\", (col) => col.notNull().defaultTo(1)).addColumn(\"identifiers\", \"jsonb\").addColumn(\"metadata\", \"jsonb\").addColumn(\"isDeleted\", \"boolean\", (col) => col.notNull().defaultTo(false)).addColumn(\"deletedAt\", \"timestamptz\").addUniqueConstraint(\"unique_doc_scope_branch\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_slug_scope_branch\").on(\"DocumentSnapshot\").columns([\n\t\t\"slug\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_doctype_scope_branch\").on(\"DocumentSnapshot\").columns([\n\t\t\"documentType\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_last_updated\").on(\"DocumentSnapshot\").column(\"lastUpdatedAt\").execute();\n\tawait db.schema.createIndex(\"idx_is_deleted\").on(\"DocumentSnapshot\").column(\"isDeleted\").execute();\n}\n//#endregion\n//#region src/storage/migrations/007_create_slug_mapping_table.ts\nvar _007_create_slug_mapping_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$19 });\nasync function up$19(db) {\n\tawait db.schema.createTable(\"SlugMapping\").addColumn(\"slug\", \"text\", (col) => col.primaryKey()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addUniqueConstraint(\"unique_docid_scope_branch\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_slug_documentid\").on(\"SlugMapping\").column(\"documentId\").execute();\n}\n//#endregion\n//#region src/storage/migrations/008_create_view_state_table.ts\nvar _008_create_view_state_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$18 });\nasync function up$18(db) {\n\tawait db.schema.createTable(\"ViewState\").addColumn(\"readModelId\", \"text\", (col) => col.primaryKey()).addColumn(\"lastOrdinal\", \"integer\", (col) => col.notNull().defaultTo(0)).addColumn(\"lastOperationTimestamp\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/009_create_operation_index_tables.ts\nvar _009_create_operation_index_tables_exports = /* @__PURE__ */ __exportAll({ up: () => up$17 });\nasync function up$17(db) {\n\tawait db.schema.createTable(\"document_collections\").addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"collectionId\", \"text\", (col) => col.notNull()).addColumn(\"joinedOrdinal\", \"bigint\", (col) => col.notNull().defaultTo(0)).addColumn(\"leftOrdinal\", \"bigint\").addPrimaryKeyConstraint(\"document_collections_pkey\", [\"documentId\", \"collectionId\"]).execute();\n\tawait db.schema.createIndex(\"idx_document_collections_collectionId\").on(\"document_collections\").column(\"collectionId\").execute();\n\tawait db.schema.createIndex(\"idx_doc_collections_collection_range\").on(\"document_collections\").columns([\"collectionId\", \"joinedOrdinal\"]).execute();\n\tawait db.schema.createTable(\"operation_index_operations\").addColumn(\"ordinal\", \"serial\", (col) => col.primaryKey()).addColumn(\"opId\", \"text\", (col) => col.notNull()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"timestampUtcMs\", \"text\", (col) => col.notNull()).addColumn(\"writeTimestampUtcMs\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"index\", \"integer\", (col) => col.notNull()).addColumn(\"skip\", \"integer\", (col) => col.notNull()).addColumn(\"hash\", \"text\", (col) => col.notNull()).addColumn(\"action\", \"jsonb\", (col) => col.notNull()).execute();\n\tawait db.schema.createIndex(\"idx_operation_index_operations_document\").on(\"operation_index_operations\").columns([\n\t\t\"documentId\",\n\t\t\"branch\",\n\t\t\"scope\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_operation_index_operations_ordinal\").on(\"operation_index_operations\").column(\"ordinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/010_create_sync_tables.ts\nvar _010_create_sync_tables_exports = /* @__PURE__ */ __exportAll({ up: () => up$16 });\nasync function up$16(db) {\n\tawait db.schema.createTable(\"sync_remotes\").addColumn(\"name\", \"text\", (col) => col.primaryKey()).addColumn(\"collection_id\", \"text\", (col) => col.notNull()).addColumn(\"channel_type\", \"text\", (col) => col.notNull()).addColumn(\"channel_id\", \"text\", (col) => col.notNull().defaultTo(\"\")).addColumn(\"remote_name\", \"text\", (col) => col.notNull().defaultTo(\"\")).addColumn(\"channel_parameters\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'{}'::jsonb`)).addColumn(\"filter_document_ids\", \"jsonb\").addColumn(\"filter_scopes\", \"jsonb\").addColumn(\"filter_branch\", \"text\", (col) => col.notNull().defaultTo(\"main\")).addColumn(\"push_state\", \"text\", (col) => col.notNull().defaultTo(\"idle\")).addColumn(\"push_last_success_utc_ms\", \"text\").addColumn(\"push_last_failure_utc_ms\", \"text\").addColumn(\"push_failure_count\", \"integer\", (col) => col.notNull().defaultTo(0)).addColumn(\"pull_state\", \"text\", (col) => col.notNull().defaultTo(\"idle\")).addColumn(\"pull_last_success_utc_ms\", \"text\").addColumn(\"pull_last_failure_utc_ms\", \"text\").addColumn(\"pull_failure_count\", \"integer\", (col) => col.notNull().defaultTo(0)).addColumn(\"created_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updated_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n\tawait db.schema.createIndex(\"idx_sync_remotes_collection\").on(\"sync_remotes\").column(\"collection_id\").execute();\n\tawait db.schema.createTable(\"sync_cursors\").addColumn(\"remote_name\", \"text\", (col) => col.primaryKey().references(\"sync_remotes.name\").onDelete(\"cascade\")).addColumn(\"cursor_ordinal\", \"bigint\", (col) => col.notNull().defaultTo(0)).addColumn(\"last_synced_at_utc_ms\", \"text\").addColumn(\"updated_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n\tawait db.schema.createIndex(\"idx_sync_cursors_ordinal\").on(\"sync_cursors\").column(\"cursor_ordinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/011_add_cursor_type_column.ts\nvar _011_add_cursor_type_column_exports = /* @__PURE__ */ __exportAll({ up: () => up$15 });\nasync function up$15(db) {\n\tawait db.deleteFrom(\"sync_cursors\").where(\"remote_name\", \"like\", \"outbox::%\").execute();\n\tawait db.deleteFrom(\"sync_remotes\").where(\"name\", \"like\", \"outbox::%\").execute();\n\tawait db.schema.dropTable(\"sync_cursors\").execute();\n\tawait db.schema.createTable(\"sync_cursors\").addColumn(\"remote_name\", \"text\", (col) => col.notNull()).addColumn(\"cursor_type\", \"text\", (col) => col.notNull().defaultTo(\"inbox\")).addColumn(\"cursor_ordinal\", \"bigint\", (col) => col.notNull().defaultTo(0)).addColumn(\"last_synced_at_utc_ms\", \"text\").addColumn(\"updated_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addPrimaryKeyConstraint(\"sync_cursors_pk\", [\"remote_name\", \"cursor_type\"]).execute();\n\tawait db.schema.createIndex(\"idx_sync_cursors_ordinal\").on(\"sync_cursors\").column(\"cursor_ordinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/012_add_source_remote_column.ts\nvar _012_add_source_remote_column_exports = /* @__PURE__ */ __exportAll({ up: () => up$14 });\nasync function up$14(db) {\n\tawait db.schema.alterTable(\"operation_index_operations\").addColumn(\"sourceRemote\", \"text\", (col) => col.notNull().defaultTo(\"\")).execute();\n}\n//#endregion\n//#region src/storage/migrations/013_create_sync_dead_letters_table.ts\nvar _013_create_sync_dead_letters_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$13 });\nasync function up$13(db) {\n\tawait db.schema.createTable(\"sync_dead_letters\").addColumn(\"ordinal\", \"serial\", (col) => col.primaryKey()).addColumn(\"id\", \"text\", (col) => col.unique().notNull()).addColumn(\"job_id\", \"text\", (col) => col.notNull()).addColumn(\"job_dependencies\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'[]'::jsonb`)).addColumn(\"remote_name\", \"text\", (col) => col.notNull().references(\"sync_remotes.name\").onDelete(\"cascade\")).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"scopes\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'[]'::jsonb`)).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"operations\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'[]'::jsonb`)).addColumn(\"error_source\", \"text\", (col) => col.notNull()).addColumn(\"error_message\", \"text\", (col) => col.notNull()).addColumn(\"created_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n\tawait db.schema.createIndex(\"idx_sync_dead_letters_remote\").on(\"sync_dead_letters\").column(\"remote_name\").execute();\n}\n//#endregion\n//#region src/storage/migrations/014_create_processor_cursor_table.ts\nvar _014_create_processor_cursor_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$12 });\nasync function up$12(db) {\n\tawait db.schema.createTable(\"ProcessorCursor\").addColumn(\"processorId\", \"text\", (col) => col.primaryKey()).addColumn(\"factoryId\", \"text\", (col) => col.notNull()).addColumn(\"driveId\", \"text\", (col) => col.notNull()).addColumn(\"processorIndex\", \"integer\", (col) => col.notNull()).addColumn(\"lastOrdinal\", \"integer\", (col) => col.notNull().defaultTo(sql`0`)).addColumn(\"status\", \"text\", (col) => col.notNull().defaultTo(sql`'active'`)).addColumn(\"lastError\", \"text\").addColumn(\"lastErrorTimestamp\", \"timestamptz\").addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/015_add_operation_denied_reason.ts\nvar _015_add_operation_denied_reason_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$11,\n\tup: () => up$11\n});\n/**\n* Records why authorization refused an operation. Separate from `error` so a\n* denial is distinguishable from a reducer failure without matching on a\n* message. Null for every operation written before decisions were enforced.\n*/\nasync function up$11(db) {\n\tawait db.schema.alterTable(\"Operation\").addColumn(\"deniedReason\", \"text\").execute();\n\tawait db.schema.alterTable(\"operation_index_operations\").addColumn(\"deniedReason\", \"text\").execute();\n}\nasync function down$11(db) {\n\tawait db.schema.alterTable(\"operation_index_operations\").dropColumn(\"deniedReason\").execute();\n\tawait db.schema.alterTable(\"Operation\").dropColumn(\"deniedReason\").execute();\n}\n//#endregion\n//#region src/storage/migrations/016_add_dead_letter_error_type.ts\nvar _016_add_dead_letter_error_type_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$10,\n\tup: () => up$10\n});\n/**\n* The classification a dead letter falls into, stored because it decides whether\n* the document stays quarantined and the in-memory error is gone after a restart.\n* Defaulted rather than nullable, so a pre-existing row rehydrates.\n*/\nasync function up$10(db) {\n\tawait db.schema.alterTable(\"sync_dead_letters\").addColumn(\"error_type\", \"text\", (col) => col.notNull().defaultTo(\"UNCLASSIFIED\")).execute();\n}\nasync function down$10(db) {\n\tawait db.schema.alterTable(\"sync_dead_letters\").dropColumn(\"error_type\").execute();\n}\n//#endregion\n//#region src/storage/migrations/017_create_group_references.ts\nvar _017_create_group_references_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$9,\n\tup: () => up$9\n});\n/**\n* One row per (document, group) reference ever discovered from an auth\n* operation's input. Rows are never updated or deleted: auth evaluation is\n* positional, so a grant that named a group at any position keeps that\n* group's stream in the document's read-set even after a later operation\n* removes the reference. Read by documentId for the groups a document\n* requires (sync), and by groupId for the documents a group change affects\n* (re-evaluation).\n*/\nasync function up$9(db) {\n\tawait db.schema.createTable(\"group_references\").addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"groupId\", \"text\", (col) => col.notNull()).addPrimaryKeyConstraint(\"group_references_pkey\", [\"documentId\", \"groupId\"]).execute();\n\tawait db.schema.createIndex(\"idx_group_references_groupId\").on(\"group_references\").column(\"groupId\").execute();\n}\nasync function down$9(db) {\n\tawait db.schema.dropTable(\"group_references\").execute();\n}\n//#endregion\n//#region src/storage/migrations/018_add_sync_remote_bound_address.ts\nvar _018_add_sync_remote_bound_address_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$8,\n\tup: () => up$8\n});\n/**\n* The address a sync channel is bound to, so a channel created by one subject\n* cannot be polled by another.\n*\n* Nullable rather than defaulted: null is a channel nobody has claimed, which is\n* what every pre-existing row is and what an anonymously created channel stays\n* until its first authenticated poll adopts it. A default would claim them all\n* for one address.\n*/\nasync function up$8(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").addColumn(\"bound_address\", \"text\").execute();\n}\nasync function down$8(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").dropColumn(\"bound_address\").execute();\n}\n//#endregion\n//#region src/storage/migrations/019_require_action_id.ts\nvar _019_require_action_id_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$7,\n\tup: () => up$7\n});\n/**\n* Makes an operation whose action carries no id physically unstorable.\n*\n* The id is not decoration: `deriveOperationId` hashes it into the operation id\n* and replay dedupes incoming operations by it, so an action without one\n* collapses every id-less operation on a document/scope/branch onto a single\n* derived operation id. The API rejects such an action now, and this is the\n* last line of defense behind it.\n*\n* Both tables are constrained because sync reads operations from the index\n* rather than the operation table, so poison reaching only the index would\n* still be served to a replica.\n*\n* Pre-existing rows are backfilled rather than left behind a NOT VALID\n* constraint: a row the index and the operation table disagree about is worse\n* than a missing id, because dedup keys off the value each side serves. The\n* backfill therefore mints one id per operation and writes that same id to both\n* tables, joined on the identity they share. Rewriting the action is safe: the\n* operation hash is taken over the resulting state, not over the action, and a\n* signature is verified from the params carried in the signature tuple, which\n* do not include the action id.\n*\n* The empty string is rejected alongside null. It derives the same colliding\n* operation id as an absent id, so admitting it would leave the hole open.\n*/\nasync function up$7(db) {\n\tawait db.updateTable(\"Operation\").set({ action: sql`jsonb_set(action, '{id}', to_jsonb(gen_random_uuid()::text))` }).where(sql`jsonb_typeof(action) = 'object' and coalesce(action->>'id', '') = ''`).execute();\n\tawait db.updateTable(\"operation_index_operations as oio\").from(\"Operation as op\").set({ action: sql`jsonb_set(oio.action, '{id}', to_jsonb(op.action->>'id'))` }).whereRef(\"oio.opId\", \"=\", \"op.opId\").whereRef(\"oio.index\", \"=\", \"op.index\").whereRef(\"oio.skip\", \"=\", \"op.skip\").where(sql`jsonb_typeof(oio.action) = 'object' and coalesce(oio.action->>'id', '') = ''`).where(sql`coalesce(op.action->>'id', '') <> ''`).execute();\n\tawait db.updateTable(\"operation_index_operations\").set({ action: sql`jsonb_set(action, '{id}', to_jsonb(gen_random_uuid()::text))` }).where(sql`jsonb_typeof(action) = 'object' and coalesce(action->>'id', '') = ''`).execute();\n\tawait db.schema.alterTable(\"Operation\").addCheckConstraint(\"action_must_have_id\", sql`action->>'id' is not null and action->>'id' <> ''`).execute();\n\tawait db.schema.alterTable(\"operation_index_operations\").addCheckConstraint(\"action_must_have_id\", sql`action->>'id' is not null and action->>'id' <> ''`).execute();\n}\n/**\n* Only the constraints are dropped. The backfilled ids stay: they are the ids\n* their operations are now known by, and reverting them would reintroduce the\n* collision the migration removed.\n*/\nasync function down$7(db) {\n\tawait db.schema.alterTable(\"operation_index_operations\").dropConstraint(\"action_must_have_id\").execute();\n\tawait db.schema.alterTable(\"Operation\").dropConstraint(\"action_must_have_id\").execute();\n}\n//#endregion\n//#region src/storage/migrations/020_add_snapshot_operation_ordinal.ts\nvar _020_add_snapshot_operation_ordinal_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$6,\n\tup: () => up$6\n});\n/** Orders header row writes across scopes; `lastOperationIndex` is per scope. */\nasync function up$6(db) {\n\tawait db.schema.alterTable(\"DocumentSnapshot\").addColumn(\"lastOperationOrdinal\", \"integer\", (col) => col.notNull().defaultTo(0)).execute();\n}\nasync function down$6(db) {\n\tawait db.schema.alterTable(\"DocumentSnapshot\").dropColumn(\"lastOperationOrdinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/021_add_sync_remote_peer.ts\nvar _021_add_sync_remote_peer_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$5,\n\tup: () => up$5\n});\n/**\n* The peer's manifest as canonical JSON, and when it was heard. Both null: not\n* yet heard. A time with no manifest: a silent peer, which gets the baselines.\n*/\nasync function up$5(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").addColumn(\"peer_manifest\", \"text\").addColumn(\"peer_manifest_at_utc_ms\", \"bigint\").execute();\n}\nasync function down$5(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").dropColumn(\"peer_manifest\").dropColumn(\"peer_manifest_at_utc_ms\").execute();\n}\n//#endregion\n//#region src/storage/migrations/022_create_sync_holds.ts\nvar _022_create_sync_holds_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$4,\n\tup: () => up$4\n});\n/** Documents held back from a remote whose peer cannot run their versions. */\nasync function up$4(db) {\n\tawait db.schema.createTable(\"sync_holds\").addColumn(\"remote_name\", \"text\", (col) => col.notNull().references(\"sync_remotes.name\").onDelete(\"cascade\")).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"protocol\", \"text\", (col) => col.notNull()).addColumn(\"version\", \"integer\", (col) => col.notNull()).addColumn(\"held_at_utc_ms\", \"bigint\", (col) => col.notNull()).addPrimaryKeyConstraint(\"sync_holds_pkey\", [\n\t\t\"remote_name\",\n\t\t\"document_id\",\n\t\t\"branch\"\n\t]).execute();\n}\nasync function down$4(db) {\n\tawait db.schema.dropTable(\"sync_holds\").execute();\n}\n//#endregion\n//#region src/storage/migrations/023_index_created_protocol_versions.ts\nvar _023_index_created_protocol_versions_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$3,\n\tup: () => up$3\n});\n/**\n* One entry per document created with protocolVersions, keyed by a hash so an\n* oversized header cannot make its creation unstorable. Startup reads the\n* distinct values without visiting every document.\n*/\nasync function up$3(db) {\n\tawait db.schema.createIndex(\"idx_operation_created_protocol_versions\").on(\"Operation\").expression(sql`md5((action->'input'->'protocolVersions')::text)`).where(sql`scope = 'document' and \"index\" = 0 and (action->'input'->'protocolVersions') is not null`).execute();\n}\nasync function down$3(db) {\n\tawait db.schema.dropIndex(\"idx_operation_created_protocol_versions\").execute();\n}\n//#endregion\n//#region src/storage/migrations/024_create_document_purges.ts\nvar _024_create_document_purges_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$2,\n\tup: () => up$2\n});\n/** One row per purged document: the tombstone. Written once, never deleted. */\nasync function up$2(db) {\n\tawait db.schema.createTable(\"document_purges\").addColumn(\"documentId\", \"text\", (col) => col.primaryKey()).addColumn(\"ordinal\", \"bigint\", (col) => col.notNull()).addColumn(\"removedRows\", \"jsonb\", (col) => col.notNull()).addColumn(\"purgedAtUtc\", \"timestamptz\", (col) => col.notNull()).addColumn(\"requestId\", \"text\", (col) => col.notNull()).execute();\n}\nasync function down$2(db) {\n\tawait db.schema.dropTable(\"document_purges\").execute();\n}\n//#endregion\n//#region src/storage/migrations/025_create_sync_received_markers.ts\nvar _025_create_sync_received_markers_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$1,\n\tup: () => up$1\n});\n/** Received purge markers awaiting their outcome; removed with their remote. */\nasync function up$1(db) {\n\tawait db.schema.createTable(\"sync_received_markers\").addColumn(\"remote_name\", \"text\", (col) => col.notNull()).addColumn(\"marker_id\", \"text\", (col) => col.notNull()).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"operation\", \"jsonb\", (col) => col.notNull()).addColumn(\"received_at_utc_ms\", \"bigint\", (col) => col.notNull()).addPrimaryKeyConstraint(\"sync_received_markers_pkey\", [\"remote_name\", \"marker_id\"]).execute();\n}\nasync function down$1(db) {\n\tawait db.schema.dropTable(\"sync_received_markers\").execute();\n}\n//#endregion\n//#region src/storage/migrations/026_create_sync_purge_refusals.ts\nvar _026_create_sync_purge_refusals_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down,\n\tup: () => up\n});\n/** A remote's refusal of a purge marker; payload-free, kept like the tombstone. */\nasync function up(db) {\n\tawait db.schema.createTable(\"sync_purge_refusals\").addColumn(\"remote_name\", \"text\", (col) => col.notNull()).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"refused_at_utc_ms\", \"bigint\", (col) => col.notNull()).addPrimaryKeyConstraint(\"sync_purge_refusals_pkey\", [\n\t\t\"remote_name\",\n\t\t\"document_id\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_sync_purge_refusals_document\").on(\"sync_purge_refusals\").column(\"document_id\").execute();\n}\nasync function down(db) {\n\tawait db.schema.dropTable(\"sync_purge_refusals\").execute();\n}\n//#endregion\n//#region src/storage/migrations/migrator.ts\nconst REACTOR_SCHEMA = \"reactor\";\nconst migrations = {\n\t\"001_create_operation_table\": _001_create_operation_table_exports,\n\t\"002_create_keyframe_table\": _002_create_keyframe_table_exports,\n\t\"003_create_document_table\": _003_create_document_table_exports,\n\t\"004_create_document_relationship_table\": _004_create_document_relationship_table_exports,\n\t\"005_create_indexer_state_table\": _005_create_indexer_state_table_exports,\n\t\"006_create_document_snapshot_table\": _006_create_document_snapshot_table_exports,\n\t\"007_create_slug_mapping_table\": _007_create_slug_mapping_table_exports,\n\t\"008_create_view_state_table\": _008_create_view_state_table_exports,\n\t\"009_create_operation_index_tables\": _009_create_operation_index_tables_exports,\n\t\"010_create_sync_tables\": _010_create_sync_tables_exports,\n\t\"011_add_cursor_type_column\": _011_add_cursor_type_column_exports,\n\t\"012_add_source_remote_column\": _012_add_source_remote_column_exports,\n\t\"013_create_sync_dead_letters_table\": _013_create_sync_dead_letters_table_exports,\n\t\"014_create_processor_cursor_table\": _014_create_processor_cursor_table_exports,\n\t\"015_add_operation_denied_reason\": _015_add_operation_denied_reason_exports,\n\t\"016_add_dead_letter_error_type\": _016_add_dead_letter_error_type_exports,\n\t\"017_create_group_references\": _017_create_group_references_exports,\n\t\"018_add_sync_remote_bound_address\": _018_add_sync_remote_bound_address_exports,\n\t\"019_require_action_id\": _019_require_action_id_exports,\n\t\"020_add_snapshot_operation_ordinal\": _020_add_snapshot_operation_ordinal_exports,\n\t\"021_add_sync_remote_peer\": _021_add_sync_remote_peer_exports,\n\t\"022_create_sync_holds\": _022_create_sync_holds_exports,\n\t\"023_index_created_protocol_versions\": _023_index_created_protocol_versions_exports,\n\t\"024_create_document_purges\": _024_create_document_purges_exports,\n\t\"025_create_sync_received_markers\": _025_create_sync_received_markers_exports,\n\t\"026_create_sync_purge_refusals\": _026_create_sync_purge_refusals_exports\n};\nvar ProgrammaticMigrationProvider = class {\n\tgetMigrations() {\n\t\treturn Promise.resolve(migrations);\n\t}\n};\n/**\n* Applies every pending migration, or every one up to and including `upTo`.\n*\n* The bound exists so a test can reach the schema a data migration is written\n* against, populate it, and then migrate across the migration under test.\n*/\nasync function runMigrations(db, schema = REACTOR_SCHEMA, upTo) {\n\ttry {\n\t\tawait sql`CREATE SCHEMA IF NOT EXISTS ${sql.id(schema)}`.execute(db);\n\t} catch (error) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmigrationsExecuted: [],\n\t\t\terror: error instanceof Error ? error : /* @__PURE__ */ new Error(\"Failed to create schema\")\n\t\t};\n\t}\n\tconst migrator = new Migrator({\n\t\tdb: db.withSchema(schema),\n\t\tprovider: new ProgrammaticMigrationProvider(),\n\t\tmigrationTableSchema: schema\n\t});\n\tlet error;\n\tlet results;\n\ttry {\n\t\tconst result = upTo ? await migrator.migrateTo(upTo) : await migrator.migrateToLatest();\n\t\terror = result.error;\n\t\tresults = result.results;\n\t} catch (e) {\n\t\terror = e;\n\t\tresults = [];\n\t}\n\tconst migrationsExecuted = results?.map((result) => result.migrationName) ?? [];\n\tif (error) return {\n\t\tsuccess: false,\n\t\tmigrationsExecuted,\n\t\terror: error instanceof Error ? error : /* @__PURE__ */ new Error(\"Unknown migration error\")\n\t};\n\treturn {\n\t\tsuccess: true,\n\t\tmigrationsExecuted\n\t};\n}\nasync function getMigrationStatus(db, schema = REACTOR_SCHEMA) {\n\treturn await new Migrator({\n\t\tdb: db.withSchema(schema),\n\t\tprovider: new ProgrammaticMigrationProvider(),\n\t\tmigrationTableSchema: schema\n\t}).getMigrations();\n}\n//#endregion\n//#region src/executor/worker/error-info.ts\nconst MAX_STACK_LENGTH = 8192;\nconst MAX_CAUSE_DEPTH = 8;\nfunction toErrorInfo(err, depth = 0) {\n\tif (depth > MAX_CAUSE_DEPTH) return {\n\t\tname: \"Error\",\n\t\tmessage: \"cause chain truncated\"\n\t};\n\tif (err instanceof Error) {\n\t\tconst info = {\n\t\t\tname: err.name || \"Error\",\n\t\t\tmessage: err.message\n\t\t};\n\t\tif (typeof err.stack === \"string\") info.stack = err.stack.length > MAX_STACK_LENGTH ? err.stack.slice(0, MAX_STACK_LENGTH) : err.stack;\n\t\tif (err.cause !== void 0) info.cause = toErrorInfo(err.cause, depth + 1);\n\t\tconst documentId = err.documentId;\n\t\tif (typeof documentId === \"string\") info.documentId = documentId;\n\t\tconst { documentType, requestedVersion } = err;\n\t\tif (typeof documentType === \"string\") info.documentType = documentType;\n\t\tif (typeof requestedVersion === \"number\") info.requestedVersion = requestedVersion;\n\t\treturn info;\n\t}\n\tif (typeof err === \"string\") return {\n\t\tname: \"Error\",\n\t\tmessage: err\n\t};\n\tif (err && typeof err === \"object\") {\n\t\tconst record = err;\n\t\treturn {\n\t\t\tname: typeof record.name === \"string\" ? record.name : \"Error\",\n\t\t\tmessage: typeof record.message === \"string\" ? record.message : safeStringify(err)\n\t\t};\n\t}\n\treturn {\n\t\tname: \"Error\",\n\t\tmessage: safeStringify(err)\n\t};\n}\nfunction safeStringify(value) {\n\tif (value === null || value === void 0) return String(value);\n\tif (typeof value === \"string\") return value;\n\tif (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\nfunction fromErrorInfo(info) {\n\tconst err = new Error(info.message);\n\tObject.defineProperty(err, \"name\", {\n\t\tvalue: info.name,\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\tif (info.stack !== void 0) err.stack = info.stack;\n\tif (info.documentId !== void 0) Object.defineProperty(err, \"documentId\", {\n\t\tvalue: info.documentId,\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\tfor (const key of [\"documentType\", \"requestedVersion\"]) if (info[key] !== void 0) Object.defineProperty(err, key, {\n\t\tvalue: info[key],\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\tif (info.cause !== void 0) Object.defineProperty(err, \"cause\", {\n\t\tvalue: fromErrorInfo(info.cause),\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\treturn err;\n}\n//#endregion\n//#region src/executor/worker/sanitize.ts\nconst MAX_DEPTH = 8;\nfunction errorToInfo(err) {\n\treturn toErrorInfo(err);\n}\nfunction sanitizeArg(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {\n\tif (depth > MAX_DEPTH) return \"[Truncated]\";\n\tif (value === null || value === void 0) return null;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"number\") return value;\n\tif (typeof value === \"string\") return value;\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (typeof value === \"function\" || typeof value === \"symbol\") return null;\n\tif (value instanceof Error) return toErrorInfo(value);\n\tif (value instanceof Date) return value.toISOString();\n\tif (value instanceof Map) {\n\t\tconst obj = {};\n\t\tfor (const [k, v] of value.entries()) obj[String(k)] = sanitizeArg(v, depth + 1, seen);\n\t\treturn obj;\n\t}\n\tif (value instanceof Set) {\n\t\tconst arr = [];\n\t\tfor (const v of value.values()) arr.push(sanitizeArg(v, depth + 1, seen));\n\t\treturn arr;\n\t}\n\tif (Array.isArray(value)) {\n\t\tif (seen.has(value)) return \"[Circular]\";\n\t\tseen.add(value);\n\t\tconst result = value.map((v) => sanitizeArg(v, depth + 1, seen));\n\t\tseen.delete(value);\n\t\treturn result;\n\t}\n\tif (typeof value === \"object\") {\n\t\tconst proto = Object.getPrototypeOf(value);\n\t\tif (proto !== Object.prototype && proto !== null) return { __nonClonable: value.constructor?.name || \"Unknown\" };\n\t\tif (seen.has(value)) return \"[Circular]\";\n\t\tseen.add(value);\n\t\tconst result = {};\n\t\tfor (const [k, v] of Object.entries(value)) result[k] = sanitizeArg(v, depth + 1, seen);\n\t\tseen.delete(value);\n\t\treturn result;\n\t}\n\treturn null;\n}\n//#endregion\n//#region src/executor/worker/forwarding-logger.ts\nfunction createForwardingLogger(post, level = \"info\", tags = []) {\n\tfunction safePost(msg) {\n\t\ttry {\n\t\t\tpost(msg);\n\t\t} catch {\n\t\t\ttry {\n\t\t\t\tprocess.stderr.write(`[forwarding-logger] postMessage failed: ${msg.level} ${msg.message}\\n`);\n\t\t\t} catch {}\n\t\t}\n\t}\n\tfunction emit(wireLevel, message, args) {\n\t\tconst sanitizedArgs = args.map((a) => sanitizeArg(a));\n\t\tsafePost({\n\t\t\ttype: \"log\",\n\t\t\tlevel: wireLevel,\n\t\t\tmessage,\n\t\t\targs: tags.length > 0 ? [sanitizeArg({ tags }), ...sanitizedArgs] : sanitizedArgs,\n\t\t\ttimestamp: Date.now()\n\t\t});\n\t}\n\treturn {\n\t\tlevel,\n\t\tverbose: (message, ...args) => emit(\"debug\", message, args),\n\t\tdebug: (message, ...args) => emit(\"debug\", message, args),\n\t\tinfo: (message, ...args) => emit(\"info\", message, args),\n\t\twarn: (message, ...args) => emit(\"warn\", message, args),\n\t\terror: (message, ...args) => emit(\"error\", message, args),\n\t\terrorHandler: ((...data) => {\n\t\t\tconst first = data[0];\n\t\t\temit(\"error\", typeof first === \"string\" ? first : \"\", data.slice(1));\n\t\t}),\n\t\tchild: (childTags) => createForwardingLogger(post, level, [...tags, ...childTags])\n\t};\n}\n//#endregion\nexport { DocumentExistence as $, GATED_DOCUMENT_ACTIONS as A, createOperation as B, describeWaitingSessions as C, matchesScope as Ct, CollectionMembershipCache as D, __exportAll as Dt, DocumentMetaCache as E, yieldToMain as Et, buildErrorResult as F, relationshipTarget as G, isGenesisOperation as H, buildSuccessResult as I, targetDocumentId as J, submittedActionIds as K, createConsistencyToken as L, TouchedStreams as M, applyDeleteDocumentAction$1 as N, DOCUMENT_SCOPE_ACTIONS as O, applyUpgradeDocumentAction$1 as P, DocumentAlreadyExistsError as Q, createDocumentFromAction as R, createKyselyWatermarkProbe as S, ReactorEventTypes as St, snapshotFunctionsFor as T, throwIfAborted as Tt, jobWriteIds as U, getNextIndexForScope as V, refusalError as W, APPEND_CONDITION_FAILED_PREFIX as X, updateDocumentRevision as Y, AppendConditionFailedError as Z, acquirePurgeLocks as _, ReservedActionError as _t, REACTOR_SCHEMA as a, AuthorizationDeniedError as at, ProbeSettler as b, UpgradePreconditionFailedError as bt, createForwardingPoolInstrumentation as c, DocumentNotDeletedError as ct, KyselyKeyframeStore as d, ExcessiveReshuffleError as dt, DuplicateOperationError as et, EventBus as f, GroupInUseError as ft, PURGE_NS as g, RelationshipNotFoundError as gt, PURGE_LOCK_BUCKETS as h, PurgeTooLargeError as ht, fromErrorInfo as i, AuthTimestampNotMonotonicError as it, PurgeFence as j, FencedWriteCache as k, instrumentPgPool as l, DocumentNotFoundError as lt, KyselyOperationIndex as m, InvalidSignatureError as mt, errorToInfo as n, RevisionMismatchError as nt, getMigrationStatus as o, BatchJobFailedError as ot, KyselyWriteCache as p, InvalidOperationTimestampError as pt, summarizeSubmittedActions as q, sanitizeArg as r, AuthEnforcementDisabledError as rt, runMigrations as s, DocumentDeletedError as st, createForwardingLogger as t, OptimisticLockError as tt, KyselyOperationStore as u, DocumentPurgedError as ut, findPurged as v, UnsupportedProtocolVersionError as vt, parseSnapshot as w, parsePagingOptions as wt, SettledWatermark as x, EventBusAggregateError as xt, listPurged as y, UnsupportedStoredProtocolError as yt, createEmptyConsistencyToken as z };\n\n//# sourceMappingURL=forwarding-logger-ByfBFgMS.js.map","import type { Operation } from \"@powerhousedao/shared/document-model\";\nimport type { AtomicTxn } from \"@powerhousedao/reactor\";\nimport type { StoredOperation } from \"./types.js\";\n\nexport class HypercoreAtomicTransaction implements AtomicTxn {\n private operations: StoredOperation[] = [];\n\n constructor(\n private documentId: string,\n private documentType: string,\n private scope: string,\n private branch: string,\n ) {}\n\n addOperations(...operations: Operation[]): void {\n for (const op of operations) {\n this.operations.push({\n ...op,\n documentId: this.documentId,\n documentType: this.documentType,\n scope: this.scope,\n branch: this.branch,\n });\n }\n }\n\n getOperations(): StoredOperation[] {\n return this.operations;\n }\n}\n","import type { StoredOperation } from \"./types.js\";\n\nconst PAD_WIDTH = 10;\n\nexport const RANGE_UPPER_BOUND = \"9\".repeat(PAD_WIDTH) + \"~\";\n\nexport function pad(n: number): string {\n return n.toString().padStart(PAD_WIDTH, \"0\");\n}\n\nexport function operationKey(\n documentId: string,\n scope: string,\n branch: string,\n index: number,\n): string {\n return `op/${documentId}/${scope}/${branch}/${pad(index)}`;\n}\n\nexport function operationPrefix(\n documentId: string,\n scope: string,\n branch: string,\n): string {\n return `op/${documentId}/${scope}/${branch}/`;\n}\n\nexport function ordinalKey(ordinal: number): string {\n return `ord/${pad(ordinal)}`;\n}\n\nexport function ordinalPrefix(): string {\n return \"ord/\";\n}\n\nexport function duplicateKey(\n opId: string,\n index: number,\n skip: number,\n): string {\n return `dup/${opId}/${pad(index)}/${pad(skip)}`;\n}\n\nexport function headKey(\n documentId: string,\n scope: string,\n branch: string,\n): string {\n return `_meta/head/${documentId}/${scope}/${branch}`;\n}\n\nexport function headPrefix(documentId: string): string {\n return `_meta/head/${documentId}/`;\n}\n\nexport const ORDINAL_COUNTER_KEY = \"_meta/ordinal\";\n\nexport type ParsedOperationKey = {\n documentId: string;\n scope: string;\n branch: string;\n index: number;\n};\n\nexport function parseOperationKey(key: string): ParsedOperationKey {\n const parts = key.split(\"/\");\n return {\n documentId: parts[1],\n scope: parts[2],\n branch: parts[3],\n index: parseInt(parts[4], 10),\n };\n}\n\nexport type OrdinalEntry = {\n documentId: string;\n documentType: string;\n scope: string;\n branch: string;\n index: number;\n operation: StoredOperation;\n};\n\nexport type HeadEntryValue = {\n index: number;\n latestTimestampUtcMs: string;\n};\n","import {\n isPurgeMarker,\n type Operation,\n type OperationWithContext,\n} from \"@powerhousedao/shared/document-model\";\nimport type {\n AppendCondition,\n AtomicTxn,\n DocumentRevisions,\n IOperationStore,\n OperationFilter,\n PagedResults,\n PagingOptions,\n} from \"@powerhousedao/reactor\";\nimport {\n AppendConditionFailedError,\n DocumentAlreadyExistsError,\n DocumentPurgedError,\n DuplicateOperationError,\n RevisionMismatchError,\n} from \"@powerhousedao/reactor\";\nimport type Hyperbee from \"hyperbee\";\nimport { HypercoreAtomicTransaction } from \"./hypercore-atomic-transaction.js\";\nimport {\n ORDINAL_COUNTER_KEY,\n RANGE_UPPER_BOUND,\n duplicateKey,\n headKey,\n headPrefix,\n operationKey,\n operationPrefix,\n ordinalKey,\n ordinalPrefix,\n pad,\n} from \"./key-encoding.js\";\nimport type { HeadEntryValue, OrdinalEntry } from \"./key-encoding.js\";\nimport type { StoredOperation } from \"./types.js\";\n\nexport class HypercoreOperationStore implements IOperationStore {\n private applyLock: Promise<void> = Promise.resolve();\n\n constructor(private bee: Hyperbee) {}\n\n async apply(\n documentId: string,\n documentType: string,\n scope: string,\n branch: string,\n revision: number,\n fn: (txn: AtomicTxn) => void | Promise<void>,\n signal?: AbortSignal,\n condition?: AppendCondition,\n ): Promise<Operation[]> {\n const prevLock = this.applyLock;\n let releaseLock: () => void;\n this.applyLock = new Promise<void>((resolve) => {\n releaseLock = resolve;\n });\n\n await prevLock;\n\n try {\n // Single writer on applyLock: nothing can append between check and write.\n if (condition) {\n await this.assertConditionHolds(condition, signal);\n }\n\n return await this.executeApply(\n documentId,\n documentType,\n scope,\n branch,\n revision,\n fn,\n signal,\n );\n } finally {\n releaseLock!();\n }\n }\n\n /** Throws if any read-set stream has grown past its recorded revision. */\n private async assertConditionHolds(\n condition: AppendCondition,\n signal?: AbortSignal,\n ): Promise<void> {\n for (const stream of condition.streams) {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const entry = await this.bee.get(\n headKey(stream.documentId, stream.scope, stream.branch),\n );\n const head = entry ? (entry.value as HeadEntryValue).index : -1;\n\n if (head > stream.revision) {\n throw new AppendConditionFailedError(condition);\n }\n }\n }\n\n private async executeApply(\n documentId: string,\n documentType: string,\n scope: string,\n branch: string,\n revision: number,\n fn: (txn: AtomicTxn) => void | Promise<void>,\n signal?: AbortSignal,\n ): Promise<Operation[]> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const hKey = headKey(documentId, scope, branch);\n const headEntry = await this.bee.get(hKey);\n const currentRevision = headEntry\n ? (headEntry.value as HeadEntryValue).index\n : -1;\n\n const atomicTxn = new HypercoreAtomicTransaction(\n documentId,\n documentType,\n scope,\n branch,\n );\n await fn(atomicTxn);\n\n const operations = atomicTxn.getOperations();\n\n // No delete path here: a stream purged elsewhere ends in its marker.\n const marker = await this.purgeMarkerAtHead(documentId);\n if (marker !== undefined && operations.length > 0) {\n if (!operations.every((op) => isPurgeMarker(op))) {\n throw new DocumentPurgedError(documentId);\n }\n return [marker];\n }\n\n if (currentRevision !== revision - 1) {\n if (revision === 0 && this.isCreate(operations)) {\n throw new DocumentAlreadyExistsError(\n documentId,\n scope,\n currentRevision,\n );\n }\n\n throw new RevisionMismatchError(currentRevision + 1, revision);\n }\n\n if (operations.length === 0) {\n return [];\n }\n\n for (const op of operations) {\n const dupKey = duplicateKey(op.id, op.index, op.skip);\n const existing = await this.bee.get(dupKey);\n if (existing) {\n throw new DuplicateOperationError(\n `${op.id} at index ${op.index} with skip ${op.skip}`,\n );\n }\n }\n\n const ordinalEntry = await this.bee.get(ORDINAL_COUNTER_KEY);\n let nextOrdinal: number = ordinalEntry ? (ordinalEntry.value as number) : 0;\n\n const batch = this.bee.batch();\n\n for (const op of operations) {\n const opKey = operationKey(documentId, scope, branch, op.index);\n const serialized = this.serializeOperation(op);\n await batch.put(opKey, serialized);\n\n const ordEntry: OrdinalEntry = {\n documentId,\n documentType,\n scope,\n branch,\n index: op.index,\n operation: serialized,\n };\n await batch.put(ordinalKey(nextOrdinal), ordEntry);\n\n await batch.put(duplicateKey(op.id, op.index, op.skip), \"\");\n\n nextOrdinal++;\n }\n\n const lastOp = operations[operations.length - 1];\n const headValue: HeadEntryValue = {\n index: lastOp.index,\n latestTimestampUtcMs: lastOp.timestampUtcMs,\n };\n await batch.put(hKey, headValue);\n await batch.put(ORDINAL_COUNTER_KEY, nextOrdinal);\n\n await batch.flush();\n\n return operations.map((op) => this.toOperation(op));\n }\n\n /** A purge marker is written to document/main whichever branch it erases. */\n private async purgeMarkerAtHead(\n documentId: string,\n ): Promise<Operation | undefined> {\n const branch = \"main\";\n const head = await this.bee.get(headKey(documentId, \"document\", branch));\n if (!head) {\n return undefined;\n }\n const index = (head.value as HeadEntryValue).index;\n const entry = await this.bee.get(\n operationKey(documentId, \"document\", branch, index),\n );\n const stored = entry?.value as StoredOperation | undefined;\n return stored && isPurgeMarker(stored)\n ? this.toOperation(stored)\n : undefined;\n }\n\n private isCreate(operations: StoredOperation[]): boolean {\n return operations.some((op) => op.action.type === \"CREATE_DOCUMENT\");\n }\n\n /**\n * The paging cursor encodes the index to resume from (one past the last\n * row returned), not the last row's own index; \"\" or \"0\" (or anything\n * unparsable) means the start of the stream. This keeps \"0\" an unambiguous\n * start-of-stream sentinel even when a page ends at index 0, which would\n * otherwise make `nextCursor` equal the start cursor and loop a caller that\n * walks pages forever. Mirrors the encoding in the Kysely store.\n */\n async getSince(\n documentId: string,\n scope: string,\n branch: string,\n revision: number,\n filter?: OperationFilter,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Operation>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const prefix = operationPrefix(documentId, scope, branch);\n const startIndex = revision + 1;\n const parsedCursor = paging?.cursor\n ? Number.parseInt(paging.cursor, 10)\n : NaN;\n const cursorIndex =\n Number.isFinite(parsedCursor) && parsedCursor > 0\n ? parsedCursor\n : startIndex;\n const effectiveStart = Math.max(startIndex, cursorIndex);\n\n const gt = prefix + pad(effectiveStart - 1);\n const lt = prefix + RANGE_UPPER_BOUND;\n const limit = paging?.limit ? paging.limit + 1 : undefined;\n\n const items: Operation[] = [];\n const stream = this.bee.createReadStream({ gt, lt, limit });\n\n for await (const entry of stream) {\n const stored = entry.value as StoredOperation;\n\n if (filter) {\n if (\n filter.actionTypes &&\n filter.actionTypes.length > 0 &&\n !filter.actionTypes.includes((stored.action as { type: string }).type)\n ) {\n continue;\n }\n if (\n filter.timestampFrom &&\n stored.timestampUtcMs < filter.timestampFrom\n ) {\n continue;\n }\n if (filter.timestampTo && stored.timestampUtcMs > filter.timestampTo) {\n continue;\n }\n if (\n filter.sinceRevision !== undefined &&\n stored.index < filter.sinceRevision\n ) {\n continue;\n }\n }\n\n items.push(this.toOperation(stored));\n }\n\n let hasMore = false;\n let resultItems = items;\n\n if (paging?.limit && items.length > paging.limit) {\n hasMore = true;\n resultItems = items.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && resultItems.length > 0\n ? (resultItems[resultItems.length - 1].index + 1).toString()\n : undefined;\n\n const cursor = paging?.cursor || \"0\";\n const resultLimit = paging?.limit || 100;\n\n return {\n results: resultItems,\n options: { cursor, limit: resultLimit },\n nextCursor,\n next: hasMore\n ? () =>\n this.getSince(\n documentId,\n scope,\n branch,\n revision,\n filter,\n { cursor: nextCursor!, limit: resultLimit },\n signal,\n )\n : undefined,\n };\n }\n\n /**\n * The paging cursor encodes the ordinal to resume from (one past the last\n * ordinal returned), not the last ordinal itself; \"\" or \"0\" (or anything\n * unparsable) means the start of the stream. Unlike the Kysely store's\n * `getSinceId` (whose auto-increment id starts at 1), this store's ordinal\n * counter starts at 0, so 0 is a real, valid ordinal and the same\n * ambiguous-cursor hazard as `getSince`/`getConflicting` applies here too.\n */\n async getSinceId(\n id: number,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationWithContext>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const startId = id + 1;\n const parsedCursor = paging?.cursor\n ? Number.parseInt(paging.cursor, 10)\n : NaN;\n const cursorId =\n Number.isFinite(parsedCursor) && parsedCursor > 0\n ? parsedCursor\n : startId;\n const effectiveStart = Math.max(startId, cursorId);\n\n const gt = ordinalPrefix() + pad(effectiveStart - 1);\n const lt = ordinalPrefix() + RANGE_UPPER_BOUND;\n const limit = paging?.limit ? paging.limit + 1 : undefined;\n\n const items: OperationWithContext[] = [];\n const stream = this.bee.createReadStream({ gt, lt, limit });\n\n for await (const entry of stream) {\n const ordEntry = entry.value as OrdinalEntry;\n const ordinal = parseInt(entry.key.split(\"/\")[1], 10);\n\n items.push({\n operation: this.toOperation(ordEntry.operation),\n context: {\n documentId: ordEntry.documentId,\n documentType: ordEntry.documentType,\n scope: ordEntry.scope,\n branch: ordEntry.branch,\n ordinal,\n },\n });\n }\n\n let hasMore = false;\n let resultItems = items;\n\n if (paging?.limit && items.length > paging.limit) {\n hasMore = true;\n resultItems = items.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && resultItems.length > 0\n ? (resultItems[resultItems.length - 1].context.ordinal + 1).toString()\n : undefined;\n\n const cursor = paging?.cursor || \"0\";\n const resultLimit = paging?.limit || 100;\n\n return {\n results: resultItems,\n options: { cursor, limit: resultLimit },\n nextCursor,\n next: hasMore\n ? () =>\n this.getSinceId(\n id,\n { cursor: nextCursor!, limit: resultLimit },\n signal,\n )\n : undefined,\n };\n }\n\n /**\n * The paging cursor here encodes the index to resume from (one past the\n * last row returned), not the last row's own index, for the same reason as\n * `getSince`: a page ending at index 0 must not produce a cursor that is\n * indistinguishable from the start-of-stream sentinel.\n */\n async getConflicting(\n documentId: string,\n scope: string,\n branch: string,\n minTimestamp: string,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Operation>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const prefix = operationPrefix(documentId, scope, branch);\n const parsedCursor = paging?.cursor\n ? Number.parseInt(paging.cursor, 10)\n : NaN;\n const cursorIndex =\n Number.isFinite(parsedCursor) && parsedCursor > 0 ? parsedCursor : -1;\n\n const gte = cursorIndex >= 0 ? prefix + pad(cursorIndex) : prefix;\n const lt = prefix + RANGE_UPPER_BOUND;\n\n const stream = this.bee.createReadStream({ gte, lt });\n\n // One row past the page is all this needs: it proves a next page exists\n // and is dropped again below. The limit cannot be pushed down into\n // createReadStream, because minTimestamp is applied per entry as it is\n // read -- a raw range limit would stop short while matching operations\n // still lay further along the range.\n const readLimit = paging?.limit ? paging.limit + 1 : undefined;\n\n const items: Operation[] = [];\n\n for await (const entry of stream) {\n const stored = entry.value as StoredOperation;\n if (stored.timestampUtcMs >= minTimestamp) {\n items.push(this.toOperation(stored));\n // Every operation of a document shares one key prefix, so without\n // this the range walk drains the whole document to hand back a\n // single page. Breaking closes the stream: for-await calls the\n // iterator's return() on the way out.\n if (readLimit !== undefined && items.length >= readLimit) break;\n }\n }\n\n let hasMore = false;\n let resultItems = items;\n\n if (paging?.limit && items.length > paging.limit) {\n hasMore = true;\n resultItems = items.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && resultItems.length > 0\n ? (resultItems[resultItems.length - 1].index + 1).toString()\n : undefined;\n\n const cursor = paging?.cursor || \"0\";\n const resultLimit = paging?.limit || 100;\n\n return {\n results: resultItems,\n options: { cursor, limit: resultLimit },\n nextCursor,\n next: hasMore\n ? () =>\n this.getConflicting(\n documentId,\n scope,\n branch,\n minTimestamp,\n { cursor: nextCursor!, limit: resultLimit },\n signal,\n )\n : undefined,\n };\n }\n\n async getRevisions(\n documentId: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<DocumentRevisions> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const prefix = headPrefix(documentId);\n const stream = this.bee.createReadStream({\n gte: prefix,\n lt: prefix + \"~\",\n });\n\n const revision: Record<string, number> = {};\n let latestTimestamp = new Date(0).toISOString();\n\n for await (const entry of stream) {\n const parts = entry.key.split(\"/\");\n const entryScope = parts[3];\n const entryBranch = parts[4];\n\n if (entryBranch !== branch) {\n continue;\n }\n\n const headValue = entry.value as HeadEntryValue;\n revision[entryScope] = headValue.index + 1;\n\n if (headValue.latestTimestampUtcMs > latestTimestamp) {\n latestTimestamp = headValue.latestTimestampUtcMs;\n }\n }\n\n return { revision, latestTimestamp };\n }\n\n /**\n * A real maximum over the rows, not the head record's `latestTimestampUtcMs`:\n * that holds the last-indexed timestamp, which a re-append can leave behind a\n * later one, so it would under-report and admit a backdated auth write.\n */\n async getStreamLatestTimestamp(\n documentId: string,\n scope: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<string | undefined> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const stored = await this.getSince(\n documentId,\n scope,\n branch,\n -1,\n undefined,\n undefined,\n signal,\n );\n\n let latest: string | undefined;\n for (const operation of stored.results) {\n if (latest === undefined || operation.timestampUtcMs > latest) {\n latest = operation.timestampUtcMs;\n }\n }\n\n return latest;\n }\n\n async findOperationIds(\n documentId: string,\n scope: string,\n branch: string,\n opIds: string[],\n signal?: AbortSignal,\n ): Promise<Set<string>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const found = new Set<string>();\n if (opIds.length === 0) {\n return found;\n }\n\n const wanted = new Set(opIds);\n const stored = await this.getSince(\n documentId,\n scope,\n branch,\n -1,\n undefined,\n undefined,\n signal,\n );\n for (const operation of stored.results) {\n if (wanted.has(operation.id)) {\n found.add(operation.id);\n }\n }\n\n return found;\n }\n\n async getOperationsByIds(\n documentId: string,\n scope: string,\n branch: string,\n opIds: string[],\n signal?: AbortSignal,\n ): Promise<Operation[]> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n if (opIds.length === 0) {\n return [];\n }\n\n const wanted = new Set(opIds);\n const stored = await this.getSince(\n documentId,\n scope,\n branch,\n -1,\n undefined,\n undefined,\n signal,\n );\n const latest = new Map<string, Operation>();\n for (const operation of stored.results) {\n if (wanted.has(operation.id)) {\n latest.set(operation.id, operation);\n }\n }\n return [...latest.values()];\n }\n\n private serializeOperation(op: StoredOperation): StoredOperation {\n return {\n id: op.id,\n index: op.index,\n skip: op.skip,\n timestampUtcMs: op.timestampUtcMs,\n hash: op.hash,\n error: op.error,\n deniedReason: op.deniedReason,\n action: op.action,\n documentId: op.documentId,\n documentType: op.documentType,\n scope: op.scope,\n branch: op.branch,\n };\n }\n\n private toOperation(stored: StoredOperation): Operation {\n return {\n id: stored.id,\n index: stored.index,\n skip: stored.skip,\n timestampUtcMs: stored.timestampUtcMs,\n hash: stored.hash,\n error: stored.error || undefined,\n deniedReason: stored.deniedReason || undefined,\n action: stored.action,\n };\n }\n}\n","import Corestore from \"corestore\";\nimport Hyperbee from \"hyperbee\";\n\nexport class StorageManager {\n private store: Corestore;\n private bee: Hyperbee | undefined;\n\n constructor(storagePath: string) {\n this.store = new Corestore(storagePath);\n }\n\n async open(): Promise<void> {\n await this.store.ready();\n const core = this.store.get({ name: \"operations\" });\n this.bee = new Hyperbee(core, {\n keyEncoding: \"utf-8\",\n valueEncoding: \"json\",\n });\n await this.bee.ready();\n }\n\n async close(): Promise<void> {\n if (this.bee) {\n await this.bee.close();\n }\n await this.store.close();\n }\n\n getBee(): Hyperbee {\n if (!this.bee) {\n throw new Error(\"StorageManager not opened. Call open() first.\");\n }\n return this.bee;\n }\n}\n"],"mappings":";;;;;;;AAmQA,IAAI,wBAAwB,MAAM,8BAA8B,MAAM;CACrE;;;;;;;CAOA,YAAY,YAAY,SAAS;EAChC,MAAM,WAAW,YAAY,WAAW,WAAW;EACnD,KAAK,OAAO;EACZ,KAAK,aAAa;EAClB,MAAM,kBAAkB,MAAM,qBAAqB;CACpD;;CAEA,OAAO,QAAQ,OAAO;EACrB,OAAO,MAAM,QAAQ,KAAK,MAAM,MAAM,SAAS,2BAA2B,MAAM,SAAS;CAC1F;AACD;;AAEA,IAAI,sBAAsB,MAAM,4BAA4B,sBAAsB;CACjF,SAAS;CACT,YAAY,YAAY,SAAS;EAChC,MAAM,YAAY,WAAW,YAAY,WAAW,YAAY;EAChE,KAAK,OAAO;EACZ,MAAM,kBAAkB,MAAM,mBAAmB;CAClD;CACA,OAAO,QAAQ,OAAO;EACrB,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS;CAC/C;AACD;;;;AA8JA,IAAI,0BAA0B,cAAc,MAAM;CACjD,YAAY,aAAa;EACxB,MAAM,wBAAwB,aAAa;EAC3C,KAAK,OAAO;CACb;AACD;;;;;AAcA,IAAI,wBAAwB,cAAc,MAAM;CAC/C,YAAY,UAAU,QAAQ;EAC7B,MAAM,+BAA+B,SAAS,QAAQ,QAAQ;EAC9D,KAAK,OAAO;CACb;AACD;;;;;AAKA,IAAI,6BAA6B,cAAc,MAAM;CACpD;CACA,YAAY,YAAY,OAAO,cAAc;EAC5C,MAAM,YAAY,WAAW,wDAAwD,MAAM,0BAA0B,cAAc;EACnI,KAAK,OAAO;EACZ,KAAK,aAAa;CACnB;CACA,OAAO,QAAQ,OAAO;EACrB,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS;CAC/C;AACD;;AAEA,MAAM,iCAAiC;;;;;AAKvC,IAAI,6BAA6B,cAAc,MAAM;CACpD;CACA,YAAY,WAAW;EACtB,MAAM,UAAU,UAAU,QAAQ,KAAK,MAAM,GAAG,EAAE,WAAW,GAAG,EAAE,MAAM,GAAG,EAAE,OAAO,GAAG,EAAE,UAAU,CAAC,CAAC,KAAK,IAAI;EAC9G,MAAM,GAAG,+BAA+B,8BAA8B,QAAQ,EAAE;EAChF,KAAK,YAAY;EACjB,KAAK,OAAO;CACb;CACA,OAAO,QAAQ,OAAO;EACrB,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS;CAC/C;;CAEA,OAAO,iBAAiB,SAAS;EAChC,OAAO,QAAQ,WAAW,8BAA8B;CACzD;AACD;AA2B+B,IAAI,IAAI,CAAC,GAAG,2BAAsB,CAAC,CAAC,QAAQ,SAAS,SAAS,iBAAiB,CAAC;;;ACnhB/G,IAAa,6BAAb,MAA6D;CAIjD;CACA;CACA;CACA;CANV,aAAwC,CAAC;CAEzC,YACE,YACA,cACA,OACA,QACA;EAJQ,KAAA,aAAA;EACA,KAAA,eAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;CACP;CAEH,cAAc,GAAG,YAA+B;EAC9C,KAAK,MAAM,MAAM,YACf,KAAK,WAAW,KAAK;GACnB,GAAG;GACH,YAAY,KAAK;GACjB,cAAc,KAAK;GACnB,OAAO,KAAK;GACZ,QAAQ,KAAK;EACf,CAAC;CAEL;CAEA,gBAAmC;EACjC,OAAO,KAAK;CACd;AACF;;;AC3BA,MAAM,YAAY;AAElB,MAAa,oBAAoB,IAAI,OAAO,SAAS,IAAI;AAEzD,SAAgB,IAAI,GAAmB;CACrC,OAAO,EAAE,SAAS,CAAC,CAAC,SAAS,WAAW,GAAG;AAC7C;AAEA,SAAgB,aACd,YACA,OACA,QACA,OACQ;CACR,OAAO,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,KAAK;AACzD;AAEA,SAAgB,gBACd,YACA,OACA,QACQ;CACR,OAAO,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO;AAC7C;AAEA,SAAgB,WAAW,SAAyB;CAClD,OAAO,OAAO,IAAI,OAAO;AAC3B;AAEA,SAAgB,gBAAwB;CACtC,OAAO;AACT;AAEA,SAAgB,aACd,MACA,OACA,MACQ;CACR,OAAO,OAAO,KAAK,GAAG,IAAI,KAAK,EAAE,GAAG,IAAI,IAAI;AAC9C;AAEA,SAAgB,QACd,YACA,OACA,QACQ;CACR,OAAO,cAAc,WAAW,GAAG,MAAM,GAAG;AAC9C;AAEA,SAAgB,WAAW,YAA4B;CACrD,OAAO,cAAc,WAAW;AAClC;AAEA,MAAa,sBAAsB;AASnC,SAAgB,kBAAkB,KAAiC;CACjE,MAAM,QAAQ,IAAI,MAAM,GAAG;CAC3B,OAAO;EACL,YAAY,MAAM;EAClB,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,OAAO,SAAS,MAAM,IAAI,EAAE;CAC9B;AACF;;;AClCA,IAAa,0BAAb,MAAgE;CAG1C;CAFpB,YAAmC,QAAQ,QAAQ;CAEnD,YAAY,KAAuB;EAAf,KAAA,MAAA;CAAgB;CAEpC,MAAM,MACJ,YACA,cACA,OACA,QACA,UACA,IACA,QACA,WACsB;EACtB,MAAM,WAAW,KAAK;EACtB,IAAI;EACJ,KAAK,YAAY,IAAI,SAAe,YAAY;GAC9C,cAAc;EAChB,CAAC;EAED,MAAM;EAEN,IAAI;GAEF,IAAI,WACF,MAAM,KAAK,qBAAqB,WAAW,MAAM;GAGnD,OAAO,MAAM,KAAK,aAChB,YACA,cACA,OACA,QACA,UACA,IACA,MACF;EACF,UAAU;GACR,YAAa;EACf;CACF;;CAGA,MAAc,qBACZ,WACA,QACe;EACf,KAAK,MAAM,UAAU,UAAU,SAAS;GACtC,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;GAGrC,MAAM,QAAQ,MAAM,KAAK,IAAI,IAC3B,QAAQ,OAAO,YAAY,OAAO,OAAO,OAAO,MAAM,CACxD;GAGA,KAFa,QAAS,MAAM,MAAyB,QAAQ,MAElD,OAAO,UAChB,MAAM,IAAI,2BAA2B,SAAS;EAElD;CACF;CAEA,MAAc,aACZ,YACA,cACA,OACA,QACA,UACA,IACA,QACsB;EACtB,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,QAAQ,YAAY,OAAO,MAAM;EAC9C,MAAM,YAAY,MAAM,KAAK,IAAI,IAAI,IAAI;EACzC,MAAM,kBAAkB,YACnB,UAAU,MAAyB,QACpC;EAEJ,MAAM,YAAY,IAAI,2BACpB,YACA,cACA,OACA,MACF;EACA,MAAM,GAAG,SAAS;EAElB,MAAM,aAAa,UAAU,cAAc;EAG3C,MAAM,SAAS,MAAM,KAAK,kBAAkB,UAAU;EACtD,IAAI,WAAW,KAAA,KAAa,WAAW,SAAS,GAAG;GACjD,IAAI,CAAC,WAAW,OAAO,OAAO,cAAc,EAAE,CAAC,GAC7C,MAAM,IAAI,oBAAoB,UAAU;GAE1C,OAAO,CAAC,MAAM;EAChB;EAEA,IAAI,oBAAoB,WAAW,GAAG;GACpC,IAAI,aAAa,KAAK,KAAK,SAAS,UAAU,GAC5C,MAAM,IAAI,2BACR,YACA,OACA,eACF;GAGF,MAAM,IAAI,sBAAsB,kBAAkB,GAAG,QAAQ;EAC/D;EAEA,IAAI,WAAW,WAAW,GACxB,OAAO,CAAC;EAGV,KAAK,MAAM,MAAM,YAAY;GAC3B,MAAM,SAAS,aAAa,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI;GAEpD,IAAI,MADmB,KAAK,IAAI,IAAI,MAAM,GAExC,MAAM,IAAI,wBACR,GAAG,GAAG,GAAG,YAAY,GAAG,MAAM,aAAa,GAAG,MAChD;EAEJ;EAEA,MAAM,eAAe,MAAM,KAAK,IAAI,IAAI,mBAAmB;EAC3D,IAAI,cAAsB,eAAgB,aAAa,QAAmB;EAE1E,MAAM,QAAQ,KAAK,IAAI,MAAM;EAE7B,KAAK,MAAM,MAAM,YAAY;GAC3B,MAAM,QAAQ,aAAa,YAAY,OAAO,QAAQ,GAAG,KAAK;GAC9D,MAAM,aAAa,KAAK,mBAAmB,EAAE;GAC7C,MAAM,MAAM,IAAI,OAAO,UAAU;GAEjC,MAAM,WAAyB;IAC7B;IACA;IACA;IACA;IACA,OAAO,GAAG;IACV,WAAW;GACb;GACA,MAAM,MAAM,IAAI,WAAW,WAAW,GAAG,QAAQ;GAEjD,MAAM,MAAM,IAAI,aAAa,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,GAAG,EAAE;GAE1D;EACF;EAEA,MAAM,SAAS,WAAW,WAAW,SAAS;EAC9C,MAAM,YAA4B;GAChC,OAAO,OAAO;GACd,sBAAsB,OAAO;EAC/B;EACA,MAAM,MAAM,IAAI,MAAM,SAAS;EAC/B,MAAM,MAAM,IAAI,qBAAqB,WAAW;EAEhD,MAAM,MAAM,MAAM;EAElB,OAAO,WAAW,KAAK,OAAO,KAAK,YAAY,EAAE,CAAC;CACpD;;CAGA,MAAc,kBACZ,YACgC;EAChC,MAAM,SAAS;EACf,MAAM,OAAO,MAAM,KAAK,IAAI,IAAI,QAAQ,YAAY,YAAY,MAAM,CAAC;EACvE,IAAI,CAAC,MACH;EAEF,MAAM,QAAS,KAAK,MAAyB;EAI7C,MAAM,UAAS,MAHK,KAAK,IAAI,IAC3B,aAAa,YAAY,YAAY,QAAQ,KAAK,CACpD,EAAA,EACsB;EACtB,OAAO,UAAU,cAAc,MAAM,IACjC,KAAK,YAAY,MAAM,IACvB,KAAA;CACN;CAEA,SAAiB,YAAwC;EACvD,OAAO,WAAW,MAAM,OAAO,GAAG,OAAO,SAAS,iBAAiB;CACrE;;;;;;;;;CAUA,MAAM,SACJ,YACA,OACA,QACA,UACA,QACA,QACA,QACkC;EAClC,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,SAAS,gBAAgB,YAAY,OAAO,MAAM;EACxD,MAAM,aAAa,WAAW;EAC9B,MAAM,eAAe,QAAQ,SACzB,OAAO,SAAS,OAAO,QAAQ,EAAE,IACjC;EAOJ,MAAM,KAAK,SAAS,IAFG,KAAK,IAAI,YAH9B,OAAO,SAAS,YAAY,KAAK,eAAe,IAC5C,eACA,UAG+B,IAAI,CAAC;EAC1C,MAAM,KAAK,SAAS;EACpB,MAAM,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,IAAI,KAAA;EAEjD,MAAM,QAAqB,CAAC;EAC5B,MAAM,SAAS,KAAK,IAAI,iBAAiB;GAAE;GAAI;GAAI;EAAM,CAAC;EAE1D,WAAW,MAAM,SAAS,QAAQ;GAChC,MAAM,SAAS,MAAM;GAErB,IAAI,QAAQ;IACV,IACE,OAAO,eACP,OAAO,YAAY,SAAS,KAC5B,CAAC,OAAO,YAAY,SAAU,OAAO,OAA4B,IAAI,GAErE;IAEF,IACE,OAAO,iBACP,OAAO,iBAAiB,OAAO,eAE/B;IAEF,IAAI,OAAO,eAAe,OAAO,iBAAiB,OAAO,aACvD;IAEF,IACE,OAAO,kBAAkB,KAAA,KACzB,OAAO,QAAQ,OAAO,eAEtB;GAEJ;GAEA,MAAM,KAAK,KAAK,YAAY,MAAM,CAAC;EACrC;EAEA,IAAI,UAAU;EACd,IAAI,cAAc;EAElB,IAAI,QAAQ,SAAS,MAAM,SAAS,OAAO,OAAO;GAChD,UAAU;GACV,cAAc,MAAM,MAAM,GAAG,OAAO,KAAK;EAC3C;EAEA,MAAM,aACJ,WAAW,YAAY,SAAS,KAC3B,YAAY,YAAY,SAAS,EAAE,CAAC,QAAQ,EAAA,CAAG,SAAS,IACzD,KAAA;EAEN,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,cAAc,QAAQ,SAAS;EAErC,OAAO;GACL,SAAS;GACT,SAAS;IAAE;IAAQ,OAAO;GAAY;GACtC;GACA,MAAM,gBAEA,KAAK,SACH,YACA,OACA,QACA,UACA,QACA;IAAE,QAAQ;IAAa,OAAO;GAAY,GAC1C,MACF,IACF,KAAA;EACN;CACF;;;;;;;;;CAUA,MAAM,WACJ,IACA,QACA,QAC6C;EAC7C,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,UAAU,KAAK;EACrB,MAAM,eAAe,QAAQ,SACzB,OAAO,SAAS,OAAO,QAAQ,EAAE,IACjC;EAKJ,MAAM,iBAAiB,KAAK,IAAI,SAH9B,OAAO,SAAS,YAAY,KAAK,eAAe,IAC5C,eACA,OAC2C;EAEjD,MAAM,KAAK,cAAc,IAAI,IAAI,iBAAiB,CAAC;EACnD,MAAM,KAAK,cAAc,IAAI;EAC7B,MAAM,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,IAAI,KAAA;EAEjD,MAAM,QAAgC,CAAC;EACvC,MAAM,SAAS,KAAK,IAAI,iBAAiB;GAAE;GAAI;GAAI;EAAM,CAAC;EAE1D,WAAW,MAAM,SAAS,QAAQ;GAChC,MAAM,WAAW,MAAM;GACvB,MAAM,UAAU,SAAS,MAAM,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE;GAEpD,MAAM,KAAK;IACT,WAAW,KAAK,YAAY,SAAS,SAAS;IAC9C,SAAS;KACP,YAAY,SAAS;KACrB,cAAc,SAAS;KACvB,OAAO,SAAS;KAChB,QAAQ,SAAS;KACjB;IACF;GACF,CAAC;EACH;EAEA,IAAI,UAAU;EACd,IAAI,cAAc;EAElB,IAAI,QAAQ,SAAS,MAAM,SAAS,OAAO,OAAO;GAChD,UAAU;GACV,cAAc,MAAM,MAAM,GAAG,OAAO,KAAK;EAC3C;EAEA,MAAM,aACJ,WAAW,YAAY,SAAS,KAC3B,YAAY,YAAY,SAAS,EAAE,CAAC,QAAQ,UAAU,EAAA,CAAG,SAAS,IACnE,KAAA;EAEN,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,cAAc,QAAQ,SAAS;EAErC,OAAO;GACL,SAAS;GACT,SAAS;IAAE;IAAQ,OAAO;GAAY;GACtC;GACA,MAAM,gBAEA,KAAK,WACH,IACA;IAAE,QAAQ;IAAa,OAAO;GAAY,GAC1C,MACF,IACF,KAAA;EACN;CACF;;;;;;;CAQA,MAAM,eACJ,YACA,OACA,QACA,cACA,QACA,QACkC;EAClC,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,SAAS,gBAAgB,YAAY,OAAO,MAAM;EACxD,MAAM,eAAe,QAAQ,SACzB,OAAO,SAAS,OAAO,QAAQ,EAAE,IACjC;EACJ,MAAM,cACJ,OAAO,SAAS,YAAY,KAAK,eAAe,IAAI,eAAe;EAErE,MAAM,MAAM,eAAe,IAAI,SAAS,IAAI,WAAW,IAAI;EAC3D,MAAM,KAAK,SAAS;EAEpB,MAAM,SAAS,KAAK,IAAI,iBAAiB;GAAE;GAAK;EAAG,CAAC;EAOpD,MAAM,YAAY,QAAQ,QAAQ,OAAO,QAAQ,IAAI,KAAA;EAErD,MAAM,QAAqB,CAAC;EAE5B,WAAW,MAAM,SAAS,QAAQ;GAChC,MAAM,SAAS,MAAM;GACrB,IAAI,OAAO,kBAAkB,cAAc;IACzC,MAAM,KAAK,KAAK,YAAY,MAAM,CAAC;IAKnC,IAAI,cAAc,KAAA,KAAa,MAAM,UAAU,WAAW;GAC5D;EACF;EAEA,IAAI,UAAU;EACd,IAAI,cAAc;EAElB,IAAI,QAAQ,SAAS,MAAM,SAAS,OAAO,OAAO;GAChD,UAAU;GACV,cAAc,MAAM,MAAM,GAAG,OAAO,KAAK;EAC3C;EAEA,MAAM,aACJ,WAAW,YAAY,SAAS,KAC3B,YAAY,YAAY,SAAS,EAAE,CAAC,QAAQ,EAAA,CAAG,SAAS,IACzD,KAAA;EAEN,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,cAAc,QAAQ,SAAS;EAErC,OAAO;GACL,SAAS;GACT,SAAS;IAAE;IAAQ,OAAO;GAAY;GACtC;GACA,MAAM,gBAEA,KAAK,eACH,YACA,OACA,QACA,cACA;IAAE,QAAQ;IAAa,OAAO;GAAY,GAC1C,MACF,IACF,KAAA;EACN;CACF;CAEA,MAAM,aACJ,YACA,QACA,QAC4B;EAC5B,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,SAAS,WAAW,UAAU;EACpC,MAAM,SAAS,KAAK,IAAI,iBAAiB;GACvC,KAAK;GACL,IAAI,SAAS;EACf,CAAC;EAED,MAAM,WAAmC,CAAC;EAC1C,IAAI,mCAAkB,IAAI,KAAK,CAAC,EAAA,CAAE,YAAY;EAE9C,WAAW,MAAM,SAAS,QAAQ;GAChC,MAAM,QAAQ,MAAM,IAAI,MAAM,GAAG;GACjC,MAAM,aAAa,MAAM;GAGzB,IAFoB,MAAM,OAEN,QAClB;GAGF,MAAM,YAAY,MAAM;GACxB,SAAS,cAAc,UAAU,QAAQ;GAEzC,IAAI,UAAU,uBAAuB,iBACnC,kBAAkB,UAAU;EAEhC;EAEA,OAAO;GAAE;GAAU;EAAgB;CACrC;;;;;;CAOA,MAAM,yBACJ,YACA,OACA,QACA,QAC6B;EAC7B,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,SAAS,MAAM,KAAK,SACxB,YACA,OACA,QACA,IACA,KAAA,GACA,KAAA,GACA,MACF;EAEA,IAAI;EACJ,KAAK,MAAM,aAAa,OAAO,SAC7B,IAAI,WAAW,KAAA,KAAa,UAAU,iBAAiB,QACrD,SAAS,UAAU;EAIvB,OAAO;CACT;CAEA,MAAM,iBACJ,YACA,OACA,QACA,OACA,QACsB;EACtB,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,wBAAQ,IAAI,IAAY;EAC9B,IAAI,MAAM,WAAW,GACnB,OAAO;EAGT,MAAM,SAAS,IAAI,IAAI,KAAK;EAC5B,MAAM,SAAS,MAAM,KAAK,SACxB,YACA,OACA,QACA,IACA,KAAA,GACA,KAAA,GACA,MACF;EACA,KAAK,MAAM,aAAa,OAAO,SAC7B,IAAI,OAAO,IAAI,UAAU,EAAE,GACzB,MAAM,IAAI,UAAU,EAAE;EAI1B,OAAO;CACT;CAEA,MAAM,mBACJ,YACA,OACA,QACA,OACA,QACsB;EACtB,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,mBAAmB;EAErC,IAAI,MAAM,WAAW,GACnB,OAAO,CAAC;EAGV,MAAM,SAAS,IAAI,IAAI,KAAK;EAC5B,MAAM,SAAS,MAAM,KAAK,SACxB,YACA,OACA,QACA,IACA,KAAA,GACA,KAAA,GACA,MACF;EACA,MAAM,yBAAS,IAAI,IAAuB;EAC1C,KAAK,MAAM,aAAa,OAAO,SAC7B,IAAI,OAAO,IAAI,UAAU,EAAE,GACzB,OAAO,IAAI,UAAU,IAAI,SAAS;EAGtC,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC;CAC5B;CAEA,mBAA2B,IAAsC;EAC/D,OAAO;GACL,IAAI,GAAG;GACP,OAAO,GAAG;GACV,MAAM,GAAG;GACT,gBAAgB,GAAG;GACnB,MAAM,GAAG;GACT,OAAO,GAAG;GACV,cAAc,GAAG;GACjB,QAAQ,GAAG;GACX,YAAY,GAAG;GACf,cAAc,GAAG;GACjB,OAAO,GAAG;GACV,QAAQ,GAAG;EACb;CACF;CAEA,YAAoB,QAAoC;EACtD,OAAO;GACL,IAAI,OAAO;GACX,OAAO,OAAO;GACd,MAAM,OAAO;GACb,gBAAgB,OAAO;GACvB,MAAM,OAAO;GACb,OAAO,OAAO,SAAS,KAAA;GACvB,cAAc,OAAO,gBAAgB,KAAA;GACrC,QAAQ,OAAO;EACjB;CACF;AACF;;;ACzpBA,IAAa,iBAAb,MAA4B;CAC1B;CACA;CAEA,YAAY,aAAqB;EAC/B,KAAK,QAAQ,IAAI,UAAU,WAAW;CACxC;CAEA,MAAM,OAAsB;EAC1B,MAAM,KAAK,MAAM,MAAM;EACvB,MAAM,OAAO,KAAK,MAAM,IAAI,EAAE,MAAM,aAAa,CAAC;EAClD,KAAK,MAAM,IAAI,SAAS,MAAM;GAC5B,aAAa;GACb,eAAe;EACjB,CAAC;EACD,MAAM,KAAK,IAAI,MAAM;CACvB;CAEA,MAAM,QAAuB;EAC3B,IAAI,KAAK,KACP,MAAM,KAAK,IAAI,MAAM;EAEvB,MAAM,KAAK,MAAM,MAAM;CACzB;CAEA,SAAmB;EACjB,IAAI,CAAC,KAAK,KACR,MAAM,IAAI,MAAM,+CAA+C;EAEjE,OAAO,KAAK;CACd;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../reactor/dist/forwarding-logger-B9LLXItm.js","../src/hypercore-atomic-transaction.ts","../src/key-encoding.ts","../src/hypercore-operation-store.ts","../src/storage-manager.ts"],"sourcesContent":["import { DOCUMENT_DELETED_REASON, DOCUMENT_SCOPE_ACTION_TYPES, PURGE_DOCUMENT, appendWithoutApplying, applyDeleteDocumentAction, applyDeleteDocumentAction as applyDeleteDocumentAction$1, applyUpgradeDocumentAction, applyUpgradeDocumentAction as applyUpgradeDocumentAction$1, baseReducerVersion, createDocumentState, createPresignedHeader, defaultBaseState, deriveOperationId, isDenied, isPurgeMarker, mentionedGroupIds, normalizeDocumentModelVersion, operationOutcome, purgedProtocolVersions, targetDocumentId, withProtocolVersions } from \"@powerhousedao/shared/document-model\";\nimport { v4 } from \"uuid\";\nimport { Migrator, TableNode, sql } from \"kysely\";\n//#region \\0rolldown/runtime.js\nvar __defProp = Object.defineProperty;\nvar __exportAll = (all, no_symbols) => {\n\tlet target = {};\n\tfor (var name in all) __defProp(target, name, {\n\t\tget: all[name],\n\t\tenumerable: true\n\t});\n\tif (!no_symbols) __defProp(target, Symbol.toStringTag, { value: \"Module\" });\n\treturn target;\n};\n//#endregion\n//#region src/shared/utils.ts\nfunction matchesScope(view = {}, scope) {\n\tif (view.scopes) return view.scopes.includes(scope);\n\treturn true;\n}\nfunction yieldToMain() {\n\tconst s = globalThis.scheduler;\n\tif (s?.yield) return s.yield();\n\treturn new Promise((resolve) => setTimeout(resolve, 0));\n}\nconst defaultAbortError = () => /* @__PURE__ */ new Error(\"Operation aborted\");\nfunction throwIfAborted(signal, makeError = defaultAbortError) {\n\tif (signal?.aborted) throw makeError();\n}\nconst TIMED_OUT = Symbol(\"deadline-expired\");\n/** Races a call that cannot be cancelled; on {@link TIMED_OUT} the call may still settle later. */\nasync function withDeadline(pending, timeoutMs) {\n\tlet handle;\n\tconst expiry = new Promise((resolve) => {\n\t\thandle = setTimeout(() => resolve(TIMED_OUT), timeoutMs);\n\t});\n\ttry {\n\t\treturn await Promise.race([pending, expiry]);\n\t} finally {\n\t\tclearTimeout(handle);\n\t}\n}\nfunction delay(ms) {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n/**\n* Validates PagingOptions and returns a normalized offset and limit.\n* Throws if the cursor is not empty and not a non-negative integer, or if\n* limit is less than 1. When `paging` is undefined, returns offset 0 and\n* the caller-supplied `defaultLimit`.\n*/\nfunction parsePagingOptions(paging, defaultLimit) {\n\tif (paging === void 0) return {\n\t\toffset: 0,\n\t\tlimit: defaultLimit\n\t};\n\tif (!Number.isInteger(paging.limit) || paging.limit < 1) throw new Error(`Invalid paging limit: ${String(paging.limit)} (must be an integer >= 1)`);\n\tif (paging.cursor === \"\") return {\n\t\toffset: 0,\n\t\tlimit: paging.limit\n\t};\n\tconst parsed = Number(paging.cursor);\n\tif (!Number.isInteger(parsed) || parsed < 0) throw new Error(`Invalid paging cursor: ${JSON.stringify(paging.cursor)} (must be empty or a non-negative integer)`);\n\treturn {\n\t\toffset: parsed,\n\t\tlimit: paging.limit\n\t};\n}\n//#endregion\n//#region src/events/types.ts\n/**\n* Custom error class that aggregates multiple errors from event subscribers.\n*/\nvar EventBusAggregateError = class extends Error {\n\terrors;\n\tconstructor(errors) {\n\t\tconst message = `EventBus emit failed with ${errors.length} error(s): ${errors.map((e) => {\n\t\t\tif (e && typeof e === \"object\" && \"message\" in e) return e.message;\n\t\t\treturn String(e);\n\t\t}).join(\"; \")}`;\n\t\tsuper(message);\n\t\tthis.name = \"EventBusAggregateError\";\n\t\tthis.errors = errors;\n\t}\n};\n/**\n* Event types for reactor lifecycle events.\n*/\nconst ReactorEventTypes = {\n\tJOB_PENDING: 10001,\n\tJOB_RUNNING: 10002,\n\tJOB_WRITE_READY: 10003,\n\tJOB_READ_READY: 10004,\n\tJOB_FAILED: 10005,\n\tREADMODEL_BATCH_COMPLETED: 10006,\n\tREADMODEL_INDEXED: 10007,\n\tMODEL_LOADED: 10008,\n\tSIGNATURE_REFUSED: 10009,\n\tCATCHUP_SWEPT: 10010\n};\n//#endregion\n//#region src/shared/errors.ts\n/**\n* Error thrown when attempting to access a deleted document.\n*/\n/** The error name on a job the reactor does not know. */\nconst JOB_NOT_FOUND_ERROR_NAME = \"JobNotFoundError\";\nvar DocumentDeletedError = class DocumentDeletedError extends Error {\n\tdocumentId;\n\tdeletedAtUtcIso;\n\tconstructor(documentId, deletedAtUtcIso = null) {\n\t\tconst message = deletedAtUtcIso ? `Document ${documentId} was deleted at ${deletedAtUtcIso}` : `Document ${documentId} has been deleted`;\n\t\tsuper(message);\n\t\tthis.name = \"DocumentDeletedError\";\n\t\tthis.documentId = documentId;\n\t\tthis.deletedAtUtcIso = deletedAtUtcIso;\n\t\tError.captureStackTrace(this, DocumentDeletedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentDeletedError\";\n\t}\n};\n/**\n* Error thrown when the auth policy denies an action at the executor gate.\n*/\nvar AuthorizationDeniedError = class AuthorizationDeniedError extends Error {\n\tdocumentId;\n\tscope;\n\toperation;\n\tsubject;\n\tconstructor(documentId, scope, operation, subject) {\n\t\tsuper(`Authorization denied: ${subject ?? \"anonymous\"} may not execute ${operation} in scope \"${scope}\" of document ${documentId}`);\n\t\tthis.name = \"AuthorizationDeniedError\";\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.operation = operation;\n\t\tthis.subject = subject;\n\t\tError.captureStackTrace(this, AuthorizationDeniedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AuthorizationDeniedError\";\n\t}\n};\n/**\n* An auth operation did not strictly exceed the newest timestamp in its stream.\n*\n* Terminal and asymmetric by design: no ordering rule can reconcile two replicas\n* that each accepted an auth operation offline, because either order hands one\n* authority the other never granted, so the replica ahead holds the arrival.\n*/\nvar AuthTimestampNotMonotonicError = class AuthTimestampNotMonotonicError extends Error {\n\tdocumentId;\n\tbranch;\n\ttimestampUtcMs;\n\tnewestTimestampUtcMs;\n\tconstructor(documentId, branch, timestampUtcMs, newestTimestampUtcMs) {\n\t\tsuper(`Auth timestamp not monotonic: ${timestampUtcMs} does not exceed ${newestTimestampUtcMs} in the auth stream of document ${documentId} on branch ${branch}`);\n\t\tthis.name = \"AuthTimestampNotMonotonicError\";\n\t\tthis.documentId = documentId;\n\t\tthis.branch = branch;\n\t\tthis.timestampUtcMs = timestampUtcMs;\n\t\tthis.newestTimestampUtcMs = newestTimestampUtcMs;\n\t\tError.captureStackTrace(this, AuthTimestampNotMonotonicError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AuthTimestampNotMonotonicError\";\n\t}\n};\n/**\n* An operation or action carried a timestamp that is not an ISO-8601 UTC\n* instant.\n*\n* Terminal rather than retryable: the value does not change between attempts,\n* so a retry re-runs the whole job to fail identically. Quarantining, unlike a\n* held auth operation — this is malformed data rather than two replicas\n* disagreeing, and nothing further from that source should be trusted until it\n* is looked at.\n*/\nvar InvalidOperationTimestampError = class InvalidOperationTimestampError extends Error {\n\tdocumentId;\n\tscope;\n\ttimestampUtcMs;\n\tconstructor(documentId, scope, timestampUtcMs, context) {\n\t\tsuper(`Invalid timestamp \"${timestampUtcMs}\" on ${context} in scope \"${scope}\" of document ${documentId}`);\n\t\tthis.name = \"InvalidOperationTimestampError\";\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.timestampUtcMs = timestampUtcMs;\n\t\tError.captureStackTrace(this, InvalidOperationTimestampError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"InvalidOperationTimestampError\";\n\t}\n};\n/** A document requires a protocol version this reactor does not run. Terminal. */\nvar UnsupportedProtocolVersionError = class UnsupportedProtocolVersionError extends Error {\n\tdocumentId;\n\tprotocol;\n\tversion;\n\tconstructor(documentId, protocol, version) {\n\t\tsuper(`Document ${documentId} requires ${protocol} ${version}, which this reactor does not support`);\n\t\tthis.name = \"UnsupportedProtocolVersionError\";\n\t\tthis.documentId = documentId;\n\t\tthis.protocol = protocol;\n\t\tthis.version = version;\n\t\tError.captureStackTrace(this, UnsupportedProtocolVersionError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"UnsupportedProtocolVersionError\";\n\t}\n};\n/**\n* A load would move more operations than the bound allows, indicating a real\n* divergence between local and incoming history. Counts only first-time moves,\n* so a re-evaluation pass's re-appends do not make busy documents\n* revocation-proof. Terminal: the condition is deterministic.\n*/\nvar ExcessiveReshuffleError = class ExcessiveReshuffleError extends Error {\n\tdocumentId;\n\tscope;\n\tcount;\n\tthreshold;\n\tconstructor(documentId, scope, count, threshold) {\n\t\tsuper(`Excessive reshuffle detected: ${count} operations in scope \"${scope}\" of document ${documentId} exceeds the threshold of ${threshold}. This indicates a significant divergence between local and incoming operations.`);\n\t\tthis.name = \"ExcessiveReshuffleError\";\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.count = count;\n\t\tthis.threshold = threshold;\n\t\tError.captureStackTrace(this, ExcessiveReshuffleError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"ExcessiveReshuffleError\";\n\t}\n};\n/** The message carries the code: only name and message cross the queue. */\nvar InvalidSignatureError = class InvalidSignatureError extends Error {\n\tdocumentId;\n\tcode;\n\treason;\n\tconstructor(documentId, code, reason) {\n\t\tsuper(`Invalid signature in document ${documentId} [${code}]: ${reason}`);\n\t\tthis.name = \"InvalidSignatureError\";\n\t\tthis.documentId = documentId;\n\t\tthis.code = code;\n\t\tthis.reason = reason;\n\t\tError.captureStackTrace(this, InvalidSignatureError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"InvalidSignatureError\";\n\t}\n};\n/**\n* An UPGRADE_DOCUMENT action's preconditions (fromVersion and the per-scope\n* revision snapshot) did not match the document state the executor loaded.\n*\n* Terminal rather than retryable: the action carries the client's snapshot,\n* which stays stale no matter how often the job re-runs. The client is\n* expected to re-read the document and submit a fresh action instead.\n*/\nvar UpgradePreconditionFailedError = class UpgradePreconditionFailedError extends Error {\n\tdocumentId;\n\tdetail;\n\tconstructor(documentId, detail) {\n\t\tsuper(`Upgrade precondition failed for document ${documentId}: ${detail}`);\n\t\tthis.name = \"UpgradePreconditionFailedError\";\n\t\tthis.documentId = documentId;\n\t\tthis.detail = detail;\n\t\tError.captureStackTrace(this, UpgradePreconditionFailedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"UpgradePreconditionFailedError\";\n\t}\n};\n/**\n* Error thrown when a document is not found (no operations exist for the document ID).\n*/\nvar DocumentNotFoundError = class DocumentNotFoundError extends Error {\n\tdocumentId;\n\t/**\n\t* @param message Overrides the default text. A handler that knows which of\n\t* several documents an action reads - a relationship's source, say - says so\n\t* here rather than rewrapping in a bare Error, which would strip the name the\n\t* executor classifies by.\n\t*/\n\tconstructor(documentId, message) {\n\t\tsuper(message ?? `Document ${documentId} not found`);\n\t\tthis.name = \"DocumentNotFoundError\";\n\t\tthis.documentId = documentId;\n\t\tError.captureStackTrace(this, DocumentNotFoundError);\n\t}\n\t/** Also true for DocumentPurgedError: only the name crosses the queue. */\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && (error.name === \"DocumentNotFoundError\" || error.name === \"DocumentPurgedError\");\n\t}\n};\n/** The document was purged; readers treat it as absent. Terminal. */\nvar DocumentPurgedError = class DocumentPurgedError extends DocumentNotFoundError {\n\tpurged = true;\n\tconstructor(documentId, message) {\n\t\tsuper(documentId, message ?? `Document ${documentId} was purged`);\n\t\tthis.name = \"DocumentPurgedError\";\n\t\tError.captureStackTrace(this, DocumentPurgedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentPurgedError\";\n\t}\n};\n/** A purge was asked for a document that is not deleted. Terminal. */\nvar DocumentNotDeletedError = class DocumentNotDeletedError extends Error {\n\tdocumentId;\n\tconstructor(documentId, message) {\n\t\tsuper(message ?? `Document ${documentId} is not deleted`);\n\t\tthis.name = \"DocumentNotDeletedError\";\n\t\tthis.documentId = documentId;\n\t\tError.captureStackTrace(this, DocumentNotDeletedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentNotDeletedError\";\n\t}\n};\n/** A surviving document's accepted auth history names the group. Terminal. */\nvar GroupInUseError = class GroupInUseError extends Error {\n\tgroupId;\n\treferencingDocumentIds;\n\tconstructor(groupId, referencingDocumentIds) {\n\t\tsuper(`Group ${groupId} cannot be purged: the auth history of ${referencingDocumentIds.join(\", \")} names it`);\n\t\tthis.name = \"GroupInUseError\";\n\t\tthis.groupId = groupId;\n\t\tthis.referencingDocumentIds = referencingDocumentIds;\n\t\tError.captureStackTrace(this, GroupInUseError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"GroupInUseError\";\n\t}\n};\n/** A purge above maxPurgeOperations without allowLarge. Terminal. */\nvar PurgeTooLargeError = class PurgeTooLargeError extends Error {\n\tdocumentId;\n\toperationCount;\n\tmaxPurgeOperations;\n\tconstructor(documentId, operationCount, maxPurgeOperations) {\n\t\tsuper(`Document ${documentId} has ${operationCount} operations, above the purge limit of ${maxPurgeOperations}; request it with allowLarge`);\n\t\tthis.name = \"PurgeTooLargeError\";\n\t\tthis.documentId = documentId;\n\t\tthis.operationCount = operationCount;\n\t\tthis.maxPurgeOperations = maxPurgeOperations;\n\t\tError.captureStackTrace(this, PurgeTooLargeError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"PurgeTooLargeError\";\n\t}\n};\n/** A regular write carried an action type only the reactor issues. Terminal. */\nvar ReservedActionError = class ReservedActionError extends Error {\n\tdocumentId;\n\tactionType;\n\tconstructor(documentId, actionType) {\n\t\tsuper(`Action ${actionType} is reserved and cannot be submitted to document ${documentId}`);\n\t\tthis.name = \"ReservedActionError\";\n\t\tthis.documentId = documentId;\n\t\tthis.actionType = actionType;\n\t\tError.captureStackTrace(this, ReservedActionError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"ReservedActionError\";\n\t}\n};\n/**\n* An authorization preflight was asked for while the reactor's decision model\n* is off, so there is no model to answer from.\n*\n* Thrown rather than answered from the legacy host-side permission tables. The\n* two systems do not compose: the tables record which addresses a host lets\n* near a drive, the policy records what a document's own grants permit, and an\n* answer stitched from both would report an admission verdict neither system\n* would reach. A caller that cannot get a prediction disables nothing, which\n* leaves the submit path -- and its real gate -- as the only authority.\n*\n* Detection is by `name`, not `instanceof`: the SharedWorker RPC boundary\n* rebuilds a thrown error from `{ name, message, stack, cause }` alone\n* (`reactor-browser/src/rpc/error-info.ts`), so the class identity and any\n* custom field are lost in transit. This error therefore carries no fields.\n*/\nvar AuthEnforcementDisabledError = class AuthEnforcementDisabledError extends Error {\n\tconstructor() {\n\t\tsuper(\"Authorization evaluation requires the authEnforcement feature flag; this reactor holds no decision model, and the legacy host-table permission system cannot answer for one\");\n\t\tthis.name = \"AuthEnforcementDisabledError\";\n\t\tError.captureStackTrace(this, AuthEnforcementDisabledError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AuthEnforcementDisabledError\";\n\t}\n};\n/**\n* Error thrown when a relationship edge an operation names does not exist.\n*\n* Detection is by `name`, not `instanceof`: the SharedWorker RPC boundary\n* rebuilds a thrown error from `{ name, message, stack, cause }` alone\n* (`reactor-browser/src/rpc/error-info.ts`), so the class identity is lost in\n* transit.\n*/\nvar RelationshipNotFoundError = class RelationshipNotFoundError extends Error {\n\tsourceId;\n\ttargetId;\n\trelationshipType;\n\tconstructor(sourceId, targetId, relationshipType) {\n\t\tsuper(`No ${relationshipType} relationship from ${sourceId} to ${targetId}`);\n\t\tthis.name = \"RelationshipNotFoundError\";\n\t\tthis.sourceId = sourceId;\n\t\tthis.targetId = targetId;\n\t\tthis.relationshipType = relationshipType;\n\t\tError.captureStackTrace(this, RelationshipNotFoundError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"RelationshipNotFoundError\";\n\t}\n};\n/** The store holds documents at protocol versions this reactor does not run. */\nvar UnsupportedStoredProtocolError = class UnsupportedStoredProtocolError extends Error {\n\tversions;\n\tdocuments;\n\tconstructor(versions, documents) {\n\t\tconst named = versions.map(({ protocol, version }) => `${protocol} ${version}`).join(\", \");\n\t\tsuper(`${documents} stored document(s) require ${named}, which this reactor does not run. Start a build that runs them, or accept them read-only with withUnsupportedStoredDocuments(\"read-only\")`);\n\t\tthis.name = \"UnsupportedStoredProtocolError\";\n\t\tthis.versions = versions;\n\t\tthis.documents = documents;\n\t\tError.captureStackTrace(this, UnsupportedStoredProtocolError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"UnsupportedStoredProtocolError\";\n\t}\n};\n/**\n* A batch job failed. A batch is not atomic, so `jobs` holds every job's final\n* state, keyed by plan key; `cause` carries the failed job's own error name.\n*\n* The SharedWorker RPC boundary rebuilds a thrown error from `{ name, message,\n* stack, cause }` alone (`src/rpc/error-info.ts`), so `key` and\n* `jobs` do not survive it. `isError` therefore checks for them, not only the\n* name; across that boundary, classify by the `cause` chain's names instead.\n*/\nvar BatchJobFailedError = class BatchJobFailedError extends Error {\n\tkey;\n\tjobs;\n\tconstructor(key, jobs) {\n\t\tconst failure = jobs[key].error;\n\t\tconst cause = new Error(failure?.message ?? \"Job failed\");\n\t\tcause.name = failure?.name ?? \"Error\";\n\t\tsuper(failure?.message ?? \"Job failed\", { cause });\n\t\tthis.name = \"BatchJobFailedError\";\n\t\tthis.key = key;\n\t\tthis.jobs = jobs;\n\t\tError.captureStackTrace(this, BatchJobFailedError);\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"BatchJobFailedError\" && typeof error.key === \"string\" && typeof error.jobs === \"object\";\n\t}\n};\n//#endregion\n//#region src/storage/interfaces.ts\n/**\n* Thrown when an operation with the same identity already exists in the store.\n*/\nvar DuplicateOperationError = class extends Error {\n\tconstructor(description) {\n\t\tsuper(`Duplicate operation: ${description}`);\n\t\tthis.name = \"DuplicateOperationError\";\n\t}\n};\n/**\n* Thrown when a concurrent write conflict is detected during an atomic apply.\n*/\nvar OptimisticLockError = class extends Error {\n\tconstructor(message) {\n\t\tsuper(message);\n\t\tthis.name = \"OptimisticLockError\";\n\t}\n};\n/**\n* Thrown when the caller-provided revision does not match the current\n* stored revision, indicating a stale read.\n*/\nvar RevisionMismatchError = class extends Error {\n\tconstructor(expected, actual) {\n\t\tsuper(`Revision mismatch: expected ${expected}, got ${actual}`);\n\t\tthis.name = \"RevisionMismatchError\";\n\t}\n};\n/**\n* A create based on an empty stream that already has operations: the id is\n* taken, and no retry can resolve it. Matched by `name`, all the RPC boundary keeps.\n*/\nvar DocumentAlreadyExistsError = class extends Error {\n\tdocumentId;\n\tconstructor(documentId, scope, headRevision) {\n\t\tsuper(`Document ${documentId} already exists: create requested revision 0 but the \"${scope}\" stream is at revision ${headRevision}`);\n\t\tthis.name = \"DocumentAlreadyExistsError\";\n\t\tthis.documentId = documentId;\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"DocumentAlreadyExistsError\";\n\t}\n};\n/** Error history keeps messages, not classes, so failures match by prefix. */\nconst APPEND_CONDITION_FAILED_PREFIX = \"Append condition failed: \";\n/**\n* A read-set stream grew before the append committed. A concurrency\n* conflict, not a fault: the caller retries against the new stream heads.\n*/\nvar AppendConditionFailedError = class extends Error {\n\tcondition;\n\tconstructor(condition) {\n\t\tconst streams = condition.streams.map((s) => `${s.documentId}:${s.scope}:${s.branch}@${s.revision}`).join(\", \");\n\t\tsuper(`${APPEND_CONDITION_FAILED_PREFIX}a read-set stream advanced [${streams}]`);\n\t\tthis.condition = condition;\n\t\tthis.name = \"AppendConditionFailedError\";\n\t}\n\tstatic isError(error) {\n\t\treturn Error.isError(error) && error.name === \"AppendConditionFailedError\";\n\t}\n\t/** True when a recorded error message is an append-condition failure. */\n\tstatic isFailureMessage(message) {\n\t\treturn message.startsWith(APPEND_CONDITION_FAILED_PREFIX);\n\t}\n};\n/**\n* Which sense of \"exists\" a caller of {@link IDocumentView.exists} means.\n*/\nlet DocumentExistence = /* @__PURE__ */ function(DocumentExistence) {\n\t/**\n\t* A document that is present and not deleted. This is the question a read\n\t* asks: a deleted document is not readable, so it does not exist.\n\t*/\n\tDocumentExistence[\"LiveOnly\"] = \"LiveOnly\";\n\t/**\n\t* Whether the id is taken, deleted or not. This is the question a write\n\t* asks: a deleted document keeps its operation stream, so its id can never\n\t* be reused, and answering from snapshots alone would say otherwise whenever\n\t* a snapshot row is missing while the stream is intact.\n\t*/\n\tDocumentExistence[\"IncludingDeleted\"] = \"IncludingDeleted\";\n\treturn DocumentExistence;\n}({});\n//#endregion\n//#region src/executor/util.ts\n/** Actions the reactor reduces itself, onto the document scope. */\nconst DOCUMENT_SCOPE_ACTIONS = DOCUMENT_SCOPE_ACTION_TYPES;\n/**\n* `CREATE_DOCUMENT` is exempt by necessity: it runs before the document exists,\n* so building a decision model would throw and defer the job forever.\n*/\nconst GATED_DOCUMENT_ACTIONS = new Set([...DOCUMENT_SCOPE_ACTIONS].filter((type) => type !== \"CREATE_DOCUMENT\"));\n/**\n* Creates a PHDocument from a CREATE_DOCUMENT action input.\n* Reconstructs the document header and initializes the base state.\n*\n* @param action - The CREATE_DOCUMENT action containing the document parameters\n* @returns A newly constructed PHDocument with initialized header and base state\n*/\nfunction createDocumentFromAction(action) {\n\tconst input = action.input;\n\tconst header = createPresignedHeader();\n\theader.id = input.documentId;\n\theader.documentType = input.model;\n\tif (input.signing) {\n\t\theader.createdAtUtcIso = input.signing.createdAtUtcIso;\n\t\theader.lastModifiedAtUtcIso = input.signing.createdAtUtcIso;\n\t\theader.sig = {\n\t\t\tpublicKey: input.signing.publicKey,\n\t\t\tnonce: input.signing.nonce\n\t\t};\n\t}\n\tif (input.slug !== void 0) header.slug = input.slug;\n\tif (!header.slug) header.slug = input.documentId;\n\tif (input.name !== void 0) header.name = input.name;\n\tif (input.branch !== void 0) header.branch = input.branch;\n\tif (input.meta !== void 0) header.meta = input.meta;\n\tif (input.protocolVersions !== void 0) header.protocolVersions = input.protocolVersions;\n\tconst baseState = defaultBaseState();\n\treturn {\n\t\theader,\n\t\toperations: {},\n\t\tstate: baseState,\n\t\tinitialState: baseState,\n\t\tclipboard: []\n\t};\n}\n/**\n* Calculate the next operation index for a specific scope.\n* Each scope maintains its own independent index sequence.\n*\n* Per-scope indexing means:\n* - Each scope (document, global, local, etc.) has independent indexes\n* - Indexes start at 0 for each scope\n* - Different scopes can have operations with the same index value\n*\n* This function uses header.revision which is populated by the cache/storage layer\n* and contains the next available index for each scope. This design avoids requiring\n* the full operation history to be loaded, which is crucial for snapshot-based caching.\n*\n* @param document - The document whose header.revision to inspect\n* @param scope - The scope to calculate the next index for\n* @returns The next available index in the specified scope\n*/\nconst getNextIndexForScope = (document, scope) => {\n\treturn document.header.revision[scope] || 0;\n};\n/**\n* Creates an empty consistency token with no coordinates.\n* Used when a job is registered or fails without writing operations.\n*\n* @returns A consistency token with an empty coordinates array\n*/\nfunction createEmptyConsistencyToken() {\n\treturn {\n\t\tversion: 1,\n\t\tcreatedAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tcoordinates: []\n\t};\n}\n/**\n* Creates a consistency token from operations written during job execution.\n* Maps each operation to a consistency coordinate tracking (documentId, scope, branch, operationIndex).\n* If no operations are provided, returns an empty token.\n*\n* @param operationsWithContext - Array of operations with their execution context\n* @returns A consistency token representing all operations written\n*/\nfunction createConsistencyToken(operationsWithContext) {\n\tif (operationsWithContext.length === 0) return createEmptyConsistencyToken();\n\tconst coordinates = [];\n\tfor (let i = 0; i < operationsWithContext.length; i++) {\n\t\tconst opWithContext = operationsWithContext[i];\n\t\tcoordinates.push({\n\t\t\tdocumentId: opWithContext.context.documentId,\n\t\t\tscope: opWithContext.context.scope,\n\t\t\tbranch: opWithContext.context.branch,\n\t\t\toperationIndex: opWithContext.operation.index\n\t\t});\n\t}\n\treturn {\n\t\tversion: 1,\n\t\tcreatedAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tcoordinates\n\t};\n}\nfunction createOperation(action, index, skip, context) {\n\treturn {\n\t\tid: deriveOperationId(context.documentId, context.scope, context.branch, action.id),\n\t\tindex,\n\t\ttimestampUtcMs: action.timestampUtcMs || (/* @__PURE__ */ new Date()).toISOString(),\n\t\thash: \"\",\n\t\tskip,\n\t\taction\n\t};\n}\nfunction updateDocumentRevision(document, scope, operationIndex) {\n\tdocument.header.revision = {\n\t\t...document.header.revision,\n\t\t[scope]: operationIndex + 1\n\t};\n}\nfunction buildSuccessResult(job, operation, documentId, documentType, resultingState, startTime) {\n\treturn {\n\t\tjob,\n\t\tsuccess: true,\n\t\toperations: [operation],\n\t\toperationsWithContext: [{\n\t\t\toperation,\n\t\t\tcontext: {\n\t\t\t\tdocumentId,\n\t\t\t\tscope: job.scope,\n\t\t\t\tbranch: job.branch,\n\t\t\t\tdocumentType,\n\t\t\t\tresultingState,\n\t\t\t\tordinal: 0\n\t\t\t}\n\t\t}],\n\t\tduration: Date.now() - startTime\n\t};\n}\nfunction buildErrorResult(job, error, startTime) {\n\treturn {\n\t\tjob,\n\t\tsuccess: false,\n\t\terror,\n\t\tduration: Date.now() - startTime\n\t};\n}\n/**\n* The error a refusal surfaces as. Both classes are already terminal in the job\n* result handler, so a refusal never burns a retry.\n*/\nfunction refusalError(reason, documentId, deletedAtUtcIso, action) {\n\tif (reason === DOCUMENT_DELETED_REASON) return new DocumentDeletedError(documentId, deletedAtUtcIso);\n\treturn new AuthorizationDeniedError(documentId, action.scope, action.type, action.context?.signer?.user.address);\n}\n/**\n* Whether this operation is part of the document's creation. The create and the\n* upgrade from version zero hold the first two indexes for the life of the\n* document, so a reshuffle has to leave them where they are.\n*/\nfunction isGenesisOperation(operation) {\n\tif (operation.action.type === \"CREATE_DOCUMENT\") return true;\n\tif (operation.action.type !== \"UPGRADE_DOCUMENT\") return false;\n\treturn operation.action.input.fromVersion === 0;\n}\n/**\n* The distinct streams a job wrote, collected so a rollback knows what to evict.\n*\n* A write records its stream on every apply, and a long run applies the same\n* stream hundreds of times, so this keeps one entry per stream rather than one\n* per write: the eviction only cares which streams were touched, and the\n* successful jobs that never read this back pay for a lookup instead of an\n* allocation.\n*/\nvar TouchedStreams = class {\n\tstreams = /* @__PURE__ */ new Map();\n\tadd(documentId, scope, branch) {\n\t\tconst key = `${documentId}\\u0000${scope}\\u0000${branch}`;\n\t\tif (this.streams.has(key)) return;\n\t\tthis.streams.set(key, {\n\t\t\tdocumentId,\n\t\t\tscope,\n\t\t\tbranch\n\t\t});\n\t}\n\t[Symbol.iterator]() {\n\t\treturn this.streams.values();\n\t}\n};\n/**\n* The ids of the actions the caller handed to a job. Load and reevaluation\n* jobs write operations nobody submitted, so they report none.\n*/\nfunction submittedActionIds(job) {\n\treturn job.kind === \"mutation\" ? job.actions.map((action) => action.id) : [];\n}\n/**\n* Reports what became of each submitted action.\n*\n* A job's operations can include ones it only moved to a new index, so only\n* those carrying a submitted action are reported. Returns undefined when the\n* job submitted nothing, which keeps `JobInfo.result` null for the jobs that\n* have no caller to answer to.\n*/\nfunction summarizeSubmittedActions(operations, submitted) {\n\tif (!submitted || submitted.length === 0) return;\n\tconst ids = new Set(submitted);\n\tconst actions = [];\n\tfor (const { operation, context } of operations) {\n\t\tif (!ids.has(operation.action.id)) continue;\n\t\tactions.push({\n\t\t\tactionId: operation.action.id,\n\t\t\tscope: context.scope,\n\t\t\tindex: operation.index,\n\t\t\t...operationOutcome(operation)\n\t\t});\n\t}\n\tif (actions.length === 0) return;\n\treturn {\n\t\tactions,\n\t\tallApplied: actions.every((action) => action.kind === \"applied\")\n\t};\n}\n/** Tombstones a job has read, each under the shared lock it took first. */\nvar PurgeFence = class {\n\tlocks;\n\tchecked;\n\tpurged;\n\tconstructor(locks, checked, purged) {\n\t\tthis.locks = locks;\n\t\tthis.checked = checked;\n\t\tthis.purged = purged;\n\t}\n\t/** Locks and reads an id the job start did not resolve. */\n\tasync isPurged(documentId) {\n\t\tawait this.isPurgedMany([documentId]);\n\t\treturn this.purged.has(documentId);\n\t}\n\t/** Locks and reads the unresolved ids in one lock and one lookup. */\n\tasync isPurgedMany(documentIds) {\n\t\tconst unchecked = [...new Set(documentIds)].filter((id) => !this.checked.has(id));\n\t\tif (unchecked.length > 0) {\n\t\t\tawait this.locks.shared(unchecked);\n\t\t\tconst found = await this.locks.purged(unchecked);\n\t\t\tfor (const id of unchecked) this.checked.add(id);\n\t\t\tfor (const id of found) this.purged.add(id);\n\t\t}\n\t\treturn new Set(documentIds.filter((id) => this.purged.has(id)));\n\t}\n};\n/** Locks and checks an id on its first read; a purged id reads as purged. */\nvar FencedWriteCache = class {\n\tinner;\n\tpurgeFence;\n\tevict;\n\tevicted = /* @__PURE__ */ new Set();\n\tconstructor(inner, purgeFence, evict) {\n\t\tthis.inner = inner;\n\t\tthis.purgeFence = purgeFence;\n\t\tthis.evict = evict;\n\t}\n\t/** Fences ids known before their reads in one round trip. */\n\tasync fence(documentIds) {\n\t\tawait this.purgeFence.isPurgedMany(documentIds);\n\t}\n\tasync getState(documentId, scope, branch, targetRevision, signal) {\n\t\tif (await this.purgeFence.isPurged(documentId)) {\n\t\t\tif (!this.evicted.has(documentId)) {\n\t\t\t\tthis.evicted.add(documentId);\n\t\t\t\tthis.evict(documentId);\n\t\t\t}\n\t\t\tthrow new DocumentPurgedError(documentId);\n\t\t}\n\t\treturn this.inner.getState(documentId, scope, branch, targetRevision, signal);\n\t}\n\tputState(documentId, scope, branch, revision, document, position) {\n\t\tthis.inner.putState(documentId, scope, branch, revision, document, position);\n\t}\n\tputRun(documentId, scope, branch, run) {\n\t\tthis.inner.putRun(documentId, scope, branch, run);\n\t}\n\tinvalidate(documentId, scope, branch) {\n\t\treturn this.inner.invalidate(documentId, scope, branch);\n\t}\n\tclear() {\n\t\tthis.inner.clear();\n\t}\n\tstartup() {\n\t\treturn this.inner.startup();\n\t}\n\tshutdown() {\n\t\treturn this.inner.shutdown();\n\t}\n};\n/** The target whose membership an ADD or REMOVE_RELATIONSHIP writes. */\nfunction relationshipTarget(action) {\n\tif (action.type !== \"ADD_RELATIONSHIP\" && action.type !== \"REMOVE_RELATIONSHIP\") return;\n\tconst target = action.input?.targetId;\n\treturn typeof target === \"string\" && target.length > 0 ? target : void 0;\n}\n/** The ids a job's locks cover, sorted: its write ids and groups it names. */\nfunction jobWriteIds(job) {\n\tconst ids = /* @__PURE__ */ new Set([job.documentId]);\n\tconst actions = [...job.actions, ...job.operations.map((operation) => operation.action)];\n\tfor (const action of actions) {\n\t\tif (DOCUMENT_SCOPE_ACTIONS.has(action.type)) ids.add(targetDocumentId(action, job.documentId));\n\t\tconst target = relationshipTarget(action);\n\t\tif (target !== void 0) ids.add(target);\n\t\tif (action.scope === \"auth\") for (const groupId of mentionedGroupIds(action)) ids.add(groupId);\n\t}\n\treturn [...ids].sort();\n}\n//#endregion\n//#region src/cache/collection-membership-cache.ts\nvar CollectionMembershipCache = class CollectionMembershipCache {\n\toperationIndex;\n\tcache = /* @__PURE__ */ new Map();\n\tconstructor(operationIndex) {\n\t\tthis.operationIndex = operationIndex;\n\t}\n\twithScopedIndex(operationIndex) {\n\t\tconst scoped = new CollectionMembershipCache(operationIndex);\n\t\tscoped.cache = this.cache;\n\t\treturn scoped;\n\t}\n\tasync getCollectionsForDocuments(documentIds) {\n\t\tconst result = {};\n\t\tconst missing = [];\n\t\tfor (const docId of documentIds) {\n\t\t\tconst cached = this.cache.get(docId);\n\t\t\tif (cached !== void 0) result[docId] = cached;\n\t\t\telse missing.push(docId);\n\t\t}\n\t\tif (missing.length > 0) {\n\t\t\tconst fromDb = await this.operationIndex.getCollectionsForDocuments(missing);\n\t\t\tfor (const docId of missing) {\n\t\t\t\tconst collections = fromDb[docId] ?? [];\n\t\t\t\tresult[docId] = collections;\n\t\t\t\tthis.cache.set(docId, collections);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\tinvalidate(documentId) {\n\t\tthis.cache.delete(documentId);\n\t}\n};\n//#endregion\n//#region src/cache/lru/lru-tracker.ts\nvar LRUNode = class {\n\tkey;\n\tprev;\n\tnext;\n\tconstructor(key) {\n\t\tthis.key = key;\n\t\tthis.prev = void 0;\n\t\tthis.next = void 0;\n\t}\n};\nvar LRUTracker = class {\n\tmap;\n\thead;\n\ttail;\n\tconstructor() {\n\t\tthis.map = /* @__PURE__ */ new Map();\n\t\tthis.head = void 0;\n\t\tthis.tail = void 0;\n\t}\n\tget size() {\n\t\treturn this.map.size;\n\t}\n\ttouch(key) {\n\t\tconst node = this.map.get(key);\n\t\tif (node) this.moveToFront(node);\n\t\telse this.addToFront(key);\n\t}\n\tevict() {\n\t\tif (!this.tail) return;\n\t\tconst key = this.tail.key;\n\t\tthis.remove(key);\n\t\treturn key;\n\t}\n\tremove(key) {\n\t\tconst node = this.map.get(key);\n\t\tif (!node) return;\n\t\tthis.removeNode(node);\n\t\tthis.map.delete(key);\n\t}\n\tclear() {\n\t\tthis.map.clear();\n\t\tthis.head = void 0;\n\t\tthis.tail = void 0;\n\t}\n\taddToFront(key) {\n\t\tconst node = new LRUNode(key);\n\t\tthis.map.set(key, node);\n\t\tif (!this.head) {\n\t\t\tthis.head = node;\n\t\t\tthis.tail = node;\n\t\t} else {\n\t\t\tnode.next = this.head;\n\t\t\tthis.head.prev = node;\n\t\t\tthis.head = node;\n\t\t}\n\t}\n\tmoveToFront(node) {\n\t\tif (node === this.head) return;\n\t\tthis.removeNode(node);\n\t\tnode.prev = void 0;\n\t\tnode.next = this.head;\n\t\tif (this.head) this.head.prev = node;\n\t\tthis.head = node;\n\t\tif (!this.tail) this.tail = node;\n\t}\n\tremoveNode(node) {\n\t\tif (node.prev) node.prev.next = node.next;\n\t\telse this.head = node.next;\n\t\tif (node.next) node.next.prev = node.prev;\n\t\telse this.tail = node.prev;\n\t}\n};\n//#endregion\n//#region src/cache/document-meta-cache.ts\n/**\n* In-memory document metadata cache with LRU eviction.\n*\n* Caches PHDocumentState per (documentId, branch) key. On cache miss,\n* rebuilds from document scope operations. Provides an explicit cross-scope\n* contract for accessing document scope metadata.\n*\n* **Thread Safety:**\n* Not thread-safe. Designed for single-threaded job executor environment.\n*/\nvar DocumentMetaCache = class DocumentMetaCache {\n\tcache;\n\tlruTracker;\n\toperationStore;\n\tconfig;\n\tconstructor(operationStore, config) {\n\t\tthis.operationStore = operationStore;\n\t\tthis.config = { maxDocuments: config.maxDocuments };\n\t\tthis.cache = /* @__PURE__ */ new Map();\n\t\tthis.lruTracker = new LRUTracker();\n\t}\n\twithScopedStore(operationStore) {\n\t\tconst scoped = new DocumentMetaCache(operationStore, this.config);\n\t\tscoped.cache = this.cache;\n\t\tscoped.lruTracker = this.lruTracker;\n\t\treturn scoped;\n\t}\n\tasync startup() {\n\t\treturn Promise.resolve();\n\t}\n\tasync shutdown() {\n\t\treturn Promise.resolve();\n\t}\n\tasync getDocumentMeta(documentId, branch, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst key = this.makeKey(documentId, branch);\n\t\tconst cached = this.cache.get(key);\n\t\tif (cached) {\n\t\t\tthis.lruTracker.touch(key);\n\t\t\treturn cached;\n\t\t}\n\t\tconst meta = await this.rebuildLatest(documentId, branch, signal);\n\t\tthis.putDocumentMeta(documentId, branch, meta);\n\t\treturn meta;\n\t}\n\tasync rebuildAtRevision(documentId, branch, targetRevision, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\treturn this.rebuildFromOperations(documentId, branch, targetRevision, signal);\n\t}\n\tputDocumentMeta(documentId, branch, meta) {\n\t\tconst key = this.makeKey(documentId, branch);\n\t\tif (!this.cache.has(key) && this.cache.size >= this.config.maxDocuments) {\n\t\t\tconst evictKey = this.lruTracker.evict();\n\t\t\tif (evictKey) this.cache.delete(evictKey);\n\t\t}\n\t\tthis.cache.set(key, structuredClone(meta));\n\t\tthis.lruTracker.touch(key);\n\t}\n\tinvalidate(documentId, branch) {\n\t\tlet evicted = 0;\n\t\tif (branch === void 0) {\n\t\t\tfor (const key of this.cache.keys()) if (key.startsWith(`${documentId}:`)) {\n\t\t\t\tthis.cache.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t} else {\n\t\t\tconst key = this.makeKey(documentId, branch);\n\t\t\tif (this.cache.has(key)) {\n\t\t\t\tthis.cache.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted = 1;\n\t\t\t}\n\t\t}\n\t\treturn evicted;\n\t}\n\tclear() {\n\t\tthis.cache.clear();\n\t\tthis.lruTracker.clear();\n\t}\n\tmakeKey(documentId, branch) {\n\t\treturn `${documentId}:${branch}`;\n\t}\n\tasync rebuildLatest(documentId, branch, signal) {\n\t\treturn this.rebuildFromOperations(documentId, branch, void 0, signal);\n\t}\n\tasync rebuildFromOperations(documentId, branch, targetRevision, signal) {\n\t\tconst docScopeOps = await this.operationStore.getSince(documentId, \"document\", branch, -1, void 0, void 0, signal);\n\t\tif (docScopeOps.results.length === 0) throw new DocumentNotFoundError(documentId);\n\t\tconst createOp = docScopeOps.results[0];\n\t\tif (isPurgeMarker(createOp)) return purgedMeta(createOp.action);\n\t\tif (createOp.action.type !== \"CREATE_DOCUMENT\") throw new Error(`Invalid document: first operation must be CREATE_DOCUMENT, found ${createOp.action.type}`);\n\t\tconst createAction = createOp.action;\n\t\tconst documentType = createAction.input.model;\n\t\tlet document = createDocumentFromAction(createAction);\n\t\tlet documentScopeRevision = 0;\n\t\tlet purged = false;\n\t\tfor (const op of docScopeOps.results) {\n\t\t\tif (targetRevision !== void 0 && op.index > targetRevision) break;\n\t\t\tdocumentScopeRevision = op.index;\n\t\t\tif (op.action.type === \"UPGRADE_DOCUMENT\") {\n\t\t\t\tconst upgradeAction = op.action;\n\t\t\t\tdocument = applyUpgradeDocumentAction$1(document, upgradeAction);\n\t\t\t} else if (op.action.type === \"DELETE_DOCUMENT\" || op.action.type === PURGE_DOCUMENT) {\n\t\t\t\tdocument = applyDeleteDocumentAction$1(document, op.action);\n\t\t\t\tpurged ||= op.action.type === PURGE_DOCUMENT;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tstate: document.state.document,\n\t\t\tdocumentType,\n\t\t\tprotocolVersions: purged ? purgedProtocolVersions() : createAction.input.protocolVersions,\n\t\t\tdocumentScopeRevision: documentScopeRevision + 1\n\t\t};\n\t}\n};\n/** A lone marker has no CREATE_DOCUMENT; the marker describes the stream. */\nfunction purgedMeta(action) {\n\treturn {\n\t\tstate: createDocumentState({\n\t\t\tisDeleted: true,\n\t\t\tdeletedAtUtcIso: action.input.purgedAtUtcIso\n\t\t}),\n\t\tdocumentType: action.input.documentType,\n\t\tprotocolVersions: purgedProtocolVersions(),\n\t\tdocumentScopeRevision: 1\n\t};\n}\n//#endregion\n//#region src/catch-up/settled-watermark.ts\nconst MAX_PENDING_PROBES = 64;\n/** pg_sequence_last_value needs 10; pg_current_* replaced txid_* in 13. */\nfunction snapshotFunctionsFor(serverVersionNum) {\n\tif (serverVersionNum >= 13e4) return {\n\t\tsnapshot: \"pg_current_snapshot\",\n\t\tcurrentXid: \"pg_current_xact_id\",\n\t\txidIfAssigned: \"pg_current_xact_id_if_assigned\"\n\t};\n\tif (serverVersionNum >= 1e5) return {\n\t\tsnapshot: \"txid_current_snapshot\",\n\t\tcurrentXid: \"txid_current\",\n\t\txidIfAssigned: \"txid_current_if_assigned\"\n\t};\n\tthrow new Error(`PostgreSQL server_version_num ${serverVersionNum} is not supported: read-side catch-up needs 10 or later`);\n}\n/** Parses the `xmin:xmax:xip,...` text form of a snapshot. */\nfunction parseSnapshot(text) {\n\tconst parts = text.split(\":\");\n\tif (parts.length !== 3) throw new Error(`Malformed snapshot: ${text}`);\n\tconst [xmin, xmax, xip] = parts;\n\treturn {\n\t\txmin: BigInt(xmin),\n\t\txmax: BigInt(xmax),\n\t\txip: xip === \"\" ? [] : xip.split(\",\").map((xid) => BigInt(xid))\n\t};\n}\nasync function readSnapshotFunctions(db) {\n\tconst result = await sql`select current_setting('server_version_num') as version`.execute(db);\n\treturn snapshotFunctionsFor(Number(result.rows[0].version));\n}\n/** A probe settles once an xmin passes the xid it took after its head. */\nvar ProbeSettler = class {\n\tsettled = 0;\n\tlastHead = 0;\n\tcovered = 0;\n\tlastXip = [];\n\tpending = [];\n\tget settledThrough() {\n\t\treturn this.settled;\n\t}\n\tget head() {\n\t\treturn this.lastHead;\n\t}\n\t/** The highest head a settled or pending probe covers. */\n\tget probedHead() {\n\t\treturn this.covered;\n\t}\n\tobserve(head, xid, snapshot, nowUtcMs) {\n\t\tthis.lastHead = Math.max(this.lastHead, head);\n\t\tthis.lastXip = snapshot.xip;\n\t\tif (xid !== null && head > this.covered) {\n\t\t\tthis.covered = head;\n\t\t\tthis.pending.push({\n\t\t\t\thead,\n\t\t\t\txid,\n\t\t\t\ttakenAtUtcMs: nowUtcMs\n\t\t\t});\n\t\t\tif (this.pending.length > MAX_PENDING_PROBES) this.pending.shift();\n\t\t}\n\t\tconst stillPending = [];\n\t\tfor (const probe of this.pending) if (snapshot.xmin > probe.xid) this.settled = Math.max(this.settled, probe.head);\n\t\telse stillPending.push(probe);\n\t\tthis.pending = stillPending.filter((probe) => probe.head > this.settled);\n\t\treturn this.settled;\n\t}\n\t/** Xids an unsettled probe still waits on. */\n\twaitingOn() {\n\t\tif (this.pending.length === 0) return [];\n\t\tconst xid = this.pending[0].xid;\n\t\treturn this.lastXip.filter((open) => open < xid).map((open) => open.toString());\n\t}\n\tstalledSinceUtcMs() {\n\t\treturn this.pending[0]?.takenAtUtcMs;\n\t}\n};\nfunction operationIndexTableName(db) {\n\tconst from = db.selectFrom(\"operation_index_operations\").selectAll().toOperationNode().from?.froms[0];\n\tconst schema = from !== void 0 && TableNode.is(from) ? from.table.schema?.name : void 0;\n\tconst quote = (identifier) => `\"${identifier.replace(/\"/g, \"\\\"\\\"\")}\"`;\n\treturn schema === void 0 ? quote(\"operation_index_operations\") : `${quote(schema)}.${quote(\"operation_index_operations\")}`;\n}\n/** Reads the head, takes and commits an xid, then reads a snapshot, in order. */\nfunction createKyselyWatermarkProbe(db) {\n\tlet resolved = null;\n\tconst resolve = async () => {\n\t\tconst fns = await readSnapshotFunctions(db);\n\t\tconst table = operationIndexTableName(db);\n\t\tconst sequence = (await sql`select pg_get_serial_sequence(${table}, 'ordinal') as sequence`.execute(db)).rows[0]?.sequence;\n\t\tif (!sequence) throw new Error(`No ordinal sequence found for ${table}`);\n\t\treturn {\n\t\t\tfns,\n\t\t\tsequence\n\t\t};\n\t};\n\treturn async (probedHead) => {\n\t\tresolved ??= resolve().catch((error) => {\n\t\t\tresolved = null;\n\t\t\tthrow error;\n\t\t});\n\t\tconst { fns, sequence } = await resolved;\n\t\tconst headRow = (await sql`select coalesce(pg_sequence_last_value(${sequence}::regclass), 0) as head, ${sql.raw(fns.xidIfAssigned)}() is null as outside_write`.execute(db)).rows[0];\n\t\tconst head = Number(headRow.head);\n\t\tlet xid = null;\n\t\tif (headRow.outside_write && head > probedHead) {\n\t\t\tconst xidResult = await sql`select ${sql.raw(fns.currentXid)}()::text as xid`.execute(db);\n\t\t\txid = BigInt(xidResult.rows[0].xid);\n\t\t}\n\t\tconst row = (await sql`select ${sql.raw(fns.snapshot)}()::text as snapshot, ${sql.raw(fns.xidIfAssigned)}() is null as outside_write`.execute(db)).rows[0];\n\t\treturn {\n\t\t\thead,\n\t\t\txid,\n\t\t\tsnapshot: parseSnapshot(row.snapshot),\n\t\t\toutsideWrite: headRow.outside_write && row.outside_write\n\t\t};\n\t};\n}\n/** Knows when an ordinal gap is final by asking which transactions are open. */\nvar SettledWatermark = class {\n\tprobe;\n\tlogger;\n\tnow;\n\tsettler = new ProbeSettler();\n\tlisteners = /* @__PURE__ */ new Set();\n\tcurrent;\n\tnext;\n\twarnedInsideWrite = false;\n\tconstructor(probe, logger, now = Date.now) {\n\t\tthis.probe = probe;\n\t\tthis.logger = logger;\n\t\tthis.now = now;\n\t}\n\tget settledThrough() {\n\t\treturn this.settler.settledThrough;\n\t}\n\trefresh(signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (this.next !== void 0) return this.next;\n\t\tif (this.current === void 0) return this.start();\n\t\tconst next = this.current.catch(() => this.settledThrough).then(() => {\n\t\t\tthis.next = void 0;\n\t\t\treturn this.start();\n\t\t});\n\t\tthis.next = next;\n\t\treturn next;\n\t}\n\tonAdvance(listener) {\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\tstatus() {\n\t\tconst stalledSinceUtcMs = this.settler.head > this.settledThrough ? this.settler.stalledSinceUtcMs() : void 0;\n\t\treturn {\n\t\t\thead: this.settler.head,\n\t\t\tsettledThrough: this.settledThrough,\n\t\t\twaitingOn: this.settler.waitingOn(),\n\t\t\t...stalledSinceUtcMs !== void 0 ? { stalledSinceUtcMs } : {}\n\t\t};\n\t}\n\tstart() {\n\t\tconst run = this.probeOnce().finally(() => {\n\t\t\tif (this.current === run) this.current = void 0;\n\t\t});\n\t\tthis.current = run;\n\t\treturn run;\n\t}\n\tasync probeOnce() {\n\t\tconst reading = await this.probe(this.settler.probedHead);\n\t\tif (!reading.outsideWrite) {\n\t\t\tif (!this.warnedInsideWrite) {\n\t\t\t\tthis.warnedInsideWrite = true;\n\t\t\t\tthis.logger.warn(\"settled watermark probe ran inside another session's write transaction; discarded\");\n\t\t\t}\n\t\t\treturn this.settledThrough;\n\t\t}\n\t\tconst before = this.settledThrough;\n\t\tconst after = this.settler.observe(reading.head, reading.xid, reading.snapshot, this.now());\n\t\tif (after > before) for (const listener of this.listeners) try {\n\t\t\tlistener(after);\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\"settled watermark listener failed: @error\", error);\n\t\t}\n\t\treturn after;\n\t}\n};\n/** Sessions holding these xids open; empty without pg_stat_activity. */\nasync function describeWaitingSessions(db, xids) {\n\tif (xids.length === 0) return [];\n\tconst epochless = xids.map((xid) => (BigInt(xid) % 2n ** 32n).toString());\n\ttry {\n\t\treturn (await sql`select pid, application_name, state, xact_start, backend_xid::text as xid\n from pg_stat_activity\n where backend_xid::text in (${sql.join(epochless)})`.execute(db)).rows.map((row) => ({\n\t\t\tpid: Number(row.pid),\n\t\t\tapplicationName: row.application_name ?? \"\",\n\t\t\tstate: row.state ?? \"\",\n\t\t\txactStart: row.xact_start === null ? null : new Date(row.xact_start).toISOString(),\n\t\t\txid: row.xid\n\t\t}));\n\t} catch {\n\t\treturn [];\n\t}\n}\n//#endregion\n//#region src/storage/kysely/document-purges.ts\n/** Class key of every purge lock; the stream locks use the single-key space. */\nconst PURGE_NS = 1347571013;\n/** Ids share this many lock keys, so a job's lock count stays bounded. */\nconst PURGE_LOCK_BUCKETS = 1024;\nasync function acquirePurgeLocks(trx, ids, mode) {\n\tconst unique = [...new Set(ids)];\n\tif (unique.length === 0) return;\n\tconst lock = sql.raw(mode === \"shared\" ? \"pg_advisory_xact_lock_shared\" : \"pg_advisory_xact_lock\");\n\tawait sql`\n with keys as materialized (\n select distinct hashtext(id) & ${sql.lit(1023)} as key\n from unnest(${unique}::text[]) as t(id)\n order by key\n )\n select ${lock}(${sql.lit(PURGE_NS)}, key) from keys order by key\n `.execute(trx);\n}\n/** The ids among `ids` that have a tombstone, read in the handle's schema. */\nasync function findPurged(db, ids) {\n\tconst unique = [...new Set(ids)];\n\tif (unique.length === 0) return /* @__PURE__ */ new Set();\n\tconst rows = await db.selectFrom(\"document_purges\").select(\"documentId\").where(sql`\"documentId\" = any(${unique}::text[])`).execute();\n\treturn new Set(rows.map((row) => row.documentId));\n}\n/** Every tombstoned id, read in the handle's schema. */\nasync function listPurged(db) {\n\treturn (await db.selectFrom(\"document_purges\").select(\"documentId\").orderBy(\"documentId\").execute()).map((row) => row.documentId);\n}\n/** Bind slots per statement: 16-bit on the wire, read signed in-process. */\nconst MAX_BIND_PARAMETERS = 32767;\n/** Splits rows into runs that each bind at most MAX_BIND_PARAMETERS. */\nfunction chunkRows(rows) {\n\tif (rows.length === 0) return [];\n\tconst columnsPerRow = Math.max(1, Object.keys(rows[0]).length);\n\tconst perChunk = Math.max(1, Math.floor(MAX_BIND_PARAMETERS / columnsPerRow));\n\tif (rows.length <= perChunk) return [rows];\n\tconst chunks = [];\n\tfor (let i = 0; i < rows.length; i += perChunk) chunks.push(rows.slice(i, i + perChunk));\n\treturn chunks;\n}\n/** Per database: the function that assigns the transaction's xid. */\nconst xidFunctions = /* @__PURE__ */ new WeakMap();\nvar KyselyOperationIndexTxn = class {\n\tcollections = [];\n\tcollectionMemberships = [];\n\tcollectionRemovals = [];\n\tgroupReferences = [];\n\toperations = [];\n\tmembershipInvalidations = /* @__PURE__ */ new Set();\n\t/** Called by the commit as it writes each document_collections row. */\n\trecordMembershipInvalidation(documentId) {\n\t\tthis.membershipInvalidations.add(documentId);\n\t}\n\tgetMembershipInvalidations() {\n\t\treturn [...this.membershipInvalidations];\n\t}\n\tcreateCollection(collectionId) {\n\t\tthis.collections.push(collectionId);\n\t}\n\taddToCollection(collectionId, documentId) {\n\t\tconst lastOpIndex = this.operations.length - 1;\n\t\tif (lastOpIndex < 0) throw new Error(\"addToCollection must be called after write() - no operations in transaction\");\n\t\tthis.collectionMemberships.push({\n\t\t\tcollectionId,\n\t\t\tdocumentId,\n\t\t\toperationIndex: lastOpIndex\n\t\t});\n\t}\n\tremoveFromCollection(collectionId, documentId) {\n\t\tconst lastOpIndex = this.operations.length - 1;\n\t\tif (lastOpIndex < 0) throw new Error(\"removeFromCollection must be called after write() - no operations in transaction\");\n\t\tthis.collectionRemovals.push({\n\t\t\tcollectionId,\n\t\t\tdocumentId,\n\t\t\toperationIndex: lastOpIndex\n\t\t});\n\t}\n\trecordGroupReferences(documentId, groupIds) {\n\t\tconst lastOpIndex = this.operations.length - 1;\n\t\tif (lastOpIndex < 0) throw new Error(\"recordGroupReferences must be called after write() - no operations in transaction\");\n\t\tif (groupIds.length === 0) return;\n\t\tthis.groupReferences.push({\n\t\t\tdocumentId,\n\t\t\tgroupIds,\n\t\t\toperationIndex: lastOpIndex\n\t\t});\n\t}\n\twrite(operations) {\n\t\tthis.operations.push(...operations);\n\t}\n\tgetCollections() {\n\t\treturn this.collections;\n\t}\n\tgetGroupReferenceRecords() {\n\t\treturn this.groupReferences;\n\t}\n\tgetCollectionMembershipRecords() {\n\t\treturn this.collectionMemberships;\n\t}\n\tgetCollectionRemovals() {\n\t\treturn this.collectionRemovals;\n\t}\n\tgetOperations() {\n\t\treturn this.operations;\n\t}\n};\nvar KyselyOperationIndex = class KyselyOperationIndex {\n\tdb;\n\ttrx;\n\tliveIds;\n\tconstructor(db) {\n\t\tthis.db = db;\n\t}\n\tget queryExecutor() {\n\t\treturn this.trx ?? this.db;\n\t}\n\t/** `liveIds`: ids the transaction read untombstoned under its shared lock. */\n\twithTransaction(trx, liveIds) {\n\t\tconst instance = new KyselyOperationIndex(this.db);\n\t\tinstance.trx = trx;\n\t\tinstance.liveIds = liveIds;\n\t\treturn instance;\n\t}\n\tstart() {\n\t\treturn new KyselyOperationIndexTxn();\n\t}\n\tasync commit(txn, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst kyselyTxn = txn;\n\t\tif (this.trx) return this.executeCommit(this.trx, kyselyTxn);\n\t\tlet resultOrdinals = [];\n\t\tawait this.db.transaction().execute(async (trx) => {\n\t\t\tresultOrdinals = await this.executeCommit(trx, kyselyTxn);\n\t\t});\n\t\treturn resultOrdinals;\n\t}\n\t/**\n\t* A policy-driven join: keeps the earliest join so a rediscovered reference\n\t* never shrinks a backfill window remotes already rely on, and reopens a\n\t* closed membership because a policy reference is not a removable one.\n\t*/\n\tasync joinKeepingEarliest(trx, kyselyTxn, documentId, collectionId, ordinal) {\n\t\tkyselyTxn.recordMembershipInvalidation(documentId);\n\t\tawait trx.insertInto(\"document_collections\").values({\n\t\t\tdocumentId,\n\t\t\tcollectionId,\n\t\t\tjoinedOrdinal: ordinal,\n\t\t\tleftOrdinal: null\n\t\t}).onConflict((oc) => oc.columns([\"documentId\", \"collectionId\"]).doUpdateSet({\n\t\t\tjoinedOrdinal: sql`LEAST(\"document_collections\".\"joinedOrdinal\", EXCLUDED.\"joinedOrdinal\")`,\n\t\t\tleftOrdinal: null\n\t\t})).execute();\n\t}\n\tasync executeCommit(trx, kyselyTxn) {\n\t\tconst collections = kyselyTxn.getCollections();\n\t\tconst memberships = kyselyTxn.getCollectionMembershipRecords();\n\t\tconst removals = kyselyTxn.getCollectionRemovals();\n\t\tconst groupReferences = kyselyTxn.getGroupReferenceRecords();\n\t\tconst operations = kyselyTxn.getOperations();\n\t\tif (collections.length > 0) {\n\t\t\tconst collectionRows = collections.map((collectionId) => ({\n\t\t\t\tdocumentId: collectionId,\n\t\t\t\tcollectionId,\n\t\t\t\tjoinedOrdinal: BigInt(0),\n\t\t\t\tleftOrdinal: null\n\t\t\t}));\n\t\t\tfor (const collectionId of collections) kyselyTxn.recordMembershipInvalidation(collectionId);\n\t\t\tfor (const chunk of chunkRows(collectionRows)) await trx.insertInto(\"document_collections\").values(chunk).onConflict((oc) => oc.doNothing()).execute();\n\t\t}\n\t\tlet operationOrdinals = [];\n\t\tif (operations.length > 0) {\n\t\t\tawait this.refusePurgedOperations(trx, operations);\n\t\t\tawait this.assignXid(trx);\n\t\t\tconst operationRows = operations.map((op) => ({\n\t\t\t\topId: op.id || \"\",\n\t\t\t\tdocumentId: op.documentId,\n\t\t\t\tdocumentType: op.documentType,\n\t\t\t\tscope: op.scope,\n\t\t\t\tbranch: op.branch,\n\t\t\t\ttimestampUtcMs: op.timestampUtcMs,\n\t\t\t\tindex: op.index,\n\t\t\t\tskip: op.skip,\n\t\t\t\thash: op.hash,\n\t\t\t\taction: op.action,\n\t\t\t\tdeniedReason: op.deniedReason ?? null,\n\t\t\t\tsourceRemote: op.sourceRemote\n\t\t\t}));\n\t\t\tfor (const chunk of chunkRows(operationRows)) {\n\t\t\t\tconst insertedOps = await trx.insertInto(\"operation_index_operations\").values(chunk).returning(\"ordinal\").execute();\n\t\t\t\toperationOrdinals = operationOrdinals.concat(insertedOps.map((row) => row.ordinal));\n\t\t\t}\n\t\t}\n\t\tif (memberships.length > 0) for (const m of memberships) {\n\t\t\tconst ordinal = operationOrdinals[m.operationIndex];\n\t\t\tkyselyTxn.recordMembershipInvalidation(m.documentId);\n\t\t\tawait trx.insertInto(\"document_collections\").values({\n\t\t\t\tdocumentId: m.documentId,\n\t\t\t\tcollectionId: m.collectionId,\n\t\t\t\tjoinedOrdinal: BigInt(ordinal),\n\t\t\t\tleftOrdinal: null\n\t\t\t}).onConflict((oc) => oc.columns([\"documentId\", \"collectionId\"]).doUpdateSet({\n\t\t\t\tjoinedOrdinal: BigInt(ordinal),\n\t\t\t\tleftOrdinal: null\n\t\t\t})).execute();\n\t\t\tconst references = await trx.selectFrom(\"group_references\").select(\"groupId\").where(\"documentId\", \"=\", m.documentId).execute();\n\t\t\tfor (const { groupId } of references) await this.joinKeepingEarliest(trx, kyselyTxn, groupId, m.collectionId, BigInt(ordinal));\n\t\t}\n\t\tif (removals.length > 0) for (const r of removals) {\n\t\t\tconst ordinal = operationOrdinals[r.operationIndex];\n\t\t\tkyselyTxn.recordMembershipInvalidation(r.documentId);\n\t\t\tawait trx.updateTable(\"document_collections\").set({ leftOrdinal: BigInt(ordinal) }).where(\"collectionId\", \"=\", r.collectionId).where(\"documentId\", \"=\", r.documentId).where(\"leftOrdinal\", \"is\", null).execute();\n\t\t}\n\t\tif (groupReferences.length > 0) for (const record of groupReferences) {\n\t\t\tconst ordinal = operationOrdinals[record.operationIndex];\n\t\t\tawait trx.insertInto(\"group_references\").values(record.groupIds.map((groupId) => ({\n\t\t\t\tdocumentId: record.documentId,\n\t\t\t\tgroupId\n\t\t\t}))).onConflict((oc) => oc.doNothing()).execute();\n\t\t\tconst rows = await trx.selectFrom(\"document_collections\").select(\"collectionId\").where(\"documentId\", \"=\", record.documentId).execute();\n\t\t\tfor (const groupId of record.groupIds) for (const { collectionId } of rows) await this.joinKeepingEarliest(trx, kyselyTxn, groupId, collectionId, BigInt(ordinal));\n\t\t}\n\t\treturn operationOrdinals;\n\t}\n\tasync getCollectionsInRange(after, through, among, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (through <= after || among?.length === 0) return [];\n\t\tlet query = this.queryExecutor.selectFrom(\"operation_index_operations as oi\").innerJoin(\"document_collections as dc\", \"oi.documentId\", \"dc.documentId\").select(\"dc.collectionId\").distinct().where(\"oi.ordinal\", \">\", after).where(\"oi.ordinal\", \"<=\", through);\n\t\tif (among !== void 0) query = query.where(\"dc.collectionId\", \"in\", [...among]);\n\t\treturn (await query.execute()).map((row) => row.collectionId);\n\t}\n\tasync getOrdinalsInRange(after, through, limit, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (through <= after || limit <= 0) return [];\n\t\treturn (await this.queryExecutor.selectFrom(\"operation_index_operations\").select(\"ordinal\").where(\"ordinal\", \">\", after).where(\"ordinal\", \"<=\", through).orderBy(\"ordinal\", \"asc\").limit(limit).execute()).map((row) => Number(row.ordinal));\n\t}\n\tasync getByOrdinals(ordinals, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (ordinals.length === 0) return [];\n\t\tconst results = [];\n\t\tfor (let i = 0; i < ordinals.length; i += MAX_BIND_PARAMETERS) {\n\t\t\tconst chunk = ordinals.slice(i, i + MAX_BIND_PARAMETERS);\n\t\t\tconst rows = await this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"ordinal\", \"in\", chunk).orderBy(\"ordinal\", \"asc\").execute();\n\t\t\tfor (const row of rows) results.push(this.rowToOperationWithContext(row));\n\t\t}\n\t\tresults.sort((a, b) => a.context.ordinal - b.context.ordinal);\n\t\treturn results;\n\t}\n\tasync getStreamAfter(stream, after, signal, limit) {\n\t\tsignal?.throwIfAborted();\n\t\treturn (await this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"documentId\", \"=\", stream.documentId).where(\"branch\", \"=\", stream.branch).where(\"scope\", \"=\", stream.scope).where(\"ordinal\", \">\", after).orderBy(\"ordinal\", \"asc\").$if(limit !== void 0, (qb) => qb.limit(limit)).execute()).map((row) => this.rowToOperationWithContext(row));\n\t}\n\tasync getGroupReferencers(groupId, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\treturn (await this.queryExecutor.selectFrom(\"group_references\").select(\"documentId\").where(\"groupId\", \"=\", groupId).orderBy(\"documentId\").execute()).map((row) => row.documentId);\n\t}\n\tasync getOrdinalsByOpIds(documentId, scope, branch, opIds, signal) {\n\t\tsignal?.throwIfAborted();\n\t\tif (opIds.length === 0) return /* @__PURE__ */ new Map();\n\t\tconst rows = await this.queryExecutor.selectFrom(\"operation_index_operations\").select(\"opId\").select((eb) => eb.fn.max(\"ordinal\").as(\"ordinal\")).where(\"documentId\", \"=\", documentId).where(\"branch\", \"=\", branch).where(\"scope\", \"=\", scope).where(\"opId\", \"in\", opIds).groupBy(\"opId\").execute();\n\t\treturn new Map(rows.map((row) => [row.opId, Number(row.ordinal)]));\n\t}\n\tasync find(collectionId, cursor, view, paging, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst outerCursor = cursor ?? -1;\n\t\tconst limit = paging?.limit ?? 500;\n\t\tconst pagingCursorOrdinal = paging?.cursor !== void 0 ? Number.parseInt(paging.cursor, 10) : -1;\n\t\tconst buildBranch = (kind) => {\n\t\t\tlet qb = this.queryExecutor.selectFrom(\"operation_index_operations as oi\").innerJoin(\"document_collections as dc\", \"oi.documentId\", \"dc.documentId\").selectAll(\"oi\").select([\"dc.documentId\", \"dc.collectionId\"]).where(\"dc.collectionId\", \"=\", collectionId).where(sql`(dc.\"leftOrdinal\" IS NULL OR oi.ordinal < dc.\"leftOrdinal\")`);\n\t\t\tif (kind === \"joiner\") qb = qb.where(\"dc.joinedOrdinal\", \">\", BigInt(outerCursor)).where(\"oi.ordinal\", \"<=\", outerCursor);\n\t\t\telse qb = qb.where(\"oi.ordinal\", \">\", outerCursor);\n\t\t\tqb = qb.where(\"oi.ordinal\", \">\", pagingCursorOrdinal);\n\t\t\tif (view?.branch) qb = qb.where(\"oi.branch\", \"=\", view.branch);\n\t\t\tif (view?.scopes && view.scopes.length > 0) qb = qb.where(\"oi.scope\", \"in\", view.scopes);\n\t\t\tif (view?.excludeSourceRemote) qb = qb.where(\"oi.sourceRemote\", \"!=\", view.excludeSourceRemote);\n\t\t\tif (view?.throughOrdinal !== void 0) qb = qb.where(\"oi.ordinal\", \"<=\", view.throughOrdinal).where(\"dc.joinedOrdinal\", \"<=\", BigInt(view.throughOrdinal));\n\t\t\treturn qb;\n\t\t};\n\t\tconst rows = await buildBranch(\"joiner\").unionAll(buildBranch(\"newOps\")).orderBy(\"ordinal\", \"asc\").limit(limit + 1).execute();\n\t\tlet hasMore = false;\n\t\tlet items = rows;\n\t\tif (rows.length > limit) {\n\t\t\thasMore = true;\n\t\t\titems = rows.slice(0, limit);\n\t\t}\n\t\tconst nextCursor = hasMore && items.length > 0 ? items[items.length - 1].ordinal.toString() : void 0;\n\t\tconst cursorValue = paging?.cursor || \"0\";\n\t\treturn {\n\t\t\tresults: items.map((row) => this.rowToOperationIndexEntry(row)),\n\t\t\toptions: {\n\t\t\t\tcursor: cursorValue,\n\t\t\t\tlimit\n\t\t\t},\n\t\t\tnextCursor,\n\t\t\tnext: hasMore ? () => this.find(collectionId, cursor, view, {\n\t\t\t\tcursor: nextCursor,\n\t\t\t\tlimit\n\t\t\t}, signal) : void 0\n\t\t};\n\t}\n\tasync get(documentId, view, paging, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst limit = paging?.limit ?? 500;\n\t\tlet query = this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"documentId\", \"=\", documentId).orderBy(\"ordinal\", \"asc\");\n\t\tif (view?.branch) query = query.where(\"branch\", \"=\", view.branch);\n\t\tif (view?.scopes && view.scopes.length > 0) query = query.where(\"scope\", \"in\", view.scopes);\n\t\tif (paging?.cursor) {\n\t\t\tconst cursorOrdinal = Number.parseInt(paging.cursor, 10);\n\t\t\tquery = query.where(\"ordinal\", \">\", cursorOrdinal);\n\t\t}\n\t\tquery = query.limit(limit + 1);\n\t\tconst rows = await query.execute();\n\t\tlet hasMore = false;\n\t\tlet items = rows;\n\t\tif (rows.length > limit) {\n\t\t\thasMore = true;\n\t\t\titems = rows.slice(0, limit);\n\t\t}\n\t\tconst nextCursor = hasMore && items.length > 0 ? items[items.length - 1].ordinal.toString() : void 0;\n\t\tconst cursorValue = paging?.cursor || \"0\";\n\t\treturn {\n\t\t\tresults: items.map((row) => this.rowToOperationIndexEntry(row)),\n\t\t\toptions: {\n\t\t\t\tcursor: cursorValue,\n\t\t\t\tlimit\n\t\t\t},\n\t\t\tnextCursor,\n\t\t\tnext: hasMore ? () => this.get(documentId, view, {\n\t\t\t\tcursor: nextCursor,\n\t\t\t\tlimit\n\t\t\t}, signal) : void 0\n\t\t};\n\t}\n\tasync getSinceOrdinal(ordinal, paging, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst limit = paging?.limit ?? 500;\n\t\tlet query = this.queryExecutor.selectFrom(\"operation_index_operations\").selectAll().where(\"ordinal\", \">\", ordinal).orderBy(\"ordinal\", \"asc\");\n\t\tif (paging?.cursor) {\n\t\t\tconst cursorOrdinal = Number.parseInt(paging.cursor, 10);\n\t\t\tquery = query.where(\"ordinal\", \">\", cursorOrdinal);\n\t\t}\n\t\tquery = query.limit(limit + 1);\n\t\tconst rows = await query.execute();\n\t\tlet hasMore = false;\n\t\tlet items = rows;\n\t\tif (rows.length > limit) {\n\t\t\thasMore = true;\n\t\t\titems = rows.slice(0, limit);\n\t\t}\n\t\tconst nextCursor = hasMore && items.length > 0 ? items[items.length - 1].ordinal.toString() : void 0;\n\t\tconst cursorValue = paging?.cursor || \"0\";\n\t\treturn {\n\t\t\tresults: items.map((row) => this.rowToOperationWithContext(row)),\n\t\t\toptions: {\n\t\t\t\tcursor: cursorValue,\n\t\t\t\tlimit\n\t\t\t},\n\t\t\tnextCursor,\n\t\t\tnext: hasMore ? () => this.getSinceOrdinal(ordinal, {\n\t\t\t\tcursor: nextCursor,\n\t\t\t\tlimit\n\t\t\t}, signal) : void 0\n\t\t};\n\t}\n\t/** Backstop to the store's refusal: only a marker indexes a purged id. */\n\tasync refusePurgedOperations(trx, operations) {\n\t\tconst ids = new Set(operations.filter((operation) => !isPurgeMarker(operation)).map((operation) => operation.documentId).filter((id) => !this.liveIds?.has(id)));\n\t\tconst purged = await findPurged(trx, ids);\n\t\tfor (const id of ids) if (purged.has(id)) throw new DocumentPurgedError(id);\n\t}\n\t/** Takes the xid before the first ordinal, as the settled watermark needs. */\n\tasync assignXid(trx) {\n\t\tlet fn = xidFunctions.get(this.db);\n\t\tif (fn === void 0) {\n\t\t\tfn = readSnapshotFunctions(trx).then((fns) => fns.currentXid);\n\t\t\txidFunctions.set(this.db, fn);\n\t\t\tfn.catch(() => xidFunctions.delete(this.db));\n\t\t}\n\t\tconst name = await fn;\n\t\tawait sql`select ${sql.raw(name)}()`.execute(trx);\n\t}\n\trowToOperationWithContext(row) {\n\t\treturn {\n\t\t\toperation: {\n\t\t\t\tindex: row.index,\n\t\t\t\ttimestampUtcMs: row.timestampUtcMs,\n\t\t\t\thash: row.hash,\n\t\t\t\tskip: row.skip,\n\t\t\t\taction: row.action,\n\t\t\t\tdeniedReason: row.deniedReason ?? void 0,\n\t\t\t\tid: row.opId\n\t\t\t},\n\t\t\tcontext: {\n\t\t\t\tdocumentId: row.documentId,\n\t\t\t\tdocumentType: row.documentType,\n\t\t\t\tscope: row.scope,\n\t\t\t\tbranch: row.branch,\n\t\t\t\tordinal: row.ordinal\n\t\t\t}\n\t\t};\n\t}\n\trowToOperationIndexEntry(row) {\n\t\treturn {\n\t\t\tordinal: row.ordinal,\n\t\t\tdocumentId: row.documentId,\n\t\t\tdocumentType: row.documentType,\n\t\t\tbranch: row.branch,\n\t\t\tscope: row.scope,\n\t\t\tindex: row.index,\n\t\t\ttimestampUtcMs: row.timestampUtcMs,\n\t\t\thash: row.hash,\n\t\t\tskip: row.skip,\n\t\t\taction: row.action,\n\t\t\tdeniedReason: row.deniedReason ?? void 0,\n\t\t\tid: row.opId,\n\t\t\tsourceRemote: row.sourceRemote\n\t\t};\n\t}\n\tasync getLatestTimestampForCollection(collectionId, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\treturn (await this.queryExecutor.selectFrom(\"operation_index_operations as oi\").innerJoin(\"document_collections as dc\", \"oi.documentId\", \"dc.documentId\").select(\"oi.timestampUtcMs\").where(\"dc.collectionId\", \"=\", collectionId).where(sql`(dc.\"leftOrdinal\" IS NULL OR oi.ordinal < dc.\"leftOrdinal\")`).orderBy(\"oi.ordinal\", \"desc\").limit(1).executeTakeFirst())?.timestampUtcMs ?? null;\n\t}\n\tasync getCollectionsForDocuments(documentIds) {\n\t\tif (documentIds.length === 0) return {};\n\t\tconst rows = await this.queryExecutor.selectFrom(\"document_collections\").select([\"documentId\", \"collectionId\"]).where(\"documentId\", \"in\", documentIds).where(\"leftOrdinal\", \"is\", null).execute();\n\t\tconst result = {};\n\t\tfor (const row of rows) {\n\t\t\tif (!(row.documentId in result)) result[row.documentId] = [];\n\t\t\tresult[row.documentId].push(row.collectionId);\n\t\t}\n\t\treturn result;\n\t}\n};\n//#endregion\n//#region src/cache/buffer/ring-buffer.ts\n/**\n* RingBuffer is a generic circular buffer implementation that stores a fixed number\n* of items. When the buffer is full, new items overwrite the oldest items.\n*\n* This implementation maintains O(1) time complexity for push operations and provides\n* items in chronological order (oldest to newest) via getAll().\n*\n* @template T - The type of items stored in the buffer\n*/\nvar RingBuffer = class {\n\tbuffer;\n\thead = 0;\n\tsize = 0;\n\tcapacity;\n\tconstructor(capacity) {\n\t\tif (capacity <= 0) throw new Error(\"Ring buffer capacity must be greater than 0\");\n\t\tthis.capacity = capacity;\n\t\tthis.buffer = new Array(capacity);\n\t}\n\t/**\n\t* Adds an item to the buffer. If the buffer is full, overwrites the oldest item.\n\t*\n\t* @param item - The item to add\n\t*/\n\tpush(item) {\n\t\tconst index = (this.head + this.size) % this.capacity;\n\t\tif (this.size < this.capacity) {\n\t\t\tthis.buffer[index] = item;\n\t\t\tthis.size++;\n\t\t} else {\n\t\t\tthis.buffer[this.head] = item;\n\t\t\tthis.head = (this.head + 1) % this.capacity;\n\t\t}\n\t}\n\t/**\n\t* Returns all items in the buffer in chronological order (oldest to newest).\n\t*\n\t* @returns Array of items in insertion order\n\t*/\n\tgetAll() {\n\t\tif (this.size === 0) return [];\n\t\tconst result = [];\n\t\tfor (let i = 0; i < this.size; i++) {\n\t\t\tconst index = (this.head + i) % this.capacity;\n\t\t\tresult.push(this.buffer[index]);\n\t\t}\n\t\treturn result;\n\t}\n\t/**\n\t* Clears all items from the buffer.\n\t*/\n\tclear() {\n\t\tthis.buffer = new Array(this.capacity);\n\t\tthis.head = 0;\n\t\tthis.size = 0;\n\t}\n\t/**\n\t* Gets the current number of items in the buffer.\n\t*/\n\tget length() {\n\t\treturn this.size;\n\t}\n};\n//#endregion\n//#region src/cache/kysely-write-cache.ts\n/**\n* The last operation index a keyframe's document reflects for the scope. A\n* keyframe only exists for a scope that has operations, so a missing entry\n* means the stored row is corrupt.\n*/\nfunction keyframeRevision(keyframe, documentId, scope) {\n\tconst nextIndex = keyframe.document.header.revision[scope];\n\tif (typeof nextIndex !== \"number\") throw new Error(`Corrupt keyframe for document ${documentId} at revision ${keyframe.revision}: header carries no ${scope} revision`);\n\treturn nextIndex - 1;\n}\nfunction extractModuleVersion(doc) {\n\tconst v = doc.state.document.version;\n\treturn normalizeDocumentModelVersion(v);\n}\n/** The highest revision held, latest push winning a tie. */\nfunction highestRevision(snapshots) {\n\tlet newest = void 0;\n\tfor (const snapshot of snapshots) if (!newest || snapshot.revision >= newest.revision) newest = snapshot;\n\treturn newest;\n}\n/**\n* Copies a document far enough that the caller cannot write through it. Inside\n* this class, callers only ever replace whole fields on these four, so one\n* level each is enough.\n*/\nfunction copyDocument(document) {\n\treturn {\n\t\t...document,\n\t\theader: { ...document.header },\n\t\tstate: { ...document.state },\n\t\toperations: { ...document.operations }\n\t};\n}\nvar KyselyWriteCache = class KyselyWriteCache {\n\tstreams;\n\tlruTracker;\n\tkeyframeStore;\n\toperationStore;\n\tregistry;\n\tconfig;\n\treads = /* @__PURE__ */ new Map();\n\tconstructor(keyframeStore, operationStore, registry, config) {\n\t\tthis.keyframeStore = keyframeStore;\n\t\tthis.operationStore = operationStore;\n\t\tthis.registry = registry;\n\t\tthis.config = {\n\t\t\tmaxDocuments: config.maxDocuments,\n\t\t\tringBufferSize: config.ringBufferSize,\n\t\t\tkeyframeInterval: config.keyframeInterval\n\t\t};\n\t\tthis.streams = /* @__PURE__ */ new Map();\n\t\tthis.lruTracker = new LRUTracker();\n\t}\n\twithScopedStores(operationStore, keyframeStore) {\n\t\tconst scoped = new KyselyWriteCache(keyframeStore, operationStore, this.registry, this.config);\n\t\tscoped.streams = this.streams;\n\t\tscoped.lruTracker = this.lruTracker;\n\t\tscoped.reads = this.reads;\n\t\treturn scoped;\n\t}\n\t/**\n\t* Initializes the write cache.\n\t* Currently a no-op as keyframe store lifecycle is managed externally.\n\t*/\n\tasync startup() {\n\t\treturn Promise.resolve();\n\t}\n\t/**\n\t* Shuts down the write cache.\n\t* Currently a no-op as keyframe store lifecycle is managed externally.\n\t*/\n\tasync shutdown() {\n\t\treturn Promise.resolve();\n\t}\n\t/**\n\t* Retrieves document state at a specific revision from cache or rebuilds it.\n\t*\n\t* Note: this returns a _shallow_ copy of the document.\n\t*\n\t* Cache hit path: Returns cached snapshot if available (O(1))\n\t* Warm miss path: Rebuilds from cached base revision + incremental ops\n\t* Cold miss path: Rebuilds from keyframe or from scratch using all operations\n\t*\n\t* @param documentId - The document identifier\n\t* @param scope - The operation scope\n\t* @param branch - The operation branch\n\t* @param targetRevision - The target revision, or undefined for newest\n\t* @param signal - Optional abort signal to cancel the operation\n\t* @returns The document at the target revision\n\t* @throws {Error} \"Operation aborted\" if signal is aborted\n\t* @throws {ModuleNotFoundError} If document type not registered in registry\n\t* @throws {DocumentPurgedError} If the stream's only row is a purge marker\n\t* @throws {Error} \"Failed to rebuild document\" if operation store fails\n\t* @throws {Error} If reducer throws during operation application\n\t* @throws {Error} If document serialization fails\n\t*/\n\tasync getState(documentId, scope, branch, targetRevision, signal) {\n\t\tconst read = { evicted: false };\n\t\tlet pending = this.reads.get(documentId);\n\t\tif (!pending) {\n\t\t\tpending = /* @__PURE__ */ new Set();\n\t\t\tthis.reads.set(documentId, pending);\n\t\t}\n\t\tpending.add(read);\n\t\ttry {\n\t\t\treturn await this.readState(documentId, scope, branch, targetRevision, signal, read);\n\t\t} finally {\n\t\t\tpending.delete(read);\n\t\t\tif (pending.size === 0) this.reads.delete(documentId);\n\t\t}\n\t}\n\tasync readState(documentId, scope, branch, targetRevision, signal, read) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst streamKey = this.makeStreamKey(documentId, scope, branch);\n\t\tconst stream = this.streams.get(streamKey);\n\t\tif (stream) {\n\t\t\tconst snapshots = stream.ringBuffer.getAll();\n\t\t\tif (targetRevision === void 0) {\n\t\t\t\tconst newest = highestRevision(snapshots);\n\t\t\t\tif (newest?.position === \"head\") {\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn copyDocument(newest.document);\n\t\t\t\t}\n\t\t\t\tif (newest) {\n\t\t\t\t\tconst document = await this.warmMissRebuild(newest.document, newest.revision, documentId, scope, branch, void 0, signal);\n\t\t\t\t\tthis.storeUnlessEvicted(read, documentId, scope, branch, (document.header.revision[scope] ?? 0) - 1, document, \"head\");\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn document;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst exactMatch = snapshots.findLast((s) => s.revision === targetRevision);\n\t\t\t\tif (exactMatch) {\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn copyDocument(exactMatch.document);\n\t\t\t\t}\n\t\t\t\tconst newestOlder = this.findNearestOlderSnapshot(snapshots, targetRevision);\n\t\t\t\tif (newestOlder) {\n\t\t\t\t\tconst document = await this.warmMissRebuild(newestOlder.document, newestOlder.revision, documentId, scope, branch, targetRevision, signal);\n\t\t\t\t\tthis.storeUnlessEvicted(read, documentId, scope, branch, targetRevision, document, \"historical\");\n\t\t\t\t\tthis.lruTracker.touch(streamKey);\n\t\t\t\t\treturn document;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst document = await this.coldMissRebuild(documentId, scope, branch, targetRevision, signal);\n\t\tconst revision = targetRevision ?? (document.header.revision[scope] ?? 0) - 1;\n\t\tthis.storeUnlessEvicted(read, documentId, scope, branch, revision, document, targetRevision === void 0 ? \"head\" : \"historical\");\n\t\treturn document;\n\t}\n\t/**\n\t* Stores a document snapshot in the cache at a specific revision.\n\t*\n\t* The cached document is a shallow copy of the input with its operation history\n\t* truncated to the last operation per scope and its clipboard cleared. This keeps\n\t* memory use and copy costs constant regardless of operation count. Consumers of\n\t* getState() must not rely on the full operation history being present; the only\n\t* guaranteed invariant is that operations[scope].at(-1) reflects the latest\n\t* operation index for each scope.\n\t*\n\t* Updates LRU tracker and may evict least recently used stream if at capacity.\n\t* Asynchronously persists keyframes at configured intervals (fire-and-forget).\n\t*\n\t* @param documentId - The document identifier\n\t* @param scope - The operation scope\n\t* @param branch - The operation branch\n\t* @param revision - The revision number\n\t* @param document - The document to cache\n\t* @throws {Error} If document serialization fails\n\t*/\n\tputState(documentId, scope, branch, revision, document, position) {\n\t\tthis.store(documentId, scope, branch, revision, document, position);\n\t}\n\t/**\n\t* Stores the run's head and mints a keyframe for every interval the run\n\t* crossed on its way there. Only the head enters the ring buffer; the\n\t* earlier revisions are keyframe candidates and nothing more.\n\t*/\n\tputRun(documentId, scope, branch, run) {\n\t\tif (run.length === 0) return;\n\t\tfor (const entry of run.slice(0, -1)) this.persistKeyframe(documentId, scope, branch, entry.revision, entry.document);\n\t\tconst head = run[run.length - 1];\n\t\tthis.store(documentId, scope, branch, head.revision, head.document, \"head\");\n\t}\n\tstoreUnlessEvicted(read, documentId, scope, branch, revision, document, position) {\n\t\tif (!read.evicted) this.store(documentId, scope, branch, revision, document, position);\n\t}\n\tstore(documentId, scope, branch, revision, document, position) {\n\t\tconst streamKey = this.makeStreamKey(documentId, scope, branch);\n\t\tconst stream = this.getOrCreateStream(streamKey);\n\t\tconst snapshot = {\n\t\t\trevision,\n\t\t\tdocument: {\n\t\t\t\t...copyDocument(document),\n\t\t\t\toperations: Object.fromEntries(Object.entries(document.operations).map(([k, ops]) => [k, ops.length ? [ops.at(-1)] : []])),\n\t\t\t\tclipboard: []\n\t\t\t},\n\t\t\tposition\n\t\t};\n\t\tstream.ringBuffer.push(snapshot);\n\t\tthis.persistKeyframe(documentId, scope, branch, revision, document);\n\t}\n\t/** Persists the snapshot if this revision is one the interval falls on. */\n\tpersistKeyframe(documentId, scope, branch, revision, document) {\n\t\tif (!this.isKeyframeRevision(revision)) return;\n\t\tthis.keyframeStore.putKeyframe(documentId, scope, branch, revision, {\n\t\t\t...document,\n\t\t\toperations: {},\n\t\t\tclipboard: []\n\t\t}).catch((err) => {\n\t\t\tconsole.error(`Failed to persist keyframe ${documentId}@${revision}:`, err);\n\t\t});\n\t}\n\t/**\n\t* Invalidates cached document streams.\n\t*\n\t* Supports three invalidation scopes:\n\t* - Document-level: invalidate(documentId) - removes all streams for document\n\t* - Scope-level: invalidate(documentId, scope) - removes all branches for scope\n\t* - Stream-level: invalidate(documentId, scope, branch) - removes specific stream\n\t*\n\t* @param documentId - The document identifier\n\t* @param scope - Optional scope to narrow invalidation\n\t* @param branch - Optional branch to narrow invalidation (requires scope)\n\t* @returns The number of streams evicted\n\t*/\n\tinvalidate(documentId, scope, branch) {\n\t\tfor (const read of this.reads.get(documentId) ?? []) read.evicted = true;\n\t\tlet evicted = 0;\n\t\tif (scope === void 0 && branch === void 0) {\n\t\t\tfor (const [key] of this.streams.entries()) if (key.startsWith(`${documentId}:`)) {\n\t\t\t\tthis.streams.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t} else if (scope !== void 0 && branch === void 0) {\n\t\t\tfor (const [key] of this.streams.entries()) if (key.startsWith(`${documentId}:${scope}:`)) {\n\t\t\t\tthis.streams.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t} else if (scope !== void 0 && branch !== void 0) {\n\t\t\tconst key = this.makeStreamKey(documentId, scope, branch);\n\t\t\tif (this.streams.has(key)) {\n\t\t\t\tthis.streams.delete(key);\n\t\t\t\tthis.lruTracker.remove(key);\n\t\t\t\tevicted = 1;\n\t\t\t}\n\t\t}\n\t\treturn evicted;\n\t}\n\t/**\n\t* Clears the entire cache, removing all cached document streams.\n\t* Resets LRU tracking state. This operation always succeeds.\n\t*/\n\tclear() {\n\t\tfor (const pending of this.reads.values()) for (const read of pending) read.evicted = true;\n\t\tthis.streams.clear();\n\t\tthis.lruTracker.clear();\n\t}\n\t/**\n\t* Retrieves a specific stream for a document. Exposed on the implementation\n\t* for testing, but not on the interface.\n\t*\n\t* @internal\n\t*/\n\tgetStream(documentId, scope, branch) {\n\t\tconst key = this.makeStreamKey(documentId, scope, branch);\n\t\treturn this.streams.get(key);\n\t}\n\tasync findNearestKeyframe(documentId, scope, branch, targetRevision, signal) {\n\t\tif (targetRevision === Number.MAX_SAFE_INTEGER || targetRevision <= 0) return;\n\t\tconst keyframe = await this.keyframeStore.findNearestKeyframe(documentId, scope, branch, targetRevision, signal);\n\t\tif (!keyframe) return;\n\t\treturn {\n\t\t\trevision: Math.min(keyframeRevision(keyframe, documentId, scope), keyframe.revision),\n\t\t\tdocument: keyframe.document\n\t\t};\n\t}\n\t/**\n\t* Rebuilds a scope from a keyframe or from the whole operation history.\n\t*\n\t* The document scope is always rebuilt first, because it carries the type,\n\t* the upgrades and the deletion marker. Its version-changing upgrades are not\n\t* applied there though: an upgrade reducer must see the state the requested\n\t* scope has reached at that upgrade's boundary, so each one is held back and\n\t* applied when the replay below crosses the boundary that\n\t* resolveModuleVersionForOp derives from it. Upgrades whose boundary lies past\n\t* the last replayed operation are applied at the end. Creation-time 0->N seed\n\t* upgrades carry the initial state, so they still apply immediately.\n\t*/\n\tasync coldMissRebuild(documentId, scope, branch, targetRevision, signal, fromKeyframe = true) {\n\t\tconst effectiveTargetRevision = targetRevision || Number.MAX_SAFE_INTEGER;\n\t\tconst keyframe = fromKeyframe ? await this.findNearestKeyframe(documentId, scope, branch, effectiveTargetRevision, signal) : void 0;\n\t\tconst documentScopeBound = scope === \"document\" ? targetRevision : void 0;\n\t\tlet document;\n\t\tlet startRevision;\n\t\tlet documentType;\n\t\tconst validatedUpgrades = [];\n\t\tconst pendingUpgrades = [];\n\t\tlet lastDocumentScopeOperation;\n\t\tif (keyframe) {\n\t\t\tdocument = keyframe.document;\n\t\t\tstartRevision = keyframe.revision;\n\t\t\tdocumentType = keyframe.document.header.documentType;\n\t\t\tconst documentScopeResume = scope === \"document\" ? keyframe.revision : keyframeRevision(keyframe, documentId, \"document\");\n\t\t\tconst docScopeOpsAfterKeyframe = await this.operationStore.getSince(documentId, \"document\", branch, documentScopeResume, void 0, void 0, signal);\n\t\t\tfor (const operation of docScopeOpsAfterKeyframe.results) {\n\t\t\t\tif (documentScopeBound !== void 0 && operation.index > documentScopeBound) break;\n\t\t\t\tlastDocumentScopeOperation = operation;\n\t\t\t\tif (operation.error || isDenied(operation)) continue;\n\t\t\t\tif (operation.action.type === \"UPGRADE_DOCUMENT\") {\n\t\t\t\t\tconst upgradeAction = operation.action;\n\t\t\t\t\tconst fromVersion = upgradeAction.input.fromVersion;\n\t\t\t\t\tconst toVersion = upgradeAction.input.toVersion;\n\t\t\t\t\tif (fromVersion > 0 && fromVersion < toVersion) {\n\t\t\t\t\t\tlet upgradePath;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tupgradePath = this.registry.computeUpgradePath(documentType, fromVersion, toVersion);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tif (upgradeAction.input.initialState !== void 0) upgradePath = void 0;\n\t\t\t\t\t\t\telse throw new Error(`Failed to rebuild document ${documentId}: no upgrade manifest for ${documentType} v${fromVersion}→v${toVersion} and no initialState snapshot. ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvalidatedUpgrades.push({\n\t\t\t\t\t\t\tfromVersion,\n\t\t\t\t\t\t\ttoVersion,\n\t\t\t\t\t\t\trevision: upgradeAction.input.revision,\n\t\t\t\t\t\t\ttimestampUtcMs: operation.timestampUtcMs\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpendingUpgrades.push({\n\t\t\t\t\t\t\taction: upgradeAction,\n\t\t\t\t\t\t\tupgradePath,\n\t\t\t\t\t\t\tindex: operation.index,\n\t\t\t\t\t\t\tsubsequentDeletes: []\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (operation.action.type === \"DELETE_DOCUMENT\" || operation.action.type === PURGE_DOCUMENT) {\n\t\t\t\t\tapplyDeleteDocumentAction(document, operation.action);\n\t\t\t\t\tfor (const pending of pendingUpgrades) pending.subsequentDeletes.push(operation.action);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tstartRevision = -1;\n\t\t\tconst createOpResult = await this.operationStore.getSince(documentId, \"document\", branch, -1, void 0, {\n\t\t\t\tcursor: \"0\",\n\t\t\t\tlimit: 1\n\t\t\t}, signal);\n\t\t\tif (createOpResult.results.length === 0) throw new DocumentNotFoundError(documentId);\n\t\t\tconst createOp = createOpResult.results[0];\n\t\t\tif (isPurgeMarker(createOp)) throw new DocumentPurgedError(documentId);\n\t\t\tif (createOp.action.type !== \"CREATE_DOCUMENT\") throw new Error(`Failed to rebuild document ${documentId}: first operation in document scope must be CREATE_DOCUMENT, found ${createOp.action.type}`);\n\t\t\tconst documentCreateAction = createOp.action;\n\t\t\tdocumentType = documentCreateAction.input.model;\n\t\t\tif (!documentType) throw new Error(`Failed to rebuild document ${documentId}: CREATE_DOCUMENT action missing model in input`);\n\t\t\tdocument = createDocumentFromAction(documentCreateAction);\n\t\t\tlastDocumentScopeOperation = createOp;\n\t\t\tlet docModule = this.registry.getModule(documentType, extractModuleVersion(document));\n\t\t\tconst docScopeOps = await this.operationStore.getSince(documentId, \"document\", branch, 0, void 0, void 0, signal);\n\t\t\tfor (const operation of docScopeOps.results) {\n\t\t\t\tif (documentScopeBound !== void 0 && operation.index > documentScopeBound) break;\n\t\t\t\tlastDocumentScopeOperation = operation;\n\t\t\t\tif (operation.index === 0) continue;\n\t\t\t\tif (operation.error || isDenied(operation)) continue;\n\t\t\t\tif (operation.action.type === \"UPGRADE_DOCUMENT\") {\n\t\t\t\t\tconst upgradeAction = operation.action;\n\t\t\t\t\tconst fromVersion = upgradeAction.input.fromVersion;\n\t\t\t\t\tconst toVersion = upgradeAction.input.toVersion;\n\t\t\t\t\tif (fromVersion > 0 && fromVersion < toVersion) {\n\t\t\t\t\t\tlet upgradePath;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tupgradePath = this.registry.computeUpgradePath(documentType, fromVersion, toVersion);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tif (upgradeAction.input.initialState !== void 0) upgradePath = void 0;\n\t\t\t\t\t\t\telse throw new Error(`Failed to rebuild document ${documentId}: no upgrade manifest for ${documentType} v${fromVersion}→v${toVersion} and no initialState snapshot. ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvalidatedUpgrades.push({\n\t\t\t\t\t\t\tfromVersion,\n\t\t\t\t\t\t\ttoVersion,\n\t\t\t\t\t\t\trevision: upgradeAction.input.revision,\n\t\t\t\t\t\t\ttimestampUtcMs: operation.timestampUtcMs\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpendingUpgrades.push({\n\t\t\t\t\t\t\taction: upgradeAction,\n\t\t\t\t\t\t\tupgradePath,\n\t\t\t\t\t\t\tindex: operation.index,\n\t\t\t\t\t\t\tsubsequentDeletes: []\n\t\t\t\t\t\t});\n\t\t\t\t\t} else document = applyUpgradeDocumentAction(document, upgradeAction, void 0);\n\t\t\t\t\tdocModule = this.registry.getModule(documentType, normalizeDocumentModelVersion(toVersion));\n\t\t\t\t} else if (operation.action.type === \"DELETE_DOCUMENT\" || operation.action.type === PURGE_DOCUMENT) {\n\t\t\t\t\tapplyDeleteDocumentAction(document, operation.action);\n\t\t\t\t\tfor (const pending of pendingUpgrades) pending.subsequentDeletes.push(operation.action);\n\t\t\t\t} else {\n\t\t\t\t\tconst protocolVersion = baseReducerVersion(document.header);\n\t\t\t\t\tdocument = withProtocolVersions(docModule.reducer(document, operation.action, void 0, {\n\t\t\t\t\t\tskip: operation.skip,\n\t\t\t\t\t\tprotocolVersion\n\t\t\t\t\t}), document.header.protocolVersions);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (scope === \"document\") {\n\t\t\tdocument = this.applyPendingUpgrades(document, pendingUpgrades, Number.MAX_SAFE_INTEGER);\n\t\t\tconst last = lastDocumentScopeOperation ?? await this.operationAt(documentId, \"document\", branch, startRevision, signal);\n\t\t\tdocument.operations = {\n\t\t\t\t...document.operations,\n\t\t\t\tdocument: last ? [last] : []\n\t\t\t};\n\t\t\treturn this.stampRevisions(document, documentId, scope, branch, targetRevision, signal);\n\t\t}\n\t\tif (keyframe) {\n\t\t\tconst resumeOperation = await this.operationAt(documentId, scope, branch, startRevision, signal);\n\t\t\tif (resumeOperation) document.operations = {\n\t\t\t\t...document.operations,\n\t\t\t\t[scope]: [resumeOperation]\n\t\t\t};\n\t\t}\n\t\tconst moduleCache = /* @__PURE__ */ new Map();\n\t\tconst getModuleCached = (version) => {\n\t\t\tconst key = version ?? 0;\n\t\t\tlet mod = moduleCache.get(key);\n\t\t\tif (!mod) {\n\t\t\t\tmod = this.registry.getModule(documentType, version);\n\t\t\t\tmoduleCache.set(key, mod);\n\t\t\t}\n\t\t\treturn mod;\n\t\t};\n\t\tconst finalVersion = validatedUpgrades.at(-1)?.toVersion ?? extractModuleVersion(document);\n\t\tlet cursor = void 0;\n\t\tconst pageSize = 100;\n\t\tlet hasMorePages;\n\t\tlet needsFullReplay = false;\n\t\tdo {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tconst paging = {\n\t\t\t\tcursor: cursor || \"0\",\n\t\t\t\tlimit: pageSize\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tconst result = await this.operationStore.getSince(documentId, scope, branch, startRevision, void 0, paging, signal);\n\t\t\t\tfor (const operation of result.results) {\n\t\t\t\t\tif (targetRevision !== void 0 && operation.index > targetRevision) break;\n\t\t\t\t\tif (keyframe && operation.skip > 0) {\n\t\t\t\t\t\tneedsFullReplay = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst moduleVersion = this.resolveModuleVersionForOp(operation.index, operation.timestampUtcMs, scope, validatedUpgrades, finalVersion);\n\t\t\t\t\tdocument = this.applyPendingUpgrades(document, pendingUpgrades, moduleVersion ?? Number.MAX_SAFE_INTEGER);\n\t\t\t\t\tif (isDenied(operation)) document = appendWithoutApplying(document, operation, scope);\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst protocolVersion = baseReducerVersion(document.header);\n\t\t\t\t\t\tdocument = withProtocolVersions(getModuleCached(moduleVersion).reducer(document, operation.action, void 0, {\n\t\t\t\t\t\t\tskip: operation.skip,\n\t\t\t\t\t\t\tprotocolVersion,\n\t\t\t\t\t\t\treplayOptions: { operation },\n\t\t\t\t\t\t\tskipIndexValidation: true\n\t\t\t\t\t\t}), document.header.protocolVersions);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst reachedTarget = targetRevision !== void 0 && result.results.some((op) => op.index >= targetRevision);\n\t\t\t\thasMorePages = Boolean(result.nextCursor) && !reachedTarget && !needsFullReplay;\n\t\t\t\tif (hasMorePages) cursor = result.nextCursor;\n\t\t\t} catch (err) {\n\t\t\t\tthrow new Error(`Failed to rebuild document ${documentId}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t\t}\n\t\t} while (hasMorePages);\n\t\tif (needsFullReplay) return this.coldMissRebuild(documentId, scope, branch, targetRevision, signal, false);\n\t\tdocument = this.applyTailPendingUpgrades(document, pendingUpgrades, scope, targetRevision);\n\t\tdocument = await this.stampRevisions(document, documentId, scope, branch, targetRevision, signal);\n\t\tif (pendingUpgrades.length > 0) {\n\t\t\tconst firstHeldBack = pendingUpgrades[0];\n\t\t\tconst stamped = document.header.revision[\"document\"] ?? 0;\n\t\t\tdocument.header.revision = {\n\t\t\t\t...document.header.revision,\n\t\t\t\tdocument: Math.min(stamped, firstHeldBack.index)\n\t\t\t};\n\t\t}\n\t\treturn document;\n\t}\n\t/**\n\t* Applies and removes every held-back upgrade whose target version is at or\n\t* below `throughVersion`, in the order the document scope recorded them.\n\t*/\n\tapplyPendingUpgrades(document, pendingUpgrades, throughVersion) {\n\t\twhile (pendingUpgrades.length > 0) {\n\t\t\tconst pending = pendingUpgrades[0];\n\t\t\tif (throughVersion < pending.action.input.toVersion) break;\n\t\t\tpendingUpgrades.shift();\n\t\t\tdocument = this.applyPendingUpgrade(document, pending);\n\t\t}\n\t\treturn document;\n\t}\n\t/**\n\t* Applies the remaining held-back upgrades after the requested scope's\n\t* replay has finished. A head read applies them all. A positional read\n\t* applies only those whose boundary for this scope lies at or before the\n\t* target position: applying a later one would label migrated state with a\n\t* pre-upgrade revision, and a keyframe stored from that poisons every\n\t* rebuild that resumes from it. Boundaries come from the upgrade's revision\n\t* snapshot; an upgrade without one records no position for this scope, and\n\t* the replay loop not having crossed it already places it past the target.\n\t*/\n\tapplyTailPendingUpgrades(document, pendingUpgrades, scope, targetRevision) {\n\t\twhile (pendingUpgrades.length > 0) {\n\t\t\tconst pending = pendingUpgrades[0];\n\t\t\tif (targetRevision !== void 0) {\n\t\t\t\tconst snapshot = pending.action.input.revision;\n\t\t\t\tif (snapshot === void 0) break;\n\t\t\t\tif ((snapshot[scope] ?? 0) > targetRevision) break;\n\t\t\t}\n\t\t\tpendingUpgrades.shift();\n\t\t\tdocument = this.applyPendingUpgrade(document, pending);\n\t\t}\n\t\treturn document;\n\t}\n\t/**\n\t* Applies one held-back upgrade, then re-applies the deletes the document\n\t* scope recorded after it so the hold-back cannot invert their order.\n\t*/\n\tapplyPendingUpgrade(document, pending) {\n\t\tdocument = applyUpgradeDocumentAction(document, pending.action, pending.upgradePath);\n\t\tfor (const deleteAction of pending.subsequentDeletes) document = applyDeleteDocumentAction(document, deleteAction);\n\t\treturn document;\n\t}\n\t/**\n\t* Copies the current document revisions onto the document. Overwrites the\n\t* requested scope revision with the target revision, if provided.\n\t*/\n\tasync stampRevisions(document, documentId, scope, branch, targetRevision, signal) {\n\t\tconst revisions = await this.operationStore.getRevisions(documentId, branch, signal);\n\t\tdocument.header.revision = revisions.revision;\n\t\tif (targetRevision !== void 0) document.header.revision = {\n\t\t\t...document.header.revision,\n\t\t\t[scope]: targetRevision + 1\n\t\t};\n\t\tdocument.header.lastModifiedAtUtcIso = revisions.latestTimestamp;\n\t\treturn document;\n\t}\n\t/** The stored operation at `index`, or undefined if it is no longer there. */\n\tasync operationAt(documentId, scope, branch, index, signal) {\n\t\tif (index < 0) return;\n\t\tconst operation = (await this.operationStore.getSince(documentId, scope, branch, index - 1, void 0, {\n\t\t\tcursor: \"0\",\n\t\t\tlimit: 1\n\t\t}, signal)).results[0];\n\t\treturn operation && operation.index === index ? operation : void 0;\n\t}\n\t/**\n\t* Resolves which module version to use for a given operation in phase 2.\n\t*\n\t* Uses the validated-upgrade boundary rules from D7:\n\t* - If `input.revision` is present: op.index < revision[scope] → before the upgrade boundary\n\t* - Otherwise: timestamp fallback\n\t* - Falls back to final module version when neither is decidable\n\t*/\n\tresolveModuleVersionForOp(opIndex, opTimestamp, scope, validatedUpgrades, finalVersion) {\n\t\tif (validatedUpgrades.length === 0) return finalVersion;\n\t\tlet currentVersion = validatedUpgrades[0]?.fromVersion;\n\t\tfor (const upgrade of validatedUpgrades) {\n\t\t\tlet beforeUpgrade;\n\t\t\tif (upgrade.revision !== void 0) beforeUpgrade = opIndex < (upgrade.revision[scope] ?? 0);\n\t\t\telse beforeUpgrade = opTimestamp < upgrade.timestampUtcMs;\n\t\t\tif (beforeUpgrade) return currentVersion;\n\t\t\tcurrentVersion = upgrade.toVersion;\n\t\t}\n\t\treturn currentVersion;\n\t}\n\tasync warmMissRebuild(baseDocument, baseRevision, documentId, scope, branch, targetRevision, signal) {\n\t\tconst documentType = baseDocument.header.documentType;\n\t\tconst docScopeNextIndex = baseDocument.header.revision[\"document\"] ?? 0;\n\t\tif ((await this.operationStore.getSince(documentId, \"document\", branch, docScopeNextIndex - 1, void 0, void 0, signal)).results.length > 0) return this.coldMissRebuild(documentId, scope, branch, targetRevision, signal);\n\t\tconst module = this.registry.getModule(documentType, extractModuleVersion(baseDocument));\n\t\tlet document = copyDocument(baseDocument);\n\t\tlet needsFullReplay = false;\n\t\ttry {\n\t\t\tconst pagedResults = await this.operationStore.getSince(documentId, scope, branch, baseRevision, void 0, void 0, signal);\n\t\t\tfor (const operation of pagedResults.results) {\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tif (targetRevision !== void 0 && operation.index > targetRevision) break;\n\t\t\t\tif (operation.skip > 0) {\n\t\t\t\t\tneedsFullReplay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (isDenied(operation)) document = appendWithoutApplying(document, operation, scope);\n\t\t\t\telse {\n\t\t\t\t\tconst protocolVersion = baseReducerVersion(document.header);\n\t\t\t\t\tdocument = withProtocolVersions(module.reducer(document, operation.action, void 0, {\n\t\t\t\t\t\tskip: operation.skip,\n\t\t\t\t\t\tprotocolVersion,\n\t\t\t\t\t\treplayOptions: { operation },\n\t\t\t\t\t\tskipIndexValidation: true\n\t\t\t\t\t}), document.header.protocolVersions);\n\t\t\t\t}\n\t\t\t\tif (targetRevision !== void 0 && operation.index === targetRevision) break;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Failed to rebuild document ${documentId}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n\t\t}\n\t\tif (needsFullReplay) return this.coldMissRebuild(documentId, scope, branch, targetRevision, signal, false);\n\t\tconst revisions = await this.operationStore.getRevisions(documentId, branch, signal);\n\t\tdocument.header.revision = revisions.revision;\n\t\tif (targetRevision !== void 0) document.header.revision = {\n\t\t\t...document.header.revision,\n\t\t\t[scope]: targetRevision + 1\n\t\t};\n\t\tdocument.header.lastModifiedAtUtcIso = revisions.latestTimestamp;\n\t\treturn document;\n\t}\n\tfindNearestOlderSnapshot(snapshots, targetRevision) {\n\t\tlet nearest = void 0;\n\t\tfor (const snapshot of snapshots) if (snapshot.revision < targetRevision) {\n\t\t\tif (!nearest || snapshot.revision > nearest.revision) nearest = snapshot;\n\t\t}\n\t\treturn nearest;\n\t}\n\tmakeStreamKey(documentId, scope, branch) {\n\t\treturn `${documentId}:${scope}:${branch}`;\n\t}\n\tgetOrCreateStream(key) {\n\t\tlet stream = this.streams.get(key);\n\t\tif (!stream) {\n\t\t\tif (this.streams.size >= this.config.maxDocuments) {\n\t\t\t\tconst evictKey = this.lruTracker.evict();\n\t\t\t\tif (evictKey) this.streams.delete(evictKey);\n\t\t\t}\n\t\t\tstream = {\n\t\t\t\tkey,\n\t\t\t\tringBuffer: new RingBuffer(this.config.ringBufferSize)\n\t\t\t};\n\t\t\tthis.streams.set(key, stream);\n\t\t}\n\t\tthis.lruTracker.touch(key);\n\t\treturn stream;\n\t}\n\tisKeyframeRevision(revision) {\n\t\treturn revision > 0 && revision % this.config.keyframeInterval === 0;\n\t}\n};\n//#endregion\n//#region src/events/event-bus.ts\nvar EventBus = class {\n\teventTypeToSubscribers = /* @__PURE__ */ new Map();\n\tsubscribe(type, subscriber) {\n\t\tlet list = this.eventTypeToSubscribers.get(type);\n\t\tif (!list) {\n\t\t\tlist = [];\n\t\t\tthis.eventTypeToSubscribers.set(type, list);\n\t\t}\n\t\tlist.push(subscriber);\n\t\tlet done = false;\n\t\treturn () => {\n\t\t\tif (done) return;\n\t\t\tdone = true;\n\t\t\tconst arr = this.eventTypeToSubscribers.get(type);\n\t\t\tif (!arr) return;\n\t\t\tconst idx = arr.indexOf(subscriber);\n\t\t\tif (idx !== -1) arr.splice(idx, 1);\n\t\t\tif (arr.length === 0) this.eventTypeToSubscribers.delete(type);\n\t\t};\n\t}\n\tasync emit(type, data) {\n\t\tconst list = this.eventTypeToSubscribers.get(type);\n\t\tif (!list || list.length === 0) return;\n\t\tconst snapshot = list.slice();\n\t\tconst errors = [];\n\t\tfor (const fn of snapshot) try {\n\t\t\tawait Promise.resolve(fn(type, data));\n\t\t} catch (err) {\n\t\t\terrors.push(err);\n\t\t}\n\t\tif (errors.length > 0) throw new EventBusAggregateError(errors);\n\t}\n};\n//#endregion\n//#region src/storage/kysely/keyframe-store.ts\nvar KyselyKeyframeStore = class KyselyKeyframeStore {\n\tdb;\n\ttrx;\n\tconstructor(db) {\n\t\tthis.db = db;\n\t}\n\tget queryExecutor() {\n\t\treturn this.trx ?? this.db;\n\t}\n\twithTransaction(trx) {\n\t\tconst instance = new KyselyKeyframeStore(this.db);\n\t\tinstance.trx = trx;\n\t\treturn instance;\n\t}\n\tasync putKeyframe(documentId, scope, branch, revision, document, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst write = async (trx) => {\n\t\t\tawait acquirePurgeLocks(trx, [documentId], \"shared\");\n\t\t\tif ((await findPurged(trx, [documentId])).has(documentId)) return;\n\t\t\tawait trx.insertInto(\"Keyframe\").values({\n\t\t\t\tdocumentId,\n\t\t\t\tdocumentType: document.header.documentType,\n\t\t\t\tscope,\n\t\t\t\tbranch,\n\t\t\t\trevision,\n\t\t\t\tdocument\n\t\t\t}).onConflict((oc) => oc.columns([\n\t\t\t\t\"documentId\",\n\t\t\t\t\"scope\",\n\t\t\t\t\"branch\",\n\t\t\t\t\"revision\"\n\t\t\t]).doUpdateSet({ document })).execute();\n\t\t};\n\t\tif (this.trx) {\n\t\t\tawait write(this.trx);\n\t\t\treturn;\n\t\t}\n\t\tawait this.db.transaction().execute(write);\n\t}\n\tasync findNearestKeyframe(documentId, scope, branch, targetRevision, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tconst row = await this.queryExecutor.selectFrom(\"Keyframe\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"revision\", \"<=\", targetRevision).orderBy(\"revision\", \"desc\").limit(1).executeTakeFirst();\n\t\tif (!row) return;\n\t\treturn {\n\t\t\trevision: row.revision,\n\t\t\tdocument: row.document\n\t\t};\n\t}\n\tasync listKeyframes(documentId, scope, branch, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tlet query = this.queryExecutor.selectFrom(\"Keyframe\").selectAll().where(\"documentId\", \"=\", documentId).orderBy(\"revision\", \"asc\");\n\t\tif (scope !== void 0) query = query.where(\"scope\", \"=\", scope);\n\t\tif (branch !== void 0) query = query.where(\"branch\", \"=\", branch);\n\t\treturn (await query.execute()).map((row) => ({\n\t\t\tscope: row.scope,\n\t\t\tbranch: row.branch,\n\t\t\trevision: row.revision,\n\t\t\tdocument: row.document\n\t\t}));\n\t}\n\tasync deleteKeyframes(documentId, scope, branch, signal) {\n\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\tlet query = this.queryExecutor.deleteFrom(\"Keyframe\").where(\"documentId\", \"=\", documentId);\n\t\tif (scope !== void 0 && branch !== void 0) query = query.where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch);\n\t\telse if (scope !== void 0) query = query.where(\"scope\", \"=\", scope);\n\t\tconst result = await query.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows || 0n);\n\t}\n};\n//#endregion\n//#region src/storage/kysely/pagination.ts\nconst DEFAULT_LIMIT = 100;\nfunction paginateRows(rows, paging, cursorOf, toItem, refetch) {\n\tlet hasMore = false;\n\tlet items = rows;\n\tif (paging?.limit && rows.length > paging.limit) {\n\t\thasMore = true;\n\t\titems = rows.slice(0, paging.limit);\n\t}\n\tconst nextCursor = hasMore && items.length > 0 ? cursorOf(items[items.length - 1]).toString() : void 0;\n\tconst cursor = paging?.cursor || \"0\";\n\tconst limit = paging?.limit || DEFAULT_LIMIT;\n\treturn {\n\t\tresults: items.map(toItem),\n\t\toptions: {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t},\n\t\tnextCursor,\n\t\tnext: hasMore ? () => refetch(nextCursor, limit) : void 0\n\t};\n}\n//#endregion\n//#region src/storage/txn.ts\nvar AtomicTransaction = class {\n\tdocumentId;\n\tdocumentType;\n\tscope;\n\tbranch;\n\tbaseRevision;\n\toperations = [];\n\tconstructor(documentId, documentType, scope, branch, baseRevision) {\n\t\tthis.documentId = documentId;\n\t\tthis.documentType = documentType;\n\t\tthis.scope = scope;\n\t\tthis.branch = branch;\n\t\tthis.baseRevision = baseRevision;\n\t}\n\taddOperations(...operations) {\n\t\tfor (const op of operations) this.operations.push({\n\t\t\tjobId: v4(),\n\t\t\topId: op.id,\n\t\t\tprevOpId: \"\",\n\t\t\tdocumentId: this.documentId,\n\t\t\tdocumentType: this.documentType,\n\t\t\tscope: this.scope,\n\t\t\tbranch: this.branch,\n\t\t\ttimestampUtcMs: new Date(op.timestampUtcMs),\n\t\t\tindex: op.index,\n\t\t\taction: JSON.stringify(op.action),\n\t\t\tskip: op.skip,\n\t\t\terror: op.error || null,\n\t\t\tdeniedReason: op.deniedReason || null,\n\t\t\thash: op.hash\n\t\t});\n\t}\n\tgetOperations() {\n\t\treturn this.operations;\n\t}\n};\n//#endregion\n//#region src/storage/kysely/store.ts\nvar _UniqueConstraintContext = class extends Error {\n\tdocumentId;\n\tscope;\n\tbranch;\n\trevision;\n\tstagedOps;\n\tconstructor(documentId, scope, branch, revision, stagedOps) {\n\t\tsuper(\"unique constraint\");\n\t\tthis.documentId = documentId;\n\t\tthis.scope = scope;\n\t\tthis.branch = branch;\n\t\tthis.revision = revision;\n\t\tthis.stagedOps = stagedOps;\n\t\tthis.name = \"UniqueConstraintContext\";\n\t}\n};\nfunction duplicateOf(ctx) {\n\tconst op = ctx.stagedOps[0];\n\treturn new DuplicateOperationError(`${op.opId} at index ${op.index} with skip ${op.skip}`);\n}\nvar KyselyOperationStore = class KyselyOperationStore {\n\tdb;\n\ttrx;\n\tliveIds;\n\tconstructor(db) {\n\t\tthis.db = db;\n\t}\n\tget queryExecutor() {\n\t\treturn this.trx ?? this.db;\n\t}\n\t/** `liveIds`: ids the transaction read untombstoned under its shared lock. */\n\twithTransaction(trx, liveIds) {\n\t\tconst instance = new KyselyOperationStore(this.db);\n\t\tinstance.trx = trx;\n\t\tinstance.liveIds = liveIds;\n\t\treturn instance;\n\t}\n\tasync apply(documentId, documentType, scope, branch, revision, fn, signal, condition) {\n\t\tif (this.trx) {\n\t\t\tlet executeResult = null;\n\t\t\tlet uniqueCtx = null;\n\t\t\ttry {\n\t\t\t\texecuteResult = await this.executeApply(this.trx, documentId, documentType, scope, branch, revision, fn, signal, condition);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof _UniqueConstraintContext) uniqueCtx = error;\n\t\t\t\telse throw error;\n\t\t\t}\n\t\t\tif (uniqueCtx !== null) throw duplicateOf(uniqueCtx);\n\t\t\treturn executeResult;\n\t\t} else {\n\t\t\tlet transactionResult = null;\n\t\t\tlet uniqueCtx = null;\n\t\t\ttry {\n\t\t\t\ttransactionResult = await this.db.transaction().execute(async (trx) => {\n\t\t\t\t\treturn this.executeApply(trx, documentId, documentType, scope, branch, revision, fn, signal, condition);\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof _UniqueConstraintContext) uniqueCtx = error;\n\t\t\t\telse throw error;\n\t\t\t}\n\t\t\tif (uniqueCtx !== null) return this.resolveUniqueConstraint(uniqueCtx);\n\t\t\treturn transactionResult;\n\t\t}\n\t}\n\tasync resolveUniqueConstraint(ctx) {\n\t\tlet replayOps = null;\n\t\ttry {\n\t\t\treplayOps = await this.findIdempotentReplay(this.db, ctx.documentId, ctx.scope, ctx.branch, ctx.revision, ctx.stagedOps);\n\t\t} catch {}\n\t\tif (replayOps !== null) return replayOps;\n\t\tthrow duplicateOf(ctx);\n\t}\n\tasync executeApply(trx, documentId, documentType, scope, branch, revision, fn, signal, condition) {\n\t\tthrowIfAborted(signal);\n\t\tconst atomicTxn = new AtomicTransaction(documentId, documentType, scope, branch, revision);\n\t\tawait fn(atomicTxn);\n\t\tconst operations = atomicTxn.getOperations();\n\t\tif (operations.length === 0) return [];\n\t\tconst purgedHead = this.liveIds?.has(documentId) ? void 0 : await this.refusePurgedAppend(trx, documentId, operations);\n\t\tif (purgedHead !== void 0) return purgedHead;\n\t\tif (condition) await this.acquireStreamLocks(trx, documentId, scope, branch, condition);\n\t\tconst latestOp = await trx.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).orderBy(\"index\", \"desc\").limit(1).executeTakeFirst();\n\t\tconst currentRevision = latestOp ? latestOp.index : -1;\n\t\tif (currentRevision !== revision - 1) {\n\t\t\tlet replayOps = null;\n\t\t\ttry {\n\t\t\t\treplayOps = await this.findIdempotentReplay(trx, documentId, scope, branch, revision, operations);\n\t\t\t} catch {}\n\t\t\tif (replayOps !== null) return replayOps;\n\t\t\tif (revision === 0 && this.isCreate(operations)) throw new DocumentAlreadyExistsError(documentId, scope, currentRevision);\n\t\t\tthrow new RevisionMismatchError(currentRevision + 1, revision);\n\t\t}\n\t\tlet prevOpId = latestOp?.opId || \"\";\n\t\tfor (const op of operations) {\n\t\t\top.prevOpId = prevOpId;\n\t\t\tprevOpId = op.opId;\n\t\t}\n\t\tlet insertedCount = operations.length;\n\t\ttry {\n\t\t\tif (condition && condition.streams.length > 0) insertedCount = await this.insertGuarded(trx, operations, condition);\n\t\t\telse await trx.insertInto(\"Operation\").values(operations).execute();\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && error.message.includes(\"unique constraint\")) throw new _UniqueConstraintContext(documentId, scope, branch, revision, operations);\n\t\t\tthrow error;\n\t\t}\n\t\tif (insertedCount !== operations.length) throw new AppendConditionFailedError(condition);\n\t\treturn operations.map((op) => ({\n\t\t\tindex: op.index,\n\t\t\ttimestampUtcMs: op.timestampUtcMs.toISOString(),\n\t\t\thash: op.hash,\n\t\t\tskip: op.skip,\n\t\t\terror: op.error || void 0,\n\t\t\tdeniedReason: op.deniedReason || void 0,\n\t\t\tid: op.opId,\n\t\t\taction: JSON.parse(op.action)\n\t\t}));\n\t}\n\t/**\n\t* Locks the written stream and every read-set stream, in sorted key order\n\t* so that overlapping concurrent appends serialize rather than deadlock.\n\t* The locks are still taken one row at a time, so the query preserves that\n\t* order. It must stay separate from the guarded insert, which would\n\t* otherwise read a snapshot taken before the locks were held.\n\t*/\n\tasync acquireStreamLocks(trx, documentId, scope, branch, condition) {\n\t\tconst keys = /* @__PURE__ */ new Set([`${documentId}:${scope}:${branch}`]);\n\t\tfor (const stream of condition.streams) keys.add(`${stream.documentId}:${stream.scope}:${stream.branch}`);\n\t\tconst sortedKeys = sql.join([...keys].sort());\n\t\tawait sql`\n with ordered as materialized (\n select key\n from unnest(array[${sortedKeys}]::text[]) with ordinality as t(key, ord)\n order by ord\n )\n select pg_advisory_xact_lock(hashtext(key)) from ordered\n `.execute(trx);\n\t}\n\t/**\n\t* Inserts the staged operations with the condition compiled in as a WHERE\n\t* NOT EXISTS guard, making the check and the append one statement. Returns\n\t* the rows inserted; zero means the guard failed and nothing was written.\n\t*/\n\tasync insertGuarded(trx, operations, condition) {\n\t\tconst branches = operations.map((op) => trx.selectNoFrom([\n\t\t\tsql`${op.jobId}::text`.as(\"jobId\"),\n\t\t\tsql`${op.opId}::text`.as(\"opId\"),\n\t\t\tsql`${op.prevOpId}::text`.as(\"prevOpId\"),\n\t\t\tsql`${op.documentId}::text`.as(\"documentId\"),\n\t\t\tsql`${op.documentType}::text`.as(\"documentType\"),\n\t\t\tsql`${op.scope}::text`.as(\"scope\"),\n\t\t\tsql`${op.branch}::text`.as(\"branch\"),\n\t\t\tsql`${op.timestampUtcMs}::timestamptz`.as(\"timestampUtcMs\"),\n\t\t\tsql`${op.index}::integer`.as(\"index\"),\n\t\t\tsql`${op.action}::jsonb`.as(\"action\"),\n\t\t\tsql`${op.skip}::integer`.as(\"skip\"),\n\t\t\tsql`${op.error ?? null}::text`.as(\"error\"),\n\t\t\tsql`${op.deniedReason ?? null}::text`.as(\"deniedReason\"),\n\t\t\tsql`${op.hash}::text`.as(\"hash\")\n\t\t]).where((eb) => eb.not(eb.exists(eb.selectFrom(\"Operation\").select(\"Operation.id\").where((web) => web.or(condition.streams.map((s) => web.and([\n\t\t\tweb(\"Operation.documentId\", \"=\", s.documentId),\n\t\t\tweb(\"Operation.scope\", \"=\", s.scope),\n\t\t\tweb(\"Operation.branch\", \"=\", s.branch),\n\t\t\tweb(\"Operation.index\", \">\", s.revision)\n\t\t]))))))));\n\t\tlet expression = branches[0];\n\t\tfor (let i = 1; i < branches.length; i++) expression = expression.unionAll(branches[i]);\n\t\treturn (await trx.insertInto(\"Operation\").columns([\n\t\t\t\"jobId\",\n\t\t\t\"opId\",\n\t\t\t\"prevOpId\",\n\t\t\t\"documentId\",\n\t\t\t\"documentType\",\n\t\t\t\"scope\",\n\t\t\t\"branch\",\n\t\t\t\"timestampUtcMs\",\n\t\t\t\"index\",\n\t\t\t\"action\",\n\t\t\t\"skip\",\n\t\t\t\"error\",\n\t\t\t\"deniedReason\",\n\t\t\t\"hash\"\n\t\t]).expression(expression).returning(\"id\").execute()).length;\n\t}\n\tasync findIdempotentReplay(executor, documentId, scope, branch, revision, stagedOps) {\n\t\tconst minIndex = revision;\n\t\tconst maxIndex = revision + stagedOps.length - 1;\n\t\tconst storedRows = await executor.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"index\", \">=\", minIndex).where(\"index\", \"<=\", maxIndex).orderBy(\"index\", \"asc\").execute();\n\t\tif (storedRows.length !== stagedOps.length) return null;\n\t\tfor (let i = 0; i < stagedOps.length; i++) {\n\t\t\tconst staged = stagedOps[i];\n\t\t\tconst stored = storedRows[i];\n\t\t\tif (stored.opId !== staged.opId || stored.index !== staged.index || stored.skip !== staged.skip) return null;\n\t\t}\n\t\treturn storedRows.map((row) => this.rowToOperation(row));\n\t}\n\t/** A purged stream refuses appends; a marker gets the stored one back. */\n\tasync refusePurgedAppend(trx, documentId, operations) {\n\t\tif (!(await findPurged(trx, [documentId])).has(documentId)) return;\n\t\tif (!operations.every((operation) => this.isMarker(operation))) throw new DocumentPurgedError(documentId);\n\t\treturn (await trx.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(sql`action->>'type' = ${PURGE_DOCUMENT}`).orderBy(\"index\", \"asc\").execute()).map((row) => this.rowToOperation(row));\n\t}\n\tisMarker(operation) {\n\t\treturn this.actionType(operation) === PURGE_DOCUMENT;\n\t}\n\tactionType(operation) {\n\t\tlet action = operation.action;\n\t\tif (typeof action === \"string\") try {\n\t\t\taction = JSON.parse(action);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (typeof action === \"object\" && action !== null && \"type\" in action && typeof action.type === \"string\") return action.type;\n\t}\n\t/** True when the staged write creates a document rather than appending to one. */\n\tisCreate(operations) {\n\t\tfor (const operation of operations) {\n\t\t\tlet action = operation.action;\n\t\t\tif (typeof action === \"string\") try {\n\t\t\t\taction = JSON.parse(action);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (typeof action === \"object\" && action !== null && \"type\" in action && typeof action.type === \"string\" && action.type === \"CREATE_DOCUMENT\") return true;\n\t\t}\n\t\treturn false;\n\t}\n\t/**\n\t* The paging cursor here encodes the index to resume from (one past the\n\t* last row returned), not the last row's own index. This keeps \"0\" an\n\t* unambiguous start-of-stream sentinel even when a page ends at index 0\n\t* (e.g. `limit: 1` on a fresh stream), which would otherwise make\n\t* `nextCursor` equal the start cursor and loop a caller that walks pages\n\t* forever.\n\t*/\n\tasync getSince(documentId, scope, branch, revision, filter, paging, signal) {\n\t\tthrowIfAborted(signal);\n\t\tlet query = this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"index\", \">\", revision).orderBy(\"index\", \"asc\");\n\t\tif (filter) {\n\t\t\tif (filter.actionTypes && filter.actionTypes.length > 0) {\n\t\t\t\tconst actionTypesArray = filter.actionTypes.map((t) => `'${t.replace(/'/g, \"''\")}'`).join(\",\");\n\t\t\t\tquery = query.where(sql`action->>'type' = ANY(ARRAY[${sql.raw(actionTypesArray)}]::text[])`);\n\t\t\t}\n\t\t\tif (filter.timestampFrom) query = query.where(\"timestampUtcMs\", \">=\", new Date(filter.timestampFrom));\n\t\t\tif (filter.timestampTo) query = query.where(\"timestampUtcMs\", \"<=\", new Date(filter.timestampTo));\n\t\t\tif (filter.sinceRevision !== void 0) query = query.where(\"index\", \">=\", filter.sinceRevision);\n\t\t}\n\t\tif (paging) {\n\t\t\tconst cursorValue = Number.parseInt(paging.cursor, 10);\n\t\t\tif (Number.isFinite(cursorValue) && cursorValue > 0) query = query.where(\"index\", \">=\", cursorValue);\n\t\t\tif (paging.limit) query = query.limit(paging.limit + 1);\n\t\t}\n\t\treturn paginateRows(await query.execute(), paging, (row) => row.index + 1, (row) => this.rowToOperation(row), (cursor, limit) => this.getSince(documentId, scope, branch, revision, filter, {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t}, signal));\n\t}\n\tasync getSinceId(id, paging, signal) {\n\t\tthrowIfAborted(signal);\n\t\tlet query = this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"id\", \">\", id).orderBy(\"id\", \"asc\");\n\t\tif (paging) {\n\t\t\tconst cursorValue = Number.parseInt(paging.cursor, 10);\n\t\t\tif (cursorValue > 0) query = query.where(\"id\", \">\", cursorValue);\n\t\t\tif (paging.limit) query = query.limit(paging.limit + 1);\n\t\t}\n\t\treturn paginateRows(await query.execute(), paging, (row) => row.id, (row) => this.rowToOperationWithContext(row), (cursor, limit) => this.getSinceId(id, {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t}, signal));\n\t}\n\t/**\n\t* The paging cursor here encodes the index to resume from (one past the\n\t* last row returned), not the last row's own index, for the same reason as\n\t* `getSince`: a page ending at index 0 must not produce a cursor that is\n\t* indistinguishable from the start-of-stream sentinel.\n\t*/\n\tasync getConflicting(documentId, scope, branch, minTimestamp, paging, signal) {\n\t\tthrowIfAborted(signal);\n\t\tlet query = this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).where(\"timestampUtcMs\", \">=\", new Date(minTimestamp)).orderBy(\"index\", \"asc\");\n\t\tif (paging) {\n\t\t\tconst cursorValue = Number.parseInt(paging.cursor, 10);\n\t\t\tif (Number.isFinite(cursorValue) && cursorValue > 0) query = query.where(\"index\", \">=\", cursorValue);\n\t\t\tif (paging.limit) query = query.limit(paging.limit + 1);\n\t\t}\n\t\treturn paginateRows(await query.execute(), paging, (row) => row.index + 1, (row) => this.rowToOperation(row), (cursor, limit) => this.getConflicting(documentId, scope, branch, minTimestamp, {\n\t\t\tcursor,\n\t\t\tlimit\n\t\t}, signal));\n\t}\n\tasync getRevisions(documentId, branch, signal) {\n\t\tthrowIfAborted(signal);\n\t\tconst scopeRevisions = await this.queryExecutor.selectFrom(\"Operation\").select(\"scope\").select((eb) => eb.fn.max(\"index\").as(\"index\")).where(\"documentId\", \"=\", documentId).where(\"branch\", \"=\", branch).groupBy(\"scope\").execute();\n\t\tconst latest = await this.queryExecutor.selectFrom(\"Operation\").select((eb) => eb.fn.max(\"timestampUtcMs\").as(\"latestTimestamp\")).where(\"documentId\", \"=\", documentId).where(\"branch\", \"=\", branch).executeTakeFirst();\n\t\tconst revision = {};\n\t\tfor (const row of scopeRevisions) revision[row.scope] = row.index + 1;\n\t\treturn {\n\t\t\trevision,\n\t\t\tlatestTimestamp: latest?.latestTimestamp ? new Date(latest.latestTimestamp).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString()\n\t\t};\n\t}\n\tasync getStreamLatestTimestamp(documentId, scope, branch, signal) {\n\t\tconst latest = await this.queryExecutor.selectFrom(\"Operation\").select((eb) => eb.fn.max(\"timestampUtcMs\").as(\"latestTimestamp\")).where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).executeTakeFirst();\n\t\treturn latest?.latestTimestamp ? new Date(latest.latestTimestamp).toISOString() : void 0;\n\t}\n\tasync findOperationIds(documentId, scope, branch, opIds, signal) {\n\t\tthrowIfAborted(signal);\n\t\tif (opIds.length === 0) return /* @__PURE__ */ new Set();\n\t\tconst rows = await this.queryExecutor.selectFrom(\"Operation\").select(\"opId\").distinct().where(\"opId\", \"in\", opIds).where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).execute();\n\t\treturn new Set(rows.map((row) => row.opId));\n\t}\n\tasync getOperationsByIds(documentId, scope, branch, opIds, signal) {\n\t\tthrowIfAborted(signal);\n\t\tif (opIds.length === 0) return [];\n\t\tconst rows = await this.queryExecutor.selectFrom(\"Operation\").selectAll().where(\"opId\", \"in\", opIds).where(\"documentId\", \"=\", documentId).where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch).orderBy(\"index\", \"asc\").execute();\n\t\tconst latest = /* @__PURE__ */ new Map();\n\t\tfor (const row of rows) latest.set(row.opId, this.rowToOperation(row));\n\t\treturn [...latest.values()];\n\t}\n\trowToOperation(row) {\n\t\treturn {\n\t\t\tindex: row.index,\n\t\t\ttimestampUtcMs: row.timestampUtcMs.toISOString(),\n\t\t\thash: row.hash,\n\t\t\tskip: row.skip,\n\t\t\terror: row.error || void 0,\n\t\t\tdeniedReason: row.deniedReason || void 0,\n\t\t\tid: row.opId,\n\t\t\taction: row.action\n\t\t};\n\t}\n\trowToOperationWithContext(row) {\n\t\treturn {\n\t\t\toperation: this.rowToOperation(row),\n\t\t\tcontext: {\n\t\t\t\tdocumentId: row.documentId,\n\t\t\t\tdocumentType: row.documentType,\n\t\t\t\tscope: row.scope,\n\t\t\t\tbranch: row.branch,\n\t\t\t\tordinal: row.id\n\t\t\t}\n\t\t};\n\t}\n};\n//#endregion\n//#region src/storage/pool-instrumentation.ts\n/**\n* Wraps an existing pg.Pool with acquire-wait timing and an event\n* subscription surface. The pool is mutated in place: pool.connect()\n* is replaced with a timing wrapper so all callers (Kysely included)\n* pick up the instrumentation transparently.\n*/\nfunction instrumentPgPool(pool, name) {\n\tconst listeners = /* @__PURE__ */ new Set();\n\tconst originalConnect = pool.connect.bind(pool);\n\tconst wrappedConnect = async () => {\n\t\tconst start = performance.now();\n\t\tconst client = await originalConnect();\n\t\tconst durationMs = performance.now() - start;\n\t\tfor (const listener of listeners) try {\n\t\t\tlistener(durationMs);\n\t\t} catch {}\n\t\treturn client;\n\t};\n\tpool.connect = wrappedConnect;\n\treturn {\n\t\tname,\n\t\tgetStats() {\n\t\t\treturn {\n\t\t\t\tsize: pool.totalCount,\n\t\t\t\tidle: pool.idleCount,\n\t\t\t\twaiting: pool.waitingCount\n\t\t\t};\n\t\t},\n\t\tonAcquire(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t}\n\t};\n}\nfunction createForwardingPoolInstrumentation(name) {\n\tconst listeners = /* @__PURE__ */ new Set();\n\tlet stats = {\n\t\tsize: 0,\n\t\tidle: 0,\n\t\twaiting: 0\n\t};\n\treturn {\n\t\tname,\n\t\tgetStats() {\n\t\t\treturn stats;\n\t\t},\n\t\tonAcquire(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tpushSamples(durations) {\n\t\t\tfor (const durationMs of durations) for (const listener of listeners) try {\n\t\t\t\tlistener(durationMs);\n\t\t\t} catch {}\n\t\t},\n\t\tupdateStats(next) {\n\t\t\tstats = next;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/storage/migrations/001_create_operation_table.ts\nvar _001_create_operation_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$26 });\nasync function up$26(db) {\n\tawait db.schema.createTable(\"Operation\").addColumn(\"id\", \"serial\", (col) => col.primaryKey()).addColumn(\"jobId\", \"text\", (col) => col.notNull()).addColumn(\"opId\", \"text\", (col) => col.notNull()).addColumn(\"prevOpId\", \"text\", (col) => col.notNull()).addColumn(\"writeTimestampUtcMs\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"timestampUtcMs\", \"timestamptz\", (col) => col.notNull()).addColumn(\"index\", \"integer\", (col) => col.notNull()).addColumn(\"action\", \"jsonb\", (col) => col.notNull()).addColumn(\"skip\", \"integer\", (col) => col.notNull()).addColumn(\"error\", \"text\").addColumn(\"hash\", \"text\", (col) => col.notNull()).addUniqueConstraint(\"unique_revision\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"index\"\n\t]).addUniqueConstraint(\"unique_operation_instance\", [\n\t\t\"opId\",\n\t\t\"index\",\n\t\t\"skip\"\n\t]).execute();\n\tawait db.schema.createIndex(\"streamOperations\").on(\"Operation\").columns([\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"id\"\n\t]).execute();\n\tawait db.schema.createIndex(\"branchlessStreamOperations\").on(\"Operation\").columns([\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"id\"\n\t]).execute();\n}\n//#endregion\n//#region src/storage/migrations/002_create_keyframe_table.ts\nvar _002_create_keyframe_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$25 });\nasync function up$25(db) {\n\tawait db.schema.createTable(\"Keyframe\").addColumn(\"id\", \"serial\", (col) => col.primaryKey()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"revision\", \"integer\", (col) => col.notNull()).addColumn(\"document\", \"jsonb\", (col) => col.notNull()).addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addUniqueConstraint(\"unique_keyframe\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"revision\"\n\t]).execute();\n\tawait db.schema.createIndex(\"keyframe_lookup\").on(\"Keyframe\").columns([\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\",\n\t\t\"revision\"\n\t]).execute();\n}\n//#endregion\n//#region src/storage/migrations/003_create_document_table.ts\nvar _003_create_document_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$24 });\nasync function up$24(db) {\n\tawait db.schema.createTable(\"Document\").addColumn(\"id\", \"text\", (col) => col.primaryKey()).addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/004_create_document_relationship_table.ts\nvar _004_create_document_relationship_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$23 });\nasync function up$23(db) {\n\tawait db.schema.createTable(\"DocumentRelationship\").addColumn(\"id\", \"text\", (col) => col.primaryKey()).addColumn(\"sourceId\", \"text\", (col) => col.notNull().references(\"Document.id\").onDelete(\"cascade\")).addColumn(\"targetId\", \"text\", (col) => col.notNull().references(\"Document.id\").onDelete(\"cascade\")).addColumn(\"relationshipType\", \"text\", (col) => col.notNull()).addColumn(\"metadata\", \"jsonb\").addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addUniqueConstraint(\"unique_source_target_type\", [\n\t\t\"sourceId\",\n\t\t\"targetId\",\n\t\t\"relationshipType\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_relationship_source\").on(\"DocumentRelationship\").column(\"sourceId\").execute();\n\tawait db.schema.createIndex(\"idx_relationship_target\").on(\"DocumentRelationship\").column(\"targetId\").execute();\n\tawait db.schema.createIndex(\"idx_relationship_type\").on(\"DocumentRelationship\").column(\"relationshipType\").execute();\n}\n//#endregion\n//#region src/storage/migrations/005_create_indexer_state_table.ts\nvar _005_create_indexer_state_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$22 });\nasync function up$22(db) {\n\tawait db.schema.createTable(\"IndexerState\").addColumn(\"id\", \"integer\", (col) => col.primaryKey().generatedAlwaysAsIdentity()).addColumn(\"lastOperationId\", \"integer\", (col) => col.notNull()).addColumn(\"lastOperationTimestamp\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/006_create_document_snapshot_table.ts\nvar _006_create_document_snapshot_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$21 });\nasync function up$21(db) {\n\tawait db.schema.createTable(\"DocumentSnapshot\").addColumn(\"id\", \"text\", (col) => col.primaryKey()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"slug\", \"text\").addColumn(\"name\", \"text\").addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"content\", \"jsonb\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"lastOperationIndex\", \"integer\", (col) => col.notNull()).addColumn(\"lastOperationHash\", \"text\", (col) => col.notNull()).addColumn(\"lastUpdatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"snapshotVersion\", \"integer\", (col) => col.notNull().defaultTo(1)).addColumn(\"identifiers\", \"jsonb\").addColumn(\"metadata\", \"jsonb\").addColumn(\"isDeleted\", \"boolean\", (col) => col.notNull().defaultTo(false)).addColumn(\"deletedAt\", \"timestamptz\").addUniqueConstraint(\"unique_doc_scope_branch\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_slug_scope_branch\").on(\"DocumentSnapshot\").columns([\n\t\t\"slug\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_doctype_scope_branch\").on(\"DocumentSnapshot\").columns([\n\t\t\"documentType\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_last_updated\").on(\"DocumentSnapshot\").column(\"lastUpdatedAt\").execute();\n\tawait db.schema.createIndex(\"idx_is_deleted\").on(\"DocumentSnapshot\").column(\"isDeleted\").execute();\n}\n//#endregion\n//#region src/storage/migrations/007_create_slug_mapping_table.ts\nvar _007_create_slug_mapping_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$20 });\nasync function up$20(db) {\n\tawait db.schema.createTable(\"SlugMapping\").addColumn(\"slug\", \"text\", (col) => col.primaryKey()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addUniqueConstraint(\"unique_docid_scope_branch\", [\n\t\t\"documentId\",\n\t\t\"scope\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_slug_documentid\").on(\"SlugMapping\").column(\"documentId\").execute();\n}\n//#endregion\n//#region src/storage/migrations/008_create_view_state_table.ts\nvar _008_create_view_state_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$19 });\nasync function up$19(db) {\n\tawait db.schema.createTable(\"ViewState\").addColumn(\"readModelId\", \"text\", (col) => col.primaryKey()).addColumn(\"lastOrdinal\", \"integer\", (col) => col.notNull().defaultTo(0)).addColumn(\"lastOperationTimestamp\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/009_create_operation_index_tables.ts\nvar _009_create_operation_index_tables_exports = /* @__PURE__ */ __exportAll({ up: () => up$18 });\nasync function up$18(db) {\n\tawait db.schema.createTable(\"document_collections\").addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"collectionId\", \"text\", (col) => col.notNull()).addColumn(\"joinedOrdinal\", \"bigint\", (col) => col.notNull().defaultTo(0)).addColumn(\"leftOrdinal\", \"bigint\").addPrimaryKeyConstraint(\"document_collections_pkey\", [\"documentId\", \"collectionId\"]).execute();\n\tawait db.schema.createIndex(\"idx_document_collections_collectionId\").on(\"document_collections\").column(\"collectionId\").execute();\n\tawait db.schema.createIndex(\"idx_doc_collections_collection_range\").on(\"document_collections\").columns([\"collectionId\", \"joinedOrdinal\"]).execute();\n\tawait db.schema.createTable(\"operation_index_operations\").addColumn(\"ordinal\", \"serial\", (col) => col.primaryKey()).addColumn(\"opId\", \"text\", (col) => col.notNull()).addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"documentType\", \"text\", (col) => col.notNull()).addColumn(\"scope\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"timestampUtcMs\", \"text\", (col) => col.notNull()).addColumn(\"writeTimestampUtcMs\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"index\", \"integer\", (col) => col.notNull()).addColumn(\"skip\", \"integer\", (col) => col.notNull()).addColumn(\"hash\", \"text\", (col) => col.notNull()).addColumn(\"action\", \"jsonb\", (col) => col.notNull()).execute();\n\tawait db.schema.createIndex(\"idx_operation_index_operations_document\").on(\"operation_index_operations\").columns([\n\t\t\"documentId\",\n\t\t\"branch\",\n\t\t\"scope\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_operation_index_operations_ordinal\").on(\"operation_index_operations\").column(\"ordinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/010_create_sync_tables.ts\nvar _010_create_sync_tables_exports = /* @__PURE__ */ __exportAll({ up: () => up$17 });\nasync function up$17(db) {\n\tawait db.schema.createTable(\"sync_remotes\").addColumn(\"name\", \"text\", (col) => col.primaryKey()).addColumn(\"collection_id\", \"text\", (col) => col.notNull()).addColumn(\"channel_type\", \"text\", (col) => col.notNull()).addColumn(\"channel_id\", \"text\", (col) => col.notNull().defaultTo(\"\")).addColumn(\"remote_name\", \"text\", (col) => col.notNull().defaultTo(\"\")).addColumn(\"channel_parameters\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'{}'::jsonb`)).addColumn(\"filter_document_ids\", \"jsonb\").addColumn(\"filter_scopes\", \"jsonb\").addColumn(\"filter_branch\", \"text\", (col) => col.notNull().defaultTo(\"main\")).addColumn(\"push_state\", \"text\", (col) => col.notNull().defaultTo(\"idle\")).addColumn(\"push_last_success_utc_ms\", \"text\").addColumn(\"push_last_failure_utc_ms\", \"text\").addColumn(\"push_failure_count\", \"integer\", (col) => col.notNull().defaultTo(0)).addColumn(\"pull_state\", \"text\", (col) => col.notNull().defaultTo(\"idle\")).addColumn(\"pull_last_success_utc_ms\", \"text\").addColumn(\"pull_last_failure_utc_ms\", \"text\").addColumn(\"pull_failure_count\", \"integer\", (col) => col.notNull().defaultTo(0)).addColumn(\"created_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updated_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n\tawait db.schema.createIndex(\"idx_sync_remotes_collection\").on(\"sync_remotes\").column(\"collection_id\").execute();\n\tawait db.schema.createTable(\"sync_cursors\").addColumn(\"remote_name\", \"text\", (col) => col.primaryKey().references(\"sync_remotes.name\").onDelete(\"cascade\")).addColumn(\"cursor_ordinal\", \"bigint\", (col) => col.notNull().defaultTo(0)).addColumn(\"last_synced_at_utc_ms\", \"text\").addColumn(\"updated_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n\tawait db.schema.createIndex(\"idx_sync_cursors_ordinal\").on(\"sync_cursors\").column(\"cursor_ordinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/011_add_cursor_type_column.ts\nvar _011_add_cursor_type_column_exports = /* @__PURE__ */ __exportAll({ up: () => up$16 });\nasync function up$16(db) {\n\tawait db.deleteFrom(\"sync_cursors\").where(\"remote_name\", \"like\", \"outbox::%\").execute();\n\tawait db.deleteFrom(\"sync_remotes\").where(\"name\", \"like\", \"outbox::%\").execute();\n\tawait db.schema.dropTable(\"sync_cursors\").execute();\n\tawait db.schema.createTable(\"sync_cursors\").addColumn(\"remote_name\", \"text\", (col) => col.notNull()).addColumn(\"cursor_type\", \"text\", (col) => col.notNull().defaultTo(\"inbox\")).addColumn(\"cursor_ordinal\", \"bigint\", (col) => col.notNull().defaultTo(0)).addColumn(\"last_synced_at_utc_ms\", \"text\").addColumn(\"updated_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addPrimaryKeyConstraint(\"sync_cursors_pk\", [\"remote_name\", \"cursor_type\"]).execute();\n\tawait db.schema.createIndex(\"idx_sync_cursors_ordinal\").on(\"sync_cursors\").column(\"cursor_ordinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/012_add_source_remote_column.ts\nvar _012_add_source_remote_column_exports = /* @__PURE__ */ __exportAll({ up: () => up$15 });\nasync function up$15(db) {\n\tawait db.schema.alterTable(\"operation_index_operations\").addColumn(\"sourceRemote\", \"text\", (col) => col.notNull().defaultTo(\"\")).execute();\n}\n//#endregion\n//#region src/storage/migrations/013_create_sync_dead_letters_table.ts\nvar _013_create_sync_dead_letters_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$14 });\nasync function up$14(db) {\n\tawait db.schema.createTable(\"sync_dead_letters\").addColumn(\"ordinal\", \"serial\", (col) => col.primaryKey()).addColumn(\"id\", \"text\", (col) => col.unique().notNull()).addColumn(\"job_id\", \"text\", (col) => col.notNull()).addColumn(\"job_dependencies\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'[]'::jsonb`)).addColumn(\"remote_name\", \"text\", (col) => col.notNull().references(\"sync_remotes.name\").onDelete(\"cascade\")).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"scopes\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'[]'::jsonb`)).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"operations\", \"jsonb\", (col) => col.notNull().defaultTo(sql`'[]'::jsonb`)).addColumn(\"error_source\", \"text\", (col) => col.notNull()).addColumn(\"error_message\", \"text\", (col) => col.notNull()).addColumn(\"created_at\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n\tawait db.schema.createIndex(\"idx_sync_dead_letters_remote\").on(\"sync_dead_letters\").column(\"remote_name\").execute();\n}\n//#endregion\n//#region src/storage/migrations/014_create_processor_cursor_table.ts\nvar _014_create_processor_cursor_table_exports = /* @__PURE__ */ __exportAll({ up: () => up$13 });\nasync function up$13(db) {\n\tawait db.schema.createTable(\"ProcessorCursor\").addColumn(\"processorId\", \"text\", (col) => col.primaryKey()).addColumn(\"factoryId\", \"text\", (col) => col.notNull()).addColumn(\"driveId\", \"text\", (col) => col.notNull()).addColumn(\"processorIndex\", \"integer\", (col) => col.notNull()).addColumn(\"lastOrdinal\", \"integer\", (col) => col.notNull().defaultTo(sql`0`)).addColumn(\"status\", \"text\", (col) => col.notNull().defaultTo(sql`'active'`)).addColumn(\"lastError\", \"text\").addColumn(\"lastErrorTimestamp\", \"timestamptz\").addColumn(\"createdAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).addColumn(\"updatedAt\", \"timestamptz\", (col) => col.notNull().defaultTo(sql`NOW()`)).execute();\n}\n//#endregion\n//#region src/storage/migrations/015_add_operation_denied_reason.ts\nvar _015_add_operation_denied_reason_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$12,\n\tup: () => up$12\n});\n/**\n* Records why authorization refused an operation. Separate from `error` so a\n* denial is distinguishable from a reducer failure without matching on a\n* message. Null for every operation written before decisions were enforced.\n*/\nasync function up$12(db) {\n\tawait db.schema.alterTable(\"Operation\").addColumn(\"deniedReason\", \"text\").execute();\n\tawait db.schema.alterTable(\"operation_index_operations\").addColumn(\"deniedReason\", \"text\").execute();\n}\nasync function down$12(db) {\n\tawait db.schema.alterTable(\"operation_index_operations\").dropColumn(\"deniedReason\").execute();\n\tawait db.schema.alterTable(\"Operation\").dropColumn(\"deniedReason\").execute();\n}\n//#endregion\n//#region src/storage/migrations/016_add_dead_letter_error_type.ts\nvar _016_add_dead_letter_error_type_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$11,\n\tup: () => up$11\n});\n/**\n* The classification a dead letter falls into, stored because it decides whether\n* the document stays quarantined and the in-memory error is gone after a restart.\n* Defaulted rather than nullable, so a pre-existing row rehydrates.\n*/\nasync function up$11(db) {\n\tawait db.schema.alterTable(\"sync_dead_letters\").addColumn(\"error_type\", \"text\", (col) => col.notNull().defaultTo(\"UNCLASSIFIED\")).execute();\n}\nasync function down$11(db) {\n\tawait db.schema.alterTable(\"sync_dead_letters\").dropColumn(\"error_type\").execute();\n}\n//#endregion\n//#region src/storage/migrations/017_create_group_references.ts\nvar _017_create_group_references_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$10,\n\tup: () => up$10\n});\n/**\n* One row per (document, group) reference ever discovered from an auth\n* operation's input. Rows are never updated or deleted: auth evaluation is\n* positional, so a grant that named a group at any position keeps that\n* group's stream in the document's read-set even after a later operation\n* removes the reference. Read by documentId for the groups a document\n* requires (sync), and by groupId for the documents a group change affects\n* (re-evaluation).\n*/\nasync function up$10(db) {\n\tawait db.schema.createTable(\"group_references\").addColumn(\"documentId\", \"text\", (col) => col.notNull()).addColumn(\"groupId\", \"text\", (col) => col.notNull()).addPrimaryKeyConstraint(\"group_references_pkey\", [\"documentId\", \"groupId\"]).execute();\n\tawait db.schema.createIndex(\"idx_group_references_groupId\").on(\"group_references\").column(\"groupId\").execute();\n}\nasync function down$10(db) {\n\tawait db.schema.dropTable(\"group_references\").execute();\n}\n//#endregion\n//#region src/storage/migrations/018_add_sync_remote_bound_address.ts\nvar _018_add_sync_remote_bound_address_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$9,\n\tup: () => up$9\n});\n/**\n* The address a sync channel is bound to, so a channel created by one subject\n* cannot be polled by another.\n*\n* Nullable rather than defaulted: null is a channel nobody has claimed, which is\n* what every pre-existing row is and what an anonymously created channel stays\n* until its first authenticated poll adopts it. A default would claim them all\n* for one address.\n*/\nasync function up$9(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").addColumn(\"bound_address\", \"text\").execute();\n}\nasync function down$9(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").dropColumn(\"bound_address\").execute();\n}\n//#endregion\n//#region src/storage/migrations/019_require_action_id.ts\nvar _019_require_action_id_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$8,\n\tup: () => up$8\n});\n/**\n* Makes an operation whose action carries no id physically unstorable.\n*\n* The id is not decoration: `deriveOperationId` hashes it into the operation id\n* and replay dedupes incoming operations by it, so an action without one\n* collapses every id-less operation on a document/scope/branch onto a single\n* derived operation id. The API rejects such an action now, and this is the\n* last line of defense behind it.\n*\n* Both tables are constrained because sync reads operations from the index\n* rather than the operation table, so poison reaching only the index would\n* still be served to a replica.\n*\n* Pre-existing rows are backfilled rather than left behind a NOT VALID\n* constraint: a row the index and the operation table disagree about is worse\n* than a missing id, because dedup keys off the value each side serves. The\n* backfill therefore mints one id per operation and writes that same id to both\n* tables, joined on the identity they share. Rewriting the action is safe: the\n* operation hash is taken over the resulting state, not over the action, and a\n* signature is verified from the params carried in the signature tuple, which\n* do not include the action id.\n*\n* The empty string is rejected alongside null. It derives the same colliding\n* operation id as an absent id, so admitting it would leave the hole open.\n*/\nasync function up$8(db) {\n\tawait db.updateTable(\"Operation\").set({ action: sql`jsonb_set(action, '{id}', to_jsonb(gen_random_uuid()::text))` }).where(sql`jsonb_typeof(action) = 'object' and coalesce(action->>'id', '') = ''`).execute();\n\tawait db.updateTable(\"operation_index_operations as oio\").from(\"Operation as op\").set({ action: sql`jsonb_set(oio.action, '{id}', to_jsonb(op.action->>'id'))` }).whereRef(\"oio.opId\", \"=\", \"op.opId\").whereRef(\"oio.index\", \"=\", \"op.index\").whereRef(\"oio.skip\", \"=\", \"op.skip\").where(sql`jsonb_typeof(oio.action) = 'object' and coalesce(oio.action->>'id', '') = ''`).where(sql`coalesce(op.action->>'id', '') <> ''`).execute();\n\tawait db.updateTable(\"operation_index_operations\").set({ action: sql`jsonb_set(action, '{id}', to_jsonb(gen_random_uuid()::text))` }).where(sql`jsonb_typeof(action) = 'object' and coalesce(action->>'id', '') = ''`).execute();\n\tawait db.schema.alterTable(\"Operation\").addCheckConstraint(\"action_must_have_id\", sql`action->>'id' is not null and action->>'id' <> ''`).execute();\n\tawait db.schema.alterTable(\"operation_index_operations\").addCheckConstraint(\"action_must_have_id\", sql`action->>'id' is not null and action->>'id' <> ''`).execute();\n}\n/**\n* Only the constraints are dropped. The backfilled ids stay: they are the ids\n* their operations are now known by, and reverting them would reintroduce the\n* collision the migration removed.\n*/\nasync function down$8(db) {\n\tawait db.schema.alterTable(\"operation_index_operations\").dropConstraint(\"action_must_have_id\").execute();\n\tawait db.schema.alterTable(\"Operation\").dropConstraint(\"action_must_have_id\").execute();\n}\n//#endregion\n//#region src/storage/migrations/020_add_snapshot_operation_ordinal.ts\nvar _020_add_snapshot_operation_ordinal_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$7,\n\tup: () => up$7\n});\n/** Orders header row writes across scopes; `lastOperationIndex` is per scope. */\nasync function up$7(db) {\n\tawait db.schema.alterTable(\"DocumentSnapshot\").addColumn(\"lastOperationOrdinal\", \"integer\", (col) => col.notNull().defaultTo(0)).execute();\n}\nasync function down$7(db) {\n\tawait db.schema.alterTable(\"DocumentSnapshot\").dropColumn(\"lastOperationOrdinal\").execute();\n}\n//#endregion\n//#region src/storage/migrations/021_add_sync_remote_peer.ts\nvar _021_add_sync_remote_peer_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$6,\n\tup: () => up$6\n});\n/**\n* The peer's manifest as canonical JSON, and when it was heard. Both null: not\n* yet heard. A time with no manifest: a silent peer, which gets the baselines.\n*/\nasync function up$6(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").addColumn(\"peer_manifest\", \"text\").addColumn(\"peer_manifest_at_utc_ms\", \"bigint\").execute();\n}\nasync function down$6(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").dropColumn(\"peer_manifest\").dropColumn(\"peer_manifest_at_utc_ms\").execute();\n}\n//#endregion\n//#region src/storage/migrations/022_create_sync_holds.ts\nvar _022_create_sync_holds_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$5,\n\tup: () => up$5\n});\n/** Documents held back from a remote whose peer cannot run their versions. */\nasync function up$5(db) {\n\tawait db.schema.createTable(\"sync_holds\").addColumn(\"remote_name\", \"text\", (col) => col.notNull().references(\"sync_remotes.name\").onDelete(\"cascade\")).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"protocol\", \"text\", (col) => col.notNull()).addColumn(\"version\", \"integer\", (col) => col.notNull()).addColumn(\"held_at_utc_ms\", \"bigint\", (col) => col.notNull()).addPrimaryKeyConstraint(\"sync_holds_pkey\", [\n\t\t\"remote_name\",\n\t\t\"document_id\",\n\t\t\"branch\"\n\t]).execute();\n}\nasync function down$5(db) {\n\tawait db.schema.dropTable(\"sync_holds\").execute();\n}\n//#endregion\n//#region src/storage/migrations/023_index_created_protocol_versions.ts\nvar _023_index_created_protocol_versions_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$4,\n\tup: () => up$4\n});\n/**\n* One entry per document created with protocolVersions, keyed by a hash so an\n* oversized header cannot make its creation unstorable. Startup reads the\n* distinct values without visiting every document.\n*/\nasync function up$4(db) {\n\tawait db.schema.createIndex(\"idx_operation_created_protocol_versions\").on(\"Operation\").expression(sql`md5((action->'input'->'protocolVersions')::text)`).where(sql`scope = 'document' and \"index\" = 0 and (action->'input'->'protocolVersions') is not null`).execute();\n}\nasync function down$4(db) {\n\tawait db.schema.dropIndex(\"idx_operation_created_protocol_versions\").execute();\n}\n//#endregion\n//#region src/storage/migrations/024_create_document_purges.ts\nvar _024_create_document_purges_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$3,\n\tup: () => up$3\n});\n/** One row per purged document: the tombstone. Written once, never deleted. */\nasync function up$3(db) {\n\tawait db.schema.createTable(\"document_purges\").addColumn(\"documentId\", \"text\", (col) => col.primaryKey()).addColumn(\"ordinal\", \"bigint\", (col) => col.notNull()).addColumn(\"removedRows\", \"jsonb\", (col) => col.notNull()).addColumn(\"purgedAtUtc\", \"timestamptz\", (col) => col.notNull()).addColumn(\"requestId\", \"text\", (col) => col.notNull()).execute();\n}\nasync function down$3(db) {\n\tawait db.schema.dropTable(\"document_purges\").execute();\n}\n//#endregion\n//#region src/storage/migrations/025_create_sync_received_markers.ts\nvar _025_create_sync_received_markers_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$2,\n\tup: () => up$2\n});\n/** Received purge markers awaiting their outcome; removed with their remote. */\nasync function up$2(db) {\n\tawait db.schema.createTable(\"sync_received_markers\").addColumn(\"remote_name\", \"text\", (col) => col.notNull()).addColumn(\"marker_id\", \"text\", (col) => col.notNull()).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"operation\", \"jsonb\", (col) => col.notNull()).addColumn(\"received_at_utc_ms\", \"bigint\", (col) => col.notNull()).addPrimaryKeyConstraint(\"sync_received_markers_pkey\", [\"remote_name\", \"marker_id\"]).execute();\n}\nasync function down$2(db) {\n\tawait db.schema.dropTable(\"sync_received_markers\").execute();\n}\n//#endregion\n//#region src/storage/migrations/026_create_sync_purge_refusals.ts\nvar _026_create_sync_purge_refusals_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down$1,\n\tup: () => up$1\n});\n/** A remote's refusal of a purge marker; payload-free, kept like the tombstone. */\nasync function up$1(db) {\n\tawait db.schema.createTable(\"sync_purge_refusals\").addColumn(\"remote_name\", \"text\", (col) => col.notNull()).addColumn(\"document_id\", \"text\", (col) => col.notNull()).addColumn(\"branch\", \"text\", (col) => col.notNull()).addColumn(\"refused_at_utc_ms\", \"bigint\", (col) => col.notNull()).addPrimaryKeyConstraint(\"sync_purge_refusals_pkey\", [\n\t\t\"remote_name\",\n\t\t\"document_id\",\n\t\t\"branch\"\n\t]).execute();\n\tawait db.schema.createIndex(\"idx_sync_purge_refusals_document\").on(\"sync_purge_refusals\").column(\"document_id\").execute();\n}\nasync function down$1(db) {\n\tawait db.schema.dropTable(\"sync_purge_refusals\").execute();\n}\n//#endregion\n//#region src/storage/migrations/027_add_sync_remote_persistence.ts\nvar _027_add_sync_remote_persistence_exports = /* @__PURE__ */ __exportAll({\n\tdown: () => down,\n\tup: () => up\n});\n/** A session remote's row exists so its cursors, holds and dead letters have a parent. */\nasync function up(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").addColumn(\"persistence\", \"text\", (col) => col.notNull().defaultTo(\"durable\")).execute();\n}\nasync function down(db) {\n\tawait db.schema.alterTable(\"sync_remotes\").dropColumn(\"persistence\").execute();\n}\n//#endregion\n//#region src/storage/migrations/migrator.ts\nconst REACTOR_SCHEMA = \"reactor\";\nconst migrations = {\n\t\"001_create_operation_table\": _001_create_operation_table_exports,\n\t\"002_create_keyframe_table\": _002_create_keyframe_table_exports,\n\t\"003_create_document_table\": _003_create_document_table_exports,\n\t\"004_create_document_relationship_table\": _004_create_document_relationship_table_exports,\n\t\"005_create_indexer_state_table\": _005_create_indexer_state_table_exports,\n\t\"006_create_document_snapshot_table\": _006_create_document_snapshot_table_exports,\n\t\"007_create_slug_mapping_table\": _007_create_slug_mapping_table_exports,\n\t\"008_create_view_state_table\": _008_create_view_state_table_exports,\n\t\"009_create_operation_index_tables\": _009_create_operation_index_tables_exports,\n\t\"010_create_sync_tables\": _010_create_sync_tables_exports,\n\t\"011_add_cursor_type_column\": _011_add_cursor_type_column_exports,\n\t\"012_add_source_remote_column\": _012_add_source_remote_column_exports,\n\t\"013_create_sync_dead_letters_table\": _013_create_sync_dead_letters_table_exports,\n\t\"014_create_processor_cursor_table\": _014_create_processor_cursor_table_exports,\n\t\"015_add_operation_denied_reason\": _015_add_operation_denied_reason_exports,\n\t\"016_add_dead_letter_error_type\": _016_add_dead_letter_error_type_exports,\n\t\"017_create_group_references\": _017_create_group_references_exports,\n\t\"018_add_sync_remote_bound_address\": _018_add_sync_remote_bound_address_exports,\n\t\"019_require_action_id\": _019_require_action_id_exports,\n\t\"020_add_snapshot_operation_ordinal\": _020_add_snapshot_operation_ordinal_exports,\n\t\"021_add_sync_remote_peer\": _021_add_sync_remote_peer_exports,\n\t\"022_create_sync_holds\": _022_create_sync_holds_exports,\n\t\"023_index_created_protocol_versions\": _023_index_created_protocol_versions_exports,\n\t\"024_create_document_purges\": _024_create_document_purges_exports,\n\t\"025_create_sync_received_markers\": _025_create_sync_received_markers_exports,\n\t\"026_create_sync_purge_refusals\": _026_create_sync_purge_refusals_exports,\n\t\"027_add_sync_remote_persistence\": _027_add_sync_remote_persistence_exports\n};\nvar ProgrammaticMigrationProvider = class {\n\tgetMigrations() {\n\t\treturn Promise.resolve(migrations);\n\t}\n};\n/**\n* Applies every pending migration, or every one up to and including `upTo`.\n*\n* The bound exists so a test can reach the schema a data migration is written\n* against, populate it, and then migrate across the migration under test.\n*/\nasync function runMigrations(db, schema = REACTOR_SCHEMA, upTo) {\n\ttry {\n\t\tawait sql`CREATE SCHEMA IF NOT EXISTS ${sql.id(schema)}`.execute(db);\n\t} catch (error) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmigrationsExecuted: [],\n\t\t\terror: error instanceof Error ? error : /* @__PURE__ */ new Error(\"Failed to create schema\")\n\t\t};\n\t}\n\tconst migrator = new Migrator({\n\t\tdb: db.withSchema(schema),\n\t\tprovider: new ProgrammaticMigrationProvider(),\n\t\tmigrationTableSchema: schema\n\t});\n\tlet error;\n\tlet results;\n\ttry {\n\t\tconst result = upTo ? await migrator.migrateTo(upTo) : await migrator.migrateToLatest();\n\t\terror = result.error;\n\t\tresults = result.results;\n\t} catch (e) {\n\t\terror = e;\n\t\tresults = [];\n\t}\n\tconst migrationsExecuted = results?.map((result) => result.migrationName) ?? [];\n\tif (error) return {\n\t\tsuccess: false,\n\t\tmigrationsExecuted,\n\t\terror: error instanceof Error ? error : /* @__PURE__ */ new Error(\"Unknown migration error\")\n\t};\n\treturn {\n\t\tsuccess: true,\n\t\tmigrationsExecuted\n\t};\n}\nasync function getMigrationStatus(db, schema = REACTOR_SCHEMA) {\n\treturn await new Migrator({\n\t\tdb: db.withSchema(schema),\n\t\tprovider: new ProgrammaticMigrationProvider(),\n\t\tmigrationTableSchema: schema\n\t}).getMigrations();\n}\n//#endregion\n//#region src/executor/worker/error-info.ts\nconst MAX_STACK_LENGTH = 8192;\nconst MAX_CAUSE_DEPTH = 8;\nfunction toErrorInfo(err, depth = 0) {\n\tif (depth > MAX_CAUSE_DEPTH) return {\n\t\tname: \"Error\",\n\t\tmessage: \"cause chain truncated\"\n\t};\n\tif (err instanceof Error) {\n\t\tconst info = {\n\t\t\tname: err.name || \"Error\",\n\t\t\tmessage: err.message\n\t\t};\n\t\tif (typeof err.stack === \"string\") info.stack = err.stack.length > MAX_STACK_LENGTH ? err.stack.slice(0, MAX_STACK_LENGTH) : err.stack;\n\t\tif (err.cause !== void 0) info.cause = toErrorInfo(err.cause, depth + 1);\n\t\tconst documentId = err.documentId;\n\t\tif (typeof documentId === \"string\") info.documentId = documentId;\n\t\tconst { documentType, requestedVersion } = err;\n\t\tif (typeof documentType === \"string\") info.documentType = documentType;\n\t\tif (typeof requestedVersion === \"number\") info.requestedVersion = requestedVersion;\n\t\treturn info;\n\t}\n\tif (typeof err === \"string\") return {\n\t\tname: \"Error\",\n\t\tmessage: err\n\t};\n\tif (err && typeof err === \"object\") {\n\t\tconst record = err;\n\t\treturn {\n\t\t\tname: typeof record.name === \"string\" ? record.name : \"Error\",\n\t\t\tmessage: typeof record.message === \"string\" ? record.message : safeStringify(err)\n\t\t};\n\t}\n\treturn {\n\t\tname: \"Error\",\n\t\tmessage: safeStringify(err)\n\t};\n}\nfunction safeStringify(value) {\n\tif (value === null || value === void 0) return String(value);\n\tif (typeof value === \"string\") return value;\n\tif (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\nfunction fromErrorInfo(info) {\n\tconst err = new Error(info.message);\n\tObject.defineProperty(err, \"name\", {\n\t\tvalue: info.name,\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\tif (info.stack !== void 0) err.stack = info.stack;\n\tif (info.documentId !== void 0) Object.defineProperty(err, \"documentId\", {\n\t\tvalue: info.documentId,\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\tfor (const key of [\"documentType\", \"requestedVersion\"]) if (info[key] !== void 0) Object.defineProperty(err, key, {\n\t\tvalue: info[key],\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\tif (info.cause !== void 0) Object.defineProperty(err, \"cause\", {\n\t\tvalue: fromErrorInfo(info.cause),\n\t\tconfigurable: true,\n\t\twritable: true\n\t});\n\treturn err;\n}\n//#endregion\n//#region src/executor/worker/sanitize.ts\nconst MAX_DEPTH = 8;\nfunction errorToInfo(err) {\n\treturn toErrorInfo(err);\n}\nfunction sanitizeArg(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {\n\tif (depth > MAX_DEPTH) return \"[Truncated]\";\n\tif (value === null || value === void 0) return null;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"number\") return value;\n\tif (typeof value === \"string\") return value;\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (typeof value === \"function\" || typeof value === \"symbol\") return null;\n\tif (value instanceof Error) return toErrorInfo(value);\n\tif (value instanceof Date) return value.toISOString();\n\tif (value instanceof Map) {\n\t\tconst obj = {};\n\t\tfor (const [k, v] of value.entries()) obj[String(k)] = sanitizeArg(v, depth + 1, seen);\n\t\treturn obj;\n\t}\n\tif (value instanceof Set) {\n\t\tconst arr = [];\n\t\tfor (const v of value.values()) arr.push(sanitizeArg(v, depth + 1, seen));\n\t\treturn arr;\n\t}\n\tif (Array.isArray(value)) {\n\t\tif (seen.has(value)) return \"[Circular]\";\n\t\tseen.add(value);\n\t\tconst result = value.map((v) => sanitizeArg(v, depth + 1, seen));\n\t\tseen.delete(value);\n\t\treturn result;\n\t}\n\tif (typeof value === \"object\") {\n\t\tconst proto = Object.getPrototypeOf(value);\n\t\tif (proto !== Object.prototype && proto !== null) return { __nonClonable: value.constructor?.name || \"Unknown\" };\n\t\tif (seen.has(value)) return \"[Circular]\";\n\t\tseen.add(value);\n\t\tconst result = {};\n\t\tfor (const [k, v] of Object.entries(value)) result[k] = sanitizeArg(v, depth + 1, seen);\n\t\tseen.delete(value);\n\t\treturn result;\n\t}\n\treturn null;\n}\n//#endregion\n//#region src/executor/worker/forwarding-logger.ts\nfunction createForwardingLogger(post, level = \"info\", tags = []) {\n\tfunction safePost(msg) {\n\t\ttry {\n\t\t\tpost(msg);\n\t\t} catch {\n\t\t\ttry {\n\t\t\t\tprocess.stderr.write(`[forwarding-logger] postMessage failed: ${msg.level} ${msg.message}\\n`);\n\t\t\t} catch {}\n\t\t}\n\t}\n\tfunction emit(wireLevel, message, args) {\n\t\tconst sanitizedArgs = args.map((a) => sanitizeArg(a));\n\t\tsafePost({\n\t\t\ttype: \"log\",\n\t\t\tlevel: wireLevel,\n\t\t\tmessage,\n\t\t\targs: tags.length > 0 ? [sanitizeArg({ tags }), ...sanitizedArgs] : sanitizedArgs,\n\t\t\ttimestamp: Date.now()\n\t\t});\n\t}\n\treturn {\n\t\tlevel,\n\t\tverbose: (message, ...args) => emit(\"debug\", message, args),\n\t\tdebug: (message, ...args) => emit(\"debug\", message, args),\n\t\tinfo: (message, ...args) => emit(\"info\", message, args),\n\t\twarn: (message, ...args) => emit(\"warn\", message, args),\n\t\terror: (message, ...args) => emit(\"error\", message, args),\n\t\terrorHandler: ((...data) => {\n\t\t\tconst first = data[0];\n\t\t\temit(\"error\", typeof first === \"string\" ? first : \"\", data.slice(1));\n\t\t}),\n\t\tchild: (childTags) => createForwardingLogger(post, level, [...tags, ...childTags])\n\t};\n}\n//#endregion\nexport { DocumentExistence as $, GATED_DOCUMENT_ACTIONS as A, yieldToMain as At, createOperation as B, describeWaitingSessions as C, ReactorEventTypes as Ct, CollectionMembershipCache as D, parsePagingOptions as Dt, DocumentMetaCache as E, matchesScope as Et, buildErrorResult as F, relationshipTarget as G, isGenesisOperation as H, buildSuccessResult as I, targetDocumentId as J, submittedActionIds as K, createConsistencyToken as L, TouchedStreams as M, applyDeleteDocumentAction$1 as N, DOCUMENT_SCOPE_ACTIONS as O, throwIfAborted as Ot, applyUpgradeDocumentAction$1 as P, DocumentAlreadyExistsError as Q, createDocumentFromAction as R, createKyselyWatermarkProbe as S, EventBusAggregateError as St, snapshotFunctionsFor as T, delay as Tt, jobWriteIds as U, getNextIndexForScope as V, refusalError as W, APPEND_CONDITION_FAILED_PREFIX as X, updateDocumentRevision as Y, AppendConditionFailedError as Z, acquirePurgeLocks as _, RelationshipNotFoundError as _t, REACTOR_SCHEMA as a, AuthorizationDeniedError as at, ProbeSettler as b, UnsupportedStoredProtocolError as bt, createForwardingPoolInstrumentation as c, DocumentNotDeletedError as ct, KyselyKeyframeStore as d, ExcessiveReshuffleError as dt, DuplicateOperationError as et, EventBus as f, GroupInUseError as ft, PURGE_NS as g, PurgeTooLargeError as gt, PURGE_LOCK_BUCKETS as h, JOB_NOT_FOUND_ERROR_NAME as ht, fromErrorInfo as i, AuthTimestampNotMonotonicError as it, PurgeFence as j, __exportAll as jt, FencedWriteCache as k, withDeadline as kt, instrumentPgPool as l, DocumentNotFoundError as lt, KyselyOperationIndex as m, InvalidSignatureError as mt, errorToInfo as n, RevisionMismatchError as nt, getMigrationStatus as o, BatchJobFailedError as ot, KyselyWriteCache as p, InvalidOperationTimestampError as pt, summarizeSubmittedActions as q, sanitizeArg as r, AuthEnforcementDisabledError as rt, runMigrations as s, DocumentDeletedError as st, createForwardingLogger as t, OptimisticLockError as tt, KyselyOperationStore as u, DocumentPurgedError as ut, findPurged as v, ReservedActionError as vt, parseSnapshot as w, TIMED_OUT as wt, SettledWatermark as x, UpgradePreconditionFailedError as xt, listPurged as y, UnsupportedProtocolVersionError as yt, createEmptyConsistencyToken as z };\n\n//# sourceMappingURL=forwarding-logger-B9LLXItm.js.map","import type { Operation } from \"@powerhousedao/shared/document-model\";\nimport type { AtomicTxn } from \"@powerhousedao/reactor\";\nimport type { StoredOperation } from \"./types.js\";\n\nexport class HypercoreAtomicTransaction implements AtomicTxn {\n private operations: StoredOperation[] = [];\n\n constructor(\n private documentId: string,\n private documentType: string,\n private scope: string,\n private branch: string,\n ) {}\n\n addOperations(...operations: Operation[]): void {\n for (const op of operations) {\n this.operations.push({\n ...op,\n documentId: this.documentId,\n documentType: this.documentType,\n scope: this.scope,\n branch: this.branch,\n });\n }\n }\n\n getOperations(): StoredOperation[] {\n return this.operations;\n }\n}\n","import type { StoredOperation } from \"./types.js\";\n\nconst PAD_WIDTH = 10;\n\nexport const RANGE_UPPER_BOUND = \"9\".repeat(PAD_WIDTH) + \"~\";\n\nexport function pad(n: number): string {\n return n.toString().padStart(PAD_WIDTH, \"0\");\n}\n\nexport function operationKey(\n documentId: string,\n scope: string,\n branch: string,\n index: number,\n): string {\n return `op/${documentId}/${scope}/${branch}/${pad(index)}`;\n}\n\nexport function operationPrefix(\n documentId: string,\n scope: string,\n branch: string,\n): string {\n return `op/${documentId}/${scope}/${branch}/`;\n}\n\nexport function ordinalKey(ordinal: number): string {\n return `ord/${pad(ordinal)}`;\n}\n\nexport function ordinalPrefix(): string {\n return \"ord/\";\n}\n\nexport function duplicateKey(\n opId: string,\n index: number,\n skip: number,\n): string {\n return `dup/${opId}/${pad(index)}/${pad(skip)}`;\n}\n\nexport function headKey(\n documentId: string,\n scope: string,\n branch: string,\n): string {\n return `_meta/head/${documentId}/${scope}/${branch}`;\n}\n\nexport function headPrefix(documentId: string): string {\n return `_meta/head/${documentId}/`;\n}\n\nexport const ORDINAL_COUNTER_KEY = \"_meta/ordinal\";\n\nexport type ParsedOperationKey = {\n documentId: string;\n scope: string;\n branch: string;\n index: number;\n};\n\nexport function parseOperationKey(key: string): ParsedOperationKey {\n const parts = key.split(\"/\");\n return {\n documentId: parts[1],\n scope: parts[2],\n branch: parts[3],\n index: parseInt(parts[4], 10),\n };\n}\n\nexport type OrdinalEntry = {\n documentId: string;\n documentType: string;\n scope: string;\n branch: string;\n index: number;\n operation: StoredOperation;\n};\n\nexport type HeadEntryValue = {\n index: number;\n latestTimestampUtcMs: string;\n};\n","import {\n isPurgeMarker,\n type Operation,\n type OperationWithContext,\n} from \"@powerhousedao/shared/document-model\";\nimport type {\n AppendCondition,\n AtomicTxn,\n DocumentRevisions,\n IOperationStore,\n OperationFilter,\n PagedResults,\n PagingOptions,\n} from \"@powerhousedao/reactor\";\nimport {\n AppendConditionFailedError,\n DocumentAlreadyExistsError,\n DocumentPurgedError,\n DuplicateOperationError,\n RevisionMismatchError,\n} from \"@powerhousedao/reactor\";\nimport type Hyperbee from \"hyperbee\";\nimport { HypercoreAtomicTransaction } from \"./hypercore-atomic-transaction.js\";\nimport {\n ORDINAL_COUNTER_KEY,\n RANGE_UPPER_BOUND,\n duplicateKey,\n headKey,\n headPrefix,\n operationKey,\n operationPrefix,\n ordinalKey,\n ordinalPrefix,\n pad,\n} from \"./key-encoding.js\";\nimport type { HeadEntryValue, OrdinalEntry } from \"./key-encoding.js\";\nimport type { StoredOperation } from \"./types.js\";\n\nexport class HypercoreOperationStore implements IOperationStore {\n private applyLock: Promise<void> = Promise.resolve();\n\n constructor(private bee: Hyperbee) {}\n\n async apply(\n documentId: string,\n documentType: string,\n scope: string,\n branch: string,\n revision: number,\n fn: (txn: AtomicTxn) => void | Promise<void>,\n signal?: AbortSignal,\n condition?: AppendCondition,\n ): Promise<Operation[]> {\n const prevLock = this.applyLock;\n let releaseLock: () => void;\n this.applyLock = new Promise<void>((resolve) => {\n releaseLock = resolve;\n });\n\n await prevLock;\n\n try {\n // Single writer on applyLock: nothing can append between check and write.\n if (condition) {\n await this.assertConditionHolds(condition, signal);\n }\n\n return await this.executeApply(\n documentId,\n documentType,\n scope,\n branch,\n revision,\n fn,\n signal,\n );\n } finally {\n releaseLock!();\n }\n }\n\n /** Throws if any read-set stream has grown past its recorded revision. */\n private async assertConditionHolds(\n condition: AppendCondition,\n signal?: AbortSignal,\n ): Promise<void> {\n for (const stream of condition.streams) {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const entry = await this.bee.get(\n headKey(stream.documentId, stream.scope, stream.branch),\n );\n const head = entry ? (entry.value as HeadEntryValue).index : -1;\n\n if (head > stream.revision) {\n throw new AppendConditionFailedError(condition);\n }\n }\n }\n\n private async executeApply(\n documentId: string,\n documentType: string,\n scope: string,\n branch: string,\n revision: number,\n fn: (txn: AtomicTxn) => void | Promise<void>,\n signal?: AbortSignal,\n ): Promise<Operation[]> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const hKey = headKey(documentId, scope, branch);\n const headEntry = await this.bee.get(hKey);\n const currentRevision = headEntry\n ? (headEntry.value as HeadEntryValue).index\n : -1;\n\n const atomicTxn = new HypercoreAtomicTransaction(\n documentId,\n documentType,\n scope,\n branch,\n );\n await fn(atomicTxn);\n\n const operations = atomicTxn.getOperations();\n\n // No delete path here: a stream purged elsewhere ends in its marker.\n const marker = await this.purgeMarkerAtHead(documentId);\n if (marker !== undefined && operations.length > 0) {\n if (!operations.every((op) => isPurgeMarker(op))) {\n throw new DocumentPurgedError(documentId);\n }\n return [marker];\n }\n\n if (currentRevision !== revision - 1) {\n if (revision === 0 && this.isCreate(operations)) {\n throw new DocumentAlreadyExistsError(\n documentId,\n scope,\n currentRevision,\n );\n }\n\n throw new RevisionMismatchError(currentRevision + 1, revision);\n }\n\n if (operations.length === 0) {\n return [];\n }\n\n for (const op of operations) {\n const dupKey = duplicateKey(op.id, op.index, op.skip);\n const existing = await this.bee.get(dupKey);\n if (existing) {\n throw new DuplicateOperationError(\n `${op.id} at index ${op.index} with skip ${op.skip}`,\n );\n }\n }\n\n const ordinalEntry = await this.bee.get(ORDINAL_COUNTER_KEY);\n let nextOrdinal: number = ordinalEntry ? (ordinalEntry.value as number) : 0;\n\n const batch = this.bee.batch();\n\n for (const op of operations) {\n const opKey = operationKey(documentId, scope, branch, op.index);\n const serialized = this.serializeOperation(op);\n await batch.put(opKey, serialized);\n\n const ordEntry: OrdinalEntry = {\n documentId,\n documentType,\n scope,\n branch,\n index: op.index,\n operation: serialized,\n };\n await batch.put(ordinalKey(nextOrdinal), ordEntry);\n\n await batch.put(duplicateKey(op.id, op.index, op.skip), \"\");\n\n nextOrdinal++;\n }\n\n const lastOp = operations[operations.length - 1];\n const headValue: HeadEntryValue = {\n index: lastOp.index,\n latestTimestampUtcMs: lastOp.timestampUtcMs,\n };\n await batch.put(hKey, headValue);\n await batch.put(ORDINAL_COUNTER_KEY, nextOrdinal);\n\n await batch.flush();\n\n return operations.map((op) => this.toOperation(op));\n }\n\n /** A purge marker is written to document/main whichever branch it erases. */\n private async purgeMarkerAtHead(\n documentId: string,\n ): Promise<Operation | undefined> {\n const branch = \"main\";\n const head = await this.bee.get(headKey(documentId, \"document\", branch));\n if (!head) {\n return undefined;\n }\n const index = (head.value as HeadEntryValue).index;\n const entry = await this.bee.get(\n operationKey(documentId, \"document\", branch, index),\n );\n const stored = entry?.value as StoredOperation | undefined;\n return stored && isPurgeMarker(stored)\n ? this.toOperation(stored)\n : undefined;\n }\n\n private isCreate(operations: StoredOperation[]): boolean {\n return operations.some((op) => op.action.type === \"CREATE_DOCUMENT\");\n }\n\n /**\n * The paging cursor encodes the index to resume from (one past the last\n * row returned), not the last row's own index; \"\" or \"0\" (or anything\n * unparsable) means the start of the stream. This keeps \"0\" an unambiguous\n * start-of-stream sentinel even when a page ends at index 0, which would\n * otherwise make `nextCursor` equal the start cursor and loop a caller that\n * walks pages forever. Mirrors the encoding in the Kysely store.\n */\n async getSince(\n documentId: string,\n scope: string,\n branch: string,\n revision: number,\n filter?: OperationFilter,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Operation>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const prefix = operationPrefix(documentId, scope, branch);\n const startIndex = revision + 1;\n const parsedCursor = paging?.cursor\n ? Number.parseInt(paging.cursor, 10)\n : NaN;\n const cursorIndex =\n Number.isFinite(parsedCursor) && parsedCursor > 0\n ? parsedCursor\n : startIndex;\n const effectiveStart = Math.max(startIndex, cursorIndex);\n\n const gt = prefix + pad(effectiveStart - 1);\n const lt = prefix + RANGE_UPPER_BOUND;\n const limit = paging?.limit ? paging.limit + 1 : undefined;\n\n const items: Operation[] = [];\n const stream = this.bee.createReadStream({ gt, lt, limit });\n\n for await (const entry of stream) {\n const stored = entry.value as StoredOperation;\n\n if (filter) {\n if (\n filter.actionTypes &&\n filter.actionTypes.length > 0 &&\n !filter.actionTypes.includes((stored.action as { type: string }).type)\n ) {\n continue;\n }\n if (\n filter.timestampFrom &&\n stored.timestampUtcMs < filter.timestampFrom\n ) {\n continue;\n }\n if (filter.timestampTo && stored.timestampUtcMs > filter.timestampTo) {\n continue;\n }\n if (\n filter.sinceRevision !== undefined &&\n stored.index < filter.sinceRevision\n ) {\n continue;\n }\n }\n\n items.push(this.toOperation(stored));\n }\n\n let hasMore = false;\n let resultItems = items;\n\n if (paging?.limit && items.length > paging.limit) {\n hasMore = true;\n resultItems = items.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && resultItems.length > 0\n ? (resultItems[resultItems.length - 1].index + 1).toString()\n : undefined;\n\n const cursor = paging?.cursor || \"0\";\n const resultLimit = paging?.limit || 100;\n\n return {\n results: resultItems,\n options: { cursor, limit: resultLimit },\n nextCursor,\n next: hasMore\n ? () =>\n this.getSince(\n documentId,\n scope,\n branch,\n revision,\n filter,\n { cursor: nextCursor!, limit: resultLimit },\n signal,\n )\n : undefined,\n };\n }\n\n /**\n * The paging cursor encodes the ordinal to resume from (one past the last\n * ordinal returned), not the last ordinal itself; \"\" or \"0\" (or anything\n * unparsable) means the start of the stream. Unlike the Kysely store's\n * `getSinceId` (whose auto-increment id starts at 1), this store's ordinal\n * counter starts at 0, so 0 is a real, valid ordinal and the same\n * ambiguous-cursor hazard as `getSince`/`getConflicting` applies here too.\n */\n async getSinceId(\n id: number,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationWithContext>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const startId = id + 1;\n const parsedCursor = paging?.cursor\n ? Number.parseInt(paging.cursor, 10)\n : NaN;\n const cursorId =\n Number.isFinite(parsedCursor) && parsedCursor > 0\n ? parsedCursor\n : startId;\n const effectiveStart = Math.max(startId, cursorId);\n\n const gt = ordinalPrefix() + pad(effectiveStart - 1);\n const lt = ordinalPrefix() + RANGE_UPPER_BOUND;\n const limit = paging?.limit ? paging.limit + 1 : undefined;\n\n const items: OperationWithContext[] = [];\n const stream = this.bee.createReadStream({ gt, lt, limit });\n\n for await (const entry of stream) {\n const ordEntry = entry.value as OrdinalEntry;\n const ordinal = parseInt(entry.key.split(\"/\")[1], 10);\n\n items.push({\n operation: this.toOperation(ordEntry.operation),\n context: {\n documentId: ordEntry.documentId,\n documentType: ordEntry.documentType,\n scope: ordEntry.scope,\n branch: ordEntry.branch,\n ordinal,\n },\n });\n }\n\n let hasMore = false;\n let resultItems = items;\n\n if (paging?.limit && items.length > paging.limit) {\n hasMore = true;\n resultItems = items.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && resultItems.length > 0\n ? (resultItems[resultItems.length - 1].context.ordinal + 1).toString()\n : undefined;\n\n const cursor = paging?.cursor || \"0\";\n const resultLimit = paging?.limit || 100;\n\n return {\n results: resultItems,\n options: { cursor, limit: resultLimit },\n nextCursor,\n next: hasMore\n ? () =>\n this.getSinceId(\n id,\n { cursor: nextCursor!, limit: resultLimit },\n signal,\n )\n : undefined,\n };\n }\n\n /**\n * The paging cursor here encodes the index to resume from (one past the\n * last row returned), not the last row's own index, for the same reason as\n * `getSince`: a page ending at index 0 must not produce a cursor that is\n * indistinguishable from the start-of-stream sentinel.\n */\n async getConflicting(\n documentId: string,\n scope: string,\n branch: string,\n minTimestamp: string,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Operation>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const prefix = operationPrefix(documentId, scope, branch);\n const parsedCursor = paging?.cursor\n ? Number.parseInt(paging.cursor, 10)\n : NaN;\n const cursorIndex =\n Number.isFinite(parsedCursor) && parsedCursor > 0 ? parsedCursor : -1;\n\n const gte = cursorIndex >= 0 ? prefix + pad(cursorIndex) : prefix;\n const lt = prefix + RANGE_UPPER_BOUND;\n\n const stream = this.bee.createReadStream({ gte, lt });\n\n // One row past the page is all this needs: it proves a next page exists\n // and is dropped again below. The limit cannot be pushed down into\n // createReadStream, because minTimestamp is applied per entry as it is\n // read -- a raw range limit would stop short while matching operations\n // still lay further along the range.\n const readLimit = paging?.limit ? paging.limit + 1 : undefined;\n\n const items: Operation[] = [];\n\n for await (const entry of stream) {\n const stored = entry.value as StoredOperation;\n if (stored.timestampUtcMs >= minTimestamp) {\n items.push(this.toOperation(stored));\n // Every operation of a document shares one key prefix, so without\n // this the range walk drains the whole document to hand back a\n // single page. Breaking closes the stream: for-await calls the\n // iterator's return() on the way out.\n if (readLimit !== undefined && items.length >= readLimit) break;\n }\n }\n\n let hasMore = false;\n let resultItems = items;\n\n if (paging?.limit && items.length > paging.limit) {\n hasMore = true;\n resultItems = items.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && resultItems.length > 0\n ? (resultItems[resultItems.length - 1].index + 1).toString()\n : undefined;\n\n const cursor = paging?.cursor || \"0\";\n const resultLimit = paging?.limit || 100;\n\n return {\n results: resultItems,\n options: { cursor, limit: resultLimit },\n nextCursor,\n next: hasMore\n ? () =>\n this.getConflicting(\n documentId,\n scope,\n branch,\n minTimestamp,\n { cursor: nextCursor!, limit: resultLimit },\n signal,\n )\n : undefined,\n };\n }\n\n async getRevisions(\n documentId: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<DocumentRevisions> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const prefix = headPrefix(documentId);\n const stream = this.bee.createReadStream({\n gte: prefix,\n lt: prefix + \"~\",\n });\n\n const revision: Record<string, number> = {};\n let latestTimestamp = new Date(0).toISOString();\n\n for await (const entry of stream) {\n const parts = entry.key.split(\"/\");\n const entryScope = parts[3];\n const entryBranch = parts[4];\n\n if (entryBranch !== branch) {\n continue;\n }\n\n const headValue = entry.value as HeadEntryValue;\n revision[entryScope] = headValue.index + 1;\n\n if (headValue.latestTimestampUtcMs > latestTimestamp) {\n latestTimestamp = headValue.latestTimestampUtcMs;\n }\n }\n\n return { revision, latestTimestamp };\n }\n\n /**\n * A real maximum over the rows, not the head record's `latestTimestampUtcMs`:\n * that holds the last-indexed timestamp, which a re-append can leave behind a\n * later one, so it would under-report and admit a backdated auth write.\n */\n async getStreamLatestTimestamp(\n documentId: string,\n scope: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<string | undefined> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const stored = await this.getSince(\n documentId,\n scope,\n branch,\n -1,\n undefined,\n undefined,\n signal,\n );\n\n let latest: string | undefined;\n for (const operation of stored.results) {\n if (latest === undefined || operation.timestampUtcMs > latest) {\n latest = operation.timestampUtcMs;\n }\n }\n\n return latest;\n }\n\n async findOperationIds(\n documentId: string,\n scope: string,\n branch: string,\n opIds: string[],\n signal?: AbortSignal,\n ): Promise<Set<string>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const found = new Set<string>();\n if (opIds.length === 0) {\n return found;\n }\n\n const wanted = new Set(opIds);\n const stored = await this.getSince(\n documentId,\n scope,\n branch,\n -1,\n undefined,\n undefined,\n signal,\n );\n for (const operation of stored.results) {\n if (wanted.has(operation.id)) {\n found.add(operation.id);\n }\n }\n\n return found;\n }\n\n async getOperationsByIds(\n documentId: string,\n scope: string,\n branch: string,\n opIds: string[],\n signal?: AbortSignal,\n ): Promise<Operation[]> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n if (opIds.length === 0) {\n return [];\n }\n\n const wanted = new Set(opIds);\n const stored = await this.getSince(\n documentId,\n scope,\n branch,\n -1,\n undefined,\n undefined,\n signal,\n );\n const latest = new Map<string, Operation>();\n for (const operation of stored.results) {\n if (wanted.has(operation.id)) {\n latest.set(operation.id, operation);\n }\n }\n return [...latest.values()];\n }\n\n private serializeOperation(op: StoredOperation): StoredOperation {\n return {\n id: op.id,\n index: op.index,\n skip: op.skip,\n timestampUtcMs: op.timestampUtcMs,\n hash: op.hash,\n error: op.error,\n deniedReason: op.deniedReason,\n action: op.action,\n documentId: op.documentId,\n documentType: op.documentType,\n scope: op.scope,\n branch: op.branch,\n };\n }\n\n private toOperation(stored: StoredOperation): Operation {\n return {\n id: stored.id,\n index: stored.index,\n skip: stored.skip,\n timestampUtcMs: stored.timestampUtcMs,\n hash: stored.hash,\n error: stored.error || undefined,\n deniedReason: stored.deniedReason || undefined,\n action: stored.action,\n };\n }\n}\n","import Corestore from \"corestore\";\nimport Hyperbee from \"hyperbee\";\n\nexport class StorageManager {\n private store: Corestore;\n private bee: Hyperbee | undefined;\n\n constructor(storagePath: string) {\n this.store = new Corestore(storagePath);\n }\n\n async open(): Promise<void> {\n await this.store.ready();\n const core = this.store.get({ name: \"operations\" });\n this.bee = new Hyperbee(core, {\n keyEncoding: \"utf-8\",\n valueEncoding: \"json\",\n });\n await this.bee.ready();\n }\n\n async close(): Promise<void> {\n if (this.bee) {\n await this.bee.close();\n }\n await this.store.close();\n }\n\n getBee(): Hyperbee {\n if (!this.bee) {\n throw new Error(\"StorageManager not opened. Call open() first.\");\n }\n return this.bee;\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/reactor-hypercore",
3
- "version": "6.2.3-dev.50",
3
+ "version": "6.2.3-dev.51",
4
4
  "description": "Hypercore-backed IOperationStore for the Powerhouse Reactor",
5
5
  "repository": {
6
6
  "url": "https://github.com/powerhouse-inc/powerhouse",
@@ -27,17 +27,17 @@
27
27
  "dependencies": {
28
28
  "corestore": "^6.18.4",
29
29
  "hyperbee": "^2.21.0",
30
- "@powerhousedao/shared": "6.2.3-dev.50"
30
+ "@powerhousedao/shared": "6.2.3-dev.51"
31
31
  },
32
32
  "devDependencies": {
33
- "document-model": "6.2.3-dev.50",
34
- "@powerhousedao/reactor": "6.2.3-dev.50",
33
+ "document-model": "6.2.3-dev.51",
34
+ "@powerhousedao/reactor": "6.2.3-dev.51",
35
35
  "tsdown": "0.23.0",
36
36
  "vitest": "5.0.3",
37
37
  "tsx": "4.23.13"
38
38
  },
39
39
  "peerDependencies": {
40
- "document-model": "6.2.3-dev.50"
40
+ "document-model": "6.2.3-dev.51"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "tsdown",