FullStackHero 10 .NET Starter Kit Release Merge#1152
Conversation
There was a problem hiding this comment.
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.
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" Thanks in advanced. |
|
I am currently using VS2026. |
Perfect approach, check that may be some ideas are usefull: And this "spec driven AI design": |
|
@maxiar looks like its a member only story. any crucial takeaways? |
|
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:
For more information about GitHub Code Scanning, check out the documentation. |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
fullstackhero | 4b7a641 | May 24 2026, 08:07 AM |
…, 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>
…+ 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>
…te limiting + security headers
…ption handler + rate limiting + security headers) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
….Middleware.Tests)
… 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>
#Architecture
scripts/openapi/generate-api-clients.ps1 -SpecUrl "<spec>"); Blazor consumes generated clients.