Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion .github/workflows/organization-commercial-readiness-loop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
runs-on: ubuntu-24.04
timeout-minutes: 25
permissions:
contents: read
id-token: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
ORGANIZATION: ContextualWisdomLab
Expand All @@ -32,6 +35,7 @@ jobs:
egress-policy: block
allowed-endpoints: >-
api.github.com:443
api.opencode.ai:443
github.com:443
objects.githubusercontent.com:443
release-assets.githubusercontent.com:443
Expand All @@ -53,10 +57,68 @@ jobs:
- name: Coordinate one bounded fleet pass
env:
GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}
OIDC_AUDIENCE: opencode-github-action
OPENCODE_API_BASE_URL: https://api.opencode.ai
shell: bash --noprofile --norc -e -o pipefail {0}
run: |
set -euo pipefail

exchange_unavailable() {
echo "::error::OpenCode app token exchange unavailable: $1"
exit 1
}

if [ -z "${GH_TOKEN:-}" ]; then
if [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then
exchange_unavailable "OIDC request environment is missing."
fi

request_url="${ACTIONS_ID_TOKEN_REQUEST_URL}"
separator="&"
case "$request_url" in
*\?*) ;;
*) separator="?" ;;
esac

if ! oidc_response="$(
curl -fsS \
--connect-timeout 10 \
--max-time 30 \
-H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
"${request_url}${separator}audience=${OIDC_AUDIENCE}"
)"; then
exchange_unavailable "OIDC token request did not complete."
fi
if ! oidc_token="$(
jq -er '.value | select(type == "string" and length > 0)' \
<<<"$oidc_response" 2>/dev/null
)"; then
exchange_unavailable "OIDC token response was malformed or empty."
fi
echo "::add-mask::$oidc_token"

if ! token_response="$(
curl -fsS \
--connect-timeout 10 \
--max-time 30 \
-X POST \
-H "Authorization: Bearer ${oidc_token}" \
"${OPENCODE_API_BASE_URL}/exchange_github_app_token"
)"; then
exchange_unavailable "app token request did not complete."
fi
if ! app_token="$(
jq -er '.token | select(type == "string" and length > 0)' \
<<<"$token_response" 2>/dev/null
)"; then
exchange_unavailable "app token response was malformed or empty."
fi
echo "::add-mask::$app_token"
export GH_TOKEN="$app_token"
fi

if [ -z "${GH_TOKEN:-}" ]; then
echo "::error::PR_REVIEW_MERGE_TOKEN is required; neither the reviewer credential nor repository-scoped GITHUB_TOKEN is accepted."
echo "::error::PR_REVIEW_MERGE_TOKEN or the job-bound OpenCode App token exchange is required; neither reviewer credentials nor repository-scoped GITHUB_TOKEN are accepted."
exit 1
fi
echo "::add-mask::$GH_TOKEN"
Expand Down
12 changes: 11 additions & 1 deletion docs/doctoring/organization-commercial-readiness-loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ The coordinator may dispatch at most one review-repair workflow and one product-

A single workflow cannot safely write every repository merely because it runs in the organization `.github` repository. GitHub's default `GITHUB_TOKEN` is scoped to the repository containing the workflow; cross-repository Actions dispatch therefore requires an explicitly provisioned user or GitHub App credential with the required repository and Actions permissions. This control does not make every repository directly writable. It only considers repositories the live API reports as organization-owned, non-fork, enabled, non-archived, default-branch-bearing, and writable by the authenticated installation.

The central job therefore refuses both repository-scoped and reviewer-scoped token fallbacks. It requires the maintainer-scoped `PR_REVIEW_MERGE_TOKEN`; `OPENCODE_APPROVE_TOKEN` remains isolated to the reviewer credential chain and `GITHUB_TOKEN` is not accepted for cross-repository coordination. The maintainer token is exposed only to the final dispatch shell step, not checkout, setup, artifact upload, or other third-party actions. The coordinator itself receives neither `NVIDIA_NIM_API_KEY` nor `COPILOT_GITHUB_TOKEN`. Model credentials remain inside separately reviewed repository-local or central workers.
The central job prefers the maintainer-scoped `PR_REVIEW_MERGE_TOKEN`. If that secret is absent on the protected default-branch scheduled run, the job may use its job-bound GitHub OIDC identity to request the existing short-lived OpenCode GitHub App installation token. The fallback is limited to `id-token: write` on the coordinator job, the exact `api.opencode.ai` endpoint, bounded network timeouts, strict non-empty JSON token fields, and token masking. `OPENCODE_APPROVE_TOKEN`, repository-scoped `GITHUB_TOKEN`, reviewer credentials, model-provider keys, and `COPILOT_GITHUB_TOKEN` are not accepted as coordinator fallbacks. The selected maintainer credential is exposed only to the final dispatch shell step, not checkout, setup, artifact upload, or other third-party actions. Model credentials remain inside separately reviewed repository-local or central workers.

## 2026-09-01 protected-main credential failure RCA

Scheduled protected-main run `33483275421` checked out exact central source `5686de41660d51a7a7f22b8840dfa6ccfe5ff3f1` and failed before the coordinator process started. The `Coordinate one bounded fleet pass` step showed an empty `GH_TOKEN` and exited on the PAT-only guard with `PR_REVIEW_MERGE_TOKEN is required`. This is missing configuration/credential availability, not a downstream repository defect, model/provider outage, network failure, or a substantive test/security finding. Because the coordinator never started, the JSON fleet receipt was not created and the subsequent `if: always()` artifact upload failed independently with `No files were found`.

Protected `main` still carried the same PAT-only source after that run. The smallest repair keeps `PR_REVIEW_MERGE_TOKEN` as the first choice and, only when it is absent, exchanges the protected scheduled job's GitHub OIDC identity for the already established OpenCode GitHub App installation token. The exchange follows the existing central worker trust pattern: `api.opencode.ai:443` is the only added blocked-egress endpoint; both HTTP calls use 10-second connect and 30-second total timeouts; malformed or empty responses fail closed; both temporary tokens are masked; and neither the repository token nor reviewer/model credentials become mutation authority.

The broader DDD automation branch in PR #1545 independently carried the same credential-recovery design, but coupled it to unrelated architecture-contract work and was not mergeable on the current protected base during this incident. The focused current-main repair deliberately extracts only the credential boundary so recovery of the production schedule is not coupled to that larger feature. PR #1545 may later absorb the integrated fallback when it reconciles with protected main.

A pull-request quality run proves the static workflow contract and full coordinator test suite. It cannot prove a real protected-default-branch OIDC exchange because pull-request code must not receive a production job-bound mutation identity. Operational acceptance therefore requires a post-integration scheduled run on protected `main` whose exact source contains the fallback, reaches the coordinator rather than the missing-PAT guard, emits its deterministic JSON receipt, and preserves all downstream fail-closed governance.

## Dynamic repository-writer lease

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,26 @@ def test_maintainer_token_is_scoped_only_to_the_dispatch_step() -> None:
assert "PR_REVIEW_MERGE_TOKEN" not in before_dispatch
assert "GH_TOKEN:" not in before_dispatch
assert "env:\n GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}" in dispatch_step


def test_missing_maintainer_secret_uses_bounded_job_oidc_exchange() -> None:
"""A protected scheduled pass must not die solely because the PAT is absent."""
source = WORKFLOW_PATH.read_text(encoding="utf-8")
_, dispatch_step = source.split(
" - name: Coordinate one bounded fleet pass\n", maxsplit=1
)

assert "id-token: write" in source
assert "api.opencode.ai:443" in source
assert "OIDC_AUDIENCE: opencode-github-action" in dispatch_step
assert "OPENCODE_API_BASE_URL: https://api.opencode.ai" in dispatch_step
assert "ACTIONS_ID_TOKEN_REQUEST_TOKEN" in dispatch_step
assert "ACTIONS_ID_TOKEN_REQUEST_URL" in dispatch_step
assert "--connect-timeout 10" in dispatch_step
assert "--max-time 30" in dispatch_step
assert "/exchange_github_app_token" in dispatch_step
assert 'export GH_TOKEN="$app_token"' in dispatch_step
assert "::add-mask::$oidc_token" in dispatch_step
assert "::add-mask::$app_token" in dispatch_step
assert "${{ github.token }}" not in dispatch_step
assert "GITHUB_TOKEN:" not in dispatch_step
Loading