The product was materialized from the template at `4dc033c` and has stayed on it through 43 template commits, so it was missing all three rounds of adapter remediation — including files it never had, such as the shared `abortable-operation` primitive and the `exact-snapshot` decoder that later fixes are written against. Taking only the newest round was not possible for that reason: the delta is coherent only as a whole. The product had not touched `src/adapters` at all since materialization, so the 140-file delta applied with a three-way merge and no conflicts. `package.json` was the single overlap and merged cleanly: the product owns `name`, the template contributed `check:adapter-inventory`, `check:remediation-ledger` and the image-resolve-signal type fixture. All 24 product-owned files — README, index.html, CI workflow, i18n catalog, home page, generated schemas, evidence scripts, component and visual snapshots — are byte-identical to `main`. `template.lock.json` now pins the synced revision and tree. Verified in this repository, not inherited from the template: six type projects, lint, nine gates (adapter inventory, remediation ledger, registries, diagnostics, realtime boundaries, architecture, browser file/storage boundaries, optional recipes, documentation), the production build, and 2,054 of 2,073 tests. The 19 failures are all in `tests/unit/ci-artifact-contract.test.ts` and are the same pre-existing sandbox RLIMIT, EMFILE, umask and `/tmp` permission behaviour the template records; four suites that failed once under parallel load pass in isolation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
290 lines
8.8 KiB
TypeScript
290 lines
8.8 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import { createContractHttpExecutor } from "../../src/adapters/http/http-execution-v3.ts";
|
|
import {
|
|
composeContractContributions,
|
|
ContractContributionError,
|
|
} from "../../src/contracts/external-contract-runtime.ts";
|
|
import {
|
|
installRestAuthProfileRegistry,
|
|
REST_AUTH_PROFILES,
|
|
} from "../../src/contracts/rest-profiles.ts";
|
|
import {
|
|
TEST_CONTRACT_CONTRIBUTION,
|
|
TEST_LIST_HTTP_CONTRACT,
|
|
} from "../helpers/external-contract-fixture.ts";
|
|
|
|
const ROUTE_ID = "TEST_ROUTE";
|
|
|
|
/**
|
|
* The shipped fixture policy declares `TEST_AUTH`; the installed registry owns
|
|
* the concrete transport rules, so this suite installs an equivalent bearer
|
|
* profile under that identity.
|
|
*/
|
|
const TEST_PROFILES = installRestAuthProfileRegistry({
|
|
TEST_AUTH: {
|
|
authProfileId: "TEST_AUTH",
|
|
transport: "BEARER_HEADER",
|
|
credentials: "omit",
|
|
allowedCredentialHeaders: ["authorization"],
|
|
requiredCredentialHeaders: ["authorization"],
|
|
},
|
|
TEST_ANONYMOUS: {
|
|
authProfileId: "TEST_ANONYMOUS",
|
|
transport: "ANONYMOUS",
|
|
credentials: "omit",
|
|
allowedCredentialHeaders: [],
|
|
requiredCredentialHeaders: [],
|
|
},
|
|
});
|
|
|
|
function scopeSnapshot(isCurrent: () => boolean = () => true) {
|
|
return Object.freeze({
|
|
generation: 1,
|
|
fingerprint: "scope-1",
|
|
identities: Object.freeze({}) as never,
|
|
signal: new AbortController().signal,
|
|
isCurrent,
|
|
});
|
|
}
|
|
|
|
function operationWithProfile(authProfileId: string, deadlineMs?: number) {
|
|
return {
|
|
...TEST_LIST_HTTP_CONTRACT,
|
|
frontend: {
|
|
...TEST_LIST_HTTP_CONTRACT.frontend,
|
|
authProfileId,
|
|
...(deadlineMs === undefined ? {} : { totalDeadlineMs: deadlineMs }),
|
|
},
|
|
};
|
|
}
|
|
|
|
const bearerOperation = () => operationWithProfile("TEST_AUTH");
|
|
const anonymousOperation = () => operationWithProfile("TEST_ANONYMOUS");
|
|
|
|
describe("V3 installed auth profile authority", () => {
|
|
it("rejects an unknown auth profile during composition", () => {
|
|
const contribution = {
|
|
...TEST_CONTRACT_CONTRIBUTION,
|
|
http: [
|
|
{
|
|
...TEST_LIST_HTTP_CONTRACT,
|
|
frontend: {
|
|
...TEST_LIST_HTTP_CONTRACT.frontend,
|
|
authProfileId: "NO_SUCH_PROFILE",
|
|
},
|
|
},
|
|
] as unknown as readonly never[],
|
|
};
|
|
|
|
let thrown: unknown;
|
|
try {
|
|
composeContractContributions([contribution] as never);
|
|
} catch (error) {
|
|
thrown = error;
|
|
}
|
|
expect(thrown).toBeInstanceOf(ContractContributionError);
|
|
expect((thrown as ContractContributionError).reason).toContain(
|
|
"unknown authProfileId NO_SUCH_PROFILE",
|
|
);
|
|
|
|
expect(() =>
|
|
installRestAuthProfileRegistry({
|
|
BROKEN: {
|
|
authProfileId: "BROKEN",
|
|
transport: "BEARER_HEADER",
|
|
credentials: "include",
|
|
allowedCredentialHeaders: [],
|
|
requiredCredentialHeaders: ["authorization"],
|
|
},
|
|
}),
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("rejects credential attempts to replace Accept Content-Type or credentials", async () => {
|
|
for (const hostileHeaders of [
|
|
{ accept: "text/plain" },
|
|
{ "content-type": "text/plain" },
|
|
{ cookie: "session=1" },
|
|
]) {
|
|
const fetcher = vi.fn();
|
|
const executor = createContractHttpExecutor({
|
|
baseUrl: "https://api.example/",
|
|
maxRetryAttempts: 0,
|
|
authProfiles: TEST_PROFILES,
|
|
attachCredentials: () =>
|
|
({
|
|
kind: "READY" as const,
|
|
headers: {
|
|
authorization: "Bearer token",
|
|
...hostileHeaders,
|
|
},
|
|
}) as never,
|
|
fetcher: fetcher as unknown as typeof fetch,
|
|
});
|
|
|
|
const outcome = await executor.execute(
|
|
bearerOperation(),
|
|
{ limit: 5 },
|
|
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
|
|
);
|
|
|
|
expect(outcome).toMatchObject({
|
|
kind: "AUTH_INTEGRATION_FAILURE",
|
|
effect: "NOT_APPLICABLE",
|
|
});
|
|
expect(fetcher).not.toHaveBeenCalled();
|
|
}
|
|
});
|
|
|
|
it("requires authorization for a bearer profile before fetch", async () => {
|
|
const fetcher = vi.fn();
|
|
const executor = createContractHttpExecutor({
|
|
baseUrl: "https://api.example/",
|
|
maxRetryAttempts: 0,
|
|
authProfiles: TEST_PROFILES,
|
|
attachCredentials: () => ({
|
|
kind: "READY" as const,
|
|
headers: {},
|
|
}),
|
|
fetcher: fetcher as unknown as typeof fetch,
|
|
});
|
|
|
|
const outcome = await executor.execute(
|
|
bearerOperation(),
|
|
{ limit: 5 },
|
|
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
|
|
);
|
|
|
|
expect(outcome).toMatchObject({
|
|
kind: "AUTH_INTEGRATION_FAILURE",
|
|
reason: "MISSING_REQUIRED_CREDENTIAL_HEADER",
|
|
});
|
|
expect(fetcher).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("forbids credential headers for an anonymous profile", async () => {
|
|
const withCredential = vi.fn();
|
|
const rejected = createContractHttpExecutor({
|
|
baseUrl: "https://api.example/",
|
|
maxRetryAttempts: 0,
|
|
authProfiles: TEST_PROFILES,
|
|
attachCredentials: () => ({
|
|
kind: "READY" as const,
|
|
headers: { authorization: "Bearer token" },
|
|
}),
|
|
fetcher: withCredential as unknown as typeof fetch,
|
|
});
|
|
const rejectedOutcome = await rejected.execute(
|
|
anonymousOperation(),
|
|
{ limit: 5 },
|
|
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
|
|
);
|
|
expect(rejectedOutcome).toMatchObject({
|
|
kind: "AUTH_INTEGRATION_FAILURE",
|
|
reason: "CREDENTIAL_HEADER_NOT_ALLOWED",
|
|
});
|
|
expect(withCredential).not.toHaveBeenCalled();
|
|
|
|
const observed: Array<Readonly<Record<string, string>>> = [];
|
|
const accepted = createContractHttpExecutor({
|
|
baseUrl: "https://api.example/",
|
|
maxRetryAttempts: 0,
|
|
authProfiles: TEST_PROFILES,
|
|
attachCredentials: () => ({ kind: "READY" as const, headers: {} }),
|
|
fetcher: (async (_input: RequestInfo | URL, init?: RequestInit) => {
|
|
const headers = new Headers(init?.headers);
|
|
observed.push(
|
|
Object.freeze(Object.fromEntries(headers.entries())),
|
|
);
|
|
expect(init?.credentials).toBe("omit");
|
|
return Response.json([]);
|
|
}) as unknown as typeof fetch,
|
|
});
|
|
const acceptedOutcome = await accepted.execute(
|
|
anonymousOperation(),
|
|
{ limit: 5 },
|
|
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
|
|
);
|
|
expect(acceptedOutcome.kind).toBe("SUCCESS");
|
|
expect(observed).toHaveLength(1);
|
|
expect(observed[0]?.authorization).toBeUndefined();
|
|
expect(observed[0]?.accept).toBe("application/json");
|
|
});
|
|
|
|
it("bounds a non-cooperative credential owner by the operation lifetime", async () => {
|
|
const fetcher = vi.fn();
|
|
let observedSignal: AbortSignal | undefined;
|
|
const executor = createContractHttpExecutor({
|
|
baseUrl: "https://api.example/",
|
|
maxRetryAttempts: 0,
|
|
authProfiles: TEST_PROFILES,
|
|
attachCredentials: (_operation, context) => {
|
|
observedSignal = context.signal;
|
|
// Non-cooperative: it never settles on its own.
|
|
return new Promise<never>(() => {});
|
|
},
|
|
fetcher: fetcher as unknown as typeof fetch,
|
|
});
|
|
|
|
const outcome = await executor.execute(
|
|
operationWithProfile("TEST_AUTH", 10),
|
|
{ limit: 5 },
|
|
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
|
|
);
|
|
|
|
expect(outcome).toMatchObject({
|
|
kind: "TRANSPORT_FAILURE",
|
|
failure: { kind: "TIMEOUT" },
|
|
});
|
|
expect(fetcher).not.toHaveBeenCalled();
|
|
expect(observedSignal?.aborted).toBe(true);
|
|
});
|
|
|
|
it("ignores a late credential completion after caller abort or scope fence", async () => {
|
|
const fetcher = vi.fn();
|
|
let release: ((patch: unknown) => void) | undefined;
|
|
const caller = new AbortController();
|
|
const executor = createContractHttpExecutor({
|
|
baseUrl: "https://api.example/",
|
|
maxRetryAttempts: 0,
|
|
authProfiles: TEST_PROFILES,
|
|
attachCredentials: () =>
|
|
new Promise((resolve) => {
|
|
release = resolve as (patch: unknown) => void;
|
|
}) as never,
|
|
fetcher: fetcher as unknown as typeof fetch,
|
|
});
|
|
|
|
const execution = executor.execute(
|
|
bearerOperation(),
|
|
{ limit: 5 },
|
|
{
|
|
routeId: ROUTE_ID,
|
|
scope: scopeSnapshot(),
|
|
signal: caller.signal,
|
|
},
|
|
);
|
|
await Promise.resolve();
|
|
caller.abort();
|
|
const outcome = await execution;
|
|
expect(outcome.kind).toBe("CANCELLED");
|
|
|
|
release?.({
|
|
kind: "READY",
|
|
headers: { authorization: "Bearer late" },
|
|
});
|
|
await Promise.resolve();
|
|
expect(fetcher).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("keeps the shipped bearer profile strict", () => {
|
|
expect(REST_AUTH_PROFILES.REFERENCE_EXTERNAL_BEARER).toMatchObject({
|
|
transport: "BEARER_HEADER",
|
|
credentials: "omit",
|
|
requiredCredentialHeaders: ["authorization"],
|
|
});
|
|
expect(REST_AUTH_PROFILES.ANONYMOUS.requiredCredentialHeaders).toEqual([]);
|
|
});
|
|
});
|