Security Overview
Unified Security for multi-tenant data isolation in Semaphor
Unified Security is Semaphor's model for controlling data access across the platform. It lets you define security policies on a connection, then assign them to specific actors -- tenants, tenant users, or organization users -- so each person sees only the data they should.
Three policy primitives cover the most common multi-tenant isolation patterns:
| Policy | Full Name | What It Controls |
|---|---|---|
| CLS | Connection Level Security | Parameterize database connection strings or file paths per actor |
| SLS | Schema Level Security | Route actors to specific database schemas |
| RLS | Row Level Security | Filter rows with WHERE clause predicates |
You can use these individually or combine them. A tenant might connect to a dedicated database (CLS), operate within a specific schema (SLS), and still have row-level filtering applied (RLS).
How It Works
Unified Security follows a three-step model: define, assign, resolve.
1. Define policies on connections
An admin creates policy definitions on a connection. A policy definition is a reusable template with placeholders for values that vary per actor.
A single policy definition can include CLS, SLS, and RLS rules together, or any subset.
2. Assign policies to actors
An admin creates assignments that bind a policy definition to a specific actor scope and fill in the placeholder values.
For example, assigning the RLS policy definition above to tenant "Acme Corp" with tenant_id = "acme" means every Acme user will have WHERE tenant_id = 'acme' applied to their queries.
3. Resolve at runtime
When a user runs a query, Semaphor resolves their effective security context by collecting all applicable assignments, merging them according to each policy type's rules, and applying the result to the query before execution.
The resolved CLS configures the connection, SLS pins the schema, and RLS predicates are injected as WHERE clauses -- all before the query reaches the database.
Actor Model
Unified Security supports four assignment scopes that target different levels of your user hierarchy:
| Scope | Target | Use Case |
|---|---|---|
ALL_TENANTS | Every tenant in the project | Shared baseline policy (e.g., a common RLS rule) |
TENANT | A specific tenant | Tenant-specific connection params or schema |
TENANT_USER | A specific end user within a tenant | User-level row filtering or access narrowing |
ORG_USER | An organization user | Internal user policies (independent, no inheritance) |
Tenant inheritance
For tenant users, policies inherit and narrow through three layers:
Each layer can only restrict further, never widen access. If a tenant-level policy sets tenant_id = 'acme', a tenant-user policy cannot change it to tenant_id IN ('acme', 'beta'). It can only add additional restrictions like region = 'west'.
This means the tenant boundary is always preserved. Admins define the tenant-wide default, and tenant-user assignments narrow within that boundary.
Organization users
Org-user assignments are independent -- they do not participate in the tenant inheritance chain. If an org user has no assignment, they receive unrestricted access to the connection.
Connection Security Mode
Each connection operates in one of two security modes:
| Mode | Behavior |
|---|---|
legacy | Uses the existing token-based CLS, RCLS, and SLS model |
unified | Uses Unified Security policy definitions and assignments |
This is a per-connection setting, not project-wide. You can migrate connections one at a time while the rest continue using legacy security.
Migration path
- Start with all connections in
legacymode. - Author Unified Security policy definitions and assignments (this has no runtime effect while in
legacy). - Preview the resolved security for different actors to verify correctness.
- Switch the connection to
unifiedmode. - If issues arise, switch back to
legacy-- policy definitions and assignments are preserved.
Policy definitions are inert until assigned
Creating a policy definition does not enforce anything on its own. Enforcement begins
only when an assignment binds a policy definition to an actor and the connection
is in unified mode. Unassigned actors on a unified connection use the base
connection with no Unified Security restrictions.
When to Use What
Choose your policy type based on how your data is organized:
| Data Architecture | Recommended Policy |
|---|---|
| Separate databases per tenant | CLS -- parameterize the connection string |
| Separate schemas per tenant | SLS -- route to the correct schema |
| Shared tables with a tenant identifier column | RLS -- filter rows by tenant |
| Separate databases with shared tables inside | CLS + RLS |
| Separate schemas with user-level filtering | SLS + RLS |
| File-based sources (S3) with tenant folders | CLS -- parameterize file paths |
Most multi-tenant applications need at least one of CLS or SLS for tenant isolation, often combined with RLS for finer-grained access control within the tenant boundary.
Key Concepts
Before diving into configuration, here are the terms you will encounter throughout the security documentation:
- Policy Definition -- A reusable security policy template attached to a connection. Contains CLS, SLS, and/or RLS configuration with placeholder parameters.
- Assignment -- Binds a policy definition to an actor scope (ALL_TENANTS, TENANT, TENANT_USER, or ORG_USER) with concrete parameter values.
- Resolution -- The runtime process that collects applicable assignments for the current actor and merges them into an effective security context.
- Security mode -- The per-connection setting (
legacyorunified) that controls which security model is active.
Next Steps
Policy Types
Learn how CLS, SLS, and RLS work, including combination rules and examples
Policy Definitions & Assignments
Create policy definitions and assign them to actors
Token Integration
Supply runtime parameters and policy overlays through embed tokens
Migration Guide
Migrate from legacy token-based security to Unified Security
Legacy Security
For the legacy security model using token-based CLS, RCLS, and SLS policies, see Multi-Tenancy (Legacy).