Skip to content

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

  1. Core Principles
  2. File Organization Standards
  3. Profile Development Standards
  4. Invariant Standards
  5. Terminology and Binding Standards
  6. Reference and Identifier Standards
  7. Documentation Standards
  8. Must Support Standards
  9. Extension Standards
  10. Validation and Testing Standards
  11. Version Management Standards
  12. 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

  1. Retain Raw Source Codes: Always preserve original EMR codes alongside mapped standard terminologies to prevent semantic loss
  2. Model Data, Not UI: Represent clinical concepts, not form fields or interface elements
  3. Use Extensions Sparingly: Only when no base element exists and the need is clearly documented
  4. First-Class Resources: Treat Device, Practitioner, PractitionerRole, and Organization as distinct entities
  5. 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 .fsh file contains exactly ONE profile, extension, or value set
  • Shared aliases may be defined in a separate aliases.fsh file
  • 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

  1. Prefer CA-Core+ profiles as parent when available
  2. Fall back to base FHIR R4 resources when CA-Core+ doesn't exist
  3. 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]"

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 .fsh files
  • 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

  1. Description: Comprehensive overview including:
  2. Clinical/business purpose
  3. Relationship to other Polaris profiles
  4. Alignment with CA-Core+ or other standards
  5. Key constraints and requirements

  6. Implementation Notes: Document in profile description or page content:

  7. Integration patterns
  8. Common implementation challenges
  9. Example scenarios
  10. Migration considerations

  11. Mapping Documentation: Include in separate markdown files:

  12. Source system field mappings
  13. Terminology mappings
  14. Transformation logic
  15. 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

  1. Syntactic Validation
  2. FSH files must compile without errors
  3. Generated StructureDefinitions must be valid

  4. Semantic Validation

  5. Invariants must have valid FHIRPath expressions
  6. Bindings must reference valid value sets
  7. References must target valid profiles

  8. Example Validation

  9. Every profile must have at least one valid example
  10. Examples must validate against the profile
  11. 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