chore(release): pending release v0.47.0#698
Open
fro-bot[bot] wants to merge 2 commits into
Open
Conversation
…sages (#697) * chore(gateway): add hono dependency for announce webhook Adds hono@4.12.23 + @hono/node-server@1.19.14 (matching apps/workspace-agent's pinned versions) so the gateway can host the announce webhook HTTP server. Includes the implementation plan. * feat(gateway): announce webhook config, HMAC, payload schema, presence posting Building blocks for the POST /v1/announce control-plane presence webhook: - Config: GATEWAY_WEBHOOK_SECRET, GATEWAY_PRESENCE_CHANNEL_ID, GATEWAY_HTTP_PORT - HMAC-SHA256 verification over timestamp + '.' + rawBody (Stripe-style), with constant-time compare, length guards, and a replay-window check - Effect Schema payload validation (two v1 event types; unknown rejected) with content-free error reasons - Presence channel posting helper that resolves a channel by ID and sends an embed with allowedMentions:{parse:[]} * feat(gateway): announce embed templates registry Maps each announce event_type to a Discord embed with an accent color and in-character text. Honors a non-null rendered_text override verbatim (v1 emits null). Includes reserved color stubs for the not-yet-emitted fast-follower event types. * feat(gateway): announce webhook HTTP server and request handler Adds the POST /v1/announce Hono server and the request pipeline: 8 KB size cap, per-source rate limiting, HMAC verification, replay-window check, an in-memory replay cache, exact-string timestamp cross-check, schema decode, embed render, and presence post. Authentication failures return an identical 401 so callers cannot tell which check failed; the replay signature is recorded only after a successful Discord post so retries after a post failure still succeed. Reject logging records the reason only, never the body. * feat(gateway): wire announce server into program lifecycle and shutdown Starts the announce HTTP server during gateway boot and closes it in the shutdown drain alongside the Discord client; a server-close failure is logged without masking client teardown. New announce requests are refused with 503 while the gateway is draining for shutdown. * fix(gateway): harden announce webhook against concurrent replay and rate-limit spoofing - Replace the replay check/record pair with an atomic reserve/commit/release so two concurrent requests carrying the same signature can no longer both post; the reservation is released on every failure path so a legitimate retry after a failed post still succeeds. - Key rate limiting on the TCP socket remote address instead of the caller-supplied X-Forwarded-For header, and bound the limiter to a maximum number of tracked keys to prevent unbounded pre-auth memory growth. - Truncate embed descriptions to Discord's 4096-character limit so an over-long payload cannot wedge the control plane into endless retries. - Drop an unreachable parse-error classification branch, share the body-size constant, and make the payload schema value module-private. * docs(gateway): document announce webhook http/ layer and Schema usage Updates the gateway agent notes for the new src/http/ announce webhook: the fail-closed request pipeline, the generic-401 no-oracle auth behavior, the presence posting helper, the shutdown drain that closes the HTTP server, and the GATEWAY_ webhook config vars. Marks Effect Schema as now in use. * fix(gateway): reject oversized announce bodies during read and bound the Discord post - Enforce the 8 KB announce body cap with streaming bodyLimit middleware so an oversized request is rejected while the body is read, not after the whole payload has been buffered into memory. The earlier content-length precheck was bypassable with chunked transfer encoding, leaving an unauthenticated memory-pressure path; the streaming limit closes it. - Bound the Discord fetch-and-post with a timeout so a hung call can no longer leave a replay reservation pinned for the process lifetime, which would have permanently blocked retries for that signature. - Fall back to the templated description when rendered_text is empty or whitespace-only, avoiding an empty embed that Discord would reject.
8 tasks
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.
Pending Release: v0.47.0
This PR tracks changes pending release. Released on the next auto-release cycle (Sunday/Wednesday) or via manual dispatch.
Merge this PR to trigger a release. Releases also run automatically on Sunday/Wednesday at 20:00 UTC, or via manual workflow dispatch.
Commits Since Last Release
Auto-generated by the release pipeline. Updated: 2026-05-30 03:01 UTC