# Phase 4 — Surface C: terminal ~2 days. First surface accepting user input — injection (A03) is the primary risk here. ## RED - [ ] `exec_parse_test.go` — fuzz corpus: every non-allowlisted input rejects and performs zero upstream calls - [ ] `exec_test.go` — unknown namespace rejects on snapshot membership, not regex ## GREEN - [ ] `POST /api/exec` — session cookie, 20/min/session; input parses to a closed command enum, anything unmatched rejected before any lookup - [ ] Command set: `get nodes`, `get pods `, `get apps`, `top nodes`, `describe pod `, `help` - [ ] Namespace and resource-name arguments validated by **set membership against current snapshot**, not regex/escaping - [ ] No shell, no `exec`, no `kubectl` binary in the container image - [ ] Frontend: reuse [components/InteractiveTerminal.tsx](../components/InteractiveTerminal.tsx), wire to `/api/exec` - [ ] Structured logging: every rejected `/api/exec` input logged ## REFACTOR - [ ] `simplify` pass on the enum parser ## Verify ```bash # attempt injection payloads against /api/exec; all rejected, all logged curl -X POST https://riotpiao.com/api/exec -d '{"cmd":"get pods; rm -rf /"}' ``` Next: [06-phase5-chat.md](06-phase5-chat.md)