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/ewcm/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,WCMAPIe outras). O comando valida estas chamadas contra a referênciafluig.d.tsembutida. Estas regras cobrem tambémdatasets/,events/,mechanisms/eworkflow/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 umnullem 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| 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.
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:
- A CLI baixa o processo do servidor alvo (só leitura) e lê as etapas reais.
- Ela acha o formulário vinculado ao processo pelo
forms.jsondo projeto. Sem o vínculo, a mensagem diz como criar (form importouform link). - Ela cruza as classes
activity-Ndo HTML com as sequences (WF001/WF002). - Ela cruza os números comparados com a etapa corrente nos scripts
workflow/scripts/<id>.*.js(WF003).
fluigcli audit --process contratos_notificacao_vegetacao --jsonactivity-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.
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.
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.
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 baselineRegras:
- 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
auditavisa quando achados do baseline somem. É a dívida quitada. Regrave com--save-baselinepara 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.
--no-baseline. Quando o arquivo existe,
eles o respeitam. Para o gate estrito, apague o arquivo ou não o crie.
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.
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.
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.