feat: Stripe invoice PDF delivery, Vercel build cache invalidation, multi-provider OAuth#701
Merged
temma02 merged 2 commits intoMay 30, 2026
Conversation
…ulti-provider OAuth StellerCraft#659 — Stripe invoice PDF generation and email delivery - Add InvoiceDeliveryService that retrieves the hosted invoice PDF URL from Stripe and emails it to the customer on subscription renewal - Hook into the invoice.payment_succeeded webhook event in PaymentService; delivery failures are logged but do not fail the webhook (best-effort) - Email sending uses a configurable provider (EMAIL_API_URL/EMAIL_API_KEY/ EMAIL_FROM env vars); falls back to console logging in dev/test - Retry transient email failures with exponential back-off via retryWithBackoff - Tests: invoice PDF retrieval, email delivery, email-from-expanded-customer, missing PDF URL, missing email, retry wrapper invoked, dev-mode logging StellerCraft#660 — Vercel build cache invalidation strategy for template code generation - Add BuildCacheService that computes a deterministic SHA-256 content hash over all generated files (sorted by path for order-independence) - Integrate cache check into DeploymentPipelineService after syntax validation: logs cache hit/miss with the content hash prefix - Store the hash in deployments.customization_config._buildCacheHash after a successful build so future runs can detect unchanged code (cache hit) - Tests: deterministic hash, order-independence, content-change detection, file-addition detection, cache hit/miss logic, hash persistence StellerCraft#661 — Multi-provider OAuth token exchange for GitHub and Stellar wallet - Add MultiProviderAuthService coordinating GitHub and Stellar wallet auth under a single platform identity (Supabase user ID) - GitHub tokens are encrypted with AES-256-GCM (existing token-encryption lib) before storage; Stellar stores only the wallet public key — no private key is ever held by the platform - Provider tokens are isolated: GitHub uses existing profile columns; Stellar uses a new provider_connections JSONB column - Handles partial connection (one provider connected, not the other) - Add migration 012_multi_provider_oauth.sql adding provider_connections JSONB column to profiles; update database.types.ts accordingly - Tests: GitHub token encryption on connect, expiry storage, Stellar public-key- only storage, existing connections preserved, disconnect clears correct fields, partial connection status, token decryption, public key retrieval Closes StellerCraft#659 Closes StellerCraft#660 Closes StellerCraft#661
|
@topsonDev 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! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements three features in a single PR.
#659 — Stripe invoice PDF generation and email delivery
New file:
apps/backend/src/services/invoice-delivery.service.tsModified:
apps/backend/src/services/payment.service.tsInvoiceDeliveryServiceretrieves the Stripe-hosted invoice PDF URL and emails it to the customer on every successful subscription renewal.invoice.payment_succeededwebhook event inPaymentService.handleWebhook. Delivery failures are caught and logged — they do not fail the webhook so Stripe does not retry unnecessarily.EMAIL_API_URL,EMAIL_API_KEY, andEMAIL_FROM. Falls back toconsole.logwhenEMAIL_API_URLis unset (dev/test mode).retryWithBackoffutility.#660 — Vercel build cache invalidation strategy
New file:
apps/backend/src/services/build-cache.service.tsModified:
apps/backend/src/services/deployment-pipeline.service.tsBuildCacheService.computeContentHashproduces a deterministic SHA-256 hash over all generated files (sorted by path, order-independent).checkCachecompares the new hash against the value stored indeployments.customization_config._buildCacheHashand returnshitormiss.DeploymentPipelineServiceafter syntax validation: cache status (hit/miss + hash prefix) is written to deployment logs.storeHashpersists the hash after a successful build so future runs can detect unchanged code without triggering a redundant Vercel deployment.#661 — Multi-provider OAuth token exchange
New file:
apps/backend/src/services/multi-provider-auth.service.tsNew migration:
supabase/migrations/012_multi_provider_oauth.sqlModified:
apps/backend/src/lib/supabase/database.types.tsMultiProviderAuthServicecoordinates GitHub and Stellar wallet auth under a single platform identity (Supabase user ID).encryptToken/decryptToken) before storage in the existinggithub_token_encryptedcolumn. Stellar stores only the wallet public key in the newprovider_connectionsJSONB column — no private key is ever held by the platform.provider_connections JSONBtoprofiles;database.types.tsupdated accordingly.Tests
27 tests added across 3 new test files — all passing:
invoice-delivery.service.test.tsbuild-cache.service.test.tsmulti-provider-auth.service.test.tsCloses #659
Closes #660
Closes #661