0013 — Analytics (Aptabase): auto-provisão forjando o token de sessão¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-03 · Decidido em: 2026-07-03
Contexto¶
Fase 6 da Central de Apps: a feature analytics. Apps X-Adm (Flutter) usam Aptabase
(self-hosted); a app_key (A-SH-*, pública) era criada na mão e hardcoded. O broker deve
provisionar — mas o Aptabase não tem API de provisão (auth é magic-link/sessão; o
AppsController é [IsAuthenticated], sem API token — verificado na fonte aptabase/aptabase).
Decisão¶
- Aptabase provisiona os eventos da feature
analytics. (À época,analytics = [aptabase]só — o Metabase estava fora. Atualizado pela decisão 0014: o Metabase foi re-escopado para dentro deanalytics, que agora provisiona[aptabase, metabase].) - Auto-provisão forjando o token de sessão. O magic-link do Aptabase é um JWT HS256 assinado
com o
AUTH_SECRET(bytes ASCII; claims{type, name, email, iss:"aptabase-sh", exp}— verificado emAuthTokenManager/EnvSettings). O broker forja um token deRegister(o/continuecria a conta setup se não existe e loga) e abre sessão: - forja o JWT (HS256,
AUTH_SECRET). GET /api/_auth/continue?token=…→ cookie de sessão (sem seguir o redirect).GET /api/_apps→ lista-antes-de-criar (reusa por nome=app_id).POST /api/_apps {name: app_id}→app_key(client-grade →app.json). Sem e-mail, sem log, sem Coolify.- Idempotência: list-before-create no Aptabase + reuso da key persistida no
ProvisioningService(não re-faz o fluxo quando jáligada). - Sem corretor runtime (o app manda eventos direto ao ingest com a app_key pública).
Operar (config no recurso auth)¶
Provisão 100% automática via /xadm-setup (feature analytics) → POST /api/setup/provision.
Não há runbook separado (não há procedimento manual — o broker forja o token e cria/reusa o app).
O operador só liga a feature setando estas envs uma vez no recurso auth (Coolify):
| Variável | Valor | Secret? |
|---|---|---|
APTABASE_ADMIN_URL |
https://aptabase.xadm.biz |
não |
APTABASE_SETUP_EMAIL |
e-mail da conta setup (ex. setup@xadm.biz) — o /continue cria se não existe |
não |
APTABASE_SETUP_NAME |
nome da conta (default X-Adm Setup) |
não |
APTABASE_AUTH_SECRET |
= o AUTH_SECRET do serviço Aptabase (mesmo valor) |
sim ✅ |
Opcional APTABASE_ISS (default aptabase-sh). Ausência das obrigatórias → o provider recusa (boot
ok). Não precisa de APTABASE_COOLIFY_UUID nem de COOLIFY_*.
Pegar o AUTH_SECRET (no host do Coolify, terminal):
docker inspect $(docker ps --filter "name=aptabase" -q | head -1) \
--format '{{json .Config.Env}}' | tr ',' '\n' | grep -i AUTH_SECRET
APTABASE_AUTH_SECRET.
Diagnóstico — o /provision responde providers[].last_error (fail-fast, nunca key falsa):
falha ao forjar o token — AUTH_SECRET < 32 bytes? (secret vazio/curto); continue HTTP 4xx — token
rejeitado (APTABASE_AUTH_SECRET ≠ o real, ou iss errado); GET /_apps … (sessão não abriu?)
(o cookie do /continue não pegou — mudança de versão?).
Alternativas consideradas (a saga)¶
- Login e-mail+senha: inválido — o Aptabase não tem senha (magic-link).
- Manual-register (dev cria na UI + informa a key): funcional, mas o alvo era 100% automático.
- Raspar o magic-link do log do Coolify: inviável — o Aptabase é um Coolify service
(compose) e a API do Coolify não expõe logs de service (só de
application— verificado emroutes/api.php). Descartado. - Forjar o token (escolhido): robusto, independe de logs/infra, funciona pra service.
Consequências / riscos¶
- Segurança — credencial poderosa: o
AUTH_SECRETno env do broker permite forjar sessão de qualquer usuário do Aptabase. Aceito como infra do broker (é o mesmo nível dos outros admin tokens que oauthguarda), mas é o secret mais sensível dessa feature — só no env doauth. - Guardas (endpoints/claims internos, não-documentados): versão do Aptabase fixada
(
main:/api/_auth/continue,/api/_apps, claimtype=Register,iss=aptabase-sh) — reconferir em upgrade. Fail-fast: qualquer passo falho (forja, continue 4xx, sessão, parse) →state=falha+last_error; nunca key falsa (resposta honesta 0.17.6). - Config nova (recurso
auth): ver Operar acima (envs + como pegar oAUTH_SECRET).APTABASE_COOLIFY_UUIDnão é mais necessário. - Lado Flutter (fora do
auth): oclient_configtrazaptabase_key+aptabase_host— a keyA-SH-self-hosted é inútil no cliente sem o host, porque o SDK Flutter exigeInitOptions(host:). O host é o próprioAPTABASE_ADMIN_URL(URL pública da instância; admin e ingestão no mesmo host). O/xadm-setupgrava ambos emfeatures.analyticsnoapp.jsone scaffolda o helper (mirror sulplata); vêm doapp.json, não hardcoded.