# Módulo 25 — fechamento definitivo do SSO oficial e bloqueio de acesso direto

Fechamento incremental aplicado **sobre a base já consolidada até o módulo 24**, sem reabrir a arquitetura aprovada do portal, do bridge `/public/nvr`, do catálogo/launch/entitlement e do gateway.

## Objetivo fechado

Revalidar com runtime real que o **portal é a única entrada principal do usuário final** e endurecer o NVR para que:

- `/nvr` (raiz integrada),
- `/login`,
- `/launch.php`,
- o workspace `/app` e `/cliente`

falhem fechado sem contexto válido do portal.

## Ajustes aplicados

### 1. SSO oficial mais auditável
`platform/src/Domain/CentralIntegration/Services/CentralProductLaunchTicketService.php`

O validate do ticket assinado agora devolve metadados auditáveis do handoff:

- `ttl_seconds`
- `issuer`
- `audience`
- `header`
- `signature_verified`

### 2. Sessão oficial do launch mais rica e verificável
`platform/src/Http/Controllers/Auth/PortalLaunchController.php`

O consume oficial agora persiste no `$_SESSION['portal_launch']`:

- `ticket_issuer`
- `ticket_audience`
- `ticket_alg`
- `ticket_type`
- `signature_verified`
- `ttl_seconds`
- `site_name`
- `unit_code`
- `launch_guard=portal_signed_ticket_v1`

Além disso, a auditoria do consume bem sucedido passou a registrar explicitamente:

- tenant
- usuário
- site/unidade
- escopo
- emissão
- expiração
- assinatura verificada
- algoritmo
- audience
- destino final

### 3. `/login` comum endurecido contra bypass
`platform/src/Http/Controllers/Auth/LoginController.php`

O boot do login comum agora registra trilha auditável quando o usuário tenta usar `/login` fora do fluxo oficial do portal.

Eventos incluídos:

- `auth.login.direct_entry_blocked`
- `auth.login.direct_entry_disabled`

### 4. `/login-tecnico` explicitamente isolado
`platform/src/Http/Controllers/Auth/LoginController.php`
`platform/resources/views/auth/login.php`

A tela técnica foi endurecida para deixar claro que é **contingência administrativa explícita**, separada do fluxo principal.

Foi adicionada demarcação operacional por cabeçalhos HTTP:

- `X-NVR-Auth-Boundary: technical-contingency`
- `X-NVR-Auth-Mode: local-contingency`
- `X-NVR-Portal-Entry-Required: true|false`

A tela técnica também deixou de competir com o fluxo principal ao remover atalhos genéricos de cadastro/recuperação do portal.

### 5. Regressão real ampliada
`platform/tests/suites/final-product-regression.php`

A suíte canônica final agora cobre explicitamente:

- bloqueio do `login-central` quando o portal oficial é obrigatório
- bloqueio do callback `sso/entrar` quando o fluxo direto está desabilitado
- bloqueio do `/login` comum
- bloqueio do `/launch.php` sem ticket
- bloqueio com assinatura inválida
- bloqueio com ticket expirado
- persistência auditável de `tenant`, `user`, `site`, `scope`, `issued_at`, `expires_at`, `signature_verified`
- isolamento explícito e auditável do `/login-tecnico`

## Arquivos principais alterados

- `platform/src/Http/Controllers/Auth/LoginController.php`
- `platform/src/Http/Controllers/Auth/PortalLaunchController.php`
- `platform/src/Domain/CentralIntegration/Services/CentralProductLaunchTicketService.php`
- `platform/resources/views/auth/login.php`
- `platform/tests/bootstrap.php`
- `platform/tests/Feature/NvrIntegratedRuntimeRegressionTest.php`
- `platform/tests/Feature/NvrOfficialSsoBoundaryRegressionTest.php`
- `platform/tests/Feature/PortalLaunchMandatoryEntryTest.php`
- `platform/tests/suites/final-product-regression.php`

## Resultado objetivo desta rodada

- `php artisan about` → ok
- `php artisan route:list` → ok
- `php tests/run.php --suite=final-product-regression` → **27 passou, 0 falhou**
- `bash scripts/test.sh` → ok
- `bash scripts/test-regression.sh` → ok

## Leitura funcional

Com este corretivo, o caminho principal do usuário final fica definitivamente ancorado no portal oficial, enquanto o login técnico local permanece:

- separado,
- explícito,
- marcado por boundary próprio,
- auditável,
- e sem substituir o launch oficial do produto.
