Skip to content

PR26.2: panel-survival framework + FakePanelAdapter#529

Merged
itcmsgr merged 1 commit intomainfrom
feat/pr26.2-panel-framework
Apr 29, 2026
Merged

PR26.2: panel-survival framework + FakePanelAdapter#529
itcmsgr merged 1 commit intomainfrom
feat/pr26.2-panel-framework

Conversation

@itcmsgr
Copy link
Copy Markdown
Owner

@itcmsgr itcmsgr commented Apr 29, 2026

Summary

Generic hosting-panel adapter framework. Adds PANEL-SURVIVAL-001 as a new post-install assertion so a detected panel with a failing integration cannot reach StateCommitted (unless the operator passes --no-panel).

PR26.2 ships the framework + a test-only FakePanelAdapter. No real adapter is registered — DirectAdmin lands in PR26.3 only after this merges.

Scope

Hard exclusions preserved per the operator authorization:

  • No DirectAdmin adapter
  • No cPanel/Plesk adapter
  • No authority residue classifier
  • No restore redesign
  • No firewall mutation
  • No runtime nft surgery
  • No host destructive testing

Invariant — PANEL-SURVIVAL-001

If a hosting panel is detected before lifecycle mutation, then nftban must either preserve the panel's required service ports through the canonical ports model and validate integration success, OR abort before StateCommitted with a clear panel-safety error. Panel detected + panel integration failure must never reach StateCommitted, unless the operator explicitly disables panel integration with a supported flag.

Implemented as: assertion panel_survival_ok appended to RunAssertions. Failure → AllPassed returns false → existing gate at cmd/nftban-installer/phases.go falls through to StateDegraded. No phases.go mutation logic added — only an opts-bearing call to the new RunAssertionsWithOpts.

Architecture

internal/installer/panelfw/
  panelfw.go         PanelAdapter interface, types, policy, registry, EvaluateAdapters
  panelfw_test.go    FakePanelAdapter + 14 framework tests (test-only — never compiled into prod)
internal/installer/validate/
  assertions.go      +AssertionOpts, +WithPanelPolicy, +panel_survival_ok assertion, +RunAssertionsWithOpts
  panel_survival_test.go   3 integration tests proving the gate via AllPassed
cmd/nftban-installer/
  flags.go           +--no-panel
  main.go            +globalPhaseData.noPanel
  phases.go          phaseValidate calls RunAssertionsWithOpts with operator-derived policy

The framework calls only the contract methods on adapters (Detect, RequiredPorts, ValidateReachability). All three are read-only by interface contract. PR26.2's FakePanelAdapter has zero mutation surface — verified structurally by the TestFramework_NoExecutorMutation table test.

Test matrix (FakePanelAdapter spec)

Case Result
Fake panel detected + integration failure (RequiredPorts errors) StateCommitted blocked
Fake panel detected + integration failure (ValidateReachability errors) StateCommitted blocked
Fake panel absent pass
AllowPanelAbsent=false + no panel detected blocked (policy variant)
Fake panel detected + happy path pass
Fake panel detected + failing integration + OperatorDisabled=true pass (operator opt-out)
Fake panel detected + happy path + OperatorDisabled=true pass
Fake panel detected + failing integration + RequirePanelSuccess=false pass (migration variant)
Multi-adapter registry: first-detected-wins; later adapters not called proven
Framework executor-mutation audit: 0 commands, 0 written files across 4 shapes proven
Default registry empty proven
Register / RegisteredAdapters returns a copy proven
Register(nil) is a no-op proven
DefaultPolicy() values proven
Nil logger tolerated proven

Plus 3 validate-level integration tests:

  • TestRunAssertions_PanelSurvival_BlocksStateCommitted — adapter failure → AllPassed=false
  • TestRunAssertions_PanelSurvival_OperatorDisabled_DoesNotBlock--no-panelAllPassed=true
  • TestRunAssertions_DefaultPath_PanelSurvivalPasses — default RunAssertions (empty registry) → pass

Lab proof (lab4, RHEL/cPanel, go1.25.8)

Branch base: cdf8f770 (origin/main, post-PR26.1 merge).

go vet ./internal/installer/panelfw/... ./internal/installer/validate/... ./cmd/nftban-installer/...
  → VET_EXIT=0 (clean)

go test -v ./internal/installer/panelfw/... ./internal/installer/validate/...
  → PASS — all 14 panelfw tests + all validate tests including the 3 new panel_survival tests

go test ./...
  → FULL_EXIT=0 — 65 packages PASS, 0 FAIL
  (was 64 before PR26.2; +1 = new internal/installer/panelfw)

TMPDIR=/root/build-tmp (lab4: both /tmp and /var/tmp are noexec under cPanel).

Test plan

  • go test ./internal/installer/panelfw/... green on lab4
  • go test ./internal/installer/validate/... green on lab4 (no regression vs PR26.1 baseline)
  • go vet ./internal/installer/panelfw/... ./internal/installer/validate/... ./cmd/nftban-installer/... clean on lab4
  • go test ./... green on lab4 (65 packages, 0 fail)
  • CI green on this PR (incl. staticcheck)
  • Auditor on-PR final review

🤖 Generated with Claude Code

PR26.2 — generic hosting-panel adapter framework. Adds the
PANEL-SURVIVAL-001 invariant: a detected panel whose adapter
integration fails must not reach StateCommitted unless the operator
opts out via --no-panel.

internal/installer/panelfw/ (new package):
  - PanelAdapter interface (read-only contract)
  - PanelDetection / PanelPolicy / PanelResult types
  - Register / RegisteredAdapters (registry; empty in PR26.2)
  - DefaultPolicy (RequirePanelSuccess=true, AllowPanelAbsent=true)
  - Evaluate / EvaluateAdapters (test-callable variant)
  - FakePanelAdapter (test-only via _test.go) + 14 spec tests

internal/installer/validate:
  - new assertion `panel_survival_ok` consuming opts.PanelPolicy
  - new RunAssertionsWithOpts(...) entry point + AssertionOpts.WithPanelPolicy
  - existing RunAssertions delegates to RunAssertionsWithOpts with default opts;
    callers stay source-compatible
  - integration tests prove the assertion blocks StateCommitted via AllPassed

cmd/nftban-installer:
  - new --no-panel flag
  - phaseData.noPanel propagates from cfg
  - phaseValidate (VALIDATE_1 and VALIDATE_2) calls RunAssertionsWithOpts
    with the operator-derived policy

Hard exclusions:
  - no DirectAdmin / cPanel / Plesk adapter (those land in PR26.3+)
  - no firewall mutation
  - no runtime nft surgery
  - no host destructive testing
  - no restore changes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@itcmsgr itcmsgr merged commit fdbebe8 into main Apr 29, 2026
63 checks passed
@itcmsgr itcmsgr deleted the feat/pr26.2-panel-framework branch April 29, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant