Replies: 3 comments
|
This is one of the best contributions this project has had — and yes, it lands. Error fidelity is the seventh guardrail property. You've articulated something I felt but hadn't named: the six properties all probe what the layer protects on the success path, and none of them probe what it does when the data layer fails. A guardrail layer that turns a rejected query into a confident "you have no observations" is failing at its actual job, and "verifiable, not marketing" has to extend to the failure paths or it's only half true. The framing that sold me: for an agent, "no data" and "your query was rejected" require opposite reactions, and for a patient-facing deployment "you have no observations" is a clinical statement the layer must never fabricate. That's exactly right, and it's the kind of thing that's invisible until someone names it. On the concrete plan — I'm in on all five, in your suggested order:
How I'd like to run it, if you're up for it: file the four remaining items as tracked issues (per the "issue tracker is the canonical log" convention). I'll label a couple of them One bigger-picture note: this is also exactly the kind of thing that makes the project matter outside itself. "Agents recover from structured errors far better than from silent failures" (your Medplum #9616 lineage) is a claim the whole agent-on-FHIR ecosystem needs to internalize, and a graded, verifiable error-fidelity property is how you make it undeniable. That's a contribution to the field, not just the repo. Thank you for leading with a direction instead of a drive-by fix. Tag me on the issues as you file them and let's build it. 🙏 |
|
Thank you, I’m fully in. I’ll file the four remaining issues in the agreed order and tag you on each. I’m happy to drive the conformance profiles/property-seven work, while leaving the transport adapter and strict-search slices open for help wanted contributors. Really appreciate the trust and the offer to credit the property’s authorship—let’s build it. |
|
Status: both bookends are on On the filed issues: #117 covers the core of #94, so I'll follow up there to reframe what remains (self-link hardening and the search-parameter registry); #93 (transport adapter) is still open and scoped for the |
Uh oh!
There was an error while loading. Please reload this page.
Proposing a direction rather than a single fix, so posting here instead of the tracker — the first concrete issue is filed (#74), and the rest follow individually if this resonates.
The
$conformancescorecard grades six properties — PHI redaction, immutable audit, step-up auth, human-in-the-loop, tenant isolation, medical disclaimers. The probes verify those protections on successful responses; none of them probes what the layer does when the data layer fails. Today the stack converts errors into confident wrong answers at three independent layers:{total: 0, entry: []}; any non-200/404 on read →None→ facade reports404 not found. An upstream 400 OperationOutcome, an expired OAuth token, and a genuinely empty record are indistinguishable.r6/fhir_proxy.pyL170–198Observation?date=ge2024returns unfiltered results. The self link (routes.py L901–909) correctly echoes only applied params, but there's no warning entry, no strict mode, and the self link is skipped for_summary=count, omitscontext-id, and doesn't URL-encode.r6/routes.pyL734+, L901{error: "search failed with status 400"}, discarding the OperationOutcome the Flask layer produced; the HTTP and SSE transports never setisErrorand surface uncaught exceptions as JSON-RPC-32603— while the stdio transport already does both correctly, so the transports disagree.services/agent-orchestrator/src/tools.ts,index.tsThe compounding effect: a rejected upstream query flows through as a 200 empty bundle,
fhir_searchtells the agent "No Observation resources found matching criteria" in_mcp_summary, and the audit trail recordssearch (upstream): 0 resultsfor a search that never executed. For an agent, "no data" and "your query was rejected" require opposite reactions — and for a patient-facing deployment, "you have no observations" is a clinical statement the layer should never fabricate.None of this needs invented machinery — FHIR R4 search already specifies the error contract (
Prefer: handling=strictas a client request servers SHOULD honor; the self-link SHALL;search.mode="outcome"warning entries; SHALL-reject for unsupported modifiers), and MCP classifies tool failures as results withisError: true(which stdio here already emits).The concrete work, if the direction lands
Each of these would be its own tracked issue (per the roadmap's "issue tracker is the canonical log" convention), and I'm offering the PRs:
_rewrite_urlsisn't sanitization), auditoutcome='failure'. Filed: Upstream proxy converts FHIR errors into empty search results (and auth failures into 404s) #74.isError+ sanitized OperationOutcome bodies, aligning with stdio's existing behavior via a transport-layer adapter.Prefer: handling=strict, emit lenient-mode warning entries, harden the self link, reject unsupported modifiers — with semantically safe suggestions only (neverdatetime → _lastUpdated; modification time isn't clinical time).action_policy.yamlload-bearing, then expose it as adescribecontract — today the YAML isn't loaded at runtime, isn't in the orchestrator image, and contradicts enforcement (e.g.fhir_propose_write); corrective errors should point at a contract the runtime actually obeys.$conformanceprobes, split into a local profile (deterministic everywhere) and a mock-upstream proxy profile — so the property is verifiable the same way the other six are, and a graded F is on the board even before the fixes land.Deliberate limits: param-level correction only (no StructureDefinition-level errors, consistent with Known Limitations); no changes to write semantics, step-up, or redaction; ignore-by-default stays for callers that don't opt into strict, so nothing breaks.
Context: this grew out of medplum/medplum#9616 — agents recover from structured errors far better than from silent or transport failures — applied to the guardrail layer itself. "Verifiable, not marketing" is the best line in this repo; this direction extends it to the failure paths. Does this fit where you want the project to go?
All reactions