Summary
PATCH /shipments/:id allows replacing the entire tags array, but there is no way to add or remove individual tags without reading the current list first and sending the full replacement array. For concurrent clients this creates a race condition. Dedicated tag add/remove endpoints solve this atomically at the DB level.
Location
src/modules/shipments/shipments.controller.ts — add POST :id/tags and DELETE :id/tags/:tag
src/modules/shipments/shipments.service.ts — add addTag() using Prisma push and removeTag() using prisma.$executeRaw array_remove
Expected Behaviour
POST /shipments/:id/tags body: { tag: string }. Validates tag is non-empty, max 50 chars, no spaces. Appends using { push: [tag] }. Returns 409 if tag already exists.
DELETE /shipments/:id/tags/:tag removes the tag using array_remove SQL. Returns 404 if the tag is not present.
- Both endpoints restricted to the shipment's
buyerAddress and only allowed when shipment is ACTIVE.
- Return the updated tags array after each operation.
Acceptance Criteria
- Adding an existing tag returns 409
- Removing a non-existent tag returns 404
- Both operations are atomic at the database level
- Only the buyer can modify tags; others receive 403
Summary
PATCH /shipments/:idallows replacing the entiretagsarray, but there is no way to add or remove individual tags without reading the current list first and sending the full replacement array. For concurrent clients this creates a race condition. Dedicated tag add/remove endpoints solve this atomically at the DB level.Location
src/modules/shipments/shipments.controller.ts— addPOST :id/tagsandDELETE :id/tags/:tagsrc/modules/shipments/shipments.service.ts— addaddTag()using PrismapushandremoveTag()usingprisma.$executeRawarray_removeExpected Behaviour
POST /shipments/:id/tagsbody:{ tag: string }. Validates tag is non-empty, max 50 chars, no spaces. Appends using{ push: [tag] }. Returns 409 if tag already exists.DELETE /shipments/:id/tags/:tagremoves the tag usingarray_removeSQL. Returns 404 if the tag is not present.buyerAddressand only allowed when shipment is ACTIVE.Acceptance Criteria