Row-Level Security
NearSync enforces data isolation at the PostgreSQL level using Row-Level Security (RLS) policies. Every database table has RLS enabled, and policies control which rows a user can read, insert, update, or delete based on their authenticated context.
Why RLS Matters
RLS is the last line of defense for data isolation. Even if there is a bug in the application code, a misconfigured API endpoint, or a compromised client-side check, the database itself will refuse to return rows that do not belong to the requesting user's organization.
This is a critical distinction from application-level access control alone. With RLS:
- Direct database queries (via Supabase client, REST API, or SQL) respect the same access rules
- No amount of client-side manipulation can bypass data isolation
- Cross-tenant data leakage is prevented at the lowest possible layer
How RLS Works in NearSync
Organization Isolation (Managed Multi-Tenant)
In the managed deployment model, all organizations share a single database. Tenant data isolation is enforced by the org_id column present on every tenant-scoped table.
The standard isolation pattern works as follows:
- Every tenant table includes an
org_idcolumn - A RESTRICTIVE RLS policy ensures that only rows matching the current user's
org_idare visible - The current user's
org_idis determined from the authenticated user's profile at query time - RESTRICTIVE policies compound with other policies - meaning even if a permissive policy grants broader access, the
org_idrestriction cannot be overridden
RESTRICTIVE vs. PERMISSIVE policies: PostgreSQL supports two policy types. NearSync uses RESTRICTIVE policies for tenant isolation, which means they must ALL pass for a row to be accessible. A permissive policy on the same table cannot grant access to another organization's rows.
Full Isolation (BYOK)
In the BYOK model, each client has their own database. RLS policies are still applied (for user-level access control within the organization), but cross-tenant isolation is inherently guaranteed by database separation.
Coverage
RLS is enabled on tenant-scoped tables across all modules:
| Module | Tables Protected |
|---|---|
| User Management | Profiles, roles, permissions, role mappings |
| CRM | Contacts, companies, deals, pipelines, stages, tasks, activities |
| Communications | Email messages, WhatsApp messages, chat threads, templates |
| Finance | Invoices, expenses (company and employee), subscriptions, approvals |
| HR Management | Employees, departments, leave requests, attendance, payroll |
| Projects | Issues, boards, sprints, time tracking, documents |
| Support | Tickets, SLA configurations, knowledge base |
| Marketing | Campaigns, email lists, analytics |
| Operations | Workflows, automation rules |
| AI & Knowledge | Knowledge base entries, AI configuration |
| Platform | Global settings, system manifest, invitations, audit logs |
Isolation Verification
NearSync maintains an automated test suite that verifies tenant isolation across critical tables. The test suite:
- Creates test data belonging to different organizations
- Attempts cross-organization data access via the Supabase client
- Verifies that queries return zero rows when accessing another organization's data
- Covers 15 critical tables including profiles, CRM records, financial data, HR records, project issues, and support tickets
Test results: 588+ tests with 100% pass rate.
Policy Patterns
NearSync uses several RLS policy patterns depending on the table's requirements:
Tenant Isolation
Applied to all tenant-scoped tables. Ensures users can only access rows belonging to their organization. This is the foundational policy applied to every table that stores business data.
Role-Based Access
Applied to sensitive tables where not all users within an organization should have the same access. These policies check the user's role in addition to their organization membership.
Append-Only Audit
Applied to audit log tables. Users can insert new audit records but cannot update or delete existing ones, preserving the integrity of the audit trail.
Public Read
Applied to a small number of tables that need to be readable without authentication (e.g., public booking availability, document verification). Write operations on these tables still require authentication.
Managed Multi-Tenant Data Flow
Here is how a typical data request flows through the RLS layer in the managed model:
- User makes a request from the NearSync frontend
- The Supabase client attaches the user's JWT to the request
- Supabase validates the JWT and establishes the authenticated context
- The SQL query executes against the requested table
- RLS policies evaluate: does the user's
org_idmatch the row'sorg_id? - Only matching rows are returned; all other rows are invisible to the query
- The result is returned to the frontend
At no point does application code filter by org_id manually. The database handles isolation transparently.
Known Limitations
- Client-side module gating is enforced in the UI layer only, not at the Edge Function level. This means that if a user crafts a direct API request to an Edge Function for a module they should not have access to, the request will succeed if the underlying RLS policies permit the data access. Module-level server-side gating is planned for a future release.
Related Pages
- RBAC & Permissions - role-based access that works alongside RLS
- Security Overview - how RLS fits into the defense-in-depth model
- Data Sovereignty - RLS in the context of BYOK deployments