feat(foundry): close the operational map data loop

This commit is contained in:
Codex
2026-07-20 20:45:05 +03:00
parent aac44d057f
commit a02c3ff3dd
44 changed files with 4158 additions and 811 deletions
+42 -8
View File
@@ -38,6 +38,21 @@ function targetDigest(target) {
.digest("hex");
}
function grantGeneration(value) {
const generation = Number(value ?? 1);
if (!Number.isSafeInteger(generation) || generation < 1 || generation > 2_147_483_647) {
throw provisionerError("foundry_reader_grant_generation_invalid", 400);
}
return generation;
}
function readerTokenPath(tokenRoot, digest, generation) {
// Generation one keeps the deployed path for a zero-copy migration. Every
// successor gets a separate immutable capability file so a new snapshot can
// be accepted before the predecessor is revoked.
return join(resolve(tokenRoot), generation === 1 ? digest : `${digest}.g${generation}`);
}
function signingPayload({ audience, serviceId, keyId, method, path, timestamp, nonce, bodySha256 }) {
return JSON.stringify({
schemaVersion: SIGNATURE_SCHEMA,
@@ -137,10 +152,11 @@ export function createFoundryReaderGrantProvisioner({
return { product, sourceScope: "resolved-server-side" };
}
async function ensure(target) {
async function ensure(target, options = {}) {
const identity = targetIdentity(target);
const digest = targetDigest(identity);
const token = await ensureReaderToken(join(resolve(tokenRoot), digest), {
const generation = grantGeneration(options.generation);
const token = await ensureReaderToken(readerTokenPath(tokenRoot, digest, generation), {
production,
randomBytesImpl,
});
@@ -151,26 +167,44 @@ export function createFoundryReaderGrantProvisioner({
{
allowedDataProductIds: [identity.dataProductId],
expiresAt: null,
generation: 1,
generation,
capabilityDigest: createHash("sha256").update(token, "utf8").digest("hex"),
},
);
const binding = payload?.readerBinding;
if (binding?.bindingKey !== bindingKey || binding?.generation !== 1 || binding?.active !== true
if (binding?.bindingKey !== bindingKey || binding?.generation !== generation || binding?.active !== true
|| binding?.expiresAt !== null || binding?.sourceScope !== "resolved-server-side"
|| !Array.isArray(binding?.allowedDataProductIds)
|| !binding.allowedDataProductIds.includes(identity.dataProductId)) {
throw provisionerError("foundry_reader_grant_ensure_response_invalid", 502);
}
return { ensured: true, idempotent: payload?.idempotent === true, generation: 1, sourceScope: "resolved-server-side" };
return { ensured: true, idempotent: payload?.idempotent === true, generation, sourceScope: "resolved-server-side" };
}
async function readToken(target) {
async function revoke(target, options = {}) {
const digest = targetDigest(target);
const generation = grantGeneration(options.generation);
const bindingKey = `fndrc-${digest}`;
const payload = await signedRequest(
"POST",
`/internal/data-plane/v1/consumer-reader-bindings/by-key/${encodeURIComponent(bindingKey)}/generations/${generation}/revoke`,
{},
);
const binding = payload?.readerBinding;
if (binding?.bindingKey !== bindingKey || binding?.generation !== generation || binding?.active !== false
|| binding?.sourceScope !== "resolved-server-side") {
throw provisionerError("foundry_reader_grant_revoke_response_invalid", 502);
}
return { revoked: true, idempotent: payload?.idempotent === true, generation, sourceScope: "resolved-server-side" };
}
async function readToken(target, options = {}) {
if (!tokenRoot) return null;
return readReaderToken(join(resolve(tokenRoot), targetDigest(target)), { production, missing: null });
const generation = grantGeneration(options.generation);
return readReaderToken(readerTokenPath(tokenRoot, targetDigest(target), generation), { production, missing: null });
}
return { configured, plan, ensure, readToken };
return { configured, plan, ensure, revoke, readToken };
}
async function readPrivateKeySecurely(path, { production }) {