chore: initialize from frontend template 4dc033c

This commit is contained in:
DongHyeonka
2026-08-13 18:23:26 +09:00
commit 40107eec84
897 changed files with 234824 additions and 0 deletions
@@ -0,0 +1,32 @@
declare const authorizedDownloadCapabilityBrand: unique symbol;
declare const authorizedDownloadCapabilityReceiptBrand: unique symbol;
/**
* Telemetry-safe server-issued identifier. It is not a URL, credential,
* object-store key or authorization token.
*/
export type AuthorizedDownloadCapabilityReceipt = string & {
readonly [authorizedDownloadCapabilityReceiptBrand]:
"AuthorizedDownloadCapabilityReceipt";
};
/**
* Opaque GET-only download handle shared by the file-delivery and transfer
* ports. The adapter owns the corresponding URL/query/header binding in an
* identity vault, so structurally equal caller-created objects are rejected.
*/
export type AuthorizedDownloadCapability = Readonly<{
capabilityReceipt: AuthorizedDownloadCapabilityReceipt;
method: "GET";
binding: Readonly<{
kind: "DOWNLOAD";
resourceId: string;
}>;
mediaType: string;
byteLength: number;
maxBytes: number;
expectedSha256: string;
expiresAtEpochMs: number;
readonly [authorizedDownloadCapabilityBrand]:
"AuthorizedDownloadCapability";
}>;
@@ -0,0 +1,183 @@
import type { BrowserDataResult } from "../browser-file-storage/shared.ts";
declare const imageAssetReferenceBrand: unique symbol;
declare const imagePresetReferenceBrand: unique symbol;
export type ImageRasterMediaType =
| "image/avif"
| "image/jpeg"
| "image/png"
| "image/webp";
export type ImageOutputFormat = "avif" | "jpeg" | "png" | "webp";
export type ImageFit = "contain" | "cover" | "fill" | "inside" | "outside";
/**
* Identity capability backed by an adapter-owned WeakMap. A structurally equal
* object or a reference issued by another runtime must be rejected.
*/
export type ImageAssetReference = Readonly<{
readonly [imageAssetReferenceBrand]: "ImageAssetReference";
}>;
/**
* Composition-issued named preset reference. Presentation cannot submit
* width, height, DPR, quality, format, URL or query overrides.
*/
export type ImagePresetReference = Readonly<{
presetKey: string;
intention: string;
readonly [imagePresetReferenceBrand]: "ImagePresetReference";
}>;
export type PublicImmutableImageAsset = Readonly<{
kind: "ALLOWLISTED_PUBLIC";
originKey: string;
assetId: string;
revision: string;
mediaType: ImageRasterMediaType;
contentKind: "RASTER_STATIC";
intrinsicWidth: number;
intrinsicHeight: number;
}>;
/**
* Server-issued descriptor for private signed delivery. It contains no URL or
* request headers. The signature covers every immutable field and the exact
* set of registry-owned preset binding IDs.
*/
export type BackendIssuedImageAsset = Readonly<{
kind: "BACKEND_ISSUED_PRIVATE";
issuer: string;
originKey: string;
assetId: string;
revision: string;
mediaType: ImageRasterMediaType;
contentKind: "RASTER_STATIC";
intrinsicWidth: number;
intrinsicHeight: number;
capabilityId: string;
issuedAtEpochMs: number;
expiresAtEpochMs: number;
allowedPresetBindingIds: readonly string[];
signature: Readonly<{
algorithm: "ECDSA_P256_SHA256";
keyId: string;
capabilityBindingDigestHex: string;
valueBase64Url: string;
}>;
}>;
export type ImageCapabilityVerificationRequest = Readonly<{
algorithm: "ECDSA_P256_SHA256";
keyId: string;
canonicalPayload: Uint8Array;
signatureBase64Url: string;
}>;
export interface ImageCapabilityVerifier {
/** Exact membership check against the verifier's immutable key registry. */
acceptsKey(keyId: string): boolean;
verify(
request: ImageCapabilityVerificationRequest,
): Promise<boolean>;
}
export interface ImageAssetAcceptancePort {
acceptPublicImmutable(
descriptor: PublicImmutableImageAsset,
): BrowserDataResult<ImageAssetReference>;
acceptBackendIssued(
descriptor: BackendIssuedImageAsset,
options?: Readonly<{ signal?: AbortSignal }>,
): Promise<BrowserDataResult<ImageAssetReference>>;
}
export type ImageDeliveryClass =
| "PUBLIC_IMMUTABLE"
| "PRIVATE_SIGNED";
export type ImageProbeRequest = Readonly<{
absoluteUrl: string;
expectedMediaType: ImageRasterMediaType;
expectedWidth: number;
expectedHeight: number;
maxEncodedBytes: number;
maxDecodedPixels: number;
maxDecodedBytes: number;
delivery: ImageDeliveryClass;
minimumPublicMaxAgeSeconds: number;
referrerPolicy: "no-referrer" | "strict-origin-when-cross-origin";
signal: AbortSignal;
}>;
export type ImageProbeReceipt = Readonly<{
absoluteUrl: string;
mediaType: ImageRasterMediaType;
encodedBytes: number;
decodedWidth: number;
decodedHeight: number;
}>;
/**
* Optional browser-native seam. Implementations must bound the encoded body
* before buffering and close the decoded ImageBitmap after inspecting it.
*/
export interface ImageResourceProbePort {
probe(
request: ImageProbeRequest,
): Promise<BrowserDataResult<ImageProbeReceipt>>;
}
export type ImagePresentationSource = Readonly<{
type: ImageRasterMediaType;
srcSet: string;
}>;
export type ImagePresentationDescriptor = Readonly<{
src: string;
srcSet: string;
sources: readonly ImagePresentationSource[];
sizes: string;
width: number;
height: number;
fallbackMediaType: ImageRasterMediaType;
loading: "eager" | "lazy";
decoding: "async" | "sync";
fetchPriority: "high" | "low" | "auto";
referrerPolicy: "no-referrer" | "strict-origin-when-cross-origin";
crossOrigin: "anonymous";
delivery: Readonly<{
class: ImageDeliveryClass;
assetVersion: string;
browserCache: "PUBLIC_IMMUTABLE" | "NO_STORE";
sharedCache: "PUBLIC_IMMUTABLE" | "FORBIDDEN";
purge:
| "REVISION_ROLLOVER"
| "CAPABILITY_REVOCATION_OR_EXPIRY";
expiresAtEpochMs: number | null;
}>;
decodeBudget: Readonly<{
maximumCandidatePixels: number;
maximumDecodedBytes: number;
maximumEncodedBytes: number;
}>;
}>;
export interface ImageCdnPresentationPort {
resolve(request: Readonly<{
asset: ImageAssetReference;
preset: ImagePresetReference;
signal?: AbortSignal;
}>): Promise<BrowserDataResult<ImagePresentationDescriptor>>;
}
export type ImageCdnRuntime = Readonly<{
assets: ImageAssetAcceptancePort;
presentation: ImageCdnPresentationPort;
/**
* Terminal and idempotent. Aborts in-flight verification/probing, revokes
* every issued reference and makes later accept/resolve calls unavailable.
*/
close(): void;
}>;
@@ -0,0 +1,68 @@
export type {
AuthorizedDownloadCapability,
AuthorizedDownloadCapabilityReceipt,
} from "./authorized-download.ts";
export type {
BackendIssuedImageAsset,
ImageAssetAcceptancePort,
ImageAssetReference,
ImageCapabilityVerificationRequest,
ImageCapabilityVerifier,
ImageCdnPresentationPort,
ImageCdnRuntime,
ImageDeliveryClass,
ImageFit,
ImageOutputFormat,
ImagePresentationDescriptor,
ImagePresentationSource,
ImagePresetReference,
ImageProbeReceipt,
ImageProbeRequest,
ImageRasterMediaType,
ImageResourceProbePort,
PublicImmutableImageAsset,
} from "./image-cdn.ts";
export type {
PresignedDownloadByteSource,
PresignedDownloadCapability,
PresignedDownloadSourcePort,
PresignedTransferBinding,
PresignedTransferCapability,
PresignedTransferCapabilityProvider,
PresignedTransferCapabilityReceipt,
PresignedTransferMethod,
PresignedTransferReplayGuard,
PresignedUploadPartCapability,
PresignedUploadPartCapabilityProvider,
PresignedUploadPartOutcome,
PresignedUploadPartPort,
} from "./presigned-transfer.ts";
export type {
ActiveUploadStatus,
QuarantinedUpload,
ResumableUploadCheckpoint,
ResumableUploadCheckpointAdmin,
ResumableUploadCheckpointStore,
ResumableUploadControlPlane,
ResumableUploadPort,
ResumableUploadRequest,
ResumableUploadSource,
UploadAbortOutcome,
UploadFileFingerprint,
UploadPartCapability,
UploadPartDescriptor,
UploadPartExecutor,
UploadPartReceipt,
UploadProviderFailure,
UploadProviderResult,
UploadRangeReader,
UploadSession,
UploadSessionStatus,
} from "./resumable-upload.ts";
export {
RESUMABLE_UPLOAD_PROTOCOL,
type ResumableUploadProtocol,
} from "./resumable-upload.ts";
@@ -0,0 +1,151 @@
import type { FileByteSource } from "../browser-file-storage/file.ts";
import type { BrowserDataResult } from "../browser-file-storage/shared.ts";
import type {
AuthorizedDownloadCapability,
AuthorizedDownloadCapabilityReceipt,
} from "./authorized-download.ts";
import type { ResumableUploadProtocol } from "./resumable-upload.ts";
declare const presignedTransferCapabilityBrand: unique symbol;
/**
* Server-issued, telemetry-safe identifier. It is not a URL, credential,
* object-store key or authorization token.
*/
export type PresignedTransferCapabilityReceipt =
AuthorizedDownloadCapabilityReceipt;
export type PresignedTransferMethod = "GET" | "PUT";
export type PresignedTransferBinding =
| Readonly<{
kind: "DOWNLOAD";
resourceId: string;
}>
| Readonly<{
kind: "UPLOAD_PART";
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
/**
* SHA-256 over the canonical session, request and whole-file fingerprint
* binding. The raw session fields remain owned by the upload control
* plane; they must never be smuggled into resourceId.
*/
uploadBindingSha256: string;
partNumber: number;
offset: number;
idempotencyKey: string;
}>;
/**
* Opaque capability handle crossing the application boundary. The adapter owns
* the corresponding URL, query values and request headers in an in-memory
* identity vault. Implementations must reject structurally equal or fabricated
* handles, even if every visible field matches.
*/
export type PresignedDownloadCapability = AuthorizedDownloadCapability;
export type PresignedUploadPartCapability = Readonly<{
capabilityReceipt: PresignedTransferCapabilityReceipt;
method: "PUT";
binding: Extract<
PresignedTransferBinding,
Readonly<{ kind: "UPLOAD_PART" }>
>;
mediaType: string;
byteLength: number;
maxBytes: number;
expectedSha256: string;
expiresAtEpochMs: number;
readonly [presignedTransferCapabilityBrand]:
"PresignedTransferCapability";
}>;
export type PresignedTransferCapability =
| PresignedDownloadCapability
| PresignedUploadPartCapability;
export interface PresignedTransferCapabilityProvider {
/**
* Calls a composition-owned backend/BFF capability endpoint. Callers choose
* only an opaque resource ID; they cannot supply a transfer URL or headers.
*/
issueDownload(input: Readonly<{
resourceId: string;
signal: AbortSignal;
}>): Promise<BrowserDataResult<PresignedDownloadCapability>>;
}
export interface PresignedUploadPartCapabilityProvider {
issueUploadPart(input: Readonly<{
sessionId: string;
requestBindingSha256: string;
uploadBindingSha256: string;
partNumber: number;
offset: number;
byteLength: number;
checksumSha256: string;
mediaType: string;
idempotencyKey: string;
signal: AbortSignal;
}>): Promise<BrowserDataResult<PresignedUploadPartCapability>>;
}
/**
* Atomic local replay seam. The server/object-store capability must also
* enforce single use or equivalent idempotency because a browser guard is not
* an authorization boundary.
*/
export interface PresignedTransferReplayGuard {
claim(
capability: PresignedTransferCapability,
): BrowserDataResult<true>;
}
/**
* Successful exhaustion proves length and SHA-256 before the terminal success
* of the closed-Result stream. Consumers must not commit a destination until
* the iterable finishes without a failure result.
*/
export type PresignedDownloadByteSource = FileByteSource &
Readonly<{
byteLength: number;
capability: PresignedDownloadCapability;
integrity: "VERIFIED_ON_SUCCESSFUL_EXHAUSTION";
}>;
export interface PresignedDownloadSourcePort {
open(input: Readonly<{
resourceId: string;
capability: PresignedDownloadCapability;
signal: AbortSignal;
}>): Promise<BrowserDataResult<PresignedDownloadByteSource>>;
}
export type PresignedUploadPartOutcome = Readonly<{
bytesWritten: number;
checksumSha256: string;
/**
* Non-authorizing object-store acknowledgement (for example a normalized
* ETag). It is safe to persist only as part of the exact completed-part
* binding and must never be reused as a transfer capability.
*/
receiptToken: string;
}>;
export interface PresignedUploadPartPort {
put(input: Readonly<{
capability: PresignedUploadPartCapability;
sessionId: string;
requestBindingSha256: string;
uploadBindingSha256: string;
partNumber: number;
offset: number;
byteLength: number;
checksumSha256: string;
idempotencyKey: string;
bytes: Uint8Array;
signal: AbortSignal;
}>): Promise<BrowserDataResult<PresignedUploadPartOutcome>>;
}
@@ -0,0 +1,279 @@
import type { Result } from "../../result.ts";
import type { FileByteSource } from "../browser-file-storage/file.ts";
import type {
BrowserDataFailure,
BrowserDataResult,
TransferProgress,
} from "../browser-file-storage/shared.ts";
export const RESUMABLE_UPLOAD_PROTOCOL =
"PRESIGNED_MULTIPART_V1" as const;
export type ResumableUploadProtocol =
typeof RESUMABLE_UPLOAD_PROTOCOL;
/**
* Multipart uploads use a bounded part manifest instead of a whole-file
* ArrayBuffer. The digest is SHA-256 over the canonical ordered part metadata
* and SHA-256 part digests.
*/
export type UploadFileFingerprint = Readonly<{
algorithm: "SHA-256-PARTS-V1";
digestHex: string;
byteLength: number;
partSizeBytes: number;
partCount: number;
}>;
export type UploadPartDescriptor = Readonly<{
partNumber: number;
offset: number;
byteLength: number;
checksumSha256: string;
}>;
/**
* A non-authorizing server acknowledgement. It must be opaque, contain no PII,
* URL or credential, and be accepted only with the exact descriptor binding.
*/
export type UploadPartReceipt = UploadPartDescriptor &
Readonly<{
receiptToken: string;
}>;
export interface UploadRangeReader {
readonly byteLength: number;
readRange(input: Readonly<{
offset: number;
length: number;
signal: AbortSignal;
}>): Promise<BrowserDataResult<Uint8Array>>;
}
/**
* FILE_BYTE_SOURCE supports existing FileByteSource implementations. It must
* be replayable for the fingerprint pass and transfer pass. RANGE_READER is
* preferred for concurrent uploads and OPFS/file-vault range adapters.
*/
export type ResumableUploadSource =
| Readonly<{
kind: "FILE_BYTE_SOURCE";
bytes: FileByteSource;
}>
| Readonly<{
kind: "RANGE_READER";
reader: UploadRangeReader;
}>;
export type ResumableUploadRequest = Readonly<{
/** Opaque, caller-stable operation key. It must not contain a file name. */
uploadKey: string;
/** Registry-approved backend purpose identifier, not user-provided text. */
purpose: string;
mediaType: string;
source: ResumableUploadSource;
signal: AbortSignal;
onProgress?: (progress: TransferProgress) => void;
}>;
export type QuarantinedUpload = Readonly<{
state: "QUARANTINED";
resourceId: string;
byteLength: number;
replayed: boolean;
}>;
export type UploadAbortOutcome = Readonly<{
state: "ABORTED" | "ORPHANED" | "ALREADY_COMPLETED" | "NOT_FOUND";
}>;
export interface ResumableUploadPort {
upload(
request: ResumableUploadRequest,
): Promise<BrowserDataResult<QuarantinedUpload>>;
abort(request: Readonly<{
uploadKey: string;
signal: AbortSignal;
}>): Promise<BrowserDataResult<UploadAbortOutcome>>;
}
/**
* Retry-After is transport metadata used only by the runtime. It is bounded
* before sleeping and is removed from the application-facing failure.
*/
export type UploadProviderFailure = BrowserDataFailure &
Readonly<{
retryAfterMs?: number;
}>;
export type UploadProviderResult<Value> = Result<
Value,
UploadProviderFailure
>;
export type UploadSession = Readonly<{
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
fingerprint: UploadFileFingerprint;
partSizeBytes: number;
partCount: number;
maxConcurrency: number;
expiresAtEpochMs: number;
}>;
export type ActiveUploadStatus = Readonly<{
state: "ACTIVE";
session: UploadSession;
acceptedParts: readonly UploadPartReceipt[];
}>;
export type UploadSessionStatus =
| ActiveUploadStatus
| Readonly<{
state: "QUARANTINED";
session: UploadSession;
resourceId: string;
}>
| Readonly<{
state: "ABORTED" | "EXPIRED" | "NOT_FOUND";
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
}>;
/**
* The capability value is intentionally generic. The presigned-transfer
* adapter owns its URL/method/header contract; this port neither duplicates
* that type nor permits it to enter a durable checkpoint.
*/
export type UploadPartCapability<Capability> = Readonly<{
capability: Capability;
uploadBindingSha256: string;
expiresAtEpochMs: number;
}>;
export interface ResumableUploadControlPlane<Capability> {
createSession(input: Readonly<{
protocol: ResumableUploadProtocol;
uploadKey: string;
purpose: string;
mediaType: string;
requestBindingSha256: string;
fingerprint: UploadFileFingerprint;
requestedPartSizeBytes: number;
requestedMaxConcurrency: number;
idempotencyKey: string;
signal: AbortSignal;
}>): Promise<UploadProviderResult<UploadSession>>;
getStatus(input: Readonly<{
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
fingerprint: UploadFileFingerprint;
signal: AbortSignal;
}>): Promise<UploadProviderResult<UploadSessionStatus>>;
issuePartCapability(input: Readonly<{
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
uploadBindingSha256: string;
fingerprint: UploadFileFingerprint;
mediaType: string;
part: UploadPartDescriptor;
idempotencyKey: string;
signal: AbortSignal;
}>): Promise<UploadProviderResult<UploadPartCapability<Capability>>>;
complete(input: Readonly<{
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
fingerprint: UploadFileFingerprint;
orderedParts: readonly UploadPartReceipt[];
idempotencyKey: string;
signal: AbortSignal;
}>): Promise<UploadProviderResult<Readonly<{
state: "QUARANTINED";
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
fingerprint: UploadFileFingerprint;
resourceId: string;
}>>>;
abort(input: Readonly<{
protocol: ResumableUploadProtocol;
sessionId: string;
requestBindingSha256: string;
idempotencyKey: string;
signal: AbortSignal;
}>): Promise<UploadProviderResult<Readonly<{
state: "ABORTED" | "NOT_FOUND" | "EXPIRED" | "ALREADY_COMPLETED";
}>>>;
}
export interface UploadPartExecutor<Capability> {
uploadPart(input: Readonly<{
protocol: ResumableUploadProtocol;
capability: Capability;
sessionId: string;
requestBindingSha256: string;
uploadBindingSha256: string;
fingerprint: UploadFileFingerprint;
mediaType: string;
part: UploadPartDescriptor;
bytes: Uint8Array;
idempotencyKey: string;
signal: AbortSignal;
}>): Promise<UploadProviderResult<UploadPartReceipt>>;
}
/**
* Durable, non-secret recovery state. Implementations must reject any unknown
* property so a signed URL, authorization header or user metadata cannot be
* smuggled into persistence.
*/
export type ResumableUploadCheckpoint = Readonly<{
schemaVersion: 1;
protocol: ResumableUploadProtocol;
revision: number;
state: "ACTIVE" | "ABORT_PENDING";
uploadKey: string;
requestBindingSha256: string;
fingerprint: UploadFileFingerprint;
sessionId: string;
sessionExpiresAtEpochMs: number;
sessionMaxConcurrency: number;
acceptedParts: readonly UploadPartReceipt[];
updatedAtEpochMs: number;
}>;
export interface ResumableUploadCheckpointStore {
read(
uploadKey: string,
signal?: AbortSignal,
): Promise<BrowserDataResult<ResumableUploadCheckpoint | null>>;
compareAndSwap(input: Readonly<{
expectedRevision: number | null;
checkpoint: ResumableUploadCheckpoint;
signal?: AbortSignal;
}>): Promise<BrowserDataResult<ResumableUploadCheckpoint>>;
remove(input: Readonly<{
uploadKey: string;
expectedRevision: number;
signal?: AbortSignal;
}>): Promise<BrowserDataResult<void>>;
close(): void;
}
export interface ResumableUploadCheckpointAdmin {
/**
* Account/logout lifecycle operation for this already-bound opaque partition.
* The adapter closes its connection before deletion and bounds blocked waits.
*/
deletePartition(
signal?: AbortSignal,
): Promise<BrowserDataResult<Readonly<{ state: "DELETED" }>>>;
}