fix: tighten evidence artifact guarantees
This commit is contained in:
@@ -230,14 +230,20 @@ function evidenceDocumentation(
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
const evidenceVariables = variables.filter(({ role }) => role === "EVIDENCE");
|
const evidenceVariables = variables.filter(({ role }) => role === "EVIDENCE");
|
||||||
|
const requiredVariables = evidenceVariables.filter(({ suffix }) => suffix !== "SESSION_TOKEN_FILE");
|
||||||
|
const optionalVariables = evidenceVariables.filter(({ suffix }) => suffix === "SESSION_TOKEN_FILE");
|
||||||
return [
|
return [
|
||||||
...common,
|
...common,
|
||||||
...details,
|
...details,
|
||||||
`- Maximum chunk characters: \`${policy.max_chunk_chars}\``,
|
`- Maximum chunk characters: \`${policy.max_chunk_chars}\``,
|
||||||
`- Retained published generations: \`${policy.retain_published_generations}\``,
|
`- Retained published generations: \`${policy.retain_published_generations}\``,
|
||||||
...(evidenceVariables.length === 0 ? [] : [
|
...(requiredVariables.length === 0 ? [] : [
|
||||||
"- Required installation file variables:",
|
"- Required installation file variables:",
|
||||||
...evidenceVariables.map(({ name }) => ` - \`${name}\``),
|
...requiredVariables.map(({ name }) => ` - \`${name}\``),
|
||||||
|
]),
|
||||||
|
...(optionalVariables.length === 0 ? [] : [
|
||||||
|
"- Optional installation file variables:",
|
||||||
|
...optionalVariables.map(({ name }) => ` - \`${name}\``),
|
||||||
]),
|
]),
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -615,6 +615,24 @@ test("real publish create/update, pull, list, and read preserve a complete Evide
|
|||||||
baseCommit: createdRevision.commit, baseBlob: createdRevision.blob,
|
baseCommit: createdRevision.commit, baseBlob: createdRevision.blob,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
expect(update.statusCode).toBe(200);
|
||||||
|
await realGit(fixture.author, ["pull", "--ff-only", "origin", "main"]);
|
||||||
|
const remotelyEdited = validateCanonicalWorkspace({
|
||||||
|
...updated,
|
||||||
|
evidence: {
|
||||||
|
...updated.evidence,
|
||||||
|
policy: { max_chunk_chars: 9_001, retain_published_generations: 9 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
writeFileSync(
|
||||||
|
join(fixture.author, "workspaces", "research-clinical.yaml"),
|
||||||
|
serializeWorkspaceYaml(remotelyEdited),
|
||||||
|
);
|
||||||
|
await realGit(fixture.author, ["add", "workspaces/research-clinical.yaml"]);
|
||||||
|
await realGit(fixture.author, ["commit", "-m", "Remote Evidence-only descriptor edit"]);
|
||||||
|
await realGit(fixture.author, ["push", "origin", "main"]);
|
||||||
|
const remoteCommit = await realGit(fixture.author, ["rev-parse", "HEAD"]);
|
||||||
|
|
||||||
const pull = await fixture.app.inject({ method: "POST", url: "/workspace-registry/pull" });
|
const pull = await fixture.app.inject({ method: "POST", url: "/workspace-registry/pull" });
|
||||||
const list = await fixture.app.inject({ method: "GET", url: "/workspaces" });
|
const list = await fixture.app.inject({ method: "GET", url: "/workspaces" });
|
||||||
const read = await fixture.app.inject({ method: "GET", url: "/workspaces/research-clinical" });
|
const read = await fixture.app.inject({ method: "GET", url: "/workspaces/research-clinical" });
|
||||||
@@ -623,10 +641,12 @@ test("real publish create/update, pull, list, and read preserve a complete Evide
|
|||||||
expect(create.statusCode).toBe(200);
|
expect(create.statusCode).toBe(200);
|
||||||
expect(update.statusCode).toBe(200);
|
expect(update.statusCode).toBe(200);
|
||||||
expect(pull.statusCode).toBe(200);
|
expect(pull.statusCode).toBe(200);
|
||||||
|
expect(pull.json().head).toBe(remoteCommit);
|
||||||
expect(list.statusCode).toBe(200);
|
expect(list.statusCode).toBe(200);
|
||||||
expect(list.json().find(({ id }: { id: string }) => id === "research-clinical").workspace).toEqual(updated);
|
expect(list.json().find(({ id }: { id: string }) => id === "research-clinical").workspace)
|
||||||
|
.toEqual(remotelyEdited);
|
||||||
expect(read.statusCode).toBe(200);
|
expect(read.statusCode).toBe(200);
|
||||||
expect(read.json().workspace).toEqual(updated);
|
expect(read.json().workspace).toEqual(remotelyEdited);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("real route reports a safe field for an Evidence-only concurrent edit", async () => {
|
test("real route reports a safe field for an Evidence-only concurrent edit", async () => {
|
||||||
@@ -697,11 +717,18 @@ test.each([
|
|||||||
label: "inline S3 credential field",
|
label: "inline S3 credential field",
|
||||||
source: { type: "s3", uri: "s3://clinical-evidence/published/", access_key: SECRET_CANARY },
|
source: { type: "s3", uri: "s3://clinical-evidence/published/", access_key: SECRET_CANARY },
|
||||||
},
|
},
|
||||||
])("real validate rejects $label without echoing it", async ({ source }) => {
|
])("real publish rejects $label without echoing it or changing HEAD", async ({ source }) => {
|
||||||
const fixture = await createRealRouteFixture();
|
const fixture = await createRealRouteFixture();
|
||||||
|
await fixture.registry.bootstrap();
|
||||||
|
const base = await fixture.registry.read("psd-clinical");
|
||||||
|
const invalid = structuredClone(base.workspace) as any;
|
||||||
|
invalid.evidence = { source };
|
||||||
const response = await fixture.app.inject({
|
const response = await fixture.app.inject({
|
||||||
method: "POST", url: "/workspaces/validate",
|
method: "POST", url: "/workspaces/publish",
|
||||||
payload: { workspace: { ...workspace, evidence: { source } } },
|
payload: {
|
||||||
|
action: "update", workspace: invalid,
|
||||||
|
baseCommit: base.revision.commit, baseBlob: base.revision.blob,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(response.statusCode).toBe(400);
|
expect(response.statusCode).toBe(400);
|
||||||
|
|||||||
@@ -1013,13 +1013,17 @@ test("snapshots canonical Evidence artifacts at the active commit without copyin
|
|||||||
const committedDescriptor = parseWorkspaceYaml(await gitOutput(remote.source, [
|
const committedDescriptor = parseWorkspaceYaml(await gitOutput(remote.source, [
|
||||||
"show", `${remote.initialCommit}:workspaces/psd-clinical.yaml`,
|
"show", `${remote.initialCommit}:workspaces/psd-clinical.yaml`,
|
||||||
])) as CanonicalWorkspace;
|
])) as CanonicalWorkspace;
|
||||||
|
const committedBlob = await gitOutput(remote.source, [
|
||||||
|
"rev-parse", `${remote.initialCommit}:workspaces/psd-clinical.yaml`,
|
||||||
|
]);
|
||||||
|
expect(active.revision.blob).toBe(committedBlob);
|
||||||
expect(expectedFiles["psd-clinical.yaml"]).toBe(serializeWorkspaceYaml(committedDescriptor));
|
expect(expectedFiles["psd-clinical.yaml"]).toBe(serializeWorkspaceYaml(committedDescriptor));
|
||||||
expect(readdirSync(snapshotDirectory).sort()).toEqual([
|
expect(readdirSync(snapshotDirectory).sort()).toEqual([
|
||||||
"psd-clinical.env.example", "psd-clinical.md", "psd-clinical.yaml", "snapshot.json",
|
"psd-clinical.env.example", "psd-clinical.md", "psd-clinical.yaml", "snapshot.json",
|
||||||
]);
|
]);
|
||||||
expect(manifest.head).toBe(remote.initialCommit);
|
expect(manifest.head).toBe(remote.initialCommit);
|
||||||
expect(manifest.revisions[0]).toMatchObject({
|
expect(manifest.revisions[0]).toMatchObject({
|
||||||
id: "psd-clinical", commit: remote.initialCommit, blob: active.revision.blob,
|
id: "psd-clinical", commit: remote.initialCommit, blob: committedBlob,
|
||||||
});
|
});
|
||||||
expect(Object.keys(manifest.files).sort()).toEqual(Object.keys(expectedFiles).sort());
|
expect(Object.keys(manifest.files).sort()).toEqual(Object.keys(expectedFiles).sort());
|
||||||
for (const [name, contents] of Object.entries(expectedFiles)) {
|
for (const [name, contents] of Object.entries(expectedFiles)) {
|
||||||
|
|||||||
@@ -444,6 +444,25 @@ test.each(evidenceSources)("renders deterministic public Evidence docs for $labe
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("documents the S3 session token file as optional", () => {
|
||||||
|
const descriptor = parseWorkspaceYaml(
|
||||||
|
`${renderWorkspaceWithoutEvidence()}evidence:
|
||||||
|
source: { type: s3, uri: s3://clinical-evidence/published/, credentials: static_files }
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
const markdown = renderWorkspaceDocs(descriptor).markdown;
|
||||||
|
const required = markdown.slice(
|
||||||
|
markdown.indexOf("- Required installation file variables:"),
|
||||||
|
markdown.indexOf("- Optional installation file variables:"),
|
||||||
|
);
|
||||||
|
const optional = markdown.slice(markdown.indexOf("- Optional installation file variables:"));
|
||||||
|
|
||||||
|
expect(required).toContain("EVIDENCE_ACCESS_KEY_FILE");
|
||||||
|
expect(required).toContain("EVIDENCE_SECRET_KEY_FILE");
|
||||||
|
expect(required).not.toContain("EVIDENCE_SESSION_TOKEN_FILE");
|
||||||
|
expect(optional).toContain("EVIDENCE_SESSION_TOKEN_FILE");
|
||||||
|
});
|
||||||
|
|
||||||
test("documents same-revision filesystem ownership without claiming P1 materialization", () => {
|
test("documents same-revision filesystem ownership without claiming P1 materialization", () => {
|
||||||
const descriptor = parseWorkspaceYaml(
|
const descriptor = parseWorkspaceYaml(
|
||||||
`${renderWorkspaceWithoutEvidence()}evidence:\n source: { type: filesystem, uri: workspace-content/psd-clinical/evidence }\n`,
|
`${renderWorkspaceWithoutEvidence()}evidence:\n source: { type: filesystem, uri: workspace-content/psd-clinical/evidence }\n`,
|
||||||
|
|||||||
Reference in New Issue
Block a user