Files
LlamaCasty/Distribution.md
T
gramps 7827d239e2 docs(commercial): one source of truth for the money — prices, entitlement, channels
The commercial plan was spread over five documents written in five different weeks,
and they contradicted each other: product.md sold the Store, decisions.md called the
Store dead then re-opened, Distribution.md (736 lines) still described Polar as a
download host, MARCOM.md quoted "no subscription" next to a paid tier, and README.md
promised "free forever". An outsider could not tell what ships.

docs/ai/commercial.md is now the only place money is decided: free = whole app at a
921,600 px / 30 fps output profile covering the recording as well as the stream; Pro =
$10/mo or $400 lifetime through Polar, key bound to the buyer's YouTube channel ID via
a claim page, 2 activations, 7–14 day lease with offline grace, fail closed, never
downgrade a running stream; one portable zip + winget primary, Steam and the Store
parked; Azure Trusted Signing (~$9.99/mo), no EV; Founding 200 promo; ~$135/yr costs;
anti-piracy posture and what is permanently rejected.

Everything else now points at it instead of restating it:
- product.md — money sections replaced with pointers; packaging rewritten to
  winget-first, Store parked; signing updated to Trusted Signing.
- decisions.md — graveyard with cause of death for free-forever, the Store ordering,
  the updater, and the 2026-10-30 reversal of the quality-ceiling rejection.
- Distribution.md — rewritten to release mechanics only (artifact, GitHub Releases,
  winget manifest, signing, checklist, takedown): 736 → 120 lines.
- TASKS.md — TASK 54 rewritten, TASK 48's route settled, TASK 10 superseded, five new
  rows (entitlement seam, output-profile gate, licence UI, system messages, packaging).
- README.md — "free forever" replaced with the real split.
- capture.md — obs-backgroundremoval is GPL-3.0 and so licence-INCOMPATIBLE since the
  proprietary EULA; the old "compatible" line was falsified by that change.
- TASKS/task-10, task-48, task-51, task-54 — superseded-banner at the top of each, so
  none of them reads as current policy.
- HANDOFF.md — rewritten: plan settled, next code unit is the entitlement seam.

MARCOM.md and MONETIZATION.md (gitignored) were corrected in place: policy pointer at
the top of each, the flash removed from every live claim, the Polar fee break-even
corrected to ~$900/mo, and the projections flagged as written against a dead model.
2026-10-31 08:32:25 -07:00

121 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Distribution & release mechanics
How the build becomes a file someone installs. **Policy — prices, entitlement, which channels
exist and why — is [`docs/ai/commercial.md`](docs/ai/commercial.md).** This file is the how.
> The previous version of this document was a 736-line Polar/MSIX/obfuscation plan. It was
> superseded on 2026-10-31; the reasoning that still matters lives in `commercial.md` and
> `docs/ai/decisions.md`, and the full text is in `git log -- Distribution.md`.
## 1. The artifact
One self-contained single-file exe plus the bundled ffmpeg folder, zipped. No .NET install on the
target machine, no installer framework, no admin rights.
```bash
dotnet publish ytLive.csproj -c Release -r win-x64 --self-contained true \
-p:PublishSingleFile=true \
-p:IncludeNativeLibrariesForSelfExtract=true \
-p:EnableCompressionInSingleFile=true \
-p:PublishReadyToRun=true
```
- **`PublishTrimmed` stays OFF.** Trimming breaks WPF's XAML reflection (`Binding`, `DataTemplate`,
`StaticResource`). The exe is therefore fat — expect ~110–150 MB compressed with the runtime
inside, and that is the accepted cost of "copy it and run it".
- **ffmpeg stays outside the exe** — `ffmpeg\` beside it (already the app's locator contract, see
[`output.md`](output.md) → "FFmpeg locator"). Embedding it passes 200 MB and adds an extraction
step for no benefit.
- **WebView2 is the one machine dependency**: the Evergreen runtime ships with Windows 11 and most
Windows 10; a genuinely clean machine needs the bootstrapper once. Say so in the download note.
- **`AssemblyName` is still `ytLive`** → the shipped exe is `ytLive.exe` today. The rename to
`LlamaCasty.exe` is queued (three pack URIs break — see `product.md`), and until it lands every
release note names the real file.
**Portable mode.** A `portable.txt` marker beside the exe keeps the layout DB, `Assets` and
settings in `.\data\` instead of `%APPDATA%\ytLlive` (hung off `LayoutPathOverride`). Same binary,
USB-stick behaviour, nothing to uninstall.
## 2. Release
```
publish → zip → SHA-256 → GitHub Release → winget manifest PR → update notice
```
1. **Tag and publish.** `v<major>.<minor>.<patch>` tag; attach `LlamaCasty-<version>-win-x64.zip`
to the **GitHub Release**. Binaries live there, never on the droplet — free CDN, durable URLs,
release notes in the same place, and `wingetcreate` reads `releases/latest` natively.
2. **Record the hash.** `sha256sum` the zip; it goes in the winget manifest and in the release
notes. This is the anti-tamper wall: the official channel delivers exactly this artifact or
fails.
3. **winget.** `wingetcreate update LlamaCasty.LlamaCasty --version <v> --urls <release-url>
--submit` — it opens the PR against `microsoft/winget-pkgs`. Manifest shape:
`InstallerType: portable`, `InstallerSha256`, `NestedInstallerType` where the zip nests the exe.
First submission is `wingetcreate new`; the identifier is `LlamaCasty.LlamaCasty`.
4. **Update notice.** Write the current version into a small version file on the site (or read
`releases/latest` from the GitHub API). The app shows one line — *"v1.4 is out — `winget upgrade
LlamaCasty.LlamaCasty`"*. **Nothing downloads or executes**: that is Store policy 10.2.2 and a
permanent no (see `product.md`).
5. **Optional mirrors.** Scoop (a small JSON manifest hosted in a bucket) and Chocolatey (a nupkg
with a checksum) — ten minutes each, same audience.
6. **MSIX** stays buildable for the parked Store channel: `scripts/package-msix.sh` →
`artifacts/LlamaCasty.msix`, submitted nowhere until the Individual account exists.
## 3. Signing
**Azure Trusted Signing, ~$9.99/month** — Microsoft-issued, individuals eligible after identity
verification, and it accrues SmartScreen reputation without buying a certificate.
```powershell
signtool sign /v /fd SHA256 /tr http://timestamp.acs.microsoft.com /td SHA256 `
/dlib "Azure.CodeSigning.Dlib.dll" /dmdf "metadata.json" LlamaCasty.exe
```
- **⛔ No EV certificate.** Microsoft removed the EV SmartScreen instant-bypass in March 2024, so
EV ($400+/yr) buys exactly what OV (~$150–300/yr) buys — and a bought cert is a 460-day recurring
line item whose key must live on an HSM or hardware token.
- **No certificate at all** is the interim state: ship unsigned and accept the "unknown publisher"
line. winget spares the browser prompt, not the publisher line, so signing is what makes the
channel feel legitimate — the reason it is in the year-one budget.
- **Signing never clears the warning on day one** — only download volume does. Plan for weeks.
- Secrets: the Trusted Signing profile lives in CI secrets; **never commit** a `.pfx` or
`metadata.json` with credentials. `MSIX_PFX`/`MSIX_PFX_PASSWORD` are for local test installs only.
- Verify every release: `signtool verify /pa /v <file>`, and confirm the hash in the manifest
matches the uploaded zip.
## 4. Release checklist
- Build clean, 0 warnings (`./scripts/verify.sh`), full test suite green.
- `signtool verify /pa` passes on the shipped exe.
- Launch on a clean Windows profile: first-run works, recording writes where it claims, ffmpeg is
found beside the exe, WebView2-loaded UI renders.
- Fresh install through `winget install LlamaCasty.LlamaCasty` on a second machine, then
`winget upgrade` over the previous version.
- ZIP hash published; manifest PR merged; version notice updated.
- Portable mode: `portable.txt` present → data lands in `.\data\`, deleting the folder deletes the
app's footprint.
## 5. Legal and takedown
- **`LICENSE`** (EULA) forbids redistribution, resale, reverse-engineering and circumvention, and
disclaims warranty. It is what makes a mirror site a licence breach rather than a grey area.
- **`PRIVACY.md`** must name any third party the app contacts — today that is Google/YouTube,
ffmpeg is local, and **Polar** is added the day licence validation ships.
- **`THIRD-PARTY-NOTICES.txt`** stays shipped and shown in About; the ffmpeg pin stays
`lgpl-shared`, and no GPL component may be linked (see `product.md` → "Licensing").
- **DMCA**: statutory damages need a registration ($65), and a takedown needs only the notice —
host, link, good-faith statement, signature. Worth doing once there is something to pirate.
- **What actually protects the product** is in `commercial.md` → "Anti-piracy posture": signed
hash-pinned delivery, short leases, a free tier good enough that a crack buys nothing, and a
licence ID in About. **Not obfuscation, not a native DLL, not hardware locking.**
## 6. Effort, once
| Step | Effort |
|---|---|
| Publish profile + portable mode | 0.5 day |
| GitHub Release + hash + version notice | 0.5 day |
| First winget manifest (`wingetcreate new`) | 0.5 day, then ~15 min per release |
| Azure Trusted Signing profile + CI step | 0.5 day |
| Clean-machine + `winget` smoke test | 0.5 day |