7.9 KiB
CLAUDE.md — Reglas del proyecto
Este archivo lo carga el agente (Claude Code) por defecto. Contiene lo que aplica a TODO el proyecto: reglas no negociables, decisiones ya tomadas, política de iniciativa y verificaciones pre-entrega. El agente NO puede re-decidir lo que está acá. (Patrón B.4.)
Identidad del proyecto
Plataforma de encuestas con soberanía de datos. Caso fundacional: mapeo de cuidadores en empresas. Objetivo macro: "economía de la discapacidad" en Paraguay. Trata datos sensibles (salud/ discapacidad) → la privacidad no es una feature, es una restricción de diseño.
Reglas no negociables (datos y privacidad)
- Anonimato es por-encuesta, no global. Cada encuesta declara su modo; el esquema y la lógica de guardado lo respetan. Nunca asumir anonimato por defecto ni quitarlo por conveniencia.
- En encuestas anónimas, NUNCA escribir una clave de individuo (
respondent_id) ni cookie de sesión linkeable. La deduplicación se hace conip_hash(hash unidireccional + salt), nunca con identidad. - El umbral de k-anonimato es mandatorio en toda visualización compartida. Ninguna celda, gráfico o tabla expuesta a una empresa puede mostrar un segmento con n < UMBRAL_K (config del proyecto, default 5). Esto aplica AUNQUE la encuesta sea anónima.
- El texto libre NO entra al store analítico crudo. Se excluye o se categoriza antes (es un vector de re-identificación). El gráfico/reporte trabaja sobre categorías, no sobre texto crudo.
- El consentimiento es evidencia, no UI. Cada respuesta guarda un registro de consentimiento versionado, con timestamp, inmutable, contra la versión del texto vigente al momento. Cambiar el wording del consentimiento NO altera registros viejos. (Ver ADR-003.)
- La elección granular del titular (el respondente) siempre gana sobre cualquier documento firmado por la empresa. La empresa autoriza el despliegue; el individuo consiente el tratamiento de su propio dato.
- Modo de responsable (
controller_role) define el flujo de datos:- Modo A (nosotros = responsable): el dato puede alimentar el macro a todos los niveles que el titular consintió.
- Modo B (empresa = responsable, nosotros = encargado): el dato solo puede alimentar el macro vía Nivel 1 anonimizado irreversible. Nunca Nivel 2/3.
- v1 corre solo Modo A. El campo existe pero la lógica dual no se construye todavía.
- La empresa nunca accede a dato individual crudo. Solo recibe agregados/dashboards autorizados por encima del umbral. (Coherente con Modo A + k-anonimato.)
- Manejo de API keys de Supabase — transversal y crítico. La
anonkey es pública y respeta RLS: es la única que puede tocar el frontend/cliente. Laservice_rolekey bypassa RLS por completo y por lo tanto saltea k-anonimato, consentimiento y todo el modelo de ADR-001. Reglas:- La
service_roleNUNCA va al frontend, al cliente, a un artefacto público ni a git. Solo vive server-side (Edge Functions / backend), cargada desde variable de entorno. .envy.env.*siempre en.gitignore. Unaservice_roleen el historial de git es un incidente de seguridad aunque el repo sea privado → rotar la key de inmediato.- Toda operación de cara al respondente o a la empresa usa
anonkey + RLS. Si algo "necesita"service_rolepara funcionar en el cliente, está mal diseñado: revisar las policies, no exponer la key.
- La
- El flujo del respondente NUNCA se ata a un IdP / SSO. Encuestas anónimas = sin login, sin
Keycloak, sin cookie de sesión identificable. El SSO (Keycloak) es solo para staff interno. RLS
lee claims por nombre (
org_id,role) para que el emisor del token sea intercambiable; nunca basar RLS enuser_metadata(modificable por el usuario). (Ver ADR-004.)
Distinción que NO se puede volver a confundir: anónimo vs pseudónimo
- Comparar segmentos ("alguien de 25, sector X, zona A" vs "alguien de 25, sector X, zona B") se
hace con los cuasi-identificadores guardados en cada fila. NO requiere
respondent_id. Vive en datos 100% anónimos. respondent_id(clave pseudónima) sirve para vincular varias respuestas a la misma persona desconocida (longitudinal individual, re-contacto, dedup avanzado). Nada de eso es caso de v1.- Por lo tanto: anónimo a nivel respondente alcanza para la comparación que el producto necesita. La comparación individuo-vs-individuo (n=1) está prohibida en dashboards compartidos.
Política de iniciativa proactiva (clasificar antes de actuar)
Ante una mejora fuera del scope, el agente clasifica el impacto y actúa según el nivel. Evaluar en este orden; el primero que aplique decide:
- ¿Resuelve un ítem de
TECH_DEBT.md/BACKLOG.md/ planificación? → Nivel 3. - ¿Choca con restricción explícita del prompt ("NO entra", "NO tocar", "agendado para etapa Z")? → Nivel 3.
- ¿Toca privacidad, anonimato, consentimiento, clasificación de datos o RLS? → Nivel 3 SIEMPRE.
- ¿Modifica paginación, layout, cantidad de archivos o estructura de salida? → Nivel 2 mínimo.
- ¿Es visible al usuario final (texto, color, posición, contenido)? → Nivel 2 mínimo.
- ¿Afecta marca, identidad, dependencias o configuración? → Nivel 3.
- Si nada aplica → Nivel 1.
- Nivel 1 (interno, invisible, reversible): ejecutar; mencionar al final si fueron varios.
- Nivel 2 (visible reversible): ejecutar y reportar como "decisión proactiva — validar/revertir".
- Nivel 3 (marca/arquitectura/datos/privacidad): NO ejecutar. Consultar antes con el formato:
PROPUESTA DE CAMBIO NIVEL 3 — requiere aprobación Cambio sugerido: [descripción] Justificación: [por qué] Impacto: [qué afecta] Alternativa si se rechaza: [qué hacer]
Argumentos que NO bajan de nivel: "es legibilidad", "es consistencia", "es trivial de revertir", "es un bug menor", "el usuario lo va a agradecer". Si está en TECH_DEBT/BACKLOG, es Nivel 3 sin importar el tamaño técnico.
Verificaciones obligatorias antes de entregar (toda etapa)
git diff --name-only HEAD→ solo archivos autorizados por el prompt. Si aparece uno no autorizado: revertir (git checkout HEAD -- <archivo>), listar bajo "Conflictos de scope", no incluirlo.- Si una restricción del prompt (
NO tocar X) colisiona con otro requisito (build limpio): DETENERSE y reportar el conflicto, no resolver unilateralmente. - Reporte con datos concretos, no descripciones ("PDF: 78 KB, 4 págs, tabla 11 filas", no "PDF generado correctamente").
- Separar explícitamente Verificado vs Asumido vs Hallazgos no esperados.
- Tests verdes NO es etapa terminada. Si hay artefacto visible, el humano lo abre (validación visual la hace el director, no el agente).
Decisiones ya tomadas (no consultar de nuevo)
- Etapa 1 = una encuesta fija (mapeo cuidadores) multi-empresa. NO builder visual.
- Las 4 encuestas de v1: anónimas a nivel respondente + confidenciales (seguridad).
- Se conservan
company_id+ cuasi-identificadores. NO se usarespondent_id. - Modo A (nosotros responsables). Sin Nivel 3 atribuible en esta etapa.
- Empresas actúan sobre agregados, nunca sobre individuos nombrados.
- Dedup por
ip_hash. Consentimiento granular versionado e inmutable. - Umbral de k-anonimato default = 5 (parametrizable por proyecto).
- Separador de miles y formato de cifras: definir en
CONVENTIONS.md(ver Decisiones abiertas).
Decisiones abiertas (requieren al director, no las cierra el agente)
- Nombre/marca del producto (Nivel 3).
- Residencia de datos: Supabase Cloud vs self-host (ADR-002).
CONVENTIONS.md: formato de cifras, idioma de la UI, tono de los mensajes. Apenas una convención se pregunte 2 veces, documentarla acá (anti-patrón AP.4).