From 2d31680072f9bee536381d6057fda890b6ec80e5 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Sun, 5 Apr 2026 12:24:17 +0200 Subject: [PATCH] docs(17-02): complete server-side storage integration plan - SUMMARY.md with 2 task commits documented - STATE.md updated with progress and decision - ROADMAP.md updated with plan progress - REQUIREMENTS.md updated (IMG-01, IMG-03 complete) --- .planning/REQUIREMENTS.md | 4 +- .planning/ROADMAP.md | 8 +- .planning/STATE.md | 17 +-- .../phases/17-object-storage/17-02-SUMMARY.md | 124 ++++++++++++++++++ 4 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 .planning/phases/17-object-storage/17-02-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 815f2c2..72b74a0 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -36,7 +36,7 @@ Requirements for this milestone. Each maps to roadmap phases. - [x] **IMG-01**: Images are stored in MinIO (S3-compatible) instead of local filesystem - [ ] **IMG-02**: Existing uploaded images are migrated to MinIO -- [ ] **IMG-03**: Image upload and retrieval work through the new storage layer +- [x] **IMG-03**: Image upload and retrieval work through the new storage layer - [x] **IMG-04**: Docker Compose provides MinIO for local development ### Global Item Database @@ -134,7 +134,7 @@ Which phases cover which requirements. Updated during roadmap creation. | MULTI-06 | Phase 16 | Pending | | IMG-01 | Phase 17 | Complete | | IMG-02 | Phase 17 | Pending | -| IMG-03 | Phase 17 | Pending | +| IMG-03 | Phase 17 | Complete | | IMG-04 | Phase 17 | Complete | | GLOB-01 | Phase 18 | Pending | | GLOB-02 | Phase 18 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 60550e5..987dbda 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -161,10 +161,10 @@ Plans: 2. All previously uploaded images are accessible after migration to MinIO (no broken images) 3. Image URLs work correctly in all views (collection, planning, setups, comparison table) 4. Docker Compose includes MinIO for local development with no manual bucket setup required -**Plans:** 3 plans +**Plans:** 2/3 plans executed Plans: -- [ ] 17-01-PLAN.md — Storage service abstraction + Docker Compose MinIO infrastructure -- [ ] 17-02-PLAN.md — Server-side image handling refactoring (routes, services, MCP tools) +- [x] 17-01-PLAN.md — Storage service abstraction + Docker Compose MinIO infrastructure +- [x] 17-02-PLAN.md — Server-side image handling refactoring (routes, services, MCP tools) - [ ] 17-03-PLAN.md — Client component updates + image migration script ### Phase 18: Global Items & Public Profiles @@ -200,5 +200,5 @@ Plans: | 14. PostgreSQL Migration | v2.0 | 0/? | Not started | - | | 15. External Authentication | v2.0 | 0/? | Not started | - | | 16. Multi-User Data Model | v2.0 | 2/4 | Complete | 2026-04-05 | -| 17. Object Storage | v2.0 | 0/3 | Not started | - | +| 17. Object Storage | v2.0 | 2/3 | In Progress| | | 18. Global Items & Public Profiles | v2.0 | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index 4575dae..54280c5 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.3 milestone_name: Research & Decision Tools status: planning -stopped_at: Completed 17-01-PLAN.md -last_updated: "2026-04-05T10:17:07.581Z" +stopped_at: Completed 17-02-PLAN.md +last_updated: "2026-04-05T10:24:04.581Z" last_activity: 2026-04-03 — v2.0 roadmap created (Phases 14-18) progress: - total_phases: 8 - completed_phases: 6 - total_plans: 12 - completed_plans: 11 + total_phases: 11 + completed_phases: 9 + total_plans: 28 + completed_plans: 25 percent: 0 --- @@ -55,6 +55,7 @@ Key decisions made during v2.0 planning: - Separate globalItems table — not a flag on user items table - Single-user SQLite mode diverges at v2.0 boundary - [Phase 17]: Private S3 bucket with presigned URLs (1h default), MinIO pinned to quay.io RELEASE.2025-09-07 +- [Phase 17]: Image URL enrichment at route level, not service level, keeping services storage-agnostic ### Pending Todos @@ -67,6 +68,6 @@ None active. ## Session Continuity -Last session: 2026-04-05T10:17:07.579Z -Stopped at: Completed 17-01-PLAN.md +Last session: 2026-04-05T10:24:04.579Z +Stopped at: Completed 17-02-PLAN.md Resume file: None diff --git a/.planning/phases/17-object-storage/17-02-SUMMARY.md b/.planning/phases/17-object-storage/17-02-SUMMARY.md new file mode 100644 index 0000000..5a6f38b --- /dev/null +++ b/.planning/phases/17-object-storage/17-02-SUMMARY.md @@ -0,0 +1,124 @@ +--- +phase: 17-object-storage +plan: 02 +subsystem: api +tags: [s3, minio, image-upload, presigned-urls, object-storage] + +requires: + - phase: 17-object-storage + provides: "S3 storage service (uploadImage, deleteImage, getImageUrl, withImageUrl, withImageUrls)" +provides: + - "All server image operations routed through S3 storage service" + - "API responses enriched with presigned imageUrl fields" + - "Static /uploads/* serving removed from server" +affects: [17-object-storage, client-image-display] + +tech-stack: + added: [] + patterns: ["withImageUrl/withImageUrls enrichment on API responses", "deleteImage in delete handlers"] + +key-files: + created: [] + modified: + - src/server/services/image.service.ts + - src/server/routes/images.ts + - src/server/routes/items.ts + - src/server/routes/threads.ts + - src/server/routes/setups.ts + - src/server/index.ts + - src/server/mcp/tools/items.ts + - src/server/mcp/tools/threads.ts + - src/server/mcp/tools/images.ts + - tests/services/image.service.test.ts + - tests/routes/images.test.ts + +key-decisions: + - "Enrich responses at route level (not service level) to keep services storage-agnostic" + - "Setup items enriched via withImageUrls on GET /:id only (list doesn't include item images)" + +patterns-established: + - "Image URL enrichment: wrap service results with withImageUrl/withImageUrls before returning JSON" + - "Image cleanup: call deleteImage() in try/catch on entity deletion (missing object = silent)" + +requirements-completed: [IMG-01, IMG-03] + +duration: 4min +completed: 2026-04-05 +--- + +# Phase 17 Plan 02: Server-Side Storage Integration Summary + +**Replaced all local filesystem image operations with S3 storage service calls across routes, services, and MCP tools** + +## Performance + +- **Duration:** 4 min +- **Started:** 2026-04-05T10:19:05Z +- **Completed:** 2026-04-05T10:22:45Z +- **Tasks:** 2 +- **Files modified:** 11 + +## Accomplishments +- All image uploads (direct file and URL fetch) now go through S3 storage service +- All image deletions (item delete, candidate delete, thread delete) use deleteImage() instead of unlink() +- API responses for items, threads, setups, and MCP tools enriched with presigned imageUrl fields +- Static /uploads/* serving removed from server entry point + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Refactor image service and routes to use storage service** - `5ce3f92` (feat) +2. **Task 2: Wire storage into all routes and MCP tools, remove static serving** - `f5d7907` (feat) + +## Files Created/Modified +- `src/server/services/image.service.ts` - Replaced Bun.write/mkdir with uploadImage() call +- `src/server/routes/images.ts` - Replaced local write with uploadImage() for direct uploads +- `src/server/routes/items.ts` - deleteImage() on delete, withImageUrl(s) on GET responses +- `src/server/routes/threads.ts` - deleteImage() on delete, withImageUrls on GET thread candidates +- `src/server/routes/setups.ts` - withImageUrls on GET setup items +- `src/server/index.ts` - Removed /uploads/* static file serving line +- `src/server/mcp/tools/items.ts` - withImageUrl/withImageUrls on list and get tool responses +- `src/server/mcp/tools/threads.ts` - withImageUrls on get_thread candidate responses +- `src/server/mcp/tools/images.ts` - Updated description text (local -> storage) +- `tests/services/image.service.test.ts` - Mock storage service, verify uploadImage calls +- `tests/routes/images.test.ts` - Mock storage service, added upload test + +## Decisions Made +- Enrichment happens at route/handler level, not service level, keeping services storage-agnostic +- Setup list endpoint not enriched (doesn't return item images), only setup detail GET /:id + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Removed unused withImageUrl import from threads.ts** +- **Found during:** Task 2 (lint check) +- **Issue:** Imported withImageUrl but only used withImageUrls in threads route +- **Fix:** Removed unused import to pass lint +- **Files modified:** src/server/routes/threads.ts +- **Committed in:** f5d7907 (part of Task 2 commit) + +--- + +**Total deviations:** 1 auto-fixed (1 bug/unused import) +**Impact on plan:** Trivial cleanup. No scope creep. + +## Issues Encountered +None + +## Known Stubs +None - all image operations fully wired to storage service. + +## User Setup Required +None - no additional external service configuration required (MinIO setup was done in Plan 01). + +## Next Phase Readiness +- Server-side storage integration complete +- Ready for Plan 03: client-side refactoring to use presigned imageUrl from API responses instead of /uploads/ paths + +--- +*Phase: 17-object-storage* +*Completed: 2026-04-05* + +## Self-Check: PASSED