327e9043e9
NtfyAdapter.__init__, _env_enablement, check_requirements, validate_config, is_connected, and _standalone_send all read NTFY_SERVER_URL/NTFY_TOPIC/ NTFY_PUBLISH_TOPIC/NTFY_MARKDOWN/NTFY_HOME_CHANNEL(_NAME) via raw os.getenv -- only NTFY_TOKEN already went through the module's _get_scoped_secret helper. Under gateway.multiplex_profiles, env_enablement_fn/check_fn/ is_connected all run inside the registry-enablement loop in load_gateway_config() (confirmed in gateway/config.py, lines ~2704-2820, inside _profile_runtime_scope for secondary profiles), and adapter construction likewise runs scoped -- so os.environ there still holds the DEFAULT profile's env-bridge output. A secondary profile with its own (or no) ntfy topic configured could silently: - get auto-enabled via _env_enablement()/is_connected() using the default profile's topic, even though it never configured ntfy itself - have its adapter subscribe to / publish on the default profile's topic and server instead of (or in addition to) its own - deliver cron/send_message_tool messages via _standalone_send to the wrong topic Switch every raw NTFY_* read (except the two secret-material fields already scoped: NTFY_TOKEN) to _get_scoped_secret(), matching the established helper already defined in this module and used for NTFY_TOKEN, and the same pattern applied to the sibling LINE/DingTalk/ Teams/SMS/WeCom adapters in this series. Adds a new TestMultiplexProfileScope class to tests/gateway/test_ntfy_plugin.py (7 tests) mirroring the fixture/assertion style established in tests/gateway/test_line_plugin.py's TestMultiplexProfileScope. Mutation- verified: stashed the production fix and confirmed 5 of the 7 new tests fail against pre-fix code (the other 2 are non-differentiating regression guards -- extra-wins-over-env and unscoped-default-profile-precedence -- which correctly pass either way); restored the fix and confirmed all 37 tests in the file, plus the file's 5 parametrized _get_scoped_secret tests in test_adapter_startup_secret_scope.py, pass.