-
Notifications
You must be signed in to change notification settings - Fork 48
Comparing changes
Open a pull request
base repository: hookdeck/outpost
base: v1.0.2
head repository: hookdeck/outpost
compare: v1.0.3
- 16 commits
- 353 files changed
- 7 contributors
Commits on May 1, 2026
-
ci: Update outpost version in compose.yml to 1.0.2 (#884)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 2d067c3 - Browse repository at this point
Copy the full SHA 2d067c3View commit details -
chore: 🐝 Update SDK - Generate OUTPOST-GO 1.1.0 (#885)
* `Outpost.Destinations.Create()`: * `request.Body.union(kafka)` **Added** * `response.union(kafka)` **Added** (Breaking
⚠️ ) * `Outpost.Destinations.Disable()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Events.List()`: `request.Request` **Changed** (Breaking⚠️ ) * `Outpost.Attempts.List()`: * `request.Request` **Changed** (Breaking⚠️ ) * `response.Models[].Destination.union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Attempts.Get()`: `response.Destination.union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Destinations.List()`: `response.[].union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Metrics.GetAttemptMetrics()`: `request.Request` **Changed** (Breaking⚠️ ) * `Outpost.Destinations.Update()`: * `request.Body.union(DestinationUpdateKafka)` **Added** * `response.union(Destination).union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Metrics.GetEventMetrics()`: `request.Request` **Changed** (Breaking⚠️ ) * `Outpost.Destinations.Enable()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Destinations.Get()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Destinations.ListAttempts()`: * `request.Request` **Changed** (Breaking⚠️ ) * `response.Models[].Destination.union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Destinations.GetAttempt()`: `response.Destination.union(kafka)` **Added** (Breaking⚠️ ) * `Outpost.Retry.Retry()`: **Added** * `Outpost.Attempts.Retry()`: **Removed** (Breaking⚠️ ) Co-authored-by: speakeasybot <bot@speakeasyapi.dev>Configuration menu - View commit details
-
Copy full SHA for c665fd3 - Browse repository at this point
Copy the full SHA c665fd3View commit details -
chore(sdk): update outpost-go shields.json to version v1.1.0 (#886)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 9155606 - Browse repository at this point
Copy the full SHA 9155606View commit details -
chore: 🐝 Update SDK - Generate OUTPOST-PYTHON 1.1.0 (#887)
* `outpost.destinations.create()`: * `request.body.union(kafka)` **Added** * `response.union(kafka)` **Added** (Breaking
⚠️ ) * `outpost.destinations.disable()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.events.list()`: `request` **Changed** (Breaking⚠️ ) * `outpost.attempts.list()`: * `request` **Changed** (Breaking⚠️ ) * `response.models[].destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.attempts.get()`: `response.destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.list()`: `response.[].union(kafka)` **Added** (Breaking⚠️ ) * `outpost.metrics.get_attempt_metrics()`: `request` **Changed** (Breaking⚠️ ) * `outpost.destinations.update()`: * `request.body.union(DestinationUpdateKafka)` **Added** * `response.union(Destination).union(kafka)` **Added** (Breaking⚠️ ) * `outpost.metrics.get_event_metrics()`: `request` **Changed** (Breaking⚠️ ) * `outpost.destinations.enable()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.get()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.list_attempts()`: * `request` **Changed** (Breaking⚠️ ) * `response.models[].destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.get_attempt()`: `response.destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.retry.retry()`: **Added** * `outpost.attempts.retry()`: **Removed** (Breaking⚠️ ) Co-authored-by: speakeasybot <bot@speakeasyapi.dev>Configuration menu - View commit details
-
Copy full SHA for 88c2fcc - Browse repository at this point
Copy the full SHA 88c2fccView commit details -
chore: 🐝 Update SDK - Generate OUTPOST-TS 1.1.0 (#888)
* `outpost.destinations.create()`: * `request.body.union(kafka)` **Added** * `response.union(kafka)` **Added** (Breaking
⚠️ ) * `outpost.destinations.disable()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.events.list()`: `request` **Changed** (Breaking⚠️ ) * `outpost.attempts.list()`: * `request` **Changed** (Breaking⚠️ ) * `response.models[].destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.attempts.get()`: `response.destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.list()`: `response.[].union(kafka)` **Added** (Breaking⚠️ ) * `outpost.metrics.getAttemptMetrics()`: `request` **Changed** (Breaking⚠️ ) * `outpost.destinations.update()`: * `request.body.union(DestinationUpdateKafka)` **Added** * `response.union(Destination).union(kafka)` **Added** (Breaking⚠️ ) * `outpost.metrics.getEventMetrics()`: `request` **Changed** (Breaking⚠️ ) * `outpost.destinations.enable()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.get()`: `response.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.listAttempts()`: * `request` **Changed** (Breaking⚠️ ) * `response.models[].destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.destinations.getAttempt()`: `response.destination.union(kafka)` **Added** (Breaking⚠️ ) * `outpost.retry.retry()`: **Added** * `outpost.attempts.retry()`: **Removed** (Breaking⚠️ ) Co-authored-by: speakeasybot <bot@speakeasyapi.dev>Configuration menu - View commit details
-
Copy full SHA for 48fe03c - Browse repository at this point
Copy the full SHA 48fe03cView commit details -
chore(sdk): hoist publish and retry to SDK root (#889)
* chore(sdk): hoist publish and retry to SDK root Use x-speakeasy-group: "" to lift /publish and /retry off their single-operation namespaces, so callers can use sdk.publish() and sdk.retry() directly instead of sdk.Publish.Event() / sdk.Retry.Retry(). Verified locally with speakeasy run -t outpost-go: publish.go and retry.go namespace files are removed and Publish/Retry become methods on the root Outpost client. Spec-only change; SDKs will regenerate on the next 1.2.0 release. * chore(sdk): update examples and docs for hoisted publish() call Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: gofmt --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for fa79e0a - Browse repository at this point
Copy the full SHA fa79e0aView commit details -
chore: 🐝 Update SDK - Generate OUTPOST-GO 1.2.0 (#890)
* `Outpost.Publish()`: **Added** * `Outpost.Retry()`: **Added** * `Outpost.Publish.Event()`: **Removed** (Breaking
⚠️ ) * `Outpost.Retry.Retry()`: **Removed** (Breaking⚠️ ) Co-authored-by: speakeasybot <bot@speakeasyapi.dev>Configuration menu - View commit details
-
Copy full SHA for bc014ba - Browse repository at this point
Copy the full SHA bc014baView commit details -
chore(sdk): update outpost-go shields.json to version v1.2.0 (#891)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for f740dde - Browse repository at this point
Copy the full SHA f740ddeView commit details -
chore: 🐝 Update SDK - Generate OUTPOST-PYTHON 1.2.0 (#892)
* `outpost.publish()`: **Added** * `outpost.retry()`: **Added** * `outpost.publish.event()`: **Removed** (Breaking
⚠️ ) * `outpost.retry.retry()`: **Removed** (Breaking⚠️ ) Co-authored-by: speakeasybot <bot@speakeasyapi.dev>Configuration menu - View commit details
-
Copy full SHA for c8f3f39 - Browse repository at this point
Copy the full SHA c8f3f39View commit details -
chore: 🐝 Update SDK - Generate OUTPOST-TS 1.2.0 (#893)
* `outpost.publish()`: **Added** * `outpost.retry()`: **Added** * `outpost.publish.event()`: **Removed** (Breaking
⚠️ ) * `outpost.retry.retry()`: **Removed** (Breaking⚠️ ) Co-authored-by: speakeasybot <bot@speakeasyapi.dev>Configuration menu - View commit details
-
Copy full SHA for b0e749e - Browse repository at this point
Copy the full SHA b0e749eView commit details
Commits on May 5, 2026
-
feat(logging): add node identifier to log lines (#894)
* feat(logging): add node identifier to log lines Closes #307. Adds an `os.Hostname()`-derived `node` field to every log line so multi-node deployments can be traced from log output alone. Per the issue body, `os.Hostname()` returns sensible identifiers across the relevant deployment targets: - Kubernetes: pod name (e.g. `outpost-api-5bbd447f65-x2444`) - Docker: container ID - ECS: task/container ID - Cloud VMs: instance hostname The hostname is captured once inside `makeLogger` and attached as a default zap field via `zapLogger.With(...)`. Both the main logger and the audit logger pick this up because they share the same construction path. otelzap preserves zap `With` fields, so `Ctx(ctx)` derivations also carry the node identifier. If `os.Hostname()` returns an error, the field falls back to `"unknown"`. This matches the silent-fallback pattern in `internal/redislock/redislock.go` and avoids failing logger construction on observability metadata. * feat(logging): use host.name per OTEL convention Per @alexluong's review: the hostname attribute should follow the OTEL host semantic convention to avoid confusion with k8s node semantics.
Configuration menu - View commit details
-
Copy full SHA for eed63b0 - Browse repository at this point
Copy the full SHA eed63b0View commit details -
feat(api): enable/disable destinations via Create and Update (#895)
* feat(api): accept created_at/updated_at/disabled_at on destination Create; disabled_at on Update Enables importing destinations from another system (e.g. Svix migrations) with their original timestamps preserved. The Update API also accepts disabled_at (omit/null/timestamp) so callers can enable/disable as part of a normal PATCH without a separate /enable or /disable round-trip. Validation: created_at <= updated_at <= now and created_at <= disabled_at <= now. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(api): default created_at to disabled_at when only disabled_at is provided on Create Importers can now send disabled_at alone without also having to send a created_at; the destination's created_at silently mirrors disabled_at in that case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: drop timestamp validation on Create and Update Trust import payloads — accept created_at/updated_at/disabled_at as-is instead of enforcing future and ordering checks. Importers from other systems may carry inconsistent data, and rejecting it would block migrations for no real benefit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(api): reject future disabled_at on Create and Update The only validation worth keeping — a disabled_at in the future would mean "scheduled to disable later," which is not a feature we support. Other timestamp fields stay unvalidated; importers can carry whatever their source system has. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(api): reject future created_at and updated_at on destination Create Mirrors the disabled_at future check. None of these timestamps make sense in the future at create time. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(api): gate created_at/updated_at on Create to admin (API key) auth JWT-authenticated tenants can no longer rewrite their own audit timestamps; sending created_at or updated_at without admin auth returns 403. disabled_at stays accessible to both roles, matching the existing /enable and /disable endpoint semantics. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test: harden 403 coverage for admin-only timestamp fields - Verify destination is not persisted when 403 is returned - Cover both fields together - Regression guard: JWT can still create destinations without these fields Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(api): set status field to 422 in validation error responses ErrorResponse.Parse leaves Code unset when it falls through to the default branch (e.g. plain errors.New from handlers), which caused AbortWithValidationError to emit {"status":0,...} alongside an HTTP 422. Set Code at the call site since AbortWithValidationError is always 422 by definition; Parse stays caller-agnostic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for a1d10cc - Browse repository at this point
Copy the full SHA a1d10ccView commit details
Commits on May 7, 2026
-
fix: correct misleading ID prefix field descriptions (#896)
* fix: correct misleading ID prefix field descriptions The desc tags for AttemptPrefix, DestinationPrefix, and EventPrefix incorrectly stated the prefix is "prepended with underscore". The prefix is actually used as-is (verified by idgen tests). Updated descriptions to clarify this behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: clarify prefix descriptions and use cloud example Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for dbdefaf - Browse repository at this point
Copy the full SHA dbdefafView commit details
Commits on May 11, 2026
-
fix: add automated db migrations to docker-compose using an outpost-m…
…igrate service (#898) * fix: add automated db migrations to docker-compose using an outpost-migrate service * chore:changed the name of migration service from 'outpost-migrate' to 'migrate' and added the service in awssqs compose file. Cleaned up some of the trailing whitespaces as well
Configuration menu - View commit details
-
Copy full SHA for 4b87b8c - Browse repository at this point
Copy the full SHA 4b87b8cView commit details
Commits on May 13, 2026
-
feat(webhook): proxy-aware error handling for forward proxies (#899)
* docs(webhook): document forward proxy feature and Envoy support Adds a Features page covering the existing DESTINATIONS_WEBHOOK_PROXY_URL configuration and introduces DESTINATIONS_WEBHOOK_PROXY_TYPE=envoy as an opt-in for Envoy-aware error handling: infra-error detection via x-envoy-response-flags and the proxyconnect error path, transparent redelivery via nack, and x-envoy-*/server header sanitization. Includes required Envoy configuration, a minimal reference envoy.yaml, and queue retry policy guidance for sufficient redelivery runway during proxy outages. Default behavior for existing users is unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): narrow nack semantics to proxy infra only Adds an explicit error-attribution table. Nack is reserved for cases where the proxy itself is the proximate cause (auth failure, proxy unreachable). Destination failures that Envoy merely reports (upstream DNS / connect / timeout) are recorded as normal failed delivery attempts with destination-attributed codes; the wrapper sanitizes the response data so Envoy is not exposed, but the customer still sees a destination failure. This avoids the infinite-nack failure mode for genuinely broken destinations. Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): clarify dead-letter window phrasing "DLQ runway" replaced with an explicit statement of what the number means: the maximum time a single nacked message is retried before landing in the dead-letter queue. Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): drop PROXY_TYPE knob, auto-detect Envoy signals Removes DESTINATIONS_WEBHOOK_PROXY_TYPE. Envoy-specific signals (x-envoy-response-flags, x-envoy-* / server: envoy headers) are detected automatically from response headers when present; nothing to configure. The proxy-infra nack path (proxyconnect 407, dial to proxy fails) is generic and applies to any forward proxy, since the discriminator is "the proxy is broken or misconfigured," not "the proxy is Envoy." Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): split error table into generic and Envoy-specific Reorganizes the error handling section so generic-proxy behavior and Envoy-specific signals are in separate tables. Adding support for other proxy implementations (Squid, HAProxy, nginx) in the future would extend the Envoy support pattern. Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): clarify sanitization scope and proxy security trade-offs Two clarifications: 1. Response sanitization is best-effort and currently complete only for Envoy. For arbitrary proxies, Outpost can rewrite error messages but cannot reliably strip proxy-identifying content from response bodies or headers. 2. Production proxy auth + TLS recommendation now depends on topology: not required if Outpost and the proxy share a private network; strongly recommended if the proxy is reachable over the internet to prevent open-relay abuse. Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): demote production notes to a short paragraph Trim the production-deployment guidance to a single sentence on the VPC-vs-internet trade-off, instead of a subsection with specific configuration suggestions. Co-Authored-By: Claude <noreply@anthropic.com> * feat(destregistry): add proxy error sentinel types Defines ErrProxyInfra (signals nack-on-infra-error) and ErrProxyDestination (signals record-as-destination-error with mapped code) along with MapEnvoyResponseFlag for translating Envoy response flags into existing destination error codes (connection_refused, timeout, dns_error, network_unreachable). No consumers yet; subsequent commits add the transport wrapper and integration into the webhook delivery path. Co-Authored-By: Claude <noreply@anthropic.com> * feat(destwebhook): nack proxy infra errors, classify destination errors Wraps the proxy transport when a proxy URL is configured. Detects two classes of proxy-originated failures: - Proxy infrastructure (407 / 401 / 403 on CONNECT, dial-to-proxy failure): wrapped as ErrProxyInfra. ExecuteHTTPRequest returns Delivery: nil so the message handler nacks via the existing nil-attempt path (registry.go:179-195), preserving the destination's retry budget across proxy outages. - Destination errors that the proxy reports (5xx on CONNECT, etc.): wrapped as ErrProxyDestination with a classification code mapped from the response. Falls through to the standard failed-attempt path with the explicit code instead of substring-matching the underlying error. CONNECT-time detection uses http.Transport.OnProxyConnectResponse which exposes the full response (status + headers) before Go discards it, sidestepping the fragility of parsing internal error strings. The wrapper still detects dial-to-proxy failures via the "proxyconnect" prefix that Go's net.OpError keeps for that case. Co-Authored-By: Claude <noreply@anthropic.com> * feat(destwebhook): Envoy response-flag detection and header sanitization Extends proxyTransport with Envoy-specific signals layered on top of the generic proxy handling: - Plain-HTTP forwarding path: responses carrying a non-empty/non-"-" x-envoy-response-flags header are treated as Envoy-synthesized failures, converted to ErrProxyDestination with the flag mapped to a destination error code, and their bodies dropped so they don't reach the delivery record. - CONNECT path: onProxyConnectResponse reads the same flag header on non-200 responses to refine the generic "connection_refused" classification (e.g. flag DC -> dns_error, UT -> timeout). - Successful responses are stripped of x-envoy-* headers and a "server: envoy" header before being returned, so the proxy is not fingerprinted in the destination's recorded response. Co-Authored-By: Claude <noreply@anthropic.com> * test(destregistry): pin Go stdlib "proxyconnect" error wording Adds a snapshot test asserting that net/http still emits "proxyconnect" in dial-to-proxy failure errors. The proxyTransport detector relies on this internal stdlib convention; if a Go upgrade changes the wording, this test fails in CI rather than letting the detector silently stop matching and causing proxy outages to be misclassified as destination errors. Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): align tables with implementation Two small adjustments after the code landed: - Drop the implementation-specific "Outpost sees" column from the generic table; describe observed behavior instead. Proxy auth-style failures cover 407, 401, and 403, not just 407. - Frame the Envoy table around the response-flag signal directly, rather than listing every flag-to-code combination (those are documented by the MapEnvoyResponseFlag mapping). Co-Authored-By: Claude <noreply@anthropic.com> * docs(webhook): move response_headers_to_add to RouteConfiguration Envoy rejects response_headers_to_add at the HttpConnectionManager level (confirmed on Envoy 1.31). The field belongs on RouteConfiguration. Updates both the standalone snippet and the reference envoy.yaml. Co-Authored-By: Claude <noreply@anthropic.com> * fix(destwebhook): treat HTTPS responses as byte-transparent Destinations commonly sit behind their own Envoy at the edge, which emits server: envoy and x-envoy-response-flags on the response. For HTTPS destinations, that response travels through an established CONNECT tunnel — the forward proxy is byte-blind to TLS-encrypted bytes and cannot have synthesized or modified anything. Previously the wrapper treated those headers as if our forward proxy had set them, which: - converted a real destination 503 from a downed app into a misleading "connection_refused" with no body - stripped the destination's own envoy observability headers After this change, HTTPS responses (post-successful-CONNECT) are returned unchanged. Proxy-originated HTTPS failures all happen at CONNECT time and remain handled in onProxyConnectResponse. The plain-HTTP forwarding path still applies envoy detection and header stripping because the forward proxy is in the byte path on the return. The residual case where this over-strips — a plain-HTTP destination that is itself behind Envoy — is documented as a limitation; attribution remains correct because x-envoy-response-flags is overwritten by the forward Envoy via OVERWRITE_IF_EXISTS_OR_ADD. Top-of-file doc comment on proxyTransport now describes the two surfaces (CONNECT-time vs plain-HTTP-forwarding) so the dual-path design is discoverable. Co-Authored-By: Claude <noreply@anthropic.com> * chore(destwebhook): apply review nits to proxy transport - httphelper: skip ClassifyNetworkError when ErrProxyDestination sentinel matches - proxytransport: drop strings.ToLower; http.Header keys are canonicalized - proxytransport: drop impossible nil-guard on req/req.URL in RoundTrip - proxytransport: note unhandled Envoy flags fall through to network_error - proxytransport: cross-reference pin test from proxyconnect detector - proxytransport_test: drop unreachable empty-flag row from map test Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(destregistry): extract NewHTTPClient as free function MakeHTTPClient never touched BaseProvider state — it was a free helper pretending to be a method. Move it to httpclient.go and update the three HTTP-based providers (desthookdeck, destwebhook, destwebhookstandard) to call destregistry.NewHTTPClient directly. BaseProvider keeps only the metadata/validation concerns it actually owns. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(destwebhook): scope proxy transport to webhook package Move proxytransport.go, the Envoy flag mapping, and all sentinels (ErrProxyInfra, ErrProxyDestination, IsProxyInfraError) into the destwebhook package — the only place they're actually used. destregistry keeps a generic WrapTransport hook on HTTPClientConfig; destwebhook exports a WrapTransport function and the two webhook providers (destwebhook, destwebhookstandard) plug it in when constructing their HTTP client. destregistry/ no longer has any proxy-specific code. The wrapper, the Envoy flag table, the CONNECT-response callback, and all four test files move with the sentinels. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: gofmt baseprovider Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(webhook-proxy): clarify Pub/Sub redelivery runway with OSS defaults Replace the "set 5s/600s/10 attempts for ~30min runway" recommendation with the actual behavior of the default provisioning in internal/mqinfra/gcppubsub.go (10s/120s/6 attempts ~ 5min) and note that operators expecting longer proxy outages should tune MinRetryBackoff/MaxRetryBackoff/RetryLimit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(destwebhook): map Envoy DF (DNS failure), not DC DC (Downstream Connection Termination) is the wrong flag — it means the client closed the connection, not DNS resolution. The actual flag emitted by Envoy's dynamic_forward_proxy when a host fails to resolve is DF (DNS Failure). Verified against a local Envoy reference proxy (build/dev/envoy/envoy.yaml): nonexistent.invalid → DF → dns_error. Also adds a local-dev Envoy service (build/dev/compose.yml + envoy.yaml) matching the documented config — `%RESPONSE_FLAGS%` on RouteConfiguration with OVERWRITE_IF_EXISTS_OR_ADD — so the QA suite at qa/suites/outpost/ webhook-proxy.md can be run against a real proxy locally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(destwebhook): expand Envoy flag mapping + capture diagnostics Address review feedback that the recorded error code is too coarse and gives operators nothing to diagnose with. Mapping: align with ClassifyNetworkError vocabulary so customers see the same codes whether or not a proxy is in path. - UC, UR, LR → connection_reset (split out of connection_refused) - UPE, DPE → protocol_error (new bucket; previously network_error) - UMSDR → timeout - network_error stays as the catch-all; operator-visible signal that a new flag has shown up and the table should be expanded. Diagnostics: capture raw x-envoy-response-flags and the new x-envoy-response-code-details (stage{reason}) on ErrProxyDestination and attach them to the publish-attempt error payload as proxy_flag / proxy_details. Logged operator-side; never written to the customer- visible attempt response_data — same model EG uses. Ref Envoy config emits both headers with OVERWRITE_IF_EXISTS_OR_ADD so destinations can't spoof them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(destwebhook): generic Diagnostics map on ErrProxyDestination Replace Flag/Details fields with a free-form Diagnostics map[string]string. The previous shape baked Envoy-specific terminology into a struct that classifies errors from any forward proxy — even though only Envoy populates the fields today. Generic map keeps the contract honest: whoever populates a key owns its naming (envoy_flag, envoy_details for Envoy; future Squid/HAProxy paths would add their own). Error() sorts keys for deterministic log output. httphelper splats the map into the publish-attempt Data payload. Behavior unchanged — same log strings, same customer-invisible surface. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for 121bd95 - Browse repository at this point
Copy the full SHA 121bd95View commit details -
fix: increase consumer error tolerance for transient infra outages (#900
) Previously the consumer gave up after 5 consecutive receive errors with a 5s backoff cap (~3s total tolerance), permanently killing the worker with no recovery path. A brief broker hiccup (e.g. GCP OAuth/DNS blip, managed broker restart) was enough to take down logmq/deliverymq workers across deployments until containers were manually restarted. Mirrors the same fix applied to the retrymq scheduler in #881. Increase to 10 errors with 15s backoff cap (~1 min tolerance window). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 2aa4cec - Browse repository at this point
Copy the full SHA 2aa4cecView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v1.0.2...v1.0.3