Skip to content

[Feature] Merchant webhooks, nearest-driver assignment, driver earnings, and proof-of-delivery gating - #178

Merged
Tybravo merged 4 commits into
SwiftChainn:mainfrom
Dannyorji:backend-task
Sep 1, 2026
Merged

[Feature] Merchant webhooks, nearest-driver assignment, driver earnings, and proof-of-delivery gating#178
Tybravo merged 4 commits into
SwiftChainn:mainfrom
Dannyorji:backend-task

Conversation

@Dannyorji

Copy link
Copy Markdown
Contributor

Summary

  • Webhook dispatch system (src/services/webhookService.ts): merchants register HTTPS
    endpoints (WebhookSubscription) that receive a signed (HMAC-SHA256), retried POST on every
    delivery status transition. Attempts are persisted (WebhookDeliveryAttempt) so retries
    survive a restart; a cron sweep (jobs/webhookRetryJob.ts) drives exponential-backoff retries
    up to WEBHOOK_MAX_RETRIES. CRUD endpoints live under POST/GET/PATCH/DELETE /api/v1/webhooks
    (merchant/admin only), including secret rotation.

  • Nearest-driver assignment (src/services/assignmentService.ts): finds and assigns the
    nearest available driver to a funded delivery using the existing DriverLocation 2dsphere
    index, expanding the search radius on a miss (up to ASSIGNMENT_RADIUS_EXPANSION_STEPS).
    Race conditions are handled with an atomic per-driver claim (findOneAndUpdate on
    isAvailable) plus a per-delivery Redis lock, so concurrent attempts can't double-book a
    driver or a delivery. A cron sweep auto-assigns unassigned funded deliveries; a manual admin
    endpoint (POST /api/v1/deliveries/:id/assign-nearest-driver) covers on-demand retries.

  • Driver earnings ledger (GET /api/v1/drivers/:id/earnings): aggregates a driver's
    earnings by day/week/month from resolved (released) Escrow documents joined to their
    delivery's driverId, rather than deriving amounts from the Delivery record. Accessible by
    the driver themselves or an admin.

  • Proof of delivery gating: drivers must upload a completion photo
    (POST /api/v1/deliveries/:id/proof-of-delivery, stored via the existing S3/local storage
    driver abstraction) before a delivery can transition to completed or its escrow can be
    released. The image reference is stored on the Delivery document; both the completion
    transition (delivery.service.ts) and the escrow release flow (escrow.service.ts) now
    assert proof exists first.

Notes

  • New env vars (all with sane defaults) cover webhook retry tuning, assignment radius
    expansion/cron, and proof-of-delivery upload limits — see src/config/env.ts.
  • Fixed a pre-existing duplicate-import bug in src/routes/index.ts while wiring up the new
    routers.

Closes #127
Closes #128
Closes #130
Closes #133

Dannyorji and others added 4 commits September 1, 2026 08:49
Merchants can register HTTPS endpoints per delivery-lifecycle event; every
delivery status transition now fires a signed (HMAC-SHA256), retried
(exponential backoff via a cron sweep) POST to each subscribed endpoint,
persisted through WebhookSubscription/WebhookDeliveryAttempt so retries
survive a process restart.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Assigns the nearest available driver to a funded delivery using the
existing DriverLocation 2dsphere index, expanding the search radius on a
miss. Race conditions are handled with an atomic per-driver claim
(findOneAndUpdate on isAvailable) plus a per-delivery Redis lock, so
concurrent assignment attempts cannot double-book a driver or a delivery.
A cron sweep auto-assigns unassigned funded deliveries on a schedule, and
a manual admin endpoint (POST /deliveries/:id/assign-nearest-driver)
covers on-demand retries.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GET /api/v1/drivers/:id/earnings aggregates a driver's earnings by
day/week/month, sourced from resolved (released) Escrow documents joined
to their delivery's driverId rather than derived from Delivery fields.
Accessible by the driver themselves or an admin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Drivers must upload a delivery image (stored via the existing S3/local
storage driver abstraction) before a delivery can transition to completed
or its escrow can be released. The image reference lives on the Delivery
document; both the completion transition (delivery.service.ts) and the
escrow release endpoint (escrow.service.ts) now assert proof exists first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@drips-wave

drips-wave Bot commented Sep 1, 2026

Copy link
Copy Markdown

@Dannyorji Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Tybravo

Tybravo commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

@Dannyorji

Thank you for contributing to the project

@Tybravo
Tybravo merged commit c866416 into SwiftChainn:main Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants