Estado del documento
- Estado:
pilot.- Última revisión: 2026-03-26.
- Fuente de verdad / evidencia base: árbol actual del repo,
docs/MASTER_GOVERNANCE_REGISTER.md,git tag --list,.github/workflows/*,backend/api/urls.py.- Riesgos o lagunas abiertas: el único tag Git verificable en este corte es
v0.2.0-rc.0; cualquier narrativa dev0.4.0-rc.1en el repo debe leerse como borrador documental no verificado hasta que exista un tag/publicación real.
Aplicación móvil para pases de turno clínico construida con React Native (Expo) y TypeScript. Incluye un backend único en Django/DRF para FHIR, asistencia documental con IA y auditoría, además de una cola offline que garantiza la entrega de bundles FHIR incluso con conectividad intermitente.
Nombre comercial oficial: HANDOVER – Relevo Seguro de Enfermería
Subtítulo documental de trabajo: Sistema Clínico Digital para la Entrega y Continuidad del Turno de Enfermería
Referencia documental base: HANDOVER – Relevo Seguro de Enfermería, Sistema Clínico Digital para la Entrega y Continuidad del Turno de Enfermería.
Posicionamiento público de este repositorio: HANDOVER es hoy un piloto operativo de software clínico orientado a soporte de continuidad del turno de enfermería. El repo incluye documentación MDR/QMS útil como baseline de trabajo y trazabilidad, pero no debe presentarse como expediente regulatorio cerrado, certificación, autorización comercial ni software production-ready. Este software apoya la continuidad del turno de enfermería y no sustituye el juicio clínico.
Seguridad y control de acceso (resumen):
- Autenticación JWT con Auth0 (OIDC) en el backend Django.
- Autorización por roles (
nurse,supervisor,admin) y scopes clínicos (handover:write,handover:audit). - Endpoint
/api/me/capabilitiesexpone capacidades derivadas de roles y scopes.
Auditoría y trazabilidad (resumen):
- Eventos de auditoría estructurados sin PHI, con hash de payload y request IDs.
- Retención configurable y comando de limpieza de eventos.
Documentación de gobernanza y preparación regulatoria disponible en el repo:
Para ejecución de piloto clínico, auditoría interna y preparación regulatoria de NNN + ICEA+, usar este paquete documental:
- Plan de QA clínico + cumplimiento MDR: estrategia ejecutable de pruebas funcionales, integración, E2E, seguridad, rendimiento y estructura de evidencia para Anexo II.
- Matriz de trazabilidad NNN + ICEA+: tabla requisito → implementación → test → evidencia para control de cobertura regulatoria.
- Plantilla de informe de rendimiento por unidad: formato baseline vs post con métricas mínimas (mediana, P90, abandono/error, IA ON/OFF) y criterio de aceptación.
- Plantilla de registro de decisiones clínicas de IA: estructura para auditar sugerencia mostrada, aceptación/rechazo, contexto mínimo y timestamp.
- Checklist de ciberseguridad NNN + ICEA+: verificación operativa de logs/PHI, secretos, HMAC, rate limits, replay, retry offline e idempotencia.
Recomendación de uso: completar estos documentos por release candidate y enlazar sus evidencias en el expediente técnico/QMS antes de la aprobación Go/No-Go. Importante: este paquete queda ahora en estado piloto-grade trazable; no declara cumplimiento MDR total ni sustituye la evidencia operativa/regulatoria específica del entorno.
- Node.js 20
- pnpm 10
- Expo CLI (
pnpm dlx expo installinstala dependencias nativas cuando se añaden paquetes) - Python 3.10+ y SQLite/PostgreSQL si vas a ejecutar localmente el backend operativo Django/DRF incluido en
backend/
- Copia el archivo de ejemplo y ajusta las variables de OpenID Connect y FHIR:
cp .env.example .env
- Variables de Auth0/OIDC (cliente móvil):
EXPO_PUBLIC_AUTH0_DOMAIN+EXPO_PUBLIC_AUTH0_CLIENT_ID(recomendado para Auth0) o, en su defecto,EXPO_PUBLIC_OIDC_ISSUER+EXPO_PUBLIC_OIDC_CLIENT_ID.EXPO_PUBLIC_AUTH0_AUDIENCEoEXPO_PUBLIC_OIDC_AUDIENCEpara emitir access tokens con audiencia del API.EXPO_PUBLIC_OIDC_SCOPE(por ejemploopenid profile email offline_accesspara refresh tokens).- El flujo se resuelve en
src/security/OAuthService.tsy se integra ensrc/security/auth.tsx; las guardias RBAC viven ensrc/security/acl.ts.
FHIR_BASE_URLoEXPO_PUBLIC_FHIR_BASE_URLdefine la URL consumida porsrc/lib/fhir-client.tspara leer/escribir Bundles.EXPO_PUBLIC_ALLOWED_UNITSrestringe el acceso del cliente a unidades clínicas explícitas.HANDOVER_FHIR_VALIDATION_MODE: controla la validación de Bundles FHIR en el backend Django/DRF."off"(por defecto): el backend reenviará los Bundles sin validarlos."remote": se invocará$validatecontra el servidor FHIR (FHIR_BASE/Bundle/$validate) antes de reenviar; si se detectan erroreserror/fatalse responderá422con detalles.
- Variables de Auth0/OIDC (cliente móvil):
- Variables adicionales leídas desde Expo (
app.config.ts > extra) o el entorno:EXPO_PUBLIC_HANDOVER_FHIR_VALIDATION_MODE:off | local | remotecontrola la validación del cliente (por defectooffen desarrollo; en producción se recomiendaremotepara validar contra el servidor FHIR antes de enviar). Requiere que el backend tengaHANDOVER_FHIR_VALIDATION_MODE=remotepara que el servidor valide.EXPO_PUBLIC_API_BASE_URL(oAPI_BASE_URL) apunta al backend REST si se usa el servidor Django.EXPO_PUBLIC_STORAGE_NAMESPACEpersonaliza el espacio de almacenamiento seguro y el aislamiento de datos offline.- La clave de cifrado offline se genera en runtime y se persiste en almacenamiento seguro del dispositivo; no se acepta una semilla secreta desde el bundle cliente.
EXPO_PUBLIC_OFFLINE_REPLAY_MAX_ATTEMPTSyEXPO_PUBLIC_QUEUE_BACKOFF_BASEafinan la cola offline y el backoff exponencial.EXPO_PUBLIC_FAST_VALIDATE_BEFORE_QUEUEhabilita una validación remota rápida (Bundle/$validate) antes de encolar si hay conectividad. Si el servidor devuelve unOperationOutcomecon severidaderror/fatal, se muestra un alert con los detalles y no se encola el bundle; en modo offline sigue encolando para respetar offline-first. Recomendado en entornos de staging/producción para detectar problemas de estructura antes de ocupar la cola.- Voz + IA:
EXPO_PUBLIC_API_BASE_URL/API_BASE_URL: base única del backend Django/DRF.- STT usa siempre
POST /api/ai/transcribe(derivado como${API_BASE_URL}/api/ai/transcribe). EXPO_PUBLIC_AI_BACKEND_BASE_URL/AI_BACKEND_BASE_URL: backend Django/DRF para generación y refinado SBAR, STT y sugerencias. Si no se define, la app usaAPI_BASE_URL/apipor defecto.- Las claves reales del proveedor de IA viven solo en el backend (
OPENAI_API_KEYy compañía); el cliente no acepta claves del proveedor.
- La firma eIDAS cliente queda degradada: la app no acepta credenciales ni llamadas directas al proveedor desde Expo. Hasta disponer de un endpoint backend-mediated, solo se mantiene un mock local en desarrollo.
- Define
EXPO_TOKENo credenciales EAS en CI/CD cuando generes binarios firmados con Expo Application Services.
- El login usa OAuth 2.0/OIDC mediante
expo-auth-sessioncon Auth0. Define permisos y roles en el backend de identidad para que el claimroleincluya valores comonurse,adminoviewer. - Deep links de autenticación:
- Prod:
handover-pro://redirectyhandover-pro://logout. - Dev Client:
exp+handover-pro://redirect. - En Web se usan
--/redirecty--/logout(verapp.config.ts).
- Prod:
AuthProviderllamaconfigureFHIRClient({ getToken, ensureFreshToken })para que el FHIR client renueve tokens silenciosamente antes de cada request.- En Android se solicitan permisos para cámara, micrófono y notificaciones (ver
app.config.ts). El flujo de QR y notas de audio depende deandroid.permission.CAMERAyandroid.permission.RECORD_AUDIOrespectivamente. - Para pruebas sin un proveedor OIDC real, puedes habilitar la pantalla mock en
src/screens/LoginMock.tsxajustando las banderas de características enapp.config.ts. - Las guardias RBAC reutilizables viven en
src/security/acl.ts; usaensureRoleyensureUnitpara proteger nuevas pantallas.
safeFetchensrc/lib/net.tsfuerza HTTPS en producción, aplica timeouts y reintentos con backoff exponencial frente a errores 502/503/504, y añade cabeceras de idempotencia.- La cola offline (
src/lib/queue.ts+src/lib/sync.ts) genera UUID por bundle, persiste en SQLite y reintenta envíos cuando detecta conectividad con@react-native-community/netinfo. - Puedes inspeccionar y vaciar la cola desde la pantalla
SyncCenter(src/screens/SyncCenter.tsx). Los elementos consyncStatus=errormuestran el estado específico (incluyendo422 Error de validación FHIR), un badge “Error” y detalle de issues FHIR cuando el servidor devolvió unOperationOutcome. - Los borradores se guardan en SecureStore; al reconectar se validan mediante esquemas Zod antes de sincronizar.
- Los adjuntos (imágenes, documentos, audio) se capturan con
expo-image-picker,expo-document-pickeryexpo-file-system. Mantén estos paquetes endependenciespara asegurar compatibilidad con el SDK de Expo. - El flujo de audio utiliza
expo-audioy permisos de micrófono definidos enapp.config.ts.
- En móvil, usa Adjuntos → “Abrir nota de voz avanzada” para grabar audio, dictar o transcribir la nota. En web el dictado con micrófono se marca como no disponible.
- Dictado STT y transcripción IA usan un único endpoint DRF:
${API_BASE_URL}/api/ai/transcribe. - El frontend centraliza esta URL en
AI_TRANSCRIBE_ENDPOINT(derivada deresolveApiBaseUrl) y normaliza errores HTTP (401/413/415/5xx) sin loguear PHI. - SBAR con IA:
- Generación y refinado usan
AI_BACKEND_BASE_URL(/ai/summarize-sbary/ai/refine-sbar) y envían el bearer token real de sesión al backend Django/DRF. - Si el backend no está configurado, devuelve
401/403, o no responde, la UI muestra un borrador local por reglas de forma explícita para no bloquear el handover. - La sugerencia SBAR asistida queda en revisión humana antes de aceptarse o descartarse; no se trata como paso clínico obligatorio ni como automatización decisoria.
- Generación y refinado usan
- TTS usa
expo-speechy solo está disponible en iOS/Android; en web se muestra como no disponible. - Subida de audio a FHIR (opcional) requiere
API_BASE_URLcon el endpoint/upload/audio-to-fhir.
- Hashing y random bytes se resuelven vía
expo-cryptosin añadir polyfills globales decrypto. - La firma de bundles FHIR depende de
globalThis.crypto.subtle; si no está disponible, la firma se omite y el envío continúa sin bloquear la cola.
- El mapeo FHIR vive en
src/lib/fhir-map.tsy se expone víabuildHandoverBundle. Para evitar bloqueos en UI, usabuildHandoverBundleAsyncen flujos interactivos (defer en el event loop) y encapsula la creación del bundle dentro de callbacks memoizados. Así evitas recrear funciones costosas en cada render y preparas el terreno para futuras ejecuciones en Web Workers para web. - Las pruebas de estrés están en
src/lib/__tests__/fhir-map.performance.spec.tsy usanperformance.now()para capturar duraciones de escenarios pequeños/medianos/grandes. Ajusta los tamaños si necesitas calibrar tiempos en dispositivos de baja gama.
- La app ya no intenta firmar contra un proveedor eIDAS directamente desde el cliente.
- En desarrollo se conserva un mock local para no bloquear la UI. En producción, hasta disponer de un endpoint backend-mediated, la subida continúa como PDF no firmado y se registra la degradación de capacidad.
- La firma criptográfica autoritativa de Bundles FHIR sigue viviendo en el backend Django/DRF (
HANDOVER_PRIVATE_KEY_PATH,HANDOVER_PUBLIC_KEY_PATH,HANDOVER_SIGNATURE_DISABLED).
Se retiró el servidor auxiliar FastAPI de STT para unificar validación y seguridad en el backend Django/DRF.
Fuente de verdad operativa del backend en este corte:
manage.pyfijabackend.settingsbackend/api/urls.pypublica la API clínica operativaProcfilearrancagunicorn backend.wsgi- en esta rama no hay
main.pytrackeado en la raíz y, por tanto, no forma parte de la ruta operativa actual
La decisión queda registrada en docs/adr/0001-backend-source-of-truth.md.
| Método | Ruta | Descripción | Auth |
|---|---|---|---|
| POST | /api/fhir/transaction |
Transacción Bundle FHIR con validación remota opcional, attestation de cierre para relevos finales, firma/verificación digital de transporte y creación de AuditEvent. |
JWT + rol/scope clínico |
| POST | /api/ai/transcribe |
Transcripción de audio (STT) con multipart/form-data. |
JWT + handover:write |
| POST | /api/ai/summarize-sbar |
Resume notas clínicas en formato SBAR. | JWT + handover:write |
| POST | /api/ai/suggest-interventions |
Genera sugerencias de intervenciones de enfermería. | JWT + handover:write |
| POST | /api/upload/audio-to-fhir |
Sube audio y crea un DocumentReference en servidor FHIR. |
JWT + handover:write |
CLI (sin servidor auxiliar):
python manage.py transcribe_audio ./audio.m4a --language es- FHIR y validación:
FHIR_BASE,HANDOVER_FHIR_VALIDATION_MODE,HANDOVER_VALIDATE_STRICT,HANDOVER_REQUIRE_RBAC_ON_FHIR. - ICEA+:
ICEA_WEBHOOK_ENABLED,ICEA_WEBHOOK_URL,ICEA_WEBHOOK_SECRET,ICEA_WEBHOOK_TIMEOUT_MS,ICEA_WEBHOOK_RETRY_MAX,ICEA_WEBHOOK_ANTI_REPLAY,ICEA_WEBHOOK_REPLAY_WINDOW_SECONDS. - Firma digital:
HANDOVER_PRIVATE_KEY_PATH,HANDOVER_PUBLIC_KEY_PATH,HANDOVER_SIGNATURE_DISABLED. - IA:
OPENAI_API_KEY,OPENAI_MODEL_SBAR,OPENAI_MODEL_WHISPER,OPENAI_MODEL_SUGGESTIONS,AI_SUGGESTIONS_ENABLED. - Uploads de audio:
HANDOVER_MAX_AUDIO_BYTES(por defecto26214400, equivalente a 25 MB).
- Instala dependencias JavaScript:
pnpm -w install
- Levanta el backend operativo Django/DRF si necesitas un API REST local o validar la ruta clínica end-to-end:
python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt python manage.py migrate python manage.py runserver 0.0.0.0:8000
- Define
HANDOVER_ALLOWED_ORIGINS(p. ej.https://app.handover-pro.es,https://app.handover-pro.lat) para restringir CORS/ALLOWED_HOSTS en Django. - En producción mantén
ENABLE_SSL_REDIRECT=truey despliega detrás de un proxy TLS 1.3 con HSTS (ya habilitado enbackend/settings.py).
- Define
- Crea
backend/.enva partir del ejemplobackend/.env.exampley define:AUTH0_ISSUER_BASE_URLAUTH0_AUDIENCE
- En una terminal inicia el servidor:
python manage.py runserver 0.0.0.0:8000
- En otra terminal valida que los endpoints FHIR estén protegidos:
Debe responder
curl http://localhost:8000/api/fhir/transaction
401. - Con un JWT válido de Auth0 (reemplaza
<TOKEN>):Debe pasar autenticación (por ejemplo respondercurl -H "Authorization: Bearer <TOKEN>" http://localhost:8000/api/fhir/transaction422si el payload no es válido), pero no401. - Arranca el cliente Expo:
Usa la app Expo Go o un emulador (
pnpm expo start
pnpm expo run:android,pnpm expo run:ios,pnpm expo start --web).
- Genera un par de claves ECDSA (prime256v1) y guarda las rutas en variables de entorno:
openssl ecparam -name prime256v1 -genkey -noout -out private.pem openssl ec -in private.pem -pubout -out public.pem export HANDOVER_PRIVATE_KEY_PATH=$PWD/private.pem export HANDOVER_PUBLIC_KEY_PATH=$PWD/public.pem
- El backend (
/fhir/transaction) firma los Bundles antes de reenviarlos al servidor FHIR cuando ambas rutas están definidas yHANDOVER_SIGNATURE_DISABLEDno estrue. Si el cliente ya envíabundle.signature, se verifica con la clave pública y se rechaza con400si la firma es inválida. - En cierres finales, HANDOVER exige checklist completo, attestation de enfermera saliente, attestation autenticada de enfermera entrante y actores distintos; el actor entrante debe coincidir con el usuario autenticado que envía la transacción.
- La evidencia criptográfica de transporte se serializa en
bundle.signaturey se registra con hash único enHandoverSignatureAudit; esta evidencia no debe presentarse como firma profesional cualificada/eIDAS del relevo clínico. - En entornos de desarrollo se puede desactivar la firma criptográfica exportando
HANDOVER_SIGNATURE_DISABLED=true. Cuando la libreríacryptographyno está disponible, el backend recurre aopenssl dgstpara firmar/verificar usando las claves PEM configuradas.
La automatización usa Vitest como runner principal de frontend y pytest para Django/DRF.
- Revisar tipos:
pnpm -w typecheck - Linter estricto:
pnpm -w lint:ci - Runner principal JS:
pnpm test - Suites pilot-grade sensibles con cobertura:
pnpm -w test:pilot:coverage - Espejo local del gate JS de CI (incluye
test:e2e):pnpm -w quality:pilot:ci - Runner secundario Vitest general:
pnpm -w test:unit - Runner legacy de compatibilidad:
pnpm -w test:legacy - Runner backend:
pytest --ds=backend.settings --disable-socket --allow-hosts=127.0.0.1,localhost backend tests - Validación de bundles FHIR representativos:
pnpm -w validate:fhir
Los umbrales de cobertura sensibles están definidos en vitest.pilot.config.ts y se enfocan en auth/ACL, queue/sync, src/lib/fhir-map.ts, src/validation/schemas.ts, src/lib/profile-runtime.ts, src/screens/HandoverForm.tsx y src/screens/handover/submission.ts.
En local, pnpm -w test:pilot:coverage deja lcov.info bajo coverage/pilot-grade/. En CI, pnpm -w test:pilot:coverage:ci emite lcov.info y Cobertura XML bajo coverage/.
El workflow CI usa .nvmrc (20.17.0) y packageManager=pnpm@10.17.1 para fijar el toolchain del gate JS. En el estado actual del repo, el job de Node es bloqueante: instala dependencias con pnpm install --frozen-lockfile, ejecuta pnpm -w typecheck, pnpm -w lint:ci, pnpm -w gate:any-sensitive, pnpm -w test:pilot:coverage:ci, instala Playwright, corre pnpm -w test:e2e y valida bundles con pnpm -w validate:fhir.
La evidencia de RC publicada por CI incluye coverage-badge, coverage-pilot, playwright-evidence y fhir-validation. La evidencia backend (backend-coverage-xml) sigue en el workflow separado Django CI.
Puedes pilotar la visibilidad de funcionalidades por unidad sin redeploy usando defaults globales (EXPO_PUBLIC_SHOW_*) y overrides por unidad (HANDOVER_UNITS_JSON).
Ejemplo:
export EXPO_PUBLIC_SHOW_NIC_CODING=false
export EXPO_PUBLIC_SHOW_NOC_OUTCOMES=false
export EXPO_PUBLIC_SHOW_HANDOVER_TIMING_METRICS=false
export EXPO_PUBLIC_HIDE_LEGACY_FIELDS=false
export EXPO_PUBLIC_HANDOVER_UNITS_JSON='[
{
"id": "uci-adulto",
"name": "UCI Adulto",
"specialty": "icu",
"default": true,
"features": {
"showNicCoding": true,
"showNocOutcomes": true,
"showHandoverTimingMetrics": true,
"hideLegacyFields": true
}
},
{
"id": "pediatria",
"name": "Pediatría",
"specialty": "ped",
"features": {
"showNicCoding": "0",
"showNocOutcomes": "1"
}
}
]'Notas de robustez:
- Se aceptan valores booleanos y boolean-like (
true/false/1/0/on/off/yes/no) en features por unidad. - Si
HANDOVER_UNITS_JSONestá vacío, malformado o no es un arreglo válido, la app hace fallback automático a la configuración estática por defecto. - La activación productiva de perfiles y overlays se controla aparte con
EXPO_PUBLIC_HANDOVER_PROFILE_ACTIVATION_JSONoHANDOVER_PROFILE_ACTIVATION_JSON; el catálogo maestro queda centralizado ensrc/config/profiles/index.tsy un overlay no se activa sin un UPP compatible ya activo.
Los catálogos completos de NANDA, NIC y NOC se mantienen en modo BYO-license:
- el repo solo incluye placeholders mínimos para búsqueda y pruebas;
- los datasets completos se cargan bajo demanda desde variables de entorno, URL externa o endpoints backend cacheables;
- la UI muestra un gate explícito antes de habilitar el catálogo completo.
Frontend/Expo:
export EXPO_PUBLIC_NANDA_CATALOG_URL='https://terminology.example/nanda.json'
export EXPO_PUBLIC_NIC_CATALOG_URL='https://terminology.example/nic.json'
export EXPO_PUBLIC_NOC_CATALOG_URL='https://terminology.example/noc.json'Backend/Django:
GET /api/catalogs/nandaGET /api/catalogs/nicGET /api/catalogs/noc- Variables opcionales:
NANDA_CATALOG_JSON/NANDA_CATALOG_FILE,NIC_CATALOG_JSON/NIC_CATALOG_FILE,NOC_CATALOG_JSON/NOC_CATALOG_FILE - Respuestas versionadas con
licensed,version,warning,codes,ETagyCache-Control
Se recomienda activar Dependabot para revisar automáticamente librerías frontend/backend y recibir PRs con actualizaciones de seguridad. El archivo de configuración vive en .github/dependabot.yml y está preparado para el ecosistema npm/pnpm.
src/lib/net.ts: capa de red con timeouts, reintentos y bloqueo de HTTP en producción.src/lib/fhir-client.ts: cliente FHIR con manejo de OperationOutcome y cabeceras idempotentes.src/lib/queue.tsysrc/lib/sync.ts: sincronización offline de bundles con SQLite/Expo.scripts/validate-fhir.ts: validación de recursos FHIR durante CI o pipelines.docs/DEPLOY.md: guía de despliegue multiplataforma.
Consulta docs/DEPLOY.md para el estado real del despliegue. La topología automatizada prioritaria del repo es la exportación web estática en staging mediante Dockerfile + docker-compose.yml + .github/workflows/deploy-staging.yml; el backend Django sigue siendo un servicio separado con arranque gunicorn vía Procfile.
El estado consolidado de gobierno técnico y documental está en docs/MASTER_GOVERNANCE_REGISTER.md. En este corte del repo:
- el único tag Git verificable localmente es
v0.2.0-rc.0; CHANGELOG.mdyRELEASE_NOTES.mdconservan una narrativa heredada rotulada comov0.4.0-rc.1, pero esa etiqueta no está respaldada por un tag Git local verificable;package.jsonyapp.config.tssiguen en1.0.0como metadato de build, no como identificador fiable de release piloto.
Para publicar una RC nueva sin deriva documental:
- Ejecuta los cheques del gate sensible (
pnpm -w typecheck,pnpm -w lint:ci,pnpm -w gate:any-sensitive,pnpm -w test:pilot:coverage,pnpm -w test:e2e,pnpm -w validate:fhir,pytest --ds=backend.settings --disable-socket --allow-hosts=127.0.0.1,localhost backend tests). - Genera los binarios siguiendo la guía de despliegue.
- Crea el tag que realmente vaya a publicarse y actualiza
CHANGELOG.md,RELEASE_NOTES.mdy el registro maestro en el mismo corte. - Trata el tag Git +
RELEASE_NOTES.md+ los artefactos CI del corte como fuente de verdad del release piloto; no asumas quepackage.jsonoapp.config.tsreflejan ese identificador. - Si quieres bloquear merges o tags sin ese gate, configura branch protection / required checks en GitHub como follow-up manual; este repo solo puede documentarlo.
Explora la documentación técnica para conocer la arquitectura, configuración y flujos clave antes de contribuir al proyecto.
- Arquitectura general
- ADR-0001: backend source of truth
- Contrato base de perfiles clínicos
- Playbook de rollout y gate de reanudación
- Guía de onboarding
- Interoperabilidad FHIR
- Seguridad y autenticación
- Offline y cola
- Pruebas y CI
- Guía de despliegue
HANDOVER incluye ahora un puente analitico dedicado hacia ICEA+ que se activa solo despues de una transaccion clinica FHIR exitosa.
Que hace HANDOVER:
- estructura y mapea el Bundle FHIR a un payload analitico v1;
- envia la solicitud de scoring de forma desacoplada y no bloqueante;
- degrada de forma honesta si fallan outbox, persistencia tecnica, snapshot o bridge, sin cambiar el exito clinico ya confirmado;
- persiste estado visible, hash, warnings, modo de scoring y resumen minimo del resultado;
- expone endpoints
/api/icea/bridge/*solo para trazabilidad tecnica y superficies agregadas/admin autorizadas.
Que no hace HANDOVER:
- no ejecuta el motor matematico de ICEA+;
- no afirma conclusiones clinicas definitivas en
immediate_provisional; - no habilita dashboards nominales, scoring individual, resumen causal visible ni evaluacion profesional individual;
- no permite llamadas directas desde la app movil a ICEA+.
Flags principales:
- Backend:
ENABLE_ICEA_BRIDGE,ENABLE_ICEA_IMMEDIATE_SCORING=falsepor defecto,ENABLE_ICEA_ENRICHED_SCORING=falsepor defecto,ENABLE_ICEA_PATIENT_RISK=false,ENABLE_ICEA_CAUSAL_SUMMARY=false,ICEA_BRIDGE_MODEL_IDobligatorio para score real,ICEA_BRIDGE_SCORE_PATH=/api/v1/icea-plus/score/,ICEA_BRIDGE_STATUS_PATHopcional - Frontend:
EXPO_PUBLIC_ENABLE_ICEA_BRIDGE,EXPO_PUBLIC_ENABLE_ICEA_IMMEDIATE_SCORING=falsepor defecto,EXPO_PUBLIC_ENABLE_ICEA_ENRICHED_SCORING=falsepor defecto,EXPO_PUBLIC_ENABLE_ICEA_PATIENT_RISK=false,EXPO_PUBLIC_AI_SUGGESTIONS_ENABLED=false
Mientras el upstream ICEA+ no publique un endpoint real de status para score, HANDOVER no inventa polling: el estado local visible pasa a ser la fuente operativa y solo se intenta refresh remoto cuando el cliente pide refresh=true y existe ICEA_BRIDGE_STATUS_PATH configurado.
En postura de piloto prudente, HANDOVER conserva la trazabilidad tecnica del bridge pero suprime cualquier salida ICEA paciente-a-paciente en la UI operativa, incluido score individual, resumen causal, soporte bedside visible y cualquier uso nominal o punitivo.
Documentacion relacionada:
HANDOVER Core, offline-first, FHIR, MPAC, outbox ICEA, bridge y el contrato
handover-icea-feature-v1 ya existian antes de Build Week.
El commit funcional ba4b652 incorpora HANDOVER → ICEA Integration Readiness & Shadow Bridge
Verification, desarrollada con Codex + GPT-5.6 Sol. La feature verifica readiness, contrato y
governance de forma fail-closed; no garantiza compatibilidad entre feature-spaces previamente
incompatibles.
Session ID del hilo principal de desarrollo:
019f797f-63a3-70e1-b717-d51a11a8a2a4.
En una prueba cross-repository real, HANDOVER alcanzo una instancia ICEA local con JWT y RBAC de rol
service funcionales. El transporte obtuvo HTTP 200 y reached_icea=true, pero el verificador
detecto contract_mismatch porque el modelo demo disponible no era compatible con el feature-space
producido por HANDOVER. Esto demuestra la deteccion fail-closed, no compatibilidad end-to-end del
scoring. La deduplicacion del receptor permanece NOT_VERIFIED.