Etapa 07 — Configuração global sincronizada¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-06
Fornece a tabela KV sincronizada que os clientes e o backend leem em runtime — e o canal do sinal de reset disparado pela etapa 05. A tela de edição é protegida pelo login Google da etapa 06.
1. Contexto e escopo¶
Algumas configurações precisam ser compartilhadas entre o backend e os clientes
móveis em runtime — e o sinal de reset do PowerSync precisa chegar aos celulares.
A solução é uma tabela KV (bi_configuracao) sincronizada via PowerSync,
consumida pelos dois lados.
Dentro do escopo: a tabela KV; o consumo no backend (cache + TTL); as telas
de administração; o sinal de reset (ultimo_nuke); a separação chaves de sistema
vs editáveis.
Fora do escopo: o serviço de reset em si → etapa 05.
2. Modelo de dados¶
bi_configuracao (V12, spec 007) é bi_* (sincroniza via PowerSync, stream
recent_data, priority 0, sem filtro; GRANT ao powersync_role garantido em
V13). A chave é o próprio id (TEXT) — não há surrogate. É a única exceção
à convenção UUID v7 das bi_* (decisão 0008):
PowerSync aceita PK single-column TEXT, e a KV fica mais legível com o id sendo
a própria chave semântica do que com UUID v7 surrogate + UNIQUE(chave).
erDiagram
bi_configuracao {
text id PK "a chave É o id semântico"
text valor "NOT NULL"
varchar tipo "CHECK: STRING|INT|BOOL|TIMESTAMP|JSON"
text descricao
boolean sistema "default FALSE; TRUE = read-only na UI"
timestamptz atualizado_em "default NOW()"
}
Seed (V12, ON CONFLICT (id) DO NOTHING):
id |
tipo |
sistema |
Quem escreve | Quem lê |
|---|---|---|---|---|
ultimo_nuke |
TIMESTAMP |
TRUE |
NukeReplicationService (auto, no FINALIZAR) |
Cliente Flutter |
slow_query_timeout_ms |
INT (10000) |
FALSE |
UI admin | Cliente Flutter |
Convenção de serialização: STRING/JSON cru, INT Integer.toString, BOOL
lowercase, TIMESTAMP ISO 8601. Renomear o id = delete + insert (é a chave
semântica, não surrogate).
3. Fluxos principais¶
- Backend (
service/ConfigService): lê com cache in-memory + TTL 30 s (getString/getInt/getBool/…). Janela máxima de staleness após edição pela UI = 30 s. - Cliente Flutter: lê via PowerSync sync (stream
recent_data). - Telas admin (
/admin/configuracoes, sob login Google — etapa 06): listam, editam e criam chaves. Rowssistema=TRUE(ex.:ultimo_nuke) aparecem read-only; POST manual via curl numa chave de sistema retorna 403. Chave nova pela UI nascesistema=FALSE; chave de sistema só nasce via migration. - Sinal de reset: o nuke (etapa 05) faz UPSERT em
ultimo_nuke = NOW()::TEXTnoFINALIZAR; o cliente Dart compara com o valor guardado emSharedPreferencese, quando muda, persiste o novo valor antes de chamardisconnectAndClear()e reconectar — evita rows zumbi no SQLite local.
4. Decisões¶
| Nº | Decisão |
|---|---|
| 0014 | bi_configuracao KV + sinal de nuke |
| 0008 | PK UUID v7 nas bi_* (KV é a exceção TEXT) |
| 0013 | GRANT ao powersync_role |
5. Riscos¶
- Edição de chave de sistema corromper o sinal → bloqueado na UI (read-only) e no POST (403).
- Staleness de até 30 s no backend após edição → aceitável por design (TTL do cache); documentado.
bi_configuracaosem GRANT aopowersync_role→ não sincroniza (42501); consolidado em V13 (decisão 0013).