System-level functional and non-functional requirements for the Item Image
Upload feature. Each requirement is derived from the source use cases and
feature specifications, and is verifiable by an independent agent once the
system is built.
- Source use cases:
GEN::MEDIA::0001 (Set), GEN::MEDIA::0002 (Remove),
GEN::MEDIA::0003 (View), REF::ITM::0003::0010 (Create), REF::ITM::0004::0006 (Edit)
- Feature specs:
GEN::MEDIA::FR-0001–FR-0020, REF::ITM::FR-0006–FR-0008
- Design decisions: TD-01 through TD-08, Decision Log
- Scoping: Scoping
| ID | Requirement | Source |
|---|
| FR-001 | The SPA shall provide a single image input surface that accepts file selection, drag-and-drop, clipboard paste, URL text entry, data URI text, and camera capture without requiring the user to select an input mode. | GEN::MEDIA::FR-0001, 0001::0001.UC |
| FR-002 | The SPA shall automatically detect the input method and route the provided image through the appropriate internal processing path. All paths converge to the managed upload path — no input method results in a directly persisted external URL. | GEN::MEDIA::FR-0002, 0001::0002.FS, TD-01 |
| FR-003 | When the user provides an HTTPS URL, the SPA shall validate the URL, attempt to fetch the image directly, and on CORS failure fall back to the BFF for reachability check and/or image fetch. | 0001::0004.FS, TD-02 |
| FR-004 | For HTTPS URL inputs, the SPA shall fetch the image, render it in the image editor for crop/zoom/rotate, and upload the result via the managed presigned-upload path. The external URL shall never be persisted as the entity image reference. | GEN::MEDIA::FR-0020, TD-01, TD-05 |
| FR-005 | When clipboard content is HTML with an embedded image URL, the SPA shall extract the URL, validate it, fetch the image SPA-side, and route it through the managed upload path. | 0001::0002.FS, TD-01, SD-14 |
| FR-006 | When clipboard content is a raw image blob, the SPA shall generate a local preview and route the binary content through the managed upload path on confirm. | 0001::0002.FS |
| FR-007 | When the user provides data: or blob: URI text, the SPA shall decode the content as image data and route it through the managed upload path. These URI schemes shall never be persisted. | GEN::MEDIA::FR-0012, GEN::MEDIA::FR-0013 |
| ID | Requirement | Source |
|---|
| FR-008 | The SPA shall accept images in JPEG, PNG, WebP, HEIC, and HEIF formats. SVG shall be rejected. | GEN::MEDIA::FR-0005, 0001::0003.FS |
| FR-009 | The SPA shall enforce a maximum file size per entity type (default 10 MB). When the file exceeds the limit, the SPA shall attempt auto-compression (85% JPEG quality, max 2048px longest edge) before rejecting. | GEN::MEDIA::FR-0006, 0001::0003.FS, SD-10 |
| FR-010 | The SPA shall accept only HTTPS URLs as external image references. All other URI schemes (http:, data:, blob:, javascript:, file:) shall be rejected for URL input. | GEN::MEDIA::FR-0009, 0001::0004.FS |
| FR-011 | The SPA shall verify URL reachability and confirm the response content type is a supported image format before accepting a URL input. On CORS failure, the BFF shall proxy the reachability check. | GEN::MEDIA::FR-0010, 0001::0004.FS, TD-02 |
| FR-012 | The Backend shall validate that all persisted image URLs match the expected CDN host and key pattern. URLs not matching the managed storage pattern shall be rejected. | GEN::MEDIA::FR-0011, TD-05 |
| FR-013 | All validation error messages shall use plain language understandable by non-technical users and suggest a corrective action. | GEN::MEDIA::FR-0008 |
| ID | Requirement | Source |
|---|
| FR-014 | The SPA shall render an image preview at the target aspect ratio defined by the entity type (1:1 square for Items). | GEN::MEDIA::FR-0014, 0001::0005.FS, SD-06 |
| FR-015 | The SPA shall provide crop, zoom, rotate, pan, and reset operations in the image preview editor. The crop aspect ratio is locked per entity type and is not user-modifiable. | GEN::MEDIA::FR-0015, 0001::0005.FS, SD-12 |
| FR-016 | When replacing an existing image, the SPA shall display the current image alongside the new preview for visual comparison (side-by-side on desktop, tabbed on mobile). Replacing an image uses the same interaction flow as setting one for the first time (the comparison layout is the only difference). | GEN::MEDIA::FR-0004, GEN::MEDIA::FR-0016, 0001::0005.FS, SD-11 |
| FR-017 | The SPA shall display a preview of the provided image before the user confirms, regardless of input method. | GEN::MEDIA::FR-0003 |
| ID | Requirement | Source |
|---|
| FR-018 | The SPA shall display copyright acknowledgment text inline in the confirm dialog footer. The text states that by providing images, the user accepts they have the right to use them. The confirm button is always enabled; no blocking checkbox or gate is required. | 0001::0006.FS, SD-07, FD-18 |
| FR-019 | Server-side logging of the copyright acknowledgment is out of scope. The acknowledgment is SPA-only — no backend record of acknowledgment is required. | TD-04 |
| ID | Requirement | Source |
|---|
| FR-020 | The Backend (Operations) shall generate presigned POST credentials for uploading images to managed storage. The BFF shall proxy this request, adding authentication headers and tenant context. | TD-03, TD-08 |
| FR-021 | The SPA shall upload image file bytes directly to Storage using the presigned POST credentials. The BFF and Backend are not in the data path for file bytes. | TD-06, GEN::MEDIA::FR-0019 |
| FR-022 | After a successful upload, the SPA shall persist the resulting CDN URL on the entity via the BFF/Backend API. | 0001::0006.FS |
| FR-023 | The Backend shall verify the uploaded object exists in Storage (via HEAD request) before persisting the image URL on the entity. | Prior design: Static Asset Repository write flow step 5 |
| FR-024 | Presigned POST credentials shall enforce Content-Type (must start with image/) and Content-Length (1 byte to max file size) via S3 policy conditions. | TD-08, prior research on content validation |
| ID | Requirement | Source |
|---|
| FR-025 | The SPA shall require user confirmation before removing an entity’s image. On confirm, the entity’s image reference is cleared via the BFF/Backend API. | GEN::MEDIA::FR-0017, 0002::0001.UC |
| FR-026 | Removing an image shall clear the entity’s image URL field. The entity shall display a default placeholder. | GEN::MEDIA::FR-0017, REF::ITM::FR-0006 |
| FR-027 | Previous image references shall be retained in the entity’s version history. Managed assets shall not be deleted on removal or replacement. | GEN::MEDIA::FR-0018 |
| ID | Requirement | Source |
|---|
| FR-028 | The SPA shall render entity images as thumbnails in grid views, scaled to fit cell dimensions while preserving aspect ratio. Entities without images shall show a default placeholder (initials or generic icon). | 0003::0001.UC, REF::ITM::FR-0007 |
| FR-029 | Hovering over an image thumbnail in the grid for ~500 ms shall show a popover with a larger preview. The popover shall dismiss on mouse-out. No action icons are shown in the hover popover — quick inspection only. Single click on the cell selects the row (AG Grid default). | 0003::0002.FS, CD-08 (revised) |
| FR-030 | When an image URL is unreachable or returns an error, the grid cell shall show the default placeholder with an error badge. No toast or error message shall be displayed. The hover preview popover shall not be shown for error-state thumbnails. | 0003::0003.FS |
| FR-031 | While an image is loading, the grid cell shall show a lightweight loading indicator (shimmer or spinner). | 0003::0003.FS |
| ID | Requirement | Source |
|---|
| FR-032 | Double-click or Enter on an image cell in a grid view shall open a modal overlay containing the full image editor (same unified input surface as the form context). | 0001::0007.FS, SD-15 |
| FR-033 | On confirm in the grid editor, the change shall be persisted and the grid row shall reflect the updated thumbnail. On discard, no change. | 0001::0007.FS |
| ID | Requirement | Source |
|---|
| FR-034 | The Add Item form shall include an optional image field that uses the unified image input surface. Items saved without an image shall display a default placeholder. | REF::ITM::0003::0010.UC, REF::ITM::FR-0006 |
| FR-035 | The Edit Item form shall allow changing or removing the item’s image. Changing follows the set-image flow (FR-001–FR-024). Removing follows the remove flow (FR-025–FR-027). | REF::ITM::0004::0006.UC, REF::ITM::FR-0008 |
| ID | Requirement | Source |
|---|
| FR-036 | The BFF shall issue CloudFront signed cookies scoped to the active tenant’s key prefix (/<tenantId>/*) on session establishment. CloudFront shall reject image requests that do not carry a valid signed cookie. | TD-11 |
| FR-037 | Signed cookies shall have a short TTL (default 30 minutes, configurable). The SPA shall proactively refresh cookies before expiry (at approximately 50% of TTL). | TD-12 |
| FR-038 | When the active tenant changes during a session (without re-authentication), the SPA shall immediately request new signed cookies from the BFF scoped to the new tenant. Until the new cookies arrive, image requests to the new tenant’s images may return 403; the SPA shall show loading state during the refresh window. On 403 from a CDN image request, the SPA shall refresh cookies and retry (max 1 retry per image request); if the retry also returns 403, show error-state placeholder. | TD-12, Audit #13 |
| FR-039 | The BFF signed-cookie endpoint shall validate the caller’s session and extract the tenant ID from the authenticated context. It shall not accept a tenant ID as a client-supplied parameter. | TD-11 |
| ID | Requirement | Source |
|---|
| FR-040 | The SPA shall enforce a minimum image dimension of 200x200 pixels. Images below this threshold shall be rejected with a plain-language error. Per-entity-type configurability of minimum dimensions is deferred to a future release; V1 uses this hardcoded default. | GEN::MEDIA::FR-0007, Audit #6 |
| ID | Requirement | Source |
|---|
| FR-041 | Only one image upload may be active per browser session. While an upload is in the Uploading state, other image upload triggers (form fields, grid cell editors) shall be disabled. | Audit #20 |
| FR-042 | The image editor shall always produce JPEG output regardless of input format. HEIC/HEIF inputs are converted to JPEG during editing. The contentType in the presigned credential request shall be image/jpeg. | Audit #21 |
| ID | Requirement | Source |
|---|
| NFR-001 | Image uploads via presigned POST shall complete within 10 seconds for files up to 10 MB on a typical broadband connection (10 Mbps upload). | Derived from UX responsiveness expectations |
| NFR-002 | CDN-served images shall load within 500 ms for cached content (P95) in the US/EU delivery region. | Derived from grid rendering performance |
| NFR-003 | Presigned POST credential generation (Backend round-trip) shall complete within 1 second (P95). | Derived from upload UX flow responsiveness |
| NFR-004 | Grid thumbnail rendering shall not cause visible reflow or layout shifts when images load asynchronously. | 0003::0003.FS |
| ID | Requirement | Source |
|---|
| NFR-005 | All persisted image URLs shall originate from managed storage. The Backend shall reject any image URL that does not match the expected CDN host and key pattern. | TD-05, GEN::MEDIA::FR-0011 |
| NFR-006 | Presigned POST credentials shall be scoped to a specific S3 key prefix (tenant-partitioned) and shall expire within 15 minutes (aligned with existing uploadSignatureDuration). | Derived from TD-03, tenant isolation |
| NFR-007 | S3 object keys shall include the tenant ID as a path prefix for tenant isolation. | Derived from existing architecture, DQ-3 |
| NFR-008 | The BFF URL reachability check shall only target external URLs. It shall never check URLs on managed storage (those are known-good). | TD-02 |
| NFR-009 | The BFF URL reachability endpoint shall implement request-rate limiting and target-URL validation to prevent SSRF abuse. | Derived from OWASP SSRF prevention |
| NFR-017 | Product images shall be treated as sensitive data. CDN access shall require valid CloudFront signed cookies. Unauthenticated requests to the CDN shall receive 403 Forbidden. | TD-11 |
| NFR-018 | CloudFront signed cookies shall be scoped to the requesting tenant’s key prefix. A cookie issued for Tenant A shall not grant access to Tenant B’s images. | TD-11 |
| NFR-019 | Signed cookie TTL shall default to 30 minutes (configurable). Shorter TTLs reduce the breach window if cookies are exfiltrated. | TD-12 |
| NFR-020 | The CloudFront signing key pair shall be rotatable without downtime. CloudFront trusted key groups support multiple active keys for zero-downtime rotation. | TD-11, operational security |
| ID | Requirement | Source |
|---|
| NFR-010 | If an upload fails mid-transfer, the SPA shall allow the user to retry without re-entering the image. The presigned POST credentials shall be re-requested if expired. | Derived from upload UX robustness |
| NFR-011 | Incomplete multipart uploads in S3 shall be automatically aborted via lifecycle rule (1-day expiration). | Derived from prior research on upload failure handling |
| NFR-012 | Orphaned uploads (presigned credentials used but entity never updated) remain in the persistent bucket indefinitely. At projected volumes (~50 GB, ~$1.10/month), storage cost is negligible. A periodic cleanup mechanism (scan job comparing S3 objects against entity image URLs) is deferred to a future enhancement. No staging prefix is used — uploads go directly to the final key. | Derived from DQ-5/DQ-8 prior research, R-002 |
| ID | Requirement | Source |
|---|
| NFR-013 | The design shall support at least 100 tenants × 1,000 images per tenant (~50 GB total storage) without architectural changes. | Derived from prior cost projection |
| NFR-014 | Image delivery shall use CloudFront CDN to avoid backend involvement in the read path. | TD-06, TD-07 |
| ID | Requirement | Source |
|---|
| NFR-015 | The image upload capability shall be generic (parameterized by ImageFieldConfig) so that future entity types can adopt it without re-implementing the upload workflow. | GEN::MEDIA cross-cutting design principle |
| NFR-016 | AWS-specific implementation details shall be isolated in the AWS actor specification. Scenario diagrams shall reference “Storage” as a black box. | TD-07 |
| ID | Requirement | Source |
|---|
| NFR-021 | The SPA shall display an upload progress indicator (percentage or indeterminate) during the Uploading state. For presigned POST uploads, the XHR/fetch progress event provides byte-level tracking. | R-006 mitigation, Audit #18 |
The following requirements are documented for future implementation. They are
out of scope for V1 (see Scoping).
| ID | Requirement | Source |
|---|
| NFR-022 | The image editor controls (crop, zoom, rotate, pan, reset) shall be operable via keyboard. Focus order shall follow the visual layout. | WCAG 2.1 AA, Audit #19 |
| NFR-023 | The ImageUploadDialog modal overlay shall implement a focus trap. Focus returns to the triggering element on close. | WCAG 2.1 AA, Audit #19 |
| NFR-024 | Image thumbnails in the grid shall include alt text derived from the entity name (e.g., “Product image for [Item Name]”). Placeholders shall have alt="" (decorative). | WCAG 2.1 AA, Audit #19 |
| NFR-025 | Upload state transitions (uploading, success, error) shall be announced to screen readers via ARIA live regions. | WCAG 2.1 AA, Audit #19 |
The User actor is a human operating through a modern web browser. The system
design assumes the following behaviors and constraints:
| ID | Assumption | Implication |
|---|
| UA-001 | The user operates a modern desktop or mobile browser supporting <canvas>, FileReader, Clipboard API, and fetch. | Client-side image processing (crop, rotate, compression) is feasible. HEIC/HEIF support depends on browser capabilities — the SPA should detect and gracefully degrade. |
| UA-002 | The user may be non-technical (e.g., shop floor worker, inventory manager). | All error messages must be plain-language. Technical jargon (MIME type, presigned URL, Content-Length) must never be exposed. |
| UA-003 | The user may paste images from diverse sources (screenshot tools, Google Image Search, Amazon product pages, email clients). | Clipboard handling must detect multiple content types (image blob, HTML with embedded URL, plain text URL, unrecognized). |
| UA-004 | The user may provide images from external URLs that are CORS-restricted. | The BFF must provide a reachability/fetch fallback for CORS-blocked URLs. |
| UA-005 | The user operates within an authenticated session. The active tenant may change during the session without re-authentication (multi-tenant users). | Tenant isolation is enforced at every layer. The user cannot access or modify images belonging to a tenant they are not currently operating in. CDN signed cookies must be refreshed on tenant switch (FR-038). |
| UA-006 | Multiple users may edit the same entity concurrently. | Last-writer-wins semantics apply. The bitemporal persistence layer provides a full audit trail. No locking or conflict resolution is required for image fields. |
| UA-007 | The user expects uploaded images to be immediately visible after confirmation. | The upload workflow must be synchronous from the user’s perspective — no background processing delay between confirm and display. CDN propagation must be near-instant (or the initial read uses S3 directly). |
Copyright: (c) Arda Systems 2025-2026, All rights reserved