Skip to content

Commit 710b8bb

Browse files
committed
tighten storage quality baseline
1 parent bff76dd commit 710b8bb

File tree

196 files changed

+4246
-608
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

196 files changed

+4246
-608
lines changed

.editorconfig

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
9+
[*.md]
10+
trim_trailing_whitespace = false
11+
12+
[*.{g.cs,g.i.cs,Designer.cs,AssemblyInfo.cs}]
13+
generated_code = true
14+
15+
[*.cs]
16+
indent_style = space
17+
indent_size = 4
18+
19+
dotnet_diagnostic.CS1591.severity = none
20+
dotnet_diagnostic.CA1501.severity = suggestion
21+
dotnet_diagnostic.CA1502.severity = suggestion
22+
dotnet_diagnostic.CA1505.severity = suggestion
23+
dotnet_diagnostic.CA1506.severity = suggestion
24+
dotnet_diagnostic.CA1001.severity = suggestion
25+
dotnet_diagnostic.CA1051.severity = suggestion
26+
dotnet_diagnostic.CA1061.severity = suggestion
27+
dotnet_diagnostic.CA1068.severity = suggestion
28+
dotnet_diagnostic.CA1707.severity = suggestion
29+
dotnet_diagnostic.CA1716.severity = suggestion
30+
dotnet_diagnostic.CA1805.severity = suggestion
31+
dotnet_diagnostic.CA1822.severity = suggestion
32+
dotnet_diagnostic.CA1835.severity = suggestion
33+
dotnet_diagnostic.CA1848.severity = suggestion
34+
dotnet_diagnostic.CA1852.severity = suggestion
35+
dotnet_diagnostic.CA1859.severity = suggestion
36+
dotnet_diagnostic.CA1861.severity = suggestion
37+
dotnet_diagnostic.CA1863.severity = suggestion
38+
dotnet_diagnostic.CA1869.severity = suggestion
39+
dotnet_diagnostic.CA1870.severity = suggestion
40+
dotnet_diagnostic.CA1873.severity = suggestion
41+
42+
[ManagedCode.Storage.TestFakes/**/*.cs]
43+
dotnet_diagnostic.CA1502.severity = suggestion
44+
dotnet_diagnostic.CA1506.severity = suggestion
45+
46+
[Tests/**/*.cs]
47+
dotnet_diagnostic.CA1051.severity = none
48+
dotnet_diagnostic.CA1707.severity = none
49+
dotnet_diagnostic.CA1711.severity = none
50+
dotnet_diagnostic.CA1502.severity = suggestion
51+
dotnet_diagnostic.CA1506.severity = suggestion
52+
53+
[*.{csproj,props,targets,slnx}]
54+
indent_style = space
55+
indent_size = 4

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ jobs:
2626
- name: Restore dependencies
2727
run: dotnet restore ManagedCode.Storage.slnx
2828

29+
- name: Verify formatting
30+
run: dotnet format ManagedCode.Storage.slnx --verify-no-changes --no-restore
31+
2932
- name: Build
3033
run: dotnet build ManagedCode.Storage.slnx --configuration Release --no-restore
3134

AGENTS.md

Lines changed: 270 additions & 151 deletions
Large diffs are not rendered by default.

CodeMetricsConfig.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CA1501: 6
2+
CA1502: 25
3+
CA1502(Type): 6
4+
CA1505: 10
5+
CA1506: 40
6+
CA1506(Type): 120

Directory.Build.props

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<TargetFramework>net10.0</TargetFramework>
55
<LangVersion>14</LangVersion>
66
<EnableNETAnalyzers>true</EnableNETAnalyzers>
7+
<AnalysisLevel>latest-recommended</AnalysisLevel>
8+
<AnalysisMode>Recommended</AnalysisMode>
79
<DebugType>embedded</DebugType>
810
<Nullable>enable</Nullable>
911
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -27,8 +29,8 @@
2729
<RepositoryUrl>https://github.com/managedcode/Storage</RepositoryUrl>
2830
<PackageProjectUrl>https://github.com/managedcode/Storage</PackageProjectUrl>
2931
<Product>Managed Code - Storage</Product>
30-
<Version>10.0.2</Version>
31-
<PackageVersion>10.0.2</PackageVersion>
32+
<Version>10.0.3</Version>
33+
<PackageVersion>10.0.3</PackageVersion>
3234

3335
</PropertyGroup>
3436

@@ -40,7 +42,10 @@
4042
<None Include="$(SolutionDir)\README.md" Pack="true" Visible="false" PackagePath="\"/>
4143
</ItemGroup>
4244
<ItemGroup>
43-
<PackageReference Update="DotNet.ReproducibleBuilds" Version="1.2.25">
45+
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeMetricsConfig.txt" />
46+
</ItemGroup>
47+
<ItemGroup>
48+
<PackageReference Update="DotNet.ReproducibleBuilds">
4449
<PrivateAssets>all</PrivateAssets>
4550
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
4651
</PackageReference>

Directory.Packages.props

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
6+
<ItemGroup>
7+
<PackageVersion Include="AWSSDK.S3" Version="4.0.19" />
8+
<PackageVersion Include="Azure.Identity" Version="1.19.0" />
9+
<PackageVersion Include="Azure.Storage.Blobs" Version="12.27.0" />
10+
<PackageVersion Include="Azure.Storage.Files.DataLake" Version="12.25.0" />
11+
<PackageVersion Include="coverlet.collector" Version="8.0.0" />
12+
<PackageVersion Include="coverlet.msbuild" Version="8.0.0" />
13+
<PackageVersion Include="CsvHelper" Version="33.1.0" />
14+
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="1.2.25" />
15+
<PackageVersion Include="Dropbox.Api" Version="7.0.0" />
16+
<PackageVersion Include="Google.Api.Gax" Version="4.13.1" />
17+
<PackageVersion Include="Google.Api.Gax.Rest" Version="4.13.1" />
18+
<PackageVersion Include="Google.Apis.Drive.v3" Version="1.73.0.4068" />
19+
<PackageVersion Include="Google.Apis.Storage.v1" Version="1.73.0.4052" />
20+
<PackageVersion Include="Google.Cloud.Storage.V1" Version="4.14.0" />
21+
<PackageVersion Include="Humanizer.Core" Version="3.0.10" />
22+
<PackageVersion Include="ManagedCode.Communication" Version="10.0.1" />
23+
<PackageVersion Include="ManagedCode.MimeTypes" Version="10.0.1" />
24+
<PackageVersion Include="Microsoft.AspNetCore.Http" Version="2.3.9" />
25+
<PackageVersion Include="Microsoft.AspNetCore.Http.Connections.Client" Version="10.0.5" />
26+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.5" />
27+
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.5" />
28+
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.5" />
29+
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.5" />
30+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.5" />
31+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.5" />
32+
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.5" />
33+
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.5" />
34+
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.5" />
35+
<PackageVersion Include="Microsoft.Graph" Version="5.103.0" />
36+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
37+
<PackageVersion Include="Microsoft.Orleans.Runtime" Version="10.0.1" />
38+
<PackageVersion Include="Microsoft.Orleans.TestingHost" Version="10.0.1" />
39+
<PackageVersion Include="NetArchTest.Rules" Version="1.3.2" />
40+
<PackageVersion Include="Shouldly" Version="4.3.0" />
41+
<PackageVersion Include="SSH.NET" Version="2025.1.0" />
42+
<PackageVersion Include="Testcontainers" Version="4.11.0" />
43+
<PackageVersion Include="Testcontainers.Azurite" Version="4.11.0" />
44+
<PackageVersion Include="Testcontainers.FakeGcsServer" Version="4.11.0" />
45+
<PackageVersion Include="Testcontainers.LocalStack" Version="4.11.0" />
46+
<PackageVersion Include="Testcontainers.Sftp" Version="4.11.0" />
47+
<PackageVersion Include="xunit" Version="2.9.3" />
48+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
49+
</ItemGroup>
50+
</Project>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
Project: ManagedCode.Storage.Client.SignalR
2+
Owned by: ManagedCode.Storage maintainers
3+
4+
Parent: `../../AGENTS.md`
5+
6+
## Purpose
7+
8+
- Provides the SignalR client used for streaming transfers and progress notifications.
9+
- Exists so callers can consume the server hub contract without referencing the ASP.NET host project directly.
10+
11+
## Entry Points
12+
13+
- `IStorageSignalRClient.cs`
14+
- `StorageSignalRClient.cs`
15+
- `StorageSignalRClientOptions.cs`
16+
- `StorageSignalREventNames.cs`
17+
18+
## Boundaries
19+
20+
- In scope: SignalR connection lifecycle, client events, transfer-progress handling, and public configuration
21+
- Out of scope: server-side hub behavior, HTTP controller flows, and provider implementations
22+
- Protected or high-risk areas: hub event names, payload shapes, and connection disposal behavior shared with the server hub
23+
24+
## Project Commands
25+
26+
- `build`: `dotnet build ManagedCode.Storage.Client.SignalR.csproj`
27+
- `test`: `dotnet test ../../Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release`
28+
- `format`: `dotnet format ../../ManagedCode.Storage.slnx`
29+
- Active test framework: `xUnit`
30+
- Runner model: `VSTest`
31+
- Analyzer severity lives in the repo-root `.editorconfig`.
32+
33+
## Applicable Skills
34+
35+
- `mcaf-dotnet`
36+
- `mcaf-testing`
37+
- `mcaf-dotnet-xunit`
38+
- `mcaf-dotnet-quality-ci`
39+
- `mcaf-solid-maintainability`
40+
41+
## Local Constraints
42+
43+
- Stricter maintainability limits: none; inherit the root defaults.
44+
- Required local docs: `docs/Architecture.md`, `README.md`, and the nearest feature or ADR docs when public behavior changes.
45+
- Local exception policy: inherit the root `exception_policy` and document any project-specific exception in the nearest ADR, feature doc, or local `AGENTS.md`.
46+
47+
## Local Rules
48+
49+
- Keep event names and payload expectations aligned with `StorageHubBase` and `StorageSignalREventNames`.
50+
- Dispose handlers and hub connections cleanly; leaked subscriptions are regressions.
51+
- Do not depend on server internals beyond the published SignalR contract.

Integraions/ManagedCode.Storage.Client.SignalR/ManagedCode.Storage.Client.SignalR.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
</ItemGroup>
2121

2222
<ItemGroup>
23-
<PackageReference Include="ManagedCode.MimeTypes" Version="10.0.1" />
24-
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.1" />
25-
<PackageReference Include="Microsoft.AspNetCore.Http.Connections.Client" Version="10.0.1" />
23+
<PackageReference Include="ManagedCode.MimeTypes" />
24+
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" />
25+
<PackageReference Include="Microsoft.AspNetCore.Http.Connections.Client" />
2626
</ItemGroup>
2727

2828
<ItemGroup>

Integraions/ManagedCode.Storage.Client.SignalR/StorageSignalRClient.cs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public StorageSignalRClient()
3939
/// <param name="options">Preconfigured client options.</param>
4040
public StorageSignalRClient(StorageSignalRClientOptions options)
4141
{
42-
_options = options ?? throw new ArgumentNullException(nameof(options));
42+
ArgumentNullException.ThrowIfNull(options);
43+
_options = options;
4344
}
4445

4546
/// <inheritdoc />
@@ -57,18 +58,12 @@ public StorageSignalRClient(StorageSignalRClientOptions options)
5758
/// <inheritdoc />
5859
public async Task ConnectAsync(StorageSignalRClientOptions options, CancellationToken cancellationToken = default)
5960
{
60-
if (options is null)
61-
{
62-
throw new ArgumentNullException(nameof(options));
63-
}
61+
ArgumentNullException.ThrowIfNull(options);
6462

6563
await _connectionLock.WaitAsync(cancellationToken).ConfigureAwait(false);
6664
try
6765
{
68-
if (_disposed)
69-
{
70-
throw new ObjectDisposedException(nameof(StorageSignalRClient));
71-
}
66+
ObjectDisposedException.ThrowIf(_disposed, this);
7267

7368
_options = options;
7469

@@ -141,15 +136,8 @@ public async Task DisconnectAsync(CancellationToken cancellationToken = default)
141136
/// <inheritdoc />
142137
public async Task<StorageTransferStatus> UploadAsync(Stream stream, StorageUploadStreamDescriptor descriptor, IProgress<StorageTransferStatus>? progress = null, CancellationToken cancellationToken = default)
143138
{
144-
if (stream is null)
145-
{
146-
throw new ArgumentNullException(nameof(stream));
147-
}
148-
149-
if (descriptor is null)
150-
{
151-
throw new ArgumentNullException(nameof(descriptor));
152-
}
139+
ArgumentNullException.ThrowIfNull(stream);
140+
ArgumentNullException.ThrowIfNull(descriptor);
153141

154142
var connection = EnsureConnected();
155143

@@ -211,10 +199,7 @@ public async Task<StorageTransferStatus> DownloadAsync(string blobName, Stream d
211199
throw new ArgumentException("Blob name is required.", nameof(blobName));
212200
}
213201

214-
if (destination is null)
215-
{
216-
throw new ArgumentNullException(nameof(destination));
217-
}
202+
ArgumentNullException.ThrowIfNull(destination);
218203

219204
var connection = EnsureConnected();
220205

@@ -309,7 +294,10 @@ public async ValueTask DisposeAsync()
309294

310295
_disposed = true;
311296
await DisconnectAsync().ConfigureAwait(false);
312-
_connection?.DisposeAsync();
297+
if (_connection is not null)
298+
{
299+
await _connection.DisposeAsync().ConfigureAwait(false);
300+
}
313301
_connection = null;
314302
_connectionLock.Dispose();
315303
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
Project: ManagedCode.Storage.Client
2+
Owned by: ManagedCode.Storage maintainers
3+
4+
Parent: `../../AGENTS.md`
5+
6+
## Purpose
7+
8+
- Provides the HTTP client surface that talks to the ASP.NET storage controllers.
9+
- Exists so consumers can integrate with storage endpoints without depending on server-side implementation details.
10+
11+
## Entry Points
12+
13+
- `IStorageClient.cs`
14+
- `StorageClient.cs`
15+
- `ProgressStatus.cs`
16+
17+
## Boundaries
18+
19+
- In scope: HTTP request and response handling, client-facing transfer helpers, and public client contracts
20+
- Out of scope: server routing policy, provider-specific behavior, and SignalR streaming internals
21+
- Protected or high-risk areas: request or response shapes shared with `ManagedCode.Storage.Server`
22+
23+
## Project Commands
24+
25+
- `build`: `dotnet build ManagedCode.Storage.Client.csproj`
26+
- `test`: `dotnet test ../../Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release`
27+
- `format`: `dotnet format ../../ManagedCode.Storage.slnx`
28+
- Active test framework: `xUnit`
29+
- Runner model: `VSTest`
30+
- Analyzer severity lives in the repo-root `.editorconfig`.
31+
32+
## Applicable Skills
33+
34+
- `mcaf-dotnet`
35+
- `mcaf-testing`
36+
- `mcaf-dotnet-xunit`
37+
- `mcaf-dotnet-quality-ci`
38+
- `mcaf-solid-maintainability`
39+
40+
## Local Constraints
41+
42+
- Stricter maintainability limits: none; inherit the root defaults.
43+
- Required local docs: `docs/Architecture.md`, `README.md`, and the nearest feature or ADR docs when public behavior changes.
44+
- Local exception policy: inherit the root `exception_policy` and document any project-specific exception in the nearest ADR, feature doc, or local `AGENTS.md`.
45+
46+
## Local Rules
47+
48+
- Keep the client contract aligned with `ManagedCode.Storage.Server/Controllers/IStorageController.cs`.
49+
- Do not introduce provider-specific branches; this client stays storage-agnostic.
50+
- Preserve stream-first transfer and cancellation behavior so large-file flows remain viable.

0 commit comments

Comments
 (0)