Documentation Index
Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
Use this file to discover all available pages before exploring further.
For: Organization administrators and billing staff
Last Updated: 2026-02-23
Permission Required: pm.portal.manage
Overview
The PM-12 Patient Portal provides patient self-service capabilities. This guide covers configuration, proxy management, and troubleshooting.
Portal Architecture
Authentication Flow
- Patient registers with email matching their
pm_patients record
- Supabase Auth creates identity;
pf_profiles.portal_patient_id links to patient
- Login creates an audit row in
pm_portal_sessions (append-only)
- Account lockout triggers after 5 consecutive failed attempts
Data Isolation
- RLS:
pm_portal_has_org_access() and pm_portal_visible_patient_ids() (SECURITY DEFINER)
- Application:
usePortalPatientId() hook scopes all portal queries
- Double enforcement: Both layers must pass for data access
Proxy Authorization
Granting Proxy Access
Staff with pm.portal.manage permission can authorize proxy access:
- Navigate to the patient’s record in PM
- Add a proxy entry in
pm_portal_users with:
proxy_for_patient_id: The patient being represented
proxy_relationship: parent, legal_guardian, healthcare_decision_maker, or other
proxy_expires_at: Expiration date (required)
Revoking Proxy Access
Set proxy_expires_at to a past date or update status to inactive. The proxy user will immediately lose access to the linked patient’s data.
Proxy Rules
- Proxy access is always time-limited
- Expired proxies return no data (enforced at RLS and application layers)
- A user can be a proxy for multiple patients
- Proxy audit trail is maintained in
pm_portal_sessions
Session Management
Audit Trail
All portal sessions are recorded in pm_portal_sessions:
portal_user_id, ip_address, user_agent, created_at
- Sessions are append-only — no UPDATE or DELETE allowed
revoked_at is set on sign-out
Account Lockout
- After 5 failed login attempts,
pm_portal_users.status is set to locked
- Staff can unlock by updating the status back to
active
- Lockout does not affect the Supabase Auth account itself
Security Configuration
MFA
- Patients can self-enroll in TOTP MFA via the portal Security page
pm_portal_users.mfa_enabled flag tracks enrollment status
- Supabase Auth handles TOTP factor management natively
- Backup codes are displayed once during enrollment
Rate Limiting
- Portal login attempts are tracked per-user
- No IP-based rate limiting at the application layer (rely on Supabase Auth and infrastructure-level protections)
Feature Integration Summary
| Feature | Source Spec | Portal Capability |
|---|
| Appointments | PM-03 | View upcoming/past, cancel |
| Health Records | CL-* | View chart, medications, goals (consent-gated) |
| Forms | PF-08 | Complete intake/consent forms |
| Demographics | PM-01 | View info, submit update requests |
| Billing | PM-09 | View balance, payment history |
| Messages | PM-14 | Secure messaging with care team |
SUD Consent & Clinical Records (CL-11)
When a patient’s chart has SUD (Substance Use Disorder) indicated:
- The portal checks for active Part 2 consent via
cl_check_sud_consent RPC
- Without consent, SUD-related data (e.g., risk level) is suppressed from the portal view
- Non-SUD clinical data (medications, treatment goals) remains accessible per the 21st Century Cures Act
- A consent restriction banner is shown to the patient
- This is enforced at both the RLS layer (database) and the application layer (
useConsentCheck)
Troubleshooting
| Issue | Resolution |
|---|
| Patient can’t register | Verify email matches pm_patients record |
| Portal shows no data | Check pf_profiles.portal_patient_id is set |
| Proxy sees wrong patient | Verify pm_portal_users.proxy_for_patient_id and expiration |
| Account locked | Update pm_portal_users.status to active |
| MFA lost | Patient must contact admin; unenroll factor via Supabase Auth dashboard |
| Session audit missing | Check pm_portal_sessions — rows are append-only |
Database Tables
| Table | Purpose | RLS |
|---|
pm_portal_users | Portal user metadata, proxy config | FORCE RLS |
pm_portal_sessions | Append-only session audit | FORCE RLS (no UPDATE/DELETE) |
pf_profiles.portal_patient_id | Links auth user to patient record | Existing PF RLS |
Permissions
| Permission | Description | Default Roles |
|---|
pm.portal.view | View portal configuration and proxy list | org_admin |
pm.portal.manage | Manage proxy authorization and settings | org_admin |