diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..be6a6c2 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 9ac8057..3a19ab7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .env .env.* .env.local +!.env.example # Claude Code — settings locales (allow personales del usuario) .claude/settings.local.json @@ -12,4 +13,8 @@ supabase/.temp/ # Node node_modules/ -package-lock.json + +# Supabase — claves y credenciales +*.key +service_role* +.env.production \ No newline at end of file diff --git a/DATA_MODEL.md b/DATA_MODEL.md index b5d2bbd..002fbaa 100644 --- a/DATA_MODEL.md +++ b/DATA_MODEL.md @@ -150,3 +150,18 @@ granted_at timestamptz not null default now() - `agg_segment(survey_id, dimensions[])` → agregación que **suprime** automáticamente celdas con `count < k_threshold` (devuelve "n insuficiente" en lugar del valor). - Un trigger/constraint que rechaza `respondent_id` no nulo cuando `is_anonymous = true`. + +--- + +## Decisiones ratificadas en ejecución (Sprint 1) +- **`options` en preguntas `rating` (F3, G4):** se guarda como objeto + `{"min":1,"max":5,"min_label":"...","max_label":"..."}`, NO como array. El frontend (Sprint 2) + debe manejar dos formas de `options`: array para `single_choice`/`multiple_choice`, objeto para + `rating`. +- **`required = false` en todas las preguntas seeded:** la obligatoriedad real se define en Sprint 2 + (validación del formulario). Nota: B1 estaba marcada obligatoria en el mockup; revisar al construir + el formulario. +- **Policies de `org_admin` presentes pero inertes en v1:** las policies RLS para `org_admin` + (acceso multi-tenant por empresa) existen en migración 003, pero v1 NO tiene login de cliente + ("nosotros presentamos a cada empresa"). El acceso real lo hace el analyst vía `service_role`. El + camino `org_admin` queda reservado para un futuro de auto-servicio, no operado en v1. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f299f93 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,147 @@ +{ + "name": "Motor de encuestas", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "supabase": "^2.102.0" + } + }, + "node_modules/@supabase/cli-darwin-arm64": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-arm64/-/cli-darwin-arm64-2.102.0.tgz", + "integrity": "sha512-DzQetP1iOnxAmbarZJLoFr3yMtyDrfOC/T2aNpYEASykFGnvCb87CbWMQhjp9zDdA0pFfDYgzM5yESg7cC/anw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@supabase/cli-darwin-x64": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-x64/-/cli-darwin-x64-2.102.0.tgz", + "integrity": "sha512-jJxyULNvgBuWxDrjVySwIB76IUlWOf5lYd/2Zz/Lrop8r1sr7aKJFULz7l1A1vk09ImbvnbkM9IBtH8rNdmBUg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@supabase/cli-linux-arm64": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64/-/cli-linux-arm64-2.102.0.tgz", + "integrity": "sha512-vOEdz4mWoqSpygXliGysYsDobtTlZLMhC2KpDsoYio9vQuQPRgaK2kW4fIGPKfagR4Odv3PycgjoNfdsg7TYUQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@supabase/cli-linux-arm64-musl": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.102.0.tgz", + "integrity": "sha512-VCEJiXK4JhDRXPR32UcIijKdsVT0zg81EoIt6ydmNDJ9vfPI+eFRIzJpeEST1XobTMAVzbJEBw/b/zq5BywR5w==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@supabase/cli-linux-x64": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-linux-x64/-/cli-linux-x64-2.102.0.tgz", + "integrity": "sha512-Jcekp6NOWlLuj8vs/ToR11bbqGWhlijs0rmMRyQvDRocWFgeDWX5IBWZwCXZX2xxr7pICJaSdRZx6V8uW2XVEQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@supabase/cli-linux-x64-musl": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-linux-x64-musl/-/cli-linux-x64-musl-2.102.0.tgz", + "integrity": "sha512-KFzdivlbk8rnMHebxFa//AlQE3uxCWF6ZNIWkYUjE+1EBVXJr/j2Mr1SxkJJyt9h/8jztBUUPJgzuRzIJW0GyA==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@supabase/cli-windows-arm64": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-windows-arm64/-/cli-windows-arm64-2.102.0.tgz", + "integrity": "sha512-yY3qbHhMtQFI2TBXbU611UI7b0TaShxGwbunMUwmTUyaCLDTSsxOjxwbpCyfvgY7eDEeYI0WnkbBKHKxknKVDQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@supabase/cli-windows-x64": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-windows-x64/-/cli-windows-x64-2.102.0.tgz", + "integrity": "sha512-PpIBXxGRi3bk0Zj2JeDCsr2edDt2qd5j31aaixuxHSsPJh0A052kDEDw4jSOWFHBL1UEai6rGF7zWuX/F3gNiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/supabase": { + "version": "2.102.0", + "resolved": "https://registry.npmjs.org/supabase/-/supabase-2.102.0.tgz", + "integrity": "sha512-PMoWgoQOb1/mZ3Y+e/HIIvWmEfui20cWELXYURrb6s66Swvo1jnkBmRvtCtSA8lan+aHtkgVQAyekocugle2eg==", + "license": "MIT", + "bin": { + "supabase": "dist/supabase.js" + }, + "optionalDependencies": { + "@supabase/cli-darwin-arm64": "2.102.0", + "@supabase/cli-darwin-x64": "2.102.0", + "@supabase/cli-linux-arm64": "2.102.0", + "@supabase/cli-linux-arm64-musl": "2.102.0", + "@supabase/cli-linux-x64": "2.102.0", + "@supabase/cli-linux-x64-musl": "2.102.0", + "@supabase/cli-windows-arm64": "2.102.0", + "@supabase/cli-windows-x64": "2.102.0" + } + } + } +} diff --git a/sprints/sprint-1/ETAPA_1C_PROMPT.md b/sprints/sprint-1/ETAPA_1C_PROMPT.md new file mode 100644 index 0000000..5a3720b --- /dev/null +++ b/sprints/sprint-1/ETAPA_1C_PROMPT.md @@ -0,0 +1,82 @@ +# ETAPA 1C — Cierre de la fundación: REVOKE del GRANT peligroso + documentación + +> Prompt versionado (Patrón B.1). Cierra la auditoría de la Etapa 1B con el único cambio bloqueante +> que encontró y documenta tres decisiones que el agente tomó por iniciativa. Claude Code lo ejecuta +> tras leer `CLAUDE.md`, `DATA_MODEL.md` y este prompt. + +## 1. Objetivo +Quitar el `GRANT SELECT ON consent_records TO authenticated` (puerta apoyada-sin-llave: hoy inerte, +peligrosa si alguien suma una policy SELECT a futuro), **confirmar en ejecución que no rompe el flujo +de envío de la encuesta** (la FK `responses.consent_record_id`), y documentar en `DATA_MODEL.md` tres +decisiones tomadas en la 1B. + +## 2. Contexto previo +La 1B aplicó las migraciones 001-006 a Supabase Cloud y la auditoría aprobó la fundación de datos +salvo este punto. La migración **006 ya está aplicada en Cloud** → **NO se edita** (rompería el +historial de migraciones). El cambio va en una migración nueva, 007. + +## 3. Decisiones ya tomadas (no consultar de nuevo) +- El cambio es un `REVOKE`, en migración **nueva** 007. NO editar 001-006. +- El `GRANT INSERT ON consent_records TO anon, authenticated` **se mantiene** (el envío del formulario + lo necesita). Solo se revoca el SELECT. +- NO se agrega ninguna policy SELECT a `consent_records`. El analyst lee vía `service_role` (que + bypassa RLS y no necesita GRANTs). +- No se toca el resto del esquema, ni las policies, ni `service_role`. + +## 4. Tareas +1. Crear la migración con `supabase migration new revoke_consent_select` y poner como contenido: + ```sql + -- 007: Revoca el SELECT sobre consent_records a authenticated. + -- Auditoría 1B: GRANT inerte hoy (no hay policy SELECT) pero peligroso si a futuro alguien + -- agrega una policy SELECT para org_admin → expondría quién consintió qué, vector de + -- correlación con respuestas en encuesta anónima. El analyst lee vía service_role. + REVOKE SELECT ON public.consent_records FROM authenticated; + ``` +2. Aplicar a Cloud: `supabase db push` (usar `npx supabase ...` si el CLI no es global). +3. Correr las validaciones de la sección 6 contra la base real. +4. Documentar en `DATA_MODEL.md` las tres decisiones (texto exacto en la sección 5 de este prompt). + +## 5. Texto EXACTO a agregar al final de `DATA_MODEL.md` (sección nueva) +```markdown +## Decisiones ratificadas en ejecución (Sprint 1) +- **`options` en preguntas `rating` (F3, G4):** se guarda como objeto + `{"min":1,"max":5,"min_label":"...","max_label":"..."}`, NO como array. El frontend (Sprint 2) + debe manejar dos formas de `options`: array para `single_choice`/`multiple_choice`, objeto para + `rating`. +- **`required = false` en todas las preguntas seeded:** la obligatoriedad real se define en Sprint 2 + (validación del formulario). Nota: B1 estaba marcada obligatoria en el mockup; revisar al construir + el formulario. +- **Policies de `org_admin` presentes pero inertes en v1:** las policies RLS para `org_admin` + (acceso multi-tenant por empresa) existen en migración 003, pero v1 NO tiene login de cliente + ("nosotros presentamos a cada empresa"). El acceso real lo hace el analyst vía `service_role`. El + camino `org_admin` queda reservado para un futuro de auto-servicio, no operado en v1. +``` + +## 6. Validaciones automatizadas mandatorias (contra la base Cloud) +La central es la #1 — confirma que revocar el SELECT NO rompe el envío: +- **FK intacta:** simulando rol `anon` (SET ROLE anon + claims, o vía anon key), `INSERT` en + `consent_records` → obtener su id → `INSERT` en `responses` referenciando ese `consent_record_id` + (con `survey_id` de una encuesta `status='live'` y `respondent_id` NULL) → **debe insertar sin + error**. Esto prueba que la verificación de FK no requiere SELECT sobre `consent_records`. +- **REVOKE efectivo:** como `authenticated`, `SELECT FROM consent_records` → ahora "permission + denied" (ya no "0 filas"). Confirma que el revoke aplicó. +- **Sin regresión:** re-correr las claves de la 1B → RLS sobre `responses`/`answers` = 0 filas para + org_admin; `agg_segment` n=3 → suprimido, n=5 → valor; inmutabilidad de `consent_records` (UPDATE/ + DELETE → error) sigue vigente. +- Si CUALQUIERA falla: **NO declarar lista la etapa.** Reportar y esperar. En especial, si la #1 + fallara (la FK SÍ necesitaba el SELECT), **detenerse y reportar** — sería el caso que invalida el + cambio. + +## 7. Qué reportar +- **Verificado:** salida concreta de cada validación (el INSERT anónimo que efectivamente insertó, el + "permission denied" del SELECT como authenticated, y las 3 de no-regresión). +- **Asumido / Hallazgos / Decisiones por iniciativa** (clasificadas por nivel). +- **`git diff --name-only HEAD`:** debe contener solo la migración 007 nueva + `DATA_MODEL.md`. + +## 8. Qué NO hacer +- NO editar las migraciones 001-006 (006 ya está en Cloud). +- NO agregar policy SELECT a `consent_records`. +- NO tocar `service_role`, ni las policies de org_admin, ni el resto del esquema. +- NO usar `respondent_id` ni exponer texto libre. +- Ante conflicto entre una restricción y "que aplique limpio": **detenerse y reportar**, no resolver + unilateralmente. \ No newline at end of file diff --git a/supabase/.DS_Store b/supabase/.DS_Store new file mode 100644 index 0000000..e07a13b Binary files /dev/null and b/supabase/.DS_Store differ diff --git a/supabase/migrations/20260602111851_revoke_consent_select.sql b/supabase/migrations/20260602111851_revoke_consent_select.sql new file mode 100644 index 0000000..1da9c90 --- /dev/null +++ b/supabase/migrations/20260602111851_revoke_consent_select.sql @@ -0,0 +1,5 @@ +-- 007: Revoca el SELECT sobre consent_records a authenticated. +-- Auditoría 1B: GRANT inerte hoy (no hay policy SELECT) pero peligroso si a futuro alguien +-- agrega una policy SELECT para org_admin → expondría quién consintió qué, vector de +-- correlación con respuestas en encuesta anónima. El analyst lee vía service_role. +REVOKE SELECT ON public.consent_records FROM authenticated; diff --git a/supabase/seed.sql b/supabase/seed.sql index 19eff4d..3437f3d 100644 --- a/supabase/seed.sql +++ b/supabase/seed.sql @@ -1,32 +1,25 @@ -- ============================================================ --- Seed: Etapa 1 — Encuesta de Mapeo de Cuidadores +-- seed.sql — Encuesta "Mapeo de Cuidadores" — 34 preguntas +-- Fuente autoritativa: SEED_SPEC.md +-- Reemplaza el seed inventado de Etapa 1 (9 preguntas, tipos incorrectos) +-- Etapa 1B — 2026-06-02 -- --- Carga: --- 1. 1 organización de prueba --- 2. 1 consent_version v1 (scopes: operativo + macro_n1) --- 3. 1 encuesta "Mapeo de Cuidadores" (anónima, sensible, confidencial, Modo A) --- 4. 9 preguntas con códigos del mockup: --- B1 (yes_no), B2, B4, B5 — situación de cuidado (B5 is_sensitive=true) --- C1 (yes_no) — impacto laboral --- D1 (yes_no) — apoyo recibido --- G4 (single_choice) — frecuencia de estrés [condicional a C1=yes] --- H1 (multiple_choice, max_select=3) — apoyo preferido --- H3 (text_long) — comentarios libres --- 5. conditional_rules: B1 → show B2/B4/B5; C1 → show G4 +-- Convenciones (SEED_SPEC.md §Convenciones): +-- - conditional_rules en la pregunta DEPENDIENTE (no en el trigger) +-- - B1/C1/D1 son single_choice de 3 opciones; solo "Sí" dispara el bloque +-- - Valor de opción "Sí" = literal "Sí" (coincide con conditional_rules) +-- - is_sensitive=true en las preguntas marcadas en SEED_SPEC.md (11 total) +-- - H3 (text_long) NO exponer en agg_segment (regla 4 CLAUDE.md) -- --- UUIDs fijos para reproducibilidad y referencia desde tests. --- Nota: el mockup original no estaba disponible; los textos de pregunta --- son diseñados según el contexto "mapeo de cuidadores". Ver ETAPA_1_PROMPT.md. +-- UUIDs fijos: +-- org: 10000000-0000-0000-0000-000000000001 +-- cv-v1: 20000000-0000-0000-0000-000000000001 +-- survey: 30000000-0000-0000-0000-000000000001 +-- preguntas 40000000-0000-0000-0000-000000000001 .. 000000000034 -- ============================================================ --- UUIDs de referencia: --- org: 10000000-0000-0000-0000-000000000001 --- consent_v1: 20000000-0000-0000-0000-000000000001 --- survey: 30000000-0000-0000-0000-000000000001 --- q_B1..q_H3: 4000...0001 al 4000...0009 - -- ============================================================ --- 1. Organización de prueba +-- 1. Organización demo -- ============================================================ INSERT INTO public.organizations (id, name, sector, size_bucket) VALUES ( @@ -34,13 +27,10 @@ VALUES ( 'Empresa Demo S.A.', 'Servicios', '100-500' -) -ON CONFLICT (id) DO NOTHING; +) ON CONFLICT (id) DO NOTHING; -- ============================================================ -- 2. Versión de consentimiento v1 --- Scopes ofrecidos: operativo (dashboard empresa) + macro_n1 (estudio país anonimizado) --- NO incluye macro_n3 (atribuible) — decisión de v1 (ADR-001) -- ============================================================ INSERT INTO public.consent_versions (id, version, body, scopes) VALUES ( @@ -49,259 +39,659 @@ VALUES ( 'Esta encuesta es completamente anónima: no registramos tu nombre, número de documento ' 'ni ningún dato que permita identificarte personalmente. ' 'Tus respuestas se usarán con dos propósitos: ' - '(1) Ayudar a tu empresa a comprender la situación de cuidado de sus colaboradores y ' - 'diseñar apoyos más adecuados (uso operativo, solo agregados). ' - '(2) Contribuir a un estudio de alcance nacional sobre la "economía del cuidado" en Paraguay, ' - 'utilizando únicamente datos anonimizados e irreversiblemente desvinculados de cualquier empresa ' - '(Nivel 1 anonimizado). ' + '(1) Ayudar a tu empresa a comprender la situación de cuidado de sus colaboradores y diseñar ' + 'apoyos más adecuados (uso operativo, solo agregados). ' + '(2) Contribuir a un estudio de alcance nacional sobre la economía del cuidado en Paraguay, ' + 'utilizando únicamente datos anonimizados e irreversiblemente desvinculados de cualquier empresa. ' 'Una vez enviada tu respuesta, al ser anónima, no es posible retirarla ni modificarla. ' 'Podés elegir qué propósitos autorizás marcando las casillas a continuación.', - '["operativo", "macro_n1"]'::jsonb -) -ON CONFLICT (id) DO NOTHING; + '["operativo","macro_n1"]'::jsonb +) ON CONFLICT (id) DO NOTHING; -- ============================================================ --- 3. Encuesta: Mapeo de Cuidadores --- Anónima + Sensible (contiene datos de salud/discapacidad) + Confidencial --- Modo A: nosotros como responsables del tratamiento --- k_threshold=5: ninguna celda expuesta con n<5 +-- 3. Encuesta — anónima / sensible / confidencial / Modo A / k=5 -- ============================================================ INSERT INTO public.surveys ( - id, org_id, title, status, - is_anonymous, data_sensitivity, security_class, controller_role, + id, org_id, title, status, is_anonymous, + data_sensitivity, security_class, controller_role, consent_version_id, k_threshold ) VALUES ( '30000000-0000-0000-0000-000000000001', '10000000-0000-0000-0000-000000000001', - 'Mapeo de Cuidadores — Edición 2026', + 'Mapeo de Cuidadores — 2026', 'draft', - true, -- anónima (regla no negociable #2: respondent_id siempre NULL) - 'sensible', -- contiene preguntas de salud/discapacidad (B5) - 'confidencial', -- acceso restringido a la empresa y analistas internos - 'A', -- Modo A: InQ es responsable del tratamiento (v1 solo Modo A) + true, + 'sensible', + 'confidencial', + 'A', '20000000-0000-0000-0000-000000000001', - 5 -- umbral k-anonimato por defecto -) -ON CONFLICT (id) DO NOTHING; + 5 +) ON CONFLICT (id) DO NOTHING; -- ============================================================ --- 4. Preguntas de la encuesta --- Orden: position define el flujo de presentación --- conditional_rules en el formato: [{ if_question, op, value, action, target }] --- if_question = code de la pregunta trigger --- target = code de la pregunta afectada +-- 4. Preguntas (34) — DELETE+INSERT para idempotencia total +-- +-- Estructura condicional (SEED_SPEC §Estructura): +-- cond-B: B2-B5 visibles si B1 = 'Sí' +-- cond-C: C2-C5 visibles si C1 = 'Sí' +-- cond-D: D2-D5 visibles si D1 = 'Sí' +-- Resto: siempre visible (top-level) -- ============================================================ +DELETE FROM public.questions +WHERE survey_id = '30000000-0000-0000-0000-000000000001'; --- B1: Pregunta disparadora — ¿Tenés persona a cargo? --- Si es "yes" → se despliegan B2, B4, B5 -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, conditional_rules -) + +-- ══════════════════════════════════════════════════ +-- SECCIÓN A — Datos Generales (cuasi-identificadores) +-- qi_sector ← A1 · qi_age_bucket ← A2 · qi_zone = NULL +-- ══════════════════════════════════════════════════ + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) VALUES ( '40000000-0000-0000-0000-000000000001', '30000000-0000-0000-0000-000000000001', - 'B1', - 'yes_no', - '¿Tenés a cargo a una o más personas con discapacidad permanente o adultos mayores ' - '(60 años o más) que requieran cuidados especiales de forma regular?', - 1, - false, - true, + 'A1', 'single_choice', + '¿En qué área o gerencia trabajás?', + 1, false, false, '[ - {"if_question": "B1", "op": "eq", "value": "yes", "action": "show", "target": "B2"}, - {"if_question": "B1", "op": "eq", "value": "yes", "action": "show", "target": "B4"}, - {"if_question": "B1", "op": "eq", "value": "yes", "action": "show", "target": "B5"} + {"value":"Operaciones/Producción","label":"Operaciones/Producción"}, + {"value":"Comercial/Ventas","label":"Comercial/Ventas"}, + {"value":"Administración/Finanzas","label":"Administración/Finanzas"}, + {"value":"RRHH/Cultura","label":"RRHH/Cultura"}, + {"value":"Tecnología/Sistemas","label":"Tecnología/Sistemas"}, + {"value":"Logística/Distribución","label":"Logística/Distribución"}, + {"value":"Otra área","label":"Otra área"} ]'::jsonb -) -ON CONFLICT (id) DO NOTHING; +); --- B2: ¿Cuántas personas a cargo? (condicional a B1=yes) -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, options -) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) VALUES ( '40000000-0000-0000-0000-000000000002', '30000000-0000-0000-0000-000000000001', - 'B2', - 'single_choice', - '¿Cuántas personas a tu cargo requieren cuidado especial?', - 2, - false, - false, + 'A2', 'single_choice', + '¿Cuántos años tenés?', + 2, false, false, '[ - {"value": "1", "label": "1 persona"}, - {"value": "2", "label": "2 personas"}, - {"value": "3+", "label": "3 o más personas"} + {"value":"Menos de 25","label":"Menos de 25"}, + {"value":"25-34","label":"25-34"}, + {"value":"35-44","label":"35-44"}, + {"value":"45-54","label":"45-54"}, + {"value":"55+","label":"55+"}, + {"value":"Prefiero no decir","label":"Prefiero no decir"} ]'::jsonb -) -ON CONFLICT (id) DO NOTHING; +); --- B4: Relación con la persona a cargo (condicional a B1=yes) -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, options -) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) VALUES ( '40000000-0000-0000-0000-000000000003', '30000000-0000-0000-0000-000000000001', - 'B4', - 'single_choice', - '¿Cuál es tu relación con la principal persona que cuidás?', - 3, - false, - false, + 'A3', 'single_choice', + '¿Con qué género te identificás?', + 3, false, false, '[ - {"value": "hijo_a", "label": "Hijo/a"}, - {"value": "padre_madre", "label": "Padre, madre o suegro/a"}, - {"value": "conyuge", "label": "Cónyuge o pareja"}, - {"value": "hermano_a", "label": "Hermano/a"}, - {"value": "otro_familiar", "label": "Otro familiar"}, - {"value": "otra", "label": "Otra relación"} + {"value":"Femenino","label":"Femenino"}, + {"value":"Masculino","label":"Masculino"}, + {"value":"No binario/Otro","label":"No binario/Otro"}, + {"value":"Prefiero no decir","label":"Prefiero no decir"} ]'::jsonb -) -ON CONFLICT (id) DO NOTHING; +); --- B5: Tipo de discapacidad/condición (condicional a B1=yes) --- is_sensitive=true: contiene datos de salud (categoría especial Ley 7593/2025) -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, options -) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) VALUES ( '40000000-0000-0000-0000-000000000004', '30000000-0000-0000-0000-000000000001', - 'B5', - 'multiple_choice', - '¿Qué tipo de discapacidad o condición tiene la persona que cuidás? ' - '(Podés marcar más de una opción)', - 4, - true, -- SENSIBLE: dato de salud/discapacidad (Ley 7593, categoría especial) - false, + 'A4', 'single_choice', + '¿Cuál es tu modalidad de trabajo actual?', + 4, false, false, '[ - {"value": "fisica", "label": "Física o motriz"}, - {"value": "visual", "label": "Visual"}, - {"value": "auditiva", "label": "Auditiva"}, - {"value": "mental", "label": "Mental o psicosocial"}, - {"value": "intelectual", "label": "Intelectual o cognitiva"}, - {"value": "am_sin_cert", "label": "Adulto mayor sin discapacidad certificada"}, - {"value": "otra", "label": "Otra condición"} + {"value":"Presencial","label":"Presencial"}, + {"value":"Remoto","label":"Remoto"}, + {"value":"Híbrido","label":"Híbrido"} ]'::jsonb -) -ON CONFLICT (id) DO NOTHING; +); --- C1: Impacto laboral --- Si es "yes" → se despliega G4 -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, conditional_rules -) + +-- ══════════════════════════════════════════════════ +-- SECCIÓN B — ¿Vivís con discapacidad? (is_sensitive=true: B1-B5) +-- cond-B: B2-B5 se muestran si B1 = 'Sí' +-- ══════════════════════════════════════════════════ + +-- B1: trigger — single_choice, is_sensitive=true, sin conditional_rules +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) VALUES ( '40000000-0000-0000-0000-000000000005', '30000000-0000-0000-0000-000000000001', - 'C1', - 'yes_no', - '¿Sentís que tu rol de cuidador/a afecta tu asistencia, puntualidad o rendimiento ' - 'en el trabajo?', - 5, - false, - true, + 'B1', 'single_choice', + '¿Vos mismo/a tenés alguna discapacidad o condición de salud permanente o de largo plazo?', + 5, true, false, '[ - {"if_question": "C1", "op": "eq", "value": "yes", "action": "show", "target": "G4"} + {"value":"Sí","label":"Sí"}, + {"value":"No","label":"No"}, + {"value":"Prefiero no decir","label":"Prefiero no decir"} ]'::jsonb -) -ON CONFLICT (id) DO NOTHING; +); --- D1: Apoyo recibido de la empresa --- Declarada como trigger de sub-preguntas; sub-preguntas se agregan en iteración posterior -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, conditional_rules -) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) VALUES ( '40000000-0000-0000-0000-000000000006', '30000000-0000-0000-0000-000000000001', - 'D1', - 'yes_no', - '¿Tu empresa te ofrece actualmente algún apoyo o beneficio pensado para personas que ' - 'cuidan a familiares con discapacidad o adultos mayores?', - 6, - false, - true, - '[]'::jsonb -- sub-preguntas a agregar en iteración posterior (mockup pendiente) -) -ON CONFLICT (id) DO NOTHING; + 'B2', 'multiple_choice', + '¿Qué tipo de discapacidad tenés? (podés marcar más de una)', + 6, true, false, + '[ + {"value":"Física/motriz","label":"Física/motriz"}, + {"value":"Visual","label":"Visual"}, + {"value":"Auditiva","label":"Auditiva"}, + {"value":"Intelectual","label":"Intelectual"}, + {"value":"TEA","label":"TEA"}, + {"value":"Psicosocial","label":"Psicosocial"}, + {"value":"Condición crónica","label":"Condición crónica"}, + {"value":"Otra","label":"Otra"} + ]'::jsonb, + '[{"if_question":"B1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); --- G4: Frecuencia de estrés (condicional a C1=yes) -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, options -) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) VALUES ( '40000000-0000-0000-0000-000000000007', '30000000-0000-0000-0000-000000000001', - 'G4', - 'single_choice', - '¿Con qué frecuencia la situación de cuidado te genera preocupación o estrés ' - 'durante tu jornada laboral?', - 7, - false, - false, + 'B3', 'single_choice', + '¿Contás con certificado oficial de discapacidad?', + 7, true, false, '[ - {"value": "nunca", "label": "Nunca"}, - {"value": "raramente", "label": "Raramente (1-2 veces por mes)"}, - {"value": "a_veces", "label": "A veces (1-2 veces por semana)"}, - {"value": "frecuentemente","label": "Frecuentemente (casi todos los días)"}, - {"value": "siempre", "label": "Siempre (todos los días)"} - ]'::jsonb -) -ON CONFLICT (id) DO NOTHING; + {"value":"Sí","label":"Sí"}, + {"value":"En trámite","label":"En trámite"}, + {"value":"No","label":"No"} + ]'::jsonb, + '[{"if_question":"B1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); --- H1: Apoyo preferido (max_select=3) -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required, max_select, options -) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) VALUES ( '40000000-0000-0000-0000-000000000008', '30000000-0000-0000-0000-000000000001', - 'H1', - 'multiple_choice', - '¿Qué tipos de apoyo de parte de la empresa valorarías más? ' - 'Elegí hasta 3 opciones.', - 8, - false, - false, - 3, -- max_select=3 (mockup H1) + 'B4', 'single_choice', + '¿Tu discapacidad afecta tu desempeño o comodidad en el trabajo?', + 8, true, false, '[ - {"value": "horario_flex", "label": "Horarios flexibles o trabajo híbrido"}, - {"value": "teletrabajo", "label": "Teletrabajo permanente"}, - {"value": "licencias", "label": "Licencias especiales para situaciones de cuidado"}, - {"value": "apoyo_eco", "label": "Apoyo económico o subsidio"}, - {"value": "orientacion", "label": "Orientación o asesoramiento profesional"}, - {"value": "grupos_apoyo", "label": "Grupos de apoyo entre pares"}, - {"value": "recursos_ext", "label": "Conexión con servicios o recursos externos"}, - {"value": "otro", "label": "Otro (especificar en comentarios)"} - ]'::jsonb -) -ON CONFLICT (id) DO NOTHING; + {"value":"Sí, significativamente","label":"Sí, significativamente"}, + {"value":"Sí, aspectos puntuales","label":"Sí, aspectos puntuales"}, + {"value":"No, bien gestionada","label":"No, bien gestionada"}, + {"value":"Prefiero no decir","label":"Prefiero no decir"} + ]'::jsonb, + '[{"if_question":"B1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); --- H3: Texto libre — NO expuesto en el store analítico crudo (regla #4 CLAUDE.md) -INSERT INTO public.questions ( - id, survey_id, code, type, prompt, position, - is_sensitive, required -) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) VALUES ( '40000000-0000-0000-0000-000000000009', '30000000-0000-0000-0000-000000000001', - 'H3', - 'text_long', - 'Si querés compartir algo más sobre tu situación o tenés sugerencias para la empresa, ' - 'podés hacerlo acá. (Opcional — tu respuesta es anónima)', - 9, - false, - false -) -ON CONFLICT (id) DO NOTHING; + 'B5', 'single_choice', + '¿La empresa conoce tu situación?', + 9, true, false, + '[ + {"value":"Sí, con apoyo","label":"Sí, con apoyo"}, + {"value":"Sí, sin apoyo","label":"Sí, sin apoyo"}, + {"value":"No, privado","label":"No, privado"} + ]'::jsonb, + '[{"if_question":"B1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + + +-- ══════════════════════════════════════════════════ +-- SECCIÓN C — Familiares con Discapacidad +-- is_sensitive=true: C1-C4 | C5: NOT sensitive +-- cond-C: C2-C5 se muestran si C1 = 'Sí' +-- ══════════════════════════════════════════════════ + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000010', + '30000000-0000-0000-0000-000000000001', + 'C1', 'single_choice', + '¿Tenés algún familiar cercano que viva con discapacidad?', + 10, true, false, + '[ + {"value":"Sí","label":"Sí"}, + {"value":"No","label":"No"}, + {"value":"Prefiero no decir","label":"Prefiero no decir"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000011', + '30000000-0000-0000-0000-000000000001', + 'C2', 'multiple_choice', + '¿Cuál es el vínculo? (podés marcar más de una)', + 11, true, false, + '[ + {"value":"Hijo/a","label":"Hijo/a"}, + {"value":"Cónyuge/pareja","label":"Cónyuge/pareja"}, + {"value":"Padre/madre","label":"Padre/madre"}, + {"value":"Hermano/a","label":"Hermano/a"}, + {"value":"Otro familiar","label":"Otro familiar"} + ]'::jsonb, + '[{"if_question":"C1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000012', + '30000000-0000-0000-0000-000000000001', + 'C3', 'multiple_choice', + '¿Qué tipo de discapacidad tiene? (podés marcar más de una)', + 12, true, false, + '[ + {"value":"Física/motriz","label":"Física/motriz"}, + {"value":"Visual","label":"Visual"}, + {"value":"Auditiva","label":"Auditiva"}, + {"value":"Intelectual","label":"Intelectual"}, + {"value":"TEA","label":"TEA"}, + {"value":"Psicosocial","label":"Psicosocial"}, + {"value":"Condición crónica","label":"Condición crónica"} + ]'::jsonb, + '[{"if_question":"C1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000013', + '30000000-0000-0000-0000-000000000001', + 'C4', 'single_choice', + '¿Esta persona requiere apoyo o cuidado cotidiano?', + 13, true, false, + '[ + {"value":"Alta dependencia","label":"Alta dependencia"}, + {"value":"Apoyo parcial","label":"Apoyo parcial"}, + {"value":"Autónomo/a","label":"Autónomo/a"} + ]'::jsonb, + '[{"if_question":"C1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000014', + '30000000-0000-0000-0000-000000000001', + 'C5', 'single_choice', + '¿Quién es el responsable principal del cuidado?', + 14, false, false, + '[ + {"value":"Yo principal","label":"Yo principal"}, + {"value":"Compartido","label":"Compartido"}, + {"value":"Cuidador pagado","label":"Cuidador pagado"}, + {"value":"Institución","label":"Institución"} + ]'::jsonb, + '[{"if_question":"C1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + + +-- ══════════════════════════════════════════════════ +-- SECCIÓN D — Adultos Mayores a Cargo +-- is_sensitive=true: D3, D4 | D1, D2, D5: NOT sensitive +-- cond-D: D2-D5 se muestran si D1 = 'Sí' +-- ══════════════════════════════════════════════════ + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000015', + '30000000-0000-0000-0000-000000000001', + 'D1', 'single_choice', + '¿Tenés algún adulto mayor (60+) a tu cuidado?', + 15, false, false, + '[ + {"value":"Sí","label":"Sí"}, + {"value":"No","label":"No"}, + {"value":"Prefiero no decir","label":"Prefiero no decir"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000016', + '30000000-0000-0000-0000-000000000001', + 'D2', 'single_choice', + '¿Cuántos adultos mayores están bajo tu cuidado?', + 16, false, false, + '[ + {"value":"1","label":"1"}, + {"value":"2","label":"2"}, + {"value":"3+","label":"3+"} + ]'::jsonb, + '[{"if_question":"D1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000017', + '30000000-0000-0000-0000-000000000001', + 'D3', 'single_choice', + '¿Qué nivel de dependencia tiene/n?', + 17, true, false, + '[ + {"value":"Supervisión","label":"Supervisión"}, + {"value":"Dependencia leve","label":"Dependencia leve"}, + {"value":"Dependencia moderada","label":"Dependencia moderada"}, + {"value":"Dependencia severa","label":"Dependencia severa"} + ]'::jsonb, + '[{"if_question":"D1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000018', + '30000000-0000-0000-0000-000000000001', + 'D4', 'multiple_choice', + '¿Tiene condición diagnosticada? (podés marcar más de una)', + 18, true, false, + '[ + {"value":"Demencia/Alzheimer","label":"Demencia/Alzheimer"}, + {"value":"ACV/Parálisis","label":"ACV/Parálisis"}, + {"value":"Enf. crónica","label":"Enf. crónica"}, + {"value":"Movilidad reducida","label":"Movilidad reducida"}, + {"value":"Deterioro cognitivo","label":"Deterioro cognitivo"}, + {"value":"Ninguna específica","label":"Ninguna específica"} + ]'::jsonb, + '[{"if_question":"D1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options, conditional_rules) +VALUES ( + '40000000-0000-0000-0000-000000000019', + '30000000-0000-0000-0000-000000000001', + 'D5', 'single_choice', + '¿La persona vive con vos o en otra vivienda?', + 19, false, false, + '[ + {"value":"Vive conmigo","label":"Vive conmigo"}, + {"value":"Otra vivienda","label":"Otra vivienda"}, + {"value":"Institución","label":"Institución"} + ]'::jsonb, + '[{"if_question":"D1","op":"eq","value":"Sí","action":"show"}]'::jsonb +); + + +-- ══════════════════════════════════════════════════ +-- SECCIÓN E — Tu Rol como Cuidador/a (top-level) +-- ══════════════════════════════════════════════════ + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000020', + '30000000-0000-0000-0000-000000000001', + 'E1', 'single_choice', + '¿Cuántas horas por día dedicás, en promedio, al cuidado directo?', + 20, false, false, + '[ + {"value":"Menos de 1h","label":"Menos de 1h"}, + {"value":"1-3h","label":"1-3h"}, + {"value":"3-6h","label":"3-6h"}, + {"value":"Más de 6h","label":"Más de 6h"}, + {"value":"Variable","label":"Variable"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000021', + '30000000-0000-0000-0000-000000000001', + 'E2', 'multiple_choice', + '¿En qué momentos realizás principalmente el cuidado? (podés marcar más de una)', + 21, false, false, + '[ + {"value":"Antes del trabajo","label":"Antes del trabajo"}, + {"value":"Durante horario laboral","label":"Durante horario laboral"}, + {"value":"Al llegar","label":"Al llegar"}, + {"value":"Durante la noche","label":"Durante la noche"}, + {"value":"Fines de semana","label":"Fines de semana"}, + {"value":"Continuo","label":"Continuo"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000022', + '30000000-0000-0000-0000-000000000001', + 'E3', 'single_choice', + '¿Contás con apoyo de otras personas para el cuidado?', + 22, false, false, + '[ + {"value":"Apoyo familiar suficiente","label":"Apoyo familiar suficiente"}, + {"value":"Apoyo insuficiente","label":"Apoyo insuficiente"}, + {"value":"Único responsable","label":"Único responsable"}, + {"value":"Apoyo contratado","label":"Apoyo contratado"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000023', + '30000000-0000-0000-0000-000000000001', + 'E4', 'single_choice', + '¿Tuviste que faltar al trabajo por el cuidado en el último año?', + 23, false, false, + '[ + {"value":"Nunca","label":"Nunca"}, + {"value":"Pocas veces (1-3)","label":"Pocas veces (1-3)"}, + {"value":"Varias veces (4-10)","label":"Varias veces (4-10)"}, + {"value":"Con frecuencia (10+)","label":"Con frecuencia (10+)"} + ]'::jsonb +); + + +-- ══════════════════════════════════════════════════ +-- SECCIÓN F — Impacto Económico (top-level) +-- ══════════════════════════════════════════════════ + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000024', + '30000000-0000-0000-0000-000000000001', + 'F1', 'single_choice', + '¿Cuánto estimás que gastás mensualmente en el cuidado?', + 24, false, false, + '[ + {"value":"Sin gastos significativos","label":"Sin gastos significativos"}, + {"value":"Menos de 500k","label":"Menos de 500k"}, + {"value":"500k-1.5M","label":"500k-1.5M"}, + {"value":"1.5M-3M","label":"1.5M-3M"}, + {"value":"3M-6M","label":"3M-6M"}, + {"value":"Más de 6M","label":"Más de 6M"}, + {"value":"Prefiero no decir","label":"Prefiero no decir"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000025', + '30000000-0000-0000-0000-000000000001', + 'F2', 'multiple_choice', + '¿Qué servicios o apoyos utilizás actualmente? (podés marcar más de una)', + 25, false, false, + '[ + {"value":"Terapias especializadas","label":"Terapias especializadas"}, + {"value":"Cuidador particular","label":"Cuidador particular"}, + {"value":"Centro de día","label":"Centro de día"}, + {"value":"Transporte adaptado","label":"Transporte adaptado"}, + {"value":"Medicación alto costo","label":"Medicación alto costo"}, + {"value":"Tecnología asistiva","label":"Tecnología asistiva"}, + {"value":"Apoyo ONG","label":"Apoyo ONG"}, + {"value":"Sin servicios formales","label":"Sin servicios formales"} + ]'::jsonb +); + +-- F3: rating — escala 1-5 (Sin impacto → Muy alto impacto) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000026', + '30000000-0000-0000-0000-000000000001', + 'F3', 'rating', + '¿Los gastos de cuidado impactan en tu situación económica personal?', + 26, false, false, + '{"min":1,"max":5,"min_label":"Sin impacto","max_label":"Muy alto impacto"}'::jsonb +); + + +-- ══════════════════════════════════════════════════ +-- SECCIÓN G — Bienestar y Descanso (top-level) +-- ══════════════════════════════════════════════════ + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000027', + '30000000-0000-0000-0000-000000000001', + 'G1', 'single_choice', + '¿Cómo describirías tu nivel de descanso habitual?', + 27, false, false, + '[ + {"value":"Descanso bien","label":"Descanso bien"}, + {"value":"Descanso irregular","label":"Descanso irregular"}, + {"value":"Me cuesta descansar","label":"Me cuesta descansar"}, + {"value":"Muy poco descanso","label":"Muy poco descanso"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000028', + '30000000-0000-0000-0000-000000000001', + 'G2', 'single_choice', + 'En los últimos 3 meses, ¿con qué frecuencia el cuidado afectó tu concentración o rendimiento laboral?', + 28, false, false, + '[ + {"value":"Nunca/casi nunca","label":"Nunca/casi nunca"}, + {"value":"Algunas veces al mes","label":"Algunas veces al mes"}, + {"value":"Varias veces por semana","label":"Varias veces por semana"}, + {"value":"Casi todos los días","label":"Casi todos los días"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000029', + '30000000-0000-0000-0000-000000000001', + 'G3', 'multiple_choice', + '¿Qué aspectos de tu vida se ven más afectados? (podés marcar más de una)', + 29, false, false, + '[ + {"value":"Tiempo libre","label":"Tiempo libre"}, + {"value":"Sueño y descanso","label":"Sueño y descanso"}, + {"value":"Vida social","label":"Vida social"}, + {"value":"Vida en pareja/familia","label":"Vida en pareja/familia"}, + {"value":"Salud física","label":"Salud física"}, + {"value":"Salud emocional","label":"Salud emocional"}, + {"value":"Desarrollo profesional","label":"Desarrollo profesional"}, + {"value":"Situación económica","label":"Situación económica"} + ]'::jsonb +); + +-- G4: rating — escala 1-5 (Muy mal → Muy bien) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000030', + '30000000-0000-0000-0000-000000000001', + 'G4', 'rating', + '¿Cómo evaluás tu bienestar general en este momento?', + 30, false, false, + '{"min":1,"max":5,"min_label":"Muy mal","max_label":"Muy bien"}'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000031', + '30000000-0000-0000-0000-000000000001', + 'G5', 'single_choice', + '¿Sentís que tu empresa comprende la realidad de ser cuidador/a?', + 31, false, false, + '[ + {"value":"Sí, acompañado/a","label":"Sí, acompañado/a"}, + {"value":"Parcialmente","label":"Parcialmente"}, + {"value":"No, invisible","label":"No, invisible"}, + {"value":"Nunca lo supo","label":"Nunca lo supo"} + ]'::jsonb +); + + +-- ══════════════════════════════════════════════════ +-- SECCIÓN H — Necesidades (top-level) +-- ══════════════════════════════════════════════════ + +-- H1: multiple_choice con max_select = 3 +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, max_select, options) +VALUES ( + '40000000-0000-0000-0000-000000000032', + '30000000-0000-0000-0000-000000000001', + 'H1', 'multiple_choice', + '¿Qué tipo de apoyo de tu empresa te ayudaría más? (hasta 3 opciones)', + 32, false, false, 3, + '[ + {"value":"Flexibilidad horaria/remoto","label":"Flexibilidad horaria/remoto"}, + {"value":"Info recursos y servicios","label":"Info recursos y servicios"}, + {"value":"Apoyo psicológico","label":"Apoyo psicológico"}, + {"value":"Espacio de escucha","label":"Espacio de escucha"}, + {"value":"Convenios descuentos","label":"Convenios descuentos"}, + {"value":"Grupos de pares","label":"Grupos de pares"}, + {"value":"Capacitación autocuidado","label":"Capacitación autocuidado"}, + {"value":"Nada, estoy bien","label":"Nada, estoy bien"} + ]'::jsonb +); + +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required, options) +VALUES ( + '40000000-0000-0000-0000-000000000033', + '30000000-0000-0000-0000-000000000001', + 'H2', 'single_choice', + '¿Estarías dispuesto/a a participar en un grupo de apoyo para cuidadores?', + 33, false, false, + '[ + {"value":"Sí, definitivamente","label":"Sí, definitivamente"}, + {"value":"Tal vez","label":"Tal vez"}, + {"value":"No por ahora","label":"No por ahora"}, + {"value":"Prefiero privacidad","label":"Prefiero privacidad"} + ]'::jsonb +); + +-- H3: text_long — opcional, NO exponer en store analítico crudo (regla 4 CLAUDE.md) +INSERT INTO public.questions + (id, survey_id, code, type, prompt, position, is_sensitive, required) +VALUES ( + '40000000-0000-0000-0000-000000000034', + '30000000-0000-0000-0000-000000000001', + 'H3', 'text_long', + '¿Querés compartir algo más sobre tu experiencia como cuidador/a? (opcional)', + 34, false, false +);