feat(sharing): external client roster on the Sharing tab (trinity-enterprise#20)#1335
Conversation
|
Resolve by running |
vybe
left a comment
There was a problem hiding this comment.
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
02567d2 to
de41ccd
Compare
Rebased onto
|
Rebased onto
|
f2a5731 to
7244bb3
Compare
…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>
7244bb3 to
ff90b92
Compare
Resolve the requirements.md conflict from the #1406/#1412 monolith→area-file split: relocate the "External Client Roster (#20)" requirement (§46) from the retired docs/memory/requirements.md monolith into docs/memory/requirements/ public-access.md, which owns the Telegram/WhatsApp channel integrations the roster aggregates. All code (database.py, models.py, SharingPanel.vue, architecture.md) auto-merged clean.
vybe
left a comment
There was a problem hiding this comment.
Prior CHANGES_REQUESTED is resolved (the semantic SharingPanel.vue re-integration after the Access-tab reframe was addressed across dolho's rebases). Re-validated: three-layer separation clean, ClientRosterEntry in models.py, tenant-isolation test present, no schema/migration/security/packaging gaps. Rebased onto today's dev — resolved the #1412 requirements-split conflict by relocating the roster requirement into requirements/public-access.md; all 4 required checks green. Approving.
/#1335/#1406 conflicts Resolutions: - requirements.md: take dev's index (#1406 split); relocate the #1205 section into requirements/public-access.md as Section 47 (46 was taken by #1335's roster requirement) - Alembic: renumber 0011_agent_ownership_public_channel_prompt -> 0012, re-parent on 0011_agent_ownership_tts_voice (#1397 landed first; whichever lands second renumbers) - db/migrations.py: keep both MIGRATIONS entries (tts_voice + public_channel_prompt) - routers/sharing.py + SharingPanel.vue + architecture.md: keep both #1335 roster and #1205 public-prompt surfaces (independent features) - .claude + src/backend/enterprise submodules: reset to dev's pointers (the branch pinned unrelated/stale commits) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
list_clients_for_agent()join methods (binding → chat_links) on Telegram + WhatsApp ops; exposed via thedatabase.pyfacadeservices/client_roster_service.py: cross-channel aggregation, sort bylast_activedesc (never-active last), per-channel failure degradationGET /api/agents/{name}/clients(OwnedAgentByName, read-only, DB-sourced so it renders when the agent container is stopped);ClientRosterEntrymodel is channel-extensibleSharingPanel.vuetests/unit/test_client_roster.py(5): join normalization, tenant isolation, sort/nulls-last, channel-failure degradationScope
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