refactor: remove workspace revision state consumers

This commit is contained in:
2026-08-10 21:44:57 +02:00
parent fa24f43fd4
commit ab315c2130
3 changed files with 25 additions and 8 deletions
+3 -2
View File
@@ -141,7 +141,7 @@ import { readFile, realpath, stat } from "node:fs/promises";
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
import { spawnSync } from "node:child_process";
const [root,readPath,publishPath,snapshots,checkout,output,renderer]=process.argv.slice(2);
const HEX40=/^[0-9a-f]{40}$/,HEX64=/^[0-9a-f]{64}$/;
const HEX40=/^[0-9a-f]{40}$/,HEX64=/^[0-9a-f]{64}$/,REVISION_KEYS=["blob","commit","id","snapshotPath"];
const bounded=async(path,label="saved response")=>{let s;try{s=await stat(path);}catch{throw new Error(label+" is missing or unbounded");}if(!s.isFile()||s.size<2||s.size>1048576)throw new Error(label+" is missing or unbounded");let v;try{v=JSON.parse(await readFile(path,"utf8"));}catch{throw new Error(label+" is malformed JSON");}return v;};
const boundedBytes=async(path)=>{let s;try{s=await stat(path);}catch{throw new Error("saved snapshot is missing or unbounded");}if(!s.isFile()||s.size<2||s.size>1048576)throw new Error("saved snapshot is missing or unbounded");return await readFile(path);};
const read=await bounded(readPath),published=await bounded(publishPath);const revision=read?.revision,commit=revision?.commit,snapshot=revision?.snapshotPath,publishedCommit=published?.head??published?.revision?.commit;
@@ -154,7 +154,8 @@ if(manifest?.head!==commit||!files||typeof files!=="object"||Array.isArray(files
const expected=files[id+".yaml"];if(!HEX64.test(expected??""))throw new Error("snapshot manifest digest is invalid");
const snapshotBytes=await boundedBytes(canonical);if(createHash("sha256").update(snapshotBytes).digest("hex")!==expected)throw new Error("snapshot bytes differ from manifest digest");
const entry=Array.isArray(revisions)?revisions.find(candidate=>candidate?.id===id):undefined;
if(!entry||!HEX40.test(entry?.blob??"")||entry.commit!==commit||typeof entry.snapshotPath!=="string"||resolve(entry.snapshotPath)!==canonical||(entry.state!=="operational"&&entry.state!=="migration_required"))throw new Error("snapshot manifest revision is invalid");
const exactEntry=entry&&typeof entry==="object"&&!Array.isArray(entry)&&Object.keys(entry).sort().every((key,index)=>key===REVISION_KEYS[index])&&Object.keys(entry).length===REVISION_KEYS.length;
if(!exactEntry||entry.id!==id||entry.commit!==commit||typeof entry.blob!=="string"||!HEX40.test(entry.blob)||entry.snapshotPath!==canonical)throw new Error("snapshot manifest revision is invalid");
if(!HEX40.test(revision?.blob??"")||revision.blob!==entry.blob)throw new Error("saved revision blob differs from snapshot manifest");
const blobCheck=spawnSync("git",["-C",checkout,"rev-parse",commit+":workspaces/"+id+".yaml"],{encoding:"utf8"});
if(blobCheck.status!==0||blobCheck.stdout.trim()!==entry.blob)throw new Error("snapshot blob differs from installed Git commit");
+21 -5
View File
@@ -436,10 +436,16 @@ test("generated render command binds snapshot bytes to the commit manifest and G
const readPath=join(run.root,"responses/read-p1-filesystem.json"),pullPath=join(run.root,"responses/pull.json"),script=join(run.root,"commands/render-1.sh"),script2=join(run.root,"commands/render-2.sh"),output=join(run.root,"rendered/runtime-1.yaml"),output2=join(run.root,"rendered/runtime-2.yaml");
const rendererStub=join(repo,"backend/scripts/p1-render-snapshot.mjs"),stubArgs=join(run.root,"rendered/stub-args.json");
await writeFile(rendererStub,`import { writeFileSync } from "node:fs";\nwriteFileSync(${JSON.stringify(stubArgs)}, JSON.stringify(process.argv.slice(2)));\n`);
const manifest=()=>({head:commit,revisions:[{id:"p1-filesystem",commit,blob,snapshotPath,state:"operational"}],files:{"p1-filesystem.yaml":snapshotSha}});
await writeFile(readPath,JSON.stringify({revision:{id:"p1-filesystem",commit,blob,snapshotPath,state:"operational"}})); await writeFile(pullPath,JSON.stringify({head:commit}));
const revision={id:"p1-filesystem",commit,blob,snapshotPath};
const manifest=(entry=revision)=>({head:commit,revisions:[entry],files:{"p1-filesystem.yaml":snapshotSha}});
await writeFile(readPath,JSON.stringify({revision})); await writeFile(pullPath,JSON.stringify({head:commit}));
await assert.rejects(execFileAsync("bash",[script],{cwd:repo}),/snapshot manifest.*(missing|unbounded)/i);
await assert.rejects(lstat(output));
const legacyRevision={...revision}; legacyRevision.state=["oper","ational"].join("");
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify(manifest(legacyRevision)));
await assert.rejects(execFileAsync("bash",[script],{cwd:repo}),/snapshot manifest revision is invalid/);
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify(manifest({...revision,unexpected:"field"})));
await assert.rejects(execFileAsync("bash",[script],{cwd:repo}),/snapshot manifest revision is invalid/);
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify(manifest()));
await execFileAsync("bash",[script],{cwd:repo});
assert.deepEqual(JSON.parse(await readFile(stubArgs,"utf8")),["--ownership",join(run.root,"ownership.json"),"--snapshot",snapshot,"--output",output,"--snapshot-sha256",snapshotSha]);
@@ -450,12 +456,22 @@ test("generated render command binds snapshot bytes to the commit manifest and G
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify({...manifest(),head:"c".repeat(40)}));
await assert.rejects(execFileAsync("bash",[script2],{cwd:repo}),/snapshot manifest identity is invalid/);
await assert.rejects(lstat(output2));
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify(manifest()));
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify({...manifest(),revisions:[{id:"p1-filesystem",commit,blob:"f".repeat(40),snapshotPath,state:"operational"}]}));
for(const malformed of [
{id:"p1-filesystem",commit,blob},
{...revision,id:"p1-http"},
{...revision,commit:"c".repeat(40)},
{...revision,blob:"f".repeat(39)},
{...revision,blob:[blob]},
{...revision,snapshotPath:join(commitDir,"wrong.yaml")},
]){
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify(manifest(malformed)));
await assert.rejects(execFileAsync("bash",[script2],{cwd:repo}),/snapshot manifest revision is invalid/);
}
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify(manifest({...revision,blob:"f".repeat(40)})));
await assert.rejects(execFileAsync("bash",[script2],{cwd:repo}),/saved revision blob differs from snapshot manifest/);
await assert.rejects(lstat(output2));
await writeFile(join(commitDir,"snapshot.json"),JSON.stringify(manifest()));
await writeFile(readPath,JSON.stringify({revision:{id:"p1-filesystem",commit,blob:"f".repeat(40),snapshotPath,state:"operational"}}));
await writeFile(readPath,JSON.stringify({revision:{...revision,blob:"f".repeat(40)}}));
await assert.rejects(execFileAsync("bash",[script2],{cwd:repo}),/saved revision blob differs/);
await assert.rejects(lstat(output2));
});
+1 -1
View File
@@ -36,7 +36,7 @@ evidence:
`);
const snapshotBytes=await readFile(snapshot); const snapshotSha256=sha256(snapshotBytes);
const manifestPath=join(dirname(snapshot),"snapshot.json");
await writeFile(manifestPath,JSON.stringify({head:commit,revisions:[{id:"p1-filesystem",commit,blob:"0".repeat(40),snapshotPath:snapshot,state:"operational"}],files:{"p1-filesystem.yaml":snapshotSha256}}));
await writeFile(manifestPath,JSON.stringify({head:commit,revisions:[{id:"p1-filesystem",commit,blob:"0".repeat(40),snapshotPath:snapshot}],files:{"p1-filesystem.yaml":snapshotSha256}}));
const env={THT_WS_P1_FILESYSTEM_DWH_TRANSPORT:"postgres_direct",THT_WS_P1_FILESYSTEM_DWH_HOST:"dwh.invalid",THT_WS_P1_FILESYSTEM_DWH_PORT:"5432",THT_WS_P1_FILESYSTEM_DWH_USER:"reader",THT_WS_P1_FILESYSTEM_DWH_PASSWORD_FILE:secret};
return {repo,root,snapshot,snapshotSha256,manifestPath,env};
}