Commit 3b83403
feat(v1.100 PR-P2-1): prior-authority record hardening — 5-state classification + required RecordedAt/InstallerVersion/ActiveAtInstall (#484)
Pre-PR-23 blocker #1. Strengthens prior-authority records so PR-24
restore-enforcement can rely on them without inheriting weak semantics.
**Scope-locked per repair contract:**
- schema additions (recorded_at, installer_version, *bool active_at_install)
- 5-state classification (NoRecord / Malformed / Incomplete /
UsableActive / UsableInactive)
- backward-safe degradation of old weak records to Incomplete
- render/JSON symmetry — PriorActiveAtInstall field + render line
- tests + contract/doc updates only
- NO restore execution, NO lifecycle mutation, NO signature/checksum
framework, NO unrelated refactors
## Schema additions (prior.go)
```go
type PriorRecord struct {
SchemaVersion string
FirewallType string
RecordedAt *time.Time // NEW — required for usable
InstallerVersion string // NEW — required for usable
ActiveAtInstall *bool // CHANGED from bool — tri-state:
// nil = record writer did not commit
// &true = prior was active
// &false = prior was explicitly inactive
}
```
## 5-state classification
| State | Condition |
|---|---|
| NoRecord | no artifact on disk |
| RecordMalformed | JSON does not parse (was folded into Incomplete before) |
| RecordIncomplete | parses but required field missing/invalid |
| RecordUsableActive | all required + ActiveAtInstall=&true |
| RecordUsableInactive | all required + ActiveAtInstall=&false |
`PriorRecordState.IsUsable()` helper returns true for both Usable*
variants — RestoreAuthorized uses it.
`IncompleteReason` enum provides machine-consumable reason codes:
Unreadable, SchemaMismatch, MissingFirewallType, UnknownFirewallType,
MissingRecordedAt, MissingInstallerVersion, MissingActiveAtInstall.
## Backward-safety
Older records from before PR-P2-1 that lack recorded_at /
installer_version / explicit active_at_install are intentionally
reclassified as RecordIncomplete. Migration-style silent upgrade is
forbidden. Test `TestProbe_OldStyleRecord_DegradesToIncomplete`
falsifies this path directly.
> **Migration note:** Older prior-authority records may now classify
> as Incomplete by design. This is intentional safety tightening, not
> a functional regression. Records produced by the install-side writer
> that lands alongside PR-23 will carry all required fields.
## Plan integration (plan.go)
- `Plan.RestoreAuthorized` now uses `PriorState.IsUsable()` — both
Usable variants authorize, active/inactive is separate dimension
- new `Plan.PriorIncompleteReason` surfaces typed reason in JSON
- new `Plan.PriorActiveAtInstall *bool` surfaces the tri-state
(nil = unknown, &true/&false = explicit) — PR-24 uses this to
decide whether restoration needs a second confirmation prompt
- new Render line `Prior firewall at install : active|inactive`
only emitted when record is usable — no defaulted values
- new warning when restore requested on UsableInactive record
## Tests
Added (uninstall_test.go):
- `TestProbe_RecordUsableActive` (rename of TestProbe_RecordUsable)
- `TestProbe_RecordUsableInactive` — active_at_install=false path
- `TestProbe_RecordMalformed_BadJSON` — split from Incomplete
- `TestProbe_RecordIncomplete_MissingRecordedAt`
- `TestProbe_RecordIncomplete_MissingInstallerVersion`
- `TestProbe_RecordIncomplete_MissingActiveAtInstall`
- `TestProbe_OldStyleRecord_DegradesToIncomplete` — backward-safety
- `TestBuildPlan_Restore_UsableInactive_AuthorizedButWarned`
- All existing tests updated: fixtures carry all 5 required fields;
JSON strings updated to `record_usable_active`
Every Incomplete* test also asserts the specific IncompleteReason
(not just the state) so regressions attribute cleanly.
## Doc update (contract.md)
Added "PR-P2-1 hardening" section under the prior-authority record
definition: describes the 5 states, what "usable" now means, explicit
backward-safety rule.
## Non-goals (strict scope lock)
- no restore execution
- no lifecycle mutation
- no signature/checksum framework
- no unrelated refactors
Refs: internal/installer/uninstall/contract.md §"Pre-PR-23 blockers"
Authorization: locked repair contract (pre-PR-23 Phase 2 item #1)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent ff22efa commit 3b83403
4 files changed
Lines changed: 453 additions & 87 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
85 | 85 | | |
86 | 86 | | |
87 | 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 | + | |
88 | 122 | | |
89 | 123 | | |
90 | 124 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
81 | | - | |
82 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
83 | 85 | | |
84 | 86 | | |
85 | | - | |
86 | | - | |
87 | | - | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
88 | 90 | | |
89 | 91 | | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
90 | 113 | | |
91 | 114 | | |
92 | 115 | | |
| |||
123 | 146 | | |
124 | 147 | | |
125 | 148 | | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
134 | 158 | | |
135 | 159 | | |
136 | 160 | | |
| |||
139 | 163 | | |
140 | 164 | | |
141 | 165 | | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
142 | 175 | | |
143 | 176 | | |
144 | 177 | | |
| |||
154 | 187 | | |
155 | 188 | | |
156 | 189 | | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
157 | 194 | | |
158 | 195 | | |
159 | | - | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
160 | 205 | | |
161 | 206 | | |
162 | 207 | | |
| |||
220 | 265 | | |
221 | 266 | | |
222 | 267 | | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
223 | 282 | | |
224 | 283 | | |
225 | 284 | | |
| |||
0 commit comments