@voltro/plugin-storage 0.86.0 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5484 -0
- package/README.md +27 -0
- package/THIRD-PARTY-NOTICES.md +2503 -690
- package/dist/access.js +26 -27
- package/dist/assetRef.js +1 -2
- package/dist/avatar.js +1 -2
- package/dist/byteSecurity.d.ts +3 -0
- package/dist/byteSecurity.js +6 -0
- package/dist/connection.js +98 -0
- package/dist/constraints.js +1 -2
- package/dist/custody.js +131 -0
- package/dist/derivatives.js +1 -2
- package/dist/env.js +8 -3
- package/dist/grant.js +90 -71
- package/dist/index.d.ts +453 -215
- package/dist/index.js +709 -537
- package/dist/ingest.js +7 -2
- package/dist/ingestPolicy.js +1 -1
- package/dist/metadataError.js +8 -9
- package/dist/objectAbandon.js +15 -0
- package/dist/objectLifecycle.js +135 -102
- package/dist/objectMetadata.js +253 -96
- package/dist/objectWriter.js +51 -23
- package/dist/pathDurability.js +1 -2
- package/dist/physicalReferences.js +53 -0
- package/dist/providers.js +451 -307
- package/dist/referenceCatalogue.js +1 -2
- package/dist/renditionProof.js +81 -0
- package/dist/retainedCapture.js +390 -0
- package/dist/retainedObjects.js +189 -0
- package/dist/rpc.d.ts +1 -15
- package/dist/rpc.js +1 -2
- package/dist/scanners.js +1 -2
- package/dist/server.d.ts +153 -0
- package/dist/server.js +4 -0
- package/dist/service.js +879 -546
- package/dist/sourceIdentity.js +13 -0
- package/dist/sourcePin.js +34 -0
- package/dist/storageNamespaces.js +52 -29
- package/dist/storageNumbers.js +1 -2
- package/dist/storageObjectNamespaces.js +170 -122
- package/dist/storageReferenceInstances.js +1 -2
- package/dist/storageRequest.js +9 -0
- package/dist/storageRouting.js +45 -0
- package/dist/streamBridge.js +5 -3
- package/dist/table.js +2 -2
- package/dist/transcodeVideo.js +85 -48
- package/dist/transform.js +30 -27
- package/dist/transformCache.js +1 -2
- package/dist/types.d.ts +115 -137
- package/dist/types.js +15 -16
- package/package.json +22 -11
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
|
+
import { ByteStream } from '@voltro/kv/storage';
|
|
1
2
|
import { ColumnBuilder } from '@voltro/database';
|
|
2
3
|
import { ColumnType } from '@voltro/database';
|
|
4
|
+
import { ConnectionRef } from '@voltro/kv/connection';
|
|
5
|
+
import { ConnectionRegistryShape } from '@voltro/kv/connection';
|
|
3
6
|
import { Context } from 'effect';
|
|
4
7
|
import { DataStore } from '@voltro/database';
|
|
5
8
|
import { Effect } from 'effect';
|
|
6
9
|
import { FieldDefinitions } from '@voltro/database';
|
|
10
|
+
import { isStorageKey } from '@voltro/kv/storage';
|
|
7
11
|
import { Layer } from 'effect';
|
|
8
12
|
import { mixin } from '@voltro/database';
|
|
13
|
+
import { ObjectMeta } from '@voltro/kv/storage';
|
|
9
14
|
import { PluginEgressDeclaration } from '@voltro/protocol';
|
|
10
15
|
import { Readable } from 'node:stream';
|
|
11
16
|
import { Schema } from 'effect';
|
|
12
17
|
import { StorageAccessPolicy } from '@voltro/protocol';
|
|
13
18
|
import { StorageAccessRule } from '@voltro/protocol';
|
|
19
|
+
import { StorageAddress } from '@voltro/kv/storage';
|
|
20
|
+
import { storageAddressIdentity } from '@voltro/kv/storage';
|
|
21
|
+
import { StorageConnectionConnector } from '@voltro/kv/storage';
|
|
22
|
+
import { StorageDestination } from '@voltro/kv/storage';
|
|
23
|
+
import { StorageDestinationRouter } from '@voltro/kv/storage';
|
|
24
|
+
import { StorageError } from '@voltro/kv/storage';
|
|
25
|
+
import { StorageObjectLocation } from '@voltro/kv/storage';
|
|
26
|
+
import { StorageProvider } from '@voltro/kv/storage';
|
|
27
|
+
import { StorageProviderName } from '@voltro/kv/storage';
|
|
28
|
+
import { StoredObject } from '@voltro/kv/storage';
|
|
29
|
+
import { StoredStream } from '@voltro/kv/storage';
|
|
14
30
|
import { Stream } from 'effect';
|
|
15
31
|
import { Subject } from '@voltro/protocol';
|
|
16
32
|
import { Table } from '@voltro/database';
|
|
@@ -35,12 +51,24 @@ export declare type AccessPolicy = StorageAccessPolicy;
|
|
|
35
51
|
*/
|
|
36
52
|
export declare type AccessRule = StorageAccessRule;
|
|
37
53
|
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*/
|
|
43
|
-
|
|
54
|
+
/** The app Storage plugin's bound service and durable object metadata. */
|
|
55
|
+
export declare interface AppStorageObjects {
|
|
56
|
+
readonly service: StorageServiceShape;
|
|
57
|
+
readonly metadata: StorageObjectMetadata;
|
|
58
|
+
/** The destination new objects land in. */
|
|
59
|
+
readonly bucket: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Borrow the bound service and object metadata of the app's one Storage plugin, for server code that runs
|
|
63
|
+
* outside the request layer (a Rooms Host, a geometry source). Read it after `bindDataStore`. Refuses with no
|
|
64
|
+
* or several Storage installs, and before binding or with app-supplied ref/grant stores (no metadata boundary). */
|
|
65
|
+
export declare const appStorageObjects: (plugins: ReadonlyArray<VoltroPlugin>) => AppStorageObjects;
|
|
66
|
+
|
|
67
|
+
/** Borrow the app's configured destination. Absence is an error, never a fresh memory store. */
|
|
68
|
+
export declare const appStorageProvider: (plugins: ReadonlyArray<VoltroPlugin>) => StorageProvider;
|
|
69
|
+
|
|
70
|
+
/** Resolve persisted ownership across this app, independently of new defaults. */
|
|
71
|
+
export declare const appStorageRouter: (plugins: ReadonlyArray<VoltroPlugin>) => StorageDestinationRouter;
|
|
44
72
|
|
|
45
73
|
/** A column binding an entity to a stored asset (a `_voltro_storage_refs` id). */
|
|
46
74
|
export declare function assetRef(options: AssetRefOptions & {
|
|
@@ -96,14 +124,7 @@ export declare const buildStorageService: (options: StorageServiceOptions) => St
|
|
|
96
124
|
* stream. `subarray` keeps the chunks as views (no copy). */
|
|
97
125
|
export declare const bytesToStream: (bytes: Uint8Array, chunkSize?: number) => ByteStream;
|
|
98
126
|
|
|
99
|
-
|
|
100
|
-
* A lazy stream of bytes — the streaming counterpart to {@link StoredObject}'s
|
|
101
|
-
* eager `bytes`. Backpressured: chunks are pulled on demand, so a multi-GB blob
|
|
102
|
-
* never fully materialises in memory. The error channel is {@link StorageError}
|
|
103
|
-
* so a stream handed to `putStream` carries the same typed failure the rest of
|
|
104
|
-
* the transport does (callers map their source errors into it).
|
|
105
|
-
*/
|
|
106
|
-
export declare type ByteStream = Stream.Stream<Uint8Array, StorageError>;
|
|
127
|
+
export { ByteStream }
|
|
107
128
|
|
|
108
129
|
/** Check an upload against the limits. Returns `null` when ok, else a
|
|
109
130
|
* `{ reason, detail }` describing the violation. */
|
|
@@ -141,24 +162,13 @@ export declare const collectStream: (stream: ByteStream) => Effect.Effect<Uint8A
|
|
|
141
162
|
/** Concatenate byte chunks into one contiguous Uint8Array. */
|
|
142
163
|
export declare const concatBytes: (chunks: ReadonlyArray<Uint8Array>) => Uint8Array;
|
|
143
164
|
|
|
144
|
-
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
* `restore`, whose whole job is to refuse a flag the app cannot honour. They
|
|
152
|
-
* were dead, and what they let through is worse than an unchecked flag: with no
|
|
153
|
-
* storage configured, `backup --assets` captured from a FRESH memory provider,
|
|
154
|
-
* found nothing in it, and wrote an artefact stamped `assets: { count: 0 }` —
|
|
155
|
-
* a rollback story that says the blobs are in there.
|
|
156
|
-
*
|
|
157
|
-
* "Configured" means one of the two things a person actually did: installed
|
|
158
|
-
* `storagePlugin(...)` (which registers here at construction), or set
|
|
159
|
-
* `STORAGE_PROVIDER`. A memory provider nobody asked for is not a decision.
|
|
160
|
-
*/
|
|
161
|
-
export declare const configuredStorageProvider: () => StorageProvider | undefined;
|
|
165
|
+
/** Select only transports contributed by this app's plugin instances.
|
|
166
|
+
* Multiple destinations require explicit asset routing, never last-writer wins.
|
|
167
|
+
* An implicit in-memory fallback is never reported as configured storage. */
|
|
168
|
+
export declare const configuredStorageProvider: (plugins: ReadonlyArray<VoltroPlugin>) => StorageProvider | undefined;
|
|
169
|
+
|
|
170
|
+
/** The CLI injects this server adapter into the leaf registry. No plugin imports enter KV. */
|
|
171
|
+
export declare const connectStorage: StorageConnectionConnector;
|
|
162
172
|
|
|
163
173
|
/** `image/*` matches `image/png`; exact otherwise. */
|
|
164
174
|
export declare const contentTypeAllowed: (contentType: string, allowed: ReadonlyArray<string> | undefined) => boolean;
|
|
@@ -173,10 +183,13 @@ export declare const databaseProvider: () => StorageProvider & {
|
|
|
173
183
|
bindDataStore: (store: unknown) => void;
|
|
174
184
|
};
|
|
175
185
|
|
|
176
|
-
|
|
186
|
+
/** Dynamic grants resolve through a currently visible reference. The concrete
|
|
187
|
+
* store retains its namespace through cleanup; grant rows alone never authorize
|
|
188
|
+
* bytes in a newly rebound destination. */
|
|
189
|
+
export declare const dataStoreGrantStore: (store: DataStore, configuredView: StorageReferenceView) => GrantStore;
|
|
177
190
|
|
|
178
191
|
/** Ref store backed by the app's `DataStore` (`_voltro_storage_refs`). */
|
|
179
|
-
export declare const dataStoreRefStore: (store: DataStore, configuredScope:
|
|
192
|
+
export declare const dataStoreRefStore: (store: DataStore, configuredScope: StorageReferenceView) => RefStore;
|
|
180
193
|
|
|
181
194
|
/** Decode a `data:<mime>;base64,<data>` URI to bytes + content type. */
|
|
182
195
|
export declare const decodeDataUri: (dataUri: string) => {
|
|
@@ -207,6 +220,17 @@ export declare const encodeInstream: (bytes: Uint8Array, chunkSize?: number) =>
|
|
|
207
220
|
* describes the persisted reference catalogue, not its provider bytes or host. */
|
|
208
221
|
export declare const ensureStorageReferenceCatalogue: (store: DataStore) => Promise<void>;
|
|
209
222
|
|
|
223
|
+
/**
|
|
224
|
+
* The identity a filesystem volume ALREADY carries — never a new one.
|
|
225
|
+
*
|
|
226
|
+
* `filesystemObjectNamespace` mints the marker on an empty root, which is right
|
|
227
|
+
* for a serving process and wrong for a migration: a migrate job started
|
|
228
|
+
* without the volume mounted read an empty directory, minted an identity no
|
|
229
|
+
* serving replica has, and an assignment to it exited 0. A metadata upgrade
|
|
230
|
+
* resolves the namespace through this function, so a missing volume refuses.
|
|
231
|
+
*/
|
|
232
|
+
export declare const existingFilesystemObjectNamespace: (root: string) => string;
|
|
233
|
+
|
|
210
234
|
export declare const fetchIngestBody: (url: string, configuredMaxBytes?: number, policy?: IngestPolicy) => Effect.Effect<StoredObject, StorageError | StorageRejected>;
|
|
211
235
|
|
|
212
236
|
export declare interface FfmpegRenditionSpec {
|
|
@@ -311,7 +335,7 @@ export declare interface ImageEdit {
|
|
|
311
335
|
readonly crop?: Region;
|
|
312
336
|
}
|
|
313
337
|
|
|
314
|
-
/** Where `ingestUrl` may fetch from — see `ssrfReason` in `@voltro/
|
|
338
|
+
/** Where `ingestUrl` may fetch from — see `ssrfReason` in `@voltro/protocol`. */
|
|
315
339
|
export declare interface IngestPolicy {
|
|
316
340
|
/** Hosts (or `host:port`, or `*.suffix`) reachable although internal — a
|
|
317
341
|
* deliberate internal source, or a local test server. Everything else that
|
|
@@ -319,8 +343,13 @@ export declare interface IngestPolicy {
|
|
|
319
343
|
readonly allowHosts?: ReadonlyArray<string>;
|
|
320
344
|
/** Redirect hops followed, each checked again. Default 5. */
|
|
321
345
|
readonly maxRedirects?: number;
|
|
346
|
+
/** Refuse HTTP at the initial source and every redirect before fetching.
|
|
347
|
+
* Host allowlisting does not bypass this transport requirement. Default false. */
|
|
348
|
+
readonly requireHttps?: boolean;
|
|
322
349
|
}
|
|
323
350
|
|
|
351
|
+
export { isStorageKey }
|
|
352
|
+
|
|
324
353
|
/**
|
|
325
354
|
* Filter + page a `StorageService.listRefs` / media-library query. Every
|
|
326
355
|
* filter is optional and ANDed; omit them all to page the whole (tenant-scoped)
|
|
@@ -356,50 +385,88 @@ export declare interface ListRefsResult {
|
|
|
356
385
|
readonly nextOffset: number | null;
|
|
357
386
|
}
|
|
358
387
|
|
|
359
|
-
/**
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
388
|
+
/** Each call captures its request tenant; no request changes the selected cell. */
|
|
389
|
+
export declare const makeStorageDestinationRouter: (binding: StorageDestinationBinding) => StorageDestinationRouter;
|
|
390
|
+
|
|
391
|
+
/** Resolve every operation to one concrete physical namespace. Metadata-only
|
|
392
|
+
* discovery stays instance scoped; the persisted intent is validated against
|
|
393
|
+
* the retained destination before it can authorize reads, claims or deletion. */
|
|
394
|
+
export declare const makeStorageObjectMetadata: (store: DataStore, configuredView: StorageReferenceView, admit?: StorageObjectAdmission) => {
|
|
395
|
+
scopeFor: (input: {
|
|
396
|
+
readonly bucket: string;
|
|
397
|
+
readonly tenantId: string | null;
|
|
398
|
+
} | {
|
|
399
|
+
readonly refId: string;
|
|
400
|
+
}) => Promise<StorageReferenceScope>;
|
|
367
401
|
intent: (refId: string) => Promise<{
|
|
368
402
|
identity: {
|
|
369
|
-
readonly storageInstance: string;
|
|
370
|
-
readonly objectNamespace: string;
|
|
371
403
|
readonly tenantId: string | null;
|
|
372
404
|
readonly bucket: string;
|
|
405
|
+
readonly objectNamespace: string;
|
|
406
|
+
readonly fingerprint: string;
|
|
407
|
+
readonly checksum: string;
|
|
408
|
+
readonly storageInstance: string;
|
|
373
409
|
readonly operationId: string;
|
|
410
|
+
readonly logicalKey: string;
|
|
411
|
+
readonly retainedSource?: {
|
|
412
|
+
readonly refId: string;
|
|
413
|
+
readonly digest: string;
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
ref: StorageRef;
|
|
417
|
+
} | undefined>;
|
|
418
|
+
operationStatus: (input: {
|
|
419
|
+
readonly bucket: string;
|
|
420
|
+
readonly tenantId: string | null;
|
|
421
|
+
readonly operationId: string;
|
|
422
|
+
}) => Promise<{
|
|
423
|
+
observation: StorageOperationState;
|
|
424
|
+
scope: StorageReferenceScope;
|
|
425
|
+
}>;
|
|
426
|
+
lookup: (input: Omit<StorageObjectOperationScope, keyof StorageReferenceScope>, claim: string) => Promise<{
|
|
427
|
+
state: "ready" | "reserved" | "deleting" | "deleted";
|
|
428
|
+
ref: StorageRef;
|
|
429
|
+
held: boolean;
|
|
430
|
+
} | undefined>;
|
|
431
|
+
operation: (key: StorageObjectOperationKey) => Promise<{
|
|
432
|
+
state: "ready" | "reserved" | "deleting" | "deleted";
|
|
433
|
+
identity: {
|
|
434
|
+
readonly tenantId: string | null;
|
|
435
|
+
readonly bucket: string;
|
|
436
|
+
readonly objectNamespace: string;
|
|
374
437
|
readonly fingerprint: string;
|
|
375
438
|
readonly checksum: string;
|
|
439
|
+
readonly storageInstance: string;
|
|
440
|
+
readonly operationId: string;
|
|
376
441
|
readonly logicalKey: string;
|
|
442
|
+
readonly retainedSource?: {
|
|
443
|
+
readonly refId: string;
|
|
444
|
+
readonly digest: string;
|
|
445
|
+
};
|
|
377
446
|
};
|
|
378
447
|
ref: StorageRef;
|
|
379
448
|
} | undefined>;
|
|
380
|
-
/** `claim` is registered only where the caller receives the ref: here when
|
|
381
|
-
* the operation is already ready (`joined`), else on `confirm`. A claimant
|
|
382
|
-
* whose provider write fails therefore holds nothing. */
|
|
383
449
|
reserve: (identity: StorageObjectIdentity, proposed: StorageRef, quota?: StorageQuota, claim?: string) => Promise<{
|
|
384
450
|
ref: StorageRef;
|
|
385
451
|
ready: boolean;
|
|
386
452
|
outcome: PutOutcome;
|
|
387
453
|
}>;
|
|
388
454
|
confirm: (identity: StorageObjectIdentity, claim?: string) => Promise<StorageRef>;
|
|
389
|
-
/** With a `claim`, releases that claim and deletes the object only when no
|
|
390
|
-
* other claimant holds it; `released` alone (no `operation`) means another
|
|
391
|
-
* claimant still does. Without one, the whole object goes, claims included. */
|
|
392
455
|
beginDelete: (refId: string, tenantId?: string | null, claim?: string) => Promise<{
|
|
393
456
|
released: true;
|
|
394
457
|
identity: {
|
|
395
|
-
readonly storageInstance: string;
|
|
396
|
-
readonly objectNamespace: string;
|
|
397
458
|
readonly tenantId: string | null;
|
|
398
459
|
readonly bucket: string;
|
|
399
|
-
readonly
|
|
460
|
+
readonly objectNamespace: string;
|
|
400
461
|
readonly fingerprint: string;
|
|
401
462
|
readonly checksum: string;
|
|
463
|
+
readonly storageInstance: string;
|
|
464
|
+
readonly operationId: string;
|
|
402
465
|
readonly logicalKey: string;
|
|
466
|
+
readonly retainedSource?: {
|
|
467
|
+
readonly refId: string;
|
|
468
|
+
readonly digest: string;
|
|
469
|
+
};
|
|
403
470
|
};
|
|
404
471
|
operation?: never;
|
|
405
472
|
} | {
|
|
@@ -417,14 +484,18 @@ export declare const makeStorageObjectMetadata: (store: DataStore, configuredSco
|
|
|
417
484
|
readonly deleteKey: string | null;
|
|
418
485
|
};
|
|
419
486
|
identity: {
|
|
420
|
-
readonly storageInstance: string;
|
|
421
|
-
readonly objectNamespace: string;
|
|
422
487
|
readonly tenantId: string | null;
|
|
423
488
|
readonly bucket: string;
|
|
424
|
-
readonly
|
|
489
|
+
readonly objectNamespace: string;
|
|
425
490
|
readonly fingerprint: string;
|
|
426
491
|
readonly checksum: string;
|
|
492
|
+
readonly storageInstance: string;
|
|
493
|
+
readonly operationId: string;
|
|
427
494
|
readonly logicalKey: string;
|
|
495
|
+
readonly retainedSource?: {
|
|
496
|
+
readonly refId: string;
|
|
497
|
+
readonly digest: string;
|
|
498
|
+
};
|
|
428
499
|
};
|
|
429
500
|
}>;
|
|
430
501
|
confirmDelete: (identity: StorageObjectIdentity) => Promise<boolean>;
|
|
@@ -446,11 +517,7 @@ export declare interface MultipartTicketPayload extends Omit<UploadTicketPayload
|
|
|
446
517
|
readonly size: number;
|
|
447
518
|
}
|
|
448
519
|
|
|
449
|
-
|
|
450
|
-
export declare interface ObjectMeta {
|
|
451
|
-
readonly size: number;
|
|
452
|
-
readonly etag?: string;
|
|
453
|
-
}
|
|
520
|
+
export { ObjectMeta }
|
|
454
521
|
|
|
455
522
|
/** Parse a clamd INSTREAM reply: `stream: OK` → clean; `stream: <T> FOUND`
|
|
456
523
|
* → infected; anything else → throws. Exposed for testing. */
|
|
@@ -487,6 +554,8 @@ export declare const putAvatar: (storage: StorageServiceShape, args: {
|
|
|
487
554
|
|
|
488
555
|
/** Input to `StorageService.put`. */
|
|
489
556
|
export declare interface PutInput {
|
|
557
|
+
/** Server-owned logical destination; omitted new writes use this plugin's selection. */
|
|
558
|
+
readonly destination?: string;
|
|
490
559
|
readonly bytes: Uint8Array;
|
|
491
560
|
readonly contentType: string;
|
|
492
561
|
/** Active org id — scopes the key prefix + the ref row. */
|
|
@@ -578,9 +647,13 @@ export declare interface RefStatistics {
|
|
|
578
647
|
}
|
|
579
648
|
|
|
580
649
|
export declare interface RefStore {
|
|
650
|
+
/** Complete metadata-only ownership observation; no pagination or recent limit. */
|
|
651
|
+
readonly listObjectReferences: () => Effect.Effect<ReadonlyArray<StorageObjectReference>, StorageError>;
|
|
581
652
|
/** Stable identity of this actual reference view. Shared catalogues expose
|
|
582
653
|
* the same identity; independent/process-local stores must expose their own. */
|
|
583
654
|
readonly catalogueId: Effect.Effect<string, StorageError>;
|
|
655
|
+
/** Durable reservations retain bytes before a reference is confirmed. */
|
|
656
|
+
readonly hasObjectReservation?: (namespace: string, key: string) => Effect.Effect<boolean, StorageError>;
|
|
584
657
|
/** Aggregate the complete reference index without a recent-object limit. */
|
|
585
658
|
readonly statistics: () => Effect.Effect<RefStatistics, StorageError>;
|
|
586
659
|
readonly insert: (ref: StorageRef) => Effect.Effect<void, StorageError>;
|
|
@@ -590,10 +663,8 @@ export declare interface RefStore {
|
|
|
590
663
|
* same id refund the tenant counter exactly once. */
|
|
591
664
|
readonly delete: (id: string) => Effect.Effect<boolean, StorageError>;
|
|
592
665
|
readonly listRecent: (limit: number) => Effect.Effect<ReadonlyArray<StorageRef>, StorageError>;
|
|
593
|
-
/**
|
|
594
|
-
|
|
595
|
-
* sibling ref. */
|
|
596
|
-
readonly countByKey: (bucket: string, key: string) => Effect.Effect<number, StorageError>;
|
|
666
|
+
/** Logical address count; physical cleanup also observes other destinations. */
|
|
667
|
+
readonly countByAddress: (address: StorageAddress) => Effect.Effect<number, StorageError>;
|
|
597
668
|
/** Total bytes + object count for a tenant — LIVE sum over the ref rows
|
|
598
669
|
* (reporting / dashboards). The quota GATE does not read this — it rides
|
|
599
670
|
* the atomic `consumeUsage` counter, which a read-then-compare here could
|
|
@@ -630,7 +701,7 @@ export declare interface RefStore {
|
|
|
630
701
|
readonly setVisibility?: ((id: string, visibility: StorageVisibility) => Effect.Effect<StorageRef | null, StorageError>) | undefined;
|
|
631
702
|
/** How many PUBLIC refs point at this provider key — whether the object must
|
|
632
703
|
* stay publicly readable. */
|
|
633
|
-
readonly
|
|
704
|
+
readonly countPublicByAddress?: ((address: StorageAddress) => Effect.Effect<number, StorageError>) | undefined;
|
|
634
705
|
}
|
|
635
706
|
|
|
636
707
|
/** A region of an image in pixels. */
|
|
@@ -644,6 +715,8 @@ declare interface Region {
|
|
|
644
715
|
/** One derived output a `Transcoder` produces from a source asset. Each becomes
|
|
645
716
|
* a normal storage ref linked back to the original via `derivedFrom`. */
|
|
646
717
|
export declare interface Rendition {
|
|
718
|
+
/** Optional structured producer attestation; unproven outputs keep it absent. */
|
|
719
|
+
readonly derivation?: RenditionDerivation;
|
|
647
720
|
readonly bytes: Uint8Array;
|
|
648
721
|
readonly contentType: string;
|
|
649
722
|
/** Derivative class — e.g. `'rendition'` (a playable variant) or `'poster'`. */
|
|
@@ -652,7 +725,47 @@ export declare interface Rendition {
|
|
|
652
725
|
readonly label?: string;
|
|
653
726
|
}
|
|
654
727
|
|
|
655
|
-
/**
|
|
728
|
+
/** Producer attestation. Digests bind a normalized recipe and the observed
|
|
729
|
+
* engine build; the consumer still admits allowed recipes, engines and rights. */
|
|
730
|
+
export declare interface RenditionDerivation {
|
|
731
|
+
readonly recipe: {
|
|
732
|
+
readonly format: string;
|
|
733
|
+
readonly digest: string;
|
|
734
|
+
};
|
|
735
|
+
readonly engine: {
|
|
736
|
+
readonly name: string;
|
|
737
|
+
readonly version: string;
|
|
738
|
+
readonly digest: string;
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/** Storage-verified input/output identity around a producer attestation.
|
|
743
|
+
* Not an approval, rights grant or proof of complete external dependencies. */
|
|
744
|
+
export declare interface RenditionProof extends RenditionDerivation {
|
|
745
|
+
readonly version: 1;
|
|
746
|
+
readonly source: {
|
|
747
|
+
readonly id: string;
|
|
748
|
+
readonly metadataDigest: string;
|
|
749
|
+
readonly checksum: string;
|
|
750
|
+
readonly size: number;
|
|
751
|
+
readonly contentType: string;
|
|
752
|
+
};
|
|
753
|
+
readonly output: {
|
|
754
|
+
readonly checksum: string;
|
|
755
|
+
readonly size: number;
|
|
756
|
+
readonly contentType: string;
|
|
757
|
+
};
|
|
758
|
+
readonly digest: string;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Nullable additions deliberately fail closed until the explicit upgrade.
|
|
763
|
+
*
|
|
764
|
+
* The refusal names every table still holding unassigned rows and how many,
|
|
765
|
+
* because the commonest way to meet it AFTER a completed assignment is a
|
|
766
|
+
* reference a previous-version replica wrote while the assignment ran — and a
|
|
767
|
+
* recorded file migration does not run again by itself.
|
|
768
|
+
*/
|
|
656
769
|
export declare const requireStorageObjectNamespaces: (store: DataStore) => Promise<void>;
|
|
657
770
|
|
|
658
771
|
/** A `ListRefsInput` after the service normalizes its defaults / clamps — what
|
|
@@ -670,11 +783,7 @@ export declare interface ResolvedListQuery {
|
|
|
670
783
|
|
|
671
784
|
export declare const resolveStorageProvider: (options: StoragePluginOptions) => StorageProvider;
|
|
672
785
|
|
|
673
|
-
/**
|
|
674
|
-
* The signing secret. A dedicated `VOLTRO_STORAGE_SECRET` is preferred so
|
|
675
|
-
* grant tokens and session cookies can be rotated independently; absent
|
|
676
|
-
* that we fall back to the session secret so it works out of the box.
|
|
677
|
-
*/
|
|
786
|
+
/** The secret new storage tokens are signed with — the first of {@link resolveStorageSecrets}. */
|
|
678
787
|
export declare const resolveStorageSecret: () => string;
|
|
679
788
|
|
|
680
789
|
/** What a resumable ticket authorizes: one chunked upload session, until `exp`. */
|
|
@@ -685,6 +794,63 @@ export declare interface ResumableTicketPayload extends Omit<UploadTicketPayload
|
|
|
685
794
|
readonly size: number;
|
|
686
795
|
}
|
|
687
796
|
|
|
797
|
+
export declare interface RetainedCaptureKey {
|
|
798
|
+
readonly id: string;
|
|
799
|
+
readonly instance: string;
|
|
800
|
+
readonly objectNamespace: string;
|
|
801
|
+
readonly tenantId: string | null;
|
|
802
|
+
readonly bucket: string;
|
|
803
|
+
/** Binds the caller's immutable publication/configuration admission. */
|
|
804
|
+
readonly contextDigest: string;
|
|
805
|
+
/** Different configured source; absent for same-instance custody. */
|
|
806
|
+
readonly source?: {
|
|
807
|
+
readonly instance: string;
|
|
808
|
+
readonly objectNamespace: string;
|
|
809
|
+
readonly bucket: string;
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
export declare interface RetainedCapturePin extends RetainedCaptureKey {
|
|
814
|
+
readonly count: number;
|
|
815
|
+
readonly digest: string;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
export declare const retainedCaptureTables: readonly [ Table<"_voltro_storage_retained_captures", FieldDefinitions<{
|
|
819
|
+
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
820
|
+
readonly captureId: ColumnBuilder<string, "text", boolean>;
|
|
821
|
+
readonly instance: ColumnBuilder<string, "text", boolean>;
|
|
822
|
+
readonly tenantId: ColumnBuilder<string | null, "text", boolean>;
|
|
823
|
+
readonly bucket: ColumnBuilder<string, "text", boolean>;
|
|
824
|
+
readonly contextDigest: ColumnBuilder<string, "text", boolean>;
|
|
825
|
+
readonly state: ColumnBuilder<"abandoned" | "complete" | "capturing", "text", boolean>;
|
|
826
|
+
readonly nonce: ColumnBuilder<string, "text", boolean>;
|
|
827
|
+
readonly config: ColumnBuilder<unknown, "json", boolean>;
|
|
828
|
+
readonly count: ColumnBuilder<number, "integer", boolean>;
|
|
829
|
+
readonly digest: ColumnBuilder<string | null, "text", boolean>;
|
|
830
|
+
readonly cleanupOrdinal: ColumnBuilder<number, "integer", true>;
|
|
831
|
+
}>, false, never>, Table<"_voltro_storage_retained_capture_items", FieldDefinitions<{
|
|
832
|
+
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
833
|
+
readonly captureId: ColumnBuilder<string, "text", boolean>;
|
|
834
|
+
readonly ordinal: ColumnBuilder<number, "integer", boolean>;
|
|
835
|
+
readonly sourceId: ColumnBuilder<string, "text", boolean>;
|
|
836
|
+
readonly sourceDigest: ColumnBuilder<string, "text", boolean>;
|
|
837
|
+
readonly operationId: ColumnBuilder<string, "text", boolean>;
|
|
838
|
+
readonly pin: ColumnBuilder<unknown, "json", boolean>;
|
|
839
|
+
}>, false, "storage_retained_capture_page">];
|
|
840
|
+
|
|
841
|
+
export declare interface RetainedStorageObject {
|
|
842
|
+
readonly version: 1;
|
|
843
|
+
readonly tenantId: string | null;
|
|
844
|
+
readonly bucket: string;
|
|
845
|
+
readonly operationId: string;
|
|
846
|
+
readonly sourceId: string;
|
|
847
|
+
readonly sourceDigest: string;
|
|
848
|
+
readonly refId: string;
|
|
849
|
+
readonly checksum: string;
|
|
850
|
+
readonly size: number;
|
|
851
|
+
readonly contentType: string;
|
|
852
|
+
}
|
|
853
|
+
|
|
688
854
|
export declare const s3Provider: (options: S3ProviderOptions) => StorageProvider;
|
|
689
855
|
|
|
690
856
|
export declare interface S3ProviderOptions {
|
|
@@ -706,10 +872,7 @@ export declare interface S3ProviderOptions {
|
|
|
706
872
|
readonly publicAcl?: boolean;
|
|
707
873
|
}
|
|
708
874
|
|
|
709
|
-
declare type ScopedStorageObjectIdentity = StorageObjectIdentity & StorageReferenceScope;
|
|
710
|
-
|
|
711
|
-
/** Register the app's storage provider (or clear with `undefined`). */
|
|
712
|
-
export declare const setActiveStorageProvider: (provider: StorageProvider | undefined) => void;
|
|
875
|
+
export declare type ScopedStorageObjectIdentity = StorageObjectIdentity & StorageReferenceScope;
|
|
713
876
|
|
|
714
877
|
/** Sign a finalize token valid for `ttlSeconds`. */
|
|
715
878
|
export declare const signFinalizeTicket: (fields: Omit<FinalizeTicketPayload, "exp" | "version">, ttlSeconds: number, secret?: string) => string;
|
|
@@ -753,6 +916,88 @@ declare const StorageAccessDenied_base: Schema.Class<StorageAccessDenied, Schema
|
|
|
753
916
|
readonly reason: Schema.String;
|
|
754
917
|
}>, YieldableError>;
|
|
755
918
|
|
|
919
|
+
export { StorageAddress }
|
|
920
|
+
|
|
921
|
+
export { storageAddressIdentity }
|
|
922
|
+
|
|
923
|
+
export declare const storageByteSecurityHeaders: (contentType: string) => Readonly<Record<string, string>>;
|
|
924
|
+
|
|
925
|
+
/** Private-byte custody for trusted server coordinators. storagePlugin supplies
|
|
926
|
+
* this service only for its exact instance. Pins confer no end-user authority. */
|
|
927
|
+
export declare class StorageCustody extends StorageCustody_base {
|
|
928
|
+
/** Reconstruct a transfer from configured services on each worker. Both must
|
|
929
|
+
* use the same application database; only the destination stores custody. */
|
|
930
|
+
static withSource(input: {
|
|
931
|
+
readonly source: StorageCustodyShape;
|
|
932
|
+
readonly destination: StorageCustodyShape;
|
|
933
|
+
}): Effect.Effect<StorageCustodyShape, StorageError>;
|
|
934
|
+
static forInstance(selection?: StorageCustodyInstance): Context.Service<StorageCustody, StorageCustodyShape>;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
declare const StorageCustody_base: Context.ServiceClass<StorageCustody, string, StorageCustodyShape>;
|
|
938
|
+
|
|
939
|
+
/** Uses the same instance selector as storagePlugin. */
|
|
940
|
+
export declare interface StorageCustodyInstance {
|
|
941
|
+
readonly alias?: string;
|
|
942
|
+
readonly name?: string;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/** Trusted server selection. Source enumeration runs in the caller's DB TX. */
|
|
946
|
+
export declare interface StorageCustodyRegistration {
|
|
947
|
+
readonly id: string;
|
|
948
|
+
readonly tenantId: string | null;
|
|
949
|
+
readonly contextDigest: string;
|
|
950
|
+
readonly maxBytes: number;
|
|
951
|
+
readonly sources: () => Iterable<string | StorageSourcePin> | AsyncIterable<string | StorageSourcePin>;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
export declare interface StorageCustodyShape {
|
|
955
|
+
/** Read and lock metadata from this configured source, including rendition
|
|
956
|
+
* provenance. No provider I/O, access grant or recipe/rights approval.
|
|
957
|
+
* Bind the pin to the caller's immutable candidate and contextDigest, then
|
|
958
|
+
* pass it to register in the same application transaction. */
|
|
959
|
+
readonly inspect: (tx: DataStore, input: {
|
|
960
|
+
readonly id: string;
|
|
961
|
+
readonly tenantId: string | null;
|
|
962
|
+
}) => Effect.Effect<StorageSourcePin, StorageError>;
|
|
963
|
+
/** Register stable work in the same transaction as the caller's source pin.
|
|
964
|
+
* The transaction must belong to this plugin's bound application database. */
|
|
965
|
+
readonly register: (tx: DataStore, input: StorageCustodyRegistration) => Effect.Effect<{
|
|
966
|
+
readonly key: RetainedCaptureKey;
|
|
967
|
+
readonly count: number;
|
|
968
|
+
}, StorageError>;
|
|
969
|
+
/** Copy/verify bytes outside a DB transaction; retries reuse registered work. */
|
|
970
|
+
readonly run: (key: RetainedCaptureKey) => Effect.Effect<void, StorageError>;
|
|
971
|
+
/** Seal with the caller's final manifest and durable result in one DB TX. */
|
|
972
|
+
readonly seal: (tx: DataStore, key: RetainedCaptureKey) => Effect.Effect<RetainedCapturePin, StorageError>;
|
|
973
|
+
/** Private pins. Consume through EOF and stage output until digest success.
|
|
974
|
+
* Pass the same application transaction when enumerating a just-sealed pin. */
|
|
975
|
+
readonly items: (pin: RetainedCapturePin, tx?: DataStore) => Stream.Stream<RetainedStorageObject, StorageError>;
|
|
976
|
+
/** Trusted server read of a verified member pin. Not an access grant.
|
|
977
|
+
* Tenant admission must come from the caller; finish byte verification at EOF. */
|
|
978
|
+
readonly read: (capture: RetainedCapturePin, object: RetainedStorageObject, scope: {
|
|
979
|
+
readonly tenantId: string | null;
|
|
980
|
+
readonly maxBytes: number;
|
|
981
|
+
}) => Effect.Effect<{
|
|
982
|
+
readonly stream: ByteStream;
|
|
983
|
+
readonly contentType: string;
|
|
984
|
+
readonly size: number;
|
|
985
|
+
}, StorageError>;
|
|
986
|
+
/** Close admission before cleanup. Repeat cleanup after uncertain/late I/O. */
|
|
987
|
+
readonly abandon: (key: RetainedCaptureKey) => Effect.Effect<void, StorageError>;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
export { StorageDestination }
|
|
991
|
+
|
|
992
|
+
declare interface StorageDestinationBinding {
|
|
993
|
+
readonly selected: () => string;
|
|
994
|
+
readonly directDestination: string | undefined;
|
|
995
|
+
readonly directProvider: () => StorageProvider;
|
|
996
|
+
readonly registry: () => ConnectionRegistryShape | undefined;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
export { StorageDestinationRouter }
|
|
1000
|
+
|
|
756
1001
|
/**
|
|
757
1002
|
* Where the bytes go, read from the same options and env `resolveProvider`
|
|
758
1003
|
* reads: an object store is a destination outside the installation; the
|
|
@@ -760,20 +1005,7 @@ declare const StorageAccessDenied_base: Schema.Class<StorageAccessDenied, Schema
|
|
|
760
1005
|
*/
|
|
761
1006
|
export declare const storageEgressOf: (options: StoragePluginOptions) => ReadonlyArray<PluginEgressDeclaration>;
|
|
762
1007
|
|
|
763
|
-
|
|
764
|
-
* Storage failure. `transient` drives retry — `true` for 429 / 5xx /
|
|
765
|
-
* network blips, `false` for 4xx / config / not-found. Surfaced typed so
|
|
766
|
-
* handlers can `Effect.catchTag('StorageError', …)`.
|
|
767
|
-
*/
|
|
768
|
-
export declare class StorageError extends StorageError_base {
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
declare const StorageError_base: Schema.Class<StorageError, Schema.TaggedStruct<"StorageError", {
|
|
772
|
-
readonly provider: Schema.String;
|
|
773
|
-
readonly message: Schema.String;
|
|
774
|
-
readonly transient: Schema.Boolean;
|
|
775
|
-
readonly status: Schema.optional<Schema.Number>;
|
|
776
|
-
}>, YieldableError>;
|
|
1008
|
+
export { StorageError }
|
|
777
1009
|
|
|
778
1010
|
/** A persisted, explicit share of one object with one principal. */
|
|
779
1011
|
export declare interface StorageGrant {
|
|
@@ -803,9 +1035,11 @@ export declare type StorageGuard = (ctx: {
|
|
|
803
1035
|
* and `BASE_NAME` is not exported, so a caller minting a ticket outside the
|
|
804
1036
|
* plugin had to guess it. Guessing is exactly what a `string` parameter invites.
|
|
805
1037
|
*
|
|
806
|
-
*
|
|
1038
|
+
* Use this name in the ticket's `instance` field. The ticket also captures
|
|
1039
|
+
* the selected destination, owner, tenant, content type and visibility.
|
|
1040
|
+
* const writeScope = await Effect.runPromise(service.uploadTicketScope({ tenantId, destination }))
|
|
807
1041
|
* const ticket = signUploadTicket(
|
|
808
|
-
* { writeScope, instance: storageInstanceName(options), key, ct: contentType, sub: ownerId, tenant: tenantId, vis: 'private' },
|
|
1042
|
+
* { writeScope, destination, instance: storageInstanceName(options), key, ct: contentType, sub: ownerId, tenant: tenantId, vis: 'private' },
|
|
809
1043
|
* 300,
|
|
810
1044
|
* )
|
|
811
1045
|
*
|
|
@@ -815,16 +1049,24 @@ export declare type StorageGuard = (ctx: {
|
|
|
815
1049
|
*/
|
|
816
1050
|
export declare const storageInstanceName: (options?: StoragePluginOptions) => string;
|
|
817
1051
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
1052
|
+
/** Internal database-only admission. Runs under the storage tenant lock, in
|
|
1053
|
+
* the same transaction as reserve/join/confirm. It must lock or write its own
|
|
1054
|
+
* durable owner row; observing a live flag before this transaction is unsafe.
|
|
1055
|
+
* No provider, engine or other external I/O belongs in this callback. */
|
|
1056
|
+
declare type StorageObjectAdmission = (tx: DataStore, identity: StorageObjectIdentity, phase: 'reserve' | 'confirm') => Promise<void>;
|
|
1057
|
+
|
|
1058
|
+
export declare interface StorageObjectIdentity extends StorageObjectOperationKey {
|
|
822
1059
|
/** Hash of all immutable put inputs, including content and access metadata. */
|
|
823
1060
|
readonly fingerprint: string;
|
|
824
1061
|
/** SHA-256 of the actual normalized provider bytes, separate from metadata. */
|
|
825
1062
|
readonly checksum: string;
|
|
826
1063
|
/** Already tenant-scoped logical provider key. */
|
|
827
1064
|
readonly logicalKey: string;
|
|
1065
|
+
/** Private retained-input provenance; not an access rule or CMS policy. */
|
|
1066
|
+
readonly retainedSource?: {
|
|
1067
|
+
readonly refId: string;
|
|
1068
|
+
readonly digest: string;
|
|
1069
|
+
};
|
|
828
1070
|
}
|
|
829
1071
|
|
|
830
1072
|
/** Internal persistence substrate. Service wiring must commit quota and refs in
|
|
@@ -855,6 +1097,8 @@ export declare const storageObjectLifecycleTables: ( Table<"_voltro_storage_oper
|
|
|
855
1097
|
readonly claim: ColumnBuilder<string, "text", boolean>;
|
|
856
1098
|
}>, false, never>)[];
|
|
857
1099
|
|
|
1100
|
+
export { StorageObjectLocation }
|
|
1101
|
+
|
|
858
1102
|
export declare type StorageObjectMetadata = ReturnType<typeof makeStorageObjectMetadata>;
|
|
859
1103
|
|
|
860
1104
|
/** Credential-independent identity of a physical object-key namespace.
|
|
@@ -870,11 +1114,42 @@ export declare interface StorageObjectNamespaceMigrationResult {
|
|
|
870
1114
|
readonly pendingDeletes: readonly StorageObjectNamespaceAssignment[];
|
|
871
1115
|
}
|
|
872
1116
|
|
|
1117
|
+
export declare interface StorageObjectOperationKey {
|
|
1118
|
+
readonly tenantId: string | null;
|
|
1119
|
+
readonly bucket: string;
|
|
1120
|
+
readonly operationId: string;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
export declare interface StorageObjectOperationScope extends StorageReferenceScope {
|
|
1124
|
+
readonly tenantId: string | null;
|
|
1125
|
+
readonly bucket: string;
|
|
1126
|
+
readonly operationId: string;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
export declare type StorageObjectReference = Pick<StorageRef, 'bucket' | 'tenantId' | 'key' | 'visibility'> & Partial<StorageReferenceScope>;
|
|
1130
|
+
|
|
1131
|
+
/** A durable metadata observation, not a claim on the object or a provider HEAD. */
|
|
1132
|
+
export declare type StorageOperationState = {
|
|
1133
|
+
readonly state: 'absent' | 'reserved' | 'deleting' | 'deleted';
|
|
1134
|
+
} | {
|
|
1135
|
+
readonly state: 'ready';
|
|
1136
|
+
readonly ref: StorageRef;
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
/** Metadata state qualified by the actual selected storage destination. */
|
|
1140
|
+
export declare type StorageOperationStatus = StorageOperationState & {
|
|
1141
|
+
/** Configured instance, actual catalogue, physical namespace and logical bucket. */
|
|
1142
|
+
readonly scope: string;
|
|
1143
|
+
/** Selected logical destination; retain it with the scope before minting a ticket. */
|
|
1144
|
+
readonly destination: string;
|
|
1145
|
+
};
|
|
1146
|
+
|
|
873
1147
|
export declare const storagePlugin: (options?: StoragePluginOptions) => VoltroPlugin;
|
|
874
1148
|
|
|
875
1149
|
export declare interface StoragePluginOptions {
|
|
876
1150
|
/** `'s3' | 'minio' | 'filesystem' | 'memory'` (built from env) or a
|
|
877
1151
|
* `StorageProvider`. Default: `STORAGE_PROVIDER` env, else `'memory'`. */
|
|
1152
|
+
readonly connection?: ConnectionRef<'storage'>;
|
|
878
1153
|
readonly provider?: StorageProviderName | StorageProvider;
|
|
879
1154
|
/** Bucket name (s3/minio). Default `S3_BUCKET`/`STORAGE_BUCKET` env, else 'voltro'. */
|
|
880
1155
|
readonly bucket?: string;
|
|
@@ -1018,100 +1293,9 @@ export declare interface StoragePluginOptions {
|
|
|
1018
1293
|
readonly name?: string;
|
|
1019
1294
|
}
|
|
1020
1295
|
|
|
1021
|
-
|
|
1022
|
-
* A backend transport. Keyed by an opaque object key (the service owns key
|
|
1023
|
-
* derivation + tenant prefixing); knows nothing about refs, tenants, or
|
|
1024
|
-
* access policy.
|
|
1025
|
-
*/
|
|
1026
|
-
export declare interface StorageProvider {
|
|
1027
|
-
/** Stable physical object-key namespace; exclude credentials and plugin aliases. */
|
|
1028
|
-
readonly objectNamespace: Effect.Effect<string, StorageError>;
|
|
1029
|
-
/**
|
|
1030
|
-
* Where a FILESYSTEM provider writes. Absent for every other provider.
|
|
1031
|
-
*
|
|
1032
|
-
* It exists so a caller can ask a question this interface otherwise cannot
|
|
1033
|
-
* answer: does what I write here survive the process? A rollback capture
|
|
1034
|
-
* written for a pod that then dies is worthless, and `filesystem` is the one
|
|
1035
|
-
* provider that can be either — a mounted volume or an ephemeral container
|
|
1036
|
-
* directory. A deployment pointed this out: their check for "storage is
|
|
1037
|
-
* configured" passed on a `/tmp` path with no volume behind it.
|
|
1038
|
-
*/
|
|
1039
|
-
readonly root?: string;
|
|
1040
|
-
readonly name: string;
|
|
1041
|
-
/** True when `getUrl` returns a real presigned URL (s3/minio). When
|
|
1042
|
-
* false the service serves bytes via the `/_voltro/storage/:id`
|
|
1043
|
-
* endpoint instead (filesystem/memory). */
|
|
1044
|
-
readonly presigns: boolean;
|
|
1045
|
-
readonly put: (key: string, bytes: Uint8Array, meta: {
|
|
1046
|
-
readonly contentType: string;
|
|
1047
|
-
readonly public?: boolean;
|
|
1048
|
-
}) => Effect.Effect<ObjectMeta, StorageError>;
|
|
1049
|
-
readonly get: (key: string) => Effect.Effect<StoredObject, StorageError>;
|
|
1050
|
-
readonly delete: (key: string) => Effect.Effect<void, StorageError>;
|
|
1051
|
-
/** Presigned GET (s3/minio) for private reads. */
|
|
1052
|
-
readonly getUrl: (key: string, expiresInSec: number) => Effect.Effect<string, StorageError>;
|
|
1053
|
-
/** A direct, cacheable URL for a PUBLIC object — virtual-hosted bucket
|
|
1054
|
-
* URL or a configured CDN base. `null` when the provider can't serve
|
|
1055
|
-
* publicly without the app (filesystem/memory) → the service falls
|
|
1056
|
-
* back to the `/_voltro/storage/:id` route. */
|
|
1057
|
-
readonly publicUrl?: (key: string) => string | null;
|
|
1058
|
-
/** Make an object publicly readable at the provider, or not (s3/minio with
|
|
1059
|
-
* per-object ACLs). Absent where the app decides per request (database,
|
|
1060
|
-
* filesystem, memory) — there a ref's visibility is the whole answer. */
|
|
1061
|
-
readonly setObjectPublic?: (key: string, isPublic: boolean) => Effect.Effect<void, StorageError>;
|
|
1062
|
-
/** Presigned PUT for direct-to-bucket uploads (s3/minio). Absent on
|
|
1063
|
-
* providers that can't presign uploads. */
|
|
1064
|
-
readonly getUploadUrl?: (key: string, expiresInSec: number, contentType: string) => Effect.Effect<string, StorageError>;
|
|
1065
|
-
readonly createMultipartUpload?: (key: string, contentType: string, opts?: {
|
|
1066
|
-
readonly public?: boolean;
|
|
1067
|
-
}) => Effect.Effect<{
|
|
1068
|
-
readonly uploadId: string;
|
|
1069
|
-
}, StorageError>;
|
|
1070
|
-
readonly presignUploadPart?: (key: string, uploadId: string, partNumber: number, expiresInSec: number) => Effect.Effect<string, StorageError>;
|
|
1071
|
-
readonly completeMultipartUpload?: (key: string, uploadId: string, parts: ReadonlyArray<{
|
|
1072
|
-
readonly partNumber: number;
|
|
1073
|
-
readonly etag: string;
|
|
1074
|
-
}>) => Effect.Effect<{
|
|
1075
|
-
readonly etag?: string;
|
|
1076
|
-
}, StorageError>;
|
|
1077
|
-
readonly abortMultipartUpload?: (key: string, uploadId: string) => Effect.Effect<void, StorageError>;
|
|
1078
|
-
readonly head: (key: string) => Effect.Effect<ObjectMeta | null, StorageError>;
|
|
1079
|
-
/**
|
|
1080
|
-
* Stream an object's bytes in chunks instead of buffering the whole blob
|
|
1081
|
-
* ({@link get}). Present on backends with a real streaming read (filesystem,
|
|
1082
|
-
* s3, azure). OPTIONAL: when a provider omits it, {@link getObjectStream}
|
|
1083
|
-
* transparently falls back to `get` + a chunked in-memory stream — correct
|
|
1084
|
-
* for the small-blob backends (memory / database) that have nothing to
|
|
1085
|
-
* stream from.
|
|
1086
|
-
*/
|
|
1087
|
-
readonly getStream?: (key: string) => Effect.Effect<StoredStream, StorageError>;
|
|
1088
|
-
/**
|
|
1089
|
-
* Consume a {@link ByteStream} and store it via the backend's chunked /
|
|
1090
|
-
* multipart upload, so a large upload never fully materialises in memory.
|
|
1091
|
-
* Present on filesystem (streamed atomic write), s3 (multipart via
|
|
1092
|
-
* `@aws-sdk/lib-storage`), azure (`uploadStream`). OPTIONAL: when absent,
|
|
1093
|
-
* {@link putObjectStream} buffers the stream and calls `put`. `totalSize`,
|
|
1094
|
-
* when the caller knows it (e.g. from an export manifest), lets the backend
|
|
1095
|
-
* report an accurate size without a follow-up HEAD.
|
|
1096
|
-
*/
|
|
1097
|
-
readonly putStream?: (key: string, stream: ByteStream, meta: {
|
|
1098
|
-
readonly contentType: string;
|
|
1099
|
-
readonly public?: boolean;
|
|
1100
|
-
readonly totalSize?: number;
|
|
1101
|
-
}) => Effect.Effect<ObjectMeta, StorageError>;
|
|
1102
|
-
/**
|
|
1103
|
-
* Read a byte range `[start, endInclusive]` (HTTP Range / fd offset). Enables
|
|
1104
|
-
* seekable + resumable reads. OPTIONAL and best-effort: whole-object resume
|
|
1105
|
-
* already works via content-addressing (skip an asset whose hash is present
|
|
1106
|
-
* at the target), so this is an optimisation, not a correctness requirement.
|
|
1107
|
-
*/
|
|
1108
|
-
readonly getRange?: (key: string, start: number, endInclusive: number) => Effect.Effect<Uint8Array, StorageError>;
|
|
1109
|
-
/** Providers that store bytes via the app's DataStore (e.g. `database`)
|
|
1110
|
-
* receive it here once it exists — bound by the plugin at boot. */
|
|
1111
|
-
readonly bindDataStore?: (store: unknown) => void;
|
|
1112
|
-
}
|
|
1296
|
+
export { StorageProvider }
|
|
1113
1297
|
|
|
1114
|
-
export
|
|
1298
|
+
export { StorageProviderName }
|
|
1115
1299
|
|
|
1116
1300
|
export declare const storagePutIntentsTable: Table<"_voltro_storage_put_intents", FieldDefinitions<{
|
|
1117
1301
|
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
@@ -1166,8 +1350,13 @@ export declare interface StorageRef {
|
|
|
1166
1350
|
readonly derivedFrom?: string | null;
|
|
1167
1351
|
/** Derivative label — e.g. `'rendition'` / `'poster'`; null on an original. */
|
|
1168
1352
|
readonly kind?: string | null;
|
|
1353
|
+
/** Immutable provenance for an attested transcode; absent on older/unproven refs. */
|
|
1354
|
+
readonly renditionProof?: RenditionProof | null;
|
|
1169
1355
|
}
|
|
1170
1356
|
|
|
1357
|
+
/** Persisted destination ownership is independent of the current write selection. */
|
|
1358
|
+
export declare const storageRefAddress: (ref: Pick<StorageRef, "bucket" | "tenantId" | "key">) => StorageAddress;
|
|
1359
|
+
|
|
1171
1360
|
export declare const storageReferenceCatalogueTable: Table<"_voltro_storage_reference_catalogue", FieldDefinitions<{
|
|
1172
1361
|
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
1173
1362
|
readonly namespace: ColumnBuilder<string, "text", boolean>;
|
|
@@ -1178,11 +1367,21 @@ export declare interface StorageReferenceInstanceAssignment {
|
|
|
1178
1367
|
readonly storageInstance: string;
|
|
1179
1368
|
}
|
|
1180
1369
|
|
|
1370
|
+
/** A plugin instance may retain several tenant-specific physical destinations.
|
|
1371
|
+
* Resolve the concrete namespace at the boundary; never substitute a sentinel
|
|
1372
|
+
* namespace for a tenant-scoped connection. */
|
|
1373
|
+
export declare interface StorageReferenceResolver {
|
|
1374
|
+
readonly storageInstance: string;
|
|
1375
|
+
readonly resolveNamespace: (address: StorageAddress) => Effect.Effect<string, StorageError>;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1181
1378
|
export declare interface StorageReferenceScope {
|
|
1182
1379
|
readonly storageInstance: string;
|
|
1183
1380
|
readonly objectNamespace: string;
|
|
1184
1381
|
}
|
|
1185
1382
|
|
|
1383
|
+
export declare type StorageReferenceView = StorageReferenceScope | StorageReferenceResolver;
|
|
1384
|
+
|
|
1186
1385
|
/** An upload was rejected by a constraint (size / content-type / magic-byte
|
|
1187
1386
|
* mismatch). `reason` is a stable code; `detail` is human-readable. */
|
|
1188
1387
|
export declare class StorageRejected extends StorageRejected_base {
|
|
@@ -1217,6 +1416,9 @@ export declare interface StorageScanResult {
|
|
|
1217
1416
|
readonly threat?: string;
|
|
1218
1417
|
}
|
|
1219
1418
|
|
|
1419
|
+
/** A secret, or the set a rotation keeps accepting (the signing one first). */
|
|
1420
|
+
declare type StorageSecrets = string | ReadonlyArray<string>;
|
|
1421
|
+
|
|
1220
1422
|
export declare class StorageService extends StorageService_base {
|
|
1221
1423
|
}
|
|
1222
1424
|
|
|
@@ -1229,6 +1431,10 @@ export declare interface StorageServiceOptions {
|
|
|
1229
1431
|
readonly refStore: RefStore;
|
|
1230
1432
|
readonly grantStore: GrantStore;
|
|
1231
1433
|
readonly bucket: string;
|
|
1434
|
+
/** New writes select a destination; reads retain SQL destination/tenant ownership. */
|
|
1435
|
+
readonly destinations?: StorageDestinationRouter;
|
|
1436
|
+
/** App-owned resolution of each persisted physical reference owner. */
|
|
1437
|
+
readonly resolveObjectReference?: (reference: StorageObjectReference) => Effect.Effect<StorageProvider, StorageError>;
|
|
1232
1438
|
/** Canonical plugin instance; separates new plain keys on a shared provider. */
|
|
1233
1439
|
readonly storageInstance?: string;
|
|
1234
1440
|
/** Static prefix prepended to every key (e.g. an app/env namespace). */
|
|
@@ -1283,8 +1489,20 @@ export declare interface StorageServiceOptions {
|
|
|
1283
1489
|
|
|
1284
1490
|
/** The service handlers consume: `const storage = yield* StorageService`. */
|
|
1285
1491
|
export declare interface StorageServiceShape {
|
|
1492
|
+
/** Trusted server read of one raw durable put identity in this configured
|
|
1493
|
+
* instance/physical namespace/bucket and the explicitly supplied tenant.
|
|
1494
|
+
* No access-policy check, claim, byte read, retry write or provider HEAD.
|
|
1495
|
+
* Unbound/unsupported/corrupt metadata refuses; it never becomes absence. */
|
|
1496
|
+
readonly operationStatus: (input: {
|
|
1497
|
+
readonly operationId: string;
|
|
1498
|
+
readonly tenantId: string | null;
|
|
1499
|
+
readonly destination?: string;
|
|
1500
|
+
}) => Effect.Effect<StorageOperationStatus, StorageError>;
|
|
1286
1501
|
/** Opaque destination binding for manually signed upload-family credentials. */
|
|
1287
|
-
readonly uploadTicketScope: (
|
|
1502
|
+
readonly uploadTicketScope: (input?: {
|
|
1503
|
+
readonly tenantId?: string | null;
|
|
1504
|
+
readonly destination?: string;
|
|
1505
|
+
}) => Effect.Effect<string, StorageError>;
|
|
1288
1506
|
/** Store bytes. The result is the ref plus this call's `outcome`. */
|
|
1289
1507
|
readonly put: (input: PutInput) => Effect.Effect<StoredRef, StorageError | StorageRejected | StorageScanRejected>;
|
|
1290
1508
|
/** Fetch an object's bytes by id. Enforces the tenant guard ONLY — it does
|
|
@@ -1455,9 +1673,9 @@ export declare interface StorageServiceShape {
|
|
|
1455
1673
|
readonly contentType: string;
|
|
1456
1674
|
readonly tenantId?: string | null;
|
|
1457
1675
|
readonly expiresInSec?: number;
|
|
1458
|
-
}) => Effect.Effect<{
|
|
1676
|
+
}) => Effect.Effect<StorageAddress & {
|
|
1677
|
+
readonly writeScope: string;
|
|
1459
1678
|
readonly uploadUrl: string;
|
|
1460
|
-
readonly key: string;
|
|
1461
1679
|
readonly expiresInSec: number;
|
|
1462
1680
|
}, StorageError>;
|
|
1463
1681
|
/** Promote a blob the client PUT directly to a TEMP `key` into a real ref:
|
|
@@ -1466,6 +1684,7 @@ export declare interface StorageServiceShape {
|
|
|
1466
1684
|
* scanned + a non-degraded ref — out of band from the direct PUT. On a scan
|
|
1467
1685
|
* reject the temp bytes are deleted (fail-closed, nothing promoted). */
|
|
1468
1686
|
readonly finalizeUpload: (input: {
|
|
1687
|
+
readonly destination: string;
|
|
1469
1688
|
readonly key: string;
|
|
1470
1689
|
readonly contentType: string;
|
|
1471
1690
|
readonly tenantId?: string | null;
|
|
@@ -1480,6 +1699,7 @@ export declare interface StorageServiceShape {
|
|
|
1480
1699
|
/** Store one chunk of a resumable upload as its own durable `_incoming/<id>/
|
|
1481
1700
|
* <index>` object. Idempotent — re-PUTting the same index overwrites it. */
|
|
1482
1701
|
readonly putResumableChunk: (input: {
|
|
1702
|
+
readonly destination: string;
|
|
1483
1703
|
readonly uploadId: string;
|
|
1484
1704
|
readonly index: number;
|
|
1485
1705
|
readonly bytes: Uint8Array;
|
|
@@ -1489,6 +1709,7 @@ export declare interface StorageServiceShape {
|
|
|
1489
1709
|
* 0 and returns the received byte `offset` + the `nextIndex` to send. Lets a
|
|
1490
1710
|
* reconnecting client resume instead of restarting. */
|
|
1491
1711
|
readonly resumableStatus: (input: {
|
|
1712
|
+
readonly destination: string;
|
|
1492
1713
|
readonly uploadId: string;
|
|
1493
1714
|
readonly tenantId?: string | null;
|
|
1494
1715
|
}) => Effect.Effect<{
|
|
@@ -1499,6 +1720,7 @@ export declare interface StorageServiceShape {
|
|
|
1499
1720
|
* concatenate, run the FULL `put()` pipeline, then delete the chunk objects
|
|
1500
1721
|
* (on success AND on reject — fail-closed). */
|
|
1501
1722
|
readonly finalizeResumable: (input: {
|
|
1723
|
+
readonly destination: string;
|
|
1502
1724
|
readonly uploadId: string;
|
|
1503
1725
|
readonly count: number;
|
|
1504
1726
|
readonly contentType: string;
|
|
@@ -1530,12 +1752,14 @@ export declare interface StorageServiceShape {
|
|
|
1530
1752
|
readonly tenantId?: string | null;
|
|
1531
1753
|
readonly visibility?: StorageVisibility;
|
|
1532
1754
|
readonly expiresInSec?: number;
|
|
1533
|
-
}) => Effect.Effect<{
|
|
1755
|
+
}) => Effect.Effect<StorageAddress & {
|
|
1756
|
+
readonly writeScope: string;
|
|
1534
1757
|
readonly uploadId: string;
|
|
1535
|
-
readonly key: string;
|
|
1536
1758
|
}, StorageError>;
|
|
1537
1759
|
/** Presign a PUT for one part (1-based `partNumber`). */
|
|
1538
1760
|
readonly signMultipartPart: (input: {
|
|
1761
|
+
readonly destination: string;
|
|
1762
|
+
readonly tenantId: string | null;
|
|
1539
1763
|
readonly key: string;
|
|
1540
1764
|
readonly uploadId: string;
|
|
1541
1765
|
readonly partNumber: number;
|
|
@@ -1545,6 +1769,7 @@ export declare interface StorageServiceShape {
|
|
|
1545
1769
|
* registered straight from it (size via HEAD, etag as checksum). No fetch-back,
|
|
1546
1770
|
* so NO scan/derivatives — scan multi-GB out of band. */
|
|
1547
1771
|
readonly completeMultipart: (input: {
|
|
1772
|
+
readonly destination: string;
|
|
1548
1773
|
readonly key: string;
|
|
1549
1774
|
readonly uploadId: string;
|
|
1550
1775
|
readonly parts: ReadonlyArray<{
|
|
@@ -1563,20 +1788,36 @@ export declare interface StorageServiceShape {
|
|
|
1563
1788
|
}) => Effect.Effect<StorageRef, StorageError | StorageRejected>;
|
|
1564
1789
|
/** Abort a multipart session (client cancelled) — frees the bucket's parts. */
|
|
1565
1790
|
readonly abortMultipart: (input: {
|
|
1791
|
+
readonly destination: string;
|
|
1792
|
+
readonly tenantId: string | null;
|
|
1566
1793
|
readonly key: string;
|
|
1567
1794
|
readonly uploadId: string;
|
|
1568
1795
|
}) => Effect.Effect<void, StorageError>;
|
|
1569
1796
|
}
|
|
1570
1797
|
|
|
1798
|
+
/** Trusted build-input metadata, not a delivery DTO or access grant. The
|
|
1799
|
+
* caller persists this alongside its immutable publication/recipe selection. */
|
|
1800
|
+
export declare interface StorageSourcePin {
|
|
1801
|
+
readonly version: 1;
|
|
1802
|
+
readonly instance: string;
|
|
1803
|
+
readonly tenantId: string | null;
|
|
1804
|
+
readonly bucket: string;
|
|
1805
|
+
readonly id: string;
|
|
1806
|
+
readonly sourceDigest: string;
|
|
1807
|
+
readonly checksum: string;
|
|
1808
|
+
readonly size: number;
|
|
1809
|
+
readonly contentType: string;
|
|
1810
|
+
readonly derivedFrom: string | null;
|
|
1811
|
+
readonly kind: string | null;
|
|
1812
|
+
readonly renditionProof: RenditionProof | null;
|
|
1813
|
+
readonly digest: string;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1571
1816
|
/** `public` = anyone, served direct from bucket/CDN; `private` = gated by
|
|
1572
1817
|
* the ref's access policy + grants. Default for a new put is `private`. */
|
|
1573
1818
|
export declare type StorageVisibility = 'public' | 'private';
|
|
1574
1819
|
|
|
1575
|
-
|
|
1576
|
-
export declare interface StoredObject {
|
|
1577
|
-
readonly bytes: Uint8Array;
|
|
1578
|
-
readonly contentType: string;
|
|
1579
|
-
}
|
|
1820
|
+
export { StoredObject }
|
|
1580
1821
|
|
|
1581
1822
|
/** What `put` returns: the stored ref, plus what this call did to it. The
|
|
1582
1823
|
* `outcome` is a fact about the CALL, not the row — it is never persisted and
|
|
@@ -1585,13 +1826,7 @@ export declare type StoredRef = StorageRef & {
|
|
|
1585
1826
|
readonly outcome: PutOutcome;
|
|
1586
1827
|
};
|
|
1587
1828
|
|
|
1588
|
-
|
|
1589
|
-
* its content type and, when the backend reports it up front, its size. */
|
|
1590
|
-
export declare interface StoredStream {
|
|
1591
|
-
readonly stream: ByteStream;
|
|
1592
|
-
readonly contentType: string;
|
|
1593
|
-
readonly size?: number;
|
|
1594
|
-
}
|
|
1829
|
+
export { StoredStream }
|
|
1595
1830
|
|
|
1596
1831
|
/**
|
|
1597
1832
|
* A ByteStream → Node `Readable`, for SDK uploaders that consume Node streams
|
|
@@ -1613,9 +1848,7 @@ export declare type Transcoder = (input: {
|
|
|
1613
1848
|
readonly ref: StorageRef;
|
|
1614
1849
|
}) => ReadonlyArray<Rendition> | Promise<ReadonlyArray<Rendition>> | Effect.Effect<ReadonlyArray<Rendition>>;
|
|
1615
1850
|
|
|
1616
|
-
|
|
1617
|
-
* requests for the same variant don't re-encode. */
|
|
1618
|
-
export declare const transformCached: (refId: string, bytes: Uint8Array, contentType: string, params: TransformParams) => Promise<Transformed | null>;
|
|
1851
|
+
export declare const transformCached: (addressIdentity: string, bytes: Uint8Array, contentType: string, params: TransformParams) => Promise<Transformed | null>;
|
|
1619
1852
|
|
|
1620
1853
|
export declare interface Transformed {
|
|
1621
1854
|
readonly bytes: Uint8Array;
|
|
@@ -1678,6 +1911,8 @@ export declare interface UploadTicketPayload {
|
|
|
1678
1911
|
readonly issuerReplicaId?: string;
|
|
1679
1912
|
/** Exact storage plugin instance authorized to accept the bytes. */
|
|
1680
1913
|
readonly instance: string;
|
|
1914
|
+
/** Logical destination selected before issuing the upload/session. */
|
|
1915
|
+
readonly destination: string;
|
|
1681
1916
|
/** ownerId (subject id) the stored object is attributed to. */
|
|
1682
1917
|
readonly sub: string | null;
|
|
1683
1918
|
/** tenantId that scopes the key prefix + ref row. */
|
|
@@ -1708,28 +1943,28 @@ export declare interface UsageDelta {
|
|
|
1708
1943
|
|
|
1709
1944
|
/** Verify a finalize token. Returns the payload on success, null on any failure
|
|
1710
1945
|
* (malformed, bad signature, expired, missing temp key). Never throws. */
|
|
1711
|
-
export declare const verifyFinalizeTicket: (token: string, secret?:
|
|
1946
|
+
export declare const verifyFinalizeTicket: (token: string, secret?: StorageSecrets) => FinalizeTicketPayload | null;
|
|
1712
1947
|
|
|
1713
1948
|
/**
|
|
1714
1949
|
* Verify a grant token. Returns the payload on success, null on any
|
|
1715
1950
|
* failure (malformed, bad signature, expired). Never throws.
|
|
1716
1951
|
*/
|
|
1717
|
-
export declare const verifyGrant: (token: string, secret?:
|
|
1952
|
+
export declare const verifyGrant: (token: string, secret?: StorageSecrets) => GrantTokenPayload | null;
|
|
1718
1953
|
|
|
1719
1954
|
/** Verify a multipart ticket. Returns the payload on success, null on any
|
|
1720
1955
|
* failure (malformed, bad signature, expired, missing key/uploadId). */
|
|
1721
|
-
export declare const verifyMultipartTicket: (token: string, secret?:
|
|
1956
|
+
export declare const verifyMultipartTicket: (token: string, secret?: StorageSecrets) => MultipartTicketPayload | null;
|
|
1722
1957
|
|
|
1723
1958
|
/** Constant-time check of a plaintext password against a stored hash. */
|
|
1724
1959
|
export declare const verifyPassword: (password: string | undefined, stored: string | null) => boolean;
|
|
1725
1960
|
|
|
1726
1961
|
/** Verify a resumable ticket. Returns the payload on success, null on any
|
|
1727
1962
|
* failure (malformed, bad signature, expired, missing id/size). Never throws. */
|
|
1728
|
-
export declare const verifyResumableTicket: (token: string, secret?:
|
|
1963
|
+
export declare const verifyResumableTicket: (token: string, secret?: StorageSecrets) => ResumableTicketPayload | null;
|
|
1729
1964
|
|
|
1730
1965
|
/** Verify an upload ticket. Returns the payload on success, null on any
|
|
1731
1966
|
* failure (malformed, bad signature, expired). Never throws. */
|
|
1732
|
-
export declare const verifyUploadTicket: (token: string, secret?:
|
|
1967
|
+
export declare const verifyUploadTicket: (token: string, secret?: StorageSecrets) => UploadTicketPayload | null;
|
|
1733
1968
|
|
|
1734
1969
|
/**
|
|
1735
1970
|
* App-supplied media probe for video/audio uploads. The core deliberately does
|
|
@@ -1774,4 +2009,7 @@ export declare const _voltroStorageUsageTable: TableLike;
|
|
|
1774
2009
|
*/
|
|
1775
2010
|
export declare const withStorage: () => ReturnType<typeof mixin>;
|
|
1776
2011
|
|
|
2012
|
+
/** All keyed operations share the same namespace, including presigned and multipart paths. */
|
|
2013
|
+
export declare const withStorageKeyPrefix: (provider: StorageProvider, prefix?: string) => StorageProvider;
|
|
2014
|
+
|
|
1777
2015
|
export { }
|