mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-15 10:04:44 +00:00
Update docs formatting
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
# User Authentication Flow — Error Handling
|
||||
|
||||
Global exception mapping performed by `API.Core`'s `GlobalExceptionFilter`. Applies uniformly across every authentication endpoint (registration, login, refresh, confirm, resend, update-username/email/password/profile, delete-account) — see the per-flow diagrams for where each exception type is thrown.
|
||||
Global exception mapping performed by `API.Core`'s `GlobalExceptionFilter`.
|
||||
Applies uniformly across every authentication endpoint (registration, login,
|
||||
refresh, confirm, resend, update-username/email/password/profile,
|
||||
delete-account) — see the per-flow diagrams for where each exception type is
|
||||
thrown.
|
||||
|
||||
```mermaid
|
||||
--8<-- "web/diagrams/auth/error-handling.mmd"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Database Schema
|
||||
|
||||
Every table also has a `RowVersion ROWVERSION` column (optimistic concurrency), omitted below for brevity. Tables marked `(*)` have no repository/feature slice yet.
|
||||
Every table also has a `RowVersion ROWVERSION` column (optimistic concurrency),
|
||||
omitted below for brevity. Tables marked `(*)` have no repository/feature slice
|
||||
yet.
|
||||
|
||||
```mermaid
|
||||
--8<-- "web/diagrams/database-schema.mmd"
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
|
||||
## Notes
|
||||
|
||||
- **Dev network** (`devnet`, bridge): internal DNS resolves service names such as `sqlserver` and `api.core`. Volumes: `sqlserverdata-dev`, `nuget-cache-dev`, `seaweedfsdata-dev`. Startup order: SQL Server (health check) → migrations (run-once) → seed (run-once, depends on `seaweedfs`) → API (long-running, depends on seed).
|
||||
- **Test network** (`testnet`, bridge): all test components isolated; fresh DB instance each run (`CLEAR_DATABASE=true`, ephemeral `sqlserverdata-test`/`seaweedfsdata-test` volumes). `api.specs`, `unit.tests`, and `frontend.tests` all run as separate containers, results aggregated.
|
||||
- **Prod network** (`prodnet`, bridge): isolated from dev/test networks. Volumes: `sqlserverdata-prod`, `nuget-cache-prod`. No seed step in production.
|
||||
- **Database-only environment**: same devnet volumes/images as `docker-compose.dev.yaml`, minus `api.core`, `frontend`, and `mailpit` — for working against the database (and object storage, since `seaweedfs` is still included) without running the API or website.
|
||||
- **Minimal environment**: database + migrations + seed + `seaweedfs` + mailpit, no API or frontend container — for frontend development against an `API.Core` process run outside Docker.
|
||||
- `unit.tests` builds `Dockerfile.tests`, which restores/builds against `Biergarten.API.slnx` then runs `dotnet test` for every `Features/*.Tests` project in turn (`Features.Users.Tests`, `Features.Breweries.Tests`, `Features.Emails.Tests`, `Features.PhotoUpload.Tests`), mocking each handler's repository/service dependencies with Moq — no real database needed.
|
||||
- `.trx` results are readable by Visual Studio, Azure DevOps, and GitHub Actions.
|
||||
| Environment | Details |
|
||||
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Dev network** (`devnet`, bridge) | Internal DNS resolves service names such as `sqlserver` and `api.core`. Volumes: `sqlserverdata-dev`, `nuget-cache-dev`, `seaweedfsdata-dev`. Startup order: SQL Server (health check) → migrations (run-once) → seed (run-once, depends on `seaweedfs`) → API (long-running, depends on seed). |
|
||||
| **Test network** (`testnet`, bridge) | All test components are isolated; fresh DB instance each run (`CLEAR_DATABASE=true`, ephemeral `sqlserverdata-test` / `seaweedfsdata-test` volumes). `api.specs`, `unit.tests`, and `frontend.tests` all run as separate containers; results are aggregated. |
|
||||
| **Prod network** (`prodnet`, bridge) | Isolated from dev/test networks. Volumes: `sqlserverdata-prod`, `nuget-cache-prod`. No seed step in production. |
|
||||
| **Database-only environment** | Same devnet volumes/images as `docker-compose.dev.yaml`, minus `api.core`, `frontend`, and `mailpit` — for working against the database (and object storage, since `seaweedfs` is still included) without running the API or website. |
|
||||
| **Minimal environment** | Database + migrations + seed + `seaweedfs` + mailpit, no API or frontend container — for frontend development against an `API.Core` process run outside Docker. |
|
||||
| `unit.tests` | Builds `Dockerfile.tests`, which restores/builds against `Biergarten.API.slnx` and then runs `dotnet test` for every `Features/*.Tests` project in turn (`Features.Users.Tests`, `Features.Breweries.Tests`, `Features.Emails.Tests`, `Features.PhotoUpload.Tests`), mocking each handler's repository/service dependencies with Moq — no real database needed. |
|
||||
| `.trx` results | Readable by Visual Studio, Azure DevOps, and GitHub Actions. |
|
||||
|
||||
@@ -17,12 +17,12 @@ doesn't wire up any slice; it applies schema directly.
|
||||
## Project reference dependencies
|
||||
|
||||
Solid arrows are compile-time project references. Dashed arrows are the two
|
||||
places slices talk to each other without a direct reference: the email
|
||||
MediatR contract routed through `Shared.Application`, and the one place that
|
||||
pattern is broken outright. Every DB-backed slice depends on the same three
|
||||
foundation projects (`Shared.Contracts`, `Domain.Entities`,
|
||||
`Database.Connection`) — drawn as one box instead of fifteen separate arrows;
|
||||
see the notes for what else each of those foundation projects pulls in.
|
||||
places slices talk to each other without a direct reference: the email MediatR
|
||||
contract routed through `Shared.Application`, and the one place that pattern is
|
||||
broken outright. Every DB-backed slice depends on the same three foundation
|
||||
projects (`Shared.Contracts`, `Domain.Entities`, `Database.Connection`) — drawn
|
||||
as one box instead of fifteen separate arrows; see the notes for what else each
|
||||
of those foundation projects pulls in.
|
||||
|
||||
```mermaid
|
||||
--8<-- "web/diagrams/vertical-slice/project-references.mmd"
|
||||
@@ -33,32 +33,49 @@ see the notes for what else each of those foundation projects pulls in.
|
||||
- **API.Core**: Program.cs wiring only
|
||||
- MediatR + `AddApplicationPart` per HTTP-exposed `Features.*` assembly
|
||||
- Swagger/OpenAPI, health checks, JWT auth middleware, global exception filter
|
||||
- Only `Features.Users` and `Features.Breweries` get `AddApplicationPart` (controllers)
|
||||
- `Features.PhotoUpload` and `Features.Emails` scanned for MediatR handlers only
|
||||
- `Features.Locations` and `Features.Beers` not referenced by `API.Core` at all
|
||||
- Only `Features.Users` and `Features.Breweries` get `AddApplicationPart`
|
||||
(controllers)
|
||||
- `Features.PhotoUpload` and `Features.Emails` scanned for MediatR handlers
|
||||
only
|
||||
- `Features.Locations` and `Features.Beers` not referenced by `API.Core` at
|
||||
all
|
||||
|
||||
- **Feature slices**: each owns its own controller (where present), commands/queries + handlers, validators, and Dapper repository
|
||||
- `Features.Users` covers auth (`Commands/Authentication`), account management (`Commands/Account`), and profile/avatar (`Commands/Profile`)
|
||||
- internally namespaced `Features.Auth`, despite project name `Features.Users`
|
||||
- `Features.Emails` and `Features.PhotoUpload` have no controller — invoked only via MediatR commands sent from other slices
|
||||
- `Features.Locations` has no controller; one MediatR handler (`GetOrCreateCityHandler`) registered by `Database.Seed` only — `API.Core` never scans it
|
||||
- `Features.Beers` is scaffolded (project + references only, no source files yet)
|
||||
- **Feature slices**: each owns its own controller (where present),
|
||||
commands/queries + handlers, validators, and Dapper repository
|
||||
- `Features.Users` covers auth (`Commands/Authentication`), account management
|
||||
(`Commands/Account`), and profile/avatar (`Commands/Profile`)
|
||||
- internally namespaced `Features.Auth`, despite project name
|
||||
`Features.Users`
|
||||
- `Features.Emails` and `Features.PhotoUpload` have no controller — invoked
|
||||
only via MediatR commands sent from other slices
|
||||
- `Features.Locations` has no controller; one MediatR handler
|
||||
(`GetOrCreateCityHandler`) registered by `Database.Seed` only — `API.Core`
|
||||
never scans it
|
||||
- `Features.Beers` is scaffolded (project + references only, no source files
|
||||
yet)
|
||||
|
||||
- **The one exception to slice isolation**: `Features.Users` takes a direct project reference to `Features.PhotoUpload`
|
||||
- **The one exception to slice isolation**: `Features.Users` takes a direct
|
||||
project reference to `Features.PhotoUpload`
|
||||
- sends its `UploadPhotoCommand` via MediatR from `UploadAvatarHandler`
|
||||
- unlike the email flow, the command type lives in the target slice itself, not in `Shared.Application`
|
||||
- unlike the email flow, the command type lives in the target slice itself,
|
||||
not in `Shared.Application`
|
||||
|
||||
- **Shared.Application**:
|
||||
- `ValidationBehavior` (MediatR pipeline)
|
||||
- Cross-slice email commands (`SendRegistrationEmailCommand`, `SendResendConfirmationEmailCommand`)
|
||||
- Cross-slice email commands (`SendRegistrationEmailCommand`,
|
||||
`SendResendConfirmationEmailCommand`)
|
||||
- MediatR command contract (not project reference)
|
||||
- Every slice (including `Features.Emails`) references it for the pipeline behavior alone
|
||||
- Every slice (including `Features.Emails`) references it for the pipeline
|
||||
behavior alone
|
||||
|
||||
- **Domain.Entities**:
|
||||
- `UserAccount`, `UserCredential`, `UserVerification`, `UserProfile`, `UserAvatar`
|
||||
- `UserAccount`, `UserCredential`, `UserVerification`, `UserProfile`,
|
||||
`UserAvatar`
|
||||
- `BreweryPost`, `BreweryPostLocation`
|
||||
- `City`, `StateProvince`, `Country`
|
||||
- `BeerPost`, `BeerStyle`, `Photo` (schema tables exist for `BeerPost`/`BeerStyle`; no repository yet since `Features.Beers` has no code)
|
||||
- `BeerPost`, `BeerStyle`, `Photo` (schema tables exist for
|
||||
`BeerPost`/`BeerStyle`; no repository yet since `Features.Beers` has no
|
||||
code)
|
||||
|
||||
- **Database.Connection**: the shared connection-factory project
|
||||
- each slice's own repository issues inline SQL via Dapper against it
|
||||
@@ -68,7 +85,8 @@ see the notes for what else each of those foundation projects pulls in.
|
||||
- **Database.Migrations**: separate console app
|
||||
- `schema.dbml` + SQL scripts
|
||||
- applies DDL directly
|
||||
- distinct from `Database.Seed`, which loads data through the feature slices' own DI extensions
|
||||
- distinct from `Database.Seed`, which loads data through the feature slices'
|
||||
own DI extensions
|
||||
|
||||
- **Database.Seed**:
|
||||
- calls each slice's `AddFeatures*()` DI extension directly
|
||||
@@ -76,6 +94,10 @@ see the notes for what else each of those foundation projects pulls in.
|
||||
- no API host, no shared pipeline with `API.Core`
|
||||
|
||||
- **Omitted from the diagram**:
|
||||
- `Domain.Exceptions` (referenced by nearly every project directly, including all of `Shared.Contracts`, `Infrastructure.Jwt`, and each feature slice)
|
||||
- `Infrastructure.Configuration` (the shared options-binding project referenced by `Database.Connection`, `Infrastructure.Email`, `Infrastructure.FileUpload`, and `Features.Emails` directly)
|
||||
- both are plumbing-level dependencies of nearly everything above, and drawing them would just add a second copy of the same fan-in
|
||||
- `Domain.Exceptions` (referenced by nearly every project directly, including
|
||||
all of `Shared.Contracts`, `Infrastructure.Jwt`, and each feature slice)
|
||||
- `Infrastructure.Configuration` (the shared options-binding project
|
||||
referenced by `Database.Connection`, `Infrastructure.Email`,
|
||||
`Infrastructure.FileUpload`, and `Features.Emails` directly)
|
||||
- both are plumbing-level dependencies of nearly everything above, and drawing
|
||||
them would just add a second copy of the same fan-in
|
||||
|
||||
Reference in New Issue
Block a user