Skip to content

feat(messaging): group & broadcast messages + email-all#60

Merged
ralyodio merged 1 commit into
mainfrom
feat/group-broadcast-messaging
Jun 27, 2026
Merged

feat(messaging): group & broadcast messages + email-all#60
ralyodio merged 1 commit into
mainfrom
feat/group-broadcast-messaging

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Summary

Lets a member message a group or everyone (not just one member), and gives the operator an email-all announcement. Two delivery channels, kept cleanly separate so an ordinary group message never fans out to email:

  • BBS inbox (any member) — direct, group, or broadcast.
  • Email (operator, explicit) — agentbbs broadcast.

Inbox messaging — open to any member

msg@ route now accepts a recipient spec:

ssh msg@host bob hi              # one member (unchanged)
ssh msg@host alice,bob,carol hi  # a group (comma-separated)
ssh msg@host all hi              # broadcast to everyone (also: *, everyone, @all)
echo note | ssh msg@host all     # body on stdin

resolveRecipients validates names, excludes the sender, dedupes, reports unknown names, and skips banned accounts on broadcast.

Members hub TUI gains multi-select:

Key Action
space select / deselect the member under the cursor
a select all (again to clear)
m message the selected group (else the member under the cursor)

Selected rows show [x]; the composer header names the audience (e.g. 3 members); the selection clears after a successful send.

All group/broadcast inbox writes happen in one transaction via the new store.SendMessageMulti (dedupes recipients, skips empties, returns the count written).

Email broadcast — agentbbs broadcast (operator)

The explicit "mail all users" action — an operator command (DB + SMTP env on the host), preview by default like notify-creds:

agentbbs broadcast "Upgrading at 0200 UTC."          # preview
agentbbs broadcast --send "Heads up: downtime"       # inbox + email to all
agentbbs broadcast --send --no-email "BBS-only"      # one channel
agentbbs broadcast --send --no-inbox --subject "Outage" "..."

Inbox reaches every non-banned member; email reaches only verified addresses and refuses --send without SMTP (use --no-email). Per-channel delivered/failed summary; non-zero exit on email failure.

Permissions

Per the requested design: any member can broadcast to all inboxes (selected or all). The email blast is the separate, explicit agentbbs broadcast (operator-run). If you'd like members to trigger email-all from inside the BBS too, that's a small follow-up — say the word.

Tests

  • store.SendMessageMulti — multi-delivery, dedupe, empty list.
  • resolveRecipients — comma list (lowercase/dedupe/sender-exclude), unknown reporting, all/*/everyone/@all tokens, banned + sender exclusion.
  • Members TUI — space toggle, select-all/clear, group compose + recipient label.

go build ./..., go vet ./..., gofmt -l, go test ./... all green (go 1.26.4).

Docs

docs/messaging.md — direct/group/broadcast + the broadcast CLI.

🤖 Generated with Claude Code

Members can now message a group or everyone, and the operator can announce to
the whole membership by email.

Inbox channel (any member):
  - msg@ recipient spec accepts a comma list (alice,bob,carol) or all/*/everyone
    to broadcast: `ssh msg@host alice,bob hi`, `ssh msg@host all hi`.
  - Members hub TUI gains multi-select: space toggles, `a` selects all, `m`
    messages the selected group (header names the audience); selection clears
    after send.
  - store.SendMessageMulti delivers one body to many inboxes in a single
    transaction (dedupes, skips empties); resolveRecipients validates names,
    excludes the sender, and skips banned members on broadcast.

Email channel (operator, explicit):
  - new `agentbbs broadcast` subcommand sends an announcement to ALL members via
    inbox + email. Preview by default (like notify-creds); --send delivers;
    --no-inbox/--no-email pick a channel; --subject/--from/--user refine it.
    Email reaches only verified addresses and refuses --send without SMTP.

Tests: SendMessageMulti (dedupe/empty), resolveRecipients (list/unknown/all
tokens, banned + sender exclusion), TUI selection (toggle/select-all/group
compose). Docs: docs/messaging.md. build/vet/gofmt/`go test ./...` green.

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 54ede81 into main Jun 27, 2026
5 checks passed
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