feat: pymthouse plans + subscribe checkout - #8
Open
eliteprox wants to merge 14 commits into
Open
Conversation
Wire BFF routes and PlansPanel through builder-sdk createBillingCheckout so dashboard can exercise end-user checkout against pymthouse before NaaP.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
5 tasks
builder-sdk#50 merged and published; drop the git branch pin and the onlyBuiltDependencies workaround needed for prepare-on-install.
Collaborator
Author
|
Pinned to published |
Resolve dep conflict on the stacked base; keep createBillingCheckout plus the 0.6.3 Sonar/CI security patch.
Collaborator
Author
|
Synced with #3 and bumped pin to |
Add merchant card controls and invoice links through the billing BFF so users can manage their payment method and access Connect-hosted invoices.
Wire useBillingAccount into BillingSection: live payment method list
with Set-as-default and Remove (confirm) row actions, live invoice
table with View/PDF links resolved via the Stripe hosted-url endpoint,
and updated copy ("Stripe invoices for this account"). Removes static
blur/WIP overlay and fake billing-details block; plan section stays
static pending subscribe-flow work.
Keep plan actions aligned with the current PymtHouse subscription so active users change plans or resume checkout instead of creating conflicting subscriptions.
useAccountUsage cast every 200 body straight to AccountUsagePayload, so a malformed response became a value that lied about its type. Consumers then dereferenced `period.end` and ran BigInt reads over `current`/`balance` and threw during render — a broken upstream body surfaced as a crashed page rather than as the error state the hook already has. Responses are now shape-checked at runtime and malformed bodies route to that existing error state. The guard covers only the fields consumers dereference without a fallback; `clientId` and `priorPeriod` are carried by the type but never read, so they are deliberately unchecked. Error messages on non-OK responses are likewise read without trusting the body shape.
…oard env
The dashboard kept its own copy of the signer DMZ base in
PYMTHOUSE_SIGNER_URL (plus two aliases) and used it as a fallback whenever
the issuer did not return signer_url. That made the dashboard a second
source of truth for a value the issuer already owns, so a signer move meant
redeploying the dashboard to stay reachable.
The issuer is now the only source: API-key exchange takes signer_url from
the exchange response, and signer sessions resolve it from
GET …/apps/{clientId}/signer/routing, cached for five minutes so the
routing lookup does not add a round trip per session. Locally built
python-gateway --token bundles are dropped in favour of the issuer-built
sdkToken, which already carries the routing. PYMTHOUSE_SIGNER_URL is
removed from .env.example accordingly.
Key creation also no longer reloads the list mid-flight: the caller inserts
the new row and reveals the full key in the same paint, then soft-refreshes,
so a slow list fetch cannot delay or blank the reveal.
The UI trusted any pendingCancel the Builder API returned, but upstream
reports whichever canceled OpenMeter row still occupies the slot — including
one belonging to a plan the user has already switched away from. Billing
therefore showed "Pay as you go" as the current plan while simultaneously
offering to restore a superseded plan, behind a restore button that could
only fail. Cancel/restore affordances now require the pending cancel to
match the live plan, current-plan resolution is single-sourced through
deriveBillingSubscriptionUiState, and a rejected resume reconciles the stale
snapshot instead of stranding an error.
That reconciliation keys on the upstream machine-readable code
`nothing_to_resume`, not on the status class. Treating any 4xx as "nothing
was scheduled" silently swallowed 401/403, unrelated 404s, and the 502
`resume_failed` branch where a resume target existed but the restore threw;
those are real failures and now surface as such.
Cancel and plan change gain explicit timing (immediate, end of period, or a
chosen date), and a scheduled-change conflict prompts before replacing the
existing schedule rather than failing opaquely.
pymthouse-bff gains isUserNotFoundError, accepting both the `code:
"not_found"` envelope and the code-less `{"error":"not_found"}` the
mint-token route returns, so auto-provisioning keeps working across
builder-sdk versions.
Alongside this, the owner wallet surface: prepaid balance, Stripe top-up,
platform invoices, and the auto-debit payment method over Builder M2M. Plan
listing hydrates pay-per-use threshold and behaviour copy from the wallet
summary because the apiVersion=2 product shape omits them, falling back to
generic copy when the wallet API is absent. Allowance copy moves from
"Starter" to "Prepaid" to match. Checkout return URLs prefer a configured
public HTTPS origin, since Stripe rejects most http return URLs.
The settings rail reads its active tab from useSearchParams rather than
window.location, which disagreed between SSR and client and left General
highlighted on a ?tab=billing load until hydration.
Wallet and subscription changes share lib/dashboard/pymthouse-billing-bff.ts
and plan listing calls into the wallet summary, so they ship together rather
than being split by hunk.
Replace soft-limit strip copy with the API-owned posture card (status badge, buffer meter, collection schedule) and align pay-per-use plan wording with progressive invoicing.
- Changed `MockUser.id` to derive from email using SHA-256 for consistency. - Updated `connect` and `updateUser` methods to return promises for better async handling. - Enhanced `hydrateMockUser` to support async operations and ensure proper user ID assignment. - Improved localStorage handling for user sessions and legacy machine IDs. - Adjusted login page to await connection on email and OAuth submissions. - Refined comments and documentation for clarity.
- Introduced `formatBillingPlanPrice` to standardize billing plan price formatting, including handling of included usage for Starter plans. - Updated `isUsagePlan` to account for `isStarterDefault` in plan checks. - Enhanced `PlansPanel` and `BillingSection` components to support new billing logic, including improved URL handling for plan changes. - Added `availableRunway` and `overageLimitNote` functions to better represent wallet states and spending limits in the UI. - Implemented soft error handling for billing list availability in `useBillingAccount`. - Updated tests to cover new billing functionalities and ensure accurate behavior across components.
…hance billing UI - Added a new API route for retrieving user subscriptions, ensuring externalUserId is validated. - Introduced a `TimingChoicePanel` component for selecting subscription change timing options. - Enhanced `PlansPanel` and `BillingSection` components to support subscription timing changes and conflicts. - Updated billing state management to include subscription history and error handling for subscription-related actions. - Refactored existing billing functions to accommodate new subscription logic and improve user experience.
- Changed dependency from local file reference to versioned package for better stability and compatibility. - Updated pnpm-lock.yaml to reflect the new versioning for @pymthouse/builder-sdk.
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
GET /api/pymthouse/plansandPOST /api/pymthouse/subscribeBFF routes via@pymthouse/builder-sdklistBillingProducts/createBillingCheckout@pymthouse/builder-sdkto published0.6.3Test plan
PYMTHOUSE_PUBLIC_CLIENT_IDset, open/usageand confirm active plans loadpnpm typecheck/pnpm lintStacked on: #3