Skip to content

SRE-915: Resolve the Vault target from the job's environment - #9161

Open
TimDiekmann wants to merge 4 commits into
mainfrom
t/sre-915-narrow-vault-dev-role-housekeeping-workflow
Open

SRE-915: Resolve the Vault target from the job's environment#9161
TimDiekmann wants to merge 4 commits into
mainfrom
t/sre-915-narrow-vault-dev-role-housekeeping-workflow

Conversation

@TimDiekmann

@TimDiekmann TimDiekmann commented Aug 4, 2026

Copy link
Copy Markdown
Member

🌟 What is the purpose of this PR?

Two CI secrets move to a dedicated ci/ mount, each read by a role scoped to a single path: the sccache build cache and the Sentry sourcemap token.

Stacked on #9160. The Vault side is already applied.

🔗 Related links

  • SRE-915 (internal)
  • Terraform: internal-infra#319

🚫 Blocked by

🔍 What does this change?

Sentry — the sourcemaps job declares a GitHub environment, and both the Vault address and the Cloudflare Access credentials resolve from it. Each instance holds only its own tier's token, so the role name and the path carry no tier. The environment is keyed on the ref, so a workflow_dispatch on main — a publishing run elsewhere in this workflow — gets the same tier as a push.

sccacheinstall-sccache reads ci/data/sccache/r2 with role: ci-hash-sccache instead of role: dev, and sends Access headers. install-tools gained vault_address, cf_access_client_id and cf_access_client_secret; the sccache gate moved to the client secret, which keeps it skipped on fork pull requests.

sccache stays on explicitly pinned names rather than the environment-resolved ones: it runs in twenty jobs that declare no environment, and a shared cache should serve pull requests and main alike. Its install step is now continue-on-error — a cache must not be able to fail the build.

Legacybench.yml and release.yml still read their own secrets from the old Vault and take its address inline, because they have no environment and would otherwise resolve to the wrong instance. test.yml lost a VAULT_ADDR it no longer read.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

⚠️ Known issues

  • The sourcemaps job now produces a deployment record per run, pull requests included. Accepted for one job; the same on the sccache path would mean ~20 per run.
  • account_id and bucket sit in Vault alongside the two R2 keys although neither is a secret, so both are masked in logs and the sccache endpoint reads as https://***.r2.cloudflarestorage.com. Moving them out means two more inputs across 20 call sites, which is not worth it until endpoint debugging actually hurts.
  • bench and release still read from the old Vault. Retiring it needs those two moved first.

🐾 Next steps

  • Once merged, the repo-level VAULT_ADDR variable and secret are unreferenced and can go.

🛡 What tests cover this?

  • sccache: every workflow using install-tools with Rust enabled exercises it. With continue-on-error a Vault failure no longer fails the job, so check the step's own outcome rather than the job's.
  • Sentry: a pull-request run of deploy.yml covers one tier, a push to main the other.
  • Verified against both applied Vaults: each role carries the expected claims, and the field names match what the actions request.
  • Not covered: fork pull requests, which cannot be exercised from a same-repo branch.

❓ How to test this?

  1. Any Install tools step with Rust enabled — Retrieve secrets succeeds and Start sccache server connects
  2. A deploy.yml run with sourcemaps in the matrix — sentry-cli login succeeds
  3. A job with rust: false still skips sccache

📹 Demo

Not applicable, CI-only change.

The exported Vault token has no consumers — VAULT_TOKEN appears only as VAULT_TOKEN: "" in five places, clearing it again. Dropping exportToken removes the job-environment path, which was the only Vault path the payload could have walked on a GitHub runner. secrets: inherit passed the full secret set to a reusable workflow that reads no secrets.*, and contents: write was never used because Renovate commits with the App token.
…coped role

The credentials move to ci/data/sccache/r2 behind a single-path policy, read by the ci-hash-sccache role instead of the broad dev role. The endpoint sits behind Cloudflare Access, so vault-action sends a service-token pair scoped to this repo and this environment. The sccache gate moves from vault_address to the Cloudflare client secret, which is the value that is actually required and is still empty on fork pull requests.
@TimDiekmann TimDiekmann self-assigned this Aug 4, 2026
@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview Aug 5, 2026 1:01am
hashdotdesign-tokens Ready Ready Preview Aug 5, 2026 1:01am
petrinaut Error Error Aug 5, 2026 1:01am

@github-actions github-actions Bot added the area/infra Relates to version control, CI, CD or IaC (area) label Aug 4, 2026
@vercel
vercel Bot temporarily deployed to Preview – hashdotdesign-tokens August 4, 2026 22:24 Inactive
@vercel
vercel Bot temporarily deployed to Preview – petrinaut August 4, 2026 22:26 Inactive
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 59.57%. Comparing base (c5953fd) to head (29e65af).

Additional details and impacted files
@@                                           Coverage Diff                                           @@
##           t/sre-901-harden-the-centralized-renovate-workflow-against-compromised    #9161   +/-   ##
=======================================================================================================
  Coverage                                                                   59.57%   59.57%           
=======================================================================================================
  Files                                                                        1413     1413           
  Lines                                                                      138053   138053           
  Branches                                                                     6510     6510           
=======================================================================================================
  Hits                                                                        82240    82240           
  Misses                                                                      54771    54771           
  Partials                                                                     1042     1042           
Flag Coverage Δ
apps.hash-ai-worker-ts 1.99% <ø> (ø)
apps.hash-api 12.56% <ø> (ø)
blockprotocol.type-system 40.84% <ø> (ø)
local.claude-hooks 0.00% <ø> (ø)
local.harpc-client 51.49% <ø> (ø)
local.hash-backend-utils 3.27% <ø> (ø)
local.hash-graph-sdk 10.02% <ø> (ø)
local.hash-isomorphic-utils 12.25% <ø> (ø)
rust.antsi 2.36% <ø> (ø)
rust.error-stack 90.81% <ø> (ø)
rust.harpc-codec 84.70% <ø> (ø)
rust.harpc-net 96.19% <ø> (ø)
rust.harpc-tower 67.03% <ø> (ø)
rust.harpc-types 0.00% <ø> (ø)
rust.harpc-wire-protocol 92.23% <ø> (ø)
rust.hash-codec 72.76% <ø> (ø)
rust.hash-graph-api 7.36% <ø> (ø)
rust.hash-graph-authorization 62.59% <ø> (ø)
rust.hash-graph-embeddings 91.88% <ø> (ø)
rust.hash-graph-postgres-store 29.66% <ø> (ø)
rust.hash-graph-store 42.16% <ø> (ø)
rust.hash-graph-temporal-versioning 47.95% <ø> (ø)
rust.hash-graph-types 0.00% <ø> (ø)
rust.hash-graph-validation 84.71% <ø> (ø)
rust.hashql-ast 89.63% <ø> (ø)
rust.hashql-compiletest 28.39% <ø> (ø)
rust.hashql-core 78.98% <ø> (ø)
rust.hashql-diagnostics 72.51% <ø> (ø)
rust.hashql-eval 79.82% <ø> (ø)
rust.hashql-hir 89.09% <ø> (ø)
rust.hashql-mir 87.92% <ø> (ø)
rust.hashql-syntax-jexpr 94.04% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@TimDiekmann
TimDiekmann marked this pull request as ready for review August 4, 2026 22:28
Copilot AI balanced review requested due to automatic review settings August 4, 2026 22:28
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes how CI authenticates to Vault and which secrets paths/roles are used; misconfigured repo vars or environment bindings would break Rust caching or Sentry uploads across many workflows, though scope is narrowed compared to the old dev role.

Overview
CI moves sccache (R2) and Sentry sourcemap credentials off the broad dev Vault role onto the staging Vault behind Cloudflare Access, with path-scoped roles.

sccache (install-sccache / install-tools): Vault login uses role ci-hash-sccache, reads ci/data/sccache/r2, and sends CF Access headers. install-tools forwards vault_address plus CF client id/secret, skips sccache when the secret is empty (fork PRs), and sets continue-on-error: true on the sccache step. Nine workflows wire vars.VAULT_STAGE_ADDR and the stage CF credentials into every install-tools call.

Sentry (deploy.yml sourcemaps): The job picks GitHub environment main vs pull-request from the ref so OIDC binds the right tier; Vault uses ci-hash-sentry, environment-scoped vars.VAULT_ADDR / CF headers, and ci/data/sentry/sourcemaps instead of automation/data/pipelines/hash/{prod,dev}.

Legacy Vault stays inline where tier vars would be wrong: bench.yml keeps https://vault.blockprotocol.org for AWS deploy creds; release.yml uses the same URL for the GitHub App worker secrets. test.yml drops the workflow-level VAULT_ADDR secret.

Reviewed by Cursor Bugbot for commit 29e65af. Bugbot is set up for automated code reviews on this repo. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Moves sccache credential retrieval to the staging Vault’s dedicated CI mount and scoped role.

Changes:

  • Adds Cloudflare Access authentication to the sccache action.
  • Uses the scoped ci-hash-sccache role and ci/data/sccache/r2 secrets.
  • Propagates staging Vault credentials through 20 workflow call sites.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
.github/actions/install-sccache/action.yml Configures scoped Vault and Cloudflare authentication.
.github/actions/install-tools/action.yml Adds and forwards the new authentication inputs.
.github/workflows/ai-pr-review.yml Supplies staging Vault configuration.
.github/workflows/bench.yml Supplies staging Vault configuration.
.github/workflows/canary-release.yml Supplies staging Vault configuration.
.github/workflows/codspeed.yml Supplies staging Vault configuration.
.github/workflows/deploy.yml Supplies staging Vault configuration.
.github/workflows/lint.yml Supplies staging Vault configuration.
.github/workflows/publish-blocks-to-preview.yml Supplies staging Vault configuration.
.github/workflows/release.yml Supplies staging Vault configuration.
.github/workflows/test.yml Supplies staging Vault configuration.

@codspeed-hq

codspeed-hq Bot commented Aug 4, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 15.38%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 2 regressed benchmarks
✅ 96 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
bit_matrix/dense/iter_row[64] 140.8 ns 170 ns -17.16%
bit_matrix/dense/iter_row[200] 185.8 ns 215 ns -13.57%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing t/sre-915-narrow-vault-dev-role-housekeeping-workflow (29e65af) with t/sre-901-harden-the-centralized-renovate-workflow-against-compromised (c5953fd)

Open in CodSpeed

The job picked its Vault role from an expression about its own trigger, and nothing checked it. The role now binds the environment claim and, for main, the ref, so a pull-request branch cannot reach the main-tier token. The tokens move to ci/sentry/{main,pull-request} in the staging Vault.
Copilot AI review requested due to automatic review settings August 4, 2026 22:59
@TimDiekmann TimDiekmann changed the title SRE-915: Read the sccache credentials from the staging Vault with a scoped role SRE-915: Read CI secrets from the staging Vault with scoped roles Aug 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

.github/workflows/deploy.yml:264

  • The PR description explicitly says that only sccache moves and that deploy keeps reading its own secrets from the other Vault, but this block also migrates SENTRY_AUTH_TOKEN to the staging ci/ mount and new role/environment contract. Please either revert the Sentry migration so the code matches the stated rollout boundary, or update the PR and its infrastructure verification to include this additional migration.
          url: ${{ vars.VAULT_STAGE_ADDR }}
          method: jwt
          role: ci-hash-sentry-${{ env.VAULT_TIER }}
          extraHeaders: |
            CF-Access-Client-Id: ${{ vars.CF_ACCESS_CI_CLIENT_ID }}

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a7283dd. Configure here.

Comment thread .github/workflows/deploy.yml Outdated
Comment thread .github/workflows/deploy.yml Outdated
The Sentry sourcemap job declares a GitHub environment, and the Vault address and Cloudflare Access credentials resolve from it: pull-request points at the staging instance, main at production. Each instance holds only its own tier's token, so the role name and the secret path carry no tier.

sccache is deliberately exempt. It runs in twenty jobs that declare no environment, and a shared build cache should serve pull requests and main alike, so it keeps explicitly pinned names for the staging instance. Its install step also becomes non-fatal: a cache must not be able to fail the build.

The two consumers still on the legacy Vault take its address inline, because they have no environment and would otherwise resolve to the wrong instance.
Copilot AI review requested due to automatic review settings August 5, 2026 00:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (2)

.github/actions/install-tools/action.yml:59

  • continue-on-error converts every Vault authentication, secret lookup, installation, or server-start failure inside install-sccache into a successful tools setup. A wrong role/path or an unavailable Vault will therefore leave Rust jobs compiling without the configured cache while CI stays green, contrary to the stated verification that failures surface at Retrieve secrets. The existing if already skips fork PRs when the secret is empty, so remove this suppression and let failures on configured runs propagate.
      continue-on-error: true

.github/workflows/deploy.yml:264

  • This implementation does not match the Vault contract described in the PR: the PR says both Sentry tiers are in the staging Vault at ci/data/sentry/{main,pull-request} under roles ci-hash-sentry-{tier}, whereas this selects the production Vault for main and uses one ci-hash-sentry role plus ci/data/sentry/sourcemaps. Because the Vault state is already applied, please reconcile the workflow with that applied role/path layout (or update the PR contract if this newer per-instance layout is the applied one) before merging.
          # Address and Access credentials come from the job's environment:
          # `pull-request` resolves to the staging Vault, `main` to production.
          # Each instance holds only its own tier's token, so the role name and
          # the path carry no tier — the instance is the tier.
          url: ${{ vars.VAULT_ADDR }}

@TimDiekmann TimDiekmann changed the title SRE-915: Read CI secrets from the staging Vault with scoped roles SRE-915: Resolve the Vault target from the job's environment Aug 5, 2026
Base automatically changed from t/sre-901-harden-the-centralized-renovate-workflow-against-compromised to main August 5, 2026 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/infra Relates to version control, CI, CD or IaC (area)

Development

Successfully merging this pull request may close these issues.

2 participants