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:
co-authored by
Claude Opus 5
parent
002ba3624e
commit
4bff9ca151
@@ -5,6 +5,46 @@ import type {
|
||||
CursorPaginationRuntime,
|
||||
} from "../../contracts/cursor-pagination.ts";
|
||||
import { createFailure } from "../../contracts/errors.ts";
|
||||
import { snapshotExactObject } from "../../contracts/exact-snapshot.ts";
|
||||
|
||||
const ABORTED = Symbol("PAGINATION_ABORTED");
|
||||
|
||||
/**
|
||||
* Resolves as soon as the operation settles or the signal aborts, whichever
|
||||
* comes first. A late operation result is observed and discarded, never thrown
|
||||
* as an unhandled rejection.
|
||||
*
|
||||
* OPT-NET-01. A loader rejection is *not* an abort. The presence of a signal
|
||||
* says nothing about why the loader failed, so a rejection is re-thrown exactly
|
||||
* as it would be with no signal at all; only a signal that has actually
|
||||
* aborted classifies the outcome as cancellation.
|
||||
*/
|
||||
async function raceAbort<Value>(
|
||||
operation: Promise<Value>,
|
||||
signal: AbortSignal | undefined,
|
||||
): Promise<Value | typeof ABORTED> {
|
||||
operation.catch(() => {});
|
||||
if (!signal) return await operation;
|
||||
if (signal.aborted) return ABORTED;
|
||||
return await new Promise<Value | typeof ABORTED>((resolve, reject) => {
|
||||
const onAbort = () => resolve(ABORTED);
|
||||
signal.addEventListener("abort", onAbort, { once: true });
|
||||
operation.then(
|
||||
(value) => {
|
||||
signal.removeEventListener("abort", onAbort);
|
||||
resolve(value);
|
||||
},
|
||||
(reason: unknown) => {
|
||||
signal.removeEventListener("abort", onAbort);
|
||||
if (signal.aborted) {
|
||||
resolve(ABORTED);
|
||||
return;
|
||||
}
|
||||
reject(reason);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function createCursorPaginationRuntime<Value>(dependencies: Readonly<{
|
||||
definitionId: string;
|
||||
@@ -14,7 +54,17 @@ export function createCursorPaginationRuntime<Value>(dependencies: Readonly<{
|
||||
context: Readonly<{ signal?: AbortSignal }>,
|
||||
): Promise<Result<CursorPage<Value>>>;
|
||||
}>): CursorPaginationRuntime<Value> {
|
||||
validateProfile(dependencies.profile);
|
||||
// NS-07. The caps are captured once, here. Validating the caller's profile and
|
||||
// then reading it again on every page let a `maxPages` of 1 become 3 after
|
||||
// construction, so the request count, item total and byte ceiling that were
|
||||
// checked were not the ones the loop enforced. The collaborators are captured
|
||||
// for the same reason.
|
||||
const profile = snapshotProfile(dependencies.profile);
|
||||
const definitionId = dependencies.definitionId;
|
||||
const loadPage = dependencies.loadPage;
|
||||
if (typeof definitionId !== "string" || typeof loadPage !== "function") {
|
||||
throw new TypeError("Invalid cursor pagination dependencies.");
|
||||
}
|
||||
return Object.freeze({
|
||||
async loadAll(context) {
|
||||
const items: Value[] = [];
|
||||
@@ -23,16 +73,28 @@ export function createCursorPaginationRuntime<Value>(dependencies: Readonly<{
|
||||
let snapshot: string | null | undefined;
|
||||
for (
|
||||
let pageIndex = 0;
|
||||
pageIndex < dependencies.profile.maxPages;
|
||||
pageIndex < profile.maxPages;
|
||||
pageIndex += 1
|
||||
) {
|
||||
if (context.signal?.aborted) {
|
||||
return failure("REQUEST_ABORTED", "PAGINATION_ABORTED");
|
||||
}
|
||||
const result = await dependencies.loadPage(cursor, context);
|
||||
// N-10. A non-cooperative loader may never settle, or may settle after
|
||||
// abort. Race the signal so `loadAll` is bounded, and re-check before
|
||||
// observing the page so a late completion is ignored rather than
|
||||
// accumulated into a successful result.
|
||||
const raced: Result<CursorPage<Value>> | typeof ABORTED =
|
||||
await raceAbort<Result<CursorPage<Value>>>(
|
||||
loadPage(cursor, context),
|
||||
context.signal,
|
||||
);
|
||||
if (raced === ABORTED || context.signal?.aborted) {
|
||||
return failure("REQUEST_ABORTED", "PAGINATION_ABORTED");
|
||||
}
|
||||
const result: Result<CursorPage<Value>> = raced;
|
||||
if (!result.ok) return result;
|
||||
const page = result.value;
|
||||
if (!isValidPage(page, dependencies.profile)) {
|
||||
const page: CursorPage<Value> = result.value;
|
||||
if (!isValidPage(page, profile)) {
|
||||
return failure(
|
||||
"PAGINATION_CONTRACT_VIOLATION",
|
||||
"PAGINATION_PAGE_INVALID",
|
||||
@@ -48,8 +110,8 @@ export function createCursorPaginationRuntime<Value>(dependencies: Readonly<{
|
||||
}
|
||||
items.push(...page.items);
|
||||
if (
|
||||
items.length > dependencies.profile.maxTotalItems ||
|
||||
estimatedBytes(items) > dependencies.profile.maxEstimatedBytes
|
||||
items.length > profile.maxTotalItems ||
|
||||
estimatedBytes(items) > profile.maxEstimatedBytes
|
||||
) {
|
||||
return failure(
|
||||
"RESULT_LIMIT_EXCEEDED",
|
||||
@@ -57,7 +119,7 @@ export function createCursorPaginationRuntime<Value>(dependencies: Readonly<{
|
||||
);
|
||||
}
|
||||
if (!page.hasMore) return { ok: true, value: Object.freeze(items) };
|
||||
const nextCursor = page.nextCursor;
|
||||
const nextCursor: string | null = page.nextCursor;
|
||||
if (!nextCursor || cursors.has(nextCursor)) {
|
||||
return failure(
|
||||
"PAGINATION_CONTRACT_VIOLATION",
|
||||
@@ -83,13 +145,46 @@ export function createCursorPaginationRuntime<Value>(dependencies: Readonly<{
|
||||
) {
|
||||
return {
|
||||
ok: false as const,
|
||||
error: createFailure(kind, dependencies.definitionId, 0, { code }),
|
||||
error: createFailure(kind, definitionId, 0, { code }),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NS-07. Copies the profile into an owned frozen record, reading every field
|
||||
* exactly once, and validates that copy. An accessor, an inherited or extra
|
||||
* field, a symbol key or a Proxy trap fails closed rather than becoming a cap
|
||||
* that can change after it was checked.
|
||||
*/
|
||||
function snapshotProfile(source: unknown): CursorPaginationProfile {
|
||||
const profile = snapshotExactObject(source, {
|
||||
allowed: [
|
||||
"profileId",
|
||||
"maxPages",
|
||||
"maxTotalItems",
|
||||
"maxEstimatedBytes",
|
||||
"maxCursorBytes",
|
||||
"allowSparsePage",
|
||||
],
|
||||
required: [
|
||||
"profileId",
|
||||
"maxPages",
|
||||
"maxTotalItems",
|
||||
"maxEstimatedBytes",
|
||||
"maxCursorBytes",
|
||||
"allowSparsePage",
|
||||
],
|
||||
}) as CursorPaginationProfile | null;
|
||||
if (profile === null || typeof profile.allowSparsePage !== "boolean") {
|
||||
throw new TypeError("Invalid cursor pagination profile.");
|
||||
}
|
||||
validateProfile(profile);
|
||||
return profile;
|
||||
}
|
||||
|
||||
function validateProfile(profile: CursorPaginationProfile): void {
|
||||
if (
|
||||
typeof profile.profileId !== "string" ||
|
||||
!profile.profileId ||
|
||||
!Number.isSafeInteger(profile.maxPages) ||
|
||||
profile.maxPages < 1 ||
|
||||
|
||||
Reference in New Issue
Block a user