Files
tech-log-frontend/tests/integration/http-execution-v3-auth-profile.test.ts
DongHyeonkaandClaude Opus 5 4bff9ca151 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>
2026-08-15 12:04:58 +09:00

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([]);
});
});