You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
proof(SafeString): annotate 7 bodyless decls as OWED (Refs standards#158) (#54)
## Summary
Converts the 7 bodyless declarations in
`src/Proven/SafeString/Proofs.idr`
from terse `Axiom:` doc-comments to the estate's OWED-with-justification
convention established 2026-05-20 across SafeChecksum / Buffer /
CryptoAccel / HKDF / Bloom / FPGA / SafeHtml / SafeCSV / SafeCORS /
SafeAPIKey / SafeSemVer / SafeMath / SafeFile / SafeHeader / SafeHTTP /
SafeArgs / SafeYAML / SafeOTP / SafeSQL / SafeNetwork:
- Triple-pipe `|||` doc stating the claim + operational witness
- `0 ` (erased multiplicity) so the postulate is not runtime-callable
- Bare signature, no `postulate` keyword
- Explicit Idris2 0.8.0 blocker + discharge condition
Refs hyperpolymath/standards#158.
## The 7 OWED items
Every blocker in this module is in the **opaque-String-FFI family** (as
predicted in the assignment brief) — `pack`, `unpack`, `length`, `++`,
`singleton`, `==` over `String` are all FFI-bound primitives that do not
type-level reduce in Idris2 0.8.0.
### `concatLength`
**Claim:** `length (s1 ++ s2) = length s1 + length s2`.
**Blocker:** `String` `++` and `length` are FFI-bound primitives; no
`pack`/`unpack` structural induction is available on opaque `String`.
**Discharge:** `Data.String` reflective tactic for `length`/`++`, or
exposing the packed-character list as a definitional equality.
### `trimNoWhitespace`
**Claim:** if `all (not . isSpace) (unpack s) = True` then `trim s = s`.
**Blocker:** `pack . unpack` round trip is FFI identity, not Refl.
**Discharge:** reflective tactic for `pack . unpack`.
### `escapeHTMLSafe`
**Claim:** `escapeHTML (singleton c) = singleton c` when `c` is not in
`{&, <, >, ", '}`.
**Blocker:** `pack (go (unpack (singleton c)))` chain does not normalise
— `singleton`/`unpack`/`pack` all FFI-bound.
**Discharge:** reflective tactic for `pack . singletonList = singleton`.
### `escapeSQLSafeProperty`
**Claim:** `all (\c => c /= '\'') (unpack (escapeSQL s)) = True`.
**Captured guarantee:** weaker "no unescaped quote in isolation" (the
stronger paired-quote invariant noted as follow-up).
**Blocker:** `unpack . pack . map f` over abstract `String`.
**Discharge:** reflective tactic or induction principle on unpacked
list.
### `escapeHTMLSafeProperty`
**Claim:** `all (\c => c /= '<' && c /= '>') (unpack (escapeHTML s)) =
True`.
**Blocker:** same as `escapeSQLSafeProperty` (the `<` |-> "<" /
`>` |-> ">" rewrite produces no raw `<`/`>` but the FFI round trip
blocks Refl).
**Discharge:** same as above.
### `splitJoinIdentity`
**Claim:** `join (singleton delim) (split delim s) = s` when `delim`
does not occur in `s`.
**Blocker:** `splitHelper` returns `[pack (unpack s)]` — `pack . unpack
= s` is FFI identity, not Refl.
**Discharge:** reflective tactic for `pack . unpack`.
### `linesUnlinesApprox`
**Claim:** `unlines (lines s) = s ++ ""` (the `++ ""` slack absorbs
trailing-newline-handling between `splitHelper` and `join "\n"`).
**Blocker:** same FFI family as `splitJoinIdentity` plus `s ++ ""`.
**Discharge:** reflective tactic for `pack . unpack` (and `s ++ ""`).
## Required side change (same file)
The two runtime-callable wrappers `escapeSQLSafe : (s : String) ->
NoUnescapedQuotes (escapeSQL s)` and `escapeHTMLSafe' : (s : String) ->
NoRawBrackets (escapeHTML s)` call the now-erased postulates and pass
them into constructor `prf` fields. To keep the wrappers compiling, the
`prf` fields of `NoUnescapedQuotes` and `NoRawBrackets` are also marked
`0 `-erased (they are proof terms, never inspected at runtime).
This is a strictly-tightening change — every existing call site already
supplied the proof in proof-relevant context. The data-type declarations
gain a `|||` block noting the erasure as a consequence of the OWED
convention.
## 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)
## Test plan
- [x] Local `idris2 0.8.0 --check` on `src/Proven/SafeString/Proofs.idr`
via `idris2 -p base -p contrib --source-dir src --check
src/Proven/SafeString/Proofs.idr` — green (5/5 modules built;
pre-existing `isSpace` shadowing warning unchanged, present in
original file too)
- [ ] Idris2 0.8.0 `--check` on full `proven.ipkg` once estate
base-package dependency resolution is unjammed (CI currently jammed —
DRAFT until then, per SafeHtml#41 precedent)
- [ ] Owner review of OWED reasons against SafeChecksum precedent
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments