---
type: "Reference"
title: "Security"
openwiki_generated: true
verified:
  - by: openwiki/0.7.2
    at: 2026-10-14T20:42:32.326Z
---


## Overview

Company OS enforces security through three core mechanisms:
1. **Tenant isolation** via Row-Level Security (RLS) in PostgreSQL
2. **Principal identity resolution** across communication channels
3. **Factory principal capability restrictions**

## Tenant Isolation

As specified in ADR-0001 §3.1 (THE-6), tenant isolation is achieved by:
- Row-Level Security (RLS) policies on all tables in the `os` schema and any application schema containing tenant data
- A mandatory `tenant_id` column on every table storing tenant-scoped data
- A `TenantContext` Effect-service that scopes every database connection via `SET LOCAL app.tenant_id = <current_tenant_id>`
- Compile-time enforcement: queries executed without an active `TenantContext` are rejected

This ensures that application bugs cannot lead to cross-tenant data leaks, as RLS acts as a defense-in-depth mechanism.

Evidence: 
- ADR-0001 §3.1: "Row-Level Security in Postgres + `tenant_id` in elke tabel van schema `os` en van elke app die tenant-data bevat + een verplichte `TenantContext`-Effect-service die elke databaseverbinding scoped (`SET LOCAL app.tenant_id`). Een query zonder `TenantContext` compileert niet."
- Acceptance test: "principal van tenant A leest een rij van tenant B via een bewust verkeerde app-query → RLS weigert."

## Principal Identity Resolution

As specified in ADR-0001 §3.2 (THE-7), the OS resolves identities from various channels (WhatsApp, Teams, Better Auth, etc.) to a unified principal model:
- Core tables:
  - `principal`: stores `id`, `tenant_id`, `class` (user|agent|factory), and `verantwoordelijke_principal_id` (responsible human)
  - `principal_identity`: links a principal to external identities via `(principal_id, provider, external_id)`
  - `agent_credential`: stores credentials for agent principals
- Identity resolution is explicit: a channel identifier (e.g., WhatsApp number) must be explicitly linked to a principal by a tenant-admin; the OS never auto-creates principals
- The same human user may have multiple channel identities (e.g., WhatsApp and Teams) that resolve to the same principal

Evidence:
- ADR-0001 §3.2: "Voorstel: `principal (id, tenant_id, class: user|agent|factory, verantwoordelijke_principal_id)`, `principal_identity (principal_id, provider, external_id)` en `agent_credential (principal_id, …)` op dag één. Een WhatsApp-nummer, Teams-user en Better Auth-sessie resolven naar dezelfde principal of worden geweigerd; het OS maakt nooit impliciet een principal aan. Alleen een tenant-admin koppelt identiteiten."

## Factory Principal Restrictions

As specified in ADR-0001 §3.4 (THE-9), factory principals are restricted to dev-tooling capabilities:
- Principals of class `factory` are only granted capabilities where `target: dev-tooling` (e.g., Linear, GitHub, CI, deploy)
- The registry permission check rejects any attempt by a factory principal to invoke a capability with `target: tenant-app` (which accesses tenant data)
- This enforcement occurs at the registry level, not via prompt filtering, ensuring systemic security

Evidence:
- ADR-0001 §3.4: "Voorstel: principal-klasse `factory` krijgt alleen capabilities met `target: dev-tooling` (Linear, GitHub, CI, deploy). Capabilities met `target: tenant-app` weigeren een factory-principal in de registry-permissiecheck, niet in een prompt. Acceptatietest: factory-principal roept `search_aanvragen` aan → `denied` met Receipt."

## Implementation Status

As of the current codebase:
- The authentication tables (`user`, `session`, `account`, `verification`) exist in the public schema (see `/packages/db/src/schema/auth.ts`)
- The OS schema (`principal`, `principal_identity`, `agent_credential`) and RLS policies are planned for implementation in slice 1 (see ADR-0001 §5)

## Related Systems

- [[/openwiki/systems/auth.md|Authentication]]: Better Auth integration for user sessions
- [[/openwiki/systems/database.md|Database]]: PostgreSQL usage and schema design
- [[/openwiki/concepts/one-way-doors.md|One-way Doors]]: THE-6 (tenant isolation) is a one-way door decision
