@streetjs/storage 1.0.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/LICENSE +21 -0
- package/README.md +719 -0
- package/dist/access.d.ts +95 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +114 -0
- package/dist/access.js.map +1 -0
- package/dist/cli/commands.d.ts +88 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +369 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/generators.d.ts +41 -0
- package/dist/cli/generators.d.ts.map +1 -0
- package/dist/cli/generators.js +119 -0
- package/dist/cli/generators.js.map +1 -0
- package/dist/directory.d.ts +88 -0
- package/dist/directory.d.ts.map +1 -0
- package/dist/directory.js +148 -0
- package/dist/directory.js.map +1 -0
- package/dist/driver.d.ts +83 -0
- package/dist/driver.d.ts.map +1 -0
- package/dist/driver.js +16 -0
- package/dist/driver.js.map +1 -0
- package/dist/drivers/azure.d.ts +239 -0
- package/dist/drivers/azure.d.ts.map +1 -0
- package/dist/drivers/azure.js +476 -0
- package/dist/drivers/azure.js.map +1 -0
- package/dist/drivers/backblaze.d.ts +105 -0
- package/dist/drivers/backblaze.d.ts.map +1 -0
- package/dist/drivers/backblaze.js +279 -0
- package/dist/drivers/backblaze.js.map +1 -0
- package/dist/drivers/gcs.d.ts +239 -0
- package/dist/drivers/gcs.d.ts.map +1 -0
- package/dist/drivers/gcs.js +454 -0
- package/dist/drivers/gcs.js.map +1 -0
- package/dist/drivers/local.d.ts +126 -0
- package/dist/drivers/local.d.ts.map +1 -0
- package/dist/drivers/local.js +321 -0
- package/dist/drivers/local.js.map +1 -0
- package/dist/drivers/memory.d.ts +104 -0
- package/dist/drivers/memory.d.ts.map +1 -0
- package/dist/drivers/memory.js +197 -0
- package/dist/drivers/memory.js.map +1 -0
- package/dist/drivers/minio.d.ts +90 -0
- package/dist/drivers/minio.d.ts.map +1 -0
- package/dist/drivers/minio.js +276 -0
- package/dist/drivers/minio.js.map +1 -0
- package/dist/drivers/r2.d.ts +100 -0
- package/dist/drivers/r2.d.ts.map +1 -0
- package/dist/drivers/r2.js +240 -0
- package/dist/drivers/r2.js.map +1 -0
- package/dist/drivers/s3-base.d.ts +270 -0
- package/dist/drivers/s3-base.d.ts.map +1 -0
- package/dist/drivers/s3-base.js +436 -0
- package/dist/drivers/s3-base.js.map +1 -0
- package/dist/drivers/s3.d.ts +111 -0
- package/dist/drivers/s3.d.ts.map +1 -0
- package/dist/drivers/s3.js +311 -0
- package/dist/drivers/s3.js.map +1 -0
- package/dist/drivers/supabase.d.ts +246 -0
- package/dist/drivers/supabase.d.ts.map +1 -0
- package/dist/drivers/supabase.js +502 -0
- package/dist/drivers/supabase.js.map +1 -0
- package/dist/errors.d.ts +115 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +131 -0
- package/dist/errors.js.map +1 -0
- package/dist/examples/storage-demo.d.ts +53 -0
- package/dist/examples/storage-demo.d.ts.map +1 -0
- package/dist/examples/storage-demo.js +242 -0
- package/dist/examples/storage-demo.js.map +1 -0
- package/dist/facade.d.ts +192 -0
- package/dist/facade.d.ts.map +1 -0
- package/dist/facade.js +898 -0
- package/dist/facade.js.map +1 -0
- package/dist/image.d.ts +94 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +224 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/events.d.ts +108 -0
- package/dist/integrations/events.d.ts.map +1 -0
- package/dist/integrations/events.js +111 -0
- package/dist/integrations/events.js.map +1 -0
- package/dist/integrations/queue.d.ts +89 -0
- package/dist/integrations/queue.d.ts.map +1 -0
- package/dist/integrations/queue.js +91 -0
- package/dist/integrations/queue.js.map +1 -0
- package/dist/integrations/realtime.d.ts +95 -0
- package/dist/integrations/realtime.d.ts.map +1 -0
- package/dist/integrations/realtime.js +90 -0
- package/dist/integrations/realtime.js.map +1 -0
- package/dist/lifecycle.d.ts +137 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +240 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/metadata.d.ts +109 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +139 -0
- package/dist/metadata.js.map +1 -0
- package/dist/multipart.d.ts +108 -0
- package/dist/multipart.d.ts.map +1 -0
- package/dist/multipart.js +200 -0
- package/dist/multipart.js.map +1 -0
- package/dist/observability.d.ts +82 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +175 -0
- package/dist/observability.js.map +1 -0
- package/dist/plugin.d.ts +82 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +100 -0
- package/dist/plugin.js.map +1 -0
- package/dist/resumable.d.ts +118 -0
- package/dist/resumable.d.ts.map +1 -0
- package/dist/resumable.js +223 -0
- package/dist/resumable.js.map +1 -0
- package/dist/search.d.ts +57 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +172 -0
- package/dist/search.js.map +1 -0
- package/dist/signed-url.d.ts +110 -0
- package/dist/signed-url.d.ts.map +1 -0
- package/dist/signed-url.js +237 -0
- package/dist/signed-url.js.map +1 -0
- package/dist/testing/index.d.ts +219 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +393 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tests/access.test.d.ts +2 -0
- package/dist/tests/access.test.d.ts.map +1 -0
- package/dist/tests/access.test.js +270 -0
- package/dist/tests/access.test.js.map +1 -0
- package/dist/tests/azure-driver.test.d.ts +2 -0
- package/dist/tests/azure-driver.test.d.ts.map +1 -0
- package/dist/tests/azure-driver.test.js +183 -0
- package/dist/tests/azure-driver.test.js.map +1 -0
- package/dist/tests/backblaze-driver.test.d.ts +2 -0
- package/dist/tests/backblaze-driver.test.d.ts.map +1 -0
- package/dist/tests/backblaze-driver.test.js +185 -0
- package/dist/tests/backblaze-driver.test.js.map +1 -0
- package/dist/tests/bridge-degradation.test.d.ts +2 -0
- package/dist/tests/bridge-degradation.test.d.ts.map +1 -0
- package/dist/tests/bridge-degradation.test.js +138 -0
- package/dist/tests/bridge-degradation.test.js.map +1 -0
- package/dist/tests/cli.test.d.ts +2 -0
- package/dist/tests/cli.test.d.ts.map +1 -0
- package/dist/tests/cli.test.js +127 -0
- package/dist/tests/cli.test.js.map +1 -0
- package/dist/tests/contract.d.ts +131 -0
- package/dist/tests/contract.d.ts.map +1 -0
- package/dist/tests/contract.js +222 -0
- package/dist/tests/contract.js.map +1 -0
- package/dist/tests/contract.test.d.ts +2 -0
- package/dist/tests/contract.test.d.ts.map +1 -0
- package/dist/tests/contract.test.js +110 -0
- package/dist/tests/contract.test.js.map +1 -0
- package/dist/tests/directory.test.d.ts +2 -0
- package/dist/tests/directory.test.d.ts.map +1 -0
- package/dist/tests/directory.test.js +125 -0
- package/dist/tests/directory.test.js.map +1 -0
- package/dist/tests/errors.test.d.ts +2 -0
- package/dist/tests/errors.test.d.ts.map +1 -0
- package/dist/tests/errors.test.js +93 -0
- package/dist/tests/errors.test.js.map +1 -0
- package/dist/tests/events-bridge.test.d.ts +2 -0
- package/dist/tests/events-bridge.test.d.ts.map +1 -0
- package/dist/tests/events-bridge.test.js +228 -0
- package/dist/tests/events-bridge.test.js.map +1 -0
- package/dist/tests/example-smoke.test.d.ts +2 -0
- package/dist/tests/example-smoke.test.d.ts.map +1 -0
- package/dist/tests/example-smoke.test.js +34 -0
- package/dist/tests/example-smoke.test.js.map +1 -0
- package/dist/tests/gcs-driver.test.d.ts +2 -0
- package/dist/tests/gcs-driver.test.d.ts.map +1 -0
- package/dist/tests/gcs-driver.test.js +197 -0
- package/dist/tests/gcs-driver.test.js.map +1 -0
- package/dist/tests/image.test.d.ts +2 -0
- package/dist/tests/image.test.d.ts.map +1 -0
- package/dist/tests/image.test.js +102 -0
- package/dist/tests/image.test.js.map +1 -0
- package/dist/tests/lifecycle.test.d.ts +2 -0
- package/dist/tests/lifecycle.test.d.ts.map +1 -0
- package/dist/tests/lifecycle.test.js +171 -0
- package/dist/tests/lifecycle.test.js.map +1 -0
- package/dist/tests/local-driver.test.d.ts +2 -0
- package/dist/tests/local-driver.test.d.ts.map +1 -0
- package/dist/tests/local-driver.test.js +153 -0
- package/dist/tests/local-driver.test.js.map +1 -0
- package/dist/tests/local-streaming.test.d.ts +2 -0
- package/dist/tests/local-streaming.test.d.ts.map +1 -0
- package/dist/tests/local-streaming.test.js +121 -0
- package/dist/tests/local-streaming.test.js.map +1 -0
- package/dist/tests/memory-driver.test.d.ts +2 -0
- package/dist/tests/memory-driver.test.d.ts.map +1 -0
- package/dist/tests/memory-driver.test.js +180 -0
- package/dist/tests/memory-driver.test.js.map +1 -0
- package/dist/tests/memory-streaming.test.d.ts +2 -0
- package/dist/tests/memory-streaming.test.d.ts.map +1 -0
- package/dist/tests/memory-streaming.test.js +92 -0
- package/dist/tests/memory-streaming.test.js.map +1 -0
- package/dist/tests/minio-driver.test.d.ts +2 -0
- package/dist/tests/minio-driver.test.d.ts.map +1 -0
- package/dist/tests/minio-driver.test.js +146 -0
- package/dist/tests/minio-driver.test.js.map +1 -0
- package/dist/tests/non-s3-integration.test.d.ts +2 -0
- package/dist/tests/non-s3-integration.test.d.ts.map +1 -0
- package/dist/tests/non-s3-integration.test.js +201 -0
- package/dist/tests/non-s3-integration.test.js.map +1 -0
- package/dist/tests/observability.registration.test.d.ts +2 -0
- package/dist/tests/observability.registration.test.d.ts.map +1 -0
- package/dist/tests/observability.registration.test.js +103 -0
- package/dist/tests/observability.registration.test.js.map +1 -0
- package/dist/tests/observability.test.d.ts +2 -0
- package/dist/tests/observability.test.d.ts.map +1 -0
- package/dist/tests/observability.test.js +240 -0
- package/dist/tests/observability.test.js.map +1 -0
- package/dist/tests/plugin.test.d.ts +2 -0
- package/dist/tests/plugin.test.d.ts.map +1 -0
- package/dist/tests/plugin.test.js +112 -0
- package/dist/tests/plugin.test.js.map +1 -0
- package/dist/tests/prop-concurrent.test.d.ts +2 -0
- package/dist/tests/prop-concurrent.test.d.ts.map +1 -0
- package/dist/tests/prop-concurrent.test.js +59 -0
- package/dist/tests/prop-concurrent.test.js.map +1 -0
- package/dist/tests/prop-copy.test.d.ts +2 -0
- package/dist/tests/prop-copy.test.d.ts.map +1 -0
- package/dist/tests/prop-copy.test.js +63 -0
- package/dist/tests/prop-copy.test.js.map +1 -0
- package/dist/tests/prop-delete.test.d.ts +2 -0
- package/dist/tests/prop-delete.test.d.ts.map +1 -0
- package/dist/tests/prop-delete.test.js +35 -0
- package/dist/tests/prop-delete.test.js.map +1 -0
- package/dist/tests/prop-directory.test.d.ts +2 -0
- package/dist/tests/prop-directory.test.d.ts.map +1 -0
- package/dist/tests/prop-directory.test.js +118 -0
- package/dist/tests/prop-directory.test.js.map +1 -0
- package/dist/tests/prop-driver-conformance.test.d.ts +2 -0
- package/dist/tests/prop-driver-conformance.test.d.ts.map +1 -0
- package/dist/tests/prop-driver-conformance.test.js +110 -0
- package/dist/tests/prop-driver-conformance.test.js.map +1 -0
- package/dist/tests/prop-driver-equivalence.test.d.ts +2 -0
- package/dist/tests/prop-driver-equivalence.test.d.ts.map +1 -0
- package/dist/tests/prop-driver-equivalence.test.js +163 -0
- package/dist/tests/prop-driver-equivalence.test.js.map +1 -0
- package/dist/tests/prop-lifecycle.test.d.ts +2 -0
- package/dist/tests/prop-lifecycle.test.d.ts.map +1 -0
- package/dist/tests/prop-lifecycle.test.js +83 -0
- package/dist/tests/prop-lifecycle.test.js.map +1 -0
- package/dist/tests/prop-list.test.d.ts +2 -0
- package/dist/tests/prop-list.test.d.ts.map +1 -0
- package/dist/tests/prop-list.test.js +53 -0
- package/dist/tests/prop-list.test.js.map +1 -0
- package/dist/tests/prop-metadata.test.d.ts +2 -0
- package/dist/tests/prop-metadata.test.d.ts.map +1 -0
- package/dist/tests/prop-metadata.test.js +87 -0
- package/dist/tests/prop-metadata.test.js.map +1 -0
- package/dist/tests/prop-move.test.d.ts +2 -0
- package/dist/tests/prop-move.test.d.ts.map +1 -0
- package/dist/tests/prop-move.test.js +67 -0
- package/dist/tests/prop-move.test.js.map +1 -0
- package/dist/tests/prop-multipart-abort.test.d.ts +2 -0
- package/dist/tests/prop-multipart-abort.test.d.ts.map +1 -0
- package/dist/tests/prop-multipart-abort.test.js +48 -0
- package/dist/tests/prop-multipart-abort.test.js.map +1 -0
- package/dist/tests/prop-multipart.test.d.ts +2 -0
- package/dist/tests/prop-multipart.test.d.ts.map +1 -0
- package/dist/tests/prop-multipart.test.js +65 -0
- package/dist/tests/prop-multipart.test.js.map +1 -0
- package/dist/tests/prop-resumable.test.d.ts +2 -0
- package/dist/tests/prop-resumable.test.d.ts.map +1 -0
- package/dist/tests/prop-resumable.test.js +78 -0
- package/dist/tests/prop-resumable.test.js.map +1 -0
- package/dist/tests/prop-search.test.d.ts +2 -0
- package/dist/tests/prop-search.test.d.ts.map +1 -0
- package/dist/tests/prop-search.test.js +120 -0
- package/dist/tests/prop-search.test.js.map +1 -0
- package/dist/tests/prop-signed-url.test.d.ts +2 -0
- package/dist/tests/prop-signed-url.test.d.ts.map +1 -0
- package/dist/tests/prop-signed-url.test.js +74 -0
- package/dist/tests/prop-signed-url.test.js.map +1 -0
- package/dist/tests/prop-streaming.test.d.ts +2 -0
- package/dist/tests/prop-streaming.test.d.ts.map +1 -0
- package/dist/tests/prop-streaming.test.js +34 -0
- package/dist/tests/prop-streaming.test.js.map +1 -0
- package/dist/tests/prop-upload-download.test.d.ts +2 -0
- package/dist/tests/prop-upload-download.test.d.ts.map +1 -0
- package/dist/tests/prop-upload-download.test.js +30 -0
- package/dist/tests/prop-upload-download.test.js.map +1 -0
- package/dist/tests/prop-validation.test.d.ts +2 -0
- package/dist/tests/prop-validation.test.d.ts.map +1 -0
- package/dist/tests/prop-validation.test.js +50 -0
- package/dist/tests/prop-validation.test.js.map +1 -0
- package/dist/tests/prop-versioning.test.d.ts +2 -0
- package/dist/tests/prop-versioning.test.d.ts.map +1 -0
- package/dist/tests/prop-versioning.test.js +74 -0
- package/dist/tests/prop-versioning.test.js.map +1 -0
- package/dist/tests/queue-bridge.test.d.ts +2 -0
- package/dist/tests/queue-bridge.test.d.ts.map +1 -0
- package/dist/tests/queue-bridge.test.js +111 -0
- package/dist/tests/queue-bridge.test.js.map +1 -0
- package/dist/tests/r2-driver.test.d.ts +2 -0
- package/dist/tests/r2-driver.test.d.ts.map +1 -0
- package/dist/tests/r2-driver.test.js +143 -0
- package/dist/tests/r2-driver.test.js.map +1 -0
- package/dist/tests/realtime-bridge.test.d.ts +2 -0
- package/dist/tests/realtime-bridge.test.d.ts.map +1 -0
- package/dist/tests/realtime-bridge.test.js +106 -0
- package/dist/tests/realtime-bridge.test.js.map +1 -0
- package/dist/tests/resumable.test.d.ts +2 -0
- package/dist/tests/resumable.test.d.ts.map +1 -0
- package/dist/tests/resumable.test.js +104 -0
- package/dist/tests/resumable.test.js.map +1 -0
- package/dist/tests/s3-base.test.d.ts +2 -0
- package/dist/tests/s3-base.test.d.ts.map +1 -0
- package/dist/tests/s3-base.test.js +289 -0
- package/dist/tests/s3-base.test.js.map +1 -0
- package/dist/tests/s3-integration.test.d.ts +2 -0
- package/dist/tests/s3-integration.test.d.ts.map +1 -0
- package/dist/tests/s3-integration.test.js +270 -0
- package/dist/tests/s3-integration.test.js.map +1 -0
- package/dist/tests/s3.test.d.ts +2 -0
- package/dist/tests/s3.test.d.ts.map +1 -0
- package/dist/tests/s3.test.js +203 -0
- package/dist/tests/s3.test.js.map +1 -0
- package/dist/tests/scaffold.test.d.ts +2 -0
- package/dist/tests/scaffold.test.d.ts.map +1 -0
- package/dist/tests/scaffold.test.js +13 -0
- package/dist/tests/scaffold.test.js.map +1 -0
- package/dist/tests/search.test.d.ts +2 -0
- package/dist/tests/search.test.d.ts.map +1 -0
- package/dist/tests/search.test.js +106 -0
- package/dist/tests/search.test.js.map +1 -0
- package/dist/tests/supabase-driver.test.d.ts +2 -0
- package/dist/tests/supabase-driver.test.d.ts.map +1 -0
- package/dist/tests/supabase-driver.test.js +196 -0
- package/dist/tests/supabase-driver.test.js.map +1 -0
- package/dist/tests/testing-utilities.test.d.ts +2 -0
- package/dist/tests/testing-utilities.test.d.ts.map +1 -0
- package/dist/tests/testing-utilities.test.js +138 -0
- package/dist/tests/testing-utilities.test.js.map +1 -0
- package/dist/tests/validation.test.d.ts +2 -0
- package/dist/tests/validation.test.d.ts.map +1 -0
- package/dist/tests/validation.test.js +135 -0
- package/dist/tests/validation.test.js.map +1 -0
- package/dist/tests/versioning.test.d.ts +2 -0
- package/dist/tests/versioning.test.d.ts.map +1 -0
- package/dist/tests/versioning.test.js +128 -0
- package/dist/tests/versioning.test.js.map +1 -0
- package/dist/types.d.ts +232 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +105 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +225 -0
- package/dist/validation.js.map +1 -0
- package/dist/versioning.d.ts +100 -0
- package/dist/versioning.d.ts.map +1 -0
- package/dist/versioning.js +179 -0
- package/dist/versioning.js.map +1 -0
- package/package.json +137 -0
package/dist/access.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streetjs/storage — provider-agnostic access control.
|
|
3
|
+
*
|
|
4
|
+
* The {@link AccessController} resolves an {@link AccessLevel} decision for a
|
|
5
|
+
* single object operation (read / write / delete) and, when the caller lacks
|
|
6
|
+
* the required access, denies the operation with an {@link AuthorizationError}
|
|
7
|
+
* so no persistence or read is performed. The facade constructs one controller
|
|
8
|
+
* per {@link Storage} instance and consults it as the first step of the object
|
|
9
|
+
* operations it guards (see the `put`/`get` data flow in the design).
|
|
10
|
+
*
|
|
11
|
+
* Access decisions are delegated to the optional **structural** auth bridge
|
|
12
|
+
* {@link AuthLike} carried on `config.auth`. This keeps the package free of any
|
|
13
|
+
* hard dependency on `@streetjs/auth`: any object exposing a compatible
|
|
14
|
+
* `can(context)` method satisfies the contract (Requirements 11.2, 17.2).
|
|
15
|
+
*
|
|
16
|
+
* The controller supports every {@link AccessLevel} value — `public`,
|
|
17
|
+
* `private`, `signed`, `authenticated`, `role-based`, and `tenant-aware`
|
|
18
|
+
* (Requirement 11.1) — and applies a single, uniform rule:
|
|
19
|
+
*
|
|
20
|
+
* - **No auth bridge configured** → every operation is permitted. The
|
|
21
|
+
* framework stays permissive by default so drivers that never configure
|
|
22
|
+
* access control (the in-memory / local defaults) behave exactly as before.
|
|
23
|
+
* - **Auth bridge configured** → the bridge's `can(context)` decision governs
|
|
24
|
+
* the operation. A `false` decision denies with an {@link AuthorizationError}
|
|
25
|
+
* (Requirement 11.3); any other result permits. This is where the
|
|
26
|
+
* `authenticated`, `role-based`, and `tenant-aware` levels are resolved
|
|
27
|
+
* against StreetJS authentication (Requirement 11.2).
|
|
28
|
+
* - **`public` reads** are permitted without authentication; a configured
|
|
29
|
+
* bridge may still block them by returning `false`, honoring the "unless
|
|
30
|
+
* another configured factor blocks the access" clause (Requirement 11.4).
|
|
31
|
+
*
|
|
32
|
+
* _Requirements: 11.1, 11.2, 11.3, 11.4_
|
|
33
|
+
*/
|
|
34
|
+
import type { AccessLevel, AuthLike } from "./types.js";
|
|
35
|
+
export type { AuthLike } from "./types.js";
|
|
36
|
+
/** The class of object operation an access decision governs. */
|
|
37
|
+
export type AccessOperation = "read" | "write" | "delete";
|
|
38
|
+
/**
|
|
39
|
+
* The subject of a single access decision: the object `key`, the attempted
|
|
40
|
+
* `operation`, the governing `accessLevel`, and the optional ownership /
|
|
41
|
+
* tenancy attributes the auth bridge may key its decision on.
|
|
42
|
+
*/
|
|
43
|
+
export interface AccessContext {
|
|
44
|
+
readonly key: string;
|
|
45
|
+
readonly operation: AccessOperation;
|
|
46
|
+
readonly accessLevel: AccessLevel;
|
|
47
|
+
readonly owner?: string;
|
|
48
|
+
readonly tenant?: string;
|
|
49
|
+
}
|
|
50
|
+
/** Options for constructing an {@link AccessController}. */
|
|
51
|
+
export interface AccessControllerOptions {
|
|
52
|
+
/** The optional structural auth bridge that governs access decisions. */
|
|
53
|
+
readonly auth?: AuthLike;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolves per-object {@link AccessLevel} decisions, denying disallowed
|
|
57
|
+
* operations with an {@link AuthorizationError}.
|
|
58
|
+
*
|
|
59
|
+
* Construct one from `config.auth`; the facade does this once per `Storage`
|
|
60
|
+
* instance and calls {@link AccessController.authorize} before delegating a
|
|
61
|
+
* guarded operation to the driver. When no auth bridge is configured the
|
|
62
|
+
* controller is a permissive no-op, preserving the framework's default
|
|
63
|
+
* behavior for unconfigured drivers.
|
|
64
|
+
*/
|
|
65
|
+
export declare class AccessController {
|
|
66
|
+
/** The optional structural auth bridge consulted for every decision. */
|
|
67
|
+
private readonly auth?;
|
|
68
|
+
constructor(options?: AccessControllerOptions);
|
|
69
|
+
/**
|
|
70
|
+
* Whether access control is actively enforced. This is `true` only when an
|
|
71
|
+
* auth bridge is configured; callers use it to skip any preparatory work
|
|
72
|
+
* (e.g. a metadata lookup to discover an object's access level) on the common
|
|
73
|
+
* unconfigured path so behavior and cost are unchanged when no bridge exists.
|
|
74
|
+
*/
|
|
75
|
+
get enforced(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Decide whether `context` is permitted and throw an {@link AuthorizationError}
|
|
78
|
+
* when it is not (Requirement 11.3). On permit this resolves without a value
|
|
79
|
+
* and the caller proceeds; on deny it throws before any persistence or read
|
|
80
|
+
* occurs so the guarded operation has no effect.
|
|
81
|
+
*
|
|
82
|
+
* Decision rules:
|
|
83
|
+
* - No auth bridge configured → permit (the framework is permissive by
|
|
84
|
+
* default so unconfigured drivers are unaffected).
|
|
85
|
+
* - `public` reads → permit unless the configured bridge explicitly returns
|
|
86
|
+
* `false`, in which case that "other configured factor" blocks the access
|
|
87
|
+
* (Requirement 11.4).
|
|
88
|
+
* - Otherwise → the bridge's `can(context)` decision governs; a `false`
|
|
89
|
+
* result denies, any other result permits (Requirements 11.1, 11.2).
|
|
90
|
+
*/
|
|
91
|
+
authorize(context: AccessContext): Promise<void>;
|
|
92
|
+
/** Build the descriptive {@link AuthorizationError} for a denied context. */
|
|
93
|
+
private denial;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAMxD,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,4DAA4D;AAC5D,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAKD;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAW;gBAErB,OAAO,GAAE,uBAA4B;IAIjD;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;;;;;;;;;;;;OAcG;IACG,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BtD,6EAA6E;IAC7E,OAAO,CAAC,MAAM;CAWf"}
|
package/dist/access.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streetjs/storage — provider-agnostic access control.
|
|
3
|
+
*
|
|
4
|
+
* The {@link AccessController} resolves an {@link AccessLevel} decision for a
|
|
5
|
+
* single object operation (read / write / delete) and, when the caller lacks
|
|
6
|
+
* the required access, denies the operation with an {@link AuthorizationError}
|
|
7
|
+
* so no persistence or read is performed. The facade constructs one controller
|
|
8
|
+
* per {@link Storage} instance and consults it as the first step of the object
|
|
9
|
+
* operations it guards (see the `put`/`get` data flow in the design).
|
|
10
|
+
*
|
|
11
|
+
* Access decisions are delegated to the optional **structural** auth bridge
|
|
12
|
+
* {@link AuthLike} carried on `config.auth`. This keeps the package free of any
|
|
13
|
+
* hard dependency on `@streetjs/auth`: any object exposing a compatible
|
|
14
|
+
* `can(context)` method satisfies the contract (Requirements 11.2, 17.2).
|
|
15
|
+
*
|
|
16
|
+
* The controller supports every {@link AccessLevel} value — `public`,
|
|
17
|
+
* `private`, `signed`, `authenticated`, `role-based`, and `tenant-aware`
|
|
18
|
+
* (Requirement 11.1) — and applies a single, uniform rule:
|
|
19
|
+
*
|
|
20
|
+
* - **No auth bridge configured** → every operation is permitted. The
|
|
21
|
+
* framework stays permissive by default so drivers that never configure
|
|
22
|
+
* access control (the in-memory / local defaults) behave exactly as before.
|
|
23
|
+
* - **Auth bridge configured** → the bridge's `can(context)` decision governs
|
|
24
|
+
* the operation. A `false` decision denies with an {@link AuthorizationError}
|
|
25
|
+
* (Requirement 11.3); any other result permits. This is where the
|
|
26
|
+
* `authenticated`, `role-based`, and `tenant-aware` levels are resolved
|
|
27
|
+
* against StreetJS authentication (Requirement 11.2).
|
|
28
|
+
* - **`public` reads** are permitted without authentication; a configured
|
|
29
|
+
* bridge may still block them by returning `false`, honoring the "unless
|
|
30
|
+
* another configured factor blocks the access" clause (Requirement 11.4).
|
|
31
|
+
*
|
|
32
|
+
* _Requirements: 11.1, 11.2, 11.3, 11.4_
|
|
33
|
+
*/
|
|
34
|
+
import { AuthorizationError } from "./errors.js";
|
|
35
|
+
/** Read-like operations that a `public` access level permits without auth. */
|
|
36
|
+
const READ_OPERATIONS = new Set(["read"]);
|
|
37
|
+
/**
|
|
38
|
+
* Resolves per-object {@link AccessLevel} decisions, denying disallowed
|
|
39
|
+
* operations with an {@link AuthorizationError}.
|
|
40
|
+
*
|
|
41
|
+
* Construct one from `config.auth`; the facade does this once per `Storage`
|
|
42
|
+
* instance and calls {@link AccessController.authorize} before delegating a
|
|
43
|
+
* guarded operation to the driver. When no auth bridge is configured the
|
|
44
|
+
* controller is a permissive no-op, preserving the framework's default
|
|
45
|
+
* behavior for unconfigured drivers.
|
|
46
|
+
*/
|
|
47
|
+
export class AccessController {
|
|
48
|
+
/** The optional structural auth bridge consulted for every decision. */
|
|
49
|
+
auth;
|
|
50
|
+
constructor(options = {}) {
|
|
51
|
+
this.auth = options.auth;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Whether access control is actively enforced. This is `true` only when an
|
|
55
|
+
* auth bridge is configured; callers use it to skip any preparatory work
|
|
56
|
+
* (e.g. a metadata lookup to discover an object's access level) on the common
|
|
57
|
+
* unconfigured path so behavior and cost are unchanged when no bridge exists.
|
|
58
|
+
*/
|
|
59
|
+
get enforced() {
|
|
60
|
+
return this.auth !== undefined;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decide whether `context` is permitted and throw an {@link AuthorizationError}
|
|
64
|
+
* when it is not (Requirement 11.3). On permit this resolves without a value
|
|
65
|
+
* and the caller proceeds; on deny it throws before any persistence or read
|
|
66
|
+
* occurs so the guarded operation has no effect.
|
|
67
|
+
*
|
|
68
|
+
* Decision rules:
|
|
69
|
+
* - No auth bridge configured → permit (the framework is permissive by
|
|
70
|
+
* default so unconfigured drivers are unaffected).
|
|
71
|
+
* - `public` reads → permit unless the configured bridge explicitly returns
|
|
72
|
+
* `false`, in which case that "other configured factor" blocks the access
|
|
73
|
+
* (Requirement 11.4).
|
|
74
|
+
* - Otherwise → the bridge's `can(context)` decision governs; a `false`
|
|
75
|
+
* result denies, any other result permits (Requirements 11.1, 11.2).
|
|
76
|
+
*/
|
|
77
|
+
async authorize(context) {
|
|
78
|
+
// Permissive default: with no configured auth bridge nothing is denied, so
|
|
79
|
+
// drivers that never configure access control behave exactly as before.
|
|
80
|
+
if (this.auth === undefined) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const decision = await this.auth.can({
|
|
84
|
+
key: context.key,
|
|
85
|
+
operation: context.operation,
|
|
86
|
+
accessLevel: context.accessLevel,
|
|
87
|
+
owner: context.owner,
|
|
88
|
+
tenant: context.tenant,
|
|
89
|
+
});
|
|
90
|
+
// A `public` read is permitted without authentication; a bridge may still
|
|
91
|
+
// block it, but only by explicitly returning `false` (Requirement 11.4).
|
|
92
|
+
if (context.accessLevel === "public" && READ_OPERATIONS.has(context.operation)) {
|
|
93
|
+
if (decision === false) {
|
|
94
|
+
throw this.denial(context);
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// For every other level/operation the bridge's decision is authoritative:
|
|
99
|
+
// a `false` result denies the operation (Requirement 11.3).
|
|
100
|
+
if (decision === false) {
|
|
101
|
+
throw this.denial(context);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Build the descriptive {@link AuthorizationError} for a denied context. */
|
|
105
|
+
denial(context) {
|
|
106
|
+
return new AuthorizationError(`Access denied: operation "${context.operation}" on "${context.key}" ` +
|
|
107
|
+
`is not permitted for access level "${context.accessLevel}".`, {
|
|
108
|
+
key: context.key,
|
|
109
|
+
operation: context.operation,
|
|
110
|
+
accessLevel: context.accessLevel,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AA+BjD,8EAA8E;AAC9E,MAAM,eAAe,GAAiC,IAAI,GAAG,CAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;AAEzF;;;;;;;;;GASG;AACH,MAAM,OAAO,gBAAgB;IAC3B,wEAAwE;IACvD,IAAI,CAAY;IAEjC,YAAY,UAAmC,EAAE;QAC/C,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,SAAS,CAAC,OAAsB;QACpC,2EAA2E;QAC3E,wEAAwE;QACxE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,0EAA0E;QAC1E,yEAAyE;QACzE,IAAI,OAAO,CAAC,WAAW,KAAK,QAAQ,IAAI,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/E,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;YACD,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,4DAA4D;QAC5D,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,6EAA6E;IACrE,MAAM,CAAC,OAAsB;QACnC,OAAO,IAAI,kBAAkB,CAC3B,6BAA6B,OAAO,CAAC,SAAS,SAAS,OAAO,CAAC,GAAG,IAAI;YACpE,sCAAsC,OAAO,CAAC,WAAW,IAAI,EAC/D;YACE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { ParsedArgs } from "streetjs";
|
|
2
|
+
/**
|
|
3
|
+
* The set of `@Command`-decorated storage commands, registered through the core
|
|
4
|
+
* `CliKernel`. A plain class (no class-level decorator) so the kernel can
|
|
5
|
+
* `container.resolve` it without constructor dependency metadata.
|
|
6
|
+
*/
|
|
7
|
+
export declare class StorageCommands {
|
|
8
|
+
/**
|
|
9
|
+
* `street make:storage <Name> [--dir <dir>] [--provider memory|local]` —
|
|
10
|
+
* scaffold a typed storage module. Delegates to the pure generators: the name
|
|
11
|
+
* (and scaffold provider) are validated before any file is written, and an
|
|
12
|
+
* existing target is never overwritten (Requirement 21.2).
|
|
13
|
+
*/
|
|
14
|
+
makeStorage(args: ParsedArgs): void;
|
|
15
|
+
/**
|
|
16
|
+
* `street storage:list [<prefix>] [--provider memory|local] [--root <dir>]` —
|
|
17
|
+
* list the stored object keys for the configured driver. Builds a `Storage`
|
|
18
|
+
* from the CLI flags and prints every key under the prefix (Requirement 21.3).
|
|
19
|
+
*/
|
|
20
|
+
storageList(args: ParsedArgs): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* `street storage:clean <prefix> [--provider memory|local] [--root <dir>]` —
|
|
23
|
+
* remove every object under a prefix from the configured driver. A prefix is
|
|
24
|
+
* required so the command never silently wipes an entire store; deletion of
|
|
25
|
+
* each object is isolated so one failure does not abort the rest
|
|
26
|
+
* (Requirement 21.3).
|
|
27
|
+
*/
|
|
28
|
+
storageClean(args: ParsedArgs): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* `street storage:sync [<prefix>] --from-provider <p> [--from-root <dir>]
|
|
31
|
+
* --to-provider <p> [--to-root <dir>]` — copy every object under a prefix from
|
|
32
|
+
* a source store to a destination store, leaving the source untouched
|
|
33
|
+
* (Requirement 21.3). Each object copy is isolated so a single failure does
|
|
34
|
+
* not abort the whole sync.
|
|
35
|
+
*/
|
|
36
|
+
storageSync(args: ParsedArgs): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* `street storage:migrate [<prefix>] --from-provider <p> [--from-root <dir>]
|
|
39
|
+
* --to-provider <p> [--to-root <dir>]` — move every object under a prefix from
|
|
40
|
+
* a source store to a destination store (copy, then remove from the source),
|
|
41
|
+
* so the destination becomes the new home for the data (Requirement 21.3).
|
|
42
|
+
* Each object migration is isolated so a single failure does not abort the
|
|
43
|
+
* whole migration.
|
|
44
|
+
*/
|
|
45
|
+
storageMigrate(args: ParsedArgs): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* `street storage:verify [--provider memory|local] [--root <dir>]` — run the
|
|
48
|
+
* shared driver contract-conformance suite against the configured driver and
|
|
49
|
+
* report pass/fail per check, exiting non-zero when any check fails
|
|
50
|
+
* (Requirement 21.4).
|
|
51
|
+
*/
|
|
52
|
+
storageVerify(args: ParsedArgs): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Copy (and optionally remove-from-source) every object under a prefix from a
|
|
55
|
+
* source store to a destination store. Shared by `storage:sync` (copy) and
|
|
56
|
+
* `storage:migrate` (move). Every per-object transfer is isolated so one
|
|
57
|
+
* failure does not abort the rest.
|
|
58
|
+
*/
|
|
59
|
+
private transfer;
|
|
60
|
+
/** Build a live {@link Storage} facade from a resolved {@link StorageConfig}. */
|
|
61
|
+
private buildStorage;
|
|
62
|
+
/**
|
|
63
|
+
* Resolve a {@link StorageConfig} from the CLI flags: `--provider` (defaults to
|
|
64
|
+
* `memory`) and `--root` (used by the `local` provider).
|
|
65
|
+
*/
|
|
66
|
+
private configFromArgs;
|
|
67
|
+
/**
|
|
68
|
+
* Resolve a source (`from`) or destination (`to`) {@link StorageConfig} from a
|
|
69
|
+
* prefixed pair of flags, e.g. `--from-provider`/`--from-root` and
|
|
70
|
+
* `--to-provider`/`--to-root`. Defaults to the `memory` provider.
|
|
71
|
+
*/
|
|
72
|
+
private transferConfig;
|
|
73
|
+
/**
|
|
74
|
+
* Build a {@link StorageDriverFactory} for the configured driver, used by
|
|
75
|
+
* `storage:verify` to obtain a freshly constructed driver per contract check.
|
|
76
|
+
* A pre-constructed `config.driver` is returned as-is; the built-in `memory`
|
|
77
|
+
* and `local` providers are constructed fresh each call. An unknown provider
|
|
78
|
+
* with no supplied driver throws a descriptive {@link StorageConfigError}.
|
|
79
|
+
*/
|
|
80
|
+
private driverFactory;
|
|
81
|
+
/** Read the generator name from the first positional arg or `--name`. */
|
|
82
|
+
private resolveName;
|
|
83
|
+
/** Read the key prefix from the first positional arg or `--prefix` (default ""). */
|
|
84
|
+
private resolvePrefix;
|
|
85
|
+
/** Close a storage facade, swallowing any error so cleanup never masks results. */
|
|
86
|
+
private closeQuietly;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAoB3C;;;;GAIG;AACH,qBAAa,eAAe;IAG1B;;;;;OAKG;IAKH,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IA0CnC;;;;OAIG;IAKG,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBlD;;;;;;OAMG;IAKG,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCnD;;;;;;OAMG;IAKG,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD;;;;;;;OAOG;IAKG,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD;;;;;OAKG;IAKG,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCpD;;;;;OAKG;YACW,QAAQ;IA6CtB,iFAAiF;IACjF,OAAO,CAAC,YAAY;IAIpB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAOtB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAQtB;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAyBrB,yEAAyE;IACzE,OAAO,CAAC,WAAW;IAQnB,oFAAoF;IACpF,OAAO,CAAC,aAAa;IAQrB,mFAAmF;YACrE,YAAY;CAO3B"}
|