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)
This commit is contained in:
@@ -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
|
- [x] **IMG-01**: Images are stored in MinIO (S3-compatible) instead of local filesystem
|
||||||
- [ ] **IMG-02**: Existing uploaded images are migrated to MinIO
|
- [ ] **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
|
- [x] **IMG-04**: Docker Compose provides MinIO for local development
|
||||||
|
|
||||||
### Global Item Database
|
### Global Item Database
|
||||||
@@ -134,7 +134,7 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| MULTI-06 | Phase 16 | Pending |
|
| MULTI-06 | Phase 16 | Pending |
|
||||||
| IMG-01 | Phase 17 | Complete |
|
| IMG-01 | Phase 17 | Complete |
|
||||||
| IMG-02 | Phase 17 | Pending |
|
| IMG-02 | Phase 17 | Pending |
|
||||||
| IMG-03 | Phase 17 | Pending |
|
| IMG-03 | Phase 17 | Complete |
|
||||||
| IMG-04 | Phase 17 | Complete |
|
| IMG-04 | Phase 17 | Complete |
|
||||||
| GLOB-01 | Phase 18 | Pending |
|
| GLOB-01 | Phase 18 | Pending |
|
||||||
| GLOB-02 | Phase 18 | Pending |
|
| GLOB-02 | Phase 18 | Pending |
|
||||||
|
|||||||
@@ -161,10 +161,10 @@ Plans:
|
|||||||
2. All previously uploaded images are accessible after migration to MinIO (no broken images)
|
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)
|
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
|
4. Docker Compose includes MinIO for local development with no manual bucket setup required
|
||||||
**Plans:** 3 plans
|
**Plans:** 2/3 plans executed
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 17-01-PLAN.md — Storage service abstraction + Docker Compose MinIO infrastructure
|
- [x] 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-02-PLAN.md — Server-side image handling refactoring (routes, services, MCP tools)
|
||||||
- [ ] 17-03-PLAN.md — Client component updates + image migration script
|
- [ ] 17-03-PLAN.md — Client component updates + image migration script
|
||||||
|
|
||||||
### Phase 18: Global Items & Public Profiles
|
### Phase 18: Global Items & Public Profiles
|
||||||
@@ -200,5 +200,5 @@ Plans:
|
|||||||
| 14. PostgreSQL Migration | v2.0 | 0/? | Not started | - |
|
| 14. PostgreSQL Migration | v2.0 | 0/? | Not started | - |
|
||||||
| 15. External Authentication | 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 |
|
| 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 | - |
|
| 18. Global Items & Public Profiles | v2.0 | 0/? | Not started | - |
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.3
|
milestone: v1.3
|
||||||
milestone_name: Research & Decision Tools
|
milestone_name: Research & Decision Tools
|
||||||
status: planning
|
status: planning
|
||||||
stopped_at: Completed 17-01-PLAN.md
|
stopped_at: Completed 17-02-PLAN.md
|
||||||
last_updated: "2026-04-05T10:17:07.581Z"
|
last_updated: "2026-04-05T10:24:04.581Z"
|
||||||
last_activity: 2026-04-03 — v2.0 roadmap created (Phases 14-18)
|
last_activity: 2026-04-03 — v2.0 roadmap created (Phases 14-18)
|
||||||
progress:
|
progress:
|
||||||
total_phases: 8
|
total_phases: 11
|
||||||
completed_phases: 6
|
completed_phases: 9
|
||||||
total_plans: 12
|
total_plans: 28
|
||||||
completed_plans: 11
|
completed_plans: 25
|
||||||
percent: 0
|
percent: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -55,6 +55,7 @@ Key decisions made during v2.0 planning:
|
|||||||
- Separate globalItems table — not a flag on user items table
|
- Separate globalItems table — not a flag on user items table
|
||||||
- Single-user SQLite mode diverges at v2.0 boundary
|
- 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]: 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
|
### Pending Todos
|
||||||
|
|
||||||
@@ -67,6 +68,6 @@ None active.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-05T10:17:07.579Z
|
Last session: 2026-04-05T10:24:04.579Z
|
||||||
Stopped at: Completed 17-01-PLAN.md
|
Stopped at: Completed 17-02-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
124
.planning/phases/17-object-storage/17-02-SUMMARY.md
Normal file
124
.planning/phases/17-object-storage/17-02-SUMMARY.md
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user