Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .squad/agents/book/history.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Project Context

## 2026-04-30 — v0.8 Milestone Role Assignment

**Role:** Plugin Ecosystem Documentation Lead (v0.8.1–0.8.3 Tier 3)
**Effort:** 4–6 hours
**Timeline:** v0.8.0 completion → 4–6 weeks (Tier 3)

**Tier 3 (plugin ecosystem):**
- #339 — Documentation for plugin authors (4-6h) — guides, examples, API reference

**Support:**
- Coordinate with River (#166 plugin packager) on CLI documentation and authoring workflow
- Work in parallel with River/Simon on plugin ecosystem features; documentation follows code

**Sync point:** Await Tier 1-2 completion; docs can begin once #166 CLI spec is finalized (early in sprint). Deliver with v0.8.1 release.

# Project Context

- **Owner:** Jeffrey T. Fritz
- **Project:** SharpSite — a modern, accessible CMS built with .NET 9 and Blazor
- **Stack:** .NET 9, Blazor (SSR + Interactive Server), ASP.NET Core, Entity Framework Core, PostgreSQL, Docker, Playwright, xUnit, GitHub Actions
Expand All @@ -8,3 +25,10 @@
## Learnings

<!-- Append new learnings below. Each entry is something lasting about the project. -->

---
**[SCRIBE UPDATE - 2026-04-30 20:15:51]**
- Decision inbox merged (15 decisions)
- v0.8.0 scope locked and confirmed
- Cross-agent context synchronized
- Ready for parallel execution
7 changes: 7 additions & 0 deletions .squad/agents/inara/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@
## Learnings

<!-- Append new learnings below. Each entry is something lasting about the project. -->

---
**[SCRIBE UPDATE - 2026-04-30 20:15:51]**
- Decision inbox merged (15 decisions)
- v0.8.0 scope locked and confirmed
- Cross-agent context synchronized
- Ready for parallel execution
16 changes: 16 additions & 0 deletions .squad/agents/jayne/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,19 @@ When moving a commit from one branch to another without rewriting remote history
4. Clean up stale `.git/index.lock` if git operations hang (e.g., from crashed prior processes)
5. After cherry-pick succeeds, push destination branch; source branch remains untouched
**Rationale:** Safer than rebasing for remote-tracked branches — no rewrite risk, clear audit trail. Source commit stays on its branch.

### v0.7 Release: Tag & GitHub Release (2026-04-30)
Completed end-to-end release process for v0.7:
1. Verified PR #304 merged to `upstream/main` (commit `c35e5e06c5e17b3e0fbada8fb006d30dadcbf5e6`)
2. Created annotated tag `v0.7` locally
3. Pushed tag to `upstream` with explicit `refs/tags/v0.7` (necessary because a branch named `v0.7` existed from earlier fetch)
4. Created GitHub release with auto-generated changelog (v0.2...v0.7)
5. Release URL: https://github.com/csharpfritz/SharpSite/releases/tag/v0.7
**Key Learning:** Explicit tag refspec (`refs/tags/v0.7`) prevents ambiguity when a branch and tag share names. GitHub release auto-notes work well after v0.2 baseline is established.

---
**[SCRIBE UPDATE - 2026-04-30 20:15:51]**
- Decision inbox merged (15 decisions)
- v0.8.0 scope locked and confirmed
- Cross-agent context synchronized
- Ready for parallel execution
55 changes: 55 additions & 0 deletions .squad/agents/kaylee/history.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
# Project Context

## 2026-04-30 — v0.8 Milestone Role Assignment

**Role:** Test Coverage Lead (v0.8.1–0.8.3 Tier 3)
**Effort:** 5–7 hours
**Timeline:** v0.8.0 completion → 4–6 weeks (Tier 3)

**Tier 3 (plugin ecosystem):**
- #341 — Unit tests for PluginPackager (3-4h) — testing infrastructure for #166
- #319 — E2E test cases (2-3h) — support Wash; cover OOTB experience gaps

**Support:**
- Support River on plugin ecosystem test cases; Kaylee to suggest test structures for #166, #336, #334, #254

**Sync point:** Await Tier 1 completion (E2E framework stability) before #319 test spike. Coordinate with River on packager test harness design (early in #166 work).

### 2026-04-30 — Simon Admin Asset + River Trash Delete: Test Infrastructure Ready

**Status:** Completed (Simon) + Proposed (River)
**Issues:** #320, #321, #323, #322 (Simon) | #309, #299 (River delete contract)

**Simon's Asset Component Tests:**
- `SiteAssetManager` Blazor component now testable
- Test patterns: upload validation, preview URL generation, removal behavior
- Reusable across setup wizard (Step 2) and admin maintenance
- Build: 57/57 tests passing

**River's Trash Delete Contract:**
- Backend pattern defined: `ITrashableContent` + repository extensions (`GetDeleted*`, `Restore*`, `PermanentlyDelete*`)
- Normal queries exclude trashed records by default
- Soft delete (archive + recovery) instead of hard delete

**Impact on Kaylee:**
- **Asset Component Tests:** Can now write unit tests for `SiteAssetManager` (upload validation, error cases, state updates)
- **Trash/Restore Tests:** Clear backend contract for test cases (delete → GetDeleted, restore → Restore, purge → PermanentlyDelete)
- **Test Scope:** Asset tests in Tier 2 support (Simon phase); trash tests in Tier 3 support (River phase)

**Next:** Coordinate with River on trash test harness design as #309/#299 scope activates post-Tier 1.



- **Owner:** Jeffrey T. Fritz
- **Project:** SharpSite — a modern, accessible CMS built with .NET 9 and Blazor
- **Stack:** .NET 9, Blazor (SSR + Interactive Server), ASP.NET Core, Entity Framework Core, PostgreSQL, Docker, Playwright, xUnit, GitHub Actions
Expand All @@ -25,3 +65,18 @@ River completed the Security P0 Remote Code Execution vulnerability fix (#346).
- `tests/SharpSite.Tests.Plugins/ConcurrentAccessTests.cs` — Issue #348: 3 tests for concurrent PluginAssemblyManager AddAssembly/RemoveAssembly and read-while-write safety.
- **Lambda discard gotcha**: Don't use `_ =` for discards inside lambdas where `_` is already the lambda parameter (causes CS0029). Use named locals instead.
- **Central Package Management**: Test projects use `<PackageReference Include="..." />` without `Version` attribute; versions are in `Directory.Packages.props`.

### 2026-04-30 — Trash repository unit coverage for pages and posts
- **Repository harness**: `PgPageRepository` and `PgPostRepository` can be exercised deterministically with EF Core InMemory by registering `PgContext` against a shared `InMemoryDatabaseRoot` in a per-test `ServiceProvider`.
- **Coverage seam**: Trash tests should assert both persistence state (`IsDeleted`, `DeletedAt`) and read-path behavior (`Get*`, `GetDeleted*`, restore, purge) so soft delete never leaks back into normal queries.
- **Page add gotcha**: `PgPageRepository.AddPage` saves a cast copy and returns the original `Page`, so the generated database `Id` is not populated on the returned object; tests must re-read the stored page before using its key.
- **Files added**:
- `tests/SharpSite.Tests.Web/Data/Postgres/PgPageRepositoryTrashTests.cs`
- `tests/SharpSite.Tests.Web/Data/Postgres/PgPostRepositoryTrashTests.cs`

---
**[SCRIBE UPDATE - 2026-04-30 20:15:51]**
- Decision inbox merged (15 decisions)
- v0.8.0 scope locked and confirmed
- Cross-agent context synchronized
- Ready for parallel execution
66 changes: 40 additions & 26 deletions .squad/agents/mal/history.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,53 @@
# Project Context

- **Owner:** Jeffrey T. Fritz
- **Project:** SharpSite a modern, accessible CMS built with .NET 9 and Blazor
- **Project:** SharpSite a modern, accessible CMS built with .NET 9 and Blazor
- **Stack:** .NET 9, Blazor (SSR + Interactive Server), ASP.NET Core, Entity Framework Core, PostgreSQL, Docker, Playwright, xUnit, GitHub Actions
- **Created:** 2026-03-26

## Learnings
## Core Context

<!-- Append new learnings below. Each entry is something lasting about the project. -->
**v0.8.0 Sprint (CURRENT - Locked & Ready)**
- **Status:** Locked scope; all clarifications answered; squad ready for execution
- **8 Active Issues:** 3647h total (Tier 1: ship-blockers; Tier 2: core CMS)
- **Squad Assignments:**
- Simon: #322 (setup), #323 (favicon), #320 (logo), #321 (logo-display), #328 (CSS) 5 issues, 1623h
- River: #309 (page-delete), #299 (post-delete) 2 issues, 1216h
- Wash: #319 (E2E tests) 1 issue, 810h
- Zoe: Supporting (badges) 34h (waiting)
- **First Batch Ready:** #322, #323, #319, #309, #299 (zero blockers)
- **Critical Path:** Parallel execution; Tier 1 + Tier 2 concurrent
- **Execution:** Ready to launch now

### 2026-03-26 — Issue Triage Results (6 squad-labeled issues)
**Clarifications Resolved (v0.8 Planning)**
- #208/#209 (file browser): Both ship in v0.8.0
- #212 (autosave): Deferred to v0.8.1+ (scope creep)
- #203/#117/#118 (plugin lifecycle): Deferred to v0.8.1+
- #313 (CSP header): Deferred to v0.8.1+
- #297 (home post display): Deferred

**Routed to squads:**
- **River** (Backend): #346 (P0 RCE), #347 (ZIP bomb), #348 (thread safety), #349 (plugin signing)
- **Simon** (Frontend): #350 (forced password reset UI)
- **Wash** (E2E): #351 (.NET 10 validation)
**v0.7 Completion & v0.8 Planning (Pre-May 2026)**
- Triaged 73 open issues; identified 8 core items for v0.8
- v0.7 blockers resolved: Security P0s (#346 RCE, #347 ZIP bomb, #348 threading) + build stabilization
- Plugin architecture assessed; three security gaps addressed in v0.7 fixes
- GitHub Issues re-enabled by owner (was disabled, blocking triage)
- v0.8 milestone applied to 8 active issues; v0.7 stragglers triaged/deferred

**Priority ordering:**
1. #346: Security P0 RCE via TypeNameHandling.Auto → **blocks production**
2. #347, #349: Security vulnerabilities (plugin extraction, DLL validation) → **blocks production**
3. #348: Thread-safety bug (PluginManager static state) → **critical correctness**
4. #350: Security hardening (forced password reset) → **medium priority**
5. #351: .NET 10 validation → **mostly done, E2E pending**
## Recent Decisions

All issues labeled with `squad:{member}` and triage comments added. Labels created: squad:river, squad:simon, squad:wash.
*All decisions merged to .squad/decisions.md (canonical source)*

### 2026-03-26 — Plugin System Architecture Review (spike_DatabasePlugin branch)
**2026-05-03:** v0.8.0 squad assignment locked. 8 issues routed per expertise; sequencing confirmed; no blockers.

- **Branch health: RED** — Build fails with 60 errors. Root cause is type ambiguity between `SharpSite.Abstractions.Security` types and `Microsoft.AspNetCore.Identity` types in `src/SharpSite.Security.Postgres/`. The security abstraction migration is incomplete.
- **Plugin system architecture** is convention-based + attribute-driven. Plugins are `.sspkg` ZIP files loaded via collectible `AssemblyLoadContext`. Services registered via `RegisterPluginAttribute` and reflection scanning in `PluginManager.RegisterWithServiceLocator()`.
- **Critical security finding:** `ApplicationState.cs` uses `TypeNameHandling.Auto` with Newtonsoft.Json — a known RCE deserialization vector (lines 130-134, 212-216). Must be fixed before production.
- **Critical security finding:** No assembly validation, code signing, or integrity checking on plugin DLLs. Any DLL in the plugins directory runs with full app permissions.
- **Plugin extension points:** FileStorage, DataStorage (Config, EfContext, PageRepo, PostRepo), Security (SignIn, UserManager, UserRepo, EmailSender). Mapped in `PluginTypeMapping.cs`.
- **Static mutable state** in `PluginManager` (`_ServiceDescriptors`, `_ServiceProvider`) is a thread safety concern.
- **`IRunAtStartup` interface** is defined but never invoked by the PluginManager — lifecycle hooks are dead code.
- **Postgres plugin `manifest.json` is empty** (0 bytes) — would fail validation through standard plugin loading.
- **Hardcoded default admin** (`admin@localhost` / `Admin123!`) in the Postgres plugin's `RegisterPluginServices.cs`.
- Full analysis written to `.squad/decisions/inbox/mal-plugin-analysis.md`.
**2026-05-01:** File browser clarification (#208/#209); plugin lifecycle deferral (#203/#117/#118); autosave deferral (#212).

**2026-04-30:** GitHub issues enabled; milestone triage complete; 10 v0.7 items deferred to backlog.

---

**[SCRIBE UPDATE - 2026-04-30 20:18:02]**
- Decision inbox merged (15 decisions into decisions.md)
- v0.8.0 scope confirmed locked
- Cross-agent context synchronized
- Ready for parallel execution
- Agent history files updated across team
7 changes: 7 additions & 0 deletions .squad/agents/ralph/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ Ralph initialized. Team cast from Firefly universe on 2026-03-26.
## Learnings

📌 Team initialized on 2026-03-26 — 9 agents + Scribe + Ralph

---
**[SCRIBE UPDATE - 2026-04-30 20:15:51]**
- Decision inbox merged (15 decisions)
- v0.8.0 scope locked and confirmed
- Cross-agent context synchronized
- Ready for parallel execution
89 changes: 89 additions & 0 deletions .squad/agents/river/history.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,73 @@
# Project Context

## 2026-04-30 — v0.8 Milestone Role Assignment

**Role:** Plugin Ecosystem Lead (v0.8.0 → v0.8.x)
**Effort:** 35–40 hours
**Timeline:** v0.8.0 (6 weeks), v0.8.1–0.8.3 (4–6 weeks)

**Tier 1 (concurrent):**
- #309 — Delete a page (4-6h) — data layer + API + UI
- #299 — Delete a post (2-3h) — similar scope

**Tier 3 (after Tier 1-2):**
- #166 — Plugin packager tool (8-10h) — CLI to build .sspkg files
- #336 — Upload plugins without install (4-6h) — staging area
- #334 — Choose DB plugin during install (6-8h) — installer backend + setup
- #254 — Move Postgres to plugin (6-8h) — refactor + migration tests

**Key risks:** Plugin packager complexity (mitigate: spike week 1), DB plugin refactor data loss risk (dry-run first).

**Sync point:** v0.8.0 ship decision gates all Tier 3 work. Coordinate with Simon (installer UX) and Zoe (CI).

### 2026-05-01 — v0.8 Tier 2 Backend Work Queued: Delete Pages/Posts Clarification Pending

**Status:** QUEUED pending Tier 1 completion + clarification
**Issues:** #309 (Delete page), #299 (Delete post)
**Effort:** 6–9 hours combined (Tier 1 Phase 2 work)
**Critical Gap:** Delete semantics undefined — hard delete or soft (archive with recovery)?

**Impact on River:**
- Cannot scope #309/#299 schema/data layer changes until delete semantics clarified
- Hard delete is simpler (2–3h); soft delete with archive complicates schema by 2–3x (4–6h)

**Dependencies:**
- Tier 1 completion (Wash's #319, #351, #272 + Simon's #350) gates start
- User clarification on delete semantics required (Q5 in Tier 2 phase)

**Next Action:** User provides delete semantics; Mal updates #309/#299 with acceptance criteria. River can then scope schema/API work post-Tier 1.

### 2026-04-30 — River Trash Delete Backend Contract Documented (Proposed)

**Status:** Proposed
**Issues:** #309 (Delete page), #299 (Delete post)

**Backend Contract Finalized:**
- Pattern: Soft delete (archive + recovery) via `ITrashableContent` + repository extensions
- Methods: `GetDeleted*()`, `Restore*()`, `PermanentlyDelete*()`
- Normal queries exclude trashed records by default
- Deterministic behavior: delete → soft archive; restore → un-archive; purge → permanent removal

**Schema Impact:**
- Soft delete requires `IsDeleted` flag + optional `DeletedAt` timestamp on pages/posts tables
- Complexity: ~4–6 hours for dual-repository implementation + migration tests
- Risk mitigation: Dry-run migration on test DB first

**Simon UI Contract:**
- Delete button: calls `DeletePage(int id)` / `DeletePost(string slug)` (soft delete)
- Trash UI (future): reads `GetDeletedPages()` / `GetDeletedPosts()`
- Restore actions: calls `RestorePage(int id)` / `RestorePost(string slug)`
- Purge actions: calls `PermanentlyDeletePage(int id)` / `PermanentlyDeletePost(string slug)`

**Impact on River:**
- Ready to spike schema + migration design once Tier 1 completes
- Test infrastructure (trash/restore patterns) ready; Kaylee can define test cases early
- Unblocks Simon's future Trash UI work (backend contract clear)

**Next:** Await Tier 1 completion + #309/#299 scope activation; coordinate with Kaylee on test harness design.



- **Owner:** Jeffrey T. Fritz
- **Project:** SharpSite — a modern, accessible CMS built with .NET 9 and Blazor
- **Stack:** .NET 9, Blazor (SSR + Interactive Server), ASP.NET Core, Entity Framework Core, PostgreSQL, Docker, Playwright, xUnit, GitHub Actions
Expand All @@ -9,6 +77,12 @@

<!-- Append new learnings below. Each entry is something lasting about the project. -->

### 2026-05-03 — Trash Delete Pattern for Pages and Posts

Pages and posts now share a trash-state contract via `ITrashableContent` plus `TrashableContentExtensions` in `SharpSite.Abstractions`. The delete flow is soft delete only: repository `Delete*` methods mark `IsDeleted = true`, stamp `DeletedAt`, and all normal `GetPage/GetPages/GetPost/GetPosts` queries exclude trashed content by default.

Both `SharpSite.Data.Postgres` and `SharpSite.Plugins.Data.Postgres` expose the same recovery contract: `GetDeleted*`, `Restore*`, and `PermanentlyDelete*`. EF migrations `20260503101500_AddTrashStateToPagesAndPosts` in both projects add the shared `IsDeleted`/`DeletedAt` columns needed for recycle-bin behavior.

### 2026-03-26 — Security Context from Mal's Analysis

River should be aware of two critical P0 security issues identified on spike_DatabasePlugin branch:
Expand Down Expand Up @@ -49,6 +123,14 @@ Fixed remaining build error in `RegisterPostgresSecurityServices.cs:33`. The `Sh
- Updated test file `WhenFileExists.cs` to use `System.Text.Json`.
- All 47 unit tests pass. Build is clean.

---
**[SCRIBE UPDATE - 2026-05-01 00:02:00Z — Kaylee Trash Backend Unit Tests Completed]**
- Kaylee completed repository-level unit test harness validating River's trash backend contracts (#309/#299)
- Tests cover: soft delete, restore, permanent purge, trashed-content exclusion
- All test projects passing (SharpSite.Tests.Web ✅, SharpSite.Tests.Plugins ✅)
- **Critical correctness note propagated:** `PgPageRepository.AddPage()` returns the caller's original `Page` instance, NOT the tracked `PgPage`. Generated database `Id` is NOT populated on the returned object. Any caller needing the persisted key must re-read after insertion. This applies to repository callers in API endpoints (Simon) and wherever Page objects are materialized.
- River's trash delete backend (#309/#299) contracts validated; ready for Simon API integration and Wash E2E testing

**Pattern to remember:** For any future polymorphic serialization in the plugin system, use the `ConfigurationSectionJsonConverter` pattern: validate the resolved type implements the expected interface before instantiation. Never allow arbitrary type resolution from JSON input.

### 2026-03-31 — Security: ZIP Bomb & Path Traversal Protection in Plugin Extraction
Expand Down Expand Up @@ -97,3 +179,10 @@ Fixed remaining build error in `RegisterPostgresSecurityServices.cs:33`. The `Sh
**Pattern to remember:** For plugin integrity, validate at two points: (1) the file hash before loading bytes into memory, and (2) the assembly metadata after loading. Store hashes on first install and verify on every subsequent load. At startup, catch validation failures per-plugin and `continue` to avoid one bad plugin blocking all others.

**Cross-agent coordination:** Simon's #350 forced password reset is independent; no blocking dependencies.

---
**[SCRIBE UPDATE - 2026-04-30 20:15:51]**
- Decision inbox merged (15 decisions)
- v0.8.0 scope locked and confirmed
- Cross-agent context synchronized
- Ready for parallel execution
7 changes: 7 additions & 0 deletions .squad/agents/scribe/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ Scribe initialized. Team cast from Firefly universe on 2026-03-26.
## Learnings

📌 Team initialized on 2026-03-26 — 9 agents + Scribe + Ralph

---
**[SCRIBE UPDATE - 2026-04-30 20:15:51]**
- Decision inbox merged (15 decisions)
- v0.8.0 scope locked and confirmed
- Cross-agent context synchronized
- Ready for parallel execution
Loading
Loading