ADR-0082: KALI.Art Phase A — operator-usable pen-test pod¶
- Status: Accepted
- Date: 2026-05-23
- Driver:
discuss_module_kali_art_2026_05_10locked KALI.Art as "the pen-tester's standard distribution complement to DoYour.Art (which is craft-your-own code)." The v3.7.0 scaffold (PR #678 family — KALI-1) shipped the pod + gVisor RuntimeClass + ttyd launcher + 9 TypeScript schemas; the operator surface was a placeholder until K-A1. - Related: PRs #1012 (K-A1), #1013 (K-A2), #1014 (K-A3), this PR (K-A4); ADR-0025 (offensive-suite parent), ADR-0081 (DoYour.Art Phase A — same operator-surface pattern).
Context¶
The KALI.Art pod (kali-art/), gVisor RuntimeClass (gvisor-offensive, shared with doyour-art), VLAN 2902 NAD, ttyd launcher (Go) + UTXO licence-token gate stub shipped earlier this year. 9 TypeScript schemas in dashboard/src/lib/kali/ (audit, ai-companion, exploit-pattern, nmap-import, pdf-report, pie-workflow, quick-launch, span-comparison, tier-gate) captured the wire shapes. None of this was usable by an operator: there was no dashboard route, the pod's /rpc endpoint did not exist, and the AI Companion / Quick-Launch were schema-only.
The dashboard-only operator-access invariant (project_dashboard_only_operator_access_2026_05_13) treats a feature without UI as incomplete. Phase A closes that for KALI.Art.
Decision¶
Ship KALI.Art Phase A as 4 sub-PRs, mirroring the DoYour.Art Phase A pattern. The 6 open questions from the discuss memo (locked defaults in the memo's "Addendum 1") are reaffirmed verbatim:
| # | Question | Decision |
|---|---|---|
| 1 | Persistent home quota | Team 1 GB / Enterprise 10 GB (locked) |
| 2 | Multi-user collaboration | 1 session per operator (no shared sessions) |
| 3 | Custom tool installation | apt install writes to overlay layer that resets on session end |
| 4 | Kali version pinning | Rolling release + weekly snapshot via CLONER fn 7 |
| 5 | Free trial | Zero free (hard Team+ gate) |
| 6 | Compliance bundle | SOC 2 Type II covers KALI at base level; dedicated audit pack add-on for FIPS / banking |
Phase A sub-PRs¶
| Sub-PR | Scope | Status |
|---|---|---|
| K-A1 | Dashboard route /art-studio/kali (5th tab), session-store.ts (in-memory dual-mode-ready), 4 API routes, tier-gate enforcement (403 Free/Indie + 429 concurrent + 403 prod-DOM), 25 i18n keys × 3 locales |
✅ #1012 |
| K-A2 | Pod /rpc server on :8084 using pkg/cross-module-rpc.Authorize. 3 tools (nmap-quick-scan, sslyze-handshake-probe, nikto-baseline) with target validation + binary_missing branch. ACL ConfigMap. Closes the cross-MÓDULO loop with DoYour.Art (template scapy-plus-kali-nmap.py now end-to-end) |
✅ #1013 |
| K-A3 | Sidebar: Tool Quick-Launch (15 curated tools × 5 categories) + AI Companion chat stub (4-bucket regex keyword map → suggestion list). API /api/kali/ai-companion. 15 i18n keys × 3 locales |
✅ #1014 |
| K-A4 | This PR — ADR + module-docs in 3 langs + recovery-memo entry | ✅ |
Shared security envelope¶
gvisor-offensiveRuntimeClass (runsc) — syscall isolation, shared with DoYour.Art.- VLAN 2902 macvlan, subnet
172.21.0.0/16. NetworkPolicy egress allow-list = DUT INSIDE only; OOBI fabric blocked from KALI's data-plane NIC; customer's MGMT (via RELAY) HARD BLOCKED. - Non-root user (UID 1000), no ServiceAccount token mounted, no ConfigMap / Secret access beyond the ACL mount.
- Cross-MÓDULO
/rpcdefault-deny on both sides (ACL Go lib + ConfigMap matchingplatform/cross-module/acl.yaml). - Audit log mandatory (auditd + shell history JSONL → sealed audit hash-chain). Retention 90 d (Team) / 7 y (Enterprise).
- AI Companion HARD rule: never executes shell commands autonomously — every suggestion is operator-confirmed in the terminal.
DOM mode interaction (carried forward from discuss memo)¶
| DOM mode | Phase A behaviour |
|---|---|
greenfield / staging / lab |
✅ Full enable. Default. |
production |
🚨 HARD BLOCKED in Phase A (403 from /api/kali/sessions). PIE workflow approval + read-only-tools subset lands in K-A5 / Phase B follow-up. |
prod-partition |
⚠ Enable with partition-scoped target enforcement (not in Phase A; deferred). |
Consequences¶
Positive
- The dashboard-only invariant is satisfied for the second member of the offensive suite (DoYour.Art was the first; KALI.Art now matches).
- The 4-sub-PR cadence keeps each merge small + reviewable + revertable.
- The cross-MÓDULO loop with DoYour.Art is closed end-to-end — operators can now write
doyour_sdk.invoke("kali-art", "nmap-quick-scan", ...)from a Scapy art piece and KALI answers from the real pod (templatescapy-plus-kali-nmap.py). - The 3 tools served by
/rpcmap 1:1 to the ACL entries shipped in Phase D-1 — wire stability across MÓDULOs.
Negative / deferred
- K-A5 / Phase B still owes:
- PIE workflow integration (operator-confirmed production override + read-only-tools subset)
- ttyd iframe embedded inside the session page (Phase A surfaces "Session id" + terminal-pending box; the real iframe needs Service exposure work + same-origin reverse-proxy plumbing)
- Real MCP bridge (
kali-art-mcpsidecar fork ofmcp-kali-serverupstream) replacing the AI Companion stub - Audit log + PDF report wiring (schemas exist; transport doesn't)
- PVC
kali-homeper-operator persistence - The 9 schemas in
dashboard/src/lib/kali/(audit, exploit-pattern, nmap-import, pdf-report, pie-workflow, span-comparison) are not yet exercised by the UI. Phase B picks them up one at a time. - The 12-PR roadmap from the discuss memo (K-1 through K-12 + the AI/Caldera Addendum's K-13..K-15) was reorganised into Phase A (K-A1..K-A4) + Phase B (K-B1+). The implementation plan in the memo is now superseded by this ADR.
Alternatives considered¶
- Skip K-A2 (no cross-MÓDULO
/rpc) — would have left the Phase D-2 SDK template (scapy-plus-kali-nmap.py) dangling. Rejected: cross-MÓDULO is the moat differentiator (no competitor has it). - Pin Kali to a snapshot for reproducibility — rejected per the discuss memo Q4 decision: rolling release + weekly snapshot via CLONER fn 7 + operator can opt to pin per-session.
- Open KALI.Art to Free tier with a 1-hour trial — rejected per Q5: hard Team+ gate. Trial path is via the conference-sandbox account, not the production UI.
- Build the AI Companion before the cross-MÓDULO RPC — rejected: RPC is the operator-visible value (running an actual nmap), AI Companion is icing. K-A2 ships first; K-A3 builds on it.
Compliance¶
Per CLAUDE.md: "Dashboard is the ONLY operator interface." Phase A delivers every operator-facing primitive (session create / list / end, AI suggestion, Quick-Launch pick) via /art-studio/kali/*; no kubectl exec into the kali pod required.
Per the locked ZTP-prem posture: Tier B obfuscation preserved (pod stays on ztp-prem.tlsstress.art/tier: B label). gosec W0 baseline stays at 0 findings post-merge (4 new inline-annotated #nosec for the launcher's intentional exec.Command(ttyd) + os.OpenFile(audit_path) + os.MkdirAll(audit_dir) + log-with-env-var-arg; documented rationale per site).
References¶
- discuss_module_kali_art_2026_05_10
- ADR-0025 — offensive-suite parent
- ADR-0081 — sister DoYour.Art Phase A
- project_dashboard_only_operator_access_2026_05_13
- PRs #1012, #1013, #1014, plus this PR — K-A1 through K-A4