# ARQUITETURA_BANCO_CENTRAL_V2_FINAL

## 1. Status da versão

Esta é a **V2 FINAL** para congelamento do banco central da plataforma.

Princípios mantidos sem alteração:

- banco central **separado** dos bancos operacionais;
- ERP atual **fora do caminho crítico**;
- nesta fase, o banco central **não substitui** login, sessão nem permissões internas do ERP;
- implantação continua **em fases**, com rollback por isolamento;
- nenhuma dependência síncrona obrigatória do ERP em relação ao banco central.

---

## 2. Escolha oficial de SGBD

**Escolha oficial: MariaDB 10.6+**

A V1 em PostgreSQL era tecnicamente válida, mas a V2 FINAL foi fechada em MariaDB para alinhar o núcleo central ao stack atual e reduzir custo operacional em:

- driver e pooling no PHP;
- administração do SGBD;
- backup/restore;
- monitoramento;
- migrations;
- runbooks do time.

A robustez perdida em recursos nativos do PostgreSQL foi recomposta no schema por:

- FKs compostas;
- colunas geradas + `UNIQUE` para unicidade condicional;
- `CHECK`;
- procedures e triggers;
- locks lógicos com `GET_LOCK()` onde há concorrência crítica.

---

## 3. Papel do banco central

O banco central é o **source of truth comercial, de identidade do portal e de entitlement da plataforma**.

Ele controla:

- clientes;
- usuários do portal principal;
- catálogo de produtos;
- planos e preços;
- assinaturas;
- trial;
- faturas;
- pagamentos;
- cupons;
- acessos por produto;
- provisionamento assíncrono;
- outbox de integração;
- segredos e configurações;
- logs administrativos e de integração.

Ele **não** controla, nesta fase:

- autenticação do ERP;
- sessão do ERP;
- ACL interna do ERP;
- dados operacionais do ERP;
- banco operacional do ERP.

---

## 4. Fechamento técnico da V2 FINAL

## 4.1 Cupons — lógica corrigida

A validação de `cupom_usos` foi endurecida e corrigida.

### O que ficou protegido no banco

1. **status/vigência do cupom só são revalidados quando a operação entra em estado ativo**, isto é:
   - insert em `reservado` ou `aplicado`;
   - update que muda o status para `reservado` ou `aplicado`.

2. **update para `cancelado` ou `estornado` continua permitido** mesmo se o cupom:
   - estiver expirado;
   - estiver inativo.

3. Para `cumulativo = false`, o banco agora impede coexistência indevida no mesmo alvo:
   - o alvo pode ser `item_assinatura`;
   - ou `fatura`;
   - são considerados estados `reservado` e `aplicado`;
   - a proteção vale tanto quando o cupom novo é não cumulativo quanto quando já existe no alvo outro cupom não cumulativo.

4. Para `primeira_compra_apenas`, a regra oficial ficou:
   - o cliente **não pode** ter fatura anterior com `status = 'paga'` antes do uso ativo do cupom.

5. `cupom_usos` agora trata **cupom/cliente/alvo como imutáveis** após criação.
   Isso evita mutações históricas perigosas e simplifica auditoria.

### Consequência prática
O banco deixa de bloquear cancelamentos/estornos históricos e, ao mesmo tempo, protege cenários reais de stacking incorreto de cupom.

---

## 4.2 Preço e assinatura — coerência fechada

`assinatura_itens` agora tem fechamento de snapshot de preço no banco.

### Regra oficial
Quando `preco_plano_produto_id` está preenchido:

- ele deve pertencer ao mesmo `plano_produto_id`;
- o `ciclo_cobranca` do item deve bater com o preço;
- a `moeda` do item deve bater com o preço;
- no `INSERT`, `valor_unitario` e `valor_setup` são carregados do preço escolhido;
- no `UPDATE`, o snapshot só é recalculado se o seletor do preço mudar;
- se o preço continuar o mesmo, o banco impede alteração manual do snapshot.

### Efeito
O item de assinatura passa a ter um **snapshot consistente e travado** do preço selecionado.

---

## 4.3 Fatura e assinatura — coerência item a item

`fatura_itens` foi fechado para impedir cruzamento incoerente entre:

- `assinatura_item_id`
- `plano_produto_id`

Regra final:

- se `assinatura_item_id` existir, o banco resolve o `plano_produto_id` do item de assinatura;
- se `plano_produto_id` vier nulo, ele pode ser preenchido automaticamente pelo trigger;
- se vier preenchido e não corresponder ao item de assinatura, o banco rejeita.

---

## 4.4 Configurações e segredos — escopo endurecido

### Configurações
`configuracoes_plataforma` agora tem regra explícita de escopo:

- `escopo_tipo = 'global'` → `escopo_id IS NULL`
- `escopo_tipo <> 'global'` → `escopo_id IS NOT NULL`

Escopos aceitos na V2 FINAL:

- `global`
- `produto`
- `cliente`
- `gateway`
- `instancia_produto`

O banco valida por trigger a existência real do destino.

### Segredos
A estratégia oficial continua sendo a **abordagem C**:

- `secret_ref` externo por padrão;
- tabela versionada para segredo cifrado quando necessário.

`segredos_plataforma` também recebeu regra explícita de escopo:

- `global`
- `gateway_pagamento`
- `produto`
- `instancia_produto`
- `mfa`

Escopos genéricos não ancorados em tabela foram removidos da V2 FINAL.

### O que pode ficar em `configuracoes_plataforma`
Pode ficar:

- texto;
- número;
- booleano;
- JSON não sensível;
- `secret_ref` apontando para cofre externo.

Não pode ficar:

- segredo bruto;
- token real;
- chave privada real;
- credencial operacional em texto puro.

Além disso, `tipo_valor = 'secret_ref'` não pode ser `classificacao = 'publica'`.

### Anti-órfão
Além da validação em insert/update, a V2 FINAL inclui triggers para impedir exclusão de entidades que estejam sendo referenciadas por configuração/segredo polimórfico.

---

## 4.5 Identidade do portal — hardening final

## `usuarios_plataforma`
Foram adicionados:

- `bloqueado_em`
- `desabilitado_em`

Regra final de senha:

- se `origem_identidade = 'local'`
- e `status IN ('ativo','bloqueado','desabilitado')`
- então `senha_hash` **não pode** ser nulo.

## MFA
`mfa_habilitado` foi **mantido**, mas passou a ser tratado como **flag derivada e sincronizada por trigger** a partir de `mfa_fatores`.

Isso evita dupla verdade entre:

- `usuarios_plataforma.mfa_habilitado`
- `mfa_fatores`

## Sessões
`sessoes_plataforma` recebeu índice adicional em:

- `familia_sessao_id`

Isso fecha melhor revogação em cascata, rotação de refresh token e análise de família de sessão.

---

## 4.6 Preços — regra de recorrência explícita

A regra final ficou formalizada em constraint:

- `ciclo_cobranca = 'unico'` → `recorrente = false`
- `ciclo_cobranca != 'unico'` → `recorrente = true`

Não há exceção aberta na V2 FINAL.

---

## 4.7 Trial — fonte de verdade

A regra oficial da V2 FINAL é:

- `trials` = **fonte de verdade**
- `assinatura_itens.trial_inicio_em / trial_fim_em` = **snapshot operacional**

Uso recomendado:

1. abrir/encerrar trial em `trials`;
2. refletir no `assinatura_item` apenas o snapshot necessário para cobrança e acesso.

Isso elimina ambiguidade documental da V2 anterior.

---

## 4.8 Webhooks e logs

## `webhooks_pagamento`
Recebeu índices adicionais orientados a reconciliação por:

- gateway + data de recebimento;
- gateway + tipo + status + data;
- gateway + data de processamento.

## `logs_plataforma`
Recebeu `expira_em` para política futura de retenção/purge sem alterar o modelo.

A V2 FINAL não impõe partição agora, mas já prepara a tabela para um job de limpeza controlado.

---

## 5. Múltiplas assinaturas e múltiplas instâncias

A regra continua explícita por produto, sem reabrir arquitetura.

## Assinaturas
Controle por:

- `produtos.permite_multiplas_assinaturas_ativas`

Se `false`, o banco impede mais de um item ativo do mesmo produto para o mesmo cliente.

## Instâncias
Controle por:

- `produtos.permite_multiplas_instancias_ativas`

Se `false`, o banco impede mais de uma instância ativa do mesmo produto para o mesmo cliente.

### Recomendação operacional mantida
- ERP: assinatura única, instância única
- Chatbot: assinatura única, múltiplas instâncias se o produto vender bots independentes
- PDF Tools: assinatura única, instância única
- Bingo: começar com assinatura única e instância única

---

## 6. Integração assíncrona mantida

A V2 FINAL preserva a malha assíncrona já definida:

- `jobs_provisionamento_produto`
- `eventos_outbox_integracao`
- `tentativas_webhook_saida`
- `fila_dead_letter`
- `logs_integracao`

Esse núcleo permite integração futura por:

- API;
- fila;
- webhook;
- sincronização assíncrona;
- reprocessamento controlado.

Nada disso entra no caminho crítico do ERP atual.

---

## 7. Impacto zero no ERP atual

A V2 FINAL continua obedecendo integralmente às restrições de produção:

- não altera o banco do ERP;
- não altera login do ERP;
- não altera sessão do ERP;
- não altera permissões internas do ERP;
- não cria dependência obrigatória do ERP com o banco central;
- não exige migração de dados operacionais do ERP.

Qualquer integração futura com o ERP continua sendo por **adapter**, de forma gradual e assíncrona.

---

## 8. Conclusão

A V2 FINAL fecha a modelagem em nível profissional para congelamento:

- coerência forte entre preço, assinatura e faturamento;
- cupom pronto para cenário real;
- identidade do portal endurecida;
- escopos de configuração/segredo protegidos;
- trial documentado como fonte oficial;
- retenção futura prevista;
- sem abrir risco para o ERP atual.

Esta versão já está preparada para:
- homologação;
- staging;
- validação de migrations;
- e posterior entrada em produção por fases.