Security

Nucleus provides defense-in-depth security: row-level security (RLS), column-level data masking, tenant-aware encryption, and immutable audit logging.

Row-Level Security (RLS)

Control which rows each user can see and modify.

Enable RLS

ENABLE RLS ON patients;

Create Policies

-- Doctors can see all patients
CREATE POLICY doctor_read ON patients
    FOR SELECT
    TO doctor
    USING (true);

-- Patients can only see their own records
CREATE POLICY patient_read ON patients
    FOR SELECT
    TO patient
    USING (patient_id = current_user_id());

-- Nurses can only see patients in their department
CREATE POLICY nurse_read ON patients
    FOR SELECT
    TO nurse
    USING (department = current_tenant());

Policy Types

| Type | Behavior | |------|----------| | Permissive (default) | At least one permissive policy must pass | | Restrictive | All restrictive policies must pass |

Policies combine: (any permissive passes) AND (all restrictive pass).

Predicate Types

| Predicate | Description | |-----------|-------------| | column = 'value' | Column equals constant | | column = current_user() | Column matches session user | | column = current_tenant() | Column matches session tenant | | has_role('admin') | Session must have role | | Combined with AND / OR | Compose predicates |

Superuser Bypass

Users with the superuser role bypass all RLS policies.

Column-Level Data Masking

Mask sensitive columns based on the querying user's role.

Masking Rules

| Rule | Input | Output | |------|-------|--------| | Redact | 555-0123 | [REDACTED] | | Email | tyler@example.com | t***@example.com | | Partial (show first 2, last 2) | 555-0123 | 55****23 | | Hash | John Smith | a1b2c3d4 |

Apply Masking

-- Analysts see masked SSNs
CREATE MASKING POLICY ssn_mask ON employees(ssn)
    FOR ROLE analyst
    USING PARTIAL(show_first=0, show_last=4, mask_char='*');

-- Support staff see masked emails
CREATE MASKING POLICY email_mask ON customers(email)
    FOR ROLE support
    USING EMAIL;

Masking is applied transparently — queries return masked values without application code changes.

Encryption

Tenant-Aware Key Management

Nucleus supports per-tenant encryption keys with rotation:

-- Register a tenant key
SELECT register_tenant_key('tenant_42', decode('...base64key...', 'base64'));

-- Rotate to a new key (old key archived for decryption)
SELECT rotate_key('tenant_42', decode('...newkey...', 'base64'));

Key Rotation

Key rotation is a managed process:

  1. Begin — New key registered, old key marked for archival
  2. Re-encrypt — Pages re-encrypted in background (progress tracked)
  3. Complete — Old key archived, new key active

Old keys are retained for decrypting data written before rotation.

Encrypted Indexes

Nucleus supports encrypted indexes that store index entries in ciphertext. Search operations decrypt at query time — the index file on disk contains no plaintext.

Audit Logging

Immutable, append-only audit log for compliance and forensics.

What's Logged

Every query execution records:

| Field | Description | |-------|-------------| | timestamp | When the query ran | | user | Who ran it | | action | Query type (SELECT, INSERT, UPDATE, DELETE, DDL) | | table | Affected table | | query | Full SQL text | | rows_affected | Number of rows modified | | success | Whether the query succeeded |

Querying the Audit Log

-- Recent activity by user
SELECT * FROM nucleus_audit_log WHERE user = 'alice' ORDER BY timestamp DESC LIMIT 100;

-- All changes to a table
SELECT * FROM nucleus_audit_log WHERE table_name = 'patients' AND action IN ('INSERT', 'UPDATE', 'DELETE');

Audit entries are immutable — they cannot be updated or deleted.

Session Context

Security features use session context to evaluate policies:

-- Set session properties
SET SESSION user = 'alice';
SET SESSION role = 'doctor';
SET SESSION tenant_id = 'hospital_42';

Context properties available to RLS predicates and masking rules:

| Function | Returns | |----------|---------| | current_user() | Session user | | current_tenant() | Session tenant ID | | has_role('name') | Whether session has role |

Cluster Security

Inter-Node TLS

In clustered deployments, replication traffic is encrypted with TLS. Configure via:

[cluster.tls]
cert = "/path/to/node.crt"
key = "/path/to/node.key"
ca = "/path/to/ca.crt"

All Raft messages, WAL streaming, and gossip use encrypted channels.