From 71c57ea647fbc376d1207f11d851c09504c9c02d Mon Sep 17 00:00:00 2001 From: bitkyc08-arch Date: Tue, 25 Aug 2026 10:37:05 +0900 Subject: [PATCH 1/4] release: v2.32.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f73ed2d0e5..063ecfe73e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bitkyc08/opencodex", - "version": "2.32.0", + "version": "2.32.1", "description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code", "type": "module", "main": "./bin/package-main.mjs", From ec51e42d745d2645bcb22cb67855fa053ba1778e Mon Sep 17 00:00:00 2001 From: bitkyc08-arch Date: Tue, 25 Aug 2026 20:25:22 +0900 Subject: [PATCH 2/4] release: v2.33.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 063ecfe73e..6f8499ffbf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bitkyc08/opencodex", - "version": "2.32.1", + "version": "2.33.0", "description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code", "type": "module", "main": "./bin/package-main.mjs", From aaa9eaf37058965373dc42d1ca344e987950b6b6 Mon Sep 17 00:00:00 2001 From: JUN Date: Wed, 2 Sep 2026 18:43:29 +0900 Subject: [PATCH 3/4] fix(release): pass the bump job's permissions through the reusable-workflow call (#3262) Both v2.40.0 release dispatches (33615174183 preview, 33615177849 main) died at startup_failure: a workflow_call cannot grant its callee more than the calling job holds, and dev-version-bump.yml's job declares contents+pull- requests write. #3129 wired the call but never dispatched a release, so this is its first live run. The caller job now declares exactly the callee's two permissions; no other job in release.yml gains anything. Co-authored-by: jun (cherry picked from commit 7ce0ba51834740d7b4d5ec4793f6572d84624409) --- .github/workflows/release.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 458bb67e0a..261aece1d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -67,6 +67,14 @@ jobs: bump-dev-version: needs: publish if: ${{ inputs.dry-run != true }} + # A reusable-workflow CALL cannot grant the callee more than the calling job holds, + # and GitHub refuses the whole run at startup when the called workflow's own job + # declares permissions the caller did not pass down ("startup_failure", runs + # 33615174183 / 33615177849 — the first dispatches since #3129 wired this call). + # The callee's job declares exactly these two; nothing else in this file gains them. + permissions: + contents: write + pull-requests: write uses: ./.github/workflows/dev-version-bump.yml with: released-version: v${{ inputs.version }} From 5c4579a94c7f9858de32a75fda1537dbe0465e3a Mon Sep 17 00:00:00 2001 From: luvs01 Date: Thu, 3 Sep 2026 14:41:00 +0900 Subject: [PATCH 4/4] fix(release): isolate dev data from bump credentials --- .github/workflows/dev-version-bump.yml | 33 ++++++++++++++++++++------ tests/ci-workflows.test.ts | 18 +++++++++++++- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/.github/workflows/dev-version-bump.yml b/.github/workflows/dev-version-bump.yml index b884b04ace..cd4580d568 100644 --- a/.github/workflows/dev-version-bump.yml +++ b/.github/workflows/dev-version-bump.yml @@ -62,17 +62,27 @@ jobs: # Open the pull request. pull-requests: write steps: - - name: Checkout dev + # Keep every executable file in the privileged job pinned to the audited + # release revision. The later dev checkout is input data only: none of its + # actions, dependencies, scripts, or tests run with this job's token. + - name: Checkout trusted automation uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: - ref: dev + ref: ${{ github.sha }} # Tags are load-bearing, not decoration: the freeness gate below is a bun # test that reads the local tag set, and release-version-line.test.ts # returns EARLY on an empty set. A shallow checkout would make that gate # silently vacuous instead of failing loudly. fetch-depth: 0 - # Do NOT set persist-credentials: false here as the read-only workflows do. - # This job has to push its bump branch. + persist-credentials: false + + - name: Checkout dev as data + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + ref: dev + path: dev-tree + fetch-depth: 0 + persist-credentials: false # The repository-owned composite action, not a hand-pinned setup-bun SHA: it # resolves the Bun version from package.json so the runtime SOT stays in one @@ -89,7 +99,7 @@ jobs: RELEASED_VERSION: ${{ inputs.released-version }} run: | set -euo pipefail - bun scripts/bump-dev-version.ts "${RELEASED_VERSION}" package.json + bun scripts/bump-dev-version.ts "${RELEASED_VERSION}" dev-tree/package.json - name: Prove the chosen version is unused if: ${{ steps.decide.outputs.changed == 'true' }} @@ -98,10 +108,14 @@ jobs: # of the tag set, so it is settled here by the detector that already owns the # question. If this fails, no pull request is opened and the job goes red asking # for a human decision - which is the correct outcome, not a fallback. - run: bun test tests/release-version-line.test.ts + run: | + # Exercise the trusted detector against the candidate package metadata. + cp dev-tree/package.json package.json + bun test tests/release-version-line.test.ts - name: Open the bump pull request if: ${{ steps.decide.outputs.changed == 'true' }} + working-directory: dev-tree env: GH_TOKEN: ${{ github.token }} NEXT_VERSION: ${{ steps.decide.outputs.version }} @@ -153,7 +167,12 @@ jobs: git checkout -b "${branch}" git add package.json git commit -m "fix(release): move dev to ${NEXT_VERSION} after ${RELEASED_VERSION}" - git push origin "${branch}" + # Supply the write credential only to this trusted push invocation. In + # particular, never persist it in the dev checkout while dev-controlled + # files could execute. + auth_header="$(printf 'x-access-token:%s' "${GH_TOKEN}" | base64 -w0)" + git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${auth_header}" \ + push origin "${branch}" fi gh pr create \ diff --git a/tests/ci-workflows.test.ts b/tests/ci-workflows.test.ts index 8a70f4e675..44fe20ddfe 100644 --- a/tests/ci-workflows.test.ts +++ b/tests/ci-workflows.test.ts @@ -730,6 +730,23 @@ describe("GitHub Actions hardening", () => { expect(workflow).toContain("actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e"); expect(workflow).not.toMatch(/uses:\s+\S+@(?:v\d+|main|master)\b/); + // The post-release bump has write authority, but dev is a mutable integration + // branch rather than the audited release input. Executable automation must stay + // on the exact caller SHA, and checkout credentials must remain absent until the + // final trusted push invocation. + const bumpWorkflow = await readText(".github/workflows/dev-version-bump.yml"); + expect(bumpWorkflow).toContain("- name: Checkout trusted automation"); + expect(bumpWorkflow).toContain("ref: ${{ github.sha }}"); + expect(bumpWorkflow).toContain("- name: Checkout dev as data"); + expect(bumpWorkflow).toContain("path: dev-tree"); + expect(count(bumpWorkflow, "persist-credentials: false")).toBe(2); + expect(bumpWorkflow).toContain( + 'bun scripts/bump-dev-version.ts "${RELEASED_VERSION}" dev-tree/package.json', + ); + expect(bumpWorkflow).toContain("cp dev-tree/package.json package.json"); + expect(bumpWorkflow).toContain("working-directory: dev-tree"); + expect(bumpWorkflow).toContain('git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${auth_header}"'); + // Workflow-dispatch inputs must reach shell code via env, never by direct // interpolation into run: source (script-injection hardening). const runBlocks = workflow.split(/\n {6,}- name: /).filter(block => block.includes("run: |")); @@ -5261,4 +5278,3 @@ describe("gui exhaustive-deps suppression stays scoped and effective", () => { expect(models).not.toContain("react-doctor-disable-next-line"); }); }); -