Skip to content

feat(audit): correlation id on payment commands + events (Story 13.7 …#27

Merged
fupelaqu merged 3 commits into
mainfrom
feature/audit
Jun 15, 2026
Merged

feat(audit): correlation id on payment commands + events (Story 13.7 …#27
fupelaqu merged 3 commits into
mainfrom
feature/audit

Conversation

@fupelaqu

Copy link
Copy Markdown
Contributor

…Phase B gate #4)

PaymentCommand extends AuditableCommand (var correlationId + withCorrelationId; zero churn). The three consumed payment events extend AuditableEvent + carry correlation_id (PaidInEvent #10, FirstRecurringPaidInEvent #10, NextRecurringPaidEvent #14).

handlePayIn / handleRecurringPayment take a correlationId param threaded from cmd.correlationId at their call sites and stamp it onto the persisted event (.copy). The checkout payIn endpoint prepends HttpCorrelation.correlationInput and stamps the PayIn command, so the originating X-Correlation-Id rides command -> PaidInEvent -> the licensing pod.

Bumps genericPersistence -> 0.9-SNAPSHOT, scheduler -> 0.8-SNAPSHOT, notification -> 0.9-SNAPSHOT, version -> 0.9-SNAPSHOT. AuditableCommandSpec (chill/Kryo round-trip, 3 green); +common/+core compile (2.12+2.13) + scalafmtAll clean.

Remaining origin coverage (follow-up): preAuthorize / recurring-registration / payInCallback endpoints + the akka-http PaymentService variant + schedule->ExecuteNext command threading. Core events are correlation-ready; gate #5 prefers event.correlationId else the deterministic in-pod fallback.

…Phase B gate #4)

PaymentCommand extends AuditableCommand (var correlationId + withCorrelationId; zero churn). The three consumed payment events extend AuditableEvent + carry correlation_id (PaidInEvent #10, FirstRecurringPaidInEvent #10, NextRecurringPaidEvent #14).

handlePayIn / handleRecurringPayment take a correlationId param threaded from cmd.correlationId at their call sites and stamp it onto the persisted event (.copy). The checkout payIn endpoint prepends HttpCorrelation.correlationInput and stamps the PayIn command, so the originating X-Correlation-Id rides command -> PaidInEvent -> the licensing pod.

Bumps genericPersistence -> 0.9-SNAPSHOT, scheduler -> 0.8-SNAPSHOT, notification -> 0.9-SNAPSHOT, version -> 0.9-SNAPSHOT. AuditableCommandSpec (chill/Kryo round-trip, 3 green); +common/+core compile (2.12+2.13) + scalafmtAll clean.

Remaining origin coverage (follow-up): preAuthorize / recurring-registration / payInCallback endpoints + the akka-http PaymentService variant + schedule->ExecuteNext command threading. Core events are correlation-ready; gate #5 prefers event.correlationId else the deterministic in-pod fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 42.08038% with 245 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.92%. Comparing base (871e6cd) to head (0d4378a).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...yment/persistence/typed/PayOutCommandHandler.scala 21.68% 65 Missing ⚠️
...ayment/persistence/typed/PayInCommandHandler.scala 46.34% 44 Missing ⚠️
...ftnetwork/payment/service/StripeEventHandler.scala 31.91% 32 Missing ⚠️
...rk/payment/persistence/typed/PaymentBehavior.scala 32.55% 29 Missing ⚠️
...istence/typed/RecurringPaymentCommandHandler.scala 56.71% 29 Missing ⚠️
...istence/typed/PreAuthorizationCommandHandler.scala 68.08% 15 Missing ⚠️
...rk/payment/service/RecurringPaymentEndpoints.scala 20.00% 8 Missing ⚠️
...ersistence/typed/PaymentMethodCommandHandler.scala 50.00% 5 Missing ⚠️
.../app/softnetwork/payment/spi/StripeRefundApi.scala 0.00% 4 Missing ⚠️
...softnetwork/payment/service/MandateEndpoints.scala 40.00% 3 Missing ⚠️
... and 6 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #27      +/-   ##
==========================================
+ Coverage   40.80%   40.92%   +0.12%     
==========================================
  Files         155      155              
  Lines       10549    10861     +312     
  Branches     1604     1810     +206     
==========================================
+ Hits         4304     4445     +141     
- Misses       6245     6416     +171     
Flag Coverage Δ
unittests 40.92% <42.08%> (+0.12%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

fupelaqu and others added 2 commits June 15, 2026 15:36
…metadata (Story 13.7 gate #4)

Emit structured payment audit lines and carry a single correlation id end-to-end (HTTP origin -> command -> persisted event -> licensing pod -> notification), with a stable orderUuid fallback so no event/line is ever untraceable.

Audit emission (PaymentAuditLog = AuditLog("payment")): charge_succeeded/charge_failed (PayIn), subscription_charged/subscription_charge_failed (recurring), refund/refund_failed, preauthorization_succeeded/failed/canceled, payout_succeeded/failed.

Coherence: each command handler shadows the threaded cid with effectiveCorrelationId = cid.getOrElse(<businessKey: orderUuid / transaction.orderUuid / recurringPayment.externalReference>), stamped on EVERY event in the persist batch and used for the audit line, so event.correlationId (read by the licensing pod) and the audit line always agree.

Stripe WRITE side: providers stamp metadata.correlation_id on object creation (PayIn/PayOut/PreAuth/Refund/Transfer/DirectDebit); RecurringPayment carries it via its metadata map, falling back to the subscription id when no explicit cid.

Stripe READ side (StripeEventHandler): webhook_received audit line + resolveCorrelationId(obj,event) = metadata.correlation_id -> external_reference -> order_uuid -> backing subscription id -> event id; all webhook-driven command stamps routed through it.

Protos: correlation_id on transaction/payment events + AuditableEvent; commands extend AuditableCommand. Endpoints: correlationInput wired across all payment endpoints (origin at the HTTP request). BasicPaymentService.run stamps the MDC cid on synchronous routes.

Tests: AuditableCommandSpec (chill/Kryo cid round-trip), StripeWebhookCorrelationSpec (metadata resolution + subscription-id fallback + webhook_received), PaymentHandlerSpec charge_succeeded capture. scalafmt clean; cross-compiles 2.12 + 2.13.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@fupelaqu fupelaqu merged commit 68efbf3 into main Jun 15, 2026
3 checks passed
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