Skip to content

feat(passwd): self-service password reset across git, mail & chat#59

Merged
ralyodio merged 1 commit into
mainfrom
feat/passwd-reset-all-services
Jun 27, 2026
Merged

feat(passwd): self-service password reset across git, mail & chat#59
ralyodio merged 1 commit into
mainfrom
feat/passwd-reset-all-services

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Summary

Adds a key-gated ssh passwd@bbs.profullstack.com route (alias password@) that lets a member set one new password across every service that has its own credential, in a single session:

Service How it's set
git (Forgejo) new forgejo.SetPassword — ensures the account, PATCHes the password, clears must_change_password
mail (Mailu webmail) existing mailu.SetPassword
chat (IRC/Ergo + The Lounge) new internal/ircpass package

Because the route authenticates by the member's registered SSH key, it also serves as the forgot-password path — no old password required. BBS/SSH login and git push are unaffected (those always use the key, not a password).

The chat privilege bridge

The BBS process runs as the unprivileged agentbbs service user, but the Ergo password store (/var/lib/ergo/irc-passwd, ergo:ergo 0600) and The Lounge user files are root-owned. internal/ircpass bridges this by shelling out to scripts/set-irc-password.sh through a narrow sudoers rule (setup.sh installs the script to /usr/local/sbin/agentbbs-set-irc-password + /etc/sudoers.d/agentbbs-ircpass, validated with visudo).

The new password travels on stdin (a new set-irc-password.sh <member> - form), so it never appears in the process table or sudo's command log.

UX & safety

  • Masked entry typed twice (readSecret); no-PTY/piped input reads stdin; empty input generates a strong password and shows it once.
  • Each service leg is independent and best-effort — a per-service ✓/✗ summary is shown.
  • A confirmation email is sent on success that never contains the password.

Tests

  • internal/ircpass — stdin contract (password on stdin, - in argv), member/password rejection, unconfigured/failure paths.
  • internal/forgejoSetPassword patches the chosen password and clears must_change; errors when the account is missing.
  • internal/authIsPasswdName + name reservation.

go build ./..., go vet ./..., gofmt -l, and go test ./... all green (go 1.26.4). bash -n setup.sh clean; the Python helper compiles and its stdin path works.

Docs

  • docs/credentials.md — new passwd@ section + env table (AGENTBBS_SET_IRC_PASSWD, AGENTBBS_SET_IRC_SUDO).
  • docs/irc.md — cross-reference to the self-service flow.

Closes the previously-noted gap where new members got no IRC password auto-provisioned.

🤖 Generated with Claude Code

Add a key-gated `ssh passwd@host` route (alias `password@`) that sets ONE
member-chosen password across every service with its own credential:

  - git  (Forgejo)        new forgejo.SetPassword (PATCH /admin/users, clears
                          must_change; EnsureUser first so the account exists)
  - mail (Mailu webmail)  existing mailu.SetPassword
  - chat (IRC/Ergo + The Lounge)  new internal/ircpass package

Because the route authenticates by the member's registered SSH key, it also
serves as the forgot-password path — no old password required.

The BBS runs as a non-root service user, but the Ergo password store and The
Lounge user files are root-owned. internal/ircpass bridges this by shelling out
to scripts/set-irc-password.sh through a narrow sudoers rule (installed by
setup.sh). The new password travels on stdin (a new `set-irc-password.sh
<member> -` form), so it never appears in the process table or sudo's log.

UX: masked entry typed twice (readSecret); no-PTY reads stdin; empty input
generates a strong password and shows it once. Each service leg is independent
and best-effort with a per-service ✓/✗ summary, plus a confirmation email that
never contains the password.

Tests: ircpass (stdin contract + member/password rejection), forgejo.SetPassword,
auth IsPasswdName + reservation. Docs: credentials.md (passwd@ section) + irc.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio ralyodio merged commit 54da317 into main Jun 27, 2026
5 checks passed
@ralyodio ralyodio deleted the feat/passwd-reset-all-services branch June 27, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant