Architecture Approved
Standard Message Headers define the required metadata fields for HSOne service communication across HTTP and Kafka protocols.
- Avro Schema Template: StandardMetaDataSchema.avsc
- Core Object: StandardMetadata.java
- Controller Implementation: LicenseController.java
| Field Name | Status | Alias | Requirement Description | Type | HTTP | Kafka |
|---|---|---|---|---|---|---|
| sessionId | Decided | — | Async routing | String | OPTIONAL | OPTIONAL |
| messageId | Decided | correlationID, idempotencyID | Origination strategy. To be used for idempotency checks and as the correlation id for related messages. | String (UUID Recommended) | REQUIRED | REQUIRED |
| createdOn | Decided | — | Generated for each new message | Long (representing epoch in milliseconds) | REQUIRED | REQUIRED |
| tenantIdType | Decided | — | [ACCOUNT_ID, SERIAL_NUMBER, CUSTOMER_NUMBER] *default = CUSTOMER_NUMBER. Others should be approved and added to this document. CUSTOMER_NUMBER should represent only a child-most account. | String (represents enum) | REQUIRED | REQUIRED |
| tenantId | Decided | salesforce accountId, customerNumber, SerialNumber | ⚠️ Warning: An HSOne OrgId needs to become an engineering/architecture priority and is essential to ensuring data is processed securely. We are currently using salesforce accountId for lack of a better current option but should be considered expensive technical debt. | String | REQUIRED | REQUIRED |
| userId | REVIEWING | clientId | Auth0 userId or Auth0 clientId for M2M. We should get more clarity on this as the Auth0 projects move forward. Must be provided but can be either a user ID or a machine ID if a user ID is not available. Use the first identifiable system. Get as close to the initial request as possible. Should we add UserIdType? | String | REQUIRED | REQUIRED |
| systemId | UNDECIDED | — | This is the system user | — | — | — |
| applicationId | Decided | — | [DENTRIX_CORE, DENTRIX_ENTERPRISE, ASCEND, etc] Originating application id (mostly useful for on-prem applications where we do not have proper identity/auth solutions) | String (represents enum) | OPTIONAL | OPTIONAL |
| applicationVersion | UNDECIDED | — | Version number for originating application | String | OPTIONAL | OPTIONAL |
| isSynthetic | UNDECIDED | — | A marker for synthetic test data that can be filtered out of the streaming before triggering non-idempotent events. Synthetics can be generated by test and APM tooling to validate continuous uptimes and SLOs. | boolean (default false) | OPTIONAL | OPTIONAL |
This example demonstrates how standard metadata flows through a multi-service architecture:
Salesforce triggers event originating from Salesforce by assigning "Voice-Perio" product to a practice's account. Using Confluent Cloud Connector for Salesforce, event is published to:
private.crm.salesforce.order_change_delta_event.1CRM-Service consumes Salesforce event, and calls Licensing-Service through sync API call:
POST https://licensing-service.dev-dentalapp.cc/api/licenseLicensing-Service receives command request via API then:
- Publishes a command to:
private.licensing.license.command.1 - Consumes command request, stores event data and publishes event to:
public.licensing.license.event.1
- Publishes a command to:
Voice-Perio-Service consumes
LicenseEventthen:- Calls Bola API to provision a new Bola Account for the practice
- POSTs a
ResourceCommandRequestto:POST https://licensing-service.dev-dentalapp.cc/api/resource
Licensing-Service receives command request then:
- Publishes a command to:
private.licensing.resource.command.1 - Consumes command request, stores event data and publishes
ResourceEventto:public.licensing.resource.event.1
- Publishes a command to:
Licensing-Service receives
ResourceEventthen:- Publishes a command to update the LicenseStatus from
"PROVISIONING"to"PROVISIONED":private.licensing.license.command.1 - Consumes command request, makes change, then stores event data and publishes
LicenseEventto:public.licensing.license.event.1
- Publishes a command to update the LicenseStatus from
An HSOne OrgId needs to become an engineering/architecture priority and is essential to ensuring data is processed securely. We are currently using Salesforce accountId for lack of a better current option but should be considered expensive technical debt.
The messageId field serves dual purposes:
- Idempotency checks: Prevents duplicate message processing
- Correlation ID: Links related messages across services
Use UUID format for globally unique identifiers.
The isSynthetic flag allows test and APM tooling data to be filtered from production event streams before triggering non-idempotent operations.