The first half of surge day 1. One question, "may this session emit Pro output?", with one method on the interface so nothing downstream knows which rail proved it. SteamEntitlement reads the lifetime SKU the way Valve intends: SteamAPI.Init() then SteamApps.BIsDlcInstalled(dlcAppId). Four different failure paths all resolve to the free tier rather than to Pro or to a crash — no DLC id configured, no Steam client, steam_api64.dll missing (a throw on first touch), and simply not owned. A copied folder run without Steam is the common case, not an exceptional one. NotConfigured() is the shipping default until Steamworks creates the DLC app; it answers false without ever touching the native library, so today's builds behave exactly as they did before this commit. HasProOutput is now IsPremium || DeveloperMode || rail, with an internal EntitlementOverride test seam (internal, because a public setter here is a licence bypass). Four tests: no id reads false, no client reads false without throwing, the fake reports what a test sets, and the view model takes its answer from the rail. Steamworks.NET 2024.8.0 added; the native DLL still comes from scripts/steam-sdk.sh, so the csproj change is three lines and no formatting churn.
41 lines
2.7 KiB
Markdown
41 lines
2.7 KiB
Markdown
# HANDOFF — 2026-11-01 (exe renamed, depot builds, output rule enforced)
|
||
|
||
## State
|
||
|
||
- Branch `main`, level with `origin` through `8f79b20`; this unit is local.
|
||
- **The shipped exe is `LlamaCasty.exe`** (`AssemblyName` renamed; four pack URIs fixed — the docs
|
||
said three, `KeepBroadcastDialog.xaml:5` was the fourth). Guarded by `AssemblyIdentityTests`.
|
||
- **`scripts/publish.sh`** stages `artifacts/steam-stage` and refuses to finish if `ffmpeg\`, the
|
||
licence, privacy or notices file is missing, or test assemblies leaked in. Output 257 MB.
|
||
- **The output-profile rule is built and enforced**: `Models/OutputProfile.cs` (921,600 px / 30 fps,
|
||
fail closed) resolved once in `BuildEncoderOptions` — one ffmpeg process, two outputs.
|
||
`MainViewModel.DeveloperMode` bypasses it in Debug only.
|
||
- **Distribution is Steam-exclusive** (2026-10-31): free app + paid edition as a Steam **DLC**; the
|
||
**$10/month** plan sold off-Steam by Polar, *stated, never sold*, in-app. Entitlement is
|
||
`steamDlcOwned || polarKeyValid`; the app must start without Steam, falling back to free.
|
||
- **Site live with Steam** (`a9d07ce`); `www.llamacasty.com` 301s to the apex.
|
||
|
||
## Next action
|
||
|
||
**Surge, 2026-11-02 → 11-07 — six days, all remaining code.** Day 1 is partly done ahead of time:
|
||
`IEntitlement` + `SteamEntitlement` (Steamworks.NET, fail-closed on every path) + `FakeEntitlement`,
|
||
with `HasProOutput` reading the rail. Undo/redo, the rail gear and the EDIT alignment also landed
|
||
early. Remaining on day 1: greyed tiers, licence UI's four states, system messages, licence ID in
|
||
About. Days 2–6 in `TASKS.md` → "The surge".
|
||
|
||
## Landmines
|
||
|
||
- **⛔ `ExcludeFromSingleFile="true"` on the ffmpeg content** — without it the publisher bundles
|
||
libav\*.dll into the exe and the app ships unable to find ffmpeg. Recipe in `MyMistakes.md`.
|
||
- **Dev affordances are compiled out, not hidden** — `DeveloperPanel` is removed from the Release
|
||
build; `Helpers/DevBuild.cs` is the single source for the flag (never `const`).
|
||
- **Nothing may gate a feature.** The only paid delta is the output profile; `ShowBrandFlash` stays
|
||
`false` and entitlement must never enable it.
|
||
- **No checkout inside a Steam build** — the Wallet rule. The monthly is named, never sold, in-app.
|
||
- **The org access token never ships.** `organization_id` is public; the token is not.
|
||
- **The site publishes the model, never the numbers**, and never takes payment or links a checkout.
|
||
- **No self-updater and no version banner**: Steam updates the app.
|
||
- Pre-existing: the **full test suite hangs** (WASAPI teardown) — per-class runs; `ytLive.Tests`
|
||
carries 3 xUnit warnings the app-only gate does not see.
|
||
- Not every hex is a theme colour — `BorderColorPalette`/chat defaults are USER DATA, not tokens.
|