fix(tasks): add a max length to task Description (and record the DTO validation audit)

Aperta
#365 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
68/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
csharp
Ambito
api, backend

Direzione di ricerca

Start with TaskItemValidator and ProjectValidator to follow the existing description-length rule pattern, then review the controller validation paths noted in the issue. Add validator tests under TaskFlow.Api.Tests/Validators/ and controller tests covering PUT and PATCH rejection with no task changes. Done means all acceptance criteria pass, including POST/PUT/PATCH behavior, and dotnet test plus dotnet format --verify-no-changes pass.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

tech-debt

Groomed 2026-10-30 — ready for implementation.

Waits for the monorepo move (#397). This changes the API, so it is built after the assistant moves into this repo and the MCP change ships in the same PR (checked by the integration and error-code tests).

Original Description

Problem

UpdateTaskItemDto and PatchTaskItemDto have fields with no DTO-level validator. #207 (PR #363) added validators for CreateTaskItemDto, UpdateTaskItemDto and PatchTaskItemDto, but each covers only TimezoneOffsetMinutes.

During validation of #207 the reviewer noted that other fields, for example Title length and Description length, are not checked at the DTO level. In PATCH, Title appears to be checked only through the TaskItem model validator (TaskItemValidator) after the changes are applied to the entity.

This has not been verified as a real gap. The TaskItem validator may already cover these fields, in which case the only difference is where the error is raised. This issue is to find out.

What to check
  1. For each field on CreateTaskItemDto, UpdateTaskItemDto and PatchTaskItemDto, list which rule (if any) validates it today, and where (DTO validator, TaskItemValidator, EF constraint, or none).
  2. Identify any field where invalid input can reach the database, or cause a 500, or be accepted by one endpoint and rejected by another. Examples to try: over-long Title or Description, empty or whitespace-only Title on PATCH, BlockedReason length, DueDate extremes.
  3. Compare the three endpoints (POST, PUT, PATCH) for consistent behavior on the same invalid input.
Outcome
  • If every field is already covered by TaskItemValidator, close this issue with a short table of findings.
  • If there are gaps, add the missing rules (in Validators/, following the .InclusiveBetween / WithMessage pattern used for the offset) and tests under TaskFlow.Api.Tests/Validators/, or split out one issue per gap.
Context

Raised as a note-only observation by the implementation-validator during /feature-factory 207 (PR #363). Out of scope there.


Audit findings (2026-10-30, by reading the code; no requests were sent)

TaskItemValidator validates the entity after the DTO is mapped onto it. It runs on create (TaskItemsController.cs, around line 192) and in ApplyUpdateAsync (around line 437), so POST, PUT and PATCH are covered the same way. The three DTO validators cover only TimezoneOffsetMinutes, which is fine.

Field Validated by Gap
Title TaskItemValidator: not empty, max 100 none
Status, Priority TaskItemValidator: IsInEnum none
BlockedReason TaskItemValidator: max 200, only while Blocked none
Description nothing (no rule in TaskItemValidator, no length constraint in TaskDbContext) no length limit on POST, PUT or PATCH
DueDate nothing no range check; extremes are covered by #238
ParentTaskItemId, ProjectId controller checks not examined here

Comparable text fields are bounded: Project description 2000, Note content 2000, JournalNote content 2000, JournalLogEntry content 2000, JournalEntry summary 10000. Task Description is the only unbounded user text field.

Stored data check (2026-10-30, via the TaskFlow MCP list_tasks, 11 tasks, detailed format): the longest description is about 110 characters (task #68). Caveats: the MCP's target instance was not confirmed to be production, and the detailed format may truncate descriptions.

User Story

As a task owner, I want an over-long task description to be rejected with a clear message, so that task data stays bounded like every other text field and an accidental paste cannot bloat the database or the responses.

Acceptance Criteria

  1. Given a POST with a Description longer than 2000 characters, then the response is 400 with the message "Description must not exceed 2000 characters." and no task is created.
  2. Given a PUT with a Description longer than 2000 characters, then the response is 400 with the same message and the task is unchanged.
  3. Given a PATCH with a Description longer than 2000 characters, then the response is 400 with the same message and the task is unchanged.
  4. Given a Description of exactly 2000 characters, null, or empty, then POST, PUT and PATCH accept it.
  5. Given the rule, then it lives in TaskItemValidator (Validators/), not in the three DTO validators, so one rule covers every endpoint and the parent auto-complete path. Errors keep the BadRequest(validationResult.Errors) shape.
  6. Given the validator, then unit tests under TaskFlow.Api.Tests/Validators/ cover 2000 accepted, 2001 rejected, null and empty accepted, with the exact message. Controller tests cover PUT and PATCH rejection with the task unchanged.
  7. Given the finished change, then dotnet test and dotnet format --verify-no-changes pass, and backend line coverage stays at 75% or above.

Edge Cases

  • Existing data above the limit. PUT resends Description, so a stored description longer than 2000 characters would make every later update of that task fail until it is shortened. The MCP check found nothing near the limit, but it could not be confirmed against production. Check production data (for example with the MCP against the live instance) before merging.
  • Parent auto-complete. TryAutoCompleteParentAsync validates the parent entity (around line 575). A parent with an over-limit legacy description would fail validation there. Confirm what the user sees.
  • Counting. MaximumLength counts UTF-16 code units, not characters as the user perceives them. 2000 is the same unit the other validators use; do not change it.
  • Frontend. Check how the task forms surface a 400 on Description. Adding a maxLength attribute is optional and not required by this story.
  • The message and rule follow ProjectValidator (Description max 2000).

Out of Scope

  • DueDate range or wire format (#238).
  • Title, Status, Priority and BlockedReason rules (already covered).
  • Changing the TimezoneOffsetMinutes rules from #207.
  • Changing the error shape (BadRequest(validationResult.Errors) is the convention; see #364).
  • Global FluentValidation auto-validation.
  • Adding a database column constraint or migration.
  • ParentTaskItemId and ProjectId validation.
Lingua principale
C#
Stelle
1
Fork
0
Merge medio
2h 2m
PR unite (30g)
98

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di nevridge/TaskFlow

Tutte le issue di nevridge/TaskFlow

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.