Skip to content

Commit f70f85b

Browse files
committed
test: prove interrupted metadata publication fails closed
1 parent 2b3d08d commit f70f85b

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

tests/recovery.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,47 @@ describe("live daemon registry recovery", () => {
201201
expect(metadata(root, name).lastAttachAt).toBe(mutated.lastAttachAt);
202202
});
203203

204+
it("fails closed when metadata publication stops after revision advancement", () => {
205+
const root = makeRoot();
206+
const name = "interrupted-revision";
207+
startProvider(root, name);
208+
const before = metadata(root, name);
209+
const snapshot = writeSnapshot(root, name, before);
210+
const mutated: SessionMetadata = {
211+
...before,
212+
tags: { role: "must-not-publish" },
213+
};
214+
215+
expect(() => writeMetadata(name, mutated, {
216+
afterRecoveryRevisionPublished: () => {
217+
throw new Error("stop before metadata publication");
218+
},
219+
})).toThrow("stop before metadata publication");
220+
221+
// Publication stopped in the exact revision-before-metadata window: the
222+
// old metadata remains visible, but its signed revision is no longer
223+
// authoritative.
224+
expect(metadata(root, name)).toEqual(before);
225+
const advanced = readBoundedJson<RecoveryRevision>(
226+
recoveryRevisionPath(root, name),
227+
);
228+
expect(verifyRecoveryRevision(before.recovery!.secret, advanced)).toBe(true);
229+
expect(advanced.metadataRevision).toBe(metadataRevision(mutated));
230+
expect(advanced.metadataRevision).not.toBe(before.recovery!.metadataRevision);
231+
232+
unlinkRegistry(root, name);
233+
for (let attempt = 0; attempt < 2; attempt++) {
234+
const refused = run(root, ["recover", name, "--snapshot", snapshot]);
235+
expect(refused.status).not.toBe(0);
236+
expect(fs.existsSync(path.join(root, `${name}.sock`))).toBe(false);
237+
expect(fs.existsSync(path.join(root, `${name}.pid`))).toBe(false);
238+
expect(fs.existsSync(path.join(root, `${name}.json`))).toBe(false);
239+
expect(readBoundedJson<RecoveryRevision>(
240+
recoveryRevisionPath(root, name),
241+
)).toEqual(advanced);
242+
}
243+
}, 20_000);
244+
204245
it("rebinds the original daemon while preserving provider and attached client", async () => {
205246
const root = makeRoot();
206247
const name = "positive";

0 commit comments

Comments
 (0)