Tenant Service
Overview
The Tenant service is the entry point for configuring a tenant into Link Cloud. The service is responsible for maintaining and generating events for the scheduled measure reporting periods that the tenant is configured for. These events contain the initial information needed for Link Cloud to query resources and perform measure evaluations based on a specific reporting period.
The Tenant service uses Quartz with ADO Job Stores to manage jobs across multiple instances of the service, primarily for producing ReportScheduled Kafka events.
flowchart LR
nTenantService_F25B55["Service: Tenant Service"]
nTenantService_F25B55 -->|produces| nAuditableEventOccurred_2E7ED8D7["Event: AuditableEventOccurred"]
nTenantService_F25B55 -->|produces| nReportScheduled_BC6D32E["Event: ReportScheduled"]
nTenantService_F25B55 -->|sends| nGenerateReportRequested_7BC99734["Command: GenerateReportRequested"]
nTenantService_F25B55 -->|provides| nGetFacilitiesList_5CEDF833["Query: GetFacilitiesList"]
nTenantService_F25B55 -->|provides| nGetFacilityConfig_32C58A79["Query: GetFacilityConfig"]
nTenantService_F25B55 -->|provides| nGetServiceInfo_13F02E06["Query: GetServiceInfo"]
nTenantService_F25B55 -->|requests| nGetFacilitiesList_5CEDF833["Query: GetFacilitiesList"]
nTenantService_F25B55 -->|requests| nGetFacilityConfig_32C58A79["Query: GetFacilityConfig"]
nTenantService_F25B55 -->|requests| nGetServiceInfo_13F02E06["Query: GetServiceInfo"]
subgraph nCompliance_DBAE25D_domain["Domain: Compliance"]
nAuditableEventOccurred_2E7ED8D7
end
subgraph nReport_4D4FBBDA_domain["Domain: Report"]
nGenerateReportRequested_7BC99734
nReportScheduled_BC6D32E
end
subgraph nTenant_379CD514_domain["Domain: Tenant"]
nGetFacilitiesList_5CEDF833
nGetFacilityConfig_32C58A79
nGetServiceInfo_13F02E06
nTenantService_F25B55
end
Common Configurations
- Swagger
- Azure App Configuration
- Kafka Configuration
- Kafka Consumer Retry Configuration
- Service Registry Configuration
- CORS Configuration
- Token Service Configuration
- Service Authentication
- SQL Server Database Configuration
Custom Configuration
| Name | Value | Secret? |
|---|---|---|
| MeasureConfig__CheckIfMeasureExists | true or false | No |
Soft Delete
The Tenant service supports soft deletion of facilities. Rather than permanently removing a facility record, the soft delete endpoint marks the facility with an isDeleted flag set to true. This preserves the facility's configuration and historical data while effectively removing it from active use.
DELETE /api/Facility/softDelete/{facilityId}
Soft deletes a facility by setting its isDeleted flag to true.
Parameters:
facilityId(path, required): The unique identifier of the facility to soft delete.
Response:
200 OK: Facility soft deleted successfully. Returns the updated facility configuration.400 Bad Request: If the request is invalid.404 Not Found: If no facility exists for the specified facilityId.500 Internal Server Error: If an error occurs during processing.
Features and Functionality
Key Management
Keys are managed independently by the tenant service, and then associated with tenants. These keys are used for signing authentication JWTs that are passed to /token endpoints at the EHRs. EHRs check that the JWTs are signed using a key found in the JWKS endpoint exposed by Link.
- Key Registry: A global repository where all JWT signing keys are stored and managed. Each key includes metadata such as kid, algorithm, creation timestamp, status (active, disabled, expired), and an optional primary flag.
- Lifecycle Operations:
- Create: Keys can be generated through the admin API/UI with algorithm selection and optional designation as primary.
- Disable/Delete: Keys no longer in use can be deactivated or removed without disrupting tenant authentication, unless actively in use. This can occur when needing to rotate a key.
- Rotating Keys:
- Create a new key
- Associate the new key with tenants
- Delete the old key.
- Tenant Association (handled separately):
- Tenants reference keys by kid through the Tenant Service configuration interface.
- A tenant may use a shared or unique key from the registry.
- Changing a tenant’s associated key does not impact the underlying key object—it only changes the reference.
- JWKS documents are managed automatically
- When keys change the JWKS document is re-generated
- The JWKS document is stored on the file system
- The JWKS document on the file system is exposed via proxy to external parties for verification (such as EHRs)
The following sequence diagram illustrates how the keys are used during the authentication requests to EHRs:
sequenceDiagram
participant L as Link
participant J as JWKS Endpoint
participant E as EHR Vendor
L->>L: Create JWT
L->>L: Sign JWT (with kid)
L->>J: Publish key to JWKS
L->>E: POST /token (with JWT)
E->>J: GET /.well-known/jwks.json
J-->>E: Return JWKS document
E->>E: Verify signature using kid
E-->>L: Return access token
Database Schema
| Name | Type | Required? | Length |
|---|---|---|---|
| MigrationId | string | Yes | 150 |
| ProductVersion | string | Yes | 32 |
| Name | Type | Required? | Length |
|---|---|---|---|
| Id | string | Yes | |
| FacilityId | string | Yes | |
| FacilityName | string | No | |
| CreateDate | string (date-time) | Yes | |
| ModifyDate | string (date-time) | No | |
| ScheduledReports | string | Yes | |
| TimeZone | string | Yes | |
| IsDeleted | boolean | Yes | |
| Vendor | string | No | 50 |
OpenAPI Operations
Get facilities
Route Parameters
None
Query Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | No | ||
| facilityName | No | ||
| timeZone | No | ||
| vendor | No | ||
| sortBy | No | ||
| sortOrder | No | ||
| pageSize | No | ||
| pageNumber | No | ||
| includeDeleted | No |
Creates a facility configuration.
Route Parameters
None
Query Parameters
None
Get a list of all facilities
Route Parameters
None
Query Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| search | No | ||
| includeDeleted | No |
Gets a facility configuration by facilityId.
Route Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | Yes |
Query Parameters
None
Updates a facility configuration.
Route Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | Yes |
Query Parameters
None
Deletes a facility configuration.
Route Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | Yes |
Query Parameters
None
Route Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | Yes |
Query Parameters
None
Restores a soft-deleted facility configuration.
Route Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | Yes |
Query Parameters
None
Generate
Route Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | Yes |
Query Parameters
None
Route Parameters
| Name | Type | Required? | Description |
|---|---|---|---|
| facilityId | Yes |
Query Parameters
None
Route Parameters
None
Query Parameters
None
Health check endpoint
Route Parameters
None
Query Parameters
None
Relationships
flowchart LR
nTenantService_F25B55["Service: Tenant Service"]
nTenantService_F25B55 -->|produces| nAuditableEventOccurred_2E7ED8D7["Event: AuditableEventOccurred"]
nTenantService_F25B55 -->|produces| nReportScheduled_BC6D32E["Event: ReportScheduled"]
nTenantService_F25B55 -->|sends| nGenerateReportRequested_7BC99734["Command: GenerateReportRequested"]
nTenantService_F25B55 -->|provides| nGetFacilitiesList_5CEDF833["Query: GetFacilitiesList"]
nTenantService_F25B55 -->|provides| nGetFacilityConfig_32C58A79["Query: GetFacilityConfig"]
nTenantService_F25B55 -->|provides| nGetServiceInfo_13F02E06["Query: GetServiceInfo"]
nTenantService_F25B55 -->|requests| nGetFacilitiesList_5CEDF833["Query: GetFacilitiesList"]
nTenantService_F25B55 -->|requests| nGetFacilityConfig_32C58A79["Query: GetFacilityConfig"]
nTenantService_F25B55 -->|requests| nGetServiceInfo_13F02E06["Query: GetServiceInfo"]
subgraph nCompliance_DBAE25D_domain["Domain: Compliance"]
nAuditableEventOccurred_2E7ED8D7
end
subgraph nReport_4D4FBBDA_domain["Domain: Report"]
nGenerateReportRequested_7BC99734
nReportScheduled_BC6D32E
end
subgraph nTenant_379CD514_domain["Domain: Tenant"]
nGetFacilitiesList_5CEDF833
nGetFacilityConfig_32C58A79
nGetServiceInfo_13F02E06
nTenantService_F25B55
end