autonomous.contact/PERMISSIONS.md
2026-03-09 14:36:05 -04:00

13 KiB

PERMISSIONS.md

Permission reference for autonomous.contact.

This document was built by crawling the codebase for:

Sources of truth

Current default permission sets are defined in public/api/users/index.ts.

  • DEFAULT_USER_PERMISSIONS are assigned to normal users during signup.
  • DEFAULT_SUPERUSER_PERMISSIONS are assigned to the first/bootstrap user.

How permissions work

There are two layers of access control in this codebase:

  1. Global permission strings stored on the user record.
  2. Object-level ACLs stored inside resources, especially channel permissions.read, permissions.write, permissions.events.read, and permissions.events.write.

Important consequence: a user may have a global permission and still be blocked by a channel-level ACL.

Generic permission families

These are not stored as standalone permissions, but the server checks for these prefixes:

Permissions bible

Permission Default user Bootstrap superuser Purpose Where checked Notes
channels.read yes yes Allows listing channels. public/api/channels/index.ts Channel detail reads also require channel ACL membership; this permission gates the channel list endpoint only.
channels.create no yes Allows creating channels. public/api/channels/index.ts, public/tabs/chat/channel_sidebar.html Fully wired.
channels.delete no yes Intended to allow channel deletion. Defined in public/api/users/index.ts No direct server-side check found. Channel deletion currently uses channel.permissions.write membership instead of this string. See public/api/channels/:channel_id/index.ts.
channels.write no yes Intended to allow channel updates. Defined in public/api/users/index.ts No direct server-side check found. Channel updates currently use channel.permissions.write membership instead of this string. See public/api/channels/:channel_id/index.ts.
events.create.blurb yes yes Allows creating blurb events. utils/prechecks.ts, public/tabs/blurbs/new_blurb.html Matches server behavior.
events.create.chat yes yes Allows creating chat events. utils/prechecks.ts UI mismatch: chat composer is gated by events.write.chat, not events.create.chat. See public/tabs/chat/chat.html.
events.create.essay yes yes Allows creating essay events. utils/prechecks.ts, public/tabs/essays/new_essay.html Matches server behavior.
events.create.post yes yes Allows creating post events. utils/prechecks.ts, public/tabs/forum/new_post.html Matches server behavior.
events.create.presence yes yes Intended to allow creating presence events. utils/prechecks.ts No dedicated UI or route-specific feature found beyond generic event creation.
events.read.blurb yes yes Intended to allow viewing blurbs. public/tabs/blurbs/blurbs.html Frontend-only gate found. No matching server-side event-read check by permission string was found.
events.read.chat yes yes Intended to allow viewing chat. public/tabs/chat/chat.html Frontend-only gate found. Server reads rely on authentication and channel ACLs, not this string.
events.read.essay yes yes Intended to allow viewing essays. public/tabs/essays/essays.html Frontend-only gate found.
events.read.post yes yes Intended to allow viewing posts. public/tabs/forum/forum.html Frontend-only gate found.
events.read.presence yes yes Intended to allow viewing presence events. Defined in public/api/users/index.ts No active check found beyond the default assignment.
events.write.blurb yes yes Allows updating/deleting blurb events. utils/prechecks.ts Used by generic event update/delete endpoints.
events.write.chat yes yes Allows updating/deleting chat events. utils/prechecks.ts, public/tabs/chat/chat.html Also used by the chat composer UI, which appears to be stricter/different than server-side create rules.
events.write.essay yes yes Allows updating/deleting essay events. utils/prechecks.ts No dedicated UI gate found.
events.write.post yes yes Allows updating/deleting post events. utils/prechecks.ts No dedicated UI gate found.
events.write.presence yes yes Intended to allow updating/deleting presence events. utils/prechecks.ts No dedicated UI or route-specific usage found beyond generic event mutation logic.
files.write.own yes yes Allows uploads only inside the current user's home path under /files/users/<user-id>/.... public/_pre.ts Fully wired.
files.write.all no yes Allows uploads anywhere under /files/.... public/_pre.ts, tests/11_file_uploads.test.ts Fully wired.
invites.create yes yes Allows creating invite codes. public/api/users/:user_id/invites/index.ts Fully wired.
invites.read.own yes yes Allows reading invites for the path user when it is self. public/api/users/:user_id/invites/index.ts Route behavior currently has filtering issues; see REVIEW.md.
invites.read.all no yes Allows reading invites across users. public/api/users/:user_id/invites/index.ts Route behavior currently has filtering issues; see REVIEW.md.
self.read yes yes Allows reading the current authenticated user's own profile. public/api/users/me/index.ts, public/api/users/:user_id/index.ts Fully wired.
self.write yes yes Allows updating/deleting the current user's own profile. public/api/users/:user_id/index.ts, public/api/users/:user_id/index.ts Fully wired.
signups.read.own yes yes Allows reading signups for the path user when it is self. public/api/users/:user_id/signups/index.ts Route behavior currently has filtering issues; see REVIEW.md.
signups.read.all no yes Allows reading signups across users. public/api/users/:user_id/signups/index.ts Route behavior currently has filtering issues; see REVIEW.md.
users.read yes yes Allows reading/searching other users. public/api/users/index.ts, public/api/users/:user_id/index.ts Fully wired.
users.write no yes Allows updating/deleting other users and editing permissions. public/api/users/:user_id/index.ts, public/api/users/:user_id/index.ts, public/api/users/:user_id/index.ts Fully wired.
watches.create.own yes yes Allows creating watches for self. public/api/users/:user_id/watches/index.ts Fully wired.
watches.create.all no no Allows creating watches for other users. public/api/users/:user_id/watches/index.ts Referenced but not granted by either default permission set. Must be assigned manually if needed.
watches.read.own yes yes Allows reading watches for self. public/api/users/:user_id/watches/index.ts Route behavior currently has filtering issues; see REVIEW.md.
watches.read.all no yes Allows reading watches across users. public/api/users/:user_id/watches/index.ts Route behavior currently has filtering issues; see REVIEW.md.
watches.write.own yes yes Intended to allow updating/deleting own watches. Defined in public/api/users/index.ts No direct permission check found. Watch update/delete currently use ownership only. See public/api/users/:user_id/watches/:watch_id/index.ts and public/api/users/:user_id/watches/:watch_id/index.ts.
watches.write.all no yes Intended to allow updating/deleting others' watches. Defined in public/api/users/index.ts No direct permission check found. Watch update/delete currently use ownership only.

Summary: default permissions vs actual code

Normal-user defaults that are clearly used

These are present in DEFAULT_USER_PERMISSIONS and have matching checks in code:

  • channels.read
  • events.create.blurb
  • events.create.chat
  • events.create.essay
  • events.create.post
  • events.create.presence
  • events.write.blurb
  • events.write.chat
  • events.write.essay
  • events.write.post
  • events.write.presence
  • files.write.own
  • invites.create
  • invites.read.own
  • self.read
  • self.write
  • signups.read.own
  • users.read
  • watches.create.own
  • watches.read.own

Defaults that are only partially matched or frontend-only

  • events.read.blurb
  • events.read.chat
  • events.read.essay
  • events.read.post
  • events.read.presence
  • watches.write.own

Bootstrap/superuser defaults that are present but not fully wired as permission strings

  • channels.delete
  • channels.write
  • watches.write.all

Referenced in code but not granted by default

  • watches.create.all

Biggest mismatches to know about

  1. Channel update/delete do not use channels.write or channels.delete. They use per-channel ACL membership instead. See public/api/channels/:channel_id/index.ts.

  2. Watch update/delete do not use watches.write.own or watches.write.all. They use ownership checks only. See public/api/users/:user_id/watches/:watch_id/index.ts.

  3. events.read.* permissions are mostly UI gates, not server-enforced authorization. The event read endpoints do not generally check these strings.

  4. Chat creation UI uses events.write.chat, but the server requires events.create.chat for POST. This is the clearest create-vs-write mismatch in the current code.

  5. watches.create.all exists in code but is missing from both default sets.

Recommendation

If the goal is to make permissions predictable, the cleanest next step would be to choose one of these approaches:

  1. remove unused permission strings from defaults, or
  2. add explicit checks so every documented permission is actually authoritative

The most important cleanup targets are:

  • channels.write
  • channels.delete
  • watches.write.own
  • watches.write.all
  • the events.read.* family
  • the chat UI mismatch between events.create.chat and events.write.chat