UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

637 lines (636 loc) • 30.7 kB
import { randomBytes } from "node:crypto"; import { existsSync, readdirSync, readFileSync, unlinkSync } from "node:fs"; import { join, resolve } from "node:path"; import { adoptFilePermissionRuleStore } from "../permission-rule-adopt.js"; import { BootLock, atomicWriteFile, ensureDir, sanitizeScope } from "../fs-atomic.js"; import { SESSION_POLICY_MARK_SUFFIX, attributeSessionPolicyRow, judgeSessionPolicyRowObject, readSessionPolicyMark } from "../session-policy-store.js"; import { SessionPolicyError } from "../../../core/session-policy-store.js"; import { thrownText } from "../../../core/thrown-value.js"; import { AdoptionError, NOT_MIGRATED_BY_DESIGN, readRootAdoptionFile, writeRootAdoptionFile, } from "./marker.js"; const CONFIG_ACCOUNT_FILE = "adoption-configs.json"; function baselineConfigs(toPrincipal) { return [ { deployment: "web-client-bff", key: "injected-principal", requiredValue: toPrincipal, migrated: false }, { deployment: "cli", key: "cloud-credentials+profiles", requiredValue: toPrincipal, migrated: false }, { deployment: "cli", key: "SEMA_LIVE_PRINCIPAL", requiredValue: toPrincipal, migrated: false }, { deployment: "env", key: "REQUIRE_PRINCIPAL", requiredValue: "true", migrated: false }, { deployment: "core-decl", key: "localOwnerRules", requiredValue: "withdrawn", migrated: false }, ]; } function readConfigAccount(root) { let raw; try { raw = readFileSync(join(root, CONFIG_ACCOUNT_FILE), "utf8"); } catch (err) { if (err.code === "ENOENT") return undefined; throw err; } let parsed; try { parsed = JSON.parse(raw); } catch (err) { throw new AdoptionError("adoption_marker_corrupt", `the adoption config account in ${root} is not valid JSON (${err.message})`); } if (!isConfigAccountShape(parsed)) { throw new AdoptionError("adoption_marker_corrupt", `the adoption config account in ${root} does not carry a readable shape`); } return parsed; } function readConfigAccountEvidence(root) { try { return readConfigAccount(root); } catch (err) { if (err instanceof AdoptionError) return undefined; throw err; } } function isConfigAccountShape(v) { if (v === null || typeof v !== "object") return false; const f = v; if (f.schemaVersion !== 1 || typeof f.adoptionId !== "string" || !Array.isArray(f.configs)) return false; const finite = (n) => typeof n === "number" && Number.isFinite(n); return f.configs.every((c) => { if (c === null || typeof c !== "object") return false; const e = c; if (typeof e.deployment !== "string" || typeof e.key !== "string" || typeof e.requiredValue !== "string" || typeof e.migrated !== "boolean") { return false; } if (e.ack !== undefined) { if (e.ack === null || typeof e.ack !== "object" || !finite(e.ack.atMs)) return false; } if (e.witnessed !== undefined) { if (e.witnessed === null || typeof e.witnessed !== "object") return false; const w = e.witnessed; if (!finite(w.atMs) || w.receipt === null || typeof w.receipt !== "object") return false; const r = w.receipt; if (r.adoptionId !== f.adoptionId || r.deployment !== e.deployment || r.key !== e.key || r.observedValue !== e.requiredValue || !finite(r.atMs)) { return false; } } return true; }); } function writeConfigAccount(root, account) { atomicWriteFile(join(root, "tmp"), join(root, CONFIG_ACCOUNT_FILE), JSON.stringify(account, null, 2)); } function configIdentity(c) { return JSON.stringify([c.deployment, c.key]); } function upsertConfigAccount(root, adoptionId, toPrincipal, additional) { const existing = readConfigAccount(root); if (existing !== undefined && existing.adoptionId === adoptionId) { const known = new Set(existing.configs.map(configIdentity)); let grew = false; for (const c of additional) { if (!known.has(configIdentity(c))) { existing.configs.push({ ...c }); known.add(configIdentity(c)); grew = true; } } if (grew) writeConfigAccount(root, existing); return; } const merged = new Map(); for (const c of baselineConfigs(toPrincipal)) merged.set(configIdentity(c), c); for (const c of additional) merged.set(configIdentity(c), c); writeConfigAccount(root, { schemaVersion: 1, adoptionId, configs: [...merged.values()] }); } function outstandingOf(account) { if (account === undefined) return []; return account.configs.filter((c) => c.witnessed === undefined).map((c) => `${c.deployment}:${c.key}`); } export function ackAdoptionConfig(root, deployment, key, now) { const account = readConfigAccount(root); const entry = account?.configs.find((c) => c.deployment === deployment && c.key === key); if (account === undefined || entry === undefined) { throw new AdoptionError("adoption_witness_mismatch", `no adoption config account entry for ${deployment}:${key} in ${root}`); } entry.ack = { atMs: (now ?? Date.now)() }; writeConfigAccount(root, account); } export function witnessAdoptionConfig(root, receipt) { const account = readConfigAccount(root); const entry = account?.configs.find((c) => c.deployment === receipt.deployment && c.key === receipt.key); if (account === undefined || entry === undefined) { throw new AdoptionError("adoption_witness_mismatch", `no adoption config account entry for ${receipt.deployment}:${receipt.key} in ${root}`); } if (receipt.adoptionId !== account.adoptionId) { throw new AdoptionError("adoption_witness_mismatch", `the witness receipt names adoption "${receipt.adoptionId}" but this root's adoption is "${account.adoptionId}" — a witness binds to the adoption it observed`); } if (typeof receipt.atMs !== "number" || !Number.isFinite(receipt.atMs)) { throw new AdoptionError("adoption_witness_mismatch", `the witness receipt carries an invalid timestamp (${String(receipt.atMs)}) — refusing to record evidence the account reader would reject`); } if (receipt.observedValue !== entry.requiredValue) { throw new AdoptionError("adoption_witness_mismatch", `the witness for ${receipt.deployment}:${receipt.key} observed "${receipt.observedValue}" but the adoption requires "${entry.requiredValue}" — refusing to clear the account on a value that would leave the consumer locked out`); } entry.witnessed = { atMs: receipt.atMs, receipt }; writeConfigAccount(root, account); } const QUARANTINE_DIR = "adoption-quarantine"; export function listAdoptionQuarantine(root) { const base = join(root, QUARANTINE_DIR); let stores; try { stores = readdirSync(base); } catch (err) { if (err.code === "ENOENT") return []; throw err; } const out = []; for (const store of stores) { let names; try { names = readdirSync(join(base, store)); } catch { continue; } for (const name of names) out.push({ store, name, path: join(base, store, name) }); } return out; } function quarantineRow(root, store, name, bytes) { const dir = join(root, QUARANTINE_DIR, sanitizeScope(store)); ensureDir(dir); const base = sanitizeScope(name); let target = join(dir, base); for (let i = 2; existsSync(target); i += 1) { if (readFileSync(target, "utf8") === bytes) return; target = join(dir, `${base}.${i}`); } atomicWriteFile(join(root, "tmp"), target, bytes); } function rewriteSessionPolicyRows(root, fromPrincipal, toPrincipal) { const dir = join(root, "session-policy"); let files; try { files = readdirSync(dir); } catch (err) { if (err.code === "ENOENT") return 0; throw err; } const tmpDir = join(dir, "tmp"); let rows = 0; for (const file of files) { if (!file.endsWith(".json") || file.endsWith(SESSION_POLICY_MARK_SUFFIX)) continue; const source = join(dir, file); let raw; try { raw = readFileSync(source, "utf8"); } catch (err) { if (err.code === "ENOENT") continue; throw err; } const judged = judgeSessionPolicyRowObject(raw); const row = "row" in judged ? judged.row : undefined; const { owner } = attributeSessionPolicyRow(dir, file, row); if (owner === undefined) continue; if (owner.principal !== fromPrincipal) continue; const stem = sanitizeScope(JSON.stringify([owner.sessionId, toPrincipal])); const rewritten = row !== undefined ? JSON.stringify({ ...row, __principal: toPrincipal }) : raw; const target = join(dir, `${stem}.json`); if (existsSync(target)) { if (readFileSync(target, "utf8") === rewritten) { removeIfPresent(source); rows += 1; continue; } throw new AdoptionError("adoption_row_collision", `a session-policy row for session "${owner.sessionId}" already exists under "${toPrincipal}" with different content — ` + `merging two existing rows is a sync join, not a rewrite; the adoption marker is left in place for inspection`); } atomicWriteFile(tmpDir, target, rewritten); removeIfPresent(source); rows += 1; } for (const file of files) { if (file.endsWith(SESSION_POLICY_MARK_SUFFIX)) carrySessionPolicyMark(dir, tmpDir, file, fromPrincipal, toPrincipal); } return rows; } function carrySessionPolicyMark(dir, tmpDir, file, fromPrincipal, toPrincipal) { const source = join(dir, file); const mark = readMarkOrRefuse(source); if (mark === null) return; if (mark.__principal !== fromPrincipal) return; if (typeof mark.__sid !== "string") return; const target = join(dir, `${sanitizeScope(JSON.stringify([mark.__sid, toPrincipal]))}${SESSION_POLICY_MARK_SUFFIX}`); const there = readMarkOrRefuse(target); const merged = there === null ? mark.__hwm : Math.max(mark.__hwm, there.__hwm); const mergedGen = Math.max(mark.__gen ?? 0, there?.__gen ?? 0); atomicWriteFile(tmpDir, target, JSON.stringify({ ...mark, __principal: toPrincipal, __hwm: merged, __gen: mergedGen })); removeIfPresent(source); } function readMarkOrRefuse(path) { const read = readSessionPolicyMark(path); if ("corrupt" in read) { throw new SessionPolicyError("corrupt", `session rules high-water mark ${read.corrupt.reason}: ${path} — refusing rather than restart this key's rev from zero. Deleting that file is the repair, and it gives up the number it was holding.`); } return read.mark; } function removeIfPresent(path) { try { unlinkSync(path); } catch (err) { if (err.code !== "ENOENT") throw err; } } const ZERO_ACTION_STORES = [ "session", "checkpoint", "tool-result", "file-snapshot", "memory", "memory-engine", "task-list", "mailbox", "workflow-run", "workflow-journal", "background-agent", ]; const SESSION_POLICY_LEG = "session-policy"; const CARRIAGE_BIT_PREFIX = "carriage:"; function sameSource(a, b) { return a.kind === "principal" ? b.kind === "principal" && a.principal === b.principal : b.kind === "local-owner"; } function sourceText(o) { return o.kind === "principal" ? `principal "${o.principal}"` : "the local owner"; } function receiptFromTerminal(root, adopted) { const account = readConfigAccountEvidence(root); const accountBinds = account !== undefined && account.adoptionId === adopted.immutableReport.adoptionId; return { status: "adopted", immutableReport: adopted.immutableReport, current: { outstandingConfigs: accountBinds ? outstandingOf(account) : adopted.immutableReport.affectedDeploymentConfigs.map((c) => `${c.deployment}:${c.key}`), quarantined: listAdoptionQuarantine(root).length, }, }; } function rebuildConfigAccountIfUnbound(root, report) { const account = readConfigAccountEvidence(root); if (account !== undefined && account.adoptionId === report.adoptionId) return; writeConfigAccount(root, { schemaVersion: 1, adoptionId: report.adoptionId, configs: report.affectedDeploymentConfigs.map((c) => ({ ...c })), }); } export function readAdoptionStatus(root) { const f = readRootAdoptionFile(root); if (f === undefined) return { state: "none" }; if ("marker" in f) { return { state: "in-flight", from: f.marker.from, toPrincipal: f.marker.toPrincipal, phase: f.marker.phase }; } return { state: "adopted", receipt: receiptFromTerminal(root, f.adopted) }; } function answerFromExisting(root, existing, from, toPrincipal) { if (existing === undefined) return undefined; if ("adopted" in existing) { if (existing.adopted.toPrincipal === toPrincipal && sameSource(existing.adopted.from, from)) { return receiptFromTerminal(root, existing.adopted); } throw new AdoptionError("adoption_retarget", `this data root already carries a completed adoption (${sourceText(existing.adopted.from)} → "${existing.adopted.toPrincipal}") — ` + `a second adoption of the same root is a multi-tenant transfer, not a shape this protocol supports`); } if (existing.marker.toPrincipal !== toPrincipal || !sameSource(existing.marker.from, from)) { throw new AdoptionError("adoption_in_flight_mismatch", `an adoption toward "${existing.marker.toPrincipal}" is already in flight in this data root (phase ${existing.marker.phase}) — ` + `refusing to start a different one (resume the original, or repair the marker by hand)`); } return undefined; } export async function adoptLocalDataRoot(opts) { if (typeof opts.toPrincipal !== "string" || opts.toPrincipal === "") { throw new AdoptionError("adoption_bad_request", "adoptLocalDataRoot requires the adopting principal — adoption is the act of giving this data root an identity"); } if (opts.from.kind === "principal" && (typeof opts.from.principal !== "string" || opts.from.principal === "")) { throw new AdoptionError("adoption_bad_request", "a principal-form source requires a non-empty principal — local-single-user identity is the local-owner kind, never an empty string"); } if (opts.from.kind === "principal" && opts.from.principal === opts.toPrincipal) { throw new AdoptionError("adoption_bad_request", `the data root already belongs to "${opts.toPrincipal}" — there is nothing to adopt`); } if (typeof opts.credentials.ref !== "string" || opts.credentials.ref === "") { throw new AdoptionError("adoption_bad_request", "the credentials claim ref must be a non-empty reference (the claim is what makes the new identity redeemable)"); } if (opts.from === null || typeof opts.from !== "object" || opts.credentials === null || typeof opts.credentials !== "object") { throw new AdoptionError("adoption_bad_request", "adoptLocalDataRoot requires `from` and `credentials` objects"); } if (opts.additionalConfigs !== undefined && !Array.isArray(opts.additionalConfigs)) { throw new AdoptionError("adoption_bad_request", "additionalConfigs must be an array when supplied"); } if (opts.carriage !== undefined && !Array.isArray(opts.carriage)) { throw new AdoptionError("adoption_bad_request", "carriage must be an array when supplied"); } if (opts.rules !== undefined && (opts.rules === null || typeof opts.rules !== "object")) { throw new AdoptionError("adoption_bad_request", "rules must be an object when supplied"); } if (opts.now !== undefined && typeof opts.now !== "function") { throw new AdoptionError("adoption_bad_request", "`now` must be callable when supplied — it publishes the terminal timestamp"); } if (opts.onError !== undefined && typeof opts.onError !== "function") { throw new AdoptionError("adoption_bad_request", "`onError` must be callable when supplied"); } if (opts.from.kind !== "local-owner" && opts.from.kind !== "principal") { throw new AdoptionError("adoption_bad_request", "the adoption source must be the local-owner kind or a named principal"); } if (opts.credentials.issuedBy !== "server") { throw new AdoptionError("adoption_bad_request", `the credentials claim must be server-issued (got issuedBy: ${JSON.stringify(opts.credentials.issuedBy)}) — the server mints the new identity`); } for (const c of opts.additionalConfigs ?? []) { if (c === null || typeof c !== "object" || typeof c.deployment !== "string" || c.deployment === "" || typeof c.key !== "string" || c.key === "" || typeof c.requiredValue !== "string" || typeof c.migrated !== "boolean") { throw new AdoptionError("adoption_bad_request", `a malformed additionalConfigs entry (${JSON.stringify(c)}) — each entry is { deployment, key, requiredValue: strings; migrated: boolean }`); } } if (opts.rules !== undefined && (typeof opts.rules.dir !== "string" || opts.rules.dir === "" || typeof opts.rules.transport !== "function")) { throw new AdoptionError("adoption_bad_request", "a rules leg needs a non-empty bucket directory and a transport function"); } { const seen = new Set(); for (const leg of opts.carriage ?? []) { if (leg === null || typeof leg !== "object" || typeof leg.store !== "string" || leg.store === "" || typeof leg.run !== "function") { throw new AdoptionError("adoption_bad_request", "a carriage leg is { store: non-empty string; run: function }"); } if (seen.has(leg.store)) { throw new AdoptionError("adoption_bad_request", `two carriage legs share the store name "${leg.store}" — a leg's plan identity is its store family, one leg per store`); } seen.add(leg.store); } } ensureDir(opts.root); const pre = answerFromExisting(opts.root, readRootAdoptionFile(opts.root), opts.from, opts.toPrincipal); if (pre !== undefined) { const account = readConfigAccountEvidence(opts.root); if (account !== undefined && account.adoptionId === pre.immutableReport.adoptionId) return pre; } const engineLock = new BootLock(join(opts.root, "LOCK")); try { engineLock.acquire(); } catch (err) { throw new AdoptionError("adoption_locked", `a live instance owns this data root — stop the engine before adopting: ${err.message}`); } const adoptionLock = new BootLock(join(opts.root, "ADOPTION-LOCK")); try { adoptionLock.acquire(); } catch (err) { engineLock.release(); throw new AdoptionError("adoption_locked", `another adoption owns this data root: ${err.message}`); } try { const existing = readRootAdoptionFile(opts.root); const answered = answerFromExisting(opts.root, existing, opts.from, opts.toPrincipal); if (answered !== undefined) { rebuildConfigAccountIfUnbound(opts.root, answered.immutableReport); return receiptFromTerminal(opts.root, { from: answered.immutableReport.from, toPrincipal: answered.immutableReport.toPrincipal, atMs: answered.immutableReport.atMs, immutableReport: answered.immutableReport, }); } const now = opts.now ?? Date.now; const offeredRulesDir = opts.rules !== undefined ? resolve(opts.rules.dir) : undefined; const offeredCarriage = (opts.carriage ?? []).map((l) => l.store); let phase; let adoptionId; let legBits; let plan; if (existing !== undefined && "marker" in existing) { phase = existing.marker.phase; adoptionId = existing.marker.adoptionId; legBits = existing.marker.legs ?? {}; plan = existing.marker.plan; const missing = []; if (plan.rulesDir !== undefined && offeredRulesDir !== plan.rulesDir) { missing.push(`the permission-rule leg over "${plan.rulesDir}"${offeredRulesDir !== undefined ? ` (offered "${offeredRulesDir}")` : ""}`); } const offered = new Set(offeredCarriage); for (const store of plan.carriage) if (!offered.has(store)) missing.push(`the "${store}" carriage leg`); if (plan.credentialsRef !== opts.credentials.ref) missing.push(`the credentials claim (recorded "${plan.credentialsRef}")`); if (missing.length > 0) { throw new AdoptionError("adoption_plan_mismatch", `this resume supplies less than the adoption's recorded plan — missing: ${missing.join("; ")}. ` + `Re-run with the original legs (growing the plan is fine, shrinking it is not), or repair the marker by hand.`); } const lateAdds = []; if (plan.rulesDir === undefined && offeredRulesDir !== undefined) { if (phase < 3) plan = { ...plan, rulesDir: offeredRulesDir }; else lateAdds.push(`the permission-rule leg (stage ③ already completed at phase ${phase})`); } const knownCarriage = new Set(plan.carriage); const newCarriage = offeredCarriage.filter((s) => !knownCarriage.has(s)); if (newCarriage.length > 0) { if (phase < 5) plan = { ...plan, carriage: [...plan.carriage, ...newCarriage] }; else lateAdds.push(`the ${newCarriage.map((s) => `"${s}"`).join("/")} carriage leg(s) (stage ⑤ already completed)`); } if (lateAdds.length > 0) { throw new AdoptionError("adoption_plan_mismatch", `this resume offers legs whose stage has already completed — ${lateAdds.join("; ")}. ` + `They would never run, and reporting them as done would be a lie; post-adoption carriage rides each store's normal channel.`); } if (plan !== existing.marker.plan) { publishMarker(opts.root, adoptionId, opts.from, opts.toPrincipal, phase, plan, legBits); } const accountInFlight = readConfigAccount(opts.root); if (accountInFlight === undefined || accountInFlight.adoptionId !== adoptionId) { throw new AdoptionError("adoption_marker_corrupt", `the adoption config account is ${accountInFlight === undefined ? "missing" : "bound to a different adoption"} while an adoption is in flight — ` + `it lands before the marker and never disappears mid-arc; restore it before resuming`); } upsertConfigAccount(opts.root, adoptionId, opts.toPrincipal, opts.additionalConfigs ?? []); } else { adoptionId = `adp_${randomBytes(8).toString("hex")}`; phase = 2; legBits = {}; plan = { ...(offeredRulesDir !== undefined ? { rulesDir: offeredRulesDir } : {}), carriage: offeredCarriage, credentialsRef: opts.credentials.ref }; upsertConfigAccount(opts.root, adoptionId, opts.toPrincipal, opts.additionalConfigs ?? []); publishMarker(opts.root, adoptionId, opts.from, opts.toPrincipal, 2, plan, legBits); } const legs = []; if (phase < 3) { if (opts.rules !== undefined) { let nested; try { nested = await adoptFilePermissionRuleStore({ dir: opts.rules.dir, from: opts.from, toPrincipal: opts.toPrincipal, transport: opts.rules.transport, ...(opts.now !== undefined ? { now: opts.now } : {}), ...(opts.onError !== undefined ? { onError: opts.onError } : {}), }); } catch (err) { if (err instanceof AdoptionError) throw err; throw new AdoptionError("adoption_rule_leg_refused", `the permission-rule leg refused: ${thrownText(err)}`); } if (nested.status === "stalled") { return { status: "stalled", phase: 2, error: `the permission-rule leg stalled (its own marker holds phase ${nested.phase}): ${nested.error}`, }; } } if (legBits[SESSION_POLICY_LEG]?.done !== true) { const rows = rewriteSessionPolicyRows(opts.root, opts.from.kind === "principal" ? opts.from.principal : null, opts.toPrincipal); legBits = { ...legBits, [SESSION_POLICY_LEG]: { done: true, rows } }; publishMarker(opts.root, adoptionId, opts.from, opts.toPrincipal, 2, plan, legBits); } publishMarker(opts.root, adoptionId, opts.from, opts.toPrincipal, 3, plan, legBits); phase = 3; } if (phase < 4) { publishMarker(opts.root, adoptionId, opts.from, opts.toPrincipal, 4, plan, legBits); phase = 4; } if (phase < 5) { for (const leg of opts.carriage ?? []) { if (legBits[`${CARRIAGE_BIT_PREFIX}${leg.store}`]?.done === true) continue; let quarantined = 0; const ctx = { quarantine: (name, bytes) => { quarantineRow(opts.root, leg.store, name, bytes); quarantined += 1; }, }; let rows; try { const res = await leg.run(ctx); rows = res === undefined ? undefined : res.rows; } catch (err) { return { status: "stalled", phase: 4, error: `the "${leg.store}" carriage leg failed: ${thrownText(err)} — resume when it is healthy`, }; } if (rows !== undefined && (!Number.isSafeInteger(rows) || rows < 0)) { return { status: "stalled", phase: 4, error: `the "${leg.store}" carriage leg reported an invalid row count (${String(rows)}) — a leg reports a non-negative integer or nothing; fix the leg and resume`, }; } legBits = { ...legBits, [`${CARRIAGE_BIT_PREFIX}${leg.store}`]: { done: true, ...(rows !== undefined ? { rows } : {}), ...(quarantined > 0 ? { quarantined } : {}), }, }; publishMarker(opts.root, adoptionId, opts.from, opts.toPrincipal, 4, plan, legBits); } publishMarker(opts.root, adoptionId, opts.from, opts.toPrincipal, 5, plan, legBits); phase = 5; } if (plan.rulesDir !== undefined) legs.push({ store: "permission-rule", action: "bucket-rebind" }); legs.push({ store: SESSION_POLICY_LEG, action: "row-rewrite", rows: legBits[SESSION_POLICY_LEG]?.rows ?? 0 }); const carried = Object.entries(legBits) .filter(([k]) => k.startsWith(CARRIAGE_BIT_PREFIX)) .map(([k, bit]) => ({ store: k.slice(CARRIAGE_BIT_PREFIX.length), action: "carried", ...(bit.rows !== undefined ? { rows: bit.rows } : {}), ...(bit.quarantined !== undefined ? { quarantined: bit.quarantined } : {}), })); legs.push(...carried); const carriedNames = new Set(carried.map((l) => l.store)); for (const store of ZERO_ACTION_STORES) { if (!carriedNames.has(store)) legs.push({ store, action: "none" }); } legs.push({ store: "usage-window", action: "reset" }); const account = readConfigAccount(opts.root); const atMs = now(); if (!Number.isSafeInteger(atMs) || atMs < 0) { return { status: "stalled", phase: 5, error: `the clock returned an invalid timestamp (${String(atMs)}) — refusing to publish a terminal record the reader would reject; fix the injected clock and resume`, }; } const immutableReport = { adoptionId, from: opts.from, toPrincipal: opts.toPrincipal, atMs, credentials: opts.credentials, affectedDeploymentConfigs: (account?.configs ?? []).map(({ deployment, key, requiredValue, migrated }) => ({ deployment, key, requiredValue, migrated })), legs, notMigratedByDesign: NOT_MIGRATED_BY_DESIGN.map((e) => ({ ...e })), }; writeRootAdoptionFile(opts.root, { schemaVersion: 1, adopted: { from: opts.from, toPrincipal: opts.toPrincipal, atMs: immutableReport.atMs, immutableReport }, }); return receiptFromTerminal(opts.root, { from: opts.from, toPrincipal: opts.toPrincipal, atMs: immutableReport.atMs, immutableReport }); } finally { adoptionLock.release(); engineLock.release(); } } function publishMarker(root, adoptionId, from, toPrincipal, phase, plan, legs) { writeRootAdoptionFile(root, { schemaVersion: 1, marker: { adoptionId, from, toPrincipal, phase, plan, ...(Object.keys(legs).length > 0 ? { legs } : {}) }, }); }