Skip to main content

Sharing

A ResourceShare row records a per-resource share between a user and either another user or a group. Shares apply to annotations, summaries, claims, personas, and world states. A recipient gains either read-only access or the additional ability to fork the resource into their own ownership.

Endpoints

POST   /api/sharing                  body { resourceType, resourceId,
sharedWithUserId?, sharedWithGroupId?,
permissionLevel, expiresAt? }
GET /api/sharing/received shares pointed at the requester
GET /api/sharing/sent shares the requester created
DELETE /api/sharing/:shareId revoke a share
POST /api/sharing/:shareId/fork fork a forkable share into an owned copy

Exactly one of sharedWithUserId / sharedWithGroupId is set per row.

Resource types

annotation | summary | claim | persona | world_state

The resource must exist and be readable to the requester; the route checks ability.can('share', subject(...)) on the source row before creating the share.

Permission levels

read_only   recipient can read the resource only
forkable recipient can additionally call POST /api/sharing/:shareId/fork
to copy the resource into their own ownership

A share cannot escalate. If the requester only has read_only access (because the resource was shared to them at that level), they cannot re-share at forkable. The route refuses; this is the sharing privilege cap.

Forking

POST /api/sharing/:shareId/fork writes a new owned copy of the resource under the requester. The fork carries fresh ids; cross- references inside the resource (gloss items, claim relations) are remapped using the same ID-regeneration machinery as cross-user imports.

Forking is one-way: revoking the original share does not delete the forked copy.

Expiry

expiresAt is optional. When set, the share becomes invisible to the recipient after that timestamp; the row stays in the database for audit purposes. A revoked share is hard-deleted.

See also