provision-ci-release-token.sh mints write:repository only; add write:package so ward publish-kdl-write can push to the package registry #448

Closed
opened 2026-07-03 06:51:24 +00:00 by coilysiren · 2 comments
Owner

Problem

scripts/provision-ci-release-token.sh mints the CI_RELEASE_TOKEN PAT with write:repository scope only:

-X POST ".../api/v1/users/${FORGEJO_USER}/tokens" \
  -d "{\"name\":\"${TOKEN_NAME}\",\"scopes\":[\"write:repository\"]}"

That scope covers the Contents + Releases APIs (release-asset upload works), but not the Forgejo generic package registry (/api/packages/...), which needs write:package.

Impact

ward#501 added a publish-kdl-write CI job that PUTs the write-tier binary to the package registry using CI_RELEASE_TOKEN. It 401s on every release (ward run 799), so the ward-kdl-write package registry is empty and the broker's internal channel (the point of ward#455) has nothing in it. Tracked ward-side as ward#550.

Fix (one scope, this script)

  • Add write:package to the minted scope list: \"scopes\":[\"write:repository\",\"write:package\"] (Forgejo's write:package implies read and covers the job's DELETE-then-PUT).
  • Update the matching prose: the header comment ("scope write:repository"), the UI-mode comment ("scope repository Read+Write"), and the Minting token ... (scope write:repository) echo, so the script self-documents the added scope.
  • No change needed in the UI-mint path logic, but note in the comment that a UI-minted CI_RELEASE_PAT must now also carry package Read+Write.

After the code lands (operator action - not the engineer's)

Re-run the script (CI_RELEASE_PAT=<ui-token> or the API-mint mode) to rotate the token in SSM /forgejo/ci-release-token and the coilyco-flight-deck/CI_RELEASE_TOKEN org Actions secret with the new scope, then re-run the ward release workflow and confirm GET /api/v1/packages/coilyco-flight-deck?type=generic&q=ward-kdl-write lists both arch binaries.

  • ward#550 (the failing job + verify steps)
  • ward#501 (added the job), ward#455 (release-asset removal this survives)
## Problem `scripts/provision-ci-release-token.sh` mints the `CI_RELEASE_TOKEN` PAT with **`write:repository` scope only**: ``` -X POST ".../api/v1/users/${FORGEJO_USER}/tokens" \ -d "{\"name\":\"${TOKEN_NAME}\",\"scopes\":[\"write:repository\"]}" ``` That scope covers the Contents + Releases APIs (release-asset upload works), but **not** the Forgejo generic **package registry** (`/api/packages/...`), which needs `write:package`. ## Impact ward#501 added a `publish-kdl-write` CI job that PUTs the write-tier binary to the package registry using `CI_RELEASE_TOKEN`. It **401s** on every release (ward run 799), so the `ward-kdl-write` package registry is empty and the broker's internal channel (the point of ward#455) has nothing in it. Tracked ward-side as ward#550. ## Fix (one scope, this script) - Add `write:package` to the minted scope list: `\"scopes\":[\"write:repository\",\"write:package\"]` (Forgejo's `write:package` implies read and covers the job's DELETE-then-PUT). - Update the matching prose: the header comment ("scope write:repository"), the UI-mode comment ("scope repository Read+Write"), and the `Minting token ... (scope write:repository)` echo, so the script self-documents the added scope. - No change needed in the UI-mint path logic, but note in the comment that a UI-minted `CI_RELEASE_PAT` must now also carry package Read+Write. ## After the code lands (operator action - not the engineer's) Re-run the script (`CI_RELEASE_PAT=<ui-token>` or the API-mint mode) to rotate the token in SSM `/forgejo/ci-release-token` and the `coilyco-flight-deck/CI_RELEASE_TOKEN` org Actions secret with the new scope, then re-run the ward release workflow and confirm `GET /api/v1/packages/coilyco-flight-deck?type=generic&q=ward-kdl-write` lists both arch binaries. ## Related - ward#550 (the failing job + verify steps) - ward#501 (added the job), ward#455 (release-asset removal this survives)
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-infrastructure-448 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-03T07:03:07Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-infrastructure-448` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-03T07:03:07Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

WARD-OUTCOME: done - provision-ci-release-token.sh now mints CI_RELEASE_TOKEN with write:repository + write:package; landed on main, CI green.

Genuinely a one-scope change plus three prose spots, so the code side was quick and low-risk. The one thing that fought back was the commit gate, not the diff: the pylint pre-commit hook (always_run, uv run pylint) tried to download a managed CPython into the root-owned /opt/uv/python and died with a permission error, so my first commit was blocked by something that had nothing to do with my change. Pointing UV_PYTHON_INSTALL_DIR at a writable dir let uv fetch its own Python and the hook then passed at 10.00/10, identical to the CI lint job, so I did not have to reach for --no-verify. Worth flagging as a container-env rough edge if other agents hit the same wall.

Confidence is high on what actually landed: the scope array and all the self-documenting prose (header, UI-mode note, mint echo) now agree, and CI (CI / lint, TruffleHog) is green on the merge commit. The part I cannot verify from here is the payoff - the actual write:package grant only matters once the operator rotates the token in SSM /forgejo/ci-release-token and the org Actions secret, then re-runs the ward release and checks the ward-kdl-write package lists both arch binaries. That operator step is called out in the issue and is out of the engineer's hands. No follow-ups worth filing; the sibling provision-tap-bump-token.sh still mints write:repository only, but that token has no package-registry job, so it is correctly left alone.

WARD-OUTCOME: done - provision-ci-release-token.sh now mints CI_RELEASE_TOKEN with write:repository + write:package; landed on main, CI green. Genuinely a one-scope change plus three prose spots, so the code side was quick and low-risk. The one thing that fought back was the commit gate, not the diff: the `pylint` pre-commit hook (`always_run`, `uv run pylint`) tried to download a managed CPython into the root-owned `/opt/uv/python` and died with a permission error, so my first commit was blocked by something that had nothing to do with my change. Pointing `UV_PYTHON_INSTALL_DIR` at a writable dir let uv fetch its own Python and the hook then passed at 10.00/10, identical to the CI lint job, so I did not have to reach for `--no-verify`. Worth flagging as a container-env rough edge if other agents hit the same wall. Confidence is high on what actually landed: the scope array and all the self-documenting prose (header, UI-mode note, mint echo) now agree, and CI (`CI / lint`, `TruffleHog`) is green on the merge commit. The part I cannot verify from here is the payoff - the actual `write:package` grant only matters once the operator rotates the token in SSM `/forgejo/ci-release-token` and the org Actions secret, then re-runs the ward release and checks the `ward-kdl-write` package lists both arch binaries. That operator step is called out in the issue and is out of the engineer's hands. No follow-ups worth filing; the sibling provision-tap-bump-token.sh still mints write:repository only, but that token has no package-registry job, so it is correctly left alone.
Sign in to join this conversation.
No description provided.