You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 82f8450
Browse filesBrowse the repository at this point in the historyBrowse files
fix(delivery): stable provider idempotency tokens, and correctness fixes around them
Six independent fixes found while investigating a Slack transport failure. None
of them are that failure; all of them are live.
**Money writes could be delivered twice.** Square (8 tools), Brex (5) and Outlook
Calendar minted their provider idempotency token with `generateId()` at
request-build time. That is stable inside the transport retry loop —
`prepareToolRequest` runs once above it — but a BLOCK-level retry re-enters the
handler and mints a fresh one, defeating the provider's dedupe. A builder ticking
"retry" on a Square block turned a committed write into a second card charge, and
a Brex one into a second money transfer. Tokens now come from
`deriveDeliveryKey`, a pure function of execution + block + tool + invocation, so
every retry layer derives the same value. Stripe joins them: all ~50 tools
previously sent no `Idempotency-Key` at all.
The comment on `brex/create_transfer.ts` claimed a fresh key per transfer
*prevents* duplicate money movement. That is inverted — fresh per *attempt* is
what permits it — and is corrected here.
**`invocationId` is required, not optional.** Deriving from `executionId` alone
would be worse than the bug: five loop iterations paying five invoices would
share one token, the provider would honour the first and silently drop four real
payments, and it would look like five successes.
Also:
- `INTERNAL_API_BASE_URL` is now ignored on Trigger.dev workers. It names a route
that resolves only inside the app container, and several modules run in both
runtimes — `guardrails/mask-client.ts` says so in its own TSDoc — so setting it
produced `PII redaction failed: Unable to connect` on every worker-side
redaction. Mirrored into `packages/testing`'s urls mock, which reimplements the
function and would otherwise have diverged.
- `engines.bun` raised to >=1.3.14. Measured on 1.2.15, which the old floor
permitted: a fully-delivered POST is silently replayed and the caller sees 200.
- CloudWatch `put-metric-data` pinned to `maxAttempts: 1`. The AWS SDK default of
3 already replayed it, and `PutMetricData` aggregates rather than overwrites, so
a duplicate silently corrupts the customer's metric series and alarm thresholds.
- `webhookIdempotency` given a bounded in-progress lease. An untimed run held a
SEVEN DAY lease while concurrent duplicates polled it once a second.
Verified: `tsc --noEmit` clean, 30,100 tests pass.
0 commit comments