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 Type | Subtypes | Example |
|---|---|---|
| conversation | -- | A chat conversation |
| source | folder, document | A document or folder |
| agent | -- | An AI agent |
Shares
A share grants a subject (user or group) access to a feature with a specific role.
| Field | Description |
|---|---|
| featureId | The resource being shared |
| subjectType | "user" or "group" |
| subjectId | User ID or group ID |
| accessRole | Permission level (viewer, editor, etc.) |
| grantedByUserId | Who created the share |
Link Settings
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
-
Client calls
POST /api/v1/sharing/shareon user-service:{
"resourceType": "conversation",
"resourceId": "uuid-of-conversation",
"shares": [
{ "subjectType": "user", "subjectId": "user-uuid", "accessRole": "editor" }
]
} -
user-service ensures a feature record exists for this resource by calling user-base-ms
POST /api/v1/features -
user-service creates the share(s) by calling user-base-ms
POST /api/v1/features/shares -
The share is stored in the
feature_sharestable with a unique constraint on(featureId, subjectType, subjectId)whereis_active = true
Client --> user-service --> user-base-ms
|
v
features table (ensure exists)
feature_shares table (create share)
Checking Access
Steps
-
Any service that needs to verify access calls user-service
POST /api/v1/sharing/check-access:{
"resourceType": "document",
"resourceId": "uuid",
"userId": "uuid"
} -
user-service calls user-base-ms
POST /api/v1/features/check-access -
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?)
-
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
- Client calls
POST /api/v1/sharing/locks/:resourceType/:resourceIdon user-service - user-service calls user-base-ms
POST /api/v1/features/:featureId/locks - If no active lock exists, a lock is created for the requesting user (TTL: 5 minutes)
- If a lock already exists from another user, the request is rejected
Release Lock
- Client calls
DELETE /api/v1/sharing/locks/:resourceType/:resourceIdon user-service - Lock is deleted from the
feature_lockstable
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:
- On each JWT-authenticated request, user-service fetches the user's roles from user-base-ms (
GET /api/v1/user-role/user/:userId) - Fetches the role permissions from admin-base-ms (
POST /api/v1/role-permissions/roles) - Builds a CASL ability object that defines what the user can and cannot do
- 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?