Skip to main content
Synced from the repo — do not edit here

Canonical source: FEATURES.md. This page is generated by docs/scripts/sync-handbook.mjs. Edit the source file in the repo; changes appear here on the next build.

Basis Platform — Feature Status

AGENTS: Read this before touching any feature. Update the relevant row when you complete work. Format: Status | Last changed | What changed | Known issues

For bugs: Find the feature row → read Key Files → check Known Issues before writing any code.

Three-file system:

  • FEATURES.md (this file) — what exists now, current state, known issues
  • ROADMAP.md — what to build next, YAML task definitions with test criteria
  • CLAUDE.md — how to work here, rules, patterns, gotchas

Versioning

AppCurrent VersionLast ReleaseDistribution
Basis Hybrid (iOS)See basishybrid/pubspec.yamlApp Store via TransporterTestFlight → App Store Review
Basis Hybrid (Android)See basishybrid/pubspec.yamlGoogle Play ConsoleInternal testing → Production
Basis Flow WebN/A (SPA)Firebase Hosting (continuous)firebase deploy --only hosting:platform
Basis WebN/A (SPA)Netlify (auto-deploy on push)Git push to branch
Cloud FunctionsN/A (per-function)firebase deploy --only functions:name --forcePer-function deployment

How to Update This File

After completing work on any feature, update its row:

  • Status: 🟢 Stable / 🟡 Active Dev / 🔴 Known Issues / ⚪ Untouched
  • Last Changed: Date + brief description (not a full changelog — one line)
  • Known Issues: Add new ones, remove fixed ones

Platform Apps

AppStatusLast ChangedKey PathNotes
Basis Flow Web (staff)🟡 Active Dev2026-03-15 archive/delete workflow, proration fix, multi-location availabilityhybrid/basisflow-web/Main staff platform. Deploy: firebase deploy --only hosting:platform
Basis Web (client portal)🟡 Active Dev2026-03-04 bank transfer processing statushybrid/basisweb/Deploys to Netlify (NOT Firebase). Auto-deploy on push
Basis Hybrid (mobile)🟢 StableActive maintenancehybrid/basishybrid/Flutter. DO NOT flutter clean
Basis Flow (legacy Flutter)⚪ Deprecatedhybrid/basisflow/⛔ DO NOT MODIFY

Backend Infrastructure

FeatureStatusLast ChangedKey FilesKnown Issues
Firebase Functions🟢 Stablebasis-functions/functions/src/Always use GB_1 memory. Never deploy all at once
Firestore Rules🟢 Stablebasis-functions/firestore.rulesEach settings/{name} needs its OWN explicit rule — no wildcard
Storage Rules🟢 Stablebasis-functions/storage.ruleshasPermission() checks BOTH implicit_permissions and permissions arrays
Firebase Auth🟢 StableAuth via Firebase ConsoleCustom domains must be added to Auth → Authorized Domains
Activity Log🟢 Stable2026-03functions_activity_log.pyLLM-friendly audit logging. Categories: CATALOG, CLINICAL, PROTOCOL, SETTINGS, SCHEDULING, USERS, COMMUNICATION, BILLING, DATA, SECURITY. Stored at clinicsv2/{clinic}/activity_log/{id}. Used by copilot and cron functions for audit trail.
Scheduled Crons🟢 Stable2026-03-04 status transitionsfunctions_clinic.pyprocess_waitlist_notifications (every 15 min). process_client_status_transitions (every 15 min, GB_1): auto-reactivates paused clients, auto-deactivates scheduled clients.
CI/CD Pipeline🟢 Stable2026-03-06.github/workflows/, .github/scripts/Autonomous dev pipeline: nightly orchestrator (2 AM UTC) → triage agent (Haiku) → build agent (Sonnet) → QA agent (Haiku). Slack notifications for all events. See docs/claude/operations.md.
Health Check🟢 Stable2026-03health-check.yml, functions_clinic.py → health_checkHourly health check. Tests Firestore, Auth, GCS. Alerts on failure.
Clinical Audit Trail🟢 Stable2026-03-08functions_clinical_audit.pycreate_clinical_audit() helper for logging clinical data changes. Stores at clinicsv2/{clinic}/clinical_audits/{id} with before/after snapshots. Used by superbill auto-generation and agent execute tools.
Superbill Auto-Generation🟢 Stable2026-03-08functions_superbill.pyFirestore trigger on notes with billing codes → auto-creates draft superbill. Separates ICD-10/CPT. superbill_service callable for status management (draft → submitted → accepted/rejected). 2026-07-26: structured lineItems + fees + provider/patient blocks + totalFee (#448); server-side branded patient-facing PDF via superbill_service get_superbill_pdf (#450); auto-generate on/off via settings/billing.superbillsEnabled toggle (#452). 2026-08: on ISSUE the superbill PDF is saved to the client's documents (users/{uid}/files/superbill_{id}.pdf) via _persist_superbill_document so cash-pay / OON clients can self-retrieve it (#800).
Insurance Billing / RCM (Stedi)🟡 Active Dev2026-08-21 batch: billing workspace + Ready-to-bill queue (#795), Review & submit scrubber + AI denial-risk (#797), secondary/COB claims (#784), corrected/voided claims (#785), policy-level prior-auth/referral #s + per-procedure modifiers (#806), coverage badge (T4), unmatched-remittance reconcile (#739), auto-eligibility nightly + at-booking (#786), per-client billing method + AoB (#658) — all deployedfunctions_stedi.py, stedi_client.py, stedi_claims.py, stedi_scrubber.py, billing/page.tsx, InsuranceClaimsSection.tsx, CoverageBadge.tsx, ClientDetailPage.tsxFull pipeline: eligibility 270/271, 837P submit + resubmit + secondary(COB) + corrected(freq 7)/void(freq 8), 999/277CA/835 lifecycle webhook, ERA reconcile by PCN + unmatched-remittance capture, /billing workspace (Ready-to-bill · Claims · Transactions). Billing method (insurance/courtesy/time_of_service) + AoB drive claim flags. Prior-auth/referral are POLICY-level (no per-claim UI). Demo clinic axuk-khwf-prkr sandboxed (test key eligibility; claims → Stedi Test Payer). ERA enrollment E2E needs a real practice NPI (fake demo NPI is ERA-enrolled elsewhere — exclusive per NPI). Collections metering (#14) next. 2026-08-21 — #802 deployed (stedi_denial_intelligence, stedi_generate_appeal, stedi_outcome_rollup): Denials & underpayments worklist — denied/underpaid claims decode their CARC/RARC into a plain-language reason + a deterministic next action; AI drafts a payer-ready appeal letter grounded in the clinic's own denial-outcome history and NEVER auto-submits (biller reviews → sends → "Mark appealed" logs the result to the denial-outcome ledger, which sharpens future drafts). 2026-07-26: multi-specialty provider-scope enforcement + auto therapy modifiers (GP/GO/GN) + AT/25/59-XP warnings, rendering provider sourced from the billed appointment (#608); future-date submit guard + editable resubmit date + provider/linked refs in the claim drawer (#616). See docs/claude/insurance-rcm.md · docs/features/billing-insurance.md.

Core Features

Scheduling

Sub-featureStatusLast ChangedKey FilesKnown Issues
Booking🟢 Stablefunctions_clinic.py → book_appointmentMembership booking window constraints applied; test with Admin not System Admin
Google Calendar 2-way sync (#558)🟢 Stable2026-07-21 book/edit/reschedule/cancel propagate to the clinic's Google Calendarfunctions_google_meet.py (calendar_link_fields/patch/delete), functions_clinic.pyReschedule PATCHes in place (Meet link preserved); cancel deletes (sendUpdates=all); waitlist swap deletes the original attendee's event so they stop getting updates. Verified live (tools/verify_558_calendar_sync.py). Forward-only: events booked before deploy have no linkage.
Reschedule across services (#561)🟢 Stable2026-07-21 reschedule modal gains Service selector + staff-eligibility guardEventDetailsDrawer.tsx, functions_clinic.py → update_event_detailsBackend rejects a service the resulting staff don't offer (fail-open when service has no coach roster); audit txn carries old/new service name. NOT retroactive — old wrong-service events need re-reschedule/Edit or a targeted backfill.
Availability🟢 Stable2026-03-15 multi-location coach availabilityfunctions_clinic.py → find_availability_intervals, StaffDetailPage.tsxAvailability blocks use ISO weekday (1=Mon, 7=Sun) — NOT 0-indexed. SlotModal supports multi-location selection (checkboxes) — creates one block per location with deduplication.
Group Services🟢 Stable2026-02-02 materialization fixfunctions_clinic.py → materialize_group_seriesTimezone shift fixed; use UTC midnight for date creation
Waitlist🟢 Stable2026-01-25 locationId filter removedfunctions_clinic.py → join/leave/assign_from_waitlistget_waitlist returns list[dict] (not model) to preserve entryId
Cancellation🟢 Stablefunctions_clinic.py → cancel_appointmentLate cancellation detected from membership cancellationPolicy
Rescheduling🟢 Stabletools/test-reschedule.jsUse test tool to verify duration preserved after move
Unavailability🟢 Stableclinic_service → create_unavailabilitycreatedByUid stored on events; transactions logged
Link appointment to a program (#257)🟢 Stable2026-08-17 associate an appointment with one of the client's active programs from its details drawerEventDetailsDrawer.tsx (editProgramId, "Link to program"), functions_clinic.py (edit-appointment program_id, empty = unlink), model_event.py (Event.protocolId)See docs/features/link-appointment-to-program.md. Clearing the selection unlinks.
Open-Gym / QR Check-In (#721)🟢 Stable2026-08-17 members scan a per-location QR to check in with no appointment; appear in dashboard "In Session"functions_clinic.py → open_gym_checkin (attended drop-in event, idempotent, optional credit), model_clinic.py (Location.openGymServiceId, Service.dropInCheckinEnabled/dropInDeductsCredit), dashboard/page.tsx ("In Session"), basishybrid modal_checkin_scanner.dartCheck-in events carry source='open_gym_checkin'. See docs/features/qr-check-in.md.

Next: Google Calendar two-way sync (Phase 3). Recurring appointment management improvements.

Labs

Sub-featureStatusLast ChangedKey FilesKnown Issues
Lab Upload & Analysis🔴 Known Issuesfunctions_ai_documents.py, document_processor.pyImportLabModal / UploadDocumentModal in Basis Flow Web was broken by a change — ⛔ DO NOT MODIFY these components
Lab Ordering (Junction)🟢 Stablefunctions_junction.pyWebhook at junction_webhook; results in clinicsv2/{clinic}/lab_orders
Lab Registry🟢 Stablemetric_registry.py, get_lab_registry HTTP fnClinic synonyms at clinicsv2/{clinic}/settings/labSynonyms
Lab Visualization🟢 StableClientDetailPage.tsx → LabsTabReference ranges age/gender-aware when available

Next: Unified clinical document extractor (Phase 1.5 in ROADMAP.md).

Chat & Messaging

Sub-featureStatusLast ChangedKey FilesKnown Issues
Staff ↔ Client Chat🟢 Stablefunctions_chat.py, ChatDrawer.tsxhumanChatEnabled / humanChatClientReplyEnabled flags control access
Push for Chat🟢 Stablefunctions_notifications.pyFCM triggers on new messages; device token at users/{uid}.deviceToken
AI Chat (client)🟢 Stablestub_service_chat_ai_backend.dartaiChatEnabled flag; aiDefaultFallbackPrompt for KB misses
Chat Blast (#691)🟢 Stable2026-08-16 broadcast a message to a filtered audience (membership/status/payer/service-behavior), 2-step review, sent history + duplicatefunctions_chat_option_a.py (chat_blast, chat_blast_count, list_blast_recipients, list_blasts, _blast_author), components/chat/BlastTab.tsx, messages/page.tsxSends as the clinic ("Care Team"), pushes to recipients, writes into each client's own thread so staff aren't spammed. History at clinicsv2/{clinic}/blasts. See docs/features/chat-blast.md.

Next: WhatsApp Business channel (Phase 3 in ROADMAP.md). Twilio SMS messaging (Phase 5).

Copilot (Atlas AI — Staff)

Sub-featureStatusLast ChangedKey FilesKnown Issues
Agent Core🟢 Stable2026-03 Claude Opus 4.6 + save_clinical_note toolfunctions_ai_agent.py, functions_orchestrator.pyAlways use fire.db — never create separate Firestore client
Quick Answers🟡 Active Dev2026-03-04 complex query bypassquick_answers.py_is_complex_query() detects multi-metric/protocol/report queries and skips QA → routes to full agent. Simple single-metric queries still fast-pathed.
Knowledge Base🟢 Stablefunctions_ai.py → kb_searchStored in clinicsv2/{clinic}/settings/copilot.knowledgeBase[]
Orchestrator🟢 Stable2026-02 intent classificationfunctions_orchestrator.pyIntent: CLINICAL/OPS/RESEARCH/MIXED → filters tools accordingly
AI Scribe (Telehealth)🟢 Stable2026-03functions_scribe.py, generate_soap_from_transcript toolRecall.ai bot joins video calls → transcript → Claude Sonnet SOAP note with patient context (conditions, meds, allergies, recent notes). Sessions at clinicsv2/{clinic}/scribe_sessions. Gap: In-person ambient scribe via Recall.ai Desktop SDK (Phase 2.6).
Save Clinical Note🟢 Stable2026-03 new toolfunctions_ai_agent.py → _exec_save_clinical_noteCopilot can save notes directly to patient chart (requires clinician confirmation)
Streaming🟢 Stableclinical_agent_stream, RTDB debug.actionsUse RTDB debug to verify tool routing path
Patient Memory🟢 Stablefunctions_ai_memory.pyStored at clinicsv2/{clinic}/clinic_users/{uid}/settings/memory
Atlas REST API🟢 Stable2026-07-10 auditedfunctions_atlas_api.pyAPI key auth (X-API-Key/Bearer), gen/validate/revoke, clinic scoping, rate limits. Settings UI EXISTS (Settings → API & Webhooks). Scopes ENFORCED as of 2026-07-10 (#182): 'clinical'/'admin' gates PHI tools, 'atlas'/'admin'/'operations' gates writes, else read-only — hard tool-level filter (filter_tools_for_api_key); legacy scope-less keys grandfathered full access.
MCP Server🟢 Stable2026-07-10 auditedfunctions_mcp.pyMCP 2024-11-05, JSON-RPC 2.0; 14 read tools + atlas_query meta-tool; shares the REST API key store (managed in the same Settings UI). Key scopes enforced at tool level (#182, shares filter_tools_for_api_key). Gap: tool calls route through the agent (latency) instead of direct bindings.
Test Suite🟢 Stable2026-02 6/7 passingfunctions/test/test_copilot.pySleep query fails (test API key needs clinical permission)
SSE Streaming + Extended Thinking🟢 Stable2026-06clinical_agent_sse (functions_ai_agent.py)Live reasoning + elapsed timer in basisflow-web Atlas panel.
Observation Engine (Need Attention)🟢 Stable2026-07-21 heartbeat-crash fixfunctions_ai_agent.py, heartbeat dispatcher/workerProactive scan→score→ground→dashboard briefing card. Detectors: templates / clinician-rules / autonomous. Toggles in Settings→Need Attention. ⚠️ 2026-07-21: was crashing every ~15 min (firebase_functions.logger.warning AttributeError) → engine dormant fleet-wide after #371 broadened the scan; fixed (logger.warn), verified clean.
Client Apps — In-focus metric (heroScore) #564🟡 Built, pending platform deploy2026-07-22settings/page.tsx (ClientAppTab), preferences/clientApp.heroScoreSelector to choose/hide the home-screen hero score (biologicalAge/recovery/cardiovascular/adherence/none); mobile already reads it (rp_live.dart). Mirrors slotGrouping.
Chat Draft-Assist + Auto-Categorize🟢 Stable2026-06functions_ai_agent.py"✦ Draft with Atlas" in chat; incoming messages auto-categorized.
Scheduled Tasks🟢 Stable2026-06schedule_task tool, heartbeatOne-time + recurring reminders/messages/reports ("every Friday send me a revenue report").
Clinic Analytics Engine🟢 Stable2026-06functions_reports.py (generate_report, run_report)NL reports: revenue/sessions/orders/clients. Nightly rollups + live fallback.
Knowledge-Gap Loop🟢 Stable2026-06gap-loop capture + weekly digestCaptures what Atlas couldn't answer → weekly digest.
Atlas in Slack — AI Employee🟢 Stable2026-07functions_slack_bot.py, functions_atlas_slack.py, atlas_slack_worker/events/interactivityOps Q&A + confirm-card approvals as Slack buttons. Per-clinic install (state=clinic_id). PHI denylist gate + Settings→Atlas AI toggle. Identity via userMap→email→pending.
Atlas Ops Write-Tools (Slack + web)🟢 Stable2026-07functions_ai_agent.py (_call_clinic_handler, _COPILOT_ACTION_WRITERS)Confirm-card gated: invite client/staff, time-off, products, services, memberships, duplicate (service/membership/protocol), tasks, reschedule/reassign. Bright lines: never message patients, never charge.
Atlas Services & Memberships (with Stripe mint)🟢 Stable2026-07functions_ai_agent.py (_mint_stripe_price)Create/update/duplicate services + memberships; mints Stripe product+price on the clinic's connected account (execute_copilot_action/atlas_slack_interactivity carry STRIPE_API_KEY).
Goal-Gate (heartbeat evaluator)🟢 Stable2026-07-10functions_heartbeat.py (_goal_gate, _default_criteria)#157: fresh-context Haiku evaluator judges each heartbeat/scheduled run against successCriteria (per-task or per-type defaults) before the result ships; 1 retry with feedback, then ships flagged lowConfidence. Verdicts → atlas_signals (stream gate). Fails open. ⚠️ Deploy landmine: helpers must NOT sit between @on_schedule and the dispatcher def (decorator displacement deleted the dispatcher once — restored).

Next: Goal-based evaluator stop-gate (autonomy prerequisite) · continual-learning signal capture (confirm-card accept/edit) · consumer Atlas. See docs/claude/atlas-operator-plan.md.

Programs & Protocols

Sub-featureStatusLast ChangedKey FilesKnown Issues
Protocol Assignment🟢 Stablefunctions_clinic.py → assign_protocolDual-write: clinicsv2/.../protocols + users/{uid}/protocols
Event Generation🟢 Stablefunctions_clinic.py → assign_protocolEvents get protocolId, habitId, clinicId — needed for preset lookup
Client Completion Sync🟢 Stablefunctions_event_mirror.py → sync_user_event_to_clinicFirestore trigger; needs clinicId on event to find clinic path
Preset Display (Hybrid)🟢 Stableroute_summary.dart → _loadRecurringEventPresetsLooks up clinicsv2/.../protocols/{id} → finds habit by habitId
Biomarker Tracking🟢 Stablelib/biomarker-catalog.ts, BiomarkerProgressCard.tsx80% adherence required for valid analysis
Copilot Protocol Context🟢 Stablelib/protocol-copilot-context.ts"Ask Copilot" button in PlanTab builds full context
Plan of Care — Service Visits (#673)🟢 Stable2026-08-16 protocols can include Service Visit activities (a booked clinic service with a target # of visits) alongside habits/supplements; Plan tab shows a mixed plan cardfunctions_clinic.py (book_care_plan_series shared planId, targetVisits/closeReason, appointment↔activity auto-complete bridge), model_event.py (Event.planId), PlanTab.tsx (attended/target counters, close-with-reason, flat chronological calendar), lib/protocol-data.ts (Service Visits type)Booked visit series shares one planId; per-visit .ics confirmation via send_care_plan_confirmation_email. See docs/features/plan-of-care.md.

Next: Voice interface for Atlas (Phase 4 in ROADMAP.md). Ambient scribe improvements (Phase 2.6).

Notifications & Email

Sub-featureStatusLast ChangedKey FilesKnown Issues
Appointment Emails🟢 Stablefunctions_appointment_emails.pyiCal attachments included; branded domain via MailerSend
Email Delivery Tracking🟢 Stable2026-03functions_email_webhooks.pyMailerSend webhook → clinicsv2/{clinic}/clinic_users/{uid}/emailEvents. Tracks delivered/bounced/spam. Correlates by recipient + subject + timestamp.
Push (Appointments)🟢 Stablefunctions_appointment_notifications.pyDevice token at users/{uid}.deviceToken
In-App (Hybrid)🟢 Stableservice_notifications.dartiOS 64-notification limit handled; timezone-aware scheduling
Guest Invite Email (#485)🟢 Stable2026-08-17 a guest added to a booking (name+email) is emailed a branded invite + .ics AND captured as a CRM leadfunctions_appointment_emails.py → send_guest_invite_email, functions_clinic.py → _process_event_guest (from book_appointment), functions_growth_leads.py → create_referral_lead (source_id='event_guest')Works from app, client portal, and staff booking. Guests without an email are recorded but not emailed/leaded. See docs/features/guest-invites.md.

Next: Twilio SMS reminders (Phase 5 in ROADMAP.md). WhatsApp Business API (Phase 3 in ROADMAP.md).

Onboarding

Sub-featureStatusLast ChangedKey FilesKnown Issues
Client Invitation🟢 Stablefunctions_clinic.py → add_clinic_userInitializes onboarding state, sends welcome email
Intake Forms🟢 Stablefunctions_onboarding.pyForms at clinicsv2/{clinic}/settings/onboarding; rendered at forms.basishealth.io
Mobile Onboarding🟢 Stableroute_onboarding.dart9 pages: privacy → health → analyze → devices → profile → sleep → windows → notifications → calendar

Next: Client self-service portal onboarding (basisweb/app/portal/onboarding/ in progress).

Marketplace & Payments

Sub-featureStatusLast ChangedKey FilesKnown Issues
Stripe Payments🟢 Stable2026-03-15 invoice billing proration fixfunctions_payment.py, PaymentTab.tsxACH + card. Invoice billing with billing_cycle_anchor (1st of month). Proration estimate uses clinic timezone (not browser local time). Removed off_session=True conflict with setup_future_usage. 3-column Charge Client modal with dedicated cart column.
Client A/R Ledger & Balances (#710)🟢 Stable2026-08 per-client running balance (accounts-receivable): post charges + settle by card-on-file / hosted invoice / manual (cash·check·Venmo·Zelle); post insurance patient-responsibility to the balance without double-charging a collected copayfunctions_payment.py (post_ledger_charge, add_ledger_charge, settle_ledger, post_remittance_to_balance, list_ledger, void_ledger_entry), PaymentTab.tsx (ClientLedgerSection, "Balance")Ledger at clinicsv2/{clinic}/clinic_users/{uid}/ledger. settle_ledger methods: card_on_file / invoice / manual. Callables gated ClinicPermission.BILLING. Scheduled auto-invoice emails open balances. See docs/features/billing-insurance.md.
ACH / Bank Accounts🟢 Stable2026-03-04PaymentTab.tsx, PaymentModal.tsxBank accounts show with Building2 icon. ACH charges return processing status — staff sees "bank transfer takes 3-5 days" toast. Client portal shows success-like state for processing. PaymentElement auto-shows bank entry once backend enables us_bank_account.
Memberships🟢 Stable2026-03-15clinic_service, Basis Flow Web Marketplace tabview_revenue permission is standalone — not implied by billing
Products🟢 StableBasis Flow Web Marketplace tabservices permission separate from products
Marketplace Catalog Variants🟡 In progress2026-05-06functions_clinic.py (marketplace_*, add_product, update_product), CatalogAdminPanel.tsxPer-variant vendorCost, msrpPrice, platformFeePctOverride (admin), markupPctOverride (admin or clinic). Computed wholesalePrice/suggestedRetailPrice persisted at save time. Field rename variantsvariantGroups (legacy still read for one release). Storefront variant selector (basisweb/basishybrid) and Stripe code-naming for restricted categories pending.
Fullscript🟢 Stablefunctions_fullscript.pyOAuth per-clinic; orders webhook at fullscript_webhook
Referral Rewards (#719)🟢 Stable2026-08-17 clinic toggles referral rewards, picks Fixed amount or % of referred client's first payment; referrer earns a balance credit on conversion, applied to Stripe balance with one buttonfunctions_growth_leads.py (award_referral_on_conversion, _resolve_reward_dollars, _post_referral_credit), functions_growth_crm.py (referral_config, mark_referral_successful), functions_payment.py → apply_ledger_credit_to_stripe, settings/page.tsx (GuestsReferralsTab)Reward posted once (idempotent) to the referrer's ledger. See docs/features/referral-rewards.md.
Book & Pay Later (#656)🟡 Partially live2026-08-17 staff setting + backend shipped; client-app "pay now / pay later" buttons still rolling outfunctions_clinic.py (book_appointment pay-later path: validates allowPayLater, stamps paymentStatus/unpaidAmountCents, posts ledger charge), functions_payment.py → post_ledger_charge (source='booking_pay_later'), model_event.py, settings/page.tsx (allowPayLater toggle, Client Apps → Payments), EventDetailsDrawer.tsx ("Unpaid — $X owed")Pay-later posts the cost to the client ledger; appointment flagged Unpaid. Toggle at preferences/clientApp.allowPayLater. See docs/features/book-pay-later.md.

Next: Twilio SMS add-on (Phase 5 in ROADMAP.md). Basis Hybrid status gating UI (needs app release).

Permissions & Auth

Sub-featureStatusLast ChangedKey FilesKnown Issues
RBAC🟢 Stablefunctions_permissions.py, permissions/{clinic}/users/{uid}ALWAYS test with Admin role, NOT System Admin
Custom Roles🟢 Stableclinicsv2/{clinic}/settings/customRolesEach settings doc needs explicit Firestore rule

Next: Granular per-feature permissions for add-ons (e.g., Twilio SMS access).

Client & Staff Management

Sub-featureStatusLast ChangedKey FilesKnown Issues
Archive/Delete Workflow🟢 Stable2026-03-15ArchiveDeleteModal.tsx, ClientDetailPage.tsx, StaffDetailPage.tsx, functions_clinic.pyHIPAA-compliant archive (10-year retention) + permanent delete for test accounts. Shared modal with step flow (choose action → confirm → result). Archive sets status to archived, cancels Stripe subscriptions, optional data export. Hard delete requires typing "DELETE", recursively removes all subcollections. Staff archive removes from public_clinicians. Replaces window.confirm().
Client Status Gating🟢 Stable2026-03-15functions_clinic.py, BookingDrawer.tsx, ClientDetailPage.tsxBackend blocks inactive/paused/archived booking. Auto-reactivation cron for paused clients. Scheduled deactivation with orange banner. Basis Hybrid: TODO — needs app release to hide booking UI.

Next: Basis Hybrid status gating UI (needs app release).


Growth Suite

Sub-featureStatusLast ChangedKey FilesKnown Issues
Website Builder (V2 — componentized)🟡 Active Dev2026-08-20 rebuilt from raw-HTML generation to componentized sections: the generator emits a structured sections[] (hero/method/services/pricing/team/testimonial/cta) filled from REAL clinic data + AI copy; basis-sites renders them through locked-layout _shared components — AI writes copy + picks images, components own the layout (no spacing/button/placeholder drift). ALL pages componentized. Plus generation metering: first generation free, then generationCredits — gates NEW full generations only (never editing/refining an existing site or anything else about the clinic).functions_growth_website.py (generate_website_v2, _generate_hero, _generate_sections, get_website_credits, grant_website_credits), hybrid/basis-sites/templates/TemplateRenderer.tsx + templates/_shared/* (Hero/Services/Pricing/HowItWorks/Team/Testimonials/CTA), app/preview/[clinicId]/page.tsx, storage clinicsv2/{clinic}/growth_website/main (+ /pages)Componentization + metering built, pending deploy (wt/growth batch). Deploy = functions:generate_website_v2,get_website_credits,grant_website_credits + basis-sites (Netlify). Refinement is still HTML-based → moving to section-edit. Next: GitHub eject/headless — one-way export to a repo that stays data-connected to Basis (services/booking/chatbot live) (#653); Stripe buy-credits + Settings→Billing surface, meter via #536 (#779).

Integrations

IntegrationStatusLast ChangedKey FilesNotes
Terra (Health Data)🟢 Stable2026-07-21 logger landmine clearedfunctions_terra.py, terra_cache_*, terra_data_converter.pyWebhook → DuckDB/GCS → Firestore mirror. 2026-07-21: cleared logger.warninglogger.warn crash-landmine in the cache/converter layer (latent, AI-consumption path via functions_ai_integrated — NOT the sync/webhook pipeline). Recurring sync/webhook crashes (DuckDB-in-serverless) remain a separate structural issue — see docs/claude/services/terra.md.
Zoom🟢 Stablefunctions_zoom.py, clinicsv2/{clinic}/config/zoomPer-clinic OAuth
Google Meet🟢 Stablefunctions_google_meet.py, clinicsv2/{clinic}/config/googlePer-clinic OAuth + Calendar API
Junction Health (Labs)🟢 Stablefunctions_junction.pyOrders at clinicsv2/{clinic}/lab_orders
MailerSend🟢 Stable2026-03 delivery webhook trackingfunctions_appointment_emails.py, functions_email_webhooks.pyBranded domains: verify DNS, set useBranded: true. Webhook tracks delivered/bounced/spam.
OpenAI / Vertex🟢 Stablefunctions_ai.py, functions-vertex/For inference only — no training on patient data
Slack Bot🟢 Stable2026-03 support botfunctions_slack_bot.pySupport bot for provider queries. Per-clinic Slack workspace integration.
Outbound Webhooks🟢 Stable2026-03functions_webhooks.pyFires events (note.created, lab.created, appointment.created/cancelled, client.created, error.logged) to configured endpoints. Config: clinicsv2/{clinic}/settings/webhooks.
DoseSpot (e-prescribing)🟢 Stable2026-03-13 address dict fixfunctions_dosespot.py, components/dosespot/DoseSpotEmbedModal.tsxFull integration: clinic provisioning, clinician NPI/DEA registration, patient sync, SSO iframe embed, Rx pull-back, allergy management, pharmacy search (Surescripts). 12 Cloud Functions. Gap: Prescriptions not shown in Plan tab (only synced to Firestore). Notification counts not surfaced in UI. See ROADMAP Phase 9.
Atlas REST API🟢 Stable2026-03functions_atlas_api.pyExternal agent access via POST with API key auth (X-API-Key or Bearer). Key generation/validation/usage tracking. Routes to run_claude_agent.
MCP Server🟢 Stable2026-03functions_mcp.pyMCP 2024-11-05 spec. API key auth, permission-based tool/resource access. Supports Claude Desktop, Cursor, etc. 766 lines.
Clinical Extractor🟢 Stable2026-03functions_clinic.py → extract_conditions_goalsScans 5 sources (docs, intake, labs, chats, health data). GPT-4o-mini. Auto-detects abnormal labs. Phase 2: expand to medications, procedures, social/family history.
KB Auto-Learning🟢 Stable2026-03functions_kb_sync.pyFirestore triggers auto-populate kbAuto/kbAutoStaff from clinic data (services, products, memberships, staff). Atlas kb_search() includes auto entries.
PostHog Analytics🟢 Stable2026-03components/PostHogProvider.tsx, lib/posthog.tsHIPAA-safe config: maskAllInputs, no IP capture, identified_only profiles. Both basisflow-web and basisweb.

Next: Twilio integration (Phase 5 in ROADMAP.md). WhatsApp Business API (Phase 3).


Data Patterns (Cross-Cutting)

PatternStatusKey RuleLast Updated
Date-only fields🟢 StableStore as string "YYYY-MM-DD" — NEVER Timestamp2026-01
Pydantic ↔ Firestore🟢 StableUse BeforeValidator for type coercion; Timestamp/string can both appear2026-01-25
camelCase fields🟢 StableAll Firestore fields camelCase — Python models too (no snake_case aliases)
Firestore rules🟢 StableAdd rule BEFORE writing code to new path; each settings/{name} needs own rule
Dual-write (protocols)🟢 Stableclinicsv2/.../protocols is source of truth; users/{uid}/protocols is mirror

Appointment Data Gotchas (Frequently Causes Bugs)

Field✅ Correct❌ Wrong
Location namedata.locationName || data.location?.name || data.location?.textlocationName only
Coach UIDattendees[isOrganiser].profileIdcoachUid (may not exist)
Coach nameLook up clinician doc by UIDattendee.namemay be an email address

Bug Context Protocol

When debugging a feature, follow this order:

  1. Find the feature row above — check Known Issues first
  2. Read the Key Files — understand current implementation before changing
  3. Check Known Gotchas in CLAUDE.md → Known Gotchas & Danger Zones
  4. Use debug tools in basis-functions/tools/ before declaring fixed
  5. Update this file when done — change status and last changed


Changelog

DateChanges
2026-03-04Added: ACH bank account payments (backend + PaymentTab + PaymentModal). Scheduled deactivation + auto-reactivation cron. Copilot complex query bypass. AI Scribe, save_clinical_note tool, Slack bot, outbound webhooks, email delivery tracking, activity log — reflected from recent commits. Versioning table. Next-phase notes per feature section.
2026-03-06Added: DoseSpot e-prescribing, Atlas REST API, MCP Server, Clinical Extractor, KB Auto-Learning, PostHog Analytics, CI/CD Pipeline, Health Check. Updated AI Scribe status (telehealth stable, in-person ambient pending). Updated Atlas API/MCP entries with current file locations.
2026-03-08Added: Clinical Audit Trail (functions_clinical_audit.py), Superbill Auto-Generation (functions_superbill.py), Provider Utilization table in analytics dashboard. Fixed nightly orchestrator to use AGENT_PAT. Added clinic_id to log_bug endpoint. ROADMAP: Added Phase 6 (Clinical Forms Scheduling) and Phase 7 (Atlas AI Custom Reports).
2026-03-15Added: Archive/Delete workflow (ArchiveDeleteModal, HIPAA 10-year retention, recursive subcollection delete). Stripe invoice billing proration timezone fix (clinic TZ, removed off_session conflict, 3-column cart modal). Multi-location coach availability (checkbox selection, deduplication). Moved Client Status Gating to Client & Staff Management section. Memberships → Stable.
2026-08-17Added weekend ship batch: Plan of Care / Service Visits (#673), Chat Blast (#691), Guest Invite Email (#485), Link appointment to a program (#257), Referral Rewards (#719), Book & Pay Later (#656, partially live), Open-Gym / QR Check-In (#721). Each has a docs/features/*.md how-it-works page and a docs/claude/growth-content-backlog.md row (🆕 unannounced).

Maintained by agents and humans. Update after every feature change.