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:
+37
-5
@@ -1,12 +1,42 @@
|
||||
# Distribution & IP Protection Plan
|
||||
|
||||
> 360-degree protection strategy for LlamaCasty (.NET 8 / WPF), built around Polar.sh.
|
||||
> 360-degree protection strategy for LlamaCasty (.NET 8 / WPF).
|
||||
|
||||
> ## ⛔ SUPERSEDED IN PART — 2026-09-27
|
||||
>
|
||||
> **Distribution is now the Microsoft Store: MSIX package + Store IAP.** The creator's criteria
|
||||
> were *"zero headaches, minimal maintenance (for me) while still providing accountability and
|
||||
> a reasonably easy upgrade flow"*, and that ruling deleted this document's central premise.
|
||||
>
|
||||
> **What still stands below:** §1 (code architecture / IP protection), §5 (obfuscation posture),
|
||||
> §6 (legal), §7 (hardening) — those are about protecting the *binary*, and an MSIX package is
|
||||
> still a binary. **§1.2's build-posture ceiling (HARDENED + MOCK_REWARDS, additive-only)
|
||||
> remains the agreed ceiling.**
|
||||
>
|
||||
> **What is dead:**
|
||||
> - **Polar as the distribution backbone** — the entire section below. Store IAP handles
|
||||
> checkout, entitlements, refunds, tax, and the customer portal. So does **file hosting**:
|
||||
> the Store is the delivery mechanism, so "upload `LlamaCasty.exe` to Polar as a File
|
||||
> Download benefit" (§2) no longer exists as a step.
|
||||
> - **Code signing as our problem** — MSIX is signed by **Microsoft**. There is no certificate
|
||||
> to buy, no HSM, no annual renewal. See §4.3, which was already corrected to say this, and
|
||||
> `TASKS/research-store-certification.md` §2–3.
|
||||
> - **Velopack / the update URL / the DO droplet** — Store auto-update.
|
||||
>
|
||||
> **The authoritative plan is now [`TASKS/task-48-distribution-msix.md`](TASKS/task-48-distribution-msix.md).**
|
||||
> Keep this file for the protection sections; do not re-derive a delivery strategy from it.
|
||||
|
||||
---
|
||||
|
||||
## Polar.sh as the Distribution Backbone
|
||||
## Polar.sh as the Distribution Backbone — ⛔ OBSOLETE (2026-09-27)
|
||||
|
||||
Polar handles everything between "customer wants to pay" and "customer has a working license key." We don't build any of that. What Polar gives us:
|
||||
> **Historical record only.** Retained because the fee tables and the reasoning about *why*
|
||||
> one-time beat subscription were worth working out. **None of the "How We Use It" rows are
|
||||
> current**, with one exception worth keeping: the Merchant-of-Record point — *someone else
|
||||
> collects and remits VAT/GST* — is still true under Store IAP, because **Microsoft** is now
|
||||
> that someone. That fact alone was the strongest argument for the ruling.
|
||||
|
||||
Polar handled everything between "customer wants to pay" and "customer has a working license key." We didn't build any of that. What Polar *was* going to give us:
|
||||
|
||||
| Capability | How We Use It |
|
||||
|------------|---------------|
|
||||
@@ -18,9 +48,11 @@ Polar handles everything between "customer wants to pay" and "customer has a wor
|
||||
| **Merchant of Record** | Polar collects and remits VAT/GST/sales tax globally. We never touch tax compliance. |
|
||||
| **Webhooks** | Polar notifies our backend on purchase, cancellation, key rotation. Used for optional telemetry (section 6.3). |
|
||||
|
||||
**Polar pricing (2026):** 5% + $0.50 per transaction (Starter plan). No monthly fee.
|
||||
**Polar pricing (2026):** 5% + $0.50 per transaction (Starter plan). No monthly fee. ⛔ *No
|
||||
longer paid to anyone — the equivalent cost is now inside the Store revenue share, whose rate
|
||||
is unverified (see `TASKS/research-store-certification.md` §11).*
|
||||
|
||||
**What Polar does NOT handle:** Obfuscation, code signing, anti-tamper, runtime protection, EULA, DMCA. That's all us — sections 1-3, 5-7 below.
|
||||
**What Polar did NOT handle:** Obfuscation, code signing, anti-tamper, runtime protection, EULA, DMCA. That's all us — sections 1-3, 5-7 below.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+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".
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
| 07 | Meter scaling amplification | ✅ Done | [`TASKS/task-07-meter-scaling.md`](TASKS/task-07-meter-scaling.md) |
|
||||
| 08 | Audio milestone | ✅ SHIPPED 2026-08-14 | [`TASKS/task-08-audio-milestone.md`](TASKS/task-08-audio-milestone.md) |
|
||||
| 09 | YouTube Live Stream Management | ⏳ In progress — items 1–3, 4 shipped; item 5 open; item 6 locked (TASK 36) | [`TASKS/task-09-live-stream-management.md`](TASKS/task-09-live-stream-management.md) |
|
||||
| 10 | Monetization: watermark-only one-time license + Polar billing | 🔶 In progress — steps 1–7 shipped | [`TASKS/task-10-monetization.md`](TASKS/task-10-monetization.md) |
|
||||
| 10 | Monetization: watermark-only one-time license + Polar billing | 🔶 In progress — steps 1–7 shipped; **now a TEARDOWN: Polar is deleted in favour of Store IAP (2026-09-27)** | [`TASKS/task-10-monetization.md`](TASKS/task-10-monetization.md) |
|
||||
| 11 | Post-pause polish batch (creator's 8 review issues) | ✅ SHIPPED 2026-08-15 | [`TASKS/task-11-polish-batch.md`](TASKS/task-11-polish-batch.md) |
|
||||
| 12 | Master limiter on the live mix | ☐ Queued | [`TASKS/task-12-master-limiter.md`](TASKS/task-12-master-limiter.md) |
|
||||
| 13 | Social media launch kit | 🔶 Scoped — queued after v1 | [`TASKS/task-13-social-launch-kit.md`](TASKS/task-13-social-launch-kit.md) |
|
||||
@@ -63,7 +63,7 @@
|
||||
| 45 | TEST-tab chat fix #2: insert body must declare `snippet.type` (400 MISSING_REQUIRED_FIELD) | ✅ Done (2026-09-25) | [`TASKS/task-45-chat-insert-type.md`](TASKS/task-45-chat-insert-type.md) |
|
||||
| 46 | Drawers: click outside the rail closes whichever is open — TEST added to the existing Stream Settings + YPP dismiss behavior | ✅ Done (2026-09-25) | [`TASKS/task-46-drawer-click-outside-close.md`](TASKS/task-46-drawer-click-outside-close.md) |
|
||||
| 47 | Alert box video: built-in/custom alert clip (+ six-animation fallback) with read-time fade in/out + ticker (now in the preview too, 3 display methods) + alert volume in the live mix | ✅ Done (2026-09-26) | [`TASKS/task-47-alert-videos.md`](TASKS/task-47-alert-videos.md) |
|
||||
| 48 | Distribution & packaging: route decision, bundled ffmpeg, MSIX + code signing | ⏳ Queued — **blocked on the creator's route decision**; bundled-ffmpeg half is unblocked and recommended | [`TASKS/task-48-distribution-msix.md`](TASKS/task-48-distribution-msix.md) |
|
||||
| 48 | Distribution & packaging: **MSIX + Store IAP** | 🔶 In progress — **✅ route decided 2026-09-27 (Store MSIX + Store IAP)**; item 1 (bundle ffmpeg) is the next code unit | [`TASKS/task-48-distribution-msix.md`](TASKS/task-48-distribution-msix.md) |
|
||||
| 49 | Chat profanity filter (local, opt-in, non-persistent, user word list) | ☐ Queued (2026-09-27) | [`TASKS/task-49-chat-profanity-filter.md`](TASKS/task-49-chat-profanity-filter.md) |
|
||||
|
||||
---
|
||||
@@ -213,18 +213,44 @@ second encoder path needing a "redirect". Record+simulcast is one ffmpeg with tw
|
||||
installer, and the Velopack update URL have one owner instead of three scattered mentions.
|
||||
**EULA draft/review and the THIRD-PARTY-NOTICES license-texts gate stay in TASK 36 item 6**,
|
||||
as does the agreed build-posture ceiling (HARDENED + MOCK_REWARDS, additive-only).
|
||||
- **TASK 48 — distribution & packaging** — **⏳ the route decision belongs to the creator.**
|
||||
Research is done and MSIX is the front-runner; the four real combinations (Store+Store IAP /
|
||||
Store+Polar / Polar-hosted+own cert / dominated Store-EXE) and their cert costs are tabulated
|
||||
in `TASKS/research-store-certification.md` §3. Two things are settled and unblocked:
|
||||
**(a) bundle ffmpeg instead of downloading it** — `FfmpegLocator` currently downloads an
|
||||
unsigned exe from GitHub and runs it, which is Store policy 10.2.2 (dynamic code inclusion)
|
||||
*and* is the root cause of the 2026-09-01 expired-pin 404; **(b) the `Distribution.md` EV
|
||||
claim is dead** — Microsoft removed the SmartScreen EV bypass in March 2024, so paying
|
||||
$400+ buys what $150 buys. Full-trust MSIX is viable (mediumIL, not AppContainer, and the
|
||||
three technical disqualifiers — drivers, per-user services, elevation — are all clear).
|
||||
Packaging, Velopack removal, WACK, the demo account, the privacy policy and the IARC
|
||||
questionnaire are all specified in the task file and waiting.
|
||||
- **TASK 48 — distribution & packaging** — **✅ ROUTE DECIDED 2026-09-27: Microsoft Store,
|
||||
MSIX package, Store IAP.** 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
|
||||
(Store+Polar, Polar-hosted + own cert, Store-EXE) are recorded with their reasons in
|
||||
`TASKS/research-store-certification.md` §3 so the decision is not reopened.
|
||||
- **The consequence that makes it cheap: the entire licensing subsystem is deleted.**
|
||||
`Services/PolarLicenseService.cs` (HTTP validation, swallowed network failures, the
|
||||
ignored `expires_at`), `Helpers/PolarLicense.cs`, `ViewModels/MainViewModel.License.cs`
|
||||
(`PremiumUrl`, customer portal, the `OfflineGracePeriod = 14 days` subscription-era
|
||||
artifact, renewal/lapse copy), and the incorrect "Polar unlocks alerts" string in
|
||||
`Controls/OverlayHost.xaml` all become dead code. `IsPremium` is derived from the **Store
|
||||
entitlement** instead of a remote HTTP call — one locally cached bit refreshed by the OS,
|
||||
and the whole "network flaky → app thinks I'm expired" bug class disappears with the
|
||||
offline-grace machine.
|
||||
- **Unchanged:** the watermarks posture. Free gets everything; the branding flash stays the
|
||||
ONLY paid delta (TASK 36 item 2). Store IAP changes how the bit is *obtained*, never what
|
||||
it *gates*.
|
||||
- **Still to verify (does not block packaging):** current Store revenue-share terms — ⚠️ do
|
||||
not assume any percentage, verify before setting a price; and the one-time vs
|
||||
subscription shape of the IAP tier (the storefront is decided, the price is not).
|
||||
- **First code unit: item 1 — bundle ffmpeg instead of downloading it.** Unblocked,
|
||||
recommended on every route, and it fixes a real user-facing failure.
|
||||
- **TASK 10 is now a teardown, not a build** (2026-09-27) — Store IAP deletes the Polar
|
||||
licensing path. The Polar fee tables, the perpetual-key model, and the customer-portal
|
||||
plumbing in `MONETIZATION.md` (gitignored, local) are obsolete; the **watermark-only
|
||||
entitlement and the branding-flash delta carry over unchanged**. The stale Polar product
|
||||
(`$99/yr`, id `d105dfa1-…`) is not reused — Store IAP products are declared in Partner
|
||||
Center instead.
|
||||
- **Pricing is re-opened** (2026-09-27) — `MONETIZATION.md` carries a **one-time perpetual**
|
||||
decision from 2026-09-21 (`$29` founder → `$49` list) that explicitly superseded the old
|
||||
`$99/yr` subscription; the creator's current instinct is back toward a subscription.
|
||||
**Unresolved — do not encode a price until it is settled**, and note that Store IAP moves
|
||||
pricing into fixed Store tiers, so the "floor" (`~$69` per `MONETIZATION.md`) and the
|
||||
"don't break the launch-price promise" note now refer to a different storefront.
|
||||
- **TASK 49 — chat profanity filter** — queued, not blocked, size S. Local, on-device,
|
||||
**non-persistent**, opt-in, **user-supplied word list (never a hardcoded slur list)**, and it
|
||||
must **never match the SuperChat amount or reward fields** (financial data, Store 10.5.5).
|
||||
|
||||
@@ -14,13 +14,18 @@
|
||||
|
||||
## 1. Bottom line
|
||||
|
||||
**✅ ROUTE DECIDED 2026-09-27 — the creator chose route A: Microsoft Store, MSIX package,
|
||||
Store IAP.** The research below is what the decision was made from, and it stays as the
|
||||
audit trail so the choice is never re-litigated. The executable checklist is
|
||||
`TASKS/task-48-distribution-msix.md`; the ruling and the criteria behind it are in that
|
||||
file's item 0.
|
||||
|
||||
**MSIX packaging is viable.** One real blocker, and it is a code change we should want
|
||||
anyway (§4). Three technical blockers that normally kill a Store submission — drivers,
|
||||
per-user services, elevation — we **do not trip** (§7).
|
||||
|
||||
**The decision is NOT made.** The route is open; this file records the options and their
|
||||
costs so the decision can be made from a clear page. `Distribution.md` holds the older
|
||||
plan and contains **one factually dead claim** — see §2.
|
||||
**Nothing else is open on distribution.** The only number still unverified is the Store
|
||||
revenue-share rate (§11 item 4), which is a *pricing* input, not a distribution one.
|
||||
|
||||
---
|
||||
|
||||
@@ -74,20 +79,28 @@ Also worth knowing before budgeting:
|
||||
| **C** | Polar file hosting | Polar | $150–300/yr | no |
|
||||
| **D** | Store EXE (10.2.9) | Polar | $150–300/yr | no |
|
||||
|
||||
**✅ A was chosen (2026-09-27)** — the creator's criteria were "zero headaches, minimal
|
||||
maintenance (for me) while still providing accountability and a reasonably easy upgrade
|
||||
flow," and A is the only option where *every* one of those is solved by handing the work to
|
||||
Microsoft rather than to a certificate vendor. The rest of this section stays as the record
|
||||
of what was rejected and why, so the decision is not reopened by a later session that
|
||||
remembers only that "certs cost $150/yr."
|
||||
|
||||
**A** is the only one where Polar becomes unnecessary — the Store handles payment,
|
||||
entitlement, and refunds, and you would delete `PolarLicenseService` and the
|
||||
customer-portal plumbing. That is a *distribution* choice that happens to subsume
|
||||
licensing.
|
||||
entitlement, and refunds, and `PolarLicenseService` and the customer-portal plumbing are
|
||||
deleted. That is a *distribution* choice that happens to subsume licensing.
|
||||
|
||||
**B** is the compromise worth serious consideration: the Store solves the SmartScreen
|
||||
problem and the annual cert bill while Polar stays the licensing system and we keep 100%
|
||||
of revenue. Cost is two systems to maintain.
|
||||
**B** is the compromise that was **not** taken: the Store would have solved the SmartScreen
|
||||
problem and the annual cert bill while Polar stayed the licensing system. Rejected because
|
||||
it keeps a licensing backend, a customer portal, activation limits, and an offline-grace
|
||||
machine alive — the exact maintenance the ruling was made to eliminate.
|
||||
|
||||
**C** is the status quo already sketched in `Distribution.md:14` / `:296` — Polar hosts the
|
||||
signed exe (10GB, signed personal download URLs, SHA-256 included). **The Store is not
|
||||
needed for delivery at all.** The Store's only unique value is *free Microsoft signing with
|
||||
no SmartScreen warning*, and its cost is MSIX packaging work, Store review, and a public
|
||||
listing.
|
||||
**C** is the status quo previously sketched in `Distribution.md:14` / `:296` — Polar hosts
|
||||
the signed exe (10GB, signed personal download URLs, SHA-256 included). **The Store is not
|
||||
needed for delivery at all**; its only unique value is *free Microsoft signing with no
|
||||
SmartScreen warning*, and its cost is MSIX packaging work, Store review, and a public
|
||||
listing. Note the irony: C is the only option with a recurring cost *and* the only one where
|
||||
the creator maintains payment plumbing themselves.
|
||||
|
||||
**D is dominated** — strictly worse than both A and C: cert required anyway, silent install
|
||||
required, and we maintain the versioned download URL. Documented in one line so it is
|
||||
|
||||
@@ -5,40 +5,73 @@
|
||||
> 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)
|
||||
**Status:** 🔶 In progress — **✅ ROUTE DECIDED 2026-09-27: Microsoft Store MSIX + Store IAP.**
|
||||
Polar is deleted; every licensing subsystem goes with it.
|
||||
|
||||
**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
|
||||
## 0. ✅ THE DECISION — Microsoft Store, MSIX, Store IAP (creator ruling 2026-09-27)
|
||||
|
||||
Pick one:
|
||||
**Creator's stated criteria, verbatim: "zero headaches, minimal maintenance (for me) while
|
||||
still providing accountability and a reasonably easy upgrade flow."**
|
||||
|
||||
| # | 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 |
|
||||
**Ruling: distribute as an MSIX package through the Microsoft Store, and take payment through
|
||||
Store IAP.** All four criteria are satisfied by the same mechanism:
|
||||
|
||||
**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*.
|
||||
| Criterion | How MSIX + Store IAP satisfies it |
|
||||
|---|---|
|
||||
| Zero headaches | **$0/yr** — Microsoft holds the signing certificate, the reputation, and the installer. No cert, no HSM, no annual renewal, no SmartScreen ramp |
|
||||
| Minimal maintenance | Microsoft handles **updates**, **payments**, **entitlements**, **refunds**, and **customer support**. Nothing to run |
|
||||
| Accountability | Microsoft reviews every submission — that *is* the accountability layer, and it is a real one |
|
||||
| Easy upgrade flow | Store auto-update. **Velopack, the update URL, and the DO droplet all go** |
|
||||
|
||||
Cost table, full detail, and the dead-EV correction: `research-store-certification.md` §2–3.
|
||||
### The consequence that makes this cheap: the entire licensing subsystem is deleted
|
||||
|
||||
Choosing Store IAP over Store+Polar is what makes "minimal maintenance" real. Keeping Polar
|
||||
would have left the creator maintaining a licensing backend, a customer portal, activation
|
||||
limits, and an offline-grace machine — the exact burden the ruling was made to avoid.
|
||||
|
||||
**Dead code / deleted concepts (TASK 10 is now a teardown, not a build):**
|
||||
- `Services/PolarLicenseService.cs` — HTTP validation, the swallowed network failures, the
|
||||
ignored `expires_at`
|
||||
- `Helpers/PolarLicense.cs` — the record type
|
||||
- `ViewModels/MainViewModel.License.cs` — `PremiumUrl`, the customer portal, the
|
||||
`OfflineGracePeriod = 14 days` subscription-era artifact, renewal/lapse copy
|
||||
- `Controls/OverlayHost.xaml` — the incorrect "Polar unlocks alerts" copy resolves itself
|
||||
- `ytLive.csproj:92` Velopack `PackageReference` + `App.xaml.cs:3,38-46` — see item 3
|
||||
- The `MONETIZATION.md` provider sections (gitignored — local file)
|
||||
|
||||
**What replaces it:** `IsPremium` is derived from the **Store entitlement** instead of a
|
||||
remote HTTP call. One bit, locally cached, refreshed by the OS. The offline-grace machine
|
||||
disappears because the OS supplies license state — and with it the whole class of
|
||||
"network flaky → app thinks I'm expired" bugs.
|
||||
|
||||
⚠️ **The watermarks posture is unchanged:** free gets everything; the branding flash stays the
|
||||
ONLY paid delta (TASK 36 item 2). Store IAP changes how the bit is *obtained*, never what it
|
||||
*gates*.
|
||||
|
||||
### Still to verify (does not block packaging work)
|
||||
|
||||
- ☐ **Current Store revenue-share terms.** ⚠️ **Do not assume any percentage** — the terms have
|
||||
moved more than once and smaller indie apps sometimes qualify for better rates. **Verify
|
||||
before setting a price.** Microsoft also requires that any IAP products and their pricing be
|
||||
declared in Partner Center.
|
||||
- ☐ **Store IAP tier shape** — one-time vs subscription. The creator's one-time-vs-both
|
||||
question is still open; the storefront it is sold through is now decided.
|
||||
- ☐ Individual vs Company Partner Center account (10.8.3 / 10.14 — see
|
||||
`research-store-certification.md` §11 item 1). **Get this right before enrolling**; a
|
||||
Store+IAP product needing financial info for primary functionality would require Company,
|
||||
but a free product with a paid upgrade tier is the normal consumer shape and is fine on an
|
||||
individual account.
|
||||
|
||||
---
|
||||
|
||||
## 1. ⛔ Bundle ffmpeg instead of downloading it — **do this on EVERY route**
|
||||
|
||||
**Not conditional on the Store. This is worth doing regardless.**
|
||||
**This is item 1 because it is genuinely first** — it fixes a user-facing failure on its own and is a hard certification gate.
|
||||
|
||||
`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
|
||||
@@ -66,14 +99,12 @@ 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.
|
||||
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
|
||||
- `uap10:TrustLevel="mediumIL"` and `uap10:RuntimeBehavior="packagedClassicApp"` — the
|
||||
latter 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
|
||||
@@ -82,7 +113,7 @@ so this is purely additive.
|
||||
|
||||
## 3. ☐ Remove Velopack — 3 edit sites
|
||||
|
||||
Only if the Store is chosen (the Store handles updates). Trivially removable; the code was
|
||||
The Store handles updates, so this is simply **deleted**. Trivially removable; the code was
|
||||
written defensively for exactly this.
|
||||
|
||||
- `ytLive.csproj:92` — `<PackageReference Include="Velopack" Version="1.2.0" />`
|
||||
@@ -103,14 +134,15 @@ relevant check: the app must start promptly, stay responsive, and shut down grac
|
||||
|
||||
**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)
|
||||
- ☐ **The IARC age-rating questionnaire** (10.11.1) — general audience, 12+ territory
|
||||
- ☐ **Declare the IAP products and their pricing** in Partner Center (required for Store IAP)
|
||||
- ☐ Note that the product is **general audience, not directed at under-13s**
|
||||
- ☐ The 11.12 UGC position is **less load-bearing now that Polar is gone** — the strong part of
|
||||
the original argument was "we render transiently, persist nothing, and provide no
|
||||
user-to-user communication surface," which is *unaffected*. State it in full anyway; the
|
||||
reasoning and the Q1-2026 YouTube enforcement numbers are in
|
||||
`research-store-certification.md` §9
|
||||
- ☐ The **YouTube age-gate argument** — the operator is 13+ by construction (§8)
|
||||
|
||||
**On `llamachile.shop`:**
|
||||
|
||||
@@ -122,13 +154,11 @@ relevant check: the app must start promptly, stay responsive, and shut down grac
|
||||
|
||||
**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
|
||||
- ☐ Review the **Individual vs Company** account question before enrolling
|
||||
|
||||
## 6. ☐ The full-trust recording invariant — **comment lands WITH this work**
|
||||
|
||||
|
||||
@@ -1794,14 +1794,34 @@ published decisions (recorded in `TASKS/task-43-native-alerts.md`):
|
||||
|
||||
---
|
||||
|
||||
## Windows packaging & distribution (2026-09-27 — research settled, route NOT decided)
|
||||
## Windows packaging & distribution (✅ DECIDED 2026-09-27 — Store MSIX + Store IAP)
|
||||
|
||||
Full analysis: `TASKS/research-store-certification.md` (Store Policies **7.20**, effective
|
||||
2026-10-22 — re-check the version before acting). Executable checklist:
|
||||
`TASKS/task-48-distribution-msix.md`. **The route is the creator's decision** (Store MSIX +
|
||||
Store IAP / Store MSIX + Polar / Polar-hosted + own cert / dominated Store-EXE). Do not build
|
||||
packaging work before that call, and do not re-derive the options — they are tabulated in the
|
||||
research file §3.
|
||||
**The distribution route is settled: Microsoft Store, MSIX package, Store IAP.** Creator's
|
||||
criteria, verbatim: *"zero headaches, minimal maintenance (for me) while still providing
|
||||
accountability and a reasonably easy upgrade flow."* Route A was chosen because it 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 live in
|
||||
`TASKS/research-store-certification.md` §3 — **read that before reopening the question**, not
|
||||
before re-deriving it. Executable checklist: `TASKS/task-48-distribution-msix.md`.
|
||||
|
||||
**Consequences that are architecture, not packaging detail:**
|
||||
|
||||
- **⛔ Velopack and the update URL are deleted** — the Store auto-updates. 3 edit sites,
|
||||
`ytLive.csproj:92` + `App.xaml.cs:3,38-46`. The self-hosted DO droplet dies with it.
|
||||
- **⛔ The Polar licensing subsystem 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 in `OverlayHost.xaml`. **`IsPremium` is derived from the
|
||||
Store entitlement**, not a remote HTTP call. That deletes the entire "network flaky → app
|
||||
thinks I'm expired" bug class along with the offline-grace machine.
|
||||
- **⛔ Bundle ffmpeg — no runtime downloads** (Store policy 10.2.2; also the 2026-09-01 404).
|
||||
See the FFmpeg locator section above. **This is the first code unit.**
|
||||
|
||||
**What does NOT change: the monetization posture.** Free gets everything; the branding flash
|
||||
stays the **only** paid delta (`TASK 36` item 2). Store IAP changes how `IsPremium` is
|
||||
*obtained*, never what it *gates*. `Monetization` above still governs.
|
||||
|
||||
### ⛔ Durable invariant: full trust, or recording silently breaks
|
||||
|
||||
@@ -1833,15 +1853,15 @@ line item) and private keys must live on an **HSM or hardware token**. The **Sto
|
||||
needs no certificate at all** — Microsoft re-signs. `Distribution.md` §4.3 was corrected
|
||||
2026-09-27; it previously recommended EV.
|
||||
|
||||
### Distribution and licensing are independent
|
||||
### Distribution and licensing are independent — but the ruling collapsed them
|
||||
|
||||
A **Store-distributed** app may still verify licenses with **Polar** (policy 10.8.1
|
||||
explicitly permits a secure third-party purchase API for non-game PC products; the box is
|
||||
ticked in Partner Center). So "should we use the Store?" does **not** imply "should we drop
|
||||
Polar?" — the only combination that removes Polar is Store + Store IAP, and that is a
|
||||
*licensing* choice which happens to ride on a *distribution* decision. (The monetisation
|
||||
posture itself is unchanged and lives in the Monetization section above: free gets
|
||||
everything; the branding flash is the only paid delta.)
|
||||
A **Store-distributed** app *may* still verify licenses with **Polar** (policy 10.8.1
|
||||
explicitly permits a secure third-party purchase API for non-game PC products), so "should we
|
||||
use the Store?" did not logically imply "drop Polar?" — route B was a real option. **The
|
||||
creator chose route A instead**, so Polar is gone. Recording the distinction because it was
|
||||
the reason the decision was thought-through rather than assumed: the licensing choice rode on
|
||||
a distribution decision, and the *only* route that removed the licensing backend was the one
|
||||
that also removed the certificate. Both burdens had the same single solution.
|
||||
|
||||
### ⛔ "Only when the user says so" is enforced by Windows, not by us
|
||||
|
||||
|
||||
Reference in New Issue
Block a user