export interface SignedUrlConfig { /** HMAC key (raw bytes or UTF-8 string). */ readonly key: string | Uint8Array; /** URL prefix; the segment URL is `${baseUrl}/${segmentId}?st=${token}`. */ readonly baseUrl: string; /** Token TTL; SHOULD be ≤ 15 minutes (§5.4). Default 900. */ readonly ttlSeconds?: number; /** * Opaque per-partition audience (§5.4): stable per partition, MUST NOT * disclose the internal partition id. */ readonly audience: (partition: string) => string; } /** What descriptor emission needs: the §5.4 `url`/`urlExpiresAtMs` pair. */ export interface SegmentUrlIssue { readonly url: string; readonly urlExpiresAtMs: number; } export interface SegmentPresignArgs { readonly segmentId: string; readonly partition: string; readonly scopeDigest: string; readonly nowMs: number; /** Resolved TTL (config value or the 900 s default) — already applied. */ readonly ttlSeconds: number; } /** * Delegated presign (§5.4): the provider signs the URL. The callback MUST * satisfy the equivalence rule — the signed object key embeds exactly one * `segmentId`, and `urlExpiresAtMs` reflects the real provider expiry. * `S3SegmentStore.presignSegmentGet` (via `s3PresignedUrls`) is the * in-tree implementation. */ export interface DelegatedPresignConfig { readonly presign: (args: SegmentPresignArgs) => SegmentUrlIssue | Promise; /** URL TTL; SHOULD be ≤ 15 minutes (§5.4). Default 900. */ readonly ttlSeconds?: number; } /** Either §5.4 scheme; the pull emits descriptors identically for both. */ export type SegmentUrlConfig = SignedUrlConfig | DelegatedPresignConfig; /** * Issue the §5.4 `url`/`urlExpiresAtMs` pair for one segment descriptor, * routing to the native HMAC token or the delegated presigner. Callers * (the pull) invoke this only after scope resolution and only when the * client advertised accept bit 3. */ export declare function issueSegmentUrl(config: SegmentUrlConfig, args: { readonly segmentId: string; readonly partition: string; readonly scopeDigest: string; readonly nowMs: number; }): Promise; /** * Delegated presign for BLOB downloads (§5.9.5). The blob twin of * `DelegatedPresignConfig`: the provider signs the URL and the signed object * key embeds the `blobId`. Issuance happens ONLY after the §5.9.5 * row-derived authorization check (never before), so the URL is a short-TTL * bearer grant to exactly those immutable bytes — the SPEC's "authorization * was resolved against the referencing rows at issuance". Unlike segments, * there is no native-HMAC blob token scheme wired this rung; presign is the * shipped path (`S3BlobStore.presignBlobGet` via `s3PresignedBlobUrls`). */ export interface BlobPresignArgs { readonly partition: string; readonly blobId: string; readonly nowMs: number; /** Resolved TTL (config value or the 900 s default) — already applied. */ readonly ttlSeconds: number; } export interface BlobPresignConfig { readonly presign: (args: BlobPresignArgs) => SegmentUrlIssue | Promise; /** URL TTL; SHOULD be ≤ 15 minutes (§5.9.5). Default 900. */ readonly ttlSeconds?: number; } /** * Issue the §5.9.5 `url`/`urlExpiresAtMs` pair for one blob download. The * caller (blob-handlers `downloadBlob`) invokes this only after the * row-derived authorization check passes. */ export declare function issueBlobUrl(config: BlobPresignConfig, args: { readonly partition: string; readonly blobId: string; readonly nowMs: number; }): Promise; /** * Delegated presign for BLOB UPLOADS (§5.9.3 direct-to-storage). The upload * twin of `BlobPresignConfig`: the provider signs a single PUT whose object * key embeds the `blobId`. Issuance happens ONLY after host authentication in * the upload-grant handler (uploading is host-auth-only, not scope-bearing — * §5.9.3). The `byteLength` rides through so a provider MAY bind * `Content-Length` (S3 conditional) to the granted size. Never a multipart or * chunk protocol — single PUT only, this rung and the next (§5.9.3 non-goal). * `S3BlobStore.presignBlobPut` (via `s3PresignedBlobUploads`) is the in-tree * implementation. */ export interface BlobUploadPresignArgs { readonly partition: string; readonly blobId: string; readonly byteLength: number; readonly nowMs: number; /** Resolved TTL (config value or the 900 s default) — already applied. */ readonly ttlSeconds: number; } export interface BlobUploadPresignConfig { readonly presign: (args: BlobUploadPresignArgs) => SegmentUrlIssue | Promise; /** URL TTL; SHOULD be ≤ 15 minutes (§5.9.3). Default 900. */ readonly ttlSeconds?: number; } /** * Issue the §5.9.3 `url`/`urlExpiresAtMs` pair for one presigned blob upload. * The caller (blob-handlers `handleBlobUploadGrant`) invokes this only after * host authentication and the size-cap check against the declared byteLength. */ export declare function issueBlobUploadUrl(config: BlobUploadPresignConfig, args: { readonly partition: string; readonly blobId: string; readonly byteLength: number; readonly nowMs: number; }): Promise; export interface SegmentTokenClaims { readonly v: 1; readonly seg: string; readonly sd: string; readonly aud: string; /** Unix seconds — the sole non-millisecond timestamp in the spec. */ readonly exp: number; } export declare function signSegmentToken(key: string | Uint8Array, claims: SegmentTokenClaims): Promise; /** * Verify a segment token per §5.4. Throws `SyncError sync.forbidden` on any * failure (MAC, expiry, or claim mismatch). */ export declare function verifySegmentToken(key: string | Uint8Array, token: string, expected: { readonly segmentId: string; readonly scopeDigest: string; readonly audience: string; readonly nowMs: number; readonly skewSeconds?: number; }): Promise;