feat: add billing proto definitions and gRPC service#1976
Conversation
Define BillingService with messages for billing runs, invoices, line items, and email delivery tracking. Includes ListBillingRuns, GetBillingRun, ListInvoices, GetInvoice, ResendInvoiceEmail, MarkInvoicePaid, VoidInvoice, and ListInvoiceEmails RPCs with HTTP mappings and OpenAPI annotations.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new Protobuf API file Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client as Client
participant Billing as BillingService
participant DB as Database
participant Email as EmailService
Client->>Billing: ResendInvoiceEmailRequest(invoice_id)
Billing->>DB: Fetch Invoice + InvoiceEmail audit by invoice_id
DB-->>Billing: Invoice + audit entries
alt invoice not found
Billing-->>Client: 404 Not Found
else invoice found
Billing->>Email: Queue/resend email (payload)
Email-->>Billing: Delivery result / status
Billing->>DB: Append InvoiceEmail audit entry
DB-->>Billing: Audit saved
Billing-->>Client: ResendInvoiceEmailResponse(status)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
test |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 321-322: The repeated enum field "status" of type BillingRunStatus
currently accepts arbitrary numeric values and the UNSPECIFIED sentinel; add
protoc-gen-validate item-level rules to reject undefined enum values and
explicitly disallow the *_UNSPECIFIED/zero value. Concretely, update the
"repeated BillingRunStatus status" field (and the other status field around
lines 354-355) to include (validate.rules) with repeated.items configured to
enforce defined_only: true and to not allow the BILLING_RUN_STATUS_UNSPECIFIED
enum value so invalid or zero enums are rejected at the API boundary.
- Around line 241-244: The current string field due_date only enforces
YYYY-MM-DD shape; replace it with a proper date typed field or tighten
validation: import google/type/date.proto and change the field to
google.type.Date due_date = 12 (preferred) so protobuf semantics guarantee valid
dates, or if you must keep a string, update the (buf.validate.field).string
pattern to a stricter regex that validates months (01-12) and days (01-31) and
accounts for leap-year/month-length rules; locate and modify the due_date field
definition in billing.proto accordingly.
- Around line 395-401: Add a caller-supplied idempotency key to the
ResendInvoiceEmailRequest to prevent duplicate queued emails: update the
protobuf message ResendInvoiceEmailRequest by adding a string field named
idempotency_key (documented as a client-provided unique retry token) with
validation (e.g., min_len: 1, reasonable max_len like 100) and update the
comment to explain its semantics; make the same change for the duplicate message
instance referenced at lines ~515-529 so both RPC contracts accept the
idempotency key. Ensure API docs/comments mention that servers should
deduplicate on this key.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 098aa41f-3ad6-46d4-9ab4-0af0304c0407
⛔ Files ignored due to path filters (2)
api/proto/meridian/billing/v1/billing.pb.gois excluded by!**/*.pb.go,!**/*.pb.goapi/proto/meridian/billing/v1/billing_grpc.pb.gois excluded by!**/*.pb.go,!**/*.pb.go,!**/*_grpc.pb.go
📒 Files selected for processing (1)
api/proto/meridian/billing/v1/billing.proto
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
- Add idempotency keys to ResendInvoiceEmail, MarkInvoicePaid, and VoidInvoice mutation requests - Add enum validation (defined_only, not_in UNSPECIFIED) to repeated status filter fields in list requests - Clarify tenant_id and line item currency inheritance in comments
Addressed in latest push
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
api/proto/meridian/billing/v1/billing.proto (3)
541-550: Document idempotency semantics in OpenAPI descriptions.The request now includes an
idempotency_key, but the OpenAPI description doesn't mention this contract. Clients benefit from knowing that retries with the same key are safe. Consider adding a note like: "Duplicate requests with the same idempotency_key will return the original result."This applies to
MarkInvoicePaidandVoidInvoiceas well.♻️ Example description update for ResendInvoiceEmail
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { summary: "Resend invoice email" - description: "Queues a new email delivery for the specified invoice." + description: "Queues a new email delivery for the specified invoice. " + "Requests are idempotent: duplicate calls with the same idempotency_key " + "will return the original queued email without creating duplicates." responses: {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 541 - 550, Update the OpenAPI descriptions for the RPCs to document idempotency semantics: edit the openapiv2_operation.description for ResendInvoiceEmail (and likewise for MarkInvoicePaid and VoidInvoice) to include a short note such as "Requests MAY include an idempotency_key; duplicate requests with the same idempotency_key will return the original result and are safe to retry," so clients know retries with the same idempotency_key are safe and will receive the original response.
173-176: Consider adding pattern validation forquantity.The
quantityfield is a string (presumably to support decimal values like"1.5"for pro-rata billing), but lacks pattern validation. Invalid values like"abc"or empty numeric strings would pass proto-level validation. A pattern like^-?\d+(\.\d+)?$would ensure numeric-like strings while still allowing decimals.♻️ Proposed pattern validation
// quantity is the number of units charged. string quantity = 2 [(buf.validate.field).string = { min_len: 1 max_len: 50 + pattern: "^-?\\d+(\\.\\d+)?$" }];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 173 - 176, The quantity string lacks regex validation and can accept non-numeric values; update the proto field definition for quantity to add a buf.validate.field string.pattern entry with a numeric pattern (e.g., allow optional sign and decimals like ^-?\d+(\.\d+)?$) so the Billing proto's quantity field enforces numeric-like strings; modify the quantity field's options (the string validation block for quantity) to include the pattern attribute so proto-level validation rejects non-numeric inputs.
461-468:ListInvoiceEmailsRequestlacks pagination support.Unlike other list endpoints, this request has no
paginationfield. For invoices in dunning cycles with multiple resend attempts, the response could grow unbounded. Consider adding pagination for consistency and to protect against large payloads.♻️ Proposed pagination addition
// ListInvoiceEmailsRequest returns email audit log entries for an invoice. message ListInvoiceEmailsRequest { // invoice_id is the unique identifier of the invoice. string invoice_id = 1 [(buf.validate.field).string = { min_len: 1 max_len: 100 }]; + + // pagination controls the page size and cursor. + meridian.common.v1.Pagination pagination = 2; }And update the response:
// ListInvoiceEmailsResponse returns the email audit log for an invoice. message ListInvoiceEmailsResponse { // emails is the list of email entries for this invoice. repeated InvoiceEmail emails = 1; + + // pagination contains the next page token and total count. + meridian.common.v1.PaginationResponse pagination = 2; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 461 - 468, Add pagination to the ListInvoiceEmailsRequest by adding a `pagination` field (e.g., of type `google.rpc.ListRequest`/or your project's common Pagination message) to the ListInvoiceEmailsRequest message so callers can page through audit entries; update the corresponding response message (ListInvoiceEmailsResponse) to return a page token/next_page_token and a repeated `email_audit_entry` field consistent with other list endpoints and adjust any service RPC comments and client/server handlers that construct or consume ListInvoiceEmailsRequest/ListInvoiceEmailsResponse to honor the new pagination fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 154-155: BillingRun currently defines total_amount_cents without
an associated currency, causing ambiguity; update the BillingRun message to
include a currency field (e.g., string currency or an enum like Currency)
alongside total_amount_cents and ensure any serialization/deserialization, RPCs,
and consumers that use BillingRun (references to BillingRun and
total_amount_cents) are updated to populate and respect this currency;
alternatively, if intentional, add a clear comment to the BillingRun definition
stating the currency is always the tenant default and ensure downstream code
enforces that invariant.
---
Nitpick comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 541-550: Update the OpenAPI descriptions for the RPCs to document
idempotency semantics: edit the openapiv2_operation.description for
ResendInvoiceEmail (and likewise for MarkInvoicePaid and VoidInvoice) to include
a short note such as "Requests MAY include an idempotency_key; duplicate
requests with the same idempotency_key will return the original result and are
safe to retry," so clients know retries with the same idempotency_key are safe
and will receive the original response.
- Around line 173-176: The quantity string lacks regex validation and can accept
non-numeric values; update the proto field definition for quantity to add a
buf.validate.field string.pattern entry with a numeric pattern (e.g., allow
optional sign and decimals like ^-?\d+(\.\d+)?$) so the Billing proto's quantity
field enforces numeric-like strings; modify the quantity field's options (the
string validation block for quantity) to include the pattern attribute so
proto-level validation rejects non-numeric inputs.
- Around line 461-468: Add pagination to the ListInvoiceEmailsRequest by adding
a `pagination` field (e.g., of type `google.rpc.ListRequest`/or your project's
common Pagination message) to the ListInvoiceEmailsRequest message so callers
can page through audit entries; update the corresponding response message
(ListInvoiceEmailsResponse) to return a page token/next_page_token and a
repeated `email_audit_entry` field consistent with other list endpoints and
adjust any service RPC comments and client/server handlers that construct or
consume ListInvoiceEmailsRequest/ListInvoiceEmailsResponse to honor the new
pagination fields.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: db9d42d0-d7e9-4038-9a46-dce8b38f4e31
⛔ Files ignored due to path filters (2)
api/proto/meridian/billing/v1/billing.pb.gois excluded by!**/*.pb.go,!**/*.pb.gofrontend/src/api/gen/meridian/billing/v1/billing_pb.tsis excluded by!**/gen/**
📒 Files selected for processing (1)
api/proto/meridian/billing/v1/billing.proto
- Add currency field to BillingRun for multi-currency clarity - Document that due_date shape validation is consistent with common.v1.DateRange; semantic validation at service layer
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
api/proto/meridian/billing/v1/billing.proto (1)
284-323: Add a queue timestamp and pagination to the invoice email audit surface.
InvoiceEmailhas noqueued_at/created_at, so pending entries can have no timestamp at all, andListInvoiceEmailsis the only list contract here that is unpaginated. That makes the audit log harder to order now and harder to scale later.🧾 Suggested contract additions
message InvoiceEmail { // idempotency_key is the unique key for this email dispatch. string idempotency_key = 1 [(buf.validate.field).string = { min_len: 1 max_len: 255 }]; @@ // bounce_reason describes why the email bounced (populated only if status is BOUNCED). string bounce_reason = 7 [(buf.validate.field).string = { max_len: 1000 }]; + + // queued_at is when the email was accepted into the outbox. + google.protobuf.Timestamp queued_at = 8 [(buf.validate.field).required = true]; } message ListInvoiceEmailsRequest { // invoice_id is the unique identifier of the invoice. string invoice_id = 1 [(buf.validate.field).string = { min_len: 1 max_len: 100 }]; + // pagination controls the page size and cursor. + meridian.common.v1.Pagination pagination = 2; } message ListInvoiceEmailsResponse { // emails is the list of email entries for this invoice. repeated InvoiceEmail emails = 1; + // pagination contains the next page token and total count. + meridian.common.v1.PaginationResponse pagination = 2; }Also applies to: 468-480
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 284 - 323, InvoiceEmail lacks a timestamp for queue/creation and the list RPC is unpaginated; add google.protobuf.Timestamp fields (e.g., queued_at and created_at) to the InvoiceEmail message to ensure pending entries have a stable ordering, and update the ListInvoiceEmails RPC contract to support pagination (add standard request pagination fields like page_size and page_token and a response next_page_token / repeated InvoiceEmail entries) so the audit list can be ordered and scaled; apply the same timestamp additions to the other InvoiceEmail declaration referenced (lines ~468-480) and ensure field names (queued_at, created_at) and the ListInvoiceEmails request/response symbols are used consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 232-233: ListInvoicesResponse should not reuse full Invoice (which
contains line_items) — introduce a new InvoiceSummary message omitting
line_items and replace the repeated Invoice in ListInvoicesResponse with
repeated InvoiceSummary; keep GetInvoice and the existing Invoice message (with
InvoiceLineItem) for the detail RPC. Update all other spots that currently
return or reference lists of Invoice (see usages around the other occurrences)
to use InvoiceSummary for list/summary endpoints and reserve Invoice for detail
endpoints like GetInvoice.
- Around line 486-625: The proto service BillingService is defined but never
registered; implement a BillingServiceServer (e.g., type billingServiceServer
struct{...} with RPC method implementations for ListBillingRuns, GetBillingRun,
ListInvoices, GetInvoice, ResendInvoiceEmail, MarkInvoicePaid, VoidInvoice,
ListInvoiceEmails), add a constructor like NewBillingServiceServer(...) if
needed, and ensure you call RegisterBillingServiceServer(grpcServer, billingSvc)
during server bootstrap (and register the gateway handler equivalent if using
grpc-gateway), or add a wireBilling(...) function that wires the service into
the app's dependency graph and is invoked from startup so RPCs no longer return
UNIMPLEMENTED.
---
Nitpick comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 284-323: InvoiceEmail lacks a timestamp for queue/creation and the
list RPC is unpaginated; add google.protobuf.Timestamp fields (e.g., queued_at
and created_at) to the InvoiceEmail message to ensure pending entries have a
stable ordering, and update the ListInvoiceEmails RPC contract to support
pagination (add standard request pagination fields like page_size and page_token
and a response next_page_token / repeated InvoiceEmail entries) so the audit
list can be ordered and scaled; apply the same timestamp additions to the other
InvoiceEmail declaration referenced (lines ~468-480) and ensure field names
(queued_at, created_at) and the ListInvoiceEmails request/response symbols are
used consistently.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e7002a4a-b008-4fa8-8313-c6b8825a0f2a
⛔ Files ignored due to path filters (2)
api/proto/meridian/billing/v1/billing.pb.gois excluded by!**/*.pb.go,!**/*.pb.gofrontend/src/api/gen/meridian/billing/v1/billing_pb.tsis excluded by!**/gen/**
📒 Files selected for processing (1)
api/proto/meridian/billing/v1/billing.proto
Add updated_at timestamp to Invoice for tracking status transitions, consistent with BillingRun which has both created_at and updated_at.
Addressed updated_at feedback
There was a problem hiding this comment.
🧹 Nitpick comments (2)
api/proto/meridian/billing/v1/billing.proto (2)
471-478: Consider adding pagination toListInvoiceEmailsRequest.An invoice could accumulate many email records over time (initial send, dunning reminders, manual resends). Without pagination, this endpoint could return an unbounded result set, impacting latency and memory for high-volume invoices. Adding
meridian.common.v1.Paginationwould maintain consistency with the other list endpoints.♻️ Suggested change
message ListInvoiceEmailsRequest { // invoice_id is the unique identifier of the invoice. string invoice_id = 1 [(buf.validate.field).string = { min_len: 1 max_len: 100 }]; + + // pagination controls the page size and cursor. + meridian.common.v1.Pagination pagination = 2; }And update the response:
message ListInvoiceEmailsResponse { // emails is the list of email entries for this invoice. repeated InvoiceEmail emails = 1; + + // pagination contains the next page token and total count. + meridian.common.v1.PaginationResponse pagination = 2; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 471 - 478, Add pagination to the ListInvoiceEmails RPC by updating the request message ListInvoiceEmailsRequest to include a meridian.common.v1.Pagination field (e.g., "pagination") and modify the corresponding response message (ListInvoiceEmailsResponse) to return a repeated email entry list plus a meridian.common.v1.Pagination field for next/total info; update proto imports to reference meridian.common.v1.Pagination and ensure field names/types align with other list endpoints for consistency with existing list message patterns.
177-181: Verify thatquantityas a string type is intentional.Using a string for
quantityallows flexible representation (e.g.,"2.5"hours, fractional units) but requires callers to parse/format values. If quantities are always integers or a fixed decimal precision is expected, consider usingint64with an implicit scale (e.g., milliunits) or a custom decimal message for type safety.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 471-478: Add pagination to the ListInvoiceEmails RPC by updating
the request message ListInvoiceEmailsRequest to include a
meridian.common.v1.Pagination field (e.g., "pagination") and modify the
corresponding response message (ListInvoiceEmailsResponse) to return a repeated
email entry list plus a meridian.common.v1.Pagination field for next/total info;
update proto imports to reference meridian.common.v1.Pagination and ensure field
names/types align with other list endpoints for consistency with existing list
message patterns.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 13432ca5-6006-4437-b8c0-0ea0c80e9410
⛔ Files ignored due to path filters (2)
api/proto/meridian/billing/v1/billing.pb.gois excluded by!**/*.pb.go,!**/*.pb.gofrontend/src/api/gen/meridian/billing/v1/billing_pb.tsis excluded by!**/gen/**
📒 Files selected for processing (1)
api/proto/meridian/billing/v1/billing.proto
|
This PR contains breaking changes to protobuf definitions. Please review the changes carefully and consider:
Run 💡 Tip: If this is an intentional breaking change, add the |
Claude Code ReviewCommit: SummaryWell-structured billing service proto definition with 8 RPCs covering billing runs, invoices, and email delivery tracking. The author has iterated well through review -- adding idempotency keys to all mutations, enum validation on status filters, currency fields, Risk Assessment
Findings
Bot Review NotesCodeRabbit thread 1 ( CodeRabbit thread 2 ( CodeRabbit thread 3 ( Previously Flagged
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
api/proto/meridian/billing/v1/billing.proto (3)
154-160: Consider explicit validation for currency and amount fields.
total_amount_cents(line 155) lacks non-negativity validation. While billing run totals should always be non-negative, adding[(buf.validate.field).int64 = {gte: 0}]would make this invariant explicit.
currency(lines 158-160) pattern^[A-Z]{3}$implicitly requires the field since empty string won't match, but this isn't obvious. Consider addingmin_len: 3for clarity.♻️ Suggested validation improvements
// total_amount_cents is the sum of all invoice amounts in this billing run (in minor currency units). - int64 total_amount_cents = 9; + int64 total_amount_cents = 9 [(buf.validate.field).int64 = {gte: 0}]; // currency is the ISO 4217 currency code for this billing run (e.g., "GBP", "USD"). string currency = 12 [(buf.validate.field).string = { + min_len: 3 pattern: "^[A-Z]{3}$" }];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 154 - 160, Add explicit validation rules to the billing run fields: enforce non-negativity for total_amount_cents by adding a buf.validate int64 constraint (e.g., gte: 0) on the total_amount_cents field, and make the currency requirement explicit by adding a string min_len: 3 validation to the currency field in addition to the existing regex pattern; update the field options for total_amount_cents and currency accordingly so their invariants are clear and enforced.
234-241: Consider non-negativity validation forsubtotal_cents.
subtotal_cents(line 236) lacks validation. If negative invoice subtotals are invalid in your domain (credits handled separately), adding[(buf.validate.field).int64 = {gte: 0}]would enforce this at the API boundary.The
currencyfield has the same implicit-requirement issue asBillingRun.currencynoted earlier.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 234 - 241, Add a non-negativity buf validation to the invoice subtotal by updating the subtotal_cents field to include [(buf.validate.field).int64 = {gte: 0}] so negative subtotals are rejected at the API boundary; also review the currency field and the related BillingRun.currency for implicit-requirement issues and add appropriate validation (e.g., required/regex or presence semantics) to enforce the expected ISO-4217 value or make the field explicitly optional if blanks are allowed.
301-310: Consider basic email format validation forto_addresses.The
to_addressesfield validates string length but not email format. While comprehensive email validation is complex, a basic pattern likepattern: "^.+@.+$"could reject obviously invalid input at the API boundary.Alternatively, if complex validation is deferred to the service layer (as mentioned in the learnings about protovalidate limitations), this is acceptable but worth documenting.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/proto/meridian/billing/v1/billing.proto` around lines 301 - 310, Add a basic email-format pattern validation to the to_addresses field in the Billing proto: update the repeated string field "to_addresses" to include a simple regex (e.g., pattern: "^.+@.+$") in its validation options so obviously invalid emails are rejected at the API boundary; keep the existing min_len/max_len checks and note in comments if more comprehensive validation will be performed in the service layer.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 177-188: Replace the plain string quantity field with the typed
InstrumentAmount and add non-negativity validation to price fields: change the
quantity field to use meridian.quantity.v1.InstrumentAmount (reference:
quantity) instead of string to match other services, and add buf.validate
constraints gte: 0 to both unit_price_cents and total_cents (reference:
unit_price_cents, total_cents) so negative prices are rejected; if the original
free-text intent for quantity is deliberate, instead add a clarifying comment
documenting the expected format.
---
Nitpick comments:
In `@api/proto/meridian/billing/v1/billing.proto`:
- Around line 154-160: Add explicit validation rules to the billing run fields:
enforce non-negativity for total_amount_cents by adding a buf.validate int64
constraint (e.g., gte: 0) on the total_amount_cents field, and make the currency
requirement explicit by adding a string min_len: 3 validation to the currency
field in addition to the existing regex pattern; update the field options for
total_amount_cents and currency accordingly so their invariants are clear and
enforced.
- Around line 234-241: Add a non-negativity buf validation to the invoice
subtotal by updating the subtotal_cents field to include
[(buf.validate.field).int64 = {gte: 0}] so negative subtotals are rejected at
the API boundary; also review the currency field and the related
BillingRun.currency for implicit-requirement issues and add appropriate
validation (e.g., required/regex or presence semantics) to enforce the expected
ISO-4217 value or make the field explicitly optional if blanks are allowed.
- Around line 301-310: Add a basic email-format pattern validation to the
to_addresses field in the Billing proto: update the repeated string field
"to_addresses" to include a simple regex (e.g., pattern: "^.+@.+$") in its
validation options so obviously invalid emails are rejected at the API boundary;
keep the existing min_len/max_len checks and note in comments if more
comprehensive validation will be performed in the service layer.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4d965f37-ff88-45b8-91cc-881d11d212b2
⛔ Files ignored due to path filters (2)
api/proto/meridian/billing/v1/billing.pb.gois excluded by!**/*.pb.go,!**/*.pb.gofrontend/src/api/gen/meridian/billing/v1/billing_pb.tsis excluded by!**/gen/**
📒 Files selected for processing (1)
api/proto/meridian/billing/v1/billing.proto
Remaining suggestions are out of scope for proto definition task
Summary
BillingServiceproto with messages for billing runs, invoices, line items, and email delivery trackingTest plan
buf lint api/protopassesbuf build api/protopassesbuf generate api/protoproduces Go clients