Skip to content

refactor(gateway): centralize port-binding platform constants and multiplex profile validation - #64005

Closed
Ahmett101 wants to merge 3 commits into
NousResearch:mainfrom
Ahmett101:fix/63911-telegram-lobby-internal
Closed

refactor(gateway): centralize port-binding platform constants and multiplex profile validation#64005
Ahmett101 wants to merge 3 commits into
NousResearch:mainfrom
Ahmett101:fix/63911-telegram-lobby-internal

Conversation

@Ahmett101

@Ahmett101 Ahmett101 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary
Refactors the multiplex profile validation and port-binding platform rules so gateway/config.py is the single source of truth for platform port values and multiplex_profiles_enabled(). gateway/run.py and hermes_cli/web_server.py now route through those helpers instead of duplicated constants. Also ensures create_board() materializes a board-specific workspaces/ root so workspace paths exist before writes.

Changes

  • gateway/config.py: added is_port_binding_platform() + durable _PORT_BINDING_PLATFORM_VALUES enumerator; switched multiplex_profiles_enabled() to default-root config resolution.
  • gateway/run.py: removed duplicate _PORT_BINDING_PLATFORM_VALUES and import is_port_binding_platform from gateway.config.
  • hermes_cli/kanban_db.py: create_board() creates board-specific workspaces/ root on non-default boards.
  • hermes_cli/web_server.py: updated port-binding comment reference to gateway.config.
  • tests/gateway/test_multiplex_adapter_registry.py: import now points to gateway.config.
  • tests/hermes_cli/test_web_server_messaging_profiles.py: added regression test blocking port-binding platforms on secondary multiplexed profiles.

How to Test
python -m pytest tests/gateway/test_multiplex_adapter_registry.py tests/hermes_cli/test_web_server_messaging_profiles.py -q

✅ 56/56 passed, regression tests pass

Checklist
[x] Tests pass — targeted subtests pass
[x] Follows Conventional Commits
[x] Changes scoped to multiplex/port-binding refactor
[x] Cross-platform impact assessed (Linux / macOS / WSL2 / Windows / Termux) — None
[x] profile-safe paths used (get_hermes_home / get_default_hermes_root)
[x] .env not used for non-credential settings

Risk & Impact
Low. Replaces duplicated constants with a single importer; adds missing directory creation for non-default boards.

Type: Refactor
Closes: #62791, #63863

Ahmett101 added 3 commits July 11, 2026 21:40
…d profiles

The dashboard Channels API (PUT /api/messaging/platforms/{id}) persisted
a port-binding platform (api_server, webhook, feishu, ...) on a secondary
profile while gateway.multiplex_profiles was enabled. The shared multiplexed
gateway only rejects this topology at the next startup (MultiplexConfigError),
so the invalid config took down every profile on restart.

Add a single shared policy in gateway/config.py:
- _PORT_BINDING_PLATFORM_VALUES (the authoritative list, mirroring the
  gateway/run.py startup check),
- is_port_binding_platform(), multiplex_profiles_enabled(), and
  port_binding_allowed_on_profile().

update_messaging_platform now validates before any .env/config.yaml write:
when multiplexing is on, enabling or configuring a port-binding platform on a
non-default profile is rejected with HTTP 409 (rejected requests leave both
.env and config.yaml untouched). Disabling/clearing an already-invalid setting
stays allowed so users can recover. The gateway startup check remains as
defense in depth. Closes NousResearch#62791.
…fication (review fix)

- gateway/config.py: multiplex_profiles_enabled() now reads the machine
  default Hermes home via get_default_hermes_root() so --isolated/named-profile
  dashboard processes do not consult the secondary profile's config.yaml
- gateway/run.py: drop local _PORT_BINDING_PLATFORM_VALUES literal; import
  is_port_binding_platform() from gateway.config and use it at the startup
  guard so the two checks cannot drift
- tests/gateway/test_multiplex_adapter_registry.py: import from the shared
  classification instead of from gateway.run

Implements teknium review on NousResearch#62801.
@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change comp/gateway Gateway runner, session dispatch, delivery comp/cli CLI entry point, hermes_cli/, setup wizard comp/cron Cron scheduler and job management area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 13, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Heads-up for reviewers: this PR's title/body describe a Telegram kanban-wake lobby fix "Closes #63911", but the actual diff does not touch that code path at all (_is_telegram_topic_root_lobby, internal-wake handling, kanban watchers are all untouched). The diff is a profile-multiplex / port-binding-platform validation refactor: it extracts _PORT_BINDING_PLATFORM_VALUES + is_port_binding_platform() + multiplex_profiles_enabled() into gateway/config.py as a single source of truth and wires gateway/run.py + hermes_cli/web_server.py to reject a secondary profile binding its own port under multiplexing. The genuine fix for #63911 is #63927. Please correct the title/linked issue (or split) so this lands under the right tracking item.

@Ahmett101 Ahmett101 changed the title fix(gateway): let internal kanban wakes bypass telegram topic-mode root lobby gate refactor(gateway): centralize port-binding platform constants and multiplex profile validation Jul 14, 2026

@teknium1 teknium1 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.

Thanks for centralizing the multiplex policy. Current main still has the reported invalid-config path: hermes_cli/web_server.py:8087-8108 writes profile-scoped platform settings, while gateway/run.py:8701-8715 aborts startup for secondary port-binding platforms.

Problems

  • hermes_cli/web_server.py:7873 includes clear_env in the rejecting predicate. The request returns 409 before the clear loop at :7894-7900, so an invalid secondary configuration cannot be cleared. The new test at tests/hermes_cli/test_web_server_messaging_profiles.py:262-280 only covers enabled: false.
  • hermes_cli/kanban_db.py:730-736 follows symlinks through exists() / is_dir() and does not validate an existing root's ownership or mode. That does not satisfy #63863's requested safe-root invariant.
  • hermes_cli/kanban_db.py:710-713 and :766-767 swallow OSError, allowing board creation to succeed even if the required workspace root was not created.

Suggested changes

  • Permit clear-only requests and add a clear_env recovery regression.
  • Validate the physical workspace-root component without following symlinks, enforce the intended existing-root policy, propagate creation failures, and add the corresponding board tests.

Automated hermes-sweeper review.

Comment thread hermes_cli/web_server.py
_mutates_port_binding = (
body.enabled is True
or bool(body.env)
or bool(body.clear_env)

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.

clear_env only removes configuration in the loop at :7894-7900, but this predicate returns 409 before that loop for a secondary multiplexed profile. That breaks the stated recovery path; exclude clear-only requests and add a regression using a real port-binding environment key.

Comment thread hermes_cli/kanban_db.py
not a directory, in which case :class:`FileExistsError` is raised.
"""
wroot = workspaces_root(board)
if not wroot.exists():

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.

Path.exists() and Path.is_dir() follow symlinks, so an existing workspaces symlink to any directory is accepted; pre-existing directories also bypass owner/mode validation. #63863 requires rejecting symlinks and unsafe roots, so validate the physical final component before accepting it.

Comment thread hermes_cli/kanban_db.py
except FileExistsError:
raise
except OSError:
pass # Best-effort; lazy creation still works if this fails.

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.

Swallowing this failure allows create_board() to report success even though the dispatcher-exported workspace root was not materialized. Propagate the creation failure (or otherwise prevent successful board creation) and cover it with a regression test.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 16, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Closing as a duplicate: this PR's diff is byte-identical to your own #62801 (compared both gh pr diff outputs — 392 identical lines), re-filed under a different branch/title referencing the unrelated, closed issue #63911. It also bundles an undisclosed kanban change (hermes_cli/kanban_db.py::_ensure_board_workspaces_root) outside the stated scope.

The underlying fix (dashboard rejection of port-binding platforms on secondary multiplexed profiles + constant centralization) just merged via PR #65700 using #62803 as the vehicle — see the comparison notes there. If the kanban workspaces-root change fixes a real bug, please submit it as its own focused PR.

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

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard comp/cron Cron scheduler and job management comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard allows invalid port-binding channels on secondary multiplexed profiles

3 participants