You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Research and design (no implementation yet) a FHIR Resource Editor prototype for the HFS web UI: a schema-aware editor that lets a user open a FHIR resource, understand its structure, add/remove nodes of information, and edit extensions — with the schema itself driving what is offerable and what is valid.
The deliverable of this issue is a design document + prototype plan, not production code. A throwaway spike is fine (and encouraged) to de-risk the hard parts, but the output we want is a written design we can review before committing engineering time.
Why now
Two pieces have landed (or are landing) that make this feasible for the first time:
FHIR Schema capability — PR feat(validator): FHIR resource validation — schema engine, $validate, write-path enforcement #232 (feat/fhir-validator, still draft). It introduces helios-fhir-validator, a runtime FHIR Schema engine with an in-memory IR (FhirSchema) built from StructureDefinitions and shipped as embedded per-version schema packs (R4/R4B/R5/R6). This issue should target that engine as its schema source — not a hand-rolled metadata layer, and not the typed helios-fhir structs.
crates/ui — the Askama + htmx, server-rendered UI crate mounted at /ui by the hfs binary, with embedded assets and no runtime CDN dependency.
What the FHIR Schema layer already gives us (from PR #232)
helios_fhir_validator::schema::FhirSchema carries essentially the metadata an editor needs to render a form and offer the right "add node" choices:
Field
Editor use
elements (ordered IndexMap)
The set of child nodes that can be added, in spec order
type_, kind, base
Which widget to render; how to resolve nested complex types
min / max, array, required
Cardinality: required markers, "add another" affordance, when to stop offering
choices / choice_of
value[x] — offer a type picker, then bind the concrete element
binding (value_set, strength)
Coded fields: dropdown/autocomplete backed by $expand against HTS
fixed / pattern
Prefill and lock values
constraints (FHIRPath + human)
Inline invariant messages
refers
Reference pickers scoped to allowed target types
slicing / slices (incl. Match)
Profile-driven slices, and the basis for extension slices
extensions
Named extension slices declared by a profile
must_support, modifier, summary
Emphasis / ordering / progressive disclosure in the form
regex (primitives)
Client- and server-side field-level checks
So the research is mostly about how to project this IR into an editable UI, not about acquiring the schema.
Research questions to answer
1. Schema access surface. The validator's IR is internal to a Rust crate. Does the editor consume it in-process (UI crate depends on helios-fhir-validator, renders forms server-side) or over an HTTP surface (a /ui-internal or public endpoint that projects FhirSchema into an editor-friendly JSON)? Consider that PR #232 keeps schemas as compressed packs and resolves cooperatively rather than by snapshot flattening — walking it per-node for a form render needs a look at cost and at the resolver API (SchemaResolver, SchemaRegistry, CompositeResolver).
2. Editing model. Tree editor over raw JSON, or a generated form? Likely both: a structured form view for the common path plus a raw-JSON/source view, kept in sync. Decide what the canonical in-flight representation is (raw serde_json::Value is what the validator walks, which argues for it).
3. Adding nodes. The core requirement. Given a cursor position in the resource, compute the set of addable children from the schema (respecting cardinality already consumed, excluded, choice types, slices), and render an "add element" affordance. Design how this is surfaced (typeahead over element names? a filtered tree of the type?) and how deeply nested complex types are lazily expanded.
4. Extension editing (explicit requirement). Cover both cases:
Known/profiled extensions — declared via the extensions sugar / extension slices on a profile; we know the URL, the value type, and the binding, so we can render them like any other field.
Ad-hoc extensions — the user supplies an extension URL. Design URL resolution: from stored StructureDefinitions in the tenant, from the schema packs, or unresolvable (fall back to a manual value[x] type picker). Also cover nested/complex extensions (extension.extension) and modifierExtension.
5. Validation feedback loop. How and when the editor validates: live per-field (regex, cardinality, required) versus a full pass through $validate (added in PR #232, returns OperationOutcome). Map OperationOutcome.issue.expression / location back onto editor nodes so errors land on the right field. Note that FHIRPath constraints and terminology bindings are deferred (async) in the engine — the sync structural pass is cheap, the effects pass is not; that shapes the interaction design.
6. Terminology integration. For binding fields, wire code pickers to $expand / $validate-code (HTS). Decide behavior when terminology is unavailable or the value set is huge.
7. Profiles. Editing against meta.profile (and tenant/stored profiles) versus base resource type: does the user pick a profile up front, and does the form then narrow (required slices, must-support emphasis, fixed values)?
8. Technology fit. The UI crate today is server-rendered Askama + htmx with embedded assets and no runtime CDN. A resource editor is the most interaction-heavy thing we'd have built. Assess honestly whether htmx-driven fragments carry it, whether it needs a scoped island of client-side JS, and what that costs us against the crate's existing no-CDN / air-gapped stance. Recommend one, with the tradeoff written down.
9. Prior art. Survey what exists — Health Samurai's FHIR Schema-driven form work, Simplifier/Forge, the HAPI resource editor, LHC-Forms/SDC Questionnaire-based rendering, fhir-schema-based editors — and say what we should and shouldn't copy.
Scope for the prototype (what "enough capability" means)
The prototype should be able to demonstrate, end to end, on at least one FHIR version:
Load an existing resource from HFS by type + id (and start a new empty one).
Render a schema-driven editable tree/form of it, ordered and typed by the schema.
Add a new node at any valid point, with the set of offerable nodes derived from FhirSchema (including a value[x] choice-type pick and a repeating-element "add another").
Remove a node.
Add, edit, and remove extensions, including at least one profiled extension and one ad-hoc URL extension.
Save back to HFS (PUT/POST), surfacing an OperationOutcome on rejection.
Explicitly out of scope for the prototype: full profile authoring, Questionnaire/SDC rendering, bulk/multi-resource editing, offline conflict resolution.
Deliverables
A design doc (in docs/, e.g. docs/resource-editor-design.md) answering the research questions above, with a recommended architecture and the rejected alternatives noted.
A component/data-flow sketch: where schema projection happens, what crosses the wire, what the editor's in-flight state is.
A staged implementation plan with sizing, and a call on the technology question (Epic/pysof #8).
Any spike code kept on a branch, clearly labeled as a spike.
Goal
Research and design (no implementation yet) a FHIR Resource Editor prototype for the HFS web UI: a schema-aware editor that lets a user open a FHIR resource, understand its structure, add/remove nodes of information, and edit extensions — with the schema itself driving what is offerable and what is valid.
The deliverable of this issue is a design document + prototype plan, not production code. A throwaway spike is fine (and encouraged) to de-risk the hard parts, but the output we want is a written design we can review before committing engineering time.
Why now
Two pieces have landed (or are landing) that make this feasible for the first time:
feat/fhir-validator, still draft). It introduceshelios-fhir-validator, a runtime FHIR Schema engine with an in-memory IR (FhirSchema) built from StructureDefinitions and shipped as embedded per-version schema packs (R4/R4B/R5/R6). This issue should target that engine as its schema source — not a hand-rolled metadata layer, and not the typedhelios-fhirstructs.crates/ui— the Askama + htmx, server-rendered UI crate mounted at/uiby thehfsbinary, with embedded assets and no runtime CDN dependency.What the FHIR Schema layer already gives us (from PR #232)
helios_fhir_validator::schema::FhirSchemacarries essentially the metadata an editor needs to render a form and offer the right "add node" choices:elements(orderedIndexMap)type_,kind,basemin/max,array,requiredchoices/choice_ofvalue[x]— offer a type picker, then bind the concrete elementbinding(value_set,strength)$expandagainst HTSfixed/patternconstraints(FHIRPath +human)refersslicing/slices(incl.Match)extensionsmust_support,modifier,summaryregex(primitives)So the research is mostly about how to project this IR into an editable UI, not about acquiring the schema.
Research questions to answer
1. Schema access surface. The validator's IR is internal to a Rust crate. Does the editor consume it in-process (UI crate depends on
helios-fhir-validator, renders forms server-side) or over an HTTP surface (a/ui-internal or public endpoint that projectsFhirSchemainto an editor-friendly JSON)? Consider that PR #232 keeps schemas as compressed packs and resolves cooperatively rather than by snapshot flattening — walking it per-node for a form render needs a look at cost and at the resolver API (SchemaResolver,SchemaRegistry,CompositeResolver).2. Editing model. Tree editor over raw JSON, or a generated form? Likely both: a structured form view for the common path plus a raw-JSON/source view, kept in sync. Decide what the canonical in-flight representation is (raw
serde_json::Valueis what the validator walks, which argues for it).3. Adding nodes. The core requirement. Given a cursor position in the resource, compute the set of addable children from the schema (respecting cardinality already consumed,
excluded, choice types, slices), and render an "add element" affordance. Design how this is surfaced (typeahead over element names? a filtered tree of the type?) and how deeply nested complex types are lazily expanded.4. Extension editing (explicit requirement). Cover both cases:
extensionssugar / extension slices on a profile; we know the URL, the value type, and the binding, so we can render them like any other field.StructureDefinitions in the tenant, from the schema packs, or unresolvable (fall back to a manualvalue[x]type picker). Also cover nested/complex extensions (extension.extension) andmodifierExtension.extensionssugar referencing core extension URLs currently reportsunknown-schema. The design should say how the editor behaves in that gap.5. Validation feedback loop. How and when the editor validates: live per-field (regex, cardinality, required) versus a full pass through
$validate(added in PR #232, returnsOperationOutcome). MapOperationOutcome.issue.expression/ location back onto editor nodes so errors land on the right field. Note that FHIRPath constraints and terminology bindings are deferred (async) in the engine — the sync structural pass is cheap, the effects pass is not; that shapes the interaction design.6. Terminology integration. For
bindingfields, wire code pickers to$expand/$validate-code(HTS). Decide behavior when terminology is unavailable or the value set is huge.7. Profiles. Editing against
meta.profile(and tenant/stored profiles) versus base resource type: does the user pick a profile up front, and does the form then narrow (required slices, must-support emphasis, fixed values)?8. Technology fit. The UI crate today is server-rendered Askama + htmx with embedded assets and no runtime CDN. A resource editor is the most interaction-heavy thing we'd have built. Assess honestly whether htmx-driven fragments carry it, whether it needs a scoped island of client-side JS, and what that costs us against the crate's existing no-CDN / air-gapped stance. Recommend one, with the tradeoff written down.
9. Prior art. Survey what exists — Health Samurai's FHIR Schema-driven form work, Simplifier/Forge, the HAPI resource editor, LHC-Forms/SDC Questionnaire-based rendering,
fhir-schema-based editors — and say what we should and shouldn't copy.Scope for the prototype (what "enough capability" means)
The prototype should be able to demonstrate, end to end, on at least one FHIR version:
FhirSchema(including avalue[x]choice-type pick and a repeating-element "add another").$validatepath.PUT/POST), surfacing anOperationOutcomeon rejection.Explicitly out of scope for the prototype: full profile authoring, Questionnaire/SDC rendering, bulk/multi-resource editing, offline conflict resolution.
Deliverables
docs/, e.g.docs/resource-editor-design.md) answering the research questions above, with a recommended architecture and the rejected alternatives noted.Dependencies / coordination
helios-fhir-gen+#[derive(FhirValidate)]codegen path). The editor design should be robust to that decision going either way — it needs a FHIR Schema IR, and should not hard-couple to the runtime-pack specifics if the codegen path wins.Not now
Per the request: record and design only — do not build the production editor yet.