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
+118 -27
View File
@@ -6,7 +6,17 @@ import {
} from "../adapters/auth/external-session-adapter.ts";
import { createDiagnosticsAdapter } from "../adapters/diagnostics/bounded-diagnostics.ts";
import { createHttpClient } from "../adapters/http/client.ts";
import { createContractHttpExecutor } from "../adapters/http/http-execution-v3.ts";
import {
createContractHttpExecutor,
type HttpExecutionObservation,
} from "../adapters/http/http-execution-v3.ts";
import {
attemptBucket,
durationBucket,
statusGroup,
type DiagnosticRecordInput,
} from "../contracts/diagnostics.ts";
import type { TelemetryEventName } from "../contracts/telemetry.ts";
import { createBrowserCrossContextInvalidationFromHost } from "../adapters/cross-context-invalidation/index.ts";
import {
createTanStackCacheCoordinator,
@@ -19,7 +29,10 @@ import { createBrowserMutationIntentFactory } from "../adapters/platform/browser
import { createTelemetryAdapter } from "../adapters/telemetry/best-effort-telemetry.ts";
import type { AuthSessionPort } from "../application/ports/auth-session-port.ts";
import type { ReleaseInfo } from "../application/ports/release-info-port.ts";
import { createRestProviderProfile } from "../contracts/rest-profiles.ts";
import {
createRestProviderProfile,
INSTALLED_REST_AUTH_PROFILES,
} from "../contracts/rest-profiles.ts";
import type { ClockPort } from "../application/ports/clock-port.ts";
import type { MutationIntent } from "../contracts/mutation-intent.ts";
import { createInstalledFeatureInputs } from "../features/installed-feature-adapters.ts";
@@ -162,6 +175,89 @@ export function createRuntimeHttpClient(
});
}
/**
* VD-07. Exactly one diagnostic per logical V3 execution and exactly one
* `api.request.failed` telemetry event per terminal non-abort failure.
*
* The projection is closed: only registered context keys and bucketed values
* reach the sinks, and neither sink can change the HTTP outcome, because the
* caller invokes this inside the executor's isolated observation boundary.
*/
export function createHttpObservationProjector(
sinks: Readonly<{
diagnostics: Readonly<{ record(input: DiagnosticRecordInput): void }>;
telemetry: Readonly<{
emit(
eventName: TelemetryEventName,
attributes: Record<string, unknown>,
): void;
}>;
}>,
): (observation: HttpExecutionObservation) => void {
return (observation) => {
const safeAttributes = {
route_id: observation.routeId,
operation_id: observation.operationId,
error_kind: observation.errorKind,
http_status_group: statusGroup(observation.status),
attempt_count_bucket: attemptBucket(observation.attemptCount),
duration_bucket: durationBucket(observation.durationMs),
};
try {
sinks.diagnostics.record({
level: observation.outcome === "SUCCESS" ? "info" : "warn",
eventId: "http.request.completed",
context: {
...safeAttributes,
operation: observation.diagnosticsOperation,
outcome: observation.outcome,
},
});
} catch {
// Diagnostics cannot change a contract execution outcome.
}
if (!isTerminalNonAbortFailure(observation)) return;
try {
sinks.telemetry.emit("api.request.failed", { ...safeAttributes });
} catch {
// Telemetry cannot change a contract execution outcome.
}
};
}
/**
* LIVE-05. Cancellation and scope fencing are caller- or generation-owned
* decisions, not API failures: they produce a diagnostic once and never
* `api.request.failed`.
*
* A `DEADLINE` owner is the opposite case. Nobody asked for it — the API did
* not answer inside the contract's own budget — so excluding it would hide
* exactly the outage this event exists to report.
*/
const CALLER_OWNED_CANCELLATION: ReadonlySet<string> = new Set([
"CALLER",
"ROUTE_TRANSITION",
"SCOPE_FENCE",
"APPLICATION_SHUTDOWN",
]);
function isTerminalNonAbortFailure(
observation: HttpExecutionObservation,
): boolean {
if (observation.outcome === "SUCCESS") return false;
if (observation.outcome === "CANCELLED") return false;
if (
observation.cancellationOwner !== undefined &&
CALLER_OWNED_CANCELLATION.has(observation.cancellationOwner)
) {
return false;
}
return !(
observation.outcome === "CONTRACT_VIOLATION" &&
observation.errorKind === "SCOPE_FENCED"
);
}
export async function createRuntimeAdapters(
context: RuntimeAdaptersContext,
) {
@@ -299,7 +395,10 @@ export async function createRuntimeAdapters(
baseUrl: config.API_BASE_URL,
maxRetryAttempts: config.MAX_RETRY_ATTEMPTS,
fetcher: context.fetcher,
async attachCredentials(operation) {
// §7.7. The installed registry owns Fetch credentials and the exact
// credential-header sets; this collaborator only supplies proof headers.
authProfiles: INSTALLED_REST_AUTH_PROFILES,
async attachCredentials(operation, authContext) {
if (serverStateScope.getPhase() !== "READY") {
return Object.freeze({ kind: "SCOPE_FENCED" as const });
}
@@ -311,49 +410,36 @@ export async function createRuntimeAdapters(
return Object.freeze({ kind: "UNAUTHENTICATED" as const });
}
try {
const patch = await authSession.credentialPatch({
origin: new URL(config.API_BASE_URL).origin,
method: operation.method,
operationId: operation.operationId,
});
const patch = await authSession.credentialPatch(
{
origin: new URL(config.API_BASE_URL).origin,
method: operation.method,
operationId: operation.operationId,
},
authContext,
);
if (serverStateScope.getPhase() !== "READY") {
return Object.freeze({ kind: "SCOPE_FENCED" as const });
}
return Object.freeze({
kind: "READY" as const,
headers: patch.headers,
credentials: "omit" as const,
});
} catch {
return Object.freeze({ kind: "UNAVAILABLE" as const });
}
},
observe(observation) {
try {
diagnostics.record({
level:
observation.outcome === "SUCCESS" ? "info" : "warn",
eventId: "http.request.completed",
context: {
operation_id: observation.diagnosticsOperation,
outcome: observation.outcome,
attempts: observation.attempts,
certainty: observation.certainty,
},
});
} catch {
// Diagnostics cannot change a contract execution outcome.
}
},
observe: createHttpObservationProjector({ diagnostics, telemetry }),
});
const contractOperations = Object.freeze({
async execute(
operationId: string,
input: unknown,
executionContext: Readonly<{
routeId: string;
signal?: AbortSignal;
intent?: MutationIntent;
}> = {},
}>,
) {
const operation =
COMPOSED_CONTRACT_CONTRIBUTIONS.httpByOperationId.get(operationId);
@@ -368,6 +454,7 @@ export async function createRuntimeAdapters(
});
}
const outcome = await contractHttp.execute(operation, input, {
routeId: executionContext.routeId,
scope: serverStateScope.getSnapshot(),
...(executionContext.signal === undefined
? {}
@@ -410,6 +497,10 @@ export async function createRuntimeAdapters(
crossContextInvalidationStatus: () =>
serverStateGeneration.getSnapshot().crossContextStatus(),
dispose() {
// N-04. Telemetry is torn down first: it must stop scheduling and
// delivering before the diagnostics and state dependencies it observes
// are destroyed.
telemetry.dispose();
conditionalValidators.clear();
serverStateScope.dispose();
serverStateGeneration.dispose();