Skip to content

feat: soothfast-bot identity for comments, pages, releases - #165

Merged
Verdenroz merged 2 commits into
feat/soothfast-actionfrom
feat/soothfast-bot-identity
Sep 6, 2026
Merged

Verdenroz merged 2 commits into
feat/soothfast-actionfrom
feat/soothfast-bot-identity

Conversation

@Verdenroz

@Verdenroz Verdenroz commented Sep 6, 2026

Copy link
Copy Markdown
Owner

What changed

Three writes were still attributed to github-actions after #164: the gate comment on pull requests, the gh-pages push in deploy-docs, and gh release create. All three now carry the soothfast-bot identity. Pull request jobs never receive a token for it: the broker posts the gate comment itself. Release creation moves to its own job because a job carries one environment and publish already needs the release approval gate.

  • Added POST /comment to the broker. A pull_request run from the repository itself, in the soothfast-bot environment, sends {pull_request, marker, body} over its OIDC identity; the broker checks the number against the run's own merge ref, mints a pull_requests: write token for itself, creates or updates the comment that starts with the marker, and revokes the token. The job holds nothing. /token refuses pull_request runs outright.
  • Accepted tag refs for a landing token only when the compare of default branch to the OIDC sha reports behind or identical. The commit that ran is what is judged, never the tag name, so moving a tag after the run starts changes nothing. Revoked on any other status.
  • action/oidc.sh holds the broker URL and OIDC fetch shared by bot-token.sh and comment.sh. comment.sh tries the broker first and falls back to the caller's token; gate.sh runs the gate before any comment and passes no token into it.
  • soothfast-gate.yml runs in the soothfast-bot environment with id-token: write, checks out this repository's action/ at github.job_workflow_sha so a cross-repo caller gets matching scripts, installs the CLI through that checkout instead of a pinned self-reference, and posts its comment through the broker with the same fallback.
  • deploy-docs pushes gh-pages with a landing token and revokes it. release.yml gains a release job (report, changelog extraction, gh release create as soothfast-bot) between publish and binaries; publish drops the rustdoc pin it no longer needs.
  • Gate output quoted in the comment is text the pull request's own binaries wrote, now under a write-access author. It stays inside a code fence and any fence sequence in it is neutralised first, so no line of it can become top-level markdown (an @mention or a ChatOps command) posted as soothfast-bot. The broker validates a /comment body before it authenticates, so a malformed request costs no mint.
  • docs/ci.md and CLAUDE.md describe the flow. The App's permission list is unchanged.

Part of #158.

Why

Harvey's requirement is that soothfast-bot is the only identity soothfast writes with. A pull request runs unmerged code, so it must never hold a write credential; having the broker post the comment keeps the identity without handing the job anything. A tag push was excluded because a tag is not the default branch; requiring the tagged commit to already be on it makes the release equivalent to a workflow_dispatch on master. The same environment opt-in gates every request.

How was this tested

  • npm test: 64 passed, 0 failed. New coverage: /comment creates or updates by marker and ignores other bots' comments, refuses a different pull request number, validates the body and size, revokes its token on every path; /token refuses pull_request; a tag is judged by sha (the fake asserts the compared head); pull_request_target, issue_comment, and head refs stay refused.
  • tsc --noEmit: clean. shellcheck -x on all eight scripts: clean. zizmor 1.29.0 on every workflow and action.yml: no findings.
  • bot-token.sh fails loudly with no OIDC token; comment.sh falls back to the job token when the broker is unreachable (the case CI is in until the Worker is deployed).
  • Not run end to end. The first exercise is this PR's own gate matrix once the broker is live (the comment should appear as soothfast-bot); the release path runs at the next tag.
  • make check and make gate were not run for this layer. It changes no Rust.

Manual, before the first run: this repository's soothfast-bot environment must have no deployment branch policy, since the gate now uses it on pull requests and the release on tags.

Checklist

  • make check passes (fmt, clippy -D warnings, cargo test --workspace)
  • make gate BASE=master passes, or any intentional cost change is explained above
  • Tests added/updated for new behavior (not required for docs/CI-only changes)
  • Public API items have /// doc comments
  • No new dependency, or its justification is included above (see Dependency Policy)
  • Docs (README.md, docs/, soothfast:bind/soothfast:claim markers) updated if behavior changed

Comment thread .github/workflows/release.yml Fixed
Comment thread .github/workflows/release.yml Fixed
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

soothfast gate

gate: measuring merge-base of origin/master in worktree (interleaved rounds)
gate: bench binaries identical (code and data match) — no measurable change possible
gate: gating backend = walltime
gate: build=08f03a noise_floor=0.07% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_site::bench_highlight walltime_median_ns 3202050.0 -> 3202050.0 (+0.0%)
ok    soothfast_site::bench_highlight allocs 88069 -> 88069 (allowed <= 92472)
ok    soothfast_site::bench_highlight alloc_bytes 2079336 -> 2079336 (allowed <= 2183302)
ok    soothfast_site::bench_md_render walltime_median_ns 3079070.0 -> 3079070.0 (+0.0%)
ok    soothfast_site::bench_md_render allocs 68118 -> 68118 (allowed <= 71523)
ok    soothfast_site::bench_md_render alloc_bytes 3502526 -> 3502526 (allowed <= 3677652)
ok    soothfast_site::bench_highlight assert complexity: claimed O(n); growth drift x1.19 over sizes [128, 512, 2048] (limit x2.5)
ok    soothfast_site::bench_md_render assert complexity: claimed O(n); growth drift x1.00 over sizes [256, 1024, 4096] (limit x2.5)
gate: passed (2 item(s))

@Verdenroz
Verdenroz force-pushed the feat/soothfast-bot-identity branch from 16db9f0 to dc23ff4 Compare September 6, 2026 01:13
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:14 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:14 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:14 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:14 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:14 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:14 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:14 — with GitHub Actions Active
@Verdenroz
Verdenroz force-pushed the feat/soothfast-bot-identity branch from dc23ff4 to 8f140cb Compare September 6, 2026 01:14
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:15 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:15 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:15 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:15 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:15 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:15 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:15 — with GitHub Actions Active
@Verdenroz
Verdenroz force-pushed the feat/soothfast-bot-identity branch from 8f140cb to 83d0a05 Compare September 6, 2026 01:20
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:21 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:21 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:21 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:35 — with GitHub Actions Active
@Verdenroz
Verdenroz force-pushed the feat/soothfast-bot-identity branch from 556a1eb to 96176f2 Compare September 6, 2026 01:35
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:38 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:38 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:38 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:38 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:38 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:38 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 01:38 — with GitHub Actions Active
@Verdenroz
Verdenroz force-pushed the feat/soothfast-bot-identity branch from 96176f2 to ce2e925 Compare September 6, 2026 02:01
@Verdenroz
Verdenroz force-pushed the feat/soothfast-bot-identity branch from ce2e925 to e15b3cd Compare September 6, 2026 02:02
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 02:03 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 02:03 — with GitHub Actions Active
@Verdenroz
Verdenroz deployed to soothfast-bot September 6, 2026 02:03 — with GitHub Actions Active
- Every write soothfast makes now carries the bot identity, and a pull
  request job still never holds a token: it sends the gate comment to
  the broker's /comment, which posts as the bot and revokes its own
  token.
- Tags are judged by the commit that ran (the OIDC sha), accepted only
  when it is already on the default branch, so a moved tag changes
  nothing and a release equals a dispatch from master.
- Release creation moves to its own job: a job carries one environment
  and publish already needs the release approval gate.
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.

2 participants