The TEFCA responder — discovery, document query, document retrieve

FeatureSecurityService
Shipped
August 26, 2026 at 6:04 AM UTC
Author
Kamo
Commit
757045a

The three operations a partner actually calls, expressed over FHIR rather than SOAP: IHE's XCPD and XCA shapes, on the QHIN Technical Framework's FHIR path, because that is where new connections are being built and a SOAP stack is a second security surface over the same data. AUTHENTICATION. These have no session, so ExchangePartnerAuthenticator resolves a bearer credential and the tenant comes from the partner row it finds. The X-Exchange-Trust-Id header is compared against the authenticated partner and logged when it disagrees — never used to select one. Two guard tests caught the first version: the endpoint ratchet, because it resolves no session, and EhrEndpointGuardTest's tenant-from-the-caller rule, because it took a tenantId parameter. The second was a real flaw and is gone; the first is answered by a baseline entry that says why, plus a new PARTNER_AUTHENTICATED category whose own test checks the credential path EXISTS rather than merely excusing it. DISCOVERY refuses thin demographics. A family name alone is a way to enumerate a practice's patient list. Candidates carry their match score, because a requester who cannot see it cannot make the judgement the low-confidence band exists for, and finding nobody is an empty bundle rather than an error — "we do not have this person" is a common and legitimate answer. PART 2 DATA IS WITHHELD SILENTLY. A query omits it; a retrieve answers 404 rather than 403. Forbidden would confirm the document exists, and telling a partner "there is data here you cannot have" discloses the existence of substance-use-disorder treatment — which is the exact thing Part 2 protects. A restricted patient answers an empty bundle for the same reason. RETRIEVE IS RE-AUTHORISED IN FULL. The query said the document exists; this is the call that moves a patient's record to another organization, and a partner suspended between the two must not be served by the second. Every request records an ExchangeRequest row before the response is built, including the refusals. An investigation is about the refusals.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing