Status: complete staged review set, 2026-07-12. **Do not install or execute it.** No Phase 2B file has been copied to a host target; no namespace, nftables table, service, user manager, Docker daemon, container, Codex process, authentication, checkout, migration source, credential, or production change was created.
## Read-only verification record
- Docker was revalidated before launcher selection: package `1:29.6.1-1`; client `29.6.1` build `8900f1d330`; daemon binary `29.6.1` build `8ec5ab355a`.
- The exact Moby `docker-v29.6.1``contrib/dockerd-rootless.sh` was fetched for review and reproduced SHA-256 `904c9b9e35f6927c0a5e65afb4d35b6bc9eb1278c878044501281fc728c9be46`.
- Future acceptance images are pinned to OCI indexes: Alpine 3.23.3 `sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659` and nginx 1.29.4-alpine `sha256:4870c12cd2ca986de501a804b4f506ad3875a0b1874940ba0a2c7f763f1855b2`.
- The root inventory at 2026-07-12 20:24 EDT is retained verbatim under `inventory/`; every checksum in its original `SHA256SUMS` passes. Host interfaces include `192.168.10.151/24` on `enp4s0`, `10.98.0.2/24` on `wg0`, public IPv6 `2603:7080:7500:1279:75aa:d64d:4cf0:8f10/64`, loopback, and the Docker bridges below. Observed public IPv4 is `74.67.173.56`. The observed gateway/router resolver is `192.168.10.1`; it is **not approved DNS** by observation.
-`/etc/resolv.conf` also observes link-local IPv6 resolver `fe80::3e8c:f8ff:fef4:2590%enp4s0`. The proposed namespace is IPv4-only, so it is not usable there.
- Observed Docker bridge IPv4 subnets are `10.1.0.0/16`, `10.2.0.0/16`, `10.3.0.0/16`, `10.4.0.0/16`, `10.9.0.0/16`, `10.10.0.0/16`, `10.13.0.0/16`, `10.16.0.0/16` through `10.20.0.0/16`, `10.24.0.0/16`, `10.26.0.0/16` through `10.32.0.0/16`, `10.40.0.0/16`, `10.41.0.0/16`, `10.55.0.0/16`, `10.99.0.0/16`, and `172.17.0.0/16` through `172.31.0.0/16` except `172.24` is present and all ranges in that continuous interval were observed. The policy denies their covering RFC1918 ranges and the preflight re-inventories them.
- Observed Docker bridge IPv6 includes `fd00:1::/64`, `fd00:3::/64`, `fd00:4::/64`, `fd00:9::/64`, `fd00:10::/64`, `fd00:16::/64`, `fd00:17::/64`, `fd00:18::/64`, `fd00:20::/64`, `fd00:24::/64`, `fd00:26::/64` through `fd00:31::/64`, `fd00:40::/64`, `fd00:41::/64`, and link-local `fe80::/64` addresses. Namespace IPv6 is disabled and forward traffic is dropped.
-`user@1200.service` is loaded/static but inactive/dead; only the packaged `10-login-barrier.conf` drop-in exists. UID 1200 is not logged in or lingering; no UID 1200 process was observed. `/run/user/1200/docker.sock` is absent.
-`/srv/le-app-codex` is `root:le_app_codex` mode `0750`; `home`, checkout, runtime, testing, and build directories are UID/GID 1200 with mode `0700`; the source directory is root-owned `0550`; nonproduction secrets are root-owned `0750`. ACLs add no access beyond those modes. The root inventory found no project-rooted mounts.
- Root Docker inspection records 41 networks, all covered by the private/IPv6 denials. The complete nftables export has no pre-existing Phase 2B table, chain, namespace, or interface. `tests/00-read-only-preflight.sh` requires a fresh matching inventory immediately before installation.
## Artifact map
The `payload/` tree mirrors proposed absolute installation paths and makes each file separately reviewable:
- private read-only resolver configuration using the proposed public Quad9 IPv4 pair;
- separate default-deny nftables tables with reviewed host/network values;
- genuine rootless Docker user service;
- daemon and client context configuration accepting only `unix:///run/user/1200/docker.sock`;
- preflight, inert containment, and rootless Docker positive/negative tests;
- exact installation/acceptance order and Phase 2B-only rollback.
There are no remaining documentation sentinels. The operator approved Quad9's malware-blocking, DNSSEC-validating IPv4 pair, `9.9.9.9` and `149.112.112.112`. It requires **no LAN-address exception**; `192.168.10.1` and all of `192.168.0.0/16` remain denied. The root-created approval marker is intentionally absent because installation has not begun. Observed public/NAT IPv4 `74.67.173.56` remains explicitly denied; drift is a fail-closed configuration-review condition before later namespace restarts or policy regeneration.
## Unresolved operator inputs
1. Hard disk-growth enforcement is deferred and is not a Phase 2B installation blocker. Filesystem visibility and CPU/memory/task controls remain mandatory but are not a hard storage quota.
2. Whether `ProtectProc=invisible` passes inert and runtime acceptance without breaking rootless Docker; compatibility must not be assumed.
3. Later, separate approvals for starting the user manager/runtime and for the Codex authentication method. No Forge SSH exception, TCP Docker endpoint, rootful socket, LAN access, direct SMTP, or inbound publication is proposed.
The committed review set's root pre-install validator passed on TITANSERVER with zero failures: both manifests, staged nftables syntax, staged systemd units/drop-ins, shell/JSON syntax, Phase 1 ownership/modes, mount absence, installed-path absence, inactive user manager, absent linger/process/socket, and unchanged public/NAT IPv4 all passed. Missing `/usr/local/libexec` warnings were expected for the uninstalled payload. That host run predates the uncommitted Stage 1 recovery amendments; the future installer reruns the root validator against the then-current committed bytes before copying anything.
Stage 1 installation and rollback are repository-native scripts, not pasted heredocs. `tests/30-install-stage1.sh` installs exactly the 16 approved static files and validates shared parents without changing them. State uses immutable, verified generation directories under `/var/lib/le-app-codex-phase2b/stage1/generations`; a root-owned regular `current` pointer is the single atomic commit point. `IN_PROGRESS` is durable before payload copying and after every directory/file transition; `COMPLETE` requires exactly all 16 files and no pending record. `tests/31-rollback-stage1.sh` uses the strict parser in `tests/stage1-state-lib.sh`, supports both statuses, journals rollback with an atomic transaction-directory tombstone, removes only recorded matching objects, and preserves retryable state on payload or directory failure. The non-mutating `tests/32-stage1-state-tests.sh` exercises the shared parser, publication failpoints, pointer/generation rejection, partial and complete rollback simulations, and failure preservation in a temporary fake filesystem. Neither operational script creates the approval marker, reloads systemd, loads nftables, creates a namespace, or starts/enables anything.
See `STATIC-SAFETY-AUDIT.md`, `INSTALL-ORDER.md`, `ROLLBACK.md`, `tests/`, `inventory/`, and `MANIFEST.sha256`. Any edit invalidates the manifest and requires another review.