@powerhousedao/reactor 6.2.3-dev.50 → 6.2.3-dev.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{document-indexer-DwAMDVRI.js → document-indexer-3fkVWCaN.js} +26 -14
- package/dist/document-indexer-3fkVWCaN.js.map +1 -0
- package/dist/{drive-container-types-Ci1pdv4X.js → drive-container-types-BAfFzBOf.js} +133 -7
- package/dist/drive-container-types-BAfFzBOf.js.map +1 -0
- package/dist/entry.js +2 -2
- package/dist/{forwarding-logger-ByfBFgMS.js → forwarding-logger-B9LLXItm.js} +111 -79
- package/dist/forwarding-logger-B9LLXItm.js.map +1 -0
- package/dist/{index-CNhT69De.d.ts → index-dDm0fUBT.d.ts} +518 -68
- package/dist/index-dDm0fUBT.d.ts.map +1 -0
- package/dist/index.d.ts +1040 -138
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3110 -776
- package/dist/index.js.map +1 -1
- package/dist/projection-entry.js +2 -2
- package/dist/{projection-shard-manager-CQ5FwQmv.js → projection-shard-manager-Drl9w8Eo.js} +3 -13
- package/dist/projection-shard-manager-Drl9w8Eo.js.map +1 -0
- package/dist/rpc.d.ts +32 -6
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +8 -4
- package/dist/rpc.js.map +1 -1
- package/dist/{worker-handle-CN2-oRv-.js → worker-handle-Nso8i5eU.js} +2 -2
- package/dist/{worker-handle-CN2-oRv-.js.map → worker-handle-Nso8i5eU.js.map} +1 -1
- package/dist/worker-pool-router-BROOEQSE.js +35 -0
- package/dist/worker-pool-router-BROOEQSE.js.map +1 -0
- package/package.json +3 -3
- package/dist/document-indexer-DwAMDVRI.js.map +0 -1
- package/dist/drive-container-types-Ci1pdv4X.js.map +0 -1
- package/dist/forwarding-logger-ByfBFgMS.js.map +0 -1
- package/dist/index-CNhT69De.d.ts.map +0 -1
- package/dist/projection-shard-manager-CQ5FwQmv.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive-container-types-BAfFzBOf.js","names":["applyUpgradeDocumentAction"],"sources":["../src/shared/types.ts","../src/cache/operation-index-types.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/executor/types.ts","../src/core/feature-flags.ts","../src/storage/kysely/document-purger.ts","../src/executor/execution-scope.ts","../src/storage/storage-flush.ts","../src/utils/reshuffle.ts","../src/decision/merged-order.ts","../src/decision/walk.ts","../src/decision/evaluation.ts","../src/executor/document-action-handler.ts","../src/signer/passthrough-signer.ts","../src/signer/trust-policy.ts","../src/signer/did-key.ts","../src/signer/verify-action-signature.ts","../src/executor/synthesized-signing.ts","../src/executor/signature-admission.ts","../src/executor/simple-job-executor.ts","../src/core/drive-container-types.ts"],"sourcesContent":["import type {\n AuthSubject,\n OperationOutcome,\n} from \"@powerhousedao/shared/document-model\";\n\n/**\n * The document ID used for system operations (CREATE_DOCUMENT, DELETE_DOCUMENT, etc.)\n * System operations use this special ID along with the \"system\" scope.\n */\nexport const SYSTEM_DOCUMENT_ID = \"00000000-0000-0000-0000-000000000000\";\n\n/**\n * Information about an error including its name, message and stack trace.\n *\n * The name is what survives the crossing out of the executor: a consumer that\n * has to tell a terminal failure from a retryable one, or classify a dead\n * letter, only ever sees this record rather than the thrown error.\n */\nexport type ErrorInfo = {\n name: string;\n message: string;\n stack: string;\n /** The document the error names, when it carries one. */\n documentId?: string;\n /**\n * The error instance this record was derived from, when the failer had\n * one. Carried in memory so queue.failJob can emit a JOB_FAILED whose\n * error is the typed instance; absent on records built from strings and\n * on anything that crossed a serialization boundary.\n */\n source?: Error;\n};\n\n/**\n * Describes the status of a shutdown operation.\n */\nexport type ShutdownStatus = {\n /**\n * True if and only if the system has been shutdown.\n *\n * This value is meant to be polled to determine if the system has been shutdown.\n *\n * In the case of a browser process, the `kill` method should be able to synchronously set this to true.\n *\n * In the case of a server process, a graceful shutdown period should be allowed for the system to finish its work.\n */\n get isShutdown(): boolean;\n\n /**\n * A promise that resolves when the shutdown process is complete.\n *\n * For server environments, await this promise to ensure all active jobs finish\n * before exiting the process.\n */\n completed: Promise<void>;\n};\n\n/**\n * Enum that determines deletion propagation.\n */\nexport enum PropagationMode {\n None = \"none\",\n Cascade = \"cascade\",\n}\n\n/**\n * Enum that describes the type of relationship change.\n */\nexport enum RelationshipChangeType {\n Added = \"added\",\n Removed = \"removed\",\n}\n\n/**\n * Batch-specific metadata always present on every job.\n * Single jobs get a unique batchId and batchJobIds of [jobId].\n */\nexport type BatchMeta = {\n batchId: string;\n batchJobIds: string[];\n};\n\n/**\n * Metadata that flows through the job lifecycle.\n * Always includes batch fields; callers may add additional properties.\n */\nexport type JobMeta = BatchMeta & Record<string, unknown>;\n\nimport type { Job } from \"../queue/types.js\";\n\n/**\n * Marks a load whose operations a sync cursor keeps re-pullable, so its\n * write-ready needs no flush. A symbol, not exported from the package: it\n * cannot be set by an outside caller or survive any serialization boundary.\n */\nconst CURSOR_PROTECTED = Symbol(\"cursorProtected\");\n\n/** Load meta for the sync manager's inbox, the only owner of the cursor. */\nexport function cursorProtectedLoadMeta(\n sourceRemote: string,\n): Record<string, unknown> {\n return { sourceRemote, [CURSOR_PROTECTED]: true };\n}\n\nexport function isCursorProtectedLoad(job: Job): boolean {\n const meta = job.meta as { [CURSOR_PROTECTED]?: unknown };\n return job.kind === \"load\" && meta[CURSOR_PROTECTED] === true;\n}\n\n/**\n * What became of one action the caller submitted, at the position the\n * operation carrying it was written to.\n */\nexport type SubmittedActionResult = {\n actionId: string;\n scope: string;\n\n /** The index the operation occupies in its scope. */\n index: number;\n} & OperationOutcome;\n\n/**\n * The outcome of every action a job was given.\n *\n * A reducer error or a denial does not fail the job: the operation is still\n * written at its index, the rest of the batch still applies, and the job still\n * reaches READ_READY. This is the only place a caller can see that one of its\n * actions was rejected.\n */\nexport type JobResultSummary = {\n /** One entry per submitted action that produced an operation, in write order. */\n actions: SubmittedActionResult[];\n\n /** False when any submitted action hit a reducer error or was denied. */\n allApplied: boolean;\n};\n\n/**\n * Describes the current state of a job.\n */\nexport type JobInfo = {\n id: string;\n\n /** The document this job operates on; empty string when the job is unknown. */\n documentId: string;\n status: JobStatus;\n createdAtUtcIso: string;\n completedAtUtcIso?: string;\n error?: ErrorInfo;\n errorHistory?: ErrorInfo[];\n\n /**\n * What the job produced for its caller, from the moment its operations are\n * durable. Undefined until then, and on jobs that carry no submitted\n * actions.\n */\n result?: JobResultSummary;\n\n /**\n * A token for coordinating reads, only valid once a job reaches COMPLETED.\n */\n consistencyToken: ConsistencyToken;\n\n /**\n * Metadata that flows through the job lifecycle.\n */\n meta: JobMeta;\n\n /**\n * The full job object, populated on failure for debugging purposes.\n */\n job?: Job;\n};\n\n/**\n * Job execution statuses\n */\nexport enum JobStatus {\n /** Job is queued but not yet started */\n PENDING = \"PENDING\",\n /** Job is currently being executed */\n RUNNING = \"RUNNING\",\n /** Operations have been written to the operation store (JOB_WRITE_READY event) */\n WRITE_READY = \"WRITE_READY\",\n /** Read models have finished indexing operations (JOB_READ_READY event) */\n READ_READY = \"READ_READY\",\n /** Job failed (may be retried) */\n FAILED = \"FAILED\",\n}\n\n/**\n * Describe the view of a set of documents. That is, what pieces of the\n * documents are populated.\n */\nexport type ViewFilter = {\n branch?: string;\n scopes?: string[];\n revision?: number;\n /**\n * Read subject for the IReactorClient read gate; defaults to the client's\n * signer. Set per request when serving many principals. Ignored by IReactor.\n */\n subject?: AuthSubject;\n};\n\n/**\n * Describes filter options for searching documents.\n *\n * Each parameter is treated as an AND condition.\n */\nexport type SearchFilter = {\n type?: string;\n parentId?: string;\n ids?: string[];\n slugs?: string[];\n};\n\n/**\n * Describes the options for paging.\n */\nexport type PagingOptions = {\n cursor: string;\n limit: number;\n};\n\n/**\n * The paged result.\n */\nexport type PagedResults<T> = {\n results: T[];\n options: PagingOptions;\n\n next?: () => Promise<PagedResults<T>>;\n nextCursor?: string;\n};\n\n/**\n * A string key in the format `documentId:scope:branch` used to identify a consistency checkpoint.\n */\nexport type ConsistencyKey = `${string}:${string}:${string}`;\n\n/**\n * Describes a specific point in a document's operation history.\n */\nexport type ConsistencyCoordinate = {\n documentId: string;\n scope: string;\n branch: string;\n operationIndex: number;\n};\n\n/**\n * A token that captures the state of write operations at a point in time.\n * Can be used to ensure read-after-write consistency.\n */\nexport type ConsistencyToken = {\n version: 1;\n createdAtUtcIso: string;\n coordinates: ConsistencyCoordinate[];\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\";\nimport type { DocumentStreamKey } from \"./write-cache-types.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 * The documents whose collection membership the commit actually changed,\n * available once it has run.\n *\n * A caller cannot work this out from what it recorded: joining a collection\n * also joins every group the joining document has ever referenced, and that\n * set is discovered by the commit itself. Anything caching membership has to\n * be told about those documents too, or it keeps serving what it read before\n * the commit.\n */\n getMembershipInvalidations(): string[];\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 /** Collections with a member with a row in (after, through], within `among`. */\n getCollectionsInRange(\n after: number,\n through: number,\n among?: readonly string[],\n signal?: AbortSignal,\n ): Promise<string[]>;\n /** Ordinals in (after, through], ascending, at most `limit`. */\n getOrdinalsInRange(\n after: number,\n through: number,\n limit: number,\n signal?: AbortSignal,\n ): Promise<number[]>;\n /** Rows for these ordinals, ascending; a missing row is left out. */\n getByOrdinals(\n ordinals: readonly number[],\n signal?: AbortSignal,\n ): Promise<OperationWithContext[]>;\n /** A stream's rows above an ordinal, ascending, at most `limit` if given. */\n getStreamAfter(\n stream: DocumentStreamKey,\n after: number,\n signal?: AbortSignal,\n limit?: number,\n ): Promise<OperationWithContext[]>;\n /** The latest ordinal of each of `opIds` indexed in one stream. */\n getOrdinalsByOpIds(\n documentId: string,\n scope: string,\n branch: string,\n opIds: string[],\n signal?: AbortSignal,\n ): Promise<Map<string, number>>;\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 * That asymmetry is a real constraint, not a convention: a drive id\n * containing a dot does NOT survive `key` -> `fromKey`, because the split\n * takes the LAST dot and so hands the tail of the drive id back as the drive\n * id and everything before it as the branch. The key format is the wire and\n * storage representation of existing `document_collections` rows, so it\n * cannot be changed; callers that accept a drive id or branch from outside\n * (a UI field, an RPC payload) must reject dots in the drive id at their own\n * boundary. The round-trip is verifiable without parsing rules:\n * `DriveCollectionId.fromKey(id.key).key === id.key`.\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 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 const derived: Array<[string, StreamQuery[]]> = [];\n for (const [key, projection] of projections) {\n if (typeof projection.query !== \"function\") {\n continue;\n }\n derived.push([key, projection.query(staticModel)]);\n }\n if (derived.length > 0 && reader.fence) {\n await reader.fence(\n derived.flatMap(([, queries]) => queries.map((q) => q.documentId)),\n );\n }\n\n for (const [key, queries] of derived) {\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 PHDocument,\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 *\n * `carriedDocument` is that state already in hand, for a write that follows\n * another in the same run. The head read would answer with the state as it\n * stood before the run, which is not what the write is appended after.\n */\nexport type AdmissionConditions = {\n actionInput?: unknown;\n carriedDocument?: PHDocument;\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, or taken from the run's carried document when the\n * caller has already reduced earlier writes into it. That read carries no\n * append-condition entry of its own: the written stream's expected-revision\n * check already refuses a write whose scope grew between the read and the\n * 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 =\n conditions.carriedDocument ??\n (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","import type {\n Action,\n OperationWithContext,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Operation } from \"@powerhousedao/shared/document-model\";\nimport type { Job } from \"../queue/types.js\";\nimport type { IOperationIndexTxn } from \"../cache/operation-index-types.js\";\nimport type { ExecutionStores } from \"./execution-scope.js\";\nimport type { SignatureVerificationMode } from \"../signer/types.js\";\nimport type { PurgeFence, TouchedStreams } from \"./util.js\";\n\n/**\n * One action to write, and everything known about it before it is written.\n */\nexport type PendingWrite = {\n action: Action;\n\n /** How many preceding operations this one supersedes. */\n skip: number;\n\n /** The operation being replayed, when this write came from a load. */\n sourceOperation?: Operation;\n\n /** The remote the write arrived from, or empty for a local write. */\n sourceRemote: string;\n\n /** Why the write was refused, when the evaluation is already decided. */\n deniedReason?: string;\n};\n\n/**\n * A stream a job wrote to, or whose cached state a job's uncommitted writes\n * could have filled.\n */\nexport type TouchedStream = {\n documentId: string;\n scope: string;\n branch: string;\n};\n\n/**\n * The job in flight, and what a write is committed through.\n */\nexport type ExecutingJob = {\n job: Job;\n startTime: number;\n indexTxn: IOperationIndexTxn;\n stores: ExecutionStores;\n signal?: AbortSignal;\n\n /**\n * Whether these writes were accepted at their own positions already, which a\n * load and a re-evaluation pass both are. Admission does not decide again,\n * because re-deciding accepted history would drop operations.\n */\n replayingAcceptedHistory: boolean;\n\n /**\n * Whether every write already carries the verdict computed at its own position.\n * Deciding again at the stream heads would overwrite a verdict the rest of the\n * fleet computes differently.\n */\n evaluatedByPosition: boolean;\n\n /**\n * Cache entries to invalidate only after the execution transaction commits.\n * An UPGRADE_DOCUMENT reshapes sibling scopes it writes no operation to;\n * invalidating them mid-transaction lets a concurrent read repopulate the\n * cache with pre-upgrade state that then survives the commit.\n */\n postCommitInvalidations: TouchedStream[];\n\n /** Documents whose membership a concurrent reader may have refilled stale. */\n postCommitMembershipInvalidations: string[];\n\n /**\n * Streams this job wrote, to the store or to a cache. The caches are shared\n * by reference with the copies scoped to the execution transaction, so a job\n * whose transaction rolls back has to evict them itself: the writes it made\n * survive the rollback, and so does anything a read filled from the store\n * while the job's own writes were still uncommitted.\n */\n touchedStreams: TouchedStreams;\n\n /** Tombstones behind the job's shared locks; absent where no lock is held. */\n purgeFence?: PurgeFence;\n};\n\nexport type PositionedWrites = {\n writes: PendingWrite[];\n evaluatedByPosition: boolean;\n /** Set when a submitted action was refused at its position. */\n error?: Error;\n};\n\n/**\n * Represents the result of a job execution\n */\nexport type JobResult = {\n /** The job that was executed */\n job: Job;\n\n /** Whether the job executed successfully */\n success: boolean;\n\n /** Error if the job failed */\n error?: Error;\n\n /** The operations generated from the actions (if successful) */\n operations?: Operation[];\n\n /**\n * Operations with context (includes ephemeral resultingState).\n * Used for emitting to IDocumentView via event bus.\n */\n operationsWithContext?: OperationWithContext[];\n\n /** Timestamp when the job execution completed */\n completedAt?: string;\n\n /** Duration of job execution in milliseconds */\n duration?: number;\n\n /** Any additional metadata from the execution */\n metadata?: Record<string, any>;\n};\n\n/**\n * Enforcement the reactor performs, each off by default.\n *\n * An evaluation made while replaying is part of the document's history, so two\n * reactors that share documents and disagree on these diverge. A flag is turned\n * on for a set of reactors that sync with each other, not for one node.\n */\nexport type ReactorFeatureFlags = {\n /**\n * Decide whether an operation may be admitted by building a decision model\n * over the document stream, rather than reading the deleted flag from the\n * document meta cache. Deletion then takes effect from the deleting\n * operation's position rather than for the whole document.\n */\n documentDecisions: boolean;\n\n /**\n * Evaluate the auth policy by reading the auth scope as a second projection.\n * Requires documentDecisions.\n */\n authEnforcement: boolean;\n\n /**\n * Match { group } principals by folding the referenced PHGroup documents as\n * derived projections. Requires authEnforcement.\n */\n authGroups: boolean;\n\n /**\n * Evaluate `where` clauses and { match } principals against the executing\n * scope's state, the subject, and the action input. Requires authGroups.\n */\n authConditions: boolean;\n};\n\n/** 200k operations purge in 1.6 s on local Postgres; jobs time out at 30 s. */\nexport const DEFAULT_MAX_PURGE_OPERATIONS = 200_000;\n\n/** How long a deferred job waits for its document before it fails. */\nexport const DEFAULT_DEFERRED_JOB_TTL_MS = 30_000;\n\nexport const DEFAULT_JOB_TIMEOUT_MS = 30_000;\n\n/**\n * Configuration options for the job executor\n */\nexport type JobExecutorConfig = {\n /** Feature flags; anything unset is off. */\n featureFlags?: Partial<ReactorFeatureFlags>;\n\n /** Maximum number of conflicting operations to skip when reshuffling. */\n maxSkipThreshold?: number;\n\n /** Maximum number of concurrent jobs to execute */\n maxConcurrency?: number;\n\n /** Maximum time in milliseconds a job can run before being considered timed out */\n jobTimeoutMs?: number;\n\n /** How long a job whose document is missing waits for it before failing.\n * Unbounded deferral never resolves the caller awaiting the job. */\n deferredJobTtlMs?: number;\n\n /** Base delay in milliseconds for exponential backoff retries */\n retryBaseDelayMs?: number;\n\n /** Maximum delay in milliseconds for exponential backoff retries */\n retryMaxDelayMs?: number;\n\n /** Maximum elapsed milliseconds before yielding to the main thread between actions.\n * Keeps the UI responsive when processing large batches. */\n yieldDeadlineMs?: number;\n\n /**\n * Persist a job's writes in one store transaction rather than one each.\n *\n * On by default. A job's operations are reduced sequentially either way; this\n * only changes how many apply calls carry them, which is one advisory lock\n * and one guarded insert per batch instead of per operation. Only runs that\n * qualify are batched, and the executor falls back per write for the rest, so\n * this never changes which operations are produced -- only how many\n * transactions they arrive in.\n *\n * Atomicity is not one of the things it changes. A job either fully applies\n * or leaves nothing durable behind regardless of this setting, because the\n * whole job runs inside the execution scope's transaction and a failure\n * rolls it back.\n * That guarantee belongs to KyselyExecutionScope, which backs both Postgres\n * and PGlite; DefaultExecutionScope opens no transaction and is used only by\n * unit-test harnesses, which therefore see writes survive a failed job.\n */\n batchApplies?: boolean;\n\n /** Defaults to `enforce`; `log` counts refusals and admits the write. */\n signatureVerification?: SignatureVerificationMode;\n\n /** Versions run per registered protocol; defaults to the registry's. */\n protocolSupport?: ProtocolSupport;\n\n /** Index rows a purge may remove without allowLarge. */\n maxPurgeOperations?: number;\n\n /**\n * How long a committed job waits for its flush before its write-ready is\n * withheld; 0 or less waits unbounded. withGroupCommitPGlite refuses that and\n * any non-finite value. Must stay under the job timeout.\n */\n durabilityWaitMs?: number;\n};\n\n/** Cloneable, so a pooled worker refuses exactly what the host refuses. */\nexport type ProtocolSupport = { [protocol: string]: readonly number[] };\n\n/**\n * Event types for the job executor\n */\nexport const JobExecutorEventTypes = {\n JOB_STARTED: 20000,\n JOB_COMPLETED: 20001,\n JOB_FAILED: 20002,\n EXECUTOR_STARTED: 20003,\n EXECUTOR_STOPPED: 20004,\n} as const;\n\n/**\n * Event data for job execution events\n */\nexport type JobStartedEvent = {\n job: Job;\n startedAt: string;\n /**\n * Identifier of the executor that took the job. For the worker pool this is\n * the thread-worker id (e.g. \"reactor-worker-3\"); for the in-process simple\n * manager it is \"in-process-<index>\". Optional for backwards compatibility\n * with consumers built before the field was added.\n */\n workerId?: string;\n};\n\nexport type JobCompletedEvent = {\n job: Job;\n result: JobResult;\n /** See {@link JobStartedEvent.workerId}. */\n workerId?: string;\n};\n\nexport type JobFailedEvent = {\n job: Job;\n error: string;\n willRetry: boolean;\n retryCount: number;\n /** See {@link JobStartedEvent.workerId}. */\n workerId?: string;\n};\n\nexport type ExecutorStartedEvent = {\n config: JobExecutorConfig;\n startedAt: string;\n};\n\nexport type ExecutorStoppedEvent = {\n stoppedAt: string;\n graceful: boolean;\n};\n\n/**\n * Status information for the job executor manager\n */\nexport type ExecutorManagerStatus = {\n /** Whether the manager is currently running */\n isRunning: boolean;\n\n /** Number of executor instances managed */\n numExecutors: number;\n\n /** Number of jobs currently being processed */\n activeJobs: number;\n\n /** Total number of jobs processed since start */\n totalJobsProcessed: number;\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 {\n garbageCollect,\n mentionedGroupIds,\n sortOperations,\n type Operation,\n} from \"@powerhousedao/shared/document-model\";\nimport { sql, type Kysely, type Transaction } from \"kysely\";\nimport type { DocumentViewDatabase } from \"../../read-models/types.js\";\nimport { findPurged } from \"./document-purges.js\";\nimport type {\n Database,\n DocumentRelationshipTable,\n DocumentTable,\n OperationRow,\n PurgeRemovedRows,\n} from \"./types.js\";\n\n/** An `Operation` row whose DELETE_DOCUMENT applied: not errored, not denied. */\nexport const appliedDelete = sql<boolean>`action->>'type' = 'DELETE_DOCUMENT' and coalesce(error, '') = '' and coalesce(\"deniedReason\", '') = ''`;\n\n/** Rows removed per statement from the tables a document can fill. */\nexport const DEFAULT_PURGE_DELETE_BATCH = 5_000;\n\ntype PurgeDatabase = Database &\n DocumentViewDatabase & {\n Document: DocumentTable;\n DocumentRelationship: DocumentRelationshipTable;\n };\n\nexport type PurgeStream = { scope: string; branch: string };\n\n/** A document of a drive's collection, and whether the drive's purge needs it gone. */\nexport type CollectionMember = {\n documentId: string;\n openElsewhere: boolean;\n /** Not open elsewhere, and still open here or deleted; a live former member lives on. */\n required: boolean;\n};\n\n/** A purge transaction's statements; bound to the job's transaction. */\nexport class KyselyDocumentPurger {\n private readonly db: Kysely<PurgeDatabase>;\n\n constructor(\n db: Kysely<Database> | Transaction<Database>,\n private readonly batchSize = DEFAULT_PURGE_DELETE_BATCH,\n ) {\n this.db = db as unknown as Kysely<PurgeDatabase>;\n }\n\n /** Every stream the document holds operations in. */\n async streams(documentId: string): Promise<PurgeStream[]> {\n return this.db\n .selectFrom(\"Operation\")\n .select([\"scope\", \"branch\"])\n .distinct()\n .where(\"documentId\", \"=\", documentId)\n .orderBy(\"scope\")\n .orderBy(\"branch\")\n .execute();\n }\n\n async operationCount(documentId: string): Promise<number> {\n const row = await this.db\n .selectFrom(\"operation_index_operations\")\n .select((eb) => eb.fn.countAll<string | number>().as(\"count\"))\n .where(\"documentId\", \"=\", documentId)\n .executeTakeFirst();\n return Number(row?.count ?? 0);\n }\n\n /** Untombstoned documents group_references records as naming the group. */\n async groupReferencers(groupId: string): Promise<string[]> {\n const rows = await this.db\n .selectFrom(\"group_references\")\n .select(\"documentId\")\n .where(\"groupId\", \"=\", groupId)\n .where(\"documentId\", \"<>\", groupId)\n .orderBy(\"documentId\")\n .execute();\n const ids = rows.map((row) => row.documentId);\n const purged = await findPurged(this.db, ids);\n return ids.filter((id) => !purged.has(id));\n }\n\n /** Survivors whose accepted auth history names the group; refusals do not. */\n async groupReferencersInHistory(groupId: string): Promise<string[]> {\n const referencing: string[] = [];\n for (const documentId of await this.groupReferencers(groupId)) {\n const byBranch = await this.authOperations(documentId);\n const names = [...byBranch.values()].some((operations) =>\n garbageCollect(sortOperations(operations)).some(\n (operation) =>\n operation.deniedReason === undefined &&\n operation.error === undefined &&\n mentionedGroupIds(operation.action).includes(groupId),\n ),\n );\n if (names) referencing.push(documentId);\n }\n return referencing;\n }\n\n /** The document's auth-scope operations, per branch, in index order. */\n async authOperations(documentId: string): Promise<Map<string, Operation[]>> {\n const rows = await this.db\n .selectFrom(\"Operation\")\n .selectAll()\n .where(\"documentId\", \"=\", documentId)\n .where(\"scope\", \"=\", \"auth\")\n .orderBy(\"branch\")\n .orderBy(\"index\")\n .execute();\n const byBranch = new Map<string, Operation[]>();\n for (const row of rows as OperationRow[]) {\n const operations = byBranch.get(row.branch) ?? [];\n operations.push({\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 byBranch.set(row.branch, operations);\n }\n return byBranch;\n }\n\n /** Every document ever in the collection, but its owner and its own row. */\n async collectionMembers(\n collectionId: string,\n ownerId: string,\n branch: string,\n ): Promise<CollectionMember[]> {\n const rows = await this.db\n .selectFrom(\"document_collections as dc\")\n .select(\"dc.documentId\")\n .select(sql<boolean>`dc.\"leftOrdinal\" is null`.as(\"openHere\"))\n .select((eb) =>\n eb\n .exists(\n eb\n .selectFrom(\"Operation as op\")\n .select(\"op.opId\")\n .whereRef(\"op.documentId\", \"=\", \"dc.documentId\")\n .where(\"op.branch\", \"=\", branch)\n .where(\"op.scope\", \"=\", \"document\")\n .where(appliedDelete),\n )\n .as(\"deleted\"),\n )\n .select((eb) =>\n eb\n .exists(\n eb\n .selectFrom(\"document_collections as other\")\n .select(\"other.documentId\")\n .whereRef(\"other.documentId\", \"=\", \"dc.documentId\")\n .where(\"other.collectionId\", \"<>\", collectionId)\n .where(\"other.leftOrdinal\", \"is\", null),\n )\n .as(\"openElsewhere\"),\n )\n .where(\"dc.collectionId\", \"=\", collectionId)\n .where(\"dc.documentId\", \"not in\", [ownerId, collectionId])\n .orderBy(\"dc.documentId\")\n .execute();\n return rows.map((row) => {\n const openElsewhere = Boolean(row.openElsewhere);\n return {\n documentId: row.documentId,\n openElsewhere,\n required:\n !openElsewhere && (Boolean(row.openHere) || Boolean(row.deleted)),\n };\n });\n }\n\n async remoteCollection(remoteName: string): Promise<string | undefined> {\n const row = await this.db\n .selectFrom(\"sync_remotes\")\n .select(\"collection_id\")\n .where(\"name\", \"=\", remoteName)\n .executeTakeFirst();\n return row?.collection_id;\n }\n\n /** Deletes every row about the document; the counts are per table. */\n async deleteRows(documentId: string): Promise<PurgeRemovedRows> {\n const removed: PurgeRemovedRows = {};\n\n removed.Operation = await this.deleteBatched(async () => {\n const result = await this.db\n .deleteFrom(\"Operation\")\n .where(\"id\", \"in\", (eb) =>\n eb\n .selectFrom(\"Operation\")\n .select(\"id\")\n .where(\"documentId\", \"=\", documentId)\n .limit(this.batchSize),\n )\n .executeTakeFirst();\n return Number(result.numDeletedRows);\n });\n\n removed.operation_index_operations = await this.deleteBatched(async () => {\n const result = await this.db\n .deleteFrom(\"operation_index_operations\")\n .where(\"ordinal\", \"in\", (eb) =>\n eb\n .selectFrom(\"operation_index_operations\")\n .select(\"ordinal\")\n .where(\"documentId\", \"=\", documentId)\n .limit(this.batchSize),\n )\n .executeTakeFirst();\n return Number(result.numDeletedRows);\n });\n\n removed.Keyframe = await this.deleteBatched(async () => {\n const result = await this.db\n .deleteFrom(\"Keyframe\")\n .where(\"id\", \"in\", (eb) =>\n eb\n .selectFrom(\"Keyframe\")\n .select(\"id\")\n .where(\"documentId\", \"=\", documentId)\n .limit(this.batchSize),\n )\n .executeTakeFirst();\n return Number(result.numDeletedRows);\n });\n\n removed.DocumentSnapshot = await this.deleteBatched(async () => {\n const result = await this.db\n .deleteFrom(\"DocumentSnapshot\")\n .where(\"id\", \"in\", (eb) =>\n eb\n .selectFrom(\"DocumentSnapshot\")\n .select(\"id\")\n .where(\"documentId\", \"=\", documentId)\n .limit(this.batchSize),\n )\n .executeTakeFirst();\n return Number(result.numDeletedRows);\n });\n\n removed.SlugMapping = await this.deleteWhere(\n \"SlugMapping\",\n \"documentId\",\n documentId,\n );\n\n // Counted first: deleting the Document row cascades both ways (004).\n const relationships = await this.db\n .selectFrom(\"DocumentRelationship\")\n .select((eb) => eb.fn.countAll<string | number>().as(\"count\"))\n .where((eb) =>\n eb.or([\n eb(\"sourceId\", \"=\", documentId),\n eb(\"targetId\", \"=\", documentId),\n ]),\n )\n .executeTakeFirst();\n removed.DocumentRelationship = Number(relationships?.count ?? 0);\n removed.Document = await this.deleteWhere(\"Document\", \"id\", documentId);\n\n // Rows naming the purged id as the group stay: they key survivors.\n removed.group_references = await this.deleteWhere(\n \"group_references\",\n \"documentId\",\n documentId,\n );\n removed.sync_dead_letters = await this.deleteWhere(\n \"sync_dead_letters\",\n \"document_id\",\n documentId,\n );\n removed.sync_holds = await this.deleteWhere(\n \"sync_holds\",\n \"document_id\",\n documentId,\n );\n\n return removed;\n }\n\n async writeTombstone(tombstone: {\n documentId: string;\n ordinal: number;\n removedRows: PurgeRemovedRows;\n purgedAtUtc: Date | string;\n requestId: string;\n }): Promise<void> {\n const values = {\n documentId: tombstone.documentId,\n ordinal: tombstone.ordinal,\n removedRows: JSON.stringify(tombstone.removedRows),\n purgedAtUtc: tombstone.purgedAtUtc,\n requestId: tombstone.requestId,\n };\n await this.db\n .insertInto(\"document_purges\")\n .values(values)\n .onConflict((oc) =>\n oc.column(\"documentId\").doUpdateSet({\n ordinal: values.ordinal,\n removedRows: values.removedRows,\n purgedAtUtc: values.purgedAtUtc,\n requestId: values.requestId,\n }),\n )\n .execute();\n }\n\n /** Reopens every membership at the marker ordinal, plus `collectionIds`. */\n async reopenMemberships(\n documentId: string,\n ordinal: number,\n collectionIds: Iterable<string> = [],\n ): Promise<string[]> {\n await this.db\n .updateTable(\"document_collections\")\n .set({ joinedOrdinal: BigInt(ordinal), leftOrdinal: null })\n .where(\"documentId\", \"=\", documentId)\n .execute();\n for (const collectionId of new Set(collectionIds)) {\n await this.db\n .insertInto(\"document_collections\")\n .values({\n documentId,\n 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 const rows = await this.db\n .selectFrom(\"document_collections\")\n .select(\"collectionId\")\n .where(\"documentId\", \"=\", documentId)\n .orderBy(\"collectionId\")\n .execute();\n return rows.map((row) => row.collectionId);\n }\n\n private async deleteBatched(step: () => Promise<number>): Promise<number> {\n let total = 0;\n for (;;) {\n const deleted = await step();\n total += deleted;\n if (deleted < this.batchSize) {\n return total;\n }\n }\n }\n\n private async deleteWhere(\n table:\n | \"SlugMapping\"\n | \"Document\"\n | \"group_references\"\n | \"sync_dead_letters\"\n | \"sync_holds\",\n column: string,\n documentId: string,\n ): Promise<number> {\n const result = await (this.db as Kysely<any>)\n .deleteFrom(table)\n .where(column, \"=\", documentId)\n .executeTakeFirst();\n return Number(result.numDeletedRows);\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 {\n acquirePurgeLocks,\n findPurged,\n} from \"../storage/kysely/document-purges.js\";\nimport { KyselyDocumentPurger } from \"../storage/kysely/document-purger.js\";\nimport type { Database } from \"../storage/kysely/types.js\";\n\n/** Per-document purge locks, held until the job's transaction ends. */\nexport interface DocumentLocks {\n shared(ids: Iterable<string>): Promise<void>;\n exclusive(id: string): Promise<void>;\n /** The tombstoned ids among `ids`, read in the job's transaction. */\n purged(ids: Iterable<string>): Promise<Set<string>>;\n}\n\n/** For scopes without a transaction to hold a lock in. */\nexport const NOOP_DOCUMENT_LOCKS: DocumentLocks = {\n shared: () => Promise.resolve(),\n exclusive: () => Promise.resolve(),\n purged: () => Promise.resolve(new Set<string>()),\n};\n\nexport interface ExecutionStores {\n operationStore: IOperationStore;\n operationIndex: IOperationIndex;\n writeCache: IWriteCache;\n documentMetaCache: IDocumentMetaCache;\n collectionMembershipCache: ICollectionMembershipCache;\n documentLocks: DocumentLocks;\n /** Absent without a transaction, which a purge cannot run outside of. */\n purger?: KyselyDocumentPurger;\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 documentLocks: NOOP_DOCUMENT_LOCKS,\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 // A shared lock keeps a live id live until commit; its re-checks are moot.\n const sharedLocked = new Set<string>();\n const liveIds = new Set<string>();\n const scopedOperationStore = this.operationStore.withTransaction(\n trx,\n liveIds,\n );\n const scopedOperationIndex = this.operationIndex.withTransaction(\n trx,\n liveIds,\n );\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 documentLocks: {\n shared: async (ids) => {\n const list = [...ids];\n await acquirePurgeLocks(trx, list, \"shared\");\n for (const id of list) sharedLocked.add(id);\n },\n exclusive: (id) => acquirePurgeLocks(trx, [id], \"exclusive\"),\n purged: async (ids) => {\n const list = [...ids];\n const found = await findPurged(trx, list);\n for (const id of list) {\n if (sharedLocked.has(id) && !found.has(id)) liveIds.add(id);\n }\n return found;\n },\n },\n purger: new KyselyDocumentPurger(trx),\n });\n });\n }\n}\n","/**\n * The durability barrier the reactor's two acknowledgment boundaries sit\n * behind, for an embedded store whose statements do not flush themselves.\n *\n * 1. A sync cursor write flushes first, so no cursor row is ever durable\n * ahead of the operations it covers (FlushGuardedSyncCursorStorage).\n * 2. A job's write-ready announcement, which `waitForJob` turns into terminal\n * success, waits for a flush covering the job's commit - except a load a\n * sync cursor protects, whose operations are re-pulled if lost.\n *\n * A store durable per statement uses {@link NoopStorageFlusher}.\n */\nexport interface IStorageFlusher {\n /**\n * Resolves once every write issued before the call is durable. Rejects with\n * {@link StoragePoisonedError} once the store can make nothing durable again.\n */\n flush(): Promise<void>;\n}\n\n/** The store's session is poisoned; only a host restart recovers it. */\nexport class StoragePoisonedError extends Error {\n constructor(message: string, cause?: unknown) {\n super(message, { cause });\n this.name = \"StoragePoisonedError\";\n }\n}\n\nexport class NoopStorageFlusher implements IStorageFlusher {\n flush(): Promise<void> {\n return Promise.resolve();\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 \"PURGE_DOCUMENT\",\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 // Structure actions sort ahead of the rest. This is a per-operation\n // rank, not a property of the pair: deciding a criterion from\n // `a.type || b.type` made the comparator non-transitive, so sorting the\n // same set could yield different orders from different input orders.\n const rank = (op: TOp) =>\n STRICT_ORDER_ACTION_TYPES.has(op.action?.type ?? \"\") ? 0 : 1;\n const rankDiff = rank(a) - rank(b);\n if (rankDiff !== 0) {\n return rankDiff;\n }\n\n // Logical index is a replica-local coordinate, so it can only be used\n // where both sides are certain to agree on the sign: structure actions,\n // whose causal order (create before upgrade, parent before child) has to\n // survive the merge. Everything else orders by keys both replicas\n // compute identically, or the two logs never converge.\n if (rank(a) === 0) {\n const logicalIndexDiff = a.index - a.skip - (b.index - b.skip);\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 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 CreateDocumentAction,\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { createDocumentFromAction } from \"../executor/util.js\";\nimport {\n DocumentNotFoundError,\n DocumentPurgedError,\n} 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 // A self-creating load has no stored stream; deferring it would wait on itself.\n const creation = operations.find(\n (operation) =>\n operation.action.type === \"CREATE_DOCUMENT\" &&\n (operation.action as CreateDocumentAction).input.documentId ===\n target.documentId,\n );\n async function stateBefore(query: StreamQuery): Promise<PHDocument> {\n try {\n return await writeCache.getState(\n query.documentId,\n query.scope,\n query.branch,\n -1,\n signal,\n );\n } catch (error) {\n if (\n creation !== undefined &&\n query.documentId === target.documentId &&\n error instanceof DocumentNotFoundError &&\n !(error instanceof DocumentPurgedError)\n ) {\n return createDocumentFromAction(\n creation.action as CreateDocumentAction,\n );\n }\n throw error;\n }\n }\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 stateBefore(read.stream.query);\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 stateBefore(query);\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 CreateDocumentAction,\n CreateDocumentActionInput,\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 DocumentNotFoundError,\n DocumentPurgedError,\n ReservedActionError,\n UnsupportedProtocolVersionError,\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 ProtocolSupport,\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 relationshipTarget,\n targetDocumentId,\n updateDocumentRevision,\n} from \"./util.js\";\nimport { SnapshotPosition } from \"../cache/write-cache-types.js\";\n\nexport class DocumentActionHandler {\n private readonly loggedUnregisteredProtocols = new Set<string>();\n\n constructor(\n private registry: IDocumentModelRegistry,\n private logger: ILogger,\n private driveContainerTypes: ReadonlySet<string>,\n private featureFlags: ReactorFeatureFlags,\n private decisionModel: RegisteredDecisionModel,\n private protocolSupport: ProtocolSupport,\n ) {}\n\n /** Keys this reactor does not register are admitted: it cannot judge them. */\n unsupportedProtocol(\n documentId: string,\n protocolVersions: { readonly [protocol: string]: number } | undefined,\n ): UnsupportedProtocolVersionError | undefined {\n for (const [protocol, version] of Object.entries(protocolVersions ?? {})) {\n const supported = this.protocolSupport[protocol] as\n | readonly number[]\n | undefined;\n if (supported === undefined) {\n if (!this.loggedUnregisteredProtocols.has(protocol)) {\n this.loggedUnregisteredProtocols.add(protocol);\n this.logger.info(\n \"Admitting document @documentId with unregistered protocol @protocol @version\",\n documentId,\n protocol,\n version,\n );\n }\n continue;\n }\n if (!supported.includes(version)) {\n return new UnsupportedProtocolVersionError(\n documentId,\n protocol,\n version,\n );\n }\n }\n return undefined;\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 case \"PURGE_DOCUMENT\":\n return buildErrorResult(\n executing.job,\n new ReservedActionError(executing.job.documentId, action.type),\n executing.startTime,\n );\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 executing.touchedStreams.add(job.documentId, job.scope, job.branch);\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 protocolVersions: standing.header.protocolVersions,\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 input = action.input as CreateDocumentActionInput;\n const unsupported = this.unsupportedProtocol(\n input.documentId,\n input.protocolVersions,\n );\n if (unsupported) {\n return buildErrorResult(job, unsupported, startTime);\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 // Header last: a state key named \"header\" must not replace it.\n const resultingStateObj: Record<string, unknown> = {\n ...document.state,\n header: document.header,\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 executing.touchedStreams.add(document.header.id, job.scope, job.branch);\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 protocolVersions: document.header.protocolVersions,\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 executing.touchedStreams.add(documentId, job.scope, job.branch);\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 protocolVersions: document.header.protocolVersions,\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 // Header last: a state key named \"header\" must not replace it.\n const resultingStateObj: Record<string, unknown> = {\n ...document.state,\n header: document.header,\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 executing.touchedStreams.add(documentId, job.scope, job.branch);\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 protocolVersions: document.header.protocolVersions,\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 /** A submitted write naming a purged target was refused at job start. */\n private async isTargetPurged(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<boolean> {\n const target = relationshipTarget(write.action);\n if (target === undefined || !executing.purgeFence) {\n return false;\n }\n return executing.purgeFence.isPurged(target);\n }\n\n private async executeAddRelationship(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult> {\n let targetPurged: boolean;\n try {\n targetPurged = await this.isTargetPurged(write, executing);\n } catch (error) {\n return buildErrorResult(\n executing.job,\n error instanceof Error ? error : new Error(String(error)),\n executing.startTime,\n );\n }\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 (\n !targetPurged &&\n this.driveContainerTypes.has(sourceDoc.header.documentType)\n ) {\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 async executeRemoveRelationship(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<RelationshipJobResult> {\n // The purge reopened the target's memberships so they serve its marker.\n let targetPurged: boolean;\n try {\n targetPurged = await this.isTargetPurged(write, executing);\n } catch (error) {\n return buildErrorResult(\n executing.job,\n error instanceof Error ? error : new Error(String(error)),\n executing.startTime,\n );\n }\n return this.withRelationshipAction(\n \"REMOVE_RELATIONSHIP\",\n write,\n executing,\n null,\n ({ indexTxn: txn, stores: s, sourceDoc, input, job: j }) => {\n if (\n !targetPurged &&\n this.driveContainerTypes.has(sourceDoc.header.documentType)\n ) {\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 // Retyped rather than rewrapped in a bare Error, which would strip the\n // name JobResultHandler classifies by and leave a missing source document\n // burning the retry limit on a load that fails the same way every time.\n // The message still names the source, since a relationship tolerates a\n // missing target but not a missing source. A purged source keeps its\n // own error, which is terminal rather than deferred.\n if (DocumentPurgedError.isError(error)) {\n return buildErrorResult(job, error, startTime);\n }\n if (DocumentNotFoundError.isError(error)) {\n return buildErrorResult(\n job,\n new DocumentNotFoundError(\n input.sourceId,\n `${actionTypeName}: source document ${input.sourceId} not found`,\n ),\n startTime,\n );\n }\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 executing.touchedStreams.add(input.sourceId, job.scope, job.branch);\n\n // The target's collection membership is derived from the rows just\n // written. No read inside a job refills it today -- the only one asks for\n // the operation's own document -- so evicting it on rollback is insurance,\n // kept because the eviction is keyed to what the job touched rather than\n // to what one read path currently happens to ask for.\n executing.touchedStreams.add(input.targetId, job.scope, job.branch);\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 protocolVersions: sourceDoc.header.protocolVersions,\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 // Recorded before the apply, not after: the rows an apply that throws left\n // behind are the ones a rollback has to take the cached state of with it.\n executing.touchedStreams.add(documentId, scope, branch);\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 // The wrap that used to carry this phrase is gone, so the phrase lives\n // here: the error keeps its identity, the log keeps the context.\n this.logger.error(\n \"Failed to write operation to IOperationStore (@documentId @scope @branch): @Operation @Error\",\n documentId,\n scope,\n branch,\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 // The original error, not a restringified one: the executor and the\n // job result handler classify by `name`, and a rewrap erases it.\n error:\n error instanceof Error\n ? error\n : new Error(\n `Failed to write operation to IOperationStore: ${String(error)}`,\n ),\n duration: Date.now() - startTime,\n };\n }\n\n return storedOperations;\n }\n}\n","import type { ISigner, Signature } from \"@powerhousedao/shared/document-model\";\n\n/**\n * A no-op signer that returns empty values for all methods.\n * Used when signing is not required.\n */\nexport class PassthroughSigner implements ISigner {\n publicKey = {} as unknown as CryptoKey;\n\n sign(): Promise<Uint8Array> {\n return Promise.resolve(new Uint8Array(0));\n }\n\n verify(): Promise<void> {\n return Promise.resolve();\n }\n\n signAction(): Promise<Signature> {\n return Promise.resolve([\"\", \"\", \"\", \"\", \"\"]);\n }\n}\n","import type {\n ActionSigner,\n ISigner,\n} from \"@powerhousedao/shared/document-model\";\nimport { actionSignerIdentity } from \"@powerhousedao/shared/document-model\";\nimport type { SignatureTrustPolicy } from \"./types.js\";\n\n/**\n * The policy admission asks: the reactor's own key signing as its own user is\n * accepted, then the host's policy decides, else the default does. `own` is\n * read on every ask, since its user changes on login.\n */\nexport function admissionTrustPolicy(\n own: ISigner,\n authEnforcement: boolean,\n policy?: SignatureTrustPolicy,\n): SignatureTrustPolicy {\n return {\n authorizeSigner(signer, key, documentId) {\n const identity = actionSignerIdentity(own);\n if (identity.app.key !== \"\" && key === identity.app.key) {\n if (sameUser(actionSignerIdentity(signer).user, identity.user)) {\n return Promise.resolve(true);\n }\n }\n if (policy) {\n return policy.authorizeSigner(signer, key, documentId);\n }\n return Promise.resolve(!authEnforcement);\n },\n };\n}\n\nfunction sameUser(a: ActionSigner[\"user\"], b: ActionSigner[\"user\"]): boolean {\n return (\n a.address.toLowerCase() === b.address.toLowerCase() &&\n a.networkId === b.networkId &&\n a.chainId === b.chainId\n );\n}\n","import { base58Decode } from \"@powerhousedao/shared/document-model\";\n\nconst DID_KEY_PREFIX = \"did:key:z\";\nconst P256_MULTICODEC = [0x80, 0x24] as const;\nconst MAX_CACHED_KEYS = 1024;\n\nconst P = BigInt(\n \"0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff\",\n);\nconst A = BigInt(\n \"0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc\",\n);\nconst B = BigInt(\n \"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b\",\n);\n\n/** A did:key that is not a compressed P-256 public key. */\nexport class MalformedDidKeyError extends Error {\n constructor(did: string, detail: string) {\n super(`Malformed did:key ${did}: ${detail}`);\n this.name = \"MalformedDidKeyError\";\n }\n}\n\n// Insertion-ordered, so the first key is the least recently used.\nconst keyCache = new Map<string, CryptoKey>();\n\n/** Cached per process: decompressing the point costs a BigInt modPow. */\nexport async function importDidKey(did: string): Promise<CryptoKey> {\n const cached = keyCache.get(did);\n if (cached) {\n keyCache.delete(did);\n keyCache.set(did, cached);\n return cached;\n }\n\n const raw = decompressP256(compressedPointFromDid(did), did);\n const key = await crypto.subtle.importKey(\n \"raw\",\n raw.buffer as ArrayBuffer,\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n false,\n [\"verify\"],\n );\n\n keyCache.set(did, key);\n if (keyCache.size > MAX_CACHED_KEYS) {\n const oldest = keyCache.keys().next().value;\n if (oldest !== undefined) {\n keyCache.delete(oldest);\n }\n }\n return key;\n}\n\n/** Test seam: how many keys the process cache holds. */\nexport function cachedDidKeyCount(): number {\n return keyCache.size;\n}\n\nfunction compressedPointFromDid(did: string): Uint8Array {\n if (!did.startsWith(DID_KEY_PREFIX)) {\n throw new MalformedDidKeyError(did, \"not a base58btc did:key\");\n }\n const decoded = base58Decode(did.slice(DID_KEY_PREFIX.length));\n if (!decoded || decoded.length !== 35) {\n throw new MalformedDidKeyError(did, \"not a compressed P-256 key\");\n }\n if (decoded[0] !== P256_MULTICODEC[0] || decoded[1] !== P256_MULTICODEC[1]) {\n throw new MalformedDidKeyError(did, \"not a P-256 multicodec\");\n }\n return decoded.subarray(2);\n}\n\nfunction decompressP256(compressed: Uint8Array, did: string): Uint8Array {\n const prefix = compressed[0];\n if (prefix !== 0x02 && prefix !== 0x03) {\n throw new MalformedDidKeyError(did, `compression prefix ${prefix}`);\n }\n\n let x = BigInt(0);\n for (let i = 1; i < compressed.length; i++) {\n x = (x << BigInt(8)) | BigInt(compressed[i]);\n }\n if (x >= P) {\n throw new MalformedDidKeyError(did, \"x outside the field\");\n }\n\n const ySquared = (modPow(x, BigInt(3), P) + A * x + B) % P;\n let y = modPow(ySquared, (P + BigInt(1)) / BigInt(4), P);\n if ((y * y) % P !== ySquared) {\n throw new MalformedDidKeyError(did, \"x is not on the curve\");\n }\n if ((y % BigInt(2) === BigInt(0)) !== (prefix === 0x02)) {\n y = P - y;\n }\n\n const uncompressed = new Uint8Array(65);\n uncompressed[0] = 0x04;\n uncompressed.set(bigIntToBytes(x), 1);\n uncompressed.set(bigIntToBytes(y), 33);\n return uncompressed;\n}\n\nfunction modPow(base: bigint, exp: bigint, mod: bigint): bigint {\n let result = BigInt(1);\n let b = base % mod;\n let e = exp;\n while (e > BigInt(0)) {\n if (e & BigInt(1)) {\n result = (result * b) % mod;\n }\n e >>= BigInt(1);\n b = (b * b) % mod;\n }\n return result;\n}\n\nfunction bigIntToBytes(value: bigint): Uint8Array {\n const bytes = new Uint8Array(32);\n let v = value;\n for (let i = 31; i >= 0; i--) {\n bytes[i] = Number(v & BigInt(0xff));\n v >>= BigInt(8);\n }\n return bytes;\n}\n","import type {\n Action,\n ActionSigner,\n CreateDocumentActionInput,\n Signature,\n SignaturePolicy,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n buildOperationSignatureMessage,\n buildOperationSignatureParams,\n deriveDocumentId,\n hashActionV2,\n isDerivedDocumentId,\n isV2ActionHash,\n v2TupleProblem,\n} from \"@powerhousedao/shared/document-model\";\nimport { importDidKey } from \"./did-key.js\";\nimport type {\n AdmissionPath,\n SignatureScheme,\n SignatureVerdict,\n} from \"./types.js\";\n\nconst RENOWN_HASH_LENGTH = 44;\nconst SHARED_HASH_LENGTH = 28;\nconst HEX_SIGNATURE = /^(0x)?([0-9a-fA-F]{2})+$/;\n\nexport type VerificationTarget = {\n /** The stream the operation is stored in. */\n documentId: string;\n branch: string;\n /** Of the document `documentId` names; legacy when omitted. */\n policy?: SignaturePolicy;\n};\n\n/**\n * Integrity only: identity binding and the live-id check sit with the caller.\n * `operation` is the incoming operation at load admission.\n */\nexport async function verifyActionSignature(\n action: Action,\n target: VerificationTarget,\n path: AdmissionPath,\n operation?: { timestampUtcMs: string },\n): Promise<SignatureVerdict> {\n const policy = target.policy ?? \"legacy\";\n const refusal = policyRefusal(action, policy);\n if (refusal) {\n return refusal;\n }\n\n const shape = signerShape(action.context?.signer);\n if (shape.kind === \"unsigned\") {\n return policy === \"v2-required\"\n ? refuse(\n \"unsigned\",\n \"UNSIGNED_REQUIRED\",\n `action ${action.id} is unsigned but ${target.documentId} requires v2 signatures`,\n )\n : { ok: true, scheme: \"unsigned\" };\n }\n if (shape.kind === \"malformed\") {\n return refuse(\n \"legacy-unknown\",\n \"MALFORMED_TUPLE\",\n `action ${action.id} ${shape.reason}`,\n );\n }\n\n const { signer, tuple } = shape;\n\n const scheme = schemeOf(tuple[2]);\n\n if (tuple[1] !== signer.app.key) {\n return refuse(\n scheme,\n \"KEY_MISMATCH\",\n `action ${action.id} tuple key does not match signer.app.key`,\n );\n }\n\n if (scheme !== \"v2\" && policy === \"v2-required\") {\n return refuse(\n scheme,\n \"SCHEME_BELOW_POLICY\",\n `action ${action.id} carries a legacy tuple but ${target.documentId} requires v2 signatures`,\n );\n }\n\n if (scheme === \"legacy-unknown\" && path === \"mutation\") {\n return refuse(\n scheme,\n \"MALFORMED_TUPLE\",\n `action ${action.id} carries a hash of unknown length ${tuple[2].length}`,\n );\n }\n\n if (scheme === \"v2\") {\n const refusal = await checkV2(action, tuple, target, operation);\n if (refusal) {\n return refusal;\n }\n } else if (path === \"mutation\") {\n const expected = await legacyHash(scheme, action, target);\n if (expected !== tuple[2]) {\n return refuse(\n scheme,\n \"HASH_MISMATCH\",\n `action ${action.id} does not match the hash its signature covers`,\n );\n }\n }\n\n return verifyEcdsa(tuple, scheme, action.id);\n}\n\n/** Refusals a document's policy makes before any tuple is read. */\nfunction policyRefusal(\n action: Action,\n policy: SignaturePolicy,\n): SignatureVerdict | undefined {\n if (action.type !== \"CREATE_DOCUMENT\") {\n return undefined;\n }\n const scheme = schemeOfAction(action);\n const input = action.input as CreateDocumentActionInput | undefined;\n const documentId = input?.documentId ?? \"\";\n if (policy === \"legacy\") {\n // Otherwise a legacy CREATE could claim the id a v2-required one derives.\n return isDerivedDocumentId(documentId)\n ? refuse(\n scheme,\n \"ID_MISMATCH\",\n `action ${action.id}: a legacy document cannot take the content-addressed id ${documentId}`,\n )\n : undefined;\n }\n\n const expected = derivedCreateId(input);\n if (expected === documentId) {\n return undefined;\n }\n return refuse(\n scheme,\n \"ID_MISMATCH\",\n expected === undefined\n ? `action ${action.id} creates v2-required ${documentId} without the header params its id is derived from`\n : `action ${action.id} creates v2-required ${documentId}, but its header params derive ${expected}`,\n );\n}\n\nfunction derivedCreateId(\n input: CreateDocumentActionInput | undefined,\n): string | undefined {\n if (!input?.signing || !input.protocolVersions) {\n return undefined;\n }\n try {\n return deriveDocumentId({\n documentType: input.model,\n createdAtUtcIso: input.signing.createdAtUtcIso,\n nonce: input.signing.nonce,\n protocolVersions: input.protocolVersions,\n });\n } catch {\n return undefined;\n }\n}\n\nfunction schemeOfAction(action: Action): SignatureScheme {\n const shape = signerShape(action.context?.signer);\n if (shape.kind === \"unsigned\") {\n return \"unsigned\";\n }\n return shape.kind === \"signed\" ? schemeOf(shape.tuple[2]) : \"legacy-unknown\";\n}\n\ntype SignerShape =\n | { kind: \"unsigned\" }\n | { kind: \"malformed\"; reason: string }\n | { kind: \"signed\"; signer: ActionSigner; tuple: Signature };\n\n/** Peers send arbitrary JSON, so nothing past `context` is assumed. */\nfunction signerShape(value: unknown): SignerShape {\n if (value === undefined || value === null) {\n return { kind: \"unsigned\" };\n }\n if (!isRecord(value)) {\n return { kind: \"malformed\", reason: \"has a signer that is not an object\" };\n }\n const { app, user, signatures } = value;\n if (app !== undefined && app !== null && !isRecord(app)) {\n return {\n kind: \"malformed\",\n reason: \"has a signer.app that is not an object\",\n };\n }\n const key = isRecord(app) ? app.key : undefined;\n if (key !== undefined && key !== null && typeof key !== \"string\") {\n return {\n kind: \"malformed\",\n reason: \"has a signer.app.key that is not a string\",\n };\n }\n if (!key) {\n return { kind: \"unsigned\" };\n }\n if (!isRecord(user) || typeof user.address !== \"string\") {\n return { kind: \"malformed\", reason: \"has a signer without a user address\" };\n }\n if (!Array.isArray(signatures)) {\n return {\n kind: \"malformed\",\n reason: \"has a signer whose signatures are not a list\",\n };\n }\n const tuple: unknown = signatures.at(-1);\n if (!isTuple(tuple)) {\n return {\n kind: \"malformed\",\n reason:\n signatures.length === 0\n ? \"has a signer but no signatures\"\n : \"carries a malformed signature tuple\",\n };\n }\n return { kind: \"signed\", signer: value as ActionSigner, tuple };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nasync function checkV2(\n action: Action,\n tuple: Signature,\n target: VerificationTarget,\n operation: { timestampUtcMs: string } | undefined,\n): Promise<SignatureVerdict | undefined> {\n const problem = v2TupleProblem(tuple);\n if (problem) {\n return refuse(\"v2\", \"MALFORMED_TUPLE\", `action ${action.id}: ${problem}`);\n }\n\n if (\n operation &&\n !sameInstant(operation.timestampUtcMs, action.timestampUtcMs)\n ) {\n return refuse(\n \"v2\",\n \"TIMESTAMP_MISMATCH\",\n `action ${action.id} is stamped ${action.timestampUtcMs} but its operation ${operation.timestampUtcMs}`,\n );\n }\n\n let expected: string;\n try {\n expected = await hashActionV2(action, target, action.context!.signer!);\n } catch (error) {\n return refuse(\n \"v2\",\n \"HASH_MISMATCH\",\n `action ${action.id} has no v2 hash: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (expected !== tuple[2]) {\n return refuse(\n \"v2\",\n \"HASH_MISMATCH\",\n `action ${action.id} does not match the hash its signature covers`,\n );\n }\n return undefined;\n}\n\n// Stores normalize the operation timestamp's text, so compare instants.\nfunction sameInstant(a: string, b: string): boolean {\n const left = Date.parse(a);\n return !Number.isNaN(left) && left === Date.parse(b);\n}\n\nfunction schemeOf(hash: string): SignatureScheme {\n if (isV2ActionHash(hash)) {\n return \"v2\";\n }\n if (hash.length === RENOWN_HASH_LENGTH) {\n return \"legacy-renown\";\n }\n if (hash.length === SHARED_HASH_LENGTH) {\n return \"legacy-shared\";\n }\n return \"legacy-unknown\";\n}\n\nasync function legacyHash(\n scheme: SignatureScheme,\n action: Action,\n target: VerificationTarget,\n): Promise<string> {\n if (scheme === \"legacy-renown\") {\n const payload = [\n action.scope,\n action.type,\n JSON.stringify(action.input),\n ].join(\"\");\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(payload),\n );\n return bytesToBase64(new Uint8Array(digest));\n }\n\n const signer = action.context!.signer!;\n return buildOperationSignatureParams({\n documentId: target.documentId,\n signer,\n action,\n previousStateHash: \"\",\n })[2];\n}\n\nasync function verifyEcdsa(\n tuple: Signature,\n scheme: SignatureScheme,\n actionId: string,\n): Promise<SignatureVerdict> {\n const [timestamp, key, hash, prevStateHash, signatureHex] = tuple;\n\n if (!HEX_SIGNATURE.test(signatureHex)) {\n return refuse(\n scheme,\n \"MALFORMED_TUPLE\",\n `action ${actionId} signature is not hex`,\n );\n }\n\n let cryptoKey: CryptoKey;\n try {\n cryptoKey = await importDidKey(key);\n } catch (error) {\n return refuse(\n scheme,\n \"MALFORMED_TUPLE\",\n `action ${actionId}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n const message = buildOperationSignatureMessage([\n timestamp,\n key,\n hash,\n prevStateHash,\n ]);\n\n let valid: boolean;\n try {\n valid = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n cryptoKey,\n hexToBytes(signatureHex).buffer as ArrayBuffer,\n message.buffer as ArrayBuffer,\n );\n } catch {\n valid = false;\n }\n\n if (!valid) {\n return refuse(\n scheme,\n \"BAD_SIGNATURE\",\n `action ${actionId} signature does not verify under its key`,\n );\n }\n return { ok: true, scheme };\n}\n\nfunction isTuple(value: unknown): value is Signature {\n return (\n Array.isArray(value) &&\n value.length === 5 &&\n value.every((element) => typeof element === \"string\")\n );\n}\n\nfunction refuse(\n scheme: SignatureScheme,\n code: Extract<SignatureVerdict, { ok: false }>[\"code\"],\n reason: string,\n): SignatureVerdict {\n return { ok: false, scheme, code, reason };\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const clean = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const bytes = new Uint8Array(clean.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n","import type {\n Action,\n ActionSigningTarget,\n ISigner,\n Operation,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n actionSignerIdentity,\n deriveOperationId,\n hashBrowser,\n} from \"@powerhousedao/shared/document-model\";\n\n/** Submitted types whose stored action the reducer writes in their place. */\nexport const SYNTHESIZING_TYPES: ReadonlySet<string> = new Set([\n \"UNDO\",\n \"REDO\",\n]);\n\n/**\n * The id of the action synthesized from `submittedId`. Derived, so the stored\n * operation answers for the submitted id at the live-id check.\n */\nexport function synthesizedActionId(submittedId: string): string {\n return hashBrowser(`synthesized:${submittedId}`, \"sha1\", \"hex\").slice(0, 32);\n}\n\n/**\n * Whether `operation` stores an action the reducer made from `submitted`\n * rather than `submitted` itself or an operation already in `history`.\n */\nexport function isSynthesized(\n submitted: Action,\n operation: Operation,\n history: readonly Operation[],\n): boolean {\n if (!SYNTHESIZING_TYPES.has(submitted.type)) {\n return false;\n }\n const id = operation.action.id as string | undefined;\n if (!id) {\n return true;\n }\n if (id === submitted.id) {\n return false;\n }\n return !history.some((existing) => existing.action.id === id);\n}\n\n/**\n * Signs the synthesized action of `operation` in place as `signer`, under the\n * id {@link synthesizedActionId} derives from the submitted one. A REDO's\n * rebuilt action has no timestamp, so it takes the submitted one; the\n * operation timestamp is set to the action's, which a peer requires of a v2\n * tuple.\n */\nexport async function signSynthesized(\n operation: Operation,\n submitted: Action,\n target: ActionSigningTarget & { scope: string },\n signer: ISigner,\n signal?: AbortSignal,\n): Promise<void> {\n const synthesized = operation.action;\n const id = synthesizedActionId(submitted.id);\n const timestampUtcMs =\n (operation.timestampUtcMs as string | undefined) ||\n (synthesized.timestampUtcMs as string | undefined) ||\n submitted.timestampUtcMs;\n\n const action: Action = {\n id,\n timestampUtcMs,\n type: synthesized.type,\n input: synthesized.input,\n scope: synthesized.scope,\n };\n const signature = await signer.signAction(\n action,\n { documentId: target.documentId, branch: target.branch },\n signal,\n );\n\n operation.action = {\n ...action,\n context: {\n signer: { ...actionSignerIdentity(signer), signatures: [signature] },\n },\n };\n operation.id = deriveOperationId(\n target.documentId,\n target.scope,\n target.branch,\n id,\n );\n operation.timestampUtcMs = timestampUtcMs;\n}\n","import type {\n Action,\n ActionSigner,\n CreateDocumentActionInput,\n ISigner,\n Operation,\n SignaturePolicy,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n actionSigningTarget,\n canonicalJson,\n deriveOperationId,\n signaturePolicyOf,\n} from \"@powerhousedao/shared/document-model\";\nimport type { ILogger } from \"document-model\";\nimport type { IEventBus } from \"../events/interfaces.js\";\nimport {\n ReactorEventTypes,\n type SignatureRefusedEvent,\n} from \"../events/types.js\";\nimport type { IDocumentMetaCache } from \"../cache/document-meta-cache-types.js\";\nimport type { IWriteCache } from \"../cache/write/interfaces.js\";\nimport type { Job } from \"../queue/types.js\";\nimport {\n DocumentNotFoundError,\n InvalidSignatureError,\n} from \"../shared/errors.js\";\nimport { PassthroughSigner } from \"../signer/passthrough-signer.js\";\nimport { admissionTrustPolicy } from \"../signer/trust-policy.js\";\nimport type {\n AdmissionPath,\n SignatureTrustPolicy,\n SignatureVerdict,\n SignatureVerificationMode,\n} from \"../signer/types.js\";\nimport { verifyActionSignature } from \"../signer/verify-action-signature.js\";\nimport {\n SYNTHESIZING_TYPES,\n synthesizedActionId,\n} from \"./synthesized-signing.js\";\nimport type { IOperationStore } from \"../storage/interfaces.js\";\n\ntype Stream = { documentId: string; scope: string; branch: string };\n\ntype Candidate = {\n action: Action;\n stream: Stream;\n opId: string;\n /** The operation the reducer stores in place of a submitted UNDO or REDO. */\n synthesizedOpId?: string;\n operation?: Operation;\n policy?: SignaturePolicy;\n};\n\n/** What admission reads: the stream for live ids, a cache for the policy. */\nexport type AdmissionStores = {\n operationStore: IOperationStore;\n documentMetaCache: IDocumentMetaCache;\n writeCache: IWriteCache;\n};\n\n/**\n * Where a stored document's policy is read: the write cache when the decision\n * model reads the document scope from there anyway, else the meta cache.\n */\nexport type PolicySource = \"meta\" | \"write-cache\";\n\ntype Refusal = Extract<SignatureVerdict, { ok: false }>;\n\n/** Who may sign as whom: see {@link SignatureTrustPolicy}. */\nexport type AdmissionTrust = {\n /** The reactor's own signer, whose key is accepted for its own user. */\n signer?: ISigner;\n /** Selects the default when there is no `policy`. */\n authEnforcement: boolean;\n policy?: SignatureTrustPolicy;\n /** A policy slower than this fails the job, to be retried. */\n timeoutMs: number;\n};\n\nexport const DEFAULT_TRUST_TIMEOUT_MS = 10_000;\n\n/** A submitted write already stored exactly as submitted, under `opId`. */\nexport type CommittedWrite = Stream & { actionId: string; opId: string };\n\n/**\n * `committed` lists the writes an earlier attempt or submission already\n * stored; they are not written again and the rest are admitted.\n */\nexport type MutationAdmission =\n | { kind: \"admitted\"; committed: CommittedWrite[] }\n | { kind: \"refused\"; error: InvalidSignatureError };\n\n/** Runs once per write, when this reactor first stores it; never on re-appends. */\nexport class SignatureAdmission {\n private readonly trustPolicy: SignatureTrustPolicy;\n private readonly trustTimeoutMs: number;\n\n constructor(\n private readonly mode: SignatureVerificationMode,\n private readonly logger: ILogger,\n private readonly eventBus: IEventBus,\n private readonly policySource: PolicySource = \"meta\",\n trust: AdmissionTrust = {\n authEnforcement: false,\n timeoutMs: DEFAULT_TRUST_TIMEOUT_MS,\n },\n ) {\n this.trustPolicy = admissionTrustPolicy(\n trust.signer ?? new PassthroughSigner(),\n trust.authEnforcement,\n trust.policy,\n );\n this.trustTimeoutMs = trust.timeoutMs;\n }\n\n /** The first refusal of a mutation's submitted actions, when enforcing. */\n async admitMutation(\n job: Job,\n stores: AdmissionStores,\n signal?: AbortSignal,\n ): Promise<MutationAdmission> {\n const { operationStore } = stores;\n const candidates = job.actions.map((action) =>\n candidate(action, mutationStream(action, job)),\n );\n const live = await this.liveOperationIds(\n candidates,\n operationStore,\n signal,\n );\n\n // A retry or a resubmission after a lost response may find its writes\n // already stored. Refusing them as duplicates would fail writes that landed.\n const committed = await this.storedAsSubmitted(\n candidates,\n live,\n isRetry(job),\n operationStore,\n signal,\n );\n\n await resolvePolicies(candidates, job.actions, (documentId, branch) =>\n storedPolicy(stores, this.policySource, documentId, branch, signal),\n );\n const submitted = new Set<string>();\n for (const entry of candidates) {\n if (committed.has(entry)) {\n continue;\n }\n const verdict = await this.verdict(\n entry,\n live,\n submitted,\n \"mutation\",\n signal,\n );\n submitted.add(entry.opId);\n if (verdict.ok) {\n continue;\n }\n const refusal = this.record(job, entry, verdict, \"mutation\");\n if (refusal) {\n return { kind: \"refused\", error: refusal };\n }\n }\n return { kind: \"admitted\", committed: [...committed.values()] };\n }\n\n /** The incoming operations a load drops, empty unless enforcing. */\n async admitLoad(\n job: Job,\n operations: Operation[],\n stores: AdmissionStores,\n signal?: AbortSignal,\n ): Promise<Set<Operation>> {\n const { operationStore } = stores;\n const stream = {\n documentId: job.documentId,\n scope: job.scope,\n branch: job.branch,\n };\n const candidates = operations.map((operation) => ({\n ...candidate(operation.action, stream),\n operation,\n }));\n const live = await this.liveOperationIds(\n candidates,\n operationStore,\n signal,\n );\n\n const redelivered = await this.redelivered(\n candidates,\n live,\n operationStore,\n signal,\n );\n\n await resolvePolicies(\n candidates,\n job.operations.map((operation) => operation.action),\n (documentId, branch) =>\n storedPolicy(stores, this.policySource, documentId, branch, signal),\n );\n const dropped = new Set<Operation>();\n for (let i = 0; i < candidates.length; i++) {\n const verdict = await this.verdict(\n candidates[i],\n live,\n undefined,\n \"load\",\n signal,\n redelivered.has(candidates[i]),\n );\n if (verdict.ok) {\n continue;\n }\n if (this.record(job, candidates[i], verdict, \"load\")) {\n dropped.add(operations[i]);\n }\n }\n return dropped;\n }\n\n /** A marker is held to v2 and enforced whatever the policy and mode. */\n async admitMarker(\n job: Job,\n marker: Operation,\n signal?: AbortSignal,\n ): Promise<InvalidSignatureError | undefined> {\n const entry: Candidate = {\n ...candidate(marker.action, {\n documentId: job.documentId,\n scope: \"document\",\n branch: job.branch,\n }),\n operation: marker,\n policy: \"v2-required\",\n };\n const verdict = await this.verdict(\n entry,\n new Set(),\n undefined,\n \"load\",\n signal,\n );\n if (verdict.ok) {\n return undefined;\n }\n return this.record(job, entry, verdict, \"load\", true)!;\n }\n\n private async verdict(\n entry: Candidate,\n live: Set<string>,\n submitted: Set<string> | undefined,\n path: AdmissionPath,\n signal?: AbortSignal,\n known = false,\n ): Promise<SignatureVerdict> {\n const verdict = await verifyActionSignature(\n entry.action,\n {\n documentId: entry.stream.documentId,\n branch: entry.stream.branch,\n policy: entry.policy,\n },\n path,\n entry.operation,\n );\n if (!verdict.ok) {\n return verdict;\n }\n if (!known && (isLive(entry, live) || submitted?.has(entry.opId))) {\n return {\n ok: false,\n scheme: verdict.scheme,\n code: \"DUPLICATE_ACTION\",\n reason: `action ${entry.action.id} is already in the stream`,\n };\n }\n if (verdict.scheme === \"unsigned\") {\n const address = entry.action.context?.signer?.user?.address;\n return address\n ? {\n ok: false,\n scheme: \"unsigned\",\n code: \"UNSIGNED_IDENTITY\",\n reason: `action ${entry.action.id} is unsigned but claims to act as ${address}`,\n }\n : verdict;\n }\n if (known) {\n return verdict;\n }\n\n const signer = entry.action.context!.signer!;\n const authorized = await this.authorize(\n signer,\n entry.stream.documentId,\n signal,\n );\n if (!authorized) {\n return {\n ok: false,\n scheme: verdict.scheme,\n code: \"SIGNER_UNAUTHORIZED\",\n reason: `action ${entry.action.id}: key ${signer.app.key} may not sign as ${signer.user.address}`,\n };\n }\n return verdict;\n }\n\n /** Throws when the policy does, times out or the job is aborted. */\n private async authorize(\n signer: ActionSigner,\n documentId: string,\n signal?: AbortSignal,\n ): Promise<boolean> {\n signal?.throwIfAborted();\n let timer: ReturnType<typeof setTimeout> | undefined;\n let onAbort: (() => void) | undefined;\n const stop = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(\n new Error(\n `signature trust policy did not answer for ${signer.app.key} within ${this.trustTimeoutMs}ms`,\n ),\n );\n }, this.trustTimeoutMs);\n if (signal) {\n onAbort = () =>\n reject(\n signal.reason instanceof Error\n ? signal.reason\n : new Error(String(signal.reason)),\n );\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n });\n try {\n return await Promise.race([\n this.trustPolicy.authorizeSigner(signer, signer.app.key, documentId),\n stop,\n ]);\n } finally {\n clearTimeout(timer);\n if (onAbort) {\n signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n }\n\n /**\n * The live candidates stored exactly as submitted and still standing: one\n * an undo or a reshuffle has since superseded is refused, not re-emitted with\n * the state it once produced. A synthesized operation\n * holds another action, so it cannot be compared; only a retry, whose first\n * attempt this job was, takes it as committed.\n */\n private async storedAsSubmitted(\n candidates: Candidate[],\n live: Set<string>,\n retry: boolean,\n operationStore: IOperationStore,\n signal?: AbortSignal,\n ): Promise<Map<Candidate, CommittedWrite>> {\n const committed = new Map<Candidate, CommittedWrite>();\n const toCompare: Candidate[] = [];\n for (const entry of candidates) {\n if (entry.synthesizedOpId && live.has(entry.synthesizedOpId)) {\n if (retry) {\n committed.set(entry, committedWrite(entry, entry.synthesizedOpId));\n }\n } else if (live.has(entry.opId)) {\n toCompare.push(entry);\n }\n }\n for (const [stream, entries] of byStream(toCompare)) {\n const stored = await operationStore.getOperationsByIds(\n stream.documentId,\n stream.scope,\n stream.branch,\n entries.map((entry) => entry.opId),\n signal,\n );\n const byId = new Map(\n stored.map((operation) => [operation.id, operation]),\n );\n const matching = entries.filter((entry) => {\n const operation = byId.get(entry.opId);\n return operation && sameContent(operation.action, entry.action);\n });\n if (matching.length === 0) {\n continue;\n }\n const later = await operationStore.getSince(\n stream.documentId,\n stream.scope,\n stream.branch,\n Math.min(...matching.map((entry) => byId.get(entry.opId)!.index)),\n undefined,\n undefined,\n signal,\n );\n for (const entry of matching) {\n if (!isSuperseded(byId.get(entry.opId)!, later.results)) {\n committed.set(entry, committedWrite(entry, entry.opId));\n }\n }\n }\n return committed;\n }\n\n /**\n * The load candidates stored exactly as they arrive, timestamp included: a\n * peer re-sending what this stream holds, not a replay of its action.\n */\n private async redelivered(\n candidates: Candidate[],\n live: Set<string>,\n operationStore: IOperationStore,\n signal?: AbortSignal,\n ): Promise<Set<Candidate>> {\n const found = new Set<Candidate>();\n const toCompare = candidates.filter(\n (entry) =>\n live.has(entry.opId) &&\n !(entry.synthesizedOpId && live.has(entry.synthesizedOpId)),\n );\n for (const [stream, entries] of byStream(toCompare)) {\n const stored = await operationStore.getOperationsByIds(\n stream.documentId,\n stream.scope,\n stream.branch,\n entries.map((entry) => entry.opId),\n signal,\n );\n for (const entry of entries) {\n if (\n stored.some(\n (operation) =>\n operation.id === entry.opId &&\n Date.parse(operation.timestampUtcMs) ===\n Date.parse(entry.operation?.timestampUtcMs ?? \"\") &&\n sameContent(operation.action, entry.action),\n )\n ) {\n found.add(entry);\n }\n }\n }\n return found;\n }\n\n private async liveOperationIds(\n candidates: Candidate[],\n operationStore: IOperationStore,\n signal?: AbortSignal,\n ): Promise<Set<string>> {\n const live = new Set<string>();\n for (const [stream, entries] of byStream(candidates)) {\n const found = await operationStore.findOperationIds(\n stream.documentId,\n stream.scope,\n stream.branch,\n entries.flatMap((entry) =>\n entry.synthesizedOpId\n ? [entry.opId, entry.synthesizedOpId]\n : [entry.opId],\n ),\n signal,\n );\n for (const opId of found) {\n live.add(opId);\n }\n }\n return live;\n }\n\n /** Logs and counts a refusal; returns the error only when enforcing. */\n private record(\n job: Job,\n entry: Candidate,\n refusal: Refusal,\n path: AdmissionPath,\n enforced = this.mode === \"enforce\",\n ): InvalidSignatureError | undefined {\n const event: SignatureRefusedEvent = {\n jobId: job.id,\n documentId: entry.stream.documentId,\n scope: entry.stream.scope,\n branch: entry.stream.branch,\n actionId: entry.action.id,\n code: refusal.code,\n scheme: refusal.scheme,\n path,\n enforced,\n reason: refusal.reason,\n };\n\n this.logger.warn(\n enforced\n ? \"Signature refused: @Refusal\"\n : \"Signature refusal logged, write admitted: @Refusal\",\n event,\n );\n this.eventBus\n .emit(ReactorEventTypes.SIGNATURE_REFUSED, event)\n .catch((error) => {\n this.logger.error(\"Failed to emit SIGNATURE_REFUSED: @Error\", error);\n });\n\n return enforced\n ? new InvalidSignatureError(\n entry.stream.documentId,\n refusal.code,\n refusal.reason,\n )\n : undefined;\n }\n}\n\n/**\n * A CREATE_DOCUMENT is verified under its own input. Anything else takes the\n * stored document's policy, or, for a document this job creates, that CREATE's.\n */\nasync function resolvePolicies(\n candidates: Candidate[],\n jobActions: Action[],\n stored: (\n documentId: string,\n branch: string,\n ) => Promise<SignaturePolicy | undefined>,\n): Promise<void> {\n const resolved = new Map<string, SignaturePolicy>();\n for (const entry of candidates) {\n if (entry.action.type === \"CREATE_DOCUMENT\") {\n entry.policy = createPolicy(entry.action);\n continue;\n }\n\n const { documentId, branch } = entry.stream;\n const key = `${documentId}\\u0000${branch}`;\n let policy = resolved.get(key);\n if (policy === undefined) {\n policy =\n (await stored(documentId, branch)) ??\n createdPolicy(jobActions, documentId) ??\n \"legacy\";\n resolved.set(key, policy);\n }\n entry.policy = policy;\n }\n}\n\nasync function storedPolicy(\n stores: AdmissionStores,\n source: PolicySource,\n documentId: string,\n branch: string,\n signal?: AbortSignal,\n): Promise<SignaturePolicy | undefined> {\n try {\n if (source === \"write-cache\") {\n const document = await stores.writeCache.getState(\n documentId,\n \"document\",\n branch,\n undefined,\n signal,\n );\n return signaturePolicyOf(document.header);\n }\n const meta = await stores.documentMetaCache.getDocumentMeta(\n documentId,\n branch,\n signal,\n );\n return signaturePolicyOf(meta.protocolVersions);\n } catch (error) {\n if (DocumentNotFoundError.isError(error)) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction createdPolicy(\n actions: Action[],\n documentId: string,\n): SignaturePolicy | undefined {\n const create = actions.find(\n (action) =>\n action.type === \"CREATE_DOCUMENT\" &&\n (action.input as CreateDocumentActionInput | undefined)?.documentId ===\n documentId,\n );\n return create ? createPolicy(create) : undefined;\n}\n\nfunction createPolicy(action: Action): SignaturePolicy {\n return signaturePolicyOf(action.input as CreateDocumentActionInput);\n}\n\nfunction candidate(action: Action, stream: Stream): Candidate {\n const opId = (actionId: string) =>\n deriveOperationId(stream.documentId, stream.scope, stream.branch, actionId);\n return {\n action,\n stream,\n opId: opId(action.id),\n synthesizedOpId: SYNTHESIZING_TYPES.has(action.type)\n ? opId(synthesizedActionId(action.id))\n : undefined,\n };\n}\n\nfunction isLive(entry: Candidate, live: Set<string>): boolean {\n return (\n live.has(entry.opId) ||\n (entry.synthesizedOpId !== undefined && live.has(entry.synthesizedOpId))\n );\n}\n\nfunction mutationStream(action: Action, job: Job): Stream {\n return {\n ...actionSigningTarget(action, job.documentId, job.branch),\n scope: job.scope,\n };\n}\n\nfunction byStream(candidates: Candidate[]): [Stream, Candidate[]][] {\n const groups = new Map<string, [Stream, Candidate[]]>();\n for (const entry of candidates) {\n const key = `${entry.stream.documentId}\\u0000${entry.stream.scope}\\u0000${entry.stream.branch}`;\n const group = groups.get(key) ?? [entry.stream, []];\n group[1].push(entry);\n groups.set(key, group);\n }\n return [...groups.values()];\n}\n\nfunction isRetry(job: Job): boolean {\n return job.errorHistory.length > 0 || (job.retryCount ?? 0) > 0;\n}\n\nfunction committedWrite(entry: Candidate, opId: string): CommittedWrite {\n return { ...entry.stream, actionId: entry.action.id, opId };\n}\n\nfunction isSuperseded(operation: Operation, later: Operation[]): boolean {\n return later.some(\n (next) =>\n next.index > operation.index &&\n next.skip > 0 &&\n next.index - next.skip <= operation.index,\n );\n}\n\nfunction sameContent(stored: Action, submitted: Action): boolean {\n try {\n return canonicalJson(stored) === canonicalJson(submitted);\n } catch {\n return false;\n }\n}\n","import type {\n Action,\n DocumentModelModule,\n ISigner,\n Operation,\n OperationWithContext,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n actionSignerIdentity,\n baseReducerVersion,\n decide,\n garbageCollect,\n groupDocumentType,\n isPurgeMarker,\n purgeDocumentAction,\n purgeMarkerOperation,\n type PurgeMarkerOperation,\n hashDocumentStateForScope,\n isUndoRedo,\n mentionedGroupIds,\n localSupports,\n normalizeDocumentModelVersion,\n PEER_CAPABILITIES,\n sortOperations,\n withProtocolVersions,\n} from \"@powerhousedao/shared/document-model\";\nimport type { ILogger } from \"document-model\";\nimport type { ICollectionMembershipCache } from \"../cache/collection-membership-cache.js\";\nimport { DriveCollectionId } from \"../cache/operation-index-types.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 {\n ReactorEventTypes,\n type JobWriteReadyEvent,\n type PurgeMarkerContext,\n} 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 DocumentNotDeletedError,\n DocumentPurgedError,\n ExcessiveReshuffleError,\n GroupInUseError,\n InvalidOperationTimestampError,\n InvalidSignatureError,\n PurgeTooLargeError,\n ReservedActionError,\n} from \"../shared/errors.js\";\nimport type { KyselyDocumentPurger } from \"../storage/kysely/document-purger.js\";\nimport {\n delay,\n TIMED_OUT,\n withDeadline,\n yieldToMain,\n} from \"../shared/utils.js\";\nimport { isCursorProtectedLoad } from \"../shared/types.js\";\nimport type { IStorageFlusher } from \"../storage/storage-flush.js\";\nimport {\n NoopStorageFlusher,\n StoragePoisonedError,\n} from \"../storage/storage-flush.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 {\n DEFAULT_TRUST_TIMEOUT_MS,\n SignatureAdmission,\n type CommittedWrite,\n type MutationAdmission,\n} from \"./signature-admission.js\";\nimport { isSynthesized, signSynthesized } from \"./synthesized-signing.js\";\nimport { PassthroughSigner } from \"../signer/passthrough-signer.js\";\nimport type { SignatureTrustPolicy } from \"../signer/types.js\";\nimport {\n DEFAULT_DEFERRED_JOB_TTL_MS,\n DEFAULT_MAX_PURGE_OPERATIONS,\n} from \"./types.js\";\nimport type {\n ExecutingJob,\n JobExecutorConfig,\n JobResult,\n PendingWrite,\n PositionedWrites,\n ReactorFeatureFlags,\n TouchedStream,\n} from \"./types.js\";\nimport {\n buildErrorResult,\n createOperation,\n DOCUMENT_SCOPE_ACTIONS,\n getNextIndexForScope,\n isGenesisOperation,\n FencedWriteCache,\n jobWriteIds,\n PurgeFence,\n refusalError,\n relationshipTarget,\n submittedActionIds,\n targetDocumentId,\n TouchedStreams,\n} from \"./util.js\";\n\nconst MAX_SKIP_THRESHOLD = 1000;\n\n/** Retries of a failed flush before a committed job's write-ready is withheld. */\nconst MAX_ANNOUNCE_FLUSH_ATTEMPTS = 5;\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 ExecuteInScopeParams = {\n job: Job;\n startTime: number;\n stores: ExecutionStores;\n signal?: AbortSignal;\n touchedStreams: TouchedStreams;\n postCommitInvalidations: TouchedStream[];\n postCommitMembershipInvalidations: string[];\n postCommitMetaInvalidations: string[];\n};\n\n/** What a purge transaction needs once its path has decided to purge. */\ntype PurgeCommit = {\n purger: KyselyDocumentPurger;\n marker: PurgeMarkerOperation;\n documentType: string;\n held: PurgeHeld;\n sourceRemote: string;\n collectionIds: string[];\n survivors: string[];\n appliedDeletion?: true;\n};\n\ntype PurgeHeld = {\n streams: { scope: string; branch: string }[];\n branches: string[];\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 */\n/**\n * A write that has been decided and reduced but not yet persisted.\n *\n * Exists so a single write and a batch of them can share one copy of the\n * decide-and-reduce logic while differing only in how many operations reach\n * the store per transaction.\n */\ntype PreparedWrite = {\n action: Action;\n sourceRemote: string;\n scope: string;\n /** State the action was reduced against, for its document type. */\n document: PHDocument;\n updatedDocument: PHDocument;\n operation: Operation;\n resultingState: string;\n appendCondition?: AppendCondition;\n denied: boolean;\n};\n\n/** What a job produced inside the execution scope, before anything is durable. */\ntype ScopeOutcome = {\n result: JobResult;\n pendingEvent?: JobWriteReadyEvent;\n};\n\n/**\n * Carries a failed job out of the execution scope so its transaction rolls\n * back. A scope callback that returns commits, whatever result it returns, so\n * a returned failure would leave the writes the job made before it failed\n * standing. Never escapes executeJob: the failure goes back to being a\n * returned JobResult there, which is what the queue, the worker protocol and\n * every test expect a failed job to look like.\n */\n/** The ids of a purge job's request, which a drive purge may precede. */\nfunction purgeRequestDocumentIds(job: Job): string[] {\n const ids = job.meta.purgeRequestDocumentIds;\n return Array.isArray(ids)\n ? ids.filter((id): id is string => typeof id === \"string\")\n : [];\n}\n\nconst MARKER_INPUT_KEYS: ReadonlySet<string> = new Set([\n \"documentId\",\n \"documentType\",\n \"purgedAtUtcIso\",\n \"requestId\",\n]);\n\n/** A peer's marker must name this job's id on main and carry nothing else. */\nfunction malformedMarker(job: Job): InvalidSignatureError | undefined {\n const marker = job.operations.find((operation) => isPurgeMarker(operation));\n const action = marker?.action;\n const input = action?.input as Record<string, unknown> | null | undefined;\n const refuse = (reason: string) =>\n new InvalidSignatureError(\n job.documentId,\n \"ID_MISMATCH\",\n `marker ${action?.id ?? \"?\"} ${reason}`,\n );\n if (typeof input !== \"object\" || input === null) {\n return refuse(\"carries no input\");\n }\n const extra = Object.keys(input).filter((key) => !MARKER_INPUT_KEYS.has(key));\n if (extra.length > 0) {\n return refuse(`carries unexpected input ${extra.join(\", \")}`);\n }\n for (const key of MARKER_INPUT_KEYS) {\n if (typeof input[key] !== \"string\" || input[key] === \"\") {\n return refuse(`input.${key} is not a non-empty string`);\n }\n }\n const purgedAt = Date.parse(input.purgedAtUtcIso as string);\n if (\n Number.isNaN(purgedAt) ||\n new Date(purgedAt).toISOString() !== input.purgedAtUtcIso\n ) {\n return refuse(\"input.purgedAtUtcIso is not an ISO timestamp\");\n }\n if (\n input.documentId !== job.documentId ||\n job.branch !== \"main\" ||\n action?.scope !== \"document\"\n ) {\n return refuse(`does not purge ${job.documentId} on document/main`);\n }\n return undefined;\n}\n\nclass JobRollbackSignal extends Error {\n constructor(readonly result: JobResult) {\n super(\"job rolled back\");\n this.name = \"JobRollbackSignal\";\n }\n}\n\nexport class SimpleJobExecutor implements IJobExecutor {\n private config: Required<JobExecutorConfig>;\n private featureFlags: ReactorFeatureFlags;\n private decisionModel: RegisteredDecisionModel;\n private signatureAdmission: SignatureAdmission;\n private documentActionHandler: DocumentActionHandler;\n private executionScope: IExecutionScope;\n private signer: ISigner;\n private readonly flusher: IStorageFlusher;\n\n /**\n * `signer` signs the operations the reducer synthesizes; unsigned if omitted.\n * `trustPolicy` decides which keys may sign as which users at admission.\n * `flusher` makes a job durable before its write-ready is announced.\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 executionScope?: IExecutionScope,\n signer?: ISigner,\n trustPolicy?: SignatureTrustPolicy,\n flusher: IStorageFlusher = new NoopStorageFlusher(),\n ) {\n this.flusher = flusher;\n this.signer = signer ?? new PassthroughSigner();\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.config = {\n featureFlags: config.featureFlags ?? {},\n maxSkipThreshold: config.maxSkipThreshold ?? MAX_SKIP_THRESHOLD,\n maxConcurrency: config.maxConcurrency ?? 1,\n jobTimeoutMs: config.jobTimeoutMs ?? 30000,\n // Held by the executor manager, not the executor; carried so a pooled\n // worker's config round-trips unchanged.\n deferredJobTtlMs: config.deferredJobTtlMs ?? DEFAULT_DEFERRED_JOB_TTL_MS,\n retryBaseDelayMs: config.retryBaseDelayMs ?? 100,\n retryMaxDelayMs: config.retryMaxDelayMs ?? 5000,\n yieldDeadlineMs: config.yieldDeadlineMs ?? 50,\n batchApplies: config.batchApplies ?? true,\n signatureVerification: config.signatureVerification ?? \"enforce\",\n protocolSupport:\n config.protocolSupport ??\n localSupports(PEER_CAPABILITIES, this.featureFlags).protocols,\n maxPurgeOperations:\n config.maxPurgeOperations ?? DEFAULT_MAX_PURGE_OPERATIONS,\n durabilityWaitMs: config.durabilityWaitMs ?? 0,\n };\n\n this.decisionModel = selectDecisionModel(this.featureFlags, registry);\n this.signatureAdmission = new SignatureAdmission(\n this.config.signatureVerification,\n logger,\n eventBus,\n this.featureFlags.documentDecisions ? \"write-cache\" : \"meta\",\n {\n signer: this.signer,\n authEnforcement: this.featureFlags.authEnforcement,\n policy: trustPolicy,\n timeoutMs: Math.min(\n DEFAULT_TRUST_TIMEOUT_MS,\n this.config.jobTimeoutMs / 2,\n ),\n },\n );\n this.documentActionHandler = new DocumentActionHandler(\n registry,\n logger,\n driveContainerTypes,\n this.featureFlags,\n this.decisionModel,\n this.config.protocolSupport,\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 * The whole job runs inside one execution scope, and a scope callback that\n * returns commits. A failed job must therefore leave the scope by throwing,\n * or the writes it made before it failed would be durable: JobRollbackSignal\n * carries the failure out through the transaction and this method turns it\n * back into the returned JobResult every caller expects. A job either fully\n * applies or leaves nothing durable behind.\n *\n * Durable is the whole of the guarantee. The caches are shared with the\n * copies the scope hands the job, so a failed job's writes sit in them from\n * the moment it makes them until the eviction below, and a concurrent read\n * in that window sees a write that is never going to commit. The window is\n * not new -- it has always been there for a job that failed by throwing --\n * but nothing here closes it, and a caller that needs to know a write is\n * real has the job status to ask.\n */\n async executeJob(\n job: Job,\n signal?: AbortSignal,\n onCommitting?: () => void,\n ): Promise<JobResult> {\n const startTime = Date.now();\n\n // Streams the job wrote, to evict when its transaction does not commit\n const touchedStreams = new TouchedStreams();\n\n // Entries handlers request invalidated only after the transaction commits\n const postCommitInvalidations: TouchedStream[] = [];\n const postCommitMembershipInvalidations: string[] = [];\n const postCommitMetaInvalidations: string[] = [];\n\n let outcome: ScopeOutcome;\n try {\n outcome = await this.executionScope.run(async (stores) => {\n const scoped = await this.executeInScope({\n job,\n startTime,\n stores,\n signal,\n touchedStreams,\n postCommitInvalidations,\n postCommitMembershipInvalidations,\n postCommitMetaInvalidations,\n });\n\n if (!scoped.result.success) {\n throw new JobRollbackSignal(scoped.result);\n }\n\n // The point of no return: one tick, so a timeout and the COMMIT are exclusive.\n signal?.throwIfAborted();\n onCommitting?.();\n return scoped;\n }, signal);\n } catch (error) {\n this.evictTouchedStreams(touchedStreams);\n\n if (error instanceof JobRollbackSignal) {\n return error.result;\n }\n\n throw error;\n }\n\n for (const entry of postCommitInvalidations) {\n this.writeCache.invalidate(entry.documentId, entry.scope, entry.branch);\n }\n\n for (const documentId of postCommitMembershipInvalidations) {\n this.collectionMembershipCache.invalidate(documentId);\n }\n\n for (const documentId of postCommitMetaInvalidations) {\n this.documentMetaCache.invalidate(documentId);\n }\n\n const { pendingEvent } = outcome;\n if (pendingEvent && (await this.awaitDurable(job, signal))) {\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 outcome.result;\n }\n\n /**\n * Waits for a flush covering the committed job before its write-ready goes\n * out; false withholds the announcement. A failed flush is never a failed\n * job, since the commit stands: it is retried, and the announcement is\n * withheld once the store is poisoned (the host restarts), the attempts run\n * out, the wait outlives `durabilityWaitMs`, or the job's signal aborts.\n */\n private async awaitDurable(\n job: Job,\n signal: AbortSignal | undefined,\n ): Promise<boolean> {\n if (isCursorProtectedLoad(job)) {\n return true;\n }\n const budgetMs = this.config.durabilityWaitMs;\n const deadline = budgetMs > 0 ? Date.now() + budgetMs : Infinity;\n for (let attempt = 1; ; attempt++) {\n try {\n const outcome = await this.withinDurabilityWait(\n this.flusher.flush(),\n deadline,\n signal,\n );\n if (outcome !== TIMED_OUT) {\n return true;\n }\n this.logger.error(\n \"Job @JobId committed but its flush outlived the durability wait or the job was aborted; its write-ready is withheld\",\n job.id,\n );\n return false;\n } catch (error) {\n this.logger.error(\n \"Flush before announcing job @JobId failed (attempt @Attempt): @Error\",\n job.id,\n attempt,\n error,\n );\n if (\n error instanceof StoragePoisonedError ||\n attempt >= MAX_ANNOUNCE_FLUSH_ATTEMPTS\n ) {\n this.logger.error(\n \"Job @JobId committed but is not durable; its write-ready is withheld\",\n job.id,\n );\n return false;\n }\n }\n const backoff = await this.withinDurabilityWait(\n delay(\n Math.min(\n this.config.retryMaxDelayMs,\n this.config.retryBaseDelayMs * 2 ** (attempt - 1),\n ),\n ),\n deadline,\n signal,\n );\n if (backoff === TIMED_OUT) {\n return false;\n }\n }\n }\n\n /** Settles with TIMED_OUT at the deadline or on abort; the wait itself is abandoned. */\n private async withinDurabilityWait<T>(\n pending: Promise<T>,\n deadline: number,\n signal: AbortSignal | undefined,\n ): Promise<T | typeof TIMED_OUT> {\n pending.catch(() => undefined);\n if (signal?.aborted) return TIMED_OUT;\n let onAbort: (() => void) | undefined;\n const aborted = new Promise<typeof TIMED_OUT>((resolve) => {\n onAbort = () => resolve(TIMED_OUT);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n try {\n const raced = Promise.race([pending, aborted]);\n return deadline === Infinity\n ? await raced\n : await withDeadline(raced, Math.max(0, deadline - Date.now()));\n } finally {\n if (onAbort) signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n /**\n * The body of a job, run inside the execution scope's transaction.\n *\n * The stores and caches it works through are the copies scoped to that\n * transaction, so nothing it does is durable until the scope commits. The\n * write-ready event is handed back rather than emitted, because a job that\n * has not committed yet has nothing to announce.\n */\n private async executeInScope(\n params: ExecuteInScopeParams,\n ): Promise<ScopeOutcome> {\n const {\n job,\n startTime,\n stores: scopeStores,\n signal,\n touchedStreams,\n postCommitInvalidations,\n postCommitMembershipInvalidations,\n } = params;\n\n let pendingEvent: JobWriteReadyEvent | undefined;\n\n if (job.kind === \"mutation\") {\n const reserved = job.actions.find((action) => isPurgeMarker(action));\n if (reserved) {\n return {\n result: buildErrorResult(\n job,\n new ReservedActionError(job.documentId, reserved.type),\n startTime,\n ),\n };\n }\n }\n\n if (\n job.kind === \"purge\" ||\n (job.kind === \"load\" && job.operations.some((op) => isPurgeMarker(op)))\n ) {\n return this.executePurge(params);\n }\n\n const lockedIds = jobWriteIds(job);\n const lockFailure = (error: unknown) => ({\n result: buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n ),\n });\n try {\n await scopeStores.documentLocks.shared(lockedIds);\n } catch (error) {\n return lockFailure(error);\n }\n let purged: Set<string>;\n try {\n purged = await scopeStores.documentLocks.purged(lockedIds);\n } catch (error) {\n return lockFailure(error);\n }\n const purgedRefusal = this.purgedRefusal(job, purged);\n if (purgedRefusal) {\n return { result: buildErrorResult(job, purgedRefusal, startTime) };\n }\n const purgeFence = new PurgeFence(\n scopeStores.documentLocks,\n new Set(lockedIds),\n purged,\n );\n const stores: ExecutionStores = {\n ...scopeStores,\n writeCache: new FencedWriteCache(\n scopeStores.writeCache,\n purgeFence,\n (documentId) => {\n scopeStores.writeCache.invalidate(documentId);\n scopeStores.documentMetaCache.invalidate(documentId);\n },\n ),\n };\n\n const unsupported = await this.unsupportedStoredProtocol(\n job,\n stores,\n signal,\n );\n if (unsupported) {\n return { result: buildErrorResult(job, unsupported, startTime) };\n }\n\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 postCommitMembershipInvalidations,\n touchedStreams,\n purgeFence,\n });\n if (loadResult.success && loadResult.operationsWithContext) {\n const ordinals = await stores.operationIndex.commit(indexTxn, signal);\n postCommitMembershipInvalidations.push(\n ...indexTxn.getMembershipInvalidations(),\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 { result: loadResult, pendingEvent };\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 postCommitMembershipInvalidations,\n touchedStreams,\n purgeFence,\n });\n if (reevalResult.success && reevalResult.operationsWithContext) {\n const ordinals = await stores.operationIndex.commit(indexTxn, signal);\n postCommitMembershipInvalidations.push(\n ...indexTxn.getMembershipInvalidations(),\n );\n\n for (let i = 0; i < reevalResult.operationsWithContext.length; i++) {\n reevalResult.operationsWithContext[i].context.ordinal = 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 { result: reevalResult, pendingEvent };\n }\n\n let admission: MutationAdmission;\n try {\n admission = await this.signatureAdmission.admitMutation(\n job,\n stores,\n signal,\n );\n } catch (error) {\n return {\n result: buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n ),\n };\n }\n if (admission.kind === \"refused\") {\n return { result: buildErrorResult(job, admission.error, startTime) };\n }\n\n let committed: OperationWithContext[];\n try {\n committed = await this.reloadCommitted(\n admission.committed,\n stores,\n signal,\n );\n } catch (error) {\n return {\n result: buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n ),\n };\n }\n const committedIds = new Set(\n admission.committed.map((write) => write.actionId),\n );\n const fresh: Job =\n committedIds.size === 0\n ? job\n : {\n ...job,\n actions: job.actions.filter(\n (action) => !committedIds.has(action.id),\n ),\n };\n if (fresh.actions.length === 0) {\n return this.committedOutcome(job, committed, [], [], stores, startTime);\n }\n\n const positioned = await this.positionByTimestamp(fresh, stores, signal);\n if (positioned.error) {\n return { result: buildErrorResult(job, positioned.error, startTime) };\n }\n\n const executing: ExecutingJob = {\n job: fresh,\n startTime,\n indexTxn,\n stores,\n signal,\n replayingAcceptedHistory: false,\n evaluatedByPosition: positioned.evaluatedByPosition,\n postCommitInvalidations,\n postCommitMembershipInvalidations,\n touchedStreams,\n purgeFence,\n };\n\n const actionResult = await this.processActions(\n positioned.writes,\n executing,\n );\n\n if (!actionResult.success) {\n return {\n result: {\n job,\n success: false as const,\n error: actionResult.error,\n duration: Date.now() - startTime,\n },\n };\n }\n\n // Put here because a re-eval pass writes through the same db transaction.\n const reevaluationError = await this.reevaluateIfCriteriaMet(\n { scope: job.scope, operations: actionResult.generatedOperations },\n executing,\n );\n if (reevaluationError) {\n return {\n result: {\n job,\n success: false as const,\n error: reevaluationError,\n duration: Date.now() - startTime,\n },\n };\n }\n\n const ordinals = await stores.operationIndex.commit(indexTxn, signal);\n postCommitMembershipInvalidations.push(\n ...indexTxn.getMembershipInvalidations(),\n );\n\n for (let i = 0; i < actionResult.operationsWithContext.length; i++) {\n actionResult.operationsWithContext[i].context.ordinal = ordinals[i];\n }\n return this.committedOutcome(\n job,\n committed,\n actionResult.operationsWithContext,\n actionResult.generatedOperations,\n stores,\n startTime,\n );\n }\n\n /** A load names only its own id purged; a foreign one is ID_MISMATCH. */\n private purgedRefusal(job: Job, purged: Set<string>): Error | undefined {\n if (purged.size === 0) {\n return undefined;\n }\n if (purged.has(job.documentId)) {\n return new DocumentPurgedError(job.documentId);\n }\n const actions = [\n ...job.actions,\n ...job.operations.map((operation) => operation.action),\n ];\n for (const action of actions) {\n if (!DOCUMENT_SCOPE_ACTIONS.has(action.type)) {\n continue;\n }\n const target = targetDocumentId(action, job.documentId);\n if (!purged.has(target)) {\n continue;\n }\n if (job.kind === \"mutation\") {\n return new DocumentPurgedError(target);\n }\n return new InvalidSignatureError(\n job.documentId,\n \"ID_MISMATCH\",\n `${action.type} ${action.id} in ${job.documentId} writes purged ${target}`,\n );\n }\n if (job.kind !== \"mutation\") {\n return undefined;\n }\n for (const action of job.actions) {\n const target = relationshipTarget(action);\n if (\n action.type === \"ADD_RELATIONSHIP\" &&\n target !== undefined &&\n purged.has(target)\n ) {\n return new DocumentPurgedError(\n target,\n `${action.type} target ${target} was purged`,\n );\n }\n if (action.scope !== \"auth\") {\n continue;\n }\n const group = mentionedGroupIds(action).find((id) => purged.has(id));\n if (group !== undefined) {\n return new DocumentPurgedError(\n group,\n `${action.type} names purged group ${group}`,\n );\n }\n }\n return undefined;\n }\n\n /** A purge job or a marker load: the exclusive lock is the job's only lock. */\n private async executePurge(\n params: ExecuteInScopeParams,\n ): Promise<ScopeOutcome> {\n const { job, startTime, stores } = params;\n const fail = (error: unknown): ScopeOutcome => ({\n result: buildErrorResult(\n job,\n error instanceof Error ? error : new Error(String(error)),\n startTime,\n ),\n });\n\n if (job.kind === \"load\") {\n const malformed = malformedMarker(job);\n if (malformed) {\n return fail(malformed);\n }\n }\n\n const purger = stores.purger;\n if (!purger) {\n return fail(\n new Error(`Purge of ${job.documentId} needs a transactional scope`),\n );\n }\n\n try {\n await stores.documentLocks.exclusive(job.documentId);\n } catch (error) {\n return fail(error);\n }\n let alreadyPurged: boolean;\n try {\n const purged = await stores.documentLocks.purged([job.documentId]);\n alreadyPurged = purged.has(job.documentId);\n } catch (error) {\n return fail(error);\n }\n // Nothing written; the empty event is what moves the job to READ_READY.\n if (alreadyPurged) {\n return {\n result: {\n job,\n success: true,\n operations: [],\n operationsWithContext: [],\n duration: Date.now() - startTime,\n },\n pendingEvent: {\n jobId: job.id,\n operations: [],\n jobMeta: job.meta,\n collectionMemberships: {},\n },\n };\n }\n\n let commit: PurgeCommit | Error;\n try {\n commit =\n job.kind === \"purge\"\n ? await this.preparePurgeJob(params, purger)\n : await this.preparePurgeLoad(params, purger);\n } catch (error) {\n return fail(error);\n }\n if (commit instanceof Error) {\n return fail(commit);\n }\n\n try {\n return await this.commitPurge(params, commit);\n } catch (error) {\n return fail(error);\n }\n }\n\n /** Preconditions 1-5, then the marker this host signs. */\n private async preparePurgeJob(\n params: ExecuteInScopeParams,\n purger: KyselyDocumentPurger,\n ): Promise<PurgeCommit | Error> {\n const { job, stores, signal } = params;\n const documentId = job.documentId;\n if (!job.purge) {\n return new Error(`Purge job ${job.id} carries no purge options`);\n }\n\n const held = await this.heldStreams(purger, documentId);\n if (held.branches.length === 0) {\n return new DocumentNotDeletedError(\n documentId,\n `Document ${documentId} is not held here`,\n );\n }\n\n let documentType: string | undefined;\n for (const branch of held.branches) {\n let meta;\n try {\n meta = await stores.documentMetaCache.getDocumentMeta(\n documentId,\n branch,\n signal,\n );\n } catch (error) {\n return new DocumentNotDeletedError(\n documentId,\n `Document ${documentId} has no readable state on ${branch}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!meta.state.isDeleted) {\n return new DocumentNotDeletedError(\n documentId,\n `Document ${documentId} is not deleted on branch ${branch}`,\n );\n }\n documentType ??= meta.documentType;\n }\n if (documentType === undefined) {\n return new DocumentNotDeletedError(documentId);\n }\n\n if (documentType === groupDocumentType) {\n const referencers = await purger.groupReferencersInHistory(documentId);\n if (referencers.length > 0) {\n return new GroupInUseError(documentId, referencers);\n }\n }\n\n let survivors: string[] = [];\n if (this.driveContainerTypes.has(documentType)) {\n const requested = new Set(purgeRequestDocumentIds(job));\n const members = await this.driveMembers(\n purger,\n stores,\n documentId,\n held.branches,\n );\n const blocking = members.required.filter((id) => !requested.has(id));\n if (blocking.length > 0) {\n return new DocumentNotDeletedError(\n documentId,\n `Drive ${documentId} cannot be purged: ${blocking.join(\", \")} neither purged nor in the request`,\n );\n }\n survivors = members.survivors;\n }\n\n const operationCount = await purger.operationCount(documentId);\n if (\n operationCount > this.config.maxPurgeOperations &&\n !job.purge.allowLarge\n ) {\n return new PurgeTooLargeError(\n documentId,\n operationCount,\n this.config.maxPurgeOperations,\n );\n }\n\n const marker = await this.signMarker(\n documentId,\n documentType,\n job.purge.requestId,\n signal,\n );\n return {\n purger,\n marker,\n documentType,\n held,\n sourceRemote: \"\",\n collectionIds: [],\n survivors,\n };\n }\n\n /** A peer's marker, admitted alone; a receiver cannot refuse an erasure. */\n private async preparePurgeLoad(\n params: ExecuteInScopeParams,\n purger: KyselyDocumentPurger,\n ): Promise<PurgeCommit | Error> {\n const { job, stores, signal } = params;\n const documentId = job.documentId;\n const marker = job.operations.find((operation) =>\n isPurgeMarker(operation),\n ) as PurgeMarkerOperation;\n\n const refusal = await this.signatureAdmission.admitMarker(\n job,\n marker,\n signal,\n );\n if (refusal) {\n return refusal;\n }\n\n const held = await this.heldStreams(purger, documentId);\n let documentType = marker.action.input.documentType;\n let appliedDeletion = held.branches.length > 0;\n if (held.branches.length > 0) {\n try {\n const meta = await stores.documentMetaCache.getDocumentMeta(\n documentId,\n held.branches.includes(\"main\") ? \"main\" : held.branches[0],\n signal,\n );\n documentType = meta.documentType;\n appliedDeletion = !meta.state.isDeleted;\n } catch {\n // Unreadable state is still erased; the marker names the type.\n }\n }\n\n let survivors: string[] = [];\n if (this.driveContainerTypes.has(documentType)) {\n const members = await this.driveMembers(\n purger,\n stores,\n documentId,\n held.branches,\n );\n survivors = [...members.required, ...members.survivors];\n }\n\n const sourceRemote =\n typeof job.meta.sourceRemote === \"string\" ? job.meta.sourceRemote : \"\";\n const collectionId = sourceRemote\n ? await purger.remoteCollection(sourceRemote)\n : undefined;\n\n return {\n purger,\n marker: purgeMarkerOperation(marker.action),\n documentType,\n held,\n sourceRemote,\n collectionIds: collectionId === undefined ? [] : [collectionId],\n survivors,\n ...(appliedDeletion ? { appliedDeletion: true } : {}),\n };\n }\n\n /** Execution: delete, write the marker and its twin, tombstone, reopen. */\n private async commitPurge(\n params: ExecuteInScopeParams,\n commit: PurgeCommit,\n ): Promise<ScopeOutcome> {\n const { job, startTime, stores, signal, touchedStreams } = params;\n const { purger, marker, documentType, held, sourceRemote } = commit;\n const documentId = job.documentId;\n\n const streams = [...held.streams, { scope: \"document\", branch: \"main\" }];\n for (const stream of streams) {\n touchedStreams.add(documentId, stream.scope, stream.branch);\n params.postCommitInvalidations.push({ documentId, ...stream });\n }\n params.postCommitMetaInvalidations.push(documentId);\n\n const removedRows = await purger.deleteRows(documentId);\n\n const [stored] = await stores.operationStore.apply(\n documentId,\n documentType,\n \"document\",\n \"main\",\n 0,\n (txn) => {\n txn.addOperations(marker);\n },\n signal,\n );\n\n const indexTxn = stores.operationIndex.start();\n indexTxn.write([\n {\n ...stored,\n documentId,\n documentType,\n scope: \"document\",\n branch: \"main\",\n sourceRemote,\n },\n ]);\n const [ordinal] = await stores.operationIndex.commit(indexTxn, signal);\n\n await purger.writeTombstone({\n documentId,\n ordinal,\n removedRows,\n purgedAtUtc: marker.action.input.purgedAtUtcIso,\n requestId: marker.action.input.requestId,\n });\n const collections = await purger.reopenMemberships(\n documentId,\n ordinal,\n commit.collectionIds,\n );\n\n params.postCommitMembershipInvalidations.push(\n documentId,\n ...commit.survivors,\n ...indexTxn.getMembershipInvalidations(),\n );\n\n const context: PurgeMarkerContext = {\n documentId,\n scope: \"document\",\n branch: \"main\",\n documentType,\n ordinal,\n ...(commit.appliedDeletion ? { appliedDeletion: true } : {}),\n };\n const operationWithContext: OperationWithContext = {\n operation: stored,\n context,\n };\n return {\n result: {\n job,\n success: true,\n operations: [stored],\n operationsWithContext: [operationWithContext],\n duration: Date.now() - startTime,\n },\n pendingEvent: {\n jobId: job.id,\n operations: [operationWithContext],\n jobMeta: job.meta,\n collectionMemberships: { [documentId]: collections },\n },\n };\n }\n\n private async heldStreams(\n purger: KyselyDocumentPurger,\n documentId: string,\n ): Promise<PurgeHeld> {\n const streams = await purger.streams(documentId);\n const branches = [\n ...new Set(\n streams\n .filter((stream) => stream.scope === \"document\")\n .map((stream) => stream.branch),\n ),\n ];\n return { streams, branches };\n }\n\n /** Members a drive purge needs gone, and those living on elsewhere. */\n private async driveMembers(\n purger: KyselyDocumentPurger,\n stores: ExecutionStores,\n driveId: string,\n branches: string[],\n ): Promise<{ required: string[]; survivors: string[] }> {\n const required = new Set<string>();\n const survivors = new Set<string>();\n for (const branch of branches.length > 0 ? branches : [\"main\"]) {\n const collectionId = DriveCollectionId.forDrive(driveId, branch).key;\n const members = await purger.collectionMembers(\n collectionId,\n driveId,\n branch,\n );\n const purged = await stores.documentLocks.purged(\n members.map((member) => member.documentId),\n );\n for (const member of members) {\n if (purged.has(member.documentId)) {\n continue;\n }\n if (member.required) {\n required.add(member.documentId);\n } else {\n survivors.add(member.documentId);\n }\n }\n }\n return { required: [...required], survivors: [...survivors] };\n }\n\n /** The marker, signed by this executor's signer as any peer admits it. */\n private async signMarker(\n documentId: string,\n documentType: string,\n requestId: string,\n signal?: AbortSignal,\n ): Promise<PurgeMarkerOperation> {\n const action = purgeDocumentAction({ documentId, documentType, requestId });\n const signature = await this.signer.signAction(\n action,\n { documentId, branch: \"main\" },\n signal,\n );\n return purgeMarkerOperation({\n ...action,\n context: {\n signer: {\n ...actionSignerIdentity(this.signer),\n signatures: [signature],\n },\n },\n });\n }\n\n /** A stored document at a version this reactor does not run is read-only here. */\n private async unsupportedStoredProtocol(\n job: Job,\n stores: ExecutionStores,\n signal?: AbortSignal,\n ): Promise<Error | undefined> {\n let versions;\n try {\n // Read the way admission reads: with decisions on, execution bypasses the meta cache.\n versions =\n this.featureFlags.documentDecisions && job.kind !== \"load\"\n ? (\n await stores.writeCache.getState(\n job.documentId,\n \"document\",\n job.branch,\n undefined,\n signal,\n )\n ).header.protocolVersions\n : (\n await stores.documentMetaCache.getDocumentMeta(\n job.documentId,\n job.branch,\n signal,\n )\n ).protocolVersions;\n } catch {\n // Not stored yet, or unreadable: the job's own reads decide.\n return undefined;\n }\n return this.documentActionHandler.unsupportedProtocol(\n job.documentId,\n versions,\n );\n }\n\n /**\n * A successful mutation's result and the write-ready event it owes, carrying\n * what earlier attempts committed ahead of what this one wrote.\n */\n private async committedOutcome(\n job: Job,\n reloaded: OperationWithContext[],\n written: OperationWithContext[],\n generated: Operation[],\n stores: ExecutionStores,\n startTime: number,\n ): Promise<ScopeOutcome> {\n const operationsWithContext = [...reloaded, ...written];\n let pendingEvent: JobWriteReadyEvent | undefined;\n if (operationsWithContext.length > 0) {\n const collectionMemberships =\n await this.getCollectionMembershipsForOperations(\n operationsWithContext,\n stores,\n );\n pendingEvent = {\n jobId: job.id,\n operations: operationsWithContext,\n jobMeta: job.meta,\n submittedActionIds: submittedActionIds(job),\n collectionMemberships,\n };\n }\n\n return {\n result: {\n job,\n success: true as const,\n operations: [...reloaded.map((entry) => entry.operation), ...generated],\n operationsWithContext,\n duration: Date.now() - startTime,\n },\n pendingEvent,\n };\n }\n\n /**\n * The stored operations of writes an earlier attempt committed, as a fresh\n * write would report them. State is rebuilt from the write cache, and left\n * out when it cannot be.\n */\n private async reloadCommitted(\n writes: CommittedWrite[],\n stores: ExecutionStores,\n signal?: AbortSignal,\n ): Promise<OperationWithContext[]> {\n const streams = new Map<string, CommittedWrite[]>();\n for (const write of writes) {\n const key = `${write.documentId}\\u0000${write.scope}\\u0000${write.branch}`;\n streams.set(key, [...(streams.get(key) ?? []), write]);\n }\n\n const reloaded: OperationWithContext[] = [];\n for (const group of streams.values()) {\n const { documentId, scope, branch } = group[0];\n const opIds = [...new Set(group.map((write) => write.opId))];\n const operations = await stores.operationStore.getOperationsByIds(\n documentId,\n scope,\n branch,\n opIds,\n signal,\n );\n const ordinals = await stores.operationIndex.getOrdinalsByOpIds(\n documentId,\n scope,\n branch,\n opIds,\n signal,\n );\n const { documentType } = await stores.documentMetaCache.getDocumentMeta(\n documentId,\n branch,\n signal,\n );\n for (const operation of operations.sort((a, b) => a.index - b.index)) {\n reloaded.push({\n operation,\n context: {\n documentId,\n scope,\n branch,\n documentType,\n resultingState: await this.rebuiltState(\n stores,\n { documentId, scope, branch },\n operation,\n signal,\n ),\n ordinal: ordinals.get(operation.id) ?? 0,\n },\n });\n }\n }\n return reloaded;\n }\n\n private async rebuiltState(\n stores: ExecutionStores,\n stream: TouchedStream,\n operation: Operation,\n signal?: AbortSignal,\n ): Promise<string | undefined> {\n try {\n const document = await stores.writeCache.getState(\n stream.documentId,\n stream.scope,\n stream.branch,\n operation.index,\n signal,\n );\n return JSON.stringify({ ...document.state, header: document.header });\n } catch (error) {\n this.logger.warn(\n \"No state for committed operation @OperationId in @Stream: @Error\",\n operation.id,\n stream,\n error,\n );\n return undefined;\n }\n }\n\n /**\n * Drops the cached state of every stream a job wrote, after its transaction\n * did not commit.\n *\n * The caches are shared by reference with the copies the scope hands the job,\n * so a rollback undoes nothing in them: what the job put there survives, as\n * does anything a read filled from the store while the job's own writes were\n * still uncommitted. An eviction that throws is swallowed rather than allowed\n * to replace the failure the caller is owed, and the remaining streams are\n * still evicted.\n */\n private evictTouchedStreams(touchedStreams: TouchedStreams): void {\n for (const entry of touchedStreams) {\n try {\n this.writeCache.invalidate(entry.documentId, entry.scope, entry.branch);\n this.documentMetaCache.invalidate(entry.documentId, entry.branch);\n this.collectionMembershipCache.invalidate(entry.documentId);\n } catch (error) {\n this.logger.error(\n \"Failed to evict cached state for rolled back @Stream : @Error\",\n entry,\n error,\n );\n }\n }\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 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 if (this.config.batchApplies && this.canBatch(writes, executing)) {\n const batched = await this.executeRegularActionsBatched(\n writes,\n executing,\n );\n const error = this.accumulateResultOrReturnError(\n batched,\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 return { success: true, generatedOperations, operationsWithContext };\n }\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 /**\n * Decides a write and reduces it, without persisting anything.\n *\n * Split from the commit so one write and a batch of them share this logic\n * rather than keeping two copies of it. `baseDocument` lets a batch thread\n * the previous action's result forward instead of reading its own write back\n * out of the cache, which is the only reason the reduce has to be sequential.\n */\n private async prepareRegularWrite(\n write: PendingWrite,\n executing: ExecutingJob,\n baseDocument?: PHDocument,\n ): Promise<PreparedWrite | JobResult> {\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, carriedDocument: baseDocument }\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, and any operation carrying a skip need the full\n // operation history to replay state correctly: a skip rewinds the stream\n // past the operations it supersedes, so the base state is the one standing\n // before them, not the head. The write cache stores sliced documents (last\n // op per scope only), so invalidate before loading to force a cold-miss\n // rebuild.\n //\n // The skip is not always a NOOP's. A reshuffle hands its first re-appended\n // operation the whole skip, and that operation is whatever sorted first --\n // an ADD_FOLDER as readily as a NOOP. Reducing it against the sliced head\n // left the resulting state derived from the superseded lineage, which is\n // what the document view stores and serves; the write cache recovered on\n // its next cold read and the read model never did.\n if (isUndoRedo(action) || skip > 0) {\n stores.writeCache.invalidate(job.documentId, job.scope, job.branch);\n }\n\n let document: PHDocument;\n if (baseDocument !== undefined) {\n document = baseDocument;\n } else {\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\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 = withProtocolVersions(\n module.reducer(\n document as PHDocument,\n action,\n undefined,\n reducerOptions,\n ),\n document.header.protocolVersions,\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 // A peer's synthesized operation arrives signed and is admitted as is.\n if (\n deniedReason === undefined &&\n sourceOperation === undefined &&\n !executing.replayingAcceptedHistory &&\n isSynthesized(action, newOperation, document.operations[scope] ?? [])\n ) {\n try {\n await signSynthesized(\n newOperation,\n action,\n { documentId: job.documentId, scope, branch: job.branch },\n this.signer,\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 const resultingState = JSON.stringify({\n ...updatedDocument.state,\n header: updatedDocument.header,\n });\n\n return {\n action,\n sourceRemote,\n scope,\n document,\n updatedDocument,\n operation: newOperation,\n resultingState,\n appendCondition,\n denied: deniedReason !== undefined,\n };\n }\n\n /**\n * Persists a run of prepared writes in one store transaction.\n *\n * The store has always accepted many operations per apply; the executor only\n * ever handed it one. Passing the whole run means one advisory lock over the\n * read set and one guarded insert for the batch, instead of one of each per\n * operation.\n *\n * The append condition is taken from the first write. Every write in a run\n * reads the same streams at the same revisions, because nothing outside the\n * run can change them mid-batch, and the caller has already refused to batch\n * the scopes where that does not hold.\n */\n private async commitPreparedWrites(\n prepared: PreparedWrite[],\n executing: ExecutingJob,\n ): Promise<JobResult> {\n const { job, startTime, indexTxn, stores, signal } = executing;\n const first = prepared[0];\n const last = prepared[prepared.length - 1];\n const scope = first.scope;\n const documentType = first.document.header.documentType;\n const operations = prepared.map((write) => write.operation);\n\n // Recorded before the apply, not after: the rows an apply that throws left\n // behind are the ones a rollback has to take the cached state of with it.\n executing.touchedStreams.add(job.documentId, scope, job.branch);\n\n let storedOperations: Operation[];\n try {\n storedOperations = await stores.operationStore.apply(\n job.documentId,\n documentType,\n scope,\n job.branch,\n first.operation.index,\n (txn) => {\n txn.addOperations(...operations);\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 first.appendCondition,\n );\n } catch (error) {\n // The wrap that used to carry this phrase is gone, so the phrase lives\n // here: the error keeps its identity, the log keeps the context.\n this.logger.error(\n \"Failed to write operation to IOperationStore (@documentId @scope @branch): @Operation @Error\",\n job.documentId,\n scope,\n job.branch,\n operations,\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 // The original error, not a restringified one: the executor and the\n // job result handler classify by `name`, and a rewrap erases it.\n error:\n error instanceof Error\n ? error\n : new Error(\n `Failed to write operation to IOperationStore: ${String(error)}`,\n ),\n duration: Date.now() - startTime,\n };\n }\n\n const head = storedOperations[storedOperations.length - 1];\n\n last.updatedDocument.header.revision = {\n ...last.updatedDocument.header.revision,\n [scope]: head.index + 1,\n };\n\n // The whole run, not just its head: the cache keeps only the head as\n // state, but a run that writes past a keyframe boundary crossed it, and\n // handing over the head alone would skip every boundary between.\n stores.writeCache.putRun(\n job.documentId,\n scope,\n job.branch,\n storedOperations.map((operation, position) => ({\n revision: operation.index,\n document: prepared[position].updatedDocument,\n })),\n );\n\n indexTxn.write(\n storedOperations.map((operation, position) => ({\n ...operation,\n documentId: job.documentId,\n documentType,\n branch: job.branch,\n scope,\n sourceRemote: prepared[position].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 for (const write of prepared) {\n indexTxn.recordGroupReferences(\n job.documentId,\n mentionedGroupIds(write.action),\n );\n }\n }\n\n return {\n job,\n success: true,\n operations: storedOperations,\n operationsWithContext: storedOperations.map((operation, position) => ({\n operation,\n context: {\n documentId: job.documentId,\n scope,\n branch: job.branch,\n documentType,\n resultingState: prepared[position].resultingState,\n ordinal: 0,\n },\n })),\n duration: Date.now() - startTime,\n };\n }\n\n /**\n * Whether a job's writes may share one store transaction.\n *\n * Deliberately narrow. Batching changes only how many transactions the\n * operations arrive in, and every condition below is a case where that would\n * change something else as well:\n *\n * - A document-scope action goes through its own handler, which has its own\n * apply and its own reasons for it.\n * - A positional or replayed run carries skips and re-appended operations,\n * whose indices are not a simple ascending run from the head.\n * - UNDO, REDO and NOOP-with-skip each invalidate the write cache to\n * force a full-history rebuild, so they cannot be reduced against state\n * threaded from the write before them.\n * - The auth scope decides later writes against the policy earlier ones\n * install, so a batch would decide them all against the policy as it stood\n * before the batch.\n * - The document scope is read by every decision model, so writing it is\n * writing part of the read set; the per-write conditions would not agree.\n *\n * A run that fails any of these is executed one write at a time, unchanged.\n */\n private canBatch(writes: PendingWrite[], executing: ExecutingJob): boolean {\n if (writes.length < 2) {\n return false;\n }\n if (executing.evaluatedByPosition || executing.replayingAcceptedHistory) {\n return false;\n }\n const scope = executing.job.scope;\n if (scope === \"auth\" || scope === \"document\") {\n return false;\n }\n return writes.every((write) => {\n const type = write.action.type;\n return (\n write.skip === 0 &&\n write.deniedReason === undefined &&\n write.sourceOperation === undefined &&\n !DOCUMENT_SCOPE_ACTIONS.has(type) &&\n !isUndoRedo(write.action) &&\n type !== \"NOOP\"\n );\n });\n }\n\n /**\n * Decides and reduces a run of writes, then persists them together.\n *\n * The reduce stays sequential - each action needs the state the one before it\n * produced - but the result is threaded in memory rather than read back from\n * the cache, and the whole run reaches the store in a single apply.\n *\n * A write that turns out to be denied abandons the batch and replays the run\n * one write at a time, because a denied write holds a position of its own and\n * that is the path where the per-write behaviour is load-bearing. A write\n * that cannot be prepared fails the job outright: preparing is a read, so the\n * replay would only reach the same failure, and the job leaves nothing behind\n * either way.\n */\n private async executeRegularActionsBatched(\n writes: PendingWrite[],\n executing: ExecutingJob,\n ): Promise<JobResult> {\n const prepared: PreparedWrite[] = [];\n let carried: PHDocument | undefined;\n let lastYield = performance.now();\n\n for (const write of writes) {\n const outcome = await this.prepareRegularWrite(write, executing, carried);\n if (\"success\" in outcome) {\n return outcome;\n }\n if (outcome.denied) {\n return this.executeRegularActionsSequentially(writes, executing);\n }\n prepared.push(outcome);\n carried = outcome.updatedDocument;\n\n if (performance.now() - lastYield > this.config.yieldDeadlineMs) {\n await yieldToMain();\n lastYield = performance.now();\n\n if (executing.signal?.aborted) {\n return buildErrorResult(\n executing.job,\n new Error(\"Aborted\"),\n executing.startTime,\n );\n }\n }\n }\n\n // Every write in the run must have read the same streams at the same\n // revisions for one condition to stand for all of them. canBatch excludes\n // the scopes where that can fail, and this is the assertion of it: a\n // mismatch falls back rather than writing under a condition that only\n // describes part of the batch.\n if (!this.conditionsAgree(prepared)) {\n return this.executeRegularActionsSequentially(writes, executing);\n }\n\n return this.commitPreparedWrites(prepared, executing);\n }\n\n /** Whether every prepared write carries the same read-set condition. */\n private conditionsAgree(prepared: PreparedWrite[]): boolean {\n const shape = (write: PreparedWrite): string =>\n write.appendCondition === undefined\n ? \"none\"\n : JSON.stringify(\n [...write.appendCondition.streams]\n .map((stream) => [\n stream.documentId,\n stream.scope,\n stream.branch,\n stream.revision,\n ])\n .sort(),\n );\n const first = shape(prepared[0]);\n return prepared.every((write) => shape(write) === first);\n }\n\n /**\n * The unbatched path, for a run that turned out not to qualify after its\n * writes were prepared. Nothing has been persisted at that point, so\n * replaying the whole run per write is safe.\n */\n private async executeRegularActionsSequentially(\n writes: PendingWrite[],\n executing: ExecutingJob,\n ): Promise<JobResult> {\n const operations: Operation[] = [];\n const contexts: OperationWithContext[] = [];\n let lastYield = performance.now();\n\n for (const write of writes) {\n const result = await this.executeRegularAction(write, executing);\n if (!result.success) {\n return result;\n }\n operations.push(...(result.operations ?? []));\n contexts.push(...(result.operationsWithContext ?? []));\n\n if (performance.now() - lastYield > this.config.yieldDeadlineMs) {\n await yieldToMain();\n lastYield = performance.now();\n\n if (executing.signal?.aborted) {\n return buildErrorResult(\n executing.job,\n new Error(\"Aborted\"),\n executing.startTime,\n );\n }\n }\n }\n\n return {\n job: executing.job,\n success: true,\n operations,\n operationsWithContext: contexts,\n duration: Date.now() - executing.startTime,\n };\n }\n\n /** Decides, reduces and persists one write. */\n private async executeRegularAction(\n write: PendingWrite,\n executing: ExecutingJob,\n ): Promise<JobResult> {\n const prepared = await this.prepareRegularWrite(write, executing);\n if (\"success\" in prepared) {\n return prepared;\n }\n return this.commitPreparedWrites([prepared], executing);\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 const nothingToMove = async (): Promise<PositionedWrites> => {\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 if (conflicting.length === 0) {\n return nothingToMove();\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 // The conflicting rows are not what the stream applies. An earlier reshuffle\n // leaves the operations it retracted next to their re-appended copies, and its\n // own backdated write, older than this one, sits between them. So re-append\n // what the stream still applies from the first conflicting operation on,\n // whatever its timestamp, and nothing a skip has already retracted.\n const stored = (\n await stores.operationStore.getSince(\n job.documentId,\n job.scope,\n job.branch,\n firstConflicting - 1,\n undefined,\n undefined,\n signal,\n )\n ).results;\n const conflictingIds = new Set(\n conflicting.map((operation) => operation.id),\n );\n const effective = garbageCollect(sortOperations(stored)).filter(\n (operation) => !isGenesisOperation(operation),\n );\n const firstMoving = effective.findIndex((operation) =>\n conflictingIds.has(operation.id),\n );\n const moving = firstMoving === -1 ? [] : effective.slice(firstMoving);\n\n if (moving.length === 0) {\n return nothingToMove();\n }\n\n // A moving operation that heads an earlier reshuffle retracts what sits below\n // it. Retracting that operation without reaching as far would bring those back.\n let firstRetracted = moving[0].index;\n for (const operation of moving) {\n firstRetracted = Math.min(\n firstRetracted,\n operation.index - operation.skip,\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, firstRetracted) },\n moving,\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:\n i === 0\n ? retractionSkip(nextIndex, tail[0].index - tail[0].skip)\n : 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 // Reselected after a drop, so a refused operation cannot widen the window.\n const dropped = new Set<Operation>();\n const admitted = new Set<Operation>();\n let selection = await this.selectLoadWrites(\n job,\n job.operations,\n stores,\n signal,\n );\n for (;;) {\n const unadmitted = selection.incomingOpsToApply.filter(\n (operation) => !admitted.has(operation),\n );\n if (unadmitted.length === 0) {\n break;\n }\n\n let refused: Set<Operation>;\n try {\n refused = await this.signatureAdmission.admitLoad(\n job,\n unadmitted,\n stores,\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 for (const operation of unadmitted) {\n if (refused.has(operation)) {\n dropped.add(operation);\n } else {\n admitted.add(operation);\n }\n }\n if (refused.size === 0) {\n break;\n }\n\n const remaining = job.operations.filter(\n (operation) => !dropped.has(operation),\n );\n if (remaining.length === 0) {\n return {\n job,\n success: true,\n operations: [],\n operationsWithContext: [],\n duration: Date.now() - startTime,\n };\n }\n selection = await this.selectLoadWrites(job, remaining, stores, signal);\n }\n\n const {\n nonSupersededOps,\n allOpsFromMinConflictingIndex,\n incomingOpsToApply,\n } = selection;\n\n // Before costing the reshuffle: a re-delivery of held operations moves nothing.\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 // 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 // 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 // A NOOP is the v2 undo marker, and it is only a marker while its skip is\n // positive: the state rebuild reads the flag, not the count. A reshuffle\n // hands its whole skip to whichever operation sorts first and zeroes every\n // other one, so the zeroed NOOPs have to be given theirs back or they stop\n // undoing anything.\n //\n // Not the first one. Its skip spans the operations the reshuffle retired,\n // and a NOOP sorts first as readily as anything else does - it has no rank\n // of its own, so the earliest timestamp wins. Overwriting it with 1 leaves\n // the operations it was meant to supersede standing, which reads them back\n // into the next reshuffle and drives the cost toward the excessive-\n // reshuffle limit. Peers get the shortened skip too, and compute a\n // different superseded set than the reactor that sent it.\n const incomingIds = new Set(\n incomingOpsToApply.map((operation) => operation.action.id),\n );\n for (const operation of reshuffledOperations) {\n // A local NOOP's target stays behind; a skip would undo another operation.\n if (\n operation.action.type === \"NOOP\" &&\n operation.skip === 0 &&\n incomingIds.has(operation.action.id)\n ) {\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 /** The conflicting window a load opens, and which of its operations are new. */\n private async selectLoadWrites(\n job: Job,\n operations: Operation[],\n stores: ExecutionStores,\n signal?: AbortSignal,\n ): Promise<{\n nonSupersededOps: Operation[];\n allOpsFromMinConflictingIndex: Operation[];\n incomingOpsToApply: Operation[];\n }> {\n const scope = job.scope;\n\n let minIncomingIndex = Number.POSITIVE_INFINITY;\n let minIncomingTimestamp = operations[0]?.timestampUtcMs || \"\";\n for (const operation of 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(operations.map((op) => op.action.id));\n\n // The nearest later operation whose skip reaches `op`, if any.\n const supersededBy = (op: Operation): Operation | undefined => {\n let nearest: Operation | undefined;\n for (const laterOp of allOpsFromMinConflictingIndex) {\n if (\n laterOp.index > op.index &&\n laterOp.skip > 0 &&\n laterOp.index - laterOp.skip <= op.index &&\n (nearest === undefined || laterOp.index < nearest.index)\n ) {\n nearest = laterOp;\n }\n }\n return nearest;\n };\n\n // Held only in superseded rows: undone stays undone, rewound is re-applied.\n const undoneActionIds = new Set<string>();\n let predecessorBound = minIncomingIndex;\n const rowsByActionId = new Map<string, Operation[]>();\n for (const op of conflictingOps) {\n if (incomingActionIds.has(op.action.id)) {\n rowsByActionId.set(op.action.id, [\n ...(rowsByActionId.get(op.action.id) ?? []),\n op,\n ]);\n }\n }\n const liveOps = new Set<Operation>();\n for (const op of conflictingOps) {\n if (supersededBy(op) === undefined) {\n liveOps.add(op);\n }\n }\n for (const [actionId, rows] of rowsByActionId) {\n if (rows.some((row) => liveOps.has(row))) {\n continue;\n }\n if (rows.some((row) => supersededBy(row)?.action.type === \"NOOP\")) {\n undoneActionIds.add(actionId);\n } else {\n predecessorBound = Math.min(\n predecessorBound,\n Math.max(...rows.map((row) => row.index)),\n );\n }\n }\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 < predecessorBound && !incomingActionIds.has(op.action.id)) {\n return false;\n }\n return liveOps.has(op);\n });\n\n // The skip rewinds from here, so each live row from here goes back.\n let rewoundFrom = Number.POSITIVE_INFINITY;\n for (const op of nonSupersededOps) {\n if (!isGenesisOperation(op)) {\n rewoundFrom = Math.min(rewoundFrom, op.index - op.skip);\n }\n }\n const reappended = new Set(nonSupersededOps.map((op) => op.index));\n for (const op of allOpsFromMinConflictingIndex) {\n if (\n op.index >= rewoundFrom &&\n !reappended.has(op.index) &&\n supersededBy(op) === undefined\n ) {\n nonSupersededOps.push(op);\n }\n }\n\n const existingActionIds = new Set(\n nonSupersededOps.map((op) => op.action.id),\n );\n const seenIncomingActionIds = new Set<string>();\n const incomingOpsToApply = operations.filter((op) => {\n if (existingActionIds.has(op.action.id)) return false;\n if (undoneActionIds.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 return {\n nonSupersededOps,\n allOpsFromMinConflictingIndex,\n incomingOpsToApply,\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","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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"}
|