@x12i/memorix-service 3.2.1 → 3.4.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.
Files changed (164) hide show
  1. package/README.md +61 -3
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +8 -0
  4. package/dist/app.js.map +1 -1
  5. package/dist/blob-store/config.d.ts +31 -0
  6. package/dist/blob-store/config.d.ts.map +1 -0
  7. package/dist/blob-store/config.js +68 -0
  8. package/dist/blob-store/config.js.map +1 -0
  9. package/dist/blob-store/disk.d.ts +10 -0
  10. package/dist/blob-store/disk.d.ts.map +1 -0
  11. package/dist/blob-store/disk.js +104 -0
  12. package/dist/blob-store/disk.js.map +1 -0
  13. package/dist/blob-store/index.d.ts +6 -0
  14. package/dist/blob-store/index.d.ts.map +1 -0
  15. package/dist/blob-store/index.js +6 -0
  16. package/dist/blob-store/index.js.map +1 -0
  17. package/dist/blob-store/memory.d.ts +4 -0
  18. package/dist/blob-store/memory.d.ts.map +1 -0
  19. package/dist/blob-store/memory.js +47 -0
  20. package/dist/blob-store/memory.js.map +1 -0
  21. package/dist/blob-store/s3.d.ts +52 -0
  22. package/dist/blob-store/s3.d.ts.map +1 -0
  23. package/dist/blob-store/s3.js +151 -0
  24. package/dist/blob-store/s3.js.map +1 -0
  25. package/dist/blob-store/types.d.ts +30 -0
  26. package/dist/blob-store/types.d.ts.map +1 -0
  27. package/dist/blob-store/types.js +38 -0
  28. package/dist/blob-store/types.js.map +1 -0
  29. package/dist/catalog/catalog-service.d.ts +48 -0
  30. package/dist/catalog/catalog-service.d.ts.map +1 -0
  31. package/dist/catalog/catalog-service.js +397 -0
  32. package/dist/catalog/catalog-service.js.map +1 -0
  33. package/dist/catalog/package-list-source.d.ts +35 -0
  34. package/dist/catalog/package-list-source.d.ts.map +1 -0
  35. package/dist/catalog/package-list-source.js +47 -0
  36. package/dist/catalog/package-list-source.js.map +1 -0
  37. package/dist/catalog/types.d.ts +65 -0
  38. package/dist/catalog/types.d.ts.map +1 -0
  39. package/dist/catalog/types.js +16 -0
  40. package/dist/catalog/types.js.map +1 -0
  41. package/dist/catalog-store-cli.d.ts +20 -0
  42. package/dist/catalog-store-cli.d.ts.map +1 -0
  43. package/dist/catalog-store-cli.js +237 -0
  44. package/dist/catalog-store-cli.js.map +1 -0
  45. package/dist/cli.d.ts +3 -1
  46. package/dist/cli.d.ts.map +1 -1
  47. package/dist/cli.js +48 -18
  48. package/dist/cli.js.map +1 -1
  49. package/dist/connector-ops/attempt-store.d.ts +5 -0
  50. package/dist/connector-ops/attempt-store.d.ts.map +1 -0
  51. package/dist/connector-ops/attempt-store.js +186 -0
  52. package/dist/connector-ops/attempt-store.js.map +1 -0
  53. package/dist/connector-ops/index.d.ts +5 -0
  54. package/dist/connector-ops/index.d.ts.map +1 -0
  55. package/dist/connector-ops/index.js +5 -0
  56. package/dist/connector-ops/index.js.map +1 -0
  57. package/dist/connector-ops/override-store.d.ts +7 -0
  58. package/dist/connector-ops/override-store.d.ts.map +1 -0
  59. package/dist/connector-ops/override-store.js +123 -0
  60. package/dist/connector-ops/override-store.js.map +1 -0
  61. package/dist/connector-ops/sanitize.d.ts +16 -0
  62. package/dist/connector-ops/sanitize.d.ts.map +1 -0
  63. package/dist/connector-ops/sanitize.js +48 -0
  64. package/dist/connector-ops/sanitize.js.map +1 -0
  65. package/dist/connector-ops/types.d.ts +76 -0
  66. package/dist/connector-ops/types.d.ts.map +1 -0
  67. package/dist/connector-ops/types.js +12 -0
  68. package/dist/connector-ops/types.js.map +1 -0
  69. package/dist/effective-listing.d.ts +11 -0
  70. package/dist/effective-listing.d.ts.map +1 -0
  71. package/dist/effective-listing.js +41 -0
  72. package/dist/effective-listing.js.map +1 -0
  73. package/dist/errors.d.ts +5 -1
  74. package/dist/errors.d.ts.map +1 -1
  75. package/dist/errors.js +10 -3
  76. package/dist/errors.js.map +1 -1
  77. package/dist/execution-target.d.ts +16 -0
  78. package/dist/execution-target.d.ts.map +1 -1
  79. package/dist/execution-target.js +54 -0
  80. package/dist/execution-target.js.map +1 -1
  81. package/dist/index.d.ts +6 -1
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +6 -1
  84. package/dist/index.js.map +1 -1
  85. package/dist/integrations/index.d.ts +3 -0
  86. package/dist/integrations/index.d.ts.map +1 -0
  87. package/dist/integrations/index.js +3 -0
  88. package/dist/integrations/index.js.map +1 -0
  89. package/dist/integrations/instance-store.d.ts +5 -0
  90. package/dist/integrations/instance-store.d.ts.map +1 -0
  91. package/dist/integrations/instance-store.js +327 -0
  92. package/dist/integrations/instance-store.js.map +1 -0
  93. package/dist/integrations/types.d.ts +92 -0
  94. package/dist/integrations/types.d.ts.map +1 -0
  95. package/dist/integrations/types.js +40 -0
  96. package/dist/integrations/types.js.map +1 -0
  97. package/dist/magit/magit-pack-service.d.ts +436 -70
  98. package/dist/magit/magit-pack-service.d.ts.map +1 -1
  99. package/dist/magit/magit-pack-service.js +949 -202
  100. package/dist/magit/magit-pack-service.js.map +1 -1
  101. package/dist/magit/pack-to-patchset.d.ts +21 -0
  102. package/dist/magit/pack-to-patchset.d.ts.map +1 -1
  103. package/dist/magit/pack-to-patchset.js +29 -0
  104. package/dist/magit/pack-to-patchset.js.map +1 -1
  105. package/dist/magit/package-catalog-bridge.d.ts +4 -14
  106. package/dist/magit/package-catalog-bridge.d.ts.map +1 -1
  107. package/dist/magit/package-catalog-bridge.js +2 -21
  108. package/dist/magit/package-catalog-bridge.js.map +1 -1
  109. package/dist/mgc-packages.d.ts +4 -3
  110. package/dist/mgc-packages.d.ts.map +1 -1
  111. package/dist/mgc-packages.js +4 -3
  112. package/dist/mgc-packages.js.map +1 -1
  113. package/dist/openapi/openapi.json +3060 -135
  114. package/dist/optional-companion-url.d.ts +72 -0
  115. package/dist/optional-companion-url.d.ts.map +1 -0
  116. package/dist/optional-companion-url.js +148 -0
  117. package/dist/optional-companion-url.js.map +1 -0
  118. package/dist/platform.d.ts +29 -0
  119. package/dist/platform.d.ts.map +1 -1
  120. package/dist/platform.js +138 -2
  121. package/dist/platform.js.map +1 -1
  122. package/dist/restricted-store/crypto.d.ts +10 -0
  123. package/dist/restricted-store/crypto.d.ts.map +1 -0
  124. package/dist/restricted-store/crypto.js +43 -0
  125. package/dist/restricted-store/crypto.js.map +1 -0
  126. package/dist/restricted-store/index.d.ts +4 -0
  127. package/dist/restricted-store/index.d.ts.map +1 -0
  128. package/dist/restricted-store/index.js +4 -0
  129. package/dist/restricted-store/index.js.map +1 -0
  130. package/dist/restricted-store/object-store.d.ts +12 -0
  131. package/dist/restricted-store/object-store.d.ts.map +1 -0
  132. package/dist/restricted-store/object-store.js +233 -0
  133. package/dist/restricted-store/object-store.js.map +1 -0
  134. package/dist/restricted-store/types.d.ts +78 -0
  135. package/dist/restricted-store/types.d.ts.map +1 -0
  136. package/dist/restricted-store/types.js +12 -0
  137. package/dist/restricted-store/types.js.map +1 -0
  138. package/dist/routes/catalog.d.ts +4 -0
  139. package/dist/routes/catalog.d.ts.map +1 -0
  140. package/dist/routes/catalog.js +103 -0
  141. package/dist/routes/catalog.js.map +1 -0
  142. package/dist/routes/connector-ops.d.ts +12 -0
  143. package/dist/routes/connector-ops.d.ts.map +1 -0
  144. package/dist/routes/connector-ops.js +160 -0
  145. package/dist/routes/connector-ops.js.map +1 -0
  146. package/dist/routes/integrations.d.ts +5 -0
  147. package/dist/routes/integrations.d.ts.map +1 -0
  148. package/dist/routes/integrations.js +126 -0
  149. package/dist/routes/integrations.js.map +1 -0
  150. package/dist/routes/memory.d.ts.map +1 -1
  151. package/dist/routes/memory.js +9 -2
  152. package/dist/routes/memory.js.map +1 -1
  153. package/dist/routes/metadata.d.ts.map +1 -1
  154. package/dist/routes/metadata.js +459 -186
  155. package/dist/routes/metadata.js.map +1 -1
  156. package/dist/routes/pipelines.d.ts.map +1 -1
  157. package/dist/routes/pipelines.js +3 -2
  158. package/dist/routes/pipelines.js.map +1 -1
  159. package/dist/routes/restricted-store.d.ts +5 -0
  160. package/dist/routes/restricted-store.d.ts.map +1 -0
  161. package/dist/routes/restricted-store.js +117 -0
  162. package/dist/routes/restricted-store.js.map +1 -0
  163. package/openapi/openapi.json +3060 -135
  164. package/package.json +31 -7
package/README.md CHANGED
@@ -7,7 +7,7 @@ Remote apps should **call** this service over HTTP — not reinvent wiring by in
7
7
  ## Install / run
8
8
 
9
9
  ```bash
10
- npm install @x12i/memorix-service@3.0.3 # composition library / CLI
10
+ npm install @x12i/memorix-service@3.4.0 # composition library / CLI
11
11
  ```
12
12
 
13
13
  Prefer the monorepo stack (service + Studio + opx-source):
@@ -33,6 +33,51 @@ MEMORIX_SERVICE_MODE=dev npm run dev # metadata in-memory; durable routes 503
33
33
 
34
34
  Compliance: this process uses **`@x12i/core-service`** (zone port, health, live view, correlation-id).
35
35
 
36
+ ## Dual-mode org blob plane (cloud / on-prem)
37
+
38
+ Not Magit. When storing **org/connector object payloads** that would use cloud buckets,
39
+ on-prem must use **local disk**.
40
+
41
+ | Env | Effect |
42
+ |-----|--------|
43
+ | `MEMORIX_BLOB_BACKEND` | `disk` / `onprem` (default) or `s3` / `cloud` |
44
+ | `MEMORIX_BLOB_ROOT` | Disk root for on-prem (default `.memorix-blobs`) |
45
+ | `MEMORIX_S3_BUCKET` | Required when backend=`s3` |
46
+ | `MEMORIX_RESTRICTED_KEK` | Optional AES-GCM KEK for disk-encrypted restricted bodies |
47
+
48
+ Used by **`/api/restricted-store/v1`** (FG-A3). See
49
+ [restricted-store.md](../docs/connector-framework/restricted-store.md) and
50
+ [integration-registry.md](../docs/connector-framework/integration-registry.md).
51
+
52
+ ## Magit package catalog
53
+
54
+ Default-on when durable Mongo is configured (`METADATA_MAGIT=0` disables).
55
+
56
+ | Mode | Config |
57
+ |------|--------|
58
+ | **A typed store** | `MAGIT_PACKAGE_STORE_SELECTOR` + `MAGIT_PACKAGE_TYPE_ID` |
59
+ | **B flat catalog** | both unset |
60
+
61
+ Requires `@x12i/magit@2.14.0`. Defaults: `MAGIT_CATALOG_TENANT=x12i`, `MAGIT_CATALOG_REPO=memorix`.
62
+
63
+ Ops (provision / verify / recover / channels / smoke): see
64
+ [documentation/magit-typed-store-runbook.md](../documentation/magit-typed-store-runbook.md).
65
+
66
+ ```bash
67
+ npm run catalog:provision -- --out /secure/magit-store.env --confirm-allowed-kinds
68
+ npm run catalog:verify
69
+ npm run catalog:recover -- --store-id st_… --out /secure/magit-store.env
70
+ npm run catalog:list
71
+ npm run magit:cross-env-smoke
72
+ npm run magit:cross-env-smoke -- --publish
73
+ ```
74
+
75
+ **Owner mint:** repo `memorix`, Package stores **empty** until the store exists.
76
+ **Consumer:** store grant + `repoIds: []` (Repositories unchecked).
77
+ Channels and release sets need Mode A + publisher token to promote; consumers only resolve.
78
+
79
+ Env examples: [memorix-service/.env.example](./.env.example). Selector never appears in Studio or `GET /api/diagnostics/scope`.
80
+
36
81
  ## Library exports
37
82
 
38
83
  When embedding the composition root in-process:
@@ -83,8 +128,21 @@ curl -s http://127.0.0.1:5100/api/diagnostics/scope \
83
128
  ### AI-services companions
84
129
 
85
130
  Point memorix-service at FR-compliant processes via env (`FUNCX_URL`, `AI_SKILLS_URL`, `AI_TASKS_URL`, `GRAPH_ENGINE_URL`).
86
- Stack: `AI_SERVICES=1 node scripts/dev-stack.mjs` or `--ai-services`.
87
- Ops: [`.operational/ai-services-get-started.md`](../.operational/ai-services-get-started.md).
131
+ Stack: AI companions are **on by default**; skip with `--no-ai-services` or `AI_SERVICES=0`.
132
+
133
+ ### Vendor pipeline workers (opt-in)
134
+
135
+ Archetype-A HTTP companions invoke via `POST {origin}/pipeline`. Inject **base origin only** (no `/pipeline` path). Soft-skip when URL unset; fail-closed when set (`src/optional-companion-url.ts`).
136
+
137
+ | Suite | Stack flag | Client env |
138
+ |-------|------------|------------|
139
+ | Exellix Apollo + M365 | `--exellix-connectors` / `EXELLIX_CONNECTORS=1` | `EXELLIX_APOLLO_READ_URL`, `EXELLIX_APOLLO_ACTIONS_URL`, `EXELLIX_M365_USER_READ_URL`, `EXELLIX_M365_USER_ACTION_URL` (ports 9711–9722, zone `exellix-connectors`) |
140
+ | Neo security workers | `--neo-connectors` / `NEO_CONNECTORS=1` | `NEO_FIREWALL_URL`, `NEO_XDR_URL`, `NEO_NESSUS_URL`, `NEO_ENTRA_URL`, `NEO_SPLUNK_URL`, `NEO_CROWDSTRIKE_URL` (frozen ports; no zone remap) |
141
+ | Neo status UI | `--neo-status-ui` / `NEO_STATUS_UI=1` | `NEO_STATUS_UI_URL` (:9001) |
142
+
143
+ Optional hard gates: `EXELLIX_CONNECTORS_REQUIRED=1`, `NEO_CONNECTORS_REQUIRED=1`.
144
+
145
+ **Neo packages** ship on GitHub Packages. Local install needs `.npmrc` scope + `NODE_AUTH_TOKEN` (see [`.npmrc.example`](../.npmrc.example)).
88
146
 
89
147
  ### Memory (operator + called-service)
90
148
 
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAIA,OAAO,OAAO,EAAE,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAIxD,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAsBvB,MAAM,MAAM,8BAA8B,GAAG,YAAY,GAAG;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B,CAAC;AAEF,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,8BAA8B,GACnC,OAAO,CAAC;IAAE,GAAG,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAuF5E;AAED,MAAM,MAAM,0BAA0B,GAAG,8BAA8B,GAAG;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,0BAA0B;;;;;GAM7E"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAIA,OAAO,OAAO,EAAE,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAIxD,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AA0BvB,MAAM,MAAM,8BAA8B,GAAG,YAAY,GAAG;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B,CAAC;AAEF,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,8BAA8B,GACnC,OAAO,CAAC;IAAE,GAAG,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA2F5E;AAED,MAAM,MAAM,0BAA0B,GAAG,8BAA8B,GAAG;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,0BAA0B;;;;;GAM7E"}
package/dist/app.js CHANGED
@@ -9,10 +9,14 @@ import { mapErrorToHttp, redactSecrets } from "./errors.js";
9
9
  import { createMemorixPlatform, } from "./platform.js";
10
10
  import { resolveScope } from "./request-scope.js";
11
11
  import { registerMetadataRoutes } from "./routes/metadata.js";
12
+ import { registerCatalogRoutes } from "./routes/catalog.js";
12
13
  import { registerDataRoutes } from "./routes/data.js";
13
14
  import { registerRelationshipRoutes } from "./routes/relationships.js";
14
15
  import { registerMemoryRoutes } from "./routes/memory.js";
15
16
  import { registerConnectorInvocationRoutes } from "./routes/connector-invocations.js";
17
+ import { registerConnectorOpsRoutes } from "./routes/connector-ops.js";
18
+ import { registerIntegrationRoutes } from "./routes/integrations.js";
19
+ import { registerRestrictedStoreRoutes } from "./routes/restricted-store.js";
16
20
  import { registerPipelineRoutes } from "./routes/pipelines.js";
17
21
  import { registerJobsRoutes } from "./routes/jobs.js";
18
22
  import { registerOperationsRoutes } from "./routes/operations.js";
@@ -88,10 +92,14 @@ export async function createMemorixServiceApp(opts) {
88
92
  });
89
93
  registerSimulationRoutes(app, simulation);
90
94
  await registerMetadataRoutes(app, platform);
95
+ await registerCatalogRoutes(app, platform);
91
96
  await registerDataRoutes(app, platform);
92
97
  await registerRelationshipRoutes(app, platform);
93
98
  await registerMemoryRoutes(app, platform);
94
99
  await registerConnectorInvocationRoutes(app, platform);
100
+ await registerConnectorOpsRoutes(app, platform);
101
+ await registerIntegrationRoutes(app, platform);
102
+ await registerRestrictedStoreRoutes(app, platform);
95
103
  await registerPipelineRoutes(app, platform);
96
104
  await registerJobsRoutes(app, platform);
97
105
  await registerOperationsRoutes(app, platform);
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type S3BlobClient } from "./s3.js";
2
+ import type { BlobBackendKind, BlobObjectStore } from "./types.js";
3
+ export type BlobStoreConfig = {
4
+ backend: BlobBackendKind;
5
+ /** disk root (absolute). */
6
+ rootDir?: string;
7
+ s3Bucket?: string;
8
+ s3Prefix?: string;
9
+ s3Sse?: "AES256" | "aws:kms" | false;
10
+ s3KmsKeyId?: string;
11
+ };
12
+ /**
13
+ * Resolve blob backend from env.
14
+ * - disk (default / on-prem): local filesystem
15
+ * - s3 (cloud): S3-compatible bucket required
16
+ * - memory: tests / explicit only
17
+ */
18
+ export declare function resolveBlobStoreConfig(env?: NodeJS.ProcessEnv): BlobStoreConfig;
19
+ export type CreatePlatformBlobStoreOptions = {
20
+ env?: NodeJS.ProcessEnv;
21
+ /** Inject S3 client (tests). */
22
+ s3Client?: S3BlobClient;
23
+ /** Force memory backend (unit tests). */
24
+ forceMemory?: boolean;
25
+ };
26
+ /**
27
+ * Create the process-wide BlobObjectStore used by restricted store bodies.
28
+ * Fail-closed: s3 without bucket throws.
29
+ */
30
+ export declare function createPlatformBlobStore(opts?: CreatePlatformBlobStoreOptions): Promise<BlobObjectStore>;
31
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/blob-store/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,eAAe,CAAC;IACzB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,eAAe,CAgCjB;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,GAAE,8BAAmC,GACxC,OAAO,CAAC,eAAe,CAAC,CA2B1B"}
@@ -0,0 +1,68 @@
1
+ import { resolve } from "node:path";
2
+ import { createDiskBlobStore } from "./disk.js";
3
+ import { createMemoryBlobStore } from "./memory.js";
4
+ import { createAwsS3BlobClientFromEnv, createS3BlobStore, } from "./s3.js";
5
+ /**
6
+ * Resolve blob backend from env.
7
+ * - disk (default / on-prem): local filesystem
8
+ * - s3 (cloud): S3-compatible bucket required
9
+ * - memory: tests / explicit only
10
+ */
11
+ export function resolveBlobStoreConfig(env = process.env) {
12
+ const raw = (env.MEMORIX_BLOB_BACKEND ?? "disk").trim().toLowerCase();
13
+ let backend;
14
+ if (raw === "s3" || raw === "cloud")
15
+ backend = "s3";
16
+ else if (raw === "memory")
17
+ backend = "memory";
18
+ else if (raw === "disk" || raw === "onprem" || raw === "on-prem")
19
+ backend = "disk";
20
+ else {
21
+ throw new Error(`MEMORIX_BLOB_BACKEND must be s3|disk|memory (or cloud|onprem), got "${raw}"`);
22
+ }
23
+ const rootDir = resolve(env.MEMORIX_BLOB_ROOT?.trim() || resolve(process.cwd(), ".memorix-blobs"));
24
+ const s3SseRaw = env.MEMORIX_S3_SSE?.trim();
25
+ let s3Sse = "AES256";
26
+ if (s3SseRaw === "0" || s3SseRaw === "false" || s3SseRaw === "none") {
27
+ s3Sse = false;
28
+ }
29
+ else if (s3SseRaw === "aws:kms" || s3SseRaw === "kms") {
30
+ s3Sse = "aws:kms";
31
+ }
32
+ return {
33
+ backend,
34
+ rootDir,
35
+ s3Bucket: env.MEMORIX_S3_BUCKET?.trim() || undefined,
36
+ s3Prefix: env.MEMORIX_S3_PREFIX?.trim() || "memorix",
37
+ s3Sse,
38
+ s3KmsKeyId: env.MEMORIX_S3_KMS_KEY_ID?.trim() || undefined,
39
+ };
40
+ }
41
+ /**
42
+ * Create the process-wide BlobObjectStore used by restricted store bodies.
43
+ * Fail-closed: s3 without bucket throws.
44
+ */
45
+ export async function createPlatformBlobStore(opts = {}) {
46
+ if (opts.forceMemory)
47
+ return createMemoryBlobStore();
48
+ const env = opts.env ?? process.env;
49
+ const cfg = resolveBlobStoreConfig(env);
50
+ if (cfg.backend === "memory")
51
+ return createMemoryBlobStore();
52
+ if (cfg.backend === "disk") {
53
+ return createDiskBlobStore({ rootDir: cfg.rootDir });
54
+ }
55
+ // s3
56
+ if (!cfg.s3Bucket) {
57
+ throw new Error("MEMORIX_BLOB_BACKEND=s3 requires MEMORIX_S3_BUCKET (cloud object store)");
58
+ }
59
+ const client = opts.s3Client ?? (await createAwsS3BlobClientFromEnv(env));
60
+ return createS3BlobStore({
61
+ bucket: cfg.s3Bucket,
62
+ prefix: cfg.s3Prefix,
63
+ client,
64
+ serverSideEncryption: cfg.s3Sse,
65
+ sseKmsKeyId: cfg.s3KmsKeyId,
66
+ });
67
+ }
68
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/blob-store/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type BlobObjectStore } from "./types.js";
2
+ export type DiskBlobStoreOptions = {
3
+ rootDir: string;
4
+ };
5
+ /**
6
+ * On-prem object store: `{root}/{orgId}/{key...}`.
7
+ * Atomic write via tmp + rename. Never walks outside root.
8
+ */
9
+ export declare function createDiskBlobStore(opts: DiskBlobStoreOptions): BlobObjectStore;
10
+ //# sourceMappingURL=disk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../src/blob-store/disk.ts"],"names":[],"mappings":"AAUA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,oBAAoB,GACzB,eAAe,CAgFjB"}
@@ -0,0 +1,104 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, readFile, rename, stat, unlink, writeFile, } from "node:fs/promises";
3
+ import { dirname, join, resolve, sep } from "node:path";
4
+ import { assertSafeBlobKey, assertSafeOrgId, } from "./types.js";
5
+ function resolveObjectPath(rootDir, orgId, key) {
6
+ const org = assertSafeOrgId(orgId);
7
+ const safeKey = assertSafeBlobKey(key);
8
+ const root = resolve(rootDir);
9
+ const full = resolve(join(root, org, ...safeKey.split("/")));
10
+ const prefix = root.endsWith(sep) ? root : root + sep;
11
+ if (full !== root && !full.startsWith(prefix)) {
12
+ throw new Error("blob path escape rejected");
13
+ }
14
+ return full;
15
+ }
16
+ /**
17
+ * On-prem object store: `{root}/{orgId}/{key...}`.
18
+ * Atomic write via tmp + rename. Never walks outside root.
19
+ */
20
+ export function createDiskBlobStore(opts) {
21
+ const rootDir = resolve(opts.rootDir);
22
+ return {
23
+ backend: "disk",
24
+ async put(orgId, key, body, putOpts) {
25
+ const path = resolveObjectPath(rootDir, orgId, key);
26
+ await mkdir(dirname(path), { recursive: true });
27
+ const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
28
+ await writeFile(tmp, body);
29
+ await rename(tmp, path);
30
+ const contentType = putOpts?.contentType;
31
+ if (contentType) {
32
+ await writeFile(`${path}.meta.json`, JSON.stringify({ contentType }), "utf8");
33
+ }
34
+ const digest = createHash("sha256").update(body).digest("hex");
35
+ return {
36
+ backend: "disk",
37
+ orgId: assertSafeOrgId(orgId),
38
+ key: assertSafeBlobKey(key),
39
+ sizeBytes: body.byteLength,
40
+ contentType,
41
+ etag: `sha256:${digest}`,
42
+ };
43
+ },
44
+ async get(orgId, key) {
45
+ const path = resolveObjectPath(rootDir, orgId, key);
46
+ try {
47
+ return await readFile(path);
48
+ }
49
+ catch (err) {
50
+ if (err.code === "ENOENT")
51
+ return null;
52
+ throw err;
53
+ }
54
+ },
55
+ async head(orgId, key) {
56
+ const path = resolveObjectPath(rootDir, orgId, key);
57
+ try {
58
+ const st = await stat(path);
59
+ let contentType;
60
+ try {
61
+ const metaRaw = await readFile(`${path}.meta.json`, "utf8");
62
+ const meta = JSON.parse(metaRaw);
63
+ contentType = meta.contentType;
64
+ }
65
+ catch {
66
+ /* no meta */
67
+ }
68
+ const buf = await readFile(path);
69
+ const digest = createHash("sha256").update(buf).digest("hex");
70
+ return {
71
+ orgId: assertSafeOrgId(orgId),
72
+ key: assertSafeBlobKey(key),
73
+ sizeBytes: st.size,
74
+ contentType,
75
+ etag: `sha256:${digest}`,
76
+ };
77
+ }
78
+ catch (err) {
79
+ if (err.code === "ENOENT")
80
+ return null;
81
+ throw err;
82
+ }
83
+ },
84
+ async delete(orgId, key) {
85
+ const path = resolveObjectPath(rootDir, orgId, key);
86
+ try {
87
+ await unlink(path);
88
+ try {
89
+ await unlink(`${path}.meta.json`);
90
+ }
91
+ catch {
92
+ /* ignore meta */
93
+ }
94
+ return true;
95
+ }
96
+ catch (err) {
97
+ if (err.code === "ENOENT")
98
+ return false;
99
+ throw err;
100
+ }
101
+ },
102
+ };
103
+ }
104
+ //# sourceMappingURL=disk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disk.js","sourceRoot":"","sources":["../../src/blob-store/disk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from "./types.js";
2
+ export { createDiskBlobStore } from "./disk.js";
3
+ export { createMemoryBlobStore } from "./memory.js";
4
+ export { createS3BlobStore, createAwsS3BlobClientFromEnv, type S3BlobClient, type S3BlobStoreOptions, } from "./s3.js";
5
+ export { resolveBlobStoreConfig, createPlatformBlobStore, type BlobStoreConfig, type CreatePlatformBlobStoreOptions, } from "./config.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blob-store/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,8BAA8B,GACpC,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from "./types.js";
2
+ export { createDiskBlobStore } from "./disk.js";
3
+ export { createMemoryBlobStore } from "./memory.js";
4
+ export { createS3BlobStore, createAwsS3BlobClientFromEnv, } from "./s3.js";
5
+ export { resolveBlobStoreConfig, createPlatformBlobStore, } from "./config.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blob-store/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,4BAA4B,GAG7B,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GAGxB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type BlobObjectStore } from "./types.js";
2
+ /** In-process blob store for unit tests and no-mongo dev. */
3
+ export declare function createMemoryBlobStore(): BlobObjectStore;
4
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/blob-store/memory.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,YAAY,CAAC;AAOpB,6DAA6D;AAC7D,wBAAgB,qBAAqB,IAAI,eAAe,CAgDvD"}
@@ -0,0 +1,47 @@
1
+ import { createHash } from "node:crypto";
2
+ import { assertSafeBlobKey, assertSafeOrgId, } from "./types.js";
3
+ /** In-process blob store for unit tests and no-mongo dev. */
4
+ export function createMemoryBlobStore() {
5
+ const map = new Map();
6
+ const id = (orgId, key) => `${assertSafeOrgId(orgId)}\0${assertSafeBlobKey(key)}`;
7
+ return {
8
+ backend: "memory",
9
+ async put(orgId, key, body, opts) {
10
+ const k = id(orgId, key);
11
+ map.set(k, {
12
+ body: Buffer.from(body),
13
+ contentType: opts?.contentType,
14
+ });
15
+ const digest = createHash("sha256").update(body).digest("hex");
16
+ return {
17
+ backend: "memory",
18
+ orgId: assertSafeOrgId(orgId),
19
+ key: assertSafeBlobKey(key),
20
+ sizeBytes: body.byteLength,
21
+ contentType: opts?.contentType,
22
+ etag: `sha256:${digest}`,
23
+ };
24
+ },
25
+ async get(orgId, key) {
26
+ const e = map.get(id(orgId, key));
27
+ return e ? Buffer.from(e.body) : null;
28
+ },
29
+ async head(orgId, key) {
30
+ const e = map.get(id(orgId, key));
31
+ if (!e)
32
+ return null;
33
+ const digest = createHash("sha256").update(e.body).digest("hex");
34
+ return {
35
+ orgId: assertSafeOrgId(orgId),
36
+ key: assertSafeBlobKey(key),
37
+ sizeBytes: e.body.byteLength,
38
+ contentType: e.contentType,
39
+ etag: `sha256:${digest}`,
40
+ };
41
+ },
42
+ async delete(orgId, key) {
43
+ return map.delete(id(orgId, key));
44
+ },
45
+ };
46
+ }
47
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/blob-store/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,iBAAiB,EACjB,eAAe,GAGhB,MAAM,YAAY,CAAC;AAOpB,6DAA6D;AAC7D,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAiB,CAAC;IAErC,MAAM,EAAE,GAAG,CAAC,KAAa,EAAE,GAAW,EAAE,EAAE,CACxC,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;IAEzD,OAAO;QACL,OAAO,EAAE,QAAQ;QAEjB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI;YAC9B,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;gBACT,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACvB,WAAW,EAAE,IAAI,EAAE,WAAW;aAC/B,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/D,OAAO;gBACL,OAAO,EAAE,QAAQ;gBACjB,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;gBAC7B,GAAG,EAAE,iBAAiB,CAAC,GAAG,CAAC;gBAC3B,SAAS,EAAE,IAAI,CAAC,UAAU;gBAC1B,WAAW,EAAE,IAAI,EAAE,WAAW;gBAC9B,IAAI,EAAE,UAAU,MAAM,EAAE;aACD,CAAC;QAC5B,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG;YAClB,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YAClC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxC,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG;YACnB,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpB,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjE,OAAO;gBACL,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;gBAC7B,GAAG,EAAE,iBAAiB,CAAC,GAAG,CAAC;gBAC3B,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU;gBAC5B,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,IAAI,EAAE,UAAU,MAAM,EAAE;aACzB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG;YACrB,OAAO,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { type BlobObjectStore } from "./types.js";
2
+ /** Minimal S3 client surface so tests can inject mocks without network. */
3
+ export type S3BlobClient = {
4
+ putObject(input: {
5
+ Bucket: string;
6
+ Key: string;
7
+ Body: Buffer;
8
+ ContentType?: string;
9
+ ServerSideEncryption?: string;
10
+ SSEKMSKeyId?: string;
11
+ }): Promise<{
12
+ ETag?: string;
13
+ }>;
14
+ getObject(input: {
15
+ Bucket: string;
16
+ Key: string;
17
+ }): Promise<{
18
+ Body?: Uint8Array | Buffer | null;
19
+ ContentType?: string;
20
+ } | null>;
21
+ headObject(input: {
22
+ Bucket: string;
23
+ Key: string;
24
+ }): Promise<{
25
+ ContentLength?: number;
26
+ ContentType?: string;
27
+ ETag?: string;
28
+ } | null>;
29
+ deleteObject(input: {
30
+ Bucket: string;
31
+ Key: string;
32
+ }): Promise<void>;
33
+ };
34
+ export type S3BlobStoreOptions = {
35
+ bucket: string;
36
+ /** Optional key prefix (no leading/trailing slash required). */
37
+ prefix?: string;
38
+ client: S3BlobClient;
39
+ /** Default AES256 (SSE-S3). Set false to disable. */
40
+ serverSideEncryption?: "AES256" | "aws:kms" | false;
41
+ sseKmsKeyId?: string;
42
+ };
43
+ /**
44
+ * Cloud object store (S3-compatible). Bodies never touch local disk.
45
+ * Pass a real AWS SDK client or a test double via `client`.
46
+ */
47
+ export declare function createS3BlobStore(opts: S3BlobStoreOptions): BlobObjectStore;
48
+ /**
49
+ * Build SDK client from env when backend=s3. Lazy-imports @aws-sdk/client-s3.
50
+ */
51
+ export declare function createAwsS3BlobClientFromEnv(env?: NodeJS.ProcessEnv): Promise<S3BlobClient>;
52
+ //# sourceMappingURL=s3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/blob-store/s3.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,YAAY,CAAC;AAEpB,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,KAAK,EAAE;QACf,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/B,SAAS,CAAC,KAAK,EAAE;QACf,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,GAAG,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAChF,UAAU,CAAC,KAAK,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,GAAG,OAAO,CAAC;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACpF,YAAY,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,qDAAqD;IACrD,oBAAoB,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAUF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,eAAe,CAqE3E;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,YAAY,CAAC,CAqEvB"}