This page is synced from/constitution.mdat the repository root. Edit the source file — this published copy is regenerated bynpm run docs:sync-canonical. See the governance index for related documents.
Encore OS Platform – Engineering & Product Constitution
Version: 1.18.0Last Updated: 2026-06-15 This constitution defines the non‑negotiable guardrails for designing, building, and operating the Encore OS platform and its modules. It applies to everyone: engineers, product, data, and any AI assistants. When documents conflict, this constitution wins. Full document hierarchy:
constitution.md → AI_GUIDE.md → AGENTS.md → .cursor/rules/
Table of Contents
- §1 Architecture & Module Boundaries
- §2 Specification-First Delivery
- §3 Testing & Quality Discipline
- §4 Data, Security & Privacy
- §5 Database, Naming & Environment Guardrails
- §5.1 Multi-Tenant Data Model
- §5.2 Database Naming Conventions
- §5.3 Migrations & Change Management
- §5.4 Environment Separation
- §5.5 Production Deployment & Rollback
- §5.6 Performance & Monitoring Standards
- §5.7 RLS Anti-Patterns & Security Definer Functions
- §5.8 Edge Function Patterns
- §5.9 Scheduled Task Pattern
- §5.10 Bulk Import & Data Migration Standards
- §6 PWA & Mobile-First Requirements
- §7 Finance & Clinical Guardrails
- §8 Simplicity, Pragmatism & Decisions
- §9 Documentation & Ownership
- §10 Governance, Versions & AI Alignment
- §11 Project Structure & Code-Level Naming
- §12 Automation Governance
- §13 Definition of Done
1. Architecture & Module Boundaries
The platform is structured as a Platform Foundation plus domain cores. Boundaries are hard rules, not suggestions.1.1 Platform & Cores
-
Platform Foundation (PF)
Identity, tenancy, access control, navigation, audit, shared UX, cross‑cutting services, PWA infrastructure, jurisdiction/compliance configuration (PF-96), and integration glue. PF owns the jurisdiction profile system that provides state-specific Medicaid compliance rules as structured, versioned configuration data consumed by CL and PM. -
Domain Cores
- RH – Recovery Housing & Operations
- FA – Finance & Revenue
- HR – Workforce & HRIS
- GR – Governance, Compliance & Learning
- FW – Forms & Workflow
- FM – Facilities, Inventory & Vendors
- LO – Leadership Operating System
- CE – Community Engagement
- IT – IT & Security
- CL – Clinical & EHR (never a base dependency)
- PM – Practice Management (healthcare revenue cycle; distinct from FA general accounting)
1.2 Rules
- All code, tables, APIs, and UI features MUST declare an owning core/module (e.g.,
RH-01,FA-01). - Platform Foundation is the only shared base layer. Cores may depend on PF, but not on each other, except via explicit, documented integration contracts.
- CL (Clinical) is architecturally downstream:
- No other core may depend on CL.
- No “hidden clinical” logic in RH/FA/HR.
- PM (Practice Management) and CL (Clinical) are tightly integrated operationally but architecturally independent:
- Both depend only on PF, never on each other.
- Integration via Platform Integration Layer (
@/platform/clinical,@/platform/scheduling), events, and shared type definitions in PF. - The encounter (
pm_encounters, owned by PM) is the canonical entity linking scheduling, clinical documentation, and billing. CL reads encounter context via@/platform/scheduling. - PM handles healthcare revenue cycle (claims, eligibility, ERA); FA handles general accounting (GL, AP, AR).
- Encounter-to-billing pipeline: CL note finalization triggers PM charge capture via events.
- Cross-core database references:
- By default, cross-core table references use UUID columns validated at the application layer (no database FK constraints).
- Exception (CL-PM only): The encounter entity (
pm_encounters) is the canonical joint between clinical documentation and revenue cycle. CL tables MAY referencepm_encounters.idvia a database FK withON DELETE RESTRICTto preserve referential integrity. This exception is scoped to the encounter entity and documented in ADR-002. No other cross-core FK is permitted without an ADR.
- Cross‑core integrations MUST be:
- Defined as explicit contracts (events, APIs, or data feeds).
- Documented in architecture diagrams and specs.
1.3 Integration Patterns
When one core needs to interact with another (e.g., RH needing forms from FW), the integration MUST follow these patterns:Integration Pattern Decision Tree
docs/architecture/integrations/index.md for complete integration documentation.
Pattern 1: Platform Integration Layer
- For cross-cutting capabilities used by multiple cores (like Forms & Workflow), create an integration layer within Platform Foundation.
- Example:
/src/platform/forms/provides simple hooks and components that wrap FW functionality. - Other cores interact with this integration layer, NOT directly with
/src/cores/fw/.
- Cores publish domain events (e.g., “resident admitted”, “form submitted”).
- Subscribing cores listen and react without direct coupling.
- Events MUST be documented in a central registry.
- For workflow triggers based on domain events, cores register events in
fw_workflow_eventstable. - Event registry stores: event_name, display_name, description, owning_core, category, payload_schema.
- Workflow designers browse available events by core (HR, RH, FA, etc.) in the trigger configuration UI.
- Cores publish events via Platform Integration Layer:
import { publishEvent } from '@/platform/events'; - FW Automation Engine subscribes to events and triggers matching workflows.
- Constitutional compliance: Events remain within Pattern 2 (event-based integration).
- For automated processing triggered by database changes (INSERT, UPDATE, DELETE).
- Database trigger calls
pg_netto invoke edge function asynchronously. - Edge function performs complex processing (AI, external API calls, multi-step workflows).
- Constitutional compliance: Async processing without blocking database transactions.
- Well-defined, versioned APIs with clear request/response schemas.
- Documented in OpenAPI specs or equivalent.
- Breaking changes require version bumps and migration paths.
- Use Platform Integration Layer for shared utilities that multiple cores need (forms, notifications, file uploads).
- Use Event-Based for asynchronous workflows and loose coupling.
- Use API Contracts for synchronous, request-response interactions.
- Form Submission → Entity Creation: FW
map_to_entityaction usesprocess-entity-mappingEdge Function to create/update records in FA, HR, RH tables from form submissions. Configuration maps form fields to entity columns +custom_fieldsJSONB. - Picklist Integration: FW Form Builder can use PF-15 picklists as data source for select fields, managed centrally in Platform Settings.
- Direct imports from one core into another (e.g.,
import { something } from '@/cores/fa/...'inside RH code). - Shared database tables between cores without explicit ownership.
- Any exception to the above integration patterns MUST be documented as an ADR in
docs/architecture/decisions/. - ADR format: Use
specs/_templates/ADR_TEMPLATE.md. - ADRs are permanent records; they may be superseded but never deleted.
1.4 Form Ownership Pattern
The platform’s Forms & Workflow (FW) core provides form infrastructure used across all domain cores. To maintain clear ownership and enable module-specific views: Database:- All forms MUST have an
owning_corecolumn (typecore_codeenum) - Values:
'pf','rh','fa','hr','gr','fw','fm','ce','cl','pm' - Default:
'pf'(Platform Foundation / shared forms)
- Each core SHOULD have a dedicated forms page at
/{core}/forms - Example:
/hr/formsshows only forms whereowning_core = 'hr' - Platform admins can access all forms via
/fw/forms
- Forms created within a core’s context default to that core’s
owning_core - Example: Creating a form from
/hr/forms/newdefaults toowning_core = 'hr'
useFormListacceptsowningCorefilterFormSelectoracceptsowningCorepropModuleFormsPageprovides reusable filtered list
2. Specification‑First Delivery
No meaningful feature is built without a written specification.2.1 Requirements
Every feature with non‑trivial impact MUST have a spec that:- Uses the spec template:
specs/_templates/SPEC_TEMPLATE.md(see Section 2.3) - Names the core and module (e.g.,
RH-01: Census & Beds). - Articulates:
- Business context and problem statement.
- In‑scope / out‑of‑scope.
- User stories and acceptance criteria.
- Functional and non‑functional requirements.
- Performance requirements (p50, p95, p99 targets).
- Security considerations (PHI/PII, RLS, permissions).
- Testing strategy (unit, integration, RLS, E2E).
- Rollback strategy (for breaking changes).
- Known limitations (deferred features, technical debt).
- Defines:
- Data model changes (entities, relationships).
- Integration points and dependencies (documented in
/docs/architecture/integrations/). - Success metrics (how we know it worked).
2.2 Process
- Spec → Implementation Plan → Tasks → Delivery → Completion Report.
- Any deviation from architecture or this constitution MUST be called out in the spec with rationale.
2.3 Spec Template
All new specifications MUST use the template atspecs/_templates/SPEC_TEMPLATE.md, which includes:
- Required Sections: Business Context, Objectives, Scope, User Stories, Functional Requirements, Data Model, Integration Points, Performance Requirements, Security Considerations, Testing Strategy, Rollback Strategy, Known Limitations, Success Metrics, Implementation Plan.
- Integration Documentation: All cross-core integrations must be documented in
/docs/architecture/integrations/with event schemas or API contracts. Seedocs/architecture/integrations/index.mdfor overview. - Constitutional Compliance: Each spec includes a checklist ensuring compliance with architecture, database, security, testing, and documentation requirements.
- Implementation Plans: For complex features requiring multi-phase implementation, data migrations, breaking changes, or cross-module coordination, create a separate implementation plan using
specs/_templates/PLAN_TEMPLATE.md. The spec template includes guidance on when a separate plan is needed.
3. Testing & Quality Discipline
Testing is a first‑class deliverable, not an afterthought.3.1 Principles
- Every business rule MUST be covered by automated tests.
- Critical flows (auth, tenancy, billing, clinical, data movement) MUST have integration or end‑to‑end coverage.
- No feature is “done” if tests are missing or flaky.
- “Done” means reachable capability, not artifact‑existence. A spec is not complete because its files, tasks, or acceptance criteria exist on disk — it is complete when the terminal user action actually works. Dogfood it: stand the stack up and exercise the real path before claiming completion.
- A skipped test is unproven, not passing. Treat green‑by‑skip (tests that
skipIfa missing stack/seed/capability) as zero coverage for that claim, never as a pass. Prefer an honest failing result over a misleadingly green artifact, and state which path you actually ran.
3.2 Expectations
- Unit tests: Core logic, utilities, hooks, isolated components.
- Integration tests: Cross‑component flows, API contracts, RLS behavior, key DB workflows.
- E2E tests: Priority journeys (e.g., admit resident → assign bed → bill → reconcile).
- New modules: ~80%+ coverage for core logic.
- Platform and cross‑cutting utilities: ~80%+.
- Overall baseline: a sustainable bar agreed by engineering leadership.
3.3 Test File Naming Conventions
Consistent test file naming enables automatic discovery and clear organization. File Naming Standards:
Directory Structure:
3.4 Public API Documentation Coverage
Public function-like exports are part of product quality and maintainability and MUST be documented.- In-scope exported declarations (function declarations, classes, and function-valued exported constants) MUST include TSDoc/JSDoc comments.
- Changed-file no-regression MUST be enforced before merge using
npm run docs:comments:audit:changed. - Repository baseline coverage for in-scope declarations MUST be maintained at 100% unless an approved exception is documented in a spec/errata with owner and expiry.
- Documentation comments MUST be meaningful (describe behavior and intent), not placeholder boilerplate.
Test Templates: Use templates from
specs/_templates/tests/ for consistent structure:
RLS_TEST_TEMPLATE.ts- Row-Level Security testsUNIT_TEST_TEMPLATE.ts- Unit tests for hooks/utilitiesINTEGRATION_TEST_TEMPLATE.ts- Workflow integration testsE2E_TEST_TEMPLATE.ts- Playwright end-to-end tests
tests/README.md for comprehensive testing documentation.
4. Data, Security & Privacy
We operate as though under full HIPAA and payer audit from day one.4.1 Security
- Principle of least privilege for all users, services, and APIs.
- All configuration secrets (keys, credentials, tokens) MUST be stored in secure environment management (not in code, migrations, or docs).
- No backdoor “superuser” flows without explicit design, audit, and logging.
4.2 PHI / PII Handling
- Use synthetic, de‑identified data in tests and examples.
- Do NOT log free‑text PHI or full identifiers; prefer stable IDs and minimal necessary data.
-
Any export, report, or integration involving PHI MUST:
- Be explicitly scoped in a spec.
- Have a defined retention and access pattern.
-
Regulatory compliance tracking: Clinical and billing regulatory deadlines (e.g. 42 CFR Part 2, USCDI v3, CMS-0057-F, PDMP) MUST be tracked in
docs/compliance/REGULATORY_COMPLIANCE_TRACKER.md. When a deadline is missed or at risk, interim procedures MUST be documented and followed until the responsible spec is implemented.
4.3 AI Integration Security
The platform integrates AI capabilities via the Vercel AI Gateway (PF-111). All AI features MUST follow these security guidelines.4.3.1 Architecture
- AI features MUST use the Platform AI Integration Layer (
@/platform/ai) - All AI calls MUST go through edge functions, NEVER direct client-side calls
- Cores MUST NOT implement their own AI edge functions; use
ai-assistantwith module context - AI responses are stateless; conversation history is managed client-side
4.3.2 PHI Protection (CRITICAL)
- NEVER send PHI/PII to external AI services
- Sanitize all user input before including in AI prompts
- Use anonymized identifiers (e.g., “Resident R-001” not “John Doe”)
- Module context provides audit trail of AI usage per organization
- AI features SHOULD require user consent (settings toggle)
4.3.3 API Key Security
AI_GATEWAY_API_KEYis an Edge Function Secret (PM-15-P2); read it viarequireEnv('AI_GATEWAY_API_KEY')in_shared/ai/vercel-gateway.ts- NEVER expose the API key to client code
4.3.4 Model Selection
- Models are routed per module, not a single global default — see
STANDARD_MODELS/PHI_MODELSinsupabase/functions/_shared/ai/models.ts(each entry is a[primary, fallback]pair). E.g.gr/hr/cl/pm→anthropic/claude-sonnet-4.6;fa→openai/gpt-4o;pf/rh/ce/fw→google/gemini-2.5-flash;lo/fm→google/gemini-2.5-flash-lite. Update routing there, not inline.
4.3.5 Error Handling
- 429 (Rate Limited): Show “Please wait and try again”
- 402 (Payment Required): Show “AI credits depleted” with link to settings
- 500 (Gateway Error): Show “AI temporarily unavailable”
- Network errors: Graceful degradation, non-AI fallback when possible
4.3.6 Integration Pattern
Pattern: Edge Function → Vercel AI Gateway → Response Stream4.3.7 Module Context
All AI requests MUST include module context for audit and specialization:module: Core code (pf,rh,fa,hr,gr,fw,fm,lo,it,ce,cl,pm)feature: Specific feature within modulecontextData: Additional metadata for prompt customizationjurisdictionProfileId: (optional) When the AI feature operates in a jurisdiction-sensitive context (CL, PM, GR), include the organization’s jurisdiction profile ID so AI responses can be tailored to the correct state’s regulations and compliance rules. AI prompts MUST NOT include PHI/PII regardless of jurisdiction context.
4.4 Permissions System Architecture (PF-30)
The platform implements a three-tier permission system for granular access control: Tier 1: Module Permissions (PF-30)- Format:
{module}.{entity}.{action} - Examples:
hr.employees.view,fa.bills.approve,rh.residents.create - Categories:
view,create,edit,delete,approve,admin - Defined in
pf_module_permissionstable (1,600+ permissions; baseline seed + ~19*_permissions_sync_*migrations) - See
docs/pf/module-permissions-matrix.mdfor complete catalog
- Entity-level access with actions (view, create, edit, delete) per role
- Defined per record or record type
- Field visibility rules per role
- Controls which fields users can see/edit
- Organizations can create custom roles with specific permission sets
- Custom roles can optionally inherit from system roles (
staff,readonly,site_admin) - Custom roles CANNOT inherit from
org_adminorplatform_admin(security constraint) - See
pf_custom_rolesandpf_role_permissionstables
- Users assigned via
pf_user_role_assignmentstable - Supports site-scoped assignments (
site_idscolumn) - Supports time-limited access (
expires_atcolumn) - Users can have multiple roles
- V2 is the only active permission system
- All organizations use granular permissions exclusively
- Legacy
pf_user_rolestable is read-only (retained for audit/rollback purposes)
- All UPDATE RLS policies for permission tables MUST include
WITH CHECKclause - Permission checks MUST use
pf_has_permission()SECURITY DEFINER function - Navigation filtering MUST use permission-based access control
- Permission checks are cached for 5 minutes (React Query staleTime)
- Custom roles scoped to organization (multi-tenant isolation)
5. Database, Naming & Environment Guardrails
The database is a core part of the platform, not an implementation detail. We treat it as product.5.1 Multi‑Tenant Data Model
- All business data tables MUST include tenant context (for example
organization_id, andsite_idwhere applicable). - Application-layer filter: Filtering by
organization_id(andsite_idwhere applicable) is REQUIRED on all mutations (INSERT, UPDATE, DELETE) as defense-in-depth. It is RECOMMENDED on SELECT queries as defense-in-depth alongside RLS; RLS remains the primary enforcement for reads. - Row‑Level Security (RLS) (or equivalent mechanism) MUST be enabled and enforced on all business tables.
- RLS policies MUST guarantee:
- No cross‑organization data leakage.
- Restricted cross‑site visibility according to defined roles.
- Any change to RLS MUST be accompanied by test coverage validating the tenant‑isolation behavior.
- Jurisdiction-aware configuration: Organization-level and site-level business rules that vary by state Medicaid program (e.g., clinical assessment requirements, billing thresholds, filing deadlines, documentation timeliness) SHOULD be read from the jurisdiction profile system (PF-96) when available. Until PF-96 is implemented, state-specific configuration MAY use module-level settings with documented migration paths and TODO(PF-96) markers. New features in CL and PM MUST NOT introduce state-specific constants without a TODO(PF-96) marker; they SHOULD consume values from
pf_jurisdiction_profiles,pf_org_jurisdiction_config, orpf_site_jurisdiction_configonce available. Seespecs/pf/specs/PF-96-medicaid-state-compliance-configuration.md.
5.2 Database Naming Conventions
Schemas- Prefer a single primary application schema (e.g.,
public) unless a compelling separation exists. - If multiple schemas are used, each schema MUST have a documented ownership and purpose.
- All table names use
snake_caseand should be plural (e.g.,rh_residents,fa_transactions). - Tables owned by a core MUST be prefixed with that core:
pf_– Platform Foundation (e.g.,pf_users,pf_organizations,pf_sites).rh_– Recovery Housing (e.g.,rh_residents,rh_beds,rh_phases).fa_– Finance (e.g.,fa_transactions,fa_ledgers).hr_– Workforce & HR (e.g.,hr_employees,hr_credentials).gr_– Governance & Learning (e.g.,gr_policies,gr_training_events).fw_– Forms & Workflow (e.g.,fw_forms,fw_workflow_runs).fm_– Facilities & Maintenance (e.g.,fm_work_orders).cl_– Clinical & EHR (e.g.,cl_patient_charts,cl_progress_notes,cl_prescriptions).pm_– Practice Management (e.g.,pm_patients,pm_claims,pm_appointments).
- Junction tables use both entities with an underscore, ordered alphabetically (e.g.,
rh_resident_phases,fa_transaction_tags).
- All column names use
snake_case. - Primary keys:
- Prefer
idas the primary key column, with typeuuidor integer as documented in the DB architecture. - If a natural key is used, it MUST be documented in the spec.
- Prefer
- Foreign keys:
- Use
<entity>_idcorresponding to the referenced table (e.g.,resident_id,organization_id,site_id).
- Use
- Standard audit columns:
created_at(UTC timestamp).updated_at(UTC timestamp).created_by(user ID, where applicable).updated_by(user ID, where applicable).
- Soft‑delete pattern (where used):
deleted_at(nullable UTC timestamp).- Records with
deleted_atnot null are considered logically deleted.
5.2.1 Custom Fields & Extensibility
Purpose: Enable organizations to extend business entities with domain-specific metadata without schema changes. When to Usecustom_fields:
All business entity tables MUST include custom_fields JSONB DEFAULT '{}' NOT NULL unless:
- The table is purely a junction/mapping table (e.g.,
hr_team_members,rh_resident_phases). - The table is an audit/log table (e.g.,
pf_audit_logs,fw_automation_logs). - The table is a system/configuration table managed exclusively by the platform.
- Core entities:
pf_profiles,hr_employees,rh_residents,fa_transactions - Workflow entities:
fw_form_submissions,fw_automation_rules,hr_onboarding_instances - Document entities:
pf_documents,hr_employee_credentials
Design rules (summary):
- Include
custom_fieldsin migrations withCOMMENT ON COLUMNand 3–5 realistic examples (not generic placeholders). - Query with
?,->>,@>as needed; add a GIN index oncustom_fieldswhen queried heavily. custom_fieldsinherits the table’s RLS; do not store secrets (SSN, passwords) in JSONB.
- ✅ Include
organization_id(multi-tenant context) - ✅ Include
custom_fields JSONB DEFAULT '{}'(extensibility) - ✅ Include
created_at,updated_at(audit trail) - ✅ Add
COMMENT ON COLUMNwith 3-5 example use cases - ✅ Enable RLS policies
- ✅ All UPDATE policies include
WITH CHECKclause (see §5.2.9) - ✅ Document in spec and IMPLEMENTATION_LOG.md
5.2.2 Organizational Data Structure
Purpose: Standardize organizational data entities across all modules for consistent policy assignment, access control, and reporting. Platform Foundation Organizational Entities:- Sites (
pf_sites): Physical work locations with tax jurisdiction and address - Departments (
pf_departments): Unified organizational units (operational + cost centers) - Levels (
pf_levels): Employee classification with numerical ranking - Positions (
pf_positions): Job title library for consistency - Teams (
pf_teams): Cross-functional groups
- Unified Departments: Use
pf_departmentsfor both HR and FA (not separate tables)department_typefield: ‘operational’ | ‘cost_center’ | ‘both’- Single source of truth eliminates duplication
- Work Location: Use
primary_site_id(NOTwork_locationTEXT) for employee locationpf_sitesincludestax_jurisdiction,addressfields,timezonefor structured operations
- Level Assignment: All employees should have
level_idfor policy assignment- Levels enable level-based policies (spend policies, access control)
level_rank(1-10) for ordering and formula fields
- Site Usage: Include
site_id(nullable) when entity is location-specific- Required for: residences, work orders, assets, site-specific policies/forms
- Optional for: organization-wide entities (strategic goals, vision)
- Programs:
rh_programs(operational) andfa_programs(financial) serve different purposesrh_programs: Resident program structure, phase managementfa_programs: Medicaid cost reporting, grant tracking- Optional relationship:
fa_programs.rh_program_idfor financial tracking
- RH:
rh_programs(operational/resident programs) - FA:
fa_programs(financial/cost reporting programs),fa_funds - HR:
hr_employees,hr_employee_sites
- Organizations MUST have a
jurisdiction_profile_idFK topf_jurisdiction_profiles(PF-96) - Sites MAY override the organization’s jurisdiction profile via
pf_site_jurisdiction_configfor multi-state operations (e.g., telehealth providers operating across state lines) - The jurisdiction profile provides state-specific clinical, billing, and compliance configuration consumed by CL, PM, and GR features
- Profile resolution order: site override → organization profile → federal baseline defaults
- All modules reference
pf_departments,pf_sites,pf_levels,pf_teams - CL and PM modules reference
pf_jurisdiction_profilesfor state-specific rules - No cross-core dependencies (all via Platform Foundation)
- Organizational data managed through Platform Foundation, consumed by domain cores
5.2.3 Module Settings Pattern
Purpose: Enable organization-level configuration of module behavior without code changes or environment-specific configuration. When to Use Module Settings: Every domain core (HR, FW, RH, FA, etc.) SHOULD have a module settings table and admin page unless the module has no configuration requirements. Required Components:-
Settings Table:
{core}_module_settings- One row per organization (1:1 relationship)
- Contains configuration columns specific to the module
- Includes standard audit columns (
created_at,updated_at,created_by,updated_by) - RLS policies: View (org users), Insert/Update (org_admin only)
-
Admin Page:
src/cores/{core}/pages/{Core}Settings.tsx- Route:
/{core}/settings - Access:
org_adminonly (enforced in navigation and route) - Tabbed interface organizing related settings
- Auto-creates settings record if not exists
- Route:
-
Hook:
src/cores/{core}/hooks/use{Core}ModuleSettings.ts- Query hook: Fetch organization’s settings
- Mutation hooks: Create/update settings
- Handles loading states, errors, cache invalidation
-
Form Component:
src/cores/{core}/components/{Core}SettingsForm.tsx- Tabbed form matching logical groupings
- Form validation with Zod schemas
- Save/reset actions with confirmation
- ✅ Settings when organizations differ in requirements/preferences — time-based values, business-rule thresholds, UI/UX defaults, performance tuning, feature behavior.
- ✅ Jurisdiction profile (
pf_jurisdiction_profiles, PF-96) when the value varies by state Medicaid program (filing deadlines, timed-code thresholds, assessment / documentation-timeliness rules). Module settings override profile defaults only when an org explicitly customizes beyond its jurisdiction baseline. - ❌ Hard-code only system constants (enum values, system-wide limits).
5.2.4 Centralized Picklist System
Purpose: Enable organizations to define and manage custom picklist values without code changes or database migrations, providing flexibility for domain-specific workflows. When to Use Picklists vs Enums:
Playbook: Table DDL, indexes, and example RLS: docs/development/DATABASE_DEVELOPMENT_GUIDE.md § Constitution playbook — Picklists. Application hooks and UI:
specs/pf/PF-15-picklist-system.md. Custom field definitions may reference picklist_id on pf_custom_field_definitions (same guide § Custom field definitions).
Spec-Authoring Checklist (Picklist Evaluation):
When a spec introduces new status fields, categories, types, reasons, or any dropdown/select option list:
- Evaluate each value list against the Picklists vs Enums table above
- Document the decision in the spec’s Enums and Source Types section:
Picklist: Yes (org-customizable) | No (system constant, reason: ___) - If picklist: add a task to seed default picklist values via migration (
INSERT INTO pf_picklists / pf_picklist_items) - If picklist: reference in forms via
usePicklistItems(picklistId)instead of hardcoded<option>elements orCHECKconstraints - If enum: use
CHECK (column IN (...))only for true system constants; document why the values are not org-customizable
5.2.5 Custom Field Definitions (PF-16)
Status: Implemented — seespecs/pf/PF-16-custom-field-definitions.md for hooks, components, admin UI, and supported entities.
Purpose: Enable organizations to define schema-like metadata for custom fields, providing structure and validation for the JSONB custom_fields column.
When to Use Custom Field Definitions:
Custom field definitions are appropriate when:
- Organizations need to document what custom fields they use
- Validation rules are required for custom field values
- UI needs to dynamically render custom field inputs
- Reporting needs to know custom field schemas
validation_rules JSON samples: docs/development/DATABASE_DEVELOPMENT_GUIDE.md § Constitution playbook — Custom field definitions.
Relationship to custom_fields JSONB:
custom_fieldscolumn: Stores actual data values (flexible, unstructured)pf_custom_field_definitions: Stores metadata about what fields exist (structured, documented)- Custom field definitions are OPTIONAL — organizations can use
custom_fieldswithout defining schemas - When definitions exist, UI can provide better forms, validation, and reporting
specs/pf/PF-16-custom-field-definitions.md.
5.2.6 Entity Field Configuration (PF-17) ✅
Purpose: Enable organizations to control field layouts, visibility, and permissions for entity forms without code changes. Design principles (guardrails):- Configuration applies to UI only, NOT database schema — DB constraints (e.g. NOT NULL columns) remain unchanged.
- Per-entity-type (e.g.
hr_employees,rh_residents); org admins manage via UI, no code changes. - Mobile responsive:
column_span: 2becomes full width on mobile.
specs/pf/PF-17-entity-field-configuration.md.
5.2.7 PWA & Mobile Considerations
Offline Data:- Tables that support offline functionality MUST be designed with sync capabilities
- Consider
sync_statusorlast_synced_atcolumns for offline-first features - Background sync queues SHOULD use dedicated tables (e.g.,
fw_offline_queue)
- Indexes MUST be optimized for mobile query patterns
- Avoid N+1 queries that impact mobile performance
- Consider materialized views for dashboard aggregations
- Every foreign key column used in joins MUST have an index.
- Unique constraints MUST be named explicitly and reflect purpose (e.g.,
rh_residents_organization_id_external_id_key).
- Storage bucket names MUST follow the pattern:
{core_prefix}-{purpose}- Examples:
pf-avatars,pf-documents,fw-submission-attachments
- Examples:
- Public vs private buckets MUST be explicitly documented in specs
- Bucket RLS policies MUST enforce tenant isolation
- Function names MUST follow the pattern:
{core_prefix}_{action}_{entity}()- Examples:
pf_has_role(),fw_execute_automation_rule(),rh_calculate_occupancy()
- Examples:
- All functions that support RLS policies MUST be
SECURITY DEFINER - Function ownership and purpose MUST be documented in migration comments
5.2.8 Cross-Core Database References
When a table in one core needs to reference an entity owned by another core:- Default pattern: UUID column with no FK constraint. Validation at the application layer. Column comment MUST document the target table and owning core.
- Scoped exception (requires ADR): For tightly coupled domains where referential integrity is critical (e.g., CL-PM encounter references), a database FK MAY be used with
ON DELETE RESTRICT. An ADR indocs/architecture/decisions/MUST document the exception, its scope, and its rationale. - Column naming: Use
{target_entity}_id(e.g.,encounter_idforpm_encounters). - Indexes: Cross-core reference columns MUST be indexed.
5.2.9 RLS UPDATE Policy Requirements
Critical Rule: All RLS UPDATE policies MUST include bothUSING and WITH CHECK clauses.
Why This Matters:
USINGcontrols which rows can be selected for updateWITH CHECKcontrols what values the row can be updated to- Without
WITH CHECK, a user can changeorganization_idto move data between tenants
WITH CHECK, a user who can update a row can change its organization_id, effectively moving data between tenants and breaking multi-tenant isolation.
Playbook: Full patterns and examples live in docs/development/DATABASE_DEVELOPMENT_GUIDE.md § RLS Policy Patterns.
5.3 Migrations & Change Management
- All schema changes MUST be implemented as migrations in version control.
- Migrations MUST be:
- Monotonic and ordered via timestamp or sequence.
- Re‑runnable in lower environments from a clean database.
- Migration file naming:
- Manual migrations:
YYYYMMDDHHMMSS_core_short_description.sql(14-digit timestamp, seconds included — matches every file undersupabase/migrations/)
Example:20260522143000_rh_add_resident_phases.sql. - Lovable-generated migrations: Auto-generated names are acceptable (e.g.,
20241124123456_remote_schema.sql) - The important requirement is monotonic ordering and clear purpose in comments, not the exact filename format.
- Manual migrations:
- Direct schema changes in shared environments are prohibited except emergency hotfixes; those require:
- Documentation of the hotfix.
- Follow‑up migration to codify the change.
- Destructive changes (dropping tables/columns, changing primary keys, altering tenant keys) MUST:
- Be explicitly marked as breaking in the spec.
- Include a data‑migration strategy and rollback considerations.
5.4 Environment Separation
- Local, dev, staging, and prod environments MUST each have:
- Separate databases and credentials.
- Clear, documented data refresh patterns.
- Pre‑merge validation MUST:
- Run migrations against a non‑prod database.
- Run the test suite relevant to the changes (unit, integration, RLS, etc.).
5.5 Production Deployment & Rollback
Deployments to production require discipline and a clear rollback strategy. Deployment Requirements:- All production deployments MUST:
- Pass the full test suite in a staging environment.
- Have a documented rollback plan.
- Be tagged with semantic version numbers.
- Include a deployment checklist (migrations, config changes, feature flags).
- Database migrations in production MUST be:
- Backward-compatible whenever possible.
- Applied before code deployment (to support rollback).
- Tested against a production-like dataset.
- Code rollback: Previous version available via version control tags.
- Database rollback: Documented down-migrations for each schema change.
- Feature flags: Use flags to disable new features without redeployment.
- Monitoring: Alert on error rate spikes, latency increases, or failed health checks.
- Require explicit approval from technical owner.
- Must be followed by a proper migration and test coverage.
- Documented in IMPLEMENTATION_LOG.md within 24 hours.
5.6 Performance & Monitoring Standards
The platform MUST be observable and performant. Performance Targets:- API response time: p95 < 500ms for read operations, p95 < 2s for writes.
- Page load time: p95 < 3s for initial load, p95 < 1s for navigation.
- Database queries: Index all foreign keys; no full table scans in production.
- All production deployments MUST have:
- Health check endpoints (
/health,/readiness). - Error tracking (e.g., Sentry, Rollbar).
- Structured logging with correlation IDs.
- Database query performance monitoring.
- Health check endpoints (
- Critical flows (auth, billing, clinical) MUST have:
- Synthetic monitoring (uptime checks).
- Alerting on error rates > 1% or latency p95 > SLA.
- Use structured JSON logs with standard fields:
timestamp,level,module,action,user_id,org_id,correlation_id. - Do NOT log PHI, PII, or secrets.
- Log retention: 30 days for info, 90 days for errors, 1 year for audit logs.
5.7 RLS Anti-Patterns & Security Definer Functions
Critical: Avoiding Infinite Recursion RLS policies MUST NOT query the same table they are protecting. This causes infinite recursion errors. ❌ WRONG - Recursive RLS Policy:- When RLS policies need to query other tables to make authorization decisions
- When checking role-based access that requires joining tables
- When implementing reusable authorization logic across multiple policies
- MUST be explicitly marked as
SECURITY DEFINERwithSET search_path = public - MUST have clear, descriptive names indicating their purpose
- MUST be tested thoroughly to prevent privilege escalation
- MUST be documented in specs and migration comments
5.8 Edge Function Patterns
Edge functions extend backend capabilities for complex processing, external integrations, and async workflows.5.8.1 Shared Code Pattern
When multiple edge functions need common logic: Location:supabase/functions/_shared/
Structure:
- All shared code MUST be Deno-compatible (no Node.js-specific APIs)
- Shared utilities MUST be stateless and side-effect-free
- Types MUST be exported for consumer functions
- NEVER import from
src/- shared code lives in_shared/ - Edge functions MUST use
verifyOrgAccess()orverifyOrgRole()from_shared/auth.tsfor organization membership checks. Inlinepf_user_role_assignmentsqueries are prohibited — they are prone to PGRST116 errors and bypass centralized.limit(1)safeguards.
5.8.2 Database Trigger → Edge Function Pattern
For async processing triggered by database changes: When to Use:- AI-assisted processing (summarization, extraction)
- External API calls (webhooks, integrations)
- Multi-step workflows
- Long-running operations that shouldn’t block the transaction
- Use
AFTERtriggers (notBEFORE) to avoid blocking transactions - Include
organization_idfor tenant context - Handle edge function errors gracefully (don’t fail the trigger)
- Log trigger invocations for debugging
5.9 Scheduled Task Pattern
For recurring background jobs usingpg_cron and pg_net.
When to Use:
- Daily/weekly reports and summaries
- Data cleanup and archival
- Scheduled syncs with external systems
- Recurring notifications (e.g., “credentials expiring this week”)
- Aggregation and metric calculations
Job Management:
- Use descriptive job names with core prefix
- Document schedule and purpose in code comments
- Edge function MUST handle idempotency (safe to run multiple times)
- Include
triggered_atin payload for debugging - Set up alerts for failed job runs
- Consider timezone implications (pg_cron runs in UTC)
5.10 Bulk Import & Data Migration Standards
Bulk import means parsing CSV (or similar) and writing records to the database. All such flows MUST follow these standards. Shared CSV Parsing:- MUST use shared CSV parsing from Platform (
@/platform/csvor the documented shared location). No duplicateparseCsvLine/parseCsvimplementations in cores or platform components.
- Use an edge function when the import involves multi-entity creation, auth/invites, or transaction ordering that must be server-side (e.g., employee roster with sites, departments, profiles, and optional user accounts).
- Use client-side chunked insert for simple insert-only to one or a few tables (e.g., contacts, credentials, custom object records). Batch size MUST be 50 unless justified otherwise.
- For client-side bulk insert, show determinate progress when the operation can exceed a few seconds (e.g., percentage per batch).
- For edge-function-based import, indeterminate progress is acceptable unless the function supports progress reporting.
- After successful import, invalidate every query key affected by the import (e.g., list and detail queries for the imported entity and any related entities).
docs/development/BULK_IMPORT_MIGRATION_RECOMMENDATIONS.mddocs/guides/use-cases/bulk-import-migration.md
6. PWA & Mobile-First Requirements
Encore OS is a Progressive Web App (PWA) with mobile-first responsive design. All features MUST be designed and implemented with mobile devices as the primary target, with desktop as an enhancement.6.1 PWA Requirements
Installability:- All builds MUST include proper PWA manifest with real app icons (not placeholders)
- Icons MUST be provided in required sizes: 192x192, 512x512, with maskable support
- Manifest MUST include app name, short name, theme color, background color
- Install prompt MUST be implemented for discoverability
- Forms and submissions MUST work offline with background sync
- Critical user flows MUST degrade gracefully when offline
- Offline detection UI MUST be provided
- Service worker MUST be properly configured and tested
- Lighthouse PWA score MUST be 90+ in production
- First Contentful Paint: <2s
- Time to Interactive: <3.5s on 3G
- All assets MUST be cached appropriately
- PWA install flow MUST be tested on iOS, Android, and desktop
- Offline functionality MUST be tested
- Service worker updates MUST be tested
- Lighthouse audit MUST be run before production deployment
6.2 Mobile-First Design Principles
Responsive Breakpoints:- Mobile: < 768px (primary target)
- Tablet: 768px - 1024px
- Desktop: > 1024px
- All layouts MUST work on mobile first, then enhance for larger screens
- All interactive elements MUST have minimum 44x44px touch targets
- Spacing between touch targets MUST be at least 8px
- Buttons, links, and form controls MUST meet accessibility standards
- All fixed navigation elements (top header, bottom nav) MUST account for safe area insets
- Use
env(safe-area-inset-top)andenv(safe-area-inset-bottom)in CSS - Test on devices with notches and home indicators (iPhone X+, modern Android)
- Primary orientation: Portrait
- Landscape orientation MUST be supported but may have simplified layouts
- Critical features MUST work in both orientations
- Mobile pages MUST load in <3s on 3G
- Images MUST be optimized and lazy-loaded
- Code splitting MUST be used for route-based components
- Heavy components MUST be lazy-loaded
6.3 Navigation Requirements
Navigation Documentation:- All modules MUST have a navigation worksheet at
specs/{core}/navigation/NAVIGATION_WORKSHEET.md - Navigation worksheets MUST use the template from
specs/_templates/NAVIGATION_WORKSHEET_TEMPLATE.md - Navigation worksheets MUST document all navItems, navGroups, routes, permissions, and breadcrumb configuration
- Navigation worksheets MUST be updated when adding or restructuring navigation
- Modules MUST have 4-8 navGroups (recommended)
- Each navGroup MUST have 3-7 items (recommended)
- Single-item groups MUST be merged into related groups
- Groups with 8+ items SHOULD be split into logical subgroups
- Each distinct feature MUST have a unique icon within the same navigation context
- Icons MUST be imported from
lucide-reactexclusively - Icons MUST be semantically meaningful and visually distinct
- Duplicate icons for different features are prohibited
- Bottom tab bar MUST be used for primary navigation (< 768px)
- Bottom nav MUST include safe area insets
- Mobile menu sheet MUST provide access to all modules and nested navigation
- Navigation state MUST be preserved across page refreshes where applicable
- Mobile header SHOULD display current location context (breadcrumb or page title)
- Desktop primary navigation (>= 768px) MUST offer at least Sidebar mode; MAY offer Dock and Taskbar as user-selectable alternatives.
- When Sidebar mode is selected, sidebar open and collapse state MUST be persisted (e.g. in localStorage).
- Breadcrumbs MUST be provided for deep navigation (3+ levels)
- Active state indicators MUST be clear and accessible
- All navigation MUST be keyboard accessible
- Focus indicators MUST be visible
- ARIA labels MUST be provided for screen readers
- Navigation depth MUST be reasonable (max 4 levels recommended)
docs/architecture/standards/NAVIGATION_STANDARD.md for complete navigation standards and docs/architecture/standards/PERMISSION_KEY_STANDARD.md for permission key patterns.
6.3.1 Breadcrumb Standards
Breadcrumbs provide hierarchical navigation context and MUST be implemented consistently across the platform. Architecture:- Base Primitives: Use
@/shared/ui/breadcrumbcomponents (Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator) - Auto-Generated: Desktop header uses
@/platform/navigation/Breadcrumbs.tsxfor automatic route-based breadcrumbs - Route Labels: Centralized in
@/platform/navigation/route-labels.ts(~150 routes across all modules) - Mobile Support: Mobile navigation MUST include
MobileBreadcrumbscomponent (max 2 segments, horizontally scrollable)
- ✅ Detail pages (viewing/editing a specific entity)
- ✅ Nested settings pages (3+ levels deep)
- ✅ Multi-step workflows
- ❌ Module overview/dashboard pages (ModuleSwitcher provides context)
- ❌ Top-level list pages (e.g.,
/hr/employees) - For tabbed hub routes (
?tab=), the active tab is included as the final breadcrumb segment (see NAVIGATION_STANDARD §2a and hub-tab-labels).
PageContainer breadcrumbs={[…]} showBreadcrumbs for dynamic entity names / non-route segments; (3) manual @/shared/ui/breadcrumb primitives (rare). Full code + step-by-step: breadcrumb-implementation-guide.md.
Route Label Maintenance:
- All route labels are centralized in
src/platform/navigation/route-labels.ts; Breadcrumbs use this for segment labels - Tab context for hub routes (
?tab=) comes from hub-tab-labels (or the central hub-tab config in@/platform/navigation/hub-tab-labels.ts); implementers should maintain both route-labels and hub-tab-labels when adding tabbed hubs - When adding new features, add corresponding labels to
ROUTE_LABELSmap - Naming conventions:
- Use sentence case: “Work orders” not “Work Orders”
- Be concise: “Employees” not “Employee Management”
- Match UI terminology consistently
- Fallback: Path segments are auto-capitalized (e.g.,
work-orders→ “Work Orders”)
- Mobile header MUST include
MobileBreadcrumbscomponent - Maximum 2 visible segments on mobile (truncate earlier segments)
- Use horizontal scroll for overflow content
- Touch targets MUST be 44x44px minimum
- Breadcrumbs MUST respect safe area insets
- ❌ Manual inline breadcrumbs without using components (e.g., raw
<div>with ChevronRight) - ❌ Breadcrumbs that don’t match actual navigation hierarchy
- ❌ Non-clickable intermediate breadcrumb segments (except current page)
- ❌ Skipping
ROUTE_LABELSwhen adding new routes - ❌ Creating module-specific route label files (use centralized file only)
6.4 Dashboard Standards
Layout Patterns:- Dashboards MUST use consistent widget-based layouts
- Grid system MUST be responsive (1 column mobile, 2-3 columns desktop)
- Widgets MUST be self-contained and reusable
- Loading states MUST be standardized (use skeleton loaders)
- Module dashboards MUST support user widget customization
- Widget visibility is two-tier: org admins enable/disable widgets platform-wide via
pf_module_settings.enabled_widgets(JSONB boolean map, default-ON — absent key = enabled), checked withuseWidgetEnablement()from@/platform/dashboard/hooks/useWidgetEnablement; per-user show/hide preferences MUST be stored inpf_user_dashboard_preferencesand apply only to widgets the org has enabled. - Widget ID naming convention:
{core}-{feature}(e.g.,fa-budget-alerts,hr-time-clock) - Users MUST be able to show/hide widgets via settings dialog
- Widget reordering SHOULD be supported via drag-and-drop
- All dashboard widgets MUST use
DashboardWidgetwrapper from@/platform/dashboard/components/DashboardWidget - Widgets MUST be lazy-loaded using
React.lazy()for performance - Widgets MUST handle loading, error, and empty states gracefully
- Widgets MUST be registered in
@/platform/dashboard/widget-registry.tsfor platform-wide availability - Widget components location:
src/cores/{core}/components/dashboard/ - Widget file naming:
{Feature}Widget.tsx(e.g.,BudgetAlertsWidget.tsx,TimeClockWidget.tsx)
- Dashboards MUST fetch real-time data (NO hardcoded values)
- Each module SHOULD have a consolidated
use{Core}DashboardStats.tshook - Use React Query with appropriate staleTime (5 minutes for dashboard data)
- Implement optimistic updates where applicable
- Main dashboard MUST include personalized content (not just module launcher)
- Dashboards MUST show recent activity where applicable
- Empty states MUST be provided with helpful CTAs
- Quick actions MUST be prominently displayed
- Dashboards MUST implement progressive loading (above-the-fold first)
- Heavy widgets MUST be lazy-loaded
- Real-time updates MUST use Supabase realtime subscriptions
- Dashboard load time MUST be <2s on desktop, <3s on mobile
- All module dashboards MUST follow shared dashboard patterns
- Widget components MUST be reusable across modules
- Dashboard customization is REQUIRED for all module dashboards
6.5 Frontend Performance Patterns
Frontend performance is critical for PWA and mobile-first experience. These patterns are MANDATORY for all new code. Playbook: Copy-paste examples and the pattern index: AGENTS.md (Quick Reference), .cursor/rules/quick-reference.mdc, .cursor/rules/performance-patterns.md. Route-Level Code Splitting (REQUIRED):- ALL route components MUST use
React.lazy()for code splitting; direct route component imports are PROHIBITED.
- Route-level Suspense MUST wrap lazy-loaded routes; use
RouteLoadingSkeleton/AppLoadingSkeletonas documented in platform navigation components.
- NEVER use
return nullduring loading; use skeleton loaders from@/platform/navigation/components/to avoid CLS.
- Default query options SHOULD include
staleTime5 minutes,gcTime10 minutes,retry: 1,refetchOnWindowFocus: false(see global app setup).
- Maximum 2–3 font families;
font-display: swap; preconnect for font CDNs; no duplicate font imports.
- Preconnect to critical origins (e.g. Google Fonts, Supabase project host) in app HTML/template per platform setup.
- Lighthouse Performance Score: 85+
- First Contentful Paint: <2s
- Largest Contentful Paint: <2.5s
- Cumulative Layout Shift: <0.1
- Time to Interactive: <3.5s on 3G
6.6 Authentication State Management
Critical Rules:- ALWAYS use
useCurrentUserhook from@/platform/auth(not scatteredsupabase.auth.getUser()calls) - ALWAYS use static Supabase imports at file top (never dynamic imports in
useStateor elsewhere) - ALWAYS use
useEffectfor auth side effects (NEVERuseStatefor side effects) - NEVER call
supabase.auth.getUser()directly in components or hooks
- Performance: Single API call instead of 162+ (99% reduction)
- Consistency: All components see same auth state simultaneously
- Reliability: Automatic cache invalidation on auth state changes
- Build Quality: No mixed import warnings or React anti-patterns
- Use
useCurrentUserhook from@/platform/auth - Use static Supabase imports (at file top, never dynamic)
- Use
useEffectfor side effects (NEVERuseState) - Export
useCurrentUserfromsrc/platform/auth/index.ts - Test auth state changes (login, logout, refresh)
- ❌ Direct
supabase.auth.getUser()calls in components - ❌ Dynamic Supabase imports (
import('@/integrations/supabase/client')) - ❌ Using
useStatefor side effects or async operations - ❌ Multiple auth state management approaches in same codebase
6.7 UI/UX Guardrails
Reference: Seedocs/development/UI_UX_STANDARDS.md for complete UI/UX patterns and standards.Color Utilities: See
docs/development/SEMANTIC_COLORS.md for semantic color mapping utilities and semanticColorClasses from @/shared/lib/semantic-colors. Run scripts/utils/audit-hardcoded-colors.sh to detect hardcoded color classes.
Design System (MUST):
- Token-Based Styling: All colors, spacing, and typography MUST use semantic tokens from
src/index.css, never hardcoded Tailwind color classes (e.g.,text-green-500,bg-red-100). - Semantic Colors: Use semantic color tokens (
success,warning,destructive,primary, etc.) for status indicators and UI feedback. UsesemanticColorClassesutility from@/shared/lib/semantic-colorsfor consistent color mapping. - Component Variants: Use standardized component variants (Badge, Button, Alert) instead of custom className overrides.
- Loading States: All loading states MUST use skeleton loaders (
<Skeleton />component), neverreturn null. - Error States: All error states MUST show user-friendly messages with recovery actions.
- Empty States: All list/detail pages MUST use the shared
<EmptyState />component with clear next steps.
- PageHeader: Use
PageHeadercomponent for consistent page titles, descriptions, and actions. - StatCard: Use
StatCardcomponent for dashboard metrics and overview statistics. - EmptyState: Use
EmptyStatecomponent for all empty list/search states. - CardActionsMenu: Use
CardActionsMenufor card action menus with proper touch targets.
- Route Taxonomy: Follow established route patterns (flat structure with nested sub-modules where appropriate).
- Breadcrumbs: Show breadcrumbs on detail pages (3+ segments) and nested sub-module pages, not on overview/list pages.
- Route Integrity: All navigation metadata (module registry, breadcrumb labels) MUST reference routes that exist in the router.
- Touch Targets: All interactive elements MUST meet 44x44px minimum touch target size.
- Safe Areas: Fixed elements (header, bottom nav) MUST respect safe area insets using
.safe-area-top,.safe-area-bottomutilities. - Header Density: Mobile header chrome MUST minimize vertical space consumption (< 120px target on most pages).
- Always-Visible Actions: Card actions MUST be visible without hover (no hover-only action patterns).
- Standard Size Tiers: All
DialogContentMUST use one of 5 standard Tailwind size tiers:sm:max-w-md(small),sm:max-w-lg(medium),sm:max-w-2xl(large),sm:max-w-3xl(x-large),sm:max-w-4xl(full). See.cursor/rules/dialog-size-standards.mdfor decision guide. - Responsive Prefix: All dialog/sheet widths MUST include the
sm:responsive prefix (e.g.,sm:max-w-lgnotmax-w-lg). - No Arbitrary Pixels: NEVER use arbitrary pixel values for dialog/sheet widths (e.g.,
max-w-[425px],max-w-[500px]). Use Tailwind utility classes only. - No Redundant Overflow: NEVER add
overflow-y-autoormax-h-*toDialogContent— the basedialog.tsxcomponent already handles overflow and max-height. - Page Containers: All page-level content MUST use the
<PageContainer>component from@/shared/components/PageContainer— never manualcontainer mx-autopatterns.
- Native Browser Dialogs: NEVER use
window.prompt(),window.confirm(), orwindow.alert(). Use customDialog,AlertDialog, ortoastcomponents instead. - Hover-Only Actions: NEVER hide card/row actions behind
:hoverstates. Actions must be accessible on touch devices. - Hardcoded Color Maps: NEVER create switch/if statements returning hardcoded Tailwind colors. Use
semanticColorClassesutility instead. - Arbitrary Dialog Sizes: NEVER use arbitrary pixel widths (
max-w-[425px]) on dialogs or sheets. Use standard Tailwind size tiers. - Manual Page Containers: NEVER use
<div className="container mx-auto ...">for page layout. Use<PageContainer>component.
- Route Code Splitting: All route components MUST use
React.lazy()for code splitting. - Suspense Boundaries: All lazy routes MUST be wrapped in
<Suspense>with skeleton fallbacks. - QueryClient Configuration: QueryClient MUST have default
staleTimeandgcTimeconfigured (seedocs/development/UI_UX_STANDARDS.md).
- Keyboard Navigation: All interactive elements MUST be keyboard accessible with logical tab order.
- Focus Indicators: All interactive elements MUST have visible focus indicators (2px solid outline using
--ringtoken). - Contrast: All text MUST meet WCAG AA contrast ratios (4.5:1 for normal text, 3:1 for large text).
- ❌ Hardcoded Tailwind color classes (
text-green-500,bg-red-100) - ❌
return nullfor loading states (must use skeleton loaders) - ❌ Direct route imports (must use
React.lazy()) - ❌ Missing error/empty states
- ❌ Touch targets smaller than 44x44px
- ❌ Missing safe area handling on fixed elements
6.8 Wizard & Help UX Requirements
Multi-step workflows and contextual help are critical for complex features. These patterns ensure consistent, user-friendly experiences. When to Use Wizards:
Wizard Standards (REQUIRED):
- Progress Indicator: Wizards MUST show step progress (numbered steps or progress bar)
- Draft Persistence: Wizards with >3 steps MUST auto-save drafts
- Per-Step Validation: Validation MUST occur before allowing next step
- Back Navigation: Users MUST be able to go back without losing data
- Review Step: Complex wizards SHOULD include a final review step
- Exit Confirmation: Wizards with unsaved changes MUST prompt before exit
- Domain Terminology: All industry-specific terms MUST have tooltips (use
InfoTooltiporFormFieldWithHelp) - First-Time Guidance: New features SHOULD offer guided tours (use
GuidedTour) - Step Guidance: Each wizard step SHOULD have a
QuickTipexplaining the purpose - Comprehensive Help: Complex features SHOULD include
HelpPanelaccess
InfoTooltip / FormFieldWithHelp / QuickTip / GuidedTour / HelpPanel), the wizard implementation checklist, and step-by-step build guidance are the extended reference — see WIZARD_UX_STANDARD.md + WIZARD_DEVELOPMENT_GUIDE.md (component API: src/platform/help/README.md).
Prohibited Patterns:
- ❌ Wizards without progress indication
- ❌ Industry terms without explanations
- ❌ Losing data on back navigation
- ❌ Validation only on final submit
- ❌ No way to save partial progress
src/cores/rh/components/wizards/ResidentAdmissionWizard.tsx
See: src/platform/help/README.md for component API documentation.
Rationale: Guided workflows reduce errors and improve completion rates. Contextual help reduces support burden and enables self-service learning.
6.8.1 Help Content Requirements
All features SHOULD include contextual help content: Tooltip Requirements:- All domain-specific terminology MUST have tooltips
- All form fields with industry jargon MUST have explanations
- Tooltips MUST be registered in
src/platform/help/tooltip-content.ts - Use
InfoTooltipfor field labels,FormFieldWithHelpfor form fields
- Features with 4+ steps SHOULD have a guided tour
- Tours MUST be skippable
- Tour completion MUST be tracked
- Tour steps MUST use stable DOM selectors (IDs preferred)
- Complex features SHOULD have a help panel
- Help panels MUST include: Getting Started, Key Concepts, Common Tasks
- Help panels SHOULD link to related guided tours
- Use
specs/_templates/TOOLTIP_CONTENT_TEMPLATE.mdfor tooltip additions - Use
specs/_templates/GUIDED_TOUR_TEMPLATE.mdfor tour definitions - Use
specs/_templates/SPEC_TEMPLATE_LITE.mdfor content-only work
- See
docs/production-readiness/CONTENT_GAPS_CHECKLIST.mdfor module-level tracking - All new features SHOULD contribute to closing content gaps
- Run
npx tsx scripts/audit-content-gaps.tsto identify gaps - Automated weekly audit via
.github/workflows/content-gap-audit.yml
- Features that generate documents (letters, reports, certificates) SHOULD define templates
- Use
specs/_templates/SPEC_TEMPLATE_LITE.mdfor template definitions - Track in
docs/production-readiness/CONTENT_GAPS_CHECKLIST.mdwith{MODULE}-DOC-##IDs - See
src/platform/templates/README.mdfor PF-64 API
- Form submissions (FW-02) can be exported as branded PDFs using PF-64 letterheads
- Use
useFormSubmissionPdffrom@/platform/formsfor submission-to-PDF conversion - Use
useGenerateTemplatedPdffrom@/platform/templatesfor templated PDF generation - Forms collect data; Document Templates format data for print — these are complementary, not competing features
- See
docs/guides/use-cases/template-selection.mdfor guidance on when to use each
7. Finance & Clinical Guardrails
Finance and clinical domains require stricter controls.7.1 Finance (FA)
- Subledger and accounting flows MUST be explicitly modeled and documented:
- What events create charges, payments, adjustments, and write‑offs.
- How and when postings roll into a general ledger or external system.
- Financial transactions are append‑only:
- Corrections use adjustments, not destructive updates.
- All financial calculations (balances, aging, interest, accruals) MUST be covered by tests with edge cases.
7.2 Clinical (CL – Clinical & EHR)
- Clinical capabilities (documentation, orders, outcomes) will only be built on top of a mature operational and financial backbone.
- Any clinical feature must:
- Be designed with auditability, versioning of records, and legal defensibility in mind.
- Avoid being a dependency for non‑clinical cores.
- Clinical design MUST align with a recovery-oriented, trauma-informed, person-centered, and strengths-based model. Documentation and workflows MUST support the whole person, not only symptom or diagnosis.
- Social Determinants of Health (SDOH) are first-class clinical data: screening, tracking, and referral to community resources MUST be supported where specified (e.g., CL-18). ICD-10-CM Z-codes (Z55–Z65) for SDOH MUST be available in the code library.
- Peer support and lived experience services (peer specialists, recovery coaching) MUST be documented and billable per applicable specs (e.g., CL-19). Peer-delivered services are not optional add-ons but part of the care model.
- Cultural responsiveness MUST be supported: language preference, interpreter use, and cultural factors in assessment and care planning. Documentation MUST support language services tracking and cultural adaptation where required by spec.
- Jurisdiction-aware clinical requirements: Clinical documentation requirements (assessment elements, note content, timeliness rules, attestation language) vary by state Medicaid program. CL features SHOULD read these requirements from the organization’s jurisdiction profile (PF-96) when available. Until PF-96 is implemented, CL features MAY use AHCCCS defaults with TODO(PF-96) markers documenting the migration path. New CL features MUST NOT reference AHCCCS-specific policies (e.g., “AHCCCS Policy 940”, “AMPM 320-O”) as universal constants; they SHOULD use profile-driven configuration so that organizations in other states see their applicable requirements. Arizona remains the default profile for backward compatibility.
7.3 Medical Terminology Governance
- Code library (PF-70): ICD-10-CM, CPT, HCPCS, LOINC, NDC, and related code sets MUST be managed through the platform medical terminology spec (PF-70). CL and PM MUST use the shared code library for diagnosis, procedure, and modifier selection; no hard-coded code lists in application code.
- Updates: Code set updates (e.g., annual ICD-10-CM, CPT) MUST follow a documented, repeatable process with effective dating so that historical claims and documentation remain valid.
- Validation: Code-modifier combinations and effective-date checks MUST be enforced at the point of use (e.g., charge capture, claim submission). Validation rules MAY be extended by organization or payer via PF-70 configuration.
8. Simplicity, Pragmatism & Decisions
We prefer simple, explainable solutions over clever but fragile ones.8.1 Simplicity Rules
- Don’t build features “just in case.” YAGNI is the default.
- Avoid premature abstractions; duplication is acceptable until patterns are proven.
- Lean on well‑understood frameworks and libraries instead of bespoke infrastructure.
8.2 Decision Discipline
- Material decisions (architecture, data contracts, external dependencies) MUST:
- Be captured in specs or lightweight ADRs (Architecture Decision Records).
- Include trade‑offs and impact on other cores.
8.3 Code Review & Pull Request Standards
All code changes MUST go through review before merging. Pull Request Requirements:- PR title follows convention:
[CORE-##] Short description(e.g.,[RH-01] Add resident admission flow). - PR description includes:
- Link to spec or issue.
- What changed and why.
- Testing approach and results.
- Migration or deployment notes (if applicable).
- PRs MUST be:
- Small and focused (< 500 lines of code when possible).
- Self-contained (one feature or fix per PR).
- Accompanied by tests (unit, integration, or E2E as appropriate).
- Does it follow constitution naming and structure conventions?
- Are tenant isolation and RLS correctly applied?
- Is there test coverage for new behavior?
- Are migrations backward-compatible?
- Is documentation updated?
- Are there any security, privacy, or financial risks?
- Are hard-coded values that should be settings identified and moved to module settings?
- PRs should be reviewed within 24 hours (business days).
- Critical fixes: within 4 hours.
- Reviewers should provide actionable feedback, not just “LGTM.”
8.4 Deprecation & Legacy Code Policy
Technical debt is managed, not ignored. Deprecation Process:- Code, APIs, or database columns marked for deprecation MUST:
- Have a documented sunset date (at least 90 days out).
- Log warnings when used.
- Have a migration path documented.
- Deprecated features MUST be removed within 180 days unless explicitly extended.
- Legacy code that cannot be immediately refactored MUST:
- Be clearly marked (e.g.,
// LEGACY: Do not extend. Migrate to XYZ by 2026-Q2). - Have a tracking issue for removal or refactor.
- Not be a dependency for new features.
- Be clearly marked (e.g.,
- Dead code (unused functions, components, imports) MUST be removed during PR review.
- Commented-out code is not allowed; use version control history instead.
9. Documentation & Ownership
Documentation is part of the deliverable, not “nice to have.”9.1 What Must Be Documented
For each core/module, the following must exist and be kept current:- Overview: What it does and what it owns.
- Data model: Key entities, relationships, and IDs.
- APIs/contracts: External and cross‑core interfaces.
- Operational runbook: Monitoring, alerts, common failure modes, support paths.
9.2 Ownership
- Every core/module has a clearly named business owner and technical owner.
- Ownership includes:
- Decision rights within that domain.
- Responsibility for quality, documentation, and operational performance.
9.3 Implementation Log Requirements
The Implementation Log (specs/IMPLEMENTATION_LOG.md) is the system of record for completed work.
When to Update:
- After completing any feature spec (e.g.,
PF-01,RH-02). - After significant refactoring or infrastructure changes.
- After fixing critical security or data integrity issues (especially RLS fixes).
- After adding new components, hooks, or significant UI work.
- After constitution or AI Guide updates.
- AI Trigger: AI assistants MUST update the log as part of feature delivery, not as a separate task.
- Feature ID and completion date.
- Database changes (tables, functions, triggers, RLS policies).
- Components and files created or significantly modified.
- Integration points and dependencies.
- Security considerations and testing status.
- Known limitations or follow-up work.
- Each feature gets its own section under the appropriate phase.
- Use checkboxes (✅, 🔜, 🚨) to indicate status.
- Link to relevant spec files.
- Keep it concise but complete.
- The technical owner of a feature is responsible for updating the log.
- AI assistants MUST propose log updates as part of feature delivery.
- Updates should happen within 24 hours of feature completion.
10. Governance, Versions & AI Alignment
This constitution itself is a living artifact.10.1 Changes to the Constitution
- Changes MUST be made via pull request and explicitly called out as “Constitution Update.”
- Semantic versioning:
- MAJOR: Breaking principle changes or removed principles.
- MINOR: New principles or materially expanded guidance.
- PATCH: Clarifications, wording, typos, non‑semantic fixes.
- Any change MUST:
- Include an updated version line and dates.
- Note impacts on templates, tooling, or working agreements.
10.2 Relationship to AI Guidelines
- This document defines what must be true for the platform.
AI_GUIDE.md(current: see docs/VERSIONS.md) defines how AI agents must behave to stay compliant with this constitution.AGENTS.md(current: see docs/VERSIONS.md) provides a unified quick reference for all AI platforms.- In case of conflict, this constitution wins.
- The canonical cross-platform “What AI Must NEVER Do” list is maintained in
AGENTS.md; this constitution remains the normative source for underlying guardrails.
AGENTS.md and .cursor/rules/constitution.mdc (section-scoped routing).
Additional References:
- Documentation Standards - Documentation standards and best practices
- Documentation Hierarchy - Documentation hierarchy
- Architecture Documentation - System architecture and design principles
- Implementation guide:
docs/development/breadcrumb-implementation-guide.md - Mobile navigation:
docs/development/mobile-navigation-guide.md
10.3 Annual Constitution Review
The constitution is a living document. It must be reviewed annually to prune obsolete sections, incorporate lessons from the prior year, and align with regulatory or architectural changes. Cadence: Once per year, typically in Q1 (January–March). The review is triggered by a GitHub issue created via the issue template below. Review checklist:- Check all §-level cross-references still point to existing files and correct sections
- Verify “What AI Must NEVER Do” in AGENTS.md is consistent with constitution guardrails
- Prune sections made obsolete by platform evolution (mark as
[Deprecated §X.Y]with reason) - Incorporate any ADRs from the past year that modified architectural rules
- Sync
docs/VERSIONS.mdwith the new constitution version number - Run
npm run validate:governanceand confirm all checks pass
Annual Constitution Review — {YEAR} with label governance using this body:
11. Project Structure & Code‑Level Naming
Repository layout and naming are standardized to keep the system navigable.11.1 Directory Structure
At the top level, the repository follows this structure:/src/platform– Platform Foundation (auth, tenancy, navigation, shared services)./cores/rh– Recovery Housing & Operations./fa– Finance & Revenue./hr– Workforce & HRIS./gr– Governance, Compliance & Learning./fw– Forms & Workflow./fm– Facilities, Inventory & Vendors./lo– Leadership Operating System./ce– Community Engagement./it– IT & Security./cl– Clinical & EHR./pm– Practice Management.
/shared– Reusable UI components, hooks, and utilities.
/supabase/migrations– Database migration files (timestamped SQL)./functions– Edge Functions (Deno-based)./seeds– Seed data (non‑PHI, non‑prod only).
/specs- Per‑feature specs and plans organized by core (e.g.,
/specs/rh/specs/RH-01.md).
- Per‑feature specs and plans organized by core (e.g.,
/docs- Architecture, development, deployment, migration, and testing documentation.
/tests- Unit, integration, E2E, RLS, and compliance test suites.
/scripts- Developer tooling, maintenance scripts, and data migration utilities.
11.2 Code‑Level Naming
- Source code directories under
/src/coresMUST mirror the core naming (e.g.,/src/cores/rh/residents,/src/cores/fa/billing). - File names use
kebab-caseorcamelCaseper language and framework norms, but MUST be consistent within a layer. - Domain models and services SHOULD carry explicit domain context (e.g.,
ResidentService,BillingLedger,AuditTrailLogger), not generic names likeManagerorHelper.
12. Automation Governance
Automations that execute business logic must follow strict governance to prevent abuse, outages, and data integrity issues.12.1 Approval for High-Risk Automations
- Webhooks to external systems MUST be approved by org admin
- Updates to critical tables (employees, documents, financials, residents) MUST be approved
- Automations created by non-admin users SHOULD be reviewed before activation
- Approval tracked:
approved_by,approved_at,approval_notes
12.2 Circuit Breaker for Reliability
- All automations MUST have circuit breaker enabled (default behavior)
- Auto-pause after 5 consecutive failures
- Notify creator immediately when circuit trips
- Require manual reset with root cause analysis before re-enabling
12.3 Testing Requirements
- All automations MUST be tested in dry-run mode before activation
- Templates MUST include example trigger data for testing
- Complex workflows (3+ actions) SHOULD have integration tests
- Breaking changes to automation engine MUST have rollback plan
12.4 Audit & Monitoring
- All executions MUST be logged to
fw_automation_logs - Analytics dashboard SHOULD be reviewed weekly by automation owners
- Failed automations (>10% failure rate) MUST be investigated within 24 hours
- External webhooks MUST use HTTPS only (enforced by system)
12.5 Rate Limiting & Resource Protection
- Email actions: Max 100 emails per hour per organization (to be implemented)
- Webhook actions: 30 second timeout enforced
- Record updates: RLS policies enforce tenant isolation
- Scheduled automations: One execution per cron interval (no overlapping runs)
13. Definition of Done
Operational Definition of Done lives indocs/development/DEFINITION_OF_DONE.md— the source of truth for the completion sequence, AC/US/FR verification, and the machine-enforced gates (uiEvidenceGate, signoff markers,verify-acs). This section retains only the non-negotiable guardrails that must hold for every completed change, regardless of pipeline. “Done” means reachable capability, not artifact-existence (§3.1): a feature is complete only when the terminal user action actually works.
13.1 Security guardrails (non-negotiable)
- RLS policies implemented for all new tables
- RLS tests written and passing
- All mutations include
organization_idfilter (defense-in-depth) - No PHI/PII in code, tests, logs, or error messages
- SECURITY DEFINER functions used where needed
- UPDATE policies include WITH CHECK clause
Version: 1.18.0 Ratified: 2025‑11‑24 Last Updated: 2026‑06‑15 Last Amended: 2026‑06‑15 Version History:
- 1.18.0 (2026-06-15): §13 trimmed to non-negotiable security guardrails + a pointer to
docs/development/DEFINITION_OF_DONE.md(now the operational DoD source of truth). Operational checklists (quality/tests/docs/process) moved to the spine so they evolve without a constitutional amendment. Resolves the prior triple-definition DoD drift. - 1.17.2 (2026-06-04): §6 trim pass (ADR-023 extraction): §6.3.1 breadcrumb code patterns → breadcrumb-implementation-guide.md; §6.8 wizard help-component table + checklist → WIZARD_UX_STANDARD.md + WIZARD_DEVELOPMENT_GUIDE.md. All guardrails (when-to-show, mobile-CRITICAL, prohibited patterns, REQUIRED wizard/help standards) kept.
- 1.17.1 (2026-06-04): §5.2 trim pass (ADR-023 extraction): §5.2.3–§5.2.6 reduced to guardrail + target links (settings-pattern-guide.md, DATABASE_DEVELOPMENT_GUIDE.md, PF-15/16/17 specs); ~125 lines moved out, all guardrails kept.
- 1.17.0 (2026-04-12): Added §12.3–§12.5 (Testing Requirements, Audit & Monitoring, Rate Limiting & Resource Protection) to Automation Governance section; TOC alignment.
- 1.16.1 (2026-04-11): Documentation and governance alignment (AI tooling inventory references, spec workflow cross-links). No material change to technical guardrails in §1–§13.
- 1.16.0 (2026-03-29): Added jurisdiction scope language for multi-state Medicaid compliance (PF-96). §1.1: PF owns jurisdiction profile system. §4.3.7: jurisdictionProfileId in AI module context. §5.1: jurisdiction-aware configuration rule (no hardcoded state-specific constants in CL/PM). §5.2.2: jurisdiction profile assignment and resolution order. §5.2.3: decision criteria for jurisdiction profile vs module settings. §7.2: jurisdiction-aware clinical requirements (profile-driven, not AHCCCS-hardcoded).
- 1.15.0 (2026-03-19): Trimmed §6.6 Authentication State Management code blocks to bullets + playbook links (react-patterns.md, AGENTS.md); added DATABASE_DEVELOPMENT_GUIDE.md to CodeRabbit knowledge base.
- 1.14.0 (2026-03-19): Consolidated §5.2 SQL-heavy playbooks into docs/development/DATABASE_DEVELOPMENT_GUIDE.md (Constitution playbook section); trimmed §6.5 code blocks in favor of AGENTS/quick-reference links; reordered §5.2.9 after §5.2.8.
- 1.13.0 (2026-03-06): Public API documentation governance alignment. Added §3.4 Public API Documentation Coverage with 100% baseline requirement for in-scope exported function-like declarations.
- 1.12.0 (2026-02-25): CL-PM architecture formalization. Added encounter entity to §1.2; cross-core database reference rules and CL-PM FK exception (ADR-002); §5.2.7 Cross-Core Database References; ADR requirement in §1.3.
- 1.11.0 (2026-02-07): Added Bulk Import & Data Migration Standards (§5.10).
- 1.7.0 (2026-01-25): Added Test File Naming Conventions (§3.3) with standardized patterns and templates. Added Definition of Done (§13) with comprehensive completion criteria checklist.
- 1.6.1 (2025-12-03): Added LO core to the list of domain cores and updated module settings status table to reflect implemented cores (HR, FW, RH, FA, LO) and planned cores (GR, FM).
- 1.6.0 (2025-01-27): Documented PF-15/16/17 customization infrastructure (picklists, custom fields, entity field configuration) and expanded PWA/mobile requirements and frontend performance patterns.
- 1.3.0 (2025-11-25): Added Automation Governance section (11) covering approval workflows, circuit breakers, testing requirements, and monitoring standards for FW-03 automation engine.
- 1.2.1 (2025-11-24): Added storage bucket naming (5.2), database function naming (5.2), RLS anti-patterns and SECURITY DEFINER guidance (5.7), clarified migration naming for Lovable-generated files (5.3), enhanced AI log update triggers (8.3).
- 1.2.0 (2025-11-23): Added Integration Patterns (1.3), Production Deployment & Rollback (5.5), Performance & Monitoring (5.6), Code Review Standards (7.3), Deprecation Policy (7.4), and Implementation Log Requirements (8.3).
- 1.1.0 (2025-11-23): Initial ratified version with core architecture, testing, security, and database guardrails.