@x12i/catalox 2.7.0 → 3.1.1

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 (137) hide show
  1. package/README.md +73 -31
  2. package/dist/src/catalox/authorization.js +1 -1
  3. package/dist/src/catalox/authorization.js.map +1 -1
  4. package/dist/src/catalox/catalog-lifecycle.d.ts +29 -0
  5. package/dist/src/catalox/catalog-lifecycle.d.ts.map +1 -0
  6. package/dist/src/catalox/catalog-lifecycle.js +480 -0
  7. package/dist/src/catalox/catalog-lifecycle.js.map +1 -0
  8. package/dist/src/catalox/catalox-bound.d.ts +135 -0
  9. package/dist/src/catalox/catalox-bound.d.ts.map +1 -0
  10. package/dist/src/catalox/catalox-bound.js +190 -0
  11. package/dist/src/catalox/catalox-bound.js.map +1 -0
  12. package/dist/src/catalox/catalox.d.ts +34 -4
  13. package/dist/src/catalox/catalox.d.ts.map +1 -1
  14. package/dist/src/catalox/catalox.js +508 -72
  15. package/dist/src/catalox/catalox.js.map +1 -1
  16. package/dist/src/catalox/context.js +2 -2
  17. package/dist/src/catalox/context.js.map +1 -1
  18. package/dist/src/catalox/create-catalox.d.ts +28 -0
  19. package/dist/src/catalox/create-catalox.d.ts.map +1 -0
  20. package/dist/src/catalox/create-catalox.js +90 -0
  21. package/dist/src/catalox/create-catalox.js.map +1 -0
  22. package/dist/src/catalox/index.d.ts +4 -0
  23. package/dist/src/catalox/index.d.ts.map +1 -1
  24. package/dist/src/catalox/index.js +4 -0
  25. package/dist/src/catalox/index.js.map +1 -1
  26. package/dist/src/catalox/native-catalog-merge.d.ts +12 -0
  27. package/dist/src/catalox/native-catalog-merge.d.ts.map +1 -0
  28. package/dist/src/catalox/native-catalog-merge.js +102 -0
  29. package/dist/src/catalox/native-catalog-merge.js.map +1 -0
  30. package/dist/src/catalox/native-scope.d.ts +28 -0
  31. package/dist/src/catalox/native-scope.d.ts.map +1 -0
  32. package/dist/src/catalox/native-scope.js +184 -0
  33. package/dist/src/catalox/native-scope.js.map +1 -0
  34. package/dist/src/catalox/record-history.d.ts +53 -0
  35. package/dist/src/catalox/record-history.d.ts.map +1 -0
  36. package/dist/src/catalox/record-history.js +158 -0
  37. package/dist/src/catalox/record-history.js.map +1 -0
  38. package/dist/src/cli/index.js +148 -42
  39. package/dist/src/cli/index.js.map +1 -1
  40. package/dist/src/contracts/apps.d.ts +2 -0
  41. package/dist/src/contracts/apps.d.ts.map +1 -1
  42. package/dist/src/contracts/catalog-lifecycle.d.ts +70 -0
  43. package/dist/src/contracts/catalog-lifecycle.d.ts.map +1 -0
  44. package/dist/src/contracts/catalog-lifecycle.js +2 -0
  45. package/dist/src/contracts/catalog-lifecycle.js.map +1 -0
  46. package/dist/src/contracts/catalogs.d.ts +54 -0
  47. package/dist/src/contracts/catalogs.d.ts.map +1 -1
  48. package/dist/src/contracts/catalogs.js.map +1 -1
  49. package/dist/src/contracts/context.d.ts +5 -1
  50. package/dist/src/contracts/context.d.ts.map +1 -1
  51. package/dist/src/contracts/descriptors.d.ts +6 -0
  52. package/dist/src/contracts/descriptors.d.ts.map +1 -1
  53. package/dist/src/contracts/index.d.ts +5 -2
  54. package/dist/src/contracts/index.d.ts.map +1 -1
  55. package/dist/src/contracts/index.js.map +1 -1
  56. package/dist/src/contracts/items.d.ts +19 -0
  57. package/dist/src/contracts/items.d.ts.map +1 -1
  58. package/dist/src/contracts/record-history.d.ts +66 -0
  59. package/dist/src/contracts/record-history.d.ts.map +1 -0
  60. package/dist/src/contracts/record-history.js +2 -0
  61. package/dist/src/contracts/record-history.js.map +1 -0
  62. package/dist/src/embedder.d.ts +17 -0
  63. package/dist/src/embedder.d.ts.map +1 -0
  64. package/dist/src/embedder.js +17 -0
  65. package/dist/src/embedder.js.map +1 -0
  66. package/dist/src/firebase/adapter-store.d.ts +1 -0
  67. package/dist/src/firebase/adapter-store.d.ts.map +1 -1
  68. package/dist/src/firebase/adapter-store.js +3 -0
  69. package/dist/src/firebase/adapter-store.js.map +1 -1
  70. package/dist/src/firebase/binding-store.d.ts +2 -0
  71. package/dist/src/firebase/binding-store.d.ts.map +1 -1
  72. package/dist/src/firebase/binding-store.js +10 -0
  73. package/dist/src/firebase/binding-store.js.map +1 -1
  74. package/dist/src/firebase/catalog-data-index-store.d.ts +1 -0
  75. package/dist/src/firebase/catalog-data-index-store.d.ts.map +1 -1
  76. package/dist/src/firebase/catalog-data-index-store.js +3 -0
  77. package/dist/src/firebase/catalog-data-index-store.js.map +1 -1
  78. package/dist/src/firebase/catalog-item-history-store.d.ts +21 -0
  79. package/dist/src/firebase/catalog-item-history-store.d.ts.map +1 -0
  80. package/dist/src/firebase/catalog-item-history-store.js +61 -0
  81. package/dist/src/firebase/catalog-item-history-store.js.map +1 -0
  82. package/dist/src/firebase/catalog-store.d.ts +1 -0
  83. package/dist/src/firebase/catalog-store.d.ts.map +1 -1
  84. package/dist/src/firebase/catalog-store.js +3 -0
  85. package/dist/src/firebase/catalog-store.js.map +1 -1
  86. package/dist/src/firebase/index.d.ts +1 -0
  87. package/dist/src/firebase/index.d.ts.map +1 -1
  88. package/dist/src/firebase/index.js +1 -0
  89. package/dist/src/firebase/index.js.map +1 -1
  90. package/dist/src/firebase/mapping-store.d.ts +1 -0
  91. package/dist/src/firebase/mapping-store.d.ts.map +1 -1
  92. package/dist/src/firebase/mapping-store.js +3 -0
  93. package/dist/src/firebase/mapping-store.js.map +1 -1
  94. package/dist/src/firebase/native-item-store.d.ts +8 -2
  95. package/dist/src/firebase/native-item-store.d.ts.map +1 -1
  96. package/dist/src/firebase/native-item-store.js +22 -6
  97. package/dist/src/firebase/native-item-store.js.map +1 -1
  98. package/dist/src/firebase/reference-store.d.ts +3 -0
  99. package/dist/src/firebase/reference-store.d.ts.map +1 -1
  100. package/dist/src/firebase/reference-store.js +16 -0
  101. package/dist/src/firebase/reference-store.js.map +1 -1
  102. package/dist/src/firebase/renderer-snippet-store.d.ts +3 -0
  103. package/dist/src/firebase/renderer-snippet-store.d.ts.map +1 -1
  104. package/dist/src/firebase/renderer-snippet-store.js +17 -0
  105. package/dist/src/firebase/renderer-snippet-store.js.map +1 -1
  106. package/dist/src/firebase/snapshot-store.d.ts +1 -0
  107. package/dist/src/firebase/snapshot-store.d.ts.map +1 -1
  108. package/dist/src/firebase/snapshot-store.js +8 -0
  109. package/dist/src/firebase/snapshot-store.js.map +1 -1
  110. package/dist/src/index.d.ts +2 -15
  111. package/dist/src/index.d.ts.map +1 -1
  112. package/dist/src/index.js +2 -15
  113. package/dist/src/index.js.map +1 -1
  114. package/dist/src/operator.d.ts +24 -0
  115. package/dist/src/operator.d.ts.map +1 -0
  116. package/dist/src/operator.js +25 -0
  117. package/dist/src/operator.js.map +1 -0
  118. package/dist/test/integration/firestore.emulator.test.js +16 -29
  119. package/dist/test/integration/firestore.emulator.test.js.map +1 -1
  120. package/dist/test/integration/record-history.live.test.d.ts +2 -0
  121. package/dist/test/integration/record-history.live.test.d.ts.map +1 -0
  122. package/dist/test/integration/record-history.live.test.js +126 -0
  123. package/dist/test/integration/record-history.live.test.js.map +1 -0
  124. package/dist/test/unit/native-catalog-merge.test.d.ts +2 -0
  125. package/dist/test/unit/native-catalog-merge.test.d.ts.map +1 -0
  126. package/dist/test/unit/native-catalog-merge.test.js +33 -0
  127. package/dist/test/unit/native-catalog-merge.test.js.map +1 -0
  128. package/dist/test/unit/native-scope.test.d.ts +2 -0
  129. package/dist/test/unit/native-scope.test.d.ts.map +1 -0
  130. package/dist/test/unit/native-scope.test.js +29 -0
  131. package/dist/test/unit/native-scope.test.js.map +1 -0
  132. package/dist/test/unit/record-history-path.test.d.ts +2 -0
  133. package/dist/test/unit/record-history-path.test.d.ts.map +1 -0
  134. package/dist/test/unit/record-history-path.test.js +24 -0
  135. package/dist/test/unit/record-history-path.test.js.map +1 -0
  136. package/firestore.indexes.json +39 -0
  137. package/package.json +23 -6
package/README.md CHANGED
@@ -8,6 +8,8 @@ Catalox is a **data-tier** package for managing **app-scoped catalogs** in Fireb
8
8
  - **Mapped catalogs** (items normalized from MongoDB or APIs)
9
9
  - **References + validation contracts** (standardized cross-catalog shapes)
10
10
  - **Seed/import/export + batch upsert** workflows for native catalogs
11
+ - **Optional per-record native history** — NDJSON payloads in GCS plus a Firestore `catalogItemHistory` index; list/show/restore/replay APIs and `catalox history …` ([`docs/record-history.md`](docs/record-history.md))
12
+ - **Optional catalog lifecycle** — hard delete (with manifest), restore from manifest, and hard rename across collections; APIs + `catalox catalog …` ([`docs/catalog-crud.md`](docs/catalog-crud.md))
11
13
  - **Optional GCS tools** — NDJSON export/import of Firestore collections to a bucket, **compare** live data vs bucket snapshots, **`backupData` mode `gcs`** (Catalox-shaped NDJSON + manifest under a bucket prefix), and matching CLI commands (`firestore export-gcs`, `import-gcs`, `compare-gcs`, `firestore backup --mode gcs`; see [`docs/firestore-gcs-export.md`](docs/firestore-gcs-export.md), [`docs/backup.md`](docs/backup.md))
12
14
 
13
15
  Catalox **does not** own UI, workflow orchestration, remote execution, artifact blobs, or secret storage.
@@ -23,6 +25,16 @@ This repo is currently set up as a workspace package.
23
25
 
24
26
  **Direct dependency:** `@google-cloud/storage` is declared for GCS export/import/compare; it uses the same **Application Default Credentials** pattern as Firestore Admin (bucket IAM required).
25
27
 
28
+ ### Package exports (v3)
29
+
30
+ | Import path | Intended use |
31
+ |-------------|----------------|
32
+ | **`@x12i/catalox`** | Full surface: embedder API + operator tooling (markdown, diagrams, migrations, Firebase stores, backup/GCS helpers, etc.). |
33
+ | **`@x12i/catalox/embedder`** | Catalog runtime only: **`createCatalox`**, **`Catalox`**, **`withContext` / `CataloxBound`**, contracts, errors, adapters, **`validateMappingSpec` / `executeMapping`**. |
34
+ | **`@x12i/catalox/operator`** | Markdown/diagrams/JSX, validation, bindings, **`ContextResolver`**, backup/GCS transfer helpers, identity/json-io, etc. |
35
+ | **`@x12i/catalox/firebase`** | Firestore-backed store classes for advanced wiring. |
36
+ | **`@x12i/catalox/mapping`** | Full mapping module (including **`helper-gap-report`**). |
37
+
26
38
  ## Configuration (real connections)
27
39
 
28
40
  Catalox is a library: you provide initialized clients + runtime env. For a **full list of environment variables**, CLI vs library behavior, and integration-test requirements, see [`docs/environment.md`](docs/environment.md).
@@ -73,6 +85,9 @@ GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
73
85
  FIREBASE_SERVICE_ACCOUNT_PATH=/path/to/service-account.json
74
86
  FIREBASE_PROJECT_ID=your-project-id
75
87
  FIRESTORE_LIVE_TESTS=1
88
+ # Optional: record-history live test + CLI (`createCatalox`); use a dedicated test bucket:
89
+ # CATALOX_RECORD_HISTORY_BUCKET=your-test-bucket
90
+ # CATALOX_RECORD_HISTORY_PREFIX=catalox-record-history/
76
91
  # Optional defaults for the packaged `catalox` CLI (Catalox app/store context, not GCP):
77
92
  # CATALOX_APP_ID=myAppId
78
93
  # CATALOX_STORE_ID=myStoreId
@@ -87,7 +102,10 @@ The `catalox` binary loads `.env` via `dotenv`. Use **`CATALOX_*`** for **Catalo
87
102
  - **`CATALOX_APP_ID`** — Default `appId` in CLI context when a command does not pass `--app` (when present, `--app` overrides).
88
103
  - **`CATALOX_STORE_ID`** — Default `storeId` for **`report`** and **`export`** when `--store` is omitted (`--store` overrides).
89
104
  - **`CATALOX_USER_ID`** — Optional user id / actor for authz-sensitive CLI paths.
90
- - **`CATALOX_MONGO_URI`** — If set, enables the Mongo catalog adapter in the CLI (see `createCatalox()` in `src/cli/index.ts`).
105
+ - **`CATALOX_MONGO_URI`** — If set, enables the Mongo catalog adapter in the CLI (wired via **`createCatalox`** in `src/catalox/create-catalox.ts`, called from `src/cli/index.ts`).
106
+ - **`CATALOX_RECORD_HISTORY_BUCKET`** — If set, **`createCatalox`** wires **`recordHistory`** (GCS payloads + **`catalogItemHistory`** on native writes; also required for **`catalox history …`** to persist new events).
107
+ - **`CATALOX_RECORD_HISTORY_PREFIX`** — Optional GCS prefix for record history (default `catalox-record-history/`).
108
+ - **`CATALOX_RECORD_HISTORY_FAIL_CLOSED`** — When **`1`**, failed history writes fail the parent Firestore mutation.
91
109
 
92
110
  **Running commands from this repository:** the shell command `catalox` is only on your `PATH` if the package is installed globally (`npm i -g @x12i/catalox`) or linked (`npm link` from this repo). Otherwise, after `npm run build`, use:
93
111
 
@@ -110,6 +128,13 @@ npm run cli -- firestore report-native-layout --app "narrix"
110
128
  | `firestore export-gcs` / `import-gcs` | NDJSON per collection + optional manifest ([`docs/firestore-gcs-export.md`](docs/firestore-gcs-export.md)). |
111
129
  | `firestore compare-gcs` | Diff live Firestore vs bucket NDJSON (single collection or manifest). |
112
130
 
131
+ #### `history` / `catalog` CLI (3.1+)
132
+
133
+ | Command | Purpose |
134
+ |---------|---------|
135
+ | `history list` / `history show` / `history restore` / `history replay` | Per-record native history from **`catalogItemHistory`** + GCS ([`docs/record-history.md`](docs/record-history.md)). |
136
+ | `catalog delete` / `catalog restore` / `catalog rename` | Hard delete with manifest, restore from manifest, or hard rename ([`docs/catalog-crud.md`](docs/catalog-crud.md)). |
137
+
113
138
  ## Firestore data model (logical collections)
114
139
 
115
140
  For a **full layout** (subcollections, document id conventions, snapshot runs, and query notes), see [`docs/firestore-data-model.md`](docs/firestore-data-model.md). For **native** catalogs specifically (per-catalog `catalogData-*-items`, layout resolution, `listCatalogItems`, filters, troubleshooting), see [`docs/native-catalog-storage-and-api.md`](docs/native-catalog-storage-and-api.md).
@@ -126,6 +151,7 @@ Metadata:
126
151
  - `catalogDescriptors/{catalogId}` (**descriptor metadata** for generic consumption)
127
152
  - `catalogRendererSnippets/{catalogId}:{role}[:{mode}]` (**stored renderer snippets** for list/grid/item/report/dashboard rendering)
128
153
  - `catalogReferences/{referenceId}` (standardized reference records)
154
+ - `catalogItemHistory/{eventId}` (optional **native write history** index; payloads in GCS — [`docs/record-history.md`](docs/record-history.md))
129
155
 
130
156
  Data:
131
157
 
@@ -143,39 +169,31 @@ See [`docs/backup.md`](docs/backup.md) for `backupData` / CLI backup (including
143
169
 
144
170
  ## Core usage (generic from `appId`)
145
171
 
146
- ### Create stores and `Catalox`
172
+ ### Create `Catalox` (recommended)
147
173
 
148
- ```ts
149
- import { FirestoreStore } from "@x12i/catalox";
150
- import { AppStore, CatalogStore, BindingStore, DefinitionStore, MappingStore, DescriptorStore, ReferenceStore, NativeItemStore, CatalogDataIndexStore, SnapshotStore, AdapterStore } from "@x12i/catalox";
151
- import { AuthorizationService, Catalox } from "@x12i/catalox";
174
+ Use **`createCatalox`** so you do not wire every Firestore store by hand. Optional **`mongoUri`** enables Mongo mapped catalogs; API mapped catalogs use an internal adapter unless you set `enableApiAdapter: false`.
152
175
 
153
- // firebase-admin initialization is up to the consumer
176
+ ```ts
177
+ import { createCatalox } from "@x12i/catalox";
154
178
  import { getFirestore } from "firebase-admin/firestore";
155
179
 
156
180
  const firestore = getFirestore();
157
- const store = new FirestoreStore({ firestore });
158
-
159
- const bindings = new BindingStore(store);
160
- const deps = {
161
- apps: new AppStore(store),
162
- catalogs: new CatalogStore(store),
163
- bindings,
164
- definitions: new DefinitionStore(store),
165
- mappings: new MappingStore(store),
166
- descriptors: new DescriptorStore(store),
167
- references: new ReferenceStore(store),
168
- nativeItems: new NativeItemStore(store),
169
- catalogDataIndex: new CatalogDataIndexStore(store),
170
- snapshots: new SnapshotStore(store),
171
- adapters: new AdapterStore(store),
172
- firestoreStore: store,
173
- authz: new AuthorizationService(bindings),
174
- };
181
+ const catalox = createCatalox({
182
+ firestore,
183
+ // Optional: per-record native history to GCS + `catalogItemHistory` (or set CATALOX_RECORD_HISTORY_BUCKET for CLI)
184
+ // recordHistory: { gcsBucket: "my-bucket", gcsPrefix: "catalox-record-history/" },
185
+ });
175
186
 
176
- const catalox = new Catalox(deps);
187
+ // Optional: bind app/tenant context once (no globals; same semantics as passing context each call).
188
+ const scoped = catalox.withContext({ appId: "myApp" });
189
+ const list = await scoped.listCatalogItems("myCatalog", { limit: 50 });
190
+ // list.listOutcome is "ok" | "mapping_blocked"; empty items with "ok" means zero rows.
177
191
  ```
178
192
 
193
+ ### Advanced: manual `CataloxDependencies`
194
+
195
+ If you need a non-default dependency graph, import stores from `@x12i/catalox/firebase`, construct `AuthorizationService`, and pass **`new Catalox(deps)`** as before (see source under `src/catalox/catalox.ts`).
196
+
179
197
  ## Descriptor contract (planning-critical)
180
198
 
181
199
  Catalox is designed so upstream packages can be “generic” (no hardcoded catalog registrations). The stable contract is the persisted **descriptor**:
@@ -346,8 +364,8 @@ const bootstrap = await catalox.getAppCatalogBootstrap(context, "myAppId");
346
364
 
347
365
  1) `listAppCatalogs(appId)` → get catalog list + access
348
366
  2) `getAppCatalogBootstrap(appId)` → get descriptors (capabilities/query/identity/fields)
349
- 3) `listCatalogItems(catalogId, filter/sort)` → fetch normalized items
350
- 4) `getCatalogItem(catalogId, itemId)` → fetch one item
367
+ 3) `listCatalogItems(catalogId, filter/sort)` → `{ listOutcome, items, issues? }` (`listOutcome` distinguishes OK empty lists vs mapping validation blocking)
368
+ 4) `getCatalogItem(catalogId, itemId)` → `{ outcome: "found" | "not_found" | "mapping_blocked", ... }`
351
369
  5) Optional: `getCatalogItemReferences(...)`, `validateCatalogItem(...)`
352
370
 
353
371
  ## Provisioning (create catalog + bind + descriptor)
@@ -357,7 +375,7 @@ Catalox includes provisioning helpers to reduce “manual Firestore wiring”.
357
375
  ### Create a native catalog (also seeds a minimal descriptor)
358
376
 
359
377
  ```ts
360
- const ctx = { appId: "myAppId", isGodMode: true }; // or bind admin access appropriately
378
+ const ctx = { appId: "myAppId", superAdmin: true }; // set only after host auth; often from AppRecord.superAdminApp
361
379
 
362
380
  await catalox.createCatalog(ctx, {
363
381
  catalogId: "signals",
@@ -453,6 +471,7 @@ await catalox.batchUpsertNativeCatalogItems({ appId: "myAppId" }, "signals", ite
453
471
  const res = await catalox.listCatalogItems({ appId: "myAppId" }, "signals", {
454
472
  filter: { categoryId: "core" }
455
473
  });
474
+ // `res.listOutcome`: "ok" (list ran) or "mapping_blocked" (see `res.issues`). Empty `items` with "ok" means zero matches.
456
475
  ```
457
476
 
458
477
  Filtering is performed on `indexed.<field>` in stored native records (payload remains in `data`). **Blank filter values** (`""`, whitespace-only strings, `null`, `undefined`) are **not** sent as Firestore constraints so empty UI fields do not zero out lists; see [`docs/native-catalog-storage-and-api.md`](docs/native-catalog-storage-and-api.md) and **`compactCatalogFilter`** in the published API.
@@ -486,7 +505,7 @@ Validation APIs exist with standardized contracts, but **current behavior is min
486
505
 
487
506
  ## Publishing
488
507
 
489
- From a clean tree, **`npm publish`** runs **`prepublishOnly`**, which executes **`npm run build`** then **`npm test`** (unit tests). Ensure `dist/` is build output only; the published tarball includes **`dist`**, **`README.md`**, and **`LICENSE`** per `package.json` **`files`**.
508
+ From a clean tree, **`npm publish`** runs **`prepublishOnly`**, which executes **`npm run build`** then **`npm test`** (unit tests). Ensure `dist/` is build output only; the published tarball includes **`dist`**, **`README.md`**, **`LICENSE`**, and **`firestore.indexes.json`** (composite indexes for `catalogItemHistory` queries) per `package.json` **`files`**.
490
509
 
491
510
  ## Tests
492
511
 
@@ -508,14 +527,37 @@ Integration tests are **live-only** (no mocks, no emulators). They require:
508
527
  - `FIREBASE_SERVICE_ACCOUNT_PATH=...`
509
528
  - `FIREBASE_PROJECT_ID=...`
510
529
 
530
+ The **`Firestore live integration`** test (`test/integration/firestore.emulator.test.ts`) uses **`createCatalox`** and asserts v3 contracts: **`listCatalogItems`** returns **`listOutcome: "ok"`**, and **`getCatalogItem`** returns **`{ outcome: "found", item }`** for the seeded row. The descriptor patch in that test includes **`queryableFields` with `indexed: true`** for filtered fields so **`deriveIndexed`** persists **`indexed.*`** (see **Canonical `indexed` rule** above).
531
+
532
+ When **`CATALOX_RECORD_HISTORY_BUCKET`** is set, **`test/integration/record-history.live.test.ts`** runs as well: ephemeral app/catalog, **`upsert` → `update` → `listCatalogItemHistory` → `getCatalogItemHistoryEvent` → `restoreCatalogItemFromHistory`**, then best-effort Firestore + GCS cleanup for the created history objects.
533
+
511
534
  ### Live test safety (read before running)
512
535
 
513
536
  - **Never run against production credentials/projects.** Use a dedicated Firebase project for tests.
514
- - **Touched collections**: `apps`, `catalogs`, `catalogBindings`, `catalogDefinitions`, `catalogDescriptors`, `catalogData/{catalogId}`, and `catalogData-{catalogId}-items/...`. The **`catalox firestore restore-backup`** / **`undo-restore-backup`** commands additionally write `backup-restoreSessions` and `{restoreSessionId}__preRestore-*` sidecar collections (see [`docs/restore-firestore-backup.md`](docs/restore-firestore-backup.md)).
537
+ - **Touched collections**: `apps`, `catalogs`, `catalogBindings`, `catalogDefinitions`, `catalogDescriptors`, `catalogData/{catalogId}`, `catalogData-{catalogId}-items/...`, and (when record history is enabled) `catalogItemHistory/...`. The **`catalox firestore restore-backup`** / **`undo-restore-backup`** commands additionally write `backup-restoreSessions` and `{restoreSessionId}__preRestore-*` sidecar collections (see [`docs/restore-firestore-backup.md`](docs/restore-firestore-backup.md)).
515
538
  - **Cleanup**: tests do best-effort deletes of the docs they created, but do not guarantee full teardown.
516
539
 
517
540
  ## Changelog
518
541
 
542
+ ### 3.1.1
543
+
544
+ - **Live tests:** Firestore integration test now sets **`queryableFields`** on the patched descriptor so equality filters match stored **`indexed.*`** rows (same rule as production descriptors).
545
+ - **Live tests:** Record-history integration test covers **update**, **get event**, **restore**, and **GCS object** cleanup when a bucket is configured.
546
+ - **Package:** publish **`firestore.indexes.json`** in the npm tarball for operators deploying **`catalogItemHistory`** queries.
547
+
548
+ ### 3.1.0
549
+
550
+ - **Per-record history:** optional **`recordHistory`** on **`createCatalox`** (or **`CATALOX_RECORD_HISTORY_*`** env for CLI) writes **GCS NDJSON** + Firestore **`catalogItemHistory`** on native upsert/update/delete/batch/move. APIs: **`listCatalogItemHistory`**, **`getCatalogItemHistoryEvent`**, **`restoreCatalogItemFromHistory`**, **`replayCatalogToPointInTime`**. CLI: **`catalox history …`**. See [`docs/record-history.md`](docs/record-history.md), [`firestore.indexes.json`](firestore.indexes.json).
551
+ - **Catalog lifecycle:** **`deleteCatalog`**, **`restoreDeletedCatalog`**, **`renameCatalog`** (hard rename) + CLI **`catalox catalog …`**. See [`docs/catalog-crud.md`](docs/catalog-crud.md).
552
+
553
+ ### 3.0.0
554
+
555
+ - **`createCatalox(config)`** — single factory for Firestore-backed stores, authz, optional Mongo/API adapters, optional renderer snippet store (`src/catalox/create-catalox.ts`).
556
+ - **`catalox.withContext(ctx)`** / **`bindCataloxContext(catalox, ctx)`** — **`CataloxBound`**: same APIs without repeating `CataloxContext` on every call (`src/catalox/catalox-bound.ts`).
557
+ - **Breaking — lists:** **`CatalogListResult`** includes **`listOutcome: "ok" | "mapping_blocked"`**. Mapping validation failures use **`mapping_blocked`** (see **`issues`**). Empty **`items`** with **`listOutcome === "ok"`** means zero matching rows.
558
+ - **Breaking — get item:** **`getCatalogItem`** returns **`CatalogGetItemResult`** (`found` | `not_found` | `mapping_blocked`), not **`null`**.
559
+ - **Package:** **`main` / `types`** and **`exports["."]`** resolve to **`dist/src/...`**. Subpaths **`@x12i/catalox/embedder`**, **`/operator`**, **`/mapping`**, **`/firebase`**. Root **`@x12i/catalox`** re-exports embedder + operator (preserves most existing root imports).
560
+
519
561
  ### 2.7.0
520
562
 
521
563
  - **GCS restore:** **`restoreFirestoreBackupFromGcs`** + CLI **`firestore restore-backup-from-gcs`** — same pre-restore / **`undoFirestoreRestore`** model as mirror restore.
@@ -6,7 +6,7 @@ export class AuthorizationService {
6
6
  this.bindings = bindings;
7
7
  }
8
8
  async requireBindingAccess(context, appId, catalogId, required) {
9
- if (context.isGodMode) {
9
+ if (context.superAdmin) {
10
10
  // God-mode policy: bypass binding for read/admin checks if needed.
11
11
  // We still return a synthetic binding for uniformity.
12
12
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../../src/catalox/authorization.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI5D,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,QAAsB;QAAtB,aAAQ,GAAR,QAAQ,CAAc;IAAG,CAAC;IAEvD,KAAK,CAAC,oBAAoB,CACxB,OAAuB,EACvB,KAAY,EACZ,SAAoB,EACpB,QAAwB;QAExB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,mEAAmE;YACnE,sDAAsD;YACtD,OAAO;gBACL,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE;gBAClD,KAAK;gBACL,SAAS;gBACT,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACzD,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;gBACpC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;aACrC,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACvE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC5C,MAAM,IAAI,wBAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC,CAAC;QACpG,CAAC;QAED,MAAM,EAAE,GACN,QAAQ,KAAK,MAAM;YACjB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;YACjC,CAAC,CAAC,QAAQ,KAAK,OAAO;gBACpB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAClC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEzC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,wBAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../../src/catalox/authorization.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI5D,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,QAAsB;QAAtB,aAAQ,GAAR,QAAQ,CAAc;IAAG,CAAC;IAEvD,KAAK,CAAC,oBAAoB,CACxB,OAAuB,EACvB,KAAY,EACZ,SAAoB,EACpB,QAAwB;QAExB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,mEAAmE;YACnE,sDAAsD;YACtD,OAAO;gBACL,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE;gBAClD,KAAK;gBACL,SAAS;gBACT,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACzD,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;gBACpC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;aACrC,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACvE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC5C,MAAM,IAAI,wBAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC,CAAC;QACpG,CAAC;QAED,MAAM,EAAE,GACN,QAAQ,KAAK,MAAM;YACjB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;YACjC,CAAC,CAAC,QAAQ,KAAK,OAAO;gBACpB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAClC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEzC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,wBAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import type { CatalogId } from "../contracts/ids.js";
2
+ import type { DeleteCatalogInput, DeleteCatalogResult, RenameCatalogInput, RenameCatalogResult, RestoreDeletedCatalogInput, RestoreDeletedCatalogResult } from "../contracts/catalog-lifecycle.js";
3
+ import type { CataloxContext } from "../contracts/context.js";
4
+ import { AdapterStore } from "../firebase/adapter-store.js";
5
+ import { CatalogDataIndexStore } from "../firebase/catalog-data-index-store.js";
6
+ import { DefinitionStore } from "../firebase/definition-store.js";
7
+ import { DescriptorStore } from "../firebase/descriptor-store.js";
8
+ import { MappingStore } from "../firebase/mapping-store.js";
9
+ import { NativeItemStore } from "../firebase/native-item-store.js";
10
+ import { ReferenceStore } from "../firebase/reference-store.js";
11
+ import { RendererSnippetStore } from "../firebase/renderer-snippet-store.js";
12
+ import { SnapshotStore } from "../firebase/snapshot-store.js";
13
+ import { type BackupDataDeps } from "./backup-data.js";
14
+ import { type RecordHistoryDeps } from "./record-history.js";
15
+ export type CatalogLifecycleDeps = BackupDataDeps & {
16
+ definitions: DefinitionStore;
17
+ descriptors: DescriptorStore;
18
+ mappings: MappingStore;
19
+ adapters: AdapterStore;
20
+ references: ReferenceStore;
21
+ nativeItems: NativeItemStore;
22
+ snapshots: SnapshotStore;
23
+ catalogDataIndex: CatalogDataIndexStore;
24
+ rendererSnippets?: RendererSnippetStore;
25
+ };
26
+ export declare function runDeleteCatalog(deps: CatalogLifecycleDeps, recordHistory: RecordHistoryDeps | undefined, context: CataloxContext, catalogId: CatalogId, input: DeleteCatalogInput): Promise<DeleteCatalogResult>;
27
+ export declare function runRestoreDeletedCatalog(deps: CatalogLifecycleDeps, recordHistory: RecordHistoryDeps, input: RestoreDeletedCatalogInput): Promise<RestoreDeletedCatalogResult>;
28
+ export declare function runRenameCatalog(deps: CatalogLifecycleDeps, recordHistory: RecordHistoryDeps | undefined, context: CataloxContext, fromCatalogId: CatalogId, toCatalogId: CatalogId, input: RenameCatalogInput): Promise<RenameCatalogResult>;
29
+ //# sourceMappingURL=catalog-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/catalox/catalog-lifecycle.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAEV,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,mCAAmC,CAAC;AAQ3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAQ9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG;IAClD,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,aAAa,CAAC;IACzB,gBAAgB,EAAE,qBAAqB,CAAC;IACxC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;CACzC,CAAC;AAwDF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,EAC1B,aAAa,EAAE,iBAAiB,GAAG,SAAS,EAC5C,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAoL9B;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,oBAAoB,EAC1B,aAAa,EAAE,iBAAiB,EAChC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,2BAA2B,CAAC,CAuFtC;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,EAC1B,aAAa,EAAE,iBAAiB,GAAG,SAAS,EAC5C,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,SAAS,EACxB,WAAW,EAAE,SAAS,EACtB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAgM9B"}