feat: authsession service

This commit is contained in:
Ilia Denisov
2026-04-08 16:23:07 +02:00
committed by GitHub
parent 28f04916af
commit 86a68ed9d0
174 changed files with 31732 additions and 112 deletions
@@ -0,0 +1,179 @@
// Package mail provides runtime mail-delivery adapters for the auth/session
// service.
package mail
import (
"context"
"errors"
"fmt"
"sync"
"galaxy/authsession/internal/ports"
)
var errForcedFailure = errors.New("stub mail sender: forced failure")
// StubMode identifies the deterministic outcome used by StubSender for one
// delivery attempt.
type StubMode string
const (
// StubModeSent reports that the adapter accepts delivery and returns the
// stable sent outcome expected by the auth flow.
StubModeSent StubMode = "sent"
// StubModeSuppressed reports that the adapter intentionally suppresses
// outward delivery while still returning a successful suppressed outcome.
StubModeSuppressed StubMode = "suppressed"
// StubModeFailed reports that the adapter returns an explicit delivery
// failure instead of a successful outcome.
StubModeFailed StubMode = "failed"
)
// IsKnown reports whether mode is one of the supported stub delivery modes.
func (mode StubMode) IsKnown() bool {
switch mode {
case StubModeSent, StubModeSuppressed, StubModeFailed:
return true
default:
return false
}
}
// StubStep overrides the default stub behavior for one queued delivery
// attempt.
type StubStep struct {
// Mode selects the delivery behavior for this queued step.
Mode StubMode
// Err optionally overrides the failure returned when Mode is StubModeFailed.
Err error
}
// Validate reports whether step contains one supported queued behavior.
func (step StubStep) Validate() error {
if !step.Mode.IsKnown() {
return fmt.Errorf("stub mail step mode %q is unsupported", step.Mode)
}
return nil
}
// Attempt records one validated delivery request handled by StubSender.
type Attempt struct {
// Input stores the validated cleartext mail-delivery request exactly as it
// was passed into SendLoginCode.
Input ports.SendLoginCodeInput
// Mode stores the resolved stub mode after queued overrides were applied.
Mode StubMode
}
// StubSender is a deterministic runtime MailSender implementation intended
// for development, local integration, and explicit stub-based tests.
//
// The zero value is ready to use and defaults to StubModeSent.
type StubSender struct {
// DefaultMode controls the fallback behavior when Script is empty. The zero
// value is treated as StubModeSent so the zero-value sender is usable
// without extra configuration.
DefaultMode StubMode
// DefaultError optionally overrides the failure returned when DefaultMode
// resolves to StubModeFailed.
DefaultError error
// Script stores queued one-shot overrides consumed in FIFO order before the
// default behavior is used.
Script []StubStep
mu sync.Mutex
attempts []Attempt
}
// SendLoginCode records one validated delivery request and returns the
// deterministic stub outcome selected by the queued script or the default
// mode.
func (s *StubSender) SendLoginCode(ctx context.Context, input ports.SendLoginCodeInput) (ports.SendLoginCodeResult, error) {
if ctx == nil {
return ports.SendLoginCodeResult{}, errors.New("stub mail sender: nil context")
}
if err := ctx.Err(); err != nil {
return ports.SendLoginCodeResult{}, err
}
if err := input.Validate(); err != nil {
return ports.SendLoginCodeResult{}, err
}
s.mu.Lock()
defer s.mu.Unlock()
mode, errOverride, err := s.resolveNextStepLocked()
if err != nil {
return ports.SendLoginCodeResult{}, err
}
s.attempts = append(s.attempts, Attempt{
Input: input,
Mode: mode,
})
switch mode {
case StubModeSent:
return ports.SendLoginCodeResult{Outcome: ports.SendLoginCodeOutcomeSent}, nil
case StubModeSuppressed:
return ports.SendLoginCodeResult{Outcome: ports.SendLoginCodeOutcomeSuppressed}, nil
case StubModeFailed:
if errOverride != nil {
return ports.SendLoginCodeResult{}, errOverride
}
return ports.SendLoginCodeResult{}, errForcedFailure
default:
return ports.SendLoginCodeResult{}, fmt.Errorf("stub mail sender: unsupported resolved mode %q", mode)
}
}
// RecordedAttempts returns a stable defensive copy of every validated delivery
// attempt handled by the stub.
func (s *StubSender) RecordedAttempts() []Attempt {
s.mu.Lock()
defer s.mu.Unlock()
return append([]Attempt(nil), s.attempts...)
}
func (s *StubSender) resolveNextStepLocked() (StubMode, error, error) {
if len(s.Script) > 0 {
step := s.Script[0]
s.Script = append([]StubStep(nil), s.Script[1:]...)
if err := step.Validate(); err != nil {
return "", nil, fmt.Errorf("stub mail sender: %w", err)
}
if step.Mode == StubModeFailed {
if step.Err != nil {
return step.Mode, step.Err, nil
}
return step.Mode, errForcedFailure, nil
}
return step.Mode, nil, nil
}
mode := s.DefaultMode
if mode == "" {
mode = StubModeSent
}
if !mode.IsKnown() {
return "", nil, fmt.Errorf("stub mail sender: default mode %q is unsupported", mode)
}
if mode == StubModeFailed {
if s.DefaultError != nil {
return mode, s.DefaultError, nil
}
return mode, errForcedFailure, nil
}
return mode, nil, nil
}
var _ ports.MailSender = (*StubSender)(nil)