Files
clean-architecture-frontend…/tests/unit/release-coherence.test.ts
T

371 lines
11 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { verifyRollbackReleaseCoherence } from "../../scripts/drill-runbook.ts";
import { verifyReleaseArtifactsCoherence } from "../../scripts/verify-release.ts";
import type { InstalledContractPackageIdentity } from "../../src/contracts/external-contract-runtime.ts";
import { computeContractSetDigest } from "../../src/contracts/contract-set-canonical.ts";
import type {
ReleaseArtifact,
RuntimeConfigArtifact,
} from "../../src/contracts/release-artifacts.ts";
import {
compareReleaseToRuntime,
RELEASE_TOKEN_REGISTRY,
} from "../../src/contracts/release-tokens.ts";
const contractPackages = [
{
packageId: "@example/accounts",
version: "1.2.3",
digest: `sha256:${"1".repeat(64)}`,
runtimeProtocolVersion: 1,
sourceRevision: "a".repeat(40),
},
{
packageId: "@example/billing",
version: "2.3.4",
digest: `sha256:${"2".repeat(64)}`,
runtimeProtocolVersion: 1,
sourceRevision: "b".repeat(40),
},
] as const satisfies readonly InstalledContractPackageIdentity[];
const releaseV1 = {
schemaVersion: 1,
appVersion: "1.0.0",
buildId: "build-a",
commitSha: "abc1234",
configSchemaVersion: "1",
apiContractVersion: "1.4.0",
assetManifestHash: "assets-a",
releaseId: "release-a",
builtAt: "2026-08-01T00:00:00.000Z",
routeChunks: {},
} as const satisfies ReleaseArtifact;
const runtimeV1 = {
APP_ENV: "local",
API_BASE_URL: "http://localhost:8080/",
REQUEST_TIMEOUT_MS: 10_000,
MAX_RETRY_ATTEMPTS: 2,
TELEMETRY_ENABLED: false,
AUTH_MODE: "external",
CONFIG_SCHEMA_VERSION: "1",
API_CONTRACT_VERSION: "1.6.0",
RELEASE_MANIFEST_URL: "/release-manifest.json",
BUILD_ID: "build-a",
RELEASE_ID: "release-a",
} as const satisfies RuntimeConfigArtifact;
const runtimeV2 = {
APP_ENV: "local",
API_BASE_URL: "http://localhost:8080/",
REQUEST_TIMEOUT_MS: 10_000,
MAX_RETRY_ATTEMPTS: 2,
TELEMETRY_ENABLED: false,
AUTH_MODE: "external",
CONFIG_SCHEMA_VERSION: "2.0",
RELEASE_MANIFEST_URL: "/release-manifest.json",
BUILD_ID: "build-a",
RELEASE_ID: "release-a",
CAPABILITY_OVERRIDES: {
REALTIME: "DEFAULT",
WEB_WORKER: "DEFAULT",
SERVICE_WORKER: "DEFAULT",
OFFLINE_COMMANDS: "DEFAULT",
},
} as const satisfies RuntimeConfigArtifact;
async function releaseV2With(
packages: readonly InstalledContractPackageIdentity[],
setDigest?: `sha256:${string}`,
): Promise<ReleaseArtifact> {
return {
schemaVersion: 2,
appVersion: "1.0.0",
buildId: "build-a",
commitSha: "abc1234",
configSchemaVersion: "2.0",
assetManifestHash: "assets-a",
releaseId: "release-a",
builtAt: "2026-08-01T00:00:00.000Z",
routeChunks: {},
contractSet: {
setAlgorithm: "CA_CONTRACT_SET_V1",
setDigest: setDigest ?? (await computeContractSetDigest(packages)),
packages: [...packages],
},
};
}
function artifactReader(
entries: Readonly<Record<string, unknown | Error>>,
reads: string[] = [],
): (path: string) => Promise<unknown> {
return async (path) => {
reads.push(path);
const value = entries[path];
if (value === undefined) {
throw Object.assign(new Error(`missing ${path}`), { code: "ENOENT" });
}
if (value instanceof Error) throw value;
return value;
};
}
describe("release coherence", () => {
it("owns all nine release tokens and keeps builtAt diagnostic-only", () => {
// §5.2 adds contractSetDigest beside the legacy apiContractVersion scalar.
expect(Object.keys(RELEASE_TOKEN_REGISTRY)).toHaveLength(9);
expect(RELEASE_TOKEN_REGISTRY.contractSetDigest.compatibilityRole).toContain(
"multi-package",
);
expect(RELEASE_TOKEN_REGISTRY.builtAt.compatibilityRole).toContain(
"never cache identity",
);
});
it("compares the runtime config to the release structurally", () => {
const release = {
buildId: "build-a",
configSchemaVersion: "1.0",
apiContractVersion: "1.0",
assetManifestHash: "assets-a",
releaseId: "release-a",
};
expect(
compareReleaseToRuntime(release, {
BUILD_ID: "build-a",
CONFIG_SCHEMA_VERSION: "1.2",
API_CONTRACT_VERSION: "1.1",
RELEASE_ID: "release-a",
}),
).toMatchObject({ compatible: true, mismatches: [] });
});
it("rejects HTML-only rollback against a newer runtime config", () => {
const oldRelease = {
buildId: "build-old",
configSchemaVersion: "1.0",
apiContractVersion: "1.0",
assetManifestHash: "assets-old",
releaseId: "release-old",
};
expect(
compareReleaseToRuntime(oldRelease, {
BUILD_ID: "build-new",
CONFIG_SCHEMA_VERSION: "2.0",
API_CONTRACT_VERSION: "2.0",
RELEASE_ID: "release-new",
}),
).toMatchObject({
compatible: false,
mismatches: ["buildId", "configSchemaVersion", "apiContractVersion"],
});
});
it("gives release verification and rollback drills the same V1/V2 tamper verdicts", async () => {
const packageAdded = [
...contractPackages,
{
packageId: "@example/notifications",
version: "3.0.0",
digest: `sha256:${"3".repeat(64)}`,
runtimeProtocolVersion: 1,
sourceRevision: "c".repeat(40),
},
] as const satisfies readonly InstalledContractPackageIdentity[];
const packageRemoved = contractPackages.slice(0, 1);
const versionChanged = [
{ ...contractPackages[0], version: "1.2.4" },
contractPackages[1],
] as const satisfies readonly InstalledContractPackageIdentity[];
const packageDigestChanged = [
{
...contractPackages[0],
digest: `sha256:${"f".repeat(64)}`,
},
contractPackages[1],
] as const satisfies readonly InstalledContractPackageIdentity[];
const exactV2 = await releaseV2With(contractPackages);
const matrix = [
{
name: "V1 scalar success",
release: releaseV1,
runtime: runtimeV1,
expectedCompatible: true,
},
{
name: "V1 scalar mismatch",
release: releaseV1,
runtime: { ...runtimeV1, API_CONTRACT_VERSION: "2.0.0" },
expectedCompatible: false,
},
{
name: "V2 exact package set",
release: exactV2,
runtime: runtimeV2,
expectedCompatible: true,
},
{
name: "V2 exact package set in non-canonical manifest order",
release: await releaseV2With([...contractPackages].reverse()),
runtime: runtimeV2,
expectedCompatible: true,
},
{
name: "V2 package added",
release: await releaseV2With(packageAdded),
runtime: runtimeV2,
expectedCompatible: false,
},
{
name: "V2 package removed",
release: await releaseV2With(packageRemoved),
runtime: runtimeV2,
expectedCompatible: false,
},
{
name: "V2 package version tampered",
release: await releaseV2With(versionChanged),
runtime: runtimeV2,
expectedCompatible: false,
},
{
name: "V2 package digest tampered",
release: await releaseV2With(packageDigestChanged),
runtime: runtimeV2,
expectedCompatible: false,
},
{
name: "V2 set digest tampered",
release: await releaseV2With(
contractPackages,
`sha256:${"0".repeat(64)}`,
),
runtime: runtimeV2,
expectedCompatible: false,
},
];
for (const fixture of matrix) {
const input = { release: fixture.release, runtime: fixture.runtime };
const verifierVerdict = (
await verifyReleaseArtifactsCoherence({
readArtifact: artifactReader({
"dist/release-manifest.json": input.release,
"dist/config.json": input.runtime,
}),
contractPackages,
})
).coherence.compatible;
const rollbackDrillVerdict = (
await verifyRollbackReleaseCoherence({
readArtifact: artifactReader({
"dist/release-manifest.json": fixture.release,
"dist/config.json": fixture.runtime,
}),
contractPackages,
})
).coherence.compatible;
expect(verifierVerdict, `${fixture.name}: verifier`).toBe(
fixture.expectedCompatible,
);
expect(rollbackDrillVerdict, `${fixture.name}: rollback drill`).toBe(
fixture.expectedCompatible,
);
expect(rollbackDrillVerdict, `${fixture.name}: identical verdict`).toBe(
verifierVerdict,
);
}
});
it("falls back to public rollback artifacts only when primary dist is absent", async () => {
const exactV2 = await releaseV2With(contractPackages);
const tamperedPrimary = await releaseV2With(contractPackages.slice(0, 1));
const validPublic = {
"public/release-manifest.json": exactV2,
"public/config.json": runtimeV2,
};
const unavailablePrimary = [
new SyntaxError("invalid primary JSON"),
Object.assign(new Error("unreadable primary"), { code: "EACCES" }),
{ ...exactV2, unexpected: "tampered" },
];
for (const primaryFailure of unavailablePrimary) {
await expect(
verifyRollbackReleaseCoherence({
readArtifact: artifactReader({
"dist/release-manifest.json": primaryFailure,
"dist/config.json": runtimeV2,
...validPublic,
}),
contractPackages,
}),
).rejects.toBeDefined();
}
await expect(
verifyRollbackReleaseCoherence({
readArtifact: artifactReader({
"dist/release-manifest.json": tamperedPrimary,
"dist/config.json": runtimeV2,
...validPublic,
}),
contractPackages,
}),
).resolves.toMatchObject({ coherence: { compatible: false } });
const releaseOnlyMissingReads: string[] = [];
await expect(
verifyRollbackReleaseCoherence({
readArtifact: artifactReader(
{
"dist/config.json": runtimeV2,
...validPublic,
},
releaseOnlyMissingReads,
),
contractPackages,
}),
).rejects.toThrow("primary rollback artifact pair");
expect(releaseOnlyMissingReads).toEqual([
"dist/release-manifest.json",
"dist/config.json",
]);
const runtimeOnlyMissingReads: string[] = [];
await expect(
verifyRollbackReleaseCoherence({
readArtifact: artifactReader(
{
"dist/release-manifest.json": exactV2,
...validPublic,
},
runtimeOnlyMissingReads,
),
contractPackages,
}),
).rejects.toThrow("primary rollback artifact pair");
expect(runtimeOnlyMissingReads).toEqual([
"dist/release-manifest.json",
"dist/config.json",
]);
const missingPairReads: string[] = [];
await expect(
verifyRollbackReleaseCoherence({
readArtifact: artifactReader(validPublic, missingPairReads),
contractPackages,
}),
).resolves.toMatchObject({ coherence: { compatible: true } });
expect(missingPairReads).toEqual([
"dist/release-manifest.json",
"dist/config.json",
"public/release-manifest.json",
"public/config.json",
]);
});
});