Skip to content

ci: triage on plain pull_request with explicit github token; skip fork PRs - #316

Merged
allxsmith merged 2 commits into
mainfrom
fix/312-ai-triage-event
Jul 15, 2026
Merged

allxsmith merged 2 commits into
mainfrom
fix/312-ai-triage-event

Conversation

@allxsmith

@allxsmith allxsmith commented Jul 15, 2026 •

Copy link
Copy Markdown
Owner

Pull Request

Description

Fixes #312 — the ai-triage Claude step died at startup with 401 Unauthorized - Invalid OIDC token: the claude-code-action's OIDC→app-token exchange rejects tokens minted under pull_request_target (the issues and pull_request paths were never affected — the July 11 triage on #240 and every deep review prove the exchange works there).

  • bulma-ui (@allxsmith/bestax-bulma)
  • create-bestax (create-bestax)
  • docs (@allxsmith/bestax-docs) — ai-development guide notes the new scope + comment author
  • Other: .github/workflows/ai-triage.yml, .claude/commands/triage-*.md, scripts/auto-close-duplicates.mjs, root CLAUDE.md

The fix (Bun-style), plus a deliberate scope cut:

  1. Trigger: pull_request_target → plain pull_request, and the job if gains a head-repo guard. Fork PRs are no longer triaged at all — auto and label paths alike, exactly the trade-off oven-sh/bun makes. Rationale in the workflow header: rather than mitigating the pull_request_target risk class (secrets + write token exposed to fork-triggered runs), we remove it. Fork runs would lack secrets under pull_request anyway; the guard turns that failure mode into a clean silent skip.
  2. github_token: ${{ secrets.GITHUB_TOKEN }} on the Claude step — verified against the pinned action's source: a provided token short-circuits before any OIDC code runs. id-token: write is dropped from the job. Bonus: GITHUB_TOKEN-authored comments can never re-trigger workflows.
  3. Authorship ripple, handled everywhere: triage comments now post as github-actions[bot] instead of claude[bot]. Everything that probes for them is now author-agnostic (marker + Bot-type author, never a specific login — Bun's convention):
    • the three .claude/commands/triage-*.md marker pre-checks (their --edit-last refresh already had the "only if it's your most recent comment" guard, so no clobber risk);
    • scripts/auto-close-duplicates.mjs findMarkerComment, which hard-required claude[bot] and would have matched nothing ever again after this change. Old claude[bot] comments still match (smoke-tested: latest-bot-wins across both identities; human comments containing a spoofed marker are still ignored).

Related Issue(s)

Fixes #312

Type of Change

  • Bug fix
  • New feature
  • Documentation
  • Other: CI workflow + automation scripts

Checklist

  • My code follows the project style guidelines
  • I have performed a self-review of my code
  • I have added/updated documentation as needed (ai-development guide, root CLAUDE.md, workflow header comments)
  • All new and existing tests passed (workflow YAML parses; node --check + behavioral smoke of findMarkerComment; prettier + check:conformance green)
  • If this PR changes commands, conventions, or package structure, the affected CLAUDE.md files are updated (root CLAUDE.md updated)

Note: this PR touches .github/**, a loop-refused path — it's driven manually, not by the AI loop.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pohc8xLkdx4gwXkW3xd7up


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved triage marker detection by matching any bot-authored triage comment markers (not a specific bot identity).
    • Updated duplicate auto-close to prefer the latest qualifying bot-authored triage comment.
  • Security & Reliability

    • Automatic triage now runs only for same-repository pull requests; fork-originated pull requests are skipped.
    • Tightened permissions and token handling to avoid broader access during triage.
  • Documentation

    • Clarified same-repository-only triage behavior and updated workflow/marker notes accordingly.

…k prs

Fixes the ai-triage Claude step's startup failure (#312): the action's
OIDC-to-app-token exchange returns 401 for tokens minted under
pull_request_target, so the step died before any session started.

Bun-style fix, plus a deliberate scope cut:

- Trigger switches pull_request_target -> pull_request, and the job if
  gains a head-repo guard so fork PRs skip cleanly (auto AND label
  paths). Fork PRs are no longer triaged at all - same trade-off
  oven-sh/bun makes, removing the pull_request_target risk class
  instead of mitigating it.
- The Claude step now passes github_token (GITHUB_TOKEN), which
  short-circuits the OIDC exchange entirely; id-token: write is
  dropped. Triage comments post as github-actions[bot].
- Everything probing those comments is now author-agnostic (marker +
  Bot-type author, never a login): the three triage command pre-checks
  and auto-close-duplicates.mjs findMarkerComment (which previously
  hard-required claude[bot] and would have matched nothing ever again).
- Docs: ai-development guide + root CLAUDE.md note the same-repo-only
  PR scope and the new comment author.

Fixes #312

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

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4f06c419-1834-49e5-9121-00f970b12fc7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The PR changes AI triage to use same-repository pull_request events, skips fork PRs, passes an explicit GitHub token, and recognizes markers from bot-authored comments. Documentation and duplicate auto-close detection are updated accordingly.

Changes

Triage workflow and marker handling

Layer / File(s) Summary
Workflow event and authentication boundaries
.github/workflows/ai-triage.yml
Triage switches to pull_request, gates out fork PRs, removes OIDC token permission, passes github_token, and documents base-branch-only, read-only PR access plus the accepted fork-label residual.
Bot-authored marker detection
.claude/commands/triage-*.md, scripts/auto-close-duplicates.mjs
Marker checks and duplicate selection accept bot-authored comments while retaining marker and duplicate-reference requirements.
Triage behavior documentation
CLAUDE.md, docs/docs/guides/getting-started/ai-development.md
Documentation states that fork PRs are skipped and triage applies only to same-repository pull requests.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHub
  participant TriageWorkflow
  participant ClaudeAction
  GitHub->>TriageWorkflow: Send pull_request event
  TriageWorkflow->>TriageWorkflow: Check head repository matches base repository
  TriageWorkflow->>ClaudeAction: Provide explicit github_token
  ClaudeAction->>GitHub: Read triage data and post bot-authored markers
Loading

Possibly related PRs

Suggested labels: claude-assisted

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main workflow auth change and the fork-PR skip behavior.
Description check ✅ Passed The description follows the template with summary, issue link, type of change, checklist, and context filled in.
Linked Issues check ✅ Passed The PR addresses #312 by switching to pull_request, passing GITHUB_TOKEN, and updating bot-author matching as required.
Out of Scope Changes check ✅ Passed The docs, CLAUDE.md, and script updates directly support the triage/auth changes and stay in scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/312-ai-triage-event

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

@github-actions

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://cb6825c3.bestax.pages.dev

Comment thread .github/workflows/ai-triage.yml

@claude claude 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.

Deep review — 1 finding(s)

# Severity Area Finding Location
1 🟡 Minor Correctness Job-level fork guard skips the always() label-removal step, so ai-triage wedges "on" when a fork PR is labeled .github/workflows/ai-triage.yml:115

Overall: The change is sound and unusually well-documented. Switching ai-triage.yml from pull_request_target to plain pull_request + an explicit github_token cleanly removes the fork-secrets risk class and sidesteps the #312 OIDC 401, and the findMarkerComment broadening from a hardcoded claude[bot] login to isBot() is correct — it transparently matches both pre-#312 (claude[bot]) and post-#312 (github-actions[bot]) verdict comments, and the marker + Duplicate of #N gate keeps unrelated bot comments out. The riskiest external assumption is that claude-code-action truly short-circuits its OIDC->app-token exchange when github_token is supplied (the entire fix depends on it) — worth a human sanity-check that a real same-repo run posts as github-actions[bot] and the auto-close cron still finds those markers. The only defect is the minor stuck-label UX regression noted inline. Budget probe, single-flight concurrency, and veto logic are all consistent with the new bot identity.

🏄 Clean set on this one, dude — they paddled out of the gnarly pull_request_target rip current and rode plain pull_request all the way in, secrets dry the whole way. Just a little label barnacle that sticks to fork PRs, totally cosmetic. Good to send it. 🌊

The job-level fork guard also skips the always() label-removal step, so
labeling a fork PR wedges the ai-triage label. Not fixable under plain
pull_request (fork runs cap GITHUB_TOKEN at read-only, so even a
standalone unlabel job's DELETE would 403) - accepted and documented:
fork PRs are never triaged, the label is inert, manual removal.

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

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://c8e31de7.bestax.pages.dev

@allxsmith
allxsmith merged commit a3131a1 into main Jul 15, 2026
20 checks passed
@allxsmith
allxsmith deleted the fix/312-ai-triage-event branch July 15, 2026 00:46
@allxsmith

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
✅ 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.

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 5.6.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.3.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] ai-triage: Claude step fails OIDC app-token exchange (401 "Invalid OIDC token") under pull_request_target

2 participants