Skip to content

FullStackHero 10 .NET Starter Kit Release Merge#1152

Draft
iammukeshm wants to merge 660 commits into
mainfrom
develop
Draft

FullStackHero 10 .NET Starter Kit Release Merge#1152
iammukeshm wants to merge 660 commits into
mainfrom
develop

Conversation

@iammukeshm
Copy link
Copy Markdown
Member

#Architecture

  • Modular monolith with modules for Identity, Multitenancy, Auditing; mediator-based CQRS; background jobs; caching; mailing; storage abstraction.
  • Minimal API host with Identity (JWT, refresh, roles/permissions), Multitenancy (Finbuckle, provisioning lifecycle), Auditing (request/response/security/exception with background sink).
  • Shadcn-inspired MudBlazor wrappers; Dashboard/Profile/Audits pages wired to generated API clients; BFF-style auth delegating handler; theme/layout shell.
  • NSwag config + script to regenerate clients (scripts/openapi/generate-api-clients.ps1 -SpecUrl "<spec>"); Blazor consumes generated clients.
  • Multi-app AWS scaffolding (API/Blazor) with modular structure using Terraform.
  • Mediator Handlers and Validation
  • RateLimiting / Storage / Outbox Pattern

@iammukeshm iammukeshm requested a review from Copilot December 9, 2025 09:12
@iammukeshm iammukeshm self-assigned this Dec 9, 2025
@iammukeshm iammukeshm added the enhancement New feature or request label Dec 9, 2025
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces the FullStackHero 10 .NET Starter Kit, implementing a modular monolith architecture with comprehensive modules for Identity, Multitenancy, and Auditing. The implementation includes a mediator-based CQRS pattern, JWT authentication with refresh tokens, role/permission-based authorization, background job support, caching abstractions, mailing services, and storage abstractions (local and S3). The Blazor client uses Shadcn-inspired MudBlazor wrappers with generated API clients via NSwag, while the infrastructure includes multi-app AWS scaffolding using Terraform and OpenTelemetry-based observability.

Key Changes

  • Modular architecture with separate Identity, Multitenancy, and Auditing modules implementing contracts and handlers
  • JWT authentication, role/permission system, and Finbuckle multitenancy with per-tenant provisioning lifecycle
  • Auditing pipeline with request/response/security/exception tracking and background sink for SQL persistence
  • OpenTelemetry integration, rate limiting, storage abstraction (local/S3), and comprehensive building blocks for caching, jobs, mailing, and persistence

Reviewed changes

Copilot reviewed 295 out of 1048 changed files in this pull request and generated no comments.

Show a summary per file
File Description
Directory.Packages.props Updated package versions to .NET 10.0 and newer dependencies including Finbuckle 10.0.0, Mediator 3.1.0-preview.14, Hangfire 1.8.22, and OpenTelemetry 1.14.0
Directory.Build.props Enhanced with .NET 10.0 target, comprehensive code analysis settings, NuGet metadata, and stricter quality controls
BuildingBlocks/Web/*.cs New Web building block with OpenAPI/Scalar integration, OpenTelemetry, Serilog logging, rate limiting, security headers, CORS, versioning, and module loading
BuildingBlocks/Storage/*.cs Storage abstraction supporting local filesystem and AWS S3 with file type validation and upload/removal operations
BuildingBlocks/Shared/*.cs Shared contracts for multitenancy (AppTenantInfo), identity (claims, permissions, roles), pagination, and database options
BuildingBlocks/Persistence/*.cs Persistence infrastructure with specifications pattern, EF Core extensions, and database initialization interfaces
Modules/Identity/Modules.Identity.Contracts/*.cs Identity module contracts including commands/queries for token generation, user management, role management, and associated DTOs
Modules/Auditing/Modules.Auditing.Contracts/*.cs Auditing contracts with event types, payloads, DTOs, and interfaces for audit publishing, serialization, and sinking
Modules/Auditing/Modules.Auditing/*.cs Auditing implementation with SQL sink, EF interceptor, HTTP middleware for request/response capture, channel-based publisher, and query handlers

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@iammukeshm iammukeshm marked this pull request as draft December 9, 2025 09:13
@maxiar
Copy link
Copy Markdown
Contributor

maxiar commented Dec 10, 2025

#Architecture

  • Modular monolith with modules for Identity, Multitenancy, Auditing; mediator-based CQRS; background jobs; caching; mailing; storage abstraction.
  • Minimal API host with Identity (JWT, refresh, roles/permissions), Multitenancy (Finbuckle, provisioning lifecycle), Auditing (request/response/security/exception with background sink).
  • Shadcn-inspired MudBlazor wrappers; Dashboard/Profile/Audits pages wired to generated API clients; BFF-style auth delegating handler; theme/layout shell.
  • NSwag config + script to regenerate clients (scripts/openapi/generate-api-clients.ps1 -SpecUrl "<spec>"); Blazor consumes generated clients.
  • Multi-app AWS scaffolding (API/Blazor) with modular structure using Terraform.
  • Mediator Handlers and Validation
  • RateLimiting / Storage / Outbox Pattern

Wow! You woke up!! :) Excelent works, I going to clone and test it... Please check, you forgot push the /docs folders because is added in .gitignore: "/docs"
BTW.... What IDE or stack you use or recommend to work better, get a good experience with this starter kit, may be VS 2026 + Copilot, or VS Code + Codex or Cursor + Another IA Model, what is your experience creating this template, Did you use any AI Assistance with some .MD spec files to define the software architect guidelines or something like that?

Thanks in advanced.

@iammukeshm
Copy link
Copy Markdown
Member Author

@maxiar

I am currently using VS2026.
Docs is ignored purposely, as they will be on another repo. It's still a WIP.
For AI Code Guidance, currently testing with Codex CLI. Trying to formulate a framework for a nice workflow experience. Will write about it on my blog once I figure it out.

@maxiar
Copy link
Copy Markdown
Contributor

maxiar commented Dec 12, 2025

@maxiar

I am currently using VS2026.

Docs is ignored purposely, as they will be on another repo. It's still a WIP.

For AI Code Guidance, currently testing with Codex CLI. Trying to formulate a framework for a nice workflow experience. Will write about it on my blog once I figure it out.

Perfect approach, check that may be some ideas are usefull:

https://medium.com/@mikhail.petrusheuski/steal-these-25-prompts-the-rules-workflows-that-made-our-net-team-faster-27899ece4dcc

And this "spec driven AI design":

https://medium.com/@mikhail.petrusheuski/steal-these-25-prompts-the-rules-workflows-that-made-our-net-team-faster-27899ece4dcc

@iammukeshm
Copy link
Copy Markdown
Member Author

iammukeshm commented Dec 12, 2025

@maxiar looks like its a member only story. any crucial takeaways?

@github-advanced-security
Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Comment thread src/BuildingBlocks/Web/Exceptions/GlobalExceptionHandler.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/SimpleBffAuth.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/SimpleBffAuth.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/ThemeStateFactory.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/ThemeStateFactory.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/ThemeStateFactory.cs Fixed
Comment thread src/Modules/Identity/Modules.Identity/Services/TokenService.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/SimpleBffAuth.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/SimpleBffAuth.cs Fixed
Comment thread src/Modules/Identity/Modules.Identity/Services/TokenService.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/SimpleBffAuth.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/SimpleBffAuth.cs Fixed
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Mar 26, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
fullstackhero 4b7a641 May 24 2026, 08:07 AM

Comment thread src/BuildingBlocks/Caching/DistributedCacheService.cs Fixed
Comment thread src/BuildingBlocks/Caching/DistributedCacheService.cs Fixed
Comment thread src/BuildingBlocks/Caching/HybridCacheService.cs Fixed
Comment thread src/BuildingBlocks/Caching/HybridCacheService.cs Fixed
Comment thread src/BuildingBlocks/Web/Idempotency/IdempotencyEndpointFilter.cs Fixed
Comment thread src/BuildingBlocks/Web/Idempotency/IdempotencyEndpointFilter.cs Fixed
Comment thread src/Playground/Playground.Blazor/Services/SimpleBffAuth.cs Fixed
Comment thread src/Host/FSH.Starter.Api/DevSeeding/DevDataSeeder.cs Fixed
iammukeshm and others added 14 commits May 13, 2026 11:38
…, Add/Remove members, FindOrCreateDm

Each command/handler/validator/endpoint follows the project's VSA convention
(Features/v1/Channels/<FeatureName>/). Authorization helpers in
Features/v1/Internal/ChannelAuthorization keep the "must be channel member /
must be channel admin" assertions DRY and use NotFoundException over Forbidden
on missing-member so non-members can't probe channel existence.

DM uniqueness handled in FindOrCreateDmCommandHandler via DirectKey lookup; group
DMs (3+) are always created fresh per spec.

Added Archive + Find to the endpoint-verb whitelist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Completes Slice 1 baseline: read paths (list/discover/get channel,
list messages), edit/delete message lifecycle, and the mark-channel-read
endpoint advancing each member's LastReadMessageId watermark.

- GetChannelById query computes per-caller unread count via Guid v7 ordering
- ListMyChannels returns membership rows with unread counts
- DiscoverChannels lists public-only channels the caller can join
- SendMessage rejects nested threads (1-level reply depth)
- DeleteMessage author-or-moderator gate via IUserPermissionService
- MarkChannelRead validates marker message belongs to the channel
- ListChannelMessages: cursor-paged top-level only, Guid v7 desc

Endpoint verbs widened in architecture tests for Discover/Edit/Send.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…hecks

Adds the Chat module + contracts project references to Architecture.Tests
so reflection-based scanners (HandlerValidatorPairing, DomainEntity,
ContractsPurity, etc.) pick up Chat assemblies. Augments the explicit
forbidden-namespace lists with Chat.Features / Chat.Data / Chat.Domain
so the host cannot reach into module internals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
30 tests covering DM DirectKey ordering, group-DM creator-as-admin,
member add/remove rules, MarkRead watermark, slug normalization,
message edit/delete author + moderator gates, reply-count bumps,
and tombstone idempotency.

Exposes Modules.Chat internals to Chat.Tests + Integration.Tests
so internal helpers (IncrementReplyCount/DecrementReplyCount) can
be exercised directly in unit tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChatChannelsTests — happy paths, archive/restore roundtrip,
find-or-create DM idempotency via DirectKey, add/remove member,
auth gates, validation of self-DM rejection.

ChatMessagesTests — send/edit/delete lifecycle, cursor pagination,
thread replies + parent ReplyCount bump, top-level filter excludes
thread replies, mark-read watermark drops UnreadCount to zero,
1-level thread depth enforcement, 404s and 400 for missing/invalid.

Also corrects an outdated comment in ChatModule.cs — ListMyChannels
maps GET /channels (not /channels/me).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a single shared AppHub at /api/v1/realtime/hub (BuildingBlocks/Web/Realtime)
with the Redis backplane wired when CachingOptions:Redis is set. The hub joins
each connection to user:{userId} and to channel:{channelId} for every channel the
user is a member of (looked up via the new IUserChannelLookup that the Chat module
implements against ChatDbContext).

Chat handlers now publish realtime events after SaveChanges:
  SendMessage   → ChatMessageCreated         → channel:{id}
  EditMessage   → ChatMessageEdited          → channel:{id}
  DeleteMessage → ChatMessageDeleted         → channel:{id}
  AddMembers    → ChatChannelMemberAdded     → channel:{id}
                + ChatChannelAdded            → user:{newMember}
  RemoveMember  → ChatChannelMemberRemoved   → channel:{id}
                + ChatChannelRemoved          → user:{removed}
  MarkRead      → ChatChannelRead             → user:{caller} (cross-tab badge clear)

Also extends the JWT bearer OnMessageReceived path allow-list to accept
?access_token= for the hub path — browsers can't send Authorization headers on
WebSocket upgrade or EventSource fallback. Path-scoped to keep the exemption
narrow.

Existing 23 chat integration tests still pass; SignalR integration tests added
in the next commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tests via in-memory HubConnection (long-polling transport since the
TestServer has no WebSocket support):
- ChatMessageCreated lands on the channel group when a message is sent
- ChatMessageEdited mirrors edits across the channel
- ChatMessageDeleted mirrors deletes across the channel
- ChatChannelRead lands on the user's own group (cross-tab badge clear)
- Hub rejects unauthenticated connections

Also fixes AppHub authentication: ICurrentUser depends on IHttpContextAccessor,
which doesn't pin the originating negotiate HttpContext to subsequent hub
invocations. Switched to reading the user id directly off Context.User
(NameIdentifier / sub / uid) which is the canonical SignalR pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…gration

Peer module to Chat. Module Order 750 runs ahead of Chat (800) so its
integration-event subscribers are registered before Chat publishes —
handler registration is order-sensitive in the in-memory event bus.

- Modules.Notifications + .Contracts projects, slnx + Api + Migrations refs
- NotificationPermissions (Inbox.View / Inbox.MarkRead; both basic)
- Notification aggregate (UserId, Type, Title, Body, Link, Source,
  MetadataJson, ReadAtUtc, CreatedAtUtc) + MarkRead()
- NotificationsDbContext on schema "notifications" + EF config with the
  composite (UserId, ReadAtUtc, CreatedAtUtc) index that covers every
  inbox query path
- AddIntegrationEventHandlers wiring so Slice 3.5's mention handler
  picks up automatically once written
- InitialNotifications EF migration

Mediator markers intentionally omitted from Program.cs until Slice 3.3
introduces the first ICommand/IQuery (Mediator source-gen MSG0007).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Under /api/v1/notifications, all scoped to the authenticated caller:
  GET    /                   ListNotifications?unreadOnly=&page=&pageSize=
  GET    /unread-count       GetUnreadCount     — bell badge
  POST   /{id}/read          MarkNotificationRead — single
  POST   /read-all           MarkAllNotificationsRead — returns count updated

Mark-read commands use a (Id, UserId) filter so callers can only mutate
their own rows (404 instead of 403 on cross-user reach). MarkAll uses
ExecuteUpdateAsync for a single bulk UPDATE — no row materialization.

Also re-enables Notifications markers in Program.cs::AddMediator now
that ICommand/IQuery types exist (was deferred to avoid MSG0007).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a child MessageMention entity attached to Message.Mentions, with
position (StartIndex, Length) preserved from the raw body so the UI
can highlight without re-parsing.

SendMessageCommandHandler now:
- extracts @username tokens via MentionParser (Slack/Discord-style regex)
- resolves them via IMentionResolver (default: filters Identity user list)
- drops unresolved tokens and self-mentions silently
- attaches one MessageMention per resolved (other) user
- publishes one MentionedInChannelIntegrationEvent per distinct mentioned
  user (Notifications module subscribes in Slice 3.5)

MentionedInChannelIntegrationEvent lives in Modules.Chat.Contracts (the
public surface). MentionResolver implementation stays internal to Chat.

AddMessageMentions EF migration creates the chat.MessageMentions table
with cascade-delete FK to Messages and indexes on MentionedUserId +
MessageId.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Notifications subscribes to the Chat module's MentionedInChannelIntegrationEvent:
- Persists a chat.mention Notification row for the mentioned user
- Pushes a NotificationCreated SignalR event to user:{id} so the bell
  badge updates live across that user's tabs

Handler lives in Notifications/IntegrationEventHandlers/ (top-level, not
under Features/) so arch tests don't flag the non-versioned folder
under Features — matches the Identity Events/ convention.

Integration tests cover the three meaningful paths:
- @-mention persists a Notification visible in the recipient's inbox
- @-mention fires NotificationCreated over SignalR (long-polling test
  transport; receives via HubConnection authenticated as the recipient)
- Self-mentions are dropped (no notification row written)

Tests bypass /register's email-confirmation gate via UserManager so the
second user can sign in immediately — matches the existing
EmailConfirmationTests pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Threads:
- GET /chat/messages/{id}/replies — cursor-paged, reverse chronological
  via Guid v7. RequireMember through parent's channel.
- DeleteMessage already decrements parent ReplyCount (Slice 1) — covered
  by a new integration test here.

Reactions:
- MessageReaction child entity attached to Message.Reactions; unique
  index on (MessageId, UserId, Emoji) so a user can react with the
  same emoji only once per message.
- AddReaction/RemoveReaction handlers — idempotent (re-add and absent-
  remove are silent no-ops, no spurious broadcasts).
- ChatReactionChanged SignalR event broadcast to channel:{id} on each
  mutation with { channelId, messageId, userId, emoji, kind }.
- MessageDto now carries Reactions (forces the dashboard contract to
  pick up the new shape).

8 new integration tests + 6 new unit tests; existing 23 chat REST +
5 realtime + 3 mention all still green.

AddMessageReactions EF migration creates chat.MessageReactions with
cascade FK to Messages and the composite unique index.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GET /api/v1/chat/search?q=&channelId=&page=&pageSize= — ranked by ts_rank
with a stable Id-desc tiebreaker for deterministic pagination.

- AddMessagesFullTextSearch migration: GENERATED ALWAYS AS tsvector
  column on chat.Messages + GIN index. Kept out of the EF model
  (raw SQL) since EF doesn't track GENERATED columns and we never
  write to it from C#.
- SearchMessagesQueryHandler issues a single parameterized
  FromSqlInterpolated query joining against the caller's member
  channels. Channel-scoping is enforced server-side so non-members
  cannot leak results from channels they don't belong to.
- Uses websearch_to_tsquery so callers can write natural search
  syntax (quoted phrases, OR, -exclude) without server-side parsing.
- Soft-deleted messages (DeletedAtUtc IS NOT NULL) are excluded.

4 integration tests cover: token match in member channel, channelId
narrowing, non-member exclusion (registered second user, blank result),
and soft-delete tombstone exclusion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
iammukeshm and others added 30 commits May 23, 2026 17:31
…+ coverage-gate job

Fixes the stale test matrix (Chat.Tests/Files.Tests were never run in CI) and adds
a Coverage Gate job that runs the whole solution with Coverlet and fails below an
80%-ish line floor (ratchet — bump MIN_LINE as coverage rises).
…te limiting + security headers

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ler + rate limiting + security headers"

This reverts commit 3d9955a, reversing
changes made to 679e6e3.
…ption handler + rate limiting + security headers)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… audit

Findings and fixes from a race-condition / code-smell audit (Roslyn navigator
detect_antipatterns, find_dead_code, detect_circular_dependencies + targeted
concurrency sweeps). Concurrency hygiene was already strong — no async void,
no sync-over-async, no fire-and-forget, thread-safe singletons, zero circular
deps. The genuine items:

- Audit (static): swap the enricher list for an atomically-replaced immutable
  array read once per WriteAsync. Kills the latent "collection modified" race
  if Configure() ever runs concurrently with enrichment, and removes a
  process-global mutable-List test-isolation hazard.
- QuotaEnforcementMiddleware: inject TimeProvider instead of DateTimeOffset.UtcNow
  for Retry-After, matching the rest of the Quota subsystem (deterministic in tests).
- PresenceTracker.Connect: also report the offline->online transition when the
  AddOrUpdate update factory resurrects a count==0 key (Disconnect set 0 but
  hadn't removed it yet) — previously a reconnect in that window missed the
  presence broadcast.
- ChannelMember: remove dead SetMuted (zero callers); IsMuted is now get-only
  (still persisted + exposed via DTO, populated by EF via backing field).

Investigated but intentionally NOT changed (false positives confirmed):
- catch(Exception) in hosted services already filter OperationCanceledException.
- Flagged EF "missing AsNoTracking" queries all read-then-mutate-then-save
  (tracking required); the read-only paths already use AsNoTracking.
- find_dead_code hits for ChannelAuthorization / EntityEntryExtensions are
  used extension methods; EF model snapshots are tooling artifacts.

All unit (779) + integration (665) + middleware (5) tests green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… (accurate to current codebase)

Establish AGENTS.md as the canonical, tool-neutral AI guide (CLAUDE.md/GEMINI.md
are thin @import bridges) and build out .agents/ guidance verified against the
current code via Roslyn navigation + real-file extraction.

Rules (.agents/rules/) — lean, on-demand, indexed from AGENTS.md:
- cross-cutting: architecture, api-conventions, database, eventing, caching, jobs,
  resilience, storage, security, realtime, logging, testing, integration-testing
- per-module: identity, multitenancy, chat, files, webhooks, auditing, billing,
  catalog, tickets, notifications
- frontend: shared + admin + dashboard (the two React apps' real divergences)
- replaces the old flat modules.md/persistence.md/testing-rules.md

Skills (.agents/skills/) — audited the 6 existing against the live codebase and
rewrote them (they were stale: IRepository<T>, PagedList<T>, Moq/FluentAssertions,
Guid.NewGuid, class-level [FshModule(Order=n)], DbContext vs BaseDbContext, only 2
of the 4 module-registration sites). Added 5: add-react-page, add-full-slice,
create-migration, add-integration-event, add-permission. Skills hold the recipe.

Workflows (.agents/workflows/) — reconciled so they orchestrate and delegate to
skills (no duplicated/contradictory templates); fixed stale facts (migrations run
via DbMigrator, not on startup; TenantDbContext not "MultitenancyDbContext").

Also corrects the [FshModule] attribute (assembly-level positional, not class-level)
in architecture.md and the AGENTS.md pointer.

Docs only; no source/build impact.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop nswag.consolecore from dotnet-tools and delete scripts/openapi/*
  (NSwag-based C# client generation is no longer used).
- Remove scripts/test-cli.ps1 and the requirements/frontend-and-platform.md
  planning doc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…page redesign, v10

- AI-Driven Development docs section (overview, AGENTS.md & .agents/, skills &
  workflows, developing with Claude Code) + section registration.
- Sponsorship: sticky sponsor card atop the docs ToC, and a "Back the build"
  home section (Open Collective), placed right under the architecture section.
- Homepage: new "Stack at a glance" bento opener; the architecture section
  rebuilt as a modular-monolith + vertical-slice diagram (two balanced boards);
  FSH brand mark in the hero; "Who it's for" redesigned as icon-led cards;
  module-card code panels removed; competitor product references removed.
- Version: product version aligned to v10 (.NET 10) across the homepage and
  docs copy. API version paths (/api/v1, Features/v1, Contracts.v1) untouched.
- Fix: type the header nav `match` field — astro check now 0 errors / 0 warnings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lish

- Add "Tested to production standard" landing section (Testing.astro): a
  four-pillar scoreboard (unit / integration / E2E / architecture) over a
  green test-run terminal, leading with real-PostgreSQL-via-Testcontainers.
  Wire in as section 05; renumber WhoItsFor/FAQ/FinalCta to 06/07/08. Sync
  stale test counts in Hero (900+ -> 1,400+) and the FAQ answer.
- Theme toggle: replace the muddy CSS token cross-fade with a View Transitions
  API snapshot cross-fade (GPU-composited, text stays crisp, no frame drops);
  clean instant fallback for reduced-motion / unsupported browsers.
- Mobile responsiveness pass on the homepage: drop heading bases (sections
  30px, hero 34px) so they stop dominating phones; hero stats, TechStack, and
  the testing scoreboard go single-column on mobile; hero terminal scrolls
  instead of clipping; FAQ answers reclaim full width on mobile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t, React SPA hosting

- Pin Terraform >= 1.15.4 and AWS provider ~> 6.46 in the roots; permissive
  floors (>= 1.15 / >= 6.0) in child modules. Commit a multi-platform
  .terraform.lock.hcl locked to aws 6.46.0.
- Collapse the shared/ -> app_stack/ wrapper into a single root (provider +
  backend now live in app_stack/), removing ~500 lines of duplicated vars and
  outputs plus a passthrough bug that silently dropped ~30 tunables. Dedupe
  tags via provider default_tags.
- Add reusable modules/static_site (private S3 + OAC CloudFront, SPA
  403/404->index.html fallback, default-on managed security headers,
  Terraform-owned config.json) and host the two React SPAs (admin, dashboard)
  that replaced the removed server-rendered Blazor service. SPA CloudFront
  origins are auto-added to the API CORS allow-list. No Route53/domain
  resources (custom aliases optional).
- Drop the unnecessary api_task_secrets IAM policy (least privilege).
- Add one-command deploy.sh / deploy.ps1: terraform apply -> optional API
  image build/push -> build + s3 sync + CloudFront invalidate for both SPAs.
- Refresh README; terraform fmt + validate clean against aws 6.46.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…laude

Pre-existing working-tree changes outside the Terraform audit, committed so the
branch is clean:
- templates/ NuGet pack csproj, .template.config/template.json, README-template
- CLI NewCommand updates; AppHost + solution (slnx) wiring
- CI: add template-smoke workflow, ci.yml tweak
- docs: site.ts, breadcrumb helper, llms.txt/robots.txt, Cloudflare _headers/_redirects, error-handling page
- .gitignore: exclude local .claude worktrees, scheduled_tasks.lock, last30days.env

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ex pages "Overview"

- sidebar: detect the Astro 6 glob-loader bare-dir index id ('frontend' as well
  as 'frontend/index') so every section's overview is pulled out and rendered
  first, instead of leaking into the page list and sorting by order.
- breadcrumbs: a section overview now renders 'Docs / <Section>' (section is the
  current page) instead of duplicating it ('Docs / Modules / Modules'); fixed in
  both the visible component and the JSON-LD schema.
- name all 15 category index pages 'Overview' (with descriptive per-page seo.title).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…; rewrite install paths

- deployment/aspire: services that spin up locally + the design decisions.
- deployment/database-migrations: the DbMigrator (commands, multitenancy, prod usage).
- deployment/aws-terraform: end-to-end AWS deploy from prerequisites to one command.
- deployment/ci-cd: the GitHub Actions pipeline + template smoke test.
- getting-started/install: four install paths with screenshot placeholders.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Delete the Blazor.UI building-block page and drop Blazor.UI / FSH.Starter.Blazor
from the project trees, the building-blocks list (llms.txt), and the CORS CSP
note. Competitor comparisons (BlazorPlate, ABP) and legacy blazor-* redirects
are kept intentionally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- deep-dive: add the subclass 'base.OnModelCreating LAST' rule, the documented
  Billing isolation exception (plain DbContext + manual TenantId), per-tenant
  migration ordering, and the AsyncLocal test gotcha.
- fix multitenancy module links that pointed at the section index instead of
  the deep-dive; cross-link Billing to the documented exception.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dingBlocks tests (#1244)

* fix(tests): make BuildingBlocks dependency checks cross-platform

ProjectReference Include paths are authored with Windows separators
(..\Core\Core.csproj). Path.GetFileNameWithoutExtension only treats
"\" as a separator on Windows, so on Linux CI it returned the full
path minus extension (..\Core\Core) instead of the bare name (Core).

This caused BuildingBlocks_Should_Follow_Layered_Dependencies to report
12 false-positive violations on Linux (passed locally on Windows), and
silently disabled the module-reference enforcement in
BuildingBlocks_Projects_Should_Not_Reference_Modules_Directly.

Normalize "\" to "/" before extracting the project name so both checks
work on every platform.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(webhooks): require http(s) scheme for subscription URL

Uri.TryCreate(UriKind.Absolute) accepts a leading-/ path as an implicit
file:// URI on Unix (but not Windows), so "/relative/path" passed
validation on the Linux CI runner while the test passed locally on
Windows. A webhook target must be an HTTP(S) endpoint regardless of
platform, so assert the scheme explicitly. Fixes the Linux-only failure
of Create_Should_Fail_When_Url_Relative.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Loads gtag.js site-wide via the base layout head. Both script tags
use is:inline so Astro emits them verbatim instead of bundling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore: extract docs site to a separate repo (fullstackhero/docs)

The Astro docs site now lives at github.com/fullstackhero/docs. Remove
docs/ from this repo and repoint the references that pointed into it.

- Move docs/superpowers/ (audits, specs, plans -- whole-project notes,
  not docs-site content) to repo root superpowers/, preserving history
- Remove the docs/ row from the AGENTS.md repo map
- Drop docs/{node_modules,dist,.astro} entries from .gitignore
- Repoint the README "deeper story" link to the new repo
- Drop "docs" from the code-reviewer workflow change-area grouping

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@
fix(docker): create MinIO bucket in prod compose + add migrator to root compose

deploy/docker (prod): nothing created the S3 bucket the Files module
writes to (S3StorageService just PutObjects into Storage:S3:Bucket and
never creates it), so the first upload failed with NoSuchBucket. Add a
minio-init one-shot (mc mb local/fsh) and gate api on its completion. No
anonymous policy -- objects are served via the API / presigned URLs.

docker-compose.yml (root/dev): had no migrator, so the API ran against an
empty schema (the DB is not migrated at API startup). Add a migrator
(apply --seed) + matching JWT/seed env so the seeded admin can log in,
gate api on it, and add a header clarifying this is the dev compose
(Aspire and deploy/docker are the other paths). DEV-ONLY secrets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@
Valkey 8 (BSD-3, the Linux Foundation Redis fork) replaces the
source-available Redis image across Aspire and both compose files. Drop-in:
the kit uses only StackExchange.Redis over RESP (cache, data protection,
SignalR backplane, quota) with no Redis Stack modules, and Hangfire is on
Postgres. Resource/service name stays "redis" so connection strings and
config keys do not churn.

- AppHost: AddRedis(...).WithImage("valkey/valkey","8") + .WithRedisInsight()
  (auto-wired cache browser; SSPL but dev-only). The valkey image ships
  redis-* symlinks and supports Aspire's TLS command, so the Redis
  integration works unmodified.
- docker-compose.yml (dev): valkey/valkey:8-alpine.
- deploy/docker (prod): valkey/valkey:8-alpine + valkey-server/valkey-cli.

Verified by booting Aspire: Valkey starts clean (tcp+tls listeners),
authenticated PING returns PONG, RedisInsight comes up auto-connected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… Valkey

Switch the Testcontainers image from redis:7-alpine to valkey/valkey:8-alpine
so the suite proves the cache round-trip works on the new engine. Verified
locally: 4 passed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add golden rule #10 — a user-facing change (feature, endpoint, config, infra,
breaking change) isn't done until the separate docs repo
(github.com/fullstackhero/docs) is updated to match and a changelog entry is
added. Also fix the stale "Redis 6379" ports line to "Valkey 6379".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants