agentbbs/internal
Anthony Ettinger 2fb7a52233 fix(mail): unbreak join@ registration when the Mailu cert lapses
Registration has been dead since 2026-09-13. `ssh join@bbs.profullstack.com`
creates the account, then fails at the confirmation step with "couldn't email
the code" and disconnects, so nobody can finish signing up.

Cause: Caddy owns ACME for mail.profullstack.com and renewed on 2026-08-14
(valid to Nov 12), but Mailu went on serving the certificate it loaded at
container start (Jun 15 -> Sep 13). When that lapsed, the STARTTLS handshake
from internal/mail started failing verification and every transactional send
died with it -- confirmation codes, signup notifications, credential mail.
Reproduced against production; 25/465/993 all still present the expired cert
while :443 serves the renewed one.

Three things let a single stale certificate take registration down:

- setup.sh installed the refresher and enabled its *timer*, but never ran it.
  `systemctl enable --now <timer>` starts the timer, not the service, so a
  redeploy left a stale cert in place (and did nothing at all if the timer was
  never scheduled). The news and IRC sections already run theirs at provision
  time; the Mailu section now does too, which is what repairs the live host.

- refresh-certs.sh only compared files, so a copy whose reload silently failed
  left a fresh cert on disk and an expiring one on the wire -- invisible. It now
  reads back what the relay actually serves, forces a reload when that disagrees
  with /certs, refuses to copy a source cert that is itself expired, and no
  longer swallows the `docker compose restart` failure. It restarts `front`
  alone, the only container that mounts ./certs.

- internal/mail verified the relay's certificate even on loopback, where there
  is nothing to intercept. It now skips verification for a loopback relay (the
  reasoning docs/mail.md already applies to the plaintext Dovecot hand-off) and
  gains AGENTBBS_SMTP_SERVERNAME, mirroring AGENTBBS_MAIL_SMTP_SERVERNAME, so
  the documented 127.0.0.1:25 config can verify against the mail host instead of
  an IP literal. A non-loopback relay is still verified. Errors are wrapped with
  the address and the failing stage so the next failure is one journal line to
  diagnose rather than nine days of silence.

Tests cover the envelope, the unreachable-relay message, and both halves of the
TLS decision: a loopback relay with an expired cert delivers, a non-loopback one
with the same cert is refused.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 14:34:39 +00:00
..
admin members: show joined date in admin + public lists; 'last active: X ago' 2026-07-01 02:40:24 +00:00
ascii Video calls (PairUX→ASCII), agent@ chat, and finger routes 2026-06-11 11:43:38 +00:00
auth feat(gopher): serve BBS content over Gopher + SSH-authenticated "hedgehog" (#83) 2026-07-07 05:39:35 -07:00
brand Use the Profullstack </> ASCII logo as the BBS banner 2026-06-14 16:46:59 +00:00
calls Video calls (PairUX→ASCII), agent@ chat, and finger routes 2026-06-11 11:43:38 +00:00
chat Video calls (PairUX→ASCII), agent@ chat, and finger routes 2026-06-11 11:43:38 +00:00
files Serve the OpenAccess descriptor at /.well-known/openaccess.json (#127) 2026-09-12 12:26:25 -07:00
forgejo feat(passwd): self-service password reset across git, mail & chat (#59) 2026-06-27 03:46:23 -07:00
forwardemail Autonomous deploy + free-pod/Premium-email membership 2026-06-14 07:58:51 +00:00
games fix(games): reject duplicate queue entries (#117) 2026-08-12 21:20:18 -07:00
gopher fix(gopher): serve public files from SFTP storage (#115) 2026-08-12 19:20:06 -07:00
hub Fix/pod public html bind mount (#30) 2026-06-15 08:06:32 -07:00
ircpass fix(passwd): also reset The Lounge web-login password (#61) 2026-06-27 09:40:28 -07:00
mail fix(mail): unbreak join@ registration when the Mailu cert lapses 2026-09-22 14:34:39 +00:00
mailbox fix(mailbox): write messages before IMAP append wait (#113) 2026-08-11 17:44:33 -07:00
mailclients Add himalaya + meli mail clients and Shedding Snake arcade game (#88) 2026-07-10 02:30:12 -07:00
mailu Feat/mail all members (#55) 2026-06-23 03:38:31 -07:00
motd Wire shared MOTD into BBS hub and IRC 2026-06-25 11:51:06 +00:00
news fix(news): stop IHAVE when duplicate lookup fails (#89) 2026-07-12 00:43:24 -07:00
payments Rebrand paid tier to $99 Founding Lifetime Member 2026-06-14 12:46:23 +00:00
plugin fix(arcade): give ncurses games a TERM so they launch 2026-06-18 12:01:26 +00:00
pods feat(pods): SSH agent forwarding → git push from the pod with your key 2026-06-23 09:16:29 +00:00
qryptinvite fix(qryptinvite): validate quota and TTL env values (#93) 2026-07-16 19:01:41 -07:00
sandbox AgentBBS: M0 core hub, M1 arcade, pods with CoinPay membership 2026-06-11 11:08:17 +00:00
sites fix(sites): roll back failed domain claims (#119) 2026-08-13 02:34:30 -07:00
source fix: block shared/reserved IP ranges in SSRF guard (#47) 2026-06-22 05:23:15 -07:00
store fix(sites): roll back failed domain claims (#119) 2026-08-13 02:34:30 -07:00
tor tor: premium tor-url / tor-irc / tor routes over Tor 2026-06-14 10:54:21 +00:00
ui Fix/pod public html bind mount (#30) 2026-06-15 08:06:32 -07:00