/** * Opt-in capability contracts. * * This directory is a copyable recipe source, not a production entry. A project * moves only the selected contract into its application-owned boundary and puts * a concrete implementation behind that port. */ export const OPTIONAL_RECIPE_RUNTIME_SENTINEL = "frontend-optional-recipe-must-not-reach-production"; export type CapabilityFailureCode = | "ABORTED" | "AUTH_EXPIRED" | "BLOCKED" | "CONFLICT" | "CONSENT_DENIED" | "CONTRACT_DRIFT" | "CORRUPT_DATA" | "DISCONNECTED" | "EXPIRED_RESOURCE" | "INTEGRITY_FAILED" | "INVALID_INPUT" | "LIMIT_EXCEEDED" | "MIGRATION_FAILED" | "NOT_FOUND" | "NOT_READABLE" | "PERMISSION_DENIED" | "POLICY_REJECTED" | "PROVIDER_UNAVAILABLE" | "QUOTA_EXCEEDED" | "STALE_RESULT" | "STORAGE_EVICTED" | "UNSUPPORTED"; export type CapabilityFailure = Readonly<{ code: CapabilityFailureCode; retryable: boolean; safeMessage: string; }>; export type CapabilityResult = | Readonly<{ ok: true; value: T }> | Readonly<{ ok: false; failure: CapabilityFailure }>; export type Cleanup = () => void; export type RealtimeEvent = Readonly<{ id: string; sequence: number; occurredAt: string; payload: T; }>; export interface RealtimeSubscription { readonly resumeToken: string | null; unsubscribe(): void; } export interface RealtimePort { subscribe(input: { channel: string; resumeToken?: string; signal?: AbortSignal; onEvent(event: CapabilityResult>): void; }): Promise>; heartbeat(signal?: AbortSignal): Promise>; } export interface VersionedOfflineRepository { open(input: { schemaVersion: number; signal?: AbortSignal; }): Promise>; get(id: string, signal?: AbortSignal): Promise>; put(value: T, signal?: AbortSignal): Promise>; migrate(input: { from: number; to: number; signal?: AbortSignal; }): Promise>; close(): void; } export interface ServiceWorkerUpdatePort { inspect(signal?: AbortSignal): Promise< CapabilityResult> >; activate(version: string, signal?: AbortSignal): Promise>; rollback(signal?: AbortSignal): Promise>; unregister(): Promise>; } export type TransferProgress = Readonly<{ phase?: | "VALIDATING" | "PREPARING" | "TRANSFERRING" | "VERIFYING" | "FINALIZING"; transferredBytes: number; totalBytes: number | null; }>; export type TransferByteSource = Readonly<{ byteLength: number | null; chunks: AsyncIterable; }>; export interface FileTransferPort { upload(input: { file: Readonly<{ name: string; size: number; type: string; content: TransferByteSource; }>; signal: AbortSignal; onProgress(progress: TransferProgress): void; }): Promise>>; download(input: { resourceId: string; signal: AbortSignal; onProgress(progress: TransferProgress): void; }): Promise< CapabilityResult< Readonly<{ fileName: string; mediaType: string; content: TransferByteSource; }> > >; } export interface GeneratedApiFacade { execute(input: { operationId: string; contractVersion: string; body?: unknown; signal?: AbortSignal; }): Promise>; } export interface FeatureFlagPort> { evaluate(input: { key: TKey; fallback: TFlags[TKey]; maxAgeMs: number; }): Promise>; } export interface WorkerTaskPort { run(input: { taskId: string; generation: number; payload: TInput; signal: AbortSignal; }): Promise>; cancel(taskId: string): void; dispose(): void; } export type MultiTabEvent = Readonly<{ eventId: string; sourceId: string; version: number; payload: T; }>; export interface MultiTabPort { publish(event: MultiTabEvent): CapabilityResult; subscribe(input: { sourceId: string; onEvent(event: CapabilityResult>): void; }): Cleanup; close(): void; } export type BrowserCapability = | "clipboard-read" | "clipboard-write" | "media" | "notification"; export type PermissionDecision = "granted" | "denied" | "dismissed"; export interface BrowserPermissionPort { request(input: { capability: BrowserCapability; signal?: AbortSignal; }): Promise>; } export interface ClientWorkflowPort { snapshot(): Readonly; dispatch(event: TEvent): CapabilityResult>; reset(): void; subscribe(listener: (state: Readonly) => void): Cleanup; } export interface LargeDataUiFacade { window(input: { offset: number; limit: number; generation: number; }): CapabilityResult>; focus(rowId: string): CapabilityResult; replace(rows: ReadonlyArray, generation: number): void; } export type SafeAnalyticsValue = boolean | number | string | null; export interface AnalyticsErrorSink { record(input: { kind: "analytics" | "error"; eventId: string; consent: "granted" | "denied" | "not-required"; attributes: Readonly>; }): CapabilityResult; flush(signal?: AbortSignal): Promise>; dispose(): void; } export type OptionalCapabilityPorts = Readonly<{ realtime: RealtimePort; offline: VersionedOfflineRepository<{ id: string }>; serviceWorker: ServiceWorkerUpdatePort; fileTransfer: FileTransferPort; generatedApi: GeneratedApiFacade; featureFlag: FeatureFlagPort>; worker: WorkerTaskPort; multiTab: MultiTabPort; browserPermission: BrowserPermissionPort; clientWorkflow: ClientWorkflowPort; largeDataUi: LargeDataUiFacade<{ id: string }>; analytics: AnalyticsErrorSink; }>;