feat(entitlement): pivot to paid app ownership

Check Steam ownership of the paid app with BIsSubscribedApp; keep Debug fake ownership out of Release. Ref: https://partner.steamgames.com/doc/api/ISteamApps#BIsSubscribedApp
This commit is contained in:
2026-11-02 09:18:03 -08:00
parent 54902cb838
commit ff5e8d94ae
17 changed files with 229 additions and 217 deletions
+21 -12
View File
@@ -209,11 +209,11 @@ After: 127 MB exe, `ffmpeg\` present, depot ≈ 257 MB total.
`scripts/publish.sh` fails loudly when `ffmpeg\`, `LICENSE`, `PRIVACY.md` or
`THIRD-PARTY-NOTICES.txt` are missing, and when test assemblies leak in.
### STEAM IS THE DISTRIBUTOR — AND WHAT IT DOES NOT ALLOW (2026-10-31)
### STEAM DISTRIBUTION, COMMERCIAL USE, AND THE DEMO OWNERSHIP CHECK (2026-11-02)
**Why recorded:** the distribution answer changed three times in one day (winget → zip+GitHub →
Steam), and each pivot invalidated a doc written hours earlier. These are the facts that won't
change.
**Why recorded:** the Steam Subscriber Agreement's private-use wording was misread as a blocker
for monetized streaming. Check the exception and the established Steam software precedent before
raising it again.
- **Steam installs skip SmartScreen entirely** — Valve's client delivers the files, so there is no
browser download, no Mark-of-the-Web and no publisher warning. An unsigned exe is *fine* in this
@@ -221,16 +221,25 @@ change.
- **Steam updates the app** — no self-updater, no version banner, no update endpoint.
- **⛔ In-app purchases must use the Steam Wallet.** Steamworks, *Microtransactions (In-Game
Purchases)*: *"For any in-game purchases, you'll need to use the microtransaction API so Steam
customers can only make purchases from the Steam Wallet."* So a subscription sold through Polar
inside a Steam build is a policy violation. **Lifetime = plain DLC bought on the store page**
(the app only calls `BIsDlcInstalled`); the monthly is *stated*, never *sold*, in-app.
- **Steam can technically do recurring billing** (`ISteamMicroTxn` + `ProcessAgreement`) but its own
doc opens with *"Recurring Subscriptions is not a fully supported feature"* and requires a server
of yours to poll renewals — more infrastructure than Polar, for a 30% cut.
customers can only make purchases from the Steam Wallet."* LlamaCasty has no in-app checkout.
- **The private-use wording is not, by itself, a commercial-use ban for LlamaCasty.** The Steam
Subscriber Agreement §2.A permits commercial use when the applicable product terms expressly
allow it; §5 has general private/personal-use wording for third-party software. OBS Studio is
distributed on Steam as video-production software under GPL, and OBS confirms the Steam build is
the same as its website build. GPL permits commercial use. LlamaCasty's EULA should expressly
allow commercial and monetized streaming; confirm the wording with Valve or counsel. Do not call
this a Steam blocker based only on §5.
Sources: https://store.steampowered.com/subscriber_agreement/ ·
https://obsproject.com/kb/steam-faq · https://www.gnu.org/licenses/gpl-faq.html
- **Demo ownership check:** the free Demo uses its own App ID; `ISteamApps::BIsSubscribedApp`
checks ownership of the paid app. The paid App ID must be configured; zero/missing ID fails closed.
Valve reference: https://partner.steamgames.com/doc/api/ISteamApps#BIsSubscribedApp
- **Steam sells one paid app and distributes its associated free Demo.** Same code; no GitHub
binary. The demo links to the paid store page and can send a one-time wishlist notification.
- **Renaming a live exe is painful** (Steamworks → *Tip – Renaming a live exe*). Do the
`LlamaCasty.exe` rename **before** the first depot upload, not after.
- **The Steam store page must be public two weeks before release**, and the $100 Steam Direct fee
must be paid before the page can be configured at all.
- **The paid app's Steam store page must be public two weeks before release.** The Steamworks
application and $100 fee are already submitted; Valve's decision is pending.
### CONVERTING A MEDIAPIPE .tflite (WITH CUSTOM OPS) TO ONNX — AND PROVING IT (RECIPE, TASK 51)