.agent/rules/caminho-arquivos-minio.md

4.7 KiB

type name description scope trigger updatedAt
rule caminho-arquivos-minio Padronização obrigatória de caminhos de arquivos persistidos no MinIO em quatro segmentos ({inquilino}/{tabela_origem}/{codigo_origem}/{id}) global model_decision 2026-10-14

Regra: Padronização Obrigatória de Caminhos de Arquivos no MinIO

Contexto

Todos os arquivos persistidos e referenciados no MinIO dentro dos módulos do ecossistema (identificados via modulo-id em memorias-ia/modulo.yml) devem seguir uma estrutura canônica hierárquica e determinística composta por exatamente quatro segmentos:

{inquilino}/{tabela_origem}/{codigo_origem}/{id}

Essa padronização evita colisão de arquivos entre inquilinos ou entidades, permite identificação imediata da origem do arquivo e padroniza a gestão de permissões e storage.


1. Regra de Formato e Validação Canônica

Todo caminho de arquivo enviado para o MinIO deve ser construído via função canônica caminhoMinio exportada pelo pacote <modulo>-comuns (onde <modulo> é extraído de memorias-ia/modulo.yml) e validado por regexCamninhoMinio:

/** Valida quatro segmentos e exige extensão no id. */
export const regexCamninhoMinio = /^[\w$.-]+\/\w+\/[\w.-]+\/[\w.%$-]+\.\w+$(?![\s\S])/

export type CaminhoMinioParams = {
  inquilino: string
  tabela_origem: string
  codigo_origem: string
  id: string
}

export const caminhoMinio = ({
  inquilino,
  tabela_origem,
  codigo_origem,
  id,
}: CaminhoMinioParams): string => {
  const partes = [inquilino, tabela_origem, codigo_origem, id]
  const caminho = partes.join("/")

  if (partes.some((parte) => parte.includes("/")) || !regexCamninhoMinio.test(caminho)) {
    throw new Error("Caminho MinIO inválido")
  }

  return caminho
}

Regras dos Quatro Segmentos

  1. inquilino: Identificador do município / cliente / tenant (ex.: padrao-rs). Não pode conter barras.
  2. tabela_origem: Nome canônico da tabela no banco de dados (ex.: tabelas.licenciamentos, tabelas.denuncias, tabelas.oficios).
  3. codigo_origem: UUID ou identificador único do registro na tabela de origem (ou identificador de escopo como sistema para brasões/ativos globais do tenant).
  4. id: Identificador único do arquivo acompanhado obrigatoriamente de sua extensão (ex.: 01J...pdf, brasao.png, oficio_123.pdf).

2. Persistência Obrigatória no Banco de Dados

É mandatório que toda coluna do banco de dados que armazena referências a arquivos salve a string completa retornada por caminhoMinio (os 4 segmentos unidos por barras).

Exemplos de colunas que armazenam o caminho completo:

  • licencas.codigo_arquivo
  • anexos.codigo_arquivo
  • denuncias.codigo_pdf_documento
  • oficios.codigo_pdf_documento
  • documentos_registros.codigo_pdf_documento
  • auto_de_infracao.codigo_pdf_documento
  • fluxos_recebimentos.codigo_pdf_documento
  • entidades.prefeitura_brasao

⚠️ Atenção: Nunca salve apenas o último segmento (id) de arquivos gerados ou anexados. A string armazenada no banco deve ser a chave completa de 4 segmentos.


3. Upload e Integração com Plugins MinIO

No backend (<modulo>-back):

  • O plugin enviarArquivoMiniO valida o codigoArquivo recebido contra regexCamninhoMinio.
  • Caso codigoArquivo já contenha barras, o plugin reconhece que o inquilino já está incorporado no primeiro segmento e faz o upload direto para essa chave, sem duplicar o prefixo do inquilino.
  • No download ou cache temporário (baixarArquivoMiniO), caso a chave possua barras, o nome do arquivo temporário local em disco deve substituir as barras por underscores (replace(/\//g, "_")) para evitar erros de diretórios inexistentes em /tmp.

4. Miniaturas e Resoluções Gráficas

No caso de imagens que possuem geração de miniaturas (thumbnails via Sharp):

  • A miniatura adiciona o sufixo _y{tamanho} antes da extensão no 4º segmento: {inquilino}/{tabela_origem}/{codigo_origem}/{id_base}_y200.{ext}
  • No frontend (<modulo>-front), helpers como urlArquivoBaixar devem utilizar lastIndexOf(".") para formatar a URL da miniatura mantendo a hierarquia intacta.

5. Compatibilidade Legada

O helper bucket().caminho em <modulo>-comuns é retrocompatível:

  • Se id contém barras (/), ele já representa o caminho estruturado completo e é retornado sem alteração.
  • Se id não contém barras, ele trata como registro legado de 1 segmento e compõe {inquilino}/{id}.

Referências

  • Identidade do Módulo: memorias-ia/modulo.yml
  • <modulo>-comuns/src/minio.ts
  • <modulo>-back/src/plugins/MiniO/enviarArquivoMiniO.ts
  • <modulo>-back/src/plugins/MiniO/baixarArquivoMiniO.ts
  • <modulo>-front/src/api/recursos/arquivos.ts