Skip to content

Commit 9ce3391

Browse files
authored
[Alex] ARC-542: Add egress-webhook-service openapi yaml and render it (#27)
<!-- CURSOR_SUMMARY --> > [!NOTE] > Adds `services/egress-webhook-service/openapi.yaml`, surfaces it under a new "Webhook Events" tab, moves webhook security docs to `webhooks.mdx`, and removes webhook event schemas from the Customer API spec. > > - **Docs/navigation**: > - Update `docs.json` to: > - Replace `API Reference` with an **Overview** tab (adds `Webhooks` page). > - Add `Customer API` (OpenAPI `services/external-actor-gateway-service/openapi.yaml`). > - Add `Webhook Events` (OpenAPI `services/egress-webhook-service/openapi.yaml`). > - **API specs**: > - Add `services/egress-webhook-service/openapi.yaml` defining webhook events: `page.version.created|processed|published`, `form.submitted|enriched|enrichment_failed`. > - Remove embedded `webhooks` definitions from `services/external-actor-gateway-service/openapi.yaml`. > - **Content**: > - Move webhook signature verification from `index.mdx` to new `webhooks.mdx`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0d13654. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
2 parents 9db2aa6 + 0d13654 commit 9ce3391

File tree

5 files changed

+438
-380
lines changed

5 files changed

+438
-380
lines changed

docs.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,29 @@
1515
"navigation": {
1616
"tabs": [
1717
{
18-
"tab": "API Reference",
19-
"openapi": "services/external-actor-gateway-service/openapi.yaml",
18+
"tab": "Overview",
2019
"groups": [
2120
{
2221
"group": "Overview",
2322
"pages": [
2423
"index"
2524
]
25+
},
26+
{
27+
"group": "Webhooks",
28+
"pages": [
29+
"webhooks"
30+
]
2631
}
2732
]
33+
},
34+
{
35+
"tab": "Customer API",
36+
"openapi": "services/external-actor-gateway-service/openapi.yaml"
37+
},
38+
{
39+
"tab": "Webhook Events",
40+
"openapi": "services/egress-webhook-service/openapi.yaml"
2841
}
2942
]
3043
},

index.mdx

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -69,89 +69,6 @@ The API uses standard HTTP status codes and returns detailed error responses:
6969
```
7070

7171

72-
## Webhook Signature Verification
73-
74-
Webhook requests include an HMAC-SHA256 signature in the `X-Webhook-Signature-256` header that you should verify to ensure authenticity and prevent tampering.
75-
76-
### Verification Process
77-
78-
1. Extract the signature from the `X-Webhook-Signature-256` header (format: `sha256=<hex-signature>`)
79-
2. Get the raw request body before parsing
80-
3. Calculate the expected signature using your webhook signing secret
81-
4. Compare signatures using a timing-safe comparison function
82-
5. Process the webhook only if signatures match
83-
84-
<Warning>
85-
Always use the raw request body for verification, not the parsed JSON. Use timing-safe comparison functions to prevent timing attacks.
86-
</Warning>
87-
88-
### Implementation Example
89-
90-
```typescript
91-
import crypto from 'node:crypto';
92-
import express from 'express';
93-
94-
function verifyWebhookSignature(
95-
signingSecret: string,
96-
payload: string,
97-
signature: string
98-
): boolean {
99-
if (!signingSecret || !payload || !signature?.startsWith('sha256=')) {
100-
return false;
101-
}
102-
103-
try {
104-
const receivedSignature = signature.substring(7);
105-
const expectedSignature = crypto
106-
.createHmac('sha256', signingSecret)
107-
.update(payload, 'utf8')
108-
.digest('hex');
109-
110-
return crypto.timingSafeEqual(
111-
Buffer.from(expectedSignature, 'hex'),
112-
Buffer.from(receivedSignature, 'hex')
113-
);
114-
} catch (error) {
115-
console.error('Signature verification failed:', error);
116-
return false;
117-
}
118-
}
119-
```
120-
121-
### Security Best Practices
122-
123-
- Store signing secrets in environment variables, never hardcode them
124-
- Always verify signatures before processing webhook data
125-
- Use timing-safe comparison functions (`crypto.timingSafeEqual()` in Node.js, `hmac.compare_digest()` in Python)
126-
- Only accept webhooks over HTTPS
127-
- Log verification failures for security monitoring
128-
- Implement rate limiting on webhook endpoints
129-
130-
### Troubleshooting
131-
132-
<AccordionGroup>
133-
<Accordion title="Signature verification always fails">
134-
**Cause**: Using parsed JSON instead of raw request body
135-
136-
**Solution**: Use the raw request body string before any parsing:
137-
- Express: `express.raw({ type: 'application/json' })` and `req.body.toString()`
138-
- Flask: `request.get_data(as_text=True)`
139-
- FastAPI: `await request.body()` then `.decode('utf-8')`
140-
</Accordion>
141-
142-
<Accordion title="Invalid signature format error">
143-
**Cause**: Missing header or incorrect format
144-
145-
**Solution**: Verify the `X-Webhook-Signature-256` header is present and starts with `sha256=`. Check for header case sensitivity in your framework.
146-
</Accordion>
147-
148-
<Accordion title="Character encoding issues">
149-
**Cause**: Inconsistent encoding when converting body to string
150-
151-
**Solution**: Ensure consistent UTF-8 encoding throughout your verification process.
152-
</Accordion>
153-
</AccordionGroup>
154-
15572
## Support
15673

15774
For API support or questions:

0 commit comments

Comments
 (0)