Feature/secure webhook secrets and signatures - #842
Open
sideeqa wants to merge 2 commits into
Open
Conversation
Contributor
|
Fix the failed check |
Contributor
|
@sideeqa fix the failing check. |
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.
closes #797
Description
This PR introduces two related improvements to the backend webhook service and establishes a formal CI quality-gate pipeline for the backend.
Webhook secret encryption: Webhook secrets were previously stored in plaintext in the database. This adds AES-256-GCM encryption/decryption for webhook secrets at rest, using a configurable
WEBHOOK_ENCRYPTION_KEYenvironment variable. The implementation is backward-compatible — unencrypted (legacy) secrets are passed through transparently on read, so no immediate data migration is required.Signature header rename: The outbound HMAC signature header has been renamed from
X-Webhook-SignaturetoX-Bridge-Watch-Signatureto avoid collisions with generic webhook frameworks and to clearly identify the source.Backend CI pipeline: A new GitHub Actions workflow (
backend-ci.yml) adds a full quality-gate pipeline for the backend: dependency install, Prettier format check, ESLint (zero warnings), TypeScript type check, database migrations against a live TimescaleDB + Redis test environment, test coverage enforcement, and a production build. Coverage results are uploaded to Codecov and artefacts are retained for 7 days.Prettier configuration: Prettier is added as a dev dependency with a
.prettierrc.jsonconfig and.prettierignore, andformat/format:check/typechecknpm scripts are added tobackend/package.json.Type of Change
Related Issue
Closes #
Changes Made
backend-ci.yml: New GitHub Actions workflow with a singlebackend-quality-gatesjob; spins up TimescaleDB (pg15) and Redis service containers, then runs install → format check → lint → type check → migrations → tests/coverage → build in order. Uploads coverage to Codecov and preserves artefacts for 7 days. Includes a step summary table.continue-on-error: trueis set on the format and type-check steps temporarily while pre-existing issues in the base branch are resolved.webhook.service.ts: AddedencryptSecret()anddecryptSecret()private methods using AES-256-GCM with a random 12-byte IV and authentication tag. Encryption key is derived via SHA-256 fromWEBHOOK_ENCRYPTION_KEYconfig. Secrets are now encrypted oncreateEndpointandrotateSecret, and decrypted inmapRowToEndpoint.webhook.service.ts: Renamed the outbound HMAC header fromX-Webhook-SignaturetoX-Bridge-Watch-Signature.config/index.ts: AddedWEBHOOK_ENCRYPTION_KEY(optional, minimum 32 characters) to the environment schema.backend/package.json: Addedtypecheck,format, andformat:checknpm scripts; addedprettier ^3.9.6as a dev dependency..prettierrc.json/.prettierignore: Added Prettier configuration (double quotes, semicolons,es5trailing commas, 100-char print width) and an ignore file excludingdist/,coverage/,node_modules/, JSON, and Markdown.webhook.service.test.ts: Updated the signature header assertion toX-Bridge-Watch-Signature; added aWEBHOOK_ENCRYPTION_KEYvalue to the config mock; added a new"WebhookService — secret encryption"describe block with two tests (round-trip encrypt/decrypt, and legacy plaintext passthrough).Testing
npm run test:unit)npm run test:integration)New test coverage:
encryptSecret+decryptSecretround-trip test confirms AES-256-GCM encryption is reversible with the configured key.generateSignatureHeaderstest asserts the renamedX-Bridge-Watch-Signatureheader is present.Migration Changes
Documentation
README.mdupdated (new commands, endpoints, or setup steps)docs/file updated.env.exampleupdated (new environment variables) —WEBHOOK_ENCRYPTION_KEYshould be addedbackend/docs/API.mdupdated (new or changed endpoints) — outbound signature header name change must be reflected for webhook consumersChecklist
maintype(scope): summary)npm run lint,cargo clippy)npm run build,cargo build --release)console.log/println!left in production code.envfiles committedCI Status
Breaking Changes
X-Webhook-Signature→X-Bridge-Watch-SignatureAny external consumer that verifies the HMAC signature header on incoming webhook deliveries must update their header name from
X-Webhook-SignaturetoX-Bridge-Watch-Signature. Deliveries made after this change is deployed will no longer include the old header name.Migration path: Update your webhook receiver to read
X-Bridge-Watch-Signatureinstead ofX-Webhook-Signaturebefore deploying this change to production. If you control both sides, deploy the receiver update first.Additional Notes
continue-on-error: trueflags on the format check and type check CI steps are intentional and temporary. Several pre-existing type errors (bridgeMonitor.worker,healthCheck.worker,reportScheduling.service,priceAggregator.worker) and unformatted source files exist in the base branch. These flags must be removed once dedicated follow-up PRs address those issues."default-webhook-encryption-key-change-me") is present solely to prevent a hard crash whenWEBHOOK_ENCRYPTION_KEYis not set. It must not be used in production. SettingWEBHOOK_ENCRYPTION_KEYin all environments should be treated as a required operational step alongside this deployment.job.statusfor every gate row, which means all rows reflect the final job outcome rather than per-step outcomes. This is a known limitation of the summary templating and can be improved in a follow-up with per-step outcome tracking.