Registro invite-only (F1 de la task #137) · plan aprobado en plan-review
Qué es
Plan aprobado (04-08-2026) para abrir el registro self-service invite-only de CreaRack Pro — la F1 de la task #137 del Plan H2. Decidido con Edu en grill (7 decisiones) y endurecido por 3 paneles fríos de /method:plan-review (6 pasadas, 20 bloqueantes cazados y cerrados, plan v1→v7). La captura completa del ciclo vive en CreaRack-Pro/brainstorms/2026-08-04-f1-plan-tecnico.md (v7) y 2026-08-04-registro-f1.md (grill).
Decisiones de producto (grill, Edu)
- La página vive en el SaaS:
crearack.com/signup(la landing enlazará). - Puerta hasta la apertura pública de noviembre (#151): código de invitación — tabla en BD + sección en Settings (solo superusers), códigos tipo
FOUNDER-ACMEcon usos máximos, caducidad y contador de altas. - Formulario de 4 campos: código, empresa, email, username — sin password (activación por link de email, flujo existente) + Cloudflare Turnstile invisible.
- Sin código válido → mensaje claro + “Don’t have an invitation code? Contact us” →
hello@crearack.com(buzón operativo desde 04-08). - El código otorga el plan (
FOUNDER-*→ pro; genérico → starter): cero pasos manuales tras el alta de un fundador. - Página neutra “CreaRack is currently invite-only” — las condiciones de fundadores se negocian por email.
- Datos demo (F2, fase siguiente): mini-datacenter en la org del usuario con botón “Remove sample data”, sin métricas inventadas.
Arquitectura aprobada (v7)
- Puerta: form-post server-side clásico (CSRF real, cero JS propio, errores re-renderizados).
POST /api/signup/se retira del router público; la lógica pasa a un servicio (core/services/) que abre su propiatransaction.atomic(la vista queda exenta delTenantRLSMiddlewarepor lista literal — el alta no escribe en ninguna tabla con política RLS, verificado tabla por tabla; sus fallos van alogger.error, nunca a SystemLog). - Turnstile: validación server-side ANTES de tocar el código de invitación (timeout 2 s, fail-closed, nunca sosteniendo el row lock); excepción CSP solo para
/signup(flag propioneeds_turnstile—script-srcyframe-src+ challenges.cloudflare.com); sitekey+secret declarados encompose.prod.yml, hostnames del widget cubriendo PROD y STAGE. - Modelo:
InvitationCode(code único,planFKon_delete=PROTECT, max_uses, uses_count, expires_at, is_active, notas, created_by) +Organization.invitation_code(SET_NULL). Consumo atómico del último uso (select_for_update). - Rate limit:
/signupa 15/min por IP (cuenta GETs+POSTs; 3 copias alineadas), con 429 renderizado como página HTML (errors/rate_limited.html) solo para esa ruta. - Provisión:
PLAN_MAX_RACKSen fuente única; elsave_relateddel admin (que preserva módulos manuales) NO se toca.
Troceo y estado
| PR | Contenido | Estado |
|---|---|---|
| PR-0 | Fixes preexistentes: token de activación muerto (el endpoint regeneraba el password tras calcular el token) + on_commit + SITE_URL para STAGE + test del desenlace | PR #360 abierto (04-08) — gate de STAGE en curso |
| PR-A | Modelo + servicio + página /signup + retirada del endpoint + Turnstile + CSP + rate limit + tests (4 commits ≤400 LOC) | Pendiente |
| PR-B | Settings UI de códigos de invitación | Pendiente |
Gate obligatorio pre-merge (PR-0 y PR-A): fijar env vars en el Dokploy de STAGE → desplegar la RAMA a mano allí → E2E (los criterios 6 y 5-bis del plan) → solo entonces merge (main auto-deploya STAGE+PROD a la vez).
Los 3 hallazgos estrella del plan-review
- El link de activación del email nacía SIEMPRE inválido (bug preexistente: doble set del password tras calcular el token — arreglado en PR-0, también curaba el alta de primer arranque).
- La CSP enforcing de PROD habría bloqueado el iframe de Turnstile con todos los tests en verde.
- “Unificar la provisión duplicada” habría borrado módulos concedidos a mano a orgs existentes (el admin preserva, el signup pisa — no era duplicación).
Fuera de scope de F1
Datos demo + wizard (F2) · E2E completo del ciclo (F3) · enforcement de max_racks/límites (#136 Stripe) · membership multi-org · invitar usuarios a una org existente · responder “como” hello@crearack.com (decisión Zoho Mail Lite, septiembre con Txell).
Véase también
- [[concept—saas—multi-tenancy]]
- [[concept—saas—module-gating]]
- [[crearack-tech—admin—email-routing-architecture]]