Pular para conteúdo

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:

  1. mudar severidade de achado;
  2. afrouxar o gate de --fail-on;
  3. desligar a redação de segredos;
  4. mudar o teto de custo;
  5. 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).