@voltro/plugin-storage 0.83.1 → 0.85.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 +1191 -0
- package/THIRD-PARTY-NOTICES.md +90 -336
- package/dist/index.d.ts +85 -59
- package/dist/index.js +1132 -925
- package/dist/rpc.d.ts +210 -166
- package/dist/rpc.js +60 -39
- package/dist/types.d.ts +27 -45
- package/dist/types.js +5 -1
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -9,11 +9,14 @@ import { mixin } from '@voltro/database';
|
|
|
9
9
|
import { PluginEgressDeclaration } from '@voltro/protocol';
|
|
10
10
|
import { Readable } from 'node:stream';
|
|
11
11
|
import { Schema } from 'effect';
|
|
12
|
+
import { StorageAccessPolicy } from '@voltro/protocol';
|
|
13
|
+
import { StorageAccessRule } from '@voltro/protocol';
|
|
12
14
|
import { Stream } from 'effect';
|
|
13
15
|
import { Subject } from '@voltro/protocol';
|
|
14
16
|
import { Table } from '@voltro/database';
|
|
15
17
|
import { TableLike } from '@voltro/database';
|
|
16
18
|
import { VoltroPlugin } from '@voltro/protocol';
|
|
19
|
+
import { YieldableError } from 'effect/Cause';
|
|
17
20
|
|
|
18
21
|
export declare interface AccessOptions {
|
|
19
22
|
/** Resolve a subject's group ids. Default: `subject.metadata.groups`. */
|
|
@@ -22,7 +25,7 @@ export declare interface AccessOptions {
|
|
|
22
25
|
readonly guards?: Record<string, StorageGuard>;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
export declare type AccessPolicy =
|
|
28
|
+
export declare type AccessPolicy = StorageAccessPolicy;
|
|
26
29
|
|
|
27
30
|
/**
|
|
28
31
|
* One access rule. A rule GRANTS when EVERY present condition is satisfied
|
|
@@ -30,24 +33,7 @@ export declare type AccessPolicy = ReadonlyArray<AccessRule>;
|
|
|
30
33
|
* grants (OR). An empty policy on a private object means owner-only (the
|
|
31
34
|
* implicit owner check always applies).
|
|
32
35
|
*/
|
|
33
|
-
export declare
|
|
34
|
-
/** `subject.id === ref.ownerId`. */
|
|
35
|
-
readonly owner?: boolean;
|
|
36
|
-
/** `subject.metadata.roles` intersects these. */
|
|
37
|
-
readonly roles?: ReadonlyArray<string>;
|
|
38
|
-
/** resolved groups (default `subject.metadata.groups`) intersect these. */
|
|
39
|
-
readonly groups?: ReadonlyArray<string>;
|
|
40
|
-
/** `subject.scopes` intersects these. */
|
|
41
|
-
readonly scopes?: ReadonlyArray<string>;
|
|
42
|
-
/** `subject.tenantId === ref.tenantId`. */
|
|
43
|
-
readonly tenant?: boolean;
|
|
44
|
-
/** subject is any authenticated api-key. */
|
|
45
|
-
readonly apiKey?: boolean;
|
|
46
|
-
/** a correct password was supplied (checked at mint, against passwordHash). */
|
|
47
|
-
readonly password?: boolean;
|
|
48
|
-
/** a named custom guard (`options.guards[name]`) returns true. */
|
|
49
|
-
readonly guard?: string;
|
|
50
|
-
}
|
|
36
|
+
export declare type AccessRule = StorageAccessRule;
|
|
51
37
|
|
|
52
38
|
/**
|
|
53
39
|
* The provider the APP configured, falling back to the env-derived default when no
|
|
@@ -193,6 +179,12 @@ export declare const decodeDataUri: (dataUri: string) => {
|
|
|
193
179
|
*/
|
|
194
180
|
export declare const durabilityNotice: (path: string) => string | undefined;
|
|
195
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Apply a creative edit; null when the input is not an image, `sharp` is not
|
|
184
|
+
* installed, the edit is empty or fails. The format stays the input's.
|
|
185
|
+
*/
|
|
186
|
+
export declare const editImage: (bytes: Uint8Array, contentType: string, edit: ImageEdit) => Promise<Transformed | null>;
|
|
187
|
+
|
|
196
188
|
/** Frame bytes for clamd `INSTREAM`: `zINSTREAM\0` then `<u32 len><data>`
|
|
197
189
|
* chunks, terminated by a zero-length chunk. Exposed for testing. */
|
|
198
190
|
export declare const encodeInstream: (bytes: Uint8Array, chunkSize?: number) => Buffer;
|
|
@@ -286,6 +278,19 @@ export declare interface GrantTokenPayload {
|
|
|
286
278
|
/** Hash a file password as `salt:scryptHash` (hex). */
|
|
287
279
|
export declare const hashPassword: (password: string) => string;
|
|
288
280
|
|
|
281
|
+
/** A creative edit: the result is new bytes, stored as a new version — unlike a delivery transform. */
|
|
282
|
+
export declare interface ImageEdit {
|
|
283
|
+
/** Clockwise, in degrees. */
|
|
284
|
+
readonly rotate?: 90 | 180 | 270;
|
|
285
|
+
/** Mirror top to bottom. */
|
|
286
|
+
readonly flip?: boolean;
|
|
287
|
+
/** Mirror left to right. */
|
|
288
|
+
readonly flop?: boolean;
|
|
289
|
+
readonly grayscale?: boolean;
|
|
290
|
+
/** Cut this region out, in pixels of the original. */
|
|
291
|
+
readonly crop?: Region;
|
|
292
|
+
}
|
|
293
|
+
|
|
289
294
|
/** Where `ingestUrl` may fetch from — see `ssrfReason` in `@voltro/runtime`. */
|
|
290
295
|
export declare interface IngestPolicy {
|
|
291
296
|
/** Hosts (or `host:port`, or `*.suffix`) reachable although internal — a
|
|
@@ -339,9 +344,9 @@ export declare const makeStorageObjectMetadata: (store: DataStore) => {
|
|
|
339
344
|
identity: {
|
|
340
345
|
readonly tenantId: string | null;
|
|
341
346
|
readonly bucket: string;
|
|
347
|
+
readonly operationId: string;
|
|
342
348
|
readonly fingerprint: string;
|
|
343
349
|
readonly checksum: string;
|
|
344
|
-
readonly operationId: string;
|
|
345
350
|
readonly logicalKey: string;
|
|
346
351
|
};
|
|
347
352
|
ref: StorageRef;
|
|
@@ -363,30 +368,30 @@ export declare const makeStorageObjectMetadata: (store: DataStore) => {
|
|
|
363
368
|
identity: {
|
|
364
369
|
readonly tenantId: string | null;
|
|
365
370
|
readonly bucket: string;
|
|
371
|
+
readonly operationId: string;
|
|
366
372
|
readonly fingerprint: string;
|
|
367
373
|
readonly checksum: string;
|
|
368
|
-
readonly operationId: string;
|
|
369
374
|
readonly logicalKey: string;
|
|
370
375
|
};
|
|
371
376
|
operation?: never;
|
|
372
377
|
} | {
|
|
373
378
|
released: true;
|
|
374
379
|
operation: {
|
|
375
|
-
readonly key: string;
|
|
376
380
|
readonly id: string;
|
|
381
|
+
readonly objectId: string;
|
|
377
382
|
readonly fingerprint: string;
|
|
378
383
|
readonly generation: string;
|
|
379
|
-
readonly
|
|
384
|
+
readonly key: string;
|
|
380
385
|
readonly refId: string;
|
|
381
|
-
readonly
|
|
386
|
+
readonly state: "ready" | "reserved" | "deleted" | "deleting";
|
|
382
387
|
readonly deleteKey: string | null;
|
|
383
388
|
};
|
|
384
389
|
identity: {
|
|
385
390
|
readonly tenantId: string | null;
|
|
386
391
|
readonly bucket: string;
|
|
392
|
+
readonly operationId: string;
|
|
387
393
|
readonly fingerprint: string;
|
|
388
394
|
readonly checksum: string;
|
|
389
|
-
readonly operationId: string;
|
|
390
395
|
readonly logicalKey: string;
|
|
391
396
|
};
|
|
392
397
|
}>;
|
|
@@ -593,6 +598,14 @@ export declare interface RefStore {
|
|
|
593
598
|
readonly countPublicByKey?: ((bucket: string, key: string) => Effect.Effect<number, StorageError>) | undefined;
|
|
594
599
|
}
|
|
595
600
|
|
|
601
|
+
/** A region of an image in pixels. */
|
|
602
|
+
declare interface Region {
|
|
603
|
+
readonly left: number;
|
|
604
|
+
readonly top: number;
|
|
605
|
+
readonly width: number;
|
|
606
|
+
readonly height: number;
|
|
607
|
+
}
|
|
608
|
+
|
|
596
609
|
/** One derived output a `Transcoder` produces from a source asset. Each becomes
|
|
597
610
|
* a normal storage ref linked back to the original via `derivedFrom`. */
|
|
598
611
|
export declare interface Rendition {
|
|
@@ -659,19 +672,19 @@ export declare interface S3ProviderOptions {
|
|
|
659
672
|
export declare const setActiveStorageProvider: (provider: StorageProvider | undefined) => void;
|
|
660
673
|
|
|
661
674
|
/** Sign a finalize token valid for `ttlSeconds`. */
|
|
662
|
-
export declare const signFinalizeTicket: (fields: Omit<FinalizeTicketPayload, "exp">, ttlSeconds: number, secret?: string) => string;
|
|
675
|
+
export declare const signFinalizeTicket: (fields: Omit<FinalizeTicketPayload, "exp" | "version">, ttlSeconds: number, secret?: string) => string;
|
|
663
676
|
|
|
664
677
|
/** Mint a token granting read access to `refId` for `ttlSeconds`. */
|
|
665
678
|
export declare const signGrant: (refId: string, ttlSeconds: number, secret?: string, audience?: string) => string;
|
|
666
679
|
|
|
667
680
|
/** Sign a multipart ticket valid for `ttlSeconds`. */
|
|
668
|
-
export declare const signMultipartTicket: (fields: Omit<MultipartTicketPayload, "exp">, ttlSeconds: number, secret?: string) => string;
|
|
681
|
+
export declare const signMultipartTicket: (fields: Omit<MultipartTicketPayload, "exp" | "version">, ttlSeconds: number, secret?: string) => string;
|
|
669
682
|
|
|
670
683
|
/** Sign a resumable ticket valid for `ttlSeconds`. */
|
|
671
|
-
export declare const signResumableTicket: (fields: Omit<ResumableTicketPayload, "exp">, ttlSeconds: number, secret?: string) => string;
|
|
684
|
+
export declare const signResumableTicket: (fields: Omit<ResumableTicketPayload, "exp" | "version">, ttlSeconds: number, secret?: string) => string;
|
|
672
685
|
|
|
673
686
|
/** Sign an upload ticket valid for `ttlSeconds`. */
|
|
674
|
-
export declare const signUploadTicket: (fields: Omit<UploadTicketPayload, "exp">, ttlSeconds: number, secret?: string) => string;
|
|
687
|
+
export declare const signUploadTicket: (fields: Omit<UploadTicketPayload, "exp" | "version">, ttlSeconds: number, secret?: string) => string;
|
|
675
688
|
|
|
676
689
|
/** True if the bytes match the declared content type's magic number, OR we
|
|
677
690
|
* have no signature for that type (can't verify → don't block). */
|
|
@@ -693,12 +706,10 @@ export declare const STORAGE_USAGE_TABLE = "_voltro_storage_usage";
|
|
|
693
706
|
export declare class StorageAccessDenied extends StorageAccessDenied_base {
|
|
694
707
|
}
|
|
695
708
|
|
|
696
|
-
declare const StorageAccessDenied_base: Schema.
|
|
697
|
-
readonly
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
reason: typeof Schema.String;
|
|
701
|
-
}>;
|
|
709
|
+
declare const StorageAccessDenied_base: Schema.Class<StorageAccessDenied, Schema.TaggedStruct<"StorageAccessDenied", {
|
|
710
|
+
readonly refId: Schema.String;
|
|
711
|
+
readonly reason: Schema.String;
|
|
712
|
+
}>, YieldableError>;
|
|
702
713
|
|
|
703
714
|
/**
|
|
704
715
|
* Where the bytes go, read from the same options and env `resolveProvider`
|
|
@@ -715,14 +726,12 @@ export declare const storageEgressOf: (options: StoragePluginOptions) => Readonl
|
|
|
715
726
|
export declare class StorageError extends StorageError_base {
|
|
716
727
|
}
|
|
717
728
|
|
|
718
|
-
declare const StorageError_base: Schema.
|
|
719
|
-
readonly
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
status: Schema.optional<typeof Schema.Number>;
|
|
725
|
-
}>;
|
|
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>;
|
|
726
735
|
|
|
727
736
|
/** A persisted, explicit share of one object with one principal. */
|
|
728
737
|
export declare interface StorageGrant {
|
|
@@ -784,7 +793,7 @@ export declare const storageObjectLifecycleTables: ( Table<"_voltro_storage_oper
|
|
|
784
793
|
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
785
794
|
readonly generation: ColumnBuilder<string, "text", boolean>;
|
|
786
795
|
readonly key: ColumnBuilder<string, "text", boolean>;
|
|
787
|
-
readonly reservations: ColumnBuilder<
|
|
796
|
+
readonly reservations: ColumnBuilder<string, "bigint", boolean>;
|
|
788
797
|
}>, false, never> | Table<"_voltro_storage_operations", FieldDefinitions<{
|
|
789
798
|
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
790
799
|
readonly objectId: ColumnBuilder<string, "text", boolean>;
|
|
@@ -866,12 +875,25 @@ export declare interface StoragePluginOptions {
|
|
|
866
875
|
/** Access engine config — a group resolver + named custom guards. */
|
|
867
876
|
readonly access?: AccessOptions;
|
|
868
877
|
/**
|
|
869
|
-
* The
|
|
870
|
-
*
|
|
878
|
+
* The default policy for PRIVATE client uploads, or an Effect function
|
|
879
|
+
* authorizing self-service upload visibility and requested policies before the server signs a ticket. Without
|
|
871
880
|
* it only the uploader (the implicit owner rule) can read a private upload;
|
|
872
881
|
* `[{ tenant: true }]` lets everyone in the uploader's tenant read it.
|
|
873
882
|
*/
|
|
874
|
-
readonly uploadAccess?: AccessPolicy
|
|
883
|
+
readonly uploadAccess?: AccessPolicy | ((request: {
|
|
884
|
+
readonly subject: Subject;
|
|
885
|
+
readonly requested: AccessPolicy | undefined;
|
|
886
|
+
readonly visibility: 'public' | 'private';
|
|
887
|
+
readonly contentType: string;
|
|
888
|
+
}) => Effect.Effect<AccessPolicy, StorageError>);
|
|
889
|
+
/**
|
|
890
|
+
* How long a browser or shared cache may keep a PUBLIC object the serve
|
|
891
|
+
* route delivers itself (and each transform of it). Default: a year,
|
|
892
|
+
* `immutable`. An object can turn private later; a copy cached before then
|
|
893
|
+
* keeps opening until this runs out — set it to bound that window (the
|
|
894
|
+
* bucket's own caching, behind a direct URL, is the provider's).
|
|
895
|
+
*/
|
|
896
|
+
readonly publicCacheSeconds?: number;
|
|
875
897
|
/** Upload constraints — size cap, content-type allow-list, magic-byte sniff. */
|
|
876
898
|
readonly limits?: UploadLimits;
|
|
877
899
|
/**
|
|
@@ -1086,15 +1108,14 @@ export declare interface StorageRef {
|
|
|
1086
1108
|
/** An upload was rejected by a constraint (size / content-type / magic-byte
|
|
1087
1109
|
* mismatch). `reason` is a stable code; `detail` is human-readable. */
|
|
1088
1110
|
export declare class StorageRejected extends StorageRejected_base {
|
|
1111
|
+
get message(): string;
|
|
1089
1112
|
}
|
|
1090
1113
|
|
|
1091
|
-
declare const StorageRejected_base: Schema.
|
|
1092
|
-
readonly _tag: Schema.tag<"StorageRejected">;
|
|
1093
|
-
} & {
|
|
1114
|
+
declare const StorageRejected_base: Schema.Class<StorageRejected, Schema.TaggedStruct<"StorageRejected", {
|
|
1094
1115
|
/** `'too-large' | 'content-type-not-allowed' | 'content-mismatch'` */
|
|
1095
|
-
reason:
|
|
1096
|
-
detail:
|
|
1097
|
-
}>;
|
|
1116
|
+
readonly reason: Schema.String;
|
|
1117
|
+
readonly detail: Schema.String;
|
|
1118
|
+
}>, YieldableError>;
|
|
1098
1119
|
|
|
1099
1120
|
/** Scans bytes before they're stored. Return `{ clean:false, threat }` to
|
|
1100
1121
|
* reject the upload (fails with `StorageScanRejected`, nothing is stored). */
|
|
@@ -1108,11 +1129,9 @@ export declare type StorageScanner = (input: {
|
|
|
1108
1129
|
export declare class StorageScanRejected extends StorageScanRejected_base {
|
|
1109
1130
|
}
|
|
1110
1131
|
|
|
1111
|
-
declare const StorageScanRejected_base: Schema.
|
|
1112
|
-
readonly
|
|
1113
|
-
}
|
|
1114
|
-
threat: typeof Schema.String;
|
|
1115
|
-
}>;
|
|
1132
|
+
declare const StorageScanRejected_base: Schema.Class<StorageScanRejected, Schema.TaggedStruct<"StorageScanRejected", {
|
|
1133
|
+
readonly threat: Schema.String;
|
|
1134
|
+
}>, YieldableError>;
|
|
1116
1135
|
|
|
1117
1136
|
export declare interface StorageScanResult {
|
|
1118
1137
|
readonly clean: boolean;
|
|
@@ -1123,7 +1142,7 @@ export declare interface StorageScanResult {
|
|
|
1123
1142
|
export declare class StorageService extends StorageService_base {
|
|
1124
1143
|
}
|
|
1125
1144
|
|
|
1126
|
-
declare const StorageService_base: Context.
|
|
1145
|
+
declare const StorageService_base: Context.ServiceClass<StorageService, "@voltro/plugin-storage/StorageService", StorageServiceShape>;
|
|
1127
1146
|
|
|
1128
1147
|
export declare const storageServiceLayer: (options: StorageServiceOptions) => Layer.Layer<StorageService>;
|
|
1129
1148
|
|
|
@@ -1370,6 +1389,7 @@ export declare interface StorageServiceShape {
|
|
|
1370
1389
|
readonly tenantId?: string | null;
|
|
1371
1390
|
readonly ownerId?: string | null;
|
|
1372
1391
|
readonly visibility?: StorageVisibility;
|
|
1392
|
+
readonly access?: AccessPolicy;
|
|
1373
1393
|
readonly folder?: string;
|
|
1374
1394
|
readonly tags?: ReadonlyArray<string>;
|
|
1375
1395
|
readonly alt?: string;
|
|
@@ -1403,6 +1423,7 @@ export declare interface StorageServiceShape {
|
|
|
1403
1423
|
readonly tenantId?: string | null;
|
|
1404
1424
|
readonly ownerId?: string | null;
|
|
1405
1425
|
readonly visibility?: StorageVisibility;
|
|
1426
|
+
readonly access?: AccessPolicy;
|
|
1406
1427
|
readonly folder?: string;
|
|
1407
1428
|
readonly tags?: ReadonlyArray<string>;
|
|
1408
1429
|
readonly alt?: string;
|
|
@@ -1452,6 +1473,7 @@ export declare interface StorageServiceShape {
|
|
|
1452
1473
|
readonly tenantId?: string | null;
|
|
1453
1474
|
readonly ownerId?: string | null;
|
|
1454
1475
|
readonly visibility?: StorageVisibility;
|
|
1476
|
+
readonly access?: AccessPolicy;
|
|
1455
1477
|
readonly folder?: string;
|
|
1456
1478
|
readonly tags?: ReadonlyArray<string>;
|
|
1457
1479
|
readonly alt?: string;
|
|
@@ -1564,6 +1586,8 @@ export declare interface UploadLimits {
|
|
|
1564
1586
|
/** What an upload ticket authorizes: a single through-app upload bound to an
|
|
1565
1587
|
* owner/tenant/content-type/visibility, until `exp`. */
|
|
1566
1588
|
export declare interface UploadTicketPayload {
|
|
1589
|
+
/** Frozen-policy ticket contract. Previous tickets must be minted again. */
|
|
1590
|
+
readonly version: 1;
|
|
1567
1591
|
/** Optional durable write identity, preserved across ticket renewal. */
|
|
1568
1592
|
readonly operationId?: string;
|
|
1569
1593
|
/** Inspect uploads may be pinned to their issuing process. */
|
|
@@ -1577,6 +1601,8 @@ export declare interface UploadTicketPayload {
|
|
|
1577
1601
|
/** Authorized content-type — the stored object uses this. */
|
|
1578
1602
|
readonly ct: string;
|
|
1579
1603
|
readonly vis: 'public' | 'private';
|
|
1604
|
+
/** Server-authorized policy, frozen into the signed ticket. */
|
|
1605
|
+
readonly access?: AccessPolicy;
|
|
1580
1606
|
/** Optional fixed logical key (else content-addressed). */
|
|
1581
1607
|
readonly key?: string;
|
|
1582
1608
|
/** Max bytes the route will accept for this ticket (0/undefined = no cap). */
|