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:

Kapitlet om testing och det om migration finns därför att svaret på "varför ska jag lita på detta" måste vara bevis som du samlar in själv, inte ett påstående som görs här.

1.2 Vad som ingår

Allt nedan ingår i den binära filen. Varje rad namnger kapitlet som täcker det.

NCPDP Telecommunication och SCRIPT, SMART Health Links och Cards, avgränsade och råa. Se meddelandeformat.

MQTT, IBM MQ och AWS, Azure och Google Cloud-lagring och meddelandehantering. Se källreferens och destinationsreferens.

mappningstabeller och koduppsättningar, och mappningsförslag. Se filtrering och transformation.

som skickas efter leverans. Se leverans och bekräftelser.

som hittar en patients meddelanden över format. Se varningar, meddelandelagringen och felsökning.

migration.

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.

hyresgäster, en SMART-autentiseringsserver, TEFCA och UDAP, och en revisionslogg. Se säkerhet.

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

StandardVersionKontrollerad
HL7 v2valfri version: meddelanden läses av sina egna avgränsare, inte en versions schema; bekräftelser som standard till 2.5.1NIST HL7 v2-validerare; riktiga Mirth- och OIE-trafik
HL7 v2 till FHIRHL7: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
FHIRR4 (4.0.1), med R4B och R5 som läses och skrivsHL7 FHIR-valideraren; Inferno
C-CDA och CDAC-CDA 2.1ONC SITE (C-CDA-exempel skickade och mottagna via XDR); inte av en CDA-schematron
HL7 v3PIX och PDQ (IHE ITI-44, 45, 47)IHE:s NE2008-scheman och exempelmeddelanden
DICOM och DICOMwebDIMSE C-STORE, C-FIND, C-MOVE, C-GET, C-ECHO; QIDO-RS, WADO-RS, WADO-URI, STOW-RSOrthanc
X12 (HIPAA)005010: 837, 835, 270/271 (X279A1), 276/277 (X212), 834, 278 begäran (X217) och förfrågan (X215); 275 i 006020 (X314)försäkringsgivarnas publicerade kompanjonsguider; CMS esMD-exempel
CAQH CORE-anslutningvC2.2.0 SOAP och MIME, vC4.0.0 med MTOMen stand-in UM-system skriven från CAQH:s regler
NCPDPTelekommunikation D.0; SCRIPT 2023011 (och 2017071) med ePA; Real-Time Prescription Benefit v13skriven från de offentliga Surescripts-kompanjonsguiderna och deras exempel; inte mot NCPDP:s licensierade scheman
UN/EDIFACTsyntax 3 och 4, CONTRLpydifact 0.1.8
IHE-dokumentdelningXDS.b, XCA, XDR, MHD 4.2.2, PIXm, PDQm, XDMNIST XDS Toolkit; ONC SITE
Direkt säker meddelandehanteringTillämpbarhetsuttalande 1.2, XDR och XDM för Direkt, DNS och LDAP-certifikatupptäcktONC SITE; ONC:s Certificate Discovery Tool (18 av 18)
AS2RFC 4130, komprimering RFC 5402pyas2lib
Underskrivna bilagorHL7 DSDR, XAdES-X-Lxmlsec1, OpenSSL

1.3.2 FHIR-implementeringsguider

GuideReleaseKontrollerad
US Corekonverteringar till 9.0.0 (USCDI v6); FHIR-server mot 6.1.0 och 7.0.0HL7-valideraren; Inferno US Core
SMART App Launch2.2Inferno: 80 av 80 (offentlig app)
Bulk Data Access2.0.0Inferno: 48 av 48
Prenumerationer R5 Backportför R4en riktig HTTP-mottagare; PAS-kits varnings tester
Da Vinci CRD2.2.1, och 2.1.0Inferno 2.2.1: 92 pass, ingen misslyckades; 2.1.0 av guidens egna exempel
Da Vinci DTR2.2.0, och 2.1.0Inferno 2.2.0: 43 pass, 2 misslyckades (en kitdefekt); 2.1.0 av guidens egna exempel
Da Vinci PAS2.2.1, och 2.1.0Inferno 2.2.1: 82 av 84; 2.1.0 av guidens egna exempel
Da Vinci PAS, skicka (leverantörssida)2.2.1HL7 Da Vinci PAS betalningsreferensimplementering; inte en produktionsbetalare
Da Vinci PDex2.2.0Inferno PDex 2.0: betalare-till-betalare 19 av 19
Da Vinci HRex $member-match1.2.0Inferno PDex betalare-till-betalare
Da Vinci ATR2.1.0inte kontrollerad av ett externt verktyg
Da Vinci CDex $submit-attachment2.1inte kontrollerad av ett externt verktyg
Da Vinci Plan-Net1.1.0Inferno: 199 pass, 10 misslyckades (en kitdefekt)
Da Vinci US Drug Formulary2.1.0HL7-valideraren
ISiK (tyska sjukhus), FHIR-serverStufe 5, Basis modulgematiks ISiK-testsvit 3.0.9: 421 av 421
PACIO Transitions of Care, Medication Profile, Advance Directives, Functioning1.0.0, 1.0.0, 2.0.0-ballot, 2.0.0PACIOs 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 Button2.2.0HL7-valideraren
eCR2.1.2HL7-valideraren
ELRHL7 2.5.1 ELR Release 1 med dess errataONCs ELR-verktyg: 28 av 28
International Patient Summary2.0.0HL7-valideraren
DEQM5.0.0HL7-valideraren
SQL på FHIRv2det officiella testsviten: 144 av 144
SMART Health Cards och LinksCards 1.4, Links STU 1specifikationernas egna exempelkort; en publicerad SMART Health Links-visningsbibliotek
UDAP SecuritySTU 1en riktig auktoriseringsserver och förtroendesamhälle
TEFCA Facilitated FHIRSOP v2.0inte 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.

ProfilReleaseResurser giltiga
UK CoreSTU2 2.0.2185 av 187
FR Core2.2.0138 av 156
ISiK Basismodul4.0.3 (Stufe 4)18 av 47; 42 av 47 med sjukhusets egen bundle-skript
Nictiz nl-core0.12.1-beta.1 (zib 2020)12 av 24; 18 av 24 med sjukhusets egen bundle-skript
HL7 Europe Laboratory Report2.1.0106 av 426 (guiden förväntar sig ett dokument, ett v2-resultat är inte)
HL7 Europe Hospital Discharge Report1.0.068 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.

Att köra utan -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:

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:

  1. 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.
  2. Från något som redan fungerar. En uppsättning kompletta kanaler som bara behöver sina adresser fyllda i.
  3. 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

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:

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.

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:

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:

DelNyckelObligatoriskVad den gör
IdentitetnamejaNamnger kanalen. Måste vara unik.
DatatypdataTypenejHur meddelanden ska tolkas. Standard är HL7 v2.
KällasourcejaVar meddelanden anländer från. Exakt en.
FilterfilternejBeslutar vilka meddelanden som ska accepteras.
TransformationertransformationsnejOrdning av ändringar i meddelandet.
MåldestinationsjaVar 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.

I en multi-anläggningsdistribution, lägg till anläggningen i namnet istället för endast i gruppen. Mirth-distributioner över flera platser drar ofta till inkonsekvent namngivning, och den punkt då det blir smärtsamt är en incident klockan två på morgonen där kanalisten har fyra saker som heter 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.

En kanal som redigeras i webbgränssnittet skrivs tillbaka till sin fil. Om dessa filer är i versionskontroll — vilket rekommenderas — förvänta dig commits från konfigurationsändringar gjorda genom gränssnittet, och redigera inte en fil samtidigt som någon annan har den öppen i byggaren.

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

Arrival de-frame Parse Record as received Filter Transform Destination A Destination B Destination C unparseable filtered Filtered is a normal outcome, not an error. Unparseable is recorded and stops. The acknowledgement is sent after delivery by default, so a sender is not told "received" before it is true.
  1. 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.
  2. Tolka. Byte blir ett träd enligt kanalens dataType. Ett meddelande som inte kan tolkas slutar här och sparas som ett tolkningsfel.
  3. 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.
  4. 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.
  5. Transformera. Kanalens transformations körs i ordning, var och en mot föregående resultat.
  6. 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.
  7. Spela in resultatet. Per destination: levererat, köat, misslyckat eller filtrerat.
  8. 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.

Under antingen inställning, är en positiv bekräftelse inte ett löfte om att den mottagande applikationen har *bearbetat* meddelandet — endast att den accepterade byte. Om du behöver veta att ett resultat har arkiverats, måste det komma från det mottagande systemet, och ingen integrationsmotor kan tillhandahålla det.

5.4 Var meddelandet spelas in

Innan filtret, och därför innan någon transformation. Tre konsekvenser:

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

StegVad fel ser ut somVad händer
AnkomstRamfel, anslutning stängs mitt i meddelandetSpelas in, anslutning stängs, avsändaren försöker igen
ParsningInte giltig för den deklarerade typenSpelas in som parsningsfel, negativ bekräftelse om källan förväntar sig en
FilterSjälva filtret genererar felHanteras som ett avslag, spelas in med felet
OmvandlingEtt steg misslyckasBeror på stegets on_error; se omvandling
LeveransDestinationen är otillgänglig eller avvisarKö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.

Ordning mellan kanaler är inte alls garanterad. Om två flöden måste tillämpas i en viss ordning i förhållande till varandra, måste den ordningen påtvingas av mottagarsystemet, eftersom ingenting i mitten kan veta vilket av två oberoende anlända meddelanden som hände först.

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

StegVad det gör
setSkriver ett litteralt värde till en sökväg, skapar den om den saknas.
copyKopierar en sökväg till en annan, med ett valfritt standardvärde när källan saknas.
clearTömmar ett fält, lämnar det närvarande.
removeTar bort ett fält helt.
mapSöker upp det aktuella värdet i en tabell och ersätter det.
replaceReguljär uttrycksersättning inom ett fält.
padFyller ett värde till en fast bredd.
dateKonverterar ett datum eller tidsstämpel mellan format.
trimTar bort omgivande blanktecken.
caseKonverterar 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:

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:

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:

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:

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ärdeVad det är
javascriptStandard. Ett osignerat skript är JavaScript.
luaBättre val när ingen migrerar.
wasmBytekoden 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.

En icke-noll utgång betyder att modulen *misslyckades*, vilket inte är samma sak som en filter som bestämmer sig för att avvisa ett meddelande. En filtermodul säger 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: [...]

(kept for the record, används av ingenting).

som börjar samma dag, avvisas när filen läses in.

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.

annars används tabellens.

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:

FormatFilSystem
loincLoinc.csv från LOINC-tabellutgåvanhttp://loinc.org
icd10cmCMS-beställningsfilen (icd10cm_order_*.txt) eller kodfilhttp://hl7.org/fhir/sid/icd-10-cm
rxnormRXNCONSO.RRF från RxNorm-fullutgåvanhttp://www.nlm.nih.gov/research/umls/rxnorm
snomedRF2-beskrivningssnapshot (sct2_Description_Snapshot-en_*.txt)http://snomed.info/sct
snomed-rf2en 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}
clamlen ClaML-fil: WHO ICD-10, ICD-10-GM och OPS (BfArM), CIM-10 FR (ATIH)från filens titel, eller det angivna system
icd11WHO ICD-11 MMS enkel tabulering (tab-separerad, med Code och Title-kolumner)http://id.who.int/icd/release/11/mms
csvvalfri 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:

den sparas, och koder som inte finns i systemet listas på utgåvan;

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:

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ärdeFormat
hl7HL7 v2, den pipe-avgränsade standarden. Standardvärdet.
hl7v3HL7 v3 och CDA-dokument, som är XML.
x12ASC X12, används för behörighet och anspråk.
ncpdpNCPDP Telecommunication Standard D.0 apoteksanspråk.
scriptNCPDP SCRIPT, elektroniska recept. XML.
dicomDICOM-bilder.
delimitedCSV och andra avgränsade texter.
rawInga 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.

När någon skickar dig ett exempel och den kanal som skapats från det producerar nonsens, kontrollera avgränsarna innan allt annat. Begär en vanlig textbilaga snarare än ett meddelande som klistrats in i ett e-postmeddelandes brödtext.

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:

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ärdeBeteende
requireVägra utbytet. Standardvärdet.
warnBearbeta det och registrera felet mot meddelandet.
ignoreKontrollera 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.

TransaktionVad den innehåller
835Betalningsinformation: vad som betalats, vad som nekats och anledningarna till justeringar.
275Anspråksbilagor: klinisk dokumentation som stödjer ett anspråk.
277Anspråksstatus, inklusive en betalares begäran om ytterligare dokumentation.
278Tidigare auktorisation: begäran om granskning och betalarens beslut.
999Funktionsbekräftelse, som Perfuse också genererar.
271Försäkringsberättigande: om en patient är försäkrad och deras egenavgift, självrisk, friskrivningsbelopp och utbetalningsbelopp, inom och utanför nätverket.
834Registrering: medlemmar som lagts till, ändrats och avslutats, med varje försäkringslinje och dess datum.
837Ansprå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ändeVad det betyderVad man ska göra
HCR med åtgärd A3Betalaren övervägde begäran och kommer inte att certifiera den.Överklaga, eller ändra vårdplanen.
Ett AAA-segmentBetalaren 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:

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 felVar 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.

Ett dokument inuti en 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.

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.

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.

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:

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.

v2FHIR
ADTPatient, 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.
ORUDiagnosticReport 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, OMGServiceRequest.
SIUAppointment, med patienten, praktikerna från AIP och platserna från AIL.
MDMDocumentReference som innehåller dokumentet.
VXUImmunization, 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.

Dokument. Textanteckningar (TX, FT, ST) behåller sina radbrytningar, inklusive tomma rader, eftersom en tom upprepning i en anteckning är en paragrafbrytning.

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.

Besvärlig indata. Var och en av dessa rapporteras i anteckningarna snarare än beslutas tyst:

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.

annan händelse, såsom en A08, sammanfogas ingenting och en varning säger att den tidigare identifieraren fortfarande är aktiv.

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.

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".

smaken UNK, eftersom R4 kräver en klass.

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 v6FrånSom
PatientdemografiPIDNamn, 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ötessinformationPV1Möte med typ, klass, period, plats och deltagare
AnläggningsinformationPV1-3Plats, med anläggningen som dess ledande organisation
Problem, datum för debutDG1Tillstånd (mötessdiagnos). DG1-5 är debut, som HL7 v2-till-FHIR-kartan har det
Allergier och intoleranser, reaktionAL1AllergyIntolerance med kategori, kriticitet och reaktion
LaboratoriumORUDiagnosticReport, Observationer, Specimen (från SPM), ServiceRequest
OrdrarORM, OMLServiceRequest
VaccinationerVXUImmunization
Kliniska anteckningarMDMDocumentReference
VårdteammedlemmarPV1, TXA, DG1Praktiker

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:

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".

Å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.

Tre sätt att skapa en:

Bundle endpoint (url), or writes <document>.transfer.json to dir. In the channel builder: Emit › A PACIO transfer summary.

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:

ÄmneUtlöser påFilter
https://perfuse.health/fhir/SubscriptionTopic/encounterMöte skapat eller uppdateratpatient, status, class
https://perfuse.health/fhir/SubscriptionTopic/appointmentTidbokning skapat eller uppdateratpatient, 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:

Vad en klient kan göra servern att göra är avsiktligt begränsat:

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:

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.

NCPDP- och SCRIPT-kanaler är undantagna från MLLP-ramning, och detta är påkraftat snarare än rådet. Ett krav innehåller legitimt 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)

AdressAktörTransaktioner
/xds/repositoryDokumentarkivITI-41 Tillhandahåll och registrera dokumentuppsättning-b, ITI-43 Hämta dokumentuppsättning
/xds/registryDokumentregisterITI-18 Registerlagrad fråga (alla tretton lagrade frågor), ITI-42 Registrera dokumentuppsättning-b
/xca/gatewayXCA-svarsgatewayITI-38 Gateway-fråga, ITI-39 Gateway-hämta, med -xds-home-community urn:oid:...
/mhdMHD-dokumentmottagare och -svarareITI-65 Tillhandahåll dokumentpaket, ITI-66 Hitta listor, ITI-67 Hitta dokumentreferenser, ITI-68 Hämta dokument
/mhd/PatientPDQm-leverantör och PIXm-hanterareITI-78 Patientdemografisk fråga, ITI-83 Patient/$ihe-pix, från FHIR-lagrets patienter
/pixv3PIX-hanterare (HL7 v3)ITI-44 Patientidentitetsflöde HL7 V3, ITI-45 PIXV3-fråga, från patientindexet (-mpi)
/pdqv3PDQ-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:

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:

  1. 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.
  2. 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.
  3. 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 handSatt framför en granskare med rätt personMissadFel länkar
Automatisk länkning av (standard)02 649 av 3 0003510
På, standardvikt1 6371 0123510
På, vikter uppskattade från posterna1 6221 0703080

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.

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.

Om du migrerar från en annan motor, är detta värt att verifiera explicit på din egen trafik snarare än att anta. Paritetskontrollen kommer att visa det: en destination som den gamla motorn registrerade som levererad och Perfuse registrerar som misslyckad betyder vanligtvis att den gamla motorn ignorerade en NACK.

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ärdeVad som skickas
noneIngenting. Standard.
999Implementeringsbekräftelse. Ersätter 997 för HIPAA-transaktioner.
997Funktionsbekräftelse. Äldre, och fortfarande vad många betalningsanslutningar förväntar sig.
ta1Interchange-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.

Att skicka fel bekräftelse är värre än att skicka ingen alls. Det svarar på en fråga som ingen ställde medan den verkliga frågan lämnas öppen, och avsändaren har inget sätt att skilja på dem.

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

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

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:

NyckelVad den gör
enabledOm misslyckade meddelanden köas över huvud taget.
max_attemptsHur många gånger som ska försökas innan man ger upp.
backoffVänta innan det första återförsöket.
max_backoffTak på den växande väntan.
max_depthDe flesta meddelanden som ska hållas. Om den inte är inställd, finns det ingen gräns.
retain_hoursHur 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.

Ett giftigt meddelande — ett som aldrig kommer att lyckas oavsett hur ofta det försöks — är det specifika felet som den här designen är sårbar för. 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 svararPerfuse 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 allvarlighetsgradMisslyckad, med varje ERR:s plats, kod och text i felet.
AR eller CRMisslyckad, 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-meddelandeMisslyckad.

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

ResultatBetydelse
DeliveredDestinationsadressen accepterade meddelandet. För MLLP, mottogs ett positivt bekräftelsemeddelande.
QueuedLeverans misslyckades och meddelandet kommer att skickas igen.
FailedLeverans 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.
FilteredDestinationsadressen 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.

framingVad den skriver
mllp0x0b före, 0x1c 0x0d efter. Samma ram som en MLLP-destination använder.
delimitedEn delimiter efter varje meddelande, och ett valfritt start_block före det.
fixedPoster som fylls ut eller trunkeras till record_length.
lengthEn length_bytes-prefix. big_endian och length_includes_header har båda två konventioner i vilt tillstånd och skillnaden är tyst.
wholeEtt 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.

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äftadeNärvarande nedströms efteråtBekräftade men saknade
2552550

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 efterBekräftadeNärvarande nedströmsFörlorade
5514
2525124
7575273
1101102108

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

TypUtlöses när
error-rateFel överstiger en proportion av trafik.
queue-depthEn kö har fler än N meddelanden i väntan.
queue-ageDet äldsta köade meddelandet är äldre än en varaktighet.
queue-stuckEn kö töms inte alls.
no-trafficIngenting har anlänt under en fast period.
below-rhythmTrafiken är långt under vad den här feeden normalt gör *vid den här tiden på veckan*.
channel-downEn kanal som ska köras körs inte.
script-errorsEtt skript misslyckas.
rows-quarantinedEn databaskälla ställer raderna åt sidan.
slow-deliveryLeveranser lyckas men tar för lång tid.
contractEtt meddelande bryter mot kanalens deklarerade kontrakt.
phi-volumeEn kanal bär flera gånger sin vanliga hastighet för timmen.
phi-after-hoursEn kanal som bara bär dagtrafik bär något på natten.
phi-new-destinationEn kanal levererar till en adress den inte har skickat till tidigare.
phi-bulk-readsEn 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.

Frånvarande timmar inom inlärningsfönstret registreras som riktiga nollor, inte som saknad data. Hälften av signalen i en klinikfeed är *när den är legitimt tyst*, och att behandla dessa timmar som okända skulle kasta bort den.

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:

  1. below-rhythm — feeden har blivit tyst när den inte borde vara tyst.
  2. error-rate — meddelanden anländer och misslyckas.
  3. queue-age — något är fastnat snarare än bara upptaget.
  4. 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.

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.

Ombehandling levererar igen. Om meddelandena delvis lyckades första gången, kommer ombehandling att producera dubbletter på destinationerna som redan hade dem. Perfuse sparar vilka destinationer som lyckades, så ombehandling kan begränsas till de som misslyckades — gör det i stället för att ombehandla allt, såvida inte mottagarsystemet deduplicerar på meddelandekontroll-ID.

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:

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

ResultatBetydelse
changedSteget kördes och modifierade meddelandet.
no-effectSteget kördes, och meddelandet är oförändrat.
skippedStegets when-villkor var falskt, så det kördes inte.
failedSteget 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.

En steg-rapport som visar 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:

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.

Ett testmeddelande som inte är markerat som ett kommer så småningom att hittas i ett produktionsystem av någon som inte har något sätt att veta att det inte var riktigt. 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.

ContainerKontrollerVad den hittade
Keycloak 26web/e2e-saml/, och internal/saml-fixturesEn 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 Entrainternal/saml live-tester och fixturesTvå 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 FHIRgo test ./internal/engine/ -run HAPIEn defekt. En omappad tilldelningsmyndighet producerade en identifieringssystem som tillkännagav ett OID och bar ett ord, som HAPI accepterade utan klagomål
ActiveMQgo test ./internal/engine/ -run RealBrokerKorrekt, inklusive det null-byte-ram-fallet. Påstått genom brokerens egen hanteringsgränssnitt snarare än genom en funktion som returnerar nil
nginx, klientcertifikatgo test ./internal/engine/ -run ClientCertificateKorrekt
Orthanc (en riktig PACS)go test ./internal/engine/ -run RealPACSKorrekt. En C-STORE anländer och patientens namn, identifierare, studie datum, modalitet och SOP-klass alla överlever
PostgreSQLgo test ./internal/engine/ -run RealPostgresKorrekt, 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-servergo test ./internal/engine/ -run OpenSSHServerKorrekt. 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.2go test ./internal/mirth/ -run RealMirthKorrekt 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:

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.

ResultatAntal
Resurser validerade med inga fynd13 723
Resurser som rapporterats ogiltiga0
Filer som vägrats som en oimplementerad resurstyp753
Bundle-inträden som hoppades över som en oimplementerad typ1 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:

ExporteraFrån AdministratörenVad som överförs
En kanalExportera KanalKanalen
En kanalgruppExportera GruppVarje kanal i den, var och en behåller gruppen
KodmallarExportera KodmallarVarje bibliotek som en skriptfil
En server-säkerhetskopiaSäkerhetskopiera Konfiguration, eller GET /api/server/configurationAllt 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.

Perfuse kan inte nå in i Mirth, och den här handboken kommer inte att påstå annat. Ett verktyg som påstod att den verifierade en migration utan att någonsin se den gamla motorens faktiska utdata skulle verifiera ingenting. Att tillhandahålla paren är den ärliga formen av övningen.

15.4.1 Fyra siffror, inte en godkännandegrad

ResultatBetydelse
IdentiskByte för byte samma.
Kosmetiskt endastSkiljer sig på sätt som inte bär någon information — efterföljande tomma fält, en slutlig avslutare.
Skiljer sigEtt fälts värde är annorlunda.
Kunde inte körasPerfuse 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

  1. Importera kanaler och lösa allt som rapporteras som oläsligt.
  2. För varje kanal, granska varningarna. De flesta är skript.
  3. Exportera ett par tusen meddelandepar från Mirth för den mest trafikerade kanalen och kör jämförelsen.
  4. Arbeta igenom resultaten. Systematiska är ett beslut vardera.
  5. Kör igen tills de enda skillnaderna är de du har beslutat är korrekta.
  6. 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.
  7. 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.

PaketKlasser
java.utilArrayList, 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.langString, StringBuilder, StringBuffer, Integer, Long, Short, Byte, Double, Float, Boolean, Math, System (tid och radavgränsare endast)
java.text, java.math, java.net, java.nioSimpleDateFormat och DateFormat (Mirths mönsterbokstäver), BigDecimal (som en dubbel), URLEncoder, URLDecoder, StandardCharsets
Apache Commonslang3.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

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

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

APIVad den tillhandahållerGuiderAktiverad av
Patient AccessEn medlems anspråk, kliniska data och tidigare auktorisationer, till en app de väljerCARIN Blue Button 2.2.0, PDex 2.2.0, US Core, SMART App Launch-fhir och en SMART-utgivare (-smart-issuer)
Provider AccessSamma sak för en vårdgivares tilldelade medlemmar, i bulkPDex 2.2.0, Da Vinci ATR 2.1.0, Bulk Data-fhir-payer-apis och -fhir-bulk-export
Payer-to-PayerEn medlems post till en annan betalare, efter att ha matchat demHRex 1.2.0 $member-match, PDex 2.2.0-fhir-payer-apis
Prior AuthorizationVad en beställning behöver, dokumentationen, sedan begäran och beslutetDa 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:

  1. 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);
  2. från anroparens registrering: davinci_version: "2.1" på en SMART-klient (-smart-clients) eller en CDS-klient (-cds-clients);
  3. 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:

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:

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:

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:

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äranSvar
PAInitiationRequestClosed 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.
PARequestAvgörs som en PAS-begäran: Approved med auktorisationsnumret och perioden, Denied med anledningen, eller Open under granskning.
PAAppealRequestEn avslagen ärende avgörs igen, på anledningen i PANote (en överklagande utan en begärs om den).
PACancelRequestApproved 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:

TransportVad som skickasAutentisering
x12 (standard)278 skickas som application/edi-x12; svaret är svarstextenEn bärtoken, OAuth, HTTP Basic, ett klientcertifikat
core-soapCAQH 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-bilagavC2.2.0: ett användarnamn och lösenord (WS-Security UsernameToken) eller ett klientcertifikat. vC4.0.0: ett klientcertifikat och en OAuth-token
core-mimeCAQH CORE vC2.2.0 HTTP MIME multipart omslag, payloaden som en fildelOmslagets UserName och Password, eller ett klientcertifikat
sftpVarje 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:

StatusBetydelse
Klart härPerfuse tillhandahåller det och det är på.
Klart, med ett gapDet ä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öraOrganisationens del: ett avtal, en certifiering, publicering till National Provider Directory.
Inte byggtProgramvara 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:

KriteriumI PerfuseAktivera
13 FHIR-API:er, US Core, Bulk DataFHIR-slutpunkten med dess CapabilityStatement och $export-fhir, -fhir-bulk-export
14 Dokument som FHIR-bilagorDocumentReference 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 PostlokalisatorXDS.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.

En overifierad TLS-anslutning är inte samma sak som en verifierad, och skillnaden är värd att spara någonstans dina revisorer kommer att hitta den. Den bättre lösningen är nästan alltid att skaffa den avlägsna ändens certifikat och lita på det explicit snarare än att lita på allt.

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:

RollKan
ÖvervakareSe om allt fungerar: kanalstatus, antal, flödeskarta, larm, instrumentpaneler, mått och könans djup. Inga meddelandeinnehåll, kanalfiler eller köade meddelanden.
VisareKan också läsa meddelanden, kanalfiler, spår och aktivitetsloggen.
OperatörKan också återsända: ombehandla ett meddelande, upprepa en kanal och försöka leverera köade meddelanden igen.
RedaktörKan också skapa och ändra kanaler, och köra jämförelser.
AdministratörKan 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:

begränsas till FHIR-grupper. Detta är standard när ingen SMART-autentiseringsserver är konfigurerad.

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:

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>" } } } }
VerktygRollVad det gör
server_status, list_channels, queue, alertsövervakareOm saker fungerar, utan meddelandeinnehåll
get_channel, search_messages, get_message, find_patient, fhir_searchvyareKanaler, meddelanden (med innehåll), en patients meddelanden över format, en FHIR-sökning
retry_delivery, reprocess_messageoperatör, och mcp:writeFörsök leverera en köad leverans, skicka ett meddelande genom dess kanal igen
start_channel, stop_channeladministratör, och mcp:writeStarta 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:

LagringsplatsHittad av
Meddelandenidentitetsindexet (Inställningar → Data → Indexera patientidentifierare); utan det kan meddelanden inte hittas med identifierare
Leveranskögenom att läsa varje köad meddelandes identifierare
FHIR-lagretPatientresurser som bär en identifierare och varje resurs vars indexerade referenser pekar på en
Tidigare auktorisationsbegäranidentifierarna för begäran om patienten
Patientindexidentifieraren 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.

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.

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).

den varar.

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.

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:

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örSkickar vanligtvisAnteckningar
KeycloakgroupsBehöver en gruppmedlemskarta som lagts till i klienten.
Entra IDen anspråks-URI som slutar /claims/groupsSkickar gruppobjekt-ID om applikationen inte konfigurerats för att skicka namn. Mappa ID, eller ändra leverantör.
Oktavad som helst som applikationen konfigurerats medVanligtvis groups, med ett filter som bestämmer vilka som skickas.
ADFSen anspråks-URIUnderskrifter 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.

*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.

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.

En kanal som redigeras i webbgränssnittet skrivs tillbaka till sin fil. Om dessa filer finns i versionskontroll, förvänta dig commits från konfigurationsändringar som gjorts via gränssnittet, och redigera inte en fil medan någon har den öppen i byggaren.

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

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.

De andra väntar. Det enklaste att resonera om, och vad en webbplats med en upptagen server och en reservserver vill ha.

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:

TestMeddelandenBekräftade men förloradeDubbletterLä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äremellan2,0000015 s
En Linux-ledare skuren av från databasen (brandvägg), dess process lämnad kvar3,0000116 s
En Windows-ledare skuren av från databasen3,0000020 s
Ledaren dödad medan en servers klocka sprang 2 minuter för fort och en annans 90 sekunder långsamt2,0000018 s
Aktiv-aktiv, fyra feeds över tre servrar, en dödad och återupptagen6,0000224 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*.

Flaggor som visas här är illustrativa, inte uttömmande. -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:

-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.

MLLP har varken autentisering eller kryptering, varken i Perfuse eller någon annanstans. Båda dessa kommandon omfattas av detta, liksom varje MLLP-källa och -mål: åtkomsten begränsas på nätverkslagret eller så är den inte begränsad.

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:

Se digitala kvalitetsmätningar.

19.6.5 FHIR-flaggor på perfuse serve

FlaggaEffekt
-fhirTillhandahåller FHIR-slutpunkten på /fhir. På som standard.
-fhir-versionDen version som tillhandahålls. R4 som standard.
-fhir-read-onlyVägrar skriva.
-fhir-api-tokensMed SMART konfigurerat, accepterar Perfuse API-token samt SMART-token (avstängt som standard; även under Inställningar → FHIR).
-fhir-bulk-exportAktiverar $export. Avstängt som standard.
-fhir-subscriptionsAktiverar ä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-httpLåter prenumerationer leverera till vanligt http. För en testmottagare, aldrig för patientdata på ett nätverk.
-fhir-patient-directory-searchLåter en token begränsad till en patient söka i katalogen (praktiker, organisationer, platser), inom dess omfattningar. Avstängt som standard.
-fhir-declaresGuider 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

OptionTakesDefaultWhat it doesIn the console
-addrstring127.0.0.1:8080, or 127.0.0.1:8443 with -tls-certaddress to serve the interface on—
-alert-severitystringwarningminimum severity to send to the webhook: warning or criticalSettings › Alerts › Delivery: Only send alerts at least this serious
-alert-webhookstring—POST alerts to this URL as JSON. Works with Slack, Teams, Mattermost, Alertmanager or anything that accepts a webhook. The payload carries channel names, counts and thresholds; never message contentSettings › Alerts › Delivery: Send alerts to this address
-alertsstring—YAML file of alert rules. Default: alerts.yaml beside the database, written when the rules are first saved in the console; until then a conservative default set is used—
-allow-metadata-egresson/off—permit destinations pointed at cloud instance metadata addresses, which hold this machine's credentialsSettings › Security › What may leave: Allow destinations at cloud instance metadata addresses
-cds-clientsstring—the EHRs trusted to call the CDS services with signed JWTs (issuer and jwks_url)Settings › Payers › Prior authorization: EHRs trusted to call the CDS services
-channelsstring./channelsdirectory holding channel files—
-clusterstring—share the work with other servers on the same PostgreSQL -db: active-passive (one runs everything, another takes over when it stops) or active-active (channels spread over all)—
-cluster-leaseduration15show long a crashed server holds its work before another takes it over; renewed five times as often—
-crd-advisor-castring—a PEM file of certificate authorities to trust for -crd-advisor-url beside the system's (Vaglio's is its DATA/tls/ca.crt)Settings › Payers › Decision service: Certificate authorities to trust for the advice service
-crd-advisor-token-envstring—name of an environment variable holding a bearer token for -crd-advisor-url (the token itself is never a flag)Settings › Payers › Decision service: Environment variable holding the advice service's token
-crd-advisor-urlstring—with -crd-rules, ask the decision service at this URL (such as Vaglio's /api/pas/advise) what a prior authorization request for each order needing one would be told as the record stands, shown as one more CRD card; the prefetched record is POSTed to it. No answer, or any failure, leaves the cards as they are without itSettings › Payers › Decision service: Advice before submitting (CRD)
-crd-rulesstring—a Da Vinci CRD rules file: serve coverage requirements over CDS Hooks at /cds-servicesSettings › Payers › Prior authorization: Coverage rules file (Da Vinci CRD)
-dashboardsstring—a file mapping directory groups and roles to the dashboard each opens onSettings › Monitoring › Dashboards: Which dashboard each group opens on (file)
-datastring—directory for this server's own files (settings, alerts, sign-in configuration, the log): default beside -db when it is a file, the current directory when it is a PostgreSQL URL—
-davinci-versionstring2.2the Da Vinci CRD, DTR and PAS release answered when neither a request nor its client's registration says: 2.2 (CRD 2.2.1, DTR 2.2.0, PAS 2.2.1) or 2.1 (2.1.0)—
-dbstring./perfuse.dbdatabase for users, messages and stored resources: a file, or a postgres:// URL for servers that share one store (a cluster)—
-demo-accountstring—for a public demonstration server: username:password of a shared viewer account shown on the sign-in page—
-dicomweb-archivestring—keep imaging objects in this directory and serve them over DICOMweb (QIDO-RS, WADO-RS, WADO-URI, STOW-RS) at /dicomwebSettings › Data › Imaging archive: Keep images in this folder and serve them over DICOMweb
-dicomweb-corsstring—comma-separated browser origins, such as an OHIF viewer's, allowed to call /dicomwebSettings › Data › Imaging archive: Browser origins allowed to call it
-drain-forduration—after SIGTERM, report not-ready for this long before shutting down (for rolling deploys)Settings › Engine › Shutdown: Wait for in-flight messages on shutdown
-ecr-agencystring—play a public health agency for testing eCR: answer case reports at $process-message with a Reportability Response, using the agency YAML file given (name, phone, address, endpoint; optional rctc, reply)Settings › Public health › Case reporting: Act as a test public health agency
-ecr-responseson/off—accept eCR Reportability Responses at the FHIR endpoint's $process-message, storing each as DocumentReference/<id> derived from the eICR it answersSettings › Public health › Case reporting: Receive Reportability Responses
-engineon/offtruerun the channel engine in this process, so the interface can start, stop and monitor channels—
-epa-payer-idstring—this payer's identifier on the prescribing network, the From of every RTPB and ePA response (default: the formulary's payer id)Settings › Payers › Drug formulary: Payer ID on the prescribing network
-epa-reply-channelstring—route ePA decisions made after the request was answered (a reviewer's, an appeal's) to this channel, which delivers them to the prescriber's networkSettings › Payers › Drug formulary: Channel that sends later ePA decisions
-fhiron/offtrueserve a FHIR endpoint at /fhirSettings › FHIR › The FHIR server: Serve a FHIR endpoint at /fhir
-fhir-api-tokenson/off—with SMART configured, accept Perfuse API tokens on the FHIR endpoint as well (unscoped; the console's FHIR settings can switch it)Settings › FHIR › Access: Accept Perfuse API tokens beside SMART tokens
-fhir-bulk-exporton/off—enable $export, which produces a file holding every record the FHIR endpoint servesSettings › FHIR › Bulk data: Bulk Data export ($export)
-fhir-declaresstring—guides this FHIR server declares in its capability statement, comma-separated: a CapabilityStatement address, or Type=profile addressSettings › FHIR › Capability statement: Guides this server declares
-fhir-max-resourcesint—for a public server: refuse new FHIR resources once this many are held (0: no limit)Settings › FHIR › Access: Most resources held
-fhir-member-match-without-consenton/off—let $member-match answer without an active Consent; the Payer-to-Payer API is opt-in, so only for testingSettings › Payers › CMS-0057-F: Answer $member-match without the member's consent
-fhir-openon/off—serve the FHIR endpoint with no authentication at all, exposing every stored recordSettings › FHIR › Access: Let anyone read the FHIR endpoint without signing in
-fhir-patient-directory-searchon/off—let a token limited to one patient search the directory (practitioners, organisations, locations) within its scopesSettings › FHIR › Access: Let a patient's app search the directory
-fhir-payer-apison/off—enable the CMS-0057 payer operations: $member-match (Payer-to-Payer) and Group $davinci-data-export (Provider Access); the Group exports also need -fhir-bulk-exportSettings › Payers › CMS-0057-F: The CMS-0057-F payer APIs
-fhir-read-onlyon/off—refuse writes to the FHIR endpointSettings › FHIR › Access: Refuse writes to the FHIR endpoint
-fhir-subscriptionson/off—enable topic-based subscriptions, which send encounter and appointment notifications to URLs FHIR clients chooseSettings › FHIR › Notifications: FHIR subscriptions (encounter and appointment notifications)
-fhir-subscriptions-allow-httpon/off—let subscriptions deliver to plain-http endpoints; for a test receiver, never for patient data on a networkSettings › FHIR › Notifications: Allow subscriptions to notify plain-HTTP addresses
-fhir-versionstring4.0.1FHIR release to serve: R4, R4B or R5Settings › FHIR › The FHIR server: FHIR version clients see
-fhir-writes-per-minuteint—for a public server: writes one client address may make to the FHIR endpoint a minute (0: no limit)Settings › FHIR › Access: Writes a minute from one client
-fleet-labelstring—how this instance names itself in a fleet view (default: hostname)Settings › Fleet › This server: Name for this server
-formularystring—publish this drug formulary over the Da Vinci US Drug Formulary API at /formulary/fhir and answer NCPDP Real-Time Prescription Benefit and SCRIPT electronic prior authorization from itSettings › Payers › Drug formulary: Drug formulary file
-icd11-client-idstring—a WHO ICD API client: ICD-11 codes not imported are looked up thereSettings › Data › Code systems: WHO ICD API client ID
-icd11-client-secretstring—the WHO ICD API client's secretSettings › Data › Code systems: WHO ICD API client secret
-icd11-releasestring2025-01the ICD-11 MMS release the WHO ICD API is asked aboutSettings › Data › Code systems: ICD-11 release to ask for
-icd11-urlstring—the ICD API's address when it is not the WHO's: the WHO's ICD-API container on your network needs no clientSettings › Data › Code systems: ICD API address
-index-identityon/offtrueindex patient identifiers from message contents so a message can be found by MRN, name or accession in any format; has no effect when -store-payloads is offSettings › Data › What is kept: Index patient identifiers
-insecureon/off—serve over plain HTTP on a non-loopback address (not recommended)—
-inventorystring—write a Markdown inventory of every interface to this file, and keep it currentSettings › Monitoring › Inventory: Write an interface inventory to
-inventory-everyduration24h0m0show often to rewrite the interface inventorySettings › Monitoring › Inventory: Rewrite the inventory every
-json-logson/off—emit structured JSON logsSettings › Monitoring › Logging: Write logs as JSON
-ldapstring—YAML file configuring directory (LDAP) sign-in (default: ldap.yaml beside the database, once saved in the console)—
-log-filestring—append the log, and the first administrator's one-time password, to this file (mode 0600) instead of the console. A Windows service has no console, so there it defaults to perfuse.log beside the database—
-mcpon/off—serve the Model Context Protocol at /mcp, so AI agents with an API token can read status, messages, the queue, alerts and the FHIR store with that token's own accessSettings › Security › AI agents (MCP): Let AI agents connect over MCP
-measure-reporterstringPerfusethe reporting organisation's name on MeasureReports from $evaluate-measure when the request names no reporter—
-metrics-openon/off—serve /metrics to anybody who can reach the port. Only safe where that port is genuinely private: metric labels name your channels, and on a multi-tenant server they name every tenant'sSettings › Security › Metrics: Serve /metrics without a token
-metrics-tokenstring—credential the Prometheus scrape endpoint requires. Give the scraper the same value in bearer_token_file. Without this, only a signed-in operator can read /metricsSettings › Security › Metrics: Token a metrics scraper presents
-mpion/off—keep a patient index (master patient index) in mpi.db beside the database: patient records from every system linked into one enterprise identifier per person, fed by mpi destinations and the PIX v3 identity feed, answering Patient/$match, PIXm, PIX v3 (/pixv3) and PDQ v3 (/pdqv3)Settings › Data › Patient index: Keep a patient index
-multi-tenanton/off—keep each tenant's channels in their own subdirectory of -channels, so one server can run integration for several organisations without them being able to see each other—
-node-addressstring—this server's console URL as the other servers and a load balancer reach it—
-node-namestring—this server's name in the cluster (default: an id kept in -data)—
-oidcstring—YAML file configuring OpenID Connect sign-in (default: oidc.yaml beside the database, once saved in the console)—
-pason/off—serve Da Vinci PAS 2.2.1 and 2.1.0 (Claim/$submit, $inquire, $decide) on the FHIR endpoint; decisions come from -crd-rules, and what no rule decides is pended for a reviewer. With -fhir-subscriptions, the PAS topic delivers each pended request's resultSettings › Payers › Prior authorization: Da Vinci PAS prior authorization server
-pas-278-castring—a PEM file of certificate authorities to trust for the UM system beside the system'sSettings › Payers › Utilization management link: Certificate authorities to trust for the UM system
-pas-278-certstring—a PEM client certificate for X.509 mutual TLS with the UM system (CORE's authentication)Settings › Payers › Utilization management link: Client certificate file
-pas-278-core-receiverstring—the CORE envelope's ReceiverID, as the UM system's connectivity guide gives it (default: -pas-278-receiver)Settings › Payers › Utilization management link: CORE envelope ReceiverID
-pas-278-core-rule-versionstring—what to write in the CORE envelope's CORERuleVersion when the UM system's guide asks for something other than the version itself (CMS esMD's sample says v2.2.0)Settings › Payers › Utilization management link: CORERuleVersion written in the envelope
-pas-278-core-senderstring—the CORE envelope's SenderID, as the UM system's connectivity guide gives it (default: -pas-278-sender)Settings › Payers › Utilization management link: CORE envelope SenderID
-pas-278-core-versionstring2.2.0the CAQH CORE Connectivity Rule the UM system runs, for core-soap and core-mime: 2.2.0 (payload in the envelope) or C4.0.0 (payload as an MTOM attachment; SOAP only)Settings › Payers › Utilization management link: CAQH CORE Connectivity Rule
-pas-278-keystring—the private key (PEM) for -pas-278-certSettings › Payers › Utilization management link: Client certificate key file
-pas-278-oauth-client-idstring—the OAuth client ID for -pas-278-oauth-token-urlSettings › Payers › Utilization management link: OAuth client ID
-pas-278-oauth-scopestring—the scope asked for with the OAuth token, when the UM system wants oneSettings › Payers › Utilization management link: OAuth scope
-pas-278-oauth-secret-envstring—name of an environment variable holding the OAuth client secret (the secret itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the OAuth client secret
-pas-278-oauth-token-urlstring—an OAuth 2.0 token endpoint: a token got with the client-credentials grant is sent as a bearer token (CORE vC4.0.0's authorization)Settings › Payers › Utilization management link: OAuth token endpoint
-pas-278-password-envstring—name of an environment variable holding the password for -pas-278-user (the password itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the password
-pas-278-payer-idstring—the UMO's payer ID (NM1*X3) when the request's insurer carries no identifierSettings › Payers › Utilization management link: Payer ID for the 278s
-pas-278-productionon/off—mark the 278s sent as production (ISA15 P) rather than testSettings › Payers › Utilization management link: Mark the 278s as production
-pas-278-receiverstring—ISA08/GS03 receiver ID on the 278s sent to the UM systemSettings › Payers › Utilization management link: Receiver ID on the 278s
-pas-278-senderstringPERFUSEISA06/GS02 sender ID on the 278s sent to the UM systemSettings › Payers › Utilization management link: Sender ID on the 278s
-pas-278-sftpstring—host:port of the UM system's SFTP server, for -pas-278-transport sftpSettings › Payers › Utilization management link: SFTP server
-pas-278-sftp-everyduration1m0show often the SFTP inbound folder is readSettings › Payers › Utilization management link: Read the SFTP inbound folder every
-pas-278-sftp-inboundstring—the SFTP folder the UM system's 278 responses, 999s and TA1s are collected fromSettings › Payers › Utilization management link: SFTP inbound folder
-pas-278-sftp-keystring—an OpenSSH private key file for the SFTP user, instead of a passwordSettings › Payers › Utilization management link: SFTP key file
-pas-278-sftp-known-hostsstring—an OpenSSH known_hosts file holding the SFTP server's key; required, so requests never go to whoever answersSettings › Payers › Utilization management link: SFTP known_hosts file
-pas-278-sftp-outboundstring—the SFTP folder the 278 requests (and the 999s for the answers) are put inSettings › Payers › Utilization management link: SFTP outbound folder
-pas-278-sftp-password-envstring—name of an environment variable holding the SFTP password (the password itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the SFTP password
-pas-278-sftp-userstring—the SFTP user nameSettings › Payers › Utilization management link: SFTP user
-pas-278-token-envstring—name of an environment variable holding a bearer token for the UM system (the token itself is never a flag)Settings › Payers › Utilization management link: Environment variable holding the token
-pas-278-transportstringx12how the 278s reach the UM system: x12 (POSTed as application/edi-x12), core-soap (a CAQH CORE SOAP envelope), core-mime (CAQH CORE HTTP MIME multipart), or sftp (batch files over -pas-278-sftp, answers collected from its inbound folder)Settings › Payers › Utilization management link: How the 278s travel
-pas-278-urlstring—forward every PAS request to the payer's utilization management system as an X12 278 request sent to this URL (by -pas-278-transport), and answer with its 278 response; later 278 responses go to Claim/$decide-278Settings › Payers › Utilization management link: Send PAS requests on to the UM system at
-pas-278-userstring—user name for the UM system: CORE's UserName (WS-Security UsernameToken in SOAP), or HTTP Basic for x12Settings › Payers › Utilization management link: User name
-pas-decider-castring—a PEM file of certificate authorities to trust for -pas-decider-url beside the system's, such as the payer's own authority or the decision service's (Vaglio's is its DATA/tls/ca.crt)Settings › Payers › Decision service: Certificate authorities to trust for the decision service
-pas-decider-token-envstring—name of an environment variable holding a bearer token for -pas-decider-url (the token itself is never a flag)Settings › Payers › Decision service: Environment variable holding the decision service's token
-pas-decider-urlstring—ask the decision service at this URL (such as Vaglio) to decide each PAS item on the request's clinical evidence, when -crd-rules leave it to a reviewer; the PAS request Bundle is POSTed to it. Cannot be combined with -pas-278-urlSettings › Payers › Decision service: Decision service URL
-passkey-allowed-modelsstring—comma-separated authenticator AAGUIDs that may enrol; requires -passkey-attestation-roots—
-passkey-attestation-rootsstring—a PEM file of authenticator vendor certificates; passkey attestation is verified against these—
-passkey-domainstring—the bare domain passkeys are registered for, such as perfuse.example.org. No scheme, no port, no path. Setting it turns passkeys on; leaving it empty leaves them offSettings › Sign-in › Passkeys: Domain passkeys are bound to
-passkey-namestringPerfusethe name an authenticator shows a person when they register a passkeySettings › Sign-in › Passkeys: Name shown on the device
-passkey-originsstring—comma-separated origins the console is reached at, with scheme and port: https://perfuse.example.org. Defaults to https:// plus the domainSettings › Sign-in › Passkeys: Other origins passkeys are accepted from
-peersstring—YAML file listing other Perfuse instances to show in a fleet viewSettings › Fleet › Fleet: Other Perfuse servers to show (file)
-public-urlstring—the https address patients' phones and other organisations reach this server at, for the SMART Health Links it hosts (default: the listen address)Settings › FHIR › The FHIR server: Address others reach this server at
-rctcstring—eCR trigger codes for the case report preview: a FHIR ValueSet or Bundle of them, such as the eRSDSettings › Public health › Case reporting: Trigger codes file (RCTC or eRSD)
-residencystring—cloud regions this server's data may go to or come from: areas (eea, uk, ch) and region codes (eu-central-1), comma-separated; channels with connectors elsewhere are refusedSettings › Data › Data protection: Where data may go (cloud regions)
-retention-daysint30how long to keep recorded messages; 0 keeps them for ever, which will eventually fill the diskSettings › Data › How long it is kept: Delete records after
-samlstring—YAML file configuring SAML 2.0 sign-in (default: saml.yaml beside the database, once saved in the console)—
-scimon/off—accept SCIM 2.0 provisioning from an identity provider at /scim/v2. Okta, Entra ID and Google Workspace use it to create accounts and, more importantly, to disable them when somebody leavesSettings › Sign-in › Automatic accounts: Let the identity provider manage accounts
-scim-default-rolestringviewerrole for an account the identity provider does not describe. Defaults downward on purpose: an account whose role could not be determined should be able to read and nothing else—
-settingsstring—settings file the web interface may edit (default: perfuse-settings.yaml beside the database)—
-shl-allow-httpon/off—let a received SMART Health Link point at plain HTTP; for testing onlySettings › Public health › Health links: Allow SMART Health Links over plain HTTP
-signing-certstring—certificate for signing documents (defaults to -tls-cert)Settings › Security › Document signing: Certificate for signing documents
-signing-keystring—key for signing documents (defaults to -tls-key)Settings › Security › Document signing: Key for signing documents
-smart-audiencestring—the audience a SMART token must be issued for, normally the FHIR base URLSettings › SMART › Authorization: Audience tokens must name
-smart-authorizestring—the authorization endpoint to advertise to SMART appsSettings › SMART › Authorization: Authorization endpoint
-smart-backend-serviceson/off—advertise that the SMART authorization server issues backend-services (client_credentials, signed JWT) tokensSettings › SMART › Built-in server: Backend Services (system-to-system tokens)
-smart-clientsstring—run Perfuse's own SMART authorization server at /auth for the apps registered in this YAML fileSettings › SMART › Built-in server: Registered apps file (turns on the built-in server)
-smart-issuerstring—accept SMART on FHIR access tokens from this authorization serverSettings › SMART › Authorization: Accept SMART access tokens from this authorization server
-smart-jwksstring—where to fetch the SMART issuer's signing keys, when not from its published metadata (split DNS, a private address)Settings › SMART › Authorization: Key set file
-smart-jwks-uristring—the authorization server's public key set URL, advertised to SMART apps (needed to claim OpenID Connect sign-in)Settings › SMART › Authorization: Key set address
-smart-keystringsmart-signing.keythe built-in authorization server's RSA signing key (PEM, mode 0600), created if missingSettings › SMART › Built-in server: Signing key file
-smart-oidcstring—with -smart-users, let people sign in at this OpenID Connect provider (YAML: issuer, client_id, client_secret_file or client_secret_env, label); each is linked by oidc_subjectSettings › SMART › Built-in server: Sign people in through the OpenID Connect provider
-smart-tokenstring—the token endpoint to advertise to SMART appsSettings › SMART › Authorization: Token endpoint
-smart-usersstring—with -smart-clients, the people who may sign in to authorize apps (YAML: username, password_hash, fhir_user)Settings › SMART › Built-in server: People who sign in to authorize apps (file)
-snmp-allowstring—comma-separated networks or addresses the SNMP agent answers, such as 10.0.5.0/24; required with -snmp-listenSettings › Monitoring › SNMP: Networks that may ask
-snmp-base-oidstring1.3.6.1.4.1.8072.9999.9999.16, Net-SNMP's experimental spacewhere Perfuse's values sit, under your enterprise numberSettings › Monitoring › SNMP: Base OID
-snmp-communitystring—the SNMPv2c community (a password sent in clear: at least 6 characters, not public or private)Settings › Monitoring › SNMP: SNMP community
-snmp-contactstring—sysContact the SNMP agent reportsSettings › Monitoring › SNMP: Contact (sysContact)
-snmp-listenstring—answer SNMPv2c GET/GETNEXT/GETBULK on this UDP address, such as :161 (off when empty). Read-only: channel states, counts and queue depthsSettings › Monitoring › SNMP: Answer SNMP on this address
-snmp-locationstring—sysLocation the SNMP agent reportsSettings › Monitoring › SNMP: Location (sysLocation)
-snmp-trapsstring—comma-separated managers (host or host:port, default port 162) that receive an SNMPv2 trap when an alert fires or resolvesSettings › Monitoring › SNMP: Send traps to
-store-messageson/offtruerecord every message handled, which is what makes the message browser workSettings › Data › What is kept: Keep a record of each message
-store-payloadson/offtruestore message contents as well as their outcomes; turn this off where PHI must not be held at restSettings › Data › What is kept: Keep message contents
-tls-certstring—TLS certificate fileSettings › Security › Encryption: TLS certificate file
-tls-keystring—TLS private key fileSettings › Security › Encryption: TLS private key file
-trace-endpointstring—OTLP/HTTP base URL to export message traces to, for example http://localhost:4318Settings › Monitoring › Tracing: Send traces to
-trace-instancestring—name for this instance in traces; defaults to the hostname, which is what distinguishes replicasSettings › Monitoring › Tracing: This instance's name in traces
-trace-samplefloat1fraction of traces to record, 0 to 1—
-tsa-urlstring—RFC 3161 time-stamping authority for DSDR signatures on claims attachmentsSettings › Security › Document signing: Time-stamping authority
-vpnstring—partner VPN tunnels to report on the Connections dashboard (YAML: AWS Site-to-Site VPN, Azure VPN Gateway or strongSwan, and both sides' settings); see examples/vpn.yamlSettings › Monitoring › Connections: VPN tunnels to watch (file)
-watch-accesson/offtruewatch traffic and reads of patient data for what a breach looks like (bursts, night traffic, new destinations, bulk reads) and raise alerts—
-xdsstring—keep clinical documents here as an IHE XDS.b registry and repository with this repository uniqueId (an OID), answering ITI-41, ITI-42, ITI-18 and ITI-43 at /xds/repository and /xds/registrySettings › Data › Document sharing (IHE XDS): Keep documents here as an XDS registry and repository
-xds-home-communitystring—this community's home community id (urn:oid:...), so /xca/gateway answers XCA ITI-38 and ITI-39 for itSettings › Data › Document sharing (IHE XDS): Home community id, for XCA

21 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.

NyckelTypObligatoriskStandard
nametextja—
descriptiontextnej—
grouptextnej—
attachmentsBilagor (en block, utelämna för att inte använda)nej—
delimitedAvgränsad (en block, utelämna för att inte använda)nej—
tableslista av textnej—
contractContractRef (en block, utelämna för att inte använda)nej—
enabledtrue eller false (en block, utelämna för att inte använda)nej—
dataTypeDataTypenejhl7
hl7v3HL7v3Options (en block, utelämna för att inte använda)nej—
x12X12Options (en block, utelämna för att inte använda)nej—
ncpdpNCPDPOptions (en block, utelämna för att inte använda)nej—
edifactEDIFACTOptions (en block, utelämna för att inte använda)nej—
scriptScriptOptions (en block, utelämna för att inte använda)nej—
dicomDICOMOptions (en block, utelämna för att inte använda)nej—
sourceKällaja—
filtertextnej—
transformationslista av transform.Stepnej—
scriptsSkript (en block, utelämna för att inte använda)nej—
shadowSkugga (en block, utelämna för att inte använda)nej—
destinationslista av Destinationja—

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.

NyckelTypObligatoriskStandard
prefetchheltalnej10
reconnectvaraktighet, såsom 30s eller 5mnej5s

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.

NyckelTypObligatoriskStandard
listentextja—
pathtextnej—
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
idtextja—
cert_filetextja—
key_filetextja—
partnerslista av AS2Partnerja—
max_message_sizeheltalnej—
duplicate_windowvaraktighet, såsom 30s eller 5mnej—

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.

NyckelTypObligatoriskStandard
prefixtextja—
suffixtextnej—
after_readtextnej—
move_totextnejprocessed/
error_prefixtextnejerror/
poll_intervalvaraktighet, t.ex. 30s eller 5mnej30s
max_object_sizeheltalnej16 MiB
framedtrue eller falsenej—

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.

NyckelTypObligatoriskStandard
addrtextja—
destinationtextja—
logintextnej—
passcodetextnej—
hosttextnejadressens värd
selectortextnej—
subscription_idtextnejkanalnamn
heartbeatvaraktighet, t.ex. 30s eller 5mnejtrettio sekunder
reconnectvaraktighet, t.ex. 30s eller 5mnejfem sekunder
timeoutvaraktighet, t.ex. 30s eller 5mnejtrettio sekunder
tlstlsconf.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.

NyckelTypObligatoriskStandard
addresstextja—
called_aetextja—
calling_aetextnej—
leveltextnejSTUDY
patient_roottrue eller falsenej—
matchmappning av text till textnej—
returnlista av textnej—
intervalvaraktighet, såsom 30s eller 5mja—
windowvaraktighet, såsom 30s eller 5mnej—
overlapvaraktighet, såsom 30s eller 5mnejen timme
limitheltalnej500
timeoutvaraktighet, såsom 30s eller 5mnejtvå minuter
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
emit_on_first_polltrue eller falsenejfalse

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.

NyckelTypObligatoriskStandard
listentextja—
ae_titletextnej—
allowed_calling_aelista med textnej—
sop_classeslista med textnej—
transfer_syntaxeslista med textnej—
max_object_bytesheltalnej—
idle_timeoutvaraktighet, t.ex. 30s eller 5mnej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
listentextja—
pathtextnej/dicom-web
tokentextnej—
usernametextnej—
passwordtextnej—
max_object_bytesheltalnej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
drivertextja—
dsntextja—
querytextja—
after_querytextnej—
key_columntextnej—
templatetextnej—
columntextnej—
poll_intervalvaraktighet, såsom 30s eller 5mnej—
batch_sizeheltalnej100
max_attemptsheltalnej3
query_timeoutvaraktighet, såsom 30s eller 5mnej30s

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.

NyckelTypObligatoriskStandard
listentextnej—
tls_certtextnej—
tls_keytextnej—
max_bytesheltalnej—
smtp_hosttextnej—
usernametextnej—
passwordtextnej—
imapDirectIMAP (en block, utelämna för att inte använda)nej—
xdrDirectXDR (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.

NyckelTypObligatoriskStandard
protocoltextnej—
hosttextja—
portheltalnej—
securitytextnej—
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
usernametextja—
passwordtextnej—
oauthEmailOAuth (en block, utelämna för att lämna av)nej—
mailboxtextnej—
taketextnej—
attachment_nameslista av textnej—
allowed_senderslista av textnej—
after_readtextnej—
move_totextnej—
error_foldertextnej—
poll_intervalvaraktighet, såsom 30s eller 5mnej—
max_message_sizeheltalnej—

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.

NyckelTypObligatoriskStandard
hosttextja—
usertextnej—
passwordtextnej—
securityftpconn.Securitynejexplicit
insecure_skip_verifytrue eller falsenej—
roottextnej—
timeoutvaraktighet, t.ex. 30s eller 5mnejtrettio 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.

NyckelTypObligatoriskStandard
roottextja—
follow_symlinkstrue eller falsenej—

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.

NyckelTypObligatoriskStandard
prefixtextja—
suffixtextnej—
after_readtextnej—
move_totextnejprocessed/
error_prefixtextnejerror/
poll_intervalvaraktighet, t.ex. 30s eller 5mnej30s
max_object_sizeheltalnej16 MiB
framedtrue eller falsenej—

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.

NyckelTypObligatoriskStandard
listentextja—
pathtextnej"/"
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
tokentextnej—
max_message_sizeheltalnej—
read_timeoutvaraktighet, såsom 30s eller 5mnej—
ackAcknej—

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.

NyckelTypObligatoriskStandard
poll_intervalvaraktighet, såsom 30s eller 5mnej2s

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.

NyckelTypObligatoriskStandard
scripttextja—
poll_intervalvaraktighet, t.ex. 30s eller 5mnej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—

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.

NyckelTypObligatoriskStandard
brokerslista med textja—
topicslista med textja—
grouptextja—
from_beginningtrue eller falsenej—
commit_after_deliverytrue eller false (en block, utelämna för att lämna av)nej—
max_message_sizeheltalnejkanallimiten
session_timeoutvaraktighet, t.ex. 30s eller 5mnejfyrtiofem sekunder
timeoutvaraktighet, t.ex. 30s eller 5mnejtrettio sekunder
saslKafkaSASL (en block, utelämna för att lämna av)nej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
topictextja—
reconnectvaraktighet, t.ex. 30s eller 5mnej5s

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.

NyckelTypObligatoriskStandard
subscriptiontextja—
max_messagesheltalnej10
reconnectvaraktighet, t.ex. 30s eller 5mnej5s

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.

NyckelTypObligatoriskStandard
buckettextja—
path_styletrue eller falsenej—
prefixtextnej—
suffixtextnej—
after_readtextnej—
move_totextnejprocessed/
error_prefixtextnejerror/
poll_intervalvaraktighet, t.ex. 30s eller 5mnej30s
max_object_sizeheltalnej16 MiB
framedtrue eller falsenej—

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.

NyckelTypObligatoriskStandard
hosttextja22
usertextja—
passwordtextnej—
key_filetextnej—
key_passphrasetextnej—
known_hosts_filetextnej—
insecure_skip_host_key_checktrue eller falsenej—
dirtextja—
patterntextnejallt
poll_intervalvaraktighet, t.ex. 30s eller 5mnej—
after_readtextnej—
move_totextnej—
error_dirtextnej—
stable_forvaraktighet, t.ex. 30s eller 5mnej5s
framedtrue eller falsenej—
max_file_sizeheltalnej64MB
timeoutvaraktighet, t.ex. 30s eller 5mnej60s

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.

NyckelTypObligatoriskStandard
hosttextja—
sharetextja—
usertextnej—
passwordtextnej—
domaintextnej—
roottextnej—
timeoutvaraktighet, såsom 30s eller 5mnejtrettio 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.

NyckelTypObligatoriskStandard
listentextja—
profiletextnej—
pathtextnej"/"
versiontextnej1
elementtextnej—
base64true eller falsenej—
response_elementtextnej"AckResponse"
response_namespacetextnej—
wsdltextnej—
tlstlsconf.Settings (en block, utelämna för att inte använda)nej—
tokentextnej—
usernametextnej—
passwordtextnej—
max_message_sizeheltalnej—
read_timeoutvaraktighet, t.ex. 30s eller 5mnej—
ackAcknej—
fault_on_naktrue eller falsenej—

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.

NyckelTypObligatoriskStandard
queue_urltextja—
wait_secondsheltalnej20: en tom kö kostar en begäran varannan sekund
max_messagesheltalnej10
visibility_timeoutvaraktighet, såsom 30s eller 5mnejkö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.

NyckelTypObligatoriskStandard
porttextja—
baudheltalja—
data_bitsheltalnej8
paritytextnejnone
stop_bitstextnej1
flow_controltextnejnone
max_message_sizeheltalnej—
quiet_aftervaraktighet, t.ex. 30s eller 5mnej—
replytextnej—
reply_texttextnej—
reopen_aftervaraktighet, t.ex. 30s eller 5mnej—

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.

NyckelTypObligatoriskStandard
typeSourceTypeja—
listentextja—
max_message_sizeheltalnej—
idle_timeoutvaraktighet, t.ex. 30s eller 5mnej—
max_connectionsheltalnej—
tlstlsconf.Settings (en block, utelämna för att inte använda)nej—
httpHTTPSource (en block, utelämna för att inte använda)nej—
soapSOAPSource (en block, utelämna för att inte använda)nej—
dicomwebDICOMwebSource (en block, utelämna för att inte använda)nej—
directDirectSource (en block, utelämna för att inte använda)nej—
dicomDICOMSource (en block, utelämna för att inte använda)nej—
fileFileSource (en block, utelämna för att inte använda)nej—
tcpTCPSource (en block, utelämna för att inte använda)nej—
ftpFTPSource (en block, utelämna för att inte använda)nej—
smbSMBSource (en block, utelämna för att inte använda)nej—
webdavWebDAVSource (en block, utelämna för att inte använda)nej—
serialSerialSource (en block, utelämna för att inte använda)nej—
dicom_queryDICOMQuerySource (en block, utelämna för att inte använda)nej—
brokerBrokerSource (en block, utelämna för att inte använda)nej—
kafkaKafkaSource (en block, utelämna för att inte använda)nej—
sqsSQSSource (en block, utelämna för att inte använda)nej—
s3S3Source (en block, utelämna för att inte använda)nej—
amqpAMQPSource (en block, utelämna för att inte använda)nej—
azure_blobAzureBlobSource (en block, utelämna för att inte använda)nej—
emailEmailSource (en block, utelämna för att inte använda)nej—
as2AS2Source (en block, utelämna för att inte använda)nej—
pgpPGPReceive (en block, utelämna för att inte använda)nej—
mqttMQTTSource (en block, utelämna för att inte använda)nej—
ibm_mqIBMMQSource (en block, utelämna för att inte använda)nej—
pubsubPubSubSource (en block, utelämna för att inte använda)nej—
gcsGCSSource (en block, utelämna för att inte använda)nej—
databaseDatabaseSource (en block, utelämna för att inte använda)nej—
sftpSFTPSource (en block, utelämna för att inte använda)nej—
javascriptJavaScriptSource (en block, utelämna för att inte använda)nej—
ackAcknej—

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.

NyckelTypObligatoriskStandard
listentextja—
max_message_sizeheltalnej—
idle_timeoutvaraktighet, t.ex. 30s eller 5mnej—
max_connectionsheltalnej—
replytextnej—
reply_texttextnej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
urltextja—
usertextnej—
passwordtextnej—
insecure_skip_verifytrue eller falsenej—
timeoutvaraktighet, t.ex. 30s eller 5mnejsextio 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.

NyckelTypObligatoriskStandard
content_typetextnejkanalen 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.

NyckelTypObligatoriskStandard
urltextja—
fromtextja—
totextja—
cert_filetextnej—
key_filetextnej—
partner_cert_filetextnej—
unsignedtrue eller falsenej—
unencryptedtrue eller falsenej—
compresstrue eller falsenej—
receipttextnej—
unsigned_receipttrue eller falsenej—
receipt_urltextnej—
content_typetextnej—
file_nametextnej—
subjecttextnej—
usernametextnej—
passwordtextnej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
blobtextnej${date}/${channel}/${control_id}
tiertextnej—
content_typetextnej—

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.

NyckelTypObligatoriskStandard
addrtextja—
destinationtextja—
logintextnej—
passcodetextnej—
hosttextnejadressens värd
content_typetextnejtext/plain för HL7
headersmappning av text till textnej—
persistenttrue eller false (en block, utelämna för att lämna av)nejtrue
timeoutvaraktighet, t.ex. 30s eller 5mnej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
urltextnej—
dirtextnej—
writetextnej—
versiontextnejR5
identifier_systemsmappning av text till textnej—
require_agreementtrue eller falsenej—
on_no_documenttextnej—
headersmappning av text till textnej—
bearer_tokentextnej—

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.

NyckelTypObligatoriskStandard
nametextja—

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.

NyckelTypObligatoriskStandard
addresstextja—
called_aetextnej—
calling_aetextnej—
transfer_syntaxeslista med textnej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
urltextja—
tokentextnej—
usernametextnej—
passwordtextnej—
headersmappning av text till textnej—
tlstlsconf.Settings (en block, utelämna för att inte använda)nej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—

23.9 Databasdestination

DatabaseDestination skriver varje meddelande till en databas.

Definierad som DatabaseDestination i internal/config.

NyckelTypObligatoriskStandard
drivertextja—
dsntextja—
statementtextja—
paramslista med textnej—
timeoutvaraktighet, såsom 30s eller 5mnej30s
max_open_connsheltalnej4

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.

NyckelTypObligatoriskStandard
nametextja—
typeDestinationTypeja—
enabledtrue eller false (en block, utelämna för att lämna av)nej—
filtertextnej—
addresstextnej—
dirtextnej—
file_nametextnej—
temp_suffixtextnej"
appendtrue eller falsenej—
retain_hoursheltalnej—
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
fhirFHIRDestination (en block, utelämna för att lämna av)nej—
cdaCDADestination (en block, utelämna för att lämna av)nej—
httpHTTPDestination (en block, utelämna för att lämna av)nej—
databaseDatabaseDestination (en block, utelämna för att lämna av)nej—
sftpSFTPDestination (en block, utelämna för att lämna av)nej—
tcpTCPDest (en block, utelämna för att lämna av)nej—
smtpSMTPDestination (en block, utelämna för att lämna av)nej—
channelChannelDestination (en block, utelämna för att lämna av)nej—
s3S3Destination (en block, utelämna för att lämna av)nej—
ftpFTPDestination (en block, utelämna för att lämna av)nej—
documentDocumentDestination (en block, utelämna för att lämna av)nej—
soapSOAPDestination (en block, utelämna för att lämna av)nej—
dicomwebDICOMwebDestination (en block, utelämna för att lämna av)nej—
xdsXDSDestination (en block, utelämna för att lämna av)nej—
directDirectDestination (en block, utelämna för att lämna av)nej—
as2AS2Destination (en block, utelämna för att lämna av)nej—
mpiMPIDestination (en block, utelämna för att lämna av)nej—
tefcaTEFCADestination (en block, utelämna för att lämna av)nej—
pasPASDestination (en block, utelämna för att lämna av)nej—
x12_astextnej—
dicomDICOMDestination (en block, utelämna för att lämna av)nej—
javascriptJavaScriptDestination (en block, utelämna för att lämna av)nej—
brokerBrokerDestination (en block, utelämna för att lämna av)nej—
kafkaKafkaDestination (en block, utelämna för att lämna av)nej—
sqsSQSDestination (en block, utelämna för att lämna av)nej—
snsSNSDestination (en block, utelämna för att lämna av)nej—
amqpAMQPDestination (en block, utelämna för att lämna av)nej—
azure_blobAzureBlobDestination (en block, utelämna för att lämna av)nej—
mqttMQTTDestination (en block, utelämna för att lämna av)nej—
ibm_mqIBMMQDestination (en block, utelämna för att lämna av)nej—
pubsubPubSubDestination (en block, utelämna för att lämna av)nej—
gcsGCSDestination (en block, utelämna för att lämna av)nej—
elrELRDestination (en block, utelämna för att lämna av)nej—
pgpPGPSend (en block, utelämna för att lämna av)nej—
response_transformertextnej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—
retryRetrynej—
queueQueueConfig (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.

NyckelTypObligatoriskStandard
tolista av textja—
subjecttextnej—
texttextnej—
attach_nametextnej—
xdmtrue eller falsenej—
xdm_source_idtextnej—
recipient_certs_dirtextnej—
dnstextnej—
ldaptextnej—
smtp_hosttextja—
usernametextnej—
passwordtextnej—
request_mdntrue eller falsenej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—

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.

NyckelTypObligatoriskStandard
dirtextja—
formatDocumentFormatnejpdf
templatetextja—
titletextnej—
file_nametextnej—
font_sizenummernej10
landscapetrue eller falsenej—
temp_suffixtextnej"
timeoutvaraktighet, t.ex. 30s eller 5mnej30s

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.

NyckelTypObligatoriskStandard
rctctextnej—
sourcetextja—
facilityECRFacilityja—

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.

NyckelTypObligatoriskStandard
configtextja—
rctctextnej—

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.

NyckelTypObligatoriskStandard
urltextja—
versiontextnejR5
timezonetextnej—
default_identifier_systemtextnej—
identifier_systemsmappning av text till textnej—
claim_us_coretrue eller falsenej—
validate_before_sendtrue eller false (en block, utelämna för att lämna av)nejtrue: 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_warningtrue eller falsenej—
headersmappning av text till textnej—
bearer_tokentextnej—
authFHIRAuth (en block, utelämna för att lämna av)nej—
ecrECRDestination (en block, utelämna för att lämna av)nej—
bundle_scripttextnej—

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.

NyckelTypObligatoriskStandard
hosttextja21
usertextnej—
passwordtextnej—
securityFTPSecuritynejexplicit snarare än ingen
insecure_skip_verifytrue eller falsenej—
allow_clear_passwordtrue eller falsenej—
dirtextja—
file_nametextnej—
temp_suffixtextnej"
framedtrue eller falsenej—
timeoutvaraktighet, såsom 30s eller 5mnej60s

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.

NyckelTypObligatoriskStandard
objecttextnej${date}/${channel}/${control_id}
storage_classtextnej—
content_typetextnej—

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.

NyckelTypObligatoriskStandard
urltextja—
methodtextnej—
content_typetextnej—
headersmappning av text till textnej—
bearer_tokentextnej—
usernametextnej—
passwordtextnej—
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
success_statuslista av heltalnejvalfri 2xx
fail_on_bodylista av textnej—
follow_redirectstrue eller falsenej—

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.

NyckelTypObligatoriskStandard
non_persistenttrue eller falsenej—

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.

NyckelTypObligatoriskStandard
scripttextja—
timeoutvaraktighet, t.ex. 30s eller 5mnej—
success_on_undefinedtrue eller false (en block, utelämna för att lämna av)nejtrue

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.

NyckelTypObligatoriskStandard
brokerslista med textja—
topictextja—
keytextnej—
ackstextnejall
compressiontextnejsnappy
headersmappning av text till textnej—
timeoutvaraktighet, t.ex. 30s eller 5mnejtrettio sekunder
saslKafkaSASL (en block, utelämna för att lämna av)nej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
authoritiesmappning av text till textnej—
id_typetextnej—
ssn_systemtextnej—
no_mergetrue eller falsenej—

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.

NyckelTypObligatoriskStandard
topictextja—
retaintrue eller falsenej—

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.

NyckelTypObligatoriskStandard
payertextja—
bearer_tokentextnej—
authFHIRAuth (en block, utelämna för att lämna av)nej—
results_totextnej—

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.

NyckelTypObligatoriskStandard
topictextja—
order_bytextnej—

23.26 S3-mål

S3Destination skriver varje meddelande som ett objekt.

Definierad som S3Destination i internal/config.

NyckelTypObligatoriskStandard
buckettextja—
regiontextja—
keytextnejen datum-partitionerad sökväg plus kontroll-id
access_key_idtextnej—
secret_access_keytextnej—
session_tokentextnej—
endpointtextnej—
path_styletrue eller falsenej—
server_side_encryptiontextnej—
content_typetextnejapplication/hl7-v2 för HL7 och text/plain i övrigt
framedtrue eller falsenej—
timeoutvaraktighet, t.ex. 30s eller 5mnej60s
storage_classtextnej—
formattextnej—

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.

NyckelTypObligatoriskStandard
hosttextja22
usertextja—
passwordtextnej—
key_filetextnej—
key_passphrasetextnej—
known_hosts_filetextnej—
insecure_skip_host_key_checktrue eller falsenej—
dirtextja—
file_nametextnejen tidsstämpel plus kontroll-ID
temp_suffixtextnej"
framedtrue eller falsenej—
appendtrue eller falsenej—
timeoutvaraktighet, såsom 30s eller 5mnej60s

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.

NyckelTypObligatoriskStandard
hosttextja—
fromtextja—
tolista med textja—
cclista med textnej—
bcclista med textnej—
subjecttextnej—
bodytextnej—
attachtrue eller falsenej—
attach_nametextnejkontroll-ID med en
usernametextnej—
passwordtextnej—
starttlstrue eller false (en block, utelämna för att lämna av)nej—
insecure_skip_verifytrue eller falsenej—
timeoutvaraktighet, såsom 30s eller 5mnej—

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.

NyckelTypObligatoriskStandard
topic_arntextja—
subjecttextnej—
group_bytextnej—

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.

NyckelTypObligatoriskStandard
urltextja—
profiletextnej—
facility_idtextnej—
warnings_are_errorstrue eller falsenej—
actiontextnej—
versiontextnej1
bodytextja—
headertextnej—
headersmappning av text till textnej—
usernametextnej—
passwordtextnej—
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
fault_is_successlista av textnej—
timeoutvaraktighet, t.ex. 30s eller 5mnej30s

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.

NyckelTypObligatoriskStandard
queue_urltextja—
group_bytextnej—

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.

NyckelTypObligatoriskStandard
addresstextja—
max_message_sizeheltalnej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—
expect_replytrue eller falsenej—
keep_alivetrue eller falsenej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
purposetextja—
results_totextnej—

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.

NyckelTypObligatoriskStandard
urltextja—
source_idtextja—
patient_domaintextnej—
facility_typeXDSCodeja—
practice_settingXDSCodeja—
classXDSCode (en block, utelämna för att inte använda)nej—
content_typeXDSCode (en block, utelämna för att inte använda)nej—
tokentextnej—
usernametextnej—
passwordtextnej—
headersmappning av text till textnej—
tlstlsconf.Settings (en block, utelämna för att inte använda)nej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—
direct_fromtextnej—
direct_tolista av textnej—

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.

NyckelTypObligatoriskStandard
extractlista med attach.Regelja—
reassembletrue eller false (en block, utelämna för att lämna av)nejtrue

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.

NyckelTypObligatoriskStandard
delimitertextnej—
quotetextnejen dubbel citat
commenttextnej—
has_headertrue eller falsenej—
columnslista av textnej—
trim_spacetrue eller falsenej—
relaxedtrue eller falsenej—
splittrue eller false (en block, utelämna för att lämna av)nejtrue
keep_blank_linestrue eller falsenej—
filtertextnej—
transformationslista av steps.Stepnej—

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.

NyckelTypObligatoriskStandard
filtertextnej—
acknowledgetrue eller false (en block, utelämna för att lämna av)nej—
sender_devicetextnej—
sender_oidtextnej—
transformationslista av hl7v3.Stepnej—

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.

NyckelTypObligatoriskStandard
framingtextja—
delimitertextnej—
start_blocktextnej—
keep_delimitertrue eller falsenej—
record_lengthheltalnej—
trim_paddingtrue eller false (en block, utelämna för att lämna av)nej—
length_bytesheltalnej—
big_endiantrue eller falsenej—
length_includes_headertrue eller falsenej—

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.

NyckelTypObligatoriskStandard
envelopeEnvelopePolicynejkrävs
splittrue eller falsenej—
acknowledgetextnej—
ack_sender_idtextnej—
ack_sender_qualifiertextnej—
arrives_astextnej—
transformationslista över x12.Stepnej—

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.

NyckelTypObligatoriskStandard
addrtextja—
addresstextja—
usernametextnej—
passwordtextnej—
hostnametextnejvärden för addr
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
timeoutvaraktighet, t.ex. 30s eller 5mnej30s

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.

NyckelTypObligatoriskStandard
idtextja—
cert_filetextja—
allow_unsignedtrue eller falsenej—
allow_unencryptedtrue eller falsenej—

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.

NyckelTypObligatoriskStandard
regiontextja—
access_key_idtextnej—
secret_access_keytextnej—
session_tokentextnej—
endpointtextnej—

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.

NyckelTypObligatoriskStandard
whenAckWhennej—
applicationtextnej—
facilitytextnej—
include_trigger_eventtrue eller falsenej—

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.

NyckelTypObligatoriskStandard
accounttextja—
containertextja—
keytextnej—
sastextnej—
endpointtextnej—

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.

NyckelTypObligatoriskStandard
filetextja—
check_everytextnej15 minuter
overheltalnej500

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.

NyckelTypObligatoriskStandard
transformationslista över dicom.Stepnej—

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.

NyckelTypObligatoriskStandard
addresstextja—
cert_filetextja—
key_filetextja—
anchors_filetextja—

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.

NyckelTypObligatoriskStandard
hosttextja—
portheltalnej—
securitytextnej—
usernametextja—
passwordtextnej—
mailboxtextnej—
after_readtextnej—
move_totextnej—
error_foldertextnej—
poll_intervalvaraktighet, såsom 30s eller 5mnej—
tlstlsconf.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.

NyckelTypObligatoriskStandard
listentextja—
tls_certtextnej—
tls_keytextnej—
client_ca_filetextnej—

25.11 ECR-anläggning

ECR-anläggning är organisationen som skickar fallrapporter.

Definierad som ECRFacility i internal/config.

NyckelTypObligatoriskStandard
nametextja—
npitextnej—
phonetextja—
linetextnej—
citytextja—
statetextja—
postal_codetextnej—

25.12 EDIFACT-alternativ

EDIFACT-alternativ är inställningar som endast gäller för en EDIFACT-kanal.

Definierad som EDIFACTOptions i internal/config.

NyckelTypObligatoriskStandard
envelopetextnej—
splittrue eller falsenej—
acknowledgetextnej—

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.

NyckelTypObligatoriskStandard
providertextja—
tenanttextnej—
token_urltextnej—
client_idtextja—
client_secrettextnej—
refresh_tokentextnej—
scopetextnej—

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:

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.

NyckelTypObligatoriskStandard
typetextja—
regiontextnej—
access_key_idtextnej—
secret_access_keytextnej—
session_tokentextnej—
tenant_idtextnej—
token_urltextnej—
client_idtextnej—
client_secrettextnej—
scopetextnej—

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.

NyckelTypObligatoriskStandard
dirtextja—
patterntextnej—
poll_intervalvaraktighet, såsom 30s eller 5mnej—
after_readtextnej—
move_totextnej—
error_dirtextnej—
stable_forvaraktighet, såsom 30s eller 5mnej—
max_file_sizehel talnej—
framedtrue eller falsenej—
rawtrue eller falsenej—
batch_sizehel talnej—
sort_bytextnejnamn

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.

NyckelTypObligatoriskStandard
projecttextnej—
credentials_filetextnej—
endpointtextnej—

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.

NyckelTypObligatoriskStandard
buckettextja—

25.18 IBMMQ-anslutning

IBMMQConnection är en kö som nås via köhanterarens meddelande-REST-API.

Definieras som IBMMQConnection i internal/config.

NyckelTypObligatoriskStandard
urltextja—
queue_managertextja—
queuetextja—
usernametextnej—
passwordtextnej—
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
api_versiontextnej—
timeoutvaraktighet, t.ex. 30s eller 5mnej30s

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.

NyckelTypObligatoriskStandard
mechanismtextja—
usernametextja—
passwordtextja—

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.

NyckelTypObligatoriskStandard
addrtextja—
client_idtextnej—
usernametextnej—
passwordtextnej—
tlstlsconf.Settings (en block, utelämna för att lämna av)nej—
qosheltal (en block, utelämna för att lämna av)nej—
timeoutvaraktighet, t.ex. 30s eller 5mnej30s

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.

NyckelTypObligatoriskStandard
transformationslista med ncpdp.Stepnej—

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.

NyckelTypObligatoriskStandard
decrypt_withtextnej—
passphrasetextnej—
verify_withlista med textnej—
require_signaturetrue eller falsenej—
allow_unencryptedtrue eller falsenej—
pass_plaintrue eller falsenej—

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.

NyckelTypObligatoriskStandard
encrypt_tolista med textnej—
sign_withtextnej—
passphrasetextnej—
armortrue eller falsenej—
no_compresstrue eller falsenej—
file_nametextnej—

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.

NyckelTypObligatoriskStandard
enabledtrue eller falsenej—
max_attemptsheltalnej—
backoffvaraktighet, t.ex. 30s eller 5mnej—
max_backoffvaraktighet, t.ex. 30s eller 5mnej—
max_depthheltalnej—
retain_hoursheltalnej—

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.

NyckelTypObligatoriskStandard
attemptsheltalnej—
backoffvaraktighet, t.ex. 30s eller 5mnej—
max_backoffvaraktighet, t.ex. 30s eller 5mnej—

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.

NyckelTypObligatoriskStandard
transformationslista av hl7v3.Stegnej—

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.

NyckelTypObligatoriskStandard
filtertextnej—
transformertextnej—
preprocessortextnej—
deploytextnej—
undeploytextnej—
postprocessortextnej—
languagetextnej—
timeoutvaraktighet, t.ex. 30s eller 5mnej—
includelista av textnej—
file_rootslista av textnej—
allowlista av textnej—

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:

Definierad som Shadow i internal/config.

NyckelTypObligatoriskStandard
channeltextja—
samplenummernej1
comparelista av textnej—
ignorelista av textnej—
max_differencesheltalnej100
timeoutvaraktighet, såsom 30s eller 5mnej5s

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.

NyckelTypObligatoriskStandard
codetextja—
schemetextja—
displaytextnej—

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:

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:

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:

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.

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.

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:

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:

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:

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

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:

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:

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:

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

NyckelVisas i
access_key_idAWS-åtkomst, FHIR-autentisering, S3-mottagare
accountAzure Blob-åtkomst
ackHTTP-källa, SOAP-källa, Källa
ack_sender_idX12-alternativ
ack_sender_qualifierX12-alternativ
acknowledgeEDIFACT-alternativ, HL7v3-alternativ, X12-alternativ
acksKafka-mottagare
actionSOAP-mottagare
addrAMQP-anslutning, Broker-mottagare, Broker-källa, MQTT-anslutning
addressAMQP-anslutning, DICOM-mottagare, DICOM-frågekälla, Mottagare, Direktadress, TCP-mottagare
ae_titleDICOM-källa
after_queryDatabaskälla
after_readAzure Blob-källa, Direkt IMAP, E-postkälla, Filövervakning, GCS-källa, S3-källa, SFTP-källa
allowSkript
allow_clear_passwordFTP-mottagare
allow_unencryptedAS2-partner, PGP-mottagning
allow_unsignedAS2-partner
allowed_calling_aeDICOM-källa
allowed_sendersE-postkälla
amqpMottagare, Källa
anchors_fileDirektadress
api_versionIBMMQ-anslutning
appendMottagare, SFTP-mottagare
applicationBekräftelse
armorPGP-avsändare
arrives_asX12-alternativ
as2Mottagare, Källa
attachSMTP-mottagare
attach_nameDirektmottagare, SMTP-mottagare
attachment_namesE-postkälla
attachmentsKanal
attemptsÅterförsök
authFHIR-mottagare, PAS-mottagare
authoritiesMPI-mottagare
azure_blobMottagare, Källa
backoffKökonfiguration, Återförsök
base64SOAP-källa
batch_sizeDatabaskälla, Filövervakning
baudSeriell källa
bccSMTP-mottagare
bearer_tokenCDA-mottagare, FHIR-mottagare, HTTP-mottagare, PAS-mottagare
big_endianTCP-ram
blobAzure Blob-mottagare
bodySMTP-mottagare, SOAP-mottagare
brokerMottagare, Källa
brokersKafka-mottagare, Kafka-källa
bucketGCS-åtkomst, S3-mottagare, S3-källa
bundle_scriptFHIR-mottagare
called_aeDICOM-mottagare, DICOM-frågekälla
calling_aeDICOM-mottagare, DICOM-frågekälla
ccSMTP-mottagare
cdaMottagare
cert_fileAS2-mottagare, AS2-partner, AS2-källa, Direktadress
channelMottagare, Skugga
check_everyAvtalsreferens
cityECR-anläggning
claim_us_coreFHIR-mottagare
classXDS-mottagare
client_ca_fileDirekt XDR
client_idE-post OAutentisering, FHIR-autentisering, MQTT-anslutning
client_secretE-post OAutentisering, FHIR-autentisering
codeXDS-kod
columnDatabaskälla
columnsAvgränsad
commentAvgränsad
commit_after_deliveryKafka-källa
compareSkugga
compressAS2-mottagare
compressionKafka-mottagare
configELR-mottagare
containerAzure Blob-åtkomst
content_typeAMQP-mottagare, AS2-mottagare, Azure Blob-mottagare, Broker-mottagare, GCS-mottagare, HTTP-mottagare, S3-mottagare, XDS-mottagare
contractKanal
credentials_fileGCP-åtkomst
dataTypeKanal
data_bitsSeriell källa
databaseMottagare, Källa
decrypt_withPGP-mottagning
default_identifier_systemFHIR-mottagare
delimitedKanal
delimiterAvgränsad, TCP-ram
deploySkript
descriptionKanal
destinationBroker-mottagare, Broker-källa
destinationsKanal
dicomKanal, Mottagare, Källa
dicom_queryKälla
dicomwebMottagare, Källa
dirCDA-mottagare, Mottagare, Dokumentmottagare, FTP-mottagare, Filövervakning, SFTP-mottagare, SFTP-källa
directMottagare, Källa
direct_fromXDS-mottagare
direct_toXDS-mottagare
displayXDS-kod
dnsDirektmottagare
documentMottagare
domainSMB-källa
driverDatabasmottagare, Databaskälla
dsnDatabasmottagare, Databaskälla
duplicate_windowAS2-källa
ecrFHIR-mottagare
edifactKanal
elementSOAP-källa
elrMottagare
emailKälla
emit_on_first_pollDICOM-frågekälla
enabledKanal, Mottagare, Kökonfiguration
encrypt_toPGP-avsändare
endpointAWS-åtkomst, Azure Blob-åtkomst, GCP-åtkomst, S3-mottagare
envelopeEDIFACT-alternativ, X12-alternativ
error_dirFilövervakning, SFTP-källa
error_folderDirekt IMAP, E-postkälla
error_prefixAzure Blob-källa, GCS-källa, S3-källa
expect_replyTCP-mottagare
extractBilagor
facilityBekräftelse, ECR-anläggning
facility_idSOAP-mottagare
facility_typeXDS-mottagare
fail_on_bodyHTTP-mottagare
fault_is_successSOAP-mottagare
fault_on_nakSOAP-källa
fhirMottagare
fileAvtalsreferens, Källa
file_nameAS2-mottagare, Mottagare, Dokumentmottagare, FTP-mottagare, PGP-avsändare, SFTP-mottagare
file_rootsSkript
filterKanal, Avgränsad, Mottagare, HL7v3-alternativ, Skript
flow_controlSeriell källa
follow_redirectsHTTP-mottagare
follow_symlinksFilkälla
font_sizeDokumentmottagare
formatDokumentmottagare, S3-mottagare
framedAzure Blob-källa, FTP-mottagare, Filövervakning, GCS-källa, S3-mottagare, S3-källa, SFTP-mottagare, SFTP-källa
framingTCP-ram
fromAS2-mottagare, SMTP-mottagare
from_beginningKafka-källa
ftpMottagare, Källa
gcsMottagare, Källa
groupKanal, Kafka-källa
group_bySNS-mottagare, SQS-mottagare
has_headerAvgränsad
headerSOAP-mottagare
headersBroker-mottagare, CDA-mottagare, DICO Mweb-mottagare, FHIR-mottagare, HTTP-mottagare, Kafka-mottagare, SOAP-mottagare, XDS-mottagare
heartbeatBroker-källa
hl7v3Kanal
hostBroker-mottagare, Broker-källa, Direkt IMAP, E-postkälla, FTP-mottagare, FTP-källa, SFTP-mottagare, SFTP-källa, SMB-källa, SMTP-mottagare
hostnameAMQP-anslutning
httpMottagare, Källa
ibm_mqMottagare, Källa
idAS2-partner, AS2-källa
id_typeMPI-mottagare
identifier_systemsCDA-mottagare, FHIR-mottagare
idle_timeoutDICOM-källa, Källa, TCP-källa
ignoreSkugga
imapDirektkälla
includeSkript
include_trigger_eventBekräftelse
insecure_skip_host_key_checkSFTP-mottagare, SFTP-källa
insecure_skip_verifyFTP-mottagare, FTP-källa, SMTP-mottagare, Web DAV-källa
intervalDICOM-frågekälla
javascriptMottagare, Källa
kafkaMottagare, Källa
keep_aliveTCP-mottagare
keep_blank_linesAvgränsad
keep_delimiterTCP-ram
keyAzure Blob-åtkomst, Kafka-mottagare, S3-mottagare
key_columnDatabaskälla
key_fileAS2-mottagare, AS2-källa, Direktadress, SFTP-mottagare, SFTP-källa
key_passphraseSFTP-mottagare, SFTP-källa
known_hosts_fileSFTP-mottagare, SFTP-källa
landscapeDokumentmottagare
languageSkript
ldapDirektmottagare
length_bytesTCP-ram
length_includes_headerTCP-ram
levelDICOM-frågekälla
limitDICOM-frågekälla
lineECR-anläggning
listenAS2-källa, DICO Mweb-källa, DICOM-källa, Direktkälla, Direkt XDR, HTTP-källa, SOAP-källa, Källa, TCP-källa
loginBroker-mottagare, Broker-källa
mailboxDirekt IMAP, E-postkälla
matchDICOM-frågekälla
max_attemptsDatabaskälla, Kökonfiguration
max_backoffKökonfiguration, Återförsök
max_bytesDirektkälla
max_connectionsKälla, TCP-källa
max_depthKökonfiguration
max_differencesSkugga
max_file_sizeFilövervakning, SFTP-källa
max_message_sizeAS2-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_messagesPub Sub-källa, SQS-källa
max_object_bytesDICO Mweb-källa, DICOM-källa
max_object_sizeAzure Blob-källa, GCS-källa, S3-källa
max_open_connsDatabasmottagare
mechanismKafka SASL
methodHTTP-mottagare
move_toAzure Blob-källa, Direkt IMAP, E-postkälla, Filövervakning, GCS-källa, S3-källa, SFTP-källa
mpiMottagare
mqttMottagare, Källa
nameKanal, Kanalmottagare, Mottagare, ECR-anläggning
ncpdpKanal
no_compressPGP-avsändare
no_mergeMPI-mottagare
non_persistentIBMMQ-mottagare
npiECR-anläggning
oauthE-postkälla
objectGCS-mottagare
on_no_documentCDA-mottagare
order_byPub Sub-mottagare
overAvtalsreferens
overlapDICOM-frågekälla
paramsDatabasmottagare
paritySeriell källa
partner_cert_fileAS2-mottagare
partnersAS2-källa
pasMottagare
pass_plainPGP-mottagning
passcodeBroker-mottagare, Broker-källa
passphrasePGP-mottagning, PGP-avsändare
passwordAMQP-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
pathAS2-källa, DICO Mweb-källa, HTTP-källa, SOAP-källa
path_styleS3-mottagare, S3-källa
patient_domainXDS-mottagare
patient_rootDICOM-frågekälla
patternFilövervakning, SFTP-källa
payerPAS-mottagare
persistentBroker-mottagare
pgpMottagare, Källa
phoneECR-anläggning
poll_intervalAzure 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
portDirekt IMAP, E-postkälla, Seriell källa
postal_codeECR-anläggning
postprocessorSkript
practice_settingXDS-mottagare
prefetchAMQP-källa
prefixAzure Blob-källa, GCS-källa, S3-källa
preprocessorSkript
profileSOAP-mottagare, SOAP-källa
projectGCP-åtkomst
protocolE-postkälla
providerE-post OAutentisering
pubsubMottagare, Källa
purposeTEFCA-mottagare
qosMQTT-anslutning
queryDatabaskälla
query_timeoutDatabaskälla
queueMottagare, IBMMQ-anslutning
queue_managerIBMMQ-anslutning
queue_urlSQS-mottagare, SQS-källa
quiet_afterSeriell källa
quoteAvgränsad
rawFilövervakning
rctcECR-mottagare, ELR-mottagare
read_timeoutHTTP-källa, SOAP-källa
reassembleBilagor
receiptAS2-mottagare
receipt_urlAS2-mottagare
recipient_certs_dirDirektmottagare
reconnectAMQP-källa, Broker-källa, MQTT-källa, Pub Sub-källa
record_lengthTCP-ram
refresh_tokenE-post OAutentisering
regionAWS-åtkomst, FHIR-autentisering, S3-mottagare
reject_on_warningFHIR-mottagare
relaxedAvgränsad
reopen_afterSeriell källa
replySeriell källa, TCP-källa
reply_textSeriell källa, TCP-källa
request_mdnDirektmottagare
require_agreementCDA-mottagare
require_signaturePGP-mottagning
response_elementSOAP-källa
response_namespaceSOAP-källa
response_transformerMottagare
results_toPAS-mottagare, TEFCA-mottagare
retainMQTT-mottagare
retain_hoursMottagare, Kökonfiguration
retryMottagare
returnDICOM-frågekälla
rootFTP-källa, Filkälla, SMB-källa
s3Mottagare, Källa
sampleSkugga
sasAzure Blob-åtkomst
saslKafka-mottagare, Kafka-källa
schemeXDS-kod
scopeE-post OAutentisering, FHIR-autentisering
scriptKanal, Java Script-mottagare, Java Script-källa
scriptsKanal
secret_access_keyAWS-åtkomst, FHIR-autentisering, S3-mottagare
securityDirekt IMAP, E-postkälla, FTP-mottagare, FTP-källa
selectorBroker-källa
sender_deviceHL7v3-alternativ
sender_oidHL7v3-alternativ
serialKälla
server_side_encryptionS3-mottagare
session_timeoutKafka-källa
session_tokenAWS-åtkomst, FHIR-autentisering, S3-mottagare
sftpMottagare, Källa
shadowKanal
shareSMB-källa
sign_withPGP-avsändare
smbKälla
smtpMottagare
smtp_hostDirektmottagare, Direktkälla
snsMottagare
soapMottagare, Källa
sop_classesDICOM-mottagare, DICOM-källa
sort_byFilövervakning
sourceKanal, ECR-mottagare
source_idXDS-mottagare
splitAvgränsad, EDIFACT-alternativ, X12-alternativ
sqsMottagare, Källa
ssn_systemMPI-mottagare
stable_forFilövervakning, SFTP-källa
start_blockTCP-ram
starttlsSMTP-mottagare
stateECR-anläggning
statementDatabasmottagare
stop_bitsSeriell källa
storage_classGCS-mottagare, S3-mottagare
subjectAS2-mottagare, Direktmottagare, SMTP-mottagare, SNS-mottagare
subscriptionPub Sub-källa
subscription_idBroker-källa
success_on_undefinedJava Script-mottagare
success_statusHTTP-mottagare
suffixAzure Blob-källa, GCS-källa, S3-källa
tablesKanal
takeE-postkälla
tcpMottagare, Källa
tefcaMottagare
temp_suffixMottagare, Dokumentmottagare, FTP-mottagare, SFTP-mottagare
templateDatabaskälla, Dokumentmottagare
tenantE-post OAutentisering
tenant_idFHIR-autentisering
textDirektmottagare
tierAzure Blob-mottagare
timeoutAMQP-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
timezoneFHIR-mottagare
titleDokumentmottagare
tlsAMQP-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_certDirektkälla, Direkt XDR
tls_keyDirektkälla, Direkt XDR
toAS2-mottagare, Direktmottagare, SMTP-mottagare
tokenDICO Mweb-mottagare, DICO Mweb-källa, HTTP-källa, SOAP-källa, XDS-mottagare
token_urlE-post OAutentisering, FHIR-autentisering
topicKafka-mottagare, MQTT-mottagare, MQTT-källa, Pub Sub-mottagare
topic_arnSNS-mottagare
topicsKafka-källa
transfer_syntaxesDICOM-mottagare, DICOM-källa
transformationsKanal, DICOM-alternativ, Avgränsad, HL7v3-alternativ, NCPDP-alternativ, Skriptalternativ, X12-alternativ
transformerSkript
trim_paddingTCP-ram
trim_spaceAvgränsad
typeMottagare, FHIR-autentisering, Källa
undeploySkript
unencryptedAS2-mottagare
unsignedAS2-mottagare
unsigned_receiptAS2-mottagare
urlAS2-mottagare, CDA-mottagare, DICO Mweb-mottagare, FHIR-mottagare, HTTP-mottagare, IBMMQ-anslutning, SOAP-mottagare, Web DAV-källa, XDS-mottagare
userFTP-mottagare, FTP-källa, SFTP-mottagare, SFTP-källa, SMB-källa, Web DAV-källa
usernameAMQP-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_sendFHIR-mottagare
verify_withPGP-mottagning
versionCDA-mottagare, FHIR-mottagare, SOAP-mottagare, SOAP-källa
visibility_timeoutSQS-källa
wait_secondsSQS-källa
warnings_are_errorsSOAP-mottagare
webdavKälla
whenBekräftelse
windowDICOM-frågekälla
writeCDA-mottagare
wsdlSOAP-källa
x12Kanal
x12_asMottagare
xdmDirektmottagare
xdm_source_idDirektmottagare
xdrDirektkälla
xdsMottagare