feat(cost_ingestion): scope settlement webhooks by merchant - #349
Open
AnkitKmrGupta wants to merge 4 commits into
Open
feat(cost_ingestion): scope settlement webhooks by merchant#349AnkitKmrGupta wants to merge 4 commits into
AnkitKmrGupta wants to merge 4 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the cost-ingestion settlement webhook and credential/deduplication model to be merchant-scoped, allowing multiple Decision Engine merchants to ingest independently even when they share the same connector account.
Changes:
- Updated settlement webhook route to include
merchant_id(/webhooks/settlement/:merchant_id/:connector) and plumbedmerchant_idthrough verification and enqueueing. - Updated credential storage and poll-indexing logic to key credentials by
(merchant_id, connector, account)and to passmerchant_idthrough poller/worker flows. - Updated cost-ingestion dedupe constraints (MySQL + Postgres) and documentation to match merchant-scoped idempotency.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/routes/settlement_webhook.rs | Adds merchant_id to the webhook path and scopes credential lookup/signature verification accordingly. |
| src/app.rs | Wires the new webhook route path in the Axum router. |
| src/cost_ingestion/creds.rs | Changes credential keying to (merchant_id, connector, account) and updates poll index to carry merchant identity. |
| src/cost_ingestion/poller.rs | Passes merchant_id through polling so jobs are enqueued per-merchant. |
| src/cost_ingestion/worker.rs | Loads download credentials using (merchant_id, connector, account) for each job. |
| src/cost_ingestion/store.rs | Makes enqueue idempotency merchant-scoped in the “existing job” check and documentation. |
| migrations/2026-08-11-000001_cost_ingestion_merchant_scoped_dedupe/up.sql | Updates MySQL unique dedupe index to include merchant_id. |
| migrations/2026-08-11-000001_cost_ingestion_merchant_scoped_dedupe/down.sql | Reverts MySQL unique dedupe index back to connector-scoped. |
| migrations_pg/2026-08-11-000001_cost_ingestion_merchant_scoped_dedupe/up.sql | Updates Postgres unique constraint to include merchant_id. |
| migrations_pg/2026-08-11-000001_cost_ingestion_merchant_scoped_dedupe/down.sql | Reverts Postgres unique constraint back to connector-scoped. |
| migrations_pg/00000000000000_diesel_postgresql_initial_setup/down.sql | Expands down-migration cleanup to drop schema tables (per PR description’s “internal cleanup”). |
| docs/api-refs/cost-ingestion-setup.mdx | Updates webhook URL + explains why merchant_id is required and how shared connector accounts work. |
Suppressed comments (1)
src/cost_ingestion/creds.rs:446
ConnectorCredsStore::getnow only looks up the merchant-scoped config key. On upgrade, any credentials previously stored under the legacy key format (e.g.cost_ingest_creds::{connector}::{account}) become unreachable, which can break existing webhooks/polling until everything is re-saved. Consider adding a backwards-compatible fallback lookup (and validating the decrypted blob’s merchant_id matches the requested merchant_id) to keep upgrades smooth.
let name = config_name(merchant_id, connector, account);
let stored = service_configuration::find_config_by_name(name)
.await
.map_err(|e| IngestError::Storage(e.to_string()))?;
match stored.and_then(|c| c.value) {
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
AnkitKmrGupta
force-pushed
the
merchant-scoped-settlement-webhook
branch
from
August 11, 2026 11:38
53ca7d5 to
226b715
Compare
AnkitKmrGupta
force-pushed
the
merchant-scoped-settlement-webhook
branch
from
August 11, 2026 14:15
bded91f to
e5ea141
Compare
… merchant-scoped-settlement-webhook
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.
This pull request introduces merchant scoping for cost ingestion credentials and webhook endpoints, enabling multiple merchants to independently ingest from the same connector account without credential conflicts. The changes update both the API and the storage/indexing model to use
(merchant_id, connector, account)as the primary key for credentials and ingestion deduplication, and provide improved documentation and tests for this new model.API & Documentation Updates:
merchant_idin its path (/webhooks/settlement/:merchant_id/:connector), and the documentation explains why this is necessary for supporting shared connector accounts across merchants. It also describes how multiple merchants can independently ingest from the same connector account. [1] [2]Credential Storage & Indexing:
(merchant_id, connector, account)as the key, ensuring isolation between merchants even if they share connector accounts. This includes changes to config key construction, poll index management, and credential retrieval. [1] [2] [3] [4] [5] [6] [7] [8]Database Migration:
(merchant_id, connector, notification_id)as the unique key, and corresponding down migrations to revert if needed. [1] [2] [3] [4]Testing Improvements:
merchant_idfor correct operation.Internal Cleanup:
These changes collectively ensure that cost ingestion is robust to shared connector accounts and that merchants' credentials and ingestion jobs remain isolated and secure.
Screenshots