# Task 002 — Enum `OtpStatus` + máquina de transições

**Depende de:** 001
**Bloqueia:** 003, 006, 007, 009

## Objetivo

Backed enum `string` (compatível com persistência direta) com a máquina de estados do PRD §3.2.

## Deliverable

`Enums/OtpStatus.php`:

```php
namespace GalaxiaMissoes\Mensageria\sinais\Otp\Enums;

enum OtpStatus: string {
    case AGUARDANDO_ENVIO        = 'aguardando_envio';
    case ENVIADO                  = 'enviado';
    case VALIDADO                 = 'validado';
    case EXPIRADO                 = 'expirado';
    case INVALIDADO_TENTATIVAS    = 'invalidado_tentativas';
    case CANCELADO                = 'cancelado';

    public function label(): string;
    public function cssClass(): string;
    public function estadoFinal(): bool;
    public function aceitaTentativaValidacao(): bool;     // só ENVIADO
    public function podeReenviar(): bool;                  // AGUARDANDO_ENVIO ou ENVIADO (gera novo OTP)
    public function proximosStatusPossiveis(): array;
    public function podeTransicionarPara(OtpStatus $destino): bool;
}
```

## Transições

```
AGUARDANDO_ENVIO → ENVIADO, CANCELADO
ENVIADO          → VALIDADO, EXPIRADO, INVALIDADO_TENTATIVAS, CANCELADO
VALIDADO         → (final)
EXPIRADO         → (final)
INVALIDADO_TENTATIVAS → (final)
CANCELADO        → (final)
```

## Testes (já mirando task 012)

- Cada transição válida e inválida.
- `tryFrom('inexistente')` retorna null.
- `aceitaTentativaValidacao()` só true em ENVIADO.
- `estadoFinal()` true em todos os terminais.

## Critério de aceite

- Lint OK.
- Sem dependências externas (puro PHP).
