Skip to content

SRE-904: Split token minting from the release run - #9192

Open
claude[bot] wants to merge 3 commits into
mainfrom
sre-904/release-oidc-split
Open

SRE-904: Split token minting from the release run#9192
claude[bot] wants to merge 3 commits into
mainfrom
sre-904/release-oidc-split

Conversation

@claude

@claude claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Requested by Tim Diekmann · Slack thread

🌟 What is the purpose of this PR?

Ports the token-minting split from hashintel/.github#99 to this repo's release workflow, and removes id-token: write from a job that never consumes it. This is a supply-chain containment change: it narrows what compromised dependency code running in CI can reach.

Before: the single release job held id-token: write while running the full dependency graph (mise/Rust toolchain install, yarn install, turbo builds, yarn changeset publish and every module those load). Any compromised build-time dependency in that job could not only read the HASH Release App installation token and NPM_TOKEN from its own environment, but also use the job-wide ACTIONS_ID_TOKEN_REQUEST_* credentials to mint fresh OIDC tokens and authenticate to any Vault role whose claim bindings the run satisfies — at minimum the sccache role, whose R2 credentials allow poisoning the shared compile cache that feeds every Rust build. Similarly, deploy.yml's setup job granted id-token: write to a job that runs turbo query (dependency code) but consumes no OIDC at all.

After: only a new mint-token job holds id-token: write, and it runs nothing but the pinned github-app-token composite action — no repository dependency code executes there. The release job holds no OIDC permission: compromised dependency code there gets at most the hour-long installation token it is handed (which the split intentionally does not protect — the publish needs it), and can no longer sign fresh App JWTs in Vault or fetch sccache credentials. The dead grant in deploy.yml's setup job is gone entirely.

🔗 Related links

🚫 Blocked by

  • Repo secret RELEASE_TOKEN_ENC_KEY must exist in hashintel/hash before merge (value: openssl rand -base64 32; repo-level secret). Without it the mint job fails at its : "${ENC_KEY:?}" guard on the next push to main.
  • Repo secret RENOVATE_TOKEN_ENC_KEY — the bumped housekeeping-dependencies.yml declares it required: true. Already created in hashintel/hash as part of the SRE-904: Split token minting from the Renovate run .github#99 rollout, so the passthrough works immediately.

🔍 What does this change?

  • .github/workflows/release.yml — split into two jobs:
    • mint-token (environment: main kept — the ci-hash-release Vault role binds the OIDC environment claim): contents: read + id-token: write only; runs the existing pinned github-app-token action unchanged, then encrypts the token with openssl enc -aes-256-cbc -pbkdf2 -salt -pass env:ENC_KEY -base64 -A keyed by the new RELEASE_TOKEN_ENC_KEY secret. Only ciphertext leaves the job (GitHub drops masked values from job outputs, so plaintext could not cross anyway). : "${VAR:?}" guards fail loud on missing inputs. The openssl encrypt/decrypt round-trip was verified against OpenSSL 3.0.13 (the ubuntu-latest version).
    • release: no id-token; decrypts as its first step and ::add-mask::s the plaintext before anything else runs, then the existing checkout/install/changesets steps unchanged — except install-tools now gets sccache: false (the sccache credential fetch was the only remaining OIDC consumer in this job). The Rust toolchain stays: publishing @blockprotocol/type-system builds the wasm artifact from the Rust crate (build:wasm via wasm-pack; rust/pkg/ is gitignored, so it cannot come from the checkout), so rust: false was not an option. The cost is uncached Rust compiles in this job. environment: main is kept on this job too so environment-scoped secrets remain reachable.
    • NPM_TOKEN handling and the changesets config are untouched.
  • .github/workflows/deploy.ymlsetup job: id-token: writecontents: read. The job passes rust: false to install-tools, and the sccache credential fetch (gated on Rust) is the only OIDC consumer in that action — nothing in the job can use the grant, so it only widened what its dependency code (turbo query) could mint.
  • .github/workflows/{preflight,preflight-todo-comments,housekeeping}.yml + release.yml — bump every hashintel/.github pin from 8c1a3b1 to b7a5d7f651c1d6a862d5dd97aa6164125bedb6c5, the merge commit of SRE-904: Split token minting from the Renovate run .github#99. The bump crosses only Include messages within json_state output #98 (Renovate 43.288.0) and Fix behavior execution for Javascript runners #99 (the mint split); all referenced reusable workflows and the github-app-token action exist unchanged at the new pin.
  • .github/workflows/housekeeping.yml — pass RENOVATE_TOKEN_ENC_KEY through to the reusable workflow, which now requires it for the same encrypted job-boundary handoff.

Deliberately not changed:

  • canary-release.yml keeps its id-token: write. Its only OIDC consumer is the sccache credential fetch, but the canary publish runs the same yarn changeset publish path and therefore needs the Rust toolchain for the @blockprotocol/type-system wasm build; dropping sccache there trades a real (uncached full Rust builds on a manually-dispatched workflow) for a marginal gain — the stealable asset is the stage-Vault sccache role, not an App token. Can be revisited if the cache-poisoning angle is judged to outweigh that.
  • publish-blocks-to-preview.yml was in scope (two sccache-only id-token grants alongside yarn build + unpinned npx blockprotocol@latest), but SRE-908: Delete the block-publishing workflows #9187 deleted both block-publishing workflows before this PR — nothing left to fix.
  • No changes to the ds-helpers publish ordering or any publish-verification steps — separate workstream.

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 split does not protect the installation token itself — the publish step needs it, so dependency code in the release job can still read it. What the split removes is the ability to mint: fresh App JWTs signed in Vault, sccache R2 credentials, or any other role reachable with a fresh OIDC token.
  • If npm trusted publishing (SRE-768 follow-up) later replaces NPM_TOKEN, the release job will need id-token: write back for the npm exchange — that use is inseparable from the publish step. The Vault/App-token mint should stay in mint-token regardless.

🐾 Next steps

  • Consider the same split for deploy.yml's sourcemaps job (Sentry token mint + dependency code); lower value, tracked separately.

🛡 What tests cover this?

  • None automated beyond workflow linting (actionlint on all five changed files; the only findings are the pre-existing queue: keys actionlint's schema does not know). Release workflows are only exercised by a real push to main.

❓ How to test this?

  1. After creating the two secrets, merge and watch the next main push: mint-token should complete in seconds and output only ciphertext; release should decrypt, mask, and proceed through changesets exactly as before.
  2. Confirm the run's release job shows no id-token in its permissions block and no sccache install.
  3. Housekeeping: confirm the next scheduled run dispatches (the RENOVATE_TOKEN_ENC_KEY secret already exists; the requirement would fail fast at dispatch if it were missing).

📹 Demo

Not applicable (CI-only change).

Port the hashintel/.github#99 pattern to release.yml: only a new
mint-token job holds id-token: write and runs no repository dependency
code; the release job receives the App token as ciphertext and holds no
OIDC permission, so compromised build/publish dependencies can no
longer mint fresh Vault-signed App JWTs. Also drop the unused id-token
grant from deploy.yml's setup job, bump hashintel/.github pins to the
merge commit of that PR, and pass the now-required
RENOVATE_TOKEN_ENC_KEY through to the housekeeping workflow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HPkZcHmt5qmnGHtVB96d7
@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
hash Building Building Preview Aug 10, 2026 4:49pm
hashdotdesign-tokens Ready Ready Preview Aug 10, 2026 4:49pm
petrinaut Ready Ready Preview Aug 10, 2026 4:49pm

run: |
: "${TOKEN_CIPHERTEXT:?}" "${ENC_KEY:?}"
token=$(printf '%s' "${TOKEN_CIPHERTEXT}" | openssl enc -d -aes-256-cbc -pbkdf2 -pass env:ENC_KEY -base64 -A)
echo "::add-mask::${token}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:

GitHub Actions workflow command masking can be bypassed by attackers who can inject stop-commands payload, exposing the decrypted token in plaintext logs.

More details about this

The decrypted token is being masked using echo "::add-mask::${token}" in the workflow, but this masking is fragile and can be bypassed by attackers. While add-mask prevents the plaintext token from appearing in logs under normal conditions, an attacker who gains write access to this workflow (by compromising a dependency or gaining access to the repository) can insert a stop-commands payload like echo "::stop-commands::stopMarker" before any steps that use this token. This will disable GitHub Actions workflow command processing, causing the GITHUB_TOKEN environment variable and the token output to be logged in plaintext, completely defeating the masking.

Concrete attack scenario:

  1. An attacker compromises a transitive npm dependency used in the actions/checkout or .github/actions/* steps
  2. The compromised code executes early in the workflow and outputs echo "::stop-commands::STOP"
  3. This disables workflow command processing for all subsequent steps
  4. When later steps run git push or changesets/action using the unmasked token from steps.app-token.outputs.token, the plaintext token appears directly in the logs
  5. The attacker reads the logs and extracts the token to impersonate the release process or access npm

The root issue is relying solely on add-mask for secret protection when attackers can disable workflow commands entirely.

To resolve this comment:

✨ Commit fix suggestion

Suggested change
echo "::add-mask::${token}"
run: |
: "${TOKEN_CIPHERTEXT:?}" "${ENC_KEY:?}"
token=$(printf '%s' "${TOKEN_CIPHERTEXT}" | openssl enc -d -aes-256-cbc -pbkdf2 -pass env:ENC_KEY -base64 -A)
echo "token=${token}" >>"${GITHUB_OUTPUT}"
View step-by-step instructions
  1. Remove the echo "::add-mask::${token}" line so the workflow does not rely on the add-mask command for protection.

  2. Keep the decrypted token out of stdout by only writing it to GitHub’s file-based channels, such as "$GITHUB_OUTPUT" or "$GITHUB_ENV", and never printing it with echo by itself.
    For this step, keep echo "token=${token}" >>"${GITHUB_OUTPUT}", because GITHUB_OUTPUT is a file and does not depend on workflow command parsing.

  3. Avoid any shell options or debug settings in this step that could print commands or variable values, such as set -x, because that would expose ${token} in logs even without the add-mask line.

  4. Pass the token to later steps through the existing output reference, such as token: ${{ steps.app-token.outputs.token }} and GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}, instead of re-echoing or logging the plaintext token anywhere else.

  5. Alternatively, if you want to reduce the amount of time the plaintext token exists in a shell variable, write it directly to "$GITHUB_OUTPUT" from the decrypt command flow and avoid a separate token reuse beyond that step.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by unsafe-add-mask-workflow-command.

You can view more details about this finding in the Semgrep AppSec Platform.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We're keeping the mask, intentionally. A ::stop-commands:: payload presupposes an attacker already running code inside this job — and that code can read the token straight out of its own environment, so masking was never the security boundary here. The boundary this PR actually adds is the job split: the job that runs dependency code no longer holds id-token: write, so a compromise is limited to the short-lived, repo-scoped installation token it was handed, with no path back to Vault to mint fresh ones.

Applying the suggested fix would make log hygiene strictly worse: without add-mask, the decrypted value is never registered for redaction, so any accidental print — including ACTIONS_STEP_DEBUG expression evaluation of steps.app-token.outputs.token — lands in plaintext logs. Values written to GITHUB_OUTPUT are not auto-masked; the mask is the only thing keeping them out of debug output.

This mirrors the same reviewed pattern in hashintel/.github#99.

Leaving triage (/fp / /ar) to the reviewers.


Generated by Claude Code

run: |
: "${TOKEN_CIPHERTEXT:?}" "${ENC_KEY:?}"
token=$(printf '%s' "${TOKEN_CIPHERTEXT}" | openssl enc -d -aes-256-cbc -pbkdf2 -pass env:ENC_KEY -base64 -A)
echo "::add-mask::${token}"
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 59.63%. Comparing base (f06f964) to head (f720252).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #9192   +/-   ##
=======================================
  Coverage   59.63%   59.63%           
=======================================
  Files        1420     1420           
  Lines      138767   138767           
  Branches     6555     6555           
=======================================
  Hits        82754    82754           
  Misses      54949    54949           
  Partials     1064     1064           
Flag Coverage Δ
apps.hash-ai-worker-ts 1.99% <ø> (ø)
apps.hash-api 14.00% <ø> (ø)
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.22% <ø> (ø)
rust.antsi 2.36% <ø> (ø)
rust.error-stack 90.81% <ø> (ø)
rust.harpc-codec 84.70% <ø> (ø)
rust.harpc-net 96.23% <ø> (ø)
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.33% <ø> (ø)
rust.hash-graph-store 46.78% <ø> (ø)
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.

@codspeed-hq

codspeed-hq Bot commented Aug 10, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 98 untouched benchmarks


Comparing sre-904/release-oidc-split (f720252) with main (f06f964)

Open in CodSpeed

@claude
claude Bot marked this pull request as ready for review August 10, 2026 14:29
@cursor

cursor Bot commented Aug 10, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes release authentication flow and CI secrets handling on main; merge requires RELEASE_TOKEN_ENC_KEY or release will fail, but scope is limited to workflows.

Overview
Supply-chain containment for release and deploy CI: the monolithic release job is split so only mint-token runs the pinned github-app-token action with id-token: write, encrypts the app token with RELEASE_TOKEN_ENC_KEY, and passes ciphertext to a separate release job that decrypts/masks it first, then runs checkout, install-tools, and changesets as before (without the stage Vault/sccache inputs on install-tools).

Deploy setup swaps a pointless id-token: write grant for contents: read on the job that only runs turbo query.

Shared workflow pins move from 8c1a3b1 to b7a5d7f across preflight, todo-comments, housekeeping, and release; housekeeping now forwards RENOVATE_TOKEN_ENC_KEY into the reusable dependencies workflow.

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

@claude
claude Bot requested a review from TimDiekmann August 10, 2026 14:29
@github-actions

Copy link
Copy Markdown
Contributor

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$25.7 \mathrm{ms} \pm 186 \mathrm{μs}\left({\color{gray}-0.609 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.42 \mathrm{ms} \pm 19.4 \mathrm{μs}\left({\color{gray}-0.230 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1002 $$12.6 \mathrm{ms} \pm 99.4 \mathrm{μs}\left({\color{gray}1.64 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$42.6 \mathrm{ms} \pm 348 \mathrm{μs}\left({\color{gray}-0.734 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$14.2 \mathrm{ms} \pm 127 \mathrm{μs}\left({\color{gray}-1.657 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1527 $$24.3 \mathrm{ms} \pm 166 \mathrm{μs}\left({\color{gray}1.82 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$26.9 \mathrm{ms} \pm 208 \mathrm{μs}\left({\color{gray}1.30 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.77 \mathrm{ms} \pm 20.4 \mathrm{μs}\left({\color{gray}0.179 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$13.9 \mathrm{ms} \pm 97.0 \mathrm{μs}\left({\color{gray}4.79 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.74 \mathrm{ms} \pm 17.3 \mathrm{μs}\left({\color{gray}0.577 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.01 \mathrm{ms} \pm 13.9 \mathrm{μs}\left({\color{gray}0.620 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 52 $$3.37 \mathrm{ms} \pm 18.5 \mathrm{μs}\left({\color{gray}1.03 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.10 \mathrm{ms} \pm 38.3 \mathrm{μs}\left({\color{gray}0.502 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.55 \mathrm{ms} \pm 15.1 \mathrm{μs}\left({\color{gray}0.047 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 108 $$4.13 \mathrm{ms} \pm 23.2 \mathrm{μs}\left({\color{gray}0.615 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.39 \mathrm{ms} \pm 29.8 \mathrm{μs}\left({\color{gray}-1.147 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.47 \mathrm{ms} \pm 15.3 \mathrm{μs}\left({\color{gray}0.270 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$4.12 \mathrm{ms} \pm 28.5 \mathrm{μs}\left({\color{gray}0.674 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.61 \mathrm{ms} \pm 15.5 \mathrm{μs}\left({\color{gray}-2.958 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.53 \mathrm{ms} \pm 12.8 \mathrm{μs}\left({\color{gray}-0.908 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 2 $$2.61 \mathrm{ms} \pm 16.3 \mathrm{μs}\left({\color{gray}-3.283 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$2.85 \mathrm{ms} \pm 22.2 \mathrm{μs}\left({\color{gray}-3.217 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.67 \mathrm{ms} \pm 12.8 \mathrm{μs}\left({\color{gray}-3.202 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$2.89 \mathrm{ms} \pm 20.0 \mathrm{μs}\left({\color{gray}-1.692 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$3.06 \mathrm{ms} \pm 19.5 \mathrm{μs}\left({\color{gray}0.704 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.76 \mathrm{ms} \pm 14.5 \mathrm{μs}\left({\color{gray}-0.460 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 26 $$2.94 \mathrm{ms} \pm 16.8 \mathrm{μs}\left({\color{gray}-2.526 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.43 \mathrm{ms} \pm 21.6 \mathrm{μs}\left({\color{gray}0.995 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.03 \mathrm{ms} \pm 15.6 \mathrm{μs}\left({\color{gray}-0.234 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 27 $$3.25 \mathrm{ms} \pm 16.0 \mathrm{μs}\left({\color{gray}-1.955 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.36 \mathrm{ms} \pm 18.6 \mathrm{μs}\left({\color{gray}0.049 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.00 \mathrm{ms} \pm 14.7 \mathrm{μs}\left({\color{gray}-1.272 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.27 \mathrm{ms} \pm 21.4 \mathrm{μs}\left({\color{gray}-1.443 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$42.4 \mathrm{ms} \pm 195 \mathrm{μs}\left({\color{gray}0.393 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$33.4 \mathrm{ms} \pm 168 \mathrm{μs}\left({\color{gray}-1.824 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$36.2 \mathrm{ms} \pm 178 \mathrm{μs}\left({\color{gray}0.559 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$32.6 \mathrm{ms} \pm 200 \mathrm{μs}\left({\color{lightgreen}-31.574 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$42.0 \mathrm{ms} \pm 189 \mathrm{μs}\left({\color{gray}0.613 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$49.9 \mathrm{ms} \pm 312 \mathrm{μs}\left({\color{gray}1.56 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$40.8 \mathrm{ms} \pm 228 \mathrm{μs}\left({\color{gray}1.57 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$92.6 \mathrm{ms} \pm 528 \mathrm{μs}\left({\color{gray}0.780 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$34.3 \mathrm{ms} \pm 154 \mathrm{μs}\left({\color{gray}-0.072 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$274 \mathrm{ms} \pm 929 \mathrm{μs}\left({\color{gray}0.155 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$11.0 \mathrm{ms} \pm 62.1 \mathrm{μs}\left({\color{gray}0.157 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$11.1 \mathrm{ms} \pm 63.0 \mathrm{μs}\left({\color{gray}-0.289 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$11.0 \mathrm{ms} \pm 48.0 \mathrm{μs}\left({\color{gray}-1.344 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$11.0 \mathrm{ms} \pm 63.0 \mathrm{μs}\left({\color{gray}-0.096 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$11.1 \mathrm{ms} \pm 68.5 \mathrm{μs}\left({\color{gray}0.835 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$11.0 \mathrm{ms} \pm 59.0 \mathrm{μs}\left({\color{gray}-0.039 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$11.2 \mathrm{ms} \pm 71.6 \mathrm{μs}\left({\color{gray}-0.035 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$11.1 \mathrm{ms} \pm 65.1 \mathrm{μs}\left({\color{gray}0.260 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$11.2 \mathrm{ms} \pm 69.7 \mathrm{μs}\left({\color{gray}0.285 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$11.5 \mathrm{ms} \pm 63.2 \mathrm{μs}\left({\color{gray}0.367 \mathrm{\%}}\right) $$ 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 $$11.8 \mathrm{ms} \pm 63.6 \mathrm{μs}\left({\color{gray}2.36 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$11.6 \mathrm{ms} \pm 69.4 \mathrm{μs}\left({\color{gray}1.14 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$11.5 \mathrm{ms} \pm 72.3 \mathrm{μs}\left({\color{gray}-1.691 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$11.4 \mathrm{ms} \pm 57.5 \mathrm{μs}\left({\color{gray}-0.199 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$11.5 \mathrm{ms} \pm 70.1 \mathrm{μs}\left({\color{gray}0.081 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$11.6 \mathrm{ms} \pm 68.9 \mathrm{μs}\left({\color{gray}-0.779 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$11.5 \mathrm{ms} \pm 57.0 \mathrm{μs}\left({\color{gray}0.016 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$11.7 \mathrm{ms} \pm 61.4 \mathrm{μs}\left({\color{gray}0.072 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$11.7 \mathrm{ms} \pm 60.3 \mathrm{μs}\left({\color{gray}-4.447 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$8.48 \mathrm{ms} \pm 44.7 \mathrm{μs}\left({\color{gray}-0.307 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$61.1 \mathrm{ms} \pm 378 \mathrm{μs}\left({\color{red}5.15 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$112 \mathrm{ms} \pm 727 \mathrm{μs}\left({\color{lightgreen}-6.373 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$68.6 \mathrm{ms} \pm 428 \mathrm{μs}\left({\color{gray}4.65 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$77.8 \mathrm{ms} \pm 487 \mathrm{μs}\left({\color{gray}2.46 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$85.9 \mathrm{ms} \pm 505 \mathrm{μs}\left({\color{lightgreen}-8.542 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$91.4 \mathrm{ms} \pm 600 \mathrm{μs}\left({\color{gray}-2.535 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$44.0 \mathrm{ms} \pm 280 \mathrm{μs}\left({\color{gray}-3.420 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$73.0 \mathrm{ms} \pm 443 \mathrm{μs}\left({\color{lightgreen}-5.790 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$50.4 \mathrm{ms} \pm 422 \mathrm{μs}\left({\color{gray}-4.847 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$60.1 \mathrm{ms} \pm 380 \mathrm{μs}\left({\color{gray}-3.717 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$62.3 \mathrm{ms} \pm 341 \mathrm{μs}\left({\color{gray}-3.434 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$62.7 \mathrm{ms} \pm 416 \mathrm{μs}\left({\color{lightgreen}-7.677 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$128 \mathrm{ms} \pm 552 \mathrm{μs}\left({\color{gray}0.221 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$139 \mathrm{ms} \pm 545 \mathrm{μs}\left({\color{gray}-0.803 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$18.0 \mathrm{ms} \pm 107 \mathrm{μs}\left({\color{gray}-3.009 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$538 \mathrm{ms} \pm 991 \mathrm{μs}\left({\color{gray}0.343 \mathrm{\%}}\right) $$ Flame Graph

Comment thread .github/workflows/deploy.yml Outdated
Comment thread .github/workflows/release.yml Outdated
vault_address: ${{ vars.VAULT_STAGE_ADDR }}
cf_access_client_id: ${{ vars.CF_ACCESS_STAGE_CLIENT_ID }}
cf_access_client_secret: ${{ secrets.CF_ACCESS_STAGE_CLIENT_SECRET }}
sccache: false

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Running turbo-command may invoke Rust as well. Let's keep it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HPkZcHmt5qmnGHtVB96d7

@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 1 potential issue.

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 f720252. Configure here.

environment: main
permissions:
contents: read
id-token: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dead OIDC grant on release

High Severity

id-token: write is restored on release while install-tools still lacks vault_address / cf_access_*, so sccache never runs (cf_access_client_secret != '' gate). Compromised dependency code can mint fresh OIDC tokens again, without any legitimate OIDC consumer in the job.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f720252. Configure here.

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.

3 participants