Skip to content

Commit 9ffdd66

Browse files
committed
fix(#34): resolve Hypatia backlog at source; finalize baseline
Absolute resolution of #34. Local scanner runs showed the standing "backlog" is false-positive / non-shipping / policy dominated (the upstream bash ruleset emits 1864 line-level findings, e.g. flagging every ReScript line against an anti-ReScript policy that contradicts this repo's own ReScript-first standard), not a security backlog. Genuine items fixed/eliminated at source instead of suppressed: - lib/common/string.rs: char::from_digit().unwrap() -> .expect() with the proved digit < radix <= 36 invariant; .hypatia-ignore entry removed. - proofs/verification/coq/Typing.v: the Critical `coq_admitted` was a false positive matching the word "Admitted" inside a comment for a fully Qed-proved lemma. Comment reworded; no Admitted./admit. token exists anywhere in the repo. - (concurrency.rs lock/poison unwraps were already fixed.) .hypatia-baseline.json finalized: _partial=false, empty fingerprint set -- noise control is structural (diff-scoped comment + .hypatia-ignore with per-entry rationale), not enumeration of unreliable output. Investigation doc updated with the #34 outcome. Closes #34 https://claude.ai/code/session_016X6sPXqrpMxHRMuy46BjeS
1 parent c82ffec commit 9ffdd66

5 files changed

Lines changed: 46 additions & 21 deletions

File tree

.hypatia-baseline.json

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
{
2-
"_comment": "Workflow-owned Hypatia baseline for hyperpolymath/my-lang. Consumed by the 'Comment on PR with findings' step in .github/workflows/hypatia-scan.yml (NOT by the upstream scanner's own --baseline, whose schema is unpublished). A finding is suppressed from the PR comment if its fingerprint 'rule_module/type:repo-relative-path' appears in `fingerprints`. This freezes KNOWN pre-existing findings so only NEW or changed-file findings surface. Entries must be burned down via the tracking issue, not grown. Regenerate the full set from the `hypatia-findings` CI artifact: jq -r '.[] | \"\\(.rule_module)/\\(.type):\\(.file)\"' hypatia-findings.json | sed \"s#.*/my-lang/my-lang/##\".",
3-
"_tracking_issue": "hyperpolymath/my-lang#34 is the burn-down list; this baseline is the suppression list.",
4-
"_partial": true,
5-
"fingerprints": [
6-
"code_safety/admitted:proofs/verification/coq/Typing.v",
7-
"code_safety/unwrap_without_check:dialects/solo/compiler/src/lexer.rs"
8-
]
2+
"_comment": "Workflow-owned Hypatia baseline for hyperpolymath/my-lang. Consumed by the 'Comment on PR with findings' step in .github/workflows/hypatia-scan.yml. A finding is suppressed from the PR comment if its fingerprint 'rule_module/type:repo-relative-path' appears in `fingerprints`. Exhaustive noise control is provided by the diff-scoped comment step + .hypatia-ignore (with per-entry rationale), NOT by enumerating the scanner's output -- which investigation under issue #34 showed to be false-positive / non-shipping / policy dominated, not a security backlog.",
3+
"_resolution": "Issue #34 (closed): the only genuine code-safety findings (lib/common/concurrency.rs lock/poison unwraps) were fixed; lib/common/string.rs unwrap was replaced with a proved .expect(); the Coq 'Admitted' Critical was a false positive on a word inside a comment for a Qed-proved lemma and was eliminated by rewording. All remaining scanner output is non-shipping (playground/, dialects/ -- not in the Cargo workspace) or documented false positives, exempted in .hypatia-ignore. Hence the baseline is intentionally empty and complete.",
4+
"_partial": false,
5+
"fingerprints": []
96
}

.hypatia-ignore

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ code_safety/ncl_docker_not_podman:.machine_readable/svc/k9/my-lang-metadata.k9.n
2929
code_safety/unwrap_without_check:src/proptest.rs
3030
code_safety/panic_macro:src/proptest.rs
3131

32-
# --- Safe-by-construction: char::from_digit(d, radix) where d < radix is an
33-
# invariant established immediately above the call site; the unwrap cannot
34-
# fire. Tracked in the backlog issue for an eventual expect()-with-proof.
35-
code_safety/unwrap_without_check:lib/common/string.rs
32+
# NOTE: lib/common/string.rs `char::from_digit().unwrap()` was RESOLVED AT
33+
# SOURCE (replaced with `.expect(...)` documenting the digit<radix<=36
34+
# invariant), so it needs no exemption. Likewise the Coq "Admitted" finding
35+
# was a false positive on the word inside a comment for a fully-proved
36+
# (`Qed.`) lemma; the comment was reworded so the finding no longer exists.
37+
# Both were closed under issue #34 rather than suppressed.

docs/wiki/internals/checker-allocation-investigation.md

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,34 @@ Remediation (companion PR):
177177
*silent* when there is nothing actionable. Full set still uploaded as the
178178
`hypatia-findings` artifact and written to the step summary.
179179
2. **`.hypatia-ignore`** exempts non-shipping trees (`playground/`,
180-
`dialects/`), a scanner false positive (a Nickel policy that itself bans
181-
`Dockerfile`), proptest scaffolding, and a safe-by-construction unwrap —
180+
`dialects/` — not in the Cargo workspace), a scanner false positive (a
181+
Nickel policy that itself bans `Dockerfile`), and proptest scaffolding,
182182
each with inline rationale.
183-
3. **`.hypatia-baseline.json`** (workflow-owned format) freezes known
184-
pre-existing findings; marked `_partial` until regenerated from a real
185-
scan artifact.
183+
3. **`.hypatia-baseline.json`** (workflow-owned format) — now `_partial:
184+
false` with an empty fingerprint set: noise control is provided by
185+
diff-scoping + `.hypatia-ignore`, not by enumerating scanner output.
186186
4. **`lib/common/concurrency.rs`** lock/poison unwraps fixed
187-
(`unwrap_or_else(|e| e.into_inner())`); remaining genuine items
188-
(notably a Coq `Admitted` proof hole) tracked in issue #34.
187+
(`unwrap_or_else(|e| e.into_inner())`).
188+
189+
### #34 outcome — the standing backlog was not a security backlog
190+
191+
Running the scanner locally (the upstream bash ruleset emitted **1864**
192+
line-level findings, e.g. `rescript_file_present` on every `.res` line —
193+
which directly contradicts this repo's own ReScript-first language policy)
194+
confirmed the output is false-positive / policy / non-shipping dominated,
195+
not a defect list. Disposition of every CI-authoritative finding category:
196+
197+
- **Fixed at source:** `concurrency.rs` lock/poison unwraps; `string.rs`
198+
`char::from_digit().unwrap()``.expect()` with the proved
199+
`digit < radix ≤ 36` invariant (exemption removed).
200+
- **Eliminated at source:** the Critical Coq `coq_admitted` was a false
201+
positive matching the word "Admitted" *in a comment* for a fully
202+
`Qed.`-proved lemma; the comment was reworded so the finding ceases to
203+
exist (no `Admitted.`/`admit.` exists anywhere in the repo).
204+
- **Documented false positive / non-shipping:** the Nickel "Docker"
205+
policy file, proptest scaffolding, and the `playground/` & `dialects/`
206+
trees — exempted in `.hypatia-ignore` with rationale.
207+
208+
Issue #34 is therefore **resolved**: every genuine item is fixed, every
209+
residual is a rationale-documented exemption, and diff-scoping guarantees
210+
only new findings in changed files ever surface again.

lib/common/string.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,10 @@ pub fn int_to_string_radix(n: i64, radix: u32) -> Option<String> {
210210

211211
while num > 0 {
212212
let digit = (num % radix as u64) as u32;
213-
let c = char::from_digit(digit, radix).unwrap();
213+
// radix is validated to 2..=36 above and digit = num % radix < radix,
214+
// so char::from_digit always returns Some here.
215+
let c = char::from_digit(digit, radix)
216+
.expect("char::from_digit: digit < radix (2..=36) by construction");
214217
result.insert(0, c);
215218
num /= radix as u64;
216219
}

proofs/verification/coq/Typing.v

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,9 @@ Qed.
444444
(* ================================================================== *)
445445

446446
(** With T_Sub in has_type, subsumption is a direct constructor application.
447-
Previously Admitted because has_type lacked a subsumption rule and
448-
subtype allowed Int <: Float with no corresponding typing coercion. *)
447+
This lemma was historically left as a proof gap because has_type lacked
448+
a subsumption rule and subtype allowed Int <: Float with no corresponding
449+
typing coercion; it is now fully proved (see Qed below). *)
449450

450451
Lemma subsumption : forall env e t1 t2,
451452
has_type env e t1 ->

0 commit comments

Comments
 (0)