feat(observatory): verify exact published result reuse
This commit is contained in:
@@ -323,7 +323,7 @@ test("portable LAB V1 rejects an unbound existing result projection", async () =
|
||||
authority,
|
||||
}), { status: 200 }),
|
||||
}),
|
||||
/значение изменилось|значение не поддерживается|проверяемая привязка результата/,
|
||||
/значение изменилось|значение не поддерживается|обнаружены неизвестные поля/,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -348,6 +348,76 @@ test("portable LAB V1 rejects heavyweight compatibility evidence", async () => {
|
||||
);
|
||||
});
|
||||
|
||||
function cachedPortableSetup() {
|
||||
const setup = portableSetup();
|
||||
setup.existing_results = [{
|
||||
result_id: "portable-result-001",
|
||||
result_kind: setup.run_definition.result_kind,
|
||||
relation: "exact-recorded-computation",
|
||||
access: "observatory",
|
||||
created_at_utc: "2026-09-03T00:00:00Z",
|
||||
observatory_projection_available: true,
|
||||
identity: {
|
||||
job_id: "observatory-run-001",
|
||||
source_session_id: "source-a",
|
||||
source_catalog_sha256: "a".repeat(64),
|
||||
source_bundle_sha256: "b".repeat(64),
|
||||
source_capability_manifest_sha256: "c".repeat(64),
|
||||
setup_id: setup.setup_id,
|
||||
definition_sha256: setup.run_definition.definition_sha256,
|
||||
package_sha256: "d".repeat(64),
|
||||
artifact_manifest_id: "e".repeat(64),
|
||||
},
|
||||
}];
|
||||
setup.preflight = {
|
||||
outcome: "existing", action: "open-existing",
|
||||
reason: "Точный результат проверен.", submission_allowed: false,
|
||||
existing_result_ids: [setup.existing_results[0].result_id],
|
||||
};
|
||||
return setup;
|
||||
}
|
||||
|
||||
function fetchCachedPortable(setup) {
|
||||
return fetchObservatoryPortableLaboratorySetups("source-a", {
|
||||
fetcher: async () => new Response(JSON.stringify({
|
||||
schema_version: "missioncore.observatory-portable-setup-catalog/v2",
|
||||
source_session_id: "source-a", setups: [setup], authority,
|
||||
}), { status: 200 }),
|
||||
});
|
||||
}
|
||||
|
||||
test("portable exact cached result is readable without an installed executor", async () => {
|
||||
const catalog = await fetchCachedPortable(cachedPortableSetup());
|
||||
const setup = catalog.setups[0];
|
||||
assert.equal(setup.executor.state, "not-installed");
|
||||
assert.equal(setup.preflight.outcome, "existing");
|
||||
assert.equal(setup.preflight.submissionAllowed, false);
|
||||
assert.deepEqual(setup.preflight.existingResultIds, ["portable-result-001"]);
|
||||
assert.equal(setup.preservedResults[0].access, "observatory");
|
||||
});
|
||||
|
||||
for (const [label, change] of [
|
||||
["another source", (s) => { s.existing_results[0].identity.source_session_id = "source-b"; }],
|
||||
["another setup", (s) => { s.existing_results[0].identity.setup_id = "another-profile"; }],
|
||||
["another version", (s) => { s.existing_results[0].identity.definition_sha256 = "f".repeat(64); }],
|
||||
["bad package digest", (s) => { s.existing_results[0].identity.package_sha256 = "not-a-digest"; }],
|
||||
["unavailable artifact", (s) => { s.existing_results[0].observatory_projection_available = false; }],
|
||||
["missing binding", (s) => { delete s.existing_results[0].identity; }],
|
||||
["unrelated result ID", (s) => { s.preflight.existing_result_ids = ["different-result"]; }],
|
||||
["duplicate result", (s) => {
|
||||
s.existing_results.push(s.existing_results[0]);
|
||||
s.preflight.existing_result_ids.push(s.preflight.existing_result_ids[0]);
|
||||
}],
|
||||
["contradictory action", (s) => { s.preflight.action = "check"; }],
|
||||
["cached but queueable", (s) => { s.preflight.submission_allowed = true; }],
|
||||
]) {
|
||||
test(`portable cached result rejects ${label}`, async () => {
|
||||
const setup = cachedPortableSetup();
|
||||
change(setup);
|
||||
await assert.rejects(fetchCachedPortable(setup));
|
||||
});
|
||||
}
|
||||
|
||||
test("Observatory preflight sends the exact selected definition and never submits a run", async () => {
|
||||
const selected = (await fetchObservatoryLaboratorySetups("source-a", {
|
||||
fetcher: async () => new Response(JSON.stringify({
|
||||
|
||||
Reference in New Issue
Block a user