Polaris FSH Coding Standards¶
Version 1.1.0 — Production Standards
Last Updated: 2025-07-15
This document defines the comprehensive coding standards for FHIR Shorthand (FSH) files in the Polaris FHIR Implementation Guide. All FSH development must adhere to these standards to ensure consistency, maintainability, and compliance with the Polaris architecture.
Table of Contents¶
- Core Principles
- File Organization Standards
- Profile Development Standards
- Invariant Standards
- Terminology and Binding Standards
- Reference and Identifier Standards
- Documentation Standards
- Must Support Standards
- Extension Standards
- Validation and Testing Standards
- Version Management Standards
- Common Patterns and Examples
Core Principles¶
Design Philosophy¶
Polaris FSH artifacts must: - Communicate explicit clinical and technical intent - Enforce rigorous structure, bindings, and identifiers - Reflect real-world primary care documentation practices - Promote modularity, reuse, and semantic integrity - Integrate cleanly into a navigable, standards-compliant Implementation Guide
Semantic Modeling Principles¶
- Retain Raw Source Codes: Always preserve original EMR codes alongside mapped standard terminologies to prevent semantic loss
- Model Data, Not UI: Represent clinical concepts, not form fields or interface elements
- Use Extensions Sparingly: Only when no base element exists and the need is clearly documented
- First-Class Resources: Treat Device, Practitioner, PractitionerRole, and Organization as distinct entities
- Deliberate Must Support: Only mark elements that are reliably populated and required for downstream use
File Organization Standards¶
File Structure¶
// PolariResourceType.fsh
// 1. File header comment
// 2. Aliases (if not using shared aliases file)
// 3. Invariants
// 4. Profile definition
// 5. Element constraints
Naming Conventions¶
| Element | Convention | Example |
|---|---|---|
| File name | StructureDefinition-polaris-[resourcetype].fsh |
StructureDefinition-polaris-core-patient.fsh |
| Profile name | Polaris[ResourceType] |
PolarisCorePatient |
| Profile ID | polaris-[resourcetype] |
polaris-core-patient |
| Invariant name | [resourcetype]-[constraint-description] |
patient-has-polaris-id |
One Artifact Per File¶
- Each
.fshfile contains exactly ONE profile, extension, or value set - Shared aliases may be defined in a separate
aliases.fshfile - Related invariants are included in the same file as their profile
Profile Development Standards¶
Required Metadata¶
Every profile MUST include:
Profile: Polaris[ResourceType]
Parent: [BaseResource or CACore Profile]
Id: polaris-[resourcetype]
Title: "Polaris [Resource Type]"
Description: "[Comprehensive description of the profile's purpose and use]"
* ^url = "https://fhir.apps.health/StructureDefinition/polaris-[resourcetype]"
* ^status = #draft
* ^version = "1.1.0"
* ^date = "2025-01-15"
* ^publisher = "Alberta Health Services"
* ^contact.name = "AHS FHIR Team"
* ^contact.telecom.system = #url
* ^contact.telecom.value = "https://www.albertahealthservices.ca"
* ^jurisdiction = urn:iso:std:iso:3166#CA "Canada"
Profile Hierarchy¶
- Prefer CA-Core+ profiles as parent when available
- Fall back to base FHIR R4 resources when CA-Core+ doesn't exist
- Document the rationale for parent choice in the description
Element Ordering¶
Organize element constraints in this order:
1. Resource-level invariants (obeys)
2. Metadata elements (id, meta, implicitRules, language)
3. Narrative (text)
4. Extensions
5. Identifiers
6. Status/workflow elements
7. Clinical/domain-specific elements (in logical groupings)
8. References to other resources
Invariant Standards¶
Invariant Structure¶
Invariant: [resourcetype]-[constraint-name]
Description: "[Human-readable description of the constraint]"
Severity: #error
Expression: "[FHIRPath expression]"
XPath: "[XPath expression if needed for compatibility]"
Recommended Invariants¶
Identifier Pattern Invariant¶
Top-level Polaris profiles SHOULD include:
Invariant: [resourcetype]-has-polaris-id
Description: "Recommended to have at least one identifier using Polaris canonical system"
Severity: #warning
Expression: "identifier.exists(system.matches('^https://fhir\\.apps\\.health/NamingSystem/[A-Za-z0-9._-]+-[resourcetype]-identifier$'))"
When to include: - ✅ Top-level profiles (Patient, Observation, Encounter, etc.) - ❌ Contained profiles (PolarisContainedMedicationCore) - ❌ Extensions - ❌ Nested/embedded elements
Purpose: Supports resource identification and traceability across systems
Invariant Best Practices¶
- Use descriptive names that indicate what's being validated
- Write clear error messages that guide implementers
- Test FHIRPath expressions thoroughly
- Consider performance impact of complex expressions
- Document any business rules encoded in invariants
Terminology and Binding Standards¶
Binding Strength Guidelines¶
| Use Case | Binding Strength | Example |
|---|---|---|
| Closed, well-defined sets | required |
Resource status fields |
| Preferred but extensible sets | preferred |
Clinical observations |
| Examples or suggestions | example |
Reason codes |
| Broad, open sets | extensible |
Condition codes |
Binding Syntax¶
// Required binding
* status from $resource-status (required)
// Extensible binding with documentation
* code from $polaris-core-observation-codes (extensible)
* code ^binding.description = "Codes representing types of observations used in primary care"
// Sliced bindings for different contexts
* code.coding ^slicing.discriminator.type = #value
* code.coding ^slicing.discriminator.path = "system"
* code.coding ^slicing.rules = #open
* code.coding contains
loinc 0..1 MS and
snomed 0..1 MS and
local 0..1 MS
Value Set References¶
- Always use aliases for value set URLs
- Define custom value sets in separate
.fshfiles - Document the clinical rationale for custom value sets
- Include expansion criteria and maintenance processes
Reference and Identifier Standards¶
Identifier Requirements¶
// Identifier constraints
* identifier 1..* MS
* identifier ^short = "Business identifiers for this resource"
* identifier ^definition = "Business identifiers assigned by the source EMR system"
* identifier.system 1..1 MS
* identifier.value 1..1 MS
* identifier.type MS
Reference Patterns¶
// Typed references with Polaris profiles
* subject only Reference(PolarisCorePatient)
* subject 1..1 MS
* subject.identifier 1..1 MS
* subject.identifier.system 1..1
* subject.identifier.value 1..1
// Multiple allowed types
* performer only Reference(PolarisCorePractitioner or PolarisCorePractitionerRole or PolarisCoreOrganization)
// Identifier-based references preferred
* subject.reference 0..1
* subject.identifier 1..1 MS
* subject.display MS
Canonical URL Patterns¶
| Resource Type | Pattern | Example |
|---|---|---|
| Profile | https://fhir.apps.health/StructureDefinition/polaris-[type] |
https://fhir.apps.health/StructureDefinition/polaris-core-patient |
| Extension | https://fhir.apps.health/StructureDefinition/ext-[name] |
https://fhir.apps.health/StructureDefinition/ext-raw-code |
| Value Set | https://fhir.apps.health/ValueSet/[name] |
https://fhir.apps.health/ValueSet/polaris-app-state-cores |
| Code System | https://fhir.apps.health/CodeSystem/[name] |
https://fhir.apps.health/CodeSystem/polaris-app-state-core |
| Naming System | https://fhir.apps.health/NamingSystem/[instance]-[type]-identifier |
https://fhir.apps.health/NamingSystem/emr-1-patient-identifier |
Documentation Standards¶
Element Documentation¶
Every constrained element should include:
* element.name ^short = "[Brief description < 80 chars]"
* element.name ^definition = "[Complete definition explaining clinical/business meaning]"
* element.name ^comment = "[Implementation guidance, warnings, or clarifications]"
* element.name ^requirements = "[Business or clinical requirement driving this constraint]"
Profile Documentation Requirements¶
- Description: Comprehensive overview including:
- Clinical/business purpose
- Relationship to other Polaris profiles
- Alignment with CA-Core+ or other standards
-
Key constraints and requirements
-
Implementation Notes: Document in profile description or page content:
- Integration patterns
- Common implementation challenges
- Example scenarios
-
Migration considerations
-
Mapping Documentation: Include in separate markdown files:
- Source system field mappings
- Terminology mappings
- Transformation logic
- Data quality considerations
Must Support Standards¶
Must Support Criteria¶
Mark an element as Must Support (MS) only when ALL of the following apply: 1. The element is reliably populated by source systems 2. Downstream systems must process the element 3. The element is required for core use cases 4. There's a clear implementation expectation
Must Support Patterns¶
// Basic MS marking
* identifier MS
// MS with specific system
* identifier MS
* identifier.system = "https://fhir.apps.health/alberta/NamingSystem/phn" (exactly)
* identifier.value MS
// Conditional MS using slicing
* identifier ^slicing.discriminator.type = #value
* identifier ^slicing.discriminator.path = "system"
* identifier contains phn 1..1 MS
* identifier[phn].system = "https://fhir.apps.health/alberta/NamingSystem/phn"
* identifier[phn].value 1..1 MS
Must Support Documentation¶
Always document what "support" means:
* element MS
* element ^comment = "Systems SHALL capture and expose this element if known. Receiving systems SHALL process and store this element."
Extension Standards¶
When to Create Extensions¶
Create an extension only when: 1. No base FHIR element can represent the concept 2. The concept is clearly defined and scoped 3. Multiple implementations will use the extension 4. The clinical/business need is documented
Extension Structure¶
Extension: ExtRawCode
Id: ext-raw-code
Title: "Raw EMR Code"
Description: "Captures the original EMR code before terminology mapping"
* ^url = "https://fhir.apps.health/StructureDefinition/ext-raw-code"
* ^version = "1.1.0"
* ^status = #draft
* ^context[+].type = #element
* ^context[=].expression = "CodeableConcept"
* value[x] only Coding
* valueCoding 1..1
* valueCoding.system 1..1
* valueCoding.code 1..1
* valueCoding.display MS
Extension Usage in Profiles¶
* code.extension contains
$ext-raw-code named rawCode 0..* MS
* code.extension[rawCode] ^short = "Original EMR code"
* code.extension[rawCode] ^definition = "Preserves the raw code from the source EMR system"
Validation and Testing Standards¶
Profile Validation Requirements¶
- Syntactic Validation
- FSH files must compile without errors
-
Generated StructureDefinitions must be valid
-
Semantic Validation
- Invariants must have valid FHIRPath expressions
- Bindings must reference valid value sets
-
References must target valid profiles
-
Example Validation
- Every profile must have at least one valid example
- Examples must validate against the profile
- Examples must demonstrate all MS elements
Testing Checklist¶
- [ ] FSH compiles successfully with SUSHI
- [ ] IG Publisher builds without errors
- [ ] All invariants tested with valid/invalid instances
- [ ] All MS elements present in examples
- [ ] Terminology bindings validated
- [ ] Cross-profile references validated
- [ ] Generated documentation reviewed
Version Management Standards¶
Version Numbering¶
Follow Semantic Versioning (SemVer): - MAJOR.MINOR.PATCH (e.g., 1.1.0) - MAJOR: Breaking changes - MINOR: New features, backward compatible - PATCH: Bug fixes, clarifications
Version Metadata¶
* ^version = "1.1.0"
* ^date = "2025-01-15"
Change Documentation¶
- Document all changes in CHANGELOG.md
- Include version in file headers
- Tag significant versions in git
- Maintain version compatibility matrix
Common Patterns and Examples¶
Complete Profile Example¶
// PolarisCoreObservation.fsh
Alias: $observation-category = http://terminology.hl7.org/CodeSystem/observation-category
Alias: $loinc = http://loinc.org
Alias: $ucum = http://unitsofmeasure.org
Invariant: observation-has-polaris-id
Description: "Observation must have at least one Polaris identifier"
Severity: #error
Expression: "identifier.exists(system.matches('^https://fhir\\.apps\\.health/.+/NamingSystem/observation-identifier$'))"
Profile: PolarisCoreObservation
Parent: Observation
Id: polaris-core-observation
Title: "Polaris Observation"
Description: "Polaris profile for observations supporting primary care workflows with raw code preservation"
* ^url = "https://fhir.apps.health/StructureDefinition/polaris-core-observation"
* ^status = #draft
* ^version = "1.1.0"
* obeys observation-has-polaris-id
// Identifier
* identifier 1..* MS
* identifier ^short = "Business identifier for observation"
* identifier.system 1..1 MS
* identifier.value 1..1 MS
// Status
* status MS
* status from http://hl7.org/fhir/ValueSet/observation-status (required)
// Category
* category 1..* MS
* category from http://hl7.org/fhir/ValueSet/observation-category (preferred)
// Code with raw preservation
* code MS
* code.coding ^slicing.discriminator.type = #value
* code.coding ^slicing.discriminator.path = "system"
* code.coding contains
loinc 0..1 MS and
local 0..1 MS
* code.coding[loinc].system = $loinc
* code.coding[local] ^short = "Original EMR code"
* code.text MS
// Subject
* subject only Reference(PolarisCorePatient)
* subject 1..1 MS
* subject.identifier 1..1 MS
// Effective time
* effective[x] MS
* effective[x] only dateTime or Period
// Value
* value[x] MS
Slicing Pattern¶
// Slice by pattern (system)
* identifier ^slicing.discriminator.type = #pattern
* identifier ^slicing.discriminator.path = "system"
* identifier ^slicing.rules = #open
* identifier contains
mrn 0..1 MS and
phn 0..1 MS
* identifier[mrn].system = "https://fhir.apps.health/hospital/NamingSystem/mrn"
* identifier[mrn].value 1..1
* identifier[phn].system = "https://fhir.apps.health/alberta/NamingSystem/phn"
* identifier[phn].value 1..1
Complex Constraint Pattern¶
// Multi-field invariant
Invariant: observation-value-or-data-absent
Description: "If no value, must provide data absent reason"
Severity: #error
Expression: "value.exists() or dataAbsentReason.exists()"
// Conditional constraints
* component ^short = "Component observations"
* component obeys component-value-or-reason
* component.code MS
* component.value[x] MS
Appendix: Standard Aliases¶
The following aliases are pre-defined and available for use in all Polaris FSH files:
Terminology Systems¶
Alias: $SCT = http://snomed.info/sct
Alias: $LNC = http://loinc.org
Alias: $ICD10CM = http://hl7.org/fhir/sid/icd-10-cm
Alias: $ICD9CM = http://hl7.org/fhir/sid/icd-9-cm
Alias: $RXN = http://www.nlm.nih.gov/research/umls/rxnorm
Alias: $UCUM = http://unitsofmeasure.org
Alias: $v2-0203 = http://terminology.hl7.org/CodeSystem/v2-0203
Alias: $v3-ActCode = http://terminology.hl7.org/CodeSystem/v3-ActCode
FHIR Value Sets¶
Alias: $observation-category = http://terminology.hl7.org/CodeSystem/observation-category
Alias: $observation-status = http://hl7.org/fhir/observation-status
Alias: $diagnostic-report-status = http://hl7.org/fhir/diagnostic-report-status
Alias: $encounter-status = http://hl7.org/fhir/encounter-status
Alias: $condition-clinical = http://terminology.hl7.org/CodeSystem/condition-clinical
Alias: $allergy-intolerance-clinical = http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical
HL7 Extensions¶
Alias: $data-absent-reason = http://hl7.org/fhir/StructureDefinition/data-absent-reason
Alias: $rendering-style = http://hl7.org/fhir/StructureDefinition/rendering-style
CA-Core References¶
Alias: $ca-core-patient = http://fhir.infoway-inforoute.ca/StructureDefinition/ca-core-patient
Alias: $ca-core-practitioner = http://fhir.infoway-inforoute.ca/StructureDefinition/ca-core-practitioner
Alias: $ca-core-organization = http://fhir.infoway-inforoute.ca/StructureDefinition/ca-core-organization
Compliance Statement¶
All FSH files in the Polaris FHIR Implementation Guide must comply with these standards. Non-compliant files will be rejected during code review. When in doubt, refer to these standards or consult the FHIR architecture team.
Document Version: 1.1.0
Effective Date: 2025-01-15
Review Cycle: Quarterly