feat: mail service

This commit is contained in:
Ilia Denisov
2026-04-17 18:39:16 +02:00
committed by GitHub
parent 23ffcb7535
commit 5b7593e6f6
183 changed files with 31215 additions and 248 deletions
+26 -5
View File
@@ -84,7 +84,8 @@ The service is not responsible for:
- downstream business authorization
- direct push delivery to clients
- long-lived hot-path session caching inside gateway
- mail-service implementation details beyond the mail-delivery contract
- mail-service implementation details beyond the dedicated login-code delivery
REST contract
## Position in the System
@@ -140,15 +141,23 @@ The effective DTO contract is:
| `POST /api/v1/public/auth/send-email-code` | `{ "email": string }` | `{ "challenge_id": string }` |
| `POST /api/v1/public/auth/confirm-email-code` | `{ "challenge_id": string, "code": string, "client_public_key": string, "time_zone": string }` | `{ "device_session_id": string }` |
`send-email-code` may additionally receive the optional public
`Accept-Language` header through gateway. Auth resolves the first supported
BCP 47 language tag from that header, falls back to `en` when no supported
value is available, uses the resolved value as the auth-mail locale for the
dedicated `Mail Service` REST contract, and stores it on the challenge as the
create-only preferred-language candidate for a later first-user ensure step.
The created `challenge_id` is sent to `Mail Service` as the raw
`Idempotency-Key` header value of that dedicated REST call.
`client_public_key` is the standard base64-encoded raw 32-byte Ed25519 public
key registered for the created device session.
`time_zone` is the client-selected IANA time zone name. During the current
rollout phase, successful confirms forward create-only user registration
context to `User Service` as `preferred_language="en"` and the supplied
`time_zone` until gateway geoip-based language derivation is deployed.
context to `User Service` as the stored preferred-language candidate from
`send-email-code` and the supplied `time_zone`.
`User Service` now validates `preferred_language` as BCP 47 and canonicalizes
the stored value on creation, so any future derived language must already be a
valid BCP 47 tag before auth forwards it.
the stored value on creation, so the derived public language value must
already be a valid BCP 47 tag before auth forwards it.
Public boundary rules:
@@ -162,6 +171,9 @@ Public boundary rules:
IANA time zone name
- `send-email-code` remains success-shaped for existing, new, blocked, and
throttled e-mail paths
- `send-email-code` may use optional public `Accept-Language` to derive and
store the auth-mail locale plus future create-only `preferred_language`
candidate; unsupported or missing values fall back to `en`
- `confirm-email-code` returns a ready `device_session_id` synchronously on
success
@@ -236,6 +248,7 @@ Core fields:
- creation and expiration timestamps
- send and confirm attempt counters
- minimal abuse metadata
- stored preferred-language candidate derived at send time
- optional confirmation metadata used for idempotent retry
### Challenge States
@@ -259,6 +272,14 @@ Supported `challenge.DeliveryState` values:
- `throttled`
- `failed`
For the dedicated `Mail Service` REST contract, `delivery_state=sent` means
auth successfully handed the request off to
`POST /api/v1/internal/login-code-deliveries` and the mail-delivery pipeline.
That call uses the created `challenge_id` as the raw `Idempotency-Key` header
value.
It does not require that the SMTP provider exchange already completed before
`challenge_id` was returned to the caller.
Policy rules:
- initial challenge TTL is `5m`