From 9e772fdd4c2198cfec8a097c5c85c21056725e44 Mon Sep 17 00:00:00 2001 From: Grant Date: Mon, 11 May 2026 20:04:05 -0500 Subject: [PATCH] README: add developer Quick-start; refresh stale sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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. --- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index cdae82b..f7cc55f 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,37 @@

Keysat

- 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.

+

+ keysat.xyz · + docs.keysat.xyz · + Releases +

+ +--- + +## 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 & 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 > StartOS — there is no upstream project to differ from. The canonical > 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 buyer-facing receipts). 5. Create one or more **products** — each represents something you sell. -6. Create at least one **policy** per product. The policy slugged - `default` is consumed by the standard public purchase flow; other - slugs are used for manual issuance. Policies define duration, grace - period, seat cap, entitlements, trial flag, and price overrides. +6. Create at least one **policy** per product. Multi-tier ladders + (Basic / Pro / Max) are first-class: when a product has two or more + public policies, the buy page renders a tier picker and the buyer + 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 `Create discount code` action). 8. Share the public service URL with buyers. @@ -146,7 +176,7 @@ Grouped as displayed in the dashboard. **Licenses** - *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. - *Unsuspend license*. - *Revoke license* — terminal kill. @@ -192,15 +222,13 @@ the container automatically. ## 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. -- **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 license tier upgrade in place.** A buyer who got Standard cannot be upgraded to Pro on the existing key — they need a new key. -- **No bulk / volume licensing.** "Buy 10 keys at once with discount" is not built in. -- **No in-dashboard list views.** Operators query large datasets via the admin API key rather than a paginated UI. -- **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. +- **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 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. +- **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. +- **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. +- **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. ## What Is Unchanged from Upstream @@ -267,7 +295,7 @@ firstRun: severity: critical runs: configureBtcpay features: - paymentRail: btcpay-server + paymentRail: btcpay-server # zaprite planned for v0.3 (card payments) signing: ed25519 offlineVerification: true multiSeat: true @@ -275,8 +303,24 @@ features: expiry: true gracePeriod: 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 + webhookDlq: true # failed deliveries retryable from admin UI 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" ```