Skip to content

feat(contracts): extract Paperless.Contracts project (DTO/validation boundary)#5

Merged
ANcpLua merged 1 commit into
mainfrom
feat/extract-paperless-contracts
May 12, 2026
Merged

feat(contracts): extract Paperless.Contracts project (DTO/validation boundary)#5
ANcpLua merged 1 commit into
mainfrom
feat/extract-paperless-contracts

Conversation

@ANcpLua
Copy link
Copy Markdown
Owner

@ANcpLua ANcpLua commented May 12, 2026

Summary

First slice of the TourPlanner-pattern backend restructure — moves from vertical-slice Features/ to a layered API / BL / Contracts / DAL split. Starts with the safest layer (transport boundary) before touching any logic.

New project: Paperless.Contracts/Paperless.Contracts.csproj — plain class library, net10.0, no external dependencies.

Moved into Paperless.Contracts/:

  • BatchProcessing/AccessReportDto.cs (was Features/BatchProcessing/Presentation/Dto/)
  • DocumentManagement/DocumentDtos.cs — all response/query DTOs (PaginationQuery, SearchQuery, DocumentDto, CreateDocumentResponse, DocumentSearchResultDto, SummaryDto, PaginatedDocumentsResponse)
  • Validation/Constraints.csSearchConstraints + PaginationConstraints (boundary-level ranges the DTOs depend on)

Stayed in PaperlessREST:

  • UploadDocumentRequest (carries IFormFile — ASP.NET Core input model, not a wire DTO; doc-comment points to the new namespace)
  • FileUploadConstraints, RateLimitPolicies, CachePolicies (server-side)
  • SearchServiceConstraints.ServiceQueryMaxLength — renamed from SearchConstraints.ServiceQueryMaxLength so the boundary-level SearchConstraints in Paperless.Contracts stays free of server-side leakage

Wiring:

  • Paperless.slnx adds the project before PaperlessREST
  • PaperlessREST + PaperlessREST.Tests gain ProjectReference to Paperless.Contracts
  • Both projects' GlobalUsings.cs add Paperless.Contracts.{BatchProcessing,DocumentManagement,Validation} so callers see the records under the same short names

Test plan

  • ./build.sh Compile — Restore + Compile both succeed locally
  • CI Build & Test (backend) green (Restore → Compile → UnitTests → IntegrationTests → Coverage → DotCov → Codecov)
  • CI Angular + React frontend builds unaffected

Follow-ups (this series)

  • Paperless.DAL — extract Features/*/Infrastructure/ (Persistence, Storage, Search)
  • Paperless.BL — extract Features/*/Application/
  • PaperlessREST slims to API/endpoints or renames to Paperless.API
  • PaperlessServices threads through the same Contracts/BL/DAL projects

…boundary)

First slice of the TourPlanner-pattern backend restructure (vertical-slice
Features/ -> layered API/BL/Contracts/DAL split). Starts with the safest
layer: the transport boundary.

New project: Paperless.Contracts/Paperless.Contracts.csproj — plain class
library targeting net10.0 with no external dependencies.

Moved into Paperless.Contracts:
  - BatchProcessing/AccessReportDto.cs         (was Features/BatchProcessing/Presentation/Dto/)
  - DocumentManagement/DocumentDtos.cs         (was Features/DocumentManagement/Presentation/Dto/DTOs.cs)
    All response/query DTOs: PaginationQuery, SearchQuery, DocumentDto,
    CreateDocumentResponse, DocumentSearchResultDto, SummaryDto,
    PaginatedDocumentsResponse.
  - Validation/Constraints.cs                  (was Configuration/Constraints.cs subset)
    SearchConstraints + PaginationConstraints — the boundary-level ranges
    the DTOs depend on.

Stayed in PaperlessREST:
  - UploadDocumentRequest                      (Features/DocumentManagement/Presentation/Dto/DTOs.cs)
    Carries IFormFile, an ASP.NET Core input-model concern, not a wire DTO.
    A doc-comment now points readers at the new Paperless.Contracts namespace
    for the rest of the document transport surface.
  - FileUploadConstraints, RateLimitPolicies, CachePolicies, SearchServiceConstraints
    Server-side concerns. SearchConstraints.ServiceQueryMaxLength (used only in
    DocumentSearchService) was renamed to SearchServiceConstraints.ServiceQueryMaxLength
    to keep the boundary-level SearchConstraints in Paperless.Contracts free
    of server-side leakage.

Wiring:
  - Paperless.slnx adds the new project before PaperlessREST.
  - PaperlessREST + PaperlessREST.Tests gain ProjectReference to Paperless.Contracts.
  - Both projects' GlobalUsings.cs add `Paperless.Contracts.{BatchProcessing,DocumentManagement,Validation}`
    so callers see the records under the same short names as before.

Verified with ./build.sh Compile (Restore + Compile both succeed).

Follow-ups in this series:
  - Paperless.DAL (extract Features/*/Infrastructure/ — Persistence, Storage, Search)
  - Paperless.BL  (extract Features/*/Application/)
  - PaperlessREST slims to API/endpoints, or renames to Paperless.API
  - PaperlessServices threads through the same Contracts/BL/DAL projects

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 12, 2026 10:42
@ANcpLua ANcpLua merged commit 25870d5 into main May 12, 2026
2 checks passed
@ANcpLua ANcpLua deleted the feat/extract-paperless-contracts branch May 12, 2026 10:42
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR starts the backend restructure by extracting the transport/contract boundary into a new Paperless.Contracts project, moving DTOs and boundary validation constants out of the ASP.NET Core API project while keeping ASP.NET-specific request models in PaperlessREST.

Changes:

  • Added new Paperless.Contracts project and wired it into the solution and project references.
  • Moved DocumentManagement DTOs + boundary validation constraints (SearchConstraints, PaginationConstraints) into Paperless.Contracts.
  • Renamed server-side-only search truncation constant container to SearchServiceConstraints and updated the Elasticsearch search service to use it.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
PaperlessREST/PaperlessREST.csproj Adds ProjectReference to the new contracts project.
PaperlessREST/GlobalUsings.cs Switches BatchProcessing/DocumentManagement DTO visibility to Paperless.Contracts.* namespaces.
PaperlessREST/Features/DocumentManagement/Presentation/Dto/DTOs.cs Keeps UploadDocumentRequest in API (ASP.NET-specific IFormFile), removes response/query DTOs from this project.
PaperlessREST/Features/DocumentManagement/Infrastructure/Search/DocumentSearchService.cs Updates truncation constant usage to SearchServiceConstraints.
PaperlessREST/Configuration/Constraints.cs Splits out server-only constant as SearchServiceConstraints; removes public DTO validation constraints from API project.
PaperlessREST.Tests/PaperlessREST.Tests.csproj Adds ProjectReference to Paperless.Contracts.
PaperlessREST.Tests/GlobalUsings.cs Adds global usings for Paperless.Contracts.* namespaces.
Paperless.slnx Adds the new Paperless.Contracts project to the solution.
Paperless.Contracts/Validation/Constraints.cs Introduces boundary-level SearchConstraints and PaginationConstraints.
Paperless.Contracts/Paperless.Contracts.csproj New class library project for contracts (net10.0, nullable/implicit usings).
Paperless.Contracts/DocumentManagement/DocumentDtos.cs New home for DocumentManagement query/response DTOs.
Paperless.Contracts/BatchProcessing/AccessReportDto.cs Moves AccessReportDto to Paperless.Contracts.BatchProcessing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1 to 15
namespace PaperlessREST.Features.DocumentManagement.Presentation.Dto;

/// <summary>
/// Request model for uploading a PDF document.
/// Validation handled by <see cref="Filters.PdfUploadFilter"/>.
///
/// Stays in the API project (rather than Paperless.Contracts) because it carries an
/// <see cref="IFormFile"/> — an ASP.NET Core input-model concern, not a transport DTO.
/// All response/query DTOs live in <c>Paperless.Contracts.DocumentManagement</c>.
/// </summary>
public sealed record UploadDocumentRequest
{
[Description("PDF file to upload (max 10MB, PDF only)")]
public required IFormFile File { get; init; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants