Commit 07c026a
authored
fix(ashby): repair broken idempotency dedup and clarify duplicate-webhook errors (#5518)
* fix(ashby): repair broken idempotency dedup and clarify duplicate-webhook errors
extractIdempotencyId looked for a webhookActionId field that does not
exist anywhere in Ashby's webhook payload schema (confirmed against the
live OpenAPI spec), so every delivery — including Ashby's own retries —
got a fresh random dedup key and could re-execute workflows. Derive the
key from the affected resource's id plus its updatedAt/decidedAt instead.
Also surface a clear, actionable message when Ashby's webhook.create
rejects a request as a duplicate (seen repeatedly in production logs,
where the outbox retried the same failing subscription for ~23 minutes
before dead-lettering) instead of the generic API error passthrough.
Also add the interview stage `type` field to trigger outputs (present
in Ashby's schema, useful for a stage-change trigger) and fix the
employmentType description to match Ashby's actual enum values.
* fix(ashby): correct offer status enum values in trigger output descriptions
acceptanceStatus listed a non-existent "WaitingOnResponse" value and
offerStatus was missing "WaitingOnApprovalDefinition" — both caught on
a second pass re-checking every enum against Ashby's live OpenAPI spec.
* fix(ashby): harden idempotency key against Greptile-flagged collision risks
- Return null (skip dedup) when application.updatedAt is absent instead
of collapsing to an empty string, which could collide two distinct
events sharing an application id onto the same key.
- Drop decidedAt from the offerCreate key. It's populated only after
the fact, so including it gave a retry of the same delivery a
different key than the original attempt once the candidate
responded, defeating dedup. offer.id alone is already stable and
unique per created offer.
* fix(ashby): fall back to a content fingerprint instead of skipping dedup
Returning null when application.updatedAt was missing avoided false
collisions between distinct events, but also disabled retry dedup
entirely for that payload shape — an Ashby retry would get a random
key from the idempotency service's own fallback and re-run the
workflow.
Extract the fallback-fingerprint helper (sha256 of a stably-serialized
payload) out of salesforce.ts into the shared providers/utils.ts, and
use it in ashby.ts: identical retried bytes hash identically (dedup
still works), while two genuinely different events hash differently
(no false collision).
* chore(ashby): remove inline comments, let names carry the intent
* fix(ashby): fingerprint the full data payload, not just application
Hashing only data.application missed other fields (e.g. offer on
candidateHire) when updatedAt is absent, so two deliveries sharing an
application snapshot but differing elsewhere in data could collide
onto the same idempotency key.
* fix(ashby): rename output field 'type' to 'stageType' to fix build
TriggerOutput reserves the 'type' key for the output's own JSON type
(e.g. 'string'), so a nested field literally named 'type' inside
currentInterviewStage collided with that meta-field and broke the
Record<string, TriggerOutput> cast — passing local type-check (which
turbo was silently serving a stale cached pass for) but failing
Next.js's build-time type check in CI. Renamed to stageType, matching
the existing eventType-style convention used elsewhere for API fields
literally called 'type'.
* fix(ashby): rename currentInterviewStage.type to stageType in delivered data too
Renaming the field in the output schema alone (to fix the TriggerOutput
build collision) left a mismatch: Ashby's real payload still has
currentInterviewStage.type, so a picker/expression using the schema's
declared stageType would resolve to undefined at runtime. formatInput
now renames the field in the actual delivered payload so it matches
what the schema declares.
* fix(ashby): fold offer id into the idempotency key when present
When application.updatedAt is present, the key ignored sibling data
fields — a candidateHire delivery carries both application and offer,
so two deliveries sharing an application snapshot could collide even
though they concern different offers. Append offer.id to the
discriminator when present; it's the only sibling object Ashby's
schema ever pairs with application.1 parent 1236474 commit 07c026a
5 files changed
Lines changed: 322 additions & 29 deletions
File tree
- apps/sim
- lib/webhooks/providers
- triggers/ashby
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| 18 | + | |
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
| |||
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
40 | | - | |
41 | | - | |
42 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
43 | 64 | | |
44 | 65 | | |
45 | 66 | | |
46 | 67 | | |
47 | 68 | | |
48 | 69 | | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
49 | 76 | | |
50 | 77 | | |
51 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
52 | 90 | | |
53 | 91 | | |
54 | 92 | | |
| |||
185 | 223 | | |
186 | 224 | | |
187 | 225 | | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
188 | 229 | | |
189 | 230 | | |
190 | 231 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
3 | 2 | | |
4 | 3 | | |
5 | 4 | | |
| |||
8 | 7 | | |
9 | 8 | | |
10 | 9 | | |
11 | | - | |
| 10 | + | |
12 | 11 | | |
13 | 12 | | |
14 | 13 | | |
| |||
98 | 97 | | |
99 | 98 | | |
100 | 99 | | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | 100 | | |
121 | 101 | | |
122 | 102 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
9 | 39 | | |
10 | 40 | | |
11 | 41 | | |
| |||
0 commit comments