Pular para conteúdo

0024 — Slug de registry: nomenclatura, == nome da imagem, ≠ app_id

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-12 · Decidido em: 2026-08-24

Cláusula substituída pela 0038 em 2026-09-21

A cláusula "slug pode ≠ app_id" desta decisão foi substituída: a casa passou a ter uma identidade por app (app_id == slug). A razão registrada aqui — mexer no app_id quebra grants — continua verdadeira, mas só para o app que manda o próprio app_id no login (2 dos 11); a 0038 traz a sequência de migração que resolve isso com janela zero. Todo o resto desta decisão (forma do slug, slug == nome da imagem, slug deriva o nome do recurso Coolify) segue valendo.

Contexto

A 0001 congelou os nomes das pastas de documentação (os seis níveis). O slug do docs/app.json já era o identificador público da casa — pasta no bucket docs-sites/<slug>/, path do site_url, nome do .docx (publicar-docs). O que nunca teve norma é o slug como nome de imagem no registry: com o build native (0022) a CI publica fonte.xadm.biz/xadm/<slug>:native-amd64, e o slug passou a nomear também o artefato de deploy — sem convenção de como formá-lo, nem regra sobre a relação com o app_id.

Na prática, a frota já vinha divergindo: rootProject.name do Gradle não batia com o slug em vários apps (a causa concreta do binário native sair com nome errado — 0022 §imageName), e a consolidação da frota native renomeou apps para um padrão único (ver abaixo). O app_id — a identidade canônica do app no broker/Central de Apps (mesmo namespace dos oauth_grants, Central de Apps) — foi mantido antigo de propósito: mexer nele quebra grants e identidade no broker. Logo, slug ≠ app_id por decisão, não por acidente.

Decisão

O slug do app.json é o identificador único público E o nome da imagem no registry. Sua forma é <cliente_id>-<projeto> (app de cliente) ou <projeto> (app da X-Adm), kebab-case. Pode divergir do app_id.

  • Forma do slug. App da X-Adm (produto): <projeto> (ex. integrador-server). App de cliente (sob medida): <cliente_id>-<projeto> (ex. onpetro-xls, vantroba-xls) — o <cliente_id> é a chave canônica do tenant (0008).
  • Slug == nome da imagem. O slug do app.json é o mesmo nome usado em fonte.xadm.biz/xadm/<slug> (registry) e na pasta docs-sites/<slug>/ (docs). Uma fonte — não se nomeia a imagem por fora (nem por rootProject.name, que diverge). O graalvmNative fixa o binário em application (0022); o slug nomeia a imagem, não o binário.
  • Slug pode ≠ app_id. O app_id é a identidade do app no broker (grants, provisionamento) e é estável — renomear o slug não renomeia o app_id. Um rename de slug (docs + registry) é cosmético/comercial; o app_id segue o mesmo para não quebrar os grants.
  • Nome de projeto de cliente é acordado comercialmente. O <projeto> de um app de cliente é o nome combinado com o cliente (não um apelido interno) — é o que aparece na URL de doc e no registry, então tem peso de marca. Fixá-lo é decisão comercial, registrada aqui como norma.
  • O slug deriva o nome do recurso Coolify. O recurso de deploy no Coolify (o que o control-plane reconcilia, 0026) tem nome calculável do slug, não inventado: <slug>-[<instance>-]<target>-pull, kebab-case. <target> ∈ jar|native|web; -pull marca recurso de control-plane (imagem buildada off-host, o Coolify só puxa — o modo -builder fica fora, deploy.md); <instance> aparece só em app multi-instância (o integrador, deployado por cliente), adjacente ao slug. Os três formatos de recurso caem na mesma fórmula:
  • 1:1 — integrador-sascar-native-pull (um recurso).
  • canário 1:2 — central-backend-jar-pull + central-backend-native-pull (dois target, mesmo domínio; o target desambigua).
  • multi-instância 1:N — integrador-server-maxsul-jar-pull, integrador-server-onpetro-jar-pull (um <instance> por cliente).

O nome de recurso é assim mais um identificador slug-derivado, ao lado da pasta de docs (docs-sites/<slug>/) e da imagem de registry (fonte.xadm.biz/xadm/<slug>). O reconcile casa por esse nome (regra única na deploy.md), nunca por uuid — renomear um recurso é edição in-place do campo name (uuid estável), não um cutover.

Correção 2026-09-12: o reconcile casa pelo slug da imagem (compose: slug do repo git), não pelo nome do recurso — renomear o recurso não exige ação (deploy). Dois recursos no mesmo domínio são a troca blue-green, não um canário permanente (coolify).

Renames aplicados na consolidação da frota native (2026-08-24)

Ação de repo de app (§3), listada para rastro:

Antes Depois Grupo
thoms-webstorm-ecom thoms-webstorm cliente (thoms)
bi-comercial-xls onpetro-xls cliente (onpetro)
bi-transporte-xls vantroba-xls cliente (vantroba)
integrador integrador-server X-Adm
int-sascar integrador-sascar X-Adm

Consequências

  • publicar-docs documenta o slug como nome de imagem. A tabela do app.json ganha a nota "slug == pasta de docs e nome da imagem no registry"; o campo app_id reafirma "pode divergir do slug".
  • Rename de slug é §1.6. O slug é "para sempre" uma vez publicado (a URL de doc e a tag de imagem são contratos). Antes de publicar — ou por acordo comercial explícito — renomear é barato (REGRA Nº 3 / §1.6): move a pasta docs-sites/<slug>/ e a imagem, mantém o app_id.
  • O build native usa o slug. O templates/build-deploy.yml publica fonte.xadm.biz/xadm/<slug>:native-amd64 — trocar <slug> pelo do app.json é o único ajuste de nome no workflow.

Correção 2026-09-12: quem publica a imagem é o job build_<alvo> do pipeline.yml, num runner fora do host de produção; o build-deploy.yml saiu do kit (0027).

Alternativas descartadas

  • Slug == app_id (amarrar registry à identidade do broker). Renomear a imagem/doc forçaria renomear a identidade do broker → quebra de grants. Manter os dois desacoplados custa uma linha de doc e evita quebra em produção.
  • Derivar o nome da imagem do rootProject.name. Foi justamente o que divergiu e quebrou o COPY do binário native (a causa do imageName.set("application") obrigatório). Nome de imagem é o slug, decidido no app.json, não inferido do Gradle.