docs(commercial): one price — $79 Steam DLC rising to $99, subscription retired

Creator ruling 2026-11-01. One SKU, one price, Steam does the selling.

- Pro is a one-time Steam DLC on the free app: $79 introductory, $99 on a stated date, announced
  where the price is shown and actually raised.
- The subscription is retired. The reasoning is in decisions.md: no service behind a monthly fee
  (no servers, no cloud, no content), ~1-3 subscribers per 1,000 installs against 5-8% churn, and
  it carried the most expensive code in the product.
- Polar goes dormant. Its customer-portal design is recorded, not built. The "freemium on Steam,
  convert on Polar, Valve gets nothing" proposal is rejected: in-app purchases must use the Steam
  Wallet, so it risks the listing to save ~$24 a sale.
- Entitlement collapses to `steamDlcOwned`. No lease, no key, no portal, no device limit; the
  greyed tier opens the Steam store overlay, so every purchase stays inside Valve's own surface.
- The site publishes the model and links the store page. It takes no payment and hosts no binaries.
- The $400 lifetime died with the subscription it anchored. Founding 200 died with the coupons and
  passes it needed.

Costs: $115 fixed year one; $79 nets $55.30 after Steam, so three sales cover the year.
This commit is contained in:
2026-11-01 15:40:44 -08:00
parent 1c2eedcaba
commit 5d836aecbb
3 changed files with 76 additions and 86 deletions
+47 -83
View File
@@ -6,15 +6,19 @@ storefront, support or promo work. Cause of death for every retired path:
[`decisions.md`](decisions.md). Release mechanics (build, depot, SteamPipe upload):
[`Distribution.md`](../../Distribution.md).
## Model
## Model — one purchase, one price
- **Free tier — every feature, every scene, every overlay**, free forever, no account, no
watermark, nothing nagged inside the output. It is not a trial.
- **Pro — $10/month or $400 lifetime.** No annual tier.
- **Pro is a one-time Steam purchase: a DLC on the free app.**
**$79 introductory → $99** on a stated date before launch. No subscription, no lifetime SKU, no
third-party checkout.
- **The only delta is output quality.** Features are never gated; a payment buys pixels.
- **No watermark, ever**, in either edition. The branding flash is retired as a paid delta and
stays off (`ShowBrandFlash`, default `false`).
- **Clean numbers, no `.99`**, no discount codes, no countdowns, no fake scarcity.
- **Clean numbers, no `.99`**, no discount codes, no countdowns. **The one dated exception** is the
introductory price: it is announced in advance, shown where the price is shown, and actually
raised on the date — otherwise the next announcement is worthless.
- **The site publishes the model, never the numbers** — "free forever, every feature unlocked, a
paid edition with higher output quality at launch". Price, tier name, cap and frame rate are
published by the **app**, at the point of sale, not by the page.
@@ -49,64 +53,30 @@ The cap is a pixel budget plus a frame rate, not the word "720p":
(cancel, revoke, sign-out, channel switch) greys them again on the next refresh.
- **Bitrate follows the profile** — a capped user is not offered a 1080p bitrate.
## Entitlement — two sources, one profile
## Entitlement — one source
**Pro is `steamDlcOwned || polarKeyValid`.** Both resolve to the same `OutputProfile`; neither
touches a feature. Fail closed: anything unresolved is the free tier.
**Pro is `steamDlcOwned`, and nothing else.** It resolves to the `OutputProfile`; it never touches a
feature. Fail closed: anything unresolved is the free tier.
### Steam (lifetime)
- **Steam owns the lifetime SKU.** `BIsDlcInstalled(dlcAppId)` after `SteamAPI.Init`, behind
- **Steam owns the SKU.** `BIsDlcInstalled(dlcAppId)` after `SteamAPI.Init`, behind
`IEntitlement` (`Services/Entitlement/`). It is a local check against Steam's own state — no
server, no key, no lease.
- **Fail closed, four ways:** no DLC app id configured, `SteamAPI.Init()` false (no client),
a thrown native load (missing `steam_api64.dll`), and "not owned" all resolve to the free tier.
server, no key, no lease, no account, no email.
- **Fail closed, four ways:** no DLC app id configured, `SteamAPI.Init()` false (no client), a
thrown native load (missing `steam_api64.dll`), and "not owned" all resolve to the free tier.
None of them may crash the app or grant Pro.
- **Steam down or not running** → free profile, with a line explaining why, never a refusal to
start. A Steam build launched outside Steam is the common case for people who pin shortcuts.
- **No licence key exists for the Steam SKU**, so nothing to paste, email or lose. A refunded DLC
simply stops reporting ownership on the next start.
- **No licence key exists**, so nothing to paste, email, lose or reclaim. A refunded DLC simply
stops reporting ownership on the next start.
- **The upgrade path is the Steam store overlay** (`ActivateGameOverlayToStore`) from the greyed
tier menu — Valve's own surface, so the purchase stays inside the Steam Wallet rules. Never a
checkout of ours, never an external payment page.
- **No leases, no dunning, no portal, no device limits.** A one-time purchase has one state:
owned or not.
### Polar (monthly, sold off-Steam)
**Polar is the merchant of record and the only source of truth** for the monthly plan. It takes the
money, remits VAT/GST, handles refunds and chargebacks, and holds the keys. **There is no server of
ours in the loop** — no claim page, no callback endpoint, no key database.
- **Key** — `LCYT-` prefix; org `c05fb364-…` and the endpoints are in `CREDENTIALS.md`. No
product is created yet.
- **The client talks to Polar directly.** The customer-portal endpoints authenticate on the **key
itself** plus the `organization_id` (a public identifier). The **org access token must never
ship in the app** — it is only needed to create products, not to activate them.
- **Bound to the buyer's YouTube channel ID** (`UC…` from `channels.list?mine=true` — the
signed-in channel, never the `@handle`) through Polar's **`conditions`**, not through a browser
flow: `activate` is called with `conditions: { "channel_id": "UC…" }`, and every later `validate`
passes the same object. Polar compares them server-side, so the binding is enforced without us
hosting anything.
- **Two activations**, any machine, one channel (`limit_activations: 2` on the benefit). A second
channel is a second key. Two keys for one channel is never sold — it doubles the support surface
and invites "give one to a friend".
- **Runtime rule:** Pro requires `licence.channelId == connected.channelId`. Equal → Pro.
Anything else → free tier, working normally, with *"This licence belongs to another channel"*
and a link to the Polar customer portal. Never an error wall, never a blocked stream.
- **Lease, not a permanent cache:** validate on launch and daily; **7–14 days offline grace**;
no network past grace = free tier until Polar answers. Never lock a paying user out on a DNS
failure.
- **Device management is Polar's** — the customer portal already lists and deactivates
activations, so we build no UI for it. A subscription key is **auto-revoked when the
subscription ends**, which is what makes a lapse a real state on the monthly SKU.
- **Four states, and nothing else:** valid → Pro · expired/revoked → free with a banner ·
activation limit reached → "manage devices" portal link · mismatch or offline → free, explained.
- **CLI activation** — `--activate LCYT-…` so silent and fleet installs never meet a dialog.
Interactive entry in Settings is the secondary path.
- **Notice cadence** — 7 days out, 1 day out, and on the day, inline in the go-live panel with a
date and a portal link. Recording gets the banner only. Never modal, never blocking a Start,
never orange (orange is the dev-only label colour).
⛔ **`conditions` is agreement, not cryptography.** A patched client can send someone else's
channel ID. That is accepted: the free tier is the defence, the licence is a lease, and a
determined crack buys little. Do not propose a signed token, a hardware fingerprint or a server
to "fix" it.
⛔ **Subscriptions and third-party checkout are retired for launch** — see
[`decisions.md`](decisions.md). Polar stays dormant; its design is recorded there so it is not
re-derived.
## Channels — Steam only
@@ -114,13 +84,12 @@ to "fix" it.
no other vector: no direct download, no winget, no Scoop/Chocolatey, no Microsoft Store. The store
page is the single authoritative source for the download, the stats and the reviews.
- **Lifetime Pro = Steam DLC.** Bought on the **store page**; the app only reads ownership
(`ISteamApps::BIsDlcInstalled` / `UserHasLicenseForApp`). No purchase flow in the app, no Steam
Wallet code, nothing to reconcile.
- **The $10/month plan is sold outside Steam** and is **never purchasable inside a Steam build**.
Steamworks requires in-app purchases to go through the Steam Wallet — so the app *states* that
monthly plans exist on the site and does not sell them. If the app ever grows a checkout for it,
that is the policy violation.
- **Pro = Steam DLC, one-time.** Bought on the **store page**; the app only reads ownership
(`ISteamApps::BIsDlcInstalled`). No purchase flow, no Wallet code, nothing to reconcile.
- **The website sends people to Steam.** It publishes the model and links the store page; it takes
no payment, collects no email, and hosts no binaries. One shop, one price, one receipt.
- **No in-app checkout of ours, ever.** Steamworks requires in-app purchases to use the Steam
Wallet, so the only purchase surface is Steam's own store overlay.
- **Boot shape:** the app ships `steam_api64.dll` beside the exe and calls `SteamAPI.Init`. That
is a functional dependency, not the rejected "native helper DLL for IP protection" — Steam
ownership cannot be checked without it. Launched without Steam running, the app must fall back to
@@ -130,8 +99,7 @@ page is the single authoritative source for the download, the stats and the revi
- **Portable mode is no longer a distributable.** `portable.txt` remains as a feature for anyone who
copies the installed folder; it is not a delivery mechanism.
- **Steam Direct** is **$100 per app**, recoupable after $1,000 adjusted gross revenue.
- **Price parity:** if the lifetime is ever sold off-Steam, it may not be cheaper than the Steam
price.
- **Price parity is trivially satisfied** — there is no off-Steam price to keep in step.
**Not channels, ever:** direct download, winget/Chocolatey/Scoop, the Microsoft Store, Patreon or
any subscription platform of our own, paywalled early access, a paid beta, a Discord. Content is
@@ -170,21 +138,16 @@ repo for bugs that survive the friction of needing an account.
- **Nobody is locked out over a licence.** A billing hiccup drops the app to the free profile with
a banner and a portal link — never a blocked stream, never a modal.
## Founding 200 promo
## The introductory price — the only promotion
Cash cost **$0**; it is priced in support time and forgone list revenue.
Cash cost **$0**. With one SKU there is no coupon, no founder tier, no pass and no reminder cadence.
- **90 days free** — a 100%-off Polar coupon, `duration = repeating, months = 3`.
- **Founder price lock** — their $10/month stays $10 permanently.
- **Credits + in-app Founder badge** (opt-in channel name on the site).
- **30-day passes** — unique keys carrying the issuer's channel, issued **one per 30 active days,
max 3 held**, activation limit 1–2, expiring 30 days **after activation**. Earned, never handed
out: a pass nobody uses teaches nothing.
- Optional **$250 lifetime** window in the first 90 days — converting a founder beats three
months of free.
- Reminders at day 75 and 85; the renewal cliff is where founders churn.
- Terms, one paragraph: one per person, passes expire 30 days after activation, no cash value,
revoked for resale or abuse, price lock void if the subscription lapses.
- **$79 until a stated date, then $99.** The date is announced at launch on the store page, the
site and the in-app upgrade panel, and it is honoured — an introductory price that never rises
makes the next announcement worthless.
- **No launch discount stacked on top.** Two overlapping stories ("introductory" plus "15% off")
muddy both, and the increase afterwards triggers Steam's 30-day discount cooldown.
- **No coupons, no keys, no founder badges.** A one-time Steam purchase has nothing to administer.
## Costs
@@ -193,14 +156,14 @@ Cash cost **$0**; it is priced in support time and forgone list revenue.
| Domain | ~$15/yr |
| Droplet | $0 — serves the existing site |
| Steam Direct | **$100 once**, recoupable after $1,000 AGR |
| Steam revenue share | 30% on the lifetime DLC → $400 nets **$280** |
| Polar | 5% + 50¢ per sale → $10 nets $9.00 (monthly only) |
| Steam revenue share | 30% → **$79 nets $55.30**, **$99 nets $69.30** |
| Polar | **$0 — dormant.** No subscription at launch |
| Steamworks, public issue repo, Gitea | $0 |
| Azure Artifact Signing — **not needed** | Steam installs don't meet SmartScreen |
| Microsoft Store — **not used** | — |
Fixed year one ≈ **$115** (domain + Steam Direct, one time). The Steam cut is the price of not
paying for a certificate, a storefront or an update path.
Fixed year one ≈ **$115** (domain + Steam Direct, one time). At $79, **three sales cover the year**.
The Steam cut is the price of not running a storefront, a certificate or an update path.
**Signing is now moot as a launch cost.** Steam installs never meet SmartScreen, so the certificate
that existed only to soften that wall has no job. Artifact Signing stays on the shelf for the day a
@@ -218,9 +181,10 @@ pointless and a leak that is traceable — not an unbreakable binary.
machine that never runs Steam.
- **The distribution is not a handout.** Steam deliveries go through Valve's client and account, so
there is no public zip for a mirror site to repackage, and no hash pin for us to maintain.
- **Short leases** — a revoked or refunded Polar key dies inside the grace window; a refunded Steam
DLC stops reporting ownership the next time Steam is asked.
- **Licence ID in About** — a leaked build traces back to a purchase.
- **Steam is the licence state** — a refunded DLC stops reporting ownership the next time Steam is
asked, and the app drops to the free profile on the next start. Nothing to revoke by hand.
- **The Steam purchase is in About** — a leaked build traces back to a Steam account, which Valve
can action; we hold nothing to trace.
⛔ **Rejected, do not re-propose:** a native helper DLL for "IP protection", obfuscation, hardware
locking, remote code that downloads and executes, and gating asset downloads as an auth check.
+26
View File
@@ -5,6 +5,32 @@ you are about to re-open one of them. **Live commercial rules (prices, entitleme
signing, support, promo) are in [`commercial.md`](commercial.md)**; the other live rules live in
the subsystem files. This is the graveyard with cause of death.
## The business model — one price, settled 2026-11-01
**$79 one-time, raising to $99 on a stated date. Sold only on Steam, as a DLC on the free app.**
The website publishes the model and links the store page; it never takes payment.
**What died the same day:**
- **The subscription.** $10/month for pixels, with no service behind it — no servers, no cloud, no
content library, updates free through Steam. Estimated 1–3 subscribers per 1,000 installs, at
5–8% monthly churn, against the most expensive code in the product (leases, activations,
revocation, portal, dunning). Retired for launch.
- **Polar as a live rail.** Dormant. Its customer-portal design (`conditions` binding, two
activations, 7–14 day lease) is preserved here only so it is not re-derived if a cheaper entry
tier is ever justified by real support traffic.
- **The $400 lifetime** — it was an anchor for a subscription that no longer exists, and above what
a beginner pays for a tool with a free incumbent.
- **Founding 200** — coupons, price locks, earned 30-day passes, founder badges: all machinery for
a recurring plan.
- **Off-Steam conversion of any kind.** The "freemium on Steam, convert on Polar, Valve gets
nothing" proposal was rejected: Steamworks requires in-app purchases to use the Steam Wallet, so
it is a listing-level risk to save ~$24 a sale.
**Kept:** the free tier is the whole app at a 720p30 output profile, the paid delta is output
quality only, and the app never sells anything itself — the greyed tier opens the Steam store
overlay.
## Commercial mechanics — died 2026-10-31 (same week they were written)
- **The licence "claim page" is dead.** The binding was going to be an OAuth web page that wrote