chore: sync the frontend template from 4dc033c to 8157ad4

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>
This commit is contained in:
DongHyeonka
2026-08-15 12:04:58 +09:00
co-authored by Claude Opus 5
parent 002ba3624e
commit 4bff9ca151
142 changed files with 23010 additions and 1544 deletions
+82
View File
@@ -59,6 +59,88 @@ describe("shared HTTP client", () => {
expect(attempts).toBe(3);
});
it.each(["", " ", "bad\u0000key", "x".repeat(513)])(
"rejects invalid keyed command key %j before credentials and fetch",
async (idempotencyKey) => {
let fetched = 0;
let credentialAttempts = 0;
server.use(
http.post("https://api.test/api/entities", () => {
fetched += 1;
return HttpResponse.json({ success: true, data: {} });
}),
);
const client = testClient({
baseUrl: "https://api.test",
clock,
authSession: {
getState: () => "authenticated",
subscribe: () => () => {},
beginSignIn: async () => {},
signOut: async () => {},
async credentialPatch() {
credentialAttempts += 1;
return { headers: {} };
},
recover: async () => "no-session" as const,
onUnauthenticated: () => {},
},
});
await expect(
client.execute("CREATE_ENTITY", {
body: { name: "n" },
idempotencyKey,
}),
).resolves.toMatchObject({
ok: false,
error: {
kind: "VALIDATION_REJECTED",
code: "IDEMPOTENCY_KEY_INVALID",
// The repository reports attempt counts as 1-based; the invariant
// proved below is that no physical attempt happened at all.
attemptCount: 1,
},
});
expect(fetched).toBe(0);
expect(credentialAttempts).toBe(0);
},
);
it("bounds a non-cooperative legacy credential owner by total deadline", async () => {
let fetched = 0;
let observedSignal: AbortSignal | undefined;
server.use(
http.get("https://api.test/api/entities", () => {
fetched += 1;
return HttpResponse.json({ success: true, data: [] });
}),
);
const client = testClient({
baseUrl: "https://api.test",
timeoutMs: 5,
clock: { now: () => 0, sleep: async () => {} },
authSession: {
getState: () => "authenticated",
subscribe: () => () => {},
beginSignIn: async () => {},
signOut: async () => {},
credentialPatch: (_binding, context) => {
observedSignal = context?.signal;
// Never settles on its own.
return new Promise<never>(() => {});
},
recover: async () => "no-session" as const,
onUnauthenticated: () => {},
},
});
const result = await client.execute("LIST_ENTITIES");
expect(result).toMatchObject({ ok: false });
expect(fetched).toBe(0);
expect(observedSignal).toBeDefined();
});
it("rejects a non-JSON response without exposing its body", async () => {
server.use(
http.get(
@@ -2,6 +2,7 @@ import { describe, expect, it, vi } from "vitest";
import { createHttpClient } from "../../src/adapters/http/client.ts";
import { createContractHttpExecutor } from "../../src/adapters/http/http-execution-v3.ts";
import { joinMutationEffectCertainty } from "../../src/adapters/http/http-effect-certainty.ts";
import {
entityQueryKeys,
TEST_HTTP_CONTRACT,
@@ -49,12 +50,27 @@ function testClient(options: HttpDependencies) {
return createHttpClient({ ...TEST_HTTP_CONTRACT, ...options });
}
describe("mutation effect certainty lattice", () => {
it.each([
["NOT_STARTED", "NOT_APPLIED", "NOT_APPLIED"],
["NOT_APPLIED", "NOT_STARTED", "NOT_APPLIED"],
["NOT_STARTED", "MAYBE_APPLIED", "MAYBE_APPLIED"],
["MAYBE_APPLIED", "NOT_STARTED", "MAYBE_APPLIED"],
["MAYBE_APPLIED", "NOT_APPLIED", "MAYBE_APPLIED"],
["NOT_APPLIED", "MAYBE_APPLIED", "MAYBE_APPLIED"],
["MAYBE_APPLIED", "APPLIED_CONFIRMED", "APPLIED_CONFIRMED"],
["APPLIED_CONFIRMED", "NOT_STARTED", "APPLIED_CONFIRMED"],
["APPLIED_CONFIRMED", "MAYBE_APPLIED", "APPLIED_CONFIRMED"],
] as const)("joins %s with %s as %s", (current, observed, expected) => {
expect(joinMutationEffectCertainty(current, observed)).toBe(expected);
});
});
describe("HTTP operation execution contract", () => {
it("permits a keyless command intent but rejects an unexpected key before dispatch", async () => {
const attachCredentials = vi.fn(() => ({
kind: "READY" as const,
headers: {},
credentials: "omit" as const,
}));
const observedKeys: Array<string | null> = [];
const fetcher = vi.fn(
@@ -98,7 +114,7 @@ describe("HTTP operation execution contract", () => {
executor.execute(
nonKeyedCommand,
{ name: "created" },
{ scope, intent },
{ routeId: "TEST_ROUTE", scope, intent },
),
).resolves.toMatchObject({ kind: "SUCCESS" });
expect(observedKeys).toEqual([null]);
@@ -109,7 +125,7 @@ describe("HTTP operation execution contract", () => {
executor.execute(
nonKeyedCommand,
{ name: "created" },
{ scope, intent: { ...intent, idempotencyKey: "unexpected-key" } },
{ routeId: "TEST_ROUTE", scope, intent: { ...intent, idempotencyKey: "unexpected-key" } },
),
).resolves.toMatchObject({
kind: "CONTRACT_VIOLATION",
@@ -290,6 +306,9 @@ describe("HTTP operation execution contract", () => {
operationId: "LIST_ENTITIES",
routeId: "TEST_ROUTE",
});
// The credential wait is bounded by the same attempt controller, so wait
// until the request is actually in flight before firing the deadline.
await vi.waitFor(() => expect(fetcher).toHaveBeenCalledTimes(1));
await vi.waitFor(() => expect(scheduler.callbacks).toHaveLength(1));
scheduler.callbacks[0]();
await expect(timeoutResult).resolves.toMatchObject({
@@ -0,0 +1,289 @@
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([]);
});
});
@@ -0,0 +1,649 @@
import { describe, expect, it, vi } from "vitest";
import {
createContractHttpExecutor,
type HttpExecutionObservation,
} from "../../src/adapters/http/http-execution-v3.ts";
import { createHttpObservationProjector } from "../../src/bootstrap/runtime-adapters.ts";
import { installRestAuthProfileRegistry } from "../../src/contracts/rest-profiles.ts";
import { TEST_LIST_HTTP_CONTRACT } from "../helpers/external-contract-fixture.ts";
const ROUTE_ID = "TEST_ROUTE";
const TEST_PROFILES = installRestAuthProfileRegistry({
TEST_AUTH: {
authProfileId: "TEST_AUTH",
transport: "BEARER_HEADER",
credentials: "omit",
allowedCredentialHeaders: ["authorization"],
requiredCredentialHeaders: ["authorization"],
},
});
function scopeSnapshot(signal: AbortSignal = new AbortController().signal) {
return Object.freeze({
generation: 1,
fingerprint: "scope-1",
identities: Object.freeze({}) as never,
signal,
isCurrent: () => true,
});
}
function bearerOperation(deadlineMs = 10_000) {
return {
...TEST_LIST_HTTP_CONTRACT,
frontend: {
...TEST_LIST_HTTP_CONTRACT.frontend,
authProfileId: "TEST_AUTH",
totalDeadlineMs: deadlineMs,
},
};
}
function jsonResponse(body: unknown): Response {
return new Response(JSON.stringify(body), {
status: 200,
headers: { "content-type": "application/json" },
});
}
/**
* LIVE-01. A credential collaborator that is broken, unavailable or throwing is
* an integration failure of the auth system. Reporting it as `UNAUTHENTICATED`
* makes the composition root run its logout path, so an auth outage would sign
* every user out.
*/
describe("LIVE-01 credential integration failures are not user session failures", () => {
const brokenOwners = [
{
label: "returns UNAVAILABLE",
attach: () => Object.freeze({ kind: "UNAVAILABLE" as const }),
},
{
label: "throws synchronously",
attach: () => {
throw new Error("credential owner exploded");
},
},
{
label: "rejects asynchronously",
attach: () => Promise.reject(new Error("credential owner exploded")),
},
{
label: "returns a malformed outcome",
attach: () => ({ kind: "TOTALLY_UNKNOWN" }) as never,
},
];
for (const owner of brokenOwners) {
it(`closes as AUTH_INTEGRATION_FAILURE when the owner ${owner.label}`, async () => {
const fetcher = vi.fn(async () => jsonResponse([]));
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: owner.attach,
fetcher: fetcher as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("AUTH_INTEGRATION_FAILURE");
expect(outcome.effect).toBe("NOT_APPLICABLE");
expect(fetcher).toHaveBeenCalledTimes(0);
});
}
/**
* NS-01. Reading `patch.kind` and `patch.headers` off the raw answer put the
* credential decode outside the auth boundary: a throwing getter escaped into
* the transport catch and the outage was reported as `NETWORK_FAILURE`, so
* the operator saw a network incident instead of an auth integration one.
*/
const hostileOwners = [
{
label: "exposes a throwing kind getter",
attach: () =>
Object.defineProperty({}, "kind", {
enumerable: true,
get() {
throw new TypeError("hostile kind getter");
},
}) as never,
},
{
label: "exposes a throwing headers getter",
attach: () =>
Object.defineProperty({ kind: "READY" }, "headers", {
enumerable: true,
get() {
throw new TypeError("hostile headers getter");
},
}) as never,
},
{
label: "throws from an ownKeys trap",
attach: () =>
new Proxy(
{ kind: "READY", headers: { authorization: "Bearer ok" } },
{
ownKeys() {
throw new TypeError("hostile ownKeys trap");
},
},
) as never,
},
{
label: "throws from a getOwnPropertyDescriptor trap",
attach: () =>
new Proxy(
{ kind: "READY", headers: { authorization: "Bearer ok" } },
{
getOwnPropertyDescriptor() {
throw new TypeError("hostile descriptor trap");
},
},
) as never,
},
{
label: "carries the outcome only on its prototype",
attach: () =>
Object.create({
kind: "READY",
headers: { authorization: "Bearer ok" },
}) as never,
},
{
label: "carries an extra own field",
attach: () =>
Object.freeze({
kind: "READY",
headers: Object.freeze({ authorization: "Bearer ok" }),
injected: true,
}) as never,
},
{
label: "carries a symbol field",
attach: () =>
Object.freeze({
kind: "READY",
headers: Object.freeze({ authorization: "Bearer ok" }),
[Symbol.for("injected")]: true,
}) as never,
},
{
label: "hides the outcome behind a non-enumerable own field",
attach: () =>
Object.defineProperties(
{ kind: "READY" },
{
headers: {
enumerable: false,
value: { authorization: "Bearer ok" },
},
},
) as never,
},
];
for (const owner of hostileOwners) {
it(`closes as AUTH_INTEGRATION_FAILURE when the owner ${owner.label}`, async () => {
const fetcher = vi.fn(async () => jsonResponse([]));
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: owner.attach,
fetcher: fetcher as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("AUTH_INTEGRATION_FAILURE");
expect(outcome.effect).toBe("NOT_APPLICABLE");
expect(fetcher).toHaveBeenCalledTimes(0);
});
}
it("reads each field exactly once so a stateful answer cannot swap it", async () => {
const fetcher = vi.fn(async () => jsonResponse([]));
const kindReads: string[] = [];
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
new Proxy(
{ kind: "READY", headers: { authorization: "Bearer first" } },
{
getOwnPropertyDescriptor(target, key) {
if (key === "kind") {
kindReads.push(key);
return {
configurable: true,
enumerable: true,
// A second read would answer with a different verdict.
value: kindReads.length > 1 ? "UNAUTHENTICATED" : "READY",
};
}
return Reflect.getOwnPropertyDescriptor(target, key);
},
},
) as never,
fetcher: fetcher as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("SUCCESS");
expect(kindReads).toHaveLength(1);
});
it("sends an owned header snapshot rather than the owner's live object", async () => {
const headers: Record<string, string> = { authorization: "Bearer first" };
let sentHeaders: Record<string, string> | undefined;
const fetcher = vi.fn(async (_url: unknown, init?: RequestInit) => {
sentHeaders = init?.headers as Record<string, string>;
return jsonResponse([]);
});
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
// The owner keeps a live reference to the object it handed over.
attachCredentials: () => ({ kind: "READY", headers }) as never,
fetcher: fetcher as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("SUCCESS");
headers.authorization = "Bearer swapped";
expect(sentHeaders?.["Authorization"] ?? sentHeaders?.["authorization"]).toBe(
"Bearer first",
);
});
it("still reports a real absent session as UNAUTHENTICATED", async () => {
const fetcher = vi.fn(async () => jsonResponse([]));
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
Object.freeze({ kind: "UNAUTHENTICATED" as const }),
fetcher: fetcher as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("UNAUTHENTICATED");
expect(fetcher).toHaveBeenCalledTimes(0);
});
});
/**
* LIVE-04. The total deadline must bound the physical wait, not merely be
* checked between awaits. A non-cooperative `fetch` or body reader that ignores
* the abort signal cannot hold the port result open, and a value that arrives
* after the deadline already owns the execution must not be admitted.
*/
describe("LIVE-04 the total deadline owns every physical wait", () => {
it("does not wait for a non-cooperative fetch past the deadline", async () => {
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
Object.freeze({
kind: "READY" as const,
headers: { authorization: "Bearer t" },
}),
fetcher: (() => new Promise<Response>(() => {})) as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(5),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("TRANSPORT_FAILURE");
expect(
outcome.kind === "TRANSPORT_FAILURE" ? outcome.failure.kind : null,
).toBe("TIMEOUT");
});
/**
* NS-03. The `NONE` probe used to await `reader.read()` with no signal, so a
* deadline produced a bounded public result while the raw reader kept its
* lease on the body: the connection and the buffer stayed held after the
* operation had already ended.
*/
it("cancels and releases the NONE probe reader when the deadline owns the execution", async () => {
let pulls = 0;
let cancels = 0;
const neverEndingBody = new ReadableStream<Uint8Array>({
pull() {
pulls += 1;
return new Promise<void>(() => {});
},
cancel() {
cancels += 1;
},
});
const response = new Response(neverEndingBody, { status: 200 });
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
Object.freeze({
kind: "READY" as const,
headers: { authorization: "Bearer t" },
}),
fetcher: (async () => response) as unknown as typeof fetch,
});
const noBodyOperation = {
...bearerOperation(20),
contract: {
...bearerOperation(20).contract,
responseBody: "NONE" as const,
},
};
const outcome = await executor.execute(
noBodyOperation as never,
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("TRANSPORT_FAILURE");
expect(
outcome.kind === "TRANSPORT_FAILURE" ? outcome.failure.kind : null,
).toBe("TIMEOUT");
expect(pulls).toBe(1);
await vi.waitFor(() => {
expect(cancels).toBe(1);
});
expect(response.body?.locked).toBe(false);
});
it("does not wait for a non-cooperative body reader past the deadline", async () => {
const neverEndingBody = new ReadableStream<Uint8Array>({
pull() {
return new Promise<void>(() => {});
},
});
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
Object.freeze({
kind: "READY" as const,
headers: { authorization: "Bearer t" },
}),
fetcher: (async () =>
new Response(neverEndingBody, {
status: 200,
headers: { "content-type": "application/json" },
})) as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(20),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("TRANSPORT_FAILURE");
expect(
outcome.kind === "TRANSPORT_FAILURE" ? outcome.failure.kind : null,
).toBe("TIMEOUT");
});
it("does not admit a body that completes after the deadline owns the execution", async () => {
let releaseBody: (() => void) | undefined;
const lateBody = new ReadableStream<Uint8Array>({
pull(controller) {
return new Promise<void>((resolve) => {
releaseBody = () => {
// The executor is expected to have cancelled this reader already;
// enqueueing into the closed controller then throws, which is the
// late producer this scenario is about.
try {
controller.enqueue(new TextEncoder().encode("[]"));
controller.close();
} catch {
// The stream was already cancelled by the deadline owner.
}
resolve();
};
});
},
});
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
Object.freeze({
kind: "READY" as const,
headers: { authorization: "Bearer t" },
}),
fetcher: (async () =>
new Response(lateBody, {
status: 200,
headers: { "content-type": "application/json" },
})) as unknown as typeof fetch,
});
const pending = executor.execute(
bearerOperation(10),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
setTimeout(() => releaseBody?.(), 40);
const outcome = await pending;
expect(outcome.kind).toBe("TRANSPORT_FAILURE");
expect(
outcome.kind === "TRANSPORT_FAILURE" ? outcome.failure.kind : null,
).toBe("TIMEOUT");
});
it("preserves the caller and the scope as distinct cancellation owners", async () => {
const observations: HttpExecutionObservation[] = [];
const makeExecutor = () =>
createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
Object.freeze({
kind: "READY" as const,
headers: { authorization: "Bearer t" },
}),
fetcher: (() =>
new Promise<Response>(() => {})) as unknown as typeof fetch,
observe: (observation) => observations.push(observation),
});
const callerController = new AbortController();
const callerPending = makeExecutor().execute(
bearerOperation(10_000),
{ limit: 1 },
{
routeId: ROUTE_ID,
scope: scopeSnapshot(),
signal: callerController.signal,
},
);
callerController.abort();
expect((await callerPending).kind).toBe("CANCELLED");
expect(observations.at(-1)?.cancellationOwner).toBe("CALLER");
const scopeController = new AbortController();
const scopePending = makeExecutor().execute(
bearerOperation(10_000),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot(scopeController.signal) },
);
scopeController.abort();
expect((await scopePending).kind).toBe("TRANSPORT_FAILURE");
expect(observations.at(-1)?.cancellationOwner).toBe("SCOPE_FENCE");
});
it("observes a late native rejection without an unhandled rejection", async () => {
const rejections: unknown[] = [];
const onUnhandled = (event: PromiseRejectionEvent) => {
rejections.push(event.reason);
event.preventDefault();
};
globalThis.addEventListener?.(
"unhandledrejection",
onUnhandled as EventListener,
);
try {
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
authProfiles: TEST_PROFILES,
attachCredentials: () =>
Object.freeze({
kind: "READY" as const,
headers: { authorization: "Bearer t" },
}),
fetcher: (() =>
new Promise<Response>((_resolve, reject) => {
setTimeout(() => reject(new Error("late native failure")), 30);
})) as unknown as typeof fetch,
});
const outcome = await executor.execute(
bearerOperation(5),
{ limit: 1 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("TRANSPORT_FAILURE");
await new Promise((resolve) => setTimeout(resolve, 60));
expect(rejections).toEqual([]);
} finally {
globalThis.removeEventListener?.(
"unhandledrejection",
onUnhandled as EventListener,
);
}
});
});
/**
* LIVE-05. A deadline TIMEOUT is an operational failure of the API call, not a
* caller decision. Excluding it from `api.request.failed` hides exactly the
* class of outage the telemetry exists to surface.
*/
describe("LIVE-05 deadline timeouts reach failure telemetry", () => {
function projectorHarness() {
const emitted: string[] = [];
const recorded: string[] = [];
const project = createHttpObservationProjector({
diagnostics: {
record: (input) => recorded.push(input.eventId),
},
telemetry: {
emit: (eventName) => emitted.push(eventName),
},
});
return { emitted, recorded, project };
}
const base = Object.freeze({
routeId: ROUTE_ID,
operationId: "TEST_LIST_ENTITIES",
diagnosticsOperation: "test.read",
errorKind: "TIMEOUT",
attemptCount: 1,
durationMs: 10,
effect: "NOT_APPLICABLE" as const,
terminalReason: "TIMEOUT",
});
it("emits exactly one api.request.failed for a deadline timeout", () => {
const harness = projectorHarness();
harness.project(
Object.freeze({
...base,
outcome: "TRANSPORT_FAILURE" as const,
cancellationOwner: "DEADLINE" as const,
}),
);
expect(harness.emitted).toEqual(["api.request.failed"]);
expect(harness.recorded).toEqual(["http.request.completed"]);
});
it("emits nothing for caller, route and shutdown cancellation", () => {
for (const owner of [
"CALLER",
"ROUTE_TRANSITION",
"SCOPE_FENCE",
"APPLICATION_SHUTDOWN",
] as const) {
const harness = projectorHarness();
harness.project(
Object.freeze({
...base,
outcome: "CANCELLED" as const,
errorKind: "REQUEST_ABORTED",
cancellationOwner: owner,
}),
);
expect(harness.emitted).toEqual([]);
}
});
it("still emits for an ordinary network and auth integration failure", () => {
const network = projectorHarness();
network.project(
Object.freeze({
...base,
outcome: "TRANSPORT_FAILURE" as const,
errorKind: "NETWORK_FAILURE",
terminalReason: "NETWORK_FAILURE",
}),
);
expect(network.emitted).toEqual(["api.request.failed"]);
const auth = projectorHarness();
auth.project(
Object.freeze({
...base,
outcome: "AUTH_INTEGRATION_FAILURE" as const,
errorKind: "CREDENTIAL_OWNER_FAILED",
terminalReason: "AUTH_INTEGRATION_FAILURE",
}),
);
expect(auth.emitted).toEqual(["api.request.failed"]);
});
});
@@ -0,0 +1,314 @@
import { describe, expect, it, vi } from "vitest";
import { createContractHttpExecutor } from "../../src/adapters/http/http-execution-v3.ts";
import type {
HttpExecutionObservation,
} from "../../src/adapters/http/http-execution-v3.ts";
import { createHttpObservationProjector } from "../../src/bootstrap/runtime-adapters.ts";
import { createReferenceFeatureInstalledInput } from "../../src/features/reference-feature/adapters/create-reference-feature-input.ts";
import {
DIAGNOSTIC_CONTEXT_ALLOWLIST,
projectDiagnosticRecord,
type DiagnosticRecordInput,
} from "../../src/contracts/diagnostics.ts";
import {
projectTelemetryEvent,
type TelemetryEventName,
} from "../../src/contracts/telemetry.ts";
import {
TEST_CREATE_HTTP_CONTRACT,
TEST_LIST_HTTP_CONTRACT,
} from "../helpers/external-contract-fixture.ts";
const ROUTE_ID = "TEST_ROUTE";
function scopeSnapshot(isCurrent: () => boolean = () => true) {
return Object.freeze({
generation: 1,
fingerprint: "scope-1",
identities: Object.freeze({}) as never,
signal: new AbortController().signal,
isCurrent,
});
}
type RecordedDiagnostic = DiagnosticRecordInput;
type RecordedTelemetry = Readonly<{
eventName: TelemetryEventName;
attributes: Readonly<Record<string, unknown>>;
}>;
function recordingSinks() {
const diagnostics: RecordedDiagnostic[] = [];
const telemetry: RecordedTelemetry[] = [];
return {
diagnostics,
telemetry,
projector: createHttpObservationProjector({
diagnostics: {
record(input: DiagnosticRecordInput) {
diagnostics.push(input);
},
},
telemetry: {
emit(
eventName: TelemetryEventName,
attributes: Record<string, unknown>,
) {
telemetry.push(Object.freeze({ eventName, attributes }));
},
},
}),
};
}
describe("V3 HTTP observability projection", () => {
it("projects every V3 terminal outcome through the closed diagnostics allowlist", async () => {
const sinks = recordingSinks();
const cases: readonly Readonly<{
label: string;
fetcher: typeof fetch;
}>[] = [
{
label: "SUCCESS",
fetcher: (async () =>
Response.json([{ id: "a", name: "A" }])) as unknown as typeof fetch,
},
{
label: "PROBLEM",
fetcher: (async () =>
Response.json(
{ type: "about:blank", title: "nope", status: 400 },
{ status: 400 },
)) as unknown as typeof fetch,
},
{
label: "TRANSPORT_FAILURE",
fetcher: (async () => {
throw new TypeError("network down");
}) as unknown as typeof fetch,
},
{
label: "CONTRACT_VIOLATION",
fetcher: (async () =>
new Response("<html/>", {
status: 200,
headers: { "content-type": "text/html" },
})) as unknown as typeof fetch,
},
];
for (const testCase of cases) {
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
attachCredentials: () => ({
kind: "READY" as const,
headers: {},
}),
fetcher: testCase.fetcher,
observe: sinks.projector,
});
await executor.execute(
TEST_LIST_HTTP_CONTRACT,
{ limit: 5 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
}
expect(sinks.diagnostics).toHaveLength(cases.length);
for (const recorded of sinks.diagnostics) {
expect(recorded.eventId).toBe("http.request.completed");
const contextKeys = Object.keys(recorded.context ?? {});
expect(contextKeys).toEqual(
expect.arrayContaining([
"route_id",
"operation_id",
"operation",
"outcome",
"error_kind",
"http_status_group",
"attempt_count_bucket",
"duration_bucket",
]),
);
for (const key of contextKeys) {
expect(DIAGNOSTIC_CONTEXT_ALLOWLIST).toContain(key);
}
expect(contextKeys).not.toContain("attempts");
expect(contextKeys).not.toContain("certainty");
const projection = projectDiagnosticRecord(recorded);
expect(projection.success).toBe(true);
}
});
it("emits one failure telemetry event for a non-abort terminal failure", async () => {
const sinks = recordingSinks();
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
attachCredentials: () => ({
kind: "READY" as const,
headers: {},
}),
fetcher: (async () => {
throw new TypeError("network down");
}) as unknown as typeof fetch,
observe: sinks.projector,
});
const outcome = await executor.execute(
TEST_LIST_HTTP_CONTRACT,
{ limit: 5 },
{ routeId: ROUTE_ID, scope: scopeSnapshot() },
);
expect(outcome.kind).toBe("TRANSPORT_FAILURE");
expect(sinks.telemetry).toHaveLength(1);
const emitted = sinks.telemetry[0];
expect(emitted?.eventName).toBe("api.request.failed");
expect(emitted?.attributes).toMatchObject({
route_id: ROUTE_ID,
operation_id: "TEST_LIST_ENTITIES",
error_kind: "NETWORK_FAILURE",
http_status_group: "none",
attempt_count_bucket: "1",
});
const projected = projectTelemetryEvent(
emitted?.eventName ?? "api.request.failed",
emitted?.attributes ?? {},
);
expect(projected.success).toBe(true);
expect(sinks.diagnostics).toHaveLength(1);
});
it("does not emit failure telemetry for caller cancellation or scope fencing", async () => {
const cancelled = recordingSinks();
const callerController = new AbortController();
callerController.abort();
const cancelledExecutor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
attachCredentials: () => ({
kind: "READY" as const,
headers: {},
}),
fetcher: (async () =>
Response.json([{ id: "a", name: "A" }])) as unknown as typeof fetch,
observe: cancelled.projector,
});
const cancelledOutcome = await cancelledExecutor.execute(
TEST_LIST_HTTP_CONTRACT,
{ limit: 5 },
{
routeId: ROUTE_ID,
scope: scopeSnapshot(),
signal: callerController.signal,
},
);
expect(cancelledOutcome.kind).toBe("CANCELLED");
expect(cancelled.diagnostics).toHaveLength(1);
expect(cancelled.telemetry).toHaveLength(0);
const fenced = recordingSinks();
const fencedExecutor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
attachCredentials: () => ({
kind: "READY" as const,
headers: {},
}),
fetcher: (async () =>
Response.json([{ id: "a", name: "A" }])) as unknown as typeof fetch,
observe: fenced.projector,
});
const fencedOutcome = await fencedExecutor.execute(
TEST_LIST_HTTP_CONTRACT,
{ limit: 5 },
{ routeId: ROUTE_ID, scope: scopeSnapshot(() => false) },
);
expect(fencedOutcome.kind).toBe("CONTRACT_VIOLATION");
expect(fenced.diagnostics).toHaveLength(1);
expect(fenced.telemetry).toHaveLength(0);
});
it("preserves the feature route id through the installed operation executor", async () => {
const seen: Array<Readonly<Record<string, unknown>>> = [];
const installed = createReferenceFeatureInstalledInput({
contractOperations: Object.freeze({
async execute(
_operationId: string,
_input: unknown,
context?: Readonly<Record<string, unknown>>,
) {
seen.push(Object.freeze({ ...(context ?? {}) }));
return Object.freeze({
kind: "SUCCESS" as const,
value: [],
metadata: Object.freeze({ status: 200 }),
effect: "NOT_APPLICABLE" as const,
});
},
}),
});
await installed.input.listResources({ limit: 20 });
await installed.input.getResource("resource-1");
expect(seen.map((context) => context.routeId)).toEqual([
"REFERENCE_RESOURCE_LIST",
"REFERENCE_RESOURCE_DETAIL",
]);
});
it("cannot change the HTTP result when diagnostics or telemetry throws", async () => {
const projector = createHttpObservationProjector({
diagnostics: {
record() {
throw new Error("diagnostics sink exploded");
},
},
telemetry: {
emit() {
throw new Error("telemetry sink exploded");
},
},
});
const observe = vi.fn((observation: HttpExecutionObservation) => {
projector(observation);
});
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
attachCredentials: () => ({
kind: "READY" as const,
headers: {},
}),
fetcher: (async () =>
Response.json({ id: "created", name: "Created" }, {
status: 201,
})) as unknown as typeof fetch,
observe,
});
const outcome = await executor.execute(
TEST_CREATE_HTTP_CONTRACT,
{ name: "Created" },
{
routeId: ROUTE_ID,
scope: scopeSnapshot(),
intent: Object.freeze({
intentId: "intent-1",
operationId: "TEST_CREATE_ENTITY",
canonicalInputIdentity: "opaque-input-identity",
idempotencyKey: "key-1",
createdAtMonotonicMs: 1,
}),
},
);
expect(outcome.kind).toBe("SUCCESS");
expect(observe).toHaveBeenCalledTimes(1);
});
});
+20 -12
View File
@@ -4,7 +4,10 @@ import path from "node:path";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { readBoundedBytes } from "../../src/adapters/http/bounded-body-reader.ts";
import { createContractHttpExecutor } from "../../src/adapters/http/http-execution-v3.ts";
import {
createContractHttpExecutor,
type HttpExecutionObservation,
} from "../../src/adapters/http/http-execution-v3.ts";
import {
type InstalledHttpContract,
} from "../../src/contracts/external-contract-runtime.ts";
@@ -30,6 +33,13 @@ import {
type HttpScenarioOperationId,
} from "../mocks/scenarios/catalog.ts";
/** The reference gateway owns these low-cardinality route identities. */
function routeIdFor(operationId: HttpScenarioOperationId): string {
return operationId === "GET_REFERENCE_RESOURCE"
? "REFERENCE_RESOURCE_DETAIL"
: "REFERENCE_RESOURCE_LIST";
}
const RECEIPT_PATH = path.resolve(
"artifacts/tests/http-scenario-executions.json",
);
@@ -191,11 +201,7 @@ async function executeScenario(
): Promise<HttpScenarioAssertionGroups> {
const physicalAttempts: AttemptTrace[] = [];
const sleeps: RetryReason[] = [];
const observations: Array<Readonly<{
outcome: string;
attempts: number;
certainty: string;
}>> = [];
const observations: HttpExecutionObservation[] = [];
const caller = new AbortController();
const scopeLifetime = new AbortController();
let scopeCurrent = true;
@@ -225,10 +231,11 @@ async function executeScenario(
const executor = createContractHttpExecutor({
baseUrl: "https://api.test",
maxRetryAttempts: 2,
// The reference contribution declares REFERENCE_EXTERNAL_BEARER, so the
// credential owner must supply the required proof header before dispatch.
attachCredentials: () => ({
kind: "READY",
headers: {},
credentials: "omit",
headers: { authorization: "Bearer scenario-token" },
}),
fetcher,
random: () => 0,
@@ -265,6 +272,7 @@ async function executeScenario(
try {
const execution = executor.execute(operation, inputFor(entry.operationId), {
routeId: routeIdFor(entry.operationId),
scope,
signal: caller.signal,
...(entry.operationId === "CREATE_REFERENCE_RESOURCE"
@@ -296,7 +304,7 @@ async function executeScenario(
const observation = observations[0]!;
const observedSignal = scopeLifetime.signal.aborted ? "ABORTED" : "ACTIVE";
const cancellationOwner =
observation.certainty === "TIMEOUT"
observation.terminalReason === "TIMEOUT"
? "DEADLINE"
: caller.signal.aborted
? "CALLER"
@@ -314,13 +322,13 @@ async function executeScenario(
}),
effect: Object.freeze({
outcome: String(outcome.effect),
observer: observation.certainty,
observer: observation.terminalReason,
}),
retry: Object.freeze({ count: sleeps.length, reasons: Object.freeze(sleeps) }),
fetch: Object.freeze({
count: physicalAttempts.length,
observerAttempts: observation.attempts,
agrees: physicalAttempts.length === observation.attempts,
observerAttempts: observation.attemptCount,
agrees: physicalAttempts.length === observation.attemptCount,
}),
media: Object.freeze({
attempts: Object.freeze(physicalAttempts.map((attempt) => attempt.media)),
@@ -0,0 +1,240 @@
import { HttpResponse, http } from "msw";
import { setupServer } from "msw/node";
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import { createHttpClient } from "../../src/adapters/http/client.ts";
import { defineRestOperation } from "../../src/contracts/api-operations.ts";
import { createRestProviderProfile } from "../../src/contracts/rest-profiles.ts";
import { TEST_HTTP_CONTRACT } from "../helpers/http-contract-fixture.ts";
/**
* LEG-01 / LEG-02. The V2 client is not the default path any more, but a
* rollback re-activates it, so its credential and recovery authority must match
* V3 rather than diverge quietly.
*/
const BEARER_LIST = defineRestOperation({
method: "GET",
path: "/api/entities",
operationId: "LIST_ENTITIES",
auth: "external-session",
timeoutMs: null,
idempotency: "safe",
retry: "runtime",
requestSource: "search",
requestSchema: "EntityListQuery",
responseSchema: "EntityListPayload",
owner: "test-fixture",
contractVersion: 2,
protocol: "REST",
semantics: "QUERY",
replayPolicy: "SAFE",
idempotencyKeyPolicy: "NONE",
mapperId: "EntityListMapper",
successStatuses: [200],
responseMediaTypes: ["application/json"],
maxResponseBytes: 32_768,
providerId: "PRIMARY_API",
authProfileId: "REFERENCE_EXTERNAL_BEARER",
csrfProfileId: "NO_CSRF_BEARER",
pathSchema: "NoRequest",
pathParameterNames: [],
maxEncodedSearchBytes: 1_024,
});
let observedAuthorization: string | null = null;
let requestCount = 0;
let nextStatus = 200;
const server = setupServer(
http.get("https://api.test/api/entities", ({ request }) => {
requestCount += 1;
observedAuthorization = request.headers.get("authorization");
if (nextStatus === 401) {
return HttpResponse.json(
{
success: false,
error: { code: "UNAUTHENTICATED" },
meta: { requestId: "request-1", traceId: "trace-1" },
},
{ status: 401 },
);
}
return HttpResponse.json({
success: true,
data: [{ id: "resource-1", name: "Example" }],
meta: { requestId: "request-2", traceId: "trace-1" },
});
}),
);
beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
afterEach(() => {
observedAuthorization = null;
requestCount = 0;
nextStatus = 200;
server.resetHandlers();
});
afterAll(() => server.close());
const clock = { now: () => 0, sleep: async () => {} };
type HttpDependencies = Parameters<typeof createHttpClient>[0];
function bearerClient(options: Partial<HttpDependencies>) {
return createHttpClient({
...TEST_HTTP_CONTRACT,
getOperation: (operationId: string) => {
if (operationId !== "LIST_ENTITIES") {
throw new Error(`Unknown test operation: ${operationId}`);
}
return BEARER_LIST;
},
baseUrl: "https://api.test",
providerProfile: createRestProviderProfile("PRIMARY_API", "https://api.test", [
"omit",
]),
// The V2 fixture declares `NoRequest` for its path codec, which the shared
// schema registry does not carry.
validatePath: () => ({ success: true as const, data: {} }),
clock,
...options,
} as HttpDependencies);
}
function sessionStub(
overrides: Partial<{
getState: () => "authenticated" | "unauthenticated" | "recovery-pending" | "integration-failed";
credentialPatch: (...args: never[]) => Promise<{ headers: Record<string, string> }>;
recover: (...args: never[]) => Promise<"restored" | "no-session">;
onUnauthenticated: () => void;
}> = {},
) {
return {
getState: () => "authenticated" as const,
subscribe: () => () => {},
beginSignIn: async () => {},
signOut: async () => {},
credentialPatch: async () => ({ headers: { authorization: "Bearer t" } }),
recover: async () => "restored" as const,
onUnauthenticated: () => {},
...overrides,
};
}
describe("LEG-02 the bearer profile's required header is enforced", () => {
it("refuses to dispatch when a READY patch omits authorization", async () => {
const client = bearerClient({
authSession: sessionStub({
credentialPatch: async () => ({ headers: {} }),
}) as never,
});
await expect(client.execute("LIST_ENTITIES")).resolves.toMatchObject({
ok: false,
error: { kind: "AUTH_INTEGRATION_FAILURE" },
});
expect(requestCount).toBe(0);
});
it("rejects a malformed or duplicated authorization value", async () => {
const hostilePatches: readonly Record<string, string>[] = [
{ authorization: "" },
{ authorization: "Bearer bad\nvalue" },
{ Authorization: "Bearer a", authorization: "Bearer b" },
];
for (const headers of hostilePatches) {
const client = bearerClient({
authSession: sessionStub({
credentialPatch: async () => ({ headers }),
}) as never,
});
await expect(client.execute("LIST_ENTITIES")).resolves.toMatchObject({
ok: false,
error: { kind: "AUTH_INTEGRATION_FAILURE" },
});
}
expect(requestCount).toBe(0);
});
it("dispatches with the admitted authorization header", async () => {
const client = bearerClient({
authSession: sessionStub() as never,
});
await expect(client.execute("LIST_ENTITIES")).resolves.toMatchObject({
ok: true,
});
expect(observedAuthorization).toBe("Bearer t");
});
});
describe("LEG-01 recovery notification follows the adopted result", () => {
it("does not sign the user out when recovery answers after the deadline", async () => {
nextStatus = 401;
const onUnauthenticated = vi.fn();
let elapsed = 0;
const client = bearerClient({
clock: {
now: () => elapsed,
sleep: async () => {},
},
timeoutMs: 20,
authSession: sessionStub({
onUnauthenticated,
recover: async () => {
// The request's own deadline expires while recovery is still out.
elapsed = 10_000;
await new Promise((resolve) => setTimeout(resolve, 30));
return "no-session" as const;
},
}) as never,
});
const outcome = await client.execute("LIST_ENTITIES");
expect(outcome.ok).toBe(false);
await new Promise((resolve) => setTimeout(resolve, 60));
expect(onUnauthenticated).toHaveBeenCalledTimes(0);
});
it("signs the user out exactly once for an adopted no-session result", async () => {
nextStatus = 401;
const onUnauthenticated = vi.fn();
const client = bearerClient({
authSession: sessionStub({
onUnauthenticated,
recover: async () => "no-session" as const,
}) as never,
});
await expect(client.execute("LIST_ENTITIES")).resolves.toMatchObject({
ok: false,
error: { kind: "AUTH_REQUIRED" },
});
expect(onUnauthenticated).toHaveBeenCalledTimes(1);
});
it("stays bounded when recovery never settles", async () => {
nextStatus = 401;
const onUnauthenticated = vi.fn();
let elapsed = 0;
const client = bearerClient({
clock: {
now: () => {
elapsed += 5;
return elapsed;
},
sleep: async () => {},
},
timeoutMs: 20,
authSession: sessionStub({
onUnauthenticated,
recover: () => new Promise<"restored">(() => {}),
}) as never,
});
const outcome = await client.execute("LIST_ENTITIES");
expect(outcome.ok).toBe(false);
expect(onUnauthenticated).toHaveBeenCalledTimes(0);
});
});
@@ -1,5 +1,5 @@
import { spawnSync } from "node:child_process";
import { cp, mkdir, mkdtemp, readFile, rm, symlink, writeFile } from "node:fs/promises";
import { cp, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
@@ -15,6 +15,7 @@ import {
RELEASE_CANDIDATE_MANIFEST_PATH,
releaseCandidateManifestSchema,
} from "../../scripts/lib/release-candidate.ts";
import { linkFixtureNodeModules } from "../../scripts/lib/fixture-node-modules.ts";
it(
"builds a real candidate assessment and passes the default archived verifier from the captured archive",
@@ -43,7 +44,7 @@ it(
recursive: true,
force: true,
});
await symlink(path.join(sourceRoot, "node_modules"), path.join(fixtureRoot, "node_modules"), "dir");
await linkFixtureNodeModules(fixtureRoot, sourceRoot);
const git = spawnSync("git", ["show", "-s", "--format=%H%n%ct", "HEAD"], {
cwd: sourceRoot,
encoding: "utf8",