Schema do Banco D1
O banco de dados do Neemias é um SQLite gerenciado pelo Cloudflare D1. As migrações são aplicadas sequencialmente na pasta migrations/. Abaixo, o schema completo após todas as 26 migrações.
Modelo de escrita atual (v0.62+): o check-in/check-out é o fluxo de presença real —
check_in_events(0022) substituiuattendance_events(drop em 0023). O event-sourcing unificado usa a tabelaevents(0010); as tabelas legadasstudent_events/user_eventsforam aposentadas (0026).
Convenções
- UUIDs são armazenados como
TEXT PRIMARY KEY(gerados viacrypto.randomUUID()) - Timestamps usam formato ISO 8601 (
TEXT) - Booleanos são
INTEGER(0 = false, 1 = true) - JSON é armazenado como
TEXT(serializado) - Soft-delete usa coluna
status(ACTIVE|DELETED)
Tabelas
users
Usuários do sistema com autenticação PBKDF2 (two-pass, ADR-0031).
| Coluna | Tipo | Constraints |
|---|---|---|
user_id | TEXT | PRIMARY KEY |
email | TEXT | UNIQUE NOT NULL |
display_name | TEXT | NOT NULL |
username | TEXT | (0013 — autenticação OTP) |
status | TEXT | NOT NULL, DEFAULT 'ACTIVE' |
password_hash | TEXT | |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
v0.56.0: a coluna
rolefoi removida (0019) — papéis agora vivem emuser_roles.
user_roles
Tabela de junção usuário↔papel para suporte multi-role (v0.56.0+).
| Coluna | Tipo | Constraints |
|---|---|---|
user_id | TEXT | NOT NULL, REFERENCES users(user_id) |
role | TEXT | NOT NULL, CHECK IN (ADMIN, CHAMADOR, RELATORIOS, CADASTRO, RESPONSAVEL, VOLUNTARIO, COORDENACAO_KIDS, ADMINISTRATIVO_KIDS) |
Primary key: composta (user_id, role).
students
Alunos cadastrados com dados completos de cadastro.
| Coluna | Tipo | Constraints |
|---|---|---|
student_id | TEXT | PRIMARY KEY |
display_name | TEXT | NOT NULL |
photo_ref | TEXT | |
status | TEXT | NOT NULL, DEFAULT 'ACTIVE' |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
deleted_justification | TEXT | |
created_by | TEXT | NOT NULL, DEFAULT '' (0020) |
image_consent_id | TEXT | (0020 — opt-in de consentimento) |
guardian_name | TEXT | NOT NULL, DEFAULT '' |
guardian_name_alt | TEXT | |
birth_date | TEXT | formato YYYY-MM-DD |
phones | TEXT | NOT NULL, DEFAULT '[]' (array JSON) |
address_street | TEXT | |
address_number | TEXT | |
address_complement | TEXT | |
address_neighborhood | TEXT | |
address_city | TEXT | |
address_state | TEXT | |
address_zip | TEXT | |
class_id | TEXT | REFERENCES classes(class_id) |
nucleus_participates | INTEGER | NOT NULL, DEFAULT 0 |
nucleus_region | TEXT | |
nucleus_name | TEXT | |
allergies | TEXT | |
special_needs | TEXT | |
family_membership_status | TEXT | NOT NULL, DEFAULT 'DESCONHECIDO' |
Campos sociodemográficos (0008, pastorais — todos opcionais):
| Coluna | Tipo | Default |
|---|---|---|
family_structure | TEXT | 'DESCONHECIDO' |
lives_with | TEXT | |
siblings_count | INTEGER | |
economic_vulnerability | TEXT | 'DESCONHECIDO' |
cps_involvement | INTEGER | (1=true, 0=false, NULL=desconhecido) |
domestic_violence | TEXT | 'DESCONHECIDO' |
school_status | TEXT | 'DESCONHECIDO' |
family_notes | TEXT | |
child_atypical_notes | TEXT |
Índices:
idx_students_status_updated_at—(status, updated_at DESC)
Valores de family_membership_status: MEMBRO, NAO_MEMBRO, DESCONHECIDO
classes
Turmas por faixa etária, com seed de 7 classes padrão.
| Coluna | Tipo | Constraints |
|---|---|---|
class_id | TEXT | PRIMARY KEY |
name | TEXT | NOT NULL UNIQUE |
age_min | INTEGER | |
age_max | INTEGER | |
status | TEXT | NOT NULL, DEFAULT 'ACTIVE' |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
Índices:
idx_classes_status—(status, name)
Seed: Berçário (1-2), Maternal Infantil (3), Jardim de Infância (4-5), Infantil (6), Juniores 1 (7), Juniores 2 (8), Pré-Adolescentes (9-11)
nuclei
Núcleos (células/pequenos grupos) organizados por região.
| Coluna | Tipo | Constraints |
|---|---|---|
nucleus_id | TEXT | PRIMARY KEY |
region | TEXT | NOT NULL |
name | TEXT | NOT NULL |
status | TEXT | NOT NULL, DEFAULT 'ACTIVE' |
created_at | TEXT | NOT NULL, DEFAULT datetime('now') |
updated_at | TEXT | NOT NULL, DEFAULT datetime('now') |
Índices:
idx_nuclei_region—(region)idx_nuclei_status—(status)
A tabela foi recriada com defaults
datetime('now')na migração 0023 (schema espelhandoNUCLEI_MIGRATION_SQLdo módulo nucleus).
guardians
Vínculo de usuários responsáveis (papel RESPONSAVEL) aos seus alunos. Alimenta o sistema de escopo (ADR-0016).
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
user_id | TEXT | NOT NULL |
student_id | TEXT | NOT NULL |
relationship | TEXT | NOT NULL, DEFAULT 'outro' — CHECK IN (pai,mãe,avô,avó,tio,tia,outro) |
created_at | TEXT | NOT NULL |
Índices: idx_guardians_user (user_id) · idx_guardians_student (student_id) — UNIQUE (user_id, student_id)
class_assignments
Vínculo de voluntários/professores (papel VOLUNTARIO) às suas turmas. Alimenta o sistema de escopo (ADR-0016).
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
user_id | TEXT | NOT NULL |
class_id | TEXT | NOT NULL |
role | TEXT | NOT NULL, DEFAULT 'voluntario' — CHECK IN (professor,voluntario,auxiliar) |
created_at | TEXT | NOT NULL |
Índices: idx_class_assignments_user (user_id) · idx_class_assignments_class (class_id) — UNIQUE (user_id, class_id)
check_in_events
Registros imutáveis de check-in/check-out (event sourcing, ADR-0026). Cada check-in gera um código diário determinístico HMAC(church_secret, student_id + session_id + date) — o código não é armazenado, é calculado sob demanda.
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
student_id | TEXT | NOT NULL, FK → students |
session_id | TEXT | NOT NULL, FK → class_sessions |
event_type | TEXT | NOT NULL — CHECK_IN | CHECK_OUT | CHECKOUT_ATTEMPT | EMERGENCY_CHECKOUT |
daily_code | TEXT | código de 6 chars (só CHECK_IN) |
actor_user_id | TEXT | NOT NULL |
actor_role | TEXT | NOT NULL |
pickup_person | TEXT | nome do responsável (CHECK_OUT / EMERGENCY) |
pickup_phone_suffix | TEXT | últimos 4 dígitos verificados |
attempt_code | TEXT | código tentado (só CHECKOUT_ATTEMPT) |
attempt_number | INTEGER | contador de tentativas (1-based) |
override_reason | TEXT | justificativa (EMERGENCY ou admin-forced) |
created_at | TEXT | NOT NULL — timestamp ISO-8601 |
Índices:
idx_checkin_events_student—(student_id, created_at)idx_checkin_events_session—(session_id, created_at)idx_checkin_active— UNIQUE PARCIAL(student_id, session_id) WHERE event_type = 'CHECK_IN'(um check-in ativo por aluno/sessão)
class_slots
Espelha os slots de aula do IndexedDB no D1 (sync bidirecional e relatórios).
| Coluna | Tipo | Constraints |
|---|---|---|
slot_id | TEXT | PRIMARY KEY |
day_of_week | INTEGER | NOT NULL — 0=domingo .. 6=sábado |
start_time | TEXT | NOT NULL — "HH:MM" |
label | TEXT | NOT NULL |
session_date | TEXT | opcional (vagas avulsas) |
status | TEXT | NOT NULL, DEFAULT 'ACTIVE' |
capacity | INTEGER | NOT NULL, DEFAULT 0 (0018) |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
Índices: idx_class_slots_status (status)
class_sessions
Sessões de aula (semanais ou avulsas) referenciadas pelo check-in.
| Coluna | Tipo | Constraints |
|---|---|---|
session_id | TEXT | PRIMARY KEY |
slot_id | TEXT | NOT NULL, FK → class_slots(slot_id) |
session_date | TEXT | NOT NULL |
created_at | TEXT | NOT NULL |
Índices: idx_class_sessions_slot (slot_id, session_date) · idx_class_sessions_date (session_date)
session_capacity
Contagem de capacidade por sessão (dashboard de capacidade ao vivo, SDD-149).
| Coluna | Tipo | Constraints |
|---|---|---|
session_id | TEXT | PRIMARY KEY |
slot_id | TEXT | NOT NULL |
total_spots | INTEGER | NOT NULL, DEFAULT 0 |
occupied | INTEGER | NOT NULL, DEFAULT 0 |
updated_at | TEXT | NOT NULL |
Índices: idx_session_capacity_slot (slot_id, updated_at)
student_credentials
Carteirinha permanente do aluno (QR/barcode, issue #467) — separada dos códigos diários de check-in.
| Coluna | Tipo | Constraints |
|---|---|---|
credential_id | TEXT | PRIMARY KEY |
student_id | TEXT | NOT NULL, FK → students |
credential_value | TEXT | NOT NULL UNIQUE |
format | TEXT | NOT NULL, DEFAULT 'QR' — 'QR' | 'BARCODE' |
label | TEXT | DEFAULT '' |
issued_by | TEXT | NOT NULL (actor_user_id) |
issued_at | TEXT | NOT NULL |
revoked_at | TEXT | (soft-revoke; nunca reutilizado) |
Índices: idx_student_credentials_student (student_id, revoked_at) · idx_student_credentials_value (credential_value)
waiting_list
Fila FIFO de responsáveis quando a turma está cheia (issue #567).
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
class_id | TEXT | NOT NULL, FK → classes(class_id) |
guardian_id | TEXT | NOT NULL, FK → guardians(id) |
child_id | TEXT | NOT NULL, FK → students |
created_at | TEXT | NOT NULL |
notified | INTEGER | NOT NULL, DEFAULT 0 |
Índices: idx_waiting_list_class (class_id, created_at) — UNIQUE (class_id, child_id)
onboarding_links
Links únicos de auto-onboarding gerados pelo admin para pais/responsáveis.
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
class_id | TEXT | NOT NULL |
created_by | TEXT | NOT NULL |
hash | TEXT | NOT NULL UNIQUE |
expires_at | TEXT | NOT NULL |
max_uses | INTEGER | NOT NULL, DEFAULT 1 |
use_count | INTEGER | NOT NULL, DEFAULT 0 |
is_active | INTEGER | NOT NULL, DEFAULT 1 |
created_at | TEXT | NOT NULL |
Índices: idx_onboarding_links_hash (hash)
onboarding_drafts
Rascunhos de cadastro submetidos pelos pais, pendentes de aprovação.
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
hash | TEXT | NOT NULL |
class_id | TEXT | NOT NULL |
invited_by | TEXT | NOT NULL |
expires_at | TEXT | NOT NULL |
guardian_phone | TEXT | |
guardian_email | TEXT | |
otp_hash | TEXT | |
otp_attempts | INTEGER | NOT NULL, DEFAULT 0 |
otp_expires_at | TEXT | |
otp_verified_at | TEXT | |
student_data | TEXT | NOT NULL (JSON) |
consent_lgpd | INTEGER | NOT NULL, DEFAULT 0 |
consent_image | INTEGER | NOT NULL, DEFAULT 0 |
status | TEXT | NOT NULL, DEFAULT 'PENDING' — CHECK IN (PENDING,APPROVED,REJECTED,EXPIRED) |
reviewed_by | TEXT | |
reviewed_at | TEXT | |
review_notes | TEXT | |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
Índices: idx_onboarding_drafts_hash (hash) · idx_onboarding_drafts_status (status) · idx_onboarding_drafts_class (class_id)
events
Tabela unificada de event-sourcing (append-only) — fonte única da verdade para eventos imutáveis. Substitui as tabelas legadas student_events/user_events (aposentadas em 0026).
| Coluna | Tipo | Constraints |
|---|---|---|
event_id | TEXT | PRIMARY KEY (UUID — chave de idempotência) |
entity_type | TEXT | NOT NULL — STUDENT | ATTENDANCE | CLASS | ... |
entity_id | TEXT | NOT NULL |
version | INTEGER | NOT NULL — monotônico por (entity_type, entity_id) |
action_type | TEXT | NOT NULL — CREATED | UPDATED | DELETED | RESTORED |
payload | TEXT | NOT NULL (JSON — delta dos campos) |
actor_id | TEXT | NOT NULL |
actor_role | TEXT | NOT NULL (auditoria) |
justification | TEXT | (obrigatório para DELETED) |
created_at | TEXT | NOT NULL, DEFAULT datetime('now') |
Índices: uniq_events_entity_version UNIQUE (entity_type, entity_id, version) · idx_events_actor (actor_id) · idx_events_created (created_at)
A partir da migração
0016_events_unique_entity_version.sql, a unicidade de(entity_type, entity_id, version)é garantida pelo banco, não só pela checagem de aplicação emapplyEvent. O índice não-únicoidx_events_entityfoi derrubado ao mesmo tempo — o único cobre os mesmos planos de consulta. É o que fecha a janela read-then-write: dois pedidos concorrentes podiam ler a mesma versão máxima e gravar a mesma versão seguinte.
church_events
Eventos da igreja com capacidade, preço e suporte a recorrência (SDD-153 §3).
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
title | TEXT | NOT NULL |
description | TEXT | |
date_start | TEXT | NOT NULL |
date_end | TEXT | |
location | TEXT | |
capacity | INTEGER | NOT NULL, DEFAULT 0 (0 = ilimitado) |
price_in_cents | INTEGER | NOT NULL, DEFAULT 0 (0 = grátis) |
pix_key | TEXT | |
pix_qr_code | TEXT | |
status | TEXT | NOT NULL, DEFAULT 'DRAFT' — CHECK IN (DRAFT,OPEN,CLOSED,CANCELLED,FINISHED) |
recurrence | TEXT | JSON: { type, interval, count, until } |
template_id | TEXT | |
church_id | TEXT | NOT NULL, DEFAULT 'default' |
created_by | TEXT | NOT NULL |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
Índices: idx_church_events_status (status) · idx_church_events_church (church_id)
event_registrations
Inscrições públicas em eventos com fila de aprovação e status de pagamento.
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
event_id | TEXT | NOT NULL, FK → church_events(id) |
student_id | TEXT | NULL se não-cadastrado |
guardian_name | TEXT | NOT NULL |
guardian_phone | TEXT | NOT NULL |
guardian_email | TEXT | |
participant_name | TEXT | NOT NULL |
participant_age | INTEGER | |
allergies | TEXT | |
special_needs | TEXT | |
referral | TEXT | "Quem te falou?" |
heard_from | TEXT | "Onde ouviu falar?" |
payment_proof | TEXT | URL R2 |
payment_status | TEXT | NOT NULL, DEFAULT 'PENDING' — CHECK IN (PENDING,PAID,WAIVED,REFUNDED) |
status | TEXT | NOT NULL, DEFAULT 'PENDING' — CHECK IN (PENDING,APPROVED,REJECTED,WAITING_LIST,CANCELLED,CONFIRMED) |
reviewed_by | TEXT | |
reviewed_at | TEXT | |
review_notes | TEXT | |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
Índices: idx_registrations_event (event_id) · idx_registrations_status (status) · idx_registrations_payment (payment_status)
notifications
Feed de notificações para telão (SSE polling, SDD-146).
| Coluna | Tipo | Constraints |
|---|---|---|
id | TEXT | PRIMARY KEY |
church_id | TEXT | NOT NULL, DEFAULT 'default' |
type | TEXT | NOT NULL, DEFAULT 'alert' — CHECK IN (alert,info,emergency) |
child_name | TEXT | NOT NULL |
child_age | INTEGER | |
message | TEXT | NOT NULL, DEFAULT 'Procure a recepção kids' |
created_by | TEXT | NOT NULL |
created_at | TEXT | NOT NULL |
read_at | TEXT |
Índices: idx_notifications_church (church_id, created_at)
church_settings
Configurações do feed da igreja.
| Coluna | Tipo | Constraints |
|---|---|---|
church_id | TEXT | PRIMARY KEY, DEFAULT 'default' |
feed_token | TEXT | NOT NULL, DEFAULT '' |
broadcast_enabled | INTEGER | NOT NULL, DEFAULT 0 |
checkin_secret | TEXT | NOT NULL, DEFAULT '' (0022 — derivação de códigos diários) |
church_config
Store chave-valor de configurações por igreja (modo de pickup, override de emergência, limites de tentativa, labels).
| Coluna | Tipo | Constraints |
|---|---|---|
church_id | TEXT | NOT NULL, FK → church_settings(church_id) |
config_key | TEXT | NOT NULL |
config_value | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
Primary key: composta (church_id, config_key) — adicionar uma opção é um INSERT, sem migração.
auth_refresh_sessions
Sessões de refresh token com rotação e detecção de comprometimento.
| Coluna | Tipo | Constraints |
|---|---|---|
session_id | TEXT | PRIMARY KEY |
user_id | TEXT | NOT NULL, REFERENCES users(user_id) ON DELETE CASCADE |
refresh_token_hash | TEXT | NOT NULL UNIQUE |
csrf_token | TEXT | NOT NULL |
expires_at | TEXT | NOT NULL |
revoked_at | TEXT | |
replaced_by | TEXT | REFERENCES auth_refresh_sessions(session_id) |
rotated_at | TEXT | |
suspected_compromise_at | TEXT | |
created_at | TEXT | NOT NULL |
Índices:
idx_auth_refresh_sessions_user_id—(user_id, created_at DESC)idx_auth_refresh_sessions_expires_at—(expires_at)
idempotency_ledger
Registro de idempotência para detecção de replay de mutações.
| Coluna | Tipo | Constraints |
|---|---|---|
key | TEXT | PRIMARY KEY (composta com user_id) |
user_id | TEXT | PRIMARY KEY (composta com key) |
payload_hash | TEXT | NOT NULL |
status_code | INTEGER | NOT NULL |
response_body | TEXT | NOT NULL (JSON) |
created_at | TEXT | NOT NULL |
Índices:
idx_idempotency_ledger_created_at—(created_at DESC)
audit_logs
Trilha de auditoria para conformidade LGPD.
| Coluna | Tipo | Constraints |
|---|---|---|
audit_id | TEXT | PRIMARY KEY |
correlation_id | TEXT | NOT NULL |
actor_user_id | TEXT | NOT NULL |
actor_role | TEXT | NOT NULL |
endpoint | TEXT | NOT NULL |
outcome | TEXT | NOT NULL |
details | TEXT | NOT NULL (JSON) |
created_at | TEXT | NOT NULL |
roles
Catálogo de papéis com permissões granulares.
| Coluna | Tipo | Constraints |
|---|---|---|
name | TEXT | PRIMARY KEY |
display_name | TEXT | NOT NULL |
permissions | TEXT | NOT NULL, DEFAULT '[]' (array JSON) |
is_system | INTEGER | NOT NULL, DEFAULT 0 |
status | TEXT | NOT NULL, DEFAULT 'ACTIVE' (0021 — soft-delete) |
deleted_at | TEXT | (0021) |
deleted_by | TEXT | (0021) |
created_at | TEXT | NOT NULL |
updated_at | TEXT | NOT NULL |
Seed (papéis de sistema, is_system=1): ADMIN, CHAMADOR, RELATORIOS, CADASTRO, VOLUNTARIO, COORDENACAO_KIDS, ADMINISTRATIVO_KIDS, RESPONSAVEL (0017; VOLUNTEER/VOLUNTARIO_KIDS fundidos em VOLUNTARIO na 0018_merge). Lista completa em packages/permissions/index.ts.
rate_limits
Controle de rate limiting baseado em D1.
| Coluna | Tipo | Constraints |
|---|---|---|
key | TEXT | PRIMARY KEY |
count | INTEGER | NOT NULL, DEFAULT 1 |
window_start | INTEGER | NOT NULL |
expires_at | INTEGER | NOT NULL |
Tabelas removidas
| Tabela | Removida em | Substituída por |
|---|---|---|
attendance_events | 0023 (drop) | check_in_events (0022) — o check-in/check-out substituiu a marcação de presença (issue #477) |
student_events | 0026 (retire) | events (0010) — event-sourcing unificado (#608) |
user_events | 0026 (retire) | events (0010) — event-sourcing unificado (#608) |
Histórico de Migrações
⚠️ Consolidado no v1.0.0 (2026-08-12): as migrações
0001–0029(incl. os0018/0023duplicados e obackfill-events.sql) foram substituídas por uma única baseline —migrations/0001_init.sql— equivalente ao schema final (export do D1 remoto pós-0029). A tabela abaixo é histórico (o que cada migração pré-1.0 fazia); bancos novos aplicam somente a baseline e migrações futuras começam em0002. Verdocs/operations/migrations.md.
| Migração | Arquivo | Descrição |
|---|---|---|
| 0001 | 0001_init.sql | Schema core: users, students, attendance_events, student_events, user_events, idempotency_ledger, audit_logs + índices |
| 0002 | 0002_auth_sessions.sql | Tabela auth_refresh_sessions com rotação e revogação |
| 0003 | 0003_student_fields.sql | Expansão de students (guardião, telefones, endereço) + novas tabelas classes e nuclei + seed de classes |
| 0004 | 0004_family_membership.sql | Coluna family_membership_status em students |
| 0005 | 0005_compromise_detection.sql | Coluna suspected_compromise_at em auth_refresh_sessions |
| 0006 | 0006_roles.sql | Tabela roles + seed dos 4 papéis de sistema |
| 0007 | 0007_rate_limits.sql | Tabela rate_limits para controle de rate |
| 0008 | 0008_sociodemographic.sql | Campos sociodemográficos em students (9 campos pastorais) |
| 0009 | 0009_atomic_token_rotation.sql | Rotação atômica de refresh token com detecção de comprometimento |
| 0010 | 0010_events.sql | Tabela unificada events de event-sourcing (append-only) |
| 0011 | 0011_class_slots_sessions.sql | class_slots e class_sessions (semanais + avulsas) |
| 0012 | 0012_onboarding.sql | Fila de aprovação de onboarding de pais + links de registro (onboarding_links, onboarding_drafts) |
| 0013 | 0013_username.sql | Coluna username em users para autenticação OTP |
| 0014 | 0014_guardians.sql | guardians + class_assignments (sistema de escopo, ADR-0016) |
| 0015 | 0015_events.sql | church_events + event_registrations (eventos com capacidade, preço e aprovação) |
| 0016 | 0016_notifications.sql | notifications (feed SSE) + church_settings |
| 0017 | 0017_roles_seed.sql | Seed de papéis de sistema adicionais (VOLUNTARIO, RESPONSAVEL, etc.) |
| 0018 | 0018_capacity.sql + 0018_merge_voluntario.sql | Limites de capacidade em class_slots + session_capacity; merge VOLUNTEER/VOLUNTARIO_KIDS → VOLUNTARIO (#362) |
| 0019 | 0019_user_roles.sql | Tabela user_roles (multi-role). DROP COLUMN users.role. Migra papéis existentes. |
| 0020 | 0020_student_columns.sql | Colunas created_by e image_consent_id em students (projeção event-sourcing, #391) |
| 0021 | 0021_role_soft_delete.sql | Soft-delete em roles (status, deleted_at, deleted_by) — convergência de papéis (Fase 4) |
| 0022 | 0022_check_in.sql | check_in_events + church_config + church_settings.checkin_secret — check-in/check-out com códigos diários (#144, ADR-0026) |
| 0023 | 0023_drop_attendance.sql + 0023_nuclei.sql | Drop de attendance_events (#477); recriação de nuclei com defaults (módulo nucleus, #478) |
| 0024 | 0024_student_credentials.sql | student_credentials — carteirinha permanente QR/barcode (#467) |
| 0025 | 0025_waiting_list.sql | waiting_list — fila FIFO quando a turma está cheia (#567) |
| 0026 | 0026_retire_legacy_events.sql | Aposenta student_events/user_events — todo write-path usa events (#608) |
Total: 26 migrações (0001–0026) no período pré-1.0 — squashed em
0001_init.sqlno v1.0.0.0018_merge_voluntario.sqle0023_nuclei.sqleram migrações companheiras ao lado de0018_capacity.sqle0023_drop_attendance.sql.
Fonte: migrations/