Skip to content

fix(channels): managed-DM credentials surface as connected to chat#1209

Merged
senamakel merged 4 commits intotinyhumansai:mainfrom
obchain:fix/1149-telegram-chat-sync
May 5, 2026
Merged

fix(channels): managed-DM credentials surface as connected to chat#1209
senamakel merged 4 commits intotinyhumansai:mainfrom
obchain:fix/1149-telegram-chat-sync

Conversation

@obchain
Copy link
Copy Markdown
Contributor

@obchain obchain commented May 5, 2026

Summary

  • Fixes Fix Telegram connected state not syncing into chat #1149: chat reports "Telegram not connected" right after a successful managed-DM link.
  • Root-cause two backend bugs: list_provider_credentials's exact-match filter never matched the namespaced channel keys, and the welcome-agent onboarding surface only consulted the legacy TOML store.
  • Adds the connected_channel_slugs helper that merges channels_config.<slug> with the credential store so every consumer sees the same picture.

Problem

After a Telegram managed-DM link succeeds, the credential is stored under channel:telegram:managed_dm but channels_config.telegram stays unset (managed DM doesn't materialise a TOML block — the bot lives on the OpenHuman backend, not the local runtime). Two layers then go stale:

  1. openhuman.channels_status returned connected:false for every channel because list_provider_credentials filtered by provider == "channel:" (exact equality on a value that's never the literal string channel:). Frontend reload reverted the badge to "disconnected" and chat-side callers saw nothing.
  2. The welcome agent's check_onboarding_status snapshot only walked config.channels_config, so the agent answered "Telegram is not connected" verbatim even when the credential was already in place.

Solution

Three backend fixes, each in its own commit:

  1. feat(credentials): add list_provider_credentials_by_prefix — a pure prefix variant for namespaces grouped under a common stem.
  2. fix(channels): channel_status + slug merge surface credential-stored channelschannel_status switches to the prefix helper, and connected_channel_slugs merges both stores in deterministic order with dedupe.
  3. fix(agent): onboarding status surface honors credential-stored channelsOnboardingState carries the merged slug list; build_status_snapshot and format_status_markdown consume it instead of re-reading config directly.

The fourth commit is a JSON-RPC E2E test that exercises the full transport path (auth_store_provider_credentialschannels_status) so a regression in either layer is caught at the wire level.

Frontend already dispatches upsertChannelConnection({status:'connected'}) after a successful link, so no app changes are needed — the UI was correct in the moment, only the post-reload / chat-side reads were stale.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per docs/TESTING-STRATEGY.md
  • Diff coverage ≥ 80% — changed lines (Vitest + cargo-llvm-cov merged via diff-cover) meet the gate enforced by .github/workflows/coverage.yml. Run pnpm test:coverage and pnpm test:rust locally; PRs below 80% on changed lines will not merge.
  • N/A: behaviour-only change — Coverage matrix updated — added/removed/renamed feature rows in docs/TEST-COVERAGE-MATRIX.md reflect this change (no new feature row; bug fix on existing channel-status surface)
  • N/A: bug fix on existing surface, no new matrix feature ID — All affected feature IDs from the matrix are listed in the PR description under ## Related
  • No new external network dependencies introduced (mock backend used per docs/TESTING-STRATEGY.md)
  • N/A: doesn't touch release-cut surfaces — Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md)
  • Linked issue closed via Closes #NNN in the ## Related section

Impact

  • Runtime: backend-only. No frontend changes, no schema / RPC signature changes. channels_status now returns truthful entries (was previously always connected:false).
  • Compatibility: no migration. connected_channel_slugs is additive; channels_config.<slug> continues to work for bot_token / webhook / oauth flows that need a local listener.
  • Performance: one extra credential-store read per compute_state call (same as the existing Composio integrations fetch). No hot path.
  • Security: no new attack surface. Prefix-list helper reuses the existing AuthService::load_profiles path; never exports tokens.

Related

Summary by CodeRabbit

  • New Features

    • Connected messaging channels are now properly detected from stored credentials, in addition to configuration files, providing more complete channel status visibility.
    • Onboarding status display now includes credential-only channels (e.g., managed messaging platforms) that were previously not recognized as connected.
  • Tests

    • Added comprehensive test coverage for credential-based channel detection and deduplication logic.

obchain added 4 commits May 5, 2026 12:26
The exact-match filter on list_provider_credentials cannot enumerate
provider keys grouped under a common stem (e.g. channel:<slug>:<mode>).
Add a prefix variant so callers like channel_status can list every
channel-namespaced credential in one call.

Refs tinyhumansai#1149.
…channels

channel_status passed "channel:" to the exact-match
list_provider_credentials filter, so it never matched the real keys
(channel:telegram:managed_dm, channel:slack:bot_token, …) and always
reported connected:false. Switch it to the new prefix helper.

Add connected_channel_slugs which merges the legacy
channels_config.<slug> TOML store with the channel:<slug>:<mode>
credential store so every consumer agrees on what's connected. Used by
the welcome-agent onboarding snapshot in the next commit.

Refs tinyhumansai#1149.
OnboardingState now carries the merged channel list produced by
channels::controllers::connected_channel_slugs, so the welcome agent
sees Telegram/Slack/etc. as soon as their managed-DM credential lands
— no app restart required and no "telegram not connected" reply
right after a successful link.

Closes tinyhumansai#1149.
…atus

Wire-level regression guard for issue tinyhumansai#1149: store
channel:telegram:managed_dm via openhuman.auth_store_provider_credentials,
then assert openhuman.channels_status reports the managed_dm entry as
connected:true. Catches regressions in either the prefix-match
credential helper or the channels controller at the transport layer.

Refs tinyhumansai#1149.
@obchain obchain requested a review from a team May 5, 2026 07:15
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 45680113-6482-426c-872a-f06f2d629e46

📥 Commits

Reviewing files that changed from the base of the PR and between 50d109b and 17bec1b.

📒 Files selected for processing (8)
  • src/openhuman/channels/controllers/mod.rs
  • src/openhuman/channels/controllers/ops.rs
  • src/openhuman/channels/controllers/ops_tests.rs
  • src/openhuman/credentials/ops.rs
  • src/openhuman/credentials/ops_tests.rs
  • src/openhuman/tools/impl/agent/check_onboarding_status.rs
  • src/openhuman/tools/impl/agent/onboarding_status.rs
  • tests/json_rpc_e2e.rs

📝 Walkthrough

Walkthrough

This PR enables channel connection state to be tracked via credentials stored with channel:<slug>:<mode> keys alongside legacy TOML-backed channels. A new credential prefix-based listing function and channel-slug merger allow tools to detect managed-DM channels that exist only in the credential store, fixing sync issues where Telegram connects but chat runtime doesn't recognize the connection.

Changes

Credential-Backed Channel Detection

Layer / File(s) Summary
Credential Listing
src/openhuman/credentials/ops.rs
New list_provider_credentials_by_prefix function filters stored credentials by prefix instead of exact match, enabling discovery of namespaced provider keys like channel:*.
Channel Slug Merging
src/openhuman/channels/controllers/ops.rs
New connected_channel_slugs helper merges messaging channel slugs from two sources: legacy config.channels_config.<slug> entries and credential-stored channel:<slug>:<mode> keys, deduplicating and returning combined set. channel_status switches to prefix-based credential enumeration.
Module Re-export
src/openhuman/channels/controllers/mod.rs
Publicly re-exports connected_channel_slugs for external access.
Onboarding Integration
src/openhuman/tools/impl/agent/onboarding_status.rs, src/openhuman/tools/impl/agent/check_onboarding_status.rs
Onboarding status snapshot/markdown now accepts precomputed connected_channels list; OnboardingState gains connected_channels field fetched asynchronously via the new merged-slug helper.
Tests & E2E
src/openhuman/channels/controllers/ops_tests.rs, src/openhuman/credentials/ops_tests.rs, tests/json_rpc_e2e.rs
Added unit tests for prefix filtering, slug merging with deduplication, empty configs, and credential-only channels; E2E test validates managed-DM credential creation flips channels_status connected state.

Sequence Diagram

sequenceDiagram
    participant Tool as Tool
    participant Creds as Credentials<br/>Service
    participant Config as Config
    participant ChanCtrl as Channel<br/>Controller
    participant Tools as Onboarding<br/>Tools

    Tool->>+ChanCtrl: connected_channel_slugs(config)
    
    ChanCtrl->>+Config: read channels_config
    Config-->>-ChanCtrl: legacy channels
    
    ChanCtrl->>+Creds: list_provider_credentials_by_prefix("channel:")
    Creds-->>-ChanCtrl: channel:*:* credentials
    
    ChanCtrl->>ChanCtrl: merge slugs + deduplicate
    ChanCtrl-->>-Tool: Vec<String> (all connected)
    
    Tool->>+Tools: format_status_markdown(connected_channels)
    Tools-->>-Tool: markdown with all channels
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • tinyhumansai/openhuman#580: Both modify channel controller credential handling for channel:<slug>:<mode> keyed managed-DM channels and add helpers to detect credential-backed channels.
  • tinyhumansai/openhuman#725: Related change to channel controller behavior; your merged connected_channel_slugs will include TOML-backed channels like iMessage config added there.

Suggested reviewers

  • YellowSnnowmann
  • senamakel

Poem

🐰 A rabbit hops through credentials' store,
Finds channels hidden in each door,
TOML meets key, channel:<slug> delight,
No more stale states—Telegram's bright!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(channels): managed-DM credentials surface as connected to chat' clearly summarizes the main change—enabling managed-DM credentials to appear as connected in chat, which directly addresses issue #1149.
Linked Issues check ✅ Passed All coding objectives from #1149 are met: the PR adds prefix-based credential lookup [ops.rs], implements a slug-merge helper [ops.rs], updates onboarding state to detect credential-only channels [onboarding_status.rs], and includes E2E tests covering the reconnect-to-chat-availability flow [json_rpc_e2e.rs].
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing #1149: credential listing, channel-status integration, onboarding state merging, and E2E testing. No unrelated modifications to schemas, RPC signatures, or frontend logic are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@senamakel senamakel merged commit 1ac3fee into tinyhumansai:main May 5, 2026
20 checks passed
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.

Fix Telegram connected state not syncing into chat

2 participants