Restructure into src/tests and add build foundation (M0)

Moves the scaffold to src/DodoSSH.Api and establishes the repo conventions the rest
of the milestones build on.

Structure:
- src/{Contracts,Crypto,Domain,Infrastructure,Api}, tests/{Contracts,Crypto,Domain}.Tests
- DodoSSH.slnx rewritten with src/ and tests/ solution folders

Build:
- Directory.Build.props centralises TFM, nullable, deterministic builds and
  TreatWarningsAsErrors; Directory.Packages.props pins every version centrally
- packages.lock.json committed so CI restores in locked mode
- NuGet.config clears machine-level sources, which both fixes NU1507 under central
  package management and makes restore reproducible off this machine
- Microsoft.OpenApi pinned to 2.11.0: ASP.NET Core 10.0.10 resolves 2.0.0, which is
  covered by GHSA-v5pm-xwqc-g5wc (high, patched in 2.7.5)

Analyzers:
- AnalysisLevel is Recommended, not All. With warnings-as-errors, All turns opinionated
  naming rules into build breaks and trains people to blanket-suppress.
- BannedSymbols.txt bans DateTime.UtcNow (TimeProvider), Guid.NewGuid (CreateVersion7),
  sync-over-async, MD5/SHA1, PBKDF2 and SecureString
- CA1711/CA1724 disabled: both are .NET Framework CAS-era naming rules
- PublicApiAnalyzers on Contracts only, since that assembly is the client's real contract

API:
- weather-forecast template removed
- UseHttpsRedirection removed; TLS terminates at the reverse proxy and redirecting
  behind one causes loops
- /healthz/{live,ready,startup}. Liveness deliberately checks no dependencies so a
  transient database outage cannot restart the container and kill live SSH sessions.

Notes:
- No coverage collector yet. Microsoft.Testing.Extensions.CodeCoverage pulls an MTP 1.x
  MSBuild extension that throws TypeLoadException against the MTP 2.3.x xunit.v3 brings.
  Coverage gates are an M3 concern; revisit with an MTP 2.x-aligned version then.

Verified: dotnet build (0 warnings), 17 tests pass, format check clean, API serves
health and OpenAPI endpoints.
This commit is contained in:
2026-07-28 12:25:34 +02:00
parent 1138291d79
commit 3a81f3c90b
43 changed files with 1714 additions and 62 deletions
+37
View File
@@ -0,0 +1,37 @@
<Project>
<!-- Inherit everything from the repo root, then relax and add what test projects need. -->
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<!-- Test projects legitimately do things production code should not: assert on
nulls, construct throwaway objects, use reflection. Keep warnings visible
but non-fatal so a test file never blocks a build. -->
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<!-- xunit.v3 runs on Microsoft.Testing.Platform, which needs an executable host. -->
<OutputType>Exe</OutputType>
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
</PropertyGroup>
<PropertyGroup Label="Analyzer relaxations for tests">
<!-- CA1707: test method names use underscores by convention (Method_State_Expectation).
CA2007: no SynchronizationContext in tests, ConfigureAwait is noise.
CA1861: inline constant arrays in theories are clearer than static fields. -->
<NoWarn>$(NoWarn);CA1707;CA2007;CA1861;CA1052;CA1515</NoWarn>
</PropertyGroup>
<ItemGroup Label="Test framework — every test project gets these">
<PackageReference Include="xunit.v3" />
<PackageReference Include="Shouldly" />
<PackageReference Include="NSubstitute" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
<Using Include="Shouldly" />
</ItemGroup>
</Project>