Thank you for your interest in contributing! This package helps developers debug webhook signatures across multiple platforms, and we welcome contributions of all kinds.
- Add new platform verifiers (e.g., Clerk, Resend, Discord, Twilio)
- Improve existing verifiers (better error messages, edge cases)
- Fix bugs and improve performance
- Improve documentation (README, examples, JSDoc comments)
- Add tests (we need comprehensive test coverage!)
- Report issues (bugs, feature requests, documentation gaps)
# Fork the repo on GitHub, then:
git clone https://github.com/HookInbox/hookinbox-verify.git
cd hookinbox-verify
npm install# Create a new branch
git checkout -b feature/add-discord-verifier
# Make your changes in src/
# Build to check for errors
npm run build# Link the package locally
npm link
# In another project, test it
cd /path/to/test-project
npm link @hookinbox/verify
# Import and test your changes
import { verifyDiscord } from '@hookinbox/verify';git add .
git commit -m "feat: add Discord webhook verifier"
git push origin feature/add-discord-verifierThen open a pull request on GitHub!
We use Jest for testing. All contributions should include tests.
npm testnpm run test:watchnpm run test:coverageCoverage requirements:
- Branches: 80%
- Functions: 80%
- Lines: 80%
- Statements: 80%
All verifier functions should have comprehensive tests covering:
-
Valid signatures
- Correct signature with string body
- Correct signature with Buffer body
- Edge cases (empty body, special characters)
-
Invalid signatures
- Wrong secret
- Modified body
- Invalid format
- Missing required fields
-
Platform-specific rules
- Timestamp tolerance (Stripe)
- Algorithm detection (GitHub)
- Base64 encoding (Shopify)
Example test structure:
import { verifyPlatform } from '../src/platform';
describe('verifyPlatform', () => {
const secret = 'test_secret';
const body = '{"test":"data"}';
describe('valid signatures', () => {
it('should verify a valid signature', () => {
// Test implementation
});
});
describe('invalid signatures', () => {
it('should reject signature with wrong secret', () => {
// Test implementation
});
});
describe('edge cases', () => {
it('should handle empty body', () => {
// Test implementation
});
});
});tests/
├── timing-safe.test.ts
├── stripe.test.ts
├── github.test.ts
├── shopify.test.ts
└── your-platform.test.ts ← Add your tests here
1. Create the verifier file:
File: src/discord.ts
import { createHmac } from 'crypto';
import { timingSafeEqual } from './timing-safe';
export interface DiscordVerifyOptions {
body: string | Buffer;
signature: string;
timestamp: string;
publicKey: string;
}
export interface DiscordVerifyResult {
valid: boolean;
error?: string;
details?: {
expectedSignature?: string;
receivedSignature?: string;
};
}
export function verifyDiscord(options: DiscordVerifyOptions): DiscordVerifyResult {
const { body, signature, timestamp, publicKey } = options;
try {
// Discord uses Ed25519 signature verification
// Implementation here...
return {
valid: true,
};
} catch (err) {
return {
valid: false,
error: err instanceof Error ? err.message : 'Unknown error',
};
}
}2. Export it in src/index.ts:
export { verifyDiscord } from './discord';
export type { DiscordVerifyOptions, DiscordVerifyResult } from './discord';3. Document it in README.md:
### Discord
\`\`\`typescript
import { verifyDiscord } from '@hookinbox/verify';
const result = verifyDiscord({
body: rawBody,
signature: req.headers['x-signature-ed25519'],
timestamp: req.headers['x-signature-timestamp'],
publicKey: 'your-public-key',
});
\`\`\`4. Add your name to contributors:
We'll add you to the README and package.json contributors list!
- Use TypeScript for all new code
- Export clear interfaces for options and results
- Use meaningful variable names
- Add JSDoc comments for public APIs
// 1. Imports
import { createHmac } from 'crypto';
import { timingSafeEqual } from './timing-safe';
// 2. Types/Interfaces
export interface PlatformVerifyOptions {
// ...
}
export interface PlatformVerifyResult {
valid: boolean;
error?: string;
details?: Record<string, any>;
}
// 3. Main function
export function verifyPlatform(options: PlatformVerifyOptions): PlatformVerifyResult {
try {
// Implementation
} catch (err) {
return {
valid: false,
error: err instanceof Error ? err.message : 'Unknown error',
};
}
}Always return descriptive errors:
// ❌ Bad
return { valid: false, error: 'Invalid signature' };
// ✅ Good
return {
valid: false,
error: 'Signature mismatch: expected sha256 but received sha1',
details: {
expectedAlgorithm: 'sha256',
receivedAlgorithm: 'sha1',
},
};Always use timingSafeEqual() for signature comparisons:
// ❌ Bad - vulnerable to timing attacks
if (expected === received) { ... }
// ✅ Good - constant-time comparison
if (timingSafeEqual(expected, received)) { ... }We're setting up Jest for testing. In the meantime:
- Manual testing: Test with real webhook payloads
- Edge cases: Test invalid signatures, malformed headers, wrong algorithms
- Documentation: Document your test cases in the PR description
Before submitting your PR, make sure:
- Code builds without errors (
npm run build) - TypeScript types are correct
- README.md is updated with usage example
-
src/index.tsexports your new verifier - You've tested it with real webhook payloads
- Error messages are clear and helpful
- You used
timingSafeEqual()for signature comparisons - Commit messages follow Conventional Commits
feat:for new featuresfix:for bug fixesdocs:for documentationchore:for maintenance
We'd love help adding verifiers for these platforms:
- Lemon Squeezy - Payment platform
- Paddle - Subscription billing
- Chargebee - Subscription management
- Twilio - SMS/Voice webhooks
- SendGrid - Email webhooks
- Resend - Email API
- Postmark - Transactional email
- Discord - Bot webhooks
- Clerk - Authentication platform
- Auth0 - Identity platform
- WorkOS - Enterprise SSO
- Vercel - Deployment webhooks
- Railway - Deployment webhooks
- Linear - Project management
- Sentry - Error tracking
- WooCommerce - WordPress ecommerce
- BigCommerce - Ecommerce platform
- Printful - Print-on-demand
- Calendly - Scheduling webhooks
- Typeform - Form webhooks
- Airtable - Database webhooks
- Notion - Workspace webhooks
Pick one and submit a PR! 🚀
- GitHub Issues: https://github.com/hookinbox/verify/issues
- Twitter: @hookinbox
- Email: leonardo@hookinbox.dev
By contributing, you agree that your contributions will be licensed under the MIT License.
Every contribution helps developers debug webhooks faster. Thank you for making this tool better!
Built with ❤️ by the HookInbox community