[TW-4803] feat(webhook): add Pub/Sub channels, secret rotation, and signature verification#46
Merged
qasim-nylas merged 2 commits intomainfrom Apr 8, 2026
Conversation
…ignature verification Add Notifications 2.0 support under the existing webhook command group: - Pub/Sub notification channel CRUD (list/show/create/update/delete) - Webhook secret rotation with confirmation guard - Local webhook signature verification using shared HMAC-SHA256 logic extracted from the webhook server into webhookserver/signature.go
rotate_secret.go was excluded by the *secret* gitignore pattern. Add an exception for the legitimate source file so CI can find the newRotateSecretCmd definition.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Notifications 2.0 support to the Nylas CLI under the existing
nylas webhookcommand group — Pub/Sub notification channel management, webhook secret rotation, and local signature verification, all backed by the Nylas v3 API.JIRA: TW-4803 · Epic: TW-4638 (Nylas CLI)
New CLI Commands
Pub/Sub Notification Channels
nylas webhook pubsub listnylas webhook pubsub show <id>nylas webhook pubsub create --topic <topic> --triggers <types>nylas webhook pubsub update <id> [flags]nylas webhook pubsub delete <id> --yesWebhook Secret Rotation
nylas webhook rotate-secret <id> --yesLocal Signature Verification
nylas webhook verify --secret <s> --signature <sig> --payload <body>nylas webhook verify --secret <s> --signature <sig> --payload-file <path>What changed
1. Pub/Sub Notification Channels (
nylas webhook pubsub)projects/<id>/topics/<id>formatdomain.AllTriggerTypes()with validation--topicand--triggersmarked as required on create--yesconfirmation--output json/yaml/quietvia shared output flags2. Webhook Secret Rotation (
nylas webhook rotate-secret)--yesflag to prevent accidental rotation3. Local Signature Verification (
nylas webhook verify)--payloador--payload-file(mutually exclusive)webhookserver/signature.go4. Shared Signature Module
ComputeSignature,VerifySignature,NormalizeSignatureintointernal/adapters/webhookserver/signature.goArchitecture
Follows the existing hexagonal pattern across all layers:
domain/pubsub.goRotateWebhookSecretResponseindomain/webhook.goports/pubsub.go(PubSubClientinterface)RotateWebhookSecretonWebhookClientadapters/nylas/pubsub.gowebhooks.go(rotate),webhookserver/signature.go(verify)cli/webhook/pubsub*.go(4 files)verify.go, rotate-secret in existing commandsmock_pubsub.go,demo_pubsub.gomock_webhooks.go,demo_webhooks.goupdatedSecurity
hmac.Equalfor constant-time comparisonVerifySignaturerejects empty secrets defensivelyurl.PathEscaped in API URLsTesting
webhooks_test.go(516 lines) +webhooks_notifications_test.go(94 lines) to stay under file size limitsmake ci-fullpasses end-to-endTest plan
go test ./internal/adapters/webhookserver -run 'TestVerifySignature|TestNormalizeSignature' -count=1go test ./internal/adapters/nylas -run 'TestHTTPClient_.*PubSub|TestDemoClient_GetPubSubChannel_NotFound|TestHTTPClient_RotateWebhookSecret' -count=1go test ./internal/cli/webhook -run 'TestPubSub|TestRotateSecretCommand|TestVerifyCommand' -count=1go test ./internal/cli/integration -tags=integration -run 'TestCLI_Webhook(Help|CreateHelp|RotateSecretHelp|VerifyHelp|VerifyLocal|PubSubHelp|TestHelp|TestPayload)' -count=1make ci-full