1 Inleiding

Perfuse verplaatst klinische berichten tussen systemen die nooit zijn ontworpen om met elkaar te communiceren. Een laboratorium verstuurt resultaten in HL7 v2; het praktijkbeheersysteem verwacht ze met andere veldposities, een andere patiëntidentificatie en een bevestiging binnen vijf seconden. Iets moet in het midden zitten, en dat iets is een integratie-engine.

Deze handleiding beschrijft wat Perfuse doet, elke optie die het accepteert, en - waar een beslissing niet voor de hand ligt - waarom het op die manier werkt.

1.1 Waarvoor Perfuse is

Een enkele interface tussen twee klinische systemen wordt meestal geprijsd in de tienduizenden, met vijftien tot twintig procent van dat bedrag weer elk jaar in onderhoud. Een groot deel van die kosten is niet het werk; het is dat het werk iemand vereist die eerder HL7 heeft gedaan, en de meeste praktijken hebben zo iemand niet in dienst.

Perfuse is gebouwd op de veronderstelling dat de persoon die het configureert een probleem heeft om op te lossen en geen eerdere HL7-ervaring heeft. Die veronderstelling komt op specifieke plaatsen tot uiting:

Het hoofdstuk over testen en dat over migratie bestaan omdat het antwoord op "waarom zou ik dit vertrouwen" bewijs moet zijn dat u zelf verzamelt, niet een claim die hier wordt gemaakt.

1.2 Wat erin zit

Alles hieronder zit in één binaire bestand. Elke regel noemt het hoofdstuk dat het behandelt.

1.3 Standaarden en versies

Welke release van elke standaard Perfuse implementeert en hoe dat is gecontroleerd. "Gecontroleerd" noemt het externe hulpmiddel of referentie dat het resultaat heeft beoordeeld; waar niets extern het heeft beoordeeld, zegt het dat zo. Resultaten zijn van testgegevens, niet van een productiesite.

1.3.1 Berichtgeving en documenten

StandaardReleaseGecontroleerd
HL7 v2elke versie: berichten worden gelezen door hun eigen scheidingstekens, niet door een versieschema; bevestigingen zijn standaard 2.5.1NIST HL7 v2-validator; echte Mirth- en OIE-verkeer
HL7 v2 naar FHIRHL7's V2-naar-FHIR-mapping (ADT, ORU, SIU, MDM, VXU en de segmenten daarin)de HL7 FHIR-validator tegen US Core, UK Core, FR Core, ISiK, nl-core en HL7 Europa
FHIRR4 (4.0.1), met R4B en R5 gelezen en geschrevende HL7 FHIR-validator; Inferno
C-CDA en CDAC-CDA 2.1ONC SITE (C-CDA-voorbeelden verzonden en ontvangen via XDR); niet door een CDA-schematron
HL7 v3PIX en PDQ (IHE ITI-44, 45, 47)IHE's NE2008-schemas en voorbeeldberichten
DICOM en DICOMwebDIMSE C-STORE, C-FIND, C-MOVE, C-GET, C-ECHO; QIDO-RS, WADO-RS, WADO-URI, STOW-RSOrthanc
X12 (HIPAA)005010: 837, 835, 270/271 (X279A1), 276/277 (X212), 834, 278-aanvraag (X217) en onderzoek (X215); 275 in 006020 (X314)verzekeraars gepubliceerde companion guides; CMS esMD-voorbeelden
CAQH CORE-connectiviteitvC2.2.0 SOAP en MIME, vC4.0.0 met MTOMeen stand-in UM-systeem geschreven vanuit CAQH's regels
NCPDPTelecommunicatie D.0; SCRIPT 2023011 (en 2017071) met ePA; Real-Time Prescription Benefit v13geschreven vanuit de openbare Surescripts-companion guides en hun voorbeelden; niet tegen NCPDP's gelicenceerde schemas
UN/EDIFACTsyntaxis 3 en 4, CONTRLpydifact 0.1.8
IHE-documentdelingXDS.b, XCA, XDR, MHD 4.2.2, PIXm, PDQm, XDMhet NIST XDS Toolkit; ONC SITE
Direct secure messagingApplicability Statement 1.2, XDR en XDM voor Direct, DNS en LDAP-certificaatontdekkingONC SITE; ONC's Certificate Discovery Tool (18 van 18)
AS2RFC 4130, compressie RFC 5402pyas2lib
Ondertekende bijlagenHL7 DSDR, XAdES-X-Lxmlsec1, OpenSSL

1.3.2 FHIR-implementatiehandleidingen

GidsReleaseGecontroleerd
US Coreconversies naar 9.0.0 (USCDI v6); FHIR-server tegen 6.1.0 en 7.0.0de HL7-validator; Inferno US Core
SMART App Launch2.2Inferno: 80 van 80 (openbare app)
Bulk Data Access2.0.0Inferno: 48 van 48
Subscriptions R5 Backportvoor R4een echte HTTP-ontvanger; de PAS-kit's notificatietests
Da Vinci CRD2.2.1, en 2.1.0Inferno 2.2.1: 92 door, geen mislukt; 2.1.0 door de gids eigen voorbeelden
Da Vinci DTR2.2.0, en 2.1.0Inferno 2.2.0: 43 door, 2 mislukt (een kit-defect); 2.1.0 door de gids eigen voorbeelden
Da Vinci PAS2.2.1, en 2.1.0Inferno 2.2.1: 82 van 84; 2.1.0 door de gids eigen voorbeelden
Da Vinci PAS, verzenden (aanbiederszijde)2.2.1de HL7 Da Vinci PAS-verzekeringsreferentie-implementatie; geen productieverzekeringsmaatschappij
Da Vinci PDex2.2.0Inferno PDex 2.0: verzekeringsmaatschappij-tot-verzekeringsmaatschappij 19 van 19
Da Vinci HRex $member-match1.2.0Inferno PDex verzekeringsmaatschappij-tot-verzekeringsmaatschappij
Da Vinci ATR2.1.0niet gecontroleerd door een extern hulpmiddel
Da Vinci CDex $submit-attachment2.1niet gecontroleerd door een extern hulpmiddel
Da Vinci Plan-Net1.1.0Inferno: 199 door, 10 mislukt (een kit-defect)
Da Vinci US Drug Formulary2.1.0de HL7-validator
ISiK (Duitse ziekenhuizen), FHIR-serverStufe 5, Basis modulegematik's ISiK-testsuite 3.0.9: 421 van 421
PACIO Transitions of Care, Medication Profile, Advance Directives, Functioning1.0.0, 1.0.0, 2.0.0-ballot, 2.0.0PACIO's Inferno-kits met PACIO's eigen gegevens: elk falen in de gegevens of de kit. C-CDA naar TOC-document: de HL7-validator op HL7's voorbeelden, één fout over, de gids eigen
CARIN Blue Button2.2.0de HL7-validator
eCR2.1.2de HL7-validator
ELRHL7 2.5.1 ELR Release 1 met zijn errataONC's ELR-hulpmiddel: 28 van 28
International Patient Summary2.0.0de HL7-validator
DEQM5.0.0de HL7-validator
SQL on FHIRv2de officiële testsuite: 144 van 144
SMART Health Cards en LinksCards 1.4, Links STU 1de specificaties eigen voorbeeldkaart; een gepubliceerde SMART Health Links-bibliotheek
UDAP SecuritySTU 1een echte autorisatieserver en vertrouwensgemeenschap
TEFCA Facilitated FHIRSOP v2.0niet gecontroleerd tegen een echte QHIN

1.3.3 Nationale en Europese profielen

Gecontroleerd door het omzetten van gepubliceerde of verzonnen HL7 v2-berichten en het valideren van elke resource; de volledige resultaten en de redenen voor elk falen zijn in de repository's conformance/national-map.

ProfielReleaseBronnen geldig
UK CoreSTU2 2.0.2185 van 187
FR Core2.2.0138 van 156
ISiK Basismodul4.0.3 (Stufe 4)18 van 47; 42 van 47 met het eigen bundle script van het ziekenhuis
Nictiz nl-core0.12.1-beta.1 (zib 2020)12 van 24; 18 van 24 met het eigen bundle script van het ziekenhuis
HL7 Europe Laboratory Report2.1.0106 van 426 (de handleiding verwacht een document, een v2-resultaat is niet)
HL7 Europe Hospital Discharge Report1.0.068 van 69

Geen van dit is een certificering. Perfuse is niet gecertificeerd door ONC, CMS, gematik, Nictiz, NHS England of iemand anders.

1.4 Wat het vervangt

Perfuse dekt het terrein dat door Mirth Connect wordt ingenomen, en kan Mirth-kanaalexporten rechtstreeks importeren. Het hoofdstuk over migratie beschrijft wat schoon vertaalt, wat een beslissing nodig heeft, en hoe u het resultaat kunt bewijzen voordat u overschakelt.

De verschillen die ertoe doen in dagelijks gebruik zijn debuggen en stilte. In Mirth betekent het zien wat een transformatie met een bericht doet meestal het opnieuw implementeren van het kanaal met toegevoegde logging. In Perfuse kan elk opgenomen bericht opnieuw worden afgespeeld via de huidige configuratie en stap voor stap worden geïnspecteerd, zonder de actieve kanaal aan te raken. En waar een Mirth-waarschuwing voor "geen verkeer" een vaste drempel is die nutteloos is voor elke feed die 's nachts stil is, leert Perfuse wat elke feed normaal doet in een week en waarschuwt daarvoor.

1.5 Hoe deze handleiding te lezen

De eerste hoofdstukken zijn conceptueel en zijn het waard om in volgorde te lezen: kanalen, berichtstroom, dan transformatie. Alles daarna kan worden gelezen zoals nodig.

De referentiehoofdstukken aan het einde van dit document geven een overzicht van elke configuratiesleutel, het type, of het vereist is en de standaardwaarde. Deze hoofdstukken worden gegenereerd uit de bron, dus ze kunnen geen optie beschrijven die niet bestaat of eentje missen die wel bestaat. Als een sleutel in een configuratiebestand voorkomt en niet in de index, is het geen Perfuse-sleutel.

1.6 Conventies

Configuratie is YAML. De meeste sleutels zijn snake_case op de draad — max_message_size, idle_timeout — en deze handleiding geeft altijd de vorm op de draad, omdat dat is wat u typt. Er is één langdurige uitzondering, dataType op een kanaal, die camelCase is; het wordt op die manier gedocumenteerd in de kanaalreferentie en alleen in die spelling geaccepteerd.

Veldverwijzingen in HL7 gebruiken de gebruikelijke notatie: PID-5 is het vijfde veld van het PID-segment, PID-5.1 is de eerste component ervan, en PID-3(2) is de tweede herhaling van het derde veld. Een pad dat zonder herhaling is geschreven, adresseert elke herhaling (zie paden).

Duren worden geschreven als een nummer en een eenheid — 30s, 5m, 2h. Een naakt nummer is geen duur en wordt geweigerd in plaats van geraden.

2 Aan de slag

Perfuse is een enkele binaire bestand met een ingebouwde webinterface. Er is geen toepassingsserver om te installeren, geen database om te configureren en geen aparte beheerconsole.

2.1 Uitvoeren

perfuse serve -channels ./channels -db ./perfuse.db -addr 0.0.0.0:8443 \
  -tls-cert ./cert.pem -tls-key ./key.pem

-channels is een directory van YAML-bestanden, één per kanaal. -db is een SQLite-bestand dat opgenomen berichten, gebruikers en auditgeschiedenis bevat; het wordt gemaakt als het niet bestaat.

Bij de eerste start met geen geconfigureerde gebruikers, wordt een beheerdersaccount gemaakt en het wachtwoord naar het log geschreven. Dat wachtwoord kan niet later worden hersteld.

Uitvoeren zonder -tls-cert en -tls-key geeft plain HTTP. Dat is acceptabel op een lusback-adres voor een eerste blik en is niet acceptabel elders: de webinterface bevat referenties en berichtinhoud, die beide leesbaar zijn op de draad zonder TLS. Zie beveiliging.

2.2 Het eerste kanaal

Een kanaal heeft een naam, een bron en ten minste één bestemming nodig. Het kleinste bruikbare kanaal ontvangt HL7 via MLLP en schrijft elk bericht naar een bestand:

name: first-feed
dataType: hl7
source:
  type: mllp
  listen: "0.0.0.0:6661"
destinations:
  - name: to-disk
    type: file
    file:
      root: /var/spool/perfuse
      dir: incoming

Sla dat op als channels/first-feed.yaml en het wordt opgepikt zonder herstart.

Drie dingen over dat bestand zijn het vermelden waard, omdat ze de vorm van elk kanaal zijn:

2.3 Een kanaal bouwen vanuit de interface

Alles hierboven kan vanuit de webinterface worden gedaan, en voor een eerste kanaal is dat de betere route omdat het formulier u niet toestaat een bestand te produceren dat niet kan worden geladen.

De bouwer biedt drie manieren om binnen te komen:

  1. Vanuit een bericht dat iemand u heeft gestuurd. Plak het voorbeeld dat het lab of de leverancier u heeft gemaild. Perfuse leest het en stelt een kanaal voor, samen met drie afzonderlijke lijsten: wat het voorbeeld laat zien, wat is geraden en wat geen enkel voorbeeld kan vertellen. Dit wordt beschreven in testen.
  2. Vanuit iets dat al werkt. Een set complete kanalen die alleen hun adressen nodig hebben.
  3. Vanuit niets. Een leeg formulier. Beschikbaar, maar het is de langzaamste van de drie en de makkelijkste om verkeerd te doen.

2.4 Verifiëren dat het werkt voordat u iets verbindt

Twee dingen kunnen worden gedaan voordat het verzendende systeem bestaat.

Verzend een bericht met de hand vanuit de interface — de berichtverzender accepteert geplakt tekst en rapporteert wat er met het bericht is gebeurd, inclusief welke bestemmingen het hebben geaccepteerd en wat elke transformatie heeft gedaan.

Of genereer testverkeer. Als het kanaal al berichten heeft verwerkt, kan Perfuse hun vorm leren en meer berichten produceren die erop lijken, in dezelfde verhoudingen, zonder enige oorspronkelijke inhoud. Zie testen.

2.5 Wat u vervolgens moet doen

3 De webinterface

Perfuse is gebouwd op de veronderstelling dat alles kan worden gedaan vanuit de browser, en een functie die alleen kan worden bereikt door een bestand te bewerken, wordt behandeld als een defect. Dit hoofdstuk is een rondleiding door wat zich achter elk onderdeel van de navigatie bevindt, georganiseerd op de manier waarop de interface is: naar de vraag die u stelt.

De balk bevat Dashboard en Kanalen rechtstreeks, omdat de meeste sessies hier beginnen en eindigen. Alles anders is gegroepeerd, en de groepen zijn genoemd naar vragen in plaats van naar subsystemen — u gaat niet naar 'het auditsubsysteem', u gaat en vindt uit wie iets heeft gewijzigd.

3.1 Het lezen van de koptekst

Vijf dingen in de header zijn gemakkelijk te missen.

Elk overzicht heeft een adres. De adresbalk volgt het overzicht — #/channels, #/messages, #/settings — dus een herladen brengt u terug naar het overzicht, een bladwijzer opent het overzicht, een link die naar een collega is verzonden, brengt hen naar het overzicht en de terug-knop beweegt tussen overzichten in plaats van de console te verlaten. Een adres dat een overzicht boven uw rol noemt, opent in plaats daarvan het dashboard.

Zoeken, of ⌘K. Het zoekt over kanalen, instellingen, berichten en de handleiding, wat betekent dat het meestal sneller is dan navigeren — vooral voor een instelling waarvan u de naam maar half herinnert.

Thema. Drie ervan: Midnight, Dark en Light. Midnight is bijna zwart en is wat een wandweergave in een serverruimte meestal wil; Dark is een zachtere neutrale grijstint; Light is voor een laptop naast een raam. De keuze wordt opgeslagen in de browser in plaats van tegen het account, omdat een thema een eigenschap is van waar iemand zit, in plaats van van wie ze zijn — dezelfde operator wil Midnight op de wand en Light op de trein. De voorkeur van een machine wordt één keer geraadpleegd om een verstandige standaard te kiezen de eerste keer.

Taal. Het console is beschikbaar in het Engels (VK of VS datumnotatie), Duits, Frans, Nederlands, Spaans, Italiaans, Portugees, Pools, Zweeds, Deens, Noors of Fins, met datums en nummers die op de manier van die locatie worden geschreven. De keuze wordt opgeslagen in de browser en de taal van de browser wordt gebruikt totdat er een keuze is gemaakt. De vertalingen zijn gemaakt door een machine en zijn nog niet beoordeeld door moedertaalsprekers; Engels is de referentie en de keuzemogelijkheid geeft dit aan. Code, berichten, payloads, kanaalnamen en alles wat wordt getypt, worden nooit vertaald. De handleiding wordt gepubliceerd in dezelfde talen op https://perfuse.health/manual/<language>/ (de Handleiding van deze server is de Engelstalige versie).

Handleiding. Het document dat u aan het lezen bent, geserveerd door de actieve server. Het is hetzelfde bestand dat de binaire schrijver naar schijf kan schrijven, dus het beschrijft altijd de versie die voor u staat, in plaats van de laatste release.

3.2 Bewaken — of het werkt en wat er is gebeurd

3.2.1 Dashboard

De staat van elk kanaal, doorvoer en alles wat momenteel mis is. Dit is het scherm dat u open moet laten staan.

3.2.2 Berichten

Elk bericht dat is aangekomen, wat het is getransformeerd in, per bestemming en wat er mee is gebeurd. Doorzoekbaar, inclusief met een filteruitdrukking, dus 'laat me degenen van deze afzender zien die zijn afgewezen' is een query in plaats van een middag.

Een bericht kan van hieruit opnieuw worden afgespeeld en opnieuw worden verwerkt via de *huidige* configuratie, in plaats van de configuratie die live was op het moment — wat de manier is om te bevestigen dat een reparatie werkt tegen het verkeer dat het brak. Zie de berichtopslag voor wat wordt bewaard en voor hoe lang.

3.2.3 Wachtrij

Wat wacht op levering en waarom. Een wachtrij die niet leegloopt, is de meest bruikbare vroege waarschuwing die een integratiemotor produceert, en het is de moeite waard om te koppelen aan een waarschuwingsregel, zodat niemand hoeft te kijken. Zie levering.

3.2.4 Waarschuwingen

Wat is geactiveerd en wat de regels zijn. Regels worden hier bewerkt, in plaats van in een bestand. Zie waarschuwingen.

3.2.5 Metrische gegevens

Doorvoer, latentie en foutpercentages over tijd. Nuttig voor capaciteitsvragen en, vaker, voor bestuurderspakketten — wat de reden is waarom het logo van de site op het pakket verschijnt als er een is geüpload.

3.2.6 SQL op FHIR

SQL op FHIR-weergaven: kies een voorbeeld of een opgeslagen weergave, of schrijf er een, voer het uit over de FHIR-opslag van deze server (alle patiënten of één) of over resources die zijn geplakt, zie de rijen met hun typen en download CSV, NDJSON of Parquet. Opslaan houdt het voor de FHIR-eindpunkt $sql-run. Zie berichtformaten.

3.2.7 Kwaliteitsmetingen

Digitale kwaliteitsmaatregelen: kies een voorbeeld of een Maatregel in de FHIR-opslag, of schrijf er een met FHIRPath-criteria. Kies een meetperiode en een rapport (samenvatting, samenvatting met patiëntlijsten of één patiënt) en evalueer het over de FHIR-opslag of geplakte resources. Het scherm toont elke populatie telling en patiënten, de score en de strata. Download MeasureReport slaat het FHIR-resultaat op en Opslaan in de FHIR-opslag houdt de Maatregel voor Measure/$evaluate-measure. Maatregelen in CQL worden geweigerd: Perfuse heeft geen CQL-motor. Zie digitale kwaliteitsmaatregelen.

3.2.8 Stroomkaart

Een afbeelding van hoe berichten daadwerkelijk bewegen: welke bronnen welke kanalen voeden en welke bestemmingen ze bereiken.

De waarde ervan is geen decoratie. Elke onderneming houdt een kanaal dat niemand zich herinnert te hebben opgedragen en een bestemming die niemand realiseerde nog steeds in ontvangst nam, en beide zijn hier zichtbaar op een manier die ze niet zijn in een lijst met kanaalbestanden.

3.2.9 Teamdashboards

Een dashboard voor elk type persoon die de interfaces bekijkt: Operaties, Verbindingen, Interface-analist, Prioriteit, Beeldvorming, Omzetcyclus, Laboratorium, Privacy en beveiliging, en een eenvoudige afdelingsamenvatting. Tegels tonen tellingen, staten en tijden, nooit een bericht of een patiënt, zodat een dashboard naar een manager of een wand kan worden gestuurd zonder dat degenen die patiëntgegevens zien worden uitgebreid.

Elke persoon opent het dashboard van zijn of haar directorygroep of rol. -dashboards dashboards.yaml kaart ze toe:

groups: {PACS-Admins: imaging, Network-Team: connections}
roles: {viewer: manager}

Een groep wint van een rol, en iedereen die niet overeenkomt, opent op Operaties. Tegels ordenen verbergt en herschikt tegels, de kanaalkeuze filtert ze, en Opslaan als mijn weergave houdt deze als uw eigen dashboard totdat Reset.

Exporteren naar Grafana downloadt het dashboard als Grafana JSON via /metrics, met een gegevensbronvariabele en een kanaalfilter, voor iedereen die meer nodig heeft dan lichte configuratie. Tegels zonder metrische gegevens erachter worden weggelaten, en de exportbeschrijving noemt ze.

De Verbindingen-tegel controleert elke netwerkbestemming in lagen. Het zoekt de naam op, opent een TCP-verbinding, voltooit TLS waar het wordt gebruikt, en leest de laatste levering en mislukking van de bestemming uit echte verkeer. Elke mislukking zegt wat het betekent, bijvoorbeeld "geweigerd: de motor van de partner is waarschijnlijk gestopt", "time-out: een firewall of een VPN-tunnel die naar beneden is", of "een certificaat van een autoriteit die deze server niet vertrouwt". Niets wordt naar de partner verzonden, met één uitzondering: een immunisatieregister dat geen verkeer heeft gehad in zeven dagen, wordt gevraagd naar zijn CDC connectivityTest, die niets indient. Met -vpn tunnels.yaml leest de VPN-tunnels-tegel ernaast de staat van elke partnertunnel van AWS Site-to-Site VPN, een Azure VPN Gateway-verbinding of strongSwan op deze host, zodat een time-out kan worden onderscheiden van een tunnel die naar beneden is. Het vergelijkt ook beide zijden van IKE- en IPsec-instellingen, aangezien de cloud de onze rapporteert en het bestand de hunne vermeldt, en zegt waar ze niet kunnen overeenkomen. Verbindingsblad downloadt de instellingen van een partner naast elkaar als Markdown om naar hen te sturen; het bevat nooit een gedeelde sleutel. Cijfers die een dashboard nodig heeft die nog niet zijn opgenomen, worden vermeld onder Nog niet gemeten in plaats van als lege tegels te worden getekend.

De afdelingsdashboards berekenen hun eigen cijfers op de server, en elk zegt welk venster en welke bron het dekt:

3.2.10 Deling van wat een feed daadwerkelijk bevat

Profiel van deze feed rapporteert wat er echt aankomt: welke triggergebeurtenissen, welke velden zijn gevuld en hoe vaak, welke vormen de waarden aannemen, en welke codes een afzender daadwerkelijk gebruikt. Dat laatste is meestal het meest nuttige enkele feit erin.

Een profiel kan worden gedownload en naar iemand anders worden gestuurd. Het heeft een naam nodig en — vereist — welk systeem de feed heeft gegenereerd, omdat de vraag die een vreemde aan een gedeeld profiel stelt is of het zijn systeem beschrijft, en een optioneel veld zou 'Onbekend' het meest voorkomende antwoord maken in elke gedeelde collectie.

Het bevat geen patiëntgegevens, en dat wordt gecontroleerd in plaats van aangenomen. Een profiel is statistisch: tellingen, tarieven, lengtes, vormen. Waarden worden alleen bewaard voor velden die de standaard definieert als code-tabellen, omdat een code-tabelwaarde niet identificerend is. Identifier-waarden worden nooit vermeld.

Twee dingen volgen uit het feit dat dit een belofte is in plaats van een hoop. De server bouwt het profiel opnieuw op van de opgeslagen berichten wanneer u het exporteert, in plaats van het profiel dat op uw scherm staat te verzenden — dus wat het gebouw verlaat, is samengesteld door de profiler, die een test heeft om deze eigenschap te bewijzen, en niet door een browser. En de export weigert ronduit als een profiel ooit waarden voor een veld vermeldt dat geen codeertabel is, waarbij het veld wordt genoemd, maar niet de waarden.

Een profiel dat van elders aankomt, wordt op dezelfde manier gecontroleerd bij aankomst, om een andere reden: het is geproduceerd door iemand wiens zorg onbekend is, en het weergeven van de identificatoren van hun patiënten zou een schending zijn van de vertrouwelijkheid van deze server. Het importeren van een profiel verandert niets — een profiel beschrijft een feed, en wat u ermee moet doen, is een afzonderlijke beslissing.

3.3 Bouw — verander wat een kanaal doet en test het voordat het live gaat

3.3.1 Kanalen

De kanaalbouwer. Bronnen, bestemmingen, filters, transformaties, scripts en tests, met de gegenereerde YAML die naast het formulier wordt weergegeven terwijl u werkt — dus het bestand is nooit een mysterie, en iedereen die de voorkeur geeft aan het bestand, kan meelezen.

Zie kanalen voor de onderdelen en transformatie voor de acties die de stappen uitvoeren.

3.3.2 Scripts

Een werkbank voor scripts, los van de bouwer omdat het schrijven van een script en het aansluiten van een script verschillende activiteiten zijn.

Alle zeven sleuven worden aangeboden — filter, transformatie, preprocessor, postprocessor, schrijver, levenscyclus en lezer — en het kiezen van de juiste sleuf is belangrijk, omdat de sleuf bepaalt wat het script ontvangt en wat het wordt verwacht terug te geven. Het controleren van een script als het verkeerde type is geen oplossing; het compileert een ander ding.

JavaScript, Lua en WebAssembly zijn allemaal beschikbaar. Zie transformatie.

3.3.3 Contracten

Verwachtingen over hoe een feed eruit moet zien, hier gemaakt en gecontroleerd, evenals vanuit perfuse contract. Zie de opdrachtregel.

3.3.4 Tabellen

Zoektabellen en code-sets: de toewijzingen die de codes van het ene systeem omzetten in die van een ander. Hier bewerkbaar, zodat het toevoegen van een code geen implementatie is.

3.3.5 AI Mapper

Stelt veldtoewijzingen voor met een betrouwbaarheidsscore voor elk, en onthoudt zich van gokken. Ondanks de naam gebruikt het geen taalmodel en maakt het geen netwerkoproep: de suggesties komen van regels, veldnamen en de inhoud van het monster, op deze server. Het stelt ook een kanaal voor op basis van een enkel monsterbericht en geeft expliciet aan wat het monster niet kan zeggen. Dat tweede deel is het deel dat het betrouwbaar maakt - een voorstel dat er compleet uitzag, zou u uitnodigen om dingen te geloven die het bericht nooit heeft gezegd.

3.3.6 Speelplaats

Een schetsblok voor berichten en transformaties. Plak een bericht, pas stappen toe, zie het resultaat.

Niets wordt ergens naartoe gestuurd zodra de pagina is geladen, wat de reden is waarom het in deze vorm bestaat: het is veilig om iets echts in te plakken, met de garantie dat het in de browser blijft.

3.3.7 Schaduw

Verkeer door een kandidaatconfiguratie naast de live-configuratie en rapporteert de verschillen, zodat een wijziging kan worden aangetoond voordat deze wordt vertrouwd. Hetzelfde idee als perfuse compare, toegepast op een wijziging in plaats van op een migratie. Zie testing.

3.4 Uitwisseling — de standaarden die deze server spreekt met andere organisaties

3.4.1 FHIR-lab

Converteer HL7 v2 naar FHIR, valideer een resource en inspecteer het resultaat. De monsters omvatten opnames, laboratoriumresultaten, afspraken, klinische notities, immunisaties en een rapporteerbaar bezoek. De validatie omvat US Core, dat het profiel is waarin de Amerikaanse regelgeving is geschreven, dus dit antwoordt op de vraag "is wat ze ons hebben gestuurd eigenlijk conform" zonder iets te adopteren.

Openbaar gezondheidsrapport bouwt de eCR eICR die een casusrapportbestemming zou verzenden voor het bericht. Het toont welke triggercode het bezoek rapporteerbaar maakte, wat het rapport moest markeren als ontbrekend en het document zelf. Een bericht met niets rapporteerbaars krijgt de reden in plaats daarvan. Niets wordt van hieruit verzonden.

3.4.2 Abonnementen

FHIR-abonnementen en of hun notificaties aankomen: gebeurtenissen, geaccepteerd, in afwachting en de laatste reden waarom een werd geweigerd. Abonnementen worden gemaakt door FHIR-clients via de FHIR-API, niet vanaf deze pagina, en de referenties die ze de server hebben gegeven, worden nooit weergegeven. Zie berichtformaten.

3.4.3 Documenten

Klinische documenten — CDA en de afdrukbare vorm van een document. Nuttig wanneer het uitgewisselde object een ontslagbrief is in plaats van een bericht.

3.4.4 Documentdeling

Het IHE XDS.b-registratie- en repositorysysteem begon met -xds: hoeveel documenten, patiënten en indieningssets het bevat en hoeveel ervan zijn vervangen; de adressen van het repository, het register, de XCA-poort en de MHD; een zoekopdracht naar de documenten van een patiënt in dit register of een ander gemeenschapsregister (een ITI-18-register of een ITI-38-poort, met een token ervoor); en het publiceren van een CDA-document met de hand, met het faciliteitstype en de praktijkinstelling die een document niet vermeldt. Zie berichtformaten.

3.4.5 Direct

Directe beveiligde berichtenuitwisseling. De Direct-adressen van deze server lijst alle adressen op die een kanaal verstuurt of ontvangt, met het certificaat, wanneer het verloopt, de ankers die het vertrouwt en alles wat fout is (een ontbrekend bestand, een verlopen certificaat). Het adresboek bewaart de correspondenten en de certificaten waarvoor hun e-mail is versleuteld: plak er een van hun HISP in, of Sla op met het certificaat van DNS; een certificaat dat niet voor het adres of het domein is, wordt geweigerd. Vind een certificaat in DNS vraagt zonder op te slaan. Zie berichtformaten.

SMART Health Links en Cards, voor CMS's *Kill the Clipboard*. Ontvang een SMART Health Link leest de link of QR-code die een patiënt laat zien bij het inchecken, verifieert de health cards erin en verstuurt deze naar een kanaal. Deel een bezoekrecord maakt een link die deze server host, optioneel met een wachtwoord, en een QR-code voor de patiënt; Gebruik hun patiëntoverzicht vult deze met de patiënt's International Patient Summary uit deze server's FHIR-opslag. Links die deze server host lijst ze op met hoe vaak elk is opgehaald, wanneer het verloopt en het aantal wachtwoordpogingen, en herroept er een. Verifieer een SMART Health Card controleert een kaart's handtekening en uitgever op zichzelf. Zie CMS-0057 voor de serveropties die het nodig heeft.

3.4.7 Beeldvorming

Het archief dat deze server bijhoudt wanneer het wordt uitgevoerd met -dicomweb-archive: tellingen van studies, series, instanties en gebruikte ruimte, het DICOMweb-adres en de gegevensblok voor een OHIF-viewer, en een studiezoekopdracht op patiëntnaam, -ID, toegangsnummer en datum gemaakt met dezelfde QIDO-RS-aanvraag als een viewer. Een studie opent naar zijn series en instanties, en een instantie downloadt als een DICOM-bestand. Niets wordt weergegeven: Perfuse verplaatst afbeeldingen en een viewer toont ze. Zonder archief zegt het scherm hoe het kan worden ingeschakeld. Zie DICOMweb.

3.4.8 TEFCA

Het audittrail voor uitwisseling via een Qualified Health Information Network, en de regels voor het doel van het gebruik die het beheersen.

Twee transports, op echt verschillende stadia, en het scherm zegt welke van welke is. Één vlag die beide omvat zou verkeerd zijn in welke richting dan ook.

Facilitated FHIR is geïmplementeerd en heeft nooit contact gehad met een echte QHIN. Het volgt de Sequoia Project Standard Operating Procedure van 8 maart 2026: ontdek de UDAP-metadata van de partner, verifieer deze, registreer dynamisch, verkrijg een toegangstoken met het doel van het gebruik en vraag op. UDAP is een openbare sleutelinfrastructuur boven OAuth 2.0 — een vertrouwensgemeenschap verleent X.509-certificaten aan haar leden, en een lid authenticatie door JWT's te ondertekenen met de privésleutel en de certificaatketen toe te voegen.

De beveiligingslaag wordt geverifieerd tegen iemands anders implementatie, wat de enige verificatie waard is hier. Een registratie ondertekend door deze build werd naar een live derdepartijreferentieserver verzonden en geweigerd met unapproved_software_statement — Untrusted: Certificate is not a member of community. Om dat antwoord te produceren, decodeerde de server de aanvraag, parseerde de softwareverklaring als een JWT, controleerde de handtekening, liep de certificaatketen door en nam een beslissing over het lidmaatschap. Het is het verschil tussen worden weggestuurd bij de deur en een onleesbare brief terugkrijgen.

Wat overblijft kan niet van hieruit worden gedaan. Het certificaat dat het lidmaatschap van de gemeenschap bewijst, komt uit QHIN-onboarding en is niets wat software produceert. Totdat er een bestaat, voltooit geen enkele uitwisseling met een echte partner.

Hoe een kanaal vraagt. Een bestemming van het type tefca vraagt de Facilitated FHIR-partner set in Instellingen, TEFCA (tefca.partnerFHIRBase) voor elke berichtpatient: door identificator wanneer het bericht er een heeft (PID-3, of een FHIR-patientidentificator), anders door familienaam met geboortedatum, en nooit door een naam alleen, omdat een verkeerde match op een naam iemands anders record zonder fout retourneert. De bestemming stelt het doel van gebruik (behandeling, betaling, operaties, openbare gezondheid, individuele toegang) in; een doel dat de deelnemer niet verklaart, wordt geweigerd voordat er iets wordt verzonden. Doelen worden verzonden als TEFCA-uitwisselingsdoelcodes (T-TRTMNT, T-PYMNT, T-HCO, T-PH, T-IAS, systeem urn:oid:2.16.840.1.113883.3.7204.1.5.2.1), of met tefca.purposeCodes: hl7 als HL7-doelcodes voor gemeenschappen die deze gebruiken. De gevonden Bundle is het antwoord van de bestemming en kan worden doorgegeven aan een ander kanaal met results_to. Elke query, inclusief geweigerde, wordt weergegeven in het overzicht op dit scherm, dat de partner noemt.

Het hele pad, van ontdekking tot een token dat de FHIR-server van de partner accepteert, wordt getest tegen de udap-dotnet-referentieserver (zie verificatie).

De oudere QHIN-naar-QHIN-uitwisseling op basis van de IHE-profielen is niet geïmplementeerd. Een poging wordt geweigerd met een fout die zegt dat het niet is geïmplementeerd, en de weigering wordt geregistreerd als een mislukking. Dat is opzettelijk en niet een kwestie van een nette opkuisbeurt: een gestubde uitwisseling die succes rapporteert, zou vermeldingen in het audittrail toevoegen voor uitwisselingen die nooit hebben plaatsgevonden, en een trail die in strijd is met wat er is gebeurd, is erger dan geen trail, omdat de trail is wat wordt geloofd.

In de hele uitwisseling worden de eindpunten die voor uitwisseling worden gebruikt, afkomstig van het ondertekende deel van de metadata van een partner, nooit van het documentlichaam. Een handtekening verifiëren en vervolgens de eindpunten lezen uit de ondertekende kopie zou een ingewikkelde manier zijn om het netwerk te vertrouwen: een aanvaller die de reactie kan herschrijven, laat het ondertekende element ongemoeid, wijst de token-eindpunkt naar zijn eigen server en verzamelt clientasserties van iedereen die de handtekening controleerde en vervolgens negeerde wat het omvatte.

Een vertrouwensankerbundle is vereist en de afwezigheid wordt geweigerd bij het opstarten. Het controleren van de ondertekende metagegevens van een partner tegen het certificaat dat erin is opgenomen, bewijst alleen dat één partij beide heeft gemaakt — een fout die deze codebase eerder heeft gemaakt in SAML, waar de verifier de ingesloten certificaat prefereerde en een aanvaller als beheerder heeft geauthenticeerd, terwijl elke test is geslaagd. Neem de tussenliggende certificaten op in het bundle: een UDAP-server hoeft alleen zijn bladcertificaat te verzenden en de openbare referentieserver doet dit precies.

3.5 Verzekeraars — claims, voorafgaande autorisatie, medicijnen en de CMS-verzekeraarsregels

3.5.1 Claims & autorisatie

Bouw een X12 275 claimsbijlage in de 006020-vorm die CMS-0053-F aanneemt, van een geplakte C-CDA of een geüpload PDF, TIFF of JPEG, en zie deze teruglezen. Lees een 275 en download het document erin. Converteer een X12 278-beslissing naar een Da Vinci PAS ClaimResponse. Niets op deze pagina wordt opgeslagen of verzonden. Zie berichtformaten voor wat de 275 is opgebouwd en wat deze niet doet.

3.5.2 Medicijnen

De geneesmiddelenformularium geladen met -formulary, en de twee NCPDP-standaarden die ervan worden beantwoord. Formularium lijst de plannen en de geneesmiddelen op met hun tarief en vereisten, en waar de openbare Da Vinci US Drug Formulary API en de NCPDP-eindpunten zijn. Prijscontrole (RTPB) prijst een geneesmiddel voor een lid als een voorschrijver zijn Real-Time Prescription Benefit-aanvraag zou: de dekkingstatus, de beperkingen in woorden met hun codes, het aandeel van het lid en dat van het plan, en de goedkopere alternatieven. Voorafgaande autorisatie (ePA) verstuurt een SCRIPT-initiatie naar het eigen eindpunt van deze server, toont de vraagset als een formulier, verstuurt de antwoorden en toont de beslissing; hieronder, elke zaak met waar het staat en of de voorschrijver is geïnformeerd, de antwoorden van de zaak, een knop om een onverzonden beslissing opnieuw te verzenden, en de geneesmiddelcijfers die CMS-0062-P voorstelt. Zie CMS-0057.

3.5.3 CMS-0057

De verzekeraarskant van de CMS Interoperabiliteit en Voorafgaande Autorisatieregels, als vijf tools:

De conversies slaan niets op en verzenden niets.

3.5.4 CMS-gealigneerd netwerk

Klaarheid voor het CMS Interoperability Framework: elk van de 26 criteria, gegroepeerd zoals CMS deze groepeert, met wat Perfuse biedt, of het hier is ingeschakeld, de instelling die het inschakelt en wat de organisatie moet doen. De tellingen bovenaan filteren de lijst. Zie CMS-0057.

3.6 Beheer — wie wat kan doen en hoe deze server is ingesteld

3.6.1 Gebruikers

Accounts, rollen (monitor, viewer, operator, editor, admin) en kanaalgroepen. De kanaalgroepen van elke persoon worden ter plaatse bewerkt in de lijst; leeg betekent elk kanaal, en lab=editor, adt geeft een andere rol in één groep. Een beperkte beheerder tot sommige groepen ziet alleen de personen van die groepen. De koptekst toont uw eigen groepen naast uw rol wanneer u deze heeft. Zie beveiliging.

Machine-referenties zijn hier ook. Een token is voor een machine in plaats van een persoon: deze verloopt niet en wordt niet beïnvloed door iemand die afmeldt, wat een server nodig heeft die zijn buurman pollt. Alleen een hash wordt opgeslagen, dus een token wordt één keer getoond wanneer deze wordt gemaakt en kan niet worden hersteld — een gestolen database levert geen bruikbaar token op. Geef er de laagste rol die de taak doet.

Met MCP ingeschakeld, toont het gedeelte ook het adres waarop een AI-agent verbinding maakt, een clientconfiguratie om te kopiëren en elk hulpmiddel met de rol die het nodig heeft; het uitgeven van een token met Laat een AI-agent hiermee handelen geeft het mcp:write-bereik. Zie beveiliging.

3.6.2 Huurtussen

Op een gedeelde server, de lijst van organisaties van de platformbeheerder: elk met het aantal kanalen en de opgeslagen grootte naast de limieten (kanalen, berichten per minuut, opslag), die ter plaatse worden ingesteld. Alleen zichtbaar voor de platformrol. Zie beveiliging voor wat elk limiet doet.

3.6.3 Certificaten

De TLS-certificaten in gebruik en wanneer ze verlopen. De verloopdata zijn het punt: een certificaat dat op een zondag is verlopen, is een klasse van storing die geheel te voorkomen is en routinematig niet wordt voorkomen.

3.6.4 Activiteit

Wie wat heeft gewijzigd en wanneer. Elke configuratiewijziging wordt opgenomen, wat maakt dat 'het begon te falen op dinsdag' antwoordbaar is.

3.6.5 Gegevensbescherming

Een persoon zijn verzoeken onder de GDPR en de UK GDPR, juridische bewaring, het wisregister, retentie en het register van verwerkingsactiviteiten; alleen voor beheerders. Zie gegevensbescherming.

3.6.6 Vloot

Elk Perfuse-exemplaar op één pagina.

Mirth verkoopt dit als een apart product; hier is het een configuratiebestand en een alleen-lezen-token. De reden waarom het de moeite waard is om het te hebben is smal en belangrijk: een dode server ziet er niet uit als een stille. Het dashboard van één instantie kan je niet vertellen dat een tweede site is gestopt met rapporteren, en een overzicht van de vloot kan dit ook niet.

3.6.7 Migreren

Laat een Mirth- of OIE-kanaalexport vallen en zie hoeveel van uw kanalen hier ongewijzigd zouden werken. Dezelfde analyse als perfuse explain en perfuse translate, zonder een terminal nodig te hebben. Zie migratie.

3.6.8 Instellingen

Elke instelling die de server heeft, met een controle voor elk — inclusief die welke traditioneel alleen in een bestand zouden leven. Elk zegt of het onmiddellijk van kracht wordt of een herstart nodig heeft, en of het expliciet is ingesteld of op zijn standaardwaarde staat.

De instellingen omvatten elke perfuse serve-optie die een functie activeert: de FHIR-eindpunt en zijn versie, de payer-API's, PAS en de CRD-regels, de X12 278-brug, eCR, de SMART-autorisatieserver, TLS en ondertekening, metrische gegevens, vloot en VPN. Ze zijn gegroepeerd als FHIR, Payers, Openbare gezondheid, SMART, Beveiliging enz. Elk wordt ook weergegeven met de vlag waar het mee overeenkomt.

Opnieuw starten vanuit de console. Een instelling die is gemarkeerd als *Opnieuw starten nodig* wordt direct opgeslagen, maar alleen gelezen wanneer de server opnieuw wordt gestart. Zolang er instellingen in afwachting zijn, wordt een banner bovenaan de instellingen weergegeven met een Server opnieuw starten-knop (de aanmeldingseditor en de instellingsbestanden bieden dezelfde knop na opslaan). Er wordt eerst om bevestiging gevraagd, omdat elk kanaal een paar seconden stopt: elk kanaal voltooit het bericht dat het op dat moment verwerkt en verzenders verzenden opnieuw alles wat intussen binnenkomt. De console wacht vervolgens totdat de server opnieuw antwoordt en leest de instellingen opnieuw. Alleen een beheerder kan de server opnieuw starten en elke opnieuw starten wordt opgenomen in het activiteitenlogboek als server.restart.

Op Linux en macOS vervangt het proces zichzelf door een nieuwe kopie van hetzelfde programma en de argumenten, waarbij het proces-ID behouden blijft, zodat systemd, launchd of een containerruntime niets merkt. Op Windows start de server opnieuw binnen hetzelfde proces, dat een Windows-service onder het servicemanager behoudt. Als de server na twee minuten nog niet heeft geantwoord, meldt de console dit; de reden staat in het logboek van de server.

Vlaggen en het instellingsbestand. De eerste keer dat de server wordt gestart, worden de vlaggen die zijn doorgegeven, geschreven naar het instellingsbestand. Vanaf dat moment wint het bestand het van de vlaggen, dus het wijzigen van een instelling gebeurt in de console (of het bestand), niet door de opdrachtregel van de service te bewerken. Een vlag die het bestand nog niet vermeldt, wordt opgenomen wanneer de server met die vlag wordt gestart. Het verwijderen van een vlag uit de opdrachtregel later schakelt de functie niet uit: schakel deze uit in Instellingen.

SNMP heeft een paneel onder de instellingen: of de agent antwoordt en op welk adres, de netwerken waarop het antwoordt, hoeveel waarschuwingsvalstrikken zijn verzonden of mislukt, en MIB downloaden voor de basis-OID in gebruik. De waarden worden ingesteld onder Bewaking, SNMP.

Branding is hier ook: een site kan de productnaam, een slagzin, een accentkleur instellen en een logo uploaden. Het logo verschijnt vervolgens in de koptekst, op de aanmeldingspagina, op het dashboard en op de rapportageschermen. Als er geen logo wordt geüpload, wordt er niets vervangen — een niet-gebrande installatie blijft niet-gebrand in plaats van decoratie te krijgen.

3.7 Wat de kleuren betekenen

Vier registers, en elk zegt iets anders. Het onderscheid is de moeite waard om te vermelden, omdat het het verschil is tussen een scherm dat u in één oogopslag kunt lezen en een scherm waarop alles om aandacht vraagt.

Platte tekst is een feit over hoe Perfuse werkt. Het grootste deel van de interface. Niets is gekleurd om aan te geven dat het belangrijk is.

Groen betekent dat iets zojuist is geslaagd, vanwege iets dat u hebt gedaan. Het verschijnt na een actie en houdt niet aan.

Amber is een waarschuwing: het is de moeite waard om te weten voordat u actie onderneemt, en het is geen fout. Een functie die niet is ingeschakeld, een instelling waarvan de wijzigingen worden gecontroleerd, een omzetting die benadert in plaats van reproduceert, een transport dat Perfuse afhandelt maar niet volledig kan verifiëren. Amber is de kleur van "lees dit voordat u doorgaat".

Rood betekent dat er op dit moment iets mis is. Een waarde die is afgewezen, een aanvraag die is mislukt, een certificaat dat is verlopen, een kritieke waarschuwing die wordt geactiveerd. Niets anders gebruikt het.

Deze laatste regel is de reden waarom een scherm niet rood opent. Rood is de enige kleur die een instructie overdraagt — stop, en het kan iets zijn dat u hebt gedaan — en een scherm dat het voor decoratie gebruikt, heeft niets meer te zeggen wanneer de invoer echt verkeerd is. Dit was niet altijd zo: het gebruikersscherm opende vroeger met "de server heeft een antwoord gestuurd dat niet kon worden gelezen" op elke installatie die geen passkeys had geconfigureerd, en het instellingenscherm markeerde gecontroleerde waarden in dezelfde kleur als een afgewezen waarde. Een test in web/src/RedMeansWrong.test.ts faalt nu als een zin die iets beschrijft dat ontbreekt of benadert, een rode stijl krijgt.

Binnen een codebox is de woordenschat anders. Daar is rood een tokentype — een HL7-segmentnaam, een XML-element — en draagt het geen oordeel.

4 Kanalen

Een kanaal is één stroom van berichten: ergens komen ze vandaan, optionele wijzigingen en één of meer plaatsen waar ze naartoe gaan. Het is de eenheid van configuratie, de eenheid van bewaking en de eenheid van implementatie. Alles anders in Perfuse bestaat om kanalen te bedienen.

4.1 Anatomie

Een kanaalbestand heeft deze onderdelen, in de volgorde waarin ze van kracht worden:

OnderdeelSleutelVereistWat het doet
IdentiteitnamejaGeeft het kanaal een naam. Moet uniek zijn.
GegevenstypedataTypeneeHoe berichten moeten worden geparsed. Standaard is HL7 v2.
BronsourcejaWaar berichten vandaan komen. Precies één.
FilterfilterneeBepaalt welke berichten worden geaccepteerd.
TransformatiestransformationsneeGestructureerde wijzigingen in het bericht.
BestemmingendestinationsjaWaar berichten naartoe gaan. Één of meer.

Plus enkele die voor het hele kanaal gelden: scripts, shadow, contract, tables, attachments, group en enabled. Elk wordt beschreven in de kanaalreferentie.

4.2 Één bron, veel bestemmingen

Deze asymmetrie is opzettelijk en het is de moeite waard om het vroeg te begrijpen, omdat het de meest voorkomende bron van verwarring is wanneer je van een andere engine komt.

Een kanaal heeft precies één bron. Als berichten van twee plaatsen komen, zijn dat twee kanalen. Proberen om het uit te drukken als één kanaal produceert een configuratie waarin een fout in een van de transports er van buitenaf hetzelfde uitziet, en waarin het verkeer van de twee feeds samen wordt gemengd in de statistieken — dus een daling in één wordt verborgen door de andere.

Een kanaal heeft een willekeurig aantal bestemmingen, en ze zijn onafhankelijk. Als één faalt, stoppen de anderen niet, en elk heeft zijn eigen wachtrij, zijn eigen retrybeleid en zijn eigen leveringsrecord. Een bericht dat drie van de vier bestemmingen heeft bereikt, wordt opgenomen als precies dat, en niet als een succes of een fout.

4.3 Bestemmingen zijn geen keten

Elke bestemming ontvangt het bericht zoals het eruitzag na de transformaties van het kanaal. Een bestemming ontvangt niet de uitvoer van de bestemming ervoor.

Dit is belangrijk wanneer een bestemming zijn eigen transformaties heeft, wat het kan. Die worden alleen toegepast op de kopie van die bestemming. Een veelvoorkomende fout is om een wijziging op de eerste bestemming te zetten en te verwachten dat de tweede het ziet.

Als je echt een keten nodig hebt — de uitvoer van één stroom die in een andere stroom wordt gevoerd — gebruik dan een kanaalbestemming, die naar een ander kanaal wordt gestuurd op basis van de naam. Dat is expliciet, wordt weergegeven in de berichtgeschiedenis als twee kanalen, en kan worden bewaakt als twee dingen, wat een verborgen keten niet kan.

4.4 Naamgeving

De naam is de identiteit van het kanaal overal: in het bestand, in de berichtenopslag, in waarschuwingen, in het auditlog en in de URL. Het wijzigen ervan is geen hernoeming; het is een nieuw kanaal, en de geschiedenis van het oude kanaal blijft onder de oude naam.

group is afzonderlijk en bestaat om de interface te organiseren. Een groep heeft geen invloed op het gedrag, en het groeperen van kanalen maakt ze niet tot één geheel.

Bij een implementatie op meerdere locaties moet de locatie in de naam worden opgenomen in plaats van alleen in de groep. Mirth-implementaties op meerdere sites gaan betrouwbaar inconsistent worden in de naamgeving, en het punt waarop dat pijnlijk wordt is een incident om twee uur 's nachts waarbij de kanaallijst vier dingen heeft met de naam adt-inbound.

4.5 Inschakelen en uitschakelen

enabled: false stopt een kanaal zonder het te verwijderen. De configuratie, geschiedenis en statistieken blijven behouden.

Een uitgeschakeld kanaal is niet hetzelfde als een gepauzeerd kanaal. De bron luistert niet, dus een verzender die probeert te verbinden krijgt een geweigerde verbinding in plaats van een hangende verbinding. Voor MLLP is dat het juiste gedrag — de verzender zal in de wachtrij worden geplaatst en opnieuw proberen — maar het betekent wel dat het foutenlogboek van de verzender volloopt, dus een uitgeschakeld kanaal is geen vervanging voor het regelen van een uitval met degene die verstuurt.

4.6 Waar kanalen wonen

Één YAML-bestand per kanaal, in de directory die wordt gegeven door -channels. De bestandsnaam is niet de kanaalnaam; de name-sleutel is dat. Het is sterk aan te raden om ze hetzelfde te houden, en niets dwingt je ertoe.

Bestanden worden opnieuw gelezen zonder een herstart. Een bestand dat niet kan worden geparsed, wordt gemeld en de eerder geladen versie blijft draaien, dus een syntaxisfout kan een werkende feed niet uit de lucht halen.

Een kanaal dat in de webinterface is bewerkt, wordt terug naar zijn bestand geschreven. Als die bestanden in versiebeheer zitten — wat aan te raden is — verwacht dan commits van configuratiewijzigingen die via de interface zijn gemaakt, en bewerk geen bestand handmatig terwijl iemand het in de builder heeft geopend.

4.7 Versleutelen van de listener van een kanaal

Een kanaal dat luistert op een poort is zijn eigen server en de TLS is gescheiden van de TLS op het webinterface van Perfuse. Het instellen van de ene heeft geen invloed op de andere. Voor een HTTP-bron staan de instellingen onder TLS en limieten op de bron.

Het inschakelen van TLS vraagt om een certificaat en een privésleutel. Het vereisen van een clientcertificaat zet het om in wederzijdse TLS: de afzender moet een certificaat presenteren dat is ondertekend door een door u genoemde autoriteit, wat authenticatie is, dus een luisteraar met dit ingeschakeld heeft geen gedeelde token nodig — hoewel het hebben van beide niet verkeerd is.

De autoriteit wordt alleen gevraagd als een clientcertificaat is vereist en wordt weggelaten uit het bestand totdat dit het geval is. Een kanaal dat een autoriteit noemt die nooit wordt geraadpleegd, lijkt alsof afzenders worden geverifieerd terwijl dit niet het geval is.

Een MLLP-luisteraar heeft dezelfde instellingen onder Versleutel deze luisteraar, met één verschil dat vermeldenswaard is: bij MLLP is een clientcertificaat de enige beschikbare authenticatie. Er is geen token en geen header, dus een luisteraar zonder certificaat accepteert berichten van elke host die de poort kan bereiken.

Twee limieten staan ernaast. Stop met lezen na een bepaalde tijd, omdat een afzender die een verbinding opent en stopt met schrijven de verbinding anders openhoudt. En grootste bericht dat wordt geaccepteerd, in bytes, omdat nul geen limiet betekent en de limiet dan het geheugen is — een afzender die een bericht van een gigabyte verzendt, wordt geweigerd in plaats van geabsorbeerd.

4.8 Validatie

Een kanaal wordt gecontroleerd wanneer het wordt geladen en de controles zijn weigeringen in plaats van waarschuwingen waar de alternatieve optie een kanaal zou zijn dat draait en de verkeerde dingen doet.

Voorbeelden van dingen die direct worden geweigerd: een bestemming zonder type, een transformatie die een pad adresseert dat niet kan bestaan in het opgegeven gegevenstype, een bevestigingsmodus die de brontransport niet kan leveren en een recept met herhalingen voor klasse II.

Het onderscheid dat Perfuse probeert te maken, is dat alles wat een plausibel uitziend verkeerd resultaat zou kunnen produceren, wordt geweigerd, en alles wat alleen maar ongebruikelijk is, wordt toegestaan en gerapporteerd. Een kanaal dat niet verkeerd kan zijn, is waardevoller dan een kanaal dat start.

5 Berichtstroom

Dit hoofdstuk volgt één bericht vanaf het moment dat het aankomt tot het moment dat het wordt afgeleverd of opgegeven. Het kennen van deze volgorde is de snelste manier om te bepalen waar een wijziging thuishoort en waarom iets niet gebeurt.

5.1 De volgorde van gebeurtenissen

Arrival de-frame Parse Record as received Filter Transform Destination A Destination B Destination C unparseable filtered Filtered is a normal outcome, not an error. Unparseable is recorded and stops. The acknowledgement is sent after delivery by default, so a sender is not told "received" before it is true.
  1. Aankomst. De bron accepteert de bytes. Voor een stream-transport omvat dit de-de-framing — het vinden van waar een bericht eindigt en het volgende begint.
  2. Parse. De bytes worden een boom volgens het kanaal's dataType. Een bericht dat niet kan worden geparsed, stopt hier en wordt opgenomen als een parse-fout.
  3. Record. Het bericht wordt geschreven naar de berichtenopslag zoals ontvangen, voordat iets het wijzigt. Dit is wat replay en reprocessing mogelijk maakt.
  4. Filter. Als het kanaal een filter heeft, beslist het of het bericht moet worden geaccepteerd. Een afgewezen bericht wordt opgenomen als gefilterd, wat een normaal resultaat is en geen fout.
  5. Transform. Het kanaal's transformations worden uitgevoerd in volgorde, elk tegen het resultaat van de vorige.
  6. Fan out. Elk doel krijgt een kopie van het getransformeerde bericht, past zijn eigen transformaties toe als het die heeft, en levert.
  7. Record het resultaat. Per doel: geleverd, in de wachtrij geplaatst, mislukt of gefilterd.
  8. Bevestig. Als de bron een bevestiging verwacht, wordt deze gegenereerd en verstuurd. Standaard gebeurt dit hier, na levering — zie hieronder.

5.2 Wanneer de bevestiging wordt verzonden

Dit is de meest gevolgrijke instelling in een kanaal, omdat het beslist wat de afzender wordt beloofd. Het is ack.when, en het heeft twee waarden.

on_delivery is standaard. De bevestiging wordt alleen verzonden nadat elke ingeschakelde bestemming het bericht heeft geaccepteerd. Een positieve bevestiging betekent dus dat de gegevens daadwerkelijk ergens zijn aangekomen, wat de sterkste claim is die een engine in het midden eerlijk kan maken.

on_receipt bevestigt zodra het bericht is geparsed en in de wachtrij is geplaatst, voordat een bestemming is geschreven.

Perfuse gebruikt standaard on_delivery omdat het beloven van aflevering en dan het bericht verliezen erger is dan langzaam zijn. Onder on_receipt kan een bericht dat is bevestigd nog steeds verloren gaan als het proces met werk in de wachtrij crasht — de afzender denkt dat het is afgeleverd, niets stroomopwaarts zal het opnieuw verzenden, en het enige bewijs dat het heeft bestaan, is in Perfuse's eigen opslag.

5.3 Wanneer te kiezen voor on_receipt

Het geval ervoor is echt, en het zijn time-outs. Een MLLP-afzender die geen bevestiging krijgt binnen enkele seconden, zal deze meestal opnieuw verzenden, dus een trage bestemming onder on_delivery produceert duplicaten in plaats van vertraging. Als één bestemming een langzame archief of een systeem is dat regelmatig niet beschikbaar is, koppelt on_delivery de time-out van de afzender aan de slechtste casus van die bestemming.

De handel is expliciet: on_receipt verplaatst het risico van duplicaten naar verlies. Het kiezen ervan betekent dat u accepteert dat een bevestigde bericht verloren kan gaan bij een crash, en het is de moeite waard om te combineren met queue-diepte-waarschuwingen zodat een wachtrij die is stopgezet met afvoeren wordt opgemerkt. Zie waarschuwingen.

Onder beide instellingen is een positieve bevestiging geen belofte dat de ontvangende toepassing het bericht *heeft verwerkt* — alleen dat het de bytes heeft geaccepteerd. Als u wilt weten of een resultaat is opgeslagen, moet dit komen van het ontvangende systeem, en geen integratie-engine kan dit bieden.

5.4 Waar het bericht wordt opgenomen

Vóór de filter, en dus vóór elke transformatie. Drie gevolgen:

De getransformeerde vorm wordt ook opgenomen, per bestemming, naast het resultaat. Dus de opslag bevat wat is aangekomen, wat is verstuurd en wat er is gebeurd — wat een onderzoek nodig heeft.

5.5 Fout bij elke fase

FaseWat een fout eruit zietWat er gebeurt
AankomstFraming-fout, verbinding verbroken tijdens het berichtGeregistreerd, verbinding gesloten, afzender probeert opnieuw
ParsenNiet geldig voor het opgegeven typeGeregistreerd als parsfout, negatieve bevestiging als de *source* een verwacht
FilterDe filter zelf geeft een foutBehandeld als een weigering, geregistreerd met de fout
TransformatieEen stap misluktAfhankelijk van de on_error-instelling van de stap; zie transformatie
LeveringBestemming onbereikbaar of wijst afIn de wachtrij geplaatst en opnieuw geprobeerd volgens het beleid van de bestemming; zie levering

De belangrijke asymmetrie: een parsfout is permanent en een leveringsfout is meestal niet. Opnieuw proberen van een onparsbaar bericht zal nooit helpen, dus het wordt niet opnieuw geprobeerd. Opnieuw proberen van een onbereikbare bestemming zal meestal wel helpen, dus het wordt opnieuw geprobeerd.

5.6 Volgorde

Binnen één bestemming worden berichten geleverd in de volgorde waarin ze zijn aangekomen, en een bericht dat faalt en in de wachtrij terechtkomt, behoudt zijn positie — latere berichten wachten erachter in plaats van voorbij te gaan.

Dit is de juiste standaard voor klinische gegevens, waarbij een opname gevolgd door een ontslag in de verkeerde volgorde erger is dan dat beide laat zijn. Het betekent ook dat één beschadigd bericht een wachtrij kan blokkeren, wat de reden is waarom de diepte van de wachtrij het waard is om een waarschuwing voor te geven.

Over meerdere bestemmingen is er geen volgordegarantie, omdat ze onafhankelijk zijn. Twee bestemmingen zullen niet noodzakelijkerwijs hetzelfde bericht op hetzelfde moment ontvangen, en een snelle kan enkele berichten vooruit zijn op een langzame.

Volgorde over kanalen is helemaal niet gegarandeerd. Als twee feeds in een bepaalde volgorde ten opzichte van elkaar moeten worden toegepast, moet die volgorde worden afgedwongen door het ontvangende systeem, omdat niets in het midden kan weten welk van de twee onafhankelijk aankomende berichten het eerst is gebeurd.

5.7 Gelijktijdigheid

Een bron kan meerdere verbindingen tegelijk verwerken, begrensd door max_connections. Berichten van verschillende verbindingen worden gelijktijdig verwerkt.

Dit betekent dat de aankomstvolgorde van twee berichten die tegelijkertijd via twee verbindingen worden verzonden, niet is gedefinieerd en niet kan worden — ze zijn echt tegelijk aangekomen. Een verzender die volgorde nodig heeft, moet één verbinding gebruiken, wat de meeste van hen doen.

6 Transformatie

Transformaties veranderen een bericht. Ze zijn een lijst, ze worden in volgorde uitgevoerd en elke stap ziet het resultaat van de vorige stap.

De transformaties van Perfuse zijn declaratief: elke stap noemt een bewerking en het veld waarop deze wordt toegepast. Er is geen scripttaal in de gewone pad. Dit is een bewuste beperking en de redenering is in why not a script hieronder.

6.1 De stappen

StapWat het doet
setSchrijft een letterlijke waarde naar een pad, maakt het aan als het ontbreekt.
copyKopieert een pad naar een ander, met een optionele standaardwaarde als de bron ontbreekt.
clearLeegt een veld, laat het aanwezig.
removeVerwijdert een veld helemaal.
mapZoekt de huidige waarde op in een tabel en vervangt deze.
replaceReguliere expressie-substitutie binnen een veld.
padVult een waarde aan tot een vaste breedte.
dateConverteert een datum of tijdstempel tussen formaten.
trimStript omringende witruimte.
caseConverteert naar hoofdletter of kleine letter.

Elke stap accepteert ook description, die in de trace en in de interface verschijnt, en when, die de stap conditioneel maakt.

Een stap wordt geschreven als de bewerkingnaam met zijn eigen blok:

transformations:
  - description: Our record number, not theirs
    set:
      path: PID-3.4
      value: RIVERSIDE
  - copy:
      from: PID-19
      to: PID-3.1
      default: UNKNOWN
  - map:
      path: PID-8
      table:
        M: Male
        F: Female
set en value zijn geen broers. set neemt een blok met path en value. Het schrijven van set: PID-3.4 met value: ernaast is de meest voorkomende fout in een handgeschreven kanaal en produceert een laadfout in plaats van een stille misconfiguratie.

6.2 Clear, remove en het verschil

clear laat het veld aanwezig en leeg. remove haalt het helemaal weg.

Voor HL7 is dit onderscheid reëel en het bereikt de ontvanger. Een leeg veld zegt 'ik heb dit veld en het heeft geen waarde'. Een ontbrekend veld zegt niets. Sommige ontvangende systemen behandelen de eerste als een instructie om hun opgeslagen waarde te wissen en de tweede als een instructie om deze alleen te laten — wat het verschil is tussen het wissen van een patiënt's geregistreerde allergie en het niet noemen.

Als u niet weet wat de ontvanger wil, vraag het dan. Raden heeft een vijftig procent kans om stilletjes gegevens op de andere kant te vernietigen.

6.3 Voorwaarden

when neemt een expressie en de stap wordt alleen uitgevoerd als deze waar is:

  - when: MSH-9.2 == "A08"
    set:
      path: EVN-1
      value: A08

Een stap met een voorwaarde die onwaar is, wordt geregistreerd als overgeslagen, en dit wordt afzonderlijk gerapporteerd van een stap die is uitgevoerd en niets heeft gewijzigd. Dat onderscheid is het doel van de stap-voor-stap-debugger en wordt behandeld in debugging: een onwaar voorwaarde en een ontbrekend veld lijken van buitenaf identiek en betekenen tegenovergestelde dingen.

6.4 Paden

Een pad adresseert een veld: PID-5 is het vijfde veld van PID, PID-5.1 is de eerste component ervan, PID-3(2) is de tweede herhaling van PID-3 en OBX(3)-5 is het vijfde veld van het derde OBX-segment.

Twee gedragingen die het kennen waard zijn:

6.5 Fouten

De meeste stappen hebben niets om te falen. Een waarde instellen, een veld wissen of kopiëren van een ontbrekend pad met een standaardwaarde zijn allemaal gedefinieerd voor elke invoer.

date is de uitzondering, omdat een waarde die geen datum is die het herkent, geen correcte conversie heeft. Het neemt on_error:

De standaard is fail omdat een tijdstempel dat stilzwijgend niet is geconverteerd, erger is dan een bericht dat niet is aangekomen. Een datum in het verkeerde formaat ziet er meestal nog steeds uit als een datum, dus het passeert de validatie van de ontvanger en belandt in het record als de verkeerde dag.

keep is legitiem wanneer de ontvanger zowel het ene als het andere formaat tolereert, en wanneer het wordt gebruikt, markeert de trace de wijziging als opzettelijk, zodat het niet leest als een stap die stilzwijgend is mislukt.

6.6 Volgorde is belangrijk, en de trace toont dit

Elke stap ziet de uitvoer van de vorige stap. Twee gevolgen die mensen betrappen:

Beide zijn zichtbaar in de stap-voor-stap-weergave, die het hele bericht toont na elke stap, in plaats van alleen de wijziging. Zie debugging.

6.7 Suggesties voor toewijzingen en wat te doen met een suggestie

De AI Mapper stelt toewijzingen voor tussen een set bronvelden en een set doelen. Zijn definiërende gedrag is dat het afziet: onder zijn vertrouwensdrempel onthoudt het zich van gissen, omdat een zelfverzekerde verkeerde toewijzing in een klinisch systeem erger is dan helemaal geen toewijzing.

6.7.1 Geef het iets om vertrouwen in te hebben

Een naam op zich is zwak bewijs, zelfs wanneer deze exact overeenkomt. PatientMRN tegen PatientMRN scoort 68, wat afziet bij de standaarddrempel van 70.

The engine knows what an HL7 path means — it will tell you PID-7 is Date/Time of Birth and score your field name against that rather than against the string PID-7, which shares no characters with anything. A locally defined Z segment means whatever your site decided, so nothing is claimed about it.

Dat krijgt een toewijzing grotendeels. Om het af te maken, lever beide helften:

Met die, kan de motor zien dat de waarden overeenkomen met het type doel, en een suggestie rust op meer dan alleen een naam.

6.7.2 Goedkeuring gebeurt één toewijzing per keer

Elke suggestie heeft zijn eigen goedkeuringsvak. Er is geen "alles accepteren boven 80%", met opzet: de engine heeft het vertrouwen al gebruikt om te beslissen of de toewijzing moet worden aangeboden en wat overblijft is een oordeel over dit veld in deze feed. Een nummer is dat oordeel niet.

Een onthouding kan helemaal niet worden goedgekeurd. Het heeft geen vak, niet eens een uitgeschakeld vak, en het scherm zegt dat de engine het antwoord niet weet. Als u het antwoord weet, wijst u het handmatig toe - dat is een andere handeling dan het eens zijn met een suggestie.

Een suggestie onder uw drempel wordt ook zonder vak getoond, gemarkeerd als onder de drempel. Het is de moeite waard om te lezen - een near miss is vaak de toewijzing die u wilde, en het verbergen ervan zou u doen twijfelen of de engine het heeft overwogen - maar het is niet goedkeurbaar, omdat uw drempel de lijn is die u heeft getrokken.

6.7.3 Twee dingen die u kunt doen met wat u heeft goedgekeurd

Toevoegen aan een kanaal maakt elke toewijzing een kopieerstap. Dit werkt alleen waar de bron een pad in het bericht is, zoals ZPI-1, omdat een stap kopieert van de ene plaats in een bericht naar de andere. De stappen gaan naar het kanaalbestand en worden van kracht wanneer het kanaal opnieuw wordt geladen - niets verandert in het verkeer totdat dan. De beschrijving van elke stap registreert het vertrouwen waarmee het werd voorgesteld en dat een persoon het heeft goedgekeurd, wat het verantwoordelijk maakt zes maanden later.

Downloaden als recept is het juiste antwoord voor het meer voorkomende geval: een toewijzing van een kolomnaam, een JSON-sleutel of een veldnaam van een leverancier. Dat zijn echte toewijzingen, en een kanaal kan zo'n veld niet rechtstreeks lezen, dus een stap kan ze niet uitdrukken. Het recept registreert ze als goedgekeurd en kan worden gedeeld.

6.8 Waarom geen script

Mirth plaatst een JavaScript-transformatie in het centrum van elk kanaal en het is het meest flexibele ontwerp dat beschikbaar is. Perfuse biedt scripting - zie de scripts-sleutel in de kanaalverwijzing - maar maakt het niet de gewone weg, om drie redenen die voortkomen uit wat er in de praktijk misgaat.

Een declaratieve stap kan worden geïnspecteerd. Perfuse kan u vertellen dat een stap PID-5 leest en PID-8 schrijft, voordat het wordt uitgevoerd, en kan dus een veldniveau-trace tonen, waarschuwen dat een stap een pad adresseert dat het verklaarde gegevenstype niet kan bevatten en een per-stap-replay genereren. Niets van dat is mogelijk voor willekeurige code.

Een declaratieve stap kan worden nagedacht door de interface. De builder kan de velden aanbieden die bestaan in het verkeer van dit kanaal en een wijziging in een stap kan worden gecontroleerd tegen echte historische berichten voordat het wordt opgeslagen.

En een declaratieve stap kan niets doen dat niet gerelateerd is aan het bericht. Een script kan een netwerkoproeppen, het bestandssysteem lezen of afhankelijk zijn van de tijd van de dag. Wanneer een kanaal dat twee jaar heeft gewerkt plotseling verkeerde output begint te produceren, is de oorzaak die buiten het bericht ligt het moeilijkste geval om te diagnosticeren, en het verwijderen van de mogelijkheid is meer waard dan de flexibiliteit die het kost.

Waar een echte transformatie niet declaratief kan worden uitgedrukt, gebruikt u een script en accepteert u dat de trace het zal tonen als één ondoorzichtige stap.

6.9 Wat een script mag doen

Een script wordt geweigerd alles buiten het bericht, tenzij het is toegestaan, en de toestemmingen zijn in het Scripts-gedeelte van de builder. Dit is met opzet anders dan Mirth, dat elk script alle toestemmingen geeft - dus daar kan een transformatie stilzwijgend beginnen met het lezen van het bestandssysteem na een kopieer-plakactie.

Er zijn drie.

Bestanden lezen en schrijven vereist dat u de directories noemt die het mag gebruiken, en een kanaal dat toegang tot bestanden verleent zonder directories wordt geweigerd bij het laden. Die vereiste is het enige verschil tussen bestandstoegang en onbeperkte bestandstoegang: het verlenen ervan zonder directories bereikte een keer het hele bestandssysteem, inclusief de database van Perfuse, die wachtwoordhashes, het wachtwoord van de LDAP-serviceaccount en het OIDC-clientgeheim bevat. Het maken van een kanaal vereist alleen de editorrol, dus de escalatie was voltooid op het moment dat een beheerder het kanaal startte.

Een database opvragen gebruikt de verbindingen die zijn geconfigureerd op het kanaal. Een script met deze toestemming kan alles lezen waarvoor de referenties toegang hebben.

Berichten naar andere kanalen routeren laat een script een bericht naar een ander kanaal sturen, wat de manier is waarop een lus tussen twee kanalen mogelijk wordt.

Het verlenen van een mogelijkheid aan een kanaal zonder scripts doet niets, en het gegenereerde bestand slaat de hele blok over in dat geval.

6.10 Het omgaan met een datum die niet overeenkomt met zijn formaat

Een datumstap converteert van het ene formaat naar het andere, en de interessante vraag is wat er gebeurt wanneer een waarde niet overeenkomt met het formaat dat het claimt.

De standaard is om het bericht te stoppen, en het is de juiste standaard: een tijdstempel dat stilzwijgend niet is geconverteerd, wordt downstream geaccepteerd en vervolgens verkeerd gelezen, wat erger is dan een bericht dat luidruchtig is mislukt en op een plaats zit waar iemand het kan zien.

De waarde ongewijzigd laten laat het in zijn oorspronkelijke formaat door. Downstream ziet dan twee formaten in één veld, wat de fout is die de stap bestond om te voorkomen - maar het is de juiste keuze waar het veld optioneel is en een partner het onregelmatig verstuurt.

Het veld leegmaken is eerlijk en beter dan een verkeerd formaat, maar een ontvanger die het veld vereist, wijt het bericht dan af in plaats daarvan.

6.11 De scripts talen

Er worden drie talen geaccepteerd en de keuze hangt voornamelijk af van of u een migratie uitvoert. De waarde staat in de language-sleutel van een script:

WaardeWat het is
javascriptDe standaardwaarde. Een ongemarkeerd script is JavaScript.
luaDe betere keuze wanneer niemand migreert.
wasmDe bytes van een gecompileerd WebAssembly-module, niet de broncode.

JavaScript is de standaardwaarde en een ongemarkeerd script wordt als JavaScript behandeld. Het is hier om compatibiliteitsredenen en niet om een voorkeur: Mirth-scripts zijn JavaScript en een site die overstapt heeft duizenden regels ervan. Dit omvat ondersteuning voor E4X, een inmiddels verouderde extensie van de taal die Mirth-scripts gebruiken voor XML en die moet worden vertaald voordat iets kan worden geparseerd.

Lua (lua) is de betere keuze voor iedereen die niet migreert. Een kleinere runtime, geen prototype-keten om misbruik van te maken en integer-geïndexeerde tabellen die segment- en veldadressering op een meer natuurlijke manier ondersteunen dan die van JavaScript. De standaardbibliotheek is klein genoeg om op te sommen, wat het makkelijker maakt om een sandbox te maken.

WebAssembly (wasm) is geen taal, maar een gecompileerd module, en het veld verwacht de bytes van een .wasm-bestand in plaats van de broncode. Gebruik het wanneer de transformatie al bestaat in een gecompileerde taal of wanneer deze zwaar genoeg is om een impact te hebben op de runtime.

Het contract is expres het eenvoudigste dat beschikbaar is: een module leest het bericht van de standaardinput en schrijft het resultaat naar de standaardoutput. Bytes in, bytes uit — wat elk hulpmiddel al doet en wat iemand die een module op zijn eigen commandoregel test, al heeft. Het alternatief was een geëxporteerd functie over lineaire geheugen, wat sneller is en vereist dat elke moduleauteur het eens is over toewijzing, tekenreekscodering en wie wat vrijgeeft; voor iets dat één keer per bericht wordt uitgevoerd, is die ruil niet de moeite waard.

Alles wat een module naar de standaardfout schrijft, wordt logregels, dus het kan zichzelf uitleggen op de manier waarop een script logger aanroept.

Een niet-nul-afsluitcode betekent dat de module *mislukt*, wat niet hetzelfde is als een filter dat besluit een bericht te weigeren. Een filtermodule zegt true of false op de standaardoutput. Het combineren van de twee zou een crashende module ononderscheidbaar maken van een module die verkeer opzettelijk laat vallen.

6.11.1 Wat de uitvoer betekent

De regels zijn hetzelfde voor alle drie talen in plaats van nieuwe regels per runtime, dus het waarneembare gedrag van een script — wat het kan zien, wat het mag doen, hoe lang het mag duren, wat een filteroordeel betekent — wordt één keer gedefinieerd.

Voor een transformatie, voorverwerker of schrijver betekent leeg uitvoer dat het bericht ongewijzigd blijft. Aan het einde van een script komen, laat het bericht met rust; geen uitvoer behandelen als "het bericht is nu leeg" zou verkeer op een technisch detail weggooien.

WebAssembly-modules worden gecompileerd wanneer het kanaal wordt geladen, niet bij het eerste bericht. Compileren is niet gratis — een module gebouwd vanuit een taal die zijn eigen runtime meebrengt, kan honderden milliseconden duren — en die betaling bij het laden van het kanaal betekent dat het eerste bericht via een kanaal niet mysterieus langzamer is dan de rest.

6.12 Gedeelde toewijzings-tabellen

De andere helft van hetzelfde probleem: de geslachtscodes en patiëntklassen van een site worden vertaald op exact dezelfde manier in elk kanaal dat ze aanraakt, en een tabel in een kanaal is een tabel die alleen dat kanaal kan gebruiken.

# codes.codeset.yaml
tables:
  - name: sex-to-lab
    describes: the hospital's sex codes into the numeric codes the lab expects
    decided_by: Dave, during the 2019 migration
    decided_on: 2019-04-11
    source: the lab's interface specification, version 3
    entries:
      - from: M
        to: "1"
      - from: U
        to: "9"
        why: the lab has no 'unknown', and 9 is its 'not stated'
# in the channel
tables:
  - codes.codeset.yaml
transformations:
  - map:
      path: PID-8
      use: sex-to-lab

De herkomst is het punt. Het grootste deel van wat een interface moeilijk te onderhouden maakt, is dat niemand weet *waarom* een toewijzing op die manier is, en de persoon die het wist is vertrokken. Een toewijzing met een reden kan worden betwist; een zonder wordt iets waar niemand durft te veranderen en niemand durft te verwijderen.

Tabellen worden gemaakt en gewijzigd in Bouwen → Tabellen en in het bestand. Het opslaan van een tabel die van kracht is, start de actieve kanalen opnieuw die het bestand laden, zodat het volgende bericht het gebruikt; een ontwerp start niets opnieuw.

6.12.1 Versies en ingangsdatum

Een tabel kan meerdere edities onder één naam bewaren, elk met zijn eigen version. De editie die een bericht gebruikt, wordt gekozen wanneer het bericht aankomt: van de goedgekeurde edities waarvan de datums die dag (UTC) omvatten, is de een die het laatst is gestart. Dus een codeverandering die is overeengekomen voor de eerste van volgende maand, wordt nu ingevoerd en eemt automatisch over.

tables:
  - name: sex-to-lab
    version: "3"
    effective_from: 2026-11-01   # optional; empty means from the start
    effective_until: 2027-10-31  # optional; the last day it applies
    source_system: urn:local:hospital-sex
    target_system: http://terminology.hl7.org/CodeSystem/v2-0001
    entries: [...]

- Twee edities van één naam met dezelfde versie, of twee goedgekeurde edities die op dezelfde dag beginnen, worden geweigerd wanneer het bestand wordt geladen. - Het opslaan van een nieuwe versie zonder startdatum terwijl een andere is goedgekeurd, dateert deze van vandaag, zodat deze de huidige versie vervangt. Eentje die zelf pas vandaag was begonnen, wordt gepensioneerd, aangezien twee edities die op dezelfde dag beginnen, geen regel laten. - De eigen default en strict van een kaartstap worden gebruikt wanneer de stap deze instelt; anders die van de tabel. - Op het scherm Tabellen, Toon versies lijst elke editie met de status, wie deze heeft opgeslagen en wie deze heeft goedgekeurd, en Vergelijk met de huidige versie toont wat een editie toevoegt, verwijdert en wijzigt.

6.12.2 Goedkeuring

Met Instellingen → Gegevens → Toewijzings-tabellen "Wijzigingen in een toewijzings-tabel hebben een tweede persoon's goedkeuring nodig" (data.tableApproval) on, elke opslaan is een concept, en de persoon die het heeft opgeslagen kan het niet goedkeuren: iemand anders doet dit, optioneel met de dag waarop het in werking treedt. Een goedgekeurde dit kan niet ter plaatse worden bewerkt; Nieuwe versie van deze kopieert het naar de volgende versie. Goedkeuren, intrekken en verwijderen van een concept worden geschreven naar het audit logboek, en goedkeuren start de actieve kanalen opnieuw die het bestand laden.

6.12.3 Waarden zonder tabelle

Elke waarde die een kaartstap zocht en niet vond, wordt geteld, per tabel, met de kanalen waar het doorheen kwam en wanneer het voor het eerst en laatst werd gezien. Het Schermen lijst ze, meest frequent eerst. Kaart het opent de tabel met die waarde al toegevoegd als een rij; Verwerp verwijdert het totdat het weer wordt gezien. Waarden langer dan 64 tekens worden niet opgenomen (ze zijn geen codes), en de lijst behoudt wat werd gezien binnen de berichtretentieperiode. De lijst wordt bewaard in terminology.db naast de hoofddatabase.

6.12.4 Code systemen

Gepubliceerde code systemen kunnen worden geïmporteerd vanuit hun eigen bestanden van de uitgevers, onder Code systemen op het Schermen (beheerders) of met POST /api/terminology/import?format=… en het bestand als het lichaam:

FormatFileSystem
loincLoinc.csv from the LOINC table releasehttp://loinc.org
icd10cmthe CMS order file (icd10cm_order_*.txt) or codes filehttp://hl7.org/fhir/sid/icd-10-cm
rxnormRXNCONSO.RRF from the RxNorm full releasehttp://www.nlm.nih.gov/research/umls/rxnorm
snomedthe RF2 description snapshot (sct2_Description_Snapshot-en_*.txt)http://snomed.info/sct
snomed-rf2a whole SNOMED CT RF2 release package (the zip a national release centre publishes)http://snomed.info/sct, version http://snomed.info/sct/{module}/version/{date}
clamla ClaML file: WHO ICD-10, ICD-10-GM and OPS (BfArM), CIM-10 FR (ATIH)from the file's title, or the given system
icd11the WHO ICD-11 MMS simple tabulation (tab-separated, with Code and Title columns)http://id.who.int/icd/release/11/mms
csvany delimited file, with system, codeColumn and displayColumn (CPT, HCPCS, local codes, national tables)the given system

Geen wordt geleverd met Perfuse: LOINC, SNOMED CT, RxNorm en CPT hebben elk hun eigen licentie, en het scherm vraagt de importer om te bevestigen dat de organisatie deze houdt (opgenomen met de import). Geïmporteerde codes worden op drie manieren gebruikt:

deze wordt opgeslagen, en codes die niet in het systeem zijn, worden op de editie vermeld;

voor hen (zie de FHIR-serveropties). ICD-10-CM-codes worden geaccepteerd met of zonder punt.

Nationale edities en classificaties. Een SNOMED CT-editie wordt geïmporteerd uit het volledige RF2-pakket: concepten met hun werkelijke status, elke actieve beschrijving en de taalreferentiesets. De editie wordt gevonden uit het pakket (de nationale module met de meeste concepten; edition noemt het in plaats daarvan) en wordt de versie-URI. language kiest wiens voorkeursterm elke conceptweergave is (sv, da, nl, de, fr, en-GB, en-US ...; Engels anders), en elke taal voorkeursterm en volledig gespecificeerde naam worden bewaard als aanduidingen: $lookup retourneert deze, en de displayLanguage selecteert er een (de-CH valt terug naar de). De edities die Perfuse noemt (Internationaal, VK, Duitsland, Nederland, Zweden, Denemarken, België, Ierland, Noorwegen, Zwitserland, Estland, Spanje) worden opgesomd door GET /api/terminology/editions, de module-ID's niet gecontroleerd tegen een gepubliceerde bron gemarkeerd als zodanig; elke andere editie wordt ook geïmporteerd, genoemd naar de module.

ClaML-bestanden worden gelezen in UTF-8, ISO-8859-1, ISO-8859-15 of Windows-1252, zoals hun XML declaratie zegt. Elke categorie-titel is zijn voorkeur-rubriek (geneste termen inbegrepen); een modifier (een vijfde karakter voor de site van een fractuur, zeg) maakt de codes die het toevoegt, met de titel van de modifier na de categorie-titel, tenzij de categorie het uitsluit; blocks=true importeert hoofdstukken en blokken ook. De ICD-11-tabulatiekolommen worden gevonden door naam, omdat hun volgorde is veranderd tussen releases, en de dashes die diepte laten zien, worden verwijderd uit titels. Een door komma's gescheiden bestand neemt delimiter (, ; | of tab), encoding (utf-8, iso-8859-1, iso-8859-15, windows-1252) en noHeader=true, met kolommen die dan genummerd worden van 1. Het console biedt instellingen voor het VK ICD-10 5e Editie en OPCS-4-bestanden (TRUD), Frankrijks CIM-10 FR-tabel van labels (ATIH) en een ICD-10-BE-export; hun uitgevers documenteren niet allemaal deze kolommen, dus controleer ze tegen het bestandshoofd.

Effectieve datums. effective=YYYY-MM-DD importeert een versie nu en gebruikt het vanaf die dag (ICD-10-GM, zeg, elk 1 januari): totdat dan een lookup die geen versie noemt wordt beantwoord door de versie die al van kracht is, en het scherm toont de datum.

ICD-11 van de WHO. Met een client geregistreerd bij icd.who.int (Instellingen → Gegevens → Codesystemen, serve -icd11-client-id en -icd11-client-secret; -icd11-release, standaard 2025-01), ICD-11-codes die niet zijn geïmporteerd, worden opgezocht in de WHO ICD API (codeinfo, vervolgens de titel van de entiteit) en worden een dag lang bewaard. Een postgecoördineerde code (NC72.2&XK9K) wordt helemaal gecontroleerd, dus een combinatie ICD-11 die niet is toegestaan, wordt geweigerd, en de weergavenamen van elk onderdeel ("Fractuur van de hals van het femur (Rechts)").

ICD-11 zonder codes te verzenden. De WHO publiceert dezelfde API als een container (whoicd/icd-api, gratis, Intel en Arm). Voer deze uit op uw eigen netwerk en geef het adres (serve -icd11-url http://icd-api.local, of ICD API-adres in dezelfde instellingen); geen client is nodig en geen code verlaat uw netwerk. Getest tegen die container (versie 2.6.0, release 2025-01 in het Engels en Frans).

7 Filteren

Een filter beslist welke berichten een kanaal accepteert. Het is één expressie op het kanaal, geëvalueerd nadat het bericht is geparsed en opgenomen, voordat elke transformatie.

filter: MSH-9.1 == "ADT" && MSH-9.2 in ("A01", "A03", "A08")

Een bericht dat de filter afwijst, wordt opgenomen met de uitkomst gefilterd. Dit is een normaal resultaat, geen fout, en het activeert geen alarm of produceert geen negatieve bevestiging.

7.1 Gefilterd is niet gefaald

Deze onderscheid is het waard om stevig over te zijn, omdat het combineren ervan een echt probleem verbergt.

Een gefilterd bericht werd correct geweigerd: het was niet voor dit kanaal. Een gefaald bericht was er een dat dit kanaal had moeten verwerken en niet kon. Als beide op dezelfde manier werden opgenomen, zou een kanaal dat elke bericht faalt er exact hetzelfde uitzien als een kanaal dat de meeste van zijn verkeer filtert, wat de normale staat is van veel kanalen.

Dus tellen de statistieken ze apart, behandelen de alarmregels ze anders en toont de interface ze in verschillende kleuren. Een stijging in gefilterde berichten kan betekenen dat de afzender iets nieuws is gaan verzenden; een stijging in fouten betekent dat er iets kapot is.

7.2 Wat een filter kan lezen

Elk veld in het geparseerde bericht, via dezelfde paden die transformaties gebruiken. De filter wordt uitgevoerd voordat transformaties, dus het ziet het bericht zoals het aankwam — niet zoals het zal worden verzonden.

Deze volgorde is bewust gekozen. Een filter dat post-transformatie waarden leest, zou beslissen of een bericht moet worden geaccepteerd op basis van veranderingen die zijn aangebracht onder de veronderstelling dat het werd geaccepteerd, wat circulair is en kanalen produceert waarvan het gedrag afhankelijk is van de volgorde van twee dingen die onafhankelijk lijken.

7.3 Expressies

Vergelijkingen: ==, !=, en voor nummers <, <=, >, >=.

Lidmaatschap: in ("A01", "A03"), wat duidelijker is dan een keten van || en is de vorm die de builder produceert.

Combinatie: &&, ||, en haakjes. Negatie met !.

Afwezigheid: een pad dat niet aanwezig is, is ongelijk aan elke waarde, inclusief de lege string. Om afwezigheid expliciet te testen, moet u vergelijken met absent. Dit is van belang omdat een afwezig veld en een leeg veld verschillend zijn, zoals beschreven in transformatie, en een filter dat ze op dezelfde manier behandelt, berichten accepteert die het zou moeten uitsluiten.

7.4 Een fout in de filter is een weigering

Als de filter zelf faalt om te evalueren — een onjuist gevormde expressie die de validatie is gepasseerd, of een vergelijking die niet kan worden gemaakt — wordt het bericht geweigerd en wordt de fout opgenomen tegen het bericht.

Weigeren in plaats van accepteren is de veiligste van de twee, maar geen van beide is goed, en het resultaat wordt opgenomen op een manier die verschilt van een gewone filterweigering, zodat het kan worden gealarmeerd. Een filter dat faalt op elk bericht, laat de hele feed stilzwijgend vallen, en het mag er niet uitzien als een filter dat werkt.

7.5 Filter bij de bron waar mogelijk

Een filter wordt uitgevoerd nadat het bericht de netwerk heeft overgestoken en is geparseerd. Sommige bronnen kunnen filteren eerder en goedkoper:

Filteren bij de bron is een prestatiebeslissing, niet een correctheidsbeslissing, en het heeft een kosten: een bericht dat bij de broker wordt gefilterd, wordt nooit door Perfuse opgenomen, dus het verschijnt niet in de berichtenopslag en kan later niet worden geïnspecteerd. Als u moet kunnen bewijzen wat de afzender heeft verzonden, filter hier liever dan daar.

7.6 Een filter testen

Een filter kan worden gecontroleerd tegen echte historische verkeer voordat het wordt opgeslagen. De interface rapporteert hoeveel van de laatste N opgenomen berichten de filter zou accepteren, weigeren en fouten — wat de snelste manier is om te ontdekken dat een expressie die er goed uitziet, niets accepteert.

De trace toont ook, per bericht, welke velden de filter heeft gelezen en welke waarden hij heeft gevonden. Een filter dat onverwacht alles weigert, leest meestal een pad dat niet bestaat in deze feed, en de trace noemt het.

8 Berichtformaten

Het dataType van een kanaal beslist hoe bytes een bericht worden. Het beïnvloedt het parseren, wat paden betekenen, hoe het bericht wordt teruggestuurd en welke transformaties geldig zijn.

WaardeFormaat
hl7HL7 v2, de pipe-gegenereerde standaard. De standaard.
hl7v3HL7 v3 en CDA-documenten, die XML zijn.
x12ASC X12, gebruikt voor geschiktheid en claims.
ncpdpNCPDP Telecommunication Standard D.0-apotheekclaims.
scriptNCPDP SCRIPT, elektronische recepten. XML.
dicomDICOM-beeldobjecten.
delimitedCSV en andere door komma's gescheiden tekst.
rawGeen parsing. Bytes in, bytes uit.

8.1 HL7 v2

De standaard, en wat de meeste voorbeelden in deze handleiding gebruiken. Segmenten worden beëindigd met een carriage return, velden met |, componenten met ^, herhalingen met ~.

Twee dingen over de codering zijn het vermelden waard omdat ze stille fouten veroorzaken.

De scheidingstekens zijn niet vast. Ze worden verklaard in MSH-1 en MSH-2 van elk bericht, en Perfuse leest ze van daar in plaats van ervan uit te gaan dat het om pipes gaat. Een verzender die een ander veldscheidingsteken gebruikt, wordt correct geparsed.

De gevolgtrekking is dat een bericht waarvan de scheidingstekens zijn vervangen — meestal door een tekstverwerker of e-mailclient die typografische look-alikes vervangt — perfect in velden wordt geparsed die allemaal verkeerd zijn. Er treedt geen fout op. Dit is waarom de voorbeeldlezer die in testing wordt beschreven, aangeeft welk scheidingsteken het heeft gevonden en weigert om vertrouwen te hebben als het ongebruikelijk is.

Wanneer iemand u een voorbeeld stuurt en het kanaal dat daaruit is opgebouwd onzin produceert, controleer de scheidingstekens voordat u iets anders doet. Vraag om een bijlage in platte tekst in plaats van een bericht dat in de e-mailbody is geplakt.

8.2 HL7 v3 en CDA

XML in plaats van door komma's gescheiden. Paden zijn element- en attribuutpaden in plaats van veldposities.

In v3 is een waarde bijna altijd een attribuut in plaats van elementtekst. Een vergelijking die alleen elementtekst leest, rapporteert dat twee documenten identiek zijn wanneer de geboortedatum, het geslacht en elke identificator verschillen. Perfuse's vergelijking leest beide, en dat is de reden waarom: het alternatief slaagt er stilzwijgend in.

hl7v3-opties zijn in de formatreferentie.

8.3 X12

Segmenten worden conventioneel beëindigd met ~, met scheidingstekens die in het ISA-segment worden verklaard. Net als HL7 worden ze uit het bericht gelezen in plaats van ervan uit te gaan.

De structuur van X12 bestaat uit enveloppen binnen enveloppen — interchange, functionele groep, transactieset — en één interchange kan veel transacties bevatten.

Standaard is één interchange één bericht. Het hele bestand krijgt één record, één resultaat en één rij in het interface, ongeacht hoeveel transacties het bevat.

8.3.1 Mirth's X12 XML

Mirth Connect en Open Integration Engine tonen X12 als XML: een root X12Transaction (of EDIMessage wanneer de invoer niet met ISA begint) met de scheidingstekens als attributen, en één element per segment en element genaamd ISA.01, NM1.03.1 enz. Kanalen en ontvangers die zijn gebouwd voor Mirth lezen en schrijven deze vorm. Perfuse leest en schrijft dezelfde vorm:

Het formaat is geschreven vanuit de uitvoer en het gepubliceerde formaat van Open Integration Engine 4.6, en wordt gecontroleerd tegenover dit: 25 gegenereerde interchanges en 4 bewaarde voorbeelden komen er byte voor byte uit zoals OIE ze schrijft, en terug (zie verificatie). Een DOCTYPE wordt geweigerd, net als bij elk XML dat Perfuse leest.

8.3.2 Een interchange splitsen

Het instellen van split maakt elke transactieset een bericht in zijn eigen recht, met zijn eigen record, zijn eigen metriek en zijn eigen rij. Een operator die op zoek is naar één claim vindt dan één claim in plaats van een bestand met vierhonderd.

Het is standaard uitgeschakeld omdat het inschakelen ervan alles stroomafwaarts vermenigvuldigt — berichtentellingen, rijen, alarmdrempels — en een drempel die is afgestemd op bestanden die plotseling claims tellen, betekent niet wat het eerder betekende. Dat moet een beslissing zijn die iemand heeft genomen in plaats van een standaard die hij heeft geërfd.

split en acknowledge kunnen niet beide worden ingesteld, en een kanaal met beide wordt geweigerd bij het laden. Een bevestiging is een verklaring over een hele interchange, dus splitsen zou er één per transactieset sturen, en een partner die meerdere 999s ontvangt die dezelfde functionele groep noemen, heeft geen manier om ze te verzoenen.

8.3.3 Wanneer de tellingen niet kloppen

X12 verklaart zijn eigen tellingen — hoeveel segmenten, hoeveel transacties — en de envelope-sleutel zegt wat u moet doen wanneer ze niet overeenkomen met wat er daadwerkelijk aanwezig is. Die tellingen zijn de enige mechanisme die X12 heeft om te detecteren dat de helft van een claimsbestand is aangekomen.

WaardeGedrag
requireWeiger de interchange. De standaard.
warnVerwerk het, en registreer de fout tegen het bericht.
ignoreControleer helemaal niet.

warn bestaat voor een echte situatie: sommige partnersoftware heeft verkeerde tellingen gegenereerd voor jaren in anderszins complete bestanden, en een site die die moet verwerken, heeft een manier nodig om dat hardop in de configuratie te zeggen in plaats van de validatie helemaal uit te schakelen.

ignore is genoemd om oncomfortabel te zijn. Het instellen ervan gooit de enige manier weg die X12 u geeft om een afgekapt bestand te merken, en een afgekapt claimsbestand is niet te onderscheiden van een klein bestand.

8.3.4 Transacties die Perfuse als gestructureerde gegevens leest

Elke X12-uitwisseling kan worden doorgestuurd, gefilterd en geadresseerd op basis van het pad. Deze transacties worden bovendien verder geanalyseerd in genoemde velden, zodat een kanaal kan vragen wat een betaler heeft besloten in plaats van welk element op positie vier staat.

TransactieWat het bevat
835Betalingsadvies: wat is betaald, wat is geweigerd en de redenen voor aanpassing.
275Claims-bijlagen: klinische documentatie ter ondersteuning van een claim.
277Claimstatus, inclusief een verzoek van de betaler om aanvullende documentatie.
278Voorafgaande autorisatie: het verzoek om beoordeling en de beslissing van de betaler.
999Functionele bevestiging, die Perfuse ook genereert.
271Recht op vergoeding: of een patiënt is verzekerd, en de hoogte van de eigen bijdrage, verzekering, franchise en uitgaven buiten het netwerk.
834Inschrijving: leden toegevoegd, gewijzigd en beëindigd, met elk dekkingstype en de bijbehorende datums.
837Claims, zowel professioneel als institutioneel (lees voor CMS-0057's CARIN-conversie).

Perfuse maakt ook de 270-onderzoeksverzoek en de 276-claimstatusaanvraag, onder Verzekeraars → Claims & auth of via POST /api/x12/eligibility/build en /api/x12/claimstatus/build. Beide zijn de HIPAA 5010-versies (005010X279A1, 005010X212), gelezen en envelop-getoetst voordat ze worden weergegeven, en geen van beide wordt vanaf die pagina verzonden: het leveren van een van deze is de taak van een kanaal, waar de handelspartner en zijn referenties zijn.

8.3.5 Recht op vergoeding en de CAQH CORE-gegevensinhoudsregel

Een 271 is een lijst met EB-segmenten, elk een enkel feit: actieve dekking, of een eigen bijdrage van $25 voor diensttype 30 in het netwerk, of $800 van de individuele franchise resterend. De lezer assembleert ze in het antwoord dat een balie wil - "dekking actief onder Gold PPO 2000; eigen bijdrage in het netwerk $25; individuele franchise resterend in het netwerk $800" - en noemt een afwijzing (een AAA-segment) in woorden, met wat de betaler zegt te doen volgende.

Het controleert ook het antwoord tegen de CAQH CORE Eligibility & Benefits-gegevensinhoudsregel: voor een onderzoek naar gezondheidsverzekeringsdekking (servicetype 30), zou een actief antwoord plandata, de plannaam, co-betaling, co-assurantie, franchise en resterende franchise zowel binnen als buiten het netwerk moeten dragen, evenals de basisservicetypen (1, 33, 35, 47, 48, 50, 86, 88, 98, AL, MH, UC). Elk wordt opgesomd als voldaan of ontbreekt. Dit is Perfuse's interpretatie van de regel, nuttig voor "waarom vertelt deze verzekeraar ons nooit de franchise?" - het is geen CORE-certificering, die CAQH's geautoriseerde testleveranciers uitvoeren.

8.3.6 Voorafgaande autorisatie

Perfuse implementeert voorafgaande autorisatie tweemaal, met opzet.

De FHIR-kant is wat CMS-0057-F vereist dat betalers per 1 januari 2027 blootleggen. De 278 is wat betalers vandaag accepteren, en de regel vervangt deze niet — Da Vinci PAS is in de praktijk een toewijzing op deze transactie, omdat een 278 is wat een utilisatiebeheersysteem spreekt. Een motor die alleen de FHIR-helft leest, kan praten met de systemen die zullen bestaan en niet met degenen die dat doen.

Een 278-antwoord bevat het autorisatienummer, en dat is het veld waarvoor de hele transactie bestaat. Zonder dat is een gecertificeerde dienst niet declarabel: de claim gaat naar binnen zonder autorisatienummer en wordt geweigerd vanwege het ontbreken daarvan, wat downstream wordt gelezen als een klinische weigering.

Een weigering en een weigering om te overwegen zijn niet hetzelfde

Dit is de duurste verwarring in de transactie, en Perfuse rapporteert de twee afzonderlijk.

Wat is aangekomenWat het betekentWat te doen
HCR met actie A3De betaler heeft het verzoek overwogen en zal het niet certificeren.In beroep gaan, of het zorgplan wijzigen.
Een AAA-segmentDe betaler wilde het niet overwegen — patiënt niet gevonden, verzoeker niet erkend, beoordeling niet gedekt. Niets is besloten.Het verzoek corrigeren en opnieuw verzenden.

Beide worden voor iedereen die scannet als 'niet goedgekeurd' gelezen, en de correcte acties zijn tegenovergesteld. Beroep aantekenen tegen iets waar niemand een uitspraak over heeft gedaan, heeft geen effect; opnieuw indienen van een afwijzing leidt tot dezelfde afwijzing. De geparseerde uitkomstnamen die zijn opgetreden — denied tegenover not-considered — en AAA04 bevat de eigen advies van de verzekeraar over of het verzoek überhaupt hersteld kan worden.

De gedeeltelijke certificering wordt gerapporteerd als partially-certified in plaats van opgenomen in de goedkeuring. Er is een autorisatienummer om tegen te factureren, dus het telt als goedgekeurd, maar de gecertificeerde hoeveelheid is niet de aangevraagde hoeveelheid - en een praktijk die zes sessies boekt tegen drie goedgekeurde sessies, ontdekt dit bij de vierde claim.

Een actiecode die Perfuse niet herkent, wordt gerapporteerd als unknown, niet als pending. Pending wordt gelezen als "wachten" en wachten is de verkeerde actie voor de meeste dingen die een niet-herkende code zou kunnen zijn.

Een kanaal kan rechtstreeks routeren op basis van de beslissing:

filter: HCR-1 == "A3"

Omzetting tussen de twee

Perfuse zet een geparseerde 278 om in een Da Vinci PAS ClaimResponse, en rapporteert elke beoordeling die de omzetting nodig had in plaats van alleen het resultaat. De omzetting volgt drie regels:

Beperking tot een drie-staten-woordenboek — goedgekeurd, geweigerd, in behandeling — is beschikbaar en expliciet over wat het weglaat. Beperking van een weigering om te overwegen levert "geweigerd" op en zegt in woorden dat de juiste actie een gecorrigeerde herindiening is in plaats van een beroep.

Geverifieerd tegen PAS 2.2.1, niet alleen tegen zichzelf

De ClaimResponse is gevormd naar het Da Vinci PAS 2.2.1-profiel en werd geverifieerd met de officiële HL7-validator geladen met het gepubliceerde PAS-pakket. De eerste versie was alleen geverifieerd door Perfuse's eigen tests, en de validator wees deze af met zes tot acht fouten per resource. Elk van deze is iets dat een betalers PAS-eindpunt ook zou hebben afgewezen:

Wat er mis wasWaar PAS het plaatst
De beslissing stond in adjudication.category en reason.De reviewAction-extensie, op een adjudicatie waarvan de categorie submitted is.
De redencode met de naam X12-element 1034.X12-externe code lijst 886.
Een in behandeling zijnde verzoek beantwoordde outcome: queued.outcome gaat over verwerking en PAS staat alleen complete, error en partial toe. Een in behandeling zijnde verzoek is complete, met reviewactie A4.
processNote.type was een CodeableConcept.R4 heeft een code: print.
patient, created, insurer en request ontbraken.Alle vier zijn vereist. Ze worden gegeven als identifier-referenties, omdat de respons zelfstandig staat in plaats van in een bundel.

De gecorrigeerde output valideert zonder fouten voor een certificering, een weigering en een in behandeling zijnde verzoek. De waarschuwingen die overblijven, zijn de validator die zegt dat deze de X12-code-systemen niet kan laden, die X12 licentieert. Het autorisatienummer wordt meegedragen in reviewAction.number, waar het voorbeeld van de handleiding het zelf plaatst, en in preAuthRef wanneer de respons slechts één heeft.

De validator maakt geen deel uit van make check, omdat deze Java en een download van de handleiding en de afhankelijkheden nodig heeft. Wat deze heeft gevonden, wordt vastgehouden door een test: elke regel die deze heeft afgedwongen, wordt geassert, zodat een wijziging die een van deze fouten opnieuw introduceert, faalt.

Het Claims & auth-overzicht converteert een gekopieerde 278 en toont de beslissingen, de notities en de resource.

8.3.7 Bijlagen en waarom deze speciale verwerking nodig hebben

CMS-0053-F maakt de 275 een HIPAA-standaard voor claims-bijlagen, met naleving vereist tegen 26 mei 2028. Het bevat een document — een operatieve notitie, een beeldvormingsrapport, een gescande formulier — gekoppeld aan de claim die het ondersteunt.

De 277 is de andere helft van hetzelfde gesprek. Een betaler ontvangt een claim, besluit dat deze documentatie nodig heeft, en stuurt een 277 om hierom te vragen; de zorgverlener antwoordt met een 275.

Een kanaal kan rechtstreeks routeren op de statuscode, omdat STC01 een samengesteld is en het tweede onderdeel de status is. Geschreven in canonieke vorm, omdat een onderdeel wordt aangesproken met een punt en de twee notaties niet gemengd kunnen worden — STC-1.2 is onderdeel 1, component 2:

filter: STC-1.2 in ("227", "233", "252", "287")

Dit zijn de codes die ondubbelzinnig betekenen dat een document gewenst is. De status categorie in STC-1.1 wordt opzettelijk niet alleen gebruikt: R4 betekent een documentatieverzoek in sommige implementatiehandleidingen en "doorgestuurd naar elders" in andere, dus een filter op de categorie alleen zou afgeronde claims in de wachtrij plaatsen voor iemand om te achterhalen.

Twee identificatoren beslissen of een bijlage ooit wordt gekoppeld aan de bijbehorende claim, en beide worden gerapporteerd: het bijlagecontrole-nummer, dat de zorgverlener op de oorspronkelijke claim heeft geplaatst om aan te geven dat documentatie zou volgen, en het spoor-nummer, dat overeenkomt met het verzoek van de betaler. Een bijlage die aankomt met geen van beide, wordt opgeslagen en nooit verbonden met iets, terwijl de claim verouderd.

Een document binnen een 275 wordt niet geïnterpreteerd. Perfuse rapporteert de bytes en wat de afzender zegt dat het is. Een bijlage kan een PDF, een TIFF, een CDA-document of een HL7-bericht zijn, en een kanaal dat de inhoud nodig heeft, kan deze bytes doorgeven aan het formaat dat het leest.

Het 006020-formulier, dat het formulier is dat de regel overneemt

CMS-0053-F neemt versie 006020 over, en de 275 hiervan verschilt van het 005010-formulier op twee manieren die ertoe doen.

Perfuse unwrappt de entiteit en rapporteert het document erin, met het inhoudstype en de bestandsnaam. De bytes die het rapporteert, zijn exact dezelfde als de verzender had ingepakt. Een entiteit die niet kan worden uitgepakt, laat de ruwe payload op zijn plaats, met een notitie waarom.

Het opbouwen van een 275. Perfuse bouwt ook 006020X314-bijlagen: een ongevraagde bijlage om een claim te vergezellen, of een reactie op een verzoek van een betaler (277). Het verschil zit in BGN01 02 versus 11, en of TRN02 de claim's PWK06 of de 277's TRN02 bevat. Elke opgebouwde interchange wordt opnieuw geparsed voordat deze wordt geretourneerd, en het antwoord zegt of het document erin hetzelfde is als het document dat erin is gegaan.

De structuur komt uit de twee gepubliceerde companion guides voor 006020X314: de CMS esMD-gids en die van UnitedHealthcare. Het komt niet uit het X12-technisch rapport, dat X12 licentieert en dat dit project niet in bezit heeft.

Er is geen validatie tegen het technisch rapport. De companion guide van de partner is leidend.

8.3.8 Elektronische handtekeningen op bijlagen

CMS-0053-F neemt ook een handtekeningstandaard over, op 45 CFR 162.2002(e): de HL7-Implementatiegids voor CDA Release 2, Digitale Handtekeningen en Delegatie van Rechten, Release 1. Het is van toepassing op handtekeningen die op bijlage-informatie worden gezet wanneer deze in een HIPAA-bijlagetransactie wordt verzonden, vanaf 26 mei 2028. Een betaler mag niet meer vragen dan de gids voorschrijft.

Perfuse ondertekent een C-CDA op die manier op weg naar een 275, en controleert de handtekeningen op elk C-CDA in een 275 die het leest.

Als een van deze onbeschikbaar is, wordt de handtekening toch gemaakt en is deze geldig. Het resultaat noemt de XAdES-vorm die het heeft bereikt, en zegt wat het ervan weerhield om X-L te bereiken: bijvoorbeeld een zelf-ondertekend certificaat (geen CA om naar te vragen) of geen tijdstempelautoriteit.

De sleutel is -signing-cert en -signing-key. Zet de CA-certificaten na het certificaat van de ondertekenaar in hetzelfde bestand, zodat het pad met de handtekening meereist. Voor een handtekening die hetzelfde betekent als DSDR, moet het certificaat de cliniciennaam bevatten, met hun NPI, in plaats van de server. Ondertekenen is een beheeractie, net als het ondertekenen van elk document.

De gids noemt geen naamruimte voor de eigen elementen. Perfuse plaatst digitalSignature, authorizedSigner en SignaturePurpose in urn:hl7-org:sdtc. Het specificeert ook het doel als een XAdES-commitmenttype met de ASTM-OID, die XAdES-hulpmiddelen begrijpen. Delegatie van rechten, waarbij een gemachtigde ondertekent met een SAML-bewering van de gemachtigde ondertekenaar, wordt niet gegenereerd, en een ontvangen exemplaar wordt gemeld als niet geverifieerd.

De provider-NPI wordt gecontroleerd tegen de controlecijfer. Een betaler koppelt een bijlage aan de claim deels op basis van dat nummer, en een verkeerd getypt nummer laat de bijlage ongekoppeld, terwijl de claim wordt afgewezen vanwege ontbrekende documentatie.

Het Claims & auth-overzicht bouwt een 275 op van een gekopieerd C-CDA of een geüpload bestand, optioneel ondertekent het C-CDA, en leest er een terug met de bevindingen van elke handtekening. Niets op die pagina stuurt iets: de interchange wordt teruggegeven om te worden afgeleverd via een kanaal, dat is waar de partner, de referenties en de audittrail thuishoren.

8.3.9 Binaire segmenten

Een BIN-segment bevat ruwe bytes, en ruwe bytes bevatten scheidingstekens. Elk ander X12-segment eindigt bij de segmentterminator, dus een gewone parser vindt segmenten door naar één byte te zoeken; een bijlage kan niet op die manier worden gevonden. Een PDF met een ~ zou in stukken worden gesneden, en elk stuk is een structueel geldig segment — dus het document wordt afgekapt, elk segment daarna is misgealigneerd, en niets rapporteert een fout.

Perfuse leest het byte-aantal dat het segment aangeeft en neemt exact dat aantal bytes. Twee gevolgen die het vermelden waard zijn:

De esMD-handleiding bevat een voorbeeld van een uitwisseling dat 16 bytes verklaart voor hetzelfde 53-byte payload dat zijn tabel correct telt als 53. Perfuse weigert dit voorbeeld, zoals het hoort. Een test bevat zowel het voorbeeld van de tabel als de typefout in het voorbeeld, zodat een wijziging in beide richtingen wordt opgemerkt.

8.4 FHIR

8.4.1 Wat een HL7 v2-bericht wordt

Het berichttype bepaalt wat wordt gegenereerd, en elke conversie rapporteert de beslissingen die het nodig had als notities naast het bundel.

v2FHIR
ADTPatiënt, een Encounter wanneer er een bezoek is, een Condition per DG1-diagnose (ook opgenomen in de Encounter's diagnosis, een opname als AD), een Procedure per PR1 en een AllergyIntolerance per AL1. A28, A31, A29 en A24 gaan over de persoon, dus ze produceren geen Encounter of diagnoses, maar dragen wel allergieën.
ORUDiagnosticReport per OBR, met zijn Observations en Specimen, en de bestelling die het beantwoordt als een ServiceRequest (zijn aanvrager OBR-16 of ORC-12, zijn status ORC-5); OBR-32 is de resultaatinterpreter, OBR-34 en OBR-35 performers. Resultaten worden gegroepeerd onder het OBR ervoor op basis van positie, omdat OBX-4 niet betrouwbaar is.
ORM, OML, OMGServiceRequest.
SIUAppointment, met de patiënt, de praktijken van AIP en de locaties van AIL.
MDMDocumentReference met het document.
VXUImmunization, een per RXA.

Alles anders produceert de Patiënt en een waarschuwing met de naam van het type dat niet is toegewezen.

Planning. Een boeking, een herplanning, een annulering en een no-show komen allemaal terecht op dezelfde Appointment. De identiteit ervan komt van de eigen nummers van de afspraak in SCH-1 en SCH-2, nooit van het bericht, dus een annulering werkt de boeking bij. Het alternatief zou een tweede, geannuleerde afspraak naast een actieve zijn, wat aantoont dat de patiënt is geboekt in een tijdslot dat niet langer bestaat.

Documenten. Tekstnotities (TX, FT, ST) behouden hun lijnbreuk, inclusief lege lijnen, omdat een lege herhaling in een notitie een alineabreuk is.

Dit is wat het CMS Interoperability Framework-criterium 14 vraagt: grafiekenotities en klinische documenten die worden geretourneerd als FHIR-bijlagen.

Vaccinaties. Een dosis wordt nooit gemeld als toegediend wanneer het bericht zegt dat dit niet het geval is.

Moeilijke invoer. Elk van deze wordt gerapporteerd in de notities in plaats van stilzwijgend te worden besloten:

8.4.2 Wat een site toevoegt: het bundelscript

Een nationaal profiel wil vaak wat een HL7 v2-bericht niet bevat: een ziekenhuisnummer of ODS-code, welk contactniveau een bezoek heeft (ISiK), of een voornaam een voornaam of een initialen zijn (de Nederlandse nl-core). Perfuse raadt dit niet. Een fhir-bestemming heeft een bundle_script waarop een site deze gegevens kan schrijven: JavaScript die op elk omgezet Bundle wordt uitgevoerd, als bundle, voordat het wordt geverifieerd en verzonden. Wat het script achterlaat, wordt verzonden, gecontroleerd zoals elke conversie, en een script dat een fout gooit, mislukt het bericht zoals elke transformatie. De console heeft dit onder de bestemming *Voeg toe wat uw systemen weten*.

destinations:
  - name: kis
    type: fhir
    fhir:
      url: https://fhir.klinikum.example/fhir
      version: "4.0.1"
      identifier_systems: {KLINIKUM-MUSTERSTADT: "https://fhir.klinikum-musterstadt.example/sid/patientennummer"}
      bundle_script: |
        bundle.entry.forEach(function (e) {
          if (e.resource.resourceType === "Organization" && e.resource.name === "KLINIKUM-MUSTERSTADT") {
            e.resource.identifier = [{system: "http://fhir.de/sid/arge-ik/iknr", value: "260326822"}];
          }
        });

perfuse fhir convert -bundle-script FILE voert hetzelfde script uit, zodat een site het eerst zelf op zijn eigen berichten kan proberen. Twee voorbeelden werken in het repository: examples/isik/bundle-script.js (IKNR, Kontaktebene, MR-getypeerde patiëntnummer, Diagnosetyp) en examples/nictiz/bundle-script.js (voornamen en initialen). Met deze uitgevonden Duitse en Nederlandse berichten in conformance/national gaan van 18 naar 42 van de 47 resources geldig tegen ISiK en van 12 naar 18 van de 24 tegen nl-core; wat resteert, zit in de berichten of de terminologie-server en wordt daar opgesomd.

De Bundle gaat door Perfuse's model op zijn weg terug, dus een script's wijzigingen worden gecontroleerd en geschreven in de bestemming's FHIR-versie. Leden die het model geen veld voor heeft, worden bewaard zoals het script ze heeft geschreven, ook binnen gegevenstypen.

8.4.3 US Core 9.0.0 en USCDI v6

-us-core (en claim_us_core op een fhir-bestemming) plaatst een US Core-profiel in meta.profile, maar alleen op een resource die is gecontroleerd op dat profiel en in overeenstemming is bevonden. Een die tekort schiet, wordt nog steeds omgezet en verzonden zonder de claim, en een notitie geeft de reden, zoals "US Core vereist een ontmoetings-type, en deze Ontmoeting heeft er geen". De controles zijn overgeschreven van US Core 9.0.0, de versie die ONC's 2026 Standards Version Advancement Process goedkeurt voor USCDI v6. Ze dekken Patient, Ontmoeting, het laboratoriumObservatie en DiagnosticReport, Specimen, Practitioner, Organization, Location, Immunization, DocumentReference, de ontmoetings-diagnose Condition en AllergyIntolerance.

Wat de converter bevat, per USCDI v6-gegevensklasse:

USCDI v6VanAls
PatiëntgegevensPIDNaam, geboortedatum, geslacht, adres, telefoon en e-mail, identificatoren. Ras en etniciteit (PID-10, PID-22) in US Core's extensies wanneer gecodeerd in CDC Ras en Etniciteit. Voorkeurstaal (PID-15) als BCP 47
OntmoetingsinformatiePV1Ontmoeting met type, klasse, periode, locatie en deelnemers
FaciliteitsinformatiePV1-3Locatie, met de faciliteit als beheerorganisatie
Problemen, Begin van ontstaanDG1Aandoening (ontmoetingsdiagnose). DG1-5 is het begin, zoals de HL7 v2-naar-FHIR-kaart het heeft
Allergieën en intoleranties, ReactieAL1AllergieIntolerantie met categorie, criticaliteit en reactie
LaboratoriumORUDiagnostischRapport, Observaties, Specimen (uit SPM), ServiceRequest
BestellingenORM, OMLServiceRequest
VaccinatiesVXUVaccinatie
Klinische notitiesMDMDocumentReferentie
ZorgteamledenPV1, TXA, DG1Practitioner

Niet meegenomen, omdat v2-berichten van deze typen deze niet bevatten of Perfuse ze niet toewijst: Medicaties, Procedures, Doelen en Voorkeuren, Gezondheidsstatusbeoordelingen, Zorgplan, Familiegenealogie, Medische apparaten (UDI), Gezondheidsverzekeringinformatie, Vitale tekenen als een afzonderlijk profiel en Provenance.

8.4.4 R4 in beide richtingen

Een FHIR-server die R4 aankondigt, accepteert R4. Dat was niet waar voor Ontmoetingen tot deze release. De server zette wat het serveerde om naar R4, maar las wat het ontving alsof het al in zijn interne vorm was, dus een R4-Ontmoeting werd geweigerd met een 400. Dat gold ook voor elke bundel die Perfuse's eigen ADT-conversie produceerde, omdat elke Encounter.class bevat, die R4 als een enkele codering schrijft.

Het werd gevonden de eerste keer dat iets een omgezette ADT naar Perfuse's eigen R4-server postte. Een test doet dat nu voor elk toegewezen berichttype, en een andere controleert of alles dat als R4 is geschreven ongewijzigd wordt gelezen.

8.4.5 Internationaal Patiëntoverzicht

GET /fhir/Patient/{id}/$summary, of GET /fhir/Patient/$summary?identifier=system|value, retourneert een Internationaal Patiëntensamenvatting (HL7 IPS 2.0.0): een FHIR document-Bundle die de actieve problemen, allergieën, medicijnen, immunisaties, resultaten, vitale tekenen, procedures, apparaten, voormalige ziekten en zorgplannen van de patiënt bevat, elk met een leesbare narratief. Het is het korte record dat een clinici die de patiënt nog nooit heeft ontmoet, eerst leest, en de samenvatting die de Europese Gezondheidsgegevensruimte vanaf 2029 tussen landen uitwisselt.

Het wordt opgebouwd uit wat de FHIR-opslag bevat, en niets wordt verzonnen:

Access follows $everything: a token limited to one patient gets a 403 for another, and an identifier that matches two patients is refused rather than guessed. Only the IPS profile is built; asking for another profile is refused. The document Perfuse produces from its test records validates against the IPS 2.0.0 Bundle profile with the HL7 validator, with no errors. A record built from real feeds can still fail where the feed's own codes do (a display name the code system does not use, for example), because the summary passes the data on as it was received.

Uitwisseling → Gezondheidslinks → Delen vult de inhoud met een patiëntensamenvatting: typ de FHIR-id van de patiënt en kies Gebruik hun patiëntensamenvatting, lees deze en maak de link. Het bouwen ervan wordt geaudit als fhir.summary.

8.4.6 Overdrachtssamenvattingen voor post-acute zorg (PACIO)

Wanneer een patiënt het ziekenhuis verlaat voor een verpleeghuis, een revalidatie-eenheid of thuiszorg, stuurt het ziekenhuis-EHR een C-CDA: een overdrachtssamenvatting, een ontslag samenvatting of een CCD. Perfuse zet dat document om in de overdrachtssamenvatting die PACIO's Transitions of Care-gids beschrijft (hl7.fhir.us.pacio-toc 1.0.0): één FHIR R4 document-bundle, US Core 8.0.1 erin, die het ontvangende faciliteitssysteem kan opslaan zonder dat iemand XML hoeft te lezen.

Drie manieren om er een te maken:

Geverifieerd met de officiële FHIR-validator tegen het TOC 1.0.0 Bundle-profiel, op HL7's eigen C-CDA-voorbeelden (een overdrachtssamenvatting, een ontslagbrief en een CCD). De enige fout die het rapporteert, is in de handleiding: elke vitale functie komt overeen met zowel zijn simple-observation als zijn vital-signs Bundle entry slices, dus kan deze niet worden vermeden door enige afzender. Nog niet gedaan: het omzetten van de tekst-only secties (functionele status, mentale status, zorgplan, apparaten) in gecodeerde resources en de handleiding van de TOC DocumentReference die een opgeslagen overdrachtssamenvatting indexeert.

8.4.7 Abonnementen

Met -fhir-subscriptions stuurt het FHIR-eindpunt meldingen wanneer een Encounter of een Appointment wordt gemaakt of gewijzigd. Het volgt de FHIR Subscriptions R5 Backport IG voor R4, wat wordt gebruikt door CMS Interoperability Framework-criterium 15 en TEFCA's FHIR-roadmap voor afspraak- en encounter-meldingen.

Een client maakt een Subscription aan met een onderwerp en optioneel een filter zoals Encounter?patient=Patient/123. De onderwerpen worden vermeld in de capability statement:

OnderwerpVuur opFilters
https://perfuse.health/fhir/SubscriptionTopic/encounterEncounter gemaakt of bijgewerktpatient, status, class
https://perfuse.health/fhir/SubscriptionTopic/appointmentAppointment gemaakt of bijgewerktpatient, status

Een filter die iets anders noemt, wordt geweigerd, niet genegeerd. Een genegeerd filter is een abonnement dat meldingen verzendt over elke patiënt wanneer de client om één patiënt vroeg.

De eigenschappen waarop de implementatie is gebaseerd:

Wat een client de server kan laten doen, is opzettelijk beperkt:

Het is uitgeschakeld tenzij het wordt aangevraagd, omdat een FHIR-client deze server eenmaal aan kan zetten om patiëntgegevens naar een URL van de client te sturen. Het heeft een R4-eindpunt nodig dat schrijfbewerkingen accepteert en weigert te starten als dat niet het geval is.

Niet geïmplementeerd, zodat niemand het per ongeluk ontdekt:

De Abonnementen-weergave toont elk abonnement, onderwerp, filter en eindpunt, hoeveel gebeurtenissen het heeft gehad, hoeveel zijn geaccepteerd en hoeveel wachten, en de laatste reden waarom een werd geweigerd. Koptekstwaarden en de queryreeks van het eindpunt worden niet weergegeven, omdat dat is waar de referenties van de abonnee leven.

8.5 NCPDP Telecommunicatiestandaard

Apotheekclaims. Vaste breedte header gevolgd door variabele segmenten.

Twee details die ertoe doen, die beide gemakkelijk verkeerd kunnen gaan en plausibele resultaten opleveren:

De header is exact 56 bytes en heeft een vaste breedte. Een korte header kan niet alleen worden gedetecteerd door de lengte, omdat een afgekapt header plus de volgende segmenten nog steeds meer dan 56 bytes overschrijdt. Detectie gebeurt doordat een correcte header nooit een scheidingsteken bevat, dus de header wordt gescand op een scheidingsteken en een bericht dat er een bevat, wordt geweigerd met het aantal bytes dat het te kort komt.

0x1E en 0x1C zijn groeps- en veldstartmarkeringen, geen scheidingstekens. Deze als scheidingstekens behandelen, verschuift elk veld één plaats naar links, en de meeste van de resulterende waarden blijven plausibel — een hoeveelheid komt op de plaats van een dagverstrekking terecht en beide zijn nummers.

NCPDP- en SCRIPT-kanalen zijn uitgesloten van MLLP-framing, en dit wordt afgedwongen in plaats van geadviseerd. Een claim bevat rechtmatig 0x1C, wat MLLP's eigen eind-blokbyte is, dus het framen van een claim zou deze afkappen bij het eerste veldmarkering.

8.6 NCPDP SCRIPT

Elektronische recepten, in XML. Het interne pakket heet eprescribe omdat script al in gebruik was door de JavaScript-engine.

De centrale veiligheidszorg is de vervangingsvlag, en deze leest achterstevoren van de intuïtie: op de draad, betekent 0 dat vervanging is toegestaan en 1 betekent verstrekken zoals geschreven.

Een ontbrekende vervangingsvlag wordt geweigerd in plaats van standaard ingesteld. Beide mogelijke standaardinstellingen bereiken de patiënt — één kan een generiek verstrekken waar de voorschrijver de merknaam vereiste, de andere voorkomt een vervanging die de voorschrijver toestond — dus er is geen veilige veronderstelling en het bericht stopt.

Een Schedule II-recept met herhalingen wordt geweigerd, en de builder produceert er geen.

Weigeringen en waarschuwingen worden bijgehouden als afzonderlijke lijsten in plaats van één lijst met ernsttags, omdat een lezer die een ernstveld moet controleren om te weten of het bericht is verzonden, uiteindelijk niet controleert.

Elektronische voorafgaande autorisatie (PAInitiationRequest, PARequest, PAAppealRequest, PACancelRequest) en Real-Time Prescriptievoordelen worden beantwoord door de betalerkant op /ncpdp/script en /ncpdp/rtpb, vanuit de medicijnformulier; zie CMS-0057.

8.7 DICOM

Beeldvorming. Perfuse kan DICOM-objecten ontvangen, een externe archief opvragen en opslaan naar een, via de klassieke DICOM-netwerkservices of via DICOMweb, en het kan een eigen archief bijhouden voor viewers.

DICOM is geen berichtformaat in dezelfde zin als de anderen — objecten zijn groot, en de associatiehanddruk is belangrijker dan de payloadparsing. De called_ae- en calling_ae-titels zijn de meest voorkomende reden waarom een eerste verbinding mislukt, en het falen lijkt op een netwerkprobleem in plaats van een configuratieprobleem.

8.7.1 Wat een C-STORE-luisteraar accepteert

Als een DICOM-luisteraar open wordt gelaten, accepteert deze alles van iedereen die de poort kan bereiken. Vier instellingen onder Wat deze luisteraar accepteert beperken dit, en de eerste is degene die het waard is om te begrijpen.

Alleen deze oproepende AE-titels accepteren is de beperking. De *opgeroepen* AE-titel — de naam die naast het adres staat — is de naam die een verzender intoetst, dus deze identificeert de luisteraar in plaats van de verzender, en het is geen beperking. Iedereen die de poort kan bereiken, kan de correcte opgeroepen AE-titel gebruiken, omdat deze aan hen wordt gepubliceerd. Zonder een lijst van toegestane bellers, kan elke host op het netwerk beelden in een klinische kanaal pushen.

Alleen deze SOP-classes accepteren en Alleen deze overdrachtssyntaxen accepteren nemen door komma's gescheiden UIDs. Leeg accepteert elk type object en onderhandelt elke compressie die de verzender aanbiedt, wat inclusief soorten omvat die de bestemmingen van dit kanaal niet kunnen verwerken. Weigeren bij de associatie is duidelijker voor de verzender dan het object accepteren en later falen.

Grootste object dat wordt geaccepteerd is in bytes, en nul betekent geen limiet. Whole-slide-beelden en lange series kunnen tot gigabytes gaan, dus de limiet is anders in het geheugen.

8.7.2 DICOMweb

DICOMweb is DICOM over HTTP: QIDO-RS-zoekopdrachten, WADO-RS- en WADO-URI-opvraging, STOW-RS-opslag. Browserweergaven zoals OHIF spreken alleen DICOMweb, en dat doen de cloudbeeldvormingdiensten (Google Cloud Healthcare, Azure Health Data Services, AWS HealthImaging) ook. Perfuse gebruikt het op drie plaatsen.

Het beeldarchief. Start de server met -dicomweb-archive DIR (Instellingen › Gegevens › Beeldarchief) en het houdt objecten in die map bij, geïndexeerd in SQLite, en serveert ze op /dicomweb op het adres van de console: QIDO-RS op studie-, serie- en instantieniveau, WADO-RS voor objecten, metadata, frames en bulkgegevens, WADO-URI op /dicomweb/wado, en STOW-RS. Lezen vereist de weergaverol en opslaan de operatorrol, met een sessie of een API-token; elke lees- en opslagactie wordt in Activiteit als dicomweb.read of dicomweb.store geregistreerd. Een account dat is beperkt tot een tenant of tot kanaalgroepen wordt geweigerd, omdat het archief bij de hele server hoort. Objecten worden exact zoals ontvangen bewaard, dus wat een weergave ophaalt is bit voor bit wat was opgeslagen. Frames worden geretourneerd in de overdrachtssyntaxis waarin ze zijn opgeslagen; een verzoek dat transcodering zou vereisen beantwoordt met 406 in plaats van een geconverteerd beeld.

Een zoekopdracht op een kenmerk dat het archief niet indext, beantwoordt met 400 in plaats van de voorwaarde te negeren en meer studies te retourneren dan gevraagd. Geïndexeerd: patiëntennaam (jokertekens en fuzzy matching met fuzzymatching=true), patiënt-ID, geboortedatum, geslacht, studiedatum en -tijd (bereiken), toegangsnummer, studie-ID, beschrijving, verwijzende arts, studie-, serie- en SOP-instantie-UID's (lijsten), modaliteit, lichaamsdeel, serienummer en -beschrijving, SOP-klasse, instantienummer, rijen, kolommen en aantal frames.

De bron. type: dicomweb luistert naar STOW-RS, op /dicom-web/studies standaard (het pad dat Orthanc en dcm4chee gebruiken), en verzendt elk object via het kanaal als een DICOM-bericht. Het kanaal heeft dataType: dicom nodig. Stel een bearer token of een gebruikersnaam en wachtwoord in: zonder een daarvan kan iedereen die de poort kan bereiken beelden in het kanaal verzenden. Het antwoord bevat elk object als opgeslagen of mislukt, met de DICOM-foutreden, zodat een verzender weet welke opnieuw te verzenden.

name: imaging-from-viewers
dataType: dicom
source:
  type: dicomweb
  dicomweb:
    listen: 0.0.0.0:8043
    token: ${STOW_TOKEN}
    tls: { enabled: true, cert_file: /etc/perfuse/imaging.crt, key_file: /etc/perfuse/imaging.key }
destinations:
  - name: archive
    type: dicomweb
    dicomweb:
      url: https://perfuse.example/dicomweb
      token: ${ARCHIVE_TOKEN}

De bestemming staat in levering, onder DICOMweb-archieven.

OHIF naar het archief wijzen

Gebruik een DICOMweb-gegevensbron met qidoRoot en wadoRoot ingesteld op het adres van het archief (het Beeld-scherm toont het, met de hele gegevensbronblok om te kopiëren), wadoUriRoot naar dat adres gevolgd door /wado, imageRendering en thumbnailRendering naar wadors, en supportsFuzzyMatching ingesteld op true. Een weergave op een andere oorsprong heeft die oorsprong nodig in -dicomweb-cors (Browser-oorsprongen toegestaan om het aan te roepen), en de verzoeken hebben een API-token nodig in de Authorization-header, omdat een browser op een andere oorsprong de sessiecookie van de console niet verzendt. Het serveren van OHIF vanaf dezelfde oorsprong via een omgekeerde proxy voorkomt beide.

Getest tegen Orthanc met zijn DICOMweb-plugin, in beide richtingen: de bestemming slaat op in Orthanc, en Orthanc's DICOMweb-client zoekt Perfuse's archief op en haalt een studie op die bit-identiek is aan degene die is opgeslagen. OHIF 3 toont de studies van het archief en toont hun frames met de bovenstaande instellingen. OHIF en verschillende andere clients sturen type= ongequoteerd in de Accept- en Content-Type-headers, wat RFC 2045 niet toestaat; Perfuse accepteert het.

8.8 IHE document delen: XDS.b, XCA, XDR, MHD, PIXm en PDQm

Klinische documenten gedeeld tussen organisaties op de manier waarop gezondheidsinformatie-uitwisselingen, Carequality en eHealth Exchange doen: een repository bevat ze, een register indext hun metadata, en een gemeenschap beantwoordt vragen van andere gemeenschappen via een gateway. Start de server met -xds REPOSITORY-OID (Instellingen › Gegevens › Documentdeling) en het is alle drie, in de database van deze server, op de volgende adressen, elk met een API-token als bearer-token (de weergaverol om op te vragen en op te halen, de operatorrol om in te dienen; de meeste affiniteitsdomeinen voegen wederzijdse TLS toe aan de voorkant):

AdresActorTransacties
/xds/repositoryDocument RepositoryITI-41 Provide and Register Document Set-b, ITI-43 Retrieve Document Set
/xds/registryDocument RegistryITI-18 Registry Stored Query (alle dertien opgeslagen queries), ITI-42 Register Document Set-b
/xca/gatewayXCA Responding GatewayITI-38 Cross Gateway Query, ITI-39 Cross Gateway Retrieve, met -xds-home-community urn:oid:...
/mhdMHD Document Recipient en ResponderITI-65 Provide Document Bundle, ITI-66 Find Lists, ITI-67 Find Document References, ITI-68 Retrieve Document
/mhd/PatientPDQm Supplier en PIXm ManagerITI-78 Patient Demographics Query, ITI-83 Patient/$ihe-pix, vanuit de FHIR-store's Patients
/pixv3PIX Manager (HL7 v3)ITI-44 Patient Identity Feed HL7 V3, ITI-45 PIXV3 Query, vanuit de patientindex (-mpi)
/pdqv3PDQ Supplier (HL7 v3)ITI-47 PDQV3 Query, met voortzetting en annulering, vanuit de patientindex

De SOAP-transacties zijn SOAP 1.2 met WS-Addressing en MTOM/XOP waar documenten reizen (een document inline als base64 wordt ook geaccepteerd). Een mislukte transactie wordt beantwoord met een RegistryResponse met IHE-foutcodes, niet met een SOAP-fout: XDSDuplicateUniqueIdInRegistry, XDSNonIdenticalHash, XDSPatientIdDoesNotMatch, XDSMissingDocument, XDSRegistryMetadataError (met het ontbrekende veld), XDSStoredQueryMissingParam, XDSUnknownStoredQuery, XDSUnknownRepositoryId, XDSUnknownCommunity en UnresolvedReferenceException. Een vervanging (RPLC, XFRM_RPLC) deprecieert het document dat het vervangt, dat dan alleen nog antwoordt op queries die naar verouderde documenten vragen; APND, XFRM en signs worden behouden als associaties. Hash en grootte worden berekend door de repository en gecontroleerd tegen wat de indiening zegt. Op verzoek documenten en metadata bijwerken (ITI-57) worden niet ondersteund en een indiening die daarom vraagt, wordt geweigerd met de reden.

MHD is hetzelfde register in FHIR: een document dat via MHD wordt verstrekt, wordt gevonden door ITI-18 en via XCA, en een document dat via XDS.b wordt verstrekt, wordt gevonden door ITI-67. De id van een DocumentReference is de UUID van de entry, de masterIdentifier de uniqueId en de url van de bijlage de ITI-68-adres van het document. Patiënten worden opgelost naar de identifier van de affiniteitsdomein uit de FHIR-store: de eerste identifier waarvan het systeem urn:oid: is, of de Patient die in de Bundle wordt meegenomen. PIXm beantwoordt elke andere identifier van de Patient met de gegeven identifier (sourceIdentifier=system|value, ingeperkt door targetSystem), en 404 voor een die het niet kent; PDQm zoekt op identifier, naam, geboortedatum, geslacht, adres en telecom.

Publicatie. Een kanaal's xds-bestemming publiceert elk klinisch document dat het ontvangt, een CDA-document of een document dat wordt meegestuurd in een HL7 v2-bericht, naar elk XDS.b-repertoire met ITI-41. De metagegevens worden uit het document gelezen: de patiënt (de identifier in patient_domain, de affinitydomein's toewijzingsautoriteit), titel, type (als typeCode en, tenzij ingesteld, classCode), creatie- en servicetijden, auteur, vertrouwelijkheid, taal en formaat (C-CDA 2.1 of 1.1 gestructureerde body, XDS-SD, of mimeTypeSufficient, vanuit zijn sjablonen); en voltooid vanuit wat een document niet zegt: de afzender's source_id, de facility_type en practice_setting die elk register vereist. Het RegistryResponse van het repertoire beslist over de levering: een Failure of een fout in een PartialSuccess is een mislukte levering met de foutcodes van het register.

destinations:
  - name: hie
    type: xds
    xds:
      url: https://hie.example/xds/repository
      source_id: 1.2.840.114350.1.13.99
      patient_domain: 1.2.840.114350.1.13.99.2.7.5.737384.14
      facility_type: { code: "225732001", scheme: 2.16.840.1.113883.6.96, display: Community hospital }
      practice_setting: { code: "394802001", scheme: 2.16.840.1.113883.6.96, display: General medicine }
      tls: { enabled: true, cert_file: /etc/perfuse/hie.crt, key_file: /etc/perfuse/hie.key }

XDR. Voeg direct_from (uw Direct-adres) en direct_to (de ontvangers') toe en hetzelfde doel verzendt XDR als Direct's transport, zoals beschreven in het Direct Project's *XDR en XDM voor Direct Messaging*: een Direct-adresblok (urn:direct:addressing) in de SOAP-header noemt de afzender en ontvangers, en de submission's intendedRecipient noemt elke ontvanger (||^^Internet^address). Wijs url naar de XDR-endpoint van de ontvanger of een HISP die XDR accepteert. XDR reist over TLS, meestal met een clientcertificaat (tls), en is geen S/MIME. Een direct-bron neemt XDR ook (zie Direct hieronder).

    xds:
      url: https://xdr.hisp.example/xdr
      source_id: 1.2.840.114350.1.13.99
      patient_domain: 1.2.840.114350.1.13.99.2.7.5.737384.14
      facility_type: { code: "225732001", scheme: 2.16.840.1.113883.6.96, display: Community hospital }
      practice_setting: { code: "394802001", scheme: 2.16.840.1.113883.6.96, display: General medicine }
      direct_from: referrals@direct.hospital.example
      direct_to: ["intake@direct.clinic.example"]
      tls: { enabled: true, cert_file: /etc/perfuse/xdr.crt, key_file: /etc/perfuse/xdr.key }

PIX en PDQ in HL7-versie 3. Met de patientindex ingeschakeld (-mpi), is /pixv3 een PIX Manager en /pdqv3 een PDQ Supplier over SOAP 1.2, voor de ziekenhuizen en uitwisselingen die nog steeds IHE's v3-profielen spreken. Een bron voedt patienten met ITI-44 (record toegevoegd PRPA_IN201301UV02, herzien PRPA_IN201302UV02, duplicaten opgelost PRPA_IN201304UV02): de patient's eerste identifier is zijn record, de anderen en die in asOtherIDs zijn identifiers die hij draagt, en een samenvoeging vouwt de vorige record's identifier samen in de overlevende, zoals een HL7 v2 A40 doet. ITI-45 (PRPA_IN201309UV02) beantwoordt de andere identifiers van de persoon die er een heeft, versmald door dataSource, in Patient.id; de gevraagde identifier komt alleen terug in de herhaalde query. ITI-47 (PRPA_IN201305UV02) komt overeen met demografische gegevens (naam, geslacht, geboortetijd, identifier, adres, telecom) met de index's eigen matcher, minimumDegreeMatch als een score uit 100, otherIDsScopingOrganization beperkt de domeinen, en initialQuantity bladert het antwoord: de rest komt met QUQI_IN000003UV01 voor tien minuten, of wordt verwijderd door zijn annulering. De antwoorden volgen de cases van de transacties: een onbekende patient of domein is AE met fout 204 en de locatie van de parameter, een bekende patient met niets in de domeinen die worden gevraagd is NF. v3 noemt een autoriteit alleen door OID, dus een identifier wiens systeem een URL is zonder OID (erachter) (enkele nationale nummers) wordt weggelaten uit v3-antwoorden en gegeven via FHIR; stel de ondernemingsidentifier's systeem in op een OID (urn:oid:..., in de indexinstellingen) voor de EUID en de bewaarder om te verschijnen. De viewerrol vraagt en de operatorrol voedt; every transactie wordt geaudit met een identifier, nooit een naam. Een kale v3-boodschap die als application/xml wordt gepost, wordt beantwoord op dezelfde manier, wat handig is voor het testen met de hand.

Uitwisseling › Documentdeling toont wat het register bevat en waar het bereikt kan worden, vindt de documenten van een patiënt in dit register of een ander (een register's ITI-18 of een gateway's ITI-38), downloadt er een en publiceert een CDA-document handmatig met de metadata die een bestemming zou geven.

Geverifieerd tegen de NIST XDS Toolkit 7.13.0, de IHE-referentie-implementatie: Perfuse's ITI-41, ITI-18 en ITI-43 tegen zijn Registry/Repository-simulator (geaccepteerd zonder validatiefouten, het opgehaalde document byte-identiek), en zijn Initiating Gateway-simulator die Perfuse's Responding Gateway over XCA ondervroeg en ophaalde, zonder fouten in zijn log. Elk SOAP bericht dat Perfuse schrijft, valideert tegen de ebXML Registry 3.0- en XDS.b-schemas, en de MHD DocumentReference en SubmissionSet tegen IHE MHD 4.2.2 met de HL7 FHIR-validator. XDR van een xds-bestemming met een Direct-adresblok werd geaccepteerd door de toolkit's Document Recipient-simulator, wiens metadata-validatie de ene tekortkoming vond die in docs/verification.md staat, en door ONC SITE's XDR-validator, de Direct XDR-controlelijst die de (h)(2)-certificeringstest toepast. De PIX- en PDQ-v3-antwoorden valideren tegen IHE's HL7 V3-schemas (NE2008 multicacheschemas), en IHE's eigen voorbeeldberichten (de ITI-44-feed, samenvoegen, ITI-45-zoekopdracht, ITI-47-zoekopdracht, voortzetting en annulering) worden beantwoord zoals hun gepubliceerde antwoorden laten zien. Nog niet gecontroleerd tegen een onafhankelijke PIX- of PDQ-v3-implementatie, Gazelle of een Connectathon.

8.9 Directe beveiligde berichtenuitwisseling

Direct is de manier waarop Amerikaanse zorgverleners elkaar verwijzingen, samenvattingen en resultaten sturen via beveiligde e-mail: elk bericht is ondertekend met de zendercertificaat en versleuteld naar de ontvanger (S/MIME), en reist tussen HISPs (Health Information Service Providers) die de adressen uitgeven en ervoor instaan. Perfuse is het rand­systeem naast uw HISP, geen HISP: de HISP geeft uw adres, certificaat en sleutel uit, en u bewaart zijn vertrouwensbundle (zoals DirectTrust's). Het volgt de Direct Applicability Statement voor Secure Health Transport 1.2, de Implementatiehandleiding voor Delivery Notification, IHE XDM (ITI TF-1 Annex 15) voor documenten met metadata, de Certificate Discovery voor Direct Project Implementation Guide (DNS en LDAP), en XDR en XDM voor Direct Messaging.

Sending. A direct destination signs each message as your address (SHA-256, RSA), encrypts it to every recipient's certificate and your own (AES-256-CBC, RSA key transport), and submits it to the HISP by SMTP with STARTTLS required. The message travels as an attachment named by its content (document.xml, message.hl7, resource.json), or, with xdm: true, a CDA document travels as an IHE XDM package (IHE_XDM/SUBSET01/METADATA.XML with the document and its hash and size, plus INDEX.HTM and README.TXT) that receiving EHRs import with its metadata. Recipient certificates come from the Direct address book (below), then from DNS, where Direct publishes them as CERT records (RFC 4398): under the address with its @ made a dot, else under its domain; then from the recipient domain's LDAP directory, which its _ldap._tcp SRV record names (or ldap: host:port; ldap: off never asks one): each naming context is searched anonymously for an entry whose mail is the address, then the domain, and its userSMIMECertificate or userCertificate read. A certificate is used only when it is for the address or its domain, has not expired, and chains to one of your anchors, fetching any intermediate issuer its Authority Information Access extension names; and it is refused when its issuer's revocation list (from its CRL distribution point, signed by that issuer) lists it. A list that cannot be fetched does not stop delivery. A recipient with no such certificate is a failed delivery, never plain e-mail. to and subject take field references such as {PV1-8.1}, and request_mdn asks the recipient for a delivery notification.

destinations:
  - name: referrals
    type: direct
    direct:
      address: referrals@direct.hospital.example
      cert_file: /etc/perfuse/direct/referrals.crt   # with its chain after it
      key_file: /etc/perfuse/direct/referrals.key
      anchors_file: /etc/perfuse/direct/anchors.pem
      to: ["intake@direct.clinic.example"]
      subject: "Referral for {PID-5.1}"
      text: "Please see the attached summary."
      xdm: true
      xdm_source_id: 1.2.840.114350.1.13.99
      smtp_host: smtp.hisp.example:587
      username: referrals
      password: ${DIRECT_HISP_PASSWORD}
      request_mdn: true

Ontvangen. Een direct bron is de SMTP-server waar de HISP de post voor uw adres naar levert. Het neemt alleen post voor dat adres in ontvangst (alle andere wordt geweigerd bij RCPT), vereist STARTTLS wanneer een certificaat is gegeven, en opent elk bericht voordat het wordt gelezen: het decrypteert het met uw sleutel, verifieert de handtekening tegen uw ankers, en controleert of het certificaat van de ondertekenaar voor het adres van de afzender of zijn domein is. Een bericht dat niet is versleuteld met S/MIME, is ondertekend door een afzender die u niet vertrouwt, of is ondertekend met een certificaat voor iemand anders, wordt geweigerd bij DATA met de reden, zodat de HISP het behoudt en het rapporteert aan de afzender; Perfuse accepteert nooit wat het later verwijdert. Een XDM-pakket wordt omgezet in afzonderlijke berichten (gecontroleerd tegen de hashes in de metadata); anders wordt elke bijlage omgezet, of de tekst wanneer er geen bijlagen zijn. Met smtp_host ingesteld, wordt elk bericht dat wordt ontvangen beantwoord met een ondertekende, versleutelde 'verwerkt'-melding (MDN), en meldingen die aankomen voor wat u hebt verstuurd, worden gelogd.

source:
  type: direct
  direct:
    address: intake@direct.clinic.example
    cert_file: /etc/perfuse/direct/intake.crt
    key_file: /etc/perfuse/direct/intake.key
    anchors_file: /etc/perfuse/direct/anchors.pem
    listen: 0.0.0.0:2525
    tls_cert: /etc/perfuse/tls/server.crt
    tls_key: /etc/perfuse/tls/server.key
    smtp_host: smtp.hisp.example:587

Vanuit het postvak van de HISP. Een HISP die e-mail bewaart in plaats van deze te leveren, geeft het adres een IMAP-postvak: imap leest het (TLS of STARTTLS, elke peiling een nieuwe sessie), opent elk bericht zoals hierboven, verplaatst wat is opgehaald naar move_to (of verwijdert het) en wat niet kan worden geopend naar error_folder, zodat niets twee keer wordt gelezen. listen mag dan worden weggelaten. Een HISP wiens mailserver een privécertificaat heeft, wordt vertrouwd met tls.ca_file (zijn certificaat, of dat van zijn autoriteit) en tls.server_name; verificatie kan niet worden uitgeschakeld.

    imap:
      host: imap.hisp.example
      username: intake@direct.clinic.example
      password: ${DIRECT_MAILBOX_PASSWORD}
      move_to: Processed

XDR. xdr neemt XDR aan op /xdr op zijn eigen HTTPS-adres, zoals een HISP Direct naar SOAP converteert of een partner punt-tot-punt verzendt: een ITI-41 Provide and Register-verzoek waarvan elk document een bericht wordt. Een inzending waarvan het Direct-adresblok een ander adres noemt, wordt geweigerd, en een die het kanaal niet aanneemt, wordt beantwoord met een RegistryResponse-fout die zegt waarom. client_ca_file vereist een clientcertificaat van die autoriteiten. XDR wordt beschermd door TLS, niet S/MIME, dus een bron die alleen XDR aanneemt, heeft het adres nodig, maar niet zijn certificaat, sleutel of ankers. Elk document wordt een bericht van het kanaal's dataType: CDA-documenten hebben raw (doorgegeven zoals ze zijn) of hl7v3 nodig, omdat de standaard, hl7, HL7 v2 verwacht en deze weigert.

    xdr:
      listen: 0.0.0.0:8445
      tls_cert: /etc/perfuse/tls/server.crt
      tls_key: /etc/perfuse/tls/server.key
      client_ca_file: /etc/perfuse/direct/hisp-clients.pem

Uitwisseling › Direct lijst de Direct-adressen die uw kanalen verzenden en ontvangen, met hun certificaten, verloop en ankers; bewaart het adresboek van correspondenten (naam, organisatie, notities en certificaat, gekopieerd van hun HISP of gevonden in DNS of LDAP, en geweigerd wanneer het niet voor dat adres of domein is); en zoekt een adrescertificaten op in DNS of LDAP zonder ze op te slaan. Het boek is de directory direct-certs naast de database, één PEM-bestand per adres of domein, dat een bestemming leest, tenzij deze zijn eigen recipient_certs_dir noemt.

Geverifieerd tegen OpenSSL 4.0's cms en smime in beide richtingen: wat Perfuse ondertekent en versleutelt, verifieert en ontsleutelt OpenSSL (PKCS#1 v1.5 en OAEP-sleuteltransport), en Perfuse opent wat OpenSSL ondertekent en versleutelt (AES-128 en AES-256). Een bericht gemaakt met openssl smime en geleverd via SMTP wordt ontvangen, geopend en opgeslagen door een kanaal, en een door Perfuse verzonden bericht naar een andere via een HISP-tussenstation, dat antwoordt met een MDN die de verzender opent. Certificaten worden gevonden in OpenLDAP 2.4 (adresgebonden en domein-gebonden, geschreven door OpenLDAP's eigen ldapadd); een Direct-bericht wordt gelezen van een GreenMail IMAP-postvak en geopend, en een dat niet Direct is, wordt verplaatst naar de foutmap; XDR van een xds-bestemming wordt opgehaald door een direct-bron en geweigerd wanneer het is geadresseerd aan iemand anders, en geaccepteerd door de NIST XDS Toolkit's Document Recipient en ONC SITE's XDR-validator; SITE's Direct XDR Edge Test Tool heeft zowel zijn minimale als volledige metagegevensberichten naar een direct-bron gestuurd, die ze heeft opgehaald. Tegen ONC's Direct Certificate Discovery Tool kiest een Direct-bestemming het juiste certificaat, of geen, in alle 18 van zijn ontdekkingsgevallen (D1 tot D18: verlopen, ingetrokken en AIA-uitgegeven certificaten, SRV-prioriteit en gewicht, een onbereikbare directory). Een Direct-bron leest een bericht van SITE's eigen HISP (Apache James) via IMAP met STARTTLS. Nog niet getest: SMTP-uitwisseling met SITE's HISP (AWS houdt uitgaande e-mail op poort 25 voor nieuwe accounts) of met een geaccrediteerde HISP.

8.10 SQL op FHIR-weergaven

Een ViewDefinition (HL7 SQL op FHIR v2) zet elke FHIR-bron van een bepaald type om in rijen met benoemde kolommen, waarbij elke kolom een FHIRPath-expressie is, zodat FHIR-gegevens kunnen worden gelezen als tabellen door DuckDB, Athena, Spark, een datawarehouse of een spreadsheet. Perfuse voert deze uit met zijn eigen FHIRPath-engine: column, geneste select, forEach, forEachOrNull, repeat en unionAll, where, constant (elke waarde[x]-type), collection-kolommen, %rowIndex, en de getResourceKey()- en getReferenceKey(type)-join-sleutels.

{
  "resourceType": "ViewDefinition",
  "name": "blood_pressure",
  "resource": "Observation",
  "constant": [{ "name": "systolic", "valueCode": "8480-6" }],
  "where": [{ "path": "code.coding.exists(system = 'http://loinc.org' and code = '85354-9')" }],
  "select": [{ "column": [
    { "name": "id", "path": "getResourceKey()", "type": "id" },
    { "name": "patient_id", "path": "subject.getReferenceKey(Patient)", "type": "id" },
    { "name": "systolic", "path": "component.where(code.coding.code = %systolic).value.ofType(Quantity).value.first()", "type": "decimal" }
  ]}]
}

Monitor › SQL op FHIR voert een weergave uit over de FHIR-opslag van deze server (één patiënt of allemaal) of over bronnen die zijn geplakt (NDJSON van een bulkexport, een Bundle, een JSON-array), toont de rijen en downloadt ze als CSV, NDJSON of Parquet. Het begint met vijf voorbeeldweergaven (patiëntdemografie, observaties met een waarde, bloeddruk, aandoeningen, ontmoetingen) en slaat weergaven op in de views-directory naast de database, één JSON-bestand per weergave.

Het FHIR-eindpunt beantwoordt de specificatie $sql-run op systeemniveau, door GET of POST, voor een ViewDefinition-onderwerp gewezen inline (subjectResource), door subjectReference (ViewDefinition/<name>, een opgeslagen weergave) of door subjectCanonical (een gesaved weergave's url), met _format (csv, ndjson (de standaard), json of parquet), header, patient, _since, _limit, en resource om over resources te lopen die zijn verzonden met het verzoek in plaats van de winkel. Het is een leesbewerking: een SMART-token heeft leesbereik nodig voor het resource-type van de weergave, een token dat is gebonden aan één patiënt krijgt alleen de rijen van die patiënt, en granulaire bereiken vernauwen de resources die worden gelezen, net zoals bij een zoekopdracht. Meer dan een miljoen rijen vereist _limit, patient of _since.

perfuse sof -view v.json [-format csv|ndjson|json|parquet] [-o out] files... runs a view over FHIR files without a server: the NDJSON files of a bulk export, Bundles or arrays.

perfuse sof -view blood_pressure.json -format parquet -o bp.parquet export/Observation.ndjson
duckdb -c "SELECT patient_id, avg(systolic) FROM 'bp.parquet' GROUP BY 1"

Parquet-bestanden hebben één rijgroep en ongecomprimeerde PLAIN-pagina's; booleans zijn BOOLEAN, geheeltallentypes INT64, decimals DOUBLE en everything else UTF-8-strings (een collectiekolom als zijn JSON).

Geverifieerd met de officiële SQL op FHIR-testsuite (de 144 tests van de sql-on-fhir.js-repository's tests/, uitgevoerd op elke build: alle slagen), en de Parquet-uitvoer opnieuw gelezen door DuckDB 1.5.6 met de juiste typen en waarden. Niet ondersteund: SQLQuery en SQLView Libraries (SQL over de tabellen van de weergaven), $sql-export, _format=fhir, en de source- en group-parameters; elk wordt geweigerd met de reden.

8.11 Digitale kwaliteitsmaatregelen

Een digitale kwaliteitsmaatregel telt de patiënten in elke populatie van een FHIR Measure over een meetperiode (initiële totalen, teller, telleruitsluitingen en -uitzonderingen, noemer, noemeruitsluitingen) en scoort het resultaat. Het antwoord is een FHIR MeasureReport, gevormd zoals de Da Vinci Data Exchange for Quality Measures (DEQM)-handleiding vraagt. Dit is waar CMS's eCQM- programma's en NCQA's digitale HEDIS naar toe gaan.

In Perfuse zijn de populatiecriteria FHIRPath ("language": "text/fhirpath"), uitgevoerd door dezelfde motor als SQL op FHIR. Elk criterium wordt één keer per patiënt geëvalueerd. Zijn focus is een Bundle van de patiënt's record (de Patient-compartment), en hij heeft deze variabelen: %subject (de Patient), %periodStart en %periodEnd (de periode, als dateTimes) en %"Measurement Period". Een criterium geeft true of false; een enkele waarde die bestaat telt als true.

{
  "code": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": "numerator" }] },
  "criteria": {
    "language": "text/fhirpath",
    "expression": "entry.resource.ofType(Observation).where(code.coding.where(system = 'http://loinc.org' and code = '4548-4').exists() and effective.ofType(dateTime) >= %periodStart and effective.ofType(dateTime) <= %periodEnd).exists()"
  }
}

De populaties nesten zoals de Measure-specificatie zegt. Een patiënt is alleen in de teller als hij in de initiële populatie zit. Een telleruitsluiting haalt de patiënt weg voordat de noemer wordt beoordeeld. Een telleruitzondering telt alleen voor een patiënt niet in de noemer. Een proportie's score is (noemer − noemeruitsluitingen) / (teller − uitsluitingen − uitzonderingen); een verhouding's is noemer / teller; een cohort heeft tellingen en geen score. Enkelvoudige-criterium-stratifiers splitsen elke populatie op hun waarde (geslacht, bijvoorbeeld).

Perfuse heeft geen CQL-engine. De gepubliceerde CMS eCQMs en HEDIS-digitale maatregelen zijn geschreven in CQL, dus ze kunnen niet worden uitgevoerd zoals ze zijn. Een Maatregel waarvan de criteria CQL zijn, wordt geweigerd met die reden. Schrijf de logica als FHIRPath in plaats daarvan. Continue-variabele scoring, multi-component-stratificators en Groep- of Practitioner-onderwerpen worden op dezelfde manier geweigerd.

Monitor › Kwaliteitsmaatregelen evalueert een maatregel over deze server's FHIR-winkel of over geplakte resources, voor een periode. Het biedt drie rapporten: een samenvatting, een samenvatting met de patiënten in elke populatie, of één patiënt. Het scherm toont de populaties, de score en de strata, en downloadt de MeasureReport. Het begint met drie voorbeelden: bloeddruk onder toezicht, diabetes met een HbA1c-test, en patiënten gezien in de periode. Ze zijn illustratief, geschreven voor deze handleiding, en zijn geen CMS eCQMs of HEDIS-maatregelen. Opslaan in de FHIR-winkel controleert de Measure en slaat deze op als een Measure-resource.

Het FHIR-eindpunt beantwoordt Measure/[id]/$evaluate-measure en Measure/$evaluate-measure?measure=<url>, door GET of door POST van een Parameters-resource. Parameters:

Het rapport wordt geretourneerd, niet opgeslagen. De bewerking is een leesbewerking, dus een SMART-token heeft leesbereik nodig voor Measure en voor Patient. Een token dat is gebonden aan één patiënt krijgt een individueel rapport over die patiënt en geen andere.

perfuse measure -measure m.json -period-start 2026-01-01 -period-end 2026-12-31 [-type summary|subject|subject-list] [-subject Patient/ID] [-o out] files... evaluates a measure over FHIR files (a bulk export's NDJSON, Bundles, arrays) without a server. -measure example:example-bp-control runs a shipped example, and -examples lists them.

Geverifieerd. De HL7 FHIR-validator controleert de geleverde Measures tegen FHIR R4, zonder fouten. Het controleert een samenvatting, een individueel en een subject-list MeasureReport tegen de DEQM 5.0.0-samenvatting, individueel en subject-list-profielen, ook zonder fouten. Niet geverifieerd: equivalentie met enig gepubliceerd eCQM, aangezien geen enkel hier kan worden uitgevoerd zonder CQL.

8.12 De patiëntindex (MPI)

Een master patient index koppelt de records die elk systeem voor een persoon bijhoudt (het ziekenhuis's MRN, de kliniek's, de lab's) aan één ondernemingsidentifier, de EUID. Het is uit totdat iemand besluit om er een bij te houden, omdat het een tabel van patiënten's namen, geboortedata en identifiers is: schakel Instellingen → Gegevens → Patiëntindex in (of serve -mpi) en restart. Het leeft in mpi.db naast de hoofddatabase.

Voeden. Voeg een bestemming van het type mpi (De patiëntindex in de builder) toe aan de kanalen die registraties bevatten. Het leest de PID van elk HL7 v2-bericht of een FHIR-Patiënt op een ruw kanaal. Het record eigen identifier is de PID-3-herhaling van type MR (id_type verandert het); de anderen, en PID-19, worden zijn andere identificatoren. Een toewijzingsautoriteit met een universele identifier (PID-3.4.2 met type ISO) wordt urn:oid:...; een met alleen een naamruimte wordt toegewezen door authorities, of wordt urn:perfuse:aa:<namespace>. Een A40, A34, A18 of A39 voegt de persoon die de MRG-1-identifier heeft, samen met de persoon die de PID-3-identifier heeft (no_merge negeert ze).

destinations:
  - name: index
    type: mpi
    mpi:
      authorities: { HOSP: "urn:oid:1.2.840.114350.1.13.1" }

Matchen. Een nieuw record wordt op deze volgorde gekoppeld:

  1. Vertrouwde identificatoren. Een record die een identificator deelt van een systeem dat als vertrouwd wordt beschouwd (een nationaal identificatienummer, een ondernemingsnummer) is dezelfde persoon, zonder score. Nooit een systeem opnemen dat een gezin deelt, zoals een verzekeringsnummer van een abonnee.
  2. Score. Anders worden de personen wiens records mogelijk overeenkomen gevonden door blokkering (dezelfde familienaam en geboortejaar, dezelfde geboortedatum of hetzelfde telefoonnummer) en gescoord met Fellegi-Sunter-gewichten over familienaam en voornaam (Jaro-Winkler en Soundex, accenten en leestekens genegeerd, omgekeerde namen opgemerkt), geboortedatum (een dag en maand omgewisseld is gedeeltelijke overeenstemming), geslacht, postcode, telefoon en adres. Alleen velden die beide records hebben, tellen mee. De score is het bewijs dat is gevonden als een deel van het mogelijke bewijs. Blokkering gebruikt vijf sleutels, zodat één fout een persoon niet verbergt: familienaam geluid en geboortejaar, geboortedatum, telefoon, geluid van beide namen (in elke volgorde) en postcode met het geluid van de voornaam.
  3. Beslissing. Standaard koppelt niets op basis van een score alleen. Een record met een score van of boven de herzieningsdrempel (60%) wordt een nieuwe persoon en het mogelijke overeenkomst wacht op de herzieningswachtrij; die met of boven de automatische drempel (90%) met familienaam en geboortedatum die beide overeenkomen, worden gemarkeerd als *zeker*. Het koppelen van twee personen tot één (een overlay) zet één patiëntresultaat in de kaart van een andere, dus automatisch koppelen is een schakelaar die een beheerder activeert (Zeker overeenkomsten koppelen zonder iemand te vragen) zodra de wachtrij heeft aangetoond dat de zekere overeenkomsten correct zijn. Met deze schakelaar activeert, koppelt een zekere overeenkomst wanneer geen tweede persoon zo hoog scoort. Onder de herzieningsdrempel is het record een nieuwe persoon.

Nationale nummers. Het NHS-nummer (en Schotlands CHI en Noord-Ierlands Health and Care-nummer), Ierlands PPSN en IHI, Duitslands KVNR, Oostenrijks SVNR, Zwitserlands AHV-nummer, Nederlandse BSN, Belgiës nationale register nummer, Luxemburgs matricule, Frankrijks INS (NIR en NIA), Italiës codice fiscale, Spanjes DNI/NIE en CIP-SNS, Portugees SNS-nummer, de Noordse persoonsnummers (Zweden, Denemarken, Noorwegen met zijn D-nummer, Finland, IJsland), de Baltische codes, Polens PESEL, de Tsjechische en Slowaakse geboortedata, en de Hongaarse, Roemeense, Bulgaarse, Kroatische, Sloveense en Griekse nummers zijn bekend bij de index. Elk wordt op één manier opgeslagen: onder zijn systeem, spaties en punten verwijderd, dus het NHS-nummer dat door één systeem wordt verzonden als urn:oid:2.16.840.1.113883.2.1.4.1|999 000 0018 en door een ander als https://fhir.nhs.uk/Id/nhs-number|9990000018 is één identificator. Een HL7 v2 PID-3 herhaling waarvan het identificatortype NN is en een landcode van drie letters (NNDEU, NNNLD) wordt gelezen als het hoofdnummer van dat land, en type NH van de NHS-autoriteit als het NHS-nummer. Elke nummers controlecijfer wordt getest: één die faalt, wordt bewaard op zijn record, gerapporteerd (gemaskeerd) in het antwoord en nooit gebruikt om te koppelen of iemand te vinden, omdat een verkeerd getypt cijfer meestal iemands anders nummer maakt. Denemarkens CPR wordt alleen gecontroleerd op zijn datum, omdat nummers die zijn uitgegeven sinds 2007 niet hoeven te voldoen aan de oude modulus 11.

De instellingenlijst toont elk systeem met zijn formaat, zijn controle en het systeem waarin het wordt opgeslagen. Systemen die zijn overgenomen uit het landseigen FHIR-gids (UK Core, fhir.de, Nictiz, CH Core, ANS, HL7 Italia, MedCom, de Zweedse, Noorse en Finse OID-registers) worden gemarkeerd als zodanig; de anderen zijn standaardinstellingen die kunnen worden gewijzigd in de nationale waarde, die een site per systeem kan doen (de oude wordt nog steeds erkend). Een systeem vertrouwen is één vinkje. Nationale nummers worden standaard in hun geheel getoond aan editors en hoger en gemaskeerd (de laatste paar tekens) aan iedereen anders; Wie ziet nummers in hun geheel verandert dit, tot viewers of tot alleen beheerders. Waar een lands wet het gebruik van een nummer beperkt (Frankrijks Référentiel INS, Ierlands PPSN, Belgiës nationale register nummer, Duitslands §290 SGB V), zeggen de instellingen dit. GET /api/mpi/schemes lijst de systemen en POST /api/mpi/check controleert één nummer zonder het op te slaan. FHIR $match en PIXm antwoorden geautoriseerde clients met nummers in hun geheel.

Een datum die dag- of maand-eerst is geschreven (08/15/1972) wordt bewaard zoals geschreven en komt niet overeen met een jaar-eerst geschreven datum: de VS en Europese volgorde komen niet overeen, en gokken zou de verkeerde personen koppelen.

Het patiëntindexscherm (Build) toont de tellingen, zoekt personen op naam, nummer, EUID of geboortedatum, en opent elke persoon: hun dossiers, elke identifier, en de geschiedenis van wat er met hen is gebeurd en wie het heeft gedaan. Redacteuren beslissen over revisies (Dezelfde persoon koppelt hen; Verschillende personen houdt hen voor altijd gescheiden), verplaatsen een dossier naar een andere persoon, nemen een dossier weg (Niet deze persoon), en fusioneren twee personen. Beheerders stellen de drempelwaarden, de vertrouwde identificatiesystemen, de nationale nummers en het EUID-systeem in. Elke zoekopdracht en elke gelezen persoon worden geschreven naar het auditlog.

Antwoorden op vragen van anderen. POST /fhir/Patient/$match (FHIR's bewerking, zoals IHE PDQm ITI-119 deze gebruikt) neemt een Patient en retourneert de personen die het kunnen zijn, eerst de beste, every een Patient wiens id de EUID is, met elke identifier, search.score, en de match-grade extensie (certain, probable, possible); onlyCertainMatches en count worden gerespecteerd. PIXm (/mhd/Patient/$ihe-pix, ITI-83) antwoordt vanuit de index: every identifier van elke record die is gekoppeld aan de persoon, en de EUID. Dit doen PIX en PDQ in HL7 v3 (/pixv3, /pdqv3; zie IHE document delen) ook, die het ook voeden.

De API is /api/mpi (samenvatting en zoekopdracht), /api/mpi/persons/{euid}, /api/mpi/find, /api/mpi/reviews, /api/mpi/records (register, koppelen, ontkoppelen), /api/mpi/merge en /api/mpi/settings.

Gewichten. De standaard Fellegi-Sunter-gewichten komen uit de literatuur over record-linkage voor ziekenhuisregistratiegegevens. Schat uit onze records (in de instellingen, beheerders; POST /api/mpi/estimate) past ze aan op de sites eigen index met verwachting-maximalisatie, geen beoordeelde paren nodig: m (overeenstemming onder ware overeenkomsten) van de paren die blokkering samenbrengt, u (overeenstemming door toeval) van 20.000 paren die willekeurig zijn getrokken, omdat geblokkeerde paren door constructie overeenkomen in namen en data. De schatting wordt getoond naast de gebruikte gewichten en verandert niets totdat deze wordt gebruikt en opgeslagen. Een veld dat op te weinig paren wordt vergeleken, houdt zijn standaardgewicht. De fit gaat ervan uit dat de velden onafhankelijk zijn gegeven de klasse, wat ze niet helemaal zijn, dus behandel een grote verandering met argwaan.

Gemeten. Op FEBRL-dataset 3 (5.000 synthetische records van 2.000 personen, de duplicaten met typefouten, omgewisselde velden, ontbrekende waarden en bijnamen; PERFUSE_TEST_FEBRL), geregistreerd in bestandsvolgorde met een reviewer die elke gewoon paar correct beantwoordt:

Gekoppeld op eigen krachtVoorgelegd aan een reviewer met de juiste persoonGemistVerkeerde koppelingen
Automatische koppeling uit (standaard)02.649 van 3.0003510
Aan, standaardgewichten1.6371.0123510
Aan, gewichten geschat uit de records1.6221.0703080

Geen enkel record is ooit gekoppeld aan de verkeerde persoon, en geen van de 2.000 nieuwe personen is onnodig in de wachtrij geplaatst. De gemiste overeenkomsten verschillen in bijna elk veld (een geboortedatum en een adres die beide verkeerd zijn getypt, bijvoorbeeld) en scoren onder de herzieningsdrempel. FEBRL is synthetisch en heeft weinig naamgenoten; een echte index heeft er meer, dus de herzieningswachtrij zal langer zijn, en deze aantallen zijn een vloer voor de zorg, geen belofte.

8.13 Gelimiteerd

CSV en verwante bestanden. De opties staan op de bron in de builder, en de formaatverwijzing bevat de bestandsnamen.

Paden adresseren kolommen. Een benoemde kolom is beschikbaar wanneer een koptekstrij is verklaard of de namen zijn gegeven; anders worden kolommen positioneel aangesproken.

8.13.1 Kolommen benoemen

Er zijn twee manieren, en ze zijn exclusief. Of de eerste rij van het bestand noemt ze — de eerste rij noemt de kolommen — of u noemt ze zelf, in volgorde. Het declareren van een koptekst betekent dat de rij niet als gegevens wordt behandeld.

Als geen van beide is ingesteld, kunnen kolommen alleen positioneel worden aangesproken, dus een filter dat tegen een naam is geschreven, heeft niets om te matchen. Het inschakelen van de koptekst verwijdert de lijst met namen in plaats van beide te behouden: met een koptekst komen de namen uit het bestand, dus een achtergelaten lijst zou worden genegeerd, en een kanaal dat leest alsof het de namen heeft gekozen wanneer het bestand ze heeft gekozen, is moeilijker te debuggen dan een die weigert.

8.13.2 Wat een filter of script ziet

Een gelimiteerd document wordt veel berichten, dus dit moet worden gesteld voordat u een van beide schrijft.

Met splitsen ingeschakeld, werkt alles per rij. Declaratieve stappen, het filter en het transformatiescript zien allemaal één rij, en een pad betekent *deze* rij's kolom. Een filter dat een rij afwijst, wijst die rij en geen andere af, en het ontvangen aantal is rijen in plaats van documenten.

Met splitsen uitgeschakeld, is het bericht het hele document en een schrijfactie die rijen overschrijdt, wordt geweigerd in plaats van op de eerste rij toegepast. Die weigering is opzettelijk: stilzwijgend schrijven naar rij één is het gedrag dat een bestand produceert dat er getransformeerd uitziet en dat niet is.

8.13.3 De drie die veranderen wat als een fout wordt beschouwd

Rijen accepteren met het verkeerde aantal kolommen is standaard uitgeschakeld. Een rij met te veel of te weinig kolommen is dan een fout, wat het gedrag is dat een bestand vangt dat zonder waarschuwing van vorm is veranderd. Het inschakelen van deze optie accepteert de rij en laat de ontbrekende kolommen leeg.

Spaties om elke waarde trimmen lost het veelvoorkomende geval op van een waarde die is opgevuld tot een kolombreedte. Laat het uitgeschakeld waar achterste spaties belangrijk zijn, wat ze soms zijn in een identifier.

Lege regels als rijen behouden is standaard uitgeschakeld en zou dat meestal moeten zijn. Ingeschakeld, wordt een lege regel een rij van lege kolommen, wat alleen belangrijk is wanneer een telling exact moet overeenkomen met het bestand.

8.14 Ruwe

Geen parsing. Het bericht is bytes.

Gebruik dit wanneer de inhoud niet iets is dat Perfuse begrijpt en niet hoeft te zijn: een PDF die tussen systemen wordt verplaatst, een propriëtair formaat, een reeds gevormd document dat ongewijzigd wordt doorgestuurd.

De kosten zijn dat niets dat afhankelijk is van structuur werkt — geen veldniveau-transformatie, geen filter op een veld, geen veldniveau-vergelijking in de pariteitscontrole. Een ruw kanaal is een pipe, en het is eerlijk over het feit dat het een pipe is.

8.15 Kiezen

Als het bericht HL7 v2 is, gebruikt u hl7, zelfs als u het alleen ongewijzigd doorstuurt. Parsen geeft u het spoor, de veldniveau-statistieken, de mogelijkheid om later te filteren en de mogelijkheid om te vergelijken. raw op parseerbare inhoud heeft geen enkel voordeel en verliest alle voordelen.

Gebruik raw wanneer parsen zou mislukken of een leugen over de inhoud zou zijn.

De *Kill the Clipboard*-aanvraag van CMS vraagt aanbieders om een patiëntendossier van een QR-code te accepteren bij het inchecken en om het bezoekdossier op dezelfde manier terug te geven. De QR-code bevat een SMART Health Link (shlink:/...): een adres, een 256-bitsleutel en optioneel een label, een vervaldatum en een wachtwoordvlag. Exchange → Health links leest er een.

Ontvangen. Plak de link of scan deze met de camera waar de browser dit kan (Chrome en Edge). Perfuse haalt het manifest op, decrypteert elk bestand met de sleutel uit de link, samenvat eventuele FHIR-bundels - wie de patiënt is, hoeveel van elke resource - en controleert eventuele SMART Health Card tegen de gepubliceerde sleutel van de uitgever. *Afleveren aan het kanaal* geeft de FHIR-inhoud door aan een kanaal als een bericht, waardoor het de EHR bereikt. De opvraag wordt beperkt tot het egressbeleid bij aansluiting, gewoon HTTP wordt geweigerd en het antwoord van een server die geen manifestserver is, wordt nooit weergegeven, omdat het adres afkomstig is van een vreemde QR-code.

Delen. *Delen* versleutelt een FHIR-bundel, host deze en toont de link en de QR-code eenmaal. De server bewaart de ciphertext en niet de sleutel - het kan niet openen wat het host, en kan de link niet opnieuw weergeven. Een wachtwoord wordt gehasht; tien verkeerde wachtwoorden schakelen de link uit. Links verlopen na 30 dagen standaard, kunnen worden ingetrokken en tonen hoe vaak en door wie ze zijn opgehaald. Start de server met -public-url ingesteld op het https-adres dat de telefoons van patiënten bereiken; de manifest-URL die het bouwt, moet voldoen aan de specificatie van 128 tekens.

Een kaart verifiëren. *Een kaart verifiëren* neemt een numerieke shc:/ QR (één stuk of meerdere), een .smart-health-card-bestand of een JWS, en zegt of de handtekening overeenkomt met de sleutel van de uitgever.

8.17 UN/EDIFACT

dataType: edifact leest UN/EDIFACT-berichten (ISO 9735): ORDERS, INVOIC, DESADV, IFTSTA en de rest, inclusief het Europese zorgclaim- en laboratoriumbericht. Het service string-advies (UNA) wordt geëerbiedigd, met het release-teken en, voor syntaxisversie 4, de herhalingsscheidingsteken; functionele groepen (UNG/UNE) zijn optioneel. De berichtenwisseling wordt exact afgeleverd zoals de afzender deze heeft geschreven.

name: supplier-orders
dataType: edifact
edifact:
  envelope: require      # require (default), warn, or ignore
  split: false           # true: one interchange per message
  acknowledge: contrl    # none (default) or contrl
filter: 'UNB-2.1 == "5412345000013"'
source:
  type: as2              # or http, sftp, file, email ...
  # ...
destinations:
  - name: orders
    type: file
    dir: /data/orders
    filter: 'UNH-2.1 == "ORDERS"'

De envelop. UNT's segmenttelling en referentie, UNE's berichtentelling en referentie, en UNZ's telling en referentie worden vergeleken met wat de berichtenwisseling bevat. Met require, de standaard, weigert een mismatch de berichtenwisseling (het is hoe een overdracht die te vroeg wordt afgebroken, wordt getoond); warn accepteert deze en logt een waarschuwing; ignore controleert niet.

Paden, voor het kanaal- en bestemmingfilter, tellen elementen en componenten van 1 in de volgorde waarin het segment wordt geschreven, zoals implementatiehandleidingen deze nummeren: BGM-2 (het documentnummer), BGM-1.1, NAD(2)-2.1 (de tweede NAD-partij), LIN-3(2).1 (een herhaling), UNB-2.1 (de afzender), UNH-2.1 (het berichttype). Een pad zonder voorkomen richt zich tot elk exemplaar.

Splitsen levert één berichtenwisseling per bericht op, elk met de oorspronkelijke UNB (en groepskop) en trailers die één tellen, zodat een bestelling kan worden gefilterd, doorzocht en opnieuw geprobeerd. Bestemmingsfilters zien elk stuk. Een bestemming met een bestand noemt bestanden naar berichttype (ORDERS_INVOIC-20261017.edi), en ${control_id} is de referentie van de berichtenwisseling.

CONTRL. Met acknowledge: contrl wordt een afzender die via HTTP publiceert, beantwoord met een CONTRL-syntaxis- en servicerapport: UCI-actie 7 wanneer de berichtenwisseling werd gelezen en afgeleverd, 4 wanneer deze werd geweigerd of niet kon worden afgeleverd (HTTP 400 of 502 dan). Het kan niet worden gecombineerd met split, omdat een CONTRL een hele berichtenwisseling beantwoordt. Via AS2 is de ontvangstbevestiging van de partner de bevestiging.

Niet aangeboden: de berichtdirectory's (die segmenten ORDERS D.96A toestaat), dus de structuur wordt gecontroleerd, niet de inhoud; transformaties, die een document van een partner zouden herschrijven; en filter- of transformatiescripts (een preprocessor wordt uitgevoerd voordat deze wordt geparsed). Geverifieerd tegen pydifact 0.1.8, een onafhankelijke parser, in beide richtingen.

9 Bevestigingen

Een bevestiging vertelt de afzender wat er is gebeurd. Voor HL7 v2 via MLLP is het een ACK-bericht; de afzender zal het volgende bericht niet verzenden totdat het arriveert en zal het meestal opnieuw verzenden als het niet arriveert.

Bevestigingen verkeerd doen, is de meest voorkomende manier waarop een integratie stil data verliest, omdat een afzender die wordt bevestigd, geen reden heeft om te klagen.

9.1 Tijdsplanning

Besproken in berichtstroom, en het overzicht is: ack.when is on_delivery standaard, wat betekent dat de bevestiging alleen wordt verzonden nadat elke ingeschakelde bestemming het bericht heeft geaccepteerd. on_receipt verzendt het zodra het bericht is geparsed en in de wachtrij staat.

9.2 Wat Perfuse verzendt

Een AA wanneer het bericht werd geaccepteerd, een AE wanneer het werd afgewezen vanwege een reden waarop de afzender kon reageren, en een AR wanneer het werd afgewezen vanwege een reden waarop de afzender niets kon doen.

Het onderscheid tussen AE en AR is wie iets moet doen. AE betekent dat het bericht een probleem had - een veld dat niet kon worden geparsed als datum, een ontbrekend vereist segment - en de afzender het kan corrigeren en opnieuw verzenden. AR betekent dat Perfuse het niet kon accepteren, ongeacht de inhoud, wat meestal betekent dat er een configuratie- of beschikbaarheidsprobleem is aan deze kant. Een afzender die opnieuw verzendt na een AR krijgt hetzelfde antwoord.

9.3 Deze motor identificeren

ack.application en ack.facility vullen MSH-3 en MSH-4 van de bevestiging.

Wanneer beide leeg zijn, spiegelt de bevestiging de oorspronkelijke ontvanger — het gebruikt wat het inkomende bericht had in MSH-5 en MSH-6. Dat is wat de meeste afzenders verwachten, en het is de standaard om die reden.

Stel ze expliciet in wanneer de afzender ze valideert, of wanneer meerdere Perfuse-exemplaren hetzelfde feed verwerken en u moet weten welke heeft geantwoord.

9.4 Het triggergebeurtenis

ack.include_trigger_event verstuurt ACK^A01 in plaats van een kale ACK.

Sommige ontvangers vereisen dit en anderen wijzen het af, wat de reden is dat het een expliciete optie is zonder slimme standaard. Als een afzender uw bevestigingen weigert en de inhoud er goed uitziet, is dit het eerste dat u moet proberen.

9.5 Negatieve bevestigingen zijn geen fouten om te verbergen

Een NACK die als een succes wordt behandeld, is een van de meest schadelijke misconfiguraties die mogelijk zijn, en het komt vaak genoeg voor om het te noemen. Het gebeurt wanneer een bestemming een negatieve bevestiging terugstuurt en de verzendkant de *transmissie* als succesvol registreert omdat de bytes zijn verstuurd en er iets is teruggekomen.

Perfuse leest de bevestiging die het van een MLLP-bestemming ontvangt en registreert het resultaat dienovereenkomstig. Een AE of AR van een downstream-systeem is een leveringsfout, wordt opnieuw geprobeerd volgens het beleid van de bestemming en telt mee voor het foutpercentage waarop waarschuwingen worden geactiveerd.

Als u van een andere engine migreert, is het de moeite waard om dit expliciet te verifiëren op uw eigen verkeer in plaats van het aan te nemen. De parity checker zal het laten zien: een bestemming die de oude engine als geleverd heeft geregistreerd en Perfuse als mislukt heeft geregistreerd, betekent meestal dat de oude engine een NACK negeerde.

9.6 Time-outs

Het wachten op een bevestiging is begrensd. Wanneer deze niet op tijd arriveert, is de levering een fout en wordt deze in de wachtrij voor opnieuw proberen geplaatst.

Een time-out is niet hetzelfde als een afwijzing en wordt op een andere manier geregistreerd. Een afwijzing betekent dat de andere kant het bericht heeft overwogen en heeft afgewezen; een time-out betekent dat u niet weet of het is verwerkt. Dat onderscheid beslist of een opnieuw proberen veilig is: opnieuw proberen na een afwijzing is zinloos, en opnieuw proberen na een time-out riskeert een duplicaat. Perfuse probeert opnieuw na een time-out, omdat een ontbrekend klinisch bericht over het algemeen erger is dan een duplicaat, en het ontvangende systeem over het algemeen in staat is om een herhaalde berichtcontrole-ID te detecteren.

Of die ruil voor een bepaalde feed juist is, is een oordeel, en het is de moeite waard om het bewust te maken voor alles waarbij een duplicaat een klinische consequentie heeft — een bestelling, een medicatie-toediening — in plaats van stilzwijgend de standaard te accepteren.

9.7 Bronnen die geen bevestiging geven

Niet elk transport heeft het concept. Een bestandsbron heeft nergens een bevestiging naartoe te sturen; een broker-bron bevestigt aan de broker in plaats van aan de oorspronkelijke afzender; een HTTP-bron antwoordt met een statuscode.

Waar de bron de bevestigingsmodus die een kanaal vraagt niet kan leveren, wordt het kanaal geweigerd bij het laden in plaats van te starten en stilzwijgend geen bevestiging te geven. Een kanaal dat denkt dat het een bevestiging geeft en dat niet doet, is erger dan een kanaal dat niet start.

9.8 X12-bevestigingen

Alles hierboven gaat over HL7 v2. X12 heeft zijn eigen bevestigingen, en in tegenstelling tot v2 zijn ze uitgeschakeld: een lege instelling betekent geen.

Die standaard is de veilige, omdat een handelspartner die geen bevestiging verwacht en er een ontvangt, deze als een ongevraagde uitwisseling kan behandelen. De acknowledge-sleutel op een X12-kanaal neemt een van de vier waarden aan:

WaardeWat wordt verstuurd
noneNiets. De standaard.
999Implementatiebevestiging. Vervangt de 997 voor HIPAA-transacties.
997Functionele bevestiging. Ouder, en nog steeds wat veel betalingsverbindingen verwachten.
ta1Uitwisselingsbevestiging, over de envelop in plaats van de inhoud.

Welke moet worden verstuurd, is een eigenschap van de handelspartnerrelatie in plaats van van het bericht, wat de reden is dat het moet worden geconfigureerd en niet kan worden afgeleid. Een 999 vervangt een 997 voor HIPAA-transacties, maar veel partners — vooral oudere betalingsverbindingen — zijn ingesteld om een 997 te verwachten en zullen een 999 behandelen als een onherkenbaar bestand.

Het verzenden van de verkeerde bevestiging is erger dan het verzenden van geen. Het beantwoordt een vraag die niemand heeft gesteld, terwijl het echte open laat, en de afzender heeft geen manier om het verschil te zien.

9.9 HL7 v3-bevestigingen

Een HL7 v3-kanaal verstuurt een bevestiging standaard, wat het tegenovergestelde is van X12 en het waard is om te weten.

De reden is het transport in plaats van de standaard: een v3-interactie arriveert meestal via een synchrone verbinding met de verzendende toepassing die wacht op een antwoord, en een verzender die niets ontvangt, zal meestal opnieuw proberen. Dat is hoe een patiënt drie keer geregistreerd wordt.

Het uitschakelen is mogelijk en moet expliciet gebeuren — "niet ingesteld" en "ingeschakeld op false" zijn expres verschillend, dus de standaard blijft van kracht tenzij iemand anders heeft gezegd.

10 Bezorging, wachtrij en opnieuw proberen

Een bestemming die niet bereikbaar is, is de normale situatie, niet de uitzondering. Systemen worden opnieuw opgestart, netwerken vallen uit en een ziekenhuisinterface-engine is niet beschikbaar tijdens het onderhoudsvenster. Bezorging is hierop gebaseerd.

10.1 Wachtrij per bestemming

Attempt Delivered queue on disk — per destination 1, 2, 3, 4 … Retry growing backoff Dead letter kept, never discarded the same message, at the front Each destination has its own queue, so one slow receiver does not hold up the others. The queue is on disk, so a restart does not lose it. Order is preserved: message 2 is not attempted before message 1 succeeds or is given up on. A message that exhausts its attempts is dead-lettered and kept. Nothing is deleted to make a queue look healthy.

Elke bestemming heeft zijn eigen wachtrij. Een bestemming die faalt, beïnvloedt de anderen niet, en elke heeft zijn eigen diepte, leeftijd en opnieuw proberen status.

Wachtrijen zijn per bestemming in plaats van per kanaal, omdat het falen per bestemming is. Een kanaalbrede wachtrij zou de bezorging aan drie functionerende systemen vertragen, omdat een vierde uitvalt, en de twee situaties — één bestemming onbereikbaar, alle vier onbereikbaar — zouden er hetzelfde uitzien in de statistieken.

10.2 Wachtrijinstellingen

queue on a destination:

SleutelWat het doet
enabledOf mislukte berichten überhaupt in de wachtrij worden geplaatst.
max_attemptsHoe vaak te proberen voordat het opgeeft.
backoffWacht voordat de eerste opnieuw probeert.
max_backoffPlafond voor de groeiende wachttijd.
max_depthMeest berichten om vast te houden. Niet ingesteld betekent geen limiet.
retain_hoursHoe lang een bezorgd bericht wordt bewaard. Niet ingesteld houdt het het onbeperkt.

De laatste twee ontbraken in deze tabel en in de builder, en ze zijn het paar dat voorkomt dat een schijf vol raakt. Een wachtrij zonder een van beiden groeit totdat het bestandssysteem vol is, en dat falen komt als iets ongerelateerds dat breekt — een schrijffout ergens anders — in plaats van als een wachtrijprobleem.

Backoff groeit tussen pogingen tot max_backoff. Groeiend in plaats van vast, omdat een bestemming die uitvalt meestal uitvalt voor minuten in plaats van seconden, en opnieuw proberen elke seconde gedurende tien minuten produceert honderden logboekvermeldingen die de ene die ertoe doet, verbergen.

10.3 Volgorde wordt behouden

Binnen een bestemming worden berichten in aankomstvolgorde bezorgd, en een bericht dat faalt, behoudt zijn positie. Latere berichten wachten erachter in plaats van voorbij te gaan.

Dit is de juiste standaard voor klinische gegevens — een opname en een ontslag die in de verkeerde volgorde worden toegepast, is erger dan dat ze allebei laat zijn — en het heeft een gevolg dat het waard is om te begrijpen: één bericht dat altijd faalt, zal alles achter zich tegenhouden.

Dit is de reden waarom wachtrijdiepte en wachtrijleeftijd afzonderlijke waarschuwingsvoorwaarden zijn. Een diepe wachtrij die leegloopt, is een druk systeem. Een wachtrij waarvan het oudste bericht steeds ouder wordt, is vastgelopen en de waarschuwingstypen queue-depth, queue-age en queue-stuck onderscheiden hen.

Een giftig bericht — een dat nooit zal slagen, hoe vaak het ook wordt geprobeerd — is het specifieke falen waarvoor dit ontwerp kwetsbaar is. max_attempts is wat de schade beperkt: daarna wordt het bericht als mislukt geregistreerd en gaat de wachtrij verder. max_attempts heel hoog instellen in de hoop op uiteindelijke succes, verandert één mislukt bericht in een gestopte feed.

10.4 Wanneer wachtrijen zijn uitgeschakeld

Met queue.enabled ingesteld op false, is een mislukte aflevering een mislukte aflevering. Het wordt opgenomen en niet opnieuw geprobeerd.

Dat is de juiste keuze wanneer late gegevens erger zijn dan geen gegevens — een real-time-weergave, een pagingsysteem, alles waar een bericht dat veertig minuten na de gebeurtenis wordt bezorgd, misleidend in plaats van slechts vertraagd zou zijn.

Het is de verkeerde keuze voor alles wat in een record terechtkomt, waar het bericht net zo geldig is een uur later.

10.5 Opnieuw proberen versus wachtrij

Er zijn twee mechanismen en ze werken op verschillende niveaus.

retry op een bestemming beheerst onmiddellijke pogingen binnen één aflevering - een verbinding die mislukt, wordt na een korte pauze opnieuw geprobeerd, zonder de afleveringsweg te verlaten. Dit behandelt tijdelijke fouten: een verbroken verbinding, een tijdelijke weigering.

queue beheerst wat er gebeurt zodra die onmiddellijke pogingen zijn uitgeput. Het bericht verlaat de afleveringsweg en wordt later op een langere planning opnieuw geprobeerd.

Beide bestaan omdat de twee fouten verschillend zijn. Een verbinding die op de eerste poging wordt gereset, is meestal verdwenen bij de tweede, en door de wachtrij te gaan, zou dit enkele minuten latentie toevoegen aan een fout die enkele milliseconden duurde. Een bestemming die voor onderhoud is uitgeschakeld, zal niet binnen drie onmiddellijke pogingen terugkomen, en het heeft geen zin om het te blijven proberen.

10.6 Wat een HTTP-eindpunt als geleverd wordt beschouwd

Een HTTP-bestemming heeft drie instellingen die bepalen of een bericht als verzonden wordt behandeld, en alle drie staan op de bestemming in de builder.

Statuscodes die geleverd betekenen. Leeg betekent elke 2xx. Sommige eindpunten geven 202 Accepted voor iets dat ze nog niet hebben verwerkt, en sommige geven 200 met een fout in het antwoord - het tweede is waarvoor *Als mislukt behandelen als het antwoord bevat* is.

Volg omleidingen. Uitgeschakeld door default, en met opzet. Een omleiding kan naar een andere host verwijzen, dus het volgen ervan verstuurt het bericht naar een plek die niemand heeft geconfigureerd en rapporteert succes.

Bearer-token. Verzonden als een Authorization-header. Het wordt opgeslagen met het kanaal en nooit meer weergegeven, dus het laten van het vak leeg bij het bewerken van een bestaand kanaal houdt de token die al is opgeslagen in plaats van deze te wissen.

10.7 Naamgeving en snoeien van een archiefmap

Een bestemming met een bestand voegt standaard toe aan één bestand per dag en berichttype (20261012-ADT_A01.hl7), MLLP-geframeerd zodat het bestand kan worden afgespeeld met perfuse send. Vier instellingen op de bestemming veranderen dit.

Bestandsnaam (file_name) maakt één bestand per bericht in plaats daarvan, genoemd van ${date}, ${timestamp}, ${control_id}, ${message_type} en ${destination}. Een bestandsnaam die al in gebruik is (dezelfde besturings-ID tweemaal) krijgt een unieke suffix in plaats van het bericht daar te overschrijven.

Toevoegen (append: true) schrijft elk bericht naar het bestand Bestandsnaam dat is genoemd, dus ${date}.hl7 is één bestand per dag voor elk type.

Suffix tijdens schrijven (temp_suffix, één bestand per bericht alleen) staat standaard op .part en wordt verwijderd door een hernoeming zodra het bestand voltooid is. Wie deze bestanden ophaalt, moet geen halfgeschreven bestand ophalen, en een hernoeming binnen een map is atoom. Verander dit alleen als de verzamelaar filtert op een andere extensie.

Verwijderen na (retain_hours) snoeit bestanden in de map ouder dan het opgegeven aantal uren, gecontroleerd op maximaal elke tien minuten terwijl berichten aankomen. Alleen gewone bestanden rechtstreeks in de map worden verwijderd, nooit een submap. Leeg of nul houdt ze voor altijd, wat de standaard is en een beslissing is in plaats van een nalatigheid - maar een archief dat niemand snoeit, vult de schijf, en een volle schijf stopt het kanaal in plaats van het archiveren.

10.8 Verzenden naar een FHIR-server

Drie instellingen bepalen hoeveel wordt gecontroleerd voordat een bundel vertrekt.

Claim US Core-conformiteit voegt het profiel toe aan elke resource. Claim dit alleen wanneer de resource wat het profiel vereist bevat, omdat een ontvanger het tegen de claim kan valideren en een bundel kan weigeren die anders zou zijn geaccepteerd.

Valideren voordat verzenden controleert elke resource hier in plaats van te leren van de ontvanger. Een weigering aan de verre kant vertelt u minder, later, en vaak alleen in een log die u niet kunt lezen.

Waarschuwingen als weigeringen behandelen heeft alleen effect wanneer validatie is ingeschakeld, en de controle is niet beschikbaar totdat dit is gebeurd. Het is streng genoeg om een bundel te stoppen die een ontvanger zou accepteren, dus het hoort op een feed die wordt opgezet in plaats van een die in dienst is.

10.8.1 Gehoste FHIR-diensten

Een fhir-bestemming auth-blok meldt zich aan bij de gehoste diensten, waar een gekopieerde bearer-token binnen het uur ophoudt te werken:

fhir:
  url: https://healthlake.us-east-1.amazonaws.com/datastore/<id>/r4/
  auth: {type: aws, access_key_id: ${AWS_ACCESS_KEY_ID}, secret_access_key: ${AWS_SECRET_ACCESS_KEY}}

aws ondertekent elke aanvraag voor AWS HealthLake met Handtekeningversie 4, met de regio die uit de URL wordt gelezen. azure krijgt een Microsoft Entra-ID-token voor Azure Health Data Services van tenant_id, client_id en client_secret - een app-registratie die de FHIR Data Contributor-rol bevat - met de FHIR-service-URL als publiek. client_credentials doet hetzelfde tegen elke OAuth 2.0 token_url. Tokens worden hergebruikt totdat een minuut voor het verlopen. Dezelfde keuzes staan onder de Hosted service sign-in van de bestemming in de kanaalbuilder.

10.8.2 Openbare gezondheidszaakrapportage

Tick Rapporteer rapporteerbare voorwaarden aan de volksgezondheid op een FHIR-bestemming en het verzendt casusrapporten in plaats van bundles. Elk bericht wordt gecontroleerd op een rapporteerbare-voorwaarde-triggercode: een diagnose, een labtest of een gecodeerd resultaat. Als het er een heeft, wordt het bericht een HL7 eCR 2.1.2 eICR, verpakt in een eCR-bericht en gepost naar de URL's $process-message. Als het er geen heeft, wordt niets verzonden en niets faalt; de bestemming telt het als niet-rapporteerbaar.

fhir:
  url: https://ecr.agency.example/fhir
  ecr:
    rctc: /etc/perfuse/rctc.json
    source: https://fhir.springfield-general.example/fhir
    facility: {name: Springfield General Hospital, phone: +1-217-555-0100, city: Springfield, state: IL}

rctc is de Reportable Conditions Trigger Codes, als een FHIR ValueSet of de eRSD-bundle. Het heeft een UMLS-licentie nodig, dus het is niet inbegrepen; zonder het wordt een korte ingebouwde voorbeeld gebruikt, alleen voor testen. source is waar de instantie haar Reportability-antwoord verzendt. De faciliteit is vereist omdat eCR om haar telefoonnummer en adres vraagt, en een v2-bericht heeft geen van beide.

Een rapport zegt wat het bericht ontbrak in plaats van het uit te vinden, en elke lacune wordt gelogd. Probeer een bericht in het FHIR-lab's Openbare gezondheids casusrapport-paneel voordat u een live-feed naar een instantie wijst.

10.8.3 Laboratoriumresultaten naar openbare gezondheid: ELR

perfuse elr -config elr.yaml results.hl7 zet een lab's resultaten om in de HL7 2.5.1 ELR-berichten die de staatgezondheidsafdelingen ontvangen, één voor elk bericht met een rapporteerbaar resultaat, en alleen de orders die er een dragen: een complete bloedtelling naast een positieve SARS-CoV-2-test is niet de zaak van de volksgezondheid. De triggercodes zijn dezelfde als die voor casusrapportage, de RCTC die u laadt of de ingebouwde voorbeeld.

ELR noemt iedereen met OID of CLIA-nummer, wat geen enkele labfeed voor de afzender en de ontvanger bevat, dus die komen uit het bestand:

sending_application: {namespace: Perfuse, id: 2.16.840.1.113883.19.5.9, type: ISO}
sending_facility: {namespace: Springfield Lab, id: 2.16.840.1.113883.19.5, type: ISO}
receiving_application: {namespace: ELR, id: 2.16.840.1.113883.19.6.1, type: ISO}
receiving_facility: {namespace: State DOH, id: 2.16.840.1.113883.19.6, type: ISO}
processing: T
ordering_facility: {name: Springfield Clinic, phone: "+1 217 555 0100", line: 1 Main St, city: Springfield, state: IL, postalCode: "62701"}
performing_lab: {name: Springfield Lab, line: 2 Lab Rd, city: Springfield, state: IL, postalCode: "62701"}
performing_lab_clia: 14D0000000
placer_authority: {namespace: SPRINGFIELD-EHR, id: 2.16.840.1.113883.19.5.1, type: ISO}
filler_authority: {namespace: SPRINGFIELD-LAB, id: 2.16.840.1.113883.19.5.2, type: ISO}

De bestellende faciliteit, de uitvoerende lab en de toewijzingsautoriteiten worden alleen gebruikt waar het lab's bericht ze weglaat, en elke gebruik is een notitie. Wat alleen het lab weet, wordt nooit ingevuld: een resultaat zonder specimenaam gaat met SPM-4 leeg en een notitie die zegt dat, omdat een gegiste specie in een rapport aan de volksgezondheid erger is dan een lacune die de staat kan vragen. Begin met processing: T terwijl het staatsonboardteam de feed test.

Wat het lab goed deed, wordt gehouden zoals het werd verzonden. Een kindorder (een gevoeligheidspaneel of een reflextest waarvan OBR-29 de ouder noemt en die geen ORC van zichzelf heeft) gaat zoals ontvangen, zonder ORC of specie uit te vinden, en een kind zonder rapporteerbaar resultaat van zichzelf gaat met dat van de ouder, omdat een gevoeligheid niets betekent zonder de cultuur waar het bij hoort. Een notitie na de PID blijft bij de patiënt, en ORC-14, het call-back-telefoonnummer, wordt overgenomen van OBR-17 wanneer het lab het alleen daar neerzette. Alle 28 voorbeeldberichten die ONC publiceert voor zijn ELR-certificatietool komen uit als geldig met geen fouten.

MSH-2 wordt geschreven als ^~\&#, de vijf tekens die ELR Release 1's errata vereisen en ONC's certificatietool controleert. Als uw staatgids de oude vier laat zien, voeg encoding_characters: "^~\\&" toe aan het bestand.

Om ze vanuit een kanaal te verzenden in plaats van vanuit de opdrachtregel, geeft u de bestemming die de staat bereikt een elr-blok dat hetzelfde bestand noemt. Elk labresultaat wordt opnieuw gevormd op weg naar buiten, en een met niets rapporteerbaar wordt helemaal niet verzonden, wat wordt geteld als geleverd, niet gefaald: de staat vroeg alleen om rapporteerbare resultaten.

destinations:
  - name: state-elr
    type: mllp                 # or http, sftp, file: whatever the state's onboarding team gives you
    address: elr.health.state.example:6661
    tls: {enabled: true}
    elr:
      config: elr.yaml         # beside this channel file
      rctc: rctc.json          # optional; the built-in sample is for testing only

Het blok is van toepassing op een HL7 v2-kanaal, op bestemmingen die het bericht zelf leveren (mllp, http, tcp, bestand, sftp, ftp, S3, Azure Blob, soap, de message brokers, of een ander kanaal); het kanaal weigert te laden anders, en wanneer het bestand ontbreekt of ontbreekt aan de verzendende faciliteit, de ontvangende toepassing of de ontvangende faciliteit. De notities worden geschreven naar het logboek met het berichtcontrole-ID.

Het ELR-bestand is de metgezel van het kanaal, geen kanaal: perfuse check en het Channels-scherm slaan het over in plaats van een kanaal te melden dat niet zal laden. In de kanaalbouwer zijn de twee instellingen onder de bestemming, in Lab-rapportage (ELR 2.5.1); het triggercodes-veld opent zodra een ELR-bestand is genoemd, en opslaan weigert een bestand dat niet naast het kanaal staat.

10.8.4 DICOMweb-archieven

type: dicomweb slaat elk object op met STOW-RS: Orthanc, dcm4chee, de cloud-imagingdiensten, of een Perfuse-servers eigen archief. Geef de servicewortel (https://pacs.example/dicom-web); /studies wordt toegevoegd, en een URL die al eindigt met /studies wordt geweigerd in plaats van te posten naar /studies/studies. Verifieer met token (een bearer-token) of username en password; headers voegt andere toe, zoals een cloudservices projectheader. Het kanaal heeft dataType: dicom nodig.

Het antwoord van de server beslist over de uitkomst, niet alleen de statuscode. Een object dat het antwoord als mislukt noemt, is een mislukte levering met de DICOM-foutreden, en zo is ook een 202 die niets als opgeslagen noemt: de server nam het verzoek aan en hield niets ervan. Time-out staat standaard op twee minuten, omdat een grote reeks langzaam is.

10.8.5 Documentenrepositories (IHE XDS.b)

type: xds publiceert elk klinisch document naar een XDS.b-repository met ITI-41 Provide and Register: een CDA-document, of een dat een HL7 v2-bericht (MDM, ORU) draagt. De metadata komen uit het document en de bestemmingsinstellingen (source_id, patient_domain, facility_type, practice_setting), en het repositories RegistryResponse beslist over de levering. Zie IHE document delen.

10.8.6 Immunisatieregisters

Elk Amerikaans staat immunisatieregister (IIS) neemt HL7 2.5.1-berichten aan op hetzelfde SOAP-interface, het een dat de CDC in 2011 publiceerde (namespace urn:cdc:iisb:2011). Het heeft twee operaties: connectivityTest, die het eindpunt bewijst, en submitSingleMessage, die het bericht draagt. Een VXU^V04 rapporteert een injectie en komt terug als een ACK; een QBP^Q11 vraagt om een patiëntgeschiedenis en -prognose en komt terug als een RSP^K11.

Kies Immunisatieregister (CDC IIS-webdienst) als de dienst van een SOAP-bestemming, of schrijf profile: cdc-iis:

destinations:
  - name: state-registry
    type: soap
    soap:
      profile: cdc-iis
      url: https://iis.state.example/iis-ws/cdc
      username: clinic-submitter       # the registry account for this submitter
      password: "..."
      facility_id: FAC-1234            # optional in the WSDL; many registries require it
    queue: {enabled: true}

Perfuse bouwt de enveloppe, dus er is geen body om te schrijven. De gebruikersnaam en het wachtwoord gaan in het verzoek, waar de CDC WSDL ze plaatst, niet in de HTTP-authenticatie. De versie is SOAP 1.2, de binding van de WSDL, tenzij u version: "1.1" instelt voor een register wiens handleiding daarom vraagt. Waar een register een clientcertificaat vereist, stelt u de tls van de bestemming in zoals voor elke HTTPS-aanroep.

De bevestiging van het register beslist of het bericht is afgeleverd, niet de HTTP-status. Een register beantwoordt een afgewezen shot met HTTP 200 en een AR erin, dus een bestemming die de status vertrouwt, zou een verloren immunisatie als afgeleverd rapporteren.

Het register antwoordtPerfuse records
AA (of CA)Afgeleverd.
AE met ERR-segmenten die alle waarschuwingen zijn (ERR-4 W of I)Afgeleverd. De waarschuwingen staan in het antwoord.
AE met een ERR-4 E, of een ERR zonder ernstMislukt, met elke ERR-locatie, code en tekst in de fout.
AR of CRMislukt, op dezelfde manier.
Een SOAP-fout (verkeerd wachtwoord, bericht te groot)Mislukt, met de reden van het register.
Iets dat geen HL7-bericht isMislukt.

warnings_are_errors: true (Waarschuwingen als fouten behandelen) laat elke AE wachten op een persoon. Het antwoord, dat respons scripts en een HTTP-aanroeper die op het kanaal wacht, leest, is het HL7-bericht van het register: de ACK, of de RSP met de geschiedenis en de prognose. examples/iis bevat drie kanalen om mee te beginnen: VXU van een EHR via MLLP, QBP-queries via HTTP en een lokale stand-in voor een register.

Het Verbindingen-dashboard vraagt een register zijn connectivityTest wanneer niets is ingediend voor zeven dagen. Die bewerking bestaat voor dit doel en verzendt niets, dus het is de enige toepassingsniveaucontrole die Perfuse uitvoert. Het bewijst het adres, TLS en de SOAP-binding, niet de gebruikersnaam en het wachtwoord; alleen een echte indiening test die.

Een SOAP-bron kan op dezelfde manier antwoorden: Antwoorden als immunisatieregister, of profile: cdc-iis op de bron. Het echo't connectivityTest, neemt het bericht van submitSingleMessage, retourneert de bevestiging van het kanaal in return en serveert de CDC WSDL bij ?wsdl. Een gebruikersnaam en wachtwoord, wanneer ingesteld, worden gecontroleerd tegen degenen in het verzoek, en een verkeerd paar krijgt de SecurityFault van de WSDL. Een bericht dat het kanaal afwijst, gaat terug als een NAK, nooit als een fout, zoals de CDC-handleiding zegt. Gebruik het als testdouble, of om indieningen te ontvangen zoals een register dat doet.

Niet gedekt: de staatsspecifieke onderdelen van onboarding. Elk register heeft zijn eigen endpoint, accountproces en lokale profiel van de 2.5.1-handleiding (vereiste RXA- en OBX-velden, VFC-recht, weigeringscodes). Die zijn de inhoud van de berichten, die de transformaties van het kanaal vormen; geen staatendpoint is ingebouwd. Perfuse is getest tegen zichzelf en tegen opgenomen registerantwoorden, niet tegen een live staatregister.

10.9 Wanneer het transport ja zegt en het bericht niet is aangekomen

"Is dit aangekomen" is vaak geen vraag die het transport kan beantwoorden. Een MLLP-ontvanger retourneert een toepassingsbevestiging waarvan de betekenis in de tekst staat. Een HTTP-ontvanger retourneert 200 met een foutdocument. In beide gevallen is het transport geslaagd en is het bericht niet aangekomen.

Inspecteer het antwoord op een bestemming neemt een script dat de reactie van de ontvanger krijgt. Retourneer false, of gooi een uitzondering, en de levering wordt gemarkeerd als mislukt — wat betekent dat het opnieuw wordt geprobeerd, in de wachtrij wordt geplaatst en in de foutentelling verschijnt in plaats van stilzwijgend te worden geteld als afgeleverd.

Het wordt alleen aangeboden op bestemmingen die een antwoord ontvangen. Op een die dat niet kan, wordt het geweigerd bij het laden in plaats van nooit uitgevoerd te worden.

10.10 Wat een leveringsresultaat betekent

OutcomeMeaning
DeliveredThe destination accepted the message. For MLLP, a positive acknowledgement was received.
QueuedDelivery failed and the message will be retried.
FailedDelivery failed and will not be retried, either because queueing is off or attempts are exhausted.
FilteredThe destination declined the message by its own filter. Not an error.

Deze worden per bestemming per bericht opgenomen, dus een bericht dat drie van de vier bestemmingen heeft bereikt, wordt opgenomen als precies dat. Er is geen kanaalniveau "succes", omdat dat niets zou betekenen.

10.11 Trage levering

Een bestemming die berichten accepteert maar er lang over doet, is een apart probleem van een die faalt, en het is gemakkelijk om het te missen omdat elk resultaat een succes is.

Het slow-delivery-waarschuwingstype bestaat hiervoor. Het is de moeite waard om het in te stellen op alles waarop de bevestiging van de afzender wacht op de levering, omdat een bestemming waarvan de responstijd stilzwijgend is verdubbeld, uiteindelijk de time-out van de afzender zal overschrijden en zal beginnen met het produceren van opnieuw verzonden berichten — en op dat moment verschijnt het symptoom stroomopwaarts, in een systeem dat u mogelijk niet beheert.

10.12 Schrijven naar een database

type: database voert een instructie per bericht uit met waarden die zijn gebonden vanuit het bericht.

Plaatsaanduidingen zijn van de chauffeur — $1 voor postgres, ? voor mysql en sqlite, @p1 voor sqlserver — en Perfuse herschrijft ze niet. Dat is opzettelijk: een vertaallaag die een plaatsaanduiding verkeerd kreeg, zou de naam van een patiënt binden aan de verkeerde kolom, en het resultaat zou eruitzien als geldige gegevens in plaats van een fout.

Een instructie die in de verkeerde dialect is geschreven, wordt geweigerd wanneer deze wordt opgeslagen, waarbij de stijl wordt genoemd die de chauffeur wil. Voordat deze controle bestond, kwam de fout aan het licht als syntax error at or near "," van de server wanneer een bericht aankwam, die een instructie noemt die u hebt geschreven en u dus laat zoeken naar een typefout in plaats van naar de dialect.

destinations:
  - name: warehouse
    type: database
    database:
      driver: postgres
      dsn: ${WAREHOUSE_DSN}
      statement: INSERT INTO messages (mrn, family_name, birth_date) VALUES ($1, $2, $3)
      params:
        - PID-3.1
        - PID-5.1
        - PID-7

Een geciteerde parameter is een constante in plaats van een pad, wat de manier is waarop een kanaal zijn eigen naam of een broncode van het systeem in een rij naast de berichtgegevens schrijft.

Waarden worden altijd gebonden als parameters. Een ${...}-verwijzing in de instructie wordt geweigerd: een naam die een apostrof bevat, zou de instructie breken, en een vijandige waarde zou deze herschrijven.

10.13 Verzenden naar een onbewerkte socket

type: tcp schrijft naar een socket met framing die u kiest, wat meestal door een apparaat of een laboratoriuminstrument wordt gewenst. MLLP is een van de vele framings; deze bestemming biedt de anderen.

destinations:
  - name: instrument
    type: tcp
    tcp:
      address: instrument.lab:9100
      framing: delimited
      delimiter: \r
      expect_reply: true
      timeout: 30s

Framing heeft geen standaard, met opzet. Schrijven met de verkeerde framing mislukt niet. Het verre einde leest berichten die op de verkeerde plaatsen zijn gesplitst, of wacht op een terminator die nooit komt, en het symptoom verschijnt in het ontvangende systeem in plaats van hier.

framingWat het schrijft
mllp0x0b voor, 0x1c 0x0d erna. Dezelfde framing die een MLLP-bestemming gebruikt.
delimitedEen delimiter na elk bericht, en een optionele start_block ervoor.
fixedRecords worden opgevuld of afgekapt tot record_length.
lengthEen length_bytes-prefix. big_endian en length_includes_header hebben beide twee conventies in de praktijk en het verschil is stil.
wholeÉén bericht per verbinding, gesloten om het einde aan te geven.

Alleen de instellingen die de gekozen framing gebruikt, worden geaccepteerd. Een recordlengte in een gedifferentieerde stroom wordt geweigerd in plaats van genegeerd, omdat een instelling die stil wordt genegeerd, een instelling is die iemand denkt dat van kracht is.

expect_reply verandert wat geleverd betekent. Zonder dit, betekent succes dat de bytes de verzendbuffer van het besturingssysteem hebben bereikt — wat een peer die een moment later crashte, nooit heeft gelezen.

10.14 Amazon S3, SQS en SNS

A channel can read from an SQS queue or an S3 bucket prefix, and deliver to SQS, SNS or S3. All five are signed HTTP with no AWS SDK in the binary, and all five take the same access settings: region, access_key_id, secret_access_key (write ${AWS_SECRET_ACCESS_KEY} to read the environment), an optional session_token, and endpoint for LocalStack, MinIO or a VPC endpoint. Under Channels → New channel, choose *We read from an Amazon SQS queue*, *We collect objects from an Amazon S3 bucket*, or the SQS, SNS and S3 destination types.

Niets wordt bevestigd aan AWS totdat het kanaal het heeft verwerkt. Een SQS-bericht wordt daarna verwijderd en anders opnieuw weergegeven wanneer de zichtbaarheidstijdslimiet eindigt, dus een wachtrijbeleid voor herstuur verplaatst er een die blijft mislukken naar een doodbriefwachtrij. Een S3-object verplaatst zich naar processed/ daarna, of naar error/ als het niet kon worden verwerkt, dus één slecht bestand stopt de rest niet.

Op een FIFO-wachtrij of -onderwerp worden berichten gegroepeerd per patiënt standaard - SQS houdt de volgorde binnen een groep en nergens anders - en gedupliceerd op inhoud, dus een herhaling wordt niet tweemaal afgeleverd.

Een S3-archief kan rechtstreeks naar Glacier worden geschreven met storage_class, en als JSON-regels voor Amazon Athena met format: ndjson; perfuse athena print de tabel. De referentie bevat elke instelling.

10.15 AMQP 1.0 en Azure

AMQP 1.0 is wat Azure Service Bus en Event Hubs spreken, en RabbitMQ 4, ActiveMQ en Artemis naast hun andere protocollen. Een amqp-bron ontvangt van een wachtrij of een abonnement en accepteert elk bericht alleen nadat het kanaal het heeft verwerkt; een dat niet kon worden verwerkt, wordt vrijgegeven als een mislukte levering, zodat de broker het opnieuw levert en, voorbij de limiet van de wachtrij, doodbrief het. Een amqp-bestemming rapporteert alleen succes wanneer de broker het bericht accepteert. Voor Service Bus: addr is <namespace>.servicebus.windows.net:5671 met tls, username de naam van het gedeelde toegangsbeleid, password de sleutel ervan en address de naam van de wachtrij, of <topic>/subscriptions/<name> om te ontvangen.

Azure Blob Storage: een azure_blob-bestemming schrijft een blob per bericht in de toegangslaag die is gekozen - Hot, Cool, Cold of Archive - en een azure_blob-bron pikt blobs op van een prefix, verplaatst ze naar processed/ of error/ zoals de S3-bron doet. Verkies een SAS-token beperkt tot de container boven de account sleutel.

10.16 MQTT

Een mqtt-bron abonneert zich op een onderwerpfilters (+ komt overeen met één niveau, # elk niveau daaronder) op elke MQTT 3.1.1-broker: Mosquitto, EMQX, HiveMQ, AWS IoT Core, Azure Event Grid. Bij QoS 1, de standaard, wordt elk bericht alleen bevestigd nadat het kanaal het heeft verwerkt. MQTT heeft geen manier om één bericht te weigeren, dus één dat niet kon worden verwerkt, wordt onbevestigd gelaten en de verbinding wordt opnieuw gemaakt; de broker houdt de sessie onder de client-id (perfuse-<channel> tenzij client_id anders zegt) en stuurt het opnieuw, als eerste in de rij. QoS 0 is maximaal één keer: alles wat wordt verzonden terwijl Perfuse uitgeschakeld is, gaat verloren. Een mqtt-bestemming publiceert en, bij QoS 1, rapporteert succes wanneer de broker het bericht heeft.

source:
  type: mqtt
  mqtt:
    addr: broker.hospital.local:8883
    topic: hl7/+/adt
    username: perfuse
    password: ${MQTT_PASSWORD}
    tls: {enabled: true, ca_file: /etc/perfuse/broker-ca.pem}

AWS IoT Core wil een clientcertificaat: geef tls.cert_file en tls.key_file.

10.17 IBM MQ

ibm_mq leest en schrijft IBM MQ-wachtrijen via de REST API voor messaging van de wachtrijbeheerder (mqweb), die IBM MQ 9.1.5 en later op elk platform meelevert, inclusief z/OS, dus er hoeft geen MQ-client naast Perfuse te worden geïnstalleerd. De gebruiker moet de rol MQWebUser hebben en autoriteit hebben om berichten te plaatsen, op te halen en te doorzoeken in de wachtrij. Een bron doorzoekt het eerste bericht, geeft het door aan het kanaal en verwijdert het alleen met zijn bericht-id als het is verwerkt; een bericht dat mislukt, blijft bovenaan in de wachtrij. Voer één lezer per wachtrij uit. Een bestemming plaatst persistente berichten (tenzij non_persistent), met de HL7-controle-id als correlerings-id.

destinations:
  - name: to-mainframe
    type: ibm_mq
    ibm_mq:
      url: https://mq.hospital.local:9443
      queue_manager: QM1
      queue: HL7.ADT.OUT
      username: perfuse
      password: ${IBM_MQ_PASSWORD}
      tls: {enabled: true, ca_file: /etc/perfuse/mq-ca.pem}

api_version is v3 voor MQ 9.3 en later (de standaard), v2 voor 9.1.5 tot 9.2. Een wachtrijbeheerder met een AMQP-kanaal kan ook worden bereikt met de amqp-connector.

10.18 Google Cloud Pub/Sub en Cloud Storage

Een pubsub-bron haalt berichten op uit een abonnement en bevestigt elk bericht zodra het is verwerkt; één dat mislukt, wordt onmiddellijk teruggegeven (de bevestigingsdeadline wordt ingesteld op nul), met de rest van zijn batch, zodat Pub/Sub het opnieuw levert en, voorbij het dead-letterbeleid van het abonnement, dead-letters het. Een pubsub-bestemming publiceert met het HL7-berichttype en de controle-id als kenmerken; order_by: patient stelt de sorteersleutel in vanuit PID-3.1, zodat een abonnement met berichtsortering de berichten van elke patiënt in volgorde houdt.

Een gcs-bestemming schrijft één object per bericht, genoemd zoals een S3-sleutel, in de opgeslagen klasse die is geselecteerd (STANDARD, NEARLINE, COLDLINE, ARCHIVE). Een gcs-bron haalt objecten op uit een voorvoegsel en verplaatst ze naar processed/ of error/ zoals de S3-bron doet.

Beide melden zich aan als een serviceaccount: credentials_file is de JSON-sleutel ervan. Laat deze leeg op Google Cloud (een VM, GKE of Cloud Run) om de serviceaccount die daar is gekoppeld te gebruiken. endpoint noemt een emulator (de Pub/Sub-emulator, fake-gcs-server), die geen referenties nodig heeft.

source:
  type: pubsub
  pubsub:
    project: hospital-integration
    subscription: adt-to-perfuse
    credentials_file: /etc/perfuse/gcp-key.json

10.19 Een postbus lezen (IMAP en POP3)

Een email-bron leest een postbus en zet wat hij vindt om in berichten: elke bijlage (take: attachments, de standaard, versmald door attachment_names-patronen), de tekst van de e-mail (take: body), of de hele e-mail (take: raw) voor een script toem om uit elkaar te halen. Laboratoria, beeldvormingscentra en kleine praktijken sturen nog steeds resultaten op deze manier.

Elke controle meldt zich aan, leest de ongelezen post van oud naar nieuw en meldt zich af. Via IMAP wordt een e-mail opgehaald zonder deze als gelezen te markeren, doorgegeven aan het kanaal en alleen verplaatst naar move_to (Verwerkt), gemarkeerd als gelezen (after_read: flag) of verwijderd als elk bericht ervan is geaccepteerd. E-mail die mislukt is of niet is opgehaald (een afzender buiten allowed_senders, geen bijlage die overeenkomt met attachment_names, groter dan max_message_size), wordt verplaatst naar error_folder (Fout) met de reden in het logboek. Beide mappen worden gemaakt als ze ontbreken. POP3 heeft geen mappen of vlaggen, dus het verwijdert: verwijderingen worden doorgevoerd bij het einde van de controle met QUIT, dus een sessie die afbreekt, verwijdert niets en een verwerkte e-mail kan opnieuw worden gelezen (nooit verloren). POP3-e-mail die niet is opgehaald, blijft op de server en wordt één keer gerapporteerd.

Aanmelden gebeurt met een wachtwoord (${MAIL_PASSWORD}; een app-wachtwoord voor Gmail) of OAuth 2.0 via SASL XOAUTH2, wat Microsoft 365 vereist (het heeft wachtwoord-aanmelden uitgeschakeld) en Gmail prefereert:

source:
  type: email
  email:
    host: outlook.office365.com        # imap.gmail.com, pop.gmail.com, or your server
    username: results-feed@hospital.example
    oauth:
      provider: microsoft              # microsoft, google or custom (with token_url)
      tenant: hospital.onmicrosoft.com
      client_id: 00000000-0000-0000-0000-000000000000
      client_secret: ${MAIL_CLIENT_SECRET}
    attachment_names: ["*.hl7"]
    allowed_senders: [lab.example, results@partner.example]

Met client_secret en geen refresh_token wordt Microsoft 365-app-only-toegang gebruikt (de client-credentials-grant, bereik https://outlook.office365.com/.default): een beheerder registreert de app, verleent deze IMAP.AccessAsApp en beperkt deze tot één postbus met een Exchange-serviceprincipal. Met een refresh_token (iemand's toestemming) wordt het gedelegeerde bereik IMAP.AccessAsUser.All of POP.AccessAsUser.All gebruikt en een geroteerd refresh-token wordt bewaard voor de levensduur van het proces. Gmail heeft een refresh_token nodig: Google biedt geen app-only-toegang tot een postbus.

allowed_senders accepteert adressen en domeinen. De From-regel van een e-mail kan worden vervalst, dus het houdt ongelukken en afwijkende post tegen, niet een aanvaller; een feed dat vertrouwd moet worden, hoort op Direct (S/MIME ondertekend), SFTP of een VPN. security is tls (993 of 995, standaard), starttls (143 of 110) of none, wat alleen is toegestaan voor localhost. Controles vinden plaats met een tussenpoos van minimaal 10 seconden (60 standaard), omdat e-maildiensten accounts blokkeren die sneller controleren.

Getest tegen GreenMail 2.1.3 (IMAPS, IMAP, POP3S en POP3: aanmelden geweigerd met een verkeerd wachtwoord, ophalen zonder als gelezen te markeren, VERPLAATSEN, vlag, verwijderen, een te grote e-mail geweigerd voordat deze wordt gelezen) en tegen Gmail's IMAP met een app-wachtwoord (een map maken, toevoegen, ophalen, VERPLAATSEN, verwijderen). OAuth is getest tegen een stand-in token-eindpunt, niet tegen Microsoft of Google.

10.20 AS2

AS2 (RFC 4130) is de manier waarop veel betalers, clearinghouses en leveranciers EDI uitwisselen: een HTTP POST waarvan het bericht is ondertekend met het certificaat van de afzender en versleuteld voor de ontvanger, beantwoord met een ontvangstbevestiging (een MDN) die een digest van het ontvangen bericht noemt. De S/MIME is dezelfde code die direct messaging gebruikt. Beide einden zijn op de kanaalbouwer: Handelspartners sturen ons EDI via AS2 als bron, Een handelspartner via AS2 als bestemming.

# receive: partners post here
source:
  type: as2
  as2:
    listen: ":4080"            # path /as2 by default
    id: HOSPITAL-AS2           # our AS2 identifier (AS2-To)
    cert_file: as2/ours.crt    # partners encrypt to this
    key_file: as2/ours.key     # and receipts are signed with it
    tls: { enabled: true, cert_file: tls.crt, key_file: tls.key }
    partners:
      - id: PAYER-AS2
        cert_file: as2/payer.crt
dataType: x12
# send
destinations:
  - name: payer
    type: as2
    as2:
      url: https://as2.payer.example/as2
      from: HOSPITAL-AS2
      to: PAYER-AS2
      cert_file: as2/ours.crt
      key_file: as2/ours.key
      partner_cert_file: as2/payer.crt
      file_name: "${control_id}.x12"

Ontvangen. Een bericht naar elk ander AS2-To, of van een afzender die niet in partners staat, wordt geweigerd met 403 en zonder ontvangstbevestiging. Een bericht van een partner moet worden ondertekend en versleuteld, tenzij de instelling allow_unsigned of allow_unencrypted is ingesteld. De payload wordt gedecodeerd, de handtekening wordt gecontroleerd tegen de certificaat van de partner (partners wisselen meestal zelf-ondertekende certificaten uit, wat prima is: het certificaat is het vertrouwen) en wordt overgedragen aan het kanaal zoals de berichtindeling aangeeft. De partner ontvangt de ontvangstbevestiging die hij heeft aangevraagd: in het antwoord of naar de URL van Receipt-Delivery-Option verzonden; ondertekend wanneer hij om een ondertekende heeft gevraagd. Een bericht dat mislukt, krijgt een ontvangstbevestiging met de reden (decryption-failed, authentication-failed, insufficient-message-security, unexpected-processing-error).

Verzenden. Elk bericht wordt ondertekend (SHA-256) en versleuteld (AES-256-CBC). Met receipt: sync, de standaard, wordt het pas als afgeleverd beschouwd wanneer de ontvangstbevestiging wordt geverifieerd tegen partner_cert_file, processed aangeeft en dezelfde digest (MIC) bevat als wat is verzonden; alles anders is een mislukte aflevering en wordt opnieuw geprobeerd. receipt: async vraagt om de ontvangstbevestiging op receipt_url, die een AS2-bron op deze server moet zijn die de partner vermeldt: het bericht wordt pas als afgeleverd beschouwd wanneer de partner het verzoek accepteert, en een ontvangstbevestiging die later niet overeenkomt, wordt als een fout gelogd. receipt: none vraagt om niets. unsigned, unencrypted en unsigned_receipt versoepelen elk onderdeel voor een overeenkomst die zegt dat het zo moet; username en password voegen HTTP-basistoken toe voor gateways die dit vereisen. Het content-type volgt de indeling van het kanaal (application/edi-x12 voor X12) tenzij content_type er een instelt.

Triple DES, AES-128 en AES-192 worden eveneens gelezen, evenals AES-256, omdat partners deze nog steeds verzenden, en ook de streaming BER (onbepaalde lengtes) die Java-gateways schrijven.

Compressie (RFC 5402). Een gecomprimeerd bericht wordt gelezen op welke manier het ook is gebouwd: gecomprimeerd voordat het wordt ondertekend of versleuteld, of een ondertekend bericht dat in zijn geheel is gecomprimeerd. De MIC van de ontvangstbevestiging volgt de RFC: over wat is ondertekend wanneer het ondertekend is, over de ongecomprimeerde inhoud wanneer het niet ondertekend is. Een bericht dat na decompressie groter zou worden dan tien keer de max_message_size van de bron, wordt geweigerd met decompression-failed, zodat een paar kilobytes niet kunnen claimen gigabytes aan geheugen. Een bestemming comprimeert met compress: true, voordat het wordt ondertekend en versleuteld, zoals de meeste gateways doen; vraag de partner eerst.

Een bericht dat twee keer wordt verzonden. Een partner die nooit onze ontvangstbevestiging heeft ontvangen, verstuurt het bericht opnieuw met hetzelfde Message-ID (RFC 4130 sectie 7.5). De bron onthoudt elk Message-ID van de partner voor duplicate_window (standaard 720h, 30 dagen; minstens een uur) en beantwoordt een herzending met een processed-ontvangstbevestiging zonder het opnieuw door te sturen. Het record wordt bewaard in de database, zodat een herstart het niet vergeet. Een bericht waarvan de verwerking is mislukt, wordt niet onthouden, zodat de herzending van de partner doorloopt. Kopieën die op hetzelfde moment aankomen, wachten op elkaar en alleen de eerste wordt doorgegeven. Als het record niet kan worden gelezen, wordt het bericht geweigerd met unexpected-processing-error en de partner herhaalt later, in plaats van het risico te lopen dat er een tweede kopie ontstaat. Een bericht zonder Message-ID kan niet worden herkend en wordt als zodanig gelogd.

Interoperabiliteit wordt getest tegen pyas2lib 1.4.3 in beide richtingen, met Triple DES en AES-256, gecomprimeerd en niet, inclusief ondertekende synchrone ontvangstbevestigingen.

10.21 OpenPGP

Verzekeraars, clearinghouses en overheidsinstellingen nemen en verzenden vaak alleen bestanden onder OpenPGP. Een pgp-blok op een bron opent wat aankomt; een op een bestemming beschermt wat vertrekt. Beide staan op de kanaalbouwer: Open PGP-berichten onder de bron, Versleutelen met OpenPGP op elke bestemming.

source:
  type: sftp
  sftp: { host: sftp.payer.example, user: hospital, key_file: keys/id_ed25519, dir: outbound }
  pgp:
    decrypt_with: keys/our-secret.asc      # our secret key, armored or binary
    passphrase: ${PGP_PASSPHRASE}
    verify_with: [keys/payer.asc]          # the senders' public keys
    require_signature: true
destinations:
  - name: claims
    type: sftp
    sftp: { host: sftp.payer.example, user: hospital, key_file: keys/id_ed25519, dir: inbound,
            file_name: "${date}-${control_id}.x12.pgp" }
    pgp:
      encrypt_to: [keys/payer.asc]
      sign_with: keys/our-secret.asc
      passphrase: ${PGP_PASSPHRASE}

Sleutelbestanden worden gelezen ten opzichte van het kanaalbestand en worden gelezen en ontgrendeld wanneer het kanaal wordt geladen: een ontbrekende sleutel of een verkeerd wachtwoord stopt het kanaal daar, niet bij het eerste bestand.

Berichten worden geschreven met AES-256 in het RFC 4880-formaat dat oudere ontvangers kunnen lezen, en het nieuwere RFC 9580-formaat wordt eveneens gelezen. De cryptografie is ProtonMail/go-crypto; Perfuse implementeert geen primitieve cryptografie. Interoperabiliteit wordt getest tegen GnuPG in beide richtingen: gpg decrypteert en verifieert wat Perfuse schrijft, en Perfuse opent en verifieert wat gpg schrijft.

10.22 Aflevering aan een ander kanaal

Een kanaalbestemming geeft het bericht door aan een ander kanaal met naam. Het ontvangende kanaal behandelt het als elke andere aankomst: het wordt opgenomen, gefilterd, getransformeerd en uitgezonden.

Dit is de ondersteunde manier om een keten te bouwen. Het is expres zichtbaar — twee kanalen, twee sets statistieken, twee vermeldingen in de berichtgeschiedenis — omdat een keten die verborgen is binnen één kanaal, een keten is die niemand kan bewaken.

Het bericht wordt overgedragen in het geheugen in plaats van over een netwerk, dus er is geen framing, geen bevestiging en geen time-out tussen de twee.

10.23 Wat gebeurt er als het proces wordt afgebroken

De vraag die iedereen die ooit een interface-engine heeft uitgevoerd, als eerste stelt, en het antwoord dat zelden wordt gegeven, omdat het eerlijke antwoord meestal beschamend is.

Het antwoord werd gegeven door het proces te doden met SIGKILL onderweg door een batch — wat een stroomstoring, een out-of-memory-kill en een hypervisor-reset allemaal lijken vanuit het proces — en te tellen wat overleefde tegenover wat was beloofd.

De eigenschap die getest wordt, is niet "niets gaat verloren". Dat is niet haalbaar en het claimen ervan zou een leugen zijn. Het is de smallere belofte waar een afzender daadwerkelijk op vertrouwt: een bericht dat positief is bevestigd, is een bericht dat is aangekomen.

Met ack.when: on_delivery, dat standaard is, wordt elke bestemming geschreven voordat de bevestiging wordt verstuurd, dus een AA is een verklaring over de bestemming in plaats van over een wachtrij. Een bericht dat wordt gedood voordat het bevestigd is, kan verloren gaan, en dat is correct: de afzender is nooit iets beloofd en zal het opnieuw verzenden.

10.23.1 Bevestigen bij levering

Vijf runs, gedood na 5, 25, 40, 75 en 110 berichten van 120.

BevestigdAanwezig downstream daarnaBevestigd maar ontbreekt
2552550

De belofte die bij elke doodspunt wordt gehouden, en niets werd gedupliceerd. Een duplicaat zou acceptabel zijn geweest en een verlies niet: een opnieuw verzonden A08 is een hinder voor ontvangers, en een labresultaat dat stilzwijgend nooit aankomt, is een gebeurtenis met betrekking tot patiëntveiligheid.

10.23.2 Bevestigen bij ontvangst

on_receipt antwoordt zodra het bericht in de wachtrij staat, voordat een bestemming is geschreven. Dit hoofdstuk heeft altijd gezegd dat een bevestigd bericht nog steeds verloren kan gaan op die manier. Hier is de omvang ervan.

Gedood naBevestigdAanwezig downstreamVerloren
5514
2525124
7575273
1101102108

Bijna alles in de lucht. De instelling is geen defect en er zijn feeds waarvoor het de juiste keuze is, maar het moet worden gekozen met de kennis dat een crash wat is bevestigd en nog niet is geschreven, weggooit, en dat dit bijna het gehele burst is.

Niets hersteld bij opstarten, omdat perfuse run geen duurzame opslag heeft. Een bestemming die geen berichten mag verliezen tijdens een storing, heeft queue.enabled nodig, wat de database nodig heeft die perfuse serve biedt — en perfuse run weigert nu een dergelijk kanaal in plaats van het te starten zonder wachtrij.

10.23.3 Een afzender die halfweg door een bericht sterft

De gevaarlijkste van deze fouten, omdat een afgekapt HL7-bericht meestal nog steeds parseert. De segmenten vóór de knip zijn compleet en goed gevormd, dus een ontvanger heeft geen manier om te weten dat PID en PV1 zijn aangekomen en de OBX-segmenten met de resultaten niet.

Een kader werd geopend, zes tiende van een bericht verzonden, en de verbinding werd gereset in plaats van gesloten. Het gedeeltelijke bericht werd niet afgeleverd, de luisteraar overleefde het, en een goed gevormd bericht dat onmiddellijk daarna werd verzonden, werd normaal geaccepteerd, dus het fragment werd niet meegenomen in het volgende bericht.

Het verbindinglogboek rapporteert nu het aantal bytes van een onvoltooide frame dat is verlaten, voor elke storingmodus in plaats van alleen een nette sluiting. Voordien logde een gecrashte verzender, een gedode proces en een losgetrokken kabel allemaal messages=0 en niets anders, wat geen onderscheid kan maken tussen een lege gezondheidscontrole en een labresultaat dat weggegooid werd negen tiende van de weg door.

10.23.4 Een volle schijf

Ruimte-uitputting wordt gedetecteerd en gelogd in plaats van ingeslikt. Twee dingen zijn het waard om te weten.

De afzender krijgt geen prompte afwijzing. De levering herhaalt zich op het gebruikelijke schema — één seconde, twee, vier, acht — en de negatieve bevestiging arriveert ongeveer vijftien seconden later. Een afzender wiens eigen time-out korter is dan dat, ziet een stilgestelde verbinding in plaats van een AE, en zal concluderen dat het netwerk de schuld is in plaats van de schijf.

En een volume dat nul vrije bytes rapporteert, kan nog steeds kleine toevoegingen accepteren voor een tijdje, omdat het toevoegen van een paar honderd bytes aan een bestand wiens laatste blok ruimte heeft, geen nieuwe toewijzing nodig heeft. De eerste schrijffout is later dan het moment waarop de schijf vol was.

10.23.5 Wat niet getest werd

Een bestemmingsmap die schrijfmachtiging verliest. Het kon niet worden geïnjecteerd met chmod: de motor houdt het uitvoerbestand open, en het wijzigen van de modus van een bestand heeft geen invloed op een descriptor die al tegen het bestand is geopend. Het goed testen ervan heeft het volume opnieuw gemount als alleen-lezen of verwijderd onder het proces nodig, wat niet is gedaan. Het wordt hier genoemd in plaats van weggelaten, omdat een lacune die niemand noemt, een lacune lijkt die niemand heeft gezocht.

11 Waarschuwingen

Niets buiten Perfuse zal u vertellen dat een feed is gestopt. De afzender wordt bevestigd en is tevreden; de ontvanger heeft geen manier om te weten dat een bericht is verzonden. Waarschuwingen zijn het enige dat tussen een kapotte interface en iemand die het weken later opmerkt, staat.

11.1 De soorten waarschuwingen

TypeWanneer geactiveerd
error-rateAls het aantal fouten een bepaald percentage van het verkeer overschrijdt.
queue-depthAls een wachtrij meer dan N berichten in behandeling heeft.
queue-ageAls het oudste bericht in de wachtrij ouder is dan een bepaalde periode.
queue-stuckAls een wachtrij helemaal niet leegloopt.
no-trafficAls er gedurende een vaste periode niets is aangekomen.
below-rhythmAls het verkeer ver onder het normale niveau ligt *op dit moment van de week*.
channel-downAls een kanaal dat zou moeten draaien, niet draait.
script-errorsAls een script fouten produceert.
rows-quarantinedAls een databasebron rijen apart zet.
slow-deliveryAls leveringen slagen, maar te lang duren.
contractAls een bericht het contract van het kanaal schendt.
phi-volumeAls een kanaal meerdere keren zijn normale tarief voor het uur overschrijdt.
phi-after-hoursAls een kanaal dat alleen overdag verkeer heeft, 's nachts verkeer heeft.
phi-new-destinationAls een kanaal levert aan een adres waar het nog nooit eerder naartoe heeft geleverd.
phi-bulk-readsAls één persoon meer dan N verschillende patiëntendossiers binnen één minuut leest.

De laatste vier houden toegang tot patiëntgegevens in de gaten en worden hieronder beschreven.

11.2 Stilte is het moeilijkst te detecteren

Een kanaal dat is gestopt met ontvangen, produceert geen fouten. Er is niets om te tellen. Dit is waarom no-traffic bestaat, en waarom het op zichzelf niet goed genoeg is.

no-traffic is een vaste drempel: alarmeer als er niets is aangekomen voor, zeg, twee uur. Op een feed die nooit stil valt, werkt dit. Op een klinische laboratoriumfeed is het nutteloos — de feed is stil elke nacht en het hele weekend, dus een drempel van twee uur activeert iemand om 1 uur 's nachts elke nacht, en een drempel die lang genoeg is om het weekend te overleven, zal een storing op dinsdagochtend niet opmerken tot dinsdagmiddag.

Er is geen enkel nummer dat beide is. Dit is geen afstellingprobleem; het is dat de vraag "is deze feed gestopt" niet kan worden beantwoord door een constante wanneer de feed normaal varieert met een factor van honderd over de week.

11.3 Ritme-gevoelige detectie

below-rhythm vergelijkt de huidige verkeer met wat dit kanaal normaal doet in dit uur van deze dag van de week.

Perfuse leert elke week van elk kanaal uit zijn eigen opgenomen geschiedenis: 168 uurlijkse buckets, met maandag als eerste, zodat een werkweek aaneengesloten is. Voor elke bucket houdt het een mediaan, een laag en een hoog, een vloer en hoeveel observaties het is gebaseerd op.

De drempel is een deel van normaal, met een standaardwaarde van 0.8 (80 procent in de console) — alarmeer wanneer het verkeer daalt onder vier vijfde van wat normaal is voor dit uur.

11.3.1 Mediaan, niet gemiddelde

Een enkele backlog-flush van veertigduizend berichten tegen een normaal van driehonderd verplaatst een gemiddelde ver genoeg dat de feed volledig stil kan vallen zonder ooit onder de drempel te komen. De mediaan wordt niet beïnvloed door één buitengewoon uur, wat precies de eigenschap is die nodig is.

11.3.2 De vloer is een percentiel, niet het minimum

Of een kanaalritme betrouwbaar genoeg is om te alarmeerden, wordt beslist door zijn ondergrens, niet zijn bovengrens. Een tekortaan-alarm activeert wanneer het verkeer *laag* is, dus alleen de ondergrens kan zeggen of het valse positieven zal produceren. Een vroege versie van dit vergelijking vergeleek de bovengrens met de mediaan en kreeg het verkeerd in beide richtingen: het diskwalificeerde een perfect stabiel kanaal voor een maand na één backlog, en het passeerde een echt onregelmatig kanaal dat schommelde tussen twee en negenhonderd berichten in hetzelfde uur, omdat zijn bovengrens slechts drie keer zijn mediaan was.

De vloer is het twintigste percentiel, in plaats van het minimum, omdat het minimum naar nul wordt getrokken door één enkele bankvakantie. En het percentiel wordt niet geïnterpoleerd — elk nummer in een alarm om twee uur 's nachts moet een telling zijn die de feed daadwerkelijk heeft geproduceerd, niet een gemiddelde van twee tellingen die het niet heeft gedaan.

11.3.3 Het zal zeggen wanneer het niet kan zeggen

Een kanaal met helemaal geen geschiedenis wordt volledig weggelaten in plaats van behandeld als een dat is gestopt. Een nieuw kanaal mag er niet uitzien als een kapot kanaal.

Waar de geschiedenis te dun of te onregelmatig is om een oordeel te ondersteunen, weigert de regel om te activeren in plaats van te gokken. "Ik kan eerlijk gezegd niet zeggen" is een eersteklasantwoord hier, en het is de voorkeur boven een alarm dat iets vaker correct is dan toeval.

Afwezige uren binnen het leerwindow worden opgenomen als echte nullen, niet als ontbrekende gegevens. De helft van het signaal in een klinische feed is *wanneer het legitiem stil is*, en het behandelen van die uren als onbekend zou het weggooien.

11.4 Alarmen instellen

Vanuit het interface, onder Alerts, per kanaal of voor alle kanalen. Elke regel heeft een type, een drempel en waar de alert naartoe moet worden gestuurd. De regels worden opgeslagen in alerts.yaml naast de database (of het bestand -alerts dat is opgegeven) en worden onmiddellijk van kracht; totdat de eerste opslag de ingebouwde regels van toepassing zijn. Het bestand kan ook handmatig worden bewerkt: de wijziging wordt binnen dertig seconden opgepikt en een bestand dat niet langer kan worden geladen, wordt in het logboek gemeld en de regels die van kracht zijn, worden behouden.

Het is de moeite waard om dit te doen voordat een feed live gaat, in plaats van na het eerste incident. De specifieke set die het waard is om op elke klinische feed te hebben:

  1. below-rhythm — de feed is stil geworden wanneer hij dat niet zou moeten zijn.
  2. error-rate — berichten arriveren en mislukken.
  3. queue-age — iets is vastgelopen in plaats van alleen maar druk.
  4. channel-down — het kanaal draait helemaal niet.

De eerste is degene die de storing vangt die niemand anders zal melden.

11.5 Toegang tot patiëntgegevens in de gaten houden

Een inbreuk meldt zich zelden zelf. Het lijkt op een feed die meer verkeer heeft dan normaal, verkeer om drie uur 's nachts op een kanaal dat alleen kantooruren werkt, een bestemming die niemand heeft ingesteld, of één persoon die patiënt na patiënt opent. Perfuse houdt deze vier in de gaten, standaard ingeschakeld (serve -watch-access=false schakelt het uit), en rapporteert wat het ziet via de bovenstaande alertregels, zodat het is geconfigureerd, bevestigd en afgeleverd zoals elke andere alert.

Niets wordt beoordeeld voor een kanaal totdat het 200 berichten heeft vervoerd, omdat 'ongebruikelijk' niets betekent zonder een patroon. Het patroon wordt geleerd van de laatste veertien dagen van de berichtenopslag wanneer de server start, dus een herstart maakt elk kanaal niet opnieuw. Alles wat wordt gezien, wordt gedurende vijftien minuten vastgehouden, waarna de alert zichzelf wiselt.

Het houdt alleen in de gaten en rapporteert. Het houdt nooit een bericht tegen of weigert een leesactie: dit zijn heuristieken, en een feed die wordt gestopt omdat een vermoeden verkeerd is, is een klinisch probleem. Elke alert zegt wat er is gezien en wat het onschuldig kan zijn, omdat de meeste onschuldig zullen zijn.

Beheerders zien wat de monitor heeft geleerd op het scherm Alerts, onder Toegang tot patiëntgegevens in de gaten houden: elk kanaalpatroon (nog steeds leren, alleen overdag of zowel overdag als 's nachts), hoeveel bestemmingen het kent en alles wat in de afgelopen vijftien minuten is gezien, inclusief wat onder de drempel van een regel valt.

11.6 Waar alarmen naartoe gaan

Waarschuwingen kunnen als JSON naar een webhook worden verzonden (-alert-webhook: Slack, Teams, Mattermost, PagerDuty, Alertmanager of alles wat een POST accepteert), als SNMPv2-valstrikken naar SNMP-managers worden verzonden (-snmp-traps, zie SNMP), of naar het logboek worden geschreven voor een collector om op te halen. Er is geen e-maillevering van zichzelf: wijs de webhook naar een relay als waarschuwingen per e-mail moeten aankomen.

Een alarm dat alleen naar een logboek wordt geschreven dat niemand leest, is geen alarm. Als Perfuse het enige is dat een gestopte feed zal opmerken, moet het alarm een persoon bereiken.

12 De Berichtenopslag

Elk bericht dat Perfuse ontvangt, wordt opgenomen, zoals ontvangen, voordat er iets aan wordt gewijzigd. Ook wordt opgenomen wat naar elk doel is verzonden en wat er met het bericht is gebeurd. De opslag is een SQLite-bestand dat wordt opgegeven door -db.

12.1 Wat wordt bewaard

Per bericht: de ruwe bytes zoals ze zijn aangekomen, wanneer ze zijn aangekomen, welk kanaal, het geparseerde berichttype en triggergebeurtenis, en het filterresultaat.

Per doel per bericht: de bytes die zijn verzonden, het resultaat, de tijd die nodig was, en eventuele fouten of negatieve bevestigingen die zijn ontvangen.

Dit is de vorm die een onderzoek nodig heeft. "Wat hebben ze ons gestuurd", "wat hebben we hun gestuurd" en "wat hebben ze daarover gezegd" zijn drie verschillende vragen en elk van hen wordt gesteld.

12.2 Zoeken

Per kanaal, per tijdsbereik, per resultaat, per berichttype en triggergebeurtenis, en per veldwaarde.

Veldzoek werkt op het geparseerde bericht, dus zoeken naar een recordnummer vindt het overal in het bericht waar dat veld leeft, in plaats van overeen te komen met de cijfers ergens in de tekst. Een tekstzoekopdracht voor 12345 in een bericht met een hoeveelheid van 12345 vindt een bericht dat niets te maken heeft met de patiënt die u zoekt.

12.3 Afspelen en opnieuw verwerken

Omdat het origineel wordt bewaard, kan een bericht opnieuw worden verwerkt met de huidige configuratie.

Trace neemt een opgenomen bericht en toont wat het kanaal ermee zou doen nu, zonder iets te verzenden. Hierover wordt meer verteld in debugging.

Opnieuw verwerken voert het bericht daadwerkelijk opnieuw uit, inclusief levering. Dit is wat een batch berichten repareert die zijn mislukt omdat een doel verkeerd was geconfigureerd: corrigeer de configuratie, selecteer de getroffen berichten, verwerk opnieuw.

Opnieuw verwerken levert opnieuw. Als de berichten de eerste keer gedeeltelijk zijn geslaagd, zal opnieuw verwerken duplicaten produceren bij de doelen die ze al hadden. Perfuse houdt bij welke doelen zijn geslaagd, dus opnieuw verwerken kan worden beperkt tot degenen die zijn mislukt — doe dat in plaats van alles opnieuw te verwerken, tenzij het ontvangende systeem dupliceert op berichtcontrole-ID.

12.4 Veroudering

Een trace van een oud bericht tegen de huidige configuratie beantwoordt een hypothetische vraag: wat *zou* er nu gebeuren. Dat is meestal wat u wilt, maar niet altijd — als u onderzoekt wat er verkeerd is gegaan vorige dinsdag, kan het kanaal sindsdien zijn gewijzigd.

Perfuse detecteert dit en zegt het. Een trace van een bericht dat is aangekomen voordat het kanaal voor het laatst is bewerkt, wordt gemarkeerd als zodanig, zodat het antwoord niet wordt verward met een reconstructie van wat er daadwerkelijk is gebeurd.

12.5 Bewaring

De opslag groeit. cleanup.periodDays controleert hoe lang berichten worden bewaard.

Twee dingen om te overwegen. Klinische berichten kunnen onder bewaarvereisten vallen die langer zijn dan alles wat u om operationele redenen zou kiezen, en de opslag is niet het systeem van record — het ontvangende systeem is dat. De kopie van Perfuse bestaat om te diagnosticeren en opnieuw te verwerken, en beide behoeften nemen scherp af na een paar weken.

Bewaring beslist ook hoeveel geschiedenis de ritmeleerder heeft om mee te werken. Zie alerting: een bewaarvenster dat korter is dan een paar weken laat het onmogelijk om een stille zondag te onderscheiden van een gestopte feed.

12.6 De opslag bevat klinische gegevens

Dit is het deel van Perfuse dat patiëntinformatie bevat, en het moet als zodanig worden behandeld: op versleutelde opslag, als klinische gegevens geback-upt, en toegangsbeveiligd. Zie security.

De gegenereerde testberichten die in testing worden beschreven, bestaan deels zodat deze gegevens niet uit de omgeving hoeven te worden verwijderd om een probleem elders te reproduceren.

13 Debugging

De vraag is bijna altijd hetzelfde: dit bericht kwam binnen, er ging iets mis, waar is het veranderd? Perfuse beantwoordt deze vraag door een opgenomen bericht af te spelen via de huidige configuratie en elke stap te laten zien.

Er wordt niets verstuurd tijdens het traceren. Het kanaal blijft ongewijzigd draaien en er is geen opnieuw implementeren nodig.

13.1 Traceren van een bericht

Selecteer een opgenomen bericht en traceer het. Het resultaat toont, in volgorde:

13.2 Stap voor stap

De stap-voor-stap-weergave voert elke transformatie uit en maakt een momentopname van het hele bericht na afloop. Een genummerde rail van stappen, gekleurd naar wat er gebeurde, en het bericht zoals het op elk punt stond.

Het hele bericht in plaats van alleen de verandering, omdat de verandering vaak niet de plek is waar het probleem zit — een stap die correct het veld modificieerde waarop het gericht was, op een bericht waarop een eerdere stap al het verkeerde ding had geplaatst, ziet er perfect correct uit in isolatie.

13.3 Vier resultaten en het onderscheid dat ertoe doet

ResultaatBetekenis
changedDe stap werd uitgevoerd en het bericht werd gewijzigd.
no-effectDe stap werd uitgevoerd en het bericht is ongewijzigd.
skippedDe when-conditie van de stap was onwaar, dus werd deze niet uitgevoerd.
failedDe stap mislukte.

no-effect en skipped worden afzonderlijk gerapporteerd, en dit is het punt van deze hele functie.

Van buitenaf zijn ze identiek: het bericht is hetzelfde erna. Ze betekenen tegenovergestelde dingen. skipped betekent dat de conditie zoals geschreven werkte en dit bericht niet een was waarop het van toepassing was — meestal correct. no-effect betekent dat de stap werd uitgevoerd en niets te doen vond, wat meestal betekent dat het op een veld gericht is dat er niet is.

Een motor die beide als 'niets gebeurde' rapporteert, laat je niet zien dat je een werkende conditionele van een kapot pad kunt onderscheiden, en dat is de meest voorkomende transformatiefout die er is.

Een stap die no-effect rapporteert voor elk bericht is bijna altijd een verkeerd pad. De stap-voor-stap-koptekst telt hoeveel stappen niets vonden, wat de snelste manier is om het te vinden: een kanaal met drie stappen en drie no-effect-resultaten transformeert niets helemaal.

13.4 Testen van een wijziging voordat deze wordt opgeslagen

De builder kan een kandidaat-configuratie uitvoeren tegen opgenomen verkeer en rapporteren wat zou verschillen. Dit is de veiligste manier om een live-kanaal te wijzigen: maak de bewerking, zie wat het doet met de laatste paar honderd echte berichten, en sla het dan op.

Het is ook de manier om te ontdekken dat een wijziging die duidelijk correct lijkt, berichten beïnvloedt die je niet had bedacht — een stap die is voorwaardelijk voor één triggergebeurtenis, op een feed die blijkt vier te dragen.

13.5 Wat traceren je niet kan vertellen

Het voert de huidige configuratie uit. Als het kanaal is bewerkt sinds het bericht binnenkwam, is de trace een hypothetische in plaats van een reconstructie, en Perfuse markeert het als zodanig in plaats van het onderscheid stilzwijgend voorbij te laten gaan.

Het oefent ook geen transport uit. Een trace toont wat zou worden verstuurd, niet of de bestemming het zou accepteren — een bericht dat correct is en een bestemming die verbindingen weigert, produceren een schone trace en een mislukte levering. Die zijn zichtbaar in het leveringsrecord in plaats daarvan.

13.6 Scripts

Een script is één ondoorzichtige stap in de trace. Perfuse kan laten zien wat erin ging en wat eruit kwam, en kan niet laten zien wat er tussenin gebeurde of welke velden werden gelezen.

Dit is de concrete kosten van het gebruik van een script in plaats van declaratieve stappen, en het is de moeite waard om te overwegen bij het kiezen. Zie transformation.

14 Testen

Standaardadvies voor het testen van een interface is om voorbeeldberichten te maken die uw eigen omgeving weerspiegelen — uw laboratoriumcodes, uw casemix, uw verzendergewoonten — en om de patiëntgegevens eruit te halen met de hand. Dat is langzaam, en het onvolledig doen is het normale resultaat.

Perfuse biedt drie dingen in plaats daarvan: gegenereerd verkeer dat de vorm van een feed volgt zonder de inhoud, een kanaal voorgesteld op basis van een voorbeeld dat iemand u heeft gestuurd, en een vergelijking met de motor die u vervangt.

14.1 Gegenereerd testverkeer

Als een kanaal berichten heeft verwerkt, kan Perfuse meer berichten zoals deze produceren.

Wat betrouwbaar is:

Wat niet betrouwbaar is en dit wordt expliciet vermeld in plaats van impliciet: klinische coherentie. Een gegenereerde patiënt heeft een ongerelateerd recordnummer, een naam-achtige tekenreeks en een diagnose met geen relatie tot de observatie. Deze berichten oefenen een interface. Ze vormen geen klinische testset en kunnen niet worden gebruikt om klinische logica te valideren.

14.1.1 Waarom het geen echte gegevens bevat

Het argument is structureel in plaats van een bewering over inspanning. De enige invoer van de generator is het verkeersprofiel van het kanaal, en een profiel bevat invulpercentages, vormen, lengtes, herhalingstellingen en segmentfrequenties. Het bevat geen waarden.

De enige uitzondering zijn velden met codetabellen, en een code identificeert niemand.

Dit is een sterker garantie dan het anoniem maken van echte berichten, wat een proces is dat onvolledig kan worden gedaan en meestal wordt gedaan. Hier is er geen pad waarlangs een naam de uitvoer kan bereiken, omdat de naam nooit in de invoer zat.

Ieder gegenereerd bericht wordt geparsed voordat het wordt geretourneerd — een niet-parsbaar corpus zou iemand op zoek doen gaan naar een bug in hun interface die eigenlijk een bug in de generator is — en ieder bericht wordt gemarkeerd met T in MSH-11, met een opzettelijk synthetische verzendende toepassing en faciliteit.

Een testbericht dat niet als zodanig is gemarkeerd, zal uiteindelijk in een productiesysteem worden gevonden door iemand die geen manier heeft om te weten dat het niet echt was. De T en de synthetische verzender zijn niet cosmetisch.

14.2 Een kanaal opbouwen vanuit een voorbeeld

Plak het bericht dat een laboratorium, ziekenhuis of leverancier je heeft gemaild en Perfuse stelt een kanaal voor. Niets hoeft te draaien voordat.

Het behandelt wat mensen daadwerkelijk plakken: meerdere berichten in één blok, elke lijnafsluiting, MLLP-framing die de kopie heeft overleefd, en de deknotitie boven het bericht. Weigeren van een voorbeeld omdat het met Windows-lijnafsluitingen is aangekomen, zou een belemmering zijn in plaats van een controle.

14.2.1 Drie lijsten

Het voorstel komt met wat het voorbeeld laat zien, wat is geraden, en wat het voorbeeld niet kan vertellen — drie afzonderlijke lijsten, gelijk gewogen in de interface.

Ze zijn afzonderlijk omdat een lezer die niet kan zien welke hetwelk is, alles moet verifiëren of alles moet vertrouwen, en beide zijn erger dan weten waar je moet zoeken.

Vanuit één bericht worden de limieten specifiek genoemd in plaats van algemeen: welke velden optioneel zijn, welke segmenten herhalen, welke codes bestaan buiten degenen die hier zijn, of de verzender ooit een andere triggergebeurtenis verstuurt. Een algemene waarschuwing is een waarschuwing die mensen snel doorlezen.

Vertrouwen is een woord — laag, matig, redelijk — nooit een percentage. Een percentage impliceert een berekening, en dit is een oordeel over hoeveel voorbeelden er zijn.

Z-segmenten worden bij naam genoemd, omdat een lokaal segment het ding is dat geen specificatie vermeldt en de meest voorkomende reden is dat een kanaal dat vanuit een standaardsjabloon is gebouwd, niet werkt.

14.2.2 De scheidingswaarschuwing

Als de veldscheidingsteken van het voorbeeld niet het gebruikelijke | is, verschijnt dat eerst, en het vertrouwen daalt naar laag.

De reden is een echte stille fout. HL7 neemt zijn veldscheidingsteken uit het bericht zelf, dus een voorbeeld waarvan de pijpen zijn vervangen door typografische look-alikes — wat een tekstverwerker doet — parseert perfect in velden die allemaal verkeerd zijn. Niets fout gaat ergens.

Weigeren van een dergelijk voorbeeld zou verkeerd zijn, omdat een verzender legitiem een andere scheidingsteken kan gebruiken. Dus wordt het gemarkeerd, het teken wordt genoemd, en het wordt aanbevolen om een gewone tekstbijlage te vragen.

14.3 Vergelijken met de oude engine

Voordat een live-feed wordt verplaatst, is de vraag of Perfuse dezelfde uitvoer produceert als hetgeen dat al jaren draait. Geen enkele hoeveelheid ontwerpkwaliteit beantwoordt dat. Zie migration.

14.4 Verificatie tegen de echte omgeving, in containers

Drie controles worden uitgevoerd tegen echte implementaties in plaats van tegen Perfuse's eigen idee van een protocol. Ze worden buiten make check uitgevoerd omdat ze een container-runtime nodig hebben en een controle die Docker nodig heeft, is een controle die mensen stoppen met uitvoeren.

scripts/interop-up.sh start allemaal en print wat elk ervan ontgrendelt.

ContainerControlesWat het vond
Keycloak 26web/e2e-saml/, en internal/saml fixturesEen defect. De canonieke vorm van een handtekening die het dekt, werd berekend met namespace-prefixen die werden weggegooid, zodat geen enkele echte identiteitsprovider ooit iemand had kunnen inloggen
Microsoft Entrainternal/saml live tests en fixturesTwee defecten, beide in wat de protocol omgeeft. Een account werd aangemaakt onder Entra's ondoorzichtige NameID, omdat de logica voor leesbare namen een e-mailclaim wilde en Entra geen enkele stuurt. En een SAML-account werd opgeslagen als OIDC, omdat de opslag de protocol afleidde van een issuer die identiek lijkt voor beide
HAPI FHIRgo test ./internal/engine/ -run HAPIEen defect. Een niet-toegewezen autoriteit produceerde een identificatiesysteem dat een OID aankondigde en een woord droeg, dat HAPI zonder klagen accepteerde
ActiveMQgo test ./internal/engine/ -run RealBrokerCorrect, inclusief het geval met null-byte framing. Beweerd via de beheerinterface van de broker zelf in plaats van via een functie die nil retourneert
nginx, clientcertificatengo test ./internal/engine/ -run ClientCertificateCorrect
Orthanc (een echte PACS)go test ./internal/engine/ -run RealPACSCorrect. Een C-STORE arriveert en de patiëntnaam, identifier, studiedatum, modaliteit en SOP-klasse overleven allemaal
PostgreSQLgo test ./internal/engine/ -run RealPostgresCorrect, en het heeft een betere fout opgeleverd: een statement in de verkeerde dialectplaatsaanduidingen wordt nu geweigerd wanneer het wordt opgeslagen in plaats van een syntaxisfout te worden op de server wanneer een bericht arriveert
OpenSSH sftp-servergo test ./internal/engine/ -run OpenSSHServerCorrect. De bestaande SFTP-tests gebruiken dezelfde Go-bibliotheek aan beide kanten; OpenSSH is een andere implementatie en degene aan het einde van bijna elke echte feed
Mirth 4.5.2go test ./internal/mirth/ -run RealMirthCorrect nu. Het enige fixture was vroeger handgeschreven en Mirth laadde het niet; scripts/mirth-author-channel.sh laat Mirth een kanaal maken, en Perfuse leest het

Elk van hen slaat over in plaats van faalt wanneer de container ontbreekt, dus make check slaagt op een machine zonder Docker.

Waarom dit apart is van de rest van de suite. Elke andere test van deze functies had beide helften hier geschreven: een document dat deze codebase ondertekende, gelezen door de code die het ondertekende. Dat is overeenstemming met zichzelf, en het is minder waard dan het lijkt.

De SAML-canoniseerder is het geval dat het punt bewijst. Het droeg duizend regels tests, vijf ervan specifiek over canonisatie, en allemaal passeerden terwijl geen enkele echte identiteitsprovider ooit iemand had kunnen inloggen — de canonieke vorm die een handtekening dekt, werd berekend met namespace-prefixen die werden weggegooid, en de enige manier om dat te vinden was om het een document te geven dat Perfuse niet had geschreven.

Twee van de acht controles vonden defecten rechtstreeks, en een derde leidde tot een echte verbetering. Drie vonden niets verkeerds. Die verhouding is het argument voor het behouden van allemaal: een controle die slaagt, heeft je iets verteld dat je anders niet had kunnen weten, en er was geen manier om van tevoren te weten welke het zouden zijn.

Een patroon dat de moeite waard is om te noemen, omdat het in beide defecten verscheen: acceptatie is niet verificatie. HAPI accepteerde het defecte identificatiesysteem en sloeg het op; het defect verscheen pas bij het lezen van de resource terug. Een ontvanger die iets tolereert, is geen bewijs dat het correct is, alleen dat deze ontvanger soepel was.

Twee vastgelegde beweringen zijn gecommiteerd, op internal/saml/testdata/keycloak-assertion.xml en entra-response.xml, met tests over beide — zodat die specifieke regressie wordt gevangen zonder een container.

Beide zijn nodig in plaats van dat een van de twee overbodig is. Keycloak voegt voorvoegsels toe aan zijn bewering en handtekening, Entra doet dat niet, en dat zijn de twee tegenovergestelde gevallen in canonisatie — wat precies is waar het defect was. Een test beweert dat elk document nog steeds zijn eigen geval dekt, omdat een vervangende vastlegging die toevallig voorvoegsels had, stilzwijgend de dekking zou halveren zonder iets te falen. De algemene les generaliseert niet zo goedkoop: voor alles anders is de container de controle.

14.5 Diagnose van een test die één keer faalt en nooit meer

Een test die faalt in een volledige run en zestien keer alleen slaagt, is geen willekeurige test. Het is een test die iets deelt met de run, en de manier om erachter te komen wat dat is, is om de gedeelde zaak te meten in plaats van de test.

Twee instrumenten bestaan hiervoor, en beide zijn bedoeld om naast een volledige suite te worden uitgevoerd:

./scripts/e2e-watchdog.sh /tmp/watchdog.log     # the HTTP server and the shared session
./scripts/e2e-mllp-probe.py /tmp/mllp.log       # the fixture channel's listener

Elk ontdekt de poorten van de run van het state-bestand van de setup en neemt elke 500 milliseconden een monster totdat de server afsluit. Ze loggen elk monster in plaats van alleen de fouten, wat het nuttig maakt: een piek verschijnt in een run waar niets faalt, dus een fout die één keer in drie runs verschijnt, wordt meetbaar in elke run.

Stel PERFUSE_E2E_KEEP=1 in om de tijdelijke directory te behouden, die de database bevat zoals deze is achtergelaten en het serverlog voor de hele run. Het serverlog is meestal het antwoord. In een onderzocht geval werd een kanaal stopgezet en de listener opnieuw gebonden 421 milliseconden later, en de ene geweigerde verbinding van de sonde viel binnen dat venster.

Lees de trace in plaats van error-context.md, die meer dan eens leeg was op momenten waarop de trace de echte boodschap bevatte.

Kopieer de artefacten voordat u iets opnieuw uitvoert. Een geslaagde run wist test-results, dus de trace van de fout die u onderzoekt, verdwijnt op het moment dat u deze probeert te reproduceren. Als deze eenmaal verloren is gegaan, kan de vraag die deze had beantwoord, niet meer worden beantwoord.

Stop de interop-containers eerst. Stop ze voordat u een volledige browser-run uitvoert en start ze opnieuw met ./scripts/interop-up.sh als u ze nog nodig heeft.

Acht containers nemen ongeveer 9,8 GB aan geheugen in beslag en op een machine met niet veel meer dan dat, is er te weinig over voor de processen van Chromium, node en de Go-toolchain samen. Wat het produceert, is geen out-of-memory-fout, maar een renderer die niet meer wordt gepland: een opgenomen trace toont een gap van 60,2 seconden zonder enkele frames, tijdens welke Playwright wachtte tot een knop 'zichtbaar, ingeschakeld en stabiel' werd en geen twee opeenvolgende animatieframes kon vergelijken. De server was de hele tijd gezond, de langzaamste aanvraag in de hele run was 154 milliseconden.

Die fout lijkt op een defect in welke test toevallig werd uitgevoerd. Het is de moeite waard om de vorm ervan te kennen: elke aanvraag snel, de pagina visueel bevroren, de retry-lus bereikt nooit een tweede iteratie en het hele ding slaagt in isolatie.

Alleen één run tegelijk. De suite deelt één server, één ingelogde sessie in web/e2e/.auth/admin.json en één statusbestand dat de naam van het serverproces aangeeft. Niets daarvan is per run, dus een tweede run die start terwijl de eerste nog bezig is, overschrijft het statusbestand en welke afbraak als eerste wordt voltooid, doodt de server van de andere run en wist de sessie.

What that looks like is nothing like the cause. It produced a run of 279 failures whose first message was ENOENT: no such file or directory, open './e2e/.auth/admin.json', a run that stopped early reporting 217 passed, and two tests failing with bind: address already in use — none of which suggest two runs fighting. The suite now takes a lock and refuses to start, naming the process that holds it. A lock left by an interrupted run is taken over rather than blocking for ever, because a safety measure that wedges the suite is one somebody deletes along with the safety.

Een verwant valkuil, die nu is opgelost: twee specs noemden hun luisterpoorten rechtstreeks, dus een server die door een onderbroken run was achtergelaten, maakte hen falen op iets waar ze niets mee te maken hadden. Poorten worden nu aan het besturingssysteem gevraagd.

Beantwoord geen van deze met retries. Een test die bij de tweede poging slaagt, heeft een echte race gevonden en verborgen, en playwright.config.ts stelt retries: 0 in om die reden.

Een waarschuwing: bemonstering elke 100 milliseconden zorgde voor twintig processen per seconde, strekte een run met de helft en faalde twee tests op time-outs die niets mis hadden. Een instrument dat verandert wat het meet, produceert bevindingen over zichzelf.

14.6 Wat nog steeds echte infrastructuur nodig heeft

Verschillende onderdelen van Perfuse zijn geïmplementeerd en nooit getest tegen de echte zaak. Ze worden hier opgesomd in plaats van te worden ontdekt:

De functies in dit hoofdstuk en het volgende bestaan zodat u uw eigen bewijs kunt verzamelen in plaats van iemands woord te nemen.

14.7 Gemeten tegen openbare conformatiecorpora

Een testsuite waarvan de fixtures hier zijn geschreven, bewijst overeenstemming met zichzelf. Dit zijn gegevens van andere mensen.

14.7.1 FHIR R4, de voorbeelden van de specificatie

Alle 2.912 voorbeeldbestanden die zijn gepubliceerd met de FHIR R4-specificatie — elk voorbeeld dat de auteurs van de standaard hebben geschreven.

ResultaatTelling
Resources gevalideerd met geen bevindingen13.723
Resources gemeld als ongeldig0
Bestanden geweigerd als ongeïmplementeerd resourcetype753
Bundle-invoer overgeslagen als ongeïmplementeerd type1.348

Geen enkele resource werd onjuist gevalideerd. Elke fout is een expliciete weigering die het type noemt dat het niet kan lezen — 672 ValueSet, 80 ConceptMap en één Parameters. Een validator die stilzwijgend doorgeeft wat hij niet begrijpt, is erger dan een die het zegt.

Het corpus vond een defect, wat de reden is voor het uitvoeren ervan. Valideren van een bundel gaf "Bundelvalidatie vanuit een bestand wordt nog niet ondersteund" en zette door. Dat was vals in beide richtingen: bundles waarvan de entries toevallig types waren die de parser kon bevatten, werden al gevalideerd, en een bundel die echt ongeldig was, produceerde dezelfde regel, telde niets en verliet nul — inclusief onder -strict, dat bestaat zodat dit een build kan blokkeren. Tweeënveertig van de specificatie's eigen bundles werden overgeslagen.

Bundles worden nu gevalideerd entry voor entry, met drie resultaten die uit elkaar worden gehouden: een entry die verkeerd is, faalt en noemt het veld, een entry van een type dat deze build niet kan lezen, wordt geteld als overgeslagen en gerapporteerd, en een bundel die geen resource-bodies bevat, is geen van beide. Hetzelfde corpus ging van 2.100 resources gecontroleerd naar 13.723.

14.7.2 HL7 v2, het HAPI-testcorpus

De berichtfixtures van HAPI, de referentie Java HL7 v2-implementatie — expres lastig materiaal, inclusief uuencoded payloads, ontsnapte delimiters en herhalende groepen.

59 berichten, 59 geparsed, niets geweigerd. Zeven berichttypen in een corpus dat elk systeem zou beschrijven als één ding, wat het doel is waarvoor perfuse profile bestaat om dit te maken.

14.7.3 Wat niet is uitgevoerd

DICOM tegen een openbare conformiteitstest en X12 tegen een gepubliceerde corpus. Geen van beide is gedaan en geen van beide zou moeten worden afgeleid van de twee bovenstaande.

15 Migratie van Mirth

Twee dingen zijn nodig om een werkende engine te vervangen: de kanalen moeten overkomen en iemand moet kunnen aantonen dat de vervanging dezelfde output produceert. Perfuse doet het eerste door de eigen exports van Mirth te importeren en het tweede door de twee engines op uw eigen verkeer te vergelijken.

Alles in dit hoofdstuk is eveneens van toepassing op de Open Integration Engine en BridgeLink. Mirth Connect hield op open source te zijn bij 4.6 in maart 2025; OIE (gehost door de Eclipse Foundation) en BridgeLink (Innovar Healthcare) zijn de forks die de open-source-lijn voortzetten en beide schrijven dezelfde exportformaten. De importer wordt getest tegen alle drie, hieronder.

15.1 Kanalen importeren

Perfuse leest elke export die deze engines schrijven:

ExportVan de AdministratorWat overkomt
Een kanaalExport ChannelHet kanaal
Een kanaalgroepExport GroupElk kanaal erin, elk met de groep
Code-sjablonenExport Code TemplatesElk bibliotheek als één scriptbestand
Een server-backupBackup Config, of GET /api/server/configurationAlles hierboven tegelijk

Wijs perfuse translate naar een van deze, of laat er een vallen op Administer → Migrate:

perfuse translate -o ./channels server-backup.xml

Een codebibliotheek wordt lib/<library>.js naast de kanalen, en elk kanaal waarvoor Mirth de bibliotheek heeft ingeschakeld, krijgt scripts.include: [lib/<library>.js] — dus een transformatie die een sitefunctie zoals formatMRN() aanroept, vindt deze nog steeds. Een kanaal waarvoor de bibliotheek niet is ingeschakeld, bevat deze niet, omdat de scripts deze in Mirth niet konden zien. Slepen-en-neerzetten-fragmenten worden weggelaten: Mirth plakt deze alleen handmatig in een stap, dus ze zijn geen code die zelfstandig wordt uitgevoerd. In de browser worden de bibliotheken die een kanaal bevat, eerst opgeslagen wanneer een kanaal wordt geïmporteerd.

Een Channel Writer noemt het kanaal waarop het levert met zijn id. In een groep of een back-up staat het doel in hetzelfde document, zodat het een channel-bestemming wordt die dat kanaal noemt; vanuit een single-channel-export wordt het voor u gerapporteerd om in te vullen. Serverbrede globale scripts hebben geen equivalent in Perfuse en worden gerapporteerd in plaats van verwijderd.

Het rapport zegt, per kanaal, of het schoon vertaald is, met waarschuwingen vertaald is of niet kon worden gelezen.

De kopregel is een breuk met de teller — "37 van 40 klaar" — omdat "37 klaar" u niets vertelt over wat u nog moet doen.

Een kanaal dat niet kon worden gelezen is een ander probleem dan een kanaal dat niet kon worden vertaald. Het eerste betekent dat de XML zelf niet kon worden geparsed en is meestal een afgekapt of gedeeltelijk export; het tweede betekent dat de inhoud van het kanaal iets bevat zonder een Perfuse-equivalent. De importeerder scheidt deze.

15.2 Wat vertaalt en wat een beslissing nodig heeft

Bronnen, bestemmingen, filters en de gewone transformer-stappen vertalen rechtstreeks. De connectors die vertalen: TCP/MLLP (en raw TCP met framing), HTTP, Bestand, Database, JavaScript, DICOM, Web Service (SOAP), SMTP en Kanaal Lezer/Schrijver. JMS en de Document Schrijver vertalen niet en worden gerapporteerd als blokkeringen.

Een Mapper-stap die een variabele instelt, plaatst deze in de kaart die de scope noemt — channelMap standaard — precies zoals Mirth doet, dus latere stappen die deze lezen met $('name') vinden deze.

JavaScript-transformers doen dit in het algemeen niet. Mirth-kanalen bevatten vaak substantiële code in een transformer en er is geen automatische conversie van willekeurige JavaScript naar declaratieve stappen. De importer rapporteert deze in plaats van een vertaling te proberen die subtiel verkeerd kan zijn: een verkeerd vertaalde transformer is erger dan een die voor een mens wordt gemarkeerd, omdat deze zal draaien.

Waar een script echt een script moet blijven, kan Perfuse het uitvoeren — zie de scripts-sleutel in de kanaalverwijzing — tegen de prijs van het stapniveau-trace zoals beschreven in foutopsporing.

15.3 Tegen welke importer is getest

Vijf motoren, elk met zijn eigen documenten: Mirth 4.5.2, OIE 4.5.2, 4.6.0 en 4.7.0, en BridgeLink 26.9.0. scripts/mirth-engine-corpus.sh compileert een klein programma tegen elke motor's eigen jars en heeft zijn eigen serialiser om drie gewone kanalen te schrijven — een MLLP-feed met een mapper, een script dat een code-templatebibliotheek aanroept en een filter; een HTTP-feed naar een database; een bestandspolling via MLLP — plus de bibliotheek en een kanaalgroep. Het laadt ze in de actieve motor en downloadt de motor's eigen serverback-up. De resultaten worden opgeslagen onder internal/mirth/testdata/engines/, en het testsuite houdt de importer tegen elke een van hen op elke build: elke back-up wordt gelezen, vertaald, geladen, en het ADT-kanaal wordt uitgevoerd met twee berichten om te controleren of de bibliotheek het recordnummer aanvult en de filter het resultaat verwijdert.

Perfuse's eigen exports gaan de andere kant op — Perfuse-kanalen geïmporteerd in elke actieve motor en gecontroleerd of de motor ze niet heeft opgeslagen als ongeldig. Alle vijf accepteren elke transport die Perfuse exporteert. Open Integration Engine 4.7.0 voegde twee HTTP-instellingen toe zonder equivalent hier: een HTTP-verzender gebonden aan een gekozen lokaal adres wordt gemeld als een waarschuwing, en een HTTP-Listener-aanvraaglimiet alleen wanneer deze boven de 1 MB ligt die Perfuse accepteert.

De eerste run tegen deze corpus vond vier defecten, allemaal gefixt: de vertaler weigerde HTTP- en bestandsbronnen als "alleen MLLP wordt ondersteund" lang nadat Perfuse beide had; het las het adres van een HTTP-afzender uit een veld dat geen van de motoren schrijft; het vertaalde Mirth's socketbuffergrootte als een limiet van 64 KB voor berichten; en een Mapper-variabele werd een JavaScript-globale variabele die $('mrn') nooit zag, dus de bibliotheek vulde een lege tekenreeks aan.

The single-channel fixture that started this was also exported by Mirth 4.5.2, authored by Mirth itself rather than written here. That distinction earned its place: the only fixture in this repository used to be hand-written, and a real Mirth will not load it — the API accepts the POST and then stores the channel as This channel is invalid. Verify all required extensions are loaded correctly, with every destination connector discarded.

Handmatig schrijven was nooit going to werken, en de reden is het waard om te weten als u uw eigen exporten produceert. Mirth's serialiser negeert elementen die het niet herkent, dus een verkeerde elementnaam produceert geen fout whatsoever — de connector is gewoon niet aanwezig daarna. Er is niets om te lezen en niets om tegen te controleren.

scripts/mirth-author-channel.sh bouwt een kanaal met Mirth's eigen modelklassen en zijn eigen serialiser, en post het vervolgens naar een actieve server en faalt als de server het afwijst. Perfuse's importer leest het resultaat: naam, brontransport en bestemmingen overleven allemaal.

15.4 Bewijzen dat het overeenkomt

Dit is het deel dat beslist of een migratie plaatsvindt, en het heeft bewijs nodig in plaats van vertrouwen.

Perfuse vergelijkt zijn eigen uitvoer met de oude motor, bericht voor bericht, op uw verkeer. Wat het nodig heeft, zijn paren: het bericht zoals het aankwam, en het bericht dat de oude motor produceerde uit het. Beide zijn in Mirth's eigen berichtenopslag en kunnen worden geëxporteerd uit zijn berichtenbrowser.

Perfuse kan niet in Mirth kijken, en deze handleiding zal dat niet doen alsof. Een tool die beweert een migratie te verifiëren zonder ooit de daadwerkelijke uitvoer van de oude motor te zien, zou niets verifiëren. Het leveren van de paren is de eerlijke vorm van de oefening.

15.4.1 Vier nummers, geen slaagpercentage

ResultaatBetekenis
IdentiekByte voor byte hetzelfde.
Cosmetisch alleenVerschilt op manieren die geen informatie dragen — lege velden, een laatste terminator.
VerschiltEen veldwaarde is anders.
Zou niet uitvoerenPerfuse kon het bericht helemaal niet verwerken.

Ze zijn vier nummers omdat ze vier verschillende dingen betekenen en het samenvoegen ervan degenen die een beslissing nodig hebben, verbergt.

Identiek betekent byte voor byte, niet equivalent. Een zwakkere test zou verschillen in segmentvolgorde of trailing separators toelaten, en dat zijn precies de dingen die een veeleisend downstream-systeem afwijst.

Cosmetische verschillen worden afzonderlijk geteld in plaats van opgenomen in de goede kolom. Ze dragen echt geen informatie, dus ze als fouten behandelen zou echte bevindingen onderduiken onder duizenden niets — maar ze zijn niet identiek, en een ontvanger die zijn eigen strikte parsing doet, kan het oneens zijn.

"Zou niet uitvoeren" is afzonderlijk van "verschilt" omdat het meestal een configuratiegap is die de importer niet kon invullen, niet een mappingbeslissing. Als alles in die kolom staat, zegt het vonnis dat en vertelt het u om naar de configuratie te kijken voordat u iets anders leest.

15.4.2 Verschillen worden gegroepeerd per veld

Een run over vijftigduizend berichten met vierduizend verschillen heeft u niets verteld dat u kunt gebruiken. Dezelfde run die zegt dat PID-8 in elk bericht verschilt omdat de oude motor Male schreef waar Perfuse M schrijft, heeft u precies één ding verteld om te beslissen.

Elke bevinding is dus een veld, met een telling, en het zegt of het verschil systematisch is — hetzelfde waardepaar elke keer — of of het veldinhoud verschilt.

Die onderscheid is het meest nuttige ding in het rapport. Één distinct waardepaar over vierduizend berichten is één mappingbeslissing. Vierduizend distincte paren is de inhoud die verschilt, wat een ander en veel ernstiger probleem is, en de twee mogen niet op dezelfde manier worden gelezen.

Bevindingen worden gerangschikt op hoeveel berichten ze beïnvloeden, dus de grootste enkele oorzaak is eerst.

15.4.3 Het vonnis rondt niet af

Het geeft exacte tellingen: 49.993 van 50.000, niet "meer dan 99%". De zeven zijn het hele punt van het uitvoeren ervan.

Het is geschreven om citeerbaar te zijn in een wijzigingsverzoek, omdat dat is waar het nummer uiteindelijk terechtkomt.

15.5 Een voorgestelde volgorde

  1. Importeer de kanalen en los alles op dat als onleesbaar wordt gerapporteerd.
  2. Voor elk kanaal, bekijk de waarschuwingen. De meeste zijn scripts.
  3. Exporteer een paar duizend berichtenparen uit Mirth voor het drukste kanaal en voer de vergelijking uit.
  4. Werk de resultaten door. Systematische zijn één beslissing per stuk.
  5. Voer opnieuw uit totdat de enige verschillen zijn die u hebt besloten correct zijn.
  6. Voer Perfuse uit in de schaduw naast Mirth op live-verkeer, lever nergens af en vergelijk opnieuw over een periode die een weekend en een maand einde omvat.
  7. Schakel over naar één kanaal, niet allemaal.

15.6 Wat alleen werkt op de software van één leverancier

Het migratiescherm beantwoordt een tweede vraag, en het is de moeite waard om die te stellen voordat u een mening over Perfuse heeft: hoeveel van uw integratielogica kan alleen werken op de software die u heeft.

Elk kanaal krijgt een Portabiliteit-oordeel, van dezelfde scan die de migratienotities produceert. Het wordt uitgevoerd tegen een kanaalexport, dus het heeft niets geïnstalleerd nodig en verandert niets.

15.6.1 Het onderscheid is het hele punt

De meeste Java in Mirth-scripts is geen lock-in. SimpleDateFormat, HashMap, Apache Commons — alles werkt rond een JavaScript-engine uit 2009, alles is gewoon, alles heeft directe equivalenten. Een kanaal met drie honderd van die verwijzingen is volledig portabel, en een tool die '300 Java-verwijzingen, u bent vast' zou rapporteren, liegt tegen u.

Lock-in is specifiek de oproepen die de server van de leverancier nodig hebben: com.mirth.connect.* en vendor-jars. Vijf van die en u bent vast. Vijfhonderd van het andere type en u bent vrij.

Dus het oordeel begint met het nummer dat ertoe doet en zegt in dezelfde zin dat het grotere nummer het niet is. Waar er vendor-oproepen zijn, worden ze opgesomd bij naam — een telling is een bewering, en een lijst is iets dat uw eigen ingenieur kan gaan controleren.

Een derde categorie wordt afzonderlijk gehouden: functionaliteit die bestaat, maar niet vanuit een script. Het starten van een kanaal vanuit JavaScript heeft geen equivalent hier, en er is een API-eindpunt dat exact hetzelfde doet. Het noemen van lock-in zou de bevinding overdrijven.

15.6.2 Java-oproepen die ongewijzigd worden uitgevoerd

De meest voorkomende Java-klassen worden uitgevoerd zoals ze zijn geschreven. Perfuse heeft geen Java-runtime, dus zijn dit JavaScript-klassen met dezelfde namen en methoden, genoeg voor de manier waarop kanaalscripts ze gebruiken; importPackage(java.util) en importClass(...) brengen ze in scope door hun korte namen, zoals in Rhino (JavaScript's eigen Date, Map, Set, Math, String en Boolean worden nooit vervangen: de Java-versies zijn er nog steeds bij volledige naam). Het migratierapport telt elke oproep naar deze als reeds ondersteund.

PakketKlassen
java.utilArrayList, LinkedList, Vector, List, Collection, HashMap, LinkedHashMap, Hashtable, TreeMap, Properties, HashSet, LinkedHashSet, TreeSet, Arrays, Collections, Date, Calendar, GregorianCalendar, UUID, Base64, regex.Pattern (met Matcher), concurrent.ConcurrentHashMap
java.langString, StringBuilder, StringBuffer, Integer, Long, Short, Byte, Double, Float, Boolean, Math, System (tijd en lijnscheidingsteken alleen)
java.text, java.math, java.net, java.nioSimpleDateFormat en DateFormat (Mirth's patroonletters), BigDecimal (als een double), URLEncoder, URLDecoder, StandardCharsets
Apache Commonslang3.StringUtils en lang.StringUtils (ongeveer zestig methoden), StringEscapeUtils, codec.binary.Base64

Ze gedragen zich als Java waar scripts ervan afhankelijk zijn: Integer.parseInt("x") gooit een NumberFormatException, String.replaceAll en split nemen reguliere expressies, terwijl replace letterlijk is, kaarten sleutelstrings door waarde, TreeMap en TreeSet itereren in orde, en SimpleDateFormat.parse retourneert een datum getTime() werkt op. Een methode die een script aanroept die de equivalentie ontbeert, faalt op die regel, met naam; elke andere Java-klasse faalt bij naam, zoals voorheen. BigDecimal is een dubbele hier, dus houdt het geen exacte decimale wiskunde van Java: controleer scripts die het voor geld gebruiken.

15.6.3 Externe scripts worden gemeld als onbekend

Een stap die een extern scriptbestand uitvoert, verwijst naar een pad op de oude server, en het bestand is niet in de export opgenomen. Niets kan worden gezegd over wat het bevat, dus het wordt geteld als onbekend in plaats van verondersteld de een of de ander. Haal die bestanden op voordat u iets concludeert — in beide richtingen.

15.6.4 Perfuse's eigen lock-in, vermeld in dezelfde adem

Dit gedeelte zou oneerlijk zijn zonder het.

Perfuse is Apache 2.0, wat onherroepelijk is voor reeds uitgegeven code. U kunt vorken wat vandaag bestaat en niemand kan dat intrekken. Kanalen zijn YAML-bestanden en scripts zijn gewone JavaScript, dus er is geen propriëtair oppervlak om aan te roepen — Mirth's smaak van Java-afhankelijkheid is structureel niet beschikbaar hier, wat de enige plaats is waar een beperking echt een functie is.

Wat dat niet belooft: dat een toekomstige versie open blijft, dat een gehoste service bestaat tegen een prijs die u leuk vindt, of dat migreren van Perfuse niets kost. Het verplaatsen van een integratielaag betekent het opnieuw testen van elk kanaal tegen echt verkeer. Wat u kiest, is of de artefacten die u bouwt, leesbaar en portabel zijn, en of de uitgang afhankelijk is van een licentie die iemand anders controleert.

15.6.5 Het instellen van stap 6

One message real traffic Live channel unchanged Candidate the version you are testing Receiver delivers nothing Comparison field by field The candidate sees the same real messages as the live channel and delivers none of them. Only the live channel reaches the receiver. What you read afterwards is where the two disagreed, field by field — not a pass or a fail.

Het Shadow-gedeelte start een vergelijking. Kies het kanaal dat wordt uitgevoerd, kies de kandidaat om te vergelijken vanuit de lijst en start.

Drie dingen over het zijn het waard om te weten voordat u zich op de cijfers verlaat.

De kandidaat wordt gekozen uit een lijst, niet getypt. Een schaduw noemt een kanaalbestand en een naam die niet wordt opgelost, maakt het *live* kanaal ongeldig — Perfuse weigert een kanaal helemaal als iets wat het verwijst, kapot is. Dus een typefout produceert geen waarschuwing, maar maakt het actieve kanaal verdwijnen.

Het aandeel is een percentage. Verlaag het alleen op een drukke feed en weet wat het kost: steekproeven verlagen het werk en het vertrouwen in dezelfde verhouding, en het bericht dat het verschil had moeten laten zien, is het ongebruikelijke.

Velden om te negeren zijn meestal nodig. Een kanaal dat een tijdstempel of een volgnummer stempelt, verschilt op elk enkel bericht, wat een verschilpercentage van 100% rapporteert en je niets vertelt. MSH-7 en MSH-10 zijn het gebruikelijke paar.

Een vergelijking wordt geschreven naar het kanaalbestand zodra je het start en begint met observeren wanneer het kanaal de volgende keer wordt geladen — het scherm zegt dat in plaats van te beweren dat het al actief is. Het stoppen van een vergelijking laat het kandidaatkanaal op zijn plaats, omdat het kandidaat de bedoeling is om live te gaan.

Stap 6 is degene die niet kan worden ingekort. De verschillen die ertoe doen, zijn meestal in het verkeer dat alleen af en toe verschijnt — een zeldzame triggergebeurtenis, een maandelijkse batch, een afzender die zich anders gedraagt om middernacht — en een steekproef die over een middag wordt genomen, bevat ze niet.

15.7 Terugkeren naar de andere kant

Een kanaal kan worden geëxporteerd als een Mirth-kanaalbestand, vanuit de browser: Kanalen, vervolgens Naar Mirth op het kanaal dat je wilt.

Dit bestaat omdat het bezwaar tegen het vervangen van een werkende motor zelden is of de vervanging goed is. Het is wat er gebeurt als de beslissing verkeerd blijkt te zijn, en een export die terugkeert naar de manier waarop het kwam, is het goedkoopste antwoord op dat.

Lees wat het dialoogvenster je vertelt voordat je het bestand neemt. Mirth's formaat heeft nergens ruimte om een Perfuse-filter, een transformatieketen, een contract of een schaduwvergelijking te plaatsen, dus een geëxporteerd kanaal doet minder dan degene waar het vandaan kwam. De transports en hun adressen worden omgezet; de logica niet. Elk verlies wordt genoemd bij naam voordat het bestand wordt aangeboden, en dezelfde lijst gaat naar de beschrijving van het kanaal, zodat degene die het importeert, het ook ziet.

Een kanaal dat Mirth niet kan uitdrukken, wordt geweigerd in plaats van benaderd. Een S3-bestemming heeft geen Mirth-equivalent, en een kanaal dat schoon importeerde terwijl het ergens anders werd afgeleverd dan de bucket, zou erger zijn dan helemaal geen bestand. De weigering noemt de bestemming die de fout veroorzaakt.

De connectordefinities worden niet geschreven vanuit een lezing van Mirth's formaat. scripts/mirth-dump-connector-templates.sh heeft Mirth's eigen serialiser om de standaardwaarden voor elke connectorklasse te produceren, en Perfuse vervangt waarden in die documenten — weigert elke instelling die de sjabloon niet al bevat. Dit is belangrijk vanwege de manier waarop Mirth een kanaal beantwoordt dat het niet kan parseren: het weigert de import niet. Het slaat een kanaal op waarvan de beschrijving is vervangen door "Dit kanaal is ongeldig. Verifieer alle vereiste extensies zijn correct geladen" en waarvan de bestemmingen stilzwijgend zijn verwijderd. Een exporter die wordt gecontroleerd tegen zijn eigen uitvoer in plaats van tegen een server, slaagt voor elke test terwijl hij documenten produceert die worden weggegooid, wat precies is wat hier gebeurde voordat de exporteren werden getest tegen een actieve Mirth.

Wat vandaag de dag oversteekt: MLLP en TCP in beide richtingen, HTTP in beide richtingen, bestandslezen en -schrijven, databasereaderen en -schrijven, DICOM in beide richtingen, en SMTP, SOAP en JavaScript-bestemmingen. Elk paar wordt geverifieerd door te importeren in een echte Mirth 4.5.2 en te controleren of de server het kanaal niet stilzwijgend heeft vervangen.

16 CMS-0057 voor betalers

De CMS Interoperabiliteit en Prior Authorization finale regel (CMS-0057-F) vereist dat getroffen betalers — Medicare Advantage-organisaties, staat Medicaid- en CHIP-programma's en hun beheerde zorgplannen, en QHP-uitgevers op de federale uitwisselingen — vier FHIR-API's uitvoeren vanaf 1 januari 2027, en priorisatie-metrieken op hun openbare website elke jaar vanaf 2026.

Perfuse biedt de vier API's op zijn FHIR-eindpunt en de conversies die ze vullen: geclaimde claims als CARIN Blue Button, priorisaties als Da Vinci PDex, en de jaarlijkse metrieken in de lay-out van CMS's eigen sjabloon. Het CMS-0057-overzicht, onder Uitwisseling, zegt welke van de vier deze instantie kan beantwoorden en wat elk nog nodig heeft, en voert alle drie conversies uit in de browser.

Geneesmiddelen vallen buiten het bereik van de hele regel, evenals de priorisatiebepalingen: geen farmaceutische claims, geen formularium, en een metriekenrij die een geneesmiddel noemt, wordt geweigerd in plaats van geteld.

16.1 De vier API's

APIWat het serveertGidsenIngeschakeld door
Patient AccessDe claims, klinische gegevens en voorafgaande autorisaties van een lid, aan een app die hij kiestCARIN Blue Button 2.2.0, PDex 2.2.0, US Core, SMART App Launch-fhir en een SMART-uitgever (-smart-issuer)
Provider AccessHetzelfde voor de toegewezen leden van een zorgverlener, in bulkPDex 2.2.0, Da Vinci ATR 2.1.0, Bulk Data-fhir-payer-apis en -fhir-bulk-export
Payer-to-PayerHet record van een lid aan een andere verzekeraar, na matchingHRex 1.2.0 $member-match, PDex 2.2.0-fhir-payer-apis
Prior AuthorizationWat een bestelling nodig heeft, de documentatie, dan het verzoek en de beslissingDa Vinci CRD, DTR en PAS 2.2.x (2.2.1, 2.2.0, 2.2.1) en 2.1.0, met X12 278-vertaling-fhir, beschrijfbaar, en -crd-rules

De Patient Access API heeft geen eigen bewerking nodig: het is het gewone lezen en zoeken van de FHIR-eindpunkt, beschermd door SMART, met CARIN- en PDex-bronnen in de opslag. Zoeken naar ExplanationOfBenefit ondersteunt de parameters met de naam CARIN — patient, identifier, type, service-date, billable-period-start, provider, insurer, coverage — en Coverage ondersteunt subscriber-id, identifier en payor.

16.1.1 Twee releases van de gidsen: 2.1.0 en 2.2.x

CMS-0057-F beveelt CRD, DTR en PAS 2.0.1 en 2.1.0 aan. De 2.0.1-releases zijn gebaseerd op US Core 3.1.1, die op 1 januari 2026 is verlopen, dus 2.1.0 is de release die een EHR waarschijnlijk zal gebruiken; de nieuwste zijn CRD 2.2.1, DTR 2.2.0 en PAS 2.2.1. Perfuse antwoordt in beide. Het werkt uit welke versie een beller spreekt, meest specifiek eerst:

  1. vanuit het verzoek: CRD's CDS Hooks-extensie davinci-crd.requestedVersion ("2.1"), of de versie op een Da Vinci-profiel van een DTR-

of PAS-input claims (profile-pas-request-bundle|2.1.0);

  1. vanuit de registratie van de beller: davinci_version: "2.1" op een SMART-client (-smart-clients) of een CDS-client (-cds-clients);
  2. vanuit de server: serve -davinci-version 2.1; de standaard is 2.2.
clients:
  - issuer: https://ehr.example.org
    jwks_url: https://ehr.example.org/.well-known/jwks.json
    davinci_version: "2.1"

Elk antwoord wordt beslist en bewaard in de 2.2.x-vorm en herschreven voor een 2.1.0-beller wanneer het wordt verzonden, dus de regels, de review-wachtrij, de X12 278-koppeling en de metrieken zijn hetzelfde voor beide. De herschrijving dekt wat de releases verschillend spellen: CRD 2.1.0 heeft geen indeterminate (Perfuse zegt voorwaardelijk, met de reden) en geen categorie op een dekkingdetail; DTR 2.1.0 noemt het pakket PackageBundle en laat de QuestionnaireResponse over aan de app; PAS 2.1.0's $inquire antwoordt met één Bundle, en het ontbreekt aan de reviewer en transmissie-extensies. De volledige lijst, en de controle tegen elke 2.1.0-gids van zijn eigen voorbeelden, is in conformance/davinci21. Een PAS-melding volgt -davinci-version, aangezien een abonnement niet aangeeft welke release de eigenaar leest.

16.2 Deckingsvereisten en documentatie: CRD en DTR

De Prior Authorization API is in de praktijk drie Da Vinci-gidsen samen. CRD vertelt de clinician, terwijl de bestelling nog een concept is, of het is gedekt, of het een voorafgaande autorisatie nodig heeft en welke documentatie gewenst is. DTR geeft de EHR de vragenlijst die die documentatie verzamelt. PAS dient het verzoek in en retourneert de beslissing. Perfuse dient alle drie als de betaler.

-crd-rules rules.yaml dient CRD via CDS Hooks op /cds-services: alle zes hooks van CRD, order-sign, order-select, order-dispatch, appointment-book, encounter-start en encounter-discharge, elk met een prefetch voor de actieve Verzekering van de patiënt. De twee encounter-hooks prefetchen ook de encounter en geven antwoord over de encounter zelf, gematched op type en servicetype, zoals appointment-book antwoord geeft over een afspraak. De regels zijn het beleid van de verzekeraar, bewaard in een bestand omdat ze veranderen zonder software-releases:

payer: Springfield Health Plan
rules:
  - description: Home oxygen equipment
    codes: [E0424, E0431]
    covered: covered            # covered, not-covered, conditional
    pa: auth-needed             # no-auth, auth-needed, satisfied, performpa, conditional
    documentation: [clinical]
    questionnaire: https://www.springfield-health-plan.example/fhir/Questionnaire/home-oxygen

Elke bestelling krijgt een systemActions-update met CRD's coverage-informatie-extensie - die de EHR op de bestelling opslaat en later meestuurt met de prioritaire autorisatie - en een kaart die de clinici lezen. Een bestelling waarvan de code geen regel heeft, wordt beantwoord met conditional, nooit aangenomen als gedekt; een aanvraag met helemaal geen Coverage krijgt een kaart die dit aangeeft. examples/crd/ bevat een regelbestand en een overeenkomende vragenlijst.

Een regel kan ook de rest van wat CRD een betaler laat zeggen:

Wat de EHR niet heeft vooraf opgehaald, leest Perfuse uit de fhirServer van de EHR met het token dat het heeft verzonden. Als dit mislukt, is het antwoord indeterminate met CRD's technical reden, nooit een gok. Een Coverage die is beëindigd of niet actief is, wordt beantwoord met not-covered, no-active-coverage.

members: fhir in het regelbestand lost de dekking op tegen de eigen records van de betaler in de FHIR-opslag van deze server (start met -fhir), dezelfde records die $member-match leest:

met dat nummer.

Discovery verklaart davinci-crd.version en een coverage-info configuratie-optie. Wanneer een client de optie uitschakelt, is het antwoord leeg. EHR JWT's worden gecontroleerd zoals CDS Hooks ze definieert, met iss, aud, exp, iat en jti en geen sub, en een herhaalde jti wordt geweigerd.

Oproepen authenticeren met de JWT die een EHR ondertekent voor elke oproep, van een uitgever genoemd in -cds-clients met zijn JWKS URL — dat is hoe CDS Hooks het beschrijft — of met een Perfuse API-token. Discovery is open, zoals CDS Hooks vereist.

DTR: laad de vragenlijsten in de FHIR-endpoint, en POST /fhir/Questionnaire/$questionnaire-package retourneert ze als DTR-pakketbundels, met de CQL-bibliotheken die ze noemen. Het verzoek kan de vragenlijst noemen, of de bestelling verzenden en zijn coverage-informatie laten zeggen welke.

Probeer het: Payers → Claims & auth → Coverage requirements (CRD) stuurt een bestelling naar de regels van deze server of naar een CDS-service-URL van een payer en toont de kaarten en de dekkinginformatie.

16.3 Claims als CARIN Blue Button

perfuse cms0057 carinbb koppelt elke claim in een 837 aan zijn betaling in een 835, op basis van het patiëntaccountnummer dat de 835 moet teruggeven, en schrijft een FHIR-transactie voor elk: de ExplanationOfBenefit met de Patiënt, Dekking, Organisaties en Beoefenaars die het verwijst.

perfuse cms0057 carinbb -system https://fhir.your-plan.org/identifier -network innetwork \
    claims.837 remittance.835

Het profiel volgt de claim: professionele claims (837P) worden C4BB-ExplanationOfBenefit-Professional-NonClinician, en institutionele claims (837I) inpatient of outpatient op basis van het type factuur. Elke entry is een PUT met een id afgeleid van de bron-identificatoren, zodat het laden van dezelfde claim tweemaal deze bijwerkt in plaats van een tweede kopie te maken.

Drie dingen zijn niet in een van de X12-bestanden, en elk wordt afgehandeld door te zeggen dat het niet aanwezig is, in plaats van te gokken:

Diagnoses worden geschreven met hun decimale punt (J02.9, niet J029), omdat dat is hoe het codesysteem ze publiceert en een terminologie-server die naar de andere spelling wordt gevraagd, zegt dat het niet bestaat. Een afhankelijke lid-identificator is die van de abonnee, die is wat de 837 meeneemt, en de opmerkingen zeggen dit. Een NPI met een verkeerde controlecijfer wordt gemeld voordat US Core het afkeurt.

16.4 Voorafgaande autorisaties als PDex

perfuse cms0057 priorauth converteert een Da Vinci PAS ClaimResponse — of het PAS-antwoordbundle dat er een bevat — naar een PDex-prior authorisation ExplanationOfBenefit, wat alle drie data-API's serveren.

perfuse cms0057 priorauth pas-response.json pas-claim.json

De PAS-claim is optioneel en meestal nodig. Een ExplanationOfBenefit moet aangeven onder welke dekking de beslissing is genomen, en alleen het verzoek bevat dat; zonder dat stopt de conversie en wordt daar melding van gemaakt. De reviewactie — goedgekeurd, geweigerd, uitgesteld, met autorisatienummer en reden — verplaatst zich van PAS's extensie naar PDex's, en de X12-servicetype houdt zijn code onder de URI die PDex eraan bindt.

16.5 De Provider Access- en Payer-to-Payer-API's

Met -fhir-payer-apis antwoordt het FHIR-eindpunt op drie extra bewerkingen:

De exporten passen de uitsluitingsregels toe bij het uitgaan. Claims verliezen de betaling en elke kostenverdeling en terugbetalingsbedrag, en behouden de diensten, codes, datums en aanbieders; het CARIN-profiel wordt verwijderd uit meta.profile omdat de resource deze niet langer voldoet. Payer-to-Payer laat ook geweigerde prior authorisaties achterwege. Leden met een actieve PDex-Provider Access-opt-out-toestemming worden uit een providerexport weggelaten, en het logboek registreert hoeveel. De patient-parameter kan alleen worden beperkt tot leden van de groep; het noemen van iemand anders wordt geweigerd.

Toegang tot de export van een groep wordt bepaald door de authenticatie van het eindpunt. SMART-scopes geven aan welke soorten resources een token mag lezen, niet welke groep, dus elke provider heeft een token nodig dat alleen toegang heeft tot zijn eigen attributielijst. Een API-token kan worden beperkt tot groepen wanneer deze wordt gemaakt — perfuse token create -label riverside-provider-access -fhir-groups riverside-attributed, of het veld Beperk tot FHIR-groepen onder Gebruikers → Machine-referenties — en op het FHIR-eindpunt kan het vervolgens deze groepen lezen, $davinci-data-export of $export uitvoeren op deze groepen en ophalen wat de export heeft gegenereerd, en niets anders. De groep van een andere provider geeft niet-gevonden in plaats van verboden, zodat een token niet leert welke andere attributielijsten bestaan; elke andere aanvraag, inclusief lidmaatschapsvergelijking en gewone zoekopdracht, wordt geweigerd. De beperking geldt voor API-tokens; een token van een SMART-uitgever heeft geen groepsbeperking. Wanneer SMART ook is geconfigureerd, worden API-tokens geweigerd, tenzij Instellingen → FHIR → Accepteer Perfuse API-tokens naast SMART-tokens is ingeschakeld (zie Beveiliging, *Wie mag het FHIR-eindpunt aanroepen*); een groepsbeperkt token van een provider heeft dit nodig.

16.6 Een providerdirectory: Plan-Net

CMS-0057 vraagt payers ook om een providerdirectory, en het FHIR-eindpunt biedt er een aan Da Vinci Plan-Net 1.1.0 zonder optie om deze in te schakelen: laad de Practitioners, PractitionerRoles, Organizations, OrganizationAffiliations, Locations, HealthcareServices, InsurancePlans en Endpoints, en apps van leden kunnen deze doorzoeken. Elke Plan-Net-zoekparameter is geïndexeerd - een rol van het netwerk en de service, een dekking van een plan, een deelnemende organisatie van een affiliatie, een organisatie van partof - samen met de includes en omgekeerde ketens (_has) die de queries van de handleiding gebruiken, en de CapabilityStatement vermeldt de Plan-Net-profielen.

Inferno's Plan-Net-suite slaagt voor 199 tests. De 10 die het faalt zijn voorwaartse ketens waarin de kit de zoekwaarde neemt van de eerste Organisatie die het heeft gezien in plaats van een waar de doorzochte resources naar verwijzen; dit wordt gemeld aan de kit (haar issue 34), en de server beantwoordt deze queries correct wanneer deze een waarde krijgt die de gegevens bevatten.

16.7 Prior authorisatiemetrics

perfuse cms0057 metrics leest een CSV van beslissingen die zijn geëxporteerd uit het utilisatiemanagementsysteem en produceert de openbare pagina die CMS vereist, in de lay-out van zijn *Prior Authorization Metrics Reporting — Overzicht en sjabloon*.

perfuse cms0057 metrics -year 2025 -org "Springfield Health Plan" -services services.csv \
    decisions.csv > prior-authorization-metrics-2025.html

Kolommen worden gevonden door header: priority, received, decided en decision zijn vereist, en request_id, line_of_business, extended, appealed, appeal_decision, service_code en service_description worden gelezen wanneer ze aanwezig zijn. Een aanvraag behoort tot het jaar waarin deze is beslist; een aanvraag die nog steeds in behandeling is, wordt vermeld als uitgesloten, nooit geteld. Elke rij die niet kan worden gelezen, wordt gerapporteerd met zijn regelnummer.

De rekenkunde volgt het sjabloon: voor standaard- en versnelde aanvragen afzonderlijk, het aandeel goedgekeurd en geweigerd, goedgekeurd en geweigerd binnen de beslissingstermijn, goedgekeurd na verlenging van de beoordelingstijd, en goedgekeurd na beroep — uit beroepen, niet uit aanvragen — met het gemiddelde en mediaan van de tijd van ontvangst tot beslissing. Een mediaan onder een dag wordt geschreven in uren in plaats van afgerond naar "0 dagen", wat het sjabloon expliciet vraagt. Gedeeltelijk goedgekeurde aanvragen worden geteld als goedgekeurd, aangezien het sjabloon geen categorie heeft voor deze, en de pagina zegt hoeveel er waren. Metrics worden gerapporteerd per bedrijfslijn, wat het niveau is dat CMS vereist.

De pagina is zelfstandig — geen script, geen externe stylesheet of lettertype — omdat deze wordt gepubliceerd op een openbare website door degene die deze onderhoudt, en alles wat deze van elders laadt iets anders is dat kan breken of een bezoeker kan volgen. -format csv en -format json geven dezelfde nummers voor andere gebruiken. Zonder -services draagt de pagina een mededeling dat de lijst met items en diensten die een voorafgaande autorisatie vereisen ontbreekt, omdat CMS dit op dezelfde pagina vereist.

16.8 Geneesmiddelen: het formularium, Real-Time Prescription Benefit en elektronische voorafgaande autorisatie

CMS-0062-P (voorgesteld op 14 april 2026) zou medicijnen in prioritaire autorisatie brengen: getroffen payers zouden NCPDP SCRIPT-elektronische prioritaire autorisatie, de NCPDP Formulary & Benefit-standaard en NCPDP Real-Time Prescription Benefit vanaf 1 oktober 2027 ondersteunen, geneesmiddelenaanvragen binnen 24 uur (versneld) en 72 uur (standaard) beslissen, een specifieke reden geven voor elke weigering en geneesmiddelenmetingen vanaf 2028 rapporteren. Medicare Part D vereist al SCRIPT-ePA. Één bestand, de formularium, beantwoordt alles:

perfuse serve -fhir -pas -crd-rules payer-rules.yaml -formulary formulary.yaml

examples/formulary/formulary.yaml is een voorbeeld waarvan de medicijnen echte RxNorm-concepten zijn met NDC's RxNorm-lijsten voor hen (gecontroleerd tegen RxNav). Een bestand noemt de payer, de plannen (elk met het formularium dat het gebruikt, de groeps-ID's en de kostenverdeling per apotheekvoordeel en trede) en de formularia. Elk medicijn is een RxNorm SCD of SBD met zijn RxNorm-groep (de SCDG of SBDG die de Drug Formulary API vereist), de NDC's, een trede en de beperkingen: prior_authorization, step_therapy, quantity_limit (een hoeveelheid in een rollende aantal dagen, en een dagelijkse maximum), not_covered, alternatives (RxNorm-codes, meest gewenst eerst), notes en questionnaire, de canonieke URL van het FHIR-Questionnaire dat een prioritaire autorisatie vraagt. cost_30_day is de kosten van een 30-dagen-voorraad van het plan, waarvan een coinsurance een percentage is; zonder dit is een coinsurance een percentage, nooit een verzonnen bedrag. Het hele bestand wordt gecontroleerd wanneer het wordt geladen, elk probleem wordt tegelijk vermeld. Een lid wordt gevonden door de members-lijst van het bestand, door groep, of via de FHIR-store: een Coverage waarvan subscriberId de lid-ID is en waarvan class van het type plan de plan-ID is. Payers › Medicijnen toont het formularium, prijst een medicijn en voert een prioritaire autorisatie uit van begin tot eind.

16.8.1 De Da Vinci US Drug Formulary API

Gepubliceerd op /formulary/fhir als Da Vinci US Drug Formulary 2.1.0: elk plan een PayerInsurancePlan, elk formularium een Formulary (beide InsurancePlan), elk medicijn een FormularyDrug (MedicationKnowledge) en elk item een FormularyItem (Basic). De zoekopdrachten van de handleiding worden geserveerd (Basic?code=formulary-item&formulary=...&drug-tier=...&pharmacy-benefit-type=...&period=..., subject:MedicationKnowledge.code, InsurancePlan?formulary-coverage=..., coverage-type, MedicationKnowledge?code=...&doseform=...) met _include=Basic:subject, Basic:formulary en InsurancePlan:formulary-coverage. Het is openbaar, zonder referentie, zoals CMS vereist van een formularium van een payer: het wordt geserveerd vanuit een eigen opslagruimte, in het geheugen, die het formularium en niets anders bevat, zodat het openstellen niet een patiëntendossier kan bereiken. Het is alleen-lezen. Een uitgesloten medicijn wordt niet gepubliceerd, omdat de API de dekking van een formularium vermeldt; RTPB en ePA antwoorden het nog steeds als niet-dekkend. Geverifieerd met de HL7 FHIR-validator tegen het 2.1.0-pakket van de handleiding met terminologie gecontroleerd: elke resource gegenereerd uit het voorbeeld heeft geen fouten.

16.8.2 Real-Time Prescription Benefit

POST /ncpdp/rtpb neemt een RTPBRequest (NCPDP RTPB v13) met een API-token van de operatorrol en beantwoordt een RTPBResponse uit de formularium: de dekkingstatus, de formulariumstatus, de geschatte bijdrage van de lid en de planner, en de dekking beperkingen, met maximaal vijf gedekte alternatieven die op dezelfde manier worden geprijsd. Beperkingscodes en de status waaraan elk wordt toegewezen, volgen de openbare RTPB-implementatieaanbevelingen van NCPDP: 75 voorafgaande autorisatie vereist, 608 staptherapie, 76 plannen limiet overschreden, 7X dagen voorziening boven de plannen limiet (een geneesmiddel dat niet beschikbaar is per post, bijv.), 70 niet gedekt, alle *gedekt met beperkingen* (CR) behalve 70 (NC). Een lid met een goedgekeurde voorafgaande autorisatie op het dossier krijgt CC en AB8, zoals de Surescripts-gids vraagt, zodat de voorschrijver niet wordt gevraagd om opnieuw te vragen. Een aanvraag die niet kan worden geprijsd, is NotProcessed met een NCPDP-rejectcode: 52 voor een lid dat niet wordt gevonden, E7 en 19 voor een ontbrekende hoeveelheid of dagen voorziening. De apotheekvoordelen worden gelezen uit de aanvraag: een vulover 34 dagen is een drie-maands voorziening, en apotheektype M is per post besteld.

16.8.3 Elektronische voorafgaande autorisatie (NCPDP SCRIPT)

POST /ncpdp/script neemt PAInitiationRequest, PARequest, PAAppealRequest en PACancelRequest met een API-token van de operatorrol, en beantwoordt elk met zijn antwoord:

RequestAnswer
PAInitiationRequestClosed when none is needed: CC no prior authorization required, FN within the quantity limit, FM not covered or not on the formulary, FQ an approval on file, CD no such member, CG one already in process. Otherwise Open, with a case ID and the question set.
PARequestDecided as a PAS request: Approved with the authorization number and period, Denied with the reason, or Open under review.
PAAppealRequestA denied case decided again, on the reason in PANote (an appeal without one is asked for it).
PACancelRequestApproved while the case is open or under review, and the PAS request is cancelled; Denied once it is decided.

De vraagset is het FHIR-vragenformulier van het geneesmiddel uit de FHIR-store, hetzelfde dat DTR invult: een boolean wordt een ja/nee-keuze, een keuze een keuze, een nummer numeriek, een datum een datum, en alles anders vrij tekst; groepen zijn platgemaakt in volgorde, en enableWhen wordt niet overgedragen, omdat SCRIPT zich splitst op basis van keuze en niet van voorwaarde. Een geneesmiddel zonder vragenformulier krijgt drie vrije-tekstvragen: de diagnose, wat is geprobeerd, en waarom dit geneesmiddel. Een PARequest wordt een Da Vinci PAS-aanvraag: een Claim voor het geneesmiddel (RxNorm en NDC), de MedicationRequest die het vraagt, de patiënt, voorschrijver, betaler en dekking, en de antwoorden als een QuestionnaireResponse, met eventuele bijlagen als DocumentReferences. Deze wordt vervolgens beslist zoals elke voorafgaande autorisatie op deze server: het regelbestand, een beslissingsdienst (-pas-decider-url), of de reviewerwachtrij, waar deze wordt gemarkeerd als Geneesmiddel en wordt vastgehouden aan de geneesmiddeltimeframes. Een beslissingsdienst ziet een geneesmiddelaanvraag precies zoals deze een aanvraag ziet van een EHR's PAS-client. We bevelen Vaglio aan, BioDream's source-available (PolyForm Shield) beslissingsengine, die geneesmiddelbeleid met staptherapie heeft; een payers eigen engine past in via dezelfde -pas-decider-url, en geen is nodig voor het regelbestand en reviewers om te beslissen.

Een beslissing genomen na het beantwoorden van de aanvraag (een reviewers, een beroep) wordt naar de voorschrijver gestuurd als een ongevraagd PAResponse of PAAppealResponse, gerouteerd naar het kanaal genoemd door -epa-reply-channel, wat deze levert aan het netwerk. Zonder een dergelijk kanaal, of wanneer levering faalt, zegt het geval dat de voorschrijver hiervan niet op de hoogte is gesteld en het scherm stuurt deze opnieuw.

Payers › Geneesmiddelen › Voorafgaande autorisatie stuurt de berichten die een voorschrijverssysteem naar dit servers eigen endpoint zou sturen (start, beantwoord de vragen, zie de beslissing), lijst elke zaak met wat de voorschrijver is meegedeeld, en toont de geneesmiddelcijfers die CMS-0062-P voorstelt: aanvragen goedgekeurd, afgewezen en in behandeling, beroepen en goedgekeurd of afgewezen na beroep, het gemiddelde en mediaan aantal uren van aanvraag tot beslissing, en hoeveel zijn laat beslist. Medisch-voordeel geneesmiddelen aangevraagd via PAS (een HCPCS J-code met een MedicationRequest, of een item gecodeerd in RxNorm of NDC) worden geteld als geneesmiddelen in de PAS-cijfers ook.

Wat dit rust op, duidelijk gesteld. NCPDP's schemas en implementatiegidsen zijn gelicentieerd. De elementnamen en volgorde hier volgen de openbare Surescripts ePA- en RTPB-gezelschapsgidsen en hun voorbeelden, en NCPDP's openbare RTPB-aanbevelingen. Twee elementen die het openbare materiaal nooit laat zien, zijn geschreven naar het SCRIPT-patroon dat elders wordt gebruikt en moeten worden gecontroleerd tegen een gelicentieerde kopie voordat certificering: Closed/ReasonCode en Denied/DenialReason. Geen bericht is gecontroleerd tegen NCPDP's XSD of een netwerkcodering. Het NCPDP Formularium- & Voordelenbestand wordt niet geproduceerd: de volledige lay-out is in NCPDP's gelicentieerde gids, en een partieel bestand zou worden geweigerd door het netwerk dat het laadt.

16.9 Wat is gecontroleerd, en tegen wat

De CARIN- en PDex-uitvoer zijn gevalideerd met de officiële HL7 FHIR-validator, geladen met de gepubliceerde pakketten (hl7.fhir.us.carin-bb#2.2.0, hl7.fhir.us.davinci-pdex#2.2.0): professioneel, inpatient en outpatient claims en twee PAS-beslissingen, zonder fouten. De PDex-ingangen waren de PAS-gids eigen voorbeelden in plaats van vormen geschreven hier om overeen te komen met de converter. De validator vond vijf defecten in de eerste run — onder andere dat CARIN de profielversie in meta.profile en de claim-type code systeemversie op institutionele claims vereist — en elk is gefixeerd en gedekt door een test.

Het bouwen van dit vond een defect ouder dan het: de FHIR-store liet elk element dat zijn interne model niet verklaarde vallen, dus een ExplanationOfBenefit verloor zijn items, diagnoses, beoordeling en betaling op weg naar binnen. De store houdt nu alles wat een resource draagt, en een test laadt een CARIN-claim via de server en leest het terug helemaal.

CRD's output - de bijgewerkte order, en de CDS Hooks-respons tegen CRD's eigen logisch model - en DTR's pakketoutput valideren in de officiële HL7-validator tegen CRD 2.2.1 en DTR 2.2.0 met geen fouten.

DTR hier is de kant van de betaler van 2.2.0. $questionnaire-package neemt de vragenlijsten met de naam, die CRD op een bestelling noemt, of de dekking-bewering-ID die CRD retourneert (context, terwijl hetzelfde proces CRD bedient), en retourneert elk als een pakketbundle met een QuestionnaireResponse om in te vullen, de Bibliotheken die hun CQL nodig hebben en hun afhankelijkheden. De waarde sets die hun antwoorden gebruiken, reizen in het pakket wanneer ze worden geladen (PUT /fhir/ValueSet/{id}), en $expand lijst hun codes. $log-questionnaire-errors schrijft wat een DTR-app naar de serverlog rapporteert.

Adaptive vragenlijsten: schrijf de hele vragenlijst eenmaal, met SDC's questionnaireAdaptive extensie en enableWhen op de vragen die alleen soms van toepassing zijn. Het pakket geeft de app een lege schil, en elke $next-question oproep voegt de volgende vraag toe die van toepassing is op de antwoorden tot nu toe, totdat er niets meer te vragen is en het antwoord als voltooid wordt gemarkeerd. De volgorde en de vertakking zijn de regels van de verzekeraar; vragen die niet van toepassing zijn, worden nooit getoond.

Inloggen als client: DTR- en PAS-clients bereiken de verzekeraar met SMART Backend Services - een ondertekend JWT dat wordt uitgewisseld voor een token op de autorisatieserver van de verzekeraar. Stel Perfuse in op die server met -smart-issuer (en -smart-jwks als het adres niet vanuit Perfuse kan worden opgelost), en geef -smart-backend-services door zodat het ontdekkingsdocument dit aangeeft. De Inferno DTR-suite passeert op deze manier met Keycloak als autorisatieserver.

Perfuse kan zelf die autorisatieserver zijn: serve -fhir -smart-clients clients.yaml verleent Backend Services-tokens op /auth/token aan de clients in de lijst, elk met de openbare sleutels waarmee het zijn beweringen ondertekent en de systeemscopes die het kan krijgen, en het FHIR-eindpunt accepteert deze. Er is geen separate identiteitsserver nodig voor de machine-naar-machine-clients van een verzekeraar.

Met -smart-users users.yaml ernaast, melden leden en clinici zich aan om apps te autoriseren, wat de Patient Access API nodig heeft: de app stuurt de persoon naar /auth/authorize, ze melden zich aan, een clinici kiest de patiënt, en beiden zien wat de app vraagt en kunnen elk onderdeel daarvan uitschakelen. Een lid krijgt alleen zijn eigen record, ongeacht wat de app vraagt. Elke persoon in het bestand noemt de FHIR-resource die hij is, Patient/… of Practitioner/…, en een wachtwoordhash van perfuse smart hash; het wachtwoord zelf wordt nooit opgeschreven.

Mensen kunnen zich aanmelden bij de identiteitsserver van de organisatie: -smart-oidc oidc.yaml noemt deze (uitgever, client-id en waar het geheim is), en de aanmeldingspagina biedt "Aanmelden met" ernaast naast het wachtwoord. Elke persoon wordt gekoppeld aan het onderwerp van de provider, oidc_subject in het gebruikersbestand, dus het bestand beslist nog steeds wie apps kan autoriseren en welke FHIR-resource hij is; een account die aan niemand is gekoppeld, wordt geweigerd. Codes, vernieuwings tokens en intrekkingen worden in de database opgeslagen, dus een herstart meldt niemand af.

Gebruikers → SMART-apps in de console lijst de geregistreerde apps en mensen, en voegt, bewerkt en verwijdert ze. Elke opslaan wordt gecontroleerd zoals de bestanden bij het opstarten, naar hen geschreven en meteen gebruikt. Een vertrouwelijke app die zonder geheim wordt opgeslagen, krijgt er een, die eenmaal wordt getoond; een wachtwoord wordt daar ingesteld en nooit meer getoond. Het verwijderen van een app of een persoon stopt de toegangstokens die al aan hen zijn uitgegeven onmiddellijk, niet wanneer ze verlopen, en hun vernieuwings tokens met hen.

Reikwijdtes mogen fijnkorrelig zijn, zoals SMART App Launch 2 en US Core deze definiëren: patient/Observation.rs?category=laboratory leest alleen de Observaties die deze zoekopdracht zou vinden. Een toekenning die voor een type wordt gefilterd, past deze filter toe op elke zoekopdracht en elke leesactie van dat type; een ongefilterde toekenning voor het type, of voor *, heft deze op. Een filter dat niet kan worden gelezen, verleent niets in plaats van alles.

16.10 Bepalen van prioritaire autorisatieaanvragen: PAS

serve -fhir -pas -crd-rules rules.yaml beantwoordt Da Vinci PAS 2.2.1 op POST /fhir/Claim/$submit en POST /fhir/Claim/$inquire. De beslissingen komen uit hetzelfde regelbestand als de antwoorden van CRD, dus de volgorde waarin een clinicus wordt meegedeeld dat autorisatie nodig is, wordt bepaald door de regel die dat heeft aangegeven:

  - description: Physical therapy
    codes: ["PT"]                       # matched on the item's productOrService, then the code of the order it requests
    system: https://codesystem.x12.org/005010/1365
    covered: covered
    pa: auth-needed
    pa_decision: approve                # approve, deny or pend; empty: not-covered is denied, no-auth approved, the rest pended
    details:
      - {code: allowed-quantity, value: "6"}   # asked for more, it is certified for six (A6, with the authorised detail)
  - description: MRI
    codes: ["62"]
    pa_decision: approve
    pa_alternative: {system: "https://codesystem.x12.org/005010/1365", code: "4"}  # approved as an X-ray instead (an added item)
  - description: Surgery
    codes: ["2"]
    pa: auth-needed                     # pended for a reviewer, asking for:
    questionnaire: https://payer.example.org/Questionnaire/surgery   # a DTR questionnaire
    pa_attachments: ["18776-5"]         # and documents, by LOINC attachment code

Elk item krijgt een X12-beoordelingsactie: A1 gecertificeerd, A3 niet gecertificeerd, A4 uitgesteld, A6 gewijzigd, C geannuleerd (certificeringstype 3). Een regel die geen dienst noemt, wordt niet beslist maar beantwoord met een fout (X12 901 AG, correct en opnieuw indienen). Het antwoord echoot wat een 278-antwoord echoot — itemvolgnummers, de gevraagde dienstdatum, de datum van de ontmoeting, de transmissie-identificaties met verzender en ontvanger omgedraaid — en geeft elk item het eigen administratienummer van de verzekeraar. Een dienst waarvoor geen regel is opgenomen, wordt uitgesteld en nooit goedgekeurd: een beslissing die niemand heeft opgeschreven, is een beslissing voor een persoon.

Uitgestelde aanvragen wachten op een beoordelaar, die antwoordt met POST /fhir/Claim/$decide:

{"resourceType": "Parameters", "parameter": [
  {"name": "claimResponse", "valueString": "<the ClaimResponse id>"},
  {"name": "decision", "valueCode": "approve"},
  {"name": "reason", "valueString": "Reviewed with the plan of care."},
  {"name": "reviewer", "valueString": "<the reviewer's NPI>"}]}

decision kan ook modify zijn: gecertificeerd, maar niet zoals gevraagd, met quantity (valueDecimal, de gecertificeerde eenheden) en/of alternative (valueCoding, de goedgekeurde dienst in plaats daarvan). Het antwoord zegt dan A6 Gewijzigd, met het gecertificeerde detail of de alternatieve als een toegevoegd item, en een autorisatienummer. item (valueInteger, herhaalbaar) beperkt het besluit tot sommige regels. Het besluit wordt een nieuwe versie van het antwoord, gemarkeerd als beoordeeld door een persoon, en met -fhir-subscriptions wordt het geleverd op het PAS-onderwerp (PASSubscriptionTopic, gefilterd door org-identifier, de identifier van de aanvragende organisatie) als het volledige PAS-antwoordbundel, in dezelfde transactie die het opneemt. $inquire retourneert het huidige antwoord op elke aanvraag die de provider heeft gedaan over dat lid; een andere provider vindt niets. $decide heeft een schrijfreikwijdte nodig; $inquire is een leesactie.

Aanvragen en elke versie van hun antwoorden worden opgeslagen in pas_requests en pas_responses in de database van de server.

16.10.1 De beoordelaarswachtrij

In de webconsole, Payers → CMS-0057 → Reviewer queue toont de uitgestelde verzoeken die het eerst moeten worden behandeld: een versneld verzoek (Claim.priority stat) moet binnen 72 uur na aankomst worden behandeld, een standaardverzoek binnen 7 dagen. Het kiezen van een verzoek toont de lid, de zorgverlener, elke dienst met de aangevraagde eenheden en de status, het gevraagde antwoord en elk ontvangen document, met platte-tekstdocumenten inline weergegeven. Een editor registreert de beslissing daar: goedkeuren, weigeren of wijzigen (gecertificeerde eenheden of een andere goedgekeurde dienst), met een reden en het NPI van de reviewer. Een wijziging moet minder eenheden certificeren dan aangevraagd; evenveel of meer is een goedkeuring en wordt geweigerd als een wijziging. Een goedgekeurde dienst in plaats daarvan begint in het codesysteem van de aangevraagde dienst. Het is dezelfde beslissing die $decide maakt, dus de abonnement van de zorgverlener levert deze. Het lezen van een verzoek en het nemen van een beslissing worden beide geschreven naar het auditlog.

Monitor → Team dashboards → Prior authorization toont, voor de laatste 30 dagen, hoeveel standaard- en versnelde verzoeken binnen de tijdskaders van CMS-0057 zijn beslist, te laat zijn beslist, nog steeds wachten binnen de tijd en nu te laat zijn, met de mediaan tijd om te beslissen en hoe de aangevraagde diensten zijn beantwoord: goedgekeurd, gewijzigd, geweigerd of nog steeds uitgesteld. Deze twee tegels worden rechtstreeks van de verzoeken zelf gelezen, dus ze zijn niet in de Grafana-export van het dashboard opgenomen, die dit in de beschrijving vermeldt.

16.10.2 Ontvangen van de documenten die een in behandeling zijnde aanvraag vraagt

Een uitgestelde reactie vraagt om documenten met een Taak en één CommunicationRequest per document. Een vragenlijst wordt gevraagd zoals PAS het beschrijft: een CommunicationRequest met de enkele LOINC-code 102089-0, onder het spoorcijfer van de regel waarvoor het is (itemTraceNumber, die de ClaimResponse herhaalt; een regel die zonder een is verzonden, krijgt er een). Dat spoorcijfer is de DTR-context: $questionnaire-package met alleen context ingesteld op het, retourneert de vragenlijst. De zorgverlener stuurt wat is gevraagd met Da Vinci CDex $submit-attachment (POST /fhir/$submit-attachment): de TrackingId is de traceerbaarheidsnummer van de aanvraag (de eerste identifier van de ClaimResponse, die ook de Taak is), of een CommunicationRequest-identifier, AttachTo is preauthorization, en MemberId moet de aanvraag-lid zijn. Elk attachment's DocumentReference of QuestionnaireResponse wordt bewaard met de aanvraag en getoond aan zijn reviewer; een document dat aankomt, beslist niets.

16.10.3 Beslissen in een X12-gebruikbeheersysteem

De meeste verzekeraars beslissen over voorafgaande autorisaties in een UM-systeem dat X12 278 ondersteunt. Met -pas-278-url is Perfuse het FHIR-frontend van dat systeem: elke $submit wordt verzonden als één 278-aanvraag (005010X217), elke item een patiëntgebeurtenis. Elke aanvraag bevat wat PAS daarvoor noemt: het type beoordeling (extension-serviceItemRequestType, UM01: gezondheidsdiensten, opname of specialisatiezorg), het type certificering (extension-certificationType, UM02), het type dienst, de plaats van dienstverlening (UM04), het niveau van dienstverlening (extension-levelOfServiceCode, UM06: electief, dringend of spoedeisend; een stat-prioriteit staat in voor dringend), de datum, de opnamedatum en ontslagdatum van een opnamebeoordeling, de diagnoses, de zorgverlener van het zorgteam die de dienst zal uitvoeren, en de procedure en hoeveelheid, als een professionele (SV1) of, op een institutionele claim, een ziekenhuis (SV2) dienstlijn. De actiecode en autorisatienummer van de 278-reactie worden de beoordelingsactie van het item: gecertificeerd, deels of gewijzigd, afgewezen, uitgesteld, geannuleerd of niet in overweging genomen (uitgesteld voor een beoordelaar, met de afwijzingsredenen). Lokale regels worden niet geraadpleegd.

perfuse serve -fhir -pas -pas-278-url https://um.example/x12/278 -pas-278-receiver ACMEUM \
  -pas-278-token-env UM_TOKEN

Een UM-systeem dat eerst uitstelt en later beslist, plaatst zijn latere 278-reactie op POST /fhir/Claim/$decide-278; elk evenement wordt gematcht met zijn verzoek door het tracenummer dat Perfuse heeft verzonden, en wordt beslist zoals $decide zou beslissen. Als het UM-systeem niet bereikbaar is of antwoordt met iets dat geen 278-reactie is, wordt elk item uitgesteld voor een reviewer en wordt de zorgverlener alleen verteld dat; de reden staat in het serverlog.

Vragen die het UM-systeem beantwoordt

Een aanbieder moet met $inquire een autorisatie vinden, ongeacht hoe deze is aangevraagd: per fax, via de portal van de betaler, per telefoon of in een 278 die een andere aanvrager heeft verstuurd. Perfuse houdt alleen de aanvragen bij die via Perfuse zijn verstuurd; het UM-systeem houdt ze allemaal bij. Dus met een UM-systeem dat in real-time antwoordt (elke transport behalve sftp), wordt elke $inquire ook daarheen verstuurd als een 278-vraag (005010X215: BHT02 28, het lid, de aanbieder, het autorisatienummer uit de Claim's insurance.preAuthRef wanneer dit beschikbaar is, en de evenementdatums uit billablePeriod of de servicdatums van de items, anders een jaar voor of na vandaag). Elke autorisatie die het antwoord bevat en die Perfuse niet heeft (gematcht door de tracernummers die het heeft verstuurd en de autorisatienummers die het al heeft gegeven) komt terug als een extra Claim Inquiry Response Bundle: de beslissing van het UM-systeem voor elke serviceregel, het autorisatienummer en de periode, en een notitie waar het is gevonden. Geen Claim wordt gemaakt voor een autorisatie die niemand in FHIR heeft ingediend: de ClaimResponse.request bevat een reden voor ontbrekende gegevens, zoals het profiel van PAS toestaat. Een vraag leest alleen; niets in de eigen records van Perfuse verandert. Als het UM-systeem uitgeschakeld is of antwoordt met een TA1 of 999, krijgt de aanbieder wat Perfuse heeft, en de status van de link zegt waarom. De vorm volgt de 278-vraag companion guides van UnitedHealthcare, Cigna en Blue Cross Blue Shield of Massachusetts; deze is nog niet getest tegen een echt UM-systeem.

Hoe de 278's het UM-systeem bereiken

De connectiviteitsgids van het UM-systeem beschrijft hoe het 278's ontvangt, en -pas-278-transport (Instellingen, Verzekeraars, Utilisatiebeheer koppeling) volgt deze gids:

TransportWat wordt verstuurdAuthenticatie
x12 (standaard)De 278 wordt als application/edi-x12 gepost; het antwoord is de response bodyEen bearer token, OAuth, HTTP Basic, een clientcertificaat
core-soapDe CAQH CORE real-time SOAP 1.2-envelop ( COREEnvelopeRealTimeRequest, payloadtype X12_278_Request_005010X217E1_2, of X12_278_Request_005010X215 voor een onderzoek): Connectivity Rule vC2.2.0 met de payload in de envelop, die de meeste payers en CMS esMD uitvoeren, of -pas-278-core-version C4.0.0 met de payload als een MTOM-bijlagevC2.2.0: een gebruikersnaam en wachtwoord (WS-Security UsernameToken) of een clientcertificaat. vC4.0.0: een clientcertificaat en een OAuth-token
core-mimeDe CAQH CORE vC2.2.0 HTTP MIME-multipartenvelop, de payload als een bestandsonderdeelDe gebruikersnaam en wachtwoord van de envelop, of een clientcertificaat
sftpElke 278 wordt in een map op de SFTP-server van het UM-systeem geplaatst (-pas-278-sftp, -pas-278-sftp-outbound); de antwoorden worden van een andere map verzameld (-pas-278-sftp-inbound, elke -pas-278-sftp-every)Een SSH-sleutel of wachtwoord; de sleutel van de server moet in -pas-278-sftp-known-hosts staan

Een clientcertificaat is -pas-278-cert en -pas-278-key; -pas-278-ca vertrouwt op de certificeringsinstantie van de verzekeraar. OAuth is -pas-278-oauth-token-url, -pas-278-oauth-client-id en het geheim, opgehaald met de client-credentials-grant en bewaard totdat een minuut voor het verloopt. Wachtwoorden, tokens en geheimen zijn nooit vlaggen: elk wordt benoemd door een omgevingsvariabele (-pas-278-password-env, -pas-278-token-env, -pas-278-oauth-secret-env, -pas-278-sftp-password-env), of getypt in het instellingenscherm, waar het in het instellingsbestand wordt bewaard (alleen leesbaar door het serversaccount) en nooit meer wordt getoond.

UM_PASSWORD=... perfuse serve -fhir -pas -pas-278-transport core-soap \
  -pas-278-url https://um.example/CORE/RealTime -pas-278-receiver ACMEUM \
  -pas-278-user perfuse -pas-278-password-env UM_PASSWORD

Via SFTP wordt elke aanvraag in de wacht gezet totdat het antwoord arriveert: het 278-antwoord beslist over de items, en Perfuse plaatst een 999 die het accepteert in de uitgaande map. Een bestand dat niet kan worden gelezen, blijft in de inkomende map voor een persoon en wordt aangeboden bij de volgende lezing.

Wanneer het UM-systeem een aanvraag niet kan lezen

Een UM-systeem dat een 278 niet kan lezen, antwoordt met een TA1 (de envelop) of een 999 (de transactie) in plaats van een beslissing. Perfuse leest welke en wat het zegt, zet elke item in de wacht ("utilisatiebeheer kon de aanvraag niet lezen"), en registreert het. Verzekeraar, CMS-0057, Reviewer-wachtrij toont de koppeling: wat de afgelopen zeven dagen is verzonden, elke uitwisseling met zijn controle-nummer, en wat er van is geworden (beantwoord; bevestigd, antwoord te komen; afgewezen, met het segment, element en code van de 999; niet bereikt). Elke uitwisseling heeft zijn eigen controle-nummer, één meer dan de laatste, dat is wat een TA1 of 999 noemt wanneer het antwoordt.

16.10.4 Beslissen over de klinische bewijs, met een beslissingsdienst

Een regelbestand beslist op basis van dienstcode: een code heeft geen autorisatie nodig, is niet gedekt of gaat naar een reviewer. Of deze patiënt voldoet aan de criteria hiervoor, is een andere vraag, die wordt beantwoord vanuit de voorwaarden, vragenlijstantwoorden en documenten die de zorgverlener met het verzoek heeft verzonden. Met -pas-decider-url wordt elk item dat de regels naar een reviewer sturen, eerst naar een beslissingsdienst gestuurd, zoals Vaglio, die hetzelfde PAS-verzoekbundle leest via Perfuse's gepubliceerde pas-package. Een openbare Vaglio, alleen voor gefabriceerde verzoeken, draait naast Perfuse's testinstantie op https://vaglio.perfuse.health:8443 (aanmelden als demo, wachtwoord try-vaglio-demo; deze kan alles bekijken en niets wijzigen): elke beslissing daar heeft zijn bewijs, een eenvoudige brief en een ontvangstbewijs dat iedereen kan controleren.

perfuse serve -fhir -pas -crd-rules payer-rules.yaml -pas-decider-url https://vaglio.example/api/pas/decide \
  -pas-decider-token-env VAGLIO_TOKEN

De URL moet https zijn, of gewoon http naar deze machine (localhost, 127.0.0.1), omdat deze een patiëntendossier en het token bevat. Vaglio zelf antwoordt alleen via https; wanneer het een certificaat van zijn eigen autoriteit gebruikt, moet u die autoriteit doorgeven met -pas-decider-ca DATA/tls/ca.crt (of elke interne autoriteit van de verzekeraar waarvan het certificaat van de dienst afkomstig is). De dienst krijgt het verzoekbundle als de zorgverlener het heeft verzonden, POST <url>?item=<sequence> (application/fhir+json), en antwoordt {"decision": "approve" | "deny" | "pend", "why": "...", "requested": ["..."]}, of 404 wanneer het niets voor dat item beslist, wat de antwoord van de regels laat staan. why is de procesnotitie van de reactie en is vereist voor een weigering, die anders wordt uitgesteld; requested wordt aan de zorgverlener meegedeeld als de informatie die een uitgesteld verzoek nodig heeft. Een uitstel kan ook "questionnaire": "<canonical>" en "attachments": ["<LOINC>", ...] bevatten, die worden gevraagd in de reactie's CDex Taak en CommunicationRequests naast welke DTR-vragenlijst of attachments de regel vraagt (de regel's vragenlijst wint, omdat een Taak erom vraagt; een code die niet de vorm van LOINC heeft, wordt verwijderd en gelogd). Een regel die goedkeurt of weigert is het dekkingsbeleid van de verzekeraar en wordt niet naar de dienst gestuurd. Een fout, een time-out of een antwoord dat niet een van de drie beslissingen is, stelt het item uit voor een reviewer, met de reden in het serverlog: niets hier verandert een fout in een goedkeuring. Dit kan niet worden gecombineerd met -pas-278-url, waar het UM-systeem elk item antwoordt.

Advies voordat u indient. Met -crd-advisor-url naast -crd-rules, vraagt CRD ook een beslissingsdienst wat een voorafgaande autorisatieverzoek voor elke bestelling die dit nodig heeft, zou worden meegedeeld als het dossier er zo uitziet, en toont het antwoord als een extra kaart: "Voordat u indient: een verzoek hiervoor zou nodig hebben: ...", of "zou worden goedgekeurd", met wat nog nodig is, de vragenlijst die ernaar vraagt, en wat het zou goedkeuren. Vaglio antwoordt op /api/pas/advise, met hetzelfde token en de autoriteit als hierboven:

perfuse serve -fhir -pas -crd-rules payer-rules.yaml \
  -crd-advisor-url https://vaglio.example/api/pas/advise -crd-advisor-token-env VAGLIO_TOKEN

CRD verzendt POST <url> met {"service": {"system": "...", "code": "..."}, "resources": [ ... ]}, de resources zijn de prefetch van de haak (de patiënt eerst, de dekking links uit), en leest {"decides": true, "answer": "approve" | "pend" | "deny", "summary": "...", "missing": [...], "questionnaire": "...", "toApprove": [[...]], "policyTitle": "..."}. Het is advies en verandert niets: de dekking-informatie, de andere kaarten en de PAS-beslissing zijn wat de regels zeggen. Het wacht maximaal drie seconden en geen antwoord, een fout of "decides": false laat de reactie exact zoals het is zonder het. Perfuse heeft nooit een beslissingsdienst nodig.

Het verzoek bevat X-PAS-Request-Id, de id waarmee het antwoord bekend is. Een dienst met zijn eigen reviewers die een item in behandeling neemt, kan later een beslissing sturen, net zoals elke reviewer dat doet: Claim/$decide met die id als claimResponse, de sequentie van het item en de beslissing en reden. De abonnement van de provider levert het af zoals het zou doen met een reviewer in de wachtrij.

Een abonnement met id-only-inhoud vertelt de provider welk antwoord is gewijzigd zonder te zeggen wat het is: de focus van de notificatie is Bundle/<id>. GET /fhir/Bundle/<id> retourneert het laatste PAS-antwoordbundle, GET /fhir/Bundle/<id>/_history/<n> de versie die de notificatie heeft verstuurd, en GET /fhir/ClaimResponse/<id> de ClaimResponse alleen. Een token dat is gekoppeld aan één patiënt, wordt meegedeeld dat deze niet bestaat, net als bij elk record buiten de patiënt.

Geverifieerd met de officiële Inferno PAS Server v2.2.1-suite (zie verificatie). Niet verzonden, hoewel PAS aangeeft dat ze verplicht zijn: ClaimResponse.adjudication met een reviewactie, ClaimResponse.extension:authorizedProvider en ClaimResponse.item.extension:communicatedDiagnosis, omdat de extensies die ze nodig hebben niet zijn toegestaan op die plaats door hun eigen context in PAS 2.2.1 en de validator wijt een respons die ze bevat; en request.extension:DataAbsentReason, omdat Perfuse altijd de aanvraag kent. De 278's die naar een utilisatiebeheersysteem worden verzonden (hierboven), worden gecontroleerd tegen de eigen aanvraagvoorbeelden van PAS 2.2.1, de gepubliceerde esMD 278-voorbeelden van CMS en een 278-controleur die is geschreven op basis van openbare begeleidingsgidsen, en elke transport tegen een stand-in UM-systeem dat is geschreven op basis van CAQH's Connectiviteitsregels (zie verificatie); nog niet tegen een echt UM-systeem of clearinghouse, en niet CORE-gecertificeerd. Niet geïmplementeerd: bijlagen die worden teruggestuurd met CDex.

Een regelbestand wordt gecontroleerd op CRD's eigen invariante bij het laden: een vraaglijst heeft documentatie nodig, een dienst die niet is gedekt kan geen autorisatie nodig hebben, satisfied hoort bij één geval en niet bij een regel, en alles wat conditioneel is, moet een reden geven.

Niet geverifieerd: de export en het lidmaatschapsvergelijken met de implementatie van een andere payer, de metrieken tegen de gepubliceerde cijfers van een payer, en CRD tegen een echte EHR's CDS Hooks-client.

16.11 Versturen van voorafgaande autorisatieaanvragen naar een betaler (voor zorgverleners)

Alles hierboven beantwoordt aanvragen, als een betaler. De kant van een zorgverlener is omgekeerd: een EHR of een DTR-app bouwt een Da Vinci PAS-aanvraagbundle, en iets moet deze naar de betaler sturen, het antwoord bewaren en doorgeven. Een pas-bestemming doet dat.

name: prior-auth-out
dataType: raw
source:
  type: http
  http:
    listen: 127.0.0.1:8095
    path: /pas
destinations:
  - name: acme-health
    type: pas
    pas:
      payer: https://pas.acme-health.example/fhir
      bearer_token: ${ACME_PAS_TOKEN}     # or auth: { type: client_credentials, token_url, client_id, client_secret }
      results_to: pas-answers             # optional: a channel that takes each answer back to the EHR

Elk bericht moet een complete PAS-aanvraag-Bundle op een onbewerkte kanaal zijn. Perfuse plaatst het ongewijzigd op {payer}/Claim/$submit: de payer beslist over de Claim samen met de patiënt, dekking en ondersteunende resources in de Bundle, en een Claim die opnieuw is opgebouwd uit een samenvatting zou deze verliezen. Buiten deze machine moet het adres van de payer https zijn.

Een beslissing is een afgeleverd verzoek, wat er ook in staat. Een goedkeuring, een weigering en een uitstel worden allemaal geregistreerd en geen van beiden wordt opnieuw geprobeerd, omdat het opnieuw proberen van een weigering hetzelfde verzoek twee keer indient. Wat de aflevering niet slaagt en opnieuw wordt geprobeerd, is een betaler die geen beslissing heeft genomen: een foutstatus, een OperationOutcome (de tekst is de fout) of een ClaimResponse waarvan het resultaat error is. Het beslissing wordt gelezen item voor item van de PAS-beoordelingsactiecodes (X12 306: A1 goedgekeurd, A2 gedeeltelijk, A3 geweigerd, A4 uitgesteld, A6 gewijzigd); een reactie zonder code wordt vermeld als 'geen beslissingscode' in plaats van als een goedkeuring beschouwd. Een weigering zonder reden wordt geweigerd omdat deze niet voldoet aan CMS-0057.

Het antwoord van de betaler is het antwoord van de bestemming, dus Inspecteer het antwoord kan het beoordelen, en results_to geeft het door aan een ander kanaal. Elke aanvraag wordt vermeld in CMS-0057, Aanvragen verzonden naar betalers: wanneer deze werd verzonden, de patiënt, de dienst, de beslissing en de referentie van de betaler (preAuthRef), die een latere vraag noemt. De lijst wordt bewaard in prior-auth.json naast de database (maximaal 10.000 aanvragen; de oudste besliste gaan eerst, een lopende nooit), en elke huurder ziet alleen de zijne.

Geverifieerd tegen de HL7 Da Vinci PAS-betalerreferentie-implementatie (dockerimage hlseven/davinci-prior-auth): een aanvraag die via een actief kanaal wordt verzonden, wordt door deze gepend met zijn referentie, en het antwoord verschijnt op het scherm (zie verificatie). Nog niet getest tegen een productiebetaler. Nog niet gebouwd: het opvolgen van een gepende aanvraag met $inquire, of het ontvangen van het latere antwoord van de betaler via abonnement; een kanaal kan beide vandaag doen met een http- of fhir-bestemming.

16.12 CMS Aligned Networks

Het CMS Interoperability Framework (CMS Health Technology Ecosystem) vraagt gezondheidsdatanetwerken om zelf te verklaren dat ze aan 26 criteria voldoen en om te worden opgenomen als CMS Aligned Networks; EHR's, providers, payers en apps verbinden zich met deze netwerken. Criteria 13 tot en met 16 zijn sinds 4 juli 2026 van kracht: FHIR API's op US Core met een volledige CapabilityStatement en Bulk Data, documenten als mensleesbare FHIR-bijlagen, afspraak- en ontmoetingsnotificaties via FHIR Subscription, en een recordlocator.

Beheer › CMS Aligned Network toont elk criterium met wat Perfuse hiervoor biedt en waar deze server staat, gelezen van wat hier is ingeschakeld:

StatusBetekenis
Ready hierPerfuse biedt het aan en het is ingeschakeld.
Ready, met een lacuneHet is ingeschakeld en een deel van het criterium valt erbuiten (genoemd op het scherm).
Gebouwd, niet ingeschakeldPerfuse biedt het aan; het scherm noemt de instelling of vlag die het inschakelt.
Uw taakHet deel van de organisatie: een overeenkomst, een certificering, publicatie naar het National Provider Directory.
Niet gebouwdSoftware zou het doen, en Perfuse doet het niet.

Wat de vier die van kracht zijn nodig hebben van deze server:

CriteriumIn PerfuseInschakelen
13 FHIR-API's, US Core, Bulk DataHet FHIR-eindpunt met zijn CapabilityStatement en $export-fhir, -fhir-bulk-export
14 Documenten als FHIR-bijlagenDocumentReference met Binary en IHE MHD via het XDS-registratiesysteem-fhir (MHD ook -xds)
15 Ontmoetings- en afsprakenotificatiesOnderwerpbasede abonnementen (R5 Backport voor R4) van ADT- en SIU-feeds-fhir-subscriptions
16 RecordlocatorHet XDS.b-registratiesysteem, XCA voor andere gemeenschappen, PIXm-xds, -xds-home-community

Het scherm is een werkblad voor de verklaring, niet een certificering: CMS beoordeelt netwerken die het vermoedt niet aan de criteria voldoen, en de tekst van het kader is de autoriteit. Nog niet gebouwd: open kwaliteitsgatqueries (criterium 8), een payers query voor een claims ontmoetingsgegevens (9), rapportage van querymetrieken aan het National Provider Directory (19), controle van providers tegen dat directory (6), lezen van mobiele rijbewijzen of digitale verzekeringskaarten (3, 23), en afdwingen van een algemeen toestemmingsbeleid voor elke leesactie (5). IAL2-identiteitsverificatie is van de identiteitsdienst; Perfuse accepteert de tokens van de dienst die u kiest.

17 Beveiliging

Perfuse behandelt klinische gegevens. Dit hoofdstuk beschrijft wat het daarover doet en wat het aan u overlaat.

17.1 Transportsbeveiliging

TLS op het webinterface is geconfigureerd met -tls-cert en -tls-key. Zonder deze is het interface gewoon HTTP, wat acceptabel is op een lusbackadres voor een eerste blik en nergens anders — het bevat referenties en berichtinhoud, beide leesbaar op de draad.

TLS op kanaaltransporten is per bron en per bestemming, onder een tls-blok. De beschikbare instellingen zijn te vinden in de bron en bestemming verwijzingen.

insecure_skip_verify accepteert elk certificaat. Het bestaat omdat ziekenhuissystemen routinematig certificaten presenteren die niet kunnen worden geverifieerd, en weigeren om verbinding te maken zou weigeren om te integreren. Het is genoemd om opvallend te zijn, en het gebruik ervan betekent dat de verbinding is versleuteld maar niet is geauthenticeerd — u heeft bescherming tegen passieve interceptie en geen tegen een tussenliggende server.

Een ongeverifieerde TLS-verbinding is niet hetzelfde als een geverifieerde, en het onderscheid is het waard om ergens op te nemen waar uw auditors het zullen vinden. De betere oplossing is bijna altijd om het certificaat van de andere kant te verkrijgen en het expliciet te vertrouwen in plaats van alles te vertrouwen.

17.2 Authenticatie en rollen

Gebruikers worden in de database opgeslagen. Elk heeft een van de vijf rollen, en elke rol omvat alles in de rollen erboven:

RolKan
MonitorZien of alles werkt: kanaalstatus, tellingen, flowmap, waarschuwingen, dashboards, metrieken en diepte van de wachtrij. Geen berichtinhoud, kanaalbestanden of berichten in de wachtrij.
ViewerOok lezen van berichten, kanaalbestanden, traceringen en activiteitenlogboek.
OperatorOok opnieuw verzenden: opnieuw verwerken van een bericht, opnieuw afspelen van een kanaal en opnieuw proberen van berichten in de wachtrij.
EditorOok maken en wijzigen van kanalen, en vergelijkingen uitvoeren.
AdminOok starten en stoppen van kanalen, leegmaken van wachtrijen, en beheren van personen, tokens en serverinstellingen.

Een zesde rol, Platform, behoort tot degene die een gedeelde server beheert: het maakt tenants aan en stelt hun limieten vast, en heeft geen kanalen van zichzelf.

Monitor is voor een helpdesk of voor een operationeel scherm op een muur: alles wat nodig is om te zien of een feed is gestopt, en niets dat een patiënt noemt. Viewer kan berichtinhoud lezen, wat klinische gegevens zijn; het is een rol met lage privileges voor *configuratie*, niet voor privacy. Operator scheidt het hersturen van een mislukte levering 's nachts van het veranderen van wat een feed doet: de persoon die opnieuw verstuurt, hoeft niet in staat te zijn om het kanaal opnieuw te schrijven.

17.2.1 Herhaalde verkeerde wachtwoorden

Verkeerde wachtwoorden en mislukte passkey-aanmeldingen worden geteld per adres van waaruit de verbinding wordt gemaakt, en na een paar opeenvolgende mislukkingen moet dat adres even wachten voordat het opnieuw kan proberen (het antwoord is 429, met Retry-After). Accounts worden niet geblokkeerd op basis van naam, because dat zou het iedereen mogelijk maken om een beheerder opzettelijk te blokkeren.

Het adres is het adres van de verbinding zelf, nooit het adres dat een aanvraag claimt in X-Forwarded-For, dat de verzender schrijft. Achter een reverse proxy op dezelfde machine gebruikt Perfuse het laatste X-Forwarded-For-item in plaats daarvan, het item dat de proxy toevoegde, zodat elke client nog steeds afzonderlijk wordt geteld. Een proxy op een andere machine bereikt Perfuse vanaf één adres, en alle clients van die proxy delen één telling: limiet aanmeldingen bij die proxy.

17.2.2 Kanaalgroepen

Een persoon (of een API-token) kan worden beperkt tot bepaalde kanaalgroepen: ze zien en handelen dan alleen naar de kanalen waarvan group een van de hunne is. Dit is de opzet van een ziekenhuisgroep op één server, waarbij elke faciliteit zijn eigen feeds heeft en een centraal team, zonder beperking, voor alle feeds zorgt. Rhapsody noemt dit een locker.

De limiet geldt overal tegelijk, omdat deze wordt toegepast op het verzoek in plaats van door elk scherm te worden onthouden: de kanaallijst, het dashboard en flowmap, berichten en hun zoekfunctie, tellingen en grafieken, de wachtrij, waarschuwingen, metrieken, certificaten, contracten en code-setgebruik. Een kanaal buiten de groepen van de persoon bestaat niet voor hen; het vragen naar een kanaal bij naam levert *niet gevonden* op, dus de naam wordt ook niet bevestigd. Een kanaal zonder groep wordt alleen door personen met geen limiet gezien.

Het opslaan van een kanaal houdt het binnen de groepen van de persoon: ze kunnen geen kanaal maken in een andere groep, of een kanaal uit hun eigen groep verplaatsen. Wat elke faciliteit deelt - codetabellen, scriptbibliotheken, prioritaire autorisatiebeslissingen - kunnen ze lezen maar niet veranderen. Serverbrede cijfers (prioritaire autorisatie, tokengebruik, tunnels) worden alleen getoond aan personen zonder limiet, en ook metrieken en waarschuwingen over de hele server in plaats van een kanaal.

Een beheerder die is beperkt tot groepen is de beheerder van een faciliteit. Zij beheren de personen en tokens van hun groepen, starten en stoppen hun kanalen en legen hun wachtrijen. Een collega die zij toevoegen krijgt hun groepen, tenzij zij enkele daarvan noemen, zij kunnen geen groep geven die zij niet hebben, en zij zien of wijzigen nooit iemand zonder beperking. Alles wat een beheerder nog meer kan doen, verandert de hele server - instellingen, aanmelding, opnieuw opstarten, waarschuwingsregels, branding, vloot, de SMART-server - en wordt voor hen geweigerd.

Groepen worden ingesteld in Gebruikers (en voor tokens in Tokens), als een door komma's gescheiden lijst. Elke wijziging wordt opgenomen in het activiteitenlogboek en gaat in bij de volgende aanvraag van de persoon.

Een andere rol in elke groep

Een persoon kan een andere rol hebben in elke van hun groepen: lab=editor, adt in Gebruikers bewerkt de kanalen van het lab en heeft de rol die ernaast is gekozen - zeg viewer - in de opnamegroepen. Zij zien de kanalen van beide groepen op elk scherm. Opslaan, starten of opnieuw verzenden van een kanaal in een groep waar hun rol te laag is, wordt geweigerd met de rol die zij daar hebben; het doet alsof het kanaal ontbreekt, omdat zij het kunnen zien. Hun rol bovenaan het scherm is de sterkste die zij hebben, die de schermen opent die die rol gebruikt, en elke actie op die schermen is nog steeds beperkt tot de groepen waar zij die rol hebben.

Alleen personen die zijn beperkt tot kanaalgroepen kunnen een rol per groep hebben. Iemand die elk kanaal kan zien, heeft één rol, omdat 'bewerker van de kanalen van het lab' voor iemand zonder beperking bewerker van alles zou zijn dat bij geen groep hoort, en van de serverbrede pagina's. Een beheerder van een faciliteit kan een rol per groep alleen geven in de groepen die zij beheren, en nooit boven hun eigen rol daar.

17.3 Wie de FHIR-eindpunt mag bellen

De FHIR-eindpunt (serve -fhir) controleert een van twee soorten tokens:

worden beperkt tot FHIR-groepen. Dit is de standaardinstelling wanneer geen SMART-autorisatieserver is geconfigureerd.

token heeft scopes, en het eindpunt houdt elke aanvraag ernaar bij.

Met SMART geconfigureerd, worden alleen SMART-tokens geaccepteerd, zodat elke beller wordt gehouden aan zijn scopes. Een API-token heeft een rol en geen scopes: een viewer-token kan elk patiëntendossier lezen. Een betaler die SMART heeft ingeschakeld om elke app te beperken tot wat het is toegekend, zou geen manier moeten hebben om binnen te komen die niet is beperkt.

Sommige sites hebben zowel hetzelfde nodig - een interne claimsfeed die een API-token heeft en geen SMART-client, naast member-apps die zich aanmelden via SMART. Voor die sites laat Instellingen → FHIR → Perfuse API-tokens accepteren naast SMART-tokens (-fhir-api-tokens bij opstarten) API-tokens ook toe. Het is standaard uitgeschakeld, het gaat in bij de volgende aanvraag in beide richtingen, en het wijzigen ervan wordt geschreven naar het auditlogboek. Een token wordt onderscheiden door zijn vorm: een SMART-token is een ondertekend JWT, en een API-token is dat nooit, dus een wordt nooit gecontroleerd als de andere. Waar u kunt, geef een dergelijk systeem een SMART Backend Services-client in plaats daarvan, met alleen de systeemscopes die het nodig heeft.

17.3.1 Een FHIR-eindpunt dat openstaat voor vreemden

Een openbare testserver verstrekt referenties die kunnen schrijven, omdat het testen van voorafgaande autorisatie of abonnementen schrijfmogelijkheden vereist. Twee limieten voorkomen dat één client het voor iedereen verpest, beide onder Instellingen → FHIR en beide standaard uitgeschakeld:

Een eigen eindpunt van een ziekenhuis heeft geen van beide nodig.

17.4 AI-agents: de MCP-server

Met Instellingen › Beveiliging › AI-agents (MCP) ingeschakeld (of serve -mcp), serveert Perfuse het Model Context Protocol op /mcp, zodat een AI-agent zoals Claude, ChatGPT of een IDE-assistent kan vragen wat er gebeurt. Het is standaard uitgeschakeld en uitschakelen stopt elke agent bij de volgende oproep.

Een agent verbindt met een API-token van Beheer › Gebruikers › Machine-referenties als een bearer-token, nooit met een persoonlijke browsersessie (dat wordt geweigerd, dus een agent handelt nooit met de volledige toegang van een persoon). Een clientconfiguratie ziet er zo uit:

{ "mcpServers": { "perfuse": { "type": "http", "url": "https://perfuse.example/mcp",
    "headers": { "Authorization": "Bearer <token>" } } } }
ToolRolWat het doet
server_status, list_channels, queue, alertsmonitorOf dingen werken, zonder berichtinhoud
get_channel, search_messages, get_message, find_patient, fhir_searchviewerKanalen, berichten (met inhoud), een patiëntenberichten over formaten, een FHIR-zoekopdracht
retry_delivery, reprocess_messageoperator, en mcp:writeOpnieuw proberen een gekoppelde levering, een bericht opnieuw verzenden via zijn kanaal
start_channel, stop_channeladmin, en mcp:writeStart of stop een kanaal

Elk hulpmiddel wordt beantwoord door dezelfde route of FHIR-zoekopdracht die het scherm van een persoon gebruikt, aangeroepen met het token van de agent, dus het token bepaalt wat het ziet, net zoals het scherm van de console; en fhir_search krijgt de toegang van het token op het FHIR-eindpunt (dat API-tokens mogelijk helemaal weigert; zie het FHIR-gedeelte hierboven). Een agent wordt alleen de hulpmiddelen aangeboden die het token mag gebruiken. Lezen is standaard: een hulpmiddel dat iets verandert, heeft ook de mcp:write-scope van het token nodig ("Laat een AI-agent handelen met dit" bij het uitgeven van het token), dus een token dat is uitgegeven voor een rapportage-agent kan niet worden overgehaald om te handelen door een prompt. De antwoorden van een monitortoken hebben de berichtinhoud verwijderd, wat een route ook teruggeeft.

Every call is in Activity as mcp.tool with the token's name, the tool, its arguments and the outcome (ok, refused, invalid, rate-limited or the HTTP status); mcp.connect records which client connected. Each token may make 60 tool calls a minute (Tool calls a minute from one token); over that, a call is answered with an error the agent can read, and nothing is done. A request from a browser page on another origin is refused, which MCP asks of a server to stop DNS rebinding. The transport is MCP's Streamable HTTP, answered as JSON with no event stream; protocol versions 2025-06-18, 2025-03-26 and 2024-11-05 are accepted. Messages and FHIR resources hold patient data: an agent's answers go to whatever model it runs on, so give a token to an agent only where that model is allowed to see them, and give it the lowest role that does the job.

17.5 Een demonstratieaccount

serve -demo-account demo:PASSWORD maakt een gedeelde account aan voor een openbare demonstratieserver en het aanmeldingscherm toont de gebruikersnaam en het wachtwoord met een knop die aanmeldt met deze gegevens. Het account is een kijker, dus het kan alles bekijken en niets wijzigen. In tegenstelling tot elke andere kijker mag het ook de beheerschermen van de beheerders openen (gebruikers, machinetoegangstokens, instellingen, gegevensbescherming, de peers van de vloot), alleen-lezen: een demonstratie wordt beoordeeld op basis van de schermen. Het leest ze als een kijker kanalen leest, met elke referentie die wordt weergegeven als ingesteld of niet, nooit de waarde, en elke wijziging wordt geweigerd. Het mag ook de controles indrukken die niets wijzigen en niets buiten de server bereiken: een scripts controle en de validatie en parseren van de kanaaleditor. Het kan het wachtwoord niet wijzigen of een paswoord toevoegen, omdat de eerste bezoeker die een van beide doet, iedereen die daarna komt, buitensluit. Elke start stelt het terug in als kijker met het gepubliceerde wachtwoord. Het wachtwoord moet minstens 12 tekens lang zijn, net als elk ander. Gebruik het alleen op een server met testgegevens: iedereen die de aanmeldingspagina leest, kan elk bericht op de server lezen.

17.6 Audit

Configuratieveranderingen, aanmeldingen en toegang tot berichtinhoud worden geregistreerd met wie, wat en wanneer.

Het auditlog staat in dezelfde database als de berichten. Dat is handig en het is een beperking: iemand die de database kan wijzigen, kan het auditlog wijzigen. Als uw vereisten een tamper-evident auditlog omvatten, moet het log worden verzonden naar een append-only-locatie, en de loguitvoer van Perfuse is de manier om dat te doen.

17.7 Geheimen in configuratie

Wachtwoorden, toegangs codes en sleutels verschijnen in kanaalconfiguratie, wat betekent dat ze in de YAML-bestanden staan.

Twee consequenties. De bestanden moeten bestandssysteemrechten hebben die overeenkomen met de inhoud ervan, en als ze in een versiebeheersysteem zitten — wat overigens aanbevolen wordt — bevat de repository referenties en moet dienovereenkomstig worden behandeld.

Waar een waarde een geheim is, wordt deze door de interface weergegeven als een geheim en retourneert de API deze niet meer nadat deze is opgeslagen. Dat beschermt deze tegen het lezen over iemands schouder of het lekken in een screenshot. Het beschermt het bestand niet.

17.8 Wat in de database zit

De berichtenopslag bevat berichten zoals ontvangen, wat voor een klinische feed patiënt-identificeerbare gegevens betekent. Deze moet op een versleutelde opslag staan, worden gespiegeld als klinische gegevens met de retentie die dat impliceert, en toegangsbeperkingen hebben op bestandssysteemniveau, evenals via de eigen rollen van Perfuse.

cleanup.periodDays beperkt hoe lang het wordt bewaard. Zie de berichtenopslag voor de spanning tussen dit en voldoende geschiedenis voor ritmegevoelige waarschuwingen.

17.9 Gegevensbescherming (GDPR en UK GDPR)

Het Gegevensbescherming-scherm (Beheer, alleen voor beheerders) beantwoordt een persoon zijn verzoeken onder de GDPR en de UK GDPR. Het neemt geen beslissingen namens de verantwoordelijke: of een verzoek moet worden toegekend en of een uitzondering van toepassing is, is de beslissing van de verantwoordelijke, opgenomen bij het verzoek.

Vinden van wat wordt vastgehouden. Een persoon wordt geïdentificeerd door identificatoren: system|value (een NHS-nummer, een MRN met zijn toewijzingsautoriteit) of een nummer op zich. Met een patiëntindex worden deze uitgebreid tot elk nummer van elk record dat is gekoppeld aan dezelfde persoon, zodat een verzoek dat een ziekenhuisnummer noemt, de records vindt die zijn opgeslagen onder de anderen. Bekijk wat wordt vastgehouden zoekt vervolgens elke winkel die patiëntgegevens bevat:

OpslagGevonden door
Berichtende identiteitsindex (Instellingen → Gegevens → Index patiëntidentificatoren); zonder deze kunnen berichten niet worden gevonden op basis van identificatoren
De leveringswachtrijhet lezen van elke gewachte berichtidentificator
De FHIR-opslagde Patiëntbronnen die een identificator bevatten en elke bron wiens geïndexeerde verwijzingen ernaar verwijzen
Eerder verzoek om toestemmingde identificatoren van de patiënt van het verzoek
De patiëntenindexde identificator, of de EUID

Wat het niet kan bereiken, zegt het: sporen die naar een collector worden gestuurd (-trace-endpoint), het auditlogboek (bewaard: het is het record van wie wat deed, inclusief dit verzoek), en back-ups.

Verzoeken. Een verzoek wordt opgenomen met zijn soort (toegang, Artikel 15; overdraagbaarheid, Artikel 20; verwijdering, Artikel 17; beperking, Artikel 18), wie het is vanuit de records van de verantwoordelijke, de identificatoren en een notitie (hoe de identiteit werd bevestigd, een verlenging en zijn reden). Het moet binnen een maand na ontvangst worden beantwoord (Artikel 12(3)); een te late wordt in rood getoond.

Een afgesloten verzoek houdt alleen de laatste tekens van de persoonlijke nummers: het blijft als het record van een antwoord zonder een andere kopie van deze te zijn. Elke stap staat in het auditlogboek met de nummers gemaskeerd.

Juridische retentie. Een retentie noemt een persoon door identificatoren, met zijn reden en een optionele einddatum. Zolang het van kracht is, wordt een verwijdering rechtstreeks geweigerd, en de retentieperiode van de berichtenopslag spaart de berichten van de persoon (records en bodies) tot de retentie wordt opgeheven.

Back-ups en het verwijderingsregister. Een back-up die vóór een verwijdering is gemaakt, bevat nog steeds wat werd verwijderd totdat deze verloopt. Elke verwijdering wordt geschreven naar een register: wanneer, door wie, goedgekeurd door wie, hoeveel uit elke opslag is verwijderd, en de identificatoren van de persoon als gesaldeerde SHA-256-hashes in plaats van in duidelijke tekst. Na het herstellen van een back-up, Verwijderingen opnieuw toepassen heeft de identificatoren die de herstelde opslag bevat, gehasht met elk zout en de persoon die het register noemt, verwijderd. Korte nummers kunnen worden gevonden vanuit hun hashes door elke waarde te proberen, dus het register is zelf persoonsgegevens en wordt bewaard met de bescherming van de database.

Retentie. Het scherm toont hoe lang elk type record hier wordt bewaard en wat het verandert: berichtenrecords en -bodies door hun retentievensters, de wachtrij totdat deze wordt afgeleverd of verwijderd, de FHIR-opslag, eerdere autorisatieverzoeken en de patiëntindex totdat deze worden verwijderd (klinische records worden niet op een schema verwijderd), het auditlogboek bewaard.

Verwerkingsregister (Artikel 30). Verwerkingsregister downloadt, als Markdown of CSV, wat deze server weet over het verwerkingsregister: de verantwoordelijke, de functionaris voor gegevensbescherming en waar de gegevens worden opgeslagen (Instellingen → Gegevens → Gegevensbescherming), de bewaartermijn van elk type record en één verwerkingsactiviteit per kanaal met wat het ontvangt, van waar, naar welke bestemmingen en de hosts waarnaar het verzendt. De doeleinden, wettige gronden en categorieën van betrokkene worden overgelaten aan de verantwoordelijke om in te vullen en dit te vermelden. Een CSV-cel die begint met =, +, - of @ wordt geschreven met een leidende apostrof, zodat een spreadsheet deze niet uitvoert.

Waar de gegevens worden opgeslagen. Waar de gegevens worden opgeslagen (Instellingen → Gegevens → Gegevensbescherming) specificeert, in woorden die een toezichthouder kan controleren, waar de server, de database en de back-ups worden uitgevoerd; het scherm Gegevensbescherming en het record tonen dit. Een concept voor een gegevensverwerkingsovereenkomst voor organisaties die BioDream host is te vinden in docs/legal/dpa-template.md; het is een concept voor een advocaat, niet een juridisch advies.

De API is /api/privacy (samenvatting), /api/privacy/find, /api/privacy/requests (en /{id}/approve, /{id}/export, /{id}/erase, /{id}/close), /api/privacy/holds, /api/privacy/reapply en /api/privacy/register.

17.10 Huurtussen

Een tenant is een isolatiegrens: kanalen, berichten, gebruikers en instellingen horen bij één tenant, en niets gaat hier overheen.

Dit bestaat voor een dienstverlener die feeds uitvoert voor meerdere praktijken. Gebruik het niet om afdelingen binnen één organisatie te scheiden die elkaars verkeer moeten kunnen zien: de isolatie is echt en er is geen overzicht tussen tenants. Gebruik hiervoor kanaalgroepen (hierboven), die de mensen van één organisatie scheiden terwijl een centraal team alles kan zien.

17.10.1 Limieten

Een platformbeheerder stelt de limieten voor elke tenant in in Tenants, zodat één klant de rest van een gedeelde server niet kan overbelasten. Laat een limiet leeg voor geen limiet.

Geen van hen verliest een bericht. Boven de tarief- of opslaglimiet wordt een ontvangen bericht geweigerd op de manier waarop een bezette ontvanger een bericht weigert, voordat iets wordt opgeslagen of geleverd: MLLP krijgt geen bevestiging (geen afwijzing, die sommige verzenders interpreteren als 'verzend niet opnieuw'), HTTP krijgt 429 met Retry-After, SOAP krijgt 503, DICOM krijgt een retryable status en een wachtrij, bucket of bestand blijft waar het was. De verzender verzendt opnieuw, zoals elke interface-engine en EHR doet. Niets wat al is opgeslagen, wordt verwijderd om ruimte te maken. Een verhoogde limiet gaat binnen een minuut in werking en elke wijziging van limieten wordt opgenomen in het activiteitenlogboek.

17.11 Testgegevens

De gegenereerde berichten die in testing worden beschreven, bestaan deels als een privacycontrole. Het reproduceren van een probleem elders, het verzenden van een voorbeeld naar een leverancier of het voorzien van een testomgeving zijn alle dingen die anders worden gedaan met echte berichten.

De uitvoer van de generator bevat geen patiëntgegevens door constructie in plaats van door redactie. Verkiezen deze boven met de hand gestripte echte berichten, wat een proces is dat onvolledig kan worden gedaan en meestal is.

17.12 Eenmalige aanmelding

Drie mechanismen, en lokale accounts naast al deze.

OpenID Connect (-oidc), een directory over LDAP (-ldap), en SAML 2.0 (-saml). Elk wordt geconfigureerd vanuit Beheer → Aanmelding en geschreven naar het bestand dat de vlag benoemt, zodat het scherm en het bestand twee weergaven van één ding zijn in plaats van twee plaatsen die moeten worden bijgehouden.

Lokale accounts zijn altijd beschikbaar en kunnen niet worden uitgeschakeld. Dat is opzettelijk: een on-premises integratie-engine waarvan de enige toegang een identiteitsprovider is, wordt onbereikbaar op het moment dat de identiteitsprovider onbereikbaar is, en een klinische interface is geen goede plek om dat te leren. Het aanmeldingsscherm vertelt u hoeveel lokale beheerders er bestaan voordat het u aanmoedigt om te vertrouwen op iets anders.

17.12.1 Wat een groepstoewijzing beslist

Alle drie toewijzen groepen uit de directory aan Perfuse-rollen, en iemand in groepen die overeenkomen met meer dan één krijgt de meest bevoorrechte. Dat is de enige veilige richting om dit op te lossen — het alternatief is dat een persoon toegang verliest die hij recht heeft omdat hij ook in een minder groep zit.

Een van de zes rollen kan worden toegekend: monitor, viewer, operator, editor, admin en platform.

Een groep kan ook worden beperkt tot sommige kanaalgroepen, in het tweede vak van de rij (channel_groups in het bestand). Zodra een groep een naam heeft, stelt elke aanmelding de kanaalgroepen van de persoon in op basis van de groepen die hun rol hebben verleend: iemand in een groep die de kanalen van het lab bewerkt en in een andere groep die alle kanalen bekijkt, is een bewerker van de kanalen van het lab en niets anders. De sterkste rol wordt nooit gecombineerd met de breedste reikwijdte, omdat geen van beide groepen dit verleent. Een groep met een leeg vak geeft alle kanalen. Zolang geen groep een naam heeft, laat aanmelding de kanaalgroepen zoals een beheerder ze heeft ingesteld in Gebruikers.

Wanneer elke groep die een persoon overeenkomt kanaalgroepen noemt, krijgt elke kanaalgroep de sterkste rol onder de groepen die deze noemen: met Lab-Interfaces (bewerker, lab) en Clinical-IT (viewer, lab en adt), bewerkt de persoon de kanalen van het lab en bekijkt de toelatingskanalen, alsof deze handmatig waren ingesteld. Wanneer een van hun groepen elke kanaal geeft, is er geneen lijst om een rol per groep te bewaren, en geldt de regel hierboven.

roles:
  editor: [Lab-Interfaces]
  operator: [Night-Desk]
  viewer: [Clinical-IT]
  channel_groups:
    Lab-Interfaces: [lab, pathology]
    Night-Desk: [adt]

Dit is het OpenID Connect- en SAML-bestand. Het directorybestand koppelt elke groep aan één rol (roles: {Lab-Interfaces: editor}) en channel_groups staat naast roles daar.

Een toewijzing die niemand iets geeft, wordt geweigerd in plaats van opgeslagen. Een configuratie die personen verifieert en iedereen weigert, lijkt van buitenaf identiek aan een defect product: de rondreis is voltooid en iedereen wordt geweigerd zonder enige verklaring.

Het maken van een account bij de eerste aanmelding is standaard uitgeschakeld. Als het uitgeschakeld is, moet iemand al bestaan in Perfuse voordat ze kunnen aanmelden, dus de directory bepaalt wie ze zijn en Perfuse bepaalt wie toegang heeft.

17.12.2 SAML, specifiek

De onderdelen die het waard zijn om te kennen voordat u het configureert:

17.12.3 Wat elke provider verzendt

Het groepskenmerk is waar aanmeldingen misgaan, en de drie meest voorkomende providers noemen het elk op een andere manier.

ProviderMeestal verzendtNotities
KeycloakgroupsHeeft een groepslidmaatschapsmapper nodig die aan de client is toegevoegd.
Entra IDeen claim-URI die eindigt met /claims/groupsVerzendt groepsobject-id's tenzij de toepassing is geconfigureerd om namen te verzenden. Kaart de id's, of verander de provider.
Oktawat de toepassing was geconfigureerdMeestal groups, met een filter dat beslist welke worden verzonden.
ADFSeen claim-URIOndertekent het antwoord in plaats van de bewering, wat Perfuse accepteert.

Een claim-URI kan worden ingevoerd door het laatste segment: het typen van groups vindt http://schemas.microsoft.com/ws/2008/06/identity/claims/groups. Een naam die eindigt met het woord, maar niet exact overeenkomt, komt niet overeen — excluded_groups is niet groups.

Groepslidmaatschap dat aankomt als één door komma's gescheiden waarde, wordt behandeld als één groepsnaam en komt niet overeen met iets. Dat is de juiste interpretatie van de standaard, en het splitsen op komma's zou betekenen dat een groep die legitiem één bevatte, stilzwijgend twee werd. Als uw provider dat verzendt, verander het daar.

Test op het aanmeldingscherm controleert alles wat kan worden gecontroleerd zonder een persoon: de instellingen, het certificaat en of een aanmeldingsaanvraag kan worden opgebouwd. Het zegt duidelijk dat het niet kan bewijzen dat iemand kan aanmelden, omdat dat een echte bewering over een echte persoon nodig heeft en de enige manier om die te krijgen is door het te proberen.

17.13 Accounts ingericht door de identiteitsprovider: SCIM

Met -scim (Instellingen → Aanmelden → Automatische accounts), kan een identiteitsprovider zoals Okta, Microsoft Entra ID of Google Workspace Perfuse-accounts zelf maken, bijwerken en verwijderen op /scim/v2/Users, zodat een persoon die de organisatie verlaat toegang verliest wanneer hun directoryaccount wordt uitgeschakeld, niet wanneer iemand het zich herinnert. De provider authenticatie met een API-sleutel met de beheerdersrol, gemaakt onder Gebruikers → Machine-referenties, verzonden als een bearer-token.

17.14 Wat Perfuse niet doet

Het versleutelt de database niet in rust. Gebruik bestandssysteem- of volumeversleuteling.

Het beheert geen eigen certificaten of vernieuwt ze. Wijs het naar bestanden en beheer die bestanden met wat u al gebruikt.

SAML is geverifieerd tegen twee onafhankelijke providers, elk met een echte browser-aanmelding, een echte bewering en een echte sessie: Keycloak 26 en Microsoft Entra. Twee zaken zijn meer dan twee keer zoveel als één, omdat de twee op een manier verschillen die belastbaar bleek te zijn - Keycloak schrijft zijn bewering met naamruimtevoorvoegsels en Entra schrijft dezelfde elementen zonder, en het enige defect in dit gebied was in voorvoegselafhandeling.

Begin met het lezen van de metadata van uw provider. Instellingen, vervolgens Aanmelden, vervolgens het SAML-tabblad: geef de metadata-URL op of plak het document, en het aanmeldadres en het ondertekeningscertificaat worden voor u ingevuld. Elke SAML-provider publiceert een van deze - Okta, Entra, AWS IAM Identity Center, Keycloak, ADFS - en het is het verschil tussen het configureren van een provider en het overnemen van een provider. Het handmatig doen betekent het certificaat vinden in de XML, de lijnbreuken uit de base64 verwijderen en het in PEM-kopteksten wikkelen, waarbij één enkele afwijkende spatie een ondertekeningsfout veroorzaakt die niets over opmaak zegt.

Wat terugkomt, wordt beschreven in plaats van gedumpt: elk certificaatonderwerp, verloopdatum en SHA-256-vingerafdruk, zodat u het kunt controleren tegen wat het console van uw provider zelf laat zien. Een verlopen certificaat wordt aangeduid als verlopen in plaats van een datum die met het oog moet worden vergeleken. Niets wordt opgeslagen door te lezen - het toepassen op het formulier is een aparte klik, omdat een document dat iemand heeft geplakt nog geen beslissing is over wat te vertrouwen.

Een metadata-URL wordt opgehaald via https alleen, en het adres wordt gecontroleerd tegen hetzelfde beleid dat de bestemmingen van kanalen beheerst, dus dit kan niet worden gebruikt om de server te laten lezen van cloud-exemplaarreferenties. Omleidingen worden niet gevolgd, omdat een toegestaan adres dat omleidt naar een geblokkeerd adres rechtstreeks langs die controle zou lopen.

Als u Entra configureert, zullen vijf dingen niet overeenkomen met wat de voorbeelden u laten zien. Het verzendt geen e-mailclaim helemaal. De NameID is een ondoorzichtige identifier in plaats van een adres. Het verzendt geen groepsclaim tenzij de toepassing expliciet is geconfigureerd om deze te verzenden, dus een rolemapping die is geschreven tegen groepen weigert elke aanmelding. Wanneer groepen worden verzonden, zijn het object-GUID's in plaats van namen, tenzij uw tenant wordt gesynchroniseerd vanuit een on-premises Active Directory. En de claimnamen leven onder schemas.microsoft.com/identity waar de meeste documentatie schemas.xmlsoap.org laat zien. Perfuse behandelt alle vijf; ze worden opgesomd omdat de eerste vier anders zullen lijken op fouten in Perfuse wanneer ze Entra zijn die Entra is.

Dat onderscheid is hier niet theoretisch. De eerste echte Keycloak-bewering faalde volledig, omdat de canonieke vorm die de handtekening dekt, werd berekend met naamruimtevoorvoegsels die werden weggegooid. Geen enkele echte identiteitsprovider had iemand kunnen aanmelden, en de vijf canonisatietests van het pakket waren doorgegaan - elk ondertekend en geverifieerd met dezelfde code, dus ze bewezen alleen dat het het met zichzelf eens was. Als u de eerste bent die een andere provider naar dit wijst, verwacht dan iets te vinden, en het serverlog zal de fase noemen die is mislukt.

18 Bewerkingen

18.1 Implementatie

Een binaire en twee paden: een directory met kanaalbestanden en een databasebestand. Er is geen toepassingsserver, geen aparte webtier en geen berichtenbroker vereist.

perfuse serve -channels ./channels -db ./perfuse.db -addr 0.0.0.0:8443 \
  -tls-cert ./cert.pem -tls-key ./key.pem

Voer het uit onder wat diensten op de host superviseert - systemd, launchd, een containerruntime. Het verwacht te worden opnieuw gestart als het afsluit.

18.2 Waar gegevens naartoe kunnen gaan (gegevensresidencie)

serve -residency (Instellingen → Gegevens → Waar gegevens mogen worden opgeslagen) specificeert de cloudregio's waaruit de gegevens van deze server kunnen worden verstuurd of gelezen: gebieden (eea, uk, ch) en regiocode's (eu-central-1, uksouth, europe-west2), komma-gescheiden. eea zijn de AWS-, Azure- en Google Cloud-regio's in de Europese Economische Ruimte (Frankfurt, Ierland, Parijs, Stockholm, Milaan, Spanje; Nederland, Duitsland, Frankrijk, Zweden, Noorwegen, Italië, Polen, Spanje; België, Nederland, Duitsland, Italië, Frankrijk, Finland, Spanje, Polen), uk zijn die in het Verenigd Koninkrijk, ch zijn die in Zwitserland.

Als deze is ingesteld, wordt een kanaal geweigerd wanneer het wordt opgeslagen en wanneer het wordt geladen, als een connector een regio buiten de lijst noemt: een S3-, SQS- of SNS-bron of -bestemming region (of de endpoint, wanneer dit een AWS-hostnaam is), of elke bestemming waarvan het adres een AWS-hostnaam is met een regio (sqs.us-east-1.amazonaws.com, een API-Gateway-URL). De server weigert te starten met een trace collector of alert webhook in een andere regio. Een connector die naar een host wijst die geen regio noemt (een eigen systeem van een ziekenhuis, MinIO op het netwerk van de site), wordt niet beoordeeld: het record van de verwerking op het scherm Gegevensbescherming toont elke host waarnaar elk kanaal verzendt, voor de controller om te controleren. Het dashboard en het scherm Gegevensbescherming geven aan waar gegevens naartoe kunnen gaan.

Hosting in de EU en het VK. deploy/hosted bevat OpenTofu (of Terraform) voor één gehoste server per organisatie in Frankfurt, Ierland of Londen: de server, de PostgreSQL-database en back-ups, een back-upbucket, logbestanden en ondersteuningsgespreksrecords, alles versleuteld met een sleutel in de regio, niets gerepliceerd naar een andere regio, ondersteuning via Session Manager alleen en Perfuse uitgevoerd met -residency. De README zegt wat het bouwt, wat het niet dekt, wat is geverifieerd (gevalideerd en gepland tegen een echt account; nog niet toegepast) en wat het kost bij de lijstprijs in elke regio.

18.3 Configuratie als bestanden

Kanalen zijn bestanden, wat betekent dat ze in versiebeheer kunnen worden opgenomen, kunnen worden beoordeeld voordat ze worden geïmplementeerd en kunnen worden vergeleken na een incident.

Bestanden worden opnieuw gelezen zonder een herstart. Een bestand dat niet kan worden geparsed, wordt gemeld en de eerder geladen versie blijft draaien, dus een syntaxisfout kan een werkende feed niet uit de lucht halen.

Een kanaal dat in de webinterface is bewerkt, wordt teruggeschreven naar het bestand. Als deze bestanden in versiebeheer staan, verwacht dan commits van configuratiewijzigingen die via de interface zijn aangebracht en bewerk geen bestand handmatig terwijl iemand het heeft geopend in de builder.

18.4 Back-up

Twee dingen om back-up te maken, en ze hebben verschillende kenmerken.

De kanaalmap is klein, verandert zelden en is wat u nodig heeft om de service opnieuw op te bouwen. Back-up maken als configuratie; versiebeheer is meestal voldoende.

De database bevat berichten, gebruikers en auditgeschiedenis. Het is groot, verandert constant en bevat klinische gegevens — dus het moet worden back-up gemaakt als klinische gegevens, met de retentie en versleuteling die dat impliceert. Het verlies ervan stopt de service niet, maar het verliest de mogelijkheid om iets dat al is gebeurd te onderzoeken en de geschiedenis waarop de ritmeleerder afhankelijk is.

18.5 Opnieuw opstarten

Bij opnieuw opstarten, worden kanalen geladen en beginnen bronnen te luisteren. Opgeslagen leveringen worden hervat.

Het belangrijkste om te begrijpen is wat er gebeurt met werk in uitvoering. Onder de standaard on_delivery-bevestiging, wordt een bericht dat nog niet was bevestigd, niet bevestigd, dus de afzender zal het opnieuw verzenden — wat het juiste resultaat is. Onder on_receipt, is een bericht dat was bevestigd maar nog niet was afgeleverd, in de wachtrij, en hervat; als de wachtrij is uitgeschakeld, gaat het verloren. Zie berichtstroom.

18.6 Upgraden

Vervang de binaire bestanden en start opnieuw op. Het databaseschema wordt automatisch naar voren gemigreerd bij het opstarten.

Migraties zijn alleen naar voren. Er is geen downgrade, dus een terugkeer naar een vorige binaire bestand na het verplaatsen van het schema, heeft het vorige databasebestand nodig. Maak een kopie voordat u upgradet — dit is de enige operationele voorzorgsmaatregel die het waard is om disciplineert te zijn.

18.7 Bewaking

Waarschuwingen vanuit Perfuse worden behandeld in waarschuwingen en zijn wat u zal vertellen dat een feed is gestopt.

Van buitenaf, bewaak het proces, de schijf waarop de database staat en of de webinterface reageert. De database groeit en een volle schijf stopt berichtopname, wat een storing is zonder andere waarschuwing.

18.7.1 SNMP

Voor bewakingshulpmiddelen die SNMP spreken (Nagios, Zabbix, PRTG, SolarWinds, LibreNMS), voert Perfuse een alleen-lezen SNMPv2c-agent uit en verzendt een trap wanneer een waarschuwing wordt geactiveerd of opgelost. Stel het in onder Instellingen → Bewaking → SNMP, of met vlaggen:

perfuse serve -snmp-listen :161 -snmp-community 'long-random-community' -snmp-allow 10.0.5.0/24 \
  -snmp-traps nms.example.org,10.0.5.9:1162

18.7.2 Een inventaris van elk interface

-inventory interfaces.md (Instellingen → Bewaking → Inventaris) schrijft een Markdown-document dat elk kanaal opsomt - het formaat, of het wordt uitgevoerd, wat het ontvangt van en wat het naar verzendt - gevolgd door elke kanaalbeschrijving, en herschrijft het elke -inventory-every (een dag standaard). Het is bedoeld om naast de kanaalbestanden te worden geplaatst, of aan een auditor te worden gegeven, en te worden gelezen zonder dat de toepassing wordt uitgevoerd.

18.8 Capaciteit

Het doorvoerplafond van Perfuse is niet gemeten op echte hardware onder echte verkeer, en deze handleiding zal geen nummer afdrukken dat het niet kan ondersteunen.

Wat kan worden gezegd: de architectuur is één goroutine per verbinding met per-bestemmingswachtrijen, dus de doorvoer schaalt met bestemmingen in plaats van te worden geserialiseerd via één werker; berichtopname is een SQLite-schrijfactie per bericht, wat de schijf de meest waarschijnlijke eerste beperking maakt; en de berichtopslag groeit lineair met het verkeer, dus retentie is de instelling die de langetermijnschijfgebruik beheerst.

Als u dit voor een grote feed wilt dimensioneren, meet u het dan met uw eigen verkeer met behulp van het gegenereerde testcorpus dat wordt beschreven in testing. Dat is het eerlijke antwoord, en het is ook een beter antwoord dan een nummer van iemand anders' hardware.

18.9 Waar deze installatie vastliep

Activiteit bevat een paneel, zichtbaar voor beheerders, dat laat zien wat Perfuse heeft geweigerd te doen — gegroepeerd per bericht, meest frequent eerst — en hoe ver de installatie is gekomen met een werkende *channel*.

Het bestaat omdat elke andere bewering over of deze software gemakkelijk te gebruiken is, afkomstig is van de mensen die het hebben geschreven. Een weigering niet: iemand wilde iets, de server zei nee, en geen van beide partijen gokte. Het is het enige bewijs in het product dat niet afkomstig is van BioDream LLC.

De trechter noemt de stap die nog niet is gebeurd in plaats van tijdstempels te vergelijken. De staat die het waard is om te kijken is berichten arriveren en geen is afgeleverd bij een *destination* — een *channel* kan verkeer voor weken aan en geen ervan afleveren, en van elk ander scherm ziet het eruit alsof het werkt.

Niets wat iemand heeft getypt, wordt opgenomen. De tabel bevat de aanvraagroute met identificatoren vervangen door {id}, de status en de zin van de server. Een validatiebericht noemt een veld en een regel, wat het nuttige deel is; de waarde die de regel verbrak, is heel vaak patiëntgegevens, en een tabel met die gegevens zou een grotere aansprakelijkheid zijn dan de wrijving die het mat.

Twee opzettelijke uitsluitingen. Een 5xx is een fout in deze software en wordt al als zodanig gelogd — het mengen van de twee zou de gevallen waarin iemand niet kon uitvinden wat te typen, begraven onder de gevallen waarin niets wat ze typten, zou hebben geholpen. En een verlopen sessie produceert een reeks 401's die niets zeggen over de gebruiksvriendelijkheid en zou elke vinding die dat wel doet, verdrinken.

Het lezen van het rapport knipt de tabel ook af tot de meest recente vijfduizend rijen. Weigeringen zijn 4xx-antwoorden, dus het groeit langzaam, en lezen is een natuurlijk moment om op te ruimen: geen timer en niets dat draait wanneer niemand kijkt.

GET /api/friction retourneert hetzelfde voor iedereen die het liever als JSON leest.

18.10 Logbestanden

Perfuse logt naar de standaarduitvoer, die is waar een supervisor of container-runtime het zal verzamelen.

Details op berichtniveau gaan naar de *message store* in plaats van naar het logbestand, met opzet. Een logregel per bericht op een drukke feed is ruis die de regels die ertoe doen, verbergt, en de winkel is doorzoekbaar op manieren waarop een logbestand dat niet is.

Het logbestand bevat wat de winkel niet kan: opstarten en afsluiten, resultaten van configuratieladen, wijzigingen in de *channel*-status en fouten die niet toe te schrijven zijn aan een specifiek bericht.

18.11 Twee instanties uitvoeren

Twee of meer servers kunnen als één cluster worden uitgevoerd: wanneer de server die een feed uitvoert, stopt, neemt een andere server het over binnen enkele seconden, en de volgende poging van de afzender bereikt het. Ze delen één PostgreSQL-database in plaats van elk een SQLite-bestand te hebben, en komen overeen tussen hen, via de database, welke server welk werk uitvoert.

perfuse serve -db 'postgres://perfuse:SECRET@db.hospital.internal/perfuse?sslmode=verify-full' \
  -cluster active-passive -node-name perfuse-01 -node-address https://perfuse-01.hospital.internal:8443 \
  -data /var/lib/perfuse

Start elke server op dezelfde manier met zijn eigen naam en adres. Het databaseaccount moet tabellen kunnen maken en, één keer, de citext-extensie (of een beheerder voert CREATE EXTENSION citext uit voordat). Elke server houdt zijn eigen bestanden in -data: zijn logboek, zijn knooppunt-id en zijn kopieën van de configuratie.

Twee manieren om het werk te delen.

anderen wachten. Het eenvoudigst om te begrijpen, en wat een site met één drukke server en een reserve-server wil.

aan de rest; een server die zich aansluit, neemt zijn aandeel als kanalen vrijkomen, één voor één. Kanalen die naar elkaar routeren (een kanaalbestemming) worden op één server uitgevoerd en verplaatst samen, omdat routering plaatsvindt binnen een server. Een beheerder kan een kanaal handmatig verplaatsen van Bewaken → Vloot; het blijft waar het is geplaatst zolang die server leeft.

Wie voert wat uit, en geen moment met twee. Elk stuk werk is een lease in de database, vernieuwd elke vijfde van -cluster-lease (15 s standaard). Een server die de lease niet kan vernieuwen (het is crasht, het netwerk is mislukt, de database is niet bereikbaar) stopt dat werk van zichzelf zodra zijn eigen klok zegt dat de lease bijna klaar is, met een derde van de lease over. Een andere server neemt de lease alleen over nadat zijn eigen klok de lease-teller heeft zien stilstaan voor een hele lease. Geen klok wordt vergeleken met een andere, dus de klokken van de servers en de database hoeven niet overeen te komen; ze hoeven alleen ongeveer dezelfde snelheid te hebben, wat elke klok doet. Tussen het stoppen van de oude houder en het starten van de nieuwe is er een korte onderbreking waarin niemand luistert, die een afzender ziet als een geweigerde verbinding en opnieuw probeert; er is nooit een moment met twee luisteren op één feed of twee werknemers die één wachtrij legen.

Een server die schoon afsluit, of een beheerder die Terugtrekken op de leider kiest, geeft onmiddellijk over in plaats van na de lease.

Wat elke server deelt. Berichten, de leveringswachtrij, accounts en sessies, het auditlogboek, de FHIR-opslag, de terminologietabellen en de patiëntindex zijn in de database, dus welke server een kanaal uitvoert, vindt de wachtrij die de vorige heeft achtergelaten. De kanaalbestanden, het instellingsbestand, de waarschuwingsregels, single sign-on-bestanden, het logo, Direct-certificaten en opgeslagen weergaven worden op elke server hetzelfde gehouden via de database: elke server houdt zijn eigen kopie op zijn eigen schijf, een wijziging op een server (in de console, handmatig, door een git pull) bereikt de andere servers binnen twee seconden, en een kanaal dat op een andere server is gewijzigd, start opnieuw met zijn nieuwe bestand. Hetzelfde bestand dat op twee servers tegelijk is gewijzigd, houdt de versie die het eerst de database bereikte, en de andere ernaast als NAME.conflict-SERVER. Instellingen die alleen bij een opnieuw opstarten gelden (de berichtendatabase, de poorten waarop de console luistert) worden door elke server toegepast bij het volgende opnieuw opstarten, en het logboek zegt dat zo. Wat een naam op één machine aanduidt, blijft op de opdrachtregel van die server en buiten het gedeelde bestand: het certificaat en de sleutel (-tls-cert, -tls-key), het SNMP-luisteradres en de naam van de server in sporen. Instellingen laten ze zien als ingesteld op elke server.

Starten en stoppen. Het starten of stoppen van een kanaal op elke server is van toepassing op het cluster: de server die het uitvoert, start of stopt het binnen een seconde, en het antwoord zegt welke server dat is.

De load balancer ervoor. Een feedadres moet de server bereiken die deze uitvoert. Wijs de afzender naar een virtueel adres (een load balancer, een floating IP, een DNS-naam met een korte TTL) en laat de load balancer /readyz?channel=NAME controleren, die alleen op de server die deze kanaal uitvoert antwoordt met 200 en op de andere servers met 503. Voor de console is /readyz 200 op elke actieve server; /readyz?role=leader alleen op de leader.

Op een AWS Network Load Balancer gebruikt u een doelgroep per feed met een HTTPS-gezondheidscontrole op /readyz?channel=NAME, een interval van 5 seconden en een drempel van 2, en schakelt u cross-zone load balancing in. Met deze optie uitgeschakeld ziet de knooppunt van de load balancer in een zone waar geen server de feed uitvoert alleen ongezonde doelen, stuurt naar allemaal en een afzender die naar dat knooppunt is doorgestuurd, wacht totdat de feed terugkeert naar zijn zone (95 seconden in een test). Stelt u de deregistratievertraging in op 0, omdat een server die een feed stopzet, niets heeft om te drainen.

Wat getest is. Twee servers op PostgreSQL 16, een afzender die 300 berichten streamt, opnieuw verstuurt totdat er antwoord komt, en de server die de feed uitvoert, tweemaal gedood met SIGKILL (eerst de ene, dan de andere na de eerste terugkeer). Elk bevestigd bericht bereikte de ontvanger, in beide vormen die zijn geprobeerd: geleverd voordat de bevestiging, en in de gedeelde winkel in de wacht terwijl de ontvanger weigerde (185 bevestigde berichten wachtten in de wachtrij bij de dood; de overlevende leverde ze allemaal). Failover duurde 3 tot 4 seconden op een lease van 3 seconden. Een duplicaat is mogelijk en werd eenmaal in 600 gezien: een bericht dat de stervende server leverde en niet kon bevestigen, dat de afzender opnieuw verstuurd heeft. De coördinator heeft zijn eigen tests die een crash, een server die van de database is afgesneden terwijl deze nog steeds draait, step-down, verspreiding, verplaatsingen en gedeelde configuratie met conflicten behandelen. Ze worden uitgevoerd in CI tegen PostgreSQL met de racedetector, met de hele suite.

Hetzelfde is vervolgens gedaan op AWS: twee Linux-servers (ARM) en één Windows Server 2022 in drie beschikbaarheidszones, Amazon RDS PostgreSQL 16 via TLS met het certificaat gecontroleerd (sslmode=verify-full), een interne Network Load Balancer ervoor, en afzenders die opnieuw versturen totdat er antwoord komt:

TestBerichtenBevestigd maar verlorenDuplicatenLangste tijd dat een afzender wachtte
Actief-passief, de server die het feed uitvoert, gedood twee keer (Linux, dan Windows), ontvanger weigert tussenin2.0000015 s
Een Linux-leader die van de database is afgesneden (firewall), het proces nog steeds draait3.0000116 s
Een Windows-leader die van de database is afgesneden3.0000020 s
De leader gedood terwijl één server's klok 2 minuten voorliep en een andere 90 seconden achterliep2.0000018 s
Actief-actief, vier feeds over drie servers, één gedood en teruggebracht6.0000224 s

Met de standaardlease van 15 seconden, stopte een server die van de database was afgesneden, zijn feed 10 seconden na zijn laatste vernieuwing, en startte de volgende server deze 6 tot 8 seconden later: nooit allebei tegelijk. De gesynchroniseerde klokken veranderden niets, omdat geen enkele klok met een andere klok wordt vergeleken.

Nog niet. Een cluster dient één organisatie: -cluster met -multi-tenant wordt geweigerd. Luisteraars verhuizen met hun kanaal, dus de load balancer is de site die moet worden verstrekt.

Een server op zichzelf blijft werken zoals het altijd heeft gedaan, op SQLite, zonder cluster.

18.12 Meer dan één server

Een site met twee instanties heeft een vraag die geen enkele console kan beantwoorden: draait alles? Mirth berekent een prijs voor het antwoord. Dit is de vlootweergave.

Één instantie wordt aangewezen als de plaats waar u kijkt. Het pollt de anderen en toont elk kanaal op elke server in één tabel, met een samenvatting over allemaal.

18.12.1 Een peer toevoegen

Instellingen → Vloot, of PUT /api/fleet/peers. Een peer heeft een naam, een URL en een token nodig die door de peer zelf is uitgegeven.

De naam is verplicht en is niet de URL, omdat een URL niets is dat iemand om drie uur 's nachts herkent.

Het token moet op de peer worden gemaakt, onder Gebruikers, en moet viewer-georiënteerd zijn. Het toevoegen van een peer zonder token wordt geweigerd, met die instructies, in plaats van geaccepteerd en vervolgens stil falen bij elke peiling. Het lezen van de gezondheid van een andere instantie is de kleinste privilege die er is, en het is de enige die de vlootweergave nodig heeft.

18.12.2 Het besturen van een peer, die uit staat

allow_control staat het starten en stoppen van het kanaal van die peer van hieruit toe. Het is standaard uitgeschakeld en elk gebruik wordt door naam geaudit.

De twee privileges zijn expres gescheiden. Het lezen van de gezondheid van een andere server is van ondergeschikt belang; het stoppen van zijn kanalen tijdens een transfusie is dat niet, en de tweede zou nooit stil aan de eerste moeten worden toegevoegd.

18.12.3 Wat het rapport zegt

Elke server rapporteert het totale aantal kanaal, hoeveel ervan worden uitgevoerd, gestopt of foutief zijn, de diepte van de wachtrij en de leeftijd van het oudste wachtende bericht, hoeveel alarmsignalen afgegaan zijn en het of het leegloopt voor afsluiten.

De samenvatting telt servers op drie manieren: bereikbaar, niet bereikbaar en onbepaald. De derde dekt peers waarvan niemand de gezondheid kent — nog niet gepolld, weigert het token, of draait een versie die deze instantie niet kan lezen. Het wordt gescheiden gehouden van niet-bereikbaar, omdat 'we kunnen het niet zeggen' niet 'het is uit' is, en het samenvoegen van de twee is hoe een vlootpagina begint te liegen.

Om dezelfde reden bevat de samenvatting knownFrom: hoeveel instanties de kanaal- en wachtrijcijfers daadwerkelijk zijn gelezen. Twaalf kanalen die over een vloot lopen, betekenen iets anders wanneer twee van de vijf servers niet antwoorden, en het totaal alleen kan dat niet zeggen.

Een niet-bereikbare peer zegt waarom in termen die een operator kan gebruiken. Een geweigerde verbinding wordt gerapporteerd als de host die actief is met niets dat luistert op die poort, wat een ander probleem is dan een host die helemaal niet antwoordt.

18.12.4 Klokscheefheid

De samenvatting rapporteert het grootste verschil tussen de klokken van de servers erin. Het is de moeite waard om een getal te hebben: het correleren van een incident over twee instanties waarvan de klokken 4 minuten verschillen, produceert een reeks gebeurtenissen die niet zijn gebeurd.

18.12.5 Wat een peer over u leert

Aantallen en tarieven. Het rapport dat één instantie aan een andere geeft, bevat geen berichtidentificaties, geen kanaalniveau-details en geen patiëntgegevens van welke aard dan ook.

Dat is wat voorkomt dat een fleet-weergave een centralisatie van klinische gegevens wordt: de aggregatie-instantie leert hoeveel kanalen er draaien en niets over wat er doorheen stroomt. Als u de berichten wilt, opent u de console van die server, waar het auditlogboek registreert dat u dat hebt gedaan.

18.12.6 Een peer die naar zichzelf wijst

Geweigerd. Een instantie die zijn eigen adres pollt via zijn eigen HTTP-stack, verschijnt tweemaal in zijn eigen fleet-weergave en telt elke kanaal dubbel.

18.12.7 TLS op interne netwerken

insecure_skip_verify accepteert een certificaat van een peer zonder het te verifiëren. Het bestaat omdat ziekenhuisinfrastructuur draait op privé-certificeringsinstanties en weigeren om überhaupt te werken mensen zou pushen naar plain HTTP, wat erger is. Het is zo genoemd dat het niet kan worden verward met een goed idee.

19 De opdrachtregel

Alles wat Perfuse doet met een actief systeem is bereikbaar vanuit het webinterface, en dat is opzettelijk: een functie die een terminal nodig heeft, wordt behandeld als een defect in plaats van een ontwerpkeuze. De opdrachten hier zijn voor het werk dat gebeurt *rond* een actief systeem — voordat het bestaat, terwijl u besluit of u het vertrouwt, en wanneer u iets aan iemand anders moet geven.

Enkele hiervan raken geen server aan. perfuse explain, perfuse profile, perfuse deident en perfuse translate lezen bestanden en schrijven bestanden, dus ze zijn nuttig op een laptop tegen een landgoed dat nog steeds volledig draait op iets anders.

Voer elke opdracht uit met -h voor de vlaggen. Dit hoofdstuk zegt waarvoor elke opdracht *is*.

De vlaggen die hier worden weergegeven, zijn illustratief, niet uitputtend. -h wordt gegenereerd uit de code en kan niet verouderd raken; een lijst die in proza wordt gekopieerd, kan dat wel.

19.1 Actieve kanalen

19.1.1 perfuse serve

Start de webinterface en de API, en voert standaard ook de kanalen uit. Dit is het commando dat een installatie gebruikt.

Elke optie die het gebruikt, wordt vermeld in Serveropties, gegenereerd uit het programma. Het weigert om onbeveiligde HTTP te bedienen aan alles behalve loopback, tenzij u -insecure doorgeeft. Dat is geen configureerbare beleefdheid: klinische verkeer en een sessiecookie over een onbeveiligde LAN-verbinding is een rapporteerbaar evenement, en de vlag bestaat zodat het zeggen van ja een beslissing is die iemand heeft genomen, in plaats van een standaard die ze hebben geërfd. Zie beveiliging.

19.1.2 perfuse run

Voert kanalen uit vanuit YAML zonder webinterface en zonder database. Nuttig in een container die precies één ding moet doen, en nuttig wanneer u het gedrag van een kanaal wilt zien zonder dat er iets anders draait.

19.1.3 perfuse check

Valideert kanaaldefinities en print wat ze doen, zonder ze uit te voeren. Het tweede deel is het punt: een kanaal dat laadt, is niet noodzakelijkerwijs het kanaal dat u bedoelde, en het lezen van een samenvatting in gewoon Nederlands van wat een bestand zal doen, vangt een fout die validatie niet kan zien.

Sluit af met een niet-nulwaarde bij een fout, dus het hoort in welke checks uw configuratie voordat het een server bereikt. -quiet print niets bij succes, voor dat gebruik.

-allow-metadata-egress staat bestemmingen toe die naar cloud-instantiemetadata-adressen wijzen. Deze adressen bevatten de referenties van de machine zelf, dus een kanaal dat kan worden overgehaald om daarheen te sturen, is een referentielek; de check weigert ze, tenzij u anders zegt.

19.1.4 perfuse test

Voert tests uit die zijn geschreven tegen kanaaldefinities. Een test verstuurt een bericht door het echte filter, echte transformaties en echte scripts van het kanaal, in de echte volgorde, met alleen het netwerk vervangen — dus wat hier slaagt, is wat het kanaal doet.

Tests wonen in *_test.yaml of *.test.yaml naast de kanalen. Zie testen.

19.2 Migreren van een andere engine

Deze drie moeten worden uitgevoerd voordat u iets besluit. Zie migratie.

19.2.1 perfuse explain

Leest Mirth-, Open Integration Engine- en BridgeLink-exports — een kanaal, een kanaalgroep of een volledige serverback-up — en beschrijft wat elk kanaal doet en wat een migratie zou blokkeren. Het verandert niets en heeft geen Perfuse-installatie nodig, wat het de goedkoopste mogelijke eerste stap maakt: wijs het naar een export van uw bezit en lees wat terugkomt.

-strict sluit af met een niet-nulwaarde als er iets wordt geblokkeerd, dus het kan een pipeline afsluiten. -json geeft dezelfde resultaten voor een machine.

19.2.2 perfuse translate

Converteert Mirth-, Open Integration Engine- en BridgeLink-exports naar Perfuse-kanaalbestanden: één kanaal, een kanaalgroep, een code-sjabloontexport of een volledige serverback-up.

perfuse translate -o ./kanalen server-backup.xml

Code-sjabloonbibliotheken worden geschreven naar lib/ naast de kanalen, en elk kanaal dat Mirth had, bevat een bibliotheek die is ingeschakeld. Zie migratie.

Niets wordt stilzwijgend weggegooid. Elk deel van een kanaal wordt ofwel vertaald, ofwel overgedragen als een script dat ongewijzigd wordt uitgevoerd, ofwel gemeld als noodzakelijk voor een mens. De derde categorie is de eerlijke — een vertaler die een schoon uitziend bestand produceert voor elke invoer, zou de beslissingen verbergen die u het meest moet nemen.

19.2.3 perfuse compare

Voert hetzelfde verkeer uit door twee engines en rapporteert waar ze het oneens zijn, gegroepeerd per veld.

Dit is het commando dat antwoord geeft op de vraag "waarom zou ik dit moeten vertrouwen met patiëntgegevens", en het antwoord geeft met bewijs dat u hebt verzameld in plaats van een claim die hier wordt gemaakt. Het is de aanbevolen laatste stap voordat u overschakelt en de aanbevolen eerste stap in elk argument over of Perfuse klaar is.

19.3 Een feed begrijpen

19.3.1 perfuse profiel

Leest berichten en rapporteert wat er daadwerkelijk in zit: welke velden altijd zijn ingevuld, welke nooit, de werkelijke waarde sets van gecodeerde velden, herhalingstellingen en welke Z-segmenten verschijnen.

Waarden worden alleen gerapporteerd voor velden waarvan de waarden een kleine code set vormen, zodat een profiel van echte verkeer geen bestand vol met patiëntgegevens wordt.

Een profiel opslaan en later vergelijken met het is de manier waarop u erachter komt dat een afzender iets heeft veranderd:

perfuse profiel -save last-month.json corpus/ perfuse profiel -against last-month.json new/

19.3.2 perfuse contract

Zet de uitvoer van dat denken om in iets afdwingbaar. Een contract zegt hoe een feed eruit moet zien, zodat u op de dag dat het verandert wordt verteld, in plaats van later te ontdekken van een ontvanger die omvalt - de berichten zijn nog steeds geldige HL7 wanneer een veld verdwijnt, dus niets anders merkt het op.

perfuse contract promote -o adt.contract.yaml corpus/ perfuse contract check adt.contract.yaml today/

promote genereert een startpunt, niet een antwoord. Lees het en verwijder de meeste regels: elke regel rapporteert of het is gemeten of besloten, wat u vertelt welke regels u moet houden.

19.4 Berichten produceren

19.4.1 perfuse genereren

Produceert synthetische HL7 v2-berichten. Alles is uitgevonden - duidelijk fictieve namen, opeenvolgende identificatoren, gefabriceerde adressen - dus de uitvoer is veilig om te committen, te mailen en toe te voegen aan een ticket.

Het kan rechtstreeks naar een kanaal sturen in plaats van een bestand te schrijven, wat de snelste manier is om te bewijzen dat een luisteraar werkt:

perfuse genereren -n 100 -send 127.0.0.1:6661

19.4.2 perfuse deïdentificeren

Leest echte berichten en schrijft een corpus dat hun structuur, codes en intervallen behoudt, en niets van wat een patiënt identificeert. Dit is het verschil tussen het kunnen sturen van een reproductie en niet.

Het is niet hetzelfde instrument als perfuse generate en het onderscheid is van belang. Gegenereerde berichten zijn uitgevonden en dus veilig maar onrealistisch; een geanonimiseerde verzameling is *afgeleid van echte verkeer*, dus reproduceert het de eigenaardigheden die interfaces daadwerkelijk breken.

Twee eigenschappen die het waard zijn om te begrijpen voordat u het gebruikt:

-keep-local-segments geeft Z-segmenten ongewijzigd door en is onveilig. Z-segmenten zijn precies waar sites namen, notities en vrije tekst plaatsen, dus het behouden ervan verslaat het doel van het hulpmiddel. Het bestaat omdat een structureel probleem soms *in* een Z-segment zit, en dan hebt u een corpus nodig dat u niet moet delen.

19.5 Berichten verplaatsen met de hand

19.5.1 perfuse luisteren

Accepteert HL7 v2 via MLLP en bevestigt het. Een ontvanger die bestaat zolang u het nodig heeft, voor het bewijzen dat een afzender dit apparaat op alle mogelijke manieren kan bereiken.

19.5.2 Perfuse verzenden

Verzendt HL7 v2-berichten via MLLP vanuit bestanden.

MLLP heeft geen authenticatie en geen encryptie, niet in Perfuse en nergens anders. Beide opdrachten zijn hiervan onderworpen, evenals elke MLLP-bron en -bestemming: toegang is beperkt op het netwerklaag of het is niet beperkt.

19.6 FHIR

19.6.1 Perfuse FHIR

Converteert HL7 v2 naar FHIR, valideert FHIR of serveert het, afhankelijk van de subopdracht.

De validerende subopdracht is nuttig op zichzelf: het zal u vertellen of een resource die iemand u heeft gestuurd voldoet aan US Core, wat het profiel is waarop de Amerikaanse regelgeving is gebaseerd. Het kunnen beantwoorden van deze vraag zonder een engine te adopteren is het doel.

19.6.2 perfuse x12

Converteert X12 (of andere door komma's gescheiden EDI) naar XML Mirth Connect en Open Integration Engine schrijven ervoor, en terug: perfuse x12 xml FILE en perfuse x12 from-xml FILE, standaard invoer wanneer er geen bestand wordt opgegeven. De uitvoer is wat OIE 4.6 schrijft, byte voor byte, zodat deze kan worden vergeleken met wat een Mirth-server heeft geproduceerd of gevoed aan een systeem dat is gebouwd tegen het. Een kanaal doet hetzelfde met x12.arrives_as: xml en een bestemming x12_as: xml; zie X12.

19.6.3 Perfuse sof

Voert een SQL op FHIR ViewDefinition uit over FHIR-bestanden (de NDJSON van een bulkexport, Bundles of JSON-arrays; - voor stdin) en schrijft de tabel: -view FILE (vereist), -format csv|ndjson|json|parquet (csv standaard), -header=false, en -o FILE (vereist voor Parquet). Zie SQL op FHIR-weergaven.

19.6.4 Perfuse meting

Evalueert een kwaliteitsmaatstaf met FHIRPath-criteria over FHIR-bestanden (de NDJSON van een bulkexport, Bundles of JSON-arrays; - voor stdin) en schrijft de MeasureReport. Vlaggen:

Zie digitale kwaliteitsmetingen.

19.6.5 FHIR-vlaggen op Perfuse server

VlagEffect
-fhirServeer het FHIR-eindpunt op /fhir. Standaard ingeschakeld.
-fhir-versionDe release die wordt geserveerd. Standaard R4.
-fhir-read-onlyWeiger schrijfacties.
-fhir-api-tokensMet SMART geconfigureerd, accepteert Perfuse API-tokens naast SMART-tokens (uitgeschakeld door standaard; ook onder Instellingen → FHIR).
-fhir-bulk-exportSchakel $export in. Uitgeschakeld door standaard.
-fhir-subscriptionsSchakel abonnementen op onderwerpen in: notificaties over ontmoetingen en afspraken naar eindpunten die FHIR-clients kiezen. Uitgeschakeld door standaard; vereist R4 en een beschrijfbaar eindpunt.
-fhir-subscriptions-allow-httpLaat abonnementen leveren aan gewone http. Alleen voor een testontvanger, nooit voor patiëntgegevens op een netwerk.
-fhir-patient-directory-searchLaat een token dat is beperkt tot één patiënt de directory doorzoeken (praktijkhouders, organisaties, locaties), binnen zijn scopes. Uitgeschakeld door standaard.
-fhir-declaresLeidt deze server verklaart in zijn capability statement, komma-gescheiden: een gids CapabilityStatement-adres, of Type=profile-adres. Een verklaring voor clients en testkits; het verandert niets wat de winkel accepteert.

De opslag bewaart documenten evenals bronnen: een document, verzameling of berichtbundel (Bundle) dat met PUT naar /fhir/Bundle/{id} wordt verzonden, wordt in zijn geheel bewaard, bij elke release wordt elke entry gelezen en kan worden gevonden met type, identifier, timestamp en composition. Een transactie die daar met PUT wordt verzonden, wordt bewaard als een record en niet toegepast; een POST naar /fhir past deze toe.

Antwoorden zijn JSON, tenzij de client XML vraagt (Accept: application/fhir+xml, of _format=xml). Perfuse leest alleen JSON: een body die als XML wordt verzonden, krijgt 415. Een document Bundle dat naar /fhir wordt gepost, wordt bewaard wanneer deze server, op basis van identifier, de patiënt en het onderzoek waarvan de Composition de namen noemt, in bezit heeft, en wordt geweigerd met 422 anders. Een Binary die met Accept wordt gelezen en ingesteld op de eigen content type, antwoordt met de inhoud zelf.

19.7 Instellen en bedienen

19.7.1 Perfuse initialiseren

Maakt de directory-indeling, een voorbeeldkanaal en een servicedefinitie voor het besturingssysteem waarop het wordt uitgevoerd. Niets bestaands wordt vervangen, tenzij u -force doorgeeft.

Perfuse initialiseren -dir /opt/perfuse -service systemd

19.7.2 Perfuse service

Registreert Perfuse als een Windows-service, verwijdert het of rapporteert of het is geïnstalleerd en wordt uitgevoerd. Alleen voor Windows; op Linux is het equivalent het eenheidbestand dat perfuse init voor u kan schrijven. Zie bedrijfsvoering.

19.7.3 Perfuse token

Verstrekt referenties voor machines in plaats van mensen. Een token verloopt niet en wordt niet beïnvloed door iemand die afmeldt, wat een server nodig heeft die zijn buurman pollt en wat een browsersessie expres niet is.

Perfuse token maken -db perfuse.db -label vloot-van-site-a -rol viewer perfuse token lijst -db perfuse.db perfuse token intrekken -db perfuse.db -label vloot-van-site-a

Alleen de hash wordt opgeslagen, dus een token wordt één keer weergegeven wanneer het wordt gemaakt en kan later niet worden hersteld. Een gestolen database levert dus geen bruikbaar token op. Geef een token de laagste rol die het werk doet: een vlootweergave heeft viewer nodig, en niets dat alleen leest moet meer hebben.

-fhir-groups riverside-attributed,riverside-north beperkt een token tot die FHIR-groepen, voor een CMS-0057 Provider Access-export van een zorgverlener: op het FHIR-eindpunt kan het deze groepen lezen en exporteren, en niets anders. Zie CMS-0057 voor verzekeraars.

19.7.4 perfuse athena

Drukt de Amazon Athena CREATE EXTERNAL TABLE af voor een S3-archief dat is geschreven met format: ndjson, met partitieprojectie op het dt=YYYY-MM-DD-deel van de sleutel, zodat geen crawler hoeft te worden uitgevoerd wanneer dagen worden toegevoegd.

perfuse athena -bucket hospital-archive -destination archief

In plaats van uitgevoerd te worden, wordt dit afgedrukt, omdat het maken van een tabel Athena- en Glue-machtigingen vereist die dit programma niet zou moeten hebben.

19.7.5 perfuse sbom

Lijst alles wat is gekoppeld aan de binaire code, gelezen uit de build zelf in plaats van uit go.mod — dus beschrijft het de binaire code die voor u ligt en niet wat iemand ooit heeft gevraagd.

-json geeft CycloneDX uit en -spdx geeft SPDX-tag-waarde uit, wat meestal is wat een inkoop- of beveiligingsreview daadwerkelijk vraagt. De browsercode die is ingebed in de binaire code, is inbegrepen, omdat een reviewer die een binaire code tegen waarschuwingen moet matchen, moet weten dat deze een React-toepassing bevat.

19.7.6 perfuse versie

Drukt de versie en de commit af waaruit deze is gebouwd. Het is de moeite waard om in een ticket op te nemen: "de huidige" is geen versie, en twee machines die een week geleden zijn geïnstalleerd, draaien vaak niet dezelfde build.

20 Serveropties

Elke optie die perfuse serve aanneemt, gegenereerd uit het programma zelf, dus deze lijst kan geen optie noemen die niet bestaat of een optie overslaan. De meeste zijn ook een instelling in de webinterface, genoemd in de laatste kolom: een waarde die hier is opgeslagen, wint het van de vlag bij de volgende start, en de vlag blijft de manier om het in te stellen vanuit een servicedefinitie. Het luisteradres, de database en het kanaal blijven vlaggen alleen, omdat ze zeggen waar de server vindt wat het zou bewerken.

Geheimen zijn nooit vlaggen. Een optie die een wachtwoord of token nodig heeft, noemt een omgevingsvariabele die het bevat.

20.1 Alle opties

OptionTakesDefaultWhat it doesIn the console
-addrstring127.0.0.1:8080, or 127.0.0.1:8443 with -tls-certaddress to serve the interface on—
-alert-severitystringwarningminimum severity to send to the webhook: warning or criticalSettings › Alerts › Delivery: Only send alerts at least this serious
-alert-webhookstring—POST alerts to this URL as JSON. Works with Slack, Teams, Mattermost, Alertmanager or anything that accepts a webhook. The payload carries channel names, counts and thresholds; never message contentSettings › Alerts › Delivery: Send alerts to this address
-alertsstring—YAML file of alert rules. Default: alerts.yaml beside the database, written when the rules are first saved in the console; until then a conservative default set is used—
-allow-metadata-egresson/off—permit destinations pointed at cloud instance metadata addresses, which hold this machine's credentialsSettings › Security › What may leave: Allow destinations at cloud instance metadata addresses
-cds-clientsstring—the EHRs trusted to call the CDS services with signed JWTs (issuer and jwks_url)Settings › Payers › Prior authorization: EHRs trusted to call the CDS services
-channelsstring./channelsdirectory holding channel files—
-clusterstring—share the work with other servers on the same PostgreSQL -db: active-passive (one runs everything, another takes over when it stops) or active-active (channels spread over all)—
-cluster-leaseduration15show long a crashed server holds its work before another takes it over; renewed five times as often—
-crd-advisor-castring—a PEM file of certificate authorities to trust for -crd-advisor-url beside the system's (Vaglio's is its DATA/tls/ca.crt)Settings › Payers › Decision service: Certificate authorities to trust for the advice service
-crd-advisor-token-envstring—name of an environment variable holding a bearer token for -crd-advisor-url (the token itself is never a flag)Settings › Payers › Decision service: Environment variable holding the advice service's token
-crd-advisor-urlstring—with -crd-rules, ask the decision service at this URL (such as Vaglio's /api/pas/advise) what a prior authorization request for each order needing one would be told as the record stands, shown as one more CRD card; the prefetched record is POSTed to it. No answer, or any failure, leaves the cards as they are without itSettings › Payers › Decision service: Advice before submitting (CRD)
-crd-rulesstring—a Da Vinci CRD rules file: serve coverage requirements over CDS Hooks at /cds-servicesSettings › Payers › Prior authorization: Coverage rules file (Da Vinci CRD)
-dashboardsstring—a file mapping directory groups and roles to the dashboard each opens onSettings › Monitoring › Dashboards: Which dashboard each group opens on (file)
-datastring—directory for this server's own files (settings, alerts, sign-in configuration, the log): default beside -db when it is a file, the current directory when it is a PostgreSQL URL—
-davinci-versionstring2.2the Da Vinci CRD, DTR and PAS release answered when neither a request nor its client's registration says: 2.2 (CRD 2.2.1, DTR 2.2.0, PAS 2.2.1) or 2.1 (2.1.0)—
-dbstring./perfuse.dbdatabase for users, messages and stored resources: a file, or a postgres:// URL for servers that share one store (a cluster)—
-demo-accountstring—for a public demonstration server: username:password of a shared viewer account shown on the sign-in page—
-dicomweb-archivestring—keep imaging objects in this directory and serve them over DICOMweb (QIDO-RS, WADO-RS, WADO-URI, STOW-RS) at /dicomwebSettings › Data › Imaging archive: Keep images in this folder and serve them over DICOMweb
-dicomweb-corsstring—comma-separated browser origins, such as an OHIF viewer's, allowed to call /dicomwebSettings › Data › Imaging archive: Browser origins allowed to call it
-drain-forduration—after SIGTERM, report not-ready for this long before shutting down (for rolling deploys)Settings › Engine › Shutdown: Wait for in-flight messages on shutdown
-ecr-agencystring—play a public health agency for testing eCR: answer case reports at $process-message with a Reportability Response, using the agency YAML file given (name, phone, address, endpoint; optional rctc, reply)Settings › Public health › Case reporting: Act as a test public health agency
-ecr-responseson/off—accept eCR Reportability Responses at the FHIR endpoint's $process-message, storing each as DocumentReference/<id> derived from the eICR it answersSettings › Public health › Case reporting: Receive Reportability Responses
-engineon/offtruerun the channel engine in this process, so the interface can start, stop and monitor channels—
-epa-payer-idstring—this payer's identifier on the prescribing network, the From of every RTPB and ePA response (default: the formulary's payer id)Settings › Payers › Drug formulary: Payer ID on the prescribing network
-epa-reply-channelstring—route ePA decisions made after the request was answered (a reviewer's, an appeal's) to this channel, which delivers them to the prescriber's networkSettings › Payers › Drug formulary: Channel that sends later ePA decisions
-fhiron/offtrueserve a FHIR endpoint at /fhirSettings › FHIR › The FHIR server: Serve a FHIR endpoint at /fhir
-fhir-api-tokenson/off—with SMART configured, accept Perfuse API tokens on the FHIR endpoint as well (unscoped; the console's FHIR settings can switch it)Settings › FHIR › Access: Accept Perfuse API tokens beside SMART tokens
-fhir-bulk-exporton/off—enable $export, which produces a file holding every record the FHIR endpoint servesSettings › FHIR › Bulk data: Bulk Data export ($export)
-fhir-declaresstring—guides this FHIR server declares in its capability statement, comma-separated: a CapabilityStatement address, or Type=profile addressSettings › FHIR › Capability statement: Guides this server declares
-fhir-max-resourcesint—for a public server: refuse new FHIR resources once this many are held (0: no limit)Settings › FHIR › Access: Most resources held
-fhir-member-match-without-consenton/off—let $member-match answer without an active Consent; the Payer-to-Payer API is opt-in, so only for testingSettings › Payers › CMS-0057-F: Answer $member-match without the member's consent
-fhir-openon/off—serve the FHIR endpoint with no authentication at all, exposing every stored recordSettings › FHIR › Access: Let anyone read the FHIR endpoint without signing in
-fhir-patient-directory-searchon/off—let a token limited to one patient search the directory (practitioners, organisations, locations) within its scopesSettings › FHIR › Access: Let a patient's app search the directory
-fhir-payer-apison/off—enable the CMS-0057 payer operations: $member-match (Payer-to-Payer) and Group $davinci-data-export (Provider Access); the Group exports also need -fhir-bulk-exportSettings › Payers › CMS-0057-F: The CMS-0057-F payer APIs
-fhir-read-onlyon/off—refuse writes to the FHIR endpointSettings › FHIR › Access: Refuse writes to the FHIR endpoint
-fhir-subscriptionson/off—enable topic-based subscriptions, which send encounter and appointment notifications to URLs FHIR clients chooseSettings › FHIR › Notifications: FHIR subscriptions (encounter and appointment notifications)
-fhir-subscriptions-allow-httpon/off—let subscriptions deliver to plain-http endpoints; for a test receiver, never for patient data on a networkSettings › FHIR › Notifications: Allow subscriptions to notify plain-HTTP addresses
-fhir-versionstring4.0.1FHIR release to serve: R4, R4B or R5Settings › FHIR › The FHIR server: FHIR version clients see
-fhir-writes-per-minuteint—for a public server: writes one client address may make to the FHIR endpoint a minute (0: no limit)Settings › FHIR › Access: Writes a minute from one client
-fleet-labelstring—how this instance names itself in a fleet view (default: hostname)Settings › Fleet › This server: Name for this server
-formularystring—publish this drug formulary over the Da Vinci US Drug Formulary API at /formulary/fhir and answer NCPDP Real-Time Prescription Benefit and SCRIPT electronic prior authorization from itSettings › Payers › Drug formulary: Drug formulary file
-icd11-client-idstring—a WHO ICD API client: ICD-11 codes not imported are looked up thereSettings › Data › Code systems: WHO ICD API client ID
-icd11-client-secretstring—the WHO ICD API client's secretSettings › Data › Code systems: WHO ICD API client secret
-icd11-releasestring2025-01the ICD-11 MMS release the WHO ICD API is asked aboutSettings › Data › Code systems: ICD-11 release to ask for
-icd11-urlstring—the ICD API's address when it is not the WHO's: the WHO's ICD-API container on your network needs no clientSettings › Data › Code systems: ICD API address
-index-identityon/offtrueindex patient identifiers from message contents so a message can be found by MRN, name or accession in any format; has no effect when -store-payloads is offSettings › Data › What is kept: Index patient identifiers
-insecureon/off—serve over plain HTTP on a non-loopback address (not recommended)—
-inventorystring—write a Markdown inventory of every interface to this file, and keep it currentSettings › Monitoring › Inventory: Write an interface inventory to
-inventory-everyduration24h0m0show often to rewrite the interface inventorySettings › Monitoring › Inventory: Rewrite the inventory every
-json-logson/off—emit structured JSON logsSettings › Monitoring › Logging: Write logs as JSON
-ldapstring—YAML file configuring directory (LDAP) sign-in (default: ldap.yaml beside the database, once saved in the console)—
-log-filestring—append the log, and the first administrator's one-time password, to this file (mode 0600) instead of the console. A Windows service has no console, so there it defaults to perfuse.log beside the database—
-mcpon/off—serve the Model Context Protocol at /mcp, so AI agents with an API token can read status, messages, the queue, alerts and the FHIR store with that token's own accessSettings › Security › AI agents (MCP): Let AI agents connect over MCP
-measure-reporterstringPerfusethe reporting organisation's name on MeasureReports from $evaluate-measure when the request names no reporter—
-metrics-openon/off—serve /metrics to anybody who can reach the port. Only safe where that port is genuinely private: metric labels name your channels, and on a multi-tenant server they name every tenant'sSettings › Security › Metrics: Serve /metrics without a token
-metrics-tokenstring—credential the Prometheus scrape endpoint requires. Give the scraper the same value in bearer_token_file. Without this, only a signed-in operator can read /metricsSettings › Security › Metrics: Token a metrics scraper presents
-mpion/off—keep a patient index (master patient index) in mpi.db beside the database: patient records from every system linked into one enterprise identifier per person, fed by mpi destinations and the PIX v3 identity feed, answering Patient/$match, PIXm, PIX v3 (/pixv3) and PDQ v3 (/pdqv3)Settings › Data › Patient index: Keep a patient index
-multi-tenanton/off—keep each tenant's channels in their own subdirectory of -channels, so one server can run integration for several organisations without them being able to see each other—
-node-addressstring—this server's console URL as the other servers and a load balancer reach it—
-node-namestring—this server's name in the cluster (default: an id kept in -data)—
-oidcstring—YAML file configuring OpenID Connect sign-in (default: oidc.yaml beside the database, once saved in the console)—
-pason/off—serve Da Vinci PAS 2.2.1 and 2.1.0 (Claim/$submit, $inquire, $decide) on the FHIR endpoint; decisions come from -crd-rules, and what no rule decides is pended for a reviewer. With -fhir-subscriptions, the PAS topic delivers each pended request's resultSettings › Payers › Prior authorization: Da Vinci PAS prior authorization server
-pas-278-castring—a PEM file of certificate authorities to trust for the UM system beside the system'sSettings › Payers › Utilization management link: Certificate authorities to trust for the UM system
-pas-278-certstring—a PEM client certificate for X.509 mutual TLS with the UM system (CORE's authentication)Settings › Payers › Utilization management link: Client certificate file
-pas-278-core-receiverstring—the CORE envelope's ReceiverID, as the UM system's connectivity guide gives it (default: -pas-278-receiver)Settings › Payers › Utilization management link: CORE envelope ReceiverID
-pas-278-core-rule-versionstring—what to write in the CORE envelope's CORERuleVersion when the UM system's guide asks for something other than the version itself (CMS esMD's sample says v2.2.0)Settings › Payers › Utilization management link: CORERuleVersion written in the envelope
-pas-278-core-senderstring—the CORE envelope's SenderID, as the UM system's connectivity guide gives it (default: -pas-278-sender)Settings › Payers › Utilization management link: CORE envelope SenderID
-pas-278-core-versionstring2.2.0the CAQH CORE Connectivity Rule the UM system runs, for core-soap and core-mime: 2.2.0 (payload in the envelope) or C4.0.0 (payload as an MTOM attachment; SOAP only)Settings › Payers › Utilization management link: CAQH CORE Connectivity Rule
-pas-278-keystring—the private key (PEM) for -pas-278-certSettings › Payers › Utilization management link: Client certificate key file
-pas-278-oauth-client-idstring—the OAuth client ID for -pas-278-oauth-token-urlSettings › Payers › Utilization management link: OAuth client ID
-pas-278-oauth-scopestring—the scope asked for with the OAuth token, when the UM system wants oneSettings › Payers › Utilization management link: OAuth scope
-pas-278-oauth-secret-envstring—name of an environment variable holding the OAuth client secret (the secret itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the OAuth client secret
-pas-278-oauth-token-urlstring—an OAuth 2.0 token endpoint: a token got with the client-credentials grant is sent as a bearer token (CORE vC4.0.0's authorization)Settings › Payers › Utilization management link: OAuth token endpoint
-pas-278-password-envstring—name of an environment variable holding the password for -pas-278-user (the password itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the password
-pas-278-payer-idstring—the UMO's payer ID (NM1*X3) when the request's insurer carries no identifierSettings › Payers › Utilization management link: Payer ID for the 278s
-pas-278-productionon/off—mark the 278s sent as production (ISA15 P) rather than testSettings › Payers › Utilization management link: Mark the 278s as production
-pas-278-receiverstring—ISA08/GS03 receiver ID on the 278s sent to the UM systemSettings › Payers › Utilization management link: Receiver ID on the 278s
-pas-278-senderstringPERFUSEISA06/GS02 sender ID on the 278s sent to the UM systemSettings › Payers › Utilization management link: Sender ID on the 278s
-pas-278-sftpstring—host:port of the UM system's SFTP server, for -pas-278-transport sftpSettings › Payers › Utilization management link: SFTP server
-pas-278-sftp-everyduration1m0show often the SFTP inbound folder is readSettings › Payers › Utilization management link: Read the SFTP inbound folder every
-pas-278-sftp-inboundstring—the SFTP folder the UM system's 278 responses, 999s and TA1s are collected fromSettings › Payers › Utilization management link: SFTP inbound folder
-pas-278-sftp-keystring—an OpenSSH private key file for the SFTP user, instead of a passwordSettings › Payers › Utilization management link: SFTP key file
-pas-278-sftp-known-hostsstring—an OpenSSH known_hosts file holding the SFTP server's key; required, so requests never go to whoever answersSettings › Payers › Utilization management link: SFTP known_hosts file
-pas-278-sftp-outboundstring—the SFTP folder the 278 requests (and the 999s for the answers) are put inSettings › Payers › Utilization management link: SFTP outbound folder
-pas-278-sftp-password-envstring—name of an environment variable holding the SFTP password (the password itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the SFTP password
-pas-278-sftp-userstring—the SFTP user nameSettings › Payers › Utilization management link: SFTP user
-pas-278-token-envstring—name of an environment variable holding a bearer token for the UM system (the token itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the token
-pas-278-transportstringx12how the 278s reach the UM system: x12 (POSTed as application/edi-x12), core-soap (a CAQH CORE SOAP envelope), core-mime (CAQH CORE HTTP MIME multipart), or sftp (batch files over -pas-278-sftp, answers collected from its inbound folder)Settings › Payers › Utilization management link: How the 278s travel
-pas-278-urlstring—forward every PAS request to the payer's utilization management system as an X12 278 request sent to this URL (by -pas-278-transport), and answer with its 278 response; later 278 responses go to Claim/$decide-278Settings › Payers › Utilization management link: Send PAS requests on to the UM system at
-pas-278-userstring—user name for the UM system: CORE's UserName (WS-Security UsernameToken in SOAP), or HTTP Basic for x12Settings › Payers › Utilization management link: User name
-pas-decider-castring—a PEM file of certificate authorities to trust for -pas-decider-url beside the system's, such as the payer's own authority or the decision service's (Vaglio's is its DATA/tls/ca.crt)Settings › Payers › Decision service: Certificate authorities to trust for the decision service
-pas-decider-token-envstring—name of an environment variable holding a bearer token for -pas-decider-url (the token itself is never a flag)Settings › Payers › Decision service: Environment variable holding the decision service's token
-pas-decider-urlstring—ask the decision service at this URL (such as Vaglio) to decide each PAS item on the request's clinical evidence, when -crd-rules leave it to a reviewer; the PAS request Bundle is POSTed to it. Cannot be combined with -pas-278-urlSettings › Payers › Decision service: Decision service URL
-passkey-allowed-modelsstring—comma-separated authenticator AAGUIDs that may enrol; requires -passkey-attestation-roots—
-passkey-attestation-rootsstring—a PEM file of authenticator vendor certificates; passkey attestation is verified against these—
-passkey-domainstring—the bare domain passkeys are registered for, such as perfuse.example.org. No scheme, no port, no path. Setting it turns passkeys on; leaving it empty leaves them offSettings › Sign-in › Passkeys: Domain passkeys are bound to
-passkey-namestringPerfusethe name an authenticator shows a person when they register a passkeySettings › Sign-in › Passkeys: Name shown on the device
-passkey-originsstring—comma-separated origins the console is reached at, with scheme and port: https://perfuse.example.org. Defaults to https:// plus the domainSettings › Sign-in › Passkeys: Other origins passkeys are accepted from
-peersstring—YAML file listing other Perfuse instances to show in a fleet viewSettings › Fleet › Fleet: Other Perfuse servers to show (file)
-public-urlstring—the https address patients' phones and other organisations reach this server at, for the SMART Health Links it hosts (default: the listen address)Settings › FHIR › The FHIR server: Address others reach this server at
-rctcstring—eCR trigger codes for the case report preview: a FHIR ValueSet or Bundle of them, such as the eRSDSettings › Public health › Case reporting: Trigger codes file (RCTC or eRSD)
-residencystring—cloud regions this server's data may go to or come from: areas (eea, uk, ch) and region codes (eu-central-1), comma-separated; channels with connectors elsewhere are refusedSettings › Data › Data protection: Where data may go (cloud regions)
-retention-daysint30how long to keep recorded messages; 0 keeps them for ever, which will eventually fill the diskSettings › Data › How long it is kept: Delete records after
-samlstring—YAML file configuring SAML 2.0 sign-in (default: saml.yaml beside the database, once saved in the console)—
-scimon/off—accept SCIM 2.0 provisioning from an identity provider at /scim/v2. Okta, Entra ID and Google Workspace use it to create accounts and, more importantly, to disable them when somebody leavesSettings › Sign-in › Automatic accounts: Let the identity provider manage accounts
-scim-default-rolestringviewerrole for an account the identity provider does not describe. Defaults downward on purpose: an account whose role could not be determined should be able to read and nothing else—
-settingsstring—settings file the web interface may edit (default: perfuse-settings.yaml beside the database)—
-shl-allow-httpon/off—let a received SMART Health Link point at plain HTTP; for testing onlySettings › Public health › Health links: Allow SMART Health Links over plain HTTP
-signing-certstring—certificate for signing documents (defaults to -tls-cert)Settings › Security › Document signing: Certificate for signing documents
-signing-keystring—key for signing documents (defaults to -tls-key)Settings › Security › Document signing: Key for signing documents
-smart-audiencestring—the audience a SMART token must be issued for, normally the FHIR base URLSettings › SMART › Authorization: Audience tokens must name
-smart-authorizestring—the authorization endpoint to advertise to SMART appsSettings › SMART › Authorization: Authorization endpoint
-smart-backend-serviceson/off—advertise that the SMART authorization server issues backend-services (client_credentials, signed JWT) tokensSettings › SMART › Built-in server: Backend Services (system-to-system tokens)
-smart-clientsstring—run Perfuse's own SMART authorization server at /auth for the apps registered in this YAML fileSettings › SMART › Built-in server: Registered apps file (turns on the built-in server)
-smart-issuerstring—accept SMART on FHIR access tokens from this authorization serverSettings › SMART › Authorization: Accept SMART access tokens from this authorization server
-smart-jwksstring—where to fetch the SMART issuer's signing keys, when not from its published metadata (split DNS, a private address)Settings › SMART › Authorization: Key set file
-smart-jwks-uristring—the authorization server's public key set URL, advertised to SMART apps (needed to claim OpenID Connect sign-in)Settings › SMART › Authorization: Key set address
-smart-keystringsmart-signing.keythe built-in authorization server's RSA signing key (PEM, mode 0600), created if missingSettings › SMART › Built-in server: Signing key file
-smart-oidcstring—with -smart-users, let people sign in at this OpenID Connect provider (YAML: issuer, client_id, client_secret_file or client_secret_env, label); each is linked by oidc_subjectSettings › SMART › Built-in server: Sign people in through the OpenID Connect provider
-smart-tokenstring—the token endpoint to advertise to SMART appsSettings › SMART › Authorization: Token endpoint
-smart-usersstring—with -smart-clients, the people who may sign in to authorize apps (YAML: username, password_hash, fhir_user)Settings › SMART › Built-in server: People who sign in to authorize apps (file)
-snmp-allowstring—comma-separated networks or addresses the SNMP agent answers, such as 10.0.5.0/24; required with -snmp-listenSettings › Monitoring › SNMP: Networks that may ask
-snmp-base-oidstring1.3.6.1.4.1.8072.9999.9999.16, Net-SNMP's experimental spacewhere Perfuse's values sit, under your enterprise numberSettings › Monitoring › SNMP: Base OID
-snmp-communitystring—the SNMPv2c community (a password sent in clear: at least 6 characters, not public or private)Settings › Monitoring › SNMP: SNMP community
-snmp-contactstring—sysContact the SNMP agent reportsSettings › Monitoring › SNMP: Contact (sysContact)
-snmp-listenstring—answer SNMPv2c GET/GETNEXT/GETBULK on this UDP address, such as :161 (off when empty). Read-only: channel states, counts and queue depthsSettings › Monitoring › SNMP: Answer SNMP on this address
-snmp-locationstring—sysLocation the SNMP agent reportsSettings › Monitoring › SNMP: Location (sysLocation)
-snmp-trapsstring—comma-separated managers (host or host:port, default port 162) that receive an SNMPv2 trap when an alert fires or resolvesSettings › Monitoring › SNMP: Send traps to
-store-messageson/offtruerecord every message handled, which is what makes the message browser workSettings › Data › What is kept: Keep a record of each message
-store-payloadson/offtruestore message contents as well as their outcomes; turn this off where PHI must not be held at restSettings › Data › What is kept: Keep message contents
-tls-certstring—TLS certificate fileSettings › Security › Encryption: TLS certificate file
-tls-keystring—TLS private key fileSettings › Security › Encryption: TLS private key file
-trace-endpointstring—OTLP/HTTP base URL to export message traces to, for example http://localhost:4318Settings › Monitoring › Tracing: Send traces to
-trace-instancestring—name for this instance in traces; defaults to the hostname, which is what distinguishes replicasSettings › Monitoring › Tracing: This instance's name in traces
-trace-samplefloat1fraction of traces to record, 0 to 1—
-tsa-urlstring—RFC 3161 time-stamping authority for DSDR signatures on claims attachmentsSettings › Security › Document signing: Time-stamping authority
-vpnstring—partner VPN tunnels to report on the Connections dashboard (YAML: AWS Site-to-Site VPN, Azure VPN Gateway or strongSwan, and both sides' settings); see examples/vpn.yamlSettings › Monitoring › Connections: VPN tunnels to watch (file)
-watch-accesson/offtruewatch traffic and reads of patient data for what a breach looks like (bursts, night traffic, new destinations, bulk reads) and raise alerts—
-xdsstring—keep clinical documents here as an IHE XDS.b registry and repository with this repository uniqueId (an OID), answering ITI-41, ITI-42, ITI-18 and ITI-43 at /xds/repository and /xds/registrySettings › Data › Document sharing (IHE XDS): Keep documents here as an XDS registry and repository
-xds-home-communitystring—this community's home community id (urn:oid:...), so /xca/gateway answers XCA ITI-38 and ITI-39 for itSettings › Data › Document sharing (IHE XDS): Home community id, for XCA

21 Kanaalverwijzing

Elke sleutel die op het hoogste niveau van een kanaalbestand kan verschijnen. Deze worden uit de bron gehaald, dus dit hoofdstuk kan geen optie beschrijven die niet bestaat of een optie weglaten die wel bestaat.

21.1 Kanaal

Een kanaal is één geconfigureerde berichtenstroom: ergens arriveren berichten, een optionele filter en één of meer plaatsen waar ze naartoe gaan.

Gedefinieerd als Channel in internal/config.

SleutelTypeVereistStandaard
nametekstja—
descriptiontekstnee—
grouptekstnee—
attachmentsBijlagen (een blok, weglaten om niets op te nemen)nee—
delimitedBegrensd (een blok, weglaten om niets op te nemen)nee—
tableslijst van tekstnee—
contractContractRef (een blok, weglaten om niets op te nemen)nee—
enabledtrue of false (een blok, weglaten om niets op te nemen)nee—
dataTypeDataTypeneehl7
hl7v3HL7v3Options (een blok, weglaten om niets op te nemen)nee—
x12X12Options (een blok, weglaten om niets op te nemen)nee—
ncpdpNCPDPOptions (een blok, weglaten om niets op te nemen)nee—
edifactEDIFACTOptions (een blok, weglaten om niets op te nemen)nee—
scriptScriptOptions (een blok, weglaten om niets op te nemen)nee—
dicomDICOMOptions (een blok, weglaten om niets op te nemen)nee—
sourceBronja—
filtertekstnee—
transformationslijst van transform.Stepnee—
scriptsScripts (een blok, weglaten om niets op te nemen)nee—
shadowShadow (een blok, weglaten om niets op te nemen)nee—
destinationslijst van Destinationja—

21.1.1 naam

De naam identificeert het kanaal in logboeken en metrische gegevens.

Vereist en uniek.

21.1.2 groep

Een groep is waar dit kanaal deel van uitmaakt, voor het organiseren van een lijst die te lang is geworden om te lezen.

Cosmetisch bij vijf kanalen en structureel bij tweehonderd: de kanalen van een site zijn onderverdeeld in het systeem waarmee ze communiceren, of door het team dat ze bezit, en een platte lijst van tweehonderd namen is onbruikbaar, hoe goed de rest van de interface ook is.

Een gewone tekenreeks in plaats van een groepsobject met zijn eigen bestand, omdat een groep geen gedrag heeft. Het moment dat het een bestand heeft, krijgt het instellingen, en instellingen op een groep betekenen dat het gedrag van een kanaal afhankelijk is van iets dat niet in het kanaal is geschreven - wat het eigenschap is dat Mirth-configuratie moeilijk te begrijpen maakt. Groepen hier zijn een label en niets meer.

21.1.3 bijlagen

Bijlagen verplaatst grote payloads uit het bericht en plaatst ze terug voordat ze worden afgeleverd.

Opt-in per kanaal: een feed van gewone ADT-berichten heeft niets om te extraheren en zou niet moeten betalen voor de machinerie.

21.1.4 begrensd

Begrensd configureert een begrensde kanaal.

Alleen zinvol wanneer het gegevenstype begrensd is.

21.1.5 tabellen

Tabellen noemt bestanden met gedeelde mappingtabellen die een transformatie naar verwijzing kunnen noemen.

Gedeeld omdat de domeinbelasting grotendeels bestaat uit het opnieuw afleiden van een mapping die iemand al heeft afgeleid: de seks codes en patiëntklassen van een site worden op dezelfde manier vertaald in elk kanaal dat ze aanraakt, en een tabel binnen een kanaal is een tabel die alleen dat kanaal kan gebruiken.

21.1.6 ingeschakeld

Ingeschakeld staat standaard op true.

Een uitgeschakeld kanaal wordt geladen en gevalideerd, maar niet gestart, dus een bestand dat tijdelijk is uitgeschakeld, wordt nog steeds gecontroleerd door CI.

21.1.7 gegevenstype

Gegevenstype is het formaat van de berichten die deze kanaal ontvangt.

Standaard is hl7, zodat elk kanaal dat voorheen is geschreven blijft werken.

21.1.8 x12

X12 bevat de instellingen die alleen iets betekenen op een X12-kanaal.

Het instellen ervan op een ander type wordt geweigerd in plaats van genegeerd.

21.1.9 script

Script configureert een NCPDP SCRIPT-kanaal.

De stappen ervan zijn hier ondergebracht in plaats van in de bovenliggende transformaties voor hetzelfde reden als elke andere niet-v2-formaat: de staptypen verschillen per formaat, dus één sleutel zou verschillende dingen betekenen afhankelijk van gegevenstype.

21.1.10 dicom

Beeld configureert de benoemde transformatiestappen van een DICOM-kanaal.

Beeld in plaats van DICOM, omdat Bron en Bestemming al een DICOM-veld hebben en drie velden met dezelfde naam op verschillende niveaus een fout veroorzaken. De yaml-sleutel is dicom, wat iemand die het bestand schrijft verwacht, en de Go-naam is degene die een fout voorkomt op de oproepsite.

21.1.11 filter

Filter is een expressie die waar moet zijn voor een bericht om door te sturen.

Een bericht dat niet overeenkomt, wordt nog steeds bevestigd: de afzender heeft niets verkeerds gedaan, we zijn gewoon niet geïnteresseerd.

21.1.12 transformaties

Transformaties zijn declaratieve wijzigingen die worden toegepast op geaccepteerde berichten, in volgorde, voordat een script wordt uitgevoerd.

Dit is de laag die bedoeld is om het gewone werk te doen: elke stap wordt geverifieerd wanneer het bestand wordt geladen, verschijnt in een diff en kan worden beoordeeld door iemand die geen JavaScript leest.

21.1.13 scripts

Scripts bevat JavaScript voor de gevallen waarin de declaratieve stappen niet kunnen worden uitgedrukt en is wat de scripts van een Mirth-kanaal ongewijzigd in laten vallen.

Een kanaal met een script wordt gemarkeerd als zodanig in de interface, omdat het gedrag niet kan worden vastgesteld door de configuratie te lezen.

21.1.14 schaduw

Schaduw voert een kandidaatversie van dit kanaal ernaast uit en rapporteert waar ze verschillen.

Niets wat het doet kan een ontvanger bereiken.

22 Bronverwijzing

Elke manier waarop een kanaal berichten kan ontvangen, en elke sleutel die elk daarvan accepteert. Een kanaal heeft precies één bron.

22.1 AMQP-bron

AMQPSource ontvangt van een wachtrij of abonnement.

Een bericht wordt alleen geaccepteerd nadat het kanaal het heeft verwerkt. Eentje dat niet kon worden verwerkt, wordt vrijgegeven als een mislukte levering, zodat de broker het opnieuw levert en - op Service Bus, na het maximum aantal leveringen van de wachtrij - het doodlettert.

Gedefinieerd als AMQPSource in internal/config.

SleutelTypeVereistStandaard
prefetchgeheel getalnee10
reconnectduur, zoals 30s of 5mnee5s

22.1.1 prefetch

Prefetch is het aantal berichten dat de broker vooruit mag sturen.

Standaard is 10. Ze worden nog steeds één voor één verwerkt, in volgorde.

22.1.2 reconnect

Reconnect is de wachttijd na een verloren verbinding.

Defaults to 5s.

22.2 AS2-bron

AS2Source ontvangt AS2 (RFC 4130): EDI die via HTTP wordt gepost, ondertekend en versleuteld met S/MIME, en beantwoord met een ontvangstbevestiging (een MDN) met een digest van wat is aangekomen.

De payload is wat het kanaal verwerkt; X12 en EDIFACT zijn de gebruikelijke.

Gedefinieerd als AS2Source in internal/config.

SleutelTypeVereistStandaard
listentekstja—
pathtekstnee—
tlstlsconf.Settings (een blok, weglaten om het weg te laten)nee—
idtekstja—
cert_filetekstja—
key_filetekstja—
partnerslijst van AS2Partnerja—
max_message_sizegeheel getalnee—
duplicate_windowduur, zoals 30s of 5mnee—

22.2.1 path

Path is het URL-pad waarop partners posten.

Default /as2.

22.2.2 tls

TLS dient HTTPS.

De meeste partners vereisen het in hun overeenkomst, bovenop de S/MIME.

22.2.3 id

ID is onze AS2-identifier, die partners verzenden in AS2-To.

Een bericht naar elk ander wordt geweigerd.

22.2.4 partners

Partners zijn degenen die hier berichten naar kunnen sturen.

Een bericht van iemand anders wordt geweigerd.

22.2.5 duplicate_window

DuplicateWindow is de periode waarin een partner zijn Message-ID onthouden wordt, zodat een opnieuw verzonden bericht (de partner heeft onze ontvangstbevestiging niet ontvangen en heeft opnieuw geprobeerd) met een ontvangstbevestiging wordt beantwoord en niet twee keer wordt doorgegeven (RFC 4130, sectie 7.5).

Default 30 days.

22.3 Azure Blob-bron

AzureBlobSource haalt blobs op uit een container-voorvoegsel.

Gedefinieerd als AzureBlobSource in internal/config.

SleutelTypeVereistStandaard
prefixtekstja—
suffixtekstnee—
after_readtekstnee—
move_totekstneeprocessed/
error_prefixtekstneeerror/
poll_intervalduur, zoals 30s of 5mnee30s
max_object_sizegeheel getalnee16 MiB
framedtrue of falsenee—

22.3.1 move_to

MoveTo is de locatie waar een verwerkte blob naartoe verplaatst wordt.

Standaard is dit processed/.

22.3.2 error_prefix

ErrorPrefix is de locatie waar een blob die niet kan worden verwerkt naartoe verplaatst wordt, zodat deze de rest niet blokkeert.

Standaard is dit error/.

22.3.3 poll_interval

PollInterval tussen de lijstingen.

Defaults to 30s.

22.3.4 max_object_size

MaxObjectSize weigert een grotere blob, die op zijn oorspronkelijke locatie blijft.

Standaard is dit 16 MiB.

22.4 Broker-bron

BrokerSource leest berichten van een berichtenbroker.

Mirth's JMS-lezer, bereikt via STOMP omdat JMS een Java-API is in plaats van een protocol. Zie internal/stomp voor de reden waarom STOMP en niet OpenWire wordt gebruikt.

Gedefinieerd als BrokerSource in internal/config.

SleutelTypeVereistStandaard
addrtekstja—
destinationtekstja—
logintekstnee—
passcodetekstnee—
hosttekstneede host van het adres
selectortekstnee—
subscription_idtekstneede kanaalnaam
heartbeatduur, zoals 30s of 5mneedertig seconden
reconnectduur, zoals 30s of 5mneevijf seconden
timeoutduur, zoals 30s of 5mneedertig seconden
tlstlsconf.Settings (een blok, weglaten om niets te doen)nee—

22.4.1 addr

Addr is de host en poort van de broker.

Verplicht. 61613 is de gebruikelijke STOMP-poort.

22.4.2 bestemming

Bestemming is de wachtrij of het onderwerp waaruit gelezen moet worden.

Required.

Brokers spellen deze verschillend - /queue/naam in ActiveMQ, een blote naam in RabbitMQ - dus wordt deze ongewijzigd doorgegeven in plaats van hier samengesteld. Raden zou betekenen dat er tegen één broker gewerkt wordt en stilzwijgend niets gelezen wordt op een andere.

22.4.3 inloggen

Inloggen en wachtwoord verifiëren.

De meeste brokers weigeren een anonieme verbinding.

22.4.4 wachtwoord

Inloggen en wachtwoord verifiëren.

De meeste brokers weigeren een anonieme verbinding.

22.4.5 host

Host is de virtuele host.

Standaard is de host van het adres.

22.4.6 selector

Selector filtert berichten bij de broker.

Een JMS-selector, doorgegeven in plaats van geïnterpreteerd. Filteren bij de broker in plaats van hier betekent dat de berichten die dit kanaal niet wil nooit het netwerk overschrijden - wat op een gedeelde wachtrij het verschil is tussen het lezen van honderd berichten per dag en honderdduizend.

22.4.7 abonnements_id

AbonnementsID benoemt het abonnement.

Standaard is de naam van het kanaal.

Bennoemd in plaats van gegenereerd, omdat een duurzaam abonnement wordt geïdentificeerd door deze: een gegenereerd abonnement zou een nieuw abonnement maken bij elke opstart en de oude abonnementen laten accumuleren met berichten die niemand leest.

22.4.8 hartslag

Hartslag houdt de verbinding in stand.

Standaard is dertig seconden.

Standaard ingeschakeld hier, in tegenstelling tot de standaard van de client, omdat een bron één verbinding openhoudt voor weken. Zonder hartslag ziet een verbinding door een firewall die stilzwijgend de route heeft verwijderd er perfect gezond uit vanuit dit einde en houden berichten gewoon op met aankomen, zonder dat er iets wordt gelogd.

22.4.9 reconnect

Opnieuw verbinden is de tijd die gewacht moet worden voordat opnieuw verbonden wordt na een fout.

Standaard is vijf seconden.

22.4.10 time-out

Time-outgrenzen voor het verbinden.

Standaard is dertig seconden.

22.5 DICOM Query-bron

DICOMQuerySource pollt een archief met C-FIND en genereert een bericht per nieuwe studie.

Mirth heeft geen equivalent connector. De DICOM-ondersteuning is een listener en een verzender - het kan afbeeldingen ontvangen die naar het worden verwezen en deze doorsturen, en dat is alles. Het vragen van een archief wat het bevat is aangevraagd op hun forums sinds 2015.

Wat het waard maakt om te hebben, is niet de query, maar de automatisering: een prefetch die om drie uur 's ochtends wordt uitgevoerd, een reconciliatie die opmerkt dat het archief een studie mist die de RIS zegt dat het bestaat, een werklijst opgebouwd uit wat daadwerkelijk is gescand in plaats van wat is besteld. Dit zijn taken die sites momenteel uitvoeren met een geplande script buiten de engine, wat betekent dat ze onzichtbaar zijn voor de engine - geen retries, geen alarm, geen berichtgeschiedenis.

Gedefinieerd als DICOMQuerySource in internal/config.

SleutelTypeVereistStandaard
addresstekstja—
called_aetekstja—
calling_aetekstnee—
leveltekstneeSTUDY
patient_rootwaar of onwaarnee—
matchtoewijzing van tekst aan tekstnee—
returnlijst van tekstnee—
intervalduur, zoals 30s of 5mja—
windowduur, zoals 30s of 5mnee—
overlapduur, zoals 30s of 5mneeéén uur
limitgeheel getalnee500
timeoutduur, zoals 30s of 5mneetwee minuten
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—
emit_on_first_pollwaar of onwaarneefalse

22.5.1 adres

Het adres is de host en poort van het archief.

Required.

Genoemd om overeen te komen met de DICOM-bestemming in plaats van afgekort. De twee waren "adres" en "addr" voor een middag, wat het soort inconsistentie is dat iemand die handmatig een kanaalbestand schrijft, één keer verkeerd doet en vervolgens het hele formaat niet vertrouwt.

22.5.2 called_ae

CalledAE is de AE-titel van het archief.

Vereist in de praktijk: de meeste archieven weigeren een associatie die is geadresseerd aan iets anders, en die weigering wordt gelezen als een storing in plaats van als een configuratiefout.

22.5.3 calling_ae

CallingAE is de AE-titel die Perfuse presenteert.

Archives gebruiken dit meestal voor toegangscontrole.

22.5.4 niveau

Niveau is het queryniveau: PATIËNT, STUDIE, SERIE of AFBEELDING.

Standaard is STUDIE.

STUDIE is de standaard omdat het is wat bijna elke nuttige query wil en omdat de alternatieven mensen verrassen: AFBEELDING-niveau tegen een grote CT retourneert één reactie per slice, wat honderden per studie zijn.

22.5.5 match

Match zijn de querysleutels.

Een waarde filtert; een lege waarde vraagt om het veld terug te geven.

Sleutels zijn genoemd in plaats van genummerd - "PatientID" in plaats van "0010,0020" - omdat een kanaalbestand door mensen wordt gelezen, en een tagnummer in een configuratiebestand een lookup is die elke lezer moet uitvoeren.

22.5.6 retour

Retour zijn velden die moeten worden teruggebracht zonder erop te filteren.

Scheiden van Match met een lege waarde, ook al coderen ze identiek, omdat de bedoeling verschilt en een lezer kan zien welke sleutels de zoekopdracht verfijnen en welke worden verzameld.

22.5.7 interval

Interval is hoe vaak moet worden gepolld.

Required.

22.5.8 venster

Venster is hoe ver elk poll terugkijkt, als een studiedatumgebied.

Nul schakelt geheel datumfilteren uit.

Een venster is wat dit begrenst. Zonder een, vraagt elke poll de archief om alles wat het ooit heeft gehad en gooit het dan weg wat het eerder heeft gezien - wat werkt op een testarchief en is asociaal tegen een echt archief dat miljoenen studies bevat.

22.5.9 overlap

Overlap herhaalt de query zo ver in de reeds gepolde periode.

Standaard is één uur.

Noodzakelijk in plaats van voorzichtig. Een studie kan worden geregistreerd met gisterens datum, onze klok en die van het archief hoeven niet overeen te komen, en een pollgrens die exact overeenkomt met een aankomst verliest het. De overlap herhaalt de vraag, en de reeds gezien-controle stopt de duplicaat - dus de kosten van overlappen zijn een iets grotere query en de kosten van niet overlappen zijn een stilletjes gemiste studie.

22.5.10 limiet

Limiet beperkt de overeenkomsten die worden aanvaard van één poll.

Defaults to 500.

Een limiet in plaats van geen limiet, omdat een verkeerd getypte matchsleutel dit omzet in "geef me alles", en het eerste symptoom daarvan tegen een echt archief is de archiefbeheerder die vraagt wie het aan het belasten is.

22.5.11 time-out

Time-out begrenst één poll.

Standaard is twee minuten.

22.5.12 emit_on_first_poll

EmitOnFirstPoll verzendt berichten voor alles wat de eerste poll vindt.

Standaard is false.

False is van belang. Dit richten op een archief dat al een miljoen studies bevat en een bericht verzenden voor elk is niet een nuttige eerste run, en het is het soort fout dat stroomafwaarts wordt opgemerkt in plaats van hier. De eerste poll registreert wat bestaat en verzendt niets; de tweede poll en verder rapporteert wat nieuw is.

22.6 DICOM-bron

DICOMBron ontvangt beeldobjecten als een C-STORE-serviceklasseprovider.

Wat een ziekenhuis een modaliteit of een PACS naar wijst. Mirth noemt dit de DICOM-Listener en het doet alleen C-STORE, dus dit is gelijkwaardigheid in plaats van een subset.

Gedefinieerd als DICOMSource in internal/config.

SleutelTypeVereistStandaard
listentekstja—
ae_titletekstnee—
allowed_calling_aelijst van tekstnee—
sop_classeslijst van tekstnee—
transfer_syntaxeslijst van tekstnee—
max_object_bytesgeheel getalnee—
idle_timeoutduur, zoals 30s of 5mnee—
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—

22.6.1 listen

Listen is het adres waarop de service moet luisteren.

Vereist. 104 is de geregistreerde DICOM-poort; 11112 is het gebruikelijke alternatief wanneer het binden van een bevoorrechte poort niet mogelijk is.

22.6.2 ae_title

AETitle is de naam die deze endpoint gebruikt om zichzelf aan te duiden.

Sterk aanbevolen in plaats van vereist, en gewaarschuwd wanneer afwezig. De enige toegangscontrole op een DICOM-endpoint is vaak de AE-titel, dus een endpoint dat elke titel accepteert, accepteert alles wat het kan bereiken.

22.6.3 allowed_calling_ae

AllowedCallingAE geeft de AE-titels weer die zijn toegestaan om verbinding te maken.

Leeg accepteert elke beller.

Dit is de toegangscontrole die DICOM daadwerkelijk heeft. Een PACS wordt routinematig geconfigureerd om één genoemde beller te accepteren en alles anders te weigeren, en deze kant had geen equivalent: de genoemde titel werd gecontroleerd - die is de naam die de beller intoetst, dus iedereen kan deze correct verzenden - terwijl degene die belde, in het logboek werd opgenomen en verder genegeerd.

Leeg accepteert nog steeds alles, omdat een modality die niemand heeft opgenomen de normale staat is van een eerste installatie en weigeren per standaard zou elke implementatie op de eerste dag breken. In plaats daarvan wordt er een waarschuwing gegeven, en de waarschuwing noemt de titels die zijn verbonden, zodat iemand deze kan invullen op basis van wat daadwerkelijk is aangekomen.

22.6.4 sop_classes

SOPClasses beperkt de soorten objecten die worden geaccepteerd.

Leeg accepteert elke.

Leeg is een redelijke standaard hier, omdat deze engine objecten doorgeeft in plaats van ze te interpreteren, dus weigeren van een onbekende klasse zou geldige afbeeldingen weigeren zonder enig voordeel.

22.6.5 transfer_syntaxes

TransferSyntaxes beperkt de coderingen die worden geaccepteerd, in voorkeursvolgorde.

Leeg accepteert de drie ongecomprimeerde.

22.6.6 max_object_bytes

MaxObjectBytes begrenst één ontvangen object.

Nul past een standaard toe.

22.6.7 idle_timeout

IdleTimeout sluit een associatie die stil is geworden.

Nul betekent nooit, wat meestal correct is - een modaliteit houdt een associatie open tussen studies.

22.6.8 tls

TLS versleutelt inkomende associaties en kan een clientcertificaat vereisen.

Het is de moeite waard om dit duidelijk te zeggen: Mirth heeft zijn betaalde SSL Manager-extensie nodig voor dit, en de community-forks kunnen deze helemaal niet leveren. DICOM bevat patiëntnamen in zijn metadata, dus dit is een van de plaatsen waarbij het een herschrijving zijn in plaats van een fork een echt voordeel is in plaats van een stylistische.

22.7 DICOM-webbron

DICOMwebSource accepteert STOW-RS-verzoeken.

Gedefinieerd als DICOMwebSource in internal/config.

SleutelTypeVereistStandaard
listentekstja—
pathtekstnee/dicom-web
tokentekstnee—
usernametekstnee—
passwordtekstnee—
max_object_bytesgeheel getalnee—
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—

22.7.1 listen

Listen is het adres waarop de service moet luisteren.

Required.

22.7.2 path

Het pad is de servicewortel.

Objecten worden geaccepteerd op Pad/studies en Pad/studies/{uid}. Standaard is /dicom-web, wat Orthanc en dcm4chee gebruiken, dus een verzender die is geconfigureerd voor een van beide, hoeft alleen het hostadres te wijzigen.

22.7.3 token

Token, wanneer ingesteld, is vereist als een bearer-token.

Gebruikersnaam en wachtwoord vereisen HTTP-basicauthenticatie.

22.7.4 gebruikersnaam

Token, wanneer ingesteld, is vereist als een bearer-token.

Gebruikersnaam en wachtwoord vereisen HTTP-basicauthenticatie.

22.7.5 wachtwoord

Token, wanneer ingesteld, is vereist als een bearer-token.

Gebruikersnaam en wachtwoord vereisen HTTP-basicauthenticatie.

22.8 Databron

DatabaseSource leest rijen uit een database en maakt er elk een bericht van.

Dit is hoe een groot aantal ziekenhuisinterfaces daadwerkelijk begint. Een afdelingsysteem heeft geen HL7-mogelijkheid, dus iemand schrijft rijen in een tussenliggende tabel en de interface-engine pollt deze. Het is niet glamoureus en het is overal.

Het is ook de meest voorkomende manier waarop een Mirth-kanaal vastloopt, en de reden is bijna altijd van dezelfde vorm: een rij die niet kan worden verwerkt, wordt gelezen, mislukt en wordt opnieuw gelezen, voor altijd, omdat niets deze heeft gemarkeerd. Het kanaal lijkt actief. De wachtrij lijkt leeg. Niets beweegt, en elk bericht achter de slechte rij wacht op een rij die nooit zal slagen.

Het grootste deel van het ontwerp hier gaat over dat.

Gedefinieerd als DatabaseSource in internal/config.

SleutelTypeVereistStandaard
drivertekstja—
dsntekstja—
querytekstja—
after_querytekstnee—
key_columntekstnee—
templatetekstnee—
columntekstnee—
poll_intervalduur, zoals 30s of 5mnee—
batch_sizegeheel getalnee100
max_attemptsgeheel getalnee3
query_timeoutduur, zoals 30s of 5mnee30s

22.8.1 stuurprogramma

Stuurprogramma noemt de database.

See SupportedDrivers.

22.8.2 dsn

DSN is de verbindingstekenreeks.

Verkiez een omgevingsvariabele-verwijzing boven een letterlijke waarde, omdat dit meestal een wachtwoord bevat en kanalen bedoeld zijn om in git te worden opgeslagen.

22.8.3 query

Query selecteert de rijen die wachten om te worden verstuurd.

Required.

Het moet een SELECT zijn. Een poll die stilletjes schrijft, zou op een schema worden uitgevoerd zonder enig record van wat het heeft gewijzigd.

22.8.4 after_query

AfterQuery markeert een rij als verwerkt en wordt uitgevoerd met de sleutel van de rij gebonden aan deze.

Strongly recommended.

Zonder dit, leest elke poll elke rij opnieuw die de query nog steeds overeenkomt, dus de query zelf moet verwerkte rijen op een andere manier uitsluiten. Als geen van beide waar is, verzendt het kanaal dezelfde rijen voor altijd, wat een duplicaatstorm is in plaats van een stilstand en mogelijk erger is.

22.8.5 key_column

KeyColumn identificeert een rij voor AfterQuery, quarantaine en deduplicatie.

Vereist wanneer AfterQuery is ingesteld.

22.8.6 template

Template bouwt een bericht van een rij.

Ofwel dit of Kolom is vereist.

Kolomverwijzingen gebruiken ${kolom_naam}. Ontbrekende kolommen zijn een fout bij het laden in plaats van een lege tekenreeks in een klinisch bericht.

22.8.7 batch_size

BatchSize beperkt het aantal rijen dat per poll wordt genomen.

Defaults to 100.

Beperkt omdat een onbeperkte eerste poll tegen een tabel die iemand al een jaar aan het vullen is, alles in het geheugen zou lezen en vervolgens alles zou verzenden, wat de manier is waarop een migratie een live-ontvanger overspoelt.

22.8.8 max_attempts

MaxAttempts is het aantal keren dat een enkele rij kan mislukken voordat deze in quarantaine wordt geplaatst en de poll verdergaat.

Defaults to 3.

Dit is de instelling die de stilstand voorkomt. Altijd opnieuw proberen is geen veerkracht; het is één slechte rij die een ziekenhuisfeed tegenhoudt.

22.8.9 query_timeout

QueryTimeout beperkt een enkele poll.

Defaults to 30s.

22.9 Directe Bron

DirecteBron ontvangt Direct-mail die de HISP levert: een SMTP-luisteraar voor het e-mailadres.

Elk bericht wordt ontsleuteld, de handtekening wordt gecontroleerd tegen de ankers en de ondertekenaar tegen Van, en de inhoud wordt doorgegeven: een XDM-pakketdocument, anders elk bijlage, anders de tekst.

Gedefinieerd als DirectSource in internal/config.

KeyTypeRequiredDefault
listentextno—
tls_certtextno—
tls_keytextno—
max_byteswhole numberno—
smtp_hosttextno—
usernametextno—
passwordtextno—
imapDirectIMAP (a block, omit to leave off)no—
xdrDirectXDR (a block, omit to leave off)no—

22.9.1 smtp_host

SMTPHost, Username en Password zijn de HISP's submission server, die wordt gebruikt om een 'verwerkte' leveringsmelding (MDN) naar de afzender te sturen zodra een bericht is opgehaald.

Zonder dit, wordt geen melding verzonden.

22.9.2 gebruikersnaam

SMTPHost, Username en Password zijn de HISP's submission server, die wordt gebruikt om een 'verwerkte' leveringsmelding (MDN) naar de afzender te sturen zodra een bericht is opgehaald.

Zonder dit, wordt geen melding verzonden.

22.9.3 wachtwoord

SMTPHost, Username en Password zijn de HISP's submission server, die wordt gebruikt om een 'verwerkte' leveringsmelding (MDN) naar de afzender te sturen zodra een bericht is opgehaald.

Zonder dit, wordt geen melding verzonden.

22.10 E-mailbron

E-mailbron leest e-mail uit een postbus en zet bijlagen, bodies of hele berichten om in berichten.

Gedefinieerd als EmailSource in internal/config.

SleutelTypeVereistStandaard
protocoltekstnee—
hosttekstja—
portgeheel getalnee—
securitytekstnee—
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—
usernametekstja—
passwordtekstnee—
oauthEmailOAuth (een blok, weglaten om niet te gebruiken)nee—
mailboxtekstnee—
taketekstnee—
attachment_nameslijst van tekstnee—
allowed_senderslijst van tekstnee—
after_readtekstnee—
move_totekstnee—
error_foldertekstnee—
poll_intervalduur, zoals 30s of 5mnee—
max_message_sizegeheel getalnee—

22.10.1 wachtwoord

Wachtwoord kan ${ENV} zijn; voor Gmail een app-wachtwoord.

Wordt genegeerd met oauth.

22.10.2 bijlagenamen

Bijlagenamen beperkt welke bijlagen worden opgehaald, op basis van bestandsnaampatroon (*.hl7).

Leeg haalt elke bijlage op.

22.10.3 toegestane_afzenders

Toegestane afzenders beperkt van wie de e-mail wordt gelezen: adressen en domeinen.

De From-header kan worden vervalst, dus dit houdt ongelukken en ongeoorloofde e-mail tegen, maar niet een aanvaller.

22.10.4 move_to

Verplaatsen naar is de map waarin verwerkte e-mail wordt verplaatst; Standaard is Verwerkt.

Wordt aangemaakt als deze ontbreekt.

22.11 FTP-bron

FTP-bron verzamelt bestanden van een FTP- of FTPS-server.

Waarom FTP nog steeds hier is

Het is dertig jaar geleden dat het aanbevolen werd om het te vervangen en veel ziekenhuissystemen exporteren nog steeds naar FTP: apparaten waarvan de firmware nooit zal worden bijgewerkt, factureringssystemen waarvan de leverancier een vergoeding vraagt voor een wijziging. Weigeren om het te ondersteunen, maakt die systemen niet weg, het betekent dat de integratie-engine niet kan worden gebruikt.

FTPS is standaard. Het is hetzelfde protocol met TLS, de meeste overgebleven servers ondersteunen het en het is een veel gemakkelijker gesprek met een beveiligingsteam dan gewoon FTP.

Gedefinieerd als FTPSource in internal/config.

SleutelTypeVereistStandaard
hosttekstja—
usertekstnee—
passwordtekstnee—
securityftpconn.Securityneeexpliciet
insecure_skip_verifywaar of onwaarnee—
roottekstnee—
timeoutduur, zoals 30s of 5mneedertig seconden

22.11.1 host

Host is de server, met een optionele poort.

Poort 21 wordt verondersteld.

22.11.2 gebruiker

Gebruiker en wachtwoord authenticeren.

Beide mogen leeg worden gelaten voor een anonieme server.

Anonieme FTP wordt nog steeds gebruikt om sommige openbare referentiefeeds te publiceren, dus een lege gebruiker is een legitieme configuratie in plaats van een overschrijding en wordt niet geweigerd. Op een server die wel verwacht dat referenties worden opgegeven, leidt het weglaten ervan tot een aanmeldingsfout bij de verbinding, die wordt gerapporteerd tegen de kanaal in plaats van stilzwijgend opnieuw te worden geprobeerd.

22.11.3 wachtwoord

Gebruiker en wachtwoord authenticeren.

Beide mogen leeg worden gelaten voor een anonieme server.

Anonieme FTP wordt nog steeds gebruikt om sommige openbare referentiefeeds te publiceren, dus een lege gebruiker is een legitieme configuratie in plaats van een overschrijding en wordt niet geweigerd. Op een server die wel verwacht dat referenties worden opgegeven, leidt het weglaten ervan tot een aanmeldingsfout bij de verbinding, die wordt gerapporteerd tegen de kanaal in plaats van stilzwijgend opnieuw te worden geprobeerd.

22.11.4 beveiliging

Beveiliging is expliciet, impliciet of geen.

Standaard is expliciet, wat FTPS is onderhandeld met AUTH TLS op de gewone poort. "Geen" is platte FTP en moet expliciet worden gevraagd.

22.11.5 root

Root is de directory waar elke pad relatief aan is en waartegen de beperkingen worden afgedwongen.

De server heeft geen notie van het: een FTP-server accepteert ../.. als pad. Dus dit is wat voorkomt dat een move_to overal schrijft waar het account toegang toe heeft.

22.11.6 time-out

Time-out begrenst één bewerking, niet de hele poll.

Standaard is dertig seconden.

Per bewerking, omdat een poll die een directory lijst en twintig bestanden ophaalt, eenentwintig bewerkingen doet, en één budget voor allemaal zou een perfect gezonde overdracht van een groot bestand afbreken.

22.12 Bestandsbron

FileSource leest bestanden uit een directory die deze server kan zien.

De connector die een site eerst probeert

Een analyser schrijft resultaten naar een map. Een factureringssysteem laat een batch 's nachts vallen. Radiologie exporteert rapporten naar een directory die iemand jaren geleden heeft gemount. Niets hiervan heeft betrekking op een protocol, en een integratie-engine die geen map kan lezen, faalt bij de evaluatie op de eerste middag.

Gedefinieerd als FileSource in internal/config.

SleutelTypeVereistStandaard
roottekstja—
follow_symlinkswaar of onwaarnee—

22.12.1 root

Root begrenst elk pad dat deze bron aanraakt.

Required.

Los van Dir, zodat move_to en error_dir relatief kunnen zijn en toch worden begrensd. Gegeven alleen Dir, zou een error_dir van "../failed" buiten alles liggen wat de bron was toegestaan, en het weigeren ervan zou willekeurig zijn omdat er niets zou zijn om het tegen te weigeren.

22.13 GCS-bron

GCSSource haalt objecten op uit een bucket-voorvoegsel, net zoals de s3- en azure_blob-bronnen doen.

Gedefinieerd als GCSSource in internal/config.

SleutelTypeVereistStandaard
prefixtekstja—
suffixtekstnee—
after_readtekstnee—
move_totekstneeprocessed/
error_prefixtekstneeerror/
poll_intervalduur, zoals 30s of 5mnee30s
max_object_sizegeheel getalnee16 MiB
framedtrue of falsenee—

22.13.1 move_to

MoveTo is de bestemming waar een afgehandeld object naartoe gaat wanneer after_read is ingesteld op move.

Standaard is dit processed/.

22.13.2 error_prefix

ErrorPrefix is de locatie waar een object dat niet afgehandeld kon worden, naartoe gaat.

Standaard is dit error/.

22.13.3 poll_interval

PollInterval is hoe vaak de prefix wordt opgevraagd.

Defaults to 30s.

22.13.4 max_object_size

MaxObjectSize laat grotere objecten waar ze zijn.

Standaard is dit 16 MiB.

22.14 HTTP-bron

HTTPSource accepteert berichten via HTTP.

Een listener in plaats van een poller: iets posts een bericht en krijgt een bevestiging terug, wat de manier is waarop de moderne helft van het ziekenhuis integreert wanneer MLLP niet beschikbaar is.

Gedefinieerd als HTTPSource in internal/config.

SleutelTypeVereistStandaard
listentekstja—
pathtekstnee"/"
tlstlsconf.Settings (een blok, weglaten om het niet te gebruiken)nee—
tokentekstnee—
max_message_sizegeheel getalnee—
read_timeoutduur, zoals 30s of 5mnee—
ackAcknee—

22.14.1 listen

Listen is het adres waarop de service moet luisteren.

Required.

22.14.2 path

Path is het URL-pad waarop berichten worden geaccepteerd.

Defaults to "/".

22.14.3 token

Token, wanneer ingesteld, is vereist in een Authorization: Bearer-header.

Er is geen standaard en geen anonieme modus-schakelaar: een HTTP-eindpunt op een ziekenhuisnetwerk met geen authenticatie is een beslissing die zichtbaar moet zijn in het bestand, dus leeg laten staat voor een waarschuwing bij het laden.

22.14.4 max_message_size

MaxMessageSize begrenst een inkomend bericht.

Nul past een standaard toe.

22.15 IBMMQ-bron

IBMMQSource leest een wachtrij.

Gedefinieerd als IBMMQSource in internal/config.

SleutelTypeVereistStandaard
poll_intervalduur, zoals 30s of 5mnee2s

22.15.1 poll_interval

PollInterval is de wachttijd wanneer de wachtrij leeg is, of na een bericht dat niet afgehandeld kon worden.

Defaults to 2s.

22.16 Java Script-bron

JavaScriptSource configureert een bron die een script op een timer uitvoert en de geretourneerde berichten in de kanaal voert.

Dit is het equivalent van de Mirth "JavaScript Reader".

Het script wordt uitgevoerd in een goja VM met hetzelfde zandbak als transformatiescripts: msg is niet beschikbaar (er is nog geen inkomend bericht), maar globalMap, configurationMap, logger en DateUtil zijn aanwezig. Het script moet een tekenreeks (één bericht) of een array van tekenreeksen (meerdere) retourneren. Niets retourneren of een lege array retourneren betekent dat de poll geen berichten produceerde, wat normaal is.

Gedefinieerd als JavaScriptSource in internal/config.

SleutelTypeVereistStandaard
scripttekstja—
poll_intervalduur, zoals 30s of 5mnee—
timeoutduur, zoals 30s of 5mnee—

22.16.1 poll_interval

PollInterval geeft aan hoe vaak het script wordt uitgevoerd.

Nul betekent 5 seconden.

22.16.2 time-out

Timeout begrenst de uitvoering van een enkel script.

Nul betekent 30 seconden.

22.17 Kafka-bron

KafkaSource leest berichten uit een Kafka-onderwerp.

Gedefinieerd als KafkaSource in internal/config.

SleutelTypeVereistStandaard
brokerslijst van tekstja—
topicslijst van tekstja—
grouptekstja—
from_beginningwaar of onwaarnee—
commit_after_deliverywaar of onwaar (een blok, weglaten om niet te gebruiken)nee—
max_message_sizegeheel getalneehet kanaallimiet
session_timeoutduur, zoals 30s of 5mneevijfenveertig seconden
timeoutduur, zoals 30s of 5mneedertig seconden
saslKafkaSASL (een blok, weglaten om niet te gebruiken)nee—
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—

22.17.1 brokers

Brokers is de lijst van bootstrap-servers.

Required.

Een lijst in plaats van één adres, omdat één bootstrap-broker een enkel punt van falen is voor het opstarten: de cluster overleeft het verlies ervan en dit kanaal zou dat niet.

22.17.2 onderwerpen

Onderwerpen zijn de onderwerpen die worden gelezen.

Ten minste één is vereist.

22.17.3 groep

Groep is de consumentengroep.

Required.

Genoemd in plaats van gegenereerd, en vereist in plaats van standaard, omdat het is wat onthoudt hoe ver dit kanaal heeft gelezen. Een gegenereerde groep zou vanaf het begin starten - of vanaf het einde, waardoor alles verloren gaat - bij elke herstart, en het zou de oude groep achterlaten met vastgelegde offsets die niemand leest. Het vereisen ervan zorgt ervoor dat de persoon de naam geeft aan het ding dat hetzelfde moet blijven over herstarten heen.

22.17.4 van_beginning

VanBeginning leest het onderwerp vanaf het begin wanneer de groep geen vastgelegde offset heeft.

Uitgeschakeld standaard, zodat een nieuw kanaal dat naar een onderwerp met twee jaar geschiedenis wijst, niet twee jaar patiëntgebeurtenissen in een live-systeem afspreekt op de dag dat het wordt ingeschakeld. De eerste persoon die dat zou doen, zou het in productie doen, omdat dat de plek is waar het onderwerp met de geschiedenis is.

22.17.5 commit_after_delivery

CommitAfterDelivery legt de offset alleen vast nadat het bericht is verwerkt.

Ingeschakeld standaard, en de reden is het hele verschil tussen het verlies van een bericht en het zien van een dubbele. Vastleggen bij lezen betekent dat een crash tussen de vastlegging en de levering het bericht stilzwijgend verliest, en niets ergens registreert dat het heeft bestaan. Vastleggen na betekent dat een crash in hetzelfde venster het opnieuw levert, wat zichtbaar is en waaraan HL7-ontvangers zijn gebouwd om het te tolereren - een dubbele A08 is een hinder en een ontbrekend laboratoriumresultaat is een patiëntveiligheidsgebeurtenis.

22.17.6 max_message_size

MaxMessageSize begrenst één record.

Standaard de limiet van het kanaal.

22.17.7 time-out van de sessie

SessionTimeout geeft aan hoe lang de groepscoördinator wacht voordat hij aanneemt dat deze consument weg is en zijn partities opnieuw toewijst.

Standaard 45 seconden.

22.17.8 time-out

Time-outgrenzen voor verbinden en metadataverzoeken.

Standaard is dertig seconden.

22.18 MQTT-bron

MQTTSource abonneert zich op een onderwerpfilters.

Gedefinieerd als MQTTSource in internal/config.

SleutelTypeVereistStandaard
topictekstja—
reconnectduur, zoals 30s of 5mnee5s

22.18.1 reconnect

Opnieuw verbinden is de wachttijd na een verbroken verbinding of na een bericht dat niet kon worden verwerkt.

Defaults to 5s.

22.19 Pub Sub-bron

PubSubSource haalt uit een Pub/Sub-abonnement.

Gedefinieerd als PubSubSource in internal/config.

SleutelTypeVereistStandaard
subscriptiontekstja—
max_messagesgeheel getalnee10
reconnectduur, zoals 30s of 5mnee5s

22.19.1 max_berichten

MaxBerichten geeft aan hoeveel tegelijk worden opgehaald.

Ze worden nog steeds een voor een verwerkt, in volgorde. Standaard 10.

22.19.2 reconnect

Opnieuw verbinden is de wachttijd na een fout.

Defaults to 5s.

22.20 S3-bron

S3Source haalt objecten op uit een bucket.

Gedefinieerd als S3Source in internal/config.

SleutelTypeVereistStandaard
buckettekstja—
path_styletrue of falsenee—
prefixtekstnee—
suffixtekstnee—
after_readtekstnee—
move_totekstneeprocessed/
error_prefixtekstneeerror/
poll_intervalduur, zoals 30s of 5mnee30s
max_object_sizegeheel getalnee16 MiB
framedtrue of falsenee—

22.20.1 voorvoegsel

Voorvoegsel beperkt welke objecten worden gelezen, bijv. inbound/.

Lege leest de hele bucket, wat wordt geweigerd met na_lezen: verplaats tenzij verplaats_naar buiten het bereik valt - anders zouden verplaatste objecten opnieuw worden gelezen.

22.20.2 na_lezen

AfterRead is verplaats (standaard) of verwijder.

Er is geen bewaren: een bucket heeft geen bestand dat een poller zich herinnert te hebben gezien over een herstart heen, dus het achterlaten van objecten betekent dat ze elke keer opnieuw worden gelezen wanneer Perfuse start.

22.20.3 move_to

MoveTo is het voorvoegsel waarnaar een afgehandeld object verplaatst.

Standaard is dit processed/.

22.20.4 error_prefix

ErrorPrefix is waar een object dat niet afgehandeld kon worden, naartoe verplaatst, zodat één slecht bestand de rest niet blokkeert.

Standaard is dit error/.

22.20.5 poll_interval

PollInterval tussen de lijstingen.

Defaults to 30s.

22.20.6 max_object_size

MaxObjectSize weigert alles wat groter is.

Standaard is dit 16 MiB.

22.20.7 geframe

Framed leest meerdere MLLP-geframeerde berichten uit één object.

Anders is een object één bericht.

22.21 SFTP-bron

SFTPSource verzamelt berichten uit een directory op een SFTP-server.

Extreem gewoon en zelden besproken. Een laboratorium of een radiologiesysteem schrijft elke paar minuten een bestand, een SFTP-server houdt het vast, en iets moet komen en het ophalen. De helft van de feeds die worden beschreven als "we sturen je HL7" is dit.

Het deel dat zorg verdient, is niet de overdracht. Het is dat een bestand dat wordt geschreven en een bestand dat klaar is met schrijven, identiek lijken via SFTP, dus een poll die zelfs maar een beetje te gretig is, haalt een half bericht op. Dat produceert een afgekapt maar vaak parseerbaar HL7-bericht, wat het slechtste resultaat is dat beschikbaar is: het wordt geaccepteerd, bevestigd, opgeslagen en geleverd, en de ontbrekende helft wordt nooit meer genoemd.

Gedefinieerd als SFTPSource in internal/config.

SleutelTypeVereistStandaard
hosttekstja22
usertekstja—
passwordtekstnee—
key_filetekstnee—
key_passphrasetekstnee—
known_hosts_filetekstnee—
insecure_skip_host_key_checktrue of falsenee—
dirtekstja—
patterntekstneealles
poll_intervalduur, zoals 30s of 5mnee—
after_readtekstnee—
move_totekstnee—
error_dirtekstnee—
stable_forduur, zoals 30s of 5mnee5s
framedtrue of falsenee—
max_file_sizegeheel getalnee64MB
timeoutduur, zoals 30s of 5mnee60s

22.21.1 host

Host is de server, met een optionele poort.

Defaults to 22.

22.21.2 wachtwoord

Wachtwoord verifieert met een wachtwoord.

Prefer KeyFile.

22.21.3 sleutelbestand

Sleutelbestand is een privésleutel.

De betere keuze, en de keuze die door ziekenhuisbeveiligingsteams wordt gevraagd.

22.21.4 bekende_host_bestand

BekendeHostBestand verifieert de identiteit van de server.

Vereist tenzij InsecureHostSleutelControleOverslaan is ingesteld. Zonder het is er niets om de echte server te onderscheiden van alles wat antwoordt op dat adres, en worden de referenties overgedragen voordat iemand het merkt.

22.21.5 insecure_host_sleutel_controle_overslaan

InsecureHostSleutelControleOverslaan accepteert elke host-sleutel.

Bestaat omdat weigeren zonder meer mensen naar een shell-script met StrictHostKeyChecking=no stuurt, wat in alle opzichten, inclusief auditability, slechter is. Het waarschuwt luid en het is nooit de standaard.

22.21.6 patroon

Patroon selecteert bestanden met glob.

Standaard alles.

22.21.7 move_to

MoveTo is het remote directory waar bestanden na lezen naar verplaatst worden.

Vereist wanneer AfterRead 'move' is.

22.21.8 stabiel_voor

StableFor is hoe lang de grootte en wijzigingstijd van een bestand ongewijzigd moeten blijven voordat het gelezen wordt.

Defaults to 5s.

Dit is de instelling die voorkomt dat een half bericht wordt verzameld. Nul betekent het lezen van alles wat er is, wat werkt totdat een bestand groot genoeg is of een netwerk langzaam genoeg is dat schrijven langer duurt dan een poll.

22.21.9 geframe

Framed geeft aan dat het bestand MLLP-geframeerde berichten bevat.

Wanneer false, wordt het bestand gesplitst op MSH-grenzen.

22.21.10 max_bestandsgrootte

MaxFileSize weigert een bestand groter dan dit aantal bytes.

Standaard 64MB.

22.21.11 time-out

Timeout begrenst een enkele verbinding.

Defaults to 60s.

22.22 SMB Bron

SMBSource verzamelt bestanden van een Windows-bestandsshare.

Gedefinieerd als SMBSource in internal/config.

SleutelTypeVereistStandaard
hosttekstja—
sharetekstja—
usertekstnee—
passwordtekstnee—
domaintekstnee—
roottekstnee—
timeoutduur, zoals 30s of 5mneedertig seconden

22.22.1 host

Host is de server, met een optionele poort.

Poort 445 wordt aangenomen.

22.22.2 share

Share is de sharenaam alleen: de 'data' in \\\server\data.

Een pad hier wordt geweigerd in plaats van afgekapt.

22.22.3 gebruiker

Gebruiker en Wachtwoord zijn het Windows-account.

In de praktijk vereist.

Een share die bereikbaar is zonder enkele referenties is zeldzaam genoeg op een domein dat een lege gebruiker hier waarschijnlijker een fout is dan een gastshare - maar het wordt geaccepteerd, omdat weigeren ervan de ene regeling zou blokkeren waarin het correct is. Als het account deel uitmaakt van een domein, moet u Domein ook instellen: authenticatie van een domeinaccount zonder dit mislukt op een manier die lijkt op een verkeerd wachtwoord.

22.22.4 wachtwoord

Gebruiker en Wachtwoord zijn het Windows-account.

In de praktijk vereist.

Een share die bereikbaar is zonder enkele referenties is zeldzaam genoeg op een domein dat een lege gebruiker hier waarschijnlijker een fout is dan een gastshare - maar het wordt geaccepteerd, omdat weigeren ervan de ene regeling zou blokkeren waarin het correct is. Als het account deel uitmaakt van een domein, moet u Domein ook instellen: authenticatie van een domeinaccount zonder dit mislukt op een manier die lijkt op een verkeerd wachtwoord.

22.22.5 domein

Domein is het Windows-domein of -werkgroup.

Leeg is meestal correct voor een lokaal account.

22.22.6 time-out

Time-out beperkt één bewerking.

Standaard is dertig seconden.

Het is de moeite waard om te verhogen wanneer een share wordt bereikt via een sitekoppeling. Een SMB-bewerking tegen een verre server is langzamer dan dezelfde bewerking lokaal, waardoor een standaard die is afgesteld op een LAN, time-outs produceert die eruitzien alsof de share niet beschikbaar is.

22.23 SOAP-bron

SOAP-bron accepteert berichten die zijn ingepakt in een SOAP-envelop.

Het tegenovergestelde van de SOAP-bestemming, en de minder voorkomende richting: de meeste ziekenhuisintegraties hebben Perfuse die een service aanroept in plaats van er een te zijn. Het bestaat omdat Mirth's Web Service Listener dit ook doet, en een site waarvan het verzendende systeem alleen SOAP spreekt, niet kan migreren zonder dit.

Opzettelijk geen algemeen web services-framework. Het accepteert een envelop, haalt het bericht eruit en antwoordt met een envelop. Er is geen WS-Beveiliging, geen MTOM, geen WS-Adressering en geen gegenereerde bindings - dezelfde weglatingen als de bestemming, om dezelfde reden: een half-geïmplementeerde WS-Beveiliging is erger dan geen.

Gedefinieerd als SOAPSource in internal/config.

SleutelTypeVereistStandaard
listentekstja—
profiletekstnee—
pathtekstnee"/"
versiontekstnee1
elementtekstnee—
base64true of falsenee—
response_elementtekstnee"AckResponse"
response_namespacetekstnee—
wsdltekstnee—
tlstlsconf.Settings (een blok, weglaten om niets te doen)nee—
tokentekstnee—
usernametekstnee—
passwordtekstnee—
max_message_sizegeheel getalnee—
read_timeoutduur, zoals 30s of 5mnee—
ackAcknee—
fault_on_naktrue of falsenee—

22.23.1 listen

Listen is het adres waarop de service moet luisteren.

Required.

22.23.2 profiel

Profielnaam noemt een standaarddienst die deze endpoint implementeert.

Leeg accepteert elke envelop zoals hieronder geconfigureerd.

"cdc-iis" antwoordt zoals een immunisatieregister doet, op het CDC-interface (urn:cdc:iisb:2011): connectivityTest wordt herhaald, submitSingleMessage's hl7Message is het bericht en de kanaalbevestiging gaat terug in de retour, de WSDL wordt geserveerd op ?wsdl, en gebruikersnaam en wachtwoord, wanneer ingesteld, worden gecontroleerd tegen degenen in het lichaam (waar de WSDL ze plaatst) in plaats van tegen HTTP-verificatie. Voor een testdubbel van een register, of voor een site die ontvangt zoals registers doen.

22.23.3 path

Pad is het URL-pad om enveloppen op te accepteren.

Defaults to "/".

22.23.4 versie

Versie is de SOAP-versie die moet worden geantwoord, "1.1" of "1.2".

Defaults to 1.1.

Verzoeken worden geaccepteerd in beide versies, ongeacht of ze correct zijn, omdat een afzender die dit verkeerd doet, gebruikelijk is en het afwijzen ervan niemand iets leert. De instelling controleert het antwoord, waarbij het verkeerd krijgen ervan betekent dat de afzender het antwoord niet kan lezen.

22.23.5 element

Elementnaam noemt het element binnen de SOAP-Body dat het bericht bevat.

Leeg betekent de hele body-tekst.

Genoemd in plaats van geraden, omdat een body meerdere elementen kan bevatten - een bericht naast een afzenderidentificatie en een tijdstempel - en het nemen van de hele body zou de motor een XML-fragment geven waar het een HL7-bericht verwachtte.

22.23.6 base64

Base64 decodeert de inhoud van het element voordat het als bericht wordt behandeld.

Gemeenschappelijk in echte diensten, omdat HL7 wisseltekens bevat en aanroepers die daar niet aan denken, XML produceren die deze wisseltekens beschadigen. Als de inhoud base64 decodeert maar niet bedoeld was om base64 te zijn, is het resultaat geen bericht en zegt de motor dat zo - wat de reden is dat dit expliciet is in plaats van opgespoord.

22.23.7 antwoord_element

ResponseElement naamt het element dat de bevestiging omvat in het antwoord.

Standaard is "AckResponse".

22.23.8 wsdl

WSDL is een bestand dat wordt geserveerd op het luisterpad met ?wsdl.

Leeg betekent dat er geen wordt geserveerd.

Een bestand in plaats van iets gegenereerd. Een gegenereerde WSDL zou beschrijven wat deze endpoint accepteert, wat bijna nooit is wat het verzendende systeem is gebouwd tegen - en een WSDL die bijna goed is, kost meer tijd dan helemaal geen WSDL, omdat het er autoritair uitziet.

22.23.9 gebruikersnaam

Gebruikersnaam en Wachtwoord, wanneer ingesteld, vereisen HTTP-basicauthenticatie.

Aangeboden naast een token, omdat SOAP-callers over het algemeen basism authenticatie verwachten, en een site wiens verzendende systeem niet kan worden gewijzigd, de optie nodig heeft die het al heeft.

22.23.10 wachtwoord

Gebruikersnaam en Wachtwoord, wanneer ingesteld, vereisen HTTP-basicauthenticatie.

Aangeboden naast een token, omdat SOAP-callers over het algemeen basism authenticatie verwachten, en een site wiens verzendende systeem niet kan worden gewijzigd, de optie nodig heeft die het al heeft.

22.23.11 max_message_size

MaxMessageSize begrenst een inkomend bericht.

Nul past een standaard toe.

22.23.12 fout_bij_nak

FaultOnNak beantwoordt een negatieve bevestiging met een SOAP-fout in plaats van een normaal antwoord met de NAK.

Uitgeschakeld door standaard, wat de juiste standaard is en het waard is om uit te leggen. HL7 heeft al een manier om te zeggen "Ik heb dit ontvangen en geweigerd", en dat is een NAK - een succesvolle uitwisseling die een geweigerde boodschap rapporteert. Hetzelfde omzetten in een transportfout vertelt de verzender dat zijn verzoek onjuist was, wat het niet was, en veel clients reageren door het oneindig te herhalen.

Het bestaat omdat sommige callers alleen naar de HTTP-status kijken en een afwijzing anders als succes zouden behandelen.

22.24 SQS-bron

SQS-bron leest van een SQS-wachtrij.

Een bericht wordt alleen verwijderd nadat het kanaal het heeft verwerkt - afgeleverd, of gefilterd, of mislukt op een manier die het kanaal registreert. Tot dan blijft het op de wachtrij, onzichtbaar voor visibility_timeout, en komt terug als Perfuse stopt. Dus een bericht gaat nooit verloren; de prijs is dat er een tweede kan aankomen, wat SQS zelf al toestaat.

Gedefinieerd als SQSSource in internal/config.

SleutelTypeVereistStandaard
queue_urltekstja—
wait_secondsgeheel getalnee20: een lege wachtrij kost één verzoek elke twintig seconden
max_messagesgeheel getalnee10
visibility_timeoutduur, zoals 30s of 5mneede instelling van de wachtrij zelf

22.24.1 visibility_timeout

VisibilityTimeout is de tijd dat een ontvangen bericht verborgen blijft terwijl het wordt verwerkt.

Standaard is de instelling van de wachtrij zelf.

22.25 Serieel-bron

Serieel-bron leest berichten van een serieel poort.

Waarom een serieel connector in 2026

Omdat de apparatuur er nog steeds is. Een bloedgasanalyseapparaat gekocht in 2009 met een werkende sensor en een 25-pins socket, een bedmonitorsysteem, een weegschaal in een dialyse-eenheid, een oudere anesthesiemachine. Geen van hen zal ooit een Ethernet-poort krijgen, verschillende van hen kosten zes cijfers, en het alternatief voor het lezen ervan is dat iemand resultaten intoetst in een formulier.

Mirth heeft een seriële connector. Perfuse had niets en een site met een van deze had helemaal geen route naar binnen.

Framing wordt gedeeld met de TCP-connector

De framing is overal hetzelfde, waar de bytes ook vandaan komen: een analyzer die STX/ETX over een socket spreekt, spreekt STX/ETX over een kabel. Dus wordt deze de TCP-framingblok hergebruikt in plaats van een eigen te definiëren, wat ook betekent dat een apparaat dat van een seriële kabel naar een seriële-naar-Ethernet-adapter wordt verplaatst, zijn framingconfiguratie behoudt.

Wat is anders aan een seriële lijn

Er is geen verbinding. Een socket vertelt je wanneer de peer weg is gegaan; een kabel doet dat niet. Een losgekoppelde kabel, een apparaat dat is uitgeschakeld en een apparaat met niets te zeggen zijn niet van elkaar te onderscheiden - alle drie zijn stilte. Dat is waarom quiet_after bestaat: zonder iets om te zeggen "deze lijn is langer stil dan het zou moeten zijn", ziet een dode feed er precies uit als een stille nacht.

Gedefinieerd als SerialSource in internal/config.

SleutelTypeVereistStandaard
porttekstja—
baudgeheel getalja—
data_bitsgeheel getalnee8
paritytekstneegeen
stop_bitstekstnee1
flow_controltekstneegeen
max_message_sizegeheel getalnee—
quiet_afterduur, zoals 30s of 5mnee—
replytekstnee—
reply_texttekstnee—
reopen_afterduur, zoals 30s of 5mnee—

22.25.1 baud

Baud is de snelheid.

Vereist, omdat gokken bytes oplevert in plaats van een fout.

Een verkeerde baudsnelheid mislukt niet. Het levert plausibele onzin: framingbytes verschijnen willekeurig, occasionele runs decoderen als afdrukbare tekens en een soepele parser accepteert een deel ervan. Er is opzettelijk geen standaard.

22.25.2 pariteit

Pariteit is geen, oneven, even, mark of spatie.

Standaard is geen.

22.25.3 stop_bits

StopBits is 1, 1,5 of 2, geschreven als "1", "1,5" of "2".

Defaults to 1.

22.25.4 flow_control

FlowControl is geen, hardware of software.

Standaard is geen.

Het is de moeite waard om correct in te stellen in plaats van het te laten staan. Met hardware-flowcontrol verwacht en niet geconfigureerd, stopt een apparaat met verzenden halverwege een lange boodschap en het resultaat is een afgekapt bericht in plaats van een fout.

22.25.5 quiet_after

QuietAfter logt een waarschuwing wanneer er niets is ontvangen voor deze tijd.

De enige manier om een dode seriële feed op te merken. Een losgekoppelde kabel en een stille nacht zijn dezelfde stilte, dus iemand moet zeggen hoe lang te lang is voor dit specifieke apparaat.

22.25.6 reopen_after

ReopenAfter is hoe lang te wachten voordat een poort die is mislukt opnieuw wordt geopend.

Een USB-seriële adapter die is losgekoppeld en opnieuw is aangesloten, komt terug als hetzelfde apparaatpad maar een andere kernelhandle, dus de oude retourneert fouten voor altijd. Opnieuw openen is de enige hersteloptie en het doen in een strakke lus vult het logboek.

22.26 Bron

De bron is de plaats waar een kanaal berichten ontvangt.

Gedefinieerd als Source in internal/config.

SleutelTypeVereistStandaard
typeSourceTypeja—
listentekstja—
max_message_sizegeheel getalnee—
idle_timeoutduur, zoals 30s of 5mnee—
max_connectionsgeheel getalnee—
tlstlsconf.Settings (een blok, weglaten om niets te doen)nee—
httpHTTPSource (een blok, weglaten om niets te doen)nee—
soapSOAPSource (een blok, weglaten om niets te doen)nee—
dicomwebDICOMwebSource (een blok, weglaten om niets te doen)nee—
directDirectSource (een blok, weglaten om niets te doen)nee—
dicomDICOMSource (een blok, weglaten om niets te doen)nee—
fileFileSource (een blok, weglaten om niets te doen)nee—
tcpTCPSource (een blok, weglaten om niets te doen)nee—
ftpFTPSource (een blok, weglaten om niets te doen)nee—
smbSMBSource (een blok, weglaten om niets te doen)nee—
webdavWebDAVSource (een blok, weglaten om niets te doen)nee—
serialSerialSource (een blok, weglaten om niets te doen)nee—
dicom_queryDICOMQuerySource (een blok, weglaten om niets te doen)nee—
brokerBrokerSource (een blok, weglaten om niets te doen)nee—
kafkaKafkaSource (een blok, weglaten om niets te doen)nee—
sqsSQSSource (een blok, weglaten om niets te doen)nee—
s3S3Source (een blok, weglaten om niets te doen)nee—
amqpAMQPSource (een blok, weglaten om niets te doen)nee—
azure_blobAzureBlobSource (een blok, weglaten om niets te doen)nee—
emailEmailSource (een blok, weglaten om niets te doen)nee—
as2AS2Source (een blok, weglaten om niets te doen)nee—
pgpPGPReceive (een blok, weglaten om niets te doen)nee—
mqttMQTTSource (een blok, weglaten om niets te doen)nee—
ibm_mqIBMMQSource (een blok, weglaten om niets te doen)nee—
pubsubPubSubSource (een blok, weglaten om niets te doen)nee—
gcsGCSSource (een blok, weglaten om niets te doen)nee—
databaseDatabaseSource (een blok, weglaten om niets te doen)nee—
sftpSFTPSource (een blok, weglaten om niets te doen)nee—
javascriptJavaScriptSource (een blok, weglaten om niets te doen)nee—
ackAcknee—

22.26.1 type

Type is het transport.

Alleen mllp is geïmplementeerd.

22.26.2 max_message_size

MaxMessageSize begrenst één inkomend bericht.

Nul gebruikt de standaardwaarde van het transport.

22.26.3 idle_timeout

IdleTimeout sluit een verbinding die stil is geweest voor deze tijd.

Nul betekent nooit, wat meestal correct is: een ziekenhuisfeed houdt een verbinding open voor maanden en gaat 's nachts stil.

22.26.4 max_connections

MaxConnections begrenst gelijktijdige verbindingen.

Nul betekent onbeperkt.

22.27 TCP-bron

TCPSource luistert naar een socket voor berichten die niet noodzakelijkerwijs HL7 zijn.

Waarom dit apart is van een mllp-bron

MLLP is één kader en Perfuse heeft het altijd gesproken. Veel apparatuur doet dit niet: een laboratoriumanalyser, een weegschaal, een bedmonitorsysteem, een ouder factureringssysteem. Elk heeft zijn eigen conventie, en Mirth's TCP-connector dekt ze allemaal, dus een site met een socketfeed die geen HL7 was, kon Perfuse helemaal niet gebruiken.

Gedefinieerd als TCPSource in internal/config.

SleutelTypeVereistStandaard
listentekstja—
max_message_sizegeheel getalnee—
idle_timeoutduur, zoals 30s of 5mnee—
max_connectionsgeheel getalnee—
replytekstnee—
reply_texttekstnee—
tlstlsconf.Settings (een blok, weglaten om niets te doen)nee—

22.27.1 idle_timeout

IdleTimeout sluit een verbinding die stil is geweest voor deze tijd.

Nul betekent nooit, wat meestal correct is: een apparaatfeed houdt een verbinding open voor maanden en gaat stil als het 's nachts stil is.

22.27.2 max_connections

MaxConnections begrenst gelijktijdige verbindingen.

Nul betekent onbeperkt.

22.27.3 reply

Reply is wat terug te sturen is na elk bericht: niets, ack of een vaste tekenreeks.

De meeste ruwe feeds verwachten niets. Sommige verwachten één ACK-byte. Een apparaat dat een antwoord verwacht en dat niet krijgt, probeert meestal hetzelfde bericht oneindig vaak opnieuw te verzenden, dus het is de moeite waard om dit expliciet te maken.

22.28 Web DAV-bron

WebDAVSource verzamelt bestanden uit een WebDAV-verzameling.

Waar dit voorkomt: documentbeheersystemen, SharePoint, Nextcloud en leveranciersportals die een dropfolder blootstellen via HTTPS omdat dit de enige uitgaande poort is die de firewalls van hun klanten toestaat.

Gedefinieerd als WebDAVSource in internal/config.

SleutelTypeVereistStandaard
urltekstja—
usertekstnee—
passwordtekstnee—
insecure_skip_verifytrue of falsenee—
timeoutduur, zoals 30s of 5mneezestig seconden

22.28.1 gebruiker

Gebruiker en wachtwoord authenticeren met HTTP-basistauthenticatie.

Basisauthenticatie verstuurt het wachtwoord in een header die alleen beschermd wordt door TLS, dus deze horen bij een https-URL. Over http zijn ze leesbaar voor alles op het pad en er komt geen waarschuwing van de server.

22.28.2 wachtwoord

Gebruiker en wachtwoord authenticeren met HTTP-basistauthenticatie.

Basisauthenticatie verstuurt het wachtwoord in een header die alleen beschermd wordt door TLS, dus deze horen bij een https-URL. Over http zijn ze leesbaar voor alles op het pad en er komt geen waarschuwing van de server.

22.28.3 time-out

Time-out begrenst één aanvraag.

Standaard zestig seconden.

Langer dan de standaardwaarden voor FTP en SMB, met opzet. Een WebDAV-verzamelinglijst is één PROPFIND die de server mogelijk veel tijd kan besteden aan het samenstellen voor een grote directory, en er is geen gedeeltelijk resultaat om op terug te vallen.

23 Bestemmingsverwijzing

Elke manier waarop een kanaal berichten kan verzenden, en elke sleutel die elk daarvan accepteert. Een kanaal kan elk aantal bestemmingen hebben en ze zijn onafhankelijk: één falen stopt de anderen niet.

23.1 AMQP-bestemming

AMQPDestination verzendt naar een wachtrij of onderwerp en rapporteert alleen succes nadat de broker het bericht heeft geaccepteerd.

Gedefinieerd als AMQPDestination in internal/config.

SleutelTypeVereistStandaard
content_typetekstneehet gegevenstype van het kanaal

23.1.1 content_type

ContentType wordt verzonden met elk bericht.

Standaard het gegevenstype van het kanaal.

23.2 AS2-bestemming

AS2Destination verzendt elk bericht als AS2: ondertekend met onze sleutel, versleuteld naar het certificaat van de partner, gepost naar de URL van de partner en, standaard, alleen geleverd nadat de ondertekende ontvangstbevestiging van de partner dezelfde digest noemt.

Gedefinieerd als AS2Destination in internal/config.

SleutelTypeVereistStandaard
urltekstja—
fromtekstja—
totekstja—
cert_filetekstnee—
key_filetekstnee—
partner_cert_filetekstnee—
unsignedwaar of onwaarnee—
unencryptedwaar of onwaarnee—
compresswaar of onwaarnee—
receipttekstnee—
unsigned_receiptwaar of onwaarnee—
receipt_urltekstnee—
content_typetekstnee—
file_nametekstnee—
subjecttekstnee—
usernametekstnee—
passwordtekstnee—
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—

23.2.1 compress

Compress comprimeert de payload (zlib, RFC 5402) voordat deze wordt ondertekend en versleuteld.

Elke AS2-ontvanger die versie 1.1 of later aankondigt, leest dit; vraag de partner voordat u het inschakelt.

23.2.2 ongetekende_ontvangst

OngetekendeOntvangstdocument vraagt om een ontvangstbevestiging die niet is ondertekend.

Uit: een ondertekende wordt gevraagd en een niet-ondertekende wordt geweigerd.

23.2.3 content_type

ContentType is het MIME-type van de payload.

Standaard op basis van het gegevenstype van het kanaal: application/edi-x12, application/edifact, application/hl7-v2, anders application/octet-stream.

23.3 Azure Blob Bestemming

AzureBlobBestemming schrijft elke bericht als een block blob.

Gedefinieerd als AzureBlobDestination in internal/config.

SleutelTypeVereistStandaard
blobtekstnee${date}/${kanaal}/${control_id}
tiertekstnee—
content_typetekstnee—

23.3.1 blob

Blob naam geeft elke blob een naam, met de placeholders van de S3-bestemming.

Standaard ${date}/${kanaal}/${control_id}.hl7.

23.3.2 tier

Tier is Hot, Cool, Cold of Archive.

Archive is offline: het lezen van een blob terug betekent dat deze opnieuw moet worden gehydrateerd, wat uren duurt.

23.4 Broker Bestemming

BrokerBestemming publiceert berichten naar een berichtenbroker.

Mirth's JMS Writer.

Gedefinieerd als BrokerDestination in internal/config.

SleutelTypeVereistStandaard
addrtekstja—
destinationtekstja—
logintekstnee—
passcodetekstnee—
hosttekstneede host van het adres
content_typetekstneetext/plain voor HL7
headerstoewijzing van tekst aan tekstnee—
persistenttrue of false (een blok, weglaten om uit te schakelen)neetrue
timeoutduur, zoals 30s of 5mnee—
tlstlsconf.Settings (een blok, weglaten om uit te schakelen)nee—

23.4.1 addr

Addr is de host en poort van de broker.

Required.

23.4.2 bestemming

Bestemming is de wachtrij of het onderwerp dat moet worden gepubliceerd.

Required.

23.4.3 inloggen

Inloggen en wachtwoord verifiëren.

De meeste brokers weigeren een anonieme verbinding.

23.4.4 wachtwoord

Inloggen en wachtwoord verifiëren.

De meeste brokers weigeren een anonieme verbinding.

23.4.5 host

Host is de virtuele host.

Standaard is de host van het adres.

Het is de moeite waard om deze expliciet in te stellen op een broker die meerdere virtuele hosts host, waar de standaard de publicatie op de host plaatst die antwoordt op de naam van de server - een wachtrij die bestaat, de berichten accepteert en door niemand wordt gelezen.

23.4.6 content_type

ContentType wordt verzonden met elk bericht.

Standaard text/plain voor HL7.

23.4.7 headers

Headers worden met elk bericht verzonden.

Alleen configuratie, nooit inhoud van berichten. Een koptekst die uit een veld wordt genomen, zou een patiëntidentificator in brokermetadata plaatsen die wordt gelogd, geïndexeerd en zichtbaar is voor elke andere toepassing in de wachtrij.

23.4.8 persistent

Persistent vraagt de broker om een herstart te overleven.

Standaard is dit waar.

Waar omdat een niet-persistente bericht verloren gaat wanneer de broker opnieuw wordt gestart, en dat is geen redelijke standaard voor klinische gegevens. Onwaar bestaat voor een echt tijdelijke feed - een monitoring hartslag - en moet worden gekozen.

23.5 CDA Bestemming

CDADestination configureert een cda-bestemming: het neemt het klinische document dat binnen een HL7 v2-bericht zit, converteert het en schrijft of plaatst het resultaat.

Dit bestaat omdat een document bijna nooit alleen aankomt. Het komt base64-gecodeerd binnen in een MDM^T02, en elke engine die dat bericht als een ondoorzichtige blob behandelt, laat het document ongelezen. Het bezitten van beide uiteinden daarvan is het punt.

Gedefinieerd als CDADestination in internal/config.

SleutelTypeVereistStandaard
urltekstnee—
dirtekstnee—
writetekstnee—
versiontekstneeR5
identifier_systemstoewijzing van tekst aan tekstnee—
require_agreementwaar of onwaarnee—
on_no_documenttekstnee—
headerstoewijzing van tekst aan tekstnee—
bearer_tokentekstnee—

23.5.1 url

URL is een FHIR-server waarop de geconverteerde bundel wordt geplaatst.

Laat het leeg om naar Dir te schrijven. Eén van de twee is vereist.

23.5.2 dir

Dir schrijft de uitvoer naar bestanden in plaats van het te plaatsen.

Handig voor een landingzone die door een ander proces wordt opgepikt, en voor het zien van wat de conversie produceert voordat het naar een live-server wordt verwezen.

23.5.3 write

Write selecteert wat wordt geschreven of geplaatst:

fhir de omgezette transactiebundle (standaard) document het originele document in bytes, ongewijzigd beide beide, met het document naast de bundle overdracht een PACIO Transitions of Care overdrachtensamenvatting: één FHIR R4 document Bundle voor de plaats waar de patiënt naartoe gaat (een verpleeghuis, een revalidatie-eenheid, thuiszorg), gepost naar url/Bundle of geschreven naar dir

"document" is de moeite waard om op zichzelf te hebben: een site die zijn CDAs op schijf wil voor een records-team, heeft de FHIR-conversie helemaal niet nodig.

23.5.4 identifier_systems

IdentifierSystems toewijst een OID-root uit het document aan een URI, zodat een MRN genamespaceerd wordt.

Een CDA identificeert personen door OID en FHIR door URI, en niets kan er een van de andere afleiden.

23.5.5 require_agreement

RequireAgreement weigert een document waarvan de narratieve en gecodeerde invoeren elkaar tegenspreken.

Standaard uitgeschakeld, en met opzet. De controle is waardevol, maar het is een oordeel over een document dat iemand anders heeft gemaakt, en een kanaal dat echte klinische documenten stilzwijgend laat vallen omdat de C-CDA-generator van de afzender slordig is, is erger dan een dat ze doorlaat met een waarschuwing. Een site die naar zijn eigen bevindingen heeft gekeken en heeft besloten dat het de poort wil inschakelen, kan deze inschakelen.

23.5.6 on_no_document

OnNoDocument bepaalt wat er gebeurt wanneer het bericht geen klinisch document bevat:

skip: lever niets af en rapporteer succes (standaard) fail: behandel het als een afleveringsfout

De standaard is skip, omdat een kanaal met een gemengde ADT- en MDM-feed anders bij elke opname zou falen. Een kanaal dat specifiek is voor documenten, moet fail instellen, omdat een documentbericht zonder document in het bericht een echt probleem is bij de afzender.

23.5.7 bearer_token

BearerToken wordt verzonden als een Authorization-header.

Geef de voorkeur aan een verwijzing naar een omgevingsvariabele boven een letterlijke waarde in een bestand dat naar git gaat.

23.6 Kanaalbestemming

Kanaalbestemming routeert naar een ander kanaal op dezelfde server.

Gedefinieerd als ChannelDestination in internal/config.

SleutelTypeVereistStandaard
nametekstja—

23.7 DICOM-bestemming

DICOMBestemming verzendt beeldobjecten als een C-STORE-serviceklassegebruiker.

Mirth noemt dit de DICOM-verzender.

Gedefinieerd als DICOMDestination in internal/config.

SleutelTypeVereistStandaard
addresstekstja—
called_aetekstnee—
calling_aetekstnee—
transfer_syntaxeslijst van tekstnee—
timeoutduur, zoals 30s of 5mnee—
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—

23.7.1 adres

Adres is de externe host en poort.

Required.

23.7.2 called_ae

CalledAE is wat de externe zichzelf noemt, en CallingAE wat deze kant zichzelf noemt.

Beide zijn belangrijk. Sites configureren een PACS om één specifieke oproepnaam te accepteren en alles anders te weigeren, dus een mismatch is de meest voorkomende reden waarom een eerste verbinding mislukt - en de fout lijkt op een netwerkprobleem.

23.7.3 calling_ae

CalledAE is wat de externe zichzelf noemt, en CallingAE wat deze kant zichzelf noemt.

Beide zijn belangrijk. Sites configureren een PACS om één specifieke oproepnaam te accepteren en alles anders te weigeren, dus een mismatch is de meest voorkomende reden waarom een eerste verbinding mislukt - en de fout lijkt op een netwerkprobleem.

23.7.4 transfer_syntaxes

TransferSyntaxes beperkt wat wordt aangeboden, in voorkeursvolgorde.

Leeg biedt de eigen codering van het object aan en vervolgens impliciete VR little-endian als back-up.

23.7.5 time-out

Time-out begrenst één opslagoperatie.

Nul past een standaard toe.

23.8 DICO Mweb-bestemming

DICOMwebBestemming slaat elk object op met STOW-RS.

Gedefinieerd als DICOMwebDestination in internal/config.

KeyTypeRequiredDefault
urltextyes—
tokentextno—
usernametextno—
passwordtextno—
headersmapping of text to textno—
tlstlsconf.Settings (a block, omit to leave off)no—
timeoutduration, such as 30s or 5mno—

23.9 Databasebestemming

DatabaseDestination schrijft elk bericht naar een database.

Gedefinieerd als DatabaseDestination in internal/config.

SleutelTypeVereistStandaard
drivertekstja—
dsntekstja—
statementtekstja—
paramslijst van tekstnee—
timeoutduur, zoals 30s of 5mnee30s
max_open_connsgeheel getalnee4

23.9.1 stuurprogramma

Stuurprogramma noemt de database.

See SupportedDrivers.

23.9.2 instructie

De instructie wordt eenmaal per bericht uitgevoerd, met parameters die eraan zijn gebonden in de juiste volgorde.

Plaatsaanduidingen zijn specifiek voor de stuurprogramma's: $1 voor postgres, ? voor mysql en sqlite, @p1 voor sqlserver. Perfuse herschrijft ze niet, omdat een vertaaglaag die een plaatsaanduiding verkeerd interpreteert, de naam van een patiënt aan de verkeerde kolom bindt en het resultaat eruitziet als geldige gegevens.

23.9.3 parameters

Parameters zijn HL7-paden of ${...} -expressies, die in de juiste volgorde aan de instructie zijn gebonden.

Waarden worden altijd als parameters gebonden en nooit in de SQL-code geïnterpoleerd. Dat heeft niet alleen te maken met injectie: O'Brien is een veelvoorkomende naam, en een samengestelde query breekt op het apostrof.

23.9.4 time-out

Time-out

Defaults to 30s.

23.9.5 max_open_conns

MaxOpenConns beperkt het aantal verbindingen in de pool.

Defaults to 4.

23.10 Bestemming

Een bestemming is één plek waar een kanaal berichten naartoe stuurt.

Gedefinieerd als Destination in internal/config.

SleutelTypeVereistStandaard
nametekstja—
typeDestinationTypeja—
enabledtrue of false (een blok, weglaten om uit te schakelen)nee—
filtertekstnee—
addresstekstnee—
dirtekstnee—
file_nametekstnee—
temp_suffixtekstnee"
appendtrue of falsenee—
retain_hoursgeheel getalnee—
tlstlsconf.Settings (een blok, weglaten om uit te schakelen)nee—
fhirFHIRDestination (een blok, weglaten om uit te schakelen)nee—
cdaCDADestination (een blok, weglaten om uit te schakelen)nee—
httpHTTPDestination (een blok, weglaten om uit te schakelen)nee—
databaseDatabaseDestination (een blok, weglaten om uit te schakelen)nee—
sftpSFTPDestination (een blok, weglaten om uit te schakelen)nee—
tcpTCPDest (een blok, weglaten om uit te schakelen)nee—
smtpSMTPDestination (een blok, weglaten om uit te schakelen)nee—
channelChannelDestination (een blok, weglaten om uit te schakelen)nee—
s3S3Destination (een blok, weglaten om uit te schakelen)nee—
ftpFTPDestination (een blok, weglaten om uit te schakelen)nee—
documentDocumentDestination (een blok, weglaten om uit te schakelen)nee—
soapSOAPDestination (een blok, weglaten om uit te schakelen)nee—
dicomwebDICOMwebDestination (een blok, weglaten om uit te schakelen)nee—
xdsXDSDestination (een blok, weglaten om uit te schakelen)nee—
directDirectDestination (een blok, weglaten om uit te schakelen)nee—
as2AS2Destination (een blok, weglaten om uit te schakelen)nee—
mpiMPIDestination (een blok, weglaten om uit te schakelen)nee—
tefcaTEFCADestination (een blok, weglaten om uit te schakelen)nee—
pasPASDestination (een blok, weglaten om uit te schakelen)nee—
x12_astekstnee—
dicomDICOMDestination (een blok, weglaten om uit te schakelen)nee—
javascriptJavaScriptDestination (een blok, weglaten om uit te schakelen)nee—
brokerBrokerDestination (een blok, weglaten om uit te schakelen)nee—
kafkaKafkaDestination (een blok, weglaten om uit te schakelen)nee—
sqsSQSDestination (een blok, weglaten om uit te schakelen)nee—
snsSNSDestination (een blok, weglaten om uit te schakelen)nee—
amqpAMQPDestination (een blok, weglaten om uit te schakelen)nee—
azure_blobAzureBlobDestination (een blok, weglaten om uit te schakelen)nee—
mqttMQTTDestination (een blok, weglaten om uit te schakelen)nee—
ibm_mqIBMMQDestination (een blok, weglaten om uit te schakelen)nee—
pubsubPubSubDestination (een blok, weglaten om uit te schakelen)nee—
gcsGCSDestination (een blok, weglaten om uit te schakelen)nee—
elrELRDestination (een blok, weglaten om uit te schakelen)nee—
pgpPGPSend (een blok, weglaten om uit te schakelen)nee—
response_transformertekstnee—
timeoutduur, zoals 30s of 5mnee—
retryRetrynee—
queueQueueConfig (een blok, weglaten om uit te schakelen)nee—

23.10.1 naam

Naam identificeert de bestemming in logboeken en metrische gegevens.

Vereist binnen een kanaal.

23.10.2 file_name

Bestandsnaam, voor een bestemmingsbestand, maakt één bestand per bericht (${timestamp}, ${date}, ${control_id}, ${message_type}, ${destination}).

Leeg houdt de standaard: één bestand per dag en berichttype, toegevoegd aan.

23.10.3 temp_suffix

TempSuffix is de naam die een per-berichtbestand draagt terwijl het wordt geschreven, verwijderd door een hernoeming zodra het voltooid is, zodat degene die de bestanden verzamelt nooit een half bestand leest.

Standaard is ".part".

23.10.4 retain_hours

RetainHours verwijdert bestanden in Dir ouder dan dit.

Nul houdt ze voor altijd.

23.10.5 x12_as

X12As is xml voor een bestemming op een X12-kanaal dat de interchange ontvangt als XML, zoals Mirth Connect en Open Integration Engine schrijven voor X12, voor een ontvanger die is gebouwd tegen wat Mirth heeft verzonden.

Leeg of x12 verzendt X12.

23.10.6 elr

ELR maakt deze bestemming een openbare laboratoriumrapportagebestemming: elk laboratoriumresultaat (ORU^R01) wordt omgevormd tot een ELR 2.5.1-bericht dat alleen de orders met een rapporteerbaar resultaat bevat, en dat is wat wordt geleverd; een bericht met niets rapporteerbaars wordt helemaal niet verzonden.

Geldt voor bestemmingen die een HL7 v2-bericht leveren zoals het is (mllp, http, bestand, sftp en de rest), op een HL7-kanaal.

23.10.7 response_transformer

ResponseTransformer inspecteert wat de ontvanger terugzei en kan de levering als mislukt markeren.

Het bestaat omdat "is dit aangekomen" vaak geen vraag is die het transport kan beantwoorden: een MLLP-ontvanger retourneert een toepassingsacknowledgement waarvan de betekenis in de tekst staat, en een HTTP-ontvanger retourneert 200 met een foutdocument. In beide gevallen is het transport geslaagd en is het bericht niet aangekomen.

Alleen zinvol op een bestemming die een antwoord ontvangt. Op een die dat niet kan, wordt het geweigerd bij het laden in plaats van nooit uitgevoerd te worden.

23.10.8 queue

Wachtrij maakt levering duurzaam: een bericht dat nu niet kan worden geleverd, wordt op schijf bewaard en herhaald totdat het kan worden geleverd.

Standaard uitgeschakeld.

23.11 Directe Bestemming

DirectDestination verzendt elk bericht als Direct: ondertekend als dit adres, versleuteld naar elk certificaat van de ontvanger en ingediend bij de HISP via SMTP.

Gedefinieerd als DirectDestination in internal/config.

SleutelTypeVereistStandaard
tolijst van tekstja—
subjecttekstnee—
texttekstnee—
attach_nametekstnee—
xdmtrue of falsenee—
xdm_source_idtekstnee—
recipient_certs_dirtekstnee—
dnstekstnee—
ldaptekstnee—
smtp_hosttekstja—
usernametekstnee—
passwordtekstnee—
request_mdntrue of falsenee—
timeoutduur, zoals 30s of 5mnee—

23.11.1 aan

Aan zijn de Direct-adressen van de ontvangers.

Veldverwijzingen worden vervangen, dus een ontvanger kan uit het bericht komen.

23.11.2 recipient_certs_dir

RecipientCertsDir bevat ontvangercertificaten (PEM, één bestand per adres of domein, address.pem of domain.pem) die van tevoren zijn gevonden; leeg leest het server-Direct-adresboek (het Direct-scherm).

Ontvangers die daar niet zijn, worden opgezocht in DNS (CERT-records). Direct verzendt geen bericht naar een ontvanger wiens certificaat niet kan worden gevonden.

23.11.3 ldap

LDAP is het adresboek waarin het certificaat van een ontvanger wordt opgezocht wanneer DNS geen certificaat heeft (host:poort, poort 389): de tweede manier waarop de Direct-certificaatontdekkingsgids dit toelaat.

Leeg vindt het adresboek van de domein van de ontvanger door zijn DNS SRV-record (_ldap._tcp), zoals de gids zegt; "uit" vraagt nooit een adresboek.

23.12 Documentbestemming

DocumentDestination rendert elk bericht in een document.

Gedefinieerd als DocumentDestination in internal/config.

SleutelTypeVereistStandaard
dirtekstja—
formatDocumentFormatneepdf
templatetekstja—
titletekstnee—
file_nametekstnee—
font_sizenummernee10
landscapetrue of falsenee—
temp_suffixtekstnee"
timeoutduur, zoals 30s of 5mnee30s

23.12.1 formaat

Formaat is pdf of tekst.

Standaard pdf.

23.12.2 template

Sjabloon is de documentbody, met ${PID-5.1} stijlverwijzingen naar berichtpaden.

Vereist. Er is geen zinnige standaard: een document zonder sjabloon zou het ruwe bericht zijn, wat niemand wil afdrukken, of leeg.

23.12.3 lettergrootte

Lettergrootte in punten.

Standaard 10, wat 80 tekens over A4 past.

23.12.4 temp_suffix

TempSuffix wordt toegevoegd tijdens het schrijven en verwijderd door een hernoeming.

Standaard is ".part".

Dezelfde hoffelijkheid als elke andere bestemming van bestanden, en het maakt hier meer uit: een printwatcher die een halfgeschreven PDF oppakt, produceert een pagina met niets, en niemand onderzoekt een lege pagina.

23.12.5 time-out

Time-outgrenzen één schrijfactie.

Defaults to 30s.

23.13 ECR-bestemming

ECRDestination configureert elektronische casusrapportage.

Gedefinieerd als ECRDestination in internal/config.

SleutelTypeVereistStandaard
rctctekstnee—
sourcetekstja—
facilityECRFacilityja—

23.13.1 rctc

RCTC is een FHIR ValueSet, of een bundel ervan, zoals de eRSD, die de triggercodes bevat.

Zonder het wordt Perfuse's korte ingebouwde voorbeeld gebruikt, dat voor testen is: agentschappen verwachten de RCTC.

23.14 ELR-bestemming

ELRDestination configureert elektronische laboratoriumrapportage.

Gedefinieerd als ELRDestination in internal/config.

SleutelTypeVereistStandaard
configtekstja—
rctctekstnee—

23.14.1 config

Config is het ELR-bestand perfuse elr -config dat leest: de verzendende en ontvangende toepassingen en faciliteiten per OID, de verwerkingsmodus en wat de gaten vult die een labvoeding achterlaat (bestellingsfaciliteit, uitvoerend lab, toewijzingsautoriteiten).

Een relatief pad wordt gelezen vanuit het directory van het kanaalbestand.

23.14.2 rctc

RCTC is een FHIR ValueSet, of een bundel ervan, zoals de eRSD, die de triggercodes bevat.

Zonder het wordt Perfuse's korte ingebouwde voorbeeld gebruikt, dat voor testen is: agentschappen verwachten de RCTC. Relatief tot het kanaalbestand, zoals Config.

23.15 FHIR-bestemming

FHIRDestination configureert conversie naar FHIR en levering aan een FHIR-server.

Gedefinieerd als FHIRDestination in internal/config.

KeyTypeRequiredDefault
urltextyes—
versiontextnoR5
timezonetextno—
default_identifier_systemtextno—
identifier_systemsmapping of text to textno—
claim_us_coretrue or falseno—
validate_before_sendtrue or false (a block, omit to leave off)notrue: sending a resource a server will reject wastes a retry budget and hides the real problem behind a transport error
reject_on_warningtrue or falseno—
headersmapping of text to textno—
bearer_tokentextno—
authFHIRAuth (a block, omit to leave off)no—
ecrECRDestination (a block, omit to leave off)no—
bundle_scripttextno—

23.15.1 url

URL is de basis-URL van de FHIR-server, bijvoorbeeld "https://fhir.example.org/fhir".

De bundel wordt rechtstreeks naar deze URL verzonden.

23.15.2 versie

Versie is de FHIR-release die moet worden geproduceerd: R4, R4B of R5. Standaard is R5, de laatste gepubliceerde release.

Een implementatie die communiceert met een EHR wil meestal R4 en moet dit aangeven, omdat stilzwijgend downgraden een echt interoperabiliteitsbesluit zou verbergen.

23.15.3 tijdzone

De tijdzone wordt toegepast op HL7 v2-tijdstempels die geen offset bevatten. v2 staat een kale lokale tijd toe en FHIR niet, dus er moet iets worden toegevoegd.

Wanneer deze niet is ingesteld, wordt de offset die de afzender op MSH-7 heeft gezet, gebruikt, omdat v2 ervan uitgaat dat een kale tijd de lokale tijd van de afzender is; een bericht waarvan MSH-7 geen offset bevat, valt terug op UTC.

23.15.4 default_identifier_systeem

DefaultIdentifierSystem naamruimten identificatoren waarvan de toewijzingsautoriteit geen geconfigureerde URI heeft.

Zonder een systeem is een MRN ambigu tussen faciliteiten.

23.15.5 claim_us_core

ClaimUSCore voegt het US Core 9.0.0-profiel toe aan elke gegenereerde resource die is gecontroleerd tegen het profiel en overeenkomt.

Een resource die niet voldoet, wordt verzonden zonder de claim, met een notitie waarom.

23.15.6 valideer_voor_verzending

ValidateBeforeSend weigert een bundle te posten die de validatie niet doorstaat.

Standaard ingesteld op true: het verzenden van een resource die een server zal weigeren, verspilt een retry-budget en verbergt het echte probleem achter een transportfout.

23.15.7 weiger_op_waarschuwing

RejectOnWarning weigert ook op waarschuwingen, zoals een ontbrekende US Core-identifier.

Uitgeschakeld standaard, omdat een waarschuwing een oordeel is over profielconformiteit in plaats van over geldigheid.

23.15.8 bearer_token

BearerToken wordt verzonden als een Authorization-header.

Geef de voorkeur aan een omgevingsvariabele-referentie, ${NAME}, boven een letterlijke waarde in een bestand dat naar git gaat.

23.15.9 ecr

ECR maakt dit een bestemming voor openbare gezondheidszorg en casusrapportage.

Elk bericht wordt gecontroleerd op triggercodes; een bericht met triggercodes wordt verzonden als een eCR 2.1 eICR, ingepakt in een eCR-bericht, naar de url's $process-message, en een bericht zonder triggercodes wordt helemaal niet verzonden.

23.15.10 bundle_script

BundleScript is JavaScript die wordt uitgevoerd op elk omgezet Bundle voordat het wordt gevalideerd en verzonden: bundle is het Bundle als een object, bewerkt op locatie.

Het is de manier waarop een site zijn eigen systemen toevoegt en de v2-boodschap niet zegt - de IKNR- of ODS-code van zijn organisatie, het contactniveau van een nationaal profiel - zonder dat de converter het moet raden. Een script dat een fout gooit, faalt de boodschap, net als elke andere transformatie. Wordt niet uitgevoerd voor casusrapporten (ecr).

23.16 FTP-bestemming

FTPDestination uploadt een bestand per bericht.

Gedefinieerd als FTPDestination in internal/config.

SleutelTypeVereistStandaard
hosttekstja21
usertekstnee—
passwordtekstnee—
securityFTPSecurityneeexpliciet in plaats van geen
insecure_skip_verifywaar of onwaarnee—
allow_clear_passwordwaar of onwaarnee—
dirtekstja—
file_nametekstnee—
temp_suffixtekstnee"
framedwaar of onwaarnee—
timeoutduur, zoals 30s of 5mnee60s

23.16.1 host

Host is de server, met een optionele poort.

Standaard ingesteld op 21, of 990 voor impliciete TLS.

23.16.2 gebruiker

Gebruiker en wachtwoord authenticeren.

Een lege gebruiker betekent anoniem.

23.16.3 wachtwoord

Gebruiker en wachtwoord authenticeren.

Een lege gebruiker betekent anoniem.

23.16.4 beveiliging

Beveiliging selecteert TLS: expliciet, impliciet of geen.

Standaard wordt expliciet gekozen in plaats van geen, omdat standaard plain FTP kiezen de onveilige keuze zou maken en een site die echt geen TLS heeft, dit zou moeten opschrijven.

23.16.5 insecure_skip_verify

InsecureSkipVerify accepteert elk certificaat.

Vaker nodig dan iemand zou willen: deze servers hebben vaak een zelf-ondertekend certificaat dat jaren geleden is gegenereerd en dat niemand kan opnieuw uitgeven. Afzonderlijk genoemd, zodat het kiezen ervan bewust en zichtbaar is in het bestand in plaats van verborgen in een 'beveiliging: ontspannen' modus.

23.16.6 allow_clear_password

AllowClearPassword staat een wachtwoord toe over plain FTP.

Standaard geweigerd, omdat dit een referentie over het netwerk in platte tekst verzendt bij elke enkele levering. Sommige analysers hebben echt geen TLS, dus het moet mogelijk zijn - maar het moet worden opgeschreven, zodat het een beslissing is die iemand heeft genomen in plaats van een standaard die ze hebben geërfd. De naam is expres oncomfortabel om in te voeren.

23.16.7 temp_suffix

TempSuffix wordt toegevoegd terwijl het bestand wordt geschreven en verwijderd door een hernoeming zodra het voltooid is.

Standaard is ".part".

Degene die deze bestanden verzamelt, is meestal een geplande taak die alles neemt wat hij vindt, en zonder de hernoeming neemt hij uiteindelijk een half bericht.

23.16.8 time-out

Timeout begrenst één overdracht.

Defaults to 60s.

23.17 GCS Bestemming

GCSDestination schrijft elk bericht als een object.

Gedefinieerd als GCSDestination in internal/config.

SleutelTypeVereistStandaard
objecttekstnee${datum}/${kanaal}/${control_id}
storage_classtekstnee—
content_typetekstnee—

23.17.1 object

Object is de objectnaam, met dezelfde placeholders als een s3-sleutel.

Standaard ${date}/${kanaal}/${control_id}.hl7.

23.18 HTTP Bestemming

HTTPDestination verzendt berichten naar een HTTP-eindpunt.

Het meest voorkomende dat een Mirth-kanaal doet dat Perfuse niet kon, en het meest voorkomende blokkeringsbericht dat de vertaler rapporteert. De meeste gebruiken zijn onopvallend: het bericht naar een intern API verzenden, het naar een webservice verzenden die een legacy-systeem omhult, het naar iets verzenden dat iemand in een middag heeft geschreven.

Gedefinieerd als HTTPDestination in internal/config.

KeyTypeRequiredDefault
urltextyes—
methodtextno—
content_typetextno—
headersmapping of text to textno—
bearer_tokentextno—
usernametextno—
passwordtextno—
tlstlsconf.Settings (a block, omit to leave off)no—
success_statuslist of whole numbernoany 2xx
fail_on_bodylist of textno—
follow_redirectstrue or falseno—

23.18.1 url

URL is waar het bericht naartoe moet worden verzonden.

Required.

23.18.2 methode

Methode standaard is POST.

PUT is toegestaan voor een endpoint dat dit wil.

GET en DELETE worden geweigerd: dit verzendt een berichtbody, en een transport dat het bericht stilzwijgend liet vallen vanwege een methodekeuze zou een zeer stille manier zijn om gegevens te verliezen.

23.18.3 content_type

ContentType staat standaard op application/hl7-v2+er7, wat het geregistreerde type is voor een pipe-gescheiden HL7 v2-bericht.

Veel endpoints willen tekst/plaine in plaats daarvan.

23.18.4 bearer_token

BearerToken wordt verzonden als een Authorization-header.

Geef de voorkeur aan een verwijzing naar een omgevingsvariabele boven een letterlijke waarde in een bestand dat naar git gaat.

23.18.5 success_status

SuccessStatus lijst de statuscodes die worden meegeteld als geleverd.

Standaard zijn alle 2xx-codes.

Configureerbaar omdat endpoints het oneens zijn over hoe succes eruitziet: sommige antwoorden 200 met een fout in de body, en sommige antwoorden 202 voor een wachtrij die het bericht heeft geaccepteerd.

23.18.6 fail_on_body

FailOnBody behandelt een antwoord met een van deze tekenreeksen als een fout, ongeacht de statuscode.

Dit bestaat omdat een endpoint dat 200 antwoordt met "ERROR: patient not found" in de body, gebruikelijk is, en het behandelen ervan als geleverd betekent dat het bericht verdwenen is en niemand het weet.

23.18.7 follow_redirects

FollowRedirects staat de aanvraag toe om te worden omgeleid.

Standaard uitgeschakeld: een omleiding bij een schrijfactie zou klinische gegevens opnieuw plaatsen op een locatie die nooit in de configuratie is genoemd.

23.19 IBMMQ Bestemming

IBMMQBestemming plaatst elk bericht in een wachtrij.

Gedefinieerd als IBMMQDestination in internal/config.

SleutelTypeVereistStandaard
non_persistenttrue of falsenee—

23.19.1 non_persistent

NonPersistent verzendt berichten die niet overleven bij een herstart van de wachtrijbeheerder.

Standaard uitgeschakeld.

23.20 Java Script Bestemming

JavaScriptBestemming voert een script uit in plaats van ergens naartoe te verzenden.

Mirth's JavaScript Writer, en het wordt veel vaker gebruikt dan zijn positie in een functielijst suggereert. Het is de ontsnappingsmogelijkheid: wanneer een site moet communiceren met iets waarvoor geen connector beschikbaar is, of logica moet toepassen die geen transformatie uitdrukt, schrijven ze een JavaScript Writer. Een migratie die deze niet kan uitvoeren, kan de kanalen die ze hebben niet verplaatsen, wat in een volwassen Mirth-installatie een groot deel is.

Opzettelijk geen algemene scripthost. Het script krijgt het bericht en dezelfde helpers als een transformatie; wat het niet krijgt, is een manier om toegang te krijgen tot het bestandssysteem of het netwerk, omdat dat is wat de andere bestemmingen zijn voor en een script dat zijn eigen socket opent onzichtbaar is voor elke retry, wachtrij en metriek in de engine.

Gedefinieerd als JavaScriptDestination in internal/config.

SleutelTypeVereistStandaard
scripttekstja—
timeoutduur, zoals 30s of 5mnee—
success_on_undefinedtrue of false (een blok, weglaten om niet te specificeren)neetrue

23.20.1 script

Script is de code die moet worden uitgevoerd.

Required.

23.20.2 time-out

Time-out begrenst één uitvoering.

Nul past een standaard toe.

Begrensd omdat een bestemmingsscript zich op het leveringspad bevindt: een oneindige lus in één ervan zorgt er niet alleen voor dat een bericht mislukt, maar houdt ook de wachtrij erachter vast.

23.20.3 success_on_undefined

SuccessOnUndefined behandelt een script dat niets retourneert als een succes.

Standaard is dit waar.

True is de juiste standaard en het is de moeite waard om uit te leggen. Mirth's JavaScript-schrijvers doen hun werk over het algemeen en retourneren niets, dus het vereisen van een expliciete retour zou allemaal breken bij het importeren. Het instellen op false is voor een site dat een script expliciet wil aangeven of het heeft gewerkt.

23.21 Kafka-bestemming

KafkaDestination publiceert berichten naar een Kafka-onderwerp.

Gedefinieerd als KafkaDestination in internal/config.

KeyTypeRequiredDefault
brokerslist of textyes—
topictextyes—
keytextno—
ackstextnoall
compressiontextnosnappy
headersmapping of text to textno—
timeoutduration, such as 30s or 5mnothirty seconds
saslKafkaSASL (a block, omit to leave off)no—
tlstlsconf.Settings (a block, omit to leave off)no—

23.21.1 brokers

Brokers is de lijst van bootstrap-servers.

Required.

23.21.2 onderwerp

Onderwerp is waar naar toe gepubliceerd moet worden.

Required.

23.21.3 sleutel

Sleutel is een sjabloon voor de record-sleutel, die bepaalt welke partitie wordt gebruikt.

Dit is het veld dat Kafka veilig maakt voor een klinische feed, en het is de moeite waard om precies uit te leggen waarom. Kafka garandeert de volgorde binnen een partitie en nergens anders. Records met dezelfde sleutel komen altijd in dezelfde partitie terecht, dus het gebruik van de patiëntidentificatie om de gebeurtenissen van die patiënt in volgorde te houden, terwijl verschillende patiënten parallel kunnen gaan.

Zonder sleutel is er geen dergelijke garantie. Gemeten tegen een echte broker, gingen dertig ongecodeerde records naar één partitie in plaats van zich te verspreiden: de client houdt een batch bij elkaar en kiest een nieuwe partitie tussen batches. Dus de volgorde blijft per ongeluk intact en breekt op een grens die niemand kan zien, wat erger is dan consistent breken - een A03-ontslag wordt gelezen voordat de A01-toelating, intermittent, onder belasting.

Een HL7-pad, geëvalueerd tegen het uitgaande bericht: PID-3.1 codeert op patiënt.

23.21.4 acks

Acks is het aantal brokers dat een schrijfactie moet bevestigen: "all", "leader" of "none".

Standaard is all, wat de enige instelling is die overleeft als een broker faalt tussen de schrijfactie en de replicatie. "none" is fire-and-forget en zal berichten verliezen; het bestaat omdat iemand die niet-klinische telemetrie verplaatst, legitiem "none" kan willen, en het weigeren ervan zou betekenen dat ze hun eigen producer schreven.

23.21.5 compressie

Compressie is "none", "gzip", "snappy", "lz4" of "zstd".

Standaard is snappy.

Standaard ingeschakeld omdat HL7 zeer compressibele tekst is en de draad meestal de beperking is. Snappy in plaats van zstd als standaard: het is het goedkoopst in CPU, en een connector op het leveringspad moet niet het ding zijn dat een core verzadigt.

23.21.6 headers

Koppen zijn recordkopteksten die worden ingesteld.

Waarden zijn sjablonen die per bericht worden geëvalueerd.

23.21.7 time-out

Time-out beperkt één publicatie.

Standaard is dertig seconden.

23.22 MPI Bestemming

MPIDestination registreert elke patiënt van elk bericht in de patiëntindex van deze server: een HL7 v2 PID (een A40-samenvoeging mergeert), of een FHIR-patiënt op een onbewerkte kanaal.

De index bepaalt welke records dezelfde persoon zijn; zie het scherm Patiëntindex.

Gedefinieerd als MPIDestination in internal/config.

SleutelTypeVereistStandaard
authoritiestoewijzing van tekst aan tekstnee—
id_typetekstnee—
ssn_systemtekstnee—
no_mergewaar of onwaarnee—

23.22.1 bevoegdheden

Bevoegdheden kaart een toewijzingsbevoegdheid (PID-3.4.1) naar zijn identificatiesysteem, voor afzenders die geen universele identifier geven.

Ongekaarte worden urn:perfuse:aa:<namespace>.

23.22.2 id_type

IDType is het identificatietype (PID-3.5) van het eigen nummer van het record.

Default MR.

23.22.3 ssn_system

SSNSystem noemt PID-19 als een identifier.

Default http://hl7.org/fhir/sid/us-ssn.

23.23 MQTT Bestemming

MQTTDestination publiceert naar een onderwerp.

Gedefinieerd als MQTTDestination in internal/config.

SleutelTypeVereistStandaard
topictekstja—
retainwaar of onwaarnee—

23.23.1 onderwerp

Onderwerp wordt gepubliceerd.

Het mag geen wildcards bevatten.

23.24 PAS-bestemming

PASDestination verzendt elk bericht, een Da Vinci PAS-aanvraagbundle, naar een betalers Claim/$submit, voor een zorgverlener wiens systemen de aanvraag bouwen (een EHR, DTR) en deze nodig hebben om te worden verzonden, de beslissing te registreren en het antwoord door te geven.

Gedefinieerd als PASDestination in internal/config.

SleutelTypeVereistStandaard
payertekstja—
bearer_tokentekstnee—
authFHIRAuth (een blok, weglaten om niet te gebruiken)nee—
results_totekstnee—

23.24.1 bearer_token

BearerToken is een statische token, ${ENV} is toegestaan.

Auth is OAuth-clientreferenties in plaats daarvan, of Azure, als een FHIR-bestemming.

23.24.2 auth

BearerToken is een statische token, ${ENV} is toegestaan.

Auth is OAuth-clientreferenties in plaats daarvan, of Azure, als een FHIR-bestemming.

23.25 Pub Sub Bestemming

PubSubDestination publiceert naar een Pub/Sub-onderwerp.

Gedefinieerd als PubSubDestination in internal/config.

SleutelTypeVereistStandaard
topictekstja—
order_bytekstnee—

23.26 S3 Bestemming

S3Bestemming schrijft elk bericht als een object.

Gedefinieerd als S3Destination in internal/config.

KeyTypeRequiredDefault
buckettextyes—
regiontextyes—
keytextnoa date-partitioned path plus the control id
access_key_idtextno—
secret_access_keytextno—
session_tokentextno—
endpointtextno—
path_styletrue or falseno—
server_side_encryptiontextno—
content_typetextnoapplication/hl7-v2 for HL7 and text/plain otherwise
framedtrue or falseno—
timeoutduration, such as 30s or 5mno60s
storage_classtextno—
formattextno—

23.26.1 sleutel

Sleutel sjablonen de object sleutel, met behulp van dezelfde ${datum}, ${tijdstip}, ${controle_id}, ${bericht_type} en ${kanaal} placeholders als de bestand en SFTP bestemmingen.

Standaard een datum-partitiepad plus de controle-id.

Datum-partitie standaard omdat het alternatief - elk object in één plat voorvoegsel - een bucket maakt die langzaam is om te lijsten en onmogelijk is om te leven door leeftijd, en niemand ontdekt dat totdat er vier miljoen objecten in zitten.

23.26.2 toegangs_sleutel_id

AccessKeyID en SecretAccessKey authenticeren.

Een van beide kan een omgevingsvariabele noemen in plaats van de waarde te bevatten, met behulp van de vorm ${NAAM}.

23.26.3 geheime_toegangs_sleutel

AccessKeyID en SecretAccessKey authenticeren.

Een van beide kan een omgevingsvariabele noemen in plaats van de waarde te bevatten, met behulp van de vorm ${NAAM}.

23.26.4 pad_stijl

PathStyle adresseert de bucket als een pad in plaats van een subdomein.

De meeste S3-compatibele opslagruimten hebben dit nodig.

23.26.5 content_type

InhoudsType labelt het object.

Standaard application/hl7-v2 voor HL7 en text/plain anders.

23.26.6 time-out

Time-out begrenst één upload.

Defaults to 60s.

23.26.7 opslag_klasse

StorageClass is de S3-opslagklasse waarin elk object wordt geschreven: STANDARD_IA, INTELLIGENT_TIERING, GLACIER_IR, GLACIER, DEEP_ARCHIVE enz.

Dit is hoe een archief rechtstreeks naar Glacier gaat - S3 heeft geen separate Glacier API om aan te roepen.

23.26.8 formaat

Formaat is hl7 (de standaard: elk object is het bericht) of ndjson: elk object is één JSON-regel met het bericht en de velden die waard zijn om te doorzoeken, onder datum-partitie-sleutels, zodat Amazon Athena de archief kan doorzoeken.

Zie perfuse athena.

23.27 SFTP Bestemming

SFTPDestination schrijft elk bericht naar een bestand op een SFTP-server.

Gedefinieerd als SFTPDestination in internal/config.

KeyTypeRequiredDefault
hosttextyes22
usertextyes—
passwordtextno—
key_filetextno—
key_passphrasetextno—
known_hosts_filetextno—
insecure_skip_host_key_checktrue or falseno—
dirtextyes—
file_nametextnoa timestamp plus the control ID
temp_suffixtextno"
framedtrue or falseno—
appendtrue or falseno—
timeoutduration, such as 30s or 5mno60s

23.27.1 host

Host is de server, met een optionele poort.

Defaults to 22.

23.27.2 wachtwoord

Wachtwoord verifieert met een wachtwoord.

Prefer KeyFile.

23.27.3 file_name

Bestandsnaam sjablonen de naam.

Standaard een tijdstempel plus de controle-ID.

23.27.4 temp_suffix

TijdelijkeSuffix wordt toegevoegd terwijl een bestand wordt geschreven en verwijderd door een hernoeming zodra het voltooid is.

Standaard is ".part".

Hetzelfde als deze connector nodig heeft om binnen te komen. Wie deze bestanden verzamelt, heeft hetzelfde probleem en een hernoeming binnen een directory is atoom op elke server die het waard is om te gebruiken.

23.27.5 time-out

Timeout begrenst een enkele verbinding.

Defaults to 60s.

23.28 SMTP Bestemming

SMTPBestemming configureert levering per e-mail.

Gedefinieerd als SMTPDestination in internal/config.

KeyTypeRequiredDefault
hosttextyes—
fromtextyes—
tolist of textyes—
cclist of textno—
bcclist of textno—
subjecttextno—
bodytextno—
attachtrue or falseno—
attach_nametextnothe control ID with a
usernametextno—
passwordtextno—
starttlstrue or false (a block, omit to leave off)no—
insecure_skip_verifytrue or falseno—
timeoutduration, such as 30s or 5mno—

23.28.1 host

Host is de mailserver, met een optionele poort.

Poort 587 wordt aangenomen, wat overdracht met STARTTLS is - de poort die een moderne server van een client verwacht. Poort 25 is server-naar-server en is meestal geblokkeerd of niet-geliberaliseerd.

23.28.2 van

Van is de afzender van de envelop.

Vereist, omdat een bericht zonder afzender stilzwijgend wordt verwijderd door een groot deel van de mailinfrastructuur, wat het moeilijkste mogelijke fout is om te diagnosticeren.

23.28.3 aan

Aan, CC en BCC zijn ontvangers.

Ten minste één Aan is vereist.

23.28.4 cc

Aan, CC en BCC zijn ontvangers.

Ten minste één Aan is vereist.

23.28.5 bcc

Aan, CC en BCC zijn ontvangers.

Ten minste één Aan is vereist.

23.28.6 body

Body is de tekst van het bericht.

Veldverwijzingen worden vervangen, zoals in Onderwerp. Wanneer het leeg is, is het bericht zelf het lichaam.

23.28.7 bijlagen_naam

BijlagenNaam noemt de bijlage.

Standaard de controle-ID met een .hl7-suffix.

23.28.8 gebruikersnaam

Gebruikersnaam en Wachtwoord authenticeren bij de server.

Beide of geen

23.28.9 wachtwoord

Gebruikersnaam en Wachtwoord authenticeren bij de server.

Beide of geen

23.28.10 starttls

StartTLS upgradet de verbinding voordat deze wordt geauthenticeerd.

Het staat standaard aan en uitschakelen met een gebruikersnaam ingesteld wordt geweigerd in plaats van toegestaan: het verzenden van een wachtwoord over een onbeveiligde verbinding is geen compromis dat het waard is om aan te bieden.

23.28.11 insecure_skip_verify

InsecureSkipVerify accepteert elk certificaat.

Ondubbelzinnig genoemd omdat dat is wat het doet.

23.29 SNS-bestemming

SNSDestination publiceert elk bericht naar een SNS-onderwerp.

Gedefinieerd als SNSDestination in internal/config.

SleutelTypeVereistStandaard
topic_arntekstja—
subjecttekstnee—
group_bytekstnee—

23.29.1 onderwerp

Onderwerp wordt verzonden met e-mailabonnementen.

Optioneel; ${message_type} en ${control_id} worden ingevuld.

23.30 SOAP-bestemming

SOAPDestination plaatst een SOAP-aanvraag per bericht.

Gedefinieerd als SOAPDestination in internal/config.

KeyTypeRequiredDefault
urltextyes—
profiletextno—
facility_idtextno—
warnings_are_errorstrue or falseno—
actiontextno—
versiontextno1
bodytextyes—
headertextno—
headersmapping of text to textno—
usernametextno—
passwordtextno—
tlstlsconf.Settings (a block, omit to leave off)no—
fault_is_successlist of textno—
timeoutduration, such as 30s or 5mno30s

23.30.1 profiel

Profielnaam noemt een standaarddienst waarvan Perfuse de envelop zelf bouwt.

Leeg is een gewone SOAP-aanroep met de body die in dit bestand is geschreven.

"cdc-iis" is de CDC's immunisatieregisterinterface (urn:cdc:iisb:2011), die elk Amerikaans staatsregister gebruikt: het bericht gaat in submitSingleMessage, gebruikersnaam en wachtwoord gaan in de body zoals de WSDL zegt (niet als HTTP-verificatie), SOAP 1.2 standaard en de registers HL7-bevestiging beslist of het bericht is afgeleverd. Een register antwoordt op een afgewezen injectie met HTTP 200 en een AR erin, dus zonder dit leest een afwijzing als een succes.

23.30.2 faciliteits_id

FaciliteitsID is de cdc-iis faciliteitsID, de registers identifier voor de indienende organisatie.

Optioneel in de WSDL; sommige registers vereisen het.

23.30.3 waarschuwingen_zijn_fouten

WaarschuwingenZijnFouten, voor cdc-iis, behandelt een AE-bevestiging met alleen waarschuwingen als een fout.

Uitgeschakeld standaard: registers sturen AE voor "geaccepteerd met waarschuwingen" en de ERR-ernst zegt of er iets verloren is gegaan.

23.30.4 actie

Actie is de SOAPAction.

Vereist door de meeste diensten 1.1.

23.30.5 body

Body is de XML die binnen de enveloppe komt, met ${PID-5.1} stijl verwijzingen naar berichtenpaden.

Vereist, tenzij een profiel het bouwt. Er is geen bruikbare standaard: de elementnamen komen uit het schema van de dienst zelf en geen engine kan ze raden.

23.30.6 header

Header is XML voor het Header-element van de enveloppe.

Volledig weggelaten wanneer leeg, omdat sommige diensten een lege header weigeren.

23.30.7 fault_is_success

FaultIsSuccess lijst faultcodes die als geleverd worden beschouwd.

Vaker nodig dan zou moeten. Een dienst die een resend beantwoordt met "al ingediend" zegt je dat het bericht is aangekomen, en zonder dit moet een site een response transformer schrijven om dit te zeggen - of erger, kijkt een queue oneindig tegen een ontvanger aan die het bericht al heeft.

23.30.8 time-out

Time-out beperkt één oproep.

Defaults to 30s.

23.31 SQS Bestemming

SQSBestemming verzendt elk bericht naar een SQS-wachtrij.

Gedefinieerd als SQSDestination in internal/config.

SleutelTypeVereistStandaard
queue_urltekstja—
group_bytekstnee—

23.31.1 queue_url

QueueURL noemt de wachtrij.

Een die eindigt op .fifo is een FIFO-wachtrij en wordt gegroepeerd en gedupliceerd.

23.32 TCP Bestemming

TCPBestemming verzendt berichten naar een socket met configureerbare framing.

Gedefinieerd als TCPDest in internal/config.

SleutelTypeVereistStandaard
addresstekstja—
max_message_sizegeheel getalnee—
timeoutduur, zoals 30s of 5mnee—
expect_replywaar of onwaarnee—
keep_alivewaar of onwaarnee—
tlstlsconf.Settings (een blok, weglaten om niet te gebruiken)nee—

23.32.1 expect_reply

ExpectReply wacht op bytes terug voordat het succes rapporteert.

Standaard uitgeschakeld en het is de moeite waard om hierover na te denken. Met deze optie uitgeschakeld, betekent "geleverd" dat de bytes de verzendbuffer van het besturingssysteem hebben bereikt, die een peer die een moment later crashte nooit heeft gelezen. Met deze optie ingeschakeld, zal elke boodschap time-outen als een peer nooit reageert.

23.32.2 keep_alive

KeepAlive houdt één verbinding open over meerdere berichten heen in plaats van een verbinding per bericht te maken.

De meeste apparaat-eindpunten verwachten dit; sommige weigeren een tweede bericht op dezelfde verbinding. Standaard uitgeschakeld omdat een verbinding per bericht het gedrag is dat overal werkt, tegen de kosten van een handslag elke keer.

23.33 TEFCA Bestemming

TEFCABestemming vraagt de TEFCA Facilitated FHIR-partner om de records van elke patiënt van elk bericht.

Wie deze server is op het netwerk, zijn certificaat en de partner zijn serverinstellingen (Instellingen, TEFCA), omdat ze toebehoren aan de organisatie en hun overeenkomst met een QHIN. Wat een kanaal beslist is wanneer het moet vragen en waarom: het doel van het gebruik maakt deel uit van het kanaal, niet van degene die is aangemeld, dus elke query die een feed maakt, specificeert hetzelfde doel en de audittrail kan ertegen worden gelezen.

Gedefinieerd als TEFCADestination in internal/config.

SleutelTypeVereistStandaard
purposetekstja—
results_totekstnee—

23.33.1 doel

Doel is het doel van het gebruik: behandeling, betaling, operaties, volksgezondheid of toegang voor individuen.

Het moet een van de deelnemers zijn die het verklaart.

23.33.2 resultaten_naar

ResultatenNaar specificeert een kanaal in deze server dat elke Bundle van de partner retourneert als een bericht van zichzelf.

Leeg houdt de Bundle als antwoord van deze bestemming alleen, voor een respons transformatie om te lezen.

23.34 XDS Bestemming

XDSDestination publiceert elk klinisch document naar een IHE XDS.b Document Repository met ITI-41 Provide and Register.

De metagegevens worden gelezen uit het CDA-document (patiënt, titel, type, tijd, auteur, vertrouwelijkheid, taal) en aangevuld met deze instellingen, die aangeven wat het document niet kan zijn: wie het verstuurt, wat voor soort faciliteit en praktijk het vandaan komt, en welke van de patiëntidentificatoren de affiniteitsdomein is.

Gedefinieerd als XDSDestination in internal/config.

KeyTypeRequiredDefault
urltextyes—
source_idtextyes—
patient_domaintextno—
facility_typeXDSCodeyes—
practice_settingXDSCodeyes—
classXDSCode (a block, omit to leave off)no—
content_typeXDSCode (a block, omit to leave off)no—
tokentextno—
usernametextno—
passwordtextno—
headersmapping of text to textno—
tlstlsconf.Settings (a block, omit to leave off)no—
timeoutduration, such as 30s or 5mno—
direct_fromtextno—
direct_tolist of textno—

23.34.1 patient_domain

PatientDomain is de affiniteitsdomein's toewijzingsautoriteit OID: de patiëntidentificator met deze root is de geregistreerde.

Zonder dit wordt een document van een patiënt met één identificator geweigerd en wordt een document van een patiënt met meerdere identificatoren alleen verstuurd als er één identificator is.

23.34.2 token

Token of Username/Wachtwoord authenticeren; Headers worden toegevoegd aan elke aanvraag.

De meeste affiniteitsdomeinen gebruiken wederzijdse TLS (tls) in plaats daarvan.

23.34.3 gebruikersnaam

Token of Username/Wachtwoord authenticeren; Headers worden toegevoegd aan elke aanvraag.

De meeste affiniteitsdomeinen gebruiken wederzijdse TLS (tls) in plaats daarvan.

23.34.4 wachtwoord

Token of Username/Wachtwoord authenticeren; Headers worden toegevoegd aan elke aanvraag.

De meeste affiniteitsdomeinen gebruiken wederzijdse TLS (tls) in plaats daarvan.

23.34.5 headers

Token of Username/Wachtwoord authenticeren; Headers worden toegevoegd aan elke aanvraag.

De meeste affiniteitsdomeinen gebruiken wederzijdse TLS (tls) in plaats daarvan.

23.34.6 tls

Token of Username/Wachtwoord authenticeren; Headers worden toegevoegd aan elke aanvraag.

De meeste affiniteitsdomeinen gebruiken wederzijdse TLS (tls) in plaats daarvan.

23.34.7 direct_van

DirectVan en DirectAan maken de indiening XDR als Direct-vervoer: een Direct-adresblok met de naam van de afzender en de ontvangers, en de ontvangers in de bedoelde ontvanger van de indiening.

Een HISP die XDR levert, levert het als Direct-mail of naar het XDR-eindpunt van de ontvanger.

23.34.8 direct_aan

DirectVan en DirectAan maken de indiening XDR als Direct-vervoer: een Direct-adresblok met de naam van de afzender en de ontvangers, en de ontvangers in de bedoelde ontvanger van de indiening.

Een HISP die XDR levert, levert het als Direct-mail of naar het XDR-eindpunt van de ontvanger.

24 Formaat Referentie

Opties die bepalen hoe berichten worden geparsed en geschreven, voor de formaten die meer dan een naam nodig hebben.

24.1 Bijlagen

Bijlagen configureert het verplaatsen van grote payloads uit een bericht.

Een bericht met een gescand rapport of een PDF is gebruikelijk in documentworkflows, en de payload is routinematig honderden keren groter dan het bericht eromheen. Als het inline wordt gelaten, betekent dit dat de opslag groeit met de snelheid van de documenten in plaats van het verkeer, een bericht dat in de wachtrij staat voor vijf bestemmingen wordt vijf keer gekopieerd, en de interface streamt megabytes om iemand een patiëntnaam te laten zien.

Mirth noemt deze bijlagebehandelaars. Dit is het equivalent, en het is opt-in per kanaal omdat een feed van gewone ADT-berichten niets heeft om te extraheren en niet zou moeten betalen voor de machinerie.

Gedefinieerd als Attachments in internal/config.

SleutelTypeVereistStandaard
extractlijst van attach.Regelja—
reassembletrue of false (een blok, weglaten om niets te doen)neetrue

24.1.1 reassemble

Reassemble zet payloads terug voordat ze worden afgeleverd.

Standaard is dit waar.

De standaardinstelling is aan omdat een ontvanger die een document verwacht, een document moet krijgen; een bericht dat een letterlijke token bevat, zou worden opgeslagen als een rapport en niemand zou erachter komen totdat iemand het record opende.

Het uitschakelen is voor het geval waarin het doel van het kanaal is om documenten te verwijderen - metadata doorsturen naar een systeem dat geen gebruik maakt van het beeld, waarbij het verzenden ervan een privacykwestie zou zijn in plaats van een bandbreedtekwestie.

24.2 Gelimiteerd

Begrensd configureert een begrensde kanaal.

Mirth's Delimited gegevenstype: CSV, tab-gescheiden en de lange staart van formaten die een laboratoriumanalyse of een bureauservice uitgeeft.

Gedefinieerd als Delimited in internal/config.

SleutelTypeVereistStandaard
delimitertekstnee—
quotetekstneeeen dubbele aanhalingsteken
commenttekstnee—
has_headertrue of falsenee—
columnslijst van tekstnee—
trim_spacetrue of falsenee—
relaxedtrue of falsenee—
splittrue of false (een blok, weglaten om het uit te schakelen)neetrue
keep_blank_linestrue of falsenee—
filtertekstnee—
transformationslijst van stappen.Stapnee—

24.2.1 scheidingsteken

Scheidingsteken scheidt kolommen, als een teken of een naam.

Een naam wordt geaccepteerd omdat een tab niet ondubbelzinnig in een YAML-bestand kan worden geschreven en een configuratiebestand met een onzichtbaar teken onleesbaar is voor degene die het het volgende moment opent.

24.2.2 aanhalingsteken

Aanhalingstekens omvatten waarden die het scheidingsteken bevatten.

Standaard is een dubbele aanhalingsteken; 'none' schakelt het uit.

24.2.3 splitsen

Splitsen maakt elke rij zijn eigen bericht.

Standaard is dit waar.

Dit is de beslissing die een begrensd kanaal vormt en het verdient om hardop te worden gezegd. Een bestand met vijfduizend resultaten is ofwel één bericht of vijfduizend. Één bericht betekent één bevestiging, één vermelding in de browser en één fout die het hele bestand meeneemt. Vijfduizend betekent dat elke rij afzonderlijk wordt gefilterd, getransformeerd, geleverd en opnieuw geprobeerd, en één slechte rij stopt de rest niet.

Splitsen is standaard omdat per-regelafhandeling is wat bijna elke site wil en omdat de alternatief te laat wordt ontdekt: een kanaal dat er in tests met een drie-regelbestand goed uitzag, faalt een hele nacht door één onjuist gevormde regel.

24.2.4 lege_regels_bewaren

KeepBlankLines voorkomt dat lege regels worden overgeslagen.

Overslaan is standaard, omdat elk bestand eindigt met een nieuwe regel en een record van lege velden geen record is. Dit bestaat voor het zeldzame formaat waarin een lege regel betekenisvol is.

24.2.5 filter

Filter bepaalt welke berichten worden doorgestuurd, geschreven tegen kolomnamen.

Hier in plaats van op het kanaal, omdat het kanaalniveau-filter HL7-paden compileert. Twee instellingen met de naam filter zouden verwarrend zijn, maar één instelling die verschillende dingen betekent afhankelijk van dataType is erger: een begrensd kanaal dat stilzwijgend zijn filter compileert als HL7 zou niets matchen en alles weggooien, wat de fout is die de bovenste weigering bestaat om te voorkomen.

24.2.6 transformaties

Transformaties zijn de declaratieve stappen, die kolommen adresseren in plaats van HL7-velden.

Afzonderlijk van de transformaties van het kanaal om dezelfde reden als Filter, en het is de regeling die X12 en NCPDP al gebruiken.

24.3 HL7v3-opties

HL7v3Opties zijn de instellingen die alleen van toepassing zijn op een HL7 v3-kanaal.

Gedefinieerd als HL7v3Options in internal/config.

SleutelTypeVereistStandaard
filtertekstnee—
acknowledgetrue of false (een blok, weglaten om het uit te schakelen)nee—
sender_devicetekstnee—
sender_oidtekstnee—
transformationslijst van hl7v3.Stapnee—

24.3.1 filter

Filter sluit berichten uit met behulp van v3-paden.

Het heeft zijn eigen veld in plaats van het gewone filter van het kanaal, omdat het twee verschillende talen tegenover verschillende berichtmodellen betreft. Het delen van het veld zou betekenen dat een v2-filter stilzwijgend nooit overeenkomt met een v3-kanaal, of een v3-filter niet kan worden geparsed als v2 - en het tweede is alleen maar beter omdat het luidruchtig faalt.

Een kanaal dat beide instelt, wordt geweigerd bij het laden, omdat een van de twee genegeerd moet worden en er geen eerlijke manier is om te kiezen.

24.3.2 bevestigen

Bevestigen verzendt een MCCI_IN000002UV01-bevestiging terug.

Standaard ingeschakeld, in tegenstelling tot X12. Een v3-interactie via een synchrone transport verwacht een bevestiging - de verzendende toepassing wacht meestal op een - en een verzender die niets ontvangt, zal meestal opnieuw proberen, waardoor een patiënt drie keer wordt geregistreerd.

Een pointer zodat 'niet ingesteld' en 'ingesteld op false' verschillend zijn: de standaard is ingeschakeld en iemand die het uitschakelt, zou dat moeten zeggen.

24.3.3 verzend_apparaat

VerzendApparaat is de apparaatidentifier die we in een bevestiging plaatsen.

Vereist bij het bevestigen. Een v3-bevestiging noemt het apparaat waar het vandaan komt en een ontvanger die de onze niet herkent, kan het weggooien - wat er precies uitziet als het niet verzenden.

24.3.4 transformaties

Transformaties veranderen de inhoud van een v3-document.

Het heeft zijn eigen veld in plaats van de gewone transformaties van het kanaal, om dezelfde reden als het filter: het zijn verschillende vocabulaires tegenover verschillende berichtmodellen. De v2-stappen adresseren segmenten en velden, die een v3-document niet heeft, dus het delen van het veld zou betekenen dat een stap stilzwijgend niets doet.

De stapnamen komen overeen met de v2-namen waar de betekenis overeenkomt, zodat iemand die een kanaal heeft geschreven, het andere kan schrijven. Wat anders is, is wat v3 nodig heeft en v2 niet kan uitdrukken - voornamelijk dat het verwijderen van een waarde drie verschillende betekenissen heeft, dus clear, nullflavor en remove zijn drie stappen in plaats van een.

24.4 TCP-framing

TCPFraming is de manier waarop berichtgrenzen worden gevonden op een raw socket.

Gedeeld door de TCP-bron en de TCP-bestemming, en door de seriële bron, omdat de framing hetzelfde is waar de bytes vandaan komen. Een laboratoriumanalyse die STX/ETX over een socket spreekt, spreekt STX/ETX over een seriële kabel.

Gedefinieerd als TCPFraming in internal/config.

SleutelTypeVereistStandaard
framingtekstja—
delimitertekstnee—
start_blocktekstnee—
keep_delimitertrue of falsenee—
record_lengthgeheel getalnee—
trim_paddingtrue of false (een blok, weglaten om uit te schakelen)nee—
length_bytesgeheel getalnee—
big_endiantrue of falsenee—
length_includes_headertrue of falsenee—

24.4.1 framing

Framing is mllp, begrensd, vast, lengte of geheel.

Vereist, zonder standaard. Het lezen van een stroom met de verkeerde framing produceert berichten die plausibel lijken in plaats van een fout, dus raden is erger dan vragen.

24.4.2 start_block

StartBlock begint optioneel een bericht.

Bytes ervoor worden weggegooid als ruis van een gedeeltelijke verbinding.

24.4.3 keep_delimiter

KeepDelimiter inclusief de delimiter in het bericht.

Uitgeschakeld als standaard: het is framing, niet inhoud.

24.4.4 trim_padding

TrimPadding verwijdert trailing spaties en NULs uit een vast record.

Aan als standaard.

24.5 X12 Opties

X12Opties zijn de instellingen die alleen van toepassing zijn op een X12-kanaal.

Gedefinieerd als X12Options in internal/config.

SleutelTypeVereistStandaard
envelopeEnvelopePolicyneevereisen
splittrue of falsenee—
acknowledgetekstnee—
ack_sender_idtekstnee—
ack_sender_qualifiertekstnee—
arrives_astekstnee—
transformationslijst van x12.Stepnee—

24.5.1 envelope

Envelope geeft aan wat te doen wanneer de zelf-verklaarde tellingen niet overeenkomen met wat aanwezig is.

Standaard is vereisen.

24.5.2 splitsen

Split verzendt één bericht per transactieset in plaats van één per bestand.

Uitgeschakeld als standaard. Een enkele 837 kan honderden claims dragen, dus het inschakelen hiervan vermeerdert alles stroomafwaarts - berichtentellingen, bevestigingen, rijen, alarmdrempels - en dat moet een beslissing zijn die iemand neemt in plaats van een standaard die wordt geërfd.

24.5.3 bevestigen

Acknowledge geeft aan welke bevestiging moet worden teruggestuurd: 999, 997, ta1 of geen.

Welke een eigenschap is van de handelspartnerrelatie in plaats van van het bericht, dus het moet worden geconfigureerd. Een 999 vervangt een 997 voor HIPAA-transacties, maar veel partners - oude payer-verbindingen in het bijzonder - zijn ingesteld om een 997 te verwachten en zullen een 999 behandelen als een onherkend bestand. Het verzenden van de verkeerde is erger dan het verzenden van geen, omdat het antwoord geeft op een vraag die niemand heeft gesteld en de echte vraag openlaat.

Leeg betekent geen, wat de veilige standaard is: een partner die geen bevestiging verwacht en er een ontvangt, kan deze behandelen als een ongevraagde uitwisseling.

24.5.4 ack_sender_id

AckSenderID en AckSenderQualifier zijn onze eigen interchange-identifier, die ISA06 en ISA05 van elke bevestiging worden.

Vereist wanneer Acknowledge is ingesteld en geweigerd bij laden anders. Deze moeten de waarden zijn die de handelspartner voor ons heeft geconfigureerd en er is geen manier om ze te raden: een uitwisseling waarvan ISA06 de partner niet herkent, wordt weggegooid voordat iemand het leest, dus een verkeerde waarde produceert stilte die er precies uitziet als niets verzenden - en iemand spendeert een week aan het zoeken op de verkeerde plek.

24.5.5 ack_sender_qualifier

AckSenderID en AckSenderQualifier zijn onze eigen interchange-identifier, die ISA06 en ISA05 van elke bevestiging worden.

Vereist wanneer Acknowledge is ingesteld en geweigerd bij laden anders. Deze moeten de waarden zijn die de handelspartner voor ons heeft geconfigureerd en er is geen manier om ze te raden: een uitwisseling waarvan ISA06 de partner niet herkent, wordt weggegooid voordat iemand het leest, dus een verkeerde waarde produceert stilte die er precies uitziet als niets verzenden - en iemand spendeert een week aan het zoeken op de verkeerde plek.

24.5.6 aankomt_als

Komt binnen als xml wanneer de bron de uitwisseling levert als de xml die Mirth Connect en Open Integration Engine schrijven voor X12 (een X12Transaction-root, elementen met de naam CLM.05.1), als een motor die wordt gemigreerd van, of een systeem dat is gebouwd tegen een van hen, het verzendt.

Het wordt omgezet in X12 voordat er iets anders gebeurt. Leeg of x12 is X12.

24.5.7 transformaties

Transformaties zijn declaratieve wijzigingen die worden toegepast op geaccepteerde uitwisselingen.

Los van de kanaal-niveau-transformaties om dezelfde reden waarom de v3-ers dat zijn: die adresseren HL7-velden via een parser die segment-veld-onderdeel-subonderdeel leest, en X12 heeft geen subonderdeel, behandelt herhaalde segmenten als gewoon in plaats van uitzonderlijk en wordt geschreven CLM01 door de mensen die het configureren. Een gedeelde parser zou zowel notaties moeten accepteren en zou dan ambigu zijn in beide.

De stapnamen zijn dezelfde die de HL7- en v3-stappen gebruiken, dus wat een auteur al heeft geleerd, wordt overgedragen.

25 Gedragsreferentie

Bevestiging, queuing, retry, polling, scripting en schaduwinstellingen. Deze zijn van toepassing ongeacht welk transport een kanaal gebruikt.

25.1 AMQP-verbinding

AMQPConnection is waar en als wie verbonden moet worden.

Gedefinieerd als AMQPConnection in internal/config.

KeyTypeRequiredDefault
addrtextyes—
addresstextyes—
usernametextno—
passwordtextno—
hostnametextnothe host of addr
tlstlsconf.Settings (a block, omit to leave off)no—
timeoutduration, such as 30s or 5mno30s

25.1.1 gebruikersnaam

Gebruikersnaam en wachtwoord authenticeren met SASL PLAIN; beide leeg betekent ANONYMOUS.

Voor Service Bus, de naam en sleutel van het beleid.

25.1.2 wachtwoord

Gebruikersnaam en wachtwoord authenticeren met SASL PLAIN; beide leeg betekent ANONYMOUS.

Voor Service Bus, de naam en sleutel van het beleid.

25.1.3 hostname

Hostname wordt naar de broker gestuurd, waarop Service Bus wordt gerouteerd.

Standaard de host van addr.

25.1.4 tls

TLS versleutelt de verbinding.

Vereist voor Service Bus en Event Hubs.

25.1.5 time-out

Time-out grenzen voor het verbinden en elk wachten op de broker.

Defaults to 30s.

25.2 AS2-partner

AS2Partner is een handelspartner van wie een AS2-bron berichten accepteert.

Gedefinieerd als AS2Partner in internal/config.

SleutelTypeVereistStandaard
idtekstja—
cert_filetekstja—
allow_unsignedwaar of onwaarnee—
allow_unencryptedwaar of onwaarnee—

25.2.1 cert_file

CertFile is het certificaat van de partner (PEM), voor zijn handtekeningen.

Vaak zelf-ondertekend: AS2-partners wisselen certificaten rechtstreeks uit in plaats van via een autoriteit.

25.2.2 allow_unsigned

AllowUnsigned en AllowUnencrypted accepteren een bericht van deze partner dat niet is ondertekend of niet is versleuteld.

Uit: een dergelijk bericht wordt geweigerd met een ontvangstbewijs dat de reden aangeeft.

25.2.3 allow_unencrypted

AllowUnsigned en AllowUnencrypted accepteren een bericht van deze partner dat niet is ondertekend of niet is versleuteld.

Uit: een dergelijk bericht wordt geweigerd met een ontvangstbewijs dat de reden aangeeft.

25.3 AWS-toegang

AWS-toegang is de manier waarop een connector AWS bereikt: de regio waarvoor het ondertekent, de sleutels en een optionele eindpuntovername.

Referenties mogen letterlijk zijn of ${ENV_VAR}-verwijzingen, dat is de manier waarop ze moeten worden geleverd. Er is geen instantie-metadata-referentieketen, met opzet: zie internal/awsv4.

Gedefinieerd als AWSAccess in internal/config.

SleutelTypeVereistStandaard
regiontekstja—
access_key_idtekstnee—
secret_access_keytekstnee—
session_tokentekstnee—
endpointtekstnee—

25.3.1 geheime_toegangs_sleutel

GeheimeToegangSleutel is het geheime, letterlijke of ${AWS_GEHEIME_TOEGANGS_SLEUTEL}.

Verwijs naar de voorkeur: dit bestand gaat naar versiebeheer.

25.3.2 sessietoken

SessieToken is alleen voor tijdelijke referenties.

Ze verlopen en de connector stopt met werken wanneer ze dat doen.

25.4 Bevestiging

Bevestiging configureert het genereren van bevestigingen.

Gedefinieerd als Ack in internal/config.

SleutelTypeVereistStandaard
whenAckWhennee—
applicationtekstnee—
facilitytekstnee—
include_trigger_eventwaar of onwaarnee—

25.4.1 trigger_gebeurtenis_opnemen

TriggerGebeurtenisOpnemen verstuurt ACK^A01 in plaats van ACK.

Sommige ontvangers vereisen het en anderen wijzen het af, dus het is expliciet.

25.5 Azure Blob-toegang

AzureBlobToegang is het account, de container en de referentie.

Gedefinieerd als AzureBlobAccess in internal/config.

SleutelTypeVereistStandaard
accounttekstja—
containertekstja—
keytekstnee—
sastekstnee—
endpointtekstnee—

25.5.1 sleutel

Sleutel is de account-sleutel, of ${AZURE_OPslag_SLEUTEL}.

Stel het in of sas.

25.5.2 sas

SAS is een gedeelde toegangssignatuurqueryreeks, of een ${...}-verwijzing.

Voorkeur: het kan worden beperkt tot deze container.

25.6 Contractverwijzing

ContractRef wijst een kanaal naar zijn contract.

Gedefinieerd als ContractRef in internal/config.

SleutelTypeVereistStandaard
filetekstja—
check_everytekstnee15 minuten
overgeheel getalnee500

25.6.1 controleer_om_de

CheckEvery is hoe vaak opnieuw te controleren, als een duur.

Standaard 15 minuten.

Effectief gelimiteerd tot het interval van de waarschuwingsbeoordeling, dat standaard 30 seconden is, omdat de controle wordt uitgevoerd vanuit die lus in plaats van een eigen timer - dus een contract dat om 3 seconden vraagt, krijgt 30 seconden. Dat is opzettelijk: één timer is gemakkelijker te begrijpen dan twee, en het houdt een contractresultaat in fase met de bijbehorende lezing. Het is de moeite waard om te weten voordat iemand een korte interval instelt en concludeert dat het defect is.

Niet per bericht. Het opbouwen van een profiel betekent het lezen van recente verkeer, en dat doen bij elk bericht zou de doorvoer van een kanaal afhankelijk maken van hoeveel geschiedenis het heeft - wat het soort prestatiekarakteristiek is dat alleen in productie zichtbaar wordt, zes maanden later.

25.6.2 boven

Boven is hoeveel recente berichten te profileren.

Defaults to 500.

Een telling in plaats van een tijdsvenster, omdat een rustige feed en een drukke feed dezelfde hoeveelheid bewijs nodig hebben om een tarief te rechtvaardigen, en een tijdsvenster geeft hen enorm verschillende hoeveelheden.

25.7 DICOM-opties

DICOMOptions configureert een beeldvormingskanaal.

Waarom de stappen zijn genoemd in plaats van paden

Elk ander formaat krijgt een padschrijver. DICOM krijgt dat opzettelijk niet, en de reden is de pixeldatum: een object is binaire gegevens, een algemene tag-schrijver kan elke tag instellen op elke bytes, en een fout daar produceert geen geweigerd bericht - het produceert een afbeelding die opent en verkeerd is. Een radioloog die een onderzoek leest, heeft geen manier om het te weten.

Dus de vier dingen die sites daadwerkelijk nodig hebben, zijn genoemde acties met begrensde effecten: anoniem maken, een AE-titel herschrijven, privé-tags verwijderen, de instelling instellen. Elk weet welke tags het aanraakt, en geen enkele kan de pixeldatum bereiken.

Waarom deze blok bestaat nu

internal/dicom heeft steps.go en transform.go gedragen voor een tijdje - de vier acties, dicom.Apply, en tests. Niets verwijst ernaar. Vijfhonderd regels zonder aanroeper, die de wachtrij zelf in sectie 7 noemt: een implementatie zonder aanroeper is niet te onderscheiden van een functie die niet bestaat. Deze blok en de motoraanroep zijn de bedrading, niet de functie.

Gedefinieerd als DICOMOptions in internal/config.

SleutelTypeVereistStandaard
transformationslijst van dicom.Stepnee—

25.8 Directe adres

DirectAddress is een Direct-adres dat deze server bevat: zijn certificaat en sleutel, en de ankers die het vertrouwt.

Dezelfde blok wordt gebruikt om te verzenden (ondertekenen als dit adres) en om te ontvangen (decrypteren voor het).

Gedefinieerd als DirectAddress in internal/config.

SleutelTypeVereistStandaard
addresstekstja—
cert_filetekstja—
key_filetekstja—
anchors_filetekstja—

25.8.1 cert_file

CertFile en KeyFile zijn het adres van het certificaat (PEM, met de keten ervoor) en de private sleutel (PEM).

De HISP of de registratieautoriteit verstrekt deze; ze zijn de identiteit van het adres.

25.8.2 sleutelbestand

CertFile en KeyFile zijn het adres van het certificaat (PEM, met de keten ervoor) en de private sleutel (PEM).

De HISP of de registratieautoriteit verstrekt deze; ze zijn de identiteit van het adres.

25.8.3 anchors_file

AnchorsFile zijn de vertrouwensankers (PEM): de certificeringsautoriteiten waarvan deze adressen de afzenders en ontvangers vertrouwt, zoals de DirectTrust-bundel.

Een bericht dat is ondertekend met iets anders wordt geweigerd.

25.9 Direct IMAP

DirectIMAP is de HISP-postbus die een Direct-bron leest.

Gedefinieerd als DirectIMAP in internal/config.

KeyTypeRequiredDefault
hosttextyes—
portwhole numberno—
securitytextno—
usernametextyes—
passwordtextno—
mailboxtextno—
after_readtextno—
move_totextno—
error_foldertextno—
poll_intervalduration, such as 30s or 5mno—
tlstlsconf.Settings (a block, omit to leave off)no—

25.9.1 move_to

VerplaatsNaar is de map waarin berichten worden verplaatst; Standaard is Verwerkt.

Wordt aangemaakt als deze ontbreekt.

25.9.2 tls

TLS vertrouwt een CA-bestand (of het eigen certificaat van de HISP) en noemt de server die verwacht wordt, voor een HISP wiens IMAP-certificaat niet afkomstig is van een openbare autoriteit.

Het certificaat wordt altijd geverifieerd.

25.10 Direct XDR

DirectXDR is het eindpunt waar een Direct-bron XDR ontvangt.

Gedefinieerd als DirectXDR in internal/config.

SleutelTypeVereistStandaard
listentekstja—
tls_certtekstnee—
tls_keytekstnee—
client_ca_filetekstnee—

25.11 ECR Faciliteit

ECRFaciliteit is de organisatie die casusrapporten verstuurt.

Gedefinieerd als ECRFacility in internal/config.

SleutelTypeVereistStandaard
nametekstja—
npitekstnee—
phonetekstja—
linetekstnee—
citytekstja—
statetekstja—
postal_codetekstnee—

25.12 EDIFACT Opties

EDIFACTOpties zijn de instellingen die alleen van toepassing zijn op een EDIFACT-kanaal.

Gedefinieerd als EDIFACTOptions in internal/config.

SleutelTypeVereistStandaard
envelopetekstnee—
splitwaar of onwaarnee—
acknowledgetekstnee—

25.12.1 bevestigen

Acknowledge beantwoordt een afzender die via HTTP publiceert met een CONTRL in het antwoord: geaccepteerd (actie 7) wanneer de interchange werd gelezen en afgeleverd, geweigerd (4) anders.

Default none.

25.13 E-mail O Auth

EmailOAuth meldt zich aan met OAuth 2.0 (SASL XOAUTH2), wat door Microsoft 365 en Gmail wordt vereist in plaats van een wachtwoord.

Gedefinieerd als EmailOAuth in internal/config.

SleutelTypeVereistStandaard
providertekstja—
tenanttekstnee—
token_urltekstnee—
client_idtekstja—
client_secrettekstnee—
refresh_tokentekstnee—
scopetekstnee—

25.13.1 client_secret

ClientSecret kan ${ENV} zijn.

Zonder refresh_token selecteert het Microsoft's app-only client-credentials grant.

25.13.2 refresh_token

RefreshToken kan ${ENV} zijn: een postbus waarvoor een persoon toestemming heeft gegeven.

Vereist voor Gmail.

25.14 FHIR Auth

FHIRAuth is de manier waarop een FHIR-bestemming zich verifieert bij een gehoste FHIR-service.

Drie voorinstellingen, omdat de gehoste services de plek zijn waar een bearer-token dat in een bestand is geplakt binnen een uur ophoudt te werken:

Tokens worden opgehaald wanneer ze nodig zijn en hergebruikt totdat een minuut voordat ze verlopen.

Gedefinieerd als FHIRAuth in internal/config.

KeyTypeRequiredDefault
typetextyes—
regiontextno—
access_key_idtextno—
secret_access_keytextno—
session_tokentextno—
tenant_idtextno—
token_urltextno—
client_idtextno—
client_secrettextno—
scopetextno—

25.14.1 regio

Regio is de AWS-regio.

Wordt gelezen uit een HealthLake-URL wanneer deze niet is gegeven.

25.14.2 token_url

TokenURL is het OAuth-token eindpunt, voor client_credentials.

Voor azure wordt het afgeleid van de tenant.

25.14.3 client_id

ClientID en ClientSecret identificeren de toepassing.

Het geheim kan een ${ENV}-verwijzing zijn, wat de manier is waarop het moet worden gegeven.

25.14.4 client_secret

ClientID en ClientSecret identificeren de toepassing.

Het geheim kan een ${ENV}-verwijzing zijn, wat de manier is waarop het moet worden gegeven.

25.14.5 bereik

Bereik wordt aangevraagd met het token.

Voor azure staat het standaard op de FHIR-service-URL gevolgd door /.default, wat het publiek is.

25.15 Bestand Poll

FilePoll is het deel van een bestand-verzamelende bron dat niets te maken heeft met het transport.

Gedeeld door de lokale, FTP, SMB en WebDAV-bronnen, en door SFTP. Elk van deze instellingen bestaat omdat bestanden op een bepaalde manier misgaan in plaats van dat transports verschillen, wat de reden is waarom ze bij elkaar horen: een site die de juiste stable_for voor zijn analyser heeft uitgewerkt, moet deze niet opnieuw uitwerken wanneer de analyser naar een share verhuist.

Gedefinieerd als FilePoll in internal/config.

SleutelTypeVereistStandaard
dirtekstja—
patterntekstnee—
poll_intervalduur, zoals 30s of 5mnee—
after_readtekstnee—
move_totekstnee—
error_dirtekstnee—
stable_forduur, zoals 30s of 5mnee—
max_file_sizegeheel getalnee—
framedwaar of onwaarnee—
rawwaar of onwaarnee—
batch_sizegeheel getalnee—
sort_bytekstneenaam

25.15.1 patroon

Patroon selecteert bestanden met glob.

Leeg betekent elk bestand.

25.15.2 foutenmap

ErrorDir is de locatie waar een bestand dat niet verwerkt kon worden, naartoe gaat.

Los van MoveTo, met opzet. Een directory die alleen maar mislukkingen bevat, kan iemand in de gaten houden en het mengen van mislukkingen in het archief betekent dat de enige manier om ze te vinden is door elk bestand te lezen.

25.15.3 ruw

Raw behandelt het hele bestand als één bericht, ongeacht de inhoud.

De instelling die deze connector nuttig maakt voor iets anders dan HL7. Zonder deze instelling wordt een CSV-batch, een X12-claimbestand of een PDF gesplitst op regels die beginnen met MSH en produceert niets, en de foutmelding zegt dat het bestand geen HL7 is - waar, maar niet het punt, aangezien het bestand nooit bedoeld was om HL7 te zijn.

25.15.4 batch_size

BatchSize beperkt het aantal bestanden dat in één poll wordt gelezen.

Nul betekent geen limiet.

Bestaat voor de eerste poll na een storing. Een directory met veertigduizend bestanden die 's nachts zijn opgehoopt, wordt anders in één keer gelezen, wat de poll-lus vasthoudt voor zo lang als het duurt en de kanaal doen lijken alsof deze vastloopt. Het lezen van een beperkt aantal bestanden per poll houdt de kanaal responsief en de wachtrij zichtbaar leeg.

25.15.5 sorteer_op

SortBy sorteert de bestanden binnen een poll: naam, gewijzigd of geen.

Standaard is naam. De volgorde is belangrijker dan het lijkt: een ADT-stroom waarin A08-updates eerder aankomen dan de A01-opname, produceert patiënten die nog niet bestaan. De directorylijstvolgorde is willekeurig op de meeste bestandssystemen, dus het niet sorteren betekent dat de volgorde tussen polls verandert zonder zichtbare reden.

25.16 GCP-toegang

GCPAccess is de manier waarop u zich verifieert bij Google Cloud.

Gedefinieerd als GCPAccess in internal/config.

SleutelTypeVereistStandaard
projecttekstnee—
credentials_filetekstnee—
endpointtekstnee—

25.16.1 credentials_file

CredentialsFile is een JSON-sleutel van een serviceaccount.

Leeg gebruikt het serviceaccount dat is gekoppeld aan de VM, GKE-pod of Cloud Run-service waarop Perfuse wordt uitgevoerd (de metadataserver), tenzij Endpoint een emulator noemt.

25.17 GCS-toegang

GCSAccess is een Cloud Storage-bucket.

Gedefinieerd als GCSAccess in internal/config.

SleutelTypeVereistStandaard
buckettekstja—

25.18 IBMMQ-verbinding

IBMMQConnection is een wachtrij die wordt bereikt via de messaging REST API van de wachtrijbeheerder.

Gedefinieerd als IBMMQConnection in internal/config.

KeyTypeRequiredDefault
urltextyes—
queue_managertextyes—
queuetextyes—
usernametextno—
passwordtextno—
tlstlsconf.Settings (a block, omit to leave off)no—
api_versiontextno—
timeoutduration, such as 30s or 5mno30s

25.18.1 gebruikersnaam

Gebruikersnaam en wachtwoord zijn een mqweb-gebruiker met de rol MQWebUser; het wachtwoord kan ${ENV} zijn.

Laat beide leeg wanneer een clientcertificaat (tls.cert_file) authenticatie uitvoert.

25.18.2 wachtwoord

Gebruikersnaam en wachtwoord zijn een mqweb-gebruiker met de rol MQWebUser; het wachtwoord kan ${ENV} zijn.

Laat beide leeg wanneer een clientcertificaat (tls.cert_file) authenticatie uitvoert.

25.18.3 time-out

Time-out begrenst elke aanvraag.

Defaults to 30s.

25.19 Kafka SASL

KafkaSASL authenticatie voor een Kafka-cluster.

Gedefinieerd als KafkaSASL in internal/config.

KeyTypeRequiredDefault
mechanismtextyes—
usernametextyes—
passwordtextyes—

25.19.1 mechanisme

Mechanisme is "plain", "scram-sha-256" of "scram-sha-512".

PLAIN verzendt het wachtwoord leesbaar op de draad, dus het hoort bij TLS. SCRAM doet dit niet, waardoor het de moeite waard is om het verschil te noemen in plaats van de drie als uitwisselbaar te behandelen.

25.19.2 wachtwoord

Wachtwoord is het SASL-wachtwoord.

Ondersteunt ${ENV}-verwijzingen zoals elk ander geheim hier, dus een clusterreferentie hoeft niet in het kanaalbestand te worden geschreven.

25.20 MQTT-verbinding

MQTTConnection is de manier om een MQTT 3.1.1-broker te bereiken: Mosquitto, EMQX, HiveMQ, AWS IoT Core, Azure Event Grid.

Gedefinieerd als MQTTConnection in internal/config.

KeyTypeRequiredDefault
addrtextyes—
client_idtextno—
usernametextno—
passwordtextno—
tlstlsconf.Settings (a block, omit to leave off)no—
qoswhole number (a block, omit to leave off)no—
timeoutduration, such as 30s or 5mno30s

25.20.1 client_id

ClientID noemt de sessie.

Een bron houdt zijn berichten bij reconnects alleen vast onder een vaste client-id; deze heeft standaard de waarde perfuse-<channel>.

25.20.2 gebruikersnaam

Gebruikersnaam en wachtwoord authenticeren; een van beide kan leeg zijn.

Het wachtwoord kan ${ENV} zijn.

25.20.3 wachtwoord

Gebruikersnaam en wachtwoord authenticeren; een van beide kan leeg zijn.

Het wachtwoord kan ${ENV} zijn.

25.20.4 time-out

Time-out grenzen voor het verbinden en elk wachten op de broker.

Defaults to 30s.

25.21 NCPDP-opties

NCPDPOpties zijn de instellingen die alleen van toepassing zijn op eenapotheekclaimkanaal.

Gedefinieerd als NCPDPOptions in internal/config.

SleutelTypeVereistStandaard
transformationslijst van ncpdp.Stepnee—

25.21.1 transformaties

Transformaties zijn declaratieve wijzigingen die op elke transmissie worden toegepast voordat deze wordt afgeleverd.

Hetzelfde vocabulaire als elk ander formaat - set, copy, clear, map, replace, trim, case, elk met een optionele voorwaarde - omdat de stap-engine in internal/steps generisch is. Wat verschilt is de notatie: een pad wordt geschreven als D1 of 07-D7, met behulp van de standaard-eigen twee-teken-veld-identificatoren.

25.22 PGP Ontvangen

PGPReceive opent wat een bron ontvangt met OpenPGP: ontsleuteld met onze geheime sleutel en de handtekening wordt gecontroleerd tegen de openbare sleutels van de verzenders.

Gedefinieerd als PGPReceive in internal/config.

SleutelTypeVereistStandaard
decrypt_withtekstnee—
passphrasetekstnee—
verify_withlijst van tekstnee—
require_signaturetrue of falsenee—
allow_unencryptedtrue of falsenee—
pass_plaintrue of falsenee—

25.22.1 decrypt_with

DecryptWith is ons geheime sleutelbestand.

Vereist, tenzij allow_unencrypted aan staat en berichten alleen worden ondertekend.

25.22.2 passphrase

Passphrase ontgrendelt DecryptWith wanneer deze beschermd is.

Voorkeur voor een verwijzing naar een omgevingsvariabele, ${NAME}.

25.22.3 verify_with

VerifyWith zijn de openbare sleutelbestanden van de verzenders.

Een handtekening van een van hen wordt gecontroleerd en opgenomen.

25.22.4 pass_plain

PassPlain laat een bericht dat helemaal geen PGP is ongewijzigd door, voor een map die zowel ondertekende als niet-ondertekende berichten ontvangt.

Uit: een dergelijk bericht wordt geweigerd, zodat een verzender die vergeten is om te versleutelen wordt geïnformeerd.

25.23 PGP Verzenden

PGPSend beschermt wat een bestemming aflevert met OpenPGP: versleuteld naar de openbare sleutel van de ontvanger, ondertekend met de onze, of beide.

Verzekeraars, clearinghouses en overheidsinstanties nemen vaak bestanden over via SFTP alleen op deze manier.

Gedefinieerd als PGPSend in internal/config.

SleutelTypeVereistStandaard
encrypt_tolijst van tekstnee—
sign_withtekstnee—
passphrasetekstnee—
armortrue of falsenee—
no_compresstrue of falsenee—
file_nametekstnee—

25.23.1 encrypt_to

EncryptTo zijn de openbare sleutelbestanden van de ontvangers (armored of binaire bestanden).

Het bericht kan door een van hen worden gelezen. Leeg: het bericht is alleen ondertekend.

25.23.2 sign_with

SignWith is ons geheime sleutelbestand om elk bericht te ondertekenen.

Leeg: alleen versleuteld.

25.23.3 passphrase

Wachtwoord ontgrendelt SignWith wanneer het beschermd is.

Voorkeur voor een verwijzing naar een omgevingsvariabele, ${NAME}.

25.24 Wachtrijconfiguratie

Wachtrijconfiguratie activeert duurzame wachtrijen voor een bestemming.

Zonder dit, verliest een bestemming die twee minuten uitgeschakeld is alle berichten die tijdens die twee minuten zijn verzonden: nieuwe pogingen vinden plaats in het geheugen en wanneer deze op zijn, wordt het bericht geregistreerd als mislukt en verdwenen. Met dit, staat het bericht op schijf en behoudt het zijn positie totdat de ontvanger terugkeert.

Het is standaard uitgeschakeld, wat een bewuste keuze is in plaats van voorzichtigheid. Een wachtrij verandert wat een bevestiging betekent en verandert de volgorde van gedrag tijdens een storing, en beide dingen moet een operator bewust kiezen in plaats van ontdekken.

Gedefinieerd als QueueConfig in internal/config.

SleutelTypeVereistStandaard
enabledtrue of falsenee—
max_attemptsgeheel getalnee—
backoffduur, zoals 30s of 5mnee—
max_backoffduur, zoals 30s of 5mnee—
max_depthgeheel getalnee—
retain_hoursgeheel getalnee—

25.24.1 max_attempts

MaxAttempts is het aantal keren dat de wachtrij probeert voordat een bericht als mislukt wordt gemarkeerd en doorgaat met het volgende bericht.

Nul betekent dat het oneindig blijft proberen, wat legitiem is voor een feed die niets mag verliezen, maar moet worden gekozen in plaats van geërfd.

25.24.2 max_backoff

MaxBackoff beperkt de groeiende vertraging.

De standaardwaarde is één minuut in plaats van iets groter, omdat een ontvanger die terugkeert na een korte storing snel moet worden gevonden: een plafond van een uur verandert een storing van twee minuten in een uur aan achterstand.

25.24.3 max_depth

MaxDepth weigert nieuwe berichten zodra dit aantal in de wachtrij staat, zodat een ontvanger die een week uitgeschakeld is geweest de schijf niet kan vullen.

Nul betekent geen limiet.

Wanneer het limiet wordt bereikt, wordt het bericht als mislukt gemarkeerd in plaats van in de wachtrij geplaatst, en de afzender wordt hiervan op de hoogte gesteld — wat het eerlijke antwoord is, omdat we niet langer beloven het te leveren.

25.24.4 retain_hours

RetainHours is de tijd dat afgeleverde en verlaten items worden bewaard voordat ze worden verwijderd.

Ze worden bewaard zodat iemand die naar een achterstand kijkt, kan zien dat deze afneemt, en zodat een verlaten bericht later kan worden gevonden.

25.25 Opnieuw proberen

Opnieuw proberen controleert de herlevering na een fout.

Gedefinieerd als Retry in internal/config.

SleutelTypeVereistStandaard
attemptsgeheel getalnee—
backoffduur, zoals 30s of 5mnee—
max_backoffduur, zoals 30s of 5mnee—

25.25.1 pogingen

Pogingen is het totale aantal pogingen, inclusief de eerste.

Nul betekent de standaardwaarde.

25.25.2 backoff

Backoff is de wachttijd voordat de tweede poging wordt gedaan.

Het wordt elke keer verdubbeld, tot MaxBackoff.

25.26 Scriptopties

ScriptOptions configureert een NCPDP SCRIPT-kanaal.

Waarom SCRIPT een blok krijgt wanneer zijn filter top-level is

Het kanaalfilter voor elk gegevenstype is het top-level filter-sleutel, omdat internal/expr generiek is over het berichttype: één sleutel, gecompileerd tegen welke boom of claim het kanaal ook draagt. Stappen kunnen niet op die manier worden gerangschikt. Een v2-stap adresseert een segment en een veld, een X12-stap adresseert een vast breed element, en de typen zijn verschillend, dus één yaml-sleutel zou welk dan ook het gegevenstype impliceert - wat een veld is dat verschillende dingen betekent afhankelijk van een ander veld, en de foutmodus is een stap die stilzwijgend niets doet.

Dus dit volgt hl7v3, x12, ncpdp en delimited: de stappen leven in het formaatblok en de top-level transformatiesleutel wordt geweigerd op een SCRIPT-kanaal in plaats van geaccepteerd en genegeerd.

Gedefinieerd als ScriptOptions in internal/config.

SleutelTypeVereistStandaard
transformationslijst van hl7v3.Stepnee—

25.26.1 transformaties

Transformaties zijn de declaratieve stappen, die het recept als een XML-boom adresseren.

hl7v3.Step in plaats van een type op zich, en dat is geen luiheid. Een recept en een v3-document zijn beide XML, de padensyntax is dezelfde, en internal/eprescribe leent al hl7v3.Path voor zijn filter met een commentaar dat zegt - v3 en CDA gebruiken het al, en een derde kopie zou een derde set antwoorden zijn op wat //a/b[2]@c betekent.

De stappen die alleen v3-betekenis dragen, worden geweigerd bij het laden in plaats van stilzwijgend beschikbaar te zijn. nullflavor is de enige: het schrijft het v3-attribuut dat aangeeft waarom een waarde ontbreekt, wat een recept geen equivalent van heeft, en een stap die het schrijft, zou een document produceren dat de ontvanger niet begrijpt.

25.27 Scripts

Scripts bevat de JavaScript die aan een kanaal is gekoppeld.

Gedefinieerd als Scripts in internal/config.

SleutelTypeVereistStandaard
filtertekstnee—
transformertekstnee—
preprocessortekstnee—
deploytekstnee—
undeploytekstnee—
postprocessortekstnee—
languagetekstnee—
timeoutduur, zoals 30s of 5mnee—
includelijst van tekstnee—
file_rootslijst van tekstnee—
allowlijst van tekstnee—

25.27.1 filter

Filter wordt uitgevoerd na het expressiefilter, indien aanwezig, en moet een boolean retourneren.

Een Mirth-filter-script past hier ongewijzigd in.

25.27.2 transformer

Transformer wordt uitgevoerd na de declaratieve stappen en kan het bericht wijzigen.

Een Mirth-transformatiescript past hier ongewijzigd in.

25.27.3 preprocessor

De preprocessor wordt uitgevoerd voordat het bericht wordt geparsed, leest de tekst als 'bericht' en retourneert de tekst om te parseren.

Een Mirth-preprocessor past hier ongewijzigd in.

Dit is de enige plaats waar een bericht dat niet kan worden geparsed, kan worden hersteld. Sites gebruiken het voor een losse karakter uit een seriële gateway, een segment terminator die als een regelafbreking is aangekomen, of een leverancier die een veld met iets onwettigs voor zijn positie vult. Zonder het, wijst Perfuse verkeer af dat Mirth vandaag accepteert.

25.27.4 implementeren

Implementeren wordt één keer uitgevoerd wanneer het kanaal start, voordat het iets accepteert.

Dit is de plaats waar sites een lookup-cache warm maken of controleren of iets waarvan ze afhankelijk zijn, bereikbaar is. Het wordt uitgevoerd voordat de bron wordt gebonden, dus een implementatiescript dat faalt, voorkomt dat het kanaal start in plaats van dat het berichten accepteert die het niet kan verwerken.

25.27.5 ontimplementeren

Ontimplementeren wordt één keer uitgevoerd wanneer het kanaal stopt.

Nadat de bron is gestopt met accepteren en nadat in-flight berichten zijn voltooid, zodat het een kanaal ziet dat echt inactief is. De fout kan de stop niet tegenhouden: een kanaal dat niet kan worden gesloten omdat een schoonmaakscript een uitzondering gooide, zou erger zijn dan een dat logt en sluit.

25.27.6 postprocessor

De postprocessor wordt uitgevoerd nadat het bericht is verwerkt en kan het niet meer wijzigen.

Het bericht en wat er mee is gebeurd, zijn zichtbaar, dus het kan notificeren, tellen of opnemen. Het kan niet veranderen wat is verstuurd: op het moment dat het wordt uitgevoerd, is het verzenden al gebeurd, en een script dat lijkt het bericht te wijzigen, zou liegen over wat er is gebeurd.

25.27.7 taal

Taal is de scripttaal waarin deze scripts zijn geschreven: javascript of lua.

Waarom één instelling voor het hele blok in plaats van één per script

Een kanaal scripts delen het kanaalkaart en de connector kaart, en ze worden samen gelezen door degene die ze onderhoudt. Een filter in Lua naast een transformatie in JavaScript zou twee talen in één review betekenen, die staat delen via een kaart waarvan de waarden hetzelfde moeten betekenen in beide. Sites die dat willen, kunnen het kanaal splitsen.

Waarom de standaard javascript is

Elk script dat voor deze instelling is geschreven, is JavaScript en zegt niets over zijn taal. Het maken van lua de standaard zou alle scripts stilzwijgend opnieuw interpreteren; het vereisen van het veld zou ze weigeren. Geen van beide is acceptabel voor een instelling die later is toegevoegd.

25.27.8 time-out

Time-out begrenst elk script.

Nul betekent vijf seconden.

Er is opzettelijk geen manier om het uit te schakelen. Mirth laat een transformatie toe om oneindig te lussen, wat het kanaal tegenhoudt, en een interface die stopt met het accepteren van opnames vanwege een typefout, is niets dat als optie moet worden aangeboden.

25.27.9 inclusief

Inclusief noemt bestanden met gedeelde scriptbron die beschikbaar worden gesteld voor elk script op dit kanaal, in welke taal scripts.taal ook noemt.

Dit is Mirth's code-sjablonen. Een site met veertig kanalen heeft meestal één bibliotheek die elk kanaal aanroept, en zonder het, betekent een migratie dat de bibliotheek in veertig bestanden moet worden gekopieerd - veertig plaatsen om de volgende keer dat het verandert te repareren.

Paden zijn relatief ten opzichte van het kanaalbestand, dus een bibliotheek naast de kanalen reist met hen mee. Het is een lijst omdat het alternatief één enorm bestand is, en bibliotheken hebben de neiging om te worden onderverdeeld in onderwerpen.

De bestanden moeten in de taal van het kanaal zijn. Dit was voorheen alleen JavaScript, en niet vanwege een weigering: een Lua-kanaal las de bestanden, weigerde een ontbrekend bestand en vervolgens installeerde de runtime geen van allen, zodat elke oproep naar de bibliotheek faalde bij het eerste bericht met een nil-globale variabele - de exacte fout die de weigering hierboven bestaat om te voorkomen. Beide talen installeren het nu, en een bibliotheek die niet parseert, wordt geweigerd bij het laden met de naam van het bestand.

25.27.10 file_roots

FileRoots zijn de directories die FileUtil mag lezen en schrijven.

Vereist wanneer "file" is toegestaan. Het verlenen van toegang tot bestanden zonder de gebruikte directories te noemen, betekende vroeger dat het hele bestandssysteem kon worden gelezen: een script kon Perfuse's eigen database lezen, die wachtwoordhashes, het LDAP-serviceaccountwachtwoord en het OIDC-clientgeheim bevat. Het maken van een kanaal vereist alleen de editorrol, dus de escalatie was voltooid op het moment dat een beheerder het startte.

25.27.11 allow

Allow verleent capaciteiten die een script anders zouden worden geweigerd: "file", "database", "route".

Mirth verleent al deze rechten aan elk script; het vereisen dat ze worden genoemd, betekent dat een transformatie niet stilzwijgend de filesystem kan beginnen lezen na een kopieer- en plakactie.

25.28 Schaduw

Shadow voert een kandidaatversie van een kanaal uit naast de live-versie en rapporteert waar ze verschillen.

Dit is het antwoord op de vraag die interface-werk eng maakt: hoe weet je of een wijziging veilig is? Niet door het te lezen. Een transformatie is een programma dat werkt op berichten waarvan niemand de variëteit heeft gecatalogiseerd, en het geval dat breekt, is altijd het geval dat niemand had bedacht - de patiënt met twee identificatoren, het resultaat met een lege eenheden-veld, de A08 die arriveert voordat zijn A01.

Een kanaaltest bewijst de gevallen die iemand had bedacht. Shadow-modus bewijst de gevallen die daadwerkelijk arriveren, tegen echte verkeer, voordat de wijziging enige invloed heeft.

Twee eigenschappen maken het veilig, en beide zijn structureel in plaats van configureerbaar:

Gedefinieerd als Shadow in internal/config.

SleutelTypeVereistStandaard
channeltekstja—
samplenummernee1
comparelijst van tekstnee—
ignorelijst van tekstnee—
max_differencesgeheel getalnee100
timeoutduur, zoals 30s of 5mnee5s

25.28.1 kanaal

Kanaal is het pad naar het kandidaat-kanaalbestand.

Een apart bestand in plaats van een inline-blok, met opzet: de kandidaat moet de live-kanaal worden, dus het moet het artefact zijn dat wordt beoordeeld, ingediend en gepromoveerd, en niet een fragment dat moet worden geëxtraheerd.

25.28.2 monster

Monster is de fractie van berichten die moet worden geschaduwd, van 0 tot 1. Standaard is 1.

Alleen de moeite waard om te verlagen op een drukke feed, en het is de moeite waard om te begrijpen voordat je het doet: sampling vermindert de kosten en vermindert het vertrouwen in exact dezelfde verhouding, en het bericht dat het verschil had kunnen laten zien, is het ongebruikelijke bericht.

25.28.3 vergelijk

Vergelijk beperkt de vergelijking tot deze veldpaden.

Lege vergelijkingen vergelijken alles.

25.28.4 negeer

Negeer uitsluitingsveldpaden van de vergelijking.

Nodig in de praktijk, omdat een kanaal dat een tijdstempel of een volgnummer stempelt, op elk bericht verschilt en een verschilpercentage van 100% zou rapporteren, zonder iets te vertellen.

25.28.5 max_verschillen

MaxVergelijkingen beperkt het aantal verschillende berichten dat voor inspectie wordt bewaard.

Defaults to 100.

25.28.6 time-out

Time-out beperkt één schaduwrun.

Defaults to 5s.

Los van de time-out van het kanaal zelf en korter. Een kandidaat met een weggelopen script mag geen goroutines achter de live-verkeer accumuleren.

25.29 XDS-code

XDSCode is een gecodeerde waarde in bestemmingsinstellingen: code, codingschema (een OID) en weergave.

Gedefinieerd als XDSCode in internal/config.

SleutelTypeVereistStandaard
codetekstja—
schemetekstja—
displaytekstnee—

26 Hoe elk onderdeel werkt

Perfuse is opgebouwd uit kleine pakketten, elk met één taak. Dit hoofdstuk is elk onderdeel zijn eigen verhaal over wat het doet en waarom het zo is gebouwd, rechtstreeks uit de bron. Waar een beslissing een reden heeft die niet voor de hand ligt, staat de reden hier in plaats van in een commitbericht dat niemand zal vinden.

26.1 fhir

Pakket fhir implementeert FHIR-bronnen, serialisatie en validatie.

Versiebeheer is de eerste ontwerpbeslissing, omdat "FHIR" op zichzelf geen draadformaat identificeert. R5 is de laatste gepubliceerde release en is hier de standaard. R4 is wat de geïnstalleerde basis en de Amerikaanse regelgeving daadwerkelijk consumeren, dus wordt het volledig ondersteund in plaats van als verouderd behandeld. R6 is op het moment van schrijven in stemming en wordt opzettelijk niet geïmplementeerd: het verzenden van een gok naar een niet-gepubliceerde specificatie zou erger zijn dan het niet ondersteunen.

Het resource-model is R5-gevormd. Waar R4 verschilt, wordt het verschil toegepast bij het serialiseren in plaats van door twee parallelle sets van structs te behouden, wat de manier is waarop een codebase uiteindelijk twee subtiel afwijkende definities van Patient krijgt.

Source: github.com/biodream-llc/perfuse/fhir

26.2 hoofd

Het commando xmlordergen schrijft de elementvolgorde voor FHIR XML, vanuit een core-pakket's StructureDefinitions.

go run ./fhir/xmlordergen hl7.fhir.r4.core-4.0.1.tgz | gzip -9 -n > fhir/xmlorder_r4.txt.gz

JSON-objecten kunnen hun leden in elke volgorde hebben; XML niet: elk element moet in de volgorde komen zoals gedefinieerd. Elke uitvoerregel is een pad en zijn kinderen in die volgorde, elk kind met hoe het zijn eigen kinderen kan vinden: "@Path" (een element gedefinieerd inline, een backbone), "#Path" (hetzelfde als een ander element), of zijn typen.

Source: github.com/biodream-llc/perfuse/fhir/xmlordergen

26.3 hl7

Pakket hl7 leest HL7-versie 2-berichten.

Het heeft geen afhankelijkheden buiten de standaardbibliotheek en een test dwingt dat af. Het doet geen netwerk-I/O, schrijft geen bestanden en start geen goroutines, dus het is veilig om overal te gebruiken.

Reading a message

msg, err := hl7.Parse(raw) if err != nil { return err } mrn := msg.MustGet("PID-3.1") naam := msg.MustGet("PID-5.1") msgType, event, _ := msg.Type() // "ADT", "A01"

Paden zijn de notatie die mensen al gebruiken wanneer ze over HL7 praten: segment, veld, dan optioneel onderdeel en subonderdeel, zoals PID-5.1 of OBX-5.2.3. Herhalingen worden aangesproken met vierkante haken, zoals PID-3[2].1.

Get retourneert een fout voor een pad dat het niet kan parseren; MustGet retourneert in plaats daarvan de lege string. Beide zijn veilig voor ontbrekende segmenten en velden, omdat een echte feed vol zit met beide en een parser die paniceert op ontbrekende gegevens nutteloos is voor de taak. Afwezigheid is geen fout — een bericht dat eenvoudigweg geen PID-8 bevat, resulteert in "" in plaats van een fout.

Afwezig en leeg

HL7 onderscheidt een veld dat niet is verzonden van een veld dat opzettelijk leeg is verzonden, en klinisch kunnen die dingen verschillende dingen betekenen - "geen allergieën geregistreerd" is niet "geen bekende allergieën". Value.Exists rapporteert het verschil waar aanroepers het nodig hebben, terwijl String beide platdrukt naar "" voor het gebruikelijke geval.

Kopiëren en de enige manier om dit verkeerd te doen

Parse kopieert zijn invoer, dus het geretourneerde Bericht blijft geldig, ongeacht hoe de aanroeper zijn buffer opnieuw gebruikt. Dat kost ongeveer 3% en één toewijzing per bericht.

WithZeroCopy slaat de kopie over en houdt een verwijzing naar de slice van de aanroeper in plaats daarvan. Het is sneller, en het maakt het Bericht onveilig om te gebruiken nadat de slice opnieuw is geschreven. Lezen in een opnieuw gebruikt buffer is de normale, efficiënte manier om te lezen van een netwerk in Go, dus de valkuil vangt zorgvuldige code, en het symptoom is stilzwijgend verkeerde veldwaarden in plaats van een fout - één patiëntgegevens onder een andere patiëntennaam. Gebruik het voor invoer dat onveranderlijk is of langer leeft dan het Bericht, en niet anders.

Acknowledgements

AckFor bouwt een ACK of NAK voor een bericht, inclusief voor een bericht dat niet kon worden geparsed, wat het geval is dat het meest telt: een verzender heeft een antwoord nodig, zelfs als wat hij verzond geen bericht was. Zie AckOptions.

Wat dit pakket niet doet

Het schrijft of wijzigt geen berichten. Het heeft geen notie van berichtstructuur voorbij segmenten, dus het zal niet vertellen dat een PV1 bij een bepaalde bezoekgroep hoort. Het valideert niet tegen een versietabellen. Deze zijn bewuste weglatingen in plaats van omissies: dit is een indexer voor echte verkeer, dat vaak niet conform is aan de standaard en nog steeds moet worden doorgestuurd.

Source: github.com/biodream-llc/perfuse/hl7

26.4 toelaten

Pakket toelaten beperkt hoeveel werk er tegelijk in de lucht is.

De motor start een goroutine per bestemming per bericht. Goroutines zijn goedkoop; wat ze vasthouden is dat niet. Elke uitgaande levering houdt een socket aan de verre kant en een bestanddescriptor hier, en houdt ze vast voor het hele retry-budget - met de standaardinstellingen, vijf pogingen met een time-out van dertig seconden plus vijftien seconden backoff, dus bijna drie minuten. Een paar honderd verzenders tegen één ontvanger die stil is geworden, is dus een paar honderd descriptors die voor minuten worden vastgehouden, en het proces loopt uit.

Uitlopen is de fout die het waard is om te voorkomen, omdat deze niet naar boven komt waar het gebeurde. Het komt naar boven als 'te veel open bestanden' op een ongerelateerde locatie: de database kan zijn journaal niet openen, de interface stopt met accepteren, een log kan niet worden geschreven. De motor lijkt kapot op drie plaatsen tegelijk en de oorzaak is een partnersysteem dat stopte met antwoorden.

Twee limieten, en de tweede telt meer dan de eerste:

Een totaal, zodat het proces binnen zijn descriptorbudget blijft.

Een limiet per bestemming, zodat één ontvanger het totaal niet kan consumeren. Zonder het kan één vastgelopen partner alle andere kanalen naar beneden halen, wat erger is dan helemaal geen limiet hebben: de blaststraal groeit van één interface naar allemaal.

Source: github.com/biodream-llc/perfuse/internal/admit

26.5 waarschuwingen

Pakket waarschuwingen kijkt naar de metrieken en zegt wanneer er iets mis is.

Het punt is dat niemand naar het dashboard hoeft te kijken. 'Mislukte transacties blijven in de wachtrij zonder tijdige onderzoek' is een gedocumenteerde operationele fout in deze klasse van software, en de reden is altijd hetzelfde: de informatie stond op een scherm waar niemand voor stond om vier uur 's ochtends.

Drie beslissingen geven vorm aan het.

Een waarschuwing moet zichzelf wissen. Een melding die afgevuurd wordt en nooit wordt opgelost, leert mensen om meldingen te negeren. Elke regel hier wordt geëvalueerd tegen de huidige staat, dus een ontvanger die terugkomt, sluit de waarschuwing die hij opende.

Waarschuwingen worden gedebounced door duur, niet door telling. 'Foutpercentage boven de 5% op dit moment' wordt afgevuurd op één ongelukkig bericht tijdens een rustig uur. 'Boven de 5% voor twee minuten' niet. Elke regel draagt een duur en niets wordt afgevuurd totdat de voorwaarde die duur heeft gehad.

Wat wordt verzonden, bevat geen patiëntgegevens. Een waarschuwing bevat een kanaalnaam, een bestemmingsnaam, een nummer en een drempel. Deze komen uit configuratie en uit telling. Een webhook gaat naar een chatkamer, een chatkamer heeft een scrollback, en een scrollback is geen plek waar een patiëntidentificator terecht zou moeten komen.

Source: github.com/biodream-llc/perfuse/internal/alerts

26.6 amqp

Pakket amqp is een AMQP 1.0-client: één verbinding, één sessie, verzenden en ontvangen links, afgehandeld nadat de ontvanger heeft gezegd.

AMQP 1.0 is wat Azure Service Bus en Event Hubs spreken, wat RabbitMQ 4 native spreekt, en wat ActiveMQ en Artemis spreken naast STOMP. Geschreven hier voor de reden waarom de STOMP-client en de AWS-ondertekenaar zijn: een volledige clientbibliotheek zou het grootste deel van de afhankelijkheidslijst van de binaire code zijn voor vier performatives die ertoe doen.

Wat het doet: SASL PLAIN of ANONYMOUS (Service Bus neemt een gedeelde toegangsnaam en sleutel als PLAIN), TLS, open/begin/attach, credit-based flow, een overdracht gesplitst in frames wanneer het de maximale framesize van de peer overschrijdt, en dispositions - geaccepteerd, vrijgegeven, afgewezen. De verzender wacht op de disposition van de broker voordat hij succes rapporteert, dus 'verzonden' betekent dat de broker de zorg heeft overgenomen. Lege frames houden de verbinding in leven binnen de idle-timeout van de peer, die Service Bus afdwingt.

Wat het niet doet: transacties, meerdere sessies, linkherstel en berichtannotaties voorbij het lezen ervan.

Source: github.com/biodream-llc/perfuse/internal/amqp

26.7 analyseren

Pakket analyze zet een geparseerde Mirth-kanaal om in iets wat een mens kan gebruiken: een eenvoudige beschrijving van wat het kanaal doet, en een eerlijke lijst van wat niet zal overleven bij een migratie.

De ontwerpregel hier is dat een bevinding specifiek genoeg moet zijn om op te acteren. "Dit kanaal gebruikt JavaScript" is geen bevinding. "Bestemming 1 roept java.util.Date aan, die geen equivalent heeft buiten de JVM" is dat wel.

Source: github.com/biodream-llc/perfuse/internal/analyze

26.8 api

Pakket api dient de HTTP-interface die door de webfrontend wordt gebruikt.

De belangrijke ontwerpeis: kanalen worden gelezen van en geschreven naar bestanden op schijf. De API is een editor voor die bestanden, niet een ander opslagsysteem dat toevallig YAML exporteert. Een kanaal dat in de browser is gemaakt en een dat met de hand is geschreven, zijn hetzelfde artefact, en dat is wat "exporteren om te delen" triviaal maakt en git als de geschiedenis van record houdt.

Source: github.com/biodream-llc/perfuse/internal/api

26.9 as2

Pakket as2 is Applicability Statement 2 (RFC 4130): EDI over HTTP, ondertekend en versleuteld met S/MIME, met een ondertekende ontvangstbevestiging (een MDN) die een digest van de ontvangen gegevens noemt.

Verzekeraars en handelspartners gebruiken het voor X12 en EDIFACT.

De S/MIME is internal/cms, dezelfde code die Direct messaging gebruikt. Wat hier staat is AS2's eigen: de headers, de message integrity check (MIC) en de ontvangstbevestiging.

Source: github.com/biodream-llc/perfuse/internal/as2

26.10 attach

Pakket attach verplaatst grote payloads uit een bericht en plaatst ze terug.

Een HL7-bericht met een gescande rapport of een PDF is gewoon in documentworkflows, en de payload is routinematig honderden keren groter dan het bericht eromheen. Het opslaan van die payload inline betekent dat de berichtenopslag groeit met de snelheid van de documenten in plaats van het verkeer, een bericht dat in de wachtrij staat voor vijf bestemmingen, wordt vijf keer gekopieerd, en de interface moet megabytes streamen om iemand een patiëntennaam te laten zien.

Dus wordt de payload geëxtraheerd, één keer opgeslagen op basis van de inhoud, en vervangen in het bericht met een token. Mirth noemt deze attachment handlers en het is een gedocumenteerde migratiefunctie, en dat is waarom het tokenformaat hier is ontworpen om herkenbaar te zijn in plaats van slim.

Wat dit pakket niet beslist

Het doet geen opslag en geen I/O. Extractie produceert het herschreven bericht en de payloads; een Store ergens anders beslist waar die heen gaan. Die scheiding is wat de extractietest maakt zonder een database, en het is ook wat de zelfde logica laat draaien in de WASM-playground waar geen database is.

Source: github.com/biodream-llc/perfuse/internal/attach

26.11 authlimit

Pakket authlimit beperkt mislukte authenticatiepogingen per bronadres.

Het bestaat omdat twee listeners hetzelfde nodig hadden en een van hen niets had. De FHIR-server kreeg een limiter toen het authenticatie kreeg; de console-login had niets, en een meting toonde twintig wachtwoordpogingen per seconde aan tegen het beheerdersaccount zonder vertraging en zonder lockout. Op dat tempo is een zwak wachtwoord over een nacht verdwenen en het enige spoor is een log vol identieke waarschuwingen.

Express niet een algemeen doel rate limiter. Het beperkt mislukkingen, niet verzoeken: een drukke legitieme client wordt nooit beïnvloed, en het enige dat accumuleert is fout zijn.

Source: github.com/biodream-llc/perfuse/internal/authlimit

26.12 awsmsg

Pakket awsmsg communiceert met Amazon SQS en SNS met de standaardbibliotheek en de gedeelde Signature Version 4-ondertekenaar.

Hetzelfde argument als s3put: de AWS SDK zou de grootte van de factuur van materialen verdubbelen voor vier API-aanroepen. SQS gebruikt zijn JSON-protocol (AWS JSON 1.0, X-Amz-Target AmazonSQS.<Action>), dat AWS documenteert als het huidige; SNS gebruikt zijn query-protocol, dat het enige is dat het heeft. Beide werken tegen LocalStack en VPC-eindpunten via een eindpuntoverrijding.

Source: github.com/biodream-llc/perfuse/internal/awsmsg

26.13 awsv4

Pakket awsv4 ondertekent verzoeken naar AWS met Signature Version 4, met behulp van alleen de standaardbibliotheek.

Het begon binnen s3put. SQS, SNS en lezen van S3 hebben dezelfde handtekening nodig met een andere servicenaam en met een queryreeks, en een tweede kopie van de ondertekeningscode zou een tweede plaats zijn voor de ene bug die ertoe doet - een handtekeningmismatch leest exact als verkeerde referenties. Dus leeft het hier, gecontroleerd tegen AWS's gepubliceerde testvectoren, en elke AWS-connector gebruikt het.

Referenties zijn statische sleutels of standaardomgevingsvariabelen. Er is opzettelijk geen instantie-metadata-referentieketen: dit betekent IMDS-aanroepen, caching en vernieuwing, wat het punt is waarop een kleine implementatie ophoudt klein te zijn, en Perfuse weigert metadata-adressen als bestemmingen standaard toch.

Source: github.com/biodream-llc/perfuse/internal/awsv4

26.14 azblob

Pakket azblob leest en schrijft Azure Blob Storage met de standaardbibliotheek: gedeelde sleutel- of SAS-autorisatie via gewone HTTP-aanroepen.

Hetzelfde redeneren als s3put: de Azure SDK is groot en de bewerkingen die een integratie-engine nodig heeft, zijn vijf - plaatsen, ophalen, lijsten, verwijderen en instellen van het toegangsniveau. Gedeelde sleutel-onderhandeling is exact gespecificeerd ("Autoriseren met gedeelde sleutel", Azure Storage REST), en Azurite, Microsoft's emulator, controleert het op dezelfde manier als de service.

Source: github.com/biodream-llc/perfuse/internal/azblob

26.15 merkidentiteit

Pakket branding slaat een klantlogo en productnaam op, zodat een installatie zich kan presenteren als hun eigen product in plaats van als Perfuse.

Waarom het logo geen instelling is

Alles wat een operator kan veranderen, is een scalar in het instellingsbestand. Een logo is enkele honderden kilobytes binaire gegevens, en het daar plaatsen zou betekenen dat het in een YAML-bestand met base64 moet worden geplaatst dat een persoon moet kunnen lezen en handmatig bewerken. Het staat naast dat bestand en alleen de aanwezigheid is zichtbaar via het instellingenoppervlak.

Het deel dat ertoe doet: een geüpload beeld is onbetrouwde invoer

Een logo wordt geüpload door een beheerder en vervolgens aan elke browser die de console laadt, inclusief de aanmeldingspagina voordat iemand is geauthenticeerd. Dat maakt het het meest wijdverspreide stuk aanvaller-geleverde inhoud in het product, dus wordt het dienovereenkomstig behandeld:

Source: github.com/biodream-llc/perfuse/internal/branding

26.16 cda

Pakket cda leest klinische documenten.

Het ontwerp begint met hoe deze documenten daadwerkelijk reizen, wat niet als bestanden is. Een ontslagbrief verlaat een EHR binnen een HL7 v2 MDM^T02-bericht, met het hele document base64-gecodeerd in OBX-5 en beschreven door een TXA-segment. Dat zijn duizenden berichten per dag in een middelgrote ziekenhuis, en dat is waarom dit pakket naast een HL7 v2-parser zit in plaats van in een documenttoolkit: de v2-helft is al hier, dus de pijplijn van "een bericht is aangekomen" tot "een FHIR DocumentReference bestaat" is kort.

Drie dingen zijn opzettelijk in het bereik en één is opzettelijk niet.

In het bereik: een document lezen en zeggen wat het bevat in gewone bewoordingen; controleren of de mensleesbare narratief en de gecodeerde invoer overeenkomen; en converteren naar FHIR. De narratiefcontrole is de ongebruikelijke. Elk C-CDA-sectie bevat dezelfde informatie twee keer, eenmaal als tekst voor een clinician en eenmaal als codes voor een machine, en ze zouden moeten overeenkomen. In de praktijk doen ze dat vaak niet, en niets controleert het - niet de certificeringsinstrumenten, niet de engines. Wanneer de tekst zegt dat een patiënt allergisch is voor penicilline en de gecodeerde invoer iets anders zegt, handelt een van de twee lezers naar de verkeerde informatie. Het is een patiëntveiligheidsdefect dat mechanisch detecteerbaar is, dus wordt het hier gedetecteerd.

Niet in het bereik: genereren van conformant C-CDA. Het schrijven van een C-CDA betekent het voldoen aan verschillende honderden sjabloonregels en een Schematron, en het produceren van documenten die 95% correct zijn, zou certificering op manieren falen die ellendig zijn om te debuggen. Lezen, controleren en converteren is de meeste waarde voor een fractie van het risico.

Source: github.com/biodream-llc/perfuse/internal/cda

26.17 channeltest

Pakket channeltest voert tests uit tegen een kanaaldefinitie.

Een kanaal is een programma. Het filtert, herschrijft en routeert klinische berichten, en het wordt bewerkt onder druk door mensen die het niet tegen productie kunnen testen. Het ontbreken van een manier om het te testen is de enige reden waarom interface-werk eng is, en "Ik heb de transformatie gewijzigd en niets zag er anders uit in de berichtenbrowser" is geen test.

De centrale beslissing is dat een test het bericht door het echte transformatiepad loopt — hetzelfde filter, dezelfde declaratieve stappen, dezelfde script-engine, in dezelfde volgorde — met alleen het transport vervangen. Een test die een herimplementatie oefent, zou slagen terwijl het kanaal faalt, wat erger is dan helemaal geen test hebben, omdat het actief misleidt.

Source: github.com/biodream-llc/perfuse/internal/channeltest

26.18 chanscope

Pakket chanscope beperkt lezen en schrijven op een context tot enkele kanalen.

Het is afhankelijk van de context in plaats van een parameter van elke query, omdat er tientallen queries zijn over de berichtenopslag en de leveringswachtrij, en de limiet is een eigenschap van degene die vraagt, niet van de vraag. De API stelt het één keer per aanvraag in voor een persoon die beperkt is tot enkele kanaalgroepen; elke telling, lijst, grafiek, zoekopdracht en wachtrijactie is dan in overeenstemming met de anderen, zodat niemand wordt verteld dat er veertig fouten zijn en er vier worden getoond.

Source: github.com/biodream-llc/perfuse/internal/chanscope

26.19 cluster

Pakket cluster laat meerdere Perfuse-servers één PostgreSQL-opslag delen en beslissen, onderling, welke server welke taak uitvoert.

Het probleem dat het oplost

Één server is één zwakke schakel: wanneer deze stopt, stopt elke interface. Twee servers op één database lossen dit op, tenzij ze nooit hetzelfde kanaal uitvoeren, omdat twee MLLP-listeners op één feed beurtelings met de afzender communiceren, twee wachtrijwerkers hetzelfde bericht twee keer afleveren en twee DICOM-pollers elk hetzelfde onderzoek melden.

How

Een lease is een rij die aangeeft wie iets in bezit heeft, met een teller die de houder bij elke vernieuwing verplaatst, elke paar seconden. Er wordt geen klok vergeleken met een andere: een houder die de lease niet kan vernieuwen (crash, losgekoppeld van de database) stopt wat de lease dekt zodra zijn eigen klok aangeeft dat de lease bijna verlopen is, en een andere server neemt deze alleen over nadat zijn eigen klok de teller stil heeft zien staan voor de hele lease. Elke server meet een interval op zijn eigen klok, dus de klokken van de servers en de database hoeven niet overeen te komen; ze hoeven alleen ongeveer dezelfde snelheid te hebben. Een klok die springt (een virtuele machine die zichzelf synchroniseert, een beheerder die de tijd instelt) verandert niets: de eerste versie gebruikte de klok van de database voor verloop, en een test vond een database waarvan de klok dertien seconden sprong en elke lease aan een nieuwe server gaf terwijl de oude servers deze nog steeds uitvoerden.

Tussen het stoppen van de houder en het starten van de volgende is er een korte onderbreking waarin niemand de lease uitvoert, wat een afzender een paar seconden geweigerde verbindingen kost, en nooit een moment met twee.

Two modes:

Elke lease bevat een epoch, die wordt opgeteld telkens wanneer de houder verandert, en die een bezit in de geschiedenis aanduidt.

Source: github.com/biodream-llc/perfuse/internal/cluster

26.20 cms

Pakket cms is de Cryptographic Message Syntax (RFC 5652) zoals deze wordt gebruikt door S/MIME en Direct secure messaging: SignedData (een bericht ondertekenen, een bericht verifiëren en aangeven wie het heeft ondertekend) en EnvelopedData (een bericht versleutelen voor de certificaten van de ontvangers, een bericht ontsleutelen met onze sleutel).

Alleen wat de Direct Applicability Statement en de Implementation Guide vereisen: RSA met SHA-256 (SHA-1 wordt alleen geaccepteerd voor lezen, omdat oudere HISPs deze nog steeds verzenden), RSA-sleuteltransport met PKCS#1 v1.5 of OAEP, en AES-128 of AES-256 in CBC-modus. De cryptografie is die van de standaardbibliotheek; dit pakket is de ASN.1-omhulling daaromheen.

Source: github.com/biodream-llc/perfuse/internal/cms

26.21 cms0057

Pakket cms0057 bevat de betalingskantonderdelen van de CMS Interoperability en Prior Authorization-eindregel (CMS-0057-F) die gaan over gegevens in plaats van transport: geclaimde claims als CARIN Blue Button ExplanationOfBenefit-bronnen, voorafgaande autorisaties als Da Vinci PDex ExplanationOfBenefit-bronnen, HRex-lidmaatschapsvergelijking voor de Payer-to-Payer API, de lidmaatschapslijst achter de Provider Access API, en de voorafgaande autorisatie-metrieken die een betaler elk jaar moet publiceren.

De FHIR-eindpunten die deze ondersteunen, bevinden zich in fhirserver; dit pakket bepaalt wat erin komt.

Geneesmiddelen vallen buiten het bereik, net zoals in de voorafgaande autorisatiebepalingen van de regel: geen apotheek ExplanationOfBenefit, geen formularium, geen NCPDP.

Source: github.com/biodream-llc/perfuse/internal/cms0057

26.22 codeset

Pakket codeset bevat mappingtabellen die langer meegaan dan het kanaal dat ze het eerst nodig had.

De domeintaks is grotendeels het opnieuw afleiden van een mapping die iemand al eerder heeft afgeleid. De geslachtscodes, patiëntklassen, bestellingsstatussen en faciliteitsidentificatoren van een site worden op dezelfde manier vertaald in elk kanaal dat deze aanraakt, en vandaag de dag is elke vertaling een aparte tabel binnen een apart kanaal. Veertig kanalen betekent veertig kopieën en veertig plaatsen om de volgende keer dat het ontvangende systeem verandert, aan te passen.

Dus een tabel wordt een genoemd object dat naar naam wordt verwezen. Dat is voor de hand liggend en het is de kleinere helft van de waarde.

De helft die niemand bouwt

De grotere helft is herkomst. Het grootste deel van wat een interface moeilijk te onderhouden maakt, is niet de mapping - het is dat niemand weet *waarom*. 'We halen leidende nullen weg omdat de MRN-colomn van het lab numeriek is' is kennis die in iemands hoofd bestaat en het gebouw verlaat wanneer hij met pensioen gaat, en de mapping die overblijft, wordt iets waar niemand durft te veranderen en niemand durft te verwijderen.

Dus elke tabel registreert wie besloot en wanneer, elke entry kan zijn eigen reden opnemen, en beide overleven in het bestand dat in de versiebeheer terechtkomt. Een mapping met een reden kan worden betwist. Een mapping zonder reden wordt bijgeloof.

Waarom het bestand apart is van het kanaal

Omdat het gedeeld wordt. Een tabel binnen een kanaal is een tabel die alleen door dat kanaal gebruikt kan worden, en dat is het probleem. Een gedeelde tabel heeft zijn eigen geschiedenis nodig: "wie heeft de geslachtskaart gewijzigd en wanneer" is een vraag over de tabel, niet over het kanaal dat toevallig die dag bewerkt werd.

Source: github.com/biodream-llc/perfuse/internal/codeset

26.23 naleving

Pakket naleving implementeert de CMS ADT-gebeurtenisnotificatie-workflow die vereist is door 42 CFR 482.24(d) sinds mei 2021.

Ziekenhuizen moeten elektronisch de gevestigde zorgverleners van een patiënt - huisarts, specialisten, post-acute zorginstellingen - op de hoogte stellen wanneer de patiënt wordt opgenomen, ontslagen of overgeplaatst. Deze regelgeving bestaat omdat patiënten tussen de wal en het schip vallen tijdens overgangen: een huisarts die niet weet van een ontslag kan geen follow-up plannen die een heropname voorkomt.

Dit pakket biedt de middelen om: - bij te houden welke zorgverleners voor elke patiënt zijn gevestigd. - ADT-gebeurtenissen naar de juiste zorgverleners te routeren met de juiste prioriteit. - elke notificatie te registreren die is verzonden, met leveringsstatus, voor CMS-controleaudits. - nalevingsrapporten te genereren die notificatiesnelheden en -fouten laten zien.

Threadsveiligheid is vereist in de hele applicatie omdat ADT-berichten gelijktijdig vanuit meerdere kanalen aankomen en de notificatiepijplijn in parallel wordt uitgevoerd.

Source: github.com/biodream-llc/perfuse/internal/compliance

26.24 config

Pakket config laadt kanaaldefinities uit bestanden.

De configuratie staat in bestanden in plaats van in een database, wat het belangrijkste is dat Perfuse anders doet dan Mirth. Mirth bewaart kanalen in zijn eigen database, waardoor versiebeheer een apart product is, waardoor het promoveren van een kanaal van test naar productie moeilijk is en waardoor niemand kan antwoorden op "wat is er veranderd vorige dinsdag" zonder een ondersteuningsaanvraag. Bestanden geven git, diffs, review, CI en omgevingspromotie met geen extra machinerie.

Validatie gebeurt expres strikt en vindt plaats bij het laden: onbekende velden zijn een fout, filteruitdrukkingen worden gecompileerd, adressen worden gecontroleerd. Een kanaal dat niet begrepen kan worden, moet weigeren te starten in plaats van te draaien op een manier die niemand bedoelde.

Source: github.com/biodream-llc/perfuse/internal/config

26.25 contract

Pakket contract zet erop wat een feed eruit ziet, om te zetten in wat een feed moet zijn.

Een profiel beantwoordt "wat ontvang ik". Dat is één keer nuttig. Het dure probleem is de dag dat het verandert: een leveranciersupgrade laat een veld vallen, een nieuwe code verschijnt, een segment begint te herhalen. Geen van deze is een fout - de berichten zijn nog steeds geldige HL7 en elke motor in de wereld accepteert ze - dus niets merkt het totdat een ontvanger omvalt, meestal weken later, en het onderzoek begint vanaf het verkeerde einde.

Een contract is het profiel dat is opgeschreven als een verwachting en vervolgens gecontroleerd. Het is contracttesten, wat een opgelost idee is in software in het algemeen en bijna geheel afwezig is in zorgintegratie.

Waarom de eenheid een tarief is en geen bericht

Het voor de hand liggende ontwerp is om elk bericht te controleren en te klagen wanneer er een faalt. Dat produceert een systeem dat niemand kan gebruiken. Echte feeds bevatten een proportie van echt vreemde berichten - een testbericht van de leverancier, een patiënt met geen geregistreerd geslacht, een handmatige invoer - en het waarschuwen voor elk ervan leert mensen om de waarschuwingen te negeren, op het moment dat de functie erger is dan niets omdat het de aandacht heeft verbruikt die het nodig had.

Dus een verwachting gaat over een proportie over een venster: "PID-3 is bevolkt in ten minste 99% van de berichten". Één vreemd bericht activeert nooit. Vijf procent van de berichten die hun medisch dossier nummer verliezen, wel.

Een contract beschrijft wat aankomt, niet wat vertrekt

Dit is het onderscheid dat mensen het eerst verkeerd krijgen, inclusief ikzelf tijdens integratietests. Perfuse slaat het bericht op zoals het aankwam - dat is expres, omdat het opgeslagen bericht bewijs is van wat een afzender heeft verstuurd - dus een contract wordt gecontroleerd tegen de inkomende feed en niet tegen de uitvoer van de transformaties van het kanaal.

Dat is de juiste standaard met een grote marge: het ding dat zonder waarschuwing verandert is het verzendende systeem, en het doel van een contract is om op te merken. Maar het betekent dat een verwachting die is geschreven over een toegewezen waarde ("na toewijzing moeten alleen de labcodes overblijven") onmiddellijk en verwarrend faalt, omdat de codes die het noemt nooit in het verkeer verschijnen dat wordt geprofileerd. Alles over wat vertrekt, hoort in een kanaaltest, die de echte transformaties uitvoert.

Waarom een schending de tolerantie noemt die het brak

"PID-3 faalde" zegt iemand niets. "PID-3 was bevolkt in 94,2% van de laatste 500 berichten; het contract vereist 99%" zegt hen hoe erg het is, hoe vertrouwd ze kunnen zijn en of het de moeite waard is om iemand wakker te maken. De cijfers zijn het bericht.

Source: github.com/biodream-llc/perfuse/internal/contract

26.26 crd

Pakket crd is een Da Vinci Coverage Requirements Discovery-service (CRD 2.2.1): de betaalzijde van de CDS Hooks-conversatie die een clinicus vertelt, terwijl de bestelling nog een concept is, of het is gedekt, of het een voorafgaande autorisatie nodig heeft en welke documentatie de betaalzijde zal willen.

CMS-0057's Prior Authorization API is in de praktijk drie Da Vinci-gidsen samen: CRD om te zeggen wat vereist is, DTR om het te verzamelen, PAS om het in te dienen. Perfuse had PAS. Dit is de eerste van de andere twee; DTR's $questionnaire-package is op het FHIR-eindpunt.

De dekkingbeslissingen komen uit een regelbestand, omdat het het beleid van de verzekeraar is en verandert zonder software-releases: een code (of een lijst met codes) en wat daarop van toepassing is - gedekt of niet, voorafgaande autorisatie nodig of niet, documentatie en het DTR-vragenlijst dat het verzamelt. Een bestelling die geen regel overeenkomt, wordt beantwoord met "voorwaardelijk" en "onbepaald", wat CRD zegt dat moet worden geretourneerd wanneer de service niet kan beslissen - nooit een gok dat het gedekt is.

Antwoorden volgen de gids: een systeemactie die elke bestelling bijwerkt met de dekking-informatie-extensie, die de EHR op de bestelling opslaat en later meestuurt met de voorafgaande autorisatie; en een kaart per bestelling, zodat een clinicus het ziet.

Source: github.com/biodream-llc/perfuse/internal/crd

26.27 dashboards

Pakket dashboards definieert de dashboards die Perfuse levert voor elk type persoon die ernaar kijkt, en hoe een persoon er een krijgt: op basis van hun rol, op basis van een directorygroep die het dashboards-bestand toewijst, of op basis van het overzicht dat ze hebben opgeslagen.

Dashboards bestaan uit tegels, en tegels tonen alleen aggregaten - tellingen, tarieven, tijden, staten. Geen enkele toont een bericht, een patiënt of een identificator, zodat een dashboard aan een afdelingsmanager kan worden gegeven of op een wandbeeldscherm kan worden weergegeven zonder degenen die toegang hebben tot patiëntgegevens te vergroten. Een tegel die gegevens nodig heeft die Perfuse nog niet heeft opgenomen, wordt niet nagemaakt: het dashboard lijst het op onder Gepland.

Volledige flexibiliteit is de taak van Grafana, niet van dit pakket. Elke tegel die een metriek achter zich heeft, exporteert als een Grafana-paneel via Perfuse's /metrics, zodat een site die meer dan lichte configuratie wil, het dashboard daarheen kan nemen.

Source: github.com/biodream-llc/perfuse/internal/dashboards

26.28 davinci

Pakket davinci geeft aan welke release van de Da Vinci prior-authorization guides (CRD, DTR, PAS) een client spreekt.

Perfuse antwoordt in twee: 2.2 (CRD 2.2.1, DTR 2.2.0, PAS 2.2.1), de nieuwste, en 2.1 (CRD, DTR en PAS 2.1.0), de release CMS-0057-F's aanbevolen lijst wijst op het moment dat de 2.0.1 releases' US Core 3.1.1 basis verloopt. De twee verschillen in vormen die een client leest op naam - DTR's $questionnaire-package parameters (PackageBundle in 2.1, packagebundle in 2.2), PAS's $inquire antwoord (een Bundle in 2.1, een Parameters van hen in 2.2), extensies die alleen in een van hen bestaan - dus één antwoord kan niet voor beide dienen, en de server moet weten welke het is.

Het wordt verteld, meest specifiek eerst: door het verzoek zelf (CRD's davinci-crd.requestedVersion; de versie op een profiel dat de invoer claimt, profiel|2.1.0), dan door de registratie van de client (davinci_version op een SMART of CDS client), dan door de eigen instelling van de server (serve -davinci-version), die standaard naar de nieuwste gaat.

Source: github.com/biodream-llc/perfuse/internal/davinci

26.29 dbtime

Pakket dbtime formateert tijdstempels zodat het sorteren ervan als tekst het sorteren ervan als tijd sorteert.

Elke winkel in Perfuse houdt tijdstempels op als TEKST in SQLite en vertrouwt op tekenvergelijking voor ordening en voor bereikvragen: ORDER BY received_at DESC, WHERE expires_at < ?, WHERE at >= ?. Dat is een redelijke ontwerp - het houdt een database die iemand kan lezen met de sqlite3-shell - maar het werkt alleen als de tekstvorm vaste breedte heeft.

time.RFC3339Nano is dat niet. De documentatie zegt dat het trailing nullen uit het secondenveld verwijdert, zodat dezelfde klok tekenreeksen van verschillende lengtes produceert:

20:56:33.12345Z <- 123450 microseconden, trailing nul verwijderd 20:56:33.123456Z <- 123456 microseconden

Vergelijken als tekst, is de eerste *groter*, omdat na het gedeelde voorvoegsel "12345" het 'Z' heeft waar de tweede '6' heeft, en 'Z' sorteert boven elke cijfer. Dus sorteert het eerder moment later. Ongeveer één aangrenzende paar op tien wordt beïnvloed, wat de reden is dat het zich presenteert als een intermittent testfout in plaats van als een overduidelijk kapotte functie.

Wat het daadwerkelijk brak: de auditlog en de berichtenbrowser ordenen beide op een tijdstempel en kunnen dus vermeldingen uit hetzelfde seconde in de verkeerde volgorde weergeven. Een audittrail is een compliance-artefact en een berichtenbrowser is de manier waarop iemand reconstrueert wat er is gebeurd, dus in beide gevallen is de volgorde het punt.

Het onderstaande lay-out gebruikt .000000000 in plaats van .999999999. Beide printen nanoseconden; het verschil is dat nullen significant zijn in de eerste en verwijderd worden in de tweede.

Source: github.com/biodream-llc/perfuse/internal/dbtime

26.30 begrensd

Pakket delimited parseert records die zijn gescheiden en gesplitst door geconfigureerde tekens.

Dit is Mirth's Delimited gegevenstype: CSV, tab-gescheiden, pipe-gescheiden, vaste kolom bestanden, en de lange staart van formaten die een laboratoriumanalyse of een bureau-service emitteert omdat iemand het in 1994 heeft geschreven en het werkt.

Opzettelijk geen algemene CSV-bibliotheek. Wat hier toe doet, is wat een healthcare-feed doet dat een goed gevormde CSV niet doet: een headerrij die aanwezig kan zijn of niet, een trailing lege regel die niet mag worden omgezet in een lege record, kolommen die worden verwezen naar naam, zodat een transformatie niet breekt wanneer een leverancier er een invoegt, en de mogelijkheid om een hele bestand als één bericht te behandelen of elke rij als zijn eigen.

De laatste van deze is de beslissing die alles anders vormt. Een bestand met vijfduizend resultaten is ofwel één bericht of vijfduizend, en de twee zijn niet uitwisselbaar: één bericht betekent één bevestiging en één fout voor het hele bestand, en vijfduizend betekent dat elke rij kan worden gefilterd, getransformeerd en opnieuw geprobeerd.

Source: github.com/biodream-llc/perfuse/internal/delimited

26.31 dicom

Pakket dicom leest DICOM-gegevenssets.

DICOM is waar radiologie leeft, en een ziekenhuisintegratie-engine die het niet kan spreken, wordt buitengesloten van beeldvorming helemaal. Mirth heeft een DICOM-luisteraar en -afzender, dus dit is een migratieblokker voor elke site die modality-werk doet.

Scope, gesteld op een eenvoudige manier

Dit pakket parseert gegevenssets: de bestandsmeta-informatie, de elementen, de transmissiesyntaxis en de waarden die er toe doen voor routering en identificatie. Het decodeert geen beeldgegevens en zal dat ook nooit doen voor zover dit pakket betreft - een integratie-engine verplaatst beelden, het toont ze niet, en een decoder is een grote hoeveelheid formaatspecifiek werk wiens enige doel hier zou zijn om de binaire groter te maken.

Het lezen van metadata zonder pixels aan te raken is ook wat het snel maakt op het verkeer dat ertoe doet: een borst-CT is honderden megabytes aan pixels achter twee kilobytes aan informatie waarop iedereen routeert.

Waarom de waarde-representaties expliciet worden afgehandeld

Een DICOM-element bevat een tweecijferige waardevertegenwoordiging die aangeeft hoe de waarde moet worden gelezen, en de regels verschillen per VR op manieren die niet kunnen worden geraden: sommige hebben een tweecijferige lengte en sommige vier, sommige worden opgevuld met een spatie en sommige met een nul, en numerieke tekenreeksen kunnen meerdere waarden bevatten die zijn gescheiden door backslashes. Het verkeerd krijgen van een van deze levert geen fout op, maar produceert een plausibele verkeerde waarde - een patiëntennaam die uit het midden van een datum wordt gelezen, of een studie-id die één byte verschilt.

Source: github.com/biodream-llc/perfuse/internal/dicom

26.32 dicomweb

Pakket dicomweb spreekt DICOMweb (DICOM PS3.18): QIDO-RS voor zoeken, WADO-RS en WADO-URI voor opvragen, STOW-RS voor opslaan, via HTTP.

Het is de manier waarop viewers, AI-diensten en cloud-archieven nu toegang krijgen tot beeldvorming: OHIF, Google Cloud Healthcare, Azure Health Data Services, AWS HealthImaging, Orthanc's en dcm4chee's DICOMweb-interfaces. Een integratie-engine die alleen het netwerkprotocol uit 1993 spreekt (DIMSE: C-STORE, C-FIND) kan een PACS voeden, maar geen browser.

Het pakket heeft vier onderdelen: een dataset-lezer die het hele object doorloopt, inclusief sequenties, en weet waar de pixelgegevens zijn zonder deze te laden; het DICOM JSON-model (PS3.18 F.2); multipart/related, dat is hoe DICOMweb meerdere objecten in één aanvraag verplaatst; en een archief met een index, dat is waar QIDO en WADO antwoord op geven.

Source: github.com/biodream-llc/perfuse/internal/dicomweb

26.33 direct

Pakket direct is Direct-beveiligde messaging als een edge-systeem: een bericht naar een Direct-adres wordt ondertekend met dit adres's certificaat en versleuteld naar het certificaat van de ontvanger, als S/MIME, en verzonden naar een HISP via SMTP; een bericht dat wordt ontvangen van de HISP (via SMTP of verzameld via IMAP) wordt ontsleuteld en de handtekening wordt gecontroleerd tegen de trust-ankers voordat iets het leest.

Het volgt de Direct Project Applicability Statement voor Secure Health Transport 1.2 en de XDM-specificatie (IHE ITI TF-1 Annex 15) voor documenten met metadata. Het is geen HISP: de accreditatie van de HISP, het certificaatbeleid en de directory blijven bij de HISP.

Source: github.com/biodream-llc/perfuse/internal/direct

26.34 drug

Pakket drug behandelt de codes en hoeveelheden die een medicijn identificeren.

Uiteengezet van de apothekersstandaarden die deze bevatten, omdat dezelfde drugcode voorkomt in een NCPDP-claim, een SCRIPT-recept, een HL7 RXE-segment en een FHIR MedicationRequest, en een conversie die in een van deze plaatsen leeft, is een conversie die de andere drie niet nodig hebben.

Source: github.com/biodream-llc/perfuse/internal/drug

26.35 dsdr

Pakket dsdr ondertekent en verifieert CDA-documenten zoals beschreven in de HL7 Implementation Guide voor CDA Release 2: Digital Signatures en Delegation of Rights, Release 1 (oktober 2014) - de elektronische handtekeningstandaard die HIPAA aanneemt voor claims-bijlagen in CMS-0053-F, 45 CFR 162.2002(e), met naleving vanaf 26 mei 2028.

Wat de gids vraagt, en waar het hier wordt gedaan:

Waar de gids zwijgt, worden de gemaakte keuzes genoemd: deze geeft geen naamruimte voor de eigen elementen (digitalSignature, authorizedSigner, SignaturePurpose), dus worden deze in urn:hl7-org:sdtc geplaatst; en het doel wordt ook als een XAdES CommitmentTypeIndication met de ASTM-OID uitgedrukt, die XAdES-hulpmiddelen lezen en het element van de gids zelf niet.

Delegatie van rechten (een gedelegeerde ondertekenaar met een SAML-assertie) wordt niet gegenereerd; een handtekening die deze bevat, wordt als zodanig gerapporteerd.

Source: github.com/biodream-llc/perfuse/internal/dsdr

26.36 e4x

Pakket e4x maakt Mirth Connect's JavaScript ongewijzigd uitvoerbaar.

Mirth-scripts zijn geschreven voor Rhino, dat E4X implementeert: XML is een native type met zijn eigen syntaxis. De engine hier is goja, die dat niet doet, en de kloof is niet alleen een runtime-kloof.

drie onderdelen van E4X zijn *syntaxis*, dus goja's parser wijst het bestand rechtstreeks af voordat een objectmodel enige hulp kan bieden:

Dit bestand herschrijft deze in gewone ECMAScript die goja parseert, waarbij de semantiek wordt overgelaten aan het runtime-object in xml.go. Alles wat E4X betreft - eigenschapstoegang op elementnaam, indexering van herhalingen, toewijzing, toString - is al geldige JavaScript-syntaxis en heeft geen herschrijving nodig.

De herschrijving gebeurt met een echte lexer in plaats van reguliere expressies, omdat het alternatief werkbare scripts corrumpeert. Een patroon voor de descendant-operator vindt er een binnen "http://example.org", een patroon voor XML-literals vindt er een in "a < b && c > d", en een script dat stilzwijgend van betekenis verandert, is erger dan een script dat weigert te laden.

Source: github.com/biodream-llc/perfuse/internal/e4x

26.37 edifact

Pakket edifact leest en schrijft UN/EDIFACT-berichten (ISO 9735): de UNA-service-string-advies, de UNB/UNZ-berichtenomhulsel, optionele UNG/UNE-functionele groepen en UNH/UNT-berichten, met het release-teken en, voor syntaxisversie 4, de herhalingsscheidingsteken.

Het controleert de enveloppen tellingen en verwijzingen, adresseert gegevenselementen voor filters, splitst een interchange in één per bericht en bouwt een CONTRL acknowledgement.

Het leest elk berichttype (ORDERS, INVOIC, IFTSTA, MEDRPT ...); het bevat geen directories die aangeven welke segmenten een berichttype kan bevatten, dus het controleert de structuur, niet de inhoud.

Source: github.com/biodream-llc/perfuse/internal/edifact

26.38 egress

Package egress beslist of deze engine uitgaand kan verbinden met een adres.

Het bestaat omdat een bestemming overal naar kan wijzen, en één combinatie maakt dat een manier om het interne netwerk te lezen: een SOAP-bestemming met een respons transformatie retourneert de ontvanger's antwoord naar een script, zodat een editor een kanaal kan maken dat een interne URL ophaalt en de body schrijft naar een log of een bericht.

Aangetoond in plaats van theoretisch: een SOAP-bestemming gericht op een lokale HTTP-server plaatste die server's respons body in een kanaal logregel.

Het evenredige antwoord is niet om uitgaande verbindingen te verbieden - het leveren van berichten aan geconfigureerde eindpunten is het hele doel van de software, en een editor is bedoeld om deze te configureren. Het is om de specifieke adressen te weigeren die nooit een berichtbestemming zijn en altijd een referentieopslag zijn.

Source: github.com/biodream-llc/perfuse/internal/egress

26.39 engine

Package engine voert geconfigureerde kanalen uit.

Een kanaal is een bron, een filter en een set bestemmingen. De runtime's taak is om eerlijk te zijn over wat er met elk bericht is gebeurd: een acknowledgement moet betekenen wat de configuratie zegt dat het betekent, een bericht dat wordt gefilterd moet te onderscheiden zijn van een dat werd geleverd, en een bericht dat nergens kon worden geleverd mag niet worden gerapporteerd als geaccepteerd.

Source: github.com/biodream-llc/perfuse/internal/engine

26.40 epa

Package epa is NCPDP SCRIPT elektronische voorafgaande autorisatie, de betaler's kant: PAInitiationRequest, PARequest, PAAppealRequest en PACancelRequest in, en hun antwoorden uit.

CMS-0062-P stelt voor dat getroffen betalers het vanaf 1 oktober 2027 ondersteunen, en Medicare Part D vereist het al. Een verzoek wordt beslist op de manier waarop elke voorafgaande autorisatie op deze server wordt: het wordt een Da Vinci PAS-verzoek (een Claim, de MedicationRequest en de prescriber's antwoorden als een QuestionnaireResponse) en gaat naar hetzelfde regelbestand, beslissingsdienst en reviewwachtrij. De formularium zegt welke medicijnen een autorisatie nodig hebben en welke vragen moeten worden gesteld, vanuit hetzelfde FHIR-vragenlijst dat Da Vinci DTR invult.

NCPDP's schemas zijn gelicentieerd. Elementnamen en volgorde hier volgen de openbare Surescripts ePA-companion guide en zijn voorbeelden; twee elementen die het openbare materiaal nooit laat zien (de reden binnen Closed en binnen Denied) volgen het SCRIPT-patroon dat elders wordt gebruikt en worden genoemd in de handleiding zodat een betaler ze kan controleren tegen zijn eigen kopie van het schema.

Source: github.com/biodream-llc/perfuse/internal/epa

26.41 eprescribe

Package eprescribe leest en schrijft NCPDP SCRIPT, de standaard waarin recepten reizen.

Genoemd naar wat het doet in plaats van naar de standaard, omdat internal/script al de JavaScript-engine is en twee packages met de naam script in één boom een fout is die op het punt staat te worden gemaakt bij een importregel.

SCRIPT is XML, in tegenstelling tot de Telecommunicatiestandaard die de resulterende claim draagt. Een prescriber stuurt een NEWRX naar een apotheek; de apotheek stuurt terug RXFILL om te zeggen wat er is gebeurd, REFREQ om een herhaling te vragen, of RXCHG om een wijziging te vragen. Elk van deze is een bericht hier.

Waar het gevaar is

Twee velden in een recept zijn gevaarlijk als ze verkeerd worden gelezen in plaats van als ze ontbreken.

Substituties is de eerste. Een nul betekent dat substitutie is toegestaan en een één betekent dat het moet worden uitgegeven zoals geschreven. Het leest achterstevoren voor iemand die een vlag verwacht waar één ja betekent, en het fout krijgen van een generiek waar de prescriber de merknaam vereiste - of weigert een substitutie die was toegestaan, wat dezelfde fout is die de patiënt geld kost in plaats van.

Herhalingstelling is de tweede. Een recept voor een schedule II-medicijn mag niet opnieuw worden uitgegeven, en een systeem dat een herhalingstelling overneemt van een niet-gecontroleerd sjabloon produceert een ogenschijnlijk geldig recept dat een apotheek moet weigeren.

Wat niet is geverifieerd

De berichtstructuur volgt de gepubliceerde SCRIPT-elementnamen. Geen bericht van dit pakket is verstuurd via een echt routeringsnetwerk zoals Surescripts, en certificering door een van hen is een commercieel proces in plaats van een technisch proces. Dit parseert en bouwt het formaat; het claimt geen certificering.

Source: github.com/biodream-llc/perfuse/internal/eprescribe

26.42 equiv

Package equiv bewijst dat twee motoren overeenkomen, of zegt exact waar ze niet overeenkomen.

Dit is het antwoord op de enige vraag die een migratie daadwerkelijk blokkeert. Een interface-team weigert een nieuwe motor niet omdat deze functies ontbreekt; ze weigeren omdat ze niet zeker weten of deze hetzelfde zal doen met het verkeer dat ze al hebben, en fout zijn betekent dat laboratoriumresultaten niet bij artsen terechtkomen. Geen enkele functievergelijking beantwoordt deze vraag. Bewijs doet dat wel.

Het beoogde gebruik is een parallelle uitvoering. Beide motoren ontvangen dezelfde productieberichten; de zittende motor blijft leveren en Perfuse levert aan niemand, wat al is wat schaduwkanalen al zijn. Na twee weken worden de uitvoer hier vergeleken en verandert het gesprek van "vertrouw dit" naar "hier zijn de drie berichten uit vierhonderdduizend waarin we verschilden, en waarom".

Groepering is de hele functie

Een naive diff van 400.000 berichten produceert 400.000 bevindingen en wordt ongelezen gesloten. Bijna elk echt verschil heeft één oorzaak: een datumnotatie, een faciliteitscode, één transformatiestap die niemand heeft overgedragen. Dus worden verschillen gegroepeerd op oorzaak - het pad in het bericht en het type verschil - en één keer gerapporteerd met een telling. Drieduizend verschillen van één oorzaak zijn één bevinding, niet drieduizend. Die enkele beslissing is wat de rapportage leesbaar maakt, en een leesbare rapportage is het verschil tussen een migratie die doorgaat en een die stilvalt.

Waarden worden standaard niet weergegeven

Echt verkeer is patiëntgegevens, dus een vergelijking van rapporten is een plaats waar PHI in een ticket, e-mail of dia kan lekken. Standaard rapporteert dit paden, soorten en tellingen - nooit waarden. Dat is genoeg om de oorzaak te vinden: "MSH-7 verschilt in 3.000 van de 3.000 berichten" vertelt een analist dat het de datumnotatie is zonder één datum weer te geven.

Waarden kunnen opzettelijk worden ingeschakeld, omdat iemand uiteindelijk één moet zien, en doen alsof dat niet zo is, zou hen alleen maar naar een slechter hulpmiddel duwen. Het is een expliciete opt-in en het rapport vermeldt op het eerste gezicht dat het berichtinhoud bevat.

Source: github.com/biodream-llc/perfuse/internal/equiv

26.43 expr

De HL7 v2-binding.

Dit is de logica die vroeger inline in eval.go woonde. Het gedrag is ongewijzigd - opzettelijk, omdat de v2-filter is wat elke HL7-kanaal uitvoert en het doel van de generieke grammatica was om formats toe te voegen, niet om deze te wijzigen.

Source: github.com/biodream-llc/perfuse/internal/expr

26.44 fdlimit

Package fdlimit vindt uit hoeveel bestandsdescriptors dit proces mag openen en verhoogt de limiet als dat kan.

Dit bestaat vanwege de vorm van de fout die het voorkomt. Elke inkomende verbinding is een descriptor, en elke uitgaande levering in vlucht is dat ook. Een ontvanger die heeft opgehouden met antwoorden, houdt een descriptor vast voor het hele retry-budget - met de standaardinstellingen, vijf pogingen met een time-out van dertig seconden plus vijftien seconden back-off, dus bijna drie minuten. Een paar honderd verbindingen tegen één vastgelopen ontvanger zijn dus een paar honderd descriptors die voor minuten worden vastgehouden.

Het opmaken van de limiet produceert geen nette fout op de plaats waar deze is opgemaakt. Het produceert "te veel open bestanden" op een heel andere plaats: de database kan zijn journaal niet openen, de webinterface stopt met het accepteren van, een logbestand kan niet worden geschreven. De motor lijkt op drie ongerelateerde plaatsen tegelijk te zijn gebroken, en de werkelijke oorzaak is een partnersysteem dat stil is geworden. Dat is de ondersteuningsaanvraag die dit pakket bestaat om te voorkomen.

Twee dingen gebeuren bij het opstarten. De zachte limiet wordt verhoogd naar de harde limiet, wat meestal het probleem rechtstreeks verhelpt - de zachte standaardlimiet is vaak een paar honderd, terwijl de harde limiet tienduizenden is. Vervolgens wordt alles wat beschikbaar is gerapporteerd, zodat de motor zijn eigen gelijktijdigheid binnenin kan begrenzen in plaats van het te ontdekken door het te raken.

Source: github.com/biodream-llc/perfuse/internal/fdlimit

26.45 fhirpath

Package fhirpath evalueert FHIRPath (HL7 FHIRPath N1, 2.0.0) over FHIR-bronnen die als gedecodeerde JSON worden gehouden.

Het heeft geen FHIR-model: het type van een element is bekend wanneer FHIR JSON het zegt (een suffix van een keuze-element, zoals valueQuantity, een resourceType van een resource) of wordt afgeleid van de JSON-waarde anders. Dat dekt wat SQL op FHIR-weergaven en CQL-vrije kwaliteitsmaatregelen nodig hebben; navigatie die afhankelijk is van het model (het type van een primitief wanneer het geen keuze is) wordt beantwoord vanuit de vorm van de waarde.

Source: github.com/biodream-llc/perfuse/internal/fhirpath

26.46 fhirserver

Package fhirserver implementeert een FHIR REST-server.

Dit bestaat omdat het nuttige einde van een v2-naar-FHIR-mapper een plaats is om het resultaat neer te zetten. In staat zijn om een bericht te converteren is een demo; in staat zijn om het te converteren, op te slaan en vervolgens de patiënt opnieuw te vinden met een identificator is een product.

Het is een echte FHIR-server in de delen die ertoe doen voor dat: een capability statement, create, read, update, delete, zoekopdrachten op de parameters die mensen daadwerkelijk gebruiken, en transactiebundels die atomisch worden toegepast. Het is geen complete FHIR-server — geen geschiedenis, geen gekoppelde zoekopdracht, geen _include — en het zegt dat zelf in zijn eigen capability statement in plaats van een client de lacunes te laten ontdekken.

Source: github.com/biodream-llc/perfuse/internal/fhirserver

26.47 formulary

Package formulary is een drugformularium van een verzekeraar: welke medicijnen elke polis dekt, op welk niveau, en met welke beperkingen (voorafgaande autorisatie, staptherapie, hoeveelheidsbeperkingen), en wat de deelnemer betaalt.

Een bestand is de enige bron voor alles wat een vraag over een medicijn beantwoordt: de Da Vinci US Drug Formulary API (gepubliceerd als FHIR), NCPDP Real-Time Prescription Benefit-antwoorden en NCPDP SCRIPT-elektronische voorafgaande autorisatie (of een medicijn een autorisatie nodig heeft en welke vragen moeten worden gesteld). Een formularium dat op drie plaatsen leeft, beantwoordt dezelfde vraag op drie manieren.

Source: github.com/biodream-llc/perfuse/internal/formulary

26.48 framing

Package framing leest en schrijft berichten op een byte-stroom die geen MLLP is.

Waarom dit apart bestaat van mllp

MLLP is één framing: 0x0B voor, 0x1C 0x0D na. Het is wat HL7 v2 gebruikt over TCP en Perfuse heeft het altijd gesproken.

Een groot deel van de apparatuur doet dit niet. Een laboratoriumanalyseapparaat, een weegschaal, een bedmonitorsysteem, een ouder factureringssysteem - elk heeft zijn eigen conventie en de conventies zijn allemaal eenvoudige variaties op drie ideeën: een scheidingsteken ergens, een vaste recordlengte of een lengte die voor de payload wordt geschreven.

Mirth's TCP-connector dekt dit en Perfuse had niets, dus een site met een socket-feed die geen HL7 was, kon het helemaal niet gebruiken.

De fout die dit pakket probeert te vermijden

Lezen van een stroom en raden waar een bericht eindigt, is het hele probleem. Raden te kort en een bericht wordt doormidden gesneden; raden te lang en twee berichten komen als één aan. Beide produceren uitvoer die vaak plausibel lijkt, wat erger is dan een fout, dus elke modus hier is expliciet over wat een bericht beëindigt en geen ervan valt terug naar een andere.

Een bericht zonder enige framing is een legitieme configuratie - sommige apparaten openen een verbinding, sturen één bericht en sluiten - maar het kan niet worden gecombineerd met iets anders en kan niet worden gebruikt op een verbinding die open blijft, dus het wordt genoemd en gevalideerd in plaats van als standaard te worden behandeld.

Source: github.com/biodream-llc/perfuse/internal/framing

26.49 ftpconn

Pakket ftpconn uploadt bestanden via FTP en FTPS met behulp van alleen de standaardbibliotheek.

FTP is oud, praatgraag en geen goed protocol. Het is ook nog steeds de manier waarop een groot aantal ziekenhuissystemen bestanden accepteert, meestal omdat de andere kant een laboratoriumanalyseapparaat of een bureau-service is waarvan de software sinds het werkte niet is aangeraakt. Weigeren om het te ondersteunen, maakt die systemen niet modern; het maakt Perfuse onbruikbaar op die locaties.

Hier geïmplementeerd in plaats van als afhankelijkheid genomen om dezelfde reden als S3: de factuur van acht afhankelijkheden is een echt argument met degene die software beoordeelt voordat een ziekenhuis het installeert. FTP's controlekanaal is tekst op TCP, dus dit is een paar honderd regels van net en crypto/tls.

Wat wordt ondersteund en wat wordt geweigerd

Alleen passieve modus. Actieve modus vereist dat de server een verbinding terug naar de client opent, wat elke ziekenhuisfirewall die deze eeuw is gebouwd, blokkeert, en het aanbieden ervan zou betekenen dat mensen het configureren en vervolgens debuggen op een firewall.

Expliciete FTPS (AUTH TLS) wordt ondersteund en is standaard wanneer TLS wordt gevraagd. Implicit FTPS op poort 990 wordt ook ondersteund omdat sommige analysers alleen dat spreken.

Plaine FTP wordt ondersteund en waarschuwt. Het stuurt het wachtwoord in cleartext, en een site die het moet gebruiken, moet het een keer worden verteld in plaats van het te laten ontdekken van een pakketopname.

Source: github.com/biodream-llc/perfuse/internal/ftpconn

26.50 gcp

Pakket gcp praat met Google Cloud Pub/Sub en Cloud Storage via hun REST-API's, met Google's OAuth 2.0 gedaan hier: een serviceaccount-sleutel ondertekent een JWT (RS256, crypto/rsa) die wordt geruild voor een toegangstoken, of, op Google Cloud zelf, de metadataserver geeft er een uit.

Geen Google SDK.

Emulators (de Pub/Sub-emulator, fake-gcs-server) nemen geen referenties: stel Endpoint in en laat de referenties leeg.

Source: github.com/biodream-llc/perfuse/internal/gcp

26.51 generate

Pakket generate maakt synthetische HL7 v2-berichten.

Twee gebruiken. Iemand die Perfuse probeert, heeft verkeer nodig om naar te kijken, en een kanaaltest heeft een fixture nodig die realistisch genoeg is om het te testen. Een generator is een betaalde extensie in Mirth, wat aangeeft dat mensen er een willen.

Alles hier is uitgevonden. De namen komen van een vaste lijst van overduidelijk fictieve namen, de identificatoren zijn opeenvolgend binnen een run, en de adressen zijn verzonnen. Dat is geen disclaimer, het is het ontwerp: een generator die realistisch uitziende echte namen produceert, zou uiteindelijk één in een testfixture, een bugrapport en vervolgens een repository plaatsen.

Realisme wordt alleen uitgegeven waar het voor tests relevant is en nergens anders. Tijdstempels hebben offsets, herhalende velden herhalen daadwerkelijk, een naam heeft soms een tusseninitial en soms niet, en ongeveer één bericht in twaalf is expres lastig: een ontbrekend optioneel veld, een ongebruikelijke maar legale scheidingsteken, een lege component. Een kanaal voeden met alleen perfect gevormde berichten vertelt je heel weinig.

Source: github.com/biodream-llc/perfuse/internal/generate

26.52 hl7dict

Pakket hl7dict noemt de velden van HL7 v2-segmenten.

Dit bestaat voor één scherm: een berichtweergave die je kan vertellen dat PID-5.1 de familienaam van de patiënt is, in plaats van je te laten tellen bij het caret-teken. Iedereen die een interface heeft gedebugeerd, heeft dat tellen met de hand gedaan, en het is de meest voorkomende bron van off-by-one-fouten die een waarde in het verkeerde veld plaatsen.

Het is niet de hele standaard. HL7 v2 heeft honderden segmenten en duizenden velden, en de velden die hier worden genoemd, zijn die welke voorkomen in ADT-, ORU-, ORM- en SIU-verkeer. Een onbekend veld wordt gemeld als onbekend in plaats van geraden.

Source: github.com/biodream-llc/perfuse/internal/hl7dict

26.53 hl7v3

Pakket hl7v3 leest HL7-versie 3-berichten.

Versie 3 is een andere zaak dan versie 2 met dezelfde naam. Versie 2 is een pipe-gescheiden stroom van segmenten waarvan de betekenis positioneel is; versie 3 is XML gegenereerd uit een referentie-informatiemodel, waarbij de betekenis wordt gedragen door elementnamen en door een kleine set datatypes die overal terugkeren. Bijna niets wordt overgedragen tussen de twee, behalve de klinische vocabulaire.

In de praktijk arriveert v3 in een van twee vormen. Of het is een CDA-document, dat v3-afgeleid is en wordt afgehandeld door het cda-pakket, of het is een IHE-transactie - PIX en PDQ v3 in het bijzonder, wat de manier is waarop veel ziekenhuizen patiëntidentificatoren tussen systemen oplossen. Dit pakket richt zich op de tweede.

Waarom de datatypes eerst komen

Het meest consequente ding over v3 is dat een element aanwezig kan zijn en expliciet null, met een opgegeven reden. Een geboortedatum met nullFlavor="ASKU" betekent dat de patiënt werd gevraagd en weigerde te antwoorden. Een geboortedatum met nullFlavor="NAV" betekent dat de waarde bestaat, maar niet beschikbaar is op dit moment, dus opnieuw vragen kan later werken. Een geboortedatum die eenvoudigweg afwezig is, betekent dat niemand iets heeft opgenomen.

Het samenvouwen van deze in een lege tekenreeks is de fout die dit pakket is ingericht om te voorkomen. Het is geen cosmetische verlies: een downstream-systeem dat een lege geboortedatum ontvangt waar de bron zei "patiënt weigerde" zal deze meestal behandelen als ontbrekende gegevens die moeten worden nagegaan, en een demografische match die onopgelost had moeten blijven, wordt opgelost door een mens die gokt. Dus elk datatype hier onderscheidt afwezig, null-met-reden en aanwezig.

Source: github.com/biodream-llc/perfuse/internal/hl7v3

26.54 hl7xml

Pakket hl7xml converteert HL7 v2-berichten naar en van de XML-vorm die Mirth Connect gebruikt, en terug naar ER7-codering.

De vorm is geen ontwerpkeuze. Mirth-scripts zijn geschreven tegen de uitvoer van de eigen ER7-naar-XML-serializer, dus ze bevatten uitdrukkingen zoals

msg['PID']['PID.5']['PID.5.1'].toString()

en de belofte dat een bestaand script ongewijzigd blijft, wordt alleen nagekomen als de boom die het bewandelt exact dezelfde elementnamen, nesting en herhalinggedrag heeft. Elk besluit hieronder is dus "wat doet Mirth", niet "wat zou netter zijn".

De twee die het meest tellen:

Elk veld wordt omhuld door genummerde componentelementen, zelfs als het veld slechts één component heeft, dus PID-5 met de waarde "Doe" produceert nog steeds <PID.5><PID.5.1>Doe</PID.5.1></PID.5>. Scripts indexeren rechtstreeks naar .1 constant en een boom die de tekst op het veld-element zou plaatsen, zou bijna alle scripts breken.

MSH houdt de standaard HL7-veldnummers aan, waar MSH-1 het veldscheidingsteken is en MSH-9 het berichttype is. De parser in internal/hl7 indexeert MSH met een offset, omdat het scheidingsteken een positie inneemt die geen delimiter splitst, en die offset stopt hier: een script dat MSH.9 zegt, bedoelt het berichttype.

Source: github.com/biodream-llc/perfuse/internal/hl7xml

26.55 ibmmq

Pakket ibmmq verzendt naar en leest van IBM MQ-wachtrijen via de messaging-REST-API (mqweb) van de wachtrijbeheerder, die IBM MQ 9.1.5 en later op elk platform, inclusief z/OS, meelevert.

Het heeft geen MQ-clientbibliotheek nodig: het native MQI-protocol is van IBM en ongedocumenteerd, en de REST-API is de ondersteunde manier om MQ te bereiken zonder een. (IBM MQ spreekt ook AMQP 1.0 op een AMQP-kanaal; de amqp-connector van Perfuse dekt die route.)

Lezen is minstens één keer: het eerste bericht wordt doorgebladerd, aan de beller gegeven en verwijderd door zijn bericht-id alleen eenmaal de beller het heeft verwerkt. Een bericht dat niet kon worden verwerkt, blijft op de wachtrij, eerste in de rij.

Source: github.com/biodream-llc/perfuse/internal/ibmmq

26.56 identiteit

Een bericht vinden door wat je weet over het bericht, ongeacht het formaat waarin het arriveerde.

De bestaande inhoudszoekopdracht komt overeen met metadata, biedt een substring-overeenkomst tegen de payload en kan een filterexpressie evalueren - maar de expressie wordt alleen gegenereerd tegen HL7 v2 en elke expressie vereist kennis van het pad. Zo betekende het vinden van één patiëntverkeer weten dat de identiteit op PID-3 in een HL7 v2-opname leeft, op Patient.identifier in een FHIR-bron, op (0010,0020) in een DICOM-exemplaar en op NM109 van een NM1 * IL-lus in een 837-claim. Vier formaten, vier vocabulaires en tijdens een incident kan het bericht dat wordt gezocht in een van deze formaten staan.

Dit pakket toont een kleine set concepten - over wie het bericht gaat, welk bezoek, welke studie, welke claim - op de plaats waar elk formaat ze bewaart, zodat een zoekopdracht kan zijn voor "MRN 12345" in plaats van voor een pad. De concepten zijn bewust weinig: dit zijn de dingen die mensen daadwerkelijk in hun hand hebben wanneer ze een bericht moeten vinden, wat een nummer van een telefoontje of een naam van een klacht is.

Waarom extractie één keer gebeurt, op recordtijd

Het alternatief is het parseren van payloads op querytijd, wat de expressiezoekopdracht doet. Dat werkt en het is eerlijk over het feit dat het een begrensde scan is, maar het kan niet beantwoorden "elk bericht over deze patiënt via vier feeds en twee maanden" zonder elke rij te lezen. Het één keer extraheren naar een geïndexeerde tabel verandert dat in een indexzoekopdracht.

Dit is een privacy-escalatie en het is optioneel

Patiëntnamen en -identificatoren zitten momenteel in een ondoorzichtige payloadkolom. Het indexeren ervan maakt ze zoekbaar, wat het doel is, en maakt ze ook opsombaar, wat een echte verandering in blootstelling is: een database die alleen kon worden doorzocht, kan nu worden gevraagd "lijst alle patiënten". Dat is een beslissing voor de site, niet voor dit pakket, dus extractie is in- en uitschakelbaar en elke zoekopdracht via het pakket wordt opgenomen in de PHI-auditlog.

Source: github.com/biodream-llc/perfuse/internal/identity

26.57 iis

Pakket iis spreekt het transport dat elke Amerikaanse immunisatieregistry deelt: de CDC's IIS-SOAP-webservice.

In 2011 koos een door de CDC en de American Immunization Registry Association bijeengeroepen expertpanel één SOAP-interface voor het indienen van HL7 v2-berichten bij Immunisatieregistry's, en de registry's namen het over. De WSDL is klein - twee bewerkingen, connectivityTest en submitSingleMessage - en het HL7-bericht (een VXU om een injectie te melden, een QBP^Q11 om de geschiedenis van een patiënt te vragen) reist als ontsnapte tekst binnen het SOAP-lichaam. Het antwoord komt op dezelfde manier terug: een ACK, of een RSP^K11 met de geschiedenis en de prognose.

De generieke SOAP-bestemming had kunnen worden geconfigureerd om dit te doen, maar elke site had hetzelfde omhulsel moeten typen, de naamruimte goed moeten krijgen, de referenties in het lichaam moeten plaatsen in plaats van in HTTP-verificatie, en vervolgens het HL7-acknowledgement uit het antwoord moeten lezen om te leren of de registry het record heeft bewaard. Een registry beantwoordt een geweigerde injectie met HTTP 200 en een AR; het behandelen van de 200 als succes is hoe immunisaties stilzwijgend falen om te worden gerapporteerd. Dus dit pakket doet het CDC-omhulsel en beoordeelt de bevestiging, één keer.

Wat het niet doet: de WSDL-gebruikersnaam en -wachtwoord zijn de toepassingsreferenties van de registry en worden verzonden zoals de WSDL zegt, in het lichaam. Wederzijdse TLS, waar een registry dit vereist, is de TLS-instelling van de bestemming, zoals voor elke HTTPS-aanroep. Niets hier is specifiek voor één staat; waar staten verschillen (faciliteits-ID vereist of niet, SOAP 1.1 geaccepteerd of niet, waarschuwingen verzonden als AE) zegt de bestemmingsinstelling zo.

Source: github.com/biodream-llc/perfuse/internal/iis

26.58 kafka

Kafka, als client in plaats van als iets om te vervangen.

Een gezondheidssysteem dat een evenementenruggengraat heeft, heeft een Kafka-ruggengraat, en de systemen die in het afgelopen decennium zijn gebouwd, publiceren naar het Kafka-systeem in plaats van naar een JMS-broker. Dus deze connector bestaat om Perfuse het gezondheidsbewuste rand van iemands evenementenplatform te maken: het leest klinische berichten van onderwerpen en publiceert ze naar onderwerpen, en het probeert bewust niet om een streamingplatform te zijn. Windowing, joins, streamverwerking en schemaregistry's zijn Kafka's ecosysteem en blijven daar.

Waarom een afhankelijkheid, wanneer STOMP en MLLP met de hand werden geschreven

De vermelde regel in dit repository is dat een afhankelijkheid capaciteit moet kopen in plaats van gemak, en moet zuiver Go zijn, zodat één statische binary nog steeds cross-compileert naar elk doel. franz-go is zuiver Go en draagt geen cgo, wat werd gecontroleerd tegen alle zes doelen.

Kafka's protocol is niet STOMP's. STOMP is een tekstprotocol dat in een paar honderd regels past. Kafka is een versiegebonden binaire protocol over ongeveer zeventig aanvraagtypen, en het deel dat hier het meest toe doet - consumentengroepen - is een gedistribueerd coördinatieprotocol met join-, sync-, heartbeat- en offset-commitfasen en een herbalansdans tussen hen. Het subtiel verkeerd krijgen van dit protocol produceert geen duidelijke fout: het produceert een partitie die niemand leest, of twee consumenten die dezelfde partitie lezen. In een klinische feed zijn dat een ontbrekend laboratoriumresultaat en een gedupliceerde order. Dat is capaciteit, en het is niet waard om handmatig te rollen om een afhankelijkheid te besparen.

Source: github.com/biodream-llc/perfuse/internal/kafka

26.59 ldap

Pakket ldap spreekt genoeg LDAP om een persoon te verifiëren en hun groepen te lezen.

Ziekenhuizen gebruiken vrijwel universeel Active Directory, en AD spreekt LDAP. OpenID Connect is het betere antwoord waar het bereikbaar is - zie internal/oidc, en de notitie daarover dat Mirth geen enkele aanmelding heeft, tegen welke prijs dan ook - maar een integratie-engine zit vaak op een geïsoleerd VLAN waar een browser geen identiteitsprovider kan bereiken. Daarvoor is dit bedoeld.

Handmatig gemaakte BER in plaats van een afhankelijkheid, om dezelfde reden als DICOM en STOMP: de codering is klein, en wat op deze socket aankomt, bepaalt of iemand toegang krijgt tot een systeem dat patiëntgegevens verplaatst.

encoding/asn1 in de standaardbibliotheek is hier niet bruikbaar. Het richt zich op DER en wijt de contextspecifieke tags en impliciete tagging die LDAP overal gebruikt, zodat de delen die ertoe doen toch met de hand moeten worden gemaakt.

Source: github.com/biodream-llc/perfuse/internal/ldap

26.60 postbus

Pakket postbus leest e-mail van IMAP4rev1- (RFC 3501) en POP3-servers (RFC 1939), meldt zich aan met een wachtwoord of met OAuth 2.0 (SASL XOAUTH2, zoals Microsoft 365 en Gmail vereisen) en maakt berichten uit elkaar (RFC 5322 en MIME) zodat een bijlage of de tekstbody een bericht op een kanaal kan worden.

Alleen wat een inkomende feed nodig heeft: selecteer een postbus, vind ongelezen e-mail, haal deze op, verplaats, markeer of verwijder deze. Alleen standaardbibliotheek; TLS is crypto/tls.

Source: github.com/biodream-llc/perfuse/internal/mailbox

26.61 mapper

Pakket mapper suggereert veldtoewijzingen tussen systemen met vertrouwensscores.

Dit is een regelgebaseerde intelligente mapping-engine. Geen LLM, geen netwerkoproepen, geen externe afhankelijkheden. Het draait offline in dezelfde binaire en stuurt nooit patiëntgegevens naar elders.

De engine combineert meerdere signalen - fuzzy string-matching op veldnamen, herkenning van patiëntgegevenspatronen, opzoeken van codesystemen en historische acceptatiegegevens - in één vertrouwensscore per suggestie. Wanneer de vertrouwensscore onder een instelbare drempel ligt, onthoudt de mapper zich van een suggestie in plaats van verkeerd te gokken, omdat een verkeerde toewijzing in de gezondheidszorg gegevens naar het verkeerde veld kan routeren en dat een patiëntveiligheidsdefect is.

Onthouding is de kernontwerpbeslissing. Een systeem dat altijd een antwoord produceert, leert gebruikers om te stoppen met controleren, en de ene keer dat het verkeerd is, merkt niemand het tot een laboratoriumresultaat in een notitieveld terechtkomt. Een systeem dat zegt "Ik weet het niet" dwingt een menselijke beslissing af exact op het moment dat de mens nodig is.

Source: github.com/biodream-llc/perfuse/internal/mapper

26.62 meting

Pakket meting evalueert FHIR-metingen (digitale kwaliteitsmetingen) waarvan de populatiecriteria FHIRPath zijn, en schrijft het resultaat als een FHIR-metingenrapport: samenvatting, individueel of onderwerp-lijst, met stratificators en een proportiescore.

Elk criterium wordt één keer per patiënt geëvalueerd, met de focus op een bundel van het patiëntendossier (hun compartiment) en deze variabelen: %onderwerp (de patiënt), %periodeStart en %periodeEinde (de meetperiode, als DateTime's) en %"Meetperiode" (hetzelfde als een Periode). Criteria in CQL worden geweigerd met de reden: Perfuse heeft geen CQL-engine.

Source: github.com/biodream-llc/perfuse/internal/measure

26.63 metrische gegevens

Pakket metrische gegevens verzamelt wat de engine doet en houdt voldoende geschiedenis bij om deze te tekenen.

Een interface-engine wordt bewaakt, niet alleen uitgevoerd. Wanneer een afdeling zegt dat resultaten twintig minuten geleden zijn gestopt met aankomen, is de vraag wat twintig minuten geleden is veranderd, en dat kan niet worden beantwoord door alleen de huidige tellers. Daarom worden reeksen in plaats van totale waarden bijgehouden, in het geheugen, met een vaste resolutie.

Drie beslissingen geven vorm aan het.

Vertraging wordt bijgehouden als een histogram in plaats van een gemiddelde. Een gemiddelde leveringstijd is bijna nutteloos in dit domein: het getal dat ertoe doet, is of de langzaamste paar procent van de berichten langzaam genoeg zijn om een omlooptijdverplichting te schenden, en een gemiddelde verbergt precies dat. Emmer zijn exponentieel en vastgesteld bij de buildtijd, dus het opnemen van een duur is een vergelijking en een verhoging zonder toewijzing.

Reeksen zijn begrensde ringbuffers, die zijn ingesteld wanneer de collector wordt gemaakt. Niets hier groeit zonder limiet, omdat een interface-engine maandenlang draait en een metrisch systeem dat opnieuw moet worden gestart, erger is dan geen.

Cardinaliteit is begrensd. Een labelwaarde die uit berichtgegevens wordt genomen - een verzendende toepassing, bijvoorbeeld - kan duizenden waarden aannemen als iemand een feed verkeerd configureert, en onbegrensde labels zijn de standaardmanier waarop bewaking het ding dat het bewaakt, naar beneden haalt. Na de limiet worden waarden samengevoegd in een "overig"-emmer en wordt de limiet zelf gerapporteerd.

Source: github.com/biodream-llc/perfuse/internal/metrics

26.64 mirth

Java-analyse voor geïmporteerde Mirth-kanalen.

Waarom dit bestaat

Mirth draait Rhino op de JVM, dus een Mirth-script kan elke Java op de classpath aanroepen, inclusief Mirth's eigen serverklassen. Perfuse draait goja en heeft geen Java-runtime. Het weigert die oproepen met een fout die de klasse noemt - maar die weigering gebeurt wanneer het script wordt uitgevoerd, wat voor een bronconnector betekent wanneer het eerste echte bericht aankomt.

Dus een migratie verliep gebruikelijk: de import slaagt er stilzwijgend in, het kanaal wordt geïmplementeerd, en het eerste bericht van de draad faalt. Een migratie die er schoon uitziet en bij de eerste verkeer breekt, is erger dan een die bij de deur weigert, omdat de persoon die het heeft gedaan, zijn collega's al heeft verteld dat het werkte.

Dit vindt die oproepen bij importtijd en zegt wat ermee moet gebeuren.

Waarom vier oordelen en niet twee

"Gebruikt Java" is één stukje informatie en het verkeerde, omdat de Java die een echte Mirth-kanaal gebruikt, valt in groepen met compleet verschillende hoeveelheden werk eraan vast. Ongeveer de helft van wat sites daadwerkelijk schrijven, is SimpleDateFormat en HashMap, die JavaScript native ondersteunt. Een deel ervan is de gedocumenteerde script-API van Mirth, die Perfuse al implementeert onder dezelfde namen. Een klein deel wil kanalen starten en stoppen, wat Perfuse kan doen via zijn REST-API, maar niet blootstelt aan scripts. En een deel is een vendor-jar die nooit hier zal draaien.

Het rapporteren van die als één nummer zegt een migrator niets over of hun middag of hun kwartaal op het spel staat.

Source: github.com/biodream-llc/perfuse/internal/mirth

26.65 mirthlive

Pakket mirthlive vindt de draaiende Mirth-motoren die de interoperabiliteitstests aanspreken.

Mirth Connect hield op open source te zijn bij 4.6 (maart 2025). De sites die het verlaten, gaan naar een van drie plaatsen: Mirth 4.5.2, de laatste open release, die ze blijven draaien; de Open Integration Engine, de Eclipse-gehoste fork; of BridgeLink, Innovar's fork, die zijn releases nummert per jaar (26.9.0). Een kanaal dat Perfuse exporteert, moet laden in alle drie, en een kanaal dat een van hen exporteert, moet hier importeren, dus elke live-test draait één keer per motor die antwoordt.

De motoren worden gevonden door te vragen, niet door configuratie: ./scripts/interop-up.sh start ze op vaste poorten, en een motor die niet draait, wordt gerapporteerd als overgeslagen in plaats van stilzwijgend door te gaan. PERFUSE_MIRTH_ENGINES overschrijft de lijst, als naam=URL-paren, gescheiden door komma's.

Alleen tests importeren dit. Het leeft buiten een _test.go-bestand omdat twee pakketten het delen.

Source: github.com/biodream-llc/perfuse/internal/mirth/mirthlive

26.66 mpi

Pakket mpi is een master patient index: het neemt patiëntrecords van elk bronsysteem (elk geïdentificeerd door zijn toewijzingsautoriteit en nummer), beslist welke bij dezelfde persoon horen, en geeft elke persoon een ondernemingsidentifier (EUID).

Bepaalde overeenkomsten koppelen vanzelf; onzekere wachten in een reviewwachtrij voor een persoon om te beslissen; elke koppeling, ontbinding, samenvoeging en beslissing wordt opgenomen met wie het heeft gedaan.

Overeenkomen is deterministisch eerst (een identifier van een systeem dat de site vertrouwt om uniek per persoon te zijn, zoals een nationaal identifier of een ondernemingsnummer) en probabilistisch anders: Fellegi-Sunter-gewichten over naam, geboortedatum, geslacht, postcode, telefoon en adres, met Jaro-Winkler voor namen. Het beslist niets klinisch: het zegt welke records dezelfde persoon zijn, met zijn redenen, voor een persoon om te bevestigen wanneer het niet zeker is.

Source: github.com/biodream-llc/perfuse/internal/mpi

26.67 mqtt

Pakket mqtt is een MQTT 3.1.1-client: verbind (met TLS, een gebruikersnaam en wachtwoord, of een clientcertificaat), publiceer op QoS 0 of 1, abonneer en bevestig elk ontvangen QoS 1-bericht slechts één keer wanneer de beller zegt dat het is verwerkt.

Geschreven tegen de OASIS MQTT 3.1.1-standaard in plaats van geïmporteerd, zoals de andere draadprotocollen van Perfuse. 3.1.1 is de versie die elke broker spreekt: Mosquitto, EMQX, HiveMQ, VerneMQ, RabbitMQ's MQTT-plugin, IBM MQ's telemetrie-kanaal, AWS IoT Core en Azure Event Grid.

Levering: een bericht dat op QoS 1 wordt ontvangen, wordt bevestigd (PUBACK) alleen wanneer Ack wordt aangeroepen. Een beller die een bericht niet kan verwerken, sluit de verbinding in plaats daarvan; met een persistente sessie (CleanSession false) stuurt de broker het opnieuw, gemarkeerd als een duplicaat, wanneer de client opnieuw verbinding maakt. MQTT 3.1.1 heeft geen negatieve bevestiging, dus dit is de enige manier om een bericht opnieuw te vragen.

Source: github.com/biodream-llc/perfuse/internal/mqtt

26.68 msgstore

Een opgeslagen bericht vinden door wat iemand ervan weet.

De zoekopdracht die een persoon daadwerkelijk nodig heeft, is "hier is een nummer van een telefoongesprek, toon me elk bericht erover". Voordat dit betekende dat het een substring-overeenkomst over payloads was, wat grep en langzaam is, of een filteruitdrukking, die vereist dat men weet dat identiteit op PID-3 in HL7 v2 leeft en elders geheel in de andere drie formaten op dezelfde server.

Identiteit wordt één keer geëxtraheerd wanneer het bericht wordt opgenomen en geïndexeerd, dus dit is een opzoeken in plaats van een scannen. De kosten worden betaald op het opnamepad, één keer per bericht, in plaats van op elke zoekopdracht.

Source: github.com/biodream-llc/perfuse/internal/msgstore

26.69 natid

Pakket natid kent de nationale patiënt- en persoonsidentificatoren van het VK en Europa: hun formaten, hun controlecijfers, het identifier-systeem dat elke landsgids van FHIR hen noemt, en hoeveel van een ervan getoond mag worden.

Het bestaat voor de patiëntindex. Een nationaal nummer is het sterkste bewijs dat twee records één persoon zijn, en ook het makkelijkst verkeerd te krijgen: een cijfer dat twee keer wordt ingetoetst, geeft een nummer dat bij iemand anders hoort, en één bron stuurt het NHS-nummer onder een OID, terwijl een andere het onder zijn FHIR-URL stuurt. Dus elke identifier die de index opslaat, gaat hierdoorheen: zijn controlecijfer wordt getest (een verkeerd cijfer wordt nooit gebruikt om te koppelen), zijn spaties worden verwijderd, en zijn systeem wordt op één manier geschreven.

Wat wordt geverifieerd en wat niet, wordt per schema gezegd. De algoritmes zijn openbaar; de identifier-systeem-URI's zijn die van het land waar een nationale FHIR-gids er een noemt (SystemVerified), en een gedocumenteerde standaard anders, die een site kan veranderen in zijn nationale waarde onder Instellingen → Patiëntindex. Niets hier beslist iets klinisch.

Source: github.com/biodream-llc/perfuse/internal/natid

26.70 ncpdp

Een veld schrijven in een NCPDP-transmissie.

Waarom een schrijfbewerking een dubbelzinnige pad weigert

Lezen retourneert elke waarde die een pad aanspreekt, omdat een filter dat vraagt of er een DUR-conflict is, zoals een therapeutische duplicatie, allemaal moet zien. Een schrijfbewerking kan niet op die manier werken. Als D7 de productcodes van twee claims in één transmissie aanspreekt, heeft het instellen van D7 geen enkele betekenis: het schrijven van beide zou een medicijn veranderen waar niemand om heeft gevraagd, en het schrijven van de eerste zou de tweede stilzwijgend laten staan.

Dus een schrijfbewerking weigert een pad dat meer dan één veld aanspreekt, en de fout noemt de gekwalificeerde vorm die ondubbelzinnig zou zijn. Dit is dezelfde redenering die de transformatiestappen geen verwijderactie geeft: waar het eerlijke antwoord is dat de configuratie dubbelzinnig is, is het beter om dat te zeggen dan een keuze te maken.

Source: github.com/biodream-llc/perfuse/internal/ncpdp

26.71 oidc

Pakket oidc verifieert OpenID Connect-identiteiten.

Geschreven tegen de standaardbibliotheek in plaats van een JWT-afhankelijkheid. Authenticatie is de enige plaats waar een ongecontroleerde afhankelijkheid het minst acceptabel is, handtekeningverificatie voor de algoritmen die ertoe doen is ongeveer honderd regels crypto/rsa en crypto/ecdsa, en Perfuse draagt al genoeg om nog meer toe te voegen zonder reden.

De reikwijdte is opzettelijk smal: verifieer dat een identiteitsprovider voor een persoon heeft getekend en rapporteer wat het over hen heeft gezegd. Alles anders - wat ze mogen doen, hoe lang de sessie duurt - blijft bij Perfuse, omdat een identiteitsprovider weet wie iemand is en niet wat ze mogen doen in een interface-engine.

Source: github.com/biodream-llc/perfuse/internal/oidc

26.72 pariteit

Pakket parity vergelijkt wat Perfuse produceert met wat de engine die wordt vervangen produceerde.

Waarom dit bestaat

Perfuse kan een Mirth-kanaal importeren en kan traceren wat het met een bericht zou doen. Geen van beide beantwoordt de vraag die iemand eigenlijk heeft voordat hij een live-feed verplaatst, namelijk: zal dit hetzelfde resultaat opleveren als het ding dat al zes jaar draait?

Geen enkele hoeveelheid ontwerp-kwaliteit beantwoordt dat. Het enige eerlijke antwoord is bewijs, en dat bewijs moet komen van de output van de oude engine op de site-eigen verkeer.

Waarom de paren moeten worden geleverd

Dit kan niet in Mirth kijken en doen alsof het dat wel kan, zou de slechtste soort functie zijn. Wat het nodig heeft, zijn paren: een bericht zoals het is aangekomen, en het bericht dat de oude engine heeft gegenereerd uit dat bericht. Beide zijn in Mirths eigen berichtenopslag en kunnen worden geëxporteerd uit zijn berichtenbrowser, wat iets is dat een beheerder al weet hoe hij het moet doen.

Die beperking wordt gesteld in plaats van verborgen. Een hulpmiddel dat beweert een migratie te verifiëren zonder ooit de output van de oude engine te zien, zou niets verifiëren.

Waarom verschillen worden gegroepeerd in plaats van opgesomd

Een run van vijftigduizend berichten die vierduizend verschillen rapporteert, heeft iemand niets verteld dat hij kan gebruiken. Dezelfde run die rapporteert dat PID-8 in elk bericht verschilt omdat de oude engine M naar Male heeft toegewezen, heeft hem precies één ding verteld om over te beslissen.

Dus bevindingen worden gegroepeerd per veld, met een telling, een voorbeeld en de unieke waardeparen die zijn gezien. Één beslissing per bevinding is de eenheid die iemand kan doorwerken.

Source: github.com/biodream-llc/perfuse/internal/parity

26.73 pas278

Pakket pas278 kaart tussen Da Vinci-prioritaire autorisatie en de X12 278-transactie.

Waarom dit bestaat

CMS-0057-F vereist dat betalers een FHIR-prioritaire autorisatie-API blootstellen vanaf 1 januari 2027. Het vervangt de X12 278 niet, en het was nooit de bedoeling: een betalers utilisatiebeheersysteem beslist over autorisaties en spreekt 278. Dus een betaler die de regel naleeft, vertaalt FHIR naar 278 en terug, en een aanbieder die vandaag 278 verstuurt, zal morgen FHIR naar dezelfde betalers sturen die nog steeds beide accepteren.

Die vertaling is het ding dat het waard is om te bezitten. Een engine die beide modellen vasthoudt en niet tussen hen kan converteren, laat het moeilijkste deel van het werk - en het deel waar de fouten duur zijn - over aan degene die het integreert.

De regels die dit pakket volgt, gesteld in plaats van geïmpliceerd

Opgeschreven om dezelfde reden waarom v2fhir zijn eigen opschrijft: mapping is waar interoperabiliteitsprojecten falen, en de fouten zijn stil.

Source: github.com/biodream-llc/perfuse/internal/pas278

26.74 pdf

Pakket pdf maakt eenvoudige tekstdocumenten, met gebruik van alleen de standaardbibliotheek.

Mirth's Document Writer rendert HTML naar PDF, wat een lay-outengine nodig heeft. Dat is niet wat dit is. Dit produceert een eenvoudig, gepagineerd tekstdocument met een monospaced lettertype, en het bestaat omdat de daadwerkelijke vereiste bij bijna elke site die deze connector gebruikt "deze rapportage op een share zetten zodat iemand het kan afdrukken" is - een ontslagverslag, een resultaatrapport, een dagelijkse verificatie. Die zijn tekst.

Het weigeren van de functionaliteit zou een Tier 2-migratieblokkerer achterlaten. Het opnemen van een HTML-renderengine zou meer kosten dan de rest van de binaire code en zou een CVE-stroom met zich meebrengen, wat het argument van de materiaallijst zou tenietdoen. Dus: tekst, eerlijk omschreven als tekst, en een site die echt typeset-uitvoer nodig heeft, is beter bediend door een bestemming en een tool die daarvoor is gebouwd.

Waarom een PDF schrijven in plaats van een tekstbestand

Omdat de ontvangende kant meestal een persoon met een printer en een Windows-share is, en een .txt-bestand dat van een share wordt afgedrukt, zijn paginering, marges en vaak zijn lijneinden verliest. Een PDF wordt overal hetzelfde afgedrukt, en dat is de enige reden waarom iemand ernaar heeft gevraagd.

Source: github.com/biodream-llc/perfuse/internal/pdf

26.75 pgp

Pakket pgp versleutelt, ondertekent, ontsleutelt en verifieert OpenPGP-berichten (RFC 9580 en RFC 4880 voor oudere peers), voor betalers, clearinghouses en overheidsinstanties die bestanden uitwisselen via SFTP of e-mail onder PGP.

De cryptografie is github.com/ProtonMail/go-crypto, de onderhouden fork van golang.org/x/crypto/openpgp; niets hier implementeert een primitief. Dit pakket laadt alleen sleutels en beslist wat een bericht moet bevatten.

Source: github.com/biodream-llc/perfuse/internal/pgp

26.76 pixv3

Pakket pixv3 is het HL7-versie 3-gezicht van de patiëntindex: de IHE Patient Identifier Cross-referencing en Patient Demographics Query-profielen, zoals de meeste ziekenhuizen buiten de FHIR-wereld nog steeds spreken.

De antwoorden komen uit dezelfde patiëntindex als PIXm, PDQm, Patient/$match en het indexscherm, dus een record dat via v3 wordt gevoed, wordt gevonden via FHIR en omgekeerd. De berichten zijn handmatig geschreven, in schema-volgorde, vanwege de reden hl7v3.Ack.

Source: github.com/biodream-llc/perfuse/internal/pixv3

26.77 priorauth

Pakket priorauth implementeert de provider-zijde van de prior-authorization-workflow die vereist is door CMS-0057. Het verzendt prior-auth-verzoeken naar payer FHIR-API's, volgt antwoorden en converteert tussen interne typen en FHIR-bronnen.

Source: github.com/biodream-llc/perfuse/internal/priorauth

26.78 privacy

Pakket privacy beantwoordt de verzoeken van een gegevensonderwerp onder de GDPR en de UK GDPR: vind alles wat deze server over een persoon bewaart, geef het aan hen (Artikelen 15 en 20), wis het (Artikel 17) en bewaar wat een wettelijke hold dekt.

Het bereikt elke plaats waar Perfuse patiëntgegevens bewaart: de berichtenopslag (via zijn identiteitsindex), de leveringswachtrij, de FHIR-opslag (de patiëntbronnen en alles wat naar hen verwijst, met hun geschiedenis), opgeslagen prior-authorization-verzoeken en de patiëntindex, waarvan de links één identificator uitbreiden tot alle nummers van de persoon. Wat het niet kan bereiken, noemt het: sporen die naar een collector worden verzonden, het auditlog (bewaard, als het record van wie wat deed) en back-ups, die bewaren wat werd gewist totdat ze verlopen - dus elke wisbewerking wordt geschreven naar een ledger, als gesaldeerde hashes van de identificators in plaats van de identificators, en kan opnieuw worden toegepast op een herstelde kopie.

Het neemt geen beslissingen namens iemand. Of een verzoek moet worden toegekend en of een vrijstelling van toepassing is, is de beslissing van de controller; wisbewerkingen vereisen de goedkeuring van een tweede beheerder en een wettelijke hold weigert het rechtstreeks.

Source: github.com/biodream-llc/perfuse/internal/privacy

26.79 publichealth

Pakket publichealth implementeert bidirectionele openbare gezondheidsrapportage: elektronische casusrapportage (eCR), elektronische laboratoriumrapportage (ELR) en immunisatieregistry-vragen.

Elk ziekenhuis is wettelijk verplicht bepaalde aandoeningen te melden - tuberculose, mazelen, hepatitis, COVID-19, seksueel overdraagbare infecties, voedselgebonden ziekte - aan overheidsinstanties voor volksgezondheid. De rapportage gebeurt via drie verschillende interfaces:

Het pakket is bidirectioneel: het rapporteert naar buiten (ELR, eCR, VXU) en vraagt terug (VXQ/VXR). Alle bewerkingen zijn in real-time in plaats van 's nachts in batch.

Threadveiligheid: SubmissionLog is veilig voor gelijktijdig gebruik. De builder-functies zijn zuiver en veilig om op te roepen vanuit elke goroutine.

Source: github.com/biodream-llc/perfuse/internal/publichealth

26.80 published

Pakket published bevat de bewakers voor de importeerbare pakketten van Perfuse, op één plaats.

hl7 was het eerste pakket dat werd gepubliceerd en bevat zijn eigen kopie van deze controles. fhir en pas werden gepubliceerd zodat een beslissingsdienst zoals Vaglio FHIR- en PAS-verzoeken leest met exact dezelfde code die Perfuse gebruikt, in plaats van een kopie die afwijkt: vier lezers van de X12-actiecodes in dit repository waren het eerder oneens, en één las een weigering als een goedkeuring. De bewakers worden hier bewaard in plaats van gekopieerd naar elk pakket, om dezelfde reden.

Source: github.com/biodream-llc/perfuse/internal/published

26.81 queue

Pakket queue is een duurzame, per-bestemming leveringswachtrij.

Zonder dit, verliest een bestemming die twee minuten uit de lucht is alles wat tijdens die twee minuten wordt verzonden: retries gebeuren in het geheugen, en wanneer ze op zijn, wordt het bericht als mislukt geregistreerd en verdwenen. Met dit, staat het bericht op schijf en behoudt het zijn plaats totdat de bestemming weer online komt.

Twee ontwerpbeslissingen bepalen alles wat volgt.

De volgorde wordt per bestemming bewaard, en dat betekent dat een bestemming in de wachtrij geen snelle route meer neemt. HL7 is een stroom van gebeurtenissen over dezelfde patiënten: een A01 geeft op, een A03 ontslaat. Als een mislukte A01 naar de wachtrij gaat terwijl de volgende A03 rechtstreeks wordt afgeleverd, ziet het ontvangende systeem een ontslag voor een patiënt die nooit is opgenomen. Dus, zodra iets voor een bestemming in de wachtrij staat, wacht alles voor die bestemming tot de wachtrij leeg is. Dat kost doorvoer tijdens een storing en is niet optioneel, omdat het alternatief stil klinisch onzin is. Het is ook het specifieke ding dat misgaat in andere motoren wanneer iemand gelijktijdige wachtrijdraden inschakelt om een achterstand sneller te laten afvloeien.

Een bericht in de wachtrij is een geaccepteerd bericht. De verzender krijgt AA, omdat de bytes op schijf staan en zijn gesynchroniseerd voordat de bevestiging wordt verzonden. AE zeggen zou een correct functionerende opslag- en doorstuurwachtrij doen lijken als een fout en de verzender uitnodigen om opnieuw te verzenden wat we al in bezit hebben.

Source: github.com/biodream-llc/perfuse/internal/queue

26.82 verblijf

Pakketverblijf zegt waar de gegevens van deze server naartoe mogen gaan: de cloudregio's die een site toestaat (de EEA, het VK, Zwitserland of regio's die één voor één zijn genoemd), en of de regio van een connector een van hen is.

Perfuse controleert wat het kan weten. Een AWS-connector noemt zijn regio (S3, SQS, SNS), en een AWS-hostnaam draagt er een (sqs.eu-west-2.amazonaws.com); die worden gecontroleerd wanneer een kanaal wordt opgeslagen en geladen, zodat een kanaal geen patiëntgegevens naar een bucket in Virginia kan verzenden vanaf een server waarvan de gegevens in Frankfurt moeten blijven. Een gewone hostnaam (een eigen systeem van een ziekenhuis, een MLLP-luisteraar van een partner) zegt niets over waar het is, en wordt hier niet beoordeeld: het verwerkingsrecord vermeldt elke host waarnaar een kanaal verzendt, voor de controller om te controleren.

Source: github.com/biodream-llc/perfuse/internal/residency

26.83 rtpb

Pakket rtpb beantwoordt NCPDP Real-Time Prescription Benefit-aanvragen vanuit een formularium: wat een medicijn voor deze lid bij deze apotheek zal kosten, of het een voorafgaande autorisatie of een stap eerst nodig heeft, en welke alternatieven minder kosten.

CMS-0062-P stelt RTPB voor vanaf 1 oktober 2027 voor getroffen verzekeraars. De XML is NCPDP RTPB v13 (PBv13). De schema van NCPDP is gelicentieerd, dus volgen elementnamen en -volgorde de openbare Surescripts RTPB-voorbeelden en de openbare NCPDP RTPB-implementatieaanbevelingen (codes voor dekkingbeperkingen en de dekkingstatus waaraan elk is toegewezen); een antwoord wordt hier niet gecontroleerd tegen het XSD, en een netwerkcertificering is waar dat gebeurt.

Source: github.com/biodream-llc/perfuse/internal/rtpb

26.84 s3put

Pakket s3put schrijft objecten naar S3 met alleen de standaardbibliotheek.

De meest voor de hand liggende manier om met S3 te communiceren is de AWS SDK, en de SDK is enorm. Dit project verkoopt een statische binaire bestand met acht directe afhankelijkheden en een materiaallijst die op één scherm past - dat is een echt argument met de persoon die software beoordeelt voordat een ziekenhuis het installeert, en het inruilen voor één connector zou een slechte koop zijn.

Wat S3 eigenlijk nodig heeft, is een HTTP PUT en een handtekening. Handtekeningversie 4 is volledig gespecificeerd, het is deterministisch en AWS publiceert testvectoren ervoor. Dus het is hier geïmplementeerd: ongeveer tweehonderd regels tegen crypto/hmac en net/http, met geen nieuwe afhankelijkheid en niets om te patchen wanneer de SDK een advies heeft.

Wat dit expres niet doet

Geen multipart-upload, geen retries van zichzelf, geen credential-keten buiten statische sleutels en de standaardomgevingsvariabelen. Een HL7-bericht is kilobytes, dus multipart lost een probleem op dat dit niet heeft; de motor retries al; en een instantie-rol-credential-keten zou IMDS-aanroepen, caching en vernieuwingslogica betekenen, wat is waar een kleine implementatie ophoudt klein te zijn. Als iemand die dingen nodig heeft, is het eerlijke antwoord een bestemming voor een bestand en een synchronisatietool, niet een halfgebouwde SDK.

Het werkt met alles dat de S3-API spreekt - MinIO, Ceph, Wasabi, Backblaze - omdat het alleen ondertekende HTTP is. Dat is een neveneffect dat het waard is, aangezien een ziekenhuisobjectopslag vaak niet AWS is.

Source: github.com/biodream-llc/perfuse/internal/s3put

26.85 saml

Exclusieve XML-canonicalisatie (exc-c14n) per https://www.w3.org/TR/xml-exc-c14n/

Dit is de byte-exacte canonieke vorm die een XML-handtekening ondertekent. Het verkeerd krijgen betekent dat geldige handtekeningen ongeldig lijken en - erger - een implementatie die het meestal goed krijgt, zal slagen in testen tegen zijn eigen handtekeningen, maar echte IdP-antwoorden afwijzen.

De regels die ertoe doen voor SAML: - Naamruimteverklaringen worden alleen weergegeven als ze zichtbaar worden gebruikt door het element of zijn attributen. - Geërfde naamruimten die een element gebruikt maar niet heeft verklaard, worden weergegeven alsof ze op dat element zijn verklaard. - Attributen zijn gesorteerd: naamruimteverklaringen eerst (gesorteerd op voorvoegsel), dan andere attributen (gesorteerd op uitgebreide naam: naamruimte-URI dan lokale naam). - Lege elementen gebruiken start-tag/eind-tag, nooit zelfsluitend. - Tekstknooppunten worden letterlijk uitgevoerd; CDATA wordt vervangen door de inhoud met entiteitontsnapping. - Verwerkingsinstructies en opmerkingen buiten het documentelement worden uitgesloten.

Source: github.com/biodream-llc/perfuse/internal/saml

26.86 scim

Pakket scim implementeert SCIM 2.0, het protocol dat identiteitsproviders gebruiken om accounts in te richten.

Okta, Entra ID, Google Workspace en OneLogin spreken deze taal allemaal. Een beheerder voegt iemand toe aan een groep in de identiteitsprovider en binnen een minuut verschijnt hier een account met de juiste rol. Ze verwijderen deze persoon en het account verdwijnt.

Deprovisioning is het punt

Inrichten is gemak. Deprovisioning is de reden waarom dit het bouwen waard is, en het is de helft die misgaat.

Wanneer iemand een organisatie verlaat, is de identiteitsprovider het systeem dat het eerste weet - meestal omdat HR de persoon beëindigt en de provider wordt aangedreven door het HR-record. Vervolgens wordt elke verbonden applicatie opgedragen om het account te deactiveren. Als deze oproep mislukt of slaagt zonder daadwerkelijk de toegang te verwijderen, behoudt een voormalig werknemer werkt toegang tot een klinische integratie-engine en niemand ontdekt het, omdat niets toezicht houdt op iets dat niet is gebeurd.

Dus de onderdelen van dit pakket die het meest belangrijk zijn, zijn degenen die deprovisioning werkelijk maken:

Waarom het een afzonderlijk pakket is

SCIM's vormen zijn niet die van Perfuse. Het heeft zijn eigen foutformaat, zijn eigen lijstomhulsel, zijn eigen patchtaal en zijn eigen meningen over attribuutgevallen. Het houden van de vertaling op één plaats betekent dat de handlers kunnen gaan over wat er met een account gebeurt, in plaats van over JSON.

Source: github.com/biodream-llc/perfuse/internal/scim

26.87 script

Pakket script voert Mirth Connect JavaScript uit.

Het doel is dat de scripts van een kanaal ongewijzigd worden overgezet. Dat is een compatibiliteitsuitoefening, geen ontwerpuitoefening, dus de vorm van alles hier wordt bepaald door wat Mirth blootstelt: msg en tmp als E4X-bomen, zes kaarten met Java's Map-methoden, de $-familie van lookup-functies, logger en een handvol utility-objecten waarvan de methode-namen en datumformaat-strings Java's zijn.

Drie beslissingen zijn de onze, in plaats van die van Mirth, en elk is een bewuste afwijking:

Een script wordt uitgevoerd met een deadline en wordt onderbroken wanneer deze wordt overschreden. Mirth laat een script oneindig doorlopen, wat het kanaal meeneemt; een interface die ophoudt met het accepteren van opnames vanwege een typefout in een transformatie is niet acceptabel, dus er is altijd een time-out.

Java-interoperabiliteit wordt geweigerd met een fout die de klasse noemt, in plaats van ongedefinieerd terug te geven. Een script dat reikt in Packages.java.sql, kan hier niet worden gemaakt om te werken, en het nuttige resultaat is een bericht dat precies dat zegt op de regel waar het gebeurt, niet een NullPointerException drie regels later.

Bestand- en database-toegang zijn uitgeschakeld, tenzij een kanaal ze inschakelt. Mirth verleent beide aan elk script standaard. Een transformatie die elk bestand kan lezen dat het proces kan lezen, is een redelijke zaak om te willen en een onredelijke standaard.

Source: github.com/biodream-llc/perfuse/internal/script

26.88 instellingen

Pakket instellingen is de enige beschrijving van alles over een Perfuse-server dat een operator kan wijzigen.

Waarom dit bestaat

Voordat dit pakket, waren ongeveer dertig dingen opdrachtregelvlaggen en niets anders. Het wijzigen van de tijd dat berichten worden bewaard, betekende het bewerken van een servicedefinitie en opnieuw opstarten, wat in een ziekenhuis een wijzigingsticket betekent - dus in de praktijk veranderde niemand ze, en een standaard die op de eerste middag werd gekozen, werd de instelling voor altijd.

Waarom één register in plaats van een formulier

De voor de hand liggende manier om een instellingenpagina te bouwen, is het schrijven van het formulier. Dat produceert twee beschrijvingen van elke instelling - één in de server die het valideert en één in de interface die het weergeeft - en ze drijven uit elkaar. De drijving is stil: een veld dat de server niet meer accepteert, heeft nog steeds een besturingselement, dus iemand stelt het in, ziet het worden opgeslagen en het doet niets.

Dus een instelling wordt één keer verklaard, hier, met alles wat nodig is om het zowel te controleren als weer te geven: wat voor soort waarde het is, welk besturingselement het past, in welke groep het thuishoort, wat het betekent en of het wijzigen ervan onmiddellijk effect heeft. De interface vraagt om die beschrijving en geeft weer wat het wordt verteld. Het toevoegen van een instelling is één entry in dit pakket en helemaal geen interface-werk.

TestEverySettingIsFullyDescribed dwingt de onderdelen af die een mens moet leveren, omdat een instelling zonder helptekst een instelling is waar iemand naar moet raden.

Waarom een bestand in plaats van de database

Instellingen wonen in een YAML-bestand dat de interface bewerkt op zijn plaats, overeenkomstig met hoe kanalen en waarschuwingsregels al werken. Drie redenen, in volgorde van gewicht: een ziekenhuis wil configuratie die kan worden gediffd en in versiebeheer kan worden geplaatst; een operator met de machine maar niet de applicatie kan een bestand lezen en kan geen database lezen; en het herstellen van de instellingen van gisteren moet niet vereisen dat de applicatie werkt.

Waarom alleen vlaggen zaaien

Het bestand wint zodra het bestaat, en vlaggen leveren de initiële inhoud. De alternatieve optie - vlaggen die altijd winnen - zou de interface een leugenaar maken, aangezien alles dat ooit op een opdrachtregel is doorgegeven, kan worden bewerkt en opgeslagen en stilzwijgend genegeerd.

Een vlag die in conflict is met het bestand, wordt bij het opstarten gemeld, met vermelding van beide waarden, omdat de vlag anders jarenlang in de servicedefinitie blijft staan en de volgende persoon die het leest, het gelooft.

Source: github.com/biodream-llc/perfuse/internal/settings

26.89 sftpconn

Pakket sftpconn opent SFTP-verbindingen.

Uit de connectors gesplitst omdat het interessante deel authenticatie en hostkeyverificatie is, en beide identiek zijn of een kanaal nu bestanden verzamelt of schrijft. Twee kopieën zouden afwijken, en het deel dat afweek, zou het deel zijn dat de verificatie stopte.

Source: github.com/biodream-llc/perfuse/internal/sftpconn

26.90 schaduw

Pakket shadow vergelijkt een kandidaatkanaal met het livekanaal.

De vergelijking zelf is het gemakkelijke deel. De hele waarde zit in twee garanties, en beide worden afgedwongen door constructie in plaats van door configuratie:

Iets minder dan dat en shadowmodus wordt een manier om productie te breken terwijl je probeert productie te vermijden.

Source: github.com/biodream-llc/perfuse/internal/shadow

26.91 shl

Pakket shl implementeert SMART Health Links en SMART Health Cards: de QR-codes die CMS's 'Kill the Clipboard' aanbieders vraagt te accepteren bij het inchecken en om terug te geven met het bezoekrecord.

Een SMART Health Link (SMART Health Links STU 1) is shlink:/ gevolgd door base64url JSON: een manifest-URL, een 256-bitsleutel en optioneel een verloopdatum, een label en vlaggen (P wachtwoord, L langdurig, U een enkel bestand via GET). De ontvanger plaatst een bericht op de manifest-URL en krijgt bestanden terug, elk een JWE-versleuteld met die sleutel - alg dir, enc A256GCM, optioneel DEFLATE-gecomprimeerd - die FHIR JSON, SMART Health Cards of een SMART-toegangstoken bevatten. De server die de bestanden host, ziet de sleutel nooit: deze reist alleen in de link, die van de patiënt is.

Een SMART Health Card (SMART Health Cards Framework 1.4) is een ondertekend FHIR-bundle: een compacte JWS, ES256, met een DEFLATE-gecomprimeerde payload die de uitgever noemt, waarvan de openbare sleutel staat op <iss>/.well-known/jwks.json. Het reist als een numerieke shc:/ QR-code of een .smart-health-card-bestand.

Alleen de standaardbibliotheek: crypto/aes, crypto/cipher, crypto/ecdsa en compress/flate dekken alles, en een JOSE-bibliotheek zou een veel grotere oppervlakte voor twee algoritmen meebrengen.

Source: github.com/biodream-llc/perfuse/internal/shl

26.92 smartauth

Pakket smartauth is een SMART App Launch-autorisatieserver: het geeft de toegangstokens uit die de FHIR-eindpunten van Perfuse accepteren.

Geschreven tegen de standaardbibliotheek, net als internal/oidc, die verifieert wat dit ondertekent. De tokens zijn JWT's ondertekend met RS256, het enige algoritme waarop elke SMART-client en de ID-tokenregels van de specificatie kunnen vertrouwen.

Source: github.com/biodream-llc/perfuse/internal/smartauth

26.93 snmp

Pakket snmp is een kleine, alleen-lezen SNMPv2c-agent: GET, GETNEXT en GETBULK via UDP tegen een tabel met waarden die de beller invult, en SNMPv2-valstrikken.

Berichten zijn hier BER (X.690) gecodeerd; er zit niets in wat cryptografie is (de community-string van v2c is een platte-tekstwachtwoord, en dat is waarom de agent alleen antwoordt op de netwerken die het wordt verteld).

Source: github.com/biodream-llc/perfuse/internal/snmp

26.94 soap

Pakket soap verzendt SOAP-aanvragen en leest SOAP-fouten, met alleen de standaardbibliotheek.

SOAP is een behoorlijke hoeveelheid ceremonieel rond een HTTP-POST, en het is nog steeds hoe een groot deel van het ziekenhuismiddleware gegevens accepteert - patiëntbeheersystemen, documentenopslag, regionale recordservices, alles wat is gespecificeerd in het decennium waarin dit het antwoord was. Mirth heeft een Web Service-connector, dus dit is een Tier 2-migratieblokker in plaats van een leuk-om-te-hebben.

Waarom geen gegenereerde client

De gebruikelijke aanpak is om een WSDL te nemen en Go-typen te genereren op basis daarvan. Dat is het juiste antwoord voor een toepassing die met één bekende service praat, en het verkeerde antwoord hier: het doel van een integratie-engine wordt geconfigureerd door iemand die een kanaal bewerkt, niet herschreven, dus de envelop moet worden samengesteld op runtime uit een sjabloon dat ze kunnen zien en veranderen. Het betekent ook dat er geen codegeneratiestap is en niets om opnieuw te genereren wanneer de andere kant een nieuwe WSDL publiceert.

Wat dit expres niet doet

Geen WSDL-parsing, geen WS-Beveiliging, geen MTOM, geen WS-Adressering. Elk van deze zijn een specificatie op zich en doen alsof je er een ondersteunt terwijl je een detail verkeerd doet, is erger dan het niet aanbieden - een handtekening die bijna geverifieerd is, is niet te onderscheiden van een aanval aan de andere kant. WS-Beveiliging in het bijzonder is waar een half-implementatie echt schade kan aanrichten.

Wat hier is: SOAP 1.1- en 1.2-omhulsels, een gesjabloneerd lichaam, de SOAPAction-header en foutdetectie die de foutstring leest in plaats van '500' te melden.

Source: github.com/biodream-llc/perfuse/internal/soap

26.95 sof

Pakket sof voert SQL uit op FHIR v2 ViewDefinitions: een weergave zet elke FHIR-bron van een bepaald type om in rijen met benoemde kolommen, met FHIRPath, zodat FHIR-gegevens kunnen worden gelezen als tabellen door SQL-motoren, spreadsheets en kwaliteitsmaatstaven.

Het volgt de verwerking algoritme van de ViewDefinition (kolom, selecteer, forEach, forEachOrNull, herhaal, unionAll, waar, constanten, %rowIndex, getResourceKey en getReferenceKey) en wordt gecontroleerd tegen de officiële sql-on-fhir test fixtures.

Source: github.com/biodream-llc/perfuse/internal/sof

26.96 sqldb

Pakket sqldb opent databaseverbindingen voor de databasebron en -bestemming.

De stuurprogramma's worden hier geregistreerd en nergens anders, dus er is precies één plek die bepaalt waarmee Perfuse verbinding kan maken.

Source: github.com/biodream-llc/perfuse/internal/sqldb

26.97 sqlitedb

Pakket sqlitedb opent SQLite op de manier zoals een server het nodig heeft: één verbinding voor schrijven en meerdere voor lezen.

De reden is een foutmodus die alleen verschijnt als een implementatie al een tijdje draait. SQLite in WAL-modus laat lezers naast een schrijver lopen, maar Go's verbindingpool zit boven SQLite, dus een pool van één serialiseert alles ongeacht wat de database zou toelaten. Een berichtenbrowserzoeking die de payloadkolom scant, houdt dan de enige verbinding vast en elk aankomend bericht wacht erachter.

Gemeten op deze machine, duurt een schrijfoperatie 104 µs als de opslag inactief is en 2,6 ms terwijl een zoekopdracht vierduizend berichten scant: 25 keer langzamer. Dit schaalt met de tabel, dus bij een paar honderdduizend opgeslagen berichten verandert een rapport in seconden van leveringslatentie en is een schrijfoperatie op het erkenningspad. De afzender ziet een time-out, verzendt opnieuw en iemand spendeert een ochtend aan het zoeken naar een probleem in het netwerk.

Het splitsen van de pools kost niets en verwijdert de interactie: rapporten krijgen hun eigen verbindingen en de schrijver houdt er één voor zichzelf omdat SQLite precies één schrijver toestaat.

Source: github.com/biodream-llc/perfuse/internal/sqlitedb

26.98 stappen

Declaratieve transformatiestappen, voor elk berichtformaat.

Waarom dit gedeeld is

De stapvocabulaire - instellen, kopiëren, wissen, toewijzen, vervangen, bijsnijden, geval, elk met een beschrijving en een optionele voorwaarde - heeft niets te maken met een bepaald formaat. Alleen drie dingen verschillen tussen formaten: hoe een pad wordt geschreven, hoe een waarde wordt gelezen en hoe deze terug wordt geschreven.

Dit is dezelfde conclusie die de filtergrammatica bereikte in internal/expr, en om dezelfde reden. X12 had een stapengine en NCPDP had er een nodig; het kopiëren ervan zou een tweede vierhonderd-regel-engine hebben opgeleverd om handmatig bij te houden, en vervolgens een derde voor gescheiden. Het gedrag dat de moeite waard is, is subtiel genoeg dat een kopie het niet zou behouden - de reden waarom het resultaat na elke schrijfoperatie opnieuw wordt gelezen, bijvoorbeeld, nam een echte fout om te ontdekken.

Wat een formaat levert

Een Toegangsbeheerder: een padcompiler, een voorwaardecompiler en een optionele veto op stappen die het niet kan nakomen. Niets anders.

Source: github.com/biodream-llc/perfuse/internal/steps

26.99 stomp

Pakket stomp spreekt STOMP 1.2 met een berichtenbroker.

Dit is wat 'JMS-ondersteuning' moet betekenen in een programma dat geen Java is. JMS is een API in plaats van een protocol, dus er is niets om te implementeren: wat een site nodig heeft, is dat Perfuse met de broker praat die achter hun JMS-toepassingen zit.

STOMP in plaats van OpenWire, en de redenering is het opnemen waard omdat het voor de hand liggende antwoord verkeerd is. OpenWire is ActiveMQ's native protocol en een binaire serialisatie van JMS-opdrachten - weken van werk, specifiek voor één brokerfamilie en ongedocumenteerd behalve door de implementatie. ActiveMQ detecteert STOMP, AMQP en MQTT automatisch op dezelfde poort die het voor OpenWire gebruikt, dus een tekstprotocol bereikt dezelfde brokers. STOMP dekt ActiveMQ Classic, Artemis en RabbitMQ; AMQP 1.0 zou Azure Service Bus en IBM MQ toevoegen en is de verstandige volgende keuze in plaats van OpenWire.

Geschreven tegen de standaardbibliotheek. Een brokerclient is niet de plaats voor een afhankelijkheid waarvan de foutmodi iemand anders moeten uitleggen, en de framing hier is klein genoeg dat het bezitten ervan minder kost dan het lezen van hun issue tracker.

Source: github.com/biodream-llc/perfuse/internal/stomp

26.100 opslag

Het pakketopslag bevat de gegevens die echt statusvol zijn: gebruikers, sessies en een audittrail.

Kanalen zijn expres niet hierin opgenomen. Ze worden in bestanden opgeslagen, omdat dit git, diffs, codebeoordeling en omgevingspromotie gratis biedt. Het opnemen van kanalen in een database is de beslissing die ervoor zorgt dat al deze onderdelen afzonderlijk moeten worden aangeschaft, en dit is de reden waarom een derde partij een product heeft dat uitsluitend bedoeld is om Mirth-kanalen tussen de database en een git-repository over te brengen.

De splitsing is dus: configuratie in bestanden, identiteit en geschiedenis in SQLite.

Source: github.com/biodream-llc/perfuse/internal/store

26.101 tefca

Pakket tefca implementeert de onderdelen van TEFCA-deelname die geen QHIN-verbinding vereisen.

Wat is echt

Validatie van het doel van het gebruik, configuratievalidatie en de audittrail - inclusief de persistentie, de queryinterface en de verplichting om mislukte pogingen eveneens te registreren als geslaagde pogingen. Dat laatste is geen formaliteit: een reeks mislukte leveringen aan één ontvanger is de manier waarop een incorrect geconfigureerde partner zichtbaar wordt, en een reeks mislukte queries voor verschillende patiënten is de manier waarop proberen zichtbaar wordt.

Wat niet

Het netwerk. Er is geen QHIN-transport in deze build, dus er vindt geen uitwisseling plaats en elke uitwisselingsfunctie weigert met ErrExchangeNotImplemented in plaats van succes te retourneren.

Die onderscheid werd niet altijd getrokken, en de manier waarop het verkeerd ging is het behoud waard. Alle vier uitwisselingsfuncties valideerden vroeger hun invoer, deden geen netwerkoproep en retourneerden succes; Deliver retourneerde een geaccepteerd antwoord met een volgnummer dat was opgebouwd uit de klok. De auditlaag registreerde vervolgens elk als een voltooide uitwisseling - in het logboek dat bestaat om te bewijzen wat is uitgewisseld wanneer iemand maanden later vraagt. Vier tests bevestigden dat gedrag en slaagden.

Wat nodig is om het te voltooien

Ingeschreven staan bij een gekwalificeerd gezondheidsinformatienetwerk, wederzijds geauthenticeerde TLS met certificaten die via dat proces zijn uitgegeven, en ofwel de IHE-profielen die het Algemene Akkoord zijn begonnen met, of Facilitated FHIR zoals gedefinieerd door de standaardprocedure van het Sequoia Project, van kracht vanaf 8 maart 2026. Niets hiervan kan speculatief worden geschreven: het wordt getest tegen een echt QHIN of het wordt niet getest, en een ongeteste uitwisselingsimplementatie is hetzelfde defect als geen implementatie met een betere vermomming.

Source: github.com/biodream-llc/perfuse/internal/tefca

26.102 huurder

Pakket huurder biedt de identiteits- en isolatieregels voor multi-huurderbedrijf.

Een HIE, een clearinghouse of een beheerdienstverlener draait één motor op behalf van vele organisaties. Mirth kan dit niet - één instantie dient één organisatie, en een MSP eindigt met het draaien van vijftig JVM's en vijftig databases.

Wat een huurder bezit

De kanalen, als een directory van bestanden. De gebruikers. De berichten, wachtrij, audittrail en FHIR-bronnen. De metrische labels. Niets wordt gedeeld, behalve het proces, de luisterpoorten die zijn toegewezen, en de platformbeheerders.

Isolatie is structureel, niet onthouden

Het gevaarlijke falen hier is niet een crash. Het is huurder A die de berichten van huurder B ziet, wat een rapporteerbare inbreuk is in plaats van een bug. Een ontwerp waar elke query een tenant_id-parameter neemt, faalt de eerste keer dat iemand een query schrijft en vergeet er een, en die query ziet er perfect correct uit in de beoordeling.

Dus de huurder is geen parameter. Gegevenstoegang gaat via een handgreep die deze al draagt, en er is geen manier om de tabellen te bereiken zonder een. Vergeten is niet beschikbaar.

Source: github.com/biodream-llc/perfuse/internal/tenant

26.103 terminologie

Pakket terminologie houdt gepubliceerde codesystemen (LOINC, SNOMED CT, RxNorm, ICD-10-CM, CPT en lokale) voor het opzoeken van codes, en de waardenkaarten die de tabellen niet hadden, voor iemand om te kaarten.

De codesystemen worden geïmporteerd uit de bestanden die hun uitgevers distribueren. Verschillende zijn gelicentieerd (LOINC heeft een gratis account nodig, SNOMED CT een aangesloten licentie, RxNorm een UMLS-licentie, CPT een AMA-licentie), dus geen enkele wordt met Perfuse geleverd: een beheerder die de licentie bezit, uploadt het bestand, en Perfuse registreert wie het heeft geïmporteerd en wanneer.

Source: github.com/biodream-llc/perfuse/internal/terminology

26.104 tlsconf

Pakket tlsconf bouwt TLS-configuratie op vanuit bestanden en beschrijft certificaten.

Dit is het gratis equivalent van een extensie waar Mirth nu voor in rekening brengt. Het grootste deel van de waarde zit niet in de encryptie, die enkele regels code is, maar in het deel dat voorkomt dat iemand iets implementeert dat hij denkt dat veilig is, maar dat niet is: weigeren om verificatie stilzwijgend over te slaan, erop aandringen dat een clientcertificaat daadwerkelijk wordt gecontroleerd wanneer daarom wordt gevraagd, en duidelijk aangeven wanneer een certificaat op het punt staat te verlopen.

Een verlopen certificaat op een interfacefeed is een echte storing in een ziekenhuis, en dat gebeurt omdat niemand op de hoogte werd gesteld. Het beschrijvende deel van dit pakket bestaat om die reden.

Source: github.com/biodream-llc/perfuse/internal/tlsconf

26.105 tomirth

Pakket tomirth schrijft een Perfuse-kanaal opnieuw uit als Mirth-kanaal XML.

Waarom dit bestaat. Het bezwaar tegen het aannemen van een nieuwe integratiemotor is zelden "is het goed?", maar "wat als we het mis hebben en vastzitten?", en het goedkoopste antwoord daarop is de mogelijkheid om terug te keren. Perfuse kan Mirth-kanaalgegevens lezen sinds het begin; tot nu toe kon het geen kanaal schrijven, waardoor de garantie eenzijdig was en dus niet veel voorstelde.

Hoe het de valkuil vermijdt die de eerste poging nutteloos maakte. Mirth's XML is XStream's output, en XStream leest de class- en version-attributen als instructies: een element dat het niet herkent, wordt zonder een woord weggegooid, en een kanaal dat het niet kan samenstellen, wordt opgeslagen met zijn beschrijving vervangen door "Dit kanaal is ongeldig. Verifieer alle vereiste extensies zijn correct geladen" en zijn bestemmingen weggegooid. Niets in die reactie noemt het element dat de fout veroorzaakt. Een exporter die eigenschapsblokken samenstelt op basis van een lezing van het formaat, faalt dus op een manier die duur is om te diagnosticeren, wat is gebeurd: deze repository bevatte een exporter met negen geslaagde tests waarvan de output door Mirth werd weggegooid, omdat elke test deze vergeleek met onze eigen parser in plaats van een server.

Dus geen van de eigenschapsblokken worden hier samengesteld. scripts/mirth-dump-connector-templates.sh heeft Mirth's eigen ObjectXMLSerializer serialiseren van de standaardwaarden van elke connector-eigenschappenklasse, en die documenten worden toegevoegd onder templates/. Dit pakket vervangt waarden in deze documenten, en mirth.SetRawProperty weigert elk pad dat het sjabloon niet al bevat - dus een fout is een fout in de benaming van het pad, op het moment van export, in plaats van een kanaal dat verdwijnt bij import.

Wat het niet zal doen. Een transport zonder Mirth-equivalent wordt geweigerd op naam, in plaats van benaderd. Een export die stilzwijgend een S3-bestemming in een bestandsschrijver zou veranderen, zou erger zijn dan helemaal geen export, omdat het kanaal schoon zou importeren en naar de verkeerde plaats zou leveren.

Source: github.com/biodream-llc/perfuse/internal/tomirth

26.106 trace

Pakket trace produceert gedistribueerde traceringen voor berichten die door een kanaal bewegen, en exporteert deze via OTLP/HTTP met JSON-codering.

Waarom dit bestaat in plaats van de OpenTelemetry SDK: de SDK plus een OTLP-exporteur trekt ongeveer zestig modules aan en voegt net zoveel toe aan de binaire code als het hele restant van dit programma. Wat hier daadwerkelijk nodig is, is smal - W3C-traceringcontextpropagatie, een spanmodel, hoofdsampling en een batch-HTTP-POST - en OTLP/JSON is een gedocumenteerde stabiele codering die kan worden geproduceerd met de standaardbibliotheek alleen. Dezelfde keuze als het kiezen van lib/pq boven pgx: neem het kleine ding wanneer alleen een deel van het grote ding gewenst is.

De gevolgtrekking die het vermelden waard is: er is geen auto-instrumentatie en geen leverancierspecifieke exporteur. Spans zijn die welke dit programma opzettelijk maakt, en die gaan naar elk OTLP-eindpunt - een collector, Jaeger, Grafana Tempo, Honeycomb, Datadog's OTLP-ingest.

Het eigenschap dat meer telt dan de spans

Een bericht arriveert vaak met een traceparent-header van het systeem dat het heeft verstuurd, en vertrekt naar een systeem dat er een van zijn eigen zal opnemen. Het voortzetten van die tracering in plaats van een nieuwe te starten, is wat een enkel zichtbaar maken van "het EHR heeft dit verstuurd, de motor heeft het getransformeerd, het register heeft het afgewezen" mogelijk maakt. Interfaceproblemen worden bijna altijd gemeld als "we hebben het verstuurd en er gebeurde niets", en die vraag is onbeantwoordbaar zonder een identificator die de overdracht overleeft.

Tracering mag nooit de levering beïnvloeden

Elke bewerking hier is een beste inspanning. Spans worden weggegooid wanneer de buffer vol is, exportfouten worden geteld en nooit opnieuw geprobeerd in het berichtpad, en geen oproep blokkeert het netwerk. Een weggegooid span is een ongemak. Een bericht dat wordt vertraagd of verloren omdat de traceringbackend traag was, is een klinisch incident, dus de keuze is nooit in twijfel.

Source: github.com/biodream-llc/perfuse/internal/trace

26.107 transform

Pakket transform past declaratieve wijzigingen toe op een bericht.

Dit is de laag die bedoeld is om het gewone werk te doen, met scripting gehouden als een gemarkeerde ontsnappingsmogelijkheid. Het onderscheid is niet stylistisch. Een stap die in YAML is verklaard, kan worden gevalideerd voordat deze wordt uitgevoerd, getoond in een diff, beoordeeld door iemand die geen JavaScript leest, en gerapporteerd; een script kan alleen worden uitgevoerd en gehoopt. Het grootste deel van wat Mirth-transformaties daadwerkelijk doen is saai - een veld kopiëren, een identificator opvullen, een code toewijzen via een tabel, iets wissen dat het gebouw niet mag verlaten - en al dat soort dingen horen hier thuis.

Elke stap noemt zijn doelwit expliciet en elke stap is omkeerbaar in de zin dat deze aangeeft wat deze heeft gedaan, omdat de duurste fout in een interface een transformatie is die niemand wist dat plaatsvond.

Source: github.com/biodream-llc/perfuse/internal/transform

26.108 translate

Pakket translate converteert een Mirth-kanaal naar een Perfuse-kanaaldefinitie.

perfuse explain rapporteert wat een migratie blokkeert. Dit doet het grootste deel van de migratie, wat een andere en veel grotere claim is, dus is het bewust conservatief over wat het zal beweren.

Drie regels vormen de hele zaak.

Niets wordt stilzwijgend genegeerd. Elk onderdeel van het bronkanaal wordt vertaald, letterlijk overgenomen als script of gemeld als noodzakelijk voor menselijke interventie. Een vertaler die een stap stilzwijgend weglaat, produceert een kanaal dat start, draait en gegevens verliest — het slechtste mogelijke resultaat en de reden waarom mensen migratietools niet vertrouwen.

Declaratief waar het zeker is, script waar het niet zeker is. Een Mapper-stap die een veld kopieert, wordt een declaratieve stap, omdat dat leesbaar en controleerbaar is. Een JavaScript-stap wordt een script, omdat Perfuse Mirth's JavaScript ongewijzigd uitvoert en het herschrijven ervan in iets dat er equivalent uitziet, precies is waar een vertaler een verschil zou introduceren dat niemand opmerkt.

De uitvoer is bedoeld om gelezen te worden. Het bevat commentaren die uitleggen waar iets vandaan komt en wat voor een persoon is achtergelaten. Een migratie wordt beoordeeld door iemand die het moet goedkeuren, en een ongeannoteerde muur van YAML kan niet worden beoordeeld.

Source: github.com/biodream-llc/perfuse/internal/translate

26.109 udap

Pakket udap implementeert de clientzijde van HL7 Security voor Scalable Registration, Authentication en Authorization — de specificatie waarop TEFCA's Facilitated FHIR-uitwisseling rust.

UDAP is een openbare sleutelinfrastructuur die is gekoppeld aan OAuth 2.0. Een vertrouwensgemeenschap verleent X.509-certificaten aan haar leden; een lid bewijst wie het is door JWT's te ondertekenen met de privésleutel en de certificaatketen in de JWT-header te attachen. Dat vervangt het gedeelde clientgeheim van gewone OAuth, dat niet schaalbaar is tot duizenden organisaties die elkaar nooit hebben ontmoet.

Waarom dit pakket überhaupt bestaat. TEFCA-uitwisseling kan niet volledig worden geverifieerd zonder een echte QHIN: joinen vereist onboarding en uitgegeven certificaten, en kan niet worden nagemaakt. Maar het beveiligingsprofiel eronder is een gepubliceerde HL7-implementatiegids met openbare referentieservers, en een daarvan reageert op het open internet. Dus wordt het deel dat kan worden geverifieerd, hier geverifieerd, en het deel dat niet kan, wordt geweigerd aan de grens in plaats van gegokt.

Het onderscheid is belangrijk vanwege wat er met SAML in dit repository is gebeurd: duizend regels tests zijn doorgekomen, vijf daarvan specifiek over handtekeningcanonicalisatie, terwijl geen enkele echte identiteitsprovider iemand kon authenticeren. Beide helften waren hier geschreven en kwamen overeen met elkaar. De les die daaruit is getrokken, is dat een beveiligingsimplementatie niets waard is totdat iets dat iemand anders heeft geschreven, het heeft geaccepteerd of geweigerd.

Specificatiereferenties: - HL7 UDAP Security STU 1: http://hl7.org/fhir/us/udap-security/STU1/ - TEFCA SOP Facilitated FHIR Implementation v2.0, van kracht vanaf 8 maart 2026

Source: github.com/biodream-llc/perfuse/internal/udap

Pakket umlink transporteert X12 278s naar een utilisatiebeheersysteem van een verzekeraar en de antwoorden ervan, de manieren waarop die systemen in de praktijk worden bereikt: X12 in het lichaam van een HTTPS POST; CAQH CORE's SOAP-envelop (Connectivity Rule vC2.2.0, de meest gebruikte door verzekeraars en CMS's esMD, en vC4.0.0); CAQH CORE's HTTP MIME-multiparte envelop (vC2.2.0); en batchbestanden via SFTP.

Geschreven vanuit CAQH's gepubliceerde Connectivity Rules (vC2.2.0 en vC4.0.0), hun XML Schema en WSDL, en CMS's esMD X12N 278 Companion Guide. Het is niet CORE-gecertificeerd: certificering wordt uitgevoerd door CAQH's geautoriseerde testleveranciers.

De real-time-koppelingen retourneren het antwoord dat het UM-systeem gaf, dat een 278-reactie of, wanneer het de aanvraag niet kon lezen, een 999 of TA1 kan zijn: de beller leest welke. De batch-koppeling retourneert ErrAnswerLater zodra het bestand is afgeleverd en Poll verzamelt wat terugkomt.

Source: github.com/biodream-llc/perfuse/internal/umlink

26.111 v2fhir

Pakket v2fhir kaart HL7 v2-berichten aan FHIR-bronnen.

Toewijzing is waar interoperabiliteitsprojecten eigenlijk falen, dus de regels die dit pakket volgt, worden vermeld in plaats van geïmpliceerd:

Source: github.com/biodream-llc/perfuse/internal/v2fhir

26.112 vcs

Pakket vcs leest de geschiedenis van kanaalbestanden uit git.

Kanaalgeschiedenis is een betaalde extensie elders, en het is een betaalde extensie omdat die engines kanalen in een database opslaan, dus het bijhouden van wijzigingen betekent het opbouwen van een wijzigingssysteem. Perfuse slaat kanalen op in bestanden, dus de geschiedenis bestaat al en bestond sinds de eerste commit. Dit pakket hoeft alleen maar het te lezen.

Het maakt gebruik van git in plaats van een git-bibliotheek in te sluiten. De bibliotheek zou een grote afhankelijkheid toevoegen aan een binaire die vier heeft als verkooppunt, en het zou niets opleveren: een implementatie die haar kanalen onder versiebeheer houdt, heeft git geïnstalleerd, en een die dat niet doet, krijgt een duidelijke "niet een git-repository" in plaats van een subtiel andere implementatie van hetzelfde.

Source: github.com/biodream-llc/perfuse/internal/vcs

26.113 vfs

Pakket vfs is de kleine set van bestandsbewerkingen die een polling-connector nodig heeft.

Waarom een interface in plaats van vier connectors

Perfuse verzamelt bestanden van een lokale schijf, een SFTP-server, een FTP-server, een Windows-share en een WebDAV-server. De overdracht verschilt in elk geval. Alles wat daadwerkelijk beslist of berichten overleven, doet dat niet:

Eén keer geschreven per transport, zouden deze regels subtiel anders zijn, vijf keer, en de verschillen zouden alleen verschijnen als berichten die op één site vermist werden. Dus worden ze één keer geschreven, hier, over het kleinste interface dat ze ondersteunt.

Wat er bewust niet is

Geen schrijven, behalve wat nodig is voor verwijdering. Het verzenden van bestanden is een ander probleem met andere foutmodi - een gedeeltelijk geschreven bestand aan de andere kant, dat bestaande verzenders afhandelen door te schrijven naar een tijdelijke naam en hernoemen. Het combineren van beide richtingen in één interface zou elk moeilijker maken om over na te denken.

Geen recursie. Een poller die afdaalt in subdirectories, verzamelt het archiefdirectory waarin hij zojuist een bestand heeft verplaatst.

Source: github.com/biodream-llc/perfuse/internal/vfs

26.114 vpn

Pakket vpn rapporteert de staat van de site-tot-site VPN-tunnels waarover partnerverkeer loopt - AWS Site-to-Site VPN, Azure VPN Gateway-verbindingen en strongSwan - en houdt elke partnerverbinding bij: beide zijden van de tunnelinstellingen en of ze overeenkomen.

Een tunnel die down is, ziet er, vanuit een interface-engine, exact uit als een partner wiens engine is gestopt: verbindingen verlopen. Zeggen "de tunnel is down" in plaats daarvan is het verschil tussen het bellen van het netwerkteam en het bellen van de partner.

Alleen lezen. Niets hier verandert een tunnel, en geen gedeelde sleutel wordt ooit gelezen, bewaard of getoond.

Source: github.com/biodream-llc/perfuse/internal/vpn

26.115 web

Pakket web dient de gebouwde frontend vanuit de binaire code.

De assets zijn ingebed in plaats van ernaast verzonden, zodat implementatie één bestand blijft. Dat is dezelfde reden waarom de engine cgo vermijdt: een operator zou in staat moeten zijn om een binaire code naar een server te kopiëren en uit te voeren, zonder JVM, zonder installer en zonder assetdirectory die uit fase raakt met de uitvoerbare code.

De gebouwde output is gecommit zodat go build werkt op een checkout zonder Node geïnstalleerd. Bouw het opnieuw met make web.

Source: github.com/biodream-llc/perfuse/internal/web

26.116 webauthn

Pakket webauthn verifieert passkeys.

Een passkey is een sleutelpaar dat de authenticator bevat - Touch ID, Windows Hello, een YubiKey, een telefoon - waarvan de privé-helft nooit het apparaat verlaat. Inloggen betekent dat de server een willekeurige uitdaging verstuurt, de authenticator ondertekent deze na controle of de gebruiker aanwezig is, en de server verifieert de handtekening tegen de openbare sleutel die bij registratie is opgeslagen.

De eigenschap die ertoe doet, is niet dat het handig is. Het is dat er niets te phishen valt. Een wachtwoord kan worden getypt in een overtuigende kopie van een inlogpagina; een passkey-handtekening is gebonden aan de oorsprong waarvoor deze is gemaakt, dus de kopie krijgt een handtekening die de server niet kan gebruiken. Voor een integratie-engine die de interfaces van een ziekenhuis bevat, is dat het verschil dat ertoe doet.

Wat deze implementatie weigert te doen

De specificatie is permissief op plaatsen waar permissief zijn hoe implementaties kapot gaan. Deze is dat niet:

Source: github.com/biodream-llc/perfuse/internal/webauthn

26.117 winservice

Pakket winservice voert Perfuse uit als een Windows-service.

Dit bestand is de overal-anders-helft. Het bestaat zodat cmd/perfuse een oproep kan doen naar dit pakket zonder elke oproepplaats in een buildtag te wikkelen: de subopdracht is altijd gecompileerd, en op Linux of macOS legt het uit dat services een Windows-idee zijn in plaats van te falen omdat het niet bestaat.

Weigeren met een duidelijke zin is beter dan het verbergen van de subopdracht. Iemand die Windows-instructies volgt op de verkeerde machine, wordt verteld wat er werkelijk aan de hand is, en het equivalent voor hun platform.

Source: github.com/biodream-llc/perfuse/internal/winservice

26.118 x12

Lezen en schrijven van waarden op een pad.

Waarom dit apart is van Path

path.go bepaalt wat een padexpressie betekent. Dit bestand lost er een op tegen een daadwerkelijke uitwisseling. Het is apart gehouden omdat de parsingsregels de moeite waard zijn om te lezen zonder de bytebehandeling, en omdat de parser wordt gebruikt door de configuratievalidator, die geen bericht heeft om tegen te controleren.

Waarom een schrijfactie opnieuw parseert in plaats van bytes op hun plaats te bewerken

Segment.elements zijn subslices van Segment.raw, en Message.segs indexeert in Message.raw. Het bewerken van een waarde op de plaats verandert de lengte van alles daarna, dus alle subslices moeten worden aangepast, en elke subslice die wordt gemist, zal correct lezen totdat het bericht wordt gegenereerd waarin het niet correct is.

Dus een schrijfactie herbouwt het segment, herbouwt de uitwisseling en parseert deze opnieuw. Dat kost een parse per gewijzigd bericht en koopt de garantie dat een Message dat hier wordt geretourneerd, exact is wat het parsen van de eigen bytes produceert. Er is geen staat waarin de indexen en de bytes niet overeenkomen, omdat die staat niet kan worden weergegeven.

Source: github.com/biodream-llc/perfuse/internal/x12

26.119 x12xml

Pakket x12xml converteert X12 (en andere begrensde EDI) naar en van de xml die Mirth Connect en Open Integration Engine schrijven voor het, en terug.

Waarom die xml en niet een van de onze

Het doel van een xml-vorm van X12 is de systemen die er al een gebruiken. Een site die van Mirth migreert, heeft ontvangers gebouwd tegen wat Mirth's EDI/X12-gegevenstype emitteert, scripts die msg['CLM']['CLM.05']['CLM.05.1'] doorlopen, en upstream-motoren die X12 als die xml verzenden. Een nettere vorm van onze eigen zou hen niet dienen. Dus deze schrijft exact wat Open Integration Engine 4.6 schrijft, en leest exact wat het leest, en de tests vergelijken de twee byte voor byte met OIE's eigen serializer.

Een eerdere versie van dit pakket heeft zijn eigen vorm uitgevonden (een X12Interchange-root, elementen met de naam CLM05) en zei dat het overeenkwam met Mirth's. Het deed het niet; het was nooit vergeleken met Mirth, en niets in Perfuse gebruikte het.

The format

De root is X12Transaction wanneer het bericht begint met een ISA-segment en EDIMessage anders, met de drie begrenzers als attributen (segmentDelimiter, elementDelimiter, subelementDelimiter). Elk segment is een element met de naam van zijn identificator. Elk gegevenselement is SEG.NN, genummerd van 01 (ISA.01, CLM.05), en bevat zijn componenten als SEG.NN.1, SEG.NN.2 enz.: altijd minstens SEG.NN.1 voor een element met een waarde, geen voor een leeg element.

De begrenzers worden gelezen uit de ISA wanneer er een is: de element-scheidingsteken van positie 3, de component-scheidingsteken van positie 104 en de segment-terminator van positie 105, met een regelafstand erna die als onderdeel ervan wordt geteld. Anders zijn ze ~ * en:. De herhalingsscheidingsteken (ISA11) wordt niet geïnterpreteerd, wat ook het gedrag van OIE is: een herhaald element houdt zijn ^ binnen één waarde.

Dit is een herimplementatie van het gedrag, geschreven op basis van de output van OIE en de gedocumenteerde indeling; er zit geen code van Mirth in.

Source: github.com/biodream-llc/perfuse/internal/x12xml

26.120 xds

Pakket xds is IHE-cross-enterprise document sharing: een XDS.b Document Registry en Repository (ITI-41 Provide en Register, ITI-18 Registry Stored Query, ITI-43 Retrieve Document Set), een XCA Responding Gateway over dezelfde winkel (ITI-38, ITI-39), en de clientzijde van elk, zodat een kanaal een document kan publiceren naar het repository van een andere organisatie en de console een register of een gemeenschap kan opvragen.

De metagegevens zijn ebXML Registry 3.0 (ebRIM), zoals XDS.b deze definieert in IHE ITI TF-3 hoofdstuk 4. Het wordt hier gemodelleerd als Go-structs waarvan de XML-tags de namespaces bevatten, zodat een bericht op dezelfde manier wordt gelezen, ongeacht welke voorvoegsels de afzender heeft gekozen, en namespace-correct wordt geschreven.

Source: github.com/biodream-llc/perfuse/internal/xds

26.121 xmldsig

Pakket xmldsig implementeert XML Digital Signatures en het XAdES-profiel ervan.

Waarom dit is geschreven in plaats van geleend

Een ondertekend klinisch document is een juridisch artefact. Het beweert dat een genoemde persoon, op een genoemde tijd, verantwoordelijkheid nam voor een specifieke set bytes. Het verkeerd krijgen in beide richtingen is serieus: een handtekening die niet kan worden geverifieerd, maakt een geldig document eruitzien alsof het vervalst is, en een verifier die te gul is, accepteert een document dat iemand heeft gewijzigd.

Canonisatie is het hele probleem

XML heeft veel bytevolgordes die hetzelfde betekenen. Attribuutvolgorde is niet significant, namespace-voorvoegsels kunnen worden hernoemd, lege elementen kunnen op twee manieren worden geschreven en witruimte binnen een tag is vrij. Een handtekening is over bytes, dus voordat iets wordt gehasht, moeten beide partijen het eens zijn over exact één bytevolgorde voor een bepaald document. Die overeenstemming is canonisatie, en dat is waar implementaties verkeerd gaan, omdat elke fout een handtekening produceert die verifieert tegen de eigen uitvoer en faalt tegen die van iedereen anders.

Dus dit bestand is de canonisatie, op zichzelf, met zijn eigen tests. Er verschijnt niets over ondertekening hier.

Exclusief in plaats van inclusief, standaard

Inclusieve canonisatie trekt elke namespace-verklaring aan die in het bereik ligt, inclusief die welke het ondertekende element nooit gebruikt. Dat maakt een handtekening kapot wanneer het document later wordt ingebed in iets dat een niet-gerelateerde namespace op een voorouder verklaart, wat precies gebeurt wanneer een CDA in een SOAP-envelope of een IHE-metadatamap wordt geplaatst. Exclusieve canonisatie omvat alleen de verklaringen die het element daadwerkelijk gebruikt, en dat is wat documentuitwisselingsprofielen specificeren om die reden.

Source: github.com/biodream-llc/perfuse/internal/xmldsig

26.122 xtree

Pakket xtree is een mutable XML-boom.

Drie heel verschillende functies moeten XML wijzigen: HL7-transformaties, die Mirth als XML modelleert omdat dat is waar zijn scripts op werken; klinische documenten, die native XML zijn; en de declaratieve transformatiestappen. Ze delen deze ene boom in plaats van dat elk zijn eigen boom laat groeien, omdat het alternatief drie modellen zijn die het oneens zijn over wat een leeg element betekent.

Het ontwerpdoel is trouw aan E4X-semantiek, aangezien Mirth-scripts E4X zijn en het hele punt van het ongewijzigd uitvoeren ervan is dat ze hetzelfde gedrag vertonen. Dat drijft twee beslissingen aan die anders vreemd zouden lijken: een knooppunt houdt een verwijzing naar zijn ouder bij, omdat E4X parent() blootstelt, en kinderen worden besteld met dubbele toegestaan, omdat een HL7-veldherhaling letterlijk een herhaald element is en scripts indexeren naar hen op basis van positie.

Source: github.com/biodream-llc/perfuse/internal/xtree

26.123 pas

Pakket pas leest Da Vinci Prior Authorization Support (PAS) aanvraagbundels.

Het is de lezer die de eigen PAS-server van Perfuse gebruikt, gepubliceerd zodat wat dan ook beslist over een voorafgaande autorisatie - een betalersregels, een utilisatiemanagementsysteem, een beslissingsdienst zoals Vaglio - een aanvraag leest met dezelfde code, en zo dezelfde antwoorden over wat een aanvraag bevat. Twee lezers van een berichtformaat zijn twee meningen over hetzelfde.

Het heeft geen afhankelijkheden buiten de standaardbibliotheek. Een aanvraag wordt bewaard als gedecodeerde JSON (map[string]any) in plaats van als getypeerde resources, omdat een PAS-bundel alle ondersteunende resources bevat die de provider heeft gekozen om te verzenden, en een lezer die wat het niet modelleert weglaat, bewijs voor de beslissing verbergt.

req, problems := pas.Read(bundle, false) if len(problems) > 0 { // weigeren: de aanvraag kan niet correct worden beantwoord } for _, svc := range req.Services() { // svc.Codes, svc.Item, en req.Resolve voor alles wat het item verwijst }

Source: github.com/biodream-llc/perfuse/pas

27 Index van configuratiesleutels

Elke sleutel in alfabetische volgorde, met de blokken waarin deze kan voorkomen. Een sleutel die in meerdere blokken voorkomt, betekent hetzelfde in elk blok; waar het niet voorkomt, worden de blokken afzonderlijk gedocumenteerd en wordt het verschil daar vermeld.

27.1 Alle sleutels

SleutelVerschijnt in
access_key_idAWS-toegang, FHIR-authenticatie, S3-bestemming
accountAzure Blob-toegang
ackHTTP-bron, SOAP-bron, Bron
ack_sender_idX12-opties
ack_sender_qualifierX12-opties
acknowledgeEDIFACT-opties, HL7v3-opties, X12-opties
acksKafka-bestemming
actionSOAP-bestemming
addrAMQP-verbinding, Broker-bestemming, Broker-bron, MQTT-verbinding
addressAMQP-verbinding, DICOM-bestemming, DICOM-bron, Bestemming, Direct-adres, TCP-bestemming
ae_titleDICOM-bron
after_queryDatabase-bron
after_readAzure Blob-bron, Direct IMAP, E-mail-bron, Bestandspolling, GCS-bron, S3-bron, SFTP-bron
allowScripts
allow_clear_passwordFTP-bestemming
allow_unencryptedAS2-partner, PGP-ontvangst
allow_unsignedAS2-partner
allowed_calling_aeDICOM-bron
allowed_sendersE-mail-bron
amqpBestemming, Bron
anchors_fileDirect-adres
api_versionIBMMQ-verbinding
appendBestemming, SFTP-bestemming
applicationAck
armorPGP-verzending
arrives_asX12-opties
as2Bestemming, Bron
attachSMTP-bestemming
attach_nameDirect-bestemming, SMTP-bestemming
attachment_namesE-mail-bron
attachmentsKanaal
attemptsPoging
authFHIR-bestemming, PAS-bestemming
authoritiesMPI-bestemming
azure_blobBestemming, Bron
backoffWachtrijconfiguratie, Poging
base64SOAP-bron
batch_sizeDatabase-bron, Bestandspolling
baudSeriële bron
bccSMTP-bestemming
bearer_tokenCDA-bestemming, FHIR-bestemming, HTTP-bestemming, PAS-bestemming
big_endianTCP-framing
blobAzure Blob-bestemming
bodySMTP-bestemming, SOAP-bestemming
brokerBestemming, Bron
brokersKafka-bestemming, Kafka-bron
bucketGCS-toegang, S3-bestemming, S3-bron
bundle_scriptFHIR-bestemming
called_aeDICOM-bestemming, DICOM-bron
calling_aeDICOM-bestemming, DICOM-bron
ccSMTP-bestemming
cdaBestemming
cert_fileAS2-bestemming, AS2-partner, AS2-bron, Direct-adres
channelBestemming, Schaduw
check_everyContractref
cityECR-faciliteit
claim_us_coreFHIR-bestemming
classXDS-bestemming
client_ca_fileDirect XDR
client_idE-mail O Auth, FHIR-authenticatie, MQTT-verbinding
client_secretE-mail O Auth, FHIR-authenticatie
codeXDS-code
columnDatabase-bron
columnsGescheiden
commentGescheiden
commit_after_deliveryKafka-bron
compareSchaduw
compressAS2-bestemming
compressionKafka-bestemming
configELR-bestemming
containerAzure Blob-toegang
content_typeAMQP-bestemming, AS2-bestemming, Azure Blob-bestemming, Broker-bestemming, GCS-bestemming, HTTP-bestemming, S3-bestemming, XDS-bestemming
contractKanaal
credentials_fileGCP-toegang
dataTypeKanaal
data_bitsSeriële bron
databaseBestemming, Bron
decrypt_withPGP-ontvangst
default_identifier_systemFHIR-bestemming
delimitedKanaal
delimiterGescheiden, TCP-framing
deployScripts
descriptionKanaal
destinationBroker-bestemming, Broker-bron
destinationsKanaal
dicomKanaal, Bestemming, Bron
dicom_queryBron
dicomwebBestemming, Bron
dirCDA-bestemming, Bestemming, Documentbestemming, FTP-bestemming, Bestandspolling, SFTP-bestemming, SFTP-bron
directBestemming, Bron
direct_fromXDS-bestemming
direct_toXDS-bestemming
displayXDS-code
dnsDirect-bestemming
documentBestemming
domainSMB-bron
driverDatabase-bestemming, Database-bron
dsnDatabase-bestemming, Database-bron
duplicate_windowAS2-bron
ecrFHIR-bestemming
edifactKanaal
elementSOAP-bron
elrBestemming
emailBron
emit_on_first_pollDICOM-bron
enabledKanaal, Bestemming, Wachtrijconfiguratie
encrypt_toPGP-verzending
endpointAWS-toegang, Azure Blob-toegang, GCP-toegang, S3-bestemming
envelopeEDIFACT-opties, X12-opties
error_dirBestandspolling, SFTP-bron
error_folderDirect IMAP, E-mail-bron
error_prefixAzure Blob-bron, GCS-bron, S3-bron
expect_replyTCP-bestemming
extractBijlagen
facilityAck, ECR-bestemming
facility_idSOAP-bestemming
facility_typeXDS-bestemming
fail_on_bodyHTTP-bestemming
fault_is_successSOAP-bestemming
fault_on_nakSOAP-bron
fhirBestemming
fileContractref, Bron
file_nameAS2-bestemming, Bestemming, Documentbestemming, FTP-bestemming, PGP-verzending, SFTP-bestemming
file_rootsScripts
filterKanaal, Gescheiden, Bestemming, HL7v3-opties, Scripts
flow_controlSeriële bron
follow_redirectsHTTP-bestemming
follow_symlinksBestandsbron
font_sizeDocumentbestemming
formatDocumentbestemming, S3-bestemming
framedAzure Blob-bron, FTP-bestemming, Bestandspolling, GCS-bron, S3-bestemming, S3-bron, SFTP-bestemming, SFTP-bron
framingTCP-framing
fromAS2-bestemming, SMTP-bestemming
from_beginningKafka-bron
ftpBestemming, Bron
gcsBestemming, Bron
groupKanaal, Kafka-bron
group_bySNS-bestemming, SQS-bestemming
has_headerGescheiden
headerSOAP-bestemming
headersBroker-bestemming, CDA-bestemming, DICO Mweb-bestemming, FHIR-bestemming, HTTP-bestemming, Kafka-bestemming, SOAP-bestemming, XDS-bestemming
heartbeatBroker-bron
hl7v3Kanaal
hostBroker-bestemming, Broker-bron, Direct IMAP, E-mail-bron, FTP-bestemming, FTP-bron, SFTP-bestemming, SFTP-bron, SMB-bron, SMTP-bestemming
hostnameAMQP-verbinding
httpBestemming, Bron
ibm_mqBestemming, Bron
idAS2-partner, AS2-bron
id_typeMPI-bestemming
identifier_systemsCDA-bestemming, FHIR-bestemming
idle_timeoutDICOM-bron, Bron, TCP-bron
ignoreSchaduw
imapDirect-bron
includeScripts
include_trigger_eventAck
insecure_skip_host_key_checkSFTP-bestemming, SFTP-bron
insecure_skip_verifyFTP-bestemming, FTP-bron, SMTP-bestemming, Web DAV-bron
intervalDICOM-bron
javascriptBestemming, Bron
kafkaBestemming, Bron
keep_aliveTCP-bestemming
keep_blank_linesGescheiden
keep_delimiterTCP-framing
keyAzure Blob-toegang, Kafka-bestemming, S3-bestemming
key_columnDatabase-bron
key_fileAS2-bestemming, AS2-bron, Direct-adres, SFTP-bestemming, SFTP-bron
key_passphraseSFTP-bestemming, SFTP-bron
known_hosts_fileSFTP-bestemming, SFTP-bron
landscapeDocumentbestemming
languageScripts
ldapDirect-bestemming
length_bytesTCP-framing
length_includes_headerTCP-framing
levelDICOM-bron
limitDICOM-bron
lineECR-faciliteit
listenAS2-bron, DICO Mweb-bron, DICOM-bron, Direct-bron, Direct XDR, HTTP-bron, SOAP-bron, Bron, TCP-bron
loginBroker-bestemming, Broker-bron
mailboxDirect IMAP, E-mail-bron
matchDICOM-bron
max_attemptsDatabase-bron, Wachtrijconfiguratie
max_backoffWachtrijconfiguratie, Poging
max_bytesDirect-bron
max_connectionsBron, TCP-bron
max_depthWachtrijconfiguratie
max_differencesSchaduw
max_file_sizeBestandspolling, SFTP-bron
max_message_sizeAS2-bron, E-mail-bron, HTTP-bron, Kafka-bron, SOAP-bron, Seriële bron, Bron, TCP-bestemming, TCP-bron
max_messagesPub Sub-bron, SQS-bron
max_object_bytesDICO Mweb-bron, DICOM-bron
max_object_sizeAzure Blob-bron, GCS-bron, S3-bron
max_open_connsDatabase-bestemming
mechanismKafka SASL
methodHTTP-bestemming
move_toAzure Blob-bron, Direct IMAP, E-mail-bron, Bestandspolling, GCS-bron, S3-bron, SFTP-bron
mpiBestemming
mqttBestemming, Bron
nameKanaal, Kanaalbestemming, Bestemming, ECR-faciliteit
ncpdpKanaal
no_compressPGP-verzending
no_mergeMPI-bestemming
non_persistentIBMMQ-bestemming
npiECR-faciliteit
oauthE-mail-bron
objectGCS-bestemming
on_no_documentCDA-bestemming
order_byPub Sub-bestemming
overContractref
overlapDICOM-bron
paramsDatabase-bestemming
paritySeriële bron
partner_cert_fileAS2-bestemming
partnersAS2-bron
pasBestemming
pass_plainPGP-ontvangst
passcodeBroker-bestemming, Broker-bron
passphrasePGP-ontvangst, PGP-verzending
passwordAMQP-verbinding, AS2-bestemming, DICO Mweb-bestemming, DICO Mweb-bron, Direct-bestemming, Direct IMAP, Direct-bron, E-mail-bron, HTTP-bestemming, IBMMQ-verbinding, Kafka SASL, MQTT-verbinding, SFTP-bestemming, SFTP-bron, SMB-bron, SMTP-bestemming, SOAP-bestemming, SOAP-bron, Web DAV-bron, XDS-bestemming
pathAS2-bron, DICO Mweb-bron, HTTP-bron, SOAP-bron
path_styleS3-bestemming, S3-bron
patient_domainXDS-bestemming
patient_rootDICOM-bron
patternBestandspolling, SFTP-bron
payerPAS-bestemming
persistentBroker-bestemming
pgpBestemming, Bron
phoneECR-faciliteit
poll_intervalAzure Blob-bron, Database-bron, Direct IMAP, E-mail-bron, Bestandspolling, GCS-bron, IBMMQ-bron, Java Script-bron, S3-bron, SFTP-bron
portDirect IMAP, E-mail-bron, Seriële bron
postal_codeECR-faciliteit
postprocessorScripts
practice_settingXDS-bestemming
prefetchAMQP-bron
prefixAzure Blob-bron, GCS-bron, S3-bron
preprocessorScripts
profileSOAP-bestemming, SOAP-bron
projectGCP-toegang
protocolE-mail-bron
providerE-mail O Auth
pubsubBestemming, Bron
purposeTEFCA-bestemming
qosMQTT-verbinding
queryDatabase-bron
query_timeoutDatabase-bron
queueBestemming, IBMMQ-verbinding
queue_managerIBMMQ-verbinding
queue_urlSQS-bestemming, SQS-bron
quiet_afterSeriële bron
quoteGescheiden
rawBestandspolling
rctcECR-bestemming, ELR-bestemming
read_timeoutHTTP-bron, SOAP-bron
reassembleBijlagen
receiptAS2-bestemming
receipt_urlAS2-bestemming
recipient_certs_dirDirect-bestemming
reconnectAMQP-bron, Broker-bron, MQTT-bron, Pub Sub-bron
record_lengthTCP-framing
refresh_tokenE-mail O Auth
regionAWS-toegang, FHIR-authenticatie, S3-bestemming
reject_on_warningFHIR-bestemming
relaxedGescheiden
reopen_afterSeriële bron
replySeriële bron, TCP-bron
reply_textSeriële bron, TCP-bron
request_mdnDirect-bestemming
require_agreementCDA-bestemming
require_signaturePGP-ontvangst
response_elementSOAP-bron
response_namespaceSOAP-bron
response_transformerBestemming
results_toPAS-bestemming, TEFCA-bestemming
retainMQTT-bestemming
retain_hoursBestemming, Wachtrijconfiguratie
retryBestemming
returnDICOM-bron
rootFTP-bron, Bestandsbron, SMB-bron
s3Bestemming, Bron
sampleSchaduw
sasAzure Blob-toegang
saslKafka-bestemming, Kafka-bron
schemeXDS-code
scopeE-mail O Auth, FHIR-authenticatie
scriptKanaal, Java Script-bestemming, Java Script-bron
scriptsKanaal
secret_access_keyAWS-toegang, FHIR-authenticatie, S3-bestemming
securityDirect IMAP, E-mail-bron, FTP-bestemming, FTP-bron
selectorBroker-bron
sender_deviceHL7v3-opties
sender_oidHL7v3-opties
serialBron
server_side_encryptionS3-bestemming
session_timeoutKafka-bron
session_tokenAWS-toegang, FHIR-authenticatie, S3-bestemming
sftpBestemming, Bron
shadowKanaal
shareSMB-bron
sign_withPGP-verzending
smbBron
smtpBestemming
smtp_hostDirect-bestemming, Direct-bron
snsBestemming
soapBestemming, Bron
sop_classesDICOM-bron
sort_byBestandspolling
sourceKanaal, ECR-bestemming
source_idXDS-bestemming
splitGescheiden, EDIFACT-opties, X12-opties
sqsBestemming, Bron
ssn_systemMPI-bestemming
stable_forBestandspolling, SFTP-bron
start_blockTCP-framing
starttlsSMTP-bestemming
stateECR-faciliteit
statementDatabase-bestemming
stop_bitsSeriële bron
storage_classGCS-bestemming, S3-bestemming
subjectAS2-bestemming, Direct-bestemming, SMTP-bestemming, SNS-bestemming
subscriptionPub Sub-bron
subscription_idBroker-bron
success_on_undefinedJava Script-bestemming
success_statusHTTP-bestemming
suffixAzure Blob-bron, GCS-bron, S3-bron
tablesKanaal
takeE-mail-bron
tcpBestemming, Bron
tefcaBestemming
temp_suffixBestemming, Documentbestemming, FTP-bestemming, SFTP-bestemming
templateDatabase-bron, Documentbestemming
tenantE-mail O Auth
tenant_idFHIR-authenticatie
textDirect-bestemming
tierAzure Blob-bestemming
timeoutAMQP-verbinding, Broker-bestemming, Broker-bron, DICO Mweb-bestemming, DICOM-bestemming, DICOM-bron, Database-bestemming, Bestemming, Direct-bestemming, Documentbestemming, FTP-bestemming, FTP-bron, IBMMQ-verbinding, Java Script-bestemming, Java Script-bron, Kafka-bestemming, Kafka-bron, MQTT-verbinding, S3-bestemming, SFTP-bestemming, SFTP-bron, SMB-bron, SMTP-bestemming, SOAP-bestemming, Scripts, Schaduw, TCP-bestemming, Web DAV-bron, XDS-bestemming
timezoneFHIR-bestemming
titleDocumentbestemming
tlsAMQP-verbinding, AS2-bestemming, AS2-bron, Broker-bestemming, Broker-bron, DICO Mweb-bestemming, DICO Mweb-bron, DICOM-bestemming, DICOM-bron, Bestemming, Direct IMAP, E-mail-bron, HTTP-bestemming, HTTP-bron, IBMMQ-verbinding, Kafka-bestemming, Kafka-bron, MQTT-verbinding, SOAP-bestemming, SOAP-bron, Bron, TCP-bestemming, TCP-bron, XDS-bestemming
tls_certDirect-bron, Direct XDR
tls_keyDirect-bron, Direct XDR
toAS2-bestemming, Direct-bestemming, SMTP-bestemming
tokenDICO Mweb-bestemming, DICO Mweb-bron, HTTP-bron, SOAP-bron, XDS-bestemming
token_urlE-mail O Auth, FHIR-authenticatie
topicKafka-bestemming, MQTT-bestemming, MQTT-bron, Pub Sub-bestemming
topic_arnSNS-bestemming
topicsKafka-bron
transfer_syntaxesDICOM-bestemming, DICOM-bron
transformationsKanaal, DICOM-opties, Gescheiden, HL7v3-opties, NCPDP-opties, Script-opties, X12-opties
transformerScripts
trim_paddingTCP-framing
trim_spaceGescheiden
typeBestemming, FHIR-authenticatie, Bron
undeployScripts
unencryptedAS2-bestemming
unsignedAS2-bestemming
unsigned_receiptAS2-bestemming
urlAS2-bestemming, CDA-bestemming, DICO Mweb-bestemming, FHIR-bestemming, HTTP-bestemming, IBMMQ-verbinding, SOAP-bestemming, Web DAV-bron, XDS-bestemming
userFTP-bestemming, FTP-bron, SFTP-bestemming, SFTP-bron, SMB-bron, Web DAV-bron
usernameAMQP-verbinding, AS2-bestemming, DICO Mweb-bestemming, DICO Mweb-bron, Direct-bestemming, Direct IMAP, Direct-bron, E-mail-bron, HTTP-bestemming, IBMMQ-verbinding, Kafka SASL, MQTT-verbinding, SMTP-bestemming, SOAP-bestemming, SOAP-bron, XDS-bestemming
validate_before_sendFHIR-bestemming
verify_withPGP-ontvangst
versionCDA-bestemming, FHIR-bestemming, SOAP-bestemming, SOAP-bron
visibility_timeoutSQS-bron
wait_secondsSQS-bron
warnings_are_errorsSOAP-bestemming
webdavBron
whenAck
windowDICOM-bron
writeCDA-bestemming
wsdlSOAP-bron
x12Kanaal
x12_asBestemming
xdmDirect-bestemming
xdm_source_idDirect-bestemming
xdrDirect-bron
xdsBestemming