--- id: RAIL-HO-WP-0010 type: workplan title: "New reefs do not get 80/443 until a substrate grant exists" domain: financials repo: railiance-infra status: finished owner: codex topic_slug: railiance created: "2026-08-15" updated: "2026-08-22" related: - RMASTER-WP-0023 - RAIL-HO-WP-0009 - ADR-0008 state_hub_workstream_id: "226e81e2-2bed-5d3b-869f-0cec7940719c" --- # RAIL-HO-WP-0010 — new-reef host ports Intake from `RMASTER-WP-0023-T05`. ## Goal Host surface for **new** reefs: do not open 80/443 until the reef declaration carries a public substrate grant. `6443` stays operator-only (RAIL-HO-WP-0009). This is not the rapp admission desk. Nydus `2224` stays a named exception. ## T01 — Fail-closed new-reef UFW ```task id: RAIL-HO-WP-0010-T01 status: done priority: high state_hub_task_id: "7935c941-269a-5827-a139-1b02c6b649f6" ``` Bootstrap / inventory for a new reef starts with SSH (and Nydus only if the provider requires it). 80/443 require a cited reef grant. Do not add per-rapp UFW rules on a shared ingress host. **Done when:** a new reef playbook cannot open 80/443 without naming the grant, and `6443` cannot be opened by this path. **Outcome (2026-08-22):** the base role now rejects 80/443 in generic UFW extras and delegates public-web admission to a reef declaration validator. Only ports 80 and 443 are accepted, each must have a matching public substrate grant with reason, approval date, and owner, and 6443 is unconditionally rejected. Goss receives only the resulting grant-backed port list. ## Completion evidence - `python3 -m unittest discover -s tests -v`: 5 tests passed. - Live source validation against `reef-railiance/declarations/reef.yaml` for ports 80 and 443: passed. - Ansible syntax validation remains unavailable on this workstation because `ansible-playbook` is not installed; no live firewall change was applied.