Skip to content

Regras de Negócio

O Neemias segue 12 regras de negócio que regem o comportamento do sistema em todas as camadas (frontend, backend e sincronização). Estas regras são imutáveis e qualquer decisão de implementação deve respeitá-las.

1. Controle de Acesso Baseado em Papéis (RBAC) — FR-001, FR-002

Quatro papéis — ADMIN, CHAMADOR, RELATORIOS, CADASTRO — com permissões explícitas definidas em fonte única (packages/permissions/index.ts). O ADMIN possui acesso total (17 permissões); os demais papéis são restritos às permissões de sua função.

2. Soft-Delete — FR-007

Nenhuma entidade principal é excluída fisicamente do banco de dados. Alunos, turmas, núcleos e usuários são marcados com status: "DELETED", preservando o histórico completo. A exclusão de alunos exige justificativa obrigatória de 10 a 500 caracteres.

3. Event Sourcing — FR-004

Toda mutação de estado gera um evento imutável. Presenças viram registros na tabela attendance_events; alterações de alunos viram registros na tabela unificada events via createCommandHandlerapplyEvent. O estado atual de cada entidade é uma projeção derivada da cadeia de eventos (backend) ou do SQLite local (frontend). O frontend implementa o EventWriter, que grava o evento e enfileira a sincronização em uma única transação atômica.

4. Offline-First — SR-001

O IndexedDB (via Dexie) é a fonte da verdade local. O usuário trabalha normalmente sem conexão com a internet — todas as operações de leitura e escrita são resolvidas localmente. A sincronização com o backend é automática e usa backoff exponencial quando a conectividade é restaurada.

5. TTL de Sessao (24 horas) — FR-005

A sessão do usuário expira após 24 horas de inatividade. Ao expirar, um modal força a reautenticação antes de qualquer operação protegida. O access token JWT possui TTL de 15 minutos e é renovado via refresh token (7 dias) com rotação automática.

6. Sessao Expirada Bloqueia Chamada — FR-005

A página de chamada (AttendancePage) verifica a validade da sessão antes de permitir qualquer marcação de presença. Com a sessão expirada, o fluxo de chamada é interrompido até que o usuário se reautentique.

7. Criptografia em Repouso

Dados sensíveis armazenados localmente — como changePayload e justificativas de exclusão — são criptografados com AES-GCM utilizando uma chave derivada do hash da senha do usuário (SHA-256 + PBKDF2). Isso protege os dados mesmo que o dispositivo seja comprometido.

8. Resolução de Conflitos na Sincronização

Quando dois eventos conflitantes chegam ao backend, a regra ADMIN_PRECEDENCE decide o vencedor: o evento do papel com maior peso prevalece. Em caso de empate, LAST_TIMESTAMP_WINS. O evento perdedor é marcado com isConflictLoser: true e um ponteiro conflictSupersededBy aponta para o vencedor.

9. Idempotência Obrigatória

Toda mutação (POST/PATCH) exige o header Idempotency-Key. O backend mantém um ledger de idempotência (key, user_id) com hash do payload. Requisições repetidas com a mesma chave e mesmo payload retornam a resposta original; chave igual com payload diferente retorna HTTP 409 Conflict.

10. Telefones: Mínimo 1, Máximo 3

Cada aluno deve ter no mínimo 1 e no máximo 3 números de telefone cadastrados. A validação é aplicada tanto no frontend (TypeScript/Zod) quanto no backend (schemas Zod do worker).

11. E-mail Unico por Usuario — FR-001

O e-mail de cada usuário é único no sistema. A constraint UNIQUE na tabela users garante a unicidade no banco; o frontend valida duplicidade antes do envio.

12. Trilha de Auditoria

Toda operação relevante — login, criação, edição, exclusão, alteração de permissões — gera um registro imutável na tabela audit_logs com correlation_id, actor_user_id, actor_role, endpoint, outcome e detalhes em JSON. Esta trilha atende aos requisitos de rastreabilidade da LGPD.


Fontes: PRD §8 · workers/CONTEXT.md · app/CONTEXT.md

Distribuído sob licença MIT.