Pular para conteúdo

0010 — Central de Apps: modelo build-time

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-01 · Decidido em: 2026-07-01

Contexto

O auth evolui de serviço de autenticação para Backend de Central de Apps e Autenticação (plano de controle dos apps da plataforma). O contrato (Camada 1, documentacao/central-de-apps.md + constituição §7) fixou o paradigma build-time: o app declara o que usa no app.json; a skill /xadm-setup provisiona via o auth (que tem os tokens admin dos provedores) e grava o resultado client-grade de volta no app.json (o build embarca). Runtime fica só com os corretores (URLs assinadas). Ver a spec .ia/005-central-de-apps.

Decisão

Modelo de dados novo em db_auth (Flyway V7+):

  • apps — catálogo por app_id canônico (kebab, PK natural). Guarda também slug/repo_url/ production_url/stack/toolchain_json (o dashboard da central deriva os links). grupo xadm|cliente; cliente_id FK→clientes (NULL p/ xadm).
  • app_provider_resources — recurso por (app, provider) (glitchtip|garage|aptabase|metabase), com ciclo desligada→provisionando→ligada|falha, resource_ref/client_config/secret_ref em JSONB. Escopo por app (build-time), não por par.
  • Broker POST /api/setup/provision (JWT xadm_admin) — valida a feature (vocabulário fechado glitchtip|garage|analytics|docs), faz upsert do app, mapeia feature→provider(s) (analytics→ aptabase+metabase; docs→no-op), provisiona idempotente via FeatureProvider e devolve o client-grade.
  • FeatureProvider plugável (uma impl por provider; resolução por nome). Segredos cifrados com AesCipher; corretores runtime assinam derivados expiráveis.
  • Filtros por prefixo disjunto: /api/setup/** (SetupAuthFilter, xadm_admin), /api/apps/** (corretores, JWT do usuário), /api/admin/** (AdminAuthFilter, inalterado).

Consequências

  • JSONB no repo pela 1ª vez — mapeado via @TypeDef(DataType.JSON) sobre Map<String,String>; provado em round-trip com Testcontainers sob Micronaut 5 / serde Jackson 3 (spike da Fase 1).
  • Sem tabela app_pares (o paradigma runtime anterior a tinha): os "pares (cliente, app)" são derivados dos oauth_access_grants distintos; recursos de build são por app.
  • Os oauth_access_grants re-ancoram no catálogo (FK app_id→apps) — acessos de terceiros seguem por (cliente, app).
  • Providers reais (GlitchTip/Garage/Aptabase/Metabase) e a injeção de secret no Coolify entram por fase, cada um investigando a API real antes (não inventar payload).

Alternativas consideradas

  • Paradigma runtime (GET /api/apps/config + token de consumo por par + push de manifesto): descartado na reescrita do contrato — config client-grade é ~estática e cabe no app.json (build-time), evitando boot-fetch e um endpoint/tokens a mais.