refactor(forgejo): point the service-account addresses at the noreply domain #416

Sammanfogat
supernaut sammanfogade 1 incheckning från feat/rename-service-account-addresses in i main 2026-08-10 19:12:37 +00:00
Ägare

ADR 0039, issues #390 and #393. The server was changed first; this makes the declaration match.

create-user.yml is create-only and never reconciles an existing account's email, so editing these lines alone would not have changed the server — it would have drifted the declaration away from live state while changed=0 kept reporting convergence.

#390 — seven addresses

gitborg-*@gitborg.se → bitborg-*@noreply.git.bitborg.se, plus renovate_git_author, the commit author on every Renovate PR and the most visible of the set.

Forgejo's own noreply domain rather than the apex: none of these seven has a mailbox and none needs to receive, so @bitborg.se would have declared seven deliverable addresses that bounce. It's also the convention the org account already uses (bitborg@noreply.git.bitborg.se). Forgejo 16.0.1 accepts it as a user email — checked, not assumed.

#393 — three website fields, not two

Object From To
org bitborg https://www.gitborg.se/ https://www.bitborg.se/
bitborg-infra https://git.gitborg.se/ https://git.bitborg.se/
bitborg-web https://www.gitborg.se/ https://www.bitborg.se/

The issue listed the first two and flagged its own list as possibly incomplete — bitborg-web was a third. The other five repos, including all three private ones, have an empty website, so nothing was hiding where fj repo view can't show the field.

No file changes for #393: it's pure server metadata, which is exactly why the repo-wide content sweeps never saw it.

⚠️ changed=0 is NOT the evidence here

create-user.yml cannot reconcile an email, so it reports converged whatever these lines say. The assertion is against the API: all seven addresses and all three websites re-read with independent calls after the write, and every PAT survived — 10 tokens across the seven accounts, counts unchanged before and after (they key on the user id, not the login or the address).

Done with a temporary credential, by necessity

No standing token can do this, deliberately: ADR 0024 keeps every admin token read-only (webhook-admin and token-audit are both read:admin; vault_forgejo_admin_token was removed). A short-lived write:admin PAT was minted, used, deleted locally and revoked. Never vaulted, so the least-privilege model is unchanged.

Two API details cost a round trip, recorded so nobody repeats them:

  • PATCH /admin/users/{u} treats login_name and source_id as a pair — sending login_name with an email is a 422. Send email alone.
  • GET /users/{u}/tokens needs basic auth and 401s with a PAT. The working endpoint is GET /admin/users/{u}/tokens, the one token-audit already uses. My first PAT-survival check used the wrong one and would have compared ? to ? and passed vacuously.

LEGACY-PIN count in vars.yml drops 21 → 14. ansible-lint 0/0 across 194 files at production.

ADR 0039, issues #390 and #393. **The server was changed first; this makes the declaration match.** `create-user.yml` is create-only and never reconciles an existing account's email, so editing these lines alone would not have changed the server — it would have drifted the declaration away from live state while `changed=0` kept reporting convergence. ## #390 — seven addresses `gitborg-*@gitborg.se` → `bitborg-*@noreply.git.bitborg.se`, plus `renovate_git_author`, the commit author on every Renovate PR and the most visible of the set. Forgejo's own noreply domain rather than the apex: **none of these seven has a mailbox and none needs to receive**, so `@bitborg.se` would have declared seven deliverable addresses that bounce. It's also the convention the org account already uses (`bitborg@noreply.git.bitborg.se`). Forgejo 16.0.1 accepts it as a user email — checked, not assumed. ## #393 — three website fields, not two | Object | From | To | | --- | --- | --- | | org `bitborg` | `https://www.gitborg.se/` | `https://www.bitborg.se/` | | `bitborg-infra` | `https://git.gitborg.se/` | `https://git.bitborg.se/` | | `bitborg-web` | `https://www.gitborg.se/` | `https://www.bitborg.se/` | The issue listed the first two and flagged its own list as possibly incomplete — `bitborg-web` was a third. The other five repos, **including all three private ones**, have an empty `website`, so nothing was hiding where `fj repo view` can't show the field. No file changes for #393: it's pure server metadata, which is exactly why the repo-wide content sweeps never saw it. ## ⚠️ `changed=0` is NOT the evidence here `create-user.yml` cannot reconcile an email, so it reports converged whatever these lines say. The assertion is against the **API**: all seven addresses and all three websites re-read with independent calls after the write, and every PAT survived — **10 tokens across the seven accounts, counts unchanged** before and after (they key on the user id, not the login or the address). ## Done with a temporary credential, by necessity No standing token can do this, deliberately: ADR 0024 keeps every admin token read-only (`webhook-admin` and `token-audit` are both read:admin; `vault_forgejo_admin_token` was removed). A short-lived write:admin PAT was minted, used, deleted locally and revoked. Never vaulted, so the least-privilege model is unchanged. Two API details cost a round trip, recorded so nobody repeats them: - `PATCH /admin/users/{u}` treats `login_name` and `source_id` as a **pair** — sending `login_name` with an email is a 422. Send `email` alone. - `GET /users/{u}/tokens` needs **basic auth** and 401s with a PAT. The working endpoint is `GET /admin/users/{u}/tokens`, the one `token-audit` already uses. My first PAT-survival check used the wrong one and would have compared `?` to `?` and passed vacuously. `LEGACY-PIN` count in `vars.yml` drops 21 → 14. `ansible-lint` 0/0 across 194 files at `production`.
supernaut lade till 1 incheckning 2026-08-10 19:06:17 +00:00
refactor(forgejo): point the service-account addresses at the noreply domain
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m39s
5b682b6a65
ADR 0039, issues #390 and #393. The server was changed FIRST; this commit
makes the declaration match. `create-user.yml` is create-only and never
reconciles an existing account's email, so editing these lines alone
would not have changed anything on the server — it would have drifted the
declaration away from live state while `changed=0` kept reporting
convergence.

## #390 — seven addresses

`gitborg-*@gitborg.se` -> `bitborg-*@noreply.git.bitborg.se`, plus
`renovate_git_author`, which is the commit author on every Renovate PR
and the most visible of the set.

Forgejo's own noreply domain rather than the apex, because none of these
seven has a mailbox and none needs to receive: `@bitborg.se` would have
declared seven deliverable addresses that bounce. It is also the
convention the org account already uses
(`bitborg@noreply.git.bitborg.se`). Forgejo 16.0.1 accepts it as a user
email — checked, not assumed.

## #393 — three website fields, not two

- org `bitborg`      https://www.gitborg.se/ -> https://www.bitborg.se/
- `bitborg-infra`    https://git.gitborg.se/ -> https://git.bitborg.se/
- `bitborg-web`      https://www.gitborg.se/ -> https://www.bitborg.se/

The issue listed the first two and flagged its own list as possibly
incomplete; `bitborg-web` was a third. The other five repos, including
all three private ones, have an empty `website` — so nothing was hiding
where `fj repo view` could not show the field. No file changes here: this
is pure server metadata, which is why the repo-wide content sweeps never
saw it.

## `changed=0` is NOT the evidence for this change

`create-user.yml` cannot reconcile an email, so it reports converged
whatever these lines say. The assertion is against the **API**: all seven
addresses and all three websites were re-read with independent calls
after the write, and every PAT survived — 10 tokens across the seven
accounts, counts unchanged before and after (they key on the user id, not
the login or the address).

## Done with a temporary credential, by necessity

No standing token can do this and that is deliberate: ADR 0024 keeps
every admin token read-only (`webhook-admin` and `token-audit` are both
read:admin; `vault_forgejo_admin_token` was removed). A short-lived
write:admin PAT was minted, used, deleted locally and revoked. It was
never vaulted, so the least-privilege model is unchanged.

Two payload details cost a round trip and are recorded so the next person
does not repeat them: `PATCH /admin/users/{u}` treats `login_name` and
`source_id` as a PAIR, so sending `login_name` with an email is a 422 —
send `email` alone. And `GET /users/{u}/tokens` needs basic auth and 401s
with a PAT; the working endpoint is `GET /admin/users/{u}/tokens`, the
one `token-audit` already uses.
supernaut sammanfogade incheckning a6abe260d6 till main 2026-08-10 19:12:37 +00:00
supernaut tog bort grenen feat/rename-service-account-addresses 2026-08-10 19:12:37 +00:00
Logga in för att delta i denna konversation.
Inga granskare
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-infra!416
Ingen beskrivning angiven.