# Meduvo Health — Phase-Wise Build Prompts

**How to use this document:** Run each prompt in its own Claude session/conversation, in order. Paste the "Shared Context" block at the top of every prompt (or upload this whole file) so Claude has consistent domain rules even though each session starts fresh. Do not run all phases in one prompt — each is scoped to be buildable and reviewable on its own.

---

## SHARED CONTEXT (paste into every phase prompt)

```
You are an expert Senior Full-Stack Architect and HealthTech Engineer working on
"Meduvo Health," a multi-tenant Collaborative Care Model (CoCM) platform.

SYSTEM OVERVIEW:
- Backend/Admin: Laravel 12, MySQL (InnoDB), multi-tenant (tenant_id scoping on all
  clinic-owned tables, enforced via a global Eloquent scope + middleware — not
  separate databases per tenant).
- Auth: Laravel Sanctum (token-based, SPA + mobile clients). Do not use Passport
  unless a task explicitly calls for a third-party OAuth2 authorization server.
- Provider App: Flutter (mobile/tablet), Riverpod for state management.
- Patient App: Flutter (mobile), Riverpod for state management.
- Transport: REST (versioned, /api/v1/...) for CRUD; Laravel Reverb (WebSockets)
  only for: (a) BHCM registry live updates, (b) push-style in-app notifications,
  (c) call-invite signaling. Video/audio media itself goes over Daily.co (has a
  standard BAA available) or Agora (confirm current BAA/HIPAA posture before
  committing) — not over Reverb.

DOMAIN RULES (do not violate):
- Triad workflow: PCP leads care; BHCM coordinates care and owns metrics tracking;
  Psychiatric Consultant is a data-driven advisor to the BHCM/PCP only — never
  build any feature giving the psychiatric consultant direct patient messaging,
  calls, or patient-visible actions.
- Time tracking must be granular, per-activity, immutable once submitted (corrections
  create a new adjustment record referencing the original, never an in-place edit).
- Billing code logic must be DATA-DRIVEN, not hardcoded. CPT/HCPCS thresholds
  (99492, 99493, 99494, G2214) change over time and vary by payer/FQHC status.
  Store them in a versioned `billing_rule_sets` table with an `effective_date` and
  `payer_type`, and have the engine look up the active rule set rather than
  branching on hardcoded minute values. Treat the exact numeric thresholds as
  PLACEHOLDER/CONFIGURABLE data to be confirmed by a compliance/coding reviewer —
  flag this clearly wherever the seed data is created.
- All PHI-bearing tables need audit logging: who read/wrote what, when. Audit log
  table is append-only (no UPDATE/DELETE grants at the DB user level for that table).

NON-FUNCTIONAL REQUIREMENTS:
- Encrypt PHI columns at rest where feasible (Laravel's encrypted casts) in addition
  to full-disk/DB encryption; TLS everywhere in transit.
- Every endpoint enforces RBAC (SuperAdmin, ClinicAdmin, PCP, BHCM, Psychiatrist,
  Patient) AND tenant scoping — a request must never be able to read another
  clinic's data even with a valid token for a different tenant.
- Provide PHPUnit feature tests for RBAC/tenant-isolation and for the billing rule
  engine specifically — these are the two highest-liability areas in the system.
- No placeholder/mock logic — all code must run against real migrations.
```

---

## PHASE 1 — Backend Schema, Auth, and Core API (split into 1A/1B/1C)

Run these three as separate prompts, in order, within the same backend project.

### Phase 1A — Schema & Multi-Tenancy Foundation

```
[Paste SHARED CONTEXT above]

TASK: Design and generate Laravel 12 migrations, models, and factories for the
following, with full foreign keys, indices, and enum/lookup constraints:

1. `tenants` (clinics) and a `tenant_id` scoping strategy — implement as a global
   Eloquent scope (`BelongsToTenant` trait) applied to every tenant-owned model,
   plus middleware that resolves the active tenant from the authenticated user.
2. `users` — include role (enum: super_admin, clinic_admin, pcp, bhcm,
   psychiatrist, patient), tenant_id (nullable for super_admin), status
   (active/invited/suspended), and standard Sanctum fields.
3. `patient_profiles` — linked to exactly one PCP and exactly one assigned BHCM
   (foreign keys to users, role-constrained via application-level validation,
   not just FK), plus demographic fields, enrollment_date, and diagnosis codes.
4. `time_tracking_logs` — started_at, ended_at, duration_minutes (generated/
   stored, not trusted from client), activity_type (enum: direct_call,
   indirect_charting, psychiatric_caseload_review, registry_review, other),
   patient_id, provider_id, tenant_id, submitted_at, and a nullable
   `superseded_by_id` self-reference for corrections (never edit/delete a
   submitted log row).
5. `care_goals` — tenant_id, patient_profile_id, created_by_user_id (must be a
   BHCM per the Triad rule), goal statement + action steps (encrypted columns),
   target_date, achieved_at (nullable). This is the table Phase 4's Care Portal
   reads from — build it here, not as an afterthought later.
6. `audit_logs` — id, tenant_id, user_id (nullable for system-initiated actions),
   action (create/read/update/delete/export), auditable_type, auditable_id,
   old_values (json, encrypted), new_values (json, encrypted), ip_address,
   user_agent, created_at. Append-only: revoke UPDATE/DELETE grants on this
   table at the DB-user level, not just at the application layer.
7. `care_encounters` (or similar) — a lightweight session/encounter record that
   `time_tracking_logs` can optionally reference, so an auditor can trace a
   specific logged block of time back to the clinical note or assessment
   review that justified it, rather than a bare provider+patient+timestamp.
8. `billing_rule_sets` and `billing_rule_codes` — versioned lookup tables holding
   CPT/HCPCS code, min_minutes, max_minutes (nullable), payer_type,
   effective_start, effective_end. Seed with clearly-labeled PLACEHOLDER values
   and a code comment stating these must be confirmed against current CMS/payer
   guidance before production use.
9. `billing_periods` — one row per patient per calendar month, aggregating total
   minutes and the resolved billing code(s) for that period (computed, cached,
   recomputable).
10. `psychiatric_recommendations` — psychiatrist → BHCM/PCP one-way records with
   a status (pending/approved/dismissed) for the Phase 3 approval queue. Include
   a DB constraint or observer that rejects any attempt to link a recommendation
   directly to a patient-facing thread.

Do NOT touch or recreate psychometric assessment tables — assume
`assessment_templates`, `assessment_questions`, `assessment_options`, and
`patient_assessment_responses` already exist and are populated; only reference
them via foreign key where relevant (e.g., linking a time log to an assessment
review).

Also implement the tenant scope as a base trait hooking Eloquent's `creating`
event so `tenant_id` is set automatically from the authenticated user, rather
than requiring every controller to set it manually (a common source of tenant-
isolation bugs). Note in the README that relying on a single global `APP_KEY`
for all encrypted-cast columns is a real risk in a multi-tenant system — flag
key rotation / a per-tenant or envelope-encryption strategy as a follow-up
decision rather than solving it in this phase.

Deliverables: migration files, Eloquent models with relationships and the
tenant scope trait, model factories, and a short README section explaining the
tenant-isolation approach, the correction/versioning pattern for time logs, and
the encryption-key-management caveat above.
```

### Phase 1B — Auth, RBAC, and API Skeleton

```
[Paste SHARED CONTEXT above]

TASK: Assuming the Phase 1A schema exists, implement:

1. Sanctum-based auth: registration (invite-only for clinical roles — patients
   and providers are provisioned by ClinicAdmin, not self-registered), login,
   token issuance/revocation, and password reset. Back invites with an
   `invitations` table (email, role, tenant_id, token_hash, expires_at,
   accepted_at) rather than a bare emailed link with no expiry. Configure
   Sanctum token lifetimes to expire after a period of inactivity (HIPAA's
   automatic-logoff expectation) rather than living forever, and write an
   audit_logs row whenever an admin explicitly revokes a staff member's token.
2. RBAC middleware/gates: a `role:` middleware and Policy classes for each
   model (PatientProfile, TimeTrackingLog, PsychiatricRecommendation, etc.)
   enforcing both role AND tenant scope AND the Triad rule (e.g., a
   Psychiatrist policy should never authorize a "message patient" or
   "view patient contact info" ability).
3. A versioned API route file (`routes/api_v1.php`) with resource controllers
   for users, patient_profiles, and time_tracking_logs — CRUD plus the
   correction/adjustment endpoint for time logs (never a raw update endpoint).
4. Feature tests proving: (a) a user from tenant A cannot read/write tenant B's
   data even with a valid token, (b) a psychiatrist role is rejected from any
   patient-communication endpoint, (c) time log corrections create a new row
   rather than mutating the original.

Deliverables: controllers, policies, middleware, route file, and the feature
test suite described above.
```

### Phase 1C — CMS Billing Rule Engine

```
[Paste SHARED CONTEXT above]

TASK: Build the billing rule engine as a standalone, testable service class
(`App\Services\Billing\CocmRuleEngine`), NOT inline controller logic.

Requirements:
1. Given a patient_id and a calendar month, aggregate `time_tracking_logs`
   into total minutes for that period. Store each tenant's operational
   timezone on the `tenants` table and resolve "calendar month" boundaries in
   that local timezone, not UTC — a log written at 11:45pm local time on the
   last day of the month must not silently roll into the next billing period
   just because it's stored as a UTC timestamp.
2. At write time, reject a new `time_tracking_logs` row whose [started_at,
   ended_at) window overlaps another active window for the same provider
   (a provider cannot be simultaneously billing two overlapping sessions,
   even for different patients) — enforce this with a validation check backed
   by a DB-level exclusion constraint or unique-range index, not application
   logic alone.
3. Wrap the aggregation-and-write step in a `lockForUpdate()` transaction so a
   concurrent new time log and a recompute job can't race and corrupt the
   aggregated total.
4. Look up the ACTIVE `billing_rule_sets` row for the relevant payer_type and
   effective_date range (do not hardcode thresholds in the engine — pull them
   from the DB so they can be updated without a code deploy).
5. Resolve which code(s) apply (base code + any add-on units) and persist the
   result onto `billing_periods`, including a breakdown of which rule row
   justified the decision (for audit purposes).
6. Provide a recompute endpoint/command that can be re-run if historical time
   logs change (corrections) or if a rule set is retroactively updated —
   recomputation must never overwrite a billing_period that has already been
   marked "submitted to payer" without an explicit override flag.
7. Unit tests covering: exact threshold boundaries, multiple add-on units,
   the shortened-month/grace-code path, a rule-set version change mid-month
   (should use the rule set effective at time of care, not at recompute time),
   the timezone-boundary edge case above, and rejection of an overlapping
   time-log window.

Explicitly flag in comments: the numeric thresholds in the seeded
`billing_rule_sets` data are placeholders pending sign-off from a medical
billing/coding compliance reviewer — do not treat them as production-ready.

Deliverables: service class, supporting DTOs/value objects, artisan command
for recompute, and PHPUnit test suite.
```

---

## PHASE 2 — Admin Web Portal

```
[Paste SHARED CONTEXT above]

TASK: Build a desktop-optimized admin portal (Laravel Blade + Tailwind, or
Next.js consuming the Phase 1 API — pick Blade/Tailwind unless you tell me
otherwise, since it avoids a second auth integration).

Modules:
1. Clinic & Provider Onboarding — ClinicAdmin can invite users by role, and
   explicitly assign each patient's PCP + BHCM pairing (enforce one-PCP/
   one-BHCM-per-patient at the UI level, backed by the Phase 1A constraint).
2. Traffic-Light Billing Dashboard — per-patient current-month minute totals
   with status derived from the Phase 1C engine's output, not re-implemented
   in the frontend:
   - Green: base code threshold met
   - Amber: within a configurable "approaching threshold" band (make the band
     width itself configurable per rule set, not a hardcoded number)
   - Red: unbillable with days-remaining-in-month countdown
   Include a drill-down showing the exact log entries contributing to the
   total, for audit defensibility.
3. Immutable Audit Trail — a read-only, filterable, exportable (CSV) view over
   the audit log table, with filters by provider, patient, date range, and
   action type. No delete/edit UI anywhere in this module. Wrap the CSV export
   action itself so it writes an `audit_logs` "export" row before streaming
   the file — exporting PHI to a local file is itself an event worth auditing.
4. Billing Rule Settings — a UI for a billing admin to view/adjust the
   "approaching threshold" band width and other configurable parameters from
   the Phase 1C rule engine, rather than leaving those as DB-only values only
   an engineer can change. Changes here should themselves be audit-logged and
   should never edit an already-effective rule set in place — create a new
   dated rule set instead, consistent with the versioning approach in 1C.

Also specify: what does a ClinicAdmin see vs. a SuperAdmin (cross-tenant view)?
Build the SuperAdmin cross-tenant dashboard as a separate, clearly-gated view,
with a persistent visual indicator (e.g., a banner) whenever a SuperAdmin is
viewing/acting inside a specific clinic's workspace, to reduce the risk of an
accidental cross-tenant write while impersonating a tenant context.

Deliverables: routes, controllers, Blade views/Tailwind components, and a
short access-matrix table (role × module × permission) in the README.
```

---

## PHASE 3 — Flutter Provider App

```
[Paste SHARED CONTEXT above]

TASK: Build the multi-role Flutter Provider app (Riverpod), consuming the
Phase 1 API + Reverb WebSockets. The UI must adapt based on the logged-in
user's role (PCP / BHCM / Psychiatrist) rather than being three separate apps.

Features:
1. BHCM Registry Dashboard — caseload sorted by risk stratification. Risk
   score = a function of (a) latest PHQ-9/GAD-7 delta (from the Phase-2-of-the-
   assessment-integration work — assume an existing `/api/v1/assessments/delta`
   endpoint returns {assessment_type, previous_score, current_score, delta,
   direction, days_since_last}), and (b) missing-milestone flags (e.g., no
   assessment logged in 30+ days). Make the weighting between these two
   factors configurable, not hardcoded, since clinics may want to tune it.
2. Background Session Timer — starts when a provider opens a patient chart,
   pauses/stops on a 2-minute idle timeout (define idle precisely: no touch/
   scroll/keyboard event, not just app backgrounding), and writes a
   time_tracking_logs entry via the correction-safe endpoint on stop.
   - Do not rely on a live counter surviving app suspension. Instead, record
     a system timestamp at session start, listen for `AppLifecycleState`
     transitions, and compute elapsed time from the absolute clock delta when
     the app returns to foreground — this is the only approach that survives
     iOS suspending a backgrounded isolate.
   - Use a proper Android foreground service (with its required persistent
     notification) if you want the timer visibly "alive" while the device is
     locked; document iOS's stricter background-execution limits rather than
     assuming parity between platforms.
   - If the device loses connectivity before the completed log can be
     submitted, persist the pending entry in encrypted local storage (e.g.
     Hive with AES-256, or SQLCipher) and sync it once connectivity returns —
     do not hold unsynced time logs in plain, unencrypted local storage, since
     they contain patient identifiers.
3. PCP Approval Queue — list of pending `psychiatric_recommendations`, one-tap
   approve/dismiss, with the action written back via API and reflected via
   Reverb to the BHCM's view without a manual refresh. Since the same
   recommendation could in principle be actioned from two devices, make the
   approve/dismiss endpoint idempotent (a second action on an already-resolved
   recommendation should no-op with a clear response, not error or double-apply).
4. Telehealth Workspace — integrate [Daily.co or Agora — confirm which vendor
   contract exists before implementation] for the BHCM-led call, with a
   "warm handoff" action that adds the PCP into an in-progress call. Signaling
   (who's being invited, call state) goes over Reverb; media over the vendor SDK.

Deliverables: Flutter project structure, Riverpod providers/notifiers per
feature, API client layer, and a note on which platform-specific background-
timer approach you used and its known limitations.
```

---

## PHASE 4 — Flutter Patient App

```
[Paste SHARED CONTEXT above]

TASK: Build the Flutter Patient app (Riverpod), consuming the Phase 1 API.

Features:
1. Screening Forms — render PHQ-9/GAD-7 (and any other templates) dynamically
   from the existing assessment-template API (assume
   GET /api/v1/assessments/templates/{type} returns questions, options, and
   point weights — do not hardcode question text/scoring in the Flutter app).
   Push a local/native notification when a new assessment is due.
2. Telehealth Client — single-tap join for an incoming call room, triggered by
   a Reverb event from the Provider app; no ability to initiate a call to the
   psychiatrist (enforce this in the UI as a defense-in-depth measure on top
   of the backend Triad rule).
3. Care Portal — current goals (read from the `care_goals` table added in
   Phase 1A) and a secure text channel to the assigned BHCM only (never to
   PCP-only or psychiatrist accounts — validate the recipient role client-side
   and rely on the backend policy as the real enforcement). Use REST polling
   as the reliable-delivery path for messages, with Reverb layered on top for
   real-time UI updates when the connection is live — don't build a custom
   real-time protocol from scratch.

Any local cache of goals or messages (for offline viewing) must use an
encrypted storage layer keyed off the device's hardware keychain (iOS
Keychain / Android Keystore), not plaintext local storage, since this data
can include PHI.

Note: this spec does not currently include an e-consent/enrollment-
authorization capture flow. If the clinic's onboarding process requires
patients to formally consent to CoCM enrollment (common in practice), that's
a new feature to scope deliberately — likely a signature-capture or
checkbox-plus-timestamp screen tied to a `consents` table — rather than
something to assume is already covered here.

Deliverables: Flutter project structure, Riverpod providers, dynamic form
renderer widget (reusable across assessment types), and the chat UI wired to
the REST-plus-Reverb transport described above.
```

---

## Notes on sequencing

- Confirm the real CPT/HCPCS thresholds with a compliance/coding reviewer **before** Phase 1C's seed data goes anywhere near production — treat every numeric value in this document as provisional.
- Phase 3 depends on an assessment-delta endpoint that isn't in Phase 1 above; add it as a Phase 1D if you haven't built it elsewhere yet.
- Confirm the video vendor (Daily.co vs. Agora) and its BAA status before Phase 3, since it affects the SDK integration code.
- Decide deliberately whether an e-consent/enrollment-authorization flow is in scope — it isn't currently specced anywhere above, and it's easy to assume it's "someone else's phase" if you're not careful.
- Before Phase 1B, pin down the exact idle-timeout duration for token expiry — this document deliberately doesn't hardcode a number; make that call with whoever owns your HIPAA security-rule compliance sign-off.
