fix(patients): repair main's broken pipeline wiring and SSE auth - #51
Open
Ndifreke000 wants to merge 1 commit into
Open
Ndifreke000 wants to merge 1 commit into
Ndifreke000 wants to merge 1 commit into
Conversation
PR NexusHealthAll#38 (fix/ml-pipeline-wiring-and-migrations) left main in a state that doesn't compile and, once fixed to compile, panics on startup: - `pipeline` was never added to the `use crate::handlers::{...}` import in app_routes.rs, and `AppState` was missing the `pipeline_events` field pipeline.rs's handler needs -- so `cargo build` fails outright with "unresolved module `pipeline`" and "no field `pipeline_events`". - Once that's fixed, the router panics at startup: POST /api/v1/ingest/patient and GET /api/v1/patients/{id} were registered twice -- once in a new block PR NexusHealthAll#38 added, once in the original block from an earlier partial restore that was never removed. Axum's router refuses overlapping routes. - Separately, GET /api/v1/pipeline/events only accepted a header-based JWT. The browser's native EventSource API (used for the frontend's live triage updates) can't set an Authorization header, so every real SSE connection 401'd. Restored extract_claims_with_query_fallback (header first, falling back to a ?token= query param) and wired it into both the SSE handler and require_role, so routes gated by that middleware accept the fallback too. Verified locally end to end: backend builds and starts cleanly, GET /api/v1/patients returns real data, GET /api/v1/pipeline/events returns 200 with ?token= and 401 with neither, and a submitted patient resolves a real prediction via ml-service in under a second. cargo test --test patient_ingest_tests: 2 passed, 0 failed.
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.
Context
mainis currently broken. #38 (fix/ml-pipeline-wiring-and-migrations) fixed the migration version collision and re-exported the patient module, but left the router in a state that doesn't build, and has an auth regression once it does.What's broken on
mainright nowapp_routes.rscallspipeline::pipeline_eventsbut never addspipelineto theuse crate::handlers::{...}import, andAppStateis missing thepipeline_eventsfield thatpipeline.rs's handler reads (state.pipeline_events.subscribe()).cargo buildfails withunresolved module or unlinked crate 'pipeline'andno field 'pipeline_events' on type 'AppState'.POST /api/v1/ingest/patientandGET /api/v1/patients/{id}are registered twice — once in a new route block fix(pipeline): resolve migration version collision, export patient mo… #38 added, once in the original block from an earlier partial restore (ef2454e) that was never removed. Axum panics at router-build time:Overlapping method route. Handler for 'POST /api/v1/ingest/patient' already exists.GET /api/v1/pipeline/eventsonly accepts a header-based JWT (extract_claims). The browser's nativeEventSourceAPI (used by thenexusAppfrontend for live triage updates) can't set anAuthorizationheader, so every real SSE connection from the deployed frontend 401s.What this PR does
pipelineto the handler import list inapp_routes.rsand adds thepipeline_events: Arc<broadcast::Sender<PipelineEvent>>field toAppState, wired to the broadcast channel that's already constructed for the prediction worker (it just wasn't exposed to the route before).ingest_patient/get_patientroute registration, keepinglist_patientsandpipeline_eventsalongside the original two in one block.extract_claims_with_query_fallbackinutils/jwt.rs(header first, falling back to a?token=query param) and wires it intopipeline.rs's handler andrequire_rolemiddleware, so SSE and anyrequire_role-gated route accept the fallback.Testing
cargo build— clean (previously failed to compile on currentmain).cargo test --test patient_ingest_tests— 2 passed, 0 failed.ml-service, with a minted JWT:GET /api/v1/patients→200with real data (was unreachable — server wouldn't start).GET /api/v1/pipeline/events?token=...→200(was401).GET /api/v1/pipeline/eventswith no token →401(auth still enforced).POST /api/v1/ingest/patient→ worker resolved a real prediction viaml-servicein under a second, visible onGET /api/v1/patients/{id}.Test plan for reviewers
cargo buildsucceeds and the server starts without panicking.ml-service, confirmGET /api/v1/patientsandGET /api/v1/pipeline/events?token=<jwt>both return200.