Move the metadata that must not be changed into the base content package - #13
Open
dkayiwa wants to merge 4 commits into
Open
Move the metadata that must not be changed into the base content package#13dkayiwa wants to merge 4 commits into
dkayiwa wants to merge 4 commits into
Conversation
The two content packages were split by name rather than by role. `referenceapplication` was a 10-file overlay - concept classes and sources, the location tags, privileges, four global properties, two OCL packages - while `referenceapplication-demo` carried everything needed to actually run O3: the `OpenMRS ID` identifier type and its idgen source, encounter and visit types, the `Privilege Level` and `Application: ...` roles, the emrapi term mappings, ADT dispositions, order frequencies, dosing units, and the vital sign concepts with their reference ranges. So a distribution could not drop the demo package - the point of the `no-demo` profile in openmrs-distro-referenceapplication@b60dce9 - without losing the ability to log in, register a patient or record an obs. Filenames are unchanged, so the config is identical file for file: every moved file is byte-identical and no name collides. Three files held both kinds of content and were split: `OpenMRS ID` out of the identifier types, `Vital signs` out of the convsets (`Tests Orderability` stays with the lab catalog it names), and queue.sortWeightGenerator / concept.causeOfDeath / attachments.allowedFileExtensions out of the demo global properties. Existing installations do re-import the moved files once. build-distro lays config out as openmrs_config/<domain>/<package>/<file> and names checksums <domain>/<package>_<file>.checksum, so changing which package owns a file changes both its path and its checksum name. Re-import is idempotent - these are declarative CSV and XML keyed by uuid - but it also shifts their order within a domain, since `referenceapplication` sorts ahead of `referenceapplication-demo`. The boundary the README already describes decided each case: what an O3 feature resolves by uuid, code or name belongs here; what a site supplies or replaces stays in the demo package. Locations stay there, so this package defines no facility of its own. Catalogs stay too, which is why alpreferenceranges.csv and hbreferenceranges.csv did not come along: their Hb and ALP concepts live in `BasicLabTests`. dispositionConfig.json did come, and brought the misleadingly named `IPD-DEMO` OCL package with it, since that is where its admit concept is. The service queues frontend config goes the other way, to the demo package: its priority and status uuids are `DemoQueueConcepts`, and it was this package's last dependency on the demo package. There are now none. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Rb27z8QxDsmWEkt7Cs3s7
…and used O3's login page only offers locations tagged `Login Location`, and this package defines no locations - deliberately, since locations vary by site. That left a distribution built without the demo package unable to finish logging in. openmrs-core already creates `Unknown Location` in every database, and the demo package carried a row for it that restated core's own name and description and tagged nothing - a no-op. Move that row here and tag it `Login Location`, `Visit Location` and `Queue Location`. Nothing is invented: no placeholder facility name, no new uuid, and the set of locations across the two packages is unchanged. `Queue Location` is there because `/home` resolves to the Service Queues dashboard: with no location carrying that tag, `@openmrs/esm-service-queues-app` 11.1.0 throws `Cannot read properties of undefined (reading 'id')` and the first screen after login is an error page. Verified by driving the login of a packaged standalone built from this package alone - the dashboard renders its stat tiles and empty queue table once the tag is present. `Admission Location` and `Transfer Location` are deliberately left off: admitting a patient to "Unknown Location" is meaningless, so a site tags its own wards. It is a placeholder, not a facility, and the README says so: sites add their own locations, tag those, and retire this one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Rb27z8QxDsmWEkt7Cs3s7
Review feedback (#13): the division between the two packages is not "needed to run O3" - most of the demo package's metadata is strictly necessary too - but "what an implementation may want its own version of" versus "what must be set this way". The previous commits used the wrong test, which is doubly awkward because the README sentence they quote states the right one. Applying the right test, these go back to the demo package. Each is something a site legitimately defines for itself, even though O3 needs *something* there: identifier types + the idgen source and autogeneration option (sites use their own identifier schemes), visit types (local practice), order frequencies (local prescribing), relationship types, person attribute types, visit attribute types, procedure types, the vitals/BMI reference ranges (clinical policy), the encounter-print and ID-sticker defaults, misc concepts, metadata sets, and attachments.allowedFileExtensions. `metadatatermmappings` is split rather than moved: the mappings whose targets are fixed (`emr.admissionEncounterType`, `emr.visitNoteEncounterType`, `emr.clinicianEncounterRole`, ...) stay here, while `emr.primaryIdentifierType` and `emr.extraPatientIdentifierTypes` follow the identifier types they point at - the mapping must exist, but its value is the implementation's choice. That also preserves the invariant that this package references nothing defined only in the demo package; re-verified by sweeping every uuid and CIEL code. Renamed the remaining file to metadatatermmappings-core.csv so the two packages do not both ship a file called metadatatermmappings-core_demo.csv. What stays: encounter types and roles, the roles/privileges O3 checks by name, the emrapi metadata source and its fixed mappings, dispositions and the ADT concepts, the vital sign concepts and the `Vital signs` set, and the OCL packages those resolve against. The `Unknown Location` tagging stays too, flagged in the README as a bootstrap exception rather than content - without it a distro built without the demo package has nothing to log in to. It arguably belongs in a separate minimal package with an identifier source and a visit type; that is a design question for the split, not something to settle by quietly parking modifiable content here. Nothing is lost across the two packages: 100 config files before, 103 after, the three extra being the intentional splits (Vital signs, the two core global properties, the tagged Unknown Location). Both packages build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Rb27z8QxDsmWEkt7Cs3s7
dkayiwa
added a commit
to openmrs/openmrs-content-referenceapplication-demo
that referenced
this pull request
Aug 12, 2026
Follow-up to review feedback on openmrs/openmrs-content-referenceapplication#13: the division between the two packages is "what an implementation may want its own version of" versus "what must be set this way", not "needed to run O3". The first commit used the wrong test and moved out several things a site legitimately owns. These stay here after all: the identifier types with their idgen source and autogeneration option, visit types, order frequencies, relationship types, person attribute types, visit attribute types, procedure types, the vitals/BMI reference ranges, the encounter-print and ID-sticker defaults, the misc concepts, the metadata sets, and attachments.allowedFileExtensions. `metadatatermmappings` keeps `emr.primaryIdentifierType` and `emr.extraPatientIdentifierTypes`, which follow the identifier types they point at: the mappings must exist, but their values are the implementation's choice. The fixed encounter and role mappings stay in the base package. Still moved out, because an implementation changing them breaks the feature rather than customising it: encounter types and roles, the roles and privileges O3 checks by name, the emrapi metadata source, dispositions and their ADT concepts, the vital sign concepts and the `Vital signs` set, and the OCL packages those resolve against. Nothing is lost across the two packages - 100 config files before, 103 after, the extra three being intentional splits. Regenerating a demo database from this pair still yields 50 patients, all with encounters, 5821 obs, 278 visits, 11 locations, 7 forms, 4 programs and no `Site N`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Rb27z8QxDsmWEkt7Cs3s7
Two corrections to the README, both found by booting a distribution built from
this package alone and measuring rather than reasoning:
- It now says outright that logging in is as far as this package gets you.
Login completes and every O3 route renders, but `visittype` and
`idgen/identifiersource` are both empty, so no visit can be started and O3's
registration has nothing to generate a primary identifier from. Both are
site-defined, so they belong in the demo package - but a reader should not
have to discover that by booting it.
- Removed a paragraph left duplicated by the previous edit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Rb27z8QxDsmWEkt7Cs3s7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The test used
Does an O3 app or module resolve this by uuid, code or name, such that an implementation changing it breaks the feature rather than customising it?
Not "is it needed to run O3" — as @ibacher points out, most of the demo package is strictly necessary too, so that question discriminates nothing. Awkwardly, the README sentence my first pass quoted states the right test; I quoted it and then applied a different one.
What moves here
Privilege Level: Full/High, theApplication: …roles, module privilegesemr.admissionEncounterType,emr.visitNoteEncounterType,emr.clinicianEncounterRole, …CIEL:168619lives only inIPD-DEMO, which comes along)Vital signssetesm-patient-vitals-appresolves them by uuidWhat stays in the demo package after the rework
Everything an implementation may reasonably want its own version of, even where O3 needs something there: the identifier types with their idgen source and autogeneration option (sites use their own schemes), visit types, order frequencies, relationship and person attribute types, visit attribute types, procedure types, the vitals/BMI reference ranges (clinical policy), print and ID-sticker defaults, misc concepts, metadata sets,
attachments.allowedFileExtensions— plus locations, programs, forms, queues, appointment services and all the catalogs, as before.metadatatermmappingsis split, not moved:emr.primaryIdentifierTypeandemr.extraPatientIdentifierTypesfollow the identifier types they point at, because the mapping must exist but its value is the implementation's choice. That also keeps the invariant that this package references nothing defined only in the demo package — re-verified by sweeping every uuid and CIEL code after the rework.The one thing I'm knowingly stretching
The
Unknown Locationtagging. Locations are the canonical implementation-owned thing, so strictly it doesn't belong here. But O3's login page only offers locations taggedLogin Location, and with the demo package left out there is nothing to log in to — so this tags the one location that isn't a site's choice, theUnknown Locationopenmrs-core creates in every database. No facility invented, no uuid created.Reject this bit if you'd rather. I think it points at a real gap: a bootstrap package (one placeholder location, one identifier source, one visit type) would be the honest home for it, and would let
no-demoboot without parking modifiable content here. Evidence it's a real gap and not hypothetical: openmrs/openmrs-distro-referenceapplication@b60dce9 added ano-demoprofile last December, and I built and booted it — base 1.4.0 has no location taggedLogin Location, so that image cannot complete login and nobody had noticed.Separately and regardless of how this lands: with no location tagged
Queue Location,/homeresolves to the Service Queues dashboard and@openmrs/esm-service-queues-app11.1.0 throwsCannot read properties of undefined (reading 'id')— the first screen after login is an error page. Reproduced, and fixed by the tag.Verification
Nothing lost: 100 config files across the two packages before, 103 after, the three extra being the intentional splits (
Vital signs, the two core global properties, the taggedUnknown Location). Row/property unions checked file by file.Both packages build and pass
validate-content-package.Booted this package on its own (no demo package, no
referencedemodata) and drove the O3 login in a browser. Login completes onUnknown Location, and all eight routes render without errors —/home, appointments, wards, patient lists, laboratory, registration, patient search, system administration.But base-alone is not a usable EMR, and this PR does not claim otherwise. Measured on that same instance:
visittypeis empty,idgen/identifiersourceis empty, and the only identifier types are core's own two. So you cannot start a visit, and O3's registration has no source to generate a primary identifier from — a patient can only be created by supplying an identifier by hand through the API. Concepts total 378.That is the correct outcome of the boundary, not a regression: visit types and identifier schemes are things a site defines. It is also precisely the argument for the bootstrap package below — an earlier revision of this PR made base-alone fully usable, but only by parking implementation-modifiable metadata here, which is the mistake @ibacher caught.
Regenerating a demo database from the pair still gives 50 patients, all with encounters, 5821 obs, 278 visits, 11 locations, 7 forms, 4 programs, 0
Site N, andPrivilege Level: Fullgrants identical to the demo-free database (308 = 308).Notes for reviewers
Filenames are otherwise unchanged on purpose, so several files here are still named
*-core_demo.csv. @ibacher suggests fixing the naming rather than the placement — I agree the naming misled me, and I'd happily do a rename pass, but as a separate PR so a 28-file move isn't buried in it.Existing installs re-import the moved files once:
build-distrolays config out asopenmrs_config/<domain>/<package>/<file>and names checksums<domain>/<package>_<file>.checksum, so changing the owning package changes both. Idempotent — declarative CSV/XML keyed by uuid.Merge before openmrs-content-referenceapplication-demo#81.
No
O3-ticket yet — happy to retitle.🤖 Generated with Claude Code
https://claude.ai/code/session_015Rb27z8QxDsmWEkt7Cs3s7