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:
+47
-83
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user