Onboarding a non-clinical user
End-to-end flow for getting a medical coder or billing staff member onto the Tools Portal — from DNS through their first AI extraction.
Four roles, four steps. Same backend, same login, same Organization
scoping as the doctor app.
DevOps — one-time infra
# 1a — pull the latest code with codes-tool + apps/tools
git pull origin main
# 1b — apply schema additions to your DB (additive, zero-downtime)
cd apps/api && pnpm db:push
# 1c — build + start the new container
cd ../..
docker compose build tools
docker compose up -d tools
# 1d — local smoke
curl -I http://localhost:8085/healthz # → 200For production:
- Add
tools.ohm.doctorA/CNAME → same target asstudio.ohm.doctor. - Caddy auto-issues the Let's Encrypt cert (the new block is already in
Caddyfile). curl -I https://tools.ohm.doctor→ 200 from the SPA shell.
Platform Admin — enable the feature for an org
There's no UI for the paywall layer yet — it's one SQL statement:
UPDATE organizations
SET features = features || '{"codes": true}'::jsonb
WHERE slug = 'kauvery';Until this is set, no user in that org can use the Codes Tool even if their per-user flag is on. This is the layer that maps to billing / sales entitlement.
Org Admin — invite the coder
- Open
https://admin.ohm.doctor→ Invitations → + Invite doctor button. - Email =
priya@kauvery.com, name =Priya Menon. - Role dropdown → pick Other (tools.ohm.doctor).
- Enabled tools card appears → tick Codes Tool.
- (Optional) Auto-approve + set password if you want them in immediately.
- Send invite.
Mistake the role or features? On the same page, find the row → click the pencil icon to edit a still-pending invitation. No need to revoke and resend.
Coder — accept and use
- Priya clicks the email link → lands on
app.ohm.doctor/accept-invite. - Sets her password.
- The page detects
roles === ["OTHER"]and redirects her tohttps://tools.ohm.doctor/loginautomatically. - She signs in with the password she just set.
- Sidebar shows AI Code Assistant (because
codesis enabled). Other tools are hidden. - She pastes a discharge summary → clicks Extract codes → sees ranked ICD-10/SNOMED/LOINC suggestions with rationale.
Day 2 — change which tools a user has
- Admin console → Doctors (lists all users including
OTHER— the table now shows a Role column). - Her row shows role badge
OTHER+ her current feature chips. - ⋯ menu → Manage tools → tick / un-tick → Save.
- Effect is immediate on her next page load. JWT strategy reads
enabledFeaturesfresh from DB every request — no logout needed.
Sanity checks after onboarding
# As Priya (OTHER user with `codes` enabled)
curl -H "Authorization: Bearer $PRIYA_JWT" \
"https://api.ohm.doctor/api/codes/icd10/search?q=fever"
# → 200 with results
# PHI access blocked
curl -H "Authorization: Bearer $PRIYA_JWT" https://api.ohm.doctor/api/patients
# → 403 (OtherRoleGuard)
curl -H "Authorization: Bearer $PRIYA_JWT" https://api.ohm.doctor/api/visit-notes
# → 403 (ClinicalStaff guard)
# Doctor flow unchanged
curl -H "Authorization: Bearer $DOCTOR_JWT" https://api.ohm.doctor/api/patients
# → 200Edge cases
| Scenario | Outcome |
|---|---|
| Admin invites OTHER with no features ticked | Coder lands at tools.ohm.doctor and sees "No tools enabled. Ask your admin to enable a tool." |
Org's features.codes is false | Coder gets 403 Feature "codes" is not enabled for this organization on any /api/codes/* action. Solution: SQL update in Step 2. |
Admin unchecks codes for an active coder | Coder's sidebar hides the tool on next page reload. Backend rejects immediately (DB-fresh feature read). |
OTHER user navigates to app.ohm.doctor/login | Login redirect detects role and bounces them to tools.ohm.doctor/login. |
| Doctor wants to use the Codes Tool too | They can navigate to tools.ohm.doctor directly. Their DOCTOR role is in the codes-tool allowlist. Auto-redirect only fires for sole-OTHER users. |
Tools Portal
The non-clinical user portal at tools.ohm.doctor — medical coders, billing staff, and future analytics tools. Generic role with per-user feature flags so admins can grant exactly the tools each user needs.
Roles & features
How the OTHER role + per-user enabledFeatures combine with the existing role enum to gate the Tools Portal without disturbing the clinical apps.