# Changelog Operator- and user-facing changes. Internal refactoring, test additions and documentation-only commits are not listed unless they change what an operator sees or does. ## Unreleased ### Security - Runtime Worker packaging now upgrades the digest-pinned Ubuntu base before installation and pins the inference stack plus inherited Python security dependencies to reviewed fixed versions. The public-candidate gate scans the resulting fourth image instead of treating the private worker as an unexamined exception. - The Runtime Worker removes unneeded kernel-development headers after installation, eliminating their upstream-unfixed vulnerability surface without removing required runtime libraries. - Public candidate scans distinguish fixable or newly observed HIGH/CRITICAL findings from an exact reviewed upstream-unfixed baseline. A changed CVE, package, installed version, severity or newly available fix fails closed. - Node enrollment and publisher credentials now require their exact fixed scopes at both service and database boundaries. Schema `20260830_0023` validates every existing row before adding the constraints and refuses the upgrade when malformed legacy scope data exists. - Request-body streaming now has finite ASGI event/progress budgets in addition to byte limits; progressless frame floods receive the typed `request_body_progress_exhausted` response. - PostgreSQL role provisioning now removes the database's default public temporary-table grant; production startup continues to attest that the runtime role cannot create or use it. ### Fixed - Fresh schema `20260830_0024` installs no longer let Psycopg misread PostgreSQL `%rowtype` and `%I` syntax as client placeholders. - Public-candidate acceptance now works across the Gitea sibling Docker daemon while retaining isolated volumes, private workers, exact HTTP contract probes and deterministic cleanup. ## v1.2.1 — 2026-08-30 A packaging and provenance patch. No feature, API, schema or runtime-behaviour change; schema stays `20260828_0022` and no migration runs. It exists because v1.2.0's production acceptance found two defects that every existing gate was blind to — both in the artifacts rather than the source. ### Fixed - **The published console could not reach its own API.** Vite inlines `VITE_API_BASE_URL` at build time, but the release build never passed it, so every release image since v1.1.0 compiled the Dockerfile's development default `http://localhost:8000` into an immutable bundle — and the nginx CSP, derived from the same argument, hardcoded the same wrong origin. A release build now requires an explicit `--public-api-origin` (or `MODELFORGE_PUBLIC_API_ORIGIN`) and refuses to package without one. - **The Node Agent's identity could drift from its tag.** `docker-compose.node-agent.yml` declared a build with no arguments, so a Compose-built agent carried version `0.0.0` and empty revision/created labels while still being tagged from `MODELFORGE_VERSION`. Production ran an image tagged `1.1.1` whose contents were `1.2.0`. The projection now passes the release identity, as the API and console projections already did. ### Added - `scripts/release_image_acceptance.py`: a gate that inspects the **built** console image — its compiled bundle, its rendered CSP and its OCI labels — rather than the source that produced it. The release build runs it before packaging and refuses to publish an image that cannot reach the API it was built for. Verified against the exact image that broke production. - Regression coverage for both defects: the release build fails closed without an origin, the origin reaches the console build, the CSP names the same origin and is never widened to a wildcard, every release image declares complete OCI labels, and every Compose projection that builds a published image passes the release identity. ### Operations - The release manifest now records the console's compiled-in API origin, so an operator can see it without unpacking the image. - Local development is unchanged: `docker compose up` still defaults to `http://localhost:8000`. Fail-closed applies to the release path only. ## v1.2.0 — 2026-08-29 The Premium Operator Console release. No API contract, domain model, runtime behavior or database schema changed; schema stays `20260828_0022` and no migration runs. ### Added - A production command center built only from backend-authoritative evidence, stating unknowns as unknown rather than as zero. - Quick jump (Ctrl+K): a modal command palette over all 13 workspaces, matching name, domain and keywords. - An evidence timeline of recent control-plane activity, each entry linking to the workspace where it can be verified. - A split-pane Registry detail view covering upstream facts, local governance, revisions, artifacts and provenance. - One console-wide guarded destructive-action dialog showing identity, dependency posture and permanent impact before an explicit acknowledgement unlocks the confirm control. ### Changed - Workspaces are grouped by operator mental model (Command, Model supply, Serving, Infrastructure, Assurance, Projects) while every existing route hash is preserved. - One refined design token layer for light and dark, with semantic status roles that always include text and explicit focus rings. - Every route is usable from 1440 px down to a 390 px mobile viewport through a modal navigation drawer, with no horizontal overflow at any tested width. ### Fixed - The ARIA tabs pattern is complete across all six tabbed workspaces: every tab carries a stable `id` and `aria-controls`, and every panel is a real `role="tabpanel"` naming its tab back. - Lifecycle, Migrations and Recovery tablists gained roving `tabindex`, an accessible tablist name and Left/Right/Home/End keyboard movement, which they previously lacked entirely. - Capability residency unload no longer uses a native `window.confirm`; it uses the console safety dialog and shows the VRAM released and the cold-load cost the next request will pay. - Operator token fields in Operations, Recovery, Lifecycle and Migrations now sit in a real form with a stable `id`, a `name` and an explicit `