@voltro/plugin-storage 0.85.0 → 0.87.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 +5987 -0
- package/README.md +77 -0
- package/THIRD-PARTY-NOTICES.md +860 -249
- package/dist/access.js +47 -0
- package/dist/assetRef.js +13 -0
- package/dist/avatar.js +39 -0
- package/dist/byteSecurity.d.ts +3 -0
- package/dist/byteSecurity.js +7 -0
- package/dist/connection.js +99 -0
- package/dist/constraints.js +93 -0
- package/dist/custody.js +132 -0
- package/dist/derivatives.js +30 -0
- package/dist/env.js +162 -0
- package/dist/grant.js +132 -0
- package/dist/index.d.ts +525 -203
- package/dist/index.js +765 -3196
- package/dist/ingest.js +87 -0
- package/dist/ingestPolicy.js +1 -0
- package/dist/metadataError.js +19 -0
- package/dist/objectAbandon.js +16 -0
- package/dist/objectLifecycle.js +243 -0
- package/dist/objectMetadata.js +308 -0
- package/dist/objectWriter.js +87 -0
- package/dist/pathDurability.js +16 -0
- package/dist/physicalReferences.js +54 -0
- package/dist/providers.js +638 -0
- package/dist/referenceCatalogue.js +31 -0
- package/dist/renditionProof.js +82 -0
- package/dist/retainedCapture.js +391 -0
- package/dist/retainedObjects.js +190 -0
- package/dist/rpc.d.ts +3 -15
- package/dist/rpc.js +3 -1
- package/dist/scanners.js +46 -0
- package/dist/server.d.ts +153 -0
- package/dist/server.js +4 -0
- package/dist/service.js +1418 -0
- package/dist/sourceIdentity.js +14 -0
- package/dist/sourcePin.js +35 -0
- package/dist/storageNamespaces.js +80 -0
- package/dist/storageNumbers.js +13 -0
- package/dist/storageObjectNamespaces.js +243 -0
- package/dist/storageReferenceInstances.js +52 -0
- package/dist/storageRequest.js +10 -0
- package/dist/storageRouting.js +46 -0
- package/dist/streamBridge.js +33 -0
- package/dist/table.js +54 -0
- package/dist/transcodeVideo.js +91 -0
- package/dist/transform.js +94 -0
- package/dist/transformCache.js +31 -0
- package/dist/types.d.ts +116 -134
- package/dist/types.js +14 -14
- package/package.json +17 -6
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 & {
|
|
@@ -58,6 +86,20 @@ export declare interface AssetRefOptions {
|
|
|
58
86
|
readonly nullable?: boolean;
|
|
59
87
|
}
|
|
60
88
|
|
|
89
|
+
/** The caller owns the after-schema transaction, with serving replicas stopped.
|
|
90
|
+
* Assignments preserve reference IDs, keys, grants, raw put identities, claims
|
|
91
|
+
* and quota. No provider I/O or nested transaction occurs. Returned cleanup
|
|
92
|
+
* targets run through their matching service after boot. */
|
|
93
|
+
export declare const assignStorageObjectNamespacesInTransaction: (store: DataStore, scopes: readonly StorageReferenceScope[], assignments: readonly StorageObjectNamespaceAssignment[]) => Promise<StorageObjectNamespaceMigrationResult>;
|
|
94
|
+
|
|
95
|
+
/** Run in an after-schema migration with serving replicas stopped. The mapping
|
|
96
|
+
* comes from the operator, never from provider failures or the default name.
|
|
97
|
+
* The supplied store belongs to the caller’s transaction. No nested transaction
|
|
98
|
+
* is opened. Only ownership columns change: IDs, bytes, claims, quota and replay stay put. */
|
|
99
|
+
export declare const assignStorageReferenceInstancesInTransaction: (store: DataStore, instances: readonly string[], assignments: readonly StorageReferenceInstanceAssignment[]) => Promise<{
|
|
100
|
+
readonly assigned: number;
|
|
101
|
+
}>;
|
|
102
|
+
|
|
61
103
|
export declare const azureProvider: (options: AzureProviderOptions) => StorageProvider;
|
|
62
104
|
|
|
63
105
|
export declare interface AzureProviderOptions {
|
|
@@ -82,14 +124,7 @@ export declare const buildStorageService: (options: StorageServiceOptions) => St
|
|
|
82
124
|
* stream. `subarray` keeps the chunks as views (no copy). */
|
|
83
125
|
export declare const bytesToStream: (bytes: Uint8Array, chunkSize?: number) => ByteStream;
|
|
84
126
|
|
|
85
|
-
|
|
86
|
-
* A lazy stream of bytes — the streaming counterpart to {@link StoredObject}'s
|
|
87
|
-
* eager `bytes`. Backpressured: chunks are pulled on demand, so a multi-GB blob
|
|
88
|
-
* never fully materialises in memory. The error channel is {@link StorageError}
|
|
89
|
-
* so a stream handed to `putStream` carries the same typed failure the rest of
|
|
90
|
-
* the transport does (callers map their source errors into it).
|
|
91
|
-
*/
|
|
92
|
-
export declare type ByteStream = Stream.Stream<Uint8Array, StorageError>;
|
|
127
|
+
export { ByteStream }
|
|
93
128
|
|
|
94
129
|
/** Check an upload against the limits. Returns `null` when ok, else a
|
|
95
130
|
* `{ reason, detail }` describing the violation. */
|
|
@@ -127,24 +162,13 @@ export declare const collectStream: (stream: ByteStream) => Effect.Effect<Uint8A
|
|
|
127
162
|
/** Concatenate byte chunks into one contiguous Uint8Array. */
|
|
128
163
|
export declare const concatBytes: (chunks: ReadonlyArray<Uint8Array>) => Uint8Array;
|
|
129
164
|
|
|
130
|
-
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
* `restore`, whose whole job is to refuse a flag the app cannot honour. They
|
|
138
|
-
* were dead, and what they let through is worse than an unchecked flag: with no
|
|
139
|
-
* storage configured, `backup --assets` captured from a FRESH memory provider,
|
|
140
|
-
* found nothing in it, and wrote an artefact stamped `assets: { count: 0 }` —
|
|
141
|
-
* a rollback story that says the blobs are in there.
|
|
142
|
-
*
|
|
143
|
-
* "Configured" means one of the two things a person actually did: installed
|
|
144
|
-
* `storagePlugin(...)` (which registers here at construction), or set
|
|
145
|
-
* `STORAGE_PROVIDER`. A memory provider nobody asked for is not a decision.
|
|
146
|
-
*/
|
|
147
|
-
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;
|
|
148
172
|
|
|
149
173
|
/** `image/*` matches `image/png`; exact otherwise. */
|
|
150
174
|
export declare const contentTypeAllowed: (contentType: string, allowed: ReadonlyArray<string> | undefined) => boolean;
|
|
@@ -159,10 +183,13 @@ export declare const databaseProvider: () => StorageProvider & {
|
|
|
159
183
|
bindDataStore: (store: unknown) => void;
|
|
160
184
|
};
|
|
161
185
|
|
|
162
|
-
|
|
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;
|
|
163
190
|
|
|
164
191
|
/** Ref store backed by the app's `DataStore` (`_voltro_storage_refs`). */
|
|
165
|
-
export declare const dataStoreRefStore: (store: DataStore) => RefStore;
|
|
192
|
+
export declare const dataStoreRefStore: (store: DataStore, configuredScope: StorageReferenceView) => RefStore;
|
|
166
193
|
|
|
167
194
|
/** Decode a `data:<mime>;base64,<data>` URI to bytes + content type. */
|
|
168
195
|
export declare const decodeDataUri: (dataUri: string) => {
|
|
@@ -189,6 +216,23 @@ export declare const editImage: (bytes: Uint8Array, contentType: string, edit: I
|
|
|
189
216
|
* chunks, terminated by a zero-length chunk. Exposed for testing. */
|
|
190
217
|
export declare const encodeInstream: (bytes: Uint8Array, chunkSize?: number) => Buffer;
|
|
191
218
|
|
|
219
|
+
/** Boot-time initialization after normal schema reconciliation. This identity
|
|
220
|
+
* describes the persisted reference catalogue, not its provider bytes or host. */
|
|
221
|
+
export declare const ensureStorageReferenceCatalogue: (store: DataStore) => Promise<void>;
|
|
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
|
+
|
|
234
|
+
export declare const fetchIngestBody: (url: string, configuredMaxBytes?: number, policy?: IngestPolicy) => Effect.Effect<StoredObject, StorageError | StorageRejected>;
|
|
235
|
+
|
|
192
236
|
export declare interface FfmpegRenditionSpec {
|
|
193
237
|
/** Derivative class stored on the rendition ref — `'rendition'` / `'poster'`. */
|
|
194
238
|
readonly kind: string;
|
|
@@ -291,7 +335,7 @@ export declare interface ImageEdit {
|
|
|
291
335
|
readonly crop?: Region;
|
|
292
336
|
}
|
|
293
337
|
|
|
294
|
-
/** Where `ingestUrl` may fetch from — see `ssrfReason` in `@voltro/
|
|
338
|
+
/** Where `ingestUrl` may fetch from — see `ssrfReason` in `@voltro/protocol`. */
|
|
295
339
|
export declare interface IngestPolicy {
|
|
296
340
|
/** Hosts (or `host:port`, or `*.suffix`) reachable although internal — a
|
|
297
341
|
* deliberate internal source, or a local test server. Everything else that
|
|
@@ -299,8 +343,13 @@ export declare interface IngestPolicy {
|
|
|
299
343
|
readonly allowHosts?: ReadonlyArray<string>;
|
|
300
344
|
/** Redirect hops followed, each checked again. Default 5. */
|
|
301
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;
|
|
302
349
|
}
|
|
303
350
|
|
|
351
|
+
export { isStorageKey }
|
|
352
|
+
|
|
304
353
|
/**
|
|
305
354
|
* Filter + page a `StorageService.listRefs` / media-library query. Every
|
|
306
355
|
* filter is optional and ANDed; omit them all to page the whole (tenant-scoped)
|
|
@@ -336,63 +385,117 @@ export declare interface ListRefsResult {
|
|
|
336
385
|
readonly nextOffset: number | null;
|
|
337
386
|
}
|
|
338
387
|
|
|
339
|
-
/**
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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>;
|
|
343
401
|
intent: (refId: string) => Promise<{
|
|
344
402
|
identity: {
|
|
345
403
|
readonly tenantId: string | null;
|
|
346
404
|
readonly bucket: string;
|
|
405
|
+
readonly objectNamespace: string;
|
|
406
|
+
readonly fingerprint: string;
|
|
407
|
+
readonly checksum: string;
|
|
408
|
+
readonly storageInstance: string;
|
|
347
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;
|
|
348
437
|
readonly fingerprint: string;
|
|
349
438
|
readonly checksum: string;
|
|
439
|
+
readonly storageInstance: string;
|
|
440
|
+
readonly operationId: string;
|
|
350
441
|
readonly logicalKey: string;
|
|
442
|
+
readonly retainedSource?: {
|
|
443
|
+
readonly refId: string;
|
|
444
|
+
readonly digest: string;
|
|
445
|
+
};
|
|
351
446
|
};
|
|
352
447
|
ref: StorageRef;
|
|
353
448
|
} | undefined>;
|
|
354
|
-
/** `claim` is registered only where the caller receives the ref: here when
|
|
355
|
-
* the operation is already ready (`joined`), else on `confirm`. A claimant
|
|
356
|
-
* whose provider write fails therefore holds nothing. */
|
|
357
449
|
reserve: (identity: StorageObjectIdentity, proposed: StorageRef, quota?: StorageQuota, claim?: string) => Promise<{
|
|
358
450
|
ref: StorageRef;
|
|
359
451
|
ready: boolean;
|
|
360
452
|
outcome: PutOutcome;
|
|
361
453
|
}>;
|
|
362
454
|
confirm: (identity: StorageObjectIdentity, claim?: string) => Promise<StorageRef>;
|
|
363
|
-
/** With a `claim`, releases that claim and deletes the object only when no
|
|
364
|
-
* other claimant holds it; `released` alone (no `operation`) means another
|
|
365
|
-
* claimant still does. Without one, the whole object goes, claims included. */
|
|
366
455
|
beginDelete: (refId: string, tenantId?: string | null, claim?: string) => Promise<{
|
|
367
456
|
released: true;
|
|
368
457
|
identity: {
|
|
369
458
|
readonly tenantId: string | null;
|
|
370
459
|
readonly bucket: string;
|
|
371
|
-
readonly
|
|
460
|
+
readonly objectNamespace: string;
|
|
372
461
|
readonly fingerprint: string;
|
|
373
462
|
readonly checksum: string;
|
|
463
|
+
readonly storageInstance: string;
|
|
464
|
+
readonly operationId: string;
|
|
374
465
|
readonly logicalKey: string;
|
|
466
|
+
readonly retainedSource?: {
|
|
467
|
+
readonly refId: string;
|
|
468
|
+
readonly digest: string;
|
|
469
|
+
};
|
|
375
470
|
};
|
|
376
471
|
operation?: never;
|
|
377
472
|
} | {
|
|
378
473
|
released: true;
|
|
379
474
|
operation: {
|
|
380
475
|
readonly id: string;
|
|
476
|
+
readonly storageInstance: string;
|
|
477
|
+
readonly objectNamespace: string;
|
|
381
478
|
readonly objectId: string;
|
|
382
479
|
readonly fingerprint: string;
|
|
383
480
|
readonly generation: string;
|
|
384
481
|
readonly key: string;
|
|
385
482
|
readonly refId: string;
|
|
386
|
-
readonly state: "ready" | "reserved" | "
|
|
483
|
+
readonly state: "ready" | "reserved" | "deleting" | "deleted";
|
|
387
484
|
readonly deleteKey: string | null;
|
|
388
485
|
};
|
|
389
486
|
identity: {
|
|
390
487
|
readonly tenantId: string | null;
|
|
391
488
|
readonly bucket: string;
|
|
392
|
-
readonly
|
|
489
|
+
readonly objectNamespace: string;
|
|
393
490
|
readonly fingerprint: string;
|
|
394
491
|
readonly checksum: string;
|
|
492
|
+
readonly storageInstance: string;
|
|
493
|
+
readonly operationId: string;
|
|
395
494
|
readonly logicalKey: string;
|
|
495
|
+
readonly retainedSource?: {
|
|
496
|
+
readonly refId: string;
|
|
497
|
+
readonly digest: string;
|
|
498
|
+
};
|
|
396
499
|
};
|
|
397
500
|
}>;
|
|
398
501
|
confirmDelete: (identity: StorageObjectIdentity) => Promise<boolean>;
|
|
@@ -414,11 +517,7 @@ export declare interface MultipartTicketPayload extends Omit<UploadTicketPayload
|
|
|
414
517
|
readonly size: number;
|
|
415
518
|
}
|
|
416
519
|
|
|
417
|
-
|
|
418
|
-
export declare interface ObjectMeta {
|
|
419
|
-
readonly size: number;
|
|
420
|
-
readonly etag?: string;
|
|
421
|
-
}
|
|
520
|
+
export { ObjectMeta }
|
|
422
521
|
|
|
423
522
|
/** Parse a clamd INSTREAM reply: `stream: OK` → clean; `stream: <T> FOUND`
|
|
424
523
|
* → infected; anything else → throws. Exposed for testing. */
|
|
@@ -455,6 +554,8 @@ export declare const putAvatar: (storage: StorageServiceShape, args: {
|
|
|
455
554
|
|
|
456
555
|
/** Input to `StorageService.put`. */
|
|
457
556
|
export declare interface PutInput {
|
|
557
|
+
/** Server-owned logical destination; omitted new writes use this plugin's selection. */
|
|
558
|
+
readonly destination?: string;
|
|
458
559
|
readonly bytes: Uint8Array;
|
|
459
560
|
readonly contentType: string;
|
|
460
561
|
/** Active org id — scopes the key prefix + the ref row. */
|
|
@@ -546,6 +647,13 @@ export declare interface RefStatistics {
|
|
|
546
647
|
}
|
|
547
648
|
|
|
548
649
|
export declare interface RefStore {
|
|
650
|
+
/** Complete metadata-only ownership observation; no pagination or recent limit. */
|
|
651
|
+
readonly listObjectReferences: () => Effect.Effect<ReadonlyArray<StorageObjectReference>, StorageError>;
|
|
652
|
+
/** Stable identity of this actual reference view. Shared catalogues expose
|
|
653
|
+
* the same identity; independent/process-local stores must expose their own. */
|
|
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>;
|
|
549
657
|
/** Aggregate the complete reference index without a recent-object limit. */
|
|
550
658
|
readonly statistics: () => Effect.Effect<RefStatistics, StorageError>;
|
|
551
659
|
readonly insert: (ref: StorageRef) => Effect.Effect<void, StorageError>;
|
|
@@ -555,10 +663,8 @@ export declare interface RefStore {
|
|
|
555
663
|
* same id refund the tenant counter exactly once. */
|
|
556
664
|
readonly delete: (id: string) => Effect.Effect<boolean, StorageError>;
|
|
557
665
|
readonly listRecent: (limit: number) => Effect.Effect<ReadonlyArray<StorageRef>, StorageError>;
|
|
558
|
-
/**
|
|
559
|
-
|
|
560
|
-
* sibling ref. */
|
|
561
|
-
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>;
|
|
562
668
|
/** Total bytes + object count for a tenant — LIVE sum over the ref rows
|
|
563
669
|
* (reporting / dashboards). The quota GATE does not read this — it rides
|
|
564
670
|
* the atomic `consumeUsage` counter, which a read-then-compare here could
|
|
@@ -595,7 +701,7 @@ export declare interface RefStore {
|
|
|
595
701
|
readonly setVisibility?: ((id: string, visibility: StorageVisibility) => Effect.Effect<StorageRef | null, StorageError>) | undefined;
|
|
596
702
|
/** How many PUBLIC refs point at this provider key — whether the object must
|
|
597
703
|
* stay publicly readable. */
|
|
598
|
-
readonly
|
|
704
|
+
readonly countPublicByAddress?: ((address: StorageAddress) => Effect.Effect<number, StorageError>) | undefined;
|
|
599
705
|
}
|
|
600
706
|
|
|
601
707
|
/** A region of an image in pixels. */
|
|
@@ -609,6 +715,8 @@ declare interface Region {
|
|
|
609
715
|
/** One derived output a `Transcoder` produces from a source asset. Each becomes
|
|
610
716
|
* a normal storage ref linked back to the original via `derivedFrom`. */
|
|
611
717
|
export declare interface Rendition {
|
|
718
|
+
/** Optional structured producer attestation; unproven outputs keep it absent. */
|
|
719
|
+
readonly derivation?: RenditionDerivation;
|
|
612
720
|
readonly bytes: Uint8Array;
|
|
613
721
|
readonly contentType: string;
|
|
614
722
|
/** Derivative class — e.g. `'rendition'` (a playable variant) or `'poster'`. */
|
|
@@ -617,6 +725,49 @@ export declare interface Rendition {
|
|
|
617
725
|
readonly label?: string;
|
|
618
726
|
}
|
|
619
727
|
|
|
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
|
+
*/
|
|
769
|
+
export declare const requireStorageObjectNamespaces: (store: DataStore) => Promise<void>;
|
|
770
|
+
|
|
620
771
|
/** A `ListRefsInput` after the service normalizes its defaults / clamps — what
|
|
621
772
|
* a `RefStore.listRefs` impl receives. `limit` is already the `+1` probe. */
|
|
622
773
|
export declare interface ResolvedListQuery {
|
|
@@ -632,11 +783,7 @@ export declare interface ResolvedListQuery {
|
|
|
632
783
|
|
|
633
784
|
export declare const resolveStorageProvider: (options: StoragePluginOptions) => StorageProvider;
|
|
634
785
|
|
|
635
|
-
/**
|
|
636
|
-
* The signing secret. A dedicated `VOLTRO_STORAGE_SECRET` is preferred so
|
|
637
|
-
* grant tokens and session cookies can be rotated independently; absent
|
|
638
|
-
* that we fall back to the session secret so it works out of the box.
|
|
639
|
-
*/
|
|
786
|
+
/** The secret new storage tokens are signed with — the first of {@link resolveStorageSecrets}. */
|
|
640
787
|
export declare const resolveStorageSecret: () => string;
|
|
641
788
|
|
|
642
789
|
/** What a resumable ticket authorizes: one chunked upload session, until `exp`. */
|
|
@@ -647,6 +794,63 @@ export declare interface ResumableTicketPayload extends Omit<UploadTicketPayload
|
|
|
647
794
|
readonly size: number;
|
|
648
795
|
}
|
|
649
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
|
+
|
|
650
854
|
export declare const s3Provider: (options: S3ProviderOptions) => StorageProvider;
|
|
651
855
|
|
|
652
856
|
export declare interface S3ProviderOptions {
|
|
@@ -668,8 +872,7 @@ export declare interface S3ProviderOptions {
|
|
|
668
872
|
readonly publicAcl?: boolean;
|
|
669
873
|
}
|
|
670
874
|
|
|
671
|
-
|
|
672
|
-
export declare const setActiveStorageProvider: (provider: StorageProvider | undefined) => void;
|
|
875
|
+
export declare type ScopedStorageObjectIdentity = StorageObjectIdentity & StorageReferenceScope;
|
|
673
876
|
|
|
674
877
|
/** Sign a finalize token valid for `ttlSeconds`. */
|
|
675
878
|
export declare const signFinalizeTicket: (fields: Omit<FinalizeTicketPayload, "exp" | "version">, ttlSeconds: number, secret?: string) => string;
|
|
@@ -694,6 +897,8 @@ export declare const STORAGE_BLOBS_TABLE = "_voltro_storage_blobs";
|
|
|
694
897
|
|
|
695
898
|
export declare const STORAGE_GRANTS_TABLE = "_voltro_storage_grants";
|
|
696
899
|
|
|
900
|
+
export declare const STORAGE_REFERENCE_CATALOGUE_TABLE = "_voltro_storage_reference_catalogue";
|
|
901
|
+
|
|
697
902
|
export declare const STORAGE_REFS_TABLE = "_voltro_storage_refs";
|
|
698
903
|
|
|
699
904
|
export declare const STORAGE_USAGE_TABLE = "_voltro_storage_usage";
|
|
@@ -711,6 +916,88 @@ declare const StorageAccessDenied_base: Schema.Class<StorageAccessDenied, Schema
|
|
|
711
916
|
readonly reason: Schema.String;
|
|
712
917
|
}>, YieldableError>;
|
|
713
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
|
+
|
|
714
1001
|
/**
|
|
715
1002
|
* Where the bytes go, read from the same options and env `resolveProvider`
|
|
716
1003
|
* reads: an object store is a destination outside the installation; the
|
|
@@ -718,20 +1005,7 @@ declare const StorageAccessDenied_base: Schema.Class<StorageAccessDenied, Schema
|
|
|
718
1005
|
*/
|
|
719
1006
|
export declare const storageEgressOf: (options: StoragePluginOptions) => ReadonlyArray<PluginEgressDeclaration>;
|
|
720
1007
|
|
|
721
|
-
|
|
722
|
-
* Storage failure. `transient` drives retry — `true` for 429 / 5xx /
|
|
723
|
-
* network blips, `false` for 4xx / config / not-found. Surfaced typed so
|
|
724
|
-
* handlers can `Effect.catchTag('StorageError', …)`.
|
|
725
|
-
*/
|
|
726
|
-
export declare class StorageError extends StorageError_base {
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
declare const StorageError_base: Schema.Class<StorageError, Schema.TaggedStruct<"StorageError", {
|
|
730
|
-
readonly provider: Schema.String;
|
|
731
|
-
readonly message: Schema.String;
|
|
732
|
-
readonly transient: Schema.Boolean;
|
|
733
|
-
readonly status: Schema.optional<Schema.Number>;
|
|
734
|
-
}>, YieldableError>;
|
|
1008
|
+
export { StorageError }
|
|
735
1009
|
|
|
736
1010
|
/** A persisted, explicit share of one object with one principal. */
|
|
737
1011
|
export declare interface StorageGrant {
|
|
@@ -761,8 +1035,11 @@ export declare type StorageGuard = (ctx: {
|
|
|
761
1035
|
* and `BASE_NAME` is not exported, so a caller minting a ticket outside the
|
|
762
1036
|
* plugin had to guess it. Guessing is exactly what a `string` parameter invites.
|
|
763
1037
|
*
|
|
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 }))
|
|
764
1041
|
* const ticket = signUploadTicket(
|
|
765
|
-
* { instance: storageInstanceName(), key, contentType },
|
|
1042
|
+
* { writeScope, destination, instance: storageInstanceName(options), key, ct: contentType, sub: ownerId, tenant: tenantId, vis: 'private' },
|
|
766
1043
|
* 300,
|
|
767
1044
|
* )
|
|
768
1045
|
*
|
|
@@ -772,16 +1049,24 @@ export declare type StorageGuard = (ctx: {
|
|
|
772
1049
|
*/
|
|
773
1050
|
export declare const storageInstanceName: (options?: StoragePluginOptions) => string;
|
|
774
1051
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
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 {
|
|
779
1059
|
/** Hash of all immutable put inputs, including content and access metadata. */
|
|
780
1060
|
readonly fingerprint: string;
|
|
781
1061
|
/** SHA-256 of the actual normalized provider bytes, separate from metadata. */
|
|
782
1062
|
readonly checksum: string;
|
|
783
1063
|
/** Already tenant-scoped logical provider key. */
|
|
784
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
|
+
};
|
|
785
1070
|
}
|
|
786
1071
|
|
|
787
1072
|
/** Internal persistence substrate. Service wiring must commit quota and refs in
|
|
@@ -791,11 +1076,14 @@ export declare const storageObjectLifecycleTables: ( Table<"_voltro_storage_oper
|
|
|
791
1076
|
readonly nonce: ColumnBuilder<string, "text", boolean>;
|
|
792
1077
|
}>, false, never> | Table<"_voltro_storage_object_heads", FieldDefinitions<{
|
|
793
1078
|
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
1079
|
+
readonly objectNamespace: ColumnBuilder<string | null, "text", boolean>;
|
|
794
1080
|
readonly generation: ColumnBuilder<string, "text", boolean>;
|
|
795
1081
|
readonly key: ColumnBuilder<string, "text", boolean>;
|
|
796
1082
|
readonly reservations: ColumnBuilder<string, "bigint", boolean>;
|
|
797
1083
|
}>, false, never> | Table<"_voltro_storage_operations", FieldDefinitions<{
|
|
798
1084
|
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
1085
|
+
readonly storageInstance: ColumnBuilder<string | null, "text", boolean>;
|
|
1086
|
+
readonly objectNamespace: ColumnBuilder<string | null, "text", boolean>;
|
|
799
1087
|
readonly objectId: ColumnBuilder<string, "text", boolean>;
|
|
800
1088
|
readonly fingerprint: ColumnBuilder<string, "text", boolean>;
|
|
801
1089
|
readonly generation: ColumnBuilder<string, "text", boolean>;
|
|
@@ -809,13 +1097,59 @@ export declare const storageObjectLifecycleTables: ( Table<"_voltro_storage_oper
|
|
|
809
1097
|
readonly claim: ColumnBuilder<string, "text", boolean>;
|
|
810
1098
|
}>, false, never>)[];
|
|
811
1099
|
|
|
1100
|
+
export { StorageObjectLocation }
|
|
1101
|
+
|
|
812
1102
|
export declare type StorageObjectMetadata = ReturnType<typeof makeStorageObjectMetadata>;
|
|
813
1103
|
|
|
1104
|
+
/** Credential-independent identity of a physical object-key namespace.
|
|
1105
|
+
* Equal identities mean an equal key addresses the same provider bytes. */
|
|
1106
|
+
export declare const storageObjectNamespace: (parts: readonly string[]) => string;
|
|
1107
|
+
|
|
1108
|
+
export declare interface StorageObjectNamespaceAssignment extends StorageReferenceScope {
|
|
1109
|
+
readonly refId: string;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
export declare interface StorageObjectNamespaceMigrationResult {
|
|
1113
|
+
readonly assigned: number;
|
|
1114
|
+
readonly pendingDeletes: readonly StorageObjectNamespaceAssignment[];
|
|
1115
|
+
}
|
|
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
|
+
|
|
814
1147
|
export declare const storagePlugin: (options?: StoragePluginOptions) => VoltroPlugin;
|
|
815
1148
|
|
|
816
1149
|
export declare interface StoragePluginOptions {
|
|
817
1150
|
/** `'s3' | 'minio' | 'filesystem' | 'memory'` (built from env) or a
|
|
818
1151
|
* `StorageProvider`. Default: `STORAGE_PROVIDER` env, else `'memory'`. */
|
|
1152
|
+
readonly connection?: ConnectionRef<'storage'>;
|
|
819
1153
|
readonly provider?: StorageProviderName | StorageProvider;
|
|
820
1154
|
/** Bucket name (s3/minio). Default `S3_BUCKET`/`STORAGE_BUCKET` env, else 'voltro'. */
|
|
821
1155
|
readonly bucket?: string;
|
|
@@ -959,103 +1293,16 @@ export declare interface StoragePluginOptions {
|
|
|
959
1293
|
readonly name?: string;
|
|
960
1294
|
}
|
|
961
1295
|
|
|
962
|
-
|
|
963
|
-
* A backend transport. Keyed by an opaque object key (the service owns key
|
|
964
|
-
* derivation + tenant prefixing); knows nothing about refs, tenants, or
|
|
965
|
-
* access policy.
|
|
966
|
-
*/
|
|
967
|
-
export declare interface StorageProvider {
|
|
968
|
-
/**
|
|
969
|
-
* Where a FILESYSTEM provider writes. Absent for every other provider.
|
|
970
|
-
*
|
|
971
|
-
* It exists so a caller can ask a question this interface otherwise cannot
|
|
972
|
-
* answer: does what I write here survive the process? A rollback capture
|
|
973
|
-
* written for a pod that then dies is worthless, and `filesystem` is the one
|
|
974
|
-
* provider that can be either — a mounted volume or an ephemeral container
|
|
975
|
-
* directory. A deployment pointed this out: their check for "storage is
|
|
976
|
-
* configured" passed on a `/tmp` path with no volume behind it.
|
|
977
|
-
*/
|
|
978
|
-
readonly root?: string;
|
|
979
|
-
readonly name: string;
|
|
980
|
-
/** True when `getUrl` returns a real presigned URL (s3/minio). When
|
|
981
|
-
* false the service serves bytes via the `/_voltro/storage/:id`
|
|
982
|
-
* endpoint instead (filesystem/memory). */
|
|
983
|
-
readonly presigns: boolean;
|
|
984
|
-
readonly put: (key: string, bytes: Uint8Array, meta: {
|
|
985
|
-
readonly contentType: string;
|
|
986
|
-
readonly public?: boolean;
|
|
987
|
-
}) => Effect.Effect<ObjectMeta, StorageError>;
|
|
988
|
-
readonly get: (key: string) => Effect.Effect<StoredObject, StorageError>;
|
|
989
|
-
readonly delete: (key: string) => Effect.Effect<void, StorageError>;
|
|
990
|
-
/** Presigned GET (s3/minio) for private reads. */
|
|
991
|
-
readonly getUrl: (key: string, expiresInSec: number) => Effect.Effect<string, StorageError>;
|
|
992
|
-
/** A direct, cacheable URL for a PUBLIC object — virtual-hosted bucket
|
|
993
|
-
* URL or a configured CDN base. `null` when the provider can't serve
|
|
994
|
-
* publicly without the app (filesystem/memory) → the service falls
|
|
995
|
-
* back to the `/_voltro/storage/:id` route. */
|
|
996
|
-
readonly publicUrl?: (key: string) => string | null;
|
|
997
|
-
/** Make an object publicly readable at the provider, or not (s3/minio with
|
|
998
|
-
* per-object ACLs). Absent where the app decides per request (database,
|
|
999
|
-
* filesystem, memory) — there a ref's visibility is the whole answer. */
|
|
1000
|
-
readonly setObjectPublic?: (key: string, isPublic: boolean) => Effect.Effect<void, StorageError>;
|
|
1001
|
-
/** Presigned PUT for direct-to-bucket uploads (s3/minio). Absent on
|
|
1002
|
-
* providers that can't presign uploads. */
|
|
1003
|
-
readonly getUploadUrl?: (key: string, expiresInSec: number, contentType: string) => Effect.Effect<string, StorageError>;
|
|
1004
|
-
readonly createMultipartUpload?: (key: string, contentType: string, opts?: {
|
|
1005
|
-
readonly public?: boolean;
|
|
1006
|
-
}) => Effect.Effect<{
|
|
1007
|
-
readonly uploadId: string;
|
|
1008
|
-
}, StorageError>;
|
|
1009
|
-
readonly presignUploadPart?: (key: string, uploadId: string, partNumber: number, expiresInSec: number) => Effect.Effect<string, StorageError>;
|
|
1010
|
-
readonly completeMultipartUpload?: (key: string, uploadId: string, parts: ReadonlyArray<{
|
|
1011
|
-
readonly partNumber: number;
|
|
1012
|
-
readonly etag: string;
|
|
1013
|
-
}>) => Effect.Effect<{
|
|
1014
|
-
readonly etag?: string;
|
|
1015
|
-
}, StorageError>;
|
|
1016
|
-
readonly abortMultipartUpload?: (key: string, uploadId: string) => Effect.Effect<void, StorageError>;
|
|
1017
|
-
readonly head: (key: string) => Effect.Effect<ObjectMeta | null, StorageError>;
|
|
1018
|
-
/**
|
|
1019
|
-
* Stream an object's bytes in chunks instead of buffering the whole blob
|
|
1020
|
-
* ({@link get}). Present on backends with a real streaming read (filesystem,
|
|
1021
|
-
* s3, azure). OPTIONAL: when a provider omits it, {@link getObjectStream}
|
|
1022
|
-
* transparently falls back to `get` + a chunked in-memory stream — correct
|
|
1023
|
-
* for the small-blob backends (memory / database) that have nothing to
|
|
1024
|
-
* stream from.
|
|
1025
|
-
*/
|
|
1026
|
-
readonly getStream?: (key: string) => Effect.Effect<StoredStream, StorageError>;
|
|
1027
|
-
/**
|
|
1028
|
-
* Consume a {@link ByteStream} and store it via the backend's chunked /
|
|
1029
|
-
* multipart upload, so a large upload never fully materialises in memory.
|
|
1030
|
-
* Present on filesystem (streamed atomic write), s3 (multipart via
|
|
1031
|
-
* `@aws-sdk/lib-storage`), azure (`uploadStream`). OPTIONAL: when absent,
|
|
1032
|
-
* {@link putObjectStream} buffers the stream and calls `put`. `totalSize`,
|
|
1033
|
-
* when the caller knows it (e.g. from an export manifest), lets the backend
|
|
1034
|
-
* report an accurate size without a follow-up HEAD.
|
|
1035
|
-
*/
|
|
1036
|
-
readonly putStream?: (key: string, stream: ByteStream, meta: {
|
|
1037
|
-
readonly contentType: string;
|
|
1038
|
-
readonly public?: boolean;
|
|
1039
|
-
readonly totalSize?: number;
|
|
1040
|
-
}) => Effect.Effect<ObjectMeta, StorageError>;
|
|
1041
|
-
/**
|
|
1042
|
-
* Read a byte range `[start, endInclusive]` (HTTP Range / fd offset). Enables
|
|
1043
|
-
* seekable + resumable reads. OPTIONAL and best-effort: whole-object resume
|
|
1044
|
-
* already works via content-addressing (skip an asset whose hash is present
|
|
1045
|
-
* at the target), so this is an optimisation, not a correctness requirement.
|
|
1046
|
-
*/
|
|
1047
|
-
readonly getRange?: (key: string, start: number, endInclusive: number) => Effect.Effect<Uint8Array, StorageError>;
|
|
1048
|
-
/** Providers that store bytes via the app's DataStore (e.g. `database`)
|
|
1049
|
-
* receive it here once it exists — bound by the plugin at boot. */
|
|
1050
|
-
readonly bindDataStore?: (store: unknown) => void;
|
|
1051
|
-
}
|
|
1296
|
+
export { StorageProvider }
|
|
1052
1297
|
|
|
1053
|
-
export
|
|
1298
|
+
export { StorageProviderName }
|
|
1054
1299
|
|
|
1055
1300
|
export declare const storagePutIntentsTable: Table<"_voltro_storage_put_intents", FieldDefinitions<{
|
|
1056
1301
|
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
1057
1302
|
readonly refId: ColumnBuilder<string, "text", boolean>;
|
|
1058
|
-
readonly
|
|
1303
|
+
readonly storageInstance: ColumnBuilder<string | null, "text", boolean>;
|
|
1304
|
+
readonly objectNamespace: ColumnBuilder<string | null, "text", boolean>;
|
|
1305
|
+
readonly identity: ColumnBuilder<ScopedStorageObjectIdentity, "json", boolean>;
|
|
1059
1306
|
readonly ref: ColumnBuilder<StorageRef, "json", boolean>;
|
|
1060
1307
|
}>, false, never>;
|
|
1061
1308
|
|
|
@@ -1103,8 +1350,38 @@ export declare interface StorageRef {
|
|
|
1103
1350
|
readonly derivedFrom?: string | null;
|
|
1104
1351
|
/** Derivative label — e.g. `'rendition'` / `'poster'`; null on an original. */
|
|
1105
1352
|
readonly kind?: string | null;
|
|
1353
|
+
/** Immutable provenance for an attested transcode; absent on older/unproven refs. */
|
|
1354
|
+
readonly renditionProof?: RenditionProof | null;
|
|
1355
|
+
}
|
|
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
|
+
|
|
1360
|
+
export declare const storageReferenceCatalogueTable: Table<"_voltro_storage_reference_catalogue", FieldDefinitions<{
|
|
1361
|
+
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
1362
|
+
readonly namespace: ColumnBuilder<string, "text", boolean>;
|
|
1363
|
+
}>, false, never>;
|
|
1364
|
+
|
|
1365
|
+
export declare interface StorageReferenceInstanceAssignment {
|
|
1366
|
+
readonly refId: string;
|
|
1367
|
+
readonly storageInstance: string;
|
|
1368
|
+
}
|
|
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
|
+
|
|
1378
|
+
export declare interface StorageReferenceScope {
|
|
1379
|
+
readonly storageInstance: string;
|
|
1380
|
+
readonly objectNamespace: string;
|
|
1106
1381
|
}
|
|
1107
1382
|
|
|
1383
|
+
export declare type StorageReferenceView = StorageReferenceScope | StorageReferenceResolver;
|
|
1384
|
+
|
|
1108
1385
|
/** An upload was rejected by a constraint (size / content-type / magic-byte
|
|
1109
1386
|
* mismatch). `reason` is a stable code; `detail` is human-readable. */
|
|
1110
1387
|
export declare class StorageRejected extends StorageRejected_base {
|
|
@@ -1139,6 +1416,9 @@ export declare interface StorageScanResult {
|
|
|
1139
1416
|
readonly threat?: string;
|
|
1140
1417
|
}
|
|
1141
1418
|
|
|
1419
|
+
/** A secret, or the set a rotation keeps accepting (the signing one first). */
|
|
1420
|
+
declare type StorageSecrets = string | ReadonlyArray<string>;
|
|
1421
|
+
|
|
1142
1422
|
export declare class StorageService extends StorageService_base {
|
|
1143
1423
|
}
|
|
1144
1424
|
|
|
@@ -1151,6 +1431,12 @@ export declare interface StorageServiceOptions {
|
|
|
1151
1431
|
readonly refStore: RefStore;
|
|
1152
1432
|
readonly grantStore: GrantStore;
|
|
1153
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>;
|
|
1438
|
+
/** Canonical plugin instance; separates new plain keys on a shared provider. */
|
|
1439
|
+
readonly storageInstance?: string;
|
|
1154
1440
|
/** Static prefix prepended to every key (e.g. an app/env namespace). */
|
|
1155
1441
|
readonly tenantPrefix?: string;
|
|
1156
1442
|
/** Transient-failure retries (429 / 5xx / network). Default 3. */
|
|
@@ -1203,6 +1489,20 @@ export declare interface StorageServiceOptions {
|
|
|
1203
1489
|
|
|
1204
1490
|
/** The service handlers consume: `const storage = yield* StorageService`. */
|
|
1205
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>;
|
|
1501
|
+
/** Opaque destination binding for manually signed upload-family credentials. */
|
|
1502
|
+
readonly uploadTicketScope: (input?: {
|
|
1503
|
+
readonly tenantId?: string | null;
|
|
1504
|
+
readonly destination?: string;
|
|
1505
|
+
}) => Effect.Effect<string, StorageError>;
|
|
1206
1506
|
/** Store bytes. The result is the ref plus this call's `outcome`. */
|
|
1207
1507
|
readonly put: (input: PutInput) => Effect.Effect<StoredRef, StorageError | StorageRejected | StorageScanRejected>;
|
|
1208
1508
|
/** Fetch an object's bytes by id. Enforces the tenant guard ONLY — it does
|
|
@@ -1373,9 +1673,9 @@ export declare interface StorageServiceShape {
|
|
|
1373
1673
|
readonly contentType: string;
|
|
1374
1674
|
readonly tenantId?: string | null;
|
|
1375
1675
|
readonly expiresInSec?: number;
|
|
1376
|
-
}) => Effect.Effect<{
|
|
1676
|
+
}) => Effect.Effect<StorageAddress & {
|
|
1677
|
+
readonly writeScope: string;
|
|
1377
1678
|
readonly uploadUrl: string;
|
|
1378
|
-
readonly key: string;
|
|
1379
1679
|
readonly expiresInSec: number;
|
|
1380
1680
|
}, StorageError>;
|
|
1381
1681
|
/** Promote a blob the client PUT directly to a TEMP `key` into a real ref:
|
|
@@ -1384,6 +1684,7 @@ export declare interface StorageServiceShape {
|
|
|
1384
1684
|
* scanned + a non-degraded ref — out of band from the direct PUT. On a scan
|
|
1385
1685
|
* reject the temp bytes are deleted (fail-closed, nothing promoted). */
|
|
1386
1686
|
readonly finalizeUpload: (input: {
|
|
1687
|
+
readonly destination: string;
|
|
1387
1688
|
readonly key: string;
|
|
1388
1689
|
readonly contentType: string;
|
|
1389
1690
|
readonly tenantId?: string | null;
|
|
@@ -1398,6 +1699,7 @@ export declare interface StorageServiceShape {
|
|
|
1398
1699
|
/** Store one chunk of a resumable upload as its own durable `_incoming/<id>/
|
|
1399
1700
|
* <index>` object. Idempotent — re-PUTting the same index overwrites it. */
|
|
1400
1701
|
readonly putResumableChunk: (input: {
|
|
1702
|
+
readonly destination: string;
|
|
1401
1703
|
readonly uploadId: string;
|
|
1402
1704
|
readonly index: number;
|
|
1403
1705
|
readonly bytes: Uint8Array;
|
|
@@ -1407,6 +1709,7 @@ export declare interface StorageServiceShape {
|
|
|
1407
1709
|
* 0 and returns the received byte `offset` + the `nextIndex` to send. Lets a
|
|
1408
1710
|
* reconnecting client resume instead of restarting. */
|
|
1409
1711
|
readonly resumableStatus: (input: {
|
|
1712
|
+
readonly destination: string;
|
|
1410
1713
|
readonly uploadId: string;
|
|
1411
1714
|
readonly tenantId?: string | null;
|
|
1412
1715
|
}) => Effect.Effect<{
|
|
@@ -1417,6 +1720,7 @@ export declare interface StorageServiceShape {
|
|
|
1417
1720
|
* concatenate, run the FULL `put()` pipeline, then delete the chunk objects
|
|
1418
1721
|
* (on success AND on reject — fail-closed). */
|
|
1419
1722
|
readonly finalizeResumable: (input: {
|
|
1723
|
+
readonly destination: string;
|
|
1420
1724
|
readonly uploadId: string;
|
|
1421
1725
|
readonly count: number;
|
|
1422
1726
|
readonly contentType: string;
|
|
@@ -1448,12 +1752,14 @@ export declare interface StorageServiceShape {
|
|
|
1448
1752
|
readonly tenantId?: string | null;
|
|
1449
1753
|
readonly visibility?: StorageVisibility;
|
|
1450
1754
|
readonly expiresInSec?: number;
|
|
1451
|
-
}) => Effect.Effect<{
|
|
1755
|
+
}) => Effect.Effect<StorageAddress & {
|
|
1756
|
+
readonly writeScope: string;
|
|
1452
1757
|
readonly uploadId: string;
|
|
1453
|
-
readonly key: string;
|
|
1454
1758
|
}, StorageError>;
|
|
1455
1759
|
/** Presign a PUT for one part (1-based `partNumber`). */
|
|
1456
1760
|
readonly signMultipartPart: (input: {
|
|
1761
|
+
readonly destination: string;
|
|
1762
|
+
readonly tenantId: string | null;
|
|
1457
1763
|
readonly key: string;
|
|
1458
1764
|
readonly uploadId: string;
|
|
1459
1765
|
readonly partNumber: number;
|
|
@@ -1463,6 +1769,7 @@ export declare interface StorageServiceShape {
|
|
|
1463
1769
|
* registered straight from it (size via HEAD, etag as checksum). No fetch-back,
|
|
1464
1770
|
* so NO scan/derivatives — scan multi-GB out of band. */
|
|
1465
1771
|
readonly completeMultipart: (input: {
|
|
1772
|
+
readonly destination: string;
|
|
1466
1773
|
readonly key: string;
|
|
1467
1774
|
readonly uploadId: string;
|
|
1468
1775
|
readonly parts: ReadonlyArray<{
|
|
@@ -1481,20 +1788,36 @@ export declare interface StorageServiceShape {
|
|
|
1481
1788
|
}) => Effect.Effect<StorageRef, StorageError | StorageRejected>;
|
|
1482
1789
|
/** Abort a multipart session (client cancelled) — frees the bucket's parts. */
|
|
1483
1790
|
readonly abortMultipart: (input: {
|
|
1791
|
+
readonly destination: string;
|
|
1792
|
+
readonly tenantId: string | null;
|
|
1484
1793
|
readonly key: string;
|
|
1485
1794
|
readonly uploadId: string;
|
|
1486
1795
|
}) => Effect.Effect<void, StorageError>;
|
|
1487
1796
|
}
|
|
1488
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
|
+
|
|
1489
1816
|
/** `public` = anyone, served direct from bucket/CDN; `private` = gated by
|
|
1490
1817
|
* the ref's access policy + grants. Default for a new put is `private`. */
|
|
1491
1818
|
export declare type StorageVisibility = 'public' | 'private';
|
|
1492
1819
|
|
|
1493
|
-
|
|
1494
|
-
export declare interface StoredObject {
|
|
1495
|
-
readonly bytes: Uint8Array;
|
|
1496
|
-
readonly contentType: string;
|
|
1497
|
-
}
|
|
1820
|
+
export { StoredObject }
|
|
1498
1821
|
|
|
1499
1822
|
/** What `put` returns: the stored ref, plus what this call did to it. The
|
|
1500
1823
|
* `outcome` is a fact about the CALL, not the row — it is never persisted and
|
|
@@ -1503,13 +1826,7 @@ export declare type StoredRef = StorageRef & {
|
|
|
1503
1826
|
readonly outcome: PutOutcome;
|
|
1504
1827
|
};
|
|
1505
1828
|
|
|
1506
|
-
|
|
1507
|
-
* its content type and, when the backend reports it up front, its size. */
|
|
1508
|
-
export declare interface StoredStream {
|
|
1509
|
-
readonly stream: ByteStream;
|
|
1510
|
-
readonly contentType: string;
|
|
1511
|
-
readonly size?: number;
|
|
1512
|
-
}
|
|
1829
|
+
export { StoredStream }
|
|
1513
1830
|
|
|
1514
1831
|
/**
|
|
1515
1832
|
* A ByteStream → Node `Readable`, for SDK uploaders that consume Node streams
|
|
@@ -1531,9 +1848,7 @@ export declare type Transcoder = (input: {
|
|
|
1531
1848
|
readonly ref: StorageRef;
|
|
1532
1849
|
}) => ReadonlyArray<Rendition> | Promise<ReadonlyArray<Rendition>> | Effect.Effect<ReadonlyArray<Rendition>>;
|
|
1533
1850
|
|
|
1534
|
-
|
|
1535
|
-
* requests for the same variant don't re-encode. */
|
|
1536
|
-
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>;
|
|
1537
1852
|
|
|
1538
1853
|
export declare interface Transformed {
|
|
1539
1854
|
readonly bytes: Uint8Array;
|
|
@@ -1587,13 +1902,17 @@ export declare interface UploadLimits {
|
|
|
1587
1902
|
* owner/tenant/content-type/visibility, until `exp`. */
|
|
1588
1903
|
export declare interface UploadTicketPayload {
|
|
1589
1904
|
/** Frozen-policy ticket contract. Previous tickets must be minted again. */
|
|
1590
|
-
readonly version:
|
|
1905
|
+
readonly version: 2;
|
|
1591
1906
|
/** Optional durable write identity, preserved across ticket renewal. */
|
|
1592
1907
|
readonly operationId?: string;
|
|
1593
|
-
/**
|
|
1594
|
-
readonly
|
|
1908
|
+
/** Exact reference catalogue and physical byte destination authorized by the issuer. */
|
|
1909
|
+
readonly writeScope: string;
|
|
1910
|
+
/** Optional signed routing hint for the binary relay; destination authorization still uses writeScope. */
|
|
1911
|
+
readonly issuerReplicaId?: string;
|
|
1595
1912
|
/** Exact storage plugin instance authorized to accept the bytes. */
|
|
1596
1913
|
readonly instance: string;
|
|
1914
|
+
/** Logical destination selected before issuing the upload/session. */
|
|
1915
|
+
readonly destination: string;
|
|
1597
1916
|
/** ownerId (subject id) the stored object is attributed to. */
|
|
1598
1917
|
readonly sub: string | null;
|
|
1599
1918
|
/** tenantId that scopes the key prefix + ref row. */
|
|
@@ -1624,28 +1943,28 @@ export declare interface UsageDelta {
|
|
|
1624
1943
|
|
|
1625
1944
|
/** Verify a finalize token. Returns the payload on success, null on any failure
|
|
1626
1945
|
* (malformed, bad signature, expired, missing temp key). Never throws. */
|
|
1627
|
-
export declare const verifyFinalizeTicket: (token: string, secret?:
|
|
1946
|
+
export declare const verifyFinalizeTicket: (token: string, secret?: StorageSecrets) => FinalizeTicketPayload | null;
|
|
1628
1947
|
|
|
1629
1948
|
/**
|
|
1630
1949
|
* Verify a grant token. Returns the payload on success, null on any
|
|
1631
1950
|
* failure (malformed, bad signature, expired). Never throws.
|
|
1632
1951
|
*/
|
|
1633
|
-
export declare const verifyGrant: (token: string, secret?:
|
|
1952
|
+
export declare const verifyGrant: (token: string, secret?: StorageSecrets) => GrantTokenPayload | null;
|
|
1634
1953
|
|
|
1635
1954
|
/** Verify a multipart ticket. Returns the payload on success, null on any
|
|
1636
1955
|
* failure (malformed, bad signature, expired, missing key/uploadId). */
|
|
1637
|
-
export declare const verifyMultipartTicket: (token: string, secret?:
|
|
1956
|
+
export declare const verifyMultipartTicket: (token: string, secret?: StorageSecrets) => MultipartTicketPayload | null;
|
|
1638
1957
|
|
|
1639
1958
|
/** Constant-time check of a plaintext password against a stored hash. */
|
|
1640
1959
|
export declare const verifyPassword: (password: string | undefined, stored: string | null) => boolean;
|
|
1641
1960
|
|
|
1642
1961
|
/** Verify a resumable ticket. Returns the payload on success, null on any
|
|
1643
1962
|
* failure (malformed, bad signature, expired, missing id/size). Never throws. */
|
|
1644
|
-
export declare const verifyResumableTicket: (token: string, secret?:
|
|
1963
|
+
export declare const verifyResumableTicket: (token: string, secret?: StorageSecrets) => ResumableTicketPayload | null;
|
|
1645
1964
|
|
|
1646
1965
|
/** Verify an upload ticket. Returns the payload on success, null on any
|
|
1647
1966
|
* failure (malformed, bad signature, expired). Never throws. */
|
|
1648
|
-
export declare const verifyUploadTicket: (token: string, secret?:
|
|
1967
|
+
export declare const verifyUploadTicket: (token: string, secret?: StorageSecrets) => UploadTicketPayload | null;
|
|
1649
1968
|
|
|
1650
1969
|
/**
|
|
1651
1970
|
* App-supplied media probe for video/audio uploads. The core deliberately does
|
|
@@ -1690,4 +2009,7 @@ export declare const _voltroStorageUsageTable: TableLike;
|
|
|
1690
2009
|
*/
|
|
1691
2010
|
export declare const withStorage: () => ReturnType<typeof mixin>;
|
|
1692
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
|
+
|
|
1693
2015
|
export { }
|