Skip to content

feat(v1.99 PR-16): update trigger → lifecycle/rebuild integration (G3-U1..U4)#473

Merged
itcmsgr merged 4 commits intomainfrom
feat/v1.99-pr16-update-trigger
Apr 19, 2026
Merged

feat(v1.99 PR-16): update trigger → lifecycle/rebuild integration (G3-U1..U4)#473
itcmsgr merged 4 commits intomainfrom
feat/v1.99-pr16-update-trigger

Conversation

@itcmsgr
Copy link
Copy Markdown
Owner

@itcmsgr itcmsgr commented Apr 19, 2026

Summary

First PR in the v1.99 Update Engine Canonization track. Establishes the contract + first wiring layer so that nftban update is treated as a bounded state transition through the lifecycle engine, not a parallel installer.

Draft — depends on v1.98.2 tag (already shipped as of this PR), and a companion-spec review pass before landing.

Architecture constraint (INV-U-001)

Update is a bounded trigger into the rebuild/lifecycle pipeline.
No separate update-only staging/validation/switch logic. Apply work lands in PR-18 and reuses existing rebuild semantics.

The plan rendered by --dry-run prints this reminder so operators see the architectural model, not just the outcome.

Scope of this PR (explicit)

In scope — closes G3-U1..U4

Gate What this PR does
G3-U1 lifecycle entry nftban-installer --mode=upgrade --dry-run routes to runUpdateDryRun; installer binary header records mode=upgrade
G3-U2 version detection update.DetectVersions reads /usr/lib/nftban/VERSION (current) + <sourceDir>/VERSION (target). Package-install target detection deferred to PR-17.
G3-U3 --dry-run correctness runUpdateDryRun renders plan, persists plan JSON to state dir for audit, exits 0/1. No mutation of /etc/nftban/**.
G3-U4 preflight enforcement update.Preflight runs five checks P-1..P-5. Critical failures flip plan.Warnings; warning-severity failures stay informational.

Out of scope (explicit)

  • No shell update path deletion (PR-21)
  • No update apply logic (PR-18)
  • No package-install target detection (PR-17)
  • No uninstall / config-registry / hardening work

What landed

New package internal/installer/update/

  • preflight.go — 5 preconditions P-1 authority, P-2 service, P-3 artifact, P-4 nft dep, P-5 stale-state warning
  • plan.goPlan struct + DetectVersions + BuildPlan + Render + JSON round-trip. Schema version 1.99.0.
  • update_test.go — 14 tests covering happy path + each preflight failure mode + version detection edge cases + JSON schema contract

Installer binary

  • cmd/nftban-installer/update_dryrun.go — new orchestrator; reuses phaseDetect, then runs Preflight + DetectVersions + BuildPlan, renders + persists JSON
  • cmd/nftban-installer/main.go — dispatch: --mode=upgrade + --dry-runrunUpdateDryRun

CI gate (new, blocking)

  • .github/workflows/ci-update-canonization.yml — matrix Ubuntu 24.04 + AlmaLinux 9. Enforces G3-U1/U2/U3/U4. Future sub-gates (G3-U5..U17 + P-1/P-2/P-3 + G3-U-REBUILD-PARITY) added incrementally by PR-17..PR-21 per spec.

Specs

  • V1.90_AUDIT_WIKI_CODE/V199_PR16_UPDATE_TRIGGER_SPEC.md (draft)
  • V1.90_AUDIT_WIKI_CODE/G3_UPDATE_GATE_SPEC.md (v1.99 rev)

Both live in the internal planning tree — not mirrored into this repo.

Test plan

  • Go unit tests for update.Preflight + DetectVersions + BuildPlan
  • ci-update-canonization.yml runs on this PR (G3-U1..U4)
  • Manual lab run: sudo ./bin/nftban-installer --mode=upgrade --dry-run --source --source-dir=\$PWD on Ubuntu 24.04 + AlmaLinux 9
  • Review pass on PR-16 spec before un-drafting

Follow-ups

PR Gate sub-section
PR-17 package-install target detection (G3-U4 deepen)
PR-18 update apply reuses rebuild (G3-U5..U10)
PR-19 update validation (G3-U11..U13)
PR-20 update logging (G3-U15..U17)
PR-21 remove shell update paths + parity gates

🤖 Generated with Claude Code

…-U1..U4)

First PR in the v1.99 Update Engine Canonization track. Establishes the
contract + first wiring layer so that 'nftban update' is treated as a
bounded state transition through the lifecycle engine, not a parallel
installer.

Architecture constraint (INV-U-001):
  Update is a BOUNDED TRIGGER into the rebuild/lifecycle pipeline.
  No separate update-only staging/validation/switch logic. Apply work
  lands in PR-18 and reuses the existing rebuild semantics.

New package internal/installer/update/:
  - preflight.go — five precondition checks P-1..P-5:
      P-1 authority_nftban (ip nftban table present)
      P-2 service_nftband_active
      P-3 artifact_version_file (/usr/lib/nftban/VERSION)
      P-4 dependency_nft
      P-5 state_no_stale_in_progress (warning-severity)
  - plan.go — Plan struct + DetectVersions + BuildPlan + Render.
    Plan carries SchemaVersion="1.99.0", INV-U-001 reminder in Actions.
    Source-install target detection implemented; package-install target
    detection deferred to PR-17.
  - update_test.go — 14 tests: happy path + each preflight failure mode
    + version detection edge cases + plan JSON schema contract.

Installer binary:
  - cmd/nftban-installer/update_dryrun.go — new runUpdateDryRun orchestrator
    that reuses phaseDetect then runs Preflight + DetectVersions +
    BuildPlan, renders the plan, persists plan JSON to state dir, and
    exits. No mutation. Explicitly does NOT invoke phasePrepare/Switch/
    Configure/Validate — those are install-mode territory in PR-16.
  - cmd/nftban-installer/main.go — dispatch: --mode=upgrade + --dry-run
    routes to runUpdateDryRun. Install-mode dry-run behaviour preserved.

CI gate (new, blocking):
  - .github/workflows/ci-update-canonization.yml — matrix Ubuntu 24.04 +
    AlmaLinux 9. Enforces G3-U1 (installer observes mode=upgrade),
    G3-U2 (both versions detected), G3-U3 (--dry-run renders plan + no
    mutation of /etc/nftban/**), G3-U4 (all 5 preflight checks reported).
    Future sub-gates G3-U5..U17 + P-1/P-2/P-3 + G3-U-REBUILD-PARITY
    are added incrementally by PR-17..PR-21 per spec.

Out of scope for PR-16 (explicit):
  - No shell update path deletion (PR-21)
  - No update apply logic (PR-18)
  - No package-install target detection (PR-17)
  - No uninstall / config / hardening work

Spec: V1.90_AUDIT_WIKI_CODE/V199_PR16_UPDATE_TRIGGER_SPEC.md
Gate: V1.90_AUDIT_WIKI_CODE/G3_UPDATE_GATE_SPEC.md

Depends on: v1.98.2 tag (entry criterion). Do not merge until v1.98.2
tags.

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

github-actions Bot commented Apr 19, 2026

Dependency Review

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

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/checkout 34e114876b0b11c390a56381ad16ebd13914f8d5 🟢 5.7
Details
CheckScoreReason
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Code-Review🟢 10all changesets reviewed
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
Security-Policy🟢 9security policy file detected
Branch-Protection🟢 5branch protection is not maximal on development and all release branches
SAST🟢 8SAST tool detected but not run on all commits
actions/actions/setup-go d35c59abb061a4a6fb18e82ac0862c26744d6ab5 🟢 5.7
Details
CheckScoreReason
Maintained🟢 67 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 6
Code-Review🟢 10all changesets reviewed
Binary-Artifacts🟢 10no binaries found in the repo
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 10SAST tool is run on all commits

Scanned Files

  • .github/workflows/ci-update-canonization.yml

itcmsgr and others added 3 commits April 19, 2026 19:02
phaseDetect requires one of ss / sshd_config / state file / conf.local
to yield an SSH port. CI containers run without sshd, so we stub a
minimal sshd_config with Port 22. On a real upgrade host at least one
of the four SSH sources is always available (previous install left
state); this is purely a CI environmental fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…detection

Ubuntu runner's default /etc/ssh/sshd_config has Port commented out, so
the existing-file guard in the previous commit was a no-op. Switch to
seeding ssh_port_active.state under the state dir (source 3 in the 4-source
detection chain), which is exactly what a real post-install upgrade host
would have.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
phaseDetect's authority classification aborted with FAILED_AUTHORITY_ABORT
because the Ubuntu runner has UFW enabled by default and iptables-nft
ghost filter/nat/mangle tables from cloud-init / netplan.

For an update test we need to simulate a host where nftban already owns
authority (which the original install achieved). CI prep now:
  - systemctl disable --now ufw
  - nft flush ruleset (removes ghost iptables-nft tables)
  - nft add table ip nftban (authority preflight P-1)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@itcmsgr itcmsgr marked this pull request as ready for review April 19, 2026 16:19
@itcmsgr itcmsgr merged commit ca48884 into main Apr 19, 2026
54 checks passed
@itcmsgr itcmsgr deleted the feat/v1.99-pr16-update-trigger branch April 19, 2026 16:20
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