feat(acl): chat-surface ACL (append_message + list_messages)#171
Merged
Conversation
The chat surface was world-read/write: any member's token could read or append to another member's chat history via list_messages/append_message. Close it under the same ESCUREL_WRITE_ACL flag: a chat group (ADR-13: chat_group_id := community_member_id) is private to its owning member. Indexer::may_access_chat resolves the owner = the community_member instance whose id == chat_group_id (its owner_field, e.g. credential) vs the caller sub; admin bypasses; a chat_group_id with no owning instance (or unresolvable owner) is ungated (compat for non-member chat groups). append denies with a forbidden error; list_messages denies with an EMPTY page (non-leaking, like expand→null). Off → legacy open; log → warn+allow; enforce → block. Tests (no mocks, real HTTP MCP): escurel-server/tests/chat_acl.rs — owner-appends+reads / non-owner-blocked / admin-reads-any / off-open / unknown-chat-ungated. Read + write ACL e2e regression green; clippy clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the chat-surface confidentiality gap the read/write ACL work left open:
list_messages/append_messagewere world-read/write, so any member's token could read or append to another member's chat history.A chat group (ADR-13:
chat_group_id:=community_member_id) is now private to its owning member, under the sameESCUREL_WRITE_ACLflag (off|log|enforce):Indexer::may_access_chat— owner = thecommunity_memberinstance whose id ==chat_group_id(itsowner_field, e.g.credential) vs callersub; admin bypasses; an unknown/unowned chat group is ungated (compat).append_messagedenies with a forbidden error;list_messagesdenies with an empty page (non-leaking, likeexpand→null).Tests (no mocks, real HTTP MCP):
chat_acl.rs— owner appends+reads / non-owner blocked / admin reads any / off-mode open / unknown-chat ungated. Instance read + write ACL e2e regression stays green; clippy clean.This is point 2 of the ACL follow-ups (chat surface). Remaining:
capture_event/assign_eventevent ACLs + point 3 read gaps (resolve/neighbours/run_stored_query).🤖 Generated with Claude Code