README: add developer Quick-start; refresh stale sections

- New "Quick start" block at top — pitch line matches the keysat.xyz
  hero, links to docs.keysat.xyz, and lists the four SDK install
  commands (TS / Rust / Python / Go) so a GitHub visitor sees the
  install path before the StartOS-package internals.
- Tagline updated to drop "Bitcoin-native" in favor of "payment
  channels you control" (matches the landing-page de-emphasis).
- First-run flow step 6: drop the "default slug is canonical" myth.
  Multi-tier ladders are first-class.
- Actions list: drop npub from license search (UI surfaces only
  email + invoice id; backend supports npub but the purchase flow
  hasn't shipped buyer npub capture yet).
- Limitations section: drop "no recurring subscriptions" and "no
  tier upgrades" — both shipped in v0.2. Add Zaprite-pending caveat.
- YAML quick-reference: expand the features block to reflect the
  current daemon (multi-currency, marketing bullets, hidden
  entitlements, featured discounts, multi-policy scope, recurring
  subs, tier upgrades, webhook DLQ, scoped API keys, OpenAPI spec,
  Creator/Pro/Patron self-licensing tiers). Add SDK list.
This commit is contained in:
Grant
2026-05-11 20:04:05 -05:00
parent aaf8bddfe4
commit 9e772fdd4c
+61 -17
View File
@@ -5,9 +5,37 @@
<h1 align="center">Keysat</h1> <h1 align="center">Keysat</h1>
<p align="center"> <p align="center">
Bitcoin-native self-hosted licensing service for software creators. Runs on Start9. Self-hosted licensing server. Sell software on payment channels you control,
verify licenses offline, keep the keys + customer list on your hardware. Runs on Start9.
</p> </p>
<p align="center">
<a href="https://keysat.xyz">keysat.xyz</a> &middot;
<a href="https://docs.keysat.xyz">docs.keysat.xyz</a> &middot;
<a href="https://github.com/keysat-xyz/keysat/releases">Releases</a>
</p>
---
## Quick start
**Operator (install Keysat on your Start9):** add `registry.keysat.xyz` to your StartOS marketplace and install. Sideload the `.s9pk` from [GitHub releases](https://github.com/keysat-xyz/keysat/releases/latest) if you prefer. See [Install &amp; setup](https://docs.keysat.xyz/install.html) for the full walkthrough.
**Developer (verify a license in your software):** four official SDKs ship today, all wire-compatible against the same cross-check fixtures in [`licensing-service/tests/crosscheck/`](licensing-service/tests/crosscheck/).
| Language | Install |
|---|---|
| TypeScript | `npm install @keysat/licensing-client` |
| Rust | `cargo add keysat-licensing-client` |
| Python | `pip install keysat-licensing-client` |
| Go | `go get github.com/keysat-xyz/keysat-client-go` |
See [Integrate the SDK](https://docs.keysat.xyz/integrate.html) for the five-line verifier pattern.
**Operator agent / automation:** the daemon exposes an OpenAPI 3.1 spec, scoped API keys with role-based access, and outbound webhooks. See [Agent integration](https://docs.keysat.xyz/agent.html).
---
> **About this README.** Keysat is a from-scratch service authored for > **About this README.** Keysat is a from-scratch service authored for
> StartOS — there is no upstream project to differ from. The canonical > StartOS — there is no upstream project to differ from. The canonical
> implementation is this package and the Rust daemon it wraps > implementation is this package and the Rust daemon it wraps
@@ -87,10 +115,12 @@ mandatory.
4. Set your **operator name** (shown on the public homepage and in 4. Set your **operator name** (shown on the public homepage and in
buyer-facing receipts). buyer-facing receipts).
5. Create one or more **products** — each represents something you sell. 5. Create one or more **products** — each represents something you sell.
6. Create at least one **policy** per product. The policy slugged 6. Create at least one **policy** per product. Multi-tier ladders
`default` is consumed by the standard public purchase flow; other (Basic / Pro / Max) are first-class: when a product has two or more
slugs are used for manual issuance. Policies define duration, grace public policies, the buy page renders a tier picker and the buyer
period, seat cap, entitlements, trial flag, and price overrides. chooses before paying. Policies define duration, grace period, seat
cap, entitlements, recurring cadence, trial flag, price overrides,
marketing bullets, and per-entitlement hide-on-buy-page toggles.
7. Optionally create **discount / referral / free-license codes** (see 7. Optionally create **discount / referral / free-license codes** (see
`Create discount code` action). `Create discount code` action).
8. Share the public service URL with buyers. 8. Share the public service URL with buyers.
@@ -146,7 +176,7 @@ Grouped as displayed in the dashboard.
**Licenses** **Licenses**
- *Issue license manually* — comp / press / grandfathered keys. - *Issue license manually* — comp / press / grandfathered keys.
- *Search licenses* — by email, Nostr npub, or BTCPay invoice id. - *Search licenses* — by email or BTCPay invoice id.
- *Suspend license* — reversible lockout. - *Suspend license* — reversible lockout.
- *Unsuspend license*. - *Unsuspend license*.
- *Revoke license* — terminal kill. - *Revoke license* — terminal kill.
@@ -192,15 +222,13 @@ the container automatically.
## Limitations and Differences ## Limitations and Differences
Known v0.1 limitations: Known current limitations:
- **No buyer self-service portal.** Buyers cannot log in to view their licenses, transfer to a new machine, or recover a lost key without contacting the operator. Use *Search licenses* to recover. - **Buyer self-service recovery is by-design minimal.** Buyers can re-derive a lost license at `/recover` using (invoice id, buyer email). They cannot transfer between machines without contacting the operator (use *Free a machine seat* in the admin / agent API).
- **No recurring subscriptions.** Time-limited licenses expire and require a manual repurchase. BTCPay supports recurring billing but Keysat does not yet model auto-renewal. - **No bulk / volume licensing UI.** "Buy 10 keys at once with discount" is not built into the buy page. Operators can issue N comp licenses via the admin API in a loop.
- **No license tier upgrade in place.** A buyer who got Standard cannot be upgraded to Pro on the existing key — they need a new key. - **Webhook delivery retries are bounded.** A subscriber down past the 10-attempt retry window lands in the dead-letter queue (visible in admin UI → Webhooks → Failed). BTCPay invoice reconciliation runs as a background poll so dropped *payment* webhooks are recovered.
- **No bulk / volume licensing.** "Buy 10 keys at once with discount" is not built in. - **Hardware fingerprinting is client-supplied.** Keysat does not derive fingerprints itself; the buyer-side SDK passes whatever the integrator chose. The fingerprint is bound on first activate and enforced thereafter.
- **No in-dashboard list views.** Operators query large datasets via the admin API key rather than a paginated UI. - **Card payments not shipped.** The Zaprite payment provider is in design for v0.3 — operators on Pro / Patron will get a card-payment option alongside BTCPay. Until then, payments are BTC / Lightning only.
- **Webhook delivery retries are bounded.** A subscriber down past the retry window will miss events. BTCPay invoice reconciliation runs as a background poll so dropped *payment* webhooks are recovered.
- **Hardware fingerprinting is client-supplied.** Keysat does not derive fingerprints itself; the buyer-side SDK passes whatever the integrator chose.
## What Is Unchanged from Upstream ## What Is Unchanged from Upstream
@@ -267,7 +295,7 @@ firstRun:
severity: critical severity: critical
runs: configureBtcpay runs: configureBtcpay
features: features:
paymentRail: btcpay-server paymentRail: btcpay-server # zaprite planned for v0.3 (card payments)
signing: ed25519 signing: ed25519
offlineVerification: true offlineVerification: true
multiSeat: true multiSeat: true
@@ -275,8 +303,24 @@ features:
expiry: true expiry: true
gracePeriod: true gracePeriod: true
entitlements: true entitlements: true
discountCodes: [percent, fixed_sats, free_license] entitlementsCatalog: per-product # typed slugs with display names + descriptions
hiddenEntitlements: per-policy # license-granted but hidden from buy page
marketingBullets: per-policy # operator-authored ✓ items on tier cards
multiCurrency: [SAT, USD, EUR] # auto-converted at invoice creation
discountCodes: [percent, fixed_sats, set_price, free_license]
featuredDiscounts: true # launch-special, auto-applies on the buy page
multiPolicyDiscountScope: true # one code can apply to N policies
recurringSubscriptions: true # auto-renew with trials + grace
tierUpgrades: true # in-place tier upgrade with proration
outboundWebhooks: true outboundWebhooks: true
webhookDlq: true # failed deliveries retryable from admin UI
auditLog: true auditLog: true
selfLicensingTier: stub-v0.1 scopedApiKeys: [read-only, license-issuer, support, full-admin]
openapiSpec: /v1/openapi.json
selfLicensingTier: [Creator, Pro, Patron]
sdks:
- typescript: "@keysat/licensing-client (npm)"
- rust: "keysat-licensing-client (crates.io)"
- python: "keysat-licensing-client (PyPI)"
- go: "github.com/keysat-xyz/keysat-client-go"
``` ```