Resolves issue #915 (Telegram group write_file permission denied after
/addwriter) by reconstructing the real sender on announce re-ingress
and migrating ownership/audit call sites off the scope-coupled UserID.
Propagation chain (new MetaOriginSenderID key):
SubagentTask.OriginSenderID
→ AnnounceMetadata.OriginSenderID
→ InboundMessage.Metadata[MetaOriginSenderID]
→ subagentAnnounceRouting.SenderID
→ RunRequest.SenderID
Same chain for delegate_tool.announceToParent, team_tool_dispatch,
sessions_send, team_tasks_blocker escalation.
ACTOR migration (owner/audit now uses ActorIDFromContext):
- publish_skill: skill owner = individual sender
- skill_manage create/patch/delete: owner = sender; ownership check
accepts actor or legacy UserID for pre-migration rows
- delegate_tool: DelegateRequest.UserID + DomainEvent.UserID = actor
- team_tasks_blocker: blocker attribution + escalation = actor
- team_tool_cache: team access-policy check = actor (fixes per-user
allow/deny lists in group chats)
Scope-intentional (unchanged, commented): cron.go, team_tasks_create.go.
* fix(telegram): propagate local_key for forum topic routing in team notifications
Team task status messages (dispatched, completed, progress) were always
delivered to the General topic in Telegram forum groups because the
notification pipeline had no access to the originating topic's local_key.
Root cause: wireTeamProgressNotifySubscriber in gateway_events.go published
OutboundMessage with no Metadata, so the Telegram adapter had no
message_thread_id to route to the correct forum topic.
Fix has two parts:
1. Team notify path (root cause):
- Add LocalKey field to TeamTaskEventPayload (protocol)
- Extract local_key from tool context in WithContextInfo()
- Add LocalKey to NotifyRoutingMeta
- Pass LocalKey through to OutboundMessage Metadata in both
leader mode (InboundMessage) and direct mode (OutboundMessage)
2. MCP bridge context (supporting):
- Propagate local_key and session_key through bridge HTTP headers
- Add X-Local-Key and X-Session-Key to BridgeContext
- Extract and inject into tool context in gateway middleware
- Include in HMAC signature for integrity
Closes#798
* fix(telegram): pass LocalKey from task metadata in all dispatch/fail broadcast sites
The initial fix added LocalKey to the event payload and WithContextInfo(),
but 4 broadcast call sites use individual With* options instead of
WithContextInfo — so LocalKey was never populated for:
- fallback_dispatch (team_tasks_create.go)
- dispatch_unblocked (team_tool_dispatch.go)
- post_turn dispatch (team_tool_validation.go)
- blocker/fail (team_tasks_blocker.go)
Add WithLocalKey() option function and extract TaskMetaLocalKey from task
metadata at each site, matching the existing TaskMetaPeerKind pattern.
* test(mcp): add HMAC verification tests for extra params (localKey, sessionKey)
- Add tests for SignBridgeContext/VerifyBridgeContext with extra params
- Test backward compat fallback for pre-localKey sessions
- Test that param order matters in signature
- Add clarifying comment for routing context injection security model
---------
Co-authored-by: Jens Henke <jens@henke.dk>
Co-authored-by: viettranx <viettranx@gmail.com>
Two fixes:
1. Remove assistant prefill from team task reminders. The injected
[user]+[assistant]+[user] pattern caused LLMs to treat the canned
ack as "turn complete", returning NO_REPLY for every user message
in group sessions with active tasks. Reminders are now merged into
the user message as prefix tags.
2. Add PeerKind propagation to team notification routing. TaskTicker
and progress notifications were missing PeerKind on InboundMessage,
causing them to route to phantom DM sessions instead of the correct
group session. PeerKind is now carried through event payloads,
notify queue metadata, and all inbound message publications.
Extract TeamToolBackend interface from concrete *TeamToolManager to enable
unit testing of the 17 team task action handlers without DB or message bus.
- Add TeamToolBackend interface (19 methods) in team_tool_backend.go
- Add exported wrappers on TeamToolManager (cache, helpers, dispatch, manager)
- Migrate 133 call sites across 5 action handler files (pure casing rename)
- Change TeamTasksTool.manager field from *TeamToolManager to TeamToolBackend
- Add mock backend infrastructure (baseNoopTeamStore + mockTaskStore + mockBackend)
- Add 94 unit subtests across 6 test files covering all actions:
lifecycle (claim/complete/cancel/review/approve/reject),
create validation, blocker escalation, mutations (comment/progress/attach/update),
followup (ask_user/clear_ask_user/retry), read actions (notification/policy/list/search/get)
WorkspaceInterceptor and PostTurnProcessor remain on concrete *TeamToolManager.
No behavioral changes — all existing logic preserved.
- Add comment_type column (note/blocker) with migration 000028
- Blocker comments auto-fail task, cancel member session via
EventTeamTaskFailed broadcast, and escalate to leader via
InboundMessage (system:escalation bypasses debounce)
- Enrich audit events: fix tenant scope bug (context.Background →
WithTenantID), add 4 missing types (commented/progress/updated/stale),
populate data field (reason, comment_text, progress_percent)
- Add blocker escalation config toggle in team settings UI
- Add audit logs modal with paginated team events (Clock icon)
- Update features modal: all features now available (no coming soon)
- Update code comments: reviewer role not yet active, all flows via leader
- Update docs: remove v1/v2 versioning, add blocker escalation and
review workflow sections, document enriched audit events