@tinycloud/replica 0.2.4-beta.2 → 0.3.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/browser.d.ts +6 -0
- package/dist/browser.js +7 -1
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +20 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +20 -2
- package/dist/index.js.map +1 -1
- package/dist/kv-storage-testing.d.ts +83 -0
- package/dist/kv-storage-testing.js +1145 -0
- package/dist/kv-storage-testing.js.map +1 -0
- package/dist/kv-storage.d.ts +155 -0
- package/dist/kv-storage.js +2587 -0
- package/dist/kv-storage.js.map +1 -0
- package/dist/kv-storage.worker.618d3a20b6f3f54ed78b68f1dc244dddc3daba46e91e9ae2b577685cc9339315.js +18891 -0
- package/dist/kv-storage.worker.d.ts +2 -0
- package/dist/kv-storage.worker.js +18891 -0
- package/dist/kv-storage.worker.js.map +1 -0
- package/dist/profile-gate.cjs +560 -0
- package/dist/profile-gate.cjs.map +1 -0
- package/dist/profile-gate.d.cts +89 -0
- package/dist/profile-gate.d.ts +89 -0
- package/dist/profile-gate.js +517 -0
- package/dist/profile-gate.js.map +1 -0
- package/dist/replica.worker.js +444 -171
- package/dist/replica.worker.js.map +1 -1
- package/dist/sqlite.cjs +926 -239
- package/dist/sqlite.cjs.map +1 -1
- package/dist/sqlite.d.cts +77 -8
- package/dist/sqlite.d.ts +77 -8
- package/dist/sqlite.js +914 -229
- package/dist/sqlite.js.map +1 -1
- package/dist/{types-f3-kYLQZ.d.cts → types-CQ61VnsP.d.cts} +1 -1
- package/dist/{types-f3-kYLQZ.d.ts → types-CQ61VnsP.d.ts} +1 -1
- package/package.json +20 -3
package/dist/sqlite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sqlite/store.ts","../src/errors.ts","../../sdk-services/src/kv/replication/prefix.ts","../src/scope.ts","../src/sqlite/driver.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { closeSync, constants as fsConstants, fstatSync, lstatSync, openSync, readdirSync, readlinkSync, type BigIntStats, type Stats } from \"node:fs\";\nimport { chmod, link, lstat, mkdir, open, readFile, readdir, rm, rmdir, stat, unlink } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport { ReplicaError, ReplicaErrorCode, isReplicaError } from \"../errors.js\";\nimport { assertFolderPrefix, effectiveAuthority } from \"../scope.js\";\nimport type {\n Coverage,\n GrantRecord,\n LeaseToken,\n ListOpts,\n LocalEntry,\n LocalReadPolicy,\n ReplicaConfig,\n ReplicaLastError,\n ReplicaState,\n ReplicaStatus,\n ReplicaStore,\n VerifiedPage,\n} from \"../types.js\";\nimport { loadSqlite, type SqliteDatabase, type SqliteOpener, type SqlValue } from \"./driver.js\";\n\nconst SCHEMA_VERSION = 1;\n\n// Descriptor discovery below is process-wide. Keep native SQLite opens from\n// overlapping so another store's new descriptor cannot be mistaken for this one.\nlet sqliteOpenQueue: Promise<void> = Promise.resolve();\nasync function acquireSqliteOpen(): Promise<() => void> {\n const previous = sqliteOpenQueue;\n let release!: () => void;\n sqliteOpenQueue = new Promise<void>((resolve) => { release = resolve; });\n await previous;\n return release;\n}\n\ntype NamedPathIdentity = { path: string; dev: bigint; ino: bigint };\n\nasync function captureNamedPath(path: string): Promise<NamedPathIdentity[]> {\n const names: string[] = [];\n for (let current = resolve(path); ; current = dirname(current)) {\n names.push(current);\n if (dirname(current) === current) break;\n }\n const identities: NamedPathIdentity[] = [];\n for (const name of names.reverse()) {\n const stats = await lstat(name, { bigint: true });\n identities.push({ path: name, dev: stats.dev, ino: stats.ino });\n }\n return identities;\n}\nexport const DURABILITY = \"sqlite-wal-synchronous-full+fsynced-blobs\";\n\nconst SCHEMA = `\nCREATE TABLE IF NOT EXISTS replica (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n name TEXT NOT NULL,\n replica_id TEXT NOT NULL,\n host TEXT NOT NULL,\n space TEXT NOT NULL,\n prefix TEXT NOT NULL,\n device_did TEXT NOT NULL,\n allow_secrets INTEGER NOT NULL CHECK (allow_secrets IN (0, 1)),\n local_read_policy TEXT NOT NULL CHECK (local_read_policy IN ('whileGrantValid', 'retainAfterExpiry')),\n retention_grant_cid TEXT,\n grant_cid TEXT,\n grant_bytes BLOB,\n grant_audience TEXT,\n grant_issuer TEXT,\n grant_nbf INTEGER,\n grant_exp INTEGER,\n pending_grant_cid TEXT,\n pending_grant_bytes BLOB,\n pending_grant_audience TEXT,\n pending_grant_issuer TEXT,\n pending_grant_nbf INTEGER,\n pending_grant_exp INTEGER,\n node_did TEXT,\n attested INTEGER NOT NULL DEFAULT 0 CHECK (attested IN (0, 1)),\n not_before TEXT,\n expires_at TEXT,\n retain_until TEXT,\n revoked_detail TEXT,\n purge_pending INTEGER NOT NULL DEFAULT 0 CHECK (purge_pending IN (0, 1)),\n retention_revoked TEXT,\n pending_grant_error TEXT,\n cursor TEXT,\n coverage TEXT NOT NULL CHECK (coverage IN ('empty', 'bootstrapping', 'complete')),\n generation INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n last_sync_at TEXT,\n last_complete_at TEXT,\n last_error TEXT,\n last_reset TEXT,\n lease_token INTEGER NOT NULL DEFAULT 0,\n lease_holder TEXT,\n lease_expires_at INTEGER\n) STRICT;\nCREATE TABLE IF NOT EXISTS entry (\n key TEXT PRIMARY KEY,\n deleted INTEGER NOT NULL CHECK (deleted IN (0, 1)),\n etag TEXT,\n hash TEXT,\n metadata TEXT NOT NULL,\n content INTEGER NOT NULL CHECK (content IN (0, 1)),\n size INTEGER,\n CHECK (\n (deleted = 1 AND etag IS NULL AND hash IS NULL AND content = 0 AND size IS NULL) OR\n (deleted = 0 AND etag IS NOT NULL AND hash IS NOT NULL)\n )\n) STRICT, WITHOUT ROWID;\nCREATE INDEX IF NOT EXISTS entry_hash ON entry (hash) WHERE hash IS NOT NULL;\n`;\n\ntype ReplicaRow = {\n name: string;\n replica_id: string;\n host: string;\n space: string;\n prefix: string;\n device_did: string;\n allow_secrets: number;\n local_read_policy: LocalReadPolicy;\n retention_grant_cid: string | null;\n grant_cid: string | null;\n grant_bytes: Uint8Array | null;\n grant_audience: string | null;\n grant_issuer: string | null;\n grant_nbf: number | null;\n grant_exp: number | null;\n pending_grant_cid: string | null;\n pending_grant_bytes: Uint8Array | null;\n pending_grant_audience: string | null;\n pending_grant_issuer: string | null;\n pending_grant_nbf: number | null;\n pending_grant_exp: number | null;\n node_did: string | null;\n attested: number;\n not_before: string | null;\n expires_at: string | null;\n retain_until: string | null;\n revoked_detail: string | null;\n purge_pending: number;\n retention_revoked: string | null;\n pending_grant_error: string | null;\n cursor: string | null;\n coverage: Coverage;\n generation: number;\n created_at: string;\n last_sync_at: string | null;\n last_complete_at: string | null;\n last_error: string | null;\n last_reset: string | null;\n lease_token: number;\n lease_holder: string | null;\n lease_expires_at: number | null;\n};\n\ntype EntryRow = {\n key: string;\n deleted: number;\n etag: string | null;\n hash: string | null;\n metadata: string;\n content: number;\n};\n\nfunction grantOf(\n cid: string | null,\n bytes: Uint8Array | null,\n audience: string | null,\n issuer: string | null,\n nbf: number | null,\n exp: number | null,\n): GrantRecord | null {\n if (cid === null || bytes === null || audience === null || issuer === null) return null;\n return { cid, bytes: new Uint8Array(bytes), audience, issuer, notBefore: nbf, expiresAt: exp };\n}\n\nfunction entryOf(row: EntryRow): LocalEntry {\n if (row.deleted === 1) return { key: row.key, deleted: true };\n return {\n key: row.key,\n deleted: false,\n etag: row.etag!,\n hash: row.hash!,\n metadata: JSON.parse(row.metadata) as Record<string, string>,\n content: row.content === 1,\n };\n}\n\nfunction storageError(error: unknown, action: string): ReplicaError {\n if (isReplicaError(error)) return error;\n const code = errnoOf(error);\n const message = error instanceof Error ? error.message : String(error);\n if (code === \"ENOSPC\" || code === \"EDQUOT\" || /SQLITE_FULL|database or disk is full/i.test(`${String(code)} ${message}`)) {\n return new ReplicaError(ReplicaErrorCode.STORAGE_FULL, `${action}: the local disk is full.`, undefined, { cause: error });\n }\n return new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, `${action}: ${message}`, undefined, { cause: error });\n}\n\nconst isHash = (name: string) => /^[0-9a-f]{64}$/.test(name);\n\nfunction errnoOf(error: unknown): unknown {\n return typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n}\n\n\n/** A directory's entries; only a directory that does not exist is empty. */\nasync function entriesOf(path: string): Promise<string[]> {\n try {\n return await readdir(path);\n } catch (error) {\n if (errnoOf(error) === \"ENOENT\") return [];\n throw error;\n }\n}\n\n/** Crash- and race-test seam: called at the durability boundaries of `applyPage`. */\nexport type StoreFaults = {\n /** Blobs are durable; no row references them yet. */\n afterBlobs?(): void | Promise<void>;\n /** Rows and cursor are written inside the open transaction, not committed. */\n beforeCommit?(): void;\n /** The page is committed. */\n afterCommit?(): void;\n /** A revocation purge is committed; its blobs are not unlinked yet. */\n afterPurgeMark?(): void;\n};\n\n/**\n * Runs a mutation section (every database write and every filesystem\n * change). The CLI passes one that holds the profile lock briefly and\n * refuses when the profile was deleted, so a command never writes into or\n * recreates a deleted profile.\n */\nexport type MutationGuard = <T>(section: () => Promise<T>) => Promise<T>;\n\nexport type SqliteReplicaStoreOptions = {\n /** Create the replica directory and database if missing (else REPLICA_NOT_FOUND). */\n create: boolean;\n /** A checked entry's inode: reject replacement before SQLite sees its path. */\n expectedDirectory?: { dev: number; ino: number };\n sqlite?: SqliteOpener;\n /** Clock for leases and status (ms since epoch). */\n now?: () => number;\n guard?: MutationGuard;\n};\n\n/** Crash-test seam key. Only tests import it (from this module, not the package entry). */\nexport const FAULTS = Symbol(\"tinycloud.replica.faults\");\ntype InternalOptions = SqliteReplicaStoreOptions & { [FAULTS]?: StoreFaults };\n\n/** Stores may be abandoned without close by callers; release their directory descriptor on collection. */\nconst pinnedDirectories = new FinalizationRegistry<number>((fd) => {\n try { closeSync(fd); } catch { /* The process may already be shutting down. */ }\n});\n\n/**\n * The CLI replica store: SQLite (WAL, synchronous=FULL) for entries, cursor\n * and authority, committed in one transaction per page; content-addressed\n * blob files written with fsync + link before any row references them.\n */\nexport class SqliteReplicaStore implements ReplicaStore {\n readonly dir: string;\n readonly #db: SqliteDatabase;\n readonly #pinnedDir: string;\n #directoryFd?: number;\n readonly #holder = `${process.pid}-${randomBytes(6).toString(\"hex\")}`;\n readonly #now: () => number;\n readonly #faults: StoreFaults;\n readonly #guard: MutationGuard;\n /** Identity of the database file this store opened: a deleted-and-recreated replica is a different file. */\n readonly #ino: number;\n readonly #dev: number;\n readonly #namedAncestors: readonly NamedPathIdentity[];\n\n private constructor(dir: string, db: SqliteDatabase, identity: { dev: number; ino: number }, options: SqliteReplicaStoreOptions, directoryFd?: number, namedAncestors: readonly NamedPathIdentity[] = []) {\n this.dir = dir;\n this.#pinnedDir = directoryFd !== undefined && process.platform === \"linux\" ? `/proc/self/fd/${directoryFd}` : dir;\n this.#directoryFd = directoryFd;\n if (directoryFd !== undefined) pinnedDirectories.register(this, directoryFd, this);\n this.#db = db;\n this.#ino = identity.ino;\n this.#dev = identity.dev;\n this.#now = options.now ?? Date.now;\n this.#faults = (options as InternalOptions)[FAULTS] ?? {};\n this.#guard = options.guard ?? ((section) => section());\n this.#namedAncestors = namedAncestors;\n }\n\n /**\n * Read-only status snapshot; does not create a replica, migrate, recover\n * revocation cleanup, or enter the mutation guard. An existing database is\n * opened normally in read-only WAL mode so committed WAL state is visible.\n */\n\n static async inspect(\n dir: string,\n options: { now?: () => number; signal?: AbortSignal } = {},\n ): Promise<{ state: ReplicaState; status: ReplicaStatus } | null> {\n const checkAbort = () => {\n if (options.signal?.aborted) throw options.signal.reason ?? new ReplicaError(ReplicaErrorCode.CLOSED, \"Replica status inspection was cancelled.\");\n };\n checkAbort();\n const dbPath = join(dir, \"replica.db\");\n let identity: Stats;\n try {\n identity = await lstat(dbPath);\n if (!identity.isFile()) return null;\n } catch (error) {\n if (errnoOf(error) === \"ENOENT\") return null;\n throw storageError(error, \"Inspecting the replica\");\n }\n checkAbort();\n const opener = await loadSqlite();\n checkAbort();\n let db: SqliteDatabase | undefined;\n try {\n db = opener(dbPath, { readonly: true });\n db.exec(\"PRAGMA busy_timeout = 0\");\n checkAbort();\n const store = new SqliteReplicaStore(dir, db, identity, { create: false, ...(options.now ? { now: options.now } : {}) });\n for (let attempt = 0; attempt < 2; attempt++) {\n const before = db.get<{ data_version: number }>(\"PRAGMA data_version\")!.data_version;\n const state = await store.open();\n checkAbort();\n if (state === null) return null;\n const status = await store.status();\n await new Promise<void>((resolve) => setImmediate(resolve));\n checkAbort();\n const after = db.get<{ data_version: number }>(\"PRAGMA data_version\")!.data_version;\n if (before === after) return { state, status };\n }\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"The replica changed during status inspection.\");\n } catch (error) {\n if (/SQLITE_BUSY|database is locked/i.test(error instanceof Error ? error.message : String(error))) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"The replica is busy during status inspection.\", undefined, { cause: error });\n }\n throw storageError(error, \"Inspecting the replica\");\n } finally {\n db?.close();\n }\n }\n\n /**\n * Open the replica store in `dir`. With `create: false` a missing replica is\n * REPLICA_NOT_FOUND and nothing is written to disk.\n */\n static async open(dir: string, options: SqliteReplicaStoreOptions): Promise<SqliteReplicaStore> {\n const namedDbPath = join(dir, \"replica.db\");\n if (!options.create) {\n const exists = await lstat(namedDbPath).then(\n (stats) => stats.isFile(),\n () => false,\n );\n if (!exists) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, `No regular replica database at ${dir}.`);\n }\n const opener = options.sqlite ?? (await loadSqlite());\n const releaseOpen = await acquireSqliteOpen();\n let store: SqliteReplicaStore | undefined;\n let directoryFd: number | undefined;\n try {\n if (options.create) await mkdir(dir, { recursive: true, mode: 0o700 });\n if (process.platform === \"linux\") {\n directoryFd = openSync(dir, fsConstants.O_RDONLY | fsConstants.O_DIRECTORY | fsConstants.O_NOFOLLOW);\n }\n const opened = directoryFd === undefined ? lstatSync(dir, { bigint: true }) : fstatSync(directoryFd, { bigint: true });\n if (!opened.isDirectory() || opened.isSymbolicLink() ||\n (options.expectedDirectory &&\n (opened.dev !== BigInt(options.expectedDirectory.dev) || opened.ino !== BigInt(options.expectedDirectory.ino)))) {\n throw new Error(\"The replica directory changed before SQLite opened it.\");\n }\n const namedAncestors = process.platform === \"linux\" ? [] : await captureNamedPath(dir);\n if (namedAncestors.length &&\n (namedAncestors[namedAncestors.length - 1]!.dev !== opened.dev || namedAncestors[namedAncestors.length - 1]!.ino !== opened.ino)) {\n throw new Error(\"The replica directory changed while checking its ancestry.\");\n }\n const pinnedDir = directoryFd === undefined ? dir : `/proc/self/fd/${directoryFd}`;\n const dbPath = join(pinnedDir, \"replica.db\");\n if (options.create) {\n await mkdir(join(pinnedDir, \"blobs\", \".tmp\"), { recursive: true, mode: 0o700 });\n await Promise.all([chmod(pinnedDir, 0o700), chmod(join(pinnedDir, \"blobs\"), 0o700), chmod(join(pinnedDir, \"blobs\", \".tmp\"), 0o700)]);\n // SQLite gives -wal and -shm the database file's mode.\n // Only the winner creates/chmods the file; concurrent openers use the existing leaf.\n const handle = await open(dbPath, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_RDWR | fsConstants.O_NOFOLLOW, 0o600).catch((error: unknown) => {\n if (errnoOf(error) === \"EEXIST\") return null;\n throw error;\n });\n if (handle) {\n try { await handle.chmod(0o600); } finally { await handle.close(); }\n }\n }\n const leaf = await open(dbPath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);\n let db: SqliteDatabase | undefined;\n try {\n const identity = await leaf.stat();\n const named = await lstat(dbPath);\n if (!identity.isFile() || !named.isFile() || named.dev !== identity.dev || named.ino !== identity.ino) {\n throw new Error(\"The replica database changed before SQLite opened it.\");\n }\n const previousFds = process.platform === \"linux\" && !options.sqlite\n ? new Map(readdirSync(\"/proc/self/fd\").map((fd) => {\n try { return [fd, readlinkSync(`/proc/self/fd/${fd}`)] as const; } catch { return [fd, \"\"] as const; }\n }))\n : null;\n db = opener(dbPath);\n const afterOpen = lstatSync(dbPath);\n if (!afterOpen.isFile() || afterOpen.dev !== identity.dev || afterOpen.ino !== identity.ino) {\n throw new Error(\"The replica database changed while SQLite opened it.\");\n }\n // Bun opens the file lazily on its first read. Verify that descriptor before any mutating PRAGMA.\n // SQLite may resolve WAL/SHM sidecars by the database's named path;\n // the pinned directory does not make a concurrent external rename atomic.\n if (previousFds) db.get(\"SELECT count(*) FROM sqlite_master\");\n if (previousFds) {\n const databases = readdirSync(\"/proc/self/fd\").filter((fd) => {\n try {\n const target = readlinkSync(`/proc/self/fd/${fd}`);\n return target.endsWith(\"/replica.db\") && previousFds.get(fd) !== target;\n } catch { return false; }\n });\n if (databases.length === 0 || databases.some((fd) => {\n try {\n const actual = fstatSync(Number(fd));\n return actual.dev !== identity.dev || actual.ino !== identity.ino;\n } catch { return true; }\n })) {\n throw new Error(\"SQLite opened a different replica database.\");\n }\n }\n const after = lstatSync(dbPath);\n if (!after.isFile() || after.dev !== identity.dev || after.ino !== identity.ino) {\n throw new Error(\"The replica database changed while SQLite opened it.\");\n }\n db.exec(\"PRAGMA busy_timeout = 5000\");\n db.exec(\"PRAGMA journal_mode = WAL\");\n db.exec(\"PRAGMA synchronous = FULL\");\n db.exec(\"PRAGMA secure_delete = ON\");\n db.exec(\"PRAGMA foreign_keys = ON\");\n const version = db.get<{ user_version: number }>(\"PRAGMA user_version\")?.user_version ?? 0;\n if (version > SCHEMA_VERSION) {\n throw new ReplicaError(\n ReplicaErrorCode.STORAGE_ERROR,\n `The replica at ${dir} was written by a newer tc (schema ${version}); upgrade tc to read it.`,\n );\n }\n if (version < SCHEMA_VERSION) {\n db.exec(\"BEGIN IMMEDIATE\");\n db.exec(SCHEMA);\n db.exec(`PRAGMA user_version = ${SCHEMA_VERSION}`);\n db.exec(\"COMMIT\");\n }\n store = new SqliteReplicaStore(dir, db, identity, options, directoryFd, namedAncestors);\n db = undefined;\n } finally {\n try { db?.close(); } finally { await leaf.close(); }\n }\n } catch (error) {\n if (store) await store.close().catch(() => undefined);\n else if (directoryFd !== undefined) closeSync(directoryFd);\n throw storageError(error, `Opening the replica at ${dir}`);\n } finally {\n releaseOpen();\n }\n // A revocation purge interrupted by a crash (or by a writer that put\n // content back after it) finishes on the next open.\n try {\n const row = store.#row();\n if (row?.revoked_detail != null && (row.purge_pending === 1 || (await store.#holdsContentFiles().catch(() => true)))) {\n await store.#finishRevocationPurge().catch(() => undefined);\n }\n return store;\n } catch (error) {\n await store.close().catch(() => undefined);\n throw error;\n }\n }\n\n #row(): ReplicaRow | undefined {\n return this.#db.get<ReplicaRow>(\"SELECT * FROM replica WHERE id = 1\");\n }\n\n /** Refuse to touch the filesystem for a replica that was deleted (or replaced) under us. */\n async #assertPresent(): Promise<void> {\n const identity = await lstat(join(this.#pinnedDir, \"replica.db\")).catch(() => null);\n if (!identity?.isFile() || identity.dev !== this.#dev || identity.ino !== this.#ino) {\n throw new ReplicaError(\n ReplicaErrorCode.NOT_FOUND,\n `The replica at ${this.dir} was deleted while this command ran (its profile was deleted or the replica purged); nothing more was written.`,\n );\n }\n }\n\n /** A short mutation section: guarded (profile lock) and checked against the database this store opened. */\n #mutate<T>(section: () => Promise<T>): Promise<T> {\n return this.#guard(async () => {\n await this.#assertPresent();\n return section();\n });\n }\n\n /** Run `body` in a write transaction (BEGIN IMMEDIATE). Callers outside a mutation section use `#guardedWrite`. */\n #write<T>(action: string, body: () => T): T {\n try {\n this.#db.exec(\"BEGIN IMMEDIATE\");\n } catch (error) {\n throw storageError(error, action);\n }\n try {\n const result = body();\n this.#db.exec(\"COMMIT\");\n return result;\n } catch (error) {\n try {\n this.#db.exec(\"ROLLBACK\");\n } catch {\n // The transaction is already gone.\n }\n throw storageError(error, action);\n }\n }\n\n /** One write transaction as its own mutation section. */\n #guardedWrite<T>(action: string, body: () => T): Promise<T> {\n return this.#mutate(async () => this.#write(action, body));\n }\n\n /**\n * The caller still holds a live lease (its token, not expired), and the\n * replica is not revoked (unless `allowRevoked`). Inside a write\n * transaction this fences the write; before one it refuses early.\n */\n #checkLease(t: LeaseToken, options: { allowRevoked?: boolean } = {}): void {\n const row = this.#db.get<{ lease_token: number; lease_holder: string | null; lease_expires_at: number | null; revoked_detail: string | null }>(\n \"SELECT lease_token, lease_holder, lease_expires_at, revoked_detail FROM replica WHERE id = 1\",\n );\n if (row?.revoked_detail != null && options.allowRevoked !== true) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_REVOKED, `The replica's grant was revoked: ${row.revoked_detail}`);\n }\n if (row === undefined || row.lease_token !== t.token || row.lease_holder !== t.holder) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"Another process took over this replica's sync lease.\");\n }\n if (row.lease_expires_at === null || row.lease_expires_at <= this.#now()) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"This process's sync lease expired; nothing was written.\");\n }\n }\n\n async open(): Promise<ReplicaState | null> {\n let row: ReplicaRow | undefined;\n try {\n row = this.#row();\n } catch (error) {\n throw storageError(error, \"Reading the replica\");\n }\n if (row === undefined) return null;\n assertFolderPrefix(row.prefix);\n return {\n config: {\n name: row.name,\n replicaId: row.replica_id,\n host: row.host,\n space: row.space,\n prefix: row.prefix,\n deviceDid: row.device_did,\n allowSecrets: row.allow_secrets === 1,\n localReadPolicy: row.local_read_policy,\n retentionGrantCid: row.retention_grant_cid,\n },\n grant: grantOf(row.grant_cid, row.grant_bytes, row.grant_audience, row.grant_issuer, row.grant_nbf, row.grant_exp),\n pendingGrant: grantOf(\n row.pending_grant_cid,\n row.pending_grant_bytes,\n row.pending_grant_audience,\n row.pending_grant_issuer,\n row.pending_grant_nbf,\n row.pending_grant_exp,\n ),\n nodeDid: row.node_did,\n authority: row.attested === 1 ? { notBefore: row.not_before, expiresAt: row.expires_at, retainUntil: row.retain_until } : null,\n revoked: row.revoked_detail,\n retentionRevoked: row.retention_revoked,\n pendingGrantError: row.pending_grant_error === null ? null : (JSON.parse(row.pending_grant_error) as ReplicaLastError),\n cursor: row.cursor,\n coverage: row.coverage,\n generation: row.generation,\n createdAt: row.created_at,\n lastSyncAt: row.last_sync_at,\n lastCompleteAt: row.last_complete_at,\n lastError: row.last_error === null ? null : (JSON.parse(row.last_error) as ReplicaLastError),\n lastReset: row.last_reset === null ? null : (JSON.parse(row.last_reset) as { at: string; reason: string }),\n };\n }\n\n async init(c: ReplicaConfig): Promise<void> {\n assertFolderPrefix(c.prefix);\n await this.#guardedWrite(\"Creating the replica\", () => {\n if (this.#row() !== undefined) {\n throw new ReplicaError(ReplicaErrorCode.CONFIG_MISMATCH, `Replica ${c.name} already exists.`);\n }\n this.#db.run(\n `INSERT INTO replica (id, name, replica_id, host, space, prefix, device_did, allow_secrets, local_read_policy,\n retention_grant_cid, coverage, created_at)\n VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'empty', ?)`,\n c.name,\n c.replicaId,\n c.host,\n c.space,\n c.prefix,\n c.deviceDid,\n c.allowSecrets ? 1 : 0,\n c.localReadPolicy,\n c.retentionGrantCid,\n new Date(this.#now()).toISOString(),\n );\n });\n }\n\n /** Update the retention opt-in; it takes effect at the next sync. */\n async setRetentionGrant(cid: string | null): Promise<void> {\n await this.#guardedWrite(\"Updating the retention grant\", () => {\n // Changing the CID invalidates the attested retainUntil: it was earned\n // under the previous retain grant, so only a fresh sync under the new\n // CID may re-establish it.\n this.#db.run(\n \"UPDATE replica SET retention_grant_cid = ?, local_read_policy = ?, retain_until = NULL WHERE id = 1 AND retention_grant_cid IS NOT ?\",\n cid,\n cid === null ? \"whileGrantValid\" : \"retainAfterExpiry\",\n cid,\n );\n });\n }\n\n async installGrant(g: GrantRecord): Promise<void> {\n await this.#guardedWrite(\"Installing the grant\", () => {\n const row = this.#row();\n if (row === undefined) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica has not been created.\");\n if (row.grant_cid === g.cid || row.pending_grant_cid === g.cid) return;\n this.#db.run(\n `UPDATE replica SET pending_grant_cid = ?, pending_grant_bytes = ?, pending_grant_audience = ?,\n pending_grant_issuer = ?, pending_grant_nbf = ?, pending_grant_exp = ?, pending_grant_error = NULL WHERE id = 1`,\n g.cid,\n g.bytes,\n g.audience,\n g.issuer,\n g.notBefore,\n g.expiresAt,\n );\n });\n }\n\n async discardPendingGrant(cid: string, detail: string): Promise<void> {\n await this.#guardedWrite(\"Discarding the revoked pending grant\", () => {\n this.#db.run(\n `UPDATE replica SET pending_grant_cid = NULL, pending_grant_bytes = NULL, pending_grant_audience = NULL,\n pending_grant_issuer = NULL, pending_grant_nbf = NULL, pending_grant_exp = NULL, pending_grant_error = NULL,\n last_error = ? WHERE id = 1 AND pending_grant_cid = ?`,\n JSON.stringify({\n at: new Date(this.#now()).toISOString(),\n code: ReplicaErrorCode.GRANT_REVOKED,\n message: `The pending grant ${cid} was revoked and discarded: ${detail}`,\n }),\n cid,\n );\n });\n }\n\n async recordPendingGrantError(cid: string, e: ReplicaLastError): Promise<void> {\n await this.#guardedWrite(\"Recording the pending grant's refusal\", () => {\n this.#db.run(\"UPDATE replica SET pending_grant_error = ? WHERE id = 1 AND pending_grant_cid = ?\", JSON.stringify(e), cid);\n });\n }\n\n async markRetentionRevoked(cid: string, detail: string): Promise<void> {\n await this.#guardedWrite(\"Recording the retention grant's revocation\", () => {\n this.#db.run(\n `UPDATE replica SET retention_grant_cid = NULL, local_read_policy = 'whileGrantValid', retain_until = NULL,\n retention_revoked = ? WHERE id = 1 AND retention_grant_cid = ?`,\n detail,\n cid,\n );\n this.#db.run(\n \"UPDATE replica SET last_error = ? WHERE id = 1\",\n JSON.stringify({ at: new Date(this.#now()).toISOString(), code: ReplicaErrorCode.RETENTION_GRANT_REFUSED, message: detail }),\n );\n });\n }\n\n async acquireSyncLease(ttlMs: number): Promise<LeaseToken | null> {\n return this.#guardedWrite(\"Taking the sync lease\", () => {\n const row = this.#row();\n if (row === undefined) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica has not been created.\");\n const now = this.#now();\n if (row.lease_holder !== null && row.lease_expires_at !== null && row.lease_expires_at > now) return null;\n const token = row.lease_token + 1;\n this.#db.run(\n \"UPDATE replica SET lease_token = ?, lease_holder = ?, lease_expires_at = ? WHERE id = 1\",\n token,\n this.#holder,\n now + ttlMs,\n );\n return { token, holder: this.#holder };\n });\n }\n\n async renewLease(t: LeaseToken, ttlMs: number): Promise<void> {\n await this.#guardedWrite(\"Renewing the sync lease\", () => {\n this.#checkLease(t);\n this.#db.run(\"UPDATE replica SET lease_expires_at = ? WHERE id = 1\", this.#now() + ttlMs);\n });\n }\n\n async releaseLease(t: LeaseToken): Promise<void> {\n await this.#guardedWrite(\"Releasing the sync lease\", () => {\n this.#db.run(\n \"UPDATE replica SET lease_holder = NULL, lease_expires_at = NULL WHERE id = 1 AND lease_token = ? AND lease_holder = ?\",\n t.token,\n t.holder,\n );\n });\n }\n\n async hasContent(hashes: string[]): Promise<Set<string>> {\n const held = new Set<string>();\n for (let start = 0; start < hashes.length; start += 500) {\n const chunk = hashes.slice(start, start + 500);\n const rows = this.#db.all<{ hash: string }>(\n `SELECT DISTINCT hash FROM entry WHERE content = 1 AND hash IN (${chunk.map(() => \"?\").join(\",\")})`,\n ...chunk,\n );\n for (const row of rows) held.add(row.hash);\n }\n return held;\n }\n\n #blobPath(hash: string): string {\n return join(this.#pinnedDir, \"blobs\", hash.slice(0, 2), hash);\n }\n\n /**\n * Make every blob durable before any row references it: write to a fresh\n * temp file (O_EXCL, 0600), fsync, link to its content address (an existing\n * blob wins), unlink the temp, then fsync each touched directory once.\n * Never creates the replica's own directories: a deleted replica fails.\n */\n async #writeBlobs(blobs: Map<string, Uint8Array>): Promise<void> {\n const dirs = new Set<string>();\n for (const [hash, bytes] of blobs) {\n const final = this.#blobPath(hash);\n const exists = await stat(final).then(\n () => true,\n () => false,\n );\n if (exists) continue;\n const shard = join(this.#pinnedDir, \"blobs\", hash.slice(0, 2));\n await mkdir(shard, { mode: 0o700 }).catch((error: unknown) => {\n if (errnoOf(error) !== \"EEXIST\") throw error;\n });\n const temp = join(this.#pinnedDir, \"blobs\", \".tmp\", `${hash}.${randomBytes(6).toString(\"hex\")}`);\n const handle = await open(temp, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY, 0o600);\n try {\n await handle.writeFile(bytes);\n await handle.sync();\n } finally {\n await handle.close();\n }\n try {\n await link(temp, final);\n } catch (error) {\n if (errnoOf(error) !== \"EEXIST\") throw error;\n } finally {\n await unlink(temp);\n }\n dirs.add(shard);\n dirs.add(join(this.#pinnedDir, \"blobs\"));\n }\n for (const dir of dirs) {\n const handle = await open(dir, fsConstants.O_RDONLY);\n try {\n await handle.sync();\n } finally {\n await handle.close();\n }\n }\n }\n\n async applyPage(t: LeaseToken, p: VerifiedPage): Promise<void> {\n await this.#mutate(async () => {\n // Fence before any content reaches the disk: a writer whose lease was\n // taken over, expired or revoked writes nothing.\n this.#checkLease(t);\n // Resolve every reused blob's size before any row changes: an earlier\n // row of this page may drop the last entry that references it.\n const reused = new Map<string, number>();\n for (const change of p.changes) {\n if (change.deleted || !change.content || p.blobs.has(change.hash) || reused.has(change.hash)) continue;\n const size = this.#db.get<{ size: number | null }>(\n \"SELECT size FROM entry WHERE hash = ? AND content = 1 AND size IS NOT NULL LIMIT 1\",\n change.hash,\n )?.size;\n if (size === undefined || size === null) {\n throw new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, `No stored content backs ${JSON.stringify(change.key)}.`);\n }\n reused.set(change.hash, size);\n }\n try {\n await this.#writeBlobs(p.blobs);\n } catch (error) {\n throw storageError(error, \"Writing replica content\");\n }\n await this.#faults.afterBlobs?.();\n try {\n this.#write(\"Committing a sync page\", () => {\n this.#checkLease(t);\n // Authority is judged now, at the commit, not when the page arrived.\n const now = this.#now();\n if (p.window.notBefore !== null && now < Date.parse(p.window.notBefore)) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_NOT_YET_VALID, `The grant is not valid before ${p.window.notBefore}; nothing was committed.`);\n }\n if (p.window.expiresAt !== null && now >= Date.parse(p.window.expiresAt)) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, `The grant expired at ${p.window.expiresAt}; nothing was committed.`);\n }\n for (const change of p.changes) {\n if (change.deleted) {\n this.#db.run(\n `INSERT INTO entry (key, deleted, etag, hash, metadata, content, size) VALUES (?, 1, NULL, NULL, '{}', 0, NULL)\n ON CONFLICT (key) DO UPDATE SET deleted = 1, etag = NULL, hash = NULL, metadata = '{}', content = 0, size = NULL`,\n change.key,\n );\n continue;\n }\n const size = change.content ? (p.blobs.get(change.hash)?.length ?? reused.get(change.hash)!) : null;\n this.#db.run(\n `INSERT INTO entry (key, deleted, etag, hash, metadata, content, size) VALUES (?, 0, ?, ?, ?, ?, ?)\n ON CONFLICT (key) DO UPDATE SET deleted = 0, etag = excluded.etag, hash = excluded.hash,\n metadata = excluded.metadata, content = excluded.content, size = excluded.size`,\n change.key,\n change.etag,\n change.hash,\n JSON.stringify(change.metadata),\n change.content ? 1 : 0,\n size,\n );\n }\n const sets: string[] = [\"cursor = ?\", \"coverage = ?\"];\n const params: SqlValue[] = [p.cursor, p.coverage];\n if (p.authority !== null) {\n sets.push(\"node_did = ?\", \"attested = 1\", \"not_before = ?\", \"expires_at = ?\", \"last_sync_at = ?\");\n params.push(p.source.nodeDid, p.authority.notBefore, p.authority.expiresAt, p.at);\n // The attested retainUntil belongs to the retention grant the\n // request presented: if a setRetentionGrant raced the page, the\n // stored CID no longer matches and retain_until stays untouched\n // (null after the CID change) instead of reviving the previous\n // grant's window under a new CID.\n if (this.#row()!.retention_grant_cid === p.retentionGrantCid) {\n sets.push(\"retain_until = ?\");\n params.push(p.authority.retainUntil);\n // A node-attested retention under a new retain grant supersedes a learned revocation of the old one.\n if (p.authority.retainUntil !== null) sets.push(\"retention_revoked = NULL\");\n }\n }\n if (p.complete) {\n sets.push(\"last_complete_at = ?\", \"last_error = NULL\");\n params.push(p.at);\n }\n if (p.promoteGrant !== null) {\n const g = p.promoteGrant;\n sets.push(\"grant_cid = ?\", \"grant_bytes = ?\", \"grant_audience = ?\", \"grant_issuer = ?\", \"grant_nbf = ?\", \"grant_exp = ?\");\n params.push(g.cid, g.bytes, g.audience, g.issuer, g.notBefore, g.expiresAt);\n // Clear the pending slot only if it still holds the grant just validated.\n if (this.#row()!.pending_grant_cid === g.cid) {\n sets.push(\n \"pending_grant_cid = NULL\",\n \"pending_grant_bytes = NULL\",\n \"pending_grant_audience = NULL\",\n \"pending_grant_issuer = NULL\",\n \"pending_grant_nbf = NULL\",\n \"pending_grant_exp = NULL\",\n \"pending_grant_error = NULL\",\n );\n }\n }\n this.#db.run(`UPDATE replica SET ${sets.join(\", \")} WHERE id = 1`, ...params);\n this.#faults.beforeCommit?.();\n });\n } catch (error) {\n // Revoked while this call wrote its blobs: the purge may already have\n // run, so remove them again (a failure leaves purge_pending for open).\n if (isReplicaError(error, ReplicaErrorCode.GRANT_REVOKED)) await this.#purgeContent().catch(() => undefined);\n throw error;\n }\n this.#faults.afterCommit?.();\n });\n }\n\n /** Unlink every blob not in `keep`, and every temp file. Only a missing directory counts as empty. */\n async #unlinkBlobs(keep: Set<string>): Promise<number> {\n let removed = 0;\n const root = join(this.#pinnedDir, \"blobs\");\n for (const shard of await entriesOf(root)) {\n const shardPath = join(root, shard);\n if (shard === \".tmp\") {\n for (const name of await entriesOf(shardPath)) {\n await rm(join(shardPath, name), { force: true });\n removed += 1;\n }\n continue;\n }\n let kept = 0;\n for (const name of await entriesOf(shardPath)) {\n if (isHash(name) && keep.has(name)) {\n kept += 1;\n continue;\n }\n await rm(join(shardPath, name), { force: true });\n removed += 1;\n }\n if (kept === 0) await rmdir(shardPath).catch(() => undefined);\n }\n return removed;\n }\n\n /** Whether any content file (a blob or a temp file) is on disk. */\n async #holdsContentFiles(): Promise<boolean> {\n const root = join(this.#pinnedDir, \"blobs\");\n for (const shard of await entriesOf(root)) {\n if ((await entriesOf(join(root, shard))).length > 0) return true;\n }\n return false;\n }\n\n async collectGarbage(t: LeaseToken): Promise<number> {\n return this.#mutate(async () => {\n // The write lock is held across the unlinks, and the lease token is\n // checked under it: a paused former holder can never unlink a blob the\n // current holder just committed a reference to.\n try {\n this.#db.exec(\"BEGIN IMMEDIATE\");\n } catch (error) {\n throw storageError(error, \"Collecting unused content\");\n }\n try {\n this.#checkLease(t);\n const keep = new Set(\n this.#db.all<{ hash: string }>(\"SELECT DISTINCT hash FROM entry WHERE content = 1\").map((row) => row.hash),\n );\n const removed = await this.#unlinkBlobs(keep);\n this.#db.exec(\"COMMIT\");\n return removed;\n } catch (error) {\n try {\n this.#db.exec(\"ROLLBACK\");\n } catch {\n // already rolled back\n }\n throw storageError(error, \"Collecting unused content\");\n }\n });\n }\n\n async reset(t: LeaseToken, reason: string, options: { keepSource?: boolean } = {}): Promise<void> {\n await this.#mutate(async () => {\n this.#write(\"Resetting the replica\", () => {\n this.#checkLease(t);\n this.#db.run(\"DELETE FROM entry\");\n this.#db.run(\n `UPDATE replica SET cursor = NULL, ${options.keepSource ? \"\" : \"node_did = NULL, \"}coverage = 'empty', last_sync_at = NULL,\n last_complete_at = NULL, last_error = NULL, last_reset = ?, generation = generation + 1 WHERE id = 1`,\n JSON.stringify({ at: new Date(this.#now()).toISOString(), reason }),\n );\n });\n });\n await this.collectGarbage(t);\n if (!this.#checkpoint()) {\n throw new ReplicaError(\n ReplicaErrorCode.BUSY,\n \"The replica was reset, but another process is reading it, so its old pages are still in the write-ahead log. Run the reset again when that process ends.\",\n );\n }\n }\n\n /**\n * Remove this replica's directory for good (`tc replica reset --purge`).\n * Fenced like a commit: `t` must still be a live lease on the database this\n * store opened, checked under the write lock, so a paused process can\n * never remove a replica another process took over or recreated. Allowed\n * on a revoked replica. The store is unusable afterwards; close it.\n */\n async destroy(t: LeaseToken): Promise<void> {\n await this.#mutate(async () => {\n try {\n this.#db.exec(\"BEGIN IMMEDIATE\");\n } catch (error) {\n throw storageError(error, \"Removing the replica\");\n }\n try {\n this.#checkLease(t, { allowRevoked: true });\n const expected = this.#directoryFd === undefined ? this.#namedAncestors.at(-1) : fstatSync(this.#directoryFd, { bigint: true });\n if (!expected) {\n throw new ReplicaError(ReplicaErrorCode.RUNTIME_UNSUPPORTED, \"Replica removal requires an opened or identity-checked directory.\");\n }\n const assertDirectory = async (): Promise<BigIntStats> => {\n const current = await lstat(this.dir, { bigint: true });\n if (!current.isDirectory() || current.dev !== expected.dev || current.ino !== expected.ino) {\n throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica directory changed during removal.\");\n }\n return current;\n };\n const pinned = await assertDirectory();\n // Holding the write lock: no other lease holder can mutate this store.\n await this.#assertPresent();\n if (process.platform === \"linux\") {\n // The directory is pinned, but recursive rm does not pin each\n // descendant against a noncooperating rename during traversal.\n for (const entry of await readdir(this.#pinnedDir)) {\n await rm(join(this.#pinnedDir, entry), { recursive: true, force: true });\n }\n await assertDirectory();\n await rmdir(this.dir);\n } else {\n // Named-path removal cannot be atomic. Recheck captured ancestors\n // and each enumerated layout entry before nonrecursive unlink/rmdir;\n // initial aliases above this store belong to its caller's path policy.\n const ancestors = this.#namedAncestors;\n const checkAncestors = async (): Promise<void> => {\n for (const expected of ancestors) {\n const current = await lstat(expected.path, { bigint: true });\n if (current.dev !== expected.dev || current.ino !== expected.ino) {\n throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica ancestry changed during removal.\");\n }\n }\n };\n const directories = new Map<string, BigIntStats>([[this.dir, pinned]]);\n const files = new Map<string, BigIntStats>();\n const check = async (path: string, expected: BigIntStats, directory: boolean): Promise<void> => {\n if (path !== this.dir) {\n const parent = dirname(path);\n await check(parent, directories.get(parent)!, true);\n }\n await checkAncestors();\n const current = await lstat(path, { bigint: true });\n if ((directory ? !current.isDirectory() : !current.isFile()) ||\n current.dev !== expected.dev || current.ino !== expected.ino) {\n throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica layout changed during removal.\");\n }\n };\n const record = async (path: string, directory: boolean): Promise<void> => {\n const parent = dirname(path);\n await check(parent, directories.get(parent)!, true);\n const current = await lstat(path, { bigint: true });\n if (!(directory ? current.isDirectory() : current.isFile())) {\n throw new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, \"Unexpected replica layout during removal.\");\n }\n (directory ? directories : files).set(path, current);\n };\n const blobs = join(this.dir, \"blobs\");\n for (const name of await readdir(this.dir)) {\n if (name === \"blobs\") await record(blobs, true);\n else if ([\"replica.db\", \"replica.db-wal\", \"replica.db-shm\"].includes(name)) await record(join(this.dir, name), false);\n else throw new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, \"Unexpected replica layout during removal.\");\n }\n if (directories.has(blobs)) {\n await check(blobs, directories.get(blobs)!, true);\n for (const shard of await readdir(blobs)) {\n if (shard !== \".tmp\" && !/^[0-9a-f]{2}$/.test(shard)) {\n throw new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, \"Unexpected replica blob shard during removal.\");\n }\n const shardPath = join(blobs, shard);\n await record(shardPath, true);\n await check(shardPath, directories.get(shardPath)!, true);\n for (const name of await readdir(shardPath)) {\n if (shard === \".tmp\" ? !/^[0-9a-f]{64}\\.[0-9a-f]{12}$/.test(name) : !isHash(name) || !name.startsWith(shard)) {\n throw new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, \"Unexpected replica blob file during removal.\");\n }\n await record(join(shardPath, name), false);\n }\n }\n }\n for (const [path, identity] of files) {\n await check(path, identity, false);\n await unlink(path);\n }\n for (const [path, identity] of [...directories].reverse()) {\n if (path === this.dir) continue;\n await check(path, identity, true);\n await rmdir(path);\n }\n await assertDirectory();\n await checkAncestors();\n await rmdir(this.dir);\n }\n } catch (error) {\n throw storageError(error, \"Removing the replica\");\n } finally {\n try {\n this.#db.exec(\"ROLLBACK\");\n } catch {\n // Nothing was written.\n }\n }\n });\n }\n\n /**\n * Truncate the WAL so purged pages do not linger in it. TRUNCATE waits on\n * readers through busy_timeout; false when one still held it.\n */\n #checkpoint(): boolean {\n try {\n const result = this.#db.get<{ busy: number }>(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n return result === undefined || Number(result.busy) === 0;\n } catch (error) {\n throw storageError(error, \"Checkpointing the replica\");\n }\n }\n\n /**\n * Record the revocation (durable before this returns: reads are blocked\n * from here on, also after a restart), then purge. A purge that fails\n * keeps purge_pending set: status reports it and every open retries it.\n */\n async markRevoked(detail: string): Promise<void> {\n await this.#guardedWrite(\"Recording the revocation\", () => {\n this.#db.run(\"DELETE FROM entry\");\n // Bumping the lease token fences every outstanding writer.\n this.#db.run(\n `UPDATE replica SET revoked_detail = ?, cursor = NULL, coverage = 'empty', purge_pending = 1,\n lease_token = lease_token + 1, lease_holder = NULL, lease_expires_at = NULL, generation = generation + 1,\n last_error = ? WHERE id = 1`,\n detail,\n JSON.stringify({ at: new Date(this.#now()).toISOString(), code: ReplicaErrorCode.GRANT_REVOKED, message: detail }),\n );\n });\n this.#faults.afterPurgeMark?.();\n await this.#finishRevocationPurge().catch(() => undefined);\n }\n\n #finishRevocationPurge(): Promise<void> {\n return this.#mutate(() => this.#purgeContent());\n }\n\n /**\n * Inside a mutation section of a revoked replica: unlink every content\n * file and truncate the WAL. purge_pending is set first and cleared only\n * when both are done.\n */\n async #purgeContent(): Promise<void> {\n this.#write(\"Starting the revocation purge\", () => {\n this.#db.run(\"UPDATE replica SET purge_pending = 1 WHERE id = 1 AND revoked_detail IS NOT NULL\");\n });\n try {\n await this.#unlinkBlobs(new Set());\n } catch (error) {\n throw storageError(error, \"Purging revoked content\");\n }\n if (!this.#checkpoint()) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"A reader holds the replica's write-ahead log; the purge finishes on the next open.\");\n }\n this.#write(\"Finishing the revocation purge\", () => {\n this.#db.run(\"UPDATE replica SET purge_pending = 0 WHERE id = 1 AND revoked_detail IS NOT NULL\");\n });\n }\n\n async recordError(e: ReplicaLastError): Promise<void> {\n await this.#guardedWrite(\"Recording the sync error\", () => {\n this.#db.run(\"UPDATE replica SET last_error = ? WHERE id = 1\", JSON.stringify(e));\n });\n }\n\n async get(key: string): Promise<LocalEntry | undefined> {\n try {\n const row = this.#db.get<EntryRow>(\"SELECT key, deleted, etag, hash, metadata, content FROM entry WHERE key = ?\", key);\n return row === undefined ? undefined : entryOf(row);\n } catch (error) {\n throw storageError(error, \"Reading the replica\");\n }\n }\n\n async list(o: ListOpts): Promise<LocalEntry[]> {\n const where = [\"deleted = 0\"];\n const params: SqlValue[] = [];\n if (o.prefix !== undefined && o.prefix !== \"\") {\n where.push(\"key >= ?\", \"substr(key, 1, length(?)) = ?\");\n params.push(o.prefix, o.prefix, o.prefix);\n }\n if (o.after !== undefined) {\n where.push(\"key > ?\");\n params.push(o.after);\n }\n params.push(o.limit ?? -1);\n try {\n return this.#db\n .all<EntryRow>(\n `SELECT key, deleted, etag, hash, metadata, content FROM entry WHERE ${where.join(\" AND \")} ORDER BY key LIMIT ?`,\n ...params,\n )\n .map(entryOf);\n } catch (error) {\n throw storageError(error, \"Listing the replica\");\n }\n }\n\n async pendingRepairs(limit: number): Promise<Array<Extract<LocalEntry, { deleted: false }>>> {\n return this.#db\n .all<EntryRow>(\n \"SELECT key, deleted, etag, hash, metadata, content FROM entry WHERE deleted = 0 AND content = 0 ORDER BY key LIMIT ?\",\n limit,\n )\n .map(entryOf) as Array<Extract<LocalEntry, { deleted: false }>>;\n }\n\n async readContent(hash: string): Promise<Uint8Array | undefined> {\n if (!isHash(hash)) return undefined;\n try {\n return new Uint8Array(await readFile(this.#blobPath(hash)));\n } catch (error) {\n if (errnoOf(error) === \"ENOENT\") return undefined;\n throw storageError(error, \"Reading replica content\");\n }\n }\n\n async status(now = this.#now()): Promise<ReplicaStatus> {\n const state = await this.open();\n if (state === null) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica has not been created.\");\n const row = this.#row()!;\n const counts = this.#db.get<{ keys: number; missing: number; tombstones: number; bytes: number }>(\n `SELECT\n COALESCE(SUM(deleted = 0), 0) AS keys,\n COALESCE(SUM(deleted = 0 AND content = 0), 0) AS missing,\n COALESCE(SUM(deleted = 1), 0) AS tombstones,\n COALESCE(SUM(CASE WHEN deleted = 0 AND content = 1 THEN size ELSE 0 END), 0) AS bytes\n FROM entry`,\n )!;\n const { retentionRevoked: _retentionRevoked, ...authority } = effectiveAuthority({\n window: state.authority,\n grant: state.grant,\n revoked: state.revoked,\n retentionRevoked: state.retentionRevoked,\n policy: state.config.localReadPolicy,\n now,\n });\n return {\n name: state.config.name,\n replicaId: state.config.replicaId,\n source: { host: state.config.host, nodeDid: state.nodeDid, space: state.config.space, prefix: state.config.prefix },\n device: {\n did: state.config.deviceDid,\n delegationCid: state.grant?.cid ?? null,\n pendingDelegationCid: state.pendingGrant?.cid ?? null,\n pendingDelegationError: state.pendingGrantError,\n },\n authority: {\n ...authority,\n localReadPolicy: state.config.localReadPolicy,\n retentionGrantCid: state.config.retentionGrantCid,\n revokedDetail: state.revoked,\n retentionRevokedDetail: state.retentionRevoked,\n },\n consistency: \"observed\",\n coverage: state.coverage,\n lastSyncAt: state.lastSyncAt,\n lastCompleteAt: state.lastCompleteAt,\n counts: { keys: Number(counts.keys), contentMissing: Number(counts.missing), tombstones: Number(counts.tombstones) },\n bytes: Number(counts.bytes),\n durability: DURABILITY,\n syncing: row.lease_holder !== null && row.lease_expires_at !== null && row.lease_expires_at > now,\n purgePending: row.purge_pending === 1,\n lastError: state.lastError,\n lastReset: state.lastReset,\n };\n }\n\n async close(): Promise<void> {\n const fd = this.#directoryFd;\n this.#directoryFd = undefined;\n if (fd !== undefined) pinnedDirectories.unregister(this);\n try { this.#db.close(); } finally { if (fd !== undefined) closeSync(fd); }\n }\n}\n","/**\n * Typed replica errors. Every failure a caller can act on has its own code;\n * hosts (CLI, worker) map codes to their own exit codes or UI states.\n */\nexport const ReplicaErrorCode = {\n /** Another process holds the sync lease. */\n BUSY: \"REPLICA_BUSY\",\n /** No replica with this name exists. */\n NOT_FOUND: \"REPLICA_NOT_FOUND\",\n /** The replica exists but its stored configuration differs from the request. */\n CONFIG_MISMATCH: \"REPLICA_CONFIG_MISMATCH\",\n /** The runtime has no supported durable store (e.g. Node < 22.13). */\n RUNTIME_UNSUPPORTED: \"RUNTIME_UNSUPPORTED\",\n /** A required open() argument is missing or malformed (e.g. `principal`). */\n INVALID_ARGUMENT: \"REPLICA_INVALID_ARGUMENT\",\n /** The local store failed (I/O, corruption, schema). */\n STORAGE_ERROR: \"STORAGE_ERROR\",\n /** The local disk is full. */\n STORAGE_FULL: \"STORAGE_FULL\",\n /** The key is outside the replica's prefix. */\n NOT_COVERED: \"NOT_COVERED\",\n /** Syncing the secrets space or the vault namespace needs an explicit opt-in. */\n SECRETS_OPT_IN_REQUIRED: \"SECRETS_OPT_IN_REQUIRED\",\n /** No grant is installed, or none covers the requested scope. */\n GRANT_MISSING: \"GRANT_MISSING\",\n /** The grant bytes are not a verifiable UCAN, or its signature is wrong. */\n GRANT_INVALID: \"GRANT_INVALID\",\n /** SIWE/CACAO and other non-UCAN grants cannot be used for a replica. */\n GRANT_FORMAT_UNSUPPORTED: \"GRANT_FORMAT_UNSUPPORTED\",\n /** The grant was issued to a different device. */\n GRANT_AUDIENCE_MISMATCH: \"GRANT_AUDIENCE_MISMATCH\",\n /** The grant lacks `tinycloud.kv/sync` or `tinycloud.kv/get` on the prefix. */\n GRANT_NOT_COVERING: \"GRANT_NOT_COVERING\",\n GRANT_NOT_YET_VALID: \"GRANT_NOT_YET_VALID\",\n GRANT_EXPIRED: \"GRANT_EXPIRED\",\n /** The configured node does not advertise whole-space KV sync support. */\n REPLICATION_ROOT_UNSUPPORTED: \"REPLICATION_ROOT_UNSUPPORTED\",\n GRANT_REVOKED: \"GRANT_REVOKED\",\n /** The node refused the invocation for a reason other than revocation. */\n GRANT_UNAUTHORIZED: \"GRANT_UNAUTHORIZED\",\n /** The node refused the retention grant. */\n RETENTION_GRANT_REFUSED: \"RETENTION_GRANT_REFUSED\",\n /** The node could not be reached. */\n NETWORK_ERROR: \"NETWORK_ERROR\",\n /** The node answered with an unexpected status. */\n NODE_ERROR: \"NODE_ERROR\",\n /** The node's answer violates the wire contract. */\n PROTOCOL_ERROR: \"PROTOCOL_ERROR\",\n /** The node asked for a fresh bootstrap (410). Handled inside sync. */\n RESET_REQUIRED: \"RESET_REQUIRED\",\n /** The feed now comes from a different node than the one pinned. */\n SOURCE_CHANGED: \"SOURCE_CHANGED\",\n /** The feed delivered a key outside the replica's prefix. */\n SCOPE_VIOLATION: \"SCOPE_VIOLATION\",\n /** Fetched bytes do not hash to the ETag the node attested for them. */\n CONTENT_MISMATCH: \"CONTENT_MISMATCH\",\n /** A stored blob no longer hashes to its name. */\n INTEGRITY_ERROR: \"INTEGRITY_ERROR\",\n /** The replica handle was closed; in-flight calls settle with this code. */\n CLOSED: \"REPLICA_CLOSED\",\n} as const;\n\nexport type ReplicaErrorCode = (typeof ReplicaErrorCode)[keyof typeof ReplicaErrorCode];\n\n/**\n * The package ships separate entry bundles (`.`, `./sqlite`), each with its own\n * copy of this class, so identity is a registered symbol, not `instanceof`.\n */\nconst REPLICA_ERROR = Symbol.for(\"tinycloud.replica.error\");\n\nexport class ReplicaError extends Error {\n readonly [REPLICA_ERROR] = true;\n readonly code: ReplicaErrorCode;\n readonly detail?: Record<string, unknown>;\n\n constructor(code: ReplicaErrorCode, message: string, detail?: Record<string, unknown>, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ReplicaError\";\n this.code = code;\n if (detail !== undefined) this.detail = detail;\n }\n}\n\nexport function isReplicaError(error: unknown, code?: ReplicaErrorCode): error is ReplicaError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as { [REPLICA_ERROR]?: unknown })[REPLICA_ERROR] === true &&\n (code === undefined || (error as ReplicaError).code === code)\n );\n}\n","/** Shared prefix boundary and configuration rules; no runtime dependencies. */\nexport function kvPrefixCovers(prefix: string, key: string): boolean {\n return prefix === \"/\" || key.startsWith(prefix);\n}\n\n/** Replication scopes are `/` or non-empty, slash-terminated folder paths. */\nexport function assertFolderPrefix(prefix: unknown): asserts prefix is string {\n const validFolder = typeof prefix === \"string\" &&\n prefix.length > 0 &&\n !prefix.startsWith(\"/\") &&\n !prefix.includes(\"//\") &&\n prefix.endsWith(\"/\");\n if (prefix !== \"/\" && !validFolder) {\n const folderHint = typeof prefix === \"string\"\n ? prefix.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")\n : \"\";\n const suggestion = folderHint.length > 0 && !folderHint.includes(\"//\")\n ? ` Use ${JSON.stringify(`${folderHint}/`)}.`\n : ' Use \"/\" or a slash-terminated folder path such as \"notes/\".';\n throw new TypeError(`Replication prefix must be \"/\" or a non-empty slash-terminated folder path without empty segments.${suggestion}`);\n }\n}\n","import { ReplicaError, ReplicaErrorCode } from \"./errors.js\";\nimport type { AuthorityState, AuthorityWindow, GrantRecord, LocalReadPolicy } from \"./types.js\";\nimport { assertFolderPrefix as assertPureFolderPrefix } from \"@tinycloud/sdk-services/kv/replication/prefix\";\n\n/** Replication prefixes are the whole space (`/`) or a slash-terminated folder. */\nexport function assertFolderPrefix(prefix: unknown): asserts prefix is string {\n try {\n assertPureFolderPrefix(prefix);\n } catch {\n const folderHint = typeof prefix === \"string\"\n ? prefix.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")\n : \"\";\n const suggestion = prefix === \"\" ? 'use \"/\" for the whole space' :\n folderHint.length > 0 && !folderHint.includes(\"//\")\n ? `use ${JSON.stringify(`${folderHint}/`)}`\n : 'use \"/\" for the whole space or a folder path such as \"notes/\"';\n throw new ReplicaError(\n ReplicaErrorCode.INVALID_ARGUMENT,\n `Replication prefix ${JSON.stringify(prefix)} must be \"/\" or a non-empty folder path ending in / without empty segments; ${suggestion}. Run \\`tc replica reset --replica <name> --purge\\` and recreate it with the folder prefix.`,\n );\n }\n}\n\n/** Prefix coverage shared with the KV replication feed. */\nexport function kvPrefixCovers(prefix: string, key: string): boolean {\n return prefix === \"/\" || key.startsWith(prefix);\n}\n/** Capability containment: exact grants cover exact keys; slash grants cover descendants. */\nexport function authorityPathCovers(grantPath: string, requestedPath: string): boolean {\n if (grantPath === \"/\") return true;\n if (grantPath.endsWith(\"/\")) return requestedPath.startsWith(grantPath);\n return requestedPath === grantPath;\n}\n\n/**\n * Syncing the owner's secrets space, or any prefix overlapping the vault\n * namespace (including bare `vault`), copies encrypted secret material to\n * disk and needs an explicit opt-in (TC-733).\n */\nexport function requiresSecretsOptIn(space: string, prefix: string): boolean {\n if (prefix === \"/\") return true;\n if (space === \"secrets\" || space.endsWith(\":secrets\")) return true;\n const firstSegment = prefix.split(\"/\", 1)[0];\n return firstSegment === \"vault\";\n}\n\n/** `\"blake3-<hex>\"` (quoted or not) → the 64-hex hash, or undefined. */\nexport function hashFromEtag(etag: string): string | undefined {\n const match = /^\"?blake3-([0-9a-f]{64})\"?$/.exec(etag);\n return match?.[1];\n}\n\nconst RFC3339 = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\n/** An RFC 3339 instant that parses: the only form an authority bound may take. */\nexport function isInstant(value: string): boolean {\n return RFC3339.test(value) && Number.isFinite(Date.parse(value));\n}\n\nexport type EffectiveAuthority = {\n state: AuthorityState;\n notBefore: string | null;\n expiresAt: string | null;\n retainUntil: string | null;\n /** The retention grant was revoked: after expiry, reads are revoked rather than expired. */\n retentionRevoked: boolean;\n};\n\nfunction minIso(a: string | null, bSeconds: number | null): string | null {\n if (bSeconds === null) return a;\n const b = new Date(bSeconds * 1000).toISOString();\n if (a === null) return b;\n return Date.parse(a) <= Date.parse(b) ? a : b;\n}\n\nfunction maxIso(a: string | null, bSeconds: number | null): string | null {\n if (bSeconds === null) return a;\n const b = new Date(bSeconds * 1000).toISOString();\n if (a === null) return b;\n return Date.parse(a) >= Date.parse(b) ? a : b;\n}\n\n/**\n * The window local reads are enforced against: the node-attested window from\n * the last successful sync, bounded by the installed leaf grant (an upper\n * bound only — a multi-parent ancestor can end the chain earlier, which only\n * the node can see).\n */\nexport function effectiveAuthority(input: {\n window: AuthorityWindow | null;\n grant: GrantRecord | null;\n revoked: string | null;\n retentionRevoked?: string | null;\n policy: LocalReadPolicy;\n now: number;\n}): EffectiveAuthority {\n const notBefore = maxIso(input.window?.notBefore ?? null, input.grant?.notBefore ?? null);\n const expiresAt = minIso(input.window?.expiresAt ?? null, input.grant?.expiresAt ?? null);\n const retainUntil = input.policy === \"retainAfterExpiry\" ? input.window?.retainUntil ?? null : null;\n let state: AuthorityState = \"valid\";\n if (input.revoked !== null) state = \"revoked\";\n else if (notBefore !== null && input.now < Date.parse(notBefore)) state = \"not-yet-valid\";\n else if (expiresAt !== null && input.now >= Date.parse(expiresAt)) state = \"expired\";\n return { state, notBefore, expiresAt, retainUntil, retentionRevoked: (input.retentionRevoked ?? null) !== null };\n}\n\n/**\n * Throws unless local reads are allowed now. Returns the reported authority\n * state: `valid`, or `expired` while a node-attested retention holds.\n */\nexport function assertReadable(authority: EffectiveAuthority, now: number): AuthorityState {\n switch (authority.state) {\n case \"valid\":\n return \"valid\";\n case \"revoked\":\n throw new ReplicaError(ReplicaErrorCode.GRANT_REVOKED, \"The replica's grant was revoked; local reads are blocked.\");\n case \"not-yet-valid\":\n throw new ReplicaError(\n ReplicaErrorCode.GRANT_NOT_YET_VALID,\n `The replica's grant is not valid before ${authority.notBefore}.`,\n );\n case \"expired\":\n if (authority.retentionRevoked) {\n throw new ReplicaError(\n ReplicaErrorCode.GRANT_REVOKED,\n `The replica's grant expired at ${authority.expiresAt} and its retention grant was revoked; local reads are blocked.`,\n );\n }\n if (authority.retainUntil !== null && now < Date.parse(authority.retainUntil)) return \"expired\";\n throw new ReplicaError(\n ReplicaErrorCode.GRANT_EXPIRED,\n authority.retainUntil === null\n ? `The replica's grant expired at ${authority.expiresAt}; local reads are blocked.`\n : `The replica's retention ended at ${authority.retainUntil}; local reads are blocked.`,\n );\n }\n}\n","import { ReplicaError, ReplicaErrorCode } from \"../errors.js\";\n\nexport type SqlValue = string | number | null | Uint8Array;\n\n/** The synchronous SQLite surface shared by `node:sqlite` and `bun:sqlite`. */\nexport interface SqliteDatabase {\n exec(sql: string): void;\n run(sql: string, ...params: SqlValue[]): void;\n get<T>(sql: string, ...params: SqlValue[]): T | undefined;\n all<T>(sql: string, ...params: SqlValue[]): T[];\n\n close(): void;\n}\n\ntype Statement = {\n run(...params: SqlValue[]): unknown;\n get(...params: SqlValue[]): unknown;\n all(...params: SqlValue[]): unknown[];\n finalize?(): void;\n};\ntype NativeDatabase = { exec(sql: string): void; prepare(sql: string): Statement; close(): void };\n\nexport type SqliteOpenOptions = { readonly?: boolean };\nexport type SqliteOpener = (path: string, options?: SqliteOpenOptions) => SqliteDatabase;\n\nfunction wrap(native: NativeDatabase): SqliteDatabase {\n const statements = new Map<string, Statement>();\n const prepared = (sql: string): Statement => {\n let statement = statements.get(sql);\n if (statement === undefined) {\n statement = native.prepare(sql);\n statements.set(sql, statement);\n }\n return statement;\n };\n return {\n exec: (sql) => native.exec(sql),\n run: (sql, ...params) => void prepared(sql).run(...params),\n // bun:sqlite answers a missing row with null, node:sqlite with undefined.\n get: <T>(sql: string, ...params: SqlValue[]) => (prepared(sql).get(...params) ?? undefined) as T | undefined,\n all: <T>(sql: string, ...params: SqlValue[]) => prepared(sql).all(...params) as T[],\n close: () => {\n let failure: unknown;\n try {\n for (const statement of statements.values()) {\n try {\n statement.finalize?.();\n } catch (error) {\n failure ??= error;\n }\n }\n } finally {\n statements.clear();\n native.close();\n }\n if (failure !== undefined) throw failure;\n },\n };\n}\n\n\n/** Node ≥ 22.13 ships `node:sqlite` without a flag. */\nexport function nodeSqliteSupported(version: string): boolean {\n const [major = 0, minor = 0] = version.split(\".\").map(Number);\n return major > 22 || (major === 22 && minor >= 13);\n}\n\n/**\n * Load the runtime's built-in SQLite: `bun:sqlite` under Bun, `node:sqlite`\n * on Node ≥ 22.13. No native addon. Specifiers are computed so bundlers keep\n * both modules external, and only SQLite's ExperimentalWarning is silenced.\n */\nexport async function loadSqlite(): Promise<SqliteOpener> {\n const runtime = globalThis as { Bun?: unknown; process?: NodeJS.Process };\n const load = (specifier: string): Promise<Record<string, unknown>> => import(specifier);\n if (runtime.Bun !== undefined) {\n const module = await load([\"bun\", \"sqlite\"].join(\":\"));\n const Database = module.Database as new (path: string, options: { create: boolean; readonly?: boolean } | number) => NativeDatabase;\n return (path, options) =>\n wrap(new Database(path, { create: !options?.readonly, ...(options?.readonly ? { readonly: true } : {}) }));\n }\n const version = runtime.process?.versions?.node ?? \"0.0.0\";\n if (!nodeSqliteSupported(version)) {\n throw new ReplicaError(\n ReplicaErrorCode.RUNTIME_UNSUPPORTED,\n `tc replica needs Node.js 22.13 or newer (built-in SQLite); this is Node.js ${version}.`,\n { node: version },\n );\n }\n const process = runtime.process!;\n const emitWarning = process.emitWarning;\n process.emitWarning = function (this: NodeJS.Process, warning: string | Error, ...rest: unknown[]) {\n const message = typeof warning === \"string\" ? warning : warning.message;\n const type = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string } | undefined)?.type ?? (warning as Error).name;\n if (type === \"ExperimentalWarning\" && /SQLite/i.test(message)) return;\n return (emitWarning as (...args: unknown[]) => void).call(this, warning, ...rest);\n } as NodeJS.Process[\"emitWarning\"];\n let module: Record<string, unknown>;\n try {\n module = await load([\"node\", \"sqlite\"].join(\":\"));\n } finally {\n process.emitWarning = emitWarning;\n }\n const DatabaseSync = module.DatabaseSync as new (path: string, options?: { readOnly?: boolean }) => NativeDatabase;\n return (path, options) =>\n wrap(options?.readonly ? new DatabaseSync(path, { readOnly: true }) : new DatabaseSync(path));\n}\n"],"mappings":"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","names":["assertFolderPrefix","module","process","resolve","assertFolderPrefix","expected"]}
|
|
1
|
+
{"version":3,"sources":["../src/sqlite/store.ts","../src/errors.ts","../../sdk-services/src/kv/replication/prefix.ts","../src/scope.ts","../src/sqlite/driver.ts","../src/sqlite/layout.ts","../src/sqlite/schema.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { randomBytes } from \"node:crypto\";\nimport { closeSync, constants as fsConstants, fstatSync, lstatSync, openSync, readdirSync, readlinkSync, type BigIntStats, type Stats } from \"node:fs\";\nimport { chmod, link, lstat, mkdir, open, readFile, readdir, rm, rmdir, stat, unlink } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport type { ReplicaConsentAnchor } from \"@tinycloud/sdk-services/kv/replication\";\n\n\nimport { ReplicaError, ReplicaErrorCode, isReplicaError } from \"../errors.js\";\nimport { assertFolderPrefix, effectiveAuthority } from \"../scope.js\";\nimport type {\n Coverage,\n GrantRecord,\n LeaseToken,\n ListOpts,\n LocalEntry,\n LocalReadPolicy,\n ReplicaConfig,\n ReplicaLastError,\n ReplicaState,\n ReplicaStatus,\n ReplicaStore,\n VerifiedPage,\n} from \"../types.js\";\nimport { loadSqlite, type SqliteDatabase, type SqliteOpener, type SqlValue } from \"./driver.js\";\nimport { removeSqliteReplicaLayout, type SqliteLayoutEntry } from \"./layout.js\";\nimport { SCHEMA, SCHEMA_VERSION } from \"./schema.js\";\n\n// Descriptor discovery below is process-wide. Keep native SQLite opens from\n// overlapping so another store's new descriptor cannot be mistaken for this one.\nlet sqliteOpenQueue: Promise<void> = Promise.resolve();\nasync function acquireSqliteOpen(): Promise<() => void> {\n const previous = sqliteOpenQueue;\n let release!: () => void;\n sqliteOpenQueue = new Promise<void>((resolve) => { release = resolve; });\n await previous;\n return release;\n}\n\ntype NamedPathIdentity = { path: string; dev: bigint; ino: bigint };\n\nasync function captureNamedPath(path: string): Promise<NamedPathIdentity[]> {\n const names: string[] = [];\n for (let current = resolve(path); ; current = dirname(current)) {\n names.push(current);\n if (dirname(current) === current) break;\n }\n const identities: NamedPathIdentity[] = [];\n for (const name of names.reverse()) {\n const stats = await lstat(name, { bigint: true });\n identities.push({ path: name, dev: stats.dev, ino: stats.ino });\n }\n return identities;\n}\n\n/** Caller holds sqliteOpenQueue until native descriptor discovery completes. */\nasync function openVerifiedDatabase(\n path: string,\n opener: SqliteOpener,\n options: { readonly?: boolean; expected?: { dev: number; ino: number }; discoverDescriptors?: boolean } = {},\n): Promise<{ db: SqliteDatabase; identity: { dev: number; ino: number } }> {\n const leaf = await open(path, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);\n let db: SqliteDatabase | undefined;\n try {\n const identity = await leaf.stat();\n const named = await lstat(path);\n if (!identity.isFile() || !named.isFile() || named.dev !== identity.dev || named.ino !== identity.ino ||\n (options.expected !== undefined &&\n (options.expected.dev !== identity.dev || options.expected.ino !== identity.ino))) {\n throw new Error(\"The replica database changed before SQLite opened it.\");\n }\n const previousFds = process.platform === \"linux\" && options.discoverDescriptors !== false\n ? new Map(readdirSync(\"/proc/self/fd\").map((fd) => {\n try { return [fd, readlinkSync(`/proc/self/fd/${fd}`)] as const; } catch { return [fd, \"\"] as const; }\n }))\n : null;\n db = options.readonly ? opener(path, { readonly: true }) : opener(path);\n const afterOpen = lstatSync(path);\n if (!afterOpen.isFile() || afterOpen.dev !== identity.dev || afterOpen.ino !== identity.ino) {\n throw new Error(\"The replica database changed while SQLite opened it.\");\n }\n // Bun opens the file lazily on its first read. Verify that descriptor\n // before any mutating PRAGMA or schema upgrade.\n if (previousFds) db.get(\"SELECT count(*) FROM sqlite_master\");\n if (previousFds) {\n const databases = readdirSync(\"/proc/self/fd\").filter((fd) => {\n try {\n const target = readlinkSync(`/proc/self/fd/${fd}`);\n return target.endsWith(\"/replica.db\") && previousFds.get(fd) !== target;\n } catch { return false; }\n });\n // Bun can share an already-open pager for a second readonly connection:\n // only its WAL descriptor is new. In that case the existing native DB\n // descriptor (not our independent leaf) must match the pinned inode.\n const sharedPager = options.readonly && databases.length === 0 &&\n [...previousFds].some(([fd, target]) => {\n if (Number(fd) === leaf.fd || !target.endsWith(\"/replica.db\")) return false;\n try {\n const actual = fstatSync(Number(fd));\n return actual.dev === identity.dev && actual.ino === identity.ino;\n } catch { return false; }\n });\n if ((!databases.length && !sharedPager) || databases.some((fd) => {\n try {\n const actual = fstatSync(Number(fd));\n return actual.dev !== identity.dev || actual.ino !== identity.ino;\n } catch { return true; }\n })) {\n throw new Error(\"SQLite opened a different replica database.\");\n }\n }\n const after = lstatSync(path);\n if (!after.isFile() || after.dev !== identity.dev || after.ino !== identity.ino) {\n throw new Error(\"The replica database changed while SQLite opened it.\");\n }\n const checked = db;\n db = undefined;\n return { db: checked, identity };\n } finally {\n try { db?.close(); } finally { await leaf.close(); }\n }\n}\nexport const DURABILITY = \"sqlite-wal-synchronous-full+fsynced-blobs\";\n\n\ntype ReplicaRow = {\n name: string;\n replica_id: string;\n host: string;\n space: string;\n prefix: string;\n device_did: string;\n allow_secrets: number;\n local_read_policy: LocalReadPolicy;\n retention_grant_cid: string | null;\n grant_cid: string | null;\n grant_bytes: Uint8Array | null;\n grant_audience: string | null;\n grant_issuer: string | null;\n grant_nbf: number | null;\n grant_exp: number | null;\n pending_grant_cid: string | null;\n pending_grant_bytes: Uint8Array | null;\n pending_grant_audience: string | null;\n pending_grant_issuer: string | null;\n pending_grant_nbf: number | null;\n pending_grant_exp: number | null;\n node_did: string | null;\n attested: number;\n not_before: string | null;\n expires_at: string | null;\n retain_until: string | null;\n revoked_detail: string | null;\n purge_pending: number;\n retention_revoked: string | null;\n pending_grant_error: string | null;\n cursor: string | null;\n coverage: Coverage;\n generation: number;\n created_at: string;\n last_sync_at: string | null;\n last_complete_at: string | null;\n last_error: string | null;\n last_reset: string | null;\n lease_token: number;\n lease_holder: string | null;\n lease_expires_at: number | null;\n};\n\ntype EntryRow = {\n key: string;\n deleted: number;\n etag: string | null;\n hash: string | null;\n metadata: string;\n content: number;\n};\n\nfunction grantOf(\n cid: string | null,\n bytes: Uint8Array | null,\n audience: string | null,\n issuer: string | null,\n nbf: number | null,\n exp: number | null,\n): GrantRecord | null {\n if (cid === null || bytes === null || audience === null || issuer === null) return null;\n return { cid, bytes: new Uint8Array(bytes), audience, issuer, notBefore: nbf, expiresAt: exp };\n}\n\nfunction entryOf(row: EntryRow): LocalEntry {\n if (row.deleted === 1) return { key: row.key, deleted: true };\n return {\n key: row.key,\n deleted: false,\n etag: row.etag!,\n hash: row.hash!,\n metadata: JSON.parse(row.metadata) as Record<string, string>,\n content: row.content === 1,\n };\n}\n\nfunction storageError(error: unknown, action: string): ReplicaError {\n if (isReplicaError(error)) return error;\n const code = errnoOf(error);\n const message = error instanceof Error ? error.message : String(error);\n if (code === \"ENOSPC\" || code === \"EDQUOT\" || /SQLITE_FULL|database or disk is full/i.test(`${String(code)} ${message}`)) {\n return new ReplicaError(ReplicaErrorCode.STORAGE_FULL, `${action}: the local disk is full.`, undefined, { cause: error });\n }\n return new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, `${action}: ${message}`, undefined, { cause: error });\n}\n\nconst isHash = (name: string) => /^[0-9a-f]{64}$/.test(name);\n\nfunction errnoOf(error: unknown): unknown {\n return typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n}\n\n\n/** A directory's entries; only a directory that does not exist is empty. */\nasync function entriesOf(path: string): Promise<string[]> {\n try {\n return await readdir(path);\n } catch (error) {\n if (errnoOf(error) === \"ENOENT\") return [];\n throw error;\n }\n}\n\nexport type SqliteGrantInstall = {\n installedAt: number;\n effectiveExpiresAt: number;\n consentDeadline: number;\n consentAnchor: ReplicaConsentAnchor;\n};\n\nexport type SqliteGrantPolicy = {\n at: number;\n ttlMs: number;\n consentDeadline: number;\n consentAnchor: ReplicaConsentAnchor;\n};\n\n/** Crash- and race-test seam at SQLite durability boundaries. */\nexport type StoreFaults = {\n /** Blobs are durable; no row references them yet. */\n afterBlobs?(): void | Promise<void>;\n /** Rows and cursor are written inside the open transaction, not committed. */\n beforeCommit?(): void;\n /** The page is committed. */\n afterCommit?(): void;\n /** A revocation purge is committed; its blobs are not unlinked yet. */\n afterPurgeMark?(): void;\n /** Garbage collection holds an open write transaction while asynchronous blob I/O runs. */\n afterGarbageCollectionBegin?(): void | Promise<void>;\n};\n\n/**\n * Runs a mutation section (every database write and every filesystem\n * change). The CLI passes one that holds the profile lock briefly and\n * refuses when the profile was deleted, so a command never writes into or\n * recreates a deleted profile.\n */\nexport type MutationGuard = <T>(section: () => Promise<T>) => Promise<T>;\n\nexport type SqliteReplicaStoreOptions = {\n /** Create the replica directory and database if missing (else REPLICA_NOT_FOUND). */\n create: boolean;\n /** A checked entry's inode: reject replacement before SQLite sees its path. */\n expectedDirectory?: { dev: number; ino: number };\n sqlite?: SqliteOpener;\n /** Clock for leases and status (ms since epoch). */\n now?: () => number;\n guard?: MutationGuard;\n};\n\n/** Crash-test seam key. Only tests import it (from this module, not the package entry). */\nexport const FAULTS = Symbol(\"tinycloud.replica.faults\");\ntype InternalOptions = SqliteReplicaStoreOptions & { [FAULTS]?: StoreFaults };\n\n/** Stores may be abandoned without close by callers; release their directory descriptor on collection. */\nconst pinnedDirectories = new FinalizationRegistry<number>((fd) => {\n try { closeSync(fd); } catch { /* The process may already be shutting down. */ }\n});\n\n/** A checked SQLite handle stays pinned until the last controller for its directory closes. */\ntype SharedWritable = {\n key: string;\n db: SqliteDatabase;\n directoryFd: number | undefined;\n pinnedDir: string;\n namedPath: string;\n dev: number;\n ino: number;\n references: number;\n mutationTail: Promise<void>;\n};\n\nconst writableStores = new Map<string, SharedWritable>();\n\nfunction releaseWritable(shared: SharedWritable): void {\n if (shared.references === 0 || --shared.references !== 0) return;\n if (writableStores.get(shared.key) === shared) writableStores.delete(shared.key);\n try { shared.db.close(); } finally { if (shared.directoryFd !== undefined) closeSync(shared.directoryFd); }\n}\n\nconst sharedStores = new FinalizationRegistry<SharedWritable>((shared) => {\n try { releaseWritable(shared); } catch { /* The process may already be shutting down. */ }\n});\n\n/** Serialize transactions, not pre-commit blob I/O: revocation must still fence an in-flight writer. */\nasync function acquireWritableMutation(shared: SharedWritable): Promise<() => void> {\n const previous = shared.mutationTail;\n let release!: () => void;\n shared.mutationTail = new Promise<void>((resolve) => { release = resolve; });\n await previous;\n return release;\n}\n\nconst activeReadSection = new AsyncLocalStorage<{ controller: SqliteReplicaStore; active: boolean }>();\n\n/**\n * The CLI replica store: SQLite (WAL, synchronous=FULL) for entries, cursor\n * and authority, committed in one transaction per page; content-addressed\n * blob files written with fsync + link before any row references them.\n */\nexport class SqliteReplicaStore implements ReplicaStore {\n readonly dir: string;\n readonly #database: SqliteDatabase;\n get #db(): SqliteDatabase {\n if (this.#closed) throw new ReplicaError(ReplicaErrorCode.CLOSED, \"The replica store is closed.\");\n return this.#database;\n }\n #closed = false;\n #closing = false;\n #closePromise?: Promise<void>;\n #activeMutations = 0;\n #drained?: () => void;\n readonly #shared?: SharedWritable;\n readonly #readonlySnapshot: boolean;\n readonly #pinnedDir: string;\n #directoryFd?: number;\n #holder: string | undefined;\n readonly #now: () => number;\n readonly #faults: StoreFaults;\n readonly #guard: MutationGuard;\n /** Identity of the database file this store opened: a deleted-and-recreated replica is a different file. */\n readonly #ino: number;\n readonly #dev: number;\n readonly #namedAncestors: readonly NamedPathIdentity[];\n\n private constructor(dir: string, db: SqliteDatabase, identity: { dev: number; ino: number }, options: SqliteReplicaStoreOptions, directoryFd?: number, namedAncestors: readonly NamedPathIdentity[] = [], shared?: SharedWritable, readonlySnapshot = false) {\n this.dir = dir;\n this.#pinnedDir = shared?.pinnedDir ?? (directoryFd !== undefined && process.platform === \"linux\" ? `/proc/self/fd/${directoryFd}` : dir);\n this.#directoryFd = directoryFd;\n this.#shared = shared;\n this.#readonlySnapshot = readonlySnapshot;\n if (shared) {\n shared.references++;\n sharedStores.register(this, shared, this);\n } else if (directoryFd !== undefined) {\n pinnedDirectories.register(this, directoryFd, this);\n }\n this.#database = db;\n this.#ino = identity.ino;\n this.#dev = identity.dev;\n this.#now = options.now ?? Date.now;\n this.#faults = (options as InternalOptions)[FAULTS] ?? {};\n this.#guard = options.guard ?? ((section) => section());\n this.#namedAncestors = namedAncestors;\n }\n\n /**\n * Read-only status snapshot; does not create a replica, migrate, recover\n * revocation cleanup, or enter the mutation guard. An existing database is\n * opened normally in read-only WAL mode so committed WAL state is visible.\n */\n\n static async inspect(\n dir: string,\n options: { now?: () => number; signal?: AbortSignal } = {},\n ): Promise<{ state: ReplicaState; status: ReplicaStatus; grantInstall: SqliteGrantInstall | null; activeGrantInstall: SqliteGrantInstall | null } | null> {\n const checkAbort = () => {\n if (options.signal?.aborted) throw options.signal.reason ?? new ReplicaError(ReplicaErrorCode.CLOSED, \"Replica status inspection was cancelled.\");\n };\n checkAbort();\n const dbPath = join(dir, \"replica.db\");\n let identity: Stats;\n try {\n identity = await lstat(dbPath);\n if (!identity.isFile()) return null;\n } catch (error) {\n if (errnoOf(error) === \"ENOENT\") return null;\n throw storageError(error, \"Inspecting the replica\");\n }\n checkAbort();\n const opener = await loadSqlite();\n checkAbort();\n let db: SqliteDatabase | undefined;\n let releaseOpen: (() => void) | undefined;\n try {\n releaseOpen = await acquireSqliteOpen();\n const checked = await openVerifiedDatabase(dbPath, opener, { readonly: true, expected: identity });\n db = checked.db;\n releaseOpen();\n releaseOpen = undefined;\n db.exec(\"PRAGMA busy_timeout = 0\");\n checkAbort();\n const store = new SqliteReplicaStore(dir, db, checked.identity, { create: false, ...(options.now ? { now: options.now } : {}) });\n for (let attempt = 0; attempt < 2; attempt++) {\n const before = db.get<{ data_version: number }>(\"PRAGMA data_version\")!.data_version;\n const state = await store.open();\n checkAbort();\n if (state === null) return null;\n const status = await store.status();\n const latest = state.pendingGrant ?? state.grant;\n const version = db.get<{ user_version: number }>(\"PRAGMA user_version\")?.user_version ?? 0;\n const grantInstall = latest === null || version < 2 ? null : await store.getGrantInstall(latest.cid);\n const activeGrantInstall = state.grant === null || version < 2 ? null\n : state.grant === latest ? grantInstall : await store.getGrantInstall(state.grant.cid);\n await new Promise<void>((resolve) => setImmediate(resolve));\n checkAbort();\n const after = db.get<{ data_version: number }>(\"PRAGMA data_version\")!.data_version;\n if (before === after) return { state, status, grantInstall, activeGrantInstall };\n }\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"The replica changed during status inspection.\");\n } catch (error) {\n if (/SQLITE_BUSY|database is locked/i.test(error instanceof Error ? error.message : String(error))) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"The replica is busy during status inspection.\", undefined, { cause: error });\n }\n throw storageError(error, \"Inspecting the replica\");\n } finally {\n releaseOpen?.();\n if (db) {\n const releaseClose = await acquireSqliteOpen();\n try { db.close(); } finally { releaseClose(); }\n }\n }\n }\n\n /**\n * Open the replica store in `dir`. With `create: false` a missing replica is\n * REPLICA_NOT_FOUND and nothing is written to disk.\n */\n static async open(dir: string, options: SqliteReplicaStoreOptions): Promise<SqliteReplicaStore> {\n const namedDbPath = join(dir, \"replica.db\");\n if (!options.create) {\n const exists = await lstat(namedDbPath).then(\n (stats) => stats.isFile(),\n () => false,\n );\n if (!exists) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, `No regular replica database at ${dir}.`);\n }\n const releaseOpen = await acquireSqliteOpen();\n let store: SqliteReplicaStore | undefined;\n let directoryFd: number | undefined;\n try {\n if (options.create) await mkdir(dir, { recursive: true, mode: 0o700 });\n if (process.platform === \"linux\") {\n directoryFd = openSync(dir, fsConstants.O_RDONLY | fsConstants.O_DIRECTORY | fsConstants.O_NOFOLLOW);\n }\n const opened = directoryFd === undefined ? lstatSync(dir, { bigint: true }) : fstatSync(directoryFd, { bigint: true });\n if (!opened.isDirectory() || opened.isSymbolicLink() ||\n (options.expectedDirectory &&\n (opened.dev !== BigInt(options.expectedDirectory.dev) || opened.ino !== BigInt(options.expectedDirectory.ino)))) {\n throw new Error(\"The replica directory changed before SQLite opened it.\");\n }\n const namedAncestors = process.platform === \"linux\" ? [] : await captureNamedPath(dir);\n if (namedAncestors.length &&\n (namedAncestors[namedAncestors.length - 1]!.dev !== opened.dev || namedAncestors[namedAncestors.length - 1]!.ino !== opened.ino)) {\n throw new Error(\"The replica directory changed while checking its ancestry.\");\n }\n const pinnedDir = directoryFd === undefined ? dir : `/proc/self/fd/${directoryFd}`;\n const dbPath = join(pinnedDir, \"replica.db\");\n if (options.create) {\n await mkdir(join(pinnedDir, \"blobs\", \".tmp\"), { recursive: true, mode: 0o700 });\n await Promise.all([chmod(pinnedDir, 0o700), chmod(join(pinnedDir, \"blobs\"), 0o700), chmod(join(pinnedDir, \"blobs\", \".tmp\"), 0o700)]);\n // SQLite gives -wal and -shm the database file's mode.\n // Only the winner creates/chmods the file; concurrent openers use the existing leaf.\n const handle = await open(dbPath, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_RDWR | fsConstants.O_NOFOLLOW, 0o600).catch((error: unknown) => {\n if (errnoOf(error) === \"EEXIST\") return null;\n throw error;\n });\n if (handle) {\n try { await handle.chmod(0o600); } finally { await handle.close(); }\n }\n }\n const leaf = await open(dbPath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);\n let db: SqliteDatabase | undefined;\n try {\n const identity = await leaf.stat();\n const named = await lstat(dbPath);\n if (!identity.isFile() || !named.isFile() || named.dev !== identity.dev || named.ino !== identity.ino) {\n throw new Error(\"The replica database changed before SQLite opened it.\");\n }\n const key = `${opened.dev}:${opened.ino}`;\n const active = writableStores.get(key);\n if (active && (active.dev !== identity.dev || active.ino !== identity.ino)) {\n throw new Error(\"The replica database changed while another controller holds it open.\");\n }\n if (active && !options.sqlite) {\n const namedDirectory = lstatSync(dir, { bigint: true });\n if (!namedDirectory.isDirectory() || namedDirectory.dev !== opened.dev || namedDirectory.ino !== opened.ino) {\n throw new Error(\"The replica directory changed before its checked SQLite handle could be shared.\");\n }\n const pinned = active.directoryFd === undefined\n ? lstatSync(active.pinnedDir, { bigint: true })\n : fstatSync(active.directoryFd, { bigint: true });\n const activeLeaf = lstatSync(join(active.pinnedDir, \"replica.db\"));\n if (!pinned.isDirectory() || pinned.dev !== opened.dev || pinned.ino !== opened.ino ||\n !activeLeaf.isFile() || activeLeaf.dev !== identity.dev || activeLeaf.ino !== identity.ino ||\n (active.directoryFd === undefined && active.namedPath !== dir)) {\n throw new Error(\"The live replica changed before its checked SQLite handle could be shared.\");\n }\n if (directoryFd !== undefined) {\n closeSync(directoryFd);\n directoryFd = undefined;\n }\n store = new SqliteReplicaStore(dir, active.db, identity, options, active.directoryFd, namedAncestors, active);\n }\n if (!store) {\n const opener = options.sqlite ?? (await loadSqlite());\n const previousFds = process.platform === \"linux\" && !options.sqlite\n ? new Map(readdirSync(\"/proc/self/fd\").map((fd) => {\n try { return [fd, readlinkSync(`/proc/self/fd/${fd}`)] as const; } catch { return [fd, \"\"] as const; }\n }))\n : null;\n db = opener(dbPath);\n const afterOpen = lstatSync(dbPath);\n if (!afterOpen.isFile() || afterOpen.dev !== identity.dev || afterOpen.ino !== identity.ino) {\n throw new Error(\"The replica database changed while SQLite opened it.\");\n }\n // Bun opens the file lazily on its first read. Verify that descriptor before any mutating PRAGMA.\n // SQLite may resolve WAL/SHM sidecars by the database's named path;\n // the pinned directory does not make a concurrent external rename atomic.\n if (previousFds) db.get(\"SELECT count(*) FROM sqlite_master\");\n if (previousFds) {\n const databases = readdirSync(\"/proc/self/fd\").filter((fd) => {\n try {\n const target = readlinkSync(`/proc/self/fd/${fd}`);\n return target.endsWith(\"/replica.db\") && previousFds.get(fd) !== target;\n } catch { return false; }\n });\n if (databases.length === 0 || databases.some((fd) => {\n try {\n const actual = fstatSync(Number(fd));\n return actual.dev !== identity.dev || actual.ino !== identity.ino;\n } catch { return true; }\n })) {\n throw new Error(\"SQLite opened a different replica database.\");\n }\n }\n const after = lstatSync(dbPath);\n if (!after.isFile() || after.dev !== identity.dev || after.ino !== identity.ino) {\n throw new Error(\"The replica database changed while SQLite opened it.\");\n }\n db.exec(\"PRAGMA busy_timeout = 5000\");\n db.exec(\"PRAGMA journal_mode = WAL\");\n db.exec(\"PRAGMA synchronous = FULL\");\n db.exec(\"PRAGMA secure_delete = ON\");\n db.exec(\"PRAGMA foreign_keys = ON\");\n const version = db.get<{ user_version: number }>(\"PRAGMA user_version\")?.user_version ?? 0;\n if (version > SCHEMA_VERSION) {\n throw new ReplicaError(\n ReplicaErrorCode.STORAGE_ERROR,\n `The replica at ${dir} was written by a newer tc (schema ${version}); upgrade tc to read it.`,\n );\n }\n if (version < SCHEMA_VERSION) {\n db.exec(\"BEGIN IMMEDIATE\");\n db.exec(SCHEMA);\n db.exec(`PRAGMA user_version = ${SCHEMA_VERSION}`);\n db.exec(\"COMMIT\");\n }\n const shared: SharedWritable = {\n key, db, directoryFd, pinnedDir, namedPath: dir, dev: identity.dev, ino: identity.ino,\n references: 0, mutationTail: Promise.resolve(),\n };\n store = new SqliteReplicaStore(dir, db, identity, options, directoryFd, namedAncestors, shared);\n if (!options.sqlite) writableStores.set(key, shared);\n db = undefined;\n }\n } finally {\n try { db?.close(); } finally { await leaf.close(); }\n }\n } catch (error) {\n if (store) await store.close().catch(() => undefined);\n else if (directoryFd !== undefined) closeSync(directoryFd);\n throw storageError(error, `Opening the replica at ${dir}`);\n } finally {\n releaseOpen();\n }\n // A revocation purge interrupted by a crash (or by a writer that put\n // content back after it) finishes on the next open.\n try {\n const row = store.#row();\n if (row?.revoked_detail != null && (row.purge_pending === 1 || (await store.#holdsContentFiles().catch(() => true)))) {\n await store.#finishRevocationPurge().catch(() => undefined);\n }\n return store;\n } catch (error) {\n await store.close().catch(() => undefined);\n throw error;\n }\n }\n\n\n /**\n * A gated read borrows this controller's already-verified writable handle.\n * Borrow before the first await: the parent may close in the callback, but\n * its pin and native handle remain live until the snapshot releases them.\n * Serialize BEGIN through COMMIT/ROLLBACK with writes on the shared handle.\n */\n async readTransaction<T>(\n generation: number,\n checkGate: () => Promise<void>,\n section: (store: SqliteReplicaStore) => Promise<T>,\n ): Promise<T> {\n this.#assertAccepting();\n const shared = this.#shared;\n if (!shared) throw new ReplicaError(ReplicaErrorCode.CLOSED, \"The replica handle is closed.\");\n const snapshot = new SqliteReplicaStore(\n this.dir, shared.db, { dev: this.#dev, ino: this.#ino },\n { create: false, now: this.#now }, shared.directoryFd, this.#namedAncestors, shared, true,\n );\n let release: (() => void) | undefined;\n let active = false;\n let callbackFailed = false;\n try {\n release = await acquireWritableMutation(shared);\n await snapshot.#assertReadIdentity();\n snapshot.#db.exec(\"BEGIN\");\n active = true;\n const tombstone = snapshot.#db.get<{ generation: number }>(\"SELECT generation FROM replica WHERE id = 1\");\n try { await checkGate(); } catch (error) { callbackFailed = true; throw error; }\n if (tombstone === undefined || tombstone.generation !== generation) {\n throw new ReplicaError(ReplicaErrorCode.RESET_REQUIRED, \"The replica generation changed; reopen it to continue.\");\n }\n let result: T;\n const context = { controller: this, active: true };\n try {\n try { result = await activeReadSection.run(context, () => section(snapshot)); }\n catch (error) { callbackFailed = true; throw error; }\n } finally {\n context.active = false;\n }\n try { await checkGate(); } catch (error) { callbackFailed = true; throw error; }\n await snapshot.#assertReadIdentity();\n snapshot.#db.exec(\"COMMIT\");\n active = false;\n return result;\n } catch (error) {\n if (callbackFailed) throw error;\n if (isReplicaError(error) || (typeof error === \"object\" && error !== null && \"code\" in error &&\n error.code === \"REPLICA_GATED\")) throw error;\n if ([\"ENOENT\", \"ELOOP\", \"ENOTDIR\"].includes(String(errnoOf(error))) ||\n /replica database changed|SQLite opened a different replica database/i.test(error instanceof Error ? error.message : String(error))) {\n throw new ReplicaError(ReplicaErrorCode.RESET_REQUIRED, \"The replica was replaced; reopen it to continue.\", undefined, { cause: error });\n }\n throw storageError(error, \"Reading the replica snapshot\");\n } finally {\n if (active) {\n try { snapshot.#db.exec(\"ROLLBACK\"); } catch { /* Preserve the original error. */ }\n }\n try { await snapshot.close(); } finally { release?.(); }\n }\n }\n\n async #assertReadIdentity(): Promise<void> {\n const shared = this.#shared!;\n const pinned = shared.directoryFd === undefined ? lstatSync(shared.pinnedDir) : fstatSync(shared.directoryFd);\n const namedDir = lstatSync(this.dir);\n const namedDb = lstatSync(join(this.dir, \"replica.db\"));\n const pinnedDb = lstatSync(join(shared.pinnedDir, \"replica.db\"));\n if (!pinned.isDirectory() || !namedDir.isDirectory() ||\n pinned.dev !== namedDir.dev || pinned.ino !== namedDir.ino ||\n !namedDb.isFile() || !pinnedDb.isFile() ||\n namedDb.dev !== this.#dev || namedDb.ino !== this.#ino ||\n pinnedDb.dev !== this.#dev || pinnedDb.ino !== this.#ino) {\n throw new ReplicaError(ReplicaErrorCode.RESET_REQUIRED, \"The replica was replaced during its read; reopen it to continue.\");\n }\n if (this.#namedAncestors.length) {\n const ancestors = await captureNamedPath(this.dir);\n if (ancestors.length !== this.#namedAncestors.length ||\n ancestors.some((entry, index) => entry.dev !== this.#namedAncestors[index]!.dev || entry.ino !== this.#namedAncestors[index]!.ino)) {\n throw new ReplicaError(ReplicaErrorCode.RESET_REQUIRED, \"The replica directory was replaced; reopen it to continue.\");\n }\n }\n }\n\n #row(): ReplicaRow | undefined {\n return this.#db.get<ReplicaRow>(\"SELECT * FROM replica WHERE id = 1\");\n }\n\n /** Refuse to touch the filesystem for a replica that was deleted (or replaced) under us. */\n async #assertPresent(): Promise<void> {\n const identity = await lstat(join(this.#pinnedDir, \"replica.db\")).catch(() => null);\n if (!identity?.isFile() || identity.dev !== this.#dev || identity.ino !== this.#ino) {\n throw new ReplicaError(\n ReplicaErrorCode.NOT_FOUND,\n `The replica at ${this.dir} was deleted while this command ran (its profile was deleted or the replica purged); nothing more was written.`,\n );\n }\n }\n\n /** New calls stop at close; accepted mutation sections may still finish their transactions. */\n #assertAccepting(): void {\n if (this.#closing || this.#closed) {\n throw new ReplicaError(ReplicaErrorCode.CLOSED, \"The replica store is closed.\");\n }\n }\n\n /** A short mutation section: guarded (profile lock) and checked against the database this store opened. */\n #mutate<T>(section: () => Promise<T>): Promise<T> {\n this.#assertAccepting();\n if (this.#readonlySnapshot) {\n throw new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, \"A read-only replica snapshot cannot mutate the shared database.\");\n }\n const read = activeReadSection.getStore();\n if (read?.active && read.controller === this) {\n throw new ReplicaError(\n ReplicaErrorCode.STORAGE_ERROR,\n \"mutation attempted on the same controller while its readTransaction section is active; this would deadlock\",\n );\n }\n this.#activeMutations++;\n return (async () => {\n try {\n return await this.#guard(async () => {\n await this.#assertPresent();\n return section();\n });\n } finally {\n if (--this.#activeMutations === 0) {\n const drained = this.#drained;\n this.#drained = undefined;\n drained?.();\n }\n }\n })();\n }\n\n /** Run `body` in a write transaction (BEGIN IMMEDIATE). Callers outside a mutation section use `#guardedWrite`. */\n async #write<T>(action: string, body: () => T): Promise<T> {\n const release = this.#shared ? await acquireWritableMutation(this.#shared) : undefined;\n try {\n try {\n this.#db.exec(\"BEGIN IMMEDIATE\");\n } catch (error) {\n throw storageError(error, action);\n }\n try {\n const result = body();\n this.#db.exec(\"COMMIT\");\n return result;\n } catch (error) {\n try {\n this.#db.exec(\"ROLLBACK\");\n } catch {\n // The transaction is already gone.\n }\n throw storageError(error, action);\n }\n } finally {\n release?.();\n }\n }\n\n /** One write transaction as its own mutation section. */\n #guardedWrite<T>(action: string, body: () => T): Promise<T> {\n return this.#mutate(async () => this.#write(action, body));\n }\n\n /**\n * The caller still holds a live lease (its token, not expired), and the\n * replica is not revoked (unless `allowRevoked`). Inside a write\n * transaction this fences the write; before one it refuses early.\n */\n #checkLease(t: LeaseToken, options: { allowRevoked?: boolean } = {}): void {\n const row = this.#db.get<{ lease_token: number; lease_holder: string | null; lease_expires_at: number | null; revoked_detail: string | null }>(\n \"SELECT lease_token, lease_holder, lease_expires_at, revoked_detail FROM replica WHERE id = 1\",\n );\n if (row?.revoked_detail != null && options.allowRevoked !== true) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_REVOKED, `The replica's grant was revoked: ${row.revoked_detail}`);\n }\n if (row === undefined || row.lease_token !== t.token || row.lease_holder !== t.holder) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"Another process took over this replica's sync lease.\");\n }\n if (row.lease_expires_at === null || row.lease_expires_at <= this.#now()) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"This process's sync lease expired; nothing was written.\");\n }\n }\n\n async open(): Promise<ReplicaState | null> {\n this.#assertAccepting();\n let row: ReplicaRow | undefined;\n try {\n row = this.#row();\n } catch (error) {\n throw storageError(error, \"Reading the replica\");\n }\n if (row === undefined) return null;\n assertFolderPrefix(row.prefix);\n return {\n config: {\n name: row.name,\n replicaId: row.replica_id,\n host: row.host,\n space: row.space,\n prefix: row.prefix,\n deviceDid: row.device_did,\n allowSecrets: row.allow_secrets === 1,\n localReadPolicy: row.local_read_policy,\n retentionGrantCid: row.retention_grant_cid,\n },\n grant: grantOf(row.grant_cid, row.grant_bytes, row.grant_audience, row.grant_issuer, row.grant_nbf, row.grant_exp),\n pendingGrant: grantOf(\n row.pending_grant_cid,\n row.pending_grant_bytes,\n row.pending_grant_audience,\n row.pending_grant_issuer,\n row.pending_grant_nbf,\n row.pending_grant_exp,\n ),\n nodeDid: row.node_did,\n authority: row.attested === 1 ? { notBefore: row.not_before, expiresAt: row.expires_at, retainUntil: row.retain_until } : null,\n revoked: row.revoked_detail,\n retentionRevoked: row.retention_revoked,\n pendingGrantError: row.pending_grant_error === null ? null : (JSON.parse(row.pending_grant_error) as ReplicaLastError),\n cursor: row.cursor,\n coverage: row.coverage,\n generation: row.generation,\n createdAt: row.created_at,\n lastSyncAt: row.last_sync_at,\n lastCompleteAt: row.last_complete_at,\n lastError: row.last_error === null ? null : (JSON.parse(row.last_error) as ReplicaLastError),\n lastReset: row.last_reset === null ? null : (JSON.parse(row.last_reset) as { at: string; reason: string }),\n };\n }\n\n async init(c: ReplicaConfig): Promise<void> {\n assertFolderPrefix(c.prefix);\n await this.#guardedWrite(\"Creating the replica\", () => {\n if (this.#row() !== undefined) {\n throw new ReplicaError(ReplicaErrorCode.CONFIG_MISMATCH, `Replica ${c.name} already exists.`);\n }\n this.#db.run(\n `INSERT INTO replica (id, name, replica_id, host, space, prefix, device_did, allow_secrets, local_read_policy,\n retention_grant_cid, coverage, created_at)\n VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'empty', ?)`,\n c.name,\n c.replicaId,\n c.host,\n c.space,\n c.prefix,\n c.deviceDid,\n c.allowSecrets ? 1 : 0,\n c.localReadPolicy,\n c.retentionGrantCid,\n new Date(this.#now()).toISOString(),\n );\n });\n }\n\n /** Update the retention opt-in; it takes effect at the next sync. */\n async setRetentionGrant(cid: string | null): Promise<void> {\n await this.#guardedWrite(\"Updating the retention grant\", () => {\n // Changing the CID invalidates the attested retainUntil: it was earned\n // under the previous retain grant, so only a fresh sync under the new\n // CID may re-establish it.\n this.#db.run(\n \"UPDATE replica SET retention_grant_cid = ?, local_read_policy = ?, retain_until = NULL WHERE id = 1 AND retention_grant_cid IS NOT ?\",\n cid,\n cid === null ? \"whileGrantValid\" : \"retainAfterExpiry\",\n cid,\n );\n });\n }\n\n /** Per-CID first-install anchor and policy bound share the pending-grant transaction. */\n #grantInstall(cid: string): SqliteGrantInstall | null {\n const row = this.#db.get<{\n installed_at: number;\n effective_expires_at: number;\n consent_deadline: number;\n consent_anchor_at: number;\n consent_anchor_source: string;\n }>(\n \"SELECT installed_at, effective_expires_at, consent_deadline, consent_anchor_at, consent_anchor_source FROM grant_install WHERE cid = ?\",\n cid,\n );\n if (row === undefined) return null;\n if (!(row.consent_anchor_source === \"siwe\" || row.consent_anchor_source === \"delegation_iat\" ||\n row.consent_anchor_source === \"delegation_nbf\" || row.consent_anchor_source === \"first_install\") ||\n !Number.isSafeInteger(row.installed_at) || row.installed_at < 0 ||\n !Number.isSafeInteger(row.effective_expires_at) || row.effective_expires_at < 0 ||\n !Number.isSafeInteger(row.consent_deadline) || row.consent_deadline < 0 ||\n !Number.isSafeInteger(row.consent_anchor_at) || row.consent_anchor_at < 0) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, \"The stored grant expiry or consent anchor is invalid.\");\n }\n return {\n installedAt: row.installed_at,\n effectiveExpiresAt: row.effective_expires_at,\n consentDeadline: row.consent_deadline,\n consentAnchor: { at: row.consent_anchor_at, source: row.consent_anchor_source },\n };\n }\n\n async getGrantInstall(cid: string): Promise<SqliteGrantInstall | null> {\n return this.#grantInstall(cid);\n }\n\n /** Every installed CID, including superseded ones, for an origin-wide purge floor. */\n async grantInstallTimes(): Promise<Array<{ cid: string; installedAt: number }>> {\n const rows = this.#db.all<{ cid: string; installed_at: number }>(\n \"SELECT cid, installed_at FROM grant_install\",\n );\n return rows.map((row) => {\n if (typeof row.cid !== \"string\" || row.cid.length === 0 ||\n !Number.isSafeInteger(row.installed_at) || row.installed_at < 0) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, \"The stored grant install time is invalid.\");\n }\n return { cid: row.cid, installedAt: row.installed_at };\n });\n }\n\n /** Phase 2 installed grants cannot commit a page after their shorter local TTL. */\n #assertInstalledGrantTime(): void {\n const row = this.#row();\n const cid = row?.pending_grant_cid ?? row?.grant_cid;\n if (cid === undefined || cid === null) return;\n const installed = this.#grantInstall(cid);\n // Standalone Phase 1 stores have no grant policy; the Node adapter\n // separately refuses a missing install record before starting sync.\n const now = this.#now();\n if (installed !== null && (now >= installed.effectiveExpiresAt ||\n now >= installed.consentDeadline)) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, \"The installed grant expired before this page committed.\");\n }\n }\n\n #storeGrantPolicy(g: GrantRecord, policy: SqliteGrantPolicy, existing: SqliteGrantInstall | null): SqliteGrantInstall {\n const installedAt = existing?.installedAt ?? policy.at;\n const effectiveExpiresAt = Math.min(\n g.expiresAt === null ? Infinity : g.expiresAt * 1000,\n installedAt + policy.ttlMs,\n policy.consentDeadline,\n );\n if (!Number.isSafeInteger(installedAt) || installedAt < 0 ||\n !Number.isSafeInteger(effectiveExpiresAt) || effectiveExpiresAt < 0 ||\n !Number.isSafeInteger(policy.consentDeadline) || policy.consentDeadline < 0 ||\n !Number.isSafeInteger(policy.consentAnchor.at) || policy.consentAnchor.at < 0 ||\n !Number.isSafeInteger(policy.ttlMs) || policy.ttlMs <= 0) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, \"The replica grant has no finite effective expiry.\");\n }\n this.#db.run(\n `INSERT INTO grant_install (cid, installed_at, effective_expires_at, consent_deadline, consent_anchor_at, consent_anchor_source)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT (cid) DO UPDATE SET effective_expires_at = excluded.effective_expires_at,\n consent_deadline = excluded.consent_deadline, consent_anchor_at = excluded.consent_anchor_at,\n consent_anchor_source = excluded.consent_anchor_source`,\n g.cid, installedAt, effectiveExpiresAt, policy.consentDeadline,\n policy.consentAnchor.at, policy.consentAnchor.source,\n );\n return { installedAt, effectiveExpiresAt, consentDeadline: policy.consentDeadline, consentAnchor: policy.consentAnchor };\n }\n\n async installGatedGrant(g: GrantRecord, policy: SqliteGrantPolicy): Promise<SqliteGrantInstall> {\n return this.#guardedWrite(\"Installing the gated grant\", () => {\n const row = this.#row();\n if (row === undefined) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica has not been created.\");\n const previous = this.#grantInstall(g.cid);\n if (previous === null && (row.grant_cid === g.cid || row.pending_grant_cid === g.cid)) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, \"The installed grant has no durable first-install time.\");\n }\n const next = this.#storeGrantPolicy(g, policy, previous);\n if (next.effectiveExpiresAt <= this.#now()) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, \"The replica grant expired under the current policy.\");\n }\n if (row.grant_cid !== g.cid && row.pending_grant_cid !== g.cid) {\n this.#db.run(\n `UPDATE replica SET pending_grant_cid = ?, pending_grant_bytes = ?, pending_grant_audience = ?,\n pending_grant_issuer = ?, pending_grant_nbf = ?, pending_grant_exp = ?, pending_grant_error = NULL WHERE id = 1`,\n g.cid, g.bytes, g.audience, g.issuer, g.notBefore, g.expiresAt,\n );\n }\n return next;\n });\n }\n\n async recomputeGrantInstall(g: GrantRecord, policy: SqliteGrantPolicy): Promise<SqliteGrantInstall | null> {\n return this.#guardedWrite(\"Recomputing the gated grant\", () => {\n const previous = this.#grantInstall(g.cid);\n return previous === null ? null : this.#storeGrantPolicy(g, policy, previous);\n });\n }\n\n async installGrant(g: GrantRecord): Promise<void> {\n await this.#guardedWrite(\"Installing the grant\", () => {\n const row = this.#row();\n if (row === undefined) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica has not been created.\");\n if (row.grant_cid === g.cid || row.pending_grant_cid === g.cid) return;\n this.#db.run(\n `UPDATE replica SET pending_grant_cid = ?, pending_grant_bytes = ?, pending_grant_audience = ?,\n pending_grant_issuer = ?, pending_grant_nbf = ?, pending_grant_exp = ?, pending_grant_error = NULL WHERE id = 1`,\n g.cid,\n g.bytes,\n g.audience,\n g.issuer,\n g.notBefore,\n g.expiresAt,\n );\n });\n }\n\n async discardPendingGrant(cid: string, detail: string): Promise<void> {\n await this.#guardedWrite(\"Discarding the revoked pending grant\", () => {\n this.#db.run(\n `UPDATE replica SET pending_grant_cid = NULL, pending_grant_bytes = NULL, pending_grant_audience = NULL,\n pending_grant_issuer = NULL, pending_grant_nbf = NULL, pending_grant_exp = NULL, pending_grant_error = NULL,\n last_error = ? WHERE id = 1 AND pending_grant_cid = ?`,\n JSON.stringify({\n at: new Date(this.#now()).toISOString(),\n code: ReplicaErrorCode.GRANT_REVOKED,\n message: `The pending grant ${cid} was revoked and discarded: ${detail}`,\n }),\n cid,\n );\n });\n }\n\n async recordPendingGrantError(cid: string, e: ReplicaLastError): Promise<void> {\n await this.#guardedWrite(\"Recording the pending grant's refusal\", () => {\n this.#db.run(\"UPDATE replica SET pending_grant_error = ? WHERE id = 1 AND pending_grant_cid = ?\", JSON.stringify(e), cid);\n });\n }\n\n async markRetentionRevoked(cid: string, detail: string): Promise<void> {\n await this.#guardedWrite(\"Recording the retention grant's revocation\", () => {\n this.#db.run(\n `UPDATE replica SET retention_grant_cid = NULL, local_read_policy = 'whileGrantValid', retain_until = NULL,\n retention_revoked = ? WHERE id = 1 AND retention_grant_cid = ?`,\n detail,\n cid,\n );\n this.#db.run(\n \"UPDATE replica SET last_error = ? WHERE id = 1\",\n JSON.stringify({ at: new Date(this.#now()).toISOString(), code: ReplicaErrorCode.RETENTION_GRANT_REFUSED, message: detail }),\n );\n });\n }\n\n async acquireSyncLease(ttlMs: number): Promise<LeaseToken | null> {\n return this.#guardedWrite(\"Taking the sync lease\", () => {\n const row = this.#row();\n if (row === undefined) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica has not been created.\");\n const now = this.#now();\n if (row.lease_holder !== null && row.lease_expires_at !== null && row.lease_expires_at > now) return null;\n const token = row.lease_token + 1;\n const holder = this.#holder ??= `${process.pid}-${randomBytes(6).toString(\"hex\")}`;\n this.#db.run(\n \"UPDATE replica SET lease_token = ?, lease_holder = ?, lease_expires_at = ? WHERE id = 1\",\n token,\n holder,\n now + ttlMs,\n );\n return { token, holder };\n });\n }\n\n async renewLease(t: LeaseToken, ttlMs: number): Promise<void> {\n await this.#guardedWrite(\"Renewing the sync lease\", () => {\n this.#checkLease(t);\n this.#db.run(\"UPDATE replica SET lease_expires_at = ? WHERE id = 1\", this.#now() + ttlMs);\n });\n }\n\n async releaseLease(t: LeaseToken): Promise<void> {\n await this.#guardedWrite(\"Releasing the sync lease\", () => {\n this.#db.run(\n \"UPDATE replica SET lease_holder = NULL, lease_expires_at = NULL WHERE id = 1 AND lease_token = ? AND lease_holder = ?\",\n t.token,\n t.holder,\n );\n });\n }\n\n async hasContent(hashes: string[]): Promise<Set<string>> {\n this.#assertAccepting();\n const held = new Set<string>();\n for (let start = 0; start < hashes.length; start += 500) {\n const chunk = hashes.slice(start, start + 500);\n const rows = this.#db.all<{ hash: string }>(\n `SELECT DISTINCT hash FROM entry WHERE content = 1 AND hash IN (${chunk.map(() => \"?\").join(\",\")})`,\n ...chunk,\n );\n for (const row of rows) held.add(row.hash);\n }\n return held;\n }\n\n #blobPath(hash: string): string {\n return join(this.#pinnedDir, \"blobs\", hash.slice(0, 2), hash);\n }\n\n /**\n * Make every blob durable before any row references it: write to a fresh\n * temp file (O_EXCL, 0600), fsync, link to its content address (an existing\n * blob wins), unlink the temp, then fsync each touched directory once.\n * Never creates the replica's own directories: a deleted replica fails.\n */\n async #writeBlobs(blobs: Map<string, Uint8Array>): Promise<void> {\n const dirs = new Set<string>();\n for (const [hash, bytes] of blobs) {\n const final = this.#blobPath(hash);\n const exists = await stat(final).then(\n () => true,\n () => false,\n );\n if (exists) continue;\n const shard = join(this.#pinnedDir, \"blobs\", hash.slice(0, 2));\n await mkdir(shard, { mode: 0o700 }).catch((error: unknown) => {\n if (errnoOf(error) !== \"EEXIST\") throw error;\n });\n const temp = join(this.#pinnedDir, \"blobs\", \".tmp\", `${hash}.${randomBytes(6).toString(\"hex\")}`);\n const handle = await open(temp, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY, 0o600);\n try {\n await handle.writeFile(bytes);\n await handle.sync();\n } finally {\n await handle.close();\n }\n try {\n await link(temp, final);\n } catch (error) {\n if (errnoOf(error) !== \"EEXIST\") throw error;\n } finally {\n await unlink(temp);\n }\n dirs.add(shard);\n dirs.add(join(this.#pinnedDir, \"blobs\"));\n }\n for (const dir of dirs) {\n const handle = await open(dir, fsConstants.O_RDONLY);\n try {\n await handle.sync();\n } finally {\n await handle.close();\n }\n }\n }\n\n async applyPage(t: LeaseToken, p: VerifiedPage): Promise<void> {\n await this.#mutate(async () => {\n // Fence before any content reaches the disk: a writer whose lease was\n // taken over, expired or revoked writes nothing.\n this.#checkLease(t);\n this.#assertInstalledGrantTime();\n // Resolve every reused blob's size before any row changes: an earlier\n // row of this page may drop the last entry that references it.\n const reused = new Map<string, number>();\n for (const change of p.changes) {\n if (change.deleted || !change.content || p.blobs.has(change.hash) || reused.has(change.hash)) continue;\n const size = this.#db.get<{ size: number | null }>(\n \"SELECT size FROM entry WHERE hash = ? AND content = 1 AND size IS NOT NULL LIMIT 1\",\n change.hash,\n )?.size;\n if (size === undefined || size === null) {\n throw new ReplicaError(ReplicaErrorCode.STORAGE_ERROR, `No stored content backs ${JSON.stringify(change.key)}.`);\n }\n reused.set(change.hash, size);\n }\n try {\n await this.#writeBlobs(p.blobs);\n } catch (error) {\n throw storageError(error, \"Writing replica content\");\n }\n await this.#faults.afterBlobs?.();\n try {\n await this.#write(\"Committing a sync page\", () => {\n this.#checkLease(t);\n this.#assertInstalledGrantTime();\n // Authority is judged now, at the commit, not when the page arrived.\n const now = this.#now();\n if (p.window.notBefore !== null && now < Date.parse(p.window.notBefore)) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_NOT_YET_VALID, `The grant is not valid before ${p.window.notBefore}; nothing was committed.`);\n }\n if (p.window.expiresAt !== null && now >= Date.parse(p.window.expiresAt)) {\n throw new ReplicaError(ReplicaErrorCode.GRANT_EXPIRED, `The grant expired at ${p.window.expiresAt}; nothing was committed.`);\n }\n for (const change of p.changes) {\n if (change.deleted) {\n this.#db.run(\n `INSERT INTO entry (key, deleted, etag, hash, metadata, content, size) VALUES (?, 1, NULL, NULL, '{}', 0, NULL)\n ON CONFLICT (key) DO UPDATE SET deleted = 1, etag = NULL, hash = NULL, metadata = '{}', content = 0, size = NULL`,\n change.key,\n );\n continue;\n }\n const size = change.content ? (p.blobs.get(change.hash)?.length ?? reused.get(change.hash)!) : null;\n this.#db.run(\n `INSERT INTO entry (key, deleted, etag, hash, metadata, content, size) VALUES (?, 0, ?, ?, ?, ?, ?)\n ON CONFLICT (key) DO UPDATE SET deleted = 0, etag = excluded.etag, hash = excluded.hash,\n metadata = excluded.metadata, content = excluded.content, size = excluded.size`,\n change.key,\n change.etag,\n change.hash,\n JSON.stringify(change.metadata),\n change.content ? 1 : 0,\n size,\n );\n }\n const sets: string[] = [\"cursor = ?\", \"coverage = ?\"];\n const params: SqlValue[] = [p.cursor, p.coverage];\n if (p.authority !== null) {\n sets.push(\"node_did = ?\", \"attested = 1\", \"not_before = ?\", \"expires_at = ?\", \"last_sync_at = ?\");\n params.push(p.source.nodeDid, p.authority.notBefore, p.authority.expiresAt, p.at);\n // The attested retainUntil belongs to the retention grant the\n // request presented: if a setRetentionGrant raced the page, the\n // stored CID no longer matches and retain_until stays untouched\n // (null after the CID change) instead of reviving the previous\n // grant's window under a new CID.\n if (this.#row()!.retention_grant_cid === p.retentionGrantCid) {\n sets.push(\"retain_until = ?\");\n params.push(p.authority.retainUntil);\n // A node-attested retention under a new retain grant supersedes a learned revocation of the old one.\n if (p.authority.retainUntil !== null) sets.push(\"retention_revoked = NULL\");\n }\n }\n if (p.complete) {\n sets.push(\"last_complete_at = ?\", \"last_error = NULL\");\n params.push(p.at);\n }\n if (p.promoteGrant !== null) {\n const g = p.promoteGrant;\n sets.push(\"grant_cid = ?\", \"grant_bytes = ?\", \"grant_audience = ?\", \"grant_issuer = ?\", \"grant_nbf = ?\", \"grant_exp = ?\");\n params.push(g.cid, g.bytes, g.audience, g.issuer, g.notBefore, g.expiresAt);\n // Clear the pending slot only if it still holds the grant just validated.\n if (this.#row()!.pending_grant_cid === g.cid) {\n sets.push(\n \"pending_grant_cid = NULL\",\n \"pending_grant_bytes = NULL\",\n \"pending_grant_audience = NULL\",\n \"pending_grant_issuer = NULL\",\n \"pending_grant_nbf = NULL\",\n \"pending_grant_exp = NULL\",\n \"pending_grant_error = NULL\",\n );\n }\n }\n this.#db.run(`UPDATE replica SET ${sets.join(\", \")} WHERE id = 1`, ...params);\n this.#faults.beforeCommit?.();\n });\n } catch (error) {\n // Revoked while this call wrote its blobs: the purge may already have\n // run, so remove them again (a failure leaves purge_pending for open).\n if (isReplicaError(error, ReplicaErrorCode.GRANT_REVOKED)) await this.#purgeContent().catch(() => undefined);\n throw error;\n }\n this.#faults.afterCommit?.();\n });\n }\n\n /** Unlink every blob not in `keep`, and every temp file. Only a missing directory counts as empty. */\n async #unlinkBlobs(keep: Set<string>): Promise<number> {\n let removed = 0;\n const root = join(this.#pinnedDir, \"blobs\");\n for (const shard of await entriesOf(root)) {\n const shardPath = join(root, shard);\n if (shard === \".tmp\") {\n for (const name of await entriesOf(shardPath)) {\n await rm(join(shardPath, name), { force: true });\n removed += 1;\n }\n continue;\n }\n let kept = 0;\n for (const name of await entriesOf(shardPath)) {\n if (isHash(name) && keep.has(name)) {\n kept += 1;\n continue;\n }\n await rm(join(shardPath, name), { force: true });\n removed += 1;\n }\n if (kept === 0) await rmdir(shardPath).catch(() => undefined);\n }\n return removed;\n }\n\n /** Whether any content file (a blob or a temp file) is on disk. */\n async #holdsContentFiles(): Promise<boolean> {\n const root = join(this.#pinnedDir, \"blobs\");\n for (const shard of await entriesOf(root)) {\n if ((await entriesOf(join(root, shard))).length > 0) return true;\n }\n return false;\n }\n\n async collectGarbage(t: LeaseToken): Promise<number> {\n return this.#mutate(async () => {\n const release = this.#shared ? await acquireWritableMutation(this.#shared) : undefined;\n // The write lock is held across the unlinks, and the lease token is\n // checked under it: a paused former holder can never unlink a blob the\n // current holder just committed a reference to.\n try {\n this.#db.exec(\"BEGIN IMMEDIATE\");\n } catch (error) {\n release?.();\n throw storageError(error, \"Collecting unused content\");\n }\n try {\n this.#checkLease(t);\n await this.#faults.afterGarbageCollectionBegin?.();\n const keep = new Set(\n this.#db.all<{ hash: string }>(\"SELECT DISTINCT hash FROM entry WHERE content = 1\").map((row) => row.hash),\n );\n const removed = await this.#unlinkBlobs(keep);\n this.#db.exec(\"COMMIT\");\n return removed;\n } catch (error) {\n try {\n this.#db.exec(\"ROLLBACK\");\n } catch {\n // already rolled back\n }\n throw storageError(error, \"Collecting unused content\");\n } finally {\n release?.();\n }\n });\n }\n\n async reset(t: LeaseToken, reason: string, options: { keepSource?: boolean } = {}): Promise<void> {\n await this.#mutate(async () => {\n await this.#write(\"Resetting the replica\", () => {\n this.#checkLease(t);\n this.#db.run(\"DELETE FROM entry\");\n this.#db.run(\n `UPDATE replica SET cursor = NULL, ${options.keepSource ? \"\" : \"node_did = NULL, \"}coverage = 'empty', last_sync_at = NULL,\n last_complete_at = NULL, last_error = NULL, last_reset = ?, generation = generation + 1 WHERE id = 1`,\n JSON.stringify({ at: new Date(this.#now()).toISOString(), reason }),\n );\n });\n });\n await this.collectGarbage(t);\n if (!this.#checkpoint()) {\n throw new ReplicaError(\n ReplicaErrorCode.BUSY,\n \"The replica was reset, but another process is reading it, so its old pages are still in the write-ahead log. Run the reset again when that process ends.\",\n );\n }\n }\n\n /**\n * Remove the source-created mirror layout under a live lease. Unknown files\n * are removed only when their exact preflight identities were approved.\n */\n async destroy(t: LeaseToken, options: {\n approvedUnknown?: readonly SqliteLayoutEntry[];\n expectedKnown?: readonly SqliteLayoutEntry[];\n expectedRoot?: { dev: string; ino: string };\n allowMissingDatabase?: boolean;\n allowAdapterFence?: boolean;\n } = {}): Promise<void> {\n await this.#mutate(async () => {\n const release = this.#shared ? await acquireWritableMutation(this.#shared) : undefined;\n try {\n this.#db.exec(\"BEGIN IMMEDIATE\");\n } catch (error) {\n release?.();\n throw storageError(error, \"Removing the replica\");\n }\n try {\n this.#checkLease(t, { allowRevoked: true });\n const expected = this.#directoryFd === undefined ? this.#namedAncestors.at(-1) : fstatSync(this.#directoryFd, { bigint: true });\n if (!expected) {\n throw new ReplicaError(ReplicaErrorCode.RUNTIME_UNSUPPORTED, \"Replica removal requires an opened or identity-checked directory.\");\n }\n const assertDirectory = async (): Promise<BigIntStats> => {\n const current = await lstat(this.dir, { bigint: true });\n if (!current.isDirectory() || current.dev !== expected.dev || current.ino !== expected.ino) {\n throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica directory changed during removal.\");\n }\n return current;\n };\n const pinned = await assertDirectory();\n // A refused removal whose named path moved reports the move, as a changed directory does.\n const assertNamedPath = async (): Promise<void> => {\n for (const ancestor of this.#namedAncestors) {\n const current = await lstat(ancestor.path, { bigint: true });\n if (current.dev !== ancestor.dev || current.ino !== ancestor.ino) {\n throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica ancestry changed during removal.\");\n }\n }\n await assertDirectory();\n };\n // Holding the write lock: no other lease holder can mutate this store.\n await this.#assertPresent();\n try {\n await removeSqliteReplicaLayout(this.dir, {\n ...options,\n expectedRoot: options.expectedRoot ?? { dev: pinned.dev.toString(), ino: pinned.ino.toString() },\n });\n } catch (error) {\n await assertNamedPath();\n throw error;\n }\n } catch (error) {\n throw storageError(error, \"Removing the replica\");\n } finally {\n try {\n this.#db.exec(\"ROLLBACK\");\n } catch {\n // Nothing was written.\n }\n release?.();\n }\n });\n }\n\n /**\n * Truncate the WAL so purged pages do not linger in it. TRUNCATE waits on\n * readers through busy_timeout; false when one still held it.\n */\n #checkpoint(): boolean {\n try {\n const result = this.#db.get<{ busy: number }>(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n return result === undefined || Number(result.busy) === 0;\n } catch (error) {\n throw storageError(error, \"Checkpointing the replica\");\n }\n }\n\n /**\n * Record the revocation (durable before this returns: reads are blocked\n * from here on, also after a restart), then purge. A purge that fails\n * keeps purge_pending set: status reports it and every open retries it.\n */\n async markRevoked(detail: string): Promise<void> {\n await this.#guardedWrite(\"Recording the revocation\", () => {\n this.#db.run(\"DELETE FROM entry\");\n // Bumping the lease token fences every outstanding writer.\n this.#db.run(\n `UPDATE replica SET revoked_detail = ?, cursor = NULL, coverage = 'empty', purge_pending = 1,\n lease_token = lease_token + 1, lease_holder = NULL, lease_expires_at = NULL, generation = generation + 1,\n last_error = ? WHERE id = 1`,\n detail,\n JSON.stringify({ at: new Date(this.#now()).toISOString(), code: ReplicaErrorCode.GRANT_REVOKED, message: detail }),\n );\n });\n this.#faults.afterPurgeMark?.();\n await this.#finishRevocationPurge().catch(() => undefined);\n }\n\n #finishRevocationPurge(): Promise<void> {\n return this.#mutate(() => this.#purgeContent());\n }\n\n /**\n * Inside a mutation section of a revoked replica: unlink every content\n * file and truncate the WAL. purge_pending is set first and cleared only\n * when both are done.\n */\n async #purgeContent(): Promise<void> {\n await this.#write(\"Starting the revocation purge\", () => {\n this.#db.run(\"UPDATE replica SET purge_pending = 1 WHERE id = 1 AND revoked_detail IS NOT NULL\");\n });\n try {\n await this.#unlinkBlobs(new Set());\n } catch (error) {\n throw storageError(error, \"Purging revoked content\");\n }\n if (!this.#checkpoint()) {\n throw new ReplicaError(ReplicaErrorCode.BUSY, \"A reader holds the replica's write-ahead log; the purge finishes on the next open.\");\n }\n await this.#write(\"Finishing the revocation purge\", () => {\n this.#db.run(\"UPDATE replica SET purge_pending = 0 WHERE id = 1 AND revoked_detail IS NOT NULL\");\n });\n }\n\n async recordError(e: ReplicaLastError): Promise<void> {\n await this.#guardedWrite(\"Recording the sync error\", () => {\n this.#db.run(\"UPDATE replica SET last_error = ? WHERE id = 1\", JSON.stringify(e));\n });\n }\n\n async get(key: string): Promise<LocalEntry | undefined> {\n this.#assertAccepting();\n try {\n const row = this.#db.get<EntryRow>(\"SELECT key, deleted, etag, hash, metadata, content FROM entry WHERE key = ?\", key);\n return row === undefined ? undefined : entryOf(row);\n } catch (error) {\n throw storageError(error, \"Reading the replica\");\n }\n }\n\n async list(o: ListOpts): Promise<LocalEntry[]> {\n this.#assertAccepting();\n const where = [\"deleted = 0\"];\n const params: SqlValue[] = [];\n if (o.prefix !== undefined && o.prefix !== \"\") {\n where.push(\"key >= ?\", \"substr(key, 1, length(?)) = ?\");\n params.push(o.prefix, o.prefix, o.prefix);\n }\n if (o.after !== undefined) {\n where.push(\"key > ?\");\n params.push(o.after);\n }\n params.push(o.limit ?? -1);\n try {\n return this.#db\n .all<EntryRow>(\n `SELECT key, deleted, etag, hash, metadata, content FROM entry WHERE ${where.join(\" AND \")} ORDER BY key LIMIT ?`,\n ...params,\n )\n .map(entryOf);\n } catch (error) {\n throw storageError(error, \"Listing the replica\");\n }\n }\n\n async pendingRepairs(limit: number): Promise<Array<Extract<LocalEntry, { deleted: false }>>> {\n return this.#db\n .all<EntryRow>(\n \"SELECT key, deleted, etag, hash, metadata, content FROM entry WHERE deleted = 0 AND content = 0 ORDER BY key LIMIT ?\",\n limit,\n )\n .map(entryOf) as Array<Extract<LocalEntry, { deleted: false }>>;\n }\n\n async readContent(hash: string): Promise<Uint8Array | undefined> {\n if (!isHash(hash)) return undefined;\n try {\n return new Uint8Array(await readFile(this.#blobPath(hash)));\n } catch (error) {\n if (errnoOf(error) === \"ENOENT\") return undefined;\n throw storageError(error, \"Reading replica content\");\n }\n }\n\n async status(now = this.#now()): Promise<ReplicaStatus> {\n const state = await this.open();\n if (state === null) throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, \"The replica has not been created.\");\n const row = this.#row()!;\n const counts = this.#db.get<{ keys: number; missing: number; tombstones: number; bytes: number }>(\n `SELECT\n COALESCE(SUM(deleted = 0), 0) AS keys,\n COALESCE(SUM(deleted = 0 AND content = 0), 0) AS missing,\n COALESCE(SUM(deleted = 1), 0) AS tombstones,\n COALESCE(SUM(CASE WHEN deleted = 0 AND content = 1 THEN size ELSE 0 END), 0) AS bytes\n FROM entry`,\n )!;\n const { retentionRevoked: _retentionRevoked, ...authority } = effectiveAuthority({\n window: state.authority,\n grant: state.grant,\n revoked: state.revoked,\n retentionRevoked: state.retentionRevoked,\n policy: state.config.localReadPolicy,\n now,\n });\n return {\n name: state.config.name,\n replicaId: state.config.replicaId,\n source: { host: state.config.host, nodeDid: state.nodeDid, space: state.config.space, prefix: state.config.prefix },\n device: {\n did: state.config.deviceDid,\n delegationCid: state.grant?.cid ?? null,\n pendingDelegationCid: state.pendingGrant?.cid ?? null,\n pendingDelegationError: state.pendingGrantError,\n },\n authority: {\n ...authority,\n localReadPolicy: state.config.localReadPolicy,\n retentionGrantCid: state.config.retentionGrantCid,\n revokedDetail: state.revoked,\n retentionRevokedDetail: state.retentionRevoked,\n },\n consistency: \"observed\",\n coverage: state.coverage,\n lastSyncAt: state.lastSyncAt,\n lastCompleteAt: state.lastCompleteAt,\n counts: { keys: Number(counts.keys), contentMissing: Number(counts.missing), tombstones: Number(counts.tombstones) },\n bytes: Number(counts.bytes),\n durability: DURABILITY,\n syncing: row.lease_holder !== null && row.lease_expires_at !== null && row.lease_expires_at > now,\n purgePending: row.purge_pending === 1,\n lastError: state.lastError,\n lastReset: state.lastReset,\n };\n }\n\n close(): Promise<void> {\n if (this.#closePromise) return this.#closePromise;\n this.#closing = true;\n this.#closePromise = (async () => {\n if (this.#activeMutations !== 0) {\n await new Promise<void>((resolve) => { this.#drained = resolve; });\n }\n this.#closed = true;\n const fd = this.#directoryFd;\n this.#directoryFd = undefined;\n if (this.#shared) {\n sharedStores.unregister(this);\n releaseWritable(this.#shared);\n } else {\n if (fd !== undefined) pinnedDirectories.unregister(this);\n try { this.#database.close(); } finally { if (fd !== undefined) closeSync(fd); }\n }\n })();\n return this.#closePromise;\n }\n}\n","/**\n * Typed replica errors. Every failure a caller can act on has its own code;\n * hosts (CLI, worker) map codes to their own exit codes or UI states.\n */\nexport const ReplicaErrorCode = {\n /** Another process holds the sync lease. */\n BUSY: \"REPLICA_BUSY\",\n /** No replica with this name exists. */\n NOT_FOUND: \"REPLICA_NOT_FOUND\",\n /** The replica exists but its stored configuration differs from the request. */\n CONFIG_MISMATCH: \"REPLICA_CONFIG_MISMATCH\",\n /** The runtime has no supported durable store (e.g. Node < 22.13). */\n RUNTIME_UNSUPPORTED: \"RUNTIME_UNSUPPORTED\",\n /** A required open() argument is missing or malformed (e.g. `principal`). */\n INVALID_ARGUMENT: \"REPLICA_INVALID_ARGUMENT\",\n /** The local store failed (I/O, corruption, schema). */\n STORAGE_ERROR: \"STORAGE_ERROR\",\n /** The local disk is full. */\n STORAGE_FULL: \"STORAGE_FULL\",\n /** The key is outside the replica's prefix. */\n NOT_COVERED: \"NOT_COVERED\",\n /** Syncing the secrets space or the vault namespace needs an explicit opt-in. */\n SECRETS_OPT_IN_REQUIRED: \"SECRETS_OPT_IN_REQUIRED\",\n /** No grant is installed, or none covers the requested scope. */\n GRANT_MISSING: \"GRANT_MISSING\",\n /** The grant bytes are not a verifiable UCAN, or its signature is wrong. */\n GRANT_INVALID: \"GRANT_INVALID\",\n /** SIWE/CACAO and other non-UCAN grants cannot be used for a replica. */\n GRANT_FORMAT_UNSUPPORTED: \"GRANT_FORMAT_UNSUPPORTED\",\n /** The grant was issued to a different device. */\n GRANT_AUDIENCE_MISMATCH: \"GRANT_AUDIENCE_MISMATCH\",\n /** The grant lacks `tinycloud.kv/sync` or `tinycloud.kv/get` on the prefix. */\n GRANT_NOT_COVERING: \"GRANT_NOT_COVERING\",\n GRANT_NOT_YET_VALID: \"GRANT_NOT_YET_VALID\",\n GRANT_EXPIRED: \"GRANT_EXPIRED\",\n /** The configured node does not advertise whole-space KV sync support. */\n REPLICATION_ROOT_UNSUPPORTED: \"REPLICATION_ROOT_UNSUPPORTED\",\n GRANT_REVOKED: \"GRANT_REVOKED\",\n /** The node refused the invocation for a reason other than revocation. */\n GRANT_UNAUTHORIZED: \"GRANT_UNAUTHORIZED\",\n /** The node refused the retention grant. */\n RETENTION_GRANT_REFUSED: \"RETENTION_GRANT_REFUSED\",\n /** The node could not be reached. */\n NETWORK_ERROR: \"NETWORK_ERROR\",\n /** The node answered with an unexpected status. */\n NODE_ERROR: \"NODE_ERROR\",\n /** The node's answer violates the wire contract. */\n PROTOCOL_ERROR: \"PROTOCOL_ERROR\",\n /** The node asked for a fresh bootstrap (410). Handled inside sync. */\n RESET_REQUIRED: \"RESET_REQUIRED\",\n /** The feed now comes from a different node than the one pinned. */\n SOURCE_CHANGED: \"SOURCE_CHANGED\",\n /** The feed delivered a key outside the replica's prefix. */\n SCOPE_VIOLATION: \"SCOPE_VIOLATION\",\n /** Fetched bytes do not hash to the ETag the node attested for them. */\n CONTENT_MISMATCH: \"CONTENT_MISMATCH\",\n /** A stored blob no longer hashes to its name. */\n INTEGRITY_ERROR: \"INTEGRITY_ERROR\",\n /** The replica handle was closed; in-flight calls settle with this code. */\n CLOSED: \"REPLICA_CLOSED\",\n /** The lifecycle gate refused the operation (shared contract `REPLICA_GATED`); `detail.gate` says why. */\n GATED: \"REPLICA_GATED\",\n /** Quota admission refused a page (`maxBytes` or the free-space floor); nothing committed. */\n STORAGE_BUDGET: \"STORAGE_BUDGET\",\n /** The consent deadline passed: the grant is not served until the user consents again. */\n CONSENT_EXPIRED: \"CONSENT_EXPIRED\",\n} as const;\n\nexport type ReplicaErrorCode = (typeof ReplicaErrorCode)[keyof typeof ReplicaErrorCode];\n\n/**\n * The package ships separate entry bundles (`.`, `./sqlite`), each with its own\n * copy of this class, so identity is a registered symbol, not `instanceof`.\n */\nconst REPLICA_ERROR = Symbol.for(\"tinycloud.replica.error\");\n\nexport class ReplicaError extends Error {\n readonly [REPLICA_ERROR] = true;\n readonly code: ReplicaErrorCode;\n readonly detail?: Record<string, unknown>;\n\n constructor(code: ReplicaErrorCode, message: string, detail?: Record<string, unknown>, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ReplicaError\";\n this.code = code;\n if (detail !== undefined) this.detail = detail;\n }\n}\n\nexport function isReplicaError(error: unknown, code?: ReplicaErrorCode): error is ReplicaError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as { [REPLICA_ERROR]?: unknown })[REPLICA_ERROR] === true &&\n (code === undefined || (error as ReplicaError).code === code)\n );\n}\n\n/**\n * A lifecycle-gate refusal in the shared contract's shape:\n * `Error & { code: \"REPLICA_GATED\"; gate }`, with `gate` also in `detail`\n * so it survives the worker boundary.\n */\nexport function gatedError(gate: string, message: string): ReplicaError & { gate: string } {\n return Object.assign(new ReplicaError(ReplicaErrorCode.GATED, message, { gate }), { gate });\n}\n","/** Shared prefix boundary and configuration rules; no runtime dependencies. */\nexport function kvPrefixCovers(prefix: string, key: string): boolean {\n return prefix === \"/\" || key.startsWith(prefix);\n}\n\n/** Replication scopes are `/` or non-empty, slash-terminated folder paths. */\nexport function assertFolderPrefix(prefix: unknown): asserts prefix is string {\n const validFolder = typeof prefix === \"string\" &&\n prefix.length > 0 &&\n !prefix.startsWith(\"/\") &&\n !prefix.includes(\"//\") &&\n prefix.endsWith(\"/\");\n if (prefix !== \"/\" && !validFolder) {\n const folderHint = typeof prefix === \"string\"\n ? prefix.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")\n : \"\";\n const suggestion = folderHint.length > 0 && !folderHint.includes(\"//\")\n ? ` Use ${JSON.stringify(`${folderHint}/`)}.`\n : ' Use \"/\" or a slash-terminated folder path such as \"notes/\".';\n throw new TypeError(`Replication prefix must be \"/\" or a non-empty slash-terminated folder path without empty segments.${suggestion}`);\n }\n}\n","import { ReplicaError, ReplicaErrorCode } from \"./errors.js\";\nimport type { AuthorityState, AuthorityWindow, GrantRecord, LocalReadPolicy } from \"./types.js\";\nimport { assertFolderPrefix as assertPureFolderPrefix } from \"@tinycloud/sdk-services/kv/replication/prefix\";\n\n/** Replication prefixes are the whole space (`/`) or a slash-terminated folder. */\nexport function assertFolderPrefix(prefix: unknown): asserts prefix is string {\n try {\n assertPureFolderPrefix(prefix);\n } catch {\n const folderHint = typeof prefix === \"string\"\n ? prefix.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")\n : \"\";\n const suggestion = prefix === \"\" ? 'use \"/\" for the whole space' :\n folderHint.length > 0 && !folderHint.includes(\"//\")\n ? `use ${JSON.stringify(`${folderHint}/`)}`\n : 'use \"/\" for the whole space or a folder path such as \"notes/\"';\n throw new ReplicaError(\n ReplicaErrorCode.INVALID_ARGUMENT,\n `Replication prefix ${JSON.stringify(prefix)} must be \"/\" or a non-empty folder path ending in / without empty segments; ${suggestion}. Run \\`tc replica reset --replica <name> --purge\\` and recreate it with the folder prefix.`,\n );\n }\n}\n\n/** Prefix coverage shared with the KV replication feed. */\nexport function kvPrefixCovers(prefix: string, key: string): boolean {\n return prefix === \"/\" || key.startsWith(prefix);\n}\n/** Capability containment: exact grants cover exact keys; slash grants cover descendants. */\nexport function authorityPathCovers(grantPath: string, requestedPath: string): boolean {\n if (grantPath === \"/\") return true;\n if (grantPath.endsWith(\"/\")) return requestedPath.startsWith(grantPath);\n return requestedPath === grantPath;\n}\n\n/**\n * Syncing the owner's secrets space, or any prefix overlapping the vault\n * namespace (including bare `vault`), copies encrypted secret material to\n * disk and needs an explicit opt-in (TC-733).\n */\nexport function requiresSecretsOptIn(space: string, prefix: string): boolean {\n if (prefix === \"/\") return true;\n if (space === \"secrets\" || space.endsWith(\":secrets\")) return true;\n const firstSegment = prefix.split(\"/\", 1)[0];\n return firstSegment === \"vault\";\n}\n\n/** Browser read-through replicas never retain secrets or vault data, even with legacy opt-in. */\nexport function assertBrowserReadThroughScope(space: string, prefix: string, allowSecrets: boolean): void {\n if (allowSecrets || requiresSecretsOptIn(space, prefix) || prefix.split(\"/\", 1)[0] === \"secrets\") {\n throw new ReplicaError(\n ReplicaErrorCode.INVALID_ARGUMENT,\n \"Browser read-through replicas require allowSecrets=false and exclude the whole space, secrets and vault prefixes.\",\n );\n }\n}\n\n/** `\"blake3-<hex>\"` (quoted or not) → the 64-hex hash, or undefined. */\nexport function hashFromEtag(etag: string): string | undefined {\n const match = /^\"?blake3-([0-9a-f]{64})\"?$/.exec(etag);\n return match?.[1];\n}\n\nconst RFC3339 = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\n/** An RFC 3339 instant that parses: the only form an authority bound may take. */\nexport function isInstant(value: string): boolean {\n return RFC3339.test(value) && Number.isFinite(Date.parse(value));\n}\n\nexport type EffectiveAuthority = {\n state: AuthorityState;\n notBefore: string | null;\n expiresAt: string | null;\n retainUntil: string | null;\n /** The retention grant was revoked: after expiry, reads are revoked rather than expired. */\n retentionRevoked: boolean;\n};\n\nfunction minIso(a: string | null, bSeconds: number | null): string | null {\n if (bSeconds === null) return a;\n const b = new Date(bSeconds * 1000).toISOString();\n if (a === null) return b;\n return Date.parse(a) <= Date.parse(b) ? a : b;\n}\n\nfunction maxIso(a: string | null, bSeconds: number | null): string | null {\n if (bSeconds === null) return a;\n const b = new Date(bSeconds * 1000).toISOString();\n if (a === null) return b;\n return Date.parse(a) >= Date.parse(b) ? a : b;\n}\n\n/**\n * The window local reads are enforced against: the node-attested window from\n * the last successful sync, bounded by the installed leaf grant (an upper\n * bound only — a multi-parent ancestor can end the chain earlier, which only\n * the node can see).\n */\nexport function effectiveAuthority(input: {\n window: AuthorityWindow | null;\n grant: GrantRecord | null;\n revoked: string | null;\n retentionRevoked?: string | null;\n policy: LocalReadPolicy;\n now: number;\n}): EffectiveAuthority {\n const notBefore = maxIso(input.window?.notBefore ?? null, input.grant?.notBefore ?? null);\n const expiresAt = minIso(input.window?.expiresAt ?? null, input.grant?.expiresAt ?? null);\n const retainUntil = input.policy === \"retainAfterExpiry\" ? input.window?.retainUntil ?? null : null;\n let state: AuthorityState = \"valid\";\n if (input.revoked !== null) state = \"revoked\";\n else if (notBefore !== null && input.now < Date.parse(notBefore)) state = \"not-yet-valid\";\n else if (expiresAt !== null && input.now >= Date.parse(expiresAt)) state = \"expired\";\n return { state, notBefore, expiresAt, retainUntil, retentionRevoked: (input.retentionRevoked ?? null) !== null };\n}\n\n/**\n * Throws unless local reads are allowed now. Returns the reported authority\n * state: `valid`, or `expired` while a node-attested retention holds.\n */\nexport function assertReadable(authority: EffectiveAuthority, now: number): AuthorityState {\n switch (authority.state) {\n case \"valid\":\n return \"valid\";\n case \"revoked\":\n throw new ReplicaError(ReplicaErrorCode.GRANT_REVOKED, \"The replica's grant was revoked; local reads are blocked.\");\n case \"not-yet-valid\":\n throw new ReplicaError(\n ReplicaErrorCode.GRANT_NOT_YET_VALID,\n `The replica's grant is not valid before ${authority.notBefore}.`,\n );\n case \"expired\":\n if (authority.retentionRevoked) {\n throw new ReplicaError(\n ReplicaErrorCode.GRANT_REVOKED,\n `The replica's grant expired at ${authority.expiresAt} and its retention grant was revoked; local reads are blocked.`,\n );\n }\n if (authority.retainUntil !== null && now < Date.parse(authority.retainUntil)) return \"expired\";\n throw new ReplicaError(\n ReplicaErrorCode.GRANT_EXPIRED,\n authority.retainUntil === null\n ? `The replica's grant expired at ${authority.expiresAt}; local reads are blocked.`\n : `The replica's retention ended at ${authority.retainUntil}; local reads are blocked.`,\n );\n }\n}\n","import { ReplicaError, ReplicaErrorCode } from \"../errors.js\";\n\nexport type SqlValue = string | number | null | Uint8Array;\n\n/** The synchronous SQLite surface shared by `node:sqlite` and `bun:sqlite`. */\nexport interface SqliteDatabase {\n exec(sql: string): void;\n run(sql: string, ...params: SqlValue[]): void;\n get<T>(sql: string, ...params: SqlValue[]): T | undefined;\n all<T>(sql: string, ...params: SqlValue[]): T[];\n\n close(): void;\n}\n\ntype Statement = {\n run(...params: SqlValue[]): unknown;\n get(...params: SqlValue[]): unknown;\n all(...params: SqlValue[]): unknown[];\n finalize?(): void;\n};\ntype NativeDatabase = { exec(sql: string): void; prepare(sql: string): Statement; close(): void };\n\nexport type SqliteOpenOptions = { readonly?: boolean };\nexport type SqliteOpener = (path: string, options?: SqliteOpenOptions) => SqliteDatabase;\n\nfunction wrap(native: NativeDatabase): SqliteDatabase {\n const statements = new Map<string, Statement>();\n const prepared = (sql: string): Statement => {\n let statement = statements.get(sql);\n if (statement === undefined) {\n statement = native.prepare(sql);\n statements.set(sql, statement);\n }\n return statement;\n };\n return {\n exec: (sql) => native.exec(sql),\n run: (sql, ...params) => void prepared(sql).run(...params),\n // bun:sqlite answers a missing row with null, node:sqlite with undefined.\n get: <T>(sql: string, ...params: SqlValue[]) => (prepared(sql).get(...params) ?? undefined) as T | undefined,\n all: <T>(sql: string, ...params: SqlValue[]) => prepared(sql).all(...params) as T[],\n close: () => {\n let failure: unknown;\n try {\n for (const statement of statements.values()) {\n try {\n statement.finalize?.();\n } catch (error) {\n failure ??= error;\n }\n }\n } finally {\n statements.clear();\n native.close();\n }\n if (failure !== undefined) throw failure;\n },\n };\n}\n\n\n/** Node ≥ 22.13 ships `node:sqlite` without a flag. */\nexport function nodeSqliteSupported(version: string): boolean {\n const [major = 0, minor = 0] = version.split(\".\").map(Number);\n return major > 22 || (major === 22 && minor >= 13);\n}\n\n/**\n * Load the runtime's built-in SQLite: `bun:sqlite` under Bun, `node:sqlite`\n * on Node ≥ 22.13. No native addon. Specifiers are computed so bundlers keep\n * both modules external, and only SQLite's ExperimentalWarning is silenced.\n */\nexport async function loadSqlite(): Promise<SqliteOpener> {\n const runtime = globalThis as { Bun?: unknown; process?: NodeJS.Process };\n const load = (specifier: string): Promise<Record<string, unknown>> => import(specifier);\n if (runtime.Bun !== undefined) {\n const module = await load([\"bun\", \"sqlite\"].join(\":\"));\n const Database = module.Database as new (path: string, options: { create: boolean; readonly?: boolean } | number) => NativeDatabase;\n return (path, options) =>\n wrap(new Database(path, { create: !options?.readonly, ...(options?.readonly ? { readonly: true } : {}) }));\n }\n const version = runtime.process?.versions?.node ?? \"0.0.0\";\n if (!nodeSqliteSupported(version)) {\n throw new ReplicaError(\n ReplicaErrorCode.RUNTIME_UNSUPPORTED,\n `tc replica needs Node.js 22.13 or newer (built-in SQLite); this is Node.js ${version}.`,\n { node: version },\n );\n }\n const process = runtime.process!;\n const emitWarning = process.emitWarning;\n process.emitWarning = function (this: NodeJS.Process, warning: string | Error, ...rest: unknown[]) {\n const message = typeof warning === \"string\" ? warning : warning.message;\n const type = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string } | undefined)?.type ?? (warning as Error).name;\n if (type === \"ExperimentalWarning\" && /SQLite/i.test(message)) return;\n return (emitWarning as (...args: unknown[]) => void).call(this, warning, ...rest);\n } as NodeJS.Process[\"emitWarning\"];\n let module: Record<string, unknown>;\n try {\n module = await load([\"node\", \"sqlite\"].join(\":\"));\n } finally {\n process.emitWarning = emitWarning;\n }\n const DatabaseSync = module.DatabaseSync as new (path: string, options?: { readOnly?: boolean }) => NativeDatabase;\n return (path, options) =>\n wrap(options?.readonly ? new DatabaseSync(path, { readOnly: true }) : new DatabaseSync(path));\n}\n","import { constants as fsConstants, type BigIntStats } from \"node:fs\";\nimport { lstat, open, readdir, rmdir, unlink, type FileHandle } from \"node:fs/promises\";\nimport { join, parse, resolve, sep } from \"node:path\";\n\nimport { loadSqlite } from \"./driver.js\";\nimport { SCHEMA, SCHEMA_VERSION } from \"./schema.js\";\n\n// The policy-v2 branch migrated v1 in place with these exact ALTER TABLEs,\n// whereas the other v2 lineage created grant_install without changing replica.\nconst POLICY_COLUMNS = [\n \"grant_installed_at REAL\", \"grant_effective_expires_at REAL\", \"grant_consent_deadline REAL\",\n \"grant_consent_anchor_at REAL\", \"grant_consent_anchor_source TEXT\",\n \"pending_grant_installed_at REAL\", \"pending_grant_effective_expires_at REAL\",\n \"pending_grant_consent_deadline REAL\", \"pending_grant_consent_anchor_at REAL\",\n \"pending_grant_consent_anchor_source TEXT\",\n];\nconst normalizeSchema = (sql: string): string =>\n sql.replace(\" IF NOT EXISTS\", \"\").replace(/\\s+/g, \" \").trim();\nconst SOURCE_SCHEMA = SCHEMA.trim().split(\";\").map((sql) => sql.trim()).filter(Boolean).map((sql) => {\n const match = /^CREATE (TABLE|INDEX) IF NOT EXISTS ([a-z_]+)/.exec(sql);\n if (match === null) throw new Error(\"Invalid source replica schema.\");\n return { type: match[1]!.toLowerCase(), name: match[2]!, sql: normalizeSchema(sql) };\n});\nconst V1_SCHEMA = SOURCE_SCHEMA.filter((entry) => entry.name !== \"grant_install\");\nconst POLICY_REPLICA = V1_SCHEMA.find((entry) => entry.name === \"replica\")!.sql\n .replace(/\\) STRICT$/, `, ${POLICY_COLUMNS.join(\", \")}) STRICT`);\nconst POLICY_SCHEMA = V1_SCHEMA.map((entry) =>\n entry.name === \"replica\" ? { ...entry, sql: POLICY_REPLICA } : entry);\n\n/** A pathname alone cannot prove that a database contains no local outbox. */\nasync function sourceMirrorSchema(path: string): Promise<boolean> {\n let db;\n try {\n db = (await loadSqlite())(path, { readonly: true });\n db.exec(\"BEGIN\");\n const version = db.get<{ user_version: number }>(\"PRAGMA user_version\")?.user_version;\n if (version !== 1 && version !== SCHEMA_VERSION) return false;\n const rows = db.all<{ type: string; name: string; sql: string | null }>(\n \"SELECT type, name, sql FROM sqlite_schema WHERE sql IS NOT NULL ORDER BY name\",\n );\n const expected = version === 1 ? V1_SCHEMA : SOURCE_SCHEMA;\n const matches = (schema: typeof expected): boolean =>\n rows.length === schema.length && rows.every((row) => {\n const source = schema.find((entry) => entry.name === row.name);\n return source?.type === row.type && source.sql === normalizeSchema(row.sql!);\n });\n if (matches(expected)) return true;\n if (version !== 2) return false;\n // 351dd45b defined a separate v2 migration: ten nullable policy columns,\n // no grant_install. Accept only that exact source-created shape.\n return matches(POLICY_SCHEMA);\n } catch {\n return false;\n } finally {\n try { db?.close(); } catch { /* A failed schema read remains unknown. */ }\n }\n}\n\nconst SQLITE_FILE = /^(?:replica\\.db|replica\\.db-(?:wal|shm|journal))$/;\nconst SHARD = /^[0-9a-f]{2}$/;\nconst HASH = /^[0-9a-f]{64}$/;\nconst TEMP = /^[0-9a-f]{64}\\.[0-9a-f]{12}$/;\n\ntype Kind = \"file\" | \"directory\" | \"unknown\";\n\n/** The only names this store creates beside its SQLite database. */\nfunction sourceKind(parent: string, name: string, allowAdapterFence: boolean): Kind {\n if (parent === \"\") {\n if (SQLITE_FILE.test(name) || (allowAdapterFence &&\n (name === \"fence.json\" || /^fence[.]json[.][0-9a-f]{12}[.]tmp$/.test(name)))) return \"file\";\n return name === \"blobs\" ? \"directory\" : \"unknown\";\n }\n if (parent === \"blobs\") return name === \".tmp\" || SHARD.test(name) ? \"directory\" : \"unknown\";\n if (parent === \"blobs/.tmp\") return TEMP.test(name) ? \"file\" : \"unknown\";\n if (parent.startsWith(\"blobs/\") && SHARD.test(parent.slice(6))) {\n return HASH.test(name) && name.startsWith(parent.slice(6)) ? \"file\" : \"unknown\";\n }\n return \"unknown\";\n}\n\nexport interface SqliteLayoutEntry {\n path: string;\n kind: \"file\" | \"directory\" | \"symlink\";\n dev: string;\n ino: string;\n}\n\nexport type SqliteLayoutIdentity = { dev: string; ino: string };\ntype Identity = Pick<BigIntStats, \"dev\" | \"ino\">;\ntype Component = { path: string; identity: Identity };\ntype Directory = {\n path: string;\n name: string;\n relative: string;\n identity: BigIntStats;\n handle: FileHandle;\n children: Child[];\n parent?: Directory;\n components?: Component[];\n};\ntype Child = { path: string; relative: string; kind: SqliteLayoutEntry[\"kind\"]; identity: BigIntStats; parent: Directory; directory?: Directory };\n\nfunction sameFile(a: Identity, b: Identity): boolean {\n return a.dev === b.dev && a.ino === b.ino;\n}\n\nfunction identityOf(path: string, kind: SqliteLayoutEntry[\"kind\"], details: Identity): SqliteLayoutEntry {\n return { path, kind, dev: details.dev.toString(), ino: details.ino.toString() };\n}\n\nfunction fileKind(details: BigIntStats): SqliteLayoutEntry[\"kind\"] {\n if (details.isFile()) return \"file\";\n if (details.isDirectory()) return \"directory\";\n if (details.isSymbolicLink()) return \"symlink\";\n throw new Error(\"Unsupported replica entry type.\");\n}\n\n// On named-path platforms every ancestor, including the root, is a real\n// directory whose identity must remain stable for the duration of deletion.\nasync function pathComponents(path: string): Promise<Component[]> {\n const absolute = resolve(path);\n const parts = absolute.slice(parse(absolute).root.length).split(sep).filter(Boolean);\n let current = parse(absolute).root;\n const components: Component[] = [];\n for (const part of [\"\", ...parts]) {\n if (part) current = join(current, part);\n const details = await lstat(current, { bigint: true });\n if (details.isSymbolicLink()) throw new Error(`Symlink in replica path: ${current}`);\n if (!details.isDirectory()) throw new Error(`Replica path component is not a directory: ${current}`);\n components.push({ path: current, identity: details });\n }\n return components;\n}\n\nasync function pinnedDirectory(path: string, parent?: Directory, relative = \"\"): Promise<Directory> {\n const components = process.platform === \"linux\" ? undefined : parent?.components ?? await pathComponents(path);\n const before = await lstat(path, { bigint: true });\n if (before.isSymbolicLink()) throw new Error(`Symlink in replica path: ${path}`);\n if (!before.isDirectory()) throw new Error(\"Replica directory is not a real directory.\");\n const handle = await open(path, fsConstants.O_RDONLY | fsConstants.O_DIRECTORY | fsConstants.O_NOFOLLOW);\n try {\n if (!sameFile(before, await handle.stat({ bigint: true }))) {\n throw new Error(\"Replica directory changed during inspection.\");\n }\n return {\n handle, identity: before, parent, components, children: [],\n relative, name: path,\n path: process.platform === \"linux\" ? `/proc/self/fd/${handle.fd}` : path,\n };\n } catch (error) {\n await handle.close();\n throw error;\n }\n}\n\n// The leaf is checked before its ancestors, so a parent swapped while the leaf\n// is examined is still seen before the caller's unlink or rmdir.\nasync function checkDirectory(directory: Directory): Promise<void> {\n const details = await lstat(directory.name, { bigint: true });\n if (!details.isDirectory() || !sameFile(directory.identity, details)) {\n throw new Error(`Replica directory changed: ${directory.relative || directory.name}`);\n }\n if (directory.parent) await checkDirectory(directory.parent);\n else if (directory.components) {\n for (const component of directory.components) {\n const current = await lstat(component.path, { bigint: true });\n if (current.isSymbolicLink() || !current.isDirectory() || !sameFile(component.identity, current)) {\n throw new Error(`Replica path component changed: ${component.path}`);\n }\n }\n }\n}\n\nasync function inspect(dir: string, allowAdapterFence: boolean): Promise<{\n root: Directory; directories: Directory[];\n knownEntries: SqliteLayoutEntry[]; unknownPaths: string[]; unknownEntries: SqliteLayoutEntry[];\n}> {\n const root = await pinnedDirectory(dir);\n const directories = [root];\n const unknownPaths: string[] = [];\n const knownEntries: SqliteLayoutEntry[] = [];\n const unknownEntries: SqliteLayoutEntry[] = [];\n let hasDatabase = false;\n try {\n async function walk(parent: Directory): Promise<void> {\n await checkDirectory(parent);\n for (const name of (await readdir(parent.path)).sort()) {\n await checkDirectory(parent);\n const relative = parent.relative ? `${parent.relative}/${name}` : name;\n const path = join(parent.path, name);\n const details = await lstat(path, { bigint: true });\n if (process.platform !== \"linux\" && details.isSymbolicLink()) {\n throw new Error(`Symlink in replica path: ${relative}`);\n }\n const kind = fileKind(details);\n const child: Child = { path, relative, kind, identity: details, parent };\n parent.children.push(child);\n if (parent.relative === \"\" && name === \"replica.db\" && kind === \"file\") hasDatabase = true;\n if (sourceKind(parent.relative, name, allowAdapterFence) !== kind) {\n unknownPaths.push(relative);\n unknownEntries.push(identityOf(relative, kind, details));\n } else {\n knownEntries.push(identityOf(relative, kind, details));\n }\n if (kind === \"directory\") {\n const directory = await pinnedDirectory(path, parent, relative);\n if (!sameFile(details, directory.identity)) {\n await directory.handle.close();\n throw new Error(`Replica directory changed during inspection: ${relative}`);\n }\n child.directory = directory;\n directories.push(directory);\n await walk(directory);\n }\n }\n }\n await walk(root);\n if (!hasDatabase) {\n unknownPaths.push(\"replica.db\");\n } else if (!(await sourceMirrorSchema(join(root.path, \"replica.db\")))) {\n const index = knownEntries.findIndex((entry) => entry.path === \"replica.db\");\n if (index >= 0) unknownEntries.push(knownEntries.splice(index, 1)[0]!);\n unknownPaths.push(\"replica.db\");\n }\n // SQLite may materialize a WAL shared-memory sidecar for a readonly\n // schema query. Record the *post-query* inode, never approve a file that\n // was not actually present in the displayed inventory.\n await checkDirectory(root);\n const names = new Set(await readdir(root.path));\n for (let index = root.children.length - 1; index >= 0; index--) {\n const child = root.children[index]!;\n if (!names.has(child.relative)) {\n if (child.directory) throw new Error(`Replica directory vanished: ${child.relative}`);\n root.children.splice(index, 1);\n for (const list of [knownEntries, unknownEntries]) {\n const entryIndex = list.findIndex((entry) => entry.path === child.relative);\n if (entryIndex >= 0) list.splice(entryIndex, 1);\n }\n const pathIndex = unknownPaths.indexOf(child.relative);\n if (pathIndex >= 0) unknownPaths.splice(pathIndex, 1);\n continue;\n }\n const current = await lstat(child.path, { bigint: true });\n if (!sameFile(child.identity, current) || fileKind(current) !== child.kind) {\n throw new Error(`Replica child changed during schema inspection: ${child.relative}`);\n }\n }\n for (const name of names) {\n if (root.children.some((child) => child.relative === name)) continue;\n const path = join(root.path, name);\n const details = await lstat(path, { bigint: true });\n if (!/^replica\\.db-(?:wal|shm|journal)$/.test(name) || !details.isFile()) {\n throw new Error(`Unexpected replica child during schema inspection: ${name}`);\n }\n root.children.push({ path, relative: name, kind: \"file\", identity: details, parent: root });\n knownEntries.push(identityOf(name, \"file\", details));\n }\n return { root, directories, knownEntries, unknownPaths, unknownEntries };\n } catch (error) {\n await closeDirectories(directories);\n throw error;\n }\n}\n\nasync function closeDirectories(directories: Directory[]): Promise<void> {\n for (const directory of directories.reverse()) await directory.handle.close();\n}\n\n/** JSON-safe exact inventory of non-mirror entries for durable approval. */\nexport async function inspectSqliteReplicaLayout(\n dir: string, options: { allowAdapterFence?: boolean } = {},\n): Promise<{ knownEntries: SqliteLayoutEntry[]; unknownPaths: string[]; unknownEntries: SqliteLayoutEntry[]; rootIdentity: SqliteLayoutIdentity }> {\n const inventory = await inspect(dir, options.allowAdapterFence === true);\n try {\n return {\n knownEntries: inventory.knownEntries, unknownPaths: inventory.unknownPaths, unknownEntries: inventory.unknownEntries,\n rootIdentity: { dev: inventory.root.identity.dev.toString(), ino: inventory.root.identity.ino.toString() },\n };\n } finally {\n await closeDirectories(inventory.directories);\n }\n}\n\nfunction approvedEntries(entries: readonly SqliteLayoutEntry[]): Map<string, SqliteLayoutEntry> {\n const approved = new Map<string, SqliteLayoutEntry>();\n for (const entry of entries) {\n if (typeof entry !== \"object\" || entry === null ||\n Object.keys(entry).sort().join(\",\") !== \"dev,ino,kind,path\" ||\n typeof entry.path !== \"string\" || !entry.path ||\n entry.path.split(\"/\").some((part) => !part || part === \".\" || part === \"..\" || part.includes(\"\\\\\")) ||\n ![\"file\", \"directory\", \"symlink\"].includes(entry.kind) ||\n typeof entry.dev !== \"string\" || !/^(0|[1-9][0-9]*)$/.test(entry.dev) ||\n typeof entry.ino !== \"string\" || !/^(0|[1-9][0-9]*)$/.test(entry.ino) ||\n approved.has(entry.path)) {\n throw new Error(\"Invalid or duplicate replica approval.\");\n }\n approved.set(entry.path, entry);\n }\n return approved;\n}\n\n/** Test-only interleaving seam for replacement races between enumerated unlinks. */\nexport const LAYOUT_FAULTS = Symbol(\"tinycloud.replica.layout-faults\");\n\n/** Lease holder only: delete enumerated files, never recurse into an unapproved child. */\nexport async function removeSqliteReplicaLayout(\n dir: string, options: {\n approvedUnknown?: readonly SqliteLayoutEntry[];\n expectedKnown?: readonly SqliteLayoutEntry[];\n allowMissingDatabase?: boolean;\n expectedRoot?: SqliteLayoutIdentity;\n allowAdapterFence?: boolean;\n [LAYOUT_FAULTS]?: { beforeUnlink?(path: string): void | Promise<void> };\n } = {},\n): Promise<void> {\n const inventory = await inspect(dir, options.allowAdapterFence === true);\n try {\n if (options.expectedRoot &&\n (options.expectedRoot.dev !== inventory.root.identity.dev.toString() ||\n options.expectedRoot.ino !== inventory.root.identity.ino.toString())) {\n throw new Error(\"Replica root identity changed since approval.\");\n }\n const approved = approvedEntries(options.approvedUnknown ?? []);\n // Missing approved entries are safe after a partially completed prior attempt.\n // Every entry still present must match its original kind and inode.\n for (const entry of inventory.unknownEntries) {\n const match = approved.get(entry.path);\n if (!match || match.kind !== entry.kind || match.dev !== entry.dev || match.ino !== entry.ino) {\n throw new Error(`Unknown replica child or approval identity mismatch: ${entry.path}`);\n }\n }\n if (options.expectedKnown) {\n const expected = approvedEntries(options.expectedKnown);\n for (const entry of inventory.knownEntries) {\n const match = expected.get(entry.path);\n if (!match || match.kind !== entry.kind || match.dev !== entry.dev || match.ino !== entry.ino) {\n throw new Error(`Known replica child changed since preflight: ${entry.path}`);\n }\n }\n }\n if (options.allowMissingDatabase && inventory.knownEntries.some((entry) => entry.path === \"replica.db\")) {\n throw new Error(\"Replica database appeared after approval of its absence.\");\n }\n if (inventory.unknownPaths.length !== inventory.unknownEntries.length &&\n inventory.root.children.length > 0 && !options.allowMissingDatabase) {\n throw new Error(\"Replica database is missing; cannot approve removal.\");\n }\n // Keep the SQLite database until all other content is gone, so failures\n // before its unlink leave the mirror usable for a guarded retry.\n async function removeDirectory(directory: Directory): Promise<void> {\n for (const child of directory.children\n .sort((a, b) => (a.relative === \"replica.db\" ? 1 : b.relative === \"replica.db\" ? -1 : 0))) {\n if (child.directory) {\n await removeDirectory(child.directory);\n }\n await options[LAYOUT_FAULTS]?.beforeUnlink?.(child.relative);\n await checkDirectory(directory);\n const details = await lstat(child.path, { bigint: true });\n if (process.platform !== \"linux\" && details.isSymbolicLink()) {\n throw new Error(`Symlink in replica path: ${child.relative}`);\n }\n if (fileKind(details) !== child.kind || !sameFile(child.identity, details)) {\n throw new Error(`Replica child identity changed: ${child.relative}`);\n }\n if (child.directory) await rmdir(child.path);\n else await unlink(child.path);\n }\n }\n await removeDirectory(inventory.root);\n await checkDirectory(inventory.root);\n await rmdir(inventory.root.name);\n } finally {\n await closeDirectories(inventory.directories);\n }\n}\n","// Source-created SQLite mirror DDL shared by the store and read-only layout validator.\nexport const SCHEMA_VERSION = 2;\nexport const SCHEMA = `\nCREATE TABLE IF NOT EXISTS replica (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n name TEXT NOT NULL,\n replica_id TEXT NOT NULL,\n host TEXT NOT NULL,\n space TEXT NOT NULL,\n prefix TEXT NOT NULL,\n device_did TEXT NOT NULL,\n allow_secrets INTEGER NOT NULL CHECK (allow_secrets IN (0, 1)),\n local_read_policy TEXT NOT NULL CHECK (local_read_policy IN ('whileGrantValid', 'retainAfterExpiry')),\n retention_grant_cid TEXT,\n grant_cid TEXT,\n grant_bytes BLOB,\n grant_audience TEXT,\n grant_issuer TEXT,\n grant_nbf INTEGER,\n grant_exp INTEGER,\n pending_grant_cid TEXT,\n pending_grant_bytes BLOB,\n pending_grant_audience TEXT,\n pending_grant_issuer TEXT,\n pending_grant_nbf INTEGER,\n pending_grant_exp INTEGER,\n node_did TEXT,\n attested INTEGER NOT NULL DEFAULT 0 CHECK (attested IN (0, 1)),\n not_before TEXT,\n expires_at TEXT,\n retain_until TEXT,\n revoked_detail TEXT,\n purge_pending INTEGER NOT NULL DEFAULT 0 CHECK (purge_pending IN (0, 1)),\n retention_revoked TEXT,\n pending_grant_error TEXT,\n cursor TEXT,\n coverage TEXT NOT NULL CHECK (coverage IN ('empty', 'bootstrapping', 'complete')),\n generation INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n last_sync_at TEXT,\n last_complete_at TEXT,\n last_error TEXT,\n last_reset TEXT,\n lease_token INTEGER NOT NULL DEFAULT 0,\n lease_holder TEXT,\n lease_expires_at INTEGER\n) STRICT;\nCREATE TABLE IF NOT EXISTS entry (\n key TEXT PRIMARY KEY,\n deleted INTEGER NOT NULL CHECK (deleted IN (0, 1)),\n etag TEXT,\n hash TEXT,\n metadata TEXT NOT NULL,\n content INTEGER NOT NULL CHECK (content IN (0, 1)),\n size INTEGER,\n CHECK (\n (deleted = 1 AND etag IS NULL AND hash IS NULL AND content = 0 AND size IS NULL) OR\n (deleted = 0 AND etag IS NOT NULL AND hash IS NOT NULL)\n )\n) STRICT, WITHOUT ROWID;\nCREATE INDEX IF NOT EXISTS entry_hash ON entry (hash) WHERE hash IS NOT NULL;\nCREATE TABLE IF NOT EXISTS grant_install (\n cid TEXT PRIMARY KEY,\n installed_at INTEGER NOT NULL,\n effective_expires_at INTEGER NOT NULL,\n consent_deadline INTEGER NOT NULL,\n consent_anchor_at INTEGER NOT NULL,\n consent_anchor_source TEXT NOT NULL\n) STRICT, WITHOUT ROWID;\n`;\n"],"mappings":"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","names":["fsConstants","lstat","open","readdir","rmdir","unlink","join","resolve","assertFolderPrefix","module","process","resolve","lstat","open","fsConstants","readdir","join","assertFolderPrefix","unlink","rmdir"]}
|