Pular para conteúdo

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. Rows sistema=TRUE (ex.: ultimo_nuke) aparecem read-only; POST manual via curl numa chave de sistema retorna 403. Chave nova pela UI nasce sistema=FALSE; chave de sistema só nasce via migration.
  • Sinal de reset: o nuke (etapa 05) faz UPSERT em ultimo_nuke = NOW()::TEXT no FINALIZAR; o cliente Dart compara com o valor guardado em SharedPreferences e, quando muda, persiste o novo valor antes de chamar disconnectAndClear() 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_configuracao sem GRANT ao powersync_role → não sincroniza (42501); consolidado em V13 (decisão 0013).