export const PROTOCOL_VERSION = 2 as const; export const CHUNK_SIZE = 8 * 1024 * 1024; export const GCM_TAG_BYTES = 16; export const MAX_CHUNK_BODY = CHUNK_SIZE + GCM_TAG_BYTES; export const MAX_MANIFEST_PLAINTEXT = 64 * 1024; export const MAX_MANIFEST_BODY = MAX_MANIFEST_PLAINTEXT + GCM_TAG_BYTES; export const UPLOAD_RESERVATION_MS = 24 * 60 * 60 * 1000; export const LEASE_IDLE_MS = 15 * 60 * 1000; export const BLOB_WARNING_BYTES = 100 * 1024 * 1024; export const BLOB_FALLBACK_MAX_BYTES = 256 * 1024 * 1024; export const PREVIEW_MAX_BYTES = 25 * 1024 * 1024; export const EXPIRY_VALUES = ["1h", "2h", "6h", "12h", "24h", "7d"] as const; export type ExpiryChoice = (typeof EXPIRY_VALUES)[number]; export const READ_VALUES = [1, 5, 10, 20, 50, 100] as const; export type ReadChoice = (typeof READ_VALUES)[number] | null; export const DEFAULT_EXPIRY: ExpiryChoice = "24h"; export const DEFAULT_READS: ReadChoice = 1; export type DropState = "uploading" | "ready"; export interface ReserveRequest { version: 2; chunkSize: number; chunkCount: number; noncePrefix: string; expiresIn: ExpiryChoice; maxReads: ReadChoice; } export interface ReserveResponse { id: string; uploadExpiresAt: string; } export interface PublicDescriptor { version: 2; id: string; chunkSize: number; chunkCount: number; noncePrefix: string; chunkCipherBytes: number[]; manifest: string; expiresAt: string; canClaim: boolean; maxReads: ReadChoice; } export interface EncryptedManifest { version: 2; name: string; type: string; size: number; lastModified: number; chunkSize: number; chunkCount: number; } export interface LeaseResponse { token: string; leaseExpiresAt: string; expiresAt: string; } export interface StoredLease { createdAt: number; lastSeenAt: number; expiresAt: number; } export interface StoredDrop { version: 2; id: string; state: DropState; createdAt: number; uploadExpiresAt: number; expiresInMs: number; expiresAt: number | null; maxReads: ReadChoice; readsClaimed: number; chunkSize: number; chunkCount: number; noncePrefix: string; manifestBytes?: number; chunkCipherBytes?: number[]; leases: Record; accessHash: string; }