type:research: Public Access to Channels (No Auth) #63
Labels
No labels
area:api
area:core
area:docs
area:infra
area:ux
dependencies
documentation
duplicate
good first issue
help wanted
invalid
question
rust
status:complete
status:partial
status:planned
type:bug
type:design
type:feature
type:infra
type:refactor
type:research
type:ux
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
icub3d/decentcom#63
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Migrated from GitHub issue icub3d/decentcom#89
Original Author: @icub3d
Original Date: 2026-04-18T15:00:48Z
Research: Public Access to Channels
Overview
Design a mechanism to allow unauthenticated (no public key/session) read access to specific "public" channels within a decentcom server. Writes always require authentication.
Background
Currently, the API is strictly protected by the
MemberUserextractor which requires a valid session and server membership. However, some servers might want "public announcement" channels that are visible to anyone with the server address, even without joining or providing a public key.Design Direction
Read-only for public, always
Posting requires a stable identity for the rest of the model to hold together — rate limits, bans, audit log, and
MENTION_EVERYONEall assume auser_id. An unauthenticated writer has none of that, and reinventing IP-based identity fights the Ed25519 design. Every use case collapses to read-only public access:@everyonelacksSEND_MESSAGES.READ_MESSAGESgranted to a public viewer.The only new capability needed is: "can an unauthenticated request read this channel?"
Fit into the existing permission model
@everyone+ per-channel allow/deny overrides already exist (server/src/permissions.rs). Introduce a built-in pseudo-role@publicthat is not implied by@everyone(everyone = authenticated members; public = not-even-a-member). Admins grant@publictheREAD_MESSAGESpermission via the normal channel override UI on whichever channels they want public.HTTP-only, separate route prefix
Public access is exposed via a
/public/...HTTP GET prefix only. No WebSocket/gateway support in v1 — announcement use cases don't need realtime, and unauthenticated socket lifecycle is a separate problem. The separate prefix lets operators front these routes with a CDN or external rate limiter/cache without touching authenticated routes.API / Interface Changes
OptionalAuthUserextractor returningOption<AuthUser>./public/channels/:idand/public/channels/:id/messagesGET routes.None,effective_permissionsis computed against@publicalone with channel overrides applied. GET endpoints checkREAD_MESSAGES; all other endpoints still requireMemberUser.@publicrole seeded at server init, not assigned to any member, not implied by@everyone.Component Changes
server/src/permissions.rs— add@publicrole handling, extendeffective_permissions/compute_base_permissionsto work with an optional user.server/src/auth/middleware.rs— addOptionalAuthUserextractor.server/src/channels/handlers.rs,server/src/messages/handlers.rs— add public GET handlers mounted under/public.server/src/config.rs— addpublic_access_enabledserver-level kill switch.@publicrole exists.Task List
docs/design/public-access.mdcapturing this design.@publicrole alongside@everyone.OptionalAuthUserextractor.@publicwhen absent./public/router with GET message/channel endpoints.public_access_enabledserver config flag that short-circuits all/public/routes when disabled.@publicchannel overrides (can reuse existing channel override flow).Test List
@publichasREAD_MESSAGESreturns messages.@publichas no override returns 403.public_access_enabled = false.@publicgrants do not leak into@everyonepermission computation for authenticated members.Open Questions
/public/. Document the recommended deployment pattern.