Infraestrutura & Ferramentas

Changelog

Histórico de mudanças do MAD framework.

Changelog

Histórico de marcos do MAD framework. Versão atual: 5.54.0.

A partir do 5.0.0 (23/07/2026) o framework adotou semver com fonte da verdade em packages/mad-framework/VERSION (texto puro X.Y.Z): toda mudança em packages/mad-framework/** bumpa a versão no mesmo commit, com uma entrada de changelog correspondente — um hook de pre-commit aborta o commit sem bump e sem entrada. Uma entrada por bump. As entradas antigas (v1.x, abaixo) eram por marco de epic e ficam como histórico pré-5.

Como ler a versão em runtime:

\Mad\Support\MadFramework::version();   // '5.54.0' — versão do pacote instalado

A fonte completa, com detalhe de cada bump, fica no CHANGELOG.md na raiz do repositório. Esta página resume o que importa para quem consome o framework: o que quebrou, o que mudou de comportamento, e o que foi endurecido em segurança.


Linha 5.x — do 5.0.0 ao 5.54.0

Mais de 90 bumps entre julho e agosto de 2026. Os marcos que mudam como você escreve código:

5.0.0 — nasce o versionamento (2026-07-23)

  • packages/mad-framework/VERSION + Mad\Support\MadFramework::version() — o pacote passa a ter identidade de versão, exibida no card Mad Framework da Central de Comando (v local → v builder) e usada pelo canal de update.
  • <mad-field-list>: options tolerante (mapa, lista value-label ou JSON), props condicionais por linha disabled-when/readonly-when, e attrs/on-change uniformes em todos os tipos de célula.

⚠️ Nunca adicione "version" no composer.json do pacote. O require do repo e de todo app gerado é "mad/framework": "@dev" (path repo); uma version explícita torna a stability stable, o @dev para de casar e o composer install quebra. O arquivo VERSION existe exatamente para dar versão sem tocar na resolução do Composer.

Erro visível e estado de componente (5.1 – 5.2)

  • MadErrorModal — um 500 do Laravel numa resposta AJAX deixou de sumir no console: vira modal de erro na tela. Mad._httpError cobre todos os fetches do mad.js.
  • Model Eloquent em prop pública sobrevive ao state — antes o objeto era serializado e voltava corrompido; hoje o envelope de Model é reconhecido na re-hidratação, e state com tipo incompatível (payload legado) é descartado em vez de fatalar. Desde a 5.7.0 as relações carregadas também sobrevivem.

Upload e blocos de banco (5.3 – 5.4.x)

  • mode="table" no upload grava os metadados do arquivo (nome original, mime, tamanho, disco) no INSERT, não só o caminho.
  • MadRequest::files() / file() / hasFile().
  • <mad-comments> e <mad-attachments> — componentes prontos para lista de filhos de um registro.
  • <mad-db-blocks>: add-mode="inline" (formulário fixo, sem popover), upload por item, blockEdit, :preset-vars e confirm-remove (5.9.0).

Robustez do registry (5.5 – 5.8)

  • Um control quebrado derrubava o app inteiro: a descoberta fazia require_once em todo .php da camada e o try/catch nunca protegeu (erro de compilação é fatal, não Throwable). O índice passou a ser montado por tokenização.
  • Falha ao carregar o detail podia APAGAR os filhos do registro — corrigido na 5.6.0.
  • ServiceRegistry voltou a indexar interface e trait; tela citada com namespace errado deixou de derrubar o Salvar.

Dimensões, máscaras e navegação (5.13 – 5.23)

  • width/max-width não funcionavam em nenhum dos 47 componentes de campo — corrigido, com \Mad\Support\CssUnits como ponto único de normalização de unidade CSS.
  • <mad-btn> passou a honrar label, confirm e color.
  • MadRoutes::exposeMethod(path, class, method) — caminho declarativo para expor um método ao roteador; navigate="Classe::onShow()" deixou de virar URL /onShow%28%29.
  • mask e force-case voltaram a funcionar em telas abertas por overlay/drawer, e a máscara passou a se ligar sozinha (sem depender de quem injetou o campo).

<mad-pdv> — frente de caixa (5.24 – 5.35)

Componente novo de PDV/POS, entregue em 5 fases: MadPdvComponent + casca, lookup e finalização, runtime client (mad-pdv.js/mad-pdv.css), harness PdvDevView e e2e de navegador (npm run e2e:pdv). Ganhou depois: <mad-pdv-column> (colunas do carrinho declarativas, editáveis por item e gravadas na venda), catálogo de produtos para quem não tem leitor, preço/estoque em tabelas relacionadas, desconto em R$ ou %, pagamento composto com troco e venda a prazo gerando contas a receber.

Deploy em subdiretório e IA (5.36 – 5.50.x)

  • 5.36.0 — o app só conseguia rodar na raiz do domínio; os cinco layouts passaram a respeitar o base path.
  • Copilot / IA: chat embed com Mad Coding Plan + tools, blocos de visualização nível BI, ask_user (pergunta com opções clicáveis), suggest_next (próximos passos como chips), show_table com agrupamento/quebras/somatórios, widgets tool-backed com save_dashboard (dashboards persistentes) e filtros globais de dashboard com opções extraídas dos dados reais + slicer (hook mad.ai.widget_global_filter_hook).

5.51 – 5.54 (agosto/2026)

  • 5.51.0 — multi-select mode="table" sem foreign-key salvava nada.
  • 5.52.0 — a prop value era ignorada em silêncio em 10 componentes de campo.
  • 5.53.0 — o filtro lateral só achava com o valor digitado exatamente como gravado.
  • 5.53.1 — o menu superior não aparecia mesmo ligado no tema.
  • 5.54.0 — introspecção de schema derrubava banco grande: o SchemaIntrospector (usado pelo REST driver / Database Manager) fazia COUNT(*) em toda tabela mais 3 queries de catálogo por tabela. Agora rowCount vem da estatística do engine em 1 query (information_schema.tables.table_rows no MySQL, pg_class.reltuples no PostgreSQL; sqlite_stat1 no SQLite), com o campo novo rowCountApprox (bool) sinalizando estimativa, e colunas/FKs/PKs/índices carregados em lote (1 query por tipo para o schema inteiro), com fallback por tabela se o lote falhar.

v1.2.0 — Camada de dados 100% Eloquent (2026-06-19)

Épico de migração completa do acesso a dados: o framework abandonou a camada de ORM proprietária que carregava desde as primeiras versões e passou a usar Eloquent + Query Builder nativos de ponta a ponta — models, transações, queries, agregações e conexões. Schema normalizado para mad_<domínio>_<entidade>, models espelhados em App\Models\<Domínio>\<Entidade>.

⚠️ Breaking

  • ModelOptionsLoader::items() perde o parâmetro de conexão. O argumento existia para resolver a conexão manualmente — hoje a conexão vem do próprio model ($model::query()). Assinaturas novas:

    • ModelOptionsLoader::items($model, $key, $value, $orderColumn)
    • MadForm::loadOptionsFromModel($field, $model, …)
    • FieldListColumn::loadOptions($target, $model, …)

    Migração: remova o argumento de conexão (era o 1º parâmetro em items(), o 2º em loadOptionsFromModel()/loadOptions()). Exemplo: loadOptionsFromModel('cidade_id', 'business', 'Cidade') → loadOptionsFromModel('cidade_id', 'Cidade').

Removido

  • A camada de ORM proprietária inteira (registro/critério/filtro/transação/repositório) saiu do framework. Models agora estendem Illuminate\Database\Eloquent\Model diretamente, com traits explícitos para os comportamentos que antes eram automáticos (HasIdPolicy, HasMadAudit, HasMadSoftDeletes); persistir um registro é save(), não um método proprietário. Transações são DB::transaction() nativo. Consultas complexas são Eloquent Builder puro. 60 models migrados, com um teste de arquitetura travando regressão (qualquer novo model que tente herdar da camada antiga quebra o CI).
  • Conexões de banco passaram a ser 100% nativas (config/database.php), incluindo os resolvers específicos para os bancos legados ainda suportados (Oracle/Firebird).
  • Limpeza de HTML morto do tema padrão (variantes de tela de login que hoje são só CSS).

Alterado

  • Schema normalizado mad_<domínio>_<entidade>, com separação clara entre conexões de controle (auth/permissões) e de dados (multi-tenant friendly).
  • Models organizados por domínio (App\Models\<Domínio>\<Entidade>) com um registry central que resolve token curto → classe completa.
  • Convenção única e executável de nomeação tabela→model, usada tanto pelo scaffolding quanto como guard-rail de CI.
  • Correção de um bug latente na exclusão em cascata de árvores auto-referentes (estava usando uma chamada inválida para o Eloquent Query Builder).

Segurança

  • Hardening de SQL no grid e nos gráficos: subselects relacionais e filtros de coluna passaram a usar bind parametrizado (antes era concatenação com escaping manual); validação de expressões de ordenação/agrupamento por whitelist fail-closed (OrderGuard).
  • Proteção anti-injeção em ORDER BY/GROUP BY no caminho de queries nativas do grid e do serviço de registros.
  • Escopo de linha do MCP (acesso de IA aos dados) por usuário/unidade, opt-in e fail-closed.

Outras entregas

  • Exportação de grid autenticada, com link de download expirando (HTTP 410 Gone) em vez de ficar acessível para sempre.
  • Upload por linha em listas detalhadas/inline, com download de arquivo binário.
  • Rotas amigáveis para os serviços internos do Correio.
  • Detecção precisa de violação de chave única nos blocos de formulário ligados a banco.

v1.1.0 — Comunicação em tempo real (2026-06-14)

Épico de reescrita da comunicação interna: Correio (caixa de e-mail estilo Outlook/Gmail) e Chat interno, ambos sobre Laravel Reverb (WebSocket).

Adicionado

  • Correio interno reescrito: caixa single-pane (lista → leitura full-width + Voltar), pastas Caixa de entrada/Favoritos/Enviadas/Rascunhos/Arquivadas/Lixeira, rótulos, cópia (Cc), rascunhos, e separação entre "lido" e "arquivado" (ler uma mensagem não tira mais ela da caixa de entrada).
  • Entrega por destinatário — uma linha de pivot por destinatário, permitindo Cc na caixa e estado de leitura/favorito/arquivamento divergente por usuário (a mesma mensagem pode estar lida para um destinatário e não lida para outro).
  • Tempo real via Reverb no Correio: badge, toast e lista atualizam sem refresh.
  • Chat interno em tempo real sobre Reverb, com canais privados de conversa, reações e anexos.
  • Módulo de importação de dados (entrega inicial).

Alterado

  • Camada de dados nativa: config/database.php virou a fonte única das conexões usadas pelo framework (autenticação, permissões, comunicação, log).
  • Limpeza de todo o roteamento legado ainda referenciado no layout ativo.

Corrigido

  • Troca de painel single-pane (selecionar/voltar) ficou confiável em todos os casos.
  • O dropdown de mensagens do header passou a abrir a caixa nova corretamente.
  • Composição de mensagem corrigida (o envio podia falhar silenciosamente em alguns campos).
  • Vazamento de listener JS no compose ao navegar entre telas.

Segurança

  • Escopo global anti-IDOR de leitura: as queries do Correio só enxergam mensagens em que o usuário da sessão participa (remetente, destinatário ou Cc) — mesmo com acesso direto ao banco/API, não dá pra ler mensagem alheia.
  • Bloqueio de IDOR no envio: validação server-side impede mandar mensagem para fora da própria unidade, mesmo manipulando o payload do formulário.
  • Auditoria não-silenciosa: toda tentativa bloqueada por IDOR é logada com ator, alvo e IP antes de ser rejeitada.
  • Neutralização de um XSS armazenado no caminho de leitura de mensagens (sanitização do corpo).

Infraestrutura

  • O backend de tempo real legado (anterior ao Reverb) foi completamente desligado — chat e Correio rodam 100% sobre Reverb.
  • Pipeline de assets com mapa único fonte→servido e verificação automática em CI (composer mad:sync:check) — impede que o JS/CSS publicado fique fora de sincronia com a fonte.

Convenções deste changelog

  • ⚠️ Breaking — exige mudança de código em quem consome o framework.
  • Removido / Alterado / Adicionado — segue o espírito do Keep a Changelog.
  • Segurança — hardenings e correções com impacto de segurança, sempre destacados à parte.