# Requirement → Unit Map — atheos-blog-lxc **Stage**: INCEPTION — Units Generation (Part 2) > **Deliberate substitution.** The AI-DLC rules mandate `unit-of-work-story-map.md`, which maps > *user stories* to units. The **User Stories stage was skipped** (user-confirmed at the Requirements > gate: "no I'm good to skip"). With no stories to map, this document maps **requirements and > acceptance criteria** to units instead — the same assurance (nothing is silently dropped) applied > to the artifacts that actually exist. ## Functional requirements | FR | Requirement (short) | Unit | |---|---|---| | FR-1 | Alpine 3.23 LXC on scotty, 20 GB root, 2 vCPU/1 GB, onboot, unprivileged | **U1** | | FR-2 | nginx + PHP-FPM serving Atheos; ZIP/OPENSSL/MBSTRING; `allow_url_fopen=On` | **U2** | | FR-3 | Atheos installed, pinned, 5 writable paths, no DB | **U3** | | FR-4 | git integration configured (git installed, `safe.directory`, identity handling) | **U4** | | FR-5 | `armistace/blog` cloned into `workspace/` on `master` | **U4** | | FR-6 | Remote reachable; instructions to switch to SSH; agent doesn't switch it | **U4** (build) + **U5** (document) | | FR-7 | RUNBOOK.md with IP, SSH, workspace path, remote-switch steps, credential setup | **U5** | | FR-8 | README.md | **U5** | | FR-9 | Repeatable provisioning script in the repo | **U5** | | FR-10 | LAN-only; no NPM/DNS/forward | **U2** (bind + no proxy config) | | FR-11 | Agent creates no `armistace` credentials or git identity | **U4** (verification asserts identity is empty) | | FR-12 | `docs/security-notes.md` + `docs/resiliency-notes.md` | **U5** | ## Non-functional requirements | NFR | Requirement (short) | Unit | |---|---|---| | NFR-1 | Fits comfortably in 20 GB | **U1** (sizing) | | NFR-2 | Survives reboot with clone + edits intact | **U1** (onboot) + **U2** (services enabled) + **U3/U4** (persistence) → verified at Build & Test | | NFR-3 | Repeatable / idempotent-friendly provisioning | **U5** | | NFR-4 | No K3s dependency | all (negative) | | NFR-5 | Timezone Australia/Brisbane | **U1** | ## Acceptance criteria | AC | Short | Unit | |---|---|---| | AC-1 | `pct config 136` shows Alpine + 20 GB root + onboot | **U1** | | AC-2 | `http:///` serves Atheos (not 502/404) | **U2**+**U3** | | AC-3 | `blog` present as a project whose files open | **U3**+**U4** | | AC-4 | Edit + save persists to disk | **U3**+**U4** | | AC-5 | `git remote -v` points at Gitea; RUNBOOK gives the SSH switch | **U4**+**U5** | | AC-6 | Reboot → Atheos serves again, clone + edits intact | Build & Test | | AC-7 | RUNBOOK lets another agent re-provision/hand off | **U5** | | AC-8 | **No Python/pelican present** (scope respected) | Build & Test | ## Coverage check | | Count | Assigned to exactly one unit | Unassigned | |---|---|---|---| | Functional requirements | 12 | 12 ✔ | 0 | | Non-functional requirements | 5 | 5 ✔ | 0 | | Acceptance criteria | 8 | 8 ✔ | 0 | **Every FR and NFR is assigned to exactly one unit.** ACs that require two units to build but one moment to verify (AC-2, AC-3, AC-4) list both; AC-6 and AC-8 are whole-system properties verified once at Build & Test rather than owned by a single unit — noted explicitly rather than left implicit.