fix(platforms): cron home order and dashboard value checks match main (review)

- origin-less cron reports: platforms outside the priority list follow registry order again,
  as on main, instead of an alphabetical sort.
- dashboard PUT: without rules on the entry (the dashboard profile disabled the plugin, or a user
  plugin overrides it) a bundled platform's dashboard_card.py supplies them, read from its file,
  so the edited profile's Telegram/Slack values are still checked. The file loader is now
  gateway.platform_env.bundled_sibling(directory, stem).
This commit is contained in:
Teknium committed 2026-10-16 19:42:34 -07:00
1 parent fb5e7b6143
commit 7789d75c64
3 files changed
+21 -17

No files matched your search

+2 -2
View File
@@ -505,9 +505,9 @@ def _iter_home_target_platforms():
from hermes_cli.plugins import discover_plugins
discover_plugins() # idempotent
from gateway.platform_registry import platform_registry
named = {e.name for e in platform_registry.plugin_entries() if e.cron_deliver_env_var}
named = [e.name for e in platform_registry.plugin_entries() if e.cron_deliver_env_var]
yield from (n for n in _HOME_TARGET_PRIORITY if n in named)
yield from sorted(named - set(_HOME_TARGET_PRIORITY))
yield from (n for n in named if n not in _HOME_TARGET_PRIORITY) # registry order, as before
def _relay_fronted_delivery_platforms(connected: set) -> set:
+11 -13
View File
@@ -185,13 +185,17 @@ _BUNDLED_ENV_SIBLINGS = {"wecom_callback": ("wecom", "CALLBACK_")}
@functools.cache
def _bundled_gateway_env_module(directory: str) -> Any:
"""``plugins/platforms/<directory>/gateway_env.py`` executed from its file under a private name:
the plugin package (``__init__``, adapter, ``register()``) is never imported. None when absent."""
path = Path(__file__).resolve().parent.parent / "plugins" / "platforms" / directory / "gateway_env.py"
def bundled_sibling(directory: str, stem: str = "gateway_env") -> Any:
"""``plugins/platforms/<directory>/<stem>.py`` (a light declaration module importing only core)
executed from its file under a private name: the plugin package (``__init__``, adapter,
``register()``) is never imported. None when absent or *directory* is not a bundled plugin."""
from gateway.config import Platform
if directory not in Platform._scan_bundled_plugin_platforms()[0]:
return None
path = Path(__file__).resolve().parent.parent / "plugins" / "platforms" / directory / f"{stem}.py"
if not path.is_file():
return None
spec = importlib.util.spec_from_file_location(f"_hermes_bundled_gateway_env_{directory}", path)
spec = importlib.util.spec_from_file_location(f"_hermes_bundled_{stem}_{directory}", path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
@@ -202,11 +206,8 @@ def bundled_env_rows(name: str) -> Optional[tuple]:
the plugin. For when its registry entry is absent: discovery suppressed (a parked profile's
config read, ``HERMES_SAFE_MODE``) or the plugin disabled. These rows were core's own table, and
the duplicate-credential guard and the explicit-disable warning still need them then."""
from gateway.config import Platform
directory, prefix = _BUNDLED_ENV_SIBLINGS.get(name, (name, ""))
if directory not in Platform._scan_bundled_plugin_platforms()[0]:
return None
module = _bundled_gateway_env_module(directory)
module = bundled_sibling(directory)
if module is None:
return None
return (tuple(getattr(module, f"{prefix}ENV_OVERRIDES", ()) or ()),
@@ -216,11 +217,8 @@ def bundled_env_rows(name: str) -> Optional[tuple]:
def bundled_authz(name: str) -> dict:
"""``AUTHZ`` (allowlist / allow-all / allow-bots / own-policy env names) a bundled platform
plugin declares in its ``gateway_env.py``, read without the plugin; {} for other names."""
from gateway.config import Platform
directory, prefix = _BUNDLED_ENV_SIBLINGS.get(name, (name, ""))
if directory not in Platform._scan_bundled_plugin_platforms()[0]:
return {}
module = _bundled_gateway_env_module(directory)
module = bundled_sibling(directory)
return dict(getattr(module, f"{prefix}AUTHZ", None) or {}) if module is not None else {}
+8 -2
View File
@@ -106,10 +106,16 @@ def _env_value_rules(platform_id: str) -> dict[str, tuple[Any, str]]:
Resolve this in the request's own scope, right after :func:`_require_platform`: the catalog build
there has just materialized every plugin entry, so the lookup imports nothing, whereas inside
``_profile_scope`` the registry's profile overlay may not hold the entry and every rule would
silently stop applying."""
silently stop applying. Without rules on the entry (the dashboard's own profile disabled the
plugin, a user plugin overrides it) a bundled platform's ``dashboard_card.py`` answers, read from
its file: the rules guard the edited profile's values whatever the dashboard's profile loads."""
from gateway.platform_env import bundled_sibling
from gateway.platform_registry import platform_registry
entry = platform_registry.get(platform_id)
return dict(entry.env_value_rules) if entry is not None else {}
if entry is not None and entry.env_value_rules:
return dict(entry.env_value_rules)
card = getattr(bundled_sibling(platform_id, "dashboard_card"), "DASHBOARD_CARD", None) or {}
return dict(card.get("env_value_rules") or {})
def _validate_messaging_env_value(rules: dict[str, tuple[Any, str]], key: str, value: str) -> None: