feat: add multipart image uploads

Register Fastify multipart support, validate JPEG/PNG/WebP binary signatures, store upload bytes through ImageStorage, persist metadata after storage succeeds, clean up bytes on metadata failure, and document the upload boundary. Verification: npm test passed 68 tests and integration passed 14 tests. No build script is configured.
This commit is contained in:
2026-09-08 17:38:27 -04:00
parent 5a041c8a5c
commit f7152bcff3
14 changed files with 278 additions and 11 deletions
+3 -1
View File
@@ -98,7 +98,9 @@ available listings.
`POST /api/v1/admin/inventory/:id/images` stores validated image metadata for an
owned physical inventory item. File bytes are handled by the future
`ImageStorage` adapter; publication counts persisted inventory images rather
`ImageStorage` adapter; JSON metadata and multipart image uploads are accepted.
Multipart uploads require `width` and `height` fields and validate the binary
signature before storage. Publication counts persisted inventory images rather
than trusting a listing request field.
## Provider matching
+3 -2
View File
@@ -55,8 +55,9 @@ Validate:
The metadata service currently enforces JPEG, PNG, and WebP MIME types, a
10 MiB default file-size limit, and a 10,000-pixel maximum width and height.
Binary signature checks and multipart upload validation remain part of the
upload transport slice.
Multipart upload validation now checks the declared MIME type against JPEG,
PNG, and WebP signatures before storage. Image dimensions are supplied by the
upload transport until a decoder-backed dimension extractor is added.
Generate:
- thumbnail
+3 -3
View File
@@ -90,7 +90,7 @@ docker context use orbstack
- Listing publication rejects physical inventory in `SOLD` or `ARCHIVED` status with a conflict response.
- Listing reads are seller-scoped and return only admin listing DTO fields.
- Item-owned image metadata can be added through a seller-scoped, CSRF-protected admin route; publication uses the persisted image count.
- `ImageStorage` and a traversal-safe local filesystem adapter are implemented; upload transport, signature validation, and derivative processing remain.
- `ImageStorage`, traversal-safe local storage, multipart upload transport, and binary signature validation are implemented; derivative processing remains.
- Image metadata limits are enforced in the service boundary: supported MIME types, 10 MiB default file size, and 10,000-pixel maximum dimensions.
### Verified Baseline
@@ -102,13 +102,13 @@ docker context use orbstack
| HTTP | Product and inventory creation, validation, authentication/recovery, CSRF, rate limiting, and session management |
| Integration | PostgreSQL catalog/session/audit/password recovery persistence and Redis-shared login throttling |
Latest result: `npm test` passed 64 tests; `npm run test:integration` passed 14 tests against OrbStack PostgreSQL and Redis.
Latest result: `npm test` passed 68 tests; `npm run test:integration` passed 14 tests against OrbStack PostgreSQL and Redis.
## Next Milestone
Complete the inventory/listing integrity boundary before starting pricing and acquisition.
1. Add multipart upload transport, binary signature validation, and processing/derivative lifecycle for persisted image metadata.
1. Add processing/derivative lifecycle for persisted image metadata.
2. Begin acquisition and pricing foundations after the listing/image boundary is complete.
Acceptance criteria: listing reads and lifecycle writes preserve seller ownership, CSRF, inventory status, and publication prerequisites.