Skip to content

Fix WASM channel startup restore semantics#2563

Merged
serrrfirat merged 1 commit intostagingfrom
auto-start-fix
Apr 17, 2026
Merged

Fix WASM channel startup restore semantics#2563
serrrfirat merged 1 commit intostagingfrom
auto-start-fix

Conversation

@henrypark133
Copy link
Copy Markdown
Collaborator

Summary

  • restore only startup-active WASM channels instead of treating every installed channel as active
  • make startup use activated_channels as the authoritative source once persisted, with setup-selected channels as a first-run fallback
  • keep extension list status accurate for installed but inactive WASM channels and document the fallback behavior

Testing

  • cargo fmt --all
  • cargo test --lib load_startup_active_channels
  • cargo test --lib register_startup_channels_only_restores_persisted_active_channels
  • cargo test --lib test_extensions_list_handler_reports_installed_inactive_wasm_channel_as_inactive
  • cargo test --lib normalize_extension_names_canonicalizes_deduplicates_and_skips_invalid

Copilot AI review requested due to automatic review settings April 17, 2026 03:50
@github-actions github-actions bot added scope: channel/web Web gateway channel scope: channel/wasm WASM channel runtime scope: config Configuration scope: extensions Extension management scope: setup Onboarding / setup scope: docs Documentation size: L 200-499 changed lines risk: high Safety, secrets, auth, or critical infrastructure contributor: core 20+ merged PRs labels Apr 17, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refines the WASM channel startup process by ensuring that only explicitly activated channels are restored. It introduces a fallback mechanism where the setup wizard's configuration is used only until runtime activation state is persisted in the database. I have identified two critical issues regarding extension name canonicalization: the current check for active channels is case-sensitive and fails to account for name normalization (e.g., dashes vs underscores), and the returned list of channel names should use canonicalized forms to maintain consistency with the activation tracking logic in the main entry point.

Comment on lines +169 to +176
let channel_name = loaded.name().to_string();
if !startup_active_channel_names.contains(&channel_name) {
tracing::debug!(
channel = %channel_name,
"Skipping installed but inactive WASM channel during startup restore"
);
continue;
}
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.

high

The check against startup_active_channel_names is case-sensitive and does not account for extension name canonicalization (e.g., converting dashes to underscores). Since startup_active_channel_names is populated using normalize_extension_names, it contains canonicalized names. If loaded.name() returns a non-canonical form (like my-channel or Telegram), it will be incorrectly skipped during startup restore.

You should canonicalize the loaded channel's name before checking the set, handling potential errors gracefully as per project standards.

        let raw_name = loaded.name();
        let channel_name = match crate::extensions::naming::canonicalize_extension_name(raw_name) {
            Ok(name) => name,
            Err(e) => {
                tracing::warn!(channel = %raw_name, error = %e, "Skipping WASM channel with invalid name");
                continue;
            }
        };

        if !startup_active_channel_names.contains(&channel_name) {
References
  1. When parsing resources that can fail, centralize the parsing logic into a single function that handles errors gracefully (e.g., by logging a warning and returning None) to ensure consistent behavior.

Comment on lines 209 to 210
channel_names.push(name.clone());
channels.push((name, channel));
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.

high

To ensure consistency with the activation tracking logic in main.rs, the channel_names vector should contain canonicalized names. If register_wasm_channel returns the raw name from the manifest, it may cause mismatches when checking active_at_startup.contains(name) later. Using the canonicalized channel_name (as defined at the start of the loop) ensures that the returned list matches the authoritative state in the settings store.

Suggested change
channel_names.push(name.clone());
channels.push((name, channel));
channel_names.push(channel_name.clone());
channels.push((channel_name, channel));

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eab6c039c3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/extensions/manager.rs
Ok(Some(value)) => match serde_json::from_value(value) {
Ok(names) => names,
Ok(Some(value)) => match serde_json::from_value::<Vec<String>>(value) {
Ok(names) => normalize_extension_names(names),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve legacy relay names when reading activated_channels

Normalizing persisted activated_channels names at load time can break relay auto-restore for upgraded instances that still use legacy hyphenated keys. After this conversion, restore_relay_channels() receives canonicalized names (e.g. slack_relay) but is_relay_channel() only checks an exact relay:{name}:team_id key, so existing relay:slack-relay:team_id entries are missed and startup silently skips reconnecting the relay until a manual reactivation migrates state.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts WASM channel startup/restore behavior to align “active” semantics with persisted runtime activation state, rather than treating all installed channels as active at boot.

Changes:

  • Introduces activated_channels-first restore logic with settings.channels.wasm_channels (now configured_wasm_channels in resolved config) as a first-run fallback.
  • Adds normalize_extension_names() to canonicalize/dedupe/skip invalid channel/extension names when restoring.
  • Updates startup registration so only startup-active WASM channels are restored/registered, and extends tests to ensure installed-but-inactive channels report correctly.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/main.rs Computes startup-active channel set and passes it into WASM channel setup; uses it for post-startup auto-activation.
src/channels/wasm/setup.rs Filters startup restore to only channels in the startup-active set.
src/extensions/manager.rs Adds load_startup_active_channels() and normalizes persisted activated_channels.
src/extensions/naming.rs Adds normalize_extension_names() + unit test.
src/config/channels.rs Adds configured_wasm_channels to resolved config (from settings wizard selection).
src/config/mod.rs Updates Config::for_testing() to include configured_wasm_channels.
src/tunnel/mod.rs Updates test helper ChannelsConfig construction for new field.
src/settings.rs Updates docs for wasm_channels to reflect fallback semantics.
src/setup/README.md Documents the first-run fallback vs persisted activated_channels behavior.
src/channels/web/server.rs Adds regression test ensuring installed inactive WASM channels list as inactive.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main.rs
Comment on lines +415 to +426
let startup_active_channel_names = if let Some(ref ext_mgr) = components.extension_manager {
ext_mgr
.load_startup_active_channels(
&config.owner_id,
config.channels.configured_wasm_channels.clone(),
)
.await
} else {
normalize_extension_names(config.channels.configured_wasm_channels.clone())
};
let startup_active_channel_name_set: HashSet<String> =
startup_active_channel_names.iter().cloned().collect();
Comment on lines +168 to +176
for loaded in loaded_channels {
let channel_name = loaded.name().to_string();
if !startup_active_channel_names.contains(&channel_name) {
tracing::debug!(
channel = %channel_name,
"Skipping installed but inactive WASM channel during startup restore"
);
continue;
}
Copy link
Copy Markdown
Collaborator

@serrrfirat serrrfirat left a comment

Choose a reason for hiding this comment

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

Reviewed: clean semantics fix for WASM channel startup restore. Normalization is consistent across both read paths, fallback logic is sound, test coverage is solid.

@serrrfirat serrrfirat merged commit 2474f65 into staging Apr 17, 2026
15 of 19 checks passed
@serrrfirat serrrfirat deleted the auto-start-fix branch April 17, 2026 04:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: high Safety, secrets, auth, or critical infrastructure scope: channel/wasm WASM channel runtime scope: channel/web Web gateway channel scope: config Configuration scope: docs Documentation scope: extensions Extension management scope: setup Onboarding / setup size: L 200-499 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants