import assert from 'node:assert/strict' import { createHash } from 'node:crypto' import { chmod, lstat, mkdtemp, mkdir, readFile, readdir, readlink, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import test from 'node:test' import { DeploymentManager, DeploymentResolutionError } from '../bootstrap/lib/deployments.mjs' import { PlatformGarbageCollector } from '../bootstrap/lib/gc.mjs' import { canonicalJson } from '../lib/canonical-json.mjs' import { deriveImageBuildId, deriveRecordId, parseDeploymentRecord, parseImageInventory, recordsFromImageInventory, } from '../lib/deployment-contracts.mjs' import { PlatformPaths, preparePersistentLayout, resetRuntimeLayout } from '../lib/paths.mjs' import { hashTree } from '../lib/tree-hash.mjs' import { buildRuntime } from '../../control-plane/modules/patch-manager/index.mjs' const kinds = ['environment', 'pristine', 'runtime', 'system-plugins'] async function fixture({ root, paths, authority = 'stable', targetSequence = 1, marker = 'image', } = {}) { root ??= await mkdtemp(join(tmpdir(), 'dsh-deployments-')) paths ??= new PlatformPaths(join(root, 'data'), join(root, 'run')) const seedRoot = join(root, `seed-${marker}`) const assets = {} for (const kind of kinds) { const plural = kind === 'environment' ? 'environments' : kind === 'runtime' ? 'runtimes' : kind const id = `image-${kind}-${marker}` const path = join(seedRoot, plural, id) await mkdir(path, { recursive: true }) await writeFile(join(path, 'sentinel'), `${kind}:${marker}`) assets[kind] = { id, sha256: await hashTree(path) } } const content = { schema: 1, authority, platformRevision: `deployment-fixture-${marker}`, targetSequence, bootstrapApi: 1, updateApi: 1, bootstrap: { version: '1.0.0', id: 'bootstrap', sha256: 'a'.repeat(64) }, deployment: { id: `image-deployment-${marker}`, dshVersion: '0.1.0-rc.1', environmentVersion: '1.0.0', environment: assets.environment, pristine: assets.pristine, runtime: assets.runtime, systemPlugins: assets['system-plugins'], }, } const inventory = parseImageInventory({ ...content, imageBuildId: deriveImageBuildId(content) }) await preparePersistentLayout(paths) await resetRuntimeLayout(paths) const manager = new DeploymentManager({ paths, seedRoot, inventory }) return { root, seedRoot, paths, inventory, manager, image: recordsFromImageInventory(inventory).deployment } } async function repairableFixture() { const root = await mkdtemp(join(tmpdir(), 'dsh-runtime-reset-')) const paths = new PlatformPaths(join(root, 'data'), join(root, 'run')) const seedRoot = join(root, 'seed') const pristineRoot = join(seedRoot, 'pristine', 'dsh') const environmentRoot = join(seedRoot, 'environments', 'environment') const runtimeRoot = join(seedRoot, 'runtimes', 'dsh') const systemPluginsRoot = join(seedRoot, 'system-plugins', 'environment') await mkdir(join(pristineRoot, 'lib'), { recursive: true }) await mkdir(join(environmentRoot, 'artifacts'), { recursive: true }) await mkdir(systemPluginsRoot, { recursive: true }) await writeFile(join(pristineRoot, 'lib', 'bin.js'), '#!/usr/bin/env node\n') const patch = [ "import { readFile, writeFile } from 'node:fs/promises'", "import { join } from 'node:path'", "export async function applyPatch(root) { await writeFile(join(root, 'patched.txt'), 'patched\\n') }", "export async function verifyPatch(root) { if (await readFile(join(root, 'patched.txt'), 'utf8') !== 'patched\\n') throw new Error('patch missing') }", '', ].join('\n') const patchBytes = Buffer.from(patch) const patchSha256 = createHash('sha256').update(patchBytes).digest('hex') await writeFile(join(environmentRoot, 'artifacts', 'runtime-patch'), patchBytes) await writeFile(join(environmentRoot, 'environment.manifest.json'), JSON.stringify({ schema: 1, manifestType: 'environment', version: '1.0.0', keyringGeneration: 1, targetSequence: 1, issuedAt: '2026-08-20T00:00:00.000Z', artifacts: [{ id: 'runtime-patch', mediaType: 'text/javascript', sha256: patchSha256, size: patchBytes.byteLength, url: 'https://example.invalid/runtime-patch', }], bootstrapApi: 1, components: [], patches: [{ id: 'runtime-patch', sha256: patchSha256 }], systemPlugins: [], })) await buildRuntime({ pristineRoot, versionsRoot: join(seedRoot, 'runtimes'), runtimeId: 'dsh', patchPaths: [join(environmentRoot, 'artifacts', 'runtime-patch')], }) const assets = { environment: { id: 'environment', sha256: await hashTree(environmentRoot) }, pristine: { id: 'dsh', sha256: await hashTree(pristineRoot) }, runtime: { id: 'dsh', sha256: await hashTree(runtimeRoot) }, systemPlugins: { id: 'environment', sha256: await hashTree(systemPluginsRoot) }, } const content = { schema: 1, authority: 'development', platformRevision: 'runtime-reset-fixture', targetSequence: 0, bootstrapApi: 1, updateApi: 1, bootstrap: { version: '1.0.0', id: 'bootstrap', sha256: 'a'.repeat(64) }, deployment: { id: 'image-deployment-runtime-reset', dshVersion: '0.1.0-rc.1', environmentVersion: '1.0.0', ...assets, }, } const inventory = parseImageInventory({ ...content, imageBuildId: deriveImageBuildId(content) }) await preparePersistentLayout(paths) await resetRuntimeLayout(paths) const manager = new DeploymentManager({ paths, seedRoot, inventory }) const image = recordsFromImageInventory(inventory).deployment await manager.initialize(image) return { root, paths, seedRoot, manager, image, environmentRoot } } async function managedRecord( context, suffix, sequence = 2, authority = 'stable', dshVersion = `0.1.0-rc.${String(sequence)}`, receiptTokens = [], ) { const references = {} for (const kind of kinds) { const root = kind === 'environment' ? context.paths.environmentsRoot : kind === 'pristine' ? context.paths.pristineRoot : kind === 'runtime' ? context.paths.runtimesRoot : context.paths.systemPluginsRoot const id = `managed-${kind}-${suffix}` const path = join(root, id) await mkdir(path, { recursive: true }) await writeFile(join(path, 'sentinel'), `${kind}:${suffix}`) references[kind] = { storage: 'store', kind, id, sha256: await hashTree(path) } } const content = { schema: 1, authority, targetSequence: sequence, dshVersion, environmentVersion: '1.0.0', environment: references.environment, pristine: references.pristine, runtime: references.runtime, systemPlugins: references['system-plugins'], receiptTokens, snapshotId: null, } return parseDeploymentRecord({ ...content, id: deriveRecordId('deployment-record', content) }) } async function experimentalRecord(context, from, suffix, dshVersion, receiptTokens = []) { const built = await managedRecord(context, suffix, from.targetSequence, 'experimental', dshVersion, receiptTokens) const content = { ...built, environmentVersion: from.environmentVersion, environment: from.environment, systemPlugins: from.systemPlugins, } delete content.id return parseDeploymentRecord({ ...content, id: deriveRecordId('deployment-record', content) }) } test('initializes an Image Deployment through one atomic runtime view', async () => { const context = await fixture() const state = await context.manager.initialize(context.image) assert.equal(state.current, context.image.id) assert.equal(state.previous, null) assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:image') assert.match(await readlink(context.paths.deploymentView), new RegExp(`${context.image.id}$`)) assert.equal( await readlink(join(context.paths.viewsRoot, 'system-plugins')), join('..', 'system-plugin-views', 'current'), ) assert.equal( await readlink(join(context.paths.systemPluginViewsRoot, 'current')), join(context.paths.deploymentView, 'system-plugins'), ) assert.equal((await context.manager.selected()).record.id, context.image.id) const status = await context.manager.publishStatus() assert.equal(status.platformLayout, 1) assert.equal(status.imageBaseline.imageBuildId, context.inventory.imageBuildId) assert.equal(status.current.recordId, context.image.id) assert.equal(status.current.source, 'image') assert.equal(status.recoveryMode, null) }) test('rebuilds image and managed Runtime bytes without changing versions or previous Deployment', async () => { const context = await repairableFixture() let pauses = 0 let restarts = 0 const reset = () => context.manager.resetCurrentRuntime({ pauseDsh: async () => { pauses += 1 }, restartDsh: async () => { restarts += 1 assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'package', 'patched.txt'), 'utf8'), 'patched\n') }, }) const first = await reset() assert.notEqual(first.recordId, context.image.id) assert.equal(first.slots.previous, null) const repaired = await context.manager.record(first.recordId) assert.equal(repaired.runtime.storage, 'store') assert.equal(repaired.dshVersion, context.image.dshVersion) assert.equal(repaired.environmentVersion, context.image.environmentVersion) assert.deepEqual(await readdir(context.paths.runtimesRoot), [repaired.runtime.id]) const materialized = await context.manager.materializeCurrent() assert.equal(materialized.runtime.storage, 'store') assert.notEqual(materialized.id, repaired.id) assert.equal(materialized.runtime.id, repaired.runtime.id) assert.equal((await context.manager.state()).previous, null) const managedRuntime = join(context.paths.runtimesRoot, materialized.runtime.id) await writeFile(join(managedRuntime, 'package', 'patched.txt'), 'corrupt-again\n') const second = await reset() assert.equal(second.recordId, materialized.id) assert.equal(second.slots.previous, null) assert.equal(await hashTree(managedRuntime), materialized.runtime.sha256) assert.equal(pauses, 2) assert.equal(restarts, 2) await writeFile(join(managedRuntime, 'package', 'patched.txt'), 'runtime-before-failed-reset\n') let failedResetRestarts = 0 await assert.rejects(context.manager.resetCurrentRuntime({ pauseDsh: async () => { pauses += 1 }, restartDsh: async () => { failedResetRestarts += 1 const content = await readFile(join(context.paths.viewsRoot, 'runtime', 'package', 'patched.txt'), 'utf8') if (failedResetRestarts === 1) { assert.equal(content, 'patched\n') throw new Error('repaired Runtime failed to start') } assert.equal(content, 'runtime-before-failed-reset\n') }, }), /repaired Runtime failed to start/) assert.equal(failedResetRestarts, 2) assert.equal(await readFile(join(managedRuntime, 'package', 'patched.txt'), 'utf8'), 'runtime-before-failed-reset\n') assert.deepEqual(await context.manager.state(), second.slots) await writeFile(join(context.paths.environmentsRoot, materialized.environment.id, 'artifacts', 'runtime-patch'), 'corrupt artifact\n') await assert.rejects(reset(), /differs from (?:its Record|the Environment Manifest)/) assert.equal(pauses, 3) assert.equal(restarts, 2) }) test('updates a runtime operation without replacing deployment identity fields', async () => { const context = await fixture() await context.manager.initialize(context.image) const before = await context.manager.publishStatus({ recoveryMode: 'diagnostic-state' }) const restarting = await context.manager.setOperation('restarting') assert.deepEqual(restarting, { ...before, operation: 'restarting' }) const ready = await context.manager.setOperation(null) assert.deepEqual(ready, before) }) test('commits a complete managed Deployment only after candidate health succeeds', async () => { const context = await fixture() await context.manager.initialize(context.image) const candidate = await context.manager.writeRecord(await managedRecord(context, 'next')) let observed const state = await context.manager.activate(candidate.id, async () => { observed = await Promise.all(kinds.map(kind => readFile(join(context.paths.deploymentView, kind, 'sentinel'), 'utf8'))) }) assert.deepEqual(observed, kinds.map(kind => `${kind}:next`)) assert.equal(state.current, candidate.id) assert.equal(state.previous, context.image.id) }) test('restores the prior complete view and leaves slots unchanged when health fails', async () => { const context = await fixture() const before = await context.manager.initialize(context.image) const candidate = await context.manager.writeRecord(await managedRecord(context, 'broken')) await assert.rejects(context.manager.activate(candidate.id, async () => { const value = await readFile(join(context.paths.deploymentView, 'runtime', 'sentinel'), 'utf8') if (value === 'runtime:broken') throw new Error('candidate unhealthy') }), /candidate unhealthy/) assert.deepEqual(await context.manager.state(), before) assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:image') }) test('rejects modified managed content and stale Image References', async () => { const context = await fixture() const candidate = await context.manager.writeRecord(await managedRecord(context, 'tampered')) await writeFile(join(context.paths.runtimesRoot, candidate.runtime.id, 'sentinel'), 'changed') await assert.rejects(context.manager.prepareView(candidate.id), /content hash differs/) await context.manager.writeRecord(context.image) const changedContent = { ...context.inventory.document, platformRevision: 'new-image' } delete changedContent.imageBuildId const changedInventory = parseImageInventory({ ...changedContent, imageBuildId: deriveImageBuildId(changedContent) }) const changedManager = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: changedInventory }) await assert.rejects(changedManager.prepareView(context.image.id), /different image/) }) test('writes immutable Deployment Record bytes', async () => { const context = await fixture() await context.manager.writeRecord(context.image) assert.deepEqual( await readFile(context.manager.recordPath(context.image.id)), canonicalJson(context.image), ) }) test('materializes an Image Deployment as a complete Managed previous state', async () => { const context = await fixture() await context.manager.initialize(context.image) const materialized = await context.manager.materializeCurrent() assert.notEqual(materialized.id, context.image.id) assert.equal(materialized.dshVersion, context.image.dshVersion) for (const field of ['environment', 'pristine', 'runtime', 'systemPlugins']) { assert.equal(materialized[field].storage, 'store') const resolved = await context.manager.resolveReference(materialized[field]) assert.equal((await lstat(resolved)).isDirectory(), true) } assert.equal((await context.manager.state()).current, materialized.id) }) test('advances to a newer image only after startup acceptance', async () => { const context = await fixture() await context.manager.initialize(context.image) const nextContent = { ...context.inventory.document, platformRevision: 'deployment-fixture-next', targetSequence: 2, } delete nextContent.imageBuildId const nextInventory = parseImageInventory({ ...nextContent, imageBuildId: deriveImageBuildId(nextContent) }) const nextRecord = recordsFromImageInventory(nextInventory).deployment const restarted = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: nextInventory }) const plan = await restarted.prepareImage(nextRecord) assert.equal(plan.action, 'image-forward') assert.equal((await restarted.state()).current, context.image.id) const state = await restarted.acceptImage(plan) assert.equal(state.current, nextRecord.id) assert.equal(state.previous, context.image.id) }) test('does not advertise a rollback to assets owned by another Docker image', async () => { const first = await fixture({ targetSequence: 1, marker: 'rollback-first' }) await first.manager.initialize(first.image) const second = await fixture({ root: first.root, paths: first.paths, targetSequence: 2, marker: 'rollback-second', }) const plan = await second.manager.prepareImage(second.image) await second.manager.acceptImage(plan) const rollback = await second.manager.rollbackPlan() assert.equal(rollback.current.id, second.image.id) assert.equal(rollback.previous, null) }) test('selects the prior Deployment directly after an explicit Docker image rollback', async () => { const first = await fixture({ targetSequence: 1, marker: 'docker-rollback-first' }) await first.manager.initialize(first.image) const second = await fixture({ root: first.root, paths: first.paths, targetSequence: 2, marker: 'docker-rollback-second', }) await second.manager.acceptImage(await second.manager.prepareImage(second.image)) const rolledBack = new DeploymentManager({ paths: first.paths, seedRoot: first.seedRoot, inventory: first.inventory, }) const rollback = await rolledBack.prepareImage(first.image) assert.equal(rollback.action, 'image-rollback') assert.equal(rollback.target, first.image.id) await rolledBack.acceptImage(rollback) assert.equal((await rolledBack.state()).current, first.image.id) }) test('rejects an unresolvable newer image candidate and keeps the valid current Deployment', async () => { const current = await fixture({ targetSequence: 1, marker: 'current' }) await current.manager.initialize(current.image) const managed = await current.manager.materializeCurrent() const candidateContent = { ...current.inventory.document, platformRevision: 'deployment-fixture-candidate-missing', targetSequence: 2, } delete candidateContent.imageBuildId const inventory = parseImageInventory({ ...candidateContent, imageBuildId: deriveImageBuildId(candidateContent), }) const candidate = recordsFromImageInventory(inventory).deployment await rm(join(current.seedRoot, 'runtimes', inventory.deployment.runtime.id), { recursive: true }) const manager = new DeploymentManager({ paths: current.paths, seedRoot: current.seedRoot, inventory }) const plan = await manager.prepareImage(candidate) assert.equal(plan.action, 'image-rejected') assert.equal(plan.target, managed.id) assert.match(plan.candidateError, /ENOENT/) assert.equal((await manager.selected()).record.id, managed.id) assert.equal((await manager.state()).current, managed.id) }) test('commits previous only after an invalid current resolves and previous receipts activate', async () => { const context = await fixture() await context.manager.initialize(context.image) const previous = await managedRecord(context, 'previous-valid', 2, 'stable', '0.1.0-rc.2', ['receipt-previous']) const current = await managedRecord(context, 'current-invalid', 3, 'stable', '0.1.0-rc.3', ['receipt-current']) await context.manager.activateManaged(previous, { healthCheck: async () => {}, activateReceipts: async () => {} }) await context.manager.activateManaged(current, { healthCheck: async () => {}, activateReceipts: async () => {} }) await rm(join(context.paths.runtimesRoot, current.runtime.id), { recursive: true }) const manager = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: context.inventory }) await assert.rejects(manager.prepareImage(context.image), DeploymentResolutionError) const plan = await manager.preparePreviousRecovery() assert.equal((await manager.selected()).record.id, previous.id) assert.deepEqual(await manager.state(), { schema: 1, generation: 4, current: current.id, previous: previous.id }) const activations = [] await manager.acceptPreviousRecovery(plan, async tokens => { activations.push(tokens) }) assert.deepEqual(activations, [['receipt-previous']]) assert.deepEqual(await manager.state(), { schema: 1, generation: 5, current: previous.id, previous: current.id }) }) test('finishes automatic previous recovery after interruption between receipts and slots', async () => { const context = await fixture() await context.manager.initialize(context.image) const previous = await managedRecord(context, 'recovery-interrupted-previous', 2, 'stable', '0.1.0-rc.2', ['receipt-previous']) const current = await managedRecord(context, 'recovery-interrupted-current', 3, 'stable', '0.1.0-rc.3', ['receipt-current']) await context.manager.activateManaged(previous, { healthCheck: async () => {}, activateReceipts: async () => {} }) await context.manager.activateManaged(current, { healthCheck: async () => {}, activateReceipts: async () => {} }) const manager = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: context.inventory }) const plan = await manager.preparePreviousRecovery() manager.commit = async () => { throw new Error('simulated interruption before slots commit') } await assert.rejects( manager.acceptPreviousRecovery(plan, async tokens => assert.deepEqual(tokens, ['receipt-previous'])), /simulated interruption/, ) assert.equal((await manager.activation()).phase, 'receipts-active') assert.equal((await manager.state()).current, current.id) const restarted = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: context.inventory }) const recovered = await restarted.recoverActivation({ activeReceipts: async () => ({ receipts: [{ token: 'receipt-previous' }] }), activate: async () => { throw new Error('active previous must be completed') }, }) assert.deepEqual(recovered, { action: 'committed', recordId: previous.id }) assert.deepEqual(await restarted.state(), { schema: 1, generation: 5, current: previous.id, previous: current.id }) assert.equal(await restarted.activation(), undefined) }) test('does not automatically downgrade an unparseable current Deployment Record', async () => { const context = await fixture() await context.manager.initialize(context.image) const previous = await managedRecord(context, 'record-valid-previous', 2) const current = await managedRecord(context, 'record-corrupt-current', 3) await context.manager.activateManaged(previous, { healthCheck: async () => {}, activateReceipts: async () => {} }) await context.manager.activateManaged(current, { healthCheck: async () => {}, activateReceipts: async () => {} }) await writeFile(context.manager.recordPath(current.id), '{invalid') const manager = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: context.inventory }) await assert.rejects(manager.prepareImage(context.image), error => { assert.equal(error instanceof DeploymentResolutionError, false) assert.match(error.message, /valid JSON/) return true }) await assert.rejects(manager.preparePreviousRecovery(), /valid JSON/) assert.deepEqual(await manager.state(), { schema: 1, generation: 4, current: current.id, previous: previous.id }) }) test('keeps a newer managed Deployment when the image is behind', async () => { const context = await fixture() await context.manager.initialize(context.image) const managed = await context.manager.writeRecord(await managedRecord(context, 'ahead', 3)) await context.manager.activate(managed.id, async () => {}) const plan = await context.manager.prepareImage(context.image) assert.equal(plan.action, 'retain') assert.equal(plan.imageBehindCurrent, true) assert.equal(plan.target, managed.id) }) test('rejects same-sequence Stable content conflicts', async () => { const context = await fixture() await context.manager.initialize(context.image) const conflicting = await context.manager.writeRecord(await managedRecord(context, 'conflict', 1)) await context.manager.activate(conflicting.id, async () => {}) await assert.rejects(context.manager.prepareImage(context.image), /same targetSequence/) }) test('prefers a same-sequence image when the managed Environment differs only by file mode', async () => { const context = await fixture() await context.manager.initialize(context.image) const managed = await context.manager.materializeCurrent() const environmentPath = await context.manager.resolveReference(managed.environment) await chmod(join(environmentPath, 'sentinel'), 0o444) const content = { ...managed, environment: { ...managed.environment, sha256: await hashTree(environmentPath) }, } delete content.id const current = await context.manager.writeRecord({ ...content, id: deriveRecordId('deployment-record', content), }) await context.manager.commit(current.id, null) const plan = await context.manager.prepareImage(context.image) assert.equal(plan.action, 'prefer-image') assert.equal(plan.target, context.image.id) }) test('rejects a same-sequence image when the managed Environment content differs', async () => { const context = await fixture() await context.manager.initialize(context.image) const managed = await context.manager.materializeCurrent() const environmentPath = await context.manager.resolveReference(managed.environment) await writeFile(join(environmentPath, 'sentinel'), 'different environment content') const content = { ...managed, environment: { ...managed.environment, sha256: await hashTree(environmentPath) }, } delete content.id const current = await context.manager.writeRecord({ ...content, id: deriveRecordId('deployment-record', content), }) await context.manager.commit(current.id, null) await assert.rejects(context.manager.prepareImage(context.image), /same targetSequence/) }) test('replaces a rebuilt development image without retaining stale image slots', async () => { const first = await fixture({ authority: 'development', targetSequence: 0, marker: 'development-one' }) await first.manager.initialize(first.image) const rebuilt = await fixture({ root: first.root, paths: first.paths, authority: 'development', targetSequence: 0, marker: 'development-two', }) const plan = await rebuilt.manager.prepareImage(rebuilt.image) assert.equal(plan.action, 'development-refresh') assert.equal(plan.fallback, null) assert.equal(await readFile(join(rebuilt.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:development-two') const state = await rebuilt.manager.acceptImage(plan) assert.equal(state.current, rebuilt.image.id) assert.equal(state.previous, null) }) test('replaces stale formal Image Deployment slots when starting a development image', async () => { const formal = await fixture({ authority: 'stable', targetSequence: 11, marker: 'formal-eleven' }) await formal.manager.initialize(formal.image) const development = await fixture({ root: formal.root, paths: formal.paths, authority: 'development', targetSequence: 0, marker: 'local-rebuild', }) const plan = await development.manager.prepareImage(development.image) assert.equal(plan.action, 'development-refresh') assert.equal(plan.fallback, null) const state = await development.manager.acceptImage(plan) assert.equal(state.current, development.image.id) assert.equal(state.previous, null) assert.equal(await readFile(join(development.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:local-rebuild') }) test('replaces stale Managed Deployment assets when starting a compatible development image', async () => { const formal = await fixture({ authority: 'stable', targetSequence: 11, marker: 'formal-eleven' }) await formal.manager.initialize(formal.image) const managed = await formal.manager.writeRecord(await managedRecord( formal, 'managed-eleven', 11, 'stable', '0.1.0-rc.1', )) await formal.manager.activate(managed.id, async () => {}) const development = await fixture({ root: formal.root, paths: formal.paths, authority: 'development', targetSequence: 0, marker: 'local-managed-refresh', }) const plan = await development.manager.prepareImage(development.image) assert.equal(plan.action, 'development-refresh') assert.equal(plan.fallback, null) const state = await development.manager.acceptImage(plan) assert.equal(state.current, development.image.id) assert.equal(state.previous, null) assert.equal( await readFile(join(development.paths.viewsRoot, 'system-plugins', 'sentinel'), 'utf8'), 'system-plugins:local-managed-refresh', ) }) test('preserves Experimental DSH until a Stable image catches up', async () => { const context = await fixture() await context.manager.initialize(context.image) const experimental = await context.manager.writeRecord(await managedRecord( context, 'experimental', 1, 'experimental', '0.1.0-rc.3', )) await context.manager.activate(experimental.id, async () => {}) const behindDshContent = { ...context.inventory.document, platformRevision: 'stable-environment-forward', targetSequence: 2, } delete behindDshContent.imageBuildId const behindDshInventory = parseImageInventory({ ...behindDshContent, imageBuildId: deriveImageBuildId(behindDshContent), }) const environmentForward = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: behindDshInventory, }) const retained = await environmentForward.prepareImage(recordsFromImageInventory(behindDshInventory).deployment) assert.equal(retained.target, experimental.id) assert.equal(retained.requiresExperimentalRebuild, true) const caughtUpContent = structuredClone(behindDshContent) caughtUpContent.platformRevision = 'stable-caught-up' caughtUpContent.deployment.dshVersion = '0.1.0-rc.3' const caughtUpInventory = parseImageInventory({ ...caughtUpContent, imageBuildId: deriveImageBuildId(caughtUpContent), }) const caughtUpManager = new DeploymentManager({ paths: context.paths, seedRoot: context.seedRoot, inventory: caughtUpInventory, }) const caughtUp = await caughtUpManager.prepareImage(recordsFromImageInventory(caughtUpInventory).deployment) assert.equal(caughtUp.action, 'stable-caught-up') assert.notEqual(caughtUp.target, experimental.id) }) test('activates receipts and commits one complete Managed Deployment transaction', async () => { const context = await fixture() await context.manager.initialize(context.image) const candidate = await managedRecord(context, 'transaction', 2, 'stable', '0.1.0-rc.2', ['candidate-receipt']) let active = [] const trust = { activate: async tokens => { active = [...tokens] }, activeReceipts: async () => ({ receipts: active.map(token => ({ token })) }), } const slots = await context.manager.activateManaged(candidate, { healthCheck: async () => { assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:transaction') }, activateReceipts: tokens => trust.activate(tokens), }) assert.equal(slots.current, candidate.id) assert.deepEqual(active, ['candidate-receipt']) const previous = await context.manager.record(slots.previous) assert.equal(previous.runtime.storage, 'store') assert.equal(await context.manager.activation(), undefined) }) test('rolls back only the exact previous Deployment with receipts and health checks', async () => { const context = await fixture() await context.manager.initialize(context.image) const candidate = await managedRecord(context, 'rollback-target', 2, 'stable', '0.1.0-rc.2', ['candidate-receipt']) const active = [] await context.manager.activateManaged(candidate, { healthCheck: async () => {}, activateReceipts: async tokens => active.push([...tokens]), }) const before = await context.manager.state() const previous = await context.manager.record(before.previous) let healthChecks = 0 const rolledBack = await context.manager.rollback({ healthCheck: async () => { healthChecks += 1 assert.equal(JSON.parse(await readFile(context.paths.deploymentStatusPath, 'utf8')).operation, 'recovering') }, activateReceipts: async tokens => active.push([...tokens]), }) assert.equal(rolledBack.current, previous.id) assert.equal(rolledBack.previous, candidate.id) assert.deepEqual(active.at(-1), previous.receiptTokens) assert.equal(healthChecks, 1) assert.equal(await context.manager.activation(), undefined) const status = await context.manager.publishStatus() assert.equal(status.current.recordId, previous.id) assert.equal(status.operation, null) }) test('reports an image behind a newly activated Managed Deployment immediately', async () => { const context = await fixture() await context.manager.initialize(context.image) const candidate = await managedRecord(context, 'status-ahead', 2, 'stable', '0.1.0-rc.2') await context.manager.activateManaged(candidate, { healthCheck: async () => {}, activateReceipts: async () => {}, }) const status = await context.manager.publishStatus() assert.equal(status.current.recordId, candidate.id) assert.equal(status.imageBehindCurrent, true) }) test('restores the materialized previous Deployment when receipt activation fails', async () => { const context = await fixture() await context.manager.initialize(context.image) const candidate = await managedRecord(context, 'receipt-failure', 2, 'stable', '0.1.0-rc.2', ['candidate-receipt']) await assert.rejects(context.manager.activateManaged(candidate, { healthCheck: async () => {}, activateReceipts: async () => { throw new Error('receipt activation failed') }, }), /receipt activation failed/) const state = await context.manager.state() assert.notEqual(state.current, context.image.id) assert.equal((await context.manager.record(state.current)).runtime.storage, 'store') assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:image') assert.equal(await context.manager.activation(), undefined) }) test('publishes switching and recovering states around a failed atomic activation', async () => { const context = await fixture() await context.manager.initialize(context.image) await context.manager.publishStatus() const candidate = await managedRecord(context, 'operation-status', 2, 'stable', '0.1.0-rc.2') const observed = [] await assert.rejects(context.manager.activateManaged(candidate, { healthCheck: async () => { observed.push(JSON.parse(await readFile(context.paths.deploymentStatusPath, 'utf8')).operation) if (observed.length === 1) throw new Error('candidate failed') }, activateReceipts: async () => {}, }), /candidate failed/) assert.deepEqual(observed, ['switching', 'recovering']) assert.equal(JSON.parse(await readFile(context.paths.deploymentStatusPath, 'utf8')).operation, null) }) test('turns a failed image recovery operation into an explicit recovery failure', async () => { const context = await fixture() await context.manager.initialize(context.image) await context.manager.publishStatus({ recoveryMode: 'current deployment failed' }) let operation await assert.rejects(context.manager.recoverImageBaseline(context.image, { healthCheck: async () => { const status = JSON.parse(await readFile(context.paths.deploymentStatusPath, 'utf8')) operation = status.operation assert.equal(status.recoveryMode, 'current deployment failed') throw new Error('image recovery health failed') }, activateReceipts: async () => {}, }), /image recovery health failed/) assert.equal(operation, 'recovering') const failed = JSON.parse(await readFile(context.paths.deploymentStatusPath, 'utf8')) assert.equal(failed.operation, null) assert.equal(failed.recoveryMode, 'image recovery health failed') }) test('finishes a journaled activation after receipts became active before restart', async () => { const context = await fixture() await context.manager.initialize(context.image) const from = await context.manager.materializeCurrent() const candidate = await context.manager.writeRecord(await managedRecord( context, 'resume', 2, 'stable', '0.1.0-rc.2', ['candidate-receipt'], )) await context.manager.writeActivation({ phase: 'healthy', from: from.id, to: candidate.id }) const recovered = await context.manager.recoverActivation({ activeReceipts: async () => ({ receipts: [{ token: 'candidate-receipt' }] }), activate: async () => { throw new Error('active candidate must be completed') }, }) assert.deepEqual(recovered, { action: 'committed', recordId: candidate.id }) assert.equal((await context.manager.state()).current, candidate.id) assert.equal(await context.manager.activation(), undefined) }) test('keeps Experimental candidate slots uncommitted through probation and supports cancellation', async () => { const context = await fixture() await context.manager.initialize(context.image) const candidate = await experimentalRecord( context, context.image, 'probation', '0.1.0-rc.2', ['experimental-receipt'], ) await context.manager.stageCandidate(candidate, async () => { assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:probation') }) const during = await context.manager.state() assert.notEqual(during.current, candidate.id) assert.equal((await context.manager.activation()).phase, 'probation') const cancelled = await context.manager.cancelCandidate() assert.equal(cancelled.cancelled, true) assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:image') assert.equal(await context.manager.activation(), undefined) }) test('rejects rollback and cross-authority candidates at the Bootstrap boundary', async () => { const context = await fixture() await context.manager.initialize(context.image) const advanced = await managedRecord(context, 'advanced', 3) await context.manager.activateManaged(advanced, { healthCheck: async () => {}, activateReceipts: async () => {} }) const rollback = await managedRecord(context, 'rollback', 2) await assert.rejects(context.manager.activateManaged(rollback, { healthCheck: async () => {}, activateReceipts: async () => {}, }), /roll back/) const wrongExperimental = await managedRecord(context, 'wrong-environment', 3, 'experimental', '0.1.0-rc.4') await assert.rejects(context.manager.stageCandidate(wrongExperimental, async () => {}), /retain the current Environment/) }) test('does not restart previous DSH before snapshot recovery after candidate health failure', async () => { const context = await fixture() await context.manager.initialize(context.image) const candidate = await experimentalRecord(context, context.image, 'health-failure', '0.1.0-rc.2') let healthCalls = 0 await assert.rejects(context.manager.stageCandidate(candidate, async () => { healthCalls += 1 throw new Error('candidate failed health') }), /candidate failed health/) assert.equal(healthCalls, 1) assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:image') }) test('collects only Store assets and records outside slots, transactions, Holds, and snapshots', async () => { const context = await fixture() await context.manager.initialize(context.image) const current = await context.manager.writeRecord(await managedRecord(context, 'current', 2)) await context.manager.activateManaged(current, { healthCheck: async () => {}, activateReceipts: async () => {}, }) const orphan = await context.manager.writeRecord(await managedRecord(context, 'orphan', 3)) const held = await context.manager.writeRecord(await managedRecord( context, 'held', 4, 'experimental', '0.1.0-rc.held', )) await writeFile(join(context.paths.updaterStateRoot, 'channel.json'), JSON.stringify({ schema: 1, updateChannel: 'experimental', holds: [{ id: 'hold', type: 'version', dshVersion: held.dshVersion, environmentVersion: null, reason: 'fixture', createdAt: '2026-08-19T00:00:00.000Z', }], experimentalBlocked: null, })) await mkdir(join(context.paths.snapshotsRoot, 'versions', 'snapshot-kept'), { recursive: true }) await mkdir(join(context.paths.snapshotsRoot, 'versions', 'snapshot-orphan'), { recursive: true }) await writeFile(join(context.paths.updaterStateRoot, 'transaction.json'), JSON.stringify({ from: { runtime: current.id }, to: { runtime: current.id }, snapshotId: 'snapshot-kept', })) await writeFile(join(context.paths.downloadsRoot, 'disposable'), 'cache') await mkdir(context.paths.systemSkillCatalogsRoot, { recursive: true }) await writeFile(join(context.paths.systemSkillCatalogsRoot, 'catalog-marker'), 'retained') const removedSnapshots = [] const result = await new PlatformGarbageCollector({ paths: context.paths, deployments: context.manager, snapshots: { remove: async id => { removedSnapshots.push(id) await rm(join(context.paths.snapshotsRoot, 'versions', id), { recursive: true, force: true }) return true }, }, }).collect() assert.equal(result.deployments.records.includes(orphan.id), true) assert.equal(result.deployments.records.includes(held.id), false) await assert.rejects(lstat(context.manager.recordPath(orphan.id)), { code: 'ENOENT' }) assert.equal((await lstat(context.manager.recordPath(held.id))).isFile(), true) await assert.rejects(lstat(join(context.paths.runtimesRoot, orphan.runtime.id)), { code: 'ENOENT' }) assert.equal((await lstat(join(context.paths.runtimesRoot, held.runtime.id))).isDirectory(), true) assert.equal((await lstat(join(context.paths.snapshotsRoot, 'versions', 'snapshot-kept'))).isDirectory(), true) assert.deepEqual(removedSnapshots, ['snapshot-orphan']) await assert.rejects(lstat(join(context.paths.snapshotsRoot, 'versions', 'snapshot-orphan')), { code: 'ENOENT' }) await assert.rejects(lstat(join(context.paths.downloadsRoot, 'disposable')), { code: 'ENOENT' }) assert.equal(await readFile(join(context.paths.systemSkillCatalogsRoot, 'catalog-marker'), 'utf8'), 'retained') }) test('explicit recovery replaces an invalid Managed current with the exact Image Baseline', async () => { const context = await fixture() await context.manager.initialize(context.image) const managed = await managedRecord(context, 'invalid-managed', 3) await context.manager.activateManaged(managed, { healthCheck: async () => {}, activateReceipts: async () => {} }) let activated const state = await context.manager.recoverImageBaseline(context.image, { healthCheck: async () => { assert.equal(await readFile(join(context.paths.viewsRoot, 'runtime', 'sentinel'), 'utf8'), 'runtime:image') }, activateReceipts: async tokens => { activated = tokens }, }) assert.equal(state.current, context.image.id) assert.equal(state.previous, managed.id) assert.deepEqual(activated, []) }) test('explicit recovery repairs only the exact image Record after its persisted bytes are damaged', async () => { const context = await fixture() await context.manager.initialize(context.image) const managed = await managedRecord(context, 'managed-before-repair', 3) await context.manager.activateManaged(managed, { healthCheck: async () => {}, activateReceipts: async () => {} }) await writeFile(context.manager.recordPath(context.image.id), '{"damaged":true}\n') const state = await context.manager.recoverImageBaseline(context.image, { healthCheck: async () => {}, activateReceipts: async () => {}, }) assert.equal(state.current, context.image.id) assert.deepEqual(await context.manager.record(context.image.id), context.image) await assert.rejects(context.manager.repairImageRecord(managed), /differs from the current image inventory/) })