Files
DodoSSH/Directory.Packages.props
T
jaap-jan eaf68c86b0 Add data model, DbContext and initial migration (M1)
Schema for identity, vaults, grants, hosts and the sync change log, verified against a
real PostgreSQL 18 container rather than an in-memory provider: partial unique indexes,
CHECK constraints, citext and identity-always columns are all provider behaviour that an
in-memory fake would not exercise.

Invariants pushed into the database, so they hold even when application code has a bug:
- ck_host_relay_target is a security boundary, not tidiness. A host may carry a plaintext
  hostname and port ONLY when relay is deliberately enabled. Both directions are tested;
  the important one is that relay-disabled hosts cannot carry an address, since otherwise
  a bug would silently give the server infrastructure visibility it was never granted.
- ck_vault_owner: exactly one of owner_user_id or team_id, or permission resolution would
  have no defined answer.
- ck_vault_key_grant_recipient: member grants name a user; recovery and escrow grants are
  wrapped to a key and must not.
- ck_user_key_wrap_kdf: a password-derived wrap without its parameters is permanently
  unopenable, so a partial write is rejected outright.

Present from the first migration on purpose:
- GrantKind (Member/Recovery/Escrow). Recovery cannot be bolted on later — every vault
  created before it existed would be unrecoverable by design.
- team and team_membership, though team features are M3. Adding them later would mean
  introducing a foreign key on a live vault table.
- Host.ContentKeyId, reserved for per-item content keys wrapped to individual users.
- user_key as its own table, so key rotation does not require altering the user row.

Two things verified rather than assumed:
- Npgsql's UseXminAsConcurrencyToken helper no longer exists in EF 10, so xmin is mapped
  directly in XminConcurrency. The generated migration *looks* like it creates an xmin
  column; it does not. Confirmed by inspecting pg_attribute (attnum -2, a system column)
  and by grepping the emitted DDL. A test pins both, because had it created a real column
  PostgreSQL would have rejected the name.
- EF Core is now pinned centrally. The Npgsql provider asks for 10.0.4 while
  EntityFrameworkCore.Design pulls 10.0.10, and because Design is PrivateAssets=all that
  higher version does not flow to referencing projects — producing a CS1705 in any test
  project referencing Infrastructure.

Also commits artifacts/schema/v0.1.sql, the idempotent script, as the baseline for future
upgrade tests.

Verified: 0 warnings, 122 tests pass (27 new against Postgres), format clean.
2026-07-28 14:17:37 +02:00

92 lines
4.5 KiB
XML

<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<!--
Versions are pinned here for the whole solution. Packages are added per milestone
rather than all at once, so that every entry is one we have actually verified and
restored. See docs/adr/ for the choices behind the notable ones.
-->
<ItemGroup Label="ASP.NET Core">
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.10" />
</ItemGroup>
<ItemGroup Label="Pinned transitive dependencies">
<!--
Microsoft.AspNetCore.OpenApi 10.0.10 resolves Microsoft.OpenApi 2.0.0, which is
covered by GHSA-v5pm-xwqc-g5wc (high: circular schema references can terminate
OpenAPI parsing; vulnerable <= 2.7.4, patched in 2.7.5). Pinned forward within the
2.x major that ASP.NET Core 10 targets. Revisit when the ASP.NET Core package
itself moves off 2.0.0.
-->
<PackageVersion Include="Microsoft.OpenApi" Version="2.11.0" />
</ItemGroup>
<ItemGroup Label="Persistence">
<!--
EF Core pinned explicitly. The Npgsql provider asks only for 10.0.4 while
Microsoft.EntityFrameworkCore.Design pulls 10.0.10, and because Design is
PrivateAssets=all that higher version does not flow to referencing projects — which
produces a CS1705 in any test project that references Infrastructure. Pinning here lifts
every project to one version via central transitive pinning.
-->
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.10" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.10" />
<!--
Verified compatible with EF 10 before adopting; the plan flagged this package as
historically lagging EF majors. Fallback if it ever blocks an upgrade is explicit
HasColumnName in every IEntityTypeConfiguration: more code, zero risk.
-->
<PackageVersion Include="EFCore.NamingConventions" Version="10.0.1" />
</ItemGroup>
<ItemGroup Label="Cryptography">
<!--
NSec wraps libsodium. Chosen over the BCL because .NET has no X25519 or Ed25519, and
because ChaCha20Poly1305.IsSupported is false on macOS, which rules out the in-box
AEAD for a cross-platform client. NSec also holds key material in libsodium's
guarded, non-swappable memory, which a byte[] cannot do. See docs/crypto.md.
26.4.0 targets net9.0; net10.0 consumes it by forward compatibility. Native binaries
arrive via the libsodium package, pinned here because central transitive pinning
requires it to be declared.
-->
<PackageVersion Include="NSec.Cryptography" Version="26.4.0" />
<PackageVersion Include="libsodium" Version="1.0.22" />
<!-- Managed differential oracle for the crypto test suite only. -->
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.6.2" />
</ItemGroup>
<ItemGroup Label="Analyzers">
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="5.6.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="5.6.0" />
<PackageVersion Include="Meziantou.Analyzer" Version="3.0.134" />
</ItemGroup>
<ItemGroup Label="Testing">
<!--
xunit.v3 runs on Microsoft.Testing.Platform, not VSTest. Microsoft.NET.Test.Sdk and
coverlet.collector are VSTest components: referencing them alongside MTP raises
MTP0001 and their collector never runs, so neither is referenced.
No coverage collector yet. Microsoft.Testing.Extensions.CodeCoverage 18.9.0 pulls
Microsoft.Testing.Platform.MSBuild 1.9.1, which is built against MTP 1.x and throws
TypeLoadException on IDataConsumer against the MTP 2.3.x that xunit.v3 3.2.2 brings.
Coverage gates are an M3 concern (90% on Domain and Authorization); pick a version
aligned with MTP 2.x then rather than carrying a broken dependency until it matters.
-->
<PackageVersion Include="xunit.v3" Version="3.2.2" />
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="NSubstitute" Version="6.0.0" />
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.13.0" />
<PackageVersion Include="Respawn" Version="7.0.0" />
</ItemGroup>
</Project>