Files
LlamaCasty/TASKS/task-48-distribution-msix.md
T
gramps e78c58fc28 docs: bank the Windows Store + signing research, and fix the dead EV-certificate line
The distribution answer existed only in conversation, so every session re-derived
it. It is now in the map, and the route decision is explicitly parked as the
creator's.

new TASKS/research-store-certification.md — Store Policies 7.20 + MSIX packaging:
which policies bind, which don't (and why), cert economics, camera/mic gating
layers, YouTube age + COPPA, the 11.12 UGC judgment call.

Two real defects surfaced, neither fixed (docs-only unit):
- FfmpegLocator downloads an unsigned exe from GitHub and runs it. That is
  policy 10.2.2 (dynamic code inclusion) verbatim, and it is the root cause of
  the 2026-09-01 404 — the pin aged out of BtbN's 14-day retention on the
  creator's first real recording attempt. -> TASK 48 item 1, not
  Store-conditional.
- Distribution.md:318 recommended a $400+/yr EV cert for a SmartScreen bypass
  Microsoft removed in March 2024. Fixed; had it shipped it would have cost
  $400+/yr to buy what $150 buys.

Also new: TASKS/task-48 (checklist, carved out of TASK 36 item 6) and
TASKS/task-49 (chat profanity filter, not blocked). ai.md gains the durable
invariants — full trust or recording breaks silently, chat is rendered never
stored — plus a correction to the FFmpeg locator section. MyMistakes.md records
the lesson: a policy citation is a claim about scope, not just text.

MARCOM.md got the privacy-copy guard but is gitignored by design, so that edit
stays local and did not travel here.
2026-09-27 14:17:13 -07:00

188 lines
9.2 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.
# TASK 48 — Distribution & packaging: route decision, MSIX, signing
> Catalog: [`TASKS.md`](../TASKS.md) — status and requirements live here.
> **Research: [`TASKS/research-store-certification.md`](research-store-certification.md)** — the "why".
> Carved out of TASK 36 item 6 (release engineering) on 2026-09-27 so distribution has one
> owner instead of three scattered mentions.
**Status:** ☐ Queued — **⏳ blocked on the creator's route decision** (item 0)
**Goal:** get LlamaCasty in front of a user without a SmartScreen scarewall, ideally without
an annual certificate bill, and without breaking recording, capture, or audio.
⚠️ **Nothing in this task is decided yet.** The research is done and MSIX is the
front-runner, but the route is the creator's call. Items 2–8 describe the MSIX path
*conditional on choosing it* — if the answer is Polar-hosted + a cert, most of them evaporate
and only items 0, 1, and 9 remain.
---
## 0. ⛔ THE DECISION — creator, not AI
Pick one:
| # | Route | Cert/yr | SmartScreen | Extra work |
|---|---|---|---|---|
| **A** | Store MSIX + Store IAP | **$0** | none | MSIX packaging; Store review; **Polar deleted**; revenue cut |
| **B** | Store MSIX + **Polar** | **$0** | none | MSIX packaging; Store review; two systems to maintain |
| **C** | **Polar file hosting** + Polar + own cert | $120–300 | warning ramp | none beyond buying the cert |
| **D** | Store EXE (10.2.9) | $120–300 | warning ramp | **dominated** — cert anyway + silent install + maintain our own URL |
**C is the status quo already sketched in `Distribution.md:14`/`:296`** — Polar hosts the
signed exe (10GB, signed personal URLs, SHA-256). The Store is not needed for delivery at
all; its only unique value is *free Microsoft signing with no warning*.
Cost table, full detail, and the dead-EV correction: `research-store-certification.md` §2–3.
---
## 1. ⛔ Bundle ffmpeg instead of downloading it — **do this on EVERY route**
**Not conditional on the Store. This is worth doing regardless.**
`Services/Encoder/FfmpegLocator.cs:37-38` pins a GitHub release URL; `LocateAsync`
downloads (line 69), extracts (line 73), and the encoder executes the result. On a cold
cache the app downloads an unsigned executable from the internet and runs it.
- **Store blocker:** policy 10.2.2 forbids dynamic code inclusion (download-and-execute).
- **Route-independent bug class:** `FfmpegLocator.cs:30-35` records that the previous
daily pin aged out of GitHub retention and **404'd on the first real recording attempt
(2026-09-01)**. Bundling kills this permanently and removes the startup network
dependency.
**Do:** ship `ffmpeg.exe` + `ffprobe.exe` + the `libav*.dll` family inside the package;
`FfmpegLocator` resolves PATH → package-local → cache, and never downloads.
`IFfmpegLocator`'s contract, the `ExtractBinaries` staging discipline, and the existing
`FfmpegLocatorTests` cold/cache/PATH coverage all still apply.
**Licensing:** the LGPL-shared build was chosen for LGPL §6 compliance (dynamic linking =
"license text + source offer"). That reasoning is **unaffected**. Confirm
`THIRD-PARTY-NOTICES.txt` covers the bundled build.
**Record the immutable tag** in `TASKS.md` per the licensing rule, and note the URL is now
a provenance record rather than a runtime fetch.
---
## 2. ☐ `Package.appxmanifest` — full trust, camera, microphone
Only if the Store is chosen. There is currently **no `.manifest` file in the repo at all**,
so this is purely additive.
- `rescap:Capability Name="runFullTrust"` — medium integrity, not AppContainer
- `webcam` and `microphone` capabilities
- `uap10:TrustLevel="mediumIL"`, `uap10:RuntimeBehavior="packagedClassicApp"`
- `uap10:RuntimeBehavior="packagedClassicApp"` is what allows launching package
executables as child processes
- Declare **English only** (10.7 — otherwise the description must be localized into every
declared language)
- Block map SHA2-256, `StoreManifest`, under the 25 GB cap
**Do NOT use `appContainer`** — see the invariant in item 6.
## 3. ☐ Remove Velopack — 3 edit sites
Only if the Store is chosen (the Store handles updates). Trivially removable; the code was
written defensively for exactly this.
- `ytLive.csproj:92` — `<PackageReference Include="Velopack" Version="1.2.0" />`
- `App.xaml.cs:3` — `using Velopack;`
- `App.xaml.cs:38-46` — the sole call site, already try/caught and commented
"(non-fatal) … when no URL is set, the check is a no-op"
**Retires:** the pending "Velopack update URL" item (`TASKS.md` open items,
`task-10-monetization.md:43`) and the self-hosted DigitalOcean droplet.
## 4. ☐ Windows App Certification Kit
Run before submission. Technical compliance is tested by WACK; it is not optional. Known
relevant check: the app must start promptly, stay responsive, and shut down gracefully
(10.4.2).
## 5. ☐ Certification notes + the three documentation artifacts
**In Partner Center (submission):**
- ☐ **Working YouTube demo account** (10.3.1) — required, we cannot stream without sign-in
- ☐ Tick the **secure third-party purchase API** box — Polar (10.8.1 / 10.8.2)
- ☐ **The 11.12 UGC position**, stated in full — "mirrored from YouTube, which moderates it
at industrial scale upstream; we render transiently, persist nothing, and provide no
user-to-user communication surface." Full reasoning and the Q1-2026 enforcement numbers
are in `research-store-certification.md` §9
- ☐ The **YouTube age-gate argument** — operator is 13+ by construction (§8)
- ☐ Note that the product is **general audience, not directed at under-13s**
**On `llamachile.shop`:**
- ☐ **Privacy policy** (10.5.1 — mandatory for Win32/Desktop Bridge). Must state: camera/mic
access is user-directed and OS-gated; **no retention** of chat or reward payloads; no
viewer data collected; **ffmpeg is bundled and nothing is fetched at runtime**
- ☐ **Code of conduct + content guidelines** (11.12 / 11.15)
- ☐ Confirm `THIRD-PARTY-NOTICES.txt` covers the bundled LGPL ffmpeg build
**In Partner Center (listing):**
- ☐ **IARC age-rating questionnaire** (10.11.1) — general audience, 12+ territory
- ☐ Title is exactly **`LlamaCasty`** — 10.1.1 forbids marketing text or extraneous keywords
- ☐ Search terms: max 7, no pricing terms, and **no other product titles** (10.1.3 — cannot
list `OBS` or `StreamYard`)
- ☐ Real listing content — 10.1.4 requires an active, substantive presence
- ☐ Review the **Individual vs Company** account question before enrolling (see
`research-store-certification.md` §11 item 1) — getting this wrong means re-enrolling
## 6. ☐ The full-trust recording invariant — **comment lands WITH this work**
`ViewModels/MainViewModel.Recording.cs:173-179` (`DefaultRecordFolder()`) writes to
`%USERPROFILE%\Downloads` or `SpecialFolder.MyVideos`; `ChooseRecordFolder()` (line 151)
uses `Microsoft.Win32.OpenFolderDialog`; the temp-write-then-move lifecycle stays in one
directory (line 131-132).
**This works only because the package is full trust.** At `mediumIL`, user-profile writes
pass through unvirtualized and `OpenFolderDialog` is an ordinary Win32 browser with no
capability token. No `broadFileSystemAccess` needed.
⚠️ **If anyone flips the manifest to `appContainer`, recording silently breaks** —
`Directory.CreateDirectory` and `File.Move` start resolving to a per-package virtualized
location and output vanishes.
**Add a comment at `DefaultRecordFolder()` in this task, not before.** A comment describing
a manifest that does not exist is worse than no comment.
**Also verify on a real packaged build** before trusting it with recordings — the docs say
full trust passes writes through, but that is worth confirming with an actual package
identity rather than an unpackaged run.
## 7. ☐ Confirm the disqualifiers stay clear after packaging
All four are currently clear (verified by grep 2026-09-27) — re-verify once the packaging
project exists:
- No Windows driver installed (we consume DShow filters, we do not install one)
- No per-user Windows service
- No elevation / `requireAdministrator` / UAC manifest
- No shell extension, no in-process module loading by outside processes, no jump list
## 8. ☐ Pre-submission gates
- ☐ 0 warnings, full suite green
- ☐ **Vertical-recording path verified end-to-end** (compositor tier is proven by
`Render_VerticalTier_Outputs_1080x1920_From_The_Center_Crop`; the *record* path has never
been exercised — `Services/Pump/FramePump.cs:645` flags off-size tiers as a known
follow-up)
- ☐ **The real-output confirmation** the creator has been doing manually
- ☐ Camera/mic/wasapi capture verified **from the packaged build**, not just unpackaged
- ☐ Clean uninstall verified (10.2.7)
- ☐ Notification-disabled path leaves the app functional (10.9)
---
## Not in this task (deliberately)
- **Velopack hardening / obfuscation / assembly splitting** — stays a GA-time decision per
TASK 36 item 6's agreed ceiling. Compile flags max at `HARDENED` + `MOCK_REWARDS`,
additive-only.
- **EULA draft/review and the THIRD-PARTY-NOTICES gate** — stay in TASK 36 item 6.
- **Vertical-canvas feature work** — the feature exists; only the *record-path test* above
is missing.
- **macOS / Avalonia port** — deferred; would be a second app, not a port.