# Arquitetura Técnica

## Decisão principal

O sistema será um **monólito modular em PHP 8.3 sem framework**, hospedado em Apache e usando MySQL 8. A separação por módulos é lógica e de código; todos utilizam a mesma implantação e, inicialmente, o mesmo banco.

Essa decisão combina baixo custo operacional com limites claros entre domínios. Microserviços não são necessários no início e aumentariam falhas distribuídas, observabilidade e esforço de implantação.

## Componentes

```mermaid
flowchart TD
    U["Navegador / Leitor"] --> A["Apache + PHP"]
    A --> C["Núcleo da aplicação"]
    C --> M["Módulos de domínio"]
    M --> DB["MySQL 8"]
    M --> R["Redis"]
    R --> W["Workers PHP"]
    W --> EXT["SEFAZ / Mercado Livre"]
    W --> FS["Arquivos e objetos"]
```

## Estrutura proposta

```text
app/
  Core/
    Auth/
    Authorization/
    Database/
    Events/
    Files/
    Http/
    Logging/
    Queue/
    Routing/
    Security/
    Support/
    Validation/
    View/
  Modules/<Module>/
    Application/
      Commands/
      Queries/
      DTO/
      Services/
    Domain/
      Entities/
      Enums/
      Events/
      Exceptions/
      Policies/
      ValueObjects/
    Infrastructure/
      Persistence/
      Integrations/
    Http/
      Controllers/
      Requests/
    Views/
    Tests/
bin/
  console
  worker
config/
database/migrations/
database/seeds/
docs/
public/
  index.php
  assets/
resources/
  js/
  css/
  views/
routes/
storage/
  app/
  logs/
  cache/
tests/
vendor/
```

Somente `public/` deve ser servido pelo Apache. Configurações, certificados, logs, XMLs e uploads não podem ficar diretamente acessíveis.

## Núcleo próprio

O núcleo deve ser pequeno e coberto por testes. Responsabilidades:

- bootstrap e container simples de dependências;
- roteamento com método HTTP, parâmetros e middleware;
- Request e Response;
- tratamento centralizado de exceções;
- sessão segura, autenticação e CSRF;
- contexto corrente de grupo/empresa/estabelecimento;
- autorização por permissões e escopo;
- validação;
- renderização de views com escaping padrão;
- acesso a banco, transações e repositories;
- eventos internos e outbox;
- filas e agendamento;
- logs estruturados;
- migrations e seeders;
- configuração por ambiente.

Não criar recursos genéricos sem uso real. Cada abstração deve resolver uma necessidade documentada do N4STi Gestão.

## Camadas

- **Http:** protocolo, validação sintática, autenticação, autorização e resposta.
- **Application:** casos de uso, transações e orquestração.
- **Domain:** regras, estados, valores e invariantes.
- **Infrastructure:** MySQL, Redis, arquivos e APIs externas.
- **Views:** apresentação; nunca contém regra de negócio ou SQL.

## Banco e acesso

Pode-se usar PDO ou mysqli, mas a escolha deve ser única em todo o projeto. Recomendação: PDO pela clareza de transações e prepared statements, sem usar ORM.

Repositories devem possuir consultas explícitas. Para listagens complexas, criar query objects dedicados. Toda consulta deve receber o contexto de segurança ou derivá-lo de serviço confiável.

## Transações

Uma transação deve ser curta e conter somente persistência local. Chamadas ao Mercado Livre, SEFAZ, e-mail ou armazenamento remoto ocorrem depois do commit através da outbox/fila.

Fluxo:

1. validar comando;
2. abrir transação;
3. verificar invariantes e locks;
4. persistir documento e movimentos;
5. gravar evento na outbox;
6. commit;
7. worker publica/processa o evento;

## Concorrência

Usar `SELECT ... FOR UPDATE` somente nos agregados afetados, em ordem consistente. Reservas e movimentos precisam de chave idempotente. Redis pode coordenar processamento externo, mas nunca será a única fonte de verdade do estoque ou financeiro.

## Eventos internos

Eventos conectam módulos sem acoplamento direto. Exemplos:

- `SalesOrderConfirmed`
- `InventoryReserved`
- `ShipmentDispatched`
- `MarketplaceOrderImported`
- `ProductionOrderReleased`
- `OutsourcingShipmentSent`
- `OutsourcingReturnReceived`
- `ReceivableCreated`
- `InvoiceAuthorized`

Eventos críticos devem ser persistidos em `outbox_events` na mesma transação da alteração de negócio.

## Filas

Filas iniciais:

- `default`
- `marketplace-import`
- `marketplace-export`
- `inventory-sync`
- `fiscal`
- `documents`
- `notifications`
- `reports`

Cada job possui: UUID, grupo, tipo, payload versionado, tentativas, próxima execução, status, correlation ID, erro resumido e timestamps. Jobs repetidos precisam produzir o mesmo resultado ou detectar processamento anterior.

## APIs internas

Rotas web retornam HTML. Ações assíncronas e telas dinâmicas usam endpoints JSON sob `/api/v1`. A API deve usar os mesmos serviços e políticas do HTML; não duplicar regra.

Padrão de resposta de erro:

```json
{
  "error": {
    "code": "INVENTORY_INSUFFICIENT",
    "message": "Estoque disponível insuficiente.",
    "fields": {"quantity": ["Disponível: 8,000"]},
    "correlation_id": "uuid"
  }
}
```

## Arquivos

Metadados ficam no MySQL; conteúdo em storage privado. Fotos públicas derivadas podem ser expostas por URL controlada. XML, certificados, documentos pessoais e relatórios privados exigem autorização a cada download.

Usar hash SHA-256, MIME detectado no servidor, tamanho, autor e vínculo. Upload deve impedir execução e nomes de arquivo não devem definir o caminho físico.

## Configuração

- `.env` apenas no servidor, nunca versionado;
- validação obrigatória de variáveis no bootstrap;
- configurações tipadas;
- segredos criptografados quando persistidos;
- ambientes `development`, `test`, `staging`, `production`;
- integrações podem operar em sandbox/homologação por empresa.

## Escalabilidade

Primeiro escalar verticalmente e separar workers. Evolução possível:

1. Apache/PHP e MySQL na mesma infraestrutura controlada.
2. Workers em processos separados.
3. Redis e storage externos.
4. Réplicas de leitura para relatórios.
5. Separação de serviço somente para carga comprovada, como fiscal ou sincronização massiva.

## ADRs iniciais

- ADR-001: PHP sem framework.
- ADR-002: monólito modular.
- ADR-003: MySQL como fonte transacional.
- ADR-004: estoque por ledger de movimentos.
- ADR-005: outbox para efeitos externos.
- ADR-006: multiempresa por banco compartilhado com escopo obrigatório.
- ADR-007: frontend server-rendered com aprimoramento progressivo.

