mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-20 00:15:16 +00:00
Dashboard users (and other tenant-authenticated admin/operator/owner
actors) dispatching team tasks to agents in Telegram/Discord groups
previously hit the empty-sender DENY rule when the assigned agent
tried to write files — because dashboard users have tenant identities
(e.g. "viettx") that don't match the numeric file-writer grants stored
per channel.
Two-part fix:
1. CheckFileWriterPermission / CheckCronPermission add an RBAC bypass
at the store layer: if ctx carries RoleFromContext in {admin,
operator, owner}, skip the per-user grant check. Tenant RBAC already
pre-authenticated these callers at the gateway edge; requiring a
redundant per-channel grant blocks legitimate admin work.
2. Role propagation through the full dispatch chain:
ctx (RoleFromContext)
→ RunRequest.Role
→ SubagentTask.OriginRole / AnnounceMetadata.OriginRole
/ DelegateRequest.Role
→ InboundMessage.Metadata[MetaOriginRole]
→ subagentAnnounceRouting.Role / teammateRole
→ RunRequest.Role (re-ingress)
→ store.WithRole(ctx, ...) in loop_context
Covers subagent announce, delegate announce, teammate dispatch
(WS dashboard, tool), session_send, and processNormalMessage's
synthetic-sender override path. team_tasks_create persists
origin_role for deferred dispatches.
Viewer and empty roles fall through to the existing sender-based path
(no bypass).
Regression tests:
- A.10 AdminRoleBypass: admin/operator/owner in ctx allowed even with
empty sender (normally DENY).
- A.11 ViewerRoleDoesNotBypass: viewer and empty roles still hit DENY.
Builds + integration + unit tests green.
60 lines
2.5 KiB
Go
60 lines
2.5 KiB
Go
package tools
|
|
|
|
// Message metadata keys used in dispatch → consumer communication.
|
|
// These keys appear in bus.InboundMessage.Metadata for teammate and
|
|
// subagent messages routed through the gateway consumer.
|
|
const (
|
|
MetaOriginChannel = "origin_channel"
|
|
MetaOriginPeerKind = "origin_peer_kind"
|
|
MetaOriginChatID = "origin_chat_id"
|
|
MetaOriginUserID = "origin_user_id"
|
|
// MetaOriginSenderID carries the real acting sender through announce re-ingress
|
|
// so permission checks (e.g. CheckFileWriterPermission) attribute to the
|
|
// original user rather than a synthetic "subagent:<id>" / "notification:system" string.
|
|
MetaOriginSenderID = "origin_sender_id"
|
|
// MetaOriginRole carries the caller's RBAC role through dispatch + re-ingress
|
|
// so permission checks can bypass per-user grants for authenticated admins
|
|
// (e.g. dashboard user dispatches a task that writes files in a group chat).
|
|
MetaOriginRole = "origin_role"
|
|
MetaOriginLocalKey = "origin_local_key"
|
|
MetaOriginSessionKey = "origin_session_key"
|
|
MetaOriginTraceID = "origin_trace_id"
|
|
MetaOriginRootSpanID = "origin_root_span_id"
|
|
MetaFromAgent = "from_agent"
|
|
MetaToAgent = "to_agent"
|
|
MetaToAgentDisplay = "to_agent_display"
|
|
MetaTeamTaskID = "team_task_id"
|
|
MetaTeamID = "team_id"
|
|
MetaTeamWorkspace = "team_workspace"
|
|
MetaLeaderAgentID = "leader_agent_id"
|
|
MetaParentAgent = "parent_agent"
|
|
MetaSubagentLabel = "subagent_label"
|
|
MetaSubagentStatus = "subagent_status"
|
|
MetaSubagentResult = "subagent_result"
|
|
MetaSubagentRuntime = "subagent_runtime_ms"
|
|
MetaSubagentIterations = "subagent_iterations"
|
|
MetaSubagentInputToks = "subagent_input_tokens"
|
|
MetaSubagentOutputToks = "subagent_output_tokens"
|
|
MetaCommand = "command"
|
|
MetaIsForum = "is_forum"
|
|
MetaMessageThreadID = "message_thread_id"
|
|
MetaDMThreadID = "dm_thread_id"
|
|
MetaChatTitle = "chat_title"
|
|
MetaUsername = "username"
|
|
MetaUserName = "user_name"
|
|
MetaTopicSystemPrompt = "topic_system_prompt"
|
|
MetaTopicSkills = "topic_skills"
|
|
)
|
|
|
|
// Task metadata keys stored in store.TeamTaskData.Metadata.
|
|
// Written during task creation/dispatch, read during deferred dispatch
|
|
// and trace context restoration.
|
|
const (
|
|
TaskMetaPeerKind = "peer_kind"
|
|
TaskMetaLocalKey = "local_key"
|
|
TaskMetaOriginSession = "origin_session_key"
|
|
TaskMetaOriginTrace = "origin_trace_id"
|
|
TaskMetaOriginRootSpan = "origin_root_span_id"
|
|
TaskMetaTeamWorkspace = "team_workspace"
|
|
)
|