agentbbs/internal/forwardemail/forwardemail_test.go
Anthony Ettinger 7a85f2dbbb
Autonomous deploy + free-pod/Premium-email membership (#1)
Deploy automation (idempotent, runs on every deploy):
- .github/workflows/deploy.yml: push to main/master (or dispatch) SSHes to the
  droplet and re-runs setup.sh; deploys the pushed branch; smoke-tests :22.
- scripts/self-update.sh + agentbbs-update.timer: autonomous backstop that
  redeploys only when origin advances.
- setup.sh hardened: flock, fetch+reset (survives force-push), fixed the
  always-skipped arcade asset fetch path.

Membership model:
- Free, email-verified members get their own Docker pod (pod@ paywall removed)
  and a /~name homepage (seeded at join@).
- join@ is now interactive: email -> emailed 6-digit code -> enter code.
- Premium ($10 one-time, lifetime via CoinPay) grants a personal
  <name>@host email (new internal/forwardemail; forwardemail.net aliases) and
  custom domains (domain@ gated to Premium).
- ensurePremium() silently verifies/grants/provisions on hub login, join@, and
  domain@. New-signup details emailed to AGENTBBS_SIGNUP_NOTIFY (subject "bbs").

Store: User.Premium + premium/premium_ref cols, ConfirmEmailCode, GrantPremium.
Tests: store_premium_test.go, forwardemail_test.go. Build/vet/gofmt/test green.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 00:59:52 -07:00

27 lines
849 B
Go

package forwardemail
import "testing"
func TestConfiguredAndAddress(t *testing.T) {
var empty Config
if empty.Configured() {
t.Fatal("empty config must not be Configured")
}
if (Config{APIKey: "k"}).Configured() {
t.Fatal("API key without domain must not be Configured")
}
c := Config{APIKey: "k", Domain: "bbs.profullstack.com", Webmail: "https://webmail.example"}
if !c.Configured() {
t.Fatal("API key + domain should be Configured")
}
if got := c.Address("alice"); got != "alice@bbs.profullstack.com" {
t.Fatalf("Address = %q", got)
}
if c.WebmailURL() != "https://webmail.example" {
t.Fatalf("WebmailURL = %q", c.WebmailURL())
}
// Creating an alias without config is a clean error, not a panic.
if err := empty.CreateAlias("alice", "alice@x.com"); err == nil {
t.Fatal("CreateAlias on unconfigured must error")
}
}