742 lines
19 KiB
TypeScript
742 lines
19 KiB
TypeScript
import type {
|
|
CapabilityResult,
|
|
Cleanup,
|
|
TransferProgress,
|
|
} from "./contracts.ts";
|
|
|
|
/**
|
|
* Deep opt-in contracts for browser file and origin-storage capabilities.
|
|
*
|
|
* These contracts intentionally expose no File, Blob, FileSystemHandle,
|
|
* IDBDatabase, IDBTransaction, Cache, Request or Response. A selected project
|
|
* copies and narrows only the ports that its product actually owns.
|
|
*/
|
|
|
|
declare const byteCountBrand: unique symbol;
|
|
declare const localFileRefBrand: unique symbol;
|
|
declare const fileVerificationReceiptBrand: unique symbol;
|
|
declare const filePolicyKeyBrand: unique symbol;
|
|
declare const filePolicyIntentionBrand: unique symbol;
|
|
declare const browserManagedCapabilityReceiptBrand: unique symbol;
|
|
declare const authorizedDownloadCapabilityBrand: unique symbol;
|
|
declare const authorizedDownloadCapabilityReceiptBrand: unique symbol;
|
|
declare const objectIdBrand: unique symbol;
|
|
declare const objectGenerationBrand: unique symbol;
|
|
|
|
export type ByteCount = number & {
|
|
readonly [byteCountBrand]: "ByteCount";
|
|
};
|
|
|
|
export type LocalFileRef = string & {
|
|
readonly [localFileRefBrand]: "LocalFileRef";
|
|
};
|
|
|
|
export type FileVerificationReceipt = string & {
|
|
readonly [fileVerificationReceiptBrand]: "FileVerificationReceipt";
|
|
};
|
|
|
|
export type FilePolicyKey = string & {
|
|
readonly [filePolicyKeyBrand]: "FilePolicyKey";
|
|
};
|
|
|
|
export type FilePolicyIntention = string & {
|
|
readonly [filePolicyIntentionBrand]: "FilePolicyIntention";
|
|
};
|
|
|
|
/**
|
|
* Composition-issued capability selector. Implementations must resolve the
|
|
* exact registered object identity, not merely an equal string pair.
|
|
*/
|
|
export type FilePolicyReference = Readonly<{
|
|
policyKey: FilePolicyKey;
|
|
intention: FilePolicyIntention;
|
|
}>;
|
|
|
|
export type BrowserManagedDownloadCapabilityReceipt = string & {
|
|
readonly [browserManagedCapabilityReceiptBrand]:
|
|
"BrowserManagedDownloadCapabilityReceipt";
|
|
};
|
|
|
|
export type AuthorizedDownloadCapabilityReceipt = string & {
|
|
readonly [authorizedDownloadCapabilityReceiptBrand]:
|
|
"AuthorizedDownloadCapabilityReceipt";
|
|
};
|
|
|
|
/**
|
|
* GET-only provider-issued handle. The corresponding URL, signed query and
|
|
* headers stay inside the selected transfer adapter's in-memory identity
|
|
* vault; a feature cannot replace them or supply its own digest.
|
|
*/
|
|
export type AuthorizedDownloadCapability = Readonly<{
|
|
capabilityReceipt: AuthorizedDownloadCapabilityReceipt;
|
|
method: "GET";
|
|
binding: Readonly<{
|
|
kind: "DOWNLOAD";
|
|
resourceId: string;
|
|
}>;
|
|
mediaType: string;
|
|
byteLength: ByteCount;
|
|
maxBytes: ByteCount;
|
|
expectedSha256: string;
|
|
expiresAtEpochMs: number;
|
|
readonly [authorizedDownloadCapabilityBrand]:
|
|
"AuthorizedDownloadCapability";
|
|
}>;
|
|
|
|
export type DurableObjectId = string & {
|
|
readonly [objectIdBrand]: "DurableObjectId";
|
|
};
|
|
|
|
export type ObjectGeneration = number & {
|
|
readonly [objectGenerationBrand]: "ObjectGeneration";
|
|
};
|
|
|
|
export type PersistableDataClass =
|
|
| "PUBLIC"
|
|
| "INTERNAL"
|
|
| "PERSONAL"
|
|
| "CONFIDENTIAL";
|
|
|
|
export type FileSelectionSource =
|
|
| "NATIVE_INPUT"
|
|
| "SYSTEM_PICKER"
|
|
| "DROP";
|
|
|
|
export type FileAcceptRule = Readonly<{
|
|
mediaType: string;
|
|
extensions: ReadonlyArray<string>;
|
|
}>;
|
|
|
|
export type FileSelectionPolicy = Readonly<{
|
|
policyId: string;
|
|
purpose: string;
|
|
classification: PersistableDataClass;
|
|
multiple: boolean;
|
|
maxCount: number;
|
|
maxFileBytes: ByteCount;
|
|
maxTotalBytes: ByteCount;
|
|
allowEmpty: boolean;
|
|
accept: ReadonlyArray<FileAcceptRule>;
|
|
}>;
|
|
|
|
export type FileSelectionLimitReduction = Readonly<{
|
|
maxCount?: number;
|
|
maxFileBytes?: ByteCount;
|
|
maxTotalBytes?: ByteCount;
|
|
}>;
|
|
|
|
export type FileCandidate = Readonly<{
|
|
ref: LocalFileRef;
|
|
displayName: string;
|
|
sizeBytes: ByteCount;
|
|
reportedMediaType: string | null;
|
|
lastModifiedEpochMs: number | null;
|
|
source: FileSelectionSource;
|
|
}>;
|
|
|
|
export type FileSelectionOutcome =
|
|
| Readonly<{
|
|
kind: "SELECTED";
|
|
files: ReadonlyArray<FileCandidate>;
|
|
}>
|
|
| Readonly<{ kind: "DISMISSED" }>;
|
|
|
|
export type FilePickerSupport = Readonly<{
|
|
nativeInput: true;
|
|
systemOpenPicker: boolean;
|
|
systemSavePicker: boolean;
|
|
}>;
|
|
|
|
export interface FilePickerPort {
|
|
readonly support: FilePickerSupport;
|
|
|
|
select(input: {
|
|
policy: FilePolicyReference;
|
|
limits?: FileSelectionLimitReduction;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<FileSelectionOutcome>>;
|
|
|
|
release(ref: LocalFileRef): void;
|
|
}
|
|
|
|
export type FileSignatureResult =
|
|
| "MATCHED"
|
|
| "MISMATCHED"
|
|
| "UNKNOWN";
|
|
|
|
export type FileBytePattern = Readonly<{
|
|
offset: ByteCount;
|
|
bytes: ReadonlyArray<number>;
|
|
mask?: ReadonlyArray<number>;
|
|
}>;
|
|
|
|
export type FileSignatureRule = Readonly<{
|
|
mediaType: string;
|
|
extensions: ReadonlyArray<string>;
|
|
patterns: ReadonlyArray<FileBytePattern>;
|
|
}>;
|
|
|
|
export type FileInspectionPolicy = Readonly<{
|
|
policyId: string;
|
|
maxInspectionBytes: ByteCount;
|
|
acceptedSignatures: ReadonlyArray<FileSignatureRule>;
|
|
}>;
|
|
|
|
export type FileInspection = Readonly<{
|
|
byteLength: ByteCount;
|
|
reportedMediaType: string | null;
|
|
detectedMediaType: string | null;
|
|
normalizedExtension: string | null;
|
|
signature: FileSignatureResult;
|
|
verificationReceipt: FileVerificationReceipt | null;
|
|
}>;
|
|
|
|
export type FileByteSource = Readonly<{
|
|
byteLength: ByteCount | null;
|
|
stream(
|
|
signal: AbortSignal,
|
|
): AsyncIterable<CapabilityResult<Uint8Array>>;
|
|
}>;
|
|
|
|
export interface FileContentPort {
|
|
inspect(input: {
|
|
ref: LocalFileRef;
|
|
policy: FilePolicyReference;
|
|
maxInspectionBytes?: ByteCount;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<FileInspection>>;
|
|
|
|
readRange(input: {
|
|
ref: LocalFileRef;
|
|
offset: ByteCount;
|
|
length: ByteCount;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<Uint8Array>>;
|
|
|
|
openSource(input: {
|
|
ref: LocalFileRef;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<FileByteSource>>;
|
|
|
|
release(ref: LocalFileRef): void;
|
|
}
|
|
|
|
export type PreviewLease = Readonly<{
|
|
url: string;
|
|
mediaType: string;
|
|
release: Cleanup;
|
|
}>;
|
|
|
|
/**
|
|
* Presentation-local capability. The implementation owns object URL creation
|
|
* and must revoke each lease on replacement, load failure and unmount.
|
|
*/
|
|
export interface TransientPreviewPort {
|
|
create(input: {
|
|
ref: LocalFileRef;
|
|
verificationReceipt: FileVerificationReceipt;
|
|
policy: FilePolicyReference;
|
|
maxPreviewBytes?: ByteCount;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<PreviewLease>>;
|
|
|
|
dispose(): void;
|
|
}
|
|
|
|
/**
|
|
* Feature/backend workflow example, not a browser capability dependency.
|
|
* Copy it only when the backend owns authorization, resumable-session expiry,
|
|
* integrity verification, content inspection and quarantine promotion.
|
|
*/
|
|
export type ExampleUploadSession = Readonly<{
|
|
sessionId: string;
|
|
partSizeBytes: ByteCount;
|
|
maxConcurrency: number;
|
|
expiresAt: string;
|
|
checksumAlgorithm: "SHA-256";
|
|
}>;
|
|
|
|
export type ExampleUploadPartReceipt = Readonly<{
|
|
partNumber: number;
|
|
acceptedBytes: ByteCount;
|
|
checksumSha256: string;
|
|
}>;
|
|
|
|
export type ExampleQuarantinedUpload = Readonly<{
|
|
resourceId: string;
|
|
state: "QUARANTINED";
|
|
}>;
|
|
|
|
export interface ExampleQuarantinedUploadPort {
|
|
create(input: {
|
|
purpose: string;
|
|
byteLength: ByteCount;
|
|
detectedMediaType: string;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<ExampleUploadSession>>;
|
|
|
|
uploadPart(input: {
|
|
sessionId: string;
|
|
partNumber: number;
|
|
offset: ByteCount;
|
|
bytes: Uint8Array;
|
|
checksumSha256: string;
|
|
idempotencyKey: string;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<ExampleUploadPartReceipt>>;
|
|
|
|
complete(input: {
|
|
sessionId: string;
|
|
parts: ReadonlyArray<ExampleUploadPartReceipt>;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<ExampleQuarantinedUpload>>;
|
|
|
|
abort(
|
|
sessionId: string,
|
|
signal?: AbortSignal,
|
|
): Promise<CapabilityResult<void>>;
|
|
}
|
|
|
|
export type DownloadSource =
|
|
| Readonly<{
|
|
kind: "BROWSER_MANAGED_RESOURCE";
|
|
resourceId: string;
|
|
capabilityReceipt: BrowserManagedDownloadCapabilityReceipt;
|
|
}>
|
|
| Readonly<{
|
|
kind: "AUTHORIZED_STREAM_RESOURCE";
|
|
resourceId: string;
|
|
capability: AuthorizedDownloadCapability;
|
|
}>
|
|
| Readonly<{
|
|
kind: "GENERATED";
|
|
bytes: FileByteSource;
|
|
expectedSha256?: string;
|
|
}>;
|
|
|
|
export type DownloadStrategy =
|
|
| "BROWSER_MANAGED"
|
|
| "PROMPT_AND_STREAM"
|
|
| "BOUNDED_OBJECT_URL";
|
|
|
|
export type DownloadOutcome =
|
|
| Readonly<{
|
|
kind: "BROWSER_HANDOFF";
|
|
transferId: string;
|
|
}>
|
|
| Readonly<{
|
|
kind: "SAVED";
|
|
transferId: string;
|
|
bytesWritten: ByteCount;
|
|
integrity: "VERIFIED" | "NOT_PROVIDED";
|
|
}>
|
|
| Readonly<{ kind: "DISMISSED" }>;
|
|
|
|
export interface DownloadDeliveryPort {
|
|
deliver(input: {
|
|
policy: FilePolicyReference;
|
|
source: DownloadSource;
|
|
suggestedFileName: string;
|
|
maxTransferBytes?: ByteCount;
|
|
maxBufferedBytes?: ByteCount;
|
|
signal: AbortSignal;
|
|
onProgress(progress: TransferProgress): void;
|
|
}): Promise<CapabilityResult<DownloadOutcome>>;
|
|
}
|
|
|
|
export type BrowserManagedDownloadCapability = Readonly<{
|
|
capabilityReceipt: BrowserManagedDownloadCapabilityReceipt;
|
|
href: string;
|
|
resourceId: string;
|
|
mediaType: string;
|
|
safeExtension: string;
|
|
maxBytes: ByteCount;
|
|
expectedSha256?: string;
|
|
expiresAtEpochMs: number;
|
|
}>;
|
|
|
|
export interface BrowserManagedDownloadCapabilityResolver {
|
|
resolve(input: Readonly<{
|
|
resourceId: string;
|
|
capabilityReceipt: BrowserManagedDownloadCapabilityReceipt;
|
|
}>): CapabilityResult<BrowserManagedDownloadCapability>;
|
|
}
|
|
|
|
export type RegisteredPreviewPolicy = Readonly<{
|
|
allowedMediaTypes: ReadonlyArray<string>;
|
|
maxPreviewBytes: ByteCount;
|
|
}>;
|
|
|
|
export type RegisteredDownloadPolicy = Readonly<{
|
|
strategy: DownloadStrategy;
|
|
mediaType: string;
|
|
safeExtension: string;
|
|
maxTransferBytes: ByteCount;
|
|
maxBufferedBytes: ByteCount;
|
|
integrity: "OPTIONAL" | "REQUIRED";
|
|
}>;
|
|
|
|
/**
|
|
* Dataset policy belongs at composition. Feature and presentation callers
|
|
* receive only the reference plus optional reductions.
|
|
*/
|
|
export type BrowserFilePolicyProfile = Readonly<{
|
|
reference: FilePolicyReference;
|
|
selection?: FileSelectionPolicy;
|
|
inspection?: FileInspectionPolicy;
|
|
preview?: RegisteredPreviewPolicy;
|
|
download?: RegisteredDownloadPolicy;
|
|
}>;
|
|
|
|
export type BrowserPersistencePolicy = Readonly<{
|
|
owner: string;
|
|
namespace: string;
|
|
classification: PersistableDataClass;
|
|
authority: "SERVER" | "LOCAL_FIRST" | "RECONSTRUCTABLE";
|
|
accountScope: "ORIGIN_SHARED" | "OPAQUE_PARTITION";
|
|
retention:
|
|
| Readonly<{ kind: "SESSION" }>
|
|
| Readonly<{ kind: "TTL"; maxAgeMs: number }>
|
|
| Readonly<{ kind: "UNTIL_SYNCED" }>
|
|
| Readonly<{ kind: "EXPLICIT_DELETE" }>;
|
|
softBudgetBytes: ByteCount;
|
|
hardBudgetBytes: ByteCount;
|
|
evictionPriority: "RECONSTRUCTABLE" | "SYNCED_COPY" | "USER_AUTHORED";
|
|
logoutAction:
|
|
| "KEEP_ORIGIN_SHARED"
|
|
| "PURGE_PARTITION"
|
|
| "EXPORT_THEN_PURGE";
|
|
accountDeletionAction: "KEEP_ORIGIN_SHARED" | "PURGE_PARTITION";
|
|
pressureAction: "EVICT_RECONSTRUCTABLE" | "RETAIN";
|
|
unavailableFallback: "ONLINE_ONLY" | "READ_ONLY" | "EXPORT_REQUIRED";
|
|
}>;
|
|
|
|
export type OfflineStoreStatus =
|
|
| Readonly<{
|
|
kind: "READY";
|
|
persistence: "BEST_EFFORT" | "PERSISTENT";
|
|
}>
|
|
| Readonly<{
|
|
kind: "READ_ONLY";
|
|
reason: "FUTURE_SCHEMA" | "QUOTA" | "RECOVERY";
|
|
}>
|
|
| Readonly<{
|
|
kind: "ONLINE_ONLY";
|
|
reason: "UNAVAILABLE" | "MIGRATION_FAILED";
|
|
}>
|
|
| Readonly<{
|
|
kind: "UPGRADE_BLOCKED";
|
|
targetVersion: number;
|
|
}>
|
|
| Readonly<{
|
|
kind: "CLOSED";
|
|
reason: "VERSION_CHANGE" | "FORCED" | "DISPOSED";
|
|
}>;
|
|
|
|
export type OfflineStoreLifecycleEvent =
|
|
| Readonly<{ kind: "STATUS_CHANGED"; status: OfflineStoreStatus }>
|
|
| Readonly<{
|
|
kind: "MIGRATION_PROGRESS";
|
|
migrationId: string;
|
|
processedCount: number;
|
|
remainingEstimate: number | null;
|
|
}>;
|
|
|
|
export type StoredRecord<T> = Readonly<{
|
|
id: string;
|
|
revision: number;
|
|
payloadVersion: number;
|
|
createdAtEpochMs: number;
|
|
updatedAtEpochMs: number;
|
|
expiresAtEpochMs: number | null;
|
|
value: T;
|
|
}>;
|
|
|
|
export type RevisionGuard =
|
|
| Readonly<{ kind: "ANY" }>
|
|
| Readonly<{ kind: "MUST_NOT_EXIST" }>
|
|
| Readonly<{ kind: "MATCH"; revision: number }>;
|
|
|
|
export type StructuredOfflineMutation<T> =
|
|
| Readonly<{
|
|
kind: "PUT";
|
|
id: string;
|
|
value: T;
|
|
payloadVersion: number;
|
|
expiresAtEpochMs: number | null;
|
|
revision: RevisionGuard;
|
|
}>
|
|
| Readonly<{
|
|
kind: "DELETE";
|
|
id: string;
|
|
revision: RevisionGuard;
|
|
}>;
|
|
|
|
export type OfflineCommitReceipt = Readonly<{
|
|
commitId: string;
|
|
revisions: Readonly<Record<string, number | null>>;
|
|
replayed: boolean;
|
|
}>;
|
|
|
|
export type OfflinePage<T> = Readonly<{
|
|
records: ReadonlyArray<StoredRecord<T>>;
|
|
nextCursor: string | null;
|
|
}>;
|
|
|
|
/**
|
|
* Copy this as a feature-specific repository. Do not expose a generic
|
|
* transaction callback, object-store name, index name or schema version.
|
|
*/
|
|
export interface StructuredOfflineStore<T> {
|
|
open(input: {
|
|
partitionKey: string;
|
|
signal?: AbortSignal;
|
|
onLifecycle(event: OfflineStoreLifecycleEvent): void;
|
|
}): Promise<CapabilityResult<OfflineStoreStatus>>;
|
|
|
|
read(
|
|
id: string,
|
|
signal?: AbortSignal,
|
|
): Promise<CapabilityResult<StoredRecord<T> | null>>;
|
|
|
|
page(input: {
|
|
cursor?: string;
|
|
limit: number;
|
|
includeExpired?: boolean;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<OfflinePage<T>>>;
|
|
|
|
commit(input: {
|
|
idempotencyKey: string;
|
|
mutations: ReadonlyArray<StructuredOfflineMutation<T>>;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<OfflineCommitReceipt>>;
|
|
|
|
clearPartition(input: {
|
|
reason: "LOGOUT" | "ACCOUNT_DELETION" | "USER_REQUEST";
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<void>>;
|
|
|
|
status(): OfflineStoreStatus;
|
|
close(): void;
|
|
}
|
|
|
|
export type MigrationProgress = Readonly<{
|
|
migrationId: string;
|
|
state: "PENDING" | "RUNNING" | "COMPLETED" | "FAILED";
|
|
processedCount: number;
|
|
remainingEstimate: number | null;
|
|
}>;
|
|
|
|
export interface OfflineStoreMaintenancePort {
|
|
resumeDataMigration(input: {
|
|
migrationId: string;
|
|
maxRecords: number;
|
|
timeBudgetMs: number;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<MigrationProgress>>;
|
|
|
|
purgeExpired(input: {
|
|
maxRecords: number;
|
|
nowEpochMs: number;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<Readonly<{ purgedCount: number }>>>;
|
|
}
|
|
|
|
export type StorageEstimate = Readonly<{
|
|
usageBytes: number | null;
|
|
quotaBytes: number | null;
|
|
persisted: boolean | null;
|
|
pressure: "UNKNOWN" | "NORMAL" | "PRESSURE" | "CRITICAL";
|
|
}>;
|
|
|
|
export interface StorageDurabilityPort {
|
|
inspect(signal?: AbortSignal): Promise<CapabilityResult<StorageEstimate>>;
|
|
|
|
requestPersistence(input: {
|
|
reason: "PROTECT_UNSYNCED_USER_DATA";
|
|
userInitiated: true;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<"GRANTED" | "DENIED">>;
|
|
}
|
|
|
|
export type DurableObjectDataClass =
|
|
| "RECONSTRUCTABLE"
|
|
| "USER_CREATED_PRIVATE";
|
|
|
|
export type DurableObjectIntegrity = Readonly<{
|
|
algorithm: "SHA-256-TREE-V1";
|
|
rootDigest: string;
|
|
chunkSizeBytes: ByteCount;
|
|
}>;
|
|
|
|
export type DurableObjectDescriptor = Readonly<{
|
|
id: DurableObjectId;
|
|
generation: ObjectGeneration;
|
|
byteLength: ByteCount;
|
|
mediaType: string | null;
|
|
integrity: DurableObjectIntegrity;
|
|
dataClass: DurableObjectDataClass;
|
|
retention:
|
|
| Readonly<{ kind: "EXPLICIT_DELETE" }>
|
|
| Readonly<{ kind: "EXPIRES"; expiresAt: string }>;
|
|
}>;
|
|
|
|
export type DurableObjectRead = Readonly<{
|
|
descriptor: DurableObjectDescriptor;
|
|
chunks: AsyncIterable<CapabilityResult<Uint8Array>>;
|
|
}>;
|
|
|
|
export interface DurableObjectStorePort {
|
|
capabilities(signal?: AbortSignal): Promise<
|
|
CapabilityResult<
|
|
Readonly<{
|
|
backend: "OPFS" | "INDEXEDDB_BLOB" | "NONE";
|
|
persistence: "BEST_EFFORT" | "PERSISTENT";
|
|
maxObjectBytes: ByteCount;
|
|
}>
|
|
>
|
|
>;
|
|
|
|
put(input: {
|
|
id: DurableObjectId;
|
|
expectedGeneration: ObjectGeneration | null;
|
|
source: AsyncIterable<CapabilityResult<Uint8Array>>;
|
|
declaredByteLength: ByteCount;
|
|
mediaType: string | null;
|
|
dataClass: DurableObjectDataClass;
|
|
retention: DurableObjectDescriptor["retention"];
|
|
signal: AbortSignal;
|
|
onProgress(progress: TransferProgress): void;
|
|
}): Promise<CapabilityResult<DurableObjectDescriptor>>;
|
|
|
|
open(
|
|
id: DurableObjectId,
|
|
signal?: AbortSignal,
|
|
): Promise<CapabilityResult<DurableObjectRead>>;
|
|
|
|
remove(input: {
|
|
id: DurableObjectId;
|
|
expectedGeneration: ObjectGeneration;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<void>>;
|
|
}
|
|
|
|
export type ObjectStoreRecoverySummary = Readonly<{
|
|
resumedCount: number;
|
|
purgedCount: number;
|
|
quarantinedCount: number;
|
|
nextCursor: string | null;
|
|
}>;
|
|
|
|
export interface DurableObjectMaintenancePort {
|
|
reconcile(input: {
|
|
timeBudgetMs: number;
|
|
maxEntries: number;
|
|
cursor?: string;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<ObjectStoreRecoverySummary>>;
|
|
}
|
|
|
|
export type PublicAssetEntry = Readonly<{
|
|
url: string;
|
|
byteLength: ByteCount;
|
|
mediaType: string;
|
|
integritySha256: string;
|
|
requestCredentials: "OMIT";
|
|
dataClass: "PUBLIC";
|
|
}>;
|
|
|
|
export type PublicCacheLookup =
|
|
| Readonly<{
|
|
kind: "HIT";
|
|
releaseId: string;
|
|
entry: PublicAssetEntry;
|
|
}>
|
|
| Readonly<{
|
|
kind: "MISS";
|
|
reason:
|
|
| "NOT_FOUND"
|
|
| "EXPIRED"
|
|
| "NO_ACTIVE_RELEASE"
|
|
| "POLICY_REJECTED";
|
|
}>;
|
|
|
|
export type PublicCacheInspection = Readonly<{
|
|
activeReleaseId: string | null;
|
|
previousReleaseId: string | null;
|
|
candidateReleaseIds: ReadonlyArray<string>;
|
|
ownedBytes: number | null;
|
|
}>;
|
|
|
|
/**
|
|
* Platform-local Cache Storage policy facade. Raw Request/Response/Cache
|
|
* objects remain inside the adapter, and no application repository imports it.
|
|
*/
|
|
export interface PublicResponseCacheAdmin {
|
|
stageRelease(input: {
|
|
releaseId: string;
|
|
manifestDigest: string;
|
|
entries: ReadonlyArray<PublicAssetEntry>;
|
|
signal: AbortSignal;
|
|
}): Promise<CapabilityResult<void>>;
|
|
|
|
activateRelease(input: {
|
|
releaseId: string;
|
|
manifestDigest: string;
|
|
expectedPreviousReleaseId: string | null;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<void>>;
|
|
|
|
lookup(input: {
|
|
url: string;
|
|
requestCredentials: "OMIT";
|
|
hasAuthorization: false;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<PublicCacheLookup>>;
|
|
|
|
inspect(signal?: AbortSignal): Promise<
|
|
CapabilityResult<PublicCacheInspection>
|
|
>;
|
|
|
|
rollback(signal?: AbortSignal): Promise<CapabilityResult<void>>;
|
|
|
|
deleteOwned(input: {
|
|
roles: ReadonlyArray<"CANDIDATE" | "PREVIOUS" | "RUNTIME_PUBLIC">;
|
|
signal?: AbortSignal;
|
|
}): Promise<CapabilityResult<Readonly<{ deletedCount: number }>>>;
|
|
}
|
|
|
|
export type BrowserFileComposition = Readonly<{
|
|
picker: FilePickerPort;
|
|
content: FileContentPort;
|
|
previews: TransientPreviewPort;
|
|
downloads: DownloadDeliveryPort;
|
|
}>;
|
|
|
|
export type StructuredOfflineStorageComposition<T> = Readonly<{
|
|
store: StructuredOfflineStore<T>;
|
|
maintenance: OfflineStoreMaintenancePort;
|
|
}>;
|
|
|
|
export type StorageDurabilityComposition = Readonly<{
|
|
durability: StorageDurabilityPort;
|
|
}>;
|
|
|
|
export type DurableObjectStorageComposition = Readonly<{
|
|
store: DurableObjectStorePort;
|
|
maintenance: DurableObjectMaintenancePort;
|
|
}>;
|
|
|
|
export type PublicResponseCacheComposition = Readonly<{
|
|
cache: PublicResponseCacheAdmin;
|
|
}>;
|
|
|
|
/**
|
|
* Explicitly separate from BrowserFileComposition: installing file selection,
|
|
* preview or download must never imply a resumable backend upload protocol.
|
|
*/
|
|
export type ExampleBackendUploadComposition = Readonly<{
|
|
upload: ExampleQuarantinedUploadPort;
|
|
}>;
|