O problema
Uma clínica de psicologia tem uma rotina específica: sessões que se repetem toda semana, vários profissionais com financeiro próprio e salas sublocadas cobradas por mês. O ClinicaAme organiza isso numa agenda em lista e semanal, que checa disponibilidade antes de marcar, com financeiro por profissional e faturamento mensal automático da sublocação.
A API
Algumas rotas reais:
POST /auth/login → JWT
GET /api/availability?date=…
POST /api/appointments/recurrence
PATCH /api/appointments/{id}/confirm
Decisões
PHP 8.2 sem framework
Roteador e middlewares foram escritos por mim, em vez de usar Laravel ou Slim.
Por quê: queria entender o que um framework faz por baixo: como uma requisição chega ao controller, onde entra a autenticação, como um erro vira resposta HTTP. O custo é ter mais código para manter e decidir caso a caso o que um framework daria pronto.
Controller → Service → Repository
O controller só traduz HTTP. O service guarda as regras de negócio. O repository é o único lugar com SQL.
Por quê: as regras de agenda (conflito de horário, recorrência) ficam num lugar só e podem ser testadas sem subir servidor.
Regras como exceções de domínio
Conflito de horário e limite de recorrência são exceções com nome, e não um
return falseespalhado pelo código.Por quê: cada regra quebrada vira a resposta HTTP certa num ponto só, e os testes com PHPUnit conferem exatamente qual regra foi violada.
Autenticação JWT com refresh token
Token de acesso, refresh token, bloqueio depois de várias tentativas de login erradas e permissões por papel (admin e profissional).
Por quê: o sistema guarda agenda de pacientes. Força bruta no login e um profissional vendo dados de outro precisavam estar fechados desde o começo.
