fix: harden invalidation registry governance

This commit is contained in:
DongHyeonka
2026-08-01 23:59:11 +09:00
parent 73a50426d6
commit 0eb23875cb
15 changed files with 906 additions and 147 deletions
+142 -4
View File
@@ -1,4 +1,7 @@
import { readFile } from "node:fs/promises";
import { spawnSync } from "node:child_process";
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
type RegistryDefinition = Readonly<{
@@ -6,17 +9,25 @@ type RegistryDefinition = Readonly<{
owner: string;
requiredFields: string[];
fieldTypes: Record<string, string>;
path: string;
exportName: string;
rowsPath?: string;
rowKeyFields?: string[];
uniqueFields?: string[];
uniqueFieldSets?: string[][];
consumers?: Array<{ path: string; token: string }>;
breakingFields?: string[];
}>;
describe("registry governance manifest", () => {
it("declares nine typed, single-owner executable registries", async () => {
it("declares eleven typed, single-owner executable registries", async () => {
const governance = JSON.parse(
await readFile("config/contracts/registry-governance.json", "utf8"),
);
const registries = governance.registries as RegistryDefinition[];
expect(governance.registries).toHaveLength(9);
expect(governance.registries).toHaveLength(11);
expect(new Set(registries.map((entry) => entry.registryId)).size).toBe(
9,
11,
);
expect(registries.every((entry) => entry.owner)).toBe(true);
expect(
@@ -29,4 +40,131 @@ describe("registry governance manifest", () => {
),
).toBe(true);
});
it("governs the installed invalidation graph and wire versions at their real exports", async () => {
const governance = JSON.parse(
await readFile("config/contracts/registry-governance.json", "utf8"),
) as { registries: RegistryDefinition[] };
const byId = new Map(
governance.registries.map((registry) => [registry.registryId, registry]),
);
expect(byId.get("FE-REG-QUERY-INVALIDATION")).toMatchObject({
path: "src/features/installed-feature-contracts.ts",
exportName: "INVALIDATION_REGISTRY",
rowsPath: "edges",
rowKeyFields: [
"topicId",
"namespace.namespaceId",
"namespace.namespaceVersion",
],
uniqueFieldSets: [
[
"topicId",
"namespace.namespaceId",
"namespace.namespaceVersion",
],
],
consumers: [
{
path: "src/bootstrap/runtime-adapters.ts",
token: "indexInvalidationRegistry(INVALIDATION_REGISTRY)",
},
],
breakingFields: [
"topicId",
"namespace.namespaceId",
"namespace.namespaceVersion",
],
});
expect(byId.get("FE-REG-QUERY-INVALIDATION-TOPIC-VERSION")).toMatchObject({
path: "src/features/installed-feature-contracts.ts",
exportName: "INVALIDATION_TOPIC_VERSIONS",
rowKeyFields: ["topicId"],
uniqueFields: ["topicId"],
consumers: [
{
path: "src/bootstrap/runtime-adapters.ts",
token: "indexInvalidationTopicVersions(",
},
],
breakingFields: ["topicId", "topicVersion"],
});
});
it("projects graph and array exports into deterministic governed rows", async () => {
const directory = await mkdtemp(
path.join(tmpdir(), "registry-governance-projection-"),
);
const artifact = path.join(directory, "registries.json");
try {
const result = spawnSync(
process.execPath,
[
"scripts/check-registries.ts",
"--governance",
"tests/fixtures/registry/invalidation/governance.json",
"--artifact",
artifact,
"--no-baseline",
],
{ encoding: "utf8" },
);
expect(result.status, result.stderr).toBe(0);
const report = JSON.parse(await readFile(artifact, "utf8")) as {
registries: Array<{ registryId: string; rows: Record<string, unknown> }>;
};
expect(
report.registries.find(
(registry) => registry.registryId === "FIXTURE-INVALIDATION-EDGES",
)?.rows,
).toHaveProperty('["qinv.fixture.changed","orders",1]');
expect(
report.registries.find(
(registry) => registry.registryId === "FIXTURE-INVALIDATION-EDGES",
)?.rows,
).toHaveProperty('["orders","qinv.fixture.changed",1]');
expect(
report.registries.find(
(registry) => registry.registryId === "FIXTURE-INVALIDATION-VERSIONS",
)?.rows,
).toHaveProperty('["qinv.fixture.changed"]');
} finally {
await rm(directory, { recursive: true, force: true });
}
});
it("rejects duplicate composite invalidation edges after projection", async () => {
const directory = await mkdtemp(
path.join(tmpdir(), "registry-governance-duplicate-"),
);
const artifact = path.join(directory, "registries.json");
try {
const result = spawnSync(
process.execPath,
[
"scripts/check-registries.ts",
"--governance",
"tests/fixtures/registry/invalidation/duplicate-governance.json",
"--artifact",
artifact,
"--no-baseline",
],
{ encoding: "utf8" },
);
expect(result.status).toBe(1);
const report = JSON.parse(await readFile(artifact, "utf8")) as {
failures: string[];
};
expect(report.failures).toEqual([
expect.stringContaining(
"duplicates topicId+namespace.namespaceId+namespace.namespaceVersion",
),
]);
} finally {
await rm(directory, { recursive: true, force: true });
}
});
});