1 Introduktion
Perfuse flyttar kliniska meddelanden mellan system som aldrig varit avsedda att prata med varandra. Ett laboratorium skickar resultat i HL7 v2; systemet för praktikledning förväntar sig dem med olika fältpositioner, en annan patientidentifierare och en bekräftelse inom fem sekunder. Något måste sitta i mitten, och det är en integrationsmotor.
Denna manual beskriver vad Perfuse gör, alla alternativ den accepterar och - där ett beslut inte är uppenbart - varför den fungerar på det sättet.
1.1 Vad Perfuse är till för
En enda gränssnitt mellan två kliniska system kostar vanligtvis tiotusentals, med femton till tjugo procent av den summan igen varje år i underhåll. Mycket av den kostnaden är inte arbetet; det är att arbetet kräver någon som har gjort HL7 tidigare, och de flesta praktiker anställer inte en sådan person.
Perfuse är byggd på antagandet att den person som konfigurerar den har ett problem att lösa och ingen tidigare HL7-erfarenhet. Det antagandet syns på specifika ställen:
- Allt kan konfigureras från webbgränssnittet. En funktion som endast kan nås från en terminal eller en handredigerad fil behandlas som en defekt, inte ett designval.
- Meddelanden kan spåras ett transformationssteg i taget, som visar vad varje steg läste, vad det ändrade och vad det hoppade över och varför.
- Testtrafik kan genereras som matchar formen på en riktig feed utan att innehålla någon av dess data.
- En kanal kan föreslås från ett enda exempelmeddelande, med en uttrycklig förklaring av vad exemplet inte kan berätta.
- Innan en befintlig motor ersätts, kan dess utdata och Perfuses jämföras meddelande för meddelande, med skillnaderna grupperade efter fält.
1.2 Vad som ingår
Allt nedan ingår i den binära filen. Varje rad namnger kapitlet som täcker det.
- Format. HL7 v2, FHIR R4, R4B och R5, DICOM, X12 (837, 835, 270/271, 276/277, 834, 278, 275), C-CDA och CDA, HL7 v3,
NCPDP Telecommunication och SCRIPT, SMART Health Links och Cards, avgränsade och råa. Se meddelandeformat.
- Kopplingar. 28 källtyper och 32 destinationstyper, bland annat MLLP, filer, SFTP, databaser, DICOM, Kafka, AMQP 1.0,
MQTT, IBM MQ och AWS, Azure och Google Cloud-lagring och meddelandehantering. Se källreferens och destinationsreferens.
- Ändra meddelanden. Filter, elva deklarativa transformationssteg, JavaScript (Mirths dialekt inkluderad) och Lua, delade
mappningstabeller och koduppsättningar, och mappningsförslag. Se filtrering och transformation.
- Leverera dem. En varaktig, ordnad kö per destination, omförsök, döda brev som behåller meddelandet och bekräftelser
som skickas efter leverans. Se leverans och bekräftelser.
- Titta på det som körs. Instrumentpaneler, laginstrumentpaneler, en flödeskarta, elva typer av varningar, mått, spårning och en meddelandelagring
som hittar en patients meddelanden över format. Se varningar, meddelandelagringen och felsökning.
- Ändra en livegränssnitt säkert. Skuggläge, matningskontrakt, kanaltester och motorens jämförelse. Se testning.
- Lämna Mirth. Mirth, Open Integration Engine och BridgeLink-kanaler förklarade, översatta och exporterade tillbaka. Se
- Försäkringsgivare och folkhälsa. De fyra CMS-0057 API:erna, Da Vinci CRD, DTR, PAS, PDex och Plan-Net, CARIN Blue Button, en valfri
beslutsfunktion, eCR och ELR. Da Vinci CRD, DTR och PAS svarar på både deras 2.2.x och deras 2.1.0-versioner. Se CMS-0057.
- Vem som kan göra vad. SAML, OpenID Connect, LDAP, passnycklar, SCIM, ömsesidig TLS, sex roller, kanalgrupper med en roll i varje,
hyresgäster, en SMART-autentiseringsserver, TEFCA och UDAP, och en revisionslogg. Se säkerhet.
- Kör det. En statisk binärfil för Linux, macOS och Windows, som en tjänst, med en flottvy av flera servrar. Se
drift, webbgränssnittet, kommandoraden och serveralternativ.
1.3 Standarder och versioner
Vilken version av varje standard som Perfuse implementerar och hur det kontrollerades. "Kontrollerad" namnger det yttre verktyget eller referensen som bedömde resultatet; där ingenting yttre har bedömt det, säger det så.
1.3.1 Meddelanden och dokument
| Standard | Version | Kontrollerad |
|---|---|---|
| HL7 v2 | valfri version: meddelanden läses av sina egna avgränsare, inte en versions schema; bekräftelser som standard till 2.5.1 | NIST HL7 v2-validerare; riktiga Mirth- och OIE-trafik |
| HL7 v2 till FHIR | HL7:s V2-till-FHIR-mappning (ADT, ORU, SIU, MDM, VXU och segmenten i dem) | HL7 FHIR-valideraren mot US Core, UK Core, FR Core, ISiK, nl-core och HL7 Europa |
| FHIR | R4 (4.0.1), med R4B och R5 som läses och skrivs | HL7 FHIR-valideraren; Inferno |
| C-CDA och CDA | C-CDA 2.1 | ONC SITE (C-CDA-exempel skickade och mottagna via XDR); inte av en CDA-schematron |
| HL7 v3 | PIX och PDQ (IHE ITI-44, 45, 47) | IHE:s NE2008-scheman och exempelmeddelanden |
| DICOM och DICOMweb | DIMSE C-STORE, C-FIND, C-MOVE, C-GET, C-ECHO; QIDO-RS, WADO-RS, WADO-URI, STOW-RS | Orthanc |
| X12 (HIPAA) | 005010: 837, 835, 270/271 (X279A1), 276/277 (X212), 834, 278 begäran (X217) och förfrågan (X215); 275 i 006020 (X314) | försäkringsgivarnas publicerade kompanjonsguider; CMS esMD-exempel |
| CAQH CORE-anslutning | vC2.2.0 SOAP och MIME, vC4.0.0 med MTOM | en stand-in UM-system skriven från CAQH:s regler |
| NCPDP | Telekommunikation D.0; SCRIPT 2023011 (och 2017071) med ePA; Real-Time Prescription Benefit v13 | skriven från de offentliga Surescripts-kompanjonsguiderna och deras exempel; inte mot NCPDP:s licensierade scheman |
| UN/EDIFACT | syntax 3 och 4, CONTRL | pydifact 0.1.8 |
| IHE-dokumentdelning | XDS.b, XCA, XDR, MHD 4.2.2, PIXm, PDQm, XDM | NIST XDS Toolkit; ONC SITE |
| Direkt säker meddelandehantering | Tillämpbarhetsuttalande 1.2, XDR och XDM för Direkt, DNS och LDAP-certifikatupptäckt | ONC SITE; ONC:s Certificate Discovery Tool (18 av 18) |
| AS2 | RFC 4130, komprimering RFC 5402 | pyas2lib |
| Underskrivna bilagor | HL7 DSDR, XAdES-X-L | xmlsec1, OpenSSL |
1.3.2 FHIR-implementeringsguider
| Guide | Release | Kontrollerad |
|---|---|---|
| US Core | konverteringar till 9.0.0 (USCDI v6); FHIR-server mot 6.1.0 och 7.0.0 | HL7-valideraren; Inferno US Core |
| SMART App Launch | 2.2 | Inferno: 80 av 80 (offentlig app) |
| Bulk Data Access | 2.0.0 | Inferno: 48 av 48 |
| Prenumerationer R5 Backport | för R4 | en riktig HTTP-mottagare; PAS-kits varnings tester |
| Da Vinci CRD | 2.2.1, och 2.1.0 | Inferno 2.2.1: 92 pass, ingen misslyckades; 2.1.0 av guidens egna exempel |
| Da Vinci DTR | 2.2.0, och 2.1.0 | Inferno 2.2.0: 43 pass, 2 misslyckades (en kitdefekt); 2.1.0 av guidens egna exempel |
| Da Vinci PAS | 2.2.1, och 2.1.0 | Inferno 2.2.1: 82 av 84; 2.1.0 av guidens egna exempel |
| Da Vinci PAS, skicka (leverantörssida) | 2.2.1 | HL7 Da Vinci PAS betalningsreferensimplementering; inte en produktionsbetalare |
| Da Vinci PDex | 2.2.0 | Inferno PDex 2.0: betalare-till-betalare 19 av 19 |
Da Vinci HRex $member-match | 1.2.0 | Inferno PDex betalare-till-betalare |
| Da Vinci ATR | 2.1.0 | inte kontrollerad av ett externt verktyg |
Da Vinci CDex $submit-attachment | 2.1 | inte kontrollerad av ett externt verktyg |
| Da Vinci Plan-Net | 1.1.0 | Inferno: 199 pass, 10 misslyckades (en kitdefekt) |
| Da Vinci US Drug Formulary | 2.1.0 | HL7-valideraren |
| ISiK (tyska sjukhus), FHIR-server | Stufe 5, Basis modul | gematiks ISiK-testsvit 3.0.9: 421 av 421 |
| PACIO Transitions of Care, Medication Profile, Advance Directives, Functioning | 1.0.0, 1.0.0, 2.0.0-ballot, 2.0.0 | PACIOs Inferno-kits med PACIOs egna data: varje fel i dess data eller kit. C-CDA till TOC-dokument: HL7-valideraren på HL7s exempel, ett fel kvar, guidens egna |
| CARIN Blue Button | 2.2.0 | HL7-valideraren |
| eCR | 2.1.2 | HL7-valideraren |
| ELR | HL7 2.5.1 ELR Release 1 med dess errata | ONCs ELR-verktyg: 28 av 28 |
| International Patient Summary | 2.0.0 | HL7-valideraren |
| DEQM | 5.0.0 | HL7-valideraren |
| SQL på FHIR | v2 | det officiella testsviten: 144 av 144 |
| SMART Health Cards och Links | Cards 1.4, Links STU 1 | specifikationernas egna exempelkort; en publicerad SMART Health Links-visningsbibliotek |
| UDAP Security | STU 1 | en riktig auktoriseringsserver och förtroendesamhälle |
| TEFCA Facilitated FHIR | SOP v2.0 | inte kontrollerad mot en riktig QHIN |
1.3.3 Nationella och europeiska profiler
Kontrollerad genom att konvertera publicerade eller uppdiktade HL7 v2-meddelanden och validera varje resurs; de fullständiga resultaten och orsakerna till varje misslyckande finns i repositorys conformance/national-mapp.
| Profil | Release | Resurser giltiga |
|---|---|---|
| UK Core | STU2 2.0.2 | 185 av 187 |
| FR Core | 2.2.0 | 138 av 156 |
| ISiK Basismodul | 4.0.3 (Stufe 4) | 18 av 47; 42 av 47 med sjukhusets egen bundle-skript |
| Nictiz nl-core | 0.12.1-beta.1 (zib 2020) | 12 av 24; 18 av 24 med sjukhusets egen bundle-skript |
| HL7 Europe Laboratory Report | 2.1.0 | 106 av 426 (guiden förväntar sig ett dokument, ett v2-resultat är inte) |
| HL7 Europe Hospital Discharge Report | 1.0.0 | 68 av 69 |
Inget av detta är en certifiering. Perfuse har inte certifierats av ONC, CMS, gematik, Nictiz, NHS England eller någon annan.
1.4 Vad det ersätter
Perfuse täcker den mark som Mirth Connect håller, och kan importera Mirth-kanalexport direkt. Kapitlet om migration beskriver vad som översätts rent, vad som behöver ett beslut, och hur man bevisar att resultatet matchar innan man byter.
De skillnader som spelar roll i dagligt bruk är felsökning och tystnad. I Mirth innebär att se vad en transformer gjorde med ett meddelande vanligtvis att man måste distribuera om kanalen med loggning tillagd. I Perfuse kan varje inspelat meddelande spelas upp genom den aktuella konfigurationen och inspekteras steg för steg, utan att röra den körende kanalen. Och där en Mirth-varning för "ingen trafik" är en fast tröskel som är värdelös på någon feed som är tyst på natten, lär sig Perfuse vad varje feeds normala vecka ser ut och varnar mot den.
1.5 Hur man läser den här manualen
De första kapitlen är konceptuella och är värda att läsa i ordning: kanaler, meddelandeflöde, sedan transformation. Allt efter det kan läsas efter behov.
Referenskapitlen nära slutet listar varje konfigurationsnyckel, dess typ, om den är obligatorisk och dess standardvärde. Dessa kapitel genereras från källan, så de kan inte beskriva ett alternativ som inte finns eller utelämna ett som gör det. Om en nyckel visas i en konfigurationsfil och inte i index, är det inte en Perfuse-nyckel.
1.6 Konventioner
Konfigurationen är YAML. De flesta nycklar är snake_case på ledningen — max_message_size, idle_timeout — och den här handboken anger alltid ledningsformen, eftersom det är vad du skriver. Det finns ett undantag, dataType på en kanal, som är camelCase; den dokumenteras på det sättet i kanalreferensen och accepteras endast i den stavningsformen.
Fälthänvisningar i HL7 använder den vanliga notationen: PID-5 är det femte fältet i PID-segmentet, PID-5.1 dess första komponent och PID-3(2) den andra upprepningen av det tredje fältet. En sökväg skriven utan upprepning adresserar varje upprepning (se sökvägar).
Varaktigheter skrivs som ett tal och en enhet — 30s, 5m, 2h. Ett tomt tal är inte en varaktighet och kommer att avvisas i stället för att gissas.
2 Komma igång
Perfuse är en enda binärfil med en inbäddad webbgränssnitt. Det finns ingen programserver att installera, ingen databas att etablera och ingen separat administrationskonsol.
2.1 Körning
perfuse serve -channels ./channels -db ./perfuse.db -addr 0.0.0.0:8443 \
-tls-cert ./cert.pem -tls-key ./key.pem
-channels är en katalog med YAML-filer, en per kanal. -db är en SQLite-fil som innehåller inspelade meddelanden, användare och revisionshistorik; den skapas om den inte finns.
Vid första starten med inga konfigurerade användare skapas ett administratörskonto och dess lösenord skrivs till loggen en gång. Det lösenordet kan inte återställas efteråt.
-tls-cert och -tls-key tjänar vanligt HTTP. Det är acceptabelt på en loopback-adress för en första titt och är inte acceptabelt någon annanstans: webbgränssnittet bär autentiseringsuppgifter och meddelandeinnehåll, båda är läsbara på tråden utan TLS. Se säkerhet.2.2 Den första kanalen
En kanal behöver ett namn, en källa och minst en destination. Den minsta användbara kanalen tar emot HL7 via MLLP och skriver varje meddelande till en fil:
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
Spara det som channels/first-feed.yaml och det plockas upp utan omstart.
Tre saker om den filen är värda att notera, eftersom de är formen på varje kanal:
- Källblocket är platt för MLLP.
listensitter direkt påsource, inte inuti ettsource.mllp-block. Transporter som behöver mer än en adress — HTTP, SOAP, DICOM — har sina egna underblock, och de listas i källreferensen. - En fildestination behöver både
rootochdir.rootär gränsen som sökvägar löses mot och kan inte fly;dirär där meddelanden landar inom den. - Det finns ingen transformation och ingen filter. Båda är valfria, och en kanal med ingen av dem passerar bara meddelanden igenom.
2.3 Bygga en kanal från gränssnittet
Allt ovan kan göras från webbgränssnittet i stället, och för en första kanal är det den bättre vägen eftersom formuläret inte låter dig producera en fil som inte kan laddas.
Byggaren erbjuder tre sätt in:
- Från ett meddelande som någon skickat till dig. Klistra in exemplet som laboratoriet eller leverantören mejlade. Perfuse läser det och föreslår en kanal, tillsammans med tre separata listor: vad exemplet visar, vad som har gissats, och vad inget exempel kan berätta. Detta beskrivs i testing.
- Från något som redan fungerar. En uppsättning kompletta kanaler som bara behöver sina adresser fyllda i.
- Från ingenting. En tom blankett. Tillgänglig, men det är den långsammaste av de tre och den lättaste att få fel.
2.4 Verifiera att det fungerar innan du ansluter något
Två saker kan göras innan skickarsystemet existerar.
Skicka ett meddelande för hand från gränssnittet — meddelandesändaren accepterar klistrat text och rapporterar vad som hände med det, inklusive vilka destinationer som accepterade det och vad varje transformation gjorde.
Eller generera testtrafik. Om kanalen har hanterat några meddelanden alls, kan Perfuse lära sig deras form och producera fler meddelanden som liknar dem, i samma proportioner, utan något av det ursprungliga innehållet. Se testing.
2.5 Vad du ska göra härnäst
- Kanaler förklarar vad en kanal är och hur dess delar passar samman.
- Meddelandeflöde följer ett meddelande från ankomst till leverans, vilket är det snabbaste sättet att förstå var man ska placera en ändring.
- Varning är värt att ställa in innan en feed går live snarare än efter den första incidenten.
3 Webbgränssnittet
Perfuse är byggt på antagandet att allt kan göras från webbläsaren, och en funktion som endast kan nås genom att redigera en fil behandlas som ett fel. Detta kapitel är en översikt av vad som ligger bakom varje del av navigeringen, organiserad på samma sätt som gränssnittet: efter den fråga du ställer.
Menyn innehåller Instrumentpanel och Kanaler direkt, eftersom de är där de flesta sessioner börjar och slutar. Allt annat är grupperat, och grupperna är uppkallade efter frågor snarare än efter undersystem — du går inte till "revisionsundersystemet", du går och tar reda på vem som ändrade något.
3.1 Läsa rubriken
Fem saker i headern är lätta att missa.
Varje vy har en adress. Adressfältet följer vyn — #/channels, #/messages, #/settings — så en omładning återgår till den, en bokmärke öppnar den, en länk som skickas till en kollega landar dem på den, och bakåtknappen flyttar mellan vyerna snarare än att lämna konsolen. En adress som namnger en vy ovanför din roll öppnar instrumentpanelen istället.
Sök, eller ⌘K. Den söker över kanaler, inställningar, meddelanden och handboken, vilket innebär att den vanligtvis är snabbare än navigering — särskilt för en inställning vars namn du halvt minns.
Tema. Tre av dem: Midnight, Dark och Light. Midnight är nästan svart och är vad en väggskärm i ett serverrum vanligtvis vill ha; Dark är en mjukare neutral grå; Light är för en bärbar dator bredvid ett fönster. Valet sparas i webbläsaren snarare än mot kontot, eftersom ett tema är en egenskap av var någon sitter, inte av vem de är — samma operatör vill ha Midnight på väggen och Light på ett tåg. En maskins eget val konsulteras en gång, för att välja ett rimligt standardvärde första gången.
Språk. Konsolen på engelska (Storbritannien eller USA datumordning), tyska, franska, nederländska, spanska, italienska, portugisiska, polska, svenska, danska, norska eller finska, med datum och nummer skrivna på det sätt som lokalen skriver dem. Valet sparas i webbläsaren och webbläsarens eget språk används tills ett val görs. Översättningarna gjordes av maskin och har ännu inte granskats av modersmålstalare; engelska är referensen och väljaren anger detta. Koder, meddelanden, nyttolaster, kanalnammn och allt som skrivs är aldrig översatt. Handboken publiceras på samma språk på https://perfuse.health/manual/<language>/ (den här serverns egen Handbok är den engelska).
Handbok. Dokumentet du läser, serverat av den körande servern. Det är samma fil som binärfilen kan skriva till disk, så det beskriver alltid versionen framför dig snarare än den senaste versionen.
3.2 Övervakning — om det fungerar och vad som hände
3.2.1 Instrumentpanel
Tillståndet för varje kanal, genomströmning och allt som för närvarande är fel. Detta är skärmen som ska lämnas öppen.
3.2.2 Meddelanden
Varje meddelande som anlände, vad det omvandlades till, per destination, och vad som hände med det. Sökbar, inklusive med ett filteruttryck, så "visa mig de som kommer från den här avsändaren som avslogs" är en fråga snarare än en eftermiddag.
Ett meddelande kan spelas upp från här, och omprocessas genom den *nuvarande* konfigurationen snarare än den som var live vid den tidpunkten — vilket är hur du bekräftar att en korrigering fungerar mot den trafik som bröt den. Se meddelandelagringen för vad som sparas och för hur länge.
3.2.3 Kö
Vad som väntar på att levereras, och varför. En kö som inte töms är den mest användbara tidiga varningen en integrationsmotor producerar, och det är värt att para med en varningsregel så att ingen behöver titta. Se leverans.
3.2.4 Aviseringar
Vad som har utlösts och vad reglerna är. Regler redigeras här snarare än i en fil. Se varning.
3.2.5 Mått
Genomströmning, fördröjning och felrater över tid. Användbart för kapacitetsfrågor och, mer ofta, för styrelsepaketen — vilket är varför webbplatsens eget logotyp visas på det om en har laddats upp.
3.2.6 SQL på FHIR
SQL på FHIR-vyer: Välj ett exempel eller en sparad vy, eller skriv en, kör den på den här serverns FHIR-lagringsplats (alla patienter eller en) eller över resurser som klistrats in, se raderna med deras typer och ladda ner CSV, NDJSON eller Parquet. Spara sparar den för FHIR-slutpunkten $sql-run. Se meddelandeformat.
3.2.7 Kvalitetsmått
Digitala kvalitetsmått: Välj ett exempel eller ett mått i FHIR-lagret, eller skriv ett med FHIRPath-kriterier. Välj en mätningsperiod och en rapport (sammanfattning, sammanfattning med patientlistor eller en patient) och utvärdera den över FHIR-lagret eller klistrade resurser. Skärmen visar varje populations räkning och patienter, poängen och strata. Ladda ner MåttRapport sparar FHIR-resultatet, och Spara till FHIR-lagret sparar måttet för Measure/$evaluate-measure. Mått i CQL vägras: Perfuse har ingen CQL-motor. Se digitala kvalitetsmått.
3.2.8 Flödeskarta
En bild av hur meddelanden faktiskt flyttas: vilka källor matar vilka kanaler, och vilka destinationer de når.
Dess värde är inte en dekoration. Varje fastighet ackumulerar en kanal som ingen minns att de beställt och en destination som ingen insett fortfarande tar emot, och båda är synliga här på ett sätt som de inte är i en lista över kanalfiler.
3.2.9 Teaminstrumentpaneler
En instrumentpanel för varje typ av person som övervakar gränssnitten: Drift, Anslutningar, Gränssnittsanalys, Föregående auktorisering, Bild, Intäktscykel, Laboratorium, Sekretess och säkerhet, och en vanlig sammanfattning av avdelningen. Tile visar räkningar, tillstånd och tider, aldrig ett meddelande eller en patient, så en instrumentpanel kan skickas till en chef eller en väggskärm utan att utöka vem som ser patientdata.
Varje person öppnar instrumentpanelen för sin kataloggrupp eller roll som tilldelats. -dashboards dashboards.yaml mappar dem:
groups: {PACS-Admins: imaging, Network-Team: connections}
roles: {viewer: manager}
En grupp tar över en roll och alla som inte matchar öppnas på Drift. Arrange tiles döljer och omordnar tegel, kanalväljaren filtrerar dem och Spara som min vy behåller den som din egen instrumentpanel tills Återställ.
Exportera till Grafana laddar ner instrumentpanelen som Grafana JSON över /metrics, med en datakällvariabel och en kanalfilter, för alla som behöver mer än lätt konfiguration. Tile utan metric bakom dem lämnas ut, och exportbeskrivningen namnger dem.
Den Anslutningar-tile kontrollerar varje nätverksansluten destination i lager. Den söker upp namnet, öppnar en TCP-anslutning, slutför TLS där det används, och läser destinationens senaste leverans och fel från riktigt trafik. Varje fel säger vad det betyder, till exempel "vägrat: partnerns motor är troligen stoppad", "tidsgräns: en brandvägg eller en VPN-tunnel som är nere", eller "ett certifikat från en myndighet som denna server inte litar på". Ingenting skickas till partnern, med ett undantag: en vaccinationsregister som inte har haft någon trafik på sju dagar frågas om dess CDC connectivityTest, som skickar ingenting. Med -vpn tunnels.yaml läser VPN-tunnlar-tile bredvid den varje partnertunnels tillstånd från AWS Site-to-Site VPN, en Azure VPN Gateway-anslutning eller strongSwan på den här värden, så en tidsgräns kan skiljas från en tunnel som är nere. Den jämför också båda sidors IKE- och IPsec-inställningar, eftersom molnet rapporterar våra och filen listar deras, och säger var de inte kan komma överens. Anslutningsschema laddar ner en partnerns inställningar sida vid sida som Markdown för att skicka dem; den håller aldrig en delad nyckel. Siffror som en instrumentpanel behöver som inte är registrerade ännu listas under Inte mätt ännu istället för att ritas som tomma tile.
Avdelningsinstrumentpanelerna beräknar sina egna siffror på servern, och var och en säger vilket fönster och källa den täcker:
- Föregående auktorisering: PAS-förfrågningar beslutade inom CMS-0057:s 72 timmar (påskyndat) eller 7 dagar (standard), beslutade sent, väntande och försenade just nu, med median tid till beslut. Även hur de begärda tjänsterna besvarades (godkända, ändrade, nekade, väntande), som var och en för närvarande står, under 30 dagar.
- Bild: objekt mottagna av C-STORE per modalitet, och de som inte levererades. Även routningsförseningen per kanal (median och 95:e percentil), C-FIND-frågor och fel per frågekanal, och bilddokument (en ORU vars OBR-24 är en bildsektion, eller en MDM) som inte nådde varje destination.
- Intäktscykel: 999 transaktionsuppsättningar godkända, godkända med fel och avvisade, och 277CA-anspråk godkända och avvisade (A3, A4, A6, A7, A8). Även 835-anspråk som matchats av patientkontonummer till 837:or som skickats via denna server, och de vanligaste avvisningsorsakerna.
- Laboratorium: resultatleveranstid, från mottagande till den sista destinationens bekräftelse, och kritiska resultat (OBX-8 HH, LL, AA, > eller <) som inte nådde varje destination.
- Integritet och säkerhet: vem som öppnade meddelanden, sökte efter patienter eller läste föregående auktoriseringar i konsolen under 7 dagar, från granskningsloggen (att öppna ett meddelande loggas som
message.read). Även varje aktiv API-token och när den senast användes; en token som inte har använts på 90 dagar markeras.
3.2.10 Dela vad en feed faktiskt innehåller
Profilera denna feed rapporterar vad som faktiskt anländer: vilka utlösande händelser, vilka fält som är ifyllda och hur ofta, vilka former värdena tar, och vilka koder en avsändare faktiskt använder. Den sista är vanligtvis den mest användbara enskilda faktan i den.
En profil kan laddas ner och skickas till någon annan. Den behöver ett namn och — obligatoriskt — vilket system som producerade feeden, eftersom frågan en främling ställer till en delad profil är om den beskriver deras system, och ett valfritt fält skulle göra "Okänt" den vanligaste svaret i någon delad samling.
Den innehåller inga patientdata, och det kontrolleras snarare än antas. En profil är statistisk: räkningar, hastigheter, längder, former. Värden behålls endast för fält som standarden definierar som kodtabeller, eftersom en kodtabellsvärde inte är identifierande. Identifierarvärden listas aldrig.
Två saker följer av att det är ett löfte snarare än en förhoppning. Servern bygger om profilen från de lagrade meddelandena när du exporterar den, snarare än att skicka den som visas på din skärm — så det som lämnar byggnaden sattes samman av profilen, som har ett test som bevisar den här egenskapen, inte av en webbläsare. Och exporten vägrar helt enkelt om en profil någonsin listar värden för ett fält som inte är en kodtabell, och namnger fältet men inte värdena.
En profil som anländer från någon annanstans kontrolleras på samma sätt på vägen in, av en annan anledning: den producerades av någon vars omsorg är okänd, och att visa patienternas identifierare skulle vara den här serverns avslöjande. Att importera en ändrar ingenting — en profil beskriver en feed, och vad man ska göra med den är ett separat beslut.
3.3 Bygg — ändra vad en kanal gör, och testa den innan den är live
3.3.1 Kanaler
Kanalbyggaren. Källor, destinationer, filter, transformationer, skript och tester, med den genererade YAML-filen visas bredvid formuläret medan du arbetar — så filen är aldrig en hemlighet, och vem som helst som föredrar filen kan läsa med.
Se kanaler för vad delarna är, och omvandling för vad stegen gör.
3.3.2 Skript
En arbetsyta för skript, separat från byggaren eftersom att skriva ett skript och ansluta ett skript är olika aktiviteter.
Alla sju platser erbjuds — filter, transformer, preprocessor, postprocessor, writer, lifecycle och reader — och att välja rätt plats är viktigt, eftersom platsen bestämmer vad skriptet tar emot och vad det förväntas returnera. Att kontrollera ett skript som fel typ är inte en lösning; det kompilerar en annan sak.
JavaScript, Lua och WebAssembly är alla tillgängliga. Se transformation.
3.3.3 Kontrakt
Förväntningar om hur en feed måste se ut skapas och kontrolleras här samt från perfuse contract. Se kommandoraden.
3.3.4 Tabeller
Söktabeller och koduppsättningar: de mappningar som omvandlar ett systems koder till ett annat systems. Redigerbara här så att tillägg av en kod inte är en distribution.
3.3.5 AI-mappare
Föreslår fältmappningar med en konfidenspoäng för var och en, och avstår hellre än att gissa. Trots namnet använder den ingen språkmodell och gör ingen nätverksanrop: förslagen kommer från regler, fältnamn och provets innehåll, på den här servern. Den föreslår också en kanal från ett enda provmeddelande, och uttalar explicit vad provet inte kan säga. Den andra halvan är den del som gör den tillförlitlig — ett förslag som såg komplett ut skulle inbjuda dig att tro saker som meddelandet aldrig sa.
3.3.6 Lekplats
En skissbok för meddelanden och transformationer. Klistra in ett meddelande, applicera steg, se resultatet.
Ingenting skickas någonstans en gång sidan har laddats, vilket är anledningen till att den existerar i den här formen: det är säkert att klistra in något riktigt i den, med förståelsen att det stannar i webbläsaren.
3.3.7 Skugga
Kör trafik genom en kandidatkonfiguration bredvid den aktiva och rapporterar skillnaderna, så att en förändring kan beläggas innan den godkänns. Samma idé som perfuse compare, tillämpad på en förändring snarare än en migration. Se testing.
3.4 Utbyte — de standarder den här servern talar till andra organisationer
3.4.1 FHIR-lab
Konvertera HL7 v2 till FHIR, validera en resurs och inspektera resultatet. Exemplen täcker inläggningar, laboratorieresultat, möten, kliniska anteckningar, vaccinationer och en rapporterbar besök. Valideringen inkluderar US Core, som är den profil som amerikansk reglering är skriven mot, så det här svarar på "är det de skickade oss verkligen konformt" utan att anta någonting.
Allmän hälsorapport bygger eCR eICR en rapporteringsdestination skulle skicka för meddelandet. Den visar vilken utlösande kod som gjorde besöket rapporterbart, vad rapporten måste markera som saknad, och dokumentet i sig. Ett meddelande med ingenting rapporterbart får orsaken istället. Ingenting skickas från här.
3.4.2 Prenumerationer
FHIR-prenumerationer och om deras meddelanden anländer: händelser, accepterade, väntande och den senaste anledningen till att en avslogs. Prenumerationer skapas av FHIR-klienter via FHIR-API:et, inte från den här sidan, och de autentiseringsuppgifter de gav servern visas aldrig. Se meddelandeformat.
3.4.3 Dokument
Kliniska dokument — CDA och den utskrivbara formen av ett dokument. Användbart när det som utbyts är en utskrivnings sammanfattning snarare än ett meddelande.
3.4.4 Dokumentdelning
IHE XDS.b-registret och lagringsplatsen som startade med -xds: hur många dokument, patienter och insättningsuppsättningar den innehåller och hur många som ersatts; adresserna till lagringsplatsen, registret, XCA-gatewayen och MHD; en sökning efter en patients dokument i detta register eller en annan gemenskaps (ett ITI-18-register eller en ITI-38-gateway, med en token för den); och publicering av ett CDA-dokument för hand, med anläggningstypen och verksamhetsområdet som ett dokument inte säger. Se meddelandeformat.
3.4.5 Direkt
Direkt säker meddelandesändning. Denna servers Direktadresser listar varje adress som en kanal skickar eller tar emot som, med dess certifikat, när det utgår, de ankare det litar på och allt som är fel (en saknad fil, ett utgånget certifikat). Adressboken sparar korrespondenter och de certifikat som deras e-post krypteras med: klistra in ett från deras HISP eller Spara med certifikatet från DNS; ett certifikat som inte är för adressen eller dess domän avvisas. Hitta ett certifikat i DNS frågar utan att spara. Se meddelandeformat.
3.4.6 Hälso länkar
SMART Hälsolänkar och -kort, för CMS:s *Döda urklippet*. Ta emot en SMART Hälsolänk läser länken eller QR-koden en patient visar vid incheckning, verifierar hälsokorten inuti och skickar den vidare till en kanal. Dela en besöksjournal skapar en länk som denna server värdar, eventuellt med en lösenkod, och en QR-kod för patienten; Använd deras patientöversikt fyller i den med patientens Internationella patientöversikt från denna servers FHIR-lagring. Länkar som denna server värdar listar dem med hur ofta var och en hämtats, när den utgår och antalet lösenkods försök kvar, och återkallar en. Verifiera en SMART Hälsokort kontrollerar ett kortsignatur och utfärdare på egen hand. Se CMS-0057 för de serveralternativ som behövs.
3.4.7 Bild
Arkivet som den här servern behåller när den körs med -dicomweb-archive: räkningar av studier, serier, instanser och använd utrymme, DICOMweb-adressen och datakällblocket för en OHIF-visare, och en studiesökning efter patientnamn, ID, remiss och datum gjord med samma QIDO-RS-förfrågan som en visare gör. En studie öppnas till sina serier och instanser, och en instans laddas ner som en DICOM-fil. Ingenting renderas: Perfuse flyttar bilder och en visare visar dem. Utan ett arkiv säger skärmen hur man aktiverar detta. Se DICOMweb.
3.4.8 TEFCA
Revisions spåret för utbyte genom ett kvalificerat hälsoinformationsnätverk, och ändamålsanvändningsreglerna som styr det.
Två transport medel, i genuint olika skeden, och skärmen säger vilket som är vilket. En flagga som täcker båda skulle vara fel i vilken riktning den än avrundades.
Underlättat FHIR är implementerat, och har aldrig talat med ett riktigt QHIN. Det följer Sequoia Project Standard Operating Procedure som trädde i kraft den 8 mars 2026: upptäck partnerens UDAP-metadata, verifiera den, registrera dynamiskt, hämta en åtkomsttoken som bär ändamålet med användning, och fråga. UDAP är en offentlig nyckelinfrastruktur över OAuth 2.0 — en tillitsgemenskap utfärdar X.509-certifikat till sina medlemmar, och en medlem autentiserar genom att signera JWT:er med den privata nyckeln och bifoga certifikatkedjan.
Säkerhetsskiktet är verifierat mot någon annans implementering, vilket är den enda verifiering som är värd något här. En registrering som undertecknats av denna version skickades till en live tredje parts referensserver och avslogs med unapproved_software_statement — Untrusted: Certificate is not a member of community. För att producera det svaret avkodade servern begäran, parsa software-uttalandet som en JWT, kontrollerade dess signatur, gick igenom certifikatkedjan och fattade ett beslut om medlemskap. Det är skillnaden mellan att bli avvisad vid dörren och att få tillbaka ett oläsligt brev.
Vad som återstår kan inte göras från här. Certifikatet som bevisar gemenskapsmedlemskap kommer ut ur QHIN-ombordstigning och är inte något som programvara producerar. Tills ett finns, slutförs inget utbyte med en riktig partner.
Hur en kanal ber om. En destination av typ tefca ber den faciliterade FHIR-partnersatsen i Inställningar, TEFCA (tefca.partnerFHIRBase) om varje meddelandes patient: genom identifierare när meddelandet har en (PID-3, eller en FHIR-patients identifierare), annars genom efternamn med födelsedatum, och aldrig genom ett namn ensamt, eftersom en felaktig matchning på ett namn returnerar någon annans post utan fel. Destinationen anger ändamålet med användningen (behandling, betalning, drift, folkhälsa, individuell åtkomst); ett ändamål som deltagaren inte deklarerar avvisas innan något skickas. Ändamålen skickas som TEFCA-utbytesändamålskoder (T-TRTMNT, T-PYMNT, T-HCO, T-PH, T-IAS, system urn:oid:2.16.840.1.113883.3.7204.1.5.2.1), eller med tefca.purposeCodes: hl7 som HL7-ändamålskoder för samhällen som använder dem. Det funna paketet är destinationens svar och kan skickas till en annan kanal med results_to. Varje fråga, inklusive avvisade, finns i spåret på den här skärmen, som namnger parten.
Hela vägen, från upptäckt till en token som partnerns FHIR-server accepterar, testas mot udap-dotnet-referensservern (se verifikation).
Det äldre QHIN-till-QHIN-utbytet som bygger på IHE-profilerna är inte implementerat. Ett försök avvisas med ett fel som säger så, och avvisandet loggas som ett misslyckande. Det är medvetet snarare än väntande på en uppstädning: ett stubbat utbyte som rapporterar framgång skulle sätta in poster i revisions spåret för utbyten som aldrig hände, och ett spår som inte stämmer överens med vad som hände är värre än inget, eftersom spåret är vad som får tro.
Genomgående kommer slutpunkterna som används för utbyte från den undertecknade delen av en partners metadata, aldrig dokumentkroppen. Att verifiera en signatur och sedan läsa slutpunkterna från den osignerade kopian skulle vara ett elaborerat sätt att lita på nätverket: en angripare som kan skriva om svaret lämnar den undertecknade delen ensam, pekar token-slutpunkten mot sin egen server och samlar in klientpåståenden från alla som kontrollerade signaturerna och sedan ignorerade vad den täckte.
Ett tillitsankar-paket krävs och dess frånvaro vägras vid start. Att kontrollera en partners signerade metadata mot certifikatet som anlände inuti det bevisar endast att en part gjorde båda — ett misstag som detta kodunderlag har gjort tidigare, i SAML, där verifieraren föredrog det inbäddade certifikatet och autentiserade en angripare som administratör medan alla tester passerade. Inkludera mellanliggande certifikat i paketet: en UDAP-server behöver endast skicka sitt lövcertifikat, och den offentliga referensservern gör exakt det.
3.5 Försäkringsgivare — anspråk, förhandsgodkännande, läkemedel och CMS-försäkringsgivarens regler
3.5.1 Anspråk och autentisering
Bygg ett X12 275-anspråksbilaga i 006020-formen som CMS-0053-F antar, från en klistrad C-CDA eller en uppladdad PDF, TIFF eller JPEG, och se det läsas tillbaka. Läs en 275 och ladda ner dokumentet inuti. Konvertera en X12 278-beslut till en Da Vinci PAS ClaimResponse. Ingenting på den här sidan sparas eller skickas. Se meddelandeformat för vad 275 byggs från och vad den inte gör.
3.5.2 Läkemedel
Läkemedelsformuläret som laddats med -formulary, och de två NCPDP-standarderna som svaras från det. Formulär listar planerna och läkemedlen med deras nivå och krav, och var den offentliga Da Vinci US Drug Formulary API och NCPDP-slutpunkterna är. Priskontroll (RTPB) prissätter ett läkemedel för en medlem som en läkares Real-Time Prescription Benefit-förfrågan skulle: täckningsstatus, begränsningar i ord med deras koder, medlemmens andel och planens, och billigare alternativ. Förautorisering (ePA) skickar en SCRIPT-initiering till denna servers egen slutpunkt, visar frågesättet som ett formulär, skickar svaren och visar beslutet; nedan, varje ärende med var det står och om läkaren har informerats, ärendets svar, en knapp för att skicka ett osänt beslut igen, och läkemedelsstatistiken som CMS-0062-P föreslår. Se CMS-0057.
3.5.3 CMS-0057
Försäkringsgivarens sida av CMS Interoperability och förhandsgodkännanderegel, som fem verktyg:
- De fyra API:erna: om Patient Access, Provider Access, Payer-to-Payer och Föregående auktorisering är klara på denna instans, och vad var och en fortfarande behöver.
- Granskningskö: PAS-förfrågningar som väntar på en person, närmast förfallna först, med de dokument som skickats för var och en; godkänn, avvisa eller certifiera färre enheter. Se granskningskö.
- Anspråk till CARIN BB: en 837 och dess 835 omvandlad till CARIN Blue Button-paket.
- Föregående auktorisering till PDex: en PAS-svar omvandlad till en PDex-föregående auktorisering.
- Föregående auktoriseringsmått: den årliga offentliga föregående auktoriseringsmåttssidan, förhandsgranskad från en CSV-fil med beslut.
Konverteringarna lagrar ingenting och skickar ingenting.
3.5.4 CMS-justerad nätverk
Beredskap för CMS Interoperability Framework: var och en av dess 26 kriterier, grupperade som CMS grupperar dem, med vad Perfuse tillhandahåller, om det är påslaget här, inställningen som slår på det och vad organisationen ska göra. Antalen överst filtrerar listan. Se CMS-0057.
3.6 Administrera — vem som kan göra vad, och hur den här servern är konfigurerad
3.6.1 Användare
Accounts, roles (monitor, viewer, operator, editor, admin) and channel groups. Each person's channel groups are edited in place in the list; empty means every channel, and lab=editor, adt gives a different role in one group. An administrator limited to some groups sees only the people of those groups. The header shows your own groups beside your role when you have any. See security.
Maskincredentier finns också här. En token är för en maskin snarare än en person: den upphör inte att gälla och påverkas inte av att någon loggar ut, vilket är vad en server som pollar sin granne behöver. Endast en hash lagras, så en token visas en gång när den skapas och kan inte återställas — en stulen databas ger ingen användbar token. Ge en den lägsta rollen som gör jobbet.
Med MCP på, visar avsnittet också adressen som en AI-agent ansluter till, en klientkonfiguration för att kopiera och varje verktyg med den roll som behövs; utfärdande av en token med Låt en AI-agent agera med det ger den mcp:write-omfånget. Se säkerhet.
3.6.2 Hyresgäster
På en delad server, plattformsoperatörens lista över organisationer: var och en av deras kanalantal och lagrad storlek bredvid deras gränser (kanaler, meddelanden per minut, lagring), som ställs in på plats. Visas endast för plattformsrollen. Se säkerhet för vad varje gräns gör.
3.6.3 Certifikat
De TLS-certifikat som används och när de upphör att gälla. Upphörandedatum är punkten: ett certifikat som upphörde att gälla på en söndag är en klass av avbrott som helt och hållet kan förhindras och rutinmässigt inte förhindras.
3.6.4 Aktivitet
Vem som ändrade vad, och när. Varje konfigurationsändring spelas in, vilket är vad som gör "det började misslyckas på tisdag" svarbart.
3.6.5 Dataskydd
En persons begäranden enligt GDPR och UK GDPR, rättsliga kvarhållningar, suddningsregistret, kvarhållning och register över behandlingsaktiviteter; endast administratörer. Se dataskydd.
3.6.6 Flotta
Varje Perfuse-instans på en sida.
Mirth säljer detta som ett separat produkt; här är det en konfigurationsfil och en skrivskyddad token. Anledningen till att det är värt att ha är smal och viktig: en död server ser inte ut som en tyst en. En enda instans dashboard kan inte berätta för dig att en andra plats har slutat rapportera, och en flotta vy kan.
3.6.7 Migrera
Lägg till en Mirth eller OIE-kanal export och se hur många av dina kanaler som skulle köra här oförändrade. Samma analys som perfuse explain och perfuse translate, utan att behöva en terminal. Se migration.
3.6.8 Inställningar
Varje inställning som servern har, med en kontroll för var och en — inklusive de som traditionellt bara lever i en fil. Var och en säger om den träder i kraft omedelbart eller behöver en omstart, och om den har ställts in uttryckligen eller sitter på sin standard.
Inställningarna omfattar varje perfuse serve-alternativ som slår på en funktion: FHIR-slutpunkten och dess version, payer-API:erna, PAS och CRD-reglerna, X12 278-bron, eCR, SMART-autentiseringsservern, TLS och signering, statistik, flotta och VPN. De är grupperade som FHIR, Payer, Folkhälsa, SMART, Säkerhet och så vidare. Var och en visas också med flaggan den motsvarar.
Omstart från konsolen. En inställning markerad *Kräver omstart* sparas omedelbart men läses endast när servern startar. Medan några väntar, listar en banner överst i Inställningar dem med en Omstarta servern-knapp (inloggningsredigeraren och inställningsfilerna erbjuder samma knapp efter en sparande). Den frågar först, eftersom varje kanal slutar i några sekunder: var och en avslutar meddelandet den hanterar, som den gör när tjänsten stoppas, och avsändare skickar om vad som anländer under tiden. Konsolen väntar sedan på att servern ska svara igen och läser inställningarna på nytt. Endast en administratör kan starta om, och varje omstart loggas i aktivitetsloggen som server.restart.
På Linux och macOS ersätter processen sig själv med en färsk kopia av samma program och argument, och behåller process-ID, så systemd, launchd eller en containerkörning ser ingenting hända. På Windows startar servern om igen inom samma process, som behåller en Windows-tjänst under tjänstehanteraren. Om servern inte har svarat efter två minuter, säger konsolen till; orsaken är i serverns logg.
Flaggor och inställningsfilen. Första gången servern startas skrivs flaggorna den fick till inställningsfilen. Därefter vinner filen över flaggorna, så ändring av en inställning görs i konsollen (eller filen), inte genom att redigera servicekommandoraden. En flagga som filen ännu inte nämner sparas när servern startar med den. Att ta bort en flagga från kommandoraden senare stänger inte av dess funktion: stäng av den i Inställningar.
SNMP har en panel under inställningarna: om agenten svarar och på vilken adress, nätverken den svarar, hur många varningsfällor som skickats eller misslyckats, och Ladda ner MIB för det bas-OID som används. Värdena ställs in under Övervakning, SNMP.
Varumärke finns också här: en webbplats kan ange produktnamn, en tagline, en accentfärg och ladda upp en logotyp. Logotypen visas sedan i headern, på inloggningssidan, på instrumentpanelen och på rapporteringsskärmarna. Om ingen laddas upp, ersätts ingenting — en ovarumärkt installation förblir ovarumärkt snarare än att den får dekoration.
3.7 Vad färgerna betyder
Fyra register, och var och en säger något annat. Distinktionen är värd att nämna eftersom det är skillnaden mellan en skärm som kan läsas i ett ögonblick och en där allt tävlar om uppmärksamhet.
Vanlig text är en faktor om hur Perfuse fungerar. Större delen av gränssnittet. Ingenting är färgat för att tala om att det är viktigt.
Grön betyder att något lyckades just nu, på grund av något du gjorde. Den visas efter en åtgärd och består inte.
Gul är en varning: värd att veta innan du agerar, och inte ett fel. En funktion som inte är aktiverad, en inställning vars ändringar granskas, en omvandling som approximerar snarare än återger, en transport Perfuse hanterar men inte kan fullständigt verifiera. Gul är färgen på "läs detta innan du fortsätter".
Röd betyder att något är fel just nu. Ett värde som avslogs, en begäran som misslyckades, ett certifikat som har gått ut, en kritisk varning som utlöses. Ingenting annat använder den.
Den sista regeln är varför en skärm inte öppnas röd. Röd är den enda färgen som bär en instruktion — stopp, och det kan vara något du gjorde — och en skärm som använder den för dekoration har ingenting kvar att säga när indata verkligen är fel. Detta var inte alltid sant: användargränssnittet använde tidigare att öppna med "servern skickade ett svar som inte kunde läsas" på varje installation som inte hade konfigurerat passnycklar, och inställningsskärmen markerade granskade värden i samma färg som ett avsagt värde. Ett test i web/src/RedMeansWrong.test.ts misslyckas nu om en fras som beskriver något som saknas eller approximeras ges en röd stil.
Inuti en kodruta är vokabulären annorlunda. Där är röd en token-typ — ett HL7-segmentnamn, ett XML-element — och bär ingen bedömning alls.
4 Kanaler
En kanal är en flöde av meddelanden: någonstans kommer de från, valfria ändringar och en eller flera platser där de går. Det är konfigurationsenheten, övervakningsenheten och distributionsenheten. Allt annat i Perfuse finns för att betjäna kanaler.
4.1 Anatomi
En kanalfil har dessa delar, i den ordning de träder i kraft:
| Del | Nyckel | Obligatorisk | Vad den gör |
|---|---|---|---|
| Identitet | name | ja | Namnger kanalen. Måste vara unik. |
| Datatyp | dataType | nej | Hur meddelanden ska tolkas. Standard är HL7 v2. |
| Källa | source | ja | Var meddelanden anländer från. Exakt en. |
| Filter | filter | nej | Beslutar vilka meddelanden som ska accepteras. |
| Transformationer | transformations | nej | Ordning av ändringar i meddelandet. |
| Mål | destinations | ja | Var meddelanden går. Ett eller flera. |
Plus flera som gäller för hela kanalen: scripts, shadow, contract, tables, attachments, group och enabled. Var och en beskrivs i kanalreferensen.
4.2 En källa, många mål
Denna asymmetri är medveten och det är värt att förstå tidigt, eftersom det är den vanligaste källan till förvirring när man kommer från en annan motor.
En kanal har exakt en källa. Om meddelanden anländer från två platser, är det två kanaler. Att försöka uttrycka det som en kanal producerar en konfiguration där ett fel i någon transport ser ut som samma sak utifrån, och där de två flödenas trafik blandas ihop i statistiken — så en minskning i en döljs av den andra.
En kanal har valfritt antal mål, och de är oberoende. Ett fel i en stoppar inte de andra, och var och en har sin egen kö, sin egen återförsöksprincip och sin egen leveranspost. Ett meddelande som nått tre av fyra mål registreras som exakt det, inte som en framgång eller ett misslyckande.
4.3 Mål är inte en kedja
Varje mål tar emot meddelandet som det var efter kanalens transformationer. Ett mål tar inte emot utdata från målet före det.
Detta är viktigt när ett mål har sina egna transformationer, vilket det kan ha. Dessa gäller endast för den målets kopia. Ett vanligt misstag är att lägga till en ändring i det första målet och förvänta sig att det andra ska se den.
Om du verkligen behöver en kedja — utdata från ett flöde som matar in ett annat — använd en kanaldestination, som skickar till en annan kanal med namn. Det är explicit, visas i meddelandehistoriken som två kanaler och kan övervakas som två saker, vilket en dold kedja inte kan.
4.4 Namngivning
Namnet är kanalens identitet överallt: i filen, i meddelandelagret, i larm, i revisionsloggen och i URL:en. Att ändra det är inte en omnamning; det är en ny kanal, och den gamla kanalens historia stannar under det gamla namnet.
group är separat och finns för att organisera gränssnittet. En grupp har ingen effekt på beteendet, och gruppering av kanaler gör dem inte delar något.
adt-inbound.4.5 Aktivering och inaktivering
enabled: false stoppar en kanal från att starta utan att ta bort den. Dess konfiguration, historia och statistik stannar.
En inaktiverad kanal är inte en pausad. Dess källa lyssnar inte, så en avsändare som försöker ansluta får en vägrat anslutning istället för en hängande. För MLLP är det rätt beteende — avsändaren kommer att köa och försöka igen — men det betyder att avsändarens egen fellogg kommer att fyllas, så en inaktiverad kanal är inte en ersättning för att ordna en driftstörning med den som skickar.
4.6 Var kanaler bor
En YAML-fil per kanal, i katalogen som anges av -channels. Filnamnet är inte kanalnamnet; name-nyckeln är. Att hålla dem desamma rekommenderas starkt och ingenting tvingar det.
Filer läses om utan omstart. En fil som inte kan tolkas rapporteras och den tidigare laddade versionen fortsätter att köra, så ett syntaxfel kan inte ta en fungerande feed ur luften.
4.7 Kryptera en kanals egen lyssnare
En kanal som lyssnar på en port är sin egen server, och dess TLS är separat från TLS på Perfuses webbgränssnitt. Att ställa in en av dem påverkar inte den andra. För en HTTP-källa finns inställningarna under TLS och begränsningar på källan.
Att aktivera TLS begär ett certifikat och en privat nyckel. Att kräva ett klientcertifikat omvandlar det till ömsesidig TLS: avsändaren måste presentera ett certifikat som är undertecknat av en myndighet som du namnger, vilket är en autentisering, så en lyssnare med det aktiverat behöver inte heller en delad token — även om det inte är fel att ha båda.
Myndigheten begärs endast en gång ett klientcertifikat krävs, och lämnas ut ur filen tills dess. En kanal som namnger en myndighet som aldrig konsulteras ser ut som om avsändare verifieras när de inte är det.
En MLLP-lyssnare har samma inställningar under Kryptera denna lyssnare, med en skillnad som är värd att nämna: på MLLP är ett klientcertifikat den enda autentiseringen som är tillgänglig. Det finns ingen token och ingen rubrik, så en lyssnare utan ett accepterar meddelanden från vilken värd som helst som kan nå porten.
Två begränsningar sitter bredvid den. Ge upp läsning efter en varaktighet, eftersom en avsändare som öppnar en anslutning och slutar skriva annars håller den öppen. Och största meddelande som accepteras, i byte, eftersom noll betyder ingen begränsning och begränsningen är då minne — en avsändare som skickar ett gigabyte avvisas hellre än absorberas.
4.8 Validering
En kanal kontrolleras när den laddas, och kontrollerna är avslag snarare än varningar där alternativet skulle vara en kanal som körs och gör fel.
Exempel på saker som avslås direkt: en destination utan typ, en transformation som adresserar en sökväg som inte kan finnas i den deklarerade datatypen, en bekräftelseläge som källtransporten inte kan leverera, och ett recept på narkotikaklass II med påfyllningar.
Distinktionen Perfuse försöker hålla är att allt som skulle producera ett trovärdigt felaktigt resultat avslås, och allt som är ovanligt tillåts och rapporteras. En kanal som inte kan vara fel är mer värdefull än en kanal som startar.
5 Meddelandeflöde
Detta kapitel följer ett meddelande från det ögonblick det anländer till det ögonblick det levereras eller ges upp på. Att känna till denna ordning är det snabbaste sättet att ta reda på var en ändring hör hemma, och varför något inte händer.
5.1 Händelseordningen
- Ankomst. Källan accepterar byte. För en strömtransport inkluderar detta också deframing - att hitta var ett meddelande slutar och nästa börjar.
- Tolka. Byte blir ett träd enligt kanalens
dataType. Ett meddelande som inte kan tolkas slutar här och sparas som ett tolkningsfel. - Spela in. Meddelandet skrivs till meddelandelagret som mottaget, innan något modifierar det. Detta är vad som gör det möjligt att spela upp och bearbeta om.
- Filtrera. Om kanalen har ett
filter, bestämmer det om meddelandet ska accepteras. Ett avvisat meddelande sparas som filtrerat, vilket är ett normalt resultat och inte ett fel. - Transformera. Kanalens
transformationskörs i ordning, var och en mot föregående resultat. - Fläkt ut. Varje destination får en kopia av det transformerade meddelandet, tillämpar sina egna transformationer om den har några, och levererar.
- Spela in resultatet. Per destination: levererat, köat, misslyckat eller filtrerat.
- Bekräfta. Om källan förväntar sig en bekräftelse, genereras och skickas den. Som standard sker detta här, efter leverans — se nedan.
5.2 När bekräftelsen skickas
Detta är den mest konsekvensrika inställningen i en kanal, eftersom det bestämmer vad avsändaren lovas. Det är ack.when, och det har två värden.
on_delivery är standard. Bekräftelsen skickas endast efter att varje aktiverad destination har accepterat meddelandet. En positiv bekräftelse betyder därför att data faktiskt anlände någonstans, vilket är det starkaste påståendet en motor i mitten kan ärligt göra.
on_receipt bekräftar så snart meddelandet är tolkat och köat, innan någon destination har skrivits.
Perfuse använder on_delivery som standard eftersom det är värre att lova leverans och sedan förlora meddelandet än att vara långsam. Under on_receipt kan ett meddelande som har bekräftats fortfarande förloras om processen dör med arbete i kö — avsändaren tror att det är levererat, ingenting uppströms kommer att skicka det igen, och den enda posten som visar att det existerade är i Perfuses eget lager.
5.3 När man ska välja on_receipt
Fallet för det är verkligt, och det är tidsgränser. En MLLP-avsändare som inte får en bekräftelse inom några sekunder kommer vanligtvis att skicka igen, så en långsam destination under on_delivery producerar dubbletter snarare än fördröjning. Om en destination är ett långsamt arkiv eller ett system som regelbundet är otillgängligt, kopplar on_delivery avsändarens tidsgräns till den destinationens värsta fall.
Handeln är uttrycklig: on_receipt flyttar risken från dubbletter till förlust. Att välja det innebär att man accepterar att ett bekräftat meddelande kan gå förlorat vid en krasch, och det är värt att kombinera med varning för ködjup så att en kö som har slutat att tömmas upptäcks. Se varning.
5.4 Var meddelandet spelas in
Innan filtret, och därför innan någon transformation. Tre konsekvenser:
- Ett meddelande som filtret avvisade finns fortfarande i lagret. Du kan se vad som anlände och bekräfta att filtret var rätt.
- Uppspelning och ombehandling börjar alltid från vad som faktiskt anlände, inte från en delvis omvandlad version.
- En ändring av omvandlingarna kan testas mot riktiga historiska data, eftersom originalet fortfarande finns. Se testing.
Den omvandlade formen sparas också, per destination, bredvid resultatet. Så lagret innehåller vad som anlände, vad som skickades och vad som hände — vilket är vad en utredning behöver.
5.5 Fel vid varje stadium
| Steg | Vad fel ser ut som | Vad händer |
|---|---|---|
| Ankomst | Ramfel, anslutning stängs mitt i meddelandet | Spelas in, anslutning stängs, avsändaren försöker igen |
| Parsning | Inte giltig för den deklarerade typen | Spelas in som parsningsfel, negativ bekräftelse om källan förväntar sig en |
| Filter | Själva filtret genererar fel | Hanteras som ett avslag, spelas in med felet |
| Omvandling | Ett steg misslyckas | Beror på stegets on_error; se omvandling |
| Leverans | Destinationen är otillgänglig eller avvisar | Köas och försöks igen enligt destinationens policy; se leverans |
Den viktiga asymmetrin: ett parsningsfel är permanent och ett leveransfel vanligtvis inte är det. Att försöka igen med ett oparsbart meddelande kommer aldrig att hjälpa, så det försöks inte igen. Att försöka igen med en otillgänglig destination kommer vanligtvis att hjälpa, så det försöks igen.
5.6 Ordning
Inom en destination levereras meddelanden i den ordning de anlände, och ett meddelande som misslyckas och hamnar i kön håller sin plats — senare meddelanden väntar bakom det i stället för att ta över.
Detta är standardvärdet för kliniska data, där en inläggning följt av en utskrivning som levereras i fel ordning är värre än att båda är sena. Det betyder också att ett förgiftat meddelande kan hålla upp en kö, vilket är varför ködjup är värt att varna för.
Mellan destinationer finns det ingen ordningsgaranti, eftersom de är oberoende. Två destinationer kommer inte nödvändigtvis att ta emot samma meddelande samtidigt, och en snabb kan vara flera meddelanden före en långsam.
5.7 Samtidighet
En källa kan hantera flera anslutningar samtidigt, begränsat av max_connections. Meddelanden från olika anslutningar bearbetas samtidigt.
Detta betyder att ankomstordningen för två meddelanden som skickas samtidigt ner för två anslutningar inte är definierad och kan inte vara det — de anlände verkligen samtidigt. En avsändare som behöver ordning måste använda en anslutning, vilket är vad nästan alla av dem gör.
6 Omvandling
Omvandlingar ändrar ett meddelande. De är en lista, de körs i ordning och varje steg ser resultatet av det föregående steget.
Perfuses transformationer är deklarativa: varje steg namnger en operation och det fält den tillämpas på. Det finns inget skriptspråk i den vanliga vägen. Detta är en medveten begränsning och resonemanget finns i varför inte ett skript nedan.
6.1 Stegen
| Steg | Vad det gör |
|---|---|
set | Skriver ett litteralt värde till en sökväg, skapar den om den saknas. |
copy | Kopierar en sökväg till en annan, med ett valfritt standardvärde när källan saknas. |
clear | Tömmar ett fält, lämnar det närvarande. |
remove | Tar bort ett fält helt. |
map | Söker upp det aktuella värdet i en tabell och ersätter det. |
replace | Reguljär uttrycksersättning inom ett fält. |
pad | Fyller ett värde till en fast bredd. |
date | Konverterar ett datum eller tidsstämpel mellan format. |
trim | Tar bort omgivande blanktecken. |
case | Konverterar till versal eller gemen. |
Varje steg accepterar också description, som visas i spåret och i gränssnittet, och when, som gör steget villkorligt.
Ett steg skrivs som operationsnamnet med sin egen block:
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 och value är inte syskon. set tar ett block som innehåller path och value. Att skriva set: PID-3.4 med value: bredvid det är det vanligaste felet i en handskriven kanal och producerar ett laddningsfel i stället för en tyst misskonfiguration.6.2 Rensa, ta bort och skillnaden
clear lämnar fältet närvarande och tomt. remove tar bort det helt.
För HL7 är denna distinktion verklig och den når mottagaren. Ett tomt fält säger "Jag har detta fält och det har inget värde". Ett frånvarande fält säger ingenting alls. Vissa mottagarsystem behandlar det första som en instruktion att tömma det lagrade värdet och det andra som en instruktion att lämna det ensam — vilket är skillnaden mellan att ta bort en patients registrerade allergi och inte nämna den.
Om du inte vet vad mottagaren vill, fråga. Att gissa har en femtio procents chans att tyst förstöra data på andra sidan.
6.3 Villkor
when tar ett uttryck och steget körs endast om det är sant:
- when: MSH-9.2 == "A08"
set:
path: EVN-1
value: A08
Ett steg vars villkor är falskt loggas som hoppade över, och detta rapporteras separat från ett steg som kördes och inte förändrade något. Den distinktionen är poängen med steg-genom-debuggern och den täcks i felsökning: ett falskt villkor och ett frånvarande fält ser identiska ut utifrån och betyder motsatta saker.
6.4 Sökvägar
En sökväg adresserar ett fält: PID-5 är det femte fältet i PID, PID-5.1 dess första komponent, PID-3(2) den andra upprepningen av PID-3 och OBX(3)-5 det femte fältet i det tredje OBX-segmentet.
Två beteenden som är värda att känna till:
setskapar den sökväg det adresserar, inklusive mellanliggande struktur. Detta är bekvämt, och det betyder attsetaldrig kan visa att ett fält saknades — efter steget finns det. För att testa vad som händer när ett fält saknas, användcopyfrån en sökväg som inte finns.- En sökväg utan index adresserar varje upprepning och varje förekomst, precis som i ett filter (där
PID-3.5 == "SS"är sant när någon upprepning är). I ett meddelande med fem OBX-segment, ändrarsetpåOBX-5alla fem, ochsetpåPID-3.4ometiketterar varje identifierare i PID-3, inklusive det nationella numrets. För att ändra en, ange dess index:PID-3(1).4,OBX(2)-5.
6.5 Fel
De flesta steg har ingenting att misslyckas med. Att ställa in ett värde, rensa ett fält eller kopiera från en frånvarande sökväg med en standard är alla definierade för varje indata.
date är undantaget, eftersom ett värde som inte är en datum som den känner igen har ingen korrekt omvandling. Den tar on_error:
fail— standard. Meddelandet stoppas och registreras som en transformationsfel.keep— lämna det ursprungliga värdet som det är.clear— töm fältet.
Standard är fail eftersom en tidsstämpel som tyst inte konverterades är värre än ett meddelande som inte anlände. Ett datum i fel format ser fortfarande ut som ett datum, så det passerar mottagarens validering och hamnar i posten som fel dag.
keep är legitimt när mottagaren tolererar båda formaten och när den används markerar spåret ändringen som avsiktlig så att den inte läser som ett steg som tyst misslyckades.
6.6 Ordningen har betydelse och spåret visar det
Varje steg ser föregående stegs utdata. Två konsekvenser som fångar människor:
- En
mapefter encaseser det case-omvandlade värdet, så dess tabellnycklar måste matcha den omvandlade formen. En tabell medM/Fefter ett gemener-steg matchar ingenting, tyst, eftersom ett värde som inte finns i tabellen lämnas som det är. - En
copyfrån ett fält som ett senare steg tar bort fungerar fortfarande, eftersom det kördes först. Det omvända fungerar inte.
Båda är synliga i stegvis vy, som visar hela meddelandet efter varje steg snarare än endast ändringen. Se felsökning.
6.7 Föreslå mappningar och vad man ska göra med ett förslag
AI-mapparen föreslår mappningar mellan en uppsättning källfält och en uppsättning mål. Dess definierande beteende är att den avstår: under sin förtroendetröskel avstår den från att gissa, eftersom en säker felmappning i ett kliniskt system är värre än ingen mappning alls.
6.7.1 Ge den något att vara säker på
Ett namn på egen hand är svag bevis, även när det matchar exakt. PatientMRN mot PatientMRN poängsätter 68, vilket avstår vid standardtröskeln på 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.
Det får en mappning mestadels på plats. För att slutföra den, tillhandahåll båda halvorna:
- Exempelvärden för ett källfält, efter ett likhetstecken:
ZPI-1 = MRN00412, MRN00998 - Den typ av värde ett målfält innehåller, på samma sätt:
PID-3.1 = mrn. Typerna ärmrn,npi,ssn,phone,dateochemail.
Med dessa kan motorn se att värdena överensstämmer med målets typ och ett förslag vilar på mer än ett namn.
6.7.2 Godkännande sker ett till ett för varje mappning
Varje förslag har sin egen godkännanderuta. Det finns inget "godkänn allt över 80%", med flit: motorn har redan använt sig av förtroendet för att bestämma om mappningen ska erbjudas, och vad som återstår är en bedömning av detta fält i denna feed. Ett nummer är inte den bedömningen.
En avstående kan inte godkännas alls. Den har ingen ruta, inte ens en inaktiverad sådan, och skärmen säger att motorn inte vet. Om du känner till svaret, mappa det manuellt — det är en annan handling än att godkänna ett förslag.
Ett förslag under din tröskel visas utan ruta också, markerat som under den. Värt att läsa — en nära miss är ofta den mappning du ville ha, och att dölja den skulle lämna dig undrande om motorn övervägde den — men inte godkännbart, eftersom din tröskel är den linje du drog.
6.7.3 Två saker att göra med det du godkände
Lägg till dem i en kanal omvandlar varje mappning till en kopia. Detta fungerar bara där källan är en sökväg i meddelandet, såsom ZPI-1, eftersom en kopia kopierar från en plats i ett meddelande till en annan. Stegen läggs till i kanalens fil och träder i kraft när den nästa gången laddas — ingenting ändras i trafiken förrän då. Varje stegs beskrivning registrerar det förtroende det föreslogs med och att en person godkände det, vilket är vad som gör det ansvarigt sex månader senare.
Ladda ner som recept är rätt svar för det vanligare fallet: en mappning från en kolumnnamn, en JSON-nyckel eller en leverantörs eget fältnamn. Dessa är riktiga mappningar, och en kanal kan inte läsa ett sådant fält direkt, så ett steg kan inte uttrycka dem. Receptet registrerar dem som godkända och kan delas.
6.8 Varför inte ett skript
Mirth placerar en JavaScript-omvandlare i centrum av varje kanal, och det är den mest flexibla designen som finns tillgänglig. Perfuse erbjuder skript — se scripts-nyckeln i kanalreferensen — men gör det inte till den vanliga vägen, av tre skäl som kommer från vad som går fel i praktiken.
Ett deklarativt steg kan inspekteras. Perfuse kan berätta att ett steg läser PID-5 och skriver PID-8, innan det körs, och kan därför visa en fält-nivå-spårning, varna för att ett steg adresserar en sökväg som den deklarerade data typen inte kan innehålla, och generera en per-steg-replay. Inget av detta är möjligt för godtycklig kod.
Ett deklarativt steg kan resoneras om av gränssnittet. Byggaren kan erbjuda fälten som finns i kanalens trafik, och en ändring av ett steg kan kontrolleras mot riktiga historiska meddelanden innan det sparas.
Och ett deklarativt steg kan inte göra något som inte är relaterat till meddelandet. Ett skript kan anropa nätverket, läsa filsystemet eller bero på dagen. När en kanal som fungerade i två år börjar producera felaktigt utdata, är orsaken utanför meddelandet den svåraste fallet att diagnostisera, och att ta bort möjligheten är värt mer än den flexibilitet det kostar.
Där en äkta omvandling inte kan uttryckas deklarativt, använd ett skript och acceptera att spårningen kommer att visa det som ett enda ogenomskinligt steg.
6.9 Vad ett skript är tillåtet att göra
Ett skript nekas allt utanför meddelandet såvida det inte beviljas, och beviljandena är i avsnittet Skript i byggaren. Detta är med flit annorlunda än Mirth, som ger varje skript alla — så där kan en omvandlare tyst börja läsa filsystemet efter en kopia-och-klistra-in.
Det finns tre.
Läs och skriv filer kräver att du namnger de kataloger det kan använda, och en kanal som beviljar filåtkomst utan dem nekas vid inläsning. Det kravet är hela skillnaden mellan filåtkomst och obegränsad filåtkomst: att bevilja det utan kataloger en gång nådde hela filsystemet, inklusive Perfuses egen databas, som innehåller lösenordshasher, LDAP-tjänstekontots lösenord och OIDC-klienthemligheten. Att skapa en kanal behöver endast redigeringsrollen, så eskaleringen slutfördes i och med att en administratör startade kanalen.
Fråga en databas använder de anslutningar som konfigurerats på kanalen. Ett skript med detta kan läsa allt som dessa autentiseringsuppgifter kan.
Routa meddelanden till andra kanaler låter ett skript skicka ett meddelande till en annan kanal, vilket är hur en loop mellan två kanaler blir möjlig.
Att bevilja en funktion till en kanal utan skript gör ingenting, och den genererade filen utelämnar hela blocket i det fallet.
6.10 Hantering av ett datum som inte matchar dess format
Ett datumsteg omvandlar från ett format till ett annat, och den intressanta frågan är vad som händer när ett värde inte matchar formatet det påstår.
Standardvärdet är att stoppa meddelandet, och det är rätt standard: en tidsstämpel som tyst inte konverterades accepteras nedströms och sedan missläses, vilket är värre än ett meddelande som misslyckades högljutt och sitter där någon kan se det.
Lämna värdet som det är skickar det vidare i dess ursprungliga format. Nedströms ser man då två format i ett fält, vilket är felet som steget fanns till för att förhindra — men det är rätt valet där fältet är valfritt och en partner skickar det inkonsekvent.
Tömma fältet är ärligt och bättre än ett felaktigt format, men en mottagare som kräver fältet avvisar sedan meddelandet istället.
6.11 Skriptspråken
Tre språk accepteras och valet av språk beror främst på om du migrerar. Värdet anges i en skripts language-nyckel:
| Värde | Vad det är |
|---|---|
javascript | Standard. Ett osignerat skript är JavaScript. |
lua | Bättre val när ingen migrerar. |
wasm | Bytekoden för en komplicerad WebAssembly-modul, inte källkod. |
JavaScript är standard och ett osignerat skript behandlas som JavaScript. Det finns här som en kompatibilitetsåtagande snarare än ett förstahandsval: Mirths skript är JavaScript och en webbplats som flyttar över har tusentals rader med det. Detta inkluderar stöd för E4X, en långdöd utvidgning av språket som Mirths skript använder för XML och som måste översättas innan något kan tolkas.
Lua (lua) är det bättre valet för alla som inte migrerar. En mindre körning, ingen prototypkedja att missbruka och heltalsindexerade tabeller som matchar segment- och fältadressering mer naturligt än JavaScripts gör. Dess standardbibliotek är tillräckligt litet för att räknas upp, vilket är vad som gör dess sandlåda lättare att vara säker på.
WebAssembly (wasm) är inte ett språk utan en komplicerad modul, och fältet vill ha bytekoden för en .wasm-fil snarare än källkod. Använd det när transformationen redan finns i ett komplicerat språk eller när den är tillräckligt tung för att körtiden ska spela roll.
Dess kontrakt är medvetet det enklaste tillgängliga: en modul läser meddelandet på standardinmatning och skriver dess resultat till standardutmatning. Byte in, byte ut — vilket är vad varje verktygskedja redan gör, och vad någon som testar en modul på sin egen kommandorad redan har. Alternativet var en exporterad funktion över linjär minne, som är snabbare och kräver att varje modulägare kommer överens om allokering, strängkodning och vem som frigör vad; för något som körs en gång per meddelande är den handeln inte värd det.
Allt en modul skriver till standardfel blir loggrader, så den kan förklara sig på samma sätt som ett skript som anropar logger kan.
true eller false på standardutmatning. Att blanda ihop de två skulle göra en kraschad modul otillgänglig från en som medvetet släpper trafik.6.11.1 Vad utmatningen betyder
Reglerna är desamma för alla tre språken snarare än nya per körning, så ett skripts observerbara beteende — vad det kan se, vad det får göra, hur länge det får ta, vad en filterdom betyder — definieras en gång.
För en transformer, preprocessor eller skrivare, tom utmatning betyder att meddelandet är oförändrat. Att falla av slutet av ett skript lämnar meddelandet ensamt; att behandla ingen utmatning som "meddelandet är nu tomt" skulle släppa trafik på en tekniskitet.
WebAssembly-moduler är komplicerade när kanalen laddas, inte på det första meddelandet. Kompilering är inte gratis — en modul byggd från ett språk som har sin egen körning kan ta hundratals millisekunder — och att betala det vid laddningstiden betyder att det första meddelandet genom en kanal inte är mystiskt långsammare än resten.
6.12 Delade mappningstabeller
Den andra halvan av samma problem: en webbplats sexkoder och patientklasser översätts identiskt i varje kanal som berör dem, och en tabell inuti en kanal är en tabell som endast den kanalen kan använda.
# 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
Ursprunget är det viktiga. Det mesta som gör att ett gränssnitt är svårt att underhålla är att ingen vet *varför* en mappning är som den är, och personen som visste har lämnat. En mappning med en anledning kan diskuteras; en utan blir något som ingen vågar ändra och ingen vågar ta bort.
Tabeller skapas och ändras på Build → Tabeller samt i filen. Att spara en aktiv tabell startar om de kanaler som läser dess fil som körs, så att nästa meddelande använder den; ett utkast startar ingenting.
6.12.1 Versioner och ikraftträdandedatum
En tabell kan behålla flera utgåvor under ett namn, var och en med sin egen version. Utgåvan som ett meddelande använder väljs när meddelandet anländer: av de godkända utgåvorna vars datum täcker den dagen (UTC), den som började senast. Så en kodändring som överenskommits för första dagen i nästa månad skrivs in nu och tar över på egen hand.
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: [...]
statusärapproved(standard),draft(används av ingenting) ellerretired(bevaras för posteritetens skull, används av ingenting).
(kept for the record, används av ingenting).
- Två utgåvor av ett namn med samma version, eller två godkända utgåvor
som börjar samma dag, avvisas när filen läses in.
- Spara en ny version utan startdatum medan en annan är godkänd
datumstämplar den från idag, så den ersätter den som gäller. En som själv bara började idag pensioneras, eftersom två utgåvor som börjar samma dag lämnar inget regelverk.
- En kartstegs egna
defaultochstrictanvänds när steget anger dem;
annars används tabellens.
- På Skärmen Tabeller listar Visa versioner varje utgåva med dess status,
vem som sparade och vem godkände den, och Jämför med den gällande versionen visar vad en utgåva lägger till, tar bort och ändrar.
6.12.2 Underskrift
Med Inställningar → Data → Mappningstabeller "Ändringar i en mappningstabell behöver en andra persons godkännande" (data.tableApproval) på, är varje sparad utgåva ett utkast, och personen som sparade den kan inte godkänna den: någon annan gör det, eventuellt med den dag det träder i kraft. En godkänd utgåva kan inte redigeras på plats; Ny version från den här kopierar den till nästa version. Godkännande, pensionering och borttagning av ett utkast skrivs till revisionsloggen, och godkännande startar om de körande kanalerna som laddar filen.
6.12.3 Inga tabellvärden mappar
Varje värde som en kartsteg tittade efter och inte hittade räknas, per tabell, med de kanaler det kom genom och när det först och senast sågs. Skärmen Tabeller listar dem, mest frekventa först. Mappa det öppnar tabellen med det värdet redan lagt till som en rad; Avvisa tar bort det tills det ses igen. Värden längre än 64 tecken sparas inte (de är inte koder), och listan behåller vad som sågs inom meddelandebehållningsperioden. Listan sparas i terminology.db bredvid huvuddatabasen.
6.12.4 Kodsystem
Publicerade kodsystem kan importeras från deras utgivares egna filer, under Kodsystem på tabellskärmen (administratörer) eller med POST /api/terminology/import?format=… och filen som brödtext:
| Format | Fil | System |
|---|---|---|
loinc | Loinc.csv från LOINC-tabellutgåvan | http://loinc.org |
icd10cm | CMS-beställningsfilen (icd10cm_order_*.txt) eller kodfil | http://hl7.org/fhir/sid/icd-10-cm |
rxnorm | RXNCONSO.RRF från RxNorm-fullutgåvan | http://www.nlm.nih.gov/research/umls/rxnorm |
snomed | RF2-beskrivningssnapshot (sct2_Description_Snapshot-en_*.txt) | http://snomed.info/sct |
snomed-rf2 | en hel SNOMED CT RF2-utgåvapaket (zip-filen som en nationell utgivare publicerar) | http://snomed.info/sct, version http://snomed.info/sct/{module}/version/{date} |
claml | en ClaML-fil: WHO ICD-10, ICD-10-GM och OPS (BfArM), CIM-10 FR (ATIH) | från filens titel, eller det angivna system |
icd11 | WHO ICD-11 MMS enkel tabulering (tab-separerad, med Code och Title-kolumner) | http://id.who.int/icd/release/11/mms |
csv | valfri avgränsad fil, med system, codeColumn och displayColumn (CPT, HCPCS, lokala koder, nationella tabeller) | det angivna system |
Ingen följer med Perfuse: LOINC, SNOMED CT, RxNorm och CPT har var sitt licensavtal, och skärmen ber importören att bekräfta att organisationen har det (registrerat med importen). Importerade koder används på tre sätt:
- en tabell som namnger
source_systemellertarget_systemhar sina poster kontrollerade när
den sparas, och koder som inte finns i systemet listas på utgåvan;
- Hitta en kod söker efter kod eller efter ord i namnet;
- FHIR-servern svarar
CodeSystem/$lookupochCodeSystem/$validate-code
för dem (se FHIR-serveralternativen). ICD-10-CM-koder accepteras med eller utan punkt.
Nationella utgåvor och klassificeringar. En SNOMED CT-utgåva importeras från dess kompletta RF2-paket: begrepp med deras faktiska status, varje aktiv beskrivning och språkreferensuppsättningar. Utgåvan hittas från paketet (den nationella modulen med flest begrepp; edition namnger den istället) och blir versionens URI. language väljer vars föredragna term varje begrepps visning är (sv, da, nl, de, fr, en-GB, en-US ...; engelska annars), och varje språks föredragna term och fullständigt specificerat namn behålls som beteckningar: $lookup returnerar dem, och dess displayLanguage väljer en (de-CH backar till de). De utgåvor som Perfuse namnger (Internationell, Storbritannien, Tyskland, Nederländerna, Sverige, Danmark, Belgien, Irland, Norge, Schweiz, Estland, Spanien) listas av GET /api/terminology/editions, modul-ID inte kontrolleras mot en publicerad källa markerad som sådan; varje annan utgåva importeras också, namngiven av sin modul.
ClaML-filer läses in i UTF-8, ISO-8859-1, ISO-8859-15 eller Windows-1252, som deras XML-deklaration anger. Varje kategori har en rubrik som är dess föredragna rubrik (inneslagna termer ingår); en modifierare (en femte tecken för en frakturs plats, till exempel) skapar de koderna som läggs till, med modifierarens titel efter kategoriens, såvida kategorin inte utesluter den; blocks=true importerar kapitel och block också. ICD-11-tabellens kolumner hittas genom namn, eftersom deras ordning har ändrats mellan versioner, och bindestrecken som visar djup tas bort från titlarna. En avgränsad fil tar delimiter (, ; | eller tab), encoding (utf-8, iso-8859-1, iso-8859-15, windows-1252) och noHeader=true, med kolumner som sedan numreras från 1. Konsolen erbjuder inställningar för Storbritanniens ICD-10 5:e upplagan och OPCS-4-filer (TRUD), Frankrikes CIM-10 FR-etiketttabell (ATIH) och en ICD-10-BE-export; deras utgivare dokumenterar inte alla kolumner, så kontrollera dem mot filens huvud.
Ikraftträdande datum. effective=YYYY-MM-DD importerar en version nu och använder den från det datumet (ICD-10-GM, säg, varje 1 januari): tills dess svarar en sökning som namnger ingen version med versionen som redan är i kraft, och skärmen visar datumet.
ICD-11 från WHO. Med en klient registrerad på icd.who.int (Inställningar → Data → Kodesystem, serve -icd11-client-id och -icd11-client-secret; -icd11-release, 2025-01 som standard), ICD-11-koder som inte har importerats söks i WHO ICD API (codeinfo, sedan entitetens titel) och sparas i en dag. En postkoordinerad kod (NC72.2&XK9K) kontrolleras i sin helhet, så en kombination ICD-11 som inte tillåts avvisas, och dess visningsnamn för varje del ("Fraktur på lårbenets hals (Höger)").
ICD-11 utan att skicka koder ut. WHO publicerar samma API som en container (whoicd/icd-api, gratis, Intel och Arm). Kör den på ditt eget nätverk och ange dess adress (serve -icd11-url http://icd-api.local, eller ICD API-adress i samma inställningar); ingen klient behövs och ingen kod lämnar ditt nätverk. Testad mot den containern (version 2.6.0, release 2025-01 på engelska och franska).
7 Filtrering
Ett filter bestämmer vilka meddelanden en kanal accepterar. Det är ett uttryck på kanalen, utvärderat efter att meddelandet har parsats och registrerats, innan någon transformation.
filter: MSH-9.1 == "ADT" && MSH-9.2 in ("A01", "A03", "A08")
Ett meddelande som filtret avvisar registreras med resultatet filtrerat. Det är ett normalt resultat, inte ett fel, och det utlöser inte en varning eller producerar en negativ bekräftelse.
7.1 Filtrerat är inte detsamma som misslyckat
Denna distinktion är värd att vara tydlig med eftersom att blanda ihop dem är hur ett riktigt problem göms.
Ett filtrerat meddelande avvisades korrekt: det var inte för denna kanal. Ett misslyckat meddelande var ett som denna kanal borde ha hanterat men inte kunde. Om båda registrerades på samma sätt skulle en kanal som börjar misslyckas med alla meddelanden se ut exakt som en kanal som filtrerar mest av sin trafik, vilket är den normala tillståndet för många kanaler.
Så statistiken räknar dem separat, varningsreglerna behandlar dem olika och gränssnittet visar dem i olika färger. En ökning av filtrerade meddelanden kan betyda att avsändaren har börjat skicka något nytt; en ökning av fel betyder att något är trasigt.
7.2 Vad en filter kan läsa
Valfri fält i det parsade meddelandet, med samma sökvägar som transformationer använder. Filtreringen körs före transformationer, så den ser meddelandet som det anlände — inte som det kommer att skickas.
Den här ordningen är medveten. En filter som läser värden efter transformation skulle bestämma om att acceptera ett meddelande baserat på ändringar som gjorts under antagandet att det accepterades, vilket är cirkulärt och producerar kanaler vars beteende beror på ordningen på två saker som verkar oberoende.
7.3 Uttryck
Jämförelser: ==, !=, och för nummer <, <=, >, >=.
Medlemskap: in ("A01", "A03"), som är tydligare än en kedja av || och är den form som byggaren producerar.
Kombination: &&, ||, och parenteser. Negation med !.
Frånvaro: en väg som inte finns jämförs ojämnt med alla värden, inklusive den tomma strängen. För att testa för frånvaro explicit jämförs mot absent. Detta är viktigt eftersom ett frånvarande fält och ett tomt fält är olika, som beskrivs i transformation, och ett filter som behandlar dem på samma sätt kommer att acceptera meddelanden som det var tänkt att utesluta.
7.4 Ett fel i filtret är ett avslag
Om filtret själv misslyckas med att utvärdera — ett felaktigt uttryck som kom förbi validering, eller en jämförelse som inte kan göras — meddelandet avvisas och felet registreras mot det.
Att avvisa snarare än att acceptera är det säkrare av de två, men ingen av dem är bra, och resultatet registreras tydligt från ett vanligt filteravslag så att det kan varnas för. En filter som felar på alla meddelanden tappar tyst hela flödet, och den får inte se ut som en filter som fungerar.
7.5 Filtrera vid källan där du kan
En filter körs efter att meddelandet har korsat nätverket och parsats. Vissa källor kan filtrera tidigare och billigare:
- En broker-källa tar en
selector, som filtrerar vid broker. Meddelanden som denna kanal inte vill ha korsar inte nätverket alls. På en delad kö är det skillnaden mellan att läsa hundra meddelanden om dagen och hundra tusen. - En databas-källas fråga bestämmer vad den returnerar.
- En fil-källas mönster bestämmer vilka filer den plockar upp.
Filtrering vid källan är ett prestandabeslut, inte ett korrekthetsbeslut, och det har en kostnad: ett meddelande som filtreras vid broker registreras aldrig av Perfuse, så det visas inte i meddelande-lagret och kan inte inspekteras senare. Om du behöver kunna bevisa vad avsändaren skickade, filtrera här snarare än där.
7.6 Testa en filter
En filter kan kontrolleras mot riktiga historiska trafik innan den sparas. Gränssnittet rapporterar hur många av de senaste N registrerade meddelandena filtret skulle acceptera, avvisa och fel på — vilket är det snabbaste sättet att ta reda på att ett uttryck som ser rätt ut accepterar ingenting.
Spåret visar också, per meddelande, vilka fält filtret läste och vilka värden den hittade. En filter som oväntat avvisar allt är vanligtvis läsande en sökväg som inte finns i detta flöde, och spåret namnger den.
8 Meddelandeformat
En kanals dataType bestämmer hur byte blir ett meddelande. Det påverkar parsning, vad sökvägar betyder, hur meddelandet skrivs ut igen och vilka transformationer som är giltiga.
| Värde | Format |
|---|---|
hl7 | HL7 v2, den pipe-avgränsade standarden. Standardvärdet. |
hl7v3 | HL7 v3 och CDA-dokument, som är XML. |
x12 | ASC X12, används för behörighet och anspråk. |
ncpdp | NCPDP Telecommunication Standard D.0 apoteksanspråk. |
script | NCPDP SCRIPT, elektroniska recept. XML. |
dicom | DICOM-bilder. |
delimited | CSV och andra avgränsade texter. |
raw | Inga parsering. Byte in, byte ut. |
8.1 HL7 v2
Standardvärdet och det som de flesta exempel i den här handboken använder. Segment avgränsade med radbrytning, fält med |, komponenter med ^, upprepningar med ~.
Två saker om kodningen är värda att veta eftersom de orsakar tysta fel.
Avgränsarna är inte fasta. De deklareras i MSH-1 och MSH-2 i varje meddelande, och Perfuse läser dem från där snarare än att anta rör. En avsändare som använder en annan fältavgränsare parsar korrekt.
Konsekvensen är att ett meddelande vars separatorer har ersatts — oftast av ett ordbehandlingsprogram eller en e-postklient som ersätter dem med typografiska likheter — tolkas perfekt till fält som alla är fel. Ingenting felar. Det är därför exempelläsaren som beskrivs i testing rapporterar vilken separator-tecken den hittade och vägrar att uttrycka förtroende när det är ovanligt.
8.2 HL7 v3 och CDA
XML snarare än avgränsat. Sökvägar är element- och attributsökvägar snarare än fältpositioner.
I v3 är ett värde nästan alltid ett attribut snarare än elementtext. En jämförelse som endast läser elementtext kommer att rapportera att två dokument är identiska när födelsedatum, kön och varje identifierare skiljer sig. Perfuses jämförelse läser båda, och det är därför: alternativet lyckas tyst.
hl7v3-alternativ finns i formatreferensen.
8.3 X12
Segment avgränsade med ~ enligt konvention, med avgränsare deklarerade i ISA-segmentet. Liksom HL7 läses de från meddelandet snarare än antas.
X12:s struktur är kuvert inom kuvert — utbyte, funktionsgrupp, transaktionssats — och ett enda utbyte kan innehålla många transaktioner.
Som standard är ett utbyte ett meddelande. Hela filen får ett register, ett resultat och en rad i gränssnittet, oavsett hur många transaktioner den innehåller.
8.3.1 Mirths X12-XML
Mirth Connect och Open Integration Engine visar X12 som XML: en rot X12Transaction (eller EDIMessage när indata inte börjar med ISA) som bär delimiters som attribut, och ett element per segment och element med namn ISA.01, NM1.03.1 och så vidare. Kanaler och mottagare som byggts för Mirth läser och skriver den formen. Perfuse läser och skriver samma form:
x12: { arrives_as: xml }on an X12 channel takes that XML in and handles it as the X12 it stands for (the builder's It arrives as choice);x12_as: xmlon a destination sends the X12 on as that XML (the builder's Send it as Mirth's X12 XML);perfuse x12 xml [file]andperfuse x12 from-xml [file]convert at the command line.
Formatet skrevs från Open Integration Engine 4.6:s observerade utdata och publicerat format, och kontrolleras mot det: 25 genererade utbyten och 4 behållna exempel kommer ut byte för byte som OIE skriver dem, och tillbaka (se verifikation). En DOCTYPE avvisas, som i varje XML Perfuse läser.
8.3.2 Delning av utbyte
Att ställa in split gör varje transaktionssats till ett meddelande i sin egen rätt, med sitt eget register, sina egna mått och sin egen rad. En operatör som letar efter ett anspråk hittar då ett anspråk snarare än en fil med fyra hundra.
Det är avstängt som standard eftersom att aktivera det multiplicerar allt nedströms — meddelandekonton, rader, tröskelvärden för varningar — och ett tröskelvärde som är inställt för filer som plötsligt räknar anspråk kommer inte att betyda vad det tidigare gjorde. Det bör vara ett beslut som någon har fattat snarare än en standard som de har ärvt.
split och acknowledge kan inte båda vara inställda, och en kanal med båda vägras vid inläsning. Ett erkännande är ett uttalande om hela utbytet, så delning skulle skicka ett per transaktionssats, och en partner som tar emot flera 999:er som namnger samma funktionsgrupp har inget sätt att försona dem.8.3.3 När räkningarna inte stämmer
X12 deklarerar sina egna räkningar — hur många segment, hur många transaktioner — och envelope-nyckeln säger vad man ska göra när de inte stämmer med vad som faktiskt är närvarande. Dessa räkningar är den enda mekanismen X12 har för att upptäcka att halva en anspråksfil anlänt.
| Värde | Beteende |
|---|---|
require | Vägra utbytet. Standardvärdet. |
warn | Bearbeta det och registrera felet mot meddelandet. |
ignore | Kontrollera inte alls. |
warn finns för en verklig situation: vissa partners programvara har genererat felaktiga räkningar i år i annars kompletta filer, och en webbplats som måste bearbeta dem behöver ett sätt att säga så högt i konfigurationen snarare än att stänga av validering helt och hållet.
ignore är uppkallad för att vara obekväm. Att ställa in den kastar bort det enda medlet X12 ger dig för att märka en avkortad fil, och en avkortad anspråksfil är inte att skilja från en liten.8.3.4 Transaktioner som Perfuse läser som strukturerad data
Valfri X12-utbyte kan dirigeras, filtreras och adresseras via sökväg. Dessa transaktioner parsas dessutom till namngivna fält, så en kanal kan fråga vad en betalare beslutade snarare än vilket element som sitter på position fyra.
| Transaktion | Vad den innehåller |
|---|---|
835 | Betalningsinformation: vad som betalats, vad som nekats och anledningarna till justeringar. |
275 | Anspråksbilagor: klinisk dokumentation som stödjer ett anspråk. |
277 | Anspråksstatus, inklusive en betalares begäran om ytterligare dokumentation. |
278 | Tidigare auktorisation: begäran om granskning och betalarens beslut. |
999 | Funktionsbekräftelse, som Perfuse också genererar. |
271 | Försäkringsberättigande: om en patient är försäkrad och deras egenavgift, självrisk, friskrivningsbelopp och utbetalningsbelopp, inom och utanför nätverket. |
|---|---|
834 | Registrering: medlemmar som lagts till, ändrats och avslutats, med varje försäkringslinje och dess datum. |
837 | Anspråk, professionella och institutionella (läs för CMS-0057:s CARIN-omvandling). |
Perfuse skapar också 270-behörighetsförfrågan och 276-ansökan om anspråksstatus, under Erbjudare → Anspråk och auktorisering eller via POST /api/x12/eligibility/build och /api/x12/claimstatus/build. Båda är HIPAA 5010-versioner (005010X279A1, 005010X212), lästa tillbaka och kuvertkontrollerade innan de visas, och ingen av dem skickas från den sidan: leverans av en är en kanals uppgift, där handelspartnern och dess autentiseringsuppgifter finns.
8.3.5 Försäkringsberättigande och CAQH CORE-datainnehållsregel
En 271 är en lista med EB-segment, var och en en enskild faktum: aktiv täckning, eller en $25-kopay för servicetyp 30 i nätverket, eller $800 av den enskilda självrisken kvar. Läsaren sätter samman dem till det svar som en receptionsdisken vill ha - "täckning aktiv under Gold PPO 2000; kopay i nätverket $25; enskild självrisk kvar i nätverket $800" - och namnger ett avslag (ett AAA-segment) i ord, med vad utbetalaren säger att man ska göra härnäst.
Den kontrollerar också svaret mot CAQH CORE Eligibility & Benefits datainnehållsregeln: för en förfrågan om hälsoförmånsplanstäckning (servicetyp 30), bör ett aktivt svar innehålla plandatum, planens namn, kopay, självrisken och återstående självrisken både i och utanför nätverket, och de grundläggande servicetyperna (1, 33, 35, 47, 48, 50, 86, 88, 98, AL, MH, UC). Var och en listas som uppfylld eller saknad. Detta är Perfuses tolkning av regeln, användbart för "varför berättar denna utbetalare aldrig för oss om självrisken?" - det är inte CORE-certifiering, som CAQH:s auktoriserade testleverantörer utför.
8.3.6 Tidigare auktorisation
Perfuse implementerar tidigare auktorisation två gånger, med avsikt.
Den FHIR-sida som CMS-0057-F kräver att betalare exponerar från och med den 1 januari 2027. Den 278 som betalare accepterar idag, och regeln ersätter den inte — Da Vinci PAS är i praktiken en mappning till denna transaktion, eftersom en 278 är vad ett system för utnyttjande av resurser talar. En motor som läser endast FHIR-delen kan prata med de system som kommer att finnas och inte med de som finns.
Ett 278-svar innehåller auktorisationsnumret, och det är fältet som hela transaktionen finns till för att leverera. Utan det är en certifierad tjänst inte fakturerbar: anspråket skickas in utan auktorisationsnummer och avslås på grund av bristen på ett sådant, vilket läses nedströms som ett kliniskt avslag.
Ett avslag och ett beslut att inte överväga är inte samma sak
Detta är den dyraste förvirringen i transaktionen, och Perfuse rapporterar de två separat.
| Vad som anlände | Vad det betyder | Vad man ska göra |
|---|---|---|
HCR med åtgärd A3 | Betalaren övervägde begäran och kommer inte att certifiera den. | Överklaga, eller ändra vårdplanen. |
Ett AAA-segment | Betalaren vägrade överväga den — patienten hittades inte, begäran erkändes inte, granskningen omfattades inte. Ingenting beslutades. | Rätta begäran och skicka den igen. |
Båda läses som "ej godkänd" för någon som skannar, och de korrekta åtgärderna är motsatta. Att överklaga något som ingen har beslutat om uppnår ingenting; att återsända ett avslag producerar samma avslag. Det parsade resultatet namnger vilket som hände — denied mot not-considered — och AAA04 innehåller betalarens egen råd om huruvida begäran är återvinningsbar alls.
Delvis certifiering rapporteras som partially-certified snarare än införd i godkännande. Det finns ett auktorisationsnummer att fakturera mot, så det räknas som godkänt, men den certifierade mängden är inte den begärda mängden — och en praktik som bokar sex sessioner mot tre godkända upptäcker det vid den fjärde fakturan.
En åtgärdskod som Perfuse inte känner till rapporteras som unknown, inte som väntande. Väntande läses som "vänta", och att vänta är fel åtgärd för det mesta som en okänd kod kan vara.
En kanal kan dirigera på beslutet direkt:
filter: HCR-1 == "A3"
Omvandling mellan de två
Perfuse omvandlar ett parserat 278 till ett Da Vinci PAS ClaimResponse, och rapporterar varje bedömning som omvandlingen behövde snarare än endast resultatet. Omvandlingen följer tre regler:
- Inget beslut uppgraderas. En partiell certifiering förblir partiell, och en begäran som betalaren vägrade att överväga blir inte ett avslag. Båda kollapserna är tillgängliga i den uppenbara mappningen och båda är fel i den dyra riktningen.
- Ingenting uppfinns för att fylla ett obligatoriskt fält. Ett certifierat evenemang utan auktorisationsnummer rapporteras som sådant, inte ges ett trovärdigt nummer — ett fabricerat nummer producerar ett anspråk som senare avslås av en anledning som ingen kan spåra.
- Ett beslut som endast fördes på radnivå används. En betalare som svarar per tjänst kan lämna evenemanget utan ett beslut av sitt eget; att endast läsa evenemangsnivån skulle rapportera det som väntande, och en praktik väntar på ett svar som den redan har medan godkännandet går ut. Där raderna inte är överens, vinner den minst fördelaktiga, eftersom ett evenemang med en vägrat rad inte är ett godkännande.
Att begränsa till ett trespråkigt ordförråd — godkänt, avslaget, väntande — är tillgängligt och uttrycker tydligt vad det kastar bort. Att begränsa ett avslag att överväga ger "avslaget" och säger i ord att den korrekta åtgärden är en korrigering återinlämning snarare än en överklagande.
Kontrollerat mot PAS 2.2.1, inte bara mot sig själv
The ClaimResponse är formad till Da Vinci PAS 2.2.1-profilen och kontrollerades med den officiella HL7-valideraren som laddats med den publicerade PAS-paketet. Den första versionen hade endast kontrollerats av Perfuses egna tester, och valideraren avvisade den med sex till åtta fel per resurs. Var och en av dem är något som en betalares PAS-slutpunkt också skulle ha avvisat:
| Vad som var fel | Var PAS placerar det |
|---|---|
Beslutet var i adjudication.category och reason. | The reviewAction-tillägget, på en prövning vars kategori är submitted. |
| Orsaks-koden med namnet X12-element 1034. | X12 extern kodlista 886. |
Ett väntande begäran svarade outcome: queued. | outcome handlar om bearbetning och PAS tillåter endast complete, error och partial. Ett väntande är complete, med granskningsåtgärd A4. |
processNote.type var en CodeableConcept. | R4 har en kod: print. |
patient, created, insurer och request saknades. | Alla fyra är obligatoriska. De ges som identifieringsreferenser, eftersom svaret står ensamt snarare än i en samling. |
Den korrigeraade utmatningen validerar utan fel för en certifiering, ett avslag och ett väntande. Varningsmeddelandena som kvarstår är valideraren som säger att den inte kan ladda X12:s kodsystem, som X12 licensierar. Auktorisationsnumret transporteras i reviewAction.number, där guidens eget exempel placerar det, och i preAuthRef när svaret endast har en.
Valideraren är inte en del av make check, eftersom den behöver Java och en nedladdning av guiden och dess beroenden. Vad den hittade hålls av ett test istället: varje regel den påtvingade påstås, så en ändring som återinför ett av dessa fel misslyckas.
The Claims & auth-vyn konverterar en klistrad 278 och visar besluten, anteckningarna och resursen.
8.3.7 Bilagor och varför de behöver särskild hantering
CMS-0053-F gör 275 till en HIPAA-standard för anspråksbilagor, med krav på efterlevnad senast den 26 maj 2028. Den transporterar ett dokument — en operativ anteckning, en bildrapport, en skannad blankett — knuten till anspråket det stöder.
The 277 är den andra halvan av samma samtal. En betalare tar emot ett anspråk, beslutar att det behöver dokumentation och skickar en 277 som begär det; leverantören svarar med en 275.
En kanal kan dirigera på statuskoden direkt, eftersom STC01 är ett sammansatt och dess andra komponent är statusen. Skrivet i kanonisk form, eftersom en komponent adresseras med en punkt och de två notationerna inte kan blandas — STC-1.2 är element 1, komponent 2:
filter: STC-1.2 in ("227", "233", "252", "287")
Dessa är koderna som otvetydigt betyder att ett dokument önskas. Status kategori i STC-1.1 används inte medvetet på egen hand: R4 betyder en dokumentbegäran i vissa implementeringsguider och "vidarebefordrad på annan plats" i andra, så ett filter på kategorin ensam skulle placera färdigställda anspråk i kön för att någon ska jaga.
Två identifierare bestämmer om en bilaga någonsin associeras med sitt anspråk, och båda rapporteras: bilagakontrollnumret, som leverantören placerade på det ursprungliga anspråket för att säga att dokumentation skulle följa, och spårningsnumret, som matchar betalarens begäran. En bilaga som anländer utan någon av dem arkiveras och kopplas aldrig till något, medan anspråket åldras.
275 tolkas inte. Perfuse rapporterar dess byte och vad avsändaren säger att de är. En bilaga kan vara en PDF, en TIFF, en CDA-dokument eller ett HL7-meddelande, och en kanal som behöver innehållet kan lämna över dessa byte till formatet som läser det.Formuläret 006020, som är det som regeln antar
CMS-0053-F antar version 006020, och dess 275 skiljer sig från 005010-formuläret på två sätt som har betydelse.
- Nyttolasten är i
BDS, inteBIN.BDS01namnger ett filter,ASCellerB64.BDS02är längden ochBDS03data. - Nyttolasten är en MIME-enhet, med rubriker som säger vad dokumentet är och en base64-kropp. Med
B64är enheten i sig base64 också.
Perfuse packar upp entiteten och rapporterar dokumentet inuti den, med dess innehållstyp och filnamn. De byte som rapporteras är exakt de som avsändaren packade. En entitet som inte kan packas upp lämnar den råa nyttolasten på plats, med en anteckning som säger varför.
Bygger en 275. Perfuse bygger också 006020X314-bilagor: en oanmodad som åtföljer ett anspråk, eller ett svar på en betalares 277-begäran. Skillnaden är BGN01 02 mot 11, och om TRN02 innehåller anspråkets PWK06 eller 277:s TRN02. Varje byggt utbyte parsas tillbaka innan det returneras, och svaret säger om dokumentet inuti är det som gick in.
Strukturen kommer från de två publicerade vägledningarna för 006020X314: CMS esMD-vägledningen och UnitedHealthcares. Den kommer inte från X12-tekniska rapporten, som X12 licensierar och som detta projekt inte innehar.
- Där de två vägledningarna är överens, följer Perfuse dem.
- Där de skiljer sig åt, tillfredsställer den båda om den kan.
CAT02ärHLför ett HL7-dokument, som esMD använder, ochIAför en bild, som UnitedHealthcare använder. - Annars skickar den det valfria segmentet endast när den ges värdet: esMD:s
REF*X1-anspråksidentifierare och UnitedHealthcaresDTP*472-tjänstedatum.
Det finns ingen validering mot den tekniska rapporten. Partnerns vägledning styr.
8.3.8 Elektroniska signaturer på bilagor
CMS-0053-F antar också en signaturstandard, i 45 CFR 162.2002(e): HL7-implementeringsguiden för CDA-utgåva 2, digitala signaturer och delegering av rättigheter, utgåva 1. Den gäller för signaturer som läggs till på bilageinformation när den skickas i en HIPAA-bilage-transaktion, från och med den 26 maj 2028. En betalare får inte begära mer än vad guiden gör.
Perfuse signerar en C-CDA på det sättet på väg in i en 275, och kontrollerar signaturerna på varje C-CDA i en 275 som den läser.
- Vad som signeras. Hela dokumentet utom dess
legalAuthenticatorochauthenticator-deltagare, så att varje senare signatur lämnar de tidigare signaturerna intakta. Signaturerna säger så med en XPath-filter 2.0-omvandling som varje XML-signaturbibliotek kan utvärdera. - Var den hamnar. Base64 i
sdtc:signatureTextpå den signering som deltagare, med en enradig ren-textbeskrivning. Signeraren är dokumentets juridiska autentisator om den har en osignerad, annars en nyauthenticator. - Vad den uttalar. Signerarens certifikat, tiden i UTC, en roll från NUCC-leverantörstaxonomi och ett syfte från ASTM E1762. Syftet är som standard *Författarens signatur* för en juridisk autentisator och *Medförfattarens signatur* i annat fall, som i guidens eget exempel.
- Hur länge den varar. Guiden begär XAdES-X-L, som innehåller allt en betalare behöver för att verifiera signaturerna år senare utan att nå nätverket. Det är certifieringsvägen, en OCSP-svar eller CRL från CA, och två tidsstämplar från en tidsstämpelmyndighet. Perfuse hämtar återkallningsdata från adresserna i certifikatet och tidsstämplar från
-tsa-url.
Om något av detta inte är tillgängligt, görs signaturerna ändå och gäller. Resultatet namnger XAdES-formen den nådde, och säger vad som hindrade den från att nå X-L: till exempel ett självsignerat certifikat (ingen CA att fråga) eller ingen tidsstämpelmyndighet.
Nyckeln är -signing-cert och -signing-key. Lägg till CA-certifikaten efter signerarens i samma fil så att vägen följer med signaturerna. För en signatur som betyder vad DSDR betyder, bör certifikatet namnge kliniken, med dess NPI, snarare än servern. Signering är en administrativ åtgärd, som signering av vilket dokument som helst.
Guiden namnger inte ett namnområde för sina egna element. Perfuse placerar digitalSignature, authorizedSigner och SignaturePurpose i urn:hl7-org:sdtc. Den uttalar också syftet som en XAdES-åtagandetyp med ASTM-OID, som XAdES-verktyg förstår. Delegering av rättigheter, där en delegat signerar med en SAML-påstående från den auktoriserade signeraren, produceras inte, och en mottagen rapporteras som inte verifierad.
Leverantörens NPI kontrolleras mot dess kontrollsiffra. En betalare matchar en bilaga till dess anspråk delvis på det numret, och ett felaktigt nummer lämnar bilagan omatchad medan anspråket nekas på grund av saknad dokumentation.
Anspråk och autentisering-vyn bygger en 275 från en klistrad C-CDA eller en uppladdad fil, eventuellt signerar C-CDA, och läser en tillbaka med varje signaturs resultat. Ingenting på den sidan skickar någonting: utbytet lämnas tillbaka för att levereras genom en kanal, som är där partnern, autentiseringsuppgifterna och revisionsspåret tillhör.
8.3.9 Binära segment
Ett BIN-segment innehåller råa byte, och råa byte innehåller avgränsare. Varje annat X12-segment slutar vid segmentavslutaren, så en vanlig parser hittar segment genom att söka efter en byte; en bilaga kan inte hittas på det sättet. En PDF som innehåller en ~ skulle delas upp i bitar, och varje bit är ett strukturellt giltigt segment — så dokumentet trunkeras, varje segment efter det är feljusterat, och ingenting rapporterar ett fel.
Perfuse läser byte-räkningen som segmentet deklarerar och tar exakt så många byte. Två konsekvenser som är värda att känna till:
- En deklarerad längd som inte matchar data avvisas, och båda numren anges. Den relevanta frågan är om avsändarens räkning var fel eller om filen trunkerades under överföringen, och endast de båda numren kan besvara den.
BDS, den binära segmentet006020, lagrar sin räkning iBDS02och dess data iBDS03. Det avvisades tills det kunde bekräftas från en publicerad källa snarare än från minnet, och två källor bekräftar nu det: CMS esMD companion guide'sBDS-tabell och UnitedHealthcares guide.
EsMD-guidens egen exempel på utbyte deklarerar 16 byte för samma 53-byte payload som dess tabell korrekt räknar som 53. Perfuse avvisar det exemplet, som den ska. Ett test innehåller både tabellens exempel och exemplet med skrivfel, så en ändring i antingen riktning märks.
8.4 FHIR
8.4.1 Vad ett HL7 v2-meddelande blir
Meddelandetypen bestämmer vad som produceras, och varje omvandling rapporterar de bedömningar som behövdes som anteckningar bredvid paketet.
| v2 | FHIR |
|---|---|
ADT | Patient, en Encounter när det finns ett besök, en Condition per DG1-diagnos (även listad i Encounter's diagnosis, en intagande som AD), en Procedure per PR1 och en AllergyIntolerance per AL1. A28, A31, A29 och A24 handlar om personen, så de producerar ingen Encounter eller diagnoser, men de bär på allergier. |
ORU | DiagnosticReport per OBR, med dess Observationer och Specimen, och ordern som den svarar på som en ServiceRequest (dess begärande OBR-16 eller ORC-12, dess status ORC-5); OBR-32 är resultattolkaren, OBR-34 och OBR-35 utförare. Resultaten grupperas under OBR före dem efter position, eftersom OBX-4 inte är tillförlitlig. |
ORM, OML, OMG | ServiceRequest. |
SIU | Appointment, med patienten, praktikerna från AIP och platserna från AIL. |
MDM | DocumentReference som innehåller dokumentet. |
VXU | Immunization, en per RXA. |
Allt annat producerar Patient och en varning som namnger den typ som inte kartlades.
Schemaläggning. En bokning, en om schemaläggning, en avbokning och en som inte dyker upp alla landar på samma Appointment. Dess identitet kommer från appointmentens egna nummer i SCH-1 och SCH-2, aldrig från meddelandet, så en avbokning uppdaterar bokningen. Alternativet skulle vara en andra, avbruten appointment bredvid en levande, vilket visar att patienten bokades in i en tid som inte längre existerar.
- Status. Fyllningsstatusen i
SCH-25bestämmer det, och triggerhändelsen används endast när det är tomt. - Blockerade tider. En blockerad tid är inte en appointment med en patient och producerar ingen.
- Starttid. Den läses från
AIS,AIG,AILellerAIPförst, sedanSCH-11, eftersom version 2.5 flyttade den och feeds inte alla följde med. - Varaktigheter. En varaktighet i en enhet som Perfuse inte känner till lämnas ut, inte gissad.
Dokument. Textanteckningar (TX, FT, ST) behåller sina radbrytningar, inklusive tomma rader, eftersom en tom upprepning i en anteckning är en paragrafbrytning.
- Inbäddade dokument. Ett inbäddat PDF, TIFF eller JPEG (
ED) transporteras byte för byte. Base64 som inte är giltig base64 avvisas snarare än skickas vidare. - Typer. Dokumenttypen i
TXA-2behålls som skickad och, där det finns en tydlig ekvivalent, ges LOINC-koden som US Core använder. - Signering. En anteckning som ingen har signerat är
preliminary, ochT11gör dokumentetentered-in-error. - Inget innehåll. En notifikation med inget innehåll (
T01,T03och de andra udda nummerhändelserna) producerar ingen DocumentReference. FHIR kräver innehåll, och en tom bilaga skulle se ut som anteckningen medan den säger ingenting.
Detta är vad CMS Interoperability Framework-kriterium 14 ber om: kartnoter och kliniska dokument returnerade som FHIR-bilagor.
Vaccinationer. En dos rapporteras aldrig som given när meddelandet säger något annat.
- Avvisade doser. En avvisad eller inte administrerad dos (
RXA-20REellerNA) ärnot-done, med orsaken frånRXA-18. - Borttagningar. En borttagen dos (
RXA-21D) ärentered-in-error. - Historiska register. Ett register som transkriberats från någon annanstans (
RXA-9annat än00) är inte en primärkälla. - Okända mängder. En mängd på
999betyder okänd, inte 999. - Vägar och platser. Varje dos tar vägen och platsen från
RXRefter den, så ett meddelande med två doser ger inte den andra dosen den första dosen väg.
Besvärlig indata. Var och en av dessa rapporteras i anteckningarna snarare än beslutas tyst:
- Identiteter.
PID-2ochPID-4, som dragits tillbaka efter v2.7 men fortfarande skickas, behålls somPID-3.CX.7ochCX.8blir
Identifier.period. En tilldelad myndighet som bär en ISO OID (AUSHIC&2.16.840.1.113883.3.879&ISO) blir urn:oid:. En typkod utanför HL7-tabellen 0203 behålls som text, inte märkt som en.
- Sammanläggningar.
MRGpå en sammanläggningshändelse (A40och dess släktingar) skickar den pensionerade posten också, inaktiv, medPatient.linkbåda vägarna. Vid någon
annan händelse, såsom en A08, sammanfogas ingenting och en varning säger att den tidigare identifieraren fortfarande är aktiv.
- Tider. En födelse tid i
PID-7går tillpatient-birthTime-tillägget. En tidsstämpel utan offset tar den konfigurerade
tidszonen, annars offseten på MSH-7 (v2 förutsätter avsändarens lokala tid), annars UTC. En födelse tid är undantaget: med ingen offset från någon av de tre lämnas den ut istället för att märkas UTC, eftersom en felaktig offset kan flytta en födelse till en annan dag. birthDate behålls, och en varning säger att tiden släpptes och att inställning av en tidszon för flödet behåller den.
- Resultat. Upprepa ett textresultat fogas samman med radbrytningar. Ett
ED-resultat eller ett kodat vars värde uppenbarligen är Base64, blir en
DocumentReference som Observationen pekar på i derivedFrom, eftersom en R4 Observation inte har något bilagorvärde. En SN jämförare av = släpps som redundant; <> behåller texten, eftersom ingen mängd kan säga "inte lika med".
- Besök. En
A08med en utskrivningsdatum (PV1-45) är ett avslutat möte. En saknad eller okänd patientklass är den null
smaken UNK, eftersom R4 kräver en klass.
- Z-segment namnges i en varning, eftersom det inte finns någon standardkarta för dem.
- Namn. När avsändaren delar upp ett efternamn (
XPN.1,XCN.2) i dess beståndsdelar - ett efternamnsprefix och ett efternamn, personens eget och en partners, som nederländska och flamländska namn skickas - ärfamilyhela namnet och delarna hamnar i HL7:s efternamnsutvidgningar (humanname-own-prefix,-own-name,-partner-prefix,-partner-name). - Förfaranden.
PR1blir ett förfarande med statusunknown, eftersom en ADT inte anger om det utfördes eller planerades; anestesisten (PR1-8) och kirurgen (PR1-11) är utförare med SNOMED CT-roller. En OPS-kod får också sin SNOMED CT-kategori från dess kapitel, enligt HL7 DeutschlandsOPS-SNOMED-Category-karta, som ISiK kräver.
8.4.2 Vad en webbplats lägger till: bundle-skriptet
Ett nationellt profil vill ofta ha vad ett HL7 v2-meddelande inte bär: ett sjukhus IK-nummer eller ODS-kod, vilken kontakt nivå ett besök är (ISiK), om ett givet namn är ett förnamn eller en initial (den nederländska nl-core). Perfuse gissar inte dessa. En fhir-destination bundle_script är där en webbplats skriver dem: JavaScript som körs på varje omvandlat Bundle, som bundle, innan det valideras och skickas. Vad skriptet lämnar är vad som skickas, kontrollerat som vilken omvandling som helst, och ett skript som genererar fel gör meddelandet felaktigt som vilken transformer som helst. Konsolen har det under destinationens *Lägg till vad dina system vet*.
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 kör samma skript, så en webbplats kan prova det på sina egna meddelanden först. Två fungerande exempel finns i lagret: examples/isik/bundle-script.js (IKNR, Kontaktebene, MR-typad patientnummer, Diagnosetyp) och examples/nictiz/bundle-script.js (förnamn och initialer). Med dem går de uppfunna tyska och nederländska meddelandena i conformance/national från 18 till 42 av 47 resurser som är giltiga mot ISiK och från 12 till 18 av 24 mot nl-core; vad som är kvar är i meddelandena eller terminologiservern och listas där.
Bundle går genom Perfuse-modellen på vägen tillbaka, så ett skripts ändringar kontrolleras och skrivs i destinationens FHIR-version. Medlemmar som modellen inte har något fält för behålls som skriptet skrev dem, inuti data typer också.
8.4.3 US Core 9.0.0 och USCDI v6
-us-core (och claim_us_core på en fhir-destination) sätter ett US Core-profil i meta.profile, men bara på en resurs som har kontrollerats mot det profilen och funnits överensstämma. En som inte uppfyller kraven konverteras och skickas fortfarande utan anspråk, och en not ger orsaken, till exempel "US Core kräver en mötestyp, och detta Möte har ingen". Kontrollerna är avskrivna från US Core 9.0.0, den version som ONC:s 2026 Standards Version Advancement Process godkänner för USCDI v6. De täcker Patient, Möte, laboratorie-Observation och DiagnosticReport, Specimen, Practitioner, Organization, Location, Immunization, DocumentReference, mötes-diagnos Condition och AllergyIntolerance.
Vad konverteraren bär, enligt USCDI v6 dataklass:
| USCDI v6 | Från | Som |
|---|---|---|
| Patientdemografi | PID | Namn, födelsedatum, kön, adress, telefon och e-post, identifierare. Ras och etnicitet (PID-10, PID-22) i US Core-tillägg när de är kodade i CDC Ras och Etnicitet. Föredragen språk (PID-15) som BCP 47 |
| Mötessinformation | PV1 | Möte med typ, klass, period, plats och deltagare |
| Anläggningsinformation | PV1-3 | Plats, med anläggningen som dess ledande organisation |
| Problem, datum för debut | DG1 | Tillstånd (mötessdiagnos). DG1-5 är debut, som HL7 v2-till-FHIR-kartan har det |
| Allergier och intoleranser, reaktion | AL1 | AllergyIntolerance med kategori, kriticitet och reaktion |
| Laboratorium | ORU | DiagnosticReport, Observationer, Specimen (från SPM), ServiceRequest |
| Ordrar | ORM, OML | ServiceRequest |
| Vaccinationer | VXU | Immunization |
| Kliniska anteckningar | MDM | DocumentReference |
| Vårdteammedlemmar | PV1, TXA, DG1 | Praktiker |
Inte medtagen, eftersom v2-meddelanden av dessa typer inte innehåller dem eller Perfuse inte kartlägger dem: Läkemedel, Förfaranden, Mål och Preferenser, Hälsostatusbedömningar, Vårdplan, Familjehälsohistoria, Medicinska enheter (UDI), Hälsosäkerhetsinformation, Livstecken som en särskild profil och Bevis.
8.4.4 R4 i båda riktningarna
En FHIR-server som deklarerar R4 accepterar R4. Det var inte sant för Möten förrän denna version. Servern konverterade vad den serverade till R4 men läste vad den mottog som om det redan var i dess interna form, så ett R4-möte avslogs med en 400. Så var också varje paket som Perfuses egen ADT-omvandling producerade, eftersom var och en bär Encounter.class, som R4 skriver som en enda kodning.
Det upptäcktes första gången något publicerade en omvandlad ADT till Perfuses egen R4-server. En test gör nu det för varje kartlagd meddelandetyp, och en annan kontrollerar att allt som skrivs som R4 läses tillbaka oförändrat.
8.4.5 Internationell patientöversikt
GET /fhir/Patient/{id}/$summary, eller GET /fhir/Patient/$summary?identifier=system|value, returnerar en internationell patientöversikt (HL7 IPS 2.0.0): en FHIR document-samling vars sammansättning listar patientens aktiva problem, allergier, mediciner, vaccineringar, resultat, viktiga tecken, procedurer, enheter, tidigare sjukdomar, social historia och vårdplaner, var och en med en läsbar beskrivning. Det är den korta journalen som en kliniker som aldrig har mött patienten läser först, och den sammanfattning som den europeiska hälsodataplattformen utbyter mellan länder från 2029.
Den byggs från vad FHIR-lagret innehåller, och ingenting uppfanns:
- Poster märkta
entered-in-errorlämnas ut. - Ett löst tillstånd hamnar under tidigare sjukdom, inte problem.
- En läkemedelsbeställning som stoppades eller slutfördes är historia, inte en aktuell medicin.
- De tre avsnitten som IPS kräver (problem, allergier, läkemedel) är alltid närvarande. När en av dem inte har något i den,
avsnittet bär den kodade tomma orsaken unavailable och säger att servern inte har någon information, "vilket inte betyder att det inte finns någon". En tom allergilista får aldrig läsas som "inga kända allergier".
- De praktiker, organisationer, läkemedel och platser som posterna pekar på ingår, så att dokumentet kan läsas på egen hand.
Åtkomst följer $everything: en token som är begränsad till en patient får en 403 för en annan, och en identifierare som matchar två patienter avvisas snarare än gissas. Endast IPS-profilen skapas; att begära en annan profile avvisas. Dokumentet som Perfuse producerar från sina testposter validerar mot IPS 2.0.0 Bundle-profilen med HL7-valideraren, utan fel. En post som skapats från riktiga flöden kan fortfarande misslyckas där flödets egna koder gör det (t.ex. ett visningsnamn som kodsystemet inte använder), eftersom sammanfattningen skickar vidare data som den mottogs.
Utbyte → Hälsolänkar → Dela fyller innehållet med en patients sammanfattning: skriv patientens FHIR-id och välj Använd deras patientöversikt, sedan läs och skapa länken. Byggnationen granskas som fhir.summary.
8.4.6 Överföringssummeringar för postakut vård (PACIO)
När en patient lämnar sjukhuset för ett vårdhem, en rehabiliteringsenhet eller hemsjukvård, skickar sjukhusets journalsystem ett C-CDA: en överföringsöversikt, en utskrivningsöversikt eller ett CCD. Perfuse omvandlar det dokumentet till överföringsöversikten som beskrivs i PACIO:s Transitions of Care-guide (hl7.fhir.us.pacio-toc 1.0.0): en FHIR R4 document-samling, US Core 8.0.1 inuti, som mottagande anläggningens system kan arkivera utan att någon behöver läsa XML.
- Var och en av handbokens femton sektioner finns med, var och en med sin egen text, i handbokens ordning: förväntade direktiv, allergier, beteendehälsa, funktionell status, vaccinationer, utskrivningsinstruktioner, medicinska enheter, läkemedel, vårdplan, problem, procedurer, anledning till remiss, resultat, social historia och vitala tecken.
- En sektion som dokumentet inte har sägs vara saknad, aldrig ifylld. Den skickas ut tom, med den kodade orsaken
unavailableoch meningen "Det ursprungliga dokumentet hade ingen ... sektion". En tom allergisektion får inte tolkas som "inga kända allergier". - En sektion som bärs som ren text behåller sin text och får inga poster. Prosa omvandlas inte till kodad data. Funktionell status, beteendehälsa (C-CDA:s mentala statussektion), förväntade direktiv, medicinska enheter, vårdplan, utskrivningsinstruktioner, anledning till remiss och social historia skickas på detta sätt idag; noterna säger så för var och en.
- Kodade poster blir resurser enligt samma regler som den vanliga omvandlingen: allergier (US Core AllergyIntolerance), problem och utskrivningsdiagnoser (US Core Condition, problemlista eller mötesdiagnos), procedurer, vaccinationer, resultat, vitala tecken och läkemedel som en PACIO-läkemedelslista av MedicationStatements (
104204-3, utskriven läkemedelslista, från en utskriven läkemedelssektion;104202-7, aktiv läkemedelslista, annars). - Vitala tecken i FHIR:s form. Ett systoliskt och ett diastoliskt tryck som tas tillsammans blir ett blodtryckspanel (
85354-9) med två komponenter, och en mer specifik kod (kroppsvikt mätt,3141-9) bär också koden FHIR:s vital-signs-profiler fix (29463-7), bredvid den ursprungliga. - Vem och varifrån. Dokumentets författare blir Compositions författare (en praktiker, med NPI när dess kontrolliffer är giltigt), dess vårdgivare vårdgivarorganisationen, dess omfattande möte vistelsen som sammanfattningen avslutar. Ett dokument utan person som författare, eller utan vårdgivare, avvisas: handboken kräver båda, och Perfuse kommer inte att lägga till ett namn på en klinisk post som ingen har gett.
- Negation behåller sin betydelse. "Inga kända allergier" (en negerad allergi mot någon substans) skickas som SNOMED CT
716186003; en negerad allergi mot ett läkemedel avvisas, eftersom FHIR inte kan säga det och resursen skulle säga motsatsen; en negerad problem ärrefuted.
Tre sätt att skapa en:
- A channel: a
cdadestination withwrite: transferposts each document's transfer summary to the FHIR server's
Bundle endpoint (url), or writes <document>.transfer.json to dir. In the channel builder: Emit › A PACIO transfer summary.
- The command line:
perfuse fhir transfer [-authority OID=URI] [-out dir] <document.xml>.... - The console: Documents, turn on Also make a PACIO transfer summary, and read the document.
Kontrollerad med den officiella FHIR-valideraren mot TOC 1.0.0 Bundle-profilen, på HL7:s egna C-CDA-exempel (en överföringssummering, en utskrivningssummering och en CCD). Felet den rapporterar är i guiden: varje vital tecken matchar både dess simple-observation och dess vital-signs Bundle-entries slices, så det kan inte undvikas av någon avsändare. Inte gjort ännu: omvandling av textbaserade avsnittens poster (funktionsstatus, mental status, vårdplan, enheter) till kodade resurser, och guidens TOC DocumentReference som index en lagrad överföringssummering.
8.4.7 Prenumerationer
Med -fhir-subscriptions skickar FHIR-slutpunkten meddelanden när en möte eller ett möte skapas eller ändras. Den följer FHIR-prenumerations R5 Backport IG för R4, som är vad CMS Interoperability Framework-kriterium 15 och TEFCA:s FHIR-vägkarta använder för mötes- och mötesmeddelanden.
En klient skapar en Subscription som namnger ett ämne och valfritt en filter, till exempel Encounter?patient=Patient/123. Ämnena listas i kapacitetsutlåtandet:
| Ämne | Utlöser på | Filter |
|---|---|---|
https://perfuse.health/fhir/SubscriptionTopic/encounter | Möte skapat eller uppdaterat | patient, status, class |
https://perfuse.health/fhir/SubscriptionTopic/appointment | Tidbokning skapat eller uppdaterat | patient, status |
Ett filter som namnger något annat avvisas, inte ignoreras. Ett ignorerat filter är en prenumeration som meddelar om varje patient när klienten begärde en.
Egenskaperna som implementationen byggs runt:
- An acknowledged change is never a lost notification. The notification is recorded in the same database transaction as the change it describes, and delivered from there, so it survives a restart. A test writes an Encounter, starts a new server on the same database, and checks the notification arrives.
- Notifications arrive in order, and gaps are visible. Event 2 is not sent before event 1 is accepted, and each notification carries the running count, so a receiver can tell when it has missed one.
- The server decides when a subscription is active. A new subscription is
requested, and becomesactiveonly when the endpoint accepts a handshake. A client that asks foractivegetsrequested. A refused handshake is tried again four times over about fifteen seconds before the subscription is anerror: it goes out the moment the subscription is stored, often before the client that created it is listening. - A full-resource notification carries the version that changed. A discharge notification carries the discharge, not whatever the Encounter had become by the time delivery succeeded.
- Failure is bounded. A refused delivery is retried with a growing delay. After ten consecutive failures the subscription goes to
error: later changes are counted but not queued, and updating the subscription resumes delivery from the oldest held notification. The count then shows how many were missed.
Vad en klient kan göra servern att göra är avsiktligt begränsat:
- Slutpunkter måste vara
httpssåvida operatören inte skickar-fhir-subscriptions-allow-http, vilket är för en testmottagare. - Utgångspolicyn tillämpas när en prenumeration skapas, igen vid varje leverans och på den adress som varje anslutning faktiskt når (så ett namn som ändrar vad det löser till mellan kontrollen och anslutningen avvisas fortfarande); omdirigeringar följs inte.
- Nyttolasten är som standard
id-only, vilket anger vad som ändrades och låter mottagaren hämta det med sina egna autentiseringsuppgifter. - Ingenting en mottagare skickar tillbaka visas för någon, endast dess statuskod.
Det är avstängt såvida det inte begärs, eftersom en FHIR-klient kan göra att denna server skickar patientdata till en URL som klienten väljer. Den behöver en R4-slutpunkt som accepterar skrivningar och vägrar att starta annars.
Inte implementerat, så att ingen behöver ta reda på det genom att försöka:
- kanaler förutom
rest-hook - hjärtslag
- meddelanden vid borttagning
$status- och$events-operationer
Prenumerationsvyn visar varje prenumerationens ämne, filter och slutpunkt, hur många händelser den har haft, hur många som accepterats och hur många som väntar, och den senaste orsaken till att en avvisades. Huvudvärden och slutpunktens frågesträng undanhålls, eftersom det är där en prenumerants autentiseringsuppgifter bor.
8.5 NCPDP Telekommunikationsstandard
Apoteksanspråk. Fast breddhuvud följt av variabla segment.
Två detaljer som är viktiga, båda av vilka är lätta att göra fel och producera trovärdiga resultat:
Huvudet är exakt 56 byte och fast bredd. Ett kort huvud kan inte upptäckas genom längd ensam, eftersom ett trunkerat huvud plus de följande segmenten fortfarande överstiger 56 byte. Upptäckt sker genom att huvudet scannas efter en separatorbyte, så ett meddelande som innehåller en sådan vägras med antalet byte det är kort med.
0x1E och 0x1C är grupp- och fältstartmarkörer, inte separatorer. Att behandla dem som separatorer förskjuter varje fält ett steg till vänster, och de flesta av de resulterande värdena förblir trovärdiga — en mängd hamnar där en dagsförsörjning förväntades och båda är nummer.
0x1C, som är MLLP:s egen slut-blockbyte, så ramning av ett krav skulle trunkera det vid den första fältmarkören.8.6 NCPDP SCRIPT
Elektroniska recept, i XML. Det interna paketet kallas eprescribe eftersom script var upptaget av JavaScript-motorn.
Den centrala säkerhetsfrågan är ersättningsflaggan, och den läses baklänges från intuitionen: på tråden, 0 betyder att ersättning är tillåten och 1 betyder att den ska expedieras som skriven.
En frånvarande ersättningsflagga vägras snarare än standard. Båda möjliga standarder når patienten — en kan expediera en generisk där läkaren krävde varumärket, den andra förhindrar en ersättning som läkaren tillät — så det finns ingen säker antagande och meddelandet stoppas.
Ett recept för schema II med påfyllningar vägras, och byggaren kommer inte att producera en.
Vägran och varningar hålls som separata listor snarare än en lista med allvarlighetsgrader, eftersom en läsare som måste kontrollera ett allvarlighetsfält för att veta om meddelandet skickades kommer så småningom inte att kontrollera det.
Elektronisk förhandsauktorisation (PAInitiationRequest, PARequest, PAAppealRequest, PACancelRequest) och Real-Time Prescription Benefit besvaras av betalarsidan på /ncpdp/script och /ncpdp/rtpb, från läkemedelsformuläret; se CMS-0057.
8.7 DICOM
Bild. Perfuse kan ta emot DICOM-objekt, fråga en fjärrarkiv och lagra till en, över de klassiska DICOM-nätverkstjänsterna eller över DICOMweb, och den kan behålla ett arkiv av sin egen för visare.
DICOM är inte en meddelandeformat i samma mening som de andra — objekt är stora, och associationshandslaget är viktigare än payload-parsing. called_ae- och calling_ae-titlarna är den vanligaste orsaken till att en första anslutning misslyckas, och felet ser ut som ett nätverksproblem snarare än ett konfigurationsproblem.
8.7.1 Vad en C-STORE-lyssnare accepterar
Lämna öppet, en DICOM-lyssnare accepterar allt från vem som helst som kan nå porten. Fyra inställningar under Vad denna lyssnare accepterar begränsar detta, och den första är den som är värd att förstå.
Endast acceptera dessa anropande AE-titlar är begränsningen. Den *anropade* AE-titeln — den som ligger bredvid adressen — är det namn en avsändare ringer, så den identifierar denna lyssnare snarare än avsändaren, och den är inte en begränsning. Vem som helst som kan nå porten kan använda den korrekta anropade AE-titeln, eftersom den publiceras till dem. Utan en lista över tillåtna anropare kan vilken värd som helst på nätverket skicka bilder till en klinisk kanal.
Endast acceptera dessa SOP-klasser och endast acceptera dessa överföringssyntaxer tar komma-separerade UIDs. Tom accepterar alla typer av objekt och förhandlar om vilken komprimering avsändaren erbjuder, vilket inkluderar typer som denna kanals destinationspunkter inte kan hantera. Att vägra vid associationshandslaget är tydligare för avsändaren än att acceptera objektet och misslyckas därefter.
Största objekt som accepteras är i byte, och noll betyder ingen gräns. Hela bildserier och långa serier kan nå gigabyte, så gränsen är annars minne.
8.7.2 DICOMweb
DICOMweb är DICOM över HTTP: QIDO-RS-sökningar, WADO-RS- och WADO-URI-hämtning, STOW-RS-lagring. Webbläsarvisare som OHIF endast talar DICOMweb, och så gör molnbildtjänsterna (Google Cloud Healthcare, Azure Health Data Services, AWS HealthImaging). Perfuse använder det på tre ställen.
Bildarkivet. Starta servern med -dicomweb-archive DIR (Inställningar › Data › Bildarkiv) och den håller objekt i den mappen, indexeras i SQLite och serveras på /dicomweb på konsolens egen adress: QIDO-RS på studie-, serienivå och instansnivå, WADO-RS för objekt, metadata, ramar och bulkdata, WADO-URI på /dicomweb/wado, och STOW-RS. Läsning tar vyrollen och lagring operatörsrollen, med en session eller en API-token; varje läsning och lagring är i Aktivitet som dicomweb.read eller dicomweb.store. Ett konto begränsat till en hyresgäst eller till kanalgrupper vägras, eftersom arkivet tillhör hela servern. Objekt hålls exakt som de mottogs, så vad en vy hämtar är byte för byte vad som lagrades. Ramar returneras i den överföringssyntax de lagrades i; en begäran som skulle kräva omkodning svarar 406 snarare än en omvandlad bild.
En sökning på ett attribut som arkivet inte indexeras svarar 400 i stället för att ignorera villkoret och returnera fler studier än som begärdes. Indexerat: patientnamn (jokertecken och fuzzy-sökning med fuzzymatching=true), patient-ID, födelsedatum, kön, studie datum och tid (intervall), åtkomstnummer, studie-ID, beskrivning, remitterande läkare, studie-, serie- och SOP-instans-UID (listor), modalitet, kroppsdel, serienummer och beskrivning, SOP-klass, instansnummer, rader, kolumner och antal ramar.
Källan. type: dicomweb lyssnar efter STOW-RS, på /dicom-web/studies som standard (sökvägen Orthanc och dcm4chee använder), och skickar varje objekt genom kanalen som ett DICOM-meddelande. Kanalen behöver dataType: dicom. Ställ in en bearer-token eller ett användarnamn och lösenord: utan en, kan vem som helst som kan nå porten skicka bilder in i kanalen. Svaret listar varje objekt som lagrat eller misslyckat, med DICOM-felorsaken, så avsändaren vet vilka som ska skickas igen.
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}
Mottagaren finns i leverans, under DICOMweb-arkiv.
Pecka OHIF mot arkivet
Använd en DICOMweb-datakälla med qidoRoot och wadoRoot inställd på arkivets adress (skärmen Imaging visar den, med hela datakällblocket att kopiera), wadoUriRoot till den adressen följt av /wado, imageRendering och thumbnailRendering till wadors, och supportsFuzzyMatching true. En vy på en annan ursprung behöver den ursprunget i -dicomweb-cors (Tillåtna webbläsar-ursprung som kan anropa det), och dess begäranden behöver en API-token i Authorization-huvudet, eftersom en webbläsare på en annan ursprung inte skickar konsolens sessionscookie. Att serva OHIF från samma ursprung via en omvänd proxy undviker båda.
Testad mot Orthanc med dess DICOMweb-plugin, i båda riktningarna: destinationen lagrar i Orthanc, och Orthancs DICOMweb-klient söker i Perfuses arkiv och hämtar en studie som är byte-identisk med den som lagrats. OHIF 3 listar arkivets studier och visar deras ramar med inställningarna ovan. OHIF och flera andra klienter skickar type= utan citattecken i Accept- och Content-Type-huvudena, vilket RFC 2045 inte tillåter; Perfuse accepterar det.
8.8 IHE-dokumentdelning: XDS.b, XCA, XDR, MHD, PIXm och PDQm
Kliniska dokument som delas mellan organisationer på samma sätt som hälsouppgiftsutbyten, Carequality och eHealth Exchange gör: ett arkiv innehåller dem, ett register indexerar deras metadata och en community svarar på andra communities frågor genom en gateway. Starta servern med -xds REPOSITORY-OID (Inställningar › Data › Dokumentdelning) och det är alla tre, i den här serverns databas, på dessa adresser, var och en som tar en API-token som en bearer-token (viewer-rollen för att fråga och hämta, operator-rollen för att skicka in; de flesta affinitetsdomäner lägger till ömsesidig TLS framför)
| Adress | Aktör | Transaktioner |
|---|---|---|
/xds/repository | Dokumentarkiv | ITI-41 Tillhandahåll och registrera dokumentuppsättning-b, ITI-43 Hämta dokumentuppsättning |
/xds/registry | Dokumentregister | ITI-18 Registerlagrad fråga (alla tretton lagrade frågor), ITI-42 Registrera dokumentuppsättning-b |
/xca/gateway | XCA-svarsgateway | ITI-38 Gateway-fråga, ITI-39 Gateway-hämta, med -xds-home-community urn:oid:... |
/mhd | MHD-dokumentmottagare och -svarare | ITI-65 Tillhandahåll dokumentpaket, ITI-66 Hitta listor, ITI-67 Hitta dokumentreferenser, ITI-68 Hämta dokument |
/mhd/Patient | PDQm-leverantör och PIXm-hanterare | ITI-78 Patientdemografisk fråga, ITI-83 Patient/$ihe-pix, från FHIR-lagrets patienter |
/pixv3 | PIX-hanterare (HL7 v3) | ITI-44 Patientidentitetsflöde HL7 V3, ITI-45 PIXV3-fråga, från patientindexet (-mpi) |
/pdqv3 | PDQ-leverantör (HL7 v3) | ITI-47 PDQV3-fråga, med fortsättning och avbryt, från patientindexet |
SOAP-transaktionerna är SOAP 1.2 med WS-Addressing, och MTOM/XOP där dokument reser (ett dokument inline som base64 accepteras också). En misslyckad transaktion besvaras med en RegistryResponse som innehåller IHEs felkoder, inte ett SOAP-fel: XDSDuplicateUniqueIdInRegistry, XDSNonIdenticalHash, XDSPatientIdDoesNotMatch, XDSMissingDocument, XDSRegistryMetadataError (med det fält som saknas), XDSStoredQueryMissingParam, XDSUnknownStoredQuery, XDSUnknownRepositoryId, XDSUnknownCommunity och UnresolvedReferenceException. Ett ersättningsdokument (RPLC, XFRM_RPLC) gör det dokument det ersätter föråldrat, som sedan bara svarar på frågor som begär föråldrade dokument; APND, XFRM och signs behålls som associationer. Hash och storlek beräknas av lagringsutrymmet och kontrolleras mot vad inlämningen säger. Dokument och metadatauppdatering på begäran (ITI-57) stöds inte, och en inlämning som begär dem avvisas med orsaken.
MHD är samma register i FHIR: ett dokument som tillhandahålls via MHD hittas av ITI-18 och via XCA, och ett som tillhandahålls via XDS.b hittas av ITI-67. En DocumentReferences id är postens UUID, dess masterIdentifier det unika id, och dess bifogads url är ITI-68-adressen för dokumentet. Patienter matchas till affinitetsdomänens identifierare från FHIR-lagret: den första identifieraren vars system är urn:oid:, eller den Patient som ingår i Bundle. PIXm svarar på varje annan identifierare för Patienten med den angivna (sourceIdentifier=system|value, begränsad av targetSystem), och 404 för en den inte känner till; PDQm söker efter identifierare, namn, födelsedatum, kön, adress och telecom.
Publicering. En kanals xds-destination publicerar varje kliniskt dokument den tar emot, ett CDA-dokument eller ett som ingår i ett HL7 v2-meddelande, till valfritt XDS.b-repository med ITI-41. Metadatan läses från dokumentet: patienten (identifieraren i patient_domain, affinitetsdomänens tilldelade myndighet), titel, typ (som typeCode och, såvida den inte är inställd, classCode), skapande- och servicetider, författare, konfidentialitet, språk och format (C-CDA 2.1 eller 1.1 strukturerad kropp, XDS-SD eller mimeTypeSufficient, från dess mallar); och kompletteras med vad ett dokument inte säger: avsändarens source_id, facility_type och practice_setting som varje register kräver. Lagringsutrymmets RegistryResponse bestämmer leveransen: ett fel, eller ett fel i en PartialSuccess, är en misslyckad leverans med registrets felkoder.
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. Lägg till direct_from (din Direct-adress) och direct_to (mottagarnas) och samma destination skickar XDR som Directs transport, som Direct-projektets *XDR och XDM för Direct Messaging* beskriver det: en Direct-adressblock (urn:direct:addressing) i SOAP-huvudet namnger avsändare och mottagare, och inlämningsförfarandets intendedRecipient namnger varje mottagare (||^^Internet^address). Pek url mot mottagarens XDR-slutpunkt eller en HISP som accepterar XDR. XDR reser över TLS, vanligtvis med ett klientcertifikat (tls), och är inte S/MIME. En direct-källa accepterar också XDR (se Direct nedan).
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 och PDQ i HL7-version 3. Med patientindexet på (-mpi), är /pixv3 en PIX-hanterare och /pdqv3 en PDQ-leverantör över SOAP 1.2, för sjukhus och utbyten som fortfarande talar IHE:s v3-profiler. En källa matar patienter med ITI-44 (post added PRPA_IN201301UV02, reviderad PRPA_IN201302UV02, dubbletter lösta PRPA_IN201304UV02): patientens första identifierare är dess post, de andra och de i asOtherIDs är identifierare den bär, och en sammanfogning viker den tidigare postens identifierare in i den överlevande, som en HL7 v2 A40 gör. ITI-45 (PRPA_IN201309UV02) svarar på de andra identifierarna för personen som innehåller en, inskränkt av dataSource, i Patient.id; den frågade identifieraren kommer tillbaka endast i den upprepade frågan. ITI-47 (PRPA_IN201305UV02) matchar demografi (namn, kön, födelse, identifierare, adress, telecom) med indexets egen matchare, minimumDegreeMatch som en poäng på 100, otherIDsScopingOrganization begränsar domänerna, och initialQuantity sidnumrerar svaret: resten kommer med QUQI_IN000003UV01 under tio minuter, eller släpps av dess avbryt. Svaren följer transaktionernas fall: en okänd patient eller domän är AE med fel 204 och platsen för parametern, en känd patient med ingenting i de domäner som begärts är NF. v3 namnger en myndighet endast med OID, så en identifierare vars system är en URL med ingen OID bakom (vissa nationella nummer) lämnas utanför v3-svar och ges över FHIR; ange företagsidentifierarens system till en OID (urn:oid:..., i indexinställningarna) för EUID och vårdgivaren att visas. Visningsrollen frågar och operatörsrollen matar; varje transaktion är granskad med en identifierare, aldrig ett namn. Ett naket v3-meddelande som postas som application/xml besvaras på samma sätt, vilket är praktiskt för testning för hand.
Utbyte › Dokumentdelning visar vad registret innehåller och var det nås, hittar en patients dokument i detta register eller ett annat (ett registers ITI-18 eller en gateways ITI-38), laddar ner ett och publicerar ett CDA-dokument manuellt med metadatan en destination skulle ge det.
Verifierad mot NIST XDS Toolkit 7.13.0, IHE-referensimplementeringen: Perfuses ITI-41, ITI-18 och ITI-43 mot dess Registry/Repository-simulator (accepterad med inga valideringsfel, dokumentet hämtat byte-identiskt), och dess Initiating Gateway-simulator som frågar och hämtar från Perfuses Responding Gateway via XCA, utan fel i dess logg. Varje SOAP-meddelande som Perfuse skriver validerar mot ebXML Registry 3.0 och XDS.b-scheman, och MHD DocumentReference och SubmissionSet mot IHE MHD 4.2.2 med HL7 FHIR-valideraren. XDR från en xds-källa med en Direct-adressblock accepterades av verktygets Document Recipient-simulator, vars metadata-validering fann den enda defekten som beskrivs i docs/verification.md, och av ONC SITE:s XDR-validerare, Direct XDR-kontrollistan som (h)(2)-certifieringstestet tillämpar. PIX- och PDQ v3-svar validerar mot IHE:s HL7 V3-scheman (NE2008 multicacheschemas), och IHE:s egna exempelmeddelanden (ITI-44-feed, sammanfoga, ITI-45-fråga, ITI-47-fråga, fortsättning och avbryt) besvaras som deras publicerade svar visar. Inte ännu kontrollerad mot en oberoende PIX- eller PDQ v3-implementering, Gazelle eller en Connectathon.
8.9 Direkt säker meddelandeöverföring
Direct är hur amerikanska vårdgivare skickar remisser, sammanfattningar och resultat till varandra via säker e-post: varje meddelande signeras med avsändarens certifikat och krypteras till mottagarens (S/MIME), och reser mellan HISPer (Health Information Service Providers) som utfärdar adresserna och garanterar för dem. Perfuse är edge-systemet bredvid din HISP, inte en HISP: HISP utfärdar din adress, dess certifikat och dess nyckel, och du behåller dess trust-bundle (såsom DirectTrusts). Det följer Direct Applicability Statement för Secure Health Transport 1.2, Implementation Guide för Delivery Notification, IHE XDM (ITI TF-1 Annex 15) för dokument med metadata, Certificate Discovery för Direct Project Implementation Guide (DNS och LDAP), och XDR och XDM för 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
Motta. En direct-källa är SMTP-servern som HISP levererar din adresss e-post till. Den tar emot e-post för den adressen endast (allt annat vägras vid RCPT), kräver STARTTLS när den ges ett certifikat, och öppnar varje meddelande innan något läser det: dekrypterar det med din nyckel, verifierar signaturen mot dina ankare och kontrollerar att signaturcertifikatet är för Från-adressen eller dess domän. Ett meddelande som inte är krypterat S/MIME, är signerat av en avsändare som du inte litar på, eller är signerat av ett certifikat för någon annan vägras vid DATA med orsaken, så HISP behåller det och rapporterar det till avsändaren; Perfuse accepterar aldrig vad den sedan släpper. Ett XDM-pakets dokument blir var och ett ett meddelande (kontrollerat mot hash-värdena i dess metadata); annars blir varje bilaga ett, eller texten när det inte finns någon. Med smtp_host inställt, svarar varje meddelande som tas emot med ett signerat, krypterat "bearbetat"-meddelande (MDN), och meddelanden som anländer för vad du skickade loggas.
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
Från HISP:s brevlåda. En HISP som sparar e-post i stället för att leverera den ger adressen en IMAP-brevlåda: imap läser den (TLS eller STARTTLS, en ny session vid varje omräkning), öppnar varje meddelande på samma sätt, flyttar det som togs till move_to (eller tar bort det) och det som inte kunde öppnas till error_folder, så att ingenting läses två gånger. listen kan sedan lämnas ut. En HISP vars e-postserver har ett privat certifikat litar på tls.ca_file (dess certifikat eller dess auktoritetscertifikat) och tls.server_name; verifiering kan inte stängas av.
imap:
host: imap.hisp.example
username: intake@direct.clinic.example
password: ${DIRECT_MAILBOX_PASSWORD}
move_to: Processed
XDR. xdr tar XDR på /xdr på sin egen HTTPS-adress, som en HISP skickar Direct som konverterats till SOAP eller en partner skickar punkt-till-punkt: en ITI-41 Provide och Register-förfrågan vars dokument var och en blir ett meddelande. En inlämning vars Direct-adressblock namnger en annan adress avvisas, och en som kanalen inte tar besvaras med en RegistryResponse-fel som säger varför. client_ca_file kräver ett klientcertifikat från de auktoriteter. XDR skyddas av TLS, inte S/MIME, så en källa som endast tar XDR behöver adressen men inte dess certifikat, nyckel eller ankare. Varje dokument blir ett meddelande av kanalens dataType: CDA-dokument behöver raw (överförs som de är) eller hl7v3, eftersom standarden, hl7, förväntar sig HL7 v2 och avvisar dem.
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
Utbyte › Direct listar de Direct-adresser dina kanaler skickar och tar emot som, med deras certifikat, utgång och ankare; behåller adressboken för korrespondenter (namn, organisation, anteckningar och certifikat, klistrade från deras HISP eller hittade i DNS eller LDAP, och avvisade när det inte är för den adressen eller domänen); och söker upp en adress certifikat i DNS eller LDAP utan att spara dem. Boken är katalogen direct-certs bredvid databasen, en PEM-fil per adress eller domän, som en destination läser såvida den inte namnger sin egen recipient_certs_dir.
Verifierad mot OpenSSL 4.0:s cms och smime i båda riktningarna: vad Perfuse signerar och krypterar verifierar OpenSSL och dekrypterar (PKCS#1 v1.5 och OAEP-nyckeltransport), och Perfuse öppnar vad OpenSSL signerar och krypterar (AES-128 och AES-256). Ett meddelande som skapats med openssl smime och levereras via SMTP tas emot, öppnas och sparas av en kanal, och en som Perfuse skickar till en annan via en HISP-ersättning, som svarar med en MDN som avsändaren öppnar. Certifikat hittas i OpenLDAP 2.4 (adressbundna och domänbundna, skrivna av OpenLDAP:s egen ldapadd); ett Direct-meddelande läses från en GreenMail IMAP-postlåda och öppnas, och ett som inte är Direct flyttas till felmappen; XDR från en xds-destination tas av en direct-källa och avvisas när det är adresserat till någon annan, och accepteras av NIST XDS Toolkit:s Document Recipient och ONC SITE:s XDR-validerare; SITE:s Direct XDR Edge Test Tool skickade både sina minimala och fullständiga metadata-meddelanden till en direct-källa, som tog emot dem. Mot ONC:s Direct Certificate Discovery Tool väljer en Direct-destination rätt certifikat, eller inget, i alla 18 av dess upptäcktsfall (D1 till D18: utgångna, återkallade och AIA-utgivna certifikat, SRV-prioritet och vikt, en otillgänglig katalog). En Direct-källa läser ett meddelande från SITE:s egen HISP (Apache James) via IMAP med STARTTLS. Inte testat ännu: SMTP-utbyte med SITE:s HISP (AWS håller utgående e-post på port 25 för nya konton) eller med en ackrediterad HISP.
8.10 SQL på FHIR-vyer
En ViewDefinition (HL7 SQL på FHIR v2) omvandlar varje FHIR-resurs av en typ till rader med namngivna kolumner, varje kolumn en FHIRPath-uttryck, så FHIR-data kan läsas som tabeller av DuckDB, Athena, Spark, en datawarehouse eller ett kalkylblad. Perfuse kör dem med sin egen FHIRPath-motor: column, nested select, forEach, forEachOrNull, repeat och unionAll, where, constant (varje värde[x]-typ), collection-kolumner, %rowIndex och getResourceKey() och getReferenceKey(type)-join-nycklar.
{
"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" }
]}]
}
Övervaka › SQL på FHIR kör en vy över den här serverns FHIR-lagring (en patient, eller alla) eller över resurser som klistrats in (NDJSON från en bulkexport, en Bundle, en JSON-array), visar raderna och laddar ner dem som CSV, NDJSON eller Parquet. Den startar från fem exempelvyer (patientdemografi, observationer med ett värde, blodtryck, tillstånd, möten) och sparar vyerna till views-katalogen bredvid databasen, en JSON-fil vardera.
FHIR-slutpunkten svarar på specifikationens $sql-run på systemnivå, med GET eller POST, för en ViewDefinition-ämne som ges inline (subjectResource), med subjectReference (ViewDefinition/<name>, en sparad vy) eller med subjectCanonical (en sparad vy:s url), med _format (csv, ndjson (standard), json eller parquet), header, patient, _since, _limit och resource för att köra över resurser som skickas med begäran istället för lagringen. Det är en läsning: en SMART-token behöver läsbehörighet för vyens resurstyp, en token bunden till en patient får endast den patientens rader, och granulära behörigheter begränsar de resurser som läses, som de gör en sökning. Mer än en miljon rader kräver _limit, patient eller _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-filer har en radgrupp och okomprimerade PLAIN-sidor; booleska värden är BOOLEAN, heltalstyper INT64, decimaler DOUBLE och allt annat UTF-8-strängar (en samlingkolumn som dess JSON).
Verifierat med den officiella SQL på FHIR-testsviten (de 144 testerna i sql-on-fhir.js-repositoriets tests/, körda på varje bygge: alla passerar), och Parquet-utmatningen lästes tillbaka av DuckDB 1.5.6 med rätt typer och värden. Inte stödd: SQLQuery och SQLView-bibliotek (SQL över vyernas tabeller), $sql-export, _format=fhir och source- och group-parametrarna; var och en avvisas med orsaken.
8.11 Digitala kvalitetsmått
En digital kvalitetsmätning räknar patienterna i varje population av en FHIR Measure under en mätningsperiod (initial population, täljare, täljareundantag och undantag, nämnare, nämnareundantag) och poängsätter resultatet. Svaret är en FHIR MeasureReport, formad som Da Vinci Data Exchange for Quality Measures (DEQM)-guiden ber om. Detta är där CMS:s eCQM-program och NCQA:s digitala HEDIS är på väg.
In Perfuse the population criteria are FHIRPath ("language": "text/fhirpath"), run by the same engine as SQL on FHIR. Each criterion is evaluated once per patient. Its focus is a Bundle of that patient's record (the Patient compartment), and it has these variables: %subject (the Patient), %periodStart and %periodEnd (the period, as dateTimes) and %"Measurement Period". A criterion gives true or false; a single value that exists counts as 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()"
}
}
Populationerna är hierarkiskt ordnade enligt Måttspecifikationen. En patient ingår endast i nämnaren om de ingår i den initiala populationen. En nämnare-exklusion tar bort patienten innan täljaren bedöms. En nämnare-undantag räknas endast för en patient som inte ingår i täljaren. En proportions poäng är (täljare - täljare-exklusioner) / (nämnare - exklusioner - undantag); en förhållande-måtts poäng är täljare / nämnare; en kohort har räkningar och ingen poäng. Enkeltkriterie-stratifiering delar varje population efter deras värde (t.ex. kön).
Perfuse har ingen CQL-motor. De publicerade CMS eCQMs och HEDIS digitala mått är skrivna i CQL, så de kan inte köras som de är. Ett Mått vars kriterier är CQL avvisas med det skälet. Skriv logiken som FHIRPath istället. Kontinuerlig variabel-poäng, flerkomponents-stratifiering och Grupp eller Praktiker-ämnen avvisas på samma sätt.
Övervaka › Kvalitetsmått utvärderar ett mått över den här serverns FHIR-lagringsplats eller över klistrade resurser, under en viss period. Det erbjuder tre rapporter: en sammanfattning, en sammanfattning med patienterna i varje population eller en patient. Skärmen visar populationerna, poängen och strata, och laddar ner MeasureReport. Det börjar med tre exempel: blodtryck under kontroll, diabetes med ett HbA1c-test och patienter som setts under perioden. De är illustrativa, skrivna för den här handboken, och är inte CMS eCQMs eller HEDIS-mått. Spara till FHIR-lagringsplatsen kontrollerar måttet och lagrar det som en Measure-resurs.
FHIR-slutpunkten svarar på Measure/[id]/$evaluate-measure och Measure/$evaluate-measure?measure=<url>, antingen via GET eller via POST av en Parameters-resurs. Parametrar:
periodStartochperiodEnd: obligatoriska. En datum innebär hela dagen.reportType:summary,subjectellersubject-list.subject:Patient/<id>.reporter:Organization/<id>. När den är frånvarande innehåller rapporten en organisation som namnges avserve -measure-reporter.measure: ett mått som skickas inline, som en POST-parameter.
Rapporten returneras, inte lagras. Operationen är en läsning, så en SMART-token behöver läsåtkomst till Mått och Patient. En token bunden till en patient får en individuell rapport om den patienten och ingen annan.
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.
Verifierad. HL7 FHIR-valideraren kontrollerar de levererade Måtten mot FHIR R4, utan fel. Den kontrollerar en sammanfattning, en individuell och en ämneslist-MåttRapport mot DEQM 5.0.0 sammanfattning, individuell och ämneslist-profiler, också utan fel. Ej verifierad: ekvivalens med något publicerat eCQM, eftersom ingen kan köras här utan CQL.
8.12 Patientindex (MPI)
En masterpatientindex länkar samman de poster varje system har för en person (sjukhusets MRN, kliniken, laboratoriet) till en enda företagsidentifierare, EUID. Den är avstängd tills någon bestämmer sig för att behålla den, eftersom den är en tabell med patienternas namn, födelsedatum och identifierare: aktivera Inställningar → Data → Patientindex (eller serve -mpi) och starta om. Den finns i mpi.db bredvid den primära databasen.
Matning. Lägg till en destination av typ mpi (Patientindex i byggaren) till de kanaler som bär registreringar. Den läser PID för varje HL7 v2-meddelande eller en FHIR-Patient på en rå kanal. Postens egen identifierare är PID-3-repetitionen av typ MR (id_type ändrar den); de andra, och PID-19, blir dess andra identifierare. En tilldelningsmyndighet med en universell identifierare (PID-3.4.2 med typ ISO) blir urn:oid:...; en med endast ett namnområde mappas av authorities, eller blir urn:perfuse:aa:<namespace>. En A40, A34, A18 eller A39 slår samman personen som har MRG-1:s identifierare med personen som har PID-3:s (no_merge ignorerar dem).
destinations:
- name: index
type: mpi
mpi:
authorities: { HOSP: "urn:oid:1.2.840.114350.1.13.1" }
Matchning. En ny post kopplas i denna ordning:
- Tillförlitliga identifierare. En post som delar en identifierare från ett system som listas som tillförlitligt (en nationell identifierare, ett företagsnummer) är samma person, utan någon poängsättning. Lista aldrig ett system som en familj delar, såsom en betalares abonnentnummer.
- Poäng. I annat fall hittas personer vars poster som kan matcha genom blockering (samma ljudande efternamn och födelseår, samma födelsedatum eller samma telefonnummer) och poängsätts med Fellegi-Sunter-vikter över efternamn och förnamn (Jaro-Winkler och Soundex, accenter och punkteering ignoreras, byta namn uppmärksammas), födelsedatum (en dag och månad som byts ut är delvis överensstämmelse), kön, postnummer, telefon och adress. Endast fält som båda posterna har räknas. Poängen är den bevisning som hittats som en andel av den möjliga bevisningen. Blockering använder fem nycklar, så att ett fel inte döljer en person: efternamnsljud och födelseår, födelsedatum, telefon, båda namnens ljud (i vilken ordning som helst) och postnummer med förnamnets ljud.
- Beslut. Som standard länkas ingenting på en poäng ensam. En post som poängsätts till eller över granskningsgränsen (60%) blir en ny person och den möjliga matchen väntar på granskningskön; de som är till eller över den automatiska gränsen (90%) med efternamn och födelsedatum som båda överensstämmer markeras *säkra*. Att länka samman två personer till en (en överlappning) placerar en patients resultat i en annan persons journal, så automatisk länkning är en ström som en administratör vänder på (Länka säkra matcher utan att fråga någon) när kön har visat att de säkra är rätt. Med den på länkas en säker match när ingen andra person poängsätts lika högt. Under granskningsgränsen är posten en ny person.
Nationella nummer. NHS-numret (och Skottlands CHI och Nordirlands hälso- och sjukvårdsnummer), Irlands PPSN och IHI, Tysklands KVNR, Österrikes SVNR, Schweiz AHV-nummer, Nederländernas BSN, Belgiens nationella registernummer, Luxemburgs matricule, Frankrikes INS (NIR och NIA), Italiens codice fiscale, Spaniens DNI/NIE och CIP-SNS, Portugals SNS-nummer, de nordiska personnumren (Sverige, Danmark, Norge med dess D-nummer, Finland, Island), de baltiska koderna, Polens PESEL, de tjeckiska och slovakiska födelsenumren och de ungerska, rumänska, bulgariska, kroatiska, slovenska och grekiska numren är kända för indexet. Var och en lagras på ett sätt: under dess systems schema, med utrymme och punkter borttagna, så att NHS-numret som skickas som urn:oid:2.16.840.1.113883.2.1.4.1|999 000 0018 av ett system och som https://fhir.nhs.uk/Id/nhs-number|9990000018 av ett annat är en identifierare. En HL7 v2 PID-3-repetition vars identifierartyp är NN och ett lands trebokstavs-kod (NNDEU, NNNLD) läses som det landets huvudsakliga nummer, och typ NH från NHS-myndigheten som NHS-numret. Varje nummers kontrollsiffra testas: en som misslyckas sparas på dess post, rapporteras (maskerad) i svaret och används aldrig för att länka eller hitta någon, eftersom en felaktigt angiven siffra vanligtvis gör en annan persons nummer. Danmarks CPR kontrolleras endast för dess datum, eftersom nummer som utfärdats sedan 2007 inte behöver passera den gamla modulen 11.
Inställningslistan visar varje schema med dess format, dess kontroll och systemet det lagras under. System som tagits från landets egen FHIR-guide (UK Core, fhir.de, Nictiz, CH Core, ANS, HL7 Italia, MedCom, de svenska, norska och finska OID-registren) markeras som sådana; de andra är standarder som kan ändras till det nationella värdet, vilket en webbplats kan göra per schema (det gamla är fortfarande erkänt). Att lita på ett schema är en tick. Nationella nummer visas i sin helhet för redaktörer och ovan som standard och maskeras (de sista tecknen) för alla andra; Vem ser nummer i sin helhet ändrar detta, ned till visare eller upp till administratörer endast. Där ett lands lag begränsar ett nummers användning (Frankrikes Référentiel INS, Irlands PPSN, Belgiens nationella registernummer, Tysklands §290 SGB V), anger inställningarna detta. GET /api/mpi/schemes listar scheman och POST /api/mpi/check kontrollerar ett nummer utan att spara det. FHIR $match och PIXm svarar auktoriserade klienter med nummer i sin helhet.
Ett datum skrivet dag- eller månadsförst (08/15/1972) sparas som skrivet och matchar inte ett år-först: den amerikanska och europeiska ordningen är oenig, och att gissa skulle länka fel personer.
Patientregister skärmen (Build) visar antal, hittar personer efter namn, nummer, EUID eller födelsedatum, och öppnar varje person: deras journaler, alla identifierare, och historiken över vad som har hänt dem och vem som gjorde det. Redigerare beslutar om granskningar (Samma person länkar dem; Olika personer håller dem separerade för alltid), flyttar en journalpost till en annan person, tar bort en journalpost (Inte denna person), och slår samman två personer. Administratörer ställer in tröskelvärdena, de betrodda identifieringssystemen, de nationella nummren och EUID-systemet. Varje sökning och varje person som läses skrivs till revisionsloggen.
Att svara på andra. POST /fhir/Patient/$match (FHIR:s operation, som IHE PDQm ITI-119 använder) tar en Patient och returnerar de personer som kan vara det, bäst först, each en Patient vars id är EUID, med varje identifierare, search.score, och match-grade-tillägget (certain, probable, possible); onlyCertainMatches och count hedras. PIXm (/mhd/Patient/$ihe-pix, ITI-83) svarar från indexet: every identifier för varje post som är länkad till personen, och EUID. Så gör PIX och PDQ i HL7 v3 (/pixv3, /pdqv3; se IHE-dokumentdelning), som också matar det.
API:n är /api/mpi (sammanfattning och sökning), /api/mpi/persons/{euid}, /api/mpi/find, /api/mpi/reviews, /api/mpi/records (register, länka, avlänka), /api/mpi/merge och /api/mpi/settings.
Vikter. Standard-Fellegi-Sunter-vikterna kommer från register-länkage-litteraturen för sjukhusregistreringsdata. Uppskatta från våra poster (i inställningarna, administratörer; POST /api/mpi/estimate) anpassar dem till webbplatsens egen index med förväntans-maximering, inga granskade par behövs: m (överensstämmelse bland sanna matcher) från paren som blockeringen bringar samman, u (överensstämmelse av en slump) från 20 000 par som dras slumpmässigt, eftersom blockerade par överensstämmer på namn och datum genom konstruktion. Uppskattningen visas bredvid de vikter som används och ändrar ingenting tills den används och sparas. Ett fält som jämförs på för få par behåller sin standard. Anpassningen antar att fälten är oberoende av klassen, vilket de inte riktigt är, så behandla en stor förändring med misstanke.
Mätt. På FEBRL-dataset 3 (5 000 syntetiska poster om 2 000 personer, de dubbletter som bär skrivfel, byta fält, saknade värden och smeknamn; PERFUSE_TEST_FEBRL), registrerad i filordning med en granskare som svarar på varje kört par korrekt:
| Länkad på egen hand | Satt framför en granskare med rätt person | Missad | Fel länkar | |
|---|---|---|---|---|
| Automatisk länkning av (standard) | 0 | 2 649 av 3 000 | 351 | 0 |
| På, standardvikt | 1 637 | 1 012 | 351 | 0 |
| På, vikter uppskattade från posterna | 1 622 | 1 070 | 308 | 0 |
Ingen post var någonsin länkad till fel person, och ingen av de 2 000 nya personerna var kört onödigt. De missade skiljer sig på nästan varje fält (ett födelsedatum och en adress båda felstavad, säg) och poängsätter under granskningsgränsen. FEBRL är syntetisk och har få namnsdubbletter; en riktig index har fler, så dess granskningskö kommer att vara längre, och dessa nummer är en golv på omsorg, inte ett löfte.
8.13 Avgränsad
CSV och dess släktingar. Alternativen finns på källan i byggaren, och formatreferensen listar filnycklarna.
Sökvägar adresserar kolumner. En namngiven kolumn är tillgänglig när en rubrikrad deklareras eller namnen anges; annars är kolumner positionella.
8.13.1 Namnge kolumnerna
Det finns två sätt, och de är exklusiva. Antingen namnger den första raden i filen dem — den första raden namnger kolumnerna — eller så listar du dem själv, i ordning. Att deklarera en rubrik innebär att raden inte behandlas som data.
Om ingen av dem är inställd, kan kolumner bara adresseras med position, så ett filter skrivet mot ett namn har ingenting att matcha. Att aktivera rubriken tar bort listan med namn i stället för att behålla båda: med en rubrik kommer namnen från filen, så en lista som lämnas kvar skulle ignoreras, och en kanal som läser som om den valde namnen när filen valde dem är svårare att felsöka än en som vägrar.
8.13.2 Vad ett filter eller ett skript ser
En avgränsad dokument blir många meddelanden, så detta behöver anges innan du skriver något av dem.
Med delning på, körs allt per rad. Declarativa steg, filtret och transformerings-skriptet ser alla en rad, och en sökväg betyder *denna* rads kolumn. Ett filter som avvisar en rad avvisar bara den raden och ingen annan, och den mottagna räkningen är rader snarare än dokument.
Med delning av, är meddelandet hela dokumentet och en skrivning som korsar rader vägras i stället för att tillämpas på den första. Detta vägran är medvetet: tyst skrivning till rad ett är beteendet som producerar en fil som ser omvandlad ut och inte är.
8.13.3 De tre som ändrar vad som räknas som ett fel
Acceptera rader med fel antal kolumner är avstängd som standard. En rad med för många eller för få kolumner är då ett fel, vilket är vad som fångar en fil vars form har ändrats utan varning. Att aktivera den accepterar raden och lämnar de saknade kolumnerna tomma.
Trimma utrymmen runt varje värde fixar det vanliga fallet med ett värde som är utformat till en kolumnbredd. Lämna den avstängd där efterföljande utrymmen är betydelsefulla, vilket de ibland är i en identifierare.
Behåll tomma rader som rader är avstängd som standard och bör vanligtvis vara det. På, blir en tom rad en rad med tomma kolumner, vilket bara har betydelse när en räkning måste matcha filen exakt.
8.14 Rå
Ingen parsing alls. Meddelandet är bytes.
Använd detta när innehållet inte är något som Perfuse förstår och inte behöver: en PDF som flyttas mellan system, ett proprietärt format, ett redan bildat dokument som skickas oförändrat.
Kostnaden är att ingenting som beror på struktur fungerar — ingen fält-nivå-transformation, inget filter på ett fält, ingen fält-nivå-jämförelse i paritetskontrollen. En rå kanal är en pipeline, och den är ärlig om att vara en.
8.15 Välj
Om meddelandet är HL7 v2, använd hl7, även om du bara avser att vidarebefordra det oförändrat. Parsing ger dig spåret, fält-nivå-statistiken, möjligheten att filtrera senare och möjligheten att jämföra. raw på parsbar innehåll köper ingenting och förlorar allt detta.
Använd raw när parsing skulle misslyckas eller skulle vara en lögn om innehållet.
8.16 SMART Hälsolänkar och -kort
CMS:s *Död åt urklippet* ber providern att acceptera en patients journaler från en QR-kod vid incheckning, och att lämna besöksjournalen tillbaka på samma sätt. QR-koden innehåller en SMART Hälsolänk (shlink:/...): en adress, en 256-bitarsnyckel och, om så önskas, en etikett, ett utgångsdatum och en passkodsflagga. Utbyte → Hälsolänkar läser en.
Mottagning. Klistra in länken eller skanna den med kameran där webbläsaren kan (Chrome och Edge). Perfuse hämtar manifestet, dekrypterar varje fil med nyckeln från länken, sammanfattar eventuella FHIR-paket - vem patienten är, hur många av varje resurs - och kontrollerar eventuella SMART Hälsokort inuti mot dess utgivares publicerade nyckel. *Leverera till kanalen* överför FHIR-innehållet till en kanal som ett meddelande, vilket är hur det når EHR. Hämtningen hålls till utgående princip vid anslutningstid, vanlig HTTP avvisas och svaret från en server som inte är en manifestserver visas aldrig, eftersom adressen kom från en främlings QR-kod.
Delning. *Dela* krypterar ett FHIR-paket, värdar det och visar länken och dess QR-kod en gång. Servern behåller ciphertexten och inte nyckeln - den kan inte öppna vad den värdar, och kan inte visa länken igen. En passkod hashas; tio felaktiga inaktiverar länken. Länkar upphör att gälla efter 30 dagar som standard, kan återkallas och listar hur ofta och av vem de hämtades. Starta servern med -public-url inställd på https-adressen som patienternas telefoner når; manifest-URL:en den bygger måste passa specifikationens 128 tecken.
Verifiera ett kort. *Verifiera ett kort* tar en numerisk shc:/ QR (en bit eller flera), en .smart-health-card-fil eller en JWS, och anger om signaturerna matchar utfärdarens nyckel.
8.17 UN/EDIFACT
dataType: edifact läser UN/EDIFACT-utbyten (ISO 9735): ORDERS, INVOIC, DESADV, IFTSTA och resten, inklusive det europeiska hälsovårdsanspråket och laboratorie-meddelanden. Tjänstesträngsrådet (UNA) hedras, med release-tecknet och, för syntaxversion 4, upprepningsseparatoren; funktionsgrupper (UNG/UNE) är valfria. Utbytet levereras exakt som avsändaren skrev det.
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"'
Kuvertet. UNT:s segmenträkning och referens, UNE:s meddelanderäkning och referens, och UNZ:s räkning och referens jämförs med vad utbytet innehåller. Med require, standard, vägrar en mismatch utbytet (det är hur en överföring som kapas visar); warn accepterar det och loggar en varning; ignore kontrollerar inte.
Sökvägar, för kanalen och destinationsfilter, räknar element och komponenter från 1 i den ordning segmentet skrivs, som implementeringsguider numrerar dem: BGM-2 (dokumentnumret), BGM-1.1, NAD(2)-2.1 (den andra NAD:s part), LIN-3(2).1 (en upprepning), UNB-2.1 (avsändaren), UNH-2.1 (meddelandetypen). En sökväg utan förekomst adresserar varje en.
Delning levererar ett utbyte per meddelande, var och en med den ursprungliga UNB (och gruppheadern) och trailers som räknar en, så en order kan filtreras, sökas och återförsökas på egen hand. Destinationsfilter ser varje bit. En fildestination namnger filer efter meddelandetyp (ORDERS_INVOIC-20261017.edi), och ${control_id} är utbytesreferensen.
CONTRL. Med acknowledge: contrl svarar en avsändare som skickar via HTTP med en CONTRL-syntaks- och servicerapport: UCI-åtgärd 7 när utbytet lästes och levererades, 4 när det vägrades eller inte kunde levereras (HTTP 400 eller 502 då). Det kan inte kombineras med split, eftersom en CONTRL svarar på ett helt utbyte. Över AS2 är partnerns mottagande bekräftelsen.
Ej erbjuds: meddelandekataloger (vilka segment ORDERS D.96A tillåter), så strukturen kontrolleras, inte innehållet; transformationer, som skulle skriva om en partners dokument; och filter- eller transformerings-skript (en preprocessor körs, innan parsing). Kontrollerat mot pydifact 0.1.8, en oberoende parser, i båda riktningarna.
9 Bekräftelser
En bekräftelse berättar för avsändaren vad som hände. För HL7 v2 via MLLP är det ett ACK-meddelande; avsändaren kommer inte att skicka nästa meddelande förrän det anländer, och kommer vanligtvis att skicka om det inte anländer.
Att få bekräftelser fel är det vanligaste sättet en integration tyst förlorar data, eftersom en avsändare som bekräftas har ingen anledning att klaga.
9.1 Tid
Beskrivs i meddelandeflöde, och sammanfattningen är: ack.when är on_delivery som standard, vilket innebär att bekräftelsen skickas bara efter att varje aktiverad destination har accepterat meddelandet. on_receipt skickar det så snart meddelandet har parsats och köats.
9.2 Vad Perfuse skickar
En AA när meddelandet accepterades, en AE när det avvisades av en anledning som avsändaren kunde agera på, och en AR när det avvisades av en anledning som avsändaren inte kunde.
Skillnaden mellan AE och AR är vem som måste göra något. AE betyder att meddelandet hade ett problem - ett fält som inte kunde parsas som ett datum, ett krävt segment som saknades - och avsändaren kan korrigera det och skicka om. AR betyder att Perfuse inte kunde acceptera det oavsett innehåll, vilket vanligtvis betyder ett konfigurations- eller tillgänglighetsproblem i denna ände. En avsändare som skickar om efter en AR kommer att få samma svar.
9.3 Identifiera den här motorn
ack.application och ack.facility fyller i MSH-3 och MSH-4 i bekräftelsen.
När båda är tomma speglar bekräftelsen den ursprungliga mottagaren — den använder vad den inkommande meddelandet hade i MSH-5 och MSH-6. Det är vad de flesta avsändare förväntar sig, och det är standard för den skull.
Ange dem explicit när avsändaren validerar dem, eller när flera Perfuse-instanser hanterar samma flöde och du behöver veta vilken som svarade.
9.4 Utlösande händelse
ack.include_trigger_event skickar ACK^A01 istället för ett tomt ACK.
Vissa mottagare kräver det och andra avvisar det, vilket är varför det är ett explicit alternativ utan någon smart standard. Om en avsändare vägrar att acceptera dina bekräftelser och innehållet ser rätt ut, är detta det första du ska försöka.
9.5 Negativa bekräftelser är inte fel som kan döljas
En NACK som behandlas som en framgång är en av de mest skadliga felkonfigurationerna som är möjliga, och det är tillräckligt vanligt för att vara värt att nämna. Det inträffar när en destination skickar tillbaka en negativ bekräftelse och den sändande sidan registrerar *överföringen* som lyckad eftersom byte skickades ut och något kom tillbaka.
Perfuse läser bekräftelsen den tar emot från en MLLP-destination och registrerar resultatet enligt. En AE eller AR från ett nedströmsystem är en leveransfel, som omprövas enligt destinationens policy, och bidrar till felraten som utlöser varningar.
9.6 Tidsgränser
Att vänta på en bekräftelse är begränsat. När den inte anländer i tid är leveransen en fel och köas för omprövning.
En tidsgräns är inte samma sak som ett avslag och registreras på ett annat sätt. Ett avslag betyder att den andra sidan övervägde meddelandet och avvisade det; en tidsgräns betyder att du inte vet om det bearbetades. Den distinktionen avgör om en omprövning är säker: att ompröva efter ett avslag är meningslöst, och att ompröva efter en tidsgräns riskerar en dubblett. Perfuse omprövar efter en tidsgräns, eftersom ett saknat kliniskt meddelande vanligtvis är värre än en dubblett, och mottagarsystemet vanligtvis kan upptäcka en upprepad meddelandekontroll-ID.
Om den handeln är rätt för ett visst flöde är en bedömning, och det är värt att göra medvetet för allt där en dubblett har en klinisk konsekvens — en order, en medicinadministrering — snarare än att acceptera standardvärdet tyst.
9.7 Källor som inte bekräftar
Inte alla transportmedel har begreppet. En filkälla har ingenstans att skicka en bekräftelse; en brokerkälla bekräftar till brokern snarare än till den ursprungliga avsändaren; en HTTP-källa svarar med en statuskod.
Där källan inte kan leverera bekräftelseläget som en kanal begär, avvisas kanalen vid inläsning snarare än att starta och tyst inte bekräfta. En kanal som tror att den bekräftar och inte gör det är värre än en som inte startar.
9.8 X12-bekräftelser
Allt ovan handlar om HL7 v2. X12 har sina egna bekräftelser, och till skillnad från v2 är de avstängda som standard: en tom inställning betyder ingen.
Den standarden är den säkra, eftersom en handelspartner som inte förväntar sig en bekräftelse och tar emot en kan behandla den som en oönskad interchange. acknowledge-nyckeln på en X12-kanal tar ett av fyra värden:
| Värde | Vad som skickas |
|---|---|
none | Ingenting. Standard. |
999 | Implementeringsbekräftelse. Ersätter 997 för HIPAA-transaktioner. |
997 | Funktionsbekräftelse. Äldre, och fortfarande vad många betalningsanslutningar förväntar sig. |
ta1 | Interchange-bekräftelse, om omslaget snarare än dess innehåll. |
Vilket som ska skickas är en egenskap hos handelspartnerrelationen snarare än meddelandet, vilket är varför det måste konfigureras och inte kan härledas. En 999 ersätter en 997 för HIPAA-transaktioner, men många partners — äldre betalningsanslutningar särskilt — är inställda på att förvänta sig en 997 och kommer att behandla en 999 som en okänd fil.
9.9 HL7 v3-bekräftelser
En HL7 v3-kanal skickar en bekräftelse som standard, vilket är motsatsen till X12 och värt att veta.
Orsaken är transporten snarare än standarden: en v3-interaktion anländer vanligtvis över en synkron anslutning där avsändarprogrammet väntar på ett svar, och en avsändare som inte får något svar kommer vanligtvis att försöka igen. Det är så en patient registreras tre gånger.
Att stänga av det är möjligt och måste göras uttryckligen — "inte inställt" och "inställt till false" är medvetet olika, så standardinställningen står kvar såvida någon inte har sagt något annat.
10 Leverans, köande och återförsök
En destination som inte kan nås är det normala fallet, inte undantaget. System startas om, nätverk släpps och en sjukhusgränssnittsmotor är otillgänglig under sitt eget underhållsfönster. Leverans byggs runt det.
10.1 Kö per destination
Varje destination har sin egen kö. En destination som misslyckas påverkar inte de andra, och var och en har sin egen djup, ålder och återförsöksstatus.
Köande sker per destination snarare än per kanal eftersom felet är per destination. En kanalvid kö skulle fördröja leverans till tre fungerande system eftersom ett fjärde är nere, och de två situationerna — en destination otillgänglig, alla fyra otillgängliga — skulle se likadana ut i statistiken.
10.2 Köinställningar
queue on a destination:
| Nyckel | Vad den gör |
|---|---|
enabled | Om misslyckade meddelanden köas över huvud taget. |
max_attempts | Hur många gånger som ska försökas innan man ger upp. |
backoff | Vänta innan det första återförsöket. |
max_backoff | Tak på den växande väntan. |
max_depth | De flesta meddelanden som ska hållas. Om den inte är inställd, finns det ingen gräns. |
retain_hours | Hur länge ett levererat meddelande ska behållas. Om den inte är inställd, behålls den tills vidare. |
De två sista saknades i den här tabellen och i byggaren, och de är paret som förhindrar att en disk fylls. En kö med varken växer tills filsystemet är fullt, och det felet anländer som något orelaterat som går sönder — ett skrivfel någon annanstans helt — snarare än som ett köproblem.
Backoff växer mellan försök upp till max_backoff. Växande snarare än fast, eftersom en destination som är nere vanligtvis är nere i minuter snarare än sekunder, och att försöka igen varje sekund i tio minuter producerar flera hundra logginlägg som begraver det som är viktigt.
10.3 Ordningen bevaras
Inom en destination levereras meddelanden i ankomstordning, och ett meddelande som misslyckas behåller sin plats. Senare meddelanden väntar bakom det snarare än att överträffa.
Detta är rätt standard för kliniska data — en inläggning och en utskrivning som tillämpas i fel ordning är värre än att båda är sena — och det har en konsekvens som är värd att förstå: ett meddelande som alltid misslyckas kommer att hålla upp allt bakom det.
Det är därför ködjup och köålder är separata varningsvillkor. En djup kö som töms är ett system som är upptaget. En kö där den äldsta meddelandet fortsätter att bli äldre är fast, och varningstyperna queue-depth, queue-age och queue-stuck skiljer dem åt.
max_attempts är vad som begränsar skadan: efter det sparas meddelandet som misslyckat och kön fortsätter. Att ställa in max_attempts mycket högt i hopp om tillfällig framgång omvandlar ett enda misslyckat meddelande till en stoppad feed.10.4 När köande är inaktiverat
Med queue.enabled false är en misslyckad leverans en misslyckad leverans. Den registreras och försöks inte igen.
Det är rätt val när sen data är värre än ingen data — en realtidsvisning, ett pagersystem, allt där ett meddelande som levereras fyrtio minuter efter händelsen skulle vara vilseledande snarare än bara försenat.
Det är fel val för allt som går in i en post, där meddelandet är lika giltigt en timme senare.
10.5 Återförsök mot kö
Det finns två mekanismer och de fungerar på olika nivåer.
retry på en destination styr omedelbara försök inom en leverans — en anslutning som misslyckas försöks igen efter en kort paus, utan att lämna leveranssökvägen. Detta hanterar tillfälliga fel: en nerslagen anslutning, ett tillfälligt avslag.
queue styr vad som händer när de omedelbara försöken är uttömda. Meddelandet lämnar leveranssökvägen och försöks igen senare enligt en längre schemaläggning.
Båda finns eftersom de två felen är olika. En anslutningsåterställning på det första försöket är vanligtvis borta på det andra, och att gå genom kön för det skulle lägga till minuter av latens till ett fel som varade millisekunder. En destination som har stängts av för underhåll kommer inte att återkomma inom tre omedelbara försök, och att bearbeta den är meningslöst.
10.6 Vad en HTTP-slutpunkt räknas som levererad
En HTTP-destination har tre inställningar som avgör om ett meddelande behandlas som skickat, och alla tre finns på destinationen i byggaren.
Statuskoder som betyder levererad. Tom betyder alla 2xx. Vissa slutpunkter svarar 202 Accepted för något de inte har bearbetat ännu, och vissa svarar 200 med ett fel i brödtexten — den senare är vad *Behandla som misslyckad om svaret innehåller* är till för. Att ange en explicit lista är värt att göra när en partner har berättat vilken kod som betyder vad, eftersom alternativet är att upptäcka skillnaden från ett meddelande som aldrig levererades och aldrig köades.
Följ omdirigeringar. Avstängd som standard, och med avsikt. En omdirigering kan peka på en annan värd, så att följa en skickar meddelandet någonstans som ingen har konfigurerat och rapporterar framgång.
Bearer-token. Skickas som en Authorization-rubrik. Den lagras med kanalen och visas aldrig igen, så att lämna rutan tom när du redigerar en befintlig kanal behåller token som redan sparats snarare än att rensa den.
10.7 Namngivning och beskärning av ett arkivmapp
En fildestination lägger till en fil per dag och meddelandetyp som standard (20261012-ADT_A01.hl7), MLLP-ramad så att filen kan återuppspelas med perfuse send. Fyra inställningar på destinationen ändrar detta.
Filnamn (file_name) skapar en fil per meddelande istället, namngiven från ${date}, ${timestamp}, ${control_id}, ${message_type} och ${destination}). Ett namn som redan tas (samma kontroll-ID två gånger) får ett unikt suffix snarare än att skriva över meddelandet där.
Lägg till (append: true) skriver varje meddelande till filen som Filnamn namnger, så ${date}.hl7 är en fil per dag för varje typ.
Suffix vid skrivning (temp_suffix, en fil per meddelande endast) är som standard .part och tas bort genom en omnamning när filen är klar. Den som samlar in dessa filer bör inte plocka upp en ofullständigt skriven, och en omnamning inom en mapp är atomär. Ändra det endast om insamlaren filtrerar på en annan tillägg.
Ta bort efter (retain_hours) rensar filer i mappen som är äldre än det angivna antalet timmar, kontrollerat som mest var tionde minut medan meddelanden anländer. Endast vanliga filer direkt i mappen tas bort, aldrig en undermapp. Tom eller noll behåller dem för alltid, vilket är standard och är ett beslut snarare än ett förbiseende - men ett arkiv som ingen rensar fyller disken, och en full disk stoppar kanalen snarare än arkiveringen.
10.8 Skicka till en FHIR-server
Tre inställningar avgör hur mycket som kontrolleras innan en samling lämnar.
Påstå US Core-överensstämmelse lägger till profilen till varje resurs. Påstå endast det när resursen bär det som profilen kräver, eftersom en mottagare kan validera mot påståendet och avvisa en samling som annars skulle ha accepterats.
Validera innan skicka kontrollerar varje resurs här snarare än att lära sig från mottagaren. Ett avslag i den avlägsna änden berättar mindre, senare och ofta endast i en logg som du inte kan läsa.
Behandla varningar som avslag har endast effekt när validering är på, och kontrollen är otillgänglig tills den är. Den är tillräckligt strikt för att stoppa en samling som en mottagare skulle acceptera, så den hör hemma på en feed som tas i bruk snarare än en i tjänst.
10.8.1 Värdtjänster för FHIR
En fhir-destinations auth-block loggar in på de värdtjänster där en klistrad bearer-token slutar fungera inom en timme:
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 signerar varje begäran för AWS HealthLake med Signaturversion 4, med regionen läst från URL:en. azure hämtar en Microsoft Entra ID-token för Azure Health Data Services från tenant_id, client_id och client_secret - en appregistrering som innehåller FHIR Data Contributor-rollen - med FHIR-tjänst-URL:en som dess publik. client_credentials gör detsamma mot valfri OAuth 2.0 token_url. Token återanvänds tills en minut före de upphör att gälla. Samma val finns under destinationens Värdtjänst-inloggning i kanalbyggaren.
10.8.2 Allmänna hälsorapporter
Bocka i Rapportera rapporterbara tillstånd till folkhälsa på en FHIR-destination och den skickar fallrapporter snarare än paket. Varje meddelande kontrolleras för en rapporterbar-tillstånds-utlösande kod: en diagnos, en labbtest eller en kodad resultaträkning. Om den har en, blir meddelandet en HL7 eCR 2.1.2 eICR, innesluten i ett eCR-meddelande och skickat till URL:ens $process-message. Om den inte har någon, skickas ingenting och ingenting misslyckas; destinationen räknar det som inte rapporterbart.
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 är Reportable Conditions Trigger Codes, antingen som en FHIR ValueSet eller eRSD-paket. Det kräver en UMLS-licens, så det ingår inte; utan det används en kort inbyggd exempeluppsättning, endast för testning. source är där myndigheten skickar sin Reportability-svar. Anläggningen krävs eftersom eCR begär dess telefon och adress, och ett v2-meddelande har varken det ena eller det andra.
En rapport beskriver vad meddelandet saknade snarare än att uppfinna det, och varje lucka loggas. Försök med ett meddelande i FHIR-labets Public health case report-panel innan du pekar en live-feed mot en myndighet.
10.8.3 Labresultat till allmänna hälsorapporter: ELR
perfuse elr -config elr.yaml results.hl7 omvandlar ett labs resultat till HL7 2.5.1 ELR-meddelanden som statens hälsoavdelningar tar emot, ett för varje meddelande med ett rapporteringsbart resultat, och endast de beställningar som bär ett sådant: en komplett blodräkning bredvid ett positivt SARS-CoV-2-test är inte folkhälsofråga. Utlösningskoderna är desamma som för casereporting, RCTC som du laddar eller den inbyggda exempeluppsättningen.
ELR namnger alla med OID eller CLIA-nummer, som ingen labbmatning bär med sig för avsändare och mottagare, så dessa kommer från filen:
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}
Beställningsanläggningen, utförande laboratorium och tilldelningsmyndigheter används endast där labbetets meddelande lämnar dem utan, och varje användning är en anteckning. Det som endast labbet vet fylls aldrig i: ett resultat utan provtyp går med SPM-4 tom och en anteckning som säger så, eftersom en gissad prov i en rapport till folkhälsofråga är värre än en lucka som staten kan fråga om. Börja med processing: T medan statens onboardningsteam testar feeden.
Det som labbet fick rätt behålls som det skickades. Ett barnbeställning (en känslighetspanel eller en reflextest som OBR-29 namnger dess förälder och som inte har någon ORC av sig själv) skickas som mottaget, utan någon ORC eller prov som uppfanns för det, och ett barn utan något rapporteringsbart resultat av sig själv skickas med dess förälders, eftersom en känslighet inte betyder något utan den kultur den tillhör. En anteckning efter PID stannar med patienten, och ORC-14, återuppringningsnumret, kopieras från OBR-17 när labbet endast lade det där. Alla 28 exempelmeddelanden som ONC publicerar för sin ELR-certifieringsverktyg kommer ut giltiga utan fel.
MSH-2 skrivs som ^~\&#, de fem tecknen som ELR Release 1:s errata kräver och ONC:s certifieringsverktyg kontrollerar. Om din stats guide visar de äldre fyra, lägg till encoding_characters: "^~\\&" till filen.
För att skicka dem från en kanal istället för från kommandoraden, ange destinationen som når tillståndet en elr-block som namnger samma fil. Varje laboratorieresultat omformas på vägen ut, och ett med inget rapporterbart skickas inte alls, vilket räknas som levererat, inte misslyckat: tillståndet begärde endast rapporterbara resultat.
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
Blocket gäller på en HL7 v2-kanal, till destinationer som levererar meddelandet själv (mllp, http, tcp, fil, sftp, ftp, S3, Azure Blob, soap, meddelandebrytare eller en annan kanal); kanalen vägrar att ladda annars, och när filen saknas eller saknar avsändaranläggning, mottagande program eller mottagande anläggning. Anteckningarna skrivs till loggen med meddelandets kontroll-ID.
ELR-filen är kanalen sällskap, inte en kanal: perfuse check och Kanalskärmen hoppar över den snarare än att rapportera en kanal som inte kan laddas. I kanalskaparen är samma två inställningar under destinationen, i Lab reporting (ELR 2.5.1); fältet för utlösningskoder öppnas när en ELR-fil namnges, och sparande vägrar en fil som inte är bredvid kanalen.
10.8.4 DICOMweb-arkiv
type: dicomweb lagrar varje objekt med STOW-RS: Orthanc, dcm4chee, molnbildtjänster eller en Perfuse-servers egen arkiv. Ge tjänstrot (https://pacs.example/dicom-web); /studies läggs till, och en URL som redan slutar med /studies vägras snarare än att publicera till /studies/studies. Autentisera med token (en bärares token) eller username och password; headers lägger till andra, såsom en molntjänsts projekthuvud. Kanalen behöver dataType: dicom.
Servrarens svar bestämmer resultatet, inte dess statuskod ensam. Ett objekt som svaret listar som misslyckat är en misslyckad leverans med DICOM-felet, och så är också ett 202 som inte listar något som lagrat: servraren tog emot begäran och behöll ingen del av den. Tidsgränsen är som standard två minuter, eftersom en stor serie är långsam.
10.8.5 Dokumentarkiv (IHE XDS.b)
type: xds publicerar varje kliniskt dokument till ett XDS.b-repo med ITI-41 Provide and Register: ett CDA-dokument eller ett som ett HL7 v2-meddelande (MDM, ORU) bär. Metadatan kommer från dokumentet och destinationens inställningar (source_id, patient_domain, facility_type, practice_setting), och repoets RegistryResponse bestämmer leveransen. Se IHE-dokumentdelning.
10.8.6 Vaccinationsregister
Varje US-stat immunisationsregister (IIS) tar emot HL7 2.5.1-meddelanden på samma SOAP-gränssnitt, det som CDC publicerade 2011 (namnområde urn:cdc:iisb:2011). Det har två operationer: connectivityTest, som bevisar slutpunkten, och submitSingleMessage, som bär meddelandet. En VXU^V04 rapporterar en vaccination och kommer tillbaka som en ACK; en QBP^Q11 frågar efter en patients historia och prognos och kommer tillbaka som en RSP^K11.
Välj Vaccinationsregister (CDC IIS webbtjänst) som tjänst för en SOAP-destination, eller skriv 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 bygger omslaget, så det finns inget brödtext att skriva. Användarnamnet och lösenordet placeras inuti begäran, där CDC WSDL placerar dem, inte i HTTP-autentisering. Versionen är SOAP 1.2, WSDL-bindningen, såvida du inte anger version: "1.1" för ett register vars guide begär det. Där ett register kräver ett klientcertifikat, ange destinationens tls som för alla HTTPS-samtal.
Registerets bekräftelse bestämmer om meddelandet levererades, inte HTTP-statusen. Ett register svarar ett avvisat vaccin med HTTP 200 och en AR inuti, så en destination som litade på statusen skulle rapportera en förlorad vaccination som levererad.
| Registret svarar | Perfuse posterar |
|---|---|
| AA (eller CA) | Levererad. |
AE vars ERR-segment är varningar (ERR-4 W eller I) | Levererad. Varningarna finns i svaret. |
AE med något ERR-4 E, eller ett ERR utan allvarlighetsgrad | Misslyckad, med varje ERR:s plats, kod och text i felet. |
| AR eller CR | Misslyckad, på samma sätt. |
| En SOAP-fel (fel lösenord, meddelande för stort) | Misslyckad, med registrets anledning. |
| Något som inte är ett HL7-meddelande | Misslyckad. |
warnings_are_errors: true (Behandla varningar som fel) gör att varje AE väntar på en person. Svaret, som svarsskript och en HTTP-anropare som väntar på kanalen läser, är registrets HL7-meddelande: ACK eller RSP med historik och prognos. examples/iis innehåller tre kanaler att starta från: VXU från en EHR via MLLP, QBP-frågor via HTTP och en lokal ersättning för ett register.
Instrumentpanelen Anslutningar ber ett register om dess connectivityTest när ingenting har skickats på sju dagar. Den åtgärden finns för detta ändamål och skickar ingenting, så det är den enda applikationsnivåkontrollen som Perfuse utför. Den bevisar adressen, TLS och SOAP-bindningen, men inte användarnamn och lösenord; endast en riktig inlämning testar dem.
En SOAP-källa kan svara på samma sätt: Svara som ett vaccinationsregister, eller profile: cdc-iis på källan. Den ekar connectivityTest, tar meddelandet från submitSingleMessage, returnerar kanalens bekräftelse i return och serverar CDC WSDL på ?wsdl. Ett användarnamn och lösenord, när de är inställda, kontrolleras mot dem i begäran, och ett felaktigt par får WSDL:s SecurityFault. Ett meddelande som kanalen avvisar skickas tillbaka som ett NAK, aldrig som ett fel, som CDC-handboken säger. Använd den som een testdubbel, eller för att ta emot inlämningar på samma sätt som ett register gör.
Ej täckt: de statsspecifika delarna av ombordstigning. Varje register har sin egen slutpunkt, kontoprocess och lokalt profil av guiden 2.5.1 (obligatoriska RXA- och OBX-fält, VFC-berättigande, vägranskoder). Dessa är meddelandenas innehåll, som kanalens transformationer formar; ingen statsspecifik slutpunkt är inbyggd. Perfuse har testats mot sig själv och mot inspelade registerbesvar, inte mot en live statlig register.
10.9 När transporten säger ja och meddelandet inte anlände
"Anlände detta" är ofta inte en fråga som transporten kan besvara. En MLLP-mottagare returnerar en applikationsbekräftelse vars betydelse är i dess text. En HTTP-mottagare returnerar 200 med ett fel-dokument. I båda fallen lyckades transporten och meddelandet anlände inte.
Inspektera svaret på en destination tar ett skript som ges mottagarens svar. Returnera false, eller kasta, och leveransen markeras som misslyckad — vilket innebär att den försöks igen, köas och visas i felräkningen istället för att tyst räknas som levererad.
Det erbjuds endast på destinationer som tar emot ett svar. På en som inte kan, avvisas det vid inläsning snarare än att lämnas aldrig körande.
10.10 Vad en leveransresultat betyder
| Resultat | Betydelse |
|---|---|
Delivered | Destinationsadressen accepterade meddelandet. För MLLP, mottogs ett positivt bekräftelsemeddelande. |
Queued | Leverans misslyckades och meddelandet kommer att skickas igen. |
Failed | Leverans misslyckades och kommer inte att skickas igen, antingen för att köhantering är inaktiverad eller för att antalet försök är slut. |
Filtered | Destinationsadressen avvisade meddelandet med hjälp av sin egen filter. Inte ett fel. |
Dessa spelas in per destination per meddelande, så ett meddelande som nådde tre av fyra destinationer spelas in som exakt det. Det finns inget kanal-nivå "lyckat", eftersom det inte skulle betyda något.
10.11 Långsam leverans
En destination som accepterar meddelanden men tar lång tid om det är ett distinkt problem från en som misslyckas, och det är lätt att missa eftersom varje resultat är en framgång.
Varningskategorin slow-delivery finns för detta. Den är värd att ställa in på allt där avsändarens bekräftelse väntar på leverans, eftersom en destinations svarstid som tyst har fördubblats så småningom kommer att korsa avsändarens tidsgräns och börja producera återsändningar — och vid den punkten visas symtomet uppströms, i ett system du kanske inte administrerar.
10.12 Skrivning till en databas
type: database kör en instruktion per meddelande med värden bundna från meddelandet.
Platshållare är förarens egna — $1 för postgres, ? för mysql och sqlite, @p1 för sqlserver — och Perfuse skriver inte om dem. Det är medvetet: en översättningslager som fick en platshållare fel skulle binda en patients namn till fel kolumn, och resultatet skulle se ut som giltig data snarare än ett fel.
En instruktion skriven i fel dialekt avvisas när den sparas, med namnet på stilen som föraren vill ha. Innan den kontrollen fanns felet som syntax error at or near "," från servern när ett meddelande anlände, som namnger en instruktion du skrev och så skickar dig att leta efter en typ istället för att titta på dialekten.
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
En citerad parameter är en konstant snarare än en sökväg, vilket är hur en kanal skriver sitt eget namn eller en källsystemkod i en rad bredvid meddelandedata.
Värden är alltid bundna som parametrar. En ${...}-referens inuti instruktionen avvisas: ett namn som innehåller en apostrof skulle bryta instruktionen, och ett fientligt värde skulle skriva om den.
10.13 Skicka till en rå socket
type: tcp skriver till en socket med den ram som du väljer, vilket är vad en enhet eller ett laboratorieinstrument vanligtvis vill ha. MLLP är en ram bland flera; denna destination erbjuder de andra.
destinations:
- name: instrument
type: tcp
tcp:
address: instrument.lab:9100
framing: delimited
delimiter: \r
expect_reply: true
timeout: 30s
Ramen har inget standardvärde, med flit. Att skriva med fel ram orsakar inte fel. Den avlägsna änden läser meddelanden som delats på fel ställen, eller väntar på en avslutare som aldrig kommer, och symtomen visas i mottagningssystemet snarare än här.
framing | Vad den skriver |
|---|---|
mllp | 0x0b före, 0x1c 0x0d efter. Samma ram som en MLLP-destination använder. |
delimited | En delimiter efter varje meddelande, och ett valfritt start_block före det. |
fixed | Poster som fylls ut eller trunkeras till record_length. |
length | En length_bytes-prefix. big_endian och length_includes_header har båda två konventioner i vilt tillstånd och skillnaden är tyst. |
whole | Ett meddelande per anslutning, stängd för att markera slutet. |
Endast de inställningar som den valda ramen använder accepteras. En postlängd i en avgränsad ström avvisas snarare än ignoreras, eftersom en inställning som tyst ignoreras är en som någon tror är i kraft.
expect_reply ändrar vad levererat innebär. Utan det betyder framgång att byte nådde operativsystemets skicka buffert — som en peer som kraschade för ett ögonblick senare aldrig läste.
10.14 Amazon S3, SQS och SNS
En kanal kan läsa från en SQS-kö eller en S3-bucketprefix och leverera till SQS, SNS eller S3. Alla fem är signerade HTTP med inget AWS SDK i binärfilen, och alla fem tar samma åtkomstinställningar: region, access_key_id, secret_access_key (skriv ${AWS_SECRET_ACCESS_KEY} för att läsa miljön), ett valfritt session_token och endpoint för LocalStack, MinIO eller en VPC-slutpunkt. Under Kanaler → Ny kanal, välj *Vi läser från en Amazon SQS-kö*, *Vi samlar in objekt från en Amazon S3-bucket* eller SQS-, SNS- och S3-måltypen.
Ingenting bekräftas till AWS förrän kanalen har hanterat det. Ett SQS-meddelande tas bort efteråt och återuppstår annars när dess synlighetstid går ut, så en kös återdirigeringsprincip är vad flyttar en som fortsätter att misslyckas till en död brevlåda. Ett S3-objekt flyttas till processed/ efteråt, eller till error/ om det inte kunde hanteras, så ett dåligt filstopp inte stoppar resten.
På en FIFO-kö eller ämne, grupperas meddelanden efter patient som standard - SQS behåller ordningen inom en grupp och ingen annanstans - och dubblettidentifieras efter innehåll, så en återförsök inte levereras två gånger.
En S3-arkiv kan skrivas direkt till Glacier med storage_class, och som JSON-rader för Amazon Athena med format: ndjson; perfuse athena skriver ut tabellen. Referensen har varje inställning.
10.15 AMQP 1.0 och Azure
AMQP 1.0 är vad Azure Service Bus och Event Hubs talar, och RabbitMQ 4, ActiveMQ och Artemis bredvid deras andra protokoll. En amqp-källa tar emot från en kö eller en prenumeration och accepterar varje meddelande endast en gång kanalen har hanterat det; en som inte kunde hanteras släpps som en misslyckad leverans, så mäklaren omlevererar den och, förbi könens gräns, dödbrevlådar den. En amqp-mål rapporterar framgång endast när mäklaren accepterar meddelandet. För Service Bus: addr är <namespace>.servicebus.windows.net:5671 med tls, username delad åtkomstprincipnamn, password dess nyckel och address kön namn, eller <topic>/subscriptions/<name> för att ta emot.
Azure Blob Storage: en azure_blob-mål skriver en blob per meddelande i den valda åtkomstnivån - Hot, Cool, Cold eller Arkiv - och en azure_blob-källa plockar upp blobbar från ett prefix, flyttar dem till processed/ eller error/ som S3-källan gör. Föredra en SAS-token begränsad till containern över kontonyckeln.
10.16 MQTT
En mqtt-källa prenumererar på ett ämnesfilter (+ matchar en nivå, # varje nivå under) på valfri MQTT 3.1.1-broker: Mosquitto, EMQX, HiveMQ, AWS IoT Core, Azure Event Grid. Vid QoS 1, standardvärdet, bekräftas varje meddelande endast en gång kanalen har hanterat det. MQTT har inget sätt att vägra ett enskilt meddelande, så ett som inte kunde hanteras lämnas obekräftat och anslutningen görs igen; brokern behåller sessionen under klient-ID (perfuse-<channel> såvida client_id inte anger annat) och skickar det igen, först i kön. QoS 0 är som mest en gång: allt som skickas medan Perfuse är nedstängt går förlorat. En mqtt-destination publicerar och, vid QoS 1, rapporterar framgång när brokern har meddelandet.
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 vill ha ett klientcertifikat: ge tls.cert_file och tls.key_file.
10.17 IBM MQ
ibm_mq läser och skriver IBM MQ-köer via köhanterarens meddelande-REST-API (mqweb), som IBM MQ 9.1.5 och senare levererar på varje plattform, z/OS inkluderat, så ingen MQ-klient installeras bredvid Perfuse. Användaren behöver MQWebUser-rollen och sätta, hämta och bläddra behörighet på kön. En källa bläddrar i det första meddelandet, överlämnar det till kanalen och tar bort det efter dess meddelande-ID endast en gång det hanterades; ett meddelande som misslyckas stannar kvar först på kön. Kör en läsare per kö. En mål sätter beständiga meddelanden (om inte non_persistent), med HL7-kontroll-ID som korrelations-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 är v3 för MQ 9.3 och senare (standard), v2 för 9.1.5 till 9.2. En köhanterare med en AMQP-kanal kan också nås med amqp-anslutningen.
10.18 Google Cloud Pub/Sub och Cloud Storage
En pubsub-källa hämtar från en prenumeration och bekräftar varje meddelande så snart det har hanterats; en som misslyckas återlämnas omedelbart (dess bekräftelsedeadline är inställd på noll), tillsammans med resten av dess batch, så Pub/Sub levererar det igen och, efter prenumerationens dödbrevspolicy, dödbrevar det. En pubsub-mottagare publicerar med HL7-meddelandetyp och kontroll-ID som attribut; order_by: patient anger ordningssnyckeln från PID-3.1, så en prenumeration med meddelandeordning håller varje patients meddelanden i ordning.
En gcs-mål skriver ett objekt per meddelande, namnges som en S3-nyckel, i den valda lagringsklassen (STANDARD, NEARLINE, COLDLINE, ARCHIVE). En gcs-källa plockar upp objekt från ett prefix och flyttar dem till processed/ eller error/ som S3-källan gör.
Båda loggar in som en tjänstekonto: credentials_file är dess JSON-nyckel. Lämna den tom på Google Cloud (en VM, GKE eller Cloud Run) för att använda tjänstekontot som är bifogat där. endpoint namnger en emulator (Pub/Sub-emulatorn, fake-gcs-server), som inte tar några autentiseringsuppgifter.
source:
type: pubsub
pubsub:
project: hospital-integration
subscription: adt-to-perfuse
credentials_file: /etc/perfuse/gcp-key.json
10.19 Läsa en inkorg (IMAP och POP3)
En email-källa läser en inkorg och omvandlar det den hittar till meddelanden: varje bilaga (take: attachments, standard, inskränkt av attachment_names-mönster), e-posttexten (take: body) eller hela e-postmeddelandet (take: raw) för att ett skript ska kunna ta isär det. Laboratorier, bildningscentrum och små mottagningar skickar fortfarande resultaten på detta sätt.
Varje kontroll loggar in, läser den olästa e-posten äldst först och loggar ut. Över IMAP hämtas ett e-postmeddelande utan att markeras som läst, överlämnas till kanalen och flyttas endast en gång varje meddelande från det accepterades till move_to (Bearbetad), markeras som läst (after_read: flag) eller tas bort. E-post som misslyckades eller som inte togs (en avsändare utanför allowed_senders, ingen bilaga som matchar attachment_names, större än max_message_size), flyttas till error_folder (Fel) med orsaken i loggen. Båda mapparna skapas när de saknas. POP3 har inga mappar eller flaggor, så den tar bort: borttagningar är åtaganden med QUIT i slutet av kontrollen, så en session som bryts av tar bort ingenting och ett hanterat e-postmeddelande kan läsas igen (aldrig förlorat). POP3-e-post som inte tas emot stannar på servern och rapporteras en gång.
Inloggning är ett lösenord (${MAIL_PASSWORD}; ett app-lösenord för Gmail) eller OAuth 2.0 via SASL XOAUTH2, som Microsoft 365 kräver (det har stängt av lösenordsinloggning) och Gmail föredrar:
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]
Med client_secret och inget refresh_token, används Microsoft 365 app-endast-åtkomst (client-credentials-beviljande, omfång https://outlook.office365.com/.default): en administratör registrerar appen, beviljar den IMAP.AccessAsApp och begränsar den till den ena inkorgen med en Exchange-tjänstprincipal. Med en refresh_token (en persons samtycke), används den delegerade omfånget IMAP.AccessAsUser.All eller POP.AccessAsUser.All, och en roterad refresh-token hålls för processens livslängd. Gmail behöver en refresh_token: Google erbjuder ingen app-endast-åtkomst till en inkorg.
allowed_senders tar adresser och domäner. Från-raden i ett e-postmeddelande kan förfalskas, så den håller ut olyckor och vilt mail, inte en angripare; en feed som måste lita på tillhör på Direct (S/MIME signerad), SFTP eller en VPN. security är tls (993 eller 995, standard), starttls (143 eller 110) eller none, som endast tillåts till localhost. Kontroller sker minst 10 sekunder isär (60 som standard), eftersom e-posttjänster begränsar konton som kontrollerar snabbare.
Testad mot GreenMail 2.1.3 (IMAPS, IMAP, POP3S och POP3: inloggning vägras med felaktigt lösenord, hämtning utan att markera som läst, FLYTTA, flagga, ta bort, ett för stort e-postmeddelande vägras innan det läses) och mot GMail:s IMAP med en app-lösenord (skapa en mapp, lägg till, hämta, FLYTTA, ta bort). OAuth testades mot en ersättnings-token-slutpunkt endast: inte mot Microsoft eller Google.
10.20 AS2
AS2 (RFC 4130) är hur många betalare, clearinghus och leverantörer utbyter EDI: en HTTP-POST vars brödtext är signerad med avsändarens certifikat och krypterad till mottagarens, besvarad med en kvittens (en MDN) som namnger en sammanfattning av vad som anlände. S/MIME är samma kod som Direct-meddelanden använder. Båda ändar är på kanalbyggaren: Handelspartners skickar oss EDI via AS2 som källa, En handelspartner via AS2 som destination.
# 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"
Mottagning. Ett meddelande till någon annan AS2-To, eller från en avsändare som inte finns i partners, nekas med 403 och ingen kvittens. Ett partners meddelande måste vara signerat och krypterat såvida dess post inte anger allow_unsigned eller allow_unencrypted. Nyttolasten dekrypteras, dess signatur kontrolleras mot partnerens certifikat (partners utbyter vanligtvis självsignerade, vilket är okej: certifikatet är förtroendet) och överlämnas till kanalen enligt dess meddelandeformat. Partnern får den kvittens den begärde: i svaret eller publicerad till dess Receipt-Delivery-Option-URL; signerad när den begärde en signerad. Ett meddelande som misslyckas får en kvittens som anger varför (decryption-failed, authentication-failed, insufficient-message-security, unexpected-processing-error).
Skicka. Varje meddelande signeras (SHA-256) och krypteras (AES-256-CBC). Med receipt: sync, standardvärdet, räknas det som levererat endast när kvittot verifieras mot partner_cert_file, säger processed och bär samma sammanfattning (MIC) som vad som skickades; allt annat är en misslyckad leverans och försöks igen. receipt: async ber om kvittot på receipt_url, som måste vara en AS2-källa på denna server som listar parten: meddelandet räknas som levererat så snart parten accepterar begäran, och ett kvitto som senare inte stämmer överens loggas som ett fel. receipt: none ber om ingenting. unsigned, unencrypted och unsigned_receipt slappnar av varje del för eett avtal som säger så; username och password lägger till HTTP-basautentisering för gateways som kräver det. Innehållstypen följer kanalens format (application/edi-x12 för X12) såvida content_type inte anger en annan.
Triple DES, AES-128 och AES-192 kan läsas samt AES-256, eftersom parter fortfarande skickar dem, och även den strömmande BER (obestämda längder) som Java-gateways skriver.
Komprimering (RFC 5402). Ett komprimerat meddelande läses oavsett hur det skapades: komprimerat före signering eller kryptering, eller ett signerat meddelande som komprimerats i sin helhet. Mottagningsmeddelandets MIC följer RFC: över vad som signerades när det signerades, över den okomprimerade innehållet när det inte är det. Ett meddelande som skulle expandera förbi tio gånger källans max_message_size avvisas med decompression-failed, så att några kilobyte inte kan göra anspråk på gigabyte av minne. En destination komprimerar med compress: true, före signering och kryptering, som de flesta gateways gör; fråga parten först.
Ett meddelande skickas två gånger. En partner som aldrig fick vår mottagningsbekräftelse skickar meddelandet igen med samma Message-ID (RFC 4130 avsnitt 7.5). Källan kom ihåg varje partners Message-ID under duplicate_window (standard 720h, 30 dagar; minst en timme) och svarar på en återsändning med en processed-mottagningsbekräftelse utan att skicka den vidare igen. Posten sparas i databasen, så en omstart glömmer den inte. Ett meddelande vars bearbetning misslyckades kommer inte ihåg, så partnerens omförsök går igenom. Kopior som anländer samtidigt väntar på varandra, och endast den första skickas vidare. Om posten inte kan läsas, avvisas meddelandet med unexpected-processing-error och parten försöker igen senare, snarare än att riskera en andra kopia. Ett meddelande utan Message-ID kan inte erkännas och loggas som sådant.
Samarbetsförmåga testas mot pyas2lib 1.4.3 i båda riktningarna, med Triple DES och AES-256, komprimerat och inte, signerade synkrona kvitton inkluderat.
10.21 OpenPGP
Betalare, clearinghus och statliga myndigheter tar ofta emot och skickar filer endast under OpenPGP. En pgp-block på en källa öppnar vad som anländer; en på en destination skyddar vad som lämnar. Båda är på kanalbyggaren: Öppna PGP-krypterade meddelanden under källan, Kryptera med OpenPGP på varje destination.
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}
Nyckelfiler läses relativt till kanalfilen och läses och låses upp när kanalen laddas: en saknad nyckel eller ett felaktigt lösenord stoppar kanalen där, inte på det första meddelandet.
- På en källa, öppnas hela filen, objektet, e-postbilagan eller begärans text först och sedan delas den upp i meddelanden, så en batchkrypterad fil fungerar. En som inte kan öppnas avvisas: en filkälla flyttar den till sin felkatalog, en HTTP-avsändare svarar 400 med orsaken.
require_signatureavvisar ett meddelande som inte är signerat av en avverify_with;allow_unencryptedaccepterar ett som bara är signerat;pass_plainlåter ett meddelande som inte alls är PGP passera oförändrat, för en mapp som tar emot båda. - På en destination, krypteras vad som skulle ha levererats (till någon av
encrypt_to) och signeras (medsign_with), efter varje annan steg. En fil-, SFTP-, FTP-, S3-, Azure Blob- eller GCS-destination namnger fortfarande filen från det okrypterade meddelandet, så${control_id}fungerar, och alla ramar är innanför krypteringen.armor: trueskriver.asc-text istället för binär;no_compressstänger av komprimering;file_nameär namnet som medföljer i meddelandet.
Meddelanden skrivs med AES-256 i RFC 4880-format som äldre mottagare kan läsa, och det nyare RFC 9580-formatet kan också läsas. Krypteringen är ProtonMail/go-crypto; Perfuse implementerar ingen primitiv. Kompatibilitet testas mot GnuPG i båda riktningarna: gpg dekrypterar och verifierar vad Perfuse skriver, och Perfuse öppnar och verifierar vad gpg skriver.
10.22 Leverans till en annan kanal
En kanaldestination överlämnar meddelandet till en annan kanal med namn. Mottagarkanalen behandlar det som vilket annat ankommande meddelande som helst: den sparar det, filtrerar det, omvandlar det och sprider det utåt.
Detta är det stödda sättet att bygga en kedja. Det är medvetet synligt — två kanaler, två uppsättningar statistik, två poster i meddelandehistoriken — eftersom en kedja som är dold inuti en kanal är en kedja som ingen kan övervaka.
Meddelandet överlämnas i minnet snarare än över ett nätverk, så det finns ingen ram, ingen bekräftelse och ingen tidsgräns mellan de två.
10.23 Vad som händer när processen dödas
Frågan som alla som har kört en integrationsmotor frågar först, och den som sällan besvaras, eftersom det ärliga svaret vanligtvis är pinsamt.
Det besvarades genom att döda processen med SIGKILL mitt i en batch — vilket är vad en strömavbrott, en utgång-ur-minne-död och en hypervisornivå-återställning alla ser ut som från insidan — och räknade vad som överlevde mot vad som hade utlovats.
Egenskapen som testas är inte "ingenting går förlorat". Det är inte uppnåeligt och att påstå det vore en lögn. Det är det smalare löftet som en avsändare faktiskt förlitar sig på: ett meddelande som har bekräftats är ett meddelande som har anlänt.
Med ack.when: on_delivery, som är standard, skrivs varje destination innan bekräftelsen skickas ut, så ett AA är ett uttalande om destinationen snarare än om en kö. Ett meddelande som dödas innan dess bekräftelse kan mycket väl gå förlorat, och det är korrekt: avsändaren lovades aldrig någonting och kommer att skicka det igen.
10.23.1 Bekräftelse vid leverans
Fem körningar, dödade efter 5, 25, 40, 75 och 110 meddelanden av 120.
| Bekräftade | Närvarande nedströms efteråt | Bekräftade men saknade |
|---|---|---|
| 255 | 255 | 0 |
Löftet upprätthölls vid varje dödspunkt, och ingenting duplicerades. En kopia hade varit acceptabel och en förlust skulle inte ha varit det: ett återsänt A08 är ett besvär som mottagare absorberar, och ett laboratoriebesked som tyst never anländer är en patientsäkerhetsincident.
10.23.2 Bekräftelse vid mottagande
on_receipt svarar så snart meddelandet har köats, innan någon destination har skrivits. Detta kapitel har alltid sagt att ett bekräftat meddelande fortfarande kan gå förlorat på det sättet. Här är storleken på det.
| Dödad efter | Bekräftade | Närvarande nedströms | Förlorade |
|---|---|---|---|
| 5 | 5 | 1 | 4 |
| 25 | 25 | 1 | 24 |
| 75 | 75 | 2 | 73 |
| 110 | 110 | 2 | 108 |
I princip allt som är på väg. Inställningen är inte ett fel och det finns flöden där det är rätt val, men det bör väljas med vetskap om att en krasch förkastar vad som har bekräftats och ännu inte skrivits, och att detta är nästan allt av en burst.
Ingenting återhämtas vid omstart, eftersom perfuse run inte har någon varaktig lagring. En destination som inte får förlora meddelanden under en avbrott behöver queue.enabled, som behöver databasen som perfuse serve tillhandahåller — och perfuse run vägrar nu sådan kanal snarare än att starta den utan kön.
10.23.3 En avsändare som dör halvvägs genom ett meddelande
Den farligaste av dessa fel, eftersom ett avkortat HL7-meddelande vanligtvis fortfarande parsas. Segmenten före skäret är kompletta och välbildade, så en mottagare har inget sätt att veta att PID och PV1 anlände och att OBX-segmenten som bär resultaten inte gjorde det.
En ram öppnades, sex tiondelar av ett meddelande skickades och anslutningen återställdes snarare än stängdes. Det partiella meddelandet levererades inte, lyssnaren överlevde och ett välbildat meddelande som skickades omedelbart därefter accepterades normalt, så fragmentet fördes inte in i nästa meddelande heller.
Anslutningsloggen rapporterar nu hur många byte av en ofullständig ram som övergavs, för varje felmodus och inte bara en ren stängning. Tidigare loggade en kraschad avsändare, en avslagen process och en utdragen kabel alla messages=0 och ingenting annat, vilket inte kan skilja på en tom hälsokontroll och ett laboratorieprov som slängdes bort nio tiondelar genom.
10.23.4 En full disk
Utrymmesutmatning upptäcks och loggas snarare än sväljs. Två saker om det är värda att veta.
Avsändaren får inte en omedelbar avvisning. Leveransen försöker på det vanliga schemat — en sekund, två, fyra, åtta — och den negativa bekräftelsen anländer ungefär femton sekunder senare. En avsändare vars egen tidsgräns är kortare än så ser en stilleståndskontakt snarare än ett AE, och kommer att dra slutsatsen att nätverket är felaktigt snarare än disken.
Och en volym som rapporterar noll byte ledigt fortfarande kan acceptera små tillägg under en tid, eftersom att lägga till ett par hundra byte till en fil vars sista block har utrymme behöver ingen ny tilldelning. Det första skrivfel inträffar senare än ögonblicket när disken fylldes.
10.23.5 Vad som inte testades
En destinationskatalog som förlorar skrivbehörighet. Den kunde inte injiceras med chmod: motorn håller utdatafilen öppen, och ändring av en fils läge påverkar inte en descriptor som redan har öppnats mot den. Att testa det ordentligt behöver volymen ommonterad som skrivskyddad eller borttagen under processen, vilket inte har gjorts. Den nämns här snarare än utelämnas, eftersom ett gap som ingen nämner läser som ett gap som ingen tittade på.
11 Varning
Ingenting utanför Perfuse kommer att tala om för dig att ett flöde har slutat. Avsändaren bekräftas och är nöjd; mottagaren har inget sätt att veta att ett meddelande skickades. Varning är den enda sak som står mellan ett trasigt gränssnitt och att någon märker det veckor senare.
11.1 Varningskategorierna
| Typ | Utlöses när |
|---|---|
error-rate | Fel överstiger en proportion av trafik. |
queue-depth | En kö har fler än N meddelanden i väntan. |
queue-age | Det äldsta köade meddelandet är äldre än en varaktighet. |
queue-stuck | En kö töms inte alls. |
no-traffic | Ingenting har anlänt under en fast period. |
below-rhythm | Trafiken är långt under vad den här feeden normalt gör *vid den här tiden på veckan*. |
channel-down | En kanal som ska köras körs inte. |
script-errors | Ett skript misslyckas. |
rows-quarantined | En databaskälla ställer raderna åt sidan. |
slow-delivery | Leveranser lyckas men tar för lång tid. |
contract | Ett meddelande bryter mot kanalens deklarerade kontrakt. |
phi-volume | En kanal bär flera gånger sin vanliga hastighet för timmen. |
phi-after-hours | En kanal som bara bär dagtrafik bär något på natten. |
phi-new-destination | En kanal levererar till en adress den inte har skickat till tidigare. |
phi-bulk-reads | En person läser mer än N olika patientjournaler inom en minut. |
De fyra sista övervakar åtkomst till patientdata och beskrivs nedan.
11.2 Tystnad är det svåraste att upptäcka
En kanal som har slutat ta emot data producerar inga fel. Det finns inget att räkna. Det är därför no-traffic finns, och varför det inte är tillräckligt på egen hand.
no-traffic är en fast tröskel: varna om inget har anlänt på, säg, två timmar. På en feed som aldrig blir tyst fungerar det. På en kliniklab-feed är det värdelöst — feeden är tyst varje natt och helg, så en tvåtimmes-tröskel utlöser en varning klockan 01.00 varje natt, och en tröskel som är tillräckligt lång för att överleva helgen kommer inte att märka en avbrott på tisdag morgon förrän på tisdag eftermiddag.
Det finns inget enda nummer som är båda. Det är inte ett justeringsproblem; det är att frågan "har denna feed slutat" inte kan besvaras av en konstant när feedens normala varierar med en faktor av hundra över veckan.
11.3 Rytmmedveten upptäckt
below-rhythm jämför nuvarande trafik mot vad denna kanal normalt gör i denna timme på denna veckodag.
Perfuse lär sig varje kanals vecka från dess egen inspelade historia: 168 timbucketer, måndag först så att en arbetsvecka är sammanhängande. För varje bucket håller den ett medianvärde, ett lågt och ett högt värde, en golv och hur många observationer det baseras på.
Tröskeln är en andel av normalt, som standard 0.8 (80 procent i konsolen) — varna när trafiken faller under fyra femtedelar av vad som är normalt för denna timme.
11.3.1 Median, inte medelvärde
En enda backlog-flush på fyrtio tusen meddelanden mot ett normalt tre hundra flyttar medelvärdet tillräckligt långt så att feeden kan bli helt tyst därefter utan att någonsin falla under det. Medianen påverkas inte av en extraordinär timme, vilket är exakt den egenskap som behövs.
11.3.2 Golvet är en percentil, inte minimum
Om en kanals rytm är tillräckligt tillförlitlig för att varna på beslutas av dess låga ände, inte dess höga ände. En varning för underskott utlöses när trafiken är *låg*, så endast den låga ändan kan säga om den kommer att producera falska positiva. En tidig version av detta jämförde det höga mot medianen och fick det fel i båda riktningarna samtidigt: den diskvalificerade en perfekt stabil feed för en månad efter en backlog och godkände en genuint oregelbunden feed som svängde mellan två och nio hundra meddelanden i samma timme eftersom dess höga var bara tre gånger dess median.
Golvet är den tjugonde percentilen snarare än minimum, eftersom minimum dras till noll av en enda bankhelg. Och percentilen är inte interpolerad — varje nummer i en varning klockan 02.00 på morgonen bör vara ett antal som feeden faktiskt producerade, inte en genomsnitt av två antal som den inte gjorde.
11.3.3 Den kommer att säga när den inte kan avgöra
En kanal med ingen historia alls utelämnas helt snarare än behandlas som en som har slutat. En ny kanal får inte se ut som en trasig.
Där historien är för tunn eller för oregelbunden för att stödja en bedömning, avstår regeln från att utlösa snarare än gissar. "Jag kan inte ärligt säga" är ett första-klass-svar här, och det föredras framför en varning som är rätt något oftare än chans.
11.4 Konfigurera varningar
Från gränssnittet, under Alerts, per kanal eller över alla. Varje regel har en typ, en tröskel och var varningen ska skickas. Reglerna sparas till alerts.yaml bredvid databasen (eller den fil -alerts namnger) och träder i kraft omedelbart; tills den första sparningen tillämpas de inbyggda reglerna. Filen kan också redigeras för hand: ändringen hämtas inom trettio sekunder, och en fil som inte längre kan laddas rapporteras i loggen och de regler som gäller behålls.
Värt att göra innan en feed går live snarare än efter det första incidenten. Den specifika uppsättning som är värd att ha på någon klinisk feed:
below-rhythm— feeden har blivit tyst när den inte borde vara tyst.error-rate— meddelanden anländer och misslyckas.queue-age— något är fastnat snarare än bara upptaget.channel-down— kanalen körs inte alls.
Den första är den som fångar felet som ingen annan kommer att rapportera.
11.5 Övervakning av åtkomst till patientdata
Ett brott mot sekretessen tillkännager sig sällan. Det ser ut som en feed som bär mer än vanligt, trafik klockan tre på morgonen på en kanal som bara fungerar kontorstid, en destination som ingen ställt in, eller en person som öppnar patient efter patient. Perfuse övervakar de fyra, på som standard (serve -watch-access=false stänger av det), och rapporterar vad den ser genom varningsreglerna ovan, så det är konfigurerat, bekräftat och levererat som vilken annan varning som helst.
- Bursts (
phi-volume). Varje kanals hastighet jämförs med dess egen historia vid samma tid på dagen, så en hektisk morgon är inget nytt. Tröskeln är ett multiplum av den vanliga hastigheten, tre som standard. En burst är vanligtvis en kö som släpps efter en avbrott, och det är också vad det ser ut som när poster extraheras genom en feed. - Natttrafik på en dagkanal (
phi-after-hours). En kanal räknas som dagtid endast när mindre än 2 procent av vad den har transporterat har fallit utanför 07:00 till 19:00, i serverns tidszon. - En ny destination (
phi-new-destination). Adressen är vad destinationen namnger: en värd och port, en URL, en mapp. Att byta namn på en destination är inget nytt; att peka en på en ny värd är det. De adresser som varje kanal har skickat till sparas iaccess-watch.jsonbredvid databasen, så en destination som ändrades medan servern var nere rapporteras fortfarande. - Bulk-läsningar (
phi-bulk-reads). Räknas från revisions-spåret: meddelanden öppnade, patienter sökta eller tittade på (PDQm, PIXm, identitetssökning), dokument och bilder lästa (XDS, MHD, DICOMweb), tidigare auktorisationer lästa, sammanfattningar och vyer körda. Att läsa samma post igen räknas inte två gånger. Tröskeln är hur många olika poster per minut, tio som standard, av ett konto från en adress.
Ingenting bedöms för en kanal förrän den har transporterat 200 meddelanden, eftersom "ovanligt" inte betyder något utan ett mönster. Mönstret lärdes från de senaste två veckornas meddelande-lagring när servern startar, så en omstart gör inte varje kanal ny igen. Allt som ses hålls i femton minuter, sedan rensas varningen.
Den tittar bara och rapporterar. Den håller aldrig upp ett meddelande eller vägrar en läsning: detta är heuristiker, och en feed som stoppas för att en gissning var fel är ett kliniskt problem. Varje varning säger vad som sågs och vad det kan vara oskyldigt, eftersom de flesta av dem kommer att vara oskyldiga.
Administratörer ser vad övervakaren har lärt sig på skärmen Varningar, under Övervakning av åtkomst till patientdata: varje kanals mönster (fortfarande lär, endast dagtid eller dag och natt), hur många destinationer den känner till och allt som setts under de senaste femton minuterna, inklusive vad som ligger under en regels tröskel.
11.6 Var varningar skickas
Aviseringar kan skickas som JSON till en webhook (-alert-webhook: Slack, Teams, Mattermost, PagerDuty, Alertmanager eller allt som accepterar en POST), skickas som SNMPv2-fällor till SNMP-chefer (-snmp-traps, se SNMP), eller skrivas till loggen för en insamlare att plocka upp. Det finns ingen e-postleverans i sig: peka webhooken mot en relä om aviseringar måste anlända som e-post.
En varning som bara skrivs till en logg som ingen läser är inte en varning. Om Perfuse är det enda som kommer att märka en stoppad feed, måste varningen nå en person.
12 Meddelandelagret
Varje meddelande som Perfuse tar emot spelas in, så som det mottogs, innan något modifierar det. Detsamma gäller för vad som skickades till varje destination och vad som hände med det. Lagret är en SQLite-fil som anges av -db.
12.1 Vad som sparas
Per meddelande: de råa bytearna som de anlände, när de anlände, vilken kanal, den parsade meddelandetypen och triggerhändelsen, samt filterresultatet.
Per destination per meddelande: de byte som skickades, resultatet, den tid som togs, och eventuella fel eller negativa bekräftelser som mottogs.
Detta är den form en utredning behöver. "Vad skickade de till oss", "vad skickade vi till dem" och "vad sa de om det" är tre olika frågor och var och en av dem ställs.
12.2 Sökning
Efter kanal, tidsspann, resultat, meddelandetyp och triggerhändelse, samt efter fältvärde.
Feltsökning fungerar på det parsade meddelandet, så att sökning efter en journalnummer hittar det oavsett var i meddelandet som fältet finns, snarare än att matcha siffrorna var som helst i texten. En textsökning efter 12345 i ett meddelande som innehåller en mängd 12345 hittar ett meddelande som inte har något att göra med den patient du letar efter.
12.3 Uppspelning och ombehandling
Eftersom originalet sparas, kan ett meddelande köras igenom den aktuella konfigurationen.
Spår tar ett inspelat meddelande och visar vad kanalen skulle göra med det nu, utan att skicka någonting. Beskrivs i felsökning.
Ombehandla kör det faktiskt igen, inklusive leverans. Detta är vad som åtgärdar en batch med meddelanden som misslyckades på grund av att en destination var felkonfigurerad: korrigera konfigurationen, markera de påverkade meddelandena, ombehandla.
12.4 Föråldring
En spårning av ett gammalt meddelande mot den aktuella konfigurationen besvarar en hypotetisk fråga: vad *skulle* hända nu. Det är vanligtvis vad du vill ha, men inte alltid — om du utreder vad som gick fel förra tisdagen, kan kanalen ha ändrats sedan.
Perfuse upptäcker detta och säger till. En spårning av ett meddelande som anlände innan kanalen senast redigerades markeras som sådan, så att svaret inte förväxlas med en rekonstruktion av vad som faktiskt hände.
12.5 Kvarhållning
Lagret växer. cleanup.periodDays kontrollerar hur länge meddelanden sparas.
Två saker att väga. Kliniska meddelanden kan omfattas av kvarhållningskrav som är längre än vad du skulle välja av operativa skäl, och lagret är inte systemet för registrering — mottagarsystemet är. Perfuses kopia finns för att diagnostisera och ombehandla, och båda dessa behov avtar skarpt efter några veckor.
Kvarhållning bestämmer också hur mycket historia rytmiklärande har att arbeta med. Se alerting: ett kvarhållningsfönster som är kortare än några veckor gör det omöjligt att skilja på en tyst söndag och en avstannad feed.
12.6 Lagret innehåller kliniska data
Detta är den del av Perfuse som innehåller patientinformation, och den bör behandlas som sådan: lagras krypterat, säkerhetskopieras som kliniska data och har åtkomstkontroll. Se säkerhet.
De genererade testmeddelanden som beskrivs i testing finns delvis så att dessa data inte behöver lämna miljön för att reproducera ett problem på annan plats.
13 Felsökning
Frågan är nästan alltid densamma: det här meddelandet kom in, något gick fel ut, var ändrades det? Perfuse svarar på det genom att spela upp ett inspelat meddelande genom den aktuella konfigurationen och visa varje steg.
Ingenting skickas medan spårning pågår. Kanalen fortsätter att köra opåverkad och ingen omdistribution behövs.
13.1 Spåra ett meddelande
Välj vilket inspelat meddelande som helst och spåra det. Resultatet visas i ordning:
- Vad filtret läste. Vilka fält det tittade på och vilka värden den hittade. En filter som avvisar allt läser vanligtvis en sökväg som inte finns i den här feeden, och detta namnger den.
- Varje transformation. Vad den ändrade, från vad till vad.
- Vad varje destination beslutade. Om den skulle acceptera meddelandet och varför inte om den inte skulle.
- Utmatningen. Meddelandet som varje destination skulle skicka det.
13.2 Steg för steg
Stegvis vy kör varje transformation för sig och skapar en ögonblicksbild av hela meddelandet efteråt. En numrerad järnväg av steg, färgad efter vad som hände, och meddelandet som det såg ut vid varje punkt.
Hela meddelandet snarare än bara ändringen, eftersom ändringen ofta inte är där problemet är — ett steg som korrekt modifierade fältet det var riktat mot, på ett meddelande där ett tidigare steg redan hade lagt fel sak där, ser perfekt korrekt ut i isolering.
13.3 Fyra resultat, och den distinktion som betyder något
| Resultat | Betydelse |
|---|---|
changed | Steget kördes och modifierade meddelandet. |
no-effect | Steget kördes, och meddelandet är oförändrat. |
skipped | Stegets when-villkor var falskt, så det kördes inte. |
failed | Steget felade. |
no-effect och skipped rapporteras separat, och detta är poängen med hela funktionen.
Från utsidan är de identiska: meddelandet är detsamma efteråt oavsett. De betyder motsatta saker. skipped betyder att villkoret fungerade som det var skrivet och att detta meddelande inte var en av dem det tillämpades på — vanligtvis korrekt. no-effect betyder att steget kördes och inte hittade något att göra, vilket vanligtvis betyder att det är riktat mot ett fält som inte finns.
En motor som rapporterar båda som "ingenting hände" lämnar dig oförmögen att skilja på en fungerande villkor och en trasig sökväg, och det är den vanligaste transformationsbugen där är.
no-effect för varje meddelande är nästan alltid en felaktig väg. Steg-genom-gång-räknaren visar hur många steg som inte hittade någonting, vilket är det snabbaste sättet att upptäcka det: en kanal med tre steg och tre no-effect-resultat omvandlar ingenting alls.13.4 Testa en ändring innan du sparar den
Byggaren kan köra en kandidatkonfiguration mot inspelad trafik och rapportera vad som skulle skilja sig. Detta är det säkraste sättet att ändra en live-kanal: gör redigeringen, se vad den gör med de senaste få hundra riktiga meddelandena, sedan spara.
Det är också hur man tar reda på att en ändring som ser uppenbarligen korrekt påverkar meddelanden man inte hade tänkt på — ett steg som är villkorat av en utlösande händelse, på en feed som visar sig bära fyra.
13.5 Vad spårning inte kan berätta
Den kör den aktuella konfigurationen. Om kanalen har redigerats sedan meddelandet anlände, är spårningen en hypotetisk snarare än en rekonstruktion, och Perfuse markerar den som sådan snarare än att låta distinktionen passera tyst.
Den övar inte heller transporten. En spårning visar vad som skulle skickas, inte om destinationen skulle acceptera det — ett meddelande som är korrekt och en destination som vägrar anslutningar producerar en ren spårning och en misslyckad leverans. Dessa är synliga i leveransposten istället.
13.6 Skript
Ett skript är ett ogenomskinligt steg i spårningen. Perfuse kan visa vad som gick in och vad som kom ut, och kan inte visa vad som hände däremellan eller vilka fält som lästes.
Detta är den konkreta kostnaden för att använda ett skript snarare än deklarativa steg, och det är värt att väga när man väljer. Se transformation.
14 Testning
Standardråd för testning av ett gränssnitt är att bygga exempelmeddelanden som återspeglar er egen miljö — er laboratoriets koder, er fallblandning, er avsändares vanor — och att ta bort patientdata för hand. Det är långsamt, och att göra det ofullständigt är det normala resultatet.
Perfuse erbjuder tre saker istället: genererad trafik som matchar en feeds form utan dess innehåll, en kanal föreslagen från ett exempel någon skickade er, och en jämförelse mot motorn ni ersätter.
14.1 Genererad testtrafik
Om en kanal har hanterat meddelanden kan Perfuse producera fler meddelanden som liknar dem.
Vad som är troget:
- Utlösa händelser i de proportioner som verkligen observerats, med minst en av varje så att en sällsynt händelse fortfarande visas.
- Fält fylls i de hastigheter de verkligen är — så fallet där ett fält är *frånvarande* testas, vilket är fallet som bryter saker.
- Upprepningar där upprepningar förekommer, sammansatt struktur där den förekommer.
- Koder dras från de kodtabeller som verkligen ses.
Vad som inte är troget, och detta anges snarare än antyds: klinisk samstämmighet. En genererad patient har ett orelaterat journalnummer, en namnformad sträng och en diagnos utan relation till observationen. Dessa meddelanden övar en gränssnitt. De är inte en klinisk testuppsättning och kan inte användas för att validera klinisk logik.
14.1.1 Varför den innehåller ingen riktiga data
Argumentet är strukturellt snarare än ett påstående om ansträngning. Generatorns enda indata är kanalens trafik profil, och en profil innehåller fyllningshastigheter, former, längder, upprepningstäler och segmentfrekvenser. Den innehåller inga värden.
Det enda undantaget är kodtabellsfält, och en kod identifierar ingen.
Detta är en starkare garanti än att avidentifiera riktiga meddelanden, vilket är en process som kan göras ofullständigt och vanligtvis är. Här finns ingen väg genom vilken ett namn kunde nå utdata, eftersom namnet aldrig var i indatan.
Varje genererat meddelande parsas innan det returneras — ett oparsbart korpus skulle skicka någon på jakt efter en bugg i deras gränssnitt som i själva verket är en bugg i generatorn — och var och en markeras T i MSH-11, med en medvetet syntetisk avsändarapplikation och anläggning.
T:et och den syntetiska avsändaren är inte kosmetiska.14.2 Bygga en kanal från ett exempel
Klistra in meddelandet ett laboratorium, sjukhus eller leverantör mejlade dig och Perfuse föreslår en kanal för det. Ingenting behöver köras först.
Den hanterar vad människor faktiskt klistrar in: flera meddelanden i en block, vilken radavslutning som helst, MLLP-ramning som överlevde kopieringen och den täckande notisen ovanför meddelandet. Att vägra ett exempel för att det anlände med Windows-radavslutningar skulle vara ett hinder snarare än en kontroll.
14.2.1 Tre listor
Förslaget kommer med vad exemplet visar, vad som har gissats och vad exemplet inte kan berätta — tre separata listor, viktade lika i gränssnittet.
De är separata eftersom en läsare som inte kan se vilken som är vilken måste verifiera allt eller lita på allt, och båda är sämre än att veta var man ska titta.
Från ett enda meddelande är gränserna namngivna specifikt snarare än allmänt: vilka fält som är valfria, vilka segment upprepas, vilka koder existerar utöver de som finns här, om avsändaren någonsin skickar en annan utlösande händelse. En allmän varning är en varning som människor skummar.
Förtroende är ett ord — lågt, måttligt, rimligt — aldrig en procent. En procent antyder en beräkning, och detta är en bedömning av hur många exempel det finns.
Z-segment kallas ut med namn, eftersom ett lokalt segment är den sak som ingen specifikation nämner och den vanligaste orsaken till att en kanal byggd från en standardmall inte fungerar.
14.2.2 Separatorvarningen
Om exemplet fältseparator inte är den vanliga |, visas det först, och förtroendet sjunker till lågt.
Orsaken är ett äkta tyst fel. HL7 tar sin fältseparator från meddelandet självt, så ett exempel vars rör har ersatts av typografiska likheter — vilket är vad ett ordbehandlingsprogram gör — parsar perfekt till fält som alla är fel. Ingenting felar någonstans.
Att vägra ett sådant exempel skulle vara fel, eftersom en avsändare kan legitimt använda en annan separator. Så det markeras, tecknet namnges och att begära en vanlig textbilaga föreslås.
14.3 Jämföra mot den gamla motorn
Innan en live-feed flyttas uppstår frågan om Perfuse producerar samma utdata som det som har kört i åratal. Inga mängder designkvalitet kan besvara det. Se migration.
14.4 Verifiering mot den riktiga saken, i containrar
Tre kontroller körs mot riktiga implementationer snarare än mot Perfuse egna idé om ett protokoll. De lever utanför make check eftersom de behöver en container-runtime, och en kontroll som behöver Docker är en kontroll som människor slutar köra.
scripts/interop-up.sh startar alla och skriver ut vad var och en låser upp.
| Container | Kontroller | Vad den hittade |
|---|---|---|
| Keycloak 26 | web/e2e-saml/, och internal/saml-fixtures | En defekt. Den kanoniska formen en signatur täcker beräknades med namnutrymmesprefix borttagna, så ingen riktig identitetsleverantör kunde någonsin ha signerat in någon |
| Microsoft Entra | internal/saml live-tester och fixtures | Två defekter, båda i vad som omger protokollet. Ett konto skapades under Entras opaka NameID, eftersom den läsbara-namnlogiken ville ha ett e-postkrav och Entra skickar inget. Och ett SAML-konto registrerades som OIDC, eftersom lagret härledde protokollet från en utgivare som ser identisk ut för båda |
| HAPI FHIR | go test ./internal/engine/ -run HAPI | En defekt. En omappad tilldelningsmyndighet producerade en identifieringssystem som tillkännagav ett OID och bar ett ord, som HAPI accepterade utan klagomål |
| ActiveMQ | go test ./internal/engine/ -run RealBroker | Korrekt, inklusive det null-byte-ram-fallet. Påstått genom brokerens egen hanteringsgränssnitt snarare än genom en funktion som returnerar nil |
| nginx, klientcertifikat | go test ./internal/engine/ -run ClientCertificate | Korrekt |
| Orthanc (en riktig PACS) | go test ./internal/engine/ -run RealPACS | Korrekt. En C-STORE anländer och patientens namn, identifierare, studie datum, modalitet och SOP-klass alla överlever |
| PostgreSQL | go test ./internal/engine/ -run RealPostgres | Korrekt, och det utlöste ett bättre fel: ett uttalande i felaktig dialektens platshållare avvisas nu när det sparas snarare än att bli ett syntaxfel på servern när ett meddelande anländer |
| OpenSSH sftp-server | go test ./internal/engine/ -run OpenSSHServer | Korrekt. De befintliga SFTP-testerna använder samma Go-bibliotek på båda sidor; OpenSSH är en annan implementation och den som finns på den andra änden av nästan varje riktig feed |
| Mirth 4.5.2 | go test ./internal/mirth/ -run RealMirth | Korrekt nu. Den enda fixturen som användes var skriven för hand och Mirth skulle inte ladda den; scripts/mirth-author-channel.sh har Mirth skapa en istället, och Perfuse läser den |
Var och en hoppar över snarare än misslyckas när dess container är frånvarande, så make check passerar på en maskin med ingen Docker.
Varför detta är separat från resten av sviten. Varje annan test av dessa funktioner hade båda halvorna skrivna här: ett dokument som denna kodbas signeras, läst tillbaka av den kod som signeras. Det är överensstämmelse med sig själv, och det är värt mindre än det verkar.
SAML-kanoniseraren är fallet som bevisar poängen. Den bar tusen rader med tester, fem av dem specifikt om kanonisering, och alla passerade medan ingen riktig identitetsleverantör kunde någonsin ha signerat in någon — den kanoniska formen som en signatur täcker beräknades med namnutrymmesprefix borttagna, och det enda sättet att hitta det var att handla över ett dokument Perfuse inte hade skrivit.
Två av de åtta kontrollerna hittade defekter uttryckligen, och en tredje utlöste en riktig förbättring. Tre hittade ingenting fel. Den förhållningen är argumentet för att behålla alla: en kontroll som passerar har berättat något du inte kunde ha vetat annars, och det fanns inget sätt att veta i förväg vilka de skulle vara.
Ett mönster värt att namnge, eftersom det visade sig i båda defekterna: acceptans är inte verifiering. HAPI accepterade det felaktiga identifieringssystemet och lagrade det; defekten visade sig bara när resursen lästes tillbaka. En mottagare som tolererar något är inte bevis för att det är rätt, bara att denna mottagare var generös.
Två infångade påståenden är begångna, på internal/saml/testdata/keycloak-assertion.xml och entra-response.xml, med tester över båda — så att den specifika regressionen fångas utan en container.
Båda behövs snarare än att en är reserv. Keycloak prefixerar sin assertion och signatur, Entra gör inte det, och de är de två motsatta fallen i kanonisering — vilket är exakt där defekten var. En test påstår att varje dokument fortfarande täcker sitt eget fall, eftersom en ersättning som infångats som råkade vara prefixerad skulle tyst halvera täckningen utan att misslyckas något. Den allmänna lärdomen generaliserar inte så billigt: för allt annat är containern kontrollen.
14.5 Diagnostisera ett test som misslyckas en gång och aldrig igen
Ett test som misslyckas i en fullständig körning och passerar ensam sexton gånger är inte ett fläkttest. Det är ett test som delade något med körningen, och sättet att ta reda på vad är att mäta det delade snarare än testet.
Två instrument finns för detta, och båda är avsedda att köras bredvid en fullständig svit:
./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
Var och en upptäcker körningens portar från setupens egen tillståndsfil och provar var 500 millisekund tills servern avslutas. De loggar varje prov snarare än bara fel, vilket är vad som gör dem användbara: en blip visas i en körning där ingenting misslyckades, så ett fel som visas en gång i tre körningar blir mätbart på var och en.
Ställ PERFUSE_E2E_KEEP=1 för att behålla den tillfälliga katalogen, som innehåller databasen som den lämnades och serverloggen för hela körningen. Serverloggen är vanligtvis svaret. I ett undersökt fall spelade den in att en kanal stannade och dess lyssnare återanslöts 421 millisekunder senare, och provets ena vägrade anslutning föll inom det fönstret.
Läs spåret i stället för error-context.md, som har varit tomt mer än en gång där spåret innehöll det riktiga meddelandet.
Kopiera artefakterna ut innan du kör något igen. Ett lyckat test rensar test-results, så spåret för felet du undersöker försvinner i samma ögonblick du försöker reproducera det. När det väl är förlorat kan frågan det skulle ha besvarat inte besvaras.
Stoppa interop-containrarna först. Stoppa dem innan en fullständig webbläsarkörning och starta dem med ./scripts/interop-up.sh efteråt om du fortfarande behöver dem.
Åtta containrar använder cirka 9,8 GB minne, och på en maskin utan mycket mer än så finns det för lite kvar för Chromes processer, node och Go-verktygskedjan tillsammans. Vad det producerar är inte ett minnesfel, utan en renderare som slutar schemaläggas: en inspelad spårning visar ett 60,2 sekunders glapp utan några ramar alls, under vilken Playwright väntade på att en knapp skulle bli "synlig, aktiverad och stabil" och inte kunde få två på varandra följande animationsramar att jämföra. Servern var frisk under hela tiden, den långsammaste begäran under hela körningen var 154 millisekunder.
Det felet ser ut som ett fel i vilket test som råkade köras. Det är värt att veta dess form: varje begäran snabb, sidan visuellt frusen, återförsöksloopen nådde aldrig en andra iteration, och hela testet passerade i isolering.
Endast en körning i taget. Sviten delar en server, en inloggad session i web/e2e/.auth/admin.json och en tillståndsfil som namnger serverns process. Ingen av dessa är per körning, så en andra körning som startar medan den första pågår skriver över tillståndsfilen, och vilken nedbrytning som helst dödar den andra körningens server och tar bort dess session.
Vad det ser ut som är ingenting likt orsaken. Det producerade en serie på 279 fel vars första meddelande var ENOENT: no such file or directory, open './e2e/.auth/admin.json', en serie som avbröts i förtid och rapporterade 217 godkända, och två tester som misslyckades med bind: address already in use — ingenting av detta antyder att två körningar kämpar. Sviten tar nu en lås och vägrar att starta, och namnger processen som håller den. En lås som lämnats av en avbruten körning tas över i stället för att blockeras för alltid, eftersom en säkerhetsåtgärd som blockerar sviten är något som någon raderar tillsammans med säkerheten.
En relaterad fälla, nu åtgärdad: två specifikationer namngav sina lyssnarportar direkt, så en server som lämnades kvar av en avbruten körning gjorde att de misslyckades med något de inte hade något att göra med. Portar begärs nu av operativsystemet.
Besvara inte något av detta med återförsök. Ett test som passerar på andra försöket hittade ett riktigt lopp och dolde det, och playwright.config.ts ställer in retries: 0 av den anledningen.
En varning: att sampla var 100:e millisekund spawnaade tjugo processer per sekund, sträckte en körning med en halv gång, och misslyckades med två tester på tidsgränser som inte hade något fel med dem. Ett instrument som förändrar vad det mäter producerar fynd om sig själv.
14.6 Vad som fortfarande behöver riktig infrastruktur
Flera delar av Perfuse är implementerade och har aldrig testats mot den riktiga saken. De listas här i stället för att upptäckas:
- SMB mot en riktig Windows-delning — protokollkoden är komplett och testad för sökvägsäkerhet och argumenthantering, men inget test öppnar en socket till en domänansluten server.
- En riktig serieport.
- Mirth-importören mot XML som en riktig Mirth producerade. Testad mot Mirth 4.5.2 i en container, och fyndet var om detta repository: den enda migrationsfixturen som skrevs här för hand och Mirth kommer inte att ladda den — den lagrar kanalen som ogiltig och kastar varje anslutning. Vad som avgjordes är att
version-attributen som riktig Mirth skriver på varje element tolkas till samma kanal, så de är inte en fara; vad som inte är avgjort är allt annat som en riktig export innehåller. - SAML mot en värd kommersiell identitetsleverantör. Keycloak är verifierad; en leverantör bevisar att en implementering matchar en leverantör.
- En NCPDP-anspråk via en riktig apoteksväxel.
- Ett SCRIPT-meddelande via Surescripts, där certifiering är en kommersiell process snarare än en teknisk.
Funktionerna i det här kapitlet och nästa finns så att du kan samla in dina egna bevis snarare än att ta någon annans ord.
14.7 Mätt mot offentliga konformitetskorpus
En testsvit vars fixture skrevs här bevisar överensstämmelse med sig själv. Detta är andras data.
14.7.1 FHIR R4, specifikationens egna exempel
Alla 2 912 exempelfiler som publicerats med FHIR R4-specifikationen — varje exempel som standardförfattarna skrev.
| Resultat | Antal |
|---|---|
| Resurser validerade med inga fynd | 13 723 |
| Resurser som rapporterats ogiltiga | 0 |
| Filer som vägrats som en oimplementerad resurstyp | 753 |
| Bundle-inträden som hoppades över som en oimplementerad typ | 1 348 |
Inget resursvaliderades felaktigt. Varje fel är ett uttryckligt avslag som namnger typen som inte kan läsas — 672 ValueSet, 80 ConceptMap och en Parameters. En validerare som tyst passerar vad den inte förstår är värre än en som säger det.
Korpusen hittade ett fel, vilket är anledningen till att den körs. Validering av en samling skrev ut "Validering av en samling från en fil stöds ännu inte" och fortsatte. Det var falskt i båda riktningarna: samlingar vars poster råkade vara typer som parsaren kunde hantera validerades redan, och en samling som verkligen var ogiltig producerade samma rad, räknade ingenting och avslutades noll — inklusive under -strict, som finns så att detta kan blockera en byggnation. Fyrtiotvå av specifikationens egna samlingar hoppades över.
Buntar valideras nu post för post, med tre resultat som hålls isär: en post som är felaktig misslyckas och namnger fältet, en post av en typ som den här versionen inte kan läsa räknas som hoppad över och rapporteras, och en bunt som bär inga resurskroppar är varken. Samma korpus gick från 2 100 resurser kontrollerade till 13 723.
14.7.2 HL7 v2, HAPI-testkorpusen
Meddelandefixturerna från HAPI, den referensjava-HL7 v2-implementeringen — medvetet besvärligt material, inklusive uuencoderade nyttolaster, flyktiga avgränsare och upprepningsgrupper.
59 meddelanden, 59 parsade, ingenting vägrade. Sju meddelandetyper i en korpus som varje enskild system skulle beskriva som en sak, vilket är poängen med att perfuse profile finns till för att göra.
14.7.3 Vad som inte har körts
DICOM mot ett offentligt konformitetsschema och X12 mot en publicerad korpus. Ingen av dem har utförts och ingen av dem bör antas från de två ovan.
15 Migration från Mirth
Två saker behövs för att ersätta en fungerande motor: kanalerna måste komma över, och någon måste kunna visa att ersättningen producerar samma utdata. Perfuse gör det första genom att importera Mirths egna exporter, och det andra genom att jämföra de två motorerna med er egen trafik.
Allt i detta kapitel gäller lika för Open Integration Engine och BridgeLink. Mirth Connect upphörde att vara öppen källkod vid version 4.6 i mars 2025; OIE (värd av Eclipse Foundation) och BridgeLink (Innovar Healthcare) är grenarna som fortsätter den öppna källkodsraden, och båda skriver samma exportformat. Importören testas mot alla tre, nedan.
15.1 Import av kanaler
Perfuse läser varje export som dessa motorer skriver:
| Exportera | Från Administratören | Vad som överförs |
|---|---|---|
| En kanal | Exportera Kanal | Kanalen |
| En kanalgrupp | Exportera Grupp | Varje kanal i den, var och en behåller gruppen |
| Kodmallar | Exportera Kodmallar | Varje bibliotek som en skriptfil |
| En server-säkerhetskopia | Säkerhetskopiera Konfiguration, eller GET /api/server/configuration | Allt ovan på en gång |
Peka perfuse translate på någon av dem, eller släpp en på Administrera → Migrera:
perfuse translate -o ./channels server-backup.xml
En kodmallbibliotek blir lib/<library>.js bredvid kanalerna, och varje kanal som Mirth hade biblioteket aktiverat för får scripts.include: [lib/<library>.js] — så en transformer som anropar en lokal funktion som formatMRN() fortfarande hittar den. En kanal som biblioteket inte var aktiverat för inkluderar det inte, eftersom dess skript inte kunde se det i Mirth heller. Dra-och-släpp-exempel lämnas utanför: Mirth klistrar bara in dem i ett steg för hand, så de är inte kod som körs på egen hand. I webbläsaren sparar import av en kanal först de bibliotek den inkluderar.
En Kanal Skrivare namnger kanalen den levererar till med id. I en grupp eller en säkerhetskopia är målet i samma dokument, så det blir en channel-destination som namnger den kanalen; från en enkanalsexport rapporteras det för att du ska fylla i det. Serveromfattande globala skript har ingen motsvarighet i Perfuse och rapporteras snarare än att släppas.
Rapporten säger, per kanal, om den översattes renligt, översattes med varningar eller inte kunde läsas.
Rubriken är en bråkdel med dess nämnare — "37 av 40 redo" — eftersom "37 redo" inte säger någonting om vad du fortfarande måste göra.
En kanal som inte kunde läsas är ett annat problem än en som inte kunde översättas. Det första betyder att XML själv inte parsades och är vanligtvis en avklippt eller ofullständig export; det andra betyder att kanalens innehåll har någonting utan en motsvarighet i Perfuse. Importen separerar dem.
15.2 Vad som översätts och vad som behöver ett beslut
Källor, destinationer, filter och de vanliga transformeringsstegen översätts direkt. De anslutningar som översätts: TCP/MLLP (och rå TCP med dess ramverk), HTTP, fil, databas, JavaScript, DICOM, webbtjänst (SOAP), SMTP och kanalläsare/skrivare. JMS och dokumentsskrivaren översätts inte och rapporteras som blockeringar.
En mappningssteg som ställer in en variabel placerar den i kartan som dess omfång namnger — channelMap som standard — exakt som Mirth gör, så att senare steg som läser den med $('name') hittar den.
JavaScript-transformatorer gör det inte i allmänhet. Mirth-kanaler innehåller ofta betydande kod i en transformer, och det finns ingen automatisk omvandling från godtycklig JavaScript till deklarativa steg. Importören rapporterar dessa snarare än att försöka en översättning som kan vara subtilt fel: en feltolkad transformer är värre än en som flaggas för en människa, eftersom den kommer att köras.
Där ett skript verkligen måste förbli ett skript kan Perfuse köra det — se scripts-nyckeln i kanalreferensen — till priset av den stegnivåbaserade spårningen som beskrivs i felsökning.
15.3 Vad importören har testats mot
Fem motorer, var och en som skapar sina egna dokument: Mirth 4.5.2, OIE 4.5.2, 4.6.0 och 4.7.0, och BridgeLink 26.9.0. scripts/mirth-engine-corpus.sh sammanställer ett litet program mot varje motors egna jar-filer och har sin egen serialiserare som skriver tre vanliga kanaler — en MLLP-matare med en mappare, ett skript som anropar en kodmallbibliotek och ett filter; en HTTP-matare till en databas; en filhämtning ut över MLLP — plus biblioteket och en kanalgrupp. Den laddar dem in i den körande motorn och laddar ner motorns egen serverbackup. Resultaten är incheckade under internal/mirth/testdata/engines/, och testsviten håller importören till var och en av dem på varje bygge: varje backup läses, översätts, laddas och ADT-kanalen körs med två meddelanden för att kontrollera att biblioteket fyller i postnumret och filtret släpper resultatet.
Perfuses egna exporter går åt andra hållet — Perfuse-kanaler importerade till varje körande motor och kontrolleras så att motorn inte lagrar dem som ogiltiga. Alla fem accepterar varje transport som Perfuse exporterar. Open Integration Engine 4.7.0 lade till två HTTP-inställningar utan motsvarighet här: en HTTP-avsändare bunden till en vald lokal adress rapporteras som en varning, och en HTTP-lyssnare-begäran-gräns endast när den är över den 1 MB som Perfuse accepterar.
Det första löpningen mot denna korpus hittade fyra defekter, alla åtgärdade: översättaren vägrade HTTP- och filkällor som "endast MLLP stöds" långt efter att Perfuse hade båda; den läste en HTTP-avsändares adress från ett fält som ingen av motorerna skriver; den översatte Mirths socketbuffertstorlek som en 64 KB-meddelandegräns; och en mappares variabel blev en JavaScript-global som $('mrn') aldrig såg, så biblioteket fyllde i en tom sträng.
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.
Att skriva en för hand var aldrig meningsfullt, och orsaken är värd att veta om du producerar exporter av din egen. Mirths serialiserare ignorerar element som den inte känner till, så ett felaktigt elementnamn producerar inget fel alls — anslutningen är helt enkelt inte där efteråt. Det finns ingenting att läsa och ingenting att korrigera mot.
scripts/mirth-author-channel.sh bygger en med hjälp av Mirths egna modellklasser och sin egen serialiserare, och postar den sedan till en körande server och misslyckas om servern avvisar den. Perfuses importör läser resultatet: namn, källtransport och destinationer alla överlever.
15.4 Bevisa att den matchar
Detta är den del som bestämmer om en migration sker, och den behöver bevis snarare än förtroende.
Perfuse jämför sin egen utdata mot den gamla motorens, meddelande för meddelande, på din trafik. Vad den behöver är par: meddelandet som det anlände, och meddelandet som den gamla motorn producerade från det. Båda finns i Mirths egna meddelandelagringsplats och kan exporteras från dess meddelandebrowser.
15.4.1 Fyra siffror, inte en godkännandegrad
| Resultat | Betydelse |
|---|---|
| Identisk | Byte för byte samma. |
| Kosmetiskt endast | Skiljer sig på sätt som inte bär någon information — efterföljande tomma fält, en slutlig avslutare. |
| Skiljer sig | Ett fälts värde är annorlunda. |
| Kunde inte köras | Perfuse kunde inte bearbeta meddelandet alls. |
De är fyra siffror eftersom de betyder fyra olika saker och att kollapsa dem döljer de som behöver ett beslut.
Identisk betyder byte för byte, inte ekvivalent. En svagare test skulle låta skillnader i segmentordning eller efterföljande separatorer passera, och det är exakt vad ett krävande nedströmsystem avvisar.
Kosmetiska skillnader räknas separat snarare än veckas in i den goda kolumnen. De bär verkligen ingen information, så att behandla dem som fel skulle begrava riktiga fynd under tusentals ingenting — men de är inte identiska heller, och en mottagare som gör sin egen strikta parsing kan vara oense.
"Kunde inte köras" är separat från "skiljer sig" eftersom det vanligtvis är ett konfigurationsgap som importören inte kunde fylla, inte ett mappningsbeslut. Om allt är i den kolumnen, säger utlåtandet det och ber dig att titta på konfigurationen innan du läser något annat.
15.4.2 Skillnader grupperas efter fält
Ett löpande över femtiotusen meddelanden som rapporterar fyrtusen skillnader har berättat ingenting du kan agera på. Samma löpande som rapporterar att PID-8 skiljer sig i varje meddelande eftersom den gamla motorn skrev Male där Perfuse skriver M har berättat exakt en sak att besluta.
Så varje fynd är ett fält, med en räkning, och det säger om skillnaden är systematisk — samma värdepar varje gång — eller om fältets innehåll skiljer sig.
Den distinktionen är det mest användbara i rapporten. Ett distinkt värdepar över fyrtusen meddelanden är ett enda mappningsbeslut. Fyrtusen distinkta par är innehållet som skiljer sig, vilket är ett annat och mycket värre problem, och de två måste inte läsa likadant.
Fynden är ordnade efter hur många meddelanden de påverkar, så den största enskilda orsaken är först.
15.4.3 Utlåtandet avrundar inte
Det ger exakta räkningar: 49 993 av 50 000, inte "över 99%". De sju är hela poängen med att köra det.
Det är skrivet för att kunna citeras i en ändringsbegäran, eftersom det är där numret hamnar.
15.5 En föreslagen sekvens
- Importera kanaler och lösa allt som rapporteras som oläsligt.
- För varje kanal, granska varningarna. De flesta är skript.
- Exportera ett par tusen meddelandepar från Mirth för den mest trafikerade kanalen och kör jämförelsen.
- Arbeta igenom resultaten. Systematiska är ett beslut vardera.
- Kör igen tills de enda skillnaderna är de du har beslutat är korrekta.
- Kör Perfuse i skugglag bredvid Mirth på live-trafik, levererar ingenstans, och jämför igen under en period som omfattar en helg och en månads slut.
- Byt ut en kanal, inte alla.
15.6 Vad som bara körs på en leverantörs programvara
Migrations-skärmen besvarar en andra fråga, och det är värt att fråga innan du har någon åsikt om Perfuse: hur mycket av din integrationslogik kan bara köras på den programvara du har.
Varje kanal får ett Portabilitets-utlåtande, från samma skanning som producerar migrationsanteckningarna. Den körs mot en kanal-export, så den behöver ingenting installerat och ändrar ingenting.
15.6.1 Distinktionen är hela poängen
De flesta Java i Mirth-skript är inte låsning. SimpleDateFormat, HashMap, Apache Commons — allt fungerar runt en JavaScript-motor från 2009, allt är vanligt, allt har direkta ekvivalenter. En kanal med tre hundra av dessa referenser är fullständigt portabel, och ett verktyg som rapporterade "300 Java-referenser, du är låst" skulle ljuga för dig.
Låsning är specifikt de samtal som behöver leverantörens egen server: com.mirth.connect.* och leverantörs-jar. Fem av dessa och du är fast. Fem hundra av den andra sorten och du är fri.
Så utlåtandet leder med det nummer som är viktigt och säger i samma mening att det större numret inte är det. Där det finns leverantörssamtal, listas de efter namn — en räkning är ett påstående, och en lista är något din egen ingenjör kan gå och kontrollera.
En tredje kategori hålls separat: funktion som existerar men inte från ett skript. Att starta en kanal från JavaScript har ingen ekvivalent här, och det finns ett API-slutpunkt som gör exakt samma sak. Att kalla det för låsning skulle överdriva resultatet.
15.6.2 Java-samtal som körs oförändrade
De vanligaste av dessa Java-klasser körs som de är skrivna. Perfuse har ingen Java-körning, så dessa är JavaScript-klasser med samma namn och metoder, tillräckligt för det sätt som kanalskript använder dem; importPackage(java.util) och importClass(...) bringar dem inom räckhåll med deras korta namn, som i Rhino (JavaScripts egna Date, Map, Set, Math, String och Boolean ersätts aldrig: de Java-baserade är fortfarande där med fullständigt namn). Migrationsrapporten räknar varje ett av dessa samtal som redan stöds.
| Paket | Klasser |
|---|---|
java.util | ArrayList, LinkedList, Vector, List, Collection, HashMap, LinkedHashMap, Hashtable, TreeMap, Properties, HashSet, LinkedHashSet, TreeSet, Arrays, Collections, Date, Calendar, GregorianCalendar, UUID, Base64, regex.Pattern (med Matcher), concurrent.ConcurrentHashMap |
java.lang | String, StringBuilder, StringBuffer, Integer, Long, Short, Byte, Double, Float, Boolean, Math, System (tid och radavgränsare endast) |
java.text, java.math, java.net, java.nio | SimpleDateFormat och DateFormat (Mirths mönsterbokstäver), BigDecimal (som en dubbel), URLEncoder, URLDecoder, StandardCharsets |
| Apache Commons | lang3.StringUtils och lang.StringUtils (omkring sextio metoder), StringEscapeUtils, codec.binary.Base64 |
De beter sig som Java gör där skript är beroende av det: Integer.parseInt("x") genererar NumberFormatException, String.replaceAll och split tar reguljära uttryck medan replace är bokstavlig, kartor nyckelsträngar med värde, TreeMap och TreeSet itererar i ordning, och SimpleDateFormat.parse returnerar ett datum som getTime() fungerar på. En metod som ett skript anropar som den motsvarande saknar misslyckas på den raden, namnger den; varje annan Java-klass misslyckas med namn, som tidigare. BigDecimal är en dubbel här, så den behåller inte Javas exakta decimalaritmetik: kontrollera skript som använder den för pengar.
15.6.3 Externa skript rapporteras som okända
Ett steg som kör ett externt skriptfil refererar till en sökväg på den gamla servern, och filen är inte i exporten. Ingenting kan sägas om vad den innehåller, så den räknas som okänd snarare än antas antingen väg — hämta dessa filer innan du drar någon slutsats — i båda riktningarna.
15.6.4 Perfuses egen låsning, uttalad i samma andetag
Detta avsnitt skulle vara oärligt utan det.
Perfuse är Apache 2.0, som är oåterkallelig för kod som redan släppts. Du kan fork-a det som finns idag och ingen kan återkalla det. Kanaler är YAML-filer och skript är vanligt JavaScript, så det finns ingen proprietär yta att ringa — Mirths smak av Java-beroende är strukturellt otillgänglig här, vilket är den enda platsen en begränsning verkligen är en funktion.
Vad det inte lovar: att en framtida version stannar öppen, att en värd-tjänst finns till ett pris du gillar, eller att att migrera bort från Perfuse kostar ingenting. Att flytta någon integreringslager innebär att omtesta varje kanal mot riktigt trafik. Vad du väljer är om de artefakter du bygger är läsbara och portabla, och om utgången beror på en licens som någon annan kontrollerar.
15.6.5 Konfigurera steg 6
Avsnittet Skugga startar en jämförelse. Välj den kanal som körs, välj den kandidat som ska jämföras mot från listan, och starta.
Tre saker om det är värda att veta innan du förlitar dig på siffrorna.
Kandidaten väljs från en lista, inte skrivs in. En skugga namnger en kanalfil, och ett namn som inte kan matchas gör den *aktiva* kanalen ogiltig — Perfuse avvisar en kanal i sin helhet när något den refererar till är trasigt. Så ett skrivfel producerar inte en varning, det gör den aktiva kanalen osynlig.
Andelen är ett procenttal. Sänk den bara på en upptagen feed, och veta vad det kostar: sampling minskar arbete och förtroende i samma proportion, och meddelandet som skulle ha visat skillnaden är det ovanliga.
Fält att ignorera behövs vanligtvis. En kanal som stämplar en tidsstämpel eller en sekvensnummer skiljer sig på varje enskilt meddelande, vilket rapporterar en skillnadsfrekvens på 100% och berättar ingenting. MSH-7 och MSH-10 är det vanliga paret.
En jämförelse skrivs till kanalfilen så snart du startar den, och börjar observera när kanalen nästa gång laddas — skärmen säger det istället för att påstå att den redan körs. Att stoppa en jämförelse lämnar kandidatkanalen på plats, eftersom kandidaten är det som är tänkt att gå live.
Steg 6 är det som inte kan förkortas. De skillnader som betyder något är vanligtvis i trafik som bara visas ibland — en sällsynt utlösande händelse, en månadsvis batch, en avsändare som beter sig annorlunda vid midnatt — och ett urval som tas under en eftermiddag kommer inte att innehålla dem.
15.7 Gå tillbaka åt andra hållet
En kanal kan exporteras som en Mirth-kanalfil, från webbläsaren: Kanaler, sedan Till Mirth på den kanal du vill.
Detta finns eftersom invändningen mot att ersätta en fungerande motor sällan är om ersättningen är något bra. Det är vad som händer om beslutet visar sig vara fel, och en export som går tillbaka samma väg är det billigaste svaret på det.
Läs vad dialogen berättar för dig innan du tar filen. Mirths format har ingenstans att lägga en Perfuse-filter, en transformationskedja, ett kontrakt eller en skuggjämförelse, så en exporterad kanal gör mindre än den den kom från. Transporterna och deras adresser konverterar; logiken gör det inte. Varje förlust listas med namn innan filen erbjuds, och samma lista går in i kanalens beskrivning så att den som importerar den ser den också.
En kanal som Mirth inte kan uttrycka avvisas istället för att approximeras. En S3-destination har ingen Mirth-ekvivalent, och en kanal som importerades renligt medan den levererade någonstans annat än bucketen skulle vara sämre än ingen fil alls. Avvisandet namnger destinationen som orsakar felet.
Kopplingsdefinitionerna skrivs inte från en läsning av Mirths format. scripts/mirth-dump-connector-templates.sh har Mirths egen serialisator producera standardvärdena för varje kopplingsklass, och Perfuse ersätter värden i dessa dokument — avvisar alla inställningar som mallen inte redan innehåller. Detta är viktigt på grund av hur Mirth svarar på en kanal som den inte kan parsera: den avvisar inte importen. Den lagrar en kanal vars beskrivning har ersatts med "Denna kanal är ogiltig. Verifiera att alla obligatoriska tillägg är laddade korrekt" och vars destinationer har tystats bort. En exporter som kontrolleras mot sin egen utdata istället för mot en server passerar varje test medan den producerar dokument som kastas bort, vilket är exakt vad som hände här innan exporterna testades mot en igång Mirth.
Vad som korsar idag: MLLP och TCP i båda riktningarna, HTTP i båda riktningarna, fil läsning och skrivning, databas läsning och skrivning, DICOM i båda riktningarna, och SMTP, SOAP och JavaScript-destinationer. Varje par är verifierat genom att importeras till en riktig Mirth 4.5.2 och kontrollera att servern inte tystade bort kanalen.
16 CMS-0057 för betalare
CMS Interoperability och Prior Authorization slutregel (CMS-0057-F) kräver att påverkade betalare — Medicare Advantage-organisationer, statliga Medicaid- och CHIP-program och deras hanterade vårdplaner, och QHP-utgivare på federala utbyten — ska köra fyra FHIR-API:er från och med den 1 januari 2027, och ska publicera prioriseringsmetriker på sin offentliga webbplats varje år från 2026.
Perfuse tillhandahåller de fyra API:erna på sin FHIR-slutpunkt och omvandlingarna som fyller dem: avgjorda anspråk som CARIN Blue Button, prioriseringsauktorisationer som Da Vinci PDex, och årliga metriker i layouten av CMS eget mall. CMS-0057-vyn, under Utbyte, säger vilken av de fyra den här instansen kan svara på och vad var och en fortfarande behöver, och gör alla tre omvandlingarna i webbläsaren.
Läkemedel är utanför omfång överallt, eftersom de är i regelns prioriseringsbestämmelser: inga apoteksanspråk, inga formularier, och en metrikrad som namnger ett läkemedel avvisas istället för att räknas.
16.1 De fyra API:erna
| API | Vad den tillhandahåller | Guider | Aktiverad av |
|---|---|---|---|
| Patient Access | En medlems anspråk, kliniska data och tidigare auktorisationer, till en app de väljer | CARIN Blue Button 2.2.0, PDex 2.2.0, US Core, SMART App Launch | -fhir och en SMART-utgivare (-smart-issuer) |
| Provider Access | Samma sak för en vårdgivares tilldelade medlemmar, i bulk | PDex 2.2.0, Da Vinci ATR 2.1.0, Bulk Data | -fhir-payer-apis och -fhir-bulk-export |
| Payer-to-Payer | En medlems post till en annan betalare, efter att ha matchat dem | HRex 1.2.0 $member-match, PDex 2.2.0 | -fhir-payer-apis |
| Prior Authorization | Vad en beställning behöver, dokumentationen, sedan begäran och beslutet | Da Vinci CRD, DTR och PAS 2.2.x (2.2.1, 2.2.0, 2.2.1) och 2.1.0, med X12 278-översättning | -fhir, skrivbar, och -crd-rules |
Patient Access API behöver ingen egen åtgärd: den är FHIR-slutpunkten för vanlig läsning och sökning, skyddad av SMART, med CARIN- och PDex-resurser i lagret. Sökning av ExplanationOfBenefit stöder CARIN-namnparametrarna — patient, identifier, type, service-date, billable-period-start, provider, insurer, coverage — och Coverage stöder subscriber-id, identifier och payor.
16.1.1 Två versioner av guiderna: 2.1.0 och 2.2.x
CMS-0057-F rekommenderar CRD, DTR och PAS 2.0.1 och 2.1.0. Versionerna 2.0.1 bygger på US Core 3.1.1, som upphörde att gälla den 1 januari 2026, så 2.1.0 är den version en EHR som byggts för regeln troligen talar; de senaste är CRD 2.2.1, DTR 2.2.0 och PAS 2.2.1. Perfuse svarar i båda. Den bestämmer vilken version en anropare talar, mest specifik först:
- från begäran: CRD:s CDS Hooks-tillägg
davinci-crd.requestedVersion("2.1"), eller versionen på en Da Vinci-profil som en DTR- eller PAS-inmatning påstår (profile-pas-request-bundle|2.1.0); - från anroparens registrering:
davinci_version: "2.1"på en SMART-klient (-smart-clients) eller en CDS-klient (-cds-clients); - från servern:
serve -davinci-version 2.1; standard är 2.2.
clients:
- issuer: https://ehr.example.org
jwks_url: https://ehr.example.org/.well-known/jwks.json
davinci_version: "2.1"
Varje svar bestäms och sparas i formen 2.2.x och skrivs om för en 2.1.0-anropare när det skickas, så reglerna, granskningskön, X12 278-länken och måtten är desamma för båda. Omformuleringen täcker vad versionerna stavar olika: CRD 2.1.0 har inget indeterminate (Perfuse säger villkorligt, med orsaken) och ingen kategori på en täckningsdetalj; DTR 2.1.0 namnger paketet PackageBundle och lämnar QuestionnaireResponse till appen; PAS 2.1.0:s $inquire svarar med en Bundle, och den saknar granskarens och överföringstilläggen. Den fullständiga listan, och kontrollen mot varje 2.1.0-guides egna exempel, finns i conformance/davinci21. En PAS-avisering följer -davinci-version, eftersom en prenumeration inte anger vilken version dess ägare läser.
16.2 Täckningskrav och dokumentation: CRD och DTR
Prior Authorization API är i praktiken tre Da Vinci-guider tillsammans. CRD berättar för kliniken, medan ordern fortfarande är en utkast, om den är täckt, om den behöver föregående auktorisering och vilken dokumentation som önskas. DTR överlämnar EHR-frågeformuläret som samlar in den dokumentationen. PAS skickar in begäran och returnerar beslutet. Perfuse betjänar alla tre som betalare.
-crd-rules rules.yaml servar CRD via CDS Hooks på /cds-services: alla sex av CRD:s hooks, order-sign, order-select, order-dispatch, appointment-book, encounter-start och encounter-discharge, var och en med en prefetch för patientens aktiva Täckning. De två möteshookarna prefetchar också mötet och svarar om mötet i sig, matchat efter dess typ och servicetyp, liknande appointment-book som svarar om en mötestid. Reglerna är betalarens policy, som hålls i en fil eftersom de ändras utan programvarureleaser:
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
Varje order får en systemActions-uppdatering som bär CRD: s täckningsinformationsutvidgning - som EHR lagrar på ordern och senare skickar med föregående auktorisering - och ett kort som kliniken läser. En order vars kod har ingen regel besvaras conditional, aldrig antas täckt; en begäran med ingen täckning alls får ett kort som säger så. examples/crd/ har en regelfil och ett matchande frågeformulär.
En regel kan också bära resten av vad CRD låter en betalare säga:
billing_codes: de koderna som faktureras under.details: begränsningar och kostnader, såsomallowed-periodellerin-network-copay.contact: vem man ska ringa.expiry_days: hur länge svaret gäller.depends_on: koderna för andra beställningar som svaret är beroende av, så att journalsystemet frågar igen om de ändras.doc_purpose: vad dokumentationen är till för (withclaim,withorder,retain-doc).withpaavvisas, eftersom CRD 2.2.1:s
eget invariant crd-ci-q4 avvisar det.
Vad EHR inte förprefetchade, läser Perfuse från EHR: s fhirServer med token som skickades. Om det misslyckas är svaret indeterminate med CRD: s technical orsak, aldrig en gissning. En täckning som har upphört eller inte är aktiv besvaras not-covered, no-active-coverage.
members: fhir i regelfilen löser täckningen mot försäkringsgivarens egna register i den här serverns FHIR-lagring (starta den med -fhir), samma register som $member-match läser:
- en patient som inte är medlem svaras
no-member-found; - en medlem vars täckning inte matchar svaras
coverage-not-found; - en tidigare godkänd begäran om förhandsgranskning för tjänsten (en ClaimResponse med en
preAuthRef) gör att svaret blirsatisfied,
med det numret.
Upptäckt deklarerar davinci-crd.version och en coverage-info-konfigurationsalternativ. När en klient stänger av alternativet är svaret tomt. EHR JWT: er kontrolleras som CDS Hooks definierar dem, med iss, aud, exp, iat och jti och ingen sub, och en upprepad jti vägras.
Samtal autentiserar med JWT som en EHR undertecknar för varje samtal, från en utfärdare som anges i -cds-clients med dess JWKS-URL - som CDS Hooks beskriver det - eller med en Perfuse API-token. Upptäckt är öppen, eftersom CDS Hooks kräver det.
DTR: ladda frågeformulären in i FHIR-slutpunkten, och POST /fhir/Questionnaire/$questionnaire-package returnerar dem som DTR-paket, med CQL-biblioteken de namnger. Begäran kan namnge frågeformuläret eller skicka ordern och låta dess täckningsinformation säga vilken.
Försök: Payers → Claims & auth → Coverage requirements (CRD) skickar en order till den här serverns regler eller till en betalares CDS-tjänst-URL och visar korten och täckningsinformationen.
16.3 Anspråk som CARIN Blue Button
perfuse cms0057 carinbb parar varje anspråk i en 837 med dess betalning i en 835, efter patientkontonumret som 835 kräver ska återges, och skriver en FHIR-transaktion för varje: ExplanationOfBenefit med Patient, Coverage, Organizations och Practitioners som det refererar till.
perfuse cms0057 carinbb -system https://fhir.your-plan.org/identifier -network innetwork \
claims.837 remittance.835
Profilen följer anspråket: professionella anspråk (837P) blir C4BB-ExplanationOfBenefit-Professional-NonClinician, och institutionella (837I) inpatient eller outpatient efter fakturans typ. Varje post är en PUT med ett ID taget från käll-identifierarna, så att laddning av samma anspråk två gånger uppdaterar det snarare än skapar en andra kopia.
Tre saker finns inte i någon av X12-filerna, och var och en hanteras genom att säga det snarare än att gissa:
- Identitetssystemet. CARIN kräver att medlemmens identifierare ska ange betalarens namnrymd.
-systemkrävs; det finns inget standardvärde, eftersom ett standardvärde skulle ge alla betalare som använder Perfuse samma namnrymd. - Nätverksstatus. Ingen av transaktionerna anger om faktureringsleverantören är i nätverket, och det bestämmer vad medlemmen betalar. Utan
-networkär förmånsbetalningsstatusenotheroch konverteringsanteckningarna varför. - Ett anspråk som 835 inte nämner. En CARIN ExplanationOfBenefit är ett avgjort anspråk. Utan 835 finns det inget betalarnummer, ingen betalning och ingen medlemsansvar, så anspråket rapporteras som hoppad över och inte konverterat.
Diagnoser skrivs med sin decimalpunkt (J02.9, inte J029), eftersom det är så kodschemat publicerar dem och en terminologiserver som tillfrågats om den andra stavningsvarianten säger att den inte finns. En beroendes medlemidentifierare är prenumerantens, vilket är vad 837 bär, och noterna säger det. En NPI med felaktig kontrollsiffra rapporteras innan US Core avvisar den.
16.4 Föregående auktoriseringar som PDex
perfuse cms0057 priorauth konverterar en Da Vinci PAS ClaimResponse — eller PAS-svars-paketet som innehåller en — till en PDex föregående auktorisation ExplanationOfBenefit, vilket är vad alla tre data-API:erna tillhandahåller.
perfuse cms0057 priorauth pas-response.json pas-claim.json
PAS-anspråket är valfritt och nästan alltid behövs. En ExplanationOfBenefit måste ange vilket skydd beslutet togs under, och endast begäran innehåller det; utan det stoppas konverteringen och meddelar det. Granskningsåtgärden — godkänd, avvisad, försenad, med auktorisationsnummer och anledning — flyttas från PAS-utvidgning till PDex, och X12-tjänsttypen behåller sin kod under URI: n som PDex binder den till.
16.5 Provider Access- och Payer-to-Payer-API:er
Med -fhir-payer-apis svarar FHIR-slutpunkten på tre fler åtgärder:
POST /fhir/Patient/$member-match— HRex-medlemssammanfogning. Täckningsidentifierarna smalnar av till ett fåtal kandidater, och efternamn och födelsedatum måste sedan överensstämma; ett förnamn jämförs med initial och kön endast när båda sidor anger det. Mer än en överlevande kandidat är inte en match, och svaret är 422 snarare än en gissning, eftersom en gissning avslöjar en främlings anspråk. En aktiv samtycke som tillåter avslöjande krävs, eftersom Payer-to-Payer-API är valfritt för medlemmen;-fhir-member-match-without-consentstänger av det för testning.GETellerPOST /fhir/Group/{id}/$davinci-data-export— Da Vincis bulkexport av en grupps nuvarande medlemmar.exportTypeväljer målgruppen:hl7.fhir.us.davinci-pdex#provider-downloadeller#provider-deltaför Provider Access,#payertopayerför Payer-to-Payer.GET /fhir/Group/{id}/$export— standard bulkdata gruppexport, behandlas som Provider Access.
Exporterna tillämpar regelns undantag på vägen ut. Anspråk förlorar betalning och alla kostnadsdelnings- och återbetalningsbelopp, och behåller tjänsterna, koderna, datum och leverantörerna; CARIN-profilen tas bort från meta.profile eftersom resursen inte längre uppfyller den. Payer-to-Payer lämnar också ut förnekade föregående auktorisationer. Medlemmar som innehar en aktiv PDex Provider Access-opt-out-samtycke lämnas ut ur en leverantörsexport, och loggen registrerar hur många. patient-parametern kan endast smalna av till medlemmar i gruppen; att namnge någon annan vägras.
Tillgång till en grupps export bestäms av slutpunkternas autentisering. SMART-omfattningar anger vilka typer av resurser en token får läsa, inte vilken grupp, så varje leverantör behöver en token som endast kan nå sin egen attributionslista. En API-token kan begränsas till grupper när den skapas — perfuse token create -label riverside-provider-access -fhir-groups riverside-attributed, eller fältet Begränsa till FHIR-grupper under Användare → Maskincredentiella — och på FHIR-slutpunkten kan den sedan läsa dessa grupper, köra $davinci-data-export eller $export på dem och hämta vad exporten producerade, och ingenting annat. En annan leverantörs grupp svarar inte hittad istället för förbjuden, så en token lär sig inte vilka andra attributionslistor som finns; alla andra förfrågningar, inklusive medlemsmatchning och vanlig sökning, avvisas. Begränsningen gäller API-token; en token från en SMART-utfärdare har ingen gruppgräns. När SMART också är konfigurerat avvisas API-token om inte Inställningar → FHIR → Acceptera Perfuse API-token bredvid SMART-token är på (se Säkerhet, *Vem får anropa FHIR-slutpunkten*); en leverantörs grupp-begränsade token behöver det.
16.6 En leverantörs katalog: Plan-Net
CMS-0057 begär också en leverantörsregister från betalare, och FHIR-slutpunkten tillhandahåller en till Da Vinci Plan-Net 1.1.0 utan möjlighet att aktivera: ladda Practitioners, PractitionerRoles, Organizations, OrganizationAffiliations, Locations, HealthcareServices, InsurancePlans och Endpoints, och medlemmarnas appar kan söka efter dem. Varje Plan-Net-sökparameter är indexerad - en rolls nätverk och tjänst, en plans täckningsområde, en anslutnings deltagande organisation, en organisations partof - tillsammans med de inkluderar och omvända kedjor (_has) som guidens frågor använder, och CapabilityStatement listar Plan-Net-profilerna.
Infernos Plan-Net-svit passerar 199 tester. De 10 det misslyckas med är framtida kedjor där kitet tar sin sökning från den första organisationen den har sett snarare än en som de sökta resurserna hänvisar till; det rapporteras till kitet (dess ärende 34), och servern svarar korrekt på dessa frågor när den ges ett värde som data innehåller.
16.7 Föregående auktorisationsstatistik
perfuse cms0057 metrics läser en CSV med beslut som exporterats från användningshanteringssystemet och producerar den offentliga sidan som CMS kräver, i layouten för dess *Föregående auktorisationsstatistik — Översikt och mall*.
perfuse cms0057 metrics -year 2025 -org "Springfield Health Plan" -services services.csv \
decisions.csv > prior-authorization-metrics-2025.html
Kolumner hittas av rubrik: priority, received, decided och decision är obligatoriska, och request_id, line_of_business, extended, appealed, appeal_decision, service_code och service_description läses när de är närvarande. En begäran tillhör det år den beslutades i; en som fortfarande väntar är listad som utesluten, aldrig räknad. Varje rad som inte kan läsas rapporteras med dess radnummer.
Aritmetiken följer mallen: för standard- och skyndsamhetsbegäranden separat, andelen godkänd och avvisad, godkänd och avvisad inom beslutsramen, godkänd efter att granskningsperioden förlängts, och godkänd efter överklagande — av överklaganden, inte av begäranden — med medel- och median tid från mottagande till beslut. En median under en dag skrivs i timmar snarare än avrundad till "0 dagar", vilket mallen begär uttryckligen. Delvis godkända begäranden räknas som godkända, eftersom mallen inte har någon kategori för dem, och sidan anger hur många det fanns. Statistik rapporteras per affärsområde, vilket är den nivå som CMS kräver.
Sidans innehåll är självförsörjande — ingen skript, ingen extern stylesheet eller teckensnitt — eftersom den publiceras på en offentlig webbplats av vem som helst som underhåller den, och allt den laddar från någon annan plats är något som kan brytas eller spåra en besökare. -format csv och -format json ger samma nummer för andra användningsområden. Utan -services innehåller sidan ett meddelande om att listan över objekt och tjänster som kräver föregående godkännande saknas, eftersom CMS kräver det på samma sida.
16.8 Läkemedel: formulariet, Real-Time Prescription Benefit och elektronisk föregående godkännande
CMS-0062-P (föreslagen den 14 april 2026) skulle införa läkemedel i förhandsgranskning: påverkade betalare skulle stödja NCPDP SCRIPT elektronisk förhandsgranskning, NCPDP Formulary & Benefit-standarden och NCPDP Real-Time Prescription Benefit från och med den 1 oktober 2027, fatta beslut om läkemedelsbegäranden inom 24 timmar (påskyndat) och 72 timmar (standard), ge en specifik anledning till varje avslag, och rapportera läkemedelsmått från och med 2028. Medicare Part D kräver redan SCRIPT ePA. En fil, formulariet, svarar på allt detta:
perfuse serve -fhir -pas -crd-rules payer-rules.yaml -formulary formulary.yaml
examples/formulary/formulary.yaml är ett exempel vars läkemedel är verkliga RxNorm-koncept med NDC som RxNorm listar för dem (kontrollerat mot RxNav). En fil namnger betalaren, dess planer (var och en med det formulary den använder, dess grupp-ID och dess kostnadsandelar per apoteksförmån och nivå) och dess formularier. Varje läkemedel är ett RxNorm SCD eller SBD med dess RxNorm-grupp (SCDG eller SBDG som Drug Formulary API kräver), dess NDC, en nivå och dess begränsningar: prior_authorization, step_therapy, quantity_limit (en mängd under en rullande antal dagar, och en daglig maximal), not_covered, alternatives (RxNorm-koder, mest föredragna först), notes, och questionnaire, den kanoniska URL:en för FHIR-frågeformuläret som en förhandsgranskning begär. cost_30_day är planens kostnad för en 30-dagars försörjning, som en självrisk är en procentuell andel av; utan det är en självrisk citerad som en procentuell andel, aldrig som en uppfunnen summa. Hela filen kontrolleras när den laddas, varje problem listas på en gång. En medlem hittas av filens members-lista, per grupp, eller genom FHIR-lagret: en Coverage vars subscriberId är medlemmens ID och vars class av typ plan är planens ID. Betalare › Läkemedel visar formulariet, prissätter ett läkemedel och kör en förhandsgranskning från början till slut.
16.8.1 Da Vinci US Drug Formulary API
Publicerad på /formulary/fhir som Da Vinci US Drug Formulary 2.1.0: varje plan en PayerInsurancePlan, varje formulary en Formulary (båda InsurancePlan), varje läkemedel en FormularyDrug (MedicationKnowledge) och varje post en FormularyItem (Basic). Guidens sökningar betjänas (Basic?code=formulary-item&formulary=...&drug-tier=...&pharmacy-benefit-type=...&period=..., subject:MedicationKnowledge.code, InsurancePlan?formulary-coverage=..., coverage-type, MedicationKnowledge?code=...&doseform=...) med _include=Basic:subject, Basic:formulary och InsurancePlan:formulary-coverage. Den är offentlig, utan behörighet, som CMS kräver av en betalares formulary: den betjänas från ett lager av sitt eget, i minnet, som innehåller formulariet och ingenting annat, så att den kan vara öppen utan att nå en patients journal. Den är skrivskyddad. Ett uteslutet läkemedel publiceras inte, eftersom API:et listar vad ett formulary täcker; RTPB och ePA svarar fortfarande på det som inte täcks. Verifierad med HL7 FHIR-valideraren mot guidens 2.1.0-paket med terminologi kontrollerad: varje resurs som genereras från exemplet har inga fel.
16.8.2 Real-Time Prescription Benefit
POST /ncpdp/rtpb tar en RTPBRequest (NCPDP RTPB v13) med en API-token för operatörsrollen och svarar med en RTPBResponse från formulariet: täckningsstatusen, formulary-statusen, medlemmens uppskattade andel och planens, och täckningsbegränsningarna, med upp till fem täckta alternativ prissatta på samma sätt. Begränsningskoder och den status var och en kartläggs till följer NCPDP:s offentliga RTPB-Implementeringsrekommendationer: 75 förhandsgranskning krävs, 608 stegterapi, 76 planbegränsningar överskrids, 7X dagars försörjning över planbegränsningen (ett läkemedel som inte är tillgängligt via post, till exempel), 70 inte täckt, alla *täckta med begränsningar* (CR) utom 70 (NC). En medlem med en godkänd förhandsgranskning på fil får CC och AB8, som Surescripts-guiden begär, så att prescribern inte skickas för att begära igen. En begäran som inte kan prissättas är NotProcessed med en NCPDP-avvisningskod: 52 för en medlem som inte hittas, E7 och 19 för en saknad mängd eller dagars försörjning. Apoteksförmånen läses från begäran: en fyllning över 34 dagar är en tre månaders försörjning, och apotekstyp M är postorder.
16.8.3 Elektroniskt föregående godkännande (NCPDP SCRIPT)
POST /ncpdp/script tar PAInitiationRequest, PARequest, PAAppealRequest och PACancelRequest med en API-token för operatörsrollen, och svarar på var och en med dess svar:
| Begäran | Svar |
|---|---|
PAInitiationRequest | Closed när ingen behövs: CC ingen förhandsgranskning krävs, FN inom mängdbegränsningen, FM inte täckt eller inte på formulariet, FQ en godkänd förhandsgranskning på fil, CD ingen sådan medlem, CG en redan pågående. Annars Open, med ett ärendenummer och frågesättet. |
PARequest | Avgörs som en PAS-begäran: Approved med auktorisationsnumret och perioden, Denied med anledningen, eller Open under granskning. |
PAAppealRequest | En avslagen ärende avgörs igen, på anledningen i PANote (en överklagande utan en begärs om den). |
PACancelRequest | Approved medan ärendet är öppet eller under granskning, och PAS-begäran avbryts; Denied en gång det är avgjort. |
Frågesättet är läkemedlets FHIR-frågeformulär från FHIR-lagret, samma som DTR fyller i: en boolesk blir ett ja/nej-val, ett val ett val, ett nummer ett numeriskt värde, ett datum ett datum och allt annat fritt text; grupper är plattade i ordning och enableWhen tas inte med, eftersom SCRIPT grenar efter val och inte efter villkor. Ett läkemedel utan frågeformulär får tre fritextfrågor: diagnosen, vad som har provats och varför detta läkemedel. En PARequest blir en Da Vinci PAS-förfrågan: en Claim för läkemedlet (RxNorm och NDC), MedicationRequest som begärs, patienten, förskrivare, betalare och täckning, samt svaren som en QuestionnaireResponse, med eventuella bilagor som DocumentReference. Det beslutas sedan som varje föregående prioritering på denna server: regelfilen, ett beslutsstöd (-pas-decider-url), eller granskningskön, där det markeras Läkemedel och hålls till läkemedelstidramen. Ett beslutsstöd ser en läkemedelsbegäran exakt som den ser en från en EHR: s PAS-klient. Vi rekommenderar Vaglio, BioDreams källkods-tillgängliga (PolyForm Shield) beslutsstödmotor, som har läkemedelspolicys med stegterapi; en betalares egen motor ansluter via samma -pas-decider-url, och ingen behövs för regelfilen och granskarna för att fatta beslut.
Ett beslut som fattas efter att begäran har besvarats (en granskares, en överklagans) skickas till förskrivaren som ett oanmodat PAResponse eller PAAppealResponse, dirigerat till kanalen som anges av -epa-reply-channel, som levererar det till nätverket. Utan en sådan, eller när leveransen misslyckas, anger fallet att förskrivaren inte har informerats och skärmen skickar det igen.
Betalare › Läkemedel › Prioritering skickar meddelanden som en förskrivar-system skulle till denna servers egen slutpunkt (start, besvara frågorna, se beslutet), listar varje ärende med vad förskrivaren har informerats om och visar läkemedelsstatistiken som CMS-0062-P föreslår: begäranden godkända, avvisade och väntande, överklagade och godkända eller avvisade vid överklagande, medel- och median-timmar från begäran till beslut, och hur många som beslutades sent. Läkemedel för medicinska förmåner som begärs via PAS (en HCPCS J-kod med en MedicationRequest, eller en artikel kodad i RxNorm eller NDC) räknas också som läkemedel i PAS-statistiken.
Vad detta vilar på, uttryckt tydligt. NCPDP: s scheman och implementeringsguider är licensierade. Elementnamnen och ordningen här följer de offentliga Surescripts ePA- och RTPB-kompletteringsguiderna och deras exempel, och NCPDP: s offentliga RTPB-rekommendationer. Två element som det offentliga materialet aldrig visar skrivs till SCRIPT-mönstret som används på andra ställen och bör kontrolleras mot en licensierad kopia innan certifiering: Closed/ReasonCode och Denied/DenialReason. Inget meddelande har kontrollerats mot NCPDP: s XSD eller ett nätverks certifiering. NCPDP Formulary & Benefit-filen produceras inte: dess fullständiga layout finns i NCPDP: s licensierade guide, och en partiell fil skulle avvisas av nätverket som laddar den.
16.9 Vad som kontrollerades och mot vad
CARIN- och PDex-utdata validerades med den officiella HL7 FHIR-valideraren, laddad med de publicerade paketen (hl7.fhir.us.carin-bb#2.2.0, hl7.fhir.us.davinci-pdex#2.2.0): professionella, slutenvård- och öppenvårdskrav och två PAS-beslut, utan fel. PDex-inmatningarna var PAS-guidens egna exempel snarare än former skrivna här för att överensstämma med omvandlaren. Valideraren fann fem defekter på den första körningen — bland annat att CARIN kräver profilversionen i meta.profile och kravtypkodsystemversionen på institutionella krav — och var och en är åtgärdad och täckt av en test.
Att bygga detta fann en defekt som var äldre än det: FHIR-lagret släppte varje element som dess interna modell inte deklarerade, så en ExplanationOfBenefit förlorade sina artiklar, diagnoser, prövning och betalning på vägen in. Lagret behåller nu allt som en resurs bär, och en test laddar ett CARIN-krav genom servern och läser det tillbaka helt.
CRD: s utdata - den uppdaterade ordern och CDS Hooks-svaret mot CRD: s eget logiska modell - och DTR: s paketutdata validerar i den officiella HL7-valideraren mot CRD 2.2.1 och DTR 2.2.0 med inga fel.
DTR här är betalarens sida av 2.2.0. $questionnaire-package tar frågeformulären som namnges, de som CRD namnger på en order, eller täckningspåståendet id som CRD returnerar (context, medan samma process betjänar CRD), och returnerar var och en som ett paket med en QuestionnaireResponse att fylla i, Biblioteken som CQL behöver och deras beroenden. Värdesätt som svaren använder reser i paketet när de laddas (PUT /fhir/ValueSet/{id}), och $expand listar deras koder. $log-questionnaire-errors skriver vad en DTR-app rapporterar till serverloggen.
Adaptiva frågeformulär: skriv hela frågeformuläret en gång, med SDC: s questionnaireAdaptive-tillägg och enableWhen på frågorna som bara gäller ibland. Paketet ger appen en tom skal, och varje $next-question-anrop lägger till nästa fråga som gäller för svaren hittills, tills det inte finns något mer att fråga och svaret markeras som komplett. Ordningen och grenarna är betalarens egna regler; frågor som inte gäller visas aldrig.
Inloggning som klient: DTR- och PAS-klienter når betalaren med SMART Backend Services - en signerad JWT utbytt mot en token på betalarens auktoriseringsserver. Peka Perfuse mot den servern med -smart-issuer (och -smart-jwks om dess adress inte kan lösas från Perfuse), och skicka -smart-backend-services så att upptäcktsdokumentet säger så. Inferno DTR-sviten passerar på detta sätt med Keycloak som auktoriseringsserver.
Perfuse kan vara den auktoriseringsservern själv: serve -fhir -smart-clients clients.yaml utfärdar Backend Services-token på /auth/token till de klienter som listas, var och en med de offentliga nycklar som den signerar sina påståenden med och de systemomfattningar som den kan beviljas, och FHIR-slutpunkten accepterar dem. Inget separat identitetsserver behövs för en betalares maskin-till-maskin-klienter.
Med -smart-users users.yaml också, loggar medlemmar och kliniker in där för att auktorisera appar, vilket Patient Access API behöver: appen skickar personen till /auth/authorize, de loggar in, en kliniker väljer patienten och båda ser vad appen begär och kan avmarkera någon av dem. En medlem får endast sin egen journal, oavsett vad appen begär. Varje person i filen namnger den FHIR-resurs de är, Patient/… eller Practitioner/…, och en lösenordshash från perfuse smart hash; lösenordet självt skrivs aldrig ner.
Personer kan logga in på organisationens egen identitetsprovider istället: -smart-oidc oidc.yaml namnger den (utfärdare, klient-id och var hemligheten är), och inloggningssidan erbjuder "Logga in med" den bredvid lösenordet. Varje person är länkad av providerns ämne, oidc_subject i användarfilen, så filen bestämmer fortfarande vem som kan auktorisera appar och vilken FHIR-resurs de är; ett konto som är länkat till ingen avvisas. Koder, uppdateringstoken och återkallanden sparas i databasen, så en omstart loggar ut ingen.
Användare → SMART-appar i konsolen listar de registrerade apparna och personerna, och lägger till, redigerar och tar bort dem. Varje sparande kontrolleras som filerna är vid start, skrivs till dem och används omedelbart. En konfidentiell app som sparas utan hemlighet tilldelas en, visas en gång; ett lösenord ställs in där och visas aldrig igen. Att ta bort en app eller en person stoppar omedelbart de åtkomsttoken som redan har utfärdats till den eller beviljats av dem, och deras uppdateringstoken med dem.
Omfattningar kan vara granulära, som SMART App Launch 2 och US Core definierar dem: patient/Observation.rs?category=laboratory läser endast de Observationer som sökningen skulle hitta. En beviljande som filtreras för en typ tillämpar sitt filter på varje sökning och varje läsning av den typen; en ofiltrerad beviljande för typen, eller för *, lyfter det. Ett filter som inte kan läsas beviljar ingenting snarare än allt.
16.10 Besluta om förhandsauktorisationsbegäran: PAS
serve -fhir -pas -crd-rules rules.yaml svarar på Da Vinci PAS 2.2.1 vid POST /fhir/Claim/$submit och POST /fhir/Claim/$inquire. Besluten kommer från samma regelfil som CRD:s svar, så den ordning en kliniker informeras om behöver auktorisering bestäms av den regel som sa så:
- 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
Varje artikel får en X12-granskningsåtgärd: A1 certifierad, A3 inte certifierad, A4 väntande, A6 ändrad, C avbruten (certifieringstyp 3). En rad som inte namnger någon tjänst är inte beslutad men besvaras med ett fel (X12 901 AG, korrigera och skicka in igen). Svaret ekar vad en 278-svar ekar — artikelspårningsnummer, de begärda tjänstdatum, mötets datum, överföringsidentifierare med avsändare och mottagare bytta — och ger varje rad betalarens egen administrationsreferensnummer. En tjänst som ingen regel namnger är väntande, aldrig godkänd: ett beslut som ingen skrev ner är ett beslut för en person.
Väntande begäran väntar på en granskare, som svarar med 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 också vara modify: certifierad, men inte som begärt, med quantity (valueDecimal, de certifierade enheterna) och/eller alternative (valueCoding, den godkända tjänsten istället). Svaret säger sedan A6 Modified, med den certifierade detaljen eller alternativet som en tillagd post, och ett auktorisationsnummer. item (valueInteger, upprepningsbar) begränsar beslutet till vissa rader. Beslutet blir en ny version av svaret, markerat som granskat av en person, och med -fhir-subscriptions levereras det på PAS-ämnet (PASSubscriptionTopic, filterat av org-identifier, den begärande organisationens identifierare) som det fullständiga PAS-svars paketet, i samma transaktion som registrerar det. $inquire returnerar det aktuella svaret till varje begäran som leverantören gjort om den medlemmen; en annan leverantörs förfrågan hittar ingenting. $decide behöver ett skrivomfång; $inquire är ett läs.
Begäran och varje version av deras svar sparas i pas_requests och pas_responses i serverns databas.
16.10.1 Granskarkön
I webbkonsolen listar Betalare → CMS-0057 → Granskningskö de väntande begärandena, med de som snart är förfallna först: en skyndsam begäran (Claim.priority stat) är förfallen 72 timmar efter ankomst, en standardbegäran 7 dagar. Att välja en visar medlemmen, leverantören, varje tjänst med de begärda enheterna och var den står, vad svaret begärde, och varje dokument som mottagits för den, med vanliga textdokument som visas inline. En redigerare registrerar beslutet där: godkänna, avslå eller ändra (certifierade enheter, eller en annan tjänst godkänd i stället), med en orsak och granskarens NPI. En ändring måste certifiera färre enheter än som begärdes; lika många eller fler är ett godkännande, och avslås som en ändring. En godkänd tjänst i stället börjar i kodsystemet för den begärda tjänsten. Det är samma beslut som $decide gör, så leverantörens prenumeration levererar det. Att läsa en begäran och fatta beslut om den skrivs båda till revisionsloggen.
Övervakning → Teaminstrumentpaneler → Föregående auktorisering visar, för de senaste 30 dagarna, hur många standard- och skyndsam begäran som beslutades inom CMS-0057:s tidsramar, beslutades sent, fortfarande väntar inom tiden och är försenade nu, med medianvärdet för tiden att fatta beslut, och hur de begärda tjänsterna besvarades: godkända, ändrade, avslagna eller fortfarande väntande. Dessa två paneler läses från begärandena själva, så de är inte i instrumentpanelens Grafana-export, som säger så i sin beskrivning.
16.10.2 Mottagande av dokument som en väntande begäran begär
Ett penderat svar begär dokument med en uppgift och en Kommunikationsbegäran per dokument. En frågeformulär begärs som PAS beskriver det: en Kommunikationsbegäran med den enskilda LOINC-koden 102089-0, under spårningsnumret för raden den är för (itemTraceNumber, som ClaimResponse ekar; en rad som skickas utan ett spårningsnummer tilldelas ett). Det spårningsnumret är DTR-sammanhanget: $questionnaire-package med endast context inställt på det returnerar frågeformuläret. Leverantören skickar vad som begärts med Da Vinci CDex $submit-attachment (POST /fhir/$submit-attachment): TrackingId är begäran eget spårningsnummer (ClaimResponses första identifierare, som också är uppgiftens), eller en Kommunikationsbegärans identifierare, AttachTo är preauthorization, och MemberId måste vara begäran medlem. Varje bilaga DocumentReference eller QuestionnaireResponse sparas med begäran och visas för dess granskare; ett dokument som anländer beslutar ingenting.
16.10.3 Avgörande i ett X12-användningssystem
De flesta betalare beslutar om förhandsgodkännanden i ett UM-system som talar X12 278. Med -pas-278-url är Perfuse FHIR-gränssnittet för det systemet: varje $submit skickas som en 278-förfrågan (005010X217), varje artikel en patienthändelse. Var och en bär det som PAS namnger för den: gransknings typen (extension-serviceItemRequestType, UM01: hälsovårdstjänster, inläggning eller specialistvård), certifieringstypen (extension-certificationType, UM02), tjänsttypen, tjänstestället (UM04), tjänstens nivå (extension-levelOfServiceCode, UM06: valfri, brådskande eller akut; en stat-prioritet står för brådskande), datum, inläggningsgranskningens inläggnings- och utskrivningsdatum, diagnoserna, vårdteamets leverantör som ska utföra tjänsten och förfarandet och kvantiteten, som en professionell (SV1) eller, på en institutionsanspråk, en sjukhus (SV2) tjänstelinje. 278-svarets åtgärdskod och auktorisationsnummer blir artikelnas granskningsåtgärd: certifierad, delvis eller ändrad, avslagen, väntande, avbruten eller inte övervägd (väntande för en granskare, med avvisningsorsaker). Lokala regler konsulteras inte.
perfuse serve -fhir -pas -pas-278-url https://um.example/x12/278 -pas-278-receiver ACMEUM \
-pas-278-token-env UM_TOKEN
Ett UM-system som väntar först och beslutar senare skickar sitt senare 278-svar till POST /fhir/Claim/$decide-278; varje händelse matchas till sin begäran med spårningsnumret Perfuse skickade, och beslutas som $decide skulle besluta om det. Om UM-systemet inte kan nås, eller svarar med något som inte är ett 278-svar, väntas varje artikel för en granskare och leverantören meddelas endast det; orsaken är i serverloggen.
Förfrågningar som UM-systemet svarar
En leverantörs $inquire måste hitta en auktorisering oavsett hur den begärdes: via fax, genom försäkringsgivarens portal, via telefon eller i en 278 som en annan avsändare skickat. Perfuse håller endast de begäranden som kom genom den; UM-systemet håller alla. Så med ett UM-system som svarar i realtid (varje transport utom sftp), skickas varje $inquire också dit som en 278 förfrågan (005010X215: BHT02 28, medlemmen, leverantören, auktorisationsnumret från Claim's insurance.preAuthRef när det finns ett, och händelsedatum från billablePeriod eller tjänsternas servicedatum, annars ett år före eller efter idag). Varje auktorisering som svaret innehåller som Perfuse inte gör (matchad av spårningsnumren den skickade och auktorisationsnumren den redan gett) kommer tillbaka som en till Claim Inquiry Response Bundle: UM-systemets beslut för varje tjänstelinje, auktorisationsnumret och perioden, och en anteckning som säger var den hittades. Inga Claim skapas för en auktorisering som ingen skickat i FHIR: dess ClaimResponse.request bär en data-frånvaro-anledning, som PAS-profilen tillåter. En förfrågan läser endast; ingenting i Perfuses egna register ändras. Om UM-systemet är ned eller svarar med en TA1 eller 999, får leverantören det som Perfuse har, och länkens status säger varför. Formen följer 278 förfrågans companion guides som UnitedHealthcare, Cigna och Blue Cross Blue Shield of Massachusetts publicerar; den har inte testats mot ett riktigt UM-system.
Hur 278:orna når UM-systemet
UM-systemets anslutningsguide säger hur det tar 278:or, och -pas-278-transport (Inställningar, Betalare, Användningshantering länk) följer det:
| Transport | Vad som skickas | Autentisering |
|---|---|---|
x12 (standard) | 278 skickas som application/edi-x12; svaret är svarstexten | En bärtoken, OAuth, HTTP Basic, ett klientcertifikat |
core-soap | CAQH CORE realtidsskydd 1.2 omslag (COREEnvelopeRealTimeRequest, payloadtyp X12_278_Request_005010X217E1_2, eller X12_278_Request_005010X215 för en förfrågan): Anslutningsregel vC2.2.0 med payloaden i omslaget, som de flesta försäkringsgivare och CMS esMD kör, eller -pas-278-core-version C4.0.0 med payloaden som en MTOM-bilaga | vC2.2.0: ett användarnamn och lösenord (WS-Security UsernameToken) eller ett klientcertifikat. vC4.0.0: ett klientcertifikat och en OAuth-token |
core-mime | CAQH CORE vC2.2.0 HTTP MIME multipart omslag, payloaden som en fildel | Omslagets UserName och Password, eller ett klientcertifikat |
sftp | Varje 278 placeras i en mapp på UM-systemets SFTP-server (-pas-278-sftp, -pas-278-sftp-outbound); svaren samlas in från en annan (-pas-278-sftp-inbound, varje -pas-278-sftp-every) | En SSH-nyckel eller lösenord; serverns nyckel måste finnas i -pas-278-sftp-known-hosts |
Ett klientcertifikat är -pas-278-cert och -pas-278-key; -pas-278-ca litar på en betalares egen certifikatutfärdare. OAuth är -pas-278-oauth-token-url, -pas-278-oauth-client-id och hemligheten, hämtad med klientautentiseringsbidrag och behålls tills en minut innan den går ut. Lösenord, token och hemligheter är aldrig flaggor: var och en namnges av en miljövariabel (-pas-278-password-env, -pas-278-token-env, -pas-278-oauth-secret-env, -pas-278-sftp-password-env), eller skrivs in i inställningsskärmen, där den sparas i inställningsfilen (läsbar av serverkontot endast) och visas aldrig igen.
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
Över SFTP väntar varje begäran tills svaret anländer: 278-svaret bestämmer objekten, och Perfuse placerar en 999 som accepterar den i utgående mappen. En fil som inte kan läsas stannar i inkommande mappen för en person och erbjuds igen vid nästa läsning.
När UM-systemet inte kan läsa en begäran
Ett UM-system som inte kan läsa en 278 svarar med en TA1 (omslaget) eller en 999 (transaktionen) istället för ett beslut. Perfuse läser vilken och vad den säger, väntar på varje objekt ("användningshantering kunde inte läsa begäran"), och registrerar den. Betalare, CMS-0057, Granskningskö visas länken: vad som skickades under de senaste sju dagarna, varje samverkan med dess kontrollnummer, och vad som hände med den (besvarad; erkänd, svar att komma; avvisad, med 999-segment, element och kod; inte nådd). Varje samverkan har sitt eget kontrollnummer, ett mer än det sista, som är vad en TA1 eller 999 namnger när den svarar.
16.10.4 Avgörande baserat på kliniska bevis, med en beslutsfunktion
En regelfil beslutar genom tjänstekod: en kod behöver ingen auktorisering, är inte täckt eller skickas till en granskare. Om denna patient uppfyller kriterierna för det är en annan fråga, som besvaras från villkor, enkätssvar och dokument som leverantören skickade med begäran. Med -pas-decider-url skickas varje punkt som reglerna lämnar till en granskare först till ett beslutsstöd, såsom Vaglio, som läser samma PAS-begäran genom Perfuses publicerade pas-paket. En offentlig Vaglio, endast för påhittade begäran, körs bredvid Perfuses testinstans på https://vaglio.perfuse.health:8443 (logga in som demo, lösenord try-vaglio-demo; den kan se allt och ändra ingenting): varje beslut där har sin bevis, ett tydligt språkbreve och en kvittens som vem som helst kan kontrollera.
perfuse serve -fhir -pas -crd-rules payer-rules.yaml -pas-decider-url https://vaglio.example/api/pas/decide \
-pas-decider-token-env VAGLIO_TOKEN
URL:en måste vara https eller vanlig http till den här datorn (localhost, 127.0.0.1), eftersom den bär en patients journal och token. Vaglio själv svarar endast på https; när den använder ett certifikat från sin egen myndighet, ange myndigheten med -pas-decider-ca DATA/tls/ca.crt (eller någon annan intern myndighet som tjänstens certifikat kommer från). Tjänsten skickas begäran Bundle som leverantören skickade den, POST <url>?item=<sequence> (application/fhir+json), och svarar {"decision": "approve" | "deny" | "pend", "why": "...", "requested": ["..."]}, eller 404 när den inte fattar något beslut för den här posten, vilket lämnar reglernas svar stående. why är svarets processanteckning och krävs för ett avslag, som annars skjuts upp; requested sägs till leverantören som den information som en uppskjuten begäran behöver. Ett uppskjutande kan också innehålla "questionnaire": "<canonical>" och "attachments": ["<LOINC>", ...], som begärs i svarets CDex Task och CommunicationRequests bredvid vilken DTR-frågeformulär eller bilagor som regeln begär (regelns frågeformulär vinner, eftersom en uppgift begär en; en kod som inte är LOINC:s form skjuts bort och loggas). En regel som godkänner eller avslår är betalarens täckningspolicy och skickas inte till tjänsten. Ett fel, en tidsgräns eller ett svar som inte är ett av de tre besluten skjuter upp posten för en granskare, med orsaken i serverloggen: ingenting här förvandlar ett fel till ett godkännande. Det kan inte kombineras med -pas-278-url, där UM-systemet svarar på varje post.
Råd innan du skickar in. Med -crd-advisor-url bredvid -crd-rules, frågar CRD också ett beslutsstöd vad en förhandsauktoriseringsbegäran för varje beställning som behöver det skulle bli tilldelad medan journalen förblir oförändrad, och visar svaret som ett tilläggsalt: "Innan du skickar in: en begäran om detta skulle behöva: ...", eller "skulle bli godkänt", med vad som fortfarande behövs, enkäten som begär det och vad som skulle godkänna det. Vaglio svarar på /api/pas/advise, med samma token och myndighet som ovan:
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 skickar POST <url> med {"service": {"system": "...", "code": "..."}, "resources": [ ... ]}, där resurserna är hookens förväntade data (patienten först, täckning utelämnad), och läser {"decides": true, "answer": "approve" | "pend" | "deny", "summary": "...", "missing": [...], "questionnaire": "...", "toApprove": [[...]], "policyTitle": "..."}. Det är råd och ändrar ingenting: täckningsinformationen, de andra korten och PAS-beslutet är vad reglerna säger. Det väntar i högst tre sekunder, och inget svar, ett fel eller "decides": false lämnar svaret exakt som det är utan det. Perfuse behöver aldrig en besluts-tjänst.
Begäran bär X-PAS-Request-Id, id som svaret känns igen av. En tjänst med egna granskare som väntar en punkt kan skicka sitt beslut senare som vilken granskare som helst: Claim/$decide med det id som claimResponse, punktens sekvens och beslutet och orsaken. Leverantörens prenumeration levererar det som den skulle en som gjorts i granskningskön.
En prenumeration med id-only-innehåll berättar för leverantören vilket svar som ändrades utan att säga vad det är: meddelandets fokus är Bundle/<id>. GET /fhir/Bundle/<id> returnerar det senaste PAS-svars-paketet, GET /fhir/Bundle/<id>/_history/<n> versionen som ett meddelande skickade, och GET /fhir/ClaimResponse/<id> ClaimResponse ensam. En token bunden till en patient berättas att de inte existerar, som för vilken som helst post utanför dess patient.
Verifierad med den officiella Inferno PAS Server v2.2.1-sviten (se verifiering). Inte skickad, även om PAS markerar dem som måste stödjas: ClaimResponse.adjudication med en granskningsåtgärd, ClaimResponse.extension:authorizedProvider och ClaimResponse.item.extension:communicatedDiagnosis, eftersom tilläggen de behöver inte tillåts där av deras egen kontext i PAS 2.2.1 och valideraren avvisar ett svar som bär dem; och request.extension:DataAbsentReason, eftersom Perfuse alltid vet begäran. De 278 som skickas till ett användningssystem (ovan) kontrolleras mot PAS 2.2.1:s egna begäransexempel, CMS:s publicerade esMD 278-exempel och en 278-kontroll skriven från offentliga kompanjonsguider, och varje transport mot ett ställföreträdande UM-system skrivet från CAQH:s anslutningsregler (se verifiering); inte ännu mot ett riktigt UM-system eller clearinghus, och inte CORE-certifierad. Inte implementerad: bilagor som skickas tillbaka med CDex.
En regelfil kontrolleras mot CRD:s egna invarianter när den laddas: en enkät behöver dokumentation, en tjänst som inte är täckt kan inte behöva auktorisering, satisfied tillhör ett fall och inte en regel, och allt villkorligt måste ge en orsak.
Ej verifierat: exporterna och medlemsmatchning mot en annan betalares implementering, måtten mot en betalares publicerade siffror, och CRD mot en riktig EHR:s CDS Hooks-klient.
16.11 Skicka förfrågningar om tidigare auktorisationer till en betalare (för vårdgivare)
Allt ovan svarar på förfrågningar, som en betalare. En vårdgivares sida är tvärtom: en EHR eller en DTR-app bygger en Da Vinci PAS-förfrågnings-paket, och något måste skicka det till betalaren, behålla svaret och skicka det vidare. En pas-destination gör det.
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
Varje meddelande måste vara en hel PAS-förfrågningspaket på en rå kanal. Perfuse skickar den oförändrad till {payer}/Claim/$submit: betalaren beslutar om anspråket tillsammans med patienten, täckning och stödresurser i paketet, och ett anspråk som byggts om från en sammanfattning skulle förlora dem. Utanför denna maskin måste betalarens adress vara https.
Ett beslut är en levererad begäran, oavsett vad den säger. Ett godkännande, ett avslag och ett pend är alla registrerade och ingen återförsöks, eftersom återförsök av ett avslag skickar samma begäran två gånger. Vad som misslyckas med leveransen och återförsöks är en betalare som inte har fattat något beslut: ett felstatus, ett OperationOutcome (dess text är felet) eller ett ClaimResponse vars resultat är error. Beslutet läses punkt för punkt från PAS-granskningsåtgärdskoderna (X12 306: A1 godkänt, A2 delvis, A3 avslaget, A4 penderat, A6 ändrat); ett svar utan kod listas som "ingen besluts kod" snarare än att det tas som ett godkännande. Ett avslag utan anledning någonstans avvisas som inte uppfyller CMS-0057.
Betalarens svar är destinations-svaret, så Granska svaret kan bedöma det, och results_to lämnar det till en annan kanal. Varje förfrågan listas på CMS-0057, Förfrågningar skickade till betalare: när den skickades, patienten, tjänsten, beslutet och betalarens referens (preAuthRef), som en senare förfrågan namnger. Listan sparas i prior-auth.json bredvid databasen (högst 10 000 förfrågningar; de äldsta beslutade förfrågningarna först, en pendlad förfrågan aldrig), och varje hyresgäst ser endast sin egen.
Verifierad mot HL7 Da Vinci PAS-betalare-referens-implementeringen (docker-bild hlseven/davinci-prior-auth): en förfrågan som skickats genom en igång-kanal pendlas av den med dess referens, och svaret visas på skärmen (se verifiering). Inte ännu testad mot en produktions-betalare. Inte byggd: att följa upp en pendlad förfrågan med $inquire, eller att ta emot betalarens senare svar genom prenumeration; en kanal kan göra båda idag med en http- eller fhir-destination.
16.12 CMS-justerade nätverk
CMS Interoperability Framework (CMS Health Technology Ecosystem) ber hälsodata-nätverk att självintyga till 26 kriterier och listas som CMS Aligned Networks; EHR:er, leverantörer, betalare och appar ansluter till dem. Kriterierna 13 till 16 har varit i kraft sedan den 4 juli 2026: FHIR-API:er på US Core med en full CapabilityStatement och Bulk Data, dokument som mänskligt läsbara FHIR-bilagor, mötes- och mötesmeddelanden via FHIR-prenumeration, och en postlokalisator.
Administrera › CMS Aligned Network listar varje kriterium med vad Perfuse tillhandahåller för det och var den här servern står, läst från vad som är aktiverat här:
| Status | Betydelse |
|---|---|
| Klart här | Perfuse tillhandahåller det och det är på. |
| Klart, med ett gap | Det är på, och en del av kriteriet ligger utanför det (namnges på skärmen). |
| Byggt, inte på | Perfuse tillhandahåller det; skärmen namnger inställningen eller flaggan som aktiverar det. |
| Ditt att göra | Organisationens del: ett avtal, en certifiering, publicering till National Provider Directory. |
| Inte byggt | Programvara skulle göra det, och Perfuse gör det inte. |
Vad de fyra som är i kraft behöver från den här servern:
| Kriterium | I Perfuse | Aktivera |
|---|---|---|
| 13 FHIR-API:er, US Core, Bulk Data | FHIR-slutpunkten med dess CapabilityStatement och $export | -fhir, -fhir-bulk-export |
| 14 Dokument som FHIR-bilagor | DocumentReference med Binary och IHE MHD över XDS-registret | -fhir (MHD också -xds) |
| 15 Mötes- och mötesaviseringar | Ämnesbaserade prenumerationer (R5 Backport för R4) från ADT- och SIU-flöden | -fhir-subscriptions |
| 16 Postlokalisator | XDS.b-registret, XCA för andra samhällen, PIXm | -xds, -xds-home-community |
Skärmen är ett arbetsblad för intygandet, inte en certifiering: CMS granskar nätverk som misstänks inte uppfylla kriterierna, och ramverkets egen text är auktoriteten. Inte byggt idag: öppna kvalitetsgapfrågor (kriterium 8), en utbetalares fråga för en anspråks mötesdata (9), rapporteringsfrågemått till National Provider Directory (19), kontroll av leverantörer mot den katalogen (6), läsning av mobila körkort eller digitala försäkringskort (3, 23), och tillämpning av en allmän samtyckespolicy för varje läsning (5). IAL2-identitetsverifiering är identitetstjänstens; Perfuse accepterar token från den du väljer.
17 Säkerhet
Perfuse hanterar kliniska data. Detta kapitel beskriver vad den gör åt det och vad den lämnar till dig.
17.1 Transport-säkerhet
TLS på webbgränssnittet konfigureras med -tls-cert och -tls-key. Utan dem är gränssnittet vanligt HTTP, vilket är acceptabelt på en loopback-adress för en första titt och ingen annanstans — det bär autentiseringsuppgifter och meddelandeinnehåll, båda läsbara på ledningen.
TLS på kanaltransporter är per källa och per destination, under en tls-block. De tillgängliga inställningarna finns i käll och destination-referenserna.
insecure_skip_verify accepterar alla certifikat. Det finns eftersom sjukhusystem rutinmässigt presenterar certifikat som inte kommer att verifieras, och att vägra att ansluta skulle innebära att vägra att integrera. Det är namngivet för att vara iögonfallande, och att använda det innebär att anslutningen är krypterad men inte autentiserad — du har skydd mot passiv avlyssning och inget mot en inplacerad server.
17.2 Autentisering och roller
Användare hålls i databasen. Var och en har en av fem roller, och varje roll innehåller allt i de ovanför det:
| Roll | Kan |
|---|---|
| Övervakare | Se om allt fungerar: kanalstatus, antal, flödeskarta, larm, instrumentpaneler, mått och könans djup. Inga meddelandeinnehåll, kanalfiler eller köade meddelanden. |
| Visare | Kan också läsa meddelanden, kanalfiler, spår och aktivitetsloggen. |
| Operatör | Kan också återsända: ombehandla ett meddelande, upprepa en kanal och försöka leverera köade meddelanden igen. |
| Redaktör | Kan också skapa och ändra kanaler, och köra jämförelser. |
| Administratör | Kan också starta och stoppa kanaler, rensa köer och hantera personer, token och serverns inställningar. |
En sjätte roll, Plattform, tillhör den som kör en delad server: den skapar hyresgäster och ställer in deras begränsningar, och har inga kanaler av sig själv.
Övervakning är för en hjälpdisk eller för en driftsskärm på en vägg: allt som behövs för att se att en feed har stoppats, och ingenting som namnger en patient. Visare kan läsa meddelandeinnehåll, som är kliniska data; det är en lågprivilegerad roll för *konfiguration*, inte för sekretess. Operatör separerar åtgärdandet av en misslyckad leverans på natten från ändringen av vad en feed gör: personen som återsänder behöver inte kunna om skriva kanalen.
17.2.1 Upprepade felaktiga lösenord
Felaktiga lösenord och misslyckade passkys-signningar räknas från den adress som anslutningen kommer från, och efter ett fåtal i rad väntar den adressen innan den får försöka igen (svaret är 429, med Retry-After). Konton låses inte av namn, eftersom det skulle tillåta vem som helst att låsa ut en administratör med flit.
Adressen är anslutningens egen, aldrig den som en begäran hävdar i X-Forwarded-For, som avsändaren skriver. Bakom en omvänd proxy på samma maskin använder Perfuse den sista X-Forwarded-For-posten istället, den som proxyn lade till, så att varje klient fortfarande räknas separat. En proxy på en annan maskin når Perfuse från en adress, och alla dess klienter delar en räkning: begränsa inloggningar vid den proxyn också.
17.2.2 Kanalgrupper
En person (eller en API-token) kan begränsas till vissa kanalgrupper: de ser och agerar då endast på de kanaler vars group är en av deras. Detta är arrangementet för en sjukhusgrupp på en server, där varje anläggnings analytiker ansvarar för sina egna flöden och ett centralt team, utan begränsning, ansvarar för alla. Rhapsody kallar det för en låda.
Begränsningen gäller överallt på en gång, eftersom den tillämpas på begäran snarare än att kommas ihåg av varje skärm: kanallistan, instrumentpanelen och flödeskartan, meddelanden och deras sökning, räkningar och diagram, kön, varningar, mått, certifikat, kontrakt och koduppsättningsanvändning. En kanal utanför personens grupper existerar inte för dem; att begära den med namn svarar *hittades inte*, så dess namn bekräftas inte heller. En kanal med ingen grupp ses endast av personer med ingen begränsning.
Att spara en kanal håller den inom personens grupper: de kan inte skapa en kanal i en annan grupp, eller flytta en ut ur sin egen. Det som varje anläggning delar - kodtabeller, skriptbibliotek, förauktoriseringsbeslut - kan de läsa men inte ändra. Serveromfattande siffror (förauktorisering, tokenanvändning, tunnlar) visas endast till personer med ingen begränsning, och så är mått och varningar om hela servern snarare än en kanal.
En administratör begränsad till grupper är en anläggningens egen administratör. De hanterar personer och token i sina grupper, startar och stoppar sina kanaler och rensar sina köer. En kollega de lägger till får deras grupper om de inte namnger några av dem, de kan inte ge en grupp de inte har, och de ser eller ändrar aldrig någon med ingen begränsning. Allt annat en administratör kan göra ändrar hela servern - inställningar, inloggning, omstart, varningsregler, varumärke, flotta, SMART-servern - och nekas till dem.
Grupper ställs in i Användare (och för token i Token), som en kommaavgränsad lista. Varje ändring spelas in i aktivitetsloggen och träder i kraft vid personens nästa begäran.
En annan roll i varje grupp
En person kan ha en annan roll i varje grupp de tillhör: lab=editor, adt i Användare redigerar labbens kanaler och har den roll som valts bredvid den - säg visare - i admissionsgrupperna. De ser båda gruppernas kanaler på varje skärm. Spara, starta eller skicka om en kanal i en grupp där deras roll är för låg nekas med den roll de har där; det låtsas inte att kanalen saknas, eftersom de kan se den. Deras roll högst upp på skärmen är den starkaste de har, vilket öppnar de skärmar som rollen använder, och varje åtgärd på dessa skärmar är fortfarande begränsad till de grupper där de har den rollen.
Endast personer begränsade till kanalsgrupper kan ha en. Någon som ser varje kanal har en roll, eftersom "redaktör för labbens kanaler" för en person med ingen begränsning skulle vara redaktör för allt som tillhör ingen grupp, och för serveromfattande sidor. En anläggningens administratör kan ge en roll per grupp endast i grupperna de administrerar, och aldrig ovanför sin egen roll där.
17.3 Vem som får anropa FHIR-slutpunkten
FHIR-slutpunkten (serve -fhir) kontrollerar en av två typer av token:
- Perfuse API-nycklar, skapade under Användare → Maskinreferenser eller med
perfuse token create. Var och en har en roll och kan
begränsas till FHIR-grupper. Detta är standard när ingen SMART-autentiseringsserver är konfigurerad.
- SMART-åtkomsttoken, från Perfuses egen autentiseringsserver (
-smart-clients) eller en extern (-smart-issuer). Var och en
har omfång och slutpunkten håller varje begäran till dem.
Med SMART konfigurerat accepteras endast SMART-token, så varje anropshavare hålls till dess omfattningar. En API-token har en roll och inga omfattningar: en visartoken kan läsa varje patients journal. En utbetalare som aktiverade SMART för att begränsa varje app till vad den beviljades bör inte ha en väg in som inte är begränsad.
Vissa webbplatser behöver båda samtidigt - en intern anspråksfeed som håller en API-token och har ingen SMART-klient, bredvid medlemsappar som loggar in via SMART. För dem låter Inställningar → FHIR → Acceptera Perfuse API-token bredvid SMART-token (-fhir-api-tokens vid start) API-token komma in också. Det är avstängt som standard, det träder i kraft vid nästa begäran i antingen riktning, och ändringen skrivs till revisionsloggen. En token skiljs åt av dess form: en SMART-token är en signerad JWT, och en API-token är aldrig det, så en är aldrig kontrollerad som den andra. Där du kan, ge ett sådant system en SMART Backend Services-klient istället, med endast de systemomfattningar det behöver.
17.3.1 En FHIR-slutpunkt som är öppen för främlingar
En offentlig testserver delar ut autentiseringsuppgifter som kan skriva, eftersom testning av föregående auktorisering eller prenumerationer kräver skrivbehörighet. Två begränsningar förhindrar att en klient förstör det för alla andra, båda under Inställningar → FHIR och båda inaktiverade som standard:
- Skriver en minut från en klient (
-fhir-writes-per-minute): skapar, uppdaterar och tar bort från en klientadress. Över detta, svaras en skrivning med 429 ochRetry-After: 60. Läsningar och sökningar, inklusive sökningar via POST, räknas aldrig. - Flesta resurser som hålls (
-fhir-max-resources): förbi detta, nekas nya resurser med 507, medan uppdateringar och borttagningar fortfarande fungerar.
En sjukhus egen slutpunkt behöver varken.
17.4 AI-agenter: MCP-servern
Med Inställningar › Säkerhet › AI-agenter (MCP) aktiverat (eller serve -mcp), servar Perfuse Model Context Protocol på /mcp, så att en AI-agent som Claude, ChatGPT eller en IDE-assistent kan fråga vad som händer. Det är avstängt som standard, och att stänga av det stoppar varje agent vid dess nästa anrop.
En agent ansluter med en API-token från Administrera › Användare › Maskincredentier som en bearer-token, aldrig med en persons webbläsarsession (detta nekas, så en agent agerar aldrig med en persons fulla åtkomst). En klientkonfiguration ser ut så här:
{ "mcpServers": { "perfuse": { "type": "http", "url": "https://perfuse.example/mcp",
"headers": { "Authorization": "Bearer <token>" } } } }
| Verktyg | Roll | Vad det gör |
|---|---|---|
server_status, list_channels, queue, alerts | övervakare | Om saker fungerar, utan meddelandeinnehåll |
get_channel, search_messages, get_message, find_patient, fhir_search | vyare | Kanaler, meddelanden (med innehåll), en patients meddelanden över format, en FHIR-sökning |
retry_delivery, reprocess_message | operatör, och mcp:write | Försök leverera en köad leverans, skicka ett meddelande genom dess kanal igen |
start_channel, stop_channel | administratör, och mcp:write | Starta eller stoppa en kanal |
Varje verktyg besvaras av samma ruta eller FHIR-sökning som en persons skärm använder, anropad med agentens egen token, så tokenens roll, kanalgrupper och hyresgäst bestämmer vad den ser, exakt som de gör i konsolen; och fhir_search får tokenens egen åtkomst på FHIR-slutpunkten (som kan neka API-token helt; se FHIR-avsnittet ovan). En agent erbjuds endast de verktyg som dess token kan använda. Läsning är standard: ett verktyg som ändrar något behöver också tokenens mcp:write-omfång ("Låt en AI-agent agera med det" när token utfärdas), så en token utfärdad för en rapporteringsagent kan inte övertalas att agera av en prompt. En övervakningstokens svar har meddelandeinnehåll borttaget, oavsett vad en ruta returnerar.
Varje anrop är i Activity som mcp.tool med token-namn, verktyget, dess argument och resultatet (ok, refused, invalid, rate-limited eller HTTP-status); mcp.connect registrerar vilken klient som anslöt. Varje token kan göra 60 verktygsanrop per minut (Verktygsanrop per minut från en token); över det svaras ett anrop med ett fel som agenten kan läsa, och ingenting görs. En begäran från en webbläsarsida på en annan ursprung nekas, vilket MCP ber en server att stoppa DNS-omdirigering. Transporten är MCP:s strömbara HTTP, som svaras som JSON utan händelseström; protokollversioner 2025-06-18, 2025-03-26 och 2024-11-05 accepteras. Meddelanden och FHIR-resurser innehåller patientdata: en agents svar går till den modell det körs på, så ge en token till en agent endast där den modellen har tillåtelse att se dem, och ge den den lägsta rollen som gör jobbet.
17.5 En demonstrationskonto
serve -demo-account demo:PASSWORD skapar ett delat konto för en offentlig demonstrationsserver, och inloggningssidan visar dess användarnamn och lösenord med en knapp som loggar in med dem. Kontot är en visare, så den kan titta på allt och ändra ingenting. Till skillnad från alla andra visare kan den också öppna administratörsskärmar (användare, maskintoken, inställningar, dataskydd, flottans peer), skrivskyddat: en demonstration bedöms av dess skärmar. Den läser dem som en visare läser kanaler, med varje autentiseringsuppgift visas som inställd eller inte, aldrig dess värde, och varje ändring nekas. Den kan också trycka på kontroller som inte ändrar något och någonstans utanför servern: ett skripts Kontroll, och kanalredigerarens validera och pars. Den kan inte ändra sitt lösenord eller lägga till en passnyckel,för att den första besökaren som gör något av dem skulle låsa ut alla efter dem. Varje start sätter tillbaka den som en visare med det publicerade lösenordet. Lösenordet måste vara minst 12 tecken, som alla andra. Använd det bara på en server som innehåller testdata: vem som helst som läser inloggningssidan kan läsa varje meddelande på servern.
17.6 Granskning
Konfigurationsändringar, inloggningar och åtkomst till meddelandeinnehåll spelas in med vem, vad och när.
Granskningsloggen är i samma databas som meddelandena. Det är bekvämt och det är en begränsning: någon som kan ändra databasen kan ändra granskningsloggen. Om dina krav inkluderar granskningsbevis, behöver loggen skickas någonstans append-only, och Perfuse eget loggutdata är sättet att göra det.
17.7 Hemligheter i konfiguration
Lösenord, passkoder och nycklar visas i kanalkonfiguration, vilket betyder att de är i YAML-filerna.
Två konsekvenser. Filerna behöver filsystembehörigheter som återspeglar vad de innehåller, och om de är i versionskontroll — vilket annars rekommenderas — innehåller lagret autentiseringsuppgifter och måste behandlas därefter.
Där ett värde är en hemlighet, återger gränssnittet det som en hemlighet och API:et returnerar det inte när det har sparats. Det skyddar det från att läsas över någons axel eller läckas i en skärmdump. Det skyddar inte filen.
17.8 Vad som finns i databasen
Meddelandebufferten innehåller meddelanden som mottagits, vilket för en klinisk feed innebär patientidentifierbara data. Den bör finnas på krypterad lagring, säkerhetskopieras som kliniska data med den kvarhållning som det innebär och åtkomstkontrolleras på filsystemnivå samt via Perfuses egna roller.
cleanup.periodDays begränsar hur länge den sparas. Se meddelandebufferten för spänningen mellan det och att ha tillräckligt med historia för rytmmedveten varning.
17.9 Dataskydd (GDPR och UK GDPR)
Skärmen Dataskydd (Administrera, endast administratörer) besvarar en persons begäranden enligt GDPR och UK GDPR. Den beslutar ingenting på kontrollantens vägnar: om en begäran måste beviljas och om ett undantag gäller, är kontrollantens beslut, registrerat med begäran.
Hitta vad som finns. En person identifieras med identifierare: system|value (ett NHS-nummer, ett MRN med dess tilldelande myndighet) eller ett nummer på egen hand. Med en patientindex utökas dessa till varje nummer för varje post som är länkad till samma person, så en begäran som citerar ett sjukhusnummer hittar posterna som är arkiverade under de andra. Se vad som finns söker sedan igenom varje butik som lagrar patientdata:
| Lagringsplats | Hittad av |
|---|---|
| Meddelanden | identitetsindexet (Inställningar → Data → Indexera patientidentifierare); utan det kan meddelanden inte hittas med identifierare |
| Leveranskö | genom att läsa varje köad meddelandes identifierare |
| FHIR-lagret | Patientresurser som bär en identifierare och varje resurs vars indexerade referenser pekar på en |
| Tidigare auktorisationsbegäran | identifierarna för begäran om patienten |
| Patientindex | identifieraren eller EUID |
Vad den inte kan nå säger den: spår som skickas till en insamlare (-trace-endpoint), granskningsloggen (sparad: den är en post om vem som gjorde vad, inklusive denna begäran), och säkerhetskopior.
Begäran. En begäran registreras med dess typ (åtkomst, artikel 15; överförbarhet, artikel 20; radering, artikel 17; begränsning, artikel 18), vem den är från enligt registerförarens register, identifierare och en anteckning (hur identiteten bekräftades, en förlängning och dess orsak). Den ska besvaras en månad efter mottagandet (artikel 12(3)); en försenad begäran visas i röd färg.
- Tillgång och portabilitet: Ladda ner kopian ger en zip: varje meddelande som
mottagits med dess post, varje FHIR-resurs med varje lagrad version, tidigare auktoriseringsbegäran och deras svar, och patientregistrets poster, JSON genomgående, med en README som förklarar vad varje del är. Markera som besvarad stänger det.
- Radering: en andra administratör godkänner det (den som registrerade det kan inte).
Radera nu tar bort allt som hittas: meddelanden i sin helhet (post, brödtext, leveranser, identifierare, bilagor som ingen annan meddelande använder), köade leveranser (de skickas inte), FHIR-resurserna med deras historia, tidigare auktoriseringsbegäran med deras svar, bilagor och spårningsnummer, och personen i patientregistret med varje länkad post och dess historia (en händelse registrerar att en radering skedde, och av vem).
- Begränsning: registreras som en rättslig kvarhållning, så ingenting raderas eller går ut medan
den varar.
- Avslå stänger en begäran med dess orsak, som personen måste informeras om.
En stängd begäran behåller endast de sista tecknen i personens nummer: den stannar som en post om ett svar utan att vara en annan kopia av dem. Varje steg är i granskningsloggen med numren maskerade.
Lagring av rättsliga uppgifter. En lagring av rättsliga uppgifter namnger en person med identifierare, med dess orsak och ett valfritt slutdatum. Medan den är i kraft avvisas en radering helt, och meddelandestorens kvarhållningsfönster sparar personens meddelanden (poster och kroppar) tills lagringen av rättsliga uppgifter upphävs.
Säkerhetskopior och raderingslogg. En säkerhetskopia som gjorts före en radering innehåller fortfarande det som raderades tills den går ut. Varje radering skrivs till en logg: när, av vem, godkänd av vem, hur mycket som togs bort från varje lagringsplats och personens identifierare som saltade SHA-256-hasher i stället för i klartext. Efter att en säkerhetskopia har återställts, hasher Tillämpa raderingar igen identifierarna som de återställda lagringsplatserna innehåller med varje posts salt och raderar varje person som loggen namnger. Korta nummer kan hittas från deras hasher genom att prova varje värde, så loggen är i sig personuppgifter och hålls med databasens egen skyddsnivå.
Kvarhållning. Skärmen visar hur länge varje typ av post sparas här och vad som ändrar den: meddelandeposter och kroppar efter deras kvarhållningsfönster, kön tills den levereras eller tas bort, FHIR-lagringen, tidigare auktoriseringsbegäran och patientindex tills den raderas (kliniska poster raderas inte enligt en schemalagd tid), granskningsloggen sparas.
Bearbetningsregister (Artikel 30). Bearbetningsregister laddar ner, som Markdown eller CSV, vad den här servern känner till om det: kontrollanten, dataskyddsombudet och var data lagras (Inställningar → Data → Dataskydd), kvarhållningen av varje typ av post och en bearbetningsaktivitet per kanal med vad den tar emot, varifrån, till vilka destinationer och vilka värdar den skickar till. Syftena, lagliga grunder och kategorier av dataskyddsubjekt lämnas för kontrollanten att fylla i och säga till. En CSV-cell som börjar med =, +, - eller @ skrivs med en ledande apostrof, så ett kalkylblad inte kör den.
Var data lagras. Var data lagras (Inställningar → Data → Dataskydd) anger, i ord som en tillsynsmyndighet kan kontrollera, var servern, dess databas och dess säkerhetskopior körs; dataskyddsskärmen och posten visar det. En utkast till dataprocessavtal för organisationer som BioDream värd för finns i docs/legal/dpa-template.md; det är ett utkast för en jurist, inte juridisk rådgivning.
API är /api/privacy (sammanfattning), /api/privacy/find, /api/privacy/requests (och /{id}/approve, /{id}/export, /{id}/erase, /{id}/close), /api/privacy/holds, /api/privacy/reapply och /api/privacy/register.
17.10 Hyresgäster
En hyresgäst är en isoleringsgräns: kanaler, meddelanden, användare och inställningar tillhör en, och ingenting korsar.
Detta finns för en tjänsteleverantör som kör flöden för flera praktiker. Använd det inte för att separera avdelningar inom en organisation som behöver se varandras trafik: isoleringen är verklig och det finns ingen vy över flera klienter. För det, använd kanalgupper (ovan), som delar in människor i en organisation medan en central grupp kan se allt.
17.10.1 Begränsningar
En plattformsoperatör ställer in varje hyresgästs begränsningar i Tenants, så att en kund inte kan tränga ut resten av en delad server. Lämna en begränsning tom för ingen.
- Kanaler: hur många kanaler en hyresgäst får ha. Att skapa en till nekas, med angivande av antal och gräns.
- Meddelanden per minut: hur många meddelanden dess kanaler tillsammans får ta emot per minut.
- Lagring: hur mycket lagrad meddelandeinnehåll den får behålla, i megabyte.
Ingen av dem förlorar ett meddelande. Över takten eller lagringsgränsen nekas ett mottaget meddelande på samma sätt som en upptagen mottagare nekar ett: MLLP får ingen bekräftelse (inte ett avslag, som vissa avsändare tolkar som "skicka inte om"), HTTP får 429 med Retry-After, SOAP får 503, DICOM får en återförbar status, och en kö, bucket eller fil lämnas där den var. Avsändaren skickar om, som varje gränssnittsmotor och EHR gör. Inget som redan lagrats raderas för att göra plats. En höjd gräns träder i kraft inom en minut, och varje ändring av gränser loggas i aktivitetsloggen.
17.11 Testdata
De genererade meddelanden som beskrivs i testing finns till viss del som en kontroll av integritet. Att reproducera ett problem på annan plats, skicka ett exempel till en leverantör eller fylla i en testmiljö är alla saker som annars görs med riktiga meddelanden.
Generatorns utdata innehåller inga patientdata genom konstruktion snarare än genom redigering. Föredra den framför handstrippade riktiga meddelanden, som är en process som kan göras ofullständigt och vanligtvis är.
17.12 Enkel inloggning
Tre mekanismer, och lokala konton bredvid alla.
OpenID Connect (-oidc), en katalog över LDAP (-ldap), och SAML 2.0 (-saml). Var och en konfigureras från Administrera → Inloggning och skrivs till filen som flaggan namnger, så skärmen och filen är två vyer av en sak snarare än två platser att hålla i takt.
Lokala konton är alltid tillgängliga och kan inte stängas av. Det är medvetet: en lokal integrationsmotor vars enda sätt in är en identitetsleverantör blir otillgänglig exakt när identitetsleverantören är otillgänglig, och en klinisk gränssnitt är inte en bra plats att lära sig det. Inloggnings-skärmen berättar hur många lokala administratörer som finns innan den uppmuntrar dig att förlita dig på något annat.
17.12.1 Vad en grupp-mappning bestämmer
Alla tre kartlägger grupper från katalogen till Perfuse-roller, och någon i grupper som matchar mer än en får den mest privilegierade. Det är den enda säkra riktningen att lösa det — alternativet är en person som förlorar tillgång de har rätt till för att de också är i en mindre grupp.
Valfri av de sex rollerna kan beviljas: övervakare, visare, operatör, redaktör, admin och plattform.
En grupp kan också begränsas till vissa kanalgroppper, i den andra rutan i dess rad (channel_groups i filen). När en grupp nämner någon, ställs varje inloggning in personens kanalgroppper från de grupper som beviljade deras roll: någon i en grupp som redigerar labbens kanaler och i en annan som visar varje kanal är redaktör för labbens kanaler och ingenting annat. Den starkaste rollen förenas aldrig med den bredaste räckvidden, eftersom ingen grupp beviljar det. En grupp med en tom ruta ger tvarje kanal. Medan ingen grupp namnger någon, lämnar inloggning kanalgroppper som en administratör ställt in dem i Användare.
När varje grupp en person matchar namnger kanalgroppper, får varje kanalgrop den starkaste rollen bland grupperna som namnger den: med Lab-Interfaces (redaktör, lab) och Clinical-IT (visare, lab och adt), redigerar personen labbens kanaler och visar admissionskanalerna, som om de ställts in för hand. När en av deras grupper ger varje kanal, finns det ingen lista för att hålla en roll per grupp, och regeln ovan gäller.
roles:
editor: [Lab-Interfaces]
operator: [Night-Desk]
viewer: [Clinical-IT]
channel_groups:
Lab-Interfaces: [lab, pathology]
Night-Desk: [adt]
Det är OpenID Connect- och SAML-filen. Katalogens fil mappar varje grupp till en roll (roles: {Lab-Interfaces: editor}), och channel_groups sitter bredvid roles där.
En mappning som inte ger någon någonting nekas i stället för att sparas. En konfiguration som autentiserar personer och vägrar alla ser ut som ett trasigt produkt från utsidan: rundresan slutförs och alla nekas utan att någonting förklarar varför.
Att skapa ett konto vid första inloggningen är avstängt som standard. Med det avstängt måste någon finnas i Perfuse innan de kan logga in, så katalogen bestämmer vem de är och Perfuse bestämmer vem som får komma in.
17.12.2 SAML, specifikt
Delarna som är värda att veta innan du konfigurerar det:
- Endast det certifikat du konfigurerar är betrott. Ett certifikat som skickas i en respons används aldrig. En angripare som kan skicka ett dokument kan också lägga till sitt eget certifikat i det, och en verifierare som läser det är någon som kan autentisera sig som vem som helst.
- En respons måste svara på en inloggning som den här servern startade. Perfuse minns den begäran den skickade och vägrar en respons som namnger något annat, eller namnger en begäran den redan har svarat på. Utan den här kontrollen är en giltig respons en bärartoken för vem som helst som har den: någon loggar in som sig själv, sparar responsen och skickar den till din webbläsare, och du är då inne på deras konto med granskningsloggen som registrerar deras namn.
- Inloggningar som startas hos identitetsleverantören är därför inaktiverade som standard. Aktivera *Acceptera inloggningar som startas hos identitetsleverantören* endast om du behöver en portalruta, och med vetskapen om att det är vad som gör ovanstående möjligt.
- Gruppattributet har inget standardvärde och är obligatoriskt. Entra skickar
groups, Okta skickar vad som helst som applikationen har konfigurerats med, ADFS skickar en anspråks-URI. En gissning skulle producera en inloggning som fungerar och ger ingen någonting. Om en inloggning vägras på grund av att den saknar roll, namnger serverloggen de attribut som anlände — vilket vanligtvis är hela svaret. - Svars-URL:en måste matcha exakt vad som är registrerat hos leverantören. En respons anger var den var avsedd att skickas och en som är adresserad till en annan plats vägras, eftersom att acceptera den skulle innebära att acceptera en respons som var avsedd för en annan tjänst.
17.12.3 Vad varje leverantör skickar
Gruppattributet är där inloggningar går fel, och de tre vanliga leverantörerna namnger det på olika sätt.
| Leverantör | Skickar vanligtvis | Anteckningar |
|---|---|---|
| Keycloak | groups | Behöver en gruppmedlemskarta som lagts till i klienten. |
| Entra ID | en anspråks-URI som slutar /claims/groups | Skickar gruppobjekt-ID om applikationen inte konfigurerats för att skicka namn. Mappa ID, eller ändra leverantör. |
| Okta | vad som helst som applikationen konfigurerats med | Vanligtvis groups, med ett filter som bestämmer vilka som skickas. |
| ADFS | en anspråks-URI | Underskrifter svar i stället för påstående, vilket Perfuse accepterar. |
En anspråks-URI kan anges genom dess sista segment: att skriva groups hittar http://schemas.microsoft.com/ws/2008/06/identity/claims/groups. Ett namn som bara slutar med ordet matchar inte — excluded_groups är inte groups.
Gruppmedlemskap som anländer som ett komma-separerat värde behandlas som ett enda gruppnamn och matchar ingenting. Det är den korrekta läsningen av standarden, och att dela på komma skulle innebära att en grupp som legitimitet innehåller en tyst blev två. Om det är vad din leverantör skickar, ändra det där.
Test på inloggnings-skärmen kontrollerar allt som kan kontrolleras utan en person: inställningarna, certifikatet och om en inloggning-begäran kan byggas. Den säger tydligt att den inte kan bevisa att någon kan logga in, eftersom det behöver en riktig påstående om en riktig person och det enda sättet att få en är att de försöker.
17.13 Konton som etablerats av identitetsleverantören: SCIM
Med -scim (Inställningar → Inloggning → Automatiska konton), skapar en identitetsleverantör som Okta, Microsoft Entra ID eller Google Workspace Perfuse-konton själv på /scim/v2/Users, så att en person som lämnar organisationen förlorar åtkomst när deras katalogkonto inaktiveras, inte när någon kommer ihåg. Leverantören autentiserar med en API-nyckel som innehåller admin-rollen, gjord under Användare → Maskincredentier, skickad som en bäraresymbol.
- Inaktivering av ett konto avslutar dess sessioner omedelbart, och servern kontrollerar att inga sessioner överlevde innan den svarar. En leverantör meddelas aldrig att ett konto har inaktiverats när det inte har gjorts, eftersom en leverantör inte försöker igen med något som den har informerats om att det lyckades.
- En borttagning inaktiverar först, sedan tar bort, så ett fel halvvägs lämnar ett konto som ingen kan logga in på. Revisionshistoriken för ett borttaget konto behålls.
- Rollen kommer från personens grupper eller roller, matchade efter namn: en grupp vars namn innehåller *admin*, *editor*, *operator*,
*viewer* (eller *read-only*) eller *monitor* ger den rollen, så APP-Perfuse-Editor och Perfuse Operators fungerar som de är namngivna. Allt annat får -scim-default-role, viewer om inte annat anges. Plattform kan aldrig beviljas på detta sätt.
- Inga lösenord. Ett konto som skapas av SCIM loggar in via identitetsleverantören; ett andra lösenord som ingen uppströms känner till skulle överleva en inaktivering där.
/scim/v2/ServiceProviderConfiganger vad som stöds: skapa, läsa, ersätta, patcha och ta bort Användare, och filter upp till 200
resultat. Bulkoperationer, sortering och ETags stöds inte.
17.14 Vad Perfuse inte gör
Det krypterar inte databasen i vila. Använd filsystem- eller volymkryptering.
Det hanterar inte sina egna certifikat eller förnyar dem. Ange sökvägen till filer och hantera dessa filer med det du redan använder.
SAML har verifierats mot två oberoende leverantörer, var och en med en riktig webbläsarinloggning, en riktig påstående och en riktig session: Keycloak 26 och Microsoft Entra. Två är mer än dubbelt så mycket som en, eftersom de två oenigas på ett sätt som visade sig vara viktigt — Keycloak skriver sin påstående med namnutrymmesprefix och Entra skriver samma element utan dem, och den enda defekten detta område har haft var i prefixhantering.
Börja med att läsa din leverantörs metadata. Inställningar, sedan Inloggning, sedan SAML-fliken: ange metadata-URL eller klistra in dokumentet, och inloggningsadressen och signeringcertifikatet fylls i automatiskt. Varje SAML-leverantör publicerar en av dessa — Okta, Entra, AWS IAM Identity Center, Keycloak, ADFS — och det är skillnaden mellan att konfigurera en leverantör och att skriva av en. Att göra det manuellt innebär att hitta certifikatet inuti XML, ta bort radbrytningarna ur base64 och lägga till PEM-rubriker, där ett enda felaktigt utrymme producerar ett signaturfel som inte säger något om formatering.
Vad som kommer tillbaka beskrivs snarare än dumpas: varje certifikats ämne, utgångsdatum och SHA-256-fingeravtryck, så att du kan kontrollera det mot vad din leverantörs egen konsol visar. Ett utgånget certifikat kallas utgånget snarare än att lämnas som ett datum att jämföra med ögonen. Ingenting sparas genom att läsa — att tillämpa det på formuläret är ett separat klick, eftersom ett dokument som någon klistrat in ännu inte är ett beslut om vad som ska lita på.
En metadata-URL hämtas över https endast, och adressen kontrolleras mot samma princip som styr kanaldestinationer, så detta kan inte användas för att få servern att läsa molninstansens autentiseringsuppgifter. Omdirigeringar följs inte, eftersom en tillåten adress som omdirigerar till en blockerad skulle gå rakt förbi den kontrollen.
Om du konfigurerar Entra, kommer fem saker inte att matcha vad exemplen visar dig. Det skickar ingen e-post-påstående alls. Dess NameID är en ogenomskinlig identifierare snarare än en adress. Det skickar ingen grupp-påstående om inte programmet uttryckligen konfigurerats för att skicka en, så en rollmappning skriven mot grupper vägrar varje inloggning. När grupper skickas är de objekt-GUID:er snarare än namn, såvida inte din klient synkroniserar från lokalt Active Directory. Och dess påståendeheter lever under schemas.microsoft.com/identity där de flesta dokument visar schemas.xmlsoap.org. Perfuse hanterar alla fem; de listas eftersom de första fyra annars skulle se ut som fel i Perfuse när de är Entra som är Entra.
Den distinktionen är inte teoretisk här. Den första riktiga Keycloak-påståendet misslyckades helt, eftersom den kanoniska formen som signeringen täcker beräknades med namnutrymmesprefix borttagna. Inga riktiga identitetsleverantörer kunde ha skrivit in någon, och paketets egna fem kanoniserings tester passerade genom hela — var och en av dem signerad och verifierad med samma kod, så de bevisade bara att det var överens med sig själv. Om du är den första som pekar en annan leverantör mot detta, förvänta dig att hitta något, och serverloggen kommer att namnge det skede som misslyckades.
18 Drift
18.1 Distribution
En binärfil och två sökvägar: en katalog med kanalfiler och en databasfil. Det finns ingen programserver, ingen separat webbnivå och ingen meddelandekö som krävs.
perfuse serve -channels ./channels -db ./perfuse.db -addr 0.0.0.0:8443 \
-tls-cert ./cert.pem -tls-key ./key.pem
Kör den under vad som övervakar tjänster på värden — systemd, launchd, en containerruntime. Den förväntar sig att startas om den avslutas.
18.2 Där data kan gå (dataresidens)
serve -residency (Inställningar → Data → Var data kan skickas) anger molnregionerna som serverns data kan skickas till eller läsas från: områden (eea, uk, ch) och regionskoder (eu-central-1, uksouth, europe-west2), komma-separerade. eea är AWS-, Azure- och Google Cloud-regionerna i Europeiska ekonomiska samarbetsområdet (Frankfurt, Irland, Paris, Stockholm, Milano, Spanien; Nederländerna, Tyskland, Frankrike, Sverige, Norge, Italien, Polen, Spanien; Belgien, Nederländerna, Tyskland, Italien, Frankrike, Finland, Spanien, Polen), uk är de i Storbritannien, ch är de i Schweiz.
När det är inställt, avvisas en kanal när den sparas och när den läses in, om en anslutning namnger en region utanför listan: en S3-, SQS- eller SNS-källa eller måls region (eller dess endpoint, när det är en AWS-värdnamn), eller varje mål vars adress är en AWS-värdnamn som bär en region (sqs.us-east-1.amazonaws.com, en API-Gateway-URL). Servern vägrar att starta med en spårinsamlare eller en varnings-Webhook i en annan region. En anslutning som pekar på en värd som inte namnger någon region (ett sjukhus eget system, MinIO på webbplatsens nätverk) bedöms inte: posten om bearbetning på dataskyddsskärmen listar varje värd som varje kanal skickar till, för kontrollanten att kontrollera. Instrumentpanelen och dataskyddsskärmen säger var data kan skickas.
Värd i EU och Storbritannien. deploy/hosted innehåller OpenTofu (eller Terraform) för en värdserver per organisation i Frankfurt, Irland eller London: servern, dess PostgreSQL-databas och säkerhetskopior, en säkerhetskopieringsbucket, loggar och support-sessioner, allt krypterat med en nyckel i regionen, ingenting replikerat till en annan region, support via Session Manager endast, och Perfuse körs med -residency. Dess README säger vad det bygger, vad det inte täcker, vad som har verifierats (validerat och planerat mot ett riktigt konto; inte ännu tillämpat) och vad det kostar till listpris i varje region.
18.3 Konfiguration som filer
Kanaler är filer, vilket innebär att de kan finnas i versionskontroll, granskas före distribution och jämföras efter en incident.
Filer läses om utan omstart. En fil som inte kan tolkas rapporteras och den tidigare laddade versionen fortsätter att köra, så ett syntaxfel kan inte ta en fungerande feed ur luften.
18.4 Säkerhetskopiering
Två saker att säkerhetskopiera, och de har olika egenskaper.
Katalogen för kanaler är liten, ändras sällan och är det du behöver för att återställa tjänsten. Säkerhetskopiera den som konfiguration, versionskontroll är vanligtvis tillräckligt.
Databasen innehåller meddelanden, användare och revisionshistorik. Den är stor, ändras konstant och innehåller kliniska data — så den behöver säkerhetskopieras som kliniska data, med den kvarhållning och kryptering som det innebär. Att förlora den stoppar inte tjänsten, men den förlorar förmågan att undersöka allt som redan har hänt och den historik som rytm-lärandet är beroende av.
18.5 Omstartsbeteende
Vid omstart läses kanaler in och källor börjar lyssna. Köade leveranser återupptas.
Det viktiga är att förstå vad som händer med arbete under flygning. Under standard-on_delivery-bekräftelse, bekräftas ett meddelande som ännu inte har bekräftats inte, så avsändaren kommer att skicka det igen — vilket är det korrekta resultatet. Under on_receipt, är ett meddelande som bekräftades men inte levererades ännu i kön och återupptas, om kön är inaktiverad, förloras det. Se meddelandeflöde.
18.6 Uppgradering
Ersätt binärfilen och starta om. Databasschemat migreras automatiskt framåt vid start.
Migreringar är endast framåt. Det finns ingen nedgradering, så en återställning till en tidigare binärfil efter att schemat har flyttats kräver den tidigare databasen. Ta en kopia innan du uppgraderar — detta är den enda operativa försiktigheten som är värd att vara disciplinerad om.
18.7 Övervakning
Larm från Perfuse täcks i larm och är vad som kommer att tala om för dig att en feed har stoppats.
Från utsidan, övervaka processen, disken som databasen är på och om webbgränssnittet svarar. Databasen växer och en full disk stoppar meddelanderecording, vilket är ett felmodus utan någon annan varning.
18.7.1 SNMP
För övervakningsverktyg som talar SNMP (Nagios, Zabbix, PRTG, SolarWinds, LibreNMS), kör Perfuse en skrivskyddad SNMPv2c-agent och skickar en fälla när en varning utlöses eller löses. Ställ in det under Inställningar → Övervakning → SNMP, eller med flaggor:
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
- Agenten svarar på GET, GETNEXT och GETBULK, och endast från nätverken i
-snmp-allow: v2c:s community är ett lösenord som skickas i klartext, så det är aldrig öppet för alla. En community under 6 tecken, ellerpublic/private, stoppar servern vid start. - Den betjänar systemgruppen (sysDescr, sysUpTime, sysName från flottans etikett, sysContact, sysLocation), totaler under
BASE.1(kanaler, körs, trasiga, mottagna, levererade, misslyckade, köade) och en kanaltabell underBASE.2.1(namn, körs eller stoppas, mottagna, levererade, misslyckade, köade, ålder på den äldsta köade meddelanden). Siffrorna är de som instrumentpanelen och/metricsvisar. - Fällor skickas till varje chef i
-snmp-traps:BASE.0.1en varning utlöses,BASE.0.2den löstes, med varningens typ, allvarlighetsgrad, kanal, destination och sammanfattning. Aldrig meddelandeinnehåll. En bekräftad varning skickar ingen fälla. BASEär1.3.6.1.4.1.8072.9999.9999.16(Net-SNMP:s experimentella utrymme) såvida inte-snmp-base-oidplacerar den under ditt eget företagsnummer. Ladda ner MIB på Inställningar-sidan (ellerGET /api/snmp/mib) ger en MIB för den bas som används; samma panel visar om agenten svarar och hur många fällor som skickats.
18.7.2 En inventering av varje gränssnitt
-inventory interfaces.md (Inställningar → Övervakning → Inventering) skriver en Markdown-dokument som listar varje kanal - dess format, om den körs, vad den tar emot från och vad den skickar till - följt av varje kanals egen beskrivning, och skriver om den varje -inventory-every (en dag som standard). Den är tänkt att committas bredvid kanal filerna, eller överlämnas till en revisor, och läsas utan att programmet körs.
18.8 Kapacitet
Perfuses genomströmnings tak har inte mätts på riktigt maskinvara under riktigt trafik, och den här handboken kommer inte att skriva ut ett nummer som den inte kan stödja.
Vad som kan sägas: arkitekturen är en goroutine per anslutning med per-destination-köer, så genomströmning skalar med destinationer snarare än att serialiseras genom en arbetare, meddelanderecording är en SQLite-skrivning per meddelande, vilket gör disken till den mest sannolika första begränsningen, och meddelandelagret växer linjärt med trafik, så kvarhållning är inställningen som styr långsiktig disk-användning.
Om du storleksanpassar detta för en stor mängd data, mät det med din egen trafik med hjälp av det genererade testmaterialet som beskrivs i testing. Det är det ärliga svaret, och det är också ett bättre svar än ett nummer från någon annans hårdvara.
18.9 Där denna installation fastnade
Aktiviteten har en panel, synlig för administratörer, som visar vad Perfuse har vägrat att göra — grupperat per meddelande, mest frekvent först — och hur långt installationen har kommit mot en fungerande kanal.
Den finns eftersom varje annan påstående om huruvida denna programvara är lätt att använda kommer från de personer som skrev den. Ett avslag gör inte det: någon ville något, servern sa nej, och ingen av parterna gissade. Det är det enda beviset i produkten som inte kommer från BioDream LLC.
Trattens namn anger det steg som ännu inte har hänt, snarare än att lämna tidsstämplar att jämföra. Tillståndet som är värt att titta på är meddelanden anländer och ingen har levererats till en destination — en kanal kan ta trafik under veckor och leverera ingen av den, och från varje annan skärm ser det ut som om den fungerar.
Inget som någon skrivit sparas. Tabellen innehåller begäran vägen med identifierare ersatta av {id}, statusen och serverns eget påstående. Ett valideringsmeddelande namnger ett fält och en regel, vilket är den användbara delen; värdet som bröt mot regeln är mycket ofta patientdata, och en tabell med dessa vore en större skuld än den friktion den mätte.
Två medvetna undantag. Ett 5xx är ett fel i denna programvara och loggas redan som ett sådant — att blanda de två skulle begrava fallen där någon inte kunde lista ut vad de skulle skriva under fallen där ingenting de skrev skulle ha hjälpt. Och en utgången session producerar en rad 401 som inte säger något om användbarhet och skulle drunkna varje upptäckt som gör det.
Att läsa rapporten trimmar också tabellen till dess fem senaste tusen rader. Avslag är 4xx-svar, så den växer långsamt, och läsning är en naturlig ögonblick att städa: ingen timer och ingenting som körs när ingen tittar.
GET /api/friction returnerar samma sak för alla som hellre vill läsa den som JSON.
18.10 Loggar
Perfuse loggar till standardutmatning, vilket är där en övervakare eller container-runtime kommer att samla in den.
Meddelandenivådetalj går till meddelandelagret snarare än loggen, med avsikt. En loggradering per meddelande på en upptagen feed är brus som döljer de rader som betyder något, och lagret är sökbart på sätt som en loggfil inte är.
Loggen bär det som lagret inte kan: start och stopp, konfigurationsladdningsresultat, kanalstatusändringar och fel som inte kan hänföras till ett specifikt meddelande.
18.11 Körning av två instanser
Två eller flera servrar kan köras som en kluster: när den som kör en feed stoppas, tar en annan över inom några sekunder, och avsändarens nästa försök når den. De delar en PostgreSQL-databas istället för att var och en håller en SQLite fil, och kommer överens sinsemellan, genom den, vilken av dem som kör vad.
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
Starta varje server på samma sätt med dess eget namn och adress. Databaskontot behöver skapa tabeller och, en gång, citext-tillägget (eller en administratör kör CREATE EXTENSION citext först). Varje server håller sina egna filer i -data: dess logg, dess nod-ID och dess kopior av konfigurationen.
Två sätt att dela arbetet.
active-passive: ledaren kör varje kanal och varje jobb som måste köras en gång (FHIR-prenumerationsmeddelanden).
De andra väntar. Det enklaste att resonera om, och vad en webbplats med en upptagen server och en reservserver vill ha.
active-active: kanalerna fördelas över de aktiva servrarna, ungefär jämnt. En server som stannar överlämnar sina kanaler
till de övriga; en som ansluter tar sin andel av kanaler allteftersom de blir lediga, en i taget. Kanaler som dirigeras till varandra (en kanaldestination) körs på en server och flyttas tillsammans, eftersom dirigeringsprocessen sker inom en server. En administratör kan flytta en kanal manuellt från Övervakning → Flotta; den stannar där den placerades medan den servern är aktiv.
Vem kör vad, och ingen stund med två. Varje arbetsenhet är ett arrendeanbud i databasen, som förnyas var femte -cluster-lease (15 s som standard). En server som inte kan förnya det (den kraschade, dess nätverk misslyckades, databasen är otillgänglig) stoppar arbetet automatiskt när dess egen klocka säger att arrendet nästan är slut, med en tredjedel av arrendet kvar. En annan server tar över arrendet först efter att dess egen klocka har sett arrendets counter stå still under en hel arrendeperiod. Inga klockor jämförs med varandra, så servrarnas klockor och databasens behöver inte vara överens; de behöver bara gå i ungefär samma takt, vilket varje klocka gör. Mellan den gamla innehavarens stopp och den nya innehavarens start finns ett kort glapp med ingen som lyssnar, vilket en avsändare uppfattar som en vägrad anslutning och försöker igen; det finns aldrig en stund med två som lyssnar på en feed eller två arbetare som tömmer en kö.
En server som stängs av rent, eller en administratör som väljer Steg ned på ledaren, överlämnar omedelbart i stället för efter uthyrningen.
Vad varje server delar. Meddelanden, leveransköran, konton och sessioner, granskningsloggen, FHIR-lagret, terminologitabellerna och patientindex är i databasen, så vilken server som kör en kanal hittar kön den senaste lämnade. Kanalfilerna, inställningsfilen, varningsreglerna, enkel inloggning-filer, logotypen, Direct-certifikat och sparade vyer hålls desamma på varje server genom databasen: var och en håller sin egen kopia på sin egen disk, en ändring på någon server (i konsolen, för hand, genom en git pull) når de andra inom två sekunder, och en kanal som ändrats på en annan server startar om med sin nya fil. Samma fil som ändrats på två servrar samtidigt behåller den version som nådde databasen först, och den andra bredvid den som NAME.conflict-SERVER. Inställningar som bara gäller vid en omstart (meddelandedatabasen, portarna som konsolen lyssnar på) tillämpas av varje server vid dess nästa omstart, och loggen säger så. Vad namnet på något på en maskin stannar på den serverns kommandorad och utanför den delade filen: certifikatet och nyckeln (-tls-cert, -tls-key), SNMP-lyssnande adressen och serverns namn i spår. Inställningar visar dem som inställda på varje server.
Starta och stoppa. Att starta eller stoppa en kanal på valfri server gäller för klustret: servern som kör den startar eller stoppar den inom en sekund, och svaret säger vilken server det är.
Lastbalanseraren framför. En feeds adress måste nå den server som kör den. Pecka avsändaren på en virtuell adress (en lastbalanserare, en flytande IP, en DNS-namn med en kort TTL) och ha lastbalanseraren kontrollera /readyz?channel=NAME, som svarar 200 endast på den server som kör den kanalen, och 503 på de andra. För konsolen är /readyz 200 på varje levande server; /readyz?role=leader endast på ledaren.
På en AWS Network Load Balancer, använd en målgrupp per feed med en HTTPS-hälsokontroll på /readyz?channel=NAME, ett 5-sekundersintervall och en tröskel på 2, och aktivera cross-zone lastbalansering. Med den avstängd ser lastbalanserarens nod i en zon där ingen server kör feeden endast ohälsosamma mål, skickar till alla av dem ändå, och en avsändare som löstes till den noden väntar tills feeden kommer tillbaka till sin zon (95 sekunder i en test). Ställ in avregistreringsfördröjningen till 0, eftersom en server som slutar köra en feed inte har något att tömma.
Vad som testades. Två servrar på PostgreSQL 16, en avsändare som strömmade 300 meddelanden, som skickades om tills de besvarades, och servern som körde feeden avslutades med SIGKILL två gånger (först den ena, sedan den andra efter att den första återuppstått). Varje bekräftat meddelande nådde mottagaren, i båda former som testades: levererat innan bekräftelsen, och köat i den delade lagringen medan mottagaren vägrade (185 bekräftade meddelanden väntade i kön vid avslut; överlevaren levererade alla). Failover tog 3 till 4 sekunder på en 3-sekunders lease. En dubblett är möjlig och sågs en gång i 600: ett meddelande som den döende servern levererade och inte kunde bekräfta, som avsändaren skickade om. Koordinatorns egna tester täcker en krasch, en server som skärs av från databasen medan den körs, step-down, spridning, flytt och delad konfiguration med konflikter. De körs i CI mot PostgreSQL med race-detektor, med hela sviten.
Samma sak gjordes sedan på AWS: två Linux-servrar (ARM) och en Windows Server 2022 i tre tillgänglighetszoner, Amazon RDS PostgreSQL 16 över TLS med certifikatkontroll (sslmode=verify-full), en intern Network Load Balancer framför, och avsändare som skickade om tills de besvarades:
| Test | Meddelanden | Bekräftade men förlorade | Dubbletter | Längst en avsändare väntade |
|---|---|---|---|---|
| Aktiv-passiv, servern som kör feeden dödad två gånger (Linux, sedan Windows), mottagare som vägrade däremellan | 2,000 | 0 | 0 | 15 s |
| En Linux-ledare skuren av från databasen (brandvägg), dess process lämnad kvar | 3,000 | 0 | 1 | 16 s |
| En Windows-ledare skuren av från databasen | 3,000 | 0 | 0 | 20 s |
| Ledaren dödad medan en servers klocka sprang 2 minuter för fort och en annans 90 sekunder långsamt | 2,000 | 0 | 0 | 18 s |
| Aktiv-aktiv, fyra feeds över tre servrar, en dödad och återupptagen | 6,000 | 0 | 2 | 24 s |
Med standardhyran på 15 sekunder, en server som skärs av från databasen stoppade sin feed 10 sekunder efter sin senaste förnyelse, och nästa server startade den 6 till 8 sekunder efter det: aldrig båda på samma gång. De skeva klockorna förändrade ingenting, eftersom ingen klocka jämförs med en annan.
Inte ännu. En kluster tjänar en organisation: -cluster med -multi-tenant är inte tillåtet. Lyssnare flyttar med sin kanal, så lastbalanseraren är platsens att tillhandahålla.
En server på egen hand fortsätter att fungera som den alltid har gjort, på SQLite, utan något kluster alls.
18.12 Mer än en server
En plats med två instanser har en fråga som ingen enskild konsol kan besvara: körs allt? Mirth tar betalt för svaret. Detta är flottvy.
En instans utses som den plats man tittar på. Den pollar de andra och visar varje kanal på varje server i en tabell, med en sammanfattning över alla.
18.12.1 Lägga till en peer
Inställningar → Flotta, eller PUT /api/fleet/peers. En peer behöver ett namn, en URL och en token som utfärdats av peer-en själv.
Namnet är obligatoriskt och är inte URL:en, eftersom en URL inte är något som någon känner igen klockan tre på morgonen.
Token måste skapas på peer, under Användare, och bör vara viewer-scoped. Att lägga till en peer utan en är inte tillåtet, med dessa instruktioner, snarare än att accepteras och sedan misslyckas tyst på varje poll. Att läsa en annan instans hälsa är den minsta privilegiet som finns, och det är det enda som flottvyn behöver.
18.12.2 Kontrollera en peer som är avstängd
allow_control tillåter start och stopp av den peer-kanalen från här. Det är avstängt som standard och varje användning loggas med namn.
De två privilegierna är medvetet separata. Att läsa en annan servers hälsa är en mindre sak; att stoppa dess kanaler under en transfusion är inte det, och den andra bör aldrig anlända tyst bifogad till den första.
18.12.3 Vad rapporten säger
Varje server rapporterar det totala antalet kanaler, hur många som körs, stoppats eller felat, koledjans djup och åldern på den äldsta väntande meddelanden, hur många varningar som utlöses och huruvida den töms för avstängning.
Sammanfattningen räknar servrar på tre sätt: tillgänglig, otillgänglig och obestämd. Den tredje täcker peers vars hälsa ingen vet — inte ännu pollad, vägrar token, eller kör en version som denna inte kan läsa. Den hålls separat från otillgänglig eftersom "vi kan inte säga" inte är "den är nere", och att kombinera de två är hur en flottvy börjar ljuga.
Av samma anledning bär sammanfattningen knownFrom: hur många instanser kanal- och kösiffrorna faktiskt lästes från. Tolv kanaler som körs över en flotta betyder något annat när två av fem servrar inte svarade, och totalt ensam kan inte säga det.
En otillgänglig peer säger varför på ett sätt som en operatör kan agera på. En vägrat anslutning rapporteras som en värd som är uppe med ingenting som lyssnar på den porten, vilket är ett annat problem än en värd som inte svarar alls.
18.12.4 Klockfel
Sammanfattningen rapporterar den största skillnaden mellan klockorna på servrarna i den. Värt ett eget nummer: att korrelera en incident över två instanser vars klockor inte är överensstämmande med fyra minuter producerar en sekvens av händelser som inte hände.
18.12.5 Vad en peer lär sig om dig
Antal och hastigheter. Rapporten en instans ger en annan innehåller inga meddelandeidentifierare, inga kanal-specifika detaljer och inga patientdata av något slag.
Det är vad som stoppar en flottvy från att vara en centralisering av kliniska data: den aggregerande instansen lär sig hur många kanaler som körs och ingenting alls om vad som flödade genom dem. Om du vill ha meddelandena öppnar du den serverns egen konsol, där granskningsloggen registrerar att du gjorde det.
18.12.6 En peer som pekar på sig själv
Vägrat. En instans som pollar sin egen adress genom sin egen HTTP-stack verkar som två i sin egen flottvy och dubbelräknar varje kanal den har.
18.12.7 TLS på interna nätverk
insecure_skip_verify accepterar en peers certifikat utan att verifiera det. Den finns eftersom sjukhusinfrastruktur körs på privata certifikatutfärdare, och att vägra att fungera alls skulle driva människor till vanlig HTTP, vilket är sämre. Den är namngiven så att den inte kan förväxlas med en bra idé.
19 Kommandoraden
Allt Perfuse gör till ett körsystem är tillgängligt från webbgränssnittet, och det är medvetet: en funktion som behöver en terminal behandlas som en defekt snarare än ett designval. Kommandona här är för arbetet som sker *runtom* ett körsystem — innan det existerar, medan du bestämmer dig för om du ska lita på det, och när du behöver ge något till någon annan.
Flera av dem berör inte ens en server. perfuse explain, perfuse profile, perfuse deident och perfuse translate läser filer och skriver filer, så de är användbara på en bärbar dator mot en fastighet som fortfarande körs helt på något annat.
Kör vilket kommando som helst med -h för dess flaggor. Detta kapitel säger vad var och en är *till för*.
-h genereras från koden och kan inte bli inaktuell; en lista som kopierats in i prosan kan.19.1 Kör kanaler
19.1.1 perfuse serve
Kör webbgränssnittet och API:et, och kör som standard även kanalerna. Detta är kommandot som en installation använder.
Varje alternativ det tar är listat i Serveralternativ, som genereras från programmet. Det vägrar att betjäna vanlig HTTP till allt utom loopback såvida du inte anger -insecure. Det är inte konfigurerbar artighet: klinisk trafik och en sessionscookie över en oekrypterad LAN-anslutning är ett rapporteringsbart händelse, och flaggan finns så att att säga ja är ett beslut som någon har gjort snarare än en standard som de har ärvt. Se säkerhet.
19.1.2 perfuse run
Kör kanaler från YAML utan webbgränssnitt och utan databas. Användbart i en container som ska göra exakt en sak, och användbart när du vill se en kanals beteende utan att något annat körs.
19.1.3 perfuse check
Validerar kanaldefinitioner och skriver ut vad de gör, utan att köra dem. Den senare delen är poängen: en kanal som laddas är inte nödvändigtvis den kanal du menade, och att läsa en ren-Engelsk sammanfattning av vad en fil kommer att göra fångar ett misstag som validering inte kan se.
Avslutas med en icke-nollkod vid en fel, så den hör hemma i vilka kontroller som helst som kontrollerar din konfiguration innan den når en server. -quiet skriver ut ingenting vid framgång, för det ändamålet.
-allow-metadata-egress tillåter destinationer som pekar på molninstansens metadataadresser. Dessa adresser innehåller maskinens egna autentiseringsuppgifter, så en kanal som kan övertalas att skicka dit är en autentiseringsläcka; kontrollen vägrar dem om du inte säger något annat.
19.1.4 perfuse test
Kör tester som är skrivna mot kanaldefinitioner. Ett test skickar ett meddelande genom kanalens riktiga filter, riktiga transformationer och riktiga skript, i riktiga ordning, med endast nätverket ersatt — så det som passerar här är vad kanalen gör.
Tester finns i *_test.yaml eller *.test.yaml bredvid kanalerna. Se testning.
19.2 Migrering från en annan motor
Dessa tre är de som ska köras först, innan du bestämmer dig för något. Se migration.
19.2.1 perfuse explain
Läser Mirth, Open Integration Engine och BridgeLink-export — en kanal, en kanalgrupp eller en hel serverbackup — och beskriver vad varje kanal gör och vad som skulle blockera en migration. Den ändrar ingenting och behöver ingen Perfuse-installation, vilket gör den till den billigaste möjliga första steget: peka på en export av din egendom och läs vad som kommer tillbaka.
-strict avslutas med en icke-nollkod om något är blockerat, så den kan styra en pipeline. -json emitterar samma resultat för en maskin.
19.2.2 perfuse translate
Konverterar Mirth, Open Integration Engine och BridgeLink-export till Perfuse-kanalfiler: en kanal, en kanalgrupp, en kodmallsexport eller en hel serverbackup.
perfuse translate -o ./channels server-backup.xml
Kodmallbibliotek skrivs till lib/ bredvid kanalerna, och varje kanal som Mirth hade en bibliotek aktiverat för inkluderar det. Se migration.
Ingenting tystas bort. Varje del av en kanal är antingen översatt, buren över som ett skript som körs oförändrat, eller rapporterat som behöver en människa. Den tredje kategorin är den ärliga — en översättare som producerade en ren-utseende-fil för varje indata skulle dölja de beslut du mest behöver fatta.
19.2.3 perfuse compare
Kör samma trafik genom två motorer och rapporterar var de inte är överens, grupperade efter fält.
Detta är kommandot som svarar på "varför ska jag lita på detta med patientdata", och det svarar med bevis som du har samlat in snarare än ett påstående som görs här. Det är det rekommenderade sista steget innan man byter över, och det rekommenderade första steget i någon diskussion om huruvida Perfuse är redo.
19.3 Att förstå en feed
19.3.1 perfuse profil
Läser meddelanden och rapporterar vad som faktiskt finns i dem: vilka fält som alltid är ifyllda, vilka aldrig är det, de faktiska värdesuppsättningarna för kodade fält, upprepningssiffror och vilka Z-segment som visas.
Värden rapporteras endast för fält vars värden utgör en liten koduppsättning, så en profil av riktigt trafik blir inte en fil full av patientdata.
Att spara en profil och jämföra den med en senare är hur du upptäcker att en avsändare har ändrat något:
perfuse profil -spara last-month.json corpus/ perfuse profil -mot last-month.json new/
19.3.2 perfuse kontrakt
Omformar utdata från den tanken till något som kan verkställas. Ett kontrakt säger hur en feed måste se ut, så att den dagen den ändras du blir informerad, snarare än att upptäcka det veckor senare från en mottagare som kollapsade — meddelandena är fortfarande giltiga HL7 när ett fält försvinner, så ingenting annat märker det.
perfuse kontrakt främja -o adt.kontrakt.yaml corpus/ perfuse kontrakt kontrollera adt.kontrakt.yaml today/
promote genererar en utgångspunkt, inte ett svar. Läs det och ta bort mest av det: varje rad registrerar om den mättes eller beslutades, vilket är vad som berättar för dig vilka rader du ska behålla.
19.4 Att producera meddelanden
19.4.1 perfuse generera
Producerar syntetiska HL7 v2-meddelanden. Allt är uppfunnet — uppenbarligen fiktiva namn, sekventiella identifierare, påhittade adresser — så utdata är säkert att commit, maila och bifoga till en biljett.
Det kan skicka direkt till en kanal snarare än att skriva en fil, vilket är det snabbaste sättet att bevisa att en lyssnare fungerar:
perfuse generera -n 100 -skicka 127.0.0.1:6661
19.4.2 perfuse avidentifiera
Läser riktiga meddelanden och skriver en korpus som behåller deras struktur, deras koder och deras intervall, och ingenting som identifierar en patient. Detta är skillnaden mellan att kunna skicka någon en reproduktion och inte.
Det är inte samma verktyg som perfuse generate och skillnaden är viktig. Genererade meddelanden är uppfunna och därmed säkra men orealistiska; en deidentifierad korpus är *härledd från riktigt trafik*, så den återger de egenskaper som faktiskt bryter mot gränssnitten.
Två egenskaper som är värda att förstå innan du använder det:
- Samma salt producerar alltid samma korpus, så en delad korpus kan regenereras snarare än arkiveras.
- Behåll saltet hemligt. Pseudonymer är härledda från riktiga värden, så vem som helst som har saltet kan bekräfta en gissning om vem en post hänvisar till.
-keep-local-segments passerar Z-segment oförändrade och är osäkert. Z-segment är exakt där webbplatser lägger namn, anteckningar och fritext, så att behålla dem besegrar verktygets syfte. Det finns därför att ett strukturellt problem ibland är *i* ett Z-segment, och då behöver du en korpus som du inte får dela.19.5 Att flytta meddelanden för hand
19.5.1 perfuse lyssna
Accepterar HL7 v2 via MLLP och bekräftar det. En mottagare som existerar så länge du behöver den, för att bevisa att en avsändare kan nå den här maskinen över huvud taget.
19.5.2 Perfuse skicka
Skickar HL7 v2-meddelanden via MLLP från filer.
19.6 FHIR
19.6.1 Perfuse fhir
Konverterar HL7 v2 till FHIR, validerar FHIR eller serverar det, beroende på underkommandot.
Valideringsunderkommandot är användbart i sig: det berättar om en resurs som någon skickat till dig uppfyller US Core, som är profilen som den amerikanska lagstiftningen är skriven mot. Att kunna svara på det utan att anta en motor är poängen.
19.6.2 perfuse x12
Converts X12 (or other delimited EDI) to the XML Mirth Connect and Open Integration Engine write for it, and back: perfuse x12 xml FILE and perfuse x12 from-xml FILE, standard input when no file is given. The output is what OIE 4.6 writes, byte for byte, so it can be compared with what a Mirth server produced or fed to a system built against it. A channel does the same with x12.arrives_as: xml and a destination's x12_as: xml; see X12.
19.6.3 Perfuse sof
Runs a SQL on FHIR ViewDefinition over FHIR files (the NDJSON of a bulk export, Bundles or JSON arrays; - for stdin) and writes the table: -view FILE (required), -format csv|ndjson|json|parquet (csv by default), -header=false, and -o FILE (required for Parquet). See SQL on FHIR views.
19.6.4 Perfuse mät
Utvärderar en kvalitetsmätning med FHIRPath-kriterier över FHIR-filer (NDJSON av en bulkexport, Bundles eller JSON-arrayer; - för stdin) och skriver MeasureReport. Flaggor:
-measure FILE, or-measure example:IDfor a shipped example: required.-exampleslists the examples.-period-startand-period-end: required.-type summary|subject|subject-list.-subject Patient/ID.-reporter NAME.-o FILE.
Se digitala kvalitetsmätningar.
19.6.5 FHIR-flaggor på perfuse serve
| Flagga | Effekt |
|---|---|
-fhir | Tillhandahåller FHIR-slutpunkten på /fhir. På som standard. |
-fhir-version | Den version som tillhandahålls. R4 som standard. |
-fhir-read-only | Vägrar skriva. |
-fhir-api-tokens | Med SMART konfigurerat, accepterar Perfuse API-token samt SMART-token (avstängt som standard; även under Inställningar → FHIR). |
-fhir-bulk-export | Aktiverar $export. Avstängt som standard. |
-fhir-subscriptions | Aktiverar ämnesprenumerationer: mötes- och tidsbokningsmeddelanden till slutpunkter som FHIR-klienter väljer. Avstängt som standard; kräver R4 och en skrivbar slutpunkt. |
-fhir-subscriptions-allow-http | Låter prenumerationer leverera till vanligt http. För en testmottagare, aldrig för patientdata på ett nätverk. |
-fhir-patient-directory-search | Låter en token begränsad till en patient söka i katalogen (praktiker, organisationer, platser), inom dess omfattningar. Avstängt som standard. |
-fhir-declares | Guider som denna server deklarerar i sin förmågeutlåtande, komma-separerad: en guides CapabilityStatement-adress, eller Type=profile-adress. Ett utlåtande för klienter och testkit; det ändrar ingenting som lagret accepterar. |
Butiken håller dokument samt resurser: ett dokument, en samling eller en meddelande-Bundle som skickas till /fhir/Bundle/{id} hålls helt, läses tillbaka med varje post i den version som servas, och hittas av type, identifier, timestamp och composition. En transaktion som skickas dit hålls som en post och tillämpas inte; en POST till /fhir tillämpas.
Svar är JSON såvida klienten inte begär XML (Accept: application/fhir+xml, eller _format=xml). Perfuse läser endast JSON: en kropp som skickas som XML får 415. En dokument-Bundle som POSTas till /fhir behålls när den här servern innehåller, genom identifierare, patienten och mötet dess Composition namnger, och avvisas med 422 annars. En Binary-läsning med Accept inställd på dess eget innehållstyp svarar med innehållet själv.
19.7 Konfigurera och driftsätta
19.7.1 Perfuse init
Skapar kataloglayouten, ett exempelkanal och en tjänstdefinition för det operativsystem som det körs på. Ingenting existerande ersätts såvida du inte anger -force.
Perfuse init -dir /opt/perfuse -service systemd
19.7.2 Perfuse tjänst
Registrerar Perfuse som en Windows-tjänst, tar bort den eller rapporterar om den är installerad och körs. Endast Windows; på Linux är motsvarigheten enhetsfilen perfuse init kan skriva för dig. Se drift.
19.7.3 Perfuse token
Utgår autentiseringsuppgifter för maskiner snarare än människor. En token upphör inte att gälla och påverkas inte av att någon loggar ut, vilket är vad en server som pollar sin granne behöver och vad en webbläsarsession medvetet inte är.
Perfuse token skapa -db perfuse.db -etikett flotta-från-plats-a -roll visare perfuse token lista -db perfuse.db perfuse token återkalla -db perfuse.db -etikett flotta-från-plats-a
Endast hashen lagras, så en token visas en gång när den skapas och kan inte återställas senare. En stulen databas ger därför ingen användbar token. Ge en token den lägsta rollen som fungerar: en flottvy behöver viewer, och ingenting som bara läser bör ha något mer.
-fhir-groups riverside-attributed,riverside-north begränsar en token till dessa FHIR-grupper, för en leverantörs CMS-0057 Provider Access-export: på FHIR-slutpunkten kan den läsa dessa grupper och exportera dem, och ingenting annat. Se CMS-0057 för betalare.
19.7.4 Perfuse athena
Skriver ut Amazon Athena CREATE EXTERNAL TABLE för en S3-arkiv skriven med format: ndjson, med partitionprojektion på dt=YYYY-MM-DD-delen av nyckeln, så att ingen crawler behöver köras när dagar läggs till.
Perfuse athena -bucket sjukhusarkiv -destination arkiv
Skriver ut i stället för att köra, eftersom skapande av tabell kräver Athena- och Glue-behörigheter som detta program inte bör ha.
19.7.5 Perfuse sbom
Visar allt som är länkat till binärfilen, läst från bygget i sig snarare än från go.mod — så det beskriver binärfilen framför dig och inte vad någon en gång begärde.
-json skriver ut CycloneDX och -spdx skriver ut SPDX tag-värde, vilket vanligtvis är vad en upphandling eller säkerhetsgranskning faktiskt begär. Den inbäddade webbkoden i binärfilen ingår, eftersom en granskare som matchar en binärfil mot råd behöver veta att den innehåller en React-applikation.
19.7.6 Perfuse version
Skriver ut versionen och den commit den byggdes från. Det är värt att lägga till i en biljett: "den aktuella" är inte en version, och två maskiner som installerades en vecka isär körs ofta inte samma version.
20 Serveralternativ
Varje alternativ perfuse serve tar, genererat från programmet i sig, så att denna lista inte kan namnge ett alternativ som inte finns eller lämna ett ut. De flesta är också en inställning i webbgränssnittet, namngiven i den sista kolumnen: ett värde som sparas där vinner över flaggan vid nästa start, och flaggan förblir sättet att ställa in den från en servicedefinition. Lyssnandeadressen, databasen och kanalkatalogen förblir endast flaggor, eftersom de säger var servern hittar vad den skulle redigera.
Hemligheter är aldrig flaggor. Ett alternativ som behöver ett lösenord eller en token namnger en miljövariabel som innehåller den.
20.1 Alla alternativ
| Option | Takes | Default | What it does | In the console |
|---|---|---|---|---|
-addr | string | 127.0.0.1:8080, or 127.0.0.1:8443 with -tls-cert | address to serve the interface on | — |
-alert-severity | string | warning | minimum severity to send to the webhook: warning or critical | Settings › Alerts › Delivery: Only send alerts at least this serious |
-alert-webhook | string | — | 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 content | Settings › Alerts › Delivery: Send alerts to this address |
-alerts | string | — | 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-egress | on/off | — | permit destinations pointed at cloud instance metadata addresses, which hold this machine's credentials | Settings › Security › What may leave: Allow destinations at cloud instance metadata addresses |
-cds-clients | string | — | 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 |
-channels | string | ./channels | directory holding channel files | — |
-cluster | string | — | 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-lease | duration | 15s | how long a crashed server holds its work before another takes it over; renewed five times as often | — |
-crd-advisor-ca | string | — | 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-env | string | — | 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-url | string | — | 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 it | Settings › Payers › Decision service: Advice before submitting (CRD) |
-crd-rules | string | — | a Da Vinci CRD rules file: serve coverage requirements over CDS Hooks at /cds-services | Settings › Payers › Prior authorization: Coverage rules file (Da Vinci CRD) |
-dashboards | string | — | a file mapping directory groups and roles to the dashboard each opens on | Settings › Monitoring › Dashboards: Which dashboard each group opens on (file) |
-data | string | — | 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-version | string | 2.2 | the 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) | — |
-db | string | ./perfuse.db | database for users, messages and stored resources: a file, or a postgres:// URL for servers that share one store (a cluster) | — |
-demo-account | string | — | for a public demonstration server: username:password of a shared viewer account shown on the sign-in page | — |
-dicomweb-archive | string | — | keep imaging objects in this directory and serve them over DICOMweb (QIDO-RS, WADO-RS, WADO-URI, STOW-RS) at /dicomweb | Settings › Data › Imaging archive: Keep images in this folder and serve them over DICOMweb |
-dicomweb-cors | string | — | comma-separated browser origins, such as an OHIF viewer's, allowed to call /dicomweb | Settings › Data › Imaging archive: Browser origins allowed to call it |
-drain-for | duration | — | 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-agency | string | — | 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-responses | on/off | — | accept eCR Reportability Responses at the FHIR endpoint's $process-message, storing each as DocumentReference/<id> derived from the eICR it answers | Settings › Public health › Case reporting: Receive Reportability Responses |
-engine | on/off | true | run the channel engine in this process, so the interface can start, stop and monitor channels | — |
-epa-payer-id | string | — | 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-channel | string | — | 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 network | Settings › Payers › Drug formulary: Channel that sends later ePA decisions |
-fhir | on/off | true | serve a FHIR endpoint at /fhir | Settings › FHIR › The FHIR server: Serve a FHIR endpoint at /fhir |
-fhir-api-tokens | on/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-export | on/off | — | enable $export, which produces a file holding every record the FHIR endpoint serves | Settings › FHIR › Bulk data: Bulk Data export ($export) |
-fhir-declares | string | — | guides this FHIR server declares in its capability statement, comma-separated: a CapabilityStatement address, or Type=profile address | Settings › FHIR › Capability statement: Guides this server declares |
-fhir-max-resources | int | — | 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-consent | on/off | — | let $member-match answer without an active Consent; the Payer-to-Payer API is opt-in, so only for testing | Settings › Payers › CMS-0057-F: Answer $member-match without the member's consent |
-fhir-open | on/off | — | serve the FHIR endpoint with no authentication at all, exposing every stored record | Settings › FHIR › Access: Let anyone read the FHIR endpoint without signing in |
-fhir-patient-directory-search | on/off | — | let a token limited to one patient search the directory (practitioners, organisations, locations) within its scopes | Settings › FHIR › Access: Let a patient's app search the directory |
-fhir-payer-apis | on/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-export | Settings › Payers › CMS-0057-F: The CMS-0057-F payer APIs |
-fhir-read-only | on/off | — | refuse writes to the FHIR endpoint | Settings › FHIR › Access: Refuse writes to the FHIR endpoint |
-fhir-subscriptions | on/off | — | enable topic-based subscriptions, which send encounter and appointment notifications to URLs FHIR clients choose | Settings › FHIR › Notifications: FHIR subscriptions (encounter and appointment notifications) |
-fhir-subscriptions-allow-http | on/off | — | let subscriptions deliver to plain-http endpoints; for a test receiver, never for patient data on a network | Settings › FHIR › Notifications: Allow subscriptions to notify plain-HTTP addresses |
-fhir-version | string | 4.0.1 | FHIR release to serve: R4, R4B or R5 | Settings › FHIR › The FHIR server: FHIR version clients see |
-fhir-writes-per-minute | int | — | 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-label | string | — | how this instance names itself in a fleet view (default: hostname) | Settings › Fleet › This server: Name for this server |
-formulary | string | — | 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 it | Settings › Payers › Drug formulary: Drug formulary file |
-icd11-client-id | string | — | a WHO ICD API client: ICD-11 codes not imported are looked up there | Settings › Data › Code systems: WHO ICD API client ID |
-icd11-client-secret | string | — | the WHO ICD API client's secret | Settings › Data › Code systems: WHO ICD API client secret |
-icd11-release | string | 2025-01 | the ICD-11 MMS release the WHO ICD API is asked about | Settings › Data › Code systems: ICD-11 release to ask for |
-icd11-url | string | — | the ICD API's address when it is not the WHO's: the WHO's ICD-API container on your network needs no client | Settings › Data › Code systems: ICD API address |
-index-identity | on/off | true | index 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 off | Settings › Data › What is kept: Index patient identifiers |
-insecure | on/off | — | serve over plain HTTP on a non-loopback address (not recommended) | — |
-inventory | string | — | write a Markdown inventory of every interface to this file, and keep it current | Settings › Monitoring › Inventory: Write an interface inventory to |
-inventory-every | duration | 24h0m0s | how often to rewrite the interface inventory | Settings › Monitoring › Inventory: Rewrite the inventory every |
-json-logs | on/off | — | emit structured JSON logs | Settings › Monitoring › Logging: Write logs as JSON |
-ldap | string | — | YAML file configuring directory (LDAP) sign-in (default: ldap.yaml beside the database, once saved in the console) | — |
-log-file | string | — | 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 | — |
-mcp | on/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 access | Settings › Security › AI agents (MCP): Let AI agents connect over MCP |
-measure-reporter | string | Perfuse | the reporting organisation's name on MeasureReports from $evaluate-measure when the request names no reporter | — |
-metrics-open | on/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's | Settings › Security › Metrics: Serve /metrics without a token |
-metrics-token | string | — | 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 /metrics | Settings › Security › Metrics: Token a metrics scraper presents |
-mpi | on/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-tenant | on/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-address | string | — | this server's console URL as the other servers and a load balancer reach it | — |
-node-name | string | — | this server's name in the cluster (default: an id kept in -data) | — |
-oidc | string | — | YAML file configuring OpenID Connect sign-in (default: oidc.yaml beside the database, once saved in the console) | — |
-pas | on/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 result | Settings › Payers › Prior authorization: Da Vinci PAS prior authorization server |
-pas-278-ca | string | — | a PEM file of certificate authorities to trust for the UM system beside the system's | Settings › Payers › Utilization management link: Certificate authorities to trust for the UM system |
-pas-278-cert | string | — | 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-receiver | string | — | 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-version | string | — | 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-sender | string | — | 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-version | string | 2.2.0 | the 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-key | string | — | the private key (PEM) for -pas-278-cert | Settings › Payers › Utilization management link: Client certificate key file |
-pas-278-oauth-client-id | string | — | the OAuth client ID for -pas-278-oauth-token-url | Settings › Payers › Utilization management link: OAuth client ID |
-pas-278-oauth-scope | string | — | the scope asked for with the OAuth token, when the UM system wants one | Settings › Payers › Utilization management link: OAuth scope |
-pas-278-oauth-secret-env | string | — | 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-url | string | — | 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-env | string | — | 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-id | string | — | the UMO's payer ID (NM1*X3) when the request's insurer carries no identifier | Settings › Payers › Utilization management link: Payer ID for the 278s |
-pas-278-production | on/off | — | mark the 278s sent as production (ISA15 P) rather than test | Settings › Payers › Utilization management link: Mark the 278s as production |
-pas-278-receiver | string | — | ISA08/GS03 receiver ID on the 278s sent to the UM system | Settings › Payers › Utilization management link: Receiver ID on the 278s |
-pas-278-sender | string | PERFUSE | ISA06/GS02 sender ID on the 278s sent to the UM system | Settings › Payers › Utilization management link: Sender ID on the 278s |
-pas-278-sftp | string | — | host:port of the UM system's SFTP server, for -pas-278-transport sftp | Settings › Payers › Utilization management link: SFTP server |
-pas-278-sftp-every | duration | 1m0s | how often the SFTP inbound folder is read | Settings › Payers › Utilization management link: Read the SFTP inbound folder every |
-pas-278-sftp-inbound | string | — | the SFTP folder the UM system's 278 responses, 999s and TA1s are collected from | Settings › Payers › Utilization management link: SFTP inbound folder |
-pas-278-sftp-key | string | — | an OpenSSH private key file for the SFTP user, instead of a password | Settings › Payers › Utilization management link: SFTP key file |
-pas-278-sftp-known-hosts | string | — | an OpenSSH known_hosts file holding the SFTP server's key; required, so requests never go to whoever answers | Settings › Payers › Utilization management link: SFTP known_hosts file |
-pas-278-sftp-outbound | string | — | the SFTP folder the 278 requests (and the 999s for the answers) are put in | Settings › Payers › Utilization management link: SFTP outbound folder |
-pas-278-sftp-password-env | string | — | 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-user | string | — | the SFTP user name | Settings › Payers › Utilization management link: SFTP user |
-pas-278-token-env | string | — | 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-transport | string | x12 | how 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-url | string | — | 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-278 | Settings › Payers › Utilization management link: Send PAS requests on to the UM system at |
-pas-278-user | string | — | user name for the UM system: CORE's UserName (WS-Security UsernameToken in SOAP), or HTTP Basic for x12 | Settings › Payers › Utilization management link: User name |
-pas-decider-ca | string | — | 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-env | string | — | 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-url | string | — | 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-url | Settings › Payers › Decision service: Decision service URL |
-passkey-allowed-models | string | — | comma-separated authenticator AAGUIDs that may enrol; requires -passkey-attestation-roots | — |
-passkey-attestation-roots | string | — | a PEM file of authenticator vendor certificates; passkey attestation is verified against these | — |
-passkey-domain | string | — | 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 off | Settings › Sign-in › Passkeys: Domain passkeys are bound to |
-passkey-name | string | Perfuse | the name an authenticator shows a person when they register a passkey | Settings › Sign-in › Passkeys: Name shown on the device |
-passkey-origins | string | — | comma-separated origins the console is reached at, with scheme and port: https://perfuse.example.org. Defaults to https:// plus the domain | Settings › Sign-in › Passkeys: Other origins passkeys are accepted from |
-peers | string | — | YAML file listing other Perfuse instances to show in a fleet view | Settings › Fleet › Fleet: Other Perfuse servers to show (file) |
-public-url | string | — | 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 |
-rctc | string | — | eCR trigger codes for the case report preview: a FHIR ValueSet or Bundle of them, such as the eRSD | Settings › Public health › Case reporting: Trigger codes file (RCTC or eRSD) |
-residency | string | — | 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 refused | Settings › Data › Data protection: Where data may go (cloud regions) |
-retention-days | int | 30 | how long to keep recorded messages; 0 keeps them for ever, which will eventually fill the disk | Settings › Data › How long it is kept: Delete records after |
-saml | string | — | YAML file configuring SAML 2.0 sign-in (default: saml.yaml beside the database, once saved in the console) | — |
-scim | on/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 leaves | Settings › Sign-in › Automatic accounts: Let the identity provider manage accounts |
-scim-default-role | string | viewer | role 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 | — |
-settings | string | — | settings file the web interface may edit (default: perfuse-settings.yaml beside the database) | — |
-shl-allow-http | on/off | — | let a received SMART Health Link point at plain HTTP; for testing only | Settings › Public health › Health links: Allow SMART Health Links over plain HTTP |
-signing-cert | string | — | certificate for signing documents (defaults to -tls-cert) | Settings › Security › Document signing: Certificate for signing documents |
-signing-key | string | — | key for signing documents (defaults to -tls-key) | Settings › Security › Document signing: Key for signing documents |
-smart-audience | string | — | the audience a SMART token must be issued for, normally the FHIR base URL | Settings › SMART › Authorization: Audience tokens must name |
-smart-authorize | string | — | the authorization endpoint to advertise to SMART apps | Settings › SMART › Authorization: Authorization endpoint |
-smart-backend-services | on/off | — | advertise that the SMART authorization server issues backend-services (client_credentials, signed JWT) tokens | Settings › SMART › Built-in server: Backend Services (system-to-system tokens) |
-smart-clients | string | — | run Perfuse's own SMART authorization server at /auth for the apps registered in this YAML file | Settings › SMART › Built-in server: Registered apps file (turns on the built-in server) |
-smart-issuer | string | — | accept SMART on FHIR access tokens from this authorization server | Settings › SMART › Authorization: Accept SMART access tokens from this authorization server |
-smart-jwks | string | — | 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-uri | string | — | 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-key | string | smart-signing.key | the built-in authorization server's RSA signing key (PEM, mode 0600), created if missing | Settings › SMART › Built-in server: Signing key file |
-smart-oidc | string | — | 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_subject | Settings › SMART › Built-in server: Sign people in through the OpenID Connect provider |
-smart-token | string | — | the token endpoint to advertise to SMART apps | Settings › SMART › Authorization: Token endpoint |
-smart-users | string | — | 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-allow | string | — | comma-separated networks or addresses the SNMP agent answers, such as 10.0.5.0/24; required with -snmp-listen | Settings › Monitoring › SNMP: Networks that may ask |
-snmp-base-oid | string | 1.3.6.1.4.1.8072.9999.9999.16, Net-SNMP's experimental space | where Perfuse's values sit, under your enterprise number | Settings › Monitoring › SNMP: Base OID |
-snmp-community | string | — | the SNMPv2c community (a password sent in clear: at least 6 characters, not public or private) | Settings › Monitoring › SNMP: SNMP community |
-snmp-contact | string | — | sysContact the SNMP agent reports | Settings › Monitoring › SNMP: Contact (sysContact) |
-snmp-listen | string | — | answer SNMPv2c GET/GETNEXT/GETBULK on this UDP address, such as :161 (off when empty). Read-only: channel states, counts and queue depths | Settings › Monitoring › SNMP: Answer SNMP on this address |
-snmp-location | string | — | sysLocation the SNMP agent reports | Settings › Monitoring › SNMP: Location (sysLocation) |
-snmp-traps | string | — | comma-separated managers (host or host:port, default port 162) that receive an SNMPv2 trap when an alert fires or resolves | Settings › Monitoring › SNMP: Send traps to |
-store-messages | on/off | true | record every message handled, which is what makes the message browser work | Settings › Data › What is kept: Keep a record of each message |
-store-payloads | on/off | true | store message contents as well as their outcomes; turn this off where PHI must not be held at rest | Settings › Data › What is kept: Keep message contents |
-tls-cert | string | — | TLS certificate file | Settings › Security › Encryption: TLS certificate file |
-tls-key | string | — | TLS private key file | Settings › Security › Encryption: TLS private key file |
-trace-endpoint | string | — | OTLP/HTTP base URL to export message traces to, for example http://localhost:4318 | Settings › Monitoring › Tracing: Send traces to |
-trace-instance | string | — | name for this instance in traces; defaults to the hostname, which is what distinguishes replicas | Settings › Monitoring › Tracing: This instance's name in traces |
-trace-sample | float | 1 | fraction of traces to record, 0 to 1 | — |
-tsa-url | string | — | RFC 3161 time-stamping authority for DSDR signatures on claims attachments | Settings › Security › Document signing: Time-stamping authority |
-vpn | string | — | 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.yaml | Settings › Monitoring › Connections: VPN tunnels to watch (file) |
-watch-access | on/off | true | watch traffic and reads of patient data for what a breach looks like (bursts, night traffic, new destinations, bulk reads) and raise alerts | — |
-xds | string | — | 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/registry | Settings › Data › Document sharing (IHE XDS): Keep documents here as an XDS registry and repository |
-xds-home-community | string | — | this community's home community id (urn:oid:...), so /xca/gateway answers XCA ITI-38 and ITI-39 for it | Settings › Data › Document sharing (IHE XDS): Home community id, for XCA |
21 Kanalkatalog
Varje nyckel som kan förekomma på översta nivån i en kanalfil. Dessa extraheras från källan, så detta kapitel kan inte beskriva ett alternativ som inte finns eller utelämna ett som gör det.
21.1 Kanal
Kanal är en konfigurerad meddelandeflöde: någonstans anländer meddelanden, ett valfritt filter och en eller flera platser där de skickas.
Definierad som Channel i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
name | text | ja | — |
description | text | nej | — |
group | text | nej | — |
attachments | Bilagor (en block, utelämna för att inte använda) | nej | — |
delimited | Avgränsad (en block, utelämna för att inte använda) | nej | — |
tables | lista av text | nej | — |
contract | ContractRef (en block, utelämna för att inte använda) | nej | — |
enabled | true eller false (en block, utelämna för att inte använda) | nej | — |
dataType | DataType | nej | hl7 |
hl7v3 | HL7v3Options (en block, utelämna för att inte använda) | nej | — |
x12 | X12Options (en block, utelämna för att inte använda) | nej | — |
ncpdp | NCPDPOptions (en block, utelämna för att inte använda) | nej | — |
edifact | EDIFACTOptions (en block, utelämna för att inte använda) | nej | — |
script | ScriptOptions (en block, utelämna för att inte använda) | nej | — |
dicom | DICOMOptions (en block, utelämna för att inte använda) | nej | — |
source | Källa | ja | — |
filter | text | nej | — |
transformations | lista av transform.Step | nej | — |
scripts | Skript (en block, utelämna för att inte använda) | nej | — |
shadow | Skugga (en block, utelämna för att inte använda) | nej | — |
destinations | lista av Destination | ja | — |
21.1.1 namn
Namn identifierar kanalen i loggar och mått.
Obligatorisk och unik.
21.1.2 grupp
Grupp är vad denna kanal tillhör, för att organisera en lista som har vuxit för lång för att läsas.
Kosmetiskt vid fem kanaler och strukturellt vid två hundra: en webbplats kanaler delas av systemet de pratar med, eller av teamet som äger dem, och en platt lista med två hundra namn är oanvändbar hur bra resten av gränssnittet är.
En vanlig sträng snarare än en gruppobjekt med sin egen fil, eftersom en grupp inte har något beteende. I samma ögonblick som den har en fil förvärvar den inställningar, och inställningar på en grupp innebär att en kanals beteende beror på något som inte är skrivet i kanalen - vilket är den egenskap som gör Mirth-konfiguration svår att resonera om. Grupper här är en etikett och ingenting mer.
21.1.3 bilagor
Bilagor flyttar stora nyttolaster ut ur meddelandet och sätter tillbaka dem före leverans.
Frivilligt per kanal: en ström av rena ADT-meddelanden har ingenting att extrahera och bör inte betala för maskineriet.
21.1.4 avgränsad
Avgränsad konfigurerar en avgränsad kanal.
Endast meningsfull när datatypen är avgränsad.
21.1.5 tabeller
Tabellnamn filer med delade mappningstabeller som en transformation kan hänvisa till med namn.
Delade eftersom domänskatten till stor del är om-derivning av en mappning som någon redan har derivat: en webbplats könkoder och patientklasser översätts identiskt i varje kanal som rör dem, och en tabell inuti en kanal är en tabell som endast den kanalen kan använda.
21.1.6 aktiverad
Aktiverad är standard till true.
En inaktiverad kanal är laddad och validerad men inte startad, så en fil som tillfälligt är avstängd är fortfarande kontrollerad av CI.
21.1.7 datatyp
Datatyp är formatet på meddelandena som denna kanal tar emot.
Standard är hl7, så varje kanal som skrevs före detta fortsätter att fungera.
21.1.8 x12
X12 innehåller inställningar som endast har betydelse på en X12-kanal.
Att ställa in det på någon annan typ nekas snarare än ignoreras.
21.1.9 skript
Skript konfigurerar en NCPDP SCRIPT-kanal.
Dess steg finns här snarare än i överordnade transformationer för samma anledning som alla andra icke-v2-format: steptyperna skiljer sig per format, så en nyckel skulle betyda olika saker beroende på datatyp.
21.1.10 dicom
Bild konfigurerar en DICOM-kanals namngivna transformationssteg.
Namnet Bild snarare än DICOM eftersom Källa och Mål redan har ett DICOM-fält och tre fält med samma namn på olika nivåer är hur någon ställer in fel fält. YAML-nyckeln är dicom, vilket är vad en person som skriver filen förväntar sig, och Go-namnet är det som förhindrar ett misstag på anropsplatsen.
21.1.11 filter
Filter är ett uttryck som måste gälla för att ett meddelande ska vidarebefordras.
Ett meddelande som inte matchar bekräftas fortfarande: avsändaren gjorde inget fel, vi är bara inte intresserade.
21.1.12 transformationer
Transformationer är deklarativa ändringar som tillämpas på accepterade meddelanden, i ordning, innan något skript körs.
Detta är den lager som är tänkt att bära det vanliga arbetet: varje steg valideras när filen laddas, visas i en diff och kan granskas av någon som inte läser JavaScript.
21.1.13 skript
Skript innehåller JavaScript för de fall där de deklarativa stegen inte kan uttryckas, och är vad en Mirth-kanals egna skript hamnar i oförändrade.
En kanal med ett skript markeras som sådan i gränssnittet, eftersom dess beteende inte kan fastställas genom att läsa konfigurationen.
21.1.14 skugga
Skugga kör en kandidatversion av denna kanal bredvid den och rapporterar var de skiljer sig.
Ingenting den gör kan nå en mottagare.
22 Källreferens
Varje sätt som en kanal kan ta emot meddelanden och varje nyckel som var och en accepterar. En kanal har exakt en källa.
22.1 AMQP Källa
AMQP Källa tar emot från en kö eller prenumeration.
Ett meddelande accepteras bara efter att kanalen har hanterat det. Ett som inte kunde hanteras släpps som en misslyckad leverans, så att bryggan redeliverar det och - på Service Bus, förbi könens maximala leveransantal - dead-letterar det.
Definierad som AMQPSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
prefetch | heltal | nej | 10 |
reconnect | varaktighet, såsom 30s eller 5m | nej | 5s |
22.1.1 prefetch
Prefetch är hur många meddelanden som bryggan får skicka i förväg.
Standardvärdet är 10. De hanteras fortfarande en i taget, i ordning.
22.1.2 reconnect
Reconnect är väntetiden efter en förlorad anslutning.
Defaults to 5s.
22.2 AS2 Källa
AS2 Källa tar emot AS2 (RFC 4130): EDI som skickas via HTTP, signerad och krypterad med S/MIME, besvarad med en kvittens (en MDN) som innehåller en sammanfattning av vad som anlände.
Payloaden är vad kanalen hanterar; X12 och EDIFACT är de vanligaste.
Definierad som AS2Source i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | ja | — |
path | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
id | text | ja | — |
cert_file | text | ja | — |
key_file | text | ja | — |
partners | lista av AS2Partner | ja | — |
max_message_size | heltal | nej | — |
duplicate_window | varaktighet, såsom 30s eller 5m | nej | — |
22.2.1 sökväg
Sökvägen är den URL-sökväg som partners skickar till.
Default /as2.
22.2.2 tls
TLS tillhandahåller HTTPS.
De flesta partners kräver det i sitt avtal, utöver S/MIME.
22.2.3 id
ID är vår AS2-identifierare, som partners skickar i AS2-To.
Ett meddelande till någon annan nekas.
22.2.4 partners
Partners är de som kan skicka här.
Ett meddelande från någon annan avvisas.
22.2.5 duplicate_window
DuplicateWindow är hur länge en partners Message-ID kommas ihåg, så att ett meddelande som skickas igen (partnern fick aldrig vår kvittens och försökte igen) besvaras med en kvittens och inte skickas vidare två gånger (RFC 4130 avsnitt 7.5).
Default 30 days.
22.3 Azure Blob-källa
AzureBlobSource hämtar blobbar från en containerprefix.
Definieras som AzureBlobSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
prefix | text | ja | — |
suffix | text | nej | — |
after_read | text | nej | — |
move_to | text | nej | processed/ |
error_prefix | text | nej | error/ |
poll_interval | varaktighet, t.ex. 30s eller 5m | nej | 30s |
max_object_size | heltal | nej | 16 MiB |
framed | true eller false | nej | — |
22.3.1 move_to
MoveTo är var en hanterad blob flyttas.
Standard är processed/.
22.3.2 error_prefix
ErrorPrefix är var en blob som inte kan hanteras flyttas, så att den inte blockerar resten.
Standard är error/.
22.3.3 poll_interval
PollInterval mellan listningar.
Defaults to 30s.
22.3.4 max_object_size
MaxObjectSize vägrar en större blob, som lämnas där den är.
Standard är 16 MiB.
22.4 Mäklarkälla
BrokerSource läser meddelanden från en meddelandemäklare.
Mirths JMS-läsare, nådd via STOMP eftersom JMS är en Java-API och inte ett protokoll. Se internal/stomp för varför STOMP och inte OpenWire.
Definieras som BrokerSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
addr | text | ja | — |
destination | text | ja | — |
login | text | nej | — |
passcode | text | nej | — |
host | text | nej | adressens värd |
selector | text | nej | — |
subscription_id | text | nej | kanalnamn |
heartbeat | varaktighet, t.ex. 30s eller 5m | nej | trettio sekunder |
reconnect | varaktighet, t.ex. 30s eller 5m | nej | fem sekunder |
timeout | varaktighet, t.ex. 30s eller 5m | nej | trettio sekunder |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
22.4.1 addr
Addr är värden och porten för medlaren.
Obligatoriskt. 61613 är den vanliga STOMP-porten.
22.4.2 destination
Mål är kön eller ämnet som ska läsas från.
Required.
Medlare stavar dessa olika - /queue/namn på ActiveMQ, ett naket namn på RabbitMQ - så det skickas igenom oförändrat snarare än att sättas samman här. Att gissa skulle innebära att arbeta mot en medlare och tyst läsa ingenting på en annan.
22.4.3 inloggning
Inloggning och lösenkod autentiserar.
De flesta medlare vägrar en anonym anslutning.
22.4.4 lösenkod
Inloggning och lösenkod autentiserar.
De flesta medlare vägrar en anonym anslutning.
22.4.5 värd
Värd är den virtuella värden.
Standardvärdet är värden för adressen.
22.4.6 väljare
Väljare filtrerar meddelanden på medlaren.
En JMS-väljare, som skickas igenom snarare än tolkas. Att filtrera på medlaren snarare än här innebär att meddelanden som denna kanal inte vill ha aldrig korsar nätverket - vilket på en delad kö är skillnaden mellan att läsa hundra meddelanden om dagen och hundratusen.
22.4.7 prenumerations_id
PrenumerationsID namnger prenumerationen.
Standardvärdet är kanalnamnet.
Namngiven snarare än genererad, eftersom en varaktig prenumeration identifieras av den: en genererad skulle skapa en ny prenumeration vid varje omstart och lämna de gamla prenumerationerna som ackumulerar meddelanden som ingen läser.
22.4.8 hjärtslag
Hjärtslag håller anslutningen vid liv.
Standardvärdet är trettio sekunder.
På som standard här, till skillnad från klientens eget standardvärde, eftersom en källa håller en anslutning öppen i veckor. Utan hjärtslag ser en anslutning genom en brandvägg som tyst har tagit bort rutten ut perfekt frisk från den här änden och meddelanden slutar helt enkelt anlända, utan att något loggas.
22.4.9 reconnect
Omkoppling är hur länge man ska vänta innan man återansluter efter ett fel.
Standardvärdet är fem sekunder.
22.4.10 tidsgräns
Tidsgränser för anslutning.
Standardvärdet är trettio sekunder.
22.5 DICOM-frågekälla
DICOMQuerySource pollar ett arkiv med C-FIND och skickar ett meddelande per ny studie.
Mirth har ingen motsvarande anslutning. Dess DICOM-stöd är en lyssnare och en avsändare - den kan ta emot bilder som skickas till den och skicka dem vidare, och det är allt. Att fråga ett arkiv vad det innehåller har begärts på deras forum sedan 2015.
Det som gör det värt att ha är inte frågan, det är automatiseringen: en förkörsel som körs klockan tre på morgonen, en avstämning som märker att arkivet saknar en studie som RIS säger finns, en arbetslista byggd från vad som faktiskt skannades snarare än vad som beställdes. Det är jobb som webbplatser för närvarande gör med ett schemalagt skript utanför motorn, vilket innebär att de är osynliga för den - ingen omprövning, ingen varning, ingen meddelandehistorik.
Definierad som DICOMQuerySource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
address | text | ja | — |
called_ae | text | ja | — |
calling_ae | text | nej | — |
level | text | nej | STUDY |
patient_root | true eller false | nej | — |
match | mappning av text till text | nej | — |
return | lista av text | nej | — |
interval | varaktighet, såsom 30s eller 5m | ja | — |
window | varaktighet, såsom 30s eller 5m | nej | — |
overlap | varaktighet, såsom 30s eller 5m | nej | en timme |
limit | heltal | nej | 500 |
timeout | varaktighet, såsom 30s eller 5m | nej | två minuter |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
emit_on_first_poll | true eller false | nej | false |
22.5.1 adress
Adressen är arkivets värd och port.
Required.
Namngiven för att matcha DICOM-målet snarare än förkortad. De två var "adress" och "addr" under en eftermiddag, vilket är den sortens inkonsekvens som någon som skriver en kanal fil för hand får fel en gång och sedan misstror hela formatet över.
22.5.2 anropad_ae
Anropad AE är arkivets AE-titel.
Obligatorisk i praktiken: de flesta arkiv vägrar en association som är adresserad till något annat, och det vägrar att läsa som en konfigurationsfel snarare än som en driftstörning.
22.5.3 anropande_ae
Anropande AE är den AE-titel som Perfuse presenterar.
Arkiv använder den vanligtvis för åtkomstkontroll.
22.5.4 nivå
Nivå är frågenivån: PATIENT, STUDIE, SERIE eller BILD.
Standard är STUDIE.
STUDIE är standard eftersom det är vad nästan alla användbara frågor vill ha och eftersom alternativen förvånar människor: BILD-nivå mot en stor CT returnerar ett svar per skiva, vilket är hundratals per studie.
22.5.5 match
Match är frågetangenterna.
Ett värde filtrerar; ett tomt värde ber om att fältet ska returneras.
Tangenter är namngivna snarare än numrerade - "PatientID" snarare än "0010,0020" - eftersom en kanal fil läses av människor, och en taggnummer i en konfigurationsfil är en sökning som varje läsare måste utföra.
22.5.6 returnera
Return är fält som ska returneras utan filtrering på dem.
Separera från Match med ett tomt värde, även om de kodar identiskt, eftersom avsikten skiljer sig och en läsare kan se vilka nycklar som begränsar sökningen och vilka som samlas in.
22.5.7 intervall
Intervall är hur ofta man ska fråga.
Required.
22.5.8 fönster
Fönster är hur långt tillbaka varje fråga tittar, som en studie datumintervall.
Noll inaktiverar datumfiltrering helt.
Ett fönster är vad som håller detta begränsat. Utan ett, frågar varje fråga arkivet om allt det någonsin har haft och sedan släpper det som det har sett tidigare - vilket fungerar på ett testarkiv och är antisocialt mot ett riktigt arkiv som innehåller miljontals studier.
22.5.9 överlappning
Överlappning frågar om detta så långt in i den redan frågade perioden.
Standard är en timme.
Nödvändig snarare än försiktig. En studie kan registreras med gårdagens datum, vår klocka och arkivets behöver inte överensstämma, och en frågegräns som sammanfaller exakt med en ankomst förlorar den. Överlappningsfrågan frågar om igen, och den redan sedda kontrollen stoppar dubletten - så kostnaden för överlappning är en något större fråga och kostnaden för att inte överlappa är en tyst missad studie.
22.5.10 gräns
Gräns begränsar antalet träffar som accepteras från en fråga.
Defaults to 500.
En gräns snarare än ingen gräns eftersom en felaktigt skriven matchningsnyckel förvandlar detta till "ge mig allt", och det första symtomet på detta mot ett riktigt arkiv är arkivets administratör som frågar vem som slår på det.
22.5.11 tidsgräns
Tidsgräns begränsar en fråga.
Standard är två minuter.
22.5.12 emit_on_first_poll
EmitOnFirstPoll skickar meddelanden för allt som den första frågan hittar.
Standard är falskt.
Falskt är viktigt. Att peka på ett arkiv som redan innehåller en miljon studier och ha det skicka ett meddelande för varje är inte en användbar första körning, och det är den typen av misstag som märks nedströms snarare än här. Den första frågan registrerar vad som finns och skickar ingenting; den andra frågan och framåt rapporterar vad som är nytt.
22.6 DICOM-källa
DICOM-källa tar emot bildobjekt som en C-STORE-tjänsteklassleverantör.
Vad ett sjukhus pekar en modalitet eller en PACS på. Mirth kallar detta för DICOM-lyssnaren och det gör bara C-STORE, så detta är jämlikhet snarare än en undermängd.
Definieras som DICOMSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | ja | — |
ae_title | text | nej | — |
allowed_calling_ae | lista med text | nej | — |
sop_classes | lista med text | nej | — |
transfer_syntaxes | lista med text | nej | — |
max_object_bytes | heltal | nej | — |
idle_timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
22.6.1 lyssna
Lyssna är adressen att betjäna på.
Obligatoriskt. 104 är den registrerade DICOM-porten; 11112 är den vanliga alternativet där bindning av en privilegerad port inte är möjlig.
22.6.2 ae_title
AETitle är vad denna slutpunkt kallar sig själv.
Starkt rekommenderat snarare än obligatoriskt, och varnas om när den är frånvarande. En webbplats enda åtkomstkontroll på en DICOM-slutpunkt är ofta AE-titeln, så en slutpunkt som accepterar vilken titel som helst accepterar allt som kan nå den.
22.6.3 allowed_calling_ae
AllowedCallingAE listar de AE-titlar som tillåts ansluta.
Tom accepterar alla anropare.
Detta är den åtkomstkontroll som DICOM faktiskt har. En PACS konfigureras vanligtvis för att acceptera en namngiven anropande titel och avvisa allt annat, och denna ände hade ingen motsvarighet: den anropade titeln kontrollerades - vilket är namnet som anroparen slår, så vem som helst kan skicka det korrekt - medan vem som anropade loggades och annars ignorerades.
Tom accepterar fortfarande allt, eftersom en modality som ingen har listat är det normala tillståndet för en första installation och att vägra som standard skulle bryta varje distribution på dag ett. Den varnar istället, och varningen namnger de titlar som har anslutit så att någon kan fylla i detta från vad som faktiskt anlände.
22.6.4 sop_classes
SOPClasses begränsar vilka typer av objekt som ska accepteras.
Tom accepterar alla.
Tom är ett rimligt standardvärde här eftersom denna motor förmedlar objekt snarare än tolkar dem, så att vägra ett okänt klass skulle vägra giltiga bilder utan någon fördel.
22.6.5 transfer_syntaxes
TransferSyntaxes begränsar kodningarna som ska accepteras, i preferensordning.
Tom accepterar de okomprimerade tre.
22.6.6 max_object_bytes
MaxObjectBytes begränsar ett mottaget objekt.
Noll tillämpar ett standardvärde.
22.6.7 idle_timeout
IdleTimeout stänger en association som har blivit tyst.
Noll betyder aldrig, vilket vanligtvis är rätt - en modalitet håller en association öppen mellan studier.
22.6.8 tls
TLS krypterar inkommande associationer och kan kräva ett klientcertifikat.
Det är värt att säga rakt ut: Mirth behöver sin betalda SSL Manager-tillägg för detta, och community-forkarna kan inte leverera det alls. DICOM bär patientnamn i sin metadata, så detta är en av de platser där att vara en omskrivning snarare än en fork är en riktig fördel snarare än en stilistisk.
22.7 DICO Mweb Källa
DICOMwebSource accepterar STOW-RS-förfrågningar.
Definierad som DICOMwebSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | ja | — |
path | text | nej | /dicom-web |
token | text | nej | — |
username | text | nej | — |
password | text | nej | — |
max_object_bytes | heltal | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
22.7.1 lyssna
Lyssna är adressen att betjäna på.
Required.
22.7.2 sökväg
Sökväg är tjänstrot.
Objekt accepteras på Sökväg/studier och Sökväg/studier/{uid}. Standard är /dicom-web, vilket är vad Orthanc och dcm4chee använder, så en avsändare konfigurerad för antingen behöver bara ändra värd.
22.7.3 token
Token, när den är inställd, krävs som en bearer-token.
Användarnamn och Lösenord kräver HTTP-basautentisering.
22.7.4 användarnamn
Token, när den är inställd, krävs som en bearer-token.
Användarnamn och Lösenord kräver HTTP-basautentisering.
22.7.5 lösenord
Token, när den är inställd, krävs som en bearer-token.
Användarnamn och Lösenord kräver HTTP-basautentisering.
22.8 Databas Källa
DatabaseSource läser rader från en databas och omvandlar var och en till ett meddelande.
Detta är hur de flesta sjukhusgränssnitt faktiskt börjar. Ett avdelningssystem har ingen HL7-funktion, så någon skriver rader till en mellanlagrings-tabell och gränssnittsmotorn pollar den. Det är oglamoröst och det är överallt.
Det är också det vanligaste sättet ett Mirth-kanal stannar, och orsaken är nästan alltid av samma form: en rad som inte kan bearbetas läses, misslyckas och läses igen, för alltid, eftersom ingenting markerade den. Kanalen ser levande ut. Köerna ser tomma ut. Ingenting rör sig, och varje meddelande bakom den dåliga raden väntar på en rad som aldrig kommer att lyckas.
Större delen av designen här handlar om det.
Definierad som DatabaseSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
driver | text | ja | — |
dsn | text | ja | — |
query | text | ja | — |
after_query | text | nej | — |
key_column | text | nej | — |
template | text | nej | — |
column | text | nej | — |
poll_interval | varaktighet, såsom 30s eller 5m | nej | — |
batch_size | heltal | nej | 100 |
max_attempts | heltal | nej | 3 |
query_timeout | varaktighet, såsom 30s eller 5m | nej | 30s |
22.8.1 drivrutin
Drivrutin namnger databasen.
See SupportedDrivers.
22.8.2 dsn
DSN är anslutningssträngen.
Föredra en miljövariabelreferens över en bokstav, eftersom detta vanligtvis innehåller ett lösenord och kanaler är avsedda att finnas i git.
22.8.3 fråga
Frågan väljer de rader som väntar på att skickas.
Required.
Det måste vara en SELECT. En poll som tyst utförde skrivningar skulle köra på en schemalagd tid med ingen post om vad den ändrade.
22.8.4 efter_fråga
AfterQuery markerar en rad som bearbetad och körs med radens nyckel bunden till den.
Strongly recommended.
Utan det läser varje poll om varje rad som frågan fortfarande matchar, så frågan själv måste utesluta bearbetade rader på något annat sätt. Om ingen av dem är sann skickar kanalen om samma rader för alltid, vilket är en dubblettstorm snarare än ett stopp och är möjligen värre.
22.8.5 nyckelkolumn
KeyColumn identifierar en rad för AfterQuery, karantän och dubblettreducering.
Krävs när AfterQuery är inställd.
22.8.6 mall
Mall bygger ett meddelande från en rad.
Antingen detta eller Kolumn krävs.
Kolumnreferenser använder ${kolumn_namn}. Saknade kolumner är ett fel vid inläsning snarare än en tom sträng i ett kliniskt meddelande.
22.8.7 batchstorlek
BatchSize begränsar antalet rader som tas per poll.
Defaults to 100.
Begränsad eftersom en obegränsad första poll mot en tabell som någon har fyllt i ett år skulle läsa in allt i minnet och sedan skicka allt, vilket är hur en migration översvämmar en live-mottagare.
22.8.8 max_försök
MaxFörsök är hur många gånger en enskild rad får misslyckas innan den karantäniseras och pollningen fortsätter.
Defaults to 3.
Detta är inställningen som förhindrar stoppet. Att försöka för alltid är inte motståndskraft; det är en dålig rad som stoppar en sjukhusmatning.
22.8.9 frågetid
QueryTimeout begränsar en enskild poll.
Defaults to 30s.
22.9 Direkt Källa
DirektKälla tar emot Direkt-e-post som HISP levererar: en SMTP-lyssnare för denna adressens e-post.
Varje meddelande dekrypteras, dess signatur kontrolleras mot förankringarna och dess avsändare mot Från, och dess innehåll skickas vidare: en XDM-pakets dokument, annars varje bilaga, annars texten.
Definieras som DirectSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | nej | — |
tls_cert | text | nej | — |
tls_key | text | nej | — |
max_bytes | heltal | nej | — |
smtp_host | text | nej | — |
username | text | nej | — |
password | text | nej | — |
imap | DirectIMAP (en block, utelämna för att inte använda) | nej | — |
xdr | DirectXDR (en block, utelämna för att inte använda) | nej | — |
22.9.1 smtp_host
SMTPHost, användarnamn och lösenord är HISP:s inlämningsserver, som används för att skicka en "bearbetad" leveransmeddelande (MDN) till avsändaren när ett meddelande har tagits emot.
Utan det skickas inget meddelande.
22.9.2 användarnamn
SMTPHost, användarnamn och lösenord är HISP:s inlämningsserver, som används för att skicka en "bearbetad" leveransmeddelande (MDN) till avsändaren när ett meddelande har tagits emot.
Utan det skickas inget meddelande.
22.9.3 lösenord
SMTPHost, användarnamn och lösenord är HISP:s inlämningsserver, som används för att skicka en "bearbetad" leveransmeddelande (MDN) till avsändaren när ett meddelande har tagits emot.
Utan det skickas inget meddelande.
22.10 E-postkälla
E-postkällan läser e-post från en inkorg och omvandlar bilagor, meddelandetext eller hela meddelanden till meddelanden.
Definierad som EmailSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
protocol | text | nej | — |
host | text | ja | — |
port | heltal | nej | — |
security | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
username | text | ja | — |
password | text | nej | — |
oauth | EmailOAuth (en block, utelämna för att lämna av) | nej | — |
mailbox | text | nej | — |
take | text | nej | — |
attachment_names | lista av text | nej | — |
allowed_senders | lista av text | nej | — |
after_read | text | nej | — |
move_to | text | nej | — |
error_folder | text | nej | — |
poll_interval | varaktighet, såsom 30s eller 5m | nej | — |
max_message_size | heltal | nej | — |
22.10.1 lösenord
Lösenord kan vara ${ENV}; för Gmail krävs ett app-lösenord.
Ignoreras med oauth.
22.10.2 bilage_namn
BilageNamn begränsar vilka bilagor som tas, efter filnamnsmönster (*.hl7).
Tom tar alla bilagor.
22.10.3 tillåtna_avsändare
TillåtnaAvsändare begränsar vars e-post som läses: adresser och domäner.
Från-rubriken kan förfalskas, så detta håller borta olyckor och tillfällig e-post, men inte en angripare.
22.10.4 move_to
FlyttaTill är den mapp som hanterad e-post flyttas till; som standard är det Bearbetad.
Skapas när den saknas.
22.11 FTP-källa
FTP-källan samlar in filer från en FTP- eller FTPS-server.
Varför FTP fortfarande finns
Det är trettio år sedan det rekommenderades att ersätta det och många sjukvårdssystem exporterar fortfarande till det: apparater vars firmware aldrig kommer att uppdateras, faktureringssystem vars leverantör tar betalt för en ändring. Att vägra tala det språket gör inte att systemen försvinner, det innebär att integrationsmotorn inte kan användas.
FTPS är standard. Det är samma protokoll med TLS, de flesta överlevande servrar stöder det och det är ett mycket enklare samtal med ett säkerhetsteam än vanligt FTP.
Definierad som FTPSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
host | text | ja | — |
user | text | nej | — |
password | text | nej | — |
security | ftpconn.Security | nej | explicit |
insecure_skip_verify | true eller false | nej | — |
root | text | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | trettio sekunder |
22.11.1 värd
Värden är servern, med ett valfritt portnummer.
Port 21 antas.
22.11.2 användare
Användare och lösenord autentiserar.
Båda kan utelämnas för en anonym server.
Anonym FTP är fortfarande hur vissa offentliga referensflöden publiceras, så en tom användare är en giltig konfiguration snarare än ett förbiseende och avvisas inte. På en server som förväntar sig autentiseringsuppgifter leder utelämnandet av dem till en inloggningsfel vid anslutningstid, som rapporteras mot kanalen snarare än återförsök tyst.
22.11.3 lösenord
Användare och lösenord autentiserar.
Båda kan utelämnas för en anonym server.
Anonym FTP är fortfarande hur vissa offentliga referensflöden publiceras, så en tom användare är en giltig konfiguration snarare än ett förbiseende och avvisas inte. På en server som förväntar sig autentiseringsuppgifter leder utelämnandet av dem till en inloggningsfel vid anslutningstid, som rapporteras mot kanalen snarare än återförsök tyst.
22.11.4 säkerhet
Säkerheten är explicit, implicit eller ingen.
Standard är explicit, vilket är FTPS förhandlat med AUTH TLS på den vanliga porten. "Ingen" är vanlig FTP och måste begäras med namn.
22.11.5 rot
Roten är katalogen som alla sökvägar är relativa till, och vad inneslutning verkställs mot.
Servern har ingen kännedom om den: en FTP-server accepterar gärna ../.. som en sökväg. Så detta är vad som förhindrar att en move_to skriver var som helst kontot kan nå.
22.11.6 tidsgräns
Tidsgräns begränsar en operation, inte hela pollningen.
Standardvärdet är trettio sekunder.
Per operation eftersom en pollning som listar en katalog och hämtar tjugo filer utför tjugoett operationer, och en enda budget för alla skulle avbryta en fullständigt frisk överföring av en stor fil.
22.12 Filkälla
FileSource läser filer från en katalog som servern kan se.
Den anslutning som en webbplats försöker först
En analyserare skriver resultat till en mapp. Ett faktureringsystem släpper en batch över natten. Radiologi exporterar rapporter till en katalog som någon monterade för år sedan. Inget av det involverar ett protokoll, och en integrationsmotor som inte kan läsa en mapp misslyckas med sin utvärdering på första eftermiddagen.
Definierad som FileSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
root | text | ja | — |
follow_symlinks | true eller false | nej | — |
22.12.1 rot
Rotten begränsar varje sökväg som denna källa berör.
Required.
Separat från Dir så att move_to och error_dir kan vara relativa och fortfarande vara inneslutna. Om endast Dir anges, skulle en error_dir på "../failed" vara utanför allt som källan hade fått, och att vägra det skulle vara godtyckligt eftersom det inte skulle finnas något att vägra det mot.
22.13 GCS-källa
GCSSource plockar upp objekt från en bucket-prefix, som s3- och azure_blob-källorna gör.
Definieras som GCSSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
prefix | text | ja | — |
suffix | text | nej | — |
after_read | text | nej | — |
move_to | text | nej | processed/ |
error_prefix | text | nej | error/ |
poll_interval | varaktighet, t.ex. 30s eller 5m | nej | 30s |
max_object_size | heltal | nej | 16 MiB |
framed | true eller false | nej | — |
22.13.1 move_to
MoveTo är var ett hanterat objekt hamnar efter att after_read är move.
Standard är processed/.
22.13.2 error_prefix
ErrorPrefix är var ett objekt som inte kunde hanteras hamnar.
Standard är error/.
22.13.3 poll_interval
PollInterval är hur ofta prefixet listas.
Defaults to 30s.
22.13.4 max_object_size
MaxObjectSize lämnar större objekt där de är.
Standard är 16 MiB.
22.14 HTTP-källa
HTTP-källan accepterar meddelanden via HTTP.
En lyssnare snarare än en poller: något skickar ett meddelande och får en bekräftelse tillbaka, vilket är hur den moderna halvan av sjukhuset integrerar när MLLP inte är tillgänglig för det.
Definieras som HTTPSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | ja | — |
path | text | nej | "/" |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
token | text | nej | — |
max_message_size | heltal | nej | — |
read_timeout | varaktighet, såsom 30s eller 5m | nej | — |
ack | Ack | nej | — |
22.14.1 lyssna
Lyssna är adressen att betjäna på.
Required.
22.14.2 sökväg
Sökväg är URL-sökvägen för att acceptera meddelanden på.
Defaults to "/".
22.14.3 token
Token, när den är inställd, krävs i en Authorization: Bearer-rubrik.
Det finns ingen standard och ingen anonym läge-omkopplare: en HTTP-slutpunkt på ett sjukhusnätverk med ingen autentisering alls är ett beslut som måste vara synligt i filen, så att lämna detta tomt rapporteras som en varning vid inläsning.
22.14.4 max_meddelandestorlek
MaxMeddelandestorlek begränsar en inkommande kropp.
Noll tillämpar ett standardvärde.
22.15 IBMMQ-källa
IBMMQ-källan läser en kö.
Definieras som IBMMQSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
poll_interval | varaktighet, såsom 30s eller 5m | nej | 2s |
22.15.1 poll_interval
PollInterval är väntetiden när kön är tom, eller efter ett meddelande som inte kunde hanteras.
Defaults to 2s.
22.16 Java Script-källa
JavaScript-källan konfigurerar en källa som kör ett skript på en timer och matar in de returnerade meddelandena i kanalen.
Detta är motsvarigheten till Mirths "JavaScript-läsare".
Skriptet körs i en goja-VM med samma sandlåda som transformerings-skript: msg är inte tillgänglig (det finns inget inkommande meddelande ännu), men globalMap, configurationMap, logger och DateUtil är närvarande. Skriptet måste returnera en sträng (ett meddelande) eller en array av strängar (många). Att returnera ingenting eller en tom array innebär att pollningen inte producerade några meddelanden, vilket är normalt.
Definieras som JavaScriptSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
script | text | ja | — |
poll_interval | varaktighet, t.ex. 30s eller 5m | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
22.16.1 poll_interval
PollInterval anger hur ofta skriptet körs.
Noll betyder 5 sekunder.
22.16.2 tidsgräns
Timeout begränsar en enskild skriptkörning.
Noll betyder 30 sekunder.
22.17 Kafka-källa
KafkaSource läser meddelanden från ett Kafka-ämne.
Definieras som KafkaSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
brokers | lista med text | ja | — |
topics | lista med text | ja | — |
group | text | ja | — |
from_beginning | true eller false | nej | — |
commit_after_delivery | true eller false (en block, utelämna för att lämna av) | nej | — |
max_message_size | heltal | nej | kanallimiten |
session_timeout | varaktighet, t.ex. 30s eller 5m | nej | fyrtiofem sekunder |
timeout | varaktighet, t.ex. 30s eller 5m | nej | trettio sekunder |
sasl | KafkaSASL (en block, utelämna för att lämna av) | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
22.17.1 mäklare
Mäklare är bootstrap-serverlistan.
Required.
En lista istället för en adress, eftersom en enda bootstrap-mäklare är en enda felkälla för start: klustret överlever att förlora den och denna kanal skulle inte.
22.17.2 ämnen
Ämnen är de ämnen som ska läsas.
Minst ett krävs.
22.17.3 grupp
Grupp är konsumentgruppen.
Required.
Namngiven istället för genererad, och obligatorisk istället för standard, eftersom det är vad som kommer ihåg hur långt denna kanal har läst. En genererad grupp skulle starta från början - eller från slutet, och förlora allt - vid varje omstart, och den skulle lämna den gamla gruppen kvar som håller kommitterade offset som ingen läser. Att kräva det gör att personen namnger det som måste förbli detsamma över omstarter.
22.17.4 from_beginning
FromBeginning läser ämnet från dess början när gruppen inte har någon kommitterad offset.
Avstängd som standard, så en ny kanal som pekar på ett ämne med två års historia inte återuppspelas två års patienthändelser i ett live-system på den dag det aktiveras. Den första personen som träffar det skulle göra det i produktion, eftersom det är där ämnet med historiken är.
22.17.5 commit_after_delivery
CommitAfterDelivery committerar offseten endast när meddelandet har hanterats.
På som standard, och anledningen är hela skillnaden mellan att förlora ett meddelande och se det två gånger. Att committera på läsning innebär att en krasch mellan committen och leveransen tyst förlorar meddelandet, och ingenting någonstans registrerar att det existerade. Att committera efter innebär att en krasch i samma fönster levererar det igen, vilket är synligt och vilket HL7-mottagare är byggda för att tolerera - en dubblett A08 är ett besvär och ett saknat laboratorie resultat är en patientsäkerhets händelse.
22.17.6 max_meddelandestorlek
MaxMessageSize begränsar en enskild post.
Standard är kanallimiten.
22.17.7 session_timeout
SessionTimeout anger hur länge gruppkoordinatorn väntar innan den antar att den här konsumenten är borta och återger dess partitioner.
Standard är fyrtiofem sekunder.
22.17.8 tidsgräns
Tidsgränser för anslutning och metadataförfrågningar.
Standardvärdet är trettio sekunder.
22.18 MQTT Källa
MQTTSource prenumererar på en ämnesfilter.
Definierad som MQTTSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
topic | text | ja | — |
reconnect | varaktighet, t.ex. 30s eller 5m | nej | 5s |
22.18.1 reconnect
Reconnect är väntetiden efter en förlorad anslutning eller efter ett meddelande som inte kunde hanteras.
Defaults to 5s.
22.19 Pub Sub Källa
PubSubSource hämtar från en Pub/Sub-prenumeration.
Definierad som PubSubSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
subscription | text | ja | — |
max_messages | heltal | nej | 10 |
reconnect | varaktighet, t.ex. 30s eller 5m | nej | 5s |
22.19.1 max_messages
MaxMessages anger hur många som hämtas på en gång.
De hanteras fortfarande en i taget, i ordning. Standard är 10.
22.19.2 reconnect
Reconnect är väntetiden efter ett fel.
Defaults to 5s.
22.20 S3 Källa
S3Source hämtar objekt från en bucket.
Definierad som S3Source i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
bucket | text | ja | — |
path_style | true eller false | nej | — |
prefix | text | nej | — |
suffix | text | nej | — |
after_read | text | nej | — |
move_to | text | nej | processed/ |
error_prefix | text | nej | error/ |
poll_interval | varaktighet, t.ex. 30s eller 5m | nej | 30s |
max_object_size | heltal | nej | 16 MiB |
framed | true eller false | nej | — |
22.20.1 prefix
Prefix begränsar vilka objekt som läses, t.ex. inbound/.
Tomma läser hela bucket, vilket vägras med after_read: move såvida move_to inte är utanför den - annars skulle flyttade objekt läsas igen.
22.20.2 after_read
AfterRead är antingen flytta (standard) eller ta bort.
Det finns inget lämna: en bucket har ingen fil som en poller kan komma ihåg att ha sett över en omstart, så att lämna objekt innebär att läsa dem alla igen varje gång Perfuse startas.
22.20.3 move_to
MoveTo är prefixet som ett hanterat objekt flyttas till.
Standard är processed/.
22.20.4 error_prefix
ErrorPrefix är var ett objekt som inte kunde hanteras flyttas, så att en dålig fil inte blockerar resten.
Standard är error/.
22.20.5 poll_interval
PollInterval mellan listningar.
Defaults to 30s.
22.20.6 max_object_size
MaxObjectSize vägrar allt som är större.
Standard är 16 MiB.
22.20.7 ramad
Framed läser flera MLLP-ramade meddelanden från ett objekt.
Annars är ett objekt ett meddelande.
22.21 SFTP-källa
SFTPSource samlar in meddelanden från en katalog på en SFTP-server.
Mycket vanligt och sällan talat om. Ett laboratorium eller ett radiologisystem skriver en fil var få minuter, en SFTP-server håller den, och något måste komma och hämta den. Hälften av de flöden som beskrivs som "vi skickar er HL7" är detta.
Den del som är värd att bry sig om är inte överföringen. Det är att en fil som skrivs till och en fil som är färdigskriven ser identiska ut över SFTP, så en poll som är ens lite för ivrig samlar in halva meddelandet. Det producerar ett trunkerat men ofta parsbart HL7-meddelande, vilket är den sämsta möjliga utgången: det accepteras, bekräftas, lagras och levereras, och den saknade halvan nämns aldrig igen.
Definierad som SFTPSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
host | text | ja | 22 |
user | text | ja | — |
password | text | nej | — |
key_file | text | nej | — |
key_passphrase | text | nej | — |
known_hosts_file | text | nej | — |
insecure_skip_host_key_check | true eller false | nej | — |
dir | text | ja | — |
pattern | text | nej | allt |
poll_interval | varaktighet, t.ex. 30s eller 5m | nej | — |
after_read | text | nej | — |
move_to | text | nej | — |
error_dir | text | nej | — |
stable_for | varaktighet, t.ex. 30s eller 5m | nej | 5s |
framed | true eller false | nej | — |
max_file_size | heltal | nej | 64MB |
timeout | varaktighet, t.ex. 30s eller 5m | nej | 60s |
22.21.1 värd
Värden är servern, med ett valfritt portnummer.
Defaults to 22.
22.21.2 lösenord
Lösenord autentiserar med ett lösenord.
Prefer KeyFile.
22.21.3 key_file
KeyFile är en privat nyckel.
Det bättre valet, och det som sjukhusens säkerhetsteam ber om.
22.21.4 known_hosts_file
KnownHostsFile verifierar serverns identitet.
Obligatorisk om inte InsecureSkipHostKeyCheck är inställt. Utan det finns inget som skiljer den riktiga servern från allt som svarar på den adressen, och autentiseringsuppgifterna lämnas över innan någon märker det.
22.21.5 insecure_skip_host_key_check
InsecureSkipHostKeyCheck accepterar alla värdnycklar.
Existerar eftersom att direkt vägra skickar människor till ett shell-skript med StrictHostKeyChecking=no, vilket är sämre på alla sätt, inklusive granskningsbarhet. Det varnar högt och det är aldrig standard.
22.21.6 mönster
Mönstret väljer filer med glob.
Standard är allt.
22.21.7 move_to
MoveTo är den fjärrkatalog som filer flyttas till efter läsning.
Krävs när AfterRead är "flytta".
22.21.8 stabil för
StabilFor är hur länge en fils storlek och ändringstid måste vara oförändrad innan den läses.
Defaults to 5s.
Detta är inställningen som förhindrar att halva meddelandet samlas in. Noll betyder att läsa allt som finns, vilket fungerar tills en fil är tillräckligt stor eller ett nätverk tillräckligt långsamt så att skrivning tar längre tid än en avläsning.
22.21.9 ramad
Framed anger att filen innehåller MLLP-ramade meddelanden.
När detta är falskt, delas filen på MSH-gränser.
22.21.10 max_fil_storlek
MaxFilStorlek vägrar en fil som är större än detta antal byte.
Standard är 64 MB.
22.21.11 tidsgräns
Tidsgräns begränsar en enskild anslutning.
Defaults to 60s.
22.22 SMB-källa
SMB-källan samlar in filer från en Windows-filresurs.
Definierad som SMBSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
host | text | ja | — |
share | text | ja | — |
user | text | nej | — |
password | text | nej | — |
domain | text | nej | — |
root | text | nej | — |
timeout | varaktighet, såsom 30s eller 5m | nej | trettio sekunder |
22.22.1 värd
Värden är servern, med ett valfritt portnummer.
Port 445 antas.
22.22.2 delad
Delad är delningsnamnet endast: "data" i \\\server\data.
En sökväg här vägras snarare än trimmas.
22.22.3 användare
Användare och Lösenord är det Windows-konto.
Krävs i praktiken.
En delad resurs som kan nås utan några autentiseringsuppgifter alls är tillräckligt ovanlig på en domän så att ett tomt användarnamn här troligen är ett misstag snarare än en gästdelad resurs - men det accepteras, eftersom att vägra det skulle blockera den ena arrangementet där det är korrekt. Om kontot tillhör en domän, ange Domän också: att autentisera ett domänkonto utan det misslyckas på ett sätt som liknar ett felaktigt lösenord.
22.22.4 lösenord
Användare och Lösenord är det Windows-konto.
Krävs i praktiken.
En delad resurs som kan nås utan några autentiseringsuppgifter alls är tillräckligt ovanlig på en domän så att ett tomt användarnamn här troligen är ett misstag snarare än en gästdelad resurs - men det accepteras, eftersom att vägra det skulle blockera den ena arrangementet där det är korrekt. Om kontot tillhör en domän, ange Domän också: att autentisera ett domänkonto utan det misslyckas på ett sätt som liknar ett felaktigt lösenord.
22.22.5 domän
Domän är Windows-domän eller arbetsgrupp.
Tom är vanligtvis rätt för ett lokalt konto.
22.22.6 tidsgräns
Tidsgräns begränsar en operation.
Standardvärdet är trettio sekunder.
Värt att öka på en resurs som nås via en sitelänk. En SMB-operation mot en avlägsen server är långsammare än samma operation lokalt, så att en standard som är inställd för ett LAN producerar tidsgränser som ser ut som om resursen inte är tillgänglig.
22.23 SOAP-källa
SOAP-källan accepterar meddelanden inneslutna i ett SOAP-omslag.
Motparten till SOAP-målet, och den ovanligare riktningen: de flesta sjukhusintegrationer har Perfuse som anropar en tjänst snarare än att vara en. Den finns eftersom Mirths Web Service Listener finns, och en plats vars avsändarsystem endast talar SOAP inte kan migrera utan den.
Medvetet inte en allmän webbtjänstekramverk. Den accepterar ett omslag, tar ut meddelandet ur det och svarar med ett omslag. Det finns inget WS-Säkerhet, inget MTOM, inget WS-Addressing och inga genererade bindningar - samma utelämnanden som målet, av samma anledning: en halvimplementering av WS-Säkerhet är värre än ingen.
Definierad som SOAPSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | ja | — |
profile | text | nej | — |
path | text | nej | "/" |
version | text | nej | 1 |
element | text | nej | — |
base64 | true eller false | nej | — |
response_element | text | nej | "AckResponse" |
response_namespace | text | nej | — |
wsdl | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
token | text | nej | — |
username | text | nej | — |
password | text | nej | — |
max_message_size | heltal | nej | — |
read_timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
ack | Ack | nej | — |
fault_on_nak | true eller false | nej | — |
22.23.1 lyssna
Lyssna är adressen att betjäna på.
Required.
22.23.2 profil
Profilnamn anger en standardtjänst som den här slutpunkten implementerar.
Tom accepterar alla omslag som konfigurerats nedan.
"cdc-iis" svarar som ett vaccinationsregister gör, på CDC-gränssnittet (urn:cdc:iisb:2011): connectivityTest ekas, submitSingleMessages hl7Message är meddelandet och kanalen ack sänds tillbaka i retur, WSDL serveras på ?wsdl och användarnamn och lösenord, när de är inställda, kontrolleras mot de som finns i brödtexten (där WSDL placerar dem) snarare än mot HTTP-autentisering. För en registrets testdubbel eller för en plats som tar emot inlämningar på samma sätt som register gör.
22.23.3 sökväg
Sökväg är URL-sökvägen för att acceptera omslag på.
Defaults to "/".
22.23.4 version
Version är den SOAP-version som ska svaras i, "1.1" eller "1.2".
Defaults to 1.1.
Förfrågningar accepteras i båda versionerna oavsett, eftersom en avsändare som får detta fel är vanlig och att avvisa det lär ingen någonting. Inställningen kontrollerar svaret, där att få det fel innebär att avsändaren inte kan läsa svaret.
22.23.5 element
Elementnamn anger det element inuti SOAP-Bröd som innehåller meddelandet.
Tom betyder hela brödtexten.
Namngiven snarare än gissad eftersom en bröd kan bära flera element - ett meddelande bredvid en avsändaridentifierare och en tidsstämpel - och att ta hela brödtexten skulle ge motorn en XML-fragment där den förväntade sig HL7.
22.23.6 base64
Base64 avkodar elementets innehåll innan det behandlas som ett meddelande.
Vanligt i riktiga tjänster, eftersom HL7 bär radbrytningar och anropare som inte tänkte på det slutar med XML som förstör dem. Om innehållet avkodas som base64 men inte var tänkt att vara det, är resultatet inte ett meddelande och motorn säger så - vilket är varför detta är explicit snarare än sniffat.
22.23.7 svars_element
ResponseElement namnger elementet som omsluter bekräftelsen i svaret.
Standardvärdet är "AckResponse".
22.23.8 wsdl
WSDL är en fil som serveras på lyssningsvägen med ?wsdl.
Tom betyder att ingen serveras.
En fil snarare än något genererat. En genererad WSDL skulle beskriva vad denna slutpunkt accepterar, vilket nästan aldrig är vad skickarsystemet byggdes mot - och en WSDL som nästan är rätt kostar mer tid än ingen WSDL alls, eftersom den ser auktoritativ ut.
22.23.9 användarnamn
Användarnamn och Lösenord, när de är inställda, kräver HTTP-basautentisering.
Erbjuds bredvid en token eftersom SOAP-anropare överväldigande förväntar sig basautentisering, och en webbplats vars skickarsystem inte kan ändras behöver alternativet som den redan har.
22.23.10 lösenord
Användarnamn och Lösenord, när de är inställda, kräver HTTP-basautentisering.
Erbjuds bredvid en token eftersom SOAP-anropare överväldigande förväntar sig basautentisering, och en webbplats vars skickarsystem inte kan ändras behöver alternativet som den redan har.
22.23.11 max_meddelandestorlek
MaxMeddelandestorlek begränsar en inkommande kropp.
Noll tillämpar ett standardvärde.
22.23.12 fault_on_nak
FaultOnNak svarar på en negativ bekräftelse med en SOAP-fel i stället för ett normalt svar som bär NAK.
Avstängd som standard, vilket är rätt standard och värt att förklara. HL7 har redan ett sätt att säga "Jag mottog detta och avslog det", och det är en NAK - en lyckad överföring som rapporterar ett avsagt meddelande. Att omvandla samma sak till ett transportfel berättar för avsändaren att dess begäran var felaktig, vilket den inte var, och många klienter svarar genom att försöka igen för evigt.
Den finns eftersom vissa anropare bara tittar på HTTP-statusen och annars skulle behandla ett avslag som en framgång.
22.24 SQS-källa
SQSSource läser från en SQS-kö.
Ett meddelande raderas endast efter att kanalen har hanterat det - levererat, eller filtrerat, eller misslyckats på ett sätt som kanalen registrerar. Tills dess stannar det i kön, osynligt under visibility_timeout, och kommer tillbaka om Perfuse stoppas. Så ett meddelande går aldrig förlorat; priset är att ett kan anlända två gånger, vilket SQS själv redan tillåter.
Definierad som SQSSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
queue_url | text | ja | — |
wait_seconds | heltal | nej | 20: en tom kö kostar en begäran varannan sekund |
max_messages | heltal | nej | 10 |
visibility_timeout | varaktighet, såsom 30s eller 5m | nej | könens egna inställning |
22.24.1 visibility_timeout
VisibilityTimeout är hur länge ett mottaget meddelande stannar dolt medan det hanteras.
Standardvärdet är könens egna inställning.
22.25 Serielkälla
SerialSource läser meddelanden från en serieport.
Varför en serieanslutning 2026
För att utrustningen fortfarande finns. En blodgasanalysator köpt 2009 med en fungerande sensor och en 25-pinskontakt, en sängmonitor, en våg i en dialysenhet, en äldre anestesimaskin. Ingen av dem kommer någonsin att få en Ethernet-port, flera av dem kostar sexsiffriga belopp, och alternativet till att läsa dem är att någon skriver in resultaten i ett formulär.
Mirth har en seriell anslutning. Perfuse hade ingenting och en webbplats med en av dessa hade ingen väg in alls.
Ramverk delas med TCP-anslutningen
Ramverken är desamma oavsett var byte kommer från: en analyserare som talar STX/ETX över en socket talar STX/ETX över en kabel. Så detta återanvänder TCP-ramverksblocket istället för att definiera sitt eget, vilket också innebär att en enhet som flyttas från en seriell kabel till en seriell-till-Ethernet-adapter behåller sin ramverkskonfiguration.
Vad som skiljer sig åt i en seriell linje
Det finns ingen anslutning. En socket berättar för dig när peer gick bort; en kabel gör det inte. En urkopplad kabel, en enhet som stängts av och en enhet med ingenting att säga är inte igenkännliga - alla tre är tystnad. Det är därför quiet_after finns: utan något att säga "denna linje har varit tyst i längre tid än den borde vara", ser en död matning exakt ut som en tyst natt.
Definierad som SerialSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
port | text | ja | — |
baud | heltal | ja | — |
data_bits | heltal | nej | 8 |
parity | text | nej | none |
stop_bits | text | nej | 1 |
flow_control | text | nej | none |
max_message_size | heltal | nej | — |
quiet_after | varaktighet, t.ex. 30s eller 5m | nej | — |
reply | text | nej | — |
reply_text | text | nej | — |
reopen_after | varaktighet, t.ex. 30s eller 5m | nej | — |
22.25.1 baud
Baud är hastigheten.
Obligatorisk, eftersom gissning producerar byte istället för ett fel.
En felaktig baudhastighet misslyckas inte. Den levererar trovärdig-looking skräp: ramverksbyte visas slumpmässigt, tillfälliga körningar avkodas som skrivbara tecken och en tolerant parser accepterar några av dem. Det finns medvetet inget standardvärde.
22.25.2 parity
Paritet är none, odd, even, mark eller space.
Standard är none.
22.25.3 stop_bits
StopBits är 1, 1,5 eller 2, skrivet som "1", "1,5" eller "2".
Defaults to 1.
22.25.4 flow_control
FlowControl är none, hardware eller software.
Standard är none.
Värt att ställa in korrekt istället för att lämna. Med hårdvarukontroll förväntad och inte konfigurerad, slutar en enhet att skicka delvis genom ett långt meddelande och resultatet är ett trunkerat meddelande istället för ett fel.
22.25.5 quiet_after
QuietAfter loggar en varning när ingenting har mottagits under så lång tid.
Det enda sättet att märka en död seriell matning. En urkopplad kabel och en tyst natt är samma tystnad, så någon måste säga hur länge är för länge för denna specifika enhet.
22.25.6 reopen_after
ReopenAfter är hur länge man ska vänta innan man öppnar en port som misslyckades.
En USB-seriell adapter som kopplats ur och tillbaka kommer tillbaka som samma enhetsväg men en annan kärnhanterare, så den gamla returnerar fel för alltid. Återöppnande är den enda återhämtningen, och att göra det i en tät slinga fyller loggen.
22.26 Källa
Källa är där en kanal tar emot meddelanden.
Definierad som Source i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
type | SourceType | ja | — |
listen | text | ja | — |
max_message_size | heltal | nej | — |
idle_timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
max_connections | heltal | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
http | HTTPSource (en block, utelämna för att inte använda) | nej | — |
soap | SOAPSource (en block, utelämna för att inte använda) | nej | — |
dicomweb | DICOMwebSource (en block, utelämna för att inte använda) | nej | — |
direct | DirectSource (en block, utelämna för att inte använda) | nej | — |
dicom | DICOMSource (en block, utelämna för att inte använda) | nej | — |
file | FileSource (en block, utelämna för att inte använda) | nej | — |
tcp | TCPSource (en block, utelämna för att inte använda) | nej | — |
ftp | FTPSource (en block, utelämna för att inte använda) | nej | — |
smb | SMBSource (en block, utelämna för att inte använda) | nej | — |
webdav | WebDAVSource (en block, utelämna för att inte använda) | nej | — |
serial | SerialSource (en block, utelämna för att inte använda) | nej | — |
dicom_query | DICOMQuerySource (en block, utelämna för att inte använda) | nej | — |
broker | BrokerSource (en block, utelämna för att inte använda) | nej | — |
kafka | KafkaSource (en block, utelämna för att inte använda) | nej | — |
sqs | SQSSource (en block, utelämna för att inte använda) | nej | — |
s3 | S3Source (en block, utelämna för att inte använda) | nej | — |
amqp | AMQPSource (en block, utelämna för att inte använda) | nej | — |
azure_blob | AzureBlobSource (en block, utelämna för att inte använda) | nej | — |
email | EmailSource (en block, utelämna för att inte använda) | nej | — |
as2 | AS2Source (en block, utelämna för att inte använda) | nej | — |
pgp | PGPReceive (en block, utelämna för att inte använda) | nej | — |
mqtt | MQTTSource (en block, utelämna för att inte använda) | nej | — |
ibm_mq | IBMMQSource (en block, utelämna för att inte använda) | nej | — |
pubsub | PubSubSource (en block, utelämna för att inte använda) | nej | — |
gcs | GCSSource (en block, utelämna för att inte använda) | nej | — |
database | DatabaseSource (en block, utelämna för att inte använda) | nej | — |
sftp | SFTPSource (en block, utelämna för att inte använda) | nej | — |
javascript | JavaScriptSource (en block, utelämna för att inte använda) | nej | — |
ack | Ack | nej | — |
22.26.1 typ
Typ är transporten.
Endast mllp är implementerad.
22.26.2 max_meddelandestorlek
MaxMessageSize begränsar en inkommande meddelandestorlek.
Noll använder transportens standardvärde.
22.26.3 idle_timeout
IdleTimeout stänger en anslutning som har varit tyst i så lång tid.
Noll betyder aldrig, vilket vanligtvis är rätt: en sjukhusmatning håller en anslutning öppen i månader och går tyst över natten.
22.26.4 max_connections
MaxConnections begränsar samtidiga anslutningar.
Noll betyder obegränsat.
22.27 TCP-källa
TCPSource lyssnar på en socket för meddelanden som inte nödvändigtvis är HL7.
Varför detta är separat från en mllp-källa
MLLP är en ram och Perfuse har alltid talat den. Mycket utrustning gör inte det: en laboratorieanalyserare, en våg, en sängbordsterminal, ett äldre fakturasystem. Var och en tenderar att ha sin egen konvention, och Mirths TCP-anslutning täcker alla, så en plats med en socketmatning som inte var HL7 kunde inte använda Perfuse alls.
Definierad som TCPSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | ja | — |
max_message_size | heltal | nej | — |
idle_timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
max_connections | heltal | nej | — |
reply | text | nej | — |
reply_text | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
22.27.1 idle_timeout
IdleTimeout stänger en anslutning som har varit tyst i så lång tid.
Noll betyder aldrig, vilket vanligtvis är rätt: en enhetsmatning håller en anslutning öppen i månader och går tyst över natten.
22.27.2 max_connections
MaxConnections begränsar samtidiga anslutningar.
Noll betyder obegränsat.
22.27.3 svar
Svar är vad som ska skickas tillbaka efter varje meddelande: ingenting, ack eller en fast sträng.
De flesta råa matningarna förväntar sig ingenting. Vissa förväntar sig en enda ACK-byte. En enhet som förväntar sig ett svar och inte får det försöker vanligtvis skicka samma meddelande för evigt, så detta är värt att vara tydlig om.
22.28 Webb DAV-källa
WebDAVSource samlar in filer från en WebDAV-samling.
Där detta dyker upp: dokumenthanteringssystem, SharePoint, Nextcloud och leverantörsportaler som exponerar en drop-folders mapp över HTTPS eftersom det är den enda utgående porten som deras kunders brandväggar tillåter.
Definieras som WebDAVSource i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
user | text | nej | — |
password | text | nej | — |
insecure_skip_verify | true eller false | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | sextio sekunder |
22.28.1 användare
Användare och Lösenord autentiserar med HTTP-basautentisering.
Basautentisering skickar lösenordet i en rubrik som endast skyddas av TLS, så dessa hör ihop med en https-URL. Över http är de läsbara av allt på vägen och ingen varning från servern kommer att tala om det för dig.
22.28.2 lösenord
Användare och Lösenord autentiserar med HTTP-basautentisering.
Basautentisering skickar lösenordet i en rubrik som endast skyddas av TLS, så dessa hör ihop med en https-URL. Över http är de läsbara av allt på vägen och ingen varning från servern kommer att tala om det för dig.
22.28.3 tidsgräns
Timeout begränsar en begäran.
Standard är sextio sekunder.
Längre än standarden för FTP och SMB med flit. En WebDAV-samlinglista är en enda PROPFIND som servern kan ta lång tid att sammanställa för en stor katalog, och det finns inget delresultat att falla tillbaka på.
23 Mottagarens referens
Varje sätt som en kanal kan skicka meddelanden, och varje nyckel som var och en accepterar. En kanal kan ha valfritt antal mottagare, och de är oberoende: en som misslyckas stoppar inte de andra.
23.1 AMQP-mottagare
AMQPDestination skickar till en kö eller ämne och rapporterar framgång endast när brokern har accepterat meddelandet.
Definieras som AMQPDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
content_type | text | nej | kanalen datatyp |
23.1.1 innehållstyp
Innehållstyp skickas med varje meddelande.
Standard är kanaltypens datatyp.
23.2 AS2-mottagare
AS2Destination skickar varje meddelande som AS2: signerat med vår nyckel, krypterat till partnercertifikatet, publicerat på partner-URL:en och, som standard, levererat endast när partnerens signerade kvittens namnger samma sammanfattning.
Definieras som AS2Destination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
from | text | ja | — |
to | text | ja | — |
cert_file | text | nej | — |
key_file | text | nej | — |
partner_cert_file | text | nej | — |
unsigned | true eller false | nej | — |
unencrypted | true eller false | nej | — |
compress | true eller false | nej | — |
receipt | text | nej | — |
unsigned_receipt | true eller false | nej | — |
receipt_url | text | nej | — |
content_type | text | nej | — |
file_name | text | nej | — |
subject | text | nej | — |
username | text | nej | — |
password | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
23.2.1 komprimera
Komprimera komprimerar nyttolasten (zlib, RFC 5402) innan signering och kryptering.
Varje AS2-mottagare som meddelar version 1.1 eller senare läser den; fråga partnern innan du aktiverar den.
23.2.2 odaterad_mottagningsbekräftelse
UnsignedReceipt begär en mottagningsbekräftelse som inte är signerad.
Av: en signerad begärs och en odaterad vägras.
23.2.3 innehållstyp
ContentType är MIME-typen för nyttolasten.
Standard enligt kanalens datatyp: application/edi-x12, application/edifact, application/hl7-v2, annars application/octet-stream.
23.3 Azure Blob-mål
AzureBlobDestination skriver varje meddelande som en blockblob.
Definierad som AzureBlobDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
blob | text | nej | ${date}/${channel}/${control_id} |
tier | text | nej | — |
content_type | text | nej | — |
23.3.1 blob
Blob namnger varje blob, med S3-målens platshållare.
Standard är ${date}/${channel}/${control_id}.hl7.
23.3.2 tier
Tier är Hot, Cool, Cold eller Arkiv.
Arkiv är offline: att läsa tillbaka en blob innebär att den återfuktas, vilket tar timmar.
23.4 Mäklarmål
BrokerDestination publicerar meddelanden till en meddelandemäklare.
Mirths JMS-skribent.
Definierad som BrokerDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
addr | text | ja | — |
destination | text | ja | — |
login | text | nej | — |
passcode | text | nej | — |
host | text | nej | adressens värd |
content_type | text | nej | text/plain för HL7 |
headers | mappning av text till text | nej | — |
persistent | true eller false (en block, utelämna för att lämna av) | nej | true |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
23.4.1 addr
Addr är värden och porten för medlaren.
Required.
23.4.2 destination
Mål är kön eller ämne som publiceras till.
Required.
23.4.3 inloggning
Inloggning och lösenkod autentiserar.
De flesta medlare vägrar en anonym anslutning.
23.4.4 lösenkod
Inloggning och lösenkod autentiserar.
De flesta medlare vägrar en anonym anslutning.
23.4.5 värd
Värd är den virtuella värden.
Standardvärdet är värden för adressen.
Värt att ställa in explicit på en mäklare som värdar flera virtuella värdar, där standard landar publiceringen på vilken som helst som svarar på serverns eget namn - en kö som finns, accepterar meddelandet och läses av ingen.
23.4.6 innehållstyp
Innehållstyp skickas med varje meddelande.
Standard är text/plain för HL7.
23.4.7 headers
Rubriker skickas med varje meddelande.
Konfiguration endast, aldrig meddelandeinnehåll. En rubrik som tas från ett fält skulle placera en patientidentifierare i brokermetadata som loggas, indexeras och är synlig för varje annan applikation i kön.
23.4.8 beständig
Beständig ber broker att överleva en omstart.
Standard är true.
True eftersom ett icke-beständigt meddelande förloras när broker omstartar, och det är inte ett rimligt standardvärde för kliniska data. False finns för en genuint tillfällig feed - en övervakningspuls - och måste väljas.
23.5 CDA-mål
CDADestination konfigurerar ett CDA-mål: det tar det kliniska dokument som finns inuti ett HL7 v2-meddelande, konverterar det och skriver eller postar resultatet.
Detta finns eftersom ett dokument nästan aldrig anländer på egen hand. Det anländer base64-kodat inuti ett MDM^T02, och varje motor som behandlar meddelandet som en ogenomskinlig blob lämnar dokumentet oläst. Att äga båda ändarna av detta är poängen.
Definierat som CDADestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | nej | — |
dir | text | nej | — |
write | text | nej | — |
version | text | nej | R5 |
identifier_systems | mappning av text till text | nej | — |
require_agreement | true eller false | nej | — |
on_no_document | text | nej | — |
headers | mappning av text till text | nej | — |
bearer_token | text | nej | — |
23.5.1 url
URL är en FHIR-server som postar det konverterade paketet till.
Lämna den tom för att skriva till Dir istället. En av de två krävs.
23.5.2 dir
Dir skriver utdata till filer istället för att posta dem.
Användbart för en landningszon som en annan process plockar upp, och för att se vad konvertering producerar innan den pekas mot en live-server.
23.5.3 write
Write väljer vad som skrivs eller postas:
fhir den konverterade transaktionsbunteln (standard) dokumentera det ursprungliga dokumentets byte, oförändrat båda, med dokumentet bredvid bunteln överföra en PACIO-övergångssammanfattning för vård: en FHIR R4-dokumentbunt för den plats patienten går till härnäst (ett vårdhem, en rehabiliteringsenhet, hemsjukvård), publicerad till url/Bundle eller skriven till dir
"dokument" är värt att ha för sig själv: en plats som vill ha sina CDAs på skiva för en registergrupp behöver inte FHIR-konverteringen alls.
23.5.4 identifier_systems
IdentifierSystems mappar en OID-rot från dokumentet till en URI, så att en MRN blir namnrymd.
En CDA identifierar personer med OID och FHIR med URI, och ingenting kan härleda en från den andra.
23.5.5 require_agreement
RequireAgreement vägrar ett dokument vars berättelse och kodade poster motsäger varandra.
Avstängd som standard, och med avsikt. Kontrollen är värdefull, men det är en bedömning av ett dokument som någon annan har skapat, och en kanal som tyst droppar riktiga kliniska dokument på grund av att en avsändares C-CDA-generator är slarvig är värre än en som skickar dem vidare med en varning. En webbplats som har granskat sina egna resultat och beslutat att den vill ha grinden kan aktivera den.
23.5.6 on_no_document
OnNoDocument beslutar vad som händer när meddelandet inte innehåller något kliniskt dokument:
hoppa över leverera ingenting och rapportera framgång (standard) misslyckas behandla det som en leveransmisslyckande
Standard är att hoppa över, eftersom en kanal som bär en blandad ADT- och MDM-matare annars skulle misslyckas varje inlämning. En kanal som är dedikerad till dokument bör ange misslyckas, eftersom ett dokumentmeddelande utan dokument i det är ett riktigt problem hos avsändaren.
23.5.7 bearer_token
BearerToken skickas som en auktoriseringshuvud.
Föredra en miljövariabelreferens över en bokstav i en fil som går in i git.
23.6 Kanaldestination
Kanaldestination dirigerar till en annan kanal i samma server.
Definierad som ChannelDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
name | text | ja | — |
23.7 DICOM-destination
DICOMDestination skickar bildobjekt som en C-STORE-tjänstklassanvändare.
Mirth kallar detta för DICOM-avsändare.
Definierad som DICOMDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
address | text | ja | — |
called_ae | text | nej | — |
calling_ae | text | nej | — |
transfer_syntaxes | lista med text | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
23.7.1 adress
Adressen är den fjärranslutna värden och porten.
Required.
23.7.2 anropad_ae
AnropadAE är vad den fjärranslutna kallar sig själv, och AnropandeAE vad den här änden kallar sig själv.
Båda är viktiga. Webbplatser konfigurerar en PACS för att acceptera en specifik anropande titel och avvisa allt annat, så en felmatchning är den vanligaste orsaken till att en första anslutning misslyckas - och misslyckandet ser ut som ett nätverksproblem.
23.7.3 anropande_ae
AnropadAE är vad den fjärranslutna kallar sig själv, och AnropandeAE vad den här änden kallar sig själv.
Båda är viktiga. Webbplatser konfigurerar en PACS för att acceptera en specifik anropande titel och avvisa allt annat, så en felmatchning är den vanligaste orsaken till att en första anslutning misslyckas - och misslyckandet ser ut som ett nätverksproblem.
23.7.4 transfer_syntaxes
Överföringssyntaxer begränsar vad som ska erbjudas, i preferensordning.
Tomt erbjuder objektets egen kodning och sedan implicit VR liten ändian som en reserv.
23.7.5 tidsgräns
Tidsgräns begränsar en enda lagringsoperation.
Noll tillämpar ett standardvärde.
23.8 DICO Mweb-destination
DICOMwebDestination lagrar varje objekt med STOW-RS.
Definierad som DICOMwebDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
token | text | nej | — |
username | text | nej | — |
password | text | nej | — |
headers | mappning av text till text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
23.9 Databasdestination
DatabaseDestination skriver varje meddelande till en databas.
Definierad som DatabaseDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
driver | text | ja | — |
dsn | text | ja | — |
statement | text | ja | — |
params | lista med text | nej | — |
timeout | varaktighet, såsom 30s eller 5m | nej | 30s |
max_open_conns | heltal | nej | 4 |
23.9.1 drivrutin
Drivrutin namnger databasen.
See SupportedDrivers.
23.9.2 instruktion
Instruktionen körs en gång per meddelande, med Params bunden till den i ordning.
Platshållare är drivarens egna: $1 för postgres, ? för mysql och sqlite, @p1 för sqlserver. Perfuse skriver inte om dem, eftersom ett översättningslager som fick en platshållare fel skulle binda en patients namn till fel kolumn och resultatet skulle se ut som giltig data.
23.9.3 params
Params är HL7-sökvägar eller ${...} uttryck, bundna till instruktionen i ordning.
Värdena är alltid bundna som parametrar och aldrig interpolerade i SQL. Det handlar inte bara om injicering: O'Brien är ett vanligt namn, och en sammanfogad fråga bryts på apostrofen.
23.9.4 tidsgräns
Timeout begränsar en enskild instruktion.
Defaults to 30s.
23.9.5 max_open_conns
MaxOpenConns begränsar poolen.
Defaults to 4.
23.10 Destination
Destination är en plats där en kanal skickar meddelanden.
Definierad som Destination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
name | text | ja | — |
type | DestinationType | ja | — |
enabled | true eller false (en block, utelämna för att lämna av) | nej | — |
filter | text | nej | — |
address | text | nej | — |
dir | text | nej | — |
file_name | text | nej | — |
temp_suffix | text | nej | " |
append | true eller false | nej | — |
retain_hours | heltal | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
fhir | FHIRDestination (en block, utelämna för att lämna av) | nej | — |
cda | CDADestination (en block, utelämna för att lämna av) | nej | — |
http | HTTPDestination (en block, utelämna för att lämna av) | nej | — |
database | DatabaseDestination (en block, utelämna för att lämna av) | nej | — |
sftp | SFTPDestination (en block, utelämna för att lämna av) | nej | — |
tcp | TCPDest (en block, utelämna för att lämna av) | nej | — |
smtp | SMTPDestination (en block, utelämna för att lämna av) | nej | — |
channel | ChannelDestination (en block, utelämna för att lämna av) | nej | — |
s3 | S3Destination (en block, utelämna för att lämna av) | nej | — |
ftp | FTPDestination (en block, utelämna för att lämna av) | nej | — |
document | DocumentDestination (en block, utelämna för att lämna av) | nej | — |
soap | SOAPDestination (en block, utelämna för att lämna av) | nej | — |
dicomweb | DICOMwebDestination (en block, utelämna för att lämna av) | nej | — |
xds | XDSDestination (en block, utelämna för att lämna av) | nej | — |
direct | DirectDestination (en block, utelämna för att lämna av) | nej | — |
as2 | AS2Destination (en block, utelämna för att lämna av) | nej | — |
mpi | MPIDestination (en block, utelämna för att lämna av) | nej | — |
tefca | TEFCADestination (en block, utelämna för att lämna av) | nej | — |
pas | PASDestination (en block, utelämna för att lämna av) | nej | — |
x12_as | text | nej | — |
dicom | DICOMDestination (en block, utelämna för att lämna av) | nej | — |
javascript | JavaScriptDestination (en block, utelämna för att lämna av) | nej | — |
broker | BrokerDestination (en block, utelämna för att lämna av) | nej | — |
kafka | KafkaDestination (en block, utelämna för att lämna av) | nej | — |
sqs | SQSDestination (en block, utelämna för att lämna av) | nej | — |
sns | SNSDestination (en block, utelämna för att lämna av) | nej | — |
amqp | AMQPDestination (en block, utelämna för att lämna av) | nej | — |
azure_blob | AzureBlobDestination (en block, utelämna för att lämna av) | nej | — |
mqtt | MQTTDestination (en block, utelämna för att lämna av) | nej | — |
ibm_mq | IBMMQDestination (en block, utelämna för att lämna av) | nej | — |
pubsub | PubSubDestination (en block, utelämna för att lämna av) | nej | — |
gcs | GCSDestination (en block, utelämna för att lämna av) | nej | — |
elr | ELRDestination (en block, utelämna för att lämna av) | nej | — |
pgp | PGPSend (en block, utelämna för att lämna av) | nej | — |
response_transformer | text | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
retry | Retry | nej | — |
queue | QueueConfig (en block, utelämna för att lämna av) | nej | — |
23.10.1 namn
Namn identifierar destinationen i loggar och mått.
Obligatoriskt inom en kanal.
23.10.2 file_name
Filnamn, för en fildestination, skapar en fil per meddelande (${timestamp}, ${date}, ${control_id}, ${message_type}, ${destination}).
Tom behåller standard: en fil per dag och meddelandetyp, bilagd till.
23.10.3 temp_suffix
TempSuffix är namnet på en per-meddelandefil som den bär medan den skrivs, tas bort av en omnamning när den är klar, så vad som samlar in filerna aldrig läser halva.
Standard är ".part".
23.10.4 retain_hours
RetainHours tar bort filer i Dir som är äldre än detta.
Noll behåller dem för alltid.
23.10.5 x12_as
X12As är xml för en destination på en X12-kanal som tar emot interchange som Mirth Connect och Open Integration Engine skriver för X12, för en mottagare byggd mot vad Mirth skickade till den.
Tom eller x12 skickar X12.
23.10.6 elr
ELR gör denna till en offentlig hälso-laboratorierapportdestination: varje laboratorieresultat (ORU^R01) omformas till ett ELR 2.5.1-meddelande som endast innehåller de beställningar med ett rapporterbart resultat, och det är vad som levereras; ett meddelande med ingenting rapporterbart skickas inte alls.
Gäller för destinationer som levererar ett HL7 v2-meddelande som det är (mllp, http, fil, sftp och resten), på en hl7-kanal.
23.10.7 response_transformer
ResponseTransformer inspekterar vad mottagaren sa tillbaka och kan markera leveransen som misslyckad.
Den finns eftersom "anlände detta" ofta inte är en fråga som transporten kan besvara: en MLLP-mottagare returnerar en applikationsbekräftelse vars betydelse är i dess text, och en HTTP-mottagare returnerar 200 med ett fel-dokument. I båda fallen lyckades transporten och meddelandet anlände inte.
Endast meningsfullt på en destination som tar emot ett svar. På en som inte kan, avvisas den vid inläsning snarare än att lämnas aldrig körande.
23.10.8 kö
Kön gör leveransen beständig: ett meddelande som inte kan levereras just nu sparas på disk och försöks igen tills det kan.
Avstängd som standard.
23.11 Direkt Destination
DirectDestination skickar varje meddelande som Direct: signerat med denna adress, krypterat till varje mottagares certifikat och skickat till HISP via SMTP.
Definierad som DirectDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
to | lista av text | ja | — |
subject | text | nej | — |
text | text | nej | — |
attach_name | text | nej | — |
xdm | true eller false | nej | — |
xdm_source_id | text | nej | — |
recipient_certs_dir | text | nej | — |
dns | text | nej | — |
ldap | text | nej | — |
smtp_host | text | ja | — |
username | text | nej | — |
password | text | nej | — |
request_mdn | true eller false | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
23.11.1 till
Till är mottagarnas Direct-adresser.
Fältreferenser ersätts, så en mottagare kan komma från meddelandet.
23.11.2 recipient_certs_dir
RecipientCertsDir innehåller mottagarcertifikat (PEM, en fil per adress eller domän, address.pem eller domain.pem) som hittats i förväg; tom läser serverns Direct-adressbok (Direct-skärmen).
Mottagare som inte finns där söks i DNS (CERT-poster). Direct skickar inte till en mottagare vars certifikat inte kan hittas.
23.11.3 ldap
LDAP är katalogen där en mottagares certifikat söks när DNS inte har någon (värd:port, port 389): det andra sättet som Direct-certifikatguiden tillåter.
Tomt hittar mottagardomänens katalog med dess DNS SRV-post (_ldap._tcp), som guiden säger; "av" aldrig frågar en katalog.
23.12 Dokument Destination
DocumentDestination renderar varje meddelande till ett dokument.
Definierad som DocumentDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
dir | text | ja | — |
format | DocumentFormat | nej | |
template | text | ja | — |
title | text | nej | — |
file_name | text | nej | — |
font_size | nummer | nej | 10 |
landscape | true eller false | nej | — |
temp_suffix | text | nej | " |
timeout | varaktighet, t.ex. 30s eller 5m | nej | 30s |
23.12.1 format
Format är pdf eller text.
Standard är pdf.
23.12.2 mall
Mall är dokumentkroppen, med ${PID-5.1}-liknande referenser till meddelandesökvägar.
Obligatorisk. Det finns inget rimligt standardvärde: ett dokument utan mall skulle antingen vara det råa meddelandet, som ingen vill ha utskrivet, eller tomt.
23.12.3 font_size
Teckenstorlek i punkter.
Standard är 10, vilket ryms med 80 tecken över A4.
23.12.4 temp_suffix
TempSuffix läggs till medan det skrivs och tas bort av en omnamning.
Standard är ".part".
Samma artighet som varje annan fildestination, och det spelar en större roll här: en skrivskyddsvakt som plockar upp ett halvfärdigt PDF-producerar en sida med ingenting, och ingen utredare en tom sida.
23.12.5 tidsgräns
Tidsgränsen begränsar en skrivning.
Defaults to 30s.
23.13 ECR-mål
ECRDestination konfigurerar elektronisk ärendehantering.
Definierad som ECRDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
rctc | text | nej | — |
source | text | ja | — |
facility | ECRFacility | ja | — |
23.13.1 rctc
RCTC är en FHIR-värdesats eller en samling av dem, såsom eRSD, som innehåller utlösandekoderna.
Utan det används Perfuses korta inbyggda exempel, som är för testning: myndigheter förväntar sig RCTC.
23.14 ELR-mål
ELRDestination konfigurerar elektronisk laboratorierapportering.
Definierad som ELRDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
config | text | ja | — |
rctc | text | nej | — |
23.14.1 konfiguration
Konfigurationen är ELR-filen som perfuse elr -config läser: de sändande och mottagande applikationerna och anläggningarna via OID, bearbetningsläget och vad som fyller i luckorna som en labbförsörjning lämnar (beställande anläggning, utförande laboratorium, tilldelande myndigheter).
En relativ sökväg läses från kanalens filkatalog.
23.14.2 rctc
RCTC är en FHIR-värdesats eller en samling av dem, såsom eRSD, som innehåller utlösandekoderna.
Utan det används Perfuses korta inbyggda exempel, som är för testning: myndigheter förväntar sig RCTC. Relativt till kanalens fil, som konfiguration.
23.15 FHIR-mål
FHIRDestination konfigurerar omvandling till FHIR och leverans till en FHIR-server.
Definierad som FHIRDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
version | text | nej | R5 |
timezone | text | nej | — |
default_identifier_system | text | nej | — |
identifier_systems | mappning av text till text | nej | — |
claim_us_core | true eller false | nej | — |
validate_before_send | true eller false (en block, utelämna för att lämna av) | nej | true: att skicka en resurs som en server kommer att avvisa slösar bort en återförsöksbudget och döljer det verkliga problemet bakom ett transportfel |
reject_on_warning | true eller false | nej | — |
headers | mappning av text till text | nej | — |
bearer_token | text | nej | — |
auth | FHIRAuth (en block, utelämna för att lämna av) | nej | — |
ecr | ECRDestination (en block, utelämna för att lämna av) | nej | — |
bundle_script | text | nej | — |
23.15.1 url
URL är den grundläggande URL:en för FHIR-servern, till exempel "https://fhir.example.org/fhir".
Samlingen skickas direkt till den.
23.15.2 version
Version är den FHIR-utgåva som ska produceras: R4, R4B eller R5. Standard är R5, den senaste publicerade utgåvan.
En distribution som pratar med ett EHR vill nästan alltid ha R4 och bör säga det, eftersom tyst nedgradering skulle dölja ett verkligt beslut om samverkansförmåga.
23.15.3 tidszon
Tidszonen tillämpas på HL7 v2-tidsstämplar som inte har någon offset. v2 tillåter en lokal tid utan offset och FHIR gör det inte, så något måste tillhandahålla en.
När den inte är inställd, används den offset som avsändaren satte på MSH-7, eftersom v2 förutsätter att en lokal tid är avsändarens lokal tid; ett meddelande vars MSH-7 inte har någon offset heller faller tillbaka till UTC.
23.15.4 standard_identifier_system
StandardIdentifierSystem namnger identifierare vars tilldelande myndighet inte har någon konfigurerad URI.
Utan ett system är en MRN tvetydig mellan anläggningar.
23.15.5 claim_us_core
ClaimUSCore lägger till US Core 9.0.0-profilen till varje resurs som produceras och som har kontrollerats mot den och som överensstämmer.
En resurs som inte uppfyller kraven skickas utan anspråk, med en not som anger varför.
23.15.6 validera_före_skicka
ValidateBeforeSend vägrar att publicera en samling som inte klarar valideringen.
Standard är true: att skicka en resurs som en server kommer att avvisa slösar bort en återförsöksbudget och döljer det verkliga problemet bakom ett transportfel.
23.15.7 avvisa_på_varning
RejectOnWarning vägrar också på varningar, såsom en saknad US Core-identifierare.
Avstängd som standard, eftersom en varning är en bedömning om profilöverensstämmelse snarare än om giltighet.
23.15.8 bearer_token
BearerToken skickas som en auktoriseringshuvud.
Föredra en miljövariabelreferens, ${NAME}, över en bokstav i en fil som går in i git.
23.15.9 ecr
ECR gör detta till en destination för allmän hälsorapportering.
Varje meddelande kontrolleras för utlösande koder; ett som har några skickas som en eCR 2.1 eICR, innesluten i ett eCR-meddelande, till url:ens $process-message, och ett utan några skickas inte alls.
23.15.10 bundle_script
BundleScript är JavaScript som körs på varje konverterad Bundle innan den valideras och skickas: bundle är Bundle som ett objekt, redigerat på plats.
Det är hur en webbplats lägger till vad dess egna system vet och v2-meddelandet inte säger - dess organisationens IKNR eller ODS-kod, en nationell profils kontakt nivå - utan att konverteraren gissar det. Ett skript som genererar ett fel misslyckas med meddelandet, precis som alla andra transformerare. Kördes inte för fallrapporter (ecr).
23.16 FTP-mål
FTPDestination laddar upp en fil per meddelande.
Definierad som FTPDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
host | text | ja | 21 |
user | text | nej | — |
password | text | nej | — |
security | FTPSecurity | nej | explicit snarare än ingen |
insecure_skip_verify | true eller false | nej | — |
allow_clear_password | true eller false | nej | — |
dir | text | ja | — |
file_name | text | nej | — |
temp_suffix | text | nej | " |
framed | true eller false | nej | — |
timeout | varaktighet, såsom 30s eller 5m | nej | 60s |
23.16.1 värd
Värden är servern, med ett valfritt portnummer.
Standard är 21, eller 990 för implicit TLS.
23.16.2 användare
Användare och lösenord autentiserar.
En tom användare innebär anonym.
23.16.3 lösenord
Användare och lösenord autentiserar.
En tom användare innebär anonym.
23.16.4 säkerhet
Säkerhet väljer TLS: explicit, implicit eller ingen.
Standard är explicit i stället för ingen, eftersom standard för vanlig FTP skulle göra det osäkra valet det tysta, och en webbplats som verkligen inte har någon TLS bör skriva ner det.
23.16.5 insecure_skip_verify
InsecureSkipVerify accepterar alla certifikat.
Behövs oftare än någon skulle önska: dessa servrar har ofta ett självsignerat certifikat som genererades för år sedan som ingen kan återutfärda. Namnges separat så att valet är medvetet och synligt i filen snarare än dolt i en "säkerhetsläge: avslappnad".
23.16.6 allow_clear_password
AllowClearPassword tillåter ett lösenord över vanlig FTP.
Avvisas som standard, eftersom det skickar en autentiseringsuppgift över nätverket i klartext vid varje enskild leverans. Vissa analysverktyg har verkligen ingen TLS, så det måste vara möjligt - men det måste skrivas ner, så att det är ett beslut som någon har fattat snarare än en standard som de har ärvt. Namnet är medvetet obekvämt att skriva.
23.16.7 temp_suffix
TempSuffix läggs till medan filen skrivs och tas bort med en omnamning när den är klar.
Standard är ".part".
Den som samlar in dessa filer är vanligtvis ett schemalagt jobb som tar allt den hittar, och utan omnamningen tar den så småningom halva meddelandet.
23.16.8 tidsgräns
Timeout begränsar en överföring.
Defaults to 60s.
23.17 GCS-mål
GCSDestination skriver varje meddelande som ett objekt.
Definieras som GCSDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
object | text | nej | ${date}/${channel}/${control_id} |
storage_class | text | nej | — |
content_type | text | nej | — |
23.17.1 objekt
Objekt är objektnamnet, med samma platshållare som en S3-nyckel.
Standard är ${date}/${channel}/${control_id}.hl7.
23.18 HTTP-mål
HTTPDestination skickar meddelanden till en HTTP-slutpunkt.
Det vanligaste som en Mirth-kanal gör som Perfuse inte kunde, och det vanligaste hindret som översättaren rapporterar. De flesta användningar är oglamorösa: skicka meddelandet till en intern API, skicka det till en webbtjänst som omger ett äldre system, skicka det till något som någon skrev på en eftermiddag.
Definieras som HTTPDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
method | text | nej | — |
content_type | text | nej | — |
headers | mappning av text till text | nej | — |
bearer_token | text | nej | — |
username | text | nej | — |
password | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
success_status | lista av heltal | nej | valfri 2xx |
fail_on_body | lista av text | nej | — |
follow_redirects | true eller false | nej | — |
23.18.1 url
URL är var du ska skicka.
Required.
23.18.2 metod
Metoden standard är POST.
PUT är tillåtet för en slutpunkt som vill ha det.
GET och DELETE nekas: detta skickar en meddelandetext, och ett transportmedel som tyst droppar meddelandet på grund av ett metodval skulle vara ett mycket tyst sätt att förlora data.
23.18.3 innehållstyp
ContentType standard är application/hl7-v2+er7, som är den registrerade typen för ett pipe-avgränsat HL7 v2-meddelande.
Många slutpunkter vill ha text/plain istället.
23.18.4 bearer_token
BearerToken skickas som en auktoriseringshuvud.
Föredra en miljövariabelreferens över en bokstav i en fil som går in i git.
23.18.5 success_status
SuccessStatus listar statuskoderna som räknas som levererade.
Standard är alla 2xx.
Konfigurerbart eftersom slutpunkter inte är överens om vad som utgör en framgång: vissa svarar 200 med ett fel i brödtexten, och vissa svarar 202 för en kö som de har accepterat meddelandet till.
23.18.6 fail_on_body
FailOnBody behandlar ett svar som innehåller någon av dessa strängar som ett fel, oavsett statuskod.
Detta finns eftersom en slutpunkt som svarar 200 med "ERROR: patient not found" i brödtexten är vanligt, och att behandla det som levererat innebär att meddelandet försvinner och ingen vet.
23.18.7 follow_redirects
FollowRedirects tillåter begäran att omdirigeras.
Avstängt som standard: en omdirigering på en skrivning skulle skicka om kliniska data till en plats som konfigurationen aldrig namngav.
23.19 IBMMQ Mål
IBMMQDestination lägger varje meddelande på en kö.
Definierat som IBMMQDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
non_persistent | true eller false | nej | — |
23.19.1 non_persistent
NonPersistent skickar meddelanden som inte överlever en omstart av köhanteraren.
Avstängd som standard.
23.20 Java Script Mål
JavaScriptDestination kör ett skript istället för att skicka någonstans.
Mirths JavaScript Writer, och det används mycket mer än dess position i en funktionlista antyder. Det är undantaget: när en webbplats behöver prata med något som ingen anslutning täcker, eller tillämpa logik som ingen transformation uttrycker, skriver de en JavaScript Writer. En migration som inte kan köra dessa kan inte flytta kanalerna som har dem, vilket i en mogen Mirth-installation är en stor andel.
Medvetet inte en allmän skriptvärd. Skriptet får meddelandet och samma hjälpare som en transformer får; vad det inte får är ett sätt att nå filsystemet eller nätverket, eftersom det är vad de andra målen är till för och ett skript som öppnar sin egen socket är osynligt för varje omförsök, kö och mätning i motorn.
Definierat som JavaScriptDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
script | text | ja | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
success_on_undefined | true eller false (en block, utelämna för att lämna av) | nej | true |
23.20.1 skript
Skript är den kod som ska köras.
Required.
23.20.2 tidsgräns
Timeout begränsar en exekvering.
Noll tillämpar ett standardvärde.
Begränsad eftersom ett destinations-skript finns på leveranssökvägen: en oändlig loop i ett stoppar inte bara ett meddelande, det håller också kön bakom det.
23.20.3 success_on_undefined
SuccessOnUndefined behandlar ett skript som returnerar ingenting som en framgång.
Standard är true.
True är standardvärdet och värt att förklara. Mirths JavaScript-författare gör i överväldigande grad sitt arbete och returnerar ingenting, så att kräva ett explicit returvärde skulle bryta alla dem vid import. Att ställa in det på false är för en webbplats som vill att ett skript ska vara tydligt med huruvida det fungerade.
23.21 Kafka-mål
KafkaDestination publicerar meddelanden till ett Kafka-ämne.
Definierat som KafkaDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
brokers | lista med text | ja | — |
topic | text | ja | — |
key | text | nej | — |
acks | text | nej | all |
compression | text | nej | snappy |
headers | mappning av text till text | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | trettio sekunder |
sasl | KafkaSASL (en block, utelämna för att lämna av) | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
23.21.1 mäklare
Mäklare är bootstrap-serverlistan.
Required.
23.21.2 ämne
Ämne är var meddelandet ska publiceras.
Required.
23.21.3 nyckel
Nyckel är en mall för postnyckeln, som bestämmer partitionen.
Detta är fältet som gör Kafka säkert för en klinisk feed, och det är värt att vara exakt om varför. Kafka garanterar ordning inom en partition och ingen annanstans. Poster med samma nyckel hamnar alltid i samma partition, så nyckling på patientidentifikatorn håller patientens händelser i ordning medan olika patienter kan gå parallellt.
Utan en nyckel finns det ingen sådan garanti. Mätt mot en riktig broker, trettio onycklade poster gick till en partition istället för att spridas: klienten håller en batch samman och väljer en ny partition mellan batcher. Så ordningen håller av en tillfällighet och bryts vid en gräns som ingen kan se, vilket är värre än att bryta konsekvent - en A03-utskrivning lästes före dess A01-inläggning, intermittent, under belastning.
En HL7-sökväg, utvärderad mot det utgående meddelandet: PID-3.1 nycklar på patient.
23.21.4 acks
Acks är hur många brokers som måste bekräfta en skrivning: "all", "leader" eller "none".
Standard är all, vilket är den enda inställningen som överlever en broker som misslyckas mellan skrivningen och replikeringen. "none" är eld-och-glöm och kommer att förlora meddelanden; det finns eftersom någon som flyttar icke-klinisk telemetri kan legitimt vilja ha det, och att vägra det helt och hållet skulle betyda att de skrev sin egen producent istället.
23.21.5 komprimering
Komprimering är "none", "gzip", "snappy", "lz4" eller "zstd".
Standard är snappy.
På som standard eftersom HL7 är högt komprimerbart text och tråden är vanligtvis begränsningen. Snappy snarare än zstd som standard: det är det billigaste i CPU, och en anslutning på leveranssökvägen bör inte vara det som mättar en kärna.
23.21.6 headers
Huvuden är posthuvuden som ställs in.
Värden är mallar som utvärderas per meddelande.
23.21.7 tidsgräns
Tidsgräns begränsar en publicering.
Standardvärdet är trettio sekunder.
23.22 MPI Mottagare
MPIMottagare registrerar varje meddelandes patient i denna servers patientindex: en HL7 v2 PID (en A40-sammanslagning slås samman), eller en FHIR-patient på en rå kanal.
Indexet bestämmer vilka poster som är samma person; se patientindexskärmen.
Definierad som MPIDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
authorities | mappning av text till text | nej | — |
id_type | text | nej | — |
ssn_system | text | nej | — |
no_merge | true eller false | nej | — |
23.22.1 myndigheter
Myndigheter mappar en tilldelande myndighets namnrymd (PID-3.4.1) till dess identifieringssystem, för avsändare som inte tillhandahåller någon universell identifierare.
Ommappade blir urn:perfuse:aa:<namnrymd>.
23.22.2 id_typ
IDTyp är identifieringstypen (PID-3.5) för postens eget nummer.
Default MR.
23.22.3 ssn_system
SSNSystem namnger PID-19 som en identifierare.
Default http://hl7.org/fhir/sid/us-ssn.
23.23 MQTT Mottagare
MQTTMottagare publicerar till ett ämne.
Definierad som MQTTDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
topic | text | ja | — |
retain | true eller false | nej | — |
23.23.1 ämne
Ämne som publiceras till.
Det får inte innehålla jokertecken.
23.24 PAS-destination
PASDestination skickar varje meddelande, en Da Vinci PAS-begäran, till en betalares Claim/$submit, för en leverantör vars system bygger begäran (ett EHR, DTR) och behöver den skickad, beslutet registrerat och svaret vidarebefordrat.
Definierad som PASDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
payer | text | ja | — |
bearer_token | text | nej | — |
auth | FHIRAuth (en block, utelämna för att lämna av) | nej | — |
results_to | text | nej | — |
23.24.1 bearer_token
BearerToken är en statisk token, ${ENV} tillåten.
Auth är OAuth-klientautentiseringsuppgifter istället, eller Azure, som en FHIR-destinations.
23.24.2 auth
BearerToken är en statisk token, ${ENV} tillåten.
Auth är OAuth-klientautentiseringsuppgifter istället, eller Azure, som en FHIR-destinations.
23.25 Pub Sub Mottagare
PubSubMottagare publicerar till ett Pub/Sub-ämne.
Definierad som PubSubDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
topic | text | ja | — |
order_by | text | nej | — |
23.26 S3-mål
S3Destination skriver varje meddelande som ett objekt.
Definierad som S3Destination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
bucket | text | ja | — |
region | text | ja | — |
key | text | nej | en datum-partitionerad sökväg plus kontroll-id |
access_key_id | text | nej | — |
secret_access_key | text | nej | — |
session_token | text | nej | — |
endpoint | text | nej | — |
path_style | true eller false | nej | — |
server_side_encryption | text | nej | — |
content_type | text | nej | application/hl7-v2 för HL7 och text/plain i övrigt |
framed | true eller false | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | 60s |
storage_class | text | nej | — |
format | text | nej | — |
23.26.1 nyckel
Nyckelmallar objektets nyckel med hjälp av samma ${date}, ${timestamp}, ${control_id}, ${message_type} och ${channel}-platshållare som fil- och SFTP-målen.
Standard är en datum-partitionerad sökväg plus kontroll-id.
Datum-partitionering som standard eftersom alternativet - alla objekt i en platt prefix - skapar en bucket som är långsam att lista och omöjlig att livscykla efter ålder, och ingen upptäcker det förrän det finns fyra miljoner objekt i den.
23.26.2 access_key_id
AccessKeyID och SecretAccessKey autentiserar.
Antingen kan namnge en miljövariabel istället för att hålla värdet, med formen ${NAME}.
23.26.3 secret_access_key
AccessKeyID och SecretAccessKey autentiserar.
Antingen kan namnge en miljövariabel istället för att hålla värdet, med formen ${NAME}.
23.26.4 path_style
PathStyle adresserar bucketen som en sökväg snarare än ett underdomän.
De flesta S3-kompatibla lagringsutrymmen behöver detta.
23.26.5 innehållstyp
ContentType märker objektet.
Standard är application/hl7-v2 för HL7 och text/plain i övrigt.
23.26.6 tidsgräns
Timeout begränsar en uppladdning.
Defaults to 60s.
23.26.7 storage_class
StorageClass är den S3-lagringsklass som varje objekt skrivs med: STANDARD_IA, INTELLIGENT_TIERING, GLACIER_IR, GLACIER, DEEP_ARCHIVE och så vidare.
Detta är hur ett arkiv går direkt till Glacier - S3 har ingen separat Glacier-API att anropa.
23.26.8 format
Format är hl7 (standard: varje objekt är meddelandet) eller ndjson: varje objekt är en JSON-rad med meddelandet och fälten som är värda att fråga, under datum-partitionerade nycklar, så Amazon Athena kan fråga arkivet.
Se perfuse athena.
23.27 SFTP-mål
SFTPDestination skriver varje meddelande till en fil på en SFTP-server.
Definierad som SFTPDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
host | text | ja | 22 |
user | text | ja | — |
password | text | nej | — |
key_file | text | nej | — |
key_passphrase | text | nej | — |
known_hosts_file | text | nej | — |
insecure_skip_host_key_check | true eller false | nej | — |
dir | text | ja | — |
file_name | text | nej | en tidsstämpel plus kontroll-ID |
temp_suffix | text | nej | " |
framed | true eller false | nej | — |
append | true eller false | nej | — |
timeout | varaktighet, såsom 30s eller 5m | nej | 60s |
23.27.1 värd
Värden är servern, med ett valfritt portnummer.
Defaults to 22.
23.27.2 lösenord
Lösenord autentiserar med ett lösenord.
Prefer KeyFile.
23.27.3 file_name
Mall för filnamn.
Standard är en tidsstämpel plus kontroll-ID.
23.27.4 temp_suffix
TempSuffix läggs till medan en fil skrivs och tas bort genom en omnamning när den är klar.
Standard är ".part".
Samma artighet som denna anslutning behöver på vägen in. Den som samlar in dessa filer har samma problem, och en omnamning inom en katalog är atomisk på varje server som är värd att använda.
23.27.5 tidsgräns
Tidsgräns begränsar en enskild anslutning.
Defaults to 60s.
23.28 SMTP-mottagare
SMTP-mottagare konfigurerar leverans via e-post.
Definierad som SMTPDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
host | text | ja | — |
from | text | ja | — |
to | lista med text | ja | — |
cc | lista med text | nej | — |
bcc | lista med text | nej | — |
subject | text | nej | — |
body | text | nej | — |
attach | true eller false | nej | — |
attach_name | text | nej | kontroll-ID med en |
username | text | nej | — |
password | text | nej | — |
starttls | true eller false (en block, utelämna för att lämna av) | nej | — |
insecure_skip_verify | true eller false | nej | — |
timeout | varaktighet, såsom 30s eller 5m | nej | — |
23.28.1 värd
Värd är e-postservern, med ett valfritt portnummer.
Port 587 antas, vilket är inlämning med STARTTLS - det portnummer som en modern server förväntar sig att en klient ska använda. Port 25 är server-till-server och är vanligtvis antingen blockerad eller oautentiserad.
23.28.2 från
Från är avsändaren.
Obligatorisk, eftersom ett meddelande utan avsändare tyst diskvalificeras av en stor del av e-postinfrastrukturen, vilket gör det till den svåraste möjliga felkällan att diagnostisera.
23.28.3 till
Till, CC och BCC är mottagare.
Minst en Till är obligatorisk.
23.28.4 cc
Till, CC och BCC är mottagare.
Minst en Till är obligatorisk.
23.28.5 bcc
Till, CC och BCC är mottagare.
Minst en Till är obligatorisk.
23.28.6 brödtext
Brödtext är meddelandetexten.
Fältreferenser ersätts, som i Ämne. När den är tom är meddelandet själv brödtexten.
23.28.7 bilaga_namn
BilagaNamn namnger bilagan.
Standard är kontroll-ID med en .hl7-suffix.
23.28.8 användarnamn
Användarnamn och Lösenord autentiserar till servern.
Antingen båda eller ingen.
23.28.9 lösenord
Användarnamn och Lösenord autentiserar till servern.
Antingen båda eller ingen.
23.28.10 starttls
StartTLS uppgraderar anslutningen innan autentisering.
Det är som standard aktiverat och att stänga av det med ett användarnamn inställt nekas i stället för att tillåtas: att skicka ett lösenord över en oekrypterad anslutning är inte en kompromiss som är värd att erbjuda.
23.28.11 insecure_skip_verify
InsecureSkipVerify accepterar alla certifikat.
Namngiven entydigt eftersom det är vad den gör.
23.29 SNS-mål
SNSDestination publicerar varje meddelande till ett SNS-ämne.
Definierad som SNSDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
topic_arn | text | ja | — |
subject | text | nej | — |
group_by | text | nej | — |
23.29.1 ämne
Ämne skickas med e-postprenumerationer.
Valfritt; ${message_type} och ${control_id} fylls i.
23.30 SOAP-mål
SOAPDestination skickar en SOAP-förfrågan per meddelande.
Definierad som SOAPDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
profile | text | nej | — |
facility_id | text | nej | — |
warnings_are_errors | true eller false | nej | — |
action | text | nej | — |
version | text | nej | 1 |
body | text | ja | — |
header | text | nej | — |
headers | mappning av text till text | nej | — |
username | text | nej | — |
password | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
fault_is_success | lista av text | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | 30s |
23.30.1 profil
Profilnamn anger en standardtjänst vars omslag Perfuse bygger själv.
Tom är ett vanligt SOAP-anrop med brödtexten skriven i den här filen.
"cdc-iis" är CDC:s vaccinationsregistergränssnitt (urn:cdc:iisb:2011), som varje amerikansk delstatsregister använder: meddelandet skickas i submitSingleMessage, användarnamn och lösenord skickas i brödtexten enligt WSDL (inte som HTTP-autentisering), SOAP 1.2 som standard och registrets HL7-bekräftelse avgör om meddelandet levererades. Ett register svarar på ett avvisat skott med HTTP 200 och en AR inuti, så utan detta läser en avvisning som en framgång.
23.30.2 anläggnings_id
Anläggnings-ID är cdc-iis-anläggnings-ID, registrets identifierare för den som skickar organisationen.
Valfritt i WSDL; vissa register kräver det.
23.30.3 varningar_är_fel
VarningarÄrFel, för cdc-iis, behandlar en AE-bekräftelse som bara innehåller varningar som ett fel.
Avstängd som standard: register skickar AE för "godkänt med varningar" och ERR-allvarlighetsgraden anger om något gick förlorat.
23.30.4 åtgärd
Åtgärd är SOAPAction.
Krävs av de flesta 1.1-tjänster.
23.30.5 brödtext
Brödtext är den XML som placeras inuti kuvertet, med ${PID-5.1}-liknande referenser till meddelandesökvägar.
Obligatorisk, såvida inte en profil skapar den. Det finns inget användbart standardvärde: elementnamnen kommer från tjänstens eget schema och ingen motor kan gissa dem.
23.30.6 huvud
Huvud är XML för kuvertets huvudelement.
Utelämnas helt när den är tom, eftersom vissa tjänster avvisar en tom sådan.
23.30.7 fel_är_lyckad
FelÄrLyckad listar felkoder som räknas som levererade.
Behövs oftare än det borde. En tjänst som svarar på en omssändning med "redan skickad" berättar för dig att meddelandet anlände, och utan detta måste en webbplats skriva en svarstransformator för att säga så - eller värre, tittar på en kö som försöker om och om igen mot en mottagare som redan har meddelandet.
23.30.8 tidsgräns
Tidsgräns begränsar ett anrop.
Defaults to 30s.
23.31 SQS-mål
SQSMål skickar varje meddelande till en SQS-kö.
Definierad som SQSDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
queue_url | text | ja | — |
group_by | text | nej | — |
23.31.1 kö_url
KöURL namnger kön.
En som slutar med .fifo är en FIFO-kö och grupperas och dubblettreduceras.
23.32 TCP-mål
TCPMål skickar meddelanden till en socket med konfigurerbar ram.
Definierad som TCPDest i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
address | text | ja | — |
max_message_size | heltal | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
expect_reply | true eller false | nej | — |
keep_alive | true eller false | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
23.32.1 vänta_på_svar
VäntaPåSvar väntar på byte tillbaka innan det rapporterar framgång.
Avstängd som standard, och värt att fundera på. Med den avstängd betyder "levererad" att byte nådde operativsystemets skicka buffert, som en peer som kraschade ett ögonblick senare aldrig läste. Med den på, gör en peer som aldrig svarar att varje meddelande timeout.
23.32.2 keep_alive
KeepAlive håller en anslutning öppen över meddelanden snarare än att ringa per meddelande.
De flesta enhetsändpunkter förväntar sig detta; vissa vägrar ett andra meddelande på samma anslutning. Avstängd som standard eftersom en anslutning per meddelande är beteendet som fungerar överallt, till en kostnad av en handskakning varje gång.
23.33 TEFCA-destination
TEFCADestination ber TEFCA Facilitated FHIR-partnern om patientens journaler för varje meddelandes patient.
Vem denna server är på nätverket, dess certifikat och parten är serverinställningar (Inställningar, TEFCA), eftersom de tillhör organisationen och dess avtal med en QHIN. Vad en kanal bestämmer är när och varför: syftet med användningen är en del av kanalen, inte av vem som är inloggad, så varje fråga en feed gör anger samma anledning och revisions-spåret kan läsas mot den.
Definierad som TEFCADestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
purpose | text | ja | — |
results_to | text | nej | — |
23.33.1 syfte
Syfte är syftet med användningen: behandling, betalning, drift, folkhälsa eller individuell åtkomst.
Det måste vara en av de deltagare som deklarerar.
23.33.2 resultat_till
ResultatTill namnger en kanal i denna server som tar emot varje Bundle som parten returnerar, som ett meddelande i sig.
Tomma håller Bundle som detta måls svar endast, för en svarstransformator att läsa.
23.34 XDS Mottagare
XDSDestination publicerar varje kliniskt dokument till en IHE XDS.b Document Repository med ITI-41 Provide and Register.
Metadatan läses från CDA-dokumentet (patient, titel, typ, tid, författare, konfidentialitet, språk) och kompletteras från dessa inställningar, som anger vad dokumentet inte kan: vem som skickar det, vilken typ av anläggning och verksamhet det kommer från, och vilken av patientens identifierare som är affinitetsdomänens.
Definierad som XDSDestination i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
source_id | text | ja | — |
patient_domain | text | nej | — |
facility_type | XDSCode | ja | — |
practice_setting | XDSCode | ja | — |
class | XDSCode (en block, utelämna för att inte använda) | nej | — |
content_type | XDSCode (en block, utelämna för att inte använda) | nej | — |
token | text | nej | — |
username | text | nej | — |
password | text | nej | — |
headers | mappning av text till text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att inte använda) | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
direct_from | text | nej | — |
direct_to | lista av text | nej | — |
23.34.1 patient_domain
PatientDomain är affinitetsdomänens tilldelande myndighets OID: patientidentifieraren med denna rot är den som registreras.
Utan den skickar ett dokument vars patient har en identifierare den identifieraren, och ett med flera identifierare vägras.
23.34.2 token
Token eller Username/Lösenord autentiserar; Headers läggs till i varje begäran.
De flesta affinitetsdomäner använder ömsesidig TLS (tls) istället.
23.34.3 användarnamn
Token eller Username/Lösenord autentiserar; Headers läggs till i varje begäran.
De flesta affinitetsdomäner använder ömsesidig TLS (tls) istället.
23.34.4 lösenord
Token eller Username/Lösenord autentiserar; Headers läggs till i varje begäran.
De flesta affinitetsdomäner använder ömsesidig TLS (tls) istället.
23.34.5 headers
Token eller Username/Lösenord autentiserar; Headers läggs till i varje begäran.
De flesta affinitetsdomäner använder ömsesidig TLS (tls) istället.
23.34.6 tls
Token eller Username/Lösenord autentiserar; Headers läggs till i varje begäran.
De flesta affinitetsdomäner använder ömsesidig TLS (tls) istället.
23.34.7 direkt_från
DirectFrom och DirectTo gör att inlämnandet XDR som Directs transport: en Direct-adressblock som namnger denna avsändares Direct-adress och mottagarnas, och mottagarna i inlämnandets avsedda mottagare.
En HISP som tar XDR levererar den som Direct-e-post eller till mottagarens eget XDR-slutpunkt.
23.34.8 direkt_till
DirectFrom och DirectTo gör att inlämnandet XDR som Directs transport: en Direct-adressblock som namnger denna avsändares Direct-adress och mottagarnas, och mottagarna i inlämnandets avsedda mottagare.
En HISP som tar XDR levererar den som Direct-e-post eller till mottagarens eget XDR-slutpunkt.
24 Formatreferens
Alternativ som styr hur meddelanden parsas och skrivs, för format som behöver mer än ett namn.
24.1 Bilagor
Bilagor konfigurerar flyttning av stora nyttolaster utanför ett meddelande.
Ett meddelande som bär en skannad rapport eller en PDF är vanligt i dokumentflöden, och nyttolasten är rutinmässigt hundratals gånger större än meddelandet runt omkring. Lämnad inline betyder det att lagret växer i takt med dokumenten snarare än trafiken, ett meddelande som köas för fem destinationer kopieras fem gånger, och gränssnittet strömmar megabyte för att visa någon en patientnamn.
Mirth kallar dessa bilagehanterare. Detta är motsvarigheten, och det är valfritt per kanal eftersom en feed av vanliga ADT-meddelanden inte har något att extrahera och bör inte betala för maskineriet.
Definierad som Attachments i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
extract | lista med attach.Regel | ja | — |
reassemble | true eller false (en block, utelämna för att lämna av) | nej | true |
24.1.1 reassemble
Reassemble lägger tillbaka nyttolaster före leverans.
Standard är true.
Standardvärdet är på eftersom en mottagare som förväntar sig ett dokument måste få ett dokument; ett meddelande som innehåller en bokstavlig token skulle arkiveras som en rapport och ingen skulle ta reda på det förrän någon öppnade posten.
Att stänga av det är för det fall där kanalen syftar till att ta bort dokument - vidarebefordra metadata till ett system som inte har någon användning för bilden, där att skicka den skulle vara en fråga om sekretess snarare än bandbredd.
24.2 Avgränsad
Avgränsad konfigurerar en avgränsad kanal.
Mirths avgränsade datatyp: CSV, tabbavgränsad och den långa svansen av format som en laboratorieanalytiker eller en byråtjänst emitterar.
Definierad som Delimited i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
delimiter | text | nej | — |
quote | text | nej | en dubbel citat |
comment | text | nej | — |
has_header | true eller false | nej | — |
columns | lista av text | nej | — |
trim_space | true eller false | nej | — |
relaxed | true eller false | nej | — |
split | true eller false (en block, utelämna för att lämna av) | nej | true |
keep_blank_lines | true eller false | nej | — |
filter | text | nej | — |
transformations | lista av steps.Step | nej | — |
24.2.1 avgränsare
Avgränsaren separerar kolumner, som en tecken eller ett namn.
Ett namn accepteras eftersom en tabb inte kan skrivas in i en YAML-fil utan tvetydighet, och en konfigurationsfil som innehåller en osynlig tecken är oläslig för den som öppnar den nästa.
24.2.2 citat
Citatet omger värden som innehåller avgränsaren.
Standard är ett dubbelcitat; "none" inaktiverar det.
24.2.3 delad
Delad gör varje rad till sitt eget meddelande.
Standard är true.
Detta är beslutet som formar en avgränsad kanal och det förtjänar att sägas högt. En fil med fem tusen resultat är antingen ett meddelande eller fem tusen. Ett meddelande innebär ett erkännande, en post i webbläsaren och ett fel som tar med sig hela filen. Fem tusen innebär att varje rad filtreras, omvandlas, levereras och försöks igen på egen hand, och en enskild dålig rad stoppar inte resten.
Delning är standard eftersom per-radhantiering är vad nästan varje webbplats vill ha och eftersom alternativet upptäcks sent: en kanal som såg bra ut i testning med en tre-radersfil misslyckas en hel natts överföring på grund av en felaktig rad.
24.2.4 behåll_tomma_rader
BehållTommaRader stoppar tomma rader från att hoppas över.
Hoppande är standard, eftersom varje fil slutar med en ny rad och en post med tomma fält är inte en post. Detta finns för det sällsynta formatet där en tom rad är meningsfull.
24.2.5 filter
Filter bestämmer vilka meddelanden fortsätter, skrivna mot kolumnnamn.
Här snarare än på kanalen eftersom kanalens filter sammanställer HL7-sökvägar. Två inställningar med namnet filter skulle vara förvirrande, men en inställning som betyder olika saker beroende på dataType är värre: en avgränsad kanal som tyst sammanställde sitt filter som HL7 skulle matcha ingenting och släppa allt, vilket är felet som det övergripande avslaget finns för att förhindra.
24.2.6 transformationer
Omvandlingar är de deklarativa stegen, som adresserar kolumner snarare än HL7-fält.
Separat från kanalens omvandlingar av samma anledning som Filter, och det är den ordning som X12 och NCPDP redan använder.
24.3 HL7v3-alternativ
HL7v3-alternativ är inställningarna som endast gäller för en HL7 v3-kanal.
Definierad som HL7v3Options i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
filter | text | nej | — |
acknowledge | true eller false (en block, utelämna för att lämna av) | nej | — |
sender_device | text | nej | — |
sender_oid | text | nej | — |
transformations | lista av hl7v3.Step | nej | — |
24.3.1 filter
Filter utesluter meddelanden med hjälp av v3-sökvägar.
Det är ett eget fält snarare än kanalen vanliga filter, eftersom de två är olika språk mot olika meddelandemodeller. Att dela fältet skulle innebära att ett v2-filter tyst inte matchar på en v3-kanal, eller att ett v3-filter misslyckas med att parsas som v2 - och den senare är bara bättre för att den misslyckas högt.
En kanal som ställer in båda två nekas vid inläsning, eftersom en av dem måste ignoreras och det finns inget ärligt sätt att välja.
24.3.2 bekräfta
Bekräfta skickar en MCCI_IN000002UV01-bekräftelse tillbaka.
På som standard, till skillnad från X12. En v3-interaktion över en synkron transport förväntar sig en bekräftelse - den skickande applikationen väntar vanligtvis på en - och en avsändare som inte får någon kommer vanligtvis att försöka igen, vilket är hur en patient registreras tre gånger.
En peka så att "inte inställd" och "inställd på falskt" är olika: standard är på, och någon som stänger av den bör ha sagt så.
24.3.3 avsändar_enhet
AvsändarEnhet är enhetsidentifieraren som vi lägger i en bekräftelse.
Krävs när bekräftelse skickas. En v3-bekräftelse namnger den enhet den kommer från, och en mottagare som inte känner igen vår kan kasta den - vilket ser ut exakt som att inte skicka en.
24.3.4 transformationer
Transformationer ändrar innehållet i ett v3-dokument.
Det är ett eget fält snarare än kanalen vanliga transformationer, av samma anledning som filtret: de är olika vokabulärer mot olika meddelandemodeller. V2-stegen adresserar segment och fält, som ett v3-dokument inte har, så att dela fältet skulle innebära att ett steg tyst inte gör något.
Stegnamnen matchar v2-namnen där betydelsen matchar, så att någon som har skrivit en kanal kan skriva den andra. Vad som är annorlunda är vad v3 behöver och v2 inte kan uttrycka - främst att att ta bort ett värde har tre olika betydelser, så clear, nullflavor och remove är tre steg snarare än ett.
24.4 TCP-ramning
TCP-ramning är hur meddelandegränser hittas på en rå socket.
Delas av TCP-källan och TCP-destinationen, och av den seriella källan, eftersom ramningarna är desamma oavsett var byte kommer från. Ett laboratorieanalyser som talar STX/ETX över en socket talar STX/ETX över en seriekabel också.
Definieras som TCPFraming i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
framing | text | ja | — |
delimiter | text | nej | — |
start_block | text | nej | — |
keep_delimiter | true eller false | nej | — |
record_length | heltal | nej | — |
trim_padding | true eller false (en block, utelämna för att lämna av) | nej | — |
length_bytes | heltal | nej | — |
big_endian | true eller false | nej | — |
length_includes_header | true eller false | nej | — |
24.4.1 ramning
Ramning är mllp, avgränsad, fast, längd eller hel.
Obligatorisk, utan standard. Att läsa en ström med felaktig ramning producerar meddelanden som ser trovärdiga ut snarare än ett fel, så att gissa är sämre än att fråga.
24.4.2 start_block
StartBlock börjar valfritt en meddelande.
Byte före det kastas bort som brus från en partiell anslutning.
24.4.3 behåll_avgränsare
KeepDelimiter inkluderar avgränsaren i meddelandet.
Avstängd som standard: det är ramverk, inte innehåll.
24.4.4 trim_padding
TrimPadding tar bort efterföljande blanksteg och NUL från en fast post.
På som standard.
24.5 X12-alternativ
X12-alternativ är inställningar som endast gäller för en X12-kanal.
Definierad som X12Options i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
envelope | EnvelopePolicy | nej | krävs |
split | true eller false | nej | — |
acknowledge | text | nej | — |
ack_sender_id | text | nej | — |
ack_sender_qualifier | text | nej | — |
arrives_as | text | nej | — |
transformations | lista över x12.Step | nej | — |
24.5.1 envelope
Envelope anger vad som ska göras när de självdeklarerade räkningarna inte matchar vad som finns.
Standard är krävs.
24.5.2 delad
Split skickar ett meddelande per transaktionssats istället för ett per fil.
Avstängd som standard. En enda 837 kan innehålla hundratals anspråk, så att aktivera detta multiplicerar allt nedströms - meddelandecount, bekräftelser, rader, varningströsklar - och det bör vara ett beslut som någon har fattat snarare än en standard som de har ärvt.
24.5.3 bekräfta
Acknowledge anger vilken bekräftelse som ska skickas tillbaka: 999, 997, ta1 eller ingen.
Vilken som helst är en egenskap hos handelspartnerskapet snarare än meddelandet, så den måste konfigureras. En 999 ersätter en 997 för HIPAA-transaktioner, men många partners - äldre betalningsanslutningar i synnerhet - är konfigurerade för att förvänta sig en 997 och kommer att behandla en 999 som en okänd fil. Att skicka fel bekräftelse är värre än att inte skicka någon alls, eftersom det svarar på en fråga som ingen har ställt och lämnar den riktiga öppen.
Tom betyder ingen, vilket är standardvärdet: en partner som inte förväntar sig en bekräftelse och får en kan behandla den som en oönskad växling.
24.5.4 ack_sender_id
AckSenderID och AckSenderQualifier är vår egen växlingsidentifierare, som blir ISA06 och ISA05 för eventuella bekräftelser.
Obligatoriskt när Acknowledge är inställt, och vägras vid inläsning annars. Dessa måste vara de värden som handelspartnern har konfigurerat för oss och det finns inget sätt att gissa dem: en växling vars ISA06-partnern inte känner igen kasseras innan någon läser den, så ett felaktigt värde producerar tystnad som ser ut som om ingenting skickades - och någon tillbringar en vecka med att leta på fel plats.
24.5.5 ack_sender_qualifier
AckSenderID och AckSenderQualifier är vår egen växlingsidentifierare, som blir ISA06 och ISA05 för eventuella bekräftelser.
Obligatoriskt när Acknowledge är inställt, och vägras vid inläsning annars. Dessa måste vara de värden som handelspartnern har konfigurerat för oss och det finns inget sätt att gissa dem: en växling vars ISA06-partnern inte känner igen kasseras innan någon läser den, så ett felaktigt värde producerar tystnad som ser ut som om ingenting skickades - och någon tillbringar en vecka med att leta på fel plats.
24.5.6 anländer_som
AnländerSom är xml när källan levererar utbytet som XML som Mirth Connect och Open Integration Engine skriver för X12 (en X12Transaction rot, element med namn CLM.05.1), som en motor som migreras från, eller ett system byggt mot en, skickar det.
Det omvandlas tillbaka till X12 innan något annat händer. Tomma eller x12 är X12.
24.5.7 transformationer
Transformations är deklarativa ändringar som tillämpas på accepterade växlingar.
Separat från kanalens transformations för samma anledning som v3: de adresserar HL7-fält genom en parser som läser segment-fält-komponent-underkomponent, och X12 har ingen underkomponent, behandlar upprepade segment som vanliga snarare än exceptionella, och skrivs CLM01 av de som konfigurerar den. En delad parser måste acceptera båda notationerna och skulle då vara tvetydig i båda.
Stegnamnen är desamma som HL7- och v3-stegen använder, så det som en författare redan har lärt sig förmedlas.
25 Beteendereferens
Bekräftelse, köning, omförsök, polling, skriptning och skugginställningar. Dessa gäller oavsett vilken transport en kanal använder.
25.1 AMQP-anslutning
AMQP-anslutning är var och som vem man ansluter.
Definierad som AMQPConnection i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
addr | text | ja | — |
address | text | ja | — |
username | text | nej | — |
password | text | nej | — |
hostname | text | nej | värden för addr |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | 30s |
25.1.1 användarnamn
Användarnamn och lösenord autentiserar med SASL PLAIN; båda tomma betyder ANONYMOUS.
För Service Bus, principnamn och nyckel.
25.1.2 lösenord
Användarnamn och lösenord autentiserar med SASL PLAIN; båda tomma betyder ANONYMOUS.
För Service Bus, principnamn och nyckel.
25.1.3 värddnamn
Värddnamn skickas till brokern, som Service Bus dirigerar på.
Standard är värden för addr.
25.1.4 tls
TLS krypterar anslutningen.
Obligatorisk för Service Bus och Event Hubs.
25.1.5 tidsgräns
Tidsgräns för anslutning och varje väntan på brokern.
Defaults to 30s.
25.2 AS2-partner
AS2-partner är en handelspartner som en AS2-källa accepterar meddelanden från.
Definierad som AS2Partner i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
id | text | ja | — |
cert_file | text | ja | — |
allow_unsigned | true eller false | nej | — |
allow_unencrypted | true eller false | nej | — |
25.2.1 cert_file
CertFile är partnerns certifikat (PEM), för dess signaturer.
Ofta självsignerad: AS2-partner utbyter certifikat direkt snarare än genom en myndighet.
25.2.2 allow_unsigned
AllowUnsigned och AllowUnencrypted accepterar ett meddelande från denna partner som inte är signerat eller inte krypterat.
Av: ett sådant meddelande avvisas med en kvittens som anger varför.
25.2.3 allow_unencrypted
AllowUnsigned och AllowUnencrypted accepterar ett meddelande från denna partner som inte är signerat eller inte krypterat.
Av: ett sådant meddelande avvisas med en kvittens som anger varför.
25.3 AWS-åtkomst
AWS-åtkomst är hur en anslutning når AWS: den region den skriver under för, nycklarna och ett valfritt slutpunktsöverlag.
Autentiseringsuppgifter kan vara bokstavligen eller ${ENV_VAR}-referenser, vilket är hur de bör tillhandahållas. Det finns ingen instans-metadata-credentialed kedja, med avsikt: se internal/awsv4.
Definierad som AWSAccess i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
region | text | ja | — |
access_key_id | text | nej | — |
secret_access_key | text | nej | — |
session_token | text | nej | — |
endpoint | text | nej | — |
25.3.1 secret_access_key
SecretAccessKey är den hemliga, bokstavligen eller ${AWS_SECRET_ACCESS_KEY}.
Föredra referensen: den här filen går in i versionskontroll.
25.3.2 session_token
SessionToken är endast för tillfälliga autentiseringsuppgifter.
De upphör att gälla, och anslutningen slutar fungera när de gör det.
25.4 Bekräftelse
Bekräftelse konfigurerar generering av bekräftelser.
Definierad som Ack i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
when | AckWhen | nej | — |
application | text | nej | — |
facility | text | nej | — |
include_trigger_event | true eller false | nej | — |
25.4.1 include_trigger_event
IncludeTriggerEvent skickar ACK^A01 snarare än ACK.
Vissa mottagare kräver det och andra avvisar det, så det är uttryckligen.
25.5 Azure Blob-åtkomst
AzureBlobAccess är kontot, behållaren och autentiseringsuppgifterna.
Definierad som AzureBlobAccess i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
account | text | ja | — |
container | text | ja | — |
key | text | nej | — |
sas | text | nej | — |
endpoint | text | nej | — |
25.5.1 nyckel
Nyckel är kontonyckeln eller ${AZURE_STORAGE_KEY}.
Ställ in den eller sas.
25.5.2 sas
SAS är en delad åtkomstsignatur-frågesträng, eller en ${...}-referens.
Föredragen: den kan begränsas till den här behållaren.
25.6 Kontraktreferens
ContractRef pekar på en kanal till dess kontrakt.
Definierad som ContractRef i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
file | text | ja | — |
check_every | text | nej | 15 minuter |
over | heltal | nej | 500 |
25.6.1 kontrollera varje
CheckEvery är hur ofta man ska kontrollera igen, som en varaktighet.
Standard är 15 minuter.
Effektivt golvad vid varningsutvärderingsintervallet, som är 30 sekunder som standard, eftersom kontrollen körs från den slingan snarare än en egen timer - så ett kontrakt som begär 3s får 30s. Det är medvetet: en timer är lättare att resonera om än två, och det håller ett kontraktresultat i takt med den läsning det är kopplat till. Värt att veta innan någon ställer in ett kort intervall och drar slutsatsen att det är trasigt.
Inte per meddelande. Att bygga ett profil innebär att läsa nylig trafik, och att göra det på varje meddelande skulle göra en kanals genomströmning beroende av hur mycket historia den har - vilket är den typen av prestandakaraktär som bara visas i produktion, sex månader in.
25.6.2 över
Över är hur många nyliga meddelanden som ska profileras.
Defaults to 500.
Ett antal snarare än ett tidsfönster, eftersom en tyst matning och en upptagen matning behöver samma mängd bevis för att motivera en hastighet, och ett tidsfönster ger dem vilt olika mängder.
25.7 DICOM-alternativ
DICOMOptions konfigurerar en bildkanal.
Varför stegen är namngivna snarare än sökvägar
Varje annan format får en sökvägsskrivare. DICOM får avsiktligt inte det, och anledningen är pixeldata: ett objekt är binärt, en allmän taggskrivare kan ställa in valfri tagg till valfria byte, och ett misstag där producerar inte ett avvisat meddelande - det producerar en bild som öppnas och är fel.
Så de fyra sakerna webbplatser faktiskt behöver är namngivna åtgärder med begränsade effekter: avidentifiera, skriva om en AE-titel, ta bort privata taggar, ange institutionen. Var och en vet vilka taggar den berör, och ingen kan nå pixeldata.
Varför denna block finns nu
internal/dicom har burit steps.go och transform.go under en tid - de fyra åtgärderna, dicom.Apply och tester. Ingenting refererade till dem. Femhundra rader med ingen anropare, som könens egen avdelning 7 namnger: en implementering utan anropare är inte att skilja från en funktion som inte existerar. Denna block och motorn anrop är kopplingen, inte funktionen.
Definierad som DICOMOptions i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
transformations | lista över dicom.Step | nej | — |
25.8 Direktadress
DirectAddress är en direktadress som denna server har: dess certifikat och nyckel, och de ankare den litar på.
Samma block används för att skicka (signera som denna adress) och för att ta emot (dekryptera för den).
Definierad som DirectAddress i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
address | text | ja | — |
cert_file | text | ja | — |
key_file | text | ja | — |
anchors_file | text | ja | — |
25.8.1 cert_file
CertFile och KeyFile är adressens certifikat (PEM, med dess kedja efter det) och privat nyckel (PEM).
HISP eller dess registreringsmyndighet utfärdar dem; de är adressens identitet.
25.8.2 key_file
CertFile och KeyFile är adressens certifikat (PEM, med dess kedja efter det) och privat nyckel (PEM).
HISP eller dess registreringsmyndighet utfärdar dem; de är adressens identitet.
25.8.3 anchors_file
AnchorsFile är förtroendesankare (PEM): certifikatutfärdare som denna adress litar på, såsom DirectTrust-paketet.
Ett meddelande som signeras av något annat avvisas.
25.9 Direct IMAP
DirectIMAP är HISP-brevlådan som en Direct-källa läser.
Definierad som DirectIMAP i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
host | text | ja | — |
port | heltal | nej | — |
security | text | nej | — |
username | text | ja | — |
password | text | nej | — |
mailbox | text | nej | — |
after_read | text | nej | — |
move_to | text | nej | — |
error_folder | text | nej | — |
poll_interval | varaktighet, såsom 30s eller 5m | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
25.9.1 move_to
MoveTo är mappen som meddelanden flyttas till; Processed som standard.
Skapas när den saknas.
25.9.2 tls
TLS litar på ett CA-fil (eller HISP:s eget certifikat) och namnger den server som förväntas i det, för en HISP vars IMAP-certifikat inte kommer från en offentlig myndighet.
Certifikatet verifieras alltid.
25.10 Direct XDR
DirectXDR är slutpunkten som en Direct-källa tar XDR på.
Definierad som DirectXDR i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
listen | text | ja | — |
tls_cert | text | nej | — |
tls_key | text | nej | — |
client_ca_file | text | nej | — |
25.11 ECR-anläggning
ECR-anläggning är organisationen som skickar fallrapporter.
Definierad som ECRFacility i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
name | text | ja | — |
npi | text | nej | — |
phone | text | ja | — |
line | text | nej | — |
city | text | ja | — |
state | text | ja | — |
postal_code | text | nej | — |
25.12 EDIFACT-alternativ
EDIFACT-alternativ är inställningar som endast gäller för en EDIFACT-kanal.
Definierad som EDIFACTOptions i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
envelope | text | nej | — |
split | true eller false | nej | — |
acknowledge | text | nej | — |
25.12.1 bekräfta
Acknowledge svarar en avsändare som skickar via HTTP med ett CONTRL i svaret: accepterad (åtgärd 7) när interchange lästes och levererades, avvisad (4) annars.
Default none.
25.13 E-post-OAuth
EmailOAuth loggar in med OAuth 2.0 (SASL XOAUTH2), som Microsoft 365 och Gmail kräver i stället för lösenord.
Definierad som EmailOAuth i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
provider | text | ja | — |
tenant | text | nej | — |
token_url | text | nej | — |
client_id | text | ja | — |
client_secret | text | nej | — |
refresh_token | text | nej | — |
scope | text | nej | — |
25.13.1 client_secret
ClientSecret kan vara ${ENV}.
Utan refresh_token väljs Microsofts app-only client-credentials-bidrag.
25.13.2 refresh_token
RefreshToken kan vara ${ENV}: en brevlåda som en person har samtyckt till.
Krävs för Gmail.
25.14 FHIR Autentisering
FHIRAuth är hur en FHIR-mottagare autentiserar till en värd FHIR-tjänst.
Tre förinställningar, eftersom de värdtjänster där en bärtoken som klistras in i en fil slutar fungera inom en timme:
- aws: AWS HealthLake, som tar begäranden signerade med Signaturversion 4 för tjänsten "healthlake" - ingen token alls. - azure: Azure Health Data Services, som tar en Microsoft Entra ID-token för FHIR-tjänstens egen publik, som erhålls med klient-autentiseringsbeviljandet av en appregistrering som har rollen FHIR Data Contributor. - client_credentials: vilken OAuth 2.0-token slutpunkt som helst - Keycloak, Okta, en SMART-backend-tjänst med en klienthemlighet.
Token hämtas när de behövs och återanvänds tills en minut innan de går ut.
Definierad som FHIRAuth i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
type | text | ja | — |
region | text | nej | — |
access_key_id | text | nej | — |
secret_access_key | text | nej | — |
session_token | text | nej | — |
tenant_id | text | nej | — |
token_url | text | nej | — |
client_id | text | nej | — |
client_secret | text | nej | — |
scope | text | nej | — |
25.14.1 region
Region är AWS-regionen.
Läses från en HealthLake-URL när den inte anges.
25.14.2 token_url
TokenURL är OAuth-token-slutpunkten för client_credentials.
För azure härleds den från klienten.
25.14.3 client_id
ClientID och ClientSecret identifierar programmet.
Hemligheten kan vara en ${ENV}-referens, vilket är hur den bör anges.
25.14.4 client_secret
ClientID och ClientSecret identifierar programmet.
Hemligheten kan vara en ${ENV}-referens, vilket är hur den bör anges.
25.14.5 scope
Omfattning begärs med token.
För azure är standardvärdet FHIR-tjänstens URL följt av /.default, som är dess publik.
25.15 Filövervakning
FilePoll är den del av en fil-samlingskälla som inte har något att göra med transporten.
Delas av lokala, FTP, SMB och WebDAV-källor, och av SFTP. Var och en av dessa inställningar finns på grund av ett sätt som filer kan gå fel snarare än ett sätt som transporterna skiljer sig åt, vilket är varför de hör ihop: en webbplats som har arbetat ut rätt stable_for för sin analysator bör inte behöva arbeta ut det igen när analysatorn flyttas till en aktie.
Definierad som FilePoll i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
dir | text | ja | — |
pattern | text | nej | — |
poll_interval | varaktighet, såsom 30s eller 5m | nej | — |
after_read | text | nej | — |
move_to | text | nej | — |
error_dir | text | nej | — |
stable_for | varaktighet, såsom 30s eller 5m | nej | — |
max_file_size | hel tal | nej | — |
framed | true eller false | nej | — |
raw | true eller false | nej | — |
batch_size | hel tal | nej | — |
sort_by | text | nej | namn |
25.15.1 mönster
Mönstret väljer filer med glob.
Tom betyder varje fil.
25.15.2 felkatalog
ErrorDir är där en fil som inte kunde bearbetas hamnar.
Separat från MoveTo med flit. En katalog som endast innehåller fel är något som någon kan övervaka, och att blanda fel i arkivet innebär att det enda sättet att hitta dem är att läsa varje fil.
25.15.3 rå
Raw behandlar hela filen som ett meddelande oavsett innehåll.
Inställningen som gör att denna anslutning är användbar för något annat än HL7. Utan den kommer en CSV-batch, en X12-anspråksfil eller en PDF att delas upp på rader som börjar med MSH och producera ingenting, och felet säger att filen inte är HL7 - sant men inte poängen, eftersom filen aldrig var tänkt att vara.
25.15.4 batchstorlek
BatchSize begränsar hur många filer som läses under en omröstning.
Noll betyder ingen gräns.
Finns för den första omröstningen efter en avbrott. En katalog som innehåller fyrtiotusen filer som ackumulerats över natten kommer annars att läsas i ett steg, vilket håller omröstningsloopen upptagen så länge det tar och gör kanalen se hängd ut. Att läsa ett begränsat antal per omröstning håller kanalen responsiv och kön synligt tömmande.
25.15.5 sortera_efter
SortBy ordnar filerna inom en omröstning: namn, ändrad eller ingen.
Standard är namn. Ordningen är viktigare än det ser ut: en ADT-ström där A08-uppdateringar anländer före A01-inträdet skapar patienter som inte finns ännu. Kataloglistans ordning är godtycklig på de flesta filsystem, så att lämna den osorterad innebär att ordningen ändras mellan omröstningar utan synlig anledning.
25.16 GCP-åtkomst
GCPAccess är hur man autentiserar till Google Cloud.
Definierad som GCPAccess i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
project | text | nej | — |
credentials_file | text | nej | — |
endpoint | text | nej | — |
25.16.1 credentials_file
CredentialsFile är en tjänstekontos JSON-nyckel.
Tom används den tjänstekonto som är kopplad till den virtuella datorn, GKE-podden eller Cloud Run-tjänsten som Perfuse körs på (metadata-servern), såvida inte Slutpunkt namnger en emulator.
25.17 GCS-åtkomst
GCSAccess är en Cloud Storage-bucket.
Definierad som GCSAccess i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
bucket | text | ja | — |
25.18 IBMMQ-anslutning
IBMMQConnection är en kö som nås via köhanterarens meddelande-REST-API.
Definieras som IBMMQConnection i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
url | text | ja | — |
queue_manager | text | ja | — |
queue | text | ja | — |
username | text | nej | — |
password | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
api_version | text | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | 30s |
25.18.1 användarnamn
Användarnamn och lösenord är en mqweb-användare med rollen MQWebUser; lösenordet kan vara ${ENV}.
Lämna båda tomma när ett klientcertifikat (tls.cert_file) autentiserar.
25.18.2 lösenord
Användarnamn och lösenord är en mqweb-användare med rollen MQWebUser; lösenordet kan vara ${ENV}.
Lämna båda tomma när ett klientcertifikat (tls.cert_file) autentiserar.
25.18.3 tidsgräns
Timeout begränsar varje begäran.
Defaults to 30s.
25.19 Kafka SASL
KafkaSASL autentiserar till en Kafka-kluster.
Definieras som KafkaSASL i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
mechanism | text | ja | — |
username | text | ja | — |
password | text | ja | — |
25.19.1 mekanism
Mekanismen är "plain", "scram-sha-256" eller "scram-sha-512".
PLAIN skickar lösenordet läsligt på tråden, så det hör ihop med TLS. SCRAM gör det inte, vilket är varför det är värt att nämna skillnaden här snarare än att behandla de tre som utbytbara.
25.19.2 lösenord
Lösenord är SASL-lösenordet.
Stöder ${ENV}-referenser som alla andra hemligheter här, så ett klusterlegitimation behöver inte skrivas in i kanalfilen.
25.20 MQTT-anslutning
MQTTConnection är hur man når en MQTT 3.1.1-broker: Mosquitto, EMQX, HiveMQ, AWS IoT Core, Azure Event Grid.
Definieras som MQTTConnection i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
addr | text | ja | — |
client_id | text | nej | — |
username | text | nej | — |
password | text | nej | — |
tls | tlsconf.Settings (en block, utelämna för att lämna av) | nej | — |
qos | heltal (en block, utelämna för att lämna av) | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | 30s |
25.20.1 client_id
ClientID namnger sessionen.
En källa behåller sina meddelanden över omanslutningar endast under ett fast client-id; det standardiserar till perfuse-<channel>.
25.20.2 användarnamn
Användarnamn och lösenord autentiserar; antingen kan vara tomt.
Lösenordet kan vara ${ENV}.
25.20.3 lösenord
Användarnamn och lösenord autentiserar; antingen kan vara tomt.
Lösenordet kan vara ${ENV}.
25.20.4 tidsgräns
Tidsgräns för anslutning och varje väntan på brokern.
Defaults to 30s.
25.21 NCPDP-alternativ
NCPDPOptions är inställningar som endast gäller för en apoteksanspråkskanal.
Definieras som NCPDPOptions i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
transformations | lista med ncpdp.Step | nej | — |
25.21.1 transformationer
Transformationer är deklarativa ändringar som tillämpas på varje överföring innan leverans.
Samma vokabulär som alla andra format - ange, kopiera, rensa, mappa, ersätta, trimma, skift, var och en med ett valfritt villkor - eftersom stegmotorn i internal/steps är generisk. Vad som skiljer sig är notationen: en sökväg skrivs D1 eller 07-D7, med standardens egna tvåteckenfältidentifierare.
25.22 PGP Mottag
PGPMottag öppnar vad en källa tar emot med OpenPGP: dekrypterat med vår hemliga nyckel och dess signatur kontrollerad mot avsändarnas offentliga nycklar.
Definierad som PGPReceive i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
decrypt_with | text | nej | — |
passphrase | text | nej | — |
verify_with | lista med text | nej | — |
require_signature | true eller false | nej | — |
allow_unencrypted | true eller false | nej | — |
pass_plain | true eller false | nej | — |
25.22.1 decrypt_with
DecryptWith är vår hemliga nyckelfil.
Obligatorisk om allow_unencrypted inte är aktiverad och meddelanden bara är signerade.
25.22.2 passphrase
Passphrase låser upp DecryptWith när den är skyddad.
Föredra en miljövariabelreferens, ${NAME}.
25.22.3 verify_with
VerifyWith är avsändarnas offentliga nyckelfiler.
En signatur från någon av dem kontrolleras och registreras.
25.22.4 pass_plain
PassPlain låter ett meddelande som inte är PGP alls passera oförändrat, för en mapp som tar emot båda.
Av: ett sådant meddelande avvisas, så en avsändare som glömde att kryptera meddelas.
25.23 PGP Skicka
PGPSkicka skyddar vad en destination levererar med OpenPGP: krypterat till mottagarens offentliga nyckel, signerat med vår, eller båda.
Försäkringsgivare, clearinghus och statliga myndigheter tar ofta emot filer via SFTP bara på detta sätt.
Definierad som PGPSend i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
encrypt_to | lista med text | nej | — |
sign_with | text | nej | — |
passphrase | text | nej | — |
armor | true eller false | nej | — |
no_compress | true eller false | nej | — |
file_name | text | nej | — |
25.23.1 encrypt_to
EncryptTo är mottagarnas offentliga nyckelfiler (armorerade eller binära).
Meddelandet kan läsas av någon av dem. Tomt: meddelandet är endast signerat.
25.23.2 sign_with
SignWith är vår hemliga nyckelfil, för att signera varje meddelande.
Tomt: endast krypterat.
25.23.3 passphrase
Lösenfrasen låser upp SignWith när den är skyddad.
Föredra en miljövariabelreferens, ${NAME}.
25.24 Kökonfiguration
QueueConfig aktiverar beständig köning för en destination.
Utan den förlorar en destination som är nere i två minuter allt som skickats under de två minuterna: omförsök sker i minnet och när de tar slut sparas meddelandet som misslyckat och borta. Med den är meddelandet på disk och behåller sin plats tills mottagaren kommer tillbaka.
Den är inaktiverad som standard, vilket är ett medvetet val snarare än försiktighet. En kö ändrar vad en bekräftelse innebär och den ändrar ordningsbeteende under en avbrott, och båda är saker som en operatör bör välja medvetet snarare än upptäcka.
Definierad som QueueConfig i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
enabled | true eller false | nej | — |
max_attempts | heltal | nej | — |
backoff | varaktighet, t.ex. 30s eller 5m | nej | — |
max_backoff | varaktighet, t.ex. 30s eller 5m | nej | — |
max_depth | heltal | nej | — |
retain_hours | heltal | nej | — |
25.24.1 max_försök
MaxAttempts är hur många gånger kön försöker innan den markerar ett meddelande som misslyckat och går vidare till nästa.
Noll betyder att fortsätta försöka utan begränsning, vilket är legitimt för en feed som inte får förlora något men bör väljas snarare än ärvas.
25.24.2 max_backoff
MaxBackoff begränsar den ökande fördröjningen.
Standardvärdet är en minut snarare än något större eftersom en mottagare som kommer tillbaka efter en kort avbrott bör hittas snabbt: ett tak på en timme förvandlar en tvåminutersblip till en timmes backlog.
25.24.3 max_depth
MaxDepth vägrar nya meddelanden när så många väntar, så en mottagare som har varit nere i en vecka kan inte fylla disken.
Noll betyder ingen gräns.
När gränsen nås markeras meddelandet som misslyckat snarare än köat, och avsändaren meddelas - vilket är det ärliga svaret, eftersom vi inte längre lovar att leverera det.
25.24.4 retain_hours
RetainHours är hur länge levererade och övergivna objekt behålls innan de rensas.
De behålls alla så att någon som tittar på en backlog kan se att den töms, och så att ett övergivet meddelande kan hittas efteråt.
25.25 Omförsök
Omförsök kontrollerar omleverans efter ett misslyckande.
Definierad som Retry i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
attempts | heltal | nej | — |
backoff | varaktighet, t.ex. 30s eller 5m | nej | — |
max_backoff | varaktighet, t.ex. 30s eller 5m | nej | — |
25.25.1 försök
Försök är det totala antalet försök, inklusive det första.
Noll betyder standard.
25.25.2 backoff
Backoff är väntetiden före det andra försöket.
Den fördubblas varje gång, upp till MaxBackoff.
25.26 Skriptalternativ
ScriptOptions konfigurerar en NCPDP SCRIPT-kanal.
Varför SCRIPT får en blockering när dess filter är på översta nivån
Kanalens filter för varje datatyp är filtret på översta nivån, eftersom internal/expr är generiskt för meddelandetypen: en nyckel, kompilera mot vilket träd eller anspråk kanalen bär. Stegen kan inte ordnas på det sättet. Ett v2-steg adresserar ett segment och ett fält, ett X12-steg adresserar ett fast bredd-element, och typerna är olika, så en yaml-nyckel måste hålla vilken datatyp som helst - vilket är ett fält som betyder olika saker beroende på ett annat fält, och felmodusen är ett steg som tyst gör ingenting.
Så detta följer hl7v3, x12, ncpdp och avgränsad: stegen bor i formatets egen block, och den översta nivåns transformationsnyckel avvisas på en SCRIPT-kanal snarare än att accepteras och ignoreras.
Definierad som ScriptOptions i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
transformations | lista av hl7v3.Steg | nej | — |
25.26.1 transformationer
Transformationer är de deklarativa stegen, som adresserar receptet som ett XML-träd.
hl7v3.Steg snarare än en egen typ, och det är inte lathet. Ett recept och ett v3-dokument är båda XML, sökvägssyntaxen är densamma, och internal/eprescribe lånar redan hl7v3.Path för sitt filter med en kommentar som säger det - v3 och CDA använder redan det, och en tredje kopia skulle vara en tredje uppsättning svar på vad //a/b[2]@c betyder.
Stegen som bär v3-endast betydelse avvisas vid inläsning snarare än att vara tyst tillgängliga. nullflavor är den: den skriver v3-attributet som anger varför ett värde är frånvarande, vilket ett recept inte har någon motsvarighet till, och ett steg som skrev det skulle producera ett dokument som mottagaren inte förstår.
25.27 Skript
Skript innehåller det JavaScript som är kopplat till en kanal.
Definierad som Scripts i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
filter | text | nej | — |
transformer | text | nej | — |
preprocessor | text | nej | — |
deploy | text | nej | — |
undeploy | text | nej | — |
postprocessor | text | nej | — |
language | text | nej | — |
timeout | varaktighet, t.ex. 30s eller 5m | nej | — |
include | lista av text | nej | — |
file_roots | lista av text | nej | — |
allow | lista av text | nej | — |
25.27.1 filter
Filter körs efter uttrycksfiltret, om något, och måste returnera ett booleskt värde.
Ett Mirth-filter skript placeras här oförändrat.
25.27.2 transformer
Transformer körs efter de deklarativa stegen och kan modifiera meddelandet.
Ett Mirth-transformer skript placeras här oförändrat.
25.27.3 förbearbetare
Förbearbetaren körs innan meddelandet parsas, läser texten som "meddelande" och returnerar texten till parsning.
En Mirth-förbearbetare fungerar oförändrad här.
Detta är den enda platsen där ett meddelande som inte parsas kan repareras. Webbplatser använder det för en ensam karaktär från en seriegateway, en segmentavslutare som anlände som en radmatning, eller en leverantör som fyller en fält med något olagligt för dess position. Utan det avvisar Perfuse trafik som Mirth accepterar idag.
25.27.4 distribuera
Distribuera körs en gång när kanalen startar, innan den accepterar något.
Detta är där webbplatser värmer upp en sökcache eller kontrollerar att något de är beroende av är tillgängligt. Det körs innan källan binder, så ett distributionsmanuscript som misslyckas stoppar kanalen från att starta snarare än att låta den acceptera meddelanden som den inte kan hantera.
25.27.5 avdistribuera
Avdistribuera körs en gång när kanalen stoppas.
Efter att källan har slutat acceptera och efter att meddelanden som redan är på gång har avslutats, så att den ser en kanal som verkligen är inaktiv. Dess fel kan inte stoppa ett stopp: en kanal som inte kunde stängas av på grund av att ett renskript kastade skulle vara värre än en som loggade och stängde.
25.27.6 efterbearbetare
Efterbearbetaren körs efter att meddelandet har hanterats och kan inte ändra det.
Meddelandet och vad som hände med det är synliga, så att den kan meddela, räkna eller spela in. Den kan inte ändra vad som skickades: när den körs har skickandet redan skett, och ett skript som tycktes ändra ett levererat meddelande skulle ljuga om det.
25.27.7 språk
Språk är vilket skriptspråk dessa skript är skrivna i: javascript eller lua.
Varför en inställning för hela blocket snarare än en per skript
En kanals skript delar kanalkartan och anslutningskartan, och de läses tillsammans av den som underhåller dem. Ett filter i Lua bredvid en transformer i JavaScript skulle betyda två språk i en granskning, som delar tillstånd genom en karta vars värden måste betyda samma sak i båda. Webbplatser som vill ha det kan dela kanalen.
Varför standard är javascript
Varje skript som skrevs innan denna inställning existerade är JavaScript och säger ingenting om sitt språk. Att göra lua standard skulle tyst tolka om alla; att kräva fältet skulle vägra dem. Ingen av dem är acceptabel för en inställning som lagts till senare.
25.27.8 tidsgräns
Tidsgräns begränsar varje skript.
Noll betyder fem sekunder.
Det finns med avsikt inget sätt att inaktivera det. Mirth tillåter en transformer att loopa för evigt, vilket stoppar kanalen, och ett gränssnitt som stoppar att acceptera inlämningar på grund av ett skrivfel är inget som bör erbjudas som ett alternativ.
25.27.9 inkludera
Inkludera namnger filer med delad skriptkälla som görs tillgängliga för varje skript på denna kanal, i vilket språk skript.språk namnger.
Detta är Mirths kodmallar. En webbplats med fyrtio kanaler har vanligtvis en bibliotek som varje kanal anropar, och utan det skulle en migration innebära att kopiera biblioteket till fyrtio filer - fyrtio platser att fixa nästa gång det ändras.
Sökvägar är relativa till kanalens fil, så en bibliotek bredvid kanaler reser med dem. Det är en lista eftersom alternativet är en enorm fil, och bibliotek tenderar att dela upp efter ämne.
Filerna måste vara på kanalens språk. Detta var JavaScript-endast under en period, och inte på grund av vägran: en Lua-kanal läste filerna, vägrade en saknad fil och sedan installerade körningen ingen av dem, så varje anrop till biblioteket misslyckades med det första meddelandet med en nil-global - exakt felet som vägran ovan finns för att undvika. Båda språken installerar det nu, och ett bibliotek som inte parsar vägras vid lastning med filnamnet.
25.27.10 file_roots
FileRoots är katalogerna som FileUtil kan läsa och skriva.
Krävs varje gång "file" är tillåtet. Att ge filåtkomst utan att namnge kataloger betydde tidigare hela filsystemet: ett skript kunde läsa Perfuses egen databas, som innehåller lösenordshasher, LDAP-tjänstekontots lösenord och OIDC-klienthemligheten. Att skapa en kanal kräver endast redigeringsrollen, så eskaleringen slutfördes så fort en administratör startade den.
25.27.11 allow
Allow ger skripten funktioner som annars skulle ha nekats: "file", "database", "route".
Mirth ger alla dessa till varje skript; att kräva att de namnges betyder att en transformer inte tyst kan börja läsa filsystemet efter en kopia-klippa.
25.28 Skugga
Shadow kör en kandidatversion av en kanal bredvid den live och rapporterar var de skiljer sig.
Detta är svaret på den fråga som gör gränssnittsarbetet skrämmande: hur vet du att en ändring är säker? Inte genom att läsa den. En transformation är ett program som opererar på meddelanden vars variation ingen har katalogiserat, och fallet som bryter är alltid det som ingen tänkte på - patienten med två identifierare, resultatet med ett tomt enhetsfält, A08 som anländer före A01.
En kanaltest bevisar fallen som någon tänkte på. Shadow-läge bevisar fallen som faktiskt anländer, mot riktigt trafik, innan ändringen bär någon av dem.
Två egenskaper gör det säkert, och båda är strukturerade snarare än konfigurerbara:
- Shadow levererar aldrig. Dess destinationer konstrueras inte, så det finns ingen kodväg från en shadow-kanal till en mottagare, och ingen inställning kan skapa en av misstag. - Shadow påverkar aldrig den live-kanalen. Den körs efter att det live-meddelandet har levererats och bekräftats, och en shadow som panik, kastar eller hänger registreras som en shadow-fel och ingenting annat.
Definierad som Shadow i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
channel | text | ja | — |
sample | nummer | nej | 1 |
compare | lista av text | nej | — |
ignore | lista av text | nej | — |
max_differences | heltal | nej | 100 |
timeout | varaktighet, såsom 30s eller 5m | nej | 5s |
25.28.1 channel
Kanal är sökvägen till den kandidatkanal-fil som ska testas.
En separat fil snarare än en inline-block, med avsikt: kandidaten är tänkt att bli den live-kanal, så den bör vara den artefakt som granskas, committas och främjas, inte en fragment som måste extraheras.
25.28.2 sample
Sample är den bråkdel av meddelanden som ska skuggas, från 0 till 1. Standard är 1.
Värt att sänka endast på en upptagen feed, och värt att förstå innan man gör det: sampling minskar kostnad och minskar förtroende i exakt samma proportion, och meddelandet som skulle ha visat skillnaden är det ovanliga.
25.28.3 compare
Compare begränsar jämförelsen till dessa fältvägar.
Tom jämförelse jämför allt.
25.28.4 ignore
Ignorera exkluderar fältvägar från jämförelsen.
Behövs i praktiken, eftersom en kanal som stämplar en tidsstämpel eller en sekvensnummer skiljer sig på varje enskilt meddelande och skulle rapportera en skillnadsfrekvens på 100% medan den inte berättar någonting.
25.28.5 max_differences
MaxDifferences begränsar hur många skiljande meddelanden som sparas för inspektion.
Defaults to 100.
25.28.6 tidsgräns
Timeout begränsar en skuggkörning.
Defaults to 5s.
Separat från kanalens egen timeout, och kortare. En kandidat med en sprungande skript måste inte ackumulera gorutiner bakom den live-trafiken.
25.29 XDS-kod
XDS-kod är en kodad värde i destinationsinställningar: kod, kodningsschema (en OID) och visning.
Definierad som XDSCode i internal/config.
| Nyckel | Typ | Obligatorisk | Standard |
|---|---|---|---|
code | text | ja | — |
scheme | text | ja | — |
display | text | nej | — |
26 Hur varje komponent fungerar
Perfuse är byggt av små paket, var och en med ett jobb. Detta kapitel är var och ens egen redogörelse för vad den gör och varför den är byggd på det sättet, tagen från källan. Där ett beslut har en anledning som inte är uppenbar, är anledningen här snarare än i ett commit-meddelande som ingen kommer att hitta.
26.1 fhir
Paketet fhir implementerar FHIR-resurser, serialisering och validering.
Versionshantering är det första designbeslutet, eftersom "FHIR" i sig inte identifierar en trådformat. R5 är den senaste publicerade versionen och är standard här. R4 är vad den installerade basen och den amerikanska regleringen faktiskt konsumerar, så den stöds fullt ut snarare än att behandlas som legacy. R6 är i omröstning vid tidpunkten för skrivandet och är medvetet inte implementerad: att leverera en gissning på en outgiven specifikation skulle vara värre än att inte stödja den.
Resursmodellen är R5-formad. Där R4 skiljer sig, tillämpas skillnaden vid serialisering snarare än genom att behålla två parallella uppsättningar av strukturer, vilket är hur en kodbas kan få två subtilt avvikande definitioner av Patient.
Source: github.com/biodream-llc/perfuse/fhir
26.2 huvud
Kommandot xmlordergen skriver elementordningen för FHIR-XML som behövs, från en kärnpakets StructureDefinitions.
go run ./fhir/xmlordergen hl7.fhir.r4.core-4.0.1.tgz | gzip -9 -n > fhir/xmlorder_r4.txt.gz
JSON-objekt kan hålla sina medlemmar i valfri ordning; XML får inte: varje element måste komma i den ordning dess definition listar. Varje utdatarad är en sökväg och dess underordnade i den ordningen, varje underordnad med hur man hittar dess egna underordnade: "@Path" (ett element definierat inline, en ryggrad), "#Path" (samma som ett annat element), eller dess typer.
Source: github.com/biodream-llc/perfuse/fhir/xmlordergen
26.3 hl7
Paketet hl7 läser HL7-version 2-meddelanden.
Det har inga beroenden utanför standardbiblioteket, och en test säkerställer det. Det gör ingen nätverks-I/O, skriver inga filer och startar inga gorutiner, så det är säkert att använda från var som helst.
Reading a message
msg, err := hl7.Parse(raw) om err != nil { return err } mrn := msg.MustGet("PID-3.1") namn := msg.MustGet("PID-5.1") msgTyp, händelse, _ := msg.Type() // "ADT", "A01"
Sökvägar är den notation som människor redan använder när de pratar om HL7: segment, fält, sedan valfritt komponent och subkomponent, som i PID-5.1 eller OBX-5.2.3. Uppreparess är adresserade med hakparenteser, som i PID-3[2].1.
Get returnerar ett fel för en sökväg som den inte kan tolka; MustGet returnerar den tomma strängen istället. Båda är säkra på frånvarande segment och fält, eftersom en riktig feed är full av båda och en parser som panikar på saknad data är värdelös för jobbet. Frånvaro är inte ett fel — ett meddelande som enkelt inte bär PID-8 ger "" snarare än ett misslyckande.
Frånvarande och tom
HL7 skiljer på ett fält som inte skickades från ett som skickades medvetet tomt, och kliniskt kan dessa betyda olika saker - "inga allergier registrerade" är inte "inga kända allergier". Value.Exists rapporterar skillnaden där anroparna behöver den, medan String plattar båda till "" för det vanliga fallet.
Kopiering och det enda sättet att få detta fel
Parse kopierar sin indata, så det returnerade meddelandet förblir giltigt oavsett hur anroparen återanvänder sin buffert. Det kostar cirka 3% och en allokering per meddelande.
WithZeroCopy hoppar över kopieringen och behåller en referens till anroparens skiva istället. Det är snabbare, och det gör meddelandet osäkert att använda efter att skivan skrivits om igen. Att läsa in i en återanvänd buffert är det normala, effektiva sättet att läsa från ett nätverk i Go, så fällan fångar noggrann kod, och symtomet är tyst felaktiga fältvärden snarare än ett fel - en patients data under en annan patients namn. Använd det för indata som är oföränderlig eller överlever meddelandet, och inte annars.
Acknowledgements
AckFor bygger ett ACK eller NAK för ett meddelande, inklusive för ett som misslyckades med att parsas, vilket är det fall som är viktigast: en avsändare behöver ett svar även när det som skickades inte var ett meddelande. Se AckOptions.
Vad detta paket inte gör
Det skriver inte eller modifierar meddelanden. Det har ingen kännedom om meddelandestruktur utöver segment, så det kommer inte att berätta att en PV1 tillhör en viss besöksgrupp. Det validerar inte mot en versions tabeller. Dessa är medvetna utelämnanden snarare än förbiseenden: detta är en indexerare för riktigt trafik, som ofta inte är standardkonform och ändå måste dirigeras.
Source: github.com/biodream-llc/perfuse/hl7
26.4 admit
Paketet admit begränsar hur mycket arbete som är i flykt på en gång.
Motorn skapar en goroutine per destination per meddelande. Goroutines är billiga; vad de håller är inte det. Varje utgående leverans håller en socket i den avlägsna änden och en filbeskrivare här, och den håller dem för hela återförsöksbudgeten - med standardvärdena, fem försök med en tidsgräns på trettio sekunder plus femton sekunders backoff, så nästan tre minuter. Några hundra avsändare mot en mottagare som har tystnat är därför några hundra beskrivare som hålls i minuter, och processen tar slut.
Att ta slut är felet som är värt att förhindra, eftersom det inte visas där det hände. Det visas som "för många öppna filer" någonstans orelaterat: databasen kan inte öppna sin journal, gränssnittet slutar acceptera, en logg kan inte skrivas. Motorn ser trasig ut på tre ställen på en gång och orsaken är ett partnersystem som slutade svara.
Två gränser, och den andra är viktigare än den första:
En total, så processen stannar inom sin beskrivningsbudget.
En gräns per destination, så en mottagare inte kan konsumera totalen. Utan det kan en ensam hängande partner ta ner alla andra kanaler, vilket är värre än att ha ingen gräns alls: spridningsradien växer från en gränssnitt till alla.
Source: github.com/biodream-llc/perfuse/internal/admit
26.5 alerts
Paketet alerts övervakar måtten och säger när något är fel.
Poängen är att ingen ska behöva titta på instrumentpanelen. "Misslyckade transaktioner förblir köade utan att undersökas i tid" är ett dokumenterat operativt fel i denna klass av programvara, och orsaken är alltid densamma: informationen var på en skärm som ingen var framför klockan fyra på morgonen.
Tre beslut formar det.
En varning måste rensa sig själv. En notifikation som utlöses och aldrig löser sig tränar människor att ignorera notifikationer. Varje regel här utvärderas mot aktuellt tillstånd, så en mottagare som kommer tillbaka stänger varningen den öppnade.
Varningar är fördröjda av varaktighet, inte av antal. "Felhastighet över 5% just nu" utlöses på ett enda olyckligt meddelande under en tyst timme. "Över 5% i två minuter" gör det inte. Varje regel bär en varaktighet och ingenting utlöses förrän villkoret har hållit i så lång tid.
Vad som skickas innehåller ingen patientdata. En varning innehåller ett kanalnammn, ett destinationsnamn, ett nummer och en tröskel. Dessa kommer från konfiguration och från räkning. En webhook går till en chatt-rum, en chatt-rum har en scrollback, och en scrollback är inte någonstans en patientidentifierare ska hamna.
Source: github.com/biodream-llc/perfuse/internal/alerts
26.6 amqp
Paketet amqp är en AMQP 1.0-klient: en anslutning, en session, skicka- och mottagarlänkar, fastställd efter mottagaren säger så.
AMQP 1.0 är vad Azure Service Bus och Event Hubs talar, vad RabbitMQ 4 talar naturligt, och vad ActiveMQ och Artemis talar bredvid STOMP. Skrivet här av samma anledning som STOMP-klienten och AWS-undertecknaren är: en fullständig klientbibliotek skulle vara större delen av binärfilens beroendelista för fyra performativa som är viktiga.
Vad det gör: SASL PLAIN eller ANONYMOUS (Service Bus tar en delad åtkomstnyckelnamn och nyckel som PLAIN), TLS, öppna/börja/attach, kreditbaserad flöde, en överföring som delas upp i ramar när den överstiger motpartens maximala ramstorlek, och dispositioner - accepterad, släppt, avvisad. Avsändaren väntar på mottagarens disposition innan den rapporterar framgång, så "skickad" betyder att mottagaren tog emot. Tomma ramar håller anslutningen vid liv inom motpartens inaktivitetstid, som Service Bus tillämpar.
Vad det inte gör: transaktioner, flera sessioner, länktillfriskning och meddelandeanteckningar utöver att läsa dem.
Source: github.com/biodream-llc/perfuse/internal/amqp
26.7 analysera
Paketet analyze omvandlar en parsad Mirth-kanal till något en människa kan agera på: en vanlig beskrivning av vad kanalen gör och en ärlig lista över vad som inte kommer att överleva en migration.
Designregeln här är att en upptäckt måste vara tillräckligt specifik för att kunna agera på. "Denna kanal använder JavaScript" är inte en upptäckt. "Destination 1 anropar java.util.Date, som inte har någon motsvarighet utanför JVM" är.
Source: github.com/biodream-llc/perfuse/internal/analyze
26.8 api
Paketet api tillhandahåller HTTP-gränssnittet som används av webbgränssnittet.
Den viktiga designbegränsningen är att kanaler läses från och skrivs till filer på disk. API:et är en redigerare för dessa filer, inte ett annat lagringssystem som råkar exportera YAML. En kanal som skapats i webbläsaren och en som skrivits för hand är samma artefakt, vilket är vad som gör "exportera för att dela" trivialt och behåller git som historik.
Source: github.com/biodream-llc/perfuse/internal/api
26.9 as2
Paketet as2 är Applicability Statement 2 (RFC 4130): EDI över HTTP, signerad och krypterad med S/MIME, med en signerad kvittens (en MDN) som namnger en sammanfattning av vad som anlände.
Försäkringsgivare och handelspartner använder det för X12 och EDIFACT.
S/MIME är internal/cms, samma kod som Direct messaging använder. Vad som finns här är AS2:s egna: dess rubriker, meddelandeintegritetskontrollen (MIC) och kvittensen.
Source: github.com/biodream-llc/perfuse/internal/as2
26.10 attach
Paketet attach flyttar stora nyttolaster utanför ett meddelande och sätter tillbaka dem.
Ett HL7-meddelande som bär en skannad rapport eller en PDF är vanligt i dokumentflöden, och nyttolasten är rutinmässigt hundratals gånger större än meddelandet runt omkring. Att lagra det inline innebär att meddelandelagret växer i takt med dokumenten snarare än trafiken, ett meddelande som köas för fem destinationer kopieras fem gånger, och gränssnittet måste strömma megabyte för att visa någon en patientnamn.
Så nyttolasten extraheras, lagras en gång per innehåll och ersätts i meddelandet med en token. Mirth kallar dessa attachment-hanterare och det är en dokumenterad migrationsfunktion, vilket är varför tokenformatet här är utformat för att vara igenkännligt snarare än smart.
Vad detta paket inte bestämmer
Det gör ingen lagring och ingen I/O. Extrahering producerar det omstrukturerade meddelandet och nyttolasterna; en lagring någon annanstans bestämmer var dessa hamnar. Den separationen är vad som gör extraheringstestet möjligt utan en databas, och det är också vad som låter samma logik köra i WASM-lekplatsen där det inte finns någon databas alls.
Source: github.com/biodream-llc/perfuse/internal/attach
26.11 authlimit
Paketet authlimit begränsar misslyckade autentiseringsförsök efter källadress.
Det existerar eftersom två lyssnare behövde samma sak och en av dem hade ingenting. FHIR-servern fick en begränsare när den fick autentisering; konsollogin hade ingen alls, och en mätning visade tjugo lösenordsförsök per sekund mot administratörskontot utan fördröjning och utan låsning. I den takten är ett svagt lösenord borta över natten och den enda spåren är en logg full av identiska varningar.
Medvetet inte en allmän begränsare för hastighet. Den begränsar misslyckanden, inte förfrågningar: en upptagen legitim klient påverkas aldrig, och det enda som ackumuleras är att vara fel.
Source: github.com/biodream-llc/perfuse/internal/authlimit
26.12 awsmsg
Paketet awsmsg talar med Amazon SQS och SNS med standardbiblioteket och den delade Signature Version 4-signeraren.
Samma argument som s3put: AWS SDK skulle dubbla storleken på materialförteckningen för fyra API-anrop. SQS använder sitt JSON-protokoll (AWS JSON 1.0, X-Amz-Target AmazonSQS.<Action>), som AWS dokumenterar som det aktuella; SNS använder sitt frågeprotokoll, som är det enda den har. Båda fungerar mot LocalStack och VPC-slutpunkter via en slutpunktsåsidosättning.
Source: github.com/biodream-llc/perfuse/internal/awsmsg
26.13 awsv4
Paketet awsv4 signerar förfrågningar till AWS med Signature Version 4, med endast standardbiblioteket.
Det började inuti s3put. SQS, SNS och läsning från S3 behöver samma signatur med ett annat tjänstnamn och med en frågesträng, och en andra kopia av signeringkoden skulle vara en andra plats för den ena buggen som spelar roll - en signaturfel läser exakt som felaktiga autentiseringsuppgifter. Så det bor här, kontrollerat mot AWS publicerade testvektorer, och varje AWS-anslutning använder det.
Autentiseringsuppgifter är statiska nycklar eller standardmiljövariabler. Det finns medvetet ingen instans-metadata-credentialekedja: det innebär IMDS-samtal, cachelagring och uppdatering, vilket är där en liten implementation slutar vara liten, och Perfuse vägrar metadata-adresser som destinationsadresser som standard.
Source: github.com/biodream-llc/perfuse/internal/awsv4
26.14 azblob
Paketet azblob läser och skriver Azure Blob Storage med standardbiblioteket: Delad nyckel eller SAS-auktorisering via vanliga HTTP-samtal.
Samma resonemang som s3put: Azure SDK är stor och de operationer en integrationsmotor behöver är fem - lägga till, hämta, lista, ta bort och ange åtkomstnivå. Delad nyckel-signering är specificerad exakt ("Auktorisera med Delad nyckel", Azure Storage REST), och Azurite, Microsofts emulator, kontrollerar det på samma sätt som tjänsten gör.
Source: github.com/biodream-llc/perfuse/internal/azblob
26.15 varumärkesidentitet
Paketet varumärkesidentitet lagrar en kunds logotyp och produktnamn så att en installation kan presentera sig som deras eget produkt i stället för som Perfuse.
Varför logotypen inte är en inställning
Allt annat som en operatör kan ändra är en skalär i inställningsfilen. En logotyp är några hundra kilobyte binär data, och att lägga till den där skulle innebära base64 i en YAML-fil som en person förväntas kunna läsa och redigera manuellt. Den finns bredvid den filen i stället, och endast dess närvaro är synlig genom inställningsgränssnittet.
Den del som är viktig: en uppladdad bild är obehörig indata
En logotyp laddas upp av en administratör och sedan visas den för varje webbläsare som laddar konsolen, inklusive på inloggningssidan innan någon har autentiserat. Det gör den till den mest spridda delen av angripar- tillhandahållen innehåll i produkten, så den behandlas därefter:
- Den deklarerade innehållstypen ignoreras. Byte läses och resultatet måste finnas i en tillåtelselista. En fil som heter logo.png som innehåller HTML är HTML. - SVG accepteras, eftersom det är vad företag faktiskt har, men det är ett exekverbart dokumentformat: det kan bära skriptelement, händelsehanterareattribut, externa referenser och inbäddade främmande objekt. Det skrivs om för att ta bort alla dessa innan det sparas, och om skrivningen verifieras genom att plantera varje attack i en test. - Den visas med en innehållssäkerhetspolicy som tillåter ingenting, med sniffning inaktiverad och som en bifogad inline-bild endast. Även en sanitiseringsbug bör inte bli skriptkörning på konsolens egen ursprung. - Den uppladdade filnamnet används aldrig för att bygga en sökväg. Det sparade namnet är härlett från den sniffade typen, så ett namn som ../../etc/perfuse inte kan fly anywhere.
Source: github.com/biodream-llc/perfuse/internal/branding
26.16 cda
Paketet cda läser kliniska dokument.
Designen börjar med hur dessa dokument faktiskt reser, vilket inte är som filer. En utskrivnings sammanfattning lämnar en EHR inuti ett HL7 v2 MDM^T02-meddelande, med hela dokumentet base64-kodat i OBX-5 och beskrivet av en TXA-segment. Det är tusentals meddelanden per dag på ett medelstort sjukhus, och det är varför detta paket sitter bredvid en HL7 v2-parser snarare än i en dokumentverktygslåda: v2-delen är redan här, så pipeline från "ett meddelande anlände" till "en FHIR DocumentReference finns" är kort.
Tre saker är medvetet inom ramen och en är medvetet inte.
Inom ramen: läsa ett dokument och säga vad det innehåller på vanligt språk; kontrollera att den mänskligt läsbara berättelsen och de kodade posterna stämmer överens; och konvertera till FHIR. Berättelsekontrollen är den ovanliga. Varje C-CDA-sektion bär samma information två gånger, en gång som text för en kliniker och en gång som koder för en maskin, och de ska matcha. I praktiken matchar de ofta inte, och ingenting kontrollerar det - inte certifieringsverktygen, inte motorerna. När texten säger att en patient är allergisk mot penicillin och den kodade posten säger något annat, agerar en av de två läsarna på fel information. Det är en patientsäkerhetsdefekt som är mekaniskt upptäckbar, så den upptäcks här.
Inom ramen: generera konform C-CDA. Att skriva en innebär att tillfredsställa flera hundra mallregler och en Schematron, och producera dokument som är 95% rätt skulle misslyckas med certifiering på sätt som är eländiga att felsöka. Läsa, kontrollera och konvertera är mest av värdet för en bråkdel av risken.
Source: github.com/biodream-llc/perfuse/internal/cda
26.17 channeltest
Paketet channeltest kör tester mot en kanaldefinition.
En kanal är ett program. Den filtrerar, skriver om och dirigerar kliniska meddelanden, och den redigeras under tryck av personer som inte kan prova den mot produktion. Avsaknaden av ett sätt att testa en är den enskilt största anledningen till att gränssnittsarbetet är skrämmande, och "Jag ändrade transformatorn och ingenting såg annorlunda ut i meddelandebrowsern" är inte ett test.
Den centrala beslutet är att ett test kör meddelandet genom den riktiga transformationsbanan — samma filter, samma deklarativa steg, samma skriptmotor, i samma ordning — med endast transporten ersatt. Ett test som övade en omimplementering skulle passera medan kanalen misslyckades, vilket är värre än att ha inget test alls eftersom det aktivt vilseleder.
Source: github.com/biodream-llc/perfuse/internal/channeltest
26.18 chanscope
Paketet chanscope begränsar läsningar och skrivningar på en kontext till vissa kanaler.
Det beror på sammanhanget snarare än att det är en parameter för varje fråga eftersom det finns dussintals frågor över hela meddelandebutiken och leveransköerna, och gränsen är en egenskap hos den som frågar, inte frågan. API:et ställer in det en gång per begäran för en person som begränsas till vissa kanalsgrupper; varje räkning, lista, diagram, sökning och köåtgärd är sedan överens med de andra, så att ingen berättas att det totalt sett är fyrtio fel och visas fyra.
Source: github.com/biodream-llc/perfuse/internal/chanscope
26.19 kluster
Paketkluster låter flera Perfuse-servrar dela en PostgreSQL-lagring och bestämma, mellan dem, vilken som kör vad.
Problemet det löser
En server är en felkälla: när den slutar fungera, slutar varje gränssnitt att fungera. Två servrar på en databas löser det bara om de aldrig båda kör samma kanal, eftersom två MLLP-lyssnare på en feed turas om med avsändaren, två köarbetare levererar samma meddelande två gånger, och två DICOM-pollers rapporterar var och en samma studie.
How
En hyra är en rad som namnger vem som innehar något, med en räknare som innehavaren flyttar på vid varje förnyelse, var få sekunder. Ingen klocka jämförs med en annan: en innehavare som inte kan förnya (kraschar, kopplas bort från databasen) slutar vad hyran täcker när dess egen klocka säger att hyran nästan är klar, och en annan server tar över den bara efter att dess egen klocka har sett räknaren stå stilla under hela hyran. Var och en mäter ett intervall på sin egen klocka, så servrarnas klockor och databasens klocka behöver inte överensstämma; de behöver bara gå i ungefär samma takt. En klocka som hoppar (en virtuell maskin som synkroniserar, en administratör som ställer in tiden) förändrar ingenting: den första versionen använde databasens klocka för utgång, och ett test hittade en databas vars klocka hoppade tretton sekunder och gav varje hyra till en ny server medan de gamla fortfarande körde dem.
Mellan den som slutar och den som börjar finns ett kort gap med ingen som kör, vilket kostar en avsändare några sekunder av vägrade anslutningar, och aldrig ett ögonblick med två.
Two modes:
- aktiv-passiv: en hyra, "ledare". Dess innehavare kör varje kanal och varje jobb som måste köras en gång (prenumerationsmeddelanden, larm). De andra väntar, och den första som ser den upphöra tar över. - aktiv-aktiv: ledaren kör fortfarande jobben, och varje kanal har en hyra av sin egen, spridd jämnt över de aktiva servrarna. En server som lämnar ger sina kanaler till de andra; en som ansluter tar sin andel när de blir lediga.
Varje hyra har en epok, räknad upp varje gång dess innehavare ändras, som namnger ett innehav i historien.
Source: github.com/biodream-llc/perfuse/internal/cluster
26.20 cms
Paketet cms är den kryptografiska meddelandestrukturen (RFC 5652) som S/MIME och Direct-säker meddelandehantering använder: SignedData (signera ett meddelande, verifiera ett och säga vem som signerade det) och EnvelopedData (kryptera ett meddelande till mottagarnas certifikat, dekryptera ett med vår nyckel).
Bara det som Direct Applicability Statement och dess implementeringsguide kräver: RSA med SHA-256 (SHA-1 accepteras för läsning, eftersom äldre HISPar fortfarande skickar det), RSA-nyckeltransport med PKCS#1 v1.5 eller OAEP, och AES-128 eller AES-256 i CBC-läge. Krypteringen är standardbibliotekets; detta paket är ASN.1 runt den.
Source: github.com/biodream-llc/perfuse/internal/cms
26.21 cms0057
Paketet cms0057 innehåller betalarens delar av CMS Interoperability och Prior Authorization slutregel (CMS-0057-F) som handlar om data snarare än transport: avgjorda anspråk som CARIN Blue Button ExplanationOfBenefit-resurser, förhandsgodkännanden som Da Vinci PDex ExplanationOfBenefit-resurser, HRex-medlemmatchning för Payer-to-Payer-API, medlemslistan bakom Provider Access API och förhandsgodkännandemått som en betalare måste publicera varje år.
FHIR-slutpunkterna som betjänar dessa finns i fhirserver; detta paket bestämmer vad som ska finnas i dem.
Läkemedel är utanför omfånget överallt, eftersom de också är det i förhandsgodkännandebestämmelserna i regeln: ingen apoteks ExplanationOfBenefit, ingen formulary, ingen NCPDP.
Source: github.com/biodream-llc/perfuse/internal/cms0057
26.22 koduppsättning
Paketet koduppsättning innehåller mappningstabeller som överlever den kanal som först behövde en.
Domänskatten består till stor del i att återvinna en mappning som någon redan har härlett. En webbplats sexkoder, patientklasser, beställningsstatus och facilitetsidentifierare översätts på samma sätt i varje kanal som berör dem, och idag är var och en av dessa översättningar en separat tabell inuti en separat kanal. Fyrtio kanaler innebär fyrtio kopior och fyrtio platser att fixa nästa gång mottagarsystemet ändras.
Så en tabell blir ett namngivet objekt som refereras till med namn. Det är uppenbart och det är den mindre halvan av värdet.
Den halva som ingen bygger
Den större halvan är bevis. Det mesta som gör en gränssnitt svårt att underhålla är inte mappningen - det är att ingen vet *varför*. "Vi tar bort ledande nollor eftersom labbets MRN-kolumn är numerisk" är kunskap som finns i en persons huvud och lämnar byggnaden när de går i pension, och den mappning som återstår blir något som ingen vågar ändra och ingen vågar ta bort.
Så varje tabell registrerar vem som beslutade och när, varje post kan registrera sin egen anledning, och båda överlever till filen som går in i versionskontroll. En mappning med en anledning kan diskuteras. En mappning utan en blir vidskepelse.
Varför filen är separat från kanalen
Det beror på att den delas. En tabell inom en kanal är en tabell som endast den kanalen kan använda, vilket är problemet. Och en delad tabell behöver sin egen historia: "vem ändrade könsmappningen och när" är en fråga om tabellen, inte om vilken kanal som råkade redigeras den dagen.
Source: github.com/biodream-llc/perfuse/internal/codeset
26.23 efterlevnad
Paketet efterlevnad implementerar CMS ADT-händelseanmälningsarbetsflödet som krävs enligt 42 CFR 482.24(d) sedan maj 2021.
Sjukhus måste elektroniskt meddela en patients etablerade vårdgivare — primärvård, specialister, eftervårdskliniker — när patienten tas in, skrivs ut eller överförs. Regeln finns eftersom patienter faller mellan stolarna under övergångar: en allmänläkare som inte vet om en utskrivning kan inte schemalägga uppföljningen som förhindrar en återinläggning.
Detta paket tillhandahåller maskineriet för att: - Spåra vilka vårdgivare som är etablerade för varje patient. - Dirigera ADT-händelser till rätt vårdgivare med rätt prioritet. - Registrera varje skickad anmälan med leveransstatus för CMS-revisorer. - Generera efterlevnadsrapporter som visar anmälningsfrekvenser och fel.
Trådsäkerhet krävs överallt eftersom ADT-meddelanden anländer samtidigt från flera kanaler och anmälningspipelinen körs parallellt.
Source: github.com/biodream-llc/perfuse/internal/compliance
26.24 konfiguration
Paketet config läser in kanalddefinitioner från filer.
Konfigurationen finns i filer snarare än i en databas, vilket är den viktigaste skillnaden mellan Perfuse och Mirth. Mirth lagrar kanaler i sin egen databas, vilket är varför versionskontroll är ett separat produkt, varför det är svårt att främja en kanal från test till produktion och varför ingen kan svara på "vad ändrades förra tisdagen" utan ett supportanrop. Filer ger git, diff, granskning, CI och miljöfrämjande med ingen extra maskin.
Validering är medvetet strikt och sker vid inläsning: okända fält är ett fel, filteruttryck kompileras, adresser kontrolleras. En kanal som inte kan förstås måste vägra starta snarare än köra på ett sätt som ingen avsåg.
Source: github.com/biodream-llc/perfuse/internal/config
26.25 kontrakt
Paketet kontrakt omvandlar vad en feed ser ut som till vad en feed måste se ut som.
En profil svarar på "vad tar jag emot". Det är användbart en gång. Det dyra problemet är den dagen det ändras: en leverantörsuppgradering släpper ett fält, en ny kod dyker upp, en segment börjar upprepas. Ingen av dem är ett fel - meddelandena är fortfarande giltiga HL7 och varje motor i världen accepterar dem - så ingenting märker förrän en mottagare faller, vanligtvis veckor senare, och utredningen börjar från fel ände.
Ett kontrakt är profilen skriven ner som en förväntan och sedan kontrollerad. Det är kontraktstestning, som är en löst idé i programvara i allmänhet och nästan helt frånvarande i hälsointegrering.
Varför enheten är en frekvens och inte ett meddelande
Den uppenbara designen är att kontrollera varje meddelande och klaga när ett misslyckas. Det producerar ett system som ingen kan använda. Riktiga feeds innehåller en proportion av genuint konstiga meddelanden - ett testmeddelande från leverantören, en patient utan registrerat kön, en manuell inmatning - och varning på var och en tränar människor att ignorera varningarna, vid vilken punkt funktionen är sämre än ingenting eftersom den har konsumerat uppmärksamheten den behövde.
Så en förväntan handlar om en proportion under ett fönster: "PID-3 är ifyllt i minst 99% av meddelandena". Ett konstigt meddelande utlöser aldrig. Fem procent av meddelandena som förlorar sitt medicinska journalnummer gör.
Ett kontrakt beskriver vad som anländer, inte vad som lämnar
Detta är den distinktion som människor får fel först, inklusive mig medan jag testade integrationen. Perfuse lagrar meddelandet som det anlände - det är medvetet, eftersom det lagrade meddelandet är bevis för vad en avsändare skickade - så ett kontrakt kontrolleras mot den inkommande feeden och inte mot utmatningen av kanaltansformationerna.
Det är rätt standard med stor marginal: det som ändras utan varning är avsändarsystemet, och syftet med ett kontrakt är att märka. Men det betyder att en förväntan skriven om ett mappat värde ("efter mappning, ska endast labbkoderna kvarstå") kommer att misslyckas omedelbart och förvirrande, eftersom koderna den namnger aldrig visas i den profilerade trafiken. Allt om vad som lämnar hör hemma i en kanaltest, som kör de riktiga transformationerna.
Varför en överträdelse namnger toleransen den bröt
"PID-3 misslyckades" berättar ingenting för någon. "PID-3 var ifyllt i 94,2% av de senaste 500 meddelandena; kontraktet kräver 99%" berättar för dem hur illa det är, hur säker de kan vara och om det är värt att väcka någon. Siffrorna är meddelandet.
Source: github.com/biodream-llc/perfuse/internal/contract
26.26 crd
Paketet crd är en Da Vinci Coverage Requirements Discovery-tjänst (CRD 2.2.1): betalarens sida av CDS Hooks-samtalet som berättar för en kliniker, medan ordern fortfarande är en utkast, om den är täckt, om den behöver föregående auktorisation och vilken dokumentation betalaren kommer att vilja ha.
CMS-0057:s Prior Authorization API är i praktiken tre Da Vinci-guider tillsammans: CRD för att säga vad som krävs, DTR för att samla in det, PAS för att skicka in det. Perfuse hade PAS. Detta är den första av de andra två; DTR:s $questionnaire-package är på FHIR-slutpunkten.
Täckningsbesluten kommer från en regelfil, eftersom de är utbetalarens policy och ändras utan programvarureleaser: en kod (eller en lista med koder) och vad som gäller för den - täckt eller inte, om föregående godkännande behövs eller inte, dokumentation och DTR-frågeformuläret som samlar in den. En order som inte matchar någon regel besvaras "villkorlig" och "obestämd", vilket är vad CRD säger att man ska returnera när tjänsten inte kan fatta ett beslut - aldrig en gissning att den är täckt.
Svar följer guiden: en systemåtgärd som uppdaterar varje order med täckningsinformationstillägget, som EHR lagrar på ordern och senare skickar med i förväg godkännandet; och ett kort per order, så att en kliniker ser det.
Source: github.com/biodream-llc/perfuse/internal/crd
26.27 instrumentpaneler
Paket instrumentpaneler definierar instrumentpanelerna som Perfuse levererar för varje typ av person som tittar på dem, och hur en person tilldelas en: genom deras roll, genom en kataloggrupp som instrumentpanelsfilen mappar, eller genom den vy som de sparade.
Instrumentpaneler består av kakor, och kakor visar endast aggregerad information - antal, hastigheter, tider, tillstånd. Ingen visar ett meddelande, en patient eller en identifierare, så en instrumentpanel kan tilldelas en avdelningschef eller placeras på en väggskärm utan att utöka vem som ser patientdata. En kaka som behöver data som Perfuse ännu inte har registrerat är inte fejkad: instrumentpanelen listar den under Planerad.
Full flexibilitet är Grafanas uppgift, inte detta pakets. Varje kaka som har en mätning bakom den exporteras som en Grafa-panel via Perfuses /mätvärden, så en webbplats som vill ha mer än lätt konfiguration tar instrumentpanelen där.
Source: github.com/biodream-llc/perfuse/internal/dashboards
26.28 davinci
Paket davinci anger vilken version av Da Vincis prioriseringsguider (CRD, DTR, PAS) en klient talar.
Perfuse svarar i två versioner: 2.2 (CRD 2.2.1, DTR 2.2.0, PAS 2.2.1), den senaste, och 2.1 (CRD, DTR och PAS 2.1.0), den version som CMS-0057-F:s rekommenderade lista pekar på en gång 2.0.1-releasernas US Core 3.1.1-bas har upphört att gälla. De två skiljer sig i former som en klient läser med namn - DTR:s $questionnaire-package-parametrar (PackageBundle i 2.1, packagebundle i 2.2), PAS:s $inquire-svar (en Bundle i 2.1, en Parameters av dem i 2.2), tillägg som bara finns i en av dem - så ett svar inte kan tjäna båda, och servern måste veta vilken den pratar med.
Det anges, mest specifikt först: av själva begäran (CRD:s davinci-crd.requestedVersion; versionen på en profil som indata påstår, profil|2.1.0), sedan av klientens registrering (davinci_version på en SMART- eller CDS-klient), sedan av serverns egen inställning (serve -davinci-version), som standard är den senaste.
Source: github.com/biodream-llc/perfuse/internal/davinci
26.29 dbtid
Paket dbtid formaterar tidsstämplar så att sortering av dem som text sorteras som tid.
Varje butik i Perfuse lagrar tidsstämplar som TEXT i SQLite och förlitar sig på strängjämförelse för sortering och för intervallfrågor: SORTERA EFTER mottagen_at DESC, VAR utgår_at < ?, VAR vid >= ?. Det är en rimlig design - den håller en databas som någon kan läsa med sqlite3-skalet - men den fungerar bara om textformen är fast bredd.
time.RFC3339Nano är inte det. Dess dokumentation säger att den tar bort efterföljande nollor från sekundfältet, så samma klocka producerar strängar av olika längd:
20:56:33.12345Z <- 123450 mikrosekunder, efterföljande nolla borttagen 20:56:33.123456Z <- 123456 mikrosekunder
Jämfört som text är den första *större*, eftersom efter det delade prefixet "12345" den har 'Z' där den andra har '6', och 'Z' sorteras ovanför varje siffra. Så den tidigare ögonblicket sorteras senare. Ungefär en angränsande par på tio påverkas, vilket är varför det presenterades som ett intermittent testfel snarare än som ett uppenbart trasigt funktion.
Vad det faktiskt bröt: revisionsloggen och meddelandebrowsern sorterar båda efter en tidsstämpel och kan därför lista poster från samma sekund i fel ordning. En revisionslogg är ett efterlevnadsartefakt och en meddelandebrowser är hur någon rekonstruerar vad som hände, så i båda fallen är ordningen poängen.
Layouten nedan använder .000000000 istället för .999999999. Båda skriver ut nanosekunder; skillnaden är att nollor är signifikanta i den första och borttagna i den andra.
Source: github.com/biodream-llc/perfuse/internal/dbtime
26.30 avgränsad
Paket begränsad tolkar poster som separeras och delas av konfigurerade tecken.
Detta är Mirths begränsade datatyp: CSV, tabb-separerad, pipe-separerad, fast kolumnfil och den långa svansen av format som ett laboratorieanalyser eller en byråtjänst emitterar eftersom någon skrev det 1994 och det fungerar.
Medvetet inte en allmän CSV-bibliotek. Vad som är viktigt här är vad en hälsoflöde gör som en välformad CSV inte gör: en rubrikrad som kan finnas eller inte, en efterföljande tom rad som inte får bli en tom post, kolumner som refereras till med namn så att en transformation inte bryts när en leverantör infogar en, och möjligheten att behandla en hel fil som ett meddelande eller varje rad som sin egen.
Den sista av dessa är beslutet som formar allt annat. En fil med fem tusen resultat är antingen ett meddelande eller fem tusen, och de två är inte utbytbara: ett meddelande innebär ett erkännande och ett fel för hela filen, och fem tusen innebär att varje rad kan filtreras, omvandlas och försökas på nytt på egen hand.
Source: github.com/biodream-llc/perfuse/internal/delimited
26.31 dicom
Paket dicom läser DICOM-datauppsättningar.
DICOM är där radiologin bor, och en sjukhusintegreringsmotor som inte kan tala det är stängd från avbildning helt. Mirth har en DICOM-lyssnare och avsändare, så detta är en migrationsblockerare för alla webbplatser som utför modalitetsarbete.
Omfattning, uttryckt tydligt
Detta paket tolkar datauppsättningar: filmetainformationen, elementen, överföringssyntaxen och värdena som är viktiga för routning och identifiering. Det dekoderar inte pixeldata, och det kommer aldrig att göra det så långt detta paket är bekymrat - en integreringsmotor flyttar bilder, den visar dem inte, och en dekoder är ett stort format-specifikt arbete vars enda syfte här skulle vara att göra binärfilen större.
Att läsa metadata utan att röra pixlarna är också vad som gör det snabbt på den trafik som är viktig: en bröst-CT är hundratals megabyte pixlar bakom två kilobyte information som någon router på.
Varför värdepresentationerna hanteras explicit
Ett DICOM-element innehåller ett tvåbokstävigt värde som anger hur dess värde ska läsas, och reglerna skiljer sig åt per VR på sätt som inte kan gissas: vissa har en tvåbyte lång längd och vissa fyra, vissa är utfyllda med ett mellanslag och vissa med en null, och numeriska strängar kan innehålla flera värden separerade med bakslash. Att få ett fel leder inte till ett fel, utan till ett trovärdigt felaktigt värde - ett patientnamn som läses från mitten av ett datum, eller en studieidentifierare som är felaktig med en byte.
Source: github.com/biodream-llc/perfuse/internal/dicom
26.32 dicomweb
Paketet dicomweb talar DICOMweb (DICOM PS3.18): QIDO-RS för att söka, WADO-RS och WADO-URI för att hämta, STOW-RS för att lagra, över HTTP.
Det är hur visningsprogram, AI-tjänster och molnarkiv når bildmaterial nu: OHIF, Google Cloud Healthcare, Azure Health Data Services, AWS HealthImaging, Orthancs och dcm4chees DICOMweb-gränssnitt. En integrationsmotor som endast talar nätverksprotokollet från 1993 (DIMSE: C-STORE, C-FIND) kan mata en PACS men inte en webbläsare.
Paketet har fyra delar: en datamängdsläsare som går igenom hela objektet, inklusive sekvenser, och vet var pixeldata är utan att ladda den; DICOM JSON-modellen (PS3.18 F.2); multipart/related, som är hur DICOMweb flyttar flera objekt i en begäran; och ett arkiv med en index, som är vad QIDO och WADO svarar från.
Source: github.com/biodream-llc/perfuse/internal/dicomweb
26.33 direct
Paketet direct är Direct-säker meddelandehantering som en edge-system: ett meddelande till en Direct-adress signeras med denna adressens certifikat och krypteras till mottagarens, som S/MIME, och skickas till en HISP via SMTP; ett meddelande som tas emot från HISP (via SMTP eller samlas in via IMAP) dekrypteras och dess signatur kontrolleras mot förtroendesankringar innan något läser det.
Det följer Direct Project Applicability Statement för Secure Health Transport 1.2 och XDM-specifikationen (IHE ITI TF-1 Annex 15) för dokument med metadata. Det är inte en HISP: HISP:s ackreditering, dess certifikatpolicy och dess katalog stannar med HISP.
Source: github.com/biodream-llc/perfuse/internal/direct
26.34 drug
Paketet drug hanterar koderna och mängderna som identifierar ett läkemedel.
Delat ut från apoteksstandarder som bär dem, eftersom samma läkemedelskod visas i en NCPDP-anspråk, en SCRIPT-recept, en HL7 RXE-segment och en FHIR MedicationRequest, och en omvandling som bor i en av dessa platser är en omvandling som de andra tre saknar.
Source: github.com/biodream-llc/perfuse/internal/drug
26.35 dsdr
Paketet dsdr signeras och verifierar CDA-dokument enligt HL7 Implementation Guide för CDA Release 2: Digital Signatures och Delegation of Rights, Release 1 (oktober 2014) - den elektroniska signaturstandarden som HIPAA antar för anspråksbilagor i CMS-0053-F, 45 CFR 162.2002(e), med efterlevnad från den 26 maj 2028.
Vad guiden ber om, och var det görs här:
- Sammanfattningen är över hela dokumentet, med undantag för varje legalAuthenticator och authenticator-element (avsnitt 3.1.2), så att senare signaturer inte bryter tidigare signaturer. Uttryckt i signatur som en XPath Filter 2.0 subtraheringsomvandling, som varje XML-DSig-implementering kan utvärdera. - Signatur är XAdES-X-L (3.1.1, ESMD-1 till ESMD-6): signaturcertifikat, UTC-signeringstid, en roll från NUCC-leverantörstaxonomi, en signaturändamål från ASTM E1762, certifikatvägen i CertificateValues och en OCSP- eller CRL-svar i RevocationValues, med tidsstämplar X-L byggs på. - Det bärs base64 i sdtc:signatureText på den som signerade, med en vanlig textminiatyrbild (3.3, ESMD-7 till ESMD-16), inuti digitalSignature/authorizedSigner.
Där guiden är tyst, är valen gjorda uppkallade: den anger inte ett namnområde för sina egna element (digitalSignature, authorizedSigner, SignaturePurpose), så de placeras i urn:hl7-org:sdtc; och ändamålet anges också som en XAdES CommitmentTypeIndication med ASTM OID, som XAdES-verktyg läser och guidens eget element som de inte gör.
Delegering av rättigheter (en delegerad signatur med en SAML-påstående) produceras inte; en signatur som bär en rapporteras som sådan.
Source: github.com/biodream-llc/perfuse/internal/dsdr
26.36 e4x
Paketet e4x gör Mirth Connects JavaScript körs oförändrad.
Mirth-skript skrivs för Rhino, som implementerar E4X: XML är en inbyggd typ med sin egen syntax. Motorn här är goja, som inte gör det, och gapet är inte bara ett körningsgap.
tre delar av E4X är *syntax*, så gojas parser avvisar filen direkt innan någon objektmål kunde hjälpa: for each (var seg i msg..OBX) { } // for-each, och ättlingoperatorn var z = <ZZZ><ZZZ.1>value</ZZZ.1></ZZZ>; // en XML-literal var id = node.@root; // en attributreferens
Denna fil omformar dessa till vanlig ECMAScript som goja parsar, och lämnar semantiken till körningens objektmål i xml.go. Allt annat om E4X - egenskapstillgång genom elementnamn, indexering av repetitioner, tilldelning, toString - är redan giltig JavaScript-syntax och behöver ingen omformning.
Omformningen görs med en riktig lexer snarare än reguljära uttryck, eftersom alternativet korrumperar fungerande skript. Ett mönster för ättlingoperatorn hittar en inuti "http://example.org", ett mönster för XML-literaler hittar en i "a < b && c > d", och ett skript som tyst ändrar betydelse är mycket värre än ett som vägrar att ladda.
Source: github.com/biodream-llc/perfuse/internal/e4x
26.37 edifact
Paketet edifact läser och skriver UN/EDIFACT-utbyten (ISO 9735): UNA-tjänstesträngsråd, UNB/UNZ-utbyteskuvert, valfria UNG/UNE-funktionella grupper och UNH/UNT-meddelanden, med utgåvatecknet och, för syntaxversion 4, upprepningsskiljetecknet.
Det kontrollerar kuvertets räkningar och referenser, adresserar dataelement för filter, delar upp en utbyte i ett per meddelande och skapar en CONTRL-bekräftelse.
Det läser alla meddelandetyper (ORDERS, INVOIC, IFTSTA, MEDRPT ...); det har inte katalogerna som anger vilka segment en meddelandetyp kan innehålla, så det kontrollerar struktur, inte innehåll.
Source: github.com/biodream-llc/perfuse/internal/edifact
26.38 utgång
Paketet utgång bestämmer om den här motorn får ansluta utåt till en adress.
Det finns eftersom en destination kan pekas var som helst, och en kombination gör det till ett sätt att läsa det interna nätverket: en SOAP-destination med en svarstransformator returnerar mottagarens svar till ett skript, så en redigerare kan skapa en kanal som hämtar en intern URL och skriver brödtexten till en logg eller ett meddelande.
Demonstrerat snarare än teoretiserat: en SOAP-destination riktad mot en lokal HTTP-server satte serverns svarsbrödtext i en kanallogg-rad.
Det proportionerliga svaret är inte att förbjuda utgående anslutningar - leverans av meddelanden till konfigurerade slutpunkter är hela syftet med programvaran, och en redigerare är tänkt att konfigurera dem. Det är att vägra de specifika adresserna som aldrig är en meddelandedestination och alltid är en credentialbutik.
Source: github.com/biodream-llc/perfuse/internal/egress
26.39 motor
Paketet motor kör konfigurerade kanaler.
En kanal är en källa, ett filter och en uppsättning destinationer. Körningens jobb är att vara ärlig om vad som hände med varje meddelande: en bekräftelse bör betyda vad konfigurationen säger att den betyder, ett meddelande som filtreras bort bör kunna särskiljas från ett som levererades, och ett meddelande som inte kunde levereras någonstans får inte rapporteras som godkänt.
Source: github.com/biodream-llc/perfuse/internal/engine
26.40 epa
Paketet epa är NCPDP SCRIPT elektronisk förhandsauktorisation, betalarens sida: PAInitiationRequest, PARequest, PAAppealRequest och PACancelRequest in, och deras svar ut.
CMS-0062-P föreslår att påverkade betalare stöder det från och med den 1 oktober 2027, och Medicare Part D kräver redan det. En begäran beslutas på samma sätt som varje förhandsauktorisation på den här servern: den blir en Da Vinci PAS-begäran (ett anspråk, MedicationRequest och prescriberns svar som en QuestionnaireResponse) och går till samma regelfil, beslutstjänst och granskningskö.
NCPDP:s scheman är licensierade. Elementnamn och ordning här följer den offentliga Surescripts ePA-kompletteringsguiden och dess exempel; två element som det offentliga materialet aldrig visar (anledningen inuti Closed och inuti Denied) följer SCRIPT-mönstret som används på andra ställen och är uppkallade i handboken så att en betalare kan kontrollera dem mot sin egen kopia av schemat.
Source: github.com/biodream-llc/perfuse/internal/epa
26.41 eprescribe
Paketet eprescribe läser och skriver NCPDP SCRIPT, den standard som recept reser i.
Namngiven efter vad den gör snarare än efter standarden, eftersom internal/script redan är JavaScript-motorn och två paket som heter script i ett träd är ett misstag som väntar på att ske på en import-rad.
SCRIPT är XML, till skillnad från telekommunikationsstandarden som bär det resulterande anspråket. En prescriber skickar en NEWRX till en apotek; apoteket skickar tillbaka RXFILL för att säga vad som hände, REFREQ för att begära en påfyllning, eller RXCHG för att begära en ändring. Var och en av dem är ett meddelande här.
Där faran är
Två fält i ett recept är farliga när de missläses snarare än när de saknas.
Ersättningar är det första. En nolla betyder att ersättning är tillåten och en etta betyder att den ska skrivas ut som den är. Det läses baklänges för någon som förväntar sig en flagga där en betyder ja, och att få det fel resulterar i att en generisk utskrivs där prescribern krävde varumärket - eller vägrar en ersättning som var tillåten, vilket är samma fel som kostar patienten pengar istället.
Påfyllningsräkning är det andra. Ett recept för schema II får inte fyllas på alls, och ett system som bär en påfyllningsräkning över från en icke-kontrollerad mall producerar ett giltigt utseende recept som ett apotek måste vägra.
Vad som inte har verifierats
Meddelandestrukturen följer de publicerade SCRIPT-elementnamnen. Inget meddelande från det här paketet har skickats genom ett riktigt routningsnätverk som Surescripts, och certifiering av en är en kommersiell process snarare än en teknisk.
Source: github.com/biodream-llc/perfuse/internal/eprescribe
26.42 ekvivalens
Paketet equiv bevisar att två motorer är överens, eller säger exakt var de inte är.
Detta är svaret på den enda frågan som faktiskt blockerar en migration. Ett gränssnittsteam vägrar inte en ny motor för att den saknar funktioner; de vägrar för att de inte kan vara säkra på att den kommer att göra samma sak med den trafik de redan har, och att vara fel innebär att laboratorieresultat inte når läkare. Inga funktioner jämförelse svarar på det. Bevis gör det.
Det avsedda användningsområdet är en parallell körning. Båda motorerna tar emot samma produktionsmeddelanden; den sittande motorn fortsätter att leverera och Perfuse levererar till ingen, vilket är vad skuggkanaler redan är. Efter två veckor jämförs utdatan här, och samtalet ändras från "lita på detta" till "här är de tre meddelandena av fyra hundra tusen där vi skilde oss, och varför".
Gruppering är hela funktionen
En naiv diff av 400 000 meddelanden producerar 400 000 resultat och stängs oläst. Nästan varje verklig skillnad har en orsak: ett datumformat, en anläggningskod, ett transformeringsskede som ingen bar med sig. Så skillnader grupperas efter orsak - sökvägen i meddelandet och typen av skillnad - och rapporteras en gång med en räkning. Tre tusen skillnader från en orsak är ett resultat, inte tre tusen. Det enskilda beslutet är vad som gör rapporten läsbar, och en läsbar rapport är skillnaden mellan en migration som fortskrider och en som stannar.
Värdena är inte med som standard
Verklig trafik är patientdata, så en jämförelserapport är en plats där PHI kan läcka in i en biljett, ett e-postmeddelande eller en bild. Som standard rapporterar detta sökvägar, typer och räkningar - aldrig värden. Det räcker för att hitta orsaken: "MSH-7 skiljer sig i 3 000 av 3 000 meddelanden" berättar för en analytiker att det är datumformatet utan att visa ett datum.
Värden kan aktiveras medvetet, eftersom någon så småningom behöver se ett, och att låtsas som om det inte vore fallet skulle bara driva dem till ett sämre verktyg. Det är ett uttryckligt val och rapporten säger på sitt sätt att den innehåller meddelandeinnehåll.
Source: github.com/biodream-llc/perfuse/internal/equiv
26.43 uttryck
HL7 v2-bindningen.
Detta är logiken som tidigare levde inline i eval.go. Det är oförändrat i beteende - medvetet, eftersom v2-filtret är vad varje HL7-kanal körs och poängen med den generiska grammatiken var att lägga till format, inte att ändra detta.
Source: github.com/biodream-llc/perfuse/internal/expr
26.44 fdlimit
Paketet fdlimit tar reda på hur många filbeskrivningar som den här processen kan öppna och höjer gränsen om den kan.
Detta finns på grund av formen på felet som det förhindrar. Varje inkommande anslutning är en beskrivning, och så är varje utgående leverans under flygning. En mottagare som har slutat att svara håller en beskrivning för hela återförsöksbudgeten - med standardvärdena, fem försök med en tidsgräns på trettio sekunder plus femton sekunder av backoff, så nästan tre minuter. Få hundra anslutningar mot en hängande mottagare är därför flera hundra beskrivningar som hålls i flera minuter.
Att köra ut producerar inte ett snyggt fel på den plats som körde ut. Det producerar "för många öppna filer" någon annanstans helt: databasen kan inte öppna sin journal, webbgränssnittet slutar att acceptera, en loggfil kan inte skrivas. Motorn verkar ha brutits på tre olika ställen på en gång, och den verkliga orsaken är ett partnersystem som gick tyst. Det är det supportanrop som detta paket finns för att undvika.
Två saker händer vid start. Den mjuka gränsen höjs till den hårda gränsen, vilket vanligtvis tar bort problemet helt - den mjuka standarden är ofta några hundra medan den hårda gränsen är tiotusentals. Sedan rapporteras vad som är tillgängligt, så motorn kan begränsa sin egen samtidighet inom den snarare än att upptäcka den genom att träffa den.
Source: github.com/biodream-llc/perfuse/internal/fdlimit
26.45 fhirpath
Paketet fhirpath utvärderar FHIRPath (HL7 FHIRPath N1, 2.0.0) över FHIR-resurser som hålls som avkodad JSON.
Det har ingen FHIR-modell: en elements typ är känd när FHIR JSON säger det (ett valfritt elements suffix, såsom valueQuantity, en resurs resourceType) eller härledd från JSON-värdet annars. Det täcker vad SQL på FHIR-vyer och CQL-fria kvalitetsmått behöver; navigering som beror på modellen (en primitivs egen typ när den inte är ett val) besvaras från värdets form.
Source: github.com/biodream-llc/perfuse/internal/fhirpath
26.46 fhirserver
Paketet fhirserver implementerar en FHIR REST-server.
Detta finns eftersom den användbara änden av en v2-till-FHIR-mappare är någonstans att lägga resultatet. Att kunna konvertera ett meddelande är en demo; att kunna konvertera det, lagra det och sedan hitta patienten igen med identifierare är en produkt.
Det är en riktig FHIR-server i de delar som är viktiga för det: en kapacitetsförklaring, skapa, läsa, uppdatera, ta bort, söka på parametrarna som folk faktiskt använder, och transaktionspaket som appliceras atomiskt. Det är inte en komplett FHIR-server — ingen historia, ingen kedjad sökning, ingen _inkludering — och det säger så i sin egen kapacitetsförklaring snarare än att låta en klient upptäcka luckorna.
Source: github.com/biodream-llc/perfuse/internal/fhirserver
26.47 formulary
Paketet formulary är en betalares läkemedelsformulär: vilka läkemedel varje plan täcker, på vilken nivå och med vilka begränsningar (föregående auktorisation, stegterapi, kvantitetsbegränsningar), och vad medlemmen betalar.
En fil är den enda källan för allt som besvarar en fråga om ett läkemedel: Da Vinci US Drug Formulary API (publicerad från den som FHIR), NCPDP Real-Time Prescription Benefit-svar och NCPDP SCRIPT elektronisk förhandsauktorisation (om ett läkemedel behöver en och vilka frågor som ska ställas). En formulary som fanns på tre ställen skulle besvara samma fråga på tre sätt.
Source: github.com/biodream-llc/perfuse/internal/formulary
26.48 ramning
Paketering av ramar läser och skriver meddelanden på en byte-ström som inte är MLLP.
Varför detta existerar separat från mllp
MLLP är en ram: 0x0B före, 0x1C 0x0D efter. Det är vad HL7 v2 använder över TCP och Perfuse har alltid talat det.
Många enheter gör inte det. En laboratorieanalyserare, en våg, en sängbordsterminal, ett äldre faktureringsystem - var och en tenderar att ha sin egen konvention, och konventionerna är alla enkla variationer på samma tre idéer: en avgränsare någonstans, en fast postlängd eller en längd skriven framför nyttolasten.
Mirths TCP-anslutning täcker detta och Perfuse hade ingenting, så en plats med en socket-matare som inte var HL7 kunde inte använda den alls.
Misstaget som detta paket är skrivet för att undvika
Att läsa från en ström och gissa var ett meddelande slutar är hela problemet. Gissa kort och ett meddelande kapas i två delar; gissa långt och två meddelanden anländer som ett. Båda producerar utdata som ofta ser trovärdiga ut, vilket är värre än ett fel, så varje läge här är uttryckligt om vad som avslutar ett meddelande och ingen av dem backar till ett annat.
Ett meddelande med ingen ram alls är en giltig konfiguration - vissa enheter öppnar en anslutning, skickar ett meddelande och stänger - men det kan inte kombineras med något annat och kan inte användas på en anslutning som förblir öppen, så det namnges och valideras snarare än behandlas som standard.
Source: github.com/biodream-llc/perfuse/internal/framing
26.49 ftpconn
Paketet ftpconn laddar upp filer via FTP och FTPS med hjälp av endast standardbiblioteket.
FTP är gammalt, pratigt och inte en bra protokoll. Det är också fortfarande hur många sjukhusystem accepterar filer, vanligtvis för att den avlägsna änden är en laboratorieanalyserare eller en byråtjänst vars programvara inte har rörts sedan den fungerade. Att vägra stödja det gör inte att dessa system blir moderna; det gör Perfuse oanvändbart på dessa platser.
Implementerat här snarare än taget som en beroende av samma anledning som S3: den åtta-beroende fakturan är ett verkligt argument med vem som granskar programvara innan ett sjukhus installerar den. FTP:s kontrollkanal är textorienterad text över TCP, så detta är ett par hundra rader av net och crypto/tls.
Vad som stöds och vad som vägras
Endast passivt läge. Aktivt läge kräver att servern öppnar en anslutning tillbaka till klienten, vilket varje sjukhusbrandvägg byggt detta århundrade blockerar, och att erbjuda det skulle innebära att människor konfigurerar det och sedan felsöker en brandvägg.
Explicit FTPS (AUTH TLS) stöds och är standard när TLS begärs. Implicit FTPS på port 990 stöds också eftersom vissa analyserare endast talar det.
Vanligt FTP stöds och varnar. Det skickar lösenordet i klartext, och en plats som måste använda det bör meddelas en gång snarare än lämnas att upptäcka från en paketinspelning.
Source: github.com/biodream-llc/perfuse/internal/ftpconn
26.50 gcp
Paketet gcp pratar med Google Cloud Pub/Sub och Cloud Storage via deras REST-API:er, med Googles OAuth 2.0 gjort här: en tjänstekontonyckel signeras med en JWT (RS256, crypto/rsa) som byts mot en åtkomsttoken, eller, på Google Cloud själv, metadata-servern delar ut en.
Inga Google-SDK.
Emulatorer (Pub/Sub-emulatorn, fake-gcs-server) tar inga autentiseringsuppgifter: ange Endpoint och lämna autentiseringsuppgifterna tomma.
Source: github.com/biodream-llc/perfuse/internal/gcp
26.51 generate
Paketet generate skapar syntetiska HL7 v2-meddelanden.
Två användningar. Någon som försöker Perfuse behöver trafik att titta på, och en kanaltest behöver en fixture som är tillräckligt realistisk för att öva det som testas. En generator är en betald tillägg i Mirth, vilket berättar att människor vill ha en.
Allt här är uppfunnet. Namnen kommer från en fast lista med uppenbarligen fiktiva namn, identifierarna är sekventiella inom en körning, och adresserna är uppfunna. Det är inte en disclaimer, det är designen: en generator som producerade trovärdigt utseende riktiga namn skulle så småningom sätta ett i en testfixture, en felrapport och sedan ett repository.
Realism åtgår där det behövs för testning och ingen annanstans. Tidsstämplar har offset, upprepningsfält upprepas faktiskt, ett namn har ibland ett mellannamn och ibland inte, och ungefär ett meddelande av tolv är medvetet besvärligt: ett saknat valfritt fält, en ovanlig men laglig separator, en tom komponent. Att mata en kanal med endast perfekt formade meddelanden berättar mycket lite.
Source: github.com/biodream-llc/perfuse/internal/generate
26.52 hl7dict
Paketet hl7dict namnger fälten i HL7 v2-segment.
Detta finns för en skärm: en meddelandevisare som kan berätta att PID-5.1 är patientens efternamn istället för att låta dig räkna hakparenteser. Alla som har felsökt en gränssnitt har räknat på det sättet för hand, och det är den vanligaste källan till off-by-one-fel som placerar ett värde i fel fält.
Det är inte hela standarden. HL7 v2 har hundratals segment och tusentals fält, och de som finns här är de som visas i ADT-, ORU-, ORM- och SIU-trafik. Ett okänt fält rapporteras som okänt snarare än gissat.
Source: github.com/biodream-llc/perfuse/internal/hl7dict
26.53 hl7v3
Paketet hl7v3 läser HL7-version 3-meddelanden.
Version 3 är en annan sak än version 2 med samma namn. Version 2 är en pipe-avgränsad ström av segment vars betydelse är positionell; version 3 är XML som genereras från en referensinformationsmodell, där betydelsen bärs av elementnamn och av en liten uppsättning datatyper som återkommer överallt. Knappast någonting överförs mellan de två utöver den kliniska vokabulären.
I praktiken anländer v3 i en av två former. Antingen är det ett CDA-dokument, som är v3-derivat och hanteras av cda-paketet, eller så är det en IHE-transaktion - PIX och PDQ v3 i synnerhet, som är hur de flesta sjukhus löser patientidentiteter mellan system. Detta paket riktar sig mot den senare.
Varför datatyperna kommer först
Den mest konsekventa sak om v3 är att ett element kan vara närvarande och uttryckligen null, med en angiven anledning. En födelsedatum som bär nullFlavor="ASKU" betyder att patienten blev tillfrågad och vägrade att svara. En som bär nullFlavor="NAV" betyder att värdet finns men är inte tillgängligt just nu, så att fråga igen senare kan fungera. En som helt enkelt är frånvarande betyder att ingen spelade in någonting alls.
Att kollapsa dessa till en tom sträng är misstaget som detta paket är utformat för att förhindra. Det är inte en kosmetisk förlust: ett nedströmsystem som tar emot en tom födelsedatum där källan sa "patienten vägrade" kommer vanligtvis att behandla det som saknat data som ska jagas, och en demografisk match som borde ha lämnats olöst får lösas av en människa som gissar. Så varje datatyp här skiljer på frånvarande, null-med-anledning och närvarande.
Source: github.com/biodream-llc/perfuse/internal/hl7v3
26.54 hl7xml
Paketet hl7xml konverterar HL7 v2-meddelanden till och från den XML-form som Mirth Connect använder, och tillbaka till ER7-kodning.
Formen är inte ett designval. Mirths skript är skrivna mot utdata från dess egen ER7-till-XML-serieiserare, så de innehåller uttryck som
msg['PID']['PID.5']['PID.5.1'].toString()
och löftet att ett befintligt skript körs oförändrat upprätthålls endast om trädet det vandrar har exakt samma elementnamn, kapslings- och upprepningsbeteende. Varje beslut nedan är därför "vad gör Mirth", inte "vad vore snyggare".
De två som betyder mest:
Varje fält är inneslutet i numrerade komponentelement även när fältet endast har en komponent, så PID-5 med värdet "Doe" fortfarande producerar <PID.5><PID.5.1>Doe</PID.5.1></PID.5>. Skript index direkt till .1 konstant och ett träd som placerar texten på fältet skulle bryta nästan alla.
MSH behåller standard-HL7-fältnummer, där MSH-1 är fältavgränsaren och MSH-9 är meddelandetypen. Parseen i internal/hl7 index MSH med en offset eftersom avgränsaren upptar en position som ingen avgränsare delar, och den offseten stoppar här: ett skript som säger MSH.9 menar meddelandetypen.
Source: github.com/biodream-llc/perfuse/internal/hl7xml
26.55 ibmmq
Paketet ibmmq skickar till och läser från IBM MQ-köer via köledarens meddelande-REST-API (mqweb), som IBM MQ 9.1.5 och senare levereras på varje plattform, inklusive z/OS.
Det behöver ingen MQ-klientbibliotek: det nativa MQI-protokollet är IBMs och odokumenterat, och REST-API:t är det stödda sättet att nå MQ utan en. (IBM MQ talar också AMQP 1.0 på en AMQP-kanal; Perfuses amqp-anslutning täcker den vägen.)
Läsning är minst en gång: det första meddelandet bläddras, överlämnas till anroparen och tas bort av dess meddelande-ID endast en gång anroparen har hanterat det. Ett meddelande som inte kunde hanteras stannar på kön, först i kön.
Source: github.com/biodream-llc/perfuse/internal/ibmmq
26.56 identitet
Att hitta ett meddelande efter vad du vet om det, oavsett vilket format det anlände i.
Den befintliga innehållssökningen matchar metadata, erbjuder en delsträngsöverensstämmelse mot payloaden och kan utvärdera ett filteruttryck - men uttrycket utvärderas endast mot HL7 v2, och varje uttryck kräver att man känner till sökvägen. Så att hitta en patients trafik innebar att veta att identiteten finns på PID-3 i en HL7 v2-inlämning, på Patient.identifier i en FHIR-resurs, på (0010,0020) i en DICOM-instans och på NM109 i en NM1*IL-slinga i en 837-anspråk. Fyra format, fyra vokabulärer, och under en incident kan meddelandet som eftersöks finnas i något av dem.
Detta paket kartlägger ett litet antal begrepp - vem meddelandet handlar om, vilket besök, vilken studie, vilket anspråk - till den plats varje format lagrar dem, så en sökning kan vara för "MRN 12345" snarare än för en sökväg. Begreppen är medvetet få: det är de saker människor faktiskt har i handen när de behöver hitta ett meddelande, som ett nummer från ett telefonsamtal eller ett namn från en klagomål.
Varför extrahering sker en gång, vid posttid
Alternativet är att parsning av payloaden sker vid frågetid, vilket är vad uttryckssökningen gör. Det fungerar och det är ärligt om att vara en begränsad sökning, men det kan inte svara på "alla meddelanden om denna patient över fyra flöden och två månader" utan att läsa varje rad. Att extrahera en gång till en indexerad tabell omvandlar det till en indexsökning.
Detta är en sekretesshöjning, och det är valfritt
Patientnamn och identifierare sitter för närvarande inuti en ogenomskinlig payload-kolumn. Att indexera dem gör dem frågebara, vilket är poängen, och gör dem också uppräkneliga, vilket är en verklig förändring av exponering: en databas som endast kunde genomsökas kan nu frågas "lista alla patienter". Det är ett beslut för webbplatsen, inte för detta paket, så extraheringen är omkopplningsbar och varje sökning genom den loggas i PHI-granskningsloggen.
Source: github.com/biodream-llc/perfuse/internal/identity
26.57 iis
Paketet iis talar transporten som varje amerikansk vaccinationsregister delar: CDC:s IIS SOAP-webbtjänst.
År 2011 sammanställde en expertpanel som CDC och American Immunization Registry Association en SOAP-gränssnitt för att skicka HL7 v2-meddelanden till vaccinationsinformationssystem, och registren antog det. WSDL är liten - två operationer, connectivityTest och submitSingleMessage - och HL7-meddelandet (en VXU för att rapportera en skott, en QBP^Q11 för att fråga efter en patients historia) reser som flykttext inuti SOAP-kroppen. Svaret kommer tillbaka på samma sätt: en ACK, eller en RSP^K11 som bär historiken och prognosen.
Den generiska SOAP-destinationen kunde konfigureras för att göra detta, men varje webbplats skulle behöva skriva samma kuvert, få namnutrymmet rätt, lägga till autentiseringsuppgifterna i kroppen snarare än i HTTP-autentisering, och sedan läsa HL7-bekräftelsen ut ur svaret för att lära sig om registret behöll posten. Ett register svarar på ett avvisat skott med HTTP 200 och en AR; att behandla 200 som framgång är hur vaccinationer tystnar för att rapporteras. Så detta paket gör CDC-kuvertet och bedömer bekräftelsen, en gång.
Vad det inte gör: WSDL-användarnamn och lösenord är registrets programautentiseringsuppgifter och skickas som WSDL säger, i kroppen. Ömsesidig TLS, där ett register kräver det, är destinationens TLS-inställning som för alla HTTPS-samtal. Ingenting här är specifikt för en stat; där stater skiljer sig (facilitets-ID krävs eller inte, SOAP 1.1 accepteras eller inte, varningar skickas som AE) säger destinationens inställningar så.
Source: github.com/biodream-llc/perfuse/internal/iis
26.58 kafka
Kafka, som en klient snarare än som något att ersätta.
Ett hälsovårdssystem som har en händelsebackbone har en Kafka, och systemen som byggdes under det senaste decenniet publicerar till det snarare än till en JMS-broker. Så detta anslutningsprogram finns för att göra Perfuse till den hälsovårdsvetenskapliga kanten av någon annans händelseplattform: det läser kliniska meddelanden från ämnen och publicerar dem till ämnen, och det försöker medvetet inte vara en strömmande plattform. Fönster, kopplingar, strömbehandling och schemaregister är Kafkas ekosystem och stannar där.
Varför en beroende, när STOMP och MLLP skrevs för hand
Den angivna regeln i detta repository är att en beroende måste köpa kapacitet snarare än bekvämlighet, och måste vara ren Go så att en statisk binär fortfarande kan korscompilera till varje mål. franz-go är ren Go och bär ingen cgo, vilket kontrollerades mot alla sex mål.
Kafkas protokoll är inte STOMP:s. STOMP är ett textprotokoll som passar i några hundra rader. Kafka är ett versionerat binärt protokoll över ungefär sjuttio förfrågetyper, och den del som är viktigast här - konsumentgrupper - är ett distribuerat samordningsprotokoll med join, sync, hjärtslag och offset-commit-faser och en omräkning dans mellan dem. Att få det subtilt fel producerar inte ett uppenbart fel: det producerar en partition som ingen läser, eller två konsumenter som läser samma sak. I en klinisk feed är det ett saknat laboratorieresultat och en duplicerad ordning. Det är kapacitet, och det är inte värt att handrulla för att spara en beroende.
Source: github.com/biodream-llc/perfuse/internal/kafka
26.59 ldap
Paketet ldap talar tillräckligt med LDAP för att autentisera en person och läsa deras grupper.
Sjukhus använder nästan alltid Active Directory, och AD talar LDAP. OpenID Connect är det bättre svaret där det är tillgängligt - se internal/oidc, och notisen där om att Mirth inte har någon enkel inloggning till något pris - men en integrationsmotor sitter ofta på ett isolerat VLAN där en webbläsare inte kan nå en identitetsleverantör alls. Det är därför det här finns.
Egen BER-kodning istället för en beroende, av samma anledning som DICOM och STOMP: kodningen är liten, och vad som anländer till den här sockeln bestämmer om någon kommer in i ett system som flyttar patientdata.
encoding/asn1 i standardbiblioteket är inte användbart här. Det riktar sig mot DER och avvisar de kontextspecifika taggarna och implicit taggning som LDAP använder genomgående, så de delar som är viktiga skulle ändå behöva skrivas för hand.
Source: github.com/biodream-llc/perfuse/internal/ldap
26.60 postlåda
Paketet postlåda läser e-post från IMAP4rev1- (RFC 3501) och POP3-servrar (RFC 1939), loggar in med ett lösenord eller med OAuth 2.0 (SASL XOAUTH2, som Microsoft 365 och Gmail kräver), och tar isär meddelanden (RFC 5322 och MIME) så att en bilaga eller textkroppen kan bli ett meddelande på en kanal.
Bara vad en inkommande feed behöver: välj en postlåda, hitta olästa meddelanden, hämta dem i sin helhet, sedan flytta, markera eller ta bort dem. Endast standardbibliotek; TLS är crypto/tls.
Source: github.com/biodream-llc/perfuse/internal/mailbox
26.61 mappare
Paketet mappare föreslår fältmappningar mellan system med konfidenspoäng.
Detta är en regelbaserad intelligent mappningsmotor. Inga LLM, inga nätverksanrop, inga externa beroenden. Den körs offline i samma binär och skickar aldrig patientdata någonstans.
Motorn kombinerar flera signaler - fuzzy strängmatchning på fältnamn, erkännande av mönster för hälsoidentifierare, kodsystemslösningar och historiska acceptansdata - till ett enda konfidenspoäng per förslag. När konfidensen är under en konfigurerbar tröskel avstår mapparen från att gissa fel, eftersom en felaktig mappning inom hälsovården kan dirigera data till fel fält och det är en patientsäkerhetsdefekt.
Avstående är det centrala designbeslutet. Ett system som alltid producerar ett svar tränar användare att sluta kontrollera, och den gång det är fel märker ingen till att en labresultat hamnar i en anteckningsfält. Ett system som säger "Jag vet inte" tvingar ett mänskligt beslut exakt när det mänskliga behövs.
Source: github.com/biodream-llc/perfuse/internal/mapper
26.62 mätning
Paketet mätning utvärderar FHIR-mätningar (digitala kvalitetsmätningar) vars populationskriterier är FHIRPath, och skriver resultatet som en FHIR-mätrapport: sammanfattning, individuell eller ämneslista, med stratifier och en proportionspoäng.
Varje kriterium utvärderas en gång per patient, med fokus på en samling av patientens journal (deras avdelning) och dessa variabler: %subject (patienten), %periodStart och %periodEnd (mätperioden, som DateTimes) och %"Mätperiod" (samma som en period). Kriterier i CQL avvisas med orsaken: Perfuse har ingen CQL-motor.
Source: github.com/biodream-llc/perfuse/internal/measure
26.63 mätvärden
Paketet mätvärden samlar in vad motorn gör och behåller tillräckligt med historia för att rita det.
En gränssnittsmotor övervakas, inte bara körs. När en avdelning säger att resultaten slutade anlända för tjugo minuter sedan är frågan vad som ändrades för tjugo minuter sedan, och det kan inte besvaras av nuvarande räknare ensam. Så det här behåller serier snarare än totaler, i minnet, i en fast upplösning.
Tre beslut formar det.
Fördröjning behålls som ett histogram snarare än ett medelvärde. Ett genomsnittligt leveranstid är nästan värdelöst i det här området: det som är viktigt är om de långsammaste få procenten av meddelandena är tillräckligt långsamma för att bryta ett omsättningslöfte, och ett medelvärde döljer exakt det. Bucketer är exponentiella och fasta vid byggtid, så att spela in en varaktighet är en jämförelse och en ökning utan allokering.
Serier är begränsade ringbuffertar, storleksbestämda när insamlaren skapas. Ingenting här växer utan begränsning, eftersom en gränssnittsmotor körs i månader i taget och ett mätningssystem som behöver startas om är värre än inget.
Kardinalitet är begränsad. En etikettvärde som tas från meddelandedata - en avsändande applikation, säg - kan ta tusentals värden om någon felkonfigurerar en feed, och obegränsade etiketter är det standardiserade sättet övervakning tar ner det som övervakas. Förbi begränsningen kollapsar värdena till en "annan"-bucket och begränsningen rapporteras själv.
Source: github.com/biodream-llc/perfuse/internal/metrics
26.64 mirth
Javaanalys för importerade Mirth-kanaler.
Varför det här finns
Mirth kör Rhino på JVM, så en Mirth-skript kan anropa valfri Java på klasssökvägen, inklusive Mirths egna serverklasser. Perfuse kör goja och har ingen Java-körning. Den avvisar dessa anrop med ett fel som namnger klassen - men det avvisandet sker när skriptet körs, vilket för en källanslutning betyder när det första riktiga meddelandet anländer.
Så en migration gick tidigare: importen lyckas tyst, kanalen distribueras, och det första meddelandet från ledningen misslyckas. En migration som ser ren ut och bryter på första trafiken är värre än en som avvisar vid dörren, eftersom personen som gjorde det redan har berättat för sina kollegor att det fungerade.
Detta hittar dessa anrop vid importtid och säger vad som ska göras med var och en.
Varför fyra utslag och inte två
"Använder Java" är en bit information och den felaktiga, eftersom den Java som ett riktigt Mirth-kanal använder faller in i grupper med helt olika mängder arbete kopplat. Ungefär hälften av vad webbplatser faktiskt skriver är SimpleDateFormat och HashMap, som JavaScript hanterar nativt. En del av det är Mirths dokumenterade skript-API, som Perfuse redan implementerar under samma namn. En liten del vill starta och stoppa kanaler, som Perfuse kan göra via sin REST-API men inte exponerar för skript. Och en del är en leverantörsjar som aldrig kommer att köras här.
Att rapportera dessa som ett nummer berättar ingenting för en migrerare om huruvida deras eftermiddag eller deras kvartal står på spel.
Source: github.com/biodream-llc/perfuse/internal/mirth
26.65 mirthlive
Paketet mirthlive hittar de körs Mirth-familjens motorer som interoperabilitetstesterna pratar med.
Mirth Connect slutade vara öppen källkod vid 4.6 (mars 2025). Webbplatser som lämnar det går till en av tre platser: Mirth 4.5.2, den sista öppna versionen, som de fortsätter att köra; Open Integration Engine, Eclipse-värden fork; eller BridgeLink, Innovars fork, som numrerar sina versioner efter år (26.9.0). En kanal som Perfuse exporterar måste laddas i alla dessa, och en kanal som någon av dem exporterar måste importeras här, så varje livetest körs en gång per motor som svarar.
Motorerna hittas genom att fråga, inte konfigureras: ./scripts/interop-up.sh startar dem på fasta portar, och en motor som inte körs rapporteras som hoppad över snarare än tyst passerar. PERFUSE_MIRTH_ENGINES åsidosätter listan, som namn=URL-par separerade med kommatecken.
Endast tester importerar detta. Det lever utanför en _test.go-fil eftersom två paket delar på det.
Source: github.com/biodream-llc/perfuse/internal/mirth/mirthlive
26.66 mpi
Paketet mpi är en master patient index: det tar patientposter från varje källsystem (varje identifierat av dess tilldelningsmyndighet och nummer), bestämmer vilka som tillhör samma person och ger varje person ett företagsidentifierare (EUID).
Vissa matcher länkar på egen hand; osäkra väntar i en granskningskö för att en person ska fatta ett beslut; varje länk, länkborttagning, sammanslagning och beslut registreras med vem som gjorde det.
Matchning är deterministisk först (en identifierare från ett system som webbplatsen litar på att vara unik per person, såsom en nationell identifierare eller ett företagsnummer) och probabilistisk i övrigt: Fellegi-Sunter-vikter över namn, födelsedatum, kön, postnummer, telefon och adress, med Jaro-Winkler för namn. Den bestämmer ingenting kliniskt: den säger vilka poster som är samma person, med sina skäl, för en person att bekräfta när den inte är säker.
Source: github.com/biodream-llc/perfuse/internal/mpi
26.67 mqtt
Paketet mqtt är en MQTT 3.1.1-klient: anslut (med TLS, ett användarnamn och lösenord, eller ett klientcertifikat), publicera vid QoS 0 eller 1, prenumerera och bekräfta varje mottagen QoS 1-meddelande endast en gång när anroparen säger att det har hanterats.
Skriven mot OASIS MQTT 3.1.1-standarden snarare än importerad, som Perfuses andra trådprotokoll är. 3.1.1 är den version varje mäklare talar: Mosquitto, EMQX, HiveMQ, VerneMQ, RabbitMQs MQTT-plugin, IBM MQs telemetrikanal, AWS IoT Core och Azure Event Grid.
Leverans: ett meddelande som tas emot vid QoS 1 bekräftas (PUBACK) endast när Ack anropas. En anropare som inte kan hantera ett meddelande stänger anslutningen istället; med en beständig session (CleanSession false) skickar mäklaren det igen, markerat som en kopia, när klienten ansluter igen. MQTT 3.1.1 har ingen negativ bekräftelse, så detta är det enda sättet att begära ett meddelande igen.
Source: github.com/biodream-llc/perfuse/internal/mqtt
26.68 msgstore
Hitta ett lagrat meddelande genom vad någon vet om det.
Sökningen en person faktiskt behöver är "här är ett nummer från ett telefonsamtal, visa mig varje meddelande om det". Innan detta innebar det antingen en delsträngsmatchning över nyttolast, som är grep och långsam, eller ett filteruttryck, som kräver att man vet att identitet bor på PID-3 i HL7 v2 och någon annanstans helt i de andra tre formaten på samma server.
Identitet extraheras en gång när meddelandet spelas in och indexeras, så detta är en sökning snarare än en skanning. Kostnaden betalas på inspelningssökvägen, en gång per meddelande, istället för på varje sökning.
Source: github.com/biodream-llc/perfuse/internal/msgstore
26.69 natid
Paketet natid känner till de nationella patient- och personidentifierarna i Storbritannien och Europa: deras format, deras kontrollsiffror, identifieringssystemet som varje lands FHIR-guiden namnger dem med, och hur mycket av en som får visas.
Det finns för patientindex. En nationell nummer är det starkaste beviset att två poster är en person, och också det lättaste att göra fel: en siffra som skrivs två gånger ger ett nummer som tillhör någon annan, och en källa skickar NHS-numret under ett OID medan en annan skickar det under dess FHIR-URL. Så varje identifierare som indexet lagrar går genom här: dess kontrollsumma testas (en felaktig används aldrig för att länka), dess avstånd tas bort och dess system skrivs på ett sätt.
Vad som verifieras och vad som inte är sagt per schema. Algoritmerna är offentliga; identifieringssystem-URI:erna är landets egna där en nationell FHIR-guide namnger en (SystemVerified), och ett dokumenterat standardvärde i övrigt, som en webbplats ändrar till sitt nationella värde under Inställningar → Patientindex. Ingenting här bestämmer något kliniskt.
Source: github.com/biodream-llc/perfuse/internal/natid
26.70 ncpdp
Skrivning av ett fält i en NCPDP-överföring.
Varför en skrivning vägrar en tvetydig sökväg
Läsning returnerar varje värde som en sökväg adresserar, eftersom ett filter som frågar om något DUR-konflikt är en terapeutisk duplicering bör se alla. En skrivning kan inte fungera på det sättet. Om D7 adresserar produktkoderna för två anspråk i en överföring, har inställning av D7 ingen entydig betydelse: skrivning av båda skulle ändra ett läkemedel som ingen frågade om, och skrivning av det första skulle tyst lämna det andra.
Så en skrivning vägrar en sökväg som adresserar mer än ett fält, och felet namnger den kvalificerade formen som skulle vara entydig. Detta är samma resonemang som ger transformationsstegen ingen ta bort-åtgärd: där det ärliga svaret är att konfigurationen är tvetydig, säger det slår att välja en.
Source: github.com/biodream-llc/perfuse/internal/ncpdp
26.71 oidc
Paketet oidc verifierar OpenID Connect-identiteter.
Skrivet mot standardbiblioteket snarare än en JWT-beroende. Autentisering är den plats där en ogranskad beroende är minst acceptabel, signaturverifiering för de algoritmer som är viktiga är cirka hundra rader av crypto/rsa och crypto/ecdsa, och Perfuse bär redan tillräckligt för att lägga till mer behöver en anledning snarare än en vana.
Omfattningen är medvetet smal: verifiera att en identitetsleverantör intygar en person, och rapportera vad den sa om dem. Allt annat - vad de kan göra, hur länge sessionen varar - stannar med Perfuse, eftersom en identitetsleverantör vet vem någon är och inte vad de har tillåtelse att göra i en gränssnittsmotor.
Source: github.com/biodream-llc/perfuse/internal/oidc
26.72 parity
Paketet parity jämför vad Perfuse producerar mot vad motorn som ersätts producerade.
Varför det här finns
Perfuse kan importera en Mirth-kanal och kan spåra vad den skulle göra med ett meddelande. Ingen av dem svarar på frågan någon faktiskt har innan man flyttar en live-feed, som är: kommer detta att producera samma utdata som det som har kört i sex år?
Ingen mängd designkvalitet svarar på det. Det enda ärliga svaret är bevis, och bevisen måste komma från den gamla motorn eget utdata på webbplatsens egen trafik.
Varför paren måste tillhandahållas
Detta kan inte nå in i Mirth, och att låtsas som om det vore en funktion vore den värsta sortens funktion. Vad det tar är par: ett meddelande som det anlände, och meddelandet den gamla motorn producerade från det. Båda finns i Mirths egen meddelandelagringsplats och kan exporteras från dess meddelandebrowser, som är en sak en administratör redan vet hur man gör.
Den begränsningen anges snarare än dold. Ett verktyg som påstod sig verifiera en migration utan att någonsin se den gamla motorns utdata skulle verifiera ingenting.
Varför skillnader grupperas snarare än listas
En körning över femtiotusen meddelanden som rapporterar fyrtusen skillnader har berättat någon ingenting de kan agera på. Samma körning som rapporterar att PID-8 skiljer sig i varje meddelande eftersom den gamla motorn mappade M till Male har berättat dem exakt en sak att bestämma om.
Så resultaten grupperas efter fält, med en räkning, ett exempel och de distinkta värdepar som ses. En beslut per resultat är den enhet någon kan arbeta igenom.
Source: github.com/biodream-llc/perfuse/internal/parity
26.73 pas278
Paketet pas278 mappar mellan Da Vinci föregående auktorisering och X12 278-transaktionen.
Varför det här finns
CMS-0057-F kräver att betalare exponerar en FHIR-föregående auktoriserings-API den 1 januari 2027. Det ersätter inte X12 278, och det var aldrig meningen att det skulle: en betalares utnyttjandeledningssystem bestämmer auktoriseringar och talar 278. Så en betalare som uppfyller regeln översätter FHIR till 278 och tillbaka, och en leverantör som skickar 278 idag kommer att skicka FHIR imorgon till samma betalare som fortfarande accepterar båda.
Den översättningen är det som är värt att äga. En motor som håller båda modellerna och inte kan konvertera mellan dem lämnar det svåraste arbetet - och det som felet är dyrt - till den som integrerar den.
Reglerna som detta paket följer, angivna snarare än antydda
Skrivna ner för samma anledning v2fhir skriver ner sina egna: mappning är där interoperabilitetsprojekt misslyckas, och misslyckandena är tysta.
- Ett beslut uppgraderas aldrig. Delvis certifiering blir inte godkännande, och en begäran som betalaren vägrade att överväga blir inte en avvisning. Båda av dessa kollaps är tillgängliga i den uppenbara mappningen och båda är fel i den riktning som kostar någon veckor: en överklagande som lämnats in mot ett beslut som ingen gjorde, eller sex sessioner bokade mot tre godkända. - Ingenting uppfinner för att fylla ett obligatoriskt fält. Där målformatet kräver något som källan inte bär, rapporterar mappningen det som en anteckning snarare än att tillhandahålla ett rimligt standardvärde. Ett fabricerat auktorisationsnummer är värre än ett frånvarande. - Varje bedömning rapporteras. Anteckningar kommer tillbaka med resultatet, så en person kan läsa den handfull som behövde ett beslut snarare än hela utdata. - Rundresor testas, inte antas. En mappning som förlorar ett fält i en riktning hittas genom att konvertera tillbaka och jämföra, vilket är det enda sättet att se ett fält som ingen tänkte på att hävda på.
Source: github.com/biodream-llc/perfuse/internal/pas278
26.74 pdf
Paketet pdf skriver enkla textdokument med hjälp av endast standardbiblioteket.
Mirths Document Writer renderar HTML till PDF, vilket kräver en layoutmotor. Det är inte vad detta är. Detta producerar ett enkelt, paginerat textdokument med ett monospacet teckensnitt, och det finns eftersom den faktiska kravet på nästan varje webbplats som använder den här anslutningen är "lägg till detta rapport på en delad mapp så att någon kan skriva ut den" - en utskrivbar sammanfattning, en resultatrappport, en daglig försoning. Dessa är text.
Att vägra funktionen helt skulle lämna en Tier 2-migrationsblockerare på plats. Att dra in en HTML-renderingsmotor skulle kosta mer än hela resten av binärfilen och medföra en CVE-ström, vilket skulle ogöra argumentet för materialet. Så: text, ärligt beskriven som text, och en webbplats som verkligen behöver typesatt utdata är bättre betjänt av en fildestination och ett verktyg som är byggt för det.
Varför skriva en PDF alls i stället för en textfil
Eftersom mottagaren vanligtvis är en person med en skrivare och en Windows-delad mapp, och en .txt-fil som skrivs ut från en delad mapp förlorar sin paginering, marginaler och ofta sin radbrytning. En PDF skrivs ut på samma sätt överallt, vilket är den enda anledningen till att någon begärde en.
Source: github.com/biodream-llc/perfuse/internal/pdf
26.75 pgp
Paketet pgp krypterar, signerar, dekrypterar och verifierar OpenPGP-meddelanden (RFC 9580 och RFC 4880 för äldre peer), för betalare, clearinghus och statliga myndigheter som utbyter filer över SFTP eller e-post under PGP.
Kryptografin är github.com/ProtonMail/go-crypto, den underhållna grenen av golang.org/x/crypto/openpgp; ingenting här implementerar en primitiv. Detta paket laddar endast nycklar och bestämmer vad ett meddelande måste bära.
Source: github.com/biodream-llc/perfuse/internal/pgp
26.76 pixv3
Paket pixv3 är HL7-version 3-ansiktet för patientindex: IHE Patient Identifier Cross-referencing och Patient Demographics Query-profiler som de flesta sjukhus utanför FHIR-världen fortfarande talar.
- ITI-44, Patient Identity Feed HL7 V3: en källa lägger till en patient (PRPA_IN201301UV02), reviderar en (PRPA_IN201302UV02) eller säger att två poster är samma person (PRPA_IN201304UV02). Besvaras med MCCI_IN000002UV01. - ITI-45, PIXV3-fråga: de andra identifierarna för personen som innehar en (PRPA_IN201309UV02 -> PRPA_IN201310UV02). - ITI-47, PDQV3-fråga: personer som matchar vissa demografiska data (PRPA_IN201305UV02 -> PRPA_IN201306UV02), med fortsättning (QUQI_IN000003UV01) och avbryt (QUQI_IN000003UV01_Avbryt).
Svaren kommer från samma patientindex som PIXm, PDQm, Patient/$match och indexskärmen, så en post som matas in i v3 hittas via FHIR och vice versa. Meddelandena skrivs för hand, i schemats ordning, på grund av att hl7v3.Ack ger.
Source: github.com/biodream-llc/perfuse/internal/pixv3
26.77 priorauth
Paketet priorauth implementerar den leverantörsspecifika arbetsflödet för förhandsauktorisation som krävs av CMS-0057. Det skickar förhandsauktoriseringsbegäranden till betalarens FHIR-API:er, spårar svar och konverterar mellan interna typer och FHIR-resurser.
Source: github.com/biodream-llc/perfuse/internal/priorauth
26.78 privacy
Paketet privacy svarar på en datasubjekts begäranden enligt GDPR och den brittiska GDPR: hitta allt som denna server har om en person, ge det till dem (artiklarna 15 och 20), radera det (artikel 17) och behåll vad en laglig kvarhållning täcker.
Det når varje plats där Perfuse lagrar patientdata: meddelandebutiken (genom dess identitetsindex), leveranskönen, FHIR-butiken (personens Patient-resurser och allt som hänvisar till dem, med deras historia), lagrade förhandsauktoriseringsbegäranden och patientindexet, vars länkar utvidgar en identifierare till alla personens nummer. Vad det inte kan nå namnger det: spår som skickas till en insamlare, granskningsloggen (som behålls, som en post om vem som gjorde vad) och säkerhetskopior, som behåller vad som raderats tills de upphör att gälla - så varje radering skrivs till en förteckning, som saltade hash-värden för identifierarna snarare än identifierarna, och kan tillämpas igen på en återställd kopia.
Det beslutar ingenting på någon annans vägnar. Om en begäran måste beviljas och om ett undantag gäller är kontrollantens beslut; radering kräver en andra administratörens godkännande, och en laglig kvarhållning vägrar den helt.
Source: github.com/biodream-llc/perfuse/internal/privacy
26.79 publichealth
Paketet publichealth implementerar dubbelriktad allmän hälsorapportering: elektronisk fallrapportering (eCR), elektronisk laboratorierapportering (ELR) och immuniseringregisterförfrågningar.
Varje sjukhus är enligt lag skyldigt att rapportera vissa tillstånd - tuberkulos, mässling, hepatit, COVID-19, sexuellt överförbara infektioner, matburna sjukdomar - till statliga och lokala hälsomyndigheter. Rapporteringen sker genom tre olika gränssnitt:
- ELR: HL7 2.5.1 ORU^R01-meddelanden som bär laboratorieresultat till hälsomyndigheter (elr.go). - eCR: FHIR-baserade elektroniska initiala fallrapporter (eICR) när ett rapporteringsbart tillstånd diagnostiseras. - Immuniseringregister: VXU^V04 för att rapportera vaccineringar som administrerats och VXQ^V01 för att fråga en patients immuniseringshistoria.
Paketet är dubbelriktat: det rapporterar utåt (ELR, eCR, VXU) och frågar tillbaka (VXQ/VXR). Alla operationer är i realtid snarare än nattliga batch.
Trådsäkerhet: SubmissionLog är säker för samtidig användning. Byggfunktionerna är rena och säkra att anropa från valfri goroutine.
Source: github.com/biodream-llc/perfuse/internal/publichealth
26.80 published
Paketet published innehåller vakterna för Perfuses importabla paket, på en plats.
hl7 var det första paketet som publicerades och bär sin egen kopia av dessa kontroller. fhir och pas publicerades så att en besluts tjänst som Vaglio läser FHIR- och PAS-begäranden med exakt den kod som Perfuse använder, snarare än en kopia som glider: fyra läsare av X12-åtgärdskoderna i detta repository var oense, och en läste en avvisning som ett godkännande. Vakterna hålls här snarare än kopieras in i varje paket, av samma anledning.
Source: github.com/biodream-llc/perfuse/internal/published
26.81 kö
Paketet queue är en hållbar, per-destination leveranskö.
Utan det förlorar en destination som är nere i två minuter allt som skickas under de två minuterna: omförsök sker i minnet, och när de tar slut sparas meddelandet som misslyckat och försvinner. Med det sparas meddelandet på disk och behåller sin plats tills destinationen kommer tillbaka.
Två designbeslut formar allt annat.
Ordningen behålls per destination, och det innebär att en köad destination slutar ta den snabba vägen. HL7 är en ström av händelser om samma patienter: en A01 medger, en A03 utskriver. Om en misslyckad A01 går till kön medan nästa A03 levereras direkt ser mottagningssystemet en utskrivning för en patient som aldrig togs in. Så när något köas för en destination köar allt för den destinationen bakom det tills kön töms. Det kostar genomströmning under en avbrott och det är inte valbart, eftersom alternativet är tyst klinisk nonsens. Det är också det specifika som går fel i andra motorer när någon aktiverar samtidiga kötrådar för att tömma en backlogg snabbare.
Ett köat meddelande är ett accepterat meddelande. Avsändaren meddelas AA, eftersom byte sparats på disk och fsyncats innan bekräftelsen skickas ut. Att säga AE skulle göra en korrekt fungerande lagrings- och vidarebefordringskö look som ett fel och inbjuda avsändaren att skicka om det som vi redan har.
Source: github.com/biodream-llc/perfuse/internal/queue
26.82 vistelse
Paketvistelse anger var den här serverns data får gå: molnregioner som en webbplats tillåter (EEA, Storbritannien, Schweiz eller regioner som namnges en och en), och om en anslutnings region är en av dem.
Perfuse kontrollerar vad den kan veta. En AWS-anslutning namnger sin region (S3, SQS, SNS), och en AWS-värdnamn bär en (sqs.eu-west-2.amazonaws.com); dessa kontrolleras när en kanal sparas och laddas, så en kanal kan inte skicka patientdata till en bucket i Virginia från en server vars data måste stanna i Frankfurt. Ett vanligt värdnamn (ett sjukhus eget system, en partners MLLP-lyssnare) säger ingenting om var det är, och bedöms inte här: posten för bearbetning listar varje värd som en kanal skickar till, för kontrollanten att kontrollera.
Source: github.com/biodream-llc/perfuse/internal/residency
26.83 rtpb
Paket rtpb svarar på NCPDP Real-Time Prescription Benefit-förfrågningar från en formulary: vad en medicin kommer att kosta den här medlemmen på den här apoteket, om det behöver en föregående auktorisation eller ett steg först, och vilka alternativ som kostar mindre.
CMS-0062-P föreslår RTPB för påverkade betalare från och med den 1 oktober 2027. XML är NCPDP RTPB v13 (PBv13). NCPDP:s schema är licensierat, så elementnamn och ordning följer de offentliga Surescripts RTPB-exemplen och NCPDP:s offentliga RTPB-Implementeringsrekommendationer (täckningsbegränsningskoder och den täckningsstatus som var och en kartläggs till); ett svar kontrolleras inte mot XSD här, och en nätverkscertifiering är där det händer.
Source: github.com/biodream-llc/perfuse/internal/rtpb
26.84 s3put
Paket s3put skriver objekt till S3 med hjälp av endast standardbiblioteket.
Det uppenbara sättet att prata med S3 är AWS SDK, och SDK är enorm. Det här projektet säljer en statisk binär med åtta direkta beroenden och en materialförteckning som får plats på en skärm - det är ett riktigt argument med den person som granskar programvara innan ett sjukhus installerar den, och att byta bort det för en anslutning vore ett dåligt köp.
Vad S3 faktiskt behöver är en HTTP-PUT och en signatur. Signaturversion 4 är fullständigt specificerad, den är deterministisk, och AWS publicerar testvektorer för den. Så den implementeras här: cirka två hundra rader mot crypto/hmac och net/http, med inga nya beroenden och ingenting att patcha när SDK har en rådgivare.
Vad detta medvetet inte gör
Ingen multipart-uppladdning, inga omförsök av egen, ingen autentiseringskedja utöver statiska nycklar och standardmiljövariabler. Ett HL7-meddelande är kilobytes, så multipart löser ett problem som detta inte har; motorn försöker redan om; och en instansrollautentiseringskedja skulle innebära IMDS-samtal, cachelogik och uppdateringslogik, vilket är där en liten implementering slutar vara liten. Om någon behöver dessa, är det ärliga svaret en fildestination och en synkverktyg, inte en halvfärdig SDK.
Det fungerar med allt som talar S3-API - MinIO, Ceph, Wasabi, Backblaze - eftersom det bara är signerad HTTP. Det är en bieffekt som är värd att ha, eftersom ett sjukhusobjektbutik ofta inte är AWS.
Source: github.com/biodream-llc/perfuse/internal/s3put
26.85 saml
Exklusiv XML-kanonisering (exc-c14n) enligt https://www.w3.org/TR/xml-exc-c14n/
Detta är den exakta kanoniska formen som en XML-signatur signerar. Att göra fel innebär att giltiga signaturer verkar ogiltiga och - värre - en implementering som får det mesta rätt kommer att passera i test mot sina egna signaturer medan den avvisar riktiga IdP-svar.
Reglerna som är viktiga för SAML: - Namnutrymmesdeklarationer renderas endast om de synligt används av elementet eller dess attribut. - Ärvda namnutrymmen som ett element använder men inte deklarerar renderas som om de deklarerats på det elementet. - Attribut sorteras: namnutrymmesdeklarationer först (sorterade efter prefix), sedan andra attribut (sorterade efter utökad namn: namnutrymmes-URI sedan lokal namn). - Tomma element använder start-tag/slut-tag, aldrig självstängande. - Textnoder skrivs ut oförändrade; CDATA ersätts av dess innehåll med enhetsescapning. - Bearbetningsanvisningar och kommentarer utanför dokumentelementet utesluts.
Source: github.com/biodream-llc/perfuse/internal/saml
26.86 scim
Paket scim implementerar SCIM 2.0, det protokoll som identitetsleverantörer använder för att etablera konton.
Okta, Entra ID, Google Workspace och OneLogin talar alla detta språk. En administratör lägger till någon i en grupp i identitetsleverantören, och inom en minut dyker ett konto upp här med rätt roll. De tar bort dem, och kontot försvinner.
Avregistrering är punkten
Etablering är bekvämlighet. Avregistrering är anledningen till att detta är värt att bygga, och det är den del som går fel.
När någon lämnar en organisation är identitetsleverantören det system som vet först - vanligtvis för att HR avslutar dem och leverantören drivs från HR-posten. Det meddelar sedan varje ansluten applikation att inaktivera kontot. Om samtalet misslyckas eller lyckas utan att faktiskt ta bort åtkomsten behåller en tidigare anställd arbetsåtkomst till en klinisk integrationsmotor och ingen upptäcker det, eftersom ingenting övervakar något som inte hände.
Så de delar av detta paket som betyder mest är de som gör avregistrering verklig:
- Att ställa in active till false avslutar varje session omedelbart, inte vid nästa utgång. En webbläsartabb som lämnats öppen på en bärbar dator som har tagits hem av en avslutad anställd måste sluta fungera, och en session som överlever tills den går ut är en session som överlever avskedandet. - Ett fel är ett fel. SCIM har inga återförsökssemantik som en applikation kan lita på, så att returnera 200 för något som inte hände betyder att identitetsleverantören registrerar avregistreringen som slutförd och aldrig försöker igen. - Att ta bort en användare behandlas på samma sätt som att inaktivera: åtkomsten upphör. Revisionshistorik behålls oavsett, eftersom en post som namnger någon som inte längre existerar är värre än en som markeras som tillbakadragen.
Varför det är ett separat paket
SCIM:s former är inte Perfuse:s. Det har sitt eget felformat, sin egen lista omslag, sitt eget språk för korrigering och sina egna åsikter om attributskapitalisering. Att hålla översättningen på en plats betyder att hanterarna kan handla om vad som händer med ett konto snarare än om JSON.
Source: github.com/biodream-llc/perfuse/internal/scim
26.87 skript
Paketskript kör Mirth Connect JavaScript.
Målet är att en kanals skript flyttas över utan att röras. Det är en kompatibilitetsövning, inte en designövning, så formen på allt här dikteras av vad Mirth exponerar: msg och tmp som E4X-träd, sex kartor med Javas Map-metoder, $-familjen av sökfunktioner, logger och ett antal hjälpobjekt vars metodnamn och datumformatsträngar är Javas.
Tre beslut är våra snarare än Mirth:s, och var och en är en medveten avvikelse:
Ett skript körs med en deadline och avbryts när den passerar. Mirth låter ett skript loopa för evigt, vilket tar kanalen med det; ett gränssnitt som slutar acceptera inlämningar på grund av en skrivfel i en transformer är inte acceptabelt, så det finns alltid en tidsgräns.
Java-samverkan vägras med ett fel som namnger klassen, snarare än att returnera undefined. Ett skript som når in i Packages.java.sql kan inte göras att fungera här, och det användbara resultatet är ett meddelande som exakt säger det på den raden där det händer, inte ett NullPointerException tre rader senare.
Fil- och databasåtkomst är avstängd om inte en kanal slår på dem. Mirth beviljar båda till varje skript som standard. En transformer som kan läsa vilken fil processen kan läsa är en rimlig sak att vilja ha och en orimlig standard.
Source: github.com/biodream-llc/perfuse/internal/script
26.88 inställningar
Paketinställningar är den enda beskrivningen av allt om en Perfuse-server som en operatör kan ändra.
Varför det här finns
Innan detta paket var det ungefär trettio saker som var kommandoradsflaggor och ingenting annat. Att ändra hur länge meddelanden behålls innebar att redigera en tjänstdefinition och starta om, vilket på ett sjukhus innebär en ändringsticket - så i praktiken ändrade ingen dem, och en standard som valdes på den första eftermiddagen blev inställningen för alltid.
Varför en register snarare än en form
Det uppenbara sättet att bygga en inställningssida är att skriva formuläret. Det producerar två beskrivningar av varje inställning - en i servern som validerar den och en i gränssnittet som renderar den - och de glider isär. Glidningen är tyst: ett fält som servern slutade acceptera har fortfarande en kontroll, så någon ställer in det, ser det sparas och det gör ingenting.
Så en inställning deklareras en gång, här, med allt som behövs för att både kontrollera den och rita den: vilken typ av värde det är, vilken kontroll som passar den, vilken grupp den tillhör, vad den betyder och om ändringen träder i kraft nu. Gränssnittet ber om den beskrivningen och renderar vad den än blir tillsagd. Att lägga till en inställning är en post i detta paket och ingen gränssnittsarbete alls.
TestEverySettingIsFullyDescribed tvingar fram de delar som en människa måste tillhandahålla, eftersom en inställning utan hjälptext är en inställning som någon gissar på.
Varför en fil snarare än databasen
Inställningar bor i en YAML-fil som gränssnittet redigerar på plats, vilket matchar hur kanaler och varningsregler redan fungerar. Tre skäl, i ordning av vikt: ett sjukhus ändringskontroll vill ha konfiguration som kan diffas och läggas i versionskontroll; en operatör med maskinen men inte applikationen kan läsa en fil och kan inte läsa en databas; och att återställa gårdagens inställningar bör inte kräva att applikationen fungerar.
Varför flaggor bara såddar den
Filen vinner så snart den existerar, och flaggor tillhandahåller den initiala innehållet. Alternativet - flaggor som alltid vinner - skulle göra gränssnittet till en lögnare, eftersom allt som någonsin skickas på en kommandorad kan redigeras och sparas och tyst ignoreras.
En flagga som inte överensstämmer med filen rapporteras vid start, med båda värdena, eftersom annars flaggan förblir i tjänstedefinitionen i år och nästa person som läser den tror att den är korrekt.
Source: github.com/biodream-llc/perfuse/internal/settings
26.89 sftpconn
Paketet sftpconn öppnar SFTP-anslutningar.
Utbrutet från anslutningarna eftersom den intressanta delen är autentisering och värdnyckelverifiering, och båda är identiska oavsett om en kanal samlar in filer eller skriver dem. Två kopior skulle glida isär, och den del som glidit isär skulle vara den del som slutade verifiera.
Source: github.com/biodream-llc/perfuse/internal/sftpconn
26.90 skugga
Paketet shadow jämför en kandidatkanal med den aktiva.
Jämförelsen i sig är den lätta delen. Hela värdet ligger i två garantier, och båda är påtvingade av konstruktionen snarare än av konfigurationen:
- En shadow kan inte leverera. Den innehåller en transformations pipeline och inga avsändare, så det finns ingen kodväg från här till en mottagare. En inställning kan inte skapa en och ett misstag kan inte aktivera en. - En shadow kan inte påverka den aktiva kanalen. Den anropas efter att det aktiva meddelandet har levererats och bekräftats, dess panikåtgärder har återhämtats, och dess tidsgränser är dess egna.
Allt mindre än så och shadow-läge blir ett sätt att bryta produktionen medan man försöker undvika att bryta produktionen.
Source: github.com/biodream-llc/perfuse/internal/shadow
26.91 shl
Paketet shl implementerar SMART Health Links och SMART Health Cards: QR-koderna som CMS "Kill the Clipboard" ber leverantörer att acceptera vid incheckning, och att lämna tillbaka med besöksrekordet.
En SMART Health Link (SMART Health Links STU 1) är shlink:/ följt av base64url JSON: en manifest-URL, en 256-bitarsnyckel och valfritt ett utgångsdatum, en etikett och flaggor (P passkod, L långsiktig, U en enda fil via GET). Mottagaren skickar till manifest-URL:en och får tillbaka filer, var och en krypterad med den nyckeln - alg dir, enc A256GCM, valfritt DEFLATE-komprimerad - som innehåller FHIR JSON, SMART Health Cards eller en SMART-åtkomsttoken. Servern som värd för filerna ser aldrig nyckeln: den reser endast i länken, som är patientens.
En SMART Health Card (SMART Health Cards Framework 1.4) är en signerad FHIR-samling: en kompakt JWS, ES256, med en DEFLATE-komprimerad nyttolast som namnger dess utfärdare, vars offentliga nyckel finns på <iss>/.well-known/jwks.json. Den reser som en numerisk shc:/ QR-kod eller en .smart-health-card-fil.
Endast standardbiblioteket: crypto/aes, crypto/cipher, crypto/ecdsa och compress/flate täcker allt, och ett JOSE-bibliotek skulle medföra en mycket större yta för två algoritmer.
Source: github.com/biodream-llc/perfuse/internal/shl
26.92 smartauth
Paketet smartauth är en SMART App Launch-autentiseringsserver: den utfärdar åtkomsttoken som Perfuses FHIR-slutpunkt accepterar.
Skriven mot standardbiblioteket, som internal/oidc, som verifierar vad den här undertecknar. Token är JWT:er signerade RS256, den enda algoritmen som varje SMART-klient och specifikationens ID-tokenregler kan lita på.
Source: github.com/biodream-llc/perfuse/internal/smartauth
26.93 snmp
Paketet snmp är en liten, skrivskyddad SNMPv2c-agent: GET, GETNEXT och GETBULK över UDP mot en tabell med värden som anroparen fyller i, och SNMPv2-fällor.
Meddelanden är BER (X.690) kodade här; ingenting i det är kryptografi (v2c:s community-sträng är en ren textlösenord, vilket är varför agenten endast svarar på de nätverk den har informerats om).
Source: github.com/biodream-llc/perfuse/internal/snmp
26.94 soap
Paketet soap skickar SOAP-förfrågningar och läser SOAP-fel, med endast standardbiblioteket.
SOAP är en hel del ceremoni runt en HTTP-POST, och det är fortfarande hur en stor del av sjukhusens mellanprogram accepterar data - patientadministrativa system, dokumentarkiv, regionala journaltjänster, allt som specificerats under det årtionde då detta var svaret. Mirth har en Web Service-anslutning, så detta är en Tier 2-migrationsblockerare snarare än en trevlig-att-ha.
Varför inte en genererad klient
Det vanliga tillvägagångssättet är att ta en WSDL och generera Go-typer från den. Det är det rätta svaret för ett program som pratar med en känd tjänst, och det felaktiga svaret här: en integrationsmotors destination konfigureras av någon som redigerar en kanal, inte omkompilera, så omslaget måste sättas samman vid körning från en mall som de kan se och ändra. Det innebär också att det inte finns något kodgenereringssteg och ingenting att regenerera när den avlägsna änden publicerar en ny WSDL.
Vad detta medvetet inte gör
Ingen WSDL-parsing, ingen WS-Säkerhet, ingen MTOM, ingen WS-Addressing. Var och en av dessa är en specifikation i sig, och att låtsas stödja en av dem medan man får en detalj fel är värre än att inte erbjuda den alls - en signatur som nästan verifierar är inte att skilja från en attack i den andra änden. WS-Säkerhet i synnerhet är där en halvimplementering skulle kunna göra verklig skada.
Vad som finns här: SOAP 1.1 och 1.2-omslag, en mallbaserad kropp, SOAPAction-huvudet och felidentifiering som läser felsträngen snarare än att rapportera "500".
Source: github.com/biodream-llc/perfuse/internal/soap
26.95 sof
Paketet sof kör SQL på FHIR v2 ViewDefinitions: en vy omvandlar varje FHIR-resurs av en typ till rader med namngivna kolumner, med FHIRPath, så att FHIR-data kan läsas som tabeller av SQL-motorer, kalkylblad och kvalitetsmått.
Det följer ViewDefinitionens bearbetningsalgoritm (kolumn, välj, forEach, forEachOrNull, upprepa, unionAll, där, konstanter, %rowIndex, getResourceKey och getReferenceKey) och kontrolleras mot de officiella sql-on-fhir-testfixturerna.
Source: github.com/biodream-llc/perfuse/internal/sof
26.96 sqldb
Paketet sqldb öppnar databasanslutningar för databaskällan och målet.
Drivrutinerna registreras här och ingen annanstans, så det finns exakt en plats som bestämmer vad Perfuse kan ansluta till.
Source: github.com/biodream-llc/perfuse/internal/sqldb
26.97 sqlitedb
Paketet sqlitedb öppnar SQLite på det sätt som en server behöver: en anslutning för skrivningar och flera för läsningar.
Anledningen är ett feläge som bara uppträder när en distribution har varit igång en stund. SQLite i WAL-läge låter läsare köra bredvid en skrivare, men Go:s anslutningspool sitter ovanpå SQLite, så en pool med en serialiserar allt oavsett vad databasen skulle tillåta. En meddelandesökning som skannar payload-kolumnen håller då den enda anslutningen, och varje ankommande meddelande väntar bakom den.
Mätt på den här maskinen tar en skrivning 104 µs när lagret är inaktivt och 2,6 ms medan en sökning skannar fyra tusen meddelanden: tjugo gånger långsammare. Det skalar med tabellen, så vid ett par hundratusen lagrade meddelanden blir en rapport flera sekunders leveransfördröjning, och en skrivning är på bekräftelsevägen. Avsändaren ser en tidsgräns, skickar om och någon tillbringar en morgon med att leta efter ett problem i nätverket.
Att dela poolerna kostar ingenting och tar bort interaktionen: rapporter får sina egna anslutningar, och skrivaren behåller en för sig själv eftersom SQLite tillåter exakt en skrivare ändå.
Source: github.com/biodream-llc/perfuse/internal/sqlitedb
26.98 steg
Declarativa transformationssteg för valfri meddelandeformat.
Varför detta är delat
Stegvokabulären - ange, kopiera, rensa, mappa, ersätta, trimma, fall, var och en med en beskrivning och ett valfritt villkor - har ingenting att göra med något särskilt format. Bara tre saker skiljer sig mellan format: hur en sökväg skrivs, hur ett värde läses och hur det skrivs tillbaka.
Detta är samma slutsats som filtergrammatiken nådde i internal/expr, och av samma anledning. X12 hade en stegmotor och NCPDP behövde en; att kopiera den skulle ha producerat en andra fyrahundra-radiga motor att hålla i takt för hand, och sedan en tredje för avgränsade. Det beteende som är värt att ha är tillräckligt subtilt för att en kopia inte skulle ha behållit det - anledningen till att resultatet läses om efter varje skrivning, till exempel, tog ett riktigt fel att upptäcka.
Vad ett format tillhandahåller
En åtkomst: en sökvägskompilator, en villkorskompilator och ett valfritt veto mot steg som det inte kan hedra. Ingenting annat.
Source: github.com/biodream-llc/perfuse/internal/steps
26.99 stomp
Paketet stomp talar STOMP 1.2 till en meddelandebroker.
Detta är vad "JMS-stöd" måste betyda i ett program som inte är Java. JMS är ett API snarare än ett protokoll, så det finns ingenting att implementera: vad en webbplats faktiskt behöver är att Perfuse pratar med brokern som sitter bakom deras JMS-applikationer.
STOMP snarare än OpenWire, och resonemanget är värt att spela in eftersom det uppenbara svaret är fel. OpenWire är ActiveMQ:s ursprungliga protokoll och en binär serialisering av JMS-kommandon - veckor av arbete, specifikt för en brokerfamilj, och odokumenterad utom genom sin implementering. ActiveMQ automatiskt upptäcker STOMP, AMQP och MQTT på samma port som den betjänar OpenWire på, så en textbaserad protokoll når samma brokare. STOMP täcker ActiveMQ Classic, Artemis och RabbitMQ; AMQP 1.0 skulle lägga till Azure Service Bus och IBM MQ, och är det rimliga nästa steget snarare än OpenWire.
Skriven mot standardbiblioteket. En brokerklient är inte platsen för en beroende vars feläge är någon annans att förklara, och ramverket här är tillräckligt litet för att äga det kostar mindre än att läsa deras issue-spår.
Source: github.com/biodream-llc/perfuse/internal/stomp
26.100 lagringsutrymme
Paketlagringsutrymmet innehåller de data som verkligen är tillståndskänsliga: användare, sessioner och en revisionshistorik.
Kanaler är medvetet inte här. De finns i filer, eftersom det är vad som ger git, diff, kodgranskning och miljöfrämjande för frihet. Att lägga kanaler i en databas är beslutet som tvingar var och en av dem att köpas separat, och det är anledningen till att en tredjepartsprodukt finns enbart för att transportera Mirth-kanaler mellan dess databas och ett git-repo.
Så splittringen är: konfiguration i filer, identitet och historia i SQLite.
Source: github.com/biodream-llc/perfuse/internal/store
26.101 tefca
Paketet tefca implementerar de delar av TEFCA-deltagande som inte kräver en QHIN-anslutning.
Vad som är verkligt
Syfte-validering, konfigurationsvalidering och revisionshistoriken - inklusive dess beständighet, dess frågegränssnitt och dess skyldighet att spara misslyckade försök samt lyckade. Den sista delen är inte en tekniskitet: en serie misslyckade leveranser till en mottagare är hur en felkonfigurerad partner visas, och en serie misslyckade frågor för olika patienter är hur sondering visas.
Vad som inte är
Nätverket. Det finns ingen QHIN-transport i den här versionen, så ingen utbyte sker, och varje utbytesfunktion vägrar med ErrExchangeNotImplemented i stället för att returnera framgång.
Den distinktionen drogs inte alltid, och hur det gick fel är värt att behålla. Alla fyra utbytesfunktioner validerade tidigare sina indata, gjorde inga nätverksanrop och returnerade framgång; Deliver returnerade ett accepterat svar med ett spårnings-ID byggt från klockan. Revisionslagret spelade sedan in var och en som en slutförd utbyte - i loggen som finns för att bevisa vad som utbyttes när någon frågar månader senare. Fyra tester påstod att beteende och passerade.
Vad som krävs för att slutföra det
Onboarding med en kvalificerad hälsouppgiftsnätverk, ömsesidigt autentiserad TLS med certifikat utfärdade genom den processen, och antingen IHE-profiler som den gemensamma överenskommelsen började med eller faciliterad FHIR enligt Sequoia Projects standardprocedur, giltig från och med den 8 mars 2026. Inget av det kan skrivas spekulativt: det testas mot ett riktigt QHIN eller så testas det inte, och en otestad utbytesimplementering är samma defekt som ingen implementering med en bättre förklädnad.
Source: github.com/biodream-llc/perfuse/internal/tefca
26.102 hyresgäst
Paketet hyresgäst tillhandahåller identitets- och isoleringsregler för multihyresgäst drift.
En HIE, en clearinghouse eller en hanterad tjänsteleverantör kör en motor på uppdrag av många organisationer. Mirth kan inte göra detta - en instans betjänar en organisation, och en MSP slutar med att köra femtio JVM och femtio databaser.
Vad en hyresgäst äger
Dess kanaler, som en katalog med filer. Dess användare. Dess meddelanden, kö, revisionshistorik och FHIR-resurser. Dess måttiketler. Ingenting delas utom processen, lyssnande portar som tilldelats den och plattformsadministratörerna.
Isolering är strukturell, inte ihågkommen
Den farliga felet här är inte en krasch. Det är hyresgäst A som ser hyresgäst B:s meddelanden, vilket är en rapporterbar brott mot sekretessen snarare än en bugg. En design där varje fråga tar en hyresgäst_id-parameter misslyckas första gången någon skriver en fråga och glömmer en, och den frågan ser perfekt ut i granskning.
Så hyresgästen är inte en parameter. Dataåtkomst sker genom en handtag som redan bär den, och det finns inget sätt att nå tabellerna utan en. Att glömma är inte tillgängligt.
Source: github.com/biodream-llc/perfuse/internal/tenant
26.103 terminologi
Paketet terminologi håller publicerade kodsystem (LOINC, SNOMED CT, RxNorm, ICD-10-CM, CPT och lokala) för att titta upp koder, och de värde-mappningstabeller som inte fanns, för att någon ska kunna mappa.
Kodsystemen importeras från filerna som deras utgivare distribuerar. Flera är licensierade (LOINC behöver ett kostnadsfritt konto, SNOMED CT en affiliate-licens, RxNorm en UMLS-licens, CPT en AMA-licens), så ingen levereras med Perfuse: en administratör som innehar licensen laddar upp filen, och Perfuse registrerar vem som importerade den och när.
Source: github.com/biodream-llc/perfuse/internal/terminology
26.104 tlsconf
Paketet tlsconf skapar TLS-konfiguration från filer och beskriver certifikat.
Detta är den kostnadsfria motsvarigheten till en Mirth-tillägg som nu debiteras. Större delen av värdet ligger inte i krypteringen, som bara är några rader, utan i den del som förhindrar att någon distribuerar något som de tror är säkert men inte är: vägran att tyst tala om för att hoppa över verifiering, insistera på att en klientcertifikat faktiskt kontrolleras när en begärs, och tydligt ange när ett certifikat är på väg att gå ut.
Ett utgånget certifikat på en gränssnittsmatare är en riktig sjukhusdriftstörning, och det händer för att ingen informerades. Den beskrivande delen av detta paket finns av den anledningen.
Source: github.com/biodream-llc/perfuse/internal/tlsconf
26.105 tomirth
Paketet tomirth skriver ut en Perfuse-kanal som Mirth-kanal-XML.
Varför detta finns. Invändningen mot att anta en ny integreringsmotor är sällan "är den bra". Det är "vad händer om vi har fel och är fast", och det billigaste svaret på det är att kunna gå tillbaka ut. Perfuse har läst Mirths kanaler från början; tills nu kunde den inte skriva ut en, vilket gjorde försäkran enkelriktad och därför inte särskilt mycket av en försäkran.
Hur det undviker fällan som gjorde det första försöket värdelöst. Mirths XML är XStreams utdata, och XStream läser klass- och versionsattributen som instruktioner: ett element som den inte känner igen släpps utan ett ord, och en kanal som den inte kan montera sparas med dess beskrivning ersatt av "Denna kanal är ogiltig. Verifiera att alla obligatoriska tillägg är korrekt laddade" och dess destinationer kastas. Ingenting i det svaret namnger det felaktiga elementet. En exporterare som komponerar egenskapsblock från en läsning av formatet misslyckas därför på det sätt som är dyrt att diagnostisera, vilket är vad som hände: detta repository bar en exporterare med nio passerande tester vars utdata Mirth kastade, eftersom varje test jämförde det mot vår egen parser istället för en server.
Så inga av egenskapsblocken komponeras här. scripts/mirth-dump-connector-templates.sh har Mirths egen ObjectXMLSerializer serialisera standardvärdena för varje anslutningsegenskapsklass, och dessa dokument är åtaganden under templates/. Detta paket ersätter värden i dem, och mirth.SetRawProperty vägrar varje sökväg som mallen inte redan innehåller - så ett misstag är ett fel som namnger sökvägen, vid exporttillfället, snarare än en kanal som försvinner vid import.
Vad det inte kommer att göra. En transport med ingen Mirth-motsvarighet vägras med namn snarare än approximeras. En export som tyst förvandlar en S3-destination till en filskrivare vore värre än ingen export alls, eftersom kanalen skulle importeras renligt och leverera till fel plats.
Source: github.com/biodream-llc/perfuse/internal/tomirth
26.106 trace
Paketet trace producerar distribuerade spår för meddelanden som flyttar genom en kanal, och exporterar dem via OTLP/HTTP med JSON-kodning.
Varför detta finns istället för OpenTelemetry SDK: SDK plus en OTLP-exportör drar in ungefär sextio moduler och lägger till lika mycket till binärfilen som hela resten av detta program. Vad som faktiskt behövs här är smalt - W3C-spårkontextpropagering, en spännmodell, huvudsampling och en batchad HTTP-POST - och OTLP/JSON är en dokumenterad stabil kodning som kan produceras med standardbiblioteket ensamt. Samma handel som att välja lib/pq över pgx: ta det lilla när bara en del av det stora behövs.
Konsekvensen som är värd att nämna: det finns ingen auto-instrumentering och ingen leverantörsspecifik exportör. Spänn är de som detta program skapar medvetet, och de går till vilken OTLP-slutpunkt som helst - en insamlare, Jaeger, Grafana Tempo, Honeycomb, Datadog's OTLP-ingest.
Egenskapen som är viktigare än spänn
Ett meddelande anländer ofta med ett traceparent-huvud från systemet som skickade det, och lämnar mot ett system som kommer att spara ett av sina egna. Att fortsätta det spåret snarare än att starta ett nytt är vad som gör en enda vy av "EHR skickade detta, motorn omvandlade det, registret avslog det" möjlig över huvud taget. Gränssnittsproblem rapporteras nästan alltid som "vi skickade det och ingenting hände", och den frågan är obesvarbar utan en identifierare som överlever hoppet.
Spårning får aldrig påverka leverans
Varje operation här är bästa ansträngning. Spänn släpps när bufferten är full, exportfel räknas och återförs aldrig in i meddelandevägen, och inget samtal blockeras av nätverket. Ett släppt spår är ett besvär. Ett meddelande som försenas eller förloras på grund av att spårningsbakänden var långsam är en klinisk incident, så handeln är aldrig ifrågasatt.
Source: github.com/biodream-llc/perfuse/internal/trace
26.107 transform
Paketet transform tillämpar deklarativa ändringar på ett meddelande.
Detta är lagret som är tänkt att bära det vanliga arbetet, med skriptning hålls som en markerad undantagsklausul. Distinktionen är inte stilistisk. Ett steg som deklareras i YAML kan valideras innan det körs, visas i en diff, granskas av någon som inte läser JavaScript, och rapporteras på; ett skript kan bara köras och hoppas om. Det mesta av vad Mirth-omvandlare faktiskt gör är tråkigt - kopiera ett fält, fylla en identifierare, mappa en kod genom en tabell, rensa något som inte ska lämna byggnaden - och allt det hör hemma här.
Varje steg namnger sitt mål explicit och varje steg är reversibelt i den meningen att det säger vad det gjorde, eftersom den dyraste felet i ett gränssnitt är en omvandling som ingen visste var på gång.
Source: github.com/biodream-llc/perfuse/internal/transform
26.108 translate
Paketet translate omvandlar en Mirth-kanal till en Perfuse-kanaldefinition.
perfuse explain rapporterar vad som blockerar en migration. Detta gör större delen av migrationen, som är ett annat och mycket större påstående, så det är medvetet försiktigt med vad det kommer att hävda.
Tre regler formar hela saken.
Ingenting släpps tyst. Varje del av källkanalen är antingen översatt, överförd oförändrad som ett skript eller rapporterad som behöver en människa. En översättare som tyst utelämnar ett steg skulle producera en kanal som startar, körs och förlorar data — det sämsta möjliga resultatet och anledningen till att människor misstror migreringsverktyg.
Declarativt där det är säkert, skript där det inte är. Ett Mapper-steg som kopierar ett fält blir ett deklarativt steg, eftersom det är läsbart och kontrollerbart. Ett JavaScript-steg blir ett skript, eftersom Perfuse kör Mirths JavaScript oförändrat och om skriptet skrivs om till något som ser ut att vara ekvivalent är det exakt där en översättare skulle införa en skillnad som ingen lägger märke till.
Utmatningen är tänkt att läsas. Den innehåller kommentarer som förklarar varifrån något kommer och vad som lämnades för en person. En migration granskas av någon som måste godkänna den, och en oannoterad vägg av YAML kan inte granskas.
Source: github.com/biodream-llc/perfuse/internal/translate
26.109 udap
Paketet udap implementerar klientdelen av HL7-säkerhet för skalbar registrering, autentisering och auktorisering — specifikationen TEFCA:s underlättade FHIR-utbyte vilar på.
UDAP är en offentlig nyckelinfrastruktur som är fäst vid OAuth 2.0. En förtroendegemenskap utfärdar X.509-certifikat till sina medlemmar; en medlem bevisar vem den är genom att signera JWT:er med den privata nyckeln och bifoga certifikatkedjan i JWT-huvudet. Det ersätter den delade klienthemligheten i vanlig OAuth, som inte fungerar för tusentals organisationer som aldrig har träffats.
Varför detta paket existerar över huvud taget. TEFCA-utbyte kan inte fullständigt verifieras utan en riktig QHIN: att gå med i en kräver onboarding och utfärdade certifikat, och kan inte förfalskas. Men säkerhetsprofilen under den är en publicerad HL7-implementeringsguide med offentliga referensservrar, och en av dem svarar på den öppna internet. Så den del som kan verifieras verifieras här, och den del som inte kan det avvisas vid gränsen i stället för att gissas.
Skillnaden är viktig på grund av vad som hände med SAML i detta repository: tusen rader tester passerade, fem av dem specifikt om signaturkanonisering, medan ingen riktig identitetsprovider kunde autentisera någon. Båda halvorna hade skrivits här och överensstämde med varandra. Lektionen som dragits från det är att en säkerhetsimplementering inte är värd något förrän något som någon annan skrivit har accepterat eller avvisat det.
Specifikationsreferenser: - HL7 UDAP-säkerhet STU 1: http://hl7.org/fhir/us/udap-security/STU1/ - TEFCA SOP underlättat FHIR-implementering v2.0, giltig från och med den 8 mars 2026
Source: github.com/biodream-llc/perfuse/internal/udap
26.110 umlink
Paketet umlink transporterar X12 278 till ett betalningsansvarigt systems system för användningshantering och dess svar, de sätt som dessa system nås i praktiken: X12 i kroppen av en HTTPS-POST; CAQH CORE:s SOAP-omslag (Anslutningsregel vC2.2.0, den som de flesta betalare och CMS:er kör esMD, och vC4.0.0); CAQH CORE:s HTTP MIME-mångfaldig omslag (vC2.2.0); och batchfiler via SFTP.
Skriven från CAQH:s publicerade anslutningsregler (vC2.2.0 och vC4.0.0), deras XML-schema och WSDL, och CMS:s esMD X12N 278 Companion Guide. Det är inte CORE-certifierat: certifiering görs av CAQH:s auktoriserade testleverantörer.
De realtidslänkarna returnerar svaret som UM-systemet gav, som kan vara ett 278-svar eller, när det inte kunde läsa begäran, ett 999 eller TA1: anroparen läser vilket. Batchlänken returnerar ErrAnswerLater så snart filen har levererats, och Poll samlar in vad som kommer tillbaka.
Source: github.com/biodream-llc/perfuse/internal/umlink
26.111 v2fhir
Paketet v2fhir mappar HL7 v2-meddelanden till FHIR-resurser.
Mappning är där interoperabilitetsprojekt faktiskt misslyckas, så reglerna som detta paket följer anges snarare än antyds:
- Ett värde som inte kan mappas bevaras som text, aldrig gissat. En lokal kod som omvandlas till en trovärdig standardkod är värre än ett ovärt värde, eftersom mottagaren tror på det. - Varje mappningsbeslut som involverade bedömning rapporteras som en anteckning, så en människa kan kontrollera de som är viktiga i stället för att läsa hela utmatningen. - Tidsstämplar omvandlas, inte kopieras. HL7 v2-tidsstämplar är inte ISO 8601, och en dateTime som bär en lokal tid utan offset är den vanligaste anledningen till att en omvandlad resurs avvisas. - Enheter behåller sin ursprungliga text och får en UCUM-kod endast när mappningen är säker. En felaktig enhetskod är en patientsäkerhetsdefekt, inte ett formateringsproblem.
Source: github.com/biodream-llc/perfuse/internal/v2fhir
26.112 vcs
Paketet vcs läser kanalhistorik från git.
Kanalhistorik är en betald tilläggelse någon annanstans, och det är en betald tilläggelse eftersom dessa motorer håller kanaler i en databas, så spårning av ändringar innebär att bygga ett ändringsspårningssystem. Perfuse håller kanaler i filer, så historiken finns redan och har funnits sedan den första committen. Detta paket behöver bara läsa den.
Det skickar ut till git i stället för att infoga ett git-bibliotek. Biblioteket skulle lägga till en stor beroende till en binär som har fyra, och det skulle inte köpa något: en distribution som håller sina kanaler under versionskontroll har git installerat, och en som inte får en tydlig "inte ett git-repository" i stället för en subtilt annorlunda implementering av samma sak.
Source: github.com/biodream-llc/perfuse/internal/vcs
26.113 vfs
Paketet vfs är den lilla uppsättningen filoperationer som en pollningsanslutning behöver.
Varför ett gränssnitt i stället för fyra anslutningar
Perfuse samlar in filer från en lokal skiva, en SFTP-server, en FTP-server, en Windows-delning och en WebDAV-server. Överföringen skiljer sig i varje fall. Allt som faktiskt bestämmer om meddelanden överlever gör inte:
- En fil som skrivs och en fil som har skrivits färdigt är inte att skilja från varandra. Det finns inget lås, ingen flagga och inga meddelanden på någon av dessa transportmetoder - det finns en storlek och en ändringstid, och båda är sanna för en halvt skriven fil. Att läsa för tidigt samlar in halva meddelandet, och HL7 har ingen avslutare, så halva meddelande är ofta fortfarande parsbart. MSH är intakt, segmenten som anlände är välformade, de som inte gjorde det är enkelt frånvarande. Det accepteras, bekräftas, lagras, levereras och ingenting kommer någonsin att nämna det. - En fil får inte kasseras förrän varje meddelande i den har accepterats, eftersom filen är den enda kopian. - En fil som misslyckades får inte plockas upp igen på nästa omröstning för alltid, och får inte tystas.
Skriven en gång per transport, skulle dessa regler vara subtilt annorlunda fem gånger, och skillnaderna skulle bara visas som meddelanden som försvann på en plats. Så de skrivs en gång, här, över det minsta gränssnittet som stöder dem.
Vad som medvetet inte är här
Ingen skrivning, utöver vad som behövs för att göra sig av med. Att skicka filer är ett annat problem med olika felmoder - en delvis skriven fil i den avlägsna änden, som befintliga avsändare hanterar genom att skriva till ett tillfälligt namn och byta namn. Att kombinera båda riktningarna i ett gränssnitt skulle göra var och en svårare att resonera om.
Ingen rekursion. En omröstare som sjunker ner i underkataloger samlar in arkivkatalogen den precis flyttade en fil till.
Source: github.com/biodream-llc/perfuse/internal/vfs
26.114 vpn
Paketet vpn rapporterar tillståndet för plats-till-plats-VPN-tunnlarna som partnertrafiken körs över - AWS Site-to-Site VPN, Azure VPN Gateway-anslutningar och strongSwan - och behåller varje partners anslutningsschema: båda sidors tunnelinställningar och om de är överens.
En tunnel som är nere ser, från en gränssnittsmotor, exakt ut som en partner vars motor är stoppad: anslutningar går ut. Att säga "tunneln är nere" istället är skillnaden mellan att ringa nätverksteamet och ringa partnern.
Endast läsning. Ingenting här ändrar en tunnel, och ingen fördelad nyckel läses, sparas eller visas någonsin.
Source: github.com/biodream-llc/perfuse/internal/vpn
26.115 web
Paketet web betjänar den byggda frontend från insidan av binärfilen.
Tillgångarna är inbäddade snarare än skeppade bredvid, så distributionen förblir en fil. Det är samma anledning som motorn undviker cgo: en operatör bör kunna kopiera en binärfil till en server och köra den, utan JVM, utan installerare och utan tillgångskatalog som kan komma ur fas med den körbara filen.
Den byggda utmatningen är kommiterad så att go build fungerar på en utcheckning utan Node installerat. Bygg om den med make web.
Source: github.com/biodream-llc/perfuse/internal/web
26.116 webauthn
Paketet webauthn verifierar passnycklar.
En passnyckel är ett nyckelpar som autentiseraren håller - Touch ID, Windows Hello, en YubiKey, en telefon - där den privata halvan aldrig lämnar enheten. Att logga in innebär att servern skickar en slumpmässig utmaning, autentiseraren skriver under den efter att ha kontrollerat att användaren är närvarande, och servern verifierar signaturen mot den offentliga nyckel som lagrades vid registreringen.
Egenskapen som är viktig är inte att det är bekvämt. Det är att det inte finns något att fiska. Ett lösenord kan skrivas in i en övertygande kopia av en inloggningssida; en passnyckelsignatur är bunden till ursprunget som den skapades för, så kopian får en signatur som dess server inte kan använda. För en integrationsmotor som håller en sjukhusgränsyta är det skillnaden som är värd att ha.
Vad denna implementering vägrar att göra
Specifikationen är tillåtande på platser där att vara tillåtande är hur implementationer bryts. Den här är inte:
- Signeralgoritmen är fast vid registrering och lagras med nyckeln. Ingenting vid inloggning läser en algoritm från klienten, eftersom det är algoritmförvirring och det finns ingen funktion här som kunde göra det. - Ursprunget jämförs exakt, aldrig med prefix eller suffix. En kontroll som accepterar allt som slutar med rätt domän accepterar en angriparens underdomän. - En utmaning är engångs- och upphör, och tas bort när den konsumeras, så en fångad påstående inte kan spelas upp. - Attestationen litar inte på någonting. Attestationsuttalandet parsas för att extrahera credentialen och sedan ignoreras dess signatur, eftersom att verifiera den ordentligt behöver en underhållen rotbutik och att låtsas verifiera den är värre än att inte påstå att den gör det. - Signeringsräkningen kontrolleras när autentiseraren tillhandahåller en, och dess frånvaro behandlas inte som misstänkt. Många autentiserare lämnar den legitimitetsligt på noll.
Source: github.com/biodream-llc/perfuse/internal/webauthn
26.117 winservice
Paketet winservice kör Perfuse som en Windows-tjänst.
Den här filen är den överallt-annorstädes-halvan. Den finns så att cmd/perfuse kan anropa det här paketet utan att omge varje anropssida med en byggtagg: underkommandot är alltid komplicerat, och på Linux eller macOS förklarar det att tjänster är en Windows-idé snarare än att misslyckas med att existera.
Att vägra med en tydlig mening är bättre än att dölja underkommandot. Någon som följer Windows-instruktioner på fel maskin får veta vad som faktiskt händer, och motsvarande för deras plattform.
Source: github.com/biodream-llc/perfuse/internal/winservice
26.118 x12
Läsa och skriva värden vid en sökväg.
Varför detta är separat från Sökväg
path.go bestämmer vad en sökvägsuttryck betyder. Den här filen matchar en mot en faktisk växling. Hålls isär eftersom parsningsreglerna är värda att läsa utan hantering av byte, och eftersom parsaren används av konfigurationsvalideraren, som inte har något meddelande att matcha mot.
Varför en skrivning omparsar i stället för att redigera byte på plats
Segment.element är underslices av Segment.raw, och Message.segs indexeras i Message.raw. Att redigera ett värde på plats ändrar längden på allt efter det, så alla dessa slices måste justeras, och alla som missas kommer att läsas korrekt tills det meddelande där det inte fungerar.
Så en skrivning bygger om segmentet, bygger om växlingen och parsar den igen. Det kostar en parsning per ändrat meddelande och köper garantin att ett Message som returneras från här är exakt vad parsning av dess egna byte producerar. Det finns inget tillstånd där index och byte inte överensstämmer, eftersom det tillståndet inte kan representeras.
Source: github.com/biodream-llc/perfuse/internal/x12
26.119 x12xml
Paketet x12xml omvandlar X12 (och andra avgränsade EDI) till och från XML som Mirth Connect och Open Integration Engine skriver för det, och tillbaka.
Varför den XML och inte en av våra egna
Syftet med en XML-form av X12 är system som redan använder en. En plats som flyttar från Mirth har mottagare byggda mot vad Mirths EDI/X12-data typ emitterar, skript som går igenom msg['CLM']['CLM.05']['CLM.05.1'], och uppströms motorer som skickar X12 som den XML. En snyggare form av vår egen skulle inte tjäna någon av dem. Så den skriver exakt vad Open Integration Engine 4.6 skriver, och läser exakt vad den läser, och testerna jämför de två byte för byte mot OIE:s egen serialisator.
En tidigare version av detta paket uppfann sin egen form (en X12Interchange rot, element med namn CLM05) och sa att den matchade Mirth. Den gjorde det inte; den hade aldrig jämförts med Mirth, och ingenting i Perfuse använde den.
The format
Roten är X12Transaction när meddelandet börjar med ett ISA-segment och EDIMessage annars, som bär de tre avgränsarna som attribut (segmentDelimiter, elementDelimiter, subelementDelimiter). Varje segment är ett element med namn efter dess identifierare. Varje dataelement är SEG.NN, numrerad från 01 (ISA.01, CLM.05), och innehåller sina komponenter som SEG.NN.1, SEG.NN.2 och så vidare: alltid minst SEG.NN.1 för ett element med ett värde, inga för ett tomt.
Avgränsarna läses från ISA när det finns ett: elementseparatoren från position 3, komponentseparatoren från position 104 och segmentavslutaren från position 105, med en radmatning efter den räknas som en del av den. Annars är de ~ * och :. Upprepningsseparatoren (ISA11) tolkas inte, vilket är OIE:s beteende också: ett upprepat element behåller sin ^ inom ett värde.
Detta är en omimplementering av beteendet, skriven från att observera OIE:s utdata och från dess dokumenterade format; ingen kod från Mirth är i det.
Source: github.com/biodream-llc/perfuse/internal/x12xml
26.120 xds
Paketet xds är IHE cross-entreprise-dokumentdelning: en XDS.b-dokumentregistrerings- och lagringsplats (ITI-41 Tillhandahåll och registrera, ITI-18 Registrerad lagrad fråga, ITI-43 Hämta dokumentuppsättning), en XCA-svarsgateway över samma lagringsplats (ITI-38, ITI-39) och klientdelen av var och en, så en kanal kan publicera ett dokument till en annan organisations lagringsplats och konsolen kan fråga en registrerings- eller gemenskapsdatabas.
Metadatan är ebXML Registry 3.0 (ebRIM), som XDS.b definierar den i IHE ITI TF-3 kapitel 4. Den modelleras här som Go-strukturer vars XML-taggar bär namnområden, så ett meddelande läses på samma sätt oavsett vilka prefix avsändaren valde, och skrivs namnområdeskorrekt.
Source: github.com/biodream-llc/perfuse/internal/xds
26.121 xmldsig
Paketet xmldsig implementerar XML Digital Signatures och XAdES-profilen av dem.
Varför detta skrivs i stället för att lånas
Ett undertecknat kliniskt dokument är ett juridiskt artefakt. Det hävdar att en namngiven person, vid en namngiven tid, tog ansvar för en specifik uppsättning byte. Att få det fel i antingen riktning är allvarligt: en signatur som inte kan verifieras gör ett giltigt dokument se ut som en förfalskning, och en verifierare som är för generös accepterar ett dokument som någon annan har ändrat.
Kanonisering är hela problemet
XML har många byte sekvenser som betyder samma sak. Attributordning är inte signifikant, namnområdesprefix kan döpas om, tomma element kan skrivas på två sätt och whitespace inuti en tagg är fritt. En signatur är över byte, så innan något hashas måste båda parterna komma överens om exakt en byte sekvens för ett visst dokument. Den överenskommelsen är kanonisering, och det är där implementationer går fel, eftersom varje misstag producerar en signatur som verifierar mot din egen utdata och misslyckas mot alla andras.
Så den här filen är kanoniseringen, på egen hand, med sina egna tester. Ingenting om signering visas här.
Exklusiv i stället för inklusiv, som standard
Inklusiv kanonisering drar in varje namnområdesdeklaration som är i omfång, inklusive de som det undertecknade elementet aldrig använder. Det gör en signatur bryta när dokumentet senare bäddas in i något som deklarerar ett orelaterat namnområde på en förfader, vilket är exakt vad som händer när en CDA placeras i en SOAP-omslag eller en IHE-metadataomslag. Exklusiv kanonisering innehåller endast de deklarationer som elementet faktiskt använder, och det är vad dokumentutbytesprofiler specificerar av den anledningen.
Source: github.com/biodream-llc/perfuse/internal/xmldsig
26.122 xtree
Paketet xtree är ett mutable XML-träd.
Tre mycket olika funktioner måste modifiera XML: HL7-omvandlingar, som Mirth modellerar som XML eftersom det är vad dess skript opererar på; kliniska dokument, som är XML på naturlig väg; och de deklarativa omvandlingsstegen. De delar detta träd i stället för att var och en växer sin egen, eftersom alternativet är tre modeller som inte är överens om vad ett tomt element betyder.
Designmålet är trohet mot E4X-semantik, eftersom Mirth-skript är E4X och hela poängen med att köra dem oförändrade är att de beter sig på samma sätt. Det driver två beslut som annars skulle se konstiga ut: en nod behåller en pekare till sin förälder, eftersom E4X exponerar parent(), och barn är ordnade med tillåtna dubbletter, eftersom en HL7-fältupprepning är bokstavligen ett upprepat element och skript indexeras in i dem efter position.
Source: github.com/biodream-llc/perfuse/internal/xtree
26.123 paket pas
Paketet pas läser Da Vinci Prior Authorization Support (PAS) begäranbuntar.
Det är läsaren som Perfuse eget PAS-server använder, publicerad så att vad som helst som beslutar om en förhandsauktorisation - en betalares regler, ett system för användningshantering, en beslutstjänst som Vaglio - läser en begäran med samma kod, och så samma svar om vad en begäran innehåller. Två läsare av ett meddelandeformat är två åsikter om det.
Det har inga beroenden utanför standardbiblioteket. En begäran hålls som avkodad JSON (map[string]any) i stället för som typade resurser, eftersom en PAS-bunt transporterar vilka stödresurser som helst som leverantören valde att skicka, och en läsare som släppte vad den inte modellerade skulle dölja bevis från beslutet.
req, problems := pas.Läs(bundle, false) om len(problems) > 0 { // vägra: begäran kan inte besvaras korrekt } för _, svc := range req.Tjänster() { // svc.Koder, svc.Artikel, och req.Lös för allt som artikeln hänvisar till }
Source: github.com/biodream-llc/perfuse/pas
27 Index över konfigurationsnycklar
Varje nyckel i bokstavsordning, med de block den kan förekomma i. En nyckel som förekommer i flera block betyder samma sak i var och en; där den inte gör det, dokumenteras blocken separat och skillnaden anges där.
27.1 Alla nycklar
| Nyckel | Visas i |
|---|---|
access_key_id | AWS-åtkomst, FHIR-autentisering, S3-mottagare |
account | Azure Blob-åtkomst |
ack | HTTP-källa, SOAP-källa, Källa |
ack_sender_id | X12-alternativ |
ack_sender_qualifier | X12-alternativ |
acknowledge | EDIFACT-alternativ, HL7v3-alternativ, X12-alternativ |
acks | Kafka-mottagare |
action | SOAP-mottagare |
addr | AMQP-anslutning, Broker-mottagare, Broker-källa, MQTT-anslutning |
address | AMQP-anslutning, DICOM-mottagare, DICOM-frågekälla, Mottagare, Direktadress, TCP-mottagare |
ae_title | DICOM-källa |
after_query | Databaskälla |
after_read | Azure Blob-källa, Direkt IMAP, E-postkälla, Filövervakning, GCS-källa, S3-källa, SFTP-källa |
allow | Skript |
allow_clear_password | FTP-mottagare |
allow_unencrypted | AS2-partner, PGP-mottagning |
allow_unsigned | AS2-partner |
allowed_calling_ae | DICOM-källa |
allowed_senders | E-postkälla |
amqp | Mottagare, Källa |
anchors_file | Direktadress |
api_version | IBMMQ-anslutning |
append | Mottagare, SFTP-mottagare |
application | Bekräftelse |
armor | PGP-avsändare |
arrives_as | X12-alternativ |
as2 | Mottagare, Källa |
attach | SMTP-mottagare |
attach_name | Direktmottagare, SMTP-mottagare |
attachment_names | E-postkälla |
attachments | Kanal |
attempts | Återförsök |
auth | FHIR-mottagare, PAS-mottagare |
authorities | MPI-mottagare |
azure_blob | Mottagare, Källa |
backoff | Kökonfiguration, Återförsök |
base64 | SOAP-källa |
batch_size | Databaskälla, Filövervakning |
baud | Seriell källa |
bcc | SMTP-mottagare |
bearer_token | CDA-mottagare, FHIR-mottagare, HTTP-mottagare, PAS-mottagare |
big_endian | TCP-ram |
blob | Azure Blob-mottagare |
body | SMTP-mottagare, SOAP-mottagare |
broker | Mottagare, Källa |
brokers | Kafka-mottagare, Kafka-källa |
bucket | GCS-åtkomst, S3-mottagare, S3-källa |
bundle_script | FHIR-mottagare |
called_ae | DICOM-mottagare, DICOM-frågekälla |
calling_ae | DICOM-mottagare, DICOM-frågekälla |
cc | SMTP-mottagare |
cda | Mottagare |
cert_file | AS2-mottagare, AS2-partner, AS2-källa, Direktadress |
channel | Mottagare, Skugga |
check_every | Avtalsreferens |
city | ECR-anläggning |
claim_us_core | FHIR-mottagare |
class | XDS-mottagare |
client_ca_file | Direkt XDR |
client_id | E-post OAutentisering, FHIR-autentisering, MQTT-anslutning |
client_secret | E-post OAutentisering, FHIR-autentisering |
code | XDS-kod |
column | Databaskälla |
columns | Avgränsad |
comment | Avgränsad |
commit_after_delivery | Kafka-källa |
compare | Skugga |
compress | AS2-mottagare |
compression | Kafka-mottagare |
config | ELR-mottagare |
container | Azure Blob-åtkomst |
content_type | AMQP-mottagare, AS2-mottagare, Azure Blob-mottagare, Broker-mottagare, GCS-mottagare, HTTP-mottagare, S3-mottagare, XDS-mottagare |
contract | Kanal |
credentials_file | GCP-åtkomst |
dataType | Kanal |
data_bits | Seriell källa |
database | Mottagare, Källa |
decrypt_with | PGP-mottagning |
default_identifier_system | FHIR-mottagare |
delimited | Kanal |
delimiter | Avgränsad, TCP-ram |
deploy | Skript |
description | Kanal |
destination | Broker-mottagare, Broker-källa |
destinations | Kanal |
dicom | Kanal, Mottagare, Källa |
dicom_query | Källa |
dicomweb | Mottagare, Källa |
dir | CDA-mottagare, Mottagare, Dokumentmottagare, FTP-mottagare, Filövervakning, SFTP-mottagare, SFTP-källa |
direct | Mottagare, Källa |
direct_from | XDS-mottagare |
direct_to | XDS-mottagare |
display | XDS-kod |
dns | Direktmottagare |
document | Mottagare |
domain | SMB-källa |
driver | Databasmottagare, Databaskälla |
dsn | Databasmottagare, Databaskälla |
duplicate_window | AS2-källa |
ecr | FHIR-mottagare |
edifact | Kanal |
element | SOAP-källa |
elr | Mottagare |
email | Källa |
emit_on_first_poll | DICOM-frågekälla |
enabled | Kanal, Mottagare, Kökonfiguration |
encrypt_to | PGP-avsändare |
endpoint | AWS-åtkomst, Azure Blob-åtkomst, GCP-åtkomst, S3-mottagare |
envelope | EDIFACT-alternativ, X12-alternativ |
error_dir | Filövervakning, SFTP-källa |
error_folder | Direkt IMAP, E-postkälla |
error_prefix | Azure Blob-källa, GCS-källa, S3-källa |
expect_reply | TCP-mottagare |
extract | Bilagor |
facility | Bekräftelse, ECR-anläggning |
facility_id | SOAP-mottagare |
facility_type | XDS-mottagare |
fail_on_body | HTTP-mottagare |
fault_is_success | SOAP-mottagare |
fault_on_nak | SOAP-källa |
fhir | Mottagare |
file | Avtalsreferens, Källa |
file_name | AS2-mottagare, Mottagare, Dokumentmottagare, FTP-mottagare, PGP-avsändare, SFTP-mottagare |
file_roots | Skript |
filter | Kanal, Avgränsad, Mottagare, HL7v3-alternativ, Skript |
flow_control | Seriell källa |
follow_redirects | HTTP-mottagare |
follow_symlinks | Filkälla |
font_size | Dokumentmottagare |
format | Dokumentmottagare, S3-mottagare |
framed | Azure Blob-källa, FTP-mottagare, Filövervakning, GCS-källa, S3-mottagare, S3-källa, SFTP-mottagare, SFTP-källa |
framing | TCP-ram |
from | AS2-mottagare, SMTP-mottagare |
from_beginning | Kafka-källa |
ftp | Mottagare, Källa |
gcs | Mottagare, Källa |
group | Kanal, Kafka-källa |
group_by | SNS-mottagare, SQS-mottagare |
has_header | Avgränsad |
header | SOAP-mottagare |
headers | Broker-mottagare, CDA-mottagare, DICO Mweb-mottagare, FHIR-mottagare, HTTP-mottagare, Kafka-mottagare, SOAP-mottagare, XDS-mottagare |
heartbeat | Broker-källa |
hl7v3 | Kanal |
host | Broker-mottagare, Broker-källa, Direkt IMAP, E-postkälla, FTP-mottagare, FTP-källa, SFTP-mottagare, SFTP-källa, SMB-källa, SMTP-mottagare |
hostname | AMQP-anslutning |
http | Mottagare, Källa |
ibm_mq | Mottagare, Källa |
id | AS2-partner, AS2-källa |
id_type | MPI-mottagare |
identifier_systems | CDA-mottagare, FHIR-mottagare |
idle_timeout | DICOM-källa, Källa, TCP-källa |
ignore | Skugga |
imap | Direktkälla |
include | Skript |
include_trigger_event | Bekräftelse |
insecure_skip_host_key_check | SFTP-mottagare, SFTP-källa |
insecure_skip_verify | FTP-mottagare, FTP-källa, SMTP-mottagare, Web DAV-källa |
interval | DICOM-frågekälla |
javascript | Mottagare, Källa |
kafka | Mottagare, Källa |
keep_alive | TCP-mottagare |
keep_blank_lines | Avgränsad |
keep_delimiter | TCP-ram |
key | Azure Blob-åtkomst, Kafka-mottagare, S3-mottagare |
key_column | Databaskälla |
key_file | AS2-mottagare, AS2-källa, Direktadress, SFTP-mottagare, SFTP-källa |
key_passphrase | SFTP-mottagare, SFTP-källa |
known_hosts_file | SFTP-mottagare, SFTP-källa |
landscape | Dokumentmottagare |
language | Skript |
ldap | Direktmottagare |
length_bytes | TCP-ram |
length_includes_header | TCP-ram |
level | DICOM-frågekälla |
limit | DICOM-frågekälla |
line | ECR-anläggning |
listen | AS2-källa, DICO Mweb-källa, DICOM-källa, Direktkälla, Direkt XDR, HTTP-källa, SOAP-källa, Källa, TCP-källa |
login | Broker-mottagare, Broker-källa |
mailbox | Direkt IMAP, E-postkälla |
match | DICOM-frågekälla |
max_attempts | Databaskälla, Kökonfiguration |
max_backoff | Kökonfiguration, Återförsök |
max_bytes | Direktkälla |
max_connections | Källa, TCP-källa |
max_depth | Kökonfiguration |
max_differences | Skugga |
max_file_size | Filövervakning, SFTP-källa |
max_message_size | AS2-källa, E-postkälla, HTTP-källa, Kafka-källa, SOAP-källa, Seriell källa, Källa, TCP-mottagare, TCP-källa |
max_messages | Pub Sub-källa, SQS-källa |
max_object_bytes | DICO Mweb-källa, DICOM-källa |
max_object_size | Azure Blob-källa, GCS-källa, S3-källa |
max_open_conns | Databasmottagare |
mechanism | Kafka SASL |
method | HTTP-mottagare |
move_to | Azure Blob-källa, Direkt IMAP, E-postkälla, Filövervakning, GCS-källa, S3-källa, SFTP-källa |
mpi | Mottagare |
mqtt | Mottagare, Källa |
name | Kanal, Kanalmottagare, Mottagare, ECR-anläggning |
ncpdp | Kanal |
no_compress | PGP-avsändare |
no_merge | MPI-mottagare |
non_persistent | IBMMQ-mottagare |
npi | ECR-anläggning |
oauth | E-postkälla |
object | GCS-mottagare |
on_no_document | CDA-mottagare |
order_by | Pub Sub-mottagare |
over | Avtalsreferens |
overlap | DICOM-frågekälla |
params | Databasmottagare |
parity | Seriell källa |
partner_cert_file | AS2-mottagare |
partners | AS2-källa |
pas | Mottagare |
pass_plain | PGP-mottagning |
passcode | Broker-mottagare, Broker-källa |
passphrase | PGP-mottagning, PGP-avsändare |
password | AMQP-anslutning, AS2-mottagare, DICO Mweb-mottagare, DICO Mweb-källa, Direktmottagare, Direkt IMAP, Direktkälla, E-postkälla, FTP-mottagare, FTP-källa, HTTP-mottagare, IBMMQ-anslutning, Kafka SASL, MQTT-anslutning, SFTP-mottagare, SFTP-källa, SMB-källa, SMTP-mottagare, SOAP-mottagare, SOAP-källa, Web DAV-källa, XDS-mottagare |
path | AS2-källa, DICO Mweb-källa, HTTP-källa, SOAP-källa |
path_style | S3-mottagare, S3-källa |
patient_domain | XDS-mottagare |
patient_root | DICOM-frågekälla |
pattern | Filövervakning, SFTP-källa |
payer | PAS-mottagare |
persistent | Broker-mottagare |
pgp | Mottagare, Källa |
phone | ECR-anläggning |
poll_interval | Azure Blob-källa, Databaskälla, Direkt IMAP, E-postkälla, Filövervakning, GCS-källa, IBMMQ-källa, Java Script-källa, S3-källa, SFTP-källa |
port | Direkt IMAP, E-postkälla, Seriell källa |
postal_code | ECR-anläggning |
postprocessor | Skript |
practice_setting | XDS-mottagare |
prefetch | AMQP-källa |
prefix | Azure Blob-källa, GCS-källa, S3-källa |
preprocessor | Skript |
profile | SOAP-mottagare, SOAP-källa |
project | GCP-åtkomst |
protocol | E-postkälla |
provider | E-post OAutentisering |
pubsub | Mottagare, Källa |
purpose | TEFCA-mottagare |
qos | MQTT-anslutning |
query | Databaskälla |
query_timeout | Databaskälla |
queue | Mottagare, IBMMQ-anslutning |
queue_manager | IBMMQ-anslutning |
queue_url | SQS-mottagare, SQS-källa |
quiet_after | Seriell källa |
quote | Avgränsad |
raw | Filövervakning |
rctc | ECR-mottagare, ELR-mottagare |
read_timeout | HTTP-källa, SOAP-källa |
reassemble | Bilagor |
receipt | AS2-mottagare |
receipt_url | AS2-mottagare |
recipient_certs_dir | Direktmottagare |
reconnect | AMQP-källa, Broker-källa, MQTT-källa, Pub Sub-källa |
record_length | TCP-ram |
refresh_token | E-post OAutentisering |
region | AWS-åtkomst, FHIR-autentisering, S3-mottagare |
reject_on_warning | FHIR-mottagare |
relaxed | Avgränsad |
reopen_after | Seriell källa |
reply | Seriell källa, TCP-källa |
reply_text | Seriell källa, TCP-källa |
request_mdn | Direktmottagare |
require_agreement | CDA-mottagare |
require_signature | PGP-mottagning |
response_element | SOAP-källa |
response_namespace | SOAP-källa |
response_transformer | Mottagare |
results_to | PAS-mottagare, TEFCA-mottagare |
retain | MQTT-mottagare |
retain_hours | Mottagare, Kökonfiguration |
retry | Mottagare |
return | DICOM-frågekälla |
root | FTP-källa, Filkälla, SMB-källa |
s3 | Mottagare, Källa |
sample | Skugga |
sas | Azure Blob-åtkomst |
sasl | Kafka-mottagare, Kafka-källa |
scheme | XDS-kod |
scope | E-post OAutentisering, FHIR-autentisering |
script | Kanal, Java Script-mottagare, Java Script-källa |
scripts | Kanal |
secret_access_key | AWS-åtkomst, FHIR-autentisering, S3-mottagare |
security | Direkt IMAP, E-postkälla, FTP-mottagare, FTP-källa |
selector | Broker-källa |
sender_device | HL7v3-alternativ |
sender_oid | HL7v3-alternativ |
serial | Källa |
server_side_encryption | S3-mottagare |
session_timeout | Kafka-källa |
session_token | AWS-åtkomst, FHIR-autentisering, S3-mottagare |
sftp | Mottagare, Källa |
shadow | Kanal |
share | SMB-källa |
sign_with | PGP-avsändare |
smb | Källa |
smtp | Mottagare |
smtp_host | Direktmottagare, Direktkälla |
sns | Mottagare |
soap | Mottagare, Källa |
sop_classes | DICOM-mottagare, DICOM-källa |
sort_by | Filövervakning |
source | Kanal, ECR-mottagare |
source_id | XDS-mottagare |
split | Avgränsad, EDIFACT-alternativ, X12-alternativ |
sqs | Mottagare, Källa |
ssn_system | MPI-mottagare |
stable_for | Filövervakning, SFTP-källa |
start_block | TCP-ram |
starttls | SMTP-mottagare |
state | ECR-anläggning |
statement | Databasmottagare |
stop_bits | Seriell källa |
storage_class | GCS-mottagare, S3-mottagare |
subject | AS2-mottagare, Direktmottagare, SMTP-mottagare, SNS-mottagare |
subscription | Pub Sub-källa |
subscription_id | Broker-källa |
success_on_undefined | Java Script-mottagare |
success_status | HTTP-mottagare |
suffix | Azure Blob-källa, GCS-källa, S3-källa |
tables | Kanal |
take | E-postkälla |
tcp | Mottagare, Källa |
tefca | Mottagare |
temp_suffix | Mottagare, Dokumentmottagare, FTP-mottagare, SFTP-mottagare |
template | Databaskälla, Dokumentmottagare |
tenant | E-post OAutentisering |
tenant_id | FHIR-autentisering |
text | Direktmottagare |
tier | Azure Blob-mottagare |
timeout | AMQP-anslutning, Broker-mottagare, Broker-källa, DICO Mweb-mottagare, DICOM-mottagare, DICOM-frågekälla, Databasmottagare, Mottagare, Direktmottagare, Dokumentmottagare, FTP-mottagare, FTP-källa, IBMMQ-anslutning, Java Script-mottagare, Java Script-källa, Kafka-mottagare, Kafka-källa, MQTT-anslutning, S3-mottagare, SFTP-mottagare, SFTP-källa, SMB-källa, SMTP-mottagare, SOAP-mottagare, Skript, Skugga, TCP-mottagare, Web DAV-källa, XDS-mottagare |
timezone | FHIR-mottagare |
title | Dokumentmottagare |
tls | AMQP-anslutning, AS2-mottagare, AS2-källa, Broker-mottagare, Broker-källa, DICO Mweb-mottagare, DICO Mweb-källa, DICOM-mottagare, DICOM-frågekälla, DICOM-källa, Mottagare, Direkt IMAP, E-postkälla, HTTP-mottagare, HTTP-källa, IBMMQ-anslutning, Kafka-mottagare, Kafka-källa, MQTT-anslutning, SOAP-mottagare, SOAP-källa, Källa, TCP-mottagare, TCP-källa, XDS-mottagare |
tls_cert | Direktkälla, Direkt XDR |
tls_key | Direktkälla, Direkt XDR |
to | AS2-mottagare, Direktmottagare, SMTP-mottagare |
token | DICO Mweb-mottagare, DICO Mweb-källa, HTTP-källa, SOAP-källa, XDS-mottagare |
token_url | E-post OAutentisering, FHIR-autentisering |
topic | Kafka-mottagare, MQTT-mottagare, MQTT-källa, Pub Sub-mottagare |
topic_arn | SNS-mottagare |
topics | Kafka-källa |
transfer_syntaxes | DICOM-mottagare, DICOM-källa |
transformations | Kanal, DICOM-alternativ, Avgränsad, HL7v3-alternativ, NCPDP-alternativ, Skriptalternativ, X12-alternativ |
transformer | Skript |
trim_padding | TCP-ram |
trim_space | Avgränsad |
type | Mottagare, FHIR-autentisering, Källa |
undeploy | Skript |
unencrypted | AS2-mottagare |
unsigned | AS2-mottagare |
unsigned_receipt | AS2-mottagare |
url | AS2-mottagare, CDA-mottagare, DICO Mweb-mottagare, FHIR-mottagare, HTTP-mottagare, IBMMQ-anslutning, SOAP-mottagare, Web DAV-källa, XDS-mottagare |
user | FTP-mottagare, FTP-källa, SFTP-mottagare, SFTP-källa, SMB-källa, Web DAV-källa |
username | AMQP-anslutning, AS2-mottagare, DICO Mweb-mottagare, DICO Mweb-källa, Direktmottagare, Direkt IMAP, Direktkälla, E-postkälla, HTTP-mottagare, IBMMQ-anslutning, Kafka SASL, MQTT-anslutning, SFTP-mottagare, SFTP-källa, SMTP-mottagare, SOAP-mottagare, SOAP-källa, XDS-mottagare |
validate_before_send | FHIR-mottagare |
verify_with | PGP-mottagning |
version | CDA-mottagare, FHIR-mottagare, SOAP-mottagare, SOAP-källa |
visibility_timeout | SQS-källa |
wait_seconds | SQS-källa |
warnings_are_errors | SOAP-mottagare |
webdav | Källa |
when | Bekräftelse |
window | DICOM-frågekälla |
write | CDA-mottagare |
wsdl | SOAP-källa |
x12 | Kanal |
x12_as | Mottagare |
xdm | Direktmottagare |
xdm_source_id | Direktmottagare |
xdr | Direktkälla |
xds | Mottagare |