AUR-500: perfis de revisor prontos
Documento histórico do board. Para uso atual, consulte o guia do produto.
O que é
internal/reviewprofile é o sistema de perfis de revisor embutidos e
versionados: solid, seguranca e performance. Um perfil é um preset
determinístico, nunca um plugin: ele declara apenas o enfoque da review e
as famílias de regra habilitadas, e é resolvido em processo. Nada no pacote
lê arquivo de perfil, abre socket, executa conteúdo de perfil ou deixa um perfil
carregar uma instrução.
Seleção
Um perfil é escolhido por configuração do repositório ou pela flag da review. A flag vence a configuração; uma seleção vazia é o caso zero-config:
res, err := reviewprofile.Resolve(reviewprofile.Selection{
Config: "performance", // .aurumcode/config.yml
Flag: "seguranca", // --perfil / flag da review
})
// res.Profile.Name == "seguranca"
// res.Declared == "profile: seguranca (v1)"
A resolução declara qual perfil entrou (Result.Declared). Um nome desconhecido
é um erro nomeado (ErrUnknownProfile) retornado antes de qualquer chamada ao
modelo. Uma seleção ausente devolve Applied=false e o chamador mantém o
comportamento atual byte a byte.
A fronteira que o perfil nunca cruza
Um perfil pode definir somente enfoque e famílias habilitadas. Ele nunca pode:
- mudar severidade de achado;
- afrouxar o gate de
--fail-on; - desligar a redação de segredos;
- mudar o teto de custo;
- desligar a passagem de segurança determinística.
Uma definição (Spec) que nomeie qualquer uma dessas cláusulas é recusada
em Compile com um ErrRefusedClause que cita a cláusula recusada. O preset
resolvido (Effective) fixa essas fronteiras para todo perfil embutido: passagem
de segurança ligada, redação ligada, severidade/--fail-on intocados, teto de
custo inalterado.
_, err := reviewprofile.Compile([]byte("name: evil\nsecurity_pass: false\n"))
// errors.Is(err, reviewprofile.ErrRefusedClause) == true
// err.Error() cita "security_pass"
A recusa é fail-closed: Compile percorre a árvore YAML crua antes de
ligar a Spec, normaliza cada chave (minúsculas; sem -, _, .) e recusa
qualquer grafia alternativa (security-pass, Security_Pass, security.pass,
redact-secrets, no_redaction, disable_redaction, failOn, cost-cap,
Severity, …), inclusive aliases YAML, security: <desligado> e chaves de
merge (<<: &m {security_pass: false}), que o yaml.v3 resolveria depois do
scan. A ligação usa
KnownFields(true), então uma chave desconhecida restante também falha. O preset
global é imutável: Builtin e Resolve devolvem uma cópia independente de
Effective.Families, de modo que mutar a fatia devolvida não corrompe o
embutido.
Os três embutidos são Specs de código compilados no init: um embutido que
carregasse uma cláusula proibida derrubaria o binário no start (mustBuiltins),
de modo que o programa não inicia com um preset que viole a fronteira.
Determinismo e versão
Cada perfil embutido declara um identificador de versão. Profile.Signature()
cobre nome, versão, enfoque, famílias e instruções: a mesma entrada produz a
mesma assinatura e a mesma lista de regras/instruções habilitadas.
Não-objetivos
Perfis remotos ou baixados, perfis como plugin executável, e perfis que alterem o vocabulário de severidade (isso é AUR-471).