Skip to content

caller-pins: measure which adopters are running a stale copy of the lane - #19

Merged
bdelanghe merged 1 commit into
mainfrom
claude/osv-rollout-adoption-gap-oistiz
Aug 3, 2026
Merged

caller-pins: measure which adopters are running a stale copy of the lane#19
bdelanghe merged 1 commit into
mainfrom
claude/osv-rollout-adoption-gap-oistiz

Conversation

@bdelanghe

Copy link
Copy Markdown
Contributor

Addresses the measurement half of #10, and answers its open question — item 3 does not generalise.

The problem, measured rather than asserted

uses: …/osv-scan.yml@<sha> resolves the reusable workflow at that commit, including the scanner version and digest pinned inside it. So a caller's pin decides which scanner that repo actually runs. Across 10 callers read live on 2026-08-03:

✗ brand           62990dd  behind      ✗ prx         62990dd  behind
✗ conformance     62990dd  behind      ✗ site        62990dd  behind
✗ conformance-kit 62990dd  behind      ✗ static-mcp  62990dd  behind
✗ door-kit        62990dd  behind      ✗ guest-room  8b7d8a8  behind
✗ drift-gate      62990dd  behind      ✓ front-desk-scheduler  162accb  current

The polarity has inverted since #10 was filed. That issue found the two reference adopters lagging and re-pinned them. The fan-out then landed ~44 repos on what was current that day; the template moved to 162accb; and the two repos #10 repaired are now the only current ones. Same defect, opposite direction, larger radius — which is why a one-time re-pin isn't the fix. It buys a day.

Three consequences that make this more than cosmetic:

  • grace-expires is built but not deployed. The mechanism added for Remediation queue: clear findings and remove report-only grace (it has no expiry and no owner) #8 — unbounded-grace warning, fail-closed on malformed dates, hard-fail past the date — doesn't exist at 62990dd. It reaches 2 of ~46 repos.
  • The Monday canary tests a digest the fleet doesn't rescan on. Converter fixes, digest corrections and scanner bumps land on main and reach nobody.
  • Nothing goes red. A stale caller keeps scanning happily under old rules, so this is invisible until someone diffs it by hand.

Answering #10's open question: the resolver doesn't cover this

#10 leaned toward a pin resolver in self-test generalising better than a per-repo drift gate. The measurement says otherwise: 62990dd resolves perfectly. git cat-file -e passes. A resolver catches fabricated SHAs (@REPLACE_WITH_MERGE_SHA, a hand-typed 40-hex) and is structurally blind to a stale-but-valid pin — which is the failure that actually happened, twice.

What distinguishes staleness is ancestry, not existence: git merge-base --is-ancestor <caller-pin> <template-pin> is true exactly when a caller is behind. That comparison needs to read other repos, so it can't live in templates/. Both checks are wanted; they catch disjoint failures, the same complementarity check_template_pins.py already documents between shape and resolution.

What's here

file
tools/caller-pins.py enumerate callers, extract pins, classify by ancestry, emit a table plus one FDS-PINS-RESULT line
.github/workflows/caller-pins.yml Monday 06:41, after self-test (06:17) and before the fleet rescans (Tue 07:23)
test/test_caller_pins.py 14 tests over the pure half
self-test.yml, flake.nix wired into both runners, per the parity rule
README.md a "Bumping the shared osv-scan lane" procedure, with re-pinning as step 3

Stdlib only — no requests, the same constraint that shapes deno-lock-cdx.py.

unknown is a distinct state from behind. If a sha can't be resolved locally (shallow checkout, forked pin), the tool abstains rather than guessing — a census that guesses produces re-pin PRs against repos nobody measured. That's the property the tests exist for, and it's why the workflow sets fetch-depth: 0.

Empty census fails. Zero callers is refused rather than reported green — the hollow-green shape check_template_pins.py guards one lane over.

Deliberately not here

Re-pinning. Opening a PR per laggard needs contents:write + pull_requests:write org-wide. The good news is that needs no new App and no standing PAT: bounded-systems-front-desk is already installed on all repos, and front-desk-pin is an existing broker entry at exactly those permissions. It's one new pinned GH_APPS entry naming caller-pins.yml's ref — the broker refuses contents:write on an unpinned entry (unsafePrivilegedApp), which is the right refusal. That's a wrangler.jsonc change through the reviewer-gated deploy lane, so it lands separately.

Failing on lag. fail-on-lag defaults false while the fleet is knowingly behind — a lane red every week for a known reason teaches people to ignore it, which is the required-baseline.yml failure this repo keeps citing. Flip it to true once the bulk re-pin lands and it becomes a ratchet.

Private repos are invisible while unauthenticated, and are counted and reported as unexamined rather than silently dropped.

Note on running it from a session

A cloud session can't enumerate the org — GET /orgs/{org}/repos is 403 at the egress proxy. Hence --repos a,b,c for spot checks; the census proper belongs on a runner. That constraint is why this is a workflow and not something a session runs on request.

🤖 Generated with Claude Code

https://claude.ai/code/session_017RMKHpGXzw9Zkv49fzVssg


Generated by Claude Code

A caller's `uses: ...@<sha>` resolves the reusable workflow AT THAT COMMIT,
so the pin decides which scanner that repo actually runs. Nothing detected a
caller left behind: templates/ has no drift lane against its callers.

That gap has now fired twice in opposite directions. #10 found the two
reference adopters four commits behind the template and re-pinned them; the
fan-out then landed ~44 repos on what was current that day, the template
moved to 162accb, and the two repaired repos became the only current ones.
Measured across 10 callers: 9 behind (8 at 62990dd, guest-room still at
8b7d8a8), 1 current.

Why this is not self-test's template-pins job: that proves a pin names a
REAL commit, which is a different question. A stale pin is a real commit --
62990dd resolves perfectly and is four behind. Staleness is ancestry, so the
check is `git merge-base --is-ancestor`, and it needs fetch-depth 0.

Report-only for now. Opening a re-pin PR per laggard needs contents:write +
pull_requests:write org-wide, which here means a new PINNED GH_APPS broker
entry (front-desk-pin is the precedent; the broker refuses contents:write on
an unpinned entry). That is a wrangler.jsonc change through the
reviewer-gated deploy lane, so it lands separately from the measurement.

Unauthenticated, so public repos only -- private repos are counted and
reported as unexamined rather than silently dropped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RMKHpGXzw9Zkv49fzVssg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants