C4 Component
Introdução ao documento
Este documento registra uma visão de componentes no nível C4 adaptada ao que o repositório realmente expõe em runtime. O recorte prioriza módulos que mudam juntos e pontos cuja falha interrompe cadastro, autenticação, confirmação por OTP, redirecionamento para grupo ou operação básica da aplicação.
Fato observado
- O repositório combina interface em
app/, APIs internas empages/api/eapp/api/, e adapters HTTP emsrc/features/api/external/. - O app é um frontend Next.js com comportamento de BFF fino para autenticação, participant upsert, OTP, telemetria e integrações externas.
Inferência controlada
- No contexto deste repositório, o "serviço" é melhor entendido como um app web com componentes client/server e uma camada de integração server-side, e não como um backend monolítico com domínio persistente local.
Evidências:
../../app/layout.tsx#L32-L64../../app/[slug]/page.tsx#L16-L47../../pages/api/v1/participantes/[cpf].ts#L6-L54../../app/api/meta-conversion/route.ts#L7-L47../../src/common/util/fetchWithTimeout.ts#L1-L60
Versionamento
Este documento deve ser atualizado quando houver mudança em:
- rotas principais de experiência (
/[slug], inscrição, OTP, grupo, manutenção); - mecanismo de autenticação e sessão (
NextAuth, AMEI/Keycloak, guards client-side); - contratos da API interna (
pages/api/*,app/api/*); - integrações externas que afetam elegibilidade, upsert de participante, OTP, tracking ou probes operacionais.
Fato observado
- Essas responsabilidades estão espalhadas entre rotas App Router, handlers Pages Router e adapters de integração, então alterações em qualquer um desses pontos mudam a topologia de componentes.
Evidências:
../../app/[slug]/page.tsx#L23-L46../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L45-L130../../pages/api/auth/[...nextauth].ts#L25-L153../../pages/api/v1/otp/confirm.ts#L12-L57../../middleware.ts#L4-L40
Referencial teórico
Este documento usa um recorte C4 de componentes, mas adaptado às fronteiras reais do código:
- rotas e layouts do Next.js como componentes de experiência;
- providers, sessão e guards como componentes de acesso;
- handlers HTTP internos como componentes de aplicação/BFF;
- adapters
external/*e utilitários de resiliência como componentes de integração.
Fato observado
- O código já está organizado nessas fronteiras:
app/,pages/api/,src/common/components/providers,src/features/api/external.
Inferência controlada
- Esse corte é o mais útil aqui porque coincide com as áreas que quebram juntas em produção.
Evidências:
../../app/layout.tsx#L41-L60../../src/common/components/providers/Providers.component.tsx#L41-L189../../pages/api/auth/[...nextauth].ts#L39-L151../../src/common/constants/config.ts#L1-L7
Responsabilidade do serviço/app
Fato observado
- Renderizar a página pública de curso a partir de customização e status externos.
- Autenticar participantes por CPF com
NextAuthe, opcionalmente, por AMEI/Keycloak. - Validar elegibilidade de matrícula antes de liberar o fluxo.
- Ler, criar ou atualizar participante e disparar OTP por WhatsApp.
- Confirmar OTP, reenviar template de fluxo e redirecionar para link de grupo.
- Expor configuração de runtime e endpoints operacionais (
health,readiness,liveness).
Inferência controlada
- O app funciona como frontend transacional de onboarding, com lógica de negócio leve concentrada em autenticação, elegibilidade e orquestração de integrações.
Evidências:
../../app/[slug]/page.tsx#L23-L46../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L110-L130../../pages/api/auth/[...nextauth].ts#L65-L120../../pages/api/v1/participantes/[cpf].ts#L23-L52../../pages/api/v1/otp/confirm.ts#L22-L52../../app/grupo/[uid]/page.tsx#L12-L41../../pages/api/health.ts#L20-L108
Dependências
Banco de dados
Fato observado
- Não há cliente de banco, ORM ou migration local declarados nas dependências principais do app.
- Os acessos a dados comprovados no código de aplicação deste repositório acontecem por HTTP para serviços externos.
Inferência controlada
- Se existir banco persistente no ecossistema, ele está atrás dos serviços externos e não dentro deste repositório.
Evidências:
../../package.json#L14-L44../../src/common/constants/config.ts#L1-L7../../src/features/api/external/wp/getCustomization/getCustomization.ts#L27-L34../../src/features/api/external/registrations/getUserByCpf/getUserByCpf.ts#L22-L45
Cache
Fato observado
- O app usa
AppRouterCacheProviderno browser para integração do MUI com App Router. - As chamadas HTTP compartilhadas desabilitam cache do
fetchcomcache: 'no-store'. - Não há evidência local de Redis, Memcached ou outro cache externo dedicado.
Evidências:
../../src/common/components/providers/Providers.component.tsx#L126-L133../../src/common/components/providers/Providers.component.tsx#L177-L184../../src/common/util/fetchWithTimeout.ts#L31-L39../../package.json#L14-L44
Fila, cron, worker
Fato observado
- Não há dependência explícita de fila/consumer nas dependências principais do app.
- Não há módulos dedicados de worker de negócio em
app/,pages/ousrc/. - O único "worker" comprovado no repositório é o
mswpara mocking em desenvolvimento.
Evidências:
Storage
Fato observado
- Não há cliente explícito de object storage ou filesystem remoto nas dependências principais.
- O estado persistido no cliente que impacta o fluxo é
sessionStoragepara a flagamei_auth. - O repositório usa assets estáticos locais, inclusive para imagens e para o diretório do worker MSW.
Evidências:
../../package.json#L14-L44../../package.json#L72-L75../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L62-L64../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L99-L101../../src/common/components/AuthProtected/AuthProtected.component.tsx#L13-L18../../app/grupo/[uid]/page.tsx#L15-L19
Serviços externos
Fato observado
WordPress backend: customização do curso, status do curso, manutenção, lookup/update/create de participante, status de matrícula e link de grupo.WhatsApp API: envio de OTP, confirmação de OTP e envio de template de fluxo.Registration backend: adapter presente no código para busca/criação/atualização de pessoa por CPF.AMEI/Keycloak: configuração carregada em runtime e montada peloUserAuthProvider.Datadog: RUM inicializado no cliente a partir de/api/envs.Meta Graph API: eventos enviados pela rota server-side/api/meta-conversion.
Evidências:
../../src/common/constants/config.ts#L1-L7../../src/features/api/external/wp/getCustomization/getCustomization.ts#L27-L34../../src/features/api/external/wp/getUserEnrollStatus/getUserEnrollStatus.ts#L19-L34../../src/features/api/external/wp/getGroupLink/getGroupLink.ts#L17-L31../../src/features/api/external/whats/otpSend/otpSend.ts#L20-L32../../src/features/api/external/registrations/getUserByCpf/getUserByCpf.ts#L22-L45../../pages/api/config/keycloak.ts#L22-L61../../app/components/DatadogInit.tsx#L8-L29../../app/api/envs/route.ts#L4-L20../../app/api/meta-conversion/route.ts#L7-L47
Componentes internos agrupados por camada
1. Camada de experiência e navegação
Fato observado
RootLayout: injetaSessionProvider,Providers,DatadogInit,MetaPixel, metadados e inicialização opcional do MSW.CourseDetailsPage: carrega status e customização do curso e decide entrenotFound, manutenção ou detalhe do curso.SignupConfirmationeOTPConfirmation: etapas protegidas do fluxo de cadastro e confirmação.GrupoPage: resolve o link do grupo e redireciona o participante.
Evidências:
../../app/layout.tsx#L12-L20../../app/layout.tsx#L32-L64../../app/[slug]/page.tsx#L23-L46../../app/[slug]/inscricao/confirmacao/page.tsx#L8-L15../../app/[slug]/inscricao/codigo/page.tsx#L8-L15../../app/grupo/[uid]/page.tsx#L12-L41
2. Camada de acesso, sessão e guardas
Fato observado
Providers: carrega configuração de Keycloak via/api/config/keycloak, montaUserAuthProviderquando habilitado e encapsulaThemeProvider,SnackbarProvidereAppRouterCacheProvider.CourseRegistration: inicia login por CPF comsignIn("cpf")e também o caminho alternativo AMEI.NextAuth credentials provider: consulta participante, valida elegibilidade por matrícula e popula a sessão JWT.AuthProtected: bloqueia páginas internas quando não há sessão nem usuário AMEI.
Evidências:
../../src/common/components/providers/Providers.component.tsx#L22-L39../../src/common/components/providers/Providers.component.tsx#L120-L185../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L45-L75../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L110-L130../../pages/api/auth/[...nextauth].ts#L39-L128../../pages/api/auth/[...nextauth].ts#L131-L151../../src/common/components/AuthProtected/AuthProtected.component.tsx#L8-L18
3. Camada de aplicação e BFF interno
Fato observado
pages/api/v1/cursos/[slug]: expõe customização simplificada do curso.pages/api/v1/participantes/[cpf]: autentica sessão e orquestra leitura/criação/atualização de participante.pages/api/v1/otp/sendepages/api/v1/otp/confirm: encapsulam o fluxo OTP server-side.pages/api/v1/flow/resend: reenvia template de fluxo usando dados da sessão.pages/api/config/keycloak,app/api/envseapp/api/meta-conversion: fornecem runtime config e tracking server-side.health,readiness,liveness: endpoints de operação e probes.
Evidências:
../../pages/api/v1/cursos/[slug].ts#L5-L29../../pages/api/v1/participantes/[cpf].ts#L6-L54../../pages/api/v1/otp/send.ts#L6-L36../../pages/api/v1/otp/confirm.ts#L8-L57../../pages/api/v1/flow/resend.ts#L7-L45../../pages/api/config/keycloak.ts#L14-L64../../app/api/envs/route.ts#L4-L20../../app/api/meta-conversion/route.ts#L7-L47../../pages/api/health.ts#L20-L108../../pages/api/readiness.ts#L8-L83../../pages/api/liveness.ts#L8-L31
4. Camada de integração, resiliência e telemetria
Fato observado
config.tscentraliza URLs e tokens de integrações externas.fetchWithTimeoutimpõe timeout,AbortController,cache: 'no-store'ekeepalive: false.- Os adapters
external/wp,external/whatseexternal/registrationsencapsulam contratos externos. middleware.tsconsulta modo de manutenção com timeout de 3s e políticafail-open.DatadogInite/api/envsformam o bootstrap de observabilidade client-side.
Evidências:
../../src/common/constants/config.ts#L1-L7../../src/common/util/fetchWithTimeout.ts#L21-L59../../src/features/api/external/wp/getCustomization/getCustomization.ts#L22-L38../../src/features/api/external/whats/otpSend/otpSend.ts#L10-L35../../src/features/api/external/registrations/getUserByCpf/getUserByCpf.ts#L14-L49../../middleware.ts#L4-L35../../app/components/DatadogInit.tsx#L8-L29../../app/api/envs/route.ts#L4-L20
Fluxos críticos
1. Entrada no curso e desvio para manutenção
Fato observado
- O middleware consulta
getMaintenanceMode()com timeout de 3s e, se o modo estiver ativo, redireciona para/maintenance. - A página
/[slug]também consulta status e customização do curso e pode renderizar manutenção no nível da feature.
Por que quebra o sistema:
- Se a customização não vier, a página cai em
notFound. - Se o contrato de manutenção quebrar, a experiência pode divergir entre middleware e página.
Evidências:
../../middleware.ts#L4-L35../../app/[slug]/page.tsx#L23-L39../../src/features/api/external/wp/getMaintenanceMode/getMaintenanceMode.ts#L12-L30
2. Autenticação por CPF/AMEI e validação de elegibilidade
Fato observado
CourseRegistrationdisparasignIn("cpf")comcpfecourse_slug, ou usa o caminho AMEI quando habilitado.- O
CredentialsProviderconsulta participante no backend WordPress, busca status de matrícula e aplica bloqueios por inscrição existente, mesma categoria, concorrência ou excesso de cancelamentos.
Por que quebra o sistema:
- Esse é o principal gate de entrada no fluxo protegido.
- Falhas em
getUserByCpf,getUserEnrollStatusou na montagem da sessão impedem progresso em todas as etapas seguintes.
Evidências:
../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L45-L75../../src/features/components/CourseRegistration/CourseRegistration.component.tsx#L110-L130../../pages/api/auth/[...nextauth].ts#L46-L127../../src/features/api/external/wp/getUserEnrollStatus/getUserEnrollStatus.ts#L18-L38
3. Confirmação de perfil, upsert de participante e envio do OTP
Fato observado
SignupConfirmationmonta o participante a partir da sessão local ou do usuário AMEI e, no caso AMEI, ainda busca o ID canônico por CPF.ProfileFormchamasubscribeToCourse(), que fazPUT /v1/participantes/{cpf}.- O handler
/v1/participantes/{cpf}decide entreupdateUserByIdecreateUser. - Após o upsert, o frontend chama
sendOtpCode(), que usa/v1/otp/send.
Por que quebra o sistema:
- Qualquer divergência entre sessão, CPF, ID retornado ou backend de participante impede a etapa OTP.
- É um ponto de acoplamento alto entre frontend, sessão e WordPress.
Evidências:
../../src/features/components/SignupConfirmation/SignupConfirmation.component.tsx#L21-L82../../src/features/components/SignupConfirmation/components/ProfileForm/ProfileForm.component.tsx#L47-L96../../src/features/api/subscribeToCourse/subscribeToCourse.api.ts#L4-L21../../pages/api/v1/participantes/[cpf].ts#L23-L52../../src/features/api/sendOtpCode/sendOtpCode.api.ts#L6-L27../../pages/api/v1/otp/send.ts#L20-L35
4. Confirmação do OTP e disparo do template de fluxo
Fato observado
- A tela de OTP envia
phoneecodepara/v1/otp/confirm. - O handler confirma o código no backend WhatsApp, lê
flow_template_ideflow_template_header_imageno WordPress e disparasendFlowTemplate. - O endpoint
/v1/flow/resendrepete essa orquestração a partir da sessão, sem input adicional do cliente.
Por que quebra o sistema:
- Essa é a transição entre validação do usuário e entrada na etapa final de turma/grupo.
- Exige consistência simultânea entre sessão, WhatsApp API e customização do curso.
Evidências:
../../src/features/components/OTPConfirmation/components/Form/Form.component.tsx#L27-L57../../src/features/api/confirmOtpCode/confirmOtpCode.api.ts#L3-L20../../pages/api/v1/otp/confirm.ts#L22-L52../../src/features/api/resendTemplate/resendTemplate.api.ts#L6-L24../../pages/api/v1/flow/resend.ts#L21-L41
5. Resolução do link de grupo
Fato observado
- A rota
/grupo/[uid]decodifica o identificador, chamagetGroupLink()e fazredirect()paragroup_link. - Se o link não vier, a página degrada para uma tela de erro de negócio.
Por que quebra o sistema:
- É a última entrega funcional do onboarding; sem esse link o usuário conclui o fluxo, mas não entra no grupo associado.
Evidências:
../../app/grupo/[uid]/page.tsx#L12-L41../../src/features/api/external/wp/getGroupLink/getGroupLink.ts#L16-L35
Diagrama Mermaid
Evidências:
../../src/common/components/providers/Providers.component.tsx#L22-L39../../pages/api/auth/[...nextauth].ts#L39-L151../../pages/api/v1/participantes/[cpf].ts#L23-L52../../pages/api/v1/otp/confirm.ts#L22-L52../../app/api/envs/route.ts#L4-L20../../app/api/meta-conversion/route.ts#L22-L43../../src/common/util/fetchWithTimeout.ts#L10-L59
Pendências
- Confirmar qual backend é a fonte canônica de pessoa/participante no ecossistema: WordPress ou
API_REGISTRATION_BACKEND_URL. - Confirmar se o adapter de
Registration APIestá ativo em produção ou apenas preservado no código para uso futuro/paralelo. - Confirmar se
API_CLASSES_BACKEND_URLainda faz parte da arquitetura alvo, já que o valor é declarado, mas não há consumo comprovado fora deconfig.ts. - Confirmar a decisão arquitetural de manter
app/epages/api/coexistindo como topologia estável. - Resolver a divergência entre
NEXT_DATADOG_CLIENT_IDem.env.exampleeNEXT_DATADOG_CLIENT_TOKENconsumido pelo runtime. - Confirmar o papel obrigatório da integração AMEI em todos os ambientes, já que ela depende de toggle e runtime config.
Evidências:
../../src/common/constants/config.ts#L1-L7../../src/features/api/external/registrations/getUserByCpf/getUserByCpf.ts#L22-L45../../pages/api/auth/[...nextauth].ts#L4-L6../../pages/api/v1/participantes/[cpf].ts#L1-L4../../app/layout.tsx#L32-L64../../pages/api/config/keycloak.ts#L24-L61../../.env.example#L20-L24../../app/api/envs/route.ts#L7-L18