Skip to content

feat: accept a finding in the workflow it belongs to, with a stated reason - #75

Merged
bgard68 merged 1 commit into
mainfrom
claude/suppressions-with-reasons
Aug 25, 2026
Merged

feat: accept a finding in the workflow it belongs to, with a stated reason#75
bgard68 merged 1 commit into
mainfrom
claude/suppressions-with-reasons

Conversation

@bgard68

@bgard68 bgard68 commented Aug 25, 2026

Copy link
Copy Markdown
Owner

A finding that is genuinely acceptable had nowhere to go. It reported forever, or the reader learned to ignore it.

This repository proved the point: its own accepted findings lived in a Dictionary inside a test file — invisible to anyone reading the workflow they were about, and useless to anybody else scanning their own repo.

permissions:
  # sentinel:accept GHA002 - deleting a workflow run has no narrower grant
  actions: write

Why in the workflow, not a config file

A separate file of rule/line/reason entries is the obvious design and the wrong one. Line numbers drift the moment anyone edits the workflow, the reason ends up far from what it explains, and the file outlives the code it was written about.

A comment is deleted by the same edit that deletes what it annotates, and a reviewer sees it appear in the diff beside what it waves away.

It also fits the constraints already in place: Sentinel is read-only and anonymous, so there is no account to store a decision against. It has to live in the repo it is already fetching.

Three refusals do the actual work

No reason, no acceptance. A directive with no stated reason is ignored and the finding still reports. A bare marker records that someone wanted the finding gone, not that anyone considered it — the mute button this exists instead of.

Matched on rule and line. Accepting one grant cannot quietly cover a second finding of the same rule elsewhere in the file.

A stale acceptance is itself reported. If someone accepts GHA002 on a line and later fixes the permission, that comment is now a claim sitting in the file that somebody considered a problem which is no longer there. It reads as considered when nothing considered it. Every suppression list accumulates these; reporting the rot is what stops it.

That last rule is this repository's own stated principle, previously enforced only by hand in a test file:

"An exception that no longer corresponds to a real finding is worse than no exception: it reads as considered when nothing considered it."

Nothing disappears

An accepted finding moves into Reviewed and accepted carrying its original severity and the stated reason. The summary shows both counts, so a suppressed Critical is quiet, never invisible.

The client separates the two kinds of acceptance, because they are different claims and only one of them can be wrong about the risk:

  • required by an action — a documented fact, established by the rule
  • accepted by author — a person's judgement, with their reason

The exemption table is now empty

prune-runs.yml states its own acceptance beside the grant, so RepositoryWorkflowsTests.Accepted holds nothing.

That test also stopped calling the rules directly. Doing so bypassed the service where acceptance is applied, which held this repository to a stricter standard than the tool applies to anyone else's. It now measures what the product actually reports — and fails on a stale or unexplained acceptance of its own.

Verification

322 backend tests and 28 frontend tests pass; both stacks build. Eight new tests cover the mechanism, each paired with what it must refuse: no reason, wrong rule, wrong line, still-valid, and outlived.

🤖 Generated with Claude Code

https://claude.ai/code/session_01N7HjzX5e8Wv7PKENDo2Uj7


Generated by Claude Code

…eason

A finding that is genuinely acceptable had nowhere to go. It reported forever,
or the reader learned to ignore it - and this repository proved the point: its
own accepted findings lived in a Dictionary inside a test file, invisible to
anyone reading the workflow they were about.

    permissions:
      # sentinel:accept GHA002 - deleting a workflow run has no narrower grant
      actions: write

In the workflow rather than a separate file of rule/line/reason entries, because
line numbers in such a file drift the moment anyone edits the workflow, the
reason ends up far from what it explains, and the file outlives the code it was
written about. A comment dies with the line it annotates, and a reviewer sees it
appear in the diff beside what it waves away.

Three refusals do the actual work:

  - an acceptance with no reason is ignored and the finding still reports. A
    bare marker records that someone wanted the finding gone, not that anyone
    considered it.
  - an acceptance is matched on rule AND line, so accepting one grant cannot
    quietly cover a second finding elsewhere in the same file.
  - an acceptance that no longer matches a finding is itself reported (GHA012).
    A directive that outlived its finding is a claim, sitting in the file, that
    somebody considered a problem which is no longer there. Every suppression
    list rots; reporting the rot is what stops it.

Nothing disappears. An accepted finding moves into "Reviewed and accepted"
carrying its original severity and the stated reason, and the client separates
a documented requirement from a person's judgement - only the second can be
wrong about the risk.

The Accepted table in RepositoryWorkflowsTests is now empty: prune-runs.yml
states its own acceptance beside the grant. That test also stopped calling the
rules directly, which held this repository to a stricter standard than the tool
applies to anyone else's; it now measures what the product reports, and fails
on a stale or unexplained acceptance of its own.

322 backend tests and 28 frontend tests pass; both stacks build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7HjzX5e8Wv7PKENDo2Uj7
@bgard68
bgard68 merged commit 3e3c3c8 into main Aug 25, 2026
10 checks passed
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.

2 participants