@sema-agent/core
Version:
Stateless, task-oriented AI agent core
3,859 lines • 196 kB
JavaScript
import { existsSync, fstatSync, linkSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, openSync, fsyncSync, closeSync, utimesSync } from "node:fs";
import { createHash, randomUUID } from "node:crypto";
import { dirname, join, relative } from "node:path";
import { jaccardDistance, termSet } from "../memory-vector.js";
import { MAX_MEMORY_BYTES } from "../memory.js";
import { inlineUntrusted } from "../untrusted-text.js";
import { ambiguousOriginRepresentation, committedDistilledOf, committedOriginOf, computeEntryRev, distilledEquals, entryFromFile, isValidEntryId, originEquals, parseEntryFile, serializeEntryFile } from "./frontmatter.js";
import { convertV1SidecarKeys } from "./delegation-settlement.js";
import { layerObservationLookup, observedDivergenceNotice } from "./layer-observations.js";
import { DEFAULT_MAX_ENTRY_DEPTH, MEMORY_INDEX_FILENAME, scanEntryFiles } from "./entry-scan.js";
import { ControlPlaneCorruptError, CURSORS_FILE, QUARANTINE_DIR, CHALLENGES_FILE, IMPORT_RECEIPTS_DIR, LINEAGE_FILE, SESSION_POLLUTION_DIR, appendChallengeEvents, atomicWriteFileSync, quarantineAndTombstone, captureAndClearLineageForEntries, adoptRootScopeLayout, adoptCanonicalKeyedControlDir, deriveControlPlaneDir, ensureDirExists, enqueueMemoryAnnouncement, importLatchTxnId, importLineageCommitted, importSessionPollution, isContainedIn, permissionRemedyOf, withPermissionRemedy, lineageContributionsOfSession, listSessionPollution, readChallengeEvents, readLineageRecord, registerScope, registeredScopes, releaseImportLatch, layoutNeedsAdoption, resolveMemoryEngineRoot, scopeDirFor, scopeDirName, scopeRegistryShape, stageImportLatch, landingPathOf, storeTargetEscape, TARGET_OUTSIDE_STORE, writeAllSync, } from "./layout.js";
import { screenInboundEntries } from "./data-plane.js";
import { scanMemoryFileName, scanMemoryWrite } from "./scan.js";
import { thrownText } from "../thrown-value.js";
export { DEFAULT_MAX_ENTRY_DEPTH, MEMORY_INDEX_FILENAME, scanEntryFiles } from "./entry-scan.js";
export function canonicalJsonStringify(value) {
if (Array.isArray(value))
return `[${value.map((v) => (v === undefined || typeof v === "function" || typeof v === "symbol" ? "null" : canonicalJsonStringify(v))).join(",")}]`;
if (value !== null && typeof value === "object") {
const rec = value;
const keys = Object.keys(rec)
.filter((k) => rec[k] !== undefined)
.sort();
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalJsonStringify(rec[k])}`).join(",")}}`;
}
return JSON.stringify(value);
}
export function erasureSelectHash(select) {
return createHash("sha256").update(`${canonicalJsonStringify(select)}\n`, "utf8").digest("hex");
}
export function erasureRequestInvalid(input) {
if (!input || typeof input !== "object")
return "input is not an object";
if (typeof input.requestId !== "string" || input.requestId.length === 0)
return "requestId is required (idempotency identity — a retry must reuse it; the engine never mints one)";
const sel = input.select;
if (!sel || typeof sel !== "object" || Array.isArray(sel))
return "select is not an object";
const rec = sel;
const keys = Object.keys(rec);
const kind = keys[0];
if (keys.length !== 1 || (kind !== "ids" && kind !== "scope" && kind !== "sessionId"))
return "select must carry exactly one of ids/scope/sessionId";
if (kind === "ids") {
const list = Array.isArray(rec.ids) ? rec.ids : undefined;
if (list === undefined)
return "select.ids is not an array";
const seen = new Set();
for (const id of list) {
if (typeof id !== "string" || id.length === 0)
return "select.ids carries a non-string/empty id";
if (seen.has(id))
return "select.ids carries a duplicate id (the pinned set is a set — deduplicate before calling)";
seen.add(id);
}
}
else {
const v = rec[kind];
if (typeof v !== "string" || v.length === 0)
return `select.${kind} is not a non-empty string`;
}
if (input.allowUnevidenced !== undefined && typeof input.allowUnevidenced !== "boolean")
return "allowUnevidenced must be a boolean when present";
return undefined;
}
function erasureCodedError(message, code) {
const e = new Error(message);
e.code = code;
return e;
}
function cloneErasureSelect(select) {
if ("ids" in select)
return { ids: [...select.ids] };
if ("scope" in select)
return { scope: select.scope };
return { sessionId: select.sessionId };
}
export function captureErasureInput(input) {
if (!input || typeof input !== "object")
return input;
const requestId = input.requestId;
const allowUnevidenced = input.allowUnevidenced;
const rawSel = input.select;
let select;
if (rawSel && typeof rawSel === "object" && !Array.isArray(rawSel)) {
const s = rawSel;
const captured = {};
for (const k of Object.keys(s)) {
const v = s[k];
captured[k] = Array.isArray(v) ? [...v] : v;
}
select = captured;
}
else {
select = rawSel;
}
return { requestId, select, ...(allowUnevidenced !== undefined ? { allowUnevidenced } : {}) };
}
class AuditSnapshotContendedError extends Error {
}
class AuditObservationUnstableError extends Error {
}
const LEDGER_FILE = "revs.json";
const LEDGER_SCHEMA_VERSION = 2;
const LEDGER_V1_BACKUP_FILE = "revs.v1.json.bak";
const TRANSFERS_FILE = "transfers.jsonl";
const CHAIN_DEGRADED_FILE = "transfers.chain-degraded.json";
const JOURNAL_FILE = "journal.json";
const TXN_LOCK_STALE_MS = 30_000;
const TXN_LOCK_WAIT_MS = 15_000;
const TXN_LOCK_STEAL_GRACE_MS = 250;
const SHADOW_DIR = "shadow";
const STORE_IDENTITY_FILE = "store-identity.json";
function rowsRev(rows, id) {
return rows[id]?.rev;
}
function rowsBinding(rows, id) {
const row = rows[id];
if (row === undefined || typeof row.scope !== "string" || typeof row.slug !== "string")
return undefined;
return { scope: row.scope, slug: row.slug };
}
function rowsEntries(rows) {
return Object.entries(rows);
}
function deleteRow(rows, id) {
delete rows[id];
}
function hasUnboundRows(rows) {
return rowsEntries(rows).some(([id]) => rowsBinding(rows, id) === undefined);
}
const UNBOUND_DISCLOSURE_PREFIX = "memory ledger has ";
function unboundRowIds(rows) {
return rowsEntries(rows)
.filter(([id]) => rowsBinding(rows, id) === undefined)
.map(([id]) => id);
}
function bindingEquals(a, b) {
if (a === undefined || b === undefined)
return a === b;
return a.scope === b.scope && a.slug === b.slug;
}
function bindRowTracked(rows, id, next, transfers, channel) {
const old = rows[id];
const oldBinding = rowsBinding(rows, id);
const row = { ...(old ?? {}), rev: next.rev, scope: next.scope, slug: next.slug, at: next.at };
if (oldBinding !== undefined && !bindingEquals(oldBinding, { scope: next.scope, slug: next.slug })) {
row.prev = { scope: oldBinding.scope, slug: oldBinding.slug, at: next.at };
transfers.push({ ev: randomUUID(), channel, id, from: oldBinding, to: { scope: next.scope, slug: next.slug }, at: next.at });
}
else if (old !== undefined && oldBinding === undefined) {
transfers.push({ ev: randomUUID(), channel: "migration-bind", id, to: { scope: next.scope, slug: next.slug }, at: next.at });
}
rows[id] = row;
}
function cloneRows(rows) {
const out = Object.create(null);
for (const [id, row] of rowsEntries(rows))
out[id] = { ...row, ...(row.prev !== undefined ? { prev: { ...row.prev } } : {}) };
return out;
}
function ledgerEnvelope(rows, extras) {
return { v: LEDGER_SCHEMA_VERSION, ...(extras ?? {}), rows };
}
function slugEscapes(slug) {
if (slug.length === 0 || slug.startsWith("/") || slug.includes("\\"))
return true;
return slug.split("/").some((seg) => seg === "" || seg === "." || seg === "..");
}
function validateLedgerRowsV2(rowsRaw, path) {
if (!rowsRaw || typeof rowsRaw !== "object" || Array.isArray(rowsRaw)) {
throw new ControlPlaneCorruptError(`committed-rev ledger rows have the wrong shape: ${path}`);
}
const out = Object.create(null);
for (const [id, rowRaw] of Object.entries(rowsRaw)) {
if (!rowRaw || typeof rowRaw !== "object" || Array.isArray(rowRaw)) {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} has the wrong shape: ${path}`);
}
const row = rowRaw;
if (typeof row.rev !== "string") {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} has no string rev: ${path}`);
}
const hasScope = row.scope !== undefined;
const hasSlug = row.slug !== undefined;
if (hasScope !== hasSlug) {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} is half-bound (scope and slug must appear together): ${path}`);
}
if (hasScope && (typeof row.scope !== "string" || typeof row.slug !== "string")) {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} has a non-string binding: ${path}`);
}
if (typeof row.slug === "string" && slugEscapes(row.slug)) {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} has a path-escaping slug: ${path}`);
}
if (row.at !== undefined && (typeof row.at !== "number" || !Number.isInteger(row.at))) {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} has a non-integer 'at': ${path}`);
}
if (row.prev !== undefined) {
const prev = row.prev;
if (!prev || typeof prev !== "object" || Array.isArray(prev) || typeof prev.scope !== "string" || typeof prev.slug !== "string" || typeof prev.at !== "number" || !Number.isInteger(prev.at)) {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} has a malformed 'prev' trace: ${path}`);
}
if (slugEscapes(prev.slug)) {
throw new ControlPlaneCorruptError(`committed-rev ledger row ${JSON.stringify(id)} has a path-escaping 'prev' slug: ${path}`);
}
}
out[id] = { ...row };
}
return out;
}
function parseJournal(raw, jp) {
try {
const parsed = JSON.parse(raw);
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.ops))
throw new Error("wrong shape");
return parsed;
}
catch {
throw new ControlPlaneCorruptError(`transaction journal is unparseable: ${jp}`);
}
}
function journalLedgerSnapshot(journal, jp) {
const hasV2 = journal.ledger2 !== undefined;
const hasV1 = journal.ledger !== undefined;
if (hasV2 === hasV1) {
throw new ControlPlaneCorruptError(`transaction journal has ${hasV2 ? "both ledger snapshots" : "no ledger snapshot"} (wrong shape): ${jp}`);
}
if (hasV2) {
const env = journal.ledger2;
if (!env || typeof env !== "object" || Array.isArray(env) || env.v !== LEDGER_SCHEMA_VERSION) {
throw new ControlPlaneCorruptError(`transaction journal ledger2 snapshot has the wrong shape: ${jp}`);
}
const extras = {};
for (const [k, val] of Object.entries(env))
if (k !== "v" && k !== "rows")
extras[k] = val;
return { form: "v2", rows: validateLedgerRowsV2(env.rows, jp), extras };
}
const map = journal.ledger;
if (!map || typeof map !== "object" || Array.isArray(map))
throw new ControlPlaneCorruptError(`transaction journal ledger snapshot has the wrong shape: ${jp}`);
const rows = Object.create(null);
for (const [id, rev] of Object.entries(map)) {
if (typeof rev !== "string")
throw new ControlPlaneCorruptError(`transaction journal v1 ledger snapshot entry ${JSON.stringify(id)} is not a string: ${jp}`);
rows[id] = { rev };
}
return { form: "v1", rows };
}
function parseLedgerText(raw, path) {
let parsed;
try {
parsed = JSON.parse(raw);
}
catch {
throw new ControlPlaneCorruptError(`committed-rev ledger is unparseable: ${path}`);
}
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
throw new ControlPlaneCorruptError(`committed-rev ledger has the wrong shape: ${path}`);
}
const rec = parsed;
if ("v" in rec) {
const v = rec.v;
if (typeof v !== "number" || !Number.isInteger(v)) {
throw new ControlPlaneCorruptError(`committed-rev ledger schema version is not an integer: ${path}`);
}
if (v > LEDGER_SCHEMA_VERSION) {
throw new ControlPlaneCorruptError(`committed-rev ledger schema v${v} is newer than this engine supports (v${LEDGER_SCHEMA_VERSION}) — refusing to reinterpret it: ${path}`);
}
if (v !== LEDGER_SCHEMA_VERSION) {
throw new ControlPlaneCorruptError(`committed-rev ledger has an unknown enveloped schema v${v}: ${path}`);
}
const rows = validateLedgerRowsV2(rec.rows, path);
const envelopeExtras = {};
for (const [k, val] of Object.entries(rec)) {
if (k !== "v" && k !== "rows")
envelopeExtras[k] = val;
}
return { form: "v2", rows, envelopeExtras };
}
const rows = Object.create(null);
for (const [k, v] of Object.entries(rec)) {
if (typeof v !== "string") {
throw new ControlPlaneCorruptError(`committed-rev ledger entry ${JSON.stringify(k)} is not a string: ${path}`);
}
rows[k] = { rev: v };
}
return { form: "v1", rows };
}
const KNOWN_TRANSFER_CHANNELS = new Set(["adopted-move", "applyPatches-move", "migration-bind", "migration", "delete", "erasure-anchor", "erasure-request"]);
function transferEventInvalid(raw) {
if (!raw || typeof raw !== "object" || Array.isArray(raw))
return "event is not an object";
const e = raw;
if (typeof e.ev !== "string" || e.ev.length === 0)
return "missing event id 'ev'";
if (typeof e.at !== "number" || !Number.isInteger(e.at))
return "missing/non-integer 'at'";
const bindingInvalid = (b) => {
if (!b || typeof b !== "object" || Array.isArray(b))
return true;
const r = b;
if (typeof r.scope !== "string" || r.scope.length === 0)
return true;
return typeof r.slug !== "string" || slugEscapes(r.slug);
};
const idListInvalid = (v, what) => {
const list = Array.isArray(v) ? v : undefined;
if (list === undefined)
return `${what} is not an array`;
const seen = new Set();
for (const id of list) {
if (typeof id !== "string" || id.length === 0)
return `${what} carries a non-string/empty id`;
if (seen.has(id))
return `${what} carries a duplicate id`;
seen.add(id);
}
return undefined;
};
if ((e.origin !== undefined) !== (e.srcEv !== undefined))
return "'origin' and 'srcEv' must appear together (import rows carry both; local rows carry neither)";
if (e.origin !== undefined && (typeof e.origin !== "string" || e.origin.length === 0))
return "non-string/empty 'origin'";
if (e.srcEv !== undefined && (typeof e.srcEv !== "string" || e.srcEv.length === 0))
return "non-string/empty 'srcEv'";
const redactedKeys = new Set();
if (e.redacted !== undefined) {
const list = Array.isArray(e.redacted) ? e.redacted : undefined;
if (list === undefined || list.length === 0)
return "'redacted', when present, must be a non-empty array naming the removed keys";
for (const k of list) {
if (k !== "from" && k !== "to")
return "'redacted' may only name 'from'/'to'";
if (redactedKeys.has(k))
return "'redacted' names a key twice";
redactedKeys.add(k);
}
if (e.origin === undefined)
return "'redacted' requires the import pair (origin/srcEv) — a local row is never redacted";
}
if (e.channel === "migration") {
if (typeof e.boundRows !== "number" || !Number.isInteger(e.boundRows))
return "migration summary missing integer 'boundRows'";
if (typeof e.unboundRows !== "number" || !Number.isInteger(e.unboundRows))
return "migration summary missing integer 'unboundRows'";
if (e.id !== undefined || e.from !== undefined || e.to !== undefined)
return "migration summary must not carry id/from/to";
return undefined;
}
if (e.channel === "adopted-move" || e.channel === "applyPatches-move" || e.channel === "migration-bind") {
if (typeof e.id !== "string" || e.id.length === 0)
return "row transfer missing 'id'";
if (e.to !== undefined && redactedKeys.has("to"))
return "'to' is present but named in 'redacted'";
if (e.from !== undefined && redactedKeys.has("from"))
return "'from' is present but named in 'redacted'";
if (e.to === undefined) {
if (!redactedKeys.has("to"))
return "row transfer missing/malformed 'to'";
}
else if (bindingInvalid(e.to)) {
return "row transfer missing/malformed 'to'";
}
if (e.channel === "migration-bind") {
if (e.from !== undefined && bindingInvalid(e.from))
return "malformed 'from'";
}
else if (e.from === undefined) {
if (!redactedKeys.has("from"))
return `'${e.channel}' requires a well-formed 'from'`;
}
else if (bindingInvalid(e.from)) {
return `'${e.channel}' requires a well-formed 'from'`;
}
return undefined;
}
if (e.channel === "delete") {
if (typeof e.id !== "string" || e.id.length === 0)
return "delete event missing 'id'";
if (typeof e.rev !== "string" || e.rev.length === 0)
return "delete event missing 'rev'";
if (e.boundRows !== undefined || e.unboundRows !== undefined || e.to !== undefined || e.select !== undefined)
return "delete event must not carry boundRows/unboundRows/to/select";
if (e.from !== undefined && bindingInvalid(e.from))
return "delete event has a malformed 'from'";
if (e.req !== undefined && (typeof e.req !== "string" || e.req.length === 0))
return "delete event has a non-string/empty 'req'";
if (e.sessions !== undefined) {
const sessions = Array.isArray(e.sessions) ? e.sessions : undefined;
if (sessions === undefined || sessions.some((s) => typeof s !== "string"))
return "delete event has a malformed 'sessions'";
if (e.req === undefined)
return "delete event carries 'sessions' without 'req' (only the request leg captures lineage)";
}
if ((e.legacyId !== undefined) === isValidEntryId(e.id)) {
return e.legacyId !== undefined ? "legacyId claimed for a well-formed entry id (downgrade laundering refused)" : "delete event for a non-entry-id ledger key must declare legacyId";
}
if (e.legacyId !== undefined && e.legacyId !== true)
return "legacyId, when present, must be literal true";
if (e.legacyId !== undefined && e.from !== undefined)
return "legacyId and 'from' are mutually exclusive (a legacy row has no derivable projection)";
return undefined;
}
if (e.channel === "erasure-anchor") {
if (typeof e.req !== "string" || e.req.length === 0)
return "erasure anchor missing 'req'";
if (e.id !== undefined || e.from !== undefined || e.to !== undefined || e.scope !== undefined || e.boundRows !== undefined)
return "erasure anchor must not carry id/from/to/scope/boundRows";
const sel = e.select;
if (!sel || typeof sel !== "object" || Array.isArray(sel))
return "erasure anchor 'select' is not an object";
const selRec = sel;
const selKeys = Object.keys(selRec);
if (selKeys.length !== 1 || (selKeys[0] !== "ids" && selKeys[0] !== "scope" && selKeys[0] !== "sessionId"))
return "erasure anchor 'select' must carry exactly one of ids/scope/sessionId";
if (selKeys[0] === "ids") {
const bad = idListInvalid(selRec.ids, "'select.ids'");
if (bad !== undefined)
return bad;
}
else if (typeof selRec[selKeys[0]] !== "string" || selRec[selKeys[0]].length === 0) {
return `erasure anchor 'select.${selKeys[0]}' is not a non-empty string`;
}
if (e.selectHash !== erasureSelectHash(sel))
return "erasure anchor 'selectHash' does not equal the selector's canonical hash";
const idsBad = idListInvalid(e.ids, "erasure anchor 'ids'");
if (idsBad !== undefined)
return idsBad;
const nfBad = idListInvalid(e.notFound, "erasure anchor 'notFound'");
if (nfBad !== undefined)
return nfBad;
const pinned = new Set(e.ids);
for (const id of e.notFound) {
if (!pinned.has(id))
return "erasure anchor 'notFound' is not a subset of 'ids'";
}
if (selKeys[0] === "ids") {
const selIds = selRec.ids;
const anchorIds = e.ids;
if (selIds.length !== anchorIds.length || selIds.some((id, i) => anchorIds[i] !== id)) {
return "erasure anchor 'ids' does not equal the ids-selector's verbatim id list (a pinned set the selector never named)";
}
}
return undefined;
}
if (e.channel === "erasure-request") {
if (typeof e.req !== "string" || e.req.length === 0)
return "erasure request row missing 'req'";
if (e.id !== undefined || e.from !== undefined || e.to !== undefined || e.select !== undefined || e.notFound !== undefined)
return "erasure request row must not carry id/from/to/select/notFound";
if (typeof e.scope !== "string" || e.scope.length === 0)
return "erasure request row missing 'scope'";
if (typeof e.selectHash !== "string" || !/^[0-9a-f]{64}$/.test(e.selectHash))
return "erasure request row 'selectHash' is not a sha256 hex";
const idsBad = idListInvalid(e.ids, "erasure request row 'ids'");
if (idsBad !== undefined)
return idsBad;
if (e.ids.length === 0)
return "erasure request row carries an empty 'ids' (a projection row exists only for a scope with bound ids)";
return undefined;
}
return `unknown channel ${JSON.stringify(e.channel)}`;
}
function readControlFileOrAbsent(path, what) {
try {
return readFileSync(path, "utf8");
}
catch (err) {
const code = err.code;
if (code === "ENOENT")
return undefined;
throw new ControlPlaneCorruptError(`${what} could not be read (${code ?? "io error"}) at ${path} — a read failure is not absence (fail-closed); fix the filesystem fault and retry`);
}
}
function journalOpInvalid(raw, directoryRoot) {
if (!raw || typeof raw !== "object" || Array.isArray(raw))
return "op is not an object";
const op = raw;
if (typeof op.target !== "string" || op.target.length === 0)
return "missing string target";
if (op.staged !== undefined && typeof op.staged !== "string")
return "non-string staged";
switch (op.kind) {
case "write":
if (typeof op.content !== "string")
return "write op without full content";
if (!isContainedIn(directoryRoot, op.target))
return "write target escapes the store root";
return undefined;
case "delete":
if (op.content !== undefined)
return "delete op must not carry content";
if (!isContainedIn(directoryRoot, op.target))
return "delete target escapes the store root";
return undefined;
case "shadow-write":
if (typeof op.content !== "string")
return "shadow-write op without full content";
if (!isValidEntryId(op.target))
return "shadow target is not an entry id";
return undefined;
case "shadow-delete":
if (op.content !== undefined)
return "shadow-delete op must not carry content";
if (!isValidEntryId(op.target))
return "shadow target is not an entry id";
return undefined;
default:
return "unknown op kind";
}
}
function probeProjection(absPath, id) {
let text;
try {
text = readFileSync(absPath, "utf8");
}
catch (err) {
return err.code === "ENOENT" ? "absent" : "undecidable";
}
return parseEntryFile(text).id === id ? "present" : "undecidable";
}
export class FileMemoryEngineBackend {
directoryRoot;
controlPlaneRoot;
physicalRoot;
now;
onIncident;
ledger;
envelopeExtras;
persistedSchemaVersion;
announcedV1Compat = false;
unboundRowsKnown = false;
adoptionNoticeKeys = new Set();
transfersAppendFault;
recoveryCommitProbe;
chainHealProbe;
exportFaceProbe;
deletedIdsDigest;
inboundFindings = [];
batchScan;
constructor(dir, opts = {}) {
this.now = opts.now ?? Date.now;
this.onIncident = opts.onIncident;
this.directoryRoot = dir;
if (opts.controlDir === undefined)
adoptCanonicalKeyedControlDir(resolveMemoryEngineRoot(), dir, opts.onIncident);
this.controlPlaneRoot = opts.controlDir ?? deriveControlPlaneDir(resolveMemoryEngineRoot(), dir);
ensureDirExists(dir);
this.physicalRoot = landingPathOf(dir);
ensureDirExists(this.controlPlaneRoot);
this.recoverJournal({ unlocked: true });
try {
this.loadLedger();
}
catch {
}
if (this.persistedSchemaVersion === "v1" || (this.ledger !== undefined && hasUnboundRows(this.ledger))) {
let layoutDerivesPaths = false;
try {
const shape = scopeRegistryShape(this.controlPlaneRoot);
layoutDerivesPaths = shape !== "v1" && shape !== "migrating";
}
catch {
}
if (layoutDerivesPaths)
this.tryOpportunisticMigrate();
}
}
adoptLayoutLocked(lockToken, ownerCandidate, onIncident) {
adoptRootScopeLayout(this.directoryRoot, this.controlPlaneRoot, {
ownerCandidate,
onIncident: onIncident ?? this.onIncident,
convertSidecars: convertV1SidecarKeys,
renew: () => {
const now = new Date();
utimesSync(this.txnLockDir(), now, now);
this.assertTxnLockOwnership(lockToken);
},
});
}
ensureLayout(ownerCandidate) {
this.assertRootIntact();
if (!layoutNeedsAdoption(this.directoryRoot, this.controlPlaneRoot))
return;
const lock = this.tryAcquireTxnLockSync();
if (lock === undefined)
return;
try {
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token, ownerCandidate);
}
finally {
lock.release();
}
}
async adoptRootScopeLayout(opts = {}) {
this.assertRootIntact();
if (!layoutNeedsAdoption(this.directoryRoot, this.controlPlaneRoot))
return;
const lock = await this.acquireTxnLock();
try {
this.assertTxnLockOwnership(lock.token);
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token, opts.ownerCandidate, opts.onIncident);
}
finally {
lock.release();
}
}
checkControlPlane() {
this.recoverJournal({ unlocked: true });
this.ensureLayout();
this.ledger = undefined;
this.loadLedger();
registeredScopes(this.controlPlaneRoot);
if (this.persistedSchemaVersion === "v1" || hasUnboundRows(this.loadLedger()))
this.tryOpportunisticMigrate();
if (this.persistedSchemaVersion === "v2")
this.announceUnboundRows(this.loadLedger());
}
drainInboundFindings() {
const out = this.inboundFindings;
this.inboundFindings = [];
return out;
}
readCommittedShadow(id) {
return readSafe(this.shadowPath(id));
}
shadowPath(id) {
return join(this.controlPlaneRoot, SHADOW_DIR, `${id}.md`);
}
loadLedger() {
if (this.ledger)
return this.ledger;
const path = join(this.controlPlaneRoot, LEDGER_FILE);
const raw = readControlFileOrAbsent(path, "committed-rev ledger");
if (raw === undefined) {
this.ledger = Object.create(null);
this.persistedSchemaVersion = "v2";
this.unboundRowsKnown = false;
return this.ledger;
}
const parsed = parseLedgerText(raw, path);
this.ledger = parsed.rows;
this.envelopeExtras = parsed.envelopeExtras;
this.persistedSchemaVersion = parsed.form;
this.unboundRowsKnown = hasUnboundRows(parsed.rows);
if (parsed.form === "v1" && !this.announcedV1Compat) {
this.announcedV1Compat = true;
this.enqueueExternalItems(["memory ledger v1-compat active — v2 binding guarantees not yet in force (the migration runs at the next uncontended entry)"]);
}
return this.ledger;
}
saveLedger() {
if (!this.ledger)
return;
if (this.persistedSchemaVersion !== "v2") {
throw new ControlPlaneCorruptError("committed-rev ledger write refused: the on-disk ledger is still schema v1 and the migration has not run (mutations must migrate first)");
}
atomicWriteFileSync(join(this.controlPlaneRoot, LEDGER_FILE), `${JSON.stringify(ledgerEnvelope(this.ledger, this.envelopeExtras), null, 2)}\n`);
this.unboundRowsKnown = hasUnboundRows(this.ledger);
}
persistLedgerV1(rows) {
const map = Object.create(null);
for (const [id, row] of rowsEntries(rows))
map[id] = row.rev;
atomicWriteFileSync(join(this.controlPlaneRoot, LEDGER_FILE), `${JSON.stringify(map, null, 2)}\n`);
this.unboundRowsKnown = Object.keys(map).length > 0;
}
enqueueExternalItems(items) {
if (items.length === 0)
return;
try {
enqueueMemoryAnnouncement(this.controlPlaneRoot, { kind: "external", at: this.now(), items });
}
catch {
}
}
announceAdoptionNotice(key, item) {
if (this.adoptionNoticeKeys.has(key))
return;
this.adoptionNoticeKeys.add(key);
this.enqueueExternalItems([item]);
}
announceUnboundRows(rows) {
const ids = unboundRowIds(rows);
const item = ids.length === 0 ? undefined : `${UNBOUND_DISCLOSURE_PREFIX}${ids.length} unbound row(s) (no derivable committed projection): ${ids.slice(0, 8).join(", ")}${ids.length > 8 ? ", …" : ""} — v2 binding guarantees do not cover them until they converge (duplicate projections need an unrestricted harvest or manual removal)`;
try {
enqueueMemoryAnnouncement(this.controlPlaneRoot, { kind: "external", at: this.now(), items: item === undefined ? [] : [item] }, { supersedesPrefix: UNBOUND_DISCLOSURE_PREFIX });
}
catch {
}
}
bindingAbsPath(binding) {
return join(scopeDirFor(this.directoryRoot, this.controlPlaneRoot, binding.scope), `${binding.slug}.md`);
}
bindingRelPath(binding) {
return relative(this.directoryRoot, this.bindingAbsPath(binding));
}
censusProjectionsLocked() {
let complete = true;
const byId = new Map();
for (const scope of Object.keys(registeredScopes(this.controlPlaneRoot))) {
const dir = this.scopeDir(scope);
const walk = (d, depth) => {
let names;
try {
names = readdirSync(d);
}
catch (err) {
if (err.code === "ENOENT" && depth === 0)
return;
complete = false;
return;
}
for (const name of names.sort()) {
if (name.startsWith(".") || name === MEMORY_INDEX_FILENAME)
continue;
const p = join(d, name);
let st;
try {
st = lstatSync(p);
}
catch {
complete = false;
continue;
}
if (st.isSymbolicLink())
continue;
if (st.isDirectory()) {
if (depth + 1 <= DEFAULT_MAX_ENTRY_DEPTH)
walk(p, depth + 1);
continue;
}
if (!st.isFile() || !name.endsWith(".md"))
continue;
let text;
try {
text = readFileSync(p, "utf8");
}
catch {
complete = false;
continue;
}
const id = parseEntryFile(text).id;
if (id === undefined)
continue;
const list = byId.get(id) ?? [];
list.push({ scope, slug: relative(dir, p).replace(/\.md$/, "") });
byId.set(id, list);
}
};
walk(dir, 0);
}
return { complete, byId };
}
writeV1BackupOnce() {
const raw = readControlFileOrAbsent(join(this.controlPlaneRoot, LEDGER_FILE), "committed-rev ledger");
if (raw === undefined)
throw new ControlPlaneCorruptError(`committed-rev ledger vanished under the migration lock: ${join(this.controlPlaneRoot, LEDGER_FILE)}`);
const bak = join(this.controlPlaneRoot, LEDGER_V1_BACKUP_FILE);
let fd;
try {
fd = openSync(bak, "wx", 0o600);
}
catch (err) {
if (err.code === "EEXIST")
return;
throw err;
}
try {
writeAllSync(fd, raw);
fsyncSync(fd);
}
finally {
closeSync(fd);
}
}
tryAcquireTxnLockSync() {
const lockDir = this.txnLockDir();
const ownerPath = join(lockDir, "owner");
const tryMkdir = () => {
try {
mkdirSync(this.controlPlaneRoot, { recursive: true });
}
catch (err) {
throw new ControlPlaneCorruptError(`memory control-plane root could not be created (${err.code ?? "io error"}) at ${this.controlPlaneRoot} — a lock-acquisition fault is not contention; deferring recovery/migration on it would be silent (fail-closed)`, { cause: err });
}
try {
mkdirSync(lockDir);
return true;
}
catch (err) {
if (err.code === "EEXIST")
return false;
throw new ControlPlaneCorruptError(`memory txn lock could not be created (${err.code ?? "io error"}) at ${lockDir} — a lock-acquisition fault is not contention; deferring recovery/migration on it would be silent (fail-closed)`, { cause: err });
}
};
let acquired = tryMkdir();
if (!acquired) {
let mtimeMs;
try {
mtimeMs = statSync(lockDir).mtimeMs;
}
catch (err) {
if (err.code !== "ENOENT") {
throw new ControlPlaneCorruptError(`memory txn lock state could not be probed (${err.code ?? "io error"}) at ${lockDir} — a probe failure is not contention (fail-closed)`, { cause: err });
}
let occupant;
try {
occupant = lstatSync(lockDir);
}
catch (lerr) {
if (lerr.code !== "ENOENT") {
throw new ControlPlaneCorruptError(`memory txn lock re-probe failed (${lerr.code ?? "io error"}) at ${lockDir} — a probe failure is not contention (fail-closed)`, { cause: lerr });
}
}
if (occupant !== undefined && !occupant.isDirectory()) {
throw new ControlPlaneCorruptError(`memory txn lock path is occupied by an invalid node (a dangling symlink?) at ${lockDir} — not contention and not a release race; remove the occupant (fail-closed)`, { cause: err });
}
mtimeMs = undefined;
}
if (mtimeMs !== undefined && this.now() - mtimeMs > TXN_LOCK_STALE_MS) {
let tokenPresent = false;
try {
statSync(ownerPath);
tokenPresent = true;
}
catch (err) {
if (err.code !== "ENOENT") {
throw new ControlPlaneCorruptError(`memory txn lock owner token could not be probed (${err.code ?? "io error"}) at ${ownerPath} — a probe failure is not a mid-acquisition (fail-closed)`, { cause: err });
}
}
if (tokenPresent) {
const tomb = join(this.controlPlaneRoot, `txn.lock.stale-${randomUUID()}`);
let stolen = false;
try {
renameSync(lockDir, tomb);
stolen = true;
}
catch (err) {
if (err.code !== "ENOENT") {
throw new ControlPlaneCorruptError(`memory txn lock stale-steal rename failed (${err.code ?? "io error"}) at ${lockDir} — a rename fault is not a lost race (fail-closed)`, { cause: err });
}
}
if (stolen) {
rmSync(tomb, { recursive: true, force: true });
acquired = tryMkdir();
}
}
}
if (!acquired)
return undefined;
}
const token = randomUUID();
try {
const fd = openSync(ownerPath, "w", 0o600);
try {
writeAllSync(fd, token);
fsyncSync(fd);
}
finally {
closeSync(fd);
}
}
catch (err) {
try {
rmSync(lockDir, { recursive: true, force: true });
}
catch {
}
throw new Error(`memory txn lock owner token could not be written at ${ownerPath}: ${thrownText(err)}`);
}
return {
token,
release: () => {
try {
if (readFileSync(ownerPath, "utf8") !== token)
return;
}
catch {
return;
}
try {
rmSync(lockDir, { recursive: true, force: true });
}
catch {
}
},
};
}
tryOpportunisticMigrate() {
const lock = this.tryAcquireTxnLockSync();
if (lock === undefined)
return;
try {
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token);
this.migrateLockedIfNeeded(lock.token);
}
finally {
lock.release();
}
}
migrateLockedIfNeeded(lockToken) {
this.ledger = undefined;
const rows = this.loadLedger();
if (this.persistedSchemaVersion === "v2" && !hasUnboundRows(rows))
return;
const fullMigration = this.persistedSchemaVersion === "v1";
const census = this.censusProjectionsLocked();
if (!census.complete) {
this.announceAdoptionNotice("migration-incomplete", `memory ledger ${fullMigration ? "v1→v2 migration" : "unbound-row convergence"} abandoned this pass — the projection census could not read every scope (bindings derived from a partial view could be wrong); it retries at the next entry`);
return;
}
const now = this.now();
const next = Object.create(null);
const bound = [];
const unbound = [];
const events = [];
for (const [id, row] of rowsEntries(rows)) {
if (!fullMigration && rowsBinding(rows, id) !== undefined) {
next[id] = { ...row };
continue;
}
const projections = census.byId.get(id) ?? [];
const sole = projections[0];
if (projections.length === 1 && sole !== undefined) {
next[id] = { ...row, scope: sole.scope, slug: sole.slug };
bound.push(id);
if (!fullMigration)
events.push({ ev: randomUUID(), channel: "migration-bind", id, to: sole, at: now });
}
else {
next[id] = { ...row };
unbound.push(`${id} (${projections.length} projection(s))`);
}
}
if (fullMigration) {
this.writeV1BackupOnce();
events.push({ ev: randomUUID(), channel: "migration", boundRows: bound.length, unboundRows: unbound.length, at: now });
}
else if (bound.length === 0) {
return;
}
this.assertTxnLockOwnership(lockToken);
this.precheckTransfersAppendable();
const journal = { txn: `${Date.now()}-migrate`, ops: [], ledger2: ledgerEnvelope(next, this.envelopeExtras), transfers: events };
atomicWriteFileSync(join(this.controlPlaneRoot, JOURNAL_FILE), JSON.stringify(journal));
this.ledger = next;
this.persistedSchemaVersion = "v2";
this.saveLedger();
this.appendTransfers(events);
rmSync(join(this.controlPlaneRoot, JOURNAL_FILE), { force: true });
this.enqueueExternalItems([
fullMigration
? `memory ledger upgraded to v2 (${bound.length} row(s) bound, ${unbound.length} unbound${unbound.length > 0 ? `: ${unbound.slice(0, 8).join(", ")}${unbound.length > 8 ? ", …" : ""}` : ""})`
: `memory ledger unbound row(s) converged to bound: ${bound.slice(0, 8).join(", ")}${bound.length > 8 ? ", …" : ""}`,
]);
}
chainDegradedMarkerPresent() {
return readControlFileOrAbsent(join(this.controlPlaneRoot, CHAIN_DEGRADED_FILE), "evidence-chain degradation marker") !== undefined;
}
mintChainDegradedMarker(fragmentPath) {
const path = join(this.controlPlaneRoot, CHAIN_DEGRADED_FILE);
let fd;
try {
fd = openSync(path, "wx", 0o600);
}
catch (err) {
if (err.code === "EEXIST") {
this.fsyncControlPlaneDir();
return;
}
throw new ControlPlaneCorruptError(`evidence-chain degradation marker could not be created at ${path} (${err.code ?? "io error"}) — heal aborted, the chain is unchanged (fail-closed)`);
}
try {
writeAllSync(fd, `${JSON.stringify({ at: this.now(), ...(fragmentPath !== undefined ? { fragment: fragmentPath } : {}) }, null, 2)}\n`);
fsyncSync(fd);
}
finally {
closeSync(fd);
}
this.fsyncControlPlaneDir();
if (readControlFileOrAbsent(path, "evidence-chain degradation marker") === undefined) {
throw new ControlPlaneCorruptError(`evidence-chain degradation marker vanished after its write at ${path} — heal aborted, the chain is unchanged (fail-closed)`);
}
}
fsyncControlPlaneDir() {
if (process.platform === "win32")
return;
let dfd;
try {
dfd = openSync(this.controlPlaneRoot, "r");
}
catch (err) {
throw new ControlPlaneCorruptError(`evidence-chain degradation marker's directory could not be opened for fsync (${err.code ?? "io error"}) at ${this.controlPlaneRoot} — heal aborted, the chain is unchanged (fail-closed: an unproven marker must not authorize a truncation)`, { cause: err });
}
try {
fsyncSync(dfd);
}
catch (err) {
throw new ControlPlaneCorruptError(`evidence-chain degradation marker's directory entry could not be fsynced (${err.code ?? "io error"}) at ${this.controlPlaneRoot} — heal aborted, the chain is unchanged (fail-closed: an unproven marker must not authorize a truncation)`, { cause: err });
}
finally {
closeSync(dfd);
}
}
readTransferChain(fenceToken) {
const path = join(this.controlPlaneRoot, TRANSFERS_FILE);
const raw = readControlFileOrAbsent(path, "transfer evidence log");
const out = [];
if (raw === undefined)
return out;
const byEv = new Map();
const lines = raw.split("\n");
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line === undefined || line === "")
continue;
let parsed;
try {
parsed = JSON.parse(line);
}
catch {
const isTail = lines.slice(i + 1).every((l) => l === "");
if (!isTail)
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is unparseable (not a torn tail — fail-closed): ${path}`);
let journalHasPendingEvidence = false;
const jraw = readControlFileOrAbsent(join(this.controlPlaneRoot, JOURNAL_FILE), "transaction journal");
if (jraw !== undefined) {
try {
const jparsed = JSON.parse(jraw);
const jt = typeof jparsed === "object" && jparsed !== null ? jparsed.transfers : undefined;
journalHasPendingEvidence = Array.isArray(jt) && jt.length > 0;
}
catch {
journalHasPendingEvidence = false;
}
}
const outOfBand = !journalHasPendingEvidence;
if (fenceToken !== undefined)
this.assertTxnLockOwnership(fenceToken);
let fragmentPath;
try {
ensureDirExists(join(this.controlPlaneRoot, QUARANTINE_DIR));
fragmentPath = join(this.controlPlaneRoot, QUARANTINE_DIR, `transfers-torn-tail-${this.now()}.fragment`);
atomicWriteFileSync(fragmentPath, line);
}
catch {
throw new ControlPlaneCorruptError(`transfer evidence log has a torn tail that could not be quarantined: ${path}`);
}
if (outOfBand)
this.mintChainDegradedMarker(fragmentPath);
this.chainHealProbe?.();
if (fenceToken !== undefined)
this.assertTxnLockOwnership(fenceToken);
try {
atomicWriteFileSync(path, lines.slice(0, i).join("\n") + (i > 0 ? "\n" : ""));
}
catch {
throw new ControlPlaneCorruptError(`transfer evidence log has a torn tail that could not be healed (truncation failed): ${path}`);
}
this.enqueueExternalItems([
outOfBand
? `transfer evidence log had a torn tail with NO transaction journal beside it (out-of-band damage) — the fragment is quarantined, the sound prefix stands, and the chain is durably marked degraded: new id-bearing files are refused adoption until an explicit rebuild clears ${CHAIN_DEGRADED_FILE}`
: `transfer evidence log had a torn tail (crash mid-append) — the fragment is quarantined and the sound prefix stands: ${TRANSFERS_FILE}`,
]);
break;
}
const invalid = transferEventInvalid(parsed);
if (invalid !== undefined)
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is invalid (${invalid}): ${path}`);
const rec = parsed;
const ev = rec.ev;
const canonical = canonicalJsonStringify(rec);
const prior = byEv.get(ev);
if (prior !== undefined) {
if (prior !== canonical) {
throw new ControlPlaneCorruptError(`transfer evidence log carries event id ${JSON.stringify(ev)} twice with DIFFERENT payloads (line ${i + 1}) — one ev is one identity; refusing to pick a side (fail-closed): ${path}`);
}
continue;
}
byEv.set(ev, canonical);
out.push({ ev, canonical, parsed: rec });
}
return out;
}
readTransferEvents() {
const out = new Map();
for (const row of this.readTransferChain())
out.set(row.ev, row.canonical);
return out;
}
deletedIdsDigestLocked() {
const path = join(this.controlPlaneRoot, TRANSFERS_FILE);
let fp;
try {
const st = statSync(path);
fp = `${st.size}:${st.mtimeMs}`;
}
catch (err) {
if (err.code === "ENOENT")
return { state: "complete", ids: new Set() };
throw new ControlPlaneCorruptError(`transfer evidence log could not be probed (${err.code ?? "io error"}) at ${path} — a probe failure is not an empty chain (fail-closed)`);
}
const cached = this.deletedIdsDigest;
if (cached !== undefined && cached.fp === fp)
return { state: cached.state, ids: cached.ids };
const raw = readControlFileOrAbsent(path, "transfer evidence log");
if (raw === undefined)
return { state: "complete", ids: new Set() };
let state = "complete";
const ids = new Set();
const lines = raw.split("\n");
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line === undefined || line === "")
continue;
let parsed;
try {
parsed = JSON.parse(line);
}
catch {
if (lines.slice(i + 1).every((l) => l === "")) {
state = "damaged";
break;
}
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is unparseable (not a torn tail — fail-closed): ${path}`);
}
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is not an object (fail-closed): ${path}`);
}
const e = parsed;
if (KNOWN_TRANSFER_CHANNELS.has(e.channel)) {
const invalid = transferEventInvalid(parsed);
if (invalid !== undefined)
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is invalid (${invalid}): ${path}`);
if (e.channel === "delete")
ids.add(e.id);
}
}
this.deletedIdsDigest = { fp, state, ids };
return { state, ids };
}
resurrectionBackstopVerdict(id) {
const digest = this.deletedIdsDigestLocked();
if (digest.ids.has(id))
return "erased";
if (digest.state === "damaged" || this.chainDegradedMarkerPresent())
return "degraded";
return "clear";
}
retrievalDeletedIds() {
return this.deletedIdsDigestLocked().ids;
}
freshCommittedRowsPure() {
try {
const raw = readControlFileOrAbsent(join(this.controlPlaneRoot, LEDGER_FILE), "committed-rev ledger");
if (raw === undefined)
return Object.create(null);
const parsed = parseLedgerText(raw, join(this.controlPlaneRoot, LEDGER_FILE));
return parsed.form === "v2" ? parsed.rows : Object.create(null);
}
catch (err) {
const code = err.code ?? (err instanceof ControlPlaneCorruptError ? "corrupt" : "io error");
this.announceAdoptionNotice(`retrieval-ledger-fault|${code}`, `memory retrieval guard: the committed-rev ledger could not be read on the lock-free retrieval face (${thrownText(err)}) — ` +
`ids carrying delete evidence are WITHHELD from retrieval (a legitimate re-add cannot be verified over an unreadable account) until the fault clears; ` +
`entries with no delete evidence serve normally`);
return Object.create(null);
}
}
precheckTransfersAppendable() {
this.readTransferEvents();
const fd = openSync(join(this.controlPlaneRoot, TRANSFERS_FILE), "a", 0o600);
closeSync(fd);
}
appendTransfers(events) {
if (events.length === 0)
return;
this.transfersAppendFault?.();
const existing = this.readTransferEvents();
const batch = new Map();
const toWrite = [];
for (const e of events) {
const canonical = canonicalJsonStringify(e);
const inBatch = batch.get(e.ev);
if (inBatch !== undefined) {
if (inBatch !== canonical) {
throw new ControlPlaneCorruptError(`transfer evidence batch mints event id ${JSON.stringify(e.ev)} twice with DIFFERENT payloads — one ev is one identity (minting bug, fail-closed)`);
}
continue;
}
batch.set(e.ev, canonical);
const onChain = existing.get(e.ev);
if (onChain !== undefined) {
if (onChain !== canonical) {
throw new ControlPlaneCorruptError(`transfer evidence append collides on event id ${JSON.stringify(e.ev)}: the chain already carries a DIFFERENT payload under it — one ev is one identity (fail-closed)`);
}
continue;
}
toWrite.push(canonical);
}
if (toWrite.length === 0)
return;
const raw = readControlFileOrAbsent(join(this.controlPlaneRoot, TRANSFERS_FILE), "transfer evidence log");
const needsSeparator = raw !== undefined && raw.length > 0 && !raw.endsWith("\n");
const fd = openSync(join(this.controlPlaneRoot, TRANSFERS_FILE), "a", 0o600);
try {
writeAllSync(fd, (needsSeparator ? "\n" : "") + toWrite.map((c) => `${c}\n`).join(""));
fsyncSync(fd);
}
finally {
closeSync(fd);
}
}
recoverJournal(fence) {
this.assertRootIntact();
if (fence.token === undefined) {
if (this.txnInFlight())
return;
const lock = this.tryAcquireTxnLockSync();
if (lock === undefined)
return;
try {
this.recoverJournal({ token: lock.token });
}
finally {
lock.release();
}
return;
}
const fenceToken = fence.token;
const jp = join(this.controlPlaneRoot, JOURNAL_FILE);
const raw = readControlFileOrAbsent(jp, "transaction journal");
if (raw !== undefined) {
const journal = parseJournal(raw, jp);
const { rows: snapshotRows, extras: snapshotExtras, form: snapshotForm } = journalLedgerSnapshot(journal, jp);
if (snapshotForm === "v1") {
try {
const diskRaw = readControlFileOrAbsent(join(this.controlPlaneRoot, LEDGER_FILE), "committed-rev ledger");
const diskParsed = diskRaw !== undefined ? JSON.parse(diskRaw) : undefined;
if (diskParsed !== null && typeof diskParsed === "object" && "v" in diskParsed && diskParsed.v === LEDGER_SCHEMA_VERSION) {
this.enqueueExternalItems([
"memory ledger: recovering a v1-format journal over a v2 ledger — a pre-v2 process wrote AFTER this store migrated (mixed-version deployment window). Retire old readers/writers before further writes; see the v2 rollback runbook.",
]);
}
}
catch {
}
}
for (const op of journal.ops) {
const invalid = journalOpInvalid(op, this.directoryRoot);
if (invalid !== undefined) {
throw new ControlPlaneCorruptError(`transaction journal op is invalid (${invalid}; kind=${JSON.stringify(op.kind)} target=${JSON.stringify(op.target)}) — the whole journal is refused and kept at ${jp} (control data is malformed: repair via the explicit control-plane rebuild path, not a replay guess)`);
}
}
if (journal.transfers !== undefined) {
if (!Array.isArray(journal.transfers))
throw new ControlPlaneCorruptError(`transaction journal transfers is not an array: ${jp}`);
const journalEvs = new Map();
for (const e of journal.transfers) {
const invalid = transferEventInvalid(e);
if (invalid !== undefined)
throw new ControlPlaneCorruptError(`transaction journal transfer event is invalid (${invalid}): ${jp}`);
if (e.origin !== undefined) {
throw new ControlPlaneCorruptError(`transaction journal carries an origin-bearing (imported) transfer event — imports never ride a journal: ${jp}`);
}
const canonical = canonicalJsonStringify(e);
const prior = journalEvs.get(e.ev);
if (prior !== undefined && prior !== canonical) {
throw new ControlPlaneCorruptError(`transaction journal mints event id ${JSON.stringify(e.ev)} twice with DIFFERENT payloads (fail-closed before redo): ${jp}`);
}
journalEvs.set(e.ev, canonical);
}
if (snapshotForm === "v1")
throw new ControlPlaneCorruptError(`transaction journal carries transfers with a v1 snapshot (impossible form): ${jp}`);
if (journalEvs.size > 0) {
for (const row of this.readTransferChain(fenceToken)) {
const j = journalEvs.get(row.ev);
if (j !== undefined && j !== row.canonical) {
throw new ControlPlaneCorruptError(`transaction journal event id ${JSON.stringify(row.ev)} collides with a DIFFERENT payload already on the evidence chain (fail-closed before redo): ${jp}`);
}
}
}
const transfers = journal.transfers;
const rowPresent = (id) => Object.prototype.hasOwnProperty.call(snapshotRows, id);
const deleteRows = transfers.filter((t) => t.channel === "delete");
const anchorRows = transfers.filter((t) => t.channel === "erasure-anchor");
const requestRows = transfers.filter((t) => t.channel === "erasure-request");
let chainAnchors;
for (const e of transfers) {
if (e.channel === "adopted-move" || e.channel === "applyPatches-move" || e.channel === "migration-bind") {
if (!bindingEquals(rowsBinding(snapshotRows, e.id), e.to)) {
throw new ControlPlaneCorruptError(`transaction journal transfer event for ${JSON.stringify(e.id)} disagrees with the snapshot binding: ${jp}`);
}
continue;
}
if (e.channel !== "delete")
continue;
if (rowPresent(e.id)) {
throw new ControlPlaneCorruptError(`transaction journal delete evidence for ${JSON.stringify(e.id)} disagrees with its snapshot (the row survives) — a delete claim over a surviving row is refused: ${jp}`);
}
if (e.legacyId !== true) {
if (!journal.ops.some((op) => op.kind === "shadow-delete" && op.target === e.id)) {
throw new ControlPlaneCorruptError(`transaction journal delete evidence for ${JSON.stringify(e.id)} has no same-journal shadow-delete op (uncorrelated delete claim, fail-closed): ${jp}`);
}
if (e.from !== undefined) {
const derived = this.bindingAbsPath(e.from);
if (!journal.ops.some((op) => op.kind === "delete" && op.target === derived)) {
throw new ControlPlaneCorruptError(`transaction journal delete evidence for ${JSON.stringify(e.id)} has no same-journal physical delete op at its bound projection path (an account-only delete would leave the disk copy to resurrect, fail-closed): ${jp}`);
}
}
}
if (e.req !== undefined && !anchorRows.some((a) => a.req === e.req)) {
chainAnchors ??= this.readTransferChain(fenceToken)
.map((r) => r.parsed)
.filter((p) => p.channel === "erasure-anchor" && p.origin === undefined);
const matching = chainAnchors.filter((p) => p.req === e.req);
const pinned = matching.length === 1 ? matching[0]?.ids : undefined;
if (pinned === undefined || !pinned.includes(e.id)) {
throw new ControlPlaneCorruptError(`transaction journal carries a request-driven delete for ${JSON.stringify(e.id)} (req ${JSON.stringify(e.req)}) with no same-journal anchor and no matching single chain anchor pinning the id — an unanchored erasure claim is refused: ${jp}`);
}
}
}
const chainAnchorEvsByReq = new Map();
if (anchorRows.length > 0) {
for (const p of (chainAnchors ??= this.readTransferChain(fenceToken)
.map((r) => r.parsed)
.filter((p) => p.channel === "erasure-anchor" && p.origin === undefined))) {
const set = chainAnchorEvsByReq.get(p.req) ?? new Set();
set.add(p.ev);
chainAnchorEvsByReq.set(p.req, set);
}
}
const anchorReqs = new Set();
for (const a of anchorRows) {
if (anchorReqs.has(a.req))
throw new ControlPlaneCorruptError(`transaction journal carries two erasure anchors for req ${JSON.stringify(a.req)} (one request, one anchor): ${jp}`);
const chainEvs = chainAnchorEvsByReq.get(a.req);
if (chainEvs !== undefined && [...chainEvs].some((ev) => ev !== a.ev)) {
throw new ControlPlaneCorruptError(`transaction journal mints an erasure anchor for req ${JSON.stringify(a.req)} under a DIFFERENT ev than the one already on the evidence chain (one request, one anchor — spliced journal refused): ${jp}`);
}
anchorReqs.add(a.req);
const pinned = new Set(a.ids);
const reqDeletes = deleteRows.filter((d) => d.req === a.req);
const seenDeleteIds = new Set();
for (const d of reqDeletes) {
if (!pinned.has(d.id))
throw new ControlPlaneCorruptError(`transaction journal delete evidence for ${JSON.stringify(d.id)} is outside its anchor's pinned set (req ${JSON.stringify(a.req)}): ${jp}`);
if (seenDeleteIds.has(d.id))
throw new ControlPlaneCorruptError(`transaction journal carries two delete rows for ${JSON.stringify(d.id)} under one request (req ${JSON.stringify(a.req)}): ${jp}`);
seenDeleteIds.add(d.id);
}
const reqProjections = requestRows.filter((r) => r.req === a.req);
const projScopesOf = new Map();
const seenProjScopes = new Set();
for (const r of reqProjections) {
if (seenProjScopes.has(r.scope))
throw new ControlPlaneCorruptError(`transaction journal carries two erasure projection rows for scope ${JSON.stringify(r.scope)} under one request (req ${JSON.stringify(a.req)}): ${jp}`);
seenProjScopes.add(r.scope);
if (r.selectHash !== a.selectHash)
throw new ControlPlaneCorruptError(`transaction journal erasure projection row (req ${JSON.stringify(a.req)}, scope ${JSON.stringify(r.scope)}) disagrees with its anchor's selectHash: ${jp}`);
for (const id of r.ids) {
if (!pinned.has(id))
throw new ControlPlaneCorruptError(`transaction journal erasure projection row carries ${JSON.stringify(id)} outside its anchor's pinned set (req ${JSON.stringify(a.req)}): ${jp}`);
const list = projScopesOf.get(id) ?? [];
list.push(r.scope);
projScopesOf.set(id, list);
}
}
const expectedNotFound = new Set();
for (const id of a.ids) {
const dRows = reqDeletes.filter((d) => d.id === id);
let expectScope;
if (dRows.length > 0) {
const withFrom = dRows.find((d) => d.from !== undefined);
expectScope = withFrom?.from?.scope;
}
else if (rowPresent(id)) {
expectScope = rowsBinding(snapshotRows, id)?.scope;
}
else {
expectedNotFound.add(id);
}
const cells = projScopesOf.get(id) ?? [];
if (expectScope === undefined) {
if (cells.length !== 0)
throw new ControlPlaneCorruptError(`transaction journal erasure partition violation: ${JSON.stringify(id)} appears in a projection row but belongs to no scope cell (req ${JSON.stringify(a.req)}): ${jp}`);
}
else if (cells.length !== 1 || cells[0] !== expectScope) {
throw new ControlPlaneCorruptError(`transaction journal erasure partition violation: ${JSON.stringify(id)} must appear exactly once in the ${JSON.stringify(expectScope)} projection row (req ${JSON.stringify(a.req)}): ${jp}`);
}
}
const claimedNotFound = new Set(a.notFound);
if (claimedNotFound.size !== expectedNotFound.size || [...expectedNotFound].some((id) => !claimedNotFound.has(id))) {
throw new ControlPlaneCorruptError(`transaction journal erasure anchor's notFound set disagrees with the journal's own terminal facts (req ${JSON.stringify(a.req)}): ${jp}`);
}
}
for (const r of requestRows) {
if (!anchorRows.some((a) => a.req === r.req)) {
throw new ControlPlaneCorruptError(`transaction journal erasure projection row (req ${JSON.stringify(r.req)}) has no same-journal anchor — projection rows ride the first-execution journal only: ${jp}`);
}
}
}
this.assertTxnLockOwnership(fenceToken);
const replayAt = `the journal replay (journal kept at ${jp})`;
this.refuseEscapingTargets(journal.ops, replayAt);
for (const op of journal.ops) {
this.refuseEscapingTargets([op], replayAt);
try {
if (op.kind === "write" && op.content !== undefined) {
atomicWriteFileSync(op.target, op.content);
if (op.staged)
rmSync(op.staged, { force: true });
}
else if (op.kind === "delete") {
rmSync(op.target, { force: true });
}
else if (op.kind === "shadow-write" && op.content !== undefined) {
atomicWriteFileSync(this.shadowPath(op.target), op.content);
}
else if (op.kind === "shadow-delete") {
rmSync(this.shadowPath(op.target), { force: true });
}
}
catch (err) {
const code = err.code;
throw new ControlPlaneCorruptError(`transaction journal replay failed on op kind=${op.kind} target=${JSON.stringify(op.target)} (${code ?? (thrownText(err))}) — the journal is kept at ${jp}; ${permissionRemedyOf(err, this.directoryRoot) ?? "an I/O failure retries at the next construction, a persistent fault needs the explicit control-plane rebuild path"}`);
}
}
this.recoveryCommitProbe?.();
this.assertTxnLockOwnership(fenceToken);
if (snapshotForm === "v2") {
this.ledger = snapshotRows;
this.envelopeExtras = snapshotExtras;
this.persistedSchemaVersion = "v2";
this.saveLedger();
this.appendTransfers(journal.transfers ?? []);
}
else {
this.ledger = snapshotRows;
this.persistedSchemaVersion = "v1";
this.persistLedgerV1(snapshotRows);
}
if (typeof journal.txn === "string") {
this.closeJournalIfOurs(journal.txn);
}
else {
this.assertTxnLockOwnership(fenceToken);
rmSync(jp, { force: true });
}
}
this.assertTxnLockOwnership(fenceToken);
this.sweepStagedFiles();
}
txnInFlight() {
try {
return this.now() - statSync(this.txnLockDir()).mtimeMs < TXN_LOCK_STALE_MS;
}
catch (err) {
const code = err.code;
if (code === "ENOENT")
return false;
throw new ControlPlaneCorruptError(`txn lock state could not be probed (${code ?? "io error"}) at ${this.txnLockDir()} — a probe failure is not "no writer" (fail-closed)`);
}
}
refuseEscapingTargets(ops, at) {
for (const op of ops) {
if (op.kind !== "write" && op.kind !== "delete")
continue;
for (const path of op.staged === undefined ? [op.target] : [op.target, op.staged]) {
const escape = storeTargetEscape(this.physicalRoot, path);
if (escape === undefined)
continue;
throw erasureCodedError(`${TARGET_OUTSIDE_STORE}: ${at} refused a ${op.kind} of ${op.target}${path === op.target ? "" : ` (its staged file ${path})`} — ${escape}; not performed`, TARGET_OUTSIDE_STORE);
}
}
}
assertRootIntact() {
const now = landingPathOf(this.directoryRoot);
if (now === this.physicalRoot)
return;
throw erasureCodedError(`${TARGET_OUTSIDE_STORE}: the store root ${this.directoryRoot} now resolves to ${now}, not ${this.physicalRoot} where this backend opened it — refused; open a new backend on the directory you mean`, TARGET_OUTSIDE_STORE);
}
sweepStagedFiles() {
const walk = (d, depth) => {
let names;
try {
names = readdirSync(d);
}
catch {
return;
}
for (const name of names) {
const p = join(d, name);
if (name.startsWith(".stage-")) {
rmSync(p, { force: true });
continue;
}
if (depth < DEFAULT_MAX_ENTRY_DEPTH + 1) {
try {
if (lstatSync(p).isDirectory())
walk(p, depth + 1);
}
catch {
}
}
}
};
walk(this.directoryRoot, 0);
}
scopeDir(scope) {
return registerScope(this.directoryRoot, this.controlPlaneRoot, scope);
}
containInboundReject(finding, absPath, text, entryId, committed) {
this.inboundFindings.push(finding);
const q = quarantineAndTombstone(absPath, text, join(this.controlPlaneRoot, QUARANTINE_DIR), this.now);
const shadowText = committed !== undefined ? this.readCommittedShadow(entryId) : undefined;
let restoredShadow = false;
if (shadowText !== undefined) {
try {
atomicWriteFileSync(absPath, shadowText);
restoredShadow = true;
}
catch {
}
}
if (q.detail !== undefined || (!q.removed && !restoredShadow)) {
const contained = q.removed || restoredShadow;
this.inboundFindings.push({
path: finding.path,
code: "quarantine_failed",
reason: `quarantine escalation: ${q.detail ?? "suspect copy not captured"}${contained ? "" : " — rejected content may still be on the model-visible plane"}`,
});
}
return shadowText;
}
inboundGate(relPath, text) {
const nameFinding = scanMemoryFileName(relPath);
if (nameFinding !== undefined)
return { path: relPath, code: "filename", reason: `inbound memory change blocked: ${nameFinding.reason} (quarantined)` };
const findings = scanMemoryWrite(text, { maxBytes: MAX_MEMORY_BYTES });
const first = findings[0];
if (first !== undefined) {
return { path: relPath, code: first.code, reason: `inbound memory change blocked: ${first.reason} (quarantined)` };
}
if (ambiguousOriginRepresentation(parseEntryFile(text).frontmatter)) {
return { path: relPath, code: "invalid", reason: `inbound memory change blocked: conflicting or duplicated origin representations (ambiguous external-origin marker; quarantined)` };
}
return undefined;
}
readScope(scope, sync, probeOnly, lockToken) {
if (!sync && this.batchScan !== undefined) {
const memo = this.batchScan.get(scope);
if (memo !== undefined)
return memo;
}
if (this.persistedSchemaVersion === "v1" || this.unboundRowsKnown)
this.tryOpportunisticMigrate();
const dir = this.scopeDir(scope);
const files = scanEntryFiles(dir);
const entries = [];
const rows = sync ? this.loadLedger() : undefined;
const retrievalDeleted = !sync && files.length > 0 ? this.retrievalDeletedIds() : undefined;
const retrievalGuard = retrievalDeleted !== undefined && retrievalDeleted.size > 0 ? { deleted: retrievalDeleted, account: this.freshCommittedRowsPure() } : undefined;
let ledgerChanged = false;
const adoptedExternal = [];
const moveEvents = [];
const moveAnnouncements = [];
const skippedUnreadable = [];
let table;
const observed = () => (table ??= layerObservationLookup(this.controlPlaneRoot));
let freshAccount;
for (const f of files) {
let text;
try {
text = readFileSync(f.path, "utf8");
}
catch {
skippedUnreadable.push(relative(this.directoryRoot, f.path));
continue;
}
const parsed = parseEntryFile(text);
if (parsed.id === undefined)
continue;
let entry = entryFromFile(text, parsed.id, f.slug, scope);
if (retrievalGuard !== undefined && retrievalGuard.deleted.has(entry.id) && rowsRev(retrievalGuard.account, entry.id) === undefined)
continue;
if (rows) {
const committed = rowsRev(rows, entry.id);
const binding = rowsBinding(rows, entry.id);
const relPath = relative(this.directoryRoot, f.path);
if (probeOnly === true && observed().covers(entry.id)) {
const fresh = (freshAccount ??= this.committedRowsOrFault() ?? null);
const freshBinding = fresh !== null ? rowsBinding(fresh, entry.id) : undefined;
if (fresh === null || rowsRev(fresh, entry.id) !== committed || freshBinding?.scope !== binding?.scope || freshBinding?.slug !== binding?.slug)
return undefined;
}
if (committed !== undefined && binding !== undefined && !(binding.scope === scope && binding.slug === f.slug)) {
const probe = probeProjection(this.bindingAbsPath(binding), entry.id);
if (probe === "present") {
this.announceAdoptionNotice(`copy|${relPath}|${entry.rev}`, `duplicate projection of committed entry ${entry.id} at ${JSON.stringify(inlineUntrusted(relPath))} — the committed projection lives at ${JSON.stringify(inlineUntrusted(this.bindingRelPath(binding)))}; the copy is not served (a copy is not a scope credential) and stays on disk for an unrestricted harvest or manual removal to adjudicate`);
continue;
}
if (probe === "undecidable") {
this.announceAdoptionNotice(`bindprobe|${relPath}`, `committed entry ${entry.id} appears at ${JSON.stringify(inlineUntrusted(relPath))} but is bound to ${JSON.stringify(inlineUntrusted(this.bindingRelPath(binding)))}, and the bound projection could not be probed conclusively (a read failure, or a foreign file at that address — not ENOENT) — nothing is served or adopted this pass`);
continue;
}
if (this.settledAsObserved(observed(), entries, entry, relPath, f.slug, scope, committed, binding, text, "quarantined-only"))
continue;
if (probeOnly)
return undefined;
if (lockToken !== undefined)
this.assertTxnLockOwnership(lockToken);
const adopted = this.adoptMoveCandidateLocked(rows, entry, f.path, f.slug, scope, relPath, text, committed, binding, moveEvents, moveAnnouncements, adoptedExternal);
if (adopted !== undefined) {
entries.push(adopted);
ledgerChanged = true;
}
continue;
}
if (committed !== entry.rev) {
if (committed !== undefined && this.settledAsObserved(observed(), entries, entry, relPath, f.slug, scope, committed, binding, text, "restored"))
continue;
if (probeOnly)
return undefined;
if (lockToken !== undefined)
this.assertTxnLockOwnership(lockToken);
if (committed === undefined) {
const verdict = this.resurrectionBackstopVerdict(entry.id);
if (verdict === "erased") {
this.containInboundReject({
path: relPath,
code: "invalid",
reason: `resurrected entry refused: id ${entry.id} carries a delete evidence row on the store's custody chain and has no committed account row — a deleted entry's bytes reappearing on disk are never re-adopted (quarantined; restoring the content is an explicit write minting a NEW id)`,
}, f.path, text, entry.id, undefined);
continue;
}
if (verdict === "degraded") {
this.announceAdoptionNotice(`chain-degraded|${relPath}|${entry.rev}`, `new memory entry file ${JSON.stringify(inlineUntrusted(relPath))} is NOT adopted: the transfer evidence chain is degraded (out-of-band tail damage), so "no delete row for this id" is no longer evidence it was never deleted — the file stays on disk unserved until the chain state is explicitly rebuilt (${CHAIN_DEGRADED_FILE})`);
continue;
}
}
let finding = this.inboundGate(relPath, text);
if (finding === undefined && committed !== undefined)
finding = this.whitewashInboundFinding(relPath, entry, "restored");
if (finding) {
const shadowText = this.containInboundReject(finding, f.path, text, entry.id, committed);
if (shadowText === undefined) {
if (committed !== undefined) {
deleteRow(rows, entry.id);
ledgerChanged = true;
}
continue;
}
entry = entryFromFile(shadowText, entry.id, f.slug, scope);
}
else {
if (committed === undefined && this.settledAsObserved(observed(), entries, entry, relPath, f.slug, scope, committed, binding, text, "restored"))
continue;
if (committed !== undefined)
adoptedExternal.push(relPath);
bindRowTracked(rows, entry.id, { rev: entry.rev, scope, slug: f.slug, at: this.now() }, moveEvents, "adopted-move");
try {
atomicWriteFileSync(this.shadowPath(entry.id), text);
}
catch {
}
ledgerChanged = true;
}
}
else if (this.readCommittedShadow(entry.id) === undefined) {
try {
atomicWriteFileSync(this.shadowPath(entry.id), text);
}
catch {
}
}
}
entries.push(entry);
}
if (ledgerChanged) {
if (lockToken !== undefined)
this.assertTxnLockOwnership(lockToken);
if (moveEvents.length > 0) {
this.precheckTransfersAppendable();
const journal = {
txn: `${Date.now()}-${randomUUID().slice(0, 8)}`,
ops: [],
ledger2: ledgerEnvelope(rows, this.envelopeExtras),
transfers: moveEvents,
};
atomicWriteFileSync(join(this.controlPlaneRoot, JOURNAL_FILE), JSON.stringify(journal));
this.saveLedger();
this.appendTransfers(moveEvents);
rmSync(join(this.controlPlaneRoot, JOURNAL_FILE), { force: true });
}
else {
this.saveLedger();
}
}
if (moveAnnouncements.length > 0) {
this.enqueueExternalItems(moveAnnouncements.slice(0, 12).concat(moveAnnouncements.length > 12 ? [`…and ${moveAnnouncements.length - 12} more adopted move(s)`] : []));
}
if (adoptedExternal.length > 0) {
try {
enqueueMemoryAnnouncement(this.controlPlaneRoot, {
kind: "external",
at: this.now(),
items: adoptedExternal
.slice(0, 12)
.map((rel) => `out-of-session memory change adopted: ${JSON.stringify(inlineUntrusted(rel))} — re-read it before relying on prior knowledge of it`)
.concat(adoptedExternal.length > 12 ? [`…and ${adoptedExternal.length - 12} more adopted change(s)`] : []),
});
}
catch {
}
}
if (skippedUnreadable.length > 0) {
try {
enqueueMemoryAnnouncement(this.controlPlaneRoot, {
kind: "external",
at: this.now(),
items: skippedUnreadable
.slice(0, 12)
.map((rel) => `committed memory entry could not be read and is MISSING from this session's memory: ${JSON.stringify(inlineUntrusted(rel))} — check the file (permissions/fs)`)
.concat(skippedUnreadable.length > 12 ? [`…and ${skippedUnreadable.length - 12} more unreadable entr(ies)`] : []),
});
}
catch {
}
}
if (!sync && this.batchScan !== undefined)
this.batchScan.set(scope, entries);
return entries;
}
settledAsObserved(table, out, entry, relPath, slug, scope, committed, binding, text, containment) {
if (!table.covers(entry.id) || this.inboundGate(relPath, text) !== undefined)
return false;
if (committed !== undefined && committed !== entry.rev && this.whitewashInboundFinding(relPath, entry, containment) !== undefined)
return false;
const hit = table.find(entry.id, committed, entry.rev);
if (hit === undefined)
return false;
const standIn = committed !== undefined && binding !== undefined && binding.scope === scope && binding.slug === slug ? this.readCommittedShadow(entry.id) : undefined;
const notice = observedDivergenceNotice(relPath, standIn !== undefined, hit.undecided === true);
try {
enqueueMemoryAnnouncement(this.controlPlaneRoot, { kind: "external", at: this.now(), items: [notice] }, { supersedesPrefix: notice });
}
catch {
}
if (standIn !== undefined)
out.push(entryFromFile(standIn, entry.id, slug, scope));
return true;
}
whitewashInboundFinding(relPath, entry, containment) {
const committedShadow = this.readCommittedShadow(entry.id);
const committedFm = committedShadow !== undefined ? parseEntryFile(committedShadow).frontmatter : undefined;
if (committedFm === undefined)
return undefined;
if (committedFm.provenance?.kind === "repo_file") {
const stripsProvenance = entry.frontmatter.provenance === undefined;
const stripsTrust = committedFm.trust !== undefined && entry.frontmatter.trust === undefined;
if (stripsProvenance || stripsTrust) {
return {
path: relPath,
code: "invalid",
reason: `inbound memory change blocked: repo_file provenance whitewash refused — the on-disk change drops ${stripsProvenance ? "provenance" : "trust"} from a repo-ingested entry ${containment === "restored" ? "(quarantined; committed content restored)" : "(quarantined)"}`,
};
}
}
const committedOrigin = committedOriginOf(committedFm);
if (committedOrigin !== undefined && !originEquals(committedOrigin, committedOriginOf(entry.frontmatter))) {
return {
path: relPath,
code: "invalid",
reason: `inbound memory change blocked: external-origin marker whitewash refused — the on-disk change strips or rewrites the origin marker of a marked entry ${containment === "restored" ? "(quarantined; committed content restored)" : "(quarantined)"}`,
};
}
return undefined;
}
adoptMoveCandidateLocked(rows, entry, absPath, slug, scope, relPath, text, committedRev, from, moveEvents, moveAnnouncements, adoptedExternal) {
const census = this.censusProjectionsLocked();
if (!census.complete) {
this.inboundFindings.push({
path: relPath,
code: "unreadable",
reason: `move adoption deferred: committed entry ${entry.id} lost its committed projection, but the store-wide projection census could not read every scope — nothing is served or adopted off a partial view; the next pass retries`,
});
return undefined;
}
const projections = census.byId.get(entry.id) ?? [];
const others = projections.filter((p) => !(p.scope === scope && p.slug === slug));
if (others.length > 0) {
this.announceAdoptionNotice(`ambiguous|${entry.id}|${projections
.map((p) => `${p.scope}/${p.slug}`)
.sort()
.join(",")}`, `committed entry ${entry.id} lost its committed projection and now appears at ${projections.length} path(s) — no copy is a scope credential, so none is served or adopted (read order never picks an owner); an unrestricted harvest or manual removal adjudicates which is real`);
return undefined;
}
const gateFinding = this.inboundGate(relPath, text) ?? (committedRev !== entry.rev ? this.whitewashInboundFinding(relPath, entry, "quarantined-only") : undefined);
if (gateFinding !== undefined) {
this.containInboundReject(gateFinding, absPath, text, entry.id, undefined);
return undefined;
}
const now = this.now();
bindRowTracked(rows, entry.id, { rev: entry.rev, scope, slug, at: now }, moveEvents, "adopted-move");
moveAnnouncements.push(`out-of-session memory move adopted: ${entry.id} ${JSON.stringify(inlineUntrusted(this.bindingRelPath(from)))} → ${JSON.stringify(inlineUntrusted(relPath))} — re-read it before relying on prior knowledge of it`);
if (committedRev !== entry.rev) {
adoptedExternal.push(relPath);
try {
atomicWriteFileSync(this.shadowPath(entry.id), text);
}
catch {
}
}
return entry;
}
async readScopeAdopting(scope, timings) {
const probed = this.readScope(scope, true, true);
if (probed !== undefined)
return probed;
const lock = await this.acquireTxnLock(timings);
try {
this.assertTxnLockOwnership(lock.token);
this.ledger = undefined;
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token);
this.migrateLockedIfNeeded(lock.token);
return this.readScope(scope, true, false, lock.token);
}
catch (err) {
this.ledger = undefined;
throw err;
}
finally {
lock.release();
}
}
listScopes() {
this.ensureLayout();
return { supported: true, scopes: Object.keys(registeredScopes(this.controlPlaneRoot)).sort() };
}
async listHeaders(scopes) {
this.ensureLayout();
return this.listHeadersFrom(scopes, (s) => this.readScopeAdopting(s));
}
async listHeadersFrom(scopes, read) {
const out = [];
for (const scope of scopes) {
const dir = this.scopeDir(scope);
for (const e of await read(scope)) {
out.push(headerOf(e, join(dir, `${e.slug}.md`)));
}
}
return out;
}
async getByIds(ids) {
this.ensureLayout();
return this.getByIdsFrom(ids, (s) => this.readScopeAdopting(s));
}
async getByIdsFrom(ids, read) {
const want = new Set(ids);
const out = [];
for (const scope of Object.keys(registeredScopes(this.controlPlaneRoot))) {
for (const e of await read(scope)) {
if (want.has(e.id))
out.push(e);
}
}
return out;
}
retrievalView() {
const refuse = (op) => {
throw new Error(`memory retrieval view is read-only — ${op} must go through the backend itself`);
};
return {
listHeaders: async (scopes) => (this.ensureLayout(), this.listHeadersFrom(scopes, (s) => this.withoutObserved(this.readScope(s, false), s))),
getByIds: async (ids) => (this.ensureLayout(), this.getByIdsFrom(ids, (s) => this.withoutObserved(this.readScope(s, false), s))),
search: async (query, scopes, opts) => (this.ensureLayout(), this.searchFrom(query, scopes, opts, (s) => this.withoutObserved(this.readScope(s, false), s))),
applyPatches: async () => refuse("applyPatches"),
getConsolidationCursor: async (scope) => this.getConsolidationCursor(scope),
setConsolidationCursor: async () => refuse("setConsolidationCursor"),
};
}
withoutObserved(entries, scope) {
const table = layerObservationLookup(this.controlPlaneRoot);
if (!entries.some((e) => table.covers(e.id)))
return entries;
const account = this.committedRowsOrFault();
if (account === undefined)
return entries.filter((e) => !table.covers(e.id));
const out = [];
for (const e of entries) {
const committed = rowsRev(account, e.id);
const binding = rowsBinding(account, e.id);
const boundHere = binding !== undefined && binding.scope === scope && binding.slug === e.slug;
if ((committed === e.rev && boundHere) || table.find(e.id, committed, e.rev) === undefined) {
out.push(e);
continue;
}
const standIn = committed !== undefined && boundHere ? this.readCommittedShadow(e.id) : undefined;
if (standIn !== undefined)
out.push(entryFromFile(standIn, e.id, e.slug, scope));
}
return out;
}
committedRowsOrFault() {
const path = join(this.controlPlaneRoot, LEDGER_FILE);
try {
const raw = readControlFileOrAbsent(path, "committed-rev ledger");
return raw === undefined ? Object.create(null) : parseLedgerText(raw, path).rows;
}
catch {
return undefined;
}
}
restrictedFindingKeys = new Set();
recordRestrictedFinding(key, finding) {
if (this.restrictedFindingKeys.has(key))
return;
this.restrictedFindingKeys.add(key);
this.inboundFindings.push(finding);
}
restrictedIdlessScope;
restrictedIdlessBaseline;
readScopeCommitted(scope, audit) {
if (this.persistedSchemaVersion === "v1" || this.unboundRowsKnown)
this.tryOpportunisticMigrate();
const dir = this.scopeDir(scope);
const files = scanEntryFiles(dir, {
onSkip: audit
? (p, kind) => {
if (kind !== "unreadable")
return;
const rel = relative(this.directoryRoot, p);
this.recordRestrictedFinding(`unreadable|${rel}`, {
path: rel,
code: "unreadable",
reason: "the path could not be read (lstat/readdir failed) — the restricted-session divergence audit is incomplete under it",
});
}
: undefined,
});
this.ledger = undefined;
const rows = this.loadLedger();
const idlessSeen = audit && scope === this.restrictedIdlessScope ? new Set() : undefined;
const entries = [];
for (const f of files) {
const rel = relative(this.directoryRoot, f.path);
let text;
try {
text = readFileSync(f.path, "utf8");
}
catch {
if (audit) {
this.recordRestrictedFinding(`unreadable|${rel}`, {
path: rel,
code: "unreadable",
reason: "memory entry file could not be read — it is missing from this restricted session's view",
});
}
continue;
}
const parsed = parseEntryFile(text);
if (parsed.id === undefined) {
idlessSeen?.add(rel);
continue;
}
const entry = entryFromFile(text, parsed.id, f.slug, scope);
const committed = rowsRev(rows, entry.id);
const binding = rowsBinding(rows, entry.id);
const boundElsewhere = binding !== undefined && !(binding.scope === scope && binding.slug === f.slug);
if (committed === entry.rev) {
if (boundElsewhere) {
if (audit) {
const boundRel = this.bindingRelPath(binding);
const probe = probeProjection(this.bindingAbsPath(binding), entry.id);
if (probe === "present") {
this.recordRestrictedFinding(`bindcopy|${rel}|${entry.rev}`, {
path: rel,
code: "restricted_divergence",
reason: `this file carries the bytes of committed entry ${entry.id}, whose committed projection is in place at ${JSON.stringify(inlineUntrusted(boundRel))} — a filesystem copy is not a scope credential, so this copy is withheld; an unrestricted session's harvest adjudicates it`,
});
}
else if (probe === "absent") {
this.recordRestrictedFinding(`bindmove|${rel}|${entry.rev}`, {
path: rel,
code: "restricted_divergence",
reason: `committed entry ${entry.id} is bound to ${JSON.stringify(inlineUntrusted(boundRel))} but its projection appears here instead — an unattributed move, or a delete-then-plant; this adoption-restricted session serves neither reading and leaves adjudication to an unrestricted session`,
});
}
else {
this.recordRestrictedFinding(`bindprobe|${rel}`, {
path: rel,
code: "unreadable",
reason: `committed entry ${entry.id} is bound elsewhere and the bound projection could not be probed conclusively (a read failure, not absence) — the binding audit for this file is incomplete; it is withheld this pass`,
});
}
}
continue;
}
if (audit && this.readCommittedShadow(entry.id) === undefined) {
try {
atomicWriteFileSync(this.shadowPath(entry.id), text);
}
catch {
}
}
entries.push(entry);
continue;
}
const shadowText = committed !== undefined ? this.readCommittedShadow(entry.id) : undefined;
if (shadowText !== undefined) {
const shadowEntry = entryFromFile(shadowText, entry.id, f.slug, scope);
if (shadowEntry.rev === entry.rev && !boundElsewhere) {
entries.push(entry);
continue;
}
const otherProjection = binding !== undefined ? (boundElsewhere ? this.bindingRelPath(binding) : undefined) : this.idProjectionElsewhere(entry.id, f.path);
if (otherProjection !== undefined) {
if (audit) {
const finding = this.inboundGate(rel, text);
if (finding !== undefined) {
this.containInboundReject(finding, f.path, text, entry.id, undefined);
}
else {
this.recordRestrictedFinding(`dupserve|${rel}|${entry.rev}`, {
path: rel,
code: "restricted_divergence",
reason: binding !== undefined
? `this file diverges from committed entry ${entry.id}, whose committed projection is bound at ${JSON.stringify(inlineUntrusted(otherProjection))} — the committed copy may only stand in at the entry's committed projection, so this copy is withheld; an unrestricted session's harvest adjudicates it`
: `this file carries the id of a committed entry that has another projection (${otherProjection}) — the committed copy may only stand in for an entry's unique projection, so this copy is withheld; an unrestricted session's harvest adjudicates it`,
});
}
}
continue;
}
if (audit) {
const finding = this.inboundGate(rel, text);
if (finding !== undefined) {
this.containInboundReject(finding, f.path, text, entry.id, committed);
}
else {
this.recordRestrictedFinding(`divergence|${rel}|${entry.rev}`, {
path: rel,
code: "restricted_divergence",
reason: "on-disk content diverges from the committed entry with no backend transaction backing it; this adoption-restricted session serves the committed content and leaves the disk state pending — an unrestricted session can adopt it normally",
});
}
}
entries.push(shadowEntry);
continue;
}
if (committed !== undefined) {
if (audit) {
this.recordRestrictedFinding(`legacy|${rel}|${entry.rev}`, {
path: rel,
code: "restricted_divergence",
reason: "on-disk content diverges from a committed entry that has no committed shadow copy; this adoption-restricted session withholds the entry (nothing trustworthy to serve) — an unrestricted session can adjudicate it",
});
}
continue;
}
if (audit) {
const finding = this.inboundGate(rel, text);
if (finding !== undefined) {
this.containInboundReject(finding, f.path, text, entry.id, undefined);
}
else {
this.recordRestrictedFinding(`uncommitted|${rel}|${entry.rev}`, {
path: rel,
code: "restricted_divergence",
reason: "an id-bearing memory file exists on disk that the committed account has never seen; this adoption-restricted session neither adopts nor serves it — it stays on disk for an unrestricted session to adopt normally",
});
}
}
}
if (idlessSeen !== undefined && this.restrictedIdlessBaseline === undefined)
this.restrictedIdlessBaseline = idlessSeen;
return entries;
}
idProjectionElsewhere(id, excludeAbsPath) {
for (const scope of Object.keys(registeredScopes(this.controlPlaneRoot))) {
const dir = this.scopeDir(scope);
for (const f of scanEntryFiles(dir)) {
if (f.path === excludeAbsPath)
continue;
const text = readSafe(f.path);
if (text === undefined)
continue;
if (parseEntryFile(text).id === id)
return relative(this.directoryRoot, f.path);
}
}
return undefined;
}
restrictedAdoptionView(opts) {
const audit = opts?.audit === true;
if (audit) {
this.restrictedFindingKeys = new Set();
this.restrictedIdlessScope = typeof opts?.writeScope === "string" ? opts.writeScope : undefined;
this.restrictedIdlessBaseline = undefined;
}
const refuse = (op) => {
throw new Error(`memory adoption-restricted view is read-only — ${op} must go through the backend itself`);
};
return {
listHeaders: async (scopes) => (this.ensureLayout(), this.listHeadersFrom(scopes, (s) => this.readScopeCommitted(s, audit))),
getByIds: async (ids) => (this.ensureLayout(), this.getByIdsFrom(ids, (s) => this.readScopeCommitted(s, audit))),
search: async (query, scopes, o) => (this.ensureLayout(), this.searchFrom(query, scopes, o, (s) => this.readScopeCommitted(s, audit))),
applyPatches: async () => refuse("applyPatches"),
getConsolidationCursor: async (scope) => this.getConsolidationCursor(scope),
setConsolidationCursor: async () => refuse("setConsolidationCursor"),
};
}
auditRestrictedDivergence(scopes, opts) {
this.ensureLayout();
for (const scope of scopes)
this.readScopeCommitted(scope, true);
const idlessBaseline = opts?.idlessWriteScope !== undefined && opts.idlessWriteScope === this.restrictedIdlessScope ? this.restrictedIdlessBaseline : undefined;
const idlessScope = idlessBaseline !== undefined ? opts?.idlessWriteScope : undefined;
if (this.persistedSchemaVersion === "v1" || hasUnboundRows(this.loadLedger()))
this.tryOpportunisticMigrate();
const rows = { ...this.loadLedger() };
if (this.persistedSchemaVersion === "v2")
this.announceUnboundRows(rows);
const present = new Map();
let complete = true;
for (const scope of Object.keys(registeredScopes(this.controlPlaneRoot))) {
const dir = this.scopeDir(scope);
const files = scanEntryFiles(dir, {
onSkip: (_p, kind) => {
if (kind === "unreadable")
complete = false;
},
});
for (const f of files) {
const text = readSafe(f.path);
if (text === undefined) {
complete = false;
continue;
}
const id = parseEntryFile(text).id;
if (id !== undefined) {
present.set(id, [...(present.get(id) ?? []), relative(this.directoryRoot, f.path)]);
continue;
}
if (scope === idlessScope && idlessBaseline !== undefined) {
const rel = relative(this.directoryRoot, f.path);
if (!idlessBaseline.has(rel)) {
this.recordRestrictedFinding(`idless|${rel}|${createHash("sha256").update(text, "utf8").digest("hex").slice(0, 16)}`, {
path: rel,
code: "restricted_divergence",
reason: "an id-less file appeared under the session's write scope after materialize, through none of this session's channels: a concurrent session's in-flight material, or an out-of-band drop — left on disk for an unrestricted harvest to adjudicate",
});
}
}
}
}
for (const [id, paths] of present) {
if (paths.length < 2 || rowsRev(rows, id) === undefined)
continue;
const dupBinding = rowsBinding(rows, id);
this.recordRestrictedFinding(`dup|${id}|${paths.sort().join(",")}`, {
path: paths[0] ?? id,
code: "restricted_divergence",
reason: `committed memory entry ${id} appears at ${paths.length} paths (${paths.join(", ")}) — a filesystem copy is not a rename; ${dupBinding !== undefined ? `the committed projection is ${JSON.stringify(inlineUntrusted(this.bindingRelPath(dupBinding)))}, the other path(s) carry no account backing` : "this adoption-restricted session flags it"} and an unrestricted session's harvest adjudicates`,
});
}
if (!complete) {
this.recordRestrictedFinding(`missing-audit-incomplete`, {
path: ".",
code: "restricted_divergence",
reason: "the divergence audit could not scan every path (unreadable subtree) — missing-entry detection was skipped this pass rather than judged from an incomplete scan",
});
return;
}
for (const [id, row] of rowsEntries(rows)) {
const binding = rowsBinding(rows, id);
const paths = present.get(id) ?? [];
if (binding === undefined) {
if (paths.length > 0)
continue;
}
else {
if (paths.includes(this.bindingRelPath(binding)))
continue;
}
this.ledger = undefined;
const current = this.loadLedger();
if (rowsRev(current, id) === undefined)
continue;
if (!bindingEquals(rowsBinding(current, id), binding))
continue;
const aliens = binding !== undefined ? paths.filter((p) => p !== this.bindingRelPath(binding)) : [];
this.recordRestrictedFinding(`missing|${id}|${row.rev}`, {
path: binding !== undefined ? this.bindingRelPath(binding) : `id:${id}`,
code: "restricted_divergence",
reason: binding !== undefined
? `committed memory entry ${id} is missing from its committed projection ${JSON.stringify(inlineUntrusted(this.bindingRelPath(binding)))} with no transaction backing the removal${aliens.length > 0 ? ` while byte-carriers of its id appear at ${aliens.join(", ")} — an unattributed move, or a delete-then-plant` : ""}; this adoption-restricted session neither restores nor forgets it — an unrestricted session adjudicates`
: `committed memory entry ${id} is missing from disk with no transaction backing the removal; this adoption-restricted session neither restores nor forgets it — an unrestricted session can restore it from the committed copy`,
});
}
}
async search(query, scopes, opts) {
this.ensureLayout();
return this.searchFrom(query, scopes, opts, (s) => this.readScopeAdopting(s));
}
async searchFrom(query, scopes, opts, read) {
const limit = opts?.limit ?? 20;
const q = termSet(query);
if (q.size === 0)
return [];
const scored = [];
for (const scope of scopes) {
const dir = this.scopeDir(scope);
for (const e of await read(scope)) {
const haystack = `${e.frontmatter.name ?? e.slug} ${e.frontmatter.description ?? ""} ${e.body}`;
const d = jaccardDistance(q, haystack);
if (d === null)
continue;
scored.push({ ...headerOf(e, join(dir, `${e.slug}.md`)), score: d });
}
}
const band = opts?.exposureBands === true ? (h) => (h.exposure === "external" ? 1 : 0) : () => 0;
scored.sort((a, b) => band(a) - band(b) || a.score - b.score || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
return scored.slice(0, limit);
}
async applyPatches(patches) {
const lock = await this.acquireTxnLock();
try {
return await this.applyPatchesLocked(patches, lock.token);
}
catch (err) {
throw withPermissionRemedy(err, this.directoryRoot);
}
finally {
lock.release();
}
}
txnLockDir() {
return join(this.controlPlaneRoot, "txn.lock");
}
async acquireTxnLock(timings = {}) {
const staleMs = timings.staleMs ?? TXN_LOCK_STALE_MS;
const waitMs = timings.waitMs ?? TXN_LOCK_WAIT_MS;
const stealGraceMs = timings.stealGraceMs ?? TXN_LOCK_STEAL_GRACE_MS;
const lockDir = this.txnLockDir();
const ownerPath = join(lockDir, "owner");
mkdirSync(this.controlPlaneRoot, { recursive: true });
const start = Date.now();
let deadline = start + waitMs;
for (;;) {
let acquired = false;
try {
mkdirSync(lockDir);
acquired = true;
}
catch (err) {
if (err.code !== "EEXIST")
throw err;
}
if (acquired) {
const token = randomUUID();
try {
const fd = openSync(ownerPath, "w", 0o600);
try {
writeAllSync(fd, token);
fsyncSync(fd);
}
finally {
closeSync(fd);
}
}
catch (err) {
try {
rmSync(lockDir, { recursive: true, force: true });
}
catch {
}
throw new Error(`memory txn lock owner token could not be written at ${ownerPath}: ${thrownText(err)}`);
}
return {
token,
release: () => {
try {
if (readFileSync(ownerPath, "utf8") !== token)
return;
}
catch {
return;
}
try {
rmSync(lockDir, { recursive: true, force: true });
}
catch {
}
},
};
}
let mtimeMs;
try {
mtimeMs = statSync(lockDir).mtimeMs;
}
catch {
mtimeMs = undefined;
}
if (mtimeMs !== undefined) {
const staleAt = mtimeMs + staleMs;
deadline = Math.max(deadline, staleAt + stealGraceMs);
if (Date.now() > staleAt) {
let tokenPresent = false;
try {
statSync(ownerPath);
tokenPresent = true;
}
catch {
}
if (tokenPresent) {
const tomb = join(this.controlPlaneRoot, `txn.lock.stale-${randomUUID()}`);
let stolen = false;
try {
renameSync(lockDir, tomb);
stolen = true;
}
catch {
}
if (stolen)
rmSync(tomb, { recursive: true, force: true });
}
}
}
if (Date.now() > deadline) {
throw new Error(`memory txn lock timeout (${waitMs}ms, extended to the lock's stale line) at ${lockDir} — another writer is wedged?`);
}
await new Promise((r) => setTimeout(r, 20 + Math.floor(Math.random() * 40)));
}
}
assertTxnLockOwnership(token) {
let held;
try {
held = readFileSync(join(this.txnLockDir(), "owner"), "utf8");
}
catch {
held = undefined;
}
if (held !== token) {
throw new ControlPlaneCorruptError("txn lock ownership lost before commit (holder stalled past the stale deadline and was stolen from?) — transaction aborted, nothing was committed", { facet: "lock-ownership" });
}
}
async applyPatchesLocked(patches, lockToken) {
this.assertTxnLockOwnership(lockToken);
this.ledger = undefined;
this.recoverJournal({ token: lockToken });
this.adoptLayoutLocked(lockToken, patches.find((p) => p.op === "add" && p.entry !== undefined)?.entry?.scope);
this.migrateLockedIfNeeded(lockToken);
const rows = cloneRows(this.loadLedger());
const report = { applied: [], conflicts: [] };
const ops = [];
const transfers = [];
const plannedTargets = new Set();
const nonDeleteIds = new Set();
const plannedDeletes = new Map();
this.batchScan = new Map();
try {
for (const patch of patches) {
try {
if (patch.op !== "delete") {
if (patch.entry !== undefined && patch.entry.id !== patch.id) {
report.conflicts.push({ op: patch.op, id: patch.id, reason: `patch id ${JSON.stringify(patch.id)} != entry id ${JSON.stringify(patch.entry.id)} (malformed patch refused)` });
continue;
}
if (nonDeleteIds.has(patch.id)) {
report.conflicts.push({ op: patch.op, id: patch.id, reason: "duplicate id in batch: another add/update for this id is already planned (copied file keeping its frontmatter id?)" });
continue;
}
nonDeleteIds.add(patch.id);
}
this.planOne(patch, report, ops, rows, plannedTargets, plannedDeletes, transfers);
}
catch (err) {
report.conflicts.push({ op: patch.op, id: patch.id, reason: `io error: ${thrownText(err)}` });
}
}
}
finally {
this.batchScan = undefined;
}
if (ops.length === 0) {
return report;
}
const txn = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
const stagedFiles = [];
const refuseUnstaging = (batch, at) => {
try {
this.refuseEscapingTargets(batch, at);
}
catch (err) {
for (const f of stagedFiles) {
try {
const st = lstatSync(f.path);
if (st.dev === f.dev && st.ino === f.ino)
rmSync(f.path, { force: true });
}
catch {
}
}
throw err;
}
};
let n = 0;
for (const op of ops) {
if (op.kind !== "write" || op.content === undefined)
continue;
refuseUnstaging([op], "applyPatches (staging)");
const staged = join(dirname(op.target), `.stage-${txn}-${n++}`);
mkdirSync(dirname(op.target), { recursive: true });
const fd = openSync(staged, "w", 0o600);
try {
writeAllSync(fd, op.content);
fsyncSync(fd);
const st = fstatSync(fd);
stagedFiles.push({ path: staged, dev: st.dev, ino: st.ino });
}
finally {
closeSync(fd);
}
op.staged = staged;
}
const coherentTransfers = transfers.filter((e) => {
if (e.channel === "migration" || e.channel === "erasure-anchor" || e.channel === "erasure-request")
return true;
if (e.channel === "delete")
return !Object.prototype.hasOwnProperty.call(rows, e.id);
return bindingEquals(rowsBinding(rows, e.id), e.to);
});
this.assertTxnLockOwnership(lockToken);
if (coherentTransfers.length > 0)
this.precheckTransfersAppendable();
const journal = { txn, ops, ledger2: ledgerEnvelope(rows, this.envelopeExtras), ...(coherentTransfers.length > 0 ? { transfers: coherentTransfers } : {}) };
refuseUnstaging(ops, "applyPatches (commit point)");
atomicWriteFileSync(join(this.controlPlaneRoot, JOURNAL_FILE), JSON.stringify(journal));
for (const op of ops) {
this.refuseEscapingTargets([op], "applyPatches (after the commit point; the journal is kept)");
if (op.kind === "write" && op.staged) {
renameSync(op.staged, op.target);
}
else if (op.kind === "delete") {
rmSync(op.target, { force: true });
}
else if (op.kind === "shadow-write" && op.content !== undefined) {
atomicWriteFileSync(this.shadowPath(op.target), op.content);
}
else if (op.kind === "shadow-delete") {
rmSync(this.shadowPath(op.target), { force: true });
}
}
this.ledger = rows;
this.saveLedger();
this.appendTransfers(coherentTransfers);
this.closeJournalIfOurs(txn);
return report;
}
closeJournalIfOurs(txn) {
const jp = join(this.controlPlaneRoot, JOURNAL_FILE);
let raw;
try {
raw = readFileSync(jp, "utf8");
}
catch {
return;
}
try {
const jp = JSON.parse(raw);
if (typeof jp !== "object" || jp === null || jp.txn !== txn)
return;
}
catch {
return;
}
rmSync(jp, { force: true });
}
planOne(patch, report, ops, rows, plannedTargets, plannedDeletes, transfers) {
if (!isValidEntryId(patch.id)) {
report.conflicts.push({ op: patch.op, id: patch.id, reason: `invalid_id_shape (id ${JSON.stringify(patch.id)} fails the frontmatter id contract — the read side would drop it, leaving an applied-but-invisible entry)` });
return;
}
if (patch.op !== "delete" && patch.entry !== undefined && slugEscapes(patch.entry.slug)) {
report.conflicts.push({ op: patch.op, id: patch.id, reason: `invalid_slug_shape (slug ${JSON.stringify(patch.entry.slug)} is empty, absolute, or path-escaping — a projection must stay inside its scope dir)` });
return;
}
if (patch.op !== "delete" && patch.entry !== undefined && ambiguousOriginRepresentation(patch.entry.frontmatter)) {
report.conflicts.push({
op: patch.op,
id: patch.id,
reason: `external-origin marker representation conflict: the entry carries conflicting or duplicated origin representations (malformed patch refused)`,
});
return;
}
if (patch.op === "add") {
const entry = patch.entry;
if (!entry) {
report.conflicts.push({ op: "add", id: patch.id, reason: "add patch without an entry" });
return;
}
const locatedAnywhere = this.locateById(patch.id);
const existingAnywhere = locatedAnywhere !== undefined && plannedDeletes.has(patch.id) ? undefined : locatedAnywhere;
if (locatedAnywhere !== undefined) {
const shadowText = this.readCommittedShadow(patch.id);
const committedFm = shadowText !== undefined ? parseEntryFile(shadowText).frontmatter : locatedAnywhere.entry.frontmatter;
const committedOrigin = committedOriginOf(committedFm);
if (committedOrigin !== undefined && !originEquals(committedOrigin, committedOriginOf(entry.frontmatter))) {
report.conflicts.push({
op: "add",
id: patch.id,
reason: `external-origin marker whitewash refused: the add strips or rewrites the origin marker of a marked entry (malformed patch refused)`,
});
return;
}
const committedDistilled = committedDistilledOf(committedFm);
if (committedDistilled !== undefined && !distilledEquals(committedDistilled, committedDistilledOf(entry.frontmatter))) {
report.conflicts.push({
op: "add",
id: patch.id,
reason: `distilled lineage whitewash refused: the add strips or rewrites the distilled block of a consolidation product (malformed patch refused)`,
});
return;
}
}
if (patch.guard === "absent") {
if (existingAnywhere) {
const currentRev = rowsRev(rows, patch.id) ?? existingAnywhere.entry.rev;
if (currentRev !== computeEntryRev(entry)) {
report.conflicts.push({ op: "add", id: patch.id, reason: "add_guard_absent_conflict (id already exists at a different rev; add-if-absent refuses to overwrite)", currentRev });
return;
}
if (existingAnywhere.entry.scope !== entry.scope || existingAnywhere.entry.slug !== entry.slug) {
report.conflicts.push({
op: "add",
id: patch.id,
reason: `add_guard_absent_conflict (id already exists at the same rev but a different projection ${JSON.stringify(`${existingAnywhere.entry.scope}/${existingAnywhere.entry.slug}`)}; add-if-absent refuses to duplicate)`,
currentRev,
});
return;
}
}
}
if (existingAnywhere !== undefined && existingAnywhere.entry.scope !== entry.scope) {
report.conflicts.push({ op: "add", id: patch.id, reason: `id already exists in scope ${JSON.stringify(existingAnywhere.entry.scope)} (cross-scope add refused)` });
return;
}
if (existingAnywhere !== undefined && existingAnywhere.entry.slug !== entry.slug) {
ops.push({ kind: "delete", target: existingAnywhere.path });
}
const dir = this.scopeDir(entry.scope);
let slug = entry.slug;
let target = join(dir, `${slug}.md`);
for (let n = 2;; n++) {
const existing = plannedTargets.has(target) ? "" : readSafe(target);
if (existing === undefined)
break;
if (existing !== "") {
const parsed = parseEntryFile(existing);
if (parsed.id === undefined || parsed.id === entry.id)
break;
}
slug = `${entry.slug}-${n}`;
target = join(dir, `${slug}.md`);
}
const content = serializeEntryFile(entry);
plannedTargets.add(target);
ops.push({ kind: "write", target, content });
ops.push({ kind: "shadow-write", target: entry.id, content });
const now = this.now();
bindRowTracked(rows, entry.id, { rev: computeEntryRev(entry), scope: entry.scope, slug, at: now }, transfers, "applyPatches-move");
const priorBinding = plannedDeletes.get(entry.id);
const justBound = rows[entry.id];
if (priorBinding !== undefined && justBound !== undefined && !bindingEquals(priorBinding, { scope: entry.scope, slug })) {
rows[entry.id] = { ...justBound, prev: { scope: priorBinding.scope, slug: priorBinding.slug, at: now } };
transfers.push({ ev: randomUUID(), channel: "applyPatches-move", id: entry.id, from: priorBinding, to: { scope: entry.scope, slug }, at: now });
}
report.applied.push({ op: "add", id: entry.id, slug });
return;
}
const found = this.locateById(patch.id, patch.op === "update" ? patch.entry?.scope : undefined);
if (!found) {
report.conflicts.push({ op: patch.op, id: patch.id, reason: "unknown id (entry not found in backend)" });
return;
}
if (patch.op === "update" && patch.entry !== undefined) {
const shadowText = this.readCommittedShadow(patch.id);
const committedFm = shadowText !== undefined ? parseEntryFile(shadowText).frontmatter : found.entry.frontmatter;
if (committedFm.provenance?.kind === "repo_file") {
const next = patch.entry.frontmatter;
const stripsProvenance = next.provenance === undefined;
const stripsTrust = committedFm.trust !== undefined && next.trust === undefined;
if (stripsProvenance || stripsTrust) {
report.conflicts.push({
op: "update",
id: patch.id,
reason: `repo_file provenance whitewash refused: update drops ${stripsProvenance ? "provenance" : "trust"} from a repo-ingested entry (malformed patch refused)`,
});
return;
}
}
const committedOrigin = committedOriginOf(committedFm);
if (committedOrigin !== undefined && !originEquals(committedOrigin, committedOriginOf(patch.entry.frontmatter))) {
report.conflicts.push({
op: "update",
id: patch.id,
reason: `external-origin marker whitewash refused: the update strips or rewrites the origin marker of a marked entry (malformed patch refused)`,
});
return;
}
const committedDistilled = committedDistilledOf(committedFm);
if (committedDistilled !== undefined && !distilledEquals(committedDistilled, committedDistilledOf(patch.entry.frontmatter))) {
report.conflicts.push({
op: "update",
id: patch.id,
reason: `distilled lineage whitewash refused: the update strips or rewrites the distilled block of a consolidation product (malformed patch refused)`,
});
return;
}
}
const currentRev = rowsRev(rows, patch.id) ?? found.entry.rev;
if (patch.baseRev !== undefined && patch.baseRev !== currentRev) {
report.conflicts.push({ op: patch.op, id: patch.id, reason: "rev mismatch (concurrent change)", baseRev: patch.baseRev, currentRev });
const shadowText = this.readCommittedShadow(patch.id);
if (shadowText !== undefined && shadowText !== serializeEntryFile(found.entry)) {
ops.push({ kind: "write", target: found.path, content: shadowText });
}
return;
}
if (patch.op === "delete") {
ops.push({ kind: "delete", target: found.path });
ops.push({ kind: "shadow-delete", target: patch.id });
const deletedBinding = rowsBinding(rows, patch.id);
if (deletedBinding !== undefined) {
const derived = this.bindingAbsPath(deletedBinding);
if (derived !== found.path)
ops.push({ kind: "delete", target: derived });
}
transfers.push({
ev: randomUUID(),
channel: "delete",
id: patch.id,
...(deletedBinding !== undefined ? { from: deletedBinding } : {}),
rev: currentRev,
at: this.now(),
});
deleteRow(rows, patch.id);
plannedDeletes.set(patch.id, deletedBinding);
report.applied.push({ op: "delete", id: patch.id, slug: found.entry.slug });
return;
}
const entry = patch.entry;
if (!entry) {
report.conflicts.push({ op: "update", id: patch.id, reason: "update patch without an entry" });
return;
}
const dir = this.scopeDir(entry.scope);
const target = join(dir, `${entry.slug}.md`);
const content = serializeEntryFile(entry);
if (target !== found.path)
ops.push({ kind: "delete", target: found.path });
plannedTargets.add(target);
ops.push({ kind: "write", target, content });
ops.push({ kind: "shadow-write", target: entry.id, content });
bindRowTracked(rows, entry.id, { rev: computeEntryRev(entry), scope: entry.scope, slug: entry.slug, at: this.now() }, transfers, "applyPatches-move");
report.applied.push({ op: "update", id: entry.id, slug: entry.slug });
}
locateById(id, preferScope) {
const scopes = Object.keys(registeredScopes(this.controlPlaneRoot));
const ordered = preferScope !== undefined ? [preferScope, ...scopes.filter((s) => s !== preferScope)] : scopes;
for (const scope of ordered) {
const dir = this.scopeDir(scope);
for (const e of this.readScope(scope, false)) {
if (e.id === id)
return { entry: e, path: join(dir, `${e.slug}.md`) };
}
}
return undefined;
}
async eraseWithEvidence(input) {
const captured = captureErasureInput(input);
const bad = erasureRequestInvalid(captured);
if (bad !== undefined)
throw erasureCodedError(`eraseWithEvidence: ${bad}`, "config.memory_erasure_request");
const requestId = captured.requestId;
const select = captured.select;
const lock = await this.acquireTxnLock();
try {
this.assertTxnLockOwnership(lock.token);
this.ledger = undefined;
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token);
this.migrateLockedIfNeeded(lock.token);
const rows = cloneRows(this.loadLedger());
const chain = this.readTransferChain(lock.token);
const degraded = this.chainDegradedMarkerPresent();
const custodyState = degraded ? "damaged" : "complete";
const selectHash = erasureSelectHash(select);
const now = this.now();
const localAnchors = chain.filter((r) => r.parsed.channel === "erasure-anchor" && r.parsed.origin === undefined && r.parsed.req === requestId);
if (localAnchors.length > 1) {
throw new ControlPlaneCorruptError(`erasure request ${JSON.stringify(requestId)} has ${localAnchors.length} anchors on the evidence chain — a second anchor cannot be minted by this store (the lock-held chain check runs first), so the chain was spliced out of band; refusing to pick one by file order (a human adjudicates)`);
}
const priorAnchor = localAnchors[0]?.parsed;
if (priorAnchor !== undefined && priorAnchor.selectHash !== selectHash) {
throw erasureCodedError(`eraseWithEvidence: requestId ${JSON.stringify(requestId)} was first executed with a DIFFERENT selector — a requestId names ONE request (pinned set ${JSON.stringify(priorAnchor.selectHash)}, this call ${JSON.stringify(selectHash)}); use a new requestId for a new selector`, "memory.erasure_selector_mismatch");
}
const replay = priorAnchor !== undefined;
let census;
const takeCensus = () => {
if (census === undefined) {
census = this.censusProjectionsLocked();
if (!census.complete) {
throw erasureCodedError("eraseWithEvidence: the store-wide projection census could not read every scope — an erasure attestation cannot claim a clean delete over a store that cannot be fully read; fix the filesystem fault and retry (nothing was deleted, nothing was recorded)", "memory.erasure_census_incomplete");
}
}
return census;
};
const rowPresent = (id) => Object.prototype.hasOwnProperty.call(rows, id);
let resolvedIds;
if (replay) {
resolvedIds = [...priorAnchor.ids];
}
else if ("ids" in select) {
resolvedIds = [...select.ids];
}
else if ("scope" in select) {
const scope = select.scope;
const ledgerIds = rowsEntries(rows)
.filter(([id]) => rowsBinding(rows, id)?.scope === scope)
.map(([id]) => id);
const ghostIds = [...takeCensus().byId.entries()]
.filter(([id, projections]) => !rowPresent(id) && projections.some((p) => p.scope === scope))
.map(([id]) => id);
resolvedIds = [...new Set([...ledgerIds, ...ghostIds])].sort();
}
else {
resolvedIds = lineageContributionsOfSession(this.controlPlaneRoot, select.sessionId)
.map((c) => c.entryId)
.sort();
}
const priorDeletes = new Map();
for (const r of chain) {
if (r.parsed.channel === "delete" && r.parsed.origin === undefined && r.parsed.req === requestId && typeof r.parsed.id === "string") {
const rawFrom = r.parsed.from;
const from = rawFrom !== undefined && typeof rawFrom.scope === "string" && typeof rawFrom.slug === "string" ? { scope: rawFrom.scope, slug: rawFrom.slug } : undefined;
const prev = priorDeletes.get(r.parsed.id);
priorDeletes.set(r.parsed.id, { ev: r.ev, at: r.parsed.at, ...(from !== undefined ? { from } : prev?.from !== undefined ? { from: prev.from } : {}) });
}
}
const transfers = [];
const ops = [];
const erased = [];
const erasedPreviously = [];
const notFoundRows = [];
const conflicts = [];
const rowIds = resolvedIds.filter((id) => rowPresent(id));
const accountAbsentIds = resolvedIds.filter((id) => !rowPresent(id));
if (rowIds.some((id) => isValidEntryId(id)) || accountAbsentIds.length > 0)
takeCensus();
const censusOf = (id) => census?.byId.get(id) ?? [];
const unledgeredLiveIds = accountAbsentIds.filter((id) => censusOf(id).length > 0);
const trulyAbsentIds = accountAbsentIds.filter((id) => censusOf(id).length === 0);
if (!replay) {
transfers.push({ ev: randomUUID(), channel: "erasure-anchor", req: requestId, select: cloneErasureSelect(select), selectHash, ids: [...resolvedIds], notFound: trulyAbsentIds, at: now });
const byScope = new Map();
for (const id of rowIds) {
if (!isValidEntryId(id))
continue;
const binding = rowsBinding(rows, id);
if (binding === undefined)
continue;
const list = byScope.get(binding.scope) ?? [];
list.push(id);
byScope.set(binding.scope, list);
}
for (const scope of [...byScope.keys()].sort()) {
transfers.push({ ev: randomUUID(), channel: "erasure-request", req: requestId, scope, selectHash, ids: byScope.get(scope) ?? [], at: now });
}
}
const lineageCommitted = resolvedIds.length > 0 ? readLineageRecord(this.controlPlaneRoot).committed : {};
const preSessionsOf = (id) => Object.prototype.hasOwnProperty.call(lineageCommitted, id) ? Object.keys(lineageCommitted[id] ?? {}).sort() : [];
for (const id of rowIds) {
const row = rows[id];
if (row === undefined)
continue;
const preSessions = preSessionsOf(id);
if (!isValidEntryId(id)) {
const ev = randomUUID();
transfers.push({ ev, channel: "delete", id, rev: row.rev, req: requestId, sessions: preSessions, legacyId: true, at: now });
deleteRow(rows, id);
erased.push({ id, rev: row.rev, binding: { state: "unbound" }, evidenceEv: ev, projectionsRemoved: 0, sessions: preSessions });
continue;
}
try {
const binding = rowsBinding(rows, id);
const idOps = [{ kind: "shadow-delete", target: id }];
const targets = new Set();
if (binding !== undefined)
targets.add(this.bindingAbsPath(binding));
const censusProjections = censusOf(id);
for (const p of censusProjections)
targets.add(this.bindingAbsPath(p));
for (const t of targets)
idOps.push({ kind: "delete", target: t });
const ev = randomUUID();
transfers.push({ ev, channel: "delete", id, ...(binding !== undefined ? { from: binding } : {}), rev: row.rev, req: requestId, sessions: preSessions, at: now });
ops.push(...idOps);
deleteRow(rows, id);
erased.push({
id,
rev: row.rev,
binding: binding !== undefined ? { state: "bound", scope: binding.scope, slug: binding.slug } : { state: "unbound" },
evidenceEv: ev,
projectionsRemoved: censusProjections.length,
sessions: preSessions,
});
}
catch (err) {
conflicts.push({ id, reason: `io error: ${thrownText(err)}` });
}
}
for (const id of unledgeredLiveIds) {
const preSessions = preSessionsOf(id);
try {
const projections = censusOf(id);
let rev = "unledgered";
const first = projections[0];
if (first !== undefined) {
const txt = readSafe(this.bindingAbsPath(first));
if (txt !== undefined)
rev = computeEntryRev(entryFromFile(txt, id, first.slug, first.scope));
}
const idOps = [{ kind: "shadow-delete", target: id }];
for (const p of projections)
idOps.push({ kind: "delete", target: this.bindingAbsPath(p) });
const ev = randomUUID();
transfers.push({ ev, channel: "delete", id, rev, req: requestId, sessions: preSessions, at: now });
ops.push(...idOps);
erased.push({ id, rev, binding: { state: "unbound" }, evidenceEv: ev, projectionsRemoved: projections.length, sessions: preSessions });
}
catch (err) {
conflicts.push({ id, reason: `io error: ${thrownText(err)}` });
}
}
for (const id of trulyAbsentIds) {
if (erased.some((e) => e.id === id))
continue;
const prior = priorDeletes.get(id);
if (prior !== undefined && custodyState === "complete") {
const fromFree = prior.from !== undefined &&
!Object.values(rows).some((row) => row.scope === prior.from.scope && row.slug === prior.from.slug) &&
!existsSync(this.bindingAbsPath({ scope: prior.from.scope, slug: prior.from.slug }));
erasedPreviously.push({ id, ev: prior.ev, at: prior.at, ...(fromFree ? { from: prior.from } : {}) });
}
else {
notFoundRows.push({ id, ...(custodyState !== "complete" ? { historyUnknown: true } : {}) });
}
}
if (ops.length > 0 || transfers.length > 0) {
const txn = `${Date.now()}-erase-${randomUUID().slice(0, 8)}`;
this.assertTxnLockOwnership(lock.token);
this.precheckTransfersAppendable();
const journal = { txn, ops, ledger2: ledgerEnvelope(rows, this.envelopeExtras), transfers };
this.refuseEscapingTargets(ops, "eraseWithEvidence (commit point)");
atomicWriteFileSync(join(this.controlPlaneRoot, JOURNAL_FILE), JSON.stringify(journal));
for (const op of ops) {
this.refuseEscapingTargets([op], "eraseWithEvidence (after the commit point; the journal is kept)");
if (op.kind === "delete") {
rmSync(op.target, { force: true });
}
else if (op.kind === "shadow-delete") {
rmSync(this.shadowPath(op.target), { force: true });
}
}
this.ledger = rows;
this.saveLedger();
this.appendTransfers(transfers);
this.closeJournalIfOurs(txn);
}
const late = captureAndClearLineageForEntries(this.controlPlaneRoot, resolvedIds);
for (const e of erased) {
const lateSessions = late.get(e.id);
if (lateSessions !== undefined && lateSessions.length > 0)
e.sessions = [...new Set([...e.sessions, ...lateSessions])].sort();
}
const resolvedSet = new Set(resolvedIds);
const quarantineHits = [];
let quarantineOpaque = 0;
const qDir = join(this.controlPlaneRoot, QUARANTINE_DIR);
let qNames = [];
try {
qNames = readdirSync(qDir);
}
catch (err) {
if (err.code !== "ENOENT") {
throw new ControlPlaneCorruptError(`erasure residual enumeration failed: the quarantine dir could not be read (${err.code ?? "io error"}) at ${qDir} — the attestation must not silently claim an empty residual set; retry after the filesystem fault clears (the deletions themselves are committed and a replay converges)`);
}
}
for (const name of qNames.sort()) {
const text = readSafe(join(qDir, name));
if (text === undefined) {
quarantineOpaque++;
continue;
}
const qid = parseEntryFile(text).id;
if (qid === undefined) {
quarantineOpaque++;
continue;
}
if (resolvedSet.has(qid))
quarantineHits.push(name);
}
const claimed = new Set([...erased.map((e) => e.id), ...erasedPreviously.map((e) => e.id)]);
const notFoundSet = new Set(notFoundRows.map((n) => n.id));
const complete = conflicts.length === 0 && resolvedIds.every((id) => claimed.has(id) || (custodyState === "complete" && notFoundSet.has(id)));
return {
v: 1,
requestId,
at: now,
status: complete ? "complete" : "partial",
evidenceCapability: "journal",
custodyState,
select: cloneErasureSelect(select),
selectHash,
resolvedIds,
erased,
notFound: notFoundRows,
...(erasedPreviously.length > 0 ? { erasedPreviously } : {}),
conflicts,
residuals: { quarantineHits, quarantineOpaque, propagation: "local-store-only" },
};
}
catch (err) {
this.ledger = undefined;
throw withPermissionRemedy(err, this.directoryRoot);
}
finally {
lock.release();
}
}
static AUDIT_FENCE_ATTEMPTS = 6;
static AUDIT_FENCE_RETRY_MS = 25;
auditJournalPending() {
return readControlFileOrAbsent(join(this.controlPlaneRoot, JOURNAL_FILE), "transaction journal") !== undefined;
}
auditReadLedger() {
const path = join(this.controlPlaneRoot, LEDGER_FILE);
const raw = readControlFileOrAbsent(path, "committed-rev ledger");
if (raw === undefined)
return { raw, rows: Object.create(null) };
const parsed = parseLedgerText(raw, path);
if (parsed.form === "v1") {
throw new Error(`memory audit read refused: the committed-rev ledger at ${path} is still schema v1 (pre-binding) — ` +
`migrate first (the store migrates itself at its next uncontended write/read entry or checkControlPlane); ` +
`an audit read never triggers the migration`);
}
return { raw, rows: parsed.rows };
}
async auditStable(read) {
for (let attempt = 0; attempt < FileMemoryEngineBackend.AUDIT_FENCE_ATTEMPTS; attempt++) {
if (attempt > 0)
await new Promise((r) => setTimeout(r, FileMemoryEngineBackend.AUDIT_FENCE_RETRY_MS));
if (this.auditJournalPending())
continue;
const before = this.auditReadLedger();
let out;
try {
out = read(before.rows, attempt === FileMemoryEngineBackend.AUDIT_FENCE_ATTEMPTS - 1);
}
catch (err) {
if (err instanceof AuditObservationUnstableError)
continue;
throw err;
}
if (this.auditJournalPending())
continue;
const after = readControlFileOrAbsent(join(this.controlPlaneRoot, LEDGER_FILE), "committed-rev ledger");
if (after !== before.raw)
continue;
return out;
}
throw new AuditSnapshotContendedError(`memory audit read refused after ${FileMemoryEngineBackend.AUDIT_FENCE_ATTEMPTS} attempts: a transaction journal stayed pending ` +
`(or the ledger kept advancing) across every try — the committed account cannot be snapshotted without tearing. ` +
`A journal that never clears is a crashed transaction: the next backend construction or locked write recovers it.`);
}
resolveCommittedContent(id, rev, binding, final, lockHeld = false) {
if (binding === undefined)
return { state: "unavailable", reason: "carrier-missing" };
if (!isValidEntryId(id))
return { state: "unavailable", reason: "carrier-missing" };
const shadowRaw = readControlFileOrAbsent(this.shadowPath(id), "committed shadow copy");
const absPath = this.bindingAbsPath(binding);
if (shadowRaw !== undefined) {
const shadowEntry = entryFromFile(shadowRaw, id, binding.slug, binding.scope);
if (shadowEntry.rev !== rev) {
let projText;
try {
projText = readFileSync(absPath, "utf8");
}
catch {
projText = undefined;
}
if (projText !== undefined && parseEntryFile(projText).id === id) {
const projEntry = entryFromFile(projText, id, binding.slug, binding.scope);
if (projEntry.rev === rev)
return { state: "present", entry: projEntry };
}
if (lockHeld)
return { state: "unavailable", reason: "carrier-missing" };
if (!final)
throw new AuditObservationUnstableError(`shadow bytes for ${id} do not carry the committed rev — possible adoption in flight`);
if (this.txnInFlight()) {
throw new AuditSnapshotContendedError(`memory audit read refused: shadow bytes for ${id} do not carry the committed rev while a live writer holds the txn lock — an adoption is in flight; retry when the store settles.`);
}
return { state: "unavailable", reason: "carrier-missing" };
}
return probeProjection(absPath, id) === "present" ? { state: "present", entry: shadowEntry } : { state: "unavailable", reason: "carrier-missing" };
}
let text;
try {
text = readFileSync(absPath, "utf8");
}
catch {
text = undefined;
}
if (text !== undefined && parseEntryFile(text).id === id) {
const diskEntry = entryFromFile(text, id, binding.slug, binding.scope);
if (diskEntry.rev === rev)
return { state: "present", entry: diskEntry };
}
return { state: "unavailable", reason: "shadowless-legacy" };
}
async committedSnapshotOf(id) {
this.ensureLayout();
return this.auditStable((rows, final) => {
const row = Object.prototype.hasOwnProperty.call(rows, id) ? rows[id] : undefined;
if (row === undefined)
return { state: "absent", id };
const binding = rowsBinding(rows, id);
return {
state: "row",
id,
rev: row.rev,
binding: this.publicBinding(row, binding),
content: this.resolveCommittedContent(id, row.rev, binding, final),
};
});
}
publicBinding(row, binding) {
if (binding === undefined)
return { state: "unbound" };
return {
state: "bound",
scope: binding.scope,
slug: binding.slug,
...(typeof row.at === "number" ? { at: row.at } : {}),
...(row.prev !== undefined ? { prev: { ...row.prev } } : {}),
};
}
async committedSnapshotsOfScopes(scopes) {
const want = new Set(scopes);
this.ensureLayout();
try {
return await this.auditStable((rows, final) => {
const out = { complete: true, rows: [], unbound: [] };
for (const [id, row] of rowsEntries(rows)) {
const binding = rowsBinding(rows, id);
if (binding === undefined) {
out.unbound.push(id);
continue;
}
if (!want.has(binding.scope))
continue;
out.rows.push({
state: "row",
id,
rev: row.rev,
binding: this.publicBinding(row, binding),
content: this.resolveCommittedContent(id, row.rev, binding, final),
});
}
return out;
});
}
catch (err) {
if (err instanceof AuditSnapshotContendedError)
return { complete: false };
throw err;
}
}
async custodyOf(id) {
const transfersPath = join(this.controlPlaneRoot, TRANSFERS_FILE);
for (let attempt = 0; attempt < FileMemoryEngineBackend.AUDIT_FENCE_ATTEMPTS; attempt++) {
if (attempt > 0)
await new Promise((r) => setTimeout(r, FileMemoryEngineBackend.AUDIT_FENCE_RETRY_MS));
if (this.auditJournalPending())
continue;
const rawBefore = readControlFileOrAbsent(transfersPath, "transfer evidence log");
const out = this.custodyReadPure(id, rawBefore);
if (out.state === "complete" && out.events.length === 0) {
const ledgerRaw = readControlFileOrAbsent(join(this.controlPlaneRoot, LEDGER_FILE), "committed-rev ledger");
if (ledgerRaw !== undefined) {
const parsed = parseLedgerText(ledgerRaw, join(this.controlPlaneRoot, LEDGER_FILE));
if (parsed.form === "v2" && Object.prototype.hasOwnProperty.call(parsed.rows, id) && parsed.rows[id]?.prev !== undefined) {
out.state = "damaged";
}
}
}
if (this.auditJournalPending())
continue;
if (readControlFileOrAbsent(transfersPath, "transfer evidence log") !== rawBefore)
continue;
return out;
}
throw new AuditSnapshotContendedError(`memory custody read refused after ${FileMemoryEngineBackend.AUDIT_FENCE_ATTEMPTS} attempts: a transaction journal stayed pending across ` +
`every try — the evidence chain may hold a committed transaction's rows not yet appended. A journal that never ` +
`clears is a crashed transaction: the next backend construction or locked write recovers it.`);
}
custodyReadPure(id, raw) {
const path = join(this.controlPlaneRoot, TRANSFERS_FILE);
const out = { state: "complete", events: [] };
if (raw === undefined)
return out;
const byEv = new Map();
const lines = raw.split("\n");
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line === undefined || line === "")
continue;
let parsed;
try {
parsed = JSON.parse(line);
}
catch {
if (lines.slice(i + 1).every((l) => l === "")) {
out.state = "damaged";
break;
}
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is unparseable (not a torn tail — fail-closed): ${path}`);
}
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is not an object (fail-closed): ${path}`);
}
const e = parsed;
if (typeof e.ev !== "string" || e.ev.length === 0 || typeof e.channel !== "string" || e.channel.length === 0 || typeof e.at !== "number" || !Number.isInteger(e.at)) {
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is missing its base keys (ev/channel/at) — fail-closed: ${path}`);
}
if (KNOWN_TRANSFER_CHANNELS.has(e.channel)) {
const invalid = transferEventInvalid(parsed);
if (invalid !== undefined)
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is invalid (${invalid}): ${path}`);
}
const canonical = canonicalJsonStringify(e);
const seen = byEv.get(e.ev);
if (seen !== undefined) {
if (seen.has(canonical))
continue;
out.state = "damaged";
out.reason ??= `evidence chain carries event id ${JSON.stringify(e.ev)} twice with DIFFERENT payloads (line ${i + 1}) — one ev is one identity; the chain was spliced or corrupted out of band and this store's own write path refuses to operate on it`;
seen.add(canonical);
}
else {
byEv.set(e.ev, new Set([canonical]));
}
if (e.id === id)
out.events.push(e);
}
return out;
}
static EXPORT_INCOMPLETE = "memory.export_incomplete";
storeIdentityLocked() {
const path = join(this.controlPlaneRoot, STORE_IDENTITY_FILE);
const parse = (raw) => {
let parsed;
try {
parsed = JSON.parse(raw);
}
catch {
throw new ControlPlaneCorruptError(`store identity is unparseable: ${path}`);
}
const rec = parsed;
if (!rec || typeof rec !== "object" || rec.v !== 1 || typeof rec.storeId !== "string" || rec.storeId.length === 0) {
throw new ControlPlaneCorruptError(`store identity has the wrong shape: ${path}`);
}
return rec.storeId;
};
const raw = readControlFileOrAbsent(path, "store identity");
if (raw !== undefined)
return parse(raw);
const storeId = randomUUID();
let fd;
try {
fd = openSync(path, "wx", 0o600);
}
catch (err) {
if (err.code === "EEXIST") {
const again = readControlFileOrAbsent(path, "store identity");
if (again === undefined)
throw new ControlPlaneCorruptError(`store identity vanished between its EEXIST and the re-read: ${path}`);
return parse(again);
}
throw err;
}
try {
writeAllSync(fd, `${JSON.stringify({ v: 1, storeId }, null, 2)}\n`);
fsyncSync(fd);
}
finally {
closeSync(fd);
}
return storeId;
}
exportGovernanceFingerprint() {
const h = createHash("sha256");
const feed = (label, text) => {
h.update(JSON.stringify([label, text]));
};
for (const file of [LINEAGE_FILE, CHALLENGES_FILE]) {
feed(file, readControlFileOrAbsent(join(this.controlPlaneRoot, file), `${file} (export fence)`) ?? "<absent>");
let journalRaw;
try {
journalRaw = readControlFileOrAbsent(join(this.controlPlaneRoot, `${file}.journal`), `${file} journal (export fence)`);
}
catch (err) {
throw erasureCodedError(`memory export refused: the ${file} journal could not be read (${thrownText(err)}) — a journal read failure is not absence, and exporting over it could seal stale governance under an honest hash`, FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
feed(`${file}.journal`, journalRaw ?? "<absent>");
}
const dir = join(this.controlPlaneRoot, SESSION_POLLUTION_DIR);
let names = [];
try {
names = readdirSync(dir).sort();
}
catch (err) {
if (err.code !== "ENOENT") {
throw new ControlPlaneCorruptError(`session pollution markers could not be enumerated for export (${err.code ?? "io error"}) at ${dir} — fail-closed`, { cause: err });
}
}
for (const name of names) {
let text;
try {
text = readFileSync(join(dir, name), "utf8");
}
catch (err) {
text = `<unreadable:${err.code ?? "io error"}>`;
}
feed(`pollution/${name}`, text);
}
return h.digest("hex");
}
readExportChainRowsPure() {
const path = join(this.controlPlaneRoot, TRANSFERS_FILE);
const raw = readControlFileOrAbsent(path, "transfer evidence log");
const out = [];
if (raw === undefined)
return out;
const byEv = new Map();
const lines = raw.split("\n");
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line === undefined || line === "")
continue;
let parsed;
try {
parsed = JSON.parse(line);
}
catch {
if (lines.slice(i + 1).every((l) => l === "")) {
throw erasureCodedError(`memory export refused: the transfer evidence log has a torn tail (line ${i + 1}) — the export reads it purely (the file is untouched); run any locked mutation entry (a write, an adopting read) to heal the chain, then export again`, FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is unparseable (not a torn tail — fail-closed): ${path}`);
}
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is not an object (fail-closed): ${path}`);
}
const e = parsed;
if (typeof e.ev !== "string" || e.ev.length === 0 || typeof e.channel !== "string" || e.channel.length === 0 || typeof e.at !== "number" || !Number.isInteger(e.at)) {
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is missing its base keys (ev/channel/at) — fail-closed: ${path}`);
}
if (!KNOWN_TRANSFER_CHANNELS.has(e.channel)) {
throw erasureCodedError(`memory export refused: the evidence chain carries channel ${JSON.stringify(e.channel)} this exporter does not know (line ${i + 1}) — an unknown row can neither be tenant-sliced nor silently dropped; export with the binary that wrote it (or newer)`, FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
const invalid = transferEventInvalid(parsed);
if (invalid !== undefined)
throw new ControlPlaneCorruptError(`transfer evidence log line ${i + 1} is invalid (${invalid}): ${path}`);
const canonical = canonicalJsonStringify(e);
const prior = byEv.get(e.ev);
if (prior !== undefined) {
if (prior !== canonical) {
throw erasureCodedError(`memory export refused: the evidence chain carries event id ${JSON.stringify(e.ev)} twice with DIFFERENT payloads (line ${i + 1}) — a spliced chain cannot be exported`, FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
continue;
}
byEv.set(e.ev, canonical);
out.push(e);
}
return out;
}
sliceCustodyForScopes(rows, scopeSet, fullStore, storeId) {
const custody = [];
let unsliceable = 0;
for (const e of rows) {
const channel = e.channel;
if (channel === "migration" || channel === "erasure-anchor")
continue;
if (channel === "erasure-request") {
if (scopeSet.has(e.scope))
custody.push(e);
continue;
}
if (channel === "delete") {
const from = e.from;
if (from !== undefined && typeof from.scope === "string") {
if (scopeSet.has(from.scope))
custody.push(e);
}
else if (fullStore) {
custody.push(e);
}
else {
unsliceable++;
}
continue;
}
const from = e.from;
const to = e.to;
const fromIn = from !== undefined && typeof from.scope === "string" && scopeSet.has(from.scope);
const toIn = to !== undefined && typeof to.scope === "string" && scopeSet.has(to.scope);
if (!fromIn && !toIn)
continue;
if ((from === undefined || fromIn) && (to === undefined || toIn)) {
custody.push(e);
continue;
}
const redacted = { ...e };
const named = new Set(Array.isArray(e.redacted) ? e.redacted : []);
if (from !== undefined && !fromIn) {
delete redacted.from;
named.add("from");
}
if (to !== undefined && !toIn) {
delete redacted.to;
named.add("to");
}
redacted.redacted = [...named].sort();
if (redacted.origin === undefined) {
redacted.origin = storeId();
redacted.srcEv = e.ev;
}
custody.push(redacted);
}
return { custody, unsliceable };
}
enumerateQuarantineFor(ids) {
const qDir = join(this.controlPlaneRoot, QUARANTINE_DIR);
let names = [];
try {
names = readdirSync(qDir);
}
catch (err) {
if (err.code !== "ENOENT") {
throw new ControlPlaneCorruptError(`export residual enumeration failed: the quarantine dir could not be read (${err.code ?? "io error"}) at ${qDir} — a bundle must not silently claim an empty residual set`);
}
}
const quarantined = [];
let quarantineOpaque = 0;
for (const name of names.sort()) {
const text = readSafe(join(qDir, name));
if (text === undefined) {
quarantineOpaque++;
continue;
}
const qid = parseEntryFile(text).id;
if (qid === undefined) {
quarantineOpaque++;
continue;
}
if (ids.has(qid))
quarantined.push(name);
}
return { quarantined, quarantineOpaque };
}
async exportSnapshotOf(scopes, timings) {
const scopeSet = new Set(scopes);
const lock = await this.acquireTxnLock(timings);
try {
this.assertTxnLockOwnership(lock.token);
this.ledger = undefined;
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token);
const rows = this.loadLedger();
if (this.persistedSchemaVersion !== "v2") {
throw erasureCodedError("memory export refused: the committed-rev ledger is still schema v1 (pre-binding) — the store migrates itself at its next write/read entry or checkControlPlane; an export never triggers the migration", FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
if (this.chainDegradedMarkerPresent()) {
throw erasureCodedError("memory export refused: the custody chain carries the durable degradation marker (transfers.chain-degraded.json) — evidence rows were lost to an out-of-band tear and a bundle cannot testify to a complete deletion history; resolve the marker deliberately before exporting", FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
const storeId = this.storeIdentityLocked();
const registered = registeredScopes(this.controlPlaneRoot);
const fullStore = Object.keys(registered).every((s) => scopeSet.has(s));
for (let round = 0; round < 3; round++) {
const before = this.exportGovernanceFingerprint();
const lineageRec = readLineageRecord(this.controlPlaneRoot);
const challenges = readChallengeEvents(this.controlPlaneRoot);
const polluted = listSessionPollution(this.controlPlaneRoot);
const chainRows = this.readExportChainRowsPure();
this.exportFaceProbe?.(round);
const after = this.exportGovernanceFingerprint();
if (before !== after)
continue;
const latched = new Set();
for (const txn of Object.values(lineageRec.pending))
for (const row of txn.rows)
latched.add(row.entryId);
const entries = [];
const contentUnavailable = [];
const boundIdsInScopes = new Set();
for (const [id, row] of rowsEntries(rows)) {
const binding = rowsBinding(rows, id);
if (binding === undefined || !scopeSet.has(binding.scope))
continue;
boundIdsInScopes.add(id);
if (latched.has(id))
continue;
const content = this.resolveCommittedContent(id, row.rev, binding, true, true);
if (content.state === "present")
entries.push(content.entry);
else
contentUnavailable.push({ id, scope: binding.scope, slug: binding.slug, rev: row.rev, reason: content.reason });
}
const sliced = this.sliceCustodyForScopes(chainRows, scopeSet, fullStore, () => storeId);
const residual = this.enumerateQuarantineFor(boundIdsInScopes);
const lineage = [];
for (const [entryId, sessions] of Object.entries(lineageRec.committed)) {
for (const [sessionId, c] of Object.entries(sessions))
lineage.push({ entryId, sessionId, lastRev: c.lastRev, lastAt: c.lastAt, ...(c.marked === true ? { marked: true } : {}) });
}
const pollutedSessions = Object.entries(polluted).map(([sessionId, r]) => ({ sessionId, at: r.at, reason: r.reason, ...(r.cause !== undefined ? { cause: r.cause } : {}) }));
try {
this.assertTxnLockOwnership(lock.token);
}
catch (err) {
throw erasureCodedError(`memory export refused: the transaction lock was lost during assembly (a stalled hold past the stale line was stolen from) — the read set can no longer be proven consistent; retry the export (${thrownText(err)})`, FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
return {
storeId,
fullStore,
entries,
contentUnavailable,
unbound: unboundRowIds(rows).sort(),
pendingLatch: [...latched].sort(),
custody: sliced.custody,
unsliceableCustody: sliced.unsliceable,
challenges,
lineage,
pollutedSessions,
quarantined: residual.quarantined,
quarantineOpaque: residual.quarantineOpaque,
};
}
throw erasureCodedError("memory export refused: the governance faces (challenge/lineage/pollution) kept changing across three consistency rounds — the store is too hot to snapshot without tearing; retry when its writers settle", FileMemoryEngineBackend.EXPORT_INCOMPLETE);
}
finally {
lock.release();
}
}
async governanceExport(scopes, timings) {
const scopeSet = new Set(scopes);
const lock = await this.acquireTxnLock(timings);
try {
this.assertTxnLockOwnership(lock.token);
this.ledger = undefined;
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token);
const rows = this.loadLedger();
if (this.persistedSchemaVersion !== "v2")
return { custody: [], unbound: [], complete: false, unsliceableCustody: 0, reason: "the committed-rev ledger is still schema v1 (migrate first)" };
if (this.chainDegradedMarkerPresent()) {
return { custody: [], unbound: [], complete: false, unsliceableCustody: 0, reason: "the custody chain carries the durable degradation marker (transfers.chain-degraded.json) — evidence rows were lost to an out-of-band tear" };
}
const registered = registeredScopes(this.controlPlaneRoot);
const fullStore = Object.keys(registered).every((s) => scopeSet.has(s));
try {
const chainRows = this.readExportChainRowsPure();
const sliced = this.sliceCustodyForScopes(chainRows, scopeSet, fullStore, () => this.storeIdentityLocked());
this.assertTxnLockOwnership(lock.token);
return { custody: sliced.custody, unbound: unboundRowIds(rows).sort(), complete: true, unsliceableCustody: sliced.unsliceable };
}
catch (err) {
if (err.code === FileMemoryEngineBackend.EXPORT_INCOMPLETE || err instanceof ControlPlaneCorruptError) {
if (err instanceof ControlPlaneCorruptError && err.facet !== "lock-ownership")
throw err;
return { custody: [], unbound: [], complete: false, unsliceableCustody: 0, reason: thrownText(err) };
}
throw err;
}
}
finally {
lock.release();
}
}
async custodyImport(rows, opts, timings) {
if (typeof opts?.bundleHash !== "string" || opts.bundleHash.length === 0 || typeof opts.sourceStoreId !== "string" || opts.sourceStoreId.length === 0) {
throw erasureCodedError("custodyImport: bundleHash and sourceStoreId are required (the remint namespace and the origin stamp)", "config.memory_import_request");
}
const lock = await this.acquireTxnLock(timings);
try {
this.assertTxnLockOwnership(lock.token);
this.recoverJournal({ token: lock.token });
return this.custodyImportLocked(rows, opts);
}
finally {
lock.release();
}
}
custodyImportLocked(rows, opts) {
const withheld = [];
const toAppend = [];
for (const row of rows) {
const channel = typeof row.channel === "string" ? row.channel : "<malformed>";
const srcEv = typeof row.srcEv === "string" ? row.srcEv : typeof row.ev === "string" ? row.ev : "<malformed>";
if (typeof row.ev !== "string" || row.ev.length === 0 || typeof row.channel !== "string" || row.channel.length === 0 || typeof row.at !== "number" || !Number.isInteger(row.at)) {
withheld.push({ srcEv, channel });
continue;
}
if (!KNOWN_TRANSFER_CHANNELS.has(row.channel)) {
withheld.push({ srcEv, channel });
continue;
}
if (transferEventInvalid(row) !== undefined) {
withheld.push({ srcEv, channel });
continue;
}
const reminted = {
...row,
ev: `imp:${opts.bundleHash}:${row.ev}`,
origin: row.origin ?? opts.sourceStoreId,
srcEv: row.srcEv ?? row.ev,
};
if (transferEventInvalid(reminted) !== undefined) {
withheld.push({ srcEv, channel });
continue;
}
toAppend.push(reminted);
}
this.appendTransfers(toAppend);
return { appended: toAppend.length, withheld };
}
appendImportChallengesVerified(events) {
if (events.length === 0)
return;
const { assignments } = appendChallengeEvents(this.controlPlaneRoot, events, this.now);
const replayed = assignments.filter((a) => a.replayed);
if (replayed.length === 0)
return;
const byEventId = new Map();
for (const e of readChallengeEvents(this.controlPlaneRoot))
if (!byEventId.has(e.eventId))
byEventId.set(e.eventId, e);
for (const a of replayed) {
const want = events.find((e) => e.eventId === a.eventId);
const got = byEventId.get(a.eventId);
if (want === undefined || got === undefined || got.kind !== "challenge" || got.entryId !== want.entryId || got.reason !== want.reason || got.challengedRev !== want.challengedRev) {
throw new ControlPlaneCorruptError(`bundle import aborted: challenge event ${JSON.stringify(a.eventId)} replayed onto an existing ledger event with a DIFFERENT payload (kind/entryId/reason/challengedRev) — key idempotency would silently swallow the imported challenge; the import latch stays until a clean re-import converges`);
}
}
}
async importBundleCommit(plan, timings) {
const bundleHash = typeof plan?.bundleHash === "string" ? plan.bundleHash : "";
const sourceStoreId = typeof plan?.sourceStoreId === "string" ? plan.sourceStoreId : "";
if (!/^[0-9a-f]{64}$/.test(bundleHash) || sourceStoreId.length === 0) {
throw erasureCodedError("importBundleCommit: plan.bundleHash must be the 64-hex bundle digest and sourceStoreId a non-empty string", "config.memory_import_request");
}
const lock = await this.acquireTxnLock(timings);
try {
this.assertTxnLockOwnership(lock.token);
this.ledger = undefined;
this.recoverJournal({ token: lock.token });
this.adoptLayoutLocked(lock.token);
this.migrateLockedIfNeeded(lock.token);
const ctl = this.controlPlaneRoot;
const txnId = importLatchTxnId(bundleHash);
const receiptPath = join(ctl, IMPORT_RECEIPTS_DIR, `${bundleHash}.json`);
const receiptRaw = readControlFileOrAbsent(receiptPath, "bundle import completion receipt");
if (receiptRaw !== undefined) {
let report;
try {
const parsed = JSON.parse(receiptRaw);
if (parsed === null ||
typeof parsed !== "object" ||
!("v" in parsed) ||
parsed.v !== 1 ||
!("bundleHash" in parsed) ||
parsed.bundleHash !== bundleHash ||
!("report" in parsed)) {
throw new Error("wrong envelope");
}
const rep = parsed.report;
if (!rep ||
typeof rep !== "object" ||
rep.v !== 1 ||
rep.bundleHash !== bundleHash ||
typeof rep.sourceStoreId !== "string" ||
!Array.isArray(rep.landed) ||
!Array.isArray(rep.alreadyPresent) ||
!Array.isArray(rep.refusedErased) ||
!Array.isArray(rep.refusedUntrusted) ||
!Array.isArray(rep.conflicts) ||
!Array.isArray(rep.governanceWithheld) ||
!Array.isArray(rep.erasedAtSource) ||
!Array.isArray(rep.pollutionDivergence) ||
!Array.isArray(rep.referentialOrphans) ||
!Array.isArray(rep.lineageDivergence) ||
!Array.isArray(rep.custodyWithheld) ||
typeof rep.custodyAppended !== "number") {
throw new Error("wrong report shape");
}
report = rep;
}
catch {
throw new ControlPlaneCorruptError(`bundle import completion receipt is unreadable/malformed at ${receiptPath} — it cannot prove completion and cannot be re-minted; repair or remove it deliberately (fail-closed)`);
}
releaseImportLatch(ctl, txnId);
return report;
}
const digest = this.deletedIdsDigestLocked();
if (digest.state === "damaged" || this.chainDegradedMarkerPresent()) {
throw erasureCodedError("memory bundle import refused: the destination evidence chain is damaged or durably marked degraded — deletion history cannot be proven, so the anti-resurrection judgment cannot run; heal/rebuild the chain (locked mutation entry / explicit rebuild), then import again (nothing was landed, no latch was set)", "memory.import_rejected");
}
stageImportLatch(ctl, bundleHash, plan.entries.map((e) => ({ entryId: e.id, rev: e.rev })), this.now);
const rows = this.loadLedger();
const rowPresent = (id) => Object.prototype.hasOwnProperty.call(rows, id);
const report = {
v: 1,
bundleHash,
sourceStoreId,
landed: [],
alreadyPresent: [],
refusedErased: [],
refusedUntrusted: [],
conflicts: [],
governanceWithheld: [],
erasedAtSource: [],
pollutionDivergence: [],
referentialOrphans: [],
lineageDivergence: [],
custodyWithheld: [],
custodyAppended: 0,
};
const entryById = new Map(plan.entries.map((e) => [e.id, e]));
const toLand = [];
for (const e of plan.entries) {
const present = rowPresent(e.id);
if (!present && digest.ids.has(e.id)) {
report.refusedErased.push(e.id);
continue;
}
if (present && rowsRev(rows, e.id) === e.rev && rowsBinding(rows, e.id)?.scope === e.scope) {
report.alreadyPresent.push(e.id);
continue;
}
if (!present && e.frontmatter.provenance?.kind === "repo_file" && e.frontmatter.trust === undefined) {
report.refusedUntrusted.push(e.id);
continue;
}
toLand.push(e);
}
const erasedAtSource = new Set();
for (const c of plan.custody) {
if (c.channel === "delete" && typeof c.id === "string" && rowPresent(c.id))
erasedAtSource.add(c.id);
}
report.erasedAtSource = [...erasedAtSource].sort();
const screened = new Set();
for (const finding of screenInboundEntries(toLand, { perFileBytes: MAX_MEMORY_BYTES })) {
screened.add(finding.id);
report.conflicts.push({ id: finding.id, reason: `inbound screen: ${finding.findings.map((f) => `${f.code} (${f.reason})`).join("; ")}` });
}
const patches = toLand.filter((e) => !screened.has(e.id)).map((e) => ({ op: "add", id: e.id, entry: e, guard: "absent" }));
const patchReport = patches.length > 0 ? await this.applyPatchesLocked(patches, lock.token) : { applied: [], conflicts: [] };
for (const c of patchReport.conflicts)
report.conflicts.push({ id: c.id, reason: c.reason });
const landedIds = new Set();
for (const a of patchReport.applied) {
if (a.op !== "add")
continue;
landedIds.add(a.id);
const src = entryById.get(a.id);
report.landed.push({ id: a.id, scope: src?.scope ?? "", slug: a.slug ?? src?.slug ?? "" });
}
const custodyOutcome = this.custodyImportLocked(plan.custody, { bundleHash, sourceStoreId });
report.custodyAppended = custodyOutcome.appended;
report.custodyWithheld = custodyOutcome.withheld;
const eligible = new Set([...landedIds, ...report.alreadyPresent]);
const destRows = this.loadLedger();
const destKnown = (id) => Object.prototype.hasOwnProperty.call(destRows, id);
const withheldIds = new Set();
const orphanIds = new Set();
const lineageToApply = [];
for (const row of plan.lineage) {
if (eligible.has(row.entryId)) {
if (row.marked === true) {
const shadow = this.readCommittedShadow(row.entryId);
let committedFm = shadow !== undefined ? parseEntryFile(shadow).frontmatter : undefined;
if (committedFm === undefined)
committedFm = this.locateById(row.entryId)?.entry.frontmatter;
if (committedFm !== undefined && committedOriginOf(committedFm) === undefined) {
const { marked: _dropped, ...unmarked } = row;
lineageToApply.push(unmarked);
report.conflicts.push({ id: row.entryId, reason: `lineage row claims marked:true but the committed content carries no origin marker — the bit was dropped (the pollution sweep judges the contribution)` });
continue;
}
}
lineageToApply.push(row);
}
else if (destKnown(row.entryId) || entryById.has(row.entryId))
withheldIds.add(row.entryId);
else
orphanIds.add(row.entryId);
}
const challengesToApply = [];
for (const c of plan.challenges) {
if (eligible.has(c.entryId))
challengesToApply.push(c);
else if (destKnown(c.entryId) || entryById.has(c.entryId))
withheldIds.add(c.entryId);
else
orphanIds.add(c.entryId);
}
report.governanceWithheld = [...withheldIds].sort();
report.referentialOrphans = [...orphanIds].sort();
report.lineageDivergence = importLineageCommitted(ctl, lineageToApply);
this.appendImportChallengesVerified(challengesToApply.map((c) => ({
eventId: `imp:${bundleHash}:${c.eventId}`,
entryId: c.entryId,
reason: c.reason,
...(c.challengedRev !== undefined ? { challengedRev: c.challengedRev } : {}),
})));
for (const p of [...plan.pollutedSessions].sort((a, b) => (a.sessionId < b.sessionId ? -1 : 1))) {
const contributions = lineageContributionsOfSession(ctl, p.sessionId).filter((c) => c.marked !== true);
this.appendImportChallengesVerified(contributions.map((c) => ({
eventId: `imp-sweep:${bundleHash}:pollution:${p.sessionId}:${p.at}:${c.entryId}`,
entryId: c.entryId,
reason: `challenged: the contributing session was marked polluted`,
challengedRev: c.lastRev,
})));
const outcome = importSessionPollution(ctl, p.sessionId, { at: p.at, reason: p.reason, ...(p.cause !== undefined ? { cause: p.cause } : {}) });
if (outcome === "divergent")
report.pollutionDivergence.push({ sessionId: p.sessionId, kept: "destination" });
}
ensureDirExists(join(ctl, IMPORT_RECEIPTS_DIR));
if (readControlFileOrAbsent(receiptPath, "bundle import completion receipt") !== undefined) {
throw new ControlPlaneCorruptError(`bundle import completion receipt appeared mid-import at ${receiptPath} — refusing to overwrite it (fail-closed)`);
}
const staged = join(ctl, IMPORT_RECEIPTS_DIR, `.stage-${bundleHash}-${randomUUID().slice(0, 8)}`);
const fd = openSync(staged, "wx", 0o600);
try {
writeAllSync(fd, `${JSON.stringify({ v: 1, bundleHash, at: this.now(), report }, null, 2)}\n`);
fsyncSync(fd);
}
finally {
closeSync(fd);
}
try {
linkSync(staged, receiptPath);
rmSync(staged, { force: true });
}
catch (err) {
try {
rmSync(staged, { force: true });
}
catch {
}
if (err.code === "EEXIST") {
throw new ControlPlaneCorruptError(`bundle import completion receipt appeared mid-import at ${receiptPath} — refusing to overwrite it (fail-closed)`);
}
throw err;
}
releaseImportLatch(ctl, txnId);
return report;
}
catch (err) {
this.ledger = undefined;
throw err;
}
finally {
lock.release();
}
}
async getConsolidationCursor(scope) {
const cursors = this.readCursors();
return cursors[scope];
}
async setConsolidationCursor(scope, cursor) {
const cursors = this.readCursors();
cursors[scope] = cursor;
atomicWriteFileSync(join(this.controlPlaneRoot, CURSORS_FILE), `${JSON.stringify(cursors, null, 2)}\n`);
}
readCursors() {
try {
const parsed = JSON.parse(readFileSync(join(this.controlPlaneRoot, CURSORS_FILE), "utf8"));
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
const out = Object.create(null);
for (const [k, v] of Object.entries(parsed))
if (typeof v === "string")
out[k] = v;
return out;
}
}
catch {
}
return Object.create(null);
}
}
function headerOf(e, path) {
let mtimeMs = 0;
try {
mtimeMs = statSync(path).mtimeMs;
}
catch {
}
return {
id: e.id,
slug: e.slug,
scope: e.scope,
...(e.frontmatter.name !== undefined ? { name: e.frontmatter.name } : {}),
...(e.frontmatter.description !== undefined ? { description: e.frontmatter.description } : {}),
...(e.frontmatter.type !== undefined ? { type: e.frontmatter.type } : {}),
mtimeMs,
rev: e.rev,
sizeBytes: Buffer.byteLength(serializeEntryFile(e), "utf8"),
...(committedOriginOf(e.frontmatter) !== undefined ? { exposure: "external" } : {}),
...(e.frontmatter.distilled !== undefined
? {
distilled: {
carrierRev: e.frontmatter.distilled.carrierRev,
supersedes: e.frontmatter.distilled.inputs.filter((i) => i.superseded === true).map((i) => ({ id: i.id, rev: i.rev })),
},
}
: {}),
};
}
function readSafe(path) {
try {
return readFileSync(path, "utf8");
}
catch {
return undefined;
}
}
export { scopeDirName };