Skip to content

Latest commit

 

History

History
241 lines (197 loc) · 17.6 KB

File metadata and controls

241 lines (197 loc) · 17.6 KB

fluigcli audit — Style Guide e APIs de script

O comando audit é o linter estático do projeto Fluig. Ele tem quatro famílias de regras:

  • SG* — conformidade com o Fluig Style Guide 2.0. Estas regras varrem forms/ e wcm/widget/. Elas apontam o que conflita com o tema fixo da plataforma. A partir do Fluig 2.0 o tema não é mais personalizável.
  • FL* — chamadas às APIs de script do Fluig (hAPI, getValue, form.*, FLUIGC, DatasetFactory, docAPI, WCMAPI e outras). O comando valida estas chamadas contra a referência fluig.d.ts embutida. Estas regras cobrem também datasets/, events/, mechanisms/ e workflow/scripts/. Um typo de método vira aviso. O aviso traz a sugestão do nome mais próximo. Assim você corrige o typo antes de o servidor devolver um erro críptico ou um null em silêncio em produção.
  • RHINO* — footguns do motor de script (Rhino) do Fluig. Estas regras rodam só no JS que executa no servidor (datasets/, events/, mechanisms/, workflow/scripts/ e os eventos de formulário). Elas pegam padrões que a análise estática detecta bem e que quebram sem erro claro em produção.
  • WF* — cruzamento do formulário com o processo ao qual ele está vinculado. Estas regras só rodam com --process <id>, porque precisam das etapas reais do processo. A CLI as baixa do servidor alvo (só leitura).

O comando não altera nada no servidor. Os arquivos locais só mudam com --fix.

fluigcli audit                       # projeto inteiro (todas as pastas convencionais)
fluigcli audit forms/MeuFormulario   # só um formulário
fluigcli audit --fix                 # aplica as correções determinísticas
fluigcli audit --sync                # atualiza o catálogo do servidor antes
fluigcli audit --fail-on none --json # só relatório (CI/agentes leem o data)
fluigcli audit --process meu_processo  # + regras WF*: activity-N × etapas reais

Regras

Regra Sev O que pega Sugestão / correção
SG001 aviso referência ao CSS legado fluig-style-guide.min.css (404 no 2.0) trocar para o -flat--fix aplica
SG002 erro recurso externo: <script src>/<link href>/@import/url() de CDN, Google Fonts etc. servir do próprio WAR/servidor (nos templates SPA a dependência vem por npm)
SG003 erro cor fixa (hex ou rgb()) em CSS, <style> embutido ou style= inline a variável do tema: valor idêntico → variável exata (--fix aplica nos hex); cinza → a neutra mais próxima (mesmo mapa do "Check color" oficial)
SG004 aviso !important em regra cujo seletor usa classe do style guide (em classe própria não é apontado) compor com o tema numa classe própria
SG005 aviso estilo inline (style=) mover para o CSS próprio ou utilitárias fs-*
SG006 aviso classe fs-* que não existe no catálogo do servidor (typo) a classe mais parecida do catálogo
SG007 aviso alert()/confirm()/prompt() nativos em JS de widget/form e <script> (eventos de formulário, que rodam no servidor, ficam de fora) FLUIGC.toast / FLUIGC.message.*
FL001 aviso método hAPI.* que não existe na referência (provável typo) o método mais parecido do fluig.d.ts
FL002 aviso variável WK* desconhecida em getValue() — o Fluig devolve null em silêncio a variável mais parecida (WKNumState, WKUser…)
FL003 aviso método form.* que não existe no FormController (só nos eventos de formulário, onde form é garantido) o método mais parecido
FL004 aviso membro inexistente em FLUIGC, DatasetFactory, DatasetBuilder, docAPI, WCMAPI, fluigAPI, customHTML (inclui os aninhados, ex.: FLUIGC.message.*) o membro mais parecido
FL005 erro método do hAPI chamado como função global em script de processo — getCardValue("x") sem o hAPI.. Em runtime a service task falha e a solicitação desvia para a tarefa de erro. Um helper seu com o mesmo nome é descontado quando declarado em qualquer script do mesmo processo (eles compartilham o escopo do Rhino). getValue(...) não é apontado: é a global legítima. Só em workflow/scripts/ prefixar com hAPI.
FL006 aviso getDataset(...).values (ou .getValue) encadeado direto em JS client-side (JS de formulário, widget e <script> do HTML). Quando a chamada falha no navegador — sessão/JWT expirado, dataset fora do ar — o retorno é undefined e o formulário quebra com TypeError, sem pista para o usuário final. Retorno guardado em variável não é apontado (na dúvida, a regra cala). No server-side a falha vira exceção, não undefined — a regra não roda lá guarde e verifique: var ds = DatasetFactory.getDataset(...); if (ds && ds.values) { ... }
FL007 aviso caractere fora do CP-1252 em script server-side (, , emoji…). O banco do Fluig guarda scripts em colunas CP-1252 e converte o que não cabe para ? na gravação, de forma permanente (comprovado byte a byte). A acentuação e a pontuação tipográfica (, , aspas curvas) sobrevivem e não são apontadas. O aviso aparece também no gate dos export (não barra) trocar por equivalente ASCII ( vira ->) — ou aceitar o ?
RHINO001 aviso ===/!== entre um java.lang.String (retorno de getFieldName, getInitialValue, getString, getColleagueName…) e um literal de texto — no Rhino do Fluig isso é sempre false (!== sempre true), sem erro. Rastreia também a variável que recebe esse retorno (var campo = c.getFieldName()...; if (campo === 'x')). A global de script de processo getValue("WK...") (com literal WK*) também é fonte — direta e via variável. O getValue genérico e o obj.getValue(...) ficam de fora (ambíguos). Rastreia ainda o caminho interprocedural mínimo: helper local que compara um parâmetro com ===/!== a literal de texto (function isEmpty(v){ return v === ''; }) chamado com uma fonte java — o achado ancora na chamada e cita a linha da comparação. Parâmetro reatribuído no corpo, coerção na chamada ou helper com == não acusam. String(...) e concatenação com + coagem para string JS e não são apontados. Só no JS server-side. converter com String(x.getFieldName()) === 'y' ou usar igualdade solta (==)
RHINO002 erro sintaxe ES6+ que o Rhino do Fluig (Voyager 2) não aceita e dá SyntaxError no deploy: class, import/export, async/await, parâmetro com valor default (function f(x = 1)), spread em array/chamada ([...a, 3]) e propriedade computada ({ [k]: v }). Recursos suportados não são apontados: template literal, let/const, arrow, for...of, destructuring, rest param (function f(...args)), Map/Set, Array.includes/find, String.padStart. Só no JS server-side. usar o equivalente ES5 (ex.: default → if (y == null) y = 10;; computada → obj[k] = v;; spread → .concat/.apply)
RHINO003 erro const declarado no corpo de um laço (for/while/do). No Rhino do Fluig o const não reinicializa a cada iteração — ele congela o valor da 1ª volta, em silêncio (bug de dados invisível). Um const numa função aninhada no laço não é apontado (a função cria escopo novo por chamada). O const no cabeçalho de for (const x of …) também não é apontado. Só no JS server-side. trocar por let (ou mover para fora do laço se o valor não muda)
RHINO004 aviso dataset.values[i] acessado por nome de coluna em JS server-side: values[0]["status"] ou values[0].status. No servidor a linha é um Object[] Java — o acesso por nome quebra em runtime (has no public instance field or method named "status"). O acesso por índice numérico (values[0][0]) e o .length funcionam e não são apontados. No client-side (JS de formulário) o padrão por nome funciona e a regra não roda getValue(i, "coluna") — a sugestão sai pronta, com o nome da coluna quando o acesso é por ponto
WF001 erro [requer --process] seção activity-N do formulário sem etapa de sequence N no processo — a seção nunca renderiza e a validação daquela etapa nunca roda. activity-0 é sempre válido (formulário de abertura, WKNumState = 0) a sugestão lista as etapas reais do processo (sequence + nome)
WF002 aviso [requer --process] atividade humana do processo sem seção activity-N no HTML. Só é emitido quando o formulário usa a convenção activity-* adicionar a seção — ou ignorar, se a etapa deve mostrar o formulário igual às demais
WF003 erro [requer --process] o script do processo compara a etapa corrente com um número que não é sequence de nenhuma etapa — o ramo nunca executa a sugestão lista as etapas reais do processo (sequence + nome)

As regras FL* usam a referência fluig.d.ts embutida. Esta referência é um fork do fluig-declaration-type da comunidade. O fluigcli completou o fork com APIs validadas no produto. Nenhuma referência é exaustiva. Por isso os achados FL* são avisos. Corrija no código o typo de verdade. Uma API real que falte na referência é caso de silenciar via severity/ignore. Neste caso, abra uma issue para a API entrar no arquivo.

As regras RHINO* tratam todo JS server-side como o Rhino do Fluig Voyager 2. A detecção do RHINO002 é conservadora. Ela aponta só o inequívoco. Dois casos ficam de fora de propósito para não gerar falso-positivo. O primeiro é a propriedade shorthand { valor } (parece bloco ou destructuring). O segundo é o spread solitário [...a] (igual ao rest de destructuring [...a] = x). Nestes dois casos a análise textual não separa o padrão que quebra do que é suportado.

--process (regras WF*)

Muitos formulários de processo mostram uma seção por etapa. A convenção: cada seção carrega a classe activity-N, com N = sequence da etapa (o WKNumState), e o JS do formulário mostra $(".activity-" + WKNumState).

Os números N vêm do diagrama BPMN e ninguém os decora. Quando eles não casam com o processo, o defeito é invisível: o formulário não renderiza a seção, a validação daquela etapa nunca roda, e nenhum outro comando acusa — o diff passa (local == servidor) e o request start não executa os eventos do formulário. Este foi um defeito real que custou horas em um projeto.

O mesmo vale do outro lado do processo. O script de evento também guarda o número da etapa, quase sempre numa constante no topo da função:

function beforeStateEntry(sequenceId) {
    var cancelaState = 166;
    if (sequenceId == cancelaState) { atualizaMovimento("Cancela"); }

Se 166 não é sequence de nenhuma etapa, o ramo nunca executa. Não há erro no deploy nem em runtime. A condição apenas dá false para sempre. As duas causas comuns são a constante que ficou de uma versão anterior do processo e a constante copiada de outro processo, onde o mesmo passo tem outro número.

O audit --process <id> fecha esse buraco:

  1. A CLI baixa o processo do servidor alvo (só leitura) e lê as etapas reais.
  2. Ela acha o formulário vinculado ao processo pelo forms.json do projeto. Sem o vínculo, a mensagem diz como criar (form import ou form link).
  3. Ela cruza as classes activity-N do HTML com as sequences (WF001/WF002).
  4. Ela cruza os números comparados com a etapa corrente nos scripts workflow/scripts/<id>.*.js (WF003).
fluigcli audit --process contratos_notificacao_vegetacao --json

activity-0 é sempre válido: é o formulário de abertura (antes do primeiro envio, WKNumState vale 0). A checagem usa a versão corrente do processo.

A WF003 reconhece a etapa corrente por duas vias. A primeira é o parâmetro de sequence do evento: sequenceId em beforeStateEntry, beforeStateLeave, afterStateEntry e afterStateLeave; nextSequenceId nos eventos de tarefa; iCurrentState em validateAvailableStates. A segunda é a variável que recebe getValue("WKNumState"), com ou sem parseInt. O número comparado pode ser um literal ou uma constante numérica local. A regra ignora o 0, que é a mesma convenção de "sem etapa" do activity-0.

Duas limitações conscientes. A regra não acusa comparação com literal de texto (sequenceId == "17"), porque essa forma não aparece em código real e incluí-la aumentaria o falso positivo. E ela pula a variável que recebe outro valor em algum ponto do arquivo, para não confundir constante de etapa com o idioma var x = 0; x = calcula();.

Se o prefixo dos scripts locais difere do processId do servidor, a WF003 não acha os arquivos. A CLI avisa em vez de ficar calada. Neste caso, renomeie os arquivos ou rode o audit com o id que os arquivos usam.

O --fix aplica apenas o que não tem ambiguidade. Ele corrige o SG001 (caminho legado → flat). Ele corrige também os SG003 de hex com valor idêntico a uma variável do tema. Neste caso, o render em light não muda e o dark passa a funcionar. Os cinzas aproximados, os rgb() e o resto continuam manuais. O relatório pós-fix mostra o que sobrou. Cada achado corrigível traz o campo fix no --json. Confira o resultado com git diff.

A cor fixa é erro por este motivo: o tema 2.0 troca os valores das variáveis entre os modos light e dark. Um #fff fixo fica branco nos dois modos. Por isso ele quebra o dark mode.

Catálogo

As classes válidas (~2.500) e as variáveis de tema (--fs-color-*) vêm embutidas no binário. O fluigcli extrai estes dados do CSS real de um Fluig 2.0. Com --sync o comando atualiza o catálogo do servidor alvo na hora. O style guide é público e não requer login. Quando o servidor não responde, o comando cai no catálogo embutido com um aviso.

Exceções (.fluigcli/audit.json)

O comando ignora automaticamente os arquivos vendorados minificados (*.min.* ou linha única gigante) e os bundles gerados de widgets SPA (widget new --template vue/react). Para excluir outros caminhos:

{
  "ignore": [
    "wcm/widget/legado_terceiro/",
    "forms/Formulario Congelado/",
    "*.snapshot.css"
  ],
  "severity": {
    "SG005": "off",
    "SG001": "error"
  }
}

Cada entrada de ignore casa por caminho exato, por prefixo de pasta (termina em /) ou por glob no caminho ou no nome do arquivo. O severity muda o nível por regra (error, warning) ou desliga a regra (off). O --json lista o que o comando ignorou.

Baseline (.fluigcli/audit-baseline.json)

Um projeto antigo chega com dívida. O export barra o arquivo por causa de um achado que já estava lá antes da sua mudança. A saída era o --no-audit, que desliga a checagem inteira — inclusive no código que você acabou de escrever.

O baseline resolve isso. Ele grava o retrato dos achados de hoje. Depois disso, o audit e a pré-checagem dos comandos de publish reprovam só os achados novos.

fluigcli audit --save-baseline     # grava .fluigcli/audit-baseline.json
fluigcli audit                     # exit 0: a dívida antiga não reprova mais
fluigcli audit --no-baseline       # confere tudo, ignorando o baseline

Regras:

  • O achado antigo continua no relatório, com o campo baseline: true. O baseline decide o que reprova. Ele não esconde nada.
  • A identidade do achado é o arquivo, a regra e o texto da linha apontada, com os espaços normalizados. O número da linha não entra. Por isso, mover o código ou reindentar o arquivo não invalida o baseline.
  • Linhas de texto idêntico contam. Se o baseline tem duas ocorrências e o arquivo passa a ter três, a terceira reprova.
  • O audit avisa quando achados do baseline somem. É a dívida quitada. Regrave com --save-baseline para o arquivo encolher.
  • Versione o arquivo no Git. Ele é o combinado do time sobre a dívida aceita.

O --no-audit continua existindo, para o caso de precisar publicar sem checagem nenhuma. A diferença é que agora ele não é mais a única saída.

⚠️ Os comandos de publish não têm --no-baseline. Quando o arquivo existe, eles o respeitam. Para o gate estrito, apague o arquivo ou não o crie.

No preview do dev

O fluigcli dev roda esta auditoria automaticamente no preview de cada formulário. Use o botão 🎨 da barra (verde/amarelo/vermelho). O comando reexecuta a auditoria a cada salvamento. Os achados aparecem na tela, com as mesmas sugestões.

No dataset export

O dataset export roda esta auditoria nos arquivos que vai publicar. Um achado de nível error barra o envio daquele arquivo, com o mesmo AUDIT_FAILED. Os avisos não barram nada. A opção --no-audit do export pula a checagem. Com um baseline no projeto, só os achados novos barram.

Exit code e CI

Por padrão a auditoria reprova com exit 1 quando há achados de nível error (--fail-on error). O --fail-on warning é o modo estrito. O --fail-on none sempre retorna 0 (só relatório). No --json, o envelope reprovado vem com error.code = AUDIT_FAILED e o data completo (findings[] com regra/arquivo/linha/sugestão, counts, scanned, ignored). Este formato é ideal para agentes de IA corrigirem em loop e para gates de CI.

Com um baseline no projeto, o exit 1 considera só os achados novos, e o data ganha baseline: {known, new, resolved}. É o modo recomendado em CI de projeto legado: a build falha quando a dívida cresce, não porque ela existe.