Skip to content

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 7 migrações.

Convenções

  • UUIDs são armazenados como TEXT PRIMARY KEY (gerados via crypto.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.

ColunaTipoRestrições
user_idTEXTPRIMARY KEY
emailTEXTUNIQUE NOT NULL
display_nameTEXTNOT NULL
roleTEXTNOT NULL
statusTEXTNOT NULL, DEFAULT 'ACTIVE'
password_hashTEXT
created_atTEXTNOT NULL
updated_atTEXTNOT NULL

students

Alunos cadastrados com dados completos de cadastro.

ColunaTipoRestrições
student_idTEXTPRIMARY KEY
display_nameTEXTNOT NULL
photo_refTEXT
statusTEXTNOT NULL, DEFAULT 'ACTIVE'
created_atTEXTNOT NULL
updated_atTEXTNOT NULL
deleted_justificationTEXT
guardian_nameTEXTNOT NULL, DEFAULT ''
guardian_name_altTEXT
birth_dateTEXTFormato YYYY-MM-DD
phonesTEXTNOT NULL, DEFAULT '[]' (JSON array)
address_streetTEXT
address_numberTEXT
address_complementTEXT
address_neighborhoodTEXT
address_cityTEXT
address_stateTEXT
address_zipTEXT
class_idTEXTREFERENCES classes(class_id)
nucleus_participatesINTEGERNOT NULL, DEFAULT 0
nucleus_regionTEXT
nucleus_nameTEXT
allergiesTEXT
special_needsTEXT
family_membership_statusTEXTNOT NULL, DEFAULT 'DESCONHECIDO'

Í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 turmas padrão.

ColunaTipoRestrições
class_idTEXTPRIMARY KEY
nameTEXTNOT NULL UNIQUE
age_minINTEGER
age_maxINTEGER
statusTEXTNOT NULL, DEFAULT 'ACTIVE'
created_atTEXTNOT NULL
updated_atTEXTNOT 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) organizados por região.

ColunaTipoRestrições
nucleus_idTEXTPRIMARY KEY
regionTEXTNOT NULL
nameTEXTNOT NULL
statusTEXTNOT NULL, DEFAULT 'ACTIVE'
created_atTEXTNOT NULL
updated_atTEXTNOT NULL

Índices:

  • idx_nuclei_region(region, status)

Regiões fixas: Azul Celeste, Azul, Amarela, Branca, Vermelha, Laranja, Verde

attendance_events

Eventos imutáveis de presença (event sourcing). Cada chamada gera um evento.

ColunaTipoRestrições
event_idTEXTPRIMARY KEY
student_idTEXTNOT NULL, REFERENCES students(student_id)
action_typeTEXTNOT NULL (MARK_PRESENT ou MARK_ABSENT)
happened_atTEXTNOT NULL
actor_user_idTEXTNOT NULL
actor_roleTEXTNOT NULL
server_timestampTEXTNOT NULL
is_conflict_loserINTEGERNOT NULL, DEFAULT 0
created_atTEXTNOT NULL

Índices:

  • idx_attendance_events_student_id(student_id, server_timestamp DESC)

student_events

Eventos imutáveis de mutação de alunos (CREATE, UPDATE, DELETE).

ColunaTipoRestrições
event_idTEXTPRIMARY KEY
student_idTEXTNOT NULL, REFERENCES students(student_id)
event_typeTEXTNOT NULL
actor_user_idTEXTNOT NULL
actor_roleTEXTNOT NULL
payloadTEXTNOT NULL (JSON)
server_timestampTEXTNOT NULL
is_conflict_loserINTEGERNOT NULL, DEFAULT 0
created_atTEXTNOT NULL

Índices:

  • idx_student_events_student_id(student_id, server_timestamp DESC)

user_events

Eventos imutáveis de mutação de usuários.

ColunaTipoRestrições
event_idTEXTPRIMARY KEY
target_user_idTEXTNOT NULL, REFERENCES users(user_id)
event_typeTEXTNOT NULL
actor_user_idTEXTNOT NULL
actor_roleTEXTNOT NULL
payloadTEXTNOT NULL (JSON)
server_timestampTEXTNOT NULL
created_atTEXTNOT NULL

auth_refresh_sessions

Sessões de refresh token com rotação e detecção de comprometimento.

ColunaTipoRestrições
session_idTEXTPRIMARY KEY
user_idTEXTNOT NULL, REFERENCES users(user_id) ON DELETE CASCADE
refresh_token_hashTEXTNOT NULL UNIQUE
csrf_tokenTEXTNOT NULL
expires_atTEXTNOT NULL
revoked_atTEXT
replaced_byTEXTREFERENCES auth_refresh_sessions(session_id)
rotated_atTEXT
suspected_compromise_atTEXT
created_atTEXTNOT 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 detectar replay de mutações.

ColunaTipoRestrições
keyTEXTPRIMARY KEY (composta com user_id)
user_idTEXTPRIMARY KEY (composta com key)
payload_hashTEXTNOT NULL
status_codeINTEGERNOT NULL
response_bodyTEXTNOT NULL (JSON)
created_atTEXTNOT NULL

Índices:

  • idx_idempotency_ledger_created_at(created_at DESC)

audit_logs

Trilha de auditoria para conformidade LGPD.

ColunaTipoRestrições
audit_idTEXTPRIMARY KEY
correlation_idTEXTNOT NULL
actor_user_idTEXTNOT NULL
actor_roleTEXTNOT NULL
endpointTEXTNOT NULL
outcomeTEXTNOT NULL
detailsTEXTNOT NULL (JSON)
created_atTEXTNOT NULL

roles

Catálogo de roles com permissões granulares.

ColunaTipoRestrições
nameTEXTPRIMARY KEY
display_nameTEXTNOT NULL
permissionsTEXTNOT NULL, DEFAULT '[]' (JSON array)
is_systemINTEGERNOT NULL, DEFAULT 0
created_atTEXTNOT NULL
updated_atTEXTNOT NULL

Seed (4 roles de sistema, is_system=1):

RolePermissões
ADMINattendance, reports, students.*, users.*, settings, import-export, sessions.*, nuclei.manage, classes.manage
CHAMADORattendance, students.search
RELATORIOSreports, students.search
CADASTROstudents.add, students.search, sessions.add, sessions.edit, nuclei.manage, classes.manage

rate_limits

Controle de rate limiting baseado em D1.

ColunaTipoRestrições
keyTEXTPRIMARY KEY
countINTEGERNOT NULL, DEFAULT 1
window_startINTEGERNOT NULL
expires_atINTEGERNOT NULL

Histórico de Migrações

MigraçãoArquivoDescrição
00010001_init.sqlSchema core: users, students, attendance_events, student_events, user_events, idempotency_ledger, audit_logs + índices
00020002_auth_sessions.sqlTabela auth_refresh_sessions com rotação e revogação
00030003_student_fields.sqlExpansão de students (guardião, telefones, endereço) + novas tabelas classes e nuclei + seed de turmas
00040004_family_membership.sqlColuna family_membership_status em students
00050005_compromise_detection.sqlColuna suspected_compromise_at em auth_refresh_sessions
00060006_roles.sqlTabela roles + seed dos 4 papéis do sistema
00070007_rate_limits.sqlTabela rate_limits para controle de taxa

Fonte: migrations/0001_init.sql até 0007_rate_limits.sql

Distribuído sob licença MIT.