Repository navigation
Conversation
…HIR JSON and XML FHIR views now accept and return FHIR JSON and XML through the shared core/fhir/base.py layer. _format overrides Accept, media aliases and quality values are honoured, and unsupported FHIR versions are refused. XML is converted locally with fhir.resources' R4B models (fhir.resources[xml] 8.3.0, up from 7.1.0), so XML conversion no longer calls the validator service and the FHIR_VALIDATOR_URL application setting is removed. The shared CodeSystem converter (core/code_systems/converter.py) moves to the R4B model and model_dump(). XML follows FHIR element order and preserves the values JSON carries. Unsupported elements and shapes are omitted, a single-valued element keeps its first item, and characters XML cannot represent become replacement characters. Errors from views, routing and middleware return OperationOutcome with terminology issue coding; server errors become 422 responses. FhirErrorMiddleware runs outermost, and core/wsgi.py installs FhirWSGIRequest, so a malformed Content-Type parameter or a non-text charset on a FHIR path is a FHIR JSON 400 rather than an error page; other paths are unchanged. metadata also answers with a trailing slash, and names the request's own FHIR base. Tests cover negotiation, JSON and XML input and output, malformed headers and queries, serializer outcomes and middleware failures. Work package WP1 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…ntries and support FHIR version rules Canonical resolution can select a repository type and require a released default version. The new core/fhir/resolve.py applies the FHIR base's namespace and access rules, preserves the resource type of OCL paths, and uses HEAD only when named. Repositories without a release are absent. Unavailable repositories receive the same not-found answer as missing ones. $resolveReference accepts namespace for expressions that name none when the URL registry is enabled; an expression's own namespace wins. Existing shared-resolver callers keep their default resolution rules. Registry reads no longer save or reindex entries. Repository writes refresh cached links, and ConceptContainerModel.delete in core/common/models.py preserves entries and resolves their links again after deletion. Link updates save only their own fields, preserving concurrent edits. Tests cover both registry settings, resource types, namespaces, named versions and query counts, plus link maintenance, concurrent edits and retries of interrupted repository or version deletes. Work package WP2 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…ses a caller may view CodeSystem, ValueSet and ConceptMap search and read share core/fhir/search.py. Search lists released versions with real totals, paging links and SUBSETTED summaries. Global reads use an opaque id per release; owner reads use the mnemonic and a named version or the newest visible release. meta.versionId distinguishes releases at both bases. Search supports SVCM parameters, token systems, date comparisons, comma alternatives and repeated criteria. String searches ignore case and accents except with :exact; identifiers and canonical URLs match the values resources show. CodeSystem reads include all concepts up to 1,000, then report not-present. A release is visible only with a viewable active HEAD. The global base shows public content; owner bases apply the caller's rights. Source and reference filters can match any owner's source the caller may view. ConceptMap creation by PUT or PATCH checks ownership, and deletion of a missing map returns 404. Search evaluates its criteria once, batches canonical lookups, accepts at most 20 values per parameter and 50 overall, and bounds database work to five seconds. Tests cover search semantics, paging, read content, access, write ownership, query counts and too-costly outcomes. Work package WP3 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…sistent, typed error outcomes Required-input errors in $validate-code and $translate now use the shared FHIR InvalidError. A missing required input is a 400 OperationOutcome naming it, with terminology issue coding. CodeSystem $validate-code for an unknown or unavailable system still answers result=false, with or without a code. core/fhir/tests_operation_bounds.py checks FHIR JSON POSTs and the issue coding, alongside bounded concept and mapping reads and unchanged answers for list-only options. It replaces master's copy of these bounds tests (core/code_systems/tests_operation_bounds.py, which came from this work) with core/fhir/tests_operation_bounds.py. Its $translate cases run by GET here; the POST cases come back with the $translate work later in the series. The operation input checks of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
… the requested version and value set $lookup and CodeSystem and ValueSet $validate-code now use shared operations in core/fhir/ops and an R4 response adapter. GET and POST accept separate inputs or a Coding, with instance routes for lookup and validation. CodeableConcept validation accepts one coding. Operations resolve the newest release the caller may view unless a version is named. Without the URL registry, a canonical at the global base resolves only among repositories the caller is shown, so a private copy never hides a public one; the shared resolver in core/common/models.py gains optional heads and head_shown arguments for this, and other callers keep their defaults. Owner instance routes accept HEAD when explicitly named. Conflicting systems or versions are reported, deleted concepts are absent, and unavailable repositories receive the same answers as missing ones. $lookup returns the resolved version, display, designations and inactive property. Validation returns the code, system, version, display and issues; display checks accept any concept name regardless of case, and retired codes remain valid with a warning. ValueSet membership comes from its default expansion, reporting a visible holding release: the explicit pin, then the evaluated pin, then the newest. Tests cover GET and POST, instance routes, encoded codes, display languages, version conflicts, expansion membership and access with both registry settings. Query checks keep reads focused on the named code as repositories grow. Work package WP4 + WP5 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…d map's live mappings and R4 equivalences $translate now reads the resolved ConceptMap version's own live mappings through core/fhir/ops/translate.py. GET takes code and system, or a system|code coding token; a POSTed Parameters also takes a Coding or a CodeableConcept. url and conceptMapVersion select the map. Without url, a forward translation uses the input system's own map, and a reverse one uses targetsystem's (with no targetsystem there is no map). Map types and stored relationship spellings become R4 equivalences. Reverse translation swaps direction and wider or narrower meaning; code-system versions and targetsystem narrow the matches. The input code must belong to its source scope, or target scope in reverse, with ValueSet paths resolved as value sets. Translation, ConceptMap reads and system searches name mapping sides consistently: a visible source's canonical URL, otherwise the mapping's stored URL. Deleted or retired mappings are omitted, each match names its map, and results list at most 1,000 matches within the search time bound. Tests cover versions, aliases, scopes, reverse equivalences, GET and POST, JSON and XML, access rules and bounded queries. ConceptMap reads group repeated source codes together, and writes store equivalences as the corresponding map types. Work package WP6 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…lue set's stored members ValueSet $expand now serves the resolved version's default stored expansion at type and instance routes. GET and POST only read it; neither computes nor saves an expansion. Missing, unfinished or unresolved expansions return a 422 OperationOutcome. Responses carry the ValueSet, expansion identifier and timestamp, total, offset, echoed inputs and used code systems. Each visible member has its system, code and display, with a holding release when available, inactive status and optional designations. count and offset page up to 1,000 members; activeOnly, word-prefix filter and displayLanguage shape the answer. Members report their release's own canonical URL when present, and ValueSet validation accepts that system too. Filters match decoded codes and names. Inputs requiring a newly computed expansion are refused explicitly, and members whose code systems the caller cannot view contribute neither content nor totals. Tests cover paging, filtering, languages, designations, release selection, access and unsupported inputs with both registry settings. They also check that POST writes nothing, queries stay bounded and timeouts return too- costly outcomes. Work package WP7 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…s and code-system versions each base serves CapabilityStatement is built from the routes and search definitions in core/fhir/capabilities.py. It advertises FHIR R4, the available interactions and operations, SVCM terminology support, and the request's own base URL. metadata and GET $versions work at global, organization and user bases, with either trailing-slash form. TerminologyCapabilities lists the code systems the caller may view and their released versions, each under its canonical URL or its OCL CodeSystem path. The default release is marked, and expansion and translation capabilities follow the routed operations. Business versions are listed as stored and resolve without a second decoding changing their meaning. OCL-to-FHIR path conversion replaces only the repository-type segment, preserving owner and repository names. Tests compare advertised routes, parameters and versions with the implementation, check JSON and XML at every base, and cover registry choices, shared canonicals, access, query counts and timeouts. Work package WP8 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…d candidates and check each release's mappings ConceptMap source-system and target-system searches use core/fhir/mapping_index.py to find candidate repositories and versions. The database checks each candidate through its own live mappings, avoiding a join over every mapping of a heavily mapped source. Index requests are scoped by the versions the database shows the caller, use one bounded request per parameter and require a complete answer. Time or aggregation limits return too-costly; unavailable or partial index responses return a 422 OperationOutcome. Recent releases of repositories found in the index are checked for seven days even if the release is not indexed yet. Matches through a source's canonical URL need the index: repositories with no indexed mappings, and older unindexed releases, are absent until indexed. Matches on the URL a mapping stores, external URLs and OCL paths alike, don't need the mappings to be indexed, but a search that also names a visible source's canonical URL needs a complete answer from the index. Tests cover candidate verification, case-distinct owners, current access rules, recent releases, index lag, incomplete responses, timeouts and fixed database query counts with both registry settings. Work package WP3b of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…ack to the name when no full name is set CodeSystem and ValueSet reads and search entries use the repository name as the title when the full name is null, empty or only whitespace. A nonblank full name remains the title, and title writes still update the full name. Title searches match that same displayed value for prefix, :exact and :contains searches. Tests cover both resource types at global and owner bases, including Unicode whitespace and names that differ from a nonblank full name. Work package WP3c of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…sible repository that holds it When the first repository selected for a canonical URL cannot serve the named release, FHIR resolution can select the lowest-id visible repository with that canonical that holds it. A named unreleased version or HEAD remains limited to the first eligible repository; unavailable holders are not served. This applies where repositories sharing the canonical determine resolution. An explicit registry entry still decides, owner bases stay within their owner, and requests without a version keep their default. TerminologyCapabilities also lists the additional releases served by name under the canonical, preserving the default. Tests cover lookup, validation, expansion, translation, search and capabilities across callers, bases and both registry settings, including retired, deleted and unavailable versions. Query-count tests retain the shared resolver's existing differences and account for the HEAD read used by $resolveReference's view-access check. Work package WP2b of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…ept rows report a holding release $expand and ValueSet $validate-code can report a release for a member stored as its concept's versioned-object row, which only HEAD holds. When no visible live release holds the member's exact row, a release holding another active version of that concept supplies the version. A release holding the exact member takes precedence. Within each choice, the expansion's explicit pin wins, then its evaluated pin, then the newest release. Validation keeps the stored member's own display, so the coding returned by expansion validates with that display. Tests cover root and version rows, pins, named system versions, deleted concept versions, unavailable releases and competing members with the same code. They check expansion and validation together and preserve the query count. Work package WP10 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…h competing values and explain ConceptMap URI searches A POSTed Parameters entry with more than one value[x], resource or part is now a 400 OperationOutcome naming the parameter, including nested parts. A primitive's _value[x] counts as its value[x], so its own extensions remain valid while another value choice is refused. CapabilityStatement documents that ConceptMap source-uri and target-uri match the groups' systems, since ConceptMaps store no source or target value set. Tests cover value order, nested and extension-only values, and the search documentation at every base. Work package WP11 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…t visible release that holds the concept $expand and ValueSet $validate-code now report a versioned-object member in the newest visible live release holding an active version of its concept, regardless of expansion pins. Such a row carries the concept's newest content. Members whose exact rows belong to releases still follow the explicit pin, then the evaluated pin, then the newest. Expansion reads the links of the relevant repositories' newest releases together and looks up older releases only for unresolved members. The page and used-codesystem use the same rules for selecting releases. used- codesystem reads every visible member's id and release (count=0 included); full concepts and names are read only for the page. Tests cover pins, several repositories, unavailable or deleted versions, older holding releases and members with no holding release. They verify expansion and validation agree, query counts do not grow with member count, and members held in the newest releases need no individual fallback. Work package WP12 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…e for both the total and the page $expand with a filter reads matching member ids once in id order. Their number supplies total and a slice supplies the requested page, so selecting the page no longer repeats the name filter. Unfiltered expansions keep their existing queries. Tests check a page larger than the matches, paging with an offset, count=0, an offset beyond the matches and no matches. Each filtered request matches names once, and an empty page reads no page concepts or names. Work package WP13 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…eased versions; capped reads say they're partial At an owner base, the instance-level operations (CodeSystem $lookup and $validate-code, ValueSet $validate-code and $expand) resolve a named version the read doesn't find as their type-level operations do, with the same visibility rule: a named, public, unreleased version is served, and one the caller may not see answers exactly as a missing one. Released versions the read finds keep their path and statement count, and reads still return released versions only. A version the resolver returns carries its repository's canonical URL, from the HEAD it already reads. A resolved version accepts that URL as a system or url even when its own canonical URL differs; answers name the version's own canonical URL when it has one, else its repository's, so a version named by an OCL path, or served unreleased at an owner base, no longer answers with the path. A ValueSet read builds compose from at most 1,000 concept references in id order, and a ConceptMap read builds group from at most 1,000 live mappings; each reads one more to know when it was cut and then tags meta SUBSETTED, keeping the tags meta already has. The FHIR answer to disabled anonymous access carries only its detail text. Unused parameter serializers, FhirParameters.names() and MultipleMatchesError are removed. Work package WP14 of OpenConceptLab/ocl_online#451. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
…paths
A path is a FHIR path under /fhir/, or under an owner base (/orgs/{org}/,
/users/{user}/) when it names a FHIR resource type, metadata or $versions.
Other paths whose third segment is a resource type, such as a current user's
source named CodeSystem (/user/sources/CodeSystem/), keep their own error
bodies and statuses, and the API host serves them when FHIR has its own host.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8
Member
Author
Review loop (Codex pass 1, simplification, Codex check)
The full findings are on the tracking ticket. |
Member
Author
|
Follow-up stacked on this branch: #957 gives the FHIR host its own Swagger page, listing only the operations this PR serves. It goes to |
…page of the terminology operations (#957) * OpenConceptLab/ocl_online#451 | The FHIR host serves its own Swagger page of the terminology operations On the FHIR host, /swagger/ (and swagger.json, swagger.yaml) describes the FHIR terminology service alone: search and read of CodeSystem, ValueSet and ConceptMap, $lookup, $validate-code, $expand, $translate, metadata and $versions, at /fhir and the owner bases. Each operation is listed once, tagged by resource type, with its query parameters, a Parameters body for POST, and OperationOutcome errors. Writes and the slash and no-slash duplicates are left out, and Try it out calls the FHIR host itself. When FHIR has its own host, the API's Swagger leaves the FHIR paths out (they answer 404 there) and links to the FHIR page. When FHIR shares the host, the API's Swagger lists the same curated operations instead of the generated ones. The other API operations are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8 * OpenConceptLab/ocl_online#451 | FHIR Swagger: say which inputs a coding replaces When a coding or codeableConcept is given, the operations don't read the separate inputs it stands for: code and system for $lookup (version still selects the code system version), code and display for CodeSystem $validate-code (url and version still name the code system), code, system, systemVersion and display for ValueSet $validate-code, and code, system and version for $translate. Each operation's coding parameter now names them, and each of those inputs says it isn't read alongside a coding. A GET coding token carries no version or display; a POSTed valueCoding does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8 * OpenConceptLab/ocl_online#451 | FHIR Swagger: $lookup's system still names an instance alongside a coding At the type level, $lookup takes the code system from a coding, so a separate system has no effect; at an instance, a separate system must still name that code system, as without a coding. Its description now says so instead of saying it isn't read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
snyaggarwal
reviewed
Oct 23, 2026
Contributor
There was a problem hiding this comment.
Review focused on: non-FHIR behaviour changes, missing tests, module-function vs OOP design, duplication, complexity and feature envy. Line numbers are from the PR head.
1. Non-FHIR behaviour changes
- ConceptMap import map types (
core/concept_maps/serializers.py:46, also used bycore/importers/importer.py): R4 equivalences now become OCL map types on import (wider→NARROWER-THAN,narrower→BROADER-THAN). This is the reverse mapping OpenConceptLab/ocl_issues#2924 asks for, so it's intended. Please link that ticket in the description so it closes on merge. The PR also mapsunmatched/disjoint→NOT-SAME-AS, which goes beyond the ticket but looks reasonable. - Synchronous registry relink on every repo/version save.
Source.save/Collection.savenow calllink_url_registry_entries()whenevercanonical_urlis dirty, which includes every new version row: an extraURLRegistryquery pluslookup_entry()per create, inside the request or import, next to the existing asyncresolve_url_registry_entriestask. Two mechanisms now maintain the same link (one sync, one async). The block is also duplicated betweencore/sources/models.py:702andcore/collections/models.py:170; it could live once onConceptContainerModel. - Delete relinks entries in every namespace.
relink_url_registry_entries(core/common/models.py:976) re-resolves every active entry with the deleted canonical URL, whatever its namespace, so a widely registered URL means N lookups inside the delete. URLRegistry._set_repo(core/url_registry/models.py:140) now clears the link when nothing resolves, and reads no longer write. Intended and tested, but URL-registry API responses change for entries whose URL no longer resolves; worth calling out in the description.$resolveReferencegains?namespace=(toggle-gated, tested), andresolve_expression_to_versionnow applies it to bare-string expressions too.- Looks fine: middleware reorder,
FhirWSGIRequest(FHIR paths only), theBundleMetaSerializer.lastUpdateddefault fix (datetime.now()→datetime.now, a real bug fix), and theconvert_ocl_uri_to_fhir_urlsegment-only rename.
2. Missing tests
FhirErrorMiddleware(core/middlewares/middlewares.py:278): no test that an exception on a non-FHIR path is still re-raised (test_answers_left_alonecovers responses only).FhirWSGIRequest: no test that a malformed Content-Type on a non-FHIR path behaves as before; every wsgi test uses a FHIR path.- Optional: an export → import round-trip test for map types, the round trip OpenConceptLab/ocl_issues#2924 describes.
test_group_equivalence_is_the_map_type_relationshipcovers the mapping at the serializer level. - No query-count test for creating a source/version with a canonical URL, now that save does a synchronous registry lookup.
get_latest_released_version(exclude_head=True)is only tested indirectly.convert_ocl_uri_to_fhir_urltests live incore/fhir/tests_capabilities.py:302rather than withIdentifierSerializerTestincore/common/tests.py.
3. Module-level functions vs OOP
core/fhir/resolve.pyis ~25 free functions threading(namespace, user)/(kwargs, user)through every call (is_shown,is_visible,has_release,may_view_private,owner_access,shown_q,viewable_rows,visible_versions,held_version, ...). That data clump wants to be one per-request access/resolver object.- Parameter parsing is scattered free functions taking
parameters:text,require,coding_of(ops/concepts.py),required_text,boolean,coding_of(ops/translate.py:185,196),whole_number,flag(ops/expand.py:106,118). They belong as typed accessors on the existingFhirParameters(core/fhir/base.py:473). - Import-time module state:
capabilities.STARTED = timezone.now()(capabilities.py:38) and the mutableLOGGED_DROPPED_ELEMENTS = set()(base.py:73). REGISTRY_TOGGLE/ServedHeadare declared mid-module (resolve.py:388).base.py(601 lines) mixes content negotiation, XML conversion, parameter parsing and view base classes; worth splitting.
4. Duplication
- Same parsers, different behaviour:
coding_ofsplits withrpartition('|')inops/concepts.py:40butpartition('|')inops/translate.py:196, so the samesystem|codetoken can parse differently in$lookupand$translate.- CodeableConcept:
$translatesilently takes the first coding; lookup/validate reject anything but exactly one. flagstrips whitespace andbooleandoesn't; error messages differ.
- Three too-costly factories:
too_costly()inexpand.py:101andtranslate.py:152,search_too_costly()insearch.py:597. One factory taking a message would do. - Access rules re-implemented:
owner_access(resolve.py:320) andmay_view_private(resolve.py:283) each re-deriveConceptContainerModel.has_parent_edit_access, differently within the same module;is_public(resolve.py:262) duplicatespublic_can_view. That's a second permission model that can drift from the main one. - A 1000 limit is defined five times (
CONCEPT_LIMIT,MATCH_LIMIT,MAPPING_LIMIT,REFERENCE_LIMIT,expand.MAX_COUNT), whilesearch.MAX_COUNTreuses the same name for 100. Suggest settings with distinct names. - Several OCL path ↔ FHIR URL converters:
IdentifierSerializer.convert_*,resolve.to_ocl_path,resolve.ocl_path,translate.OCL_PATH+repository_paths. CapabilityStatementView/VersionsViewroutes copy-pasted acrossorgs/urls.py,users/urls.pyandfhir/urls.py.
5. Complex logic
resolve_reference_expression/resolve_repo(core/common/models.py:1542,1624) gain four FHIR-only parameters (repo_type,allow_head,heads,head_shown) withtoo-many-arguments,too-many-localssuppressed, andfind_repo_by_canonical_url(repo_type=...)switches to different semantics under the flag. A resolution-policy object, or a FHIR subclass of the resolver, would keep the shared$resolveReferencepath free of FHIR rules.shared_resolution'shead_shownclosure appends to an outerheadslist to pass the picked HEAD back out (resolve.py:122).resolve()(resolve.py:83) layers a pipe/path version conflict, a newest-public-release fallback, a holder's pick / held version, and cached rights copied between instances. Hard to follow.with_side/shown_asintranslate.pybuild**{f'{side}_…'}dynamic Q and annotate expressions that are hard to review.
6. Feature envy
repository_access,is_visible,has_release,may_view_private,latest_public_releasereach into and write to model instances, stamping ad-hoc attributes (repository_public_access,repository_canonical_url,fhir_may_view_private,is_fqdn,resolution_url; plusfhir_concepts,concepts_over_limitinsearch.py, andcore/common/models.py:1637). That logic belongs onConceptContainerModelor a small wrapper class, not monkey-patched attributes.ConceptMapGroupField.to_representationpullsrequestandview.kwargsfrom the serializer context and callswith_side,side_system,relationshipandnamespace_offrom the ops/resolve modules.- Inverted layering:
core/common/swagger.py,core/middlewaresand the domain serializers now import fromcore.fhir, which imports them back.cyclic-importis disabled in.pylintrc, so pylint won't flag it.
Other
FhirOperationView.get_throttles(core/fhir/base.py:593) andCapabilityStatementView.get_throttles(core/fhir/views.py:19) copy a throttling pattern tracked as OpenConceptLab/ocl_online#532 debt. Please use a throttle that's the same for everyone (server protection) or wait for the #532 checkpoint.- Turning every 5xx on a FHIR path into a 422 hides real server errors from anything that counts 5xx; monitoring/alerting may need adjusting.
This branch has not been deployed
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.
FHIR R4 terminology service (SVCM transactions)
This series makes oclapi2's FHIR endpoints a FHIR R4 terminology service for the IHE SVCM transactions: CodeSystem, ValueSet and ConceptMap search and read,
$lookup,$validate-code,$expand,$translate, and the CapabilityStatement and TerminologyCapabilities. It serves them at the global base (/fhir/) and at owner bases (/orgs/{org}/,/users/{user}/), in JSON and XML. Tracking: OpenConceptLab/ocl_online#451.How to review it: 17 commits on master
addb3d5e: one per work package, each with a message describing its behaviour, then a fix from this PR's review. Only the final tree has been gated (the full test suite, pylint and coverage). Every intermediate tree compiles but hasn't been run on its own.Commits
Outside
core/fhir/These are worth a closer look, because they change code that non-FHIR paths share:
ConceptContainerModel.resolve_reference_expression/resolve_repoincore/common/models.py,core/repos/models.py,core/url_registry/models.py,core/common/mixins.py). FHIR resolves through the same resolver as$resolveReference, with flags that only FHIR passes: no HEAD by default, the HEADs a base shows, and a visibility check before any version is read. Registry reads no longer save or reindex entries. With the URL registry on,$resolveReferenceacceptsnamespacefor expressions that name none; an expression's own namespace wins./fhir/or under an owner base's FHIR routes; other routes keep their own errors. The FHIR validator setting is gone, because XML is converted locally.fhir.resources[xml]goes from 7.1.0 to 8.3.0, and the CodeSystem converter used by imports moves to the R4B models.There are no migrations. The URL registry toggle stays as it is: FHIR works with it on or off.
Testing
core/fhir).Known limits and follow-ups
referencesearches: OpenConceptLab/ocl_online#547.$expandwithfilteron the largest stored expansions (about 38,000 members) can exceed the database time limit and answer 422: OpenConceptLab/ocl_online#564.🤖 Generated with Claude Code
https://claude.ai/code/session_01R8hw7w8753DDSCezrmrDA8