Skip to content

feat(billing-platform): add refund types and endpoints for charge.refunded flow#298

Draft
armcknight wants to merge 4 commits into
mainfrom
andrewmcknight/reveng-157-platform-refunds
Draft

feat(billing-platform): add refund types and endpoints for charge.refunded flow#298
armcknight wants to merge 4 commits into
mainfrom
andrewmcknight/reveng-157-platform-refunds

Conversation

@armcknight

@armcknight armcknight commented Jun 8, 2026

Copy link
Copy Markdown
Member

Summary

Adds the proto contracts needed to handle refunds on the billing platform (REVENG-157).

  • common/v1/stripe_charge.proto: new StripeRefund message + repeated refunds on StripeCharge so webhooks can carry per-refund metadata (id, amount, reason) for idempotent ingestion. The aggregate amount_refunded alone isn't enough to dedupe refunds by Stripe refund id.
  • services/charge/v1/charge.proto: new PlatformRefund canonical projection, paralleling PlatformCharge.
  • services/charge/v1/endpoint_refund_charge.proto: ChargeService.refund_charge — admin-initiated refund (calls Stripe + records PlatformRefund, with over-refund guard and optimistic locking implemented service-side).
  • services/charge/v1/endpoint_record_charge_refunds.proto: ChargeService.record_charge_refunds — webhook-side counterpart (Stripe already refunded; just records PlatformRefund rows idempotently and syncs aggregates). Lets the charge.refunded presentation handler avoid importing the charge service's models directly.
  • services/charge/v1/endpoint_list_refunds.proto: ChargeService.list_refunds_by_invoice so presentation surfaces can render invoice-level refund state without crossing the charge service boundary.
  • services/invoicer/v1/endpoint_handle_charge_refunded.proto: InvoicerService.handle_charge_refunded — mirrors handle_charge_succeeded for the charge.refunded webhook path.

Stack

This is the bottom of a stack for REVENG-157. Follow-up getsentry PRs that consume these contracts:

  1. PlatformRefund model + ChargeService.refund_charge/record_charge_refunds/list_refunds_by_invoice implementation
  2. charge.refunded webhook + InvoicerService.handle_charge_refunded
  3. Admin refund endpoint platform-aware
  4. Render refunds in customer-facing surfaces (invoices list, receipt PDF, invoice details)

Kept draft while the full stack is built and tested end-to-end at the top.

Test plan

  • make build-py regenerates without errors
  • Stack-top integration test (in follow-up getsentry PR) exercises all six proto messages end-to-end against a local devserver

🤖 Generated with Claude Code

…unded flow

Adds the proto contracts needed to handle refunds on the billing platform
(REVENG-157):

- `common/v1/stripe_charge.proto`: new `StripeRefund` message + `repeated
  refunds` on `StripeCharge` so webhooks can convey per-refund metadata
  (id, amount, reason) for idempotent ingestion.
- `services/charge/v1/charge.proto`: new `PlatformRefund` canonical
  projection paralleling `PlatformCharge`.
- `services/charge/v1/endpoint_refund_charge.proto`: `ChargeService.refund_charge`
  for admin-initiated refunds (calls Stripe + records `PlatformRefund`).
- `services/charge/v1/endpoint_list_refunds.proto`:
  `ChargeService.list_refunds_by_invoice` so presentation surfaces can
  render invoice-level refund state without crossing service boundaries.
- `services/invoicer/v1/endpoint_handle_charge_refunded.proto`:
  `InvoicerService.handle_charge_refunded`, mirrors `handle_charge_succeeded`
  for the `charge.refunded` webhook path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 8, 2026

Copy link
Copy Markdown

REVENG-157

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow ci / buf-checks (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJun 8, 2026, 11:32 PM

getsantry Bot and others added 3 commits June 8, 2026 23:30
Webhook-side counterpart to ``refund_charge``. Records ``PlatformRefund``
rows idempotently from a ``StripeCharge`` payload (the Stripe-side refund
has already happened) and syncs aggregate refund state on the stored
``PlatformCharge``. Allows the presentation handler for ``charge.refunded``
to record refunds without crossing service boundaries to the charge
service's models.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant