feat: verify telegram owner during hot activation#1157
Conversation
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
There was a problem hiding this comment.
Pull request overview
Adds Telegram WASM channel “hot activation” improvements by verifying channel ownership during setup (via a Telegram DM), persisting owner/bot metadata, and reflecting the new activation lifecycle in the web UI and tests.
Changes:
- Implement setup-time Telegram owner verification and persist
owner_id+bot_usernamefor runtime config injection. - Introduce a typed
activation_statusfor extensions and update web handlers/UI to treat owner-bound channels as “Active”. - Expand test coverage: new Playwright scenario, Rust unit tests, and improved E2E isolation/build behavior.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/telegram_auth_integration.rs | Locate Telegram channel WASM across git worktrees for integration tests. |
| tests/e2e/scenarios/test_telegram_hot_activation.py | New E2E coverage for Telegram setup modal hint + hot-activation flow. |
| tests/e2e/conftest.py | Isolate HOME/base dir for E2E; add binary rebuild detection logic. |
| src/extensions/manager.rs | Core Telegram owner-verification flow, persisted binding state, runtime config updates, and new unit tests. |
| src/channels/web/types.rs | Add ExtensionActivationStatus enum + classifier for consistent activation state reporting. |
| src/channels/web/static/style.css | Add styling for a configure modal hint panel. |
| src/channels/web/static/i18n/en.js | Add Telegram-specific setup hint + “waiting” button text. |
| src/channels/web/static/app.js | Show Telegram owner-verification hint; update button text while waiting; restore on failure. |
| src/channels/web/server.rs | Use activation classifier and count owner-bound channels as “Active”; add test. |
| src/channels/web/handlers/extensions.rs | Same activation classification update for the handlers module. |
| src/channels/wasm/telegram_host_config.rs | Add Telegram name constant + settings key helper for bot username persistence. |
| src/channels/wasm/setup.rs | Inject persisted Telegram bot_username into runtime config on startup. |
| src/channels/wasm/mod.rs | Wire in and re-export Telegram host config helpers. |
| FEATURE_PARITY.md | Document setup-time owner verification as part of Telegram parity. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/extensions/manager.rs
Outdated
| let get_me_url = format!("https://api.telegram.org/bot{bot_token}/getMe"); | ||
| let get_me_resp = | ||
| client.get(&get_me_url).send().await.map_err(|e| { | ||
| ExtensionError::Other(format!("Telegram getMe request failed: {e}")) |
src/extensions/manager.rs
Outdated
|
|
||
| let delete_webhook_url = format!("https://api.telegram.org/bot{bot_token}/deleteWebhook"); | ||
| let delete_webhook_resp = client.post(&delete_webhook_url).send().await.map_err(|e| { | ||
| ExtensionError::Other(format!("Telegram deleteWebhook request failed: {e}")) |
src/extensions/manager.rs
Outdated
| .map_err(|e| { | ||
| ExtensionError::Other(format!("Telegram getUpdates request failed: {e}")) |
| ROOT / "providers.json", | ||
| ROOT / "src", | ||
| ROOT / "channels-src", | ||
| ] | ||
| return any(_latest_mtime(path) > binary_mtime for path in inputs) |
| #[serde(skip_serializing_if = "Option::is_none")] | ||
| pub activation_status: Option<String>, | ||
| pub activation_status: Option<ExtensionActivationStatus>, | ||
| /// Human-readable error when activation_status is "failed". |
zmanian
left a comment
There was a problem hiding this comment.
Review
The core verification logic is well-structured and the security model is reasonable for single-owner private bot setup. Three blocking issues.
Blocking
1. Bug: server.rs lost the ChannelRelay activation status branch
The refactoring replaced the per-kind if/else if chain in server.rs with a blanket call to classify_wasm_channel_activation() for ALL extensions. That function returns None for non-WasmChannel kinds. The original code had a separate else if ext.kind == ChannelRelay branch returning Active/Configured/Installed.
handlers/extensions.rs correctly preserves this branch, but server.rs does not. ChannelRelay extensions (e.g., Signal) will report activation_status: null instead of their correct status.
2. Clippy failure -- let...else should use ? operator at manager.rs:446:
// Current:
let Some(store) = self.store.as_ref() else { return None; };
// Should be:
let store = self.store.as_ref()?;3. No-panics CI check flagging test code -- .expect()/.unwrap() in #[cfg(test)] blocks are being flagged. Needs resolution (either fix CI check to exclude test blocks, or move test code to a location the check ignores).
Non-blocking
- Code duplication in
#[cfg(test)]/#[cfg(not(test))]loader blocks (~50 lines duplicated). Extract common construction into a helper. - Bot token in Telegram API URLs could leak to trace logs. Consider sanitizing before logging.
deleteWebhookduring verification leaves channel broken if verification times out (120s). Any previously configured webhook is destroyed but channel isn't activated. Consider documenting this or restoring webhook on timeout.- First-user-wins during 120s window -- first non-bot private DM sender becomes owner. Low risk for newly created bots during setup, but worth noting for public bots.
Security
- Verification flow is sound:
getMevalidates token,getUpdateslong-polls for owner DM, binding is persisted and injected into WASM runtime. - After initial binding, WASM channel runtime rejects non-owner messages (unchanged enforcement).
- No race conditions in the activation flow --
RwLockis not held across the long-polling await.
There was a problem hiding this comment.
Pull request overview
Adds “setup-time owner verification” for the Telegram WASM channel (deriving/storing an owner_id by polling Telegram updates), along with UI affordances and test coverage to support hot-activation and clearer activation states in the web Extensions tab.
Changes:
- Implement Telegram owner verification during
configure()(polls Telegram Bot API, persistsowner_id+bot_username, updates runtime config, and optionally sends a confirmation DM). - Improve Extensions UI/JSON activation-state reporting (typed activation status + Telegram-specific setup hint/waiting state) and add E2E coverage.
- Harden tests/dev ergonomics (worktree-aware Telegram WASM path in integration test; E2E runs with isolated HOME; conditional gateway binary rebuild).
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/telegram_auth_integration.rs | Locates Telegram channel WASM artifact across git worktrees. |
| tests/e2e/scenarios/test_telegram_hot_activation.py | New Playwright coverage for Telegram setup modal + hot-activation UI flow. |
| tests/e2e/conftest.py | Isolates HOME for E2E + adds “rebuild binary if sources changed” heuristic. |
| src/extensions/manager.rs | Implements Telegram owner verification, stores owner/bot username, and injects config overrides during activation/refresh. |
| src/channels/web/types.rs | Introduces typed ExtensionActivationStatus + classification helper for WASM channels. |
| src/channels/web/static/style.css | Adds styling for a configure-modal hint block. |
| src/channels/web/static/i18n/en.js | Adds Telegram-specific configure hint/waiting strings. |
| src/channels/web/static/app.js | Shows Telegram hint in configure modal; changes submit button text while waiting on verification. |
| src/channels/web/server.rs | Uses activation-status classifier and treats owner-bound channels as “active”; adds tests. |
| src/channels/web/handlers/extensions.rs | Mirrors server-side activation-status classification logic. |
| src/channels/wasm/telegram_host_config.rs | Centralizes Telegram channel name + settings key helper for bot username persistence. |
| src/channels/wasm/setup.rs | Injects persisted Telegram bot_username into runtime config during startup channel registration. |
| src/channels/wasm/mod.rs | Wires new Telegram host-config module exports. |
| FEATURE_PARITY.md | Notes Telegram “setup-time owner verification” parity. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/extensions/manager.rs
Outdated
| let delete_webhook_url = format!("https://api.telegram.org/bot{bot_token}/deleteWebhook"); | ||
| let delete_webhook_resp = client.post(&delete_webhook_url).send().await.map_err(|e| { | ||
| ExtensionError::Other(format!("Telegram deleteWebhook request failed: {e}")) | ||
| })?; | ||
| if !delete_webhook_resp.status().is_success() { |
| let deadline = std::time::Instant::now() | ||
| + std::time::Duration::from_secs(TELEGRAM_OWNER_BIND_TIMEOUT_SECS); | ||
| let mut offset = 0_i64; | ||
|
|
| ROOT / "channels-src", | ||
| ] |
There was a problem hiding this comment.
Fixed in 2be585a. _latest_mtime() now walks the tree with os.walk() and prunes target/ directories before checking mtimes, so local channels-src/*/target artifacts no longer force unnecessary gateway rebuilds during E2E runs.
src/extensions/manager.rs
Outdated
| client.get(&get_me_url).send().await.map_err(|e| { | ||
| ExtensionError::Other(format!("Telegram getMe request failed: {e}")) |
There was a problem hiding this comment.
Fixed in 2be585a. I replaced the raw reqwest::Error formatting with the typed telegram_request_error() / telegram_response_parse_error() helpers, so getMe/deleteWebhook/getUpdates failures no longer surface token-bearing URLs in logs or API errors.
src/extensions/manager.rs
Outdated
| .send() | ||
| .await | ||
| .map_err(|e| { | ||
| ExtensionError::Other(format!("Telegram getUpdates request failed: {e}")) | ||
| })?; |
There was a problem hiding this comment.
Fixed in 2be585a. The same sanitizing helper now covers the getUpdates path as well, so we no longer interpolate a raw reqwest::Error that could include the token-bearing Telegram URL.
src/extensions/manager.rs
Outdated
|
|
||
| let delete_webhook_url = format!("https://api.telegram.org/bot{bot_token}/deleteWebhook"); | ||
| let delete_webhook_resp = client.post(&delete_webhook_url).send().await.map_err(|e| { | ||
| ExtensionError::Other(format!("Telegram deleteWebhook request failed: {e}")) |
There was a problem hiding this comment.
Fixed in 2be585a. deleteWebhook now goes through the same sanitized Telegram request-error helper, so setup failures no longer echo a raw URL that embeds the bot token.
|
Addressed the blocking review items on the latest branch head.
Re-verified on current head:
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 3042 filtered out; finished in 0.01s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 3042 filtered out; finished in 0.00s |
|
Addressed the blocking review items on the latest branch head.
Re-verified on current head:
|
zmanian
left a comment
There was a problem hiding this comment.
Re-review: All blocking items resolved
All 3 blocking items from my previous review have been addressed:
- ChannelRelay activation status restored -- Fixed in commit c3a406d. The
server.rsextensions_list_handlernow has properif ext.kind == WasmChannel / else if ChannelRelay / else Nonebranching. New testtest_channel_relay_activation_status_is_preservedcovers this. - Clippy
let...else->?operator -- Fixed in commit e50ea46.manager.rs:464now useslet store = self.store.as_ref()?. - No-panics CI check on test code -- Fixed in commit e50ea46. Tests converted to
-> Result<(), String>withrequire/require_eqhelpers instead ofassert!/.expect().
Also addressed from non-blocking:
- Bot token sanitization -- Fixed in commit 2be585a. New
telegram_request_error/telegram_response_parse_errorhelpers log structured fields (action, status, timeout flags) without exposing the raw error message that might contain the token URL. - E2E conftest --
_latest_mtimenow skipstarget/directory during mtime scan.
Full CI is green (all Clippy variants, Formatting, E2E, regression test enforcement).
LGTM.
…-activation-tests # Conflicts: # src/extensions/manager.rs
There was a problem hiding this comment.
Pull request overview
Adds Telegram “hot activation” with setup-time owner verification, updates the web UI/API to reflect richer WASM-channel activation states, and expands test coverage (Rust unit tests + Playwright E2E) to cover the new flow.
Changes:
- Implement Telegram setup-time owner binding + runtime config injection (owner_id / bot_username) during activation and reconfiguration.
- Replace stringly-typed WASM channel activation status with a typed enum and shared classification logic for the web API.
- Add/adjust integration + E2E tests (including worktree-friendly WASM/binary handling).
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/extensions/manager.rs |
Core implementation: Telegram owner verification via Bot API polling, persisted owner/bot-username settings, hot-activation refinements, and extensive new tests. |
src/channels/wasm/telegram_host_config.rs |
Centralizes Telegram channel name constant + bot-username settings key helper. |
src/channels/wasm/mod.rs |
Exposes Telegram host config helpers within the wasm channel module. |
src/channels/wasm/setup.rs |
Injects persisted bot_username into Telegram channel runtime config at startup. |
src/channels/web/types.rs |
Introduces ExtensionActivationStatus enum + classify_wasm_channel_activation() helper; updates ExtensionInfo accordingly. |
src/channels/web/server.rs |
Uses the shared activation classification and incorporates “owner-bound counts as active”; adds tests. |
src/channels/web/handlers/extensions.rs |
Mirrors the server handler changes for extension listing / activation status classification. |
src/channels/web/static/app.js |
Adds Telegram-specific setup hint and “waiting for owner verification” button state in the configure modal. |
src/channels/web/static/i18n/en.js |
Adds English strings for the Telegram owner-verification hint/waiting UI. |
src/channels/web/static/style.css |
Styles the new configure hint block. |
tests/e2e/conftest.py |
Makes E2E runs more hermetic (temp HOME / base dir) and rebuilds the binary when inputs change. |
tests/e2e/scenarios/test_telegram_hot_activation.py |
New Playwright test covering Telegram setup modal + hot-activation UI transitions. |
tests/telegram_auth_integration.rs |
Makes Telegram WASM path resolution work in git worktree setups. |
FEATURE_PARITY.md |
Documents Telegram’s new “setup-time owner verification” capability. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
zmanian
left a comment
There was a problem hiding this comment.
Re-review: All prior items resolved + new verification code mechanism
The 4 original commits are unchanged from my prior review (all 3 blocking items resolved). Two new commits: a staging merge and a significant security improvement.
Prior blocking items (still resolved)
- ChannelRelay activation status -- restored in server.rs with test
- Clippy let...else -- fixed to ?-operator
- No-panics CI -- tests converted to Result<(), String>
New: Verification code replaces first-DM-wins (commit 7373178)
This directly addresses the "first-user-wins during 120s window" concern from my earlier review. Previously, the FIRST private DM sender became the owner. Now:
- System generates an 8-character random code (
rand::thread_rng(), alphanumeric, ~2.8 trillion combinations) - User sees the code + instructions + deep link (
https://t.me/bot?start=CODE) in the configure modal - Polling loop validates the received message matches the code (handles exact match,
/start CODE,/startprefix) - Challenge has 300s TTL, auto-cleared on expiry
deleteWebhookcalled withdrop_pending_updates=trueto ensure bot only receives messages after code issuance
The flow change touches all web handler paths (chat auth token, setup submit, ws) consistently -- result.verification.is_some() broadcasts AuthRequired instead of AuthCompleted, keeping auth mode active until verification completes.
Security assessment
- Code entropy is adequate for a short-lived (5 min) verification token
- No code leakage -- displayed to authenticated user only, sent over HTTPS deep link
textContentused for code display in UI (no XSS)- Expired challenges are auto-pruned on access
CI
Full CI green (all Clippy, Formatting, E2E core/extensions/features, regression check).
Title check: "feat: verify telegram owner during hot activation" -- accurate. The verification code is a natural evolution of the verification mechanism described in the title.
LGTM.
…-activation-tests # Conflicts: # src/channels/wasm/setup.rs # src/channels/web/server.rs # src/extensions/manager.rs
|
bypassing and merging. Already got approvals -> just rebasing/merge conflict resolution. |
There was a problem hiding this comment.
Pull request overview
Adds Telegram “hot activation” support by introducing a setup-time owner-verification challenge, wiring it through the extension manager, web API/SSE, and the web UI, with new unit + E2E coverage.
Changes:
- Introduce
verificationchallenges in extension configure results and surface them via web handlers and UI. - Implement Telegram owner binding (challenge issuance + long-poll verification) and persist owner/bot-username state into settings/runtime config.
- Add E2E scenario coverage and improve E2E isolation/rebuild behavior.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/telegram_auth_integration.rs | Make WASM test artifact discovery more robust (local path + git worktrees). |
| tests/e2e/scenarios/test_telegram_hot_activation.py | New Playwright scenario covering Telegram setup modal + verify-owner flow. |
| tests/e2e/conftest.py | Isolate HOME/base dir for E2E and rebuild the binary when inputs change. |
| src/extensions/mod.rs | Add VerificationChallenge and extend ConfigureResult with verification. |
| src/extensions/manager.rs | Implement Telegram owner verification/binding + runtime config updates + tests. |
| src/channels/web/ws.rs | Treat verification as “still auth required” in WS auth-token flow. |
| src/channels/web/types.rs | Add typed ExtensionActivationStatus + verification field on ActionResponse. |
| src/channels/web/static/style.css | Add styles for Telegram verification panel in configure modal. |
| src/channels/web/static/i18n/en.js | Add Telegram verification UI strings. |
| src/channels/web/static/app.js | Render Telegram verification hint/panel; update configure submit UX. |
| src/channels/web/server.rs | Surface verification through REST handlers + SSE (AuthRequired/AuthCompleted). |
| src/channels/web/handlers/extensions.rs | Use new activation-status classifier + consider owner binding as “active”. |
| src/channels/web/handlers/chat.rs | Update chat auth-token handler to broadcast AuthRequired when verification pending. |
| src/channels/wasm/telegram_host_config.rs | Define Telegram constants + settings key helper for bot username. |
| src/channels/wasm/setup.rs | Inject persisted Telegram bot username into runtime config on startup. |
| src/channels/wasm/mod.rs | Export Telegram host-config helpers for internal use. |
| FEATURE_PARITY.md | Document “setup-time owner verification” for Telegram parity notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Ok(result) => { | ||
| let mut resp = if result.verification.is_some() || result.activated { | ||
| ActionResponse::ok(result.message.clone()) | ||
| } else { | ||
| ActionResponse::fail(result.message.clone()) | ||
| }; | ||
| resp.activated = Some(result.activated); | ||
| resp.auth_url = result.auth_url.clone(); | ||
| resp.verification = result.verification.clone(); | ||
| resp.instructions = result.verification.as_ref().map(|v| v.instructions.clone()); | ||
|
|
||
| state.sse.broadcast(SseEvent::AuthCompleted { | ||
| extension_name: req.extension_name.clone(), | ||
| success: true, | ||
| message: result.message.clone(), | ||
| }); | ||
| if result.verification.is_some() { | ||
| state.sse.broadcast(SseEvent::AuthRequired { | ||
| extension_name: req.extension_name.clone(), | ||
| instructions: Some(result.message), | ||
| auth_url: None, | ||
| setup_url: None, | ||
| }); | ||
| } else if result.activated { | ||
| // Clear auth mode on the active thread | ||
| clear_auth_mode(&state).await; | ||
|
|
||
| state.sse.broadcast(SseEvent::AuthCompleted { |
| Ok(result) => { | ||
| clear_auth_mode(&state).await; | ||
| let mut resp = ActionResponse::ok(result.message.clone()); | ||
| resp.activated = Some(result.activated); | ||
| resp.auth_url = result.auth_url.clone(); | ||
| resp.verification = result.verification.clone(); | ||
| resp.instructions = result.verification.as_ref().map(|v| v.instructions.clone()); | ||
|
|
||
| state.sse.broadcast(SseEvent::AuthCompleted { | ||
| extension_name: req.extension_name.clone(), | ||
| success: true, | ||
| message: result.message.clone(), | ||
| }); | ||
| if result.verification.is_some() { | ||
| state.sse.broadcast(SseEvent::AuthRequired { | ||
| extension_name: req.extension_name.clone(), | ||
| instructions: Some(result.message), | ||
| auth_url: None, | ||
| setup_url: None, | ||
| }); | ||
| } else { | ||
| clear_auth_mode(&state).await; | ||
|
|
||
| state.sse.broadcast(SseEvent::AuthCompleted { |
| if let Some(ref ext_mgr) = state.extension_manager { | ||
| match ext_mgr.configure_token(&extension_name, &token).await { | ||
| Ok(result) => { | ||
| crate::channels::web::server::clear_auth_mode(state).await; | ||
| state | ||
| .sse | ||
| .broadcast(crate::channels::web::types::SseEvent::AuthCompleted { | ||
| extension_name, | ||
| success: true, | ||
| message: result.message, | ||
| }); | ||
| if result.verification.is_some() { | ||
| state.sse.broadcast( | ||
| crate::channels::web::types::SseEvent::AuthRequired { | ||
| extension_name: extension_name.clone(), | ||
| instructions: Some(result.message), | ||
| auth_url: None, | ||
| setup_url: None, | ||
| }, | ||
| ); | ||
| } else { | ||
| crate::channels::web::server::clear_auth_mode(state).await; | ||
| state.sse.broadcast( | ||
| crate::channels::web::types::SseEvent::AuthCompleted { | ||
| extension_name, | ||
| success: true, | ||
| message: result.message, | ||
| }, | ||
| ); | ||
| } |
| let delete_webhook_url = format!("https://api.telegram.org/bot{bot_token}/deleteWebhook"); | ||
| let delete_webhook_resp = client | ||
| .post(&delete_webhook_url) | ||
| .query(&[("drop_pending_updates", "true")]) | ||
| .send() | ||
| .await | ||
| .map_err(|e| telegram_request_error("deleteWebhook", &e))?; | ||
| if !delete_webhook_resp.status().is_success() { | ||
| return Err(ExtensionError::Other(format!( | ||
| "Telegram deleteWebhook failed (HTTP {})", | ||
| delete_webhook_resp.status() | ||
| ))); | ||
| } |
* feat(telegram): verify owner during hot activation * fix(ci): satisfy no-panics and clippy checks * fix(web): preserve relay activation status * fix(telegram): redact setup errors * fix(telegram): require owner verification code * fix(telegram): allow code in conversational dm
Summary
This PR fixes Telegram hot activation so setup can establish the Telegram owner
binding before the channel starts, instead of hot-activating into a
owner_id = nullstate that falls back to pairing.It also adds end-to-end regression coverage around the Telegram setup flow,
owner-aware activation status, and Telegram authorization behavior.
Problem
In
v0.18.0, Telegram setup could successfully:telegram_bot_tokenbut still come up with:
owner_id = nulldm_policy = pairingbot_username = nullThat meant "hot activation worked" at the transport/runtime level, but the
intended owner-verified Telegram experience did not. The first DM to the bot
fell back into pairing behavior instead of using a configured owner binding.
What Changed
Telegram setup now verifies and persists the owner binding
When configuring the Telegram channel, the extension manager now:
getMegetUpdatesto capture the first qualifying private user DMchannels.wasm_channel_owner_ids.telegrambot_usernameAfter activation succeeds for a newly verified Telegram owner, IronClaw also
sends a one-time confirmation DM to that owner so the binding result is visible
inside Telegram.
Telegram startup/hot-activation config is now consistent
The host now restores/passes Telegram-specific runtime config more consistently:
owner_idis injected during hot activation and refresh flowsbot_usernameis restored on startup as well, not only on the hot pathThis keeps post-restart Telegram behavior aligned with hot activation.
Web/UI status handling is shared and typed
The Extensions UI logic was tightened so owner-bound Telegram channels show as
activeinstead of incorrectly presenting as still awaiting pairing.This PR also refactors activation-status classification away from duplicated
stringly-typed logic into a shared typed helper used by the web handlers.
Telegram setup UI now explains the owner-verification step
The web configure modal now tells the user that, after saving the bot token,
they need to send a private message to the bot so IronClaw can verify them as
the owner. The modal also shows a waiting state while setup is in progress.
The agent-thread auth/setup prompt for Telegram now carries the same guidance.
E2E fixture isolation and worktree reliability
The E2E harness now:
HOME/IRONCLAW_BASE_DIRFiles of Note
src/extensions/manager.rschannels-src/telegram/src/lib.rssrc/channels/web/types.rsExtensionActivationStatussrc/channels/web/server.rssrc/channels/web/handlers/extensions.rssrc/channels/web/static/app.jssrc/channels/web/static/i18n/en.jssrc/channels/web/static/style.csssrc/channels/wasm/setup.rssrc/channels/wasm/telegram_host_config.rstests/e2e/conftest.pytests/e2e/scenarios/test_telegram_hot_activation.pytests/telegram_auth_integration.rsTest Coverage
Rust manager/unit coverage
test_telegram_hot_activation_runtime_config_includes_owner_idtest_telegram_hot_activation_configure_uses_mock_loader_and_persists_statetest_notify_telegram_owner_verified_sends_confirmation_for_new_bindingtest_notify_telegram_owner_verified_skips_existing_bindingtest_telegram_auth_instructions_include_owner_verification_guidancetest_wasm_channel_activation_status_owner_bound_counts_as_activeTelegram auth integration coverage
tests/telegram_auth_integration.rscontinues to verify the message-levelauthorization behavior:
owner_idis setowner_idis nullPlaywright coverage
tests/e2e/scenarios/test_telegram_hot_activation.pycovers:Verification
cargo test --lib test_telegram_hot_activation -- --nocapturecargo test --lib test_notify_telegram_owner_verified -- --nocapturecargo test --lib test_telegram_auth_instructions_include_owner_verification_guidance -- --nocapturecargo test --lib test_wasm_channel_activation_status_owner_bound_counts_as_active -- --nocapturecargo test --test telegram_auth_integration -- --nocapture/Users/henry/near_ai/near_claw/ironclaw/tests/e2e/.venv/bin/pytest tests/e2e/scenarios/test_telegram_hot_activation.py -qFeature Parity
Updated
FEATURE_PARITY.mdto note Telegram setup-time owner verification.