diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json
index 9adfa48..1e9786b 100644
--- a/.nuke/build.schema.json
+++ b/.nuke/build.schema.json
@@ -46,7 +46,8 @@
"Restore",
"SetupTestcontainers",
"Test",
- "UnitTests"
+ "UnitTests",
+ "Verify"
]
},
"Verbosity": {
diff --git a/Directory.Build.props b/Directory.Build.props
index ae80255..8702b6e 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,9 +1,17 @@
-
-
-
- true
-
+
+
+
+ $(WarningsNotAsErrors);
+ AL0025;AL0026;AL0039;AL0070;AL0081;AL0101;AL0114;AL0137;
+ RS0030;
+ CA1002;CA1032;CA1034;CA1052;CA1056;CA1307;CA1725;CA1819;CA1822;CA1823;CA1852;CA1859;
+ CA2000;CA2012;CA2201;CA5394;
+ IDE0370;IDE1006
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 025dfae..783c3bd 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,6 +4,9 @@
true
+
+ true
@@ -36,9 +39,7 @@
-
-
-
+
@@ -73,6 +74,13 @@
+
+
+
+
diff --git a/Paperless.Contracts/Paperless.Contracts.csproj b/Paperless.Contracts/Paperless.Contracts.csproj
index d7dbfaa..e18270b 100644
--- a/Paperless.Contracts/Paperless.Contracts.csproj
+++ b/Paperless.Contracts/Paperless.Contracts.csproj
@@ -1,10 +1,6 @@
-
+
- net10.0
- preview
- enable
- enable
Paperless.Contracts
diff --git a/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs b/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs
index ce4e7d1..7698d0a 100644
--- a/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs
+++ b/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs
@@ -312,11 +312,11 @@ public async Task GetDocumentsPagedAsync_ReturnsNewestFirst()
// Add documents with slight delays to ensure distinct GUIDv7s
Document oldest = new DocumentBuilder().WithFileName($"{testPrefix}-old.pdf").Build();
await _repository.AddAsync(oldest, TestContext.Current.CancellationToken);
- await Task.Delay(10);
+ await Task.Delay(10, TestContext.Current.CancellationToken);
Document middle = new DocumentBuilder().WithFileName($"{testPrefix}-mid.pdf").Build();
await _repository.AddAsync(middle, TestContext.Current.CancellationToken);
- await Task.Delay(10);
+ await Task.Delay(10, TestContext.Current.CancellationToken);
Document newest = new DocumentBuilder().WithFileName($"{testPrefix}-new.pdf").Build();
await _repository.AddAsync(newest, TestContext.Current.CancellationToken);
@@ -345,7 +345,7 @@ public async Task GetDocumentsPagedAsync_RespectsPageSize()
await _repository.AddAsync(
new DocumentBuilder().WithFileName($"{testPrefix}-{i}.pdf").Build(),
TestContext.Current.CancellationToken);
- await Task.Delay(5); // Ensure distinct GUIDv7s
+ await Task.Delay(5, TestContext.Current.CancellationToken); // Ensure distinct GUIDv7s
}
// Act
@@ -369,7 +369,7 @@ public async Task GetDocumentsPagedAsync_WithCursor_ReturnsNextPage()
Document doc = new DocumentBuilder().WithFileName($"{testPrefix}-{i}.pdf").Build();
Document added = await _repository.AddAsync(doc, TestContext.Current.CancellationToken);
addedDocs.Add(added);
- await Task.Delay(5);
+ await Task.Delay(5, TestContext.Current.CancellationToken);
}
// Act - Get first page
@@ -400,7 +400,7 @@ public async Task GetDocumentsPagedAsync_LastPage_HasMoreIsFalse()
await _repository.AddAsync(
new DocumentBuilder().WithFileName($"{testPrefix}-{i}.pdf").Build(),
TestContext.Current.CancellationToken);
- await Task.Delay(5);
+ await Task.Delay(5, TestContext.Current.CancellationToken);
}
// Act - Request more than available
diff --git a/PaperlessREST.Tests/PaperlessREST.Tests.csproj b/PaperlessREST.Tests/PaperlessREST.Tests.csproj
index fe6afbc..4602ec5 100644
--- a/PaperlessREST.Tests/PaperlessREST.Tests.csproj
+++ b/PaperlessREST.Tests/PaperlessREST.Tests.csproj
@@ -1,30 +1,22 @@
-
+
- net10.0
- preview
- enable
- enable
- Exe
- false
+ true
+
+ true
PaperlessREST.Tests
true
- true
-
- true
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs b/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs
index 9cf3226..9a9993c 100644
--- a/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs
+++ b/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs
@@ -37,7 +37,7 @@ public async Task UploadDocumentAsync_StorageTimeout_ReturnsStorageTimeoutError(
DocumentService sut = CreateSut();
// Act
- ErrorOr result = await sut.UploadDocumentAsync(request);
+ ErrorOr result = await sut.UploadDocumentAsync(request, TestContext.Current.CancellationToken);
// Assert
result.IsError.Should().BeTrue();
@@ -57,7 +57,7 @@ public async Task UploadDocumentAsync_Storage500_ReturnsStorageServerError()
DocumentService sut = CreateSut();
// Act
- ErrorOr result = await sut.UploadDocumentAsync(request);
+ ErrorOr result = await sut.UploadDocumentAsync(request, TestContext.Current.CancellationToken);
// Assert
result.IsError.Should().BeTrue();
@@ -80,7 +80,7 @@ public async Task UploadDocumentAsync_StorageConnectionRefused_ReturnsStorageCon
DocumentService sut = CreateSut();
// Act
- ErrorOr result = await sut.UploadDocumentAsync(request);
+ ErrorOr result = await sut.UploadDocumentAsync(request, TestContext.Current.CancellationToken);
// Assert
result.IsError.Should().BeTrue();
diff --git a/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs b/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs
index 6ce11ff..455989f 100644
--- a/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs
+++ b/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs
@@ -6,7 +6,7 @@ public sealed class ReportProcessor(
ILogger logger) : IReportProcessor
{
private const string SchemaFileName = "accessReport.xsd";
- private static readonly XmlSerializer Serializer = new(typeof(AccessReportDto));
+ private static readonly XmlSerializer s_serializer = new(typeof(AccessReportDto));
private XmlSchemaSet Schemas => field ??= LoadSchemas();
@@ -89,7 +89,7 @@ private XmlSchemaSet LoadSchemas()
};
using XmlReader reader = XmlReader.Create(stream, settings);
- AccessReportDto dto = (AccessReportDto)Serializer.Deserialize(reader)!;
+ AccessReportDto dto = (AccessReportDto)s_serializer.Deserialize(reader)!;
if (validationErrors.Count > 0)
{
diff --git a/PaperlessREST/Features/DocumentManagement/Application/Document.cs b/PaperlessREST/Features/DocumentManagement/Application/Document.cs
index 0553cd7..d79e24b 100644
--- a/PaperlessREST/Features/DocumentManagement/Application/Document.cs
+++ b/PaperlessREST/Features/DocumentManagement/Application/Document.cs
@@ -77,6 +77,7 @@ public sealed class Document
/// Creates a new instance from an uploaded file.
///
/// The original filename of the uploaded PDF.
+ /// Provides the UTC timestamp recorded on ; inject for testability.
/// A new in status.
///
/// This factory method initializes a document with:
diff --git a/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs b/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs
index 3245c7a..ba50d6d 100644
--- a/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs
+++ b/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs
@@ -245,6 +245,6 @@ await Task.WhenAll(
"Document.StorageConnectionFailed",
$"Cannot connect to storage service for {storagePath}"),
- _ => null!
+ _ => null
};
}
diff --git a/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs b/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs
index a569f66..7f57ab0 100644
--- a/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs
+++ b/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs
@@ -220,7 +220,7 @@ private IServiceCollection AddInfrastructure(IConfiguration config)
private IServiceCollection AddPostgres(IConfiguration config)
{
- NpgsqlDataSource dataSource = new NpgsqlDataSourceBuilder(config.GetConnectionString("PaperlessDb")!)
+ NpgsqlDataSource dataSource = new NpgsqlDataSourceBuilder(config.GetConnectionString("PaperlessDb"))
.MapEnum("document_status")
.Build();
diff --git a/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs b/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs
index ea1bfd4..b3705ae 100644
--- a/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs
+++ b/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs
@@ -5,9 +5,6 @@ namespace PaperlessREST.Host.Extensions;
///
public static class TypedErrorOrAsyncExtensions
{
- private static readonly NotFound NotFound = TypedResults.NotFound();
- private static readonly NoContent NoContent = TypedResults.NoContent();
-
private static ValidationProblem CreateValidationProblem(IReadOnlyList errors) =>
TypedResults.ValidationProblem(
errors.Where(e => e.Type == ErrorType.Validation)
@@ -79,7 +76,7 @@ public async Task, NotFound>> ToOkOr404(
}
return result.FirstError.Type == ErrorType.NotFound
- ? NotFound
+ ? TypedResults.NotFound()
: throw ContractViolationException.ForNotFoundOnly(result.FirstError, result.Errors, callerName);
}
@@ -126,11 +123,11 @@ public async Task> ToNoContentOr404([CallerMemberNa
if (!result.IsError)
{
- return NoContent;
+ return TypedResults.NoContent();
}
return result.FirstError.Type == ErrorType.NotFound
- ? NotFound
+ ? TypedResults.NotFound()
: throw ContractViolationException.ForNotFoundOnly(result.FirstError, result.Errors, callerName);
}
}
diff --git a/PaperlessREST/PaperlessREST.csproj b/PaperlessREST/PaperlessREST.csproj
index 2c553e9..dcd9e21 100644
--- a/PaperlessREST/PaperlessREST.csproj
+++ b/PaperlessREST/PaperlessREST.csproj
@@ -1,17 +1,8 @@
-
+
- net10.0
- enable
- enable
- true
- preview
Linux
- true
- true
- latest
- true
- $(NoWarn);1591
+ false
diff --git a/PaperlessServices.Tests/PaperlessServices.Tests.csproj b/PaperlessServices.Tests/PaperlessServices.Tests.csproj
index 3062150..a395a45 100644
--- a/PaperlessServices.Tests/PaperlessServices.Tests.csproj
+++ b/PaperlessServices.Tests/PaperlessServices.Tests.csproj
@@ -1,23 +1,14 @@
-
+
- net10.0
- preview
- enable
- enable
+
+ true
Exe
- false
- true
-
- true
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs b/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs
index 4d18e00..5f6fa04 100644
--- a/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs
+++ b/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs
@@ -17,8 +17,8 @@ public class SearchIndexService(
ILogger logger)
: ISearchIndexService
{
- private static readonly SemaphoreSlim SInitLock = new(1, 1);
- private static readonly ConcurrentDictionary SInitializedIndices = new();
+ private static readonly SemaphoreSlim s_initLock = new(1, 1);
+ private static readonly ConcurrentDictionary s_initializedIndices = new();
///
/// Indexes a document in Elasticsearch after OCR processing completes.
@@ -77,16 +77,16 @@ private async Task InitializeAsync(CancellationToken cancellationToken = default
string indexName = options.Value.DefaultIndex;
// Fast path: index already initialized
- if (SInitializedIndices.ContainsKey(indexName))
+ if (s_initializedIndices.ContainsKey(indexName))
{
return;
}
- await SInitLock.WaitAsync(cancellationToken);
+ await s_initLock.WaitAsync(cancellationToken);
try
{
// Double-check after acquiring lock
- if (SInitializedIndices.ContainsKey(indexName))
+ if (s_initializedIndices.ContainsKey(indexName))
{
return;
}
@@ -94,7 +94,7 @@ private async Task InitializeAsync(CancellationToken cancellationToken = default
ExistsResponse existsResponse = await elastic.Indices.ExistsAsync(indexName, cancellationToken);
if (existsResponse.Exists)
{
- SInitializedIndices.TryAdd(indexName, true);
+ s_initializedIndices.TryAdd(indexName, true);
return;
}
@@ -113,11 +113,11 @@ private async Task InitializeAsync(CancellationToken cancellationToken = default
logger.LogInformation("Created Elasticsearch index: {IndexName}", indexName);
}
- SInitializedIndices.TryAdd(indexName, true);
+ s_initializedIndices.TryAdd(indexName, true);
}
finally
{
- SInitLock.Release();
+ s_initLock.Release();
}
}
}
diff --git a/PaperlessServices/PaperlessServices.csproj b/PaperlessServices/PaperlessServices.csproj
index 3a6ce16..145c700 100644
--- a/PaperlessServices/PaperlessServices.csproj
+++ b/PaperlessServices/PaperlessServices.csproj
@@ -1,17 +1,23 @@
-
+
- net10.0
- enable
- enable
+ Exe
paperless-services
- true
- preview
+ false
+
+
+
+
+
+
+
+
diff --git a/PaperlessUI.Angular/PaperlessUI.Angular.esproj b/PaperlessUI.Angular/PaperlessUI.Angular.esproj
index 83b6915..31323fc 100644
--- a/PaperlessUI.Angular/PaperlessUI.Angular.esproj
+++ b/PaperlessUI.Angular/PaperlessUI.Angular.esproj
@@ -1,11 +1,49 @@
-
+
+
+
+
- pnpm run start
- src\
- Jasmine
-
- false
-
- $(MSBuildProjectDirectory)\dist\paperless-ui-angular
+ $(MSBuildProjectDirectory)/
+ pnpm
+ $(FrontendRoot)dist/paperless-ui-angular
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj b/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj
index b5f6af0..c349c29 100644
--- a/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj
+++ b/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj
@@ -1,10 +1,8 @@
-
+
- net10.0
- enable
- enable
true
+ false
diff --git a/PaperlessUI.React/PaperlessUI.React.esproj b/PaperlessUI.React/PaperlessUI.React.esproj
index 6e996bb..2c91422 100644
--- a/PaperlessUI.React/PaperlessUI.React.esproj
+++ b/PaperlessUI.React/PaperlessUI.React.esproj
@@ -1,11 +1,50 @@
-
+
+
+
+
- pnpm run dev
- src\
- Vitest
-
- false
-
- $(MSBuildProjectDirectory)\dist
+ $(MSBuildProjectDirectory)/
+ pnpm
+ $(FrontendRoot)dist
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Pipeline/Build.csproj b/Pipeline/Build.csproj
index 1662874..91e0794 100644
--- a/Pipeline/Build.csproj
+++ b/Pipeline/Build.csproj
@@ -27,6 +27,11 @@
+
+
+
diff --git a/global.json b/global.json
index 400edd5..8b810e1 100644
--- a/global.json
+++ b/global.json
@@ -3,6 +3,11 @@
"version": "10.0.203",
"rollForward": "latestFeature"
},
+ "msbuild-sdks": {
+ "ANcpLua.NET.Sdk": "3.4.27",
+ "ANcpLua.NET.Sdk.Web": "3.4.27",
+ "ANcpLua.NET.Sdk.Test": "3.4.27"
+ },
"test": {
"runner": "Microsoft.Testing.Platform"
}