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?