Saltar al contenido principal

Seguridad y RLS

"No confíes en ningún dato que venga del cliente; valídalo todo." — Prompt del agente backend MAMB

MAMB no tiene autenticación de usuarios: las subidas son anónimas. La seguridad se garantiza con (a) validación de Zod en cada Server Action y (b) Row Level Security estricto en la base de datos.

1. Row Level Security (RLS)​

Supabase es backendless desde el cliente, así que la seguridad debe residir en la base de datos.

  • RLS habilitado en styles, authors y artworks.
  • Políticas por tabla:
TablaSELECTINSERTUPDATE/DELETE (cliente)
stylesPúblicoBloqueado al clienteBloqueado
authorsPúblicoPúblico (anónimo)Bloqueado
artworksPúblico (no borrados)Público (validado en SA)Bloqueado

UPDATE/DELETE se reservan a la service_role (administración del museo vía dashboard de Supabase o scripts internos).

Policies reales (supabase/schema.sql)​

ALTER TABLE styles ENABLE ROW LEVEL SECURITY;
ALTER TABLE authors ENABLE ROW LEVEL SECURITY;
ALTER TABLE artworks ENABLE ROW LEVEL SECURITY;

-- Lectura pública
CREATE POLICY "styles_select_public" ON styles FOR SELECT USING (true);
CREATE POLICY "authors_select_public" ON authors FOR SELECT USING (true);
CREATE POLICY "artworks_select_public" ON artworks FOR SELECT
USING (deleted_at IS NULL);

-- Cualquier visitante puede registrarse como autor anónimo
CREATE POLICY "authors_insert_public" ON authors FOR INSERT
WITH CHECK (true);

-- Cualquier visitante puede subir una obra (validada por Zod en la SA)
CREATE POLICY "artworks_insert_public" ON artworks FOR INSERT
WITH CHECK (true);

2. Validación de entradas​

  • Zod en cada Server Action, antes de tocar la base de datos.
  • Sanitización de strings para prevenir XSS en datos dinámicos.
  • Nombres UUID en Storage para evitar colisiones y enumeración de archivos.

3. Storage seguro​

Buckets (supabase/storage.sql):

BucketLímiteMIMEsLecturaEscritura
artworks-originals5 MBimage/jpeg, image/png, image/webpPúblicaPública (validada por SA)
artworks-stylized5 MBimage/jpeg, image/png, image/webpPúblicaPública (validada por SA)

Las policies validan extensión y tamaño en la base de datos, no solo en el cliente.

4. Server Actions endurecidas​

  • Validar el payload con Zod como primer paso.
  • Errores con forma estándar: { success: false, error: 'Mensaje legible' }.
  • Rate limiting por IP (5 obras/h por defecto).
  • Tras un insert exitoso, revalidatePath('/gallery') para refrescar la caché de la galería.

5. Secrets​

  • Variables de entorno (NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY) expuestas solo al build; ningún secret sensible se envía al cliente.
  • Cualquier operación administrativa (borrar obras, marcar destacadas) se hace del lado del servidor con la service_role key, nunca expuesta al bundle.

Checklist de seguridad​

  • ¿La tabla tiene RLS habilitado?
  • ¿Todos los inputs pasan por Zod?
  • ¿Las imágenes van a buckets con políticas que limitan extensión y tamaño?
  • ¿Los errores son informativos pero no exponen detalles de la BD?
  • ¿Se están usando los tipos generados de TypeScript para Supabase?
  • ¿Las operaciones sensibles pasan por el servidor y la service_role?