Skip to main content

Sharing and Access Control Flow

How resource sharing, access checks, and editing locks work across the platform.

Services Involved

user-service (BFF), user-base-ms (data layer), admin-base-ms (RBAC)

Concepts

Features

A "feature" is a shareable resource abstraction. Every conversation, document, folder, or agent that can be shared is registered as a feature.

Feature TypeSubtypesExample
conversation--A chat conversation
sourcefolder, documentA document or folder
agent--An AI agent

Shares

A share grants a subject (user or group) access to a feature with a specific role.

FieldDescription
featureIdThe resource being shared
subjectType"user" or "group"
subjectIdUser ID or group ID
accessRolePermission level (viewer, editor, etc.)
grantedByUserIdWho created the share

Alternative to direct shares. Configure a shareable link with access level, expiry, and allowed users.

Locks

Editing locks prevent concurrent modifications. A lock has a TTL (default 5 minutes) and is tied to a specific user.

Sharing a Resource

Steps

  1. Client calls POST /api/v1/sharing/share on user-service:

    {
    "resourceType": "conversation",
    "resourceId": "uuid-of-conversation",
    "shares": [
    { "subjectType": "user", "subjectId": "user-uuid", "accessRole": "editor" }
    ]
    }
  2. user-service ensures a feature record exists for this resource by calling user-base-ms POST /api/v1/features

  3. user-service creates the share(s) by calling user-base-ms POST /api/v1/features/shares

  4. The share is stored in the feature_shares table with a unique constraint on (featureId, subjectType, subjectId) where is_active = true

Client --> user-service --> user-base-ms
|
v
features table (ensure exists)
feature_shares table (create share)

Checking Access

Steps

  1. Any service that needs to verify access calls user-service POST /api/v1/sharing/check-access:

    {
    "resourceType": "document",
    "resourceId": "uuid",
    "userId": "uuid"
    }
  2. user-service calls user-base-ms POST /api/v1/features/check-access

  3. The check evaluates:

    • Direct shares (is this user explicitly shared on this feature?)
    • Group shares (is this user in a group that has access?)
    • Link settings (is link sharing enabled with matching access level?)
    • Ownership (is this user the creator?)
  4. Returns { hasAccess: true/false, role: "editor" }

Batch Access Checks

For checking access to multiple resources at once: POST /api/v1/sharing/check-access/batch

Editing Locks

Acquire Lock

  1. Client calls POST /api/v1/sharing/locks/:resourceType/:resourceId on user-service
  2. user-service calls user-base-ms POST /api/v1/features/:featureId/locks
  3. If no active lock exists, a lock is created for the requesting user (TTL: 5 minutes)
  4. If a lock already exists from another user, the request is rejected

Release Lock

  1. Client calls DELETE /api/v1/sharing/locks/:resourceType/:resourceId on user-service
  2. Lock is deleted from the feature_locks table

Force Release

Admins can force-release a lock: DELETE /api/v1/features/:featureId/locks/force

RBAC Integration

User-service uses CASL (Attribute-Based Access Control) to enforce permissions:

  1. On each JWT-authenticated request, user-service fetches the user's roles from user-base-ms (GET /api/v1/user-role/user/:userId)
  2. Fetches the role permissions from admin-base-ms (POST /api/v1/role-permissions/roles)
  3. Builds a CASL ability object that defines what the user can and cannot do
  4. Guards on protected endpoints check this ability before proceeding
user-service
|
+--> user-base-ms: GET /user-role/user/:userId (get role IDs)
|
+--> admin-base-ms: POST /role-permissions/roles (get permissions)
|
+--> Build CASL ability
|
+--> Check: can user perform this action on this resource?