@helipod/runtime-embedded 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime.ts","../src/write-fanout.ts","../src/loopback.ts","../src/client-dedup.ts"],"sourcesContent":["/**\n * `EmbeddedRuntime` — the Tier 0 engine in one process. It wires DocStore + transactor +\n * query engine + executor + sync handler together, drives the transactor→sync fan-out seam,\n * and hands out in-process loopback connections an unmodified client can talk to. This is the\n * core a single binary (`bun build --compile`) ships.\n *\n * Storage is injected (a `DocStore`), so the runtime is storage- and runtime-agnostic — the\n * CLI picks `BunSqliteAdapter` or `NodeSqliteAdapter`.\n */\nimport { namespaceForPath, type Driver, type DriverContext, type LogChange, type WakeHost } from \"@helipod/component\";\nimport { FunctionNotFoundError } from \"@helipod/errors\";\nimport { decodeStorageTableId, decodeDocumentId, encodeInternalDocumentId, shardIdForKeyValue, DEFAULT_SHARD, type ShardId } from \"@helipod/id-codec\";\nimport { writtenTablesFromRanges, serializeKeyRange, type SerializedKeyRange } from \"@helipod/index-key-codec\";\nimport { jsonToConvex, convexToJson, type JSONValue, type Value } from \"@helipod/values\";\nimport type { DocStore, DocumentLogEntry } from \"@helipod/docstore\";\nimport { MonotonicTimestampOracle } from \"@helipod/docstore\";\nimport { SingleWriterTransactor, ShardedTransactor } from \"@helipod/transactor\";\nimport { QueryRuntime } from \"@helipod/query-engine\";\nimport { InlineUdfExecutor, mutation, type GuestDatabaseWriter, type ContextProvider, type IndexCatalog, type LogSink, type RegisteredFunction, type UdfResult, type PolicyContextProvider, type TablePolicy, type RelationRegistry, type WriteRouter } from \"@helipod/executor\";\nimport { SyncProtocolHandler, type SyncUdfExecutor, type RunMutationResult, type MutationReplay, type ClientMutationVerdict } from \"@helipod/sync\";\nimport {\n EmbeddedWriteFanout,\n InMemoryWriteFanoutAdapter,\n type EmbeddedWriteFanoutAdapter,\n} from \"./write-fanout\";\nimport { createLoopbackConnection, type LoopbackConnection } from \"./loopback\";\nimport {\n classifyDedup,\n classifyForConnect,\n clientReceiptsGuard,\n dedupCommitMeta,\n fillWriteMutationValue,\n handleDedupError,\n recordZeroWriteApplied,\n type DedupKey,\n} from \"./client-dedup\";\nimport type { ClientReplay } from \"@helipod/executor\";\n\n/**\n * The `persistence_globals` key the deployment id is stamped under — reused verbatim from\n * `@helipod/fleet`'s `FLEET_DEPLOYMENT_ID_KEY` (core has no static dep on the enterprise package,\n * so the literal is duplicated, not imported). Both stamp with `writeGlobalIfAbsent` (first-wins), so\n * a fleet + non-fleet boot against the same store agree on one id. Powers `ConnectAck.deploymentId`\n * (the same-timeline proof, verdict §(g) hazard 15).\n */\nconst DEPLOYMENT_ID_GLOBAL_KEY = \"fleet:deploymentId\";\n\n/**\n * Public-gate check: a path is internal (client-forbidden) if ANY colon-delimited segment\n * starts with `_` — not just the whole path. `path.startsWith(\"_\")` alone misses namespaced\n * component-internal paths like `scheduler:_enqueue` (the string starts with \"s\"), letting a\n * raw client dispatch privileged jobs directly. Blocks `_system:*`/`_admin:*` too (those have\n * their own privileged/trusted entrypoints — `runSystem`/`runAdmin` — and must stay off this\n * public surface). Do NOT use this to gate `invoke` (trusted server re-entrancy for actions'\n * ctx.runQuery/runMutation/runAction) or the driver's `runFunction` — both MUST still reach\n * `_`-prefixed modules.\n */\nfunction isInternalPath(path: string): boolean {\n return path.split(\":\").some((seg) => seg.startsWith(\"_\"));\n}\n\n/**\n * Single source of truth for building the tableNumber→name map (`fullTableName → tableNumber`\n * inverted) — used both by `create()` (seeding the map before the instance exists) and by the\n * instance method `setTableNumbers` (rebuilding it after an additive deploy), so the two never\n * drift by duplicating the loop.\n */\nfunction rebuildTableNumberToName(map: Map<number, string>, tableNumbers: Record<string, number>): void {\n map.clear();\n for (const [name, num] of Object.entries(tableNumbers)) map.set(num, name);\n}\n\n/** Map a JSON-friendly {@link ClientReplay} (from the classification pre-read or a forwarded owner's\n * replay) to the sync tier's `Value`-typed `MutationReplay` — the only conversion point where the\n * recorded `JSONValue` becomes a runtime `Value`. */\nfunction replayToRunResult(replay: ClientReplay): RunMutationResult {\n const out: MutationReplay = { replayed: true, verdict: replay.verdict };\n if (replay.commitTs !== undefined) out.commitTs = replay.commitTs;\n if (replay.value !== undefined) out.value = jsonToConvex(replay.value) as Value;\n if (replay.valueMissing) out.valueMissing = true;\n if (replay.code !== undefined) out.code = replay.code;\n return out;\n}\n\n/** The payload shape `DriverContext.onCommit` callbacks receive (same shape as\n * `@helipod/component`'s `DriverContext[\"onCommit\"]` parameter — kept as a local alias here\n * rather than importing it, since the interface only inlines the object type). */\ntype CommitEvent = { tables: string[]; ranges: readonly SerializedKeyRange[]; commitTs: number };\n\n/**\n * Translates a commit payload's ENCODED STORAGE-TABLE IDS (e.g. `\"3\"`, `decodeStorageTableId`'s\n * input) into full table names (e.g. `\"scheduler/jobs\"`) via `tableNumberToName` — drivers filter\n * `inv.tables` by full name (e.g. `t.startsWith(\"scheduler/\")`), so both the local commit fan-out\n * (`adapter.subscribe`'s callback, in `create()`) and a foreign fleet commit\n * (`notifyExternalCommit`, below) must translate identically before firing `commitSubs`. Shared\n * so the two paths can never drift. An id that fails to decode (not a recognized storage-table id\n * shape) passes through unchanged rather than being dropped.\n */\nfunction translateTableIds(tableIds: readonly string[], tableNumberToName: ReadonlyMap<number, string>): string[] {\n return tableIds.map((id) => {\n try {\n return tableNumberToName.get(decodeStorageTableId(id)) ?? id;\n } catch {\n return id; // not a decodable storage id — pass through rather than drop\n }\n });\n}\n\n/**\n * Fires every registered driver `onCommit` subscriber with the same commit event, isolating one\n * throwing/rejecting callback from starving the rest (a driver's `onCommit` must never prevent\n * another driver from seeing the commit signal — see the try/catch below).\n */\nfunction fireCommitSubs(commitSubs: ReadonlySet<(inv: CommitEvent) => void>, inv: CommitEvent): void {\n for (const cb of commitSubs) {\n try {\n cb(inv);\n } catch (e) {\n console.error(\"[runtime] driver onCommit callback threw:\", e);\n }\n }\n}\n\n/**\n * Fleet write-routing seam (Tier 2), PER-SHARD. Defined in `@helipod/executor` (where the\n * per-shard forward chokepoint on `ExecutorDeps.writeRouter` references it, avoiding a circular dep\n * back to this package) and re-exported here as the core seam `@helipod/fleet` implements. A node\n * that doesn't own a mutation's resolved shard forwards it to that shard's owner; queries are never\n * routed. Actions still forward wholesale at the runtime level (below) to the default-shard holder —\n * an action's INNER mutations then route per-shard from wherever the action runs. See\n * `InlineUdfExecutor.run`'s routing hook.\n */\nexport type { WriteRouter, ClientReplay } from \"@helipod/executor\";\n\nexport interface EmbeddedRuntimeOptions {\n store: DocStore;\n catalog: IndexCatalog;\n modules: Record<string, RegisteredFunction>;\n /** Privileged built-in functions (`_system:*`). Kept off the public run/sync surface. */\n systemModules?: Record<string, RegisteredFunction>;\n /** Privileged admin functions (`_admin:*`). Served over the admin sync channel. */\n adminModules?: Record<string, RegisteredFunction>;\n /** Validate an admin key presented via `SetAdminAuth`. Defaults to `() => false`. */\n verifyAdmin?: (key: string) => boolean;\n /** Set of component names; used to resolve the namespace for each function path. */\n componentNames?: ReadonlySet<string>;\n /** Swap the Tier 0 in-memory fan-out for a cross-process adapter (no app-code change). */\n fanoutAdapter?: EmbeddedWriteFanoutAdapter;\n originId?: string;\n logSink?: LogSink;\n /** Context providers contributed by composed components; attached as ctx[name] on every function call. */\n contextProviders?: ReadonlyArray<ContextProvider>;\n /** Row-policy registry contributed by components; enforced on every non-privileged run. */\n policyRegistry?: ReadonlyMap<string, TablePolicy>;\n /** Policy context providers contributed by components; used to build rule context for row policies. */\n policyProviders?: ReadonlyArray<PolicyContextProvider>;\n /** Declared relations, consulted by the kernel when resolving relation predicates. */\n relationRegistry?: RelationRegistry;\n /** Wall-clock source; defaults to `Date.now`. Injected for deterministic testing. */\n now?: () => number;\n /**\n * The host's single alarm, for a host that STOPS THE PROCESS between requests (Cloudflare\n * Containers: stopped ~5s after the last incoming request; internal timer activity does not keep\n * it alive, so `setTimeout` silently never fires and every driver goes dead). Set → this runtime\n * multiplexes every live driver timer down to ONE pending wake and hands the minimum to\n * `armWake`; the host is then the SOLE thing that fires them, via `fireDueTimers()` (the engine\n * arms no `setTimeout` of its own — two schedulers would double-fire the same callback).\n *\n * UNSET (the default, and every existing deployment — Docker/VPS/Fly/Railway/single-binary): the\n * plain `setTimeout` path below, byte-for-byte unchanged.\n */\n wakeHost?: WakeHost;\n /**\n * Answers `DriverContext.backstopMs` — a driver's declared cadence for a PURE BACKSTOP poll\n * (scheduler lease-reclaim sweep, triggers beat, storage reaper). Defaults to IDENTITY (the\n * driver's own 30s/60s constants, unchanged). A host where every wake costs a cold start stretches\n * it: on Cloudflare a 30s backstop is a container boot every 30s forever — a ~15% duty cycle for a\n * completely idle app, which would destroy scale-to-zero.\n */\n backstopMs?: (defaultMs: number) => number;\n /**\n * Disarm the sync handler's process-shaped background timers (its `setInterval` flush/resume sweep\n * and every per-session ping heartbeat). Defaults to `false` — every long-lived process host is\n * byte-for-byte unchanged. Set ONLY by the Cloudflare Durable Object host (Slice 3), where those\n * timers are actively harmful (a `setInterval` is lost on hibernation; an app-level ping would wake\n * the hibernated object every beat, defeating scale-to-zero). Just a boolean — no host type crosses\n * this seam. See `SyncProtocolHandlerOptions.disableBackgroundTimers`.\n */\n disableSyncBackgroundTimers?: boolean;\n /** Component boot steps to run once at create, namespaced + non-user (before serving traffic). */\n bootSteps?: { name: string; run: (ctx: { db: GuestDatabaseWriter; now: number }) => Promise<void> }[];\n /** Component drivers to start once at create, after boot steps + the commit fan-out are wired. */\n drivers?: Driver[];\n /**\n * `fullTableName → tableNumber` (the same map `composeComponents`/`loadProject` produce).\n * Used ONLY to translate the encoded storage-table ids on `adapter.subscribe`'s commit payload\n * (e.g. `\"3\"`) back into full names (e.g. `\"scheduler/jobs\"`) before handing them to driver\n * `onCommit` callbacks — drivers filter `inv.tables` by name (see `components/scheduler/src/\n * driver.ts`), and a raw storage id never matches. Optional: a runtime with no components (or\n * whose drivers don't inspect `inv.tables`) can omit it and driver callbacks just see raw ids.\n */\n tableNumbers?: Record<string, number>;\n /**\n * Route mutations/actions to another node instead of executing them locally, when\n * `writeRouter.isLocalWriter()` is false. Applies to EVERY mutation/action entry point (the\n * WS `syncExecutor.runMutation`/`runAction` and the public `run`/`runAction` methods) —\n * queries are never routed. See `WriteRouter`.\n */\n writeRouter?: WriteRouter;\n /**\n * Skip starting component drivers at `create()` time; call the returned instance's\n * `startDrivers()` later instead. For a fleet node that boots as a non-writer and only\n * wants drivers running once/if it becomes the writer.\n */\n deferDrivers?: boolean;\n /**\n * Receipted Outbox — receipts-guard ownership handoff (the promotion-barrier hole). Normally\n * `create()` registers the `clientReceiptsGuard()` exactly-once barrier on `options.store` here at\n * construction, because for every non-fleet deployment `options.store` IS the concrete store its\n * commits land on. A fleet SYNC node is the exception: `options.store` is a `SwitchableDocStore`\n * over the read-only replica, and on writer promotion the runtime store is swapped to the concrete\n * Postgres store WITHOUT re-forwarding registered commit guards (by `SwitchableDocStore`'s\n * documented design) — so a guard registered here would silently vanish on promotion, and a\n * promoted single-writer node's client mutations would commit with NO receipt (dedup miss → a\n * resent (clientId, seq) re-executes). When this is set, `create()` SKIPS its own registration and\n * the caller (fleet's `armWriter`) owns installing the receipts guard on the CONCRETE write store —\n * BEFORE the epoch fence, with the same release-on-re-arm discipline the fence uses. Ownership rule:\n * whoever owns the concrete store owns the receipts guard. Unset → the runtime owns it (today's\n * behavior, byte-identical for every non-fleet deployment). See `ee/fleet`'s `armWriter`.\n */\n externalReceiptsGuard?: boolean;\n /**\n * Number of shards to run (Shards B2a). When `> 1`, the runtime builds ONE `ShardedTransactor`\n * (N independent per-shard mutexes + OCC rings + oracles) over the store instead of the\n * single-shard `SingleWriterTransactor`, so mutations routed to different shards commit in\n * parallel. Unset / `1` → the single-shard transactor, byte-identical to before (the existing\n * suites are the proof). The executor resolves each mutation's shard (`shardBy`) and passes it\n * through `runInTransaction({ shardId })`; a fleet writer pairs this with the per-shard commit\n * pool so different shards' commits are genuinely concurrent Postgres transactions.\n */\n numShards?: number;\n /**\n * Fleet B4 (group commit): route commits through the two-buffer stage-then-flush committer loop\n * instead of the byte-identical single-commit path. Threaded straight into the transactor\n * (`ShardedTransactor`/`SingleWriterTransactor`) constructed below — every shard batches when this\n * is set, none do when it's unset/false. The CLI resolves this from `HELIPOD_GROUP_COMMIT`\n * (default OFF at Fleet B4/T4 — T5 owns flipping the production default); leaving it unset keeps a\n * non-fleet / flag-off deployment structurally on today's path, byte-identical to before this\n * option existed. See `ShardedTransactorOptions.groupCommit`'s doc comment for the mechanism.\n */\n groupCommit?: boolean;\n /**\n * Hybrid-node split-read seam (Fleet B3, D1). When set, `create()` builds a SECOND, separate\n * query-path transactor (`SingleWriterTransactor` — queries never commit, so no sharding is\n * needed here regardless of the write side) + `QueryRuntime` over this store, seeded from ITS\n * OWN `maxTimestamp()` (not the write store's) and wired onto `ExecutorDeps.queryPath`, so\n * `fn.type === \"query\"` runs against `queryStore` instead of `store`. Its oracle is advanced\n * ONLY by `observeTimestamp` (see below) — never by this runtime's own local commits, which\n * only ever land on the WRITE store. Unset → `queryPath` is never built; every query runs\n * against `store` through the primary pair, byte-identical to before this option existed.\n */\n queryStore?: DocStore;\n /**\n * M2b: the D1 store for `.global()` tables, pre-built by the boot layer (which holds\n * `schemaJson`). Mirrors the `queryStore` precedent above — handed in already-constructed,\n * not built inside `create()`. Threaded straight into `ExecutorDeps.globalStore`. Absent →\n * `.global()` ops fail fast in the kernel (`requireGlobalTxn`), byte-identical to before this\n * option existed. NOT `DocStore`-shaped; it never enters a transactor/`QueryRuntime`.\n */\n globalStore?: import(\"@helipod/docstore-d1\").D1DocStore;\n /**\n * The AUTHORITATIVE receipts store for the `Connect` resume handshake — where the outbox verdict\n * classification (`classifyClientMutation`) and ack-prune (`pruneClientMutations`) reads/writes\n * land (verdict §(c): \"the classification read runs where the commit runs... never against a\n * follower's embedded replica\"). The `client_mutations`/`client_floors` receipts tables are NOT\n * part of the replicated MVCC document log — they live ONLY on the authoritative primary. On a\n * fleet SYNC node, `options.store` is a `SwitchableDocStore` over the read-only replica, which\n * carries NONE of those receipts: classifying a committed seq there returns `unknown` for every\n * lookup, so the handshake spuriously reports `known:false` (a reset that re-mints the clientId)\n * and — worse — a kill-after-commit reload via a sync node reports a FALSE failure for a mutation\n * that actually committed. Set this to the primary Postgres store so the handshake reads/prunes the\n * real receipts. Safe from a read-only-until-promoted primary: `getClientVerdict` is a pure read\n * and `pruneClientMutations` is a monotonic (`GREATEST`-floored) direct query on standalone,\n * unsharded receipt tables — architecturally identical to what the WRITER's own handshake does\n * outside the OCC transactor, needing no advisory lock or write-forward hop. Unset → the handshake\n * uses `options.store` (byte-identical for every non-fleet/writer deployment, whose `store` IS the\n * primary; the mutation-path dedup already places its own classification on the owner via\n * `writeRouter`, so only the Connect handshake needed this seam). See `ee/fleet`'s sync boot.\n */\n receiptsStore?: DocStore;\n /**\n * Hybrid-node RYOW gate (Fleet B3, D2). Awaited in the runtime's serial fan-out `drain()`\n * BEFORE each queued invalidation's `handler.notifyWrites` — e.g. a hybrid node's\n * `tailer.waitFor(commitTs)`, so a locally-committed mutation's subscription re-runs don't fire\n * against a replica that hasn't applied that commit yet. A rejection is caught and logged; the\n * drain loop continues to the next queued invalidation rather than wedging the whole queue on\n * one bad wait. Unset → `drain()` is byte-identical to before this hook existed.\n */\n beforeNotify?: (commitTs: bigint) => Promise<void>;\n /**\n * The stable-prefix accessor for `DriverContext.readLog` (triggers D1). Returns the highest log\n * timestamp below which the log is GAP-FREE — the upper bound `readLog` scans to. Non-null ONLY in\n * a fleet, where N per-shard commit connections land timestamps out of order (a scan can see ts 10\n * while ts 9 is still in flight), so the bound must be `min(shard_leases.frontier_ts)` — the fleet\n * node wires it to exactly that. A `null` return (or an unset accessor) means \"no fleet gap\": every\n * non-fleet topology commits over one serialized session (SQLite's single connection; the single\n * PINNED Postgres connection — the commit pool is fleet-only), so `readLog` falls back to\n * `store.maxTimestamp()`. Consulted per `readLog` call; only ever invoked on the default-shard\n * holder by the driver lifecycle.\n */\n stablePrefix?: () => Promise<bigint | null>;\n}\n\n/** The minimal timestamp-observer seam `observeTimestamp` delegates to — a `MonotonicTimestampOracle`\n * (single-shard) or a `ShardedTransactor` (which fans a learned ts to every shard oracle). */\ninterface TimestampObserver {\n observeTimestamp(ts: bigint): void;\n}\n\n/**\n * One live `DriverContext.setTimer` handle. `atMs` is retained (not just handed to `setTimeout`)\n * because the wake seam multiplexes every live timer down to the ONE alarm a host offers — that\n * needs `min(atMs)`, which a `setTimeout` handle can't be asked for. `timeout` is set only on the\n * default (no `wakeHost`) path; under a host, the host fires them via `fireDueTimers()`.\n */\ninterface DriverTimer {\n atMs: number;\n cb: () => void;\n timeout?: ReturnType<typeof setTimeout>;\n}\n\nexport class EmbeddedRuntime {\n private sessionCounter = 0;\n\n private constructor(\n readonly store: DocStore,\n readonly executor: InlineUdfExecutor,\n readonly handler: SyncProtocolHandler,\n readonly writeFanoutAdapter: EmbeddedWriteFanoutAdapter,\n private readonly modules: Record<string, RegisteredFunction>,\n private readonly systemModules: Record<string, RegisteredFunction>,\n private readonly adminModules: Record<string, RegisteredFunction>,\n private readonly componentNames: ReadonlySet<string>,\n private readonly contextProviders: ReadonlyArray<ContextProvider>,\n private readonly policyRegistry: ReadonlyMap<string, TablePolicy>,\n private readonly policyProviders: ReadonlyArray<PolicyContextProvider>,\n private readonly relationRegistry: RelationRegistry | undefined,\n private readonly drivers: ReadonlyArray<Driver>,\n private readonly timers: Map<number, DriverTimer>,\n /** Threaded from `create()` (like `driverCtx`) so the public `fireDueTimers()` below runs against\n * the SAME timer map + wake-arming closures the `DriverContext` writes to. */\n private readonly fireDue: () => void,\n /**\n * Inverse of `tableNumbers` (tableNumber → fullTableName). Mutable (not `readonly`) so\n * `setTableNumbers` can rebuild it in place after an additive deploy — the very same `Map`\n * object `create()`'s `namesForCommit` closure captured, so mutating it here (rather than\n * reassigning the field) keeps that closure correct without any circular-reference dance.\n */\n private tableNumberToName: Map<number, string>,\n /** The WRITE transactor's timestamp observer (the single-shard oracle, or the\n * `ShardedTransactor` itself). `observeTimestamp` delegates to this UNLESS `queryOracle` is\n * set (see it below) — this oracle's own local commits always advance it directly via\n * `ShardWriter.commit`'s `oracle.publishCommitted`; `observeTimestamp` is the SEPARATE\n * fleet-follower/tailer-observation channel, which a hybrid node must NOT point back at the\n * write oracle (D1 — own local commits must never advance the query oracle, and observed\n * foreign timestamps must never advance the write oracle either, once a hybrid has a real\n * query-path oracle of its own). */\n private readonly oracle: TimestampObserver,\n /** Fleet B3 (D1): the QUERY-path oracle, set only when `EmbeddedRuntimeOptions.queryStore` was\n * configured. When set, `observeTimestamp` routes to THIS oracle instead of `oracle` — its\n * purpose is tailer post-apply feeding (a hybrid node's replica-backed query snapshot rises\n * only as the tailer confirms applied writes), never this runtime's own local commits (those\n * land on the write store and advance `oracle` directly, as shipped). Undefined when\n * `queryStore` is unset → `observeTimestamp` keeps the exact shipped write-oracle routing. */\n private readonly queryOracle: TimestampObserver | undefined,\n /** The write path — retained so a fleet writer can take a shard's commit mutex non-blockingly\n * (`tryRunExclusiveOnShard`) to close idle frontiers without racing that shard's own commits. */\n private readonly transactor: SingleWriterTransactor | ShardedTransactor,\n /** Threaded from `create()` so `startDrivers()` can start deferred drivers later. */\n private readonly driverCtx: DriverContext,\n /** Mutable: false when `deferDrivers` was set and `startDrivers()` hasn't run yet. */\n private driversStarted: boolean,\n /** When set and `isLocalWriter()` is false, every mutation/action entry point forwards\n * through it instead of executing locally. Queries never consult this. */\n private readonly writeRouter: WriteRouter | undefined,\n /** Shards B2a (T5): the SAME resolved count `create()` used to build the transactor and every\n * closure's `RunOptions.numShards` — instance methods (`run`/`runAction`/`runHttpAction`/\n * `runSystem`/`runAdmin`) thread it through here so a call made AFTER construction routes\n * identically to one made during `create()`. Defaults to 1 (byte-identical to before) when\n * `EmbeddedRuntimeOptions.numShards` is unset. */\n private readonly numShards: number,\n /** The SAME catalog the executor/kernel enforce ownership against — so `runSystem`'s privileged\n * doc-mutation routing (`resolveDocMutationShard`) reads a table's `shardKey` from the exact\n * source of truth the guards use, and can never disagree with them. */\n private readonly catalog: IndexCatalog,\n /** The SAME `commitSubs` set `create()`'s `adapter.subscribe` callback fires on every LOCAL\n * commit — also fired by `notifyExternalCommit` (below) for a FOREIGN (fleet) commit, so a\n * driver's `onCommit` wakes on both without the two paths ever drifting on which set they\n * target. */\n private readonly commitSubs: ReadonlySet<(inv: CommitEvent) => void>,\n ) {}\n\n static async create(options: EmbeddedRuntimeOptions): Promise<EmbeddedRuntime> {\n await options.store.setupSchema();\n // Register the client-mutation receipts guard ONCE, here at construction — BEFORE any fleet epoch\n // fence (which arms later, on writer promotion), so receipts run first in the guard chain (verdict\n // §(c) Risk R6). Free until used: the guard is a no-op for any commit whose units carry no dedup key\n // (every ordinary mutation), so this costs a non-outbox deployment nothing. SKIPPED when the caller\n // owns receipts-guard registration on the concrete write store (`externalReceiptsGuard` — a fleet\n // sync node, whose `options.store` is a `SwitchableDocStore` over the replica that a guard would\n // silently NOT follow across the promotion swapTo; fleet's `armWriter` installs it on the concrete\n // Postgres store instead, before the fence). See `externalReceiptsGuard`'s doc comment.\n if (!options.externalReceiptsGuard) options.store.addCommitGuard(clientReceiptsGuard());\n // Resolve (or first-stamp) the deployment id for `ConnectAck` (same-timeline proof). A fleet sync\n // node's replica may be read-only — tolerate a failed stamp (it reads the primary's replicated id;\n // worst case an empty id, still a stable per-boot value the client compares against itself).\n let deploymentId = (await options.store.getGlobal(DEPLOYMENT_ID_GLOBAL_KEY)) as string | null;\n if (deploymentId === null) {\n try {\n await options.store.writeGlobalIfAbsent(DEPLOYMENT_ID_GLOBAL_KEY, crypto.randomUUID());\n deploymentId = (await options.store.getGlobal(DEPLOYMENT_ID_GLOBAL_KEY)) as string | null;\n } catch {\n deploymentId = null;\n }\n }\n const resolvedDeploymentId = deploymentId ?? \"\";\n // Mirror the primary store's schema setup for `queryStore` (Fleet B3, D1) — idempotent on both\n // backends (SQLite `CREATE TABLE IF NOT EXISTS`; Postgres swallows the duplicate-object race),\n // so a caller handing in an already-initialized replica pays nothing extra, while a fresh store\n // (e.g. a test, or a from-scratch replica) doesn't footgun on missing tables.\n if (options.queryStore) await options.queryStore.setupSchema();\n\n const adapter = options.fanoutAdapter ?? new InMemoryWriteFanoutAdapter();\n const fanout = new EmbeddedWriteFanout(adapter, options.originId ?? \"embedded\");\n\n // Recover the timestamp high-water mark from persisted data, so snapshot reads after a\n // restart see existing documents (a fresh oracle at 0 would read `ts <= 0` and find nothing).\n const startTs = await options.store.maxTimestamp();\n // Shards B2a: with numShards > 1, one `ShardedTransactor` (per-shard mutexes/rings/oracles) so\n // cross-shard commits run in parallel; else the single-shard transactor, byte-identical to before.\n // `observeTimestamp` (fleet follower catch-up + promotion) delegates to whichever we build — the\n // ShardedTransactor fans a learned ts to every shard oracle; the single oracle takes it directly.\n let transactor: SingleWriterTransactor | ShardedTransactor;\n let oracle: TimestampObserver;\n if ((options.numShards ?? 1) > 1) {\n const sharded = new ShardedTransactor(options.store, { fanout, groupCommit: options.groupCommit ?? false });\n sharded.observeTimestamp(startTs); // floor every shard oracle at the recovered high-water mark\n transactor = sharded;\n oracle = sharded;\n } else {\n const singleOracle = new MonotonicTimestampOracle(startTs);\n transactor = new SingleWriterTransactor(options.store, singleOracle, { fanout, groupCommit: options.groupCommit ?? false });\n oracle = singleOracle;\n }\n const queryRuntime = new QueryRuntime(options.store);\n\n // Hybrid-node split-read seam (Fleet B3, D1): when `queryStore` is configured, build a SEPARATE\n // query-path transactor + QueryRuntime over it. Queries never commit, so a plain\n // `SingleWriterTransactor` is the right shape regardless of whether the WRITE side is sharded —\n // this reuses the sync-node construction (a query transactor over a replica-backed store). Its\n // oracle seeds from `queryStore`'s OWN `maxTimestamp()` (not the write store's `startTs` above)\n // and then rides ONLY `observeTimestamp` (below) — never this runtime's own local commits, which\n // land on `options.store` and advance `oracle` (the write oracle) directly, unaffected by this.\n // Unset `queryStore` → `queryPath`/`queryOracle` stay undefined: `ExecutorDeps.queryPath` is\n // never set, and `observeTimestamp` keeps the exact shipped write-oracle routing (see below).\n let queryPath: { transactor: SingleWriterTransactor; queryRuntime: QueryRuntime } | undefined;\n let queryOracle: TimestampObserver | undefined;\n if (options.queryStore) {\n const queryStartTs = await options.queryStore.maxTimestamp();\n const qOracle = new MonotonicTimestampOracle(queryStartTs);\n const queryTransactor = new SingleWriterTransactor(options.queryStore, qOracle);\n queryPath = { transactor: queryTransactor, queryRuntime: new QueryRuntime(options.queryStore) };\n queryOracle = qOracle;\n }\n\n // Shards B2a (T5): the SAME resolved count that decided the transactor above must reach every\n // `executor.run` call site's `RunOptions.numShards` — the executor/kernel shard resolution (T3)\n // defaults `numShards` to 1 there, which makes every guard short-circuit onto \"default\" no matter\n // how many shards the transactor actually runs. Captured once here; every closure below and every\n // instance method (via the constructor field) passes this same value.\n const numShards = options.numShards ?? 1;\n\n // `invoke` is TRUSTED server re-entrancy for actions' `ctx.runQuery`/`runMutation`/`runAction`:\n // it resolves ANY registered path, including `_`-prefixed component-internal modules — unlike\n // the public `run`/`runAction` below, which block `_`. The executor is constructed before\n // `contextProviders`/`policyRegistry`/etc. below exist and before `modules` is populated, so\n // `invoke` reads them through a mutable closure var (`executorRef`) to break the cycle.\n let executorRef: InlineUdfExecutor;\n const invoke = async (path: string, args: JSONValue, opts?: { identity?: string | null }): Promise<UdfResult> => {\n const fn = modules[path];\n if (!fn) throw new FunctionNotFoundError(`unknown function: ${path}`);\n return executorRef.run(fn, jsonToConvex(args), {\n path,\n namespace: namespaceForPath(path, componentNames),\n contextProviders,\n policyRegistry,\n policyProviders,\n relationRegistry,\n functionKind,\n identity: opts?.identity ?? null,\n numShards,\n });\n };\n const executor = new InlineUdfExecutor({ transactor, queryRuntime, catalog: options.catalog, logSink: options.logSink, now: options.now, invoke, writeRouter: options.writeRouter, queryPath, globalStore: options.globalStore });\n executorRef = executor;\n\n // Run component boot steps once, before serving: a namespaced, non-user mutation per step.\n // `localOnly: true` bypasses the executor's per-shard write router — a boot step seeds this\n // node's OWN store before it's ready to be any shard's owner; without the flag a fleet node\n // that isn't the default-shard owner would forward its own boot seed to a peer (or fail).\n for (const step of options.bootSteps ?? []) {\n const bootFn = mutation(async (ctx) => {\n await step.run({ db: ctx.db as unknown as GuestDatabaseWriter, now: ctx.now() });\n return null;\n });\n await executor.run(bootFn, {}, { path: `_boot:${step.name}`, namespace: step.name, identity: null, numShards, localOnly: true });\n }\n\n // A mutable map the closures read, so `setModules` hot-swaps functions in place\n // (preserving the store, oracle, and transactor — no data loss on reload).\n const componentNames = options.componentNames ?? new Set<string>();\n const contextProviders = options.contextProviders ?? [];\n const policyRegistry = options.policyRegistry ?? new Map();\n const policyProviders = options.policyProviders ?? [];\n const relationRegistry = options.relationRegistry;\n const modules: Record<string, RegisteredFunction> = { ...options.modules };\n const systemModules: Record<string, RegisteredFunction> = { ...(options.systemModules ?? {}) };\n const adminModules: Record<string, RegisteredFunction> = { ...(options.adminModules ?? {}) };\n // Resolves a target path's REAL registered kind — threaded onto every `ComponentContext` so\n // component facades (e.g. `@helipod/scheduler`'s `kindOf`) can tag a job's\n // kind:\"mutation\"|\"action\" accurately instead of guessing. See `ComponentContext.functionKind`'s\n // doc comment (packages/executor/src/executor.ts). A plain lookup against the SAME mutable\n // `modules` map `setModules` hot-swaps in place, so it stays correct across a dev reload.\n const functionKind = (path: string): \"query\" | \"mutation\" | \"action\" | \"httpAction\" | undefined => modules[path]?.type;\n const resolve = (path: string): RegisteredFunction => {\n if (isInternalPath(path)) throw new FunctionNotFoundError(`unknown function: ${path}`);\n const fn = modules[path];\n if (!fn) throw new FunctionNotFoundError(`unknown function: ${path}`);\n return fn;\n };\n\n const syncExecutor: SyncUdfExecutor = {\n async runQuery(path, args, identity) {\n const r = await executor.run(resolve(path), jsonToConvex(args), { path, namespace: namespaceForPath(path, componentNames), contextProviders, policyRegistry, policyProviders, relationRegistry, functionKind, identity: identity ?? null, numShards });\n return {\n value: r.value as Value,\n tables: writtenTablesFromRanges(r.readRanges),\n readRanges: r.readRanges.map(serializeKeyRange),\n globalTables: r.globalTables ?? [],\n ...(r.diffableRange ? { diffableRange: r.diffableRange } : {}),\n ...(r.diffablePage ? { diffablePage: r.diffablePage } : {}),\n };\n },\n async runMutation(path, args, identity, origin, dedup): Promise<RunMutationResult> {\n const fn = resolve(path);\n // Owner-placement (Receipted Outbox, verdict §(c) repair 3): the classification read must run\n // WHERE THE COMMIT RUNS. On a node that will FORWARD (a fleet non-writer for the default\n // shard), don't classify against this node's replica — thread the dedup key into the forward\n // so the OWNER classifies. On the owner / single-node, classify locally.\n const willForward = dedup !== undefined && !!options.writeRouter && !options.writeRouter.isLocalWriter(DEFAULT_SHARD);\n const classifyLocally = dedup !== undefined && !willForward;\n\n if (classifyLocally) {\n const pre = await classifyDedup(options.store, identity ?? null, dedup as DedupKey);\n if (pre) return replayToRunResult(pre);\n }\n\n // G4: thread the committing session's id (`origin`) so the commit's fan-out advances its own\n // frontier. `dedup` rides the forward (owner classifies); `commitMeta` carries the dedup key\n // to the LOCAL receipts guard (which writes the `applied` receipt atomically at commit).\n const runOpts = {\n path,\n namespace: namespaceForPath(path, componentNames),\n contextProviders,\n policyRegistry,\n policyProviders,\n relationRegistry,\n functionKind,\n identity: identity ?? null,\n numShards,\n origin,\n dedup,\n commitMeta: classifyLocally ? dedupCommitMeta(identity ?? null, dedup as DedupKey) : undefined,\n };\n let r;\n try {\n r = await executor.run(fn, jsonToConvex(args), runOpts);\n } catch (e) {\n if (classifyLocally) {\n const replay = await handleDedupError(options.store, identity ?? null, dedup as DedupKey, e);\n if (replay) return replayToRunResult(replay);\n }\n throw e;\n }\n // The owner replayed a recorded verdict for a forwarded dedup write (no commit here).\n if (r.clientReplay) return replayToRunResult(r.clientReplay);\n // Zero-write successful mutation (no doc rows → the guard never ran): write its `applied`\n // receipt (WITH the return value) standalone, post-run (verdict §(c) Risk R1).\n if (classifyLocally && !r.committed) {\n await recordZeroWriteApplied(options.store, identity ?? null, dedup as DedupKey, r.commitTs, r.value as Value);\n } else if (classifyLocally && r.oplog !== null) {\n // A committed WRITE mutation whose guard ran on THIS node's store (a real local oplog, not\n // a forwarded write another node's guard handled) — best-effort fill the value the guard\n // couldn't see at commit time (T5-review recommendation, the B3 pattern).\n await fillWriteMutationValue(options.store, identity ?? null, dedup as DedupKey, r.value as Value);\n }\n return {\n replayed: false,\n value: r.value as Value,\n tables: r.oplog?.writtenTables ?? [],\n writeRanges: r.oplog?.writtenRanges ?? [],\n // `commitTs` (B2b, T2): a LOCAL commit reports it via `r.oplog.commitTs`; a FORWARDED\n // mutation has no local oplog (null), but the executor's forward branch already threads\n // the owner's real commitTs onto `r.commitTs` itself — fall back to that.\n commitTs: Number(r.oplog?.commitTs ?? r.commitTs ?? 0n),\n // G4 fleet fallback signal: a committed write with NO local oplog was forwarded to another\n // shard's owner — its origin tag can't reach this node's `doNotifyWrites`.\n forwarded: r.committed && r.oplog === null,\n };\n },\n async runAdminQuery(path, args) {\n const fn = adminModules[path];\n if (!fn) throw new Error(`unknown admin function: ${path}`);\n const r = await executor.run(fn, jsonToConvex(args), { path, privileged: true, numShards });\n return {\n value: r.value as Value,\n tables: writtenTablesFromRanges(r.readRanges),\n readRanges: r.readRanges.map(serializeKeyRange),\n globalTables: r.globalTables ?? [],\n ...(r.diffableRange ? { diffableRange: r.diffableRange } : {}),\n ...(r.diffablePage ? { diffablePage: r.diffablePage } : {}),\n };\n },\n async runAction(path, args, identity) {\n // `resolve` is the SAME public gate `runQuery`/`runMutation` use above — it throws on\n // `_`-prefixed / namespaced-internal paths, so a client Action cannot reach internal\n // modules (e.g. `scheduler:_enqueue`). Also enforce the action-only type check, matching\n // the instance `runAction` (Task 1)'s public gate.\n const fn = resolve(path);\n if (fn.type !== \"action\") throw new Error(`${path} is not an action`);\n // Actions still forward WHOLESALE at the runtime level (not per-shard: an action has no\n // shard of its own), targeted at the default-shard holder. Once it runs on that writer-ish\n // node, its inner `ctx.runMutation`s route per-shard through the executor chokepoint.\n if (options.writeRouter && !options.writeRouter.isLocalWriter(DEFAULT_SHARD)) {\n const res = await options.writeRouter.forward(\"action\", path, args, identity ?? null, DEFAULT_SHARD);\n return { value: jsonToConvex(res.value) as Value };\n }\n const r = await executor.run(fn, jsonToConvex(args), { path, namespace: namespaceForPath(path, componentNames), contextProviders, policyRegistry, policyProviders, relationRegistry, functionKind, identity: identity ?? null, numShards });\n return { value: r.value as Value };\n },\n // ── Receipted Outbox resume-handshake support (verdict §(e)) ──────────────────────────────\n // Both reads/writes go to the AUTHORITATIVE receipts store (the primary), NOT `options.store`:\n // on a fleet sync node the latter is the replica, which carries no receipts (see\n // `receiptsStore`'s doc comment). Unset → `options.store`, byte-identical off the fleet.\n async classifyClientMutation(identity, clientId, seq): Promise<ClientMutationVerdict> {\n return classifyForConnect(options.receiptsStore ?? options.store, identity ?? null, clientId, seq);\n },\n async pruneClientMutations(identity, clientId, ackedThrough): Promise<void> {\n await (options.receiptsStore ?? options.store).pruneClientMutations(identity ?? \"\", clientId, { ackedThrough });\n },\n deploymentId(): string {\n return resolvedDeploymentId;\n },\n };\n\n // Reactivity is driven by the write fan-out (not inline in the mutation handler), so a\n // commit from ANY path — WebSocket mutation OR `runtime.run()` / HTTP `/api/run` —\n // invalidates live subscriptions. The async drain serializes notifies and runs them after\n // the current call stack (so a MutationResponse is sent before its Transition).\n const handler = new SyncProtocolHandler(syncExecutor, {\n autoNotifyOnMutation: false,\n verifyAdmin: options.verifyAdmin,\n // The DO host (Slice 3) sets this so the handler arms no `setInterval` sweep / ping heartbeat;\n // unset everywhere else (byte-identical to before this option existed).\n disableBackgroundTimers: options.disableSyncBackgroundTimers,\n });\n const queue: Array<{\n tables: string[];\n ranges: import(\"@helipod/index-key-codec\").SerializedKeyRange[];\n commitTs: number;\n origin?: string;\n writtenDocs?: import(\"@helipod/transactor\").WrittenDoc[];\n }> = [];\n let draining = false;\n const drain = async (): Promise<void> => {\n if (draining) return;\n draining = true;\n try {\n while (queue.length > 0) {\n const inv = queue.shift()!;\n // Hybrid RYOW gate (Fleet B3, D2): awaited BEFORE this invalidation's `notifyWrites`, so\n // e.g. a hybrid node's `tailer.waitFor(commitTs)` can hold a locally-committed mutation's\n // subscription re-run until the replica-backed query path has actually applied it — the\n // removes-the-briefly-stale-re-run gate. A throwing/rejecting hook is caught and logged;\n // one bad wait must not wedge every OTHER queued invalidation behind it forever.\n if (options.beforeNotify) {\n try {\n await options.beforeNotify(BigInt(inv.commitTs));\n } catch (e) {\n console.error(\"[runtime] beforeNotify hook threw:\", e);\n }\n }\n // G4: pass the origin session id through so `doNotifyWrites` can advance that session's\n // own `version.ts` past this commit even when it touched nothing the session subscribes to.\n await handler.notifyWrites(inv, inv.origin);\n }\n } finally {\n draining = false;\n }\n };\n\n // Driver lifecycle: component drivers wake on every committed write (across the whole\n // runtime, not just their own tables — a driver decides for itself what it cares about)\n // and/or on wall-clock timers. Wired to the SAME commit fan-out as `notifyWrites`, below.\n const commitSubs = new Set<(inv: { tables: string[]; ranges: readonly SerializedKeyRange[]; commitTs: number }) => void>();\n const timers = new Map<number, DriverTimer>();\n let timerSeq = 0;\n const wakeHost = options.wakeHost;\n // The instant currently armed on the host (`null` = nothing armed) — mirrors the host's ONE alarm\n // slot, so an arm only crosses the seam when the minimum actually MOVES. A driver arming\n // far-future timers (the scheduler re-arms its sweep every pass) must not thrash the host's\n // schedule: on Cloudflare each arm is a `fetch` out of the container. Starts `null` because a\n // fresh host has nothing armed.\n let armedAt: number | null = null;\n /** Recompute `min(atMs)` across live handles and push it to the host — only if it moved. */\n const rearm = (): void => {\n if (!wakeHost) return;\n let min: number | null = null;\n for (const t of timers.values()) if (min === null || t.atMs < min) min = t.atMs;\n if (min === armedAt) return;\n armedAt = min;\n wakeHost.armWake(min);\n };\n const fireDueTimers = (): void => {\n const t0 = options.now?.() ?? Date.now();\n // The wake that brought us here CONSUMED the host's alarm (a fired alarm doesn't re-arm\n // itself), so forget what we thought was armed BEFORE running anything: a callback's own\n // `setTimer` then arms correctly, and a wake that finds nothing due (an early/stale wake, or\n // the common Cloudflare case where this very request COLD-BOOTED the process and the drivers'\n // `start()` already re-derived everything) still re-arms the unchanged minimum rather than\n // silently losing it.\n armedAt = null;\n const due: DriverTimer[] = [];\n for (const [h, t] of timers) {\n if (t.atMs <= t0) {\n due.push(t);\n timers.delete(h);\n }\n }\n // Drop every due timer BEFORE running any callback: a callback re-arming its own handle (the\n // scheduler's `armSweep`, the triggers beat) must not have its fresh timer swept by this pass.\n try {\n for (const t of due) {\n // Per-callback catch, and a `finally` re-arm below. On the `setTimeout` path each callback\n // is its own macrotask, so a throw can only kill its own timer; here they share one call\n // stack, and an escaping throw would strand every LATER due callback AND skip the re-arm —\n // leaving the host with no alarm at all (`armedAt` was just cleared), i.e. drivers dead\n // forever. Every driver callback already swallows+logs internally, so this is\n // defense-in-depth against exactly the silent-death class this seam exists to fix.\n try {\n t.cb();\n } catch (e) {\n console.error(\"[runtime] driver timer callback threw:\", e);\n }\n }\n } finally {\n rearm();\n }\n };\n const backstopMs = options.backstopMs ?? ((d: number) => d);\n const driverCtx: DriverContext = {\n runFunction: async (path, args) => {\n const fn = modules[path];\n if (!fn) throw new Error(`driver: unknown function ${path}`);\n const ns = namespaceForPath(path, componentNames);\n const res = await executor.run(fn, jsonToConvex(args), {\n path,\n namespace: ns,\n contextProviders,\n policyRegistry,\n policyProviders,\n relationRegistry,\n functionKind,\n identity: null,\n privileged: true,\n numShards,\n // A driver runs on the writer that owns its control tables and must read-its-own-writes:\n // force its queries onto the PRIMARY, never a hybrid node's lagging replica queryPath, so\n // a just-enqueued scheduler job is visible on the very next peek. No-op off a hybrid.\n primaryRead: true,\n });\n return res.value;\n },\n onCommit: (cb) => {\n commitSubs.add(cb);\n return () => commitSubs.delete(cb);\n },\n setTimer: (atMs, cb) => {\n const h = ++timerSeq;\n const t: DriverTimer = { atMs, cb };\n // Only the DEFAULT (no `wakeHost`) path arms a real `setTimeout` — with a host, the host's\n // single alarm is the sole firing mechanism (`fireDueTimers`), and a `setTimeout` alongside\n // it would run the same callback twice. The self-delete keeps `min(atMs)` honest: a fired\n // handle left in the map would pin the minimum in the past forever.\n if (!wakeHost) {\n t.timeout = setTimeout(() => {\n timers.delete(h);\n cb();\n }, Math.max(0, atMs - (options.now?.() ?? Date.now())));\n }\n timers.set(h, t);\n rearm();\n return h;\n },\n clearTimer: (h) => {\n const t = timers.get(h);\n if (t) {\n if (t.timeout !== undefined) clearTimeout(t.timeout);\n timers.delete(h);\n rearm();\n }\n },\n now: () => options.now?.() ?? Date.now(),\n backstopMs,\n // Same resolver as `create()`'s local `functionKind` closure (used elsewhere for\n // `ComponentContext.functionKind`) — reused here, not recomputed, so a driver's path\n // validation (e.g. `@helipod/triggers`' boot-time handler check) and every other kind\n // lookup in this runtime always agree.\n functionKind,\n readLog: async (opts) => {\n // Reads the PRIMARY WRITE store explicitly — never a hybrid node's lagging query replica: a\n // driver runs on the writer that owns the log and must see its own committed writes.\n const store = options.store;\n const afterTs = BigInt(Math.trunc(opts.afterTs));\n // Upper scan bound = the stable log prefix. Fleet → `min(shard_leases.frontier_ts)` (N per-shard\n // commit connections land ts out of order — a gap below the max must not be crossed); every\n // non-fleet topology commits over one serialized session, so a null accessor falls back to the\n // max committed ts. This bound is what makes at-least-once delivery gap-free by construction.\n const stable = options.stablePrefix ? await options.stablePrefix() : null;\n const bound = stable ?? (await store.maxTimestamp());\n if (bound <= afterTs) return { changes: [], maxScannedTs: Number(afterTs) };\n\n // `limit: 0` is a DELIBERATE, DOCUMENTED escape hatch (triggers D2's boot idiom — see\n // `@helipod/triggers`' `src/boot.ts`): \"peek the current stable bound without scanning\n // anything.\" A caller that only wants to know the log's current tip (e.g. to seed a new\n // trigger's cursor AT the tip rather than replay history) asks for zero scanned entries and\n // gets `maxScannedTs = bound` back for free — `bound` was already computed above with no\n // per-row cost. This deliberately does NOT return `changes: []`-with-`maxScannedTs: afterTs`\n // (i.e. \"no progress\", the naive reading of \"scanned zero entries\"): that reading is useless\n // for the tip-peek use case (it would just echo `afterTs` back), and no legitimate caller\n // needs \"confirm zero rows were examined\" as a distinct signal from \"give me the bound\n // cheaply\" — so `limit: 0` unambiguously means the latter. Guarded here, before the\n // `load_documents` scan below, which would otherwise crash on `limit: 0` (a SQL `LIMIT 0`\n // yields zero rows, so `scanned.length === limit` (0===0) trips the `limitHit` branch, whose\n // `scanned[scanned.length - 1]` access is `undefined` — this early return avoids that path\n // entirely rather than requiring one to reason about it).\n if (opts.limit === 0) return { changes: [], maxScannedTs: Number(bound) };\n\n const limit = opts.limit;\n // Scan (afterTs, bound] → half-open [afterTs+1, bound+1).\n const scanned: DocumentLogEntry[] = [];\n for await (const e of store.load_documents(\n { minInclusive: afterTs + 1n, maxExclusive: bound + 1n },\n \"asc\",\n limit,\n )) {\n scanned.push(e);\n }\n\n // A commit stamps every one of its documents with the SAME ts, so a `limit` can cut in the\n // middle of a commit's revisions. Never advance the cursor past a partially-scanned ts.\n let maxScannedTs: bigint;\n let rows: DocumentLogEntry[];\n const limitHit = limit !== undefined && scanned.length === limit;\n if (!limitHit) {\n maxScannedTs = bound; // the whole range was scanned\n rows = scanned;\n } else {\n const lastTs = scanned[scanned.length - 1]!.ts;\n if (lastTs > afterTs + 1n) {\n // A complete ts group sits below `lastTs`: stop just below it and drop the (possibly\n // partial) `lastTs` group — it redelivers next scan (its changeIds are stable).\n maxScannedTs = lastTs - 1n;\n rows = scanned.filter((e) => e.ts < lastTs);\n } else {\n // Degenerate: every scanned row shares one ts (a single commit larger than `limit`). To\n // make progress the whole commit must be delivered — re-scan exactly that ts UNBOUNDED.\n maxScannedTs = lastTs;\n rows = [];\n for await (const e of store.load_documents(\n { minInclusive: lastTs, maxExclusive: lastTs + 1n },\n \"asc\",\n )) {\n rows.push(e);\n }\n }\n }\n\n const tableFilter = opts.tables ? new Set(opts.tables) : null;\n const changes: LogChange[] = [];\n for (const e of rows) {\n const name = tableNumberToName.get(e.id.tableNumber);\n // Exclude (from `changes`, but they ALREADY counted toward maxScannedTs): unresolvable ids,\n // component-namespaced tables (\"<component>/<table>\"), and app-root system tables (\"_...\").\n if (name === undefined || name.includes(\"/\") || name.startsWith(\"_\")) continue;\n if (tableFilter && !tableFilter.has(name)) continue;\n\n const op: LogChange[\"op\"] =\n e.value === null ? \"delete\" : e.prev_ts === null ? \"insert\" : \"update\";\n const newDoc = e.value === null ? null : (convexToJson(e.value.value as Value) as JSONValue);\n let oldDoc: JSONValue | null = null;\n if (e.prev_ts !== null) {\n // The prior revision via the prev_ts chain. A tombstone prev (delete→re-insert reusing the\n // id) returns null here → oldDoc null with op \"update\" (the documented edge).\n const prev = await store.get(e.id, e.prev_ts);\n oldDoc = prev === null ? null : (convexToJson(prev.value.value as Value) as JSONValue);\n }\n const idStr = encodeInternalDocumentId(e.id);\n const tsNum = Number(e.ts);\n changes.push({\n table: name,\n id: idStr,\n op,\n newDoc,\n oldDoc,\n ts: tsNum,\n changeId: `${name}:${idStr}:${tsNum}`,\n });\n }\n\n return { changes, maxScannedTs: Number(maxScannedTs) };\n },\n // M2c Task 6: `handler` (the `SyncProtocolHandler` instance) is already constructed above\n // (`const handler = new SyncProtocolHandler(...)`) by the time this `driverCtx` object is\n // built, so both hooks are plain delegations — no chicken-and-egg problem the way a\n // boot-layer-constructed poller would have (`runtime.handler` doesn't exist until\n // `createEmbeddedRuntime` RETURNS; this closure runs before that, with `handler` already live).\n notifyWrites: (inv) => handler.notifyWrites(inv),\n subscribedGlobalTables: () => handler.subscribedGlobalTables(),\n // M2c fix: plain delegation, same reasoning as the two hooks above — `handler` is already\n // constructed by the time this `driverCtx` object is built.\n onGlobalSubscribe: (cb) => handler.onGlobalSubscribe(cb),\n };\n\n // Inverse of `tableNumbers` (tableNumber → fullTableName), seeded here from\n // `options.tableNumbers` and later rebuildable via the instance method `setTableNumbers`\n // (after an additive deploy): `payload.tables` (from `adapter.subscribe`) carries ENCODED\n // STORAGE-TABLE IDS (`encodeStorageTableId`'s output, e.g. `\"3\"`), not full table names — the\n // sync path (`queue`/`notifyWrites` above) works with those ids directly via range\n // intersection, but drivers filter `inv.tables` by full name (e.g. `t.startsWith(\"scheduler/\")`),\n // so the driver fan-out below must translate. This `Map` object is also handed to the\n // constructor as `this.tableNumberToName` — `setTableNumbers` mutates it in place (not a\n // reassignment), so this closure's `namesForCommit` stays correct after a later rebuild.\n const tableNumberToName = new Map<number, string>();\n rebuildTableNumberToName(tableNumberToName, options.tableNumbers ?? {});\n const namesForCommit = (tableIds: readonly string[]): string[] => translateTableIds(tableIds, tableNumberToName);\n\n adapter.subscribe((payload) => {\n // DLR 2b response-before-Transition gate: register SYNCHRONOUSLY here, at commit time (this\n // callback fires inside the commit, before `runMutation` resolves — hence before the committing\n // session's `MutationResponse` can be sent). Registering here rather than lazily inside\n // `doNotifyWrites` is essential: the fan-out `drain` below is SERIAL, so under load\n // `doNotifyWrites` for this commit can run long after its response already flushed; a gate\n // registered there would arrive after its own release and then park forever, wedging the whole\n // notify chain (the backpressure-flood stall). The handler scopes this to a diff-capable local\n // origin session and drops it on the matching `processMutation` release — see\n // `registerOriginResponseGate`.\n handler.registerOriginResponseGate(payload.commitTs, payload.origin);\n queue.push({\n tables: payload.tables,\n ranges: payload.ranges,\n commitTs: payload.commitTs,\n origin: payload.origin,\n writtenDocs: payload.writtenDocs,\n });\n void drain();\n if (commitSubs.size > 0) {\n fireCommitSubs(commitSubs, { tables: namesForCommit(payload.tables), ranges: payload.ranges, commitTs: payload.commitTs });\n }\n });\n\n if ((options.drivers?.length ?? 0) > 0 && !options.tableNumbers) {\n // Without `tableNumbers`, `namesForCommit` above can't translate the encoded storage-table\n // ids a real commit carries back into full names, so `inv.tables` a driver's `onCommit`\n // callback sees never matches a `t.startsWith(\"scheduler/\")`-style filter — reactive wake\n // silently degrades to timer-only. Warn once (per `create()` call) rather than fail: a\n // driver relying purely on its own periodic timer still works, just not with ~0 latency.\n console.warn(\n \"[runtime] drivers registered but no `tableNumbers` provided — driver reactive wake (onCommit) will not match table-name filters; drivers will fall back to their own timers only.\",\n );\n }\n\n const drivers = options.drivers ?? [];\n // `deferDrivers` skips this: the caller starts them later via the instance's\n // `startDrivers()` (e.g. a fleet node that boots as a non-writer and only wants drivers\n // running once/if it becomes the writer).\n let driversStarted = false;\n if (!options.deferDrivers) {\n for (const d of drivers) await d.start(driverCtx);\n driversStarted = true;\n }\n\n return new EmbeddedRuntime(\n options.store, executor, handler, adapter, modules, systemModules, adminModules, componentNames,\n contextProviders, policyRegistry, policyProviders, relationRegistry, drivers, timers, fireDueTimers, tableNumberToName,\n oracle, queryOracle, transactor, driverCtx, driversStarted, options.writeRouter, numShards, options.catalog,\n commitSubs,\n );\n }\n\n /**\n * Resolves a target path's REAL registered kind against the live `this.modules` map — same\n * resolver shape as `create()`'s local `functionKind` closure, but bound to the instance so it\n * stays correct across `setModules` hot-swaps. See `ComponentContext.functionKind`'s doc\n * comment (packages/executor/src/executor.ts).\n */\n private functionKind = (path: string): \"query\" | \"mutation\" | \"action\" | \"httpAction\" | undefined => this.modules[path]?.type;\n\n /** Hot-swap the function map (dev reload) without disturbing the store/transactor. */\n setModules(modules: Record<string, RegisteredFunction>): void {\n for (const key of Object.keys(this.modules)) delete this.modules[key];\n Object.assign(this.modules, modules);\n }\n\n /**\n * Rebuild the tableNumber→name map after an additive deploy so driver commit fan-out\n * (`namesForCommit` in `create()`, which closed over this same `Map` instance) keeps\n * translating newly-added tables' encoded storage ids to their full names correctly.\n * Additive deploys keep existing numbers, so this only ever adds entries in practice.\n */\n setTableNumbers(tableNumbers: Record<string, number>): void {\n rebuildTableNumberToName(this.tableNumberToName, tableNumbers);\n }\n\n /**\n * The FOREIGN-COMMIT driver wake for a multi-writer fleet hybrid (Fleet B3, trigger-wake gap\n * fix). `commitSubs` (driver `onCommit` wakes) normally fires only from `create()`'s\n * `adapter.subscribe` callback — the LOCAL commit fan-out. In an opt-in multi-writer fleet, a\n * co-writer's commit reaches THIS node only through the hybrid-tailer `invalidationSink`\n * (`ee/packages/fleet/src/node.ts`), which calls `handler.notifyWrites` directly — bypassing\n * `adapter.subscribe` entirely, so a driver here (e.g. `@helipod/triggers`) never woke on a\n * foreign writer's commit and instead slept up to its own wall-clock beat. Delivery was always\n * guaranteed (the durable cursor over the log) — this is a LATENCY fix, not a correctness one.\n *\n * The caller (the fleet's `invalidationSink`) invokes this after `notifyWrites`, passing the\n * SAME derived invalidation. Translates `inv.tables` with the identical `translateTableIds`\n * helper the local path uses, so a driver's `t.startsWith(\"scheduler/\")`-style filter matches\n * either source the same way. A local commit and a foreign commit that happen to touch the same\n * table may both wake a driver for what is conceptually \"the same\" change window — harmless,\n * since driver wakes are level-triggered (a driver re-checks its own state, it doesn't trust the\n * wake payload as the sole source of truth).\n *\n * A no-op on any node with no registered drivers (`commitSubs` empty) — cheap to call\n * unconditionally from every fleet node, writer-ish or not.\n */\n notifyExternalCommit(inv: { tables: string[]; ranges: readonly SerializedKeyRange[]; commitTs: number }): void {\n if (this.commitSubs.size === 0) return;\n fireCommitSubs(this.commitSubs, { tables: translateTableIds(inv.tables, this.tableNumberToName), ranges: inv.ranges, commitTs: inv.commitTs });\n }\n\n /**\n * Live view of the registered app+component function paths. Reads the same mutable `modules`\n * map `setModules` hot-swaps in place, so counts stay correct across a dev reload or deploy\n * (the boot-time snapshot the server used to cache went stale after the first hot-swap).\n */\n functionPaths(): string[] {\n return Object.keys(this.modules);\n }\n\n /** Live view of the registered table names (mirrors `functionPaths`, reads the live map). */\n tableNames(): string[] {\n return [...this.tableNumberToName.values()];\n }\n\n /** Open an in-process connection an unmodified client can talk to. */\n connect(sessionId?: string): LoopbackConnection {\n return createLoopbackConnection(this.handler, sessionId ?? `session-${++this.sessionCounter}`);\n }\n\n /**\n * Synthesizes a `UdfResult` for a write forwarded to the writer node: `forward` only returns\n * the function's JSON result, not read ranges / an oplog, so those come back empty/zero here.\n * Shared by `run()` and `runAction()` — both route through the same `WriteRouter`.\n */\n private forwardedResult<T>(value: JSONValue): UdfResult<T> {\n return { value: jsonToConvex(value) as T, logs: [], committed: true, commitTs: 0n, readRanges: [], oplog: null };\n }\n\n /** Directly invoke a function (for HTTP routes / the CLI `run` command). A MUTATION routes\n * per-shard inside the executor (`executor.run` forwards a shard this node doesn't own); an\n * ACTION forwards wholesale here to the default-shard holder; queries always run locally. */\n async run<T = unknown>(\n path: string,\n args: JSONValue,\n opts?: { identity?: string | null; commitMeta?: Record<string, string>; dedup?: DedupKey },\n ): Promise<UdfResult<T>> {\n if (isInternalPath(path)) throw new FunctionNotFoundError(`unknown function: ${path}`);\n const fn = this.modules[path];\n if (!fn) throw new FunctionNotFoundError(`unknown function: ${path}`);\n if (fn.type === \"action\" && this.writeRouter && !this.writeRouter.isLocalWriter(DEFAULT_SHARD)) {\n const res = await this.writeRouter.forward(\"action\", path, args, opts?.identity ?? null, DEFAULT_SHARD);\n return this.forwardedResult<T>(res.value);\n }\n // Receipted Outbox (verdict §(c)): a dedup-keyed MUTATION reaching this OWNER (the fleet\n // `/_fleet/run` path, or a local caller) classifies here — the same code path single-node and\n // fleet share (repair 3). A recorded/floored verdict short-circuits to a replay UdfResult\n // (`clientReplay` set, `committed: false`); a miss runs with the dedup key on the commit meta so\n // the receipts guard writes the `applied` receipt atomically, and a guard PK collision replays.\n if (fn.type === \"mutation\" && opts?.dedup) {\n return this.runMutationClassified<T>(fn, path, args, opts.identity ?? null, opts.dedup, opts.commitMeta);\n }\n return this.executor.run<T>(fn, jsonToConvex(args), {\n path,\n namespace: namespaceForPath(path, this.componentNames),\n contextProviders: this.contextProviders,\n policyRegistry: this.policyRegistry,\n policyProviders: this.policyProviders,\n relationRegistry: this.relationRegistry,\n functionKind: this.functionKind,\n identity: opts?.identity ?? null,\n numShards: this.numShards,\n // Fleet B3, D3 (effectively-once forwarding): opaque commit metadata threaded straight through\n // to `Transactor.runInTransaction`'s `commitMeta` — meaningful only for a mutation that\n // actually commits (see `RunOptions.commitMeta`'s doc comment). `packages/cli`'s `/_fleet/run`\n // handler is the one caller that sets this, carrying a forwarded write's idempotency key.\n commitMeta: opts?.commitMeta,\n });\n }\n\n /**\n * The OWNER-side dedup classification for a mutation reaching `run()` with a dedup key (the fleet\n * `/_fleet/run` forward path). Shares the exact classify → run-with-guard → replay-on-collision\n * logic the sync `runMutation` uses; a replay is surfaced as a `UdfResult` with `clientReplay` set\n * (the `/_fleet/run` handler serializes it to a replay body). `base` is any pre-existing commit\n * meta (e.g. fleet's `idempotencyKey`) — the dedup keys merge onto it (disjoint keys).\n */\n private async runMutationClassified<T>(\n fn: RegisteredFunction,\n path: string,\n args: JSONValue,\n identity: string | null,\n dedup: DedupKey,\n base?: Record<string, string>,\n ): Promise<UdfResult<T>> {\n const pre = await classifyDedup(this.store, identity, dedup);\n if (pre) return this.replayResult<T>(pre);\n const commitMeta = dedupCommitMeta(identity, dedup, base);\n let r: UdfResult<T>;\n try {\n r = await this.executor.run<T>(fn, jsonToConvex(args), {\n path,\n namespace: namespaceForPath(path, this.componentNames),\n contextProviders: this.contextProviders,\n policyRegistry: this.policyRegistry,\n policyProviders: this.policyProviders,\n relationRegistry: this.relationRegistry,\n functionKind: this.functionKind,\n identity,\n numShards: this.numShards,\n commitMeta,\n });\n } catch (e) {\n const replay = await handleDedupError(this.store, identity, dedup, e);\n if (replay) return this.replayResult<T>(replay);\n throw e;\n }\n if (!r.committed) {\n await recordZeroWriteApplied(this.store, identity, dedup, r.commitTs, r.value as Value);\n } else if (r.oplog !== null) {\n // A committed WRITE mutation whose guard ran on THIS node's store (a real local oplog — the\n // executor's own per-shard forward, if any, would have left this null). Best-effort fill the\n // value the guard couldn't see at commit time (T5-review recommendation, the B3 pattern).\n await fillWriteMutationValue(this.store, identity, dedup, r.value as Value);\n }\n return r;\n }\n\n /** Wrap a {@link ClientReplay} as a `UdfResult` carrying `clientReplay` — no commit happened. */\n private replayResult<T>(replay: ClientReplay): UdfResult<T> {\n return {\n value: jsonToConvex(replay.value ?? null) as T,\n logs: [],\n committed: false,\n commitTs: replay.commitTs !== undefined ? BigInt(replay.commitTs) : 0n,\n readRanges: [],\n oplog: null,\n clientReplay: replay,\n };\n }\n\n /** Directly invoke an action (for HTTP routes / the CLI `run` command). Public gate: blocks\n * `_`-prefixed paths. Routes through `writeRouter` when set and this node isn't the writer. */\n async runAction<T = unknown>(path: string, args: JSONValue, opts?: { identity?: string | null }): Promise<UdfResult<T>> {\n if (isInternalPath(path)) throw new FunctionNotFoundError(`unknown function: ${path}`);\n const fn = this.modules[path];\n if (!fn) throw new FunctionNotFoundError(`unknown function: ${path}`);\n if (fn.type !== \"action\") throw new Error(`${path} is not an action`);\n if (this.writeRouter && !this.writeRouter.isLocalWriter(DEFAULT_SHARD)) {\n const res = await this.writeRouter.forward(\"action\", path, args, opts?.identity ?? null, DEFAULT_SHARD);\n return this.forwardedResult<T>(res.value);\n }\n return this.executor.run<T>(fn, jsonToConvex(args), {\n path,\n namespace: namespaceForPath(path, this.componentNames),\n contextProviders: this.contextProviders,\n policyRegistry: this.policyRegistry,\n policyProviders: this.policyProviders,\n relationRegistry: this.relationRegistry,\n functionKind: this.functionKind,\n identity: opts?.identity ?? null,\n numShards: this.numShards,\n });\n }\n\n /** Directly invoke an httpAction (for the public HTTP router). Passes the raw `Request` through\n * untouched and returns the handler's `Response`. Public gate: blocks `_`-prefixed paths. */\n async runHttpAction(path: string, request: Request, opts?: { identity?: string | null }): Promise<Response> {\n if (isInternalPath(path)) throw new FunctionNotFoundError(`unknown function: ${path}`);\n const fn = this.modules[path];\n if (!fn) throw new FunctionNotFoundError(`unknown function: ${path}`);\n if (fn.type !== \"httpAction\") throw new Error(`${path} is not an httpAction`);\n const result = await this.executor.run<Response>(fn, request as unknown as never, {\n path,\n namespace: namespaceForPath(path, this.componentNames),\n contextProviders: this.contextProviders,\n policyRegistry: this.policyRegistry,\n policyProviders: this.policyProviders,\n relationRegistry: this.relationRegistry,\n functionKind: this.functionKind,\n identity: opts?.identity ?? null,\n numShards: this.numShards,\n });\n return result.value;\n }\n\n /**\n * The privileged built-in doc mutations whose target is a USER table (and thus may be sharded).\n * These are the ONLY `runSystem` paths that need shard routing — every other `_system:*`/\n * `_storage:*`/`_test:*` built-in writes UNSHARDED component-internal tables, which are owned by\n * the default ring (INSERT from any ring; RMW on default), so they need no override.\n */\n private static readonly DOC_MUTATION_PATHS: ReadonlySet<string> = new Set([\n \"_system:patchDocument\",\n \"_system:deleteDocument\",\n \"_system:insertDocument\",\n ]);\n\n /** Run a privileged built-in (`_system:*`) function. Trusted callers only (the admin API).\n * For a doc mutation on a user table, the target document's OWNING shard is resolved and passed\n * through so the privileged write lands on the same ring a user's sharded mutation of that doc\n * would — one-doc-one-ring. `opts.shardId` lets a trusted caller override the resolution. */\n async runSystem<T = unknown>(\n path: string,\n args: JSONValue,\n opts?: { shardId?: ShardId; commitMeta?: Record<string, string> },\n ): Promise<UdfResult<T>> {\n const fn = this.systemModules[path];\n if (!fn) throw new FunctionNotFoundError(`unknown system function: ${path}`);\n let shardId = opts?.shardId;\n if (shardId === undefined && this.numShards > 1 && EmbeddedRuntime.DOC_MUTATION_PATHS.has(path)) {\n shardId = await this.resolveDocMutationShard(path, args);\n }\n return this.executor.run<T>(fn, jsonToConvex(args), {\n path,\n privileged: true,\n numShards: this.numShards,\n shardId,\n // Fleet B3, D3: see `run()`'s doc comment above — the forwarded-`_system:*`-doc-mutation path\n // (an admin dashboard edit landing on a non-owner) threads the same idempotency key through.\n commitMeta: opts?.commitMeta,\n });\n }\n\n /**\n * Resolve the owning shard for a privileged admin doc mutation so the write commits on the SAME\n * ring a user's sharded mutation of that document would use (the one-doc-one-ring invariant).\n * Without this, a dashboard edit of a sharded doc runs on the default ring and forks the doc's\n * prev_ts chain against its home-shard writer — a permanent tailer halt + a silently-lost update.\n *\n * The shard-key field is IMMUTABLE after insert, so peeking the current doc's key value BEFORE the\n * transaction is race-free (its shard can't have changed by the time the txn opens). An unsharded\n * target (component tables, or app tables with no `.shardKey`) resolves to `\"default\"` — its RMW\n * ring per the same invariant. Called only for `DOC_MUTATION_PATHS` when `numShards > 1`.\n */\n private async resolveDocMutationShard(path: string, args: JSONValue): Promise<ShardId> {\n const a = args as Record<string, unknown>;\n if (path === \"_system:insertDocument\") {\n // INSERT: route by the shard-key value in the incoming fields (privileged uses the raw table name).\n const meta = this.catalog.getTable(a.table as string);\n if (!meta?.shardKey) return DEFAULT_SHARD;\n const fields = a.fields as Record<string, unknown> | undefined;\n return shardIdForKeyValue(fields?.[meta.shardKey], this.numShards);\n }\n // PATCH / DELETE: route by the EXISTING document's immutable shard-key value.\n const internalId = decodeDocumentId(a.id as string);\n const meta = this.catalog.getTableByNumber(internalId.tableNumber);\n if (!meta?.shardKey) return DEFAULT_SHARD;\n const latest = await this.store.get(internalId);\n if (!latest) return DEFAULT_SHARD; // missing → the system fn itself throws DocumentNotFound\n const doc = latest.value.value as Record<string, unknown>;\n return shardIdForKeyValue(doc[meta.shardKey], this.numShards);\n }\n\n /** Run a privileged admin built-in (`_admin:*`) once (e.g. for the HTTP fallback). Trusted callers only. */\n async runAdmin<T = unknown>(path: string, args: JSONValue): Promise<UdfResult<T>> {\n const fn = this.adminModules[path];\n if (!fn) throw new FunctionNotFoundError(`unknown admin function: ${path}`);\n return this.executor.run<T>(fn, jsonToConvex(args), { path, privileged: true, numShards: this.numShards });\n }\n\n /**\n * Run every driver timer that is due (`atMs <= now()`), drop it, and re-arm the host to the new\n * minimum — the firing half of the `EmbeddedRuntimeOptions.wakeHost` seam, called when the host's\n * alarm goes off (`serve`'s `POST /_admin/wake`). It cannot be a direct call: the alarm lives in\n * the host (a Durable Object), across a network boundary from this process.\n *\n * Safe and cheap on both paths through it, so a host never branches:\n * - the process was STOPPED (the common case) — the wake request BOOTS it, the drivers' own\n * `start()` re-derives everything from committed state, and this finds nothing due: a no-op.\n * - the process was RUNNING — this runs the actual pending callback.\n *\n * Also a no-op without a `wakeHost` (nothing arms a wake, and `setTimeout` already fired\n * everything due), so the route being registered on every deployment costs nothing.\n */\n fireDueTimers(): void {\n this.fireDue();\n }\n\n /**\n * Stop the component drivers and clear their pending timers, resetting `driversStarted` so a later\n * `startDrivers()` can bring them back up. Shared by the driver-only `stopDriversOnly()` (B2b, D5)\n * and the full-shutdown `stopDrivers()` — the ONLY difference is whether the sync handler is also\n * disposed, so the two can never drift on how a driver is torn down.\n */\n private async stopDriversInternal(): Promise<void> {\n for (const t of this.timers.values()) if (t.timeout !== undefined) clearTimeout(t.timeout);\n this.timers.clear();\n // Deliberately does NOT `armWake(null)` under a `wakeHost`: the host's alarm is DURABLE and\n // outlives this process — that is the entire point of the seam. A graceful shutdown that\n // cancelled it would leave a Cloudflare deployment with no way to ever wake again (the container\n // stops within seconds of every shutdown). Nothing is lost by leaving it armed: next-wake is\n // re-derived from committed table state on the next `start()`, and an early wake that finds\n // nothing due is a cheap no-op (`fireDueTimers`). The in-process `armedAt` mirror is likewise\n // left alone, so a stop→start cycle that re-derives the SAME minimum correctly skips a re-arm\n // the host doesn't need.\n for (const d of this.drivers) await d.stop?.();\n // Reset the flag (NOT one-way): a stop→start cycle must actually restart the drivers. The shipped\n // `driversStarted` flag was write-once (only ever flipped true), so a fleet node that relinquished\n // and later re-acquired the default shard would silently no-op the restart — the D5 regression.\n this.driversStarted = false;\n }\n\n /**\n * Stop all component drivers and clear all pending driver timers. Call on runtime shutdown.\n * ALSO disposes the sync handler's background flush sweep — this is the full-teardown path.\n */\n async stopDrivers(): Promise<void> {\n await this.stopDriversInternal();\n // Stop the sync handler's background flush sweep (per-session backpressure drain) on shutdown.\n this.handler.dispose();\n }\n\n /**\n * Driver-only stop (B2b, D5 — \"drivers follow the default shard\"): stop the scheduler/workflow/cron/\n * reaper drivers and clear their timers, WITHOUT disposing the sync handler. A fleet node that\n * relinquishes (or gracefully releases) the default shard keeps serving reads, subscriptions, and\n * mutations for every OTHER shard — only its drivers go quiet, because a different node now owns the\n * default ring the scheduler tables live on. Symmetric with `startDrivers()` and idempotent both\n * ways (the reset flag makes a later `startDrivers()` a real restart, and a second stop a no-op),\n * so callers never need to track whether drivers are currently running. Deliberately NEVER touches\n * `handler.dispose()` (the shipped `stopDrivers()` did — fatal on a default-relinquish, since the\n * node stays live).\n */\n async stopDriversOnly(): Promise<void> {\n await this.stopDriversInternal();\n }\n\n /**\n * Start component drivers deferred via `EmbeddedRuntimeOptions.deferDrivers`, OR restart them after\n * a `stopDriversOnly()` (B2b, D5). Idempotent — a second (or later) call is a no-op once drivers are\n * running, so callers don't need to track whether they've already called it (e.g. a fleet node\n * calling this on every default-shard acquisition attempt).\n */\n async startDrivers(): Promise<void> {\n if (this.driversStarted) return;\n this.driversStarted = true;\n for (const d of this.drivers) await d.start(this.driverCtx);\n }\n\n /**\n * Lets a non-writer fleet node advance its local timestamp oracle past timestamps it learns\n * from the writer's change stream, so its own next allocated timestamp (if/when it becomes\n * the writer) never collides with or precedes one it already observed.\n *\n * Fleet B3 (D1) routing: WITHOUT a `queryStore` (`queryOracle` undefined), this is the shipped\n * behavior — delegates straight to the WRITE oracle (`this.oracle`; a `ShardedTransactor` fans\n * it to every shard). WITH a `queryStore` configured, a hybrid node has a real query-path oracle\n * whose sole purpose IS tailer post-apply feeding — so this routes to `queryOracle` INSTEAD, and\n * the write oracle is left untouched by tailer observations (it advances only via this runtime's\n * own local commits, through `ShardWriter.commit`'s `oracle.publishCommitted`). Sharing one\n * oracle between the two would let a query snapshot ABOVE the replica's actual watermark and\n * read holes (D1's spec-review requirement) — this branch is what keeps them separate.\n *\n * This is the READ-PATH observer (tailer/follower freshness → query snapshot). Its write-path\n * counterpart, `observeWriteTimestamp` (below), always targets the WRITE oracle and exists\n * precisely because this method stopped feeding the write side once a hybrid has a query oracle.\n */\n observeTimestamp(ts: bigint): void {\n (this.queryOracle ?? this.oracle).observeTimestamp(ts);\n }\n\n /**\n * Advance the WRITE transactor's timestamp oracle(s) past `ts` — the write-path counterpart to\n * `observeTimestamp` above, and the pre-T1 semantics of what `observeTimestamp` used to do before\n * hybrid routing split the two. ALWAYS targets `this.oracle` (the write side), independent of\n * `queryStore`/`queryOracle` routing: a `ShardedTransactor` fans `ts` to every existing shard\n * oracle AND raises its `observedHighWater` floor (so a shard writer CREATED later seeds at-or-past\n * `ts`); the single-shard `MonotonicTimestampOracle` takes it directly.\n *\n * Purpose (distinct from `observeTimestamp`): re-floor the WRITE snapshot on a shard OWNERSHIP\n * CHANGE. On a hybrid node `observeTimestamp` feeds the QUERY oracle, so nothing feeds the write\n * oracle from foreign observations anymore. A shard this node held, RELEASED (its `ShardWriter`\n * stays in the transactor's Map — only the fleet epoch is dropped), and later RE-ACQUIRES would\n * keep that `ShardWriter`'s oracle frozen at this node's own last commit; the next mutation would\n * snapshot BELOW an interim owner's commits and an RMW handler would compute on stale state (the\n * durable chain stays intact via latest-`prev_ts`, but the update is semantically lost). The fleet\n * calls this on EVERY shard acquisition with the lease row's `frontier_ts` — which is >= every\n * prior commit on that shard by the fence invariant (the commit guard writes `frontier_ts =\n * GREATEST(frontier_ts, commitTs)` inside each commit txn) — so it is the exact correct floor.\n * Idempotent/monotone: a `ts` at or below the oracle's position is a no-op (harmless on a\n * fresh/never-released shard, and on every non-hybrid node where it is called uniformly too).\n */\n observeWriteTimestamp(ts: bigint): void {\n this.oracle.observeTimestamp(ts);\n }\n\n /**\n * Run `fn` under shard `shardId`'s commit mutex IFF that shard is idle right now — the seam a fleet\n * writer's idle-frontier closer uses to publish a shard's frontier atomically with respect to that\n * shard's own commits (see `ShardedTransactor.tryRunExclusiveOnShard`). A shard is idle only when\n * the commit mutex is free AND no group-commit batch is staged/flushing (Fleet B4: the flush runs\n * OFF the mutex, so mutex-freedom alone is not enough — a mid-flush batch has ts's drawn but rows\n * not yet landed, and must read as busy to keep the closer from publishing a frontier above them).\n * Returns `true` if `fn` ran, `false` if the shard is busy (skip; retry next beat). Total across\n * sharded/single-shard runtimes — the single-shard transactor ignores `shardId` and uses its one\n * writer.\n */\n tryRunExclusiveOnShard(shardId: ShardId, fn: () => Promise<void>): Promise<boolean> {\n return this.transactor.tryRunExclusiveOnShard(shardId, fn);\n }\n\n /**\n * Group-commit counters (Fleet B4, T4 health) — total across the transactor, whichever shape it\n * is: `ShardedTransactor.groupCommitStats()` aggregates over every live shard,\n * `SingleWriterTransactor.groupCommitStats()` mirrors it for the one writer. Both are\n * structurally all-zero when `EmbeddedRuntimeOptions.groupCommit` is unset/false (the underlying\n * `ShardWriter` never touches these fields on the single-commit path) — callers need no separate\n * on/off branch. The fleet health seam (`@helipod/fleet`'s `node.ts`) reads this to derive\n * `flushesPerSec` between successive `/api/health` reads.\n */\n groupCommitStats(): { lastBatchSize: number; maxBatchSize: number; flushCount: number } {\n return this.transactor.groupCommitStats();\n }\n}\n\nexport function createEmbeddedRuntime(options: EmbeddedRuntimeOptions): Promise<EmbeddedRuntime> {\n return EmbeddedRuntime.create(options);\n}\n","/**\n * The transactor→sync fan-out seam (scale-seam #4). A committed `OplogDelta` is published as\n * a fully-serializable payload to a swappable `EmbeddedWriteFanoutAdapter`. At Tier 0 the\n * adapter is in-memory; swap it for BroadcastChannel / Redis / Queues and the SAME fan-out\n * spans many processes — with no change to app code. Each fan-out tags its `originId` so a\n * subscriber can ignore its own writes (avoiding a self-loop across processes).\n */\nimport type { SerializedKeyRange } from \"@helipod/index-key-codec\";\nimport type { OplogDelta, WriteFanout, WrittenDoc } from \"@helipod/transactor\";\n\nexport interface EmbeddedWriteFanoutPayload {\n commitTs: number;\n tables: string[];\n ranges: SerializedKeyRange[];\n originId: string;\n /**\n * G4 origin-frontier tag (client-sync verdict §(d) item 2) — the originating sync SESSION id,\n * sourced verbatim from `OplogDelta.origin`. Distinct from `originId` (the fleet-node/process\n * origin used for the cross-process self-loop guard): this is a per-commit ephemeral session tag\n * the drain hands to `handler.notifyWrites(inv, origin)` so the origin session's `version.ts` is\n * advanced past its own commit. Undefined for commits with no originating session.\n */\n origin?: string;\n /** The shard this commit landed on (Fenced Frontier B1, D6) — sourced verbatim from\n * `OplogDelta.shardId`. Additive: single-shard (Tier 0/B1) deployments always see `\"default\"`\n * (`DEFAULT_SHARD`); a multi-shard fan-out consumer (B2+) can use it to route/filter, but every\n * existing consumer today ignores it. */\n shardId: string;\n /** Written documents for local row-diffing (§DLR 2a) — sourced verbatim from\n * `OplogDelta.writtenDocs`. Present only on the local in-process fan-out (this adapter always\n * runs in-process at Tier 0/1); absent if a future cross-process adapter swap doesn't carry it. */\n writtenDocs?: WrittenDoc[];\n}\n\nexport type FanoutListener = (payload: EmbeddedWriteFanoutPayload) => void;\n\nexport interface EmbeddedWriteFanoutAdapter {\n publish(payload: EmbeddedWriteFanoutPayload): void;\n subscribe(listener: FanoutListener): () => void;\n}\n\n/** The default Tier 0 adapter: an in-process channel (also records what it published). */\nexport class InMemoryWriteFanoutAdapter implements EmbeddedWriteFanoutAdapter {\n private readonly listeners = new Set<FanoutListener>();\n readonly published: EmbeddedWriteFanoutPayload[] = [];\n\n publish(payload: EmbeddedWriteFanoutPayload): void {\n this.published.push(payload);\n for (const listener of this.listeners) listener(payload);\n }\n\n subscribe(listener: FanoutListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n}\n\n/** Implements the transactor's `WriteFanout` over a swappable adapter. */\nexport class EmbeddedWriteFanout implements WriteFanout {\n constructor(\n private readonly adapter: EmbeddedWriteFanoutAdapter,\n private readonly originId: string,\n ) {}\n\n publish(delta: OplogDelta): void {\n this.adapter.publish({\n commitTs: Number(delta.commitTs),\n tables: delta.writtenTables,\n ranges: delta.writtenRanges,\n originId: this.originId,\n origin: delta.origin,\n shardId: delta.shardId,\n writtenDocs: delta.writtenDocs,\n });\n }\n\n /** Subscribe to deltas from OTHER origins (ignores our own — the Tier 2 self-loop guard). */\n subscribe(listener: FanoutListener): () => void {\n return this.adapter.subscribe((payload) => {\n if (payload.originId !== this.originId) listener(payload);\n });\n }\n}\n","/**\n * In-memory loopback transport. A `LoopbackConnection` is the client end of an in-process\n * \"WebSocket\": `send` delivers a client message straight to the sync handler, and the\n * handler's server-side socket delivers messages straight back to the connection's\n * listeners. No sockets, no serialization-over-the-wire — but the EXACT same `SyncWebSocket`\n * the handler talks to, so a real WebSocket transport drops in unchanged at Tier 2.\n */\nimport type { SyncWebSocket } from \"@helipod/sync\";\nimport { parseClientMessage, type ClientMessage, type ServerMessage } from \"@helipod/sync\";\n\nexport type ServerMessageListener = (msg: ServerMessage) => void;\n\nexport interface LoopbackConnection {\n readonly sessionId: string;\n /** Client → server. Resolves once the handler has finished processing (loopback is synchronous). */\n send(message: ClientMessage | string): Promise<void>;\n /** Register a server → client listener; returns an unsubscribe. */\n onMessage(listener: ServerMessageListener): () => void;\n close(): void;\n}\n\n/** Server-side socket the handler sends through; forwards to the connection's listeners. */\nclass LoopbackServerSocket implements SyncWebSocket {\n readonly bufferedAmount = 0;\n private readonly listeners = new Set<ServerMessageListener>();\n private open = true;\n\n send(data: string): void {\n if (!this.open) return;\n const msg = JSON.parse(data) as ServerMessage;\n for (const listener of this.listeners) listener(msg);\n }\n\n close(): void {\n this.open = false;\n }\n\n addListener(listener: ServerMessageListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n}\n\nexport interface LoopbackHandler {\n connect(sessionId: string, socket: SyncWebSocket): void;\n disconnect(sessionId: string): void;\n handleMessage(sessionId: string, raw: string): Promise<void>;\n}\n\nexport function createLoopbackConnection(handler: LoopbackHandler, sessionId: string): LoopbackConnection {\n const socket = new LoopbackServerSocket();\n handler.connect(sessionId, socket);\n\n return {\n sessionId,\n async send(message: ClientMessage | string): Promise<void> {\n const raw = typeof message === \"string\" ? message : JSON.stringify(message);\n // Validate shape eagerly so malformed client messages fail at the call site.\n parseClientMessage(raw);\n await handler.handleMessage(sessionId, raw);\n },\n onMessage(listener: ServerMessageListener): () => void {\n return socket.addListener(listener);\n },\n close(): void {\n socket.close();\n handler.disconnect(sessionId);\n },\n };\n}\n","/**\n * Client-mutation dedup classification (the Receipted Outbox, verdict §(c)) — the OWNER-side half of\n * the resend-exactly-once contract. These helpers run WHERE THE COMMIT RUNS (single-node locally, or\n * the owning writer on a fleet forward — verdict §(c) repair 3), never in the sync handler and never\n * against a follower's replica. The sync handler only threads `{clientId, seq}` down and interprets\n * the discriminated replay.\n *\n * Two enforcement layers, per the verdict:\n * - CLASSIFICATION (the fast path): a pre-read of `getClientVerdict`/`getClientFloor`. It can race a\n * concurrent duplicate (no lock spans read→commit), so it is an OPTIMISATION, not the barrier.\n * - The COMMIT GUARD (the barrier): {@link clientReceiptsGuard} INSERTs the `applied` receipt inside\n * the mutation's own commit transaction — a PK collision is the dedup signal, thrown as a typed\n * {@link CommitGuardRejection} whose loser re-reads the winner's row and replay-acks.\n */\nimport {\n CommitGuardRejection,\n isRetryableError,\n isHelipodError,\n} from \"@helipod/errors\";\nimport type { ShardId } from \"@helipod/id-codec\";\nimport type { ClientReplay } from \"@helipod/executor\";\nimport type { ClientMutationVerdict } from \"@helipod/sync\";\nimport { convexToJson, type JSONValue, type Value } from \"@helipod/values\";\nimport type { CommitGuardUnit, DocStore, ClientVerdictRecord } from \"@helipod/docstore\";\n\n/** The durable per-tab dedup key threaded from the wire (`Mutation.clientId`/`seq`). */\nexport interface DedupKey {\n clientId: string;\n seq: number;\n}\n\n// The `CommitGuardUnit.meta` keys the receipts guard reads (the dedup key rides the EXISTING meta\n// channel — no `CommitUnit`/`CommitGuardUnit` shape change, the T2/T4 de-conflict). `seq` is\n// stringified only at this meta boundary (wire/store keep it a JS number — verdict Risk R10).\nexport const DEDUP_META_CLIENT_ID = \"clientId\";\nexport const DEDUP_META_SEQ = \"seq\";\nexport const DEDUP_META_IDENTITY = \"identity\";\n\n/** Anonymous clients key as identity `\"\"` (verdict §(c)). */\nfunction identityKey(identity: string | null): string {\n return identity ?? \"\";\n}\n\n/** Map a stored `ClientVerdictRecord` to the wire replay shape (verdict §(c) \"Classification\"). */\nexport function replayFromRecord(rec: ClientVerdictRecord): ClientReplay {\n if (rec.verdict === \"applied\") {\n return {\n verdict: \"applied\",\n commitTs: Number(rec.commitTs),\n ...(rec.hasValue ? { value: rec.value as JSONValue } : { valueMissing: true }),\n };\n }\n return { verdict: \"failed\", commitTs: Number(rec.commitTs), code: rec.errorCode ?? \"MUTATION_FAILED\" };\n}\n\n/**\n * The classification pre-read: a recorded verdict short-circuits to a replay (no run); a `seq` at or\n * below the floor with no record is `stale` (loudly disowned, never re-executed — verdict §(b)); a\n * miss above the floor returns `null` → the caller RUNS the mutation with the dedup key on the commit\n * meta. Reads the verdict BEFORE the floor so a still-present record always wins over a floor that\n * happens to cover its seq (a floor never regresses, but a record can outlive being covered).\n */\nexport async function classifyDedup(\n store: DocStore,\n identity: string | null,\n dedup: DedupKey,\n): Promise<ClientReplay | null> {\n const id = identityKey(identity);\n const rec = await store.getClientVerdict(id, dedup.clientId, dedup.seq);\n if (rec) return replayFromRecord(rec);\n const floor = await store.getClientFloor(id, dedup.clientId);\n if (floor !== null && dedup.seq <= floor) return { verdict: \"stale\", code: \"STALE_CLIENT\" };\n return null;\n}\n\n/** The read-only `Connect`-handshake classifier (verdict §(e)): the same read as {@link classifyDedup}\n * but a miss maps to `\"unknown\"` (never seen — the client should resend) rather than \"run now\". */\nexport async function classifyForConnect(\n store: DocStore,\n identity: string | null,\n clientId: string,\n seq: number,\n): Promise<ClientMutationVerdict> {\n const replay = await classifyDedup(store, identity, { clientId, seq });\n if (replay === null) return { clientId, seq, verdict: \"unknown\" };\n return { clientId, seq, ...replay };\n}\n\n/** Build the commit meta that carries the dedup key to the receipts guard (merged onto any base\n * meta, e.g. fleet's `idempotencyKey` — the two guards read disjoint keys, verdict Risk R2). */\nexport function dedupCommitMeta(\n identity: string | null,\n dedup: DedupKey,\n base?: Record<string, string>,\n): Record<string, string> {\n return {\n ...(base ?? {}),\n [DEDUP_META_IDENTITY]: identityKey(identity),\n [DEDUP_META_CLIENT_ID]: dedup.clientId,\n [DEDUP_META_SEQ]: String(dedup.seq),\n };\n}\n\n/**\n * Handle an error thrown by a dedup-keyed run (verdict §(c)):\n * - the receipts guard's `CLIENT_MUTATION_DUP` PK collision (this attempt lost the commit race) →\n * re-read the winner's row and replay-ack it (or, if the winner isn't visible yet, `null` → the\n * caller rethrows the retryable rejection);\n * - a DETERMINISTIC terminal app error (not retryable — a handler throw, validation, authz) → record\n * a standalone `failed` verdict (skip-and-record poison default; `ON CONFLICT DO NOTHING` makes a\n * concurrent poison-resend race harmless) and return `null` → the caller rethrows the original;\n * - a transient/conflict error (retryable) → record nothing, return `null` → the caller rethrows so\n * the client retries with backoff.\n */\nexport async function handleDedupError(\n store: DocStore,\n identity: string | null,\n dedup: DedupKey,\n e: unknown,\n): Promise<ClientReplay | null> {\n const id = identityKey(identity);\n if (e instanceof CommitGuardRejection && e.rejectionCode === \"CLIENT_MUTATION_DUP\") {\n const rec = await store.getClientVerdict(id, dedup.clientId, dedup.seq);\n return rec ? replayFromRecord(rec) : null;\n }\n if (!isRetryableError(e)) {\n const code = isHelipodError(e) ? e.code : \"MUTATION_FAILED\";\n await store.recordClientVerdict(id, dedup.clientId, dedup.seq, { verdict: \"failed\", commitTs: 0n, errorCode: code });\n }\n return null;\n}\n\n/** Record the `applied` receipt for a ZERO-WRITE successful mutation (verdict §(c) Risk R1 / OUTBOX-A\n * T1 controller decision): a no-doc commit never reaches the store, so the receipts guard never runs\n * for it — its receipt (WITH the return value) is written standalone here, post-run. A mutation that\n * DID write documents gets its receipt from the guard instead, and this is a no-op for it. */\nexport async function recordZeroWriteApplied(\n store: DocStore,\n identity: string | null,\n dedup: DedupKey,\n commitTs: bigint,\n value: Value,\n): Promise<void> {\n await store.recordClientVerdict(identityKey(identity), dedup.clientId, dedup.seq, {\n verdict: \"applied\",\n commitTs,\n value: convexToJson(value),\n });\n}\n\n/**\n * Best-effort post-run value fill for a COMMITTED WRITE mutation's guard-inserted `applied` receipt\n * (the B3 pattern — `LeaseManager.recordIdempotencyValue`'s sibling for client receipts; T5-review\n * recommendation). `clientReceiptsGuard` only ever sees `commitTs` when it INSERTs the receipt inside\n * the commit transaction (the return VALUE isn't known there) — this fills it in AFTER the run\n * returns, via `DocStore.updateClientVerdictValue`, so a later `applied` replay carries the real value\n * instead of `valueMissing`. Errors are swallowed here (never rethrown): a failure must NOT fail an\n * otherwise-successful mutation response — a replay for this seq then reports `valueMissing: true`\n * forever, the SAME outcome as the pre-existing crash-window gap (the value UPDATE never having run at\n * all), which Plan B's client already tolerates via the wire's `valueMissing` field. Call ONLY when\n * this node's OWN commit ran the guard (a fresh commit with dedup — never for a replay, and never for\n * a forwarded write whose guard ran on a DIFFERENT node's store).\n */\nexport async function fillWriteMutationValue(\n store: DocStore,\n identity: string | null,\n dedup: DedupKey,\n value: Value,\n): Promise<void> {\n try {\n await store.updateClientVerdictValue(identityKey(identity), dedup.clientId, dedup.seq, convexToJson(value));\n } catch {\n // Best-effort — see the doc comment above. A later replay for this seq simply reports\n // `valueMissing: true`, same as the pre-existing crash-window gap.\n }\n}\n\n/**\n * The `applied`-receipt commit guard (registered ONCE at runtime construction, BEFORE fleet's epoch\n * fence — verdict §(c) Risk R6). For every unit whose `meta` carries a dedup key, INSERTs the\n * `client_mutations` receipt at that unit's own `ts`, inside the mutation's commit transaction. The\n * INSERT is PLAIN (never `ON CONFLICT DO NOTHING`): a PK collision IS the dedup signal — it means a\n * concurrent duplicate already committed this seq, so we throw a typed {@link CommitGuardRejection}\n * (`CLIENT_MUTATION_DUP`) carrying this unit's index. On the single-commit path it propagates as this\n * mutation's own rejection (the caller replay-reads the winner); under group commit the transactor's\n * split-retry rejects ONLY this unit and re-flushes the innocent remainder. A unit with no dedup key\n * (every ordinary mutation) is skipped — the whole guard costs a deployment nothing until the outbox\n * is used.\n *\n * Store-agnostic by querier shape (verdict Risk R9 — the guard is ONE closure, not two): a Postgres\n * `PgQuerier` exposes async `query()`; a `SqliteGuardQuerier` exposes synchronous `run()`. The SQLite\n * branch runs fully synchronously and returns `undefined` (void) — it MUST, because SQLite's commit\n * is one synchronous transaction that cannot await a guard (a returned thenable there is a dev-time\n * error). The Postgres branch returns a Promise the async `commitWriteBatch` awaits.\n */\nexport function clientReceiptsGuard(): (\n q: unknown,\n units: readonly CommitGuardUnit[],\n shardId: ShardId,\n) => void | Promise<void> {\n const INSERT = `INSERT INTO client_mutations (identity, client_id, seq, verdict, commit_ts, value_json, error_code, created_at)`;\n return (q, units) => {\n const pg = q as { query?: (text: string, params?: readonly unknown[]) => Promise<unknown> };\n if (typeof pg.query === \"function\") {\n // Postgres: async — return the awaited chain.\n return (async () => {\n for (let i = 0; i < units.length; i++) {\n const dedup = readUnitDedup(units[i]!);\n if (!dedup) continue;\n try {\n await pg.query!(\n `${INSERT} VALUES ($1, $2, $3, 'applied', $4, NULL, NULL, $5)`,\n [dedup.identity, dedup.clientId, BigInt(dedup.seq), units[i]!.ts, BigInt(Date.now())],\n );\n } catch (e) {\n throw toDupOrRethrow(e, i, dedup);\n }\n }\n })();\n }\n // SQLite: synchronous — no Promise may escape.\n const sq = q as { run: (sql: string, ...params: unknown[]) => void };\n for (let i = 0; i < units.length; i++) {\n const dedup = readUnitDedup(units[i]!);\n if (!dedup) continue;\n try {\n sq.run(\n `${INSERT} VALUES (?, ?, ?, 'applied', ?, NULL, NULL, ?)`,\n dedup.identity,\n dedup.clientId,\n dedup.seq,\n units[i]!.ts,\n Date.now(),\n );\n } catch (e) {\n throw toDupOrRethrow(e, i, dedup);\n }\n }\n return undefined;\n };\n}\n\nfunction readUnitDedup(unit: CommitGuardUnit): { identity: string; clientId: string; seq: number } | null {\n const meta = unit.meta;\n const clientId = meta?.[DEDUP_META_CLIENT_ID];\n const seqStr = meta?.[DEDUP_META_SEQ];\n if (clientId === undefined || seqStr === undefined) return null;\n return { identity: meta![DEDUP_META_IDENTITY] ?? \"\", clientId, seq: Number(seqStr) };\n}\n\n/** Convert a PK-collision driver error to the typed `CLIENT_MUTATION_DUP` rejection; rethrow anything\n * else. Postgres uses SQLSTATE `23505`; SQLite exposes a `SQLITE_CONSTRAINT*` code on some drivers\n * and only a message (`node:sqlite`/`bun:sqlite`) on others. The `client_mutations` PK is the ONLY\n * unique constraint this INSERT can violate, so a unique-violation here is unambiguously the dedup\n * collision — matching the message is safe. */\nfunction toDupOrRethrow(e: unknown, unitIndex: number, dedup: { clientId: string; seq: number }): unknown {\n const code = String((e as { code?: unknown }).code ?? \"\");\n const message = String((e as { message?: unknown })?.message ?? \"\");\n const isUniqueViolation =\n code === \"23505\" || code.startsWith(\"SQLITE_CONSTRAINT\") || /unique constraint failed/i.test(message);\n if (isUniqueViolation) {\n return new CommitGuardRejection(unitIndex, \"CLIENT_MUTATION_DUP\", `client=${dedup.clientId} seq=${dedup.seq}`, {\n cause: e,\n });\n }\n return e;\n}\n"],"mappings":"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","names":["convexToJson","convexToJson","meta"]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@helipod/runtime-embedded",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "FSL-1.1-Apache-2.0",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "test": "vitest run",
22
+ "typecheck": "tsc --noEmit",
23
+ "clean": "rm -rf dist .turbo"
24
+ },
25
+ "dependencies": {
26
+ "@helipod/component": "0.1.0",
27
+ "@helipod/docstore": "0.1.0",
28
+ "@helipod/docstore-d1": "0.1.0",
29
+ "@helipod/errors": "0.1.0",
30
+ "@helipod/executor": "0.1.0",
31
+ "@helipod/id-codec": "0.1.0",
32
+ "@helipod/index-key-codec": "0.1.0",
33
+ "@helipod/query-engine": "0.1.0",
34
+ "@helipod/sync": "0.1.0",
35
+ "@helipod/transactor": "0.1.0",
36
+ "@helipod/values": "0.1.0"
37
+ },
38
+ "devDependencies": {
39
+ "@helipod/docstore-sqlite": "0.1.0",
40
+ "@types/better-sqlite3": "^7.6.12",
41
+ "better-sqlite3": "^11.8.0",
42
+ "tsup": "^8.3.5",
43
+ "typescript": "^5.7.2",
44
+ "vitest": "^2.1.8"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/helipod-sh/helipod.git",
52
+ "directory": "packages/runtime-embedded"
53
+ },
54
+ "homepage": "https://github.com/helipod-sh/helipod"
55
+ }