feat(foundry): support restricted subject aspects

This commit is contained in:
Codex
2026-07-24 09:31:34 +03:00
parent 03aa9e3e7e
commit 49f0c449c1
13 changed files with 313 additions and 15 deletions
@@ -1079,3 +1079,46 @@ test("non-geometric unit profile aspect fails closed on projection drift and inj
}
}
});
test("restricted aspect consumers require the exact declared binding data class", async () => {
for (const [bindingDataClass, expected] of [
["restricted", "ok"],
["operational", "data_product_consumer_data_class_mismatch"],
]) {
const stateDir = await mkdtemp(join(tmpdir(), `foundry-consumer-data-class-${bindingDataClass}-`));
const currentTarget = unitProfileV1Target();
currentTarget.binding.dataClass = bindingDataClass;
const manager = createFoundryDataProductConsumerManager({
stateDir,
dataPlaneUrl: "http://edp.test",
resolveTarget: async () => structuredClone(currentTarget),
readReaderToken: async () => "ndc_edprb_profile-reader-capability",
inspectReaderGrant: async () => ({
product: unitProfileV1Product,
readerGrantAction: "reuse",
readerGrantGeneration: 1,
}),
resolvePolicy: () => ({ ...unitProfileV1Policy, dataClass: "restricted" }),
sanitizeSnapshot: (value) => value,
sanitizePatch: (value) => value,
fetchImpl: async () => Response.json(unitProfileV1Snapshot()),
});
const input = {
applicationId: currentTarget.application.id,
pageId: currentTarget.page.id,
bindingId: currentTarget.binding.id,
};
try {
if (expected === "ok") {
const plan = await manager.plan(input);
assert.equal(plan.configuration.policy.dataClass, "restricted");
assert.equal(plan.configuration.target.dataClass, "restricted");
} else {
await assert.rejects(manager.plan(input), new RegExp(expected));
}
} finally {
await manager.shutdown();
await rm(stateDir, { recursive: true, force: true });
}
}
});