Docs backfill for social bar v2 (9873eed): schema v6->v8 in TASKS.md/ai.md, social bar architecture section + Simple Icons CC0 notice, README structure rows, HANDOFF rewritten (committed+pushed)
This commit is contained in:
+8
-6
@@ -7,8 +7,10 @@
|
|||||||
|
|
||||||
## Session state (last updated: 2026-08-12)
|
## Session state (last updated: 2026-08-12)
|
||||||
|
|
||||||
- **Branch:** `main` (work UNCOMMITTED — see dirty list). Includes the previous
|
- **Branch:** `main` — the social bar v2 push is **committed + pushed** (`9873eed`,
|
||||||
session's socials v2 fixes + this session's fediverse-service-icon work.
|
18 files, +1878/−321, 112 tests passing, 0 warnings). Working tree is **dirty
|
||||||
|
with the post-push docs backfill only** (ai.md, README.md, TASKS.md schema
|
||||||
|
section, THIRD-PARTY-NOTICES.txt) — ready to commit when the user says so.
|
||||||
- **Finished this session (round 3):** user's live-test report said the mastodon
|
- **Finished this session (round 3):** user's live-test report said the mastodon
|
||||||
icon still didn't show for `@gramps@llamachile.tube`. Root cause: the identity
|
icon still didn't show for `@gramps@llamachile.tube`. Root cause: the identity
|
||||||
domain `llamachile.tube` is YunoHost-SSO-gated — `/.well-known/nodeinfo`,
|
domain `llamachile.tube` is YunoHost-SSO-gated — `/.well-known/nodeinfo`,
|
||||||
@@ -20,7 +22,7 @@
|
|||||||
identity domain fails, follows the root redirect (`ResolveInstanceHostAsync`,
|
identity domain fails, follows the root redirect (`ResolveInstanceHostAsync`,
|
||||||
reads `resp.RequestMessage.RequestUri.Host`) and re-runs the nodeinfo lookup
|
reads `resp.RequestMessage.RequestUri.Host`) and re-runs the nodeinfo lookup
|
||||||
on the resolved host. New test `FediverseHandle_RootRedirectToSubdomain_ResolvesSoftware`.
|
on the resolved host. New test `FediverseHandle_RootRedirectToSubdomain_ResolvesSoftware`.
|
||||||
Build: **0 warnings**. Tests: **111 passing**.
|
Build: **0 warnings**. Tests: **112 passing**.
|
||||||
- **What landed (all rounds this session):**
|
- **What landed (all rounds this session):**
|
||||||
1. **Fediverse icon resolution** — `DetectService` maps `@user@domain` to the
|
1. **Fediverse icon resolution** — `DetectService` maps `@user@domain` to the
|
||||||
new `SocialService.Fediverse` (was `Link`/chain icon). On validate,
|
new `SocialService.Fediverse` (was `Link`/chain icon). On validate,
|
||||||
@@ -61,9 +63,9 @@
|
|||||||
- Round-3 redirect fallback fires only when identity-domain nodeinfo fails;
|
- Round-3 redirect fallback fires only when identity-domain nodeinfo fails;
|
||||||
the root follow happens automatically (HttpClient default auto-redirect),
|
the root follow happens automatically (HttpClient default auto-redirect),
|
||||||
and `RequestMessage.RequestUri.Host` is read from the final response.
|
and `RequestMessage.RequestUri.Host` is read from the final response.
|
||||||
- **Next step:** show the user the fixes and let them decide whether to commit.
|
- **Next step:** commit + push the docs backfill (ai.md / README.md / TASKS.md
|
||||||
Nothing queued beyond that — do not expand the task queue on your own.
|
schema section / THIRD-PARTY-NOTICES.txt) once the user confirms. Nothing
|
||||||
(`ytLive.Tests`/`bin` + `/obj` are dirty build artifacts, not hand-authored.)
|
else queued — do not expand the task queue on your own.
|
||||||
|
|
||||||
- **Secret/DB/port facts live:** OAuth client id/secret in `Helpers/OAuthCredentials.cs`;
|
- **Secret/DB/port facts live:** OAuth client id/secret in `Helpers/OAuthCredentials.cs`;
|
||||||
OAuth session token in `Helpers/TokenStore.cs` (DPAPI → `%APPDATA%\ytLlive\ytLlive.auth`);
|
OAuth session token in `Helpers/TokenStore.cs` (DPAPI → `%APPDATA%\ytLlive\ytLlive.auth`);
|
||||||
|
|||||||
@@ -45,12 +45,13 @@ dotnet run
|
|||||||
|
|
||||||
| Path | Role |
|
| Path | Role |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `Models/` | Scene, Source, QualityOption, StreamConfig, StreamHealth, YouTube channel/chat |
|
| `Models/` | Scene, Source, QualityOption, StreamConfig, StreamHealth, YouTube channel/chat, Socials (social bar) |
|
||||||
| `ViewModels/` | MainViewModel — scenes, stream controls, chat; GoLiveViewModel, ReuseImageViewModel |
|
| `ViewModels/` | MainViewModel — scenes, stream controls, chat; GoLiveViewModel, ReuseImageViewModel, SocialsDialogViewModel |
|
||||||
| `Services/` | YouTubeAuthService (OAuth2), YouTubeStreamService (broadcast/health), YouTubeChatService (chat polling), LayoutStore (SQLite) |
|
| `Services/` | YouTubeAuthService (OAuth2), YouTubeStreamService (broadcast/health), YouTubeChatService (chat polling), LayoutStore (SQLite), SocialValidator (social link/fediverse validation + nodeinfo icon resolution) |
|
||||||
| `Helpers/` | ViewModelBase, RelayCommand, ImageCache, AppLog, FocusPreservingListBox, OAuthCredentials |
|
| `Helpers/` | ViewModelBase, RelayCommand, ImageCache, AppLog, FocusPreservingListBox, OAuthCredentials |
|
||||||
| `Themes/` | `Controls.xaml` — the dark-theme control styles, merged once in `App.xaml` |
|
| `Themes/` | `Controls.xaml` — the dark-theme control styles, merged once in `App.xaml` |
|
||||||
| `MainWindow.xaml` | Dark-theme main UI: scene/source panel, preview, chat, status bar |
|
| `MainWindow.xaml` | Dark-theme main UI: scene/source panel, preview, chat, status bar |
|
||||||
|
| `SocialsDialog.xaml` | Social Media Site Promotion dialog — 6-slot social bar editor with sign-in gate and validation |
|
||||||
|
|
||||||
## Docs (memory map)
|
## Docs (memory map)
|
||||||
|
|
||||||
|
|||||||
@@ -401,12 +401,12 @@ cache refresh, empty payload, missing zip entry, downloader failure) — **78 pa
|
|||||||
|
|
||||||
### Status: ✅ Done
|
### Status: ✅ Done
|
||||||
|
|
||||||
1. ✅ SQLite database (`Microsoft.Data.Sqlite`) at `%APPDATA%\ytLlive\ytLlive.db`; schema versioned via `PRAGMA user_version` (currently **v6**)
|
1. ✅ SQLite database (`Microsoft.Data.Sqlite`) at `%APPDATA%\ytLlive\ytLlive.db`; schema versioned via `PRAGMA user_version` (currently **v8**)
|
||||||
2. ✅ Assets live in the DB (BLOB keyed by SHA-256 content hash), never file paths — deleting the original file never breaks a scene
|
2. ✅ Assets live in the DB (BLOB keyed by SHA-256 content hash), never file paths — deleting the original file never breaks a scene
|
||||||
3. ✅ File-model save/open — the active layout file is tracked (default is the AppData DB); **Save Layout As… / Open Layout…** switch the active file; auto-save writes to whatever is active
|
3. ✅ File-model save/open — the active layout file is tracked (default is the AppData DB); **Save Layout As… / Open Layout…** switch the active file; auto-save writes to whatever is active
|
||||||
4. ✅ Auto-save (invisible) — ~1.5s debounce on scene/source add/remove/reorder/rename/hide + any source transform change; flush on window close
|
4. ✅ Auto-save (invisible) — ~1.5s debounce on scene/source add/remove/reorder/rename/hide + any source transform change; flush on window close
|
||||||
5. ✅ Startup — load the active file; seed the five canonical scenes only when the DB is empty; (+) re-adds a missing canonical scene and is hidden once all five are present; adding beyond the five is rejected
|
5. ✅ Startup — load the active file; seed the five canonical scenes only when the DB is empty; (+) re-adds a missing canonical scene and is hidden once all five are present; adding beyond the five is rejected
|
||||||
6. ✅ Schema v1 → v6 — webcam columns (v2), singleton `Webcam` + per-scene `WebcamSceneConfig` (v3), `RectWidth`/`RectHeight` round-to-rect restore (v4), `Source.IsBackdrop` + `Source.CaptureKey` (v5), `Scene.HasBackdrop` — backdrop **Live-only by policy** (v6, one-time backfill + `EnforceBackdropPolicy` on every load); `WindowHandle` stays in-memory (per-session); save = transactional rewrite; orphaned assets pruned
|
6. ✅ Schema v1 → v8 — webcam columns (v2), singleton `Webcam` + per-scene `WebcamSceneConfig` (v3), `RectWidth`/`RectHeight` round-to-rect restore (v4), `Source.IsBackdrop` + `Source.CaptureKey` (v5), `Scene.HasBackdrop` — backdrop **Live-only by policy** (v6, one-time backfill + `EnforceBackdropPolicy` on every load), `Scene.HasSocialBar` (v7, dropped per-scene toggle — column back-compat, unread), `Socials.BarEnabled` (v8); the `SocialEntry.Software` fediverse-software column is a **column-presence migration** (commented v8→v9, no version bump — `user_version` stays 8); `WindowHandle` stays in-memory (per-session); save = transactional rewrite; orphaned assets pruned
|
||||||
|
|
||||||
### Design decisions
|
### Design decisions
|
||||||
|
|
||||||
@@ -420,16 +420,19 @@ cache refresh, empty payload, missing zip entry, downloader failure) — **78 pa
|
|||||||
**Save Layout As… / Open Layout…** switch the active file; auto-save writes to whatever is active.
|
**Save Layout As… / Open Layout…** switch the active file; auto-save writes to whatever is active.
|
||||||
4. **Auto-save (invisible)** — ~1.5s debounce on scene add/remove/reorder/rename/hide, source
|
4. **Auto-save (invisible)** — ~1.5s debounce on scene add/remove/reorder/rename/hide, source
|
||||||
add/remove/reorder, and any source transform change; flush on window close.
|
add/remove/reorder, and any source transform change; flush on window close.
|
||||||
5. **Schema** — `Scene` (Id, Name, IsHidden, IsChatScene, HasBackdrop, SortOrder), `Asset` (Id, Hash, Data,
|
5. **Schema** — `Scene` (Id, Name, IsHidden, IsChatScene, HasBackdrop, HasSocialBar, SortOrder), `Asset` (Id, Hash, Data,
|
||||||
PixelWidth, PixelHeight), `Source` (Id, SceneId FK cascade, AssetId FK, Type, Name, IsEnabled,
|
PixelWidth, PixelHeight), `Source` (Id, SceneId FK cascade, AssetId FK, Type, Name, IsEnabled,
|
||||||
X/Y/Width/Height/Opacity, MonitorIndex, DeviceId, ClipShape, IsMirrored, SortOrder) —
|
X/Y/Width/Height/Opacity, MonitorIndex, DeviceId, ClipShape, IsMirrored, SortOrder), `Socials` (Id,
|
||||||
`user_version` **6** (v1 → v2 = `ALTER TABLE` adds the two webcam columns; v3 = singleton
|
BarPosition, BarJustify — back-compat, unread, BarEnabled added via `ALTER`), `SocialEntry` (Id,
|
||||||
`Webcam` + per-scene `WebcamSceneConfig`; v4 = `WebcamSceneConfig.RectWidth`/`RectHeight` for the
|
SocialsId FK cascade, Service, Handle, ProfileUrl, SortOrder) — `user_version` **8** (v1 → v2 =
|
||||||
round-to-rect restore; v5 = `Source.IsBackdrop` + `Source.CaptureKey` for the live-capture
|
`ALTER TABLE` adds the two webcam columns; v3 = singleton `Webcam` + per-scene `WebcamSceneConfig`;
|
||||||
backdrop; v6 = `Scene.HasBackdrop` — the backdrop is **Live-only by policy**
|
v4 = `WebcamSceneConfig.RectWidth`/`RectHeight` for the round-to-rect restore; v5 = `Source.IsBackdrop`
|
||||||
(one-time backfill turns Starting/BRB/Chat/Ending off and drops their backdrop
|
+ `Source.CaptureKey` for the live-capture backdrop; v6 = `Scene.HasBackdrop` — the backdrop is
|
||||||
sources; `EnforceBackdropPolicy` re-normalizes every load). `WindowHandle` stays in-memory
|
**Live-only by policy** (one-time backfill turns Starting/BRB/Chat/Ending off and drops their backdrop
|
||||||
(per-session). Save = transactional rewrite; orphaned assets pruned.
|
sources; `EnforceBackdropPolicy` re-normalizes every load); v7 = `Scene.HasSocialBar` (per-scene toggle
|
||||||
|
dropped — column back-compat, unread); v8 = `Socials.BarEnabled`). The `SocialEntry.Software`
|
||||||
|
fediverse-software column is a column-presence migration (commented v8→v9, no version bump).
|
||||||
|
`WindowHandle` stays in-memory (per-session). Save = transactional rewrite; orphaned assets pruned.
|
||||||
6. **Startup** — load the active file; seed the five canonical scenes
|
6. **Startup** — load the active file; seed the five canonical scenes
|
||||||
(Starting/Live/BRB/Chat/Ending, `SceneCatalog`) only when the DB is empty. The (+)
|
(Starting/Live/BRB/Chat/Ending, `SceneCatalog`) only when the DB is empty. The (+)
|
||||||
button re-adds a missing canonical scene and is hidden once all five are present;
|
button re-adds a missing canonical scene and is hidden once all five are present;
|
||||||
|
|||||||
@@ -68,6 +68,17 @@ the guardrails — the "never do" list is there on purpose.
|
|||||||
License: MIT
|
License: MIT
|
||||||
Home: https://github.com/dotnet/
|
Home: https://github.com/dotnet/
|
||||||
|
|
||||||
|
8. Simple Icons (bundled SVG logo path data for the social bar, e.g. the
|
||||||
|
mastodon/peertube/pixelfed fediverse logos)
|
||||||
|
Copyright (c) Simple Icons contributors (public domain dedication)
|
||||||
|
License: CC0 1.0 Universal (no rights reserved, no attribution required)
|
||||||
|
Home: https://simpleicons.org/
|
||||||
|
Source: https://github.com/simple-icons/simple-icons
|
||||||
|
Used as: path data compiled into the app's `SocialServiceIcons` so each
|
||||||
|
social entry renders the service's real logo. CC0 imposes no
|
||||||
|
obligations; it is listed here per this file's "list everything"
|
||||||
|
policy.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
MISCELLANEOUS
|
MISCELLANEOUS
|
||||||
|
|||||||
@@ -89,9 +89,9 @@ C# / WPF (.NET 8) following MVVM:
|
|||||||
|
|
||||||
| Path | Role |
|
| Path | Role |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `Models/` | Plain data types — Scene, Source (incl. `ClipShape`, `IsMirrored`, `VideoImageSource`), QualityOption, StreamConfig, StreamHealth, YouTubeChannel, ChatMessage |
|
| `Models/` | Plain data types — Scene, Source (incl. `ClipShape`, `IsMirrored`, `VideoImageSource`), QualityOption, StreamConfig, StreamHealth, YouTubeChannel, ChatMessage, **Socials (`SocialService` enum + `SocialEntry`/`SocialsConfig` + `SocialServiceIcons`) — the social bar** |
|
||||||
| `ViewModels/` | MainViewModel — exposes collections + commands for the UI; GoLiveViewModel, ReuseImageViewModel, CameraPickerViewModel |
|
| `ViewModels/` | MainViewModel — exposes collections + commands for the UI; GoLiveViewModel, ReuseImageViewModel, CameraPickerViewModel, **SocialsDialogViewModel** |
|
||||||
| `Services/` | YouTube OAuth2, stream/broadcast management, live chat polling, LayoutStore (SQLite), **webcam: `VideoFrame` seam + `CameraDeviceInfo`/`ICameraEnumerator`/`ICameraFrameSource` interfaces + `MediaCaptureCameraEnumerator`/`MediaCaptureFrameSource` (WinRT) + `CameraManager`**, **screen capture: `IFullScreenDetector`/`Win32FullScreenDetector` + `IScreenCaptureSource`/`ScreenCaptureFrameSource` (WinRT GraphicsCapture) + `ScreenCaptureManager` + `ScreenCaptureSourceFactory` + `Direct3D11Helper`/`CaptureInterop` (COM bridges)** |
|
| `Services/` | YouTube OAuth2, stream/broadcast management, live chat polling, LayoutStore (SQLite), **SocialValidator (`ISocialValidator` seam + `HttpSocialValidator` default)**, **webcam: `VideoFrame` seam + `CameraDeviceInfo`/`ICameraEnumerator`/`ICameraFrameSource` interfaces + `MediaCaptureCameraEnumerator`/`MediaCaptureFrameSource` (WinRT) + `CameraManager`**, **screen capture: `IFullScreenDetector`/`Win32FullScreenDetector` + `IScreenCaptureSource`/`ScreenCaptureFrameSource` (WinRT GraphicsCapture) + `ScreenCaptureManager` + `ScreenCaptureSourceFactory` + `Direct3D11Helper`/`CaptureInterop` (COM bridges)** |
|
||||||
| `Helpers/` | ViewModelBase (INotifyPropertyChanged), RelayCommand, ImageCache, AppLog (file logger), FocusPreservingListBox, OAuthCredentials, **TokenStore (DPAPI session persistence)**, visibility converters |
|
| `Helpers/` | ViewModelBase (INotifyPropertyChanged), RelayCommand, ImageCache, AppLog (file logger), FocusPreservingListBox, OAuthCredentials, **TokenStore (DPAPI session persistence)**, visibility converters |
|
||||||
| `Themes/` | `Controls.xaml` — the single dark-theme source, merged once in `App.xaml` (see `Themes/index.md`) |
|
| `Themes/` | `Controls.xaml` — the single dark-theme source, merged once in `App.xaml` (see `Themes/index.md`) |
|
||||||
| `MainWindow.xaml` | Dark theme; layout: top bar (controls), center (preview), left (scenes/sources), right (chat), bottom (health) |
|
| `MainWindow.xaml` | Dark theme; layout: top bar (controls), center (preview), left (scenes/sources), right (chat), bottom (health) |
|
||||||
@@ -112,7 +112,7 @@ C# / WPF (.NET 8) following MVVM:
|
|||||||
### Current limitations / TODOs
|
### Current limitations / TODOs
|
||||||
|
|
||||||
- `Helpers/OAuthCredentials.cs` contains the real ClientId/ClientSecret. Auth is complete and the session **persists via Windows DPAPI** (`Helpers/TokenStore.cs` → `%APPDATA%\ytLlive\ytLlive.auth`, CurrentUser scope), reloaded best-effort at startup with a proactive refresh of a near-expiry access token. Sign-in/Change Account lives **inside the Start Stream dialog** (two-state flow — no separate Connect button). A **graceful End Livestream signs out**: `StopStream()` clears the session + token, so the next go-live needs a fresh sign-in; a crash never runs End, so the token survives and the creator stays signed in. `YouTubeAuthService` takes an optional `HttpClient` + `sessionChanged` callback (test seam + save hook; services are still constructed in `MainViewModel`)
|
- `Helpers/OAuthCredentials.cs` contains the real ClientId/ClientSecret. Auth is complete and the session **persists via Windows DPAPI** (`Helpers/TokenStore.cs` → `%APPDATA%\ytLlive\ytLlive.auth`, CurrentUser scope), reloaded best-effort at startup with a proactive refresh of a near-expiry access token. Sign-in/Change Account lives **inside the Start Stream dialog** (two-state flow — no separate Connect button). A **graceful End Livestream signs out**: `StopStream()` clears the session + token, so the next go-live needs a fresh sign-in; a crash never runs End, so the token survives and the creator stays signed in. `YouTubeAuthService` takes an optional `HttpClient` + `sessionChanged` callback (test seam + save hook; services are still constructed in `MainViewModel`)
|
||||||
- Scene/source/asset layout persists (SQLite, schema v6); the OAuth session persists (DPAPI); the paid-unlock state does not (yet — itch.io key verification pending)
|
- Scene/source/asset layout + the social bar persist (SQLite, schema v8); the OAuth session persists (DPAPI); the paid-unlock state does not (yet — itch.io key verification pending)
|
||||||
- `YouTubeStreamService` uses hardcoded `1080p`/`60fps` and per-broadcast streams — must switch to the v3 `variable` reusable stream
|
- `YouTubeStreamService` uses hardcoded `1080p`/`60fps` and per-broadcast streams — must switch to the v3 `variable` reusable stream
|
||||||
- Webcam capture is shipped (milestone 1); the live desktop/game backdrop is shipped (ship task #1); **the output compositor (TASK 4 ship step 1) is SHIPPED**, **the FFmpeg locator (TASK 4 ship step 2) is SHIPPED** — full plan in `TASKS.md`; the encoder subprocess + RTMP push, audio capture, and the frame-pipeline wiring follow (each its own PR)
|
- Webcam capture is shipped (milestone 1); the live desktop/game backdrop is shipped (ship task #1); **the output compositor (TASK 4 ship step 1) is SHIPPED**, **the FFmpeg locator (TASK 4 ship step 2) is SHIPPED** — full plan in `TASKS.md`; the encoder subprocess + RTMP push, audio capture, and the frame-pipeline wiring follow (each its own PR)
|
||||||
- `StreamConfig` defaults (`TargetBitrate=6000`, `Resolution="1920x1080"`) are stale — the live dropdown drives `StreamHealth.CurrentBitrate`/`FPS` instead
|
- `StreamConfig` defaults (`TargetBitrate=6000`, `Resolution="1920x1080"`) are stale — the live dropdown drives `StreamHealth.CurrentBitrate`/`FPS` instead
|
||||||
@@ -330,6 +330,32 @@ const). Constructor-injected search dirs / tools dir / downloader (`Func<string,
|
|||||||
Task<byte[]>>`) keep it hermetic: tests fake the network with a real in-memory zip. Constructed in the
|
Task<byte[]>>`) keep it hermetic: tests fake the network with a real in-memory zip. Constructed in the
|
||||||
encoder step (not yet — this PR ships the seam + impl + tests only).
|
encoder step (not yet — this PR ships the seam + impl + tests only).
|
||||||
|
|
||||||
|
### Social bar (TASK 14 — shipped 2026-08-12, plan in TASKS.md)
|
||||||
|
|
||||||
|
A **global bar layer** (never a Source, no sources-list row) that sits over the bottom or top of the
|
||||||
|
output and carries the creator's social links — content-sized, centered, GREEN glow when ON, top/bottom
|
||||||
|
snap-drag (default BOTTOM, persisted `SocialBarPosition`). `Models/Socials.cs`: `SocialService` enum
|
||||||
|
(YouTube/Twitch/X/Instagram/TikTok/Facebook/Discord/Kick/Threads/Bluesky/GitHub/LinkedIn/Pinterest/
|
||||||
|
Snapchat/Reddit/WhatsApp/Telegram/Link/Website/**Fediverse**), `SocialEntry` (Service/Handle/ProfileUrl/
|
||||||
|
`FediverseSoftware`), `SocialsConfig` (Entries + `BarPosition` + `BarEnabled`; `BarJustify` dropped,
|
||||||
|
column back-compat). Configured in the "Social Media Site Promotion" dialog (`SocialsDialog.xaml` +
|
||||||
|
`ViewModels/SocialsDialogViewModel`, WPF-free, injected `ISocialValidator` + sign-in/sign-out fakes):
|
||||||
|
ON/OFF bar switch (schema v8), 6 fixed slots — row 1 always YouTube (signed-in → channel handle;
|
||||||
|
signed-out → sign-in gate → OAuth; delete → confirm sign-out), row 2 free, rows 3–6 lock icons on
|
||||||
|
freemium. Service detection (`SocialServiceIcons.DetectService`): URL domain / fediverse `@user@domain` →
|
||||||
|
**Fediverse** / bare→Website. Validation (`Services/SocialValidator.cs`, `ISocialValidator` seam +
|
||||||
|
`HttpSocialValidator` default): async GET of the canonical profile URL; 200/redirect = valid, 404/failure =
|
||||||
|
rejected. Fediverse additionally does a **best-effort nodeinfo lookup** (`/.well-known/nodeinfo` →
|
||||||
|
`software.name`, stored in `SocialEntry.FediverseSoftware` / the `SocialEntry.Software` column,
|
||||||
|
column-presence migration, no version bump) so the entry shows the **instance's real logo**
|
||||||
|
(`LogoDataForFediverse`: mastodon/peertube/pixelfed/misskey/lemmy/pleroma/firefish, generic fediverse
|
||||||
|
honeycomb fallback — Simple Icons CC0 path data, initials badges gone); nodeinfo failure still validates
|
||||||
|
(glyph falls back). If the identity domain's nodeinfo is blocked (YunoHost SSO gates
|
||||||
|
`/.well-known/nodeinfo` behind the login page) but the bare root 302s to the real instance, the lookup
|
||||||
|
**follows the root redirect** and asks the resolved host. Cancel is a hard stop: `LookupAsync` takes a
|
||||||
|
`CancellationToken` (dialog VM owns a CTS; Cancel/X/Save abort in-flight lookups, canceled continuations
|
||||||
|
never touch slot state).
|
||||||
|
|
||||||
### Licensing — do not violate (GA = paid product; see `THIRD-PARTY-NOTICES.txt`)
|
### Licensing — do not violate (GA = paid product; see `THIRD-PARTY-NOTICES.txt`)
|
||||||
|
|
||||||
This product is closed-source and paid. Every third-party component must stay inside the LGPL/BSD/MIT
|
This product is closed-source and paid. Every third-party component must stay inside the LGPL/BSD/MIT
|
||||||
@@ -352,6 +378,10 @@ guardrails below — written down so a future "quick fix" never reintroduces a G
|
|||||||
— the obligations are not optional.
|
— the obligations are not optional.
|
||||||
- **Pin to a moving target** — the `latest` BtbN release tag floats. Only immutable autobuild tags give
|
- **Pin to a moving target** — the `latest` BtbN release tag floats. Only immutable autobuild tags give
|
||||||
a reproducible source offer. Record the tag + variant beside the URL (TASKS.md) every time the pin moves.
|
a reproducible source offer. Record the tag + variant beside the URL (TASKS.md) every time the pin moves.
|
||||||
|
- **Use non-CC0 icon art** — the social bar's bundled SVG logo path data comes from **Simple Icons**
|
||||||
|
(CC0 1.0, public domain — see `THIRD-PARTY-NOTICES.txt`). Replacing or adding logos must stay CC0 or
|
||||||
|
another public-domain source; a logo asset under a copyleft or attribution license would contaminate
|
||||||
|
the paid product.
|
||||||
- **Forget the v1 license-texts gate** — `THIRD-PARTY-NOTICES.txt` links the canonical license texts; at
|
- **Forget the v1 license-texts gate** — `THIRD-PARTY-NOTICES.txt` links the canonical license texts; at
|
||||||
**v1 (GA)** the full texts of every license it names MUST ship alongside it (TASK 4 requirement 9 is the
|
**v1 (GA)** the full texts of every license it names MUST ship alongside it (TASK 4 requirement 9 is the
|
||||||
release blocker). Queued early is wrong; the release pass owns it.
|
release blocker). Queued early is wrong; the release pass owns it.
|
||||||
|
|||||||
Reference in New Issue
Block a user