Logosulfite.app
rafagazani/sulfite 999999

Roadmap#

Visão geral de onde o Sulfite está e para onde estamos indo.

Estado atual#

ComponenteStatusDescrição
sulfite_core Motor de relatórios com 12 tipos de elementos, parser JSON, processamento de dados, ScriptEngine (filter/sort/limit/distinct/addField), GroupBands, geração multiformato (PDF, HTML, CSV, Excel), parâmetros de impressão com lookups HTTP e banco de dados, paginação de lookups, novos tipos de parâmetro ( currency , datetime ), campos format / rounding por parâmetro, formatos numéricos estilo Excel ( #,##0.00 ), pacote .sulfite (RFC-017), pivot mode no TableElement (ordenação, overrides de coluna, estilos condicionais)
sulfite_studio Editor visual com canvas interativo, inspetor de propriedades, desfazer/refazer, tradução, seletor de cores, tema personalizado, editor de gráficos, GroupBands, Transform Pipeline Editor, filtros dinâmicos com lookups e cascata (RFC-015), autocomplete de agregados (RFC-013), persistência de layout (RFC-014), preview em tempo real, save/load de .sulfite (RFC-017), aba Scripts com code_forge + Dart (RFC-016)
sulfite_report_manager Widget Flutter completo de gerenciamento de relatórios — CRUD, busca, permissões granulares, visualizador integrado com filtros automáticos, exportações e abertura no Designer (RFC-018)
sulfite_server Servidor REST completo — CRUD de relatórios, geração síncrona/assíncrona (SSE), conexões criptografadas AES-256-GCM, autenticação HMAC com permissões granulares e refresh rotation, assinatura digital de relatórios, compartilhamento público com OTP, export/edit policy, rate limiting por endpoint, consumer API e deploy via Docker/Render (RFC-025, 026, 027, 028)
sulfite_cli Gera PDFs pela linha de comando — compilável para executável nativo (~42ms por PDF)
Exportação multiformato Gera PDF, HTML, CSV e Excel a partir do mesmo JSON
FontBytesLoader Interface para carregamento de fontes — desacopla o motor de relatórios do Flutter ( AssetFontBytesLoader ) e permite uso em CLI/servidor ( FileFontBytesLoader )
ScriptEngine Motor de transformação declarativa — filter, sort, limit, distinct, addField com expressões, AND/OR/NOT; parâmetros injetados no contexto
GroupBands Quebra de grupo com groupHeader e groupFooter — subtotais automáticos por grupo
Advanced Scripting Scripts Dart com afterQuery / beforeRender hooks via dart_eval; replaces declarative transforms (RFC-016)
Print Filters Parâmetros interativos antes de imprimir — diálogo automático, lookups HTTP e banco de dados ( LookupConfig.http / LookupConfig.db ), paginação de lookup, novos tipos currency e datetime , campos format / rounding por parâmetro, validação declarativa, dependências em cascata, injeção em expressões e URLs REST (RFC-011, RFC-015)
sulfite_datasources Arquitetura modular com 4 pacotes especializados: sulfite_datasources_rest , sulfite_datasources_postgres , sulfite_datasources_postgrest (Supabase), sulfite_datasources_sqlite3 . Cada resolver pode ser usado individualmente ou via pacote guarda-chuva sulfite_datasources . Inclui DbLookupResolver com queries SQL parametrizadas, paginação e cache; suporte completo a ConnectionRegistry (RFC-019)
Pacote .sulfite Formato ZIP portátil com definição + assets embutidos — save/load no Studio e suporte no Manager (RFC-017)
Documentação Documentação com playground interativo no navegador

Próximos passos#

Fase 1 — Editores mais completos no Studio #

  • Edição visual de colunas de tabela (TableColumnEditor)
  • Estilização de trechos de texto — negrito, itálico, cor (TextSpanEditor)
  • Configuração visual dos modos de arredondamento (RoundingConfigEditor)
  • Seletor de formatos numéricos e de data (FormatPickerField)
  • Seletor de cores com paleta, campo hex e sincronização bidirecional (StudioColorPickerDialog)
  • Reordenar séries de gráfico por drag & drop (ChartEditorDialog)
  • Seleção de idioma (pt-BR / en-US) com aplicação imediata
  • Tema personalizado: cor primária livre via picker de cores; tabela de papéis do tema com hex

Fase 2 — Edição JSON ↔ Canvas (RFC 004) #

  • Editar o JSON e ver o canvas atualizar automaticamente (e vice-versa)
  • Validação em tempo real — erros e avisos aparecem inline no editor de código
  • Editor com syntax highlighting, busca, formatação automática e tooltips de propriedades (JsonEditorWidget)

Fase 2a — Chat IA integrado ao Studio #

  • Agente LLM que gera ReportDefinition completo a partir de descrição em linguagem natural
  • 5 provedores: OpenAI, Anthropic, Ollama (local), GitHub Models, GitHub Copilot
  • Auto-correção automática de JSON inválido (até 3 tentativas)
  • Painel flutuante arrastável + modo dockado como aba lateral
  • Contexto dinâmico: JSON do relatório atual é injetado a cada mensagem
  • Suporte a imagens no chat (envia como data URI)
  • Sem efeito no bundle quando chatConfig não é fornecido

Fase 2b — printWhen por elemento + ScriptEngine #

  • printWhen em qualquer ReportElement — expressão booleana que oculta o elemento quando avalia false
  • Expressões com AND, OR, NOT lógicos
  • AdvancedScriptEngine com hooks afterQuery e beforeRender — substituiu o campo transforms removido

Fase 2c — Studio auto-explicativo + DataSource + Editors visuais #

  • Tooltips e help cards em todo o Studio com i18n (pt-BR / en-US)
  • DataSourceResolver + RestDataSourceResolver — interface abstrata para fontes externas
  • TableColumnEditor — edição visual de colunas de tabela
  • TextSpanEditor — estilização visual de trechos de texto (negrito, itálico, cor)

Fase 2d — GroupHeader / GroupFooter Bands (RFC 009) #

  • Novos tipos de band: groupHeader e groupFooter com campo groupBy
  • DataProcessor agrupa registros automaticamente pela chave
  • Subtotais por grupo: AggregateElement respeita o escopo de grupo
  • PDF, HTML, CSV e Excel renderizam a hierarquia grupo → detalhe → subtotal
  • Studio: AddBandDialog com tipos groupHeader/groupFooter, PropertyInspector com campo groupBy

Fase 2e — Transform Pipeline no Studio (RFC 010) #

  • TransformPipelineEditor — painel visual com lista reordenável de operações
  • Cada operação: dropdown de tipo, dropdown de source, campos de parâmetros específicos
  • ExpressionEditorBackend com syntax highlighting e autocomplete de campos do schema
  • Preview em tempo real via compute() (isolate) — executa pipeline nos dados de amostra
  • DesignerViewModel: addTransform, removeTransform, reorderTransforms, updateTransform
  • 28 chaves i18n (pt-BR + en-US)

Fase 2f — Print Filters, Unify Rect, Aggregate AutoComplete, Layout Persistence (RFC 011–014) #

RFC-011 — Print Filters (parâmetros estáticos)

  • ReportParameter — model Freezed com tipo text/number/date/select
  • ScriptEngine.execute() — injeta parâmetros no contexto de expressões
  • RestDataSourceResolver.expandUrl() — expande {paramId} em templates de URL REST
  • PrintParamsDialog — diálogo modal automático antes de imprimir/exportar
  • ParameterEditor — editor inline no painel de configurações do relatório
  • ExpressionEvaluator — comparação lexicográfica >=/<=/>/< para strings/datas

RFC-015 — sulfite_filtros (lookups dinâmicos)

  • LookupConfig — modelo para busca de opções via HTTP com cache e placeholders
  • LookupResolver / HttpLookupResolver — interface e implementação HTTP com proteção SSRF
  • SulfiteFilterScreen — widget de filtros com lookups, cascata e validação inline
  • ValidationRule — 9 regras de validação declarativa (required, min, max, dateBefore, dateAfter, etc.)
  • dependsOn — dependências em cascata entre parâmetros

RFC-012 — Unify Rect + RoundedRect

  • borderRadius adicionado ao RectElement (default 0.0)
  • JSONs antigos com type: roundedRect migram automaticamente para RectElement
  • RoundedRectElement removido do código

RFC-013 — Aggregate AutoComplete

  • AggregateComputer — utilitário: compute/preview/fieldsFromRows
  • _AggregateTargetKeyField — autocomplete para campo targetKey no designer

RFC-014 — Layout Persistence

  • collapsedPanels: List<String> adicionado a StudioPreferences
  • PreferencesProvider: isPanelCollapsed / togglePanelCollapsed / updatePanelWeight

Fase 2g — sulfite_filtros: Lookups Dinâmicos e Cascata (RFC 015) #

  • LookupConfig — modelo Freezed: URL com {paramId}, método HTTP, cache, refreshOnDependencyChange
  • LookupResolver — interface abstrata + HttpLookupResolver com proteção SSRF
  • SulfiteFilterScreen — widget standalone: campos text/number/date/select + select com lookup (loading state)
  • ValidationRule — 9 regras declarativas: required, minLength, maxLength, min, max, dateBefore, dateAfter, lessThan, greaterThan
  • dependsOn — cascata automática: quando o valor de um parâmetro-pai muda, filhos são recarregados
  • 14 chaves i18n adicionadas (pt-BR + en-US)

Fase 2h — Advanced Scripting Engine (RFC 016) #

  • ReportScript model Freezed — id, hook (afterQuery / beforeRender / onFilter), code, description
  • AdvancedScriptEngine — registra handlers Dart por scriptId, executa hooks em ordem de declaração
  • ScriptContext — API segura: datasource(), param(), context(), query(), setBandVisible(), setElementVisible(), setElementProperty(), removeBand(), log()
  • ScriptMutations — acumula mutações de layout (hide/show bands e elementos, property overrides)
  • SqlBridge — interface para execução de queries SQL auxiliares (PostgreSQL, REST, Mock)
  • Campo scripts: List<ReportScript> adicionado ao ReportDefinition (backward compatible, default [])

Fase 2h2 — Studio: code_forge + aba Scripts (RFC 016 Sprint 3) #

  • Flutter 3.41.5 (Dart 3.11.3) — migração de todos os pacotes para SDK ^3.11.1 via FVM
  • code_forge ^9.2.0 substitui re_editor — Rope data structure, LSP builtin, multi-cursor, code folding avançado
  • CodeForgeBackend — novo backend do JSON Editor (substitui ReEditorBackend) com syntax highlighting JSON
  • CodeForgeExpressionBackend — novo backend do Expression Editor com snippets de campos de schema
  • Aba Scripts no Studio — quarto modo no toolbar (SegmentedButton) ao lado de Design / Preview / Code
    • ScriptEditorWidget — lista lateral de scripts com drag-to-reorder, add/delete
    • CodeForge com langDart + vs2015Theme + 11 snippets de ScriptContext (ctx.datasource, ctx.query, ctx.param, etc.)
    • Toolbar por script: seletor de hook (afterQuery / beforeRender / onFilter) + campo de descrição
    • Modo scripts oculta sidebar de design (sem toolbar de elementos)
  • DesignerViewModel.updateScripts() — atualiza a lista de scripts sem registrar no undo/redo global

Fase 2i — Formato .sulfite (RFC 017) #

  • SulfitePackageWriter — serializa ReportDefinition + assets em ZIP portátil (.sulfite)
  • SulfitePackageReader — extrai e reconstrói a definição a partir do ZIP
  • Studio: salva/abre pacotes .sulfite com opção de incluir dados de exemplo
  • ReportManagerWidget: detecta storageKind: package e usa SulfitePackageReader automaticamente
  • Assets (fontes, imagens) embutidos no pacote — relatório autocontido e portátil

Fase 2j — sulfite_report_manager (RFC 018) #

  • ReportManagerWidget — tela completa com lista, busca, CRUD e permissões granulares
  • ReportRepository — interface abstrata + 4 implementações: InMemory, Sqlite, Rest, Postgres
  • Fluxo viewer-first: relatório abre no visualizador (SulfiteConsumerScreen); Designer só abre se canSettings: true
  • Carregamento diferido pós-animação + compute() para parsear definição em background
  • inlineDataPayload — fornece dados inline por relatório (relatórios estáticos/demo) via SulfiteConsumerScreen
  • SulfiteConsumerScreen.onEdit — callback VoidCallback chamado com a ReportDefinition já parseada (sem re-parsear no Designer)
  • Suporte a .sulfite e JSON como formatos de armazenamento
  • SulfiteFilterScreen migrado para StudioDialogShell (visual consistente com o Studio)

Fase 2k — Lookups DB, novos tipos de parâmetro e formatos numéricos #

LookupConfig: union http / db

  • LookupConfig refatorado para union selada com discriminador "source" — backward-compatible (documentos sem source continuam funcionando como HTTP)
  • LookupConfig.db — novo backend de lookup que executa SQL contra uma entrada do ConnectionRegistry
  • DbLookupResolver (pacote sulfite_datasources) — resolves queries PostgreSQL parametrizadas com {_search}, {_page}, {_page_size}, {_offset} e {_schema}
  • Paginação em lookups HTTP e DB — pageSize + fetchPage() com suporte a resposta meta.total/page/perPage
  • Cache separado para resultados paginados (_pageCache) para evitar recomputação inconsistente de hasMore
  • SSRF: adicionado http://127.0.0.1 como origem permitida além de https:// e http://localhost

Novos tipos de parâmetro

  • currency — campo com máscara monetária e arredondamento configurável
  • datetime — seletor de data e hora (yyyy-MM-ddTHH:mm)
  • Campo format em ReportParameter — padrão intl para date/datetime, máscara "<milhar><decimal><casas>" para currency, precisão para number
  • Campo rounding em ReportParameter — aplica half_even, half_up, half_down, up, down, truncate ao reformatar no blur

Formatos numéricos estilo Excel

  • ValueFormatter aceita padrões #,##0.00, #,##0, 0.00, #,##0.000, etc. — mesmo estilo do Excel e JasperReports
  • _formatNumber agora usa roundNumWithMode com half_even em vez de toStringAsFixed direto

Fase 3 — Conectar a bancos e APIs (RFC 001, 024) #

Arquitetura modular de resolvers

  • 4 pacotes dedicados: sulfite_datasources_rest, sulfite_datasources_postgres, sulfite_datasources_postgrest, sulfite_datasources_sqlite3
  • Pacote guarda-chuva sulfite_datasources re-exporta todos os resolvers (consumidores escolhem dependências granulares)
  • PostgresDataSourceResolver — conexões PostgreSQL diretas com ConnectionRegistry
  • RestDataSourceResolver — APIs HTTP/REST com suporte a headers customizados
  • PostgRestDataSourceResolver — suporte nativo a Supabase/PostgREST com sintaxe de query PostgREST (RFC-024)
  • Sqlite3DataSourceResolver — bancos SQLite3 locais (plataformas nativas, guardado por !kIsWeb)

Studio: DataSource Dialog unificado

  • Campo driver no DataSource — seleção explícita de resolver (rest, postgres, postgrest, sqlite3, ou driver customizado)
  • kDriverLabels exportado — labels human-friendly reutilizáveis em toda UI
  • Suporte completo a drivers customizados — formulário genérico preserva driver e permite URL/connectionRef/query/headers
  • ConnectionManagerWidget — gerenciamento visual de conexões PostgreSQL, HTTP e SQLite3
  • Editor de headers HTTP — configuração visual de API keys e tokens de auth
  • Proxy pattern — padrão documentado para usar PostgREST/Supabase em Flutter Web sem expor credenciais

Lookups de banco

  • DbLookupResolver — lookups de banco já funcionam (concluído na Fase 2k)
  • LookupConfig.db — union selada com queries SQL parametrizadas
  • Paginação automática via {_page}, {_page_size}, {_offset}, {_search}, {_schema}

Fase 4 — Relatórios com milhões de registros (RFC 007) #

  • True Streaming Pipeline — processDataStream consome Stream<Map> incrementalmente
  • processDataStreamChunked para processamento em lotes sem OutOfMemoryError
  • DataSourceResolver + RestDataSourceResolver para fontes externas via HTTP

Fase 5 — Novos tipos de elementos (RFC 002) #

Elemento / FeatureDescriçãoStatus
ChartElement Gráficos (barra, linha, pizza) com legenda, grade, rótulos
Chart: barras agrupadas Múltiplas séries lado a lado com offset automático
Chart: barras empilhadas stacked: true em PDF, HTML e Studio
Chart: borda hasBorder, borderDashed, cores e espessura
Chart: paleta consistente 10 cores compartilhadas entre PDF, HTML e Studio
forcePageBreakBefore Quebra de página por band (Header, Detail, Summary, Footer)
BandVisibility Controla em quais páginas Header/Footer são renderizados (firstPage, lastPage, oddPages…)
showOnPage Renderiza a band somente em uma página específica
printWhen Expressão booleana para ocultar band condicionalmente
TableElement pivot mode Tabela pivot com totais, ordenação, overrides de coluna e estilos condicionais — campo pivot no TableElement existente

Fase 6 — Editar gráficos no Studio (RFC 008) #

  • Editar propriedades do gráfico visualmente — tipo, cores, legendas (ChartEditorDialog)
  • Adicionar e remover séries de dados com poucos cliques
  • Gráfico atualiza em tempo real no canvas
  • Reordenar séries por drag & drop

Fase 7 — sulfite_server REST backend (RFC-025) #

  • SulfiteServer — servidor REST completo construído sobre o framework Relic
  • CRUD de relatóriosGET/POST/PUT/DELETE /api/v1/reports com suporte a JSON e pacotes .sulfite
  • Geração síncrona e assíncronaPOST /generate + jobs com polling e Server-Sent Events (GET /jobs/:id/stream)
  • Gerenciamento de conexões — registre bancos (PostgreSQL, SQLite) e APIs com criptografia AES-256-GCM em repouso
  • Autenticação HMAC-SHA256 — tokens de acesso com permissões granulares (canRead, canInsert, canSettings, canDelete) e refresh rotation com detecção de reuso
  • Consumer API — endpoint read-only GET /consumer/reports para usuários finais sem token completo
  • Resolução de datasourcesPOST /datasources/resolve e /introspect com suporte a REST, PostgreSQL e PostgREST
  • Deploy via Docker e Render.com — Dockerfile multi-stage com AOT compilation; variáveis PUBLIC_URL / RENDER_EXTERNAL_URL
  • Pool de isolates — geração concorrente de relatórios sem bloquear o event loop principal

Fase 8 — Security hardening (RFC-026) #

  • SEC-01 a SEC-17: auditoria abrangente com 17+ pontos de correção de segurança
  • Rate limiting por endpoint — sliding window com LRU eviction; limites separados para leitura, escrita e geração; bypass por IP configurável
  • Headers de segurançaX-Content-Type-Options, X-Frame-Options, Cache-Control: no-store, Referrer-Policy, CSP: default-src 'none', HSTS
  • SSRF guard — bloqueio de IPs internos em lookups HTTP configurável
  • Fail2ban em OTP e shares — bloqueio automático após N tentativas inválidas por IP
  • Comparação em tempo constante — proteção contra timing attacks na verificação de segredos
  • Validação de permissões — camada de autenticação verifica permissões antes de chegar ao handler

Fase 9 — Criptografia, assinatura e rotação de tokens (RFC-027) #

  • EnvelopeEncryptor — AES-256-GCM com rotação de chave: ENCRYPTION_KEY (ativa) + ENCRYPTION_KEY_PREV (leitura legada); envelope com salt e IV aleatórios por blob
  • ReportSigner — assinatura digital por role (author, deployer, reviewer) com cadeia de confiança; signatures embutidas no pacote .sulfite
  • VerifiedIdentity — identidade verificada (email + timestamp + origin) anotada na assinatura
  • Rotação de refresh tokens — cada uso emite um novo par e invalida o anterior; detecção de reuso invalida toda a família

Fase 10 — Compartilhamento de relatórios (RFC-028) #

  • Links de compartilhamentoPOST /share gera URL pública com slug aleatório, maxViews, expiresAt, código de acesso de 8 caracteres e fail2ban
  • Páginas HTML públicas com nonce CSP — landing page e página de erro usam nonce criptográfico por request (Random.secure()); script/style com nonce-$nonce em vez de unsafe-inline
  • PUBLIC_URL — URLs de share usam o domínio externo configurado (Render, etc.) em vez de host:port local

Fase 11 — Exportação verificada com autenticação por domínio (RFC-029) #

  • ExportPolicy — allowlist de domínios de e-mail e e-mails individuais; habilitada via EXPORT_POLICY_ENABLED, EXPORT_POLICY_DOMAINS, EXPORT_POLICY_EMAILS
  • Fluxo OTP de exportaçãoPOST /export/verify valida e-mail contra a policy e envia OTP; POST /export/confirm verifica o código e devolve o pacote .sulfite assinado com identidade verificada
  • VerifiedIdentity na assinatura — e-mail, domínio, timestamp e origin embutidos na SignatureEntry do pacote exportado
  • Rastreabilidade de exportação — cada download de .sulfite carrega quem exportou, quando e de qual organização
  • StudioVerifiedExportDialog detecta policy ativa via GET /export/policy e substitui o fluxo de exportação padrão

Fase 12 — Edit policy com OTP no Studio (RFC-030) #

  • EditPolicy — allowlist de domínios e e-mails para quem pode editar; habilitada via EDIT_POLICY_ENABLED, EDIT_POLICY_DOMAINS, EDIT_POLICY_REQUIRE_OTP
  • editToken — token de vida moderada (1h) emitido após OTP de intenção edit; destravar o canvas e o editor de código no Studio
  • saveToken — token de vida ultra-curta (5min) emitido por OTP independente no momento de salvar; exigido em PUT /reports/:id para prevenir overwrites não autorizados
  • Separação de risco — computador aberto perde o direito de editar após expiração do editToken e nunca consegue salvar sem novo OTP de salvamento
  • Middleware server-sidePUT /reports/:id rejeita com 403 se EditPolicy ativa e X-Edit-Token/X-Save-Token ausentes ou inválidos

RFCs#

Todas as propostas técnicas estão documentadas como RFCs no repositório:

RFCTítuloStatus
001 Dynamic DataSource Resolution with Plugin System
002 Advanced PDF Elements & Multi-Format Export
004 Studio DX — Bidirectional Sync & Real-time Validation
006 Studio Layout & Preferences Persistence
007True Streaming Pipeline
008 Charts Integration in Studio
009 GroupHeader / GroupFooter Bands
010Transform Pipeline Studio
011 Print Filters — Parâmetros interativos antes de imprimir
012Unify Rect + RoundedRect
013 Aggregate AutoComplete no Studio
014 Layout Persistence — collapsedPanels + panelWeight
015 sulfite_filtros — Lookups HTTP e DB, Paginação, Cascata, Validação, currency / datetime
016Advanced Scripting Engine
017 Formato .sulfite — Pacote portátil com assets embutidos
018 sulfite_report_manager — Gerenciador de relatórios Flutter
019 Named Connection Registry — Desacoplar credenciais do relatório
024 PostgREST Studio Support — Supabase/PostgREST como data source
025 sulfite_server — Servidor REST backend com auth, CRUD, geração assíncrona e consumer API
026 Security Hardening — Rate limiting, SSRF guard, headers, fail2ban e auditoria SEC-01–17
027 Criptografia e Assinatura — AES-256-GCM envelope encryption, assinatura por role e rotação de tokens
028 Compartilhamento — Links públicos com slug, código de acesso e fail2ban
029 Exportação Verificada — OTP por e-mail, allowlist de domínios e VerifiedIdentity na assinatura
030 Edit Policy — OTP para abrir o Studio e OTP independente para salvar; editToken + saveToken

Quer contribuir ou sugerir uma RFC? Abra uma issue no GitHub.