Skip to content

backlog: file #1242 -- asvs-apply-cells.py is lossy in four ways and its guard sees one - #362

Merged
wshallwshall merged 1 commit into
mainfrom
claude/file-apply-cells-erasure
Aug 13, 2026
Merged

backlog: file #1242 -- asvs-apply-cells.py is lossy in four ways and its guard sees one#362
wshallwshall merged 1 commit into
mainfrom
claude/file-apply-cells-erasure

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Files one backlog item. Docs-only: docs/BACKLOG.md, +33 lines, no other file.

What it files

docs/security/asvs-apply-cells.py (vault-only tooling) re-renders any ASVS cell it touches.
It cannot append -- it hard-refuses an id not already in the scorecard -- so re-render is its
only mode
, and every rescore and anchor repair goes through it by design.

Of the four kinds of key it can encounter, it preserves one:

kind outcome
live top-level scalar preserved
live top-level table falls to the scalar helper, whose last branch stringifies -- written back as a TOML string
top-level key supplied only by the payload never emitted; the carry-through loop skips on payload membership, not on already-emitted
any key inside a sub-table entry dropped; evidence and absence entries are each rebuilt from three hard-coded fields

The preservation guard compares top-level key sets plus sub-table cardinality. A re-render that
keeps every entry and hollows each one out passes both limbs. The mangled table is still a key,
merely no longer a table. The payload-only drop is invisible by construction, because the guard
diffs against the live cell and that key was never there.

Why P1

The loss removes a check rather than tripping one. The verifier documents the optional anchor
fields as not asserted when absent, so an erased pin silently downgrades an asserted structural
claim to an unasserted one and the run reports green having checked strictly less. Silent in both
directions.

It is also pending, not hypothetical. Until this morning every evidence entry carried exactly three
keys and the sub-table limb could not fire. The D3 backfill merged today and put two structural
pins on 1,710 of 1,998 anchors. The backfill is correct and does not touch the writer -- landing
it is simply what armed a writer that was already lossy.

Verification, including what it corrected

The finding was put through an adversarial pass before landing (four independent lenses, then a
judge). All four refuted the draft, and the item records the corrections rather than quietly
absorbing them:

  • "Latent" was wrong -- it is active. The original measurement was taken one commit before
    the backfill landed. That parent revision genuinely has zero of these keys, so a stale checkout
    reproduces the wrong answer perfectly and reads as independent confirmation.
  • The clean two-way asymmetry was wrong. It concealed the table-mangling and the payload-only
    drop entirely; the real taxonomy is four-way.
  • A fifth limb was investigated and rejected. The tool does rewrite the working tree to LF, but
    core.autocrlf=true normalizes it back in the index, so the blob is unchanged and the claimed
    review-diff consequence does not occur. It is not in the item.

Notes

No deployment axis -- vault-only tooling that ships to nobody (CLAUDE.md section 0).
No ASVS cell ids appear in the item or in the commit body: those publish, the scorecard does not.
Banner validated with parse_items (exactly one OPEN banner); added text carries only the OPEN
banner and the amendment marker.

…its guard sees one

The writer re-renders every cell it touches and cannot append, so re-render is its only mode:
every rescore and every anchor repair goes through it. Of the four kinds of key it can meet, it
preserves one. A live top-level scalar survives. A live top-level TABLE falls through to the
scalar helper, whose last branch stringifies it, so a table is rewritten as a TOML string. A
top-level key supplied only by the payload is never emitted, because the carry-through loop skips
on payload membership rather than on already-emitted. And any key inside a sub-table entry is
dropped, since evidence and absence entries are each rebuilt from three hard-coded fields.

The preservation guard compares top-level key sets and sub-table cardinality. A re-render that
keeps every entry and hollows each one out passes both limbs; the mangled table is still a key,
merely no longer a table; the payload-only drop is invisible by construction because the guard
diffs against the live cell. The original block text is captured at the rewrite loop and then
discarded, there is no hash or schema check, and no test references the script.

Worse than silent: the loss removes a check instead of tripping one. The verifier documents these
optional anchor fields as not-asserted when absent, so an erased pin downgrades an asserted
structural claim to an unasserted one and the run reports green having checked strictly less.

Filed at P1 because it is pending on the next routine operation. Until this morning every evidence
entry carried exactly three keys and the sub-table limb could not fire; the D3 backfill merged
today and put two structural pins on 1,710 of 1,998 anchors. The backfill is correct and does not
touch the writer -- landing it is what armed a writer that was already lossy.

Framing corrected by an adversarial pass before landing, and the item records it. The first draft
said latent and described a clean two-way asymmetry; both were wrong. The measurement had been
taken one commit before the backfill, where the counts genuinely are zero, so a stale checkout
reproduces the wrong answer and reads as confirmation. A fifth limb about line-ending rewriting
was investigated and rejected: autocrlf normalizes it back in the index, so the claimed
review-diff consequence does not occur.

No deployment axis: vault-only tooling that ships to nobody.
@wshallwshall
wshallwshall enabled auto-merge (squash) August 13, 2026 11:08
@wshallwshall
wshallwshall merged commit 97400cc into main Aug 13, 2026
33 of 34 checks passed
@wshallwshall
wshallwshall deleted the claude/file-apply-cells-erasure branch August 13, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant