> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Encore OS - Security Architecture

> This directory contains security documentation for the Encore OS Platform.

This directory contains security documentation for the Encore OS Platform.

***

## Overview

Encore OS implements defense-in-depth security with multiple layers:

1. **Authentication & Authorization** (PF-02 RBAC)
2. **Multi-Tenant Data Isolation** (Row-Level Security)
3. **Input Validation & Sanitization**
4. **Audit Logging** (PF-04)
5. **Edge Function Security**
6. **Database Security**

***

## Security Documents

### [Reporting Security](/security/REPORTING_SECURITY)

Guide to the Reporting Engine's security measures:

* Parameterized query execution (SQL injection prevention)
* Query complexity validation
* Enhanced audit logging
* Database function security (SECURITY DEFINER)
* Incident response procedures

**Key Controls:**

* Max 5 JOINs, 3 subqueries per query
* 10,000 row limit, 30-second timeout
* Blocks dangerous keywords (DROP, ALTER, GRANT, etc.)
* All executions logged with full SQL and parameters

***

### [Automation Security](/security/AUTOMATION_SECURITY)

Security architecture for the Forms & Workflow Automation Engine:

* Trigger isolation (organization/site scoped)
* RLS enforcement on all actions
* Action execution controls (email, webhook, record update)
* Safe condition evaluation (injection prevention)
* Incident response playbook

**Key Controls:**

* Email sender validation
* HTTPS-only webhooks
* Dynamic value resolution without code execution
* Rate limiting recommendations
* Comprehensive execution logging

***

## Security Principles

### 1. Least Privilege

* Users only access data within their organization
* Role-based permissions (platform\_admin → readonly)
* SECURITY DEFINER functions minimize privilege escalation

### 2. Defense in Depth

* Multiple security layers (RLS + application + edge function)
* Input validation at every boundary
* Audit logging for accountability

### 3. Fail Secure

* Errors don't leak sensitive data
* Default deny (RLS policies must explicitly grant access)
* Graceful degradation (failed emails don't break workflows)

### 4. Zero Trust

* Every request validated (JWT auth + RLS)
* No implicit trust between modules
* Service role used only in edge functions

***

## Row-Level Security (RLS)

### Multi-Tenant Isolation Pattern

**Every business table follows this pattern:**

```sql theme={null}
CREATE POLICY "org_isolation"
ON table_name
FOR SELECT
TO authenticated
USING (
  organization_id IN (
    SELECT organization_id 
    FROM pf_user_roles 
    WHERE user_id = auth.uid()
  )
);
```

**Key Points:**

* All tables have `organization_id` column
* RLS enabled on all business tables
* Site-scoped data also includes `site_id`
* SECURITY DEFINER functions prevent recursion

### Critical Anti-Pattern: Avoid RLS Recursion

**❌ WRONG: Recursive RLS (causes infinite loop)**

```sql theme={null}
CREATE POLICY "document_org_access" ON pf_documents
FOR SELECT USING (
  organization_id IN (
    SELECT organization_id FROM pf_user_roles 
    WHERE user_id = auth.uid()  -- pf_user_roles has RLS!
  )
);
```

**✅ CORRECT: Use SECURITY DEFINER function**

```sql theme={null}
CREATE FUNCTION has_org_access(org_id uuid, user_id uuid)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
  RETURN EXISTS (
    SELECT 1 FROM pf_user_roles
    WHERE pf_user_roles.organization_id = org_id
      AND pf_user_roles.user_id = user_id
  );
END;
$$;

CREATE POLICY "document_org_access" ON pf_documents
FOR SELECT USING (has_org_access(organization_id, auth.uid()));
```

***

## Edge Function Security

### Authentication

* JWT verification enabled by default (`verify_jwt = true`)
* System services disable JWT (`verify_jwt = false`)
* Service role used for cron jobs

### Secrets Management

* Never hardcode secrets in code
* Use Supabase environment variables
* Secrets accessed via `Deno.env.get('SECRET_NAME')`

### Example: Secure Edge Function

```typescript theme={null}
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';

Deno.serve(async (req) => {
  // 1. Verify authentication
  const authHeader = req.headers.get('Authorization');
  if (!authHeader) {
    return new Response('Unauthorized', { status: 401 });
  }

  // 2. Create client with user's JWT
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL')!,
    Deno.env.get('SUPABASE_ANON_KEY')!,
    { global: { headers: { Authorization: authHeader } } }
  );

  // 3. RLS automatically enforces access control
  const { data, error } = await supabase
    .from('fw_forms')
    .select('*');

  // 4. User only sees forms in their organization
  return new Response(JSON.stringify(data), {
    headers: { 'Content-Type': 'application/json' }
  });
});
```

***

## Input Validation

### Client-Side (React Hook Form + Zod)

```typescript theme={null}
const formSchema = z.object({
  email: z.string().email(),
  age: z.number().min(18).max(120),
  role: z.enum(['staff', 'admin', 'readonly'])
});

// TypeScript enforces types
const { register, handleSubmit } = useForm<FormData>({
  resolver: zodResolver(formSchema)
});
```

### Server-Side (Edge Functions)

```typescript theme={null}
// Validate parameters
const body = await req.json();
if (!body.report_id || typeof body.report_id !== 'string') {
  return new Response('Invalid report_id', { status: 400 });
}

// Sanitize SQL parameters (use parameterized queries)
const { data } = await supabase.rpc('execute_report_query', {
  sql: 'SELECT * FROM residents WHERE name = $1',
  params: [body.user_input] // Safe: treated as literal value
});
```

### Database (CHECK Constraints & Validation Triggers)

```sql theme={null}
-- Use validation triggers (not CHECK constraints) for time-based validations
CREATE TRIGGER validate_expiration
BEFORE INSERT OR UPDATE ON hr_employee_credentials
FOR EACH ROW
EXECUTE FUNCTION validate_expiration_date();
```

***

## Audit Logging (PF-04)

### Automatic Logging (Triggers)

All critical tables have audit triggers:

```sql theme={null}
CREATE TRIGGER audit_fw_forms
AFTER INSERT OR UPDATE OR DELETE ON fw_forms
FOR EACH ROW
EXECUTE FUNCTION log_audit_event();
```

**What Gets Logged:**

* User ID (`auth.uid()`)
* Organization ID
* Action (insert, update, delete)
* Table name and record ID
* OLD and NEW values (full JSONB)
* Timestamp

### Manual Logging (Application Code)

```typescript theme={null}
await supabase.rpc('log_audit_event', {
  action: 'resident_admitted',
  module: 'rh',
  table_name: 'rh_residents',
  record_id: residentId,
  new_values: { phase: 'intake', bed_id: bedId }
});
```

***

## Incident Response

### Security Incident Classification

**Critical (P0):**

* Data breach or unauthorized access
* SQL injection exploit
* Authentication bypass
* Cross-organization data leak

**High (P1):**

* RLS policy misconfiguration
* Exposed secrets
* Privilege escalation
* Malicious automation rule

**Medium (P2):**

* Failed login attempts (brute force)
* Excessive automation failures
* Suspicious audit log patterns

**Low (P3):**

* Non-critical validation errors
* Quota limit exceeded

### Incident Response Procedures

#### 1. Detection

* Monitor audit logs for suspicious activity
* Alert on failed authentication (> 10 attempts/hour)
* Track automation execution failures
* Review report execution logs for SQL injection attempts

#### 2. Containment

* Disable affected user accounts
* Pause automation rules
* Block malicious IP addresses
* Rotate compromised secrets

#### 3. Investigation

* Query `pf_audit_logs` for full timeline
* Review edge function logs
* Check database RLS policies
* Analyze network traffic

#### 4. Recovery

* Restore from backup if data corrupted
* Re-enable services after patching
* Notify affected users (if required by law)

#### 5. Post-Incident

* Document root cause
* Update security policies
* Implement additional controls
* Train team on lessons learned

***

## Security Checklist for New Features

Before deploying any new feature, verify:

### Database

* [ ] All tables have `organization_id`
* [ ] RLS policies enabled
* [ ] SECURITY DEFINER functions used (avoid recursion)
* [ ] Validation triggers for time-based checks
* [ ] Audit triggers attached
* [ ] Indexes on `organization_id` for performance

### Edge Functions

* [ ] JWT verification enabled (unless system service)
* [ ] Input validation on all parameters
* [ ] Parameterized queries (no string interpolation)
* [ ] Error messages don't leak sensitive data
* [ ] Secrets loaded from environment variables
* [ ] CORS configured correctly

### Frontend

* [ ] Forms use Zod validation
* [ ] TypeScript types enforce data structure
* [ ] No hardcoded secrets
* [ ] Error boundaries catch exceptions
* [ ] User feedback doesn't expose internals

### Integration

* [ ] Cross-core communication via Platform Layer
* [ ] Event payloads include `organization_id`
* [ ] Webhooks use HTTPS only
* [ ] External API calls use secure credentials

### Testing

* [ ] RLS tests verify tenant isolation
* [ ] SQL injection tests confirm prevention
* [ ] Error handling tests cover edge cases
* [ ] Performance tests meet SLAs

***

## Threat Model

### Threats Mitigated

✅ **SQL Injection**

* Parameterized queries in reporting engine
* No dynamic SQL construction
* Database function restrictions

✅ **Cross-Tenant Data Access**

* RLS policies enforce isolation
* All queries scoped to `organization_id`
* Service role only in trusted edge functions

✅ **Privilege Escalation**

* Role-based access control (RBAC)
* SECURITY DEFINER functions minimize scope
* Manager access limited to direct reports

✅ **Code Injection**

* Dynamic value resolution uses safe patterns
* No `eval()` or `Function()` constructors
* HTTPS-only webhooks

✅ **Sensitive Data Exposure**

* PHI/PII not logged in free text
* Error messages sanitized
* Audit logs use structured data

### Threats Not Yet Mitigated

⚠️ **Rate Limiting**

* No global rate limits on API calls
* No per-user/org limits on reports
* Mitigation: Monitor usage, add limits in production

⚠️ **Advanced Persistent Threats (APT)**

* No intrusion detection system (IDS)
* No anomaly detection
* Mitigation: Use Supabase security advisory alerts

⚠️ **DDoS Protection**

* Relies on Supabase infrastructure
* No custom DDoS mitigation
* Mitigation: Leverage Supabase's CDN and rate limiting

***

## Security Resources

### Internal

* [REPORTING\_SECURITY.md](/security/REPORTING_SECURITY) - Reporting Engine security
* [AUTOMATION\_SECURITY.md](/security/AUTOMATION_SECURITY) - Automation Engine security
* [PF-02 RBAC Spec](https://github.com/Encore-OS/encoreos/blob/development/specs/pf/specs/PF-02-rbac.md) - Role-based access control
* [PF-04 Audit Logging Spec](https://github.com/Encore-OS/encoreos/blob/development/specs/pf/specs/PF-04-audit-logging.md) - Audit logging

### External

* [OWASP Top 10](https://owasp.org/www-project-top-ten/) - Common web vulnerabilities
* [Supabase Security](https://supabase.com/docs/guides/platform/security) - Platform security features
* [PostgreSQL RLS](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) - Row-level security docs
* [NIST Cybersecurity Framework](https://www.nist.gov/cyberframework) - Security standards

***

## Contact

For security concerns or to report vulnerabilities:

* Email: [security@encoreos.example.com](mailto:security@encoreos.example.com)
* Incident Response Team: Available 24/7
* Severity: Tag as \[SECURITY] in subject line

**Do not** disclose vulnerabilities publicly until patched.

***

**Last Updated:** 2025-11-25\
**Next Review:** 2026-02-25 (Quarterly)
