Version: 1.2.0 Last Updated: 2026-03-23 Total Functions: 294 (deployable folders underDocumentation Index
Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
Use this file to discover all available pages before exploring further.
supabase/functions/, excluding _shared. Refresh count: npm run docs:edge-functions-count from repo root.)
Reference for Supabase Edge Functions in this repo: deployment, shared code, env/secrets, and patterns. Functions cover integrations, async work, and backend processing.
Table of Contents
- Overview
- Architecture
- Shared Code
- Deployment
- Environment Variables & Secrets
- Error Handling
- Testing
- Monitoring & Logging
- Function Reference
Overview
Edge functions are Deno-based serverless functions deployed to Supabase that handle:- Complex business logic processing
- External API integrations (email, SMS, AI)
- Async workflows and automation
- Scheduled task execution
- Data transformation and aggregation
- Testing and development utilities
- Deno runtime (not Node.js)
- Serverless execution
- Automatic scaling
- CORS support
- JWT verification (configurable per function)
Architecture
Function Structure
Calling Patterns
1. Direct HTTP Invocation:Shared Code
Shared utilities are located insupabase/functions/_shared/ to avoid code duplication.
CORS Headers (_shared/cors.ts)
Standard CORS headers for all functions:
Error Handling (_shared/errors.ts)
Standardized error responses with correlation IDs:
CONFIG- Configuration errorsVALIDATION- Input validation errorsAUTHORIZATION- Permission errorsNOT_FOUND- Resource not foundRUNTIME- Runtime errorsTIMEOUT- Operation timeoutEXTERNAL_SERVICE- External API errors
Logging (_shared/logger.ts)
Structured logging with PHI protection:
Expression Evaluator (_shared/expressionEvaluator.ts)
Expression evaluation for workflow automation:
Deployment
Local Development
Production Deployment
JWT Verification
Configure JWT verification insupabase/config.toml:
verify_jwt = true:
execute-reportprocess-entity-mappingai-assistantworkflow-debug-controlsandbox-executetest-*functionsai-document-analyzeworkflow-metrics-aggregateworkflow-path-aggregateworkflow-version-compare
verify_jwt = false:
- Scheduled tasks (cron jobs)
- Database trigger invocations
- Batch processing functions
Environment Variables & Secrets
Required Secrets
Supabase (Auto-provided):SUPABASE_URL- Project URLSUPABASE_SERVICE_ROLE_KEY- Service role key
ENTRA_CLIENT_SECRET- For Entra/Graph API email (optional)GMAIL_SERVICE_ACCOUNT_JSON- For Gmail API org-level email (optional)- Per-org config in Settings → Integrations;
send-email-notificationand others use sharedemail-provider
TWILIO_ACCOUNT_SID- Twilio account SID (forsend-sms-notification)TWILIO_AUTH_TOKEN- Twilio auth tokenTWILIO_PHONE_NUMBER- Twilio phone number
OPENROUTER_API_KEY- OpenRouter API key (forai-assistant,ai-document-analyze,generate-report-narrative)APP_URL- Application URL for OpenRouter HTTP-Referer attribution (defaults tohttps://encoreos.io)
Setting Secrets
Error Handling
All functions should:- Handle CORS preflight requests
- Use standardized error responses
- Include correlation IDs for tracing
- Never expose PHI/PII in errors
- Return appropriate HTTP status codes
Testing
Unit Testing Edge Functions
Tests are co-located with functions, e.g.supabase/functions/<name>/index.test.ts or <name>_test.ts. Examples: generate-templated-pdf/index.test.ts, hr-encrypt-bank-account/index_test.ts.
Environment: Set VITE_SUPABASE_URL or SUPABASE_URL to http://localhost:54321 and the anon key (from npx supabase status) when testing against local. Some tests also use VITE_SUPABASE_PUBLISHABLE_KEY or TEST_AUTH_TOKEN.
Run from repo root: npm run test:functions (runs deno test for all Edge Function tests). Or run deno test --allow-all from a function directory.
npm run supabase:functions:serve:inspect, then open Chrome → chrome://inspect → Configure 127.0.0.1:8083 → Open dedicated DevTools for Node. Trigger a function to pause on first line and use breakpoints. See EDGE_AND_API_TESTING.md.
Integration Testing
Test functions with real database:- Use test database with seed data
- Verify RLS policies are enforced
- Test error scenarios
- Verify logging output
Troubleshooting (Edge Functions)
- 401/403 locally: Missing or invalid
Authorizationheader; confirm anon key or user JWT; checkverify_jwtif used. - Import errors: Use
npm:orjsr:specifiers and pin versions. - File writes: Only under
/tmp. - Hanging requests: Unawaited Promises; offload background work with
EdgeRuntime.waitUntil(promise).
Monitoring & Logging
Logging Best Practices
-
Use structured logging:
-
Never log PHI/PII:
- ❌
logger.info('Processing user', { name: 'John Doe', ssn: '123-45-6789' }); - ✅
logger.info('Processing user', { userId: 'uuid', orgId: 'uuid' });
- ❌
-
Include correlation IDs:
- Generate UUID for each request
- Include in all log entries
- Return in response headers
-
Log levels:
debug- Development debugginginfo- Normal operationswarn- Warning conditionserror- Error conditions
Monitoring
- Supabase Dashboard: View function logs and metrics
- Error Tracking: Integrate with Sentry/LogRocket
- Performance: Monitor execution time and memory usage
- Alerts: Set up alerts for error rates > 1%
Function Reference
Platform Foundation Functions
admin-reset-password
Purpose: Admin-initiated password reset for users
Input:
true (admin only)
Related Tables: auth.users, pf_profiles
Error Codes:
400- Invalid input403- Insufficient permissions404- User not found500- Reset failed
ai-assistant
Purpose: AI chat integration via OpenRouter (PF-59)
Model Selection: Automatic based on moduleContext.module:
gr,hr→anthropic/claude-3.5-sonnet(compliance/policy reasoning)fa,fw,rh,pf,ce→openai/gpt-4o(general analysis)lo,fm→openai/gpt-4o-mini(fast summaries)
Content-Type: text/event-stream
Output (Non-Streaming):
OPENROUTER_API_KEY(required)APP_URL(optional, defaults tohttps://encoreos.io)
true
PHI Protection: Automatically detects and logs PHI patterns in prompts
Rate Limiting: Exponential backoff retry on 429 (1s, 2s, 4s, max 30s)
Error Codes:
401- Authentication required402- AI credits depleted403- User not in organization429- Rate limited (auto-retry)500- Service error
supabase/functions/_shared/ai-utils.ts
Related Documentation:
specs/pf/PF-27-platform-ai.mdspecs/pf/PF-59-ai-provider-migration.mdsrc/platform/ai/README.md
ai-document-analyze
Purpose: Analyze documents using AI via OpenRouter (PF-59)
Model: openai/gpt-4o (optimized for structured output with tool calling)
Input:
OPENROUTER_API_KEY(required)APP_URL(optional)
true
Multimodal Support: Images (base64), PDFs, text documents
Rate Limiting: Exponential backoff retry on 429
Error Codes:
400- Missing required fields402- AI credits exhausted429- Rate limited500- Service error
pf_documents, pf_ai_usage_logs
Related Documentation: specs/pf/PF-59-ai-provider-migration.md
event-consumer
Purpose: Route domain events to appropriate handlers
Input:
false (called by database triggers)
Event Handlers:
leave_approved→ Updates leave balancesleave_cancelled→ Reverses leave balance changes- Future:
credential_expired,onboarding_completed
docs/architecture/integrations/EVENT_CONTRACTS.md
execute-report
Purpose: Execute report definitions and return results
Input:
true
Related Tables: pf_report_definitions, pf_report_history
send-email-notification
Purpose: Send email notifications via org-configured provider (Entra or Gmail)
Input:
ENTRA_CLIENT_SECRETorGMAIL_SERVICE_ACCOUNT_JSON(per org config; see EMAIL_SMS_SETUP.md)
false (called by notification system)
Error Codes:
400- Invalid email or template500- Email provider (Entra/Gmail) API error
pf_notifications
send-sms-notification (deprecated)
Status: Deprecated. Forwards to sms-send. Use sms-send directly with body { organizationId, toNumber, body, mergeData? }.
Purpose: Legacy SMS notifications (Twilio-only). Now a thin wrapper that invokes sms-send and updates pf_notifications delivery status.
Input: notificationId, phoneNumber, message, variables?, organizationId? (optional; if omitted, looked up from pf_notifications by notificationId).
Output: Same shape as before: { success, messageId, notificationId, status } for backward compatibility.
Migration: Call sms-send with organizationId (from notification or context), toNumber = phoneNumber, body = message after variable substitution, mergeData = variables. After 30 days with no callers, this function will be removed.
send-pending-notifications
Purpose: Batch process pending notifications (email and SMS)
Input:
false (scheduled task)
Scheduled: Daily via pg_cron
Related Tables: pf_notifications
Forms & Workflow Functions
aggregate-form-analytics
Purpose: Aggregate form submission analytics
Input:
false
Related Tables: fw_form_submissions, fw_form_analytics
automation-executor
Purpose: Execute automation rules and workflows (FW-03, FW-06, FW-18)
Input:
false (called by database triggers)
Features:
- Condition evaluation
- Action execution (email, notification, update, webhook)
- Workflow graph execution (FW-06)
- Variable management (FW-18)
- Retry logic
- Circuit breaker
execution_id or event_id, the executor MUST check if that id has already been processed (e.g. in fw_workflow_executions or a processed-events store) and skip duplicate execution. Use exponential backoff (1s, 2s, 4s) on transient failures; handlers must be safe when invoked more than once.
Related Tables: fw_automation_rules, fw_workflows, fw_automation_logs
Related Documentation: specs/fw/specs/FW-03-automation-engine.md, specs/fw/specs/FW-06-visual-workflows.md
process-entity-mapping
Purpose: Create/update entity records from form submissions (FW-03/PF-16)
Input:
true
Features:
- Maps form fields to entity columns
- Supports
custom_fieldsJSONB mapping - Handles create/update/upsert operations
- Template variable resolution
custom_fields
Related Documentation: specs/fw/specs/FW-03-automation-engine.md
validate-form-submission
Purpose: Validate form submissions before processing
Input:
false
Related Tables: fw_forms, fw_form_submissions
workflow-debug-control
Purpose: Debug workflow execution (enable/disable, step through)
Input:
true (admin only)
Related Tables: fw_workflows, fw_workflow_runs
workflow-metrics-aggregate
Purpose: Aggregate workflow performance metrics
Input:
true
Related Tables: fw_workflow_runs, fw_workflow_metrics
workflow-notification-trigger
Purpose: Trigger notifications from workflow nodes
Input:
false (called by workflow executor)
Related Tables: fw_workflow_runs, pf_notifications
workflow-path-aggregate
Purpose: Aggregate workflow execution paths for analytics
Input:
true
Related Tables: fw_workflow_runs
workflow-version-compare
Purpose: Compare workflow versions for changes
Input:
true
Related Tables: fw_workflows, fw_workflow_versions
HR Functions
export-employee-list
Purpose: Export employee list to CSV/Excel
Input:
true
Related Tables: hr_employees, pf_departments
export-payroll-data
Purpose: Export payroll data for external payroll systems
Input:
true (admin only)
Related Tables: hr_timesheets, hr_employees, hr_payroll_exports
generate-schedule
Purpose: Generate shift schedules based on templates and availability
Input:
false (scheduled task)
Related Tables: hr_shift_templates, hr_shifts, hr_employee_availability
generate-timesheets
Purpose: Generate timesheets for pay period
Input:
false (scheduled task)
Scheduled: Weekly (Sunday) via pg_cron
Related Tables: hr_timesheets, hr_time_entries, hr_employees
Database Function: calculate_timesheet_hours()
process-leave-accruals
Purpose: Process leave accruals for all employees
Input:
false (scheduled task)
Scheduled: Monthly (1st of month) via pg_cron
Related Tables: hr_leave_balances, hr_leave_policies, hr_employees
process-swap-request
Purpose: Process shift swap requests and approvals
Input:
false (called by application)
Related Tables: hr_shift_swaps, hr_shifts
send-credential-alerts
Purpose: Send alerts for expiring credentials
Input:
false (scheduled task)
Scheduled: Daily via pg_cron
Related Tables: hr_employee_credentials, hr_employees, pf_notifications
validate-shift-assignment
Purpose: Validate shift assignments (credentials, availability, conflicts)
Input:
false (called by application)
Validation Checks:
- Employee has required credentials
- Employee is available (no conflicts)
- Shift doesn’t exceed max hours
- Site access permissions
hr_shifts, hr_employees, hr_employee_credentials
Finance Functions
check-budget-alerts
Purpose: Check budgets and create alerts for threshold breaches
Input:
false (scheduled task)
Scheduled: Daily via pg_cron
Database Function: fa_check_budget_alerts()
Related Tables: fa_budgets, fa_budget_alerts, pf_organizations
FA scheduled reports (via execute-scheduled-reports)
Purpose: Execute scheduled Finance & Accounting reports. Use the unified execute-scheduled-reports function with body { module: 'fa' }.
Input: Same as execute-scheduled-reports with module: 'fa' in the request body. Cron callers should invoke execute-scheduled-reports with { "module": "fa" }.
Related Tables: fa_report_schedules, fa_report_runs, fa_get_due_scheduled_reports (RPC)
generate-fa-report-export
Purpose: Generate Finance report exports (PDF, Excel, CSV)
Input:
false
Related Tables: fa_reports, pf_documents
parse-bank-statement
Purpose: Parse bank statement files (CSV, OFX, QIF) and extract transactions
Input:
false
Related Tables: fa_bank_accounts, fa_transactions
query-payment-status
Purpose: Query payment status from payment processors
Input:
false
Related Tables: fa_payments, fa_invoices
trigger-invoice-creation
Purpose: Trigger invoice creation from resident charges or other events
Input:
false (called by database triggers)
Related Tables: fa_invoices, rh_resident_charges, rh_residents
Recovery Housing Functions
rh-charge-invoice
Purpose: Create invoices from resident charges
Input:
false
Related Tables: fa_invoices, rh_resident_charges, rh_residents
Facilities Functions
check-overdue-pms
Purpose: Check for overdue preventive maintenance tasks
Input:
false (scheduled task)
Scheduled: Daily via pg_cron
Related Tables: fm_pm_schedules, fm_work_orders
check-vendor-certifications
Purpose: Check vendor certifications for expiration
Input:
false (scheduled task)
Scheduled: Daily via pg_cron
Related Tables: fm_vendors, fm_vendor_certifications, pf_notifications
generate-pm-work-orders
Purpose: Generate work orders from PM schedules
Input:
false (scheduled task)
Scheduled: Daily via pg_cron
Related Tables: fm_pm_schedules, fm_work_orders
Testing Functions
calculate-test-coverage
Purpose: Calculate test coverage metrics
Input:
true (admin only)
Related Tables: Test results database
sandbox-execute
Purpose: Execute code in sandboxed environment for testing
Input:
true (admin only)
Security: Sandboxed execution, no file system access
test-cases-run
Purpose: Run test cases and return results
Input:
true (admin only)
test-datasets-import
Purpose: Import test datasets for testing
Input:
true (admin only)
Note: Only works in development/staging environments
Reporting Functions
execute-scheduled-reports
Purpose: Execute scheduled reports for Platform (PF) or Finance (FA). Single function with request body module to route.
Input:
pf_report_schedules, runs reports, emails via send-email-notification. For FA: calls fa_get_due_scheduled_reports, creates fa_report_runs, updates fa_report_schedules.
Output:
false (scheduled task)
Scheduled: Daily/Weekly/Monthly via pg_cron
Related Tables: pf_report_definitions, pf_report_history
generate-compliance-report
Purpose: Generate compliance reports (HR credentials, RH incidents, etc.)
Input:
false
Related Tables: hr_employee_credentials, rh_significant_events, pf_reports
generate-report-narrative
Purpose: Generate AI-powered narrative summaries for reports via OpenRouter (PF-59)
Model: openai/gpt-4o (for detailed analysis and recommendations)
Input:
OPENROUTER_API_KEY(required)APP_URL(optional)
false (called by scheduled reports)
Rate Limiting: Exponential backoff retry on 429
Error Codes:
400- Missing required fields402- AI credits exhausted429- Rate limited500- Service error
pf_reports, pf_report_narratives, pf_ai_usage_logs
Related Documentation: specs/pf/PF-59-ai-provider-migration.md
System Functions
process-alert-escalations
Purpose: Process alert escalations based on time and severity
Input:
false (scheduled task)
Scheduled: Hourly via pg_cron
Related Tables: pf_alerts, pf_notifications
Function Categories Summary
| Category | Count | Functions |
|---|---|---|
| Platform Foundation | 8 | admin-reset-password, ai-assistant, ai-document-analyze, event-consumer, execute-report, send-email-notification, send-sms-notification, send-pending-notifications |
| Forms & Workflow | 9 | aggregate-form-analytics, automation-executor, process-entity-mapping, validate-form-submission, workflow-debug-control, workflow-metrics-aggregate, workflow-notification-trigger, workflow-path-aggregate, workflow-version-compare |
| HR | 8 | export-employee-list, export-payroll-data, generate-schedule, generate-timesheets, process-leave-accruals, process-swap-request, send-credential-alerts, validate-shift-assignment |
| Finance | 6 | check-budget-alerts, execute-scheduled-reports (module=fa), generate-fa-report-export, parse-bank-statement, query-payment-status, trigger-invoice-creation |
| Recovery Housing | 1 | rh-charge-invoice |
| Facilities | 3 | check-overdue-pms, check-vendor-certifications, generate-pm-work-orders |
| Testing | 4 | calculate-test-coverage, sandbox-execute, test-cases-run, test-datasets-import |
| Reporting | 3 | execute-scheduled-reports, generate-compliance-report, generate-report-narrative |
| System | 1 | process-alert-escalations |
| Total | 43 |
ai-assistant, ai-document-analyze, and generate-report-narrative use OpenRouter for AI capabilities with module-specific model selection. See supabase/functions/_shared/ai-utils.ts for model configuration.
Best Practices
1. Error Handling
- Always use
_shared/errors.tsfor consistent error responses - Include correlation IDs for tracing
- Never expose PHI/PII in error messages
- Return appropriate HTTP status codes
2. Logging
- Use
_shared/logger.tsfor structured logging - Include correlation IDs in all log entries
- Never log PHI/PII (only stable IDs)
- Use appropriate log levels
3. Security
- Validate all inputs
- Enforce JWT verification where appropriate
- Use service role key only when necessary
- Never expose secrets in responses
4. Performance
- Keep execution time under 60 seconds (Supabase limit)
- Use database functions for complex queries
- Batch operations when possible
- Handle timeouts gracefully
5. Testing
- Test with real database (staging)
- Verify RLS policies are enforced
- Test error scenarios
- Verify logging output
Troubleshooting
Common Issues
1. Function Timeout- Symptom: Function returns 504 after 60 seconds
- Solution: Break into smaller functions, use database functions for heavy processing
- Symptom: Browser blocks requests
- Solution: Ensure CORS headers are included in all responses
- Symptom: 401 Unauthorized
- Solution: Check
verify_jwtsetting inconfig.toml, ensure valid JWT in request
- Symptom: Function fails with “not configured” error
- Solution: Set secrets via
supabase secrets set KEY=value
- Symptom: Function can’t connect to database
- Solution: Verify
SUPABASE_URLandSUPABASE_SERVICE_ROLE_KEYare set
Related Documentation
- Constitution:
constitution.md§5.8-5.9 (Edge Function Patterns) - AI Guide:
AI_GUIDE.md(Edge Function Patterns) - Integration Contracts:
docs/architecture/integrations/EVENT_CONTRACTS.md - Supabase Setup:
docs/integrations/SUPABASE_SETUP.md(when created)
Document Owner: Platform Team
Review Frequency: Quarterly
Last Updated: 2026-02-01