258 lines
17 KiB
Markdown
258 lines
17 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to this project will be documented in this file.
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
|
## Stadium Release Names
|
|
|
|
This project uses famous football stadiums (A-Z) that hosted FIFA World Cup matches (with notable fallbacks where necessary):
|
|
|
|
| Letter | Stadium Name | Location | Tag Name |
|
|
| ------ | ----------- | -------- | -------- |
|
|
| A | Azteca | Mexico (1970, 1986, 2026) | `azteca` |
|
|
| B | Bernabéu | Spain (1982) | `bernabeu` |
|
|
| C | Centenario | Uruguay (1930) | `centenario` |
|
|
| D | Düsseldorf (Merkur Spiel-Arena) | Germany (2006) | `dusseldorf` |
|
|
| E | Ekaterinburg Arena | Russia (2018) | `ekaterinburg` |
|
|
| F | Frankfurt Waldstadion | Germany (1974, 2006) | `frankfurt` |
|
|
| G | Gelsenkirchen | Germany (2006) | `gelsenkirchen` |
|
|
| H | Hard Rock Stadium | USA (2026) | `hardrock` |
|
|
| I | Ibn Batouta Stadium | Morocco (2030) | `ibnbatouta` |
|
|
| J | Johannesburg Soccer City | South Africa (2010) | `johannesburg` |
|
|
| K | Kazan Arena | Russia (2018) | `kazan` |
|
|
| L | Lusail | Qatar (2022) | `lusail` |
|
|
| M | Maracanã | Brazil (1950, 2014) | `maracana` |
|
|
| N | Nantes Beaujoire | France (1998) | `nantes` |
|
|
| O | Olympiastadion Berlin | Germany (1974, 2006) | `olympiastadion` |
|
|
| P | Parc des Princes | France (1938, 1998) | `parcdesprinces` |
|
|
| Q | Qatar 974 | Qatar (2022) | `qatar974` |
|
|
| R | Rose Bowl | USA (1994) | `rosebowl` |
|
|
| S | San Siro | Italy (1934, 1990) | `sansiro` |
|
|
| T | Toronto BMO Field | Canada (2026) | `toronto` |
|
|
| U | Ullevi | Sweden (1958) | `ullevi` |
|
|
| V | Volgograd Arena | Russia (2018) | `volgograd` |
|
|
| W | Wembley | England (1966) | `wembley` |
|
|
| X | Xiamen Egret Stadium | (famous fallback) | `xiamen` |
|
|
| Y | Yokohama International Stadium | Japan (2002) | `yokohama` |
|
|
| Z | Zentralstadion Leipzig | Germany (1974, 2006) | `zentralstadion` |
|
|
|
|
---
|
|
|
|
## [Unreleased]
|
|
|
|
### Added
|
|
|
|
- `CLAUDE.md` as the single source of truth for project guidance and AI-agent instructions (issue #505); consolidates content previously split between `CLAUDE.md` and `.github/copilot-instructions.md`.
|
|
- `Invariants` section to `CLAUDE.md` documenting port, API contract, commit format, and CHANGELOG update requirements.
|
|
- `Architecture Decision Records` section to `CLAUDE.md` referencing `docs/adr/` with guidance on when to load and when to create new ADRs.
|
|
- Pre-commit step 6 to `CLAUDE.md`: update CLAUDE.md and create/amend the relevant ADR when a commit introduces or changes an architectural decision.
|
|
- `docs/adr/` path instruction to `.coderabbit.yaml` covering `**/*.csproj` (DATABASE_PROVIDER runtime selection) and `.github/workflows/**` (explicit provider requirement in CI jobs that run migrations or integration tests).
|
|
- `DATABASE_PROVIDER` environment variable (`sqlite` default, `postgres` opt-in) to select the database engine at startup (issue #249).
|
|
- PostgreSQL 17 support via `Npgsql.EntityFrameworkCore.PostgreSQL` 10.0.1; migrations in `Migrations/Npgsql/` use proper PostgreSQL column types (`uuid`, `boolean`, `timestamp with time zone`).
|
|
- `ProviderSpecificMigrationsAssembly` that filters the EF Core migration set to the active provider's namespace, ensuring `MigrateAsync()` applies the correct migrations for both SQLite and PostgreSQL.
|
|
- `postgres` Docker Compose profile and service (`postgres:17-alpine`), started only when `DATABASE_PROVIDER=postgres` is set; the API service uses `depends_on` with `required: false` so SQLite mode incurs no dependency on the postgres service.
|
|
- `.env.example` documenting `DATABASE_PROVIDER`, `DATABASE_URL`, and `POSTGRES_PASSWORD`.
|
|
- `.env` added to `.gitignore`.
|
|
- ADR-0014 (`docs/adr/0014-configurable-database-provider.md`) documenting the decision; supersedes ADR-0003.
|
|
- ADR-0015: Use Full-Replace PUT as the Partial Update Strategy
|
|
- ADR-0016: Adopt AI-Assisted Development Workflow
|
|
- ADR-0017: Adopt Spec-Driven Development (SDD)
|
|
|
|
### Changed
|
|
|
|
- Improved `CLAUDE.md` project guidance via the [CLAUDE.md Management plugin](https://claude.com/plugins/claude-md-management): added `Migrations/`, `Utilities/` (src) and `Integration/` (test) to the structure tree; documented `DATABASE_URL` Npgsql format, `STORAGE_PATH` SQLite path override, and exact `dotnet ef migrations add` commands for both providers; collapsed issue template bullets for conciseness; clarified `MigrateAsync()` runs automatically at startup.
|
|
- `adr/` directory moved to `docs/adr/`; all references in `README.md`, `CONTRIBUTING.md`, and `.coderabbit.yaml` updated to the new path (issue #505).
|
|
- `.coderabbit.yaml` controller path instruction updated: status code list corrected from `(200, 201, 400, 404, 409, 500)` to `(200, 201, 404, 409, 500)` with explicit note that FluentValidation failures must return 422 via `TypedResults.Problem(new HttpValidationProblemDetails(...))` (issue #505).
|
|
- `.coderabbit.yaml` knowledge base guidelines updated from `.github/copilot-instructions.md` to `CLAUDE.md` and `docs/adr/README.md` (issue #505).
|
|
- `.coderabbit.yaml` caching description in Tech Stack corrected to reflect both 10-minute sliding and 1-hour absolute expiration (issue #505).
|
|
- `AddDbContextPoolWithSqlite` renamed to `AddDbContextPool` in `ServiceCollectionExtensions`; now reads `DATABASE_PROVIDER` and wires either `UseSqlite` or `UseNpgsql` accordingly.
|
|
- `compose.yaml`: `api` service receives `DATABASE_PROVIDER` and `DATABASE_URL` environment variables; `postgres-data` named volume added.
|
|
- `scripts/entrypoint.sh`: SQLite file-presence check is skipped when `DATABASE_PROVIDER=postgres`.
|
|
- ADR-0003 status updated to "Superseded by ADR-0014".
|
|
- `README.md`: added Database section documenting SQLite and PostgreSQL modes.
|
|
|
|
### Fixed
|
|
|
|
- Populate `BuildTargetModel` in Npgsql seed migration designer files so Npgsql's SQL generator can resolve column types when applying `InsertData` operations.
|
|
- Suppress `PendingModelChangesWarning` for the postgres provider path — hand-crafted designer files cannot replicate Npgsql-injected runtime annotations (`Relational:MaxIdentifierLength`, `UseIdentityByDefaultColumn`), causing a false-positive that aborted `MigrateAsync()` at startup.
|
|
- Normalize `DATABASE_PROVIDER` to lowercase in `entrypoint.sh` via `tr` so `POSTGRES`, `Postgres`, etc. are handled consistently with `AddDbContextPool`.
|
|
- Trim and normalize `DATABASE_PROVIDER` in `AddDbContextPool` before the provider switch; add explicit `sqlite`/empty case; throw `InvalidOperationException` for unrecognized values so typos no longer silently fall through to SQLite.
|
|
- Move `Npgsql.EntityFrameworkCore.PostgreSQL` package from the "Development dependencies" `ItemGroup` to "Runtime dependencies".
|
|
|
|
### Removed
|
|
|
|
---
|
|
|
|
## [2.1.2 - Frankfurt] - 2026-04-26
|
|
|
|
### Changed
|
|
|
|
- Field validation failures now return `422 Unprocessable Entity` (RFC 4918) instead of `400 Bad Request`; `400 Bad Request` is now reserved for malformed requests (unparseable JSON, route/body mismatch); unsupported media types return `415 Unsupported Media Type` (RFC 9110 §15.5.16) via the `[Consumes]` attribute. Error responses follow the Problem Details format (RFC 9457).
|
|
|
|
### Removed
|
|
|
|
- Remove `## How to Release` section from `CHANGELOG.md`; capitalize release codenames in `##` version headers and reference links (#468)
|
|
|
|
---
|
|
|
|
## [2.1.1 - Ekaterinburg] - 2026-04-12
|
|
|
|
### Added
|
|
|
|
- Extract `test` job from `release` in CD pipeline so tests run in isolation
|
|
before any publish step; add `linux/arm64` to build platforms; add
|
|
`id-token: write` and `attestations: write` permissions to `release`; set
|
|
`provenance: mode=max` and attest the image digest with
|
|
`actions/attest-build-provenance@v4.1.0` (`push-to-registry: true`); add
|
|
`--no-merges` to the changelog `git log` command; add empty changelog guard;
|
|
normalize first-release message to `"No changes (first release)"` (#465)
|
|
|
|
- Add `adr/0013-testing-strategy.md` documenting the decision to implement the full test pyramid as a deliberate educational choice (#421)
|
|
- Add `test/.../Integration/PlayerWebApplicationTests.cs` with 14 HTTP-layer integration tests covering all player endpoints and `/health` via `WebApplicationFactory<Program>` backed by in-memory SQLite; includes `Utilities/TestAuthHandler.cs` to bypass `[Authorize]` on `GET /players/{id:Guid}`; expose `Program` to the test project via `public partial class Program {}` in `Program.cs`; add `Microsoft.AspNetCore.Mvc.Testing` to the test project (#421)
|
|
- Add `test/.../Integration/PlayerRepositoryTests.cs` with 9 integration tests covering `Repository<T>` (`GetAllAsync`, `FindByIdAsync`, `RemoveAsync`) and `PlayerRepository` (`FindBySquadNumberAsync`, `SquadNumberExistsAsync`); all tests use `DatabaseFakes.MigrateAsync()` on in-memory SQLite and are tagged `[Trait("Category", "Integration")]` (#461)
|
|
- Add `ValidateAsync_SquadNumberNegative_ReturnsValidationError` test to exercise the `GreaterThan(0)` rule with a negative value, which passes `NotEmpty()` but fails the greater-than rule (#427)
|
|
- Add `ValidateAsync_FirstNameEmptyInUpdateRuleSet_ReturnsValidationError` test to verify the `"Update"` rule set enforces structural field validation (#427)
|
|
- Add `adr/` directory with 12 Architecture Decision Records documenting architectural choices, technology decisions, and design trade-offs (#372)
|
|
- Add ADR index and template at `adr/README.md` (#372)
|
|
- Add Architecture Decisions section to `README.md` referencing the ADR index (#372)
|
|
- Add ADR guidance section to `CONTRIBUTING.md` (#372)
|
|
- Add ADR context loading instructions to `.github/copilot-instructions.md` (#372)
|
|
|
|
### Changed
|
|
|
|
- Call `.DisableRateLimiting()` on `MapHealthChecks("/health")` to enforce the exemption from the global rate limiter at the endpoint level, ensuring health check probes are never throttled (#451)
|
|
- Move `UseCors()` before `MapControllers()` in `Program.cs` to follow the standard ASP.NET Core middleware pipeline order; add an `Infrastructure` service registration section separating cross-cutting concerns (health checks, CORS, rate limiting, Swagger) from the `Controllers` section; add descriptive phrases to top-level section banners; add inline comments explaining the purpose and ordering rationale of each middleware; document the dev-only CORS policy intent in both `Program.cs` and `ServiceCollectionExtensions.AddCorsDefaultPolicy` (#451)
|
|
- Replace pre-seeded `storage/players-sqlite3.db` binary blob with EF Core `MigrateAsync()` at startup: schema and seed data are now applied automatically before the first request is served; `STORAGE_PATH` env var controls the database file path (Docker volume path in production, `AppContext.BaseDirectory/storage/` locally); the committed database file, `Dockerfile` db copy step, and `scripts/run-migrations-and-copy-database.sh` have been removed (#459)
|
|
- Recreate EF Core migrations using `HasData()` in `OnModelCreating`: three self-contained migrations (`InitialCreate` DDL, `SeedStarting11` DML, `SeedSubstitutes` DML) generated by EF Core with literal `InsertData` values — no migration calls application methods; `NormalizePlayerDataset` patch migration eliminated by folding corrections into seed data from the start (#459)
|
|
- Replace `DatabaseFakes.CreateTable()` (placeholder schema) and `DatabaseFakes.Seed()` (manual insert bypassing migrations) with `DatabaseFakes.MigrateAsync()`, which applies the full EF Core migration chain on in-memory SQLite (#459)
|
|
- Switch runtime base image from `mcr.microsoft.com/dotnet/aspnet:10.0` (Debian)
|
|
to `mcr.microsoft.com/dotnet/aspnet:10.0-alpine` (before: 113.4 MB →
|
|
after: 73.9 MB compressed; measured via `docker manifest inspect` and
|
|
`docker save | wc -c`); replace `apt-get` with `apk` and
|
|
`useradd`/`groupadd` with `adduser`/`addgroup` accordingly (#456)
|
|
- Refactor `scripts/entrypoint.sh`: add `log()` helper with timestamp prefix,
|
|
replace raw `echo` calls, and print API base URL on startup (#456)
|
|
- Rename `ValidateAsync_SquadNumber_BelongsToPlayerBeingUpdated_ReturnsNoErrors` to `ValidateAsync_SquadNumberBelongsToPlayerBeingUpdated_ReturnsNoErrors` to align with the 3-segment naming convention for service/validator tests (#427)
|
|
- Make CSharpier step in `/pre-commit` conditional (skip with a note if not installed), consistent with the Docker and CodeRabbit steps (#427)
|
|
- Add "Verify tag commit is reachable from master" step to CD workflow using `git merge-base --is-ancestor` before any build or publish steps (#439)
|
|
- Rename five controller test methods to normalize data-state vocabulary: `NonExisting` → `Nonexistent` for the POST 201 scenario, `NonExisting` → `Unknown` for the four 404-by-lookup scenarios (#452)
|
|
- Add XML doc `<remarks>` block to `PlayerFakes` documenting the three-term data-state vocabulary (`existing`, `nonexistent`, `unknown`) (#452)
|
|
|
|
### Fixed
|
|
|
|
- `GET /players` now returns `200 OK` with an empty list `[]` when no players exist, instead of `404 Not Found` (#425)
|
|
- AutoMapper `Player → PlayerResponseModel` profile now explicitly ignores the `Id` source member via `ForSourceMember`, making the exclusion intentional rather than implicit (#425)
|
|
|
|
### Removed
|
|
|
|
---
|
|
|
|
## [2.1.0 - Dusseldorf] - 2026-03-29
|
|
|
|
### Added
|
|
|
|
- Add SonarCloud configuration via `.sonarcloud.properties` with explicit CPD exclusions for migrations, generated code, test files, and structurally repetitive production files (#426, #435)
|
|
- Add bug report issue template (`.github/ISSUE_TEMPLATE/bug_report.md`) (#426)
|
|
|
|
### Changed
|
|
|
|
- Normalize player dataset: add Lo Celso (squad 27), correct Fernández/Mac Allister/Messi team data, replace random UUIDs with deterministic UUID v5 values (#435)
|
|
- Align CRUD test fixtures: Lo Celso (squad 27) for Create and Delete, Messi (squad 10) for Retrieve, Damián Martínez (squad 23) for Update (#435)
|
|
- Bump `codecov/codecov-action` from 5.5.2 to 5.5.3 (#423)
|
|
|
|
### Fixed
|
|
|
|
- Scope `BeUniqueSquadNumber` validator to `"Create"` rule set to prevent false rejection of valid `PUT` requests (#424)
|
|
|
|
---
|
|
|
|
## [2.0.0 - Centenario] - 2026-03-18
|
|
|
|
### Changed
|
|
|
|
- Refactor error responses to use RFC 7807 Problem Details (#418)
|
|
- Add `/squadNumber/` path segment to PUT and DELETE routes — **breaking change** (#418)
|
|
- Extract `NotFoundTitle` constant and remove redundant null-conditional operator (#418)
|
|
- Rename test methods to follow Microsoft .NET naming standard (#396)
|
|
- Upgrade AutoMapper from 14.x to 16.1.1 (#414) — see Security section
|
|
- Bump FluentAssertions from 8.8.0 to 8.9.0 (#417)
|
|
- Bump coverlet.collector from 8.0.0 to 8.0.1 (#419)
|
|
- Bump softprops/action-gh-release from 2.6.0 to 2.6.1 (#416)
|
|
|
|
### Fixed
|
|
|
|
- Add squad number mismatch guard in `PutAsync` and update README (#418)
|
|
- Strengthen test assertions for Problem Details responses (#418)
|
|
- Fix broken 201 assertion in controller test for `Post_Players_NonExisting` (#396)
|
|
- Add missing edge case tests for `UpdateAsync`, `DeleteAsync`, and
|
|
`DateOfBirth` boundary validation (#396)
|
|
|
|
### Security
|
|
|
|
- Sanitize player data before logging to prevent log forging
|
|
- Upgrade AutoMapper from 14.x to 16.1.1 to resolve high-severity security vulnerability GHSA-rvv3-g6hj-g44x (#414)
|
|
|
|
---
|
|
|
|
## [1.1.0 - Bernabeu] - 2026-02-09
|
|
|
|
### Changed
|
|
|
|
- Upgrade to .NET 10 LTS from .NET 8 (#368)
|
|
- Update Microsoft.AspNetCore.OpenApi to 10.0.0
|
|
- Update Microsoft.EntityFrameworkCore.Sqlite to 10.0.0
|
|
- Update Microsoft.EntityFrameworkCore.Design to 10.0.0
|
|
- Update Microsoft.VisualStudio.Web.CodeGeneration.Design to 10.0.0
|
|
- Update Docker images to .NET 10 SDK and runtime (now based on Ubuntu 24.04 LTS instead of Debian 12)
|
|
- Update Dockerfile user creation commands for Ubuntu compatibility (`groupadd`/`useradd` instead of `adduser`)
|
|
- Update CI/CD pipelines to use .NET 10 SDK
|
|
- Token efficiency strategy for Copilot/AI agents with optimized instruction loading and improved token counting script (#364)
|
|
- Bump Swashbuckle.AspNetCore from 10.1.0 to 10.1.2
|
|
- Bump docker/login-action from 3.6.0 to 3.7.0
|
|
- Bump softprops/action-gh-release from 2.2.0 to 2.5.0
|
|
- Bump actions/checkout from 6.0.1 to 6.0.2
|
|
|
|
---
|
|
|
|
## [1.0.0 - Azteca] - 2026-01-22
|
|
|
|
Initial release. See [README.md](README.md) for complete feature list and documentation.
|
|
|
|
---
|
|
|
|
<!-- Template for new releases:
|
|
|
|
## [X.Y.Z - STADIUM_NAME] - YYYY-MM-DD
|
|
|
|
### Added
|
|
- New features
|
|
|
|
### Changed
|
|
- Changes in existing functionality
|
|
|
|
### Deprecated
|
|
- Soon-to-be removed features
|
|
|
|
### Removed
|
|
- Removed features
|
|
|
|
### Fixed
|
|
- Bug fixes
|
|
|
|
### Security
|
|
- Security vulnerability fixes
|
|
|
|
-->
|
|
|
|
---
|
|
|
|
[unreleased]: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/compare/v2.1.2-frankfurt...HEAD
|
|
[2.1.2 - Frankfurt]: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/compare/v2.1.1-ekaterinburg...v2.1.2-frankfurt
|
|
[2.1.1 - Ekaterinburg]: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/compare/v2.1.0-dusseldorf...v2.1.1-ekaterinburg
|
|
[2.1.0 - Dusseldorf]: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/compare/v2.0.0-centenario...v2.1.0-dusseldorf
|
|
[2.0.0 - Centenario]: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/compare/v1.1.0-bernabeu...v2.0.0-centenario
|
|
[1.1.0 - Bernabeu]: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/compare/v1.0.0-azteca...v1.1.0-bernabeu
|
|
[1.0.0 - Azteca]: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/releases/tag/v1.0.0-azteca
|