Stow.Row-Level Security: How Stow Keeps Multi-Tenant AI Data Isolated
SecurityApril 19, 20265 min read

Row-Level Security: How Stow Keeps Multi-Tenant AI Data Isolated

In a platform where multiple users' AI agents run simultaneously, the most important security guarantee is that one user's agent can never touch another's data. Stow enforces this at the database level.

Stow Logo

Stow is a multi-tenant platform — multiple users' AI agents operate simultaneously against a shared infrastructure. The most fundamental security requirement in that environment is data isolation: your agent can only ever see your configurations, your credentials, your activity logs. Never another user's.

That guarantee is enforced at the database layer through Row-Level Security (RLS) — not at the application layer, not through access control lists, but through policies baked into the database itself.

What Row-Level Security Is

Row-Level Security is a Postgres feature that restricts which rows a database session can access — regardless of which application queries are made. When RLS is enabled on a table, every query against that table is automatically filtered through a policy defined at the database level.

The key word is automatically. Application code can't bypass RLS by constructing a clever query. The restriction is enforced by the database engine itself, before any data is returned. Even if application code contained a bug that attempted to access another user's data, the database would return an empty result set.

How It Works in Practice

1

JWT Contains User Identity

Every request to the Stow platform carries a JWT (JSON Web Token) with the authenticated user's ID. This token is verified using asymmetric RS256/ES256 key pairs from the JWKS endpoint.

2

Database Session Sets User Context

The user's ID from the JWT is set as a session variable in the Postgres connection. This tells the database who is making the current request.

3

RLS Policies Filter Every Query

Every table with user-owned data has an RLS policy that compares the row's user_id column to the session variable. Rows that don't match the current user are invisible to the query.

4

No Application Override Possible

The filter happens at the database engine level. Application code cannot bypass it — it's not a WHERE clause the app adds, it's a policy the database enforces.

What RLS Protects in Stow

AI Agent Configurations

Your agent definitions, names, icons, and settings are invisible to other users.

Service Credentials

OAuth tokens, API keys, and personal access tokens for your connected services are isolated per user.

Permission Policies

Your per-service permission configurations are user-scoped. Another user cannot read or modify your policy toggles.

Activity Logs

Your activity history — every tool call your agents have made — is inaccessible to other users.

Approval Queues

Pending approval requests and their outcomes are private to the user who owns the agent.

Security Baselines

The network fingerprints captured for your agents are user-scoped and not visible to others.

Why Application-Layer Isolation Isn't Enough

Many multi-tenant platforms implement tenant isolation at the application layer — every query includes a WHERE clause filtering by the current user's ID. This works until it doesn't: a missing WHERE clause in one endpoint, a code path that bypasses the filter, or a bug introduced during refactoring can expose another user's data.

RLS moves the filter to the database itself. The application still applies its own filters as a matter of good practice, but they're a secondary layer. The database is the enforcer, and it doesn't have bugs introduced by application developers forgetting to add a WHERE clause.

Supabase and the RLS Implementation

Stow's database layer is built on Supabase, which provides Postgres with RLS as a first-class feature. The JWT verification uses Supabase's built-in JWKS endpoint, which rotates keys using RS256/ES256 asymmetric cryptography. This means:

  • There are no symmetric secrets that could be leaked to compromise token verification
  • Key rotation happens without downtime or secret distribution
  • The trust chain runs from the user's session → JWT → JWKS verification → Postgres session variable → RLS policy

Every step in that chain is cryptographically grounded. The result is isolation that doesn't depend on application code getting it right every time.

Your Data Is Yours. At the Database Level.

Multi-tenant isolation enforced by Postgres, not application code. No clever query bypasses it.

S

Stow Security Team

April 19, 2026