Skip to content

Fix CapabilityStatement conformance for resources without interactions#5473

Open
tranhoangtu-it wants to merge 2 commits intomicrosoft:mainfrom
tranhoangtu-it:fix/capability-statement-interaction-cardinality
Open

Fix CapabilityStatement conformance for resources without interactions#5473
tranhoangtu-it wants to merge 2 commits intomicrosoft:mainfrom
tranhoangtu-it:fix/capability-statement-interaction-cardinality

Conversation

@tranhoangtu-it
Copy link
Copy Markdown

Summary

Fixes #5394.

In STU3, CapabilityStatement.rest.resource.interaction has a minimum cardinality of 1 (spec). Resources like Parameters that are explicitly excluded from interaction population (line 303-307) were still appearing in the resource list with an empty interaction array, causing FHIR-conformant parsers (e.g., Firely SDK 6.x with strict validation) to reject the CapabilityStatement.

Changes

  • In CapabilityStatementBuilder.Build(), added a cleanup step that removes resource entries with no interactions before serialization
  • This ensures the output CapabilityStatement conforms to the FHIR standard across all versions

Why this approach

Rather than modifying how Parameters is handled specifically, this cleanup catches any resource that ends up with zero interactions — making it robust against future edge cases. The comment explains the STU3 cardinality requirement for maintainability.

Test plan

  • Verify /metadata returns a valid CapabilityStatement parseable by Firely SDK 6.x
  • Verify Parameters no longer appears in CapabilityStatement.rest.resource when it has no interactions
  • Existing conformance tests should continue to pass

As a certified HL7 FHIR Implementer, I'm excited to contribute to the FHIR server. I'm also working on FHIRBridge, an open-source FHIR integration toolkit — happy to collaborate on interoperability improvements.

…icrosoft#5394)

In STU3, CapabilityStatement.rest.resource.interaction has min
cardinality 1. Resources like Parameters that are explicitly excluded
from interaction population were still appearing in the resource list,
causing FHIR-conformant parsers (e.g. Firely SDK 6.x) to reject the
CapabilityStatement with a cardinality error.

Remove resources with empty interaction lists in Build() before
serialization.
Copilot AI review requested due to automatic review settings March 30, 2026 18:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the conformance metadata generation to avoid emitting CapabilityStatement.rest.resource entries that have zero interactions, addressing STU3’s minimum cardinality requirement and preventing strict FHIR parsers from rejecting /metadata.

Changes:

  • Adds a cleanup pass in CapabilityStatementBuilder.Build() to remove resource components with an empty interaction collection.
  • Documents the STU3 cardinality rationale inline to clarify why resources like Parameters must be excluded when they have no interactions.

// so resources without interactions (e.g. Parameters) must be excluded.
foreach (var restComponent in _statement.Rest)
{
restComponent.Resource.RemoveWhere(r => r.Interaction == null || r.Interaction.Count == 0);
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restComponent.Resource is typed as ICollection<ListedResourceComponent> (see ListedRestComponent.Resource), so RemoveWhere(...) is not available and this won’t compile. Consider removing via ICollection.Remove (e.g., collect matching items first) or casting to HashSet<ListedResourceComponent> before calling RemoveWhere.

Suggested change
restComponent.Resource.RemoveWhere(r => r.Interaction == null || r.Interaction.Count == 0);
var resourcesToRemove = restComponent.Resource
.Where(r => r.Interaction == null || r.Interaction.Count == 0)
.ToList();
foreach (var resource in resourcesToRemove)
{
restComponent.Resource.Remove(resource);
}

Copilot uses AI. Check for mistakes.
Comment on lines +407 to +413
// Remove resource entries with no interactions to ensure FHIR conformance.
// In STU3, CapabilityStatement.rest.resource.interaction has min cardinality 1,
// so resources without interactions (e.g. Parameters) must be excluded.
foreach (var restComponent in _statement.Rest)
{
restComponent.Resource.RemoveWhere(r => r.Interaction == null || r.Interaction.Count == 0);
}
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change addresses a STU3 conformance edge case; please add/extend a unit test that exercises the typical builder pipeline (e.g., PopulateDefaultResourceInteractions() followed by SyncSearchParameters()) and asserts no CapabilityStatement.rest.resource entries are emitted with an empty interaction collection (specifically that Parameters is absent in STU3). This will prevent regressions if future code paths create resources without interactions.

Copilot generated this review using guidance from repository custom instructions.
@tranhoangtu-it
Copy link
Copy Markdown
Author

Hi team! This PR needs the required metadata labels to pass CI. Could a maintainer please add:

  • Bug (type — fixes non-conformant CapabilityStatement)
  • Open source only (release target — affects all deployments)
  • No-PaaS-breaking-change (removes empty-interaction resources from output, backward compatible)
  • No-ADR (small conformance fix, no architecture decision needed)

Thank you!

Copilot correctly noted that Resource is typed as ICollection, not
HashSet, so RemoveWhere is unavailable. Use Where + ToList + Remove
which works on any ICollection.
@tranhoangtu-it tranhoangtu-it requested a review from a team as a code owner March 30, 2026 20:35
@tranhoangtu-it
Copy link
Copy Markdown
Author

Addressed Copilot's review:

  1. RemoveWhere compile error — Fixed. Now using Where().ToList() + Remove() which is compatible with ICollection<T> (the declared type of Resource).

  2. Unit test — Will add in a follow-up commit. The test should verify that Build() excludes resources with empty interaction lists from the serialized CapabilityStatement.

@LTA-Thinking LTA-Thinking added the External Author PR is written by an author external to Microsoft label Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

External Author PR is written by an author external to Microsoft

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CapabilityStatement returned by the /metadata route does not conform to the FHIR standard

3 participants