Modelo de datos
El modelo de datos de Vault refleja el alcance del producto: cubre
desde el pipeline comercial y los contratos hasta el catálogo de
productos del ecosistema, la configuración fiscal por cliente, el
audit cross-product y la matriz de acceso a EMI. Todo vive en
Supabase repartido entre los schemas emashared (compartido con
los demás productos) y emavault (propio). Los datos
extraordinariamente sensibles —información clínica de pacientes—
no están en Vault: viven en los productos respectivos (Clinic,
Lab y, aislada por separado por requerimientos de protección de
datos personales, Well).
Schemas Supabase
Sección titulada «Schemas Supabase»EMA Vault usa dos schemas dentro del proyecto emahub
(bzikofdvfvchntvfzyni):
emashared— datos transversales del ecosistema (tenants, users, EMI access, audit log).emavault— datos operacionales del back-office EMA Health.
Adicionalmente conecta a un proyecto Supabase separado
emawell (yvfxhrnghajwblyqtoel, sa-east-1) read-only por Ley
21.719 (datos de salud aislados).
Schema emashared (compartido)
Sección titulada «Schema emashared (compartido)»Mismas tablas que ya documentamos en Lab/Clinic. Vault es el provisionador de algunas:
emashared: tenants # Vault provisiona via /api/tenants/:id/provision tenant_products # Vault asigna products al tenant tenant_aidbox_credentials # Vault encripta AES-GCM y escribe (S9-3) tenant_emi_access # Vault administra via /emi-access (F082) tenant_slug_history # rename audit emi_apps # status per app (alpha/beta/ga) emi_invocations # audit log de cada call EMI (F080) users + user_roles # cross-product audit_log # destination del audit_trigger() de VaultSchema emavault
Sección titulada «Schema emavault»Tablas de operación interna:
emavault:
Vault users + permissions: vault_users # auth.users mirror + role + is_active vault_permissions # role × module × can_read × can_write vault_team_members # alias / display info
Negocio · Pipeline: leads # CRM kanban 7 etapas lead_emi_conversations # link leads ↔ emi_invocations (F083) assessments # Discovery-style assessments organizations # cliente / proveedor / partner / institución people # contactos × organizations organization_products # qué products tiene cada org
Negocio · Catálogo y pricing: catalog_services # servicios EMA catalog_costs # costos por servicio catalog_pricing # precios públicos pricing_costs # pricing tool — costos pricing_plans # planes pricing_quotes # cotizaciones generadas
Finanzas: finance_entries # multi-moneda exchange_rates # CLP/USD/UF/EUR diarios mrr_entries # MRR mensual UF contracts # con alertas vencimiento invoices # facturación interna fiscal_config # per-organización (identificador tributario del país, certificado, ambiente fiscal, tipos de documentos) dte_emissions_log # auditoría de emisiones electrónicas obligations # pagos, declaraciones, alertas
Producto: products # catálogo productos EMA + architecture_md product_layers # capas (frontend/backend/db/etc.) product_modules # módulos por producto product_features # features por módulo product_journeys # user journeys product_journey_steps # pasos del journey product_releases # releases con changelog_md product_release_items # items por release product_tech_stack # 6 categorías github_issues_cache # sync horario + webhook github_sync_log # log de syncs
Editorial: editorial_posts # blog/LinkedIn drafts + métricas
Operaciones: checklist_items # tareas operativas time_entries # horas por proyecto documents # repository ops wiki_pages # docs internas notifications # alertas in-app infra_resources # CF Workers, dominios, secrets inventory
Quality module (2026-04-05): product_quality # quality dashboard product_security # security posture product_metrics # KPIs producto
Brand: brand_assets # logo, color tokens, etc.Diagrama ER (núcleo Vault)
Sección titulada «Diagrama ER (núcleo Vault)»Tablas críticas (detalle)
Sección titulada «Tablas críticas (detalle)»vault_users + vault_permissions
Sección titulada «vault_users + vault_permissions»-- Mirror de auth.users con role y permisosCREATE TABLE emavault.vault_users ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), auth_id uuid REFERENCES auth.users(id), -- vault_users.id = auth.uid() email text UNIQUE NOT NULL, full_name text, role text CHECK (role IN ('admin','technical','commercial','finance','viewer')), is_active bool DEFAULT true, last_login timestamptz, created_at timestamptz DEFAULT now());
-- Matriz role × moduleCREATE TABLE emavault.vault_permissions ( role text NOT NULL, module text NOT NULL, -- dashboard, catalog, finance, dte, etc. can_read bool DEFAULT false, can_write bool DEFAULT false, PRIMARY KEY (role, module));tenants (provisioning)
Sección titulada «tenants (provisioning)»Vault es el escritor canonical de emashared.tenants desde
/api/tenants/:id/provision:
- INSERT en Aidbox: crear
Organizationraíz. - Aidbox: crear OAuth client + secret.
- AES-GCM encrypt + INSERT
tenant_aidbox_credentials. - POST X-Platform-Key a cada producto (clinic, lab, well) →
INSERT emashared.tenants + tenant_productsen cada uno. - INSERT
emashared.audit_log.
emi_invocations (audit log)
Sección titulada «emi_invocations (audit log)»CREATE TABLE emashared.emi_invocations ( id uuid PRIMARY KEY, tenant_id uuid NOT NULL, user_id uuid, app_slug text NOT NULL, -- 'emavault', 'emaclinic', 'emalab', etc. agent_name text, invocation_type text, -- 'chat', 'access-check' request_tokens int, response_tokens int, duration_ms int, lead_id uuid, -- F083 — link a leads.id si conversación nació allí created_at timestamptz DEFAULT now());audit_log (cross-product)
Sección titulada «audit_log (cross-product)»emashared.audit_log es destination de:
- Vault
audit_trigger()SQL (F085) — cubre 12 tablas enemavault. - Loggers cross-product (clinic, lab, well, etc.) cuando aplique.
- Operaciones manuales (
/api/audit/*).
Sanitización: campos con nombres
password|token|secret|api_key|private_key|aidbox_client_secret_encrypted
se reemplazan por [REDACTED] antes de loggear.
State machines
Sección titulada «State machines»Lead pipeline (kanban 7 etapas)
Sección titulada «Lead pipeline (kanban 7 etapas)»Probabilidad auto por etapa: 10% / 20% / 40% / 60% / 80% / 100% / 0%.
Contract lifecycle
Sección titulada «Contract lifecycle»Tenant provisioning
Sección titulada «Tenant provisioning»Product release
Sección titulada «Product release»Patrones de modelado
Sección titulada «Patrones de modelado»Slug-based subdominio
Sección titulada «Slug-based subdominio»Cada organization tipo cliente tiene un slug que define su
subdominio:
slug = "aurora"URL clinic = https://aurora.emahealth.ioURL lab = https://aurora.lab.emahealth.ioURL well = https://aurora.well.emahealth.iotenant_slug_history registra cambios de slug (F074) — pre-rename
sigue redireccionando 12 meses por compatibilidad.
Cross-product audit
Sección titulada «Cross-product audit»audit_log no se restringe a Vault — clinic/lab/well también escriben
ahí. Permite query unificado:
SELECT * FROM emashared.audit_logWHERE tenant_id = '<id>' AND created_at >= now() - interval '7 days'ORDER BY created_at DESC;EMI invocation linking a leads
Sección titulada «EMI invocation linking a leads»Cuando un lead inicia conversación con EMI desde el chatbot público:
- Lead se crea con
source='emi_chat'. - Cada call EMI se registra en
emi_invocationsconlead_id. - Vault Pipeline muestra badge violeta en el lead.
- Click en badge expande “Conversaciones EMI” con todas las invocaciones (F083).