# 43 — Milestone 0 host validation ## Outcome Milestone 0 passed its host-dependent acceptance gate on 2026-07-27. The authoritative target was an Unraid 7.2 server (`Tower`) with Docker 27.5.1, Compose 2.40.3, the pinned Node.js 24.18.0 image, and the pinned PostgreSQL 17.9 image. The workstation's unsupported Node.js 23 runtime was not used as release evidence. This report closes only Milestone 0. Later product acceptance items remain assigned to their milestones in `IMPLEMENTATION_PLAN.md`. ## Specification and clean install The validation checkout was created from Git without copying `node_modules` or build output. A frozen pnpm 10.33.0 install under Node.js 24.18.0 succeeded. The following checks passed: - `python3 scripts/validate_pack.py`: 28 P0 packages, six normative examples, 72 catalog entries, nine schemas, 28 golden prompts, and 68 release-evidence requirements; - `python3 scripts/reference_compose.py --check`: all 28 prompts matched; - `pnpm verify`: formatting, lint, strict typecheck, unit tests, both specification checks, and all 13 production builds; - `pnpm test:security`: 11 tests passed; - PostgreSQL-backed integration gates: six files and 15 database tests passed, including idempotent jobs, workspace isolation, guarded leases, stale lease recovery, generated-run persistence, and artifact integrity. The CI image needed the packages in `scripts/requirements-validate.txt`; the canonical workflow now installs those exact dependencies before invoking the Python validators. ## Production Compose evidence All targets built from the clean checkout. The production stack started with an empty PostgreSQL volume. The migration service exited successfully, web and worker ran as the unprivileged `node` user with a read-only root filesystem, and PostgreSQL was not published to the host. Web, worker, and PostgreSQL reached healthy state without a restart loop. The first worker image exposed an ESM/Pino bundle defect. The standalone bundle was repaired with an ESM-safe `createRequire` shim and a regression assertion. The rebuilt worker then stayed healthy and processed both a safe `system.health-probe` job and an unsupported job. The first succeeded; the second reached a terminal `job_type_unsupported` state without executing job content. A controlled worker restart did not duplicate either job. `/health/live` returned `200` while PostgreSQL was deliberately stopped. `/health/ready` returned `503` with the explicit `database-unavailable` reason. After PostgreSQL restarted, readiness returned to `200` and both long-running services reconnected. Running the migration against the initialized database exited zero and left the two recorded migrations unchanged. A migration run against a deliberately unreachable, non-secret test URL exited non-zero with an explicit connection failure; it did not silently continue. ## Identity, authorization, catalog, and persistence Fresh first-run setup returned `201`; a repeated setup attempt returned `409`. The built-in API returned 28 persisted records. Wrong credentials returned `401`, correct local credentials returned `200`, and the session survived a service restart. Logout revoked the session. Password reset, expiry, replay, session revocation, and legacy-hash upgrade were exercised against PostgreSQL without exposing reset tokens in logs. The live workspace matrix proved viewer read, editor write, owner control, cross-workspace denial, disabled-user denial, and no instance-administrator bypass. `pnpm validate:m0-persistence` uses the production composer and the real authorization, PostgreSQL, and local-artifact adapters. It rendered the root-cause fixture byte-identically, persisted the immutable run and a 6,806 byte Markdown artifact, and read the artifact back with SHA-256 `8389b948158cc35fa1716e170c9893bd3939dc3aaad9311971b6c267f835ae1b`. After a full Compose restart, the same command returned the original run and artifact IDs with both `created` flags false and the same digest. ## Browser evidence The in-app Chromium browser verified the live Unraid deployment at its LAN address: - home and package detail rendered persisted catalog data without Gitea; - the setup page reported `Instance ready` and did not reopen first-run; - an invalid local sign-in returned the same generic failure and cleared the password field; - the `root-cause-bugfix` detail showed its persisted version and digest; - a 390 by 844 viewport had no horizontal overflow; - semantic headings, links, inputs, status, alert, and button roles were present; - no browser console warnings or errors were recorded. The canonical Playwright gate separately covers keyboard focus, reduced motion, security headers, recovery, login, and responsive behavior. ## Backup and restore drill A PostgreSQL custom-format logical dump and a compressed artifact-volume archive were created under the restricted validation directory. Their backup digests were recorded on the host. They were restored into a new PostgreSQL 17 volume and a new artifact volume on an isolated Docker network. The validation command found the original run and artifact without creating replacements and verified the 6,806 bytes and SHA-256 shown above. The temporary restore container, network, and volumes were removed after verification; the backup files were retained as operator evidence. Encryption and session keys are not part of these ordinary backup archives. They remain separate operator secrets and are required independently for a real instance restore. ## Security and logging The configured secret values, authorization headers, and bearer-token markers were absent from production Compose logs. PostgreSQL recorded two deliberate operator validation query errors; neither contained a configured secret. The application services emitted structured, redacted records and no application stack trace after the worker repair. No default credential, Docker socket, host PID namespace, privileged mode, or arbitrary command-execution path was introduced. ## Reproduction commands From a fresh checkout with the documented environment values set: ```bash corepack pnpm install --frozen-lockfile python3 -m pip install --requirement scripts/requirements-validate.txt pnpm verify pnpm test:security docker compose build docker compose up -d docker compose ps ``` The persistence validator is intentionally explicit and requires both targets: ```bash DATABASE_URL='postgresql://…' \ ARTIFACT_ROOT='/absolute/artifact/path' \ pnpm validate:m0-persistence ``` It is a validation client, not an HTTP route or worker job, and never executes repository or imported content. ## Milestone boundary The authenticated composer UI/API, full Library Explorer, repository-profile management, export formats, Gitea adapter, and final release evidence belong to later milestones. They are not claimed by this report. Milestone 1 may begin because the repository contract and first vertical slice now have live proof.