ADR-0095 — Lab Deployment Staging wizard (6-PR wave)¶
- Status: Accepted
- Date: 2026-05-24
- Deciders: André Luiz Gallon
- Surface: Dashboard
/admin/lab-staging(multi-phase wizard) - Wave: WIZ-1 + WIZ-2 + WIZ-3 + WIZ-4 + WIZ-5 + WIZ-6 (6 sub-PRs, ~4200 LoC, 211 Vitest tests)
- Strategy memo: discuss_lab_deployment_staging_2026_05_09.md
- Related ADRs: ADR-0011 (Topology axes) · ADR-0015 (Help Center) · ADR-0017 (Backup/DR) · ADR-0094 (PURE.Art — same Dashboard surface invariant)
- Patent claim: none (UX/UI feature, not a patentable mechanism)
Context¶
Setting up the bench from "first OOBI cable" to "stacks running" has historically required:
- Reading 10+ vendor docs (one per equipment type)
- Manually translating between CLI/API formats
- Hand-running connectivity checks across L1/L2/L3
- Calculating per-server resource budgets in a spreadsheet
- Hand-writing
platform/topology.yamlandplatform/deployments/<id>.yaml - Running
kubectl apply -k k8s/dut/+kubectl patch …+ remembering the strategic-merge-patch syntax
A novice operator (CLAUDE.md's primary user — assumed zero deep knowledge) has no realistic path through this without senior help. The wizard is the materialisation of CLAUDE.md's load-bearing invariant: "Dashboard is the ONLY operator interface" — extended to the day-0 setup path.
The second load-bearing constraint, locked 2026-05-09: infrastructure stability > horse power of agents. The wizard's tier allocator (WIZ-5) refuses setup when T0 budget would underflow — operator must add servers before proceeding, never "borrow" from observability tier to give more muscle to T4 agents.
Decisions¶
10 locked decisions across the 6 sub-PRs (Q1-Q10 from memo):
-
Q1 — CLI snippets per vendor (Medium help, not videos): Ready-to-paste recipes for OOBI IP + SSH + LLDP/CDP per all 6 memo-mandatory NGFW vendors (Cisco FTD, IOS-XE/NX-OS, Palo Alto, Fortinet, Check Point, Sophos, Juniper SRX) + 3 switches (VyOS, Arista, Aruba). Videos / AI chat defer to v5.x+.
-
Q2 — Heuristic affinity v5.0, ML v5.x+: Pure-function suggester applies memo's rules (NGFW = lowest hops; personas = max NICs; infra = fastest disk). Hybrid path — heuristic ships now, ML grafts on later from historical run data.
-
Q3 — Layered detection (LOCKED): Pre-step
interface-prepare(no-shutdown + speed) + pre-stepdiscovery-protocols-enable(CDP/LLDP per vendor) + L1 link state + L2 MAC OUI cross-val + LLDP/CDP + L3 SNMP + ARP sweep + REST API. MAC OUI cross-validation is the load-bearing technique — catches swapped cables + wrong-vendor inventory entry before they break Phase 6. -
Q4 — HTML5 native drag-and-drop: react-flow swap deferred to v5.x+ to avoid +50KB dep mid-wave. HTML5 native dragstart/dragover/drop covers the MVP UX (operator drags stack onto server drop zone; works on all browsers without dep weight).
-
Q5 — Both DB + YAML export: DB row in
lab_deploymentsfor runtime queries; YAML export toplatform/deployments/<id>.yamlso operator can commit to their company's git repo. Deterministic stdlib-only YAML rendering. -
Q6 — Wizard asks update vs fresh: When operator re-enters with an in-progress deployment, dialog offers 3 options: resume / edit any prior phase / start fresh. ALL options preserve audit trail in
lab_deployments_history— every PATCH snapshots prior row first. -
Q7 — Stepper navegável: Any prior phase is clickable for revisit + edit. Phases AFTER current are gated until operator advances through them. Terminal states (completed/failed/cancelled) allow read-only browsing of any phase.
-
Q8 — Real-time conflict validation:
validatePlacementsruns on every drag-drop change; surfaces ALL conflicts simultaneously (VLAN duplicates + switch-port duplicates + NGFW-port duplicates + RAM overcommit) so operator sees the full picture. -
Q9 — Background scans permitted: Auto-discovery daemon may run in parallel with Phase 1 inventory entry (operator types specs while daemon scans subnets). UI stays sequential; background work is invisible.
-
Q10 — v5.0 MVP scope: Phases 1+2+3-manual+5+6+7 in v5.0; Q2 AI affinity in v5.1; Q1 heavy help (videos + AI chat) in v5.x+.
Consequences¶
Positive¶
- Novice operator can bring up a lab without senior help: 7-phase guided path with CLI snippets + verified cabling + heuristic affinity + capacity-bound enforcement + auto-config delegation + stack deploy.
- Reserved-resources policy is mechanically enforced: T0 underflow = hard-block (wizard refuses setup); T1/T2 = warn + confirm; never robs T0-T3 to feed T4.
- MAC OUI cross-validation catches setup errors early: Wrong vendor on a port surfaces RED in Phase 2 BEFORE the operator wastes hours on Phase 6 auto-config.
- Audit trail survives wizard re-runs:
lab_deployments_historyappend-only log preserves every snapshot; stepper navigation + Q6 update-vs-fresh dialog don't lose data. - YAML export is git-friendly: Deterministic, human-readable, drops into
platform/deployments/<id>.yaml; operator can review + version-control without owning the wizard schema.
Negative¶
- Phase 6 auto-config defers to SSH/Ansible orchestration (not yet shipped): WIZ-5 lib + UI stubs for Phase 6 exist but delegate to a separate orchestration engine; real auto-config lands when
discuss_ssh_telnet_orchestration_plane_2026_05_09is implemented. - Real-time Phase 2 connectivity engine is currently stubbed:
connectivity-engine.tsimplements verdict logic + MAC OUI catalogue, but the data populatingPortObservationcomes from Ansible/SSH (not yet wired) — operator sees the table render but with synthetic data until Phase B-late. - react-flow not used at v1: HTML5 drag-drop UX is functional but less polished (no zoom/pan/minimap). Operator can request the upgrade in v5.x+ once UX has stabilised.
- No videos / AI chat in v1: Q1 LOCKED Medium; CLI snippets only. Operators unfamiliar with vendor CLIs still need to read snippet notes + try-it-yourself.
Alternatives considered¶
- Use Helm chart + kubectl manifests as the operator surface: Rejected per CLAUDE.md invariant ("Dashboard is the ONLY operator interface"). Manifests still exist underneath; the wizard is the only surface that touches them.
- Skip the tier allocator and let operators size T4 freely: Rejected. Memo §"Reserved-resources policy" is load-bearing — without T0 hard-floor the wizard would let operators ship a lab that can't report results, defeating the whole point.
- Single-page form instead of 7-phase wizard: Rejected. Novice operators need stepwise guidance; a 7-section form would overwhelm + skip the early-error catches (Phase 2 OUI cross-val).
- react-flow for drag-drop at v1: Rejected (per Q4 lock). +50KB dep mid-wave; HTML5 native is sufficient for MVP UX.
Compliance / governance¶
- CLAUDE.md invariant: Dashboard-only operator interface — preserved (wizard touches schema + K8s via API routes, never
kubectl exec). - Audit trail:
lab_deployments_historyappend-only log; every PATCH snapshots prior row first; FK CASCADE on the parent ensures clean delete (operator can export YAML beforehand). - Reserved-resources policy (memo §"CRITICAL LOCKED"): T0 hard-floor enforced by
computeCapacity; SSD/NVMe requirement enforced; horse-power suggestion never robs from upper tier. - Per-deployment YAML export: Operator's git repo has the source-of-truth; wizard DB is runtime-only (Q5 LOCKED both paths).
References¶
- Strategic memo: discuss_lab_deployment_staging_2026_05_09.md
- Recovery memo: project_lab_staging_wizard_complete_2026_05_24.md
- Help Center primer: lab-deployment-staging
- Topology axes: ADR-0011
- Help Center policy: ADR-0015
- Backup/DR: ADR-0017
- Dashboard invariant:
project_dashboard_only_operator_access_2026_05_13 - Personas IP scheme:
project_personas_v43_public_ip_2026_05_13 - OOBI fabric:
project_oobi_no_vxlan_directive_2026_05_14