Files
tech-log-frontend/src/adapters/browser-transfer/image-cdn/image-cdn-runtime.ts
T
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

1352 lines
39 KiB
TypeScript

import type {
BackendIssuedImageAsset,
ImageAssetReference,
ImageCapabilityVerifier,
ImageCdnRuntime,
ImageOutputFormat,
ImagePresentationDescriptor,
ImagePresetReference,
ImageProbeReceipt,
ImageRasterMediaType,
ImageResourceProbePort,
PublicImmutableImageAsset,
} from "../../../application/ports/browser-transfer/image-cdn.ts";
import type {
BrowserDataObserver,
BrowserDataResult,
} from "../../../application/ports/browser-file-storage/shared.ts";
import {
browserDataFailure,
browserDataSuccess,
observeBrowserData,
} from "../../browser-file-storage/result.ts";
import {
IMAGE_FORMAT_MEDIA_TYPE,
type ImageCandidateGeometry,
type ImageCdnHardLimits,
type ImageCdnPolicyRegistry,
type ResolvedImageCdnOrigin,
type ResolvedImageCdnPreset,
} from "./image-cdn-policy.ts";
export type ImageCdnRuntimeDependencies = Readonly<{
policies: ImageCdnPolicyRegistry;
now?: () => number;
subtle?: Pick<SubtleCrypto, "digest">;
capabilityVerifier?: ImageCapabilityVerifier;
capabilityVerificationTimeoutMs?: number;
capabilityVerificationScheduler?: ImageCapabilityVerificationScheduler;
probe?: ImageResourceProbePort;
observer?: BrowserDataObserver;
}>;
export type ImageCapabilityVerificationScheduler = Readonly<{
setTimeout(callback: () => void, milliseconds: number): unknown;
clearTimeout(handle: unknown): void;
}>;
export const DEFAULT_IMAGE_CAPABILITY_VERIFICATION_TIMEOUT_MS = 5_000;
export const MAX_IMAGE_CAPABILITY_VERIFICATION_TIMEOUT_MS = 60_000;
type AssetSnapshot = Readonly<{
origin: ResolvedImageCdnOrigin;
assetId: string;
revision: string;
mediaType: ImageRasterMediaType;
intrinsicWidth: number;
intrinsicHeight: number;
delivery: "PUBLIC_IMMUTABLE" | "PRIVATE_SIGNED";
capability: Readonly<{
capabilityId: string;
expiresAtEpochMs: number;
allowedPresetBindingIds: ReadonlySet<string>;
keyId: string;
capabilityBindingDigestHex: string;
signatureBase64Url: string;
}> | null;
}>;
type IssuedDescriptorSnapshot = BackendIssuedImageAsset;
const OPAQUE_TOKEN = /^[A-Za-z0-9_-]{8,128}$/u;
const SIGNATURE = /^[A-Za-z0-9_-]{16,512}$/u;
const SHA256_HEX = /^[a-f0-9]{64}$/u;
const PUBLIC_DESCRIPTOR_KEYS = Object.freeze([
"kind",
"originKey",
"assetId",
"revision",
"mediaType",
"contentKind",
"intrinsicWidth",
"intrinsicHeight",
] as const);
const ISSUED_DESCRIPTOR_KEYS = Object.freeze([
"kind",
"issuer",
"originKey",
"assetId",
"revision",
"mediaType",
"contentKind",
"intrinsicWidth",
"intrinsicHeight",
"capabilityId",
"issuedAtEpochMs",
"expiresAtEpochMs",
"allowedPresetBindingIds",
"signature",
] as const);
const SIGNATURE_KEYS = Object.freeze([
"algorithm",
"keyId",
"capabilityBindingDigestHex",
"valueBase64Url",
] as const);
const RESOLVE_KEYS = Object.freeze([
"asset",
"preset",
"signal",
] as const);
const ACCEPT_OPTIONS_KEYS = Object.freeze(["signal"] as const);
/**
* Creates the public runtime factory. Composition should expose
* `presentation` to features and keep `assets` at the backend gateway seam.
*/
export function createImageCdnRuntime(
dependencies: ImageCdnRuntimeDependencies,
): ImageCdnRuntime {
const resolveOrigin =
dependencies.policies.resolveOrigin.bind(dependencies.policies);
const resolvePreset =
dependencies.policies.resolvePreset.bind(dependencies.policies);
const hasPresetBinding =
dependencies.policies.hasPresetBinding.bind(dependencies.policies);
const hardLimits = snapshotHardLimits(
dependencies.policies.hardLimits(),
);
const resolvedCapabilityPolicy =
dependencies.policies.capabilityPolicy();
const capabilityPolicy = Object.freeze({
issuer: resolvedCapabilityPolicy.issuer,
acceptedKeyIds: new Set(
resolvedCapabilityPolicy.acceptedKeyIds,
),
});
const now = dependencies.now ?? Date.now;
const digest = dependencies.subtle?.digest.bind(dependencies.subtle);
const verifyCapability =
dependencies.capabilityVerifier?.verify.bind(
dependencies.capabilityVerifier,
);
const acceptsCapabilityKey =
dependencies.capabilityVerifier?.acceptsKey.bind(
dependencies.capabilityVerifier,
);
if (dependencies.capabilityVerifier) {
try {
if (
!verifyCapability ||
!acceptsCapabilityKey ||
[...capabilityPolicy.acceptedKeyIds].some(
(keyId) => acceptsCapabilityKey(keyId) !== true,
)
) {
throw new TypeError(
"Image capability verifier registry does not cover policy keys.",
);
}
} catch {
throw new TypeError(
"Image capability verifier registry does not cover policy keys.",
);
}
}
const capabilityVerificationTimeoutMs =
dependencies.capabilityVerificationTimeoutMs ??
DEFAULT_IMAGE_CAPABILITY_VERIFICATION_TIMEOUT_MS;
if (
!Number.isSafeInteger(capabilityVerificationTimeoutMs) ||
capabilityVerificationTimeoutMs < 1 ||
capabilityVerificationTimeoutMs >
MAX_IMAGE_CAPABILITY_VERIFICATION_TIMEOUT_MS
) {
throw new TypeError(
"Image capability verification timeout is invalid.",
);
}
const capabilityVerificationScheduler =
snapshotCapabilityVerificationScheduler(
dependencies.capabilityVerificationScheduler ??
defaultCapabilityVerificationScheduler(),
);
const probe =
dependencies.probe?.probe.bind(dependencies.probe);
const observer = snapshotObserver(dependencies.observer);
let acceptedAssets =
new WeakMap<ImageAssetReference, AssetSnapshot>();
const lifetime = new AbortController();
let activeCapabilityVerifications = 0;
let closed = false;
const acceptPublicImmutableCore:
ImageCdnRuntime["assets"]["acceptPublicImmutable"] = (
descriptor,
) => {
if (closed) return imageRuntimeClosedFailure();
const snapshot = snapshotPublicDescriptor(descriptor);
if (!snapshot) {
return browserDataFailure("INVALID_INPUT", "IMAGE_RESOLVE");
}
const origin = resolveOrigin(snapshot.originKey);
if (
snapshot.kind !== "ALLOWLISTED_PUBLIC" ||
!origin ||
!validAssetMetadata(snapshot, hardLimits)
) {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
const reference = createAssetReference();
acceptedAssets.set(
reference,
Object.freeze({
origin,
assetId: snapshot.assetId,
revision: snapshot.revision,
mediaType: snapshot.mediaType,
intrinsicWidth: snapshot.intrinsicWidth,
intrinsicHeight: snapshot.intrinsicHeight,
delivery: "PUBLIC_IMMUTABLE",
capability: null,
}),
);
return browserDataSuccess(reference);
};
const acceptPublicImmutable:
ImageCdnRuntime["assets"]["acceptPublicImmutable"] = (
descriptor,
) => {
const result = acceptPublicImmutableCore(descriptor);
return observeImageTerminal(
observer,
result,
result.ok ? 1 : 0,
);
};
const acceptBackendIssuedCore:
ImageCdnRuntime["assets"]["acceptBackendIssued"] = async (
descriptor,
options = {},
) => {
if (closed) return imageRuntimeClosedFailure();
if (
!hasOnlyOwnKeys(options, ACCEPT_OPTIONS_KEYS) ||
!validOptionalSignal(options.signal)
) {
return browserDataFailure("INVALID_INPUT", "IMAGE_RESOLVE");
}
if (options.signal?.aborted) {
return browserDataFailure("ABORTED", "IMAGE_RESOLVE");
}
const snapshot = snapshotIssuedDescriptor(descriptor);
if (!snapshot) {
return browserDataFailure("INVALID_INPUT", "IMAGE_RESOLVE");
}
const origin = resolveOrigin(snapshot.originKey);
if (
!origin ||
!validAssetMetadata(snapshot, hardLimits) ||
snapshot.issuer !== capabilityPolicy.issuer ||
!capabilityPolicy.acceptedKeyIds.has(
snapshot.signature.keyId,
) ||
snapshot.allowedPresetBindingIds.length >
hardLimits.maxPresetBindingsPerCapability ||
snapshot.allowedPresetBindingIds.some(
(bindingId) => !hasPresetBinding(bindingId),
)
) {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
const acceptedAt = safeNow(now);
if (acceptedAt === null) {
return browserDataFailure("UNAVAILABLE", "IMAGE_RESOLVE", {
retryable: true,
recovery: "RETRY",
});
}
const capabilityLifetimeMs =
snapshot.expiresAtEpochMs - snapshot.issuedAtEpochMs;
if (
snapshot.issuedAtEpochMs >
acceptedAt + hardLimits.maxClockSkewMs ||
capabilityLifetimeMs <= 0 ||
capabilityLifetimeMs > hardLimits.maxCapabilityLifetimeMs
) {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
if (
snapshot.expiresAtEpochMs - acceptedAt <
hardLimits.minCapabilityRemainingMs
) {
return browserDataFailure(
"EXPIRED_RESOURCE",
"IMAGE_RESOLVE",
);
}
if (!digest || !verifyCapability || !acceptsCapabilityKey) {
return browserDataFailure("UNSUPPORTED", "IMAGE_RESOLVE");
}
let verifierAcceptsDescriptorKey: boolean;
try {
verifierAcceptsDescriptorKey =
acceptsCapabilityKey(snapshot.signature.keyId) === true;
} catch {
return browserDataFailure("UNAVAILABLE", "IMAGE_RESOLVE", {
retryable: true,
recovery: "RETRY",
});
}
if (!verifierAcceptsDescriptorKey) {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
if (
activeCapabilityVerifications >=
hardLimits.maxConcurrentCapabilityVerifications
) {
return browserDataFailure(
"LIMIT_EXCEEDED",
"IMAGE_RESOLVE",
);
}
activeCapabilityVerifications += 1;
// TR-RR-07. The slot belongs to the raw verifier, not to this wrapper.
// Releasing it when the wrapper's deadline expired let an abandoned
// verification keep running while a new one was admitted, so repeated
// timeouts produced more physical work than the configured cap allows.
const rawVerificationTasks: Promise<unknown>[] = [];
try {
const canonicalPayload =
canonicalImageCapabilityPayload(snapshot);
let bindingDigest: string;
let verified: boolean;
let deadline: ImageCapabilityVerificationDeadline;
try {
deadline = createCapabilityVerificationDeadline(
[options.signal, lifetime.signal],
capabilityVerificationTimeoutMs,
capabilityVerificationScheduler,
);
} catch {
return browserDataFailure("UNAVAILABLE", "IMAGE_RESOLVE", {
retryable: true,
recovery: "RETRY",
});
}
try {
if (deadline.signal.aborted) {
throw capabilityVerificationAbortException();
}
const digestTask = sha256Hex(digest, canonicalPayload);
rawVerificationTasks.push(digestTask);
bindingDigest = await awaitImageRuntimeAbort(
digestTask,
deadline.signal,
);
if (
!constantTimeHexEqual(
bindingDigest,
snapshot.signature.capabilityBindingDigestHex,
)
) {
return browserDataFailure(
"INTEGRITY_FAILED",
"IMAGE_RESOLVE",
);
}
if (deadline.signal.aborted) {
throw capabilityVerificationAbortException();
}
const verifyTask = verifyCapability({
algorithm: snapshot.signature.algorithm,
keyId: snapshot.signature.keyId,
canonicalPayload: Uint8Array.from(canonicalPayload),
signatureBase64Url: snapshot.signature.valueBase64Url,
});
rawVerificationTasks.push(verifyTask);
verified = await awaitImageRuntimeAbort(
verifyTask,
deadline.signal,
);
} catch {
if (closed) return imageRuntimeClosedFailure();
return capabilityVerificationFailure(options.signal);
} finally {
deadline.release();
}
if (closed) return imageRuntimeClosedFailure();
if (options.signal?.aborted) {
return browserDataFailure("ABORTED", "IMAGE_RESOLVE");
}
if (verified !== true) {
return browserDataFailure(
"INTEGRITY_FAILED",
"IMAGE_RESOLVE",
);
}
const verifiedAt = safeNow(now);
if (
verifiedAt === null ||
snapshot.expiresAtEpochMs <= verifiedAt
) {
return browserDataFailure(
"EXPIRED_RESOURCE",
"IMAGE_RESOLVE",
);
}
const reference = createAssetReference();
acceptedAssets.set(
reference,
Object.freeze({
origin,
assetId: snapshot.assetId,
revision: snapshot.revision,
mediaType: snapshot.mediaType,
intrinsicWidth: snapshot.intrinsicWidth,
intrinsicHeight: snapshot.intrinsicHeight,
delivery: "PRIVATE_SIGNED",
capability: Object.freeze({
capabilityId: snapshot.capabilityId,
expiresAtEpochMs: snapshot.expiresAtEpochMs,
allowedPresetBindingIds: new Set(
snapshot.allowedPresetBindingIds,
),
keyId: snapshot.signature.keyId,
capabilityBindingDigestHex:
snapshot.signature.capabilityBindingDigestHex,
signatureBase64Url:
snapshot.signature.valueBase64Url,
}),
}),
);
return browserDataSuccess(reference);
} finally {
// Released only once the physical work this slot admitted has settled.
void Promise.allSettled(rawVerificationTasks).then(() => {
activeCapabilityVerifications -= 1;
});
}
};
const acceptBackendIssued:
ImageCdnRuntime["assets"]["acceptBackendIssued"] = async (
descriptor,
options,
) => {
const result = await acceptBackendIssuedCore(
descriptor,
options,
);
return observeImageTerminal(
observer,
result,
result.ok ? 1 : 0,
);
};
const resolveCore:
ImageCdnRuntime["presentation"]["resolve"] = async (
request,
) => {
if (closed) return imageRuntimeClosedFailure();
if (
!hasOnlyOwnKeys(request, RESOLVE_KEYS) ||
!("asset" in request) ||
!("preset" in request) ||
!validOptionalSignal(request.signal)
) {
return browserDataFailure("INVALID_INPUT", "IMAGE_RESOLVE");
}
if (request.signal?.aborted) {
return browserDataFailure("ABORTED", "IMAGE_RESOLVE");
}
const asset = acceptedAssets.get(request.asset);
const preset = resolvePreset(request.preset);
if (!asset || !preset) {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
if (
asset.capability &&
!asset.capability.allowedPresetBindingIds.has(
preset.bindingId,
)
) {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
const expiryFailure = checkExpiry(
asset,
now,
hardLimits.minCapabilityRemainingMs,
);
if (expiryFailure) return expiryFailure;
if (
asset.delivery === "PRIVATE_SIGNED" &&
(preset.loading !== "eager" ||
preset.fetchPriority === "low" ||
preset.probeMode !== "PRIMARY_REQUIRED")
) {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
if (
!preset.allowUpscale &&
preset.candidates.some(
(candidate) =>
candidate.pixelWidth > asset.intrinsicWidth ||
candidate.pixelHeight > asset.intrinsicHeight,
)
) {
return browserDataFailure(
"LIMIT_EXCEEDED",
"IMAGE_RESOLVE",
);
}
let descriptor: ImagePresentationDescriptor;
try {
descriptor = buildPresentationDescriptor(
asset,
preset,
hardLimits.maxUrlLength,
);
} catch {
return browserDataFailure("POLICY_REJECTED", "IMAGE_RESOLVE");
}
if (preset.probeMode === "PRIMARY_REQUIRED") {
if (!probe || !request.signal) {
return browserDataFailure("UNSUPPORTED", "IMAGE_RESOLVE");
}
const primary = primaryCandidate(preset);
let probeResult: BrowserDataResult<ImageProbeReceipt>;
const probeScope = combineImageRuntimeAbortSignals([
request.signal,
lifetime.signal,
]);
try {
probeResult = await awaitImageRuntimeAbort(
probe({
absoluteUrl: descriptor.src,
expectedMediaType: descriptor.fallbackMediaType,
expectedWidth: primary.pixelWidth,
expectedHeight: primary.pixelHeight,
maxEncodedBytes: preset.maxEncodedBytes,
maxDecodedPixels: preset.maxTransformedPixels,
maxDecodedBytes: preset.maxDecodedBytes,
delivery: asset.delivery,
minimumPublicMaxAgeSeconds:
asset.origin.minimumPublicMaxAgeSeconds,
referrerPolicy: descriptor.referrerPolicy,
signal: probeScope.signal,
}),
probeScope.signal,
);
} catch {
probeResult = closed
? imageRuntimeClosedFailure()
: request.signal.aborted
? browserDataFailure("ABORTED", "IMAGE_RESOLVE")
: browserDataFailure("UNAVAILABLE", "IMAGE_RESOLVE", {
retryable: true,
recovery: "RETRY",
});
} finally {
probeScope.release();
}
if (closed) probeResult = imageRuntimeClosedFailure();
observeImageTerminal(
observer,
probeResult,
1,
probeResult.ok
? probeResult.value.encodedBytes
: undefined,
);
if (!probeResult.ok) return probeResult;
if (
!validProbeReceipt(
probeResult.value,
descriptor.src,
descriptor.fallbackMediaType,
primary,
preset.maxEncodedBytes,
)
) {
return browserDataFailure(
"INTEGRITY_FAILED",
"IMAGE_RESOLVE",
);
}
if (request.signal.aborted) {
return browserDataFailure("ABORTED", "IMAGE_RESOLVE");
}
const postProbeExpiry = checkExpiry(
asset,
now,
hardLimits.minCapabilityRemainingMs,
);
if (postProbeExpiry) return postProbeExpiry;
}
if (closed) return imageRuntimeClosedFailure();
return browserDataSuccess(descriptor);
};
const resolve:
ImageCdnRuntime["presentation"]["resolve"] = async (
request,
) => {
const result = await resolveCore(request);
return observeImageTerminal(
observer,
result,
result.ok ? 1 + result.value.sources.length : 0,
result.ok
? result.value.decodeBudget.maximumEncodedBytes
: undefined,
);
};
return Object.freeze({
assets: Object.freeze({
acceptPublicImmutable,
acceptBackendIssued,
}),
presentation: Object.freeze({ resolve }),
close(): void {
if (closed) return;
closed = true;
lifetime.abort();
acceptedAssets =
new WeakMap<ImageAssetReference, AssetSnapshot>();
},
});
}
/**
* Canonical signed payload. Backend and CDN implementations must reproduce
* this exact JSON-array encoding and UTF-8 bytes for schema version 1.
*/
export function canonicalImageCapabilityPayload(
descriptor: BackendIssuedImageAsset,
): Uint8Array {
return new TextEncoder().encode(
JSON.stringify([
"image-cdn-capability-v1",
descriptor.issuer,
descriptor.originKey,
descriptor.assetId,
descriptor.revision,
descriptor.mediaType,
descriptor.contentKind,
descriptor.intrinsicWidth,
descriptor.intrinsicHeight,
descriptor.capabilityId,
descriptor.issuedAtEpochMs,
descriptor.expiresAtEpochMs,
[...descriptor.allowedPresetBindingIds].sort(),
descriptor.signature.algorithm,
descriptor.signature.keyId,
]),
);
}
export async function computeImageCapabilityBindingDigestHex(
subtle: Pick<SubtleCrypto, "digest">,
descriptor: BackendIssuedImageAsset,
): Promise<string> {
return sha256Hex(
subtle.digest.bind(subtle),
canonicalImageCapabilityPayload(descriptor),
);
}
function buildPresentationDescriptor(
asset: AssetSnapshot,
preset: ResolvedImageCdnPreset,
maxUrlLength: number,
): ImagePresentationDescriptor {
const fallbackFormat = preset.formats.at(-1);
if (!fallbackFormat) {
throw new TypeError("Image CDN fallback format is missing.");
}
const primary = primaryCandidate(preset);
const sourceSets = preset.formats.map((format) =>
Object.freeze({
format,
type: IMAGE_FORMAT_MEDIA_TYPE[format],
srcSet: buildSrcSet(
asset,
preset,
format,
maxUrlLength,
),
}),
);
const fallback = sourceSets.at(-1);
if (!fallback) {
throw new TypeError("Image CDN fallback source is missing.");
}
const src = buildCandidateUrl(
asset,
preset,
fallbackFormat,
primary,
maxUrlLength,
);
const maximumCandidatePixels = Math.max(
...preset.candidates.map((candidate) => candidate.pixels),
);
const maximumDecodedBytes = Math.max(
...preset.candidates.map(
(candidate) => candidate.decodedBytes,
),
);
const isPublic = asset.delivery === "PUBLIC_IMMUTABLE";
return Object.freeze({
src,
srcSet: fallback.srcSet,
sources: Object.freeze(
sourceSets.slice(0, -1).map(({ type, srcSet }) =>
Object.freeze({ type, srcSet }),
),
),
sizes: preset.sizes,
width: preset.width,
height: preset.height,
fallbackMediaType: fallback.type,
loading: preset.loading,
decoding: preset.decoding,
fetchPriority: preset.fetchPriority,
referrerPolicy: isPublic
? preset.referrerPolicy
: "no-referrer",
crossOrigin: "anonymous",
delivery: Object.freeze({
class: asset.delivery,
assetVersion: asset.revision,
browserCache: isPublic
? "PUBLIC_IMMUTABLE"
: "NO_STORE",
sharedCache: isPublic
? "PUBLIC_IMMUTABLE"
: "FORBIDDEN",
purge: isPublic
? "REVISION_ROLLOVER"
: "CAPABILITY_REVOCATION_OR_EXPIRY",
expiresAtEpochMs:
asset.capability?.expiresAtEpochMs ?? null,
}),
decodeBudget: Object.freeze({
maximumCandidatePixels,
maximumDecodedBytes,
maximumEncodedBytes: preset.maxEncodedBytes,
}),
});
}
function buildSrcSet(
asset: AssetSnapshot,
preset: ResolvedImageCdnPreset,
format: ImageOutputFormat,
maxUrlLength: number,
): string {
return preset.candidates
.map(
(candidate) =>
`${buildCandidateUrl(
asset,
preset,
format,
candidate,
maxUrlLength,
)} ${candidate.pixelWidth}w`,
)
.join(", ");
}
function buildCandidateUrl(
asset: AssetSnapshot,
preset: ResolvedImageCdnPreset,
format: ImageOutputFormat,
candidate: ImageCandidateGeometry,
maxUrlLength: number,
): string {
const pathname =
`${asset.origin.assetPathPrefix}` +
`${encodeURIComponent(asset.assetId)}/` +
`${encodeURIComponent(asset.revision)}`;
const url = new URL(pathname, asset.origin.origin);
url.searchParams.set("dpr", formatDpr(candidate.dpr));
url.searchParams.set("fit", preset.fit);
url.searchParams.set("format", format);
url.searchParams.set("height", String(candidate.cssHeight));
url.searchParams.set("preset", preset.bindingId);
url.searchParams.set("quality", String(preset.quality));
url.searchParams.set("width", String(candidate.cssWidth));
const expectedQueryNames = new Set([
"dpr",
"fit",
"format",
"height",
"preset",
"quality",
"width",
]);
if (asset.capability) {
url.searchParams.set(
"binding",
asset.capability.capabilityBindingDigestHex,
);
url.searchParams.set(
"capability",
asset.capability.capabilityId,
);
url.searchParams.set(
"expires",
String(asset.capability.expiresAtEpochMs),
);
url.searchParams.set("key", asset.capability.keyId);
url.searchParams.set(
"signature",
asset.capability.signatureBase64Url,
);
for (const name of [
"binding",
"capability",
"expires",
"key",
"signature",
]) {
expectedQueryNames.add(name);
}
}
url.searchParams.sort();
const queryNames = [...url.searchParams.keys()];
if (
url.protocol !== "https:" ||
url.origin !== asset.origin.origin ||
url.username !== "" ||
url.password !== "" ||
url.hash !== "" ||
url.pathname !== pathname ||
queryNames.length !== expectedQueryNames.size ||
new Set(queryNames).size !== queryNames.length ||
queryNames.some((name) => !expectedQueryNames.has(name)) ||
url.href.length > maxUrlLength
) {
throw new TypeError("Image CDN URL policy was violated.");
}
return url.href;
}
function primaryCandidate(
preset: ResolvedImageCdnPreset,
): ImageCandidateGeometry {
const primary = preset.candidates.find(
(candidate) =>
candidate.cssWidth === preset.width &&
candidate.dpr === 1,
);
if (!primary) {
throw new TypeError("Image CDN primary candidate is missing.");
}
return primary;
}
function snapshotPublicDescriptor(
input: PublicImmutableImageAsset,
): PublicImmutableImageAsset | null {
if (!hasExactOwnKeys(input, PUBLIC_DESCRIPTOR_KEYS)) {
return null;
}
try {
return Object.freeze({
kind: input.kind,
originKey: input.originKey,
assetId: input.assetId,
revision: input.revision,
mediaType: input.mediaType,
contentKind: input.contentKind,
intrinsicWidth: input.intrinsicWidth,
intrinsicHeight: input.intrinsicHeight,
});
} catch {
return null;
}
}
function snapshotIssuedDescriptor(
input: BackendIssuedImageAsset,
): IssuedDescriptorSnapshot | null {
if (
!hasExactOwnKeys(input, ISSUED_DESCRIPTOR_KEYS) ||
!hasExactOwnKeys(input.signature, SIGNATURE_KEYS)
) {
return null;
}
try {
const allowedPresetBindingIds = [
...input.allowedPresetBindingIds,
];
const snapshot: IssuedDescriptorSnapshot = Object.freeze({
kind: input.kind,
issuer: input.issuer,
originKey: input.originKey,
assetId: input.assetId,
revision: input.revision,
mediaType: input.mediaType,
contentKind: input.contentKind,
intrinsicWidth: input.intrinsicWidth,
intrinsicHeight: input.intrinsicHeight,
capabilityId: input.capabilityId,
issuedAtEpochMs: input.issuedAtEpochMs,
expiresAtEpochMs: input.expiresAtEpochMs,
allowedPresetBindingIds: Object.freeze(
allowedPresetBindingIds,
),
signature: Object.freeze({
algorithm: input.signature.algorithm,
keyId: input.signature.keyId,
capabilityBindingDigestHex:
input.signature.capabilityBindingDigestHex,
valueBase64Url: input.signature.valueBase64Url,
}),
});
if (
snapshot.kind !== "BACKEND_ISSUED_PRIVATE" ||
snapshot.contentKind !== "RASTER_STATIC" ||
!OPAQUE_TOKEN.test(snapshot.capabilityId) ||
!Number.isSafeInteger(snapshot.issuedAtEpochMs) ||
snapshot.issuedAtEpochMs < 0 ||
!Number.isSafeInteger(snapshot.expiresAtEpochMs) ||
snapshot.expiresAtEpochMs < 0 ||
!Array.isArray(input.allowedPresetBindingIds) ||
allowedPresetBindingIds.length < 1 ||
new Set(allowedPresetBindingIds).size !==
allowedPresetBindingIds.length ||
allowedPresetBindingIds.some(
(bindingId) =>
typeof bindingId !== "string" ||
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(
bindingId,
),
) ||
snapshot.signature.algorithm !== "ECDSA_P256_SHA256" ||
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(
snapshot.issuer,
) ||
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(
snapshot.signature.keyId,
) ||
!SHA256_HEX.test(
snapshot.signature.capabilityBindingDigestHex,
) ||
!SIGNATURE.test(snapshot.signature.valueBase64Url)
) {
return null;
}
return snapshot;
} catch {
return null;
}
}
function validAssetMetadata(
input: Readonly<{
assetId: string;
revision: string;
mediaType: string;
contentKind: string;
intrinsicWidth: number;
intrinsicHeight: number;
}>,
hardLimits: ImageCdnHardLimits,
): input is Readonly<{
assetId: string;
revision: string;
mediaType: ImageRasterMediaType;
contentKind: "RASTER_STATIC";
intrinsicWidth: number;
intrinsicHeight: number;
}> {
return (
OPAQUE_TOKEN.test(input.assetId) &&
OPAQUE_TOKEN.test(input.revision) &&
input.contentKind === "RASTER_STATIC" &&
hardLimits.allowedSourceMediaTypes.includes(
input.mediaType as ImageRasterMediaType,
) &&
Number.isSafeInteger(input.intrinsicWidth) &&
input.intrinsicWidth > 0 &&
input.intrinsicWidth <= hardLimits.maxIntrinsicWidth &&
Number.isSafeInteger(input.intrinsicHeight) &&
input.intrinsicHeight > 0 &&
input.intrinsicHeight <= hardLimits.maxIntrinsicHeight &&
input.intrinsicWidth * input.intrinsicHeight <=
hardLimits.maxSourcePixels
);
}
function validProbeReceipt(
receipt: ImageProbeReceipt,
expectedUrl: string,
expectedMediaType: ImageRasterMediaType,
expectedGeometry: ImageCandidateGeometry,
maxEncodedBytes: number,
): boolean {
return (
receipt.absoluteUrl === expectedUrl &&
receipt.mediaType === expectedMediaType &&
Number.isSafeInteger(receipt.encodedBytes) &&
receipt.encodedBytes > 0 &&
receipt.encodedBytes <= maxEncodedBytes &&
receipt.decodedWidth === expectedGeometry.pixelWidth &&
receipt.decodedHeight === expectedGeometry.pixelHeight
);
}
function checkExpiry(
asset: AssetSnapshot,
now: () => number,
minimumRemainingMs: number,
): BrowserDataResult<never> | null {
if (!asset.capability) return null;
const current = safeNow(now);
if (
current === null ||
asset.capability.expiresAtEpochMs - current <
minimumRemainingMs
) {
return browserDataFailure(
"EXPIRED_RESOURCE",
"IMAGE_RESOLVE",
);
}
return null;
}
function safeNow(now: () => number): number | null {
try {
const value = now();
return Number.isSafeInteger(value) && value >= 0
? value
: null;
} catch {
return null;
}
}
type ImageCapabilityVerificationDeadline = Readonly<{
signal: AbortSignal;
release(): void;
}>;
function createCapabilityVerificationDeadline(
signals: readonly (AbortSignal | undefined)[],
timeoutMs: number,
scheduler: ImageCapabilityVerificationScheduler,
): ImageCapabilityVerificationDeadline {
const controller = new AbortController();
let released = false;
const abortListeners = new Map<AbortSignal, () => void>();
const activeSignals = signals.filter(
(signal): signal is AbortSignal => signal !== undefined,
);
for (const signal of new Set(activeSignals)) {
const onAbort = () => controller.abort(signal.reason);
abortListeners.set(signal, onAbort);
signal.addEventListener("abort", onAbort, { once: true });
if (signal.aborted) onAbort();
}
let timeoutHandle: unknown;
try {
timeoutHandle = scheduler.setTimeout(() => {
if (released) return;
controller.abort(capabilityVerificationAbortException());
}, timeoutMs);
} catch (error) {
for (const [signal, onAbort] of abortListeners) {
signal.removeEventListener("abort", onAbort);
}
throw error;
}
return Object.freeze({
signal: controller.signal,
release() {
if (released) return;
released = true;
try {
scheduler.clearTimeout(timeoutHandle);
} catch {
// Scheduler cleanup cannot alter an already closed adapter result.
}
for (const [signal, onAbort] of abortListeners) {
signal.removeEventListener("abort", onAbort);
}
abortListeners.clear();
},
});
}
function awaitImageRuntimeAbort<Value>(
task: Promise<Value>,
signal: AbortSignal,
): Promise<Value> {
return new Promise<Value>((resolve, reject) => {
let settled = false;
const onAbort = () => {
if (settled) return;
settled = true;
signal.removeEventListener("abort", onAbort);
reject(capabilityVerificationAbortException());
};
signal.addEventListener("abort", onAbort, { once: true });
if (signal.aborted) onAbort();
void task.then(
(value) => {
if (settled) return;
settled = true;
signal.removeEventListener("abort", onAbort);
resolve(value);
},
(error: unknown) => {
if (settled) return;
settled = true;
signal.removeEventListener("abort", onAbort);
reject(error);
},
);
});
}
function combineImageRuntimeAbortSignals(
signals: readonly AbortSignal[],
): Readonly<{ signal: AbortSignal; release(): void }> {
const controller = new AbortController();
const abortListeners = new Map<AbortSignal, () => void>();
for (const signal of new Set(signals)) {
const onAbort = () => controller.abort(signal.reason);
abortListeners.set(signal, onAbort);
signal.addEventListener("abort", onAbort, { once: true });
if (signal.aborted) onAbort();
}
let released = false;
return Object.freeze({
signal: controller.signal,
release() {
if (released) return;
released = true;
for (const [signal, onAbort] of abortListeners) {
signal.removeEventListener("abort", onAbort);
}
abortListeners.clear();
},
});
}
function capabilityVerificationFailure(
externalSignal: AbortSignal | undefined,
): BrowserDataResult<never> {
if (externalSignal?.aborted) {
return browserDataFailure("ABORTED", "IMAGE_RESOLVE");
}
return browserDataFailure("UNAVAILABLE", "IMAGE_RESOLVE", {
retryable: true,
recovery: "RETRY",
});
}
function imageRuntimeClosedFailure(): BrowserDataResult<never> {
return browserDataFailure("UNAVAILABLE", "IMAGE_RESOLVE");
}
function capabilityVerificationAbortException(): DOMException {
return new DOMException(
"Image capability verification was aborted.",
"AbortError",
);
}
function snapshotCapabilityVerificationScheduler(
scheduler: ImageCapabilityVerificationScheduler,
): ImageCapabilityVerificationScheduler {
if (
!scheduler ||
typeof scheduler.setTimeout !== "function" ||
typeof scheduler.clearTimeout !== "function"
) {
throw new TypeError(
"Image capability verification scheduler is invalid.",
);
}
return Object.freeze({
setTimeout: scheduler.setTimeout.bind(scheduler),
clearTimeout: scheduler.clearTimeout.bind(scheduler),
});
}
function defaultCapabilityVerificationScheduler(): ImageCapabilityVerificationScheduler {
const schedule = globalThis.setTimeout.bind(globalThis);
const clear = globalThis.clearTimeout.bind(globalThis);
return Object.freeze({
setTimeout(callback: () => void, milliseconds: number) {
return schedule(callback, milliseconds);
},
clearTimeout(handle: unknown) {
clear(
handle as ReturnType<typeof globalThis.setTimeout>,
);
},
});
}
function createAssetReference(): ImageAssetReference {
return Object.freeze({}) as ImageAssetReference;
}
function snapshotHardLimits(
input: ImageCdnHardLimits,
): ImageCdnHardLimits {
return Object.freeze({
...input,
allowedSourceMediaTypes: Object.freeze([
...input.allowedSourceMediaTypes,
]),
formatQualityCeilings: Object.freeze({
...input.formatQualityCeilings,
}),
});
}
function snapshotObserver(
observer: BrowserDataObserver | undefined,
): BrowserDataObserver | undefined {
if (!observer) return undefined;
const record = observer.record.bind(observer);
return Object.freeze({ record });
}
function observeImageTerminal<Value>(
observer: BrowserDataObserver | undefined,
result: BrowserDataResult<Value>,
count: number,
bytes?: number,
): BrowserDataResult<Value> {
observeBrowserData(observer, {
operation: "IMAGE_RESOLVE",
outcome: result.ok ? "SUCCEEDED" : "FAILED",
...(!result.ok ? { failureCode: result.error.code } : {}),
countBucket: countBucket(count),
...(bytes === undefined
? {}
: { byteBucket: byteBucket(bytes) }),
});
return result;
}
function countBucket(
value: number,
): "ZERO" | "ONE" | "TWO_TO_TEN" | "ELEVEN_TO_HUNDRED" | "GT_HUNDRED" {
if (value <= 0) return "ZERO";
if (value === 1) return "ONE";
if (value <= 10) return "TWO_TO_TEN";
if (value <= 100) return "ELEVEN_TO_HUNDRED";
return "GT_HUNDRED";
}
function byteBucket(
value: number,
): "ZERO" | "LT1MIB" | "1_TO_9MIB" | "10_TO_99MIB" | "GTE100MIB" {
if (value <= 0) return "ZERO";
if (value < 1024 * 1024) return "LT1MIB";
if (value < 10 * 1024 * 1024) return "1_TO_9MIB";
if (value < 100 * 1024 * 1024) return "10_TO_99MIB";
return "GTE100MIB";
}
function validOptionalSignal(
signal: AbortSignal | undefined,
): boolean {
return (
signal === undefined ||
(typeof signal === "object" &&
signal !== null &&
typeof signal.aborted === "boolean" &&
typeof signal.addEventListener === "function" &&
typeof signal.removeEventListener === "function")
);
}
function hasExactOwnKeys(
input: unknown,
keys: readonly string[],
): boolean {
if (!input || typeof input !== "object" || Array.isArray(input)) {
return false;
}
const actual = Object.keys(input).sort();
const expected = [...keys].sort();
return (
actual.length === expected.length &&
actual.every((key, index) => key === expected[index])
);
}
function hasOnlyOwnKeys(
input: unknown,
keys: readonly string[],
): boolean {
if (!input || typeof input !== "object" || Array.isArray(input)) {
return false;
}
return Object.keys(input).every((key) => keys.includes(key));
}
function formatDpr(value: number): string {
return String(value);
}
async function sha256Hex(
digest: SubtleCrypto["digest"],
bytes: Uint8Array,
): Promise<string> {
const payload = new Uint8Array(bytes.byteLength);
payload.set(bytes);
const result = await digest("SHA-256", payload.buffer);
return [...new Uint8Array(result)]
.map((value) => value.toString(16).padStart(2, "0"))
.join("");
}
function constantTimeHexEqual(
left: string,
right: string,
): boolean {
if (left.length !== right.length) return false;
let difference = 0;
for (let index = 0; index < left.length; index += 1) {
difference |=
(left.charCodeAt(index) || 0) ^
(right.charCodeAt(index) || 0);
}
return difference === 0;
}