Files
LlamaCasty/TASKS/research-store-certification.md
gramps e7cded6879 docs: pricing ruled — $10/mo + $400 lifetime, and the 15% fee is verified for subscriptions
Reconcile the pending doc edits with the creator's actual ruling, and close the
revenue-share question that was blocking the monthly price.

Verified from the App Developer Agreement v8.10 PDF itself (downloaded and
text-extracted, not a search excerpt). Section 6(b) has only three tiers:
6(b)(i) 15% for Apps and their In-App Products *not listed in* 6(b)(iii);
6(b)(ii) 12% Games-only; 6(b)(iii) 30% for Xbox console apps/games, Xbox
non-subscription IAP, and Windows 8/Phone 8. LlamaCasty is a Windows PC App,
so 6(b)(i) governs BOTH tiers -- there is no subscription surcharge. The
agreement's own changelog (v8.0, Oct 26 2017) states it outright: "implement
the 85/15 revenue share for non-Game subscriptions."

  => $10/mo nets $8.50 (~$102/yr); $400 lifetime nets $340.

Also confirmed: the 15% applies after VAT/GST (Net Receipts definition),
payouts are monthly above a $50 threshold, and no better small-indie rate
exists in the standard terms.

Creator ruling recorded: $10/mo subscription or $400 lifetime, no annual, no
.99. This supersedes the 2026-09-21 one-time $29 -> $49 model.

Two obligations ADA 6(h) attaches to the recurring tier, recorded because they
change its risk profile and are the reason lifetime is the hedge: we must
fulfil the subscription for the entire period as marketed (on breach Microsoft
may refund the full amount plus taxes in its sole discretion), and raising the
price disables auto-renew -- so $10 is effectively locked for the product's life.

Stale facts fixed in the same change rather than appended:
- research-store-certification.md: IARC was 11.11.1/11.11.2 in one table and
  10.11.1 in another; corrected to 10.11.x.
- research-store-certification.md: policy 10.8.1/10.8.2 still asserted "Polar
  explicitly permitted" and "tick the third-party purchase box". Void now that
  Store IAP is the route and Polar is being torn down.
- task-48: the working YouTube demo account (10.3.1) was accidentally dropped
  from the certification list during the Store-IAP edit. Restored -- a reviewer
  cannot use the app without one.
- MyMistakes.md: the verified-fact-vs-decided-outcome lesson now closes its
  loop (the creator did rule the way the research pointed), and records the
  over-correction that followed.

Docs-only. No code, no build, no tests.
2026-09-27 15:02:25 -07:00

27 KiB
Raw Permalink Blame History

ytLlive — Windows Store & code-signing certification research (authoritative)

Catalog: TASKS.md · memory map: schema.md · distribution plan: Distribution.md

Researched 2026-09-27 against Microsoft Store Policies version 7.20 (published 2026-09-15, effective 2026-10-22) and the MSIX packaging docs. Policy version moves — re-check the version before acting on any line here.

This file is the "why". The executable checklist lives in task-48-distribution-msix.md. No code changed as a result of this research; it only decides what task-48 will eventually do.


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).

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.


2. ⚠️ The one line in Distribution.md that is now wrong

Distribution.md:318 currently says:

Buy an EV (Extended Validation) code-signing certificate from DigiCert or Sectigo ($200-400/year). EV certificates get instant SmartScreen reputation; DV/OV certs trigger SmartScreen warnings for months.

The EV half of that is false. Microsoft removed the SmartScreen instant-bypass for EV certificates in March 2024. An EV-signed file now accumulates reputation exactly the way an OV-signed file does. Paying $400+/yr buys precisely what paying $150 buys.

schema.md rule 4: stale facts get FIXED, not appended. Corrected in Distribution.md (2026-09-27).

Also worth knowing before budgeting:

  • Cert validity is capped at 460 days (CA/B Forum CSC-31, effective 2026-03-01). This is a recurring annual line item, not a one-time purchase.
  • Private keys must live on an HSM or hardware token (CA/B rule since 2023-05). Budget for the token or a cloud HSM.
  • Signing does not clear the warning on day one. A valid cert stops the malware warning immediately; the "unrecognized publisher" warning clears as SmartScreen accrues reputation from real download volume. Expect a ramp on every route.
  • Third-party AV vendors layer their own reputation blocking on top of SmartScreen, so signed-but-new can still warn on consumer machines. The Store route is the only one that is warning-free, because Microsoft holds the reputation.

3. Signing economics

Route Cert cost SmartScreen Install UX Notes
Microsoft Store, MSIX package $0 — Microsoft re-signs No warning Normal Store review, public listing, updates handled by Store
Microsoft Store, EXE/MSI (10.2.9) $150–300/yr — your own cert Warning ramp Silent install only Store does NOT re-sign; you maintain a versioned URL
Direct + OV cert $150–300/yr Warning ramp Yours Worldwide availability
Direct + Azure Artifact Signing ~$9.99/mo ≈ $120/yr Warning ramp Yours Individuals: USA/Canada only. Identity validation required
Direct + EV cert $400+/yr Same as OV Yours Do not buy. No benefit since March 2024
Unsigned direct $0 Strong block Yours Unusable for public download

Four real combinations

# Distribute Verify payment Cert Revenue cut
A Store Store IAP $0 yes
B Store Polar $0 no
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 PolarLicenseService and the customer-portal plumbing are deleted. That is a distribution choice that happens to subsume licensing.

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 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 never re-litigated.


4. ⛔ The one real blocker: 10.2.2 (dynamic code inclusion)

Policy 10.2.2:

Your product must not attempt to fundamentally change or extend its described functionality or introduce features or functionality that is in violation of Store Policies through any form of dynamic inclusion of code. Your product should not, for example, download a remote script and subsequently execute that script in a manner that is not consistent with the described functionality.

What we do today: Services/Encoder/FfmpegLocator.cs:37-38 pins a GitHub release URL, and LocateAsync downloads the zip (line 69), extracts it (line 73), and the encoder then executes that binary. On a cold cache the app downloads an unsigned executable from the internet and runs it.

That is the pattern 10.2.2 names. The word is "script," so a narrow reviewer might quibble about a PE binary — but 10.2.3 reinforces it, and 10.2.9 separately requires all PE files to chain to the Microsoft Trusted Root Program, which a downloaded BtbN build does not.

The fix: bundle ffmpeg.exe + ffprobe.exe + the libav*.dll family inside the package instead of downloading. No dynamic code inclusion, so 10.2.2 is satisfied.

This is a fix we want regardless of route. 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 that entire class of cold-start failure permanently, and it also removes the startup network dependency.

The LGPL-shared licensing reasoning in FfmpegLocator is unaffected — dynamic linking was the deliberate choice for LGPL §6 compliance, not for download avoidance. Confirm THIRD-PARTY-NOTICES.txt (already shipped) covers the bundled build.

What I got wrong initially: I believed MSIX might forbid launching a bundled executable. It does not — see §5.


5. MSIX technical facts (full trust vs AppContainer)

MSIX packages run at one of two trust levels, chosen by the manifest:

Trust level Behavior
mediumIL / full trust Same permissions as a standard desktop app. Package identity + some file/registry virtualization. Can spawn child processes. ← this is what a WPF broadcast tool wants
appContainer Strictly isolated. Process and children see only explicitly granted resources. File/registry virtualized.

A packaged WPF app declaring runFullTrust runs at medium integrity — it is not an AppContainer. Bundling and launching ffmpeg from inside the package is therefore fine. This is the "Desktop Bridge" / packagedClassicApp model.

Critical file-write consequence: "Writes to user profile locations (such as AppData) are redirected to per-package locations for AppContainer apps, or pass through for full-trust apps." The package install folder itself is read-only.

Manifest this app needs:

  • rescap:Capability Name="runFullTrust" — medium integrity
  • webcam and microphone capabilities
  • uap10:TrustLevel="mediumIL"
  • uap10:RuntimeBehavior="packagedClassicApp"

The full-trust recording invariant (durable architectural fact)

ViewModels/MainViewModel.Recording.cs writes recordings to %USERPROFILE%\Downloads or SpecialFolder.MyVideos (DefaultRecordFolder(), line 173–179), with Microsoft.Win32.OpenFolderDialog for overrides (ChooseRecordFolder(), line 151). The whole temp-write-then-move lifecycle stays inside one directory (line 131–132).

This works only because we are full trust. At mediumIL those writes pass through unvirtualized and OpenFolderDialog is an ordinary Win32 folder browser with no capability token involved. No broadFileSystemAccess is needed.

⚠️ If anyone ever flips the manifest to appContainer, recording silently breaks — Directory.CreateDirectory and File.Move start resolving to a per-package virtualized location. A code comment belongs at DefaultRecordFolder() when the manifest lands, not before (a comment describing a manifest that does not exist is worse than no comment).


6. Store policy verdicts — what binds, what doesn't

Policy 7.20. "Binds" = must be satisfied to submit.

⛔ Binds — blockers or real work

Policy Requirement Our status
10.2.2 No dynamic code inclusion (download-and-execute) ❌ VIOLATED — see §4. Fix: bundle ffmpeg
10.3.1 Login required → supply a working demo account in certification notes ☐ TODO — we require YouTube sign-in
10.5.1 Privacy policy mandatory; URL in Partner Center. Desktop Bridge + Win32 always need one. Must state what PI is accessed/collected/transmitted, how used/stored/secured, types of parties disclosed to, controls the user has, compliance with law, and be kept current ☐ TODO — llamachile.shop can host it
10.5.4 Collect/store/transmit PI securely with modern cryptography ✅ DPAPI for tokens, HTTPS to YouTube
10.5.5 No highly sensitive PI (health/financial) unless tied to functionality + express consent ⚠️ SuperChat/reward path touches financial data — keep display-text-only processing, never log payloads
10.6 Declared capabilities must relate to the product's functions; must not circumvent OS checks ✅ camera/mic for a broadcast tool is self-evident; must use standard MF/DShow/WASAPI paths
10.7 Localize for every declared language; declare English only ☐ Keep the manifest to one language
10.1.1 Title must be unique, no marketing or descriptive text, no extraneous keywords Store name is exactly LlamaCasty
10.1.3 Search terms: max 7, no pricing terms, no other product titles unless you published them ☐ Cannot list OBS or StreamYard as search terms
10.1.4 Distinct informative metadata + active Store presence ☐ Listing must not be a stub
10.2.7 Must enable clean uninstall ☐ MSIX gives this free
10.4.2 Start promptly, stay responsive, shut down gracefully, survive native API exceptions ✅ AppLog + dispatcher handlers exist
10.11.1 IARC age-rating questionnaire required ☐ General-audience streaming tool, 12+ territory
10.11.2 Keep the rating accurate as features change ☐ Re-visit if audience-facing features shift
11.12 User Generated Content — see §9 ⚠️ Judgment call, documented not built
10.8.1 Non-game PC products may use a secure third-party purchase API or Store IAP ✅ Superseded 2026-09-27: we chose Store IAP, not Polar. The third-party-purchase path is no longer the plan
10.8.2 Third-party purchase: identify provider, authenticate user, obtain confirmation, PCI DSS, note in Partner Center ⛔ Void — Polar is being torn down (TASK 10). Store IAP is the Microsoft commerce engine, so the third-party-provider/PCI-DSS obligations do not apply
10.8.3 Individual accounts cannot require financial info for primary functionality; requiring it forces a Company account ⚠️ Open question — see §11
10.14 Individual accounts usually fine for a solo dev; Company required if the product needs financial info for primary functionality, or a consumer would read the name as a business ⚠️ Same question as 10.8.3
10.8.7 Pricing must follow the FTC Guides Against Deceptive Pricing and must not be irrationally high vs. features ☐ A pricing decision, not a code task
10.5.8 Must follow applicable safety/privacy laws re children ☐ Follow-the-law obligation — see §8
10.1.5 May enable acquisition of your other Store products or add-ons N/A

✅ Does NOT bind — recorded so it is never re-raised

Policy Why it doesn't apply
10.10 (Advertising) Ads are injected server-side by YouTube after the RTMP handoff. LlamaCasty displays no ads, renders no ad SDK, and controls no ad decision. Every 10.10 clause is conditioned on ads your product displays. Not applicable.
10.2.5 (Store-only install) 7.20 applies "installed and updated only through the Store" to game products and Xbox console products. A non-game PC app is not locked to MSIX. (The 2018 v7.7 wording said "all of your apps" — that language has been narrowed.)
10.2.3 (secondary software) ffmpeg enhances the product's functionality, and once bundled it is not "offered to install" as separate software
10.2.8 (Windows settings) RegisterHotKey and standard DShow/MF paths are supported APIs. No accessibility-API or undocumented-API tricks
10.10.1 / 10.10.2 Follows from 10.10 — no ads displayed
11.13 (Storefront) Not a storefront
11.14 (Gambling) Not applicable
11.15 (Child Safety) Prohibits products enabling exploitation/grooming/sexualization/sextortion/trafficking, and adult-themed products targeting children. A broadcast tool is not in this class. Nothing LlamaCasty does creates, uploads, or distributes child-exploiting content
10.5.2 We do not publish a customer's PI to an outside service beyond the stream they themselves broadcast
10.5.7 (location) No device location access
10.2.9 Only if we chose the Store EXE route. It would bind — see §3, route D is dominated

Certification mechanics

  • Technical compliance is tested by the Windows App Certification Kit before submission.
  • Certification takes up to 3 business days; the listing appears ~15 min after publish.
  • MSIX package requirements: SHA2-256 block map, StoreManifest, 25 GB max.
  • Partner Center account: individual vs company — see §11.

7. MSIX disqualifiers we do NOT trip

Verified by grep across the codebase 2026-09-27. The MSIX prep docs list four hard disqualifiers; all four are clear:

Disqualifier Our status
"Your application requires a Windows driver. MSIX doesn't support Windows drivers." ✅ We consume DShow filters, we don't install a driver. (A creator's third-party Virtual Capture Device is their hardware, not something we ship.)
"Your application requires a user Windows service. MSIX doesn't support per-user Windows services." ✅ No service installation anywhere
Apps requiring elevation for any functionality are not accepted ✅ No requireAdministrator / highestAvailable / UAC manifest
"Your app's modules are loaded in-process to processes that are not in your Windows app package" (shell extensions, etc.) ✅ No shell extensions, no in-process module loading, no jump lists

Also verified: there is no .manifest file in the repo at all today, so packaging is purely additive — a new Package.appxmanifest plus a packaging project. The existing unpackaged exe keeps working.

Other store rules worth knowing while listing

  • 10.1.4 requires an active Store presence — the listing cannot be a placeholder.
  • 10.7 — declare English only, or localize the description into every declared language.
  • 10.9 — the app must stay functional when notifications are disabled. Our toast stack must not be load-bearing.

8. Minors, COPPA, and the age question

The operator is 13+ by construction

YouTube Terms of Service:

  • "You must be at least 13 years old to use the Service"
  • 13–17 permitted with parent/guardian permission
  • Under 13 cannot create an account — exceptions are YouTube Kids and supervised accounts via Family Link or Google Workspace for Education
  • Google Accounts: 13 is the minimum to self-manage
  • The floor varies by region — at least one YouTube ToS variant states 14, tracking EU digital-consent ages. Treat it as 13–14, not a fixed 13.

Why this does real work: LlamaCasty requires a YouTube account to operate, because streaming requires one. So the person running the broadcast is 13+ by construction. A COPPA theory premised on "a service collecting personal information from children under 13" has no purchase against the operator — and that is true by construction, not by promise. That is the cleanest sentence available for a certification note.

The residual exposure

The viewers may still be under 13 on supervised/family-linked accounts, so the chat ingestion point does not fully disappear. It weakens substantially, because:

  • Live chat is restricted/disabled on supervised YouTube kid accounts
  • YouTube moderates the messages before we ever see them (§9)
  • Our mitigation: retain nothing — parse, display, discard (see task-49)

COPPA is very unlikely to bind

COPPA applies to child-directed services and to operators collecting PI from children under 13. The three-factor test (subject matter, audience, evidence of child focus) is nowhere near met by a broadcast tool aimed at a gaming audience. 10.5.8 is a follow-the-law obligation, not a be-child-safe obligation — it says "follow all applicable laws," it does not impose COPPA duties on us directly.

But note the enforcement trend (FTC, September 2025 Apitor settlement): operators are held responsible for what third-party components collect on their behalf, and the FTC expects a real inquiry into third-party collection practices. That case was about an SDK; the principle is what matters for a chat pipe. This is a documentation obligation, and the answer is "we integrate no third-party analytics or ad SDKs, and we persist no chat or reward payloads."


9. 11.12 User Generated Content — the judgment call

11.12 triggers on "content that users contribute to a product and which can be viewed or accessed by other users in an online state." Chat is literally that. If a reviewer classifies the chat surface as UGC, the requirements are:

  1. Published terms of service, code of conduct, and/or content guidelines for UGC, accessible in-product and on your website
  2. A means for users to report inappropriate/illegal/harmful UGC to the developer for review, and/or proactive detection
  3. Respect user safety, parental, and content privilege settings, and handle restricted access gracefully
  4. Remove or disable UGC when requested by Microsoft
  5. Disclose that content is not created by the developer/publisher where appropriate

The argument: YouTube discharges the moderation obligation upstream

11.12 asks for How YouTube already covers it
Published ToS / CoC / content guidelines Community Guidelines, linkable from our listing
A reporting mechanism Creator-side chat reporting; YouTube enforces
Respect parental / privilege settings YouTube's restricted + supervised accounts
Remove/disable on request YouTube removes; we never hosted the original
Disclose third-party UGC origin Visibly YouTube chat; YouTube is platform of record

And the enforcement is demonstrably real. YouTube's transparency report for Jan–Mar 2026: approximately 1.6 billion comments removed in a single quarter, with child safety the #2 removal reason at 124,624,293 (hateful/abusive 15,977,127; harassment/cyberbullying 71,326,861; spam/scams 1.31 B).

The certification-note sentence:

UGC is mirrored from YouTube, which moderates it at industrial scale upstream. We render transiently, persist nothing, and provide no user-to-user communication surface.

The "persist nothing" half is ours to keep — and it is the same property task-49 (profanity filter) needs. Convenient, not coincidental.

Our read: 11.12 targets products hosting a UGC community. A chat mirror rendered from YouTube — where YouTube is the platform of record and already supplies reporting, age-gating, and parental controls — is arguably not "our" UGC. This is a judgment call, and we resolve it by documenting the position rather than building features on a guess. State the reasoning in the certification notes; Microsoft reads them.

The documentation we owe regardless

Artifact Requirement
Privacy policy on llamachile.shop 10.5.1. 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, nothing is fetched at runtime
Code of conduct + content guidelines 11.12 / 11.15. General audience; explicitly not directed at under-13s
IARC age-rating questionnaire 10.11.1
Certification notes the 11.12 reading, the YouTube age-gate argument, the Polar third-party purchase box, the demo account

10. Camera, microphone, and "only when the user says so"

We do not write that certification. Windows does it — and the Store forbids us from bypassing it. Three layers:

  1. Policy 10.6 — "You must not circumvent operating system checks for capability usage." Route through the standard OS consent path; do not roll our own.
  2. Windows privacy settings — Settings → Privacy & security → Camera / Microphone. Since Windows 10 1903, "Let desktop apps access your camera/microphone" is the toggle that governs a Win32 broadcast app. Turn it off and the app loses access. That is the "explicit user direction" mechanism, enforced by the OS, not by our EULA.
  3. Hardware/OS indicators — camera light (or a notification when there is no light) and a microphone icon in the taskbar tray. Automatic. The OS is the disclosure mechanism, so we get neither credit nor blame from it.

⚠️ The open question — measure, don't assume

Microsoft's own support page carries this caveat:

Desktop apps may not always appear in the list of apps available to the Camera and Microphone settings pages or might still be able to access your camera or microphone even when these settings are turned off.

Untested: does the Win11 desktop-app camera toggle reliably gate a DShow webcam and a capture card?

  • If it does gate them, we can make privacy-forward claims after verifying.
  • If it does not, that is not a Store certification failure — we declared webcam honestly and use supported APIs — but it is a real user-trust issue, and we must not write privacy-forward marketing copy on the assumption that it works.

Tracked as an open item in TASKS.md. A guard note in MARCOM.md blocks privacy-forward copy until it passes.


11. Open questions

  1. Individual or Company Partner Center account? (10.8.3 / 10.14.) Individual accounts are "usually appropriate for a single developer working on their own," and a Company account is required if the product requires financial account information for primary functionality. Polar collects payment externally and we never ask the user for card details, so we look like a clean individual case — but it is a question for Partner Center, and getting it wrong means re-enrolling.
  2. Does the desktop-app camera toggle gate DShow? (§10) — gates the MARCOM.md privacy claim.
  3. MSIX write behavior under a real package identity — full trust passes writes through per the docs, but worth confirming on a real packaged build before trusting it with recordings.
  4. Store revenue-share terms — do not plan on any specific percentage. The terms have moved more than once and small indie apps sometimes qualify for better rates. Verify current terms and conditions before pricing against them.
  5. liveBroadcasts.insert requires status.selfDeclaredMadeForKids (COPPA) — already known, see research-youtube-api.md item 1. Confirm the dialog wording is right for a tool that is never child-directed.

12. Profanity filter — design constraints (feeds task-49)

YouTube's Community Guidelines carry a specific Vulgar language policy under "Sensitive content," alongside nudity/sexual content, child safety, and self-harm. So profanity is a named policy surface, not an edge case.

Three external reasons it earns a slot, plus the real one:

  1. YouTube treats it as policy-relevant, so 11.12's "proactive detection" language has something to attach to
  2. Competitive parity — overlay tools in this lane generally offer it
  3. It is a reasonable reading of 11.12's proactive-detection language
  4. The real reason: we control what gets projected on screen. That is the creator's call, not YouTube's.

Four constraints, because they protect the privacy story rather than complicate it:

  1. Local and on-device only. No server, no telemetry of message content, nothing leaves the machine.
  2. Non-persistent. Filter at ingest, discard the raw text, keep only the display string. Same property that makes the 11.12 answer in §9 strong.
  3. User-supplied word list, opt-in, stored locally. Not a hardcoded slur list baked into the binary — that is an unpleasant artifact, generates false positives across dialects and languages, and becomes our problem the moment someone extracts it. A user-curated list is also simply more useful: streamers know their community's euphemisms and we do not.
  4. Match display text only. Never the SuperChat amount or any reward-event field — those are financial data under 10.5.5, and matching on them would be a real mistake.

The existing alert box already has a ticker and three display methods (Controls/OverlayHost.xaml, ViewModels/MainViewModel.Chat.cs), so there is probably a single insertion point rather than scattered call sites. Verify before building.