Skip to main content

Permission Model

Sorcia uses multi-layered security to ensure users only see documents they’re authorized to access.

Permission Layers

Layer 1: Organization Membership

Database-level isolation using Row-Level Security (RLS):
-- Policy ensures users only access their org's data
CREATE POLICY org_isolation ON documents
FOR SELECT USING (
  organization_id = current_user_org_id()
);

Layer 2: Access Control Lists (ACLs)

Document-level permissions:
interface ACL {
  document_id: string;
  principal_type: 'user' | 'group' | 'channel';
  principal_id: string;
}
Example:
Document: "Sales Strategy 2024"
ACLs:
  - user:john@company.com
  - group:sales-team
  - channel:C123ABC (Slack)

Layer 3: Source Permissions

Mirrors original system permissions:
  • Public channel → All workspace members
  • Private channel → Only channel members
  • DMs → Never indexed

User Roles

Organization Roles

RolePermissions
OwnerFull admin access, billing, delete org
AdminManage integrations, invite users, configure
MemberQuery knowledge base, view own history

Custom Permission Groups

Create groups for fine-grained control:
Sales Team:
  members:
    - john@company.com
    - sarah@company.com
  integrations:
    google-drive: /Sales/*
    slack: #sales, #sales-emea
    notion: Sales Playbook
  permissions:
    query: true
    export: false
    analytics: team_only

Permission Sync

Real-Time Sync

Permissions updated when:
  • User added/removed from Slack channel
  • Google Drive file sharing changes
  • Notion page permissions modified
Sync Method:

Daily Reconciliation

Full permission audit runs nightly:
  1. Fetch all ACLs from source systems
  2. Compare with Sorcia’s ACL table
  3. Update differences
  4. Log changes for audit

Query-Time Filtering

Every search automatically filters by permissions:
SELECT d.*
FROM documents d
WHERE d.organization_id = $org_id
  AND (
    -- User has direct access
    EXISTS (
      SELECT 1 FROM acls
      WHERE document_id = d.id
        AND principal_id = $user_id
    )
    OR
    -- User's group has access
    EXISTS (
      SELECT 1 FROM acls
      WHERE document_id = d.id
        AND principal_id IN ($user_groups)
    )
  );

Audit Logging

All queries are logged:
interface QueryLog {
  id: string;
  user_id: string;
  organization_id: string;
  question: string;
  sources_accessed: number;
  documents_returned: string[];
  timestamp: Date;
}
Retention: 90 days (configurable)

Best Practices

Manage permissions via groups (e.g., “Engineering”, “Sales”) rather than individual users
Grant minimum necessary access. Users can always request more.
Review permissions quarterly. Remove access for departed team members.
Check audit logs for unusual access patterns

Common Scenarios

New Employee

1

Invite to Sorcia

Admin sends invitation
2

Auto-Assigned Groups

User automatically added to department group
3

Inherit Permissions

User gets access to all group documents

Sensitive Document

1

Restrict in Source

Limit access in Google Drive/Notion
2

Sync Permissions

Sorcia automatically mirrors restrictions
3

Verify

Test with non-privileged user account

Department Data

Engineering Department:
  members: [eng-team]
  sources:
    github: all repos
    slack: #engineering, #dev-ops
    notion: Engineering Wiki
  restrictions:
    exclude_slack: #sales, #hr
    exclude_drive: /Sales/*, /HR/*

Troubleshooting

Check:
  • User is org member
  • Source permissions are correct
  • ACLs have synced (wait 1-2 min)
  • Document isn’t excluded via filters
Cause: User has broad accessSolution: Use filters or create restricted permission groups
Fix: Manual re-sync via Integrations → Configure → Sync Permissions

Security Guarantees

No data leakage - Users never see unauthorized documentsAutomatic sync - Permissions update in real-timeSource-of-truth - Respects original system permissionsAudit trail - All access logged for compliance

Next Steps