Skip to content

feat(sharing): external client roster on the Sharing tab (trinity-enterprise#20)#1335

Open
dolho wants to merge 1 commit into
devfrom
feature/20-client-roster
Open

feat(sharing): external client roster on the Sharing tab (trinity-enterprise#20)#1335
dolho wants to merge 1 commit into
devfrom
feature/20-client-roster

Conversation

@dolho

@dolho dolho commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Surfaces the external client roster on the agent Sharing tab — outside channel users (no Trinity account) who have messaged the agent, aggregated across Telegram + WhatsApp and ordered by most-recent activity. The per-channel activity (verified_email, message_count, last_active) was already collected but never shown.

Read-only surface for the Access/Sharing redesign (epic trinity-enterprise#16). Per-client block / revoke / approve controls build on this next (trinity-enterprise#21).

Changes

  • dblist_clients_for_agent() join methods (binding → chat_links) on Telegram + WhatsApp ops; exposed via the database.py facade
  • serviceservices/client_roster_service.py: cross-channel aggregation, sort by last_active desc (never-active last), per-channel failure degradation
  • apiGET /api/agents/{name}/clients (OwnedAgentByName, read-only, DB-sourced so it renders when the agent container is stopped); ClientRosterEntry model is channel-extensible
  • ui — read-only Client Roster table in SharingPanel.vue
  • teststests/unit/test_client_roster.py (5): join normalization, tenant isolation, sort/nulls-last, channel-failure degradation
  • docs — requirements §44, architecture endpoint + service entries

Scope

Roster v1 = Telegram + WhatsApp (the channels recording the full email/count/last-active triple). Slack (verifications carry email but no activity counters) and VoIP (call logs) are additive follow-ups — the response model already accommodates them without a contract change.

Testing

24 passed — 5 new roster tests + existing Telegram/WhatsApp channel suites, no regressions.

Related to Abilityai/trinity-enterprise#20

🤖 Generated with Claude Code

@dolho dolho requested a review from vybe June 24, 2026 09:23
@github-actions

Copy link
Copy Markdown

⚠️ Nightly unit-suite check skipped — merge conflict against dev.

Resolve by running git merge dev locally and pushing the result. The next nightly run will re-test once the conflict is gone.

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated via /validate-pr — no schema/security issues, but CONFLICTING with dev after #1317. #1317 restructured SharingPanel.vue (operator management moved to the new Access tab; the panel was reframed around Identity Proof / access policy). This PR was built on the old standalone "Team Sharing Section" layout, so the SharingPanel.vue conflict is a semantic re-integration — the Client Roster section needs to be grafted onto the new structure (the #18/#20 Sharing redesign you scoped), not just line-merged. The backend conflicts (sharing.py imports, architecture.md table row) are trivial.

Please rebase onto current dev.

— posted via /validate-pr

…erprise#20)

Surface external channel users (no Trinity account) who have messaged an agent,
aggregated across Telegram + WhatsApp into one read-only roster on the Sharing
tab. Activity (verified_email, message_count, last_active) was already recorded
per channel link but never shown.

- db: list_clients_for_agent() join methods (binding -> chat_links) on the
  Telegram + WhatsApp ops, exposed via the database facade
- service: client_roster_service aggregates + sorts by last_active desc
  (never-active last), degrades per-channel on read failure
- api: GET /api/agents/{name}/clients (OwnedAgentByName, read-only, DB-sourced
  so it renders when the agent container is stopped); ClientRosterEntry model
  is channel-extensible (Slack/VoIP additive)
- ui: read-only Client Roster section in SharingPanel.vue
- tests: join normalization, tenant isolation, sort/nulls-last, channel-failure
  degradation (5 new, all green)
- docs: requirements section 44, architecture endpoint + service entries

Roster v1 = Telegram + WhatsApp (channels recording the full
email/count/last-active triple). Per-client block/revoke/approve controls are
the follow-up (trinity-enterprise#21).

Related to Abilityai/trinity-enterprise#20

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dolho dolho force-pushed the feature/20-client-roster branch from 02567d2 to de41ccd Compare June 25, 2026 14:28
@dolho

dolho commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto dev + review

Fix (rebase): resolved a semantic conflict, not just mechanical. PR was branched before #17 (the Access-tab split), so its base still carried the Team Sharing allow-list section in SharingPanel that #17 moved to AccessPanel. Resolution:

  • SharingPanel.vue: dropped the re-inherited Team Sharing section (its shareWithUser/shareEmail handlers no longer exist on dev — keeping it would've been broken), kept the new Client Roster section.
  • routers/sharing.py: unioned imports + kept both /access (Client/Viewer User Role (AUTH-002) #17 operators) and /clients (Audit Trail System (SEC-001) #20 roster) endpoints.
  • architecture.md: kept both endpoint rows.

Verified: SharingPanel.vue compiles (vue/compiler-sfc), routers/sharing.py compiles, test_client_roster.py 5/5 pass. Now mergeable.

Review: backend is clean and additive — client_roster_service aggregates Telegram + WhatsApp channel users, /clients is owner-only (OwnedAgentByName) and DB-sourced (renders when the agent is stopped). ✅

⚠️ Coordination flag (important)

This adds the Client Roster to the current (pre-reframe) SharingPanel layout. My open PRs #1347 (#18 reframe) and #1348 (#19 channel dialogs) rewrite SharingPanel.vue substantially. When those merge, this roster section will re-conflict and need re-placing into the reframed tab.

Recommended sequencing: merge #1347#1348 → then rebase #1335, slotting the Client Roster into the reframed Sharing tab (it's epic #20, designed to sit alongside the reframe). The backend half is independent and can land anytime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants