rename: seven Forgejo service-account email addresses still on gitborg-*@gitborg.se #390

Stängd
öppnade 2026-08-05 21:07:10 +00:00 av supernaut · 1 kommentar
Ägare

All seven Forgejo service accounts still carry gitborg-*@gitborg.se email addresses. The
usernames moved to bitborg-* in ADR 0039 tranche 1; the addresses were deliberately left as
LEGACY-PINs and are the last gitborg strings on those accounts.

bitborg-renovate          gitborg-renovate@gitborg.se
bitborg-reconciler        gitborg-reconciler@gitborg.se
bitborg-webhook-admin     gitborg-webhook-admin@gitborg.se
bitborg-runner-controller gitborg-runner-controller@gitborg.se
bitborg-ci                gitborg-ci@gitborg.se
bitborg-bot               gitborg-bot@gitborg.se
bitborg-token-audit       gitborg-token-audit@gitborg.se

Plus one derived consumer: renovate_git_author in roles/renovate/defaults/main.yml is
Bitborg Renovate <gitborg-renovate@gitborg.se>, which appears as the commit author on every
Renovate PR
— the most visible of the set.

⚠️ The ordering hazard — this is not a declaration edit

create-user.yml is create-only: it never reconciles an existing account's email. So editing
forgejo_service_accounts on its own does not change the server — it silently drifts the
declaration away from live state, and changed=0 would keep reporting convergence while the two
disagree. This is the same trap the username rename had to route around, and the note beside
forgejo_service_accounts in group_vars/all/vars.yml already records it.

So the order must be: change each address on the live server first (admin API), then update
the declaration to match — the reverse of the usual flow.

❓ Decide the target domain before touching anything

The pinned note says these "flip with the mail domain, not with the account name", which is what made
them look like §5 work. But they are on the apex @gitborg.se, not @mail.gitborg.se — so §5
(the sending domain, now email.bitborg.se) did not actually govern them. The apex moved on
2026-08-04 in §4b, which is arguably when these became actionable.

no-reply@email.bitborg.se is a sending identity and is wrong for an account's own address, since
these are the addresses Forgejo would send to. Most likely target is bitborg-*@bitborg.se.

Open question worth answering first: do these need to be deliverable at all? Forgejo requires an
email per account and enforces uniqueness, but bot accounts may never need to receive. If any of them
does (password reset, notification), the mailbox has to exist — §4b moved three real mailboxes, and
these seven are not among them.

Acceptance

  • All seven addresses moved on the live server, and forgejo_service_accounts matches live state
    afterwards — assert the match against the API, not against the template.
  • renovate_git_author moved with them; confirm on a freshly opened Renovate PR, since the author
    is baked in at commit time.
  • No account lost its PAT (they key on user id, not login — but verify rather than assume; the token
    audit bot and the CI token would both fail loudly and late).
  • Both hosts converge at changed=0, and the LEGACY-PIN markers are gone from those lines.
All seven Forgejo service accounts still carry `gitborg-*@gitborg.se` email addresses. The **usernames** moved to `bitborg-*` in ADR 0039 tranche 1; the addresses were deliberately left as `LEGACY-PIN`s and are the last `gitborg` strings on those accounts. ```text bitborg-renovate gitborg-renovate@gitborg.se bitborg-reconciler gitborg-reconciler@gitborg.se bitborg-webhook-admin gitborg-webhook-admin@gitborg.se bitborg-runner-controller gitborg-runner-controller@gitborg.se bitborg-ci gitborg-ci@gitborg.se bitborg-bot gitborg-bot@gitborg.se bitborg-token-audit gitborg-token-audit@gitborg.se ``` Plus one derived consumer: `renovate_git_author` in `roles/renovate/defaults/main.yml` is `Bitborg Renovate <gitborg-renovate@gitborg.se>`, which appears as the **commit author on every Renovate PR** — the most visible of the set. ## ⚠️ The ordering hazard — this is not a declaration edit `create-user.yml` is **create-only**: it never reconciles an existing account's email. So editing `forgejo_service_accounts` on its own does **not** change the server — it silently drifts the declaration away from live state, and `changed=0` would keep reporting convergence while the two disagree. This is the same trap the username rename had to route around, and the note beside `forgejo_service_accounts` in `group_vars/all/vars.yml` already records it. So the order must be: **change each address on the live server first** (admin API), **then** update the declaration to match — the reverse of the usual flow. ## ❓ Decide the target domain before touching anything The pinned note says these "flip with the mail domain, not with the account name", which is what made them look like §5 work. But they are on the **apex** `@gitborg.se`, not `@mail.gitborg.se` — so §5 (the *sending* domain, now `email.bitborg.se`) did not actually govern them. The apex moved on 2026-08-04 in §4b, which is arguably when these became actionable. `no-reply@email.bitborg.se` is a *sending* identity and is wrong for an account's own address, since these are the addresses Forgejo would send **to**. Most likely target is `bitborg-*@bitborg.se`. Open question worth answering first: **do these need to be deliverable at all?** Forgejo requires an email per account and enforces uniqueness, but bot accounts may never need to receive. If any of them does (password reset, notification), the mailbox has to exist — §4b moved three real mailboxes, and these seven are not among them. ## Acceptance - All seven addresses moved on the live server, and `forgejo_service_accounts` matches live state afterwards — assert the match against the API, not against the template. - `renovate_git_author` moved with them; confirm on a **freshly opened** Renovate PR, since the author is baked in at commit time. - No account lost its PAT (they key on user id, not login — but verify rather than assume; the token audit bot and the CI token would both fail loudly and late). - Both hosts converge at `changed=0`, and the `LEGACY-PIN` markers are gone from those lines.
Upphovsperson
Ägare

Done 2026-08-10 — server first, then the declaration (infra #416).

What changed

All seven addresses → bitborg-*@noreply.git.bitborg.se, plus renovate_git_author.

The domain question, answered

The description asked whether these need to be deliverable at all. They don't — none of the seven has a mailbox, and §4b moved only three real ones, none of them these. So bitborg-*@bitborg.se would have declared seven deliverable-looking addresses that bounce, carrying today's latent problem onto the new domain.

Forgejo's own noreply domain is the honest answer: explicitly non-deliverable, unique per account, and already the convention the org account uses (bitborg@noreply.git.bitborg.se).

One risk checked rather than assumed: Forgejo reserves that domain for the generated <login>@<noreply> pseudo-address, so it might have rejected it as a real user email. 16.0.1 accepts it.

changed=0 is not the evidence, and can't be

create-user.yml cannot reconcile an email, so it reports converged whatever the declaration says — the exact trap this issue described. The assertion is against the API: all seven re-read with independent calls after the write.

No account lost a PAT. 10 tokens across the seven, counts unchanged before and after:

bitborg-renovate 1→1   bitborg-reconciler 2→2   bitborg-webhook-admin 1→1
bitborg-runner-controller 1→1   bitborg-ci 2→2   bitborg-bot 2→2
bitborg-token-audit 1→1

Two API details worth keeping

  • PATCH /admin/users/{u} treats login_name and source_id as a pair — sending login_name with an email is a 422 ("source_id and login_name must be specified together"). 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. A PAT-survival check built on the wrong endpoint returns nothing on both sides and passes vacuously.

Required a temporary write:admin PAT; no standing token has it, deliberately (ADR 0024 — webhook-admin and token-audit are both read:admin, vault_forgejo_admin_token was removed). Minted, used, revoked, never vaulted.

One acceptance criterion still pending

confirm renovate_git_author on a freshly opened Renovate PR

The author is baked in at commit time and renovate_git_author only reaches the host on an apply, which has not run yet. Check the first Renovate PR after the next apply — the timer is Mondays 00:30 UTC. Reopen if the author line still reads gitborg-renovate@gitborg.se.

Found while verifying, out of scope

Two accounts not in forgejo_service_accounts and not sign-up drill accounts (those are drill-signup-<ts>), still carrying the old brand in both username and address:

gitborg-test-1    test1-alt@gitborg.se
gitborg-test-2    test2@gitborg.se

Left untouched — deleting accounts is destructive and outside this issue. Note they also occupy two gitborg-* names, which interacts with the reserved-username reasoning in §9.

Done 2026-08-10 — server first, then the declaration (infra #416). ## What changed All seven addresses → `bitborg-*@noreply.git.bitborg.se`, plus `renovate_git_author`. ## The domain question, answered The description asked whether these need to be deliverable at all. **They don't** — none of the seven has a mailbox, and §4b moved only three real ones, none of them these. So `bitborg-*@bitborg.se` would have declared seven deliverable-looking addresses that bounce, carrying today's latent problem onto the new domain. Forgejo's own noreply domain is the honest answer: explicitly non-deliverable, unique per account, and already the convention the **org account** uses (`bitborg@noreply.git.bitborg.se`). One risk checked rather than assumed: Forgejo reserves that domain for the generated `<login>@<noreply>` pseudo-address, so it might have rejected it as a real user email. **16.0.1 accepts it.** ## `changed=0` is not the evidence, and can't be `create-user.yml` cannot reconcile an email, so it reports converged whatever the declaration says — the exact trap this issue described. The assertion is against the **API**: all seven re-read with independent calls after the write. **No account lost a PAT.** 10 tokens across the seven, counts unchanged before and after: ``` bitborg-renovate 1→1 bitborg-reconciler 2→2 bitborg-webhook-admin 1→1 bitborg-runner-controller 1→1 bitborg-ci 2→2 bitborg-bot 2→2 bitborg-token-audit 1→1 ``` ## Two API details worth keeping - `PATCH /admin/users/{u}` treats `login_name` and `source_id` as a **pair** — sending `login_name` with an email is a 422 (`"source_id and login_name must be specified together"`). 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. A PAT-survival check built on the wrong endpoint returns nothing on both sides and passes vacuously. Required a temporary `write:admin` PAT; no standing token has it, deliberately (ADR 0024 — `webhook-admin` and `token-audit` are both read:admin, `vault_forgejo_admin_token` was removed). Minted, used, revoked, never vaulted. ## One acceptance criterion still pending > confirm `renovate_git_author` on a **freshly opened** Renovate PR The author is baked in at commit time and `renovate_git_author` only reaches the host on an **apply**, which has not run yet. Check the first Renovate PR after the next apply — the timer is Mondays 00:30 **UTC**. Reopen if the author line still reads `gitborg-renovate@gitborg.se`. ## Found while verifying, out of scope Two accounts not in `forgejo_service_accounts` and not sign-up drill accounts (those are `drill-signup-<ts>`), still carrying the old brand in both username and address: ``` gitborg-test-1 test1-alt@gitborg.se gitborg-test-2 test2@gitborg.se ``` Left untouched — deleting accounts is destructive and outside this issue. Note they also occupy two `gitborg-*` names, which interacts with the reserved-username reasoning in §9.
Logga in för att delta i denna konversation.
Ingen milstolpe
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#390
Ingen beskrivning angiven.