le-app/docs/le-app-database-migration/phase2b-contained-runtime/STATIC-SAFETY-AUDIT.md

2.9 KiB

Static safety audit

Status: pass for final review; execution remains approval-gated.

  • Endpoint: daemon service, daemon configuration, client context, environment, and tests name only unix:///run/user/1200/docker.sock. No TCP, SSH, rootful, fallback, or inherited default endpoint is accepted.
  • Lifecycle: no linger artifact or command exists. Root explicitly controls user@1200.service; the namespace unit cannot start until a separate operator approval marker exists.
  • Filesystem: the complete user manager receives a private read-only /srv with only /srv/le-app-codex rebound, empty private /var, /mnt, /media, and /opt, private /tmp, protected homes/processes, explicit production/archive/transitional path tests, and inaccessible rootful sockets/runtime data.
  • Devices/resources: closed device policy permits only FUSE and TUN. Aggregate CPU, memory, swap, and task limits cover the user manager and descendants. Hard disk-growth enforcement is deferred and is not a Phase 2B installation blocker; these mandatory controls are not a storage quota.
  • IPv4-only: the namespace receives only 10.200.120.2/30; namespace-scoped IPv6 is disabled; daemon IPv6/ip6tables are disabled; nftables drops IPv6 from the project interface.
  • Egress: only DNS to 9.9.9.9/149.112.112.112 and public TCP 80/443 are accepted. Nonpublic/reserved IPv4, loopback, link-local/metadata, multicast, all RFC1918 Docker/LAN/WireGuard ranges, direct SMTP, and all other protocols/ports drop.
  • Host isolation: host-to-project forwarding and unsolicited inbound traffic drop. Project traffic to host private addresses and observed public/NAT address 74.67.173.56 drops. RootlessKit host-loopback and external port publication are disabled and tested negatively.
  • DNS: the operator-approved Quad9 malware-blocking, DNSSEC-validating IPv4 pair avoids any LAN exception. /etc/resolv.conf is rebound read-only for the user manager. The observed 192.168.10.1 router resolver remains denied.
  • Existing nftables: the verified ruleset has no le_app_codex objects. Dedicated tables avoid editing Docker-owned chains. Interface-scoped terminal drops remain effective alongside existing Docker base chains.
  • Inventory: the root record checksums pass. UID 1200 is inactive, not lingering, has no process/runtime/socket; project ACLs and modes match Phase 1; no project-rooted mounts exist; all 41 Docker networks fall within denied IPv4/IPv6 space.
  • Rollback: names and paths are Phase 2B-specific; teardown deletes only the project tables, namespace/veth, marker, and manifest-listed files.

Hard stops remain: changed Docker version/launcher hash, changed inventory, public/NAT address drift, missing approval marker at namespace-start time, pre-existing project tables/namespace, any acceptance failure, or any endpoint other than the single rootless Unix socket. ProtectProc=invisible remains an unproven runtime acceptance candidate.