# Platform Changelog ## [Unreleased] ### Added #### ops control plane (`crates/ops-keeper`, `crates/ops-controller`) New two-component ops control plane implementing secure, auditable operation dispatch. **ops-keeper** — policy gate before any operation reaches the orchestrator: - Glob-based `PolicyDef` matching on `op_type`, `image_patterns`, `target_patterns` - `Signer` issues compact Ed25519 JWTs (`OpsClaims`) on policy approval - NATS JetStream pull consumer on `ops.pending.*` - `AuditEvent` emission to `ops.audit.*` on every terminal decision **ops-controller** — durable executor with at-least-once delivery: - Verifies keeper-signed JWT before dispatching to orchestrator HTTP API - SurrealDB idempotency store; `reconcile_pending` reconciles stale ops on startup - Structured `AckResult` (Ack / Nak / Term) per JetStream semantics - Emits audit events to `ops.audit.*` on every terminal outcome **ADR**: ADR-038 (ops control plane design) #### audit-mirror (`crates/audit-mirror`) Sidecar that consumes `ops.audit.*` and creates a signed git commit per event in a local Radicle repository, then announces the repo. JTI deduplication prevents double-commits on consumer redelivery. **ADR**: ADR-038 #### contract-tests (`crates/contract-tests`) G3 contract test suite verifying semantic equivalence across three tiers: - **Tier A**: direct registry invocation (reference baseline) - **Tier B**: axum HTTP daemon on ephemeral port - **Tier C**: in-process MCP `handle_request` Normaliser strips volatile fields; JSON schema validates every tier output against `listing_output_schema`. Regression guard for CLI↔HTTP↔MCP drift. #### control-center: NATS→WebSocket bridge (`src/handlers/nats_bridge.rs`) Eliminates long-polling between control-center UI and orchestrator. Durable JetStream consumer `cc-task-status-bridge` subscribes to `TASKS` stream and re-broadcasts each `TaskStatusPayload` to all connected WebSocket clients via `WebSocketManager`. #### API catalog endpoints (`crates/ai-service`, `crates/control-center`) `GET /api-catalog` added to ai-service and control-center. Each handler uses `inventory::iter::()` to emit a sorted JSON catalog of all registered routes — self-describing API surface without a separate OpenAPI toolchain. #### SOLID boundary pre-commit check (`.pre-commit-hooks/solid-boundary-check.sh`) Shell hook enforced in `.pre-commit-config.yaml`. Fails the commit if a crate imports across declared SOLID layer boundaries, keeping dependency direction consistent before code reaches CI. ### Removed / Lifted - **`crates/backup-manager`** — lifted to `cloudatasave` (LibreCloud/cloudDataSave). **ADR-041**. - **`crates/buildkit-launcher`** — lifted to `lian-build`. **ADR-040**. - **`crates/daemon`** — `Cargo.toml` removed; binary consolidated into `provisioning-daemon`. - **`prov-ecosystem/crates/nu-daemon`** / **`daemon-cli`** — excluded from workspace; `rustls=0.23.28` pin conflicts with surrealdb@3 (`^0.23.36`). Build standalone with `cargo build -p nu-daemon` until `nu-command` relaxes the pin. --- ## [3.6.0] — 2026-04-17 ### Added #### ncl-sync daemon (`crates/ncl-sync/`) New Rust daemon that eliminates `nickel export` latency from CLI commands by pre-compiling NCL files and maintaining a shared cache. - **File watching**: `notify` watcher on workspace NCL directories; re-exports automatically on file change - **Warm-up**: on `prvng platform start`, scans all NCL files in the workspace and exports stale entries concurrently (configurable concurrency) - **Shared cache**: `~/.cache/provisioning/config-cache/` — same directory and key strategy as `nu_plugin_nickel` - **Content-addressed keys**: `SHA256(file_content + sorted_import_paths + format)` — zero coordination overhead between daemon and plugin - **Sync requests**: Nu processes write `.sync-.json` sidecars after mutations; daemon drains them within 500 ms - **CLI subcommands**: `daemon`, `warm`, `invalidate`, `key`, `stats` - **Config-driven** via `platform-config`: `platform/config/ncl-sync.ncl` — idle timeout, concurrency, poll interval, extra import paths - **No platform dependencies**: intentionally avoids NATS, SurrealDB, and orchestrator to prevent bootstrap circularity #### Platform lifecycle integration - `prvng platform start` now launches `ncl-sync daemon` (via `ncl-sync-start` in `service-manager.nu`) - `prvng platform stop` stops ncl-sync (via PID file) - `prvng platform status` shows ncl-sync running state #### Nu cache layer - `lib_provisioning/config/cache/core.nu`: implemented `cache-lookup`, `cache-write`, `write-sync-request` (previously no-ops) - `lib_provisioning/config/cache/nickel.nu`: implemented `lookup-nickel-cache`, `derive-ncl-cache-key`, `request-ncl-sync` #### nickel_processor wrappers New `lib_provisioning/utils/nickel_processor.nu` functions: - `ncl-eval`: drop-in for `^nickel export ... | from json` — checks plugin cache, propagates error on failure - `ncl-eval-soft`: soft-failure variant with configurable fallback value #### nu_plugin_nickel updates - `nickel-eval` and `nickel-export` now accept `--import-path LIST` flag (`-I`) - New command `nickel-cache-key`: prints the cache key for a file (parity testing) - Cache key derivation updated to `SHA256(file_content + sorted_import_paths + format)` — aligned with ncl-sync - Cache key now includes import paths: same file with different import paths produces different cache entries #### Hot-path migration (C1) Replaced `^nickel export ... | from json` with `ncl-eval`/`ncl-eval-soft` in the four highest-frequency call sites: - `main_provisioning/dispatcher.nu` — commands-registry load - `main_provisioning/components.nu` — workspace settings export - `main_provisioning/workflow.nu` — workflow NCL exports - `main_provisioning/extensions.nu` — per-extension metadata #### Extended migration (C2 + C3) Migrated remaining high-value call sites (~55 additional sites across 30+ files) including `config/export.nu`, `taskservs/discover.nu`, `servers/create.nu`, `ontoref-queries.nu`, `service-manager.nu`, `dag.nu`, and others. #### ADRs - `adrs/adr-022-ncl-sync-daemon.ncl`: daemon design decisions, key strategy rationale, constraint enforcement - `adrs/adr-023-ncl-export-wrapper.ncl`: `ncl-eval`/`ncl-eval-soft` wrapper design, migration strategy #### Tests - `tests/cache/test_key_parity.nu`: validates that ncl-sync and nu_plugin_nickel produce identical keys for the same `(file, import_paths, format)` triple ### Performance | Command | Before | After (warm cache) | |---------|--------|--------------------| | `prvng component list` | 3–7 s | ~1.5 s | | `prvng workflow list` | 3–5 s | ~1.5 s | | `prvng deploy` | 15–30 s | ~3–5 s | | Multi-export commands (ontoref) | 12–30 s | ~1.5 s | Nu module parse startup (~1.2 s) is unaffected — separate concern. --- ## [3.5.0] — 2025-10-07 Initial platform version with orchestrator, control center, installer, MCP server, vault service, and extension registry.