docs: distribution route decided — Microsoft Store MSIX + Store IAP
Creator ruling 2026-09-27. Criteria, verbatim: "zero headaches, minimal maintenance (for me) while still providing accountability and a reasonably easy upgrade flow." Route A is the only combination where all four are solved by handing the work to Microsoft rather than to a certificate vendor: $0/yr, no certificate, no HSM, no annual renewal, no SmartScreen ramp — plus Store auto-update, Store-side payments/entitlements/refunds/support, and Microsoft review as the accountability layer. The rejected options and their reasons stay in research-store-certification.md §3 so a later session reads the ruling instead of re-deriving it. What this deletes: - The entire licensing backend. PolarLicenseService, PolarLicense, MainViewModel.License.cs (PremiumUrl, customer portal, the OfflineGracePeriod = 14 days subscription-era artifact, renewal/lapse copy) and the wrong "Polar unlocks alerts" string all become dead code. IsPremium is derived from the Store entitlement instead of an HTTP call, which also removes the whole "network flaky -> app thinks I'm expired" bug class. - Velopack, the update URL, and the self-hosted droplet — the Store updates. - Distribution.md's premise: Polar as the distribution backbone, Polar file hosting, and code signing as our problem. The IP-protection sections (1, 5, 6, 7) still stand and the build-posture ceiling is unchanged. What does NOT change: the entitlement. Free gets everything; the branding flash stays the only paid delta. Store IAP changes how IsPremium is obtained, never what it gates. Still open, deliberately: the price. The Store revenue share is unverified (do not assume a percentage), and MONETIZATION.md's $29 -> $49 one-time decision is re-opened against a fresh instinct toward ~$99/yr. No price encoded yet. The first code unit is unchanged: bundle ffmpeg (TASK 48 item 1). That clears the one hard certification gate and fixes a real user-facing 404. MARCOM.md and MONETIZATION.md were edited too but are gitignored by design, so those changes stayed local.
This commit is contained in:
+78
-79
@@ -1,75 +1,61 @@
|
||||
# HANDOFF — current state
|
||||
|
||||
**Branch:** `main` (pre-1.0, no feature branches — creator ruling 2026-08-24).
|
||||
**Last pushed:** `938c5b3` (alert ticker). This unit (distribution/certification research) is
|
||||
**docs-only** — no code touched, no build, no tests run.
|
||||
**Last pushed:** `e78c58f` (Store certification research). This unit (recording the Store MSIX
|
||||
+ Store IAP ruling) is **docs-only** — no code touched, no build, no tests run.
|
||||
|
||||
## This unit: distribution & Store certification research is WRITTEN DOWN
|
||||
## ✅ DECIDED 2026-09-27 — distribution is the Microsoft Store: MSIX + Store IAP
|
||||
|
||||
The session's open question was "how do we get this in front of users without a SmartScreen
|
||||
scarewall" and it had been answered **in conversation only** — which meant the next session
|
||||
would re-derive it. It is now in the map, and the conversation can be dropped.
|
||||
**Creator's criteria, verbatim: "zero headaches, minimal maintenance (for me) while still
|
||||
providing accountability and a reasonably easy upgrade flow."** Route A is the only option
|
||||
where all four are solved by handing the work to Microsoft rather than to a certificate
|
||||
vendor: **$0/yr, no certificate, no HSM, no annual renewal, no SmartScreen ramp**, plus Store
|
||||
auto-update, Store-side payments/entitlements/refunds/support, and Microsoft review as the
|
||||
accountability layer. The rejected options and their reasons are in
|
||||
`TASKS/research-store-certification.md` §3 — **read that before reopening the question, not
|
||||
before re-deriving it.**
|
||||
|
||||
| File | What it is |
|
||||
|---|---|
|
||||
| `TASKS/research-store-certification.md` | **new** — the authoritative research. Store Policies **7.20** (effective 2026-10-22, re-check the version), MSIX full-trust vs AppContainer, cert economics, a ⛔/✅ table of which policies bind and which don't, the camera/mic gating layers, the YouTube age + COPPA analysis, the 11.12 UGC judgment call, and the filter design constraints |
|
||||
| `TASKS/task-48-distribution-msix.md` | **new** — the executable checklist. Carved out of TASK 36 item 6 (code signing / installer / Velopack URL) so distribution has one owner |
|
||||
| `TASKS/task-49-chat-profanity-filter.md` | **new** — the chat filter checklist. Not blocked |
|
||||
| `Distribution.md` §4.3 | **corrected** — the EV recommendation was dead (§ below) |
|
||||
| `ai.md` | new "Windows packaging & distribution" section (durable invariants) + a correction on the FFmpeg locator |
|
||||
| `MyMistakes.md` | the policy-applicability lesson |
|
||||
| `TASKS.md` | rows 48/49, a research index, and the TASK 36 item 6 split |
|
||||
| `MARCOM.md` | ⛔ **privacy-copy guard — gitignored, so this edit is local-only and did not travel with the push** |
|
||||
**The big consequence: the whole licensing backend is deleted.** `PolarLicenseService`,
|
||||
`PolarLicense`, `MainViewModel.License.cs` (`PremiumUrl`, customer portal, the
|
||||
`OfflineGracePeriod = 14 days` subscription-era artifact, renewal/lapse copy) and the wrong
|
||||
"Polar unlocks alerts" string all become dead code. `IsPremium` comes from the **Store
|
||||
entitlement** instead of an HTTP call — which also deletes the entire "network flaky → app
|
||||
thinks I'm expired" bug class. **Velopack, the update URL and the DO droplet go too.**
|
||||
|
||||
### Two real defects the research surfaced (both now recorded, neither fixed — no code this unit)
|
||||
**What does not change: the entitlement.** Free gets everything; the branding flash stays the
|
||||
ONLY paid delta. Store IAP changes how `IsPremium` is *obtained*, never what it *gates*.
|
||||
|
||||
1. **⛔ `FfmpegLocator` downloads an unsigned exe from GitHub and runs it.** That is Store
|
||||
policy **10.2.2** (dynamic code inclusion) verbatim, *and* it is the root cause of the
|
||||
2026-09-01 failure: the previous daily pin aged out of BtbN's 14-day retention and the
|
||||
download **404'd on the creator's first real recording attempt**. `FfmpegLocator.cs:30-35`
|
||||
records the incident but still reads like a design choice. → **TASK 48 item 1.** Not
|
||||
Store-conditional: bundling kills this whole class of cold-start failure and deletes the
|
||||
startup network dependency. **This is the highest-value unblocked item in the repo.**
|
||||
2. **⛔ `Distribution.md:318` recommended a $400+/yr EV certificate for a benefit Microsoft
|
||||
deleted in March 2024.** Fixed. Had it shipped, it would have cost $400+/yr to buy exactly
|
||||
what $150 buys. Lesson in `MyMistakes.md` — the recurring shape is *citing a policy or a
|
||||
platform fact from memory instead of re-verifying it in the document itself.*
|
||||
**⏳ Still open: the price.** The Store revenue share is unverified (⚠️ assume no percentage —
|
||||
check current terms before setting a price), and `MONETIZATION.md`'s `$29 → $49` one-time
|
||||
decision is re-opened against a fresh instinct toward a ~$99/yr subscription. **No price is
|
||||
encoded anywhere until the creator settles it.** Note the storefront changed, so the old
|
||||
"~$69 floor" and "don't break the launch-price promise" notes now refer to Store tiers.
|
||||
|
||||
### ⛔ The decision that is NOT made, and belongs to the creator
|
||||
### The first code unit: bundle ffmpeg (TASK 48 item 1)
|
||||
|
||||
**The distribution route.** Research is done and MSIX is the front-runner (full trust is viable;
|
||||
we trip **none** of the four MSIX disqualifiers — no driver installed, no per-user service, no
|
||||
elevation, no shell extension). Four real combinations, costed in
|
||||
`TASKS/research-store-certification.md` §3:
|
||||
Two real defects the research surfaced — **neither is fixed yet**, this was a docs unit:
|
||||
|
||||
| # | Route | Cert/yr | SmartScreen | Notes |
|
||||
|---|---|---|---|---|
|
||||
| A | Store MSIX + Store IAP | **$0** | none | Polar gets deleted; revenue cut; public listing |
|
||||
| B | Store MSIX + **Polar** | **$0** | none | free signing **and** keep 100% — two systems to maintain |
|
||||
| C | **Polar file hosting** + own cert | $120–300 | warning ramp | **the status quo already sketched in `Distribution.md:14`/`:296`** |
|
||||
| D | Store EXE (policy 10.2.9) | $120–300 | warning ramp | **dominated** — cert anyway, silent install, own URL |
|
||||
1. **⛔ `FfmpegLocator` downloads an unsigned exe from GitHub and runs it.** Store policy
|
||||
**10.2.2** (dynamic code inclusion) verbatim, *and* the root cause of the 2026-09-01
|
||||
failure — the pin aged out of BtbN's 14-day retention and the download **404'd on the
|
||||
creator's first real recording attempt**. `FfmpegLocator.cs:30-35` records the incident but
|
||||
still reads like a design choice. **Fix: bundle it.** Also deletes the startup network
|
||||
dependency.
|
||||
2. **⛔ `Distribution.md:318` recommended a $400+/yr EV certificate for a SmartScreen bypass
|
||||
Microsoft removed in March 2024.** Fixed last commit — had it shipped, it would have cost
|
||||
$400+/yr to buy what $150 buys. Now moot anyway (MSIX is signed by Microsoft), but the
|
||||
lesson in `MyMistakes.md` stands: a policy citation is a claim about **scope**, not just
|
||||
text.
|
||||
|
||||
**Nothing else was allowed to block on this** — the user is right that most of the research is
|
||||
route-independent and worth banking regardless. So: research banked, dead line fixed, and only
|
||||
the packaging work is parked.
|
||||
### ⛔ Two invariants that break silently if touched
|
||||
|
||||
**Also still open, deliberately:** pricing (one-time vs one-time+monthly), the license provider,
|
||||
and therefore all licensing copy. `OverlayHost.xaml` still claims Polar unlocks alerts — wrong,
|
||||
alerts are not gated. Unresolved, queued, **not** to be papered over.
|
||||
|
||||
### The two findings most likely to be forgotten
|
||||
|
||||
- **Distribution and licensing are independent.** Policy 10.8.1 lets a **Store-distributed**
|
||||
app verify licenses with **Polar**. So "should we use the Store?" does not imply "drop Polar?"
|
||||
Only route A removes Polar, and that is a licensing decision riding on a distribution one.
|
||||
- **⛴ Two invariants that will break silently if touched:**
|
||||
- **Full trust, or recording breaks.** `DefaultRecordFolder()` writes to Downloads/MyVideos;
|
||||
that passes through unvirtualized **only** at `mediumIL`. Flip the manifest to
|
||||
`appContainer` and output vanishes with no error. A comment is owed there **when the
|
||||
manifest lands** (TASK 48 item 6) — not before.
|
||||
- **Chat is rendered, never stored.** That non-persistence half is the load-bearing part of
|
||||
the 11.12 certification answer. No chat history, moderation log, analytics, or crash payload
|
||||
may be added without re-arguing 11.12 first.
|
||||
- **Full trust, or recording breaks.** `DefaultRecordFolder()` writes to Downloads/MyVideos;
|
||||
that passes through unvirtualized **only** at `mediumIL`. Flip the manifest to
|
||||
`appContainer` and output vanishes with no error. A comment is owed there **when the
|
||||
manifest lands** (TASK 48 item 6) — not before.
|
||||
- **Chat is rendered, never stored.** That non-persistence half is the load-bearing part of
|
||||
the 11.12 certification answer. No chat history, moderation log, analytics, or crash payload
|
||||
may be added without re-arguing 11.12 first.
|
||||
|
||||
## Landmines
|
||||
|
||||
@@ -99,29 +85,42 @@ alerts are not gated. Unresolved, queued, **not** to be papered over.
|
||||
|
||||
## Uncommitted / untracked
|
||||
|
||||
- `MARCOM.md` — the privacy-copy guard was added but the file is **gitignored by design**
|
||||
(confidential business file, `.gitignore:11`). It stays local, as intended. Same for
|
||||
`MONETIZATION.md` and `CREDENTIALS.md` — **never commit those.**
|
||||
- `MARCOM.md`, `MONETIZATION.md` — both edited (privacy-copy guard; the Polar-obsolete banner
|
||||
and the re-opened-price note) and both **gitignored by design** (confidential business
|
||||
files, `.gitignore:10-11`). They stay local, as intended. Same for `CREDENTIALS.md` —
|
||||
**never commit those.**
|
||||
|
||||
## Next
|
||||
|
||||
1. **Bundle ffmpeg (TASK 48 item 1)** — unblocked, recommended on every route, and it fixes a
|
||||
real user-facing failure. *This is the next code unit.*
|
||||
2. **The route decision** (creator) — A/B/C above, once the ffmpeg fix is out of the way.
|
||||
3. **Vertical recording verification** — the compositor tier is proven by
|
||||
1. **Bundle ffmpeg (TASK 48 item 1)** — unblocked, first code unit, fixes a real user-facing
|
||||
failure and clears the one hard certification gate.
|
||||
2. **Settle the price** — one-time vs subscription, and the number. Then declare the IAP
|
||||
products in Partner Center. **Blocks:** the Store listing, and the `OverlayHost.xaml` copy.
|
||||
3. **The packaging project + `Package.appxmanifest`** (TASK 48 items 2–3) — full trust,
|
||||
`webcam`/`microphone`, English only; Velopack deleted. Add the `DefaultRecordFolder()`
|
||||
comment in the same unit.
|
||||
4. **Polar teardown** (TASK 48 item 0) — `PolarLicenseService`, `PolarLicense`,
|
||||
`MainViewModel.License.cs`, the `OverlayHost.xaml` string, the `csproj`/`App.xaml.cs`
|
||||
Velopack sites. `IsPremium` ← Store entitlement. **Do this as one unit** — a half-torn-down
|
||||
licensing path is worse than either end state.
|
||||
5. **Verify the Store revenue-share rate** — before step 2, not after.
|
||||
6. **Vertical recording verification** — the compositor tier is proven by
|
||||
`Render_VerticalTier_Outputs_1080x1920_From_The_Center_Crop`; the *record* path has never
|
||||
been run. `FramePump.cs:645` flags off-size tiers as a known follow-up.
|
||||
4. **Multi-instance** — route `FfmpegLocator._toolsDir` through `InstanceProfile` (same shared
|
||||
extraction race as #1, and it becomes moot if ffmpeg is bundled). Confirm the launch method:
|
||||
`$env:YTLIVE_INSTANCE=2` + `dotnet run --no-build` in a second shell is the known-good path.
|
||||
5. **Post-session efficacy report** — roll up `CurrentHealth` (dropped frames, duration, health
|
||||
7. **WACK + certification notes + the privacy policy** (TASK 48 items 4–5) — the policy must
|
||||
state camera/mic is OS-gated, nothing is retained, and nothing is fetched at runtime.
|
||||
8. **Post-session efficacy report** — roll up `CurrentHealth` (dropped frames, duration, health
|
||||
message) when a stream or recording ends. `SessionTeardownTests` is the natural home.
|
||||
6. **`scripts/publish.sh` + Debug-only `InternalsVisibleTo` + the `LlamaCasty.exe` rename** —
|
||||
still queued from 2026-09-26; do **NOT** add `-p:PublishTrimmed=true` (WPF fails at runtime,
|
||||
not build time). See `TASKS.md` → "Shipping / release build".
|
||||
7. **The alert-gating copy** (`OverlayHost.xaml`) — fix the copy or gate the alerts; do not leave
|
||||
it lying. Blocked behind the pricing ruling.
|
||||
8. **The camera-privacy measurement** — does the Win11 desktop-app camera toggle actually gate a
|
||||
DShow webcam and a capture card? Gates all privacy-forward copy (`MARCOM.md` guard).
|
||||
9. **TASK 36:212 stale "shipped" line** — one-line fix, needs a hand.
|
||||
10. Ship-checklist items live in `TASKS.md` → "1.0 gates".
|
||||
9. **Measure whether the Windows camera toggle gates DShow** — gates all privacy-forward copy
|
||||
(`MARCOM.md` guard). Not a certification risk; a trust risk.
|
||||
10. **TASK 36:212 stale "shipped" line** — one-line fix, needs a hand.
|
||||
|
||||
**Dropped from the list** because the ruling made them moot: multi-instance's ffmpeg tools-dir
|
||||
race (item 1 makes it disappear), `scripts/publish.sh` + the `LlamaCasty.exe` rename (the Store
|
||||
packages and delivers — *revisit only if we ever ship outside the Store*), and the alert-gating
|
||||
copy (the wrong string dies with the Polar teardown in step 4).
|
||||
|
||||
**Everything else in the v1 queue:** stream resilience (32), bandwidth step-down (33), scheduled
|
||||
streams (34), scene-linked audio (35), the master limiter (12), text source (3.16), reward
|
||||
events (3.20), the media picker (21), webcam identity (9.5), settings units A/C/D (40), and the
|
||||
defaults split (37). Ship-checklist items live in `TASKS.md` -> "1.0 gates".
|
||||
|
||||
Reference in New Issue
Block a user