Engineering
How the platform is built, and the rules that keep a multi-tenant healthcare system from breaking in production.
Architecture at a glance
- Frontend (staff): Next.js — Basis Flow Web → Firebase Hosting
platform. - Frontend (patients): Flutter app (white-label) + Next.js client portal (Netlify).
- Backend: Python Cloud Functions gen2 (3.12), dispatcher pattern
(
REQUEST_MODEL_MAP),GB_1memory, per-functionsecrets=[]scoping. - Data: Firestore (
clinicsv2— never legacyclinics), camelCase fields, date-only values as strings. - Shared:
basiscore(Dart models),basiscoreui,basis-functions.
Deep dives: firebase-backend · firestore-schema · UNIFIED_DATA_ARCHITECTURE · CLINIC_MODULARIZATION · date-time-handling
The non-negotiable rules
The full list lives in CLAUDE.md. The ones that cause the most production pain:
- Add Firestore/Storage rules AND deploy before writing new paths — the #1 cause of permission errors. The rule file is inert until deployed.
- Never
updateDoconclinicsv2/{clinicId}directly from the web client. - Firestore field types are never guaranteed at runtime — a TS interface lies;
coerce and default every access (
String(v),(arr || []),(n ?? 0)). - Changing a Pydantic model requires redeploying the function.
- Never deploy all functions at once —
--only functions:name --force. - Encrypted Stripe fields —
StripeConfig.decrypt(...), never readoauth_token. - Adding a new field is a full-stack checklist — model + request models + add handler + update handler + frontend save + frontend load + TS type, or it silently won't persist.
Adding an Atlas tool = 5 silent-fail layers
TOOLS schema → TOOL_PERMISSION_MAP (default-DENY) → intent set (missing = stripped) →
dispatch branch → decorator secrets=[]. lint_registrations.py checks them.
Deploy
Never raw firebase deploy. Ship via ship.sh after explicit approval. See
deployment and How we work.
Testing & debugging
QA_GUIDE · TESTING_GUIDE · debugging-tools. Test with Admin role, not System Admin (which bypasses permission checks).
No auto-generated API reference (OpenAPI). We have hand-written contracts (reports-api-contract, atlas-api-webhooks) and no formal ADR log.