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
inquilino: Identificador do município / cliente / tenant (ex.:padrao-rs). Não pode conter barras.tabela_origem: Nome canônico da tabela no banco de dados (ex.:tabelas.licenciamentos,tabelas.denuncias,tabelas.oficios).codigo_origem: UUID ou identificador único do registro na tabela de origem (ou identificador de escopo comosistemapara brasões/ativos globais do tenant).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_arquivoanexos.codigo_arquivodenuncias.codigo_pdf_documentooficios.codigo_pdf_documentodocumentos_registros.codigo_pdf_documentoauto_de_infracao.codigo_pdf_documentofluxos_recebimentos.codigo_pdf_documentoentidades.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
enviarArquivoMiniOvalida ocodigoArquivorecebido contraregexCamninhoMinio. - Caso
codigoArquivojá 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 comourlArquivoBaixardevem utilizarlastIndexOf(".")para formatar a URL da miniatura mantendo a hierarquia intacta.
5. Compatibilidade Legada
O helper bucket().caminho em <modulo>-comuns é retrocompatível:
- Se
idcontém barras (/), ele já representa o caminho estruturado completo e é retornado sem alteração. - Se
idnã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