# M14 operations and packaging evidence ## Delivered - Pinned non-root OCI application and proxy images; isolated web, scheduler, worker, migrate, and admin roles; same-origin Unix-socket proxy; no reload or embedded roles. The proxy port is loopback-bound by default (`127.0.0.1`), so the localhost public URL cannot permit remote first-admin setup takeover. Operators exposing it through an external reverse proxy must set a non-loopback public URL and bootstrap secret. - Role-aware readiness, JSON structured logs, safe worker claim shutdown, and dependency-free Prometheus metrics for request volume/duration, active/stale/failed execution state, schedule lag, corrupt/unavailable repositories, and free space. - SBOM generation at `tools/generate_sbom.py`, generated CycloneDX artifact `m14-sbom.json`, and base-image/source provenance in `m14-provenance.md`. - Metadata, repository, key, upgrade, disaster-recovery, and observability runbooks. ## Green verification ```text docker compose config --quiet # passed (loopback port binding) docker compose build --pull # passed make test-e2e # 1 passed in 51.69s (loopback regression) make check # passed after loopback regression 91 unit/contract, 61 integration, 15 fault, 33 security Ruff/format, mypy (40 files), TypeScript, frontend build all passed python tools/generate_sbom.py # 256 components ``` `test_compose_v2.py` creates its source and host-bind key fixture in pytest temporary directories. The actual service-owned master key is generated only in an ephemeral Compose named volume, then `down --volumes --remove-orphans` removes it. No fixture secret or source directory is committed. The test runs migration, starts the stack, checks readiness and metrics, stops/restarts the worker cleanly, restarts runtime roles, verifies setup metadata persists, and tears down the project.