Skip to main content

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:

  1. Every tenant table includes an org_id column
  2. A RESTRICTIVE RLS policy ensures that only rows matching the current user's org_id are visible
  3. The current user's org_id is determined from the authenticated user's profile at query time
  4. RESTRICTIVE policies compound with other policies - meaning even if a permissive policy grants broader access, the org_id restriction 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:

ModuleTables Protected
User ManagementProfiles, roles, permissions, role mappings
CRMContacts, companies, deals, pipelines, stages, tasks, activities
CommunicationsEmail messages, WhatsApp messages, chat threads, templates
FinanceInvoices, expenses (company and employee), subscriptions, approvals
HR ManagementEmployees, departments, leave requests, attendance, payroll
ProjectsIssues, boards, sprints, time tracking, documents
SupportTickets, SLA configurations, knowledge base
MarketingCampaigns, email lists, analytics
OperationsWorkflows, automation rules
AI & KnowledgeKnowledge base entries, AI configuration
PlatformGlobal 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:

  1. User makes a request from the NearSync frontend
  2. The Supabase client attaches the user's JWT to the request
  3. Supabase validates the JWT and establishes the authenticated context
  4. The SQL query executes against the requested table
  5. RLS policies evaluate: does the user's org_id match the row's org_id?
  6. Only matching rows are returned; all other rows are invisible to the query
  7. 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.