# Main Flows ## Auth / Session -> Mail ```mermaid sequenceDiagram participant Auth as Auth / Session Service participant Mail as Mail Service participant Postgres participant Scheduler participant SMTP as Provider Auth->>Mail: POST /api/v1/internal/login-code-deliveries + Idempotency-Key Mail->>Mail: validate request and idempotency scope alt MAIL_SMTP_MODE = stub Mail->>Postgres: persist delivery as suppressed Mail-->>Auth: 200 {outcome=suppressed} else MAIL_SMTP_MODE = smtp Mail->>Postgres: persist delivery as queued + attempt #1 scheduled Mail-->>Auth: 200 {outcome=sent} Scheduler->>Postgres: claim due attempt (FOR UPDATE SKIP LOCKED) Scheduler->>SMTP: send rendered auth mail SMTP-->>Scheduler: accepted or classified failure Scheduler->>Postgres: commit sent / retry / failed / dead_letter end ``` `sent` on this boundary means durable intake into the mail-delivery pipeline. It does not mean SMTP completion. ## Notification -> Mail ```mermaid sequenceDiagram participant Notify as Notification Service participant Stream as Redis Stream mail:delivery_commands participant Consumer as Command consumer participant Mail as Mail Service participant Postgres participant Redis Notify->>Stream: XADD generic command Consumer->>Stream: XREAD from last stored offset Consumer->>Mail: decode and validate command alt malformed or conflicting command Mail->>Postgres: record malformed command entry Consumer->>Redis: save stream offset else valid command Mail->>Postgres: persist delivery + first attempt + optional payload bundle Consumer->>Redis: save stream offset end ``` ## Retry and Dead Letter ```mermaid sequenceDiagram participant Scheduler participant Postgres participant Worker as Attempt worker participant SMTP as Provider Scheduler->>Postgres: find next due delivery (next_attempt_at <= now) Scheduler->>Postgres: load work item (delivery + active attempt) alt template delivery not yet rendered Scheduler->>Postgres: render and store materialized content end Scheduler->>Postgres: claim scheduled attempt (FOR UPDATE SKIP LOCKED) Scheduler->>Worker: enqueue claimed work Worker->>SMTP: send materialized message SMTP-->>Worker: accepted / suppressed / transient_failure / permanent_failure alt accepted Worker->>Postgres: commit sent + provider_accepted else suppressed Worker->>Postgres: commit suppressed + provider_rejected else transient failure before retry budget ends Worker->>Postgres: commit transport_failed|timed_out + next scheduled attempt else retry budget exhausted Worker->>Postgres: commit dead_letter + dead-letter entry else permanent failure Worker->>Postgres: commit failed + provider_rejected end ``` ## Operator Resend ```mermaid sequenceDiagram participant Ops as Trusted operator participant Mail as Mail Service participant Postgres Ops->>Mail: POST /api/v1/internal/deliveries/{delivery_id}/resend Mail->>Postgres: load original delivery and optional payload bundle Mail->>Mail: verify original status is terminal Mail->>Postgres: create clone delivery with source=operator_resend Mail-->>Ops: 200 {delivery_id=} ``` Resend always creates a new delivery and never mutates the original delivery or its attempt history.