docs: design plan for lit-payments app#354
Conversation
Plan covers a separate ops-facing app for billing operations the main lit-api-server shouldn't carry: admin credit portal (Discord mod support), LITKEY -> Stripe credit via a payment gateway contract on Base, and deferred subscription billing. Built as a new Rust crate in this monorepo, deployed on Railway outside the TEE. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
|
||
| Build a separate, ops-facing app that handles billing operations the main `lit-api-server` shouldn't carry: | ||
|
|
||
| 1. **Admin credit portal** — a logged-in moderator (Discord support, etc.) can credit a customer's Stripe balance by email or wallet address. |
| Build a separate, ops-facing app that handles billing operations the main `lit-api-server` shouldn't carry: | ||
|
|
||
| 1. **Admin credit portal** — a logged-in moderator (Discord support, etc.) can credit a customer's Stripe balance by email or wallet address. | ||
| 2. **LITKEY → Stripe credit** — let users pay with LITKEY tokens from the dashboard via a "Pay with tokens" button; auto-credit their Stripe balance. Replaces today's manual flow. |
There was a problem hiding this comment.
If someone is savvy enough to pay with Lit tokens, shouldn't this really just be a contract call ? ie, send your tokens to our contract, which emits an event which is picked up by this app which applies the credit ? I suppose we could do this through a dashboard, though.
There was a problem hiding this comment.
Scratch this - I noted it later on.!
|
|
||
| 1. **Admin credit portal** — a logged-in moderator (Discord support, etc.) can credit a customer's Stripe balance by email or wallet address. | ||
| 2. **LITKEY → Stripe credit** — let users pay with LITKEY tokens from the dashboard via a "Pay with tokens" button; auto-credit their Stripe balance. Replaces today's manual flow. | ||
| 3. **Subscription billing** *(deferred)* — set up monthly auto-charged subscriptions for B2B clients, with credits automatically applied each cycle. Build after #1 and #2 ship. |
There was a problem hiding this comment.
Doesn't this exist natively in Stripe ? We could expose the configuration setup through this app, though.
There was a problem hiding this comment.
Scratch the billing - I note later on it's in stripe. This is just a UI thing.
|
|
||
| ## Non-goals | ||
|
|
||
| - Replacing the existing customer dashboard (`lit-static/dapps/dashboard/`). End users still top up there. |
There was a problem hiding this comment.
Careful. "dashboard" is the entire app ;-) I'd get rid of the top up here - doesn't make sense you can do this in 2 different places.
| ## Non-goals | ||
|
|
||
| - Replacing the existing customer dashboard (`lit-static/dapps/dashboard/`). End users still top up there. | ||
| - Self-serve subscriptions for end users. The first subscription is a B2B contract Lit sets up; self-serve can come later as a *user-facing* edge in the dashboard, with the backend re-using this app's logic. |
There was a problem hiding this comment.
Can we just expose Stripe functionality ?
| **CoinGecko ID**: `lit-protocol` (from `https://www.coingecko.com/en/coins/lit-protocol`). | ||
|
|
||
| ### Edge cases | ||
|
|
There was a problem hiding this comment.
customer Id's are stored on chain. If we scrap postgress and just use the chain, we can check this.
| - Signed-URL token issuer in the existing dashboard backend (small change to `lit-api-server`). | ||
| - `payments.litprotocol.com/payWithLitkey` page (vanilla HTML/JS + Wagmi). | ||
| - Admin views for unattributed payments + rate config. | ||
| - Postgres tables: `litkey_payments`, `litkey_unattributed_payments`, `litkey_config`. |
There was a problem hiding this comment.
Again - would argue against database tables and maintaining state somewhere - especially when we already have the data & meta-data in stripe or in contracts right now ( save for the treasury / payment-gateway related contract/facet addition & the pricing history ).
| ## Feature 3 — Subscription billing *(deferred to phase 2)* | ||
|
|
||
| Detailed design preserved for later; build after #1 and #2 are in production. | ||
|
|
There was a problem hiding this comment.
Might have missed this above - >. this is stuff appears accurate.
| | 1 | Hostname | `payments.litprotocol.com` | | ||
| | 2 | Cloud provider | Railway (service + managed Postgres) | | ||
| | 3 | Shared crate vs copy | Copy Stripe helpers into new crate now; extract `lit-billing-core` later if drift becomes painful | | ||
| | 4 | Operator auth | Magic link via email from day 1 (Resend); 15-min token, 7-day session cookie | |
There was a problem hiding this comment.
Or give the admin operators an account in the current system and skip all of this.
| ## Risks | ||
|
|
||
| - **Mod auth abuse** — magic-link + daily caps + audit log. Even with a leaked operator account, blast radius is bounded. | ||
| - **Customer identity drift** — both services must keep treating `metadata.wallet_address` as the customer key. Extracting `lit-billing-core` later eliminates this risk. |
There was a problem hiding this comment.
This is self induced by splitting the code. Let's not split it - if we need a new project, then lets just bite the bullet and split it. Probably just need to keep the "out-of-band" caching stuff in the lit-api-server.
- Drop subscription billing entirely from the plan. - Extract lit-billing-core as a shared crate now (vs deferred). - Minimize Postgres schema; drop audit_log, subscriptions, invoice_credits, litkey_unattributed_payments, litkey_rate_history. - Drop direct-Transfer fallback; gateway contract is the only supported path. - Drop HMAC-signed payment URLs; rely on prominent account-confirmation UI. - Simplify gateway event to use plain indexed address. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rely on server logs (Railway) instead of a Slack webhook. Rate-fetch failures, stale rate, and unmatched gateway payments now just log and let the protective behavior (pause crediting / skip) carry the load. Users will surface stuck payments via support. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Railway's reliability has degraded recently. Updated the plan to target Fly.io: app + Fly Postgres (or external via Supabase/Neon), fly.toml at the repo root so the Dockerfile keeps repo-root build context for the lit-billing-core path dep, fly secrets / fly certs / fly logs for the operational surface. Decisions table #2 and #5, deployment section, and the phase-2 sequencing bullet all updated. No design changes — same architecture, different platform. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
plans/lit-payments-app.md: design doc for a separate ops-facing billing app (Discord-mod credit portal, LITKEY→Stripe credit via a Base payment gateway contract, deferred subscription billing).Test plan