Deriva la propiedad en el servidor
Un ID de registro identifica algo; no demuestra quién puede leerlo. supastack delimita los registros de usuario por workspaceId. El servidor resuelve el espacio del usuario autenticado e incluye ese límite al leer o modificar un registro.
No trates un ID de espacio enviado por el navegador como prueba de propiedad. El navegador puede pedir una acción, pero el contexto de servidor de confianza debe establecer de quién es. Esta regla debe valer para el estado de tarea, la configuración de proveedor guardada, los registros de uso y cada recurso propio del producto. Los layouts y componentes pueden filtrar lo que se renderiza, pero renderizar no es autorización — la comprobación pertenece al lugar donde el registro se lee o se escribe de verdad.
Todo lo demás en este post se sigue de esa regla: la propiedad se deriva, nunca se pide. En el momento en que un workspaceId enviado por el cliente es de fiar en algún sitio, cualquier otra comprobación se vuelve decoración. El post de autenticación cubre cómo se establece la sesión río arriba de esta frontera.
La membresía es parte de la frontera
El delimitado responde a qué espacio pertenece un registro; la membresía responde si este usuario pertenece a ese espacio. Resuelve ambas en el servidor. supastack modela espacios personales y de organización con roles de dueño, administrador y miembro — la guía de espacios de trabajo documenta el modelo.
Los roles añaden un segundo eje: un miembro puede leer lo que solo un administrador puede cambiar. Mantén las dos comprobaciones separadas — «pertenece a este espacio» y «puede ejecutar esta acción» — para que una degradación o expulsión haga efecto en la misma frontera que todo lo demás. Las invitaciones y expulsiones son parte del mismo ciclo de vida, no una idea tardía de administración.
Los cambios de membresía también tienen que hacer efecto de inmediato. La siguiente petición de un miembro expulsado debería fallar en la frontera, no cuando una credencial cacheada decida expirar — otra razón por la que la comprobación vive donde se leen los registros, en lugar de dentro de una credencial emitida antes.
Haz la recuperación útil sin conceder acceso
Una URL de tarea permite a un usuario volver tras un refresco. Es útil precisamente porque conserva una referencia al trabajo. La API autenticada debe seguir verificando que la tarea solicitada pertenece al espacio actual antes de devolver estado o resultados.
El mismo principio se aplica a la recuperación de envíos. Una clave de idempotencia ayuda a identificar una petición repetida y a evitar trabajo duplicado. No es ni una sesión ni un token de acceso. Reintentar un envío guardado sigue exigiendo autenticación, propiedad del espacio y el permiso apropiado.
Las rutas de comodidad son donde el aislamiento se erosiona en silencio. Un enlace que ayuda a un usuario legítimo a retomar trabajo — tras un refresco, desde un email de finalización — debe pasar por la misma comprobación autenticada que cualquier otra petición. El pipeline de petición a resultado usa claves de idempotencia delimitadas a la tarea exactamente por este principio.
Prueba las peticiones que deben fallar
Un test que deja a un propietario recuperar un registro demuestra el camino feliz. No demuestra el aislamiento. Combínalo con un segundo espacio pidiendo el mismo registro, una petición anónima y una escritura que intente sustituir a otro propietario.
Afirma el comportamiento externo tanto como el resultado persistido. Una petición rechazada no debe mutar los datos de otro espacio, y una respuesta de error no debe filtrar secretos ni detalles crudos de la base. Estas comprobaciones mantienen la frontera revisable cuando la implementación cambia.
- Un segundo espacio pide el mismo ID de registro — rechazado.
- Una petición anónima golpea el mismo endpoint — rechazada.
- Un miembro expulsado del espacio reintenta — rechazado.
- Una escritura nombra a otro dueño u otro espacio — rechazada, sin mutar nada.
- Las respuestas de error se quedan genéricas — sin secretos, sin detalles de esquema.
Lleva la regla a tu producto
Cuando añadas una nueva tabla de producto, decide su propiedad antes de construir la pantalla. Incluye workspaceId en su modelo de persistencia, resuelve el espacio mediante la frontera de servidor existente y usa ese contexto tanto en operaciones de lista como de detalle.
Los workers en segundo plano exigen el mismo cuidado. Una tarea encolada debe llevar suficiente contexto de confianza para cargar el registro correcto, mientras las credenciales de proveedor permanecen en el servidor. Un job programado que carga filas por ID desnudo sigue dentro de la frontera. Una regla de propiedad consistente es más fácil de mantener que una colección de excepciones por ruta.
La superficie de API pertenece a la misma frontera. Las claves de API del espacio y los webhooks salientes firmados llevan consigo el ámbito del espacio — una clave nunca debe convertirse en una forma de leer entre tenants, y una carga de webhook nunca debe llevar registros del vecino. La guía del módulo de API cubre la forma de esa superficie.
Preguntas frecuentes sobre aislamiento de espacios
El aislamiento multi-tenant levanta el mismo puñado de preguntas en cada proyecto. Estas son las que conviene resolver pronto.
- ¿Basta el delimitado a nivel de aplicación o necesito seguridad a nivel de fila? — El delimitado aplicado en el servidor en cada lectura y escritura cubre el modelo de amenazas de la mayoría de SaaS. RLS en base de datos añade defensa en profundidad, pero no sustituye las comprobaciones de frontera — los workers y las claves de API siguen necesitando la misma regla.
- ¿Cómo debería funcionar compartir entre espacios? — Modélalo explícitamente — una invitación, una fila de membresía — en lugar de debilitar el ámbito. «Cualquiera con el enlace» debería ser una función diseñada con sus propias comprobaciones, no un accidente.
- ¿Qué se rompe primero en las apps multi-tenant? — Las rutas de comodidad: enlaces de recuperación, herramientas de administración, workers en segundo plano que cargan registros por ID desnudo. Audita cada ruta de código que toca un registro sin pasar por el ámbito normal.
- ¿Cómo añado delimitado a una tabla existente? — Añade
workspaceId, rellénalo, hazlo valer en lecturas y escrituras y después toca la UI. Entrega primero los tests negativos para que la frontera quede demostrada en lugar de supuesta. - ¿Necesitan comprobaciones las acciones de servidor si la página está protegida? — Sí. Los guardas de página ocultan pantallas; no autorizan operaciones. Cada acción resuelve la sesión y el espacio de forma independiente.