diff --git a/CONTEXT.md b/CONTEXT.md index 4eb2306..673815f 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -2,61 +2,77 @@ Living orientation doc for what this repo is, how it is currently shaped, and where it appears headed. Sits alongside the root `CLAUDE.md` (operational guidance) — this file is the product/architecture view. -> **Drift notice.** The root `CLAUDE.md` and every folder-level `CLAUDE.md` currently in the tree describe the project as `.NET 9`. The most recent commit upgraded all projects to `.NET 10` (every `.csproj` now targets `net10.0`, packages pinned at `10.0.1`). Until those docs are refreshed, treat any framework-version claim in them as stale. The other staleness items are listed at the bottom of this file. +> **Status.** The root `CLAUDE.md` is current — it reflects the post-split ten-project solution, `net10.0`, and the dual-app topology. This file (`CONTEXT.md`) was the lagging document and §2 / §4 / §7 below have been brought back into line with the root `CLAUDE.md` as of 2026-06-06. Folder-level `CLAUDE.md` files are still being swept (`DOC_PLAN.md`); treat framework-version and structural claims in any *folder* `CLAUDE.md` not yet rewritten as potentially stale until that sweep lands. --- ## 1. What this project is -DeepDrftHome is the home + listening surface for **DeepDrft**, a two-person electronic music collective based in Charleston, SC (per `DeepDrftWeb.Client/Pages/Home.razor`). The product is, at minimum: +DeepDrftHome is the home + listening surface for **DeepDrft**, a two-person electronic music collective based in Charleston, SC (per `DeepDrftPublic.Client/Pages/Home.razor`). The product is, at minimum: -- A public-facing site (hero, about, "experience" features). +- A public-facing site (hero, about, "experience" features) at `DeepDrftPublic`. - A **track gallery** that browses a library of WAV recordings, plays them in-browser with a persistent dock-style player, and supports seek (including seek beyond what's been streamed so far). -- An admin CLI for adding tracks (Terminal.Gui or scripted), running locally against the same dual-database substrate the site uses. +- A browser-based **CMS** (`DeepDrftManager`) for adding, editing, and deleting tracks — gated behind AuthBlocks login and the `Admin` role. This replaced the former `DeepDrftCli` Terminal.Gui admin tool, which has been retired. -The interesting engineering bet is the **dual-database split**: structured track metadata in SQLite via EF Core, and binary media + per-vault indexes in a hand-rolled `FileDatabase` that lives on disk. The split is enforced across two ASP.NET Core hosts so that the browser never reaches the database directly. +The interesting engineering bet is the **dual-database split**: structured track metadata in PostgreSQL via EF Core, and binary media + per-vault indexes in a hand-rolled `FileDatabase` that lives on disk. The split is enforced through a dedicated authority host (`DeepDrftAPI`) so that the browser never reaches the database directly. --- ## 2. Solution shape (current) -Eight projects in `DeepDrftHome.sln`, plus an external `NetBlocks` referenced from `C:\lib\NetBlocks\`. +Ten projects in `DeepDrftHome.sln`, plus an external `NetBlocks` referenced from `C:\lib\NetBlocks\`. The solution is split into **two independent Blazor applications** — the public site (`DeepDrftPublic`) and the CMS (`DeepDrftManager`) — both fronting a single dual-database authority host (`DeepDrftAPI`). ``` -DeepDrftWeb ASP.NET Core host. Blazor Web App (Server + WASM render modes). - Owns the SQL-backed API (api/track/page), MudBlazor theme/host, - TypeScript→JS audio interop sources under Interop/. -DeepDrftWeb.Client Blazor WebAssembly assembly. All interactive UI lives here — - pages, controls, player services, dark-mode/theme plumbing, - HTTP clients for both backends. -DeepDrftWeb.Services Class library. EF Core: DeepDrftContext, TrackConfiguration, - Migrations, TrackRepository, TrackService. Sharable between - the web host and the CLI (avoids duplicating data-access). +── Public application ────────────────────────────────────────────────────── +DeepDrftPublic ASP.NET Core host. Blazor Web App (Server + WASM render + modes). Owns the browser-facing proxy controller for + api/track/* (metadata listing + audio streaming), + MudBlazor theme prerender, and TypeScript→JS audio interop + sources under Interop/. The public listening surface. +DeepDrftPublic.Client Blazor WebAssembly assembly. All interactive public UI — + pages, the player stack, dark-mode plumbing, HTTP clients + for the backend. Consumed by DeepDrftPublic. -DeepDrftContent ASP.NET Core host. Binary content API (api/track/{id}). - ApiKey middleware, CORS, ForwardedHeaders. Returns audio bytes - (with optional byte offset) and accepts PUT of AudioBinaryDto. -DeepDrftContent.Services Class library. The FileDatabase implementation in full +── CMS application ───────────────────────────────────────────────────────── +DeepDrftManager ASP.NET Core host. Blazor Web App (InteractiveServer). + Hosts all CMS Razor components/pages (Components/Pages/Cms/, + Components/Pages/Tracks/, Components/Layout/CmsLayout.razor, + Components/Shared/ — inlined from the former DeepDrftCms RCL). + Gated by AuthBlocks login + hierarchical Admin role. All track + operations proxy via ICmsTrackService / CmsTrackService. + +── Dual-database authority ───────────────────────────────────────────────── +DeepDrftAPI ASP.NET Core host. The single authority over both databases + (SQL metadata + FileDatabase binary). AuthBlocks API host + (registration, migration/seed, JWT endpoints). Seven track + endpoints (stream, vault write, upload, delete, paged list, + single metadata read, metadata update). +DeepDrftData Class library. EF Core domain logic: DeepDrftContext, + TrackConfiguration, Migrations, TrackRepository, TrackService, + TrackManager. Consumed by DeepDrftAPI and tests. +DeepDrftContent Class library. The FileDatabase implementation in full (Models, Services, Utils, Abstractions, Constants), - WavOffsetService, AudioProcessor, TrackService (the content-side - orchestrator that processes WAVs and stores them in a vault). + WavOffsetService, AudioProcessor, content-side TrackService. + Consumed by hosts and tests. +── Shared ────────────────────────────────────────────────────────────────── +DeepDrftShared.Client Razor Class Library. Shared Blazor components consumed by + BOTH DeepDrftPublic and DeepDrftManager (e.g. TrackCard, + TracksGallery) for consistency across public and admin surfaces. DeepDrftModels Shared contracts: TrackEntity, TrackDto, PagingParameters, - PagedResult. The only project all three layers reference. - -DeepDrftCli Console app. Two modes: classic `add` / `list` / `help` and - `gui` (Terminal.Gui). Consumes BOTH service libraries directly - (it's a local admin tool, not a network client). - + PagedResult, plus waveform DTOs. Every project references this. DeepDrftTests NUnit. Covers the FileDatabase, MediaVault, IndexSystem, - MediaVaultFactory, SimpleMediaTypeRegistry, utility code, and - model behaviour. References DeepDrftContent.Services. + MediaVaultFactory, SimpleMediaTypeRegistry, utility code, model + behaviour, and the waveform loudness algorithm. References + DeepDrftContent. NetBlocks (external) Result patterns: Result, ResultContainer, ApiResult, ApiResultDto. Referenced via absolute path. ``` -Two stray .sln files (`WebAPI.sln`, `WebUI.sln`, `CLI.sln`) exist at the root alongside `DeepDrftHome.sln`. `DeepDrftHome.sln` is the canonical solution; the others appear to be subsets. +**Naming history (for readers of older docs/commits):** `DeepDrftWeb` → `DeepDrftPublic`, `DeepDrftWeb.Client` → `DeepDrftPublic.Client`, `DeepDrftWeb.Services` → `DeepDrftData`, `DeepDrftContent.Services` → `DeepDrftContent` (the host that previously owned the binary API is gone; its proxy duties moved into `DeepDrftPublic`, its authority duties into `DeepDrftAPI`). `DeepDrftCli` and the `DeepDrftCms` RCL have both been removed — the CLI retired in favour of the CMS, and the CMS RCL was inlined into `DeepDrftManager`. + +**Subdomain topology (deployment):** `deepdrft.com` (public) and `manage.deepdrft.com` (CMS), behind nginx. CD infrastructure (Gitea workflows + installer scripts + systemd/nginx templates) has landed — see `COMPLETED.md` "Deployment Infrastructure." --- @@ -147,17 +163,21 @@ In dev, the host serves the original `.ts` sources at `/Interop/...` for source- Recent commits (newest first): -- `style simplification and publish upgrades for dotnet 10` -- `Styles & Home Page Content Cleanup Mobile Menu System & Dark Mode Cookie Theme Draft` -- `Theming Draft 2` -- `2026 Deep DRFT Theme Draft 1 WIP` -- `Spectrum Visualizer for player & Layout` +- `docs: archive play-state icon normalization; update DeepDrftPublic.Client CLAUDE.md` +- `Consolidate play/pause icon logic into PlaybackIcons mapper and PlayStateIcon component` +- `Reflect real playback state on gallery cards and toggle pause/resume` +- `WASM State Fixes` +- `CMS Home autoredirect to /tracks` +- `WaveformSeeker Improvements` / WaveformSeeker waves 1–3 +- (earlier: AudioPlayerBar responsive unification, CMS build-out, the two-app split, deployment infrastructure) -Three observations: +Observations: -1. **The current arc is presentation, not capability.** The last five commits are framework upgrade, theming, content/layout cleanup, mobile menu, dark-mode persistence, and the spectrum visualiser. The playback substrate, streaming, and seek-beyond-buffer machinery landed earlier and is stable enough to support cosmetic iteration on top. -2. **The "Track Gallery" is the only real page.** `/tracks` is the working surface; `/` is marketing copy. Nav (in `Pages.cs`) defines only `Home` + `Track Gallery`. -3. **Content surface is narrow on purpose.** The DeepDrftContent API exposes exactly two routes: `GET api/track/{id}` (with optional `offset`) and `PUT api/track/{id}` (ApiKey). There is no listing endpoint there; listing lives on DeepDrftWeb because listings are SQL queries. +1. **The big structural moves have landed.** Since the last revision of this doc, three large initiatives shipped: the **two-app split** (public/CMS separation with `DeepDrftAPI` as the dual-database authority), the **browser CMS** replacing the CLI (auth via AuthBlocks, stealth-routed `/cms/*`, full add/list/edit/delete parity), and **CD infrastructure** (Gitea workflows + host installer + systemd/nginx templates). The substrate is no longer the frontier — the product and presentation layers are. +2. **The recent arc is player UX polish.** The latest wave of work is the WaveformSeeker (loudness-profile seekbar), AudioPlayerBar responsive unification, and play-state icon normalization (a single `PlaybackIcons` resolver + `PlayStateIcon` component, gallery cards reflecting real playback state with pause/resume). Presentation iteration on a stable streaming core. +3. **The "Track Gallery" is still the only real public content page.** `/tracks` is the working listening surface; `/` is the (reskinned) marketing home. Nav (in `Layout/Pages.cs`) is still essentially `Home` + `Track Gallery`. The CMS adds admin surfaces under `/cms` but those are not public. +4. **The metadata/streaming surface is consolidated on `DeepDrftAPI`.** It exposes seven track endpoints (stream, vault write, upload, delete, paged list, single-metadata read, metadata update) plus waveform endpoints. `DeepDrftPublic` is a thin browser-facing proxy in front of it; the browser never reaches `DeepDrftAPI` or the databases directly. +5. **In flight (working tree, not yet committed):** an **embeddable iframe player** (`EmbedLayout.razor`, `FramePlayer.razor`, a new `ITrackDataService` seam) — a chrome-free single-track play surface for embedding off-site. Partial and not yet compiling; see `PLAN.md` "In-flight — Embeddable iframe player" for the open questions. --- @@ -167,7 +187,7 @@ Captured here so the next round of planning has a starting point — none of thi - **More vault types in active use.** `MediaVaultType.Image` exists end-to-end (tests cover it) but the production surface only registers a `tracks` vault of type `Audio`. The path to releases/albums probably runs through images first (cover art via `ImagePath`, which is currently a free-form URL string). - **More than one collection view.** The `TrackCard` already conditionally renders `ImagePath`, `Album`, `Genre`, `ReleaseDate` — the data shape supports album-grouped or genre-filtered views without schema work. -- **Upload from the web side, not just the CLI.** The CLI is currently the only producer of tracks. A web-side upload would re-use `DeepDrftContent.Services.TrackService.AddTrackFromWavAsync` and pair it with a `TrackService.Create` on the SQL side. The `[ApiKeyAuthorize]` middleware on `PUT api/track/{id}` is already in place. +- **Web upload — landed.** *(Historical note: this was a "likely direction" when the CLI was the only producer. It has since shipped.)* The CMS (`DeepDrftManager`) now produces tracks via `POST api/track/upload` on `DeepDrftAPI`, proxied through the auth-gated CMS surface. The CLI has been retired. The dual-write rollback gap (`PLAN.md §4.3`) still stands. - **Live/session content.** The home page advertises "Live Sessions" and "Video Content (coming soon)". No data model exists for these yet; they would likely need new vault types (`MediaVaultType.Media` is the obvious home for video) and new entity tables. - **Non-WAV formats.** Today the producer side is WAV-only (`AudioProcessor.ProcessWavFileAsync` validates RIFF/WAVE/PCM). `MimeTypeExtensions` already knows mp3/flac/aac/ogg/m4a — the gap is a processor per format and a decoder strategy in the JS player (currently WAV-specific). - **Search / filter on the gallery.** `TracksViewModel` exposes `SortBy` / `IsDescending` but no filter. `TrackService.GetPaged` accepts only sort, not filter. Adding filter would be a natural next step on the same pagination contract. @@ -187,14 +207,20 @@ Captured here so the next round of planning has a starting point — none of thi ## 7. Staleness in existing docs (for doc-keeper to address) -Captured so the next sweep of folder-level `CLAUDE.md` files can correct in one pass. +Two layers of drift remain. The root `CLAUDE.md` and this `CONTEXT.md` are current; the lag is now in **folder-level `CLAUDE.md` files** and the in-tree `FileDatabase` README. `DOC_PLAN.md` holds the per-folder rewrite briefs, but note that `DOC_PLAN.md` itself was authored against the *pre-split* project names (2026-05-16) and is partly superseded — see the warning at the end of this section. -- Every folder `CLAUDE.md` says ".NET 9" / "ASP.NET Core 9.0"; reality is `net10.0` across the board. -- `DeepDrftModels/CLAUDE.md` and `DeepDrftContent.Services/FileDatabase/README.md` reference `TrackEntity.MediaPath`; the field is `EntryKey` and the column is `entry_key`. -- `DeepDrftContent/CLAUDE.md` describes a `FileDatabase/` tree inside `DeepDrftContent/`; that tree has moved entirely to `DeepDrftContent.Services/FileDatabase/`. The DeepDrftContent host now contains only `Controllers/`, `Middleware/`, `Models/` (settings POCOs), `environment/`, `Program.cs`, `Startup.cs`. -- `DeepDrftContent/CLAUDE.md` documents only the PUT endpoint; the production API now also has `GET api/track/{id}?offset=` (unauthenticated read, with `WavOffsetService` for offset streaming). -- `DeepDrftWeb/CLAUDE.md` describes EF Core, repositories, services, migrations as living inside `DeepDrftWeb/Data` and `DeepDrftWeb/Services`. They have all moved to `DeepDrftWeb.Services`. The only things still in `DeepDrftWeb` are `Controllers/TrackController.cs`, `Services/DarkModeService.cs`, `Startup.cs`, `Program.cs`, `Components/`, `Interop/`, `wwwroot/`. -- `DeepDrftWeb.Client/CLAUDE.md` lists the `Pages/` directory as containing `Counter.razor` / `Weather.razor` (demo); those are gone. The real client structure is `Pages/Home.razor` + `Pages/TracksView.razor`, plus the `Controls/AudioPlayerBar/` cluster, `Controls/AudioPlayerProvider.razor`, `Services/AudioInteropService.cs` + `AudioPlayerService.cs` + `StreamingAudioPlayerService.cs` + `IPlayerService.cs` + dark-mode services, `Common/DarkModeSettings.cs` + `Common/DDIcons.cs`, and `Layout/Pages.cs` + `Layout/DeepDrftMenu.razor`. -- The `DeepDrftWeb.Services` and `DeepDrftContent.Services` projects have **no** `CLAUDE.md` yet — they are where most of the domain logic actually lives, so this is the biggest gap. -- `DeepDrftCli/CLAUDE.md` references `appsettings.json`; the CLI actually loads `environment/connections.json` into `CliSettings` (with `ConnectionString` and `VaultPath`). The "Available Commands" section is otherwise current, including the `gui` Terminal.Gui mode and interactive `add`. -- `DeepDrftContent.Services/FileDatabase/README.md` (an in-tree dev README, not a CLAUDE.md) refers to `ImageDirectoryVault`; the type is `ImageVault`. It also describes `EntryKey` as removed in favour of strings, which is accurate, but its diagram still says "FileDatabase.csproj (.NET 9.0)" — the FileDatabase no longer has its own csproj at all (it's a subdirectory of `DeepDrftContent.Services`). +**Project-rename drift (the big one).** The two-app split renamed or removed most projects. Any folder `CLAUDE.md` still using the old names is wrong at the structural level, not just the framework-version level: +- `DeepDrftWeb` → `DeepDrftPublic`; `DeepDrftWeb.Client` → `DeepDrftPublic.Client`; `DeepDrftWeb.Services` → `DeepDrftData`. +- `DeepDrftContent.Services` (class library) is now just `DeepDrftContent`; the old `DeepDrftContent` *host* is gone — binary-API duties split between the `DeepDrftPublic` proxy and the `DeepDrftAPI` authority. +- `DeepDrftCli` and the `DeepDrftCms` RCL are **deleted**. Any `CLAUDE.md` for them should be removed, not rewritten. + +**Known content drift to correct in the sweep:** +- Framework version: any folder `CLAUDE.md` still saying ".NET 9" / "ASP.NET Core 9.0" — reality is `net10.0` across the board. +- `TrackEntity.MediaPath` references (notably the `FileDatabase/README.md`) — the field is `EntryKey`, column `entry_key`. +- The `FileDatabase/README.md` refers to `ImageDirectoryVault` (the type is `ImageVault`) and a "FileDatabase.csproj (.NET 9.0)" that no longer exists (FileDatabase is a subdirectory of `DeepDrftContent`). +- `DeepDrftData` and `DeepDrftContent` are where most domain logic lives and are the highest-value targets for accurate `CLAUDE.md` coverage. + +**Already corrected (no longer stale):** +- `DeepDrftPublic.Client/CLAUDE.md` was rewritten in commit `9110b4b` and reflects the current player stack, `PlaybackIcons`/`PlayStateIcon`, and the post-split structure. + +> **`DOC_PLAN.md` caveat.** `DOC_PLAN.md` predates the two-app split — its per-folder briefs reference `DeepDrftWeb*`, `DeepDrftCli`, and a SQLite backend (now PostgreSQL). Treat its *intent* (lead-with-truth, cross-reference root, no docs for build output) as still valid, but its *project list and per-folder details* need reconciling against the current ten-project solution before doc-keeper executes against it. Flag to Daniel whether to refresh `DOC_PLAN.md` first or let doc-keeper work from the root `CLAUDE.md` directly. diff --git a/DeepDrftPublic.Client/Layout/EmbedLayout.razor b/DeepDrftPublic.Client/Layout/EmbedLayout.razor new file mode 100644 index 0000000..0bdd361 --- /dev/null +++ b/DeepDrftPublic.Client/Layout/EmbedLayout.razor @@ -0,0 +1,5 @@ +

EmbedLayout

+ +@code { + +} \ No newline at end of file diff --git a/PLAN.md b/PLAN.md index c0cc718..41c08b3 100644 --- a/PLAN.md +++ b/PLAN.md @@ -6,15 +6,25 @@ Organised by **theme**, not by date. Themes are roughly ordered by current produ --- -## In-flight — Two-app architectural split +## In-flight — Embeddable iframe player -The public site and the CMS are being split into two independent Blazor applications. **Design locked by Daniel 2026-05-19** at `design/TWO-APP-SPLIT.md` §10. All ten open questions resolved. Implementation phases ready to schedule in the phased rollout at §8. +A standalone, chrome-free player surface intended for embedding in an `