Arquitetura de Software — Decisões ASRs¶
Versão: 1.0 Escopo: Documento único contendo todos os ASRs do projeto.
Requisitos de CRUD simples e baixo risco (ex.: RF-004, RF-008, RF-012, RF-015, RF-016) foram deliberadamente deixados de fora, por não gerarem decisão arquitetural própria.
Sistema de Autenticação¶
ASR-001¶
<Backward: RF-017, RF-018- Preocupação: Armazenamento e comparação de senha são pontos de falha crítica de segurança — qualquer erro de implementação (hash fraco, comparação de texto puro, ausência de salt) compromete todas as contas do sistema.
- Decisão rápida: Usar algoritmo de hashing adequado a senhas (bcrypt ou Argon2) com salt individual por usuário, via biblioteca madura da linguagem escolhida; nunca logar, comparar ou trafegar a senha em texto puro em nenhuma camada.
ASR-002¶
<Backward: RF-019- Preocupação: A proteção contra força bruta exige contagem de tentativas falhas e bloqueio temporário por conta, sem degradar a performance do fluxo de login legítimo.
- Decisão rápida: Contador de tentativas persistido junto ao registro do usuário (coluna dedicada) para o volume esperado do MVP, com TTL de bloqueio (ex.: 15 min) resolvido por timestamp, evitando dependência de infraestrutura extra (Redis) nesta versão.
ASR-003¶
<Backward: RF-021- Preocupação: O modelo híbrido de sessão (Access Token JWT stateless + Refresh Token opaco persistido) é a espinha dorsal de segurança de todo o sistema e precisa suportar múltiplas sessões por dispositivo com revogação granular.
- Decisão rápida: Tabela
sessionsarmazenando apenas o hash do refresh token, associada auser_idedevice/user-agent; Access Token JWT curto (~15 min) nunca persistido; ambos transportados via cookiehttpOnly,Secure,SameSite.
ASR-004¶
<Backward: RNF-002- Preocupação: A exigência de sessão válida é transversal a toda operação sobre Cadernos, Itens e Sub-itens — trata-se do portão de segurança de todo o Sistema de Tarefas, não de uma regra isolada de um módulo.
- Decisão rápida: Implementar um único middleware/guard de autenticação aplicado globalmente às rotas protegidas, validando o Access Token antes de qualquer handler de negócio ser executado, evitando checagem de sessão duplicada por endpoint.
ASR-005¶
<Backward: RF-022, RF-024- Preocupação: Desativação de conta e troca de senha disparam revogação em massa de sessões, mas com uma diferença sutil e propensa a erro: a troca de senha preserva a sessão corrente, a desativação encerra todas.
- Decisão rápida: Centralizar a lógica em uma função única
revokeAllSessions(userId, exceptSessionId?), reutilizada pelos dois fluxos, para evitar duas implementações divergentes do mesmo mecanismo.
ASR-006¶
<Backward: RF-023, RF-011- Preocupação: Deleção de dados tem dois comportamentos distintos e sensíveis a inconsistência: exclusão de conta é cascata total, enquanto exclusão de Caderno preserva itens movendo-os para a Inbox — se não forem transacionais, ambos os fluxos arriscam dados órfãos.
- Decisão rápida: Toda operação de deleção com efeito em cascata deve rodar em uma transação de banco (ACID); usar
ON DELETE CASCADEno schema para exclusão de conta, e lógica de aplicação explícita (reassociação, não cascade) para exclusão de Caderno.
ASR-007¶
<Backward: RF-020, RF-018- Preocupação: O endpoint de login precisa tratar um terceiro caminho além de sucesso/falha — credenciais válidas em conta Desativada não podem gerar sessão direta nem erro genérico, exigindo um estado intermediário de confirmação.
- Decisão rápida: Login retorna um código de resposta distinto (ex.:
requires_reactivation) em vez de token quando a conta está desativada; endpoint de reativação separado (POST /user/reactivate) só então libera a emissão da sessão.
ASR-008¶
<Backward: RNF-003- Preocupação: A ausência deliberada de verificação de e-mail, recuperação de senha, login social e 2FA reduz a superfície de integração externa do MVP, mas implica que perda de senha é irrecuperável nesta versão.
- Decisão rápida: Não integrar provedores de e-mail/OAuth nesta versão; registrar a ausência de “esqueci minha senha” como risco de produto aceito, a ser tratado em
03-Riscos-Dívida-Tecnica.mdna Fase 3.
Sistema de Tarefas¶
ASR-009¶
<Backward: RF-001, RF-002, RF-003- Preocupação: A hierarquia Caderno → Item → Sub-item, incluindo o estado transitório “Inbox” (item sem caderno), é a fundação estrutural de todo o modelo de dados do sistema.
- Decisão rápida: Coluna
notebook_idnullable na tabela de Item (nulo = Inbox); Sub-item com FK obrigatória e não nulável para o Item pai do tipo TODO, sem tabela de junção N:N (proibindo reaproveitamento).
ASR-010¶
<Backward: RF-005, RF-006- Preocupação: O Item unificado com dois subtipos (SCHEDULE e TODO), com campos e regras distintas, é consultado por praticamente todos os módulos (Calendário, Planner, Todo List, Busca) — a escolha de modelagem impacta todas essas queries.
- Decisão rápida: Single Table Inheritance — uma única tabela
itemscom coluna discriminadoratypee campos específicos por tipo nulináveis, priorizando simplicidade de joins nas visões unificadas em detrimento de algum desperdício de colunas nulas.
ASR-011¶
<Backward: RF-007, RNF-001- Preocupação: Recorrência (diária/semanal/mensal) é um problema clássico de alto risco técnico — a escolha entre materializar instâncias ou calculá-las sob demanda impacta diretamente performance e complexidade de query.
- Decisão rápida: Calcular ocorrências sob demanda (regra + data base + data de término), sem tabela de instâncias materializadas — decisão simplificada pela restrição deliberada de RNF-001 (sem exceções/overrides), que eliminaria a necessidade dessa tabela de qualquer forma.
ASR-012¶
<Backward: RF-010- Preocupação: O ciclo de vida do item (Inbox → Ativo → Concluído → Arquivado; Deletado a partir de qualquer estado) é uma máquina de estados consumida por múltiplos módulos, com regra crítica de que o arquivamento nunca pode ser automático.
- Decisão rápida: Enum de status persistido no banco; validação das transições permitidas centralizada em um único service/use-case de domínio, não replicada em cada endpoint que manipula itens.
ASR-013¶
<Backward: RF-009- Preocupação: O Snooze sobrepõe uma condição temporária de visibilidade ao estado Ativo — toda listagem (Todo List, Planner, Busca) precisa respeitar esse filtro adicional, com risco de inconsistência se a regra for reimplementada em cada módulo.
- Decisão rápida: Campo
snoozed_untilna tabela de itens; filtro de visibilidade “não expirado” centralizado em uma camada de repositório/query compartilhada por todos os módulos de listagem.
ASR-014¶
<Backward: RF-014- Preocupação: As regras de exibição cruzada entre Calendário e Planner Diário (SCHEDULE sempre visível; TODO visível no calendário só com horário ou due date; TODO sem data só no planner) formam uma lógica de negócio não trivial, compartilhada entre módulos e propensa a divergência entre frontend e backend.
- Decisão rápida: Centralizar essa lógica de “visibilidade por visão” em uma única camada de query/service no backend, consumida por todos os endpoints de calendário e planner, evitando duplicação condicional no frontend.
ASR-015¶
< Backward: RF-013
Preocupação: A busca textual por título (restrita aos itens do tipo TODO) tem baixo risco de lentidão considerando a volumetria inicial do MVP. Contudo, o uso de operadores de correspondência parcial sem indexação apropriada força o banco a realizar Full Table Scans, o que degradará a performance severamente à medida que a base de dados crescer.
Decisão: Utilizar o operador nativo contains (que opera como ILIKE) do Prisma ORM para viabilizar o desenvolvimento rápido do MVP. A adoção de motores de busca dedicados e complexos, está descartada nesta fase por ser desproporcional ao escopo, infraestrutura e custos do MVP.
Trade-off / Mitigação: A ausência inicial de índices otimizados para busca de texto parcial é aceita como uma dívida técnica consciente. O caminho de evolução arquitetural já está mapeado: assim que a volumetria exigir maior performance, a mitigação será feita no nível do banco de dados (PostgreSQL) por meio da criação de um índice GIN com pg_trgm (trigramas) utilizando uma Raw Migration do Prisma, mantendo a simplicidade da infraestrutura.