email: the From address is duplicated across two repos with nothing keeping them in sync #113
Etiketter
Inga etiketter
area/backups
area/ci
area/control-panel
area/identity
area/infra
area/observability
area/payments
area/security
area/storage
area/web
blocked
needs-info
needs-triage
ready-for-implementation
type
bug
type
chore
type
docs
type
epic
type
feature
type
task
wontfix
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Inget förfallodatum satt.
Beroenden
Inga beroenden satta
Referens
bitborg/bitborg-web#113
Läser in…
Hänvisa till i nytt ärende
Ingen beskrivning angiven.
Ta bort grenen "%!s()"
Borttagning av en gren är permanent. Även om den borttagna grenen kan fortsätta existera en kort tid innan den faktiskt tas bort, kan det INTE ångras i de flesta fall. Vill du fortsätta?
The From address for outbound mail is defined in two repositories with nothing asserting they
agree:
bitborg-web—EMAIL_FROMinsrc/lib/email.ts, a hardcoded constant, deliberately notenv-configurable ("an env var here could send as an unverified domain").
bitborg-infra—forgejo_mailer_frominansible/group_vars/all/vars.yml, plusalerts@senders in the monitoring roles, plus a comment inroles/web/templates/bitborg-web.container.j2that describes the portal's hardcoded value.This already broke once
On 2026-07-31 the sending domain moved from
email.gitborg.setomail.gitborg.se. Infra wasupdated; the portal was not. The infra template comment was even updated to say
"From is fixed to no-reply@mail.gitborg.se in app code" while the app code still read
email.gitborg.se— a comment asserting a fact about another repo, with no mechanism to check it.The failure would have been near-silent and delivery-shaped: the portal keeps sending, Sweego
either rejects the unverified sending domain or the mail fails DKIM alignment. The affected path
is the sign-up credential-reset email, so sign-ups complete but the user never receives the link.
Nothing in CI or at boot would have caught it. Fixed in the commit that filed this issue; the
coupling remains.
Options
by infra as env (e.g.
EMAIL_FROM_ALLOWED_DOMAINS). Refuse to start, or refuse to send, on amismatch. Preserves the "not configurable" property while making drift loud.
EMAIL_FROMfrom infra as the single source of truth,validated at boot against a compiled-in allowlist so a typo cannot send as an arbitrary domain.
Removes the duplication rather than detecting it.
forgejo_mailer_fromand this constant and failsif the domains differ. Cheapest, but cross-repo CI coupling is awkward and it only runs in CI.
Option 1 is probably the best trade: it keeps the security property that motivated hardcoding,
needs no cross-repo CI, and converts a silent delivery failure into a loud startup failure.
Whatever is chosen, the DNS facts belong in the check's error message — the sending domain needs a
Sweego DKIM delegation (
sweego1._domainkey.<domain>) to be verified, so "domain not in allowlist"should hint at that.
Done when
Changing the sending domain in one repo and not the other causes a visible, immediate failure
rather than undelivered mail.