@nestm/storage 0.1.0-alpha.4 → 0.1.0-alpha.5

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +114 -0
  3. package/dist/artifacts/artifact-storage.d.ts +161 -0
  4. package/dist/artifacts/artifact-storage.d.ts.map +1 -0
  5. package/dist/artifacts/artifact-storage.js +452 -0
  6. package/dist/artifacts/artifact-storage.js.map +1 -0
  7. package/dist/artifacts/crypto/codec.d.ts +44 -0
  8. package/dist/artifacts/crypto/codec.d.ts.map +1 -0
  9. package/dist/artifacts/crypto/codec.js +273 -0
  10. package/dist/artifacts/crypto/codec.js.map +1 -0
  11. package/dist/artifacts/crypto/context.d.ts +48 -0
  12. package/dist/artifacts/crypto/context.d.ts.map +1 -0
  13. package/dist/artifacts/crypto/context.js +37 -0
  14. package/dist/artifacts/crypto/context.js.map +1 -0
  15. package/dist/artifacts/crypto/dek-cache.d.ts +38 -0
  16. package/dist/artifacts/crypto/dek-cache.d.ts.map +1 -0
  17. package/dist/artifacts/crypto/dek-cache.js +137 -0
  18. package/dist/artifacts/crypto/dek-cache.js.map +1 -0
  19. package/dist/artifacts/crypto/index.d.ts +25 -0
  20. package/dist/artifacts/crypto/index.d.ts.map +1 -0
  21. package/dist/artifacts/crypto/index.js +29 -0
  22. package/dist/artifacts/crypto/index.js.map +1 -0
  23. package/dist/artifacts/crypto/key-provider.d.ts +44 -0
  24. package/dist/artifacts/crypto/key-provider.d.ts.map +1 -0
  25. package/dist/artifacts/crypto/key-provider.js +36 -0
  26. package/dist/artifacts/crypto/key-provider.js.map +1 -0
  27. package/dist/artifacts/crypto/kms-provider.d.ts +16 -0
  28. package/dist/artifacts/crypto/kms-provider.d.ts.map +1 -0
  29. package/dist/artifacts/crypto/kms-provider.js +90 -0
  30. package/dist/artifacts/crypto/kms-provider.js.map +1 -0
  31. package/dist/artifacts/crypto/local-provider.d.ts +17 -0
  32. package/dist/artifacts/crypto/local-provider.d.ts.map +1 -0
  33. package/dist/artifacts/crypto/local-provider.js +58 -0
  34. package/dist/artifacts/crypto/local-provider.js.map +1 -0
  35. package/dist/artifacts/env-config.d.ts +15 -0
  36. package/dist/artifacts/env-config.d.ts.map +1 -0
  37. package/dist/artifacts/env-config.js +95 -0
  38. package/dist/artifacts/env-config.js.map +1 -0
  39. package/dist/artifacts/index.d.ts +6 -0
  40. package/dist/artifacts/index.d.ts.map +1 -0
  41. package/dist/artifacts/index.js +6 -0
  42. package/dist/artifacts/index.js.map +1 -0
  43. package/dist/artifacts/nest/index.d.ts +29 -0
  44. package/dist/artifacts/nest/index.d.ts.map +1 -0
  45. package/dist/artifacts/nest/index.js +129 -0
  46. package/dist/artifacts/nest/index.js.map +1 -0
  47. package/dist/artifacts/object-store.d.ts +27 -0
  48. package/dist/artifacts/object-store.d.ts.map +1 -0
  49. package/dist/artifacts/object-store.js +198 -0
  50. package/dist/artifacts/object-store.js.map +1 -0
  51. package/dist/artifacts/storage-driver.d.ts +48 -0
  52. package/dist/artifacts/storage-driver.d.ts.map +1 -0
  53. package/dist/artifacts/storage-driver.js +89 -0
  54. package/dist/artifacts/storage-driver.js.map +1 -0
  55. package/package.json +17 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @nestm/storage
2
2
 
3
+ ## 0.1.0-alpha.5
4
+
5
+ ### Minor Changes
6
+
7
+ - 227df5b: Add byte-compatible encrypted artifact storage through the
8
+ `@nestm/storage/artifacts` and `@nestm/storage/artifacts/nest` entry points.
9
+
10
+ The framework-neutral facade stores self-contained CAE1 AES-256-GCM envelopes,
11
+ binds ciphertext to its tenant, artifact, version, and path context, supports
12
+ local and AWS KMS key providers, and preserves authenticated content types,
13
+ bounded reads, versioned bundles, legacy migration reads, and encrypted generic
14
+ objects. The Nest entry point composes artifact and object adapters over two
15
+ named storage clients and clears cached data keys on shutdown.
16
+
17
+ The public protocol keeps the deployed filesystem and object-provider layouts,
18
+ reserves configurable ObjectStore namespaces from artifact ids, validates all
19
+ artifact/version paths, and bounds ZIP entry count and expansion before any
20
+ write. CAE1 now rejects unauthenticated empty content types and writer-side
21
+ oversized headers, KMS verifies the stored key id, DEK cache lifetimes are
22
+ capped at five minutes, filesystem `.ct` collisions are rejected, and sweepers
23
+ skip objects without trustworthy timestamps.
24
+
3
25
  ## 0.1.0-alpha.4
4
26
 
5
27
  ### Minor Changes
package/README.md CHANGED
@@ -43,6 +43,9 @@ Install only the native SDKs required by the chosen provider. For example:
43
43
  pnpm add @aws-sdk/client-s3 @aws-sdk/s3-presigned-post \
44
44
  @aws-sdk/s3-request-presigner @aws-sdk/lib-storage
45
45
 
46
+ # Encrypted artifact storage with AWS KMS
47
+ pnpm add @aws-sdk/client-kms
48
+
46
49
  # Google Cloud Storage
47
50
  pnpm add @google-cloud/storage google-auth-library
48
51
 
@@ -88,6 +91,117 @@ storage errors and operation types, and `StorageUploadControl`. It has no NestJS
88
91
  runtime or declaration imports. Provider adapters remain available through
89
92
  `@nestm/storage/files-sdk`.
90
93
 
94
+ ## Encrypted artifact storage
95
+
96
+ The optional `@nestm/storage/artifacts` entry point adds a framework-neutral
97
+ artifact facade over the same provider drivers. Every write is a self-contained
98
+ CAE1 AES-256-GCM envelope; plaintext mode does not exist. The authenticated
99
+ context binds each object to its tenant scope, artifact id, version, path, and
100
+ content type so moving ciphertext to another address fails closed.
101
+
102
+ Install `@aws-sdk/client-kms` in every artifact-storage consumer. It is an
103
+ optional peer so core-only applications do not download AWS KMS, while artifact
104
+ applications can choose either the local key provider or KMS at runtime.
105
+
106
+ Set `ARTIFACT_KEY_PROVIDER=local` with a base64-encoded 32-byte `ARTIFACT_KEK`
107
+ (`ARTIFACT_KEK_NAME` is optional), or set `ARTIFACT_KEY_PROVIDER=kms` with
108
+ `ARTIFACT_KMS_KEY_ID` (`ARTIFACT_KMS_REGION` is optional). Invalid or missing
109
+ key configuration aborts startup. `ARTIFACT_ENCRYPTION_READ_LEGACY=true` is a
110
+ temporary, explicit plaintext-read migration flag and never enables plaintext
111
+ writes.
112
+
113
+ ```ts
114
+ import {
115
+ artifactScope,
116
+ artifactStorageConfigFromEnv,
117
+ createArtifactStorage,
118
+ storageCryptoFromEnv,
119
+ } from '@nestm/storage/artifacts';
120
+
121
+ const storage = await createArtifactStorage(
122
+ artifactStorageConfigFromEnv(process.env),
123
+ storageCryptoFromEnv(process.env),
124
+ );
125
+
126
+ const ref = artifactScope({
127
+ organizationId: 'org-1',
128
+ ownerUserId: 'user-1',
129
+ });
130
+
131
+ await storage.writeHtml('artifact-1', Buffer.from('<h1>Encrypted</h1>'), {
132
+ scope: ref,
133
+ });
134
+
135
+ const html = await storage.read('artifact-1', 'index.html', {
136
+ scope: ref,
137
+ });
138
+ ```
139
+
140
+ `writeBundle()` expands a zip into separately authenticated objects, skips
141
+ traversal and reserved-namespace entries, and rejects case-folded duplicate
142
+ paths, more than 1,000 entries, entries larger than 64 MiB, or more than 256 MiB
143
+ total expanded data. Callers may lower those limits per write. `read()` and
144
+ `readWithInfo()` support directory-to-`index.html` resolution, optional
145
+ plaintext-size limits, and version-bound paths.
146
+
147
+ `ObjectStore` exposes the same encryption guarantees for non-artifact objects
148
+ such as upload staging and organization media. Keys must begin with a configured
149
+ top-level namespace; the defaults are `_staging` and `org-logos`. Those names
150
+ are reserved as artifact ids, case-insensitively, so artifact and object
151
+ operations cannot address one another even when an object-store provider uses a
152
+ shared bucket root. Override the top-level
153
+ `ArtifactStorageConfig.objectNamespaces` field when an application owns
154
+ different object families.
155
+
156
+ Keep `objectNamespaces` identical across every reader and writer for a deployed
157
+ store; changing the set is a storage-protocol migration, not a per-process
158
+ preference. On case-insensitive filesystems, use case-stable artifact ids,
159
+ version ids, and object keys (Concepta's lowercase UUID ids satisfy this).
160
+
161
+ The CAE1 framing and its `{ scope, artifactId, version, path }` context are a
162
+ compatibility contract. Existing envelopes remain readable. Filesystems retain
163
+ the layouts `<root>/<artifactId>/<path>` and `<root>/_objects/<key>`; S3 and
164
+ other object-store providers retain their deployed unprefixed object keys, so a
165
+ rolling upgrade does not split old and new writers across keyspaces. Artifact
166
+ and version ids must each be one safe storage segment. Legacy plaintext reads
167
+ are available only through the explicit
168
+ `ARTIFACT_ENCRYPTION_READ_LEGACY=true` migration flag; writes are always
169
+ encrypted.
170
+
171
+ The convenience `createArtifactStorage()` and `createObjectStore()` factories
172
+ are ideal for scripts. Long-running framework-neutral processes that need an
173
+ explicit shutdown path should create the raw clients with
174
+ `createArtifactStorageClient()` / `createObjectStorageClient()`, compose them
175
+ with the corresponding `create*WithClient()` function, call each client's
176
+ `onApplicationShutdown()`, and finally call `crypto.keyProvider.clear()`. The
177
+ Nest module owns that lifecycle automatically.
178
+
179
+ Nest applications can register both adapters with one dynamic module:
180
+
181
+ ```ts
182
+ import { Module } from '@nestjs/common';
183
+ import {
184
+ artifactStorageConfigFromEnv,
185
+ storageCryptoFromEnv,
186
+ } from '@nestm/storage/artifacts';
187
+ import { ArtifactStorageModule } from '@nestm/storage/artifacts/nest';
188
+
189
+ @Module({
190
+ imports: [
191
+ ArtifactStorageModule.forRoot({
192
+ config: artifactStorageConfigFromEnv(process.env),
193
+ crypto: storageCryptoFromEnv(process.env),
194
+ }),
195
+ ],
196
+ })
197
+ export class AppModule {}
198
+ ```
199
+
200
+ Inject `ArtifactStorage` with `@InjectArtifactStorage()` and `ObjectStore` with
201
+ `@InjectObjectStore()`. The module owns named raw clients (`artifacts` and
202
+ `objects`) and clears cached data keys during application shutdown. Set
203
+ `isGlobal: true` only when both adapters are intentionally application-wide.
204
+
91
205
  ## Configure named stores
92
206
 
93
207
  Use the package-owned S3 factory when applicable. For other providers, create a
@@ -0,0 +1,161 @@
1
+ import { type StorageClient } from '../core/index.js';
2
+ import { SCOPE_FROM_HEADER, type StorageCrypto } from './crypto/index.js';
3
+ import { type ArtifactStorageConfig } from './storage-driver.js';
4
+ export { assertStorageProvider, defaultFsRoot, type ArtifactStorageConfig, } from './storage-driver.js';
5
+ /**
6
+ * Storage for uploaded artifact files, keyed `<artifactId>/<path>` (e.g. `<id>/index.html`,
7
+ * `<id>/assets/app.js`). The api writes; the sandbox reads. The `fs` provider keeps both pointed
8
+ * at one directory (fine for a single host / shared volume); any object-store provider — S3, GCS,
9
+ * Azure, R2, and the rest — lets the two services share storage without a shared volume, which is
10
+ * what running them on separate hosts (as on ECS) requires.
11
+ *
12
+ * Every object is stored as a CAE1 encryption envelope (ADR-0001, SEC-03): callers must say who
13
+ * owns what they write (`ScopeRef`) and what they expect to read (`ReadRef`) — the codec binds
14
+ * ciphertext to `{scope, artifactId, version, path}` so a swapped or replayed object fails closed.
15
+ */
16
+ export interface ArtifactStorage {
17
+ /** Single self-contained HTML artifact → `<id>/index.html`. */
18
+ writeHtml(artifactId: string, buffer: Buffer, ref: ScopeRef): Promise<void>;
19
+ /**
20
+ * Pre-built SPA bundle (a zip whose root contains index.html). Encrypted per extracted entry.
21
+ * With `opts.versionId` (VER-03), entries land under `v/<versionId>/…` and are sealed with
22
+ * `ctx.version = versionId` (the caller's `ref.version` is overridden to match — the path⇔version
23
+ * biconditional is derived, never trusted). Reserved-namespace screening applies to the zip
24
+ * ENTRY name in both modes: a bundle shipping `v/…` or `__…` files has those skipped, not nested.
25
+ */
26
+ writeBundle(artifactId: string, zipBuffer: Buffer, ref: ScopeRef, opts?: WriteBundleOptions): Promise<void>;
27
+ /**
28
+ * Write an arbitrary file within the artifact (e.g. `__vendor/<hash>.js`, `__meta.json`).
29
+ * Rejects any `relPath` escaping the artifact directory. `contentType` rides the envelope
30
+ * header (authenticated) on both backends.
31
+ */
32
+ writeFile(artifactId: string, relPath: string, buffer: Buffer, ref: ScopeRef, contentType?: string): Promise<void>;
33
+ /** Server-rendered PNG preview → reserved key `<id>/__thumb.png`. */
34
+ writeThumbnail(artifactId: string, pngBuffer: Buffer, ref: ScopeRef): Promise<void>;
35
+ /** Delete every file under the artifact (includes the thumbnail). */
36
+ remove(artifactId: string): Promise<void>;
37
+ /**
38
+ * Read a file within the artifact; `relPath === ""` resolves to index.html. `null` if absent.
39
+ * Throws `EnvelopeError` on any decrypt failure — a corrupt or swapped object must never be
40
+ * mistaken for a missing one (no SPA fallback over tampering).
41
+ */
42
+ read(artifactId: string, relPath: string, ref: ReadRef, options?: ArtifactReadOptions): Promise<Buffer | null>;
43
+ /**
44
+ * Like `read`, but also returns the envelope's AUTHENTICATED content type (VER-03). This is the
45
+ * read primitive for publish/CoW copy loops: a decrypt→re-encrypt copy must re-seal with the
46
+ * same `ct` it opened (the type is AAD-bound and steers serving), and `read()` discards it.
47
+ * `contentType` is undefined only for legacy plaintext pass-throughs (nothing was verified).
48
+ */
49
+ readWithInfo(artifactId: string, relPath: string, ref: ReadRef, options?: ArtifactReadOptions): Promise<StoredObject | null>;
50
+ /**
51
+ * Delete specific files under the artifact (VER-03: publish prunes root paths removed by the
52
+ * newly-materialized version). Paths escaping the artifact directory and missing paths are
53
+ * ignored (idempotent — publish repair re-runs the same prune).
54
+ */
55
+ deleteFiles(artifactId: string, relPaths: string[]): Promise<void>;
56
+ /**
57
+ * List stored objects under the artifact (optionally under `subPrefix`, e.g. `v/<versionId>/`).
58
+ * Returns artifact-relative forward-slash paths + last-modified stamps, sorted by path. Reads
59
+ * no object bodies and needs no crypto — it serves the sweepers/invariants (version-prefix
60
+ * existence, orphan-prefix age, canonical bundle enumeration), never the serving plane.
61
+ */
62
+ listFiles(artifactId: string, subPrefix?: string): Promise<StoredFileInfo[]>;
63
+ }
64
+ /** One listed storage object (metadata only — the body stays sealed). */
65
+ export interface StoredFileInfo {
66
+ /** Artifact-relative path, forward slashes (e.g. `index.html`, `v/<vid>/index.html`). */
67
+ path: string;
68
+ lastModified: Date;
69
+ }
70
+ /** A decrypted object plus the authenticated content type it was sealed with (see readWithInfo). */
71
+ export interface StoredObject {
72
+ plain: Buffer;
73
+ /** From the envelope header (`ct`, AAD-bound); undefined for legacy plaintext pass-throughs. */
74
+ contentType?: string;
75
+ }
76
+ /** Bounds decrypted data while also bounding the opaque envelope downloaded before decryption. */
77
+ export interface ArtifactReadOptions {
78
+ readonly maxPlainBytes?: number;
79
+ }
80
+ /** Permanent, address-independent read rejection safe for callers to map to a bounded 4xx. */
81
+ export declare class ArtifactReadLimitError extends Error {
82
+ readonly maxPlainBytes: number;
83
+ constructor(maxPlainBytes: number);
84
+ }
85
+ /** Permanent rejection for a ZIP whose declared expansion exceeds the public protocol limits. */
86
+ export declare class ArtifactBundleLimitError extends Error {
87
+ readonly reason: 'entries' | 'entry-bytes' | 'total-bytes';
88
+ constructor(reason: 'entries' | 'entry-bytes' | 'total-bytes');
89
+ }
90
+ export declare const ARTIFACT_BUNDLE_MAX_ENTRIES = 1000;
91
+ export declare const ARTIFACT_BUNDLE_MAX_ENTRY_BYTES: number;
92
+ export declare const ARTIFACT_BUNDLE_MAX_TOTAL_BYTES: number;
93
+ /** Reserved storage path for the generated PNG preview, served by the sandbox as `<id>/__thumb.png`. */
94
+ export declare const THUMBNAIL_KEY = "__thumb.png";
95
+ /** Options for writeBundle (VER-03 versioned bundle writes). */
96
+ export interface WriteBundleOptions {
97
+ /** Write entries under `v/<versionId>/…` with `ctx.version = versionId` instead of the root. */
98
+ versionId?: string;
99
+ /** Optional stricter limits; values may lower, but never raise, the protocol hard limits. */
100
+ limits?: {
101
+ maxEntries?: number;
102
+ maxEntryBytes?: number;
103
+ maxTotalBytes?: number;
104
+ };
105
+ }
106
+ /** Who owns an object being written; `version` stays null until VER-02 introduces versions. */
107
+ export interface ScopeRef {
108
+ /** `org:<organizationId>` | `user:<ownerUserId>` | `upload:<uploadId>` — see artifactScope(). */
109
+ scope: string;
110
+ version?: string | null;
111
+ }
112
+ /**
113
+ * What the reader independently knows. The api asserts the scope it fetched from the DB; the
114
+ * sandbox — which only knows the artifactId — passes SCOPE_FROM_HEADER and relies on the wrap
115
+ * layer to enforce scope cryptographically (see crypto/context.ts).
116
+ */
117
+ export interface ReadRef {
118
+ scope: string | typeof SCOPE_FROM_HEADER;
119
+ version?: string | null;
120
+ }
121
+ export declare function createArtifactStorage(cfg: ArtifactStorageConfig, crypto: StorageCrypto): Promise<ArtifactStorage>;
122
+ /** Framework-neutral domain adapter used by both direct consumers and the Nest composition entry. */
123
+ export declare function createArtifactStorageWithClient(cfg: ArtifactStorageConfig, crypto: StorageCrypto, client: StorageClient): ArtifactStorage;
124
+ /**
125
+ * Storage path prefix for a version's objects (AP-002): `""` for a backfilled `canonical_v1`
126
+ * version (its bytes ARE the canonical root objects) and `v/<versionId>/` for a `versioned` one.
127
+ */
128
+ export declare function versionPrefix(layout: 'canonical_v1' | 'versioned', versionId: string): string;
129
+ /**
130
+ * Envelope `ctx.version` for a version's objects (AP-002): `null` for `canonical_v1` (root AAD —
131
+ * the serving plane is version-free forever) and the version UUID, byte-identical to the path
132
+ * segment, for `versioned`.
133
+ */
134
+ export declare function versionAad(layout: 'canonical_v1' | 'versioned', versionId: string): string | null;
135
+ /** Artifact ids are one storage segment; `_objects` is the filesystem object-store namespace. */
136
+ export declare function assertArtifactId(artifactId: string): void;
137
+ /** Version ids are one storage segment because they are interpolated under `v/<id>/`. */
138
+ export declare function assertVersionId(versionId: string): void;
139
+ /**
140
+ * Is this artifact-relative path inside the namespaces VER-02 reserves for the platform — the
141
+ * `v/` version prefix and the `__`-internal families (meta/thumb/source/snapshot/overflow) —
142
+ * with the one serving exemption, top-level single-segment `__vendor/<name>` pool assets?
143
+ * User-supplied bundle entries matching this are SKIPPED at write time (writeBundle), exactly
144
+ * like zip-slip entries: the sandbox deny-guard will never serve them, and letting them through
145
+ * to the seal chokepoint would turn a hostile/quirky zip into a mid-write throw.
146
+ */
147
+ export declare function isReservedArtifactPath(relPath: string): boolean;
148
+ /**
149
+ * AP-002 storage rule 2: `path.startsWith("v/" + version + "/") ⇔ version !== null`. Root objects
150
+ * never live under the reserved `v/` namespace and versioned objects never live anywhere else —
151
+ * asserted at the single ctx chokepoint (covers reads and writes, both backends), so a
152
+ * mis-addressed artifact object is impossible rather than unlikely. Throws (fail-closed): this is
153
+ * a programming error, never user input — every USER-named path (zip entries) is screened by
154
+ * `isReservedArtifactPath` before it can reach this assertion.
155
+ */
156
+ export declare function assertVersionPath(path: string, version: string | null): void;
157
+ /** Structured, greppable trace of a legacy plaintext pass-through (SEC-04 migration window). */
158
+ export declare function warnLegacyRead(where: string, key: string): void;
159
+ /** content-type for an artifact file path, falling back to octet-stream. */
160
+ export declare function contentTypeFor(path: string): string;
161
+ //# sourceMappingURL=artifact-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-storage.d.ts","sourceRoot":"","sources":["../../src/artifacts/artifact-storage.ts"],"names":[],"mappings":"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"}