le-app/docs/le-app-database-migration/phase2b-contained-runtime
2026-07-12 21:01:17 -04:00
..
inventory add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
payload add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
tests add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
.gitattributes add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
INSTALL-ORDER.md add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
MANIFEST.sha256 add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
README.md add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
ROLLBACK.md add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00
STATIC-SAFETY-AUDIT.md add Phase 2B contained runtime artifacts 2026-07-12 21:01:17 -04:00

Phase 2B contained Codex runtime — review only

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:

  • pinned Moby launcher;
  • aggregate user-1200.slice resource drop-in;
  • complete user@1200.service filesystem/process/device containment drop-in;
  • root-owned IPv4-only namespace unit/helper;
  • 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.

Validation status

The 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.

See STATIC-SAFETY-AUDIT.md, INSTALL-ORDER.md, ROLLBACK.md, tests/, inventory/, and MANIFEST.sha256. Any edit invalidates the manifest and requires another review.