Commit 5bd2b36
proof(SafeTOML): annotate 5 bodyless decls as OWED (Refs standards#158) (#52)
## Summary
Converts the 5 bodyless `export` declarations in
`src/Proven/SafeTOML/Proofs.idr` to the estate's OWED-with-justification
convention established 2026-05-20 across SafeChecksum, SafeBuffer,
SafeCryptoAccel, SafeHKDF, SafeBloom, SafeFPGA, SafeAPIKey, SafeCORS,
SafeCSV, SafeSemVer, and SafeHtml:
- Triple-pipe `|||` doc-comment stating the claim
- Leading `0 ` (erased multiplicity, runtime-stripped)
- Bare type signature, no `postulate` keyword
- Explicit Idris2 0.8.0 blocker + discharge condition
Refs hyperpolymath/standards#158.
## The 5 OWED items
### 1. `isScalarCorrect`
**Claim:** `isScalar val = True -> not (isTable val || isArray val) =
True`.
**Why OWED:** `isScalar`, `isTable`, and `isArray` are pairwise
disjoint on the ten `TOMLValue` constructors (definitions in
`src/Proven/SafeTOML/Types.idr` L376-L393). The proof closes by a
ten-arm case-split on `val`, but Idris2 0.8.0 does not auto-derive
`absurd` from `True = False` on the three non-scalar arms (`TArray`,
`TInlineTable`, `TTable`). Same shape as boj-server's class-J
`Bool`-vs-`Prop` reflection gap (SafetyLemmas `charEqSound`).
**Discharge:** reflective `Bool`-to-`Dec` lemma for derived enum-shaped
predicates, or hand-write the ten-arm split with one `Refl` per
scalar arm and `absurd Refl` for the three non-scalar arms.
### 2. `bareKeyCharsValid`
**Claim:** `isValidBareKey key = True -> all isValidBareKeyChar (unpack
key) = True`.
**Why OWED:** the definition is
`isValidBareKey s = not (null (unpack s)) && all isValidBareKeyChar
(unpack s)`
(`Types.idr` L461-L463). From `(&&) = True` we want the second
projection, but the two `unpack key` occurrences are opaque under
Idris2 0.8.0's String FFI primitives and the elaborator cannot unify
them by Refl. Same blocker family as `SafeHtml.escapePreservesNoLT`
and the SafeChecksum Luhn/ISBN OWED set.
**Discharge:** `Data.String` reflective tactic for `unpack`, or a
generic `andTrueSplit : (x && y = True) -> (x = True, y = True)`
applied under the opaque head.
### 3. `specialCharsNeedQuoting`
**Claim:** `any (not . isValidBareKeyChar) (unpack key) = True ->
needsQuoting key = True`.
**Why OWED:** chain is
`any (not . p) xs = True ==> all p xs = False ==> isValidBareKey key =
False ==> needsQuoting key = True`
(De Morgan on `any/all` + definitions `Types.idr` L461-L468). Held
back by opaque `unpack` plus the absence of a definitional
`any (not . p) xs = not (all p xs)` Refl. Same family as (2).
**Discharge:** as (2), or compose a hand-written
`anyNotAll : any (not . p) xs = True -> all p xs = False`
with `notTrueIsFalse`.
### 4. `dateComponentsValid`
**Claim:** `(d.month >= 1 && d.month <= 12 && d.day >= 1 && d.day <= 31)
= True` for any `d : TOMLDate`.
**Why OWED:** `TOMLDate` is a plain record
(`MkTOMLDate : Integer -> Nat -> Nat -> TOMLDate`, `Types.idr` L64-L68)
with no refinement on `month`/`day`. The claim is a
parser-postcondition only — nothing in the type rules out
`MkTOMLDate 2026 13 31`. Same shape as boj-server's I7
FFI-correctness assumptions (stated at the parser seam, not proved).
**Discharge:** refactor `TOMLDate` to a smart-constructor with
`{auto 0 _ : InRange month 1 12}` etc., and update `Parser.parseDate`
to produce the refined record. Alternatively thread a
`Trusted.Parser` ghost-oracle predicate.
### 5. `timeComponentsValid`
**Claim:** `(t.hour <= 23 && t.minute <= 59 && t.second <= 60) = True`
for any `t : TOMLTime` (`60` is intentional, ISO 8601 leap-second).
**Why OWED:** identical shape to (4) on `TOMLTime`
(`Types.idr` L83-L88) — plain record, parser-postcondition, no
constructor-level refinement.
**Discharge:** as (4) on `TOMLTime` fields.
## Safety posture
- Zero `believe_me`
- Zero `postulate`
- Zero `idris_crash`
- All `0 `-erased — postulates cannot leak into runtime
- Discoverable as named declarations (vs silent / commented-out)
## Local verification
```
IDRIS2_PREFIX=/home/.../idris2/0.8.0 \
idris2 --source-dir src --check src/Proven/SafeTOML/Proofs.idr
1/3: Building Proven.Core (src/Proven/Core.idr)
2/3: Building Proven.SafeTOML.Types (src/Proven/SafeTOML/Types.idr)
3/3: Building Proven.SafeTOML.Proofs (src/Proven/SafeTOML/Proofs.idr)
```
(One pre-existing `isValidBareKeyChar` shadow warning is on the
original signature, unchanged by this PR.)
## Scope
- Touches only `src/Proven/SafeTOML/Proofs.idr`
- 5 declarations annotated; the other Refl-discharged proofs in the
file are untouched
## Test plan
- [ ] CI green on this PR (idris2 0.8.0 `--check`)
- [ ] Owner review of OWED reasons against SafeChecksum / SafeHtml
precedent (PRs #33 / #41)
- [ ] Verify no downstream module shadows the names (grep was clean
at edit time)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 542d462 commit 5bd2b36
1 file changed
Lines changed: 116 additions & 37 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
141 | 158 | | |
142 | 159 | | |
143 | 160 | | |
| |||
150 | 167 | | |
151 | 168 | | |
152 | 169 | | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
160 | 191 | | |
161 | 192 | | |
162 | 193 | | |
163 | 194 | | |
164 | 195 | | |
165 | 196 | | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
173 | 219 | | |
174 | 220 | | |
175 | 221 | | |
| |||
234 | 280 | | |
235 | 281 | | |
236 | 282 | | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
253 | 332 | | |
254 | 333 | | |
255 | 334 | | |
| |||
0 commit comments