feat: add AWS EventBridge destination - #1059
Open
pryzmatical wants to merge 1 commit into
Open
Conversation
Adds aws_eventbridge as a new destination type, following the existing aws_kinesis/aws_sqs provider pattern (internal/destregistry/providers/ destawseventbridge). Implements the shape discussed on hookdeck#201: - config.event_bus_name (optional, name or ARN) + config.region (required) + config.endpoint (optional, LocalStack/VPC endpoint override) - credentials.key/secret/session are all optional on the destination itself, not hard-required, so a future credential-less publishing mode (the kind some AWS-partnered SaaS platforms use) can be added later without a breaking config change. Static credentials are still always passed to the AWS SDK explicitly, even when empty, rather than omitted -- an empty NewStaticCredentialsProvider fails loudly with an auth error instead of the SDK silently falling back to its default credential chain (env vars, shared config, EC2/ECS/EKS instance role) and authenticating as whatever role the outpost process happens to be running under. - Source is a fixed, app-level setting (DESTINATIONS_EVENTBRIDGE_SOURCE server config, defaulting to "outpost"), not a per-destination field, matching how EventBridge rules commonly key off Source to identify the emitting application. - DetailType is the event's topic; Detail carries metadata+data in the same envelope shape as aws_kinesis's metadata-in-payload mode, since EventBridge has no side channel for metadata the way SQS message attributes do. PutEvents is a batch API even for a single entry, and reports per-entry success/failure in the response body rather than solely via the returned Go error -- a call can return err == nil with FailedEntryCount == 1 if that one entry was rejected. Publish() checks both the top-level error and the entry's own ErrorCode before calling a publish successful, rather than trusting a nil top-level error alone. Error responses (both the top-level and per-entry paths) are sanitized through a shared classifyErrorCode: AWS's own ErrorCode enum values are safe to pass through as-is, but the human-readable message is always authored here, never AWS's own ErrorMessage text, which can embed account IDs and ARNs in permission-denied style errors. Tests: unit coverage for Format() (envelope shape, Source/DetailType/ EventBusName wiring) and the error-classification functions (verifying no AWS-authored message text, including ARNs/account IDs, ever leaks through). No LocalStack-based Publish() integration test is included -- this environment has no Docker available to write and verify one against, and submitting untested integration test code seemed worse than being explicit about the gap. Every other AWS/queue destination's Publish() correctness is likewise only covered by its LocalStack suite, not unit tests, so this matches existing project convention for the parts that are covered. Docs: instructions.md + metadata.json for the new provider, a destinations/aws-eventbridge.mdoc page mirroring aws-kinesis.mdoc, nav.json/ overview.mdoc/concepts.mdoc listing entries, and the DESTINATIONS_EVENTBRIDGE_SOURCE entry in docs/apis/openapi.yaml's managed config schema (hand-maintained alongside config.go, per PR hookdeck#992's precedent). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SNTzCmsH3jiGqgPqi4QMfj
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.
Closes #201.
Adds
aws_eventbridgeas a new destination type, following the existingaws_kinesis/aws_sqsprovider pattern. Implements the shape discussed on #201 with @alexbouchardd:config.event_bus_name(optional, name or ARN — empty uses the account's default bus) +config.region(required) +config.endpoint(optional, LocalStack/VPC endpoint override)credentials.key/secret/sessionare all optional on the destination itself (not hard-required), so a future credential-less publishing mode can be added later without a breaking config change. Static credentials are still always passed to the AWS SDK explicitly, even when empty, rather than omitted — an emptyNewStaticCredentialsProviderfails loudly with an auth error instead of the SDK silently falling back to its default credential chain (env vars, shared config, EC2/ECS/EKS instance role) and authenticating as whatever role the outpost process happens to be running under.Sourceis a fixed, app-level setting (DESTINATIONS_EVENTBRIDGE_SOURCEserver config, defaulting tooutpost), not a per-destination field, matching how EventBridge rules commonly key offSourceto identify the emitting application.DetailTypeis the event's topic;Detailcarriesmetadata+datain the same envelope shape asaws_kinesis's metadata-in-payload mode, since EventBridge has no side channel for metadata the way SQS message attributes do.Batch/error handling
PutEventsis a batch API even for a single entry, and reports per-entry success/failure in the response body rather than solely via the returned Go error — a call can returnerr == nilwithFailedEntryCount == 1if that one entry was rejected.Publish()checks both the top-level error and the entry's ownErrorCodebefore calling a publish successful, rather than trusting a nil top-level error alone.Error responses (both paths) are sanitized through a shared
classifyErrorCode: AWS's ownErrorCodeenum values are safe to pass through as-is, but the human-readable message is always authored here, never AWS's ownErrorMessagetext, which can embed account IDs and ARNs in permission-denied style errors.Tests
Unit coverage for
Format()(envelope shape, Source/DetailType/EventBusName wiring) and the error-classification functions (including a test that explicitly asserts no AWS-authored message text, ARNs, or account IDs ever leak through) — all passing.No LocalStack-based
Publish()integration test is included. My local environment has no Docker available, so I couldn't write and verify one the wayaws_sqs/aws_kinesisdo — I'd rather flag that gap explicitly than submit integration test code I can't confirm actually passes. Every other AWS/queue destination'sPublish()correctness is likewise only covered by its LocalStack suite rather than unit tests, so this matches existing project convention for the parts that are covered; happy to add the integration test in a follow-up once I can verify it, or if a maintainer would rather add it directly.Docs
instructions.md+metadata.jsonfor the new provider, adestinations/aws-eventbridge.mdocpage mirroringaws-kinesis.mdoc,nav.json/overview.mdoc/concepts.mdoclisting entries, and theDESTINATIONS_EVENTBRIDGE_SOURCEentry indocs/apis/openapi.yaml's managed config schema (hand-maintained alongsideconfig.go, per #992's precedent).🤖 Generated with Claude Code
https://claude.ai/code/session_01SNTzCmsH3jiGqgPqi4QMfj