rdev/internal/domain/notify.go
jordan ddcfe52b5c
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat: implement shared notify host model for platform email delivery
Replace per-project notify host provisioning (7-9 API calls + DNS + async
Resend verification) with a shared platform host for all *.threesix.ai projects.

Under the new model:
- CreateProjectNotify: 3 calls only (account + send key + host grant)
- No per-project Resend domain, DNS records, or async verification
- All *.threesix.ai projects share `threesix.ai` as the platform host
- Custom domains still get a dedicated host via ReprovisionNotifyHost

Changes:
- domain/notify.go: slim NotifyCredentials (no Host/From/ResendDomainID);
  add NotifyHostCredentials for reprovision return path
- port/notify_provisioner.go: update interface signatures and docs
- adapter/notify/provisioner.go: rewrite CreateProjectNotify (3 steps);
  rewrite DeleteProjectNotify (account-only vs full cleanup)
- adapter/notify/provisioner_reprovision.go: return *NotifyHostCredentials
- adapter/notify/provisioner_test.go: update tests for new model
- service/project_infra_crud.go: store only NOTIFY_API_KEY on provision
- domain/credential.go: add CredKeyNotifySharedHost/CredKeyNotifySharedFrom
- cmd/rdev-api/config.go: add NotifySharedHost/NotifySharedFrom to InfraConfig
- service/component.go: add notifySharedHost/notifySharedFrom + WithNotifyDefaults
- service/component_deploy.go: inject shared host defaults when no custom host stored
- handlers/notify.go: handle shared-host projects in Reprovision guard;
  add WithSharedNotifyHost builder
- cmd/rdev-api/main.go: wire SharedHost to provisioner, component service,
  and notify handler

Bootstrap: NOTIFY_SHARED_HOST=threesix.ai and NOTIFY_SHARED_FROM=noreply@threesix.ai
stored in credential store (host id=1 already provisioned with Resend provider).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:04:11 -07:00

52 lines
1.8 KiB
Go

// Package domain contains core business entities.
package domain
import "time"
// NotifyCredentials holds per-project email delivery credentials.
// Under the shared-host model, all default projects send through a pre-provisioned
// platform host (e.g., "mail.threesix.ai"). Only the account, send key, and host
// grant are created per-project; no dedicated host, Resend domain, or DNS records
// are allocated unless a custom domain is configured via ReprovisionNotifyHost.
type NotifyCredentials struct {
// ProjectID is the rdev project this credential set belongs to.
ProjectID string
// AccountID is the notify service account UUID (used for deletion).
AccountID string
// APIKey is the notify send key (notify_send_...) for sending emails.
APIKey string
// CreatedAt is when the credentials were provisioned.
CreatedAt time.Time
}
// NotifyHostCredentials holds the per-project host credentials returned by ReprovisionNotifyHost.
// Used only for custom-domain migrations; default projects use the shared platform host.
type NotifyHostCredentials struct {
// ProjectID is the rdev project this credential set belongs to.
ProjectID string
// Host is the custom sending host (e.g., "mail.myapp.threesix.ai").
Host string
// From is the from-address registered on the host (e.g., "noreply@mail.myapp.threesix.ai").
From string
// ResendDomainID is the Resend domain UUID for the new host.
ResendDomainID string
}
// NotifyDomainStatus holds the Resend verification status for a project's email domain.
type NotifyDomainStatus struct {
// Host is the per-project sending host (only set for custom domains).
Host string
// ResendDomainID is the Resend domain UUID.
ResendDomainID string
// Status is the Resend verification status: "verified", "pending", "failed", or "not_configured".
Status string
}