Skip to content

Commit 927c668

Browse files
authored
Merge pull request #598 from AdaWorldAPI/claude/medcare-bridge-lance-graph-wmx76z
fix(ogar-codebook): restore COUNT_FUSE parity + classid-keyed authorize() probe
2 parents 1b2c450 + 9411790 commit 927c668

6 files changed

Lines changed: 858 additions & 0 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Consumer Scan TODO — cross-repo latent-issue sweep (2026-06-23)
2+
3+
> Two latent issue-classes surfaced this session. Both are *anticipatable*
4+
> across every consumer, not one-offs. This is the scan checklist: run each
5+
> check against each client, tick the box, file an issue on any hit.
6+
>
7+
> Status keys: `[ ]` = not scanned · `[x]` = scanned + clean · `[!]` = hit (file issue) · `[fixed]` = scanned + repaired this arc.
8+
9+
---
10+
11+
## Issue Class A — OGAR codebook-mirror drift
12+
13+
**Symptom:** `error[E0080]` at `lance-graph-ogar/src/lib.rs` COUNT_FUSE, or a
14+
runtime `assert_codebook_parity` panic — fires in **every** build that vendors
15+
the OGAR git dep when `ogar_vocab::class_ids::ALL` and a local mirror disagree
16+
on concept count or domain.
17+
18+
**Root cause:** a hand-maintained copy of the codebook that is NOT bound to
19+
`ogar_vocab` by `pub use`. The zero-dep contract mirror cannot re-export (it has
20+
no dep on ogar-vocab by design), so it is the ONE surface that drifts.
21+
22+
**The rule (E-CODEBOOK-MINT-IS-A-CROSS-REPO-ARC):** an OGAR concept mint is a
23+
cross-repo arc. DoD = OGAR `ogar-vocab` entry **+** `lance-graph-contract::ogar_codebook`
24+
mirror rows + `ConceptDomain` variant + `canonical_concept_domain` arm **+**
25+
`lance-graph-ogar::parity::domains_agree` arm — all in the same arc.
26+
27+
### Scan check
28+
For each client: does it carry a codebook/class-id table that is a **copy**
29+
rather than a `pub use ogar_vocab::class_ids::*` re-export? If yes → drift risk.
30+
31+
```
32+
# per repo:
33+
rg -n "ConceptDomain|canonical_concept_domain|class_ids::ALL|0x0[0-9A-F]{3}" --type rust
34+
# a re-export ("pub use ogar_vocab::class_ids::*") is SAFE; a literal id table is the risk.
35+
```
36+
37+
### Per-client status
38+
- [fixed] **lance-graph-contract** `ogar_codebook::CODEBOOK` — the one hand-maintained mirror. Synced to 43 (added 0x0B auth family). This is the only client that can structurally drift; guard it hardest.
39+
- [x] **openproject-nexgen-rs** `op-canon/src/class_ids.rs``pub use ogar_vocab::class_ids::*` re-export → cannot drift. CLEAN.
40+
- [x] **MedCare-rs** — SWEPT 2026-06-23 (workspace-wide id-table grep): no literal `0xDDCC`/`ConceptDomain` table in any `medcare-*` crate. Vendors `lance-graph-ogar` + `ogar-vocab` (git main); the Health set is inherited via the upstream gate, not a hand-list. CLEAN.
41+
- [x] **smb-office-rs** — SWEPT 2026-06-23: no local codebook copy; consumes via `lance-graph-contract`. CLEAN.
42+
- [x] **woa-rs** — SWEPT 2026-06-23: no literal id table; `WoaPort` pulls classid via PortSpec. CLEAN.
43+
- [x] **q2 / ladybug-rs / crewai-rust / n8n-rs / rs-graph-llm** — SWEPT 2026-06-23: none carries a literal OGAR id table (most don't consume the codebook at all). CLEAN.
44+
45+
> **Sweep result (2026-06-23):** a workspace-wide grep for literal codebook id-tables
46+
> (`const … CODEBOOK`, `=> ConceptDomain::…`, `pub const … : u16 = 0xDD…`) returns
47+
> exactly TWO authoritative tables: `OGAR/ogar-vocab` (the source) and
48+
> `lance-graph-contract::ogar_codebook` (the mirror, now fused at 43). Every other
49+
> consumer re-exports or pulls via PortSpec. **Class-A drift surface = the one mirror.**
50+
51+
### Guard to add (prevents recurrence)
52+
- [ ] Any client that maintains its own concept list MUST either (a) `pub use ogar_vocab::class_ids::*`, or (b) add a `const _` COUNT_FUSE against `ogar_vocab::class_ids::ALL.len()`. Hand-lists with neither are the bug.
53+
54+
---
55+
56+
## Issue Class B — PaaS deploy crash (Railway / Heroku / Cloud Run / Fly)
57+
58+
**Symptom (B1 — unreachable):** container starts, binds a fixed port (e.g.
59+
`0.0.0.0:3000`), platform routes its public edge to `$PORT` (often 8080) → the
60+
app is up but the proxy can't reach it (the `shuttle.proxy…:45472 > :3000`
61+
non-resolve medcare hit).
62+
63+
**Symptom (B2 — crash-loop):** the app writes to a CWD-relative dir
64+
(`./audit`, `./data`, `./cache`) that is read-only on the container image →
65+
`PermissionDenied` at boot, fail-closed crash-loop (the medcare
66+
`MEDCARE_AUDIT_DIR` crash).
67+
68+
### Scan checks
69+
```
70+
# B1 — fixed-port bind without $PORT fallback:
71+
rg -n "TcpListener::bind|SocketAddr|\.listen|bind\(" --type rust src
72+
# HIT if the bind addr is a config/literal with NO `std::env::var("PORT")` branch.
73+
74+
# B2 — CWD-relative writable path in a sink/store/cache initializer:
75+
rg -n '"\./|from\("\.|PathBuf::from\("[^/]' --type rust src
76+
# HIT if a write target defaults to a relative path instead of a writable data root.
77+
```
78+
79+
### Per-client status (web-app `main`/`server`/`serve` found)
80+
- [fixed] **MedCare-rs** `medcare-server/src/main.rs``$PORT` bind branch added; audit dir now derives `<lance-data-root>/audit` (writable), not `./audit`. Both classes repaired.
81+
- [ ] **woa-rs** `src/main.rs` — axum; verify `$PORT` bind + Tresor/PDF/sled write dirs use a writable data root (Stefan's Railway deploy is production).
82+
- [ ] **openproject-nexgen-rs** `op-server/src/main.rs` — verify `$PORT` + any RLS/audit write dir.
83+
- [ ] **q2** `crates/quarto-hub/src/server.rs` — verify `$PORT` + hub doc-store path.
84+
- [ ] **rs-graph-llm** `insurance-claims-service` / `medical-document-service` / `recommendation-service` / `notebook` mains — verify `$PORT` + any session/Lance store path.
85+
- [ ] **n8n-rs** `n8n-server/src/main.rs` — verify `$PORT` + sled/background-work dir.
86+
- [ ] **crewai-rust** `src/bin/server.rs` — verify `$PORT` + any cache dir.
87+
- [ ] **ladybug-rs** `src/bin/server.rs` — verify `$PORT` (note: uses CogRedis, separate concern).
88+
- [ ] **spider** `spider_worker/src/main.rs` — verify `$PORT` if exposed.
89+
- [ ] **lance-graph** `lance-graph-planner/src/serve.rs`, `cognitive-shader-driver/src/{serve.rs,bin/serve.rs}` — these are lab/serve surfaces; verify `$PORT` before any are deployed.
90+
91+
### Canonical pattern (copy from medcare)
92+
```rust
93+
// B1: bind $PORT when set (all interfaces), else fall back to config.
94+
let addr: SocketAddr = match std::env::var("PORT") {
95+
Ok(p) if !p.trim().is_empty() => format!("0.0.0.0:{}", p.trim()).parse()?,
96+
_ => settings.listen.parse()?,
97+
};
98+
// B2: derive writable paths from the data root the platform mounts,
99+
// never a CWD-relative "./audit" / "./data".
100+
```
101+
102+
---
103+
104+
## How to run this sweep
105+
1. One pass per repo with the rg checks above (5 min each).
106+
2. Tick `[x]` clean / `[!]` hit. For each `[!]`, file an issue in that repo's
107+
board (`ISSUES.md` / `Altlasten.md` / `braid`) pointing at this doc.
108+
3. Class-A hits also append to OGAR `EPIPHANIES` (mint-arc rule) if a new
109+
un-guarded mirror is discovered.
110+
4. Re-run after the next OGAR codebook mint — Class A is recurring by nature.

.claude/board/EPIPHANIES.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,92 @@
1+
## 2026-06-23 — E-AUTH-CLASS-WIRED-TO-RBAC — the OGIT-imported 0x0B AuthStore family is now the membrane front-door of authorize()
2+
3+
**Status:** FINDING (2026-06-23). The OGIT `NTO/Auth/Configuration` entity (arago's
4+
`auth_store`, 1:1 with OGAR `0x0B01`) is wired into `lance-graph-rbac` as the
5+
authorization membrane (keystone §7 / I-K7: the inner `authorize()` kernel never
6+
touches a token). `lance-graph-rbac/src/auth.rs`:
7+
8+
- `AuthProvider` enum = the preminted `0x0B` family (`Store`/`Zitadel`/`Zanzibar`/
9+
`OryKeto`); each variant's classid is resolved through the **zero-dep contract
10+
mirror** (`contract::ogar_codebook::canonical_concept_id`) — one source, no
11+
hardcoded `0x0B0N`, no `ogar-vocab` dep (BBB-safe).
12+
- `ClaimGrammar` per provider (subject/roles/tenant claim keys) — Zitadel's
13+
project-roles URN, Zanzibar's user/relation/namespace tuple grammar, the
14+
plain-OIDC base — the §7 "each profile carries its claim grammar as data".
15+
- `AuthProvider::resolve(sub, roles, tenant) -> ResolvedIdentity` — the §7 mapping
16+
(`sub → actor`, `role-key → roles`, `org → tenant`/scope). `ResolvedIdentity` is
17+
the ONLY thing that crosses inward; it feeds `authorize(rbac, &id.actor, class, op)`.
18+
- 4 tests incl. `resolved_identity_feeds_authorize` (membrane → kernel end-to-end)
19+
and `provider_class_ids_resolve_through_the_contract_mirror` (pins the 0x0B family
20+
to the codebook).
21+
22+
Token *extraction* (JWT/JSON parse via `grammar()`) stays at the consumer membrane —
23+
no JWT/serde dep leaks into the rbac tier. The consumer maps IdP role strings → its
24+
own role set. Cross-ref: OGAR `CLASSID-RBAC-KEYSTONE-SPEC.md` §7, E-RBAC-AUTHORIZE-PROBE-GREEN.
25+
26+
## 2026-06-23 — E-RBAC-AUTHORIZE-PROBE-GREEN — classid-keyed `authorize()` reproduces the shipped membrane gate bit-for-bit; keystone §5 promoted CONJECTURE→FINDING (for the in-repo reference)
27+
28+
**Status:** FINDING (probe green, 2026-06-23). The OGAR `CLASSID-RBAC-KEYSTONE-SPEC.md`
29+
§10 names `PROBE-OGAR-RBAC-AUTHORIZE` as the gate that must pass before any consumer
30+
collapses onto classid-keyed authorization: the classid-keyed kernel must reproduce a
31+
reference system's decision **bit-for-bit**. Built against the in-repo reference (the
32+
shipped `lance_graph_rbac::policy::Policy::evaluate` — the "reconcile the shipped
33+
MembraneGate path with the keystone" framing of `ISS-RBAC-AUTHORIZE-BY-CLASSID`):
34+
35+
- `lance-graph-rbac/src/authorize.rs` — `ClassRbac` trait (§4), `authorize(rbac, actor,
36+
class: ClassId, op)` (§5 positive ∧ op-gate kernel), `ClassGrants` (`PermissionSpec`
37+
**re-keyed by `ClassId`**, §11). The kernel mirrors the shipped deny reasons exactly
38+
("unknown role" / "insufficient read depth" / "predicate not writable" / "action not
39+
allowed") so the comparison is bit-for-bit, not just allow/deny.
40+
- `probe_ogar_rbac_authorize` — 15-tuple corpus across all three SMB roles, all three op
41+
kinds, the allow path, every distinct deny reason, the depth boundary, and the
42+
unknown-actor path → all equal to `Policy::evaluate`. GREEN.
43+
- `probe_is_falsifiable_under_wrong_keying` — proves the gate is not vacuous: a wrong
44+
classid flips an Allow, so the corpus genuinely tests the keying + kernel, not a
45+
delegation.
46+
47+
**Honest fence (what is NOT yet certified):** the shipped reference is positive
48+
role→permission only — no row-scope predicate, no field projection in the decision. So
49+
this gate certifies the §5 *positive ∧ op-gate* half and the §11 classid re-keying.
50+
The §5 stage-2 row-scope predicate and the projecting `Allow { scope, mask }` return
51+
remain keystone work; the stronger references (Odoo `ir.model.access ∧ ir.rule`,
52+
OpenFGA) exercise scope and are the follow-on probes. **Necessary, not yet sufficient**
53+
for the full keystone — but it is the step-4 reconciliation, and it unblocks the
54+
medcare #169 consumer-collapse (`authorize(actor, HealthcarePort::class_id("Patient"))`)
55+
against the positive-grant half. Trait promotion to `lance-graph-contract` (§11) and the
56+
scope-bearing references are the next deliverables.
57+
58+
## 2026-06-23 — E-CODEBOOK-MINT-IS-A-CROSS-REPO-ARC — an OGAR concept mint is NOT done until the lance-graph-contract mirror lands in the SAME arc
59+
60+
**Status:** FINDING (cross-repo cascade, 2026-06-23). Minting the `0x0B`
61+
AuthStore family in OGAR (`ogar-vocab` PR #110, merged to OGAR `main`) added 4
62+
concepts to `ogar_vocab::class_ids::ALL` (39 → 43). The `lance-graph-contract`
63+
zero-dep mirror (`ogar_codebook::CODEBOOK`) was NOT updated in the same arc, so
64+
the **compile-time `COUNT_FUSE`** in `lance-graph-ogar` (`assert!(mirror::CODEBOOK.len()
65+
== ogar_vocab::class_ids::ALL.len())`) fired `error[E0080]` in **every** lance-graph
66+
consumer that vendors the OGAR git dep — medcare CI went red on a `cargo build`,
67+
not just a test. The fuse did exactly its job; the gap was process.
68+
69+
The lesson, promoted to a rule:
70+
71+
1. **The codebook has TWO authoritative homes that move in lockstep.** OGAR
72+
`ogar-vocab` (the source) and `lance-graph-contract::ogar_codebook` (the
73+
zero-dep wire mirror). The `COUNT_FUSE` (compile-time) + `assert_codebook_parity`
74+
(runtime, in `lance-graph-ogar`) bind them. A mint touches BOTH or it breaks
75+
the build of everything downstream.
76+
2. **A mint is a cross-repo arc, not a single-repo PR.** The Definition-of-Done
77+
for "mint concept X in OGAR" includes: (a) the OGAR `ogar-vocab` entry +
78+
`ConceptDomain` variant + `canonical_concept_domain` arm; (b) the paired
79+
`lance-graph-contract` mirror CODEBOOK rows + `ConceptDomain::X` variant +
80+
`0xDD => X` arm; (c) the `lance-graph-ogar` `domains_agree` match arm (else the
81+
runtime parity test panics); (d) the consumer coverage gates that inherit the
82+
concept set (medcare's RLS fail-closed gate inherits the Health set this way —
83+
a new Health concept becomes a fail-closed boot error, by design).
84+
3. **Fix landed here:** mirror CODEBOOK +4 auth rows (auth_store 0x0B01,
85+
auth_zitadel 0x0B02, auth_zanzibar 0x0B03, auth_ory_keto 0x0B04),
86+
`ConceptDomain::Auth`, `0x0B => Auth`, and the `domains_agree` `(O::Auth, C::Auth)`
87+
arm — restoring 43 == 43. Confirmed by the OGIT Configuration ⊨ auth_store
88+
convergence (arago's Jan-2026 bridge entity). See OGAR `docs/CLASSID-RBAC-KEYSTONE-SPEC.md`
89+
§7 + OGAR `EPIPHANIES` for the mint provenance.
190
## 2026-06-23 — E-DOLCE-ODOO-SILENT-SUFFIX-DRIFT — two hydrator-side suffix rules silently failed their own comments; cross-validation against `od_ontology::alignment` caught it (odoo-rs PR #15)
291

392
**Status:** FINDING (cross-validation result from a sibling repo). Two

.claude/board/ISSUES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Issues Log — Open + Resolved (double-entry, append-only)
22

3+
## 2026-06-23 — ISS-OGAR-AUTH-MIRROR-DRIFT — `0x0B` AuthStore mint broke the contract mirror's COUNT_FUSE in every consumer
4+
5+
**Status:** RESOLVED 2026-06-23 (this commit). OGAR `ogar-vocab` PR #110 minted the `0x0B` AuthStore family (4 concepts: auth_store 0x0B01, auth_zitadel 0x0B02, auth_zanzibar 0x0B03, auth_ory_keto 0x0B04) and merged to OGAR `main`, taking `ogar_vocab::class_ids::ALL` from 39 → 43. The paired `lance-graph-contract::ogar_codebook::CODEBOOK` mirror was NOT updated in the same arc, so the compile-time `COUNT_FUSE` in `lance-graph-ogar` (`assert!(mirror::CODEBOOK.len() == ogar_vocab::class_ids::ALL.len())`) fired `error[E0080]` (`vendor/lance-graph/crates/lance-graph-ogar/src/lib.rs:113`) in **every** consumer vendoring the OGAR git dep — medcare CI went red on `cargo build`. **Resolution:** added the 4 auth rows + `ConceptDomain::Auth` + `0x0B => Auth` to the mirror, and the `(O::Auth, C::Auth)` arm to `lance-graph-ogar::parity::domains_agree` (else the runtime `assert_codebook_parity` test panics). 43 == 43 restored; `cargo test -p lance-graph-contract` green. **Process fix (see EPIPHANIES E-CODEBOOK-MINT-IS-A-CROSS-REPO-ARC):** an OGAR concept mint is a cross-repo arc — the OGAR entry + the contract mirror + the `domains_agree` arm land together, never split across sessions. **Merge note (2026-06-23):** main landed #595 (auth sync) + #597 (PRODUCT + ACCOUNTING_ACCOUNT, OGAR #111) first; on merge this branch took main's superset `ogar_codebook.rs` (45 concepts incl. the `AppPrefix` render layer), so the auth mirror rows here are subsumed — the `domains_agree` Auth arm + this finding stand.
6+
37
## 2026-06-22 — ISS-CONTRACT-APP-PREFIX-MIRROR — `contract::ogar_codebook` lacks the OGAR#97 `APP_PREFIX` / `render_classid_for` mirror, so membrane consumers must hand-stamp the hi-u16 render prefix
48

59
**Status:** RESOLVED 2026-06-22 (`claude/contract-app-prefix-mirror`) · Owner: lance-graph-contract · Surfaced by: `.claude/knowledge/ogar-consumer-preflight.md` (the consumer spellbook).

0 commit comments

Comments
 (0)