Skip to content

[RELEASE] Sprint 19 — Polish, Markdown Editor & Categories#352

Merged
mpaulosky merged 59 commits into
mainfrom
dev
May 23, 2026
Merged

[RELEASE] Sprint 19 — Polish, Markdown Editor & Categories#352
mpaulosky merged 59 commits into
mainfrom
dev

Conversation

@mpaulosky

Copy link
Copy Markdown
Owner

Sprint 19 Release — Polish & Documentation

Promotes devmain for Sprint 19.

Release Checklist

  • Latest dev CI is green (Squad CI, Test Suite, CodeQL, Preview Validation)
  • Sprint 19 milestone: 0 open issues, 28 closed
  • Release scope reviewed
  • Breaking changes documented
  • Release notes drafted

What's in this release

✨ Features

  • Markdown Editor: Replaced InputTextArea with RTBlazorfied rich text editor + HtmlSanitizer backend in Create and Edit flows
  • Categories CRUD: Full categories management UI + blog post category assignment
  • Category UX Polish: Refined category UX, test naming, and documentation

⚙️ Platform

  • Upgraded to .NET 10 from .NET 9
  • Aspire & markdown packages upgraded
  • MongoDB pinned to mongo:7 with mongo-data-v7 volume

🐛 Bug Fixes

🧪 Tests

  • bUnit: Sprint 19 markdown editor lifecycle and interop validation
  • UX parity hardening for Create/Edit markdown editor

🔧 Tooling / Docs

  • Added markdownlint gate to pre-push hook and aligned docs
  • Dependabot: upgraded GitHub Actions group (6 updates)
  • Dotnet SDK bumped to 10.0.300

Closes milestone: Sprint 19 — Polish & Documentation (#19)

mpaulosky and others added 30 commits May 8, 2026 09:24
…rceBuilderExtensions (#262)

## Summary

Extracts the inline `WithCommand` clear-data block from `AppHost.cs`
into a new `MongoDbResourceBuilderExtensions` class.

## Changes

- **New**: `src/AppHost/MongoDbResourceBuilderExtensions.cs` — contains
`WithMongoDbDevCommands` public entry point and private
`WithClearDatabaseCommand`
- **Simplified**: `src/AppHost/AppHost.cs` — reduced from ~157 lines to
~30 lines; single `mongo.WithMongoDbDevCommands("myblog")` call

## Testing

All 10 existing tests pass:
- 5 unit tests in `MongoDbClearCommandTests`
- 5 integration tests in `MongoClearDataIntegrationTests`

Closes #259
Working as Sam (Backend/.NET)

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…leased (#257)

## Summary

Fixes the `squad-mark-released` workflow which was failing with:
> `GraphqlResponseError: Resource not accessible by integration`

## Root Cause

`GITHUB_TOKEN` cannot access GitHub Projects V2 via GraphQL mutations.
This is a known GitHub limitation — Projects V2 mutations require a PAT
with `project` scope.

## Fix

Swap `secrets.GITHUB_TOKEN` → `secrets.GH_PROJECT_TOKEN`, which is the
PAT already used by `project-board-automation.yml` and
`add-issues-to-project.yml` for Projects V2 access.

## Board Update

The v1.4.0 board update was performed manually — 22 items moved from
**Done → Released** directly via GraphQL.

## Related

- Fixes the `squad-mark-released` auto-trigger failure for v1.4.0
- Ensures future releases auto-update the board correctly

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #260

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #261

Adds `WithShowStatsCommand` — the third and final Aspire dashboard command in `MongoDbResourceBuilderExtensions`:
- Command name `show-myblog-stats`, icon `ChartMultiple`, non-highlighted
- Markdown table of collection → document count via `_clearMutex` non-blocking guard
- Empty DB returns `*(no collections found)*` row; `system.*` collections filtered
- 5 unit tests + 3 integration tests (concurrent-invocation fix: seed 50 docs)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ensions (#267)

## Summary

Renames the shared semaphore `_clearMutex` → `_dbMutex` in
`MongoDbResourceBuilderExtensions`.

The semaphore guards all three MongoDB dev commands (Clear, Seed,
Stats), not just clear. The old name was misleading.

## Changes
- `src/AppHost/MongoDbResourceBuilderExtensions.cs`: rename field
declaration and all 6 usage sites (3× WaitAsync + 3× Release) plus
updated comment

## Testing
- Build: ✅ 0 errors
- Architecture.Tests: ✅ 15/15
- Domain.Tests: ✅ 42/42
- Integration.Tests: ✅ 12/12
- No behavior change — rename only

Closes #266

Working as Sam (Backend / .NET)

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary

The `blog-readme-sync.yml` workflow was pushing `README.md` updates
directly to `main`, which is blocked by branch protection rules.

## Fix (Option C)

Changed the push target from `git push` (implicit HEAD → main) to `git
push origin HEAD:dev`.

- The workflow still **triggers** on `push: branches: [main]` (reads
`docs/blog/index.md` from main)
- The **README update** is now pushed to `dev`, flowing through the
normal dev→main release cycle
- No new secrets or PAT bypass permissions required
- `permissions: contents: write` was already present

## Root Cause

```
remote: GH013: Repository rule violations found for refs/heads/main.
remote: - Changes must be made through a pull request.
remote: - Required status check "Build Solution" is expected.
```

Closes #269

Working as Boromir (DevOps)

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… squad-mark-released (#271)

## Summary

Working as Boromir (DevOps)

Closes #268

## Root Cause

The workflow was failing with `Resource not accessible by integration`
because:

1. `permissions: repository-projects: write` only controls
`GITHUB_TOKEN` — it has **no effect** on a custom PAT passed via
`github-token:`
2. When `GH_PROJECT_TOKEN` secret is not set, `actions/github-script`
receives an empty string and falls back to using `GITHUB_TOKEN`, which
**cannot** access GitHub Projects V2 GraphQL regardless of the
permissions block

## Changes

- **Fix permissions block**: `repository-projects: write` → `contents:
read` (correct for workflows that rely exclusively on a custom PAT)
- **Add pre-flight validation step**: Checks `GH_PROJECT_TOKEN` is set;
fails early with an actionable error message if missing (includes setup
instructions and required scope)
- **Downgrade `actions/github-script@v9` → `@v7`** (stable LTS version)
- **Add top-of-file comment** documenting that a classic PAT with
`project` OAuth scope is required

## Setup Required

To make this workflow functional, add `GH_PROJECT_TOKEN` as a repository
secret:
1. Create a classic PAT at https://github.com/settings/tokens with
`project` scope
2. Add it: Settings → Secrets and variables → Actions → New repository
secret → `GH_PROJECT_TOKEN`

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Root Cause

The three `*_Concurrent_Invocations_Allow_Only_One_Run` tests fired two
`ExecuteCommand` calls **sequentially on the same thread**:

```csharp
var firstTask = annotation.ExecuteCommand(MakeContext());  // runs sync to first I/O yield
var secondTask = annotation.ExecuteCommand(MakeContext()); // runs AFTER first completes?
```

Each call executes the async lambda synchronously until its first
genuine `await` point. Against a warm, fast, local MongoDB container
(exactly CI's hot-path after fixture startup), `InsertManyAsync` for 3
small documents can return a synchronously-completed task — meaning the
entire first invocation (including the `finally { _dbMutex.Release() }`)
runs before the second call even begins. At that point the semaphore
count is back to 1, the second call also acquires it, and both succeed →
assertion blows up with `found 2`.

This explains the **intermittent** nature: sometimes MongoDB I/O
genuinely yields (test passes), sometimes it completes inline (test
fails).

## Fix

Dispatch both calls via `Task.Run` held behind a `SemaphoreSlim(0,2)`
start gate:

```csharp
var ct = TestContext.Current.CancellationToken;
using var startGate = new SemaphoreSlim(0, 2);

var firstTask  = Task.Run(async () => { await startGate.WaitAsync(ct); return await annotation.ExecuteCommand(MakeContext()); }, ct);
var secondTask = Task.Run(async () => { await startGate.WaitAsync(ct); return await annotation.ExecuteCommand(MakeContext()); }, ct);

startGate.Release(2); // both workers race for _dbMutex simultaneously
var results = await Task.WhenAll(firstTask, secondTask);
```

Both workers are released at the same instant so they **race** to
`_dbMutex.WaitAsync(0)`. One wins (proceeds with MongoDB I/O) and the
other loses (returns the `already in progress` failure) —
deterministically, regardless of MongoDB response time.

## Affected Tests

-
`MongoSeedDataIntegrationTests.SeedMyBlogData_Concurrent_Invocations_Allow_Only_One_Run`
-
`MongoClearDataIntegrationTests.ClearMyBlogData_Concurrent_Invocations_Allow_Only_One_Run`
-
`MongoShowStatsIntegrationTests.ShowMyBlogStats_Concurrent_Invocations_Allow_Only_One_Run`

Production code (`MongoDbResourceBuilderExtensions.cs`) is unchanged —
the `_dbMutex` logic is correct.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary

Merges 4 pending inbox decisions into `.squad/decisions.md`:

- **Decision #22:** Aragorn gate — PR #272 Release Sprint 18 approved
- **Decision #23:** Aragorn gate — PR #273 AppHost.Tests flake hardening
approved
- **Decision #24:** Gimli — Two-tier test strategy for AppHost Clear
Command (#248)
- **Decision #25:** Gimli — TDD as default approach (charter supplement)

Also updates agent history files for Aragorn, Boromir, Sam, and Scribe.

No source code changes. Squad docs only.

---
_Opened by Scribe (squad automation)_

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Squash-merges Sprint 18 release decisions into .squad/decisions.md and .squad/decisions/decisions.md, and logs the 2026-05-08 board sweep and CI-fix sprint in Ralph's agent history.

Closes #278

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary
Fix the profile email display when the authenticated principal exposes a
legitimate email through alternate claim forms, and keep the Auth0
management client compatible with both current and legacy configuration
keys.

Working as Sam (Backend / .NET). Ralph coordinated final delivery.

## What changed
- `src/Web/Program.cs`
- Requests the `email` scope alongside `openid profile` so Auth0 can
issue the direct email claim when available.
- `src/Web/Features/UserManagement/Profile.razor`
- Preserves direct `email` claim handling and falls back to alternate
legitimate authenticated email claim forms before rendering the profile
card.
- `tests/Architecture.Tests/ProfileEmailAuthContractTests.cs`
  - Locks in the explicit `email` scope requirement in `Program.cs`.
- `tests/Web.Tests.Bunit/Features/ProfileTests.cs`
- Adds regressions for both direct email claims and fallback shapes such
as `preferred_username`.
- `src/Web/Features/UserManagement/UserManagementHandler.cs`
- Resolves Auth0 Management API settings from both `Auth0Management:*`
and legacy `Auth0:ManagementApi*` keys, treats whitespace as missing,
and preserves explicit configuration and HTTP failure behavior.

## Validation
- Focused tests
- `tests/Architecture.Tests/Architecture.Tests.csproj --filter
ProfileEmailAuthContractTests`: 1 passed
- `tests/Web.Tests.Bunit/Web.Tests.Bunit.csproj --filter ProfileTests`:
7 passed
- `tests/Web.Tests/Web.Tests.csproj --filter
UserManagementHandlerTests`: 16 passed
- Full suite
  - `tests/Web.Tests/Web.Tests.csproj`: 148 passed, 0 failed
- AppHost runtime verification
  - Started `src/AppHost/AppHost.csproj`
  - Authenticated via `/test/login?role=Admin`
  - Confirmed `/profile` renders `test@example.com` in the live app
- Real Auth0 verification
- Prior branch validation also included a real Auth0 check to confirm
the profile email renders for a genuine authenticated principal

Closes #278

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary
- remove the remaining Release analyzer warnings in the backend, infra,
and test-project slice
- keep the production diff focused to the warning fixes plus the final
build log update
- re-establish a zero-warning Release build baseline for this issue
branch

## What changed
- add `ConfigureAwait(false)` to the async warning hotspots in
validation, repository, and cache paths
- rename the ServiceDefaults extension container and add targeted null
guards where analyzers required them
- add centralized `[tests/**/*.cs]` analyzer suppressions in
`.editorconfig` for repo-wide test-only xUnit naming and
focused-sync-validator noise
- document the final zero-warning baseline and verification pass in
`docs/build-log.txt`

## Verification
- `dotnet build MyBlog.slnx --configuration Release --no-restore`
- `dotnet test tests/Architecture.Tests/Architecture.Tests.csproj
--configuration Release --no-build`
- `dotnet test tests/Domain.Tests/Domain.Tests.csproj --configuration
Release --no-build`
- `dotnet test tests/Web.Tests/Web.Tests.csproj --configuration Release
--no-build`
- `dotnet test tests/Web.Tests.Integration/Web.Tests.Integration.csproj
--configuration Release --no-build`

Working as Boromir (DevOps / Infra)

Closes #280

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: GitHub Copilot <copilot@users.noreply.github.com>
## Summary
- preserve the original copyright year when normalizing an existing
header block
- collapse duplicate top-of-file copyright headers into one canonical
header
- document the year-preservation rule in the header update prompt

## Validation
- `dotnet build MyBlog.slnx --configuration Release --no-restore`
- `dotnet test tests/Architecture.Tests/Architecture.Tests.csproj
--configuration Release --no-build`
- `dotnet test tests/Domain.Tests/Domain.Tests.csproj --configuration
Release --no-build`
- `dotnet test tests/Web.Tests/Web.Tests.csproj --configuration Release
--no-build`
- `dotnet test tests/Web.Tests.Bunit/Web.Tests.Bunit.csproj
--configuration Release --no-build`
- `dotnet test tests/Web.Tests.Integration/Web.Tests.Integration.csproj
--configuration Release --no-build`
- `dotnet test tests/AppHost.Tests/AppHost.Tests.csproj --configuration
Release --no-build`

Closes #284

Co-authored-by: Boromir <boromir@squad.dev>
- add dotnet format verification to the pre-push hook
- document the renumbered hook gates and install output
- include the required formatting cleanup so the new gate passes on merge

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- centralise repeated table, form, alert, and secondary button styles in input.css
- update Razor views to consume the shared classes
- align Tailwind build scripts and the bUnit smoke assertion with the refactor

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…s group (#281)

Bumps the all-actions group with 1 update:
[actions/github-script](https://github.com/actions/github-script).

Updates `actions/github-script` from 7 to 9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/github-script/releases">actions/github-script's
releases</a>.</em></p>
<blockquote>
<h2>v9.0.0</h2>
<p><strong>New features:</strong></p>
<ul>
<li><strong><code>getOctokit</code> factory function</strong> —
Available directly in the script context. Create additional
authenticated Octokit clients with different tokens for multi-token
workflows, GitHub App tokens, and cross-org access. See <a
href="https://github.com/actions/github-script#creating-additional-clients-with-getoctokit">Creating
additional clients with <code>getOctokit</code></a> for details and
examples.</li>
<li><strong>Orchestration ID in user-agent</strong> — The
<code>ACTIONS_ORCHESTRATION_ID</code> environment variable is
automatically appended to the user-agent string for request
tracing.</li>
</ul>
<p><strong>Breaking changes:</strong></p>
<ul>
<li><strong><code>require('@actions/github')</code> no longer works in
scripts.</strong> The upgrade to <code>@actions/github</code> v9
(ESM-only) means <code>require('@actions/github')</code> will fail at
runtime. If you previously used patterns like <code>const { getOctokit }
= require('@actions/github')</code> to create secondary clients, use the
new injected <code>getOctokit</code> function instead — it's available
directly in the script context with no imports needed.</li>
<li><code>getOctokit</code> is now an injected function parameter.
Scripts that declare <code>const getOctokit = ...</code> or <code>let
getOctokit = ...</code> will get a <code>SyntaxError</code> because
JavaScript does not allow <code>const</code>/<code>let</code>
redeclaration of function parameters. Use the injected
<code>getOctokit</code> directly, or use <code>var getOctokit =
...</code> if you need to redeclare it.</li>
<li>If your script accesses other <code>@actions/github</code> internals
beyond the standard <code>github</code>/<code>octokit</code> client, you
may need to update those references for v9 compatibility.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Add ACTIONS_ORCHESTRATION_ID to user-agent string by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/695">actions/github-script#695</a></li>
<li>ci: use deployment: false for integration test environments by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/712">actions/github-script#712</a></li>
<li>feat!: add getOctokit to script context, upgrade
<code>@​actions/github</code> v9, <code>@​octokit/core</code> v7, and
related packages by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/700">actions/github-script#700</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Copilot"><code>@​Copilot</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/github-script/pull/695">actions/github-script#695</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/github-script/compare/v8.0.0...v9.0.0">https://github.com/actions/github-script/compare/v8.0.0...v9.0.0</a></p>
<h2>v8.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update Node.js version support to 24.x by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/637">actions/github-script#637</a></li>
<li>README for updating actions/github-script from v7 to v8 by <a
href="https://github.com/sneha-krip"><code>@​sneha-krip</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/653">actions/github-script#653</a></li>
</ul>
<h2>⚠️ Minimum Compatible Runner Version</h2>
<p><strong>v2.327.1</strong><br />
<a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Release
Notes</a></p>
<p>Make sure your runner is updated to this version or newer to use this
release.</p>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/github-script/pull/637">actions/github-script#637</a></li>
<li><a
href="https://github.com/sneha-krip"><code>@​sneha-krip</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/github-script/pull/653">actions/github-script#653</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/github-script/compare/v7.1.0...v8.0.0">https://github.com/actions/github-script/compare/v7.1.0...v8.0.0</a></p>
<h2>v7.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Upgrade husky to v9 by <a
href="https://github.com/benelan"><code>@​benelan</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/482">actions/github-script#482</a></li>
<li>Add workflow file for publishing releases to immutable action
package by <a
href="https://github.com/Jcambass"><code>@​Jcambass</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/485">actions/github-script#485</a></li>
<li>Upgrade IA Publish by <a
href="https://github.com/Jcambass"><code>@​Jcambass</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/486">actions/github-script#486</a></li>
<li>Fix workflow status badges by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/497">actions/github-script#497</a></li>
<li>Update usage of <code>actions/upload-artifact</code> by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/512">actions/github-script#512</a></li>
<li>Clear up package name confusion by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/514">actions/github-script#514</a></li>
<li>Update dependencies with <code>npm audit fix</code> by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/515">actions/github-script#515</a></li>
<li>Specify that the used script is JavaScript by <a
href="https://github.com/timotk"><code>@​timotk</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/478">actions/github-script#478</a></li>
<li>chore: Add Dependabot for NPM and Actions by <a
href="https://github.com/nschonni"><code>@​nschonni</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/472">actions/github-script#472</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/github-script/commit/3a2844b7e9c422d3c10d287c895573f7108da1b3"><code>3a2844b</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/github-script/issues/700">#700</a>
from actions/salmanmkc/expose-getoctokit + prepare re...</li>
<li><a
href="https://github.com/actions/github-script/commit/ca10bbdd1a7739de09e99a200c7a59f5d73a4079"><code>ca10bbd</code></a>
fix: use <code>@​octokit/core/</code>types import for v7
compatibility</li>
<li><a
href="https://github.com/actions/github-script/commit/86e48e20ac85c970ed1f96e718fd068173948b7b"><code>86e48e2</code></a>
merge: incorporate main branch changes</li>
<li><a
href="https://github.com/actions/github-script/commit/c1084728b5b935ec4ddc1e4cee877b01797b3ff9"><code>c108472</code></a>
chore: rebuild dist for v9 upgrade and getOctokit factory</li>
<li><a
href="https://github.com/actions/github-script/commit/afff112e4f8b57c718168af75b89ce00bc8d091d"><code>afff112</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/github-script/issues/712">#712</a>
from actions/salmanmkc/deployment-false + fix user-ag...</li>
<li><a
href="https://github.com/actions/github-script/commit/ff8117e5b78c415f814f39ad6998f424fee7b817"><code>ff8117e</code></a>
ci: fix user-agent test to handle orchestration ID</li>
<li><a
href="https://github.com/actions/github-script/commit/81c6b7876079abe10ff715951c9fc7b3e1ab389d"><code>81c6b78</code></a>
ci: use deployment: false to suppress deployment noise from integration
tests</li>
<li><a
href="https://github.com/actions/github-script/commit/3953caf8858d318f37b6cc53a9f5708859b5a7b7"><code>3953caf</code></a>
docs: update README examples from <a
href="https://github.com/v8"><code>@​v8</code></a> to <a
href="https://github.com/v9"><code>@​v9</code></a>, add getOctokit docs
and v9 brea...</li>
<li><a
href="https://github.com/actions/github-script/commit/c17d55b90dcdb3d554d0027a6c180a7adc2daf78"><code>c17d55b</code></a>
ci: add getOctokit integration test job</li>
<li><a
href="https://github.com/actions/github-script/commit/a047196d9a02fe92098771cafbb98c2f1814e408"><code>a047196</code></a>
test: add getOctokit integration tests via callAsyncFunction</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/github-script/compare/v7...v9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/github-script&package-manager=github_actions&previous-version=7&new-version=9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Pinned [MongoDB.Driver](https://github.com/mongodb/mongo-csharp-driver)
at 3.8.0.

<details>
<summary>Release notes</summary>

_Sourced from [MongoDB.Driver's
releases](https://github.com/mongodb/mongo-csharp-driver/releases)._

## 3.8.0

This is the general availability release for the 3.8.0 version of the
driver.

### The main new features in 3.8.0 include:

> [!IMPORTANT]
> Added support for MongoDB ’s [Intelligent Workload Management
(IWM)](https://www.mongodb.com/docs/atlas/intelligent-workload-management/)
and ingress connection rate limiting features. The driver now gracefully
handles write-blocking scenarios and optimizes connection establishment
during high-load conditions to maintain application availability. More
details in [CSHARP-5802](https://jira.mongodb.org/browse/CSHARP-5802):
Client Backpressure Support

- [CSHARP-5882](https://jira.mongodb.org/browse/CSHARP-5882): Support
storedSource in vector search indexes and returnStoredSource in
$vectorSearch queries
- [CSHARP-5769](https://jira.mongodb.org/browse/CSHARP-5769): Implement
hasAncestor, hasRoot, and returnScope for Atlas Search
- [CSHARP-5646](https://jira.mongodb.org/browse/CSHARP-5646): Implement
vector similarity match expressions
- [CSHARP-5762](https://jira.mongodb.org/browse/CSHARP-5762): MongoDB
Vector Search now supports vector search against nested embeddings and
arrays of embeddings.
- [CSHARP-5884](https://jira.mongodb.org/browse/CSHARP-5884): Add new
fields for Auto embedding in Atlas Vector search indexes
 
  
MongoDB v8.3 Compatible Features:
- [CSHARP-5852](https://jira.mongodb.org/browse/CSHARP-5852): Expression
to determine the subtype of BinData field
- [CSHARP-5713](https://jira.mongodb.org/browse/CSHARP-5713): Allow
native conversion from string to BSON object
- [CSHARP-5949](https://jira.mongodb.org/browse/CSHARP-5949): $convert
should allow any type to be converted to string
- [CSHARP-5818](https://jira.mongodb.org/browse/CSHARP-5818): Allow
users to generate a hash from a UTF-8 string or binary data
- [CSHARP-5950](https://jira.mongodb.org/browse/CSHARP-5950): Support
base conversion in $convert
- [CSHARP-5847](https://jira.mongodb.org/browse/CSHARP-5847): Support
Select/SelectMany/Where index overloads in LINQ provider
- [CSHARP-5828](https://jira.mongodb.org/browse/CSHARP-5828): Add Rerank
stage builder
- [CSHARP-5656](https://jira.mongodb.org/browse/CSHARP-5656): Support
Aggregation Operator to generate random object ids
- [CSHARP-5973](https://jira.mongodb.org/browse/CSHARP-5973): Support
SkipWhile/TakeWhile index overloads in LINQ provider
- [CSHARP-5825](https://jira.mongodb.org/browse/CSHARP-5825): Support
(de)serialization between BSON and EJSON
- [CSHARP-5655](https://jira.mongodb.org/browse/CSHARP-5655): Support
regular expressions in $replaceAll search string and $split delimiter

### Improvements:

- [CSHARP-5887](https://jira.mongodb.org/browse/CSHARP-5887): Simplify
retryable read and writes
- [CSHARP-2593](https://jira.mongodb.org/browse/CSHARP-2593): Add
numeric error code to default error message in
NativeMethods.CreateException
- [CSHARP-2150](https://jira.mongodb.org/browse/CSHARP-2150): Add check
that the serializer's ValueType matches the type when registering the
serializer

### Fixes:

- [CSHARP-5947](https://jira.mongodb.org/browse/CSHARP-5947): Increase
SingleServerReadBinding timeout
- [CSHARP-2862](https://jira.mongodb.org/browse/CSHARP-2862): Check that
max pool size is never less than min pool size in connection string
- [CSHARP-5935](https://jira.mongodb.org/browse/CSHARP-5935): Command
activities may be skipped when using pooled connection
- [CSHARP-5952](https://jira.mongodb.org/browse/CSHARP-5952):
SerializerFinder resolve wrong serializer for BsonDocument members

### Maintenance:

- [CSHARP-5957](https://jira.mongodb.org/browse/CSHARP-5957): Bump
maxWireVersion to 9.0

The full list of issues resolved in this release is available at [CSHARP
JIRA
project](https://jira.mongodb.org/issues/?jql=project%20%3D%20CSHARP%20AND%20fixVersion%20%3D%203.8.0%20ORDER%20BY%20key%20ASC).

Documentation on the .NET driver can be found
[here](https://www.mongodb.com/docs/drivers/csharp/v3.8/).

## 3.7.1


This is a patch release that contains fixes and stability improvements:

- [CSHARP-5916](https://jira.mongodb.org/browse/CSHARP-5916):
ExpressionNotSupportedException when a $set stage expression references
a member of a captured constant
- [CSHARP-5918](https://jira.mongodb.org/browse/CSHARP-5918):
ExpressionNotSupportedException when a $set stage expression uses ToList
method
- [CSHARP-5917](https://jira.mongodb.org/browse/CSHARP-5917): Mql.Field
should lookup for default serializer if null is provided as a
bsonSerializer parameter
- [CSHARP-5920](https://jira.mongodb.org/browse/CSHARP-5920):
SerializerFinder wrapping serializer into Upcast/Downcast serializer
breaks some expressions translation
- [CSHARP-5905](https://jira.mongodb.org/browse/CSHARP-5905): Fix bug
when using EnumRepresentationConvention or
ObjectSerializerAllowedTypesConvention
- [CSHARP-5928](https://jira.mongodb.org/browse/CSHARP-5928): LINQ
Provider throws misleading exception if expression translation is not
supported
- [CSHARP-5929](https://jira.mongodb.org/browse/CSHARP-5929): Improve
SerializerFinder to proper handling of IUnknowableSerializer

The full list of issues resolved in this release is available at [CSHARP
JIRA
project](https://jira.mongodb.org/issues/?jql=project%20%3D%20CSHARP%20AND%20fixVersion%20%3D%203.7.1%20ORDER%20BY%20key%20ASC).

Documentation on the .NET driver can be found
[here](https://www.mongodb.com/docs/drivers/csharp/v3.7/).

## 3.7.0

This is the general availability release for the 3.7.0 version of the
driver.

### The main new features in 3.7.0 include:

- [CSHARP-3124](https://jira.mongodb.org/browse/CSHARP-3124):
OpenTelemetry implementation
- [CSHARP-5736](https://jira.mongodb.org/browse/CSHARP-5736): Expose
atClusterTime parameter in snapshot sessions
- [CSHARP-5805](https://jira.mongodb.org/browse/CSHARP-5805): Add
support for server selection's deprioritized servers to all topologies
- [CSHARP-5712](https://jira.mongodb.org/browse/CSHARP-5712):
WithTransaction API retries too frequently
- [CSHARP-5836](https://jira.mongodb.org/browse/CSHARP-5836): Support
new Reverse with array overload introduced by .NET 10
- [CSHARP-4566](https://jira.mongodb.org/browse/CSHARP-4566): Support
filters comparing nullable numeric or char field to constant
- [CSHARP-5606](https://jira.mongodb.org/browse/CSHARP-5606): Support
ConvertChecked as well as Convert

### Improvements:

- [CSHARP-5841](https://jira.mongodb.org/browse/CSHARP-5841): Rewrite
$elemMatch with $or referencing implied element due to server
limitations
- [CSHARP-5572](https://jira.mongodb.org/browse/CSHARP-5572): Implement
new SerializerFinder
- [CSHARP-5861](https://jira.mongodb.org/browse/CSHARP-5861): Use
ConnectAsync in synchronous code-path to avoid dead-locks
- [CSHARP-5876](https://jira.mongodb.org/browse/CSHARP-5876): Convert
some disposer classes to structs
- [CSHARP-5889](https://jira.mongodb.org/browse/CSHARP-5889): Optimize
comparison with nullable constant translation
- [CSHARP-5890](https://jira.mongodb.org/browse/CSHARP-5890): Avoid byte
array allocations writing Int64, Double, Decimal128 in ByteBufferStream
- [CSHARP-5888](https://jira.mongodb.org/browse/CSHARP-5888): Optimize
CommandEventHelper to avoid redundant message decoding

### Fixes:

- [CSHARP-5564](https://jira.mongodb.org/browse/CSHARP-5564): Enum with
ushort underlying type is not serialized correctly
- [CSHARP-5654](https://jira.mongodb.org/browse/CSHARP-5654):
String.IndexOf comparisons to -1 return incorrect results
- [CSHARP-5866](https://jira.mongodb.org/browse/CSHARP-5866): Avoid
raising ClusterDescriptionChangedEvent on unchanged DNS records update
- [CSHARP-5850](https://jira.mongodb.org/browse/CSHARP-5850): Use of an
untranslatable property reference in a LINQ expression should be
executed client-side
- [CSHARP-5863](https://jira.mongodb.org/browse/CSHARP-5863): The
built-in `IPAddressSerializer` throws when using `IPAddress.Any`, etc
- [CSHARP-5877](https://jira.mongodb.org/browse/CSHARP-5877): Fix
First/Last field path in GroupBy optimizer when source is wrapped
- [CSHARP-5894](https://jira.mongodb.org/browse/CSHARP-5894): Deadlock
during concurrent BsonClassMap initialization

The full list of issues resolved in this release is available at [CSHARP
JIRA
project](https://jira.mongodb.org/issues/?jql=project%20%3D%20CSHARP%20AND%20fixVersion%20%3D%203.7.0%20ORDER%20BY%20key%20ASC).

Documentation on the .NET driver can be found
[here](https://www.mongodb.com/docs/drivers/csharp/v3.7/).

Commits viewable in [compare
view](mongodb/mongo-csharp-driver@v3.6.0...v3.8.0).
</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- add markdownlint and yamllint workflows for docs and YAML changes
- exclude squad/agent tooling content from lint scope where appropriate
- clean existing workflow YAML spacing so the new lint gate passes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tn variants (#295)

Closes #291
Closes #292

Squash merge by Aragorn after CI green + Copilot review resolved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #293

Squash merge by Aragorn after CI green.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…hip (#296) (#298)

## Summary

Implements [Issue #296](#296)
— auto-fill Author when creating a new blog post.

Closes #296

Working as Sam (Backend Developer)

## Changes

- **New**: `PostAuthor` sealed record in `MyBlog.Domain.ValueObjects`
(Id, Name, Email, Roles + `PostAuthor.Empty` helper)
- **Domain**: `BlogPost.Author` changed from `string` to `PostAuthor`;
`Create()` guards null author and empty Name
- **Infrastructure**: `BlogDbContext` uses `OwnsOne` to map PostAuthor
as a MongoDB sub-document
- **DTO**: `BlogPostDto` flattens PostAuthor to `AuthorId`,
`AuthorName`, `AuthorEmail`, `AuthorRoles`
- **Command/Validation**: `CreateBlogPostCommand.Author` is now
`PostAuthor`; validator checks NotNull + Name.NotEmpty
- **UI stub**: `Create.razor` has a temporary placeholder constructing
`PostAuthor` from a form field — Legolas needs to replace this with
`AuthenticationStateProvider` injection
- **Tests**: All test projects updated for new types and constructor
signatures

## Breaking Change

Existing MongoDB documents with `"Author": "string"` will fail to
deserialize. Dev: drop/recreate collection. Prod: migration script
needed (out of scope Sprint 19).

## Notes for Legolas

`Create.razor` still has an `Author` text input as a placeholder. The
next step is to inject `AuthenticationStateProvider`, read claims
(NameIdentifier, Name, Email, roles), and build `PostAuthor`
automatically — removing the manual input field.

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #299

Aligns source pre-push hook, CONTRIBUTING.md, and playbook docs so the
Gate 5 description consistently shows both Web.Tests.Integration and
AppHost.Tests (Aspire + Playwright) as required integration test suites.

Squash merge by Aragorn after CI green.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #300

UI-level ownership check in Edit.razor: Authors can only edit their own posts;
Admins retain unrestricted edit access. Non-owners redirected to /blog.

Squash merge by Aragorn after CI green.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…304)

## Summary

Closes #300

Full-stack implementation restricting blog post editing to the post's
original author or an Admin. This is the complete solution combining
Aragorn's backend enforcement with Legolas's frontend UX.

Working as **Legolas** (Frontend Developer) + incorporating **Aragorn**
(Backend Developer) changes.

---

## Changes

### Backend (Aragorn)
- **`ResultErrorCode.Unauthorized = 5`** — new enum value in
`src/Domain/Abstractions/Result.cs`
- **`EditBlogPostCommand`** — extended with `CallerUserId` and
`CallerIsAdmin` parameters
- **`EditBlogPostHandler`** — authorization check: returns
`Unauthorized` if `CallerUserId != post.Author.Id` and not Admin
- **Handler tests** — new tests: author allowed, Admin allowed,
different user → Unauthorized

### Frontend (Legolas)
- **`Edit.razor` load-time check** — after post loads, compares Auth0
`sub` claim with `post.AuthorId`; redirects non-owners to `/blog`
(unless Admin)
- **`Edit.razor` submit-time** — `HandleSubmit` passes `_callerUserId`
and `_callerIsAdmin` in the command; on `Unauthorized` response shows
inline user-friendly error instead of silent navigation
- **bUnit tests** (`EditAclTests.cs`) — 4 tests: redirect non-owner,
allow owner, allow Admin, server-side Unauthorized shows error message

---

## Test Results
- bUnit: 88 tests pass (4 new for this issue)
- Web.Tests: 154 tests pass

⚠️ This task was flagged as "needs review" — please have a squad member
review before merging.

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…) (#309)

## Summary

Closes #307

Working as Legolas (Frontend / UI / Blazor Specialist)

## Problem

The Edit page used `_model is null && _error is null` as the
"Loading..." condition. When a post is not found, `OnParametersSetAsync`
calls `NavigateTo("/blog")` and returns early — never setting `_model`
or `_error`. The component stays on "Loading..." indefinitely
(especially visible in bUnit where navigation doesn't unmount the
component).

## Changes

### `src/Web/Features/BlogPosts/Edit/Edit.razor`
- Add `private bool _isLoading = true;` field
- Replace derived condition `_model is null && _error is null` with
`_isLoading`
- Add `role="status"` ARIA attribute to the loading paragraph
- Wrap `OnParametersSetAsync` body in `try/finally { _isLoading = false;
}` — guarantees the spinner clears on every exit path including early
`return` via `NavigateTo`

### `tests/Web.Tests.Bunit/Features/EditAclTests.cs`
- Update `EditRedirectsToBlogWhenPostNotFound` to capture `cut` and
assert `Loading...` is not shown after null-post result

## Validation

- 89/89 bUnit tests pass (no regressions)
- Pre-push gate passed (format check + release build)

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #307\n\nWorking as ralph (Meta).\n\n## Summary\n- reset the Edit
page loading flag whenever route parameters change\n- prevent stale
previous-post content from persisting across post-ID navigation\n- add
bUnit regression coverage for switching IDs in the same component
instance

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- reset loading state at parameter changes so route updates fetch and
render correctly
- add bUnit coverage for post ID parameter switch regression

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>##
Summary

<!-- Describe what this PR does and why. Link the issue it closes. -->

Closes #<!-- issue number -->

## Type of Change

<!-- Check all that apply -->

- [ ] 🐛 Bug fix (non-breaking change that fixes an issue)
- [ ] ✨ Feature (non-breaking change that adds functionality)
- [ ] ♻️ Refactor (no behavior change, code cleanup/restructure)
- [ ] 🧪 Tests (new or updated tests only)
- [ ] 📝 Docs (README, XML docs, comments)
- [ ] ⚙️ Infra/CI (GitHub Actions, Aspire, NuGet, deployment)
- [ ] 🔒 Security (auth, permissions, secrets, headers)
- [ ] 💥 Breaking change (existing behavior changes)

## Domain Affected

<!-- Check all that apply — this determines which reviewers are required
-->

- [ ] 🏗️ Architecture / domain logic / CQRS → **Aragorn required**
- [ ] 🔧 Backend (handlers, repositories, API endpoints, MediatR) → **Sam
required**
- [ ] ⚛️ Frontend (Blazor components, Razor pages, CSS, JS) → **Legolas
required**
- [ ] 🧪 Unit / bUnit / integration tests → **Gimli required**
- [ ] 🧪 E2E / Playwright / Aspire integration tests → **Pippin
required**
- [ ] ⚙️ CI/CD / GitHub Actions / NuGet / Aspire AppHost → **Boromir
required**
- [ ] 🔒 Auth0 / authorization / security-relevant changes → **Gandalf
required**
- [ ] 📝 Docs / README / XML docs → **Frodo required**

## Self-Review Checklist

<!-- Complete before requesting review — incomplete PRs will be returned
-->

### Code Quality

- [ ] I ran `dotnet build MyBlog.slnx --configuration Release` — 0
errors, 0 warnings
- [ ] I ran `dotnet test MyBlog.slnx --configuration Release --no-build`
— all pass
- [ ] No TODO/FIXME left unless tracked in a follow-up issue (link it)
- [ ] No secrets, API keys, or credentials committed

### Architecture

- [ ] New handlers follow the `Command`/`Query`/`Handler`/`Validator`
naming conventions
- [ ] New handlers are `sealed`
- [ ] Domain layer has no references to `Web` or `Persistence.*`
projects
- [ ] `Result<T>` / `ResultErrorCode` used for expected failures (no
exception-driven control flow)
- [ ] DTOs are records in `Domain.DTOs`; Models are in `Domain.Models`
- [ ] No DTO types embedded in Model classes

### Tests

- [ ] New code has corresponding unit tests
- [ ] Integration tests use domain-specific collections
(`[Collection("XxxIntegration")]`)
- [ ] No test compares two `IssueDto.Empty` / `CommentDto.Empty`
instances directly

### Security (check if security-relevant)

- [ ] New endpoints have appropriate `RequireAuthorization` / policy
applied
- [ ] No `MarkupString` used with user-supplied content
- [ ] No user input reflected in MongoDB queries without sanitization

### Merge Readiness

- [ ] Branch is up to date with `main` (no merge conflicts)
- [ ] CI checks are green (do not request review while checks are
pending/failing)
- [ ] PR description is complete — reviewers should not have to ask what
this does

## Screenshots / Evidence

<!-- For UI changes: before/after screenshots. For fixes: evidence the
bug is resolved. -->

## Notes for Reviewers

<!-- Anything you want reviewers to pay special attention to, or context
they need. -->

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#313)

## Summary\n- align Blog Post author claim extraction to
nameidentifier/emailaddress claims with safe fallbacks\n- add
IsPublished checkbox behavior (default false) through Create/Edit forms,
commands, and handlers\n- fix AppHost seed author field names to match
Mongo EF mapping and prevent missing Id document errors\n- add handler
tests for publish/unpublish paths\n\nCloses #311

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Boromir <lead-organizer@squad.local>
…315)

Closes #314

Working as **Legolas** (Frontend Developer) + **Sam** (Backend
Developer)

## Summary

This PR completes Issue #314 end-to-end:
1. **Frontend (Legolas)**: Replaces `<InputTextArea>` with
[RTBlazorfied](https://github.com/vaytaliy/RTBlazorfied) v2.0.20 rich
text editor on Create and Edit blog post pages
2. **Backend (Sam)**: Adds server-side HTML sanitization via
`IHtmlSanitizer` in the Create and Edit handlers

> **Note:** `Blazored.TextEditor` referenced in the original plan does
not exist on NuGet. `RTBlazorfied` was chosen instead: 52K+ downloads,
supports `@bind-Value`, actively maintained (last update May 2026),
shadow DOM isolated.

## Changes

### Frontend — RTBlazorfied Rich Text Editor (Legolas)
- `Directory.Packages.props`: Added `RTBlazorfied` v2.0.20
- `src/Web/Web.csproj`: Added `<PackageReference Include="RTBlazorfied"
/>`
- `src/Web/Components/App.razor`: Added RTBlazorfied JS script tag
- `src/Web/Features/_Imports.razor` + `Components/_Imports.razor`: Added
`@using RichTextBlazorfied`
- `src/Web/Features/BlogPosts/Create/Create.razor`: Replaced
`<InputTextArea>` → `<RTBlazorfied @bind-Value="_model.Content"
Height="400px" />`
- `src/Web/Features/BlogPosts/Edit/Edit.razor`: Same replacement
- `tests/Web.Tests.Bunit/Features/RichTextEditorTests.cs`: **New** — 2
smoke tests
- `tests/Web.Tests.Bunit/Components/RazorSmokeTests.cs`: Updated for
shadow DOM + `ValueChanged` + `JSRuntimeMode.Loose`
- `tests/Web.Tests.Bunit/Features/EditAclTests.cs`: Added
`JSRuntimeMode.Loose`

### Backend — HtmlSanitizer (Sam)
- `CreateBlogPostHandler` and `EditBlogPostHandler`: sanitize `Content`
with `IHtmlSanitizer`
- `HtmlSanitizer` 9.1.923-beta + pinned AngleSharp 1.4.0
- `IHtmlSanitizer` registered as singleton in `Program.cs`
- Updated handler tests + new `HtmlSanitizerBehaviorTests` (7 tests)

## Test results

All tests pass ✅: 94 bUnit + 165 Web.Tests + 42 Domain.Tests

## Technical notes (RTBlazorfied)
- In C# files always use fully-qualified
`RichTextBlazorfied.RTBlazorfied` (namespace ambiguity with assembly
root namespace)
- Shadow DOM: bound content does not appear in `cut.Markup`
- bUnit: `JSRuntimeMode.Loose` required in any test class rendering
Create/Edit pages

⚠️ This task was flagged as "needs review" — please have a squad member
review before merging.

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Boromir <lead-organizer@squad.local>
mpaulosky and others added 11 commits May 13, 2026 19:37
Closes #318

## Summary

Adds Gate 2 (markdownlint) to the pre-push hook so Markdown violations
are caught locally before reaching CI. Updates all supporting tooling
files to match.

## Changes

- \.github/hooks/pre-push\ — New Gate 2: markdownlint-cli2; renumber
gates (2→3, 3→4, 4→5, 5→6); exclude \**/bin/**\ and \**/obj/**\ build
artifacts
- \.github/workflows/lint-markdown.yml\ — Add \!**/bin/**\ and
\!**/obj/**\ exclusions to match hook
- \.gitattributes\ — Add \* text=auto eol=lf\ and \*.cs text eol=lf\ to
normalise line endings repo-wide (fixes Windows CRLF/dotnet-format
cycle)
- \.squad/playbooks/pre-push-process.md\ — Updated for 6-gate process
- \docs/CONTRIBUTING.md\ — Aligned with new gate structure
- \scripts/install-hooks.sh\ — Improved hook installation
- \.github/upgrades/scenarios/dotnet-version-upgrade/**\ — Auto-fixed
markdown lint violations (MD012/MD022/MD032/MD031) in archived upgrade
docs

## Gate 6 bypass

Docker Desktop is unavailable on the local dev machine. Gates 1–5 all
passed locally. See [bypass approval
comment](#318 (comment)).
CI will validate Gate 6 (integration tests) on the Linux runner.

⚠️ This task was flagged as tooling — please have a squad member review
before merging.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Upgrade Aspire hosting/testing/driver/cache packages to 13.3.2
- Upgrade Aspire AppHost SDK to 13.3.2
- Bump markdown stack package versions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add self-authored PR gate workflow skill for lead finalization when GitHub blocks self-approval
- Archive PR #336 gate outcome in Aragorn/Sam history logs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…340)

Closes #339

- Domain: Category entity, BlogPost.AssignCategory/RemoveCategory with version increments
- Persistence: MongoDbCategoryRepository, BlogPost ExistsByCategoryAsync, unique-name index
- CQRS: Create/Edit/Delete commands + validators, GetCategories / GetCategoryById queries
- Web: Admin-only /admin/categories CRUD page, NavMenu link, category dropdown on blog post Create/Edit
- AppHost seed: idempotent upsert of "General" category
- Test infra: TestContextFactory caches DbContextOptions; suppresses ManyServiceProvidersCreatedWarning
- Tests: 472 total green (Domain, Web, Web.Bunit, Web.Integration, Architecture, AppHost E2E)
- Follow-up polish tracked in #341

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #341

## Changes

**Completed slices:**
- Legolas: UI category publish semantics/load failure/stale state
- Gimli: Update* test rename to Edit*
- Sam: AppHost seed log wording
- Frodo: .squad grammar/date polish

## Tests
- Architecture tests: 16 passed
- Domain tests: 67 passed
- Web tests: 210 passed
- Web.Tests.Bunit: 101 passed
- Integration tests: 29 passed
- AppHost.Tests (E2E): 48 passed, 1 skipped

All pre-push gates passed ✅

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ions group (#343)

Bumps the all-actions group with 1 update:
[dotnet-sdk](https://github.com/dotnet/sdk).

Updates `dotnet-sdk` from 10.0.203 to 10.0.300
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dotnet/sdk/releases">dotnet-sdk's
releases</a>.</em></p>
<blockquote>
<h2>.NET 10.0.8</h2>
<p><a
href="https://github.com/dotnet/core/releases/tag/v10.0.8">Release</a></p>
<h2>What's Changed</h2>
<ul>
<li>[release/8.0.1xx] Update dependencies from dotnet/razor by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52454">dotnet/sdk#52454</a></li>
<li>Merging internal commits for release/8.0.4xx by <a
href="https://github.com/vseanreesermsft"><code>@​vseanreesermsft</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52433">dotnet/sdk#52433</a></li>
<li>Merging internal commits for release/8.0.1xx by <a
href="https://github.com/vseanreesermsft"><code>@​vseanreesermsft</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52432">dotnet/sdk#52432</a></li>
<li>[release/9.0.1xx] Update dependencies from dotnet/msbuild by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52561">dotnet/sdk#52561</a></li>
<li>[automated] Merge branch 'release/10.0.2xx' =&gt; 'release/10.0.3xx'
by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52539">dotnet/sdk#52539</a></li>
<li>[dotnet watch] Unify code paths processing static asset and scoped
css updates by <a href="https://github.com/tmat"><code>@​tmat</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52225">dotnet/sdk#52225</a></li>
<li>Separate command definitions to a new project by <a
href="https://github.com/tmat"><code>@​tmat</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52382">dotnet/sdk#52382</a></li>
<li>[HotReloadAgent] Handle unsupported platform for
<code>PosixSignalRegistration</code> by <a
href="https://github.com/jonathanpeppers"><code>@​jonathanpeppers</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52466">dotnet/sdk#52466</a></li>
<li>Move New command definitions to CommandDefinitions project by <a
href="https://github.com/tmat"><code>@​tmat</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52526">dotnet/sdk#52526</a></li>
<li>Include more DLLs in redist fast path target by <a
href="https://github.com/jjonescz"><code>@​jjonescz</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52551">dotnet/sdk#52551</a></li>
<li>Revert &quot;Include more DLLs in redist fast path target&quot; by
<a href="https://github.com/jjonescz"><code>@​jjonescz</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52637">dotnet/sdk#52637</a></li>
<li>[release/10.0.3xx] backport mobile changes for <code>dotnet
run</code> by <a
href="https://github.com/jonathanpeppers"><code>@​jonathanpeppers</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52608">dotnet/sdk#52608</a></li>
<li>Add csc.rsp test by <a
href="https://github.com/jjonescz"><code>@​jjonescz</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52510">dotnet/sdk#52510</a></li>
<li>Fix duplicate solution folder creation when adding multiple projects
from same directory by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52092">dotnet/sdk#52092</a></li>
<li>Fix: Allow --version option with workload restore by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52048">dotnet/sdk#52048</a></li>
<li>dotnet root command and dotnet watch by <a
href="https://github.com/tmat"><code>@​tmat</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52583">dotnet/sdk#52583</a></li>
<li>[dotnet watch] Make application of changes always async by <a
href="https://github.com/tmat"><code>@​tmat</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52469">dotnet/sdk#52469</a></li>
<li>[release/10.0.3xx] Source code updates from dotnet/dotnet by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52585">dotnet/sdk#52585</a></li>
<li>Port sdk-diff-tests and license-scan pipelines to 1ES pipeline
templates by <a
href="https://github.com/mthalman"><code>@​mthalman</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52735">dotnet/sdk#52735</a></li>
<li>[automated] Merge branch 'release/10.0.2xx' =&gt; 'release/10.0.3xx'
by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52588">dotnet/sdk#52588</a></li>
<li>[automated] Merge branch 'release/10.0.2xx' =&gt; 'release/10.0.3xx'
by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52746">dotnet/sdk#52746</a></li>
<li>[release/10.0.1xx] Source code updates from dotnet/dotnet by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52748">dotnet/sdk#52748</a></li>
<li>Add support for creating and editing solution filter (.slnf) files
from the CLI by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/51156">dotnet/sdk#51156</a></li>
<li>[release/10.0.1xx] Source code updates from dotnet/dotnet by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52760">dotnet/sdk#52760</a></li>
<li>[automated] Merge branch 'release/10.0.2xx' =&gt; 'release/10.0.3xx'
by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52754">dotnet/sdk#52754</a></li>
<li>Style cleanup by <a
href="https://github.com/tmat"><code>@​tmat</code></a> in <a
href="https://redirect.github.com/dotnet/sdk/pull/52751">dotnet/sdk#52751</a></li>
<li>Update branding to 9.0.115 by <a
href="https://github.com/vseanreesermsft"><code>@​vseanreesermsft</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52781">dotnet/sdk#52781</a></li>
<li>Update branding to 9.0.312 by <a
href="https://github.com/vseanreesermsft"><code>@​vseanreesermsft</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52782">dotnet/sdk#52782</a></li>
<li>[release/10.0.1xx] Source code updates from dotnet/dotnet by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52776">dotnet/sdk#52776</a></li>
<li>[release/9.0.1xx] Update dependencies from dotnet/arcade by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52590">dotnet/sdk#52590</a></li>
<li>[release/10.0.1xx] Update dependencies from microsoft/testfx by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52797">dotnet/sdk#52797</a></li>
<li>[release/9.0.3xx] Update dependencies from dotnet/scenario-tests by
<a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52624">dotnet/sdk#52624</a></li>
<li>Update branding to 8.0.125 by <a
href="https://github.com/vseanreesermsft"><code>@​vseanreesermsft</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52778">dotnet/sdk#52778</a></li>
<li>Update branding to 8.0.419 by <a
href="https://github.com/vseanreesermsft"><code>@​vseanreesermsft</code></a>
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52780">dotnet/sdk#52780</a></li>
<li>[automated] Merge branch 'release/10.0.2xx' =&gt; 'release/10.0.3xx'
by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52767">dotnet/sdk#52767</a></li>
<li>[release/9.0.1xx] Update dependencies from dotnet/scenario-tests by
<a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52606">dotnet/sdk#52606</a></li>
<li>[release/9.0.3xx] Update dependencies from dotnet/arcade by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52592">dotnet/sdk#52592</a></li>
<li>[release/9.0.3xx] Update dependencies from dotnet/msbuild by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52594">dotnet/sdk#52594</a></li>
<li>[release/9.0.1xx] Update dependencies from dotnet/roslyn-analyzers
by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52667">dotnet/sdk#52667</a></li>
<li>[automated] Merge branch 'release/8.0.1xx' =&gt; 'release/8.0.4xx'
by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52530">dotnet/sdk#52530</a></li>
<li>[release/10.0.1xx] Source code updates from dotnet/dotnet by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52801">dotnet/sdk#52801</a></li>
<li>[release/9.0.1xx] Update dependencies from
dotnet/source-build-reference-packages by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52591">dotnet/sdk#52591</a></li>
<li>[release/9.0.1xx] Update dependencies from dotnet/templating by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52799">dotnet/sdk#52799</a></li>
<li>[release/9.0.3xx] Update dependencies from dotnet/templating by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52786">dotnet/sdk#52786</a></li>
<li>[automated] Merge branch 'release/9.0.1xx' =&gt; 'release/9.0.3xx'
by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52739">dotnet/sdk#52739</a></li>
<li>[release/10.0.1xx] Source code updates from dotnet/dotnet by <a
href="https://github.com/dotnet-maestro"><code>@​dotnet-maestro</code></a>[bot]
in <a
href="https://redirect.github.com/dotnet/sdk/pull/52823">dotnet/sdk#52823</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/dotnet/sdk/commit/8ece2d6b49edf91f2eed52867ab8a8f48ac8a2e5"><code>8ece2d6</code></a>
[automated] Merge branch 'release/10.0.1xx' =&gt; 'release/10.0.3xx' (<a
href="https://redirect.github.com/dotnet/sdk/issues/54011">#54011</a>)</li>
<li><a
href="https://github.com/dotnet/sdk/commit/fedca9a54b13829e542168166a981a136ad2aca7"><code>fedca9a</code></a>
Merge branch 'release/10.0.3xx' into
merge/release/10.0.1xx-to-release/10.0.3xx</li>
<li><a
href="https://github.com/dotnet/sdk/commit/691c4649e385201aa9585e26dd1a76a19a88aae8"><code>691c464</code></a>
[release/10.0.3xx] Fix dotnet tool runner stripping duplicate flags when
roll...</li>
<li><a
href="https://github.com/dotnet/sdk/commit/7e275509306fe9b19695aae04a44f1bc564d379f"><code>7e27550</code></a>
Reset files to release/10.0.3xx</li>
<li><a
href="https://github.com/dotnet/sdk/commit/29a838d66075f69d3cb93ebd65a48d6783abae76"><code>29a838d</code></a>
[automated] Merge branch 'release/9.0.3xx' =&gt; 'release/10.0.1xx' (<a
href="https://redirect.github.com/dotnet/sdk/issues/53992">#53992</a>)</li>
<li><a
href="https://github.com/dotnet/sdk/commit/b5d91e7246d95aaf6e93fec88c89bc42c813bc52"><code>b5d91e7</code></a>
Merge branch 'release/10.0.1xx' of <a
href="https://github.com/dotnet/sdk">https://github.com/dotnet/sdk</a>
into merge/r...</li>
<li><a
href="https://github.com/dotnet/sdk/commit/c840dab577f59dee04d22c3f8c1704e1d01b6ee5"><code>c840dab</code></a>
Switch to automatic version calculation for 10.0.3xx (<a
href="https://redirect.github.com/dotnet/sdk/issues/53974">#53974</a>)</li>
<li><a
href="https://github.com/dotnet/sdk/commit/02e38bbc87692d0fa047106dcafd99038232ba1b"><code>02e38bb</code></a>
Enable CI builds and locbranch for 4xx (<a
href="https://redirect.github.com/dotnet/sdk/issues/53968">#53968</a>)</li>
<li><a
href="https://github.com/dotnet/sdk/commit/aa68cb341ed1a0c994b7c8b41fed8b0091c148ca"><code>aa68cb3</code></a>
[automated] Merge branch 'release/10.0.1xx' =&gt; 'release/10.0.3xx' (<a
href="https://redirect.github.com/dotnet/sdk/issues/53980">#53980</a>)</li>
<li><a
href="https://github.com/dotnet/sdk/commit/7e8cbd517ec35fdf20df0c78222da16436700b90"><code>7e8cbd5</code></a>
Reset files to release/10.0.1xx</li>
<li>Additional commits viewable in <a
href="https://github.com/dotnet/sdk/compare/v10.0.203...v10.0.300">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dotnet-sdk&package-manager=dotnet_sdk&previous-version=10.0.203&new-version=10.0.300)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Updated [Aspire.Hosting.MongoDB](https://github.com/microsoft/aspire)
from 13.3.2 to 13.3.3.

<details>
<summary>Release notes</summary>

_Sourced from [Aspire.Hosting.MongoDB's
releases](https://github.com/microsoft/aspire/releases)._

## 13.3.3

## What's New in Aspire 13.3.3

Patch release for Aspire 13.3 with fixes for debug log level leaking
into user resources, Keycloak HTTPS endpoint token invalidation, and
endpoint materialization in `HostResourceWithEndpoints`.

### 🐛 Fixes

- 🔇 **Debug log level leaking into user resources** —
`Logging__LogLevel__Default=Debug` set by the app host was being
inherited by all user resources, silently changing their logging
verbosity. The app host now uses `ASPIRE_APPHOST_LOGLEVEL` instead,
which is scoped to Aspire processes only. (#​17071, backported via
#​17078)
- 🔑 **Keycloak HTTPS primary endpoint** — Fixed a regression where
Keycloak tokens became invalid after an app host restart because the
HTTPS endpoint port was dynamic. When developer certificates are
enabled, Keycloak's primary endpoint is now upgraded to HTTPS directly,
and the endpoint name is set to `http` to enable standard
`http+https://` service discovery URLs. (#​17058, backported via
#​17063)
- 🔌 **Endpoint materialization in `HostResourceWithEndpoints`** —
Endpoints configured via `HostResourceWithEndpoints` are now correctly
materialized, ensuring endpoint resolution and service discovery work as
expected. (#​17091, backported via #​17092)

### 🏷️ Housekeeping

- ⬆️ Bumped DCP (Microsoft.DeveloperControlPlane) from 0.23.5 → 0.23.6 —
includes fixes for Kubernetes OpenAPI generator types that caused
`[SHOULD NOT HAPPEN] failed to update managedFields` errors. (#​17070)
- 🚀 Bumped branding to 13.3.3 (#​17088)

---
*Full commit:
[a4615e7c6def6cba4703cdbd84009cd3da9a261b](microsoft/aspire@a4615e7c6def6cba4703cdbd84009cd3da9a261b)*


Commits viewable in [compare
view](microsoft/aspire@v13.3.2...v13.3.3).
</details>

Updated [Aspire.Hosting.Redis](https://github.com/microsoft/aspire) from
13.3.2 to 13.3.3.

<details>
<summary>Release notes</summary>

_Sourced from [Aspire.Hosting.Redis's
releases](https://github.com/microsoft/aspire/releases)._

## 13.3.3

## What's New in Aspire 13.3.3

Patch release for Aspire 13.3 with fixes for debug log level leaking
into user resources, Keycloak HTTPS endpoint token invalidation, and
endpoint materialization in `HostResourceWithEndpoints`.

### 🐛 Fixes

- 🔇 **Debug log level leaking into user resources** —
`Logging__LogLevel__Default=Debug` set by the app host was being
inherited by all user resources, silently changing their logging
verbosity. The app host now uses `ASPIRE_APPHOST_LOGLEVEL` instead,
which is scoped to Aspire processes only. (#​17071, backported via
#​17078)
- 🔑 **Keycloak HTTPS primary endpoint** — Fixed a regression where
Keycloak tokens became invalid after an app host restart because the
HTTPS endpoint port was dynamic. When developer certificates are
enabled, Keycloak's primary endpoint is now upgraded to HTTPS directly,
and the endpoint name is set to `http` to enable standard
`http+https://` service discovery URLs. (#​17058, backported via
#​17063)
- 🔌 **Endpoint materialization in `HostResourceWithEndpoints`** —
Endpoints configured via `HostResourceWithEndpoints` are now correctly
materialized, ensuring endpoint resolution and service discovery work as
expected. (#​17091, backported via #​17092)

### 🏷️ Housekeeping

- ⬆️ Bumped DCP (Microsoft.DeveloperControlPlane) from 0.23.5 → 0.23.6 —
includes fixes for Kubernetes OpenAPI generator types that caused
`[SHOULD NOT HAPPEN] failed to update managedFields` errors. (#​17070)
- 🚀 Bumped branding to 13.3.3 (#​17088)

---
*Full commit:
[a4615e7c6def6cba4703cdbd84009cd3da9a261b](microsoft/aspire@a4615e7c6def6cba4703cdbd84009cd3da9a261b)*


Commits viewable in [compare
view](microsoft/aspire@v13.3.2...v13.3.3).
</details>

Updated [Aspire.Hosting.Testing](https://github.com/microsoft/aspire)
from 13.3.2 to 13.3.3.

<details>
<summary>Release notes</summary>

_Sourced from [Aspire.Hosting.Testing's
releases](https://github.com/microsoft/aspire/releases)._

## 13.3.3

## What's New in Aspire 13.3.3

Patch release for Aspire 13.3 with fixes for debug log level leaking
into user resources, Keycloak HTTPS endpoint token invalidation, and
endpoint materialization in `HostResourceWithEndpoints`.

### 🐛 Fixes

- 🔇 **Debug log level leaking into user resources** —
`Logging__LogLevel__Default=Debug` set by the app host was being
inherited by all user resources, silently changing their logging
verbosity. The app host now uses `ASPIRE_APPHOST_LOGLEVEL` instead,
which is scoped to Aspire processes only. (#​17071, backported via
#​17078)
- 🔑 **Keycloak HTTPS primary endpoint** — Fixed a regression where
Keycloak tokens became invalid after an app host restart because the
HTTPS endpoint port was dynamic. When developer certificates are
enabled, Keycloak's primary endpoint is now upgraded to HTTPS directly,
and the endpoint name is set to `http` to enable standard
`http+https://` service discovery URLs. (#​17058, backported via
#​17063)
- 🔌 **Endpoint materialization in `HostResourceWithEndpoints`** —
Endpoints configured via `HostResourceWithEndpoints` are now correctly
materialized, ensuring endpoint resolution and service discovery work as
expected. (#​17091, backported via #​17092)

### 🏷️ Housekeeping

- ⬆️ Bumped DCP (Microsoft.DeveloperControlPlane) from 0.23.5 → 0.23.6 —
includes fixes for Kubernetes OpenAPI generator types that caused
`[SHOULD NOT HAPPEN] failed to update managedFields` errors. (#​17070)
- 🚀 Bumped branding to 13.3.3 (#​17088)

---
*Full commit:
[a4615e7c6def6cba4703cdbd84009cd3da9a261b](microsoft/aspire@a4615e7c6def6cba4703cdbd84009cd3da9a261b)*


Commits viewable in [compare
view](microsoft/aspire@v13.3.2...v13.3.3).
</details>

Updated [Aspire.MongoDB.Driver](https://github.com/microsoft/aspire)
from 13.3.2 to 13.3.3.

<details>
<summary>Release notes</summary>

_Sourced from [Aspire.MongoDB.Driver's
releases](https://github.com/microsoft/aspire/releases)._

## 13.3.3

## What's New in Aspire 13.3.3

Patch release for Aspire 13.3 with fixes for debug log level leaking
into user resources, Keycloak HTTPS endpoint token invalidation, and
endpoint materialization in `HostResourceWithEndpoints`.

### 🐛 Fixes

- 🔇 **Debug log level leaking into user resources** —
`Logging__LogLevel__Default=Debug` set by the app host was being
inherited by all user resources, silently changing their logging
verbosity. The app host now uses `ASPIRE_APPHOST_LOGLEVEL` instead,
which is scoped to Aspire processes only. (#​17071, backported via
#​17078)
- 🔑 **Keycloak HTTPS primary endpoint** — Fixed a regression where
Keycloak tokens became invalid after an app host restart because the
HTTPS endpoint port was dynamic. When developer certificates are
enabled, Keycloak's primary endpoint is now upgraded to HTTPS directly,
and the endpoint name is set to `http` to enable standard
`http+https://` service discovery URLs. (#​17058, backported via
#​17063)
- 🔌 **Endpoint materialization in `HostResourceWithEndpoints`** —
Endpoints configured via `HostResourceWithEndpoints` are now correctly
materialized, ensuring endpoint resolution and service discovery work as
expected. (#​17091, backported via #​17092)

### 🏷️ Housekeeping

- ⬆️ Bumped DCP (Microsoft.DeveloperControlPlane) from 0.23.5 → 0.23.6 —
includes fixes for Kubernetes OpenAPI generator types that caused
`[SHOULD NOT HAPPEN] failed to update managedFields` errors. (#​17070)
- 🚀 Bumped branding to 13.3.3 (#​17088)

---
*Full commit:
[a4615e7c6def6cba4703cdbd84009cd3da9a261b](microsoft/aspire@a4615e7c6def6cba4703cdbd84009cd3da9a261b)*


Commits viewable in [compare
view](microsoft/aspire@v13.3.2...v13.3.3).
</details>

Updated
[Aspire.StackExchange.Redis.DistributedCaching](https://github.com/microsoft/aspire)
from 13.3.2 to 13.3.3.

<details>
<summary>Release notes</summary>

_Sourced from [Aspire.StackExchange.Redis.DistributedCaching's
releases](https://github.com/microsoft/aspire/releases)._

## 13.3.3

## What's New in Aspire 13.3.3

Patch release for Aspire 13.3 with fixes for debug log level leaking
into user resources, Keycloak HTTPS endpoint token invalidation, and
endpoint materialization in `HostResourceWithEndpoints`.

### 🐛 Fixes

- 🔇 **Debug log level leaking into user resources** —
`Logging__LogLevel__Default=Debug` set by the app host was being
inherited by all user resources, silently changing their logging
verbosity. The app host now uses `ASPIRE_APPHOST_LOGLEVEL` instead,
which is scoped to Aspire processes only. (#​17071, backported via
#​17078)
- 🔑 **Keycloak HTTPS primary endpoint** — Fixed a regression where
Keycloak tokens became invalid after an app host restart because the
HTTPS endpoint port was dynamic. When developer certificates are
enabled, Keycloak's primary endpoint is now upgraded to HTTPS directly,
and the endpoint name is set to `http` to enable standard
`http+https://` service discovery URLs. (#​17058, backported via
#​17063)
- 🔌 **Endpoint materialization in `HostResourceWithEndpoints`** —
Endpoints configured via `HostResourceWithEndpoints` are now correctly
materialized, ensuring endpoint resolution and service discovery work as
expected. (#​17091, backported via #​17092)

### 🏷️ Housekeeping

- ⬆️ Bumped DCP (Microsoft.DeveloperControlPlane) from 0.23.5 → 0.23.6 —
includes fixes for Kubernetes OpenAPI generator types that caused
`[SHOULD NOT HAPPEN] failed to update managedFields` errors. (#​17070)
- 🚀 Bumped branding to 13.3.3 (#​17088)

---
*Full commit:
[a4615e7c6def6cba4703cdbd84009cd3da9a261b](microsoft/aspire@a4615e7c6def6cba4703cdbd84009cd3da9a261b)*


Commits viewable in [compare
view](microsoft/aspire@v13.3.2...v13.3.3).
</details>

Updated
[PSC.Blazor.Components.MarkdownEditor](https://github.com/erossini/BlazorMarkdownEditor)
from 10.0.8 to 10.0.9.

<details>
<summary>Release notes</summary>

_Sourced from [PSC.Blazor.Components.MarkdownEditor's
releases](https://github.com/erossini/BlazorMarkdownEditor/releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/erossini/BlazorMarkdownEditor/commits).
</details>

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mpaulosky <60372079+mpaulosky@users.noreply.github.com>
Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary

Closes #348

Working as Boromir (DevOps/Infra) + Sam (Backend) + Gimli (Tester).

## Root Cause

After PR #346 (mongo:7 + mongo-data-v7 fix) was merged, MongoDB
containers continued crashing in the running environment. Investigation
revealed the active Aspire AppHost was built from the **main repo's
stale local `dev` branch** — 2 commits behind `origin/dev`, still
launching `mongo:8.2` → exit 139 (SIGSEGV/AVX).

Identified via: `ps aux | grep AppHost.dll` — DLL path revealed the
wrong repo root.

## Changes

### Boromir (DevOps/Infra)
- Pulled and rebuilt main repo AppHost (`git pull origin dev` + `dotnet
build`) — **0 errors**, MongoDB now uses `mongo:7` + `mongo-data-v7`.
- Added rule 6 to `.squad/skills/mongodb-dba-patterns/SKILL.md`: sync
main repo before starting Aspire; use `ps aux | grep AppHost.dll` to
identify the active build.
- Added investigation findings to `boromir/history.md`.

### Sam (Backend)
- Full backend audit: `MongoDbBlogPostRepository`,
`MongoDbCategoryRepository`, `BlogDbContext`, `Program.cs` — all
correct. **No production code change required.**
- Added findings to `sam/history.md`.

### Gimli (Tester)
- Added `SeedMyBlogData_Makes_Seeded_Posts_Visible_On_The_Blog_Page`
integration test to `MongoSeedDataIntegrationTests` — asserts seeded
posts are visible via the real AppHost-wired Web/MongoDB path.
- Added findings to `gimli/history.md`.

## Validation

- `MongoDbContainerConfigurationTests` — 4/4 ✅
- `Web.Tests.Integration` (Testcontainers) — 29/29 ✅
- All pre-push gates passed (markdownlint, build, unit tests,
integration tests) ✅
- AppHost.Tests build: 0 errors, 0 warnings ✅

## Volume State

| Volume | Status |
|---|---|
| `mongo-data` | ⚠️ FCV-contaminated (mongo:8.2 data, UUID-format). Do
not use with mongo:7. |
| `mongo-data-v7` | ✅ Clean, numeric-ident format, lock file 0 bytes.
Safe for mongo:7. |

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary

Fixes Aspire startup failures when cloning on a fresh machine.

### Changes
- `src/AppHost/aspire.config.json` — corrected `.csproj` reference from
`MyBlog.AppHost.csproj` -> `AppHost.csproj`
- `src/AppHost/MongoDbResourceBuilderExtensions.cs` — refactored MongoDB
resource builder
- Updated package versions in `Directory.Packages.props`
- Updated `src/AppHost/AppHost.csproj` and `src/Web/Web.csproj`
- Minor README and MCP config updates

### Validation
- AppHost build passes
- Architecture.Tests: 16/16 passed

Closes #350

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 23, 2026 20:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@github-actions github-actions Bot added the squad Squad triage inbox — Lead will assign to a member label May 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🏗️ PR Added to Squad Triage Queue

This PR has been labeled with squad and added to the triage queue.

Next steps:

  • The squad Lead will review and assign to an appropriate team member
  • A squad:member label will be added after triage

If you know which squad member should handle this, you can add the appropriate squad:member label yourself.

- Land the existing release conflict resolution into dev
- Unblock release PR #352 for main promotion

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mpaulosky and others added 2 commits May 23, 2026 14:36
- Resolve the remaining dev/main conflicts for Sprint 19 release
- Preserve the validated AppHost and workflow updates already in dev

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve the remaining dev/main conflicts with main preserved as a merge parent so release PR #352 can become mergeable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…release-unblock

chore(release): preserve main ancestry in dev for PR #352

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Test Results Summary

480 tests  +149   479 ✅ +149   34s ⏱️ +15s
  6 suites ±  0     1 💤 ±  0 
  6 files   ±  0     0 ❌ ±  0 

Results for commit e0a46c6. ± Comparison against base commit 7806be9.

@codecov

codecov Bot commented May 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.26926% with 298 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.86%. Comparing base (7806be9) to head (e0a46c6).

Files with missing lines Patch % Lines
src/Web/Features/Categories/List/Index.razor 0.00% 47 Missing and 12 partials ⚠️
...frastructure/Caching/UserManagementCacheService.cs 0.00% 48 Missing and 8 partials ⚠️
...b/Features/UserManagement/UserManagementHandler.cs 53.78% 47 Missing and 8 partials ⚠️
...Infrastructure/FileStorage/LocalDiskFileStorage.cs 0.00% 20 Missing and 3 partials ⚠️
src/Web/Features/BlogPosts/Create/Create.razor 62.00% 7 Missing and 12 partials ⚠️
src/AppHost/MongoDbResourceBuilderExtensions.cs 94.61% 15 Missing and 1 partial ⚠️
src/Web/Components/Shared/TextEditor.razor 50.00% 12 Missing and 2 partials ⚠️
src/Web/Features/UserManagement/Profile.razor 78.33% 6 Missing and 7 partials ⚠️
...c/Web/Components/Shared/PageHeadingComponent.razor 57.14% 1 Missing and 5 partials ⚠️
src/Web/Features/BlogPosts/Edit/Edit.razor 91.54% 2 Missing and 4 partials ⚠️
... and 11 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #352      +/-   ##
==========================================
- Coverage   86.57%   79.86%   -6.71%     
==========================================
  Files          44       68      +24     
  Lines        1043     1659     +616     
  Branches      116      201      +85     
==========================================
+ Hits          903     1325     +422     
- Misses         96      244     +148     
- Partials       44       90      +46     
Files with missing lines Coverage Δ
src/Domain/Abstractions/Result.cs 80.55% <ø> (ø)
src/Domain/Behaviors/ValidationBehavior.cs 100.00% <100.00%> (ø)
src/Domain/Entities/BlogPost.cs 100.00% <100.00%> (ø)
src/Domain/Entities/Category.cs 100.00% <100.00%> (ø)
src/Domain/ValueObjects/PostAuthor.cs 100.00% <100.00%> (ø)
src/Web/Components/Layout/MainLayout.razor 100.00% <ø> (ø)
src/Web/Components/Layout/NavMenu.razor 75.00% <ø> (ø)
src/Web/Data/BlogDbContext.cs 100.00% <100.00%> (ø)
src/Web/Data/BlogPostDto.cs 100.00% <100.00%> (ø)
src/Web/Data/BlogPostMappings.cs 100.00% <100.00%> (ø)
... and 41 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mpaulosky
mpaulosky merged commit c7e4c3a into main May 23, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

squad Squad triage inbox — Lead will assign to a member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants