Skip to content

ci: attestation-check verifies what users install, and its schedule cannot die silently (LAB-1036) - #65

Merged
27Bslash6 merged 3 commits into
mainfrom
lab-1036-install-drift-and-liveness
Aug 4, 2026
Merged

ci: attestation-check verifies what users install, and its schedule cannot die silently (LAB-1036)#65
27Bslash6 merged 3 commits into
mainfrom
lab-1036-install-drift-and-liveness

Conversation

@27Bslash6

@27Bslash6 27Bslash6 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR strengthens the attestation-check workflow to close two silent failure gaps identified in LAB-1036.

1. Verify what users actually install

Previously the workflow only verified that the latest GitHub release's .crate was authentic (valid SLSA provenance and CycloneDX SBOM). It did not confirm that this verified version is the one cargo add resolves by default. A new step, "Check crates.io serves the verified version", queries the crates.io API and fails the job when:

  • The crates.io API is unreachable or returns an error.
  • The response shape is unexpected (missing versions array) — fails closed rather than silently skipping yank detection.
  • The verified version has been yanked (yanked crates remain downloadable, so the existing download step cannot catch this).
  • No stable version exists at all.
  • max_stable_version does not match the verified version — meaning users installing via cargo add would get a version this job never verified (e.g., hand-published, prerelease-skipped, or a publish that died after tagging).

2. Prevent the schedule from dying silently

GitHub auto-disables schedule: triggers in public repos after ~60 days of inactivity, which would turn this job's failure mode into "not running at all." A new "Assert schedule liveness" step fails the job when the repository has had no push activity for more than 43 days — giving a red run and tracking issue before the schedule goes dark. The 43-day threshold leaves margin for at least two weekly cron attempts. Malformed push timestamps fail closed.

3. Per-failure-class issue deduplication

The "Open issue on failure" step now distinguishes two mutually exclusive failure classes:

  • Verification/version breaks — deduplicated per-tag.
  • Schedule liveness — deduplicated with a dedicated marker.

This prevents an open staleness issue from swallowing a later real attestation break for the same tag. Issue titles and bodies are tailored to each failure class, and the troubleshooting guidance is expanded to cover the new max_stable_version and push-activity checks.

4. Shared crates.io User-Agent

The descriptive crates.io User-Agent string (required because crates.io returns 403 to generic user agents) is consolidated into a job-level CRATES_IO_UA environment variable, shared across all crates.io calls in the job.


Summary

This PR hardens the attestation-check CI workflow to make the crates.io verification step more resilient and fail loudly rather than silently.

Changes

Network-level error handling

  • Wrapped the fetch call to the crates.io API in a try/catch block so that network-level failures (DNS resolution, connection resets) or non-JSON response bodies now fail with a descriptive error message instead of producing a raw unhandled-rejection stack trace.

Response shape validation

  • Added an explicit check for the presence of the crate object in the API response. An error-shaped 200 response missing the crate object now fails with a clear message instead of throwing a TypeError further down the pipeline.
  • Updated the surrounding comments to clarify the fail-closed intent, ensuring the yank/version checks cannot silently degrade into no-ops.

Purpose

These changes ensure the attestation check reliably verifies what users actually install from crates.io. By failing closed with clear diagnostics on any network failure or unexpected response shape, the workflow's scheduled runs cannot pass or die silently, preserving the integrity of the yank-status and install-drift detection.

…e (LAB-1036)

Gap 1: after verifying the latest GitHub release's crate, compare it to
crates.io max_stable_version — the version 'cargo add' actually resolves.
A hand-published version, a prerelease-skipped release, or a yank now goes
red instead of leaving the job green while users install an unverified
crate. The release→publish window (release.yml tags before cargo publish)
is tolerated only on a positive observation: verified side newer AND a
release.yml run observably queued/in progress.

Gap 2: assert schedule liveness in-job. GitHub silently disables schedule:
triggers in public repos after ~60 days of repo inactivity; fail at >50
days stale so the weekly cron goes red (and files its tracking issue)
before the schedule dies. 50, not 55: a margin narrower than the 7-day
cron period can be jumped over entirely.
…ed everywhere

Panel (bug-hunter, security, craftsman, catchphrase) findings applied:
- DELETE the release-window tolerance branch: unreachable for its stated
  purpose (during the window the crate isn't on crates.io, so the job is
  already red at the download step), and itself a fail-open — release.yml
  runs on every push to main, so an unrelated in-flight run would
  green-light a dead publish or yanked version. Mismatch now fails
  unconditionally.
- versions array: explicit Array.isArray fail-closed instead of '|| []'
  silently degrading yank detection.
- liveness threshold 50 → 43: margin must fit two weekly cron attempts so
  one delayed/dropped scheduled run still leaves a red before the ~60-day
  auto-disable.
- liveness comparison NaN-proofed: !(x <= 43) fails closed on unparsable
  pushed_at.
- distinct dedupe marker/title/body for liveness failures so an open
  staleness issue can't swallow a later real attestation break.
- crates.io UA hoisted to job-level env (was duplicated verbatim).
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 26 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9c401208-2753-43c0-beee-dc98c3fabd3d

📥 Commits

Reviewing files that changed from the base of the PR and between a19decd and 77b036d.

📒 Files selected for processing (1)
  • .github/workflows/attestation-check.yml

Comment @coderabbitai help to get the list of available commands.

@kodus-27b

This comment has been minimized.

Comment thread .github/workflows/attestation-check.yml Outdated
Comment thread .github/workflows/attestation-check.yml
@27Bslash6

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…rate-object shape (Kody review)

- wrap the fetch + JSON parse in try/catch: a DNS failure, connection
  reset, or non-JSON 200 body now fails with a named message instead of a
  raw unhandled-rejection trace (still red either way).
- guard data.crate before dereferencing max_stable_version, matching the
  existing versions-array shape guard: an error-shaped 200 fails with a
  message, not a TypeError.
@kodus-27b

kodus-27b Bot commented Aug 3, 2026

Copy link
Copy Markdown

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Business Logic

Access your configuration settings here.

@27Bslash6

Copy link
Copy Markdown
Contributor Author

@kody start-review

@27Bslash6
27Bslash6 merged commit daf3459 into main Aug 4, 2026
34 checks passed
@27Bslash6
27Bslash6 deleted the lab-1036-install-drift-and-liveness branch August 4, 2026 06:39
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