SRE-871: pin mise in CI and exclude unattested @yarnpkg/libzip@3.2.2 from trust policy - #9112
SRE-871: pin mise in CI and exclude unattested @yarnpkg/libzip@3.2.2 from trust policy#9112claude[bot] wants to merge 8 commits into
Conversation
…from trust policy
|
Semgrep found 1 This Renovate configuration does not set a minimum release age. Newly published packages can be malicious or unstable. Add |
…d gate renovate bumps by release age
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9112 +/- ##
==========================================
- Coverage 59.30% 59.30% -0.01%
==========================================
Files 1406 1406
Lines 135987 135987
Branches 6380 6380
==========================================
- Hits 80651 80650 -1
- Misses 54352 54353 +1
Partials 984 984 Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PR SummaryMedium Risk Overview Pins mise in GitHub Actions to Renovate gains regex Reviewed by Cursor Bugbot for commit 411d33f. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 411d33f. Configure here.
| "matchPackageNames": ["anyhow"], | ||
| "enabled": false | ||
| "enabled": false, | ||
| "minimumReleaseAge": "7 days" |
There was a problem hiding this comment.
Accidental release-age on anyhow
Low Severity
minimumReleaseAge was added to the disabled anyhow package rule. That rule only sets enabled: false, so the age setting has no effect and looks like an edit slip from the new jdx/mise rule, which already carries the intended minimumReleaseAge.
Reviewed by Cursor Bugbot for commit 411d33f. Configure here.
There was a problem hiding this comment.
This one is deliberate, not a slip: semgrep's renovate-missing-minimum-release-age rule flags every packageRules entry lacking the key (it failed the scan on b9d3729 with exactly this entry), and its suggested exception form "minimumReleaseAge": false is rejected by renovate 43.212.4's config validator ("should be a string"). Since the entry is enabled: false, the value is inert either way — it exists purely to satisfy both checks at once.
Generated by Claude Code
There was a problem hiding this comment.
Why do we set minimumReleaseAget in the first place here?
There was a problem hiding this comment.
The org semgrep policy (rule renovate-missing-minimum-release-age) requires a minimumReleaseAge on every packageRules entry — it failed this PR's scan when this entry lacked it. The rule's own exception form, "minimumReleaseAge": false, is rejected by renovate 43.212.4's config validator ("should be a string"), so a string value is the only form that passes both gates. Since this entry is enabled: false (anyhow updates are disabled entirely), the value has no effect on behavior.
If you'd rather not carry the inert key, the alternatives are triaging the semgrep finding as acceptable-risk in the platform, or updating the semgrep rule — happy to do either as a follow-up if you prefer.
Generated by Claude Code
Benchmark results
|
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 2002 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 1002 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 3314 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 1527 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 2078 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 1033 | Flame Graph |
policy_resolution_medium
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 102 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 52 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 269 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 108 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 133 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 63 | Flame Graph |
policy_resolution_none
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 2 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 2 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 8 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 3 | Flame Graph |
policy_resolution_small
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 52 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 26 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 94 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 27 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 66 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 29 | Flame Graph |
read_scaling_complete
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id;one_depth | 1 entities | Flame Graph | |
| entity_by_id;one_depth | 10 entities | Flame Graph | |
| entity_by_id;one_depth | 25 entities | Flame Graph | |
| entity_by_id;one_depth | 5 entities | Flame Graph | |
| entity_by_id;one_depth | 50 entities | Flame Graph | |
| entity_by_id;two_depth | 1 entities | Flame Graph | |
| entity_by_id;two_depth | 10 entities | Flame Graph | |
| entity_by_id;two_depth | 25 entities | Flame Graph | |
| entity_by_id;two_depth | 5 entities | Flame Graph | |
| entity_by_id;two_depth | 50 entities | Flame Graph | |
| entity_by_id;zero_depth | 1 entities | Flame Graph | |
| entity_by_id;zero_depth | 10 entities | Flame Graph | |
| entity_by_id;zero_depth | 25 entities | Flame Graph | |
| entity_by_id;zero_depth | 5 entities | Flame Graph | |
| entity_by_id;zero_depth | 50 entities | Flame Graph |
read_scaling_linkless
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id | 1 entities | Flame Graph | |
| entity_by_id | 10 entities | Flame Graph | |
| entity_by_id | 100 entities | Flame Graph | |
| entity_by_id | 1000 entities | Flame Graph | |
| entity_by_id | 10000 entities | Flame Graph |
representative_read_entity
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1
|
Flame Graph |
representative_read_entity_type
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| get_entity_type_by_id | Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba
|
Flame Graph |
representative_read_multiple_entities
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_property | traversal_paths=0 | 0 | |
| entity_by_property | traversal_paths=255 | 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=0 | 0 | |
| link_by_source_by_property | traversal_paths=255 | 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true |
scenarios
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| full_test | query-limited | Flame Graph | |
| full_test | query-unlimited | Flame Graph | |
| linked_queries | query-limited | Flame Graph | |
| linked_queries | query-unlimited | Flame Graph |


Requested by Tim Diekmann · Slack thread
🌟 What is the purpose of this PR?
Before: any branch that misses the mise tool cache hits a cold
mise installin CI and fails with a trust-downgrade error for@yarnpkg/libzip@3.2.2(a transitive dependency of thenpm:renovatetool). CI also installed whatever mise version happened to be latest at run time, which is how this enforcement change arrived unannounced.After: cold installs pass, mise is pinned everywhere (and bumpable by Renovate), and aube's
trustPolicy=no-downgradestays enforced for every npm-backed tool — except the single reviewed version@yarnpkg/libzip@3.2.2.Why the failure happens:
renovate@43.212.4→@yarnpkg/core@4.8.0(exact pin) →@yarnpkg/libzip@^3.2.2, and the only version in range — 3.2.2 — was published without provenance attestation. It is benign: content verified against the source tag; it was a manual backfill publish by the maintainer after a failed CI release run (see forensics in the Slack thread). Enforcement arrived when embedded aube became mise's default npm installer (mise 2026.7.12, jdx/mise#11149); pinning any mise ≤ 2026.7.11 would instead silently shell out to the npm CLI with no trust checks. The pin is therefore set to 2026.7.14 — the newest installable release with enforcement. 2026.7.15 (released today) was tried first, but its release assets are not fully propagated yet (the GitHub release currently shows only 2 assets and it is absent from npm), which broke everyInstall toolsstep; Renovate will propose the bump once it has settled — and withminimumReleaseAge: 7 daysit will be settled by then.🔗 Related links
trust_policy_excludesdocs🔍 What does this change?
.config/mise/config.toml:npm:renovategainstrust_policy_excludes = ["@yarnpkg/libzip@3.2.2"], scoped to exactly that version, with aTODO(SRE-871)comment.min_versionunchanged (see Dockerfile note below), now Renovate-annotated..config/mise/mise.lock: thenpm:renovateentry gains the matchingoptionsline. This is required — with the tool option set,mise install --lockedrejects the old lockfile entry (npm:renovate@43.212.4 is not in the lockfile). The added line is byte-identical to whatmise installregenerates..github/actions/install-tools/action.yml:jdx/mise-actionnow pinsversion: 2026.7.14instead of installing latest-at-run-time.apps/{hash-graph,hash-frontend,hash-api,hash-ai-worker-ts,hash-integration-worker}/docker/Dockerfile):MISE_VERSIONstays at 2026.7.0 but is now Renovate-annotated. Bumping the images to 2026.7.14 was tried and reverted: mise changed its cargo backend between 2026.7.0 and 2026.7.14 (native binary fast path in 2026.7.1, cargo-quickinstall disabled + binstall fallback rework in 2026.7.6), and inside the arm64 imagesmise exec cargo:cargo-insta(invoked by@rust/hash-codec#build:types) fell back to a source compile that fails onrustix v0.37.27("attributes starting withrustcare reserved") — see the failed run. The amd64 runner-side install of the same tool passes, so the CI pin at 2026.7.14 is unaffected.min_versionstays at 2026.6.13 accordingly (2026.7.0 refuses configs with a higher floor)..github/renovate.json: Renovate 43.212.4'sgithub-actionsmanager does not trackjdx/mise-action'sversioninput natively (verified against its source — onlyactions/setup-{go,node,python}and a fixed community-actions list), so this adds two regexcustomManagerscovering the annotated pins (action input +min_version) and the DockerfileMISE_VERSIONpins. The# renovate:annotations and the managers travel together in this PR. Also adds apackageRulesentry forjdx/misesettingdependencyDashboardApproval: falseso bump PRs open without the dashboard checkbox gate (strike that in review if you'd rather keep the gate) andminimumReleaseAge: "7 days"so a brand-new mise release never lands the day it ships — the exact failure mode that caused this incident (and that 2026.7.15 demonstrated again today).Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
apps/hash-frontend/vercel-install.shandapps/petrinaut-website/vercel-install.shstill install mise unpinned via yum from mise.jdx.dev/rpm; pinning them is a possible follow-up.MISE_VERSIONpast 2026.7.0, the arm64 image builds will hit thecargo:cargo-instasource-compile failure above until either cargo-insta ships arm64 binaries mise's new fast path can use, therustix 0.37.27transitive is gone from cargo-insta's tree, or mise's compile fallback is fixed — that bump PR failing CI is the intended signal, not a silent break.🐾 Next steps
@yarnpkg/libzip> 3.2.2 ships — tracked in SRE-871.@yarnpkg/libzip@3.2.2for jdx/aube's built-inDEFAULT_TRUST_POLICY_EXCLUDES(it matches that list's pattern of legit-maintainer publishes that lost provenance) — noted in SRE-871.🛡 What tests cover this?
.config/mise/config.tomlchange alters the mise-action cache key, so CI runs a genuinely coldmise install --env ci --locked— exactly the scenario that was failing. It passed (3m48s cold install).npm:renovatereproduces the exact trust-downgrade error; with the exclusion and the updated lock entry,mise install --locked npm:renovatesucceeds (602 packages, via embedded aube against the live registry) and leavesmise.lockunchanged..github/renovate.jsonpassesrenovate-config-validator --strict(renovate 43.212.4, the same version CI runs), and a local-platform Renovate dry run extracts thejdx/misepins from all 7 annotated/matched sites.❓ How to test this?
mise installwithcienvironment" step in this PR's CI runs — it performs the previously-failing cold install.docker buildany of the five app images — behavior unchanged (pin stays 2026.7.0).