Apariencia
0050. Alta de cuentas solo por invitación: retiro del signup público
Estado
Aceptada. Supersede ADR-0013 (registro en 3 fases).
Contexto
El admin web nació con dos vías paralelas para crear la primera cuenta de una organización: el signup público (POST /auth/signup → verify-email OTP → onboarding, ADR-0013) y, desde platform-rbac-backend/platform-onboarding-tenants (2026-07-20/21), el alta desde plataforma (el superadmin invita a un admin, con o sin nombrar la empresa de antemano — ver ADR-0049). El signup público quedó documentado como transitorio en plataforma/superadmin-flow.md desde que apareció la vía de plataforma, pendiente de retiro en el backlog (deprecar-signup-publico).
Con el modo delegado (ADR-0049) operativo, la pregunta que bloqueaba el retiro — "¿cómo nombra su empresa un cliente que llega por invitación, sin auto-registro público?" — ya tenía respuesta: el superadmin invita sin nombrar la empresa y el cliente la nombra al aceptar, vía el mismo POST /auth/onboarding que ya usaba el signup. Sin ese hueco, el signup público pasó a ser una puerta de alta redundante: dejaba registros abandonados en pending_verification (7 días de gracia, job de expiración) y acoplaba 16 specs e2e del backend a una superficie que ya no reflejaba cómo se dan de alta cuentas en producción.
Decisión
Se retira el signup público por completo: POST /auth/signup, POST /auth/verify-email, POST /auth/resend-code y las páginas/rutas correspondientes del admin (SignUpPage, VerifyEmailPage, /signup, /verify). Toda cuenta nueva entra por POST /auth/accept-invitation — de tenant, de plataforma directa, o de plataforma delegada (ADR-0049) — que ya bifurca según si el invitado tiene membresía.
Lo que sobrevive intacto (no quedan huérfanos, corrigiendo el relevamiento inicial de esta tarea, ver ADR-0049 §"Efecto colateral"):
POST /auth/onboarding, elOnboardingPagedel admin y todo el scopeonboarding(issueOnboardingToken,OnboardingJwtGuard,JWT_ONBOARDING_SECRET) — alimentados ahora solo por la invitación delegada.- El estado
pending_onboarding— sigue vivo, producido poraccept-invitationen vez deverify-email. accept-invitation, compartido por los tres flujos de alta.
Lo que queda sin productor pero se conserva (para no forzar una migración destructiva de tipo en la misma tarea):
- El valor
pending_verificationdel enumUserStatus— las filas existentes se purgan en la migración, pero el valor del enum no se elimina. - El valor
email_verificationde la tablaverification_tokens.
El job expire-pending-accounts se repropósita: deja de cubrir pending_verification (sin productor) y pasa a limpiar usuarios invited sin membresía con más de 7 días — el hueco de invitaciones delegadas abandonadas que abrió el modo delegado y que hasta ahora nadie limpiaba.
signupAdmin() (helper de los 16 specs e2e del backend) deja de pasar por el flujo HTTP y siembra directo por Prisma (organización + rol Administrador + curvas de alimentación por defecto + membresía + signin para los tokens) — reproduce exactamente lo que hacía AuthService.onboarding(), sin acoplar los specs a la superficie de plataforma que reemplazó al signup.
Consecuencias
- Breaking intencional:
/auth/signup,/auth/verify-email,/auth/resend-codepasan a 404. Los únicos consumidores eran el admin (actualizado en la misma tarea) y Postman/docs; mobile nunca los llamó. SignInPagepierde el link "¿No tienes cuenta? Regístrate" — sin auto-registro no hay nada a lo que apuntar; se decidió no reemplazarlo por un texto informativo, dejando el formulario solo con signin + "¿olvidaste tu contraseña?".- El shape de
SigninPendingResponseDto.statusse angosta a'pending_onboarding'(antes admitía también'pending_verification'). camaroneras_mobilepierde una mitad de su chequeoisPending(pending_verification || pending_onboarding) sin cambio de código: el mensaje "Completa tu registro desde la web" sigue siendo correcto para la mitad que sobrevive.
Referencias
- Tarea
deprecar-signup-publico(2026-07-22). - ADR-0049 — decisión previa que desbloqueó este retiro.
camaroneras_backend/src/modules/auth/(controller/service),src/jobs/expire-pending- accounts.job.ts,test/helpers/bootstrap.ts(signupAdmin), migración20260722152139_drop_pending_verification_default.camaroneras_admin/src/features/auth/(páginas, api, hooks, schemas),src/app/router.tsx.camaroneras_docs/plataforma/auth-flow.md,admin-ui-flow.md,auth-mobile-flow.md,superadmin-flow.md,arquitectura/index.md(contratos actualizados)._planning/_backlog/backlog.md→ entradadeprecar-signup-publico(derivados anotados: enumpending_verification, valoremail_verification,camaroneras_mobilediferido).