Commit 433f53c
feat(v1.100 Amendment 2): code-A — G1/AuthorityNFTBan split + §54 evidence predicate + --accept-orphan-nftban (#519)
Decision-layer implementation of Amendment 2 (contract.md §§52–61).
Splits the existing G1/AuthorityNFTBan row into two evaluated-within-
Group-1 sub-rules:
- G1/AuthorityNFTBan/default — REFUSE, unchanged behavior for all flag
patterns outside the candidate triple.
- G1/AuthorityNFTBan/orphan-intent-candidate — delegates to the §54
evidence predicate; G1/AuthorityNFTBan/OrphanProceed on all-true,
G1/EvidenceMismatch on any-false.
Split is ENTIRELY within Group 1; no later group ever defeats a Group 1
outcome and §5 precedence is preserved.
Implementation surface
======================
- Add CLI flag --accept-orphan-nftban (cmd/nftban-installer/flags.go).
Restore-mode only. CLI argv only — no env-var fallback per §55. Help
text contains zero "force"/"override" tokens.
- Extend restore.Flags + restore.DecisionInput with:
- AcceptOrphanNFTBan bool
- Panel detect.PanelType
- OrphanEvidence *OrphanEvidence
- New OrphanEvidence struct with 13 boolean rows + AllTrue() + FailedRowID().
- New decideAuthorityNFTBan in restore/engine.go: candidate-triple gate
→ §54 evidence predicate → PROCEED PanelNative/csf or REFUSE.
- New cmd/nftban-installer/restore_decide_evidence.go: read-only §54
reader. Uses existing typed surfaces (FileExists, ServiceActive,
NftTableExists). E.6 csf.service state uses raw Run("systemctl",
"status"|"is-enabled","csf.service") per §43.3 (read-only probes
authorized). NO mutating systemctl verbs. Zero new typed mutation
surfaces.
- Dispatcher (restore_decide.go) gathers evidence ONLY when candidate
triple is otherwise present, avoiding unnecessary live reads on every
restore-mode invocation.
Tests
=====
- engine_amendment2_test.go: §56.1 unit fixtures (rows 01–20 + 7d
acceptable-fallback variant), §56.2 regression (R1–R6), §56.4
mutation-surface AST scan, FailedRowID per-row coverage.
- restore_decide_evidence_test.go: gatherOrphanEvidence per-row
coverage (15 cases including E.6 sub-variants: active forbidden,
not-found forbidden, enabled forbidden, static forbidden,
disabled-acceptable). NFTBAN_ACCEPT_ORPHAN env-var-fallback
source-scan invariant.
- engine_test.go: existing G1/AuthorityNFTBan fixture re-pinned to
G1/AuthorityNFTBan/default; declaredRules now lists three sub-rule
consts; two new allFixtures entries pin OrphanProceed and
EvidenceMismatch.
CI gates (§56.3) implemented as in-process tests, NOT as GitHub
Actions edits — per operator direction. Source-scan tests in
engine_amendment2_test.go (force/override scan) and
restore_decide_evidence_test.go (env-var fallback scan).
Invariants preserved
====================
- §5 precedence: split is entirely within Group 1.
- INV-PR25-AUTHORITY-IMMUTABILITY: §54 evidence read once at decision
time, never re-read.
- §19.2 layer 4 / main.go:132 history gate: untouched.
- §20.1 panel mapping: PROCEED resolves PanelNative/csf via the
existing static map.
- §22 four terminals + §19.4 exit codes: unchanged.
- §32 11-step ordering: unchanged.
- §43.3 read-only Run policy: §54 E.6 uses status/is-enabled only.
- §51.3 Option B: zero iptables introspection added.
- INV-PR26-NEW-MUTATION-SURFACES-BOUNDED: zero new mutation surfaces.
- INV-AMD2-EXPLICIT-INTENT-IS-NARROW: §53.4 13 explicit-REFUSE rows
test-pinned in §56.1.
Test results
============
- go test ./internal/installer/restore/... PASS
- go test ./cmd/nftban-installer/... PASS
- go test ./... 64 packages PASS, 0 FAIL
Grep gates (scoped to Amendment 2 changed files)
================================================
- iptables-(save|restore|nft) 0 hits → PASS
- build[ -]set[ ]+csf 0 hits → PASS
- WriteFileAtomic.*update-history|... 0 hits → PASS
- force|override in --accept-orphan-nftban 0 hits → PASS
Out of scope (deferred)
=======================
- §59 Q3/Q4 — typed read-only ServiceListed/ServiceEnabled/NftListTables
not added; raw Run for E.6 + existing NftTableExists used instead.
- §59 Q5 — final --help text wording locked here; further refinement
optional.
- amendment-2-code-E real-host srv3 destructive evidence — separate PR.
No srv3 action. No CI workflow edit. No §32 mutation path change. No
new state terminals. No new exit codes. No update-history writes.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 7080096 commit 433f53c
9 files changed
Lines changed: 1418 additions & 12 deletions
File tree
- cmd/nftban-installer
- internal/installer/restore
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
61 | 71 | | |
62 | 72 | | |
63 | 73 | | |
| |||
97 | 107 | | |
98 | 108 | | |
99 | 109 | | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
100 | 114 | | |
101 | 115 | | |
102 | 116 | | |
| |||
161 | 175 | | |
162 | 176 | | |
163 | 177 | | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
164 | 183 | | |
165 | 184 | | |
166 | 185 | | |
| |||
270 | 289 | | |
271 | 290 | | |
272 | 291 | | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
273 | 300 | | |
274 | 301 | | |
275 | 302 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
128 | 128 | | |
129 | 129 | | |
130 | 130 | | |
131 | | - | |
132 | | - | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
133 | 134 | | |
134 | 135 | | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
135 | 153 | | |
136 | 154 | | |
137 | 155 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
Lines changed: 26 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
0 commit comments