fix(idris): rebuild logSafeBounded proof for Idris2 0.8.0 (SafeAPIKey baseline rot) - #116
Merged
Merged
Conversation
The pre-existing `logSafeBounded` proof in SafeAPIKey.idr did not
type-check on the bundled Idris2 0.8.0. Audit-by-build (not by reading
PROOF-NEEDS.md) was the only way to spot this. Three concrete defects,
each fixed independently here:
1. **Removed local `plusLteMonotone` helper** which wrapped
`lteTransitive (plusLteMonotoneRight _ lmn) (plusLteMonotoneLeft _
lpq)`. Idris2 0.8.0's `Data.Nat.plusLteMonotone` is exactly the
shape we want (`LTE m n -> LTE p q -> LTE (m + p) (n + q)`), so the
local wrapper is redundant. The wrapper called `lteTransitive` (no
longer in stdlib — it's now `Control.Relation.transitive` and
ambiguous in this import context) and passed wildcard arguments
that didn't match the current `plusLteMonotoneRight` /
`plusLteMonotoneLeft` signatures (`(p,q,r : Nat) -> LTE q r ->
LTE (q+p) (r+p)`). Using stdlib directly sidesteps all of it.
2. **Lifted both branches out of the `with`-block.** Inside the
with-block, the elaborator does not reduce `length "***"` (or
`length "..."`) at type level — the goal is exposed as
`LTE (integerToNat (prim__cast_IntInteger (prim__strLength
(if ...)))) 11` with the `if`-arm unreduced. Outside the
with-block the same lemmas type-check via `Refl`-equivalent
computation. The fix: extract `logSafeBoundedShort` and
`logSafeBoundedLong` as private helpers and let the with-block
just dispatch.
3. **Right-associated the long-path proof.** `(++)` is right-
associative in Idris (`a ++ b ++ c = a ++ (b ++ c)`), but the
original proof bound `(p1 ++ "...") ++ p3` (left-associative)
while the with-block's `False`-branch rewrites the goal to
`substr 0 4 s ++ ("..." ++ substr (...) 4 s)`. The new proof
composes `step23 (length "..." + length (substr ...) ≤ 3 + 4)`
then `step123 (length (substr 0 4 s) + length (...) ≤ 4 + 7)`,
producing exactly the right-associated form.
Also fixed two bound-name typos in `toLogSafeShortEq` and
`toLogSafeLongEq` where the outer pattern discarded the `prf` argument
that the `False`/`True` branch then referenced (`absurd prf` against
an undefined `prf`).
Build verification (per-module `--check`, full ipkg --build hangs on
this machine — see PR #108 notes):
Boj.SafetyLemmas green
Boj.SafeAPIKey green (this PR)
Boj.Safety green
Boj.APIContractCoverage green
Boj.CartridgeDispatch green
Boj.Catalogue green
Boj.CredentialIsolation green
Boj.Federation green
Boj.SafeCORS green
Boj.SafeHTTP green
Boj.SafePromptInjection green
Boj.SafeWebSocket green
Stacked on PR #108 (`feat/item11-proof-debt-honest-framing`) because
this proof depends on SafetyLemmas's comma-fix; when #108 merges, this
auto-rebases to main.
No new axioms introduced. The 5-class-(J) framing from PR #108 is
preserved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🔍 Hypatia Security ScanFindings: 31 issues detected
View findings[
{
"reason": "Stale AI session file -- delete",
"type": "stale",
"file": "GEMINI.md",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "medium"
},
{
"reason": "Issue in quality.yml",
"type": "missing_workflow",
"file": "quality.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in security-policy.yml",
"type": "missing_workflow",
"file": "security-policy.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Python file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/.github/scripts/validate-eclexiaiser.py",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/sanctify-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/academic-workflow-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/fireflag-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/ephapax-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/bofig-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
marked this pull request as ready for review
May 20, 2026 08:46
🔍 Hypatia Security ScanFindings: 31 issues detected
View findings[
{
"reason": "Stale AI session file -- delete",
"type": "stale",
"file": "GEMINI.md",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "medium"
},
{
"reason": "Issue in quality.yml",
"type": "missing_workflow",
"file": "quality.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in security-policy.yml",
"type": "missing_workflow",
"file": "security-policy.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Python file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/.github/scripts/validate-eclexiaiser.py",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/sanctify-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/academic-workflow-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/fireflag-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/ephapax-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/bofig-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
added a commit
that referenced
this pull request
May 20, 2026
Both merged after PR #126 was opened. CHANGELOG.md `[Unreleased]` Fixed: - Added bullet for SafeAPIKey `logSafeBounded` rebuild (#116, MERGED 2026-05-20T08:46Z). - Added bullet for `tests/aspect_tests.sh` grep-count bash bug (#118, MERGED 2026-05-20T09:02Z). .machine_readable/6a2/STATE.a2ml session-history: - Updated the 2026-05-20 entry to mark #116 and #118 MERGED inline, rather than the stale OPEN/OPEN-DRAFT status they carried when the entry was written. #123 (e2e.yml Zig + Deno pin refresh) remains OPEN — listed in session-history with its current status. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
May 20, 2026
…eep (#126) ## Summary Human + machine documentation close-out for the 2026-05-20 epic #87 Tier C session and follow-on baseline-rot sweep. No code, no behavioural change. ## Files - **`CHANGELOG.md`** `[Unreleased]`: - *Added* — ADR-0014 RFC (#109); README "Formal verification" section (#108). - *Fixed* — SafeAPIKey `logSafeBounded` proof rebuild for Idris2 0.8.0 (#116); `tests/aspect_tests.sh` grep-count bash bug (#118); honest framing of the ABI axiom count + `(s t : T)` → `(s, t : T)` parser-comma fix to `SafetyLemmas.idr` (#108). - **`.machine_readable/6a2/STATE.a2ml`**: - `last-updated` bumped `2026-04-25` → `2026-05-20`. - `believe-me-count` corrected `4` → `5`, with citation back to `PROOF-NEEDS.md` 2026-05-18 audit + #108. - `[session-history]` entry appended summarising items 11 + 12 + the SafeAPIKey baseline-rot follow-up + the CI baseline-rot sweep + operational notes (parallel-session branch drift, workflow OAuth scope dance). ## Companion PRs from this thread | PR | Status | What | |---|---|---| | #108 | MERGED 2026-05-20T08:13Z | item 11 honest framing (docstring + README + parser-comma) | | #109 | MERGED 2026-05-20T08:12Z | item 12 ADR-0014 RFC (cross-cartridge composition safety) | | #116 | MERGED 2026-05-20T08:46Z | SafeAPIKey `logSafeBounded` rebuild for Idris2 0.8.0 | | #118 | MERGED 2026-05-20T09:02Z | `tests/aspect_tests.sh` grep-count bash bug | | #123 | OPEN | `.github/workflows/e2e.yml` Zig + Deno pin refresh | | **#126 (this)** | OPEN | session-close docs | ## Out of scope (intentionally) - `governance / Language / package anti-pattern policy` baseline rot stays untouched per the parallel-session-branch-drift guardrail (parent campaign standards#66 owns it). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
Jun 24, 2026
…orker (#251) Proof-completion work across two layers. Both pieces share this branch because the session is pinned to it; they are logically independent and reviewable as separate commits. --- ## 1 — ABI: discharge `charEqSym` axiom → constructive theorem (`666c3e0`) `charEqSym : (x, y : Char) -> (x == y) = (y == x)` was a class-(J) `believe_me` axiom classified "genuinely unavoidable." It isn't — it is **derivable from `charEqSound`** (which the repo already has): - `x == y = True` → `charEqSound` gives `x = y`, collapsing both sides → both `True`; - a mixed `True`/`False` split is impossible (soundness forces the contradiction); - both `False` → trivially equal. No new axiom is introduced. This is the first `(a) DISCHARGED` entry under the trusted-base reduction policy (standards#203), dropping the sanctioned count **5 → 4**. Survivors (`charEqSound`, `unpackLength`, `appendLengthSum`, `substrLengthBound`) remain genuinely irreducible over opaque `Char`/`String` primitives. **Verified:** `cd src/abi && idris2 --typecheck boj.ipkg` → 17/17 modules clean (Idris2 0.8.0, Chez 9.5.8); `bash scripts/check-trusted-base.sh` → OK, 4 axioms. (Same run confirms `Boj.CartridgeDispatch`/BJ1 still type-checks.) Count reconciled across `check-trusted-base.sh` (`EXPECTED_AXIOMS` 5→4), `PROOF-NEEDS.md`, `docs/proof-debt.md` (charEqSym → §(a)), `STATE.a2ml`, and `docs/backend-assurance/prim__eqChar.md`. Also fixed pre-existing drift in `src/abi/README.adoc`: it wrongly listed `logSafeBounded` as a believe_me (constructive since #116), said "graded D" (READINESS says **C**), and called CartridgeDispatch "WIP / not in `boj.ipkg`" (it's in-package and type-checks). ## 2 — Elixir: TLA+ model of `BojRest.JsWorker` (`836c977`) `specs/elixir-harness/` — a TLA+ model of `elixir/lib/boj_rest/js_worker.ex` (GenServer pipelining concurrent requests to one persistent Deno Port, per-request 30 s timeout, crash-replies-all + `:one_for_one` restart). Closes the "Elixir harness has no formal coverage" gap on the proof axis (the Idris2 proofs stop at the Zig FFI boundary). **Verified with TLC** (`Requests = {r1,r2,r3}`, 341 states, no error): - **ReplyOnce** — no caller replied twice under any response/timeout/crash interleaving (the `Map.pop` guard). Headline. - **Consistent**, **NoPendingWhileDown** — crash clears `pending` atomically. - **EventuallyReplied** (liveness) — the 30 s timer guarantees termination even if Deno hangs. - Non-vacuity: `ReachOk/ReachTimeout/ReachCrashed` sanity controls all *refuted* (all terminal outcomes reachable). Deferred (noted in the README): the `JsWorkerPool` routing/supervision layer, and the `Invoker` pool once it exists (it's fork-per-request today — ADR-0005/0006). --- ## Scope Items 1 + 2 (Idris ABI) and item 4 (Elixir model). Zig FFI/invariants (item 3) is out of scope (separate workstream). Also carries `ef959f0` (prior `allTake` dedup, not yet on `main`). Neither piece moves the CRG grade — both are on the formal-proof axis, not the empirical/dogfooding axis. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01XrPAh7eBSUcVKauTVdXH9Y --- _Generated by [Claude Code](https://claude.ai/code/session_01XrPAh7eBSUcVKauTVdXH9Y)_ --------- Co-authored-by: Claude <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
Restores
Boj.SafeAPIKeyto a green Idris2 0.8.0 build. The pre-existinglogSafeBoundedproof onmaindoes not type-check; this PR rebuilds it against the current stdlib + elaborator behaviour. No new axioms. The 5-class-(J) framing established in #108 is preserved.Discovered while verifying #108 (item 11). Was originally stacked on #108; rebased onto
mainafter #108 merged at 2026-05-20T08:13Z.Three independent defects, each fixed
Removed the redundant local
plusLteMonotonehelper. It wrappedlteTransitive (plusLteMonotoneRight _ lmn) (plusLteMonotoneLeft _ lpq):lteTransitiveis no longer in stdlib — Idris2 0.8.0 usesControl.Relation.transitive, but that's ambiguous in this import context.plusLteMonotoneRight/plusLteMonotoneLefthave signature(p, q, r : Nat) -> LTE q r -> LTE (q+p) (r+p)in this stdlib — the wrapper passed wildcards expecting a different shape.The stdlib already ships
Data.Nat.plusLteMonotone : LTE m n -> LTE p q -> LTE (m + p) (n + q)— exactly what the wrapper was trying to be. Use it directly.Lifted both branches out of the
with-block. InsidelogSafeBounded s with (length s <= 8) proof cond, Idris2 0.8.0 does not reducelength "***"(orlength "...") at type level — the goal is exposed asLTE (integerToNat (prim__cast_IntInteger (prim__strLength (if True then ... else ...)))) 11with theif-arm unreduced. Outside the with-block, the same lemmas type-check via Refl-equivalent computation. ExtractedlogSafeBoundedShort/logSafeBoundedLongas private helpers; the with-block now just dispatches.Right-associated the long-path proof.
(++)is right-associative in Idris (a ++ b ++ c = a ++ (b ++ c)), but the original composed(p1 ++ "...") ++ p3(left-associative) — its conclusion didn't match the with-block's False-branch goal. New proof:step23 (length "..." + length (substr ...) ≤ 3 + 4)thenstep123 (length (substr 0 4 s) + length (...) ≤ 4 + 7).Plus two bound-name typos in
toLogSafeShortEq/toLogSafeLongEqwhere the outer_discarded theprfargument that the inner branch then referenced.Test plan
Per-module
idris2 --checkon every safety module — all 12 green:idris2 --build src/abi/boj.ipkgdoes not complete in 9 min on my dev box (gets SIGTERMed) — same note as #108. Per-module--checkis the verification surface.Why this matters
PROOF-NEEDS.md's 2026-05-18 audit claimsSafeAPIKeycarries constructive proofs that close BJ2-partial. Pre-this-PR the proof did not compile. The audit was, like the SafetyLemmas axiom count noted in #108, evidently a desk-read of the source rather than a build. With this PR merged, the audited safety surface is buildable from scratch.Refs epic #87 Tier C (companion to #108 / #109).
🤖 Generated with Claude Code