Health domain (0x09XX): codebook, HealthcarePort, Active-Record + ClassView, concepts_in_domain#91
Conversation
Promote the medcare-rs Healthcare namespace into the canonical OGAR codebook (Northstar T9) so `MedcareBridge` can collapse to `UnifiedBridge<HealthcarePort>` the same way OpenProject/Redmine collapsed in lance-graph#570. - class_ids / CODEBOOK / ALL: 7 Health concepts (0x0901..0x0907) — patient, diagnosis, lab_value, medication, treatment, visit, vital_sign — one per OGIT NTO/Healthcare entity. The 0x09XX domain block + ConceptDomain::Health were already reserved; this lands the concepts. Single-tenant today; a future FMA/SNOMED curator converges on these ids rather than re-minting. - ports::HealthcarePort: PortSpec impl (NAMESPACE="Healthcare", BRIDGE_ID="medcare") + HEALTHCARE_ALIASES mapping the 7 OGIT entity names (Patient, Diagnosis, LabValue, Medication, Treatment, Visit, VitalSign) onto the new class_ids. - tests: namespace/bridge_id, Health-domain membership, alias count (7), unknown->None, and extend each_alias_class_id_is_in_the_codebook to cover HealthcarePort. Existing CODEBOOK/ALL drift guards cover the new entries automatically. 64 unit + 1 doctest green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
…hook Add `concepts_in_domain(ConceptDomain) -> impl Iterator<(name, id)>`: the reusable enumeration primitive a domain-scoped consumer uses to inherit its full concept set from the canonical codebook instead of hand-maintaining a parallel list. This is the fail-closed foundation for RBAC marking-inheritance: a consumer that must access-control every concept in a sensitive domain (medcare-rs over ConceptDomain::Health) derives its required-coverage set from OGAR, so a concept newly promoted upstream surfaces as missing-coverage at the consumer's boot gate — never a silently fail-open row (the Treatment/Visit/VitalSign gap medcare-bridge flagged). Tests: concepts_in_domain(Health) yields exactly the 7 OGIT entities in codebook order; per-domain counts (Health=7, Commerce=6, ProjectMgmt=26, Osint=0); domain-membership invariant; doctest. Health concepts added to codebook_ids_are_domain_prefixed_and_consistent. 65 unit + 2 doctest green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
…0x09XX Enrich the Health domain into the full reusable OGAR stack, with diagnosis (0x0902) as the worked example. ogar-vocab — 7 Active-Record `Class` builders (patient, diagnosis, lab_value, medication, treatment, visit, vital_sign), same idiom as the project/commerce concepts: typed attributes + `family_edge`/ `family_has_many` associations + canonical_concept identity. diagnosis carries the fullest schema (ICD coding, FHIR-shaped clinical/ verification status, onset/resolution dates, primary flag, 2 edges); the six siblings are competent schemas. Field names are English schema labels — never German PII labels, never PHI values. ogar-class-view — wire all 7 into `all_canonical_classes()` so the ClassView registry covers the 0x09XX block. This FIXES a regression the earlier HealthcarePort commit introduced: Health ids were added to `class_ids::ALL` but had no Class body, so the registry's reverse-gate tests (every_codebook_id_appears_in_class_ids_all + stable-order) were failing (latent — ogar-class-view wasn't re-run that commit). ogar-class-view — add `OgarClassView::access_marking(class) -> Marking`: the reusable, fail-closed marking-inheritance hook. A class inherits its RBAC data-classification from its codebook domain (Health → Restricted/ PHI, Commerce → Financial, ProjectMgmt → Internal); any unclassified domain or unknown id → Restricted (fail-closed, never Public). Reuses the contract's existing `Marking` enum — no contract change. Tests: ogar-vocab 67 (+2 Health), ogar-class-view 12 (+3, 2 regressions fixed). clippy clean (no new warnings). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
…e::membership
The access_marking(class) -> Marking method collapsed access control into
a per-class data-classification scalar, "inherited" via an override. Wrong
framing: RBAC is a relation, not a stamp. Access is
classid :: role :: membership
— a class is reached by a role, a role by a membership — already modelled
in the registry (project_role 0x0117, project_membership 0x0108,
project_member_role 0x0118 = the membership↔role join) and in
lance-graph-rbac. A class does not carry a sensitivity tag; it is keyed by
classid into the role/membership relation like every other class.
Keeps the Health Active-Record builders + ClassView registry wiring
(d950e41) — those are correct and fix the registry reverse-gate
regression. ogar-class-view 11 tests green, clippy clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 87e8dd23d8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ("Diagnosis", class_ids::DIAGNOSIS), | ||
| ("LabValue", class_ids::LAB_VALUE), |
There was a problem hiding this comment.
Add canonical-concept mappings for health aliases
These aliases are only wired into HealthcarePort; the generic codebook path still goes through canonical_concept() before canonical_concept_id(). Since no Health arms were added there, the fallback turns Diagnosis/diagnosis into diagnosi and LabValue into labvalue, so ogar_codebook("Diagnosis") or LabelDTO::from_alias("LabValue") return None even though the aliases are now promoted. Consumers using the existing codebook/DTO path for the new Health names will silently miss the minted class ids; please add these aliases to canonical_concept() with coverage.
Useful? React with 👍 / 👎.
…-lance-graph-wmx76z
…s_ids::ALL)
CI (PR merge with main) failed: main added all_promoted_classes() — an
enumerator pinned to class_ids::ALL — after this branch's base. This
branch added the 7 Health concepts to class_ids::ALL (39) but the merged
aggregator still returned 32, so all_promoted_classes_matches_class_ids_
all_{in_length,order} failed.
Append the 7 Health builders (patient, diagnosis, lab_value, medication,
treatment, visit, vital_sign) in class_ids::ALL order. ogar-vocab 71 +
ogar-class-view 11 green; clippy clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
What
Mints the Health domain (
0x09XX) as a first-class, reusable part of the OGAR canonical registry — the foundation the medcare-rs consumer inherits from (never the reverse; agnostic lance-graph stays untouched).Commits
dd1ef95— mint the0x09XXHealth codebook (7 OGIT entities: patient, diagnosis, lab_value, medication, treatment, visit, vital_sign) +HealthcarePort(ports.rs).4b0c082—concepts_in_domain(ConceptDomain)— reusable, fail-closed enumeration hook: a domain-scoped consumer inherits its full concept set from the codebook instead of hand-maintaining a parallel list (so an upstream promotion surfaces as missing-coverage at the consumer's boot gate, never a silent gap).d950e41— rich Active-RecordClassbuilders for all 7 Health concepts (diagnosis0x0902carried to full fidelity as the worked example), wired intoogar-class-view'sOgarClassViewregistry (fixes a reverse-gate regression the codebook commit introduced).87e8dd2— revert a mis-framed per-classaccess_marking → Markingscalar. RBAC isclassid :: role :: membership(a relation via role/membership), not a sensitivity stamp with override semantics.Field names
English schema labels only — never German PII labels, never PHI values (OGAR Non-negotiable: PII).
Tests
ogar-vocab67 + 2 doctests ·ogar-class-view11 (2 regressions fixed) ·ogar-render-askama44 (downstream renderer) ·cargo check --workspaceclean · clippy clean.Coordinated with
lance-graph#<MedcareBridge alias + FieldMask projection>— consumesHealthcarePort.medcare-rs#<HIPAA RBAC>— inherits the Health concept set + thediagnosisfield basis.🤖 Generated with Claude Code
https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
Generated by Claude Code