Skip to main content

Provider Directory Service — Application Logic

Status: populated Owner: TBD Last updated: 2026-04-17 Companion: DOMAIN_MODEL · API_CONTRACTS · EVENT_SCHEMAS

1. Use Cases

1.1 Commands

CommandAggregateNotes
CreatePractitionerPractitionerValidate identifier uniqueness per authority
UpdatePractitionerPractitionerOptimistic lock
DeactivatePractitionerPractitionerEnds all roles; blocks new selections
SuspendPractitionerPractitionerTemporary; blocks selections but preserves data
AddCredentialPractitioner (Credential child)Auto-flags privileges
UpdateCredentialCredentialExpiry extension
RevokeCredentialCredentialTriggers privilege revocation cascade
AssignPractitionerRoleRoleValidates required credentials (BR-PROV-001)
EndPractitionerRoleRoleSets period.end
UpsertHealthcareServiceHealthcareService
UpsertServiceEndpointEndpoint
RunEndpointHealthcheckEndpointScheduled; updates health status
LinkPractitionerToUserPractitionerBind userId from identity-service

1.2 Queries

QueryReturns
SearchPractitionersFuzzy name/identifier/specialty; multi-script
GetPractitioner(id)Full profile
ListPractitionerRoles(practitionerId)All roles (active + historical)
ListRolesByNode(nodeId)Roles scoped to node
ListEndpoints(orgNodeId?, type?)Endpoints catalog
CanPractitionerPerform(practitionerId, privilegeKey)Boolean (hot path for order/laboratory/radiology services)
ListExpiringCredentials(daysAhead)For nightly expiry job

2. Ports

PortPurpose
PractitionerRepositoryCRUD
PractitionerRoleRepositoryCRUD
HealthcareServiceRepositoryCRUD
ServiceEndpointRepositoryCRUD
PractitionerSearchIndexOpenSearch adapter
TerminologyClientValidate specialty codes
AccessPolicyClientPOST /internal/access/evaluate
LicensingClientModule gate
EventPublisherOutbox-backed
FhirProjectorPractitioner / Role / HealthcareService / Endpoint
CommunicationClientCredential expiry notifications
FacilityClientNode existence check (on role creation)
EndpointHealthCheckerHTTP/TLS probe

3. Orchestration

3.1 Role assignment with privilege gating (BR-PROV-001)

3.2 Credential expiry cascade

4. Saga / Outbox

  • Transactional outbox for all events.
  • Inbox dedup on identity.user.registered.v1 and facility.provider_membership.*.

5. Error Handling

ErrorHTTPCode
Duplicate identifier409IDENTIFIER_CONFLICT
Required credential missing422CREDENTIAL_REQUIRED
Provider deactivated409PRACTITIONER_DEACTIVATED
Specialty code not found422SPECIALTY_UNKNOWN
Node not found404HIERARCHY_NODE_NOT_FOUND
Access denied403ACCESS_DENIED
Optimistic lock409VERSION_MISMATCH

6. Policies

PolicyTriggerReaction
OnUserRegisteredPolicyidentity.user.registered.v1Optional JIT shadow practitioner in pending_profile state if registrationSource=clinician_sso
OnNodeMembershipAssignedPolicyfacility.provider_membership.assigned.v1Update cached provider scope summary
OnGdprRequestPolicygdpr.subject_request.received.v1Anonymize practitioner record if no clinical history dependency

OpenSearch index practitioners_{tenant}_{version} with:

  • N-gram analyser for Latin + Arabic scripts.
  • ICU transliteration to support "Ahmad" ↔ "احمد" matching.
  • Fields: names (all variants), identifiers, specialties, active status, node-scoped role summary.
  • Rebuild: daily full; incremental on events.