From d5db817391dab4d2e1cd8cd7289aa663cb4093f6 Mon Sep 17 00:00:00 2001 From: Patrick Buckley Date: Thu, 5 Mar 2026 18:01:47 -0800 Subject: [PATCH] Fix channel gateway Docker networking and console proxy approval scope Two runtime bugs: 1. Channel gateway advertised http://127.0.0.1:8091 which is unreachable from other Docker containers. Add TURNSTONE_CHANNEL_ADVERTISE_URL env var override for Docker/K8s environments, set to http://channel:8091 in compose.yaml, and pass --http-host=0.0.0.0 so the gateway listens on all interfaces. 2. Console proxy service JWT had only "write" scope but the approval endpoint requires "approve". Tool approval buttons in the server web UI silently failed when accessed through the console proxy. Changed proxy token scopes to read+write+approve. --- compose.yaml | 2 ++ turnstone/channels/cli.py | 16 ++++++++++------ turnstone/console/server.py | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compose.yaml b/compose.yaml index 9bfc7915..4e039a8f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -213,6 +213,7 @@ services: turnstone-channel --redis-host=redis --redis-port=6379 + --http-host=0.0.0.0 $${TURNSTONE_DISCORD_GUILD:+--discord-guild $$TURNSTONE_DISCORD_GUILD} environment: - TURNSTONE_DISCORD_TOKEN=${TURNSTONE_DISCORD_TOKEN:-} @@ -221,6 +222,7 @@ services: - TURNSTONE_JWT_SECRET=${TURNSTONE_JWT_SECRET:-} - TURNSTONE_DB_BACKEND=${DB_BACKEND:-sqlite} - TURNSTONE_DB_URL=${DATABASE_URL:-} + - TURNSTONE_CHANNEL_ADVERTISE_URL=http://channel:8091 networks: - turnstone-net depends_on: diff --git a/turnstone/channels/cli.py b/turnstone/channels/cli.py index 0dddaf8a..fd647f4d 100644 --- a/turnstone/channels/cli.py +++ b/turnstone/channels/cli.py @@ -181,12 +181,16 @@ def main() -> None: service_id = _get_service_id() - # Resolve advertise address — 0.0.0.0/:: are not routable - if args.http_host in ("0.0.0.0", "::"): - advertise_host = socket.gethostname() - else: - advertise_host = args.http_host - service_url = f"http://{advertise_host}:{args.http_port}" + # Resolve advertise URL — env override for Docker/K8s, + # otherwise derive from bind address. + advertise_url = os.environ.get("TURNSTONE_CHANNEL_ADVERTISE_URL", "").strip() + if not advertise_url: + if args.http_host in ("0.0.0.0", "::"): + advertise_host = socket.gethostname() + else: + advertise_host = args.http_host + advertise_url = f"http://{advertise_host}:{args.http_port}" + service_url = advertise_url # Register in service registry storage.register_service("channel", service_id, service_url) diff --git a/turnstone/console/server.py b/turnstone/console/server.py index 3929ce17..809df4db 100644 --- a/turnstone/console/server.py +++ b/turnstone/console/server.py @@ -1401,7 +1401,7 @@ def main() -> None: proxy_token_mgr = ServiceTokenManager( user_id="console-proxy", - scopes=frozenset({"write"}), + scopes=frozenset({"read", "write", "approve"}), source="console", secret=jwt_secret, audience=JWT_AUD_SERVER,