Skip to content

Sistema de Canary Release — Plano Completo ​

Status: Implementado (Fases 1-6)
Criado em: 2026-03-06
Última atualização: 2026-03-26
Alteração recente: Especialista removido do bypass de feature flags; Admin removido da UI de flags


1. Visão Geral ​

Sistema interno de Release Management com estratégia Canary Release para liberar funcionalidades gradualmente para grupos controlados de escolas antes do rollout geral.

Objetivos ​

  • Controle de deploy do frontend: gerenciar qual versão do app vai ao ar
  • Changelog interno: registrar versões e mudanças para a equipe
  • Feature Flags: ligar/desligar funcionalidades sem novo deploy
  • Controle por escola: liberar features gradualmente, escola por escola
  • Canary Release: validar com grupo piloto antes de promover para todos

2. Arquitetura ​

text
┌─────────────────────────────────────────────────┐
│  Admin Panel: "Releases & Versões"              │
│  ├── Changelog (histórico de versões)           │
│  ├── Feature Flags (toggle de funcionalidades)  │
│  └── Canary Groups (grupos de rollout)          │
└──────────────┬──────────────────────────────────┘
               │
    ┌──────────▼──────────┐
    │   Edge Function     │
    │  release-manager    │
    │  (CRUD + consulta)  │
    └──────────┬──────────┘
               │
    ┌──────────▼──────────────────────────┐
    │  Tabelas Supabase                   │
    │  ├── releases (changelog/versões)   │
    │  ├── feature_flags (flags globais)  │
    │  ├── canary_groups (grupos)         │
    │  ├── canary_group_escolas (vínculo) │
    │  └── feature_flag_canary (flag↔grupo)│
    └─────────────────────────────────────┘
               │
    ┌──────────▼──────────────────────────┐
    │  Frontend                           │
    │  ├── useFeatureFlags() hook         │
    │  ├── FeatureFlagsProvider context   │
    │  └── <FeatureGate> component        │
    └─────────────────────────────────────┘

3. Banco de Dados ​

3.1 Tabela releases — Changelog / Versionamento ​

ColunaTipoDescrição
iduuid PK
versaotext NOT NULL UNIQUEEx: "2.4.0"
titulotext NOT NULLTítulo da release
descricaotextNotas da versão (Markdown)
tipoenum('major','minor','patch','hotfix')Classificação semântica
statusenum('rascunho','canary','liberada','arquivada')Ciclo de vida
publicada_emtimestamptzQuando foi liberada para todos
rollback_snapshotjsonbSnapshot do estado de flags antes da promoção
criado_poruuid FK usuariosAdmin que criou
criado_emtimestamptz DEFAULT now()
atualizado_emtimestamptz DEFAULT now()

3.2 Tabela feature_flags — Flags de Funcionalidade ​

ColunaTipoDescrição
iduuid PK
chavetext UNIQUE NOT NULLEx: "mural_v2", "novo_calendario"
nometext NOT NULLNome legível
descricaotextO que a flag controla
ativa_globalboolean DEFAULT falseLiberada para todos?
release_iduuid FK releases NULLVinculada a qual release
criado_emtimestamptz DEFAULT now()
atualizado_emtimestamptz DEFAULT now()

3.3 Tabela canary_groups — Grupos de Rollout ​

ColunaTipoDescrição
iduuid PK
nometext NOT NULLEx: "Beta Testers", "Escolas Piloto"
descricaotext
ativoboolean DEFAULT true
criado_emtimestamptz DEFAULT now()
atualizado_emtimestamptz DEFAULT now()

3.4 Tabela canary_group_escolas — Escolas em Cada Grupo ​

ColunaTipoDescrição
iduuid PK
canary_group_iduuid FK canary_groups
escola_iduuid FK escolas
adicionada_emtimestamptz DEFAULT now()
UNIQUE(canary_group_id, escola_id)

3.5 Tabela feature_flag_canary — Flags Liberadas por Grupo ​

ColunaTipoDescrição
iduuid PK
feature_flag_iduuid FK feature_flags
canary_group_iduuid FK canary_groups
criado_emtimestamptz DEFAULT now()
UNIQUE(feature_flag_id, canary_group_id)

3.6 Tabela canary_group_usuarios — Usuários em Cada Grupo ​

ColunaTipoDescrição
iduuid PK
canary_group_iduuid FK canary_groups
usuario_iduuid FK usuarios
adicionado_emtimestamptz DEFAULT now()
UNIQUE(canary_group_id, usuario_id)

Uso: Permite canary por usuário individual (ex: especialista ou admin de teste). Usado pelo checkCanaryAccess() em feature-gate.ts.

3.7 RLS ​

  • Todas as tabelas: RLS ativado
  • Somente administrador pode ler/escrever (via RBAC no Edge Function)
  • Consulta de flags ativas usa security definer function para performance

3.8 Feature Gate — Bypass ​

PapelBypass de Feature FlagsBypass de Permissões
administrador✅ Total (BYPASS_ROLES em feature-gate.ts)✅ Menu completo sem filtro
especialista❌ Sujeito a flags (removido do bypass em Mar/2026)N/A (sem tabela de permissões)
escola/coordenador/diretor❌ Sujeito a flags❌ Sujeito a usuarios_escola_permissoes

4. Edge Function: release-manager ​

Actions Autenticadas (papel administrador) ​

ActionDescrição
list_releasesListar releases com paginação
create_releaseCriar nova release
update_releaseAtualizar release existente
list_flagsListar feature flags
create_flagCriar nova flag
update_flagAtualizar flag
toggle_flagToggle ativa_global
list_canary_groupsListar grupos canary
create_canary_groupCriar grupo
update_canary_groupAtualizar grupo
add_escola_to_groupAdicionar escola a grupo
remove_escola_from_groupRemover escola de grupo
assign_flag_to_groupVincular flag a grupo canary
remove_flag_from_groupDesvincular flag de grupo
promote_releaseCanary → Liberada (ativa_global=true para todas flags)
rollback_releaseReverter release (restaura snapshot)

Action Pós-Auth (qualquer papel com escola) ​

ActionDescrição
get_active_flagsRetorna array de chaves ativas para a escola do JWT

Lógica de get_active_flags ​

sql
-- Flags ativas para uma escola específica:
-- 1. Flags com ativa_global = true
-- 2. OU flags vinculadas a um grupo canary que contém a escola
SELECT DISTINCT ff.chave
FROM feature_flags ff
WHERE ff.ativa_global = true
UNION
SELECT DISTINCT ff.chave
FROM feature_flags ff
JOIN feature_flag_canary ffc ON ffc.feature_flag_id = ff.id
JOIN canary_group_escolas cge ON cge.canary_group_id = ffc.canary_group_id
WHERE cge.escola_id = $escola_id;

5. Frontend ​

5.1 Hook useFeatureFlags() ​

typescript
// Carrega flags ativas no boot via get_active_flags
// Cache com React Query (staleTime: 10min)
const { hasFlag, flags, isLoading } = useFeatureFlags();

5.2 Context FeatureFlagsProvider ​

  • Wrapa o app inteiro
  • Carrega flags no boot (após autenticação)
  • Disponibiliza hasFlag() para toda a árvore

5.3 Componente <FeatureGate> ​

tsx
// Renderiza children somente se a flag está ativa
<FeatureGate flag="mural_v2">
  <MuralV2 />
</FeatureGate>

// Com fallback para versão anterior
<FeatureGate flag="mural_v2" fallback={<MuralV1 />}>
  <MuralV2 />
</FeatureGate>

5.4 Painel Admin: seção "Releases" ​

  • Aba Versões: Lista de releases com status, criar/editar, visualizar changelog em Markdown
  • Aba Feature Flags: Tabela de flags, toggle global, ver quais grupos canary têm acesso
  • Aba Grupos Canary: Criar grupos, vincular escolas, vincular flags
  • Ação "Promover": Botão que muda release de canary → liberada
  • Ação "Reverter": Botão que restaura snapshot e desativa flags

6. Fluxo Canary na Prática ​

  1. Admin cria uma Release "v2.5.0" com status rascunho
  2. Cria feature flags: novo_mural, calendario_v2
  3. Vincula flags à release
  4. Cria grupo canary "Escolas Piloto" com 3 escolas
  5. Vincula flags ao grupo canary
  6. Muda status da release para canary
  7. Escolas do grupo passam a ver as funcionalidades via <FeatureGate>
  8. Após validação, clica "Promover para Produção"
    • Sistema salva snapshot do estado atual
    • ativa_global = true para todas as flags da release
    • Status muda para liberada
  9. Todas as escolas passam a ver as funcionalidades
  10. Se algo der errado: "Reverter" restaura o snapshot

7. Inovações Planejadas ​

7.1 Rollout Progressivo Automático (Auto-Promote) — V2.0 ​

Regras configuráveis de promoção automática:

  • "Se 0 erros reportados em 48h no grupo canary → promover"
  • "Se 80% das escolas do grupo acessaram a feature → promover"
  • Percentual progressivo: 5% → 25% → 50% → 100%

7.2 Rollback com Um Clique + Snapshot — Base ​

  • Snapshot JSONB salvo antes de cada promoção
  • Botão "Reverter" restaura estado anterior
  • Histórico de rollbacks visível no changelog

7.3 Métricas de Saúde por Feature Flag — V1.1 ​

  • Engajamento: escolas/usuários que acessaram a feature no grupo canary
  • Erros: falhas de Edge Function correlacionadas com flag ativa
  • Feedback: botão "Reportar problema" visível apenas em canary

7.4 Comunicação Contextual — V1.1 ​

  • Banner canary: "Você está testando uma novidade!"
  • Notificação interna explicando o que mudou
  • Notícia automática no Mural quando release é promovida
  • Tutorial contextual acionado pela flag

7.5 Segmentação Inteligente de Grupos — V1.2 ​

Critérios dinâmicos para grupos:

  • "Todas as escolas com plano Premium"
  • "Escolas com mais de 6 meses de uso"
  • "Escolas com mais de 200 alunos"
  • "Escolas em estado X" (rollout regional)

7.6 Feature Flags com Variantes (A/B Testing) — V2.0 ​

  • Variantes A e B em vez de apenas on/off
  • Cada grupo canary recebe uma variante
  • Métricas de engajamento por variante
  • Promover a variante vencedora

7.7 Dependências entre Flags — V1.2 ​

  • Flag X requer flag Y ativa
  • Impedir desativar Y se X ainda está ativa
  • Árvore de dependências visual

7.8 Portal de Transparência para Escolas — V2.0 ​

Painel read-only para o gestor da escola:

  • "Sua escola está no grupo Beta Testers"
  • "Funcionalidades em teste: Novo Calendário"
  • Changelog das últimas versões
  • Opt-in/opt-out de beta tester

8. Priorização ​

PrioridadeFeatureJustificativa
BaseSistema base (flags + grupos + changelog + promote)Fundação
BaseRollback com um clique + snapshotSegurança operacional
V1.1Comunicação contextual (banner canary + notícia auto)Já têm mural + notificações
V1.1Métricas básicas de engajamentoDados para decisão
V1.2Segmentação dinâmica de gruposEscala
V1.2Dependências entre flagsRobustez
V2.0Auto-promote com regrasAutomação
V2.0A/B Testing com variantesSofisticação
V2.0Portal de transparência para escolasDiferencial

9. Fases de Implementação ​

Fase 1 — Fundação ​

  • [ ] Criar tabelas no banco (releases, feature_flags, canary_groups, canary_group_escolas, feature_flag_canary)
  • [ ] RLS em todas as tabelas
  • [ ] Edge Function release-manager com CRUD completo
  • [ ] Painel admin "Releases" com 3 abas (Versões, Feature Flags, Grupos Canary)
  • [ ] Hook useReleaseManager com React Query

Fase 2 — Integração Frontend ​

  • [x] Hook useFeatureFlags() — wrapper leve sobre AuthContext (sem requests extras)
  • [x] Componente <FeatureGate> — renderização condicional com admin bypass
  • [x] Integração no boot do App — já integrado via AuthContext (canaryFlags + permissoes do /me)
  • [x] Context FeatureFlagsProvider — desnecessário, dados já estão no AuthContext
  • [x] Sync em tempo real via useFeatureFlagSync + Supabase Realtime broadcast
  • [ ] Action promote_release com snapshot (V1.1 — requer tabela releases)
  • [ ] Action rollback_release (V1.1 — requer tabela releases)

Fase 3 — Comunicação & Métricas (V1.1) ​

  • [ ] Banner contextual para escolas em canary
  • [ ] Notícia automática no mural ao promover release
  • [ ] Métricas básicas de engajamento por flag
  • [ ] Botão "Reportar problema" em canary

Fase 4 — Notificações (Pendente) ​

  • [ ] Integrar create_batch no fluxo de toggle de flag
  • [ ] Notificação de desativação planejada (INSERT antecipado)
  • [ ] Notificação de desativação de emergência (pós-toggle)
  • [ ] Mapeamento flag → papéis para destinatários precisos

Status: Documentado, aguardando implementação.

Fase 5 — Escala & Automação (V1.2+) ​

  • [ ] Segmentação dinâmica de grupos
  • [ ] Dependências entre flags
  • [ ] Auto-promote com regras configuráveis
  • [ ] A/B Testing com variantes
  • [ ] Portal de transparência para escolas

10. Arquivos a Criar/Modificar ​

AçãoArquivoStatus
Criarsupabase/functions/release-manager/index.ts⏳ Pendente (Fase 1)
Criarsrc/hooks/useFeatureFlags.ts✅ Criado (Fase 2)
Criarsrc/hooks/useReleaseManager.ts⏳ Pendente (Fase 1)
Criarsrc/components/feature-gate.tsx✅ Criado (Fase 2)
Criarsrc/components/admin-releases.tsx⏳ Pendente (Fase 1)
Criarsrc/contexts/feature-flags-context.tsx❌ Desnecessário — dados integrados ao AuthContext
Modificarsrc/App.tsx (FeatureFlagsProvider)❌ Desnecessário — idem
Modificarsupabase/config.toml (nova function)⏳ Pendente (Fase 1)
Criardocs/architecture/CANARY_RELEASE_SYSTEM.md (este arquivo)✅ Criado

11. Uso no Código ​

tsx
// Proteger uma funcionalidade nova
<FeatureGate flag="novo_mural">
  <MuralV2 />
</FeatureGate>

// Com fallback
<FeatureGate flag="novo_mural" fallback={<MuralV1 />}>
  <MuralV2 />
</FeatureGate>

// Via hook
const { hasFlag } = useFeatureFlags();
if (hasFlag('calendario_v2')) {
  // renderizar versão nova
}