feat(v1.99 PR-16): update trigger → lifecycle/rebuild integration (G3-U1..U4)#473
Merged
feat(v1.99 PR-16): update trigger → lifecycle/rebuild integration (G3-U1..U4)#473
Conversation
…-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>
Contributor
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Files
|
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First PR in the v1.99 Update Engine Canonization track. Establishes the contract + first wiring layer so that
nftban updateis treated as a bounded state transition through the lifecycle engine, not a parallel installer.Draft — depends on
v1.98.2tag (already shipped as of this PR), and a companion-spec review pass before landing.Architecture constraint (INV-U-001)
The plan rendered by
--dry-runprints this reminder so operators see the architectural model, not just the outcome.Scope of this PR (explicit)
In scope — closes G3-U1..U4
nftban-installer --mode=upgrade --dry-runroutes torunUpdateDryRun; installer binary header recordsmode=upgradeupdate.DetectVersionsreads/usr/lib/nftban/VERSION(current) +<sourceDir>/VERSION(target). Package-install target detection deferred to PR-17.--dry-runcorrectnessrunUpdateDryRunrenders plan, persists plan JSON to state dir for audit, exits 0/1. No mutation of/etc/nftban/**.update.Preflightruns five checks P-1..P-5. Critical failures flip plan.Warnings; warning-severity failures stay informational.Out of scope (explicit)
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 warningplan.go—Planstruct +DetectVersions+BuildPlan+Render+ JSON round-trip. Schema version1.99.0.update_test.go— 14 tests covering happy path + each preflight failure mode + version detection edge cases + JSON schema contractInstaller binary
cmd/nftban-installer/update_dryrun.go— new orchestrator; reusesphaseDetect, then runs Preflight + DetectVersions + BuildPlan, renders + persists JSONcmd/nftban-installer/main.go— dispatch:--mode=upgrade + --dry-run→runUpdateDryRunCI 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
update.Preflight+DetectVersions+BuildPlanci-update-canonization.ymlruns on this PR (G3-U1..U4)sudo ./bin/nftban-installer --mode=upgrade --dry-run --source --source-dir=\$PWDon Ubuntu 24.04 + AlmaLinux 9Follow-ups
🤖 Generated with Claude Code