bf51fee548
The "one gateway for all profiles" section had drifted from the runtime. Each
claim was re-verified at its defining symbol on current main and rewritten to
the behaviour users will actually see:
- named-profile guard: only `gateway run` refuses (exit 78 / EX_CONFIG,
systemd RestartPreventExitStatus; launchd KeepAlive still retries);
`start`/`install` do not refuse themselves and the message lands in the
service log; `--force` is a `run`-only flag
(hermes_cli/gateway.py::_guard_named_profile_under_multiplexer, _cmd_start)
- same (platform, token) in two profiles: the duplicate adapter is parked as
fatal/duplicate_credential and the gateway keeps running — it was described
as a fail-fast startup error (gateway/run_adapters.py::_refuse_duplicate_claim)
- status surfaces: one gateway_state.json under the default home with
`<profile>:<platform>` entries + served_profiles; nothing is written under a
secondary home (the page claimed a per-profile runtime_status.json), and
`hermes status` does not list served profiles — `gateway list`,
`-p X gateway status` and /api/status do (gateway/status.py::write_runtime_status,
hermes_cli/status.py::_render_gateway, hermes_cli/gateway.py::_cmd_status)
- API_SERVER_KEY in a secondary .env auto-enables api_server and trips the
port-binding skip; document the `enabled: false` pin
(gateway/config_env.py::_api_server / _enable_from_env)
- allowlist: it is a start-time snapshot, and the Desktop backend's cron
ticker enumerates every local profile regardless of it
(hermes_cli/web_server.py::_start_desktop_cron_ticker)
- routed-profile cron via the shared bot: only when the profile has no live
adapter of its own, and a route carrying guild_id never matches a cron
target because delivery matches on chat_id/thread_id only
(cron/scheduler_provider.py::tick_adapters_for,
cron/scheduler_preflight.py::SharedRouteAdapters.get)
- add a "What is isolated per profile" table (credentials, authorization,
endpoints, media denylist, MCP child env, outbound egress, session
namespace, logs, terminal) describing behaviour, not PR numbers
- configuration.md: the ${VAR} scoping paragraph now says where it applies
and links to the table