This document tracks known gaps, incomplete features, and areas requiring future work in the payment system. These items are documented for transparency and to guide future development.
Currently, only a server-side payment flow has been implemented. A client-side payment flow is planned to support the Product-Agnostic Design using a dedicated Stripe context provider.
Status: Not Implemented
Location: packages/srv-stripe-payment/src/completePayment.ts
Issue: Payments with hostPartnerSlug do NOT create HOST_PARTNER tracking records. Host partners won't receive their 10% of platform fee.
Code Reference:
// TODO: Calculate host partner share (10% of platform fee)
// For now, skip if not implemented
Impact: Medium. Host partners won't accumulate earnings. The schema, enums, and payout infrastructure all support it — only the share calculation logic is missing.
Severity: Medium
Future Work:
createShareTrackingBatch()hostPartnerSlugStatus: Not Implemented
Location: packages/srv-stripe-payment/src/completePayment.ts
Issue: Ambassador shares are not created. Ambassadors won't receive their referral share.
Code Reference:
// TODO: Look up ambassador relationships and create tracking records
// For now, skip if not implemented
Impact: Medium. Ambassadors won't accumulate earnings.
Severity: Medium
Additional Complexity: The user table is now decoupled to the auth project, so ambassador data needs to be stored in a separate table with one-to-one ambassador links.
Future Work:
account_ambassadors table for ambassador relationshipscreateShareTrackingBatch()Status: Not Implemented
Location: packages/srv-stripe-payment/src/webhook.ts
Issue: Refunds initiated from the Stripe Dashboard won't be reflected in the DB. Only refunds via the admin API endpoint work.
Code Reference:
case "charge.refunded": {
// TODO: implement external refund handling (refunds initiated from Stripe Dashboard)
await log.info("charge.refunded received (not yet implemented)", {
chargeId: (event.data.object as Stripe.Charge).id,
});
break;
}
Impact: Medium. Admin-initiated refunds work, but if someone refunds via Stripe Dashboard, the payment records will become inconsistent with Stripe.
Severity: Medium
Future Work:
charge.refunded webhook handlerstripeChargeIdprocessRefund() with the payment IDStatus: Known Limitation
Location: packages/srv-stripe-payment/src/refund.ts
Issue: A narrow race condition exists where two concurrent refund requests could both read the payment as SUCCEEDED before either commits.
Code Reference:
// NOTE: We should use FOR UPDATE lock here, but getStripePaymentById doesn't support it
// For now, we'll rely on status check — enhancement needed
Impact: Low. The idempotency key on the Stripe refund prevents double-refunding at the Stripe level, and the DB status update inside the transaction provides a secondary guard.
Severity: Low
Future Work:
FOR UPDATE lock support to getStripePaymentById() access functionFOR UPDATE lock in refund flow to prevent concurrent refundsStatus: Known Limitation
Location: packages/srv-stripe-payment/src/completePayment.ts
Issue: Two concurrent payment completions for the same payee could double-offset against the same advance balance.
Code Reference:
// NOTE: Should use FOR UPDATE lock, but access function doesn't support it yet
// This is a known limitation — race condition C4 may occur
Impact: Low. This is a rare edge case requiring two payments for the same talent completing simultaneously while an advance is active.
Severity: Low
Future Work:
FOR UPDATE lock support to getPayoutsWithAdvanceBalance() access functionFOR UPDATE lock when reading advance payouts in payment completion flowStatus: Not Implemented
Location: packages/srv-stripe-payment/src/payoutDaemon.ts
Issue: Talent with failed payouts won't receive notification emails about outstanding payouts. The emailOutstandingPayout flag exists but is never updated.
Impact: Low. This is a nice-to-have notification feature, not a core flow.
Severity: Low
Future Work:
updateEmailOutstandingPayout(accountId, true) after sending emailfalse when payout later succeedsStatus: Technical Debt
Location: packages/srv-stripe-payment/src/getProductByPayForId.ts and packages/util/src/calculateStripeFees.ts
Issue: Stripe fee percentages and platform fees are hardcoded. Changing them requires code changes and redeployment.
Code Reference:
// In getProductByPayForId.ts
const PLATFORM_FEE_STANDARD_CENT = 500; // $5.00 fixed
// In @zooly/util calculateStripeFees
const STRIPE_FEE_FIXED_CENT = 30;
const STRIPE_FEE_PERCENTAGE_BPS = 290;
Impact: Low. This is a maintenance concern, not a correctness issue.
Severity: Low
Future Work:
Status: Deferred
Location: packages/srv-stripe-payment/src/webhook.ts
Issue: Several webhook event types are logged but not implemented:
invoice.payment_succeeded (subscription tracking)product.created / product.updated (product sync)price.created / price.updated (price sync)Impact: None for current scope — these are P2 features marked as deferred in the plan.
Severity: None for current scope
Future Work:
stripe_products and stripe_prices tables (schema exists but unused)Status: Under Review
Issue: It's not clear if advance payouts should still be supported. The feature is implemented but may not be needed.
Impact: If removed, simplifies the codebase. If kept, requires concurrency protection improvements.
Future Work:
Status: Known Limitations
Issue: Concurrency protections are explicitly missing in critical money flows. Code comments acknowledge missing FOR UPDATE protection for advance-offset and refund lock paths.
Rationale: Concurrency can only happen if a user makes 2 purchases at the exact same time, which is extremely unlikely.
Future Work:
| Gap | Priority | Severity | Status |
|---|---|---|---|
| HOST_PARTNER Share Tracking | High | Medium | Not Implemented |
| AMBASSADOR Share Tracking | High | Medium | Not Implemented |
| External Refund Webhook | High | Medium | Not Implemented |
| FOR UPDATE Lock (Refund) | Medium | Low | Known Limitation |
| FOR UPDATE Lock (Advance) | Medium | Low | Known Limitation |
| Email Notifications | Medium | Low | Not Implemented |
| Constants in Config | Low | Low | Technical Debt |
| Subscription Sync | Low | None | Deferred |
On This Page
OverviewClient Side - MISSINGHigh Priority Gaps1. HOST_PARTNER Share Tracking2. AMBASSADOR Share Tracking3. External Refund Webhook HandlerMedium Priority Gaps4. Missing FOR UPDATE Lock in Refund Flow5. Missing FOR UPDATE Lock in Advance Offset6. Missing Email Notifications in Payout DaemonLow Priority Gaps7. Constants Not in Config8. Subscription/Product Sync Webhook HandlersDesign Decisions Requiring Review9. Advance Payout Support10. Concurrency ProtectionSummaryNext StepsRelated Documentation