# OllaBridge Cloud — live-app integration **Status:** the provider-side wiring already exists (`9-HuggingFace-Global/lib/providers/ollabridge.ts` + `chatWithFallback` short-circuits to OllaBridge when configured). What this document covers is the **user-facing pairing flow** in the live app, which today is only designed in `13-MedOS-Family/frontend/components/pages/SettingsPage.tsx` and not yet exposed to end users of `web/` and `9-HuggingFace-Global/`. This is the most credible "privacy-first" lever MedOS has. With OllaBridge Cloud, the user runs Ollama on their own machine; their prompts never leave their network. The MedOS server only exchanges encrypted, authenticated requests with the user's bridge. Read together with `PRIVACY.md` and `SAFETY.md` at the repo root. ## What changes for the user When a user pairs their bridge, the chat route detects `OLLABRIDGE_URL` (or, in the per-user model below, the user's pairing record) and routes through `streamWithOllaBridge` / `chatWithOllaBridge` instead of the default Hugging Face path. The safety sandwich does **not** change. `preCheck()` and `postCheck()` run on every request regardless of which provider answers. OllaBridge is just one more provider behind `chatWithFallback`. ## Two deployment modes | Mode | Who configures | Scope | |---|---|---| | **Operator-wide** | The MedOS deployment owner sets `OLLABRIDGE_URL` in the server env | All requests on that deployment go through that bridge | | **Per-user** *(new)* | Each user pairs from Settings → Linked devices → "Pair OllaBridge Cloud" | Only that user's requests route through their bridge | Operator-wide is what `chatWithFallback` already supports today. Per-user is what this doc plans. ## Per-user pairing flow 1. User opens **Settings → Linked devices → Pair OllaBridge Cloud** in the live app (the design exists in `13-MedOS-Family/frontend/components/pages/SettingsPage.tsx`). 2. UI shows a QR code + a 9-character pair code (rotates every 5 minutes). 3. On the user's machine, they install Ollama and run `ollabridge --pair`. The CLI scans the QR or accepts the pair code. 4. Bridge and MedOS exchange a one-time short-lived secret. MedOS server stores a per-user record: ```ts ollabridge_pairings ( user_id TEXT PRIMARY KEY, bridge_url TEXT NOT NULL, // user's bridge endpoint, often a tunnel bridge_token TEXT NOT NULL, // bearer token, encrypted at rest paired_at TEXT NOT NULL, last_seen_at TEXT, status TEXT NOT NULL // active | needs_reauth | revoked ) ``` 5. The chat route, on every request, looks up the user's pairing. If active, it routes through their bridge first; falls through to the global path on bridge failure (see "Failure handling" below). ## Provider-routing rules `chatWithFallback` becomes: ```text 1. Per-user OllaBridge pairing (if user is authenticated and has an active pairing) 2. Operator-wide OllaBridge (if OLLABRIDGE_URL is set) 3. Hugging Face Inference (12-model cascade, today's default) 4. Cached FAQ (always succeeds) ``` The order matters: privacy-first (user's own bridge) > operator's (still local-ish) > shared cloud > cached. ## Configuration Server env (operator-wide path, already supported): ```bash OLLABRIDGE_URL=https://your-bridge.example OLLABRIDGE_TOKEN= ``` Server env (per-user feature flag, to be added): ```bash MEDOS_PER_USER_OLLABRIDGE=true ``` When the flag is off, only operator-wide pairing is honoured. When on, the chat route also reads the per-user pairing record. ## Failure handling Bridges live on someone's home machine. They will go offline. - **Bridge offline.** Log it as a per-user metric (no PHI). Fall through to the next provider in the chain (operator-wide, then Hugging Face). The user's chat continues to work; they get a non-blocking notice in the UI: "Your local bridge isn't reachable; we'll use the cloud path until it's back." - **Bridge returns 401.** Mark the pairing as `needs_reauth`. The user is shown the re-pair flow next time they open the app. - **Bridge times out.** Same fallback path. Audit records the latency so we know when to lower the timeout. ## Privacy posture - The bridge URL and token live server-side, encrypted at rest (use the existing `lib/crypto.ts` helpers). - The pairing **does not** store any chat content; the safety engine's audit log already excludes content (`PRIVACY.md`). - A user can revoke their pairing from Settings; revocation is immediate and audited. - The bridge token never reaches the browser. ## Safety still applies The safety sandwich is unchanged: - `preCheck()` runs *before* the request leaves MedOS for the user's bridge. R5 emergencies are template-handled and never sent to any LLM, including the user's local one. - `postCheck()` runs on the bridge's response just like any other provider's. The deterministic post-filter rules apply identically. - Locale packs (`config/locales/*.medical.json`) are read server-side and used to compose the system prompt and the post-filter, irrespective of where the LLM physically runs. ## Implementation outline A contributor implementing per-user pairing would touch: 1. `9-HuggingFace-Global/lib/providers/ollabridge.ts` — extend with a per-user variant that takes `(bridgeUrl, bridgeToken)` arguments. 2. `9-HuggingFace-Global/lib/providers/index.ts` — make `chatWithFallback` accept an optional `userPairing` argument and try it first. 3. `9-HuggingFace-Global/lib/db.ts` — migration adding `ollabridge_pairings` table. 4. `9-HuggingFace-Global/lib/ollabridge-pairing.ts` — service module: create pairing, load pairing, mark needs-reauth, revoke. 5. `9-HuggingFace-Global/app/api/ollabridge/pair/route.ts` — API endpoints: start pairing (returns QR + pair code), confirm pairing, revoke. 6. `web/` (and / or each app frontend) — Settings page → Linked devices → "Pair OllaBridge Cloud" UI. The MedOS Family frontend already has the design. 7. CI: a smoke test that mocks a bridge and checks the routing precedence. ## What this document explicitly does NOT do - Promise that running Ollama is easy for everyone. It is a non-trivial install. The pairing flow assumes a technically comfortable user; the rest of MedOS continues to work for everyone else. - Bypass the safety sandwich. There is no "trusted bridge" mode. Every request is gated by `preCheck()` and `postCheck()`. - Move medical regional data into the bridge. Locale packs stay server-side. ## Roadmap 1. Land the per-user pairing schema + service + endpoints behind `MEDOS_PER_USER_OLLABRIDGE=false`. 2. Expose the UI in `web/` Settings. 3. Soft-launch with the flag off; flip on for opted-in users; collect failure-rate metrics (no PHI). 4. Make per-user pairing available to all users once the failure path is well-tested.