SC-Oracare
Cloud dental practice management platform
ClearInsight AI rebuilt and extended into full practice management around its referral network: clinical charting, scheduling, revenue cycle, operations and a standalone patient portal, behind Microsoft Entra External ID and role based access control.
- Period
- Status
- Live demo, synthetic data
- Role
- Software engineer and architect: backend, identity and access, patient portal, deployment
- Team
- Personal project, built on the ClearInsight AI codebase
- Stack
- Django
- Django Channels
- PostgreSQL
- Redis
- Celery
- Microsoft Entra External ID
- RBAC
- Azure Blob Storage
- Docker
- Open live demo (opens in new tab)Hosted on a free tier; the first load can take up to a minute.
The problem
A dental practice runs its whole day in software: charting, treatment plans, scheduling, billing, staff and patient communication. When the original client ceased operations before commercial launch, ClearInsight AI had a working referral network and no practice around it. SC-Oracare is that platform extended in phases into full practice management, with patients served through their own portal, and I have been building it since June 2026.
The engineering challenge
- Grow without breaking the core. Every new capability had to arrive beside a referral workflow that was already running, without rebuilding it.
- Two kinds of people. Clinicians and office staff belong in a directory; patients and the family members who act for them do not, and their sign-in has to work differently.
- A record that never loses a fact. Patient identifiers are encrypted yet still have to be found, and nothing clinical or financial may simply disappear.
Architecture
Identity provider
- Entra External ID, Clinician sign-in
Clinician side
- Practice application, Django and Channels
Patient side
- Patient portal, Own accounts and session
Oracare AI
- Oracare AI, AI capabilities
Platform data
- Redis, Channels, tasks, cache
- Azure Blob Storage, Documents, images
- PostgreSQL, Encrypted patient fields
Sign in and patient scope
- Sign in. Clinicians and staff to Entra External ID (Sign in (OIDC)). Clinicians and office staff sign in through Microsoft Entra External ID. The tokens stay on the server in the session, so the browser only ever holds a session cookie, and the ID token’s expiry is the real end of the session.
- Patient in scope. Permitted. Clinicians and staff to Practice application (Scoped request); Practice application to PostgreSQL (Scope, audit). Every patient surface goes through one scope rule: a clinician’s own patients, or their offices’ patients. Reads and writes of patient data are recorded in an audit trail that holds who and what, never the clinical content.
- Outside the scope. Refused. Clinicians and staff to Practice application (Scoped request). A patient outside that scope never appears in a list or a search, and a record number guessed from outside returns nothing.
Refer to a specialist
- Plan item to referral. Clinicians and staff to Practice application (Scoped request); Practice application to PostgreSQL (Scope, audit). A treatment plan item that needs a specialist becomes a referral: the specialist joins the patient’s care team, and the team gets a treatment room.
- Care team opens the chart. Permitted. Clinicians and staff to Practice application (Scoped request); Practice application to PostgreSQL (Scope, audit). The specialist can open this patient’s chart because they are on the referral, so access follows the care relationship. The patient still does not appear in the specialist’s own patient directory.
- Treatment room. Practice application to Redis (Channels, tasks); Practice application to Clinicians and staff (Live updates); Practice application to Azure Blob Storage (Documents). Chat, the order of the plan and attachments update live over WebSockets through Django Channels and Redis. Attachments go to Azure Blob Storage.
- Completion. Practice application to PostgreSQL (Scope, audit). The referral completes when every step of the plan is done. Completion is derived from the steps, never set by a client.
Patient portal
- Prove the mailbox. Patients to Patient portal (Sign in, verify). Patients have their own accounts, separate from clinician sign-in: a password or an emailed one-time code, optional authenticator app MFA, and lockout after repeated failures.
- Choose and verify. Permitted. Patients to Patient portal (Sign in, verify); Patient portal to PostgreSQL (Linked patient only). Signing in proves control of a mailbox, not who is at the keyboard. The patient picks whose record to open, such as a child’s, and proves that person’s date of birth before any chart is readable.
- Switch patient. Refused. Patients to Patient portal (Sign in, verify). Switching to another linked family member drops the verification, so each record has to be verified on its own.
Dictate a referral
- Speak. Clinicians and staff to Practice application (Scoped request). A clinician dictates a referral in the referral wizard instead of typing it.
- Server-side call. Practice application to Oracare AI (Delegated token). SC-Oracare calls Oracare AI from the server with the clinician’s delegated token for that one capability. The browser never talks to the AI service, and SC-Oracare holds no model and no provider key.
- A draft, for review. Clinicians and staff to Practice application (Scoped request). The extracted details fill the wizard and stop at the review step. Missing details become short follow-up questions, and nothing is submitted automatically.
- If the service is down. Practice application to Oracare AI (Delegated token). A circuit breaker makes the call fail fast, and the form stays exactly as it was.
View diagram
SC-Oracare is a modular monolith: one Django deployment on PostgreSQL and Redis, split into apps by bounded context, such as patients, referrals, clinical, revenue, operations and the patient portal. One process serves both HTTP and WebSockets through Django Channels.
Each new capability arrived as a new module with its own tables, behind a feature flag, and the referral workflow it started from was preserved through every phase; the referral core itself is never flagged. Only one part has been split out as a separate service so far, the AI capabilities, which became Oracare AI.
The diagram above is a simplified view. It shows the clinician and patient sides as separate trust boundaries because they use separate identity systems, even though they run in the same deployment.
What each person gets
- Doctors and specialists chart patients, build treatment plans, create and receive referrals, and work each referral together in a treatment room.
- Office accounts run the practice: patient registration, appointment requests, provider availability and closures, billing and accounts receivable, inventory, staff and tasks.
- Staff administrators use a separate, staff-only admin portal for user management, subscription plans, sign-in logs, compliance checks and system status.
- Patients use their own portal for their treatment plan, health record, appointments, forms with e-signature, documents, secure messages, payments and telehealth.
Referrals at the core
A referral starts in a wizard that walks through the patient, the referral, the schedule, consent and a review, and submits once, at the end. The same engine serves every entry point: a doctor, an office acting for a doctor, and an anonymous QR code link. The patient consents through a time-limited, single-use link or an encrypted QR code, with a signature.
Every referral gets a treatment room: the care team, an ordered treatment plan the team can reorder, attachments and live chat. Clinical planning feeds the network too. A treatment plan item that needs a specialist becomes a referral on its own, and the referral completes when every step of its plan is done. That status is derived from the steps, so no client can mark a referral finished while work is outstanding.
AI-assisted referral
A clinician can dictate a referral instead of typing it. The audio is transcribed, the details are extracted into a structured referral, and the wizard fills every step up to the review and stops there. Anything missing becomes a short follow-up question, answered by voice or by typing, and nothing is submitted automatically. A photographed or uploaded document can propose patient details the same way, shown for confirmation before anything is filled.
These capabilities are served by Oracare AI. SC-Oracare calls it from the server with the signed-in clinician’s delegated token, so the browser never talks to the AI service and SC-Oracare holds no model and no provider key. The audit trail stays in SC-Oracare, which remains the record of who accessed what.
Key decisions
Evolve the ClearInsight AI codebase, not rewrite it
Options considered: a rewrite, a fork, or an evolution of the same codebase.
Why: the referral workflow already worked, with its history, its database and its running referral records. New capabilities were added as separate modules around that core, so it was never rebuilt.
Trade-off accepted: renaming the application was not cosmetic. Its tables and migration history had to be renamed together, in one transaction, so the database and the code never disagreed.
Patients stay out of the clinician directory
Options considered: give patients directory identities in the same tenant as clinicians, or give them standalone portal accounts.
Why: patients are not staff. In the clinician tenant each one would become a directory identity with its own lifecycle, and a patient-side problem could reach staff sign-in. Patient flows such as self-registration, family members and activation from a practice record are modelled badly by a workforce identity product.
Trade-off accepted: a second sign-in system to own: password hashing, email verification, optional authenticator codes, lockout and throttling.
An idle page is never kept alive
Options considered: refresh the session in the background while a page is open, or refresh it only on real activity.
Why: the identity token’s expiry is the real end of a session. Keeping an idle page alive automatically is how a clinical workstation stays signed in all night.
Trade-off accepted: people are signed out when they step away. A warning appears shortly before expiry, and choosing to stay signed in refreshes the session.
Security and identity
There are two identity systems, and they never share a session.
Clinicians, office staff and administrators sign in through Microsoft Entra External ID. The tokens stay on the server, in the session, so page scripts can never read them, and the ID token’s expiry is the real end of a session.
Patients have standalone accounts in the portal, with their own passwords, emailed one-time codes, optional authenticator app MFA and lockout. Signing in has two halves. The first proves control of a mailbox; the second picks whose record to open, since one guardian can hold several family members, and proves that person’s date of birth. Switching to another family member drops the verification.
Authorization is layered. One shared scope rule decides which patients a clinician may see: their own, or their offices’. Clinical pages add a care team check, derived from the referral itself, so a specialist brought in on a patient can open that chart without the patient appearing in their own directory. The admin portal is gated twice, on each view and in middleware, and the REST API requires authentication by default, so a new endpoint that forgets to declare a policy fails closed.
Protecting patient data
SC-Oracare is built to HIPAA requirements. A patient’s name, date of birth, email and phone number are encrypted field by field. Because that encryption gives a different result each time, patients are matched through a keyed blind index and looked up by an unencrypted medical record number, and every patient is created through one registration path that reuses a record only on an exact match.
Nothing clinical or financial is deleted. Clinical facts retire by status, signed notes refuse edits and take addenda instead, financial rows are voided, and merged patients are retired rather than removed, because “no allergy recorded” and “allergy deleted” must never look alike in a medical record. Every read and write of patient data leaves an audit entry that records who did what to which patient, and never the clinical content.
Delivery and operations
Treatment room chat, direct messages, document capture in the wizard and live notifications run over WebSockets through Django Channels, on a Redis channel layer so any worker can reach any connection. Each person’s notifications go to their own group, and the notification is written to the database before it is pushed, so an offline user or a dropped connection loses nothing.
Background work runs on Celery with Redis: appointment reminders, recall notices, token cleanup, nightly backups and a retention purge that never touches audit records or patient data. Email goes through one gateway that queues delivery and logs without patient data.
The application ships as a Docker image and is configured entirely from its environment. Moving the live demonstration off Azure onto free-tier hosting changed settings, not code: no view, model or template changed.
Result
SC-Oracare runs today as a live demonstration on synthetic patient charts only. It has no customers, so there are no usage numbers to report; the running system is the evidence. Next is the clinician’s view of retrieval: asking a question about one patient and getting an answer grounded in, and citing, that patient’s records, through Oracare AI.
Demo
Open the live demo (opens in new tab). It holds synthetic data only and runs on a free tier, so the first load can take up to a minute.