# Changelog

## 6.0.0

**Breaking — MongoDB primary + Cloudflare R2 object store**

- **Mongo-only primary persistence** (continued from Unreleased work): `createCatalox({ firestore })` removed; CLI / service / management boot Mongo via `MONGO_URI` (default DB **`catalox`**).
- **Object store is Cloudflare R2** via new package **`@x12i/catalox-storage`** (S3-compatible). Google GCS / `@google-cloud/storage` removed from day-to-day runtime paths (record history, catalog lifecycle, backup helpers).
- **Default bucket:** `catalox` (`S3_BUCKET` / `CATALOX_OBJECT_STORE_BUCKET` / `CATALOX_BUCKET`). R2 buckets are **not** auto-created.
- **Migration CLI:** `catalox storage migrate-from-gcs` classifies GCS keys into R2 buckets **`catalox`** / **`magit`** / **`storage`**.
- **Record history** defaults on for Mongo hosts (disable with `CATALOX_RECORD_HISTORY=0` or `recordHistory: false`).
- **Env:** `S3_API`, `S3_ACCESS_ID`, `S3_SECRET_ACCESSKEY` (accepts `S3_ACOUNT_ID` typo for account id). `GOOGLE_SERVICE_ACCOUNT_BASE64` only for Firestore doc import / GCS→R2 migrate.
- **Docs:** [`docs/environment.md`](docs/environment.md), [`docs/record-history.md`](docs/record-history.md), [`docs/backup.md`](docs/backup.md), [`docs/mongo-persistence.md`](docs/mongo-persistence.md).

## 5.10.1

**Firestore → Mongo full copy**

- **`copyAllFirestoreCollectionsToMongo` / `copyFirestoreCollectionToMongo`** — operator utility that copies every Firestore collection (recursive by default) into Mongo with matching slash collection paths and document ids as `_id`.
- **CLI:** `catalox mongo import-from-firestore` (default `--db catalox`), plus `catalox mongo probe`.
- **Docs:** [`docs/mongo-persistence.md`](docs/mongo-persistence.md).

**Dependency alignment — `@x12i/logxer@^5.1.0`**

- Bump `@x12i/logxer` to `^5.1.0` (ESM/CJS dual export; Node-only main entry). Catalox logging stays on the main entry — engine is Node-only.
- Align workspace and root dependency pins to `5.10.1`.

## 5.10.0

**Platform prerequisites — single minor release (all five client items)**

Ships actor HTTP normalization, audit fields on reads, list filter query params, soft delete, relation catalogs, DELETE/restore routes, and OpenAPI 5.10.0 surface in one release (not staged as 5.11/5.12).

- **Audit fields on reads** — `createdAt`, `createdBy`, `lastUpdate`, `updatedBy` returned on every native `UnifiedCatalogItem` list/get; `CatalogItemAuditFields` type exported. Auto-index `createdAt` / `lastUpdate` on write.
- **`buildRequestContext`** — exported from `@x12i/catalox-api`; normalizes `actor` on all HTTP handlers via `resolveActorFromContext`.
- **List filters HTTP+SDK** — `GET /v1/catalogs/:catalogId/items?field=value&sort=field:desc`; client `listCatalogItems` serializes `filter` and `sort`. Descriptor fields require `indexed: true` and `filterable !== false`.
- **DELETE / restore** — `DELETE /v1/catalogs/:catalogId/items/:itemId` (hard by default); `POST …/restore` for soft-deleted items.
- **Soft delete (opt-in)** — `descriptor.softDelete: true` tombstones on DELETE; list supports `includeDeleted` / `deletedOnly`.
- **Relation catalogs** — `relationCatalog` + `relationListFilters` descriptors; filter-by-relation on primary list; [`docs/relation-catalogs.md`](docs/relation-catalogs.md).
- **OpenAPI** — `@x12i/catalox-openapi` updated to 5.10.0 (list filters, DELETE, restore).
- **Client response** — [`.operations/requests/catalox-platform-prerequisites-response.md`](.operations/requests/catalox-platform-prerequisites-response.md).

## 5.9.12

**Release hygiene**

- Remove accidental credential-bearing `repository` metadata injected during 5.9.11 publish (xnpm/npm); republish `@x12i/catalox-cli` and `@x12i/catalox-openapi` without exposed tokens in package metadata.
- Align workspace dependency pins and lockfile after manual publish cleanup.

## 5.9.11

**Consumer platform — actor resolution for audit fields**

- **`resolveActorFromContext(ctx)`** — exported from `@x12i/catalox-contracts` / `@x12i/catalox`; returns `{ type, id, displayName? }` for embedders persisting structured audit metadata (e.g. version checkpoint `changedBy`). Prefer over reading client PUT bodies.
- **`CataloxContext.actor.displayName`** — optional human label from host/token profile.
- **Docs:** [`docs/feature-requests/fr-catalox-graph-versioning-platform-feedback.md`](docs/feature-requests/fr-catalox-graph-versioning-platform-feedback.md) — platform readiness mapping for `@exellix/catalox-graphs` graph versioning and authoring-load FRs.

## 5.9.10

**Consumer platform — native list filter validation**

- **Native list filters** — `listCatalogItems` now rejects filter keys that are not declared `indexed: true` on the catalog descriptor with `CatalogValidationError` (`reason: "filter_field_not_queryable"`) instead of querying Firestore with undeclared `indexed.*` fields.
- **`planNativeListFilters`** — normalizes `data.*` / `indexed.*` filter paths and returns `invalidFilterKeys` for descriptor validation.
- **Docs** — expanded [`docs/consumer-platform-guide.md`](docs/consumer-platform-guide.md) with composite index template, service actor binding table, and known limits; aligned [`docs/native-catalog-storage-and-api.md`](docs/native-catalog-storage-and-api.md) filter semantics.

## 5.9.9

**Consumer platform — native catalog smoke tests and composite index errors**

- **`FirestoreCompositeIndexRequiredError`** — when Firestore rejects a native catalog list query for a missing composite index, Catalox throws a structured error with `indexDefinition`, `indexSnippet` (ready for `firestore.indexes.json`), and the Firebase console URL when available.
- **Engine helpers:** `buildNativeCatalogIndexFields`, `formatNativeCatalogIndexSnippet`, `rethrowNativeCatalogIndexError` in `@x12i/catalox/firebase`.
- **Docs:** [`docs/consumer-platform-guide.md`](docs/consumer-platform-guide.md) — consumer provisioning, composite index setup, service actor/bindings, known limits.
- **Smoke test template:** [`packages/core/engine/test/integration/consumer-native-catalog.smoke.test.ts`](packages/core/engine/test/integration/consumer-native-catalog.smoke.test.ts); run with `npm run test:smoke -w @x12i/catalox-engine` and `FIRESTORE_LIVE_TESTS=1`.
- **`updateCatalog`** — patches `schemaVersion` and inline `itemSchema` on catalog + definition records (management API support).

## 5.9.8

**New — indexed field lookup and structured read results**

- **`getCatalogItemByField(ctx, catalogId, fieldPath, value)`** on `Catalox` / `CataloxBound` — single-call resolve by descriptor-indexed field (`data.<key>` paths supported). Outcomes: `found`, `not_found`, `ambiguous`, `field_not_queryable`, `mapping_blocked`.
- **Opt-in `*Result` wrappers** on `CataloxBound`: `getCatalogItemResult`, `listCatalogItemsResult`, `getCatalogItemByFieldResult` return `CataloxResult<T>` with `CataloxClientError` `errorDetail`. Existing `getCatalogItem` / `listCatalogItems` signatures unchanged.
- **Contracts:** `CataloxResult`, `CataloxClientError`, field-path helpers, outcome mappers exported from `@x12i/catalox-contracts` and re-exported via `@x12i/catalox`.
- **HTTP API:** `GET /v1/catalogs/:catalogId/items/by-field?fieldPath=...&value=...`
- **`@x12i/catalox-client`:** `getCatalogItem`, `listCatalogItems`, and new `getCatalogItemByField` return `CataloxResult` (breaking for HTTP client consumers only).
- **Docs:** README sections for field lookup, structured errors, and toolbox bindings.

## 5.9.7

**Alignment fixes**

- Publish **`@x12i/catalox-contracts`** alongside **`@x12i/catalox`** so runtime imports resolve on npm (5.9.6 tarball referenced contracts without publishing them).
- Root **`@x12i/catalox`** declares engine runtime dependencies (`@x12i/helpers`, `firebase-admin`, etc.).
- HTTP API: **`GET/PUT /v1/catalogs/:catalogId/items/:itemId/native-record`** maps to `getNativeCatalogItem` / `replaceNativeCatalogItem`.
- Client SDK: **`getNativeCatalogItem`**, **`replaceNativeCatalogItem`** on `CataloxClientBound`.
- OpenAPI updated to **5.9.6** surface (native-record routes).
- Docs and scripts: source links point at **`packages/core/engine/src/`** (legacy root `src/` removed); `scripts/data/*` imports use workspace packages.
- CI workflow file excluded from git until PAT has `workflow` scope (`.github/` gitignored).

## 5.9.6

**New — generic catalog content helpers (embedder surface)**

Domain apps (skills, snippets, templates, etc.) can compose these without Catalox knowing item roles or catalog ids:

- **Field codec** — `normalizeTextForStorage` / `toPresentationText` (aliases `normalizeForStorage` / `toPresentationMarkdown`) for storage ⇄ presentation text round-trip.
- **Template tokens** — `extractTokenNamesFromText`, `extractTokenNamesFromStrings`, `extractTemplateTokensFromFields` for `{{token}}` (optional `${token}`) placeholder discovery.
- **Derived items** — `readIndexedParentItemId`, `withDerivedParentIndexed`, `computeDerivedFieldOverrides`, `resolveDerivedItemData`, `resolveDerivedItem`, `emptyDataFieldsPatch` for parent/child sparse-override catalogs (`indexed.parentItemId` convention).
- Contracts: `CATALOG_DERIVED_PARENT_INDEXED_KEY`, `DerivedItemFieldOverrides`, `ResolvedDerivedItem`, `ExtractedTemplateInputs`.

**New — authenticated full-document native replace (FR-CATALOX-1 / FR-CATALOX-2)**

- **`replaceNativeCatalogItem(ctx, catalogId, record)`** — generic, authenticated full-document native replace. Persists with **no field-level merge** (`merge: false`), so keys omitted from `record.data` / `record.indexed` / `record.metadata` are **removed**, not preserved from a prior revision. Enforces the same access model as `upsertNativeCatalogItem` (app binding `canWrite`, or `ctx.superAdmin` for provision) and the same scope write gate. Catalox owns `metadata.lastUpdate`, preserves `metadata.createdAt`, and increments `version`.
- **`replaceNativeCatalogItems(ctx, catalogId, records, { atomic? })`** — batch variant. `atomic` defaults to `true` (validate all rows, then commit per store batch chunk of ≤450 writes).
- **`getNativeCatalogItem(ctx, catalogId, itemId, options?)`** — authenticated read returning the stored `NativeCatalogItemRecord` envelope by logical `itemId` (respects `canRead`).
- Store layer: `replace` / `batchReplace` added to the Firestore, Mongo, and in-memory `NativeItemStore` implementations.
- Bound API (`CataloxBound`) and CLI (`catalox items replace`, `catalox items batch-replace`) wrappers.
- `upsertNativeCatalogItem` merge semantics are **unchanged**; replace is an additive, opt-in API.
- Docs: README native write contract table, [`docs/native-catalog-storage-and-api.md`](docs/native-catalog-storage-and-api.md) §6, [`docs/cli-items.md`](docs/cli-items.md).

## 5.9.5

**New — monorepo and internal HTTP API**

- npm workspaces monorepo: `@x12i/catalox-contracts`, `@x12i/catalox-engine`, `@x12i/catalox-api`, `@x12i/catalox-client`, `@x12i/catalox-authix-bridge`, `@x12i/catalox-openapi`, `catalox-service`.
- Internal HTTP API (Fastify) with dual auth: open mode (`X-Catalox-Context`) and authix mode (`Authorization: Bearer`).
- `createCataloxClient` SDK with `withContext` and `withToken`.
- Root `@x12i/catalox` re-exports `@x12i/catalox-engine` for backward compatibility.
- Docs: [`docs/catalox-v6/5.9.5/`](docs/catalox-v6/5.9.5/), transition reference [`docs/catalox-v6/6.0.0/transition-from-5.9.5.md`](docs/catalox-v6/6.0.0/transition-from-5.9.5.md).

## 5.9.0

**Breaking — local snapshot schema**

- Local file snapshots use **`catalox.catalog.local.v1`** (`CATALOX_CATALOG_LOCAL_SCHEMA_V1`). Legacy **`funcx.catalog.local.v1`** snapshots are rejected at load.
- Export rename: `FUNCX_*` local types/constants removed from the public embedder surface in favor of **`CATALOX_*`** / `CataloxCatalogLocalSnapshotV1`.

**New — MongoDB as primary persistence**

- **`createCatalox({ mongo: MongoStore })`** wires Mongo-backed domain stores (parity with Firestore collection names).
- **`createCataloxFromMongoEnv`**, **`initMongoPersistenceFromEnv`**, **`testMongoConnectionFromEnv`** via **`@x12i/helpers/mongo`** (`@x12i/catalox/mongo`).
- Native item reads report **`sourceType: "mongo"`** when wired from Mongo stores.
- Firestore operator features (GCS backup/export, migrations, record history) fail fast on Mongo and local modes.

**New — local file store (embedder)**

- **`createCatalox({ store: LocalFileStore })`** for offline read-only catalog runtime without Firebase.
- Docs: [`docs/local-file-store.md`](docs/local-file-store.md), [`docs/mongo-persistence.md`](docs/mongo-persistence.md).

**Package**

- Version **5.9.0**; `@x12i/helpers` **^1.7.0**; export **`@x12i/catalox/mongo`**.
- npm tarball includes local + mongo persistence docs.

## 5.1.1

- **CAT-001:** `getCatalogItem`, `updateNativeCatalogItem`, `deleteNativeCatalogItem`, and smart-property target resolution use `storageDocIdForItem(logicalId)` when `findByLogicalItemId` returns no rows (fixes logical ids containing `/`, e.g. `@scope/pkg`, `skillCode:code`).
- **CAT-005:** `listCatalogItems` on native catalogs uses Firestore `array-contains` on `indexed.*` for multi-value / indexed smart-property filters; multi-value smart properties always index as arrays.
- **CAT-003:** still open — no cross-catalog transaction API.

## 5.1.0

- **Smart properties:** `CatalogDescriptor.smartProperties` and `smartPropertyRules` — descriptor-driven FK fields on native upsert/patch with optional auto-create, usage metadata on targets (`usageCount`, `lastUsedAt`, `firstUsedAt`), scope union, and `minPropertiesFilled` validation. Docs: `docs/smart-properties.md`, README section.
- **CLI:** `catalox items validate --no-auto-create` for smart-property target checks.
- **Pagenti preset:** `pagenti@v4` — unified smart properties on skills, knowledge, and execution; `pagenti_target_skill` FK catalog for `skillCode`; composite identity on execution (`npm run seed:pagenti`).

## 5.0.0

**Breaking — flexible native item scope**

- **Item binding:** native rows use `scope: { domains?: string[], agents?: string[], … }`. Empty `{}` = generic item. Legacy `scope.kind` / `scoped.agent.domainId` shapes are rejected at runtime (run migration first).
- **Token scope:** set `context.scope` from the validated token. This is the mandatory visibility boundary for scoped items.
- **Fetch scope:** `options.scope.scope` narrows the request (intersects with token per dimension). Fetch scope cannot grant access when `context.scope` is empty unless `superAdmin` or `unrestrictedScope`.
- **Fetch controls:** `includeGeneric` (default true), `scopedOnly`, `genericOnly`, `includeScopeInResponse` (default true). List/get responses include item `scope`.
- **Storage:** one logical row per `itemId`; safe Firestore doc ids use `id~<base64url>` when `itemId` contains `/` (legacy `cx~m~` rows migrated).
- **Migration:** `catalox firestore migrate-native-item-scope` (`--dry-run`, `--verify-only`, `--scope-mapping`, `--i-have-backups`). Reports `conflict_physical_variants` when same `itemId` has differing payloads.
- **Removed:** `NativeCatalogStoredScope`, `NativeCatalogStoredScopeV1`, singular `context.domainId` / `context.agentId` for item visibility, `metadata.domainIds` / `agentIds` as visibility drivers.

## 4.0.3

- **Seed presets:** **`--preset <id>`** on **`catalox seed apply`** (mutually exclusive with **`--file`**). **`applyCataloxSeedPreset`** accepts **`{ preset, cwd? }`**; **`resolveCataloxSeedPresetPath`**, **`getBundledCataloxPresetsDir`**, **`CataloxSeedPresetResolveError`** exported from **`@x12i/catalox`**. Bundled **`presets/registry.json`** (aliases such as **`native-map@v1`**). Embedder packages can publish a manifest path via **`"catalox": { "seedPreset": "./path/within-package.json" }`** in **`package.json`** (default **`catalox-seed-preset.json`**).
- **Firestore probe:** **`testFirestoreConnectionFromEnv`**, **`CATALOX_FIRESTORE_PROBE_COLLECTION_ID`**, and **`TestFirestoreConnectionFromEnvResult`** re-exported from **`@x12i/catalox`** (same as **`@x12i/catalox/firebase`**).
- **Docs:** onboarding happy path updated for **`--preset`** and preset selector table.

## 4.0.0

- **Firebase bootstrap:** credential resolution order **`GOOGLE_SERVICE_ACCOUNT_BASE64`** → optional **`serviceAccountPath`** → ADC; optional **`FIRESTORE_DATABASE_ID`** for named databases.
- **`testFirestoreConnectionFromEnv`:** Firestore probe uses collection **`cataloxConnectivityProbe`** (avoids reserved `__…__` ids). Export **`CATALOX_FIRESTORE_PROBE_COLLECTION_ID`**.
- **CLI:** **`catalox firestore probe`**, **`catalox seed apply --app … --file …`** (`--god` when manifest includes descriptors).
- **Library:** **`applyCataloxSeedPreset`**, **`parseCataloxSeedManifest`**, **`loadCataloxSeedManifestFromPath`** (`src/catalox/seed-preset.ts`, re-exported from **`@x12i/catalox`**).
- **`Catalox.upsertCatalogDescriptor`** / **`CataloxBound.upsertCatalogDescriptor`** (super-admin). Contract **`UpsertCatalogDescriptorInput`**.
- **Docs:** `docs/onboarding-happy-path.md`, `docs/native-map-catalog-preset.md`; example **`presets/native-map-v1.json`** (published in npm tarball).

## 3.2.0

- Dependency refresh:
  - `@x12i/logxer` to `^4.0.2`
  - `@x12i/helpers` to `^1.5.2`

## 3.1.1

- **Live tests:** Firestore integration test now sets **`queryableFields`** on the patched descriptor so equality filters match stored **`indexed.*`** rows (same rule as production descriptors).
- **Live tests:** Record-history integration test covers **update**, **get event**, **restore**, and **GCS object** cleanup when a bucket is configured.
- **Package:** publish **`firestore.indexes.json`** in the npm tarball for operators deploying **`catalogItemHistory`** queries.

## 3.1.0

- **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`, `firestore.indexes.json`.
- **Catalog lifecycle:** **`deleteCatalog`**, **`restoreDeletedCatalog`**, **`renameCatalog`** (hard rename) + CLI **`catalox catalog …`**. See `docs/catalog-crud.md`.

## 3.0.0

- **`createCatalox(config)`** — single factory for Firestore-backed stores, authz, optional Mongo/API adapters, optional renderer snippet store (`src/catalox/create-catalox.ts`).
- **`catalox.withContext(ctx)`** / `bindCataloxContext(catalox, ctx)` — **`CataloxBound`**: same APIs without repeating `CataloxContext` on every call (`src/catalox/catalox-bound.ts`).
- **Breaking — lists:** **`CatalogListResult`** includes **`listOutcome: "ok" | "mapping_blocked"`**.
- **Breaking — get item:** **`getCatalogItem`** returns **`CatalogGetItemResult`** (`found` | `not_found` | `mapping_blocked`), not `null`.
- **Package:** `main` / `types` and `exports["."]` resolve to `packages/core/engine/dist/...`. Subpaths `@x12i/catalox/embedder`, `/operator`, `/mapping`, `/firebase`, `/mongo`.

## 1.3.0

- Expanded the public **descriptor contract** with optional UI metadata:
  - `filterSpec`
  - `presentationSpec`
  - `customRenderer`
- Added new public contracts for:
  - `FieldSource` (cross-catalog option/value sources)
  - filter + presentation specs
  - custom renderer maps (`CatalogListRenderMap`, `CatalogItemRenderMap`)
- Added public docs:
  - `docs/catalog-list-render-map.md`
  - `docs/catalog-item-render-map.md`

