Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
1d5ac07
build: enforce explicit global usings
weslleymurdock Aug 16, 2026
b40682b
build: configure application dependencies
weslleymurdock Aug 16, 2026
c758ae2
build: configure identity infrastructure dependencies
weslleymurdock Aug 16, 2026
e45e31e
build: configure composition dependencies
weslleymurdock Aug 16, 2026
9ed5d9e
build: enforce explicit presentation imports
weslleymurdock Aug 16, 2026
3195f41
build: add domain global usings
weslleymurdock Aug 16, 2026
da0c339
build: add application global usings
weslleymurdock Aug 16, 2026
6f94a32
feat: add soft deletable domain contract
weslleymurdock Aug 16, 2026
547baef
feat: define identity application contracts
weslleymurdock Aug 16, 2026
383acf8
x
weslleymurdock Aug 16, 2026
3a70b44
feat: define identity service abstraction
weslleymurdock Aug 16, 2026
eab141e
build: centralize application imports
weslleymurdock Aug 16, 2026
c40a636
build: enforce file scoped application source
weslleymurdock Aug 16, 2026
0389ab0
feat: add identity commands and queries
weslleymurdock Aug 16, 2026
47dcd45
feat: add identity fluent validators
weslleymurdock Aug 16, 2026
1db2acb
build: expose application feature contracts globally
weslleymurdock Aug 16, 2026
e0cf0ca
feat: add identity mediator handlers
weslleymurdock Aug 16, 2026
3cdaada
feat: add mediator validation pipeline middleware
weslleymurdock Aug 16, 2026
3ead276
build: expose application pipeline contracts globally
weslleymurdock Aug 16, 2026
f2078f7
build: add infrastructure global usings
weslleymurdock Aug 16, 2026
fcad45a
feat: define jwt configuration contract
weslleymurdock Aug 16, 2026
8878cac
feat: define identity token and email abstractions
weslleymurdock Aug 16, 2026
e3a999d
build: expose security primitives globally
weslleymurdock Aug 16, 2026
969bc5f
feat: add identity soft deletable dbcontext
weslleymurdock Aug 16, 2026
a479d71
build: add infrastructure expression imports
weslleymurdock Aug 16, 2026
215f5cf
feat: implement manual jwt generation validation and revocation
weslleymurdock Aug 16, 2026
f6e6b52
feat: implement identity service over usermanager and rolemanager
weslleymurdock Aug 16, 2026
223bd7e
build: add composition global usings
weslleymurdock Aug 16, 2026
a2e81f0
build: add fluentvalidation dependency injection extensions
weslleymurdock Aug 16, 2026
fb04bf2
build: centralize fluentvalidation registration imports
weslleymurdock Aug 16, 2026
fc782f0
feat: add complete application composition and http pipeline setup
weslleymurdock Aug 16, 2026
d6e5993
build: centralize composition feature imports
weslleymurdock Aug 16, 2026
7155156
feat: configure identity database and jwt settings
weslleymurdock Aug 16, 2026
3f14dc5
build: add presentation global usings
weslleymurdock Aug 16, 2026
5c945a2
feat: add manual identity api endpoints
weslleymurdock Aug 16, 2026
3095610
feat: add setup enforcement endpoint
weslleymurdock Aug 16, 2026
007bb29
refactor: route startup through composition root
weslleymurdock Aug 16, 2026
f76b90a
build: expose composition root to presentation
weslleymurdock Aug 16, 2026
b5370ac
chore: remove template class
weslleymurdock Aug 16, 2026
5b6a63b
chore: remove template class
weslleymurdock Aug 16, 2026
a02b63a
chore: remove template class
weslleymurdock Aug 16, 2026
1eb2f37
chore: remove template class
weslleymurdock Aug 16, 2026
f4826fc
test: add xunit v3 foundation project
weslleymurdock Aug 16, 2026
fe3b1bb
test: add unit test global usings
weslleymurdock Aug 16, 2026
2a9d42b
test: cover identity lifecycle and token revocation
weslleymurdock Aug 16, 2026
a43e394
test: cover identity validation rules
weslleymurdock Aug 16, 2026
6f6603c
test: cover jwt generation validation and revocation primitives
weslleymurdock Aug 16, 2026
0b77ab4
test: cover mediator validation middleware
weslleymurdock Aug 16, 2026
6937c0b
docs: enforce unit testing and coverage standards
weslleymurdock Aug 16, 2026
84e2eba
test: cover mediator identity handlers
weslleymurdock Aug 16, 2026
95d6bb5
build: expose mediator context to tests
weslleymurdock Aug 16, 2026
3c11af7
test: cover identity two factor lifecycle
weslleymurdock Aug 16, 2026
c5b8118
test: cover identity failure and enumeration-safe paths
weslleymurdock Aug 16, 2026
b110d8e
ci: add stage 01 build and coverage pipeline
weslleymurdock Aug 16, 2026
80d0cca
build: add unit tests to solution
weslleymurdock Aug 16, 2026
17ef06e
refactor: define claim based administrator policy
weslleymurdock Aug 16, 2026
f37af27
refactor: enforce administrator claim policy
weslleymurdock Aug 16, 2026
0df1951
fix: remove unused domain global imports
weslleymurdock Aug 16, 2026
d49cd15
fix: align application responses with Mediator.Net contracts
weslleymurdock Aug 16, 2026
c4744c6
fix: use Mediator.Net request contracts
weslleymurdock Aug 16, 2026
65cba7c
refactor: add Mediator.Net response envelope
weslleymurdock Aug 16, 2026
86cce89
fix: make mediator handlers return valid response contracts
weslleymurdock Aug 16, 2026
10c7016
fix: remove invalid fluentvalidation namespace import
weslleymurdock Aug 16, 2026
c126939
fix: adapt controllers to mediator response envelopes
weslleymurdock Aug 16, 2026
c017279
fix: update handler tests for mediator response envelopes
weslleymurdock Aug 16, 2026
c14194a
fix: remove unused application global imports
weslleymurdock Aug 16, 2026
0977d29
fix: add identity sign in manager dependency
weslleymurdock Aug 16, 2026
8bd6d25
fix: reference aspnet identity framework for signin manager
weslleymurdock Aug 16, 2026
fdfd74d
fix: remove unused infrastructure crypto import
weslleymurdock Aug 16, 2026
34deaa7
chore: remove framework package duplication
weslleymurdock Aug 16, 2026
640154a
fix: minimize composition global imports
weslleymurdock Aug 16, 2026
68f7506
fix: minimize presentation global imports
weslleymurdock Aug 16, 2026
9efeba0
fix: remove unused test global imports
weslleymurdock Aug 16, 2026
eb006d9
fix: pin established coverlet collector release
weslleymurdock Aug 16, 2026
f522c89
fix: remove unused hosting global import
weslleymurdock Aug 16, 2026
4cf1a90
fix: remove unused signin manager from unit test fixture
weslleymurdock Aug 16, 2026
ca153a3
fix: build
weslleymurdock Aug 16, 2026
f3e80c3
fix: run tests
weslleymurdock Aug 16, 2026
3bf0b3a
ci: make test reports resilient to test failures
weslleymurdock Aug 16, 2026
dc7b272
ci: resolve coverage from test result subdirectories
weslleymurdock Aug 16, 2026
6d8db50
fix: remove early exit on coverage enforment step
weslleymurdock Aug 16, 2026
58466e5
fix: add test execution report
weslleymurdock Aug 16, 2026
6aa3e24
fix : upload of test-results to summary using action
weslleymurdock Aug 16, 2026
af987ac
fix : fix publish test summary
weslleymurdock Aug 16, 2026
8bc1d0b
fix: add missing xunit visual studio runner package
weslleymurdock Aug 16, 2026
8c80efb
fix: add missing package version
weslleymurdock Aug 16, 2026
9b129e1
fix: identityfixture and tests
weslleymurdock Aug 16, 2026
adfa8bd
fix: make JWT token type explicit
weslleymurdock Aug 16, 2026
cc36ed1
fix: use explicit JWT token type claim
weslleymurdock Aug 16, 2026
18d4164
fix: accept explicit refresh token type
weslleymurdock Aug 16, 2026
697ac87
test: add cryptographic helpers for identity coverage
weslleymurdock Aug 16, 2026
54e1d27
test: cover two-factor success and failure paths
weslleymurdock Aug 16, 2026
0719f84
test: cover identity service branches
weslleymurdock Aug 16, 2026
ca51e21
test: expose role manager in identity fixture
weslleymurdock Aug 16, 2026
37e97d7
test: cover soft delete persistence behavior
weslleymurdock Aug 16, 2026
68592e7
test: cover JWT invalid input and revocation paths
weslleymurdock Aug 16, 2026
1b17e2e
fix: add missing using, also removed unnecessary usingsin globalusings
weslleymurdock Aug 16, 2026
1391e19
test: require confirmed accounts in identity fixture
weslleymurdock Aug 16, 2026
e18fd8a
test: exercise confirmed email and configured two-factor login paths
weslleymurdock Aug 16, 2026
18f30bb
test: configure two-factor setup through identity service contract
weslleymurdock Aug 16, 2026
72b0c82
test: generate authenticator setup code from shared key
weslleymurdock Aug 16, 2026
efffd7e
style: require complete XML documentation for public APIs
weslleymurdock Aug 16, 2026
1aeb57b
docs: define XML documentation requirements
weslleymurdock Aug 16, 2026
9d3c47d
fix: build
weslleymurdock Aug 16, 2026
171e87e
fix: enforce two-factor authentication during jwt login
weslleymurdock Aug 16, 2026
30041b6
build: defer XML documentation to release target
weslleymurdock Aug 16, 2026
fc46ad0
build: generate release XML documentation in docs-gen
weslleymurdock Aug 16, 2026
af6c2d0
build: resolve XML documentation output from repository root
weslleymurdock Aug 16, 2026
2850bfb
docs: document identity response contracts
weslleymurdock Aug 16, 2026
147a7d2
docs: document identity service abstractions
weslleymurdock Aug 16, 2026
b322cb0
docs: document JWT options
weslleymurdock Aug 16, 2026
0944bc0
docs: document identity application contract
weslleymurdock Aug 16, 2026
fae2100
docs: document identity request contracts
weslleymurdock Aug 16, 2026
91f40a7
docs: document identity validators
weslleymurdock Aug 16, 2026
6f2cc5a
docs: document identity handlers
weslleymurdock Aug 16, 2026
2119dad
docs: document validation pipeline
weslleymurdock Aug 16, 2026
dd1b93e
docs: document soft-delete contract
weslleymurdock Aug 16, 2026
3978621
docs: document JWT token infrastructure
weslleymurdock Aug 16, 2026
7d2ad3e
docs: document application composition API
weslleymurdock Aug 16, 2026
e092cfb
docs: document identity controller API
weslleymurdock Aug 16, 2026
41a2d63
docs: document setup controller API
weslleymurdock Aug 16, 2026
d5b0243
docs: document identity failure-path tests
weslleymurdock Aug 16, 2026
625eefb
docs: document identity handler tests
weslleymurdock Aug 16, 2026
0dffced
docs: document identity service tests
weslleymurdock Aug 16, 2026
5948aaa
docs: document two-factor tests
weslleymurdock Aug 16, 2026
5a3fc4d
docs: document identity validator tests
weslleymurdock Aug 16, 2026
b31972e
docs: document JWT token tests
weslleymurdock Aug 16, 2026
4fc6475
docs: document persistence tests
weslleymurdock Aug 16, 2026
5289efd
docs: document validation middleware tests
weslleymurdock Aug 16, 2026
77b944e
docs: add agent instructions
weslleymurdock Aug 16, 2026
5b79163
docs: document solution architecture
weslleymurdock Aug 16, 2026
6cceba4
docs: add C# coding style
weslleymurdock Aug 16, 2026
30d7066
docs: add project responsibilities guide
weslleymurdock Aug 16, 2026
09c1300
minor refactor
weslleymurdock Aug 16, 2026
4ce00d0
major refactor
weslleymurdock Aug 18, 2026
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
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ csharp_prefer_system_threading_lock = true:suggestion
# IDE0005 also keeps the centralized import set free of unused directives.
dotnet_diagnostic.IDE0005.severity = error

# Public API documentation is mandatory. Every public member must document its
# summary, parameters, generic parameters, exceptions, and relevant remarks.
dotnet_diagnostic.CS1591.severity = warning
dotnet_diagnostic.CS1572.severity = warning
dotnet_diagnostic.CS1573.severity = warning
dotnet_diagnostic.CS1712.severity = warning
dotnet_diagnostic.CS1574.severity = warning
dotnet_diagnostic.CS1587.severity = warning
dotnet_diagnostic.CS1591.severity = warning

[*.csproj]
dotnet_diagnostic.IDE0055.severity = error

Expand Down
139 changes: 139 additions & 0 deletions .github/workflows/CI-CT-CD.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
name: CI - CT - CD

on:
push:
branches: [main]
tags: [v*]
pull_request:
types: [opened, synchronize]

permissions:
contents: read

jobs:
build:
name: Continuous Integration
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.*
- name: Restore
run: dotnet restore SPInvisivel.slnx
- name: Build
run: dotnet build SPInvisivel.slnx --configuration Release --no-restore

tests:
name: Continuous Testing
runs-on: ubuntu-latest
needs: build
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.*
- name: Restore
run: dotnet restore ${{ github.workspace }}/tests/InvisibleSP.UnitTests/InvisibleSP.UnitTests.csproj
- name: Install ReportGenerator
run: dotnet tool install --global dotnet-reportgenerator-globaltool --version 5.5.11

- name: Test with Coverlet
id: test
shell: pwsh
continue-on-error: true
run: |
New-Item -ItemType Directory -Force -Path artifacts/test-results | Out-Null
$outputFile = Join-Path $env:GITHUB_WORKSPACE 'artifacts/test-output.txt'
& dotnet test $env:GITHUB_WORKSPACE/tests/InvisibleSP.UnitTests/InvisibleSP.UnitTests.csproj `
--configuration Release `
--no-restore `
--collect:"XPlat Code Coverage" `
--results-directory $env:GITHUB_WORKSPACE/artifacts/test-results `
--logger "trx;LogFileName=test-results.trx" 2>&1 | Tee-Object -FilePath $outputFile
$exitCode = $LASTEXITCODE
"dotnet test exit code: $exitCode" | Add-Content -Path $outputFile
"TEST_EXIT_CODE=$exitCode" | Out-File -FilePath artifacts/test-exit-code.txt -Encoding utf8

- name: Publish Test Summary
uses: dorny/test-reporter@v1
if: always()
with:
name: 'Continuous Test Results'
path: './artifacts/test-results/*.trx'
reporter: 'dotnet-trx'

- name: Generate coverage report
if: always()
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path artifacts/coverage | Out-Null
$coverageFiles = @(Get-ChildItem -Path artifacts/test-results -Filter coverage.cobertura.xml -Recurse -File -ErrorAction SilentlyContinue)
if ($coverageFiles.Count -gt 0) {
reportgenerator -reports:"artifacts/test-results/**/coverage.cobertura.xml" -targetdir:"artifacts/coverage" -reporttypes:"MarkdownSummary;Cobertura"
} else {
"# Coverage report unavailable`n`nCoverlet did not produce a coverage XML file." | Out-File artifacts/coverage/Summary.md -Encoding utf8
}

- name: Enforce 80 percent line and branch coverage
if: always()
shell: pwsh
run: |
$coverageFiles = @(Get-ChildItem -Path "$env:GITHUB_WORKSPACE/artifacts/test-results" -Directory -ErrorAction SilentlyContinue | ForEach-Object {
Get-ChildItem -Path $_.FullName -Filter coverage.cobertura.xml -File -ErrorAction SilentlyContinue
})

if ($coverageFiles.Count -eq 0) {
"## Coverage gate`n`nNo Coverlet XML was found under the test-results GUID subdirectories." | Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
return
}

$coverageFile = $coverageFiles | Select-Object -First 1
[xml]$coverage = Get-Content $coverageFile.FullName
$lineRate = [double]$coverage.coverage.'line-rate' * 100
$branchRate = [double]$coverage.coverage.'branch-rate' * 100

if ($lineRate -ge 80 -and $branchRate -ge 80) {
"## ✅ **Coverage threshold passed!**`n`n### Achieved `n**Line $([math]::Round($lineRate, 2))%**`n**Branch $([math]::Round($branchRate, 2))%**" | Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
} else {
"## ❌ Coverage threshold failed`n`nRequired: line >= 80% and branch >= 80%. Actual: **line $([math]::Round($lineRate, 2))%**, **branch $([math]::Round($branchRate, 2))%**." | Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
}

@"

## Coverage gate

| Metric | Result | Minimum |
| --- | ---: | ---: |
| Line coverage | $([math]::Round($lineRate, 2))% | 80% |
| Branch coverage | $([math]::Round($branchRate, 2))% | 80% |

"@ | Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8

- name: Append test execution report
if: always()
shell: pwsh
run: if (Test-Path artifacts/coverage/Summary.md) { Get-Content artifacts/coverage/Summary.md | Add-Content $env:GITHUB_STEP_SUMMARY } else { Add-Content $env:GITHUB_STEP_SUMMARY 'Coverage report was not generated.' }

- name: Upload test and coverage reports
if: always()
uses: actions/upload-artifact@v7
with:
name: Continuous-Testing-Reports
path: artifacts/
if-no-files-found: warn

- name: Fail if tests failed
if: always()
shell: pwsh
run: |
if (Test-Path artifacts/test-exit-code.txt) {
$exitCode = [int](Get-Content artifacts/test-exit-code.txt -Raw).Replace('TEST_EXIT_CODE=', '').Trim()
if ($exitCode -ne 0) { Write-Error "dotnet test failed with exit code $exitCode." }
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -485,3 +485,5 @@ $RECYCLE.BIN/

# Vim temporary swap files
*.swp
/workload-install.ps1
/workload-install.ps1
36 changes: 32 additions & 4 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,28 @@ The feature name should represent the aggregate/use-case boundary. `Common` is a
- Use explicit `using` aliases in `GlobalUsings.cs` when namespaces expose ambiguous type names.
- Prefer modern C#/.NET 10 language and BCL APIs when they improve correctness, clarity, performance, or maintainability.
- Prefer async APIs for I/O-bound operations and propagate `CancellationToken` through application and infrastructure boundaries.
- Avoid service-locator patterns and direct `IServiceProvider` resolution in application/domain code.
- Keep public APIs documented when they are part of a reusable abstraction or library boundary.
- Avoid service-locator patterns and direct `IServiceProvider` resolution in application/domain code except for isolated infrastructure adapters whose responsibility is explicitly to bridge a third-party pipeline into the application abstraction.
- Do not introduce nullable suppression (`!`) without a concrete invariant that makes the value safe.

## XML documentation

Every public type and public member in every C# project, including test projects, must have XML documentation.

Documentation is part of the public API contract and must contain, when applicable:

- `<summary>` — what the type/member does and its responsibility.
- `<typeparam>` — every generic type parameter.
- `<param>` — every method, constructor, indexer, or delegate parameter.
- `<returns>` — the returned value for methods/functions that return a value or task result.
- `<exception>` — every exception that callers can reasonably encounter as part of the documented contract.
- `<remarks>` — important invariants, lifecycle requirements, security considerations, side effects, threading behavior, or usage constraints that are not appropriate for the summary.

Use `<inheritdoc />` when the inherited/interface documentation completely describes the public member and no additional contract information is necessary. Do not use empty documentation merely to silence an analyzer.

XML documentation must describe the behavior of the implementation rather than restating the member name. Public API changes must update their documentation in the same change.

The compiler XML documentation diagnostics are enabled in `.editorconfig`; malformed or incomplete parameter/type-parameter documentation must not be introduced.

## Dependency injection

- Register dependencies in `InvisibleSP.Composition`.
Expand All @@ -112,10 +130,20 @@ A handler should orchestrate a use case rather than become a persistence abstrac
- Avoid anemic domain models when business invariants can naturally be expressed in the domain layer.
- Domain events represent meaningful domain occurrences; application/infrastructure concerns subscribe through appropriate abstractions.

## Testing and coverage

- Every production feature must have unit tests in `tests/InvisibleSP.UnitTests` unless a documented architectural reason makes a unit test inappropriate.
- Unit tests use xUnit v3, FluentAssertions, and `coverlet.collector`.
- Tests must exercise both success and failure paths, including meaningful branch conditions.
- The CI test job must collect line and branch coverage from Coverlet's XML output.
- Minimum required coverage is **80% lines and 80% branches** for the code included in the coverage report.
- Coverage thresholds are enforced by CI; a test run below either threshold fails the job.
- Coverage reports must be rendered as Markdown and appended to the GitHub Actions job summary so the agent can inspect the measured line and branch percentages.

## Global build enforcement

`Directory.Build.props` establishes the shared .NET 10 compiler/analyzer defaults for all projects beneath the repository root.
`Directory.Build.props` establishes the shared .NET 10 compiler/analyzer defaults for all projects beneath the repository root and generates XML documentation files.

`Directory.Build.targets` validates that every C# project has a root-level `GlobalUsings.cs` before compilation.

The repository `.editorconfig` enforces file-scoped namespaces and centralized import conventions. Build-time analyzers are enabled so code-style and analyzer feedback is visible during builds.
The repository `.editorconfig` enforces file-scoped namespaces, centralized import conventions, and XML documentation diagnostics for public APIs. Build-time analyzers are enabled so code-style and analyzer feedback is visible during builds.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>
</Project>
14 changes: 14 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,18 @@
Condition="!Exists('$(MSBuildProjectDirectory)/GlobalUsings.cs')"
Text="$(MSBuildProjectName): GlobalUsings.cs is required at the project root. Add all project-wide using directives there and do not add using directives to individual source files." />
</Target>

<Target Name="GenerateXmlDocumentation"
AfterTargets="CoreCompile"
Condition="'$(Configuration)' == 'Release' and '$(IsTestProject)' != 'true' and '$(GenerateDocumentationFile)' == 'true'">
<MakeDir Directories="$(MSBuildThisFileDirectory)docs-gen" />
<Copy SourceFiles="$(DocumentationFile)"
DestinationFiles="$(MSBuildThisFileDirectory)docs-gen/$(AssemblyName).xml"
SkipUnchangedFiles="true" />
</Target>

<PropertyGroup Condition="'$(Configuration)' == 'Release' and '$(IsTestProject)' != 'true'">
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>$(MSBuildProjectDirectory)/obj/$(Configuration)/$(TargetFramework)/$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>
</Project>
21 changes: 12 additions & 9 deletions SPInvisivel.slnx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<Solution>
<Folder Name="/src/">
<Project Path="src/InvisibleSP.Application/InvisibleSP.Application.csproj" />
<Project Path="src/InvisibleSP.Composition/InvisibleSP.Composition.csproj" />
<Project Path="src/InvisibleSP.Domain/InvisibleSP.Domain.csproj" />
<Project Path="src/InvisibleSP.Infrastructure/InvisibleSP.Infrastructure.csproj" />
<Project Path="src/InvisibleSP/InvisibleSP.csproj" />
</Folder>
</Solution>
<Solution>
<Folder Name="/src/">
<Project Path="src/InvisibleSP.Application/InvisibleSP.Application.csproj" />
<Project Path="src/InvisibleSP.Composition/InvisibleSP.Composition.csproj" />
<Project Path="src/InvisibleSP.Domain/InvisibleSP.Domain.csproj" />
<Project Path="src/InvisibleSP.Infrastructure/InvisibleSP.Infrastructure.csproj" />
<Project Path="src/InvisibleSP/InvisibleSP.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/InvisibleSP.UnitTests/InvisibleSP.UnitTests.csproj" />
</Folder>
</Solution>
57 changes: 57 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SP Invisível Architecture

## Solution layers

The solution is a feature-oriented DDD application with the following dependency direction:

`InvisibleSP` → `InvisibleSP.Composition` → `InvisibleSP.Infrastructure` → `InvisibleSP.Application` → `InvisibleSP.Domain`

`InvisibleSP.Application` may reference `InvisibleSP.Domain` directly. `InvisibleSP.Domain` must remain independent of the other solution projects.

### `src/InvisibleSP.Domain`

Contains domain entities, value objects, domain events, rules, and domain abstractions. It must not reference ASP.NET Core, Entity Framework Core, Identity, HTTP, UI, logging infrastructure, or persistence implementations.

### `src/InvisibleSP.Application`

Contains use-case contracts and orchestration: requests, responses, handlers, validators, application abstractions, and pipeline behavior. It depends on domain concepts and abstractions, not infrastructure implementations.

### `src/InvisibleSP.Infrastructure`

Contains technical implementations: Entity Framework Core persistence, Identity-like authentication infrastructure, JWT services, external integrations, and concrete implementations of application abstractions.

### `src/InvisibleSP.Composition`

Owns dependency injection and HTTP/application composition. It provides the application service-registration extension and the HTTP pipeline extension. Application and domain code must never depend on this project.

### `src/InvisibleSP`

Is the presentation and entry-point project. It contains Blazor Interactive Server UI and controllers. Controllers translate HTTP requests into application requests and must not access `DbContext` or repositories directly.

## Feature boundaries

Features are grouped by business/use-case boundary. `Common` is reserved for types genuinely shared across multiple features. Avoid global technical folders that mix unrelated features.

## Identity boundary

Identity behavior is implemented by `InvisibleSP.Infrastructure.Identity.Services.IdentityService` and related infrastructure types. Application contracts expose identity operations through `IIdentityService`. Tests must target this implementation contract and its actual Identity configuration.

Two-factor authentication uses the Identity authenticator token provider and an authenticator shared key. A TOTP code is generated from that key by the authenticator/client side and passed back to the service for validation.

## Persistence

`InvisibleSPDbContext` derives from the Identity EF Core context and owns persistence configuration. Types implementing `ISoftDeletable` receive a query filter and deleted entities are converted to updates by the save pipeline.

## Composition

Dependency registration belongs in `InvisibleSP.Composition`. Presentation startup calls the composition extension instead of duplicating registrations. Application handlers depend on application abstractions and infrastructure supplies their implementations.

## Tests

`tests/InvisibleSP.UnitTests` contains unit and infrastructure-backed tests for the production layers. It uses EF Core InMemory for persistence-focused scenarios and the real Identity implementation for identity behavior. Tests are excluded from Release XML documentation publication but are still required to contain XML documentation for public types and members.

## Build documentation

`Directory.Build.props` establishes common .NET 10 settings. `Directory.Build.targets` validates `GlobalUsings.cs` and defines `GenerateXmlDocumentation` for Release production builds. Generated XML files are copied to `docs-gen/` at repository root.

The `docs/` directory is reserved for human- and agent-authored documentation and must never be used as the generated XML output directory.
42 changes: 42 additions & 0 deletions docs/coding-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# C# Coding Style

## Language

- Target .NET 10.
- Use current C# language features when they improve clarity and correctness.
- Enable nullable reference types.
- Prefer `async` APIs for I/O and propagate `CancellationToken` through application and infrastructure boundaries.
- Avoid unnecessary nullable suppression (`!`).

## Namespaces and imports

- Use file-scoped namespaces.
- Individual C# source files must not contain `using` directives.
- Project-wide imports belong in the root `GlobalUsings.cs`.
- Keep global imports minimal and use aliases when necessary to resolve ambiguous types.

## API design

- Prefer constructor injection.
- Keep public APIs small and intentional.
- Use records for immutable request/response contracts where appropriate.
- Keep domain invariants in the domain model whenever practical.
- Keep transport concerns in presentation and technical concerns in infrastructure.

## XML documentation

Public APIs must document their contract. Use `<summary>`, `<param>`, `<typeparam>`, `<returns>`, `<exception>`, and `<remarks>` when applicable. Documentation should explain behavior, constraints, and side effects rather than repeat the identifier name.

Use `<inheritdoc />` for complete inherited/interface contracts. Do not use placeholder text or empty XML elements.

## Formatting

Follow the repository `.editorconfig`: four-space indentation for C#, LF line endings, file-scoped namespaces, braces for control flow, and centralized imports. Keep code readable rather than optimizing for compressed one-line expressions.

## Dependency injection

Register dependencies in `InvisibleSP.Composition`. Prefer abstractions at application boundaries. Choose service lifetimes intentionally: singleton for safe shared state/stateless thread-safe services, scoped for request/unit-of-work services, and transient for lightweight stateless services when justified.

## Tests

Name tests by behavior and expected outcome. Prefer one behavioral assertion group per scenario. Exercise both success and meaningful failure branches. Use the real production implementation when the purpose of the test is to validate that implementation.
Loading
Loading