@powerhousedao/reactor 6.2.2-dev.5 → 6.2.2-dev.50

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drive-container-types-BoY5t12r.js","names":["applyUpgradeDocumentAction","applyDeleteDocumentAction","applyUpgradeDocumentAction","DowngradeNotSupportedError","uuidv4","up","up","up","up","up","up","up","up","up","up","up","up","up","up","up","down","up","down","migration001","migration002","migration003","migration004","migration005","migration006","migration007","migration008","migration009","migration010","migration011","migration012","migration013","migration014","migration015","migration016","migration017"],"sources":["../src/shared/utils.ts","../src/shared/errors.ts","../src/decision/build-decision-model.ts","../src/decision/auth-decision-model.ts","../src/decision/document-decision-model.ts","../src/decision/registered-model.ts","../src/registry/errors.ts","../src/storage/interfaces.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/write-cache-types.ts","../src/cache/kysely-write-cache.ts","../src/events/event-bus.ts","../src/core/feature-flags.ts","../src/executor/execution-scope.ts","../src/utils/reshuffle.ts","../src/decision/merged-order.ts","../src/decision/walk.ts","../src/decision/evaluation.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/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/015_add_operation_denied_reason.ts","../src/storage/migrations/016_add_dead_letter_error_type.ts","../src/storage/migrations/017_create_group_references.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 the auth policy denies an action at the executor gate.\n */\nexport class AuthorizationDeniedError extends Error {\n public readonly documentId: string;\n public readonly scope: string;\n public readonly operation: string;\n public readonly subject: string | undefined;\n\n constructor(\n documentId: string,\n scope: string,\n operation: string,\n subject?: string,\n ) {\n super(\n `Authorization denied: ${subject ?? \"anonymous\"} may not execute ${operation} in scope \"${scope}\" of document ${documentId}`,\n );\n this.name = \"AuthorizationDeniedError\";\n this.documentId = documentId;\n this.scope = scope;\n this.operation = operation;\n this.subject = subject;\n\n Error.captureStackTrace(this, AuthorizationDeniedError);\n }\n\n static isError(error: unknown): error is AuthorizationDeniedError {\n return Error.isError(error) && error.name === \"AuthorizationDeniedError\";\n }\n}\n\n/**\n * An auth operation did not strictly exceed the newest timestamp in its stream.\n *\n * Terminal and asymmetric by design: no ordering rule can reconcile two replicas\n * that each accepted an auth operation offline, because either order hands one\n * authority the other never granted, so the replica ahead holds the arrival.\n */\nexport class AuthTimestampNotMonotonicError extends Error {\n public readonly documentId: string;\n public readonly branch: string;\n public readonly timestampUtcMs: string;\n public readonly newestTimestampUtcMs: string;\n\n constructor(\n documentId: string,\n branch: string,\n timestampUtcMs: string,\n newestTimestampUtcMs: string,\n ) {\n super(\n `Auth timestamp not monotonic: ${timestampUtcMs} does not exceed ${newestTimestampUtcMs} in the auth stream of document ${documentId} on branch ${branch}`,\n );\n this.name = \"AuthTimestampNotMonotonicError\";\n this.documentId = documentId;\n this.branch = branch;\n this.timestampUtcMs = timestampUtcMs;\n this.newestTimestampUtcMs = newestTimestampUtcMs;\n\n Error.captureStackTrace(this, AuthTimestampNotMonotonicError);\n }\n\n static isError(error: unknown): error is AuthTimestampNotMonotonicError {\n return (\n Error.isError(error) && error.name === \"AuthTimestampNotMonotonicError\"\n );\n }\n}\n\n/**\n * An operation or action carried a timestamp that is not an ISO-8601 UTC\n * instant.\n *\n * Terminal rather than retryable: the value does not change between attempts,\n * so a retry re-runs the whole job to fail identically. Quarantining, unlike a\n * held auth operation — this is malformed data rather than two replicas\n * disagreeing, and nothing further from that source should be trusted until it\n * is looked at.\n */\nexport class InvalidOperationTimestampError extends Error {\n public readonly documentId: string;\n public readonly scope: string;\n public readonly timestampUtcMs: string;\n\n constructor(\n documentId: string,\n scope: string,\n timestampUtcMs: string,\n context: string,\n ) {\n super(\n `Invalid timestamp \"${timestampUtcMs}\" on ${context} in scope \"${scope}\" of document ${documentId}`,\n );\n this.name = \"InvalidOperationTimestampError\";\n this.documentId = documentId;\n this.scope = scope;\n this.timestampUtcMs = timestampUtcMs;\n\n Error.captureStackTrace(this, InvalidOperationTimestampError);\n }\n\n static isError(error: unknown): error is InvalidOperationTimestampError {\n return (\n Error.isError(error) && error.name === \"InvalidOperationTimestampError\"\n );\n }\n}\n\n/**\n * A load would move more operations than the bound allows, indicating a real\n * divergence between local and incoming history. Counts only first-time moves,\n * so a re-evaluation pass's re-appends do not make busy documents\n * revocation-proof. Terminal: the condition is deterministic.\n */\nexport class ExcessiveReshuffleError extends Error {\n public readonly documentId: string;\n public readonly scope: string;\n public readonly count: number;\n public readonly threshold: number;\n\n constructor(\n documentId: string,\n scope: string,\n count: number,\n threshold: number,\n ) {\n super(\n `Excessive reshuffle detected: ${count} operations in scope \"${scope}\" of document ${documentId} exceeds the threshold of ${threshold}. This indicates a significant divergence between local and incoming operations.`,\n );\n this.name = \"ExcessiveReshuffleError\";\n this.documentId = documentId;\n this.scope = scope;\n this.count = count;\n this.threshold = threshold;\n\n Error.captureStackTrace(this, ExcessiveReshuffleError);\n }\n\n static isError(error: unknown): error is ExcessiveReshuffleError {\n return Error.isError(error) && error.name === \"ExcessiveReshuffleError\";\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\nexport { DowngradeNotSupportedError } from \"@powerhousedao/shared/document-model\";\n\n/**\n * An UPGRADE_DOCUMENT action's preconditions (fromVersion and the per-scope\n * revision snapshot) did not match the document state the executor loaded.\n *\n * Terminal rather than retryable: the action carries the client's snapshot,\n * which stays stale no matter how often the job re-runs. The client is\n * expected to re-read the document and submit a fresh action instead.\n */\nexport class UpgradePreconditionFailedError extends Error {\n public readonly documentId: string;\n public readonly detail: string;\n\n constructor(documentId: string, detail: string) {\n super(`Upgrade precondition failed for document ${documentId}: ${detail}`);\n this.name = \"UpgradePreconditionFailedError\";\n this.documentId = documentId;\n this.detail = detail;\n\n Error.captureStackTrace(this, UpgradePreconditionFailedError);\n }\n\n static isError(error: unknown): error is UpgradePreconditionFailedError {\n return (\n Error.isError(error) && error.name === \"UpgradePreconditionFailedError\"\n );\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","import type {\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { DocumentNotFoundError } from \"../shared/errors.js\";\nimport type { AppendConditionStream } from \"../storage/interfaces.js\";\nimport type {\n BuiltDecisionModel,\n DecisionModel,\n DecisionTarget,\n IStreamStateReader,\n Projection,\n ReadStream,\n StreamHistory,\n StreamQuery,\n} from \"./types.js\";\n\ntype StreamRead = {\n state: unknown;\n stream: AppendConditionStream;\n};\n\n/**\n * Reads each projection's stream through the supplied reader, recording the\n * revision observed. Static projections resolve first; derived projections\n * see only those and contribute a map from document id to state. Each\n * distinct stream is read once and yields one append condition entry.\n */\nexport async function buildDecisionModel<M>(\n reader: IStreamStateReader,\n definition: (target: DecisionTarget) => DecisionModel<M>,\n target: DecisionTarget,\n signal?: AbortSignal,\n): Promise<BuiltDecisionModel<M>> {\n const decisionModel = definition(target);\n const projections = Object.entries(decisionModel.projections) as Array<\n [string, Projection<M>]\n >;\n\n const reads = new Map<string, StreamRead>();\n const model: Record<string, unknown> = {};\n\n for (const [key, projection] of projections) {\n if (typeof projection.query === \"function\") {\n continue;\n }\n\n const read = await readStream(reader, projection.query, reads, signal);\n model[key] = read.state;\n }\n\n const staticModel = { ...model } as Partial<M>;\n\n for (const [key, projection] of projections) {\n if (typeof projection.query !== \"function\") {\n continue;\n }\n\n const queries = projection.query(staticModel);\n const value: Record<string, unknown> = {};\n for (const query of queries) {\n // A derived stream can name a document this replica does not hold (a\n // group not yet synced, or never reachable). It stays out of the model,\n // which fails closed, but its condition entry still guards the append:\n // the document arriving with operations before commit is a conflict.\n let read: StreamRead;\n try {\n read = await readStream(reader, query, reads, signal);\n } catch (error) {\n if (error instanceof DocumentNotFoundError) {\n recordEmptyStream(query, reads);\n continue;\n }\n throw error;\n }\n value[query.documentId] = read.state;\n }\n\n model[key] = value;\n }\n\n const streams = [...reads.values()].map((read) => read.stream);\n\n return {\n model: model as M,\n appendCondition: { streams },\n };\n}\n\n/** Guards a stream that holds nothing yet: any operation appearing is growth. */\nfunction recordEmptyStream(\n query: StreamQuery,\n reads: Map<string, StreamRead>,\n): void {\n const key = `${query.documentId}:${query.scope}:${query.branch}`;\n if (reads.has(key)) {\n return;\n }\n reads.set(key, {\n state: undefined,\n stream: {\n documentId: query.documentId,\n scope: query.scope,\n branch: query.branch,\n revision: -1,\n },\n });\n}\n\nasync function readStream(\n reader: IStreamStateReader,\n query: StreamQuery,\n reads: Map<string, StreamRead>,\n signal?: AbortSignal,\n): Promise<StreamRead> {\n const key = `${query.documentId}:${query.scope}:${query.branch}`;\n const existing = reads.get(key);\n if (existing) {\n return existing;\n }\n\n const document = await reader.getState(\n query.documentId,\n query.scope,\n query.branch,\n undefined,\n signal,\n );\n\n const read: StreamRead = {\n state: (document.state as Record<string, unknown>)[query.scope],\n stream: {\n documentId: query.documentId,\n scope: query.scope,\n branch: query.branch,\n revision: observedRevision(document, query.scope),\n },\n };\n\n reads.set(key, read);\n return read;\n}\n\n/**\n * The highest operation index the document reflects for the scope, or -1 if\n * empty. `header.revision` is authoritative, not the rebuilt operation list.\n */\nfunction observedRevision(document: PHDocument, scope: string): number {\n if (scope in document.header.revision) {\n return document.header.revision[scope] - 1;\n }\n\n if (scope in document.operations) {\n const operations = document.operations[scope];\n if (operations.length > 0) {\n return operations[operations.length - 1].index;\n }\n }\n\n if (!(scope in document.header.revision)) {\n return -1;\n }\n\n return document.header.revision[scope] - 1;\n}\n\n/** A derived projection, named; its streams are known only per evaluated range. */\nexport type DerivedProjection = {\n name: string;\n decidingActions: string[];\n apply: (document: PHDocument, operation: Operation) => PHDocument;\n queryOverHistory?: (reads: StreamHistory[]) => StreamQuery[];\n};\n\n/**\n * The projections whose queries depend on folded state. A positional walk\n * resolves their streams through `queryOverHistory`; a projection without one\n * contributes no streams to a walk.\n */\nexport function derivedReadSet<M>(\n definition: DecisionModel<M>,\n): DerivedProjection[] {\n const projections: DerivedProjection[] = [];\n\n for (const [name, projection] of Object.entries(\n definition.projections,\n ) as Array<[string, Projection<M>]>) {\n if (typeof projection.query !== \"function\") {\n continue;\n }\n projections.push({\n name,\n decidingActions: projection.decidingActions,\n apply: projection.apply,\n queryOverHistory: projection.queryOverHistory,\n });\n }\n\n return projections;\n}\n\n/**\n * The streams a model reads whose queries are known before it is built. A\n * derived query needs the statically-queried projections first, so it is not\n * included here.\n */\nexport function staticReadSet<M>(definition: DecisionModel<M>): ReadStream[] {\n const streams: ReadStream[] = [];\n\n for (const [name, projection] of Object.entries(\n definition.projections,\n ) as Array<[string, Projection<M>]>) {\n if (typeof projection.query === \"function\") {\n continue;\n }\n streams.push({\n name,\n query: projection.query,\n decidingActions: projection.decidingActions,\n apply: projection.apply,\n });\n }\n\n return streams;\n}\n","import type {\n AuthGroups,\n AuthRefusal,\n AuthRequest,\n AuthSubject,\n ConditionContext,\n Operation,\n PHAuthState,\n PHDocument,\n PHDocumentState,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n applyAuthAction,\n applyDeleteDocumentAction,\n AUTH_ACTION_TYPES,\n AUTH_DENIED_BY_GRANT_REASON,\n AUTH_NO_GRANT_REASON,\n AUTH_VERSION_UNSUPPORTED_REASON,\n DOCUMENT_DELETED_REASON,\n evaluate,\n groupDocumentType,\n groupMembershipActionTypes,\n mentionedGroupIds,\n normalizeDocumentModelVersion,\n referencedGroupIds,\n} from \"@powerhousedao/shared/document-model\";\nimport type { IDocumentModelRegistry } from \"../registry/interfaces.js\";\nimport type {\n DecisionModel,\n DecisionTarget,\n Evaluation,\n Projection,\n} from \"./types.js\";\n\nexport type AuthDecisionModel = {\n document: PHDocumentState;\n auth: PHAuthState;\n};\n\n/** The auth model with the referenced group documents folded in. */\nexport type AuthGroupsDecisionModel = AuthDecisionModel & {\n groups: AuthGroups;\n};\n\nfunction refusalReason(refusal: AuthRefusal): string {\n switch (refusal) {\n case \"version-unsupported\":\n return AUTH_VERSION_UNSUPPORTED_REASON;\n case \"denied-by-grant\":\n return AUTH_DENIED_BY_GRANT_REASON;\n case \"no-applicable-grant\":\n return AUTH_NO_GRANT_REASON;\n }\n}\n\nfunction decideAuthModel(\n model: AuthDecisionModel,\n subject: AuthSubject,\n request: AuthRequest,\n groups?: AuthGroups,\n conditions?: ConditionContext,\n): Evaluation {\n // A read has no position, so deletion does not gate it.\n if (request.verb === \"execute\" && model.document.isDeleted) {\n return { decision: \"deny\", reason: DOCUMENT_DELETED_REASON };\n }\n\n const evaluation = evaluate(model.auth, subject, request, groups, conditions);\n if (evaluation.decision === \"allow\") {\n return { decision: \"allow\" };\n }\n\n return { decision: \"deny\", reason: refusalReason(evaluation.refusal) };\n}\n\nfunction documentProjection<M>(target: DecisionTarget): Projection<M> {\n return {\n decidingActions: [\"DELETE_DOCUMENT\"],\n\n apply: (document, operation) =>\n operation.action.type === \"DELETE_DOCUMENT\"\n ? // this apply function mutates, so we pass in a copy\n applyDeleteDocumentAction(\n { ...document, state: { ...document.state } },\n operation.action as never,\n )\n : document,\n\n query: {\n documentId: target.documentId,\n branch: target.branch,\n scope: \"document\",\n },\n };\n}\n\nfunction authProjection<M>(target: DecisionTarget): Projection<M> {\n return {\n decidingActions: [...AUTH_ACTION_TYPES],\n\n // Every auth handler returns new objects already.\n apply: (document, operation) => applyAuthAction(document, operation.action),\n\n query: {\n documentId: target.documentId,\n branch: target.branch,\n scope: \"auth\",\n },\n };\n}\n\n/** This decision model uses both the document and the auth streams. */\nexport function authDecisionModel(\n target: DecisionTarget,\n): DecisionModel<AuthDecisionModel> {\n return {\n projections: {\n document: documentProjection(target),\n auth: authProjection(target),\n },\n\n // The auth scope included: a delete can refuse an auth operation after it.\n evaluatesScope() {\n return true;\n },\n\n decide(model, subject, request): Evaluation {\n return decideAuthModel(model, subject, request);\n },\n };\n}\n\n/**\n * Folds one group-stream operation with the registered group model's reducer.\n * A reactor without the module registered folds nothing, so the member list\n * stays as read and a missing reducer never widens access.\n */\nfunction applyGroupOperation(\n registry: IDocumentModelRegistry,\n document: PHDocument,\n operation: Operation,\n): PHDocument {\n let reducer: (document: PHDocument, action: unknown) => PHDocument;\n try {\n const module = registry.getModule(groupDocumentType) as {\n reducer: (document: PHDocument, action: unknown) => PHDocument;\n };\n reducer = module.reducer;\n } catch {\n return document;\n }\n return reducer(document, operation.action);\n}\n\n/**\n * Folds one evaluated-scope operation with the reducer registered for the\n * document's own type, at the document's stamped version. A reactor without\n * that module folds nothing, so conditions read the base state and an\n * unresolvable reducer never widens access.\n */\nfunction applyModelOperation(\n registry: IDocumentModelRegistry,\n document: PHDocument,\n operation: Operation,\n): PHDocument {\n let reducer: (document: PHDocument, action: unknown) => PHDocument;\n try {\n const version = normalizeDocumentModelVersion(\n (document.state as { document?: { version?: number } }).document?.version,\n );\n const module = registry.getModule(\n document.header.documentType,\n version,\n ) as {\n reducer: (document: PHDocument, action: unknown) => PHDocument;\n };\n reducer = module.reducer;\n } catch {\n return document;\n }\n return reducer(document, operation.action);\n}\n\n/**\n * The auth model extended with a derived groups projection: the streams it\n * reads are the group documents the folded grant list names, so adding a\n * grant that names a new group pulls that group's stream into the read-set.\n * Group queries pin the main branch, because a group's member list lives on\n * its main branch no matter which branch the referencing document is on.\n */\nfunction groupsProjection(\n registry: IDocumentModelRegistry,\n): Projection<AuthGroupsDecisionModel> {\n return {\n decidingActions: [...groupMembershipActionTypes],\n\n apply: (document, operation) =>\n applyGroupOperation(registry, document, operation),\n\n query: (model) =>\n referencedGroupIds(model.auth?.grants ?? []).map((id) => ({\n documentId: id,\n branch: \"main\",\n scope: \"global\",\n })),\n\n // A positional walk reads the union of groups the auth range ever\n // names, because a grant referenced at one position folds membership\n // there even if a later operation removes it.\n queryOverHistory: (reads) => {\n const ids: string[] = [];\n for (const read of reads) {\n if (read.name !== \"auth\") {\n continue;\n }\n for (const operation of read.operations) {\n for (const id of mentionedGroupIds(operation.action)) {\n if (!ids.includes(id)) {\n ids.push(id);\n }\n }\n }\n }\n return ids.map((id) => ({\n documentId: id,\n branch: \"main\",\n scope: \"global\",\n }));\n },\n };\n}\n\nexport function authGroupsDecisionModel(\n registry: IDocumentModelRegistry,\n): (target: DecisionTarget) => DecisionModel<AuthGroupsDecisionModel> {\n return (target) => ({\n projections: {\n document: documentProjection(target),\n auth: authProjection(target),\n groups: groupsProjection(registry),\n },\n\n evaluatesScope() {\n return true;\n },\n\n decide(model, subject, request): Evaluation {\n return decideAuthModel(model, subject, request, model.groups);\n },\n });\n}\n\n/**\n * The groups model with conditions live: decide hands the executing scope's\n * state and the action input through to the evaluator, so `where` clauses\n * and { match } principals apply. The model folds the evaluated scope during\n * a positional walk, so a condition reads the state as it stood at each\n * operation's position.\n */\nexport function authConditionsDecisionModel(\n registry: IDocumentModelRegistry,\n): (target: DecisionTarget) => DecisionModel<AuthGroupsDecisionModel> {\n return (target) => ({\n projections: {\n document: documentProjection(target),\n auth: authProjection(target),\n groups: groupsProjection(registry),\n },\n\n foldEvaluatedScope: (document, operation) =>\n applyModelOperation(registry, document, operation),\n\n evaluatesScope() {\n return true;\n },\n\n decide(model, subject, request, ctx): Evaluation {\n return decideAuthModel(model, subject, request, model.groups, {\n scopeState: ctx.scopeState,\n actionInput: ctx.actionInput,\n });\n },\n });\n}\n","import type { PHDocumentState } from \"@powerhousedao/shared/document-model\";\nimport {\n applyDeleteDocumentAction,\n DOCUMENT_DELETED_REASON,\n} from \"@powerhousedao/shared/document-model\";\nimport type { DecisionModel, DecisionTarget } from \"./types.js\";\n\n/** What the document decision model reads: the target's document scope. */\nexport type DocumentDecisionModel = {\n document: PHDocumentState;\n};\n\n/**\n * The simplest decision model: one projection over the document scope, which\n * rejects on a deleted document.\n */\nexport function documentDecisionModel(\n target: DecisionTarget,\n): DecisionModel<DocumentDecisionModel> {\n return {\n projections: {\n document: {\n decidingActions: [\"DELETE_DOCUMENT\"],\n\n apply: (document, operation) =>\n operation.action.type === \"DELETE_DOCUMENT\"\n ? // this apply function mutates, so we pass in a copy\n applyDeleteDocumentAction(\n { ...document, state: { ...document.state } },\n operation.action as never,\n )\n : document,\n\n query: {\n documentId: target.documentId,\n branch: target.branch,\n scope: \"document\",\n },\n },\n },\n\n // this model needs to evaluate all scopes\n evaluatesScope() {\n return true;\n },\n\n decide(model, subject, request) {\n // A read has no position, so deletion does not gate it: the read surface\n // serves the state at the deletion boundary rather than refusing.\n return request.verb === \"execute\" && model.document.isDeleted\n ? { decision: \"deny\", reason: DOCUMENT_DELETED_REASON }\n : { decision: \"allow\" };\n },\n };\n}\n","import type {\n AuthRequest,\n AuthSubject,\n} from \"@powerhousedao/shared/document-model\";\nimport type { IWriteCache } from \"../cache/write/interfaces.js\";\nimport type { ReactorFeatureFlags } from \"../executor/types.js\";\nimport type { IDocumentModelRegistry } from \"../registry/interfaces.js\";\nimport type { AppendCondition } from \"../storage/interfaces.js\";\nimport {\n authConditionsDecisionModel,\n authDecisionModel,\n authGroupsDecisionModel,\n} from \"./auth-decision-model.js\";\nimport { buildDecisionModel } from \"./build-decision-model.js\";\nimport type { DocumentDecisionModel } from \"./document-decision-model.js\";\nimport { documentDecisionModel } from \"./document-decision-model.js\";\nimport type { DecisionModel, DecisionTarget, Evaluation } from \"./types.js\";\n\n/**\n * A model this reactor can register. Every one carries the document projection,\n * because admission reads the version and the deletion timestamp off it; a model\n * with more projections than that is still assignable here.\n */\nexport type RegisteredDecisionModel = (\n target: DecisionTarget,\n) => DecisionModel<DocumentDecisionModel>;\n\n/** What admission needs out of a model built at the stream heads. */\nexport type AdmissionDecision = {\n evaluation: Evaluation;\n appendCondition: AppendCondition;\n documentVersion: number;\n deletedAtUtcIso: string | null;\n};\n\n/**\n * What decideAtHead resolves a condition context from: the action's input,\n * with the executing scope's state read at the head. Supplied only while\n * authConditions is on.\n */\nexport type AdmissionConditions = {\n actionInput?: unknown;\n};\n\n/**\n * Builds the model at the stream heads and decides one request against it. The\n * append condition it returns is the read-set the store enforces at write time.\n *\n * With `conditions` supplied, the executing scope's state is read at the head\n * for `doc.<scope>.*` paths. That read carries no append-condition entry of\n * its own: the written stream's expected-revision check already refuses a\n * write whose scope grew between the read and the append.\n */\nexport async function decideAtHead(\n model: RegisteredDecisionModel,\n cache: IWriteCache,\n target: DecisionTarget,\n subject: AuthSubject,\n request: AuthRequest,\n signal?: AbortSignal,\n conditions?: AdmissionConditions,\n): Promise<AdmissionDecision> {\n const built = await buildDecisionModel(cache, model, target, signal);\n\n let scopeState: unknown;\n if (conditions !== undefined) {\n const document = await cache.getState(\n target.documentId,\n request.scope,\n target.branch,\n undefined,\n signal,\n );\n scopeState = (document.state as Record<string, unknown>)[request.scope];\n }\n\n return {\n evaluation: model(target).decide(built.model, subject, request, {\n scopeState,\n actionInput: conditions?.actionInput,\n }),\n appendCondition: built.appendCondition,\n documentVersion: built.model.document.version,\n deletedAtUtcIso: built.model.document.deletedAtUtcIso ?? null,\n };\n}\n\n/**\n * The model this reactor enforces. With `authEnforcement` off the auth scope is\n * absent from every append condition and no load walks it; with `authGroups`\n * on, the group documents the grant list names join the read-set and the\n * registry supplies the reducer that folds them.\n */\nexport function selectDecisionModel(\n flags: ReactorFeatureFlags,\n registry: IDocumentModelRegistry,\n): RegisteredDecisionModel {\n if (flags.authConditions) {\n return authConditionsDecisionModel(registry);\n }\n if (flags.authGroups) {\n return authGroupsDecisionModel(registry);\n }\n return flags.authEnforcement ? authDecisionModel : documentDecisionModel;\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\nexport { DowngradeNotSupportedError } from \"@powerhousedao/shared/document-model\";\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 {\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 {\n ChannelErrorSource,\n SyncOperationErrorType,\n} 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 * One read-set stream and the highest operation index observed on it, or -1\n * if it was observed empty.\n */\nexport type AppendConditionStream = {\n documentId: string;\n scope: string;\n branch: string;\n revision: number;\n};\n\n/**\n * A read-set enforced by {@link IOperationStore.apply}: the append fails if\n * any stream has operations past its recorded revision.\n */\nexport type AppendCondition = {\n streams: AppendConditionStream[];\n};\n\n/** Error history keeps messages, not classes, so failures match by prefix. */\nexport const APPEND_CONDITION_FAILED_PREFIX = \"Append condition failed: \";\n\n/**\n * A read-set stream grew before the append committed. A concurrency\n * conflict, not a fault: the caller retries against the new stream heads.\n */\nexport class AppendConditionFailedError extends Error {\n constructor(readonly condition: AppendCondition) {\n const streams = condition.streams\n .map((s) => `${s.documentId}:${s.scope}:${s.branch}@${s.revision}`)\n .join(\", \");\n super(\n `${APPEND_CONDITION_FAILED_PREFIX}a read-set stream advanced [${streams}]`,\n );\n this.name = \"AppendConditionFailedError\";\n }\n\n static isError(error: unknown): error is AppendConditionFailedError {\n return Error.isError(error) && error.name === \"AppendConditionFailedError\";\n }\n\n /** True when a recorded error message is an append-condition failure. */\n static isFailureMessage(message: string): boolean {\n return message.startsWith(APPEND_CONDITION_FAILED_PREFIX);\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 /** The largest operation timestamp in the document, across every scope. */\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 * With an {@link AppendCondition}, the append additionally fails with\n * {@link AppendConditionFailedError} — writing nothing — if any read-set\n * stream has operations past its recorded revision. The written and\n * read-set streams are advisory-locked in sorted key order, so concurrent\n * conditional appends on overlapping streams serialize.\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 * @param condition - Optional read-set to enforce at write time\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 condition?: AppendCondition,\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 * The largest operation timestamp in one stream, or undefined when it is empty.\n * Distinct from {@link DocumentRevisions.latestTimestamp}, which maxes over\n * every scope.\n *\n * Must be a real maximum, not the last-indexed operation's timestamp: a\n * re-evaluation pass re-appends at a fresh index while keeping the original\n * timestamp, so a later timestamp can sit behind the last row.\n */\n getStreamLatestTimestamp(\n documentId: string,\n scope: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<string | undefined>;\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 /** Why it failed, in the closed set sync classifies failures into. */\n errorType: SyncOperationErrorType;\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 { 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 {\n Action,\n CreateDocumentAction,\n CreateDocumentActionInput,\n Operation,\n OperationWithContext,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n applyDeleteDocumentAction,\n applyUpgradeDocumentAction,\n createPresignedHeader,\n defaultBaseState,\n deriveOperationId,\n DOCUMENT_DELETED_REASON,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Job } from \"../queue/types.js\";\nimport {\n AuthorizationDeniedError,\n DocumentDeletedError,\n} from \"../shared/errors.js\";\nimport type {\n ConsistencyCoordinate,\n ConsistencyToken,\n} from \"../shared/types.js\";\nimport type { JobResult } from \"./types.js\";\n\nexport { applyDeleteDocumentAction, applyUpgradeDocumentAction };\n\n/** Actions the reactor reduces itself, onto the document scope. */\nexport const DOCUMENT_SCOPE_ACTIONS: ReadonlySet<string> = new Set([\n \"CREATE_DOCUMENT\",\n \"DELETE_DOCUMENT\",\n \"UPGRADE_DOCUMENT\",\n \"ADD_RELATIONSHIP\",\n \"REMOVE_RELATIONSHIP\",\n \"UPDATE_RELATIONSHIP\",\n]);\n\n/**\n * `CREATE_DOCUMENT` is exempt by necessity: it runs before the document exists,\n * so building a decision model would throw and defer the job forever.\n */\nexport const GATED_DOCUMENT_ACTIONS: ReadonlySet<string> = new Set(\n [...DOCUMENT_SCOPE_ACTIONS].filter((type) => type !== \"CREATE_DOCUMENT\"),\n);\n\n/**\n * The document a document-scope action writes to, which is not always the job's\n * own document: delete and upgrade name it in `input.documentId`, and the\n * relationship actions in `input.sourceId`. `execute` only checks that a batch\n * shares one scope, so a caller can submit an action whose target is a document\n * other than the one the job is keyed by. The policy gate has to follow the\n * action rather than the job, or it decides against a policy the caller may\n * control instead of the one guarding the write.\n */\nexport function targetDocumentId(action: Action, fallback: string): string {\n const input = action.input as\n | { documentId?: unknown; sourceId?: unknown }\n | undefined;\n\n if (\n action.type === \"ADD_RELATIONSHIP\" ||\n action.type === \"REMOVE_RELATIONSHIP\" ||\n action.type === \"UPDATE_RELATIONSHIP\"\n ) {\n return typeof input?.sourceId === \"string\" && input.sourceId.length > 0\n ? input.sourceId\n : fallback;\n }\n\n return typeof input?.documentId === \"string\" && input.documentId.length > 0\n ? input.documentId\n : fallback;\n}\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 * 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\n/**\n * The error a refusal surfaces as. Both classes are already terminal in the job\n * result handler, so a refusal never burns a retry.\n */\nexport function refusalError(\n reason: string,\n documentId: string,\n deletedAtUtcIso: string | null,\n action: Action,\n): Error {\n if (reason === DOCUMENT_DELETED_REASON) {\n return new DocumentDeletedError(documentId, deletedAtUtcIso);\n }\n return new AuthorizationDeniedError(\n documentId,\n action.scope,\n action.type,\n action.context?.signer?.user.address,\n );\n}\n\n/**\n * Whether this operation is part of the document's creation. The create and the\n * upgrade from version zero hold the first two indexes for the life of the\n * document, so a reshuffle has to leave them where they are.\n */\nexport function isGenesisOperation(operation: Operation): boolean {\n if (operation.action.type === \"CREATE_DOCUMENT\") {\n return true;\n }\n if (operation.action.type !== \"UPGRADE_DOCUMENT\") {\n return false;\n }\n return (operation.action.input as { fromVersion?: number }).fromVersion === 0;\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\nexport const DEFAULT_PAGE_LIMIT = 500;\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\ntype GroupReferenceRecord = {\n documentId: string;\n groupIds: string[];\n\n // the index of the referencing auth operation in the 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 groupReferences: GroupReferenceRecord[] = [];\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 recordGroupReferences(documentId: string, groupIds: string[]): void {\n const lastOpIndex = this.operations.length - 1;\n if (lastOpIndex < 0) {\n throw new Error(\n \"recordGroupReferences must be called after write() - no operations in transaction\",\n );\n }\n if (groupIds.length === 0) {\n return;\n }\n this.groupReferences.push({\n documentId,\n groupIds,\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 getGroupReferenceRecords(): GroupReferenceRecord[] {\n return this.groupReferences;\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 /**\n * A policy-driven join: keeps the earliest join so a rediscovered reference\n * never shrinks a backfill window remotes already rely on, and reopens a\n * closed membership because a policy reference is not a removable one.\n */\n private async joinKeepingEarliest(\n trx: Transaction<Database>,\n documentId: string,\n collectionId: string,\n ordinal: bigint,\n ): Promise<void> {\n await trx\n .insertInto(\"document_collections\")\n .values({\n documentId,\n collectionId,\n joinedOrdinal: ordinal,\n leftOrdinal: null,\n })\n .onConflict((oc) =>\n oc.columns([\"documentId\", \"collectionId\"]).doUpdateSet({\n joinedOrdinal: sql`LEAST(\"document_collections\".\"joinedOrdinal\", EXCLUDED.\"joinedOrdinal\")`,\n leftOrdinal: null,\n }),\n )\n .execute();\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 groupReferences = kyselyTxn.getGroupReferenceRecords();\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 deniedReason: op.deniedReason ?? null,\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 // A joining document brings the groups it has ever referenced, so a\n // remote backfilling it can also fold the group streams its policy reads.\n const references = await trx\n .selectFrom(\"group_references\")\n .select(\"groupId\")\n .where(\"documentId\", \"=\", m.documentId)\n .execute();\n for (const { groupId } of references) {\n await this.joinKeepingEarliest(\n trx,\n groupId,\n m.collectionId,\n BigInt(ordinal),\n );\n }\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 if (groupReferences.length > 0) {\n for (const record of groupReferences) {\n const ordinal = operationOrdinals[record.operationIndex];\n\n // Rediscovering a known reference changes nothing.\n await trx\n .insertInto(\"group_references\")\n .values(\n record.groupIds.map((groupId) => ({\n documentId: record.documentId,\n groupId,\n })),\n )\n .onConflict((oc) => oc.doNothing())\n .execute();\n\n // Each named group joins every collection the referencing document\n // belongs to. The join does not filter on leftOrdinal: a document\n // that left a collection still has served history inside its window,\n // and remotes holding that history still need the group.\n const rows = await trx\n .selectFrom(\"document_collections\")\n .select(\"collectionId\")\n .where(\"documentId\", \"=\", record.documentId)\n .execute();\n for (const groupId of record.groupIds) {\n for (const { collectionId } of rows) {\n await this.joinKeepingEarliest(\n trx,\n groupId,\n collectionId,\n BigInt(ordinal),\n );\n }\n }\n }\n }\n\n return operationOrdinals;\n }\n\n async getGroupReferencers(\n groupId: string,\n signal?: AbortSignal,\n ): Promise<string[]> {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n const rows = await this.queryExecutor\n .selectFrom(\"group_references\")\n .select(\"documentId\")\n .where(\"groupId\", \"=\", groupId)\n .orderBy(\"documentId\")\n .execute();\n\n return rows.map((row) => row.documentId);\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 limit = paging?.limit ?? DEFAULT_PAGE_LIMIT;\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 const unionQuery = buildBranch(\"joiner\")\n .unionAll(buildBranch(\"newOps\"))\n .orderBy(\"ordinal\", \"asc\")\n .limit(limit + 1);\n\n const rows = await unionQuery.execute();\n\n let hasMore = false;\n let items = rows;\n\n if (rows.length > limit) {\n hasMore = true;\n items = rows.slice(0, 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 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 const limit = paging?.limit ?? DEFAULT_PAGE_LIMIT;\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 query = query.limit(limit + 1);\n\n const rows = await query.execute();\n\n let hasMore = false;\n let items = rows;\n\n if (rows.length > limit) {\n hasMore = true;\n items = rows.slice(0, 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 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 const limit = paging?.limit ?? DEFAULT_PAGE_LIMIT;\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 query = query.limit(limit + 1);\n\n const rows = await query.execute();\n\n let hasMore = false;\n let items = rows;\n\n if (rows.length > limit) {\n hasMore = true;\n items = rows.slice(0, 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 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 deniedReason: row.deniedReason ?? undefined,\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 deniedReason: row.deniedReason ?? undefined,\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 { PHDocument } from \"@powerhousedao/shared/document-model\";\n\n/**\n * Configuration options for the write cache\n */\nexport type WriteCacheConfig = {\n /** Maximum number of document streams to cache (LRU eviction). Default: 1000 */\n maxDocuments: number;\n\n /** Number of snapshots to keep in each document's ring buffer. Default: 10 */\n ringBufferSize: number;\n\n /** Persist a keyframe snapshot every N revisions. Default: 10 */\n keyframeInterval: number;\n};\n\n/**\n * Unique identifier for a document stream\n */\nexport type DocumentStreamKey = {\n /** Document identifier */\n documentId: string;\n\n /** Operation scope */\n scope: string;\n\n /** Branch name */\n branch: string;\n};\n\n/**\n * Where a snapshot sits in its stream.\n *\n * - `Head`: the newest revision of the stream when it was stored. Only these\n * can answer a read that asks for the head.\n * - `Historical`: state at an earlier revision. Usable as a starting point to\n * replay forward from, and as an answer to a read for that same revision.\n */\nexport enum SnapshotPosition {\n Head = \"head\",\n Historical = \"historical\",\n}\n\n/**\n * A cached document snapshot at a specific revision\n */\nexport type CachedSnapshot = {\n /** The revision number of this snapshot */\n revision: number;\n\n /** The document state at this revision */\n document: PHDocument;\n\n /** Where this snapshot sat in the stream when it was stored */\n position: SnapshotPosition;\n};\n\n/**\n * Serialized keyframe snapshot for K/V store persistence\n */\nexport type KeyframeSnapshot = {\n /** The revision number of this keyframe */\n revision: number;\n\n /** Serialized document state */\n document: string;\n};\n","import type {\n CreateDocumentAction,\n DeleteDocumentAction,\n Operation,\n PHDocument,\n UpgradeDocumentAction,\n UpgradeTransition,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n appendWithoutApplying,\n applyDeleteDocumentAction,\n applyUpgradeDocumentAction,\n baseReducerVersion,\n isDenied,\n normalizeDocumentModelVersion,\n} from \"@powerhousedao/shared/document-model\";\nimport { createDocumentFromAction } from \"../executor/util.js\";\nimport type { IDocumentModelRegistry } from \"../registry/interfaces.js\";\nimport { DocumentNotFoundError } from \"../shared/errors.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 { SnapshotPosition } from \"./write-cache-types.js\";\nimport type { IWriteCache } from \"./write/interfaces.js\";\n\ntype DocumentStream = {\n key: string;\n ringBuffer: RingBuffer<CachedSnapshot>;\n};\n\n/**\n * An UPGRADE_DOCUMENT spine event validated as version-changing\n * (fromVersion > 0 and fromVersion < toVersion), as opposed to the\n * creation-time 0->N seed upgrade. Used to segment scope replay.\n */\ntype ValidatedUpgrade = {\n fromVersion: number;\n toVersion: number;\n revision: Record<string, number> | undefined;\n timestampUtcMs: string;\n};\n\n/**\n * A validated upgrade held back by the document scope pass so its transitions\n * run against the state the requested scope has reached at the upgrade's\n * boundary, rather than the state the pass starts from.\n */\ntype PendingUpgrade = {\n action: UpgradeDocumentAction;\n upgradePath: UpgradeTransition[] | undefined;\n /** The upgrade operation's index in the document scope. */\n index: number;\n /**\n * DELETE_DOCUMENT actions the document scope recorded after this upgrade.\n * The document-scope pass applies deletes inline while the upgrade is held\n * back, inverting log order; re-applying them after the upgrade restores it\n * — without this, an upgrade seeded from an initialState snapshot replaces\n * the state wholesale and a rebuilt deleted document comes back live.\n */\n subsequentDeletes: DeleteDocumentAction[];\n};\n\n/**\n * The last operation index a keyframe's document reflects for the scope. A\n * keyframe only exists for a scope that has operations, so a missing entry\n * means the stored row is corrupt.\n */\nfunction keyframeRevision(\n keyframe: { revision: number; document: PHDocument },\n documentId: string,\n scope: string,\n): number {\n const nextIndex = keyframe.document.header.revision[scope];\n\n if (typeof nextIndex !== \"number\") {\n throw new Error(\n `Corrupt keyframe for document ${documentId} at revision ${keyframe.revision}: header carries no ${scope} revision`,\n );\n }\n\n return nextIndex - 1;\n}\n\nfunction extractModuleVersion(doc: PHDocument): number {\n const v = (doc.state as Record<string, Record<string, unknown>>).document\n .version as number | undefined;\n return normalizeDocumentModelVersion(v);\n}\n\n/** The highest revision held, latest push winning a tie. */\nfunction highestRevision(\n snapshots: CachedSnapshot[],\n): CachedSnapshot | undefined {\n let newest: CachedSnapshot | undefined = undefined;\n for (const snapshot of snapshots) {\n if (!newest || snapshot.revision >= newest.revision) {\n newest = snapshot;\n }\n }\n return newest;\n}\n\n/**\n * Copies a document far enough that the caller cannot write through it. Inside\n * this class, callers only ever replace whole fields on these four, so one\n * level each is enough.\n */\nfunction copyDocument(document: PHDocument): PHDocument {\n return {\n ...document,\n header: { ...document.header },\n state: { ...document.state },\n operations: { ...document.operations },\n };\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 * Note: this returns a _shallow_ copy of the document.\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 const newest = highestRevision(snapshots);\n\n // Only the topmost snapshot can be the head, and only if it was stored\n // as one: anything above it proves the stream has grown since.\n if (newest?.position === SnapshotPosition.Head) {\n this.lruTracker.touch(streamKey);\n return copyDocument(newest.document);\n }\n\n if (newest) {\n const document = await this.warmMissRebuild(\n newest.document,\n newest.revision,\n documentId,\n scope,\n branch,\n undefined,\n signal,\n );\n\n this.store(\n documentId,\n scope,\n branch,\n (document.header.revision[scope] ?? 0) - 1,\n document,\n SnapshotPosition.Head,\n );\n this.lruTracker.touch(streamKey);\n\n return document;\n }\n } else {\n const exactMatch = snapshots.findLast(\n (s) => s.revision === targetRevision,\n );\n if (exactMatch) {\n this.lruTracker.touch(streamKey);\n return copyDocument(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.store(\n documentId,\n scope,\n branch,\n targetRevision,\n document,\n SnapshotPosition.Historical,\n );\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 // header.revision is a next index; a snapshot is labelled by last index.\n const revision =\n targetRevision ?? (document.header.revision[scope] ?? 0) - 1;\n\n this.store(\n documentId,\n scope,\n branch,\n revision,\n document,\n targetRevision === undefined\n ? SnapshotPosition.Head\n : SnapshotPosition.Historical,\n );\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 position: SnapshotPosition,\n ): void {\n this.store(documentId, scope, branch, revision, document, position);\n }\n\n private store(\n documentId: string,\n scope: string,\n branch: string,\n revision: number,\n document: PHDocument,\n position: SnapshotPosition,\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 // Copied so a caller still holding the document cannot change what we\n // stored.\n const slicedDocument: PHDocument = {\n ...copyDocument(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 position,\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 const keyframe = await this.keyframeStore.findNearestKeyframe(\n documentId,\n scope,\n branch,\n targetRevision,\n signal,\n );\n\n if (!keyframe) {\n return undefined;\n }\n\n // Where a replay resumes comes from the stored document, not the row's\n // label: rows written before the label convention settled are off by one.\n // Clamped: a legacy positional row advertises the store head, far above\n // the position it holds. The label is the bound both error modes respect.\n return {\n revision: Math.min(\n keyframeRevision(keyframe, documentId, scope),\n keyframe.revision,\n ),\n document: keyframe.document,\n };\n }\n\n /**\n * Rebuilds a scope from a keyframe or from the whole operation history.\n *\n * The document scope is always rebuilt first, because it carries the type,\n * the upgrades and the deletion marker. Its version-changing upgrades are not\n * applied there though: an upgrade reducer must see the state the requested\n * scope has reached at that upgrade's boundary, so each one is held back and\n * applied when the replay below crosses the boundary that\n * resolveModuleVersionForOp derives from it. Upgrades whose boundary lies past\n * the last replayed operation are applied at the end. Creation-time 0->N seed\n * upgrades carry the initial state, so they still apply immediately.\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 // all scope rebuilds need the document scope for type, upgrades and deletion,\n // but we need to special case for document scope rebuilds\n const documentScopeBound =\n scope === \"document\" ? targetRevision : undefined;\n\n let document: PHDocument | undefined;\n let startRevision: number;\n let documentType: string;\n\n const validatedUpgrades: ValidatedUpgrade[] = [];\n const pendingUpgrades: PendingUpgrade[] = [];\n\n let lastDocumentScopeOperation: Operation | undefined;\n\n if (keyframe) {\n document = keyframe.document;\n startRevision = keyframe.revision;\n documentType = keyframe.document.header.documentType;\n\n // The keyframe's label indexes the scope it was written for, a different\n // stream unless that scope is the document one.\n const documentScopeResume =\n scope === \"document\"\n ? keyframe.revision\n : keyframeRevision(keyframe, documentId, \"document\");\n\n const docScopeOpsAfterKeyframe = await this.operationStore.getSince(\n documentId,\n \"document\",\n branch,\n documentScopeResume,\n undefined,\n undefined,\n signal,\n );\n\n for (const operation of docScopeOpsAfterKeyframe.results) {\n if (\n documentScopeBound !== undefined &&\n operation.index > documentScopeBound\n ) {\n break;\n }\n\n lastDocumentScopeOperation = operation;\n\n if (operation.error || isDenied(operation)) {\n continue;\n }\n\n if (operation.action.type === \"UPGRADE_DOCUMENT\") {\n const upgradeAction = operation.action as UpgradeDocumentAction;\n const fromVersion = upgradeAction.input.fromVersion;\n const toVersion = upgradeAction.input.toVersion;\n\n if (fromVersion > 0 && fromVersion < toVersion) {\n let upgradePath: UpgradeTransition[] | undefined;\n try {\n upgradePath = this.registry.computeUpgradePath(\n documentType,\n fromVersion,\n toVersion,\n );\n } catch (err) {\n const upgradeInput = upgradeAction.input as {\n initialState?: unknown;\n };\n if (upgradeInput.initialState !== undefined) {\n upgradePath = undefined;\n } else {\n throw new Error(\n `Failed to rebuild document ${documentId}: no upgrade manifest for ${documentType} v${fromVersion}→v${toVersion} and no initialState snapshot. ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n }\n validatedUpgrades.push({\n fromVersion,\n toVersion,\n revision: upgradeAction.input.revision,\n timestampUtcMs: operation.timestampUtcMs,\n });\n pendingUpgrades.push({\n action: upgradeAction,\n upgradePath,\n index: operation.index,\n subsequentDeletes: [],\n });\n }\n } else if (operation.action.type === \"DELETE_DOCUMENT\") {\n applyDeleteDocumentAction(document, operation.action as never);\n for (const pending of pendingUpgrades) {\n pending.subsequentDeletes.push(\n operation.action as DeleteDocumentAction,\n );\n }\n }\n }\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 // Typed, so the executor defers the job until the document arrives.\n if (createOpResult.results.length === 0) {\n throw new DocumentNotFoundError(documentId);\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 lastDocumentScopeOperation = createOp;\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 (\n // in the case that the document scope was requested, we can exit early\n documentScopeBound !== undefined &&\n operation.index > documentScopeBound\n ) {\n break;\n }\n\n lastDocumentScopeOperation = operation;\n\n if (operation.index === 0) {\n continue;\n }\n\n if (operation.error || isDenied(operation)) {\n continue;\n }\n\n if (operation.action.type === \"UPGRADE_DOCUMENT\") {\n const upgradeAction = operation.action as UpgradeDocumentAction;\n const fromVersion = upgradeAction.input.fromVersion;\n const toVersion = upgradeAction.input.toVersion;\n\n if (fromVersion > 0 && fromVersion < toVersion) {\n let upgradePath: UpgradeTransition[] | undefined;\n try {\n upgradePath = this.registry.computeUpgradePath(\n documentType,\n fromVersion,\n toVersion,\n );\n } catch (err) {\n const upgradeInput = upgradeAction.input as {\n initialState?: unknown;\n };\n if (upgradeInput.initialState !== undefined) {\n upgradePath = undefined;\n } else {\n throw new Error(\n `Failed to rebuild document ${documentId}: no upgrade manifest for ${documentType} v${fromVersion}→v${toVersion} and no initialState snapshot. ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n }\n validatedUpgrades.push({\n fromVersion,\n toVersion,\n revision: upgradeAction.input.revision,\n timestampUtcMs: operation.timestampUtcMs,\n });\n pendingUpgrades.push({\n action: upgradeAction,\n upgradePath,\n index: operation.index,\n subsequentDeletes: [],\n });\n } else {\n document = applyUpgradeDocumentAction(\n document,\n upgradeAction,\n undefined,\n );\n }\n\n docModule = this.registry.getModule(\n documentType,\n normalizeDocumentModelVersion(toVersion),\n );\n } else if (operation.action.type === \"DELETE_DOCUMENT\") {\n applyDeleteDocumentAction(document, operation.action as never);\n for (const pending of pendingUpgrades) {\n pending.subsequentDeletes.push(\n operation.action as DeleteDocumentAction,\n );\n }\n } else {\n const protocolVersion = baseReducerVersion(document.header);\n document = docModule.reducer(document, operation.action, undefined, {\n skip: operation.skip,\n protocolVersion,\n });\n }\n }\n }\n\n // we rebuild the document scope all the time, so if that is the scope\n // requested, we're already done\n if (scope === \"document\") {\n document = this.applyPendingUpgrades(\n document,\n pendingUpgrades,\n Number.MAX_SAFE_INTEGER,\n );\n\n const last =\n lastDocumentScopeOperation ??\n (await this.operationAt(\n documentId,\n \"document\",\n branch,\n startRevision,\n signal,\n ));\n\n document.operations = {\n ...document.operations,\n document: last ? [last] : [],\n };\n\n return this.stampRevisions(\n document,\n documentId,\n scope,\n branch,\n targetRevision,\n signal,\n );\n }\n\n // keyframes carry no operations, so we need to fill the operations list\n if (keyframe) {\n const resumeOperation = await this.operationAt(\n documentId,\n scope,\n branch,\n startRevision,\n signal,\n );\n\n if (resumeOperation) {\n document.operations = {\n ...document.operations,\n [scope]: [resumeOperation],\n };\n }\n }\n\n const moduleCache = new Map<\n number,\n ReturnType<typeof this.registry.getModule>\n >();\n\n const getModuleCached = (version: number | undefined) => {\n const key = version ?? 0;\n let mod = moduleCache.get(key);\n if (!mod) {\n mod = this.registry.getModule(documentType, version);\n moduleCache.set(key, mod);\n }\n return mod;\n };\n\n const finalVersion =\n validatedUpgrades.at(-1)?.toVersion ?? 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 const moduleVersion = this.resolveModuleVersionForOp(\n operation.index,\n operation.timestampUtcMs,\n scope,\n validatedUpgrades,\n finalVersion,\n );\n\n document = this.applyPendingUpgrades(\n document,\n pendingUpgrades,\n moduleVersion ?? Number.MAX_SAFE_INTEGER,\n );\n\n // A denied operation still carries a potentially valid action, so\n // we must specifically skip without applying.\n if (isDenied(operation)) {\n document = appendWithoutApplying(document, operation, scope);\n } else {\n // Fail-fast: if reducer throws, error propagates immediately without caching partial state\n const protocolVersion = baseReducerVersion(document.header);\n document = getModuleCached(moduleVersion).reducer(\n document,\n operation.action,\n undefined,\n {\n skip: operation.skip,\n protocolVersion,\n },\n );\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 document = this.applyTailPendingUpgrades(\n document,\n pendingUpgrades,\n scope,\n targetRevision,\n );\n\n document = await this.stampRevisions(\n document,\n documentId,\n scope,\n branch,\n targetRevision,\n signal,\n );\n\n // A held-back upgrade means this positional state predates it, but the\n // stamped document-scope revision advertises the store head. A snapshot\n // stored from here can become a keyframe, and a rebuild resuming from it\n // trusts that revision to decide where to re-read the document scope —\n // so it must not point past the first upgrade this state never saw.\n if (pendingUpgrades.length > 0) {\n const firstHeldBack = pendingUpgrades[0];\n const stamped = document.header.revision[\"document\"] ?? 0;\n document.header.revision = {\n ...document.header.revision,\n document: Math.min(stamped, firstHeldBack.index),\n };\n }\n\n return document;\n }\n\n /**\n * Applies and removes every held-back upgrade whose target version is at or\n * below `throughVersion`, in the order the document scope recorded them.\n */\n private applyPendingUpgrades(\n document: PHDocument,\n pendingUpgrades: PendingUpgrade[],\n throughVersion: number,\n ): PHDocument {\n while (pendingUpgrades.length > 0) {\n const pending = pendingUpgrades[0];\n\n if (throughVersion < pending.action.input.toVersion) {\n break;\n }\n\n pendingUpgrades.shift();\n document = this.applyPendingUpgrade(document, pending);\n }\n\n return document;\n }\n\n /**\n * Applies the remaining held-back upgrades after the requested scope's\n * replay has finished. A head read applies them all. A positional read\n * applies only those whose boundary for this scope lies at or before the\n * target position: applying a later one would label migrated state with a\n * pre-upgrade revision, and a keyframe stored from that poisons every\n * rebuild that resumes from it. Boundaries come from the upgrade's revision\n * snapshot; an upgrade without one records no position for this scope, and\n * the replay loop not having crossed it already places it past the target.\n */\n private applyTailPendingUpgrades(\n document: PHDocument,\n pendingUpgrades: PendingUpgrade[],\n scope: string,\n targetRevision: number | undefined,\n ): PHDocument {\n while (pendingUpgrades.length > 0) {\n const pending = pendingUpgrades[0];\n\n if (targetRevision !== undefined) {\n const snapshot = pending.action.input.revision;\n if (snapshot === undefined) {\n break;\n }\n const boundary = snapshot[scope] ?? 0;\n if (boundary > targetRevision) {\n break;\n }\n }\n\n pendingUpgrades.shift();\n document = this.applyPendingUpgrade(document, pending);\n }\n\n return document;\n }\n\n /**\n * Applies one held-back upgrade, then re-applies the deletes the document\n * scope recorded after it so the hold-back cannot invert their order.\n */\n private applyPendingUpgrade(\n document: PHDocument,\n pending: PendingUpgrade,\n ): PHDocument {\n document = applyUpgradeDocumentAction(\n document,\n pending.action,\n pending.upgradePath,\n );\n\n for (const deleteAction of pending.subsequentDeletes) {\n document = applyDeleteDocumentAction(document, deleteAction);\n }\n\n return document;\n }\n\n /**\n * Copies the current document revisions onto the document. Overwrites the\n * requested scope revision with the target revision, if provided.\n */\n private async stampRevisions(\n document: PHDocument,\n documentId: string,\n scope: string,\n branch: string,\n targetRevision: number | undefined,\n signal?: AbortSignal,\n ): Promise<PHDocument> {\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\n if (targetRevision !== undefined) {\n document.header.revision = {\n ...document.header.revision,\n [scope]: targetRevision + 1,\n };\n }\n document.header.lastModifiedAtUtcIso = revisions.latestTimestamp;\n\n return document;\n }\n\n /** The stored operation at `index`, or undefined if it is no longer there. */\n private async operationAt(\n documentId: string,\n scope: string,\n branch: string,\n index: number,\n signal?: AbortSignal,\n ): Promise<Operation | undefined> {\n if (index < 0) {\n return undefined;\n }\n\n const result = await this.operationStore.getSince(\n documentId,\n scope,\n branch,\n index - 1,\n undefined,\n { cursor: \"0\", limit: 1 },\n signal,\n );\n\n const operation = result.results[0];\n return operation && operation.index === index ? operation : undefined;\n }\n\n /**\n * Resolves which module version to use for a given operation in phase 2.\n *\n * Uses the validated-upgrade boundary rules from D7:\n * - If `input.revision` is present: op.index < revision[scope] → before the upgrade boundary\n * - Otherwise: timestamp fallback\n * - Falls back to final module version when neither is decidable\n */\n private resolveModuleVersionForOp(\n opIndex: number,\n opTimestamp: string,\n scope: string,\n validatedUpgrades: ValidatedUpgrade[],\n finalVersion: number | undefined,\n ): number | undefined {\n if (validatedUpgrades.length === 0) {\n return finalVersion;\n }\n\n let currentVersion: number | undefined = validatedUpgrades[0]?.fromVersion;\n\n for (const upgrade of validatedUpgrades) {\n let beforeUpgrade: boolean;\n\n if (upgrade.revision !== undefined) {\n const boundary = upgrade.revision[scope] ?? 0;\n beforeUpgrade = opIndex < boundary;\n } else {\n beforeUpgrade = opTimestamp < upgrade.timestampUtcMs;\n }\n\n if (beforeUpgrade) {\n return currentVersion;\n }\n\n currentVersion = upgrade.toVersion;\n }\n\n return currentVersion;\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 docScopeNextIndex = baseDocument.header.revision[\"document\"] ?? 0;\n\n const docScopeNewOps = await this.operationStore.getSince(\n documentId,\n \"document\",\n branch,\n docScopeNextIndex - 1,\n undefined,\n undefined,\n signal,\n );\n\n // Only a cold rebuild applies document-scope operations properly; the model\n // reducer below ignores them, so a delete or an upgrade since the base\n // would go missing.\n if (docScopeNewOps.results.length > 0) {\n return this.coldMissRebuild(\n documentId,\n scope,\n branch,\n targetRevision,\n signal,\n );\n }\n\n const module = this.registry.getModule(\n documentType,\n extractModuleVersion(baseDocument),\n );\n // The base is a cached snapshot and the revisions below are written in\n // place, so copy it first or a rebuild that applies nothing rewrites it.\n let document = copyDocument(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 // A denied operation still carries a potentially valid action, so\n // we must specifically skip without applying.\n if (isDenied(operation)) {\n document = appendWithoutApplying(document, operation, scope);\n } else {\n // Fail-fast: if reducer throws, error propagates immediately without caching partial state\n const protocolVersion = baseReducerVersion(document.header);\n document = module.reducer(document, operation.action, undefined, {\n skip: operation.skip,\n protocolVersion,\n });\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\n // Positional rebuild: this scope's revision is the target, not the head.\n if (targetRevision !== undefined) {\n document.header.revision = {\n ...document.header.revision,\n [scope]: targetRevision + 1,\n };\n }\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 { ReactorFeatureFlags } from \"../executor/types.js\";\n\n/** A flag name mapped to the flags it requires. */\nexport type FeatureFlagPrerequisites = Record<string, readonly string[]>;\n\n/**\n * Every flag this reactor knows, with the flags it requires. A stage adds its\n * flag here when it ships, so asking an older reactor for a later stage's flag\n * is an unrecognized name rather than a flag that quietly does nothing.\n */\nexport const FLAG_PREREQUISITES: Record<\n keyof ReactorFeatureFlags,\n readonly (keyof ReactorFeatureFlags)[]\n> = {\n documentDecisions: [],\n authEnforcement: [\"documentDecisions\"],\n authGroups: [\"authEnforcement\"],\n authConditions: [\"authGroups\"],\n};\n\n/**\n * The flags as plain booleans, with anything unset off, validated. Callers hold\n * a partial set, because that is what crosses to a pooled worker, and every\n * consumer needs the same resolution of it.\n */\nexport function resolveFeatureFlags(\n flags: Partial<ReactorFeatureFlags> = {},\n): ReactorFeatureFlags {\n const resolved: ReactorFeatureFlags = {\n documentDecisions: flags.documentDecisions ?? false,\n authEnforcement: flags.authEnforcement ?? false,\n authGroups: flags.authGroups ?? false,\n authConditions: flags.authConditions ?? false,\n };\n\n // Against what the caller passed, so an unrecognized name is still reported.\n validateFeatureFlags(flags, FLAG_PREREQUISITES);\n return resolved;\n}\n\n/**\n * Throws when the flags ask for enforcement the reactor cannot deliver. Either\n * failure would otherwise read as enforcement being on while the reactor\n * applies less than the caller asked for.\n */\nexport function validateFeatureFlags(\n flags: Record<string, boolean | undefined>,\n prerequisites: FeatureFlagPrerequisites,\n): void {\n const known = Object.keys(prerequisites);\n\n const unrecognized = Object.keys(flags).filter(\n (name) => !known.includes(name),\n );\n if (unrecognized.length > 0) {\n throw new Error(\n `Unrecognized reactor feature flag: ${unrecognized.join(\", \")}. ` +\n `This reactor knows: ${known.join(\", \")}.`,\n );\n }\n\n for (const name of known) {\n if (flags[name] !== true) {\n continue;\n }\n const missing = prerequisites[name].filter(\n (required) => flags[required] !== true,\n );\n if (missing.length > 0) {\n throw new Error(\n `Reactor feature flag ${name} requires ${missing.join(\", \")}.`,\n );\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 { Operation } from \"@powerhousedao/shared/document-model\";\nimport type { StreamQuery } from \"./types.js\";\n\n/** Identifies a stream within a walk. */\nexport function streamKey(query: StreamQuery): string {\n return `${query.documentId}:${query.scope}:${query.branch}`;\n}\n\n/** An operation together with the stream it belongs to. */\nexport type PositionedOperation = {\n streamKey: string;\n scope: string;\n operation: Operation;\n};\n\n/** One stream's operations, with its skips already resolved. */\nexport type StreamOperations = {\n streamKey: string;\n scope: string;\n operations: Operation[];\n};\n\n/**\n * Orders two operations from different streams by position. Timestamp decides;\n * an equal timestamp puts an auth operation first, and otherwise falls to the\n * action id and then the operation id, so that two replicas holding the same\n * operations agree on the order whatever order they happen to store them in.\n */\nexport function comparePositions(\n a: PositionedOperation,\n b: PositionedOperation,\n): number {\n const aTime = Date.parse(a.operation.timestampUtcMs);\n const bTime = Date.parse(b.operation.timestampUtcMs);\n\n if (aTime !== bTime) {\n return aTime - bTime;\n }\n\n // Within one stream the stored order decides, so a tie keeps it. The rules\n // below only break ties between separate streams.\n if (a.streamKey === b.streamKey) {\n return a.operation.index - b.operation.index;\n }\n\n // An auth operation wins a tie, so a grant applying at the same millisecond is\n // not decided by the results of a hash function, for instance.\n const aAuth = a.scope === \"auth\";\n const bAuth = b.scope === \"auth\";\n if (aAuth !== bAuth) {\n return aAuth ? -1 : 1;\n }\n\n const actionIds = (a.operation.action.id ?? \"\").localeCompare(\n b.operation.action.id ?? \"\",\n );\n if (actionIds !== 0) {\n return actionIds;\n }\n\n return (a.operation.id ?? \"\").localeCompare(b.operation.id ?? \"\");\n}\n\n/**\n * Merges the read-set streams into one sequence by position. An operation's\n * place in the result is the bound a decision at that operation reads to: every\n * operation before it has been applied, and it has not.\n */\nexport function mergeByPosition(\n streams: StreamOperations[],\n): PositionedOperation[] {\n const merged: PositionedOperation[] = [];\n\n for (const stream of streams) {\n for (const operation of stream.operations) {\n merged.push({\n streamKey: stream.streamKey,\n scope: stream.scope,\n operation,\n });\n }\n }\n\n return merged.sort(comparePositions);\n}\n\n/**\n * The skip that retracts everything from `firstRetractedIndex` up to where the\n * re-appended operation lands. It spans the indexes rather than counting the\n * operations, because a stream with a gap in it makes those differ.\n */\nexport function retractionSkip(\n nextIndex: number,\n firstRetractedIndex: number,\n): number {\n return nextIndex - firstRetractedIndex;\n}\n","import type {\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n garbageCollect,\n isDenied,\n sortOperations,\n} from \"@powerhousedao/shared/document-model\";\nimport { comparePositions, mergeByPosition } from \"./merged-order.js\";\n\n/**\n * A single forward pass is only correct while a stream's effective operations\n * are ordered.\n */\nfunction assertPositionOrder(\n streamKey: string,\n scope: string,\n operations: Operation[],\n): void {\n for (let i = 1; i < operations.length; i++) {\n const previous = operations[i - 1];\n const current = operations[i];\n // The same scope on both sides, so only the intra-stream rules apply.\n if (\n comparePositions(\n { streamKey, scope, operation: previous },\n { streamKey, scope, operation: current },\n ) > 0\n ) {\n throw new Error(\n `Stream ${streamKey} is out of position order: index ${previous.index} at ${previous.timestampUtcMs} precedes index ${current.index} at ${current.timestampUtcMs}`,\n );\n }\n }\n}\n\n/** One read-set stream, with the state it holds before any of its operations. */\nexport type WalkStream = {\n streamKey: string;\n /** Decides a cross-stream timestamp tie, which an auth operation wins. */\n scope: string;\n document: PHDocument;\n apply: ApplyOperation;\n /** The stream's stored operations. Order and skips are resolved internally. */\n operations: Operation[];\n};\n\n/** Applies one operation to the stream it belongs to. */\nexport type ApplyOperation = (\n document: PHDocument,\n operation: Operation,\n) => PHDocument;\n\n/** An operation, and every stream as it stood immediately before it. */\nexport type WalkPosition = {\n streamKey: string;\n operation: Operation;\n states: Map<string, PHDocument>;\n};\n\n/**\n * Visits every operation in the read-set once, in the order their positions\n * fall, and hands back the state each stream held just before it. That state is\n * what a decision at that operation reads.\n *\n * Skips are resolved first (i.e. this is performed on a garbage collected\n * stream), which means we can do a single forward pass.\n *\n * An operation that contributes no state, whether denied or holding a reducer\n * error, is visited but not applied (this matches the write cache's rebuild).\n *\n * The consumer sends back whether it refused the operation it was handed: a\n * refusal this pass produced must suppress it the same way a stored one does.\n */\nexport function* walkByPosition(\n streams: WalkStream[],\n): Generator<WalkPosition, void, boolean> {\n const merged = mergeByPosition(\n streams.map((stream) => {\n const operations = garbageCollect(sortOperations([...stream.operations]));\n assertPositionOrder(stream.streamKey, stream.scope, operations);\n return {\n streamKey: stream.streamKey,\n scope: stream.scope,\n operations,\n };\n }),\n );\n\n const byKey = new Map(streams.map((stream) => [stream.streamKey, stream]));\n const states = new Map(\n streams.map((stream) => [stream.streamKey, stream.document]),\n );\n\n for (const { streamKey, operation } of merged) {\n const deniedNow = yield { streamKey, operation, states: new Map(states) };\n\n if (deniedNow || operation.error !== undefined || isDenied(operation)) {\n continue;\n }\n\n const stream = byKey.get(streamKey);\n const before = states.get(streamKey);\n if (before === undefined || stream === undefined) {\n throw new Error(`No state for stream ${streamKey}`);\n }\n\n states.set(streamKey, stream.apply(before, operation));\n }\n}\n","import type {\n AuthSubject,\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { DocumentNotFoundError } from \"../shared/errors.js\";\nimport { derivedReadSet, staticReadSet } from \"./build-decision-model.js\";\nimport { streamKey } from \"./merged-order.js\";\nimport type {\n DecisionModel,\n DecisionStores,\n DecisionTarget,\n EvaluationSubject,\n ReadStream,\n StreamHistory,\n StreamQuery,\n} from \"./types.js\";\nimport type { WalkStream } from \"./walk.js\";\nimport { walkByPosition } from \"./walk.js\";\n\n/** The stream key for evaluated operations whose scope no projection reads. */\nconst EVALUATED_ONLY = \"evaluated\";\n\n/** A derived stream that joined the walk, remembered by projection name. */\ntype DerivedEntry = {\n name: string;\n query: StreamQuery;\n};\n\n/**\n * Whether any stream the model reads declares this operation's action type as\n * one that can change an evaluation.\n */\nfunction isDecidingAction(\n operation: Operation,\n readSet: ReadStream[],\n): boolean {\n return readSet.some((stream) =>\n stream.decidingActions.includes(operation.action.type),\n );\n}\n\n/**\n * Who an operation acts as. A replayed operation is evaluated as its own signer,\n * so an address-scoped policy does not deny its own author's history.\n */\nfunction subjectOf(operation: Operation): AuthSubject {\n const signer = operation.action.context?.signer;\n return { address: signer?.user.address, key: signer?.app.key };\n}\n\n/**\n * The model as the walk reached this operation: each static projection's value\n * is its own scope's state, and each derived projection's value maps document\n * id to that document's state, holding only the streams this replica walked. A\n * derived stream it does not hold stays out of the map, which fails closed.\n */\nfunction modelAt<M>(\n readSet: ReadStream[],\n derivedNames: string[],\n derived: DerivedEntry[],\n states: Map<string, PHDocument>,\n): M {\n const model: Record<string, unknown> = {};\n\n for (const stream of readSet) {\n const document = states.get(streamKey(stream.query));\n if (document === undefined) {\n throw new Error(`No state walked for projection ${stream.name}`);\n }\n model[stream.name] = (document.state as Record<string, unknown>)[\n stream.query.scope\n ];\n }\n\n // Every derived projection is present even when nothing was walked for it,\n // so a decide never distinguishes \"no streams\" from \"not yet built\".\n for (const name of derivedNames) {\n model[name] = {};\n }\n\n for (const entry of derived) {\n const map = model[entry.name] as Record<string, unknown>;\n const document = states.get(streamKey(entry.query));\n if (document !== undefined) {\n map[entry.query.documentId] = (document.state as Record<string, unknown>)[\n entry.query.scope\n ];\n }\n }\n\n return model as M;\n}\n\n/**\n * Evaluates each operation at its own position and returns the refusals in an\n * array parallel to the operations, where undefined means allowed.\n *\n * A position is a timestamp, so an operation refused by a delete is one that\n * sorts after it, and the operations before it are left alone. That holds\n * whether the delete is already stored or is among the operations passed in.\n */\nexport async function evaluateByPosition<M>(\n model: (target: DecisionTarget) => DecisionModel<M>,\n target: DecisionTarget,\n subject: EvaluationSubject,\n stores: DecisionStores,\n signal?: AbortSignal,\n): Promise<Array<string | undefined>> {\n const { scope, operations } = subject;\n const { writeCache, operationStore } = stores;\n\n const definition = model(target);\n const readSet = staticReadSet(definition);\n const derivedSet = derivedReadSet(definition);\n\n if (!definition.evaluatesScope(scope)) {\n return operations.map(() => undefined);\n }\n\n // Re-evaluation passes in operations that are already stored, so the reads\n // below exclude them and no operation is refused by its own stored copy.\n const evaluating = new Set(operations.map((operation) => operation.id));\n\n // One indexed query per read stream, narrowed to the actions that can change\n // an evaluation. A document holding none of them returns just below.\n const readStreams = await Promise.all(\n readSet.map(async (stream) => ({\n stream,\n operations: (\n await operationStore.getSince(\n stream.query.documentId,\n stream.query.scope,\n stream.query.branch,\n -1,\n { actionTypes: stream.decidingActions },\n undefined,\n signal,\n )\n ).results.filter((operation) => !evaluating.has(operation.id)),\n })),\n );\n\n const decidingOperations = operations.filter((operation) =>\n isDecidingAction(operation, readSet),\n );\n\n // Derived streams can only be named by static-stream operations, so an\n // empty static range has an empty derived read-set and this exit is safe.\n if (\n readStreams.every((read) => read.operations.length === 0) &&\n decidingOperations.length === 0\n ) {\n return operations.map(() => undefined);\n }\n\n if (readStreams.length === 0) {\n throw new Error(\n `Decision model for ${target.documentId} reads no stream whose query is known before it is built`,\n );\n }\n\n const writtenProjection = readSet.find(\n (stream) => stream.query.scope === scope,\n );\n\n const walked: WalkStream[] = [];\n const histories: StreamHistory[] = [];\n for (const read of readStreams) {\n const isWritten = read.stream === writtenProjection;\n\n // Walked in the stream they are written to, so a delete among them is\n // seen by the operations after it.\n const streamOperations = isWritten\n ? [...read.operations, ...operations]\n : read.operations;\n\n // Walked from before any of its operations. On the auth stream index 0 is the\n // genesis policy, which a bound of 0 would pre-apply without ever visiting.\n const before = await writeCache.getState(\n read.stream.query.documentId,\n read.stream.query.scope,\n read.stream.query.branch,\n -1,\n signal,\n );\n walked.push({\n streamKey: streamKey(read.stream.query),\n scope: read.stream.query.scope,\n document: before,\n operations: streamOperations,\n apply: read.stream.apply,\n });\n histories.push({\n name: read.stream.name,\n operations: streamOperations,\n });\n }\n\n // Whether the evaluated scope's state is walked, and under which key. A\n // projection-read scope folds through its projection; otherwise a model\n // that reads the executing scope (conditions) folds the full effective\n // stream itself, and a model that does not lets the evaluated operations\n // take positions without contributing state.\n let evaluatedStateKey: string | undefined;\n if (writtenProjection !== undefined) {\n evaluatedStateKey = streamKey(writtenProjection.query);\n } else if (definition.foldEvaluatedScope !== undefined) {\n const query: StreamQuery = {\n documentId: target.documentId,\n scope,\n branch: target.branch,\n };\n // Every effective operation moves state, so this read is unfiltered.\n const storedOperations = (\n await operationStore.getSince(\n query.documentId,\n query.scope,\n query.branch,\n -1,\n undefined,\n undefined,\n signal,\n )\n ).results.filter((operation) => !evaluating.has(operation.id));\n\n const before = await writeCache.getState(\n query.documentId,\n query.scope,\n query.branch,\n -1,\n signal,\n );\n\n evaluatedStateKey = streamKey(query);\n walked.push({\n streamKey: evaluatedStateKey,\n scope,\n document: before,\n operations: [...storedOperations, ...operations],\n apply: definition.foldEvaluatedScope,\n });\n } else {\n walked.push({\n streamKey: EVALUATED_ONLY,\n scope,\n document: walked[0].document,\n operations,\n apply: (document) => document,\n });\n }\n\n // Derived streams join the walk from the union their range mentions. One\n // this replica does not hold stays out, which fails closed; one already\n // walked statically is not read twice.\n const derivedEntries: DerivedEntry[] = [];\n const walkedKeys = new Set(walked.map((stream) => stream.streamKey));\n for (const projection of derivedSet) {\n const queries = projection.queryOverHistory?.(histories) ?? [];\n for (const query of queries) {\n const key = streamKey(query);\n if (walkedKeys.has(key)) {\n continue;\n }\n\n let before: PHDocument;\n try {\n before = await writeCache.getState(\n query.documentId,\n query.scope,\n query.branch,\n -1,\n signal,\n );\n } catch (error) {\n if (error instanceof DocumentNotFoundError) {\n continue;\n }\n throw error;\n }\n\n const streamOperations = (\n await operationStore.getSince(\n query.documentId,\n query.scope,\n query.branch,\n -1,\n { actionTypes: projection.decidingActions },\n undefined,\n signal,\n )\n ).results.filter((operation) => !evaluating.has(operation.id));\n\n walkedKeys.add(key);\n walked.push({\n streamKey: key,\n scope: query.scope,\n document: before,\n operations: streamOperations,\n apply: projection.apply,\n });\n derivedEntries.push({ name: projection.name, query });\n }\n }\n\n const reasons = new Map<string, string | undefined>();\n\n // By hand, because for...of cannot send the verdict back into the generator.\n const walk = walkByPosition(walked);\n let step = walk.next(false);\n while (!step.done) {\n const position = step.value;\n if (!evaluating.has(position.operation.id)) {\n step = walk.next(false);\n continue;\n }\n\n // The executing scope's state as the walk reached this operation, for\n // conditions that read it. Undefined when the model does not fold it.\n const evaluatedDocument =\n evaluatedStateKey === undefined\n ? undefined\n : position.states.get(evaluatedStateKey);\n const scopeState =\n evaluatedDocument === undefined\n ? undefined\n : (evaluatedDocument.state as Record<string, unknown>)[scope];\n\n const evaluation = definition.decide(\n modelAt<M>(\n readSet,\n derivedSet.map((projection) => projection.name),\n derivedEntries,\n position.states,\n ),\n subjectOf(position.operation),\n {\n verb: \"execute\",\n scope: position.operation.action.scope,\n operation: position.operation.action.type,\n },\n { scopeState, actionInput: position.operation.action.input },\n );\n\n const denied = evaluation.decision === \"deny\";\n reasons.set(position.operation.id, denied ? evaluation.reason : undefined);\n step = walk.next(denied);\n }\n\n return operations.map((operation) => reasons.get(operation.id));\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 /**\n * Records the group documents an auth operation's input names, tied to the\n * last written operation like addToCollection. At commit each reference is\n * remembered permanently and the group joins every collection the\n * referencing document belongs to, keeping the earliest join and reopening\n * a closed membership, so sync serves the group's history to every remote\n * that can observe the referencing grant.\n */\n recordGroupReferences(documentId: string, groupIds: string[]): void;\n write(operations: OperationIndexEntry[]): void;\n}\n\n/**\n * Reads are paged with a default limit; follow `next` for the full set.\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 * The documents whose auth history has ever referenced the group, from the\n * group-reference relation. This is the set a group-stream change owes a\n * re-evaluation pass to; it is complete because a group's auth scope cannot\n * reference other groups.\n */\n getGroupReferencers(groupId: string, signal?: AbortSignal): Promise<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 deniedReason?: string | null;\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\nconst DRIVE_COLLECTION_PREFIX = \"drive.\";\n\n/**\n * Identifies the collection a remote synchronizes. Collections are drive-level\n * abstractions (document-drive and reactor-drive), so a collection id is the\n * drive document id plus the branch it scopes to rather than an opaque string.\n *\n * The canonical string form (`drive.${branch}.${driveId}`) is produced only by\n * `key` and parsed only by `fromKey`; that string is the wire and storage\n * representation and is byte-for-byte identical to the legacy\n * `driveCollectionId(branch, driveId)` output, so existing `document_collections`\n * rows and persisted remotes remain valid without migration.\n */\nexport class DriveCollectionId {\n private constructor(\n readonly driveId: string,\n readonly branch: string,\n ) {}\n\n static forDrive(driveId: string, branch = \"main\"): DriveCollectionId {\n return new DriveCollectionId(driveId, branch);\n }\n\n /**\n * The single deserializer for the wire/storage form. `branch` may contain\n * dots, while `driveId` is a dot-free document id, so the drive id is the\n * final dot-delimited segment.\n */\n static fromKey(key: string): DriveCollectionId {\n if (!key.startsWith(DRIVE_COLLECTION_PREFIX)) {\n throw new Error(`Unsupported collection id: ${key}`);\n }\n const rest = key.slice(DRIVE_COLLECTION_PREFIX.length);\n const lastDot = rest.lastIndexOf(\".\");\n if (lastDot === -1 || lastDot === rest.length - 1) {\n throw new Error(`Malformed drive collection id: ${key}`);\n }\n return new DriveCollectionId(\n rest.slice(lastDot + 1),\n rest.slice(0, lastDot),\n );\n }\n\n get key(): string {\n return `${DRIVE_COLLECTION_PREFIX}${this.branch}.${this.driveId}`;\n }\n\n toString(): string {\n return this.key;\n }\n\n equals(other: DriveCollectionId): boolean {\n return this.driveId === other.driveId && this.branch === other.branch;\n }\n}\n","import type {\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\n/** The stream an operation is written to. */\ntype WriteTarget = {\n documentId: string;\n documentType: string;\n scope: string;\n branch: string;\n};\n\ninterface RelationshipPostWriteArgs {\n indexTxn: IOperationIndexTxn;\n stores: ExecutionStores;\n sourceDoc: PHDocument;\n input: RelationshipActionShape;\n job: Job;\n}\nimport {\n hashDocumentStateForScope,\n normalizeDocumentModelVersion,\n} from \"@powerhousedao/shared/document-model\";\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 {\n DocumentDeletedError,\n UpgradePreconditionFailedError,\n} from \"../shared/errors.js\";\nimport { AppendConditionFailedError } from \"../storage/interfaces.js\";\nimport type { ExecutionStores } from \"./execution-scope.js\";\nimport type {\n ExecutingJob,\n JobResult,\n PendingWrite,\n ReactorFeatureFlags,\n} from \"./types.js\";\nimport type { RegisteredDecisionModel } from \"../decision/registered-model.js\";\nimport { decideAtHead } from \"../decision/registered-model.js\";\nimport {\n applyDeleteDocumentAction,\n applyUpgradeDocumentAction,\n buildErrorResult,\n buildSuccessResult,\n createDocumentFromAction,\n createOperation,\n GATED_DOCUMENT_ACTIONS,\n getNextIndexForScope,\n refusalError,\n targetDocumentId,\n updateDocumentRevision,\n} from \"./util.js\";\nimport { SnapshotPosition } from \"../cache/write-cache-types.js\";\n\nexport class DocumentActionHandler {\n constructor(\n private registry: IDocumentModelRegistry,\n private logger: ILogger,\n private driveContainerTypes: ReadonlySet<string>,\n private featureFlags: ReactorFeatureFlags,\n private decisionModel: RegisteredDecisionModel,\n ) {}\n\n /** Whether the write arrives with its evaluation already decided. */\n private alreadyEvaluated(executing: ExecutingJob): boolean {\n return (\n this.featureFlags.documentDecisions &&\n (executing.replayingAcceptedHistory || executing.evaluatedByPosition)\n );\n }\n\n async execute(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult> {\n const { action } = write;\n\n if (write.deniedReason !== undefined) {\n return this.writeDenied(write, executing);\n }\n\n const refusal = await this.refuseIfPolicyDenies(write, executing);\n if (refusal) {\n return refusal;\n }\n\n switch (action.type) {\n case \"CREATE_DOCUMENT\":\n return this.executeCreate(write, executing);\n case \"DELETE_DOCUMENT\":\n return this.executeDelete(write, executing);\n case \"UPGRADE_DOCUMENT\":\n return this.executeUpgrade(write, executing);\n case \"ADD_RELATIONSHIP\":\n return this.executeAddRelationship(write, executing);\n case \"REMOVE_RELATIONSHIP\":\n return this.executeRemoveRelationship(write, executing);\n case \"UPDATE_RELATIONSHIP\":\n return this.executeUpdateRelationship(write, executing);\n default:\n return buildErrorResult(\n executing.job,\n new Error(`Unknown document action type: ${action.type}`),\n executing.startTime,\n );\n }\n }\n\n /**\n * Refuses a document-scope write the policy denies, or undefined to proceed.\n * Without this an `execute`-on-`document` grant is unenforceable.\n */\n private async refuseIfPolicyDenies(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult | undefined> {\n const { action } = write;\n const { job, startTime, stores, signal } = executing;\n\n if (\n !this.featureFlags.documentDecisions ||\n !this.featureFlags.authEnforcement ||\n this.alreadyEvaluated(executing) ||\n !GATED_DOCUMENT_ACTIONS.has(action.type)\n ) {\n return undefined;\n }\n\n // Decided against the document the action writes to, which the job is not\n // required to be keyed by.\n const documentId = targetDocumentId(action, job.documentId);\n\n // Unlike processWrite, the decision's appendCondition is deliberately\n // dropped: a later-timestamped auth operation cannot retroactively deny\n // this write, and a backdated one triggers reevaluateIfNeeded, so the\n // repair path exists without conditioning on the auth head.\n let admission;\n try {\n admission = await decideAtHead(\n this.decisionModel,\n stores.writeCache,\n { documentId, branch: job.branch },\n {\n address: action.context?.signer?.user.address,\n key: action.context?.signer?.app.key,\n },\n { verb: \"execute\", scope: action.scope, operation: action.type },\n signal,\n this.featureFlags.authConditions\n ? { actionInput: action.input }\n : undefined,\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 (admission.evaluation.decision === \"allow\") {\n return undefined;\n }\n\n return buildErrorResult(\n job,\n refusalError(\n admission.evaluation.reason,\n documentId,\n admission.deletedAtUtcIso,\n action,\n ),\n startTime,\n );\n }\n\n /** A refused operation holds a position in the stream but changes nothing. */\n private async writeDenied(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult> {\n const { action, skip, sourceRemote, deniedReason } = write;\n const { job, startTime, indexTxn, stores, signal } = executing;\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 const index = getNextIndexForScope(document, job.scope);\n\n // A denied operation records the state that still stands. With a retraction\n // skip the head includes what it supersedes, so read back past the skip.\n let standing = document;\n if (skip > 0) {\n try {\n standing = await stores.writeCache.getState(\n job.documentId,\n job.scope,\n job.branch,\n index - skip - 1,\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\n let operation = createOperation(action, index, skip, {\n documentId: job.documentId,\n scope: job.scope,\n branch: job.branch,\n });\n operation.deniedReason = deniedReason;\n operation.hash = hashDocumentStateForScope(standing, job.scope);\n\n const writeResult = await this.writeOperationToStore(\n {\n documentId: job.documentId,\n documentType: document.header.documentType,\n scope: job.scope,\n branch: job.branch,\n },\n operation,\n executing,\n );\n if (!Array.isArray(writeResult)) {\n return writeResult;\n }\n operation = writeResult[0];\n\n updateDocumentRevision(standing, job.scope, operation.index);\n\n standing.operations = {\n ...standing.operations,\n [job.scope]: [...(standing.operations[job.scope] ?? []), operation],\n };\n\n stores.writeCache.putState(\n job.documentId,\n job.scope,\n job.branch,\n operation.index,\n standing,\n SnapshotPosition.Head,\n );\n\n indexTxn.write([\n {\n ...operation,\n documentId: job.documentId,\n documentType: document.header.documentType,\n branch: job.branch,\n scope: job.scope,\n sourceRemote,\n },\n ]);\n\n stores.documentMetaCache.putDocumentMeta(job.documentId, job.branch, {\n state: standing.state.document,\n documentType: standing.header.documentType,\n documentScopeRevision: operation.index + 1,\n });\n\n return buildSuccessResult(\n job,\n operation,\n job.documentId,\n standing.header.documentType,\n JSON.stringify({\n header: standing.header,\n document: standing.state.document,\n }),\n startTime,\n );\n }\n\n private async executeCreate(\n write: PendingWrite,\n executing: ExecutingJob,\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 { action, skip, sourceRemote } = write;\n const { job, startTime, indexTxn, stores, signal } = executing;\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 {\n documentId: document.header.id,\n documentType: document.header.documentType,\n scope: job.scope,\n branch: job.branch,\n },\n operation,\n executing,\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 SnapshotPosition.Head,\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.forDrive(\n document.header.id,\n job.branch,\n ).key;\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 write: PendingWrite,\n executing: ExecutingJob,\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 { action, skip, sourceRemote } = write;\n const { job, startTime, indexTxn, stores, signal } = executing;\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 // DCB allows positional deletion, so we may have already determined the\n // evaluation\n const documentState = document.state.document;\n if (documentState.isDeleted && !this.alreadyEvaluated(executing)) {\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, skip, {\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 {\n documentId: documentId,\n documentType: document.header.documentType,\n scope: job.scope,\n branch: job.branch,\n },\n operation,\n executing,\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 SnapshotPosition.Head,\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 write: PendingWrite,\n executing: ExecutingJob,\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 { action, skip, sourceRemote } = write;\n const { job, startTime, indexTxn, stores, signal } = executing;\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 // DCB allows for positional deletion, so the evaluation may have already been\n // decided\n const documentState = document.state.document;\n if (documentState.isDeleted && !this.alreadyEvaluated(executing)) {\n return buildErrorResult(\n job,\n new DocumentDeletedError(documentId, documentState.deletedAtUtcIso),\n startTime,\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 // The action carries the client's snapshot of the document version and\n // per-scope revisions. Replay treats both as ground truth when segmenting\n // history, so a snapshot that no longer matches must be rejected here and\n // rebuilt by the client rather than persisted. Writes that arrive with\n // their evaluation already decided replay accepted history and are exempt.\n const arrivesDecided =\n executing.replayingAcceptedHistory || executing.evaluatedByPosition;\n if (fromVersion > 0 && !arrivesDecided) {\n const stampedVersion = normalizeDocumentModelVersion(\n documentState.version,\n );\n if (fromVersion !== stampedVersion) {\n return buildErrorResult(\n job,\n new UpgradePreconditionFailedError(\n documentId,\n `fromVersion ${fromVersion} does not match the document's version ${stampedVersion}`,\n ),\n startTime,\n );\n }\n\n if (input.revision !== undefined) {\n // The cached document's header carries revisions stamped when its\n // snapshot was built; sibling-scope writes since then do not refresh\n // it, so the store is asked directly.\n let actualRevisions: Record<string, number>;\n try {\n const revisions = await stores.operationStore.getRevisions(\n documentId,\n job.branch,\n signal,\n );\n actualRevisions = revisions.revision;\n } catch (error) {\n return buildErrorResult(\n job,\n new Error(\n `Failed to fetch revisions for upgrade: ${error instanceof Error ? error.message : String(error)}`,\n ),\n startTime,\n );\n }\n\n const revisionScopes = new Set([\n ...Object.keys(input.revision),\n ...Object.keys(actualRevisions),\n ]);\n for (const revisionScope of revisionScopes) {\n const snapshot = input.revision[revisionScope] ?? 0;\n const actual = actualRevisions[revisionScope] ?? 0;\n if (snapshot !== actual) {\n return buildErrorResult(\n job,\n new UpgradePreconditionFailedError(\n documentId,\n `revision snapshot for scope \"${revisionScope}\" is ${snapshot} but the document is at ${actual}`,\n ),\n startTime,\n );\n }\n }\n }\n }\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 const otherScopes = Object.keys(document.state).filter(\n (scope) => scope !== job.scope,\n );\n\n // Migration reducers reshape every scope, so validated upgrades need\n // accurate sibling state. Seed upgrades (fromVersion 0) run no\n // transitions and take their state from the action's initialState, so\n // the fetches would be pure overhead in every create batch.\n if (fromVersion > 0) {\n for (const scope of otherScopes) {\n let scopedDocument: PHDocument;\n try {\n scopedDocument = await stores.writeCache.getState(\n documentId,\n scope,\n job.branch,\n undefined,\n signal,\n );\n } catch (error) {\n return buildErrorResult(\n job,\n new Error(\n `Failed to fetch ${scope} scope for upgrade: ${error instanceof Error ? error.message : String(error)}`,\n ),\n startTime,\n );\n }\n document = {\n ...document,\n state: {\n ...document.state,\n [scope]: (scopedDocument.state as Record<string, unknown>)[scope],\n } as typeof document.state,\n };\n }\n }\n\n const nextIndex = getNextIndexForScope(document, job.scope);\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 // Vouches that every scope echoed here was fetched fresh before the\n // migration ran. Upgrade operations persisted by executors that never\n // fetched sibling scopes carry stale echoes, and the document view must\n // not reindex sibling scopes from those.\n if (fromVersion > 0) {\n resultingStateObj.__migrated = true;\n }\n const resultingState = JSON.stringify(resultingStateObj);\n\n const writeResult = await this.writeOperationToStore(\n {\n documentId: documentId,\n documentType: document.header.documentType,\n scope: job.scope,\n branch: job.branch,\n },\n operation,\n executing,\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 SnapshotPosition.Head,\n );\n\n // Sibling snapshots hold pre-upgrade state, but evicting them before the\n // transaction commits lets a concurrent read repopulate the cache with\n // that same state, so the eviction is deferred to after the commit.\n for (const scope of otherScopes) {\n executing.postCommitInvalidations.push({\n documentId,\n scope,\n branch: job.branch,\n });\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 write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult> {\n return this.withRelationshipAction(\n \"ADD_RELATIONSHIP\",\n write,\n executing,\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.forDrive(\n input.sourceId,\n j.branch,\n ).key;\n txn.addToCollection(collectionId, input.targetId);\n s.collectionMembershipCache.invalidate(input.targetId);\n }\n },\n );\n }\n\n private executeRemoveRelationship(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult> {\n return this.withRelationshipAction(\n \"REMOVE_RELATIONSHIP\",\n write,\n executing,\n null,\n ({ indexTxn: txn, stores: s, sourceDoc, input, job: j }) => {\n if (this.driveContainerTypes.has(sourceDoc.header.documentType)) {\n const collectionId = DriveCollectionId.forDrive(\n input.sourceId,\n j.branch,\n ).key;\n txn.removeFromCollection(collectionId, input.targetId);\n s.collectionMembershipCache.invalidate(input.targetId);\n }\n },\n );\n }\n\n private executeUpdateRelationship(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult> {\n return this.withRelationshipAction(\n \"UPDATE_RELATIONSHIP\",\n write,\n executing,\n null,\n null,\n );\n }\n\n private async withRelationshipAction(\n actionTypeName: string,\n write: PendingWrite,\n executing: ExecutingJob,\n preValidate: ((input: RelationshipActionShape) => Error | null) | null,\n postWrite: ((args: RelationshipPostWriteArgs) => void) | null,\n ): Promise<RelationshipJobResult> {\n const { action, skip, sourceRemote } = write;\n const { job, startTime, indexTxn, stores, signal } = executing;\n\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, skip, {\n documentId: input.sourceId,\n scope: job.scope,\n branch: job.branch,\n });\n\n const writeResult = await this.writeOperationToStore(\n {\n documentId: input.sourceId,\n documentType: sourceDoc.header.documentType,\n scope: job.scope,\n branch: job.branch,\n },\n operation,\n executing,\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 SnapshotPosition.Head,\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 target: WriteTarget,\n operation: Operation,\n executing: ExecutingJob,\n ): Promise<Operation[] | JobResult> {\n const { documentId, documentType, scope, branch } = target;\n const { job, startTime, stores, signal } = executing;\n\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 // read-set streams must also leave the cache, or a retry rebuilds the\n // same stale condition\n if (AppendConditionFailedError.isError(error)) {\n for (const stream of error.condition.streams) {\n stores.writeCache.invalidate(\n stream.documentId,\n stream.scope,\n stream.branch,\n );\n }\n }\n\n return {\n job,\n success: false,\n error: AppendConditionFailedError.isError(error)\n ? error\n : 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 {\n baseReducerVersion,\n decide,\n garbageCollect,\n hashDocumentStateForScope,\n isUndoRedo,\n mentionedGroupIds,\n normalizeDocumentModelVersion,\n sortOperations,\n} from \"@powerhousedao/shared/document-model\";\nimport type { ILogger } from \"document-model\";\nimport type { ICollectionMembershipCache } from \"../cache/collection-membership-cache.js\";\nimport { resolveFeatureFlags } from \"../core/feature-flags.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 {\n AuthorizationDeniedError,\n AuthTimestampNotMonotonicError,\n DocumentDeletedError,\n ExcessiveReshuffleError,\n InvalidOperationTimestampError,\n} from \"../shared/errors.js\";\nimport { yieldToMain } from \"../shared/utils.js\";\nimport type { SignatureVerificationHandler } from \"../signer/types.js\";\nimport {\n AppendConditionFailedError,\n type AppendCondition,\n type IOperationStore,\n} from \"../storage/interfaces.js\";\nimport { reshuffleByTimestamp } from \"../utils/reshuffle.js\";\nimport type { RegisteredDecisionModel } from \"../decision/registered-model.js\";\nimport {\n decideAtHead,\n selectDecisionModel,\n} from \"../decision/registered-model.js\";\nimport { staticReadSet } from \"../decision/build-decision-model.js\";\nimport { evaluateByPosition } from \"../decision/evaluation.js\";\nimport { retractionSkip } from \"../decision/merged-order.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 {\n ExecutingJob,\n JobExecutorConfig,\n JobResult,\n PendingWrite,\n PositionedWrites,\n ReactorFeatureFlags,\n} from \"./types.js\";\nimport {\n buildErrorResult,\n createOperation,\n DOCUMENT_SCOPE_ACTIONS,\n getNextIndexForScope,\n isGenesisOperation,\n refusalError,\n} from \"./util.js\";\nimport { SnapshotPosition } from \"../cache/write-cache-types.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\n/**\n * A write that just committed, tested to decide whether earlier evaluations\n * still hold. The operations all belong to `scope` of the job's document.\n */\ntype EvaluationCriteria = {\n scope: string;\n operations: Operation[];\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 featureFlags: ReactorFeatureFlags;\n private decisionModel: RegisteredDecisionModel;\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 featureFlags: config.featureFlags ?? {},\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\n // Resolved separately so reads are plain booleans; the config keeps what\n // the caller passed, because that is what crosses to a pooled worker. The\n // builder validates too, but a pooled worker is constructed directly from\n // the flags that crossed the boundary.\n this.featureFlags = resolveFeatureFlags(config.featureFlags);\n this.decisionModel = selectDecisionModel(this.featureFlags, registry);\n this.signatureVerifierModule = new SignatureVerifier(signatureVerifier);\n this.documentActionHandler = new DocumentActionHandler(\n registry,\n logger,\n driveContainerTypes,\n this.featureFlags,\n this.decisionModel,\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 // Entries handlers request invalidated only after the transaction commits\n const postCommitInvalidations: 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 replayingAcceptedHistory: true,\n evaluatedByPosition: false,\n postCommitInvalidations,\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 if (job.kind === \"reevaluation\") {\n const reevalResult = await this.executeReevaluationJob({\n job,\n startTime,\n indexTxn,\n stores,\n signal,\n replayingAcceptedHistory: false,\n evaluatedByPosition: false,\n postCommitInvalidations,\n });\n if (reevalResult.success && reevalResult.operationsWithContext) {\n for (const owc of reevalResult.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 (\n let i = 0;\n i < reevalResult.operationsWithContext.length;\n i++\n ) {\n reevalResult.operationsWithContext[i].context.ordinal =\n ordinals[i];\n }\n if (reevalResult.operationsWithContext.length > 0) {\n const collectionMemberships =\n await this.getCollectionMembershipsForOperations(\n reevalResult.operationsWithContext,\n stores,\n );\n pendingEvent = {\n jobId: job.id,\n operations: reevalResult.operationsWithContext,\n jobMeta: job.meta,\n collectionMemberships,\n };\n }\n }\n return reevalResult;\n }\n\n const positioned = await this.positionByTimestamp(job, stores, signal);\n if (positioned.error) {\n return buildErrorResult(job, positioned.error, startTime);\n }\n\n const executing: ExecutingJob = {\n job,\n startTime,\n indexTxn,\n stores,\n signal,\n replayingAcceptedHistory: false,\n evaluatedByPosition: positioned.evaluatedByPosition,\n postCommitInvalidations,\n };\n\n const actionResult = await this.processActions(\n positioned.writes,\n executing,\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 // Put here because a re-eval pass writes through the same db db\n // transaction.\n const reevaluationError = await this.reevaluateIfCriteriaMet(\n { scope: job.scope, operations: actionResult.generatedOperations },\n executing,\n );\n if (reevaluationError) {\n return {\n job,\n success: false as const,\n error: reevaluationError,\n duration: Date.now() - startTime,\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 (result.success) {\n for (const entry of postCommitInvalidations) {\n this.writeCache.invalidate(entry.documentId, entry.scope, entry.branch);\n }\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 writes: PendingWrite[],\n executing: ExecutingJob,\n ): Promise<ProcessActionsResult> {\n const { job, signal } = executing;\n const actions = writes.map((write) => write.action);\n\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 InvalidOperationTimestampError(\n job.documentId,\n action.scope,\n action.timestampUtcMs,\n `action ${action.type} (id: ${action.id})`,\n ),\n };\n }\n }\n\n let lastYield = performance.now();\n\n for (const write of writes) {\n const isDocumentAction = DOCUMENT_SCOPE_ACTIONS.has(write.action.type);\n const result = isDocumentAction\n ? await this.documentActionHandler.execute(write, executing)\n : await this.executeRegularAction(write, executing);\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 write: PendingWrite,\n executing: ExecutingJob,\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 { action, skip, sourceOperation, sourceRemote, deniedReason } = write;\n const { job, startTime, indexTxn, stores, signal } = executing;\n\n // append conditions are used iff the decision model flag is on\n let appendCondition: AppendCondition | undefined;\n let documentVersion: number | undefined;\n\n const alreadyEvaluated =\n this.featureFlags.documentDecisions &&\n (executing.replayingAcceptedHistory || executing.evaluatedByPosition);\n\n if (this.featureFlags.documentDecisions && !alreadyEvaluated) {\n const target = { documentId: job.documentId, branch: job.branch };\n\n let admission;\n try {\n admission = await decideAtHead(\n this.decisionModel,\n stores.writeCache,\n target,\n {\n address: action.context?.signer?.user.address,\n key: action.context?.signer?.app.key,\n },\n { verb: \"execute\", scope: action.scope, operation: action.type },\n signal,\n this.featureFlags.authConditions\n ? { actionInput: action.input }\n : undefined,\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 (admission.evaluation.decision === \"deny\") {\n return buildErrorResult(\n job,\n refusalError(\n admission.evaluation.reason,\n job.documentId,\n admission.deletedAtUtcIso,\n action,\n ),\n startTime,\n );\n }\n\n appendCondition = admission.appendCondition;\n documentVersion = admission.documentVersion;\n } else if (alreadyEvaluated) {\n const documentScope = await stores.writeCache.getState(\n job.documentId,\n \"document\",\n job.branch,\n undefined,\n signal,\n );\n documentVersion = documentScope.state.document.version;\n } else {\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(\n job.documentId,\n docMeta.state.deletedAtUtcIso,\n ),\n startTime,\n );\n }\n\n documentVersion = docMeta.state.version;\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 // The interim gate, superseded by the auth projection. Re-evaluating already\n // accepted operations could drop them and diverge replicas.\n if (\n !this.featureFlags.authEnforcement &&\n !executing.replayingAcceptedHistory\n ) {\n const subject = {\n address: write.action.context?.signer?.user.address,\n key: write.action.context?.signer?.app.key,\n };\n const decision = decide(document.state.auth, subject, {\n verb: \"execute\",\n scope: action.scope,\n operation: action.type,\n });\n if (decision === \"deny\") {\n return buildErrorResult(\n job,\n new AuthorizationDeniedError(\n job.documentId,\n action.scope,\n action.type,\n subject.address,\n ),\n startTime,\n );\n }\n }\n\n let module: DocumentModelModule;\n try {\n module = this.registry.getModule(\n document.header.documentType,\n normalizeDocumentModelVersion(documentVersion),\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\n if (deniedReason !== undefined) {\n // A denied operation holds only a position but does not change state.\n const index = getNextIndexForScope(document, job.scope);\n const denied = createOperation(action, index, skip, {\n documentId: job.documentId,\n scope: job.scope,\n branch: job.branch,\n });\n denied.deniedReason = deniedReason;\n\n // A denied operation does not change state, so it records the previous\n // state. We need to add skip to get the actual previous state.\n let standing = document;\n if (skip > 0) {\n try {\n standing = await stores.writeCache.getState(\n job.documentId,\n job.scope,\n job.branch,\n index - skip - 1,\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\n denied.hash = hashDocumentStateForScope(standing, job.scope);\n\n updatedDocument = {\n ...standing,\n operations: {\n ...standing.operations,\n [job.scope]: [...(standing.operations[job.scope] ?? []), denied],\n },\n };\n } else {\n try {\n const protocolVersion = baseReducerVersion(document.header);\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\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 // Undefined unless a decision was made, so the store's guard is only\n // enforced for a write a decision stands behind.\n appendCondition,\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 // read-set streams must also leave the cache, or a retry rebuilds the\n // same stale condition\n if (AppendConditionFailedError.isError(error)) {\n for (const stream of error.condition.streams) {\n stores.writeCache.invalidate(\n stream.documentId,\n stream.scope,\n stream.branch,\n );\n }\n }\n\n return {\n job,\n success: false,\n error: AppendConditionFailedError.isError(error)\n ? error\n : 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 SnapshotPosition.Head,\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 // References come from the input as it arrived, including operations\n // stored denied or errored, so sync topology never depends on evaluation.\n if (scope === \"auth\") {\n indexTxn.recordGroupReferences(job.documentId, mentionedGroupIds(action));\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 /**\n * Orders a write by timestamp and decides it where it lands. The caller\n * supplies the timestamp, so a write can belong before operations already\n * stored; those are re-appended alongside it, the way a load reshuffles.\n *\n * Deciding a backdated write at the stream heads instead of at its position\n * would overwrite the verdict every other replica computes for it.\n */\n private async positionByTimestamp(\n job: Job,\n stores: ExecutionStores,\n signal?: AbortSignal,\n ): Promise<PositionedWrites> {\n const plain = (): PositionedWrites => ({\n writes: job.actions.map((action) => ({\n action,\n skip: 0,\n sourceRemote: \"\",\n })),\n evaluatedByPosition: false,\n });\n\n if (!this.featureFlags.documentDecisions || job.actions.length === 0) {\n return plain();\n }\n\n // Parsed, not compared as strings, here and below: a submitted timestamp\n // may carry second precision, and \"…:00Z\" sorts after \"…:00.000Z\"\n // lexically though it is the earlier instant. Selecting the minimum by\n // string would pick the later one, so a genuinely backdated action would\n // read as current and be appended at the tail instead of positioned.\n let earliest = job.actions[0].timestampUtcMs;\n let earliestAt = Date.parse(earliest);\n for (const action of job.actions) {\n const at = Date.parse(action.timestampUtcMs);\n if (at < earliestAt) {\n earliest = action.timestampUtcMs;\n earliestAt = at;\n }\n }\n\n const revisions = await stores.operationStore.getRevisions(\n job.documentId,\n job.branch,\n signal,\n );\n\n const backdated = earliestAt < Date.parse(revisions.latestTimestamp);\n\n // The auth stream is never reshuffled: rejected by the monotonic rule, or\n // evaluated where it lands without moving anything.\n if (this.featureFlags.authEnforcement && job.scope === \"auth\") {\n const newest = await stores.operationStore.getStreamLatestTimestamp(\n job.documentId,\n \"auth\",\n job.branch,\n signal,\n );\n const violation = this.firstNonMonotonicTimestamp(\n job.actions,\n newest,\n job.documentId,\n job.branch,\n );\n if (violation) {\n return { writes: [], evaluatedByPosition: false, error: violation };\n }\n\n if (!backdated) {\n return plain();\n }\n return this.evaluatePositioned(\n job,\n stores,\n this.appendedOperations(job, revisions.revision[job.scope] ?? 0),\n signal,\n );\n }\n\n if (!backdated) {\n return plain();\n }\n\n const conflicting = (\n await stores.operationStore.getConflicting(\n job.documentId,\n job.scope,\n job.branch,\n earliest,\n undefined,\n signal,\n )\n ).results.filter((operation) => !isGenesisOperation(operation));\n\n // Nothing to move here, but still below another scope's newest operation.\n if (conflicting.length === 0) {\n if (!this.featureFlags.authEnforcement) {\n return plain();\n }\n return this.evaluatePositioned(\n job,\n stores,\n this.appendedOperations(job, revisions.revision[job.scope] ?? 0),\n signal,\n );\n }\n\n const nextIndex = revisions.revision[job.scope] ?? 0;\n let firstConflicting = conflicting[0].index;\n for (const operation of conflicting) {\n if (operation.index < firstConflicting) {\n firstConflicting = operation.index;\n }\n }\n\n // Given positions rather than stored rows, so a tie puts the new write\n // after what is already there.\n const incoming = job.actions.map(\n (action, i) =>\n ({\n id: action.id,\n index: nextIndex + i,\n skip: 0,\n hash: \"\",\n timestampUtcMs: action.timestampUtcMs,\n action,\n }) as Operation,\n );\n\n const merged = reshuffleByTimestamp(\n { index: nextIndex, skip: retractionSkip(nextIndex, firstConflicting) },\n conflicting,\n incoming,\n );\n\n stores.writeCache.invalidate(job.documentId, job.scope, job.branch);\n\n // Without the auth projection the only refusal is a deletion, which fails the\n // job outright, so a head decide is equivalent.\n if (!this.featureFlags.authEnforcement) {\n return {\n writes: merged.map((operation) => ({\n action: operation.action,\n skip: operation.skip,\n sourceRemote: \"\",\n })),\n evaluatedByPosition: false,\n };\n }\n\n return this.evaluatePositioned(job, stores, merged, signal);\n }\n\n /**\n * Decides each operation where it lands and carries the verdict on it. A\n * refused submitted action is reported to the caller and nothing is stored; a\n * refused operation the reshuffle merely moved keeps its verdict, because it\n * already holds a position.\n *\n * The operations carry the indexes and skips they will be stored at, because\n * the walk resolves skips before it orders them.\n */\n private async evaluatePositioned(\n job: Job,\n stores: ExecutionStores,\n operations: Operation[],\n signal?: AbortSignal,\n ): Promise<PositionedWrites> {\n const reasons = await evaluateByPosition(\n this.decisionModel,\n { documentId: job.documentId, branch: job.branch },\n { scope: job.scope, operations },\n stores,\n signal,\n );\n\n const submitted = new Set(job.actions.map((action) => action.id));\n for (let i = 0; i < operations.length; i++) {\n const reason = reasons[i];\n if (reason !== undefined && submitted.has(operations[i].action.id)) {\n return {\n writes: [],\n evaluatedByPosition: false,\n error: refusalError(\n reason,\n job.documentId,\n null,\n operations[i].action,\n ),\n };\n }\n }\n\n return {\n writes: operations.map((operation, i) => ({\n action: operation.action,\n skip: operation.skip,\n sourceRemote: \"\",\n deniedReason: reasons[i],\n })),\n evaluatedByPosition: true,\n };\n }\n\n /**\n * The scopes a re-evaluation pass visits, in a fixed order.\n *\n * The revisions map comes from a query with no ORDER BY, and the order is\n * load-bearing: each scope's pass re-reads the auth stream, and the walk skips\n * an operation by its stored denial, so a denial this pass just wrote is\n * visible to a later-visited scope and invisible to an earlier one. The model's\n * own projection order leads, then the rest sorted, so the pass is reproducible\n * across replicas and across runs.\n */\n private evaluationOrder(\n target: { documentId: string; branch: string },\n revision: Record<string, number>,\n ): string[] {\n const definition = this.decisionModel(target);\n\n const evaluated = Object.keys(revision).filter((scope) =>\n definition.evaluatesScope(scope),\n );\n\n const leading: string[] = [];\n for (const stream of staticReadSet(definition)) {\n const scope = stream.query.scope;\n if (evaluated.includes(scope) && !leading.includes(scope)) {\n leading.push(scope);\n }\n }\n\n const rest = evaluated\n .filter((scope) => !leading.includes(scope))\n .sort((a, b) => a.localeCompare(b));\n\n return [...leading, ...rest];\n }\n\n /**\n * The first timestamp in the batch that does not strictly exceed everything\n * ahead of it, or undefined when the whole batch is monotonic.\n *\n * The bound is carried forward rather than compared against one stored maximum,\n * because a single execute can carry several auth actions stamped in the same\n * millisecond. Letting a tie through would store a stream the position walk\n * then refuses to read, with no repair path.\n */\n private firstNonMonotonicTimestamp(\n entries: Array<{ timestampUtcMs: string }>,\n newest: string | undefined,\n documentId: string,\n branch: string,\n ): Error | undefined {\n let boundIso = newest;\n let bound =\n newest === undefined ? Number.NEGATIVE_INFINITY : Date.parse(newest);\n\n for (const entry of entries) {\n if (!isValidISOTimestamp(entry.timestampUtcMs)) {\n return new InvalidOperationTimestampError(\n documentId,\n \"auth\",\n entry.timestampUtcMs,\n \"auth operation\",\n );\n }\n\n const at = Date.parse(entry.timestampUtcMs);\n if (boundIso !== undefined && at <= bound) {\n return new AuthTimestampNotMonotonicError(\n documentId,\n branch,\n entry.timestampUtcMs,\n boundIso,\n );\n }\n\n bound = at;\n boundIso = entry.timestampUtcMs;\n }\n\n return undefined;\n }\n\n /** The operations a batch of submitted actions appends at the scope's tail. */\n private appendedOperations(job: Job, nextIndex: number): Operation[] {\n return job.actions.map(\n (action, i) =>\n ({\n id: action.id,\n index: nextIndex + i,\n skip: 0,\n hash: \"\",\n timestampUtcMs: action.timestampUtcMs,\n action,\n }) as Operation,\n );\n }\n\n /**\n * Re-evaluates the document when a write meets both criteria: it was written\n * to a stream the model reads, and it is timestamped before an operation\n * already stored. The caller supplies the timestamp and the reactor does not replace\n * it, so a mutation job can write such an operation just as a load job can,\n * which is why both executeJob and executeLoadJob call this.\n */\n private async reevaluateIfCriteriaMet(\n criteria: EvaluationCriteria,\n executing: ExecutingJob,\n ): Promise<Error | undefined> {\n if (!this.featureFlags.documentDecisions) {\n return undefined;\n }\n\n const { job, stores, signal } = executing;\n\n const target = { documentId: job.documentId, branch: job.branch };\n const inReadSet = staticReadSet(this.decisionModel(target)).some(\n (stream) =>\n stream.query.documentId === job.documentId &&\n stream.query.scope === criteria.scope &&\n stream.query.branch === job.branch,\n );\n if (!inReadSet) {\n return undefined;\n }\n\n const revisions = await stores.operationStore.getRevisions(\n job.documentId,\n job.branch,\n signal,\n );\n const latest = Date.parse(revisions.latestTimestamp);\n\n const backdated = criteria.operations.some(\n (operation) => Date.parse(operation.timestampUtcMs) < latest,\n );\n if (!backdated) {\n return undefined;\n }\n\n const outcome = await this.reevaluateDocument(executing);\n return outcome.error;\n }\n\n /**\n * Re-evaluates every scope the model evaluates. Where an operation's\n * evaluation differs from what is stored, the tail from that operation is\n * re-appended, carrying a skip that spans the indices it supersedes.\n */\n private async reevaluateDocument(\n executing: ExecutingJob,\n ): Promise<{ error?: Error; operationsWithContext: OperationWithContext[] }> {\n const { job, stores, signal } = executing;\n\n const target = { documentId: job.documentId, branch: job.branch };\n const reappended: OperationWithContext[] = [];\n\n const revisions = await stores.operationStore.getRevisions(\n job.documentId,\n job.branch,\n signal,\n );\n\n for (const scope of this.evaluationOrder(target, revisions.revision)) {\n const stored = (\n await stores.operationStore.getSince(\n job.documentId,\n scope,\n job.branch,\n -1,\n undefined,\n undefined,\n signal,\n )\n ).results;\n\n const effective = garbageCollect(sortOperations([...stored]));\n if (effective.length === 0) {\n continue;\n }\n\n const reevaluated = await evaluateByPosition(\n this.decisionModel,\n target,\n { scope, operations: effective },\n stores,\n signal,\n );\n\n const firstChange = effective.findIndex(\n (operation, i) => operation.deniedReason !== reevaluated[i],\n );\n if (firstChange === -1) {\n continue;\n }\n\n const tail = effective.slice(firstChange);\n const nextIndex = revisions.revision[scope];\n\n stores.writeCache.invalidate(job.documentId, scope, job.branch);\n\n const result = await this.processActions(\n tail.map((operation, i) => ({\n action: operation.action,\n skip: i === 0 ? retractionSkip(nextIndex, tail[0].index) : 0,\n sourceRemote: \"\",\n deniedReason: reevaluated[firstChange + i],\n })),\n {\n ...executing,\n job: { ...job, scope },\n replayingAcceptedHistory: true,\n evaluatedByPosition: true,\n },\n );\n\n if (!result.success) {\n return {\n error:\n result.error ??\n new Error(`Re-evaluation of ${job.documentId} ${scope} failed`),\n operationsWithContext: reappended,\n };\n }\n\n reappended.push(...result.operationsWithContext);\n }\n\n return { operationsWithContext: reappended };\n }\n\n /**\n * Re-judges a document's stored operations because a read-set stream in\n * another document (a group) gained an operation. The trigger timestamp\n * bounds the work: an operation later than everything this document holds\n * cannot change any evaluation, so the pass is skipped.\n */\n private async executeReevaluationJob(\n executing: ExecutingJob,\n ): Promise<JobResult> {\n const { job, startTime, stores, signal } = executing;\n\n if (!this.featureFlags.documentDecisions) {\n return {\n job,\n success: true,\n operations: [],\n operationsWithContext: [],\n duration: Date.now() - startTime,\n };\n }\n\n const trigger = job.meta.triggerTimestampUtcMs;\n if (typeof trigger === \"string\") {\n let latestTimestamp: string;\n try {\n const revisions = await stores.operationStore.getRevisions(\n job.documentId,\n job.branch,\n signal,\n );\n latestTimestamp = revisions.latestTimestamp;\n } catch {\n // Nothing stored for this document here, so nothing to re-judge.\n return {\n job,\n success: true,\n operations: [],\n operationsWithContext: [],\n duration: Date.now() - startTime,\n };\n }\n\n if (Date.parse(trigger) > Date.parse(latestTimestamp)) {\n return {\n job,\n success: true,\n operations: [],\n operationsWithContext: [],\n duration: Date.now() - startTime,\n };\n }\n }\n\n const outcome = await this.reevaluateDocument(executing);\n if (outcome.error) {\n return buildErrorResult(job, outcome.error, startTime);\n }\n\n return {\n job,\n success: true,\n operations: outcome.operationsWithContext.map((owc) => owc.operation),\n operationsWithContext: outcome.operationsWithContext,\n duration: Date.now() - startTime,\n };\n }\n\n private async executeLoadJob(executing: ExecutingJob): Promise<JobResult> {\n const { job, startTime, indexTxn, stores, signal } = executing;\n\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 // Without DCB, we reject entire load jobs. With DCB we are able to\n // accept/deny individual operations.\n if (docMeta?.state.isDeleted && !this.featureFlags.documentDecisions) {\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 // The auth stream holds no ties: an arrival that does not exceed its newest\n // timestamp is rejected rather than repositioned.\n const monotonicAuthStream =\n this.featureFlags.authEnforcement && scope === \"auth\";\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 InvalidOperationTimestampError(\n job.documentId,\n scope,\n operation.timestampUtcMs,\n `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 (Date.parse(ts) < Date.parse(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 // Creation holds the first two indexes for the life of the document, so it\n // never moves however far back the conflicting range reaches. The auth stream\n // moves nothing at all.\n const existingOpsToReshuffle = monotonicAuthStream\n ? []\n : nonSupersededOps.filter((operation) => !isGenesisOperation(operation));\n\n // Only work this load does for the first time counts. A re-append is an action\n // the window already holds twice, so counting those would make the busiest\n // documents revocation-proof.\n const actionIdCounts = new Map<string, number>();\n for (const operation of allOpsFromMinConflictingIndex) {\n actionIdCounts.set(\n operation.action.id,\n (actionIdCounts.get(operation.action.id) ?? 0) + 1,\n );\n }\n const reshuffleCost = existingOpsToReshuffle.filter(\n (operation) => (actionIdCounts.get(operation.action.id) ?? 0) < 2,\n ).length;\n\n if (reshuffleCost > this.config.maxSkipThreshold) {\n return {\n job,\n success: false,\n error: new ExcessiveReshuffleError(\n job.documentId,\n scope,\n reshuffleCost,\n this.config.maxSkipThreshold,\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 // After the dedup, never before: a re-appended auth operation keeps its\n // original timestamp and does travel, so a re-delivered copy is at or below\n // the local head and would dead-letter on traffic both replicas agree about.\n if (monotonicAuthStream) {\n const newest = await stores.operationStore.getStreamLatestTimestamp(\n job.documentId,\n \"auth\",\n job.branch,\n signal,\n );\n const violation = this.firstNonMonotonicTimestamp(\n [...incomingOpsToApply].sort((a, b) => a.index - b.index),\n newest,\n job.documentId,\n job.branch,\n );\n if (violation) {\n return {\n job,\n success: false,\n error: violation,\n duration: Date.now() - startTime,\n };\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 // A deletion refuses the operations that sort after it and leaves the\n // earlier ones alone.\n let deniedReasons: Array<string | undefined> | undefined;\n if (this.featureFlags.documentDecisions) {\n try {\n deniedReasons = await evaluateByPosition(\n this.decisionModel,\n { documentId: job.documentId, branch: job.branch },\n { scope, operations: reshuffledOperations },\n stores,\n signal,\n );\n } catch (error) {\n return {\n job,\n success: false,\n error: error instanceof Error ? error : new Error(String(error)),\n duration: Date.now() - startTime,\n };\n }\n }\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 reshuffledOperations.map((operation, i) => ({\n action: operation.action,\n skip: operation.skip,\n sourceOperation: operation,\n sourceRemote: effectiveSourceRemote,\n deniedReason: deniedReasons?.[i],\n })),\n executing,\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 const reevaluationError = await this.reevaluateIfCriteriaMet(\n { scope, operations: result.generatedOperations },\n executing,\n );\n if (reevaluationError) {\n return {\n job,\n success: false,\n error: reevaluationError,\n duration: Date.now() - startTime,\n };\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 { 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 deniedReason: op.deniedReason || 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 AppendConditionFailedError,\n DuplicateOperationError,\n RevisionMismatchError,\n type AppendCondition,\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 condition?: AppendCondition,\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 condition,\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 condition,\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 condition?: AppendCondition,\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 if (condition) {\n await this.acquireStreamLocks(trx, documentId, scope, branch, condition);\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 let insertedCount = operations.length;\n try {\n if (condition && condition.streams.length > 0) {\n insertedCount = await this.insertGuarded(trx, operations, condition);\n } else {\n await trx.insertInto(\"Operation\").values(operations).execute();\n }\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 if (insertedCount !== operations.length) {\n throw new AppendConditionFailedError(condition!);\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 deniedReason: op.deniedReason || undefined,\n id: op.opId,\n action: JSON.parse(op.action as string) as Operation[\"action\"],\n }));\n }\n\n /**\n * Locks the written stream and every read-set stream, in sorted key order\n * so that overlapping concurrent appends serialize rather than deadlock.\n * The locks are still taken one row at a time, so the query preserves that\n * order. It must stay separate from the guarded insert, which would\n * otherwise read a snapshot taken before the locks were held.\n */\n private async acquireStreamLocks(\n trx: Transaction<Database>,\n documentId: string,\n scope: string,\n branch: string,\n condition: AppendCondition,\n ): Promise<void> {\n const keys = new Set<string>([`${documentId}:${scope}:${branch}`]);\n for (const stream of condition.streams) {\n keys.add(`${stream.documentId}:${stream.scope}:${stream.branch}`);\n }\n\n const sortedKeys = sql.join([...keys].sort());\n\n await sql`\n with ordered as materialized (\n select key\n from unnest(array[${sortedKeys}]::text[]) with ordinality as t(key, ord)\n order by ord\n )\n select pg_advisory_xact_lock(hashtext(key)) from ordered\n `.execute(trx);\n }\n\n /**\n * Inserts the staged operations with the condition compiled in as a WHERE\n * NOT EXISTS guard, making the check and the append one statement. Returns\n * the rows inserted; zero means the guard failed and nothing was written.\n */\n private async insertGuarded(\n trx: Transaction<Database>,\n operations: InsertableOperation[],\n condition: AppendCondition,\n ): Promise<number> {\n const branches = operations.map((op) =>\n trx\n .selectNoFrom([\n sql<string>`${op.jobId}::text`.as(\"jobId\"),\n sql<string>`${op.opId}::text`.as(\"opId\"),\n sql<string>`${op.prevOpId}::text`.as(\"prevOpId\"),\n sql<string>`${op.documentId}::text`.as(\"documentId\"),\n sql<string>`${op.documentType}::text`.as(\"documentType\"),\n sql<string>`${op.scope}::text`.as(\"scope\"),\n sql<string>`${op.branch}::text`.as(\"branch\"),\n sql<Date>`${op.timestampUtcMs}::timestamptz`.as(\"timestampUtcMs\"),\n sql<number>`${op.index}::integer`.as(\"index\"),\n sql<unknown>`${op.action}::jsonb`.as(\"action\"),\n sql<number>`${op.skip}::integer`.as(\"skip\"),\n sql<string | null>`${op.error ?? null}::text`.as(\"error\"),\n sql<string | null>`${op.deniedReason ?? null}::text`.as(\n \"deniedReason\",\n ),\n sql<string>`${op.hash}::text`.as(\"hash\"),\n ])\n .where((eb) =>\n eb.not(\n eb.exists(\n eb\n .selectFrom(\"Operation\")\n .select(\"Operation.id\")\n .where((web) =>\n web.or(\n condition.streams.map((s) =>\n web.and([\n web(\"Operation.documentId\", \"=\", s.documentId),\n web(\"Operation.scope\", \"=\", s.scope),\n web(\"Operation.branch\", \"=\", s.branch),\n web(\"Operation.index\", \">\", s.revision),\n ]),\n ),\n ),\n ),\n ),\n ),\n ),\n );\n\n let expression = branches[0];\n for (let i = 1; i < branches.length; i++) {\n expression = expression.unionAll(branches[i]);\n }\n\n const inserted = await trx\n .insertInto(\"Operation\")\n .columns([\n \"jobId\",\n \"opId\",\n \"prevOpId\",\n \"documentId\",\n \"documentType\",\n \"scope\",\n \"branch\",\n \"timestampUtcMs\",\n \"index\",\n \"action\",\n \"skip\",\n \"error\",\n \"deniedReason\",\n \"hash\",\n ])\n .expression(expression)\n .returning(\"id\")\n .execute();\n\n return inserted.length;\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 // Asked separately because the largest timestamp is not always on the\n // last-indexed operation: a reshuffle can leave a later one behind it.\n const latest = await this.queryExecutor\n .selectFrom(\"Operation\")\n .select((eb) => eb.fn.max(\"timestampUtcMs\").as(\"latestTimestamp\"))\n .where(\"documentId\", \"=\", documentId)\n .where(\"branch\", \"=\", branch)\n .executeTakeFirst();\n\n const revision: Record<string, number> = {};\n for (const row of scopeRevisions) {\n revision[row.scope] = row.index + 1;\n }\n\n return {\n revision,\n latestTimestamp: latest?.latestTimestamp\n ? new Date(latest.latestTimestamp).toISOString()\n : new Date(0).toISOString(),\n };\n }\n\n async getStreamLatestTimestamp(\n documentId: string,\n scope: string,\n branch: string,\n signal?: AbortSignal,\n ): Promise<string | undefined> {\n const latest = await this.queryExecutor\n .selectFrom(\"Operation\")\n .select((eb) => eb.fn.max(\"timestampUtcMs\").as(\"latestTimestamp\"))\n .where(\"documentId\", \"=\", documentId)\n .where(\"scope\", \"=\", scope)\n .where(\"branch\", \"=\", branch)\n .executeTakeFirst();\n\n return latest?.latestTimestamp\n ? new Date(latest.latestTimestamp).toISOString()\n : undefined;\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 deniedReason: row.deniedReason || 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 type { Kysely } from \"kysely\";\n\n/**\n * Records why authorization refused an operation. Separate from `error` so a\n * denial is distinguishable from a reducer failure without matching on a\n * message. Null for every operation written before decisions were enforced.\n */\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .alterTable(\"Operation\")\n .addColumn(\"deniedReason\", \"text\")\n .execute();\n\n // Sync reads operations from the index rather than the operation table, so\n // the reason has to be here as well or a denial does not reach a replica.\n await db.schema\n .alterTable(\"operation_index_operations\")\n .addColumn(\"deniedReason\", \"text\")\n .execute();\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n await db.schema\n .alterTable(\"operation_index_operations\")\n .dropColumn(\"deniedReason\")\n .execute();\n await db.schema.alterTable(\"Operation\").dropColumn(\"deniedReason\").execute();\n}\n","import type { Kysely } from \"kysely\";\n\n/**\n * The classification a dead letter falls into, stored because it decides whether\n * the document stays quarantined and the in-memory error is gone after a restart.\n * Defaulted rather than nullable, so a pre-existing row rehydrates.\n */\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .alterTable(\"sync_dead_letters\")\n .addColumn(\"error_type\", \"text\", (col) =>\n col.notNull().defaultTo(\"UNCLASSIFIED\"),\n )\n .execute();\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n await db.schema\n .alterTable(\"sync_dead_letters\")\n .dropColumn(\"error_type\")\n .execute();\n}\n","import type { Kysely } from \"kysely\";\n\n/**\n * One row per (document, group) reference ever discovered from an auth\n * operation's input. Rows are never updated or deleted: auth evaluation is\n * positional, so a grant that named a group at any position keeps that\n * group's stream in the document's read-set even after a later operation\n * removes the reference. Read by documentId for the groups a document\n * requires (sync), and by groupId for the documents a group change affects\n * (re-evaluation).\n */\nexport async function up(db: Kysely<any>): Promise<void> {\n await db.schema\n .createTable(\"group_references\")\n .addColumn(\"documentId\", \"text\", (col) => col.notNull())\n .addColumn(\"groupId\", \"text\", (col) => col.notNull())\n .addPrimaryKeyConstraint(\"group_references_pkey\", [\"documentId\", \"groupId\"])\n .execute();\n\n await db.schema\n .createIndex(\"idx_group_references_groupId\")\n .on(\"group_references\")\n .column(\"groupId\")\n .execute();\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n await db.schema.dropTable(\"group_references\").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\";\nimport * as migration015 from \"./015_add_operation_denied_reason.js\";\nimport * as migration016 from \"./016_add_dead_letter_error_type.js\";\nimport * as migration017 from \"./017_create_group_references.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 \"015_add_operation_denied_reason\": migration015,\n \"016_add_dead_letter_error_type\": migration016,\n \"017_create_group_references\": migration017,\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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"}