# 44 — Milestone 1 package-ingestion evidence ## Outcome Milestone 1 passed on 2026-07-27 at commit `b7dcb5d041f78027c9b6d3edf1d630098337befd`. The authoritative host was the Unraid 7.2 `linux/amd64` server with Docker 27.5.1, Compose 2.40.3, the pinned Node.js 24.18.0 image and PostgreSQL 17.9. The Windows Node.js 23 runtime was not used as milestone evidence. This milestone closes the canonical built-in content model and persistence contracts. It does not claim the Library Explorer UI, private ZIP import, Prompt Lab or package export; those remain assigned to later milestones. ## Content validation and catalog governance The runtime loader validates package schemas, normalized UTF-8 content, declared inventory, non-executable regular files, condition and template semantics, lifecycle evidence and deterministic digests. Failures use structured `{ path, code, message, remediation }` issues. A catalog load aggregates errors across package directories rather than hiding later failures. The separate seed-catalog loader validates all 72 roadmap entries and cross-checks the 28 publishable P0 entries against runtime package identity, title, category, type, risk tier, default mode and default autonomy. P1/P2 entries are never materialized as executable runtime packages. Unit evidence includes malformed YAML, schema failure, semantic secret exposure, unknown template variables, executable files, invalid UTF-8, hardlinks, multi-package aggregation, catalog mismatch and duplicate identity. The governed Python validator independently confirmed 28 P0 packages, six normative examples, 72 catalog entries, nine schemas and 28 golden prompts. ## Import, storage and query contracts The application layer owns an importer contract independent of web and worker frameworks. The PostgreSQL adapter uses an advisory lock and one transaction to create playbook identities and immutable semantic versions. Identical imports are no-ops; a reused semantic version with another digest is rejected with `playbook_version_conflict`. A database trigger independently prevents updates to published `playbook_versions` rows. The worker validates and cross-checks all built-ins before polling, imports them through the shared adapter, and logs counts only. Both supported layouts are covered: production `/content/{playbooks,catalog}` and development `/app/content/playbooks` plus `/app/catalog`. The PostgreSQL catalog chooses the highest eligible semantic version, including correct numeric and prerelease ordering, and excludes draft or deprecated versions from the current recommendation. Search uses the indexed search projection and typed category, risk, lifecycle and source filters. Detail queries return the current package plus complete version history; exact-version queries return the immutable manifest, template and quality evidence. The HTTP boundary exposes: - `GET /api/v1/playbooks` with `{ items, nextCursor, facets }`; - validated `q`, `category`, `riskTier`, `lifecycle` and `source` parameters; - `GET /api/v1/playbooks/{slug}` for current detail and history; - `GET /api/v1/playbooks/{slug}/versions/{version}` for exact content; - stable `422` responses for invalid query values. A public ZIP validation/import endpoint is intentionally not invented here. The normative API assigns operator package import to the Prompt Lab milestone; M1's invalid-input acceptance is proved at the canonical content boundary. ## Authoritative validation The clean Git-bundle clone contained only committed files. The development target performed a frozen pnpm 10.33.0 install under Node.js 24.18.0. Commands and results: | Command or check | Result | | --- | --- | | `pnpm verify` | PASS: formatting; 13 lint, typecheck and build workspaces; all unit tests; pack validation; reference composition. | | `pnpm test:security` | PASS: 2 files, 11 tests. | | `python3 scripts/validate_pack.py` through `pnpm verify` | PASS: 28 P0, 6 examples, 72 catalog entries, 9 schemas and 28 golden fixtures. | | `python3 scripts/reference_compose.py --check` through `pnpm verify` | PASS: 28 byte-identical prompts. | | `pnpm db:migrate` on an empty PostgreSQL 17 volume | PASS; replay after tests also exited zero. | | `pnpm test:integration` with explicit database and artifact targets | PASS: 3 files, 7 tests. | | Production `docker compose build` | PASS for web, worker and migrate; image digests recorded by Docker. | | Production `docker compose up -d --wait` | PASS: PostgreSQL, web and worker healthy; migration exited successfully. | An initial operator test invocation omitted the required temporary `ARTIFACT_ROOT`; that invocation was rejected explicitly. Its named temporary database and artifact volumes were removed, recreated empty and then used for the passing migration and integration run above. ## Live production evidence On the fresh Compose database, the worker reported 28 inserted playbooks and 28 inserted versions. After a controlled worker restart it reported zero inserts and 28 unchanged versions and returned healthy. Direct PostgreSQL counts were 28 playbooks and 28 versions. Live API checks returned 28 list items. The combined query `root cause` plus `bugfixing`, `moderate`, `reviewed` and `built_in` returned only `root-cause-bugfix`. Its detail response exposed current version `1.0.0` and one history item. The exact-version response contained the manifest, 591-byte template and quality record. An invalid risk tier returned `422`. The PostgreSQL integration test attempted to mutate a published version and observed the immutable trigger rejection. It also proved identical re-import, digest-conflict rejection, indexed search, full detail and exact-version reads. Web and worker ran as user `node` with read-only root filesystems and remained healthy. A production log scan found none of the configured secret values and no `Authorization:` or `Bearer ` markers. ## Browser evidence The in-app Chromium browser exercised the live Unraid deployment: - the home catalog rendered persisted built-ins without Gitea; - the Root-Cause Bug Fix detail rendered identity, lifecycle, risk, version and digest and stated the non-execution boundary; - at 390 by 844 CSS pixels the detail article remained visible and document width did not exceed viewport width; - browser warnings and errors: zero. Search controls, URL-preserved filters, favorites, dense view, enriched package detail and their keyboard/accessibility gates remain Milestone 2 scope. ## Milestone decision All Milestone 1 acceptance bullets in `IMPLEMENTATION_PLAN.md` have actual unit, PostgreSQL, production-container and browser evidence. No project-wide release artifact or final handoff is created at this intermediate gate. Milestone 2 may begin.