From 6618de9c9f6964048462601d5ed68753108a6742 Mon Sep 17 00:00:00 2001 From: Felix Faerber Date: Sun, 5 Jul 2026 15:01:10 +0300 Subject: [PATCH] ops: .env is the token source of truth (not tokens.md) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every token value must be written to gitea/secrets/.env (the master, mirrored to org Actions secrets) AND the Actions secret, kept in sync, removed from both on delete. Drop the tokens.md instruction — the @ops test dutifully re-created tokens.md because the skill still referenced it. --- .gitea/workflows/scripts/skill-gitea-admin.sh | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/scripts/skill-gitea-admin.sh b/.gitea/workflows/scripts/skill-gitea-admin.sh index ab40e24..77d22b5 100644 --- a/.gitea/workflows/scripts/skill-gitea-admin.sh +++ b/.gitea/workflows/scripts/skill-gitea-admin.sh @@ -59,20 +59,24 @@ curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: applic # 2) mint a scoped token AS that user (pick the narrowest scopes needed) tok=$(curl -sS -u "inter:$PW" -H "Content-Type: application/json" -X POST "$API/users/inter/tokens" \ -d '{"name":"inter","scopes":["read:repository","write:issue"]}' | jq -r '.sha1') -# 3) store it as a secret (org / repo / user level) — never print $tok +# 3) store the value in BOTH places (see "Secret storage" below) — never print $tok curl -sS -X PUT -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \ "$API/orgs/gitea/actions/secrets/TOKEN_INTER" -d "$(jq -nc --arg d "$tok" '{data:$d}')" ``` Token **scopes** are groups of `read:`/`write:` on: `repository`, `issue`, `organization`, `user`, `package`, `notification`, `misc`, and (only for a privileged token) `admin`. -## Token inventory — record everything in `gitea/secrets` -The private repo **`gitea/secrets`** (readable only by @ffaerber and @ops) is the source of truth for -tokens. Whenever you mint, rotate, or re-scope a token, append/update a row in its `tokens.md` via the -contents API (`GET` the file for its `sha`, then `PUT` the updated base64 content with that `sha`): -`| | | | | |`. -Storing the live value in the matching Actions secret is what workflows use; the `gitea/secrets` row -is the human-readable inventory. Never paste a token value into any issue/PR/comment/log. +## Secret storage — `gitea/secrets/.env` is the SOURCE OF TRUTH +Every token/secret value MUST live in **`gitea/secrets/.env`** (private, readable only by @ffaerber and +@ops) as a `KEY=value` line. That file is the master; the workflows only get a secret because `.env` is +mirrored into the org Actions secrets. So whenever you mint, rotate, or re-scope a token you MUST do +BOTH, in sync: + 1. **`.env`**: `GET /repos/gitea/secrets/contents/.env` for its `sha`, add or replace the `KEY=value` + line, then `PUT` the updated base64 content with that `sha`. + 2. **Actions secret**: `PUT /orgs/gitea/actions/secrets/{KEY}` with the same value (what runs use). +When you DELETE a token, remove it from BOTH. Keep `gitea/secrets/README.md` (the table describing what +each KEY is) up to date. Do NOT use `tokens.md` — the values live in `.env`. NEVER paste a token value +into any issue/PR/comment/log; it only ever goes into `.env` and the Actions secret. ## Change a user's token scope (the "update my token" flow) Tokens are immutable — you can't edit scopes. Re-mint: delete the old token and create a new one, -- 2.54.0