Specification: Frontend Implementation for Item Image Upload
Driving document for implementing the frontend image upload feature across 5 repositories in 9 sequential phases. References goal.md, analysis.md, requirements.md, and verification.md.
Summary
Section titled “Summary”This project delivers the BFF proxy layer, design system component updates,
TanStack Query integration, SPA wiring, and backend strict validation that
enable image upload, display, and management for the Item entity. It spans
api-proxy, ux-prototype, arda-frontend-app, operations, and
documentation.
The work is organized into 8 phases with review gates between each. Phases execute sequentially — each phase must pass its exit criteria and review before the next begins. The dependency chain is:
[component-preparation project] ← prerequisite (separate project/PR) └─→ 3.1 API Proxy Publish (api-proxy) └─→ 3.2 Lifecycle Framework (ux-prototype) └─→ 3.3 Component Updates (ux-prototype) └─→ 3.4 Design System Publish (ux-prototype) └─→ 3.5 BFF Routes (arda-frontend-app) └─→ 3.6 SPA Integration (arda-frontend-app) └─→ 3.6b Backend Strict Validation (operations) └─→ 3.7 Release (all repos)Prerequisite: The
component-preparation project must be
completed and merged before this project begins. It removes the legacy
@tanstack/react-table code and adds the dev:local tooling.
Note: Phases 3.1 (api-proxy) and 3.2–3.4 (ux-prototype) operate on different repositories. They could execute in parallel if needed, but sequential execution is recommended to keep the review cadence predictable.
Context
Section titled “Context”- Goal — scope, constraints, deliverables, success criteria
- Analysis — gap analysis: current state vs. specification
- Requirements — 61 functional + non-functional requirements
- Verification — traceability matrix (requirement → test → phase)
- Decision Log — FD-01 through FD-07
Architectural Decisions in Effect
Section titled “Architectural Decisions in Effect”| Decision | Summary | Impact |
|---|---|---|
| FD-01 | Typed data providers in design system | Components never import TanStack Query; app provides hooks |
| FD-02 | Hybrid code organization | New code in src/server/, src/api/, src/hooks/<feature>/, src/providers/ |
| FD-03 | Minimal lifecycle framework | Only types + useDraft<T> in this project; full framework deferred to #77 |
| FD-04 | Indeterminate upload progress | Replace simulated timer with spinner; optional onProgress added later |
| FD-05 | Entity persist stays in Redux | updateItem() via existing Redux thunk, not TanStack mutation |
| FD-06 | ItemCardEditor out of scope | Prototype-only; no production wiring |
| FD-07 | Legacy cleanup first commit | Remove @tanstack/react-table before adding new code |
Worktree Strategy
Section titled “Worktree Strategy”Worktrees already created at project start:
projects/image-upload-frontend-worktrees/├── api-proxy/ # branch: jmpicnic/image-upload-frontend├── ux-prototype/ # branch: jmpicnic/image-upload-frontend (rebased onto seb/inline-card-image-upload)├── arda-frontend-app/ # branch: jmpicnic/image-upload-frontend├── operations/ # branch: jmpicnic/image-upload-frontend (from jmpicnic/multi-pdf-print-and-bugs)└── documentation/ # branch: jmpicnic/image-upload-frontendSingle agent, sequential phases — no integration branch needed. Each repository gets one PR to its target branch.
Local development across repos uses npm run dev:local in
arda-frontend-app (see tools/dev-local.sh).
Prerequisites
Section titled “Prerequisites”component-preparation project (separate project/PR)
Section titled “component-preparation project (separate project/PR)”| Attribute | Value |
|---|---|
| Project | component-preparation |
| Repositories | arda-frontend-app |
| Deliverables | Legacy @tanstack/react-table removed, dev:local tooling added |
| Status | Must be merged before this project begins |
Phase Sequence
Section titled “Phase Sequence”Phase 3.1 — API Proxy Publish
Section titled “Phase 3.1 — API Proxy Publish”| Attribute | Value |
|---|---|
| Repository | api-proxy |
| Specification | 3.1-api-proxy-publish/specification.md |
| Tasks | 4 |
| Entry criteria | Code already implemented (preparation phase) |
| Exit criteria | Package published to GitHub Packages |
| Deliverable | @arda-cards/api-proxy at new version |
REVIEW GATE: Verify package is consumable. Test install in a scratch directory.
Phase 3.2 — Lifecycle Framework
Section titled “Phase 3.2 — Lifecycle Framework”| Attribute | Value |
|---|---|
| Repository | ux-prototype |
| Specification | 32-lifecycle-framework/specification.md |
| Tasks | 4 |
| Requirements | REQ-FE-030 through REQ-FE-033 |
| Entry criteria | ux-prototype branch, existing checks pass |
| Exit criteria | Types + useDraft<T> exported, all tests pass |
| Deliverable | Lifecycle framework types in canary entry point |
REVIEW GATE: Review type design and useDraft<T> implementation before
applying to components.
Phase 3.3 — Component Updates
Section titled “Phase 3.3 — Component Updates”| Attribute | Value |
|---|---|
| Repository | ux-prototype |
| Specification | 33-component-updates/specification.md |
| Tasks | 7 |
| Requirements | REQ-FE-040 through REQ-FE-047 |
| Entry criteria | Phase 3.2 complete, infrastructure#439 deployed |
| Exit criteria | 5 components updated, all tests + Storybook pass |
| Deliverable | Updated image components with FD-01 compliance |
REVIEW GATE: Review component changes. Verify Storybook stories render with default handlers. Verify no TanStack import in design system.
Phase 3.4 — Design System Publish
Section titled “Phase 3.4 — Design System Publish”| Attribute | Value |
|---|---|
| Repository | ux-prototype |
| Specification | 34-design-system-publish/specification.md |
| Tasks | 6 |
| Entry criteria | Phases 3.2 + 3.3 complete |
| Exit criteria | Package published to GitHub Packages at new version |
| Deliverable | @arda-cards/design-system with lifecycle types + updated components |
REVIEW GATE: Verify package is consumable. Test import of lifecycle types and updated components.
Phase 3.5 — BFF Routes
Section titled “Phase 3.5 — BFF Routes”| Attribute | Value |
|---|---|
| Repository | arda-frontend-app |
| Specification | 3.5-bff-routes/specification.md |
| Tasks | 8 |
| Requirements | REQ-FE-010 through REQ-FE-023 |
| Entry criteria | Phase 3.1 (api-proxy published), component-preparation project merged |
| Exit criteria | 4 BFF routes + 3 utilities, all tests pass |
| Deliverable | src/server/ directory with BFF routes and utilities |
REVIEW GATE: Security review of SSRF protection. Review CDN cookie
signing. Verify server-only enforcement.
Phase 3.6 — SPA Integration
Section titled “Phase 3.6 — SPA Integration”| Attribute | Value |
|---|---|
| Repository | arda-frontend-app |
| Specification | 3.6-spa-integration/specification.md |
| Tasks | 12 |
| Requirements | REQ-FE-060 through REQ-FE-077, REQ-FE-NF-001 through REQ-FE-NF-005 |
| Entry criteria | Phases 3.4 (design system published) + 3.5 (BFF routes) complete |
| Exit criteria | TanStack hooks wired, grid + form integration, all checks pass |
| Deliverable | Full SPA image upload functionality in mock mode |
REVIEW GATE: Full integration review. Verify upload flow end-to-end in mock mode. Review FD-01 wiring (no TanStack leaks into design system components). Review FD-02 directory structure.
Phase 3.6b — Backend Strict Validation
Section titled “Phase 3.6b — Backend Strict Validation”| Attribute | Value |
|---|---|
| Repository | operations |
| Specification | 36b-backend-validation/specification.md |
| Tasks | 8 |
| Entry criteria | Phase 3.6 complete (frontend sends CDN URLs only), CDN infrastructure deployed |
| Exit criteria | Strict CDN URL validation enforced, make build passes |
| Deliverable | operations branch with backward-compat relaxations reverted |
REVIEW GATE: Verify make build passes. Confirm no nullable CDN
dependencies remain. Confirm backward-compat tests removed and original
test URLs restored.
Phase 3.7 — Release
Section titled “Phase 3.7 — Release”| Attribute | Value |
|---|---|
| Repositories | All |
| Specification | 37-release/specification.md |
| Tasks | 6 |
| Entry criteria | All phases 3.0–3.6b reviewed and approved |
| Exit criteria | All PRs merged, worktrees cleaned up |
| Deliverable | Feature merged to target branches in all repos |
Cross-Phase Concerns
Section titled “Cross-Phase Concerns”Full local checks (every commit)
Section titled “Full local checks (every commit)”| Repository | Commands |
|---|---|
arda-frontend-app | npm run lint, npx tsc --noEmit, npx jest --no-coverage --watchAll=false --forceExit, npm run build |
operations | make build (Gradle build including tests) |
api-proxy | npm run lint, npm run typecheck, npm run test, npm run build |
ux-prototype | make check (lint + typecheck), make test, make build |
documentation | make pr-checks (lint + preview build + link check + smoke tests) |
Documentation commits (every phase)
Section titled “Documentation commits (every phase)”All project artifacts (specifications, session logs, byproducts, decision
log updates) live in the documentation worktree. After each phase:
- Run
make pr-checksin thedocumentationworktree to verify all checks pass (CHANGELOG validation, broken link detection, smoke tests). - Commit the documentation changes with a message referencing the phase.
- The documentation worktree accumulates commits across all phases; a single PR is created in Phase 3.7.
PR stewardship
Section titled “PR stewardship”After creating or pushing to any PR, run /pr-steward <pr-url> to monitor
CI checks, surface reviewer comments, implement fixes, reply to threads, and
resolve conversations. This applies to all PRs across all repositories
(Phases 3.1, 3.4, 3.7).
CHANGELOG discipline
Section titled “CHANGELOG discipline”Every PR to a protected branch must include a CHANGELOG update per the
release-lifecycle skill conventions. The release phase (3.7) consolidates
entries.
Temporary cross-layer imports
Section titled “Temporary cross-layer imports”New BFF routes in src/server/ import env and jwt from src/lib/
(legacy location). Annotate with // TODO #734: move to src/server/lib/.
This is cleaned up when
#734 executes.
Design system consumption model
Section titled “Design system consumption model”ux-prototypepublishes →arda-frontend-appbumps dependency- Use
npm run dev:localfor local development (seetools/dev-local.sh) - Never copy design system components into
arda-frontend-app
Applicable skills
Section titled “Applicable skills”Each phase specification references the skills relevant to its tasks. The following skills apply across the project:
| Skill | When to use |
|---|---|
implementation-task | Each phase follows the implementation task workflow (analysis, planning, byproducts, session logging) |
typescript-coding | All TypeScript code (api-proxy, BFF routes, SPA hooks) |
ui-component | Component updates in ux-prototype, component wiring in arda-frontend-app |
unit-tests-frontend | All Jest/Vitest tests (ux-prototype and arda-frontend-app) |
document-writing | All documentation artifacts (architecture docs, session logs, byproducts) |
plantuml-diagrams | All PlantUML diagrams in documentation |
release-lifecycle | CHANGELOG updates, PR creation, merge ordering |
pr-steward | PR monitoring after creation or push |
path-conventions | All Markdown links across repos |
cdk-infrastructure | CloudFront signer context (signing key construct) |
Open Questions and Decisions
Section titled “Open Questions and Decisions”Collected from all phase specifications. Resolve before or during the relevant phase.
| # | Phase | Question | Options | Recommendation | Decision |
|---|---|---|---|---|---|
| 1 | 3.2 | useDraft location: utilities/ vs. hooks/ | A: alongside types, B: dedicated hooks dir | A (colocate) | Decided: A |
| 2 | 3.2 | updateField deep clone strategy | A: shallow spread, B: structuredClone, C: immer | A (lightweight) | Decided: A — shallow spread per level, React best practice |
| 3 | 3.3 | ImageFormField prop naming | A: rename to initialValue, B: alias, C: keep imageUrl | B (backward compat) | Decided: B (alias + deprecation) |
| 4 | 3.3 | TypeaheadCellEditor interface style | A: convert to hook, B: keep promise callback | B (already FD-01) | Decided: B (keep promise callback) |
| 5 | 3.5 | CloudFront key loading | A: env var only, B: Secrets Manager with fallback | A (simpler for now) | Decided: B (Secrets Manager) — FD-10 |
| 6 | 3.6 | 403 recovery wiring level | A: component-level, B: grid wrapper | B (keeps ImageDisplay pure) | Decided: B + shared hook — FD-16 |
| 7 | 3.6 | QueryClient in test-utils | A: shared wrapper, B: per-test | A (consistent) | Decided: A |
Acceptance Checklist
Section titled “Acceptance Checklist”Before declaring the project complete (end of Phase 3.7), verify:
- All 61 requirements in verification.md have status Pass
- All phase exit criteria met
- All review gates passed
- No regressions in existing functionality across all repos
- CHANGELOGs updated for
api-proxy,ux-prototype,arda-frontend-app,operations - All PRs merged (merge ordering: documentation → operations → arda-frontend-app)
- Worktrees removed, local branches cleaned up
- Open questions table above: all resolved or deferred with ticket
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved