Reconcile docs with shipped features: subscriptions, merchant profiles, no email
payments.md: flag the smtp_* columns dormant and the companion email plan superseded. HOW_IT_WORKS.md predated recurring subscriptions and merchant profiles -- correct 'not a subscription service' (subscriptions ship on paid tiers), the single-tenant / one-box-one-business framing (merchant profiles let one instance host multiple businesses), and the 'short of an email' aside (Keysat never emails keys).
This commit is contained in:
+4
-4
@@ -4,7 +4,7 @@ This is a plain-English walkthrough of what Keysat actually does, written for pe
|
|||||||
|
|
||||||
## The cast
|
## The cast
|
||||||
|
|
||||||
Alice runs her software on her own Start9 server at home. She has two services there: her **BTCPay Server** (a self-hosted Bitcoin payment processor), and a new one she just installed called **licensing-service** — the thing this whole project is about. Her licensing-service is single-tenant: it sells *her* software only, not anyone else's. If a fellow developer wants the same functionality, they install their own copy on their own Start9, just like Alice did.
|
Alice runs her software on her own Start9 server at home. She has two services there: her **BTCPay Server** (a self-hosted Bitcoin payment processor), and a new one she just installed called **licensing-service** — the thing this whole project is about. Alice runs her own copy: Keysat is not a shared SaaS, so a fellow developer who wants the same functionality installs their own on their own Start9, just like Alice did. Within her own instance, though, Alice isn't limited to a single business — on the paid tiers she can sell for several distinct brands side by side (more in *What this setup is not*, below).
|
||||||
|
|
||||||
Bob is a customer. He may or may not own a Start9. Whether he does affects the experience, not the mechanics — we'll get to that.
|
Bob is a customer. He may or may not own a Start9. Whether he does affects the experience, not the mechanics — we'll get to that.
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ Nothing was copied or pasted. Bob never saw the license string. The key got capt
|
|||||||
|
|
||||||
### Bob is on a regular computer, and Alice's software is not a Start9 package
|
### Bob is on a regular computer, and Alice's software is not a Start9 package
|
||||||
|
|
||||||
This is the more common case for today's world. Bob goes to Alice's website, clicks "Buy," and is taken to a BTCPay checkout. He pays. BTCPay shows a success page that includes the license string — at that point it's the only way he could get it, short of an email. Bob copies the string and pastes it into Alice's app's settings dialog. Alice's app (which has embedded her public key at build time) verifies the signature and unlocks. From then on, no network is required.
|
This is the more common case for today's world. Bob goes to Alice's website, clicks "Buy," and is taken to a BTCPay checkout. He pays. BTCPay shows a success page that includes the license string — that page is how Bob gets his key (Keysat itself never emails it; if he loses it, Alice can look it up and reissue, covered below). Bob copies the string and pastes it into Alice's app's settings dialog. Alice's app (which has embedded her public key at build time) verifies the signature and unlocks. From then on, no network is required.
|
||||||
|
|
||||||
### Bob never paid — Alice gave him a comp
|
### Bob never paid — Alice gave him a comp
|
||||||
|
|
||||||
@@ -86,11 +86,11 @@ Webhook deliveries are also not the only signal. A background task inside licens
|
|||||||
|
|
||||||
## What this setup is *not*
|
## What this setup is *not*
|
||||||
|
|
||||||
Not a subscription service. A license here is perpetual — one payment, one key, forever. If Alice wants subscriptions she would need to add expiry to the payload and a renewal flow; the payload format has a `flags` byte and a future version bump to support that, but it is not in scope for the current version.
|
Not subscription-*only*. The default license is perpetual — one payment, one key, forever — and that's the simplest thing Alice can sell. But Keysat also supports recurring **subscriptions** on the paid tiers: a time-boxed license whose payload carries an expiry, plus a background renewal worker that re-bills the buyer and re-issues the key each cycle (auto-charging a saved payment method where one exists, falling back to a manual-pay link otherwise). Perpetual and subscription products coexist on one instance.
|
||||||
|
|
||||||
Not a DRM system. It does not prevent someone with a debugger from patching out the license check. Nothing running on the user's machine can, by construction — the user controls their CPU. This is a licensing system for reasonable people who want to pay.
|
Not a DRM system. It does not prevent someone with a debugger from patching out the license check. Nothing running on the user's machine can, by construction — the user controls their CPU. This is a licensing system for reasonable people who want to pay.
|
||||||
|
|
||||||
Not multi-tenant. Each Alice runs her own licensing-service. Two Alices cannot share one server to sell two different products. That simplification is deliberate — it keeps the data model small, makes disaster recovery obvious ("back up one SQLite file"), and keeps Alice in control of the signing key. If someone wants a SaaS version that hosts many sellers, that's a different product.
|
Not a multi-seller SaaS. Each Alice runs her own licensing-service; two independent sellers don't share one box. That keeps disaster recovery obvious ("back up one SQLite file") and keeps Alice in sole control of her signing key. What *did* change: one instance is no longer limited to one business. On the paid tiers Alice can define multiple **merchant profiles** — separate brands, each with its own payment accounts, checkout branding, and products — and run them all from the one server. So "one operator, one box" still holds; "one box, one business" no longer does.
|
||||||
|
|
||||||
## The bet
|
## The bet
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,10 @@ paths:
|
|||||||
|
|
||||||
# Payments & the multi-provider / merchant-profile model
|
# Payments & the multi-provider / merchant-profile model
|
||||||
|
|
||||||
Full design spec: `plans/multi-provider-payment-model.md`. Companion email plan:
|
Full design spec: `plans/multi-provider-payment-model.md`. The companion email
|
||||||
`plans/keysat-smtp-emails.md`.
|
plan `plans/keysat-smtp-emails.md` is **superseded** — Keysat does not send email;
|
||||||
|
operators receive events via webhooks and run their own email pipelines (see the
|
||||||
|
"Operability & alerts" item in `ROADMAP.md`).
|
||||||
|
|
||||||
## Model
|
## Model
|
||||||
|
|
||||||
@@ -32,7 +34,8 @@ merchant_profiles (1) ──< (N) payment_providers
|
|||||||
```
|
```
|
||||||
|
|
||||||
- **merchant_profiles** — business identity: name, branding, post-purchase
|
- **merchant_profiles** — business identity: name, branding, post-purchase
|
||||||
redirect, optional per-profile SMTP override fields. Exactly one `is_default`,
|
redirect. (The `smtp_*` columns from migration 0020 are **dormant** — never read
|
||||||
|
by any send path; the email plan was dropped.) Exactly one `is_default`,
|
||||||
auto-created at first boot from the operator-name setting.
|
auto-created at first boot from the operator-name setting.
|
||||||
- **payment_providers** — one row per configured BTCPay/Zaprite account, attached
|
- **payment_providers** — one row per configured BTCPay/Zaprite account, attached
|
||||||
to a profile (`kind` ∈ `btcpay`|`zaprite`).
|
to a profile (`kind` ∈ `btcpay`|`zaprite`).
|
||||||
|
|||||||
Reference in New Issue
Block a user