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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/content/docs/ai-development/agents-md.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ Only the root guide loads into the agent's context on every session. Detailed co
keeps each session cheap while still having deep guidance available the moment it's needed.
</Callout>

Projects created with `fsh new` (or `dotnet new fsh`) get all of these files: `AGENTS.md`, both bridges and the
whole `.agents/` folder. Sections that only apply to the kit's own repo (branching, CI gates, the docs-repo
rule) are stripped from the scaffolded `AGENTS.md`. Pass `--no-agents` (CLI) or `--agents false` (template) to
leave all four out.

## The `.agents/` folder

```
Expand Down
3 changes: 2 additions & 1 deletion src/content/docs/changelog/index.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Overview
lastUpdated: 2026-10-02
lastUpdated: 2026-10-09
description: Release notes and version history for fullstackhero.
sidebar:
order: 1
Expand All @@ -13,6 +13,7 @@ Notable changes to the kit, newest first.

## 2026-10-09

- **CLI & template: scaffolded projects now ship the AI guides `AGENTS.md` points to (fix).** `fsh new` and `dotnet new fsh` included `AGENTS.md` but excluded `CLAUDE.md`, `GEMINI.md` and `.agents/`, so the guide referenced files that did not exist. All four now ship together by default, the scaffolded `AGENTS.md` drops the sections that only apply to the kit's own repo, and `--no-agents` (CLI) / `--agents false` (template) leaves them all out. The internal `superpowers/` folder (specs and audits) no longer ships either. See [CLI](/docs/cli/#fsh-new) and [#1432](https://github.com/fullstackhero/dotnet-starter-kit/pull/1432).
- **Identity: a failed sign-in no longer turns an open profile form into a `412` (fix).** `GET /api/v1/identity/profile` published the user's `ConcurrencyStamp` as the `ETag`, and ASP.NET Identity rotates that stamp on every write to the user row, including the `AccessFailedCount` bump of a wrong password and its reset on the next good sign-in. Anyone who typed a wrong password for the account made the user's next profile save answer `412 Precondition Failed` although nothing in the profile had changed. The `ETag` is now an HMAC-SHA256 of the fields `PUT /profile` writes (first name, last name, phone number and stored avatar URL), keyed with the user's `SecurityStamp` so a logged tag cannot be used to confirm a guessed name and phone number, and `If-Match` is compared against it. Sign-ins and token refreshes leave it alone, while a real profile change, including a new avatar, still moves it; a password change or a two-factor toggle also moves it, because they rotate the key. Because the tag follows content, a save that leaves every field as it was keeps the same tag and replaying it is accepted. Identity's own `ConcurrencyStamp` check at save time is unchanged, so a non-profile write landing inside the single request between load and save still answers `412`. No migration and no client change: keep echoing the tag from the read that seeded the form. A profile form opened before the upgrade still holds an old tag, so its first save after the deploy answers `412` once, and the dashboard's usual re-read and re-save recovers from it. See [Identity](/docs/modules/identity/#profile-concurrency) and [#1425](https://github.com/fullstackhero/dotnet-starter-kit/pull/1425).
- **Authorization: `.RequirePermission(a, b)` now requires every listed permission (fix).** `RequiredPermissionAuthorizationHandler` checked only the first permission in the endpoint metadata, so a user holding `a` passed a gate that also demanded `b`. It now checks each one and succeeds only when the user holds all of them. A permission metadata entry with no permissions left (for example `.RequirePermission("")`) now denies the request; before, the handler threw `InvalidOperationException`. No kit endpoint lists more than one permission today, so nothing changes for the shipped API; your own multi-permission endpoints become stricter. See [Authorization](/docs/security/authorization/#applying-a-gate), [#1415](https://github.com/fullstackhero/dotnet-starter-kit/issues/1415) and [#1424](https://github.com/fullstackhero/dotnet-starter-kit/pull/1424).
- **Mailing & Docker Compose: e-mail works out of the box, and SMTP connection security is configurable (fix).** `SmtpMailService` always connected with STARTTLS, so any server that does not offer it was refused before a single envelope was sent, and the compose stack inherited the `smtp.ethereal.email` host with empty credentials: every confirmation, password-reset and welcome e-mail failed, and a user registered by an operator could not sign in until someone confirmed the address by hand. A new **`MailOptions:Smtp:Security`** setting (MailKit `SecureSocketOptions`, by name: `None`, `Auto`, `SslOnConnect`, `StartTls`, `StartTlsWhenAvailable`) chooses the mode; it defaults to `StartTls`, so existing configuration behaves exactly as before, and an unknown name fails the options binding instead of guessing. `deploy/docker/docker-compose.yml` now reads the SMTP target from `.env` (`FSH_SMTP_HOST`, `FSH_SMTP_PORT`, `FSH_SMTP_SECURITY`, `FSH_SMTP_USERNAME`, `FSH_SMTP_PASSWORD`), defaulting to a pinned [Mailpit](https://mailpit.axllent.org) catcher (`axllent/mailpit:v1.31.3`, `Security` set to `None`) that runs only under the `mail-catcher` compose profile, which `.env.example` enables with `COMPOSE_PROFILES=mail-catcher`. With that default, e-mail is caught, not delivered. SMTP stays on the compose network and the inbox UI is published on the host loopback only, at `http://localhost:8025` (`FSH_MAILPIT_PORT`), because it holds live reset and confirmation links. For real delivery, edit `.env` only: set `FSH_SMTP_*` to your provider, set `FSH_MAIL_FROM` to a sender it accepts (the compose default is `no-reply@fsh.local`, because `appsettings.Production.json` leaves `MailOptions:From` blank), and delete the `COMPOSE_PROFILES` line. See [Mailing](/docs/building-blocks/mailing/) and [#1409](https://github.com/fullstackhero/dotnet-starter-kit/pull/1409).
Expand Down
1 change: 1 addition & 0 deletions src/content/docs/cli/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fsh new MyApp --non-interactive -o ./somewhere-else
| `-o, --output` | Output directory (defaults to `./<name>`) |
| `--no-aspire` | Exclude the .NET Aspire AppHost project |
| `--no-frontend` | Exclude the React admin + dashboard apps |
| `--no-agents` | Exclude the AI coding guides (`AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `.agents/`) |
| `--skip-install` | Skip `npm install` for the React apps after scaffolding |
| `--non-interactive` | Skip prompts and use defaults (name becomes required) |
| `--git` | Initialize a git repository (on by default) |
Expand Down