@powerhousedao/reactor 6.1.0-dev.4 → 6.1.0-dev.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/build-worker-executor-DDVXB921.js +83 -0
  2. package/dist/build-worker-executor-DDVXB921.js.map +1 -0
  3. package/dist/document-indexer-B2iLRB0o.js +917 -0
  4. package/dist/document-indexer-B2iLRB0o.js.map +1 -0
  5. package/dist/drive-container-types-BNpMlgT_.js +2964 -0
  6. package/dist/drive-container-types-BNpMlgT_.js.map +1 -0
  7. package/dist/entry.d.ts +1 -0
  8. package/dist/entry.js +313 -0
  9. package/dist/entry.js.map +1 -0
  10. package/dist/error-info-Cpu4OY3o.js +62 -0
  11. package/dist/error-info-Cpu4OY3o.js.map +1 -0
  12. package/dist/errors-D3S6Eysd.js +56 -0
  13. package/dist/errors-D3S6Eysd.js.map +1 -0
  14. package/dist/forwarding-logger-BBkMSxuJ.js +85 -0
  15. package/dist/forwarding-logger-BBkMSxuJ.js.map +1 -0
  16. package/dist/index.d.ts +990 -75
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +889 -3890
  19. package/dist/index.js.map +1 -1
  20. package/dist/projection-entry.d.ts +1 -0
  21. package/dist/projection-entry.js +406 -0
  22. package/dist/projection-entry.js.map +1 -0
  23. package/dist/projection-shard-manager-_c7orNo5.js +313 -0
  24. package/dist/projection-shard-manager-_c7orNo5.js.map +1 -0
  25. package/dist/projection-worker-wI4PwcV2.js +13 -0
  26. package/dist/projection-worker-wI4PwcV2.js.map +1 -0
  27. package/dist/transport-ByGviWdZ.js +33 -0
  28. package/dist/transport-ByGviWdZ.js.map +1 -0
  29. package/dist/transport-CuogVKN_.js +23 -0
  30. package/dist/transport-CuogVKN_.js.map +1 -0
  31. package/dist/types-CxSpmNGK.js +32 -0
  32. package/dist/types-CxSpmNGK.js.map +1 -0
  33. package/dist/worker-SUoDhurA.js +22 -0
  34. package/dist/worker-SUoDhurA.js.map +1 -0
  35. package/dist/worker-handle-B1w03nRA.js +383 -0
  36. package/dist/worker-handle-B1w03nRA.js.map +1 -0
  37. package/package.json +6 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drive-container-types-BNpMlgT_.js","names":["DowngradeNotSupportedError","DowngradeNotSupportedError","uuidv4","up","up","up","up","up","up","up","up","up","up","up","up","up","migration001","migration002","migration003","migration004","migration005","migration006","migration007","migration008","migration009","migration010","migration011","migration012","migration013","migration014"],"sources":["../src/shared/utils.ts","../src/shared/errors.ts","../src/registry/errors.ts","../src/cache/collection-membership-cache.ts","../src/executor/util.ts","../src/cache/lru/lru-tracker.ts","../src/cache/document-meta-cache.ts","../src/cache/kysely-operation-index.ts","../src/cache/buffer/ring-buffer.ts","../src/cache/kysely-write-cache.ts","../src/events/event-bus.ts","../src/executor/execution-scope.ts","../src/utils/reshuffle.ts","../src/cache/operation-index-types.ts","../src/executor/document-action-handler.ts","../src/executor/signature-verifier.ts","../src/executor/simple-job-executor.ts","../src/registry/implementation.ts","../src/storage/kysely/keyframe-store.ts","../src/storage/kysely/pagination.ts","../src/storage/interfaces.ts","../src/storage/txn.ts","../src/storage/kysely/store.ts","../src/storage/pool-instrumentation.ts","../src/storage/migrations/001_create_operation_table.ts","../src/storage/migrations/002_create_keyframe_table.ts","../src/storage/migrations/003_create_document_table.ts","../src/storage/migrations/004_create_document_relationship_table.ts","../src/storage/migrations/005_create_indexer_state_table.ts","../src/storage/migrations/006_create_document_snapshot_table.ts","../src/storage/migrations/007_create_slug_mapping_table.ts","../src/storage/migrations/008_create_view_state_table.ts","../src/storage/migrations/009_create_operation_index_tables.ts","../src/storage/migrations/010_create_sync_tables.ts","../src/storage/migrations/011_add_cursor_type_column.ts","../src/storage/migrations/012_add_source_remote_column.ts","../src/storage/migrations/013_create_sync_dead_letters_table.ts","../src/storage/migrations/014_create_processor_cursor_table.ts","../src/storage/migrations/migrator.ts","../src/core/drive-container-types.ts"],"sourcesContent":["import type { PagingOptions, ViewFilter } from \"./types.js\";\n\nexport function matchesScope(view: ViewFilter = {}, scope: string): boolean {\n if (view.scopes) {\n return view.scopes.includes(scope);\n }\n\n // if there are no scopes specified, we match all scopes\n return true;\n}\n\nexport function yieldToMain(): Promise<void> {\n const s = (globalThis as Record<string, unknown>).scheduler as\n | { yield?: () => Promise<void> }\n | undefined;\n if (s?.yield) {\n return s.yield();\n }\n return new Promise((resolve) => setTimeout(resolve, 0));\n}\n\nconst defaultAbortError = (): Error => new Error(\"Operation aborted\");\n\nexport function throwIfAborted(\n signal: AbortSignal | undefined,\n makeError: () => Error = defaultAbortError,\n): void {\n if (signal?.aborted) {\n throw makeError();\n }\n}\n\nexport type ParsedPaging = {\n offset: number;\n limit: number;\n};\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 */\nexport function parsePagingOptions(\n paging: PagingOptions | undefined,\n defaultLimit: number,\n): ParsedPaging {\n if (paging === undefined) {\n return { offset: 0, limit: defaultLimit };\n }\n if (!Number.isInteger(paging.limit) || paging.limit < 1) {\n throw new Error(\n `Invalid paging limit: ${String(paging.limit)} (must be an integer >= 1)`,\n );\n }\n if (paging.cursor === \"\") {\n return { offset: 0, limit: paging.limit };\n }\n const parsed = Number(paging.cursor);\n if (!Number.isInteger(parsed) || parsed < 0) {\n throw new Error(\n `Invalid paging cursor: ${JSON.stringify(paging.cursor)} (must be empty or a non-negative integer)`,\n );\n }\n return { offset: parsed, limit: paging.limit };\n}\n","/**\n * Error thrown when attempting to access a deleted document.\n */\nexport class DocumentDeletedError extends Error {\n public readonly documentId: string;\n public readonly deletedAtUtcIso: string | null;\n\n constructor(documentId: string, deletedAtUtcIso: string | null = null) {\n const message = deletedAtUtcIso\n ? `Document ${documentId} was deleted at ${deletedAtUtcIso}`\n : `Document ${documentId} has been deleted`;\n\n super(message);\n this.name = \"DocumentDeletedError\";\n this.documentId = documentId;\n this.deletedAtUtcIso = deletedAtUtcIso;\n\n Error.captureStackTrace(this, DocumentDeletedError);\n }\n\n static isError(error: unknown): error is DocumentDeletedError {\n return Error.isError(error) && error.name === \"DocumentDeletedError\";\n }\n}\n\n/**\n * Error thrown when attempting to add operations before CREATE_DOCUMENT.\n */\nexport class CreateDocumentRequiredError extends Error {\n public readonly documentId: string;\n public readonly scope: string;\n\n constructor(documentId: string, scope: string) {\n const message = `Document ${documentId} requires a CREATE_DOCUMENT operation at revision 0 in the \"document\" scope before operations can be added to scope \"${scope}\"`;\n\n super(message);\n this.name = \"CreateDocumentRequiredError\";\n this.documentId = documentId;\n this.scope = scope;\n\n Error.captureStackTrace(this, CreateDocumentRequiredError);\n }\n}\n\n/**\n * Error thrown when an operation has an invalid signature.\n */\nexport class InvalidSignatureError extends Error {\n public readonly documentId: string;\n public readonly reason: string;\n\n constructor(documentId: string, reason: string) {\n super(`Invalid signature in document ${documentId}: ${reason}`);\n this.name = \"InvalidSignatureError\";\n this.documentId = documentId;\n this.reason = reason;\n\n Error.captureStackTrace(this, InvalidSignatureError);\n }\n}\n\n/**\n * Error thrown when attempting to downgrade a document version.\n */\nexport class DowngradeNotSupportedError extends Error {\n public readonly documentType: string;\n public readonly fromVersion: number;\n public readonly toVersion: number;\n\n constructor(documentType: string, fromVersion: number, toVersion: number) {\n super(\n `Downgrade not supported for ${documentType}: cannot upgrade from version ${fromVersion} to ${toVersion}`,\n );\n this.name = \"DowngradeNotSupportedError\";\n this.documentType = documentType;\n this.fromVersion = fromVersion;\n this.toVersion = toVersion;\n\n Error.captureStackTrace(this, DowngradeNotSupportedError);\n }\n}\n\n/**\n * Error thrown when an upgrade manifest is required but not registered.\n */\nexport class UpgradeManifestNotFoundError extends Error {\n public readonly documentType: string;\n\n constructor(documentType: string) {\n super(`No upgrade manifest registered for document type: ${documentType}`);\n this.name = \"UpgradeManifestNotFoundError\";\n this.documentType = documentType;\n\n Error.captureStackTrace(this, UpgradeManifestNotFoundError);\n }\n}\n\n/**\n * Error thrown when a document is not found (no operations exist for the document ID).\n */\nexport class DocumentNotFoundError extends Error {\n public readonly documentId: string;\n\n constructor(documentId: string) {\n super(`Document ${documentId} not found`);\n this.name = \"DocumentNotFoundError\";\n this.documentId = documentId;\n\n Error.captureStackTrace(this, DocumentNotFoundError);\n }\n\n static isError(error: unknown): error is DocumentNotFoundError {\n return Error.isError(error) && error.name === \"DocumentNotFoundError\";\n }\n}\n","/**\n * Error thrown when a document model module is not found in the registry.\n */\nexport class ModuleNotFoundError extends Error {\n readonly documentType: string;\n readonly requestedVersion: number | undefined;\n\n constructor(documentType: string, version?: number) {\n const versionSuffix = version !== undefined ? ` version ${version}` : \"\";\n super(\n `Document model module not found for type: ${documentType}${versionSuffix}`,\n );\n this.name = \"ModuleNotFoundError\";\n this.documentType = documentType;\n this.requestedVersion = version;\n }\n\n static isError(error: unknown): error is ModuleNotFoundError {\n return Error.isError(error) && error.name === \"ModuleNotFoundError\";\n }\n}\n\n/**\n * Error thrown when attempting to register a module that already exists.\n */\nexport class DuplicateModuleError extends Error {\n constructor(documentType: string, version?: number) {\n const versionSuffix = version !== undefined ? ` (version ${version})` : \"\";\n super(\n `Document model module already registered for type: ${documentType}${versionSuffix}`,\n );\n this.name = \"DuplicateModuleError\";\n }\n\n static isError(error: unknown): error is DuplicateModuleError {\n return Error.isError(error) && error.name === \"DuplicateModuleError\";\n }\n}\n\n/**\n * Error thrown when a module is invalid or malformed.\n */\nexport class InvalidModuleError extends Error {\n constructor(message: string) {\n super(`Invalid document model module: ${message}`);\n this.name = \"InvalidModuleError\";\n }\n}\n\n/**\n * Error thrown when attempting to register an upgrade manifest that already exists.\n */\nexport class DuplicateManifestError extends Error {\n constructor(documentType: string) {\n super(`Upgrade manifest already registered for type: ${documentType}`);\n this.name = \"DuplicateManifestError\";\n }\n\n static isError(error: unknown): error is DuplicateManifestError {\n return Error.isError(error) && error.name === \"DuplicateManifestError\";\n }\n}\n\n/**\n * Error thrown when an upgrade manifest is not found.\n */\nexport class ManifestNotFoundError extends Error {\n constructor(documentType: string) {\n super(`Upgrade manifest not found for type: ${documentType}`);\n this.name = \"ManifestNotFoundError\";\n }\n}\n\n/**\n * Error thrown when attempting a downgrade operation.\n */\nexport class DowngradeNotSupportedError extends Error {\n constructor(documentType: string, fromVersion: number, toVersion: number) {\n super(\n `Downgrade not supported for ${documentType}: cannot go from version ${fromVersion} to ${toVersion}`,\n );\n this.name = \"DowngradeNotSupportedError\";\n }\n}\n\n/**\n * Error thrown when a required upgrade transition is missing from the manifest.\n */\nexport class MissingUpgradeTransitionError extends Error {\n constructor(documentType: string, fromVersion: number, toVersion: number) {\n super(\n `Missing upgrade transition for ${documentType}: v${fromVersion} to v${toVersion}`,\n );\n this.name = \"MissingUpgradeTransitionError\";\n }\n}\n\n/**\n * Error thrown when getUpgradeReducer is called with a non-single-step version increment.\n */\nexport class InvalidUpgradeStepError extends Error {\n constructor(documentType: string, fromVersion: number, toVersion: number) {\n super(\n `Invalid upgrade step for ${documentType}: must be single version increment, got v${fromVersion} to v${toVersion}`,\n );\n this.name = \"InvalidUpgradeStepError\";\n }\n}\n","import type { IOperationIndex } from \"./operation-index-types.js\";\n\nexport interface ICollectionMembershipCache {\n // Get collections for documents (lazy load from index if not cached)\n getCollectionsForDocuments(\n documentIds: string[],\n ): Promise<Record<string, string[]>>;\n\n // Invalidate a document's cache entry (when membership changes)\n invalidate(documentId: string): void;\n}\n\nexport class CollectionMembershipCache implements ICollectionMembershipCache {\n private cache: Map<string, string[]> = new Map();\n\n constructor(private operationIndex: IOperationIndex) {}\n\n withScopedIndex(operationIndex: IOperationIndex): CollectionMembershipCache {\n const scoped = new CollectionMembershipCache(operationIndex);\n scoped.cache = this.cache;\n return scoped;\n }\n\n async getCollectionsForDocuments(\n documentIds: string[],\n ): Promise<Record<string, string[]>> {\n const result: Record<string, string[]> = {};\n const missing: string[] = [];\n\n for (const docId of documentIds) {\n const cached = this.cache.get(docId);\n if (cached !== undefined) {\n result[docId] = cached;\n } else {\n missing.push(docId);\n }\n }\n\n if (missing.length > 0) {\n const fromDb =\n await this.operationIndex.getCollectionsForDocuments(missing);\n for (const docId of missing) {\n const collections = fromDb[docId] ?? [];\n result[docId] = collections;\n this.cache.set(docId, collections);\n }\n }\n\n return result;\n }\n\n invalidate(documentId: string): void {\n this.cache.delete(documentId);\n }\n}\n","import type { OperationWithContext } from \"@powerhousedao/shared/document-model\";\nimport type {\n Action,\n CreateDocumentAction,\n CreateDocumentActionInput,\n DeleteDocumentAction,\n Operation,\n PHDocument,\n UpgradeDocumentAction,\n UpgradeTransition,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n createPresignedHeader,\n defaultBaseState,\n deriveOperationId,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Job } from \"../queue/types.js\";\nimport { DowngradeNotSupportedError } from \"../shared/errors.js\";\nimport type {\n ConsistencyCoordinate,\n ConsistencyToken,\n} from \"../shared/types.js\";\nimport type { JobResult } from \"./types.js\";\n\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 */\nexport function createDocumentFromAction(\n action: CreateDocumentAction,\n): PHDocument {\n const input = action.input as CreateDocumentActionInput;\n\n // Reconstruct the document from CreateDocumentActionInput\n const header = createPresignedHeader();\n header.id = input.documentId;\n header.documentType = input.model;\n\n // If signing info is present, populate the header signature fields\n if (input.signing) {\n header.createdAtUtcIso = input.signing.createdAtUtcIso;\n header.lastModifiedAtUtcIso = input.signing.createdAtUtcIso;\n header.sig = {\n publicKey: input.signing.publicKey,\n nonce: input.signing.nonce,\n };\n }\n\n // Populate optional mutable header fields\n if (input.slug !== undefined) {\n header.slug = input.slug;\n }\n // Default slug to document ID if empty (matching legacy behavior)\n if (!header.slug) {\n header.slug = input.documentId;\n }\n if (input.name !== undefined) {\n header.name = input.name;\n }\n if (input.branch !== undefined) {\n header.branch = input.branch;\n }\n if (input.meta !== undefined) {\n header.meta = input.meta;\n }\n if (input.protocolVersions !== undefined) {\n header.protocolVersions = input.protocolVersions;\n }\n\n // Construct the document with default base state (UPGRADE_DOCUMENT will set the full state)\n const baseState = defaultBaseState();\n const document: PHDocument = {\n header,\n operations: {},\n state: baseState,\n initialState: baseState,\n clipboard: [],\n };\n\n return document;\n}\n\n/**\n * Applies an UPGRADE_DOCUMENT action to a document.\n * Handles all upgrade scenarios including initial upgrades, no-ops, and multi-step upgrades.\n *\n * Behavior based on fromVersion/toVersion:\n * - fromVersion === toVersion (and fromVersion > 0): No-op - return unchanged document\n * - fromVersion > toVersion: Throw DowngradeNotSupportedError\n * - All other cases: Apply upgradePath transitions (if provided), then apply initialState, set version\n *\n * The initialState from the action is always applied (if provided) to maintain backward\n * compatibility with the original implementation.\n *\n * @param document - The document to upgrade\n * @param action - The UPGRADE_DOCUMENT action\n * @param upgradePath - Optional pre-computed upgrade path for multi-step upgrades\n * @returns The upgraded document (unchanged if no-op)\n * @throws DowngradeNotSupportedError if attempting to downgrade\n */\nexport function applyUpgradeDocumentAction(\n document: PHDocument,\n action: UpgradeDocumentAction,\n upgradePath?: UpgradeTransition[],\n): PHDocument {\n const fromVersion = action.input.fromVersion;\n const toVersion = action.input.toVersion;\n\n if (fromVersion === toVersion && fromVersion > 0) {\n return document;\n }\n\n if (fromVersion > toVersion) {\n throw new DowngradeNotSupportedError(\n document.header.documentType,\n fromVersion,\n toVersion,\n );\n }\n\n if (upgradePath) {\n for (const transition of upgradePath) {\n document = transition.upgradeReducer(document, action);\n }\n }\n\n applyInitialState(document, action);\n\n document.state.document = {\n ...document.state.document,\n version: toVersion,\n };\n return document;\n}\n\nfunction applyInitialState(\n document: PHDocument,\n action: UpgradeDocumentAction,\n): void {\n const input = action.input as {\n initialState?: PHDocument[\"state\"];\n state?: PHDocument[\"state\"];\n };\n\n const newState = input.initialState || input.state;\n if (newState) {\n document.state = { ...document.state, ...newState };\n document.initialState = document.state;\n }\n}\n\n/**\n * Applies a DELETE_DOCUMENT action to a document.\n * Marks the document as deleted in the document scope state.\n *\n * @param document - The document to mark as deleted\n * @param action - The DELETE_DOCUMENT action\n * @returns The updated document (mutates in place and returns for convenience)\n */\nexport function applyDeleteDocumentAction(\n document: PHDocument,\n action: DeleteDocumentAction,\n): PHDocument {\n const deletedAt = action.timestampUtcMs || new Date().toISOString();\n\n document.state = {\n ...document.state,\n document: {\n ...document.state.document,\n isDeleted: true,\n deletedAtUtcIso: deletedAt,\n },\n };\n\n return document;\n}\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 */\nexport const getNextIndexForScope = (\n document: PHDocument,\n scope: string,\n): number => {\n return document.header.revision[scope] || 0;\n};\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 */\nexport function createEmptyConsistencyToken(): ConsistencyToken {\n return {\n version: 1,\n createdAtUtcIso: new Date().toISOString(),\n coordinates: [],\n };\n}\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 */\nexport function createConsistencyToken(\n operationsWithContext: OperationWithContext[],\n): ConsistencyToken {\n if (operationsWithContext.length === 0) {\n return createEmptyConsistencyToken();\n }\n\n const coordinates: ConsistencyCoordinate[] = [];\n for (let i = 0; i < operationsWithContext.length; i++) {\n const opWithContext = operationsWithContext[i]!;\n coordinates.push({\n documentId: opWithContext.context.documentId,\n scope: opWithContext.context.scope,\n branch: opWithContext.context.branch,\n operationIndex: opWithContext.operation.index,\n });\n }\n\n return {\n version: 1,\n createdAtUtcIso: new Date().toISOString(),\n coordinates,\n };\n}\n\nexport function createOperation(\n action: Action,\n index: number,\n skip: number,\n context: { documentId: string; scope: string; branch: string },\n): Operation {\n const id = deriveOperationId(\n context.documentId,\n context.scope,\n context.branch,\n action.id,\n );\n\n return {\n id,\n index: index,\n timestampUtcMs: action.timestampUtcMs || new Date().toISOString(),\n hash: \"\",\n skip: skip,\n action: action,\n };\n}\n\nexport function updateDocumentRevision(\n document: PHDocument,\n scope: string,\n operationIndex: number,\n): void {\n document.header.revision = {\n ...document.header.revision,\n [scope]: operationIndex + 1,\n };\n}\n\nexport function buildSuccessResult(\n job: Job,\n operation: Operation,\n documentId: string,\n documentType: string,\n resultingState: string,\n startTime: number,\n): JobResult {\n return {\n job,\n success: true,\n operations: [operation],\n operationsWithContext: [\n {\n operation,\n context: {\n documentId: documentId,\n scope: job.scope,\n branch: job.branch,\n documentType: documentType,\n resultingState,\n ordinal: 0,\n },\n },\n ],\n duration: Date.now() - startTime,\n };\n}\n\nexport function buildErrorResult(\n job: Job,\n error: Error,\n startTime: number,\n): JobResult {\n return {\n job,\n success: false,\n error: error,\n duration: Date.now() - startTime,\n };\n}\n","class LRUNode<K> {\n key: K;\n prev: LRUNode<K> | undefined;\n next: LRUNode<K> | undefined;\n\n constructor(key: K) {\n this.key = key;\n this.prev = undefined;\n this.next = undefined;\n }\n}\n\nexport class LRUTracker<K> {\n private map: Map<K, LRUNode<K>>;\n private head: LRUNode<K> | undefined;\n private tail: LRUNode<K> | undefined;\n\n constructor() {\n this.map = new Map();\n this.head = undefined;\n this.tail = undefined;\n }\n\n get size(): number {\n return this.map.size;\n }\n\n touch(key: K): void {\n const node = this.map.get(key);\n\n if (node) {\n this.moveToFront(node);\n } else {\n this.addToFront(key);\n }\n }\n\n evict(): K | undefined {\n if (!this.tail) {\n return undefined;\n }\n\n const key = this.tail.key;\n this.remove(key);\n return key;\n }\n\n remove(key: K): void {\n const node = this.map.get(key);\n if (!node) {\n return;\n }\n\n this.removeNode(node);\n this.map.delete(key);\n }\n\n clear(): void {\n this.map.clear();\n this.head = undefined;\n this.tail = undefined;\n }\n\n private addToFront(key: K): void {\n const node = new LRUNode(key);\n this.map.set(key, node);\n\n if (!this.head) {\n this.head = node;\n this.tail = node;\n } else {\n node.next = this.head;\n this.head.prev = node;\n this.head = node;\n }\n }\n\n private moveToFront(node: LRUNode<K>): void {\n if (node === this.head) {\n return;\n }\n\n this.removeNode(node);\n node.prev = undefined;\n node.next = this.head;\n\n if (this.head) {\n this.head.prev = node;\n }\n\n this.head = node;\n\n if (!this.tail) {\n this.tail = node;\n }\n }\n\n private removeNode(node: LRUNode<K>): void {\n if (node.prev) {\n node.prev.next = node.next;\n } else {\n this.head = node.next;\n }\n\n if (node.next) {\n node.next.prev = node.prev;\n } else {\n this.tail = node.prev;\n }\n }\n}\n","import type {\n CreateDocumentAction,\n DeleteDocumentAction,\n UpgradeDocumentAction,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n applyDeleteDocumentAction,\n applyUpgradeDocumentAction,\n createDocumentFromAction,\n} from \"../executor/util.js\";\nimport { DocumentNotFoundError } from \"../shared/errors.js\";\nimport type { IOperationStore } from \"../storage/interfaces.js\";\nimport type {\n CachedDocumentMeta,\n DocumentMetaCacheConfig,\n IDocumentMetaCache,\n} from \"./document-meta-cache-types.js\";\nimport { LRUTracker } from \"./lru/lru-tracker.js\";\n\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 */\nexport class DocumentMetaCache implements IDocumentMetaCache {\n private cache: Map<string, CachedDocumentMeta>;\n private lruTracker: LRUTracker<string>;\n private operationStore: IOperationStore;\n private config: DocumentMetaCacheConfig;\n\n constructor(\n operationStore: IOperationStore,\n config: DocumentMetaCacheConfig,\n ) {\n this.operationStore = operationStore;\n this.config = {\n maxDocuments: config.maxDocuments,\n };\n this.cache = new Map();\n this.lruTracker = new LRUTracker<string>();\n }\n\n withScopedStore(operationStore: IOperationStore): DocumentMetaCache {\n const scoped = new DocumentMetaCache(operationStore, this.config);\n scoped.cache = this.cache;\n scoped.lruTracker = this.lruTracker;\n return scoped;\n }\n\n async startup(): Promise<void> {\n return Promise.resolve();\n }\n\n async shutdown(): Promise<void> {\n return Promise.resolve();\n }\n\n async getDocumentMeta(\n documentId: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<CachedDocumentMeta> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const key = this.makeKey(documentId, branch);\n const cached = this.cache.get(key);\n\n if (cached) {\n this.lruTracker.touch(key);\n return cached;\n }\n\n const meta = await this.rebuildLatest(documentId, branch, signal);\n this.putDocumentMeta(documentId, branch, meta);\n return meta;\n }\n\n async rebuildAtRevision(\n documentId: string,\n branch: string,\n targetRevision: number,\n signal?: AbortSignal,\n ): Promise<CachedDocumentMeta> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n return this.rebuildFromOperations(\n documentId,\n branch,\n targetRevision,\n signal,\n );\n }\n\n putDocumentMeta(\n documentId: string,\n branch: string,\n meta: CachedDocumentMeta,\n ): void {\n const key = this.makeKey(documentId, branch);\n\n if (!this.cache.has(key) && this.cache.size >= this.config.maxDocuments) {\n const evictKey = this.lruTracker.evict();\n if (evictKey) {\n this.cache.delete(evictKey);\n }\n }\n\n this.cache.set(key, structuredClone(meta));\n this.lruTracker.touch(key);\n }\n\n invalidate(documentId: string, branch?: string): number {\n let evicted = 0;\n\n if (branch === undefined) {\n for (const key of this.cache.keys()) {\n if (key.startsWith(`${documentId}:`)) {\n this.cache.delete(key);\n this.lruTracker.remove(key);\n evicted++;\n }\n }\n } else {\n const key = this.makeKey(documentId, branch);\n if (this.cache.has(key)) {\n this.cache.delete(key);\n this.lruTracker.remove(key);\n evicted = 1;\n }\n }\n\n return evicted;\n }\n\n clear(): void {\n this.cache.clear();\n this.lruTracker.clear();\n }\n\n private makeKey(documentId: string, branch: string): string {\n return `${documentId}:${branch}`;\n }\n\n private async rebuildLatest(\n documentId: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<CachedDocumentMeta> {\n return this.rebuildFromOperations(documentId, branch, undefined, signal);\n }\n\n private async rebuildFromOperations(\n documentId: string,\n branch: string,\n targetRevision: number | undefined,\n signal?: AbortSignal,\n ): Promise<CachedDocumentMeta> {\n const docScopeOps = await this.operationStore.getSince(\n documentId,\n \"document\",\n branch,\n -1,\n undefined,\n undefined,\n signal,\n );\n\n if (docScopeOps.results.length === 0) {\n throw new DocumentNotFoundError(documentId);\n }\n\n const createOp = docScopeOps.results[0];\n if (createOp.action.type !== \"CREATE_DOCUMENT\") {\n throw new Error(\n `Invalid document: first operation must be CREATE_DOCUMENT, found ${createOp.action.type}`,\n );\n }\n\n const createAction = createOp.action as CreateDocumentAction;\n const documentType = createAction.input.model;\n\n let document = createDocumentFromAction(createAction);\n let documentScopeRevision = 0;\n\n for (const op of docScopeOps.results) {\n if (targetRevision !== undefined && op.index > targetRevision) {\n break;\n }\n\n documentScopeRevision = op.index;\n\n if (op.action.type === \"UPGRADE_DOCUMENT\") {\n const upgradeAction = op.action as UpgradeDocumentAction;\n document = applyUpgradeDocumentAction(document, upgradeAction);\n } else if (op.action.type === \"DELETE_DOCUMENT\") {\n document = applyDeleteDocumentAction(\n document,\n op.action as DeleteDocumentAction,\n );\n }\n\n // for now, we are skipping relationship operations\n }\n\n return {\n state: document.state.document,\n documentType,\n documentScopeRevision: documentScopeRevision + 1,\n };\n }\n}\n","import type { OperationWithContext } from \"@powerhousedao/shared/document-model\";\nimport type { Kysely, Transaction } from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { PagedResults, PagingOptions } from \"../shared/types.js\";\nimport type { ViewFilter } from \"../storage/interfaces.js\";\nimport type { Database } from \"../storage/kysely/types.js\";\nimport type {\n InsertableDocumentCollection,\n InsertableOperationIndexOperation,\n IOperationIndex,\n IOperationIndexTxn,\n OperationIndexEntry,\n OperationIndexOperationRow,\n} from \"./operation-index-types.js\";\n\ntype CollectionMembershipRecord = {\n collectionId: string;\n documentId: string;\n\n // this is NOT operation.index -- it is the index of the operation in the\n // operations array\n operationIndex: number;\n};\n\nclass KyselyOperationIndexTxn implements IOperationIndexTxn {\n private collections: string[] = [];\n private collectionMemberships: CollectionMembershipRecord[] = [];\n private collectionRemovals: CollectionMembershipRecord[] = [];\n private operations: OperationIndexEntry[] = [];\n\n createCollection(collectionId: string): void {\n this.collections.push(collectionId);\n }\n\n addToCollection(collectionId: string, documentId: string): void {\n const lastOpIndex = this.operations.length - 1;\n if (lastOpIndex < 0) {\n throw new Error(\n \"addToCollection must be called after write() - no operations in transaction\",\n );\n }\n this.collectionMemberships.push({\n collectionId,\n documentId,\n operationIndex: lastOpIndex,\n });\n }\n\n removeFromCollection(collectionId: string, documentId: string): void {\n const lastOpIndex = this.operations.length - 1;\n if (lastOpIndex < 0) {\n throw new Error(\n \"removeFromCollection must be called after write() - no operations in transaction\",\n );\n }\n this.collectionRemovals.push({\n collectionId,\n documentId,\n operationIndex: lastOpIndex,\n });\n }\n\n write(operations: OperationIndexEntry[]): void {\n this.operations.push(...operations);\n }\n\n getCollections(): string[] {\n return this.collections;\n }\n\n getCollectionMembershipRecords(): CollectionMembershipRecord[] {\n return this.collectionMemberships;\n }\n\n getCollectionRemovals(): CollectionMembershipRecord[] {\n return this.collectionRemovals;\n }\n\n getOperations(): OperationIndexEntry[] {\n return this.operations;\n }\n}\n\nexport class KyselyOperationIndex implements IOperationIndex {\n private trx?: Transaction<Database>;\n\n constructor(private db: Kysely<Database>) {}\n\n private get queryExecutor(): Kysely<Database> | Transaction<Database> {\n return this.trx ?? this.db;\n }\n\n withTransaction(trx: Transaction<Database>): KyselyOperationIndex {\n const instance = new KyselyOperationIndex(this.db);\n instance.trx = trx;\n return instance;\n }\n\n start(): IOperationIndexTxn {\n return new KyselyOperationIndexTxn();\n }\n\n async commit(\n txn: IOperationIndexTxn,\n signal?: AbortSignal,\n ): Promise<number[]> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const kyselyTxn = txn as KyselyOperationIndexTxn;\n\n if (this.trx) {\n return this.executeCommit(this.trx, kyselyTxn);\n }\n\n let resultOrdinals: number[] = [];\n await this.db.transaction().execute(async (trx) => {\n resultOrdinals = await this.executeCommit(trx, kyselyTxn);\n });\n return resultOrdinals;\n }\n\n private async executeCommit(\n trx: Transaction<Database>,\n kyselyTxn: KyselyOperationIndexTxn,\n ): Promise<number[]> {\n const collections = kyselyTxn.getCollections();\n const memberships = kyselyTxn.getCollectionMembershipRecords();\n const removals = kyselyTxn.getCollectionRemovals();\n const operations = kyselyTxn.getOperations();\n\n if (collections.length > 0) {\n const collectionRows: InsertableDocumentCollection[] = collections.map(\n (collectionId) => ({\n documentId: collectionId,\n collectionId,\n joinedOrdinal: BigInt(0),\n leftOrdinal: null,\n }),\n );\n\n await trx\n .insertInto(\"document_collections\")\n .values(collectionRows)\n .onConflict((oc) => oc.doNothing())\n .execute();\n }\n\n let operationOrdinals: number[] = [];\n if (operations.length > 0) {\n const operationRows: InsertableOperationIndexOperation[] = operations.map(\n (op) => ({\n opId: op.id || \"\",\n documentId: op.documentId,\n documentType: op.documentType,\n scope: op.scope,\n branch: op.branch,\n timestampUtcMs: op.timestampUtcMs,\n index: op.index,\n skip: op.skip,\n hash: op.hash,\n action: op.action as unknown,\n sourceRemote: op.sourceRemote,\n }),\n );\n\n const insertedOps = await trx\n .insertInto(\"operation_index_operations\")\n .values(operationRows)\n .returning(\"ordinal\")\n .execute();\n\n operationOrdinals = insertedOps.map((row) => row.ordinal);\n }\n\n if (memberships.length > 0) {\n for (const m of memberships) {\n const ordinal = operationOrdinals[m.operationIndex];\n\n await trx\n .insertInto(\"document_collections\")\n .values({\n documentId: m.documentId,\n collectionId: m.collectionId,\n joinedOrdinal: BigInt(ordinal),\n leftOrdinal: null,\n })\n .onConflict((oc) =>\n oc.columns([\"documentId\", \"collectionId\"]).doUpdateSet({\n joinedOrdinal: BigInt(ordinal),\n leftOrdinal: null,\n }),\n )\n .execute();\n }\n }\n\n if (removals.length > 0) {\n for (const r of removals) {\n const ordinal = operationOrdinals[r.operationIndex];\n\n await trx\n .updateTable(\"document_collections\")\n .set({\n leftOrdinal: BigInt(ordinal),\n })\n .where(\"collectionId\", \"=\", r.collectionId)\n .where(\"documentId\", \"=\", r.documentId)\n .where(\"leftOrdinal\", \"is\", null)\n .execute();\n }\n }\n\n return operationOrdinals;\n }\n\n async find(\n collectionId: string,\n cursor?: number,\n view?: ViewFilter,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationIndexEntry>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const outerCursor = cursor ?? -1;\n const pagingCursorOrdinal =\n paging?.cursor !== undefined ? Number.parseInt(paging.cursor, 10) : -1;\n\n const buildBranch = (kind: \"joiner\" | \"newOps\") => {\n let qb = this.queryExecutor\n .selectFrom(\"operation_index_operations as oi\")\n .innerJoin(\n \"document_collections as dc\",\n \"oi.documentId\",\n \"dc.documentId\",\n )\n .selectAll(\"oi\")\n .select([\"dc.documentId\", \"dc.collectionId\"])\n .where(\"dc.collectionId\", \"=\", collectionId)\n .where(\n sql<boolean>`(dc.\"leftOrdinal\" IS NULL OR oi.ordinal < dc.\"leftOrdinal\")`,\n );\n\n if (kind === \"joiner\") {\n qb = qb\n .where(\"dc.joinedOrdinal\", \">\", BigInt(outerCursor))\n .where(\"oi.ordinal\", \"<=\", outerCursor);\n } else {\n qb = qb.where(\"oi.ordinal\", \">\", outerCursor);\n }\n\n qb = qb.where(\"oi.ordinal\", \">\", pagingCursorOrdinal);\n\n if (view?.branch) {\n qb = qb.where(\"oi.branch\", \"=\", view.branch);\n }\n if (view?.scopes && view.scopes.length > 0) {\n qb = qb.where(\"oi.scope\", \"in\", view.scopes);\n }\n if (view?.excludeSourceRemote) {\n qb = qb.where(\"oi.sourceRemote\", \"!=\", view.excludeSourceRemote);\n }\n\n return qb;\n };\n\n let unionQuery = buildBranch(\"joiner\")\n .unionAll(buildBranch(\"newOps\"))\n .orderBy(\"ordinal\", \"asc\");\n\n if (paging?.limit) {\n unionQuery = unionQuery.limit(paging.limit + 1);\n }\n\n const rows = await unionQuery.execute();\n\n let hasMore = false;\n let items = rows;\n\n if (paging?.limit && rows.length > paging.limit) {\n hasMore = true;\n items = rows.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && items.length > 0\n ? items[items.length - 1].ordinal.toString()\n : undefined;\n\n const cursorValue = paging?.cursor || \"0\";\n const limit = paging?.limit || 100;\n const entries = items.map((row) => this.rowToOperationIndexEntry(row));\n\n return {\n results: entries,\n options: { cursor: cursorValue, limit },\n nextCursor,\n next: hasMore\n ? () =>\n this.find(\n collectionId,\n cursor,\n view,\n { cursor: nextCursor!, limit },\n signal,\n )\n : undefined,\n };\n }\n\n async get(\n documentId: string,\n view?: ViewFilter,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationIndexEntry>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n let query = this.queryExecutor\n .selectFrom(\"operation_index_operations\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .orderBy(\"ordinal\", \"asc\");\n\n if (view?.branch) {\n query = query.where(\"branch\", \"=\", view.branch);\n }\n\n if (view?.scopes && view.scopes.length > 0) {\n query = query.where(\"scope\", \"in\", view.scopes);\n }\n\n if (paging?.cursor) {\n const cursorOrdinal = Number.parseInt(paging.cursor, 10);\n query = query.where(\"ordinal\", \">\", cursorOrdinal);\n }\n\n if (paging?.limit) {\n query = query.limit(paging.limit + 1);\n }\n\n const rows = await query.execute();\n\n let hasMore = false;\n let items = rows;\n\n if (paging?.limit && rows.length > paging.limit) {\n hasMore = true;\n items = rows.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && items.length > 0\n ? items[items.length - 1].ordinal.toString()\n : undefined;\n\n const cursorValue = paging?.cursor || \"0\";\n const limit = paging?.limit || 100;\n const entries = items.map((row) => this.rowToOperationIndexEntry(row));\n\n return {\n results: entries,\n options: { cursor: cursorValue, limit },\n nextCursor,\n next: hasMore\n ? () =>\n this.get(documentId, view, { cursor: nextCursor!, limit }, signal)\n : undefined,\n };\n }\n\n async getSinceOrdinal(\n ordinal: number,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationWithContext>> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n let query = this.queryExecutor\n .selectFrom(\"operation_index_operations\")\n .selectAll()\n .where(\"ordinal\", \">\", ordinal)\n .orderBy(\"ordinal\", \"asc\");\n\n if (paging?.cursor) {\n const cursorOrdinal = Number.parseInt(paging.cursor, 10);\n query = query.where(\"ordinal\", \">\", cursorOrdinal);\n }\n\n if (paging?.limit) {\n query = query.limit(paging.limit + 1);\n }\n\n const rows = await query.execute();\n\n let hasMore = false;\n let items = rows;\n\n if (paging?.limit && rows.length > paging.limit) {\n hasMore = true;\n items = rows.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && items.length > 0\n ? items[items.length - 1].ordinal.toString()\n : undefined;\n\n const cursorValue = paging?.cursor || \"0\";\n const limit = paging?.limit || 100;\n const operations = items.map((row) => this.rowToOperationWithContext(row));\n\n return {\n results: operations,\n options: { cursor: cursorValue, limit },\n nextCursor,\n next: hasMore\n ? () =>\n this.getSinceOrdinal(\n ordinal,\n { cursor: nextCursor!, limit },\n signal,\n )\n : undefined,\n };\n }\n\n private rowToOperationWithContext(\n row: OperationIndexOperationRow,\n ): OperationWithContext {\n return {\n operation: {\n index: row.index,\n timestampUtcMs: row.timestampUtcMs,\n hash: row.hash,\n skip: row.skip,\n action: row.action as OperationWithContext[\"operation\"][\"action\"],\n id: row.opId,\n },\n context: {\n documentId: row.documentId,\n documentType: row.documentType,\n scope: row.scope,\n branch: row.branch,\n ordinal: row.ordinal,\n },\n };\n }\n\n private rowToOperationIndexEntry(\n row: OperationIndexOperationRow,\n ): OperationIndexEntry {\n return {\n ordinal: row.ordinal,\n documentId: row.documentId,\n documentType: row.documentType,\n branch: row.branch,\n scope: row.scope,\n index: row.index,\n timestampUtcMs: row.timestampUtcMs,\n hash: row.hash,\n skip: row.skip,\n action: row.action as OperationIndexEntry[\"action\"],\n id: row.opId,\n sourceRemote: row.sourceRemote,\n };\n }\n\n async getLatestTimestampForCollection(\n collectionId: string,\n signal?: AbortSignal,\n ): Promise<string | null> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const result = await this.queryExecutor\n .selectFrom(\"operation_index_operations as oi\")\n .innerJoin(\"document_collections as dc\", \"oi.documentId\", \"dc.documentId\")\n .select(\"oi.timestampUtcMs\")\n .where(\"dc.collectionId\", \"=\", collectionId)\n .where(\n sql<boolean>`(dc.\"leftOrdinal\" IS NULL OR oi.ordinal < dc.\"leftOrdinal\")`,\n )\n .orderBy(\"oi.ordinal\", \"desc\")\n .limit(1)\n .executeTakeFirst();\n\n return result?.timestampUtcMs ?? null;\n }\n\n async getCollectionsForDocuments(\n documentIds: string[],\n ): Promise<Record<string, string[]>> {\n if (documentIds.length === 0) {\n return {};\n }\n\n const rows = await this.queryExecutor\n .selectFrom(\"document_collections\")\n .select([\"documentId\", \"collectionId\"])\n .where(\"documentId\", \"in\", documentIds)\n .where(\"leftOrdinal\", \"is\", null)\n .execute();\n\n const result: Record<string, string[]> = {};\n for (const row of rows) {\n if (!(row.documentId in result)) {\n result[row.documentId] = [];\n }\n result[row.documentId].push(row.collectionId);\n }\n return result;\n }\n}\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 */\nexport class RingBuffer<T> {\n private buffer: T[];\n private head: number = 0;\n private size: number = 0;\n private capacity: number;\n\n constructor(capacity: number) {\n if (capacity <= 0) {\n throw new Error(\"Ring buffer capacity must be greater than 0\");\n }\n this.capacity = capacity;\n this.buffer = new Array<T>(capacity);\n }\n\n /**\n * Adds an item to the buffer. If the buffer is full, overwrites the oldest item.\n *\n * @param item - The item to add\n */\n push(item: T): void {\n const index = (this.head + this.size) % this.capacity;\n\n if (this.size < this.capacity) {\n this.buffer[index] = item;\n this.size++;\n } else {\n this.buffer[this.head] = item;\n this.head = (this.head + 1) % this.capacity;\n }\n }\n\n /**\n * Returns all items in the buffer in chronological order (oldest to newest).\n *\n * @returns Array of items in insertion order\n */\n getAll(): T[] {\n if (this.size === 0) {\n return [];\n }\n\n const result: T[] = [];\n for (let i = 0; i < this.size; i++) {\n const index = (this.head + i) % this.capacity;\n result.push(this.buffer[index]);\n }\n return result;\n }\n\n /**\n * Clears all items from the buffer.\n */\n clear(): void {\n this.buffer = new Array<T>(this.capacity);\n this.head = 0;\n this.size = 0;\n }\n\n /**\n * Gets the current number of items in the buffer.\n */\n get length(): number {\n return this.size;\n }\n}\n","import type {\n CreateDocumentAction,\n PHDocument,\n UpgradeDocumentAction,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n applyDeleteDocumentAction,\n applyUpgradeDocumentAction,\n createDocumentFromAction,\n} from \"../executor/util.js\";\nimport type { IDocumentModelRegistry } from \"../registry/interfaces.js\";\nimport type { IKeyframeStore, IOperationStore } from \"../storage/interfaces.js\";\nimport { RingBuffer } from \"./buffer/ring-buffer.js\";\nimport { LRUTracker } from \"./lru/lru-tracker.js\";\nimport type { CachedSnapshot, WriteCacheConfig } from \"./write-cache-types.js\";\nimport type { IWriteCache } from \"./write/interfaces.js\";\n\ntype DocumentStream = {\n key: string;\n ringBuffer: RingBuffer<CachedSnapshot>;\n};\n\nfunction extractModuleVersion(doc: PHDocument): number | undefined {\n const v = (doc.state as Record<string, Record<string, unknown>>).document\n .version as number | undefined;\n return v === 0 ? undefined : v;\n}\n\n/**\n * In-memory write cache with keyframe persistence for PHDocuments.\n *\n * Caches document snapshots in ring buffers with LRU eviction. On cache miss,\n * rebuilds documents from nearest keyframe or full operation history.\n *\n * **Performance Characteristics:**\n * - Cache hit: O(1) lookup in ring buffer\n * - Cold miss: O(n) where n is total operation count, or O(k) where k is operations since keyframe\n * - Warm miss: O(m) where m is operations since cached revision\n * - Eviction: O(1) for LRU tracking and removal\n *\n * **Thread Safety:**\n * Not thread-safe. Designed for single-threaded job executor environment.\n * External synchronization required for concurrent access across multiple executors.\n *\n * **Example:**\n * ```typescript\n * const cache = new KyselyWriteCache(\n * keyframeStore,\n * operationStore,\n * registry,\n * { maxDocuments: 1000, ringBufferSize: 10, keyframeInterval: 10 }\n * );\n *\n * await cache.startup();\n *\n * // Retrieve or rebuild document\n * const doc = await cache.getState(docId, docType, scope, branch, revision);\n *\n * // Cache result after job execution\n * cache.putState(docId, docType, scope, branch, newRevision, updatedDoc);\n *\n * await cache.shutdown();\n * ```\n */\nexport class KyselyWriteCache implements IWriteCache {\n private streams: Map<string, DocumentStream>;\n private lruTracker: LRUTracker<string>;\n private keyframeStore: IKeyframeStore;\n private operationStore: IOperationStore;\n private registry: IDocumentModelRegistry;\n private config: Required<WriteCacheConfig>;\n\n constructor(\n keyframeStore: IKeyframeStore,\n operationStore: IOperationStore,\n registry: IDocumentModelRegistry,\n config: WriteCacheConfig,\n ) {\n this.keyframeStore = keyframeStore;\n this.operationStore = operationStore;\n this.registry = registry;\n this.config = {\n maxDocuments: config.maxDocuments,\n ringBufferSize: config.ringBufferSize,\n keyframeInterval: config.keyframeInterval,\n };\n this.streams = new Map();\n this.lruTracker = new LRUTracker<string>();\n }\n\n withScopedStores(\n operationStore: IOperationStore,\n keyframeStore: IKeyframeStore,\n ): KyselyWriteCache {\n const scoped = new KyselyWriteCache(\n keyframeStore,\n operationStore,\n this.registry,\n this.config,\n );\n scoped.streams = this.streams;\n scoped.lruTracker = this.lruTracker;\n return scoped;\n }\n\n /**\n * Initializes the write cache.\n * Currently a no-op as keyframe store lifecycle is managed externally.\n */\n async startup(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Shuts down the write cache.\n * Currently a no-op as keyframe store lifecycle is managed externally.\n */\n async shutdown(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Retrieves document state at a specific revision from cache or rebuilds it.\n *\n * Cache hit path: Returns cached snapshot if available (O(1))\n * Warm miss path: Rebuilds from cached base revision + incremental ops\n * Cold miss path: Rebuilds from keyframe or from scratch using all operations\n *\n * @param documentId - The document identifier\n * @param scope - The operation scope\n * @param branch - The operation branch\n * @param targetRevision - The target revision, or undefined for newest\n * @param signal - Optional abort signal to cancel the operation\n * @returns The document at the target revision\n * @throws {Error} \"Operation aborted\" if signal is aborted\n * @throws {ModuleNotFoundError} If document type not registered in registry\n * @throws {Error} \"Failed to rebuild document\" if operation store fails\n * @throws {Error} If reducer throws during operation application\n * @throws {Error} If document serialization fails\n */\n async getState(\n documentId: string,\n scope: string,\n branch: string,\n targetRevision?: number,\n signal?: AbortSignal,\n ): Promise<PHDocument> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const streamKey = this.makeStreamKey(documentId, scope, branch);\n const stream = this.streams.get(streamKey);\n\n if (stream) {\n const snapshots = stream.ringBuffer.getAll();\n\n if (targetRevision === undefined) {\n if (snapshots.length > 0) {\n const newest = snapshots[snapshots.length - 1];\n this.lruTracker.touch(streamKey);\n return newest.document;\n }\n } else {\n const exactMatch = snapshots.find((s) => s.revision === targetRevision);\n if (exactMatch) {\n this.lruTracker.touch(streamKey);\n return exactMatch.document;\n }\n\n const newestOlder = this.findNearestOlderSnapshot(\n snapshots,\n targetRevision,\n );\n if (newestOlder) {\n const document = await this.warmMissRebuild(\n newestOlder.document,\n newestOlder.revision,\n documentId,\n scope,\n branch,\n targetRevision,\n signal,\n );\n\n this.putState(documentId, scope, branch, targetRevision, document);\n this.lruTracker.touch(streamKey);\n\n return document;\n }\n }\n }\n\n const document = await this.coldMissRebuild(\n documentId,\n scope,\n branch,\n targetRevision,\n signal,\n );\n\n let revision = targetRevision;\n if (revision === undefined) {\n revision = document.header.revision[scope] || 0;\n }\n\n this.putState(documentId, scope, branch, revision, document);\n\n return document;\n }\n\n /**\n * Stores a document snapshot in the cache at a specific revision.\n *\n * The cached document is a shallow copy of the input with its operation history\n * truncated to the last operation per scope and its clipboard cleared. This keeps\n * memory use and copy costs constant regardless of operation count. Consumers of\n * getState() must not rely on the full operation history being present; the only\n * guaranteed invariant is that operations[scope].at(-1) reflects the latest\n * operation index for each scope.\n *\n * Updates LRU tracker and may evict least recently used stream if at capacity.\n * Asynchronously persists keyframes at configured intervals (fire-and-forget).\n *\n * @param documentId - The document identifier\n * @param scope - The operation scope\n * @param branch - The operation branch\n * @param revision - The revision number\n * @param document - The document to cache\n * @throws {Error} If document serialization fails\n */\n putState(\n documentId: string,\n scope: string,\n branch: string,\n revision: number,\n document: PHDocument,\n ): void {\n const streamKey = this.makeStreamKey(documentId, scope, branch);\n const stream = this.getOrCreateStream(streamKey);\n\n // Keep only the last operation per scope in the ring buffer. The reducer\n // only needs at(-1).index to determine the next index, so carrying the\n // full history causes O(n²) array copies across n operations. UNDO, REDO,\n // and PRUNE bypass this by forcing a cold-miss rebuild in the job executor.\n const slicedDocument: PHDocument = {\n ...document,\n operations: Object.fromEntries(\n Object.entries(document.operations).map(([k, ops]) => [\n k,\n ops.length ? [ops.at(-1)!] : [],\n ]),\n ),\n clipboard: [],\n };\n\n const snapshot: CachedSnapshot = {\n revision,\n document: slicedDocument,\n };\n\n stream.ringBuffer.push(snapshot);\n\n if (this.isKeyframeRevision(revision)) {\n this.keyframeStore\n .putKeyframe(documentId, scope, branch, revision, {\n ...document,\n operations: {},\n clipboard: [],\n })\n .catch((err) => {\n console.error(\n `Failed to persist keyframe ${documentId}@${revision}:`,\n err,\n );\n });\n }\n }\n\n /**\n * Invalidates cached document streams.\n *\n * Supports three invalidation scopes:\n * - Document-level: invalidate(documentId) - removes all streams for document\n * - Scope-level: invalidate(documentId, scope) - removes all branches for scope\n * - Stream-level: invalidate(documentId, scope, branch) - removes specific stream\n *\n * @param documentId - The document identifier\n * @param scope - Optional scope to narrow invalidation\n * @param branch - Optional branch to narrow invalidation (requires scope)\n * @returns The number of streams evicted\n */\n invalidate(documentId: string, scope?: string, branch?: string): number {\n let evicted = 0;\n\n if (scope === undefined && branch === undefined) {\n for (const [key] of this.streams.entries()) {\n if (key.startsWith(`${documentId}:`)) {\n this.streams.delete(key);\n this.lruTracker.remove(key);\n evicted++;\n }\n }\n } else if (scope !== undefined && branch === undefined) {\n for (const [key] of this.streams.entries()) {\n if (key.startsWith(`${documentId}:${scope}:`)) {\n this.streams.delete(key);\n this.lruTracker.remove(key);\n evicted++;\n }\n }\n } else if (scope !== undefined && branch !== undefined) {\n const key = this.makeStreamKey(documentId, scope, branch);\n if (this.streams.has(key)) {\n this.streams.delete(key);\n this.lruTracker.remove(key);\n evicted = 1;\n }\n }\n\n return evicted;\n }\n\n /**\n * Clears the entire cache, removing all cached document streams.\n * Resets LRU tracking state. This operation always succeeds.\n */\n clear(): void {\n this.streams.clear();\n this.lruTracker.clear();\n }\n\n /**\n * Retrieves a specific stream for a document. Exposed on the implementation\n * for testing, but not on the interface.\n *\n * @internal\n */\n getStream(\n documentId: string,\n scope: string,\n branch: string,\n ): DocumentStream | undefined {\n const key = this.makeStreamKey(documentId, scope, branch);\n return this.streams.get(key);\n }\n\n private async findNearestKeyframe(\n documentId: string,\n scope: string,\n branch: string,\n targetRevision: number,\n signal?: AbortSignal,\n ): Promise<{ revision: number; document: PHDocument } | undefined> {\n if (targetRevision === Number.MAX_SAFE_INTEGER || targetRevision <= 0) {\n return undefined;\n }\n\n return this.keyframeStore.findNearestKeyframe(\n documentId,\n scope,\n branch,\n targetRevision,\n signal,\n );\n }\n\n private async coldMissRebuild(\n documentId: string,\n scope: string,\n branch: string,\n targetRevision: number | undefined,\n signal?: AbortSignal,\n ): Promise<PHDocument> {\n const effectiveTargetRevision = targetRevision || Number.MAX_SAFE_INTEGER;\n\n const keyframe = await this.findNearestKeyframe(\n documentId,\n scope,\n branch,\n effectiveTargetRevision,\n signal,\n );\n\n let document: PHDocument | undefined;\n let startRevision: number;\n let documentType: string;\n\n if (keyframe) {\n document = keyframe.document;\n startRevision = keyframe.revision;\n documentType = keyframe.document.header.documentType;\n } else {\n startRevision = -1;\n const createOpResult = await this.operationStore.getSince(\n documentId,\n \"document\",\n branch,\n -1,\n undefined,\n { cursor: \"0\", limit: 1 },\n signal,\n );\n\n if (createOpResult.results.length === 0) {\n throw new Error(\n `Failed to rebuild document ${documentId}: no CREATE_DOCUMENT operation found in document scope`,\n );\n }\n\n const createOp = createOpResult.results[0];\n if (createOp.action.type !== \"CREATE_DOCUMENT\") {\n throw new Error(\n `Failed to rebuild document ${documentId}: first operation in document scope must be CREATE_DOCUMENT, found ${createOp.action.type}`,\n );\n }\n\n const documentCreateAction = createOp.action as CreateDocumentAction;\n documentType = documentCreateAction.input.model;\n if (!documentType) {\n throw new Error(\n `Failed to rebuild document ${documentId}: CREATE_DOCUMENT action missing model in input`,\n );\n }\n\n document = createDocumentFromAction(documentCreateAction);\n\n let docModule = this.registry.getModule(\n documentType,\n extractModuleVersion(document),\n );\n const docScopeOps = await this.operationStore.getSince(\n documentId,\n \"document\",\n branch,\n 0,\n undefined,\n undefined,\n signal,\n );\n\n for (const operation of docScopeOps.results) {\n if (operation.index === 0) {\n continue;\n }\n\n if (operation.action.type === \"UPGRADE_DOCUMENT\") {\n const upgradeAction = operation.action as UpgradeDocumentAction;\n document = applyUpgradeDocumentAction(document, upgradeAction);\n docModule = this.registry.getModule(\n documentType,\n extractModuleVersion(document),\n );\n } else if (operation.action.type === \"DELETE_DOCUMENT\") {\n applyDeleteDocumentAction(document, operation.action as never);\n } else {\n const protocolVersion =\n document.header.protocolVersions?.[\"base-reducer\"] ?? 1;\n document = docModule.reducer(document, operation.action, undefined, {\n skip: operation.skip,\n protocolVersion,\n });\n }\n }\n }\n\n const module = this.registry.getModule(\n documentType,\n extractModuleVersion(document),\n );\n let cursor: string | undefined = undefined;\n const pageSize = 100;\n let hasMorePages: boolean;\n\n do {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const paging = { cursor: cursor || \"0\", limit: pageSize };\n\n try {\n const result = await this.operationStore.getSince(\n documentId,\n scope,\n branch,\n startRevision,\n undefined,\n paging,\n signal,\n );\n\n for (const operation of result.results) {\n if (\n targetRevision !== undefined &&\n operation.index > targetRevision\n ) {\n break;\n }\n\n // Fail-fast: if reducer throws, error propagates immediately without caching partial state\n const protocolVersion =\n document.header.protocolVersions?.[\"base-reducer\"] ?? 1;\n document = module.reducer(document, operation.action, undefined, {\n skip: operation.skip,\n protocolVersion,\n });\n }\n\n const reachedTarget =\n targetRevision !== undefined &&\n result.results.some((op) => op.index >= targetRevision);\n hasMorePages = Boolean(result.nextCursor) && !reachedTarget;\n\n if (hasMorePages) {\n cursor = result.nextCursor;\n }\n } catch (err) {\n // Wrap errors with context to include document ID for debugging\n throw new Error(\n `Failed to rebuild document ${documentId}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n } while (hasMorePages);\n\n // we let these errors bubble up to jobs\n const revisions = await this.operationStore.getRevisions(\n documentId,\n branch,\n signal,\n );\n document.header.revision = revisions.revision;\n document.header.lastModifiedAtUtcIso = revisions.latestTimestamp;\n\n return document;\n }\n\n private async warmMissRebuild(\n baseDocument: PHDocument,\n baseRevision: number,\n documentId: string,\n scope: string,\n branch: string,\n targetRevision: number | undefined,\n signal?: AbortSignal,\n ): Promise<PHDocument> {\n const documentType = baseDocument.header.documentType;\n const module = this.registry.getModule(documentType);\n let document = baseDocument;\n\n try {\n const pagedResults = await this.operationStore.getSince(\n documentId,\n scope,\n branch,\n baseRevision,\n undefined,\n undefined,\n signal,\n );\n\n for (const operation of pagedResults.results) {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n if (targetRevision !== undefined && operation.index > targetRevision) {\n break;\n }\n\n // Fail-fast: if reducer throws, error propagates immediately without caching partial state\n const protocolVersion =\n document.header.protocolVersions?.[\"base-reducer\"] ?? 1;\n document = module.reducer(document, operation.action, undefined, {\n skip: operation.skip,\n protocolVersion,\n });\n\n if (\n targetRevision !== undefined &&\n operation.index === targetRevision\n ) {\n break;\n }\n }\n } catch (err) {\n // Wrap errors with context to include document ID for debugging\n throw new Error(\n `Failed to rebuild document ${documentId}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n\n // we let these errors bubble up to jobs\n const revisions = await this.operationStore.getRevisions(\n documentId,\n branch,\n signal,\n );\n document.header.revision = revisions.revision;\n document.header.lastModifiedAtUtcIso = revisions.latestTimestamp;\n\n return document;\n }\n\n private findNearestOlderSnapshot(\n snapshots: CachedSnapshot[],\n targetRevision: number,\n ): CachedSnapshot | undefined {\n let nearest: CachedSnapshot | undefined = undefined;\n\n for (const snapshot of snapshots) {\n if (snapshot.revision < targetRevision) {\n if (!nearest || snapshot.revision > nearest.revision) {\n nearest = snapshot;\n }\n }\n }\n\n return nearest;\n }\n\n private makeStreamKey(\n documentId: string,\n scope: string,\n branch: string,\n ): string {\n return `${documentId}:${scope}:${branch}`;\n }\n\n private getOrCreateStream(key: string): DocumentStream {\n let stream = this.streams.get(key);\n\n if (!stream) {\n if (this.streams.size >= this.config.maxDocuments) {\n const evictKey = this.lruTracker.evict();\n if (evictKey) {\n this.streams.delete(evictKey);\n }\n }\n\n stream = {\n key,\n ringBuffer: new RingBuffer<CachedSnapshot>(this.config.ringBufferSize),\n };\n this.streams.set(key, stream);\n }\n\n this.lruTracker.touch(key);\n return stream;\n }\n\n private isKeyframeRevision(revision: number): boolean {\n return revision > 0 && revision % this.config.keyframeInterval === 0;\n }\n}\n","import type { IEventBus } from \"./interfaces.js\";\nimport type { Subscriber, Unsubscribe } from \"./types.js\";\nimport { EventBusAggregateError } from \"./types.js\";\n\nexport class EventBus implements IEventBus {\n public readonly eventTypeToSubscribers = new Map<number, Subscriber[]>();\n\n subscribe<K>(\n type: number,\n subscriber: (type: number, event: K) => void | Promise<void>,\n ): Unsubscribe {\n let list = this.eventTypeToSubscribers.get(type);\n if (!list) {\n list = [];\n this.eventTypeToSubscribers.set(type, list);\n }\n list.push(subscriber as Subscriber);\n\n let done = false;\n return () => {\n if (done) {\n return;\n }\n done = true;\n\n const arr = this.eventTypeToSubscribers.get(type);\n if (!arr) {\n return;\n }\n\n const idx = arr.indexOf(subscriber as Subscriber);\n if (idx !== -1) {\n arr.splice(idx, 1);\n }\n if (arr.length === 0) {\n this.eventTypeToSubscribers.delete(type);\n }\n };\n }\n\n async emit(type: number, data: any): Promise<void> {\n const list = this.eventTypeToSubscribers.get(type);\n if (!list || list.length === 0) {\n return;\n }\n\n // Snapshot ensures subscribers added/removed during emit don't affect this cycle.\n const snapshot = list.slice();\n\n // Call each subscriber sequentially and collect any errors\n const errors: any[] = [];\n for (const fn of snapshot) {\n try {\n await Promise.resolve(fn(type, data));\n } catch (err) {\n errors.push(err);\n }\n }\n\n // If any errors occurred, throw an aggregate error containing all of them\n if (errors.length > 0) {\n throw new EventBusAggregateError(errors);\n }\n }\n}\n","import type { Kysely, Transaction } from \"kysely\";\nimport type { CollectionMembershipCache } from \"../cache/collection-membership-cache.js\";\nimport type { DocumentMetaCache } from \"../cache/document-meta-cache.js\";\nimport type { KyselyOperationIndex } from \"../cache/kysely-operation-index.js\";\nimport type { KyselyWriteCache } from \"../cache/kysely-write-cache.js\";\nimport type { IOperationIndex } from \"../cache/operation-index-types.js\";\nimport type { IWriteCache } from \"../cache/write/interfaces.js\";\nimport type { IDocumentMetaCache } from \"../cache/document-meta-cache-types.js\";\nimport type { ICollectionMembershipCache } from \"../cache/collection-membership-cache.js\";\nimport type { IOperationStore } from \"../storage/interfaces.js\";\nimport type { KyselyOperationStore } from \"../storage/kysely/store.js\";\nimport type { KyselyKeyframeStore } from \"../storage/kysely/keyframe-store.js\";\nimport type { Database } from \"../storage/kysely/types.js\";\n\nexport interface ExecutionStores {\n operationStore: IOperationStore;\n operationIndex: IOperationIndex;\n writeCache: IWriteCache;\n documentMetaCache: IDocumentMetaCache;\n collectionMembershipCache: ICollectionMembershipCache;\n}\n\nexport interface IExecutionScope {\n run<T>(\n fn: (stores: ExecutionStores) => Promise<T>,\n signal?: AbortSignal,\n ): Promise<T>;\n}\n\nexport class DefaultExecutionScope implements IExecutionScope {\n constructor(\n private operationStore: IOperationStore,\n private operationIndex: IOperationIndex,\n private writeCache: IWriteCache,\n private documentMetaCache: IDocumentMetaCache,\n private collectionMembershipCache: ICollectionMembershipCache,\n ) {}\n\n async run<T>(\n fn: (stores: ExecutionStores) => Promise<T>,\n signal?: AbortSignal,\n ): Promise<T> {\n signal?.throwIfAborted();\n return fn({\n operationStore: this.operationStore,\n operationIndex: this.operationIndex,\n writeCache: this.writeCache,\n documentMetaCache: this.documentMetaCache,\n collectionMembershipCache: this.collectionMembershipCache,\n });\n }\n}\n\nexport class KyselyExecutionScope implements IExecutionScope {\n constructor(\n private db: Kysely<Database>,\n private operationStore: KyselyOperationStore,\n private operationIndex: KyselyOperationIndex,\n private keyframeStore: KyselyKeyframeStore,\n private writeCache: KyselyWriteCache,\n private documentMetaCache: DocumentMetaCache,\n private collectionMembershipCache: CollectionMembershipCache,\n ) {}\n\n async run<T>(\n fn: (stores: ExecutionStores) => Promise<T>,\n signal?: AbortSignal,\n ): Promise<T> {\n signal?.throwIfAborted();\n return this.db.transaction().execute(async (trx: Transaction<Database>) => {\n const scopedOperationStore = this.operationStore.withTransaction(trx);\n const scopedOperationIndex = this.operationIndex.withTransaction(trx);\n const scopedKeyframeStore = this.keyframeStore.withTransaction(trx);\n return fn({\n operationStore: scopedOperationStore,\n operationIndex: scopedOperationIndex,\n writeCache: this.writeCache.withScopedStores(\n scopedOperationStore,\n scopedKeyframeStore,\n ),\n documentMetaCache:\n this.documentMetaCache.withScopedStore(scopedOperationStore),\n collectionMembershipCache:\n this.collectionMembershipCache.withScopedIndex(scopedOperationIndex),\n });\n });\n }\n}\n","type OperationIndex = {\n index: number;\n skip: number;\n id: string;\n timestampUtcMs: string;\n action?: {\n id?: string;\n type?: string;\n };\n};\n\nconst STRICT_ORDER_ACTION_TYPES = new Set([\n \"CREATE_DOCUMENT\",\n \"DELETE_DOCUMENT\",\n \"UPGRADE_DOCUMENT\",\n \"ADD_RELATIONSHIP\",\n \"REMOVE_RELATIONSHIP\",\n \"UPDATE_RELATIONSHIP\",\n \"ADD_FOLDER\",\n \"UPDATE_FOLDER\",\n \"REMOVE_FOLDER\",\n]);\n\n/**\n * Sorts operations by index and skip number.\n * [0:0 2:0 1:0 3:3 3:1] => [0:0 1:0 2:0 3:1 3:3]\n */\nexport function sortOperations<TOpIndex extends OperationIndex>(\n operations: TOpIndex[],\n): TOpIndex[] {\n return operations\n .slice()\n .sort((a, b) => a.skip - b.skip)\n .sort((a, b) => a.index - b.index);\n}\n\n/**\n * Reshuffles operations by timestamp, then applies deterministic tie-breaking.\n * Used for merging concurrent operations from different branches.\n *\n * For strict document-structure actions (e.g., CREATE_DOCUMENT/UPGRADE_DOCUMENT),\n * logical index (index - skip) is prioritized to preserve causal replay order.\n *\n * For other actions, action ID is prioritized to ensure a canonical cross-reactor order\n * for concurrent operations that may have diverged local indices due to prior reshuffles.\n * Logical index and operation ID are then used as deterministic tie-breakers.\n *\n * Example:\n * [0:0, 1:0, 2:0, A3:0, A4:0, A5:0] + [0:0, 1:0, 2:0, B3:0, B4:2, B5:0]\n * GC => [0:0, 1:0, 2:0, A3:0, A4:0, A5:0] + [0:0, 1:0, B4:2, B5:0]\n * Split => [0:0, 1:0] + [2:0, A3:0, A4:0, A5:0] + [B4:2, B5:0]\n * Reshuffle(6:4) => [6:4, 7:0, 8:0, 9:0, 10:0, 11:0]\n * merge => [0:0, 1:0, 6:4, 7:0, 8:0, 9:0, 10:0, 11:0]\n */\nexport function reshuffleByTimestamp<TOp extends OperationIndex>(\n startIndex: { index: number; skip: number },\n opsA: TOp[],\n opsB: TOp[],\n): TOp[] {\n return [...opsA, ...opsB]\n .sort((a, b) => {\n const timestampDiff =\n new Date(a.timestampUtcMs).getTime() -\n new Date(b.timestampUtcMs).getTime();\n if (timestampDiff !== 0) {\n return timestampDiff;\n }\n\n const shouldPrioritizeLogicalIndex =\n STRICT_ORDER_ACTION_TYPES.has(a.action?.type ?? \"\") ||\n STRICT_ORDER_ACTION_TYPES.has(b.action?.type ?? \"\");\n const logicalIndexDiff = a.index - a.skip - (b.index - b.skip);\n\n if (shouldPrioritizeLogicalIndex) {\n if (logicalIndexDiff !== 0) {\n return logicalIndexDiff;\n }\n }\n\n const actionIdDiff = (a.action?.id ?? \"\").localeCompare(\n b.action?.id ?? \"\",\n );\n if (actionIdDiff !== 0) {\n return actionIdDiff;\n }\n\n if (!shouldPrioritizeLogicalIndex && logicalIndexDiff !== 0) {\n return logicalIndexDiff;\n }\n\n return a.id.localeCompare(b.id);\n })\n .map((op, i) => ({\n ...op,\n index: startIndex.index + i,\n skip: i === 0 ? startIndex.skip : 0,\n }));\n}\n\n/**\n * Reshuffles operations by timestamp first, then by original index value.\n * Used for merging concurrent operations while preserving index ordering for operations with same timestamp.\n */\nexport function reshuffleByTimestampAndIndex<TOp extends OperationIndex>(\n startIndex: { index: number; skip: number },\n opsA: TOp[],\n opsB: TOp[],\n): TOp[] {\n return [...opsA, ...opsB]\n .sort((a, b) => {\n const indexDiff = a.index - b.index;\n if (indexDiff !== 0) {\n return indexDiff;\n }\n const timestampDiff =\n new Date(a.timestampUtcMs).getTime() -\n new Date(b.timestampUtcMs).getTime();\n if (timestampDiff !== 0) {\n return timestampDiff;\n }\n return a.id.localeCompare(b.id);\n })\n .map((op, i) => ({\n ...op,\n index: startIndex.index + i,\n skip: i === 0 ? startIndex.skip : 0,\n }));\n}\n","import type {\n Operation,\n OperationWithContext,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Generated, Insertable, Selectable, Updateable } from \"kysely\";\nimport type { PagedResults, PagingOptions } from \"../shared/types.js\";\nimport type { ViewFilter } from \"../storage/interfaces.js\";\n\nexport type OperationIndexEntry = Operation & {\n ordinal?: number;\n documentId: string;\n documentType: string;\n branch: string;\n scope: string;\n sourceRemote: string;\n};\n\nexport interface IOperationIndexTxn {\n createCollection(collectionId: string): void;\n addToCollection(collectionId: string, documentId: string): void;\n removeFromCollection(collectionId: string, documentId: string): void;\n write(operations: OperationIndexEntry[]): void;\n}\n\nexport interface IOperationIndex {\n start(): IOperationIndexTxn;\n commit(txn: IOperationIndexTxn, signal?: AbortSignal): Promise<number[]>;\n find(\n collectionId: string,\n cursor?: number,\n view?: ViewFilter,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationIndexEntry>>;\n /**\n * Get all operations for a specific document, ordered by ordinal.\n * Used for retroactive sync when a document is added to a collection.\n */\n get(\n documentId: string,\n view?: ViewFilter,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationIndexEntry>>;\n getSinceOrdinal(\n ordinal: number,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationWithContext>>;\n getLatestTimestampForCollection(\n collectionId: string,\n signal?: AbortSignal,\n ): Promise<string | null>;\n /**\n * Get all collection memberships for the given document IDs.\n * Returns a map of documentId to array of collection IDs.\n */\n getCollectionsForDocuments(\n documentIds: string[],\n ): Promise<Record<string, string[]>>;\n}\n\nexport interface DocumentCollectionTable {\n documentId: string;\n collectionId: string;\n joinedOrdinal: bigint;\n leftOrdinal: bigint | null;\n}\n\nexport interface OperationIndexOperationTable {\n ordinal: Generated<number>;\n opId: string;\n documentId: string;\n documentType: string;\n scope: string;\n branch: string;\n timestampUtcMs: string;\n writeTimestampUtcMs: Generated<Date>;\n index: number;\n skip: number;\n hash: string;\n action: unknown;\n sourceRemote: Generated<string>;\n}\n\nexport type DocumentCollectionRow = Selectable<DocumentCollectionTable>;\nexport type InsertableDocumentCollection = Insertable<DocumentCollectionTable>;\nexport type UpdateableDocumentCollection = Updateable<DocumentCollectionTable>;\n\nexport type OperationIndexOperationRow =\n Selectable<OperationIndexOperationTable>;\nexport type InsertableOperationIndexOperation =\n Insertable<OperationIndexOperationTable>;\nexport type UpdateableOperationIndexOperation =\n Updateable<OperationIndexOperationTable>;\n\nexport function driveCollectionId(branch: string, driveId: string): string {\n return `drive.${branch}.${driveId}`;\n}\n","import type {\n Action,\n CreateDocumentAction,\n DeleteDocumentActionInput,\n Operation,\n PHDocument,\n UpgradeDocumentAction,\n UpgradeDocumentActionInput,\n UpgradeTransition,\n} from \"@powerhousedao/shared/document-model\";\n\ninterface RelationshipActionShape {\n sourceId: string;\n targetId: string;\n relationshipType: string;\n}\n\ntype RelationshipJobResult = JobResult & {\n operationsWithContext?: Array<{\n operation: Operation;\n context: {\n documentId: string;\n scope: string;\n branch: string;\n documentType: string;\n };\n }>;\n};\n\ninterface RelationshipPostWriteArgs {\n indexTxn: IOperationIndexTxn;\n stores: ExecutionStores;\n sourceDoc: PHDocument;\n input: RelationshipActionShape;\n job: Job;\n}\nimport type { ILogger } from \"document-model\";\nimport type { IOperationIndexTxn } from \"../cache/operation-index-types.js\";\nimport { driveCollectionId } from \"../cache/operation-index-types.js\";\nimport type { Job } from \"../queue/types.js\";\nimport type { IDocumentModelRegistry } from \"../registry/interfaces.js\";\nimport { DocumentDeletedError } from \"../shared/errors.js\";\nimport type { ExecutionStores } from \"./execution-scope.js\";\nimport type { JobResult } from \"./types.js\";\nimport {\n applyDeleteDocumentAction,\n applyUpgradeDocumentAction,\n buildErrorResult,\n buildSuccessResult,\n createDocumentFromAction,\n createOperation,\n getNextIndexForScope,\n updateDocumentRevision,\n} from \"./util.js\";\n\nexport class DocumentActionHandler {\n constructor(\n private registry: IDocumentModelRegistry,\n private logger: ILogger,\n private driveContainerTypes: ReadonlySet<string>,\n ) {}\n\n async execute(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n skip: number = 0,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<\n JobResult & {\n operationsWithContext?: Array<{\n operation: Operation;\n context: {\n documentId: string;\n scope: string;\n branch: string;\n documentType: string;\n };\n }>;\n }\n > {\n switch (action.type) {\n case \"CREATE_DOCUMENT\":\n return this.executeCreate(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n skip,\n sourceRemote,\n signal,\n );\n case \"DELETE_DOCUMENT\":\n return this.executeDelete(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n sourceRemote,\n signal,\n );\n case \"UPGRADE_DOCUMENT\":\n return this.executeUpgrade(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n skip,\n sourceRemote,\n signal,\n );\n case \"ADD_RELATIONSHIP\":\n return this.executeAddRelationship(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n sourceRemote,\n signal,\n );\n case \"REMOVE_RELATIONSHIP\":\n return this.executeRemoveRelationship(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n sourceRemote,\n signal,\n );\n case \"UPDATE_RELATIONSHIP\":\n return this.executeUpdateRelationship(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n sourceRemote,\n signal,\n );\n default:\n return buildErrorResult(\n job,\n new Error(`Unknown document action type: ${action.type}`),\n startTime,\n );\n }\n }\n\n private async executeCreate(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n skip: number = 0,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<\n JobResult & {\n operationsWithContext?: Array<{\n operation: Operation;\n context: {\n documentId: string;\n scope: string;\n branch: string;\n documentType: string;\n };\n }>;\n }\n > {\n if (job.scope !== \"document\") {\n return {\n job,\n success: false,\n error: new Error(\n `CREATE_DOCUMENT must be in \"document\" scope, got \"${job.scope}\"`,\n ),\n duration: Date.now() - startTime,\n };\n }\n\n const document = createDocumentFromAction(action as CreateDocumentAction);\n\n let operation = createOperation(action, 0, skip, {\n documentId: document.header.id,\n scope: job.scope,\n branch: job.branch,\n });\n\n const resultingStateObj: Record<string, unknown> = {\n header: document.header,\n ...document.state,\n };\n const resultingState = JSON.stringify(resultingStateObj);\n\n const writeResult = await this.writeOperationToStore(\n document.header.id,\n document.header.documentType,\n job.scope,\n job.branch,\n operation,\n job,\n startTime,\n stores,\n signal,\n );\n if (!Array.isArray(writeResult)) {\n return writeResult;\n }\n operation = writeResult[0];\n\n updateDocumentRevision(document, job.scope, operation.index);\n\n document.operations = {\n ...document.operations,\n [job.scope]: [...(document.operations[job.scope] ?? []), operation],\n };\n\n stores.writeCache.putState(\n document.header.id,\n job.scope,\n job.branch,\n operation.index,\n document,\n );\n\n indexTxn.write([\n {\n ...operation,\n documentId: document.header.id,\n documentType: document.header.documentType,\n branch: job.branch,\n scope: job.scope,\n sourceRemote,\n },\n ]);\n\n if (this.driveContainerTypes.has(document.header.documentType)) {\n const collectionId = driveCollectionId(job.branch, document.header.id);\n indexTxn.createCollection(collectionId);\n indexTxn.addToCollection(collectionId, document.header.id);\n }\n\n stores.documentMetaCache.putDocumentMeta(document.header.id, job.branch, {\n state: document.state.document,\n documentType: document.header.documentType,\n documentScopeRevision: 1,\n });\n\n return buildSuccessResult(\n job,\n operation,\n document.header.id,\n document.header.documentType,\n resultingState,\n startTime,\n );\n }\n\n private async executeDelete(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<\n JobResult & {\n operationsWithContext?: Array<{\n operation: Operation;\n context: {\n documentId: string;\n scope: string;\n branch: string;\n documentType: string;\n };\n }>;\n }\n > {\n const input = action.input as DeleteDocumentActionInput;\n\n if (!input.documentId) {\n return buildErrorResult(\n job,\n new Error(\"DELETE_DOCUMENT action requires a documentId in input\"),\n startTime,\n );\n }\n\n const documentId = input.documentId;\n\n let document: PHDocument;\n try {\n document = await stores.writeCache.getState(\n documentId,\n job.scope,\n job.branch,\n undefined,\n signal,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n new Error(\n `Failed to fetch document before deletion: ${error instanceof Error ? error.message : String(error)}`,\n ),\n startTime,\n );\n }\n\n const documentState = document.state.document;\n if (documentState.isDeleted) {\n return buildErrorResult(\n job,\n new DocumentDeletedError(documentId, documentState.deletedAtUtcIso),\n startTime,\n );\n }\n\n const nextIndex = getNextIndexForScope(document, job.scope);\n\n let operation = createOperation(action, nextIndex, 0, {\n documentId,\n scope: job.scope,\n branch: job.branch,\n });\n\n applyDeleteDocumentAction(document, action as never);\n\n const resultingStateObj: Record<string, unknown> = {\n header: document.header,\n document: document.state.document,\n };\n const resultingState = JSON.stringify(resultingStateObj);\n\n const writeResult = await this.writeOperationToStore(\n documentId,\n document.header.documentType,\n job.scope,\n job.branch,\n operation,\n job,\n startTime,\n stores,\n signal,\n );\n if (!Array.isArray(writeResult)) {\n return writeResult;\n }\n operation = writeResult[0];\n\n updateDocumentRevision(document, job.scope, operation.index);\n\n document.operations = {\n ...document.operations,\n [job.scope]: [...(document.operations[job.scope] ?? []), operation],\n };\n\n stores.writeCache.putState(\n documentId,\n job.scope,\n job.branch,\n operation.index,\n document,\n );\n\n indexTxn.write([\n {\n ...operation,\n documentId: documentId,\n documentType: document.header.documentType,\n branch: job.branch,\n scope: job.scope,\n sourceRemote,\n },\n ]);\n\n stores.documentMetaCache.putDocumentMeta(documentId, job.branch, {\n state: document.state.document,\n documentType: document.header.documentType,\n documentScopeRevision: operation.index + 1,\n });\n\n return buildSuccessResult(\n job,\n operation,\n documentId,\n document.header.documentType,\n resultingState,\n startTime,\n );\n }\n\n private async executeUpgrade(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n skip: number = 0,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<\n JobResult & {\n operationsWithContext?: Array<{\n operation: Operation;\n context: {\n documentId: string;\n scope: string;\n branch: string;\n documentType: string;\n };\n }>;\n }\n > {\n const input = action.input as UpgradeDocumentActionInput;\n\n if (!input.documentId) {\n return buildErrorResult(\n job,\n new Error(\"UPGRADE_DOCUMENT action requires a documentId in input\"),\n startTime,\n );\n }\n\n const documentId = input.documentId;\n\n const fromVersion = input.fromVersion;\n const toVersion = input.toVersion;\n\n let document: PHDocument;\n try {\n document = await stores.writeCache.getState(\n documentId,\n job.scope,\n job.branch,\n undefined,\n signal,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n new Error(\n `Failed to fetch document for upgrade: ${error instanceof Error ? error.message : String(error)}`,\n ),\n startTime,\n );\n }\n\n const documentState = document.state.document;\n if (documentState.isDeleted) {\n return buildErrorResult(\n job,\n new DocumentDeletedError(documentId, documentState.deletedAtUtcIso),\n startTime,\n );\n }\n\n const nextIndex = getNextIndexForScope(document, job.scope);\n\n let upgradePath: UpgradeTransition[] | undefined;\n if (fromVersion > 0 && fromVersion < toVersion) {\n try {\n upgradePath = this.registry.computeUpgradePath(\n document.header.documentType,\n fromVersion,\n toVersion,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n );\n }\n }\n\n if (fromVersion === toVersion && fromVersion > 0) {\n return {\n job,\n success: true,\n operations: [],\n operationsWithContext: [],\n duration: Date.now() - startTime,\n };\n }\n\n try {\n document = applyUpgradeDocumentAction(\n document,\n action as UpgradeDocumentAction,\n upgradePath,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n );\n }\n\n let operation = createOperation(action, nextIndex, skip, {\n documentId,\n scope: job.scope,\n branch: job.branch,\n });\n\n const resultingStateObj: Record<string, unknown> = {\n header: document.header,\n ...document.state,\n };\n const resultingState = JSON.stringify(resultingStateObj);\n\n const writeResult = await this.writeOperationToStore(\n documentId,\n document.header.documentType,\n job.scope,\n job.branch,\n operation,\n job,\n startTime,\n stores,\n signal,\n );\n if (!Array.isArray(writeResult)) {\n return writeResult;\n }\n operation = writeResult[0];\n\n updateDocumentRevision(document, job.scope, operation.index);\n\n document.operations = {\n ...document.operations,\n [job.scope]: [...(document.operations[job.scope] ?? []), operation],\n };\n\n stores.writeCache.putState(\n documentId,\n job.scope,\n job.branch,\n operation.index,\n document,\n );\n\n indexTxn.write([\n {\n ...operation,\n documentId: documentId,\n documentType: document.header.documentType,\n branch: job.branch,\n scope: job.scope,\n sourceRemote,\n },\n ]);\n\n stores.documentMetaCache.putDocumentMeta(documentId, job.branch, {\n state: document.state.document,\n documentType: document.header.documentType,\n documentScopeRevision: operation.index + 1,\n });\n\n return buildSuccessResult(\n job,\n operation,\n documentId,\n document.header.documentType,\n resultingState,\n startTime,\n );\n }\n\n private executeAddRelationship(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<RelationshipJobResult> {\n return this.withRelationshipAction(\n \"ADD_RELATIONSHIP\",\n job,\n action,\n startTime,\n indexTxn,\n stores,\n sourceRemote,\n signal,\n (input) =>\n input.sourceId === input.targetId\n ? new Error(\n \"ADD_RELATIONSHIP: sourceId and targetId cannot be the same (self-relationships not allowed)\",\n )\n : null,\n ({ indexTxn: txn, stores: s, sourceDoc, input, job: j }) => {\n if (this.driveContainerTypes.has(sourceDoc.header.documentType)) {\n const collectionId = driveCollectionId(j.branch, input.sourceId);\n txn.addToCollection(collectionId, input.targetId);\n s.collectionMembershipCache.invalidate(input.targetId);\n }\n },\n );\n }\n\n private executeRemoveRelationship(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<RelationshipJobResult> {\n return this.withRelationshipAction(\n \"REMOVE_RELATIONSHIP\",\n job,\n action,\n startTime,\n indexTxn,\n stores,\n sourceRemote,\n signal,\n null,\n ({ indexTxn: txn, stores: s, sourceDoc, input, job: j }) => {\n if (this.driveContainerTypes.has(sourceDoc.header.documentType)) {\n const collectionId = driveCollectionId(j.branch, input.sourceId);\n txn.removeFromCollection(collectionId, input.targetId);\n s.collectionMembershipCache.invalidate(input.targetId);\n }\n },\n );\n }\n\n private executeUpdateRelationship(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<RelationshipJobResult> {\n return this.withRelationshipAction(\n \"UPDATE_RELATIONSHIP\",\n job,\n action,\n startTime,\n indexTxn,\n stores,\n sourceRemote,\n signal,\n null,\n null,\n );\n }\n\n private async withRelationshipAction(\n actionTypeName: string,\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n sourceRemote: string,\n signal: AbortSignal | undefined,\n preValidate: ((input: RelationshipActionShape) => Error | null) | null,\n postWrite: ((args: RelationshipPostWriteArgs) => void) | null,\n ): Promise<RelationshipJobResult> {\n if (job.scope !== \"document\") {\n return buildErrorResult(\n job,\n new Error(\n `${actionTypeName} must be in \"document\" scope, got \"${job.scope}\"`,\n ),\n startTime,\n );\n }\n\n const input = action.input as RelationshipActionShape;\n\n if (!input.sourceId || !input.targetId || !input.relationshipType) {\n return buildErrorResult(\n job,\n new Error(\n `${actionTypeName} action requires sourceId, targetId, and relationshipType in input`,\n ),\n startTime,\n );\n }\n\n if (preValidate !== null) {\n const validationError = preValidate(input);\n if (validationError !== null) {\n return buildErrorResult(job, validationError, startTime);\n }\n }\n\n let sourceDoc: PHDocument;\n try {\n sourceDoc = await stores.writeCache.getState(\n input.sourceId,\n \"document\",\n job.branch,\n undefined,\n signal,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n new Error(\n `${actionTypeName}: source document ${input.sourceId} not found: ${error instanceof Error ? error.message : String(error)}`,\n ),\n startTime,\n );\n }\n\n const nextIndex = getNextIndexForScope(sourceDoc, job.scope);\n let operation = createOperation(action, nextIndex, 0, {\n documentId: input.sourceId,\n scope: job.scope,\n branch: job.branch,\n });\n\n const writeResult = await this.writeOperationToStore(\n input.sourceId,\n sourceDoc.header.documentType,\n job.scope,\n job.branch,\n operation,\n job,\n startTime,\n stores,\n signal,\n );\n if (!Array.isArray(writeResult)) {\n return writeResult;\n }\n operation = writeResult[0];\n\n sourceDoc.header.lastModifiedAtUtcIso =\n operation.timestampUtcMs || new Date().toISOString();\n updateDocumentRevision(sourceDoc, job.scope, operation.index);\n sourceDoc.operations = {\n ...sourceDoc.operations,\n [job.scope]: [...(sourceDoc.operations[job.scope] ?? []), operation],\n };\n\n const scopeState = (sourceDoc.state as Record<string, unknown>)[job.scope];\n const resultingStateObj: Record<string, unknown> = {\n header: structuredClone(sourceDoc.header),\n [job.scope]: scopeState === undefined ? {} : structuredClone(scopeState),\n };\n const resultingState = JSON.stringify(resultingStateObj);\n\n stores.writeCache.putState(\n input.sourceId,\n job.scope,\n job.branch,\n operation.index,\n sourceDoc,\n );\n\n indexTxn.write([\n {\n ...operation,\n documentId: input.sourceId,\n documentType: sourceDoc.header.documentType,\n branch: job.branch,\n scope: job.scope,\n sourceRemote,\n },\n ]);\n\n if (postWrite !== null) {\n postWrite({ indexTxn, stores, sourceDoc, input, job });\n }\n\n stores.documentMetaCache.putDocumentMeta(input.sourceId, job.branch, {\n state: sourceDoc.state.document,\n documentType: sourceDoc.header.documentType,\n documentScopeRevision: operation.index + 1,\n });\n\n return buildSuccessResult(\n job,\n operation,\n input.sourceId,\n sourceDoc.header.documentType,\n resultingState,\n startTime,\n );\n }\n\n private async writeOperationToStore(\n documentId: string,\n documentType: string,\n scope: string,\n branch: string,\n operation: Operation,\n job: Job,\n startTime: number,\n stores: ExecutionStores,\n signal?: AbortSignal,\n ): Promise<Operation[] | JobResult> {\n let storedOperations: Operation[];\n\n try {\n storedOperations = await stores.operationStore.apply(\n documentId,\n documentType,\n scope,\n branch,\n operation.index,\n (txn) => {\n txn.addOperations(operation);\n },\n signal,\n );\n } catch (error) {\n this.logger.error(\n \"Error writing @Operation to IOperationStore: @Error\",\n operation,\n error,\n );\n\n stores.writeCache.invalidate(documentId, scope, branch);\n\n return {\n job,\n success: false,\n error: new Error(\n `Failed to write operation to IOperationStore: ${error instanceof Error ? error.message : String(error)}`,\n ),\n duration: Date.now() - startTime,\n };\n }\n\n return storedOperations;\n }\n}\n","import type { Action, Operation } from \"@powerhousedao/shared/document-model\";\nimport { deriveOperationId } from \"@powerhousedao/shared/document-model\";\nimport { InvalidSignatureError } from \"../shared/errors.js\";\nimport type { SignatureVerificationHandler } from \"../signer/types.js\";\n\nexport class SignatureVerifier {\n constructor(private verifier?: SignatureVerificationHandler) {}\n\n async verifyActions(\n documentId: string,\n branch: string,\n actions: Action[],\n ): Promise<void> {\n if (!this.verifier) {\n return;\n }\n\n for (const action of actions) {\n const signer = action.context?.signer;\n\n if (!signer) {\n continue;\n }\n\n if (signer.signatures.length === 0) {\n throw new InvalidSignatureError(\n documentId,\n `Action ${action.id} has signer but no signatures`,\n );\n }\n\n const publicKey = signer.app.key;\n\n let isValid: boolean;\n\n try {\n const tempOperation: Operation = {\n id: deriveOperationId(documentId, action.scope, branch, action.id),\n index: 0,\n timestampUtcMs: action.timestampUtcMs || new Date().toISOString(),\n hash: \"\",\n skip: 0,\n action: action,\n };\n\n isValid = await this.verifier(tempOperation, publicKey);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new InvalidSignatureError(\n documentId,\n `Action ${action.id} verification failed: ${errorMessage}`,\n );\n }\n\n if (!isValid) {\n throw new InvalidSignatureError(\n documentId,\n `Action ${action.id} signature verification returned false`,\n );\n }\n }\n }\n\n async verifyOperations(\n documentId: string,\n operations: Operation[],\n ): Promise<void> {\n if (!this.verifier) {\n return;\n }\n\n for (let i = 0; i < operations.length; i++) {\n const operation = operations[i];\n const signer = operation.action.context?.signer;\n\n if (!signer) {\n continue;\n }\n\n if (signer.signatures.length === 0) {\n throw new InvalidSignatureError(\n documentId,\n `Operation ${operation.id} at index ${operation.index} has signer but no signatures`,\n );\n }\n\n const publicKey = signer.app.key;\n\n let isValid: boolean;\n\n try {\n isValid = await this.verifier(operation, publicKey);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new InvalidSignatureError(\n documentId,\n `Operation ${operation.id} at index ${operation.index} verification failed: ${errorMessage}`,\n );\n }\n\n if (!isValid) {\n throw new InvalidSignatureError(\n documentId,\n `Operation ${operation.id} at index ${operation.index} signature verification returned false`,\n );\n }\n }\n }\n}\n","import type {\n Action,\n DocumentModelModule,\n Operation,\n OperationWithContext,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { isUndoRedo } from \"@powerhousedao/shared/document-model\";\nimport type { ILogger } from \"document-model\";\nimport type { ICollectionMembershipCache } from \"../cache/collection-membership-cache.js\";\nimport type { IDocumentMetaCache } from \"../cache/document-meta-cache-types.js\";\nimport type {\n IOperationIndex,\n IOperationIndexTxn,\n} from \"../cache/operation-index-types.js\";\nimport type { IWriteCache } from \"../cache/write/interfaces.js\";\nimport type { IEventBus } from \"../events/interfaces.js\";\nimport { ReactorEventTypes, type JobWriteReadyEvent } from \"../events/types.js\";\nimport type { Job } from \"../queue/types.js\";\nimport type { IDocumentModelRegistry } from \"../registry/interfaces.js\";\nimport { DocumentDeletedError } from \"../shared/errors.js\";\nimport { yieldToMain } from \"../shared/utils.js\";\nimport type { SignatureVerificationHandler } from \"../signer/types.js\";\nimport type { IOperationStore } from \"../storage/interfaces.js\";\nimport { reshuffleByTimestamp } from \"../utils/reshuffle.js\";\nimport { DocumentActionHandler } from \"./document-action-handler.js\";\nimport type { ExecutionStores, IExecutionScope } from \"./execution-scope.js\";\nimport { DefaultExecutionScope } from \"./execution-scope.js\";\nimport type { IJobExecutor } from \"./interfaces.js\";\nimport { SignatureVerifier } from \"./signature-verifier.js\";\nimport type { JobExecutorConfig, JobResult } from \"./types.js\";\nimport { buildErrorResult } from \"./util.js\";\n\nconst MAX_SKIP_THRESHOLD = 1000;\n\nconst ISO_TIMESTAMP_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$/;\n\nfunction isValidISOTimestamp(value: string): boolean {\n if (!ISO_TIMESTAMP_REGEX.test(value)) {\n return false;\n }\n return !isNaN(new Date(value).getTime());\n}\n\ntype ProcessActionsResult = {\n success: boolean;\n generatedOperations: Operation[];\n operationsWithContext: OperationWithContext[];\n error?: Error;\n};\n\nconst documentScopeActions = [\n \"CREATE_DOCUMENT\",\n \"DELETE_DOCUMENT\",\n \"UPGRADE_DOCUMENT\",\n \"ADD_RELATIONSHIP\",\n \"REMOVE_RELATIONSHIP\",\n \"UPDATE_RELATIONSHIP\",\n];\n\n/**\n * Simple job executor that processes a job by applying actions through document model reducers.\n */\nexport class SimpleJobExecutor implements IJobExecutor {\n private config: Required<JobExecutorConfig>;\n private signatureVerifierModule: SignatureVerifier;\n private documentActionHandler: DocumentActionHandler;\n private executionScope: IExecutionScope;\n\n constructor(\n private logger: ILogger,\n private registry: IDocumentModelRegistry,\n private operationStore: IOperationStore,\n private eventBus: IEventBus,\n private writeCache: IWriteCache,\n private operationIndex: IOperationIndex,\n private documentMetaCache: IDocumentMetaCache,\n private collectionMembershipCache: ICollectionMembershipCache,\n private driveContainerTypes: ReadonlySet<string>,\n config: JobExecutorConfig,\n signatureVerifier?: SignatureVerificationHandler,\n executionScope?: IExecutionScope,\n ) {\n this.config = {\n maxSkipThreshold: config.maxSkipThreshold ?? MAX_SKIP_THRESHOLD,\n maxConcurrency: config.maxConcurrency ?? 1,\n jobTimeoutMs: config.jobTimeoutMs ?? 30000,\n retryBaseDelayMs: config.retryBaseDelayMs ?? 100,\n retryMaxDelayMs: config.retryMaxDelayMs ?? 5000,\n yieldDeadlineMs: config.yieldDeadlineMs ?? 50,\n };\n this.signatureVerifierModule = new SignatureVerifier(signatureVerifier);\n this.documentActionHandler = new DocumentActionHandler(\n registry,\n logger,\n driveContainerTypes,\n );\n this.executionScope =\n executionScope ??\n new DefaultExecutionScope(\n operationStore,\n operationIndex,\n writeCache,\n documentMetaCache,\n collectionMembershipCache,\n );\n }\n\n /**\n * Execute a single job by applying all its actions through the appropriate reducers.\n * Actions are processed sequentially in order.\n */\n async executeJob(job: Job, signal?: AbortSignal): Promise<JobResult> {\n const startTime = Date.now();\n\n // Track document IDs touched during execution for cache invalidation on rollback\n const touchedCacheEntries: Array<{\n documentId: string;\n scope: string;\n branch: string;\n }> = [];\n\n let pendingEvent: JobWriteReadyEvent | undefined;\n let result: JobResult;\n try {\n result = await this.executionScope.run(async (stores) => {\n const indexTxn = stores.operationIndex.start();\n\n if (job.kind === \"load\") {\n const loadResult = await this.executeLoadJob(\n job,\n startTime,\n indexTxn,\n stores,\n signal,\n );\n if (loadResult.success && loadResult.operationsWithContext) {\n for (const owc of loadResult.operationsWithContext) {\n touchedCacheEntries.push({\n documentId: owc.context.documentId,\n scope: owc.context.scope,\n branch: owc.context.branch,\n });\n }\n\n const ordinals = await stores.operationIndex.commit(\n indexTxn,\n signal,\n );\n\n for (let i = 0; i < loadResult.operationsWithContext.length; i++) {\n loadResult.operationsWithContext[i].context.ordinal = ordinals[i];\n }\n const collectionMemberships =\n loadResult.operationsWithContext.length > 0\n ? await this.getCollectionMembershipsForOperations(\n loadResult.operationsWithContext,\n stores,\n )\n : {};\n pendingEvent = {\n jobId: job.id,\n operations: loadResult.operationsWithContext,\n jobMeta: job.meta,\n collectionMemberships,\n };\n }\n return loadResult;\n }\n\n const actionResult = await this.processActions(\n job,\n job.actions,\n startTime,\n indexTxn,\n stores,\n undefined,\n undefined,\n \"\",\n signal,\n );\n\n if (!actionResult.success) {\n return {\n job,\n success: false as const,\n error: actionResult.error,\n duration: Date.now() - startTime,\n };\n }\n\n if (actionResult.operationsWithContext.length > 0) {\n for (const owc of actionResult.operationsWithContext) {\n touchedCacheEntries.push({\n documentId: owc.context.documentId,\n scope: owc.context.scope,\n branch: owc.context.branch,\n });\n }\n }\n\n const ordinals = await stores.operationIndex.commit(indexTxn, signal);\n\n if (actionResult.operationsWithContext.length > 0) {\n for (let i = 0; i < actionResult.operationsWithContext.length; i++) {\n actionResult.operationsWithContext[i].context.ordinal = ordinals[i];\n }\n const collectionMemberships =\n await this.getCollectionMembershipsForOperations(\n actionResult.operationsWithContext,\n stores,\n );\n pendingEvent = {\n jobId: job.id,\n operations: actionResult.operationsWithContext,\n jobMeta: job.meta,\n collectionMemberships,\n };\n }\n\n return {\n job,\n success: true as const,\n operations: actionResult.generatedOperations,\n operationsWithContext: actionResult.operationsWithContext,\n duration: Date.now() - startTime,\n };\n }, signal);\n } catch (error) {\n for (const entry of touchedCacheEntries) {\n this.writeCache.invalidate(entry.documentId, entry.scope, entry.branch);\n this.documentMetaCache.invalidate(entry.documentId, entry.branch);\n }\n throw error;\n }\n\n if (pendingEvent) {\n this.eventBus\n .emit(ReactorEventTypes.JOB_WRITE_READY, pendingEvent)\n .catch((error) => {\n this.logger.error(\n \"Failed to emit JOB_WRITE_READY event: @Event : @Error\",\n pendingEvent,\n error,\n );\n });\n }\n\n return result;\n }\n\n private async getCollectionMembershipsForOperations(\n operations: OperationWithContext[],\n stores: ExecutionStores,\n ): Promise<Record<string, string[]>> {\n const documentIds = [\n ...new Set(operations.map((op) => op.context.documentId)),\n ];\n return stores.collectionMembershipCache.getCollectionsForDocuments(\n documentIds,\n );\n }\n\n private async processActions(\n job: Job,\n actions: Action[],\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n skipValues?: number[],\n sourceOperations?: (Operation | undefined)[],\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<ProcessActionsResult> {\n const generatedOperations: Operation[] = [];\n const operationsWithContext: OperationWithContext[] = [];\n\n try {\n await this.signatureVerifierModule.verifyActions(\n job.documentId,\n job.branch,\n actions,\n );\n } catch (error) {\n return {\n success: false,\n generatedOperations,\n operationsWithContext,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n\n for (const action of actions) {\n if (\n action.timestampUtcMs &&\n !isValidISOTimestamp(action.timestampUtcMs)\n ) {\n return {\n success: false,\n generatedOperations,\n operationsWithContext,\n error: new Error(\n `Invalid timestamp \"${action.timestampUtcMs}\" on action ${action.type} (id: ${action.id})`,\n ),\n };\n }\n }\n\n let lastYield = performance.now();\n\n for (let actionIndex = 0; actionIndex < actions.length; actionIndex++) {\n const action = actions[actionIndex];\n const skip = skipValues?.[actionIndex] ?? 0;\n const sourceOperation = sourceOperations?.[actionIndex];\n\n const isDocumentAction = documentScopeActions.includes(action.type);\n const result = isDocumentAction\n ? await this.documentActionHandler.execute(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n skip,\n sourceRemote,\n signal,\n )\n : await this.executeRegularAction(\n job,\n action,\n startTime,\n indexTxn,\n stores,\n skip,\n sourceOperation,\n sourceRemote,\n signal,\n );\n\n const error = this.accumulateResultOrReturnError(\n result,\n generatedOperations,\n operationsWithContext,\n );\n if (error !== null) {\n return {\n success: false,\n generatedOperations,\n operationsWithContext,\n error: error.error,\n };\n }\n\n if (performance.now() - lastYield > this.config.yieldDeadlineMs) {\n await yieldToMain();\n lastYield = performance.now();\n\n if (signal?.aborted) {\n return {\n success: false,\n generatedOperations,\n operationsWithContext,\n error: new Error(\"Aborted\"),\n };\n }\n }\n }\n\n return {\n success: true,\n generatedOperations,\n operationsWithContext,\n };\n }\n\n private async executeRegularAction(\n job: Job,\n action: Action,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n skip: number = 0,\n sourceOperation?: Operation,\n sourceRemote: string = \"\",\n signal?: AbortSignal,\n ): Promise<\n JobResult & {\n operationsWithContext?: Array<{\n operation: Operation;\n context: {\n documentId: string;\n scope: string;\n branch: string;\n documentType: string;\n };\n }>;\n }\n > {\n let docMeta;\n try {\n docMeta = await stores.documentMetaCache.getDocumentMeta(\n job.documentId,\n job.branch,\n signal,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n );\n }\n\n if (docMeta.state.isDeleted) {\n return buildErrorResult(\n job,\n new DocumentDeletedError(job.documentId, docMeta.state.deletedAtUtcIso),\n startTime,\n );\n }\n\n // UNDO, REDO, PRUNE, and NOOP+skip need the full operation history to\n // replay state correctly. The write cache stores sliced documents (last\n // op per scope only), so invalidate before loading to force a cold-miss\n // rebuild. NOOP+skip arises in executeLoadJob when sync reshuffling\n // converts conflicting local ops to NOOPs.\n if (\n isUndoRedo(action) ||\n action.type === \"PRUNE\" ||\n (action.type === \"NOOP\" && skip > 0)\n ) {\n stores.writeCache.invalidate(job.documentId, job.scope, job.branch);\n }\n\n let document: PHDocument;\n try {\n document = await stores.writeCache.getState(\n job.documentId,\n job.scope,\n job.branch,\n undefined,\n signal,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n );\n }\n\n let module: DocumentModelModule;\n try {\n const moduleVersion =\n docMeta.state.version === 0 ? undefined : docMeta.state.version;\n module = this.registry.getModule(\n document.header.documentType,\n moduleVersion,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n );\n }\n\n let updatedDocument: PHDocument;\n try {\n const protocolVersion =\n document.header.protocolVersions?.[\"base-reducer\"] ?? 1;\n const reducerOptions = sourceOperation\n ? {\n skip,\n branch: job.branch,\n replayOptions: { operation: sourceOperation },\n protocolVersion,\n }\n : { skip, branch: job.branch, protocolVersion };\n updatedDocument = module.reducer(\n document as PHDocument,\n action,\n undefined,\n reducerOptions,\n );\n } catch (error) {\n const contextMessage = `Failed to apply action to document:\\n Action type: ${action.type}\\n Document ID: ${job.documentId}\\n Document type: ${document.header.documentType}\\n Scope: ${job.scope}\\n Original error: ${error instanceof Error ? error.message : String(error)}`;\n const enhancedError = new Error(contextMessage);\n if (error instanceof Error && error.stack) {\n enhancedError.stack = `${contextMessage}\\n\\nOriginal stack trace:\\n${error.stack}`;\n }\n return buildErrorResult(job, enhancedError, startTime);\n }\n\n const scope = job.scope;\n const operations = updatedDocument.operations[scope];\n\n if (operations.length === 0) {\n return buildErrorResult(\n job,\n new Error(\"No operation generated from action\"),\n startTime,\n );\n }\n\n const newOperation = operations[operations.length - 1];\n\n if (!isUndoRedo(action)) {\n newOperation.skip = skip;\n }\n\n const resultingState = JSON.stringify({\n ...updatedDocument.state,\n header: updatedDocument.header,\n });\n\n let storedOperations: Operation[];\n try {\n storedOperations = await stores.operationStore.apply(\n job.documentId,\n document.header.documentType,\n scope,\n job.branch,\n newOperation.index,\n (txn) => {\n txn.addOperations(newOperation);\n },\n signal,\n );\n } catch (error) {\n this.logger.error(\n \"Error writing @Operation to IOperationStore: @Error\",\n newOperation,\n error,\n );\n\n stores.writeCache.invalidate(job.documentId, scope, job.branch);\n\n return {\n job,\n success: false,\n error: new Error(\n `Failed to write operation to IOperationStore: ${error instanceof Error ? error.message : String(error)}`,\n ),\n duration: Date.now() - startTime,\n };\n }\n\n const storedOperation = storedOperations[0];\n\n updatedDocument.header.revision = {\n ...updatedDocument.header.revision,\n [scope]: storedOperation.index + 1,\n };\n\n stores.writeCache.putState(\n job.documentId,\n scope,\n job.branch,\n storedOperation.index,\n updatedDocument,\n );\n\n indexTxn.write([\n {\n ...storedOperation,\n documentId: job.documentId,\n documentType: document.header.documentType,\n branch: job.branch,\n scope,\n sourceRemote,\n },\n ]);\n\n return {\n job,\n success: true,\n operations: [storedOperation],\n operationsWithContext: [\n {\n operation: storedOperation,\n context: {\n documentId: job.documentId,\n scope,\n branch: job.branch,\n documentType: document.header.documentType,\n resultingState,\n ordinal: 0,\n },\n },\n ],\n duration: Date.now() - startTime,\n };\n }\n\n private async executeLoadJob(\n job: Job,\n startTime: number,\n indexTxn: IOperationIndexTxn,\n stores: ExecutionStores,\n signal?: AbortSignal,\n ): Promise<JobResult> {\n if (job.operations.length === 0) {\n return buildErrorResult(\n job,\n new Error(\"Load job must include at least one operation\"),\n startTime,\n );\n }\n\n let docMeta;\n try {\n docMeta = await stores.documentMetaCache.getDocumentMeta(\n job.documentId,\n job.branch,\n signal,\n );\n } catch {\n // Document meta not found -- continue with load (may be a new document)\n }\n\n if (docMeta?.state.isDeleted) {\n return buildErrorResult(\n job,\n new DocumentDeletedError(job.documentId, docMeta.state.deletedAtUtcIso),\n startTime,\n );\n }\n\n const scope = job.scope;\n\n let latestRevision: number;\n try {\n const revisions = await stores.operationStore.getRevisions(\n job.documentId,\n job.branch,\n signal,\n );\n latestRevision = revisions.revision[scope] ?? 0;\n } catch {\n latestRevision = 0;\n }\n\n for (const operation of job.operations) {\n if (\n operation.timestampUtcMs &&\n !isValidISOTimestamp(operation.timestampUtcMs)\n ) {\n return {\n job,\n success: false,\n error: new Error(\n `Invalid timestamp \"${operation.timestampUtcMs}\" on operation (index: ${operation.index})`,\n ),\n duration: Date.now() - startTime,\n };\n }\n }\n\n let minIncomingIndex = Number.POSITIVE_INFINITY;\n let minIncomingTimestamp = job.operations[0]?.timestampUtcMs || \"\";\n for (const operation of job.operations) {\n minIncomingIndex = Math.min(minIncomingIndex, operation.index);\n const ts = operation.timestampUtcMs || \"\";\n if (ts < minIncomingTimestamp) {\n minIncomingTimestamp = ts;\n }\n }\n\n let conflictingOps: Operation[];\n try {\n const conflictingResult = await stores.operationStore.getConflicting(\n job.documentId,\n scope,\n job.branch,\n minIncomingTimestamp,\n undefined,\n signal,\n );\n\n conflictingOps = conflictingResult.results;\n } catch {\n conflictingOps = [];\n }\n\n let allOpsFromMinConflictingIndex: Operation[] = conflictingOps;\n if (conflictingOps.length > 0) {\n const minConflictingIndex = Math.min(\n ...conflictingOps.map((op) => op.index),\n );\n try {\n const allOpsResult = await stores.operationStore.getSince(\n job.documentId,\n scope,\n job.branch,\n minConflictingIndex - 1,\n undefined,\n undefined,\n signal,\n );\n allOpsFromMinConflictingIndex = allOpsResult.results;\n } catch {\n allOpsFromMinConflictingIndex = conflictingOps;\n }\n }\n\n const incomingActionIds = new Set(job.operations.map((op) => op.action.id));\n\n const nonSupersededOps = conflictingOps.filter((op) => {\n // A local op at an index below the incoming batch's lowest index with no\n // overlapping action.id is a predecessor of the incoming ops, not a\n // concurrent conflict. Including it would force a reshuffle that\n // re-inserts identical history at new indices, which cascades when many\n // ops share timestamps (bulk imports). Local ops whose action.id matches\n // an incoming op are kept so dedup + reshuffle can remap them correctly\n // (e.g. cross-reactor reshuffle rebroadcast).\n if (op.index < minIncomingIndex && !incomingActionIds.has(op.action.id)) {\n return false;\n }\n for (const laterOp of allOpsFromMinConflictingIndex) {\n if (laterOp.index > op.index && laterOp.skip > 0) {\n const logicalIndex = laterOp.index - laterOp.skip;\n if (logicalIndex <= op.index) {\n return false;\n }\n }\n }\n return true;\n });\n\n const existingOpsToReshuffle = nonSupersededOps;\n\n if (existingOpsToReshuffle.length > this.config.maxSkipThreshold) {\n return {\n job,\n success: false,\n error: new Error(\n `Excessive reshuffle detected: existing op count of ${existingOpsToReshuffle.length} exceeds threshold of ${this.config.maxSkipThreshold}. ` +\n `This indicates a significant divergence between local and incoming operations.`,\n ),\n duration: Date.now() - startTime,\n };\n }\n\n let skipCount = existingOpsToReshuffle.length;\n if (existingOpsToReshuffle.length > 0) {\n let minLogicalIndex = Number.POSITIVE_INFINITY;\n for (const op of existingOpsToReshuffle) {\n const logical = op.index - op.skip;\n if (logical < minLogicalIndex) minLogicalIndex = logical;\n }\n const logicalSkip = latestRevision - minLogicalIndex;\n if (logicalSkip > skipCount) skipCount = logicalSkip;\n }\n\n const existingActionIds = new Set(\n nonSupersededOps.map((op) => op.action.id),\n );\n const seenIncomingActionIds = new Set<string>();\n const incomingOpsToApply = job.operations.filter((op) => {\n if (existingActionIds.has(op.action.id)) return false;\n if (seenIncomingActionIds.has(op.action.id)) return false;\n seenIncomingActionIds.add(op.action.id);\n return true;\n });\n\n if (incomingOpsToApply.length === 0) {\n return {\n job,\n success: true,\n operations: [],\n operationsWithContext: [],\n duration: Date.now() - startTime,\n };\n }\n\n const reshuffledOperations =\n existingOpsToReshuffle.length === 0 && skipCount === 0\n ? incomingOpsToApply\n .slice()\n .sort((a, b) => a.index - b.index)\n .map((operation, i) => ({\n ...operation,\n index: latestRevision + i,\n }))\n : reshuffleByTimestamp(\n {\n index: latestRevision,\n skip: skipCount,\n },\n existingOpsToReshuffle,\n incomingOpsToApply.map((operation) => ({\n ...operation,\n id: operation.id,\n })),\n );\n\n for (const operation of reshuffledOperations) {\n if (operation.action.type === \"NOOP\") {\n operation.skip = 1;\n }\n }\n\n const actions = reshuffledOperations.map((operation) => operation.action);\n const skipValues = reshuffledOperations.map((operation) => operation.skip);\n\n const effectiveSourceRemote =\n skipCount > 0\n ? \"\" // reshuffle: send to all remotes including source\n : (job.meta.sourceRemote as string) || \"\"; // trivial append: suppress echo to source\n\n const result = await this.processActions(\n job,\n actions,\n startTime,\n indexTxn,\n stores,\n skipValues,\n reshuffledOperations,\n effectiveSourceRemote,\n signal,\n );\n\n if (!result.success) {\n return {\n job,\n success: false,\n error: result.error,\n duration: Date.now() - startTime,\n };\n }\n\n stores.writeCache.invalidate(job.documentId, scope, job.branch);\n\n if (scope === \"document\") {\n stores.documentMetaCache.invalidate(job.documentId, job.branch);\n }\n\n return {\n job,\n success: true,\n operations: result.generatedOperations,\n operationsWithContext: result.operationsWithContext,\n duration: Date.now() - startTime,\n };\n }\n\n private accumulateResultOrReturnError(\n result: JobResult,\n generatedOperations: Operation[],\n operationsWithContext: OperationWithContext[],\n ): JobResult | null {\n if (!result.success) {\n return result;\n }\n if (result.operations && result.operations.length > 0) {\n generatedOperations.push(...result.operations);\n }\n if (result.operationsWithContext) {\n operationsWithContext.push(...result.operationsWithContext);\n }\n return null;\n }\n}\n","import type {\n DocumentModelModule,\n UpgradeManifest,\n UpgradeReducer,\n UpgradeTransition,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n DowngradeNotSupportedError,\n DuplicateManifestError,\n DuplicateModuleError,\n InvalidUpgradeStepError,\n ManifestNotFoundError,\n MissingUpgradeTransitionError,\n ModuleNotFoundError,\n} from \"./errors.js\";\nimport type {\n IDocumentModelRegistry,\n RegistrationResult,\n} from \"./interfaces.js\";\n\n/**\n * In-memory implementation of the IDocumentModelRegistry interface.\n * Manages document model modules with version-aware storage and upgrade manifest support.\n */\nexport class DocumentModelRegistry implements IDocumentModelRegistry {\n private modules: DocumentModelModule<any>[] = [];\n private manifests: UpgradeManifest<readonly number[]>[] = [];\n\n registerModules(\n ...modules: DocumentModelModule<any>[]\n ): RegistrationResult<DocumentModelModule<any>>[] {\n return modules.map((module) => {\n try {\n const documentType = module.documentModel.global.id;\n const version = module.version ?? 1;\n\n for (let i = 0; i < this.modules.length; i++) {\n const existing = this.modules[i];\n const existingType = existing.documentModel.global.id;\n const existingVersion = existing.version ?? 1;\n\n if (existingType === documentType && existingVersion === version) {\n throw new DuplicateModuleError(documentType, version);\n }\n }\n\n this.modules.push(module);\n return { status: \"success\" as const, item: module };\n } catch (error) {\n return {\n status: \"error\" as const,\n item: module,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n });\n }\n\n unregisterModules(...documentTypes: string[]): boolean {\n let allFound = true;\n\n for (const documentType of documentTypes) {\n const hasModule = this.modules.some(\n (m) => m.documentModel.global.id === documentType,\n );\n\n if (!hasModule) {\n allFound = false;\n }\n\n this.modules = this.modules.filter(\n (m) => m.documentModel.global.id !== documentType,\n );\n }\n\n return allFound;\n }\n\n getModule(documentType: string, version?: number): DocumentModelModule<any> {\n let latestModule: DocumentModelModule<any> | undefined;\n let latestVersion = -1;\n\n for (let i = 0; i < this.modules.length; i++) {\n const module = this.modules[i];\n const moduleType = module.documentModel.global.id;\n const moduleVersion = module.version ?? 1;\n\n if (moduleType === documentType) {\n if (version !== undefined && moduleVersion === version) {\n return module;\n }\n\n if (moduleVersion > latestVersion) {\n latestModule = module;\n latestVersion = moduleVersion;\n }\n }\n }\n\n if (version === undefined && latestModule !== undefined) {\n return latestModule;\n }\n\n throw new ModuleNotFoundError(documentType, version);\n }\n\n getAllModules(): DocumentModelModule<any>[] {\n return [...this.modules];\n }\n\n clear(): void {\n this.modules = [];\n this.manifests = [];\n }\n\n getSupportedVersions(documentType: string): number[] {\n const versions: number[] = [];\n\n for (const module of this.modules) {\n if (module.documentModel.global.id === documentType) {\n versions.push(module.version ?? 1);\n }\n }\n\n if (versions.length === 0) {\n throw new ModuleNotFoundError(documentType);\n }\n\n return versions.sort((a, b) => a - b);\n }\n\n getLatestVersion(documentType: string): number {\n let latest = -1;\n let found = false;\n\n for (const module of this.modules) {\n if (module.documentModel.global.id === documentType) {\n found = true;\n const version = module.version ?? 1;\n if (version > latest) {\n latest = version;\n }\n }\n }\n\n if (!found) {\n throw new ModuleNotFoundError(documentType);\n }\n\n return latest;\n }\n\n registerUpgradeManifests(\n ...manifestsToRegister: UpgradeManifest<readonly number[]>[]\n ): RegistrationResult<UpgradeManifest<readonly number[]>>[] {\n return manifestsToRegister.map((manifestToRegister) => {\n try {\n if (!manifestToRegister.documentType) {\n throw new Error(\"Upgrade manifest is missing a documentType\");\n }\n\n for (const registeredManifest of this.manifests) {\n if (\n registeredManifest.documentType === manifestToRegister.documentType\n ) {\n throw new DuplicateManifestError(manifestToRegister.documentType);\n }\n }\n\n this.manifests.push(manifestToRegister);\n return { status: \"success\" as const, item: manifestToRegister };\n } catch (error) {\n return {\n status: \"error\" as const,\n item: manifestToRegister,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n });\n }\n\n unregisterUpgradeManifests(...documentTypes: string[]): boolean {\n let allFound = true;\n\n for (const documentType of documentTypes) {\n const hasManifest = this.manifests.some(\n (m) => m.documentType === documentType,\n );\n\n if (!hasManifest) {\n allFound = false;\n }\n\n this.manifests = this.manifests.filter(\n (m) => m.documentType !== documentType,\n );\n }\n\n return allFound;\n }\n\n getUpgradeManifest(documentType: string): UpgradeManifest<readonly number[]> {\n for (let i = 0; i < this.manifests.length; i++) {\n if (this.manifests[i].documentType === documentType) {\n return this.manifests[i];\n }\n }\n throw new ManifestNotFoundError(documentType);\n }\n\n computeUpgradePath(\n documentType: string,\n fromVersion: number,\n toVersion: number,\n ): UpgradeTransition[] {\n if (fromVersion === toVersion) {\n return [];\n }\n\n if (toVersion < fromVersion) {\n throw new DowngradeNotSupportedError(\n documentType,\n fromVersion,\n toVersion,\n );\n }\n\n const manifest = this.getUpgradeManifest(documentType);\n\n const path: UpgradeTransition[] = [];\n for (let v = fromVersion + 1; v <= toVersion; v++) {\n const key = `v${v}`;\n\n if (!(key in manifest.upgrades)) {\n throw new MissingUpgradeTransitionError(documentType, v - 1, v);\n }\n\n const transition =\n manifest.upgrades[key as keyof typeof manifest.upgrades];\n path.push(transition);\n }\n\n return path;\n }\n\n getUpgradeReducer(\n documentType: string,\n fromVersion: number,\n toVersion: number,\n ): UpgradeReducer<any, any> {\n if (toVersion !== fromVersion + 1) {\n throw new InvalidUpgradeStepError(documentType, fromVersion, toVersion);\n }\n\n const manifest = this.getUpgradeManifest(documentType);\n\n const key = `v${toVersion}`;\n\n if (!(key in manifest.upgrades)) {\n throw new MissingUpgradeTransitionError(\n documentType,\n fromVersion,\n toVersion,\n );\n }\n\n const transition = manifest.upgrades[key as keyof typeof manifest.upgrades];\n return transition.upgradeReducer;\n }\n}\n","import type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport type { Kysely, Transaction } from \"kysely\";\nimport type { IKeyframeStore } from \"../interfaces.js\";\nimport type { Database } from \"./types.js\";\n\nexport class KyselyKeyframeStore implements IKeyframeStore {\n private trx?: Transaction<Database>;\n\n constructor(private db: Kysely<Database>) {}\n\n private get queryExecutor(): Kysely<Database> | Transaction<Database> {\n return this.trx ?? this.db;\n }\n\n withTransaction(trx: Transaction<Database>): KyselyKeyframeStore {\n const instance = new KyselyKeyframeStore(this.db);\n instance.trx = trx;\n return instance;\n }\n\n async putKeyframe(\n documentId: string,\n scope: string,\n branch: string,\n revision: number,\n document: PHDocument,\n signal?: AbortSignal,\n ): Promise<void> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n await this.queryExecutor\n .insertInto(\"Keyframe\")\n .values({\n documentId,\n documentType: document.header.documentType,\n scope,\n branch,\n revision,\n document,\n })\n .onConflict((oc) =>\n oc\n .columns([\"documentId\", \"scope\", \"branch\", \"revision\"])\n .doUpdateSet({ document }),\n )\n .execute();\n }\n\n async findNearestKeyframe(\n documentId: string,\n scope: string,\n branch: string,\n targetRevision: number,\n signal?: AbortSignal,\n ): Promise<{ revision: number; document: PHDocument } | undefined> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const row = await this.queryExecutor\n .selectFrom(\"Keyframe\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .where(\"scope\", \"=\", scope)\n .where(\"branch\", \"=\", branch)\n .where(\"revision\", \"<=\", targetRevision)\n .orderBy(\"revision\", \"desc\")\n .limit(1)\n .executeTakeFirst();\n\n if (!row) {\n return undefined;\n }\n\n return {\n revision: row.revision,\n document: row.document as PHDocument,\n };\n }\n\n async listKeyframes(\n documentId: string,\n scope?: string,\n branch?: string,\n signal?: AbortSignal,\n ): Promise<\n Array<{\n scope: string;\n branch: string;\n revision: number;\n document: PHDocument;\n }>\n > {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n let query = this.queryExecutor\n .selectFrom(\"Keyframe\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .orderBy(\"revision\", \"asc\");\n\n if (scope !== undefined) {\n query = query.where(\"scope\", \"=\", scope);\n }\n if (branch !== undefined) {\n query = query.where(\"branch\", \"=\", branch);\n }\n\n const rows = await query.execute();\n\n return rows.map((row) => ({\n scope: row.scope,\n branch: row.branch,\n revision: row.revision,\n document: row.document as PHDocument,\n }));\n }\n\n async deleteKeyframes(\n documentId: string,\n scope?: string,\n branch?: string,\n signal?: AbortSignal,\n ): Promise<number> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n let query = this.queryExecutor\n .deleteFrom(\"Keyframe\")\n .where(\"documentId\", \"=\", documentId);\n\n if (scope !== undefined && branch !== undefined) {\n query = query.where(\"scope\", \"=\", scope).where(\"branch\", \"=\", branch);\n } else if (scope !== undefined) {\n query = query.where(\"scope\", \"=\", scope);\n }\n\n const result = await query.executeTakeFirst();\n\n return Number(result.numDeletedRows || 0n);\n }\n}\n","import type { PagedResults, PagingOptions } from \"../../shared/types.js\";\n\nconst DEFAULT_LIMIT = 100;\n\nexport function paginateRows<TRow, TItem>(\n rows: TRow[],\n paging: PagingOptions | undefined,\n cursorOf: (row: TRow) => number,\n toItem: (row: TRow) => TItem,\n refetch: (cursor: string, limit: number) => Promise<PagedResults<TItem>>,\n): PagedResults<TItem> {\n let hasMore = false;\n let items = rows;\n\n if (paging?.limit && rows.length > paging.limit) {\n hasMore = true;\n items = rows.slice(0, paging.limit);\n }\n\n const nextCursor =\n hasMore && items.length > 0\n ? cursorOf(items[items.length - 1]).toString()\n : undefined;\n\n const cursor = paging?.cursor || \"0\";\n const limit = paging?.limit || DEFAULT_LIMIT;\n const results = items.map(toItem);\n\n return {\n results,\n options: { cursor, limit },\n nextCursor,\n next: hasMore ? () => refetch(nextCursor!, limit) : undefined,\n };\n}\n","import type {\n Operation,\n OperationWithContext,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport type { IReadModel } from \"../read-models/interfaces.js\";\nimport type {\n ConsistencyToken,\n PagedResults,\n PagingOptions,\n} from \"../shared/types.js\";\nimport type { ChannelErrorSource } from \"../sync/types.js\";\nimport type { RemoteCursor, RemoteRecord } from \"../sync/types.js\";\n\nexport type { PagedResults, PagingOptions } from \"../shared/types.js\";\n\n/**\n * Thrown when an operation with the same identity already exists in the store.\n */\nexport class DuplicateOperationError extends Error {\n constructor(description: string) {\n super(`Duplicate operation: ${description}`);\n this.name = \"DuplicateOperationError\";\n }\n}\n\n/**\n * Thrown when a concurrent write conflict is detected during an atomic apply.\n */\nexport class OptimisticLockError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OptimisticLockError\";\n }\n}\n\n/**\n * Thrown when the caller-provided revision does not match the current\n * stored revision, indicating a stale read.\n */\nexport class RevisionMismatchError extends Error {\n constructor(expected: number, actual: number) {\n super(`Revision mismatch: expected ${expected}, got ${actual}`);\n this.name = \"RevisionMismatchError\";\n }\n}\n\n/**\n * A write transaction passed to {@link IOperationStore.apply}. Accumulates\n * operations that are committed atomically when the callback returns.\n */\nexport interface AtomicTxn {\n /** Stages one or more operations to be written as part of this transaction. */\n addOperations(...operations: Operation[]): void;\n}\n\n/**\n * Per-scope revision map for a document, used to reconstruct the header\n * revision field and lastModified timestamp.\n */\nexport type DocumentRevisions = {\n /** Map of scope to operation index for that scope */\n revision: Record<string, number>;\n\n /** Latest timestamp across revisions */\n latestTimestamp: string;\n};\n\n/**\n * Append-only store for document operations. Operations are partitioned by\n * (documentId, scope, branch) and ordered by a monotonic revision index.\n */\nexport interface IOperationStore {\n /**\n * Atomically appends operations for a single document/scope/branch.\n * The provided revision must match the current head; otherwise a\n * {@link RevisionMismatchError} is thrown.\n *\n * Returns the stored {@link Operation} rows for the operations that were\n * appended. On an idempotent replay — detected when a\n * {@link RevisionMismatchError} or {@link DuplicateOperationError} occurs and\n * a stored row at the same `(documentId, scope, branch, index)` already has\n * a matching `opId`, `index`, and `skip` — the previously-stored rows are\n * returned instead of throwing. If no matching stored row is found, the\n * original error is propagated unchanged.\n *\n * @param documentId - The document id\n * @param documentType - The document type identifier\n * @param scope - The operation scope (e.g. \"global\", \"local\")\n * @param branch - The branch name\n * @param revision - Expected current revision (optimistic lock)\n * @param fn - Callback that stages operations via {@link AtomicTxn}\n * @param signal - Optional abort signal to cancel the request\n * @returns The stored operations; empty array when no operations were staged\n */\n 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 ): Promise<Operation[]>;\n\n /**\n * Returns operations for a document/scope/branch whose index is greater\n * than the given revision.\n *\n * @param documentId - The document id\n * @param scope - The operation scope\n * @param branch - The branch name\n * @param revision - Return operations after this revision index\n * @param filter - Optional filters (action types, timestamp range)\n * @param paging - Optional paging options for cursor-based pagination\n * @param signal - Optional abort signal to cancel the request\n */\n 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\n /**\n * Returns operations across all documents whose auto-increment store id\n * is greater than the given id. Used by read models and sync to catch up\n * on operations they may have missed.\n *\n * @param id - Return operations with store id greater than this value\n * @param paging - Optional paging options for cursor-based pagination\n * @param signal - Optional abort signal to cancel the request\n */\n getSinceId(\n id: number,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationWithContext>>;\n\n /**\n * Gets operations that may conflict with incoming operations during a load.\n *\n * @param documentId - The document id\n * @param scope - The scope to query\n * @param branch - The branch name\n * @param minTimestamp - Minimum timestamp (inclusive) as ISO string\n * @param paging - Optional paging options for cursor-based pagination\n * @param signal - Optional abort signal to cancel the request\n * @returns Paged results of operations that may conflict\n */\n getConflicting(\n documentId: string,\n scope: string,\n branch: string,\n minTimestamp: string,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Operation>>;\n\n /**\n * Gets the latest operation index for each scope of a document, along with\n * the latest timestamp across all scopes. This is used to efficiently reconstruct\n * the revision map and lastModified timestamp for document headers.\n *\n * @param documentId - The document id\n * @param branch - The branch name\n * @param signal - Optional abort signal to cancel the request\n * @returns Object containing revision map and latest timestamp\n */\n getRevisions(\n documentId: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<DocumentRevisions>;\n}\n\n/**\n * Stores periodic document snapshots (keyframes) so that document state\n * can be reconstructed without replaying the full operation history.\n */\nexport interface IKeyframeStore {\n /**\n * Stores a document snapshot at a specific revision.\n *\n * @param documentId - The document id\n * @param scope - The operation scope\n * @param branch - The branch name\n * @param revision - The operation index this snapshot corresponds to\n * @param document - The full document state to persist\n * @param signal - Optional abort signal to cancel the request\n */\n putKeyframe(\n documentId: string,\n scope: string,\n branch: string,\n revision: number,\n document: PHDocument,\n signal?: AbortSignal,\n ): Promise<void>;\n\n /**\n * Finds the keyframe closest to (but not exceeding) the target revision.\n * Returns undefined if no keyframe exists for this document/scope/branch.\n *\n * @param documentId - The document id\n * @param scope - The operation scope\n * @param branch - The branch name\n * @param targetRevision - The desired revision upper bound\n * @param signal - Optional abort signal to cancel the request\n */\n findNearestKeyframe(\n documentId: string,\n scope: string,\n branch: string,\n targetRevision: number,\n signal?: AbortSignal,\n ): Promise<{ revision: number; document: PHDocument } | undefined>;\n\n /**\n * Lists all keyframes for a document, optionally filtered by scope and branch.\n *\n * @param documentId - The document id\n * @param scope - Optional scope filter\n * @param branch - Optional branch filter\n * @param signal - Optional abort signal to cancel the request\n */\n listKeyframes(\n documentId: string,\n scope?: string,\n branch?: string,\n signal?: AbortSignal,\n ): Promise<\n Array<{\n scope: string;\n branch: string;\n revision: number;\n document: PHDocument;\n }>\n >;\n\n /**\n * Deletes keyframes for a document. Optionally scoped to a specific\n * scope and/or branch.\n *\n * @param documentId - The document id\n * @param scope - Optional scope filter; omit to delete across all scopes\n * @param branch - Optional branch filter; omit to delete across all branches\n * @param signal - Optional abort signal to cancel the request\n * @returns The number of keyframes deleted\n */\n deleteKeyframes(\n documentId: string,\n scope?: string,\n branch?: string,\n signal?: AbortSignal,\n ): Promise<number>;\n}\n\n/**\n * Filters applied when reading document state from {@link IDocumentView}.\n */\nexport interface ViewFilter {\n /** Branch to read from. Defaults to the main branch when omitted. */\n branch?: string;\n /** Scopes to include. When omitted, all scopes are included. */\n scopes?: string[];\n /** Exclude operations originating from this remote name. */\n excludeSourceRemote?: string;\n}\n\n/**\n * Criteria for searching documents in storage-backed read models.\n * All provided fields are combined with AND logic.\n */\nexport interface SearchFilter {\n /** Filter by document type identifier. */\n documentType?: string;\n /** Filter by parent document id. */\n parentId?: string;\n /** Filter by arbitrary key-value identifiers stored on the document. */\n identifiers?: Record<string, any>;\n /** When true, include soft-deleted documents in results. */\n includeDeleted?: boolean;\n}\n\n/**\n * Filter options for querying operations. When multiple filters are provided,\n * they are combined with AND logic.\n */\nexport interface OperationFilter {\n /** Filter by action types (OR logic within array) */\n actionTypes?: string[];\n /** Filter operations with timestamp >= this value (ISO string) */\n timestampFrom?: string;\n /** Filter operations with timestamp <= this value (ISO string) */\n timestampTo?: string;\n /** Filter operations with index >= this value */\n sinceRevision?: number;\n}\n\n/**\n * Materialised read model that maintains document snapshots. Snapshots are\n * updated by indexing operations (which must include `resultingState`) and\n * queried with optional consistency tokens for read-after-write guarantees.\n */\nexport interface IDocumentView extends IReadModel {\n /**\n * Initializes the view.\n */\n init(): Promise<void>;\n\n /**\n * Indexes a list of operations.\n *\n * @param items - Operations with context. Context MUST include ephemeral\n * `resultingState` for optimization. IDocumentView never rebuilds\n * documents from operations - it always requires resultingState.\n */\n indexOperations(items: OperationWithContext[]): Promise<void>;\n\n /**\n * Blocks until the view has processed the coordinates referenced by the\n * provided consistency token.\n *\n * @param token - Consistency token derived from the originating job\n * @param timeoutMs - Optional timeout window in milliseconds\n * @param signal - Optional abort signal to cancel the wait\n */\n waitForConsistency(\n token: ConsistencyToken,\n timeoutMs?: number,\n signal?: AbortSignal,\n ): Promise<void>;\n\n /**\n * Returns true if and only if the documents exist.\n *\n * @param documentIds - The list of document ids to check.\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n exists(\n documentIds: string[],\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<boolean[]>;\n\n /**\n * Returns the document with the given id.\n *\n * @param documentId - The id of the document to get.\n * @param view - Optional filter containing branch and scopes information\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n get<TDocument extends PHDocument>(\n documentId: string,\n view?: ViewFilter,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<TDocument>;\n\n /**\n * Returns the documents with the given ids.\n *\n * @param documentIds - The list of document ids to get.\n * @param view - Optional filter containing branch and scopes information\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n getMany<TDocument extends PHDocument>(\n documentIds: string[],\n view?: ViewFilter,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<TDocument[]>;\n\n /**\n * Returns the document with the given identifier (either id or slug).\n * Throws an error if the identifier matches both an id and a slug that refer to different documents.\n *\n * @param identifier - The id or slug of the document to get.\n * @param view - Optional filter containing branch and scopes information\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n * @throws {Error} If identifier matches both an ID and slug referring to different documents\n */\n getByIdOrSlug<TDocument extends PHDocument>(\n identifier: string,\n view?: ViewFilter,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<TDocument>;\n\n /**\n * Finds documents by their document type.\n *\n * @param type - The document type to search for\n * @param view - Optional filter containing branch and scopes information\n * @param paging - Optional paging options for cursor-based pagination\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n findByType(\n type: string,\n view?: ViewFilter,\n paging?: PagingOptions,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<PagedResults<PHDocument>>;\n\n /**\n * Resolves a slug to a document ID.\n *\n * @param slug - The slug to resolve\n * @param view - Optional filter containing branch and scopes information\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n * @returns The document ID or undefined if the slug doesn't exist\n */\n resolveSlug(\n slug: string,\n view?: ViewFilter,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<string | undefined>;\n\n /**\n * Resolves a list of slugs to document IDs.\n *\n * @param slugs - The list of slugs to resolve.\n * @param view - Optional filter containing branch and scopes information\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n * @returns The list of document IDs\n */\n resolveSlugs(\n slugs: string[],\n view?: ViewFilter,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<string[]>;\n\n /**\n * Resolves an identifier (either id or slug) to a document ID.\n * This is a lightweight alternative to getByIdOrSlug that returns just the ID\n * without fetching the full document.\n *\n * @param identifier - The id or slug to resolve\n * @param view - Optional filter containing branch and scopes information\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n * @returns The document ID\n * @throws {Error} If document not found or identifier matches both an ID and slug referring to different documents\n */\n resolveIdOrSlug(\n identifier: string,\n view?: ViewFilter,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<string>;\n}\n\n/**\n * A directed relationship between two documents in the document graph.\n */\nexport type DocumentRelationship = {\n sourceId: string;\n targetId: string;\n relationshipType: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n};\n\n/**\n * A lightweight directed edge in a {@link IDocumentGraph}.\n */\nexport type DocumentGraphEdge = {\n from: string;\n to: string;\n type: string;\n};\n\n/**\n * A subgraph of the document relationship graph, returned by traversal\n * queries such as {@link IDocumentIndexer.findAncestors}.\n */\nexport interface IDocumentGraph {\n nodes: string[];\n edges: DocumentGraphEdge[];\n}\n\n/**\n * Read model that maintains a directed graph of document relationships.\n * Relationships are created and removed by indexing operations containing\n * ADD_RELATIONSHIP and REMOVE_RELATIONSHIP actions.\n */\nexport interface IDocumentIndexer extends IReadModel {\n /**\n * Initializes the indexer and catches up on any missed operations.\n */\n init(): Promise<void>;\n\n /**\n * Indexes a list of operations to update the relationship graph.\n *\n * @param operations - Operations to index. Will process ADD_RELATIONSHIP and\n * REMOVE_RELATIONSHIP operations.\n */\n indexOperations(operations: OperationWithContext[]): Promise<void>;\n\n /**\n * Blocks until the indexer has processed the coordinates referenced by the\n * provided consistency token.\n *\n * @param token - Consistency token derived from the originating job\n * @param timeoutMs - Optional timeout window in milliseconds\n * @param signal - Optional abort signal to cancel the wait\n */\n waitForConsistency(\n token: ConsistencyToken,\n timeoutMs?: number,\n signal?: AbortSignal,\n ): Promise<void>;\n\n /**\n * Returns outgoing relationships from a document.\n *\n * @param documentId - The source document id\n * @param types - Optional filter by relationship types\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n getOutgoing(\n documentId: string,\n types?: string[],\n paging?: PagingOptions,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<PagedResults<DocumentRelationship>>;\n\n /**\n * Returns incoming relationships to a document.\n *\n * @param documentId - The target document id\n * @param types - Optional filter by relationship types\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n getIncoming(\n documentId: string,\n types?: string[],\n paging?: PagingOptions,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<PagedResults<DocumentRelationship>>;\n\n /**\n * Checks if a relationship exists between two documents.\n *\n * @param sourceId - The source document id\n * @param targetId - The target document id\n * @param types - Optional filter by relationship types\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n hasRelationship(\n sourceId: string,\n targetId: string,\n types?: string[],\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<boolean>;\n\n /**\n * Returns all undirected relationships between two documents.\n *\n * @param a - The ID of the first document\n * @param b - The ID of the second document\n * @param types - Optional filter by relationship types\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n getUndirectedRelationships(\n a: string,\n b: string,\n types?: string[],\n paging?: PagingOptions,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<PagedResults<DocumentRelationship>>;\n\n /**\n * Returns all directed relationships between two documents.\n *\n * @param sourceId - The source document id\n * @param targetId - The target document id\n * @param types - Optional filter by relationship types\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n getDirectedRelationships(\n sourceId: string,\n targetId: string,\n types?: string[],\n paging?: PagingOptions,\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<PagedResults<DocumentRelationship>>;\n\n /**\n * Finds a path from source to target following directed edges.\n *\n * @param sourceId - The source document id\n * @param targetId - The target document id\n * @param types - Optional filter by relationship types\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n * @returns Array of document ids representing the path, or null if no path exists\n */\n findPath(\n sourceId: string,\n targetId: string,\n types?: string[],\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<string[] | null>;\n\n /**\n * Returns all ancestors of a document in the relationship graph.\n *\n * @param documentId - The document id\n * @param types - Optional filter by relationship types\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n findAncestors(\n documentId: string,\n types?: string[],\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<IDocumentGraph>;\n\n /**\n * Returns children of the given parents that have no parents outside\n * the given set. Used by cascade delete to find documents that would\n * be orphaned if all the given parents were deleted.\n *\n * @param parentIds - The set of parent document ids (the deletion set)\n * @param types - Optional filter by relationship types\n * @param signal - Optional abort signal to cancel the request\n */\n getOrphanedChildren(\n parentIds: string[],\n types?: string[],\n signal?: AbortSignal,\n ): Promise<string[]>;\n\n /**\n * Returns all relationship types currently in the system.\n *\n * @param consistencyToken - Optional token for read-after-write consistency\n * @param signal - Optional abort signal to cancel the request\n */\n getRelationshipTypes(\n consistencyToken?: ConsistencyToken,\n signal?: AbortSignal,\n ): Promise<string[]>;\n}\n\n/**\n * Persistent storage for sync remote configurations. Each remote represents\n * a connection to an external system that operations can be synced with.\n */\nexport interface ISyncRemoteStorage {\n /**\n * Lists all remotes.\n *\n * @param signal - Optional abort signal to cancel the request\n * @returns The remotes\n */\n list(signal?: AbortSignal): Promise<RemoteRecord[]>;\n\n /**\n * Gets a remote by name.\n *\n * @param name - The name of the remote\n * @param signal - Optional abort signal to cancel the request\n * @returns The remote\n */\n get(name: string, signal?: AbortSignal): Promise<RemoteRecord>;\n\n /**\n * Upserts a remote.\n *\n * @param remote - The remote to upsert\n * @param signal - Optional abort signal to cancel the request\n * @returns The remote\n */\n upsert(remote: RemoteRecord, signal?: AbortSignal): Promise<void>;\n\n /**\n * Removes a remote by name.\n *\n * @param name - The name of the remote\n * @param signal - Optional abort signal to cancel the request\n * @returns The remote\n */\n remove(name: string, signal?: AbortSignal): Promise<void>;\n}\n\n/**\n * Persistent storage for sync cursors that track inbox/outbox progress\n * per remote. Cursors allow sync to resume from where it left off.\n */\nexport interface ISyncCursorStorage {\n /**\n * Lists all cursors for a remote.\n *\n * @param remoteName - The name of the remote\n * @param signal - Optional abort signal to cancel the request\n * @returns The cursors\n */\n list(remoteName: string, signal?: AbortSignal): Promise<RemoteCursor[]>;\n\n /**\n * Gets a cursor for a remote.\n *\n * @param remoteName - The name of the remote\n * @param cursorType - The type of cursor (\"inbox\" or \"outbox\")\n * @param signal - Optional abort signal to cancel the request\n * @returns The cursor\n */\n get(\n remoteName: string,\n cursorType: \"inbox\" | \"outbox\",\n signal?: AbortSignal,\n ): Promise<RemoteCursor>;\n\n /**\n * Upserts a cursor.\n *\n * @param cursor - The cursor to upsert\n * @param signal - Optional abort signal to cancel the request\n * @returns The cursor\n */\n upsert(cursor: RemoteCursor, signal?: AbortSignal): Promise<void>;\n\n /**\n * Removes a cursor for a remote.\n *\n * @param remoteName - The name of the remote\n * @param signal - Optional abort signal to cancel the request\n * @returns The cursor\n */\n remove(remoteName: string, signal?: AbortSignal): Promise<void>;\n}\n\n/**\n * Serializable snapshot of a permanently failed SyncOperation.\n */\nexport type DeadLetterRecord = {\n id: string;\n jobId: string;\n jobDependencies: string[];\n remoteName: string;\n documentId: string;\n scopes: string[];\n branch: string;\n operations: OperationWithContext[];\n errorSource: ChannelErrorSource;\n errorMessage: string;\n};\n\n/**\n * Persists dead-lettered sync operations so they survive reactor restarts.\n */\nexport interface ISyncDeadLetterStorage {\n /**\n * Lists dead letters for a remote, ordered by ordinal DESC (newest first).\n *\n * @param remoteName - The name of the remote\n * @param paging - Optional paging options (cursor + limit)\n * @param signal - Optional abort signal to cancel the request\n * @returns Paged dead letter records\n */\n list(\n remoteName: string,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<DeadLetterRecord>>;\n\n /**\n * Adds a dead letter. Duplicate ids are silently ignored.\n *\n * @param deadLetter - The dead letter record to persist\n * @param signal - Optional abort signal to cancel the request\n */\n add(deadLetter: DeadLetterRecord, signal?: AbortSignal): Promise<void>;\n\n /**\n * Removes a single dead letter by id.\n *\n * @param id - The dead letter id\n * @param signal - Optional abort signal to cancel the request\n */\n remove(id: string, signal?: AbortSignal): Promise<void>;\n\n /**\n * Removes all dead letters for a remote.\n *\n * @param remoteName - The name of the remote\n * @param signal - Optional abort signal to cancel the request\n */\n removeByRemote(remoteName: string, signal?: AbortSignal): Promise<void>;\n\n /**\n * Returns distinct document IDs that have any dead letter record across all remotes.\n * Used to populate the quarantine set on startup.\n *\n * @param signal - Optional abort signal to cancel the request\n */\n listQuarantinedDocumentIds(signal?: AbortSignal): Promise<string[]>;\n}\n","import type { Operation } from \"@powerhousedao/shared/document-model\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { type AtomicTxn as IAtomicTxn } from \"./interfaces.js\";\nimport type { InsertableOperation } from \"./kysely/types.js\";\n\nexport class AtomicTransaction implements IAtomicTxn {\n private operations: InsertableOperation[] = [];\n\n constructor(\n private documentId: string,\n private documentType: string,\n private scope: string,\n private branch: string,\n private baseRevision: number,\n ) {\n //\n }\n\n addOperations(...operations: Operation[]): void {\n for (const op of operations) {\n this.operations.push({\n // WRONG -- we should be using the jobId\n jobId: uuidv4(),\n opId: op.id,\n prevOpId: \"\", // Will be set during apply\n documentId: this.documentId,\n documentType: this.documentType,\n scope: this.scope,\n branch: this.branch,\n timestampUtcMs: new Date(op.timestampUtcMs),\n index: op.index,\n action: JSON.stringify(op.action),\n skip: op.skip,\n error: op.error || null,\n hash: op.hash,\n });\n }\n }\n\n getOperations(): InsertableOperation[] {\n return this.operations;\n }\n}\n","import {\n type Operation,\n type OperationWithContext,\n} from \"@powerhousedao/shared/document-model\";\nimport { sql, type Kysely, type Transaction } from \"kysely\";\nimport type { PagedResults, PagingOptions } from \"../../shared/types.js\";\nimport { throwIfAborted } from \"../../shared/utils.js\";\nimport { paginateRows } from \"./pagination.js\";\nimport {\n DuplicateOperationError,\n RevisionMismatchError,\n type AtomicTxn,\n type DocumentRevisions,\n type IOperationStore,\n type OperationFilter,\n} from \"../interfaces.js\";\nimport { AtomicTransaction } from \"../txn.js\";\nimport type { Database, InsertableOperation, OperationRow } from \"./types.js\";\n\nclass _UniqueConstraintContext extends Error {\n constructor(\n readonly documentId: string,\n readonly scope: string,\n readonly branch: string,\n readonly revision: number,\n readonly stagedOps: InsertableOperation[],\n ) {\n super(\"unique constraint\");\n this.name = \"UniqueConstraintContext\";\n }\n}\n\nexport class KyselyOperationStore implements IOperationStore {\n private trx?: Transaction<Database>;\n\n constructor(private db: Kysely<Database>) {}\n\n private get queryExecutor(): Kysely<Database> | Transaction<Database> {\n return this.trx ?? this.db;\n }\n\n withTransaction(trx: Transaction<Database>): KyselyOperationStore {\n const instance = new KyselyOperationStore(this.db);\n instance.trx = trx;\n return instance;\n }\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 ): Promise<Operation[]> {\n if (this.trx) {\n let executeResult: Operation[] | null = null;\n let uniqueCtx: _UniqueConstraintContext | null = null;\n\n try {\n executeResult = await this.executeApply(\n this.trx,\n documentId,\n documentType,\n scope,\n branch,\n revision,\n fn,\n signal,\n );\n } catch (error) {\n if (error instanceof _UniqueConstraintContext) {\n uniqueCtx = error;\n } else {\n throw error;\n }\n }\n\n if (uniqueCtx !== null) {\n return this.resolveUniqueConstraint(uniqueCtx);\n }\n\n return executeResult!;\n } else {\n let transactionResult: Operation[] | null = null;\n let uniqueCtx: _UniqueConstraintContext | null = null;\n\n try {\n transactionResult = await this.db.transaction().execute(async (trx) => {\n return this.executeApply(\n trx,\n documentId,\n documentType,\n scope,\n branch,\n revision,\n fn,\n signal,\n );\n });\n } catch (error) {\n if (error instanceof _UniqueConstraintContext) {\n uniqueCtx = error;\n } else {\n throw error;\n }\n }\n\n if (uniqueCtx !== null) {\n return this.resolveUniqueConstraint(uniqueCtx);\n }\n\n return transactionResult!;\n }\n }\n\n private async resolveUniqueConstraint(\n ctx: _UniqueConstraintContext,\n ): Promise<Operation[]> {\n let replayOps: Operation[] | null = null;\n\n try {\n replayOps = await this.findIdempotentReplay(\n this.db,\n ctx.documentId,\n ctx.scope,\n ctx.branch,\n ctx.revision,\n ctx.stagedOps,\n );\n } catch {\n // Lookup failed; propagate original error below\n }\n\n if (replayOps !== null) {\n return replayOps;\n }\n\n const op = ctx.stagedOps[0];\n throw new DuplicateOperationError(\n `${op.opId} at index ${op.index} with skip ${op.skip}`,\n );\n }\n\n private async executeApply(\n trx: Transaction<Database>,\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 throwIfAborted(signal);\n\n const atomicTxn = new AtomicTransaction(\n documentId,\n documentType,\n scope,\n branch,\n revision,\n );\n\n await fn(atomicTxn);\n\n const operations = atomicTxn.getOperations();\n\n if (operations.length === 0) {\n return [];\n }\n\n const latestOp = await trx\n .selectFrom(\"Operation\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .where(\"scope\", \"=\", scope)\n .where(\"branch\", \"=\", branch)\n .orderBy(\"index\", \"desc\")\n .limit(1)\n .executeTakeFirst();\n\n const currentRevision = latestOp ? latestOp.index : -1;\n if (currentRevision !== revision - 1) {\n let replayOps: Operation[] | null = null;\n\n try {\n replayOps = await this.findIdempotentReplay(\n trx,\n documentId,\n scope,\n branch,\n revision,\n operations,\n );\n } catch {\n // Lookup failed; propagate original error below\n }\n\n if (replayOps !== null) {\n return replayOps;\n }\n\n throw new RevisionMismatchError(currentRevision + 1, revision);\n }\n\n let prevOpId = latestOp?.opId || \"\";\n for (const op of operations) {\n op.prevOpId = prevOpId;\n prevOpId = op.opId;\n }\n\n try {\n await trx.insertInto(\"Operation\").values(operations).execute();\n } catch (error: unknown) {\n if (\n error instanceof Error &&\n error.message.includes(\"unique constraint\")\n ) {\n throw new _UniqueConstraintContext(\n documentId,\n scope,\n branch,\n revision,\n operations,\n );\n }\n\n throw error;\n }\n\n return operations.map((op) => ({\n index: op.index,\n timestampUtcMs: op.timestampUtcMs.toISOString(),\n hash: op.hash,\n skip: op.skip,\n error: op.error || undefined,\n id: op.opId,\n action: JSON.parse(op.action as string) as Operation[\"action\"],\n }));\n }\n\n private async findIdempotentReplay(\n executor: Kysely<Database> | Transaction<Database>,\n documentId: string,\n scope: string,\n branch: string,\n revision: number,\n stagedOps: InsertableOperation[],\n ): Promise<Operation[] | null> {\n const minIndex = revision;\n const maxIndex = revision + stagedOps.length - 1;\n\n const storedRows = await executor\n .selectFrom(\"Operation\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .where(\"scope\", \"=\", scope)\n .where(\"branch\", \"=\", branch)\n .where(\"index\", \">=\", minIndex)\n .where(\"index\", \"<=\", maxIndex)\n .orderBy(\"index\", \"asc\")\n .execute();\n\n if (storedRows.length !== stagedOps.length) {\n return null;\n }\n\n for (let i = 0; i < stagedOps.length; i++) {\n const staged = stagedOps[i];\n const stored = storedRows[i];\n if (\n stored.opId !== staged.opId ||\n stored.index !== staged.index ||\n stored.skip !== staged.skip\n ) {\n return null;\n }\n }\n\n return storedRows.map((row) => this.rowToOperation(row));\n }\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 throwIfAborted(signal);\n\n let query = this.queryExecutor\n .selectFrom(\"Operation\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .where(\"scope\", \"=\", scope)\n .where(\"branch\", \"=\", branch)\n .where(\"index\", \">\", revision)\n .orderBy(\"index\", \"asc\");\n\n if (filter) {\n if (filter.actionTypes && filter.actionTypes.length > 0) {\n const actionTypesArray = filter.actionTypes\n .map((t) => `'${t.replace(/'/g, \"''\")}'`)\n .join(\",\");\n query = query.where(\n sql<boolean>`action->>'type' = ANY(ARRAY[${sql.raw(actionTypesArray)}]::text[])`,\n );\n }\n if (filter.timestampFrom) {\n query = query.where(\n \"timestampUtcMs\",\n \">=\",\n new Date(filter.timestampFrom),\n );\n }\n if (filter.timestampTo) {\n query = query.where(\n \"timestampUtcMs\",\n \"<=\",\n new Date(filter.timestampTo),\n );\n }\n if (filter.sinceRevision !== undefined) {\n query = query.where(\"index\", \">=\", filter.sinceRevision);\n }\n }\n\n if (paging) {\n const cursorValue = Number.parseInt(paging.cursor, 10);\n if (cursorValue > 0) {\n query = query.where(\"index\", \">\", cursorValue);\n }\n\n if (paging.limit) {\n query = query.limit(paging.limit + 1);\n }\n }\n\n const rows = await query.execute();\n\n return paginateRows(\n rows,\n paging,\n (row) => row.index,\n (row) => this.rowToOperation(row),\n (cursor, limit) =>\n this.getSince(\n documentId,\n scope,\n branch,\n revision,\n filter,\n { cursor, limit },\n signal,\n ),\n );\n }\n\n async getSinceId(\n id: number,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<OperationWithContext>> {\n throwIfAborted(signal);\n\n let query = this.queryExecutor\n .selectFrom(\"Operation\")\n .selectAll()\n .where(\"id\", \">\", id)\n .orderBy(\"id\", \"asc\");\n\n // Handle cursor-based pagination\n if (paging) {\n // Cursor encodes the last seen id\n const cursorValue = Number.parseInt(paging.cursor, 10);\n if (cursorValue > 0) {\n query = query.where(\"id\", \">\", cursorValue);\n }\n\n // Apply limit if specified (fetch one extra to determine hasMore)\n if (paging.limit) {\n query = query.limit(paging.limit + 1);\n }\n }\n\n const rows = await query.execute();\n\n return paginateRows(\n rows,\n paging,\n (row) => row.id,\n (row) => this.rowToOperationWithContext(row),\n (cursor, limit) => this.getSinceId(id, { cursor, limit }, signal),\n );\n }\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 throwIfAborted(signal);\n\n let query = this.queryExecutor\n .selectFrom(\"Operation\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .where(\"scope\", \"=\", scope)\n .where(\"branch\", \"=\", branch)\n .where(\"timestampUtcMs\", \">=\", new Date(minTimestamp))\n .orderBy(\"index\", \"asc\");\n\n if (paging) {\n const cursorValue = Number.parseInt(paging.cursor, 10);\n if (cursorValue > 0) {\n query = query.where(\"index\", \">\", cursorValue);\n }\n\n if (paging.limit) {\n query = query.limit(paging.limit + 1);\n }\n }\n\n const rows = await query.execute();\n\n return paginateRows(\n rows,\n paging,\n (row) => row.index,\n (row) => this.rowToOperation(row),\n (cursor, limit) =>\n this.getConflicting(\n documentId,\n scope,\n branch,\n minTimestamp,\n { cursor, limit },\n signal,\n ),\n );\n }\n\n async getRevisions(\n documentId: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<DocumentRevisions> {\n throwIfAborted(signal);\n\n // Get the latest operation for each scope in a single query\n // Uses a subquery to find operations where the index equals the max index for that scope\n const scopeRevisions = await this.queryExecutor\n .selectFrom(\"Operation as o1\")\n .select([\"o1.scope\", \"o1.index\", \"o1.timestampUtcMs\"])\n .where(\"o1.documentId\", \"=\", documentId)\n .where(\"o1.branch\", \"=\", branch)\n .where((eb) =>\n eb(\n \"o1.index\",\n \"=\",\n eb\n .selectFrom(\"Operation as o2\")\n .select((eb2) => eb2.fn.max(\"o2.index\").as(\"maxIndex\"))\n .where(\"o2.documentId\", \"=\", eb.ref(\"o1.documentId\"))\n .where(\"o2.branch\", \"=\", eb.ref(\"o1.branch\"))\n .where(\"o2.scope\", \"=\", eb.ref(\"o1.scope\")),\n ),\n )\n .execute();\n\n const revision: Record<string, number> = {};\n let latestTimestamp = new Date(0).toISOString();\n\n for (const row of scopeRevisions) {\n revision[row.scope] = row.index + 1;\n const timestamp = row.timestampUtcMs.toISOString();\n if (timestamp > latestTimestamp) {\n latestTimestamp = timestamp;\n }\n }\n\n return {\n revision,\n latestTimestamp,\n };\n }\n\n private rowToOperation(row: OperationRow): Operation {\n return {\n index: row.index,\n timestampUtcMs: row.timestampUtcMs.toISOString(),\n hash: row.hash,\n skip: row.skip,\n error: row.error || undefined,\n id: row.opId,\n action: row.action as Operation[\"action\"],\n };\n }\n\n private rowToOperationWithContext(row: OperationRow): OperationWithContext {\n return {\n operation: this.rowToOperation(row),\n context: {\n documentId: row.documentId,\n documentType: row.documentType,\n scope: row.scope,\n branch: row.branch,\n ordinal: row.id,\n },\n };\n }\n}\n","import type { Pool, PoolClient } from \"pg\";\n\n/**\n * Snapshot of a pg.Pool's internal counters at a point in time.\n */\nexport type PoolStats = {\n /** Connections currently open (idle + in-use). pg.Pool.totalCount. */\n size: number;\n /** Open connections not currently checked out. pg.Pool.idleCount. */\n idle: number;\n /** Callers queued waiting for a connection. pg.Pool.waitingCount. */\n waiting: number;\n};\n\n/**\n * Observable handle over an instrumented pg.Pool. Surfaces acquire-wait\n * timing and pool-stat counters without coupling the consumer to the\n * underlying pg.Pool type.\n */\nexport type PoolInstrumentation = {\n /** Stable identifier for the pool (e.g. \"host\", \"worker\"). Used as a metric label. */\n readonly name: string;\n /** Current pool counters. Cheap, synchronous read off pg.Pool. */\n getStats(): PoolStats;\n /**\n * Subscribe to per-acquire wait durations. Listener fires once per\n * resolved pool.connect() call with the time spent waiting for a client.\n * Returns an unsubscribe function.\n */\n onAcquire(listener: (durationMs: number) => void): () => void;\n};\n\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 */\nexport function instrumentPgPool(\n pool: Pool,\n name: string,\n): PoolInstrumentation {\n const listeners = new Set<(durationMs: number) => void>();\n const originalConnect = pool.connect.bind(pool) as () => Promise<PoolClient>;\n const wrappedConnect = async (): Promise<PoolClient> => {\n const start = performance.now();\n const client = await originalConnect();\n const durationMs = performance.now() - start;\n for (const listener of listeners) {\n try {\n listener(durationMs);\n } catch {\n // listener failures must not break the acquire path\n }\n }\n return client;\n };\n pool.connect = wrappedConnect as typeof pool.connect;\n return {\n name,\n getStats(): PoolStats {\n return {\n size: pool.totalCount,\n idle: pool.idleCount,\n waiting: pool.waitingCount,\n };\n },\n onAcquire(listener: (durationMs: number) => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\n/**\n * Host-side {@link PoolInstrumentation} that re-emits acquire-wait samples\n * and pool-stat snapshots forwarded from a worker thread. The worker owns\n * the real pg.Pool; this object lets the host's OpenTelemetry instrumentation\n * subscribe to those events as if the pool were local.\n *\n * The host wires one of these per worker (one per executor worker, one per\n * projection shard). The worker batches acquire-wait durations and periodic\n * stats over its existing transport; the host pumps them in via\n * {@link pushSamples} / {@link updateStats}.\n */\nexport type ForwardingPoolInstrumentation = PoolInstrumentation & {\n pushSamples(durations: number[]): void;\n updateStats(stats: PoolStats): void;\n};\n\nexport function createForwardingPoolInstrumentation(\n name: string,\n): ForwardingPoolInstrumentation {\n const listeners = new Set<(durationMs: number) => void>();\n let stats: PoolStats = { size: 0, idle: 0, waiting: 0 };\n return {\n name,\n getStats(): PoolStats {\n return stats;\n },\n onAcquire(listener: (durationMs: number) => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n pushSamples(durations: number[]): void {\n for (const durationMs of durations) {\n for (const listener of listeners) {\n try {\n listener(durationMs);\n } catch {\n // listener failures must not break sample forwarding\n }\n }\n }\n },\n updateStats(next: PoolStats): void {\n stats = next;\n },\n };\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"Operation\")\n .addColumn(\"id\", \"serial\", (col) => col.primaryKey())\n .addColumn(\"jobId\", \"text\", (col) => col.notNull())\n .addColumn(\"opId\", \"text\", (col) => col.notNull())\n .addColumn(\"prevOpId\", \"text\", (col) => col.notNull())\n .addColumn(\"writeTimestampUtcMs\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"documentId\", \"text\", (col) => col.notNull())\n .addColumn(\"documentType\", \"text\", (col) => col.notNull())\n .addColumn(\"scope\", \"text\", (col) => col.notNull())\n .addColumn(\"branch\", \"text\", (col) => col.notNull())\n .addColumn(\"timestampUtcMs\", \"timestamptz\", (col) => col.notNull())\n .addColumn(\"index\", \"integer\", (col) => col.notNull())\n .addColumn(\"action\", \"jsonb\", (col) => col.notNull())\n .addColumn(\"skip\", \"integer\", (col) => col.notNull())\n .addColumn(\"error\", \"text\")\n .addColumn(\"hash\", \"text\", (col) => col.notNull())\n .addUniqueConstraint(\"unique_revision\", [\n \"documentId\",\n \"scope\",\n \"branch\",\n \"index\",\n ])\n .addUniqueConstraint(\"unique_operation_instance\", [\"opId\", \"index\", \"skip\"])\n .execute();\n\n // Create index for streaming operations\n await db.schema\n .createIndex(\"streamOperations\")\n .on(\"Operation\")\n .columns([\"documentId\", \"scope\", \"branch\", \"id\"])\n .execute();\n\n // Create index for branchless streaming operations\n await db.schema\n .createIndex(\"branchlessStreamOperations\")\n .on(\"Operation\")\n .columns([\"documentId\", \"scope\", \"id\"])\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"Keyframe\")\n .addColumn(\"id\", \"serial\", (col) => col.primaryKey())\n .addColumn(\"documentId\", \"text\", (col) => col.notNull())\n .addColumn(\"documentType\", \"text\", (col) => col.notNull())\n .addColumn(\"scope\", \"text\", (col) => col.notNull())\n .addColumn(\"branch\", \"text\", (col) => col.notNull())\n .addColumn(\"revision\", \"integer\", (col) => col.notNull())\n .addColumn(\"document\", \"jsonb\", (col) => col.notNull())\n .addColumn(\"createdAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addUniqueConstraint(\"unique_keyframe\", [\n \"documentId\",\n \"scope\",\n \"branch\",\n \"revision\",\n ])\n .execute();\n\n // Create index for keyframe lookup\n await db.schema\n .createIndex(\"keyframe_lookup\")\n .on(\"Keyframe\")\n .columns([\"documentId\", \"scope\", \"branch\", \"revision\"])\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"Document\")\n .addColumn(\"id\", \"text\", (col) => col.primaryKey())\n .addColumn(\"createdAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"DocumentRelationship\")\n .addColumn(\"id\", \"text\", (col) => col.primaryKey())\n .addColumn(\"sourceId\", \"text\", (col) =>\n col.notNull().references(\"Document.id\").onDelete(\"cascade\"),\n )\n .addColumn(\"targetId\", \"text\", (col) =>\n col.notNull().references(\"Document.id\").onDelete(\"cascade\"),\n )\n .addColumn(\"relationshipType\", \"text\", (col) => col.notNull())\n .addColumn(\"metadata\", \"jsonb\")\n .addColumn(\"createdAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addUniqueConstraint(\"unique_source_target_type\", [\n \"sourceId\",\n \"targetId\",\n \"relationshipType\",\n ])\n .execute();\n\n // Create indexes for efficient graph traversal\n await db.schema\n .createIndex(\"idx_relationship_source\")\n .on(\"DocumentRelationship\")\n .column(\"sourceId\")\n .execute();\n\n await db.schema\n .createIndex(\"idx_relationship_target\")\n .on(\"DocumentRelationship\")\n .column(\"targetId\")\n .execute();\n\n await db.schema\n .createIndex(\"idx_relationship_type\")\n .on(\"DocumentRelationship\")\n .column(\"relationshipType\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"IndexerState\")\n .addColumn(\"id\", \"integer\", (col) =>\n col.primaryKey().generatedAlwaysAsIdentity(),\n )\n .addColumn(\"lastOperationId\", \"integer\", (col) => col.notNull())\n .addColumn(\"lastOperationTimestamp\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"DocumentSnapshot\")\n .addColumn(\"id\", \"text\", (col) => col.primaryKey())\n .addColumn(\"documentId\", \"text\", (col) => col.notNull())\n .addColumn(\"slug\", \"text\")\n .addColumn(\"name\", \"text\")\n .addColumn(\"scope\", \"text\", (col) => col.notNull())\n .addColumn(\"branch\", \"text\", (col) => col.notNull())\n .addColumn(\"content\", \"jsonb\", (col) => col.notNull())\n .addColumn(\"documentType\", \"text\", (col) => col.notNull())\n .addColumn(\"lastOperationIndex\", \"integer\", (col) => col.notNull())\n .addColumn(\"lastOperationHash\", \"text\", (col) => col.notNull())\n .addColumn(\"lastUpdatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"snapshotVersion\", \"integer\", (col) =>\n col.notNull().defaultTo(1),\n )\n .addColumn(\"identifiers\", \"jsonb\")\n .addColumn(\"metadata\", \"jsonb\")\n .addColumn(\"isDeleted\", \"boolean\", (col) => col.notNull().defaultTo(false))\n .addColumn(\"deletedAt\", \"timestamptz\")\n .addUniqueConstraint(\"unique_doc_scope_branch\", [\n \"documentId\",\n \"scope\",\n \"branch\",\n ])\n .execute();\n\n // Create indexes for query optimization\n await db.schema\n .createIndex(\"idx_slug_scope_branch\")\n .on(\"DocumentSnapshot\")\n .columns([\"slug\", \"scope\", \"branch\"])\n .execute();\n\n await db.schema\n .createIndex(\"idx_doctype_scope_branch\")\n .on(\"DocumentSnapshot\")\n .columns([\"documentType\", \"scope\", \"branch\"])\n .execute();\n\n await db.schema\n .createIndex(\"idx_last_updated\")\n .on(\"DocumentSnapshot\")\n .column(\"lastUpdatedAt\")\n .execute();\n\n await db.schema\n .createIndex(\"idx_is_deleted\")\n .on(\"DocumentSnapshot\")\n .column(\"isDeleted\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"SlugMapping\")\n .addColumn(\"slug\", \"text\", (col) => col.primaryKey())\n .addColumn(\"documentId\", \"text\", (col) => col.notNull())\n .addColumn(\"scope\", \"text\", (col) => col.notNull())\n .addColumn(\"branch\", \"text\", (col) => col.notNull())\n .addColumn(\"createdAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addUniqueConstraint(\"unique_docid_scope_branch\", [\n \"documentId\",\n \"scope\",\n \"branch\",\n ])\n .execute();\n\n // Create index for reverse lookup (documentId -> slug)\n await db.schema\n .createIndex(\"idx_slug_documentid\")\n .on(\"SlugMapping\")\n .column(\"documentId\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await db.schema\n .createTable(\"ViewState\")\n .addColumn(\"readModelId\", \"text\", (col) => col.primaryKey())\n .addColumn(\"lastOrdinal\", \"integer\", (col) => col.notNull().defaultTo(0))\n .addColumn(\"lastOperationTimestamp\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"document_collections\")\n .addColumn(\"documentId\", \"text\", (col) => col.notNull())\n .addColumn(\"collectionId\", \"text\", (col) => col.notNull())\n .addColumn(\"joinedOrdinal\", \"bigint\", (col) => col.notNull().defaultTo(0))\n .addColumn(\"leftOrdinal\", \"bigint\")\n .addPrimaryKeyConstraint(\"document_collections_pkey\", [\n \"documentId\",\n \"collectionId\",\n ])\n .execute();\n\n await db.schema\n .createIndex(\"idx_document_collections_collectionId\")\n .on(\"document_collections\")\n .column(\"collectionId\")\n .execute();\n\n await db.schema\n .createIndex(\"idx_doc_collections_collection_range\")\n .on(\"document_collections\")\n .columns([\"collectionId\", \"joinedOrdinal\"])\n .execute();\n\n await db.schema\n .createTable(\"operation_index_operations\")\n .addColumn(\"ordinal\", \"serial\", (col) => col.primaryKey())\n .addColumn(\"opId\", \"text\", (col) => col.notNull())\n .addColumn(\"documentId\", \"text\", (col) => col.notNull())\n .addColumn(\"documentType\", \"text\", (col) => col.notNull())\n .addColumn(\"scope\", \"text\", (col) => col.notNull())\n .addColumn(\"branch\", \"text\", (col) => col.notNull())\n .addColumn(\"timestampUtcMs\", \"text\", (col) => col.notNull())\n .addColumn(\"writeTimestampUtcMs\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"index\", \"integer\", (col) => col.notNull())\n .addColumn(\"skip\", \"integer\", (col) => col.notNull())\n .addColumn(\"hash\", \"text\", (col) => col.notNull())\n .addColumn(\"action\", \"jsonb\", (col) => col.notNull())\n .execute();\n\n await db.schema\n .createIndex(\"idx_operation_index_operations_document\")\n .on(\"operation_index_operations\")\n .columns([\"documentId\", \"branch\", \"scope\"])\n .execute();\n\n await db.schema\n .createIndex(\"idx_operation_index_operations_ordinal\")\n .on(\"operation_index_operations\")\n .column(\"ordinal\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"sync_remotes\")\n .addColumn(\"name\", \"text\", (col) => col.primaryKey())\n .addColumn(\"collection_id\", \"text\", (col) => col.notNull())\n .addColumn(\"channel_type\", \"text\", (col) => col.notNull())\n .addColumn(\"channel_id\", \"text\", (col) => col.notNull().defaultTo(\"\"))\n .addColumn(\"remote_name\", \"text\", (col) => col.notNull().defaultTo(\"\"))\n .addColumn(\"channel_parameters\", \"jsonb\", (col) =>\n col.notNull().defaultTo(sql`'{}'::jsonb`),\n )\n .addColumn(\"filter_document_ids\", \"jsonb\")\n .addColumn(\"filter_scopes\", \"jsonb\")\n .addColumn(\"filter_branch\", \"text\", (col) =>\n col.notNull().defaultTo(\"main\"),\n )\n .addColumn(\"push_state\", \"text\", (col) => col.notNull().defaultTo(\"idle\"))\n .addColumn(\"push_last_success_utc_ms\", \"text\")\n .addColumn(\"push_last_failure_utc_ms\", \"text\")\n .addColumn(\"push_failure_count\", \"integer\", (col) =>\n col.notNull().defaultTo(0),\n )\n .addColumn(\"pull_state\", \"text\", (col) => col.notNull().defaultTo(\"idle\"))\n .addColumn(\"pull_last_success_utc_ms\", \"text\")\n .addColumn(\"pull_last_failure_utc_ms\", \"text\")\n .addColumn(\"pull_failure_count\", \"integer\", (col) =>\n col.notNull().defaultTo(0),\n )\n .addColumn(\"created_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"updated_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n\n await db.schema\n .createIndex(\"idx_sync_remotes_collection\")\n .on(\"sync_remotes\")\n .column(\"collection_id\")\n .execute();\n\n await db.schema\n .createTable(\"sync_cursors\")\n .addColumn(\"remote_name\", \"text\", (col) =>\n col.primaryKey().references(\"sync_remotes.name\").onDelete(\"cascade\"),\n )\n .addColumn(\"cursor_ordinal\", \"bigint\", (col) => col.notNull().defaultTo(0))\n .addColumn(\"last_synced_at_utc_ms\", \"text\")\n .addColumn(\"updated_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n\n await db.schema\n .createIndex(\"idx_sync_cursors_ordinal\")\n .on(\"sync_cursors\")\n .column(\"cursor_ordinal\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n // Delete any leftover fake \"outbox::\" cursor rows and remote records\n await db\n .deleteFrom(\"sync_cursors\")\n .where(\"remote_name\", \"like\", \"outbox::%\")\n .execute();\n await db\n .deleteFrom(\"sync_remotes\")\n .where(\"name\", \"like\", \"outbox::%\")\n .execute();\n\n // Recreate sync_cursors with cursor_type column and composite PK (no FK)\n await db.schema.dropTable(\"sync_cursors\").execute();\n\n await db.schema\n .createTable(\"sync_cursors\")\n .addColumn(\"remote_name\", \"text\", (col) => col.notNull())\n .addColumn(\"cursor_type\", \"text\", (col) => col.notNull().defaultTo(\"inbox\"))\n .addColumn(\"cursor_ordinal\", \"bigint\", (col) => col.notNull().defaultTo(0))\n .addColumn(\"last_synced_at_utc_ms\", \"text\")\n .addColumn(\"updated_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addPrimaryKeyConstraint(\"sync_cursors_pk\", [\"remote_name\", \"cursor_type\"])\n .execute();\n\n await db.schema\n .createIndex(\"idx_sync_cursors_ordinal\")\n .on(\"sync_cursors\")\n .column(\"cursor_ordinal\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .alterTable(\"operation_index_operations\")\n .addColumn(\"sourceRemote\", \"text\", (col) => col.notNull().defaultTo(\"\"))\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"sync_dead_letters\")\n .addColumn(\"ordinal\", \"serial\", (col) => col.primaryKey())\n .addColumn(\"id\", \"text\", (col) => col.unique().notNull())\n .addColumn(\"job_id\", \"text\", (col) => col.notNull())\n .addColumn(\"job_dependencies\", \"jsonb\", (col) =>\n col.notNull().defaultTo(sql`'[]'::jsonb`),\n )\n .addColumn(\"remote_name\", \"text\", (col) =>\n col.notNull().references(\"sync_remotes.name\").onDelete(\"cascade\"),\n )\n .addColumn(\"document_id\", \"text\", (col) => col.notNull())\n .addColumn(\"scopes\", \"jsonb\", (col) =>\n col.notNull().defaultTo(sql`'[]'::jsonb`),\n )\n .addColumn(\"branch\", \"text\", (col) => col.notNull())\n .addColumn(\"operations\", \"jsonb\", (col) =>\n col.notNull().defaultTo(sql`'[]'::jsonb`),\n )\n .addColumn(\"error_source\", \"text\", (col) => col.notNull())\n .addColumn(\"error_message\", \"text\", (col) => col.notNull())\n .addColumn(\"created_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n\n await db.schema\n .createIndex(\"idx_sync_dead_letters_remote\")\n .on(\"sync_dead_letters\")\n .column(\"remote_name\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"ProcessorCursor\")\n .addColumn(\"processorId\", \"text\", (col) => col.primaryKey())\n .addColumn(\"factoryId\", \"text\", (col) => col.notNull())\n .addColumn(\"driveId\", \"text\", (col) => col.notNull())\n .addColumn(\"processorIndex\", \"integer\", (col) => col.notNull())\n .addColumn(\"lastOrdinal\", \"integer\", (col) =>\n col.notNull().defaultTo(sql`0`),\n )\n .addColumn(\"status\", \"text\", (col) =>\n col.notNull().defaultTo(sql`'active'`),\n )\n .addColumn(\"lastError\", \"text\")\n .addColumn(\"lastErrorTimestamp\", \"timestamptz\")\n .addColumn(\"createdAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .addColumn(\"updatedAt\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(sql`NOW()`),\n )\n .execute();\n}\n","import { Migrator, sql } from \"kysely\";\nimport type { MigrationProvider, Kysely } from \"kysely\";\nimport type { MigrationResult } from \"./types.js\";\n\nexport const REACTOR_SCHEMA = \"reactor\";\nimport * as migration001 from \"./001_create_operation_table.js\";\nimport * as migration002 from \"./002_create_keyframe_table.js\";\nimport * as migration003 from \"./003_create_document_table.js\";\nimport * as migration004 from \"./004_create_document_relationship_table.js\";\nimport * as migration005 from \"./005_create_indexer_state_table.js\";\nimport * as migration006 from \"./006_create_document_snapshot_table.js\";\nimport * as migration007 from \"./007_create_slug_mapping_table.js\";\nimport * as migration008 from \"./008_create_view_state_table.js\";\nimport * as migration009 from \"./009_create_operation_index_tables.js\";\nimport * as migration010 from \"./010_create_sync_tables.js\";\nimport * as migration011 from \"./011_add_cursor_type_column.js\";\nimport * as migration012 from \"./012_add_source_remote_column.js\";\nimport * as migration013 from \"./013_create_sync_dead_letters_table.js\";\nimport * as migration014 from \"./014_create_processor_cursor_table.js\";\n\nconst migrations = {\n \"001_create_operation_table\": migration001,\n \"002_create_keyframe_table\": migration002,\n \"003_create_document_table\": migration003,\n \"004_create_document_relationship_table\": migration004,\n \"005_create_indexer_state_table\": migration005,\n \"006_create_document_snapshot_table\": migration006,\n \"007_create_slug_mapping_table\": migration007,\n \"008_create_view_state_table\": migration008,\n \"009_create_operation_index_tables\": migration009,\n \"010_create_sync_tables\": migration010,\n \"011_add_cursor_type_column\": migration011,\n \"012_add_source_remote_column\": migration012,\n \"013_create_sync_dead_letters_table\": migration013,\n \"014_create_processor_cursor_table\": migration014,\n};\n\nclass ProgrammaticMigrationProvider implements MigrationProvider {\n getMigrations() {\n return Promise.resolve(migrations);\n }\n}\n\nexport async function runMigrations(\n db: Kysely<any>,\n schema: string = REACTOR_SCHEMA,\n): Promise<MigrationResult> {\n try {\n await sql`CREATE SCHEMA IF NOT EXISTS ${sql.id(schema)}`.execute(db);\n } catch (error) {\n return {\n success: false,\n migrationsExecuted: [],\n error:\n error instanceof Error ? error : new Error(\"Failed to create schema\"),\n };\n }\n\n const migrator = new Migrator({\n db: db.withSchema(schema),\n provider: new ProgrammaticMigrationProvider(),\n migrationTableSchema: schema,\n });\n\n let error: unknown;\n let results: Awaited<ReturnType<typeof migrator.migrateToLatest>>[\"results\"];\n try {\n const result = await migrator.migrateToLatest();\n error = result.error;\n results = result.results;\n } catch (e) {\n error = e;\n results = [];\n }\n\n const migrationsExecuted =\n results?.map((result) => result.migrationName) ?? [];\n\n if (error) {\n return {\n success: false,\n migrationsExecuted,\n error:\n error instanceof Error ? error : new Error(\"Unknown migration error\"),\n };\n }\n\n return {\n success: true,\n migrationsExecuted,\n };\n}\n\nexport async function getMigrationStatus(\n db: Kysely<any>,\n schema: string = REACTOR_SCHEMA,\n) {\n const migrator = new Migrator({\n db: db.withSchema(schema),\n provider: new ProgrammaticMigrationProvider(),\n migrationTableSchema: schema,\n });\n\n return await migrator.getMigrations();\n}\n","export const DEFAULT_DRIVE_CONTAINER_TYPES: ReadonlySet<string> = new Set([\n \"powerhouse/document-drive\",\n \"powerhouse/reactor-drive\",\n]);\n"],"mappings":"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"}