feat: deny retired and unassigned mailbox warmup actions without retrying authoritative absence or weakening send safety

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Matthew Meszaros
2026-10-10 07:53:48 +00:00
co-authored by Devin AI
parent c85b2bcb23
commit 4e1c2e6053
4 changed files with 75 additions and 0 deletions
+2
View File
@@ -636,6 +636,8 @@ Cloud-managed OAuth additionally exposes `POST /pool-link/instance/oauth/start-c
`POST /internal/worker/outbound-dispatch`, `/internal/worker/warmup-actions`, and `/internal/worker/diagnostic-auth` use the existing execution-plane internal token, never customer API keys. They bind the current mailbox/worker and require protocol 2. Outbound start additionally rechecks task/organization/provider/nonce/recipients and current campaign or diagnostic policy. Diagnostic authorization/result submission binds one exact already-owned warmup receipt and short-lived nonce; it neither ingests unrelated inbox messages nor trusts event/header claims. No public scope or permission was added. Details and limits: [send safety](/development/send-safety/).
Warmup actions for a deleted, unassigned or no-longer-authorized mailbox return no permitted actions. The worker treats that authoritative denial as a no-op without touching the provider. Database or authority failures still return `503` and retry; denial does not authorize a send, clear a send hold, or acknowledge an arrival.
### Referrals and discounts
The referral program and billing discount history are part of `/subscription/*`, so they are JWT only and never accept an API key. There is no API permission scope for them; browser callers are gated by the org permission below. The discount validation and checkout endpoints are listed under [Subscription and billing](/api/reference/account-org/) in the reference.
@@ -9,8 +9,36 @@ import (
"github.com/google/uuid"
"github.com/warmbly/warmbly/internal/config"
"github.com/warmbly/warmbly/internal/models"
"github.com/warmbly/warmbly/internal/repository"
)
type warmupActionAuthorityStub struct {
repository.SyncContextRepository
err error
}
func (s *warmupActionAuthorityStub) PermittedWarmupActions(context.Context, uuid.UUID, uuid.UUID, []string) ([]string, error) {
return nil, s.err
}
func TestWarmupActionAuthorityDenialDoesNotTouchMailbox(t *testing.T) {
w := &WorkerService{ID: uuid.NewString(), SyncContextRepository: &warmupActionAuthorityStub{}}
for _, action := range []string{models.WarmupActionFile, models.WarmupActionDelete, models.WarmupActionVerifyRemoval} {
if err := w.HandleWarmupAction(t.Context(), models.WarmupEmailAction{EmailID: uuid.New(), Actions: []string{action}, FilingID: uuid.NewString()}); err != nil {
t.Fatalf("denied %s action must finish without loading a mailbox: %v", action, err)
}
}
}
func TestWarmupActionAuthorityFailureMustRetry(t *testing.T) {
failure := errors.New("authority unavailable")
w := &WorkerService{ID: uuid.NewString(), SyncContextRepository: &warmupActionAuthorityStub{err: failure}}
err := w.HandleWarmupAction(t.Context(), models.WarmupEmailAction{EmailID: uuid.New(), Actions: []string{models.WarmupActionDelete}})
if !errors.Is(err, failure) {
t.Fatalf("authority failure must remain retryable: %v", err)
}
}
func TestWarmupFilingFallsBackForOlderEvents(t *testing.T) {
// An event published before the placement fields existed has to behave the
// way every mailbox did then: the default folder.
@@ -2,12 +2,49 @@ package repository
import (
"context"
"errors"
"testing"
"github.com/google/uuid"
"github.com/warmbly/warmbly/internal/models"
)
func TestLiveWarmupActionsDenyUnavailableMailbox(t *testing.T) {
for _, state := range []string{"missing", "deleted", "unassigned"} {
t.Run(state, func(t *testing.T) {
f, r := lineageFixture(t)
worker := uuid.New()
mailbox := f.recipient
switch state {
case "missing":
mailbox = uuid.New()
case "deleted":
if _, err := f.pool.Exec(t.Context(), `DELETE FROM email_accounts WHERE id=$1`, mailbox); err != nil {
t.Fatal(err)
}
case "unassigned":
if _, err := f.pool.Exec(t.Context(), `UPDATE email_accounts SET worker_id=NULL WHERE id=$1`, mailbox); err != nil {
t.Fatal(err)
}
}
actions, err := r.PermittedWarmupActions(t.Context(), mailbox, worker, []string{models.WarmupActionFile, models.WarmupActionDelete})
if err != nil || len(actions) != 0 {
t.Fatalf("unavailable mailbox must deny provider actions without retry: actions=%v err=%v", actions, err)
}
})
}
}
func TestLiveWarmupActionsPreserveAuthorityFailure(t *testing.T) {
f, r := lineageFixture(t)
ctx, cancel := context.WithCancel(t.Context())
cancel()
actions, err := r.PermittedWarmupActions(ctx, f.recipient, uuid.New(), []string{models.WarmupActionDelete})
if !errors.Is(err, context.Canceled) || len(actions) != 0 {
t.Fatalf("authority failure must remain retryable: actions=%v err=%v", actions, err)
}
}
func TestLiveDiagnosticOffStopsQueuedSendAndActions(t *testing.T) {
f, r := lineageFixture(t)
ctx := t.Context()
@@ -64,6 +101,10 @@ func TestLiveDiagnosticOffStopsQueuedSendAndActions(t *testing.T) {
if err != nil || len(got) != len(actions) {
t.Fatal("explicit legacy behavior changed", got, err)
}
got, err = r.PermittedWarmupActions(ctx, f.recipient, uuid.New(), actions)
if err != nil || len(got) != 0 {
t.Fatal("a different worker gained provider action authority", got, err)
}
exec(`UPDATE email_accounts SET test_mode='off' WHERE id=$1`, f.recipient)
got, err = r.PermittedWarmupActions(ctx, f.recipient, worker, actions)
if err != nil || len(got) != 1 || got[0] != models.WarmupActionDelete {
@@ -8,6 +8,7 @@ import (
"net/http"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/warmbly/warmbly/internal/models"
)
@@ -24,6 +25,9 @@ func (r *taskRepository) PermittedWarmupActions(ctx context.Context, mailbox, wo
err := r.db.QueryRow(ctx, `SELECT ea.status='active' AND ea.worker_id=$2 AND n.role='worker' AND n.active AND n.last_seen_at>NOW()-INTERVAL '10 minutes' AND n.warmup_send_protocol>=2
AND o.risk_state IN ('trusted','watch') AND NOT EXISTS(SELECT 1 FROM cloud_link_mailboxes c WHERE c.email_account_id=ea.id),ea.test_mode,ea.test_send_enabled,ea.test_receive_enabled
FROM email_accounts ea JOIN organizations o ON o.id=ea.organization_id JOIN fleet_nodes n ON n.id=ea.worker_id WHERE ea.id=$1`, mailbox, worker).Scan(&active, &a.TestMode, &a.TestSendEnabled, &a.TestReceiveEnabled)
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
if err != nil {
return nil, err
}