TASK 48 slice 3: the self-updater is deleted - the Store updates the app
The creator's ruling (2026-09-27) is Store MSIX + Store IAP, so Microsoft delivers the updates and the in-app updater is gone rather than parked. This is a COMPLIANCE action, not cleanup: the Velopack bootstrap downloaded and executed a payload, which Store policy 10.2.2 does not permit. Three edit sites, as planned: the PackageReference in ytLive.csproj, 'using Velopack;' in App.xaml.cs, and the bootstrap block. The self-hosted DigitalOcean update-URL droplet dies with it. Guard: ytLive.Tests/StorePackagingTests.cs - the ONE test asserts the app project references no updater package (Velopack/Squirrel/NetSparkle/AutoUpdater/WinSparkle) and that no app source file uses the updater API. The check matches CODE (a using directive, a type usage), not a bare word, so a file's prose may still name what it deliberately does not do. Smoke-tested after the removal: MainWindow loaded, 0 exceptions in startup.log. Full suite 437/437, 0 warnings.
This commit is contained in:
+2
-14
@@ -1,6 +1,5 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using Velopack;
|
||||
using ytLive.Helpers;
|
||||
|
||||
namespace ytLive;
|
||||
@@ -31,19 +30,8 @@ public partial class App : Application
|
||||
// the per-build GUID is forensic only and lands here.
|
||||
AppLog.Write($"Build {ytLive.Helpers.BuildStamp.Id} (compiled {ytLive.Helpers.BuildStamp.BuiltLocal})");
|
||||
|
||||
// Velopack auto-update bootstrap — checks for updates on startup and
|
||||
// applies them (the app restarts automatically if an update is found).
|
||||
// Update URL is configured per-deployment (self-hosted on DO droplet);
|
||||
// when no URL is set, the check is a no-op.
|
||||
try
|
||||
{
|
||||
VelopackApp.Build()
|
||||
.Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppLog.Write($"Velopack bootstrap failed (non-fatal): {ex.Message}");
|
||||
}
|
||||
// There is deliberately NO self-update bootstrap here: the Microsoft Store updates the
|
||||
// app (TASK 48 — Store MSIX route), and a second updater would fight it.
|
||||
|
||||
base.OnStartup(e);
|
||||
AppLog.Write("App OnStartup end");
|
||||
|
||||
+6
-4
@@ -409,10 +409,12 @@ Set-AuthenticodeSignature -FilePath "LlamaCasty.exe" `
|
||||
### 4.4 Update Mechanism — ⛔ OBSOLETE (2026-09-27)
|
||||
|
||||
> **Superseded by Store updates.** Microsoft delivers and updates the app from the listing, so
|
||||
> there is nothing to check and no manifest to host. The Velopack updater currently in
|
||||
> `App.xaml.cs` **downloads *and executes***, which Store policy **10.2.2** does not permit — its
|
||||
> removal is a **compliance action**, not optional cleanup (TASK 48 item 3). The Polar-native design
|
||||
> below is retained as a record of the approach that was rejected; it is not an option.
|
||||
> there is nothing to check and no manifest to host. The Velopack updater that used to sit in
|
||||
> `App.xaml.cs` **downloaded *and executed***, which Store policy **10.2.2** does not permit — its
|
||||
> removal was a **compliance action**, not optional cleanup, and it is **done** (TASK 48 slice 3,
|
||||
> 2026-10-22: the package reference and the bootstrap are gone; `ytLive.Tests/StorePackagingTests.cs`
|
||||
> guards it). The Polar-native design below is retained as a record of the approach that was
|
||||
> rejected; it is not an option.
|
||||
|
||||
**Polar-native approach (no custom infrastructure):**
|
||||
|
||||
|
||||
+14
-4
@@ -77,6 +77,16 @@
|
||||
unchanged; the seams are two `internal` properties). Guard:
|
||||
`ytLive.Tests/AppLogRotationTests.cs`. Slices 2 (temp alert-clip cleanup) and 3 (low-disk
|
||||
guard before recording) are still open.
|
||||
- **TASK 48 slice 3 — the self-updater is gone (shipped 2026-10-22).** The Store route (creator
|
||||
ruling 2026-09-27) means the Store updates the app, so the Velopack package + bootstrap were
|
||||
**deleted** (`ytLive.csproj`, `App.xaml.cs`) — a compliance action, not cleanup: the updater
|
||||
downloaded *and executed*, which Store policy 10.2.2 does not permit. The DO update-URL droplet
|
||||
dies with it. Guard: `ytLive.Tests/StorePackagingTests.cs` (no updater package, no updater API
|
||||
in any app source file). The app was smoke-tested after the removal: `MainWindow loaded`, no
|
||||
exceptions. **Still open on TASK 48:** slice 2 (the `Package.appxmanifest` + packaging project),
|
||||
slice 6 (the full-trust recording invariant comment), slice 7 (disqualifier re-check), slice 8
|
||||
(the pre-submission gates) — and slices 4/5 are the creator's (Certification Kit, Partner
|
||||
Center listing, the demo account).
|
||||
- **The previous session (HA lights) produced NO ytLive code** — it was spent on the creator's Home
|
||||
Assistant light alert system (off-repo, `192.168.50.145`). See `MyMistakes.md` → 2026-10-21: the plan
|
||||
was one tweak to a verified-working script; the script was rewritten twice, the alert path broke, and
|
||||
@@ -270,10 +280,10 @@ Zombie entities deleted from the registry: `script.leak_strobe`, `script.doorbel
|
||||
Galaxy `cef.log` at 2.7 GB is NOT ours.)
|
||||
|
||||
## Tests
|
||||
- Last full run: **436/436 passed, 0 warnings** (2026-10-22 — after TASK 55 slice 1's
|
||||
`AppLogRotationTests`; the run before was 435/435 after TASK 63, and the runs before that were
|
||||
435/435 after TASK 61+62, 433/433 after TASK 60, 432/432 after TASK 59 and 431/431 after
|
||||
TASK 58). The one failure seen earlier in the
|
||||
- Last full run: **437/437 passed, 0 warnings** (2026-10-22 — after TASK 48 slice 3's
|
||||
`StorePackagingTests`; the run before was 436/436 after TASK 55 slice 1's
|
||||
`AppLogRotationTests`, and the one before that 435/435 after TASK 63). The one failure seen
|
||||
earlier in the
|
||||
session was `LayerReorderPersistenceTests.RealMouseDrag_OnTheLayerList_PersistsTheReorder`,
|
||||
which **passes in isolation** (re-run: 3/3) — the known real-mouse flake, not a regression.
|
||||
- Known flaky-by-environment (all pass in isolation): `AudioPipelineTests.Mix_HonorsProviderGains…`,
|
||||
|
||||
@@ -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: **MSIX + Store IAP** | 🔶 In progress — **✅ route decided 2026-09-27 (Store MSIX + Store IAP)**; **item 1 (bundle ffmpeg) SHIPPED 2026-09-28** | [`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) SHIPPED 2026-09-28**; **item 3 (remove the Velopack updater) SHIPPED 2026-10-22** — the Store updates the app | [`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) |
|
||||
| 50 | One-button "Publish this video" (resumable upload of the local recording) | ☐ Queued (2026-09-28) | [`TASKS/task-50-publish-recording.md`](TASKS/task-50-publish-recording.md) |
|
||||
| 51 | **Webcam background effects: Remove + Blur** | ✅ **Built 2026-10-09** (v1 requirement) — bundled MediaPipe Selfie Segmenter → ONNX (verified vs Google's runtime), Remove + Blur with strength, per-scene config persisted, one processing point in CameraManager, radio-pill UI in the webcam's Layers properties. Creator check 2026-10-09: **Remove jitter FIXED** (temporal mask smoothing 0.75/0.25, OBS/Jitsi-derived) and **Blur "heavy" FIXED** (quadratic radius 1→6 small px, default 0.5 = 2, StreamFX-consensus); recheck on the real camera pending | [`TASKS/task-51-webcam-bg-effects.md`](TASKS/task-51-webcam-bg-effects.md) |
|
||||
@@ -129,7 +129,7 @@ second encoder path needing a "redirect". Record+simulcast is one ffmpeg with tw
|
||||
`DroppedFrames`/`StreamDuration`; `SessionTeardownTests` is the natural home for the roll-up.
|
||||
- **TASK 3** — items 16 (Text source) + 20 (RewardEvent capture → SQLite, Alerts' persistence half) open; **17 (Alerts) is DONE via TASK 43 (2026-09-24) — native six-event alert box**
|
||||
- **TASK 9** — item 5 open (webcam identity key reconciliation)
|
||||
- **TASK 10** — Velopack update URL pending → **now owned by TASK 48** (retires if the Store handles updates)
|
||||
- **TASK 10** — the Velopack update URL is **RETIRED (2026-10-22)**: the updater was deleted (TASK 48 slice 3) and the Store updates the app
|
||||
- **Shipping / release build (creator-queued 2026-09-26)** — no publish config exists yet:
|
||||
the csproj has only `OutputType=WinExe` + `TargetFramework`, so a plain `dotnet publish`
|
||||
is **framework-dependent** (customer needs the .NET 8 Desktop Runtime preinstalled).
|
||||
|
||||
@@ -68,7 +68,7 @@ licensing path is being deleted because Store IAP supplies the same bit from the
|
||||
handles purchase. Paid users see zero license UI.
|
||||
7. ⛔ **Licensing model / renewal-lapse path** — already dead before the Store ruling (a perpetual
|
||||
key never expires). Now superseded again: **Store IAP has no keys at all.**
|
||||
8. 🔶 **Velopack auto-updates** — NuGet packages + bootstrap in `App.xaml.cs`. **TEARDOWN is a
|
||||
compliance action, not cleanup:** the updater downloads *and executes*, and Store policy 10.2.2
|
||||
does not permit it. Tracked as [`TASKS/task-48-distribution-msix.md`](task-48-distribution-msix.md)
|
||||
item 3; the Store updates the app instead.
|
||||
8. ✅ **Velopack auto-updates** — NuGet package + bootstrap in `App.xaml.cs`. **DELETED
|
||||
2026-10-22 (TASK 48 slice 3)** — a compliance action, not cleanup: the updater downloaded
|
||||
*and executed*, and Store policy 10.2.2 does not permit it. The Store updates the app
|
||||
instead. Guard: `ytLive.Tests/StorePackagingTests.cs`.
|
||||
@@ -158,15 +158,21 @@ There is currently **no `.manifest` file in the repo at all**, so this is purely
|
||||
|
||||
**Do NOT use `appContainer`** — see the invariant in item 6.
|
||||
|
||||
## 3. ☐ Remove Velopack — 3 edit sites
|
||||
## 3. ✅ Remove Velopack — 3 edit sites (DONE 2026-10-22)
|
||||
|
||||
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" />`
|
||||
- `App.xaml.cs:3` — `using Velopack;`
|
||||
- `App.xaml.cs:38-46` — the sole call site, already try/caught and commented
|
||||
"(non-fatal) … when no URL is set, the check is a no-op"
|
||||
- `ytLive.csproj:92` — `<PackageReference Include="Velopack" Version="1.2.0" />` — **REMOVED**
|
||||
- `App.xaml.cs:3` — `using Velopack;` — **REMOVED**
|
||||
- `App.xaml.cs:38-46` — the sole call site (already try/caught and commented
|
||||
"(non-fatal) … when no URL is set, the check is a no-op") — **REMOVED**
|
||||
|
||||
**Guard:** `ytLive.Tests/StorePackagingTests.cs` — the ONE test asserts the app project
|
||||
references no updater package (Velopack/Squirrel/NetSparkle/AutoUpdater/WinSparkle) and that no
|
||||
app source file uses the updater API (matched as CODE — a `using` directive, a type usage — not
|
||||
as a bare word, so a file's prose may still name what it deliberately does not do). The app was
|
||||
smoke-tested after the removal: `MainWindow loaded`, no exceptions.
|
||||
|
||||
**Retires:** the pending "Velopack update URL" item (`TASKS.md` open items,
|
||||
`task-10-monetization.md:43`) and the self-hosted DigitalOcean droplet.
|
||||
|
||||
@@ -2583,8 +2583,10 @@ 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.
|
||||
- **⛔ Velopack and the update URL are deleted** — the Store auto-updates. **DONE 2026-10-22**
|
||||
(TASK 48 slice 3): the `PackageReference` in `ytLive.csproj` and the bootstrap in
|
||||
`App.xaml.cs` are gone, and `ytLive.Tests/StorePackagingTests.cs` guards that no updater
|
||||
package or updater API comes back. 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
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace ytLive.Tests;
|
||||
|
||||
/// <summary>TASK 48, slice 3 — the creator's ruling (2026-09-27): the app ships as a
|
||||
/// **Microsoft Store MSIX** and the **Store updates it**. The self-update subsystem that
|
||||
/// existed for the abandoned self-hosted route (a Velopack bootstrap plus the DigitalOcean
|
||||
/// update-URL droplet) is therefore deleted, not parked: a second updater inside a
|
||||
/// Store-installed package fights the Store's own updater.
|
||||
///
|
||||
/// <para>This test is the guard: the app project references no updater package and no app
|
||||
/// source file uses the updater API — so the deleted subsystem cannot creep back in, and
|
||||
/// the "the Store updates it" decision stays the only update path.</para></summary>
|
||||
public class StorePackagingTests
|
||||
{
|
||||
/// <summary>Known self-update packages. If one of these comes back, the Store route has
|
||||
/// been quietly reversed.</summary>
|
||||
private static readonly string[] UpdaterPackages =
|
||||
{
|
||||
"Velopack", "Squirrel", "NetSparkle", "AutoUpdater", "WinSparkle"
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void The_app_ships_no_self_update_subsystem()
|
||||
{
|
||||
// 1. The app project references no updater package.
|
||||
var project = XDocument.Load(SourceAssert.RepoPath("ytLive.csproj"));
|
||||
var packages = project.Descendants()
|
||||
.Where(e => e.Name.LocalName == "PackageReference")
|
||||
.Select(e => (string?)e.Attribute("Include"))
|
||||
.Where(name => name != null)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var updater in UpdaterPackages)
|
||||
Assert.DoesNotContain(updater, packages);
|
||||
|
||||
// 2. No app source file uses the updater API. Matched as CODE (a using directive,
|
||||
// a type usage), not as a bare word — a file's prose is allowed to name what it
|
||||
// deliberately does not do.
|
||||
var root = Path.GetDirectoryName(SourceAssert.RepoPath("ytLive.csproj"))!;
|
||||
foreach (var file in AppSourceFiles(root))
|
||||
{
|
||||
var text = File.ReadAllText(file);
|
||||
Assert.False(
|
||||
Regex.IsMatch(text, @"^\s*using\s+Velopack\s*;", RegexOptions.Multiline),
|
||||
$"{Path.GetFileName(file)} still imports the Velopack updater — the Store updates this app.");
|
||||
Assert.False(
|
||||
Regex.IsMatch(text, @"\bVelopackApp\b"),
|
||||
$"{Path.GetFileName(file)} still calls the Velopack updater — the Store updates this app.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Every C# file of the app project (not the test project, not build output).</summary>
|
||||
private static IEnumerable<string> AppSourceFiles(string root)
|
||||
{
|
||||
return Directory.EnumerateFiles(root, "*.cs", SearchOption.AllDirectories)
|
||||
.Where(path => !path.Contains($"{Path.DirectorySeparatorChar}ytLive.Tests{Path.DirectorySeparatorChar}"))
|
||||
.Where(path => !path.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}"))
|
||||
.Where(path => !path.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}"));
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,6 @@
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.12" />
|
||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
|
||||
<PackageReference Include="Velopack" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user