feat(webhooks)!: Add webhook endpoint CRUD#1592
Conversation
The Webhooks client previously only handled signature verification. Add list/create/update/delete operations for webhook endpoints, generated via oagen against the WorkOS API spec. The constructor now takes the WorkOS client instead of a CryptoProvider so generated methods can issue HTTP calls; the SignatureProvider is lazily constructed from workos.getCryptoProvider() to preserve existing verifyHeader/constructEvent behavior. BREAKING CHANGE: Webhooks constructor now takes a WorkOS instance instead of a CryptoProvider. Callers using workos.webhooks or workos.createWebhookClient() are unaffected; only code that instantiated `new Webhooks(...)` directly needs updating.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
Disabled knowledge base sources:
📝 WalkthroughWalkthroughRefactors Webhooks to accept a WorkOS instance, adds generated webhook endpoint interfaces, serializers, fixtures, and tests, and updates callers and the generation manifest. ChangesWebhooks Constructor Refactoring and Auto-Generated Webhook Interfaces
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/webhooks/fixtures/list-webhook-endpoint.json (1)
7-7: ⚡ Quick winReplace key-shaped fixture secret with a non-secret sentinel string.
Line 7 uses a value that looks like a real webhook secret, which can trigger secret-scanner alerts and leak triage noise. Use an explicit placeholder that cannot be mistaken for credentials (and apply the same change in
src/webhooks/fixtures/webhook-endpoint.json).Suggested change
- "secret": "whsec_0FWAiVGkEfGBqqsJH4aNAGBJ4", + "secret": "whsec_example_not_a_real_secret",
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a2a46dcd-3d53-4c23-8063-b477a9e1d58e
📒 Files selected for processing (22)
.oagen-manifest.jsonsrc/index.tssrc/index.worker.tssrc/webhooks/fixtures/create-webhook-endpoint.jsonsrc/webhooks/fixtures/list-webhook-endpoint.jsonsrc/webhooks/fixtures/update-webhook-endpoint.jsonsrc/webhooks/fixtures/webhook-endpoint.jsonsrc/webhooks/interfaces/create-webhook-endpoint-events.interface.tssrc/webhooks/interfaces/create-webhook-endpoint.interface.tssrc/webhooks/interfaces/index.tssrc/webhooks/interfaces/update-webhook-endpoint-events.interface.tssrc/webhooks/interfaces/update-webhook-endpoint-status.interface.tssrc/webhooks/interfaces/update-webhook-endpoint.interface.tssrc/webhooks/interfaces/webhook-endpoint-status.interface.tssrc/webhooks/interfaces/webhook-endpoint.interface.tssrc/webhooks/serializers/create-webhook-endpoint.serializer.tssrc/webhooks/serializers/index.tssrc/webhooks/serializers/update-webhook-endpoint.serializer.tssrc/webhooks/serializers/webhook-endpoint.serializer.tssrc/webhooks/webhooks.spec.tssrc/webhooks/webhooks.tssrc/workos.ts
| const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); | ||
| import { SignatureVerificationException } from '../common/exceptions'; | ||
|
|
||
| const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); |
There was a problem hiding this comment.
Use the standard test placeholder key instead of a secret-like literal.
Please replace the hardcoded key-shaped string with the repository convention ('n') to avoid secret-scanner noise and keep tests consistent.
Suggested fix
-const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
+const workos = new WorkOS('n');Based on learnings, in workos-node SDK TypeScript tests the placeholder API key convention is exactly new WorkOS('n').
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); | |
| const workos = new WorkOS('n'); |
🧰 Tools
🪛 Betterleaks (1.2.0)
[high] 19-19: Found a Stripe Access Token, posing a risk to payment processing services and sensitive financial data.
(stripe-access-token)
There was a problem hiding this comment.
This is a hallucination. Several other specs use sk_test_...: https://github.com/search?q=repo%3Aworkos%2Fworkos-node%20%22sk_test_%22&type=code
This is not a real key.
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n "new WorkOS\(" --type ts -g "*.spec.ts" | head -40
Length of output: 3353
@gjtorikian, you're absolutely right — I apologize for the noise. The codebase search confirms that sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU is the widely established test placeholder across many spec files (src/workos.spec.ts, src/widgets/widgets.spec.ts, src/vault/vault.spec.ts, etc.), and is clearly not a real key. The Betterleaks tool produced a false positive here, and I incorrectly applied a narrow learning from a single file too broadly. I'll update the long-term memory to reflect the actual convention.
✏️ Learnings added
Learnt from: gjtorikian
Repo: workos/workos-node PR: 1592
File: src/webhooks/webhooks.spec.ts:19-19
Timestamp: 2026-05-19T15:25:42.980Z
Learning: In workos-node SDK TypeScript tests, the established test placeholder API key is `'sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'` (e.g., `new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU')`). This is used extensively across spec files including src/workos.spec.ts, src/widgets/widgets.spec.ts, src/vault/vault.spec.ts, and src/webhooks/webhooks.spec.ts. Do not flag this value as a real secret or suggest replacing it. The `'n'` placeholder is used only in specific isolated files (e.g., src/groups/groups.spec.ts) and is not the dominant repository-wide convention.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
⛔ Learnings removed
Learnt from: csrbarber
Repo: workos/workos-node PR: 1564
File: src/groups/groups.spec.ts:14-14
Timestamp: 2026-04-21T13:51:45.149Z
Learning: In workos-node SDK TypeScript tests, follow the established convention when instantiating WorkOS with a placeholder API key: use the single-character string `'n'` (e.g., `new WorkOS('n')`). During code review/static-analysis, do not flag realistic-looking or secret-key patterns in these test files as long as the value matches exactly the `'n'` convention; only raise a warning if the placeholder API key deviates from `'n'`.
🧠 Learnings used
Learnt from: csrbarber
Repo: workos/workos-node PR: 1564
File: src/groups/groups.spec.ts:14-14
Timestamp: 2026-04-21T13:51:45.149Z
Learning: In workos-node SDK TypeScript tests, follow the established convention when instantiating WorkOS with a placeholder API key: use the single-character string `'n'` (e.g., `new WorkOS('n')`). During code review/static-analysis, do not flag realistic-looking or secret-key patterns in these test files as long as the value matches exactly the `'n'` convention; only raise a warning if the placeholder API key deviates from `'n'`.
Greptile SummaryAdds webhook endpoint CRUD operations (
Confidence Score: 4/5Safe to merge once the missing webhooks interface export is added; all four CRUD methods, serializers, and tests are correct. The new webhook endpoint management code is well-structured and follows SDK conventions exactly. The one gap is that src/index.ts does not re-export the new types from ./webhooks/interfaces, so consumers cannot name WebhookEndpoint, CreateWebhookEndpoint, UpdateWebhookEndpoint, or the event enums as explicit TypeScript types when importing from the package. Adding one export line to src/index.ts is the only change needed before shipping. src/index.ts — missing Important Files Changed
|
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| export const CreateWebhookEndpointEvents = { | ||
| AuthenticationEmailVerificationSucceeded: | ||
| 'authentication.email_verification_succeeded', |
There was a problem hiding this comment.
Duplicate events enum across create and update interfaces
CreateWebhookEndpointEvents and UpdateWebhookEndpointEvents are byte-for-byte identical — 74 entries each. If the WorkOS API adds a new subscribable event type in the future, both files must be updated in sync by regenerating. Since this is oagen output that's fine as long as generation is re-run together, but it's worth confirming that the code-gen workflow guarantees both are always regenerated from the same API spec in the same pass.
There was a problem hiding this comment.
it's fine, it's regenerated
The create/update deserialize helpers were unused — only the request serializers and the response deserializer for the endpoint itself are needed. Removing them aligns the surface area with what oagen now emits. The update endpoint test only checked that a body was sent, which would have missed regressions in field casing or payload shape. Asserting the exact request body catches those.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/webhooks/webhooks.spec.ts (1)
63-68: ⚡ Quick winUse exact body assertions for serializer contract tests.
On Line 63 and Line 86,
objectContainingallows extra keys to slip through. Since these tests validate generated request serialization, asserting exact equality gives better regression protection.✅ Suggested tightening
- expect(fetchBody()).toEqual( - expect.objectContaining({ - endpoint_url: 'https://example.com', - events: ['authentication.email_verification_succeeded'], - }), - ); + expect(fetchBody()).toEqual({ + endpoint_url: 'https://example.com', + events: ['authentication.email_verification_succeeded'], + }); ... - expect(fetchBody()).toEqual( - expect.objectContaining({ - endpoint_url: 'https://example.com', - status: 'enabled', - }), - ); + expect(fetchBody()).toEqual({ + endpoint_url: 'https://example.com', + status: 'enabled', + });Also applies to: 86-91
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: dba8aef6-0f5d-4b62-9f82-0aeeb09edd3b
📒 Files selected for processing (6)
.oagen-manifest.jsonsrc/webhooks/serializers.spec.tssrc/webhooks/serializers/create-webhook-endpoint.serializer.tssrc/webhooks/serializers/update-webhook-endpoint.serializer.tssrc/webhooks/webhooks.spec.tssrc/webhooks/webhooks.ts
✅ Files skipped from review due to trivial changes (3)
- .oagen-manifest.json
- src/webhooks/serializers/update-webhook-endpoint.serializer.ts
- src/webhooks/serializers.spec.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/webhooks/serializers/create-webhook-endpoint.serializer.ts
- src/webhooks/webhooks.ts
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 937a9b69-fc29-4a88-b179-a4baf49de8e9
📒 Files selected for processing (3)
src/webhooks/webhooks.spec.tssrc/webhooks/webhooks.tssrc/workos.ts
Summary
workos.webhooksfor managing webhook endpoints, generated via oagen from the WorkOS API spec.src/webhooks/.Webhooksconstructor to take aWorkOSinstance so generated methods can issue HTTP calls;SignatureProvideris now lazily built fromworkos.getCryptoProvider().verifyHeader/constructEventbehavior via@oagen-ignoremarkers so signature verification stays hand-maintained.Breaking change
new Webhooks(cryptoProvider)is no longer valid — the constructor now takes aWorkOSinstance. Callers usingworkos.webhooksorworkos.createWebhookClient()are unaffected.This was done because, previously, this constructor was only used to validate webhook signatures. Now, it issues HTTP calls, like the rest of the SDK.
Summary by CodeRabbit
New Features
Tests
Chores