Open the news ingest endpoint by default, wire NEWS_INGEST_URL in compose - #137
Merged
Conversation
… compose POST /internal/news was fail-closed on CONVERSATION_BACKEND_TOKEN and no deployment set NEWS_INGEST_URL, so the deterministic news rail merged in #114 was inert everywhere and needed two manual variables to come alive. Two problems, both fixed here: - Authenticating this endpoint buys no integrity. The rail exists to carry broadcast content the deployment does not control — a post in an open channel is written by whoever cares to write it and reaches the Herald through the legitimate path anyway. Meanwhile fail-closed fails *silently*, because forward_news() swallows a 403 by design. The endpoint is now open unless NEWS_INGEST_TOKEN is set, which is enforced when it is. - It gets its own variable rather than reusing CONVERSATION_BACKEND_TOKEN: the entrypoint generates that one whenever it is missing, so "no token configured" would never be observable and every gateway call would 403. /internal/conversations and /internal/email stay fail-closed — they push to the user's devices and send mail; filing a feed reference reaches nobody. NEWS_INGEST_URL now defaults to the in-network web-gateway address on all three gateway services, alongside RETINUE_GATEWAY_URL and STT_SERVICE_URL, so the rail needs no deployment configuration. Tests: tests/test_news_ingest_auth.py (4 cases, incl. the generated-token trap). Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #114. The deterministic news rail it merged is inert in every deployment:
POST /internal/newsis fail-closed onCONVERSATION_BACKEND_TOKEN, and no compose file setsNEWS_INGEST_URL. Both had to be wired by hand, for a URL that only ever has one sensible value.Open by default
The rail carries broadcast content the deployment does not control — a post in an open channel is written by whoever cares to write it, and reaches the Herald through the legitimate path regardless. Authenticating the transport therefore buys no integrity for what lands in the feed, while a fail-closed default fails silently:
forward_news()is best-effort and swallows a 403, so a token mismatch produces a rail that looks wired and quietly drops every item.POST /internal/newsnow accepts an untokened call. A deployment that wants it locked down setsNEWS_INGEST_TOKEN, which is enforced when present./internal/conversationsand/internal/emailstay fail-closed. They push to the user's devices and send mail; filing a feed reference reaches nobody.Why a separate variable
Reusing
CONVERSATION_BACKEND_TOKENwould not work:scripts/entrypoint.shgenerates it whenever it is missing, so the web-gateway always holds one while the gateway containers never see it. "No token configured" would be unreachable and every forward would 403 — the exact silent failure this PR removes.tests/test_news_ingest_auth.pypins that case.news_ingest.pystill falls back toCONVERSATION_BACKEND_TOKENwhenNEWS_INGEST_TOKENis unset, so a deployment wired before this PR keeps working.Zero-config URL
NEWS_INGEST_URL=http://retinue:8080/internal/newsis now set on all three gateway services in the base compose file, next to theRETINUE_GATEWAY_URLandSTT_SERVICE_URLentries that already follow that pattern. In-network addresses belong in the base compose; only deployment-specific values belong in an override. Emptying it disables the rail.Changes
scripts/web-gateway.py—_news_ingest_authorized(), with the reasoning in its docstring;_handle_internal_newsuses it.scripts/news_ingest.py— prefersNEWS_INGEST_TOKEN, falls back to the old variable.docker-compose.yml—NEWS_INGEST_URLdefault plus optionalNEWS_INGEST_TOKENpassthrough on the three gateway services.docs/triage-delivery-gate.md— documents the asymmetry and drops the stale "token-gated" wording.tests/test_news_ingest_auth.py— new, 4 cases.Verification
tests/test_news_ingest_auth.py4/4,test_news_gateway.py,test_news_store.py,test_triage_policy.py13/13 andtest_web_gateway_send_page.py5/5 all pass; both touched scripts compile; the compose file parses and yields the new entries on all three services.Tier 3 — takes effect on merge plus a rebuild of the gateway images.