Skip to content

fix(strix): add missing github-token fallback for self-target status publish - #1441

Closed
seonghobae wants to merge 7 commits into
mainfrom
fix/strix-self-target-status-token-403-20260830
Closed

fix(strix): add missing github-token fallback for self-target status publish#1441
seonghobae wants to merge 7 commits into
mainfrom
fix/strix-self-target-status-token-403-20260830

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1434's investigation (item 3 of the coordinator's priority list): fixes the secondary target-app-token HTTP 403 finding on repository_dispatch Strix runs that target .github itself.

  • Root cause: strix.yml's publish-manual-pr-evidence-status job's target-app-token (an OpenCode app-token exchange) is scoped for sibling repositories, not for .github as the target of its own repository_dispatch — this central repo normally dispatches Strix to siblings, not to itself, so this token can never succeed for that self-referential case. Observed live on PR fix(zdr): cite NVIDIA's own Trial ToS for the nvidia_nim not-ZDR classification #1434's own dispatch run (ContextualWisdomLab/.github/actions/runs/33306963425): target-app-token did not succeed: gh: Resource not accessible by integration (HTTP 403), followed by a hard failure — the publisher only tolerates an unpublishable status when the underlying scan result was itself success (correct fail-closed behavior, not the bug).
  • Fix: the job already declares permissions: statuses: write, so github.token has exactly the scope this case needs. A near-identical status-publish block ~40 lines earlier in the same file already has this exact fallback (a GITHUB_STATUS_TOKEN env var conditioned on target_repository == github.repository, so it's never attempted — and never a source of new noise — for a genuine cross-repo target). This second block had simply drifted without it; this PR mirrors the existing pattern exactly.
  • No behavior change for genuine cross-repo repository_dispatch targets (the new fallback is empty and skipped in that case, same as today).

Test plan

  • coverage run -m pytest tests -q — 1882 passed, 1 skipped, 21 subtests (unchanged from main)
  • interrogate — 100.0% (unchanged)
  • coverage report — 99% total, single pre-existing miss in scripts/ci/pingora_edge_policy.py:274 (untouched)
  • python3 -c "yaml.safe_load(...)" on strix.yml
  • tests/test_pr_governance_audit_contract.py passes

Not verified on a live hosted run: reproducing the original failure requires a repository_dispatch Strix run targeting .github itself, the same rare trigger path that surfaced the bug.

🤖 Generated with Claude Code

https://claude.ai/code/session_015Gs7KmNvH75nxz1sL8mKjw


Generated by Claude Code


Devin Review

Summary by CodeRabbit

  • 버그 수정

    • 저장소 자체를 대상으로 하는 수동 Strix 상태 게시가 실패하던 문제를 수정했습니다.
    • 이제 해당 상황에서는 상태가 정상적으로 게시됩니다.
    • 다른 저장소를 대상으로 하는 기존 동작에는 변경이 없습니다.
  • 문서

    • 관련 장애 원인과 수정 내용을 변경 로그 및 기술 문서에 반영했습니다.

…publish

The publish-manual-pr-evidence-status job's target-app-token (an OpenCode
app-token exchange) is scoped for sibling repositories and always 403s when
.github is the repository_dispatch target of its own Strix run -- observed
live on PR #1434's own repository_dispatch run
(ContextualWisdomLab/.github/actions/runs/33306963425): "target-app-token
did not succeed: gh: Resource not accessible by integration (HTTP 403)",
then a hard failure since the publisher only tolerates an unpublishable
status when the scan result was itself success.

The job already declares permissions: statuses: write, so github.token has
exactly the scope this self-referential case needs. A near-identical
status-publish block ~40 lines earlier in the same file already has this
exact fallback (GITHUB_STATUS_TOKEN, conditioned on target_repository ==
github.repository so it's never attempted -- and never a source of new
403 noise -- for a genuine cross-repo target); this second block had
simply drifted without it. Mirrors that existing pattern exactly.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 7 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 89c64325-657c-441c-83d0-7e3e88ff322c

📥 Commits

Reviewing files that changed from the base of the PR and between 698ffde and 3bca264.

📒 Files selected for processing (4)
  • .github/workflows/strix.yml
  • CHANGELOG.md
  • docs/product-technical-gap-baseline.md
  • scripts/ci/test_strix_quick_gate.sh

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e689002-7027-4755-b5c0-cdadd2e9595b

📥 Commits

Reviewing files that changed from the base of the PR and between e36a1f7 and 698ffde.

📒 Files selected for processing (3)
  • .github/workflows/strix.yml
  • CHANGELOG.md
  • docs/product-technical-gap-baseline.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

publish-manual-pr-evidence-status가 자기 저장소를 대상으로 실행될 때 github.token을 상태 게시 폴백으로 사용합니다. 관련 변경 사항과 장애 원인을 변경 로그 및 기술 문서에 기록했습니다.

Changes

Strix 상태 게시 수정

Layer / File(s) Summary
상태 게시 폴백과 변경 기록
.github/workflows/strix.yml, CHANGELOG.md, docs/product-technical-gap-baseline.md
target_repository가 비어 있거나 현재 저장소와 같을 때 github.token을 제공합니다. target-app-token 시도 후 post_strix_status "github-token" 폴백을 실행합니다. 교차 저장소 대상의 동작은 유지됩니다. 관련 원인과 검증 상태를 문서에 기록했습니다.

Estimated code review effort: 1 (Trivial) | ~5분

Merge Risk: 🔵 Low · up to 698ff

The workflow now recovers same-repository status publication when the delegated token is unavailable, without changing cross-repository behavior. A bounded merge-readiness risk remains because a failed target-validation path may still publish a failure status using raw dispatch values; this is mergeable with explicit owner awareness and follow-up to gate publication on validated target data.

Suggested reviewers: cursoragent

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 self-target 상태 게시에 필요한 github-token 폴백 추가를 정확히 설명합니다. 변경의 주요 목적과 범위를 간결하게 전달합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (3 skipped: 3 unsupported.)

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/strix-self-target-status-token-403-20260830

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

devin-ai-integration[bot]

This comment was marked as resolved.

…nd declaration

Devin Review finding on the prior commit: the smoke test's
status_token_count assertion still expected exactly one GITHUB_STATUS_TOKEN
declaration, which the prior commit's second declaration (in
publish-manual-pr-evidence-status) broke. Fixed by:

- Updating the declaration-count assertion from 1 to 2 (one per
  status-publishing job).
- Adding a new assertion pinning both declarations to the identical
  same-repository conditional expression, so a future divergent copy
  (e.g. a typo'd comparison) fails closed here.
- Adding a new assertion on how many times post_strix_status is actually
  invoked with the github-token fallback (3: the strix job's own inline
  publish tries it twice -- mid-chain and as the final last-resort retry
  -- while publish-manual-pr-evidence-status tries it once), so a
  declared-but-unused token would also fail closed.

Verified against the actual file content, not assumed: ran the full
scripts/ci/test_strix_quick_gate.sh (PASS) and the full pytest suite (1882
passed) locally before pushing.

Co-Authored-By: Claude <noreply@anthropic.com>
seonghobae pushed a commit that referenced this pull request Aug 30, 2026
…t timeout)

Verified directly from #1441's noema-review job
log (99249903390, head d877886): healthz and the launcher's own internal
preflight succeeded (past the family-cap fix's stage entirely), but the
shell script's separate post-healthz gateway smoke request -- max_tokens
now 4096 per #1436's fix, up from 16 -- got zero bytes back for the full
120-second curl timeout. Distinct from both other evidence in this entry:
not a bad-request rejection (no response at all) and not Strix's own
client code path. Documented with plausible causes (the 120s ceiling never
re-examined when max_tokens grew 256x; a real server-side hang for a
specific request shape; transient flakiness) but not pursued further this
pass -- noted as evidence for whoever picks this up next.

Co-Authored-By: Claude <noreply@anthropic.com>
@seonghobae

Copy link
Copy Markdown
Contributor Author

Contextual-Orchestrator를 같이 손보든 어쩌든 해결하세요. Bypass merge 필요하면 가능 (chicken and eggs 상황이라면) + NVIDIA NIM 만 쓰는 건 허용하지 않아요. Contextual-Orchestrator를 쓰세요.

@devin-ai-integration devin-ai-integration Bot 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.

Devin Review found 3 new potential issues.

Devin Review

# sibling repos, not to ContextualWisdomLab/.github as its own
# target). Empty for a cross-repo target, matching post_strix_status's
# existing empty-token skip.
GITHUB_STATUS_TOKEN: ${{ (github.event.client_payload.target_repository == '' || github.event.client_payload.target_repository == github.repository) && github.token || '' }}

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.

📝 Info: Fallback remains repository-scoped

An absent target resolves to the workflow repository, while an explicit matching target selects GITHUB_STATUS_TOKEN. Sibling targets leave it empty and skip publication.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +1214 to +1216
if post_strix_status "github-token" "$GITHUB_STATUS_TOKEN"; then
exit 0
fi

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.

📝 Info: Fallback ordering preserves sibling behavior

Self-target runs try GITHUB_STATUS_TOKEN after the app token. Sibling runs skip the empty token, preserving the existing credential sequence.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 220 to +231
status_token_count="$(grep -c '^[[:space:]]*GITHUB_STATUS_TOKEN:' "$workflow_file")"
assert_equals "1" "$status_token_count" "strix workflow defines GITHUB_STATUS_TOKEN once so GitHub can parse repository_dispatch"
assert_equals "2" "$status_token_count" "strix workflow defines GITHUB_STATUS_TOKEN exactly twice, once per status-publishing job"
status_token_conditional_count="$(grep -c "GITHUB_STATUS_TOKEN: \${{ (github.event.client_payload.target_repository == '' || github.event.client_payload.target_repository == github.repository) && github.token || '' }}" "$workflow_file")"
assert_equals "2" "$status_token_conditional_count" "both GITHUB_STATUS_TOKEN declarations use the identical same-repository conditional"
# Three invocations, not two: the strix job's own inline publish tries
# the github-token fallback twice (once mid-chain, once as the final
# last-resort retry after every other credential has failed), while
# publish-manual-pr-evidence-status tries it once. Both jobs actually
# consuming their own declared GITHUB_STATUS_TOKEN (not just declaring
# and ignoring it) is the property under test here.
github_status_token_fallback_count="$(grep -c 'post_strix_status "github-token" "\$GITHUB_STATUS_TOKEN"' "$workflow_file")"
assert_equals "3" "$github_status_token_fallback_count" "both status-publishing jobs actually invoke their own GITHUB_STATUS_TOKEN fallback, not just declare it"

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.

📝 Info: Contract test couples global counts

The assertions count declarations and calls across the whole workflow. A future unrelated publisher will require updating this test despite preserving both protected jobs.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Ports the identical fix already applied to this session's #1476 and #1488
(commit 4323e27 pattern; root-caused in .github#1506, which targets main
but has not merged there yet). This PR's exact-head-path-policy check runs
its own head-branch copy of scripts/ci/test_strix_quick_gate.sh (plain
pull_request trigger, not pull_request_target), and the merge commit onto
this branch carried forward the pre-existing bug from both sides (neither
main nor this branch's own prior head had the fix), so it needs porting
here directly -- confirmed live: run 33455130248/job 99693376191 failed
with exactly this assertion.

Root cause: assert_opencode_review_uses_codegraph_and_contextual_orchestrator
extracted the required-workflow-bootstrap job block from
opencode-review.yml with awk '/^  required-workflow-bootstrap:$/,/^[^ ]/'.
Every job key in that workflow is indented 2 spaces (never column 0), so
the end pattern never matched until EOF, sweeping an unrelated if: line
from a later job into the "block" and failing the assertion on unrelated
content.

Fixed by using an explicit state flag so the end pattern
(^  [A-Za-z0-9_-]+:) is only tested starting on the line after the start
match, correctly bounding the block to just its own lines.

Verified directly: the old awk swept in line 219's `if: github.event.action
!= 'closed'` from a later job; the new awk captures zero if: lines. Full
local run: bash scripts/ci/test_strix_quick_gate.sh -> PASS, exit 0 (was
FAIL/exit 1 before this commit). coverage run -m pytest tests -q -> 2126
passed, 1 skipped, 21 subtests. coverage report -> 100%. interrogate ->
100%.

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

Copy link
Copy Markdown
Contributor Author

exact-head-path-policy failure on the merge-commit head — root-caused and fixed

The merge commit 7a94578 (main → this branch, resolving the earlier dirty conflict state) made exact-head-path-policy fail on run 33455130248/job 99693376191:

FAIL: opencode required workflow bootstrap must not depend on required-workflow event payload fields
...
test_strix_quick_gate: 1 failure(s)
Process completed with exit code 1

Root cause: this is the same pre-existing bug already root-caused and fixed elsewhere this session (.github#1506, targeting main; also ported directly onto #1476 and #1488's own branches). scripts/ci/test_strix_quick_gate.sh's assert_opencode_review_uses_codegraph_and_contextual_orchestrator extracted the required-workflow-bootstrap job block from opencode-review.yml with:

awk '/^  required-workflow-bootstrap:$/,/^[^ ]/' "$bootstrap_file"

Every job key in that workflow is indented 2 spaces (never column 0), so the range's end pattern (/^[^ ]/) never matches until EOF — the "block" swept in an unrelated if: line from a later job (line 219, if: github.event.action != 'closed', added by already-merged #1497) and failed the assertion on unrelated content.

I checked whether this dropped out of the merge or was reintroduced by main: neither. origin/main itself still carries the buggy awk pattern (#1506 hasn't merged there yet), and this branch's own prior head never had the fix either — exact-head-path-policy runs a plain pull_request-triggered copy of the script from each branch's own tree (not pull_request_target against the trusted base), so every open PR whose branch predates #1506 needs the fix ported onto its own copy directly, same as #1476/#1488.

Fix (commit 3bca264d): identical one-line change to the established pattern — an explicit awk state flag so the end pattern (^ [A-Za-z0-9_-]+:) is only tested starting the line after the start match, correctly bounding extraction to just the required-workflow-bootstrap job's own lines.

Verified:

  • Isolated before/after: old awk captured line 219's stray if:; new awk captures zero if: lines.
  • bash scripts/ci/test_strix_quick_gate.shtest_strix_quick_gate: PASS, exit 0 (was FAIL/exit 1 before).
  • coverage run -m pytest tests -q → 2126 passed, 1 skipped, 21 subtests.
  • coverage report → 100%. interrogate → 100%. YAML still well-formed.

Pushed as 3bca264d on top of the merge commit; no drift on the branch at push time (verified origin tip was an ancestor of the new commit before pushing).

🤖 Generated with Claude Code

https://claude.ai/code/session_015Gs7KmNvH75nxz1sL8mKjw


Generated by Claude Code

@seonghobae

Copy link
Copy Markdown
Contributor Author

Contextual-Orchestrator와 관계한 것들을 같이 손보든 어쩌든 해결하세요. Bypass merge 필요하면 가능 (chicken and eggs 상황이라면) + NVIDIA NIM 만 쓰는 건 허용하지 않아요. Contextual-Orchestrator를 쓰세요. Timeout은 적어도 3시간으로 잡으세요. 120초 같은 건 당황스럽군요. Opencode와 Noema 는 Coderabbitai 및 Devin 수준으로 실제로 리뷰를 하게 하시오. Strix도 보안 리뷰를 꼼꼼하게 하도록 하시오. 특히 보안 리뷰는 전체 코드로 수행하는 것입니다. Contextual-Orchestrator는 실시간으로 빠르면서 능력이 좋은 모델에 요청을 보내어 시간을 당기시오. @opencode-agent 라고 부르면 호출되는 기능도 인터넷 가이드에는 /oc 라고 나와있기 때문에 이 점도 확인해 보는 게 좋겠습니다.

Copy link
Copy Markdown
Contributor Author

Superseded by protected main. Fresh main@2436454e3a969a282b5edc7303a485ccd37c3e9f inspection confirms the actual Strix publish-manual-pr-evidence-status path already defines GITHUB_STATUS_TOKEN as github.token when the repository_dispatch target is empty/self (target_repository == '' || target_repository == github.repository), alongside the target-app and cross-repository token candidates. That is the causal self-target 403 fallback this PR introduced. Keeping this predecessor open no longer changes product behavior and only adds another required-workflow lane. Closing unmerged; historical hosted evidence remains here and does not transfer.

Copy link
Copy Markdown
Contributor Author

Superseded by protected main. Fresh main@5686de41660d51a7a7f22b8840dfa6ccfe5ff3f1 inspection shows strix.yml already sets GITHUB_STATUS_TOKEN exactly for same-repository/self-target dispatch (target_repository == '' || target_repository == github.repository) alongside the target-App and PR-review-merge credential paths, which is the causal fix this PR exists to add. Keeping this older four-file branch open now only consumes review/check capacity and risks replaying stale docs/test context. Closing unmerged; no predecessor checks or reviews are transferred. Any remaining status-publication defect should be reproduced against current main and filed as a new bounded owner.

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