diff --git a/.gitignore b/.gitignore index fdcd584..b01f2d5 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ _diagrams/.$* # the publisher writes this to the root on every build Requirements-fromNarrative.json + +# editor settings +.vscode/ diff --git a/TODO.md b/TODO.md index 9567b84..046398e 100644 --- a/TODO.md +++ b/TODO.md @@ -1,21 +1,25 @@ # Pendientes -Este archivo reúne lo que el repositorio tiene marcado como pendiente. Cada entrada dice dónde vive, para que al resolverla se borren las dos cosas a la vez, la marca en su archivo y la línea de aquí. +Este archivo reúne lo que el repositorio tiene marcado como pendiente. Cada entrada dice a qué parte de la guía afecta, para que al resolverla se actualice esa parte y se borre la línea de aquí. ## Marcas en las páginas -1. **Rehacer en draw.io los diagramas de la sección 2.2.** Los tres diagramas de las pestañas son un mock en PlantUML y deben quedar como la Figura 2-1. En `input/pagecontent/volume-1-actors.md:8`. -2. **Alinear el tratamiento de la aplicación del paciente.** Figura como cliente en el Authorization Server y puede ser un cliente confidencial cuando tiene backend propio, y de eso depende si se la considera miembro y qué le exigen ATNA, CT y la auditoría. En `input/pagecontent/volume-1-groupings.md:31` (requiere discusión previa). -3. **Comprobar con pruebas qué guarda el registro de mensajes de X-Road.** Hay que saber si conserva los mensajes completos y cómo se configura, y reflejar el resultado en esa opción y en las decisiones de política de la sección 2.6. En `input/pagecontent/volume-1-options.md:37`. +1. **Rehacer en draw.io los diagramas de la sección 2.2.** Los tres diagramas de las pestañas son un mock en PlantUML y deben quedar como la Figura 2-1. Afecta a las figuras de la sección 2.2 en `input/pagecontent/volume-1-actors.md`. +2. **Alinear el tratamiento de la aplicación del paciente.** Figura como cliente en el Authorization Server y puede ser un cliente confidencial cuando tiene backend propio, y de eso depende si se la considera miembro y qué le exigen ATNA, CT y la auditoría. Afecta a la sección 2.4 en `input/pagecontent/volume-1-groupings.md` (requiere discusión previa). +3. **Comprobar con pruebas qué guarda el registro de mensajes de X-Road.** Hay que saber si conserva los mensajes completos y cómo se configura, y reflejar el resultado en esa opción y en las decisiones de política de la sección 2.6. Afecta a la Opción de Canal de Interconexión en `input/pagecontent/volume-1-options.md`. +4. **Definir la auditoría de una aplicación del paciente sin backend propio.** La aplicación ya opera casi como un miembro, pero puede no tener backend propio y hacer todo su flujo en el navegador de la persona, y por eso la sección 2.4 la deja por ahora fuera de ATNA y de CT. Hay que probar si ese flujo tiene limitantes y, si no las tiene, auditarla como a un miembro más. Va junto con el punto 2, porque los dos deciden si la aplicación se trata como miembro. Afecta a la Tabla 3-1 y a la auditoría de `input/pagecontent/volume-2.md`. ## Páginas declaradas pero no escritas -La estructura completa de la guía ya está en `sushi-config.yaml`, comentada hasta que cada parte exista. Son treinta páginas repartidas así. +La estructura completa de la guía ya está en `sushi-config.yaml`, comentada hasta que cada parte exista. Son diecinueve páginas repartidas así. -1. **El Volumen 2 entero**, once páginas contando su portada y el índice de transacciones, con ITI-65, ITI-67, ITI-68, ITI-83, ITI-104, ITI-90 y las tres transacciones propias HIX-1, HIX-2 y HIX-3, desde la línea 69. -2. **La sección de conformidad**, seis páginas con las ediciones soportadas, la matriz de requisitos, las desviaciones respecto a IHE, las extensiones propias y los artefactos, desde la línea 107. +1. **Las consideraciones entre perfiles y despliegue del Volumen 1**, una página, en la línea 67. +2. **El Volumen 3 entero**, ocho páginas contando su portada, con los metadatos del puntero, la identidad del paciente, los recursos del directorio, los claims de autorización, el consentimiento y las etiquetas de seguridad, los registros de auditoría y la terminología, desde la línea 83. +3. **La sección de conformidad**, seis páginas con las ediciones soportadas, la matriz de requisitos, las desviaciones respecto a IHE, las extensiones propias y los artefactos, desde la línea 99. +4. **Tres apéndices**, la justificación del diseño, las referencias y el historial de cambios, desde la línea 115. +5. **La página de descargas**, una página, en la línea 121. -Nota: las dependencias en el archivo de sushi están comentadas para evitar problemas con el CI de despliegue durante la escritura de estas páginas. En el release formal se descomentaran y se hará la integration completa a la guía. +Nota: las dependencias del archivo de sushi ya están activas. Queda la integración completa de sus artefactos en la guía para el release formal. ## Capacidades aplazadas a una versión posterior diff --git a/_diagrams/central-architecture-diagram.drawio b/_diagrams/central-architecture-diagram.drawio index 33d6e23..50c08f1 100644 --- a/_diagrams/central-architecture-diagram.drawio +++ b/_diagrams/central-architecture-diagram.drawio @@ -1,178 +1,174 @@ - + - + - + - + - - + + - - + + - + - - + + - - + + - + - + - - - - - - - - - - - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - - - - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + + + + + + + + + + diff --git a/_diagrams/hix-2-hix-1-recorrido.plantuml b/_diagrams/hix-2-hix-1-recorrido.plantuml new file mode 100644 index 0000000..15a491b --- /dev/null +++ b/_diagrams/hix-2-hix-1-recorrido.plantuml @@ -0,0 +1,118 @@ +@startuml hix-2-hix-1-recorrido +skinparam shadowing false +skinparam backgroundColor white +skinparam defaultFontName Verdana +skinparam defaultFontSize 12 +skinparam defaultFontColor #222222 +skinparam sequenceMessageAlign center +skinparam sequenceArrowThickness 1.75 +skinparam ParticipantPadding 4 +skinparam BoxPadding 4 +skinparam RoundCorner 8 + +skinparam sequence { + ArrowColor #333333 + LifeLineBorderColor #B5B5B5 + ParticipantBorderColor #666666 + ParticipantBackgroundColor white + ParticipantFontSize 12 + BoxBorderColor #D6D6D6 + BoxBackgroundColor #F6F7F8 + BoxFontColor #555555 + BoxFontSize 11 + GroupBorderColor #B5B5B5 + GroupBorderThickness 1 + GroupHeaderFontColor #555555 + GroupHeaderFontStyle plain + GroupFontColor #555555 + GroupFontStyle plain + GroupFontSize 11 + DividerBackgroundColor white + DividerBorderColor #C62828 + DividerFontColor #C62828 + DividerFontSize 11 +} + +skinparam legend { + FontSize 11 + BackgroundColor white + BorderColor #D6D6D6 +} + +skinparam note { + BackgroundColor #EAF5EC + BorderColor #9CC9A6 +} + +hide footbox + +' Colores de los tokens +!$SOL = "token del solicitante" +!$ACT = "token de actor" +!$INT = "token mediado" +!$NO = "#C62828" + +' La audiencia de cada token, dicha en claro +!$AUD_SOL = "audiencia: la infraestructura central" +!$AUD_ACT = "audiencia: el Authorization Server" +!$AUD_INT = "audiencia: solo el Laboratorio" + +box "Miembro solicitante" + participant "Hospital" as H +end box + +box "Infraestructura central" + participant "Record Locator\nService (RLS)" as RLS + participant "Authorization\nServer" as AS +end box + +box "Custodio" + participant "Laboratorio" as LAB +end box + +box "Otro custodio" + participant "Clínica" as CLI +end box + +H -[#2E6DB4]> RLS : (1) pide el documento [ITI-68]\ncon el $SOL\n$AUD_SOL + +RLS -[#2E6DB4]> AS : (2) comprueba [ITI-102]\nel $SOL +AS --> RLS : sigue vigente + +group Opcional [si no tiene un token de actor vigente] + RLS -[#6B6B6B]> AS : (3) pide su $ACT [ITI-71] + AS -[#6B6B6B]-> RLS : $ACT\n$AUD_ACT +end + +group Intercambio de tokens [HIX-1] + RLS -> AS : (4) pide un token para acceder al Laboratorio\nen nombre del solicitante\npresenta: el $SOL y el $ACT + + AS -[#2E8540]-> RLS : $INT\npermite al RLS actuar en nombre del solicitante\n$AUD_INT +end + +RLS -[#2E8540]> LAB : (5) pide el documento [ITI-68]\ncon el $INT + +note left of LAB + (6) valida el token con las JWKs + y lo acepta: su audiencia + es el Laboratorio +end note + +LAB --> RLS : documento +RLS --> H : (7) documento + +== Lo que nunca ocurre == + +H -[$NO]->x LAB : el solicitante no llega a ningún custodio por su cuenta:\nsolo a través del RLS, que es quien usa un $INT + +RLS -[$NO]->x H : el $INT\nnunca llega al solicitante + +RLS -[$NO]->x LAB : el $SOL y el $ACT\nnunca llegan a un custodio:\nsu audiencia no es ningún custodio + +RLS -[$NO]->x CLI : el $INT no vale ante la Clínica:\nsu audiencia es solo el Laboratorio + +legend bottom + La audiencia de un token dice ante quién vale. Cualquier otro lo rechaza. +endlegend + +@enduml diff --git a/_diagrams/hix-2-hix-1.plantuml b/_diagrams/hix-2-hix-1.plantuml new file mode 100644 index 0000000..dd77ac6 --- /dev/null +++ b/_diagrams/hix-2-hix-1.plantuml @@ -0,0 +1,24 @@ +@startuml hix-2-hix-1 +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam defaultFontSize 11 +skinparam sequenceMessageAlign center +skinparam ParticipantPadding 8 +skinparam sequence { + ArrowColor #333333 + LifeLineBorderColor #999999 + ParticipantBorderColor #555555 + ParticipantBackgroundColor white + GroupBorderColor #999999 +} + +participant "Record Locator\nService" as RLS +participant "Authorization\nServer" as AS + +opt sin token de actor vigente + RLS -> AS : [ITI-71] Get Access Token\n(client_credentials, token propio del RLS) + AS --> RLS : token de actor (aud = Authorization Server) +end +RLS -> AS : [HIX-1] Mediated Token Exchange\n(subject_token, actor_token, resource, scope) +AS --> RLS : JWT (aud = destino, sub = solicitante,\nact = RLS, vida ≤ 120 s) +@enduml diff --git a/_diagrams/hix-2-hix-2.plantuml b/_diagrams/hix-2-hix-2.plantuml new file mode 100644 index 0000000..1712f72 --- /dev/null +++ b/_diagrams/hix-2-hix-2.plantuml @@ -0,0 +1,33 @@ +@startuml hix-2-hix-2 +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam defaultFontSize 11 +skinparam sequenceMessageAlign center +skinparam ParticipantPadding 8 +skinparam sequence { + ArrowColor #333333 + LifeLineBorderColor #999999 + ParticipantBorderColor #555555 + ParticipantBackgroundColor white + ActorBorderColor #555555 + ActorBackgroundColor white + GroupBorderColor #999999 +} + +actor "Persona" as P +participant "Aplicación\ndel paciente" as APP +participant "Authorization\nServer" as AS +participant "Master Patient\nIndex" as PMIR + +APP -> AS : [HIX-2] Petición de autorización\n(response_type = code, resource = RLS,\nlaunch/patient, PKCE S256) +AS <-> P : autenticación y consentimiento +AS -> PMIR : [ITI-83] identidad verificada +PMIR --> AS : identidad maestra +AS --> APP : redirección (code, state) +APP -> AS : [HIX-2] Petición de token\n(authorization_code, code_verifier) +AS --> APP : token (aud = RLS), id_token,\nrefresh_token (con offline_access), patient +opt renovación, fuera de ITI-71 (token vencido y refresh token vigente) + APP -> AS : [HIX-2] Petición de token (refresh_token) + AS --> APP : token nuevo, mismo patient, sin ITI-83 +end +@enduml diff --git a/_diagrams/hix-actores-hospital.plantuml b/_diagrams/hix-actores-hospital.plantuml index 72ab4ee..29b581b 100644 --- a/_diagrams/hix-actores-hospital.plantuml +++ b/_diagrams/hix-actores-hospital.plantuml @@ -29,7 +29,7 @@ rectangle "Hospital (consumidor)" as HOSP #DAE8FC { rectangle "MHD Document Consumer" <> as H2 rectangle "PIXm / PDQm Consumer" <> as H3 } -rectangle "Authorization Server (STS)" as STS #F5F5F5 { +rectangle "Authorization Server" as STS #F5F5F5 { rectangle "IUA Authorization Server" <> as STS1 rectangle "OpenID Provider" <> as STS2 rectangle "PIXm Consumer" <> as STS3 @@ -38,16 +38,20 @@ rectangle "Record Locator Service (Mediador)" as RLS #D5E8D4 { rectangle "IUA Resource Server" <> as RLS1 rectangle "IUA Authorization Client" <> as RLS0 rectangle "MHD Document Responder" <> as RLS2 - rectangle "MHD Document Consumer (delegated)" <> as RLS3 - rectangle "PIXm / PDQm Consumer (delegated)" <> as RLS4 + rectangle "MHD Document Consumer" <> as RLS3 + rectangle "PIXm Consumer" <> as RLS4 +} +rectangle "Master Patient Index" as MPI #FFF2CC { + rectangle "PIXm Manager" <> as MPI1 + rectangle "PDQm Supplier" <> as MPI2 } rectangle "Custodio" as CUST #FFE6CC { rectangle "IUA Resource Server" <> as CUST1 - rectangle "MHD Document Responder" <> as CUST2 + rectangle "Servicio que aloja el contenido" <> as CUST2 } H1 --> STS1 : [ITI-71] Get Access Token\natención: purpose_of_use = TREAT\nemergencia: purpose_of_use = ETREAT -H3 --> RLS4 : atención: [ITI-83] resuelve su identificador local\nemergencia: [ITI-78] busca por datos demográficos -H2 --> RLS2 : [ITI-67] Find Document References\n[ITI-68] Retrieve Document -STS1 <-- RLS0 : [HIX-1] Custodian Token Exchange -RLS3 --> CUST2 : [ITI-68] Retrieve Document\ntoken derivado, aud = custodio +H3 --> MPI : atención: [ITI-83] resuelve su identificador local\nemergencia: [ITI-78] busca por datos demográficos +H2 --> RLS2 : [ITI-66] Find Document Lists\n[ITI-67] Find Document References\n[ITI-68] Retrieve Document +STS1 <-- RLS0 : [HIX-1] Mediated Token Exchange +RLS3 --> CUST2 : [ITI-68] Retrieve Document\ntoken mediado, aud = custodio @enduml diff --git a/_diagrams/hix-actores-laboratorio.plantuml b/_diagrams/hix-actores-laboratorio.plantuml index 7886c0b..28b0e19 100644 --- a/_diagrams/hix-actores-laboratorio.plantuml +++ b/_diagrams/hix-actores-laboratorio.plantuml @@ -28,23 +28,29 @@ rectangle "Laboratorio (custodio)" as LAB #DAE8FC { rectangle "IUA Authorization Client" <> as L1 rectangle "PIXm Patient Identity Source" <> as L2 rectangle "MHD Document Source" <> as L3 - rectangle "MHD Document Responder" <> as L4 + rectangle "Servicio que aloja el contenido" <> as L4 rectangle "IUA Resource Server" <> as L5 } -rectangle "Authorization Server (STS)" as STS #F5F5F5 { +rectangle "Authorization Server" as STS #F5F5F5 { rectangle "IUA Authorization Server" <> as STS1 rectangle "OpenID Provider" <> as STS2 rectangle "PIXm Consumer" <> as STS3 } +rectangle "Master Patient Index" as MPI #FFF2CC { + rectangle "PIXm Manager" <> as MPI1 +} +rectangle "Document Registry" as DR #E1D5E7 { + rectangle "MHD Document Recipient" <> as DR1 +} rectangle "Record Locator Service (Mediador)" as RLS #D5E8D4 { rectangle "IUA Authorization Client" <> as RLS0 rectangle "IUA Resource Server" <> as RLS1 - rectangle "MHD Document Consumer (delegated)" <> as RLS3 + rectangle "MHD Document Consumer" <> as RLS3 } L1 --> STS1 : [ITI-71] Get Access Token\npurpose_of_use = TREAT -L2 --> RLS : [ITI-104] Patient Identity Feed\nidentidad local + identificador nacional -L3 --> RLS : [ITI-65] Provide Document Bundle\npuntero con custodio y securityLabel -STS1 <-u- RLS0 : [HIX-1] Custodian Token Exchange -RLS3 --> L4 : [ITI-68] Retrieve Document\ntoken derivado, aud = laboratorio\ncuando otro miembro recupera +L2 --> MPI1 : [ITI-104] Patient Identity Feed\nidentidad local + identificador nacional +L3 --> DR1 : [ITI-65] Provide Document Bundle\npuntero con custodio y securityLabel +STS1 <-u- RLS0 : [HIX-1] Mediated Token Exchange +RLS3 --> L4 : [ITI-68] Retrieve Document\ntoken mediado, aud = laboratorio\ncuando otro miembro recupera L4 -[hidden]-> RLS1 @enduml diff --git a/_diagrams/hix-actores-paciente.plantuml b/_diagrams/hix-actores-paciente.plantuml index 4fd929f..87c179b 100644 --- a/_diagrams/hix-actores-paciente.plantuml +++ b/_diagrams/hix-actores-paciente.plantuml @@ -28,7 +28,7 @@ rectangle "Aplicación del paciente" as APP #DAE8FC { rectangle "IUA Authorization Client" <> as APP1 rectangle "MHD Document Consumer" <> as APP2 } -rectangle "Authorization Server (STS)" as STS #F5F5F5 { +rectangle "Authorization Server" as STS #F5F5F5 { rectangle "IUA Authorization Server" <> as STS1 rectangle "OpenID Provider" <> as STS2 rectangle "PIXm Consumer" <> as STS3 @@ -37,15 +37,15 @@ rectangle "Record Locator Service (Mediador)" as RLS #D5E8D4 { rectangle "IUA Resource Server" <> as RLS1 rectangle "IUA Authorization Client" <> as RLS0 rectangle "MHD Document Responder" <> as RLS2 - rectangle "MHD Document Consumer (delegated)" <> as RLS3 - rectangle "PIXm / PDQm Consumer (delegated)" <> as RLS4 + rectangle "MHD Document Consumer" <> as RLS3 + rectangle "PIXm Consumer" <> as RLS4 } rectangle "Custodio" as CUST #FFE6CC { rectangle "IUA Resource Server" <> as CUST1 - rectangle "MHD Document Responder" <> as CUST2 + rectangle "Servicio que aloja el contenido" <> as CUST2 } -APP1 --> STS1 : [HIX-2] Patient Application Launch\npurpose_of_use = PATRQT, FAMRQT o PWATRNY\npaciente = identidad maestra +APP1 --> STS1 : [HIX-2] Patient Application Launch\npurpose_of_use = PATRQT\npaciente = identidad maestra APP2 --> RLS2 : [ITI-67] Find Document References\n[ITI-68] Retrieve Document\ntoken aud = RLS, confinado al paciente -STS1 <-- RLS0 : [HIX-1] Custodian Token Exchange -RLS3 --> CUST2 : [ITI-68] Retrieve Document\ntoken derivado, aud = custodio +STS1 <-- RLS0 : [HIX-1] Mediated Token Exchange +RLS3 --> CUST2 : [ITI-68] Retrieve Document\ntoken mediado, aud = custodio @enduml diff --git a/_diagrams/hix-delegacion.plantuml b/_diagrams/hix-delegacion.plantuml index 8a976c5..a19b8cb 100644 --- a/_diagrams/hix-delegacion.plantuml +++ b/_diagrams/hix-delegacion.plantuml @@ -34,9 +34,9 @@ rectangle "Custodios" as CUSTODIOS #F4F4F4 { rectangle "Custodio B" as B } -M --> RLS : token del miembro\naud = RLS +M --> RLS : token del miembro\naud = Resource Servers centrales RLS --> AS : intercambio [HIX-1]\nresource = custodio X -AS --> RLS : token derivado\naud = custodio X\nsub = miembro\nact = RLS +AS --> RLS : token mediado\naud = custodio X\nsub = miembro\nact = RLS RLS --> REG : token\naud = Document Registry RLS --> A : token\naud = Custodio A RLS --> B : token\naud = Custodio B diff --git a/_diagrams/hix-flujo-identidad.plantuml b/_diagrams/hix-flujo-identidad.plantuml index 9853f34..8e24fee 100644 --- a/_diagrams/hix-flujo-identidad.plantuml +++ b/_diagrams/hix-flujo-identidad.plantuml @@ -13,27 +13,21 @@ skinparam sequence { } participant "Fuente autoritativa\n(p. ej. EDUS)" as SRC -participant "Registro de\nidentidad maestra" as PMIR -participant "Record Locator\nService" as RLS +participant "Master Patient\nIndex" as MPI participant "Custodio" as K participant "Consumidor" as C == Identidad maestra == -SRC -> PMIR : [ITI-93] Mobile Patient Identity Feed\n(identidad verificada) -PMIR -> PMIR : crea o actualiza\nla identidad maestra -PMIR --> SRC : 200 +SRC -> MPI : [ITI-93] Mobile Patient Identity Feed\n(identidad verificada) +MPI -> MPI : crea o actualiza\nla identidad maestra +MPI --> SRC : 200 == Identidad local de un miembro == -K -> RLS : [ITI-104] Patient Identity Feed\n(Patient local + identificador comunitario) -RLS -> RLS : dominio = organización del token -RLS -> PMIR : [ITI-104] (delegado) -PMIR -> PMIR : vincula la identidad local\ncon la identidad maestra -PMIR --> RLS : 200, o 422 si la persona\nno existe en la comunidad -RLS --> K : resultado +K -> MPI : [ITI-104] Patient Identity Feed FHIR\n(Patient local + identificador nacional) +MPI -> MPI : dominio = organización del token\nvincula la identidad local\ncon la identidad maestra +MPI --> K : 200, o rechazo por defecto si la persona\nno tiene identidad maestra == Resolución == -C -> RLS : [ITI-83] Cross-reference Query\n(identificador local o comunitario) -RLS -> PMIR : [ITI-83] (delegado) -PMIR --> RLS : identificadores de la persona -RLS --> C : identificadores permitidos\npor la política +C -> MPI : [ITI-83] Cross-reference Query\n(identificador local o nacional) +MPI --> C : solo la identidad maestra @enduml diff --git a/_diagrams/hix-flujo-localizacion.plantuml b/_diagrams/hix-flujo-localizacion.plantuml index b7d65b4..20a65fc 100644 --- a/_diagrams/hix-flujo-localizacion.plantuml +++ b/_diagrams/hix-flujo-localizacion.plantuml @@ -15,22 +15,22 @@ skinparam sequence { participant "Consumidor" as C participant "Authorization\nServer" as AS participant "Record Locator\nService" as RLS -participant "Registro de\nidentidad maestra" as PMIR +participant "Master Patient\nIndex" as PMIR participant "Document\nRegistry" as REG participant "Directorio" as DIR participant "Custodio" as K == Localización == C -> AS : [ITI-71] Get Access Token -AS --> C : token (audiencia: RLS) +AS --> C : token (audiencia: Resource Servers centrales) C -> RLS : [ITI-67] Find Document References\n(patient) [ITI-72] RLS -> AS : [ITI-102] Introspect Token AS --> RLS : activo, organización, propósito -RLS -> PMIR : [ITI-83] identidad maestra -PMIR --> RLS : identidad maestra RLS -> AS : [HIX-1] intercambio\n(resource = Document Registry) AS --> RLS : JWT (aud = registro, sub = consumidor,\nact = RLS, vida ≤ 120 s) RLS -> REG : [ITI-67] [ITI-72] +REG -> PMIR : [ITI-83] identidad maestra +PMIR --> REG : identidad maestra REG --> RLS : punteros RLS -> RLS : decisión de divulgación por puntero\nURL de contenido → RLS RLS --> C : Bundle de punteros divulgados @@ -41,7 +41,7 @@ RLS -> AS : [ITI-102] Introspect Token RLS -> RLS : relee el puntero\nrecomprueba la divulgación RLS -> DIR : [ITI-90] custodio → endpoint DIR --> RLS : endpoint activo del custodio -RLS -> AS : [HIX-1] Custodian Token Exchange\n(resource = custodio) +RLS -> AS : [HIX-1] Mediated Token Exchange\n(resource = custodio) AS --> RLS : JWT (aud = custodio, sub = consumidor,\nact = RLS, vida ≤ 120 s) RLS -> K : [ITI-68] Retrieve Document [ITI-72] K -> K : validación local del JWT @@ -51,5 +51,5 @@ alt el custodio responde else el custodio no responde RLS --> C : OperationOutcome (transitorio) end -note over C, K : Cada llamada del RLS a un servicio central o a un custodio va precedida de un intercambio [HIX-1] a nombre del solicitante; se muestra solo donde importa.\nCada actor registra sus eventos [ITI-20] bajo el identificador de correlación de la operación. +note over C, K : Cada llamada del RLS a un custodio, o a un actor central desplegado como sistema distinto, va precedida de un intercambio [HIX-1] a nombre del solicitante. Se muestra solo donde importa.\nCada actor registra sus eventos [ITI-20] bajo el identificador de correlación de la operación. @enduml diff --git a/_diagrams/hix-flujo-paciente.plantuml b/_diagrams/hix-flujo-paciente.plantuml index 42e8e53..455bbc7 100644 --- a/_diagrams/hix-flujo-paciente.plantuml +++ b/_diagrams/hix-flujo-paciente.plantuml @@ -18,10 +18,10 @@ actor "Persona" as P participant "Aplicación\ndel paciente" as APP participant "Authorization\nServer" as AS participant "Fuente autoritativa\n(p. ej. EDUS)" as SRC -participant "Registro de\nidentidad maestra" as PMIR +participant "Master Patient\nIndex" as PMIR participant "Record Locator\nService" as RLS -== Enrolamiento (una vez) == +== Enrolamiento (una vez, según la política de la comunidad) == P -> AS : crea su cuenta AS -> SRC : verificación de identidad SRC --> AS : identidad verificada diff --git a/_diagrams/hix-flujo-publicacion.plantuml b/_diagrams/hix-flujo-publicacion.plantuml index d3e57a3..084f291 100644 --- a/_diagrams/hix-flujo-publicacion.plantuml +++ b/_diagrams/hix-flujo-publicacion.plantuml @@ -14,27 +14,26 @@ skinparam sequence { participant "Custodio" as K participant "Authorization\nServer" as AS -participant "Record Locator\nService" as RLS -participant "Registro de\nidentidad maestra" as PMIR participant "Document\nRegistry" as REG +participant "Master Patient\nIndex" as MPI +participant "Directorio" as DIR K -> K : almacena el documento\nen su repositorio K -> AS : [ITI-71] Get Access Token -AS --> K : token (audiencia: RLS) -K -> RLS : [ITI-65] Provide Document Bundle\n(metadatos, URL relativa) [ITI-72] -RLS -> AS : [ITI-102] Introspect Token -AS --> RLS : activo, organización, propósito -RLS -> RLS : custodio = organización del token\nURL relativa\netiqueta de confidencialidad presente -RLS -> PMIR : [ITI-83] paciente local → identidad maestra -PMIR --> RLS : identidad maestra -RLS -> AS : [HIX-1] Token Exchange\n(resource = Document Registry) -AS --> RLS : JWT (aud = registro, sub = custodio,\nact = RLS, vida ≤ 120 s) -RLS -> REG : [ITI-65] puntero con\nsubject = identidad maestra [ITI-72] -REG --> RLS : 200 -RLS --> K : 200 -alt la comunidad rechaza la publicación - RLS --> K : 4xx con OperationOutcome +AS --> K : token (audiencia: Resource Servers centrales) +K -> REG : [ITI-65] Provide Document Bundle\n(metadatos, URL relativa) [ITI-72] +REG -> AS : [ITI-102] Introspect Token +AS --> REG : activo, organización, propósito +REG -> DIR : [ITI-90] ¿miembro activo? +DIR --> REG : organización activa +REG -> REG : custodio = organización del token\nURL relativa\netiqueta de confidencialidad presente\nidentidad local declarada por el custodio +REG -> MPI : [ITI-83] identificador → identidad maestra +MPI --> REG : identidad maestra +REG -> REG : registra el puntero con\nsubject = identidad maestra +REG --> K : 200 +alt el Document Registry rechaza la publicación + REG --> K : 4xx con OperationOutcome K -> K : revierte el documento local end -note over K, REG : Cada llamada del RLS a un servicio central o a un custodio va precedida de un intercambio [HIX-1] a nombre del solicitante.\nCada actor registra sus eventos [ITI-20] bajo el identificador de correlación de la operación. +note over K, MPI : Cada actor registra sus eventos [ITI-20] bajo el identificador de correlación de la operación. @enduml diff --git a/_diagrams/hix-master-patient-index.plantuml b/_diagrams/hix-master-patient-index.plantuml index 7666183..22179d1 100644 --- a/_diagrams/hix-master-patient-index.plantuml +++ b/_diagrams/hix-master-patient-index.plantuml @@ -17,7 +17,7 @@ rectangle "Hospital A" as A #F4F4F4 rectangle "Fuente autoritativa de identidad\n(p. ej. EDUS)" as SRC #F8F8F8 rectangle "Clínica B" as B #F4F4F4 -rectangle "Registro de identidad maestra" as MPI #EEF5EE { +rectangle "Master Patient Index" as MPI #EEF5EE { rectangle "Identidad local\n\nDominio del Hospital A\nPatient/349832" as LA rectangle "Identidad maestra\nuna por persona\n\nDominio verificado cédula 1-0234-0567" as MASTER rectangle "Identidad local\n\nDominio de la Clínica B\nPatient/123e4567" as LB diff --git a/_scripts/pagediff.py b/_scripts/pagediff.py index 042aba2..162d53a 100644 --- a/_scripts/pagediff.py +++ b/_scripts/pagediff.py @@ -21,6 +21,7 @@ # `| --- | :--: |`, the row that makes a table a table RULER = re.compile(r"^[ \t]*\|?[\s:|-]+\|?[ \t]*$") HEADING = re.compile(r"^#{1,6}[ \t]+(.*)$", re.M) +FENCE = re.compile(r"^[ \t]*(?:```|~~~)", re.M) NOTE = re.compile(r"^\[\^[^\]\n]+\]:") NOTEREF = re.compile(r"\[\^[^\]\n]+\]") # a that lands in front of a line's marker takes the line's meaning with it @@ -28,7 +29,7 @@ # Anything a mark would ruin by landing in the middle of it counts as one word: # a link cut in two stops being a link. WHOLE = "|".join(( - r"\[[^\]\n]*\]\([^)\n]*\)", # a link, text and target together + r"\[[^[\]\n]*\]\([^)\n]*\)", # a link, text and target together r"\[\^[^\]\n]*\]", # a footnote reference r"`[^`\n]*`", # code r"\*\*[^*\n]+\*\*", # bold @@ -74,14 +75,25 @@ def source(name, base): def blocks(text): - """The text as [block, gap, block, gap, ...]; "".join puts it back exactly.""" - return re.split(r"(\n[ \t]*\n)", text) + """The text as [block, gap, block, gap, ...]; "".join puts it back exactly. + A fenced code block stays one block across its blank lines: a mark that + opens inside the fence and closes outside it takes the page apart.""" + parts = re.split(r"(\n[ \t]*\n)", text) + out = [parts[0]] + for k in range(1, len(parts), 2): + if len(FENCE.findall(out[-1])) % 2: + out[-1] += parts[k] + parts[k + 1] + else: + out += [parts[k], parts[k + 1]] + return out def kind(block): head = block.lstrip() if NOTE.match(head): return "note" + if FENCE.match(head): + return "code" return {"#": "heading", "|": "table"}.get(head[:1], "text") @@ -133,6 +145,9 @@ def mark(old, new): i = pairs.get(j - j1) if i is None: out[j] = box("d-new", after) + elif kind(after) == "code": + # inside a fence a mark is only more code, so the bar says it all + out[j] = box("d-chg", after) elif kind(after) == "table": out[j] = box("d-chg", rows(was[i1 + i], after)) else: diff --git a/_scripts/preview.py b/_scripts/preview.py index 64d69db..e6de14b 100755 --- a/_scripts/preview.py +++ b/_scripts/preview.py @@ -19,7 +19,6 @@ import http.server import json import re -import socketserver import subprocess import sys from pathlib import Path @@ -49,14 +48,16 @@ """ -# Read before the page paints, so a reader who muted the marks never sees them -# flash, and a reader reviewing the branch never renders HEAD first. +# Read before the page paints, so a reader who muted the marks or hid the page +# list never sees them flash, and a reader reviewing the branch never renders +# HEAD first. SETUP_JS = """