docs(17-01): complete S3 storage service and MinIO infrastructure plan
- Add 17-01-SUMMARY.md with execution results - Update STATE.md with decisions and session info - Mark IMG-01 and IMG-04 requirements complete
This commit is contained in:
@@ -34,10 +34,10 @@ Requirements for this milestone. Each maps to roadmap phases.
|
|||||||
|
|
||||||
### Image Storage
|
### Image Storage
|
||||||
|
|
||||||
- [ ] **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
|
- [ ] **IMG-03**: Image upload and retrieval work through the new storage layer
|
||||||
- [ ] **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
|
||||||
|
|
||||||
@@ -132,10 +132,10 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| MULTI-04 | Phase 16 | Pending |
|
| MULTI-04 | Phase 16 | Pending |
|
||||||
| MULTI-05 | Phase 16 | Pending |
|
| MULTI-05 | Phase 16 | Pending |
|
||||||
| MULTI-06 | Phase 16 | Pending |
|
| MULTI-06 | Phase 16 | Pending |
|
||||||
| IMG-01 | Phase 17 | Pending |
|
| IMG-01 | Phase 17 | Complete |
|
||||||
| IMG-02 | Phase 17 | Pending |
|
| IMG-02 | Phase 17 | Pending |
|
||||||
| IMG-03 | Phase 17 | Pending |
|
| IMG-03 | Phase 17 | Pending |
|
||||||
| IMG-04 | Phase 17 | Pending |
|
| 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 |
|
||||||
| GLOB-03 | Phase 18 | Pending |
|
| GLOB-03 | Phase 18 | Pending |
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
---
|
---
|
||||||
gsd_state_version: 1.0
|
gsd_state_version: 1.0
|
||||||
milestone: v2.0
|
milestone: v1.3
|
||||||
milestone_name: Platform Foundation
|
milestone_name: Research & Decision Tools
|
||||||
status: planning
|
status: planning
|
||||||
stopped_at: null
|
stopped_at: Completed 17-01-PLAN.md
|
||||||
last_updated: "2026-04-03"
|
last_updated: "2026-04-05T10:17:07.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: 5
|
total_phases: 8
|
||||||
completed_phases: 0
|
completed_phases: 6
|
||||||
total_plans: 0
|
total_plans: 12
|
||||||
completed_plans: 0
|
completed_plans: 11
|
||||||
percent: 0
|
percent: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ Progress: [----------] 0% (v2.0 milestone)
|
|||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
**Velocity:**
|
**Velocity:**
|
||||||
|
|
||||||
- Total plans completed: 0 (v2.0 milestone)
|
- Total plans completed: 0 (v2.0 milestone)
|
||||||
- Average duration: --
|
- Average duration: --
|
||||||
- Total execution time: --
|
- Total execution time: --
|
||||||
@@ -46,12 +47,14 @@ Progress: [----------] 0% (v2.0 milestone)
|
|||||||
### Decisions
|
### Decisions
|
||||||
|
|
||||||
Key decisions made during v2.0 planning:
|
Key decisions made during v2.0 planning:
|
||||||
|
|
||||||
- Platform pivot: single-user to multi-user with discovery-first approach
|
- Platform pivot: single-user to multi-user with discovery-first approach
|
||||||
- External auth provider (self-hosted, open-source) — Logto vs Authentik OPEN decision
|
- External auth provider (self-hosted, open-source) — Logto vs Authentik OPEN decision
|
||||||
- SQLite to Postgres migration — required by auth provider and multi-user concurrency
|
- SQLite to Postgres migration — required by auth provider and multi-user concurrency
|
||||||
- Structured UGC only — ratings and predefined fields, no freeform text until moderation
|
- Structured UGC only — ratings and predefined fields, no freeform text until moderation
|
||||||
- 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
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -64,6 +67,6 @@ None active.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-03
|
Last session: 2026-04-05T10:17:07.579Z
|
||||||
Stopped at: v2.0 roadmap created with 5 phases (14-18) covering 30 requirements
|
Stopped at: Completed 17-01-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
99
.planning/phases/17-object-storage/17-01-SUMMARY.md
Normal file
99
.planning/phases/17-object-storage/17-01-SUMMARY.md
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
phase: 17-object-storage
|
||||||
|
plan: 01
|
||||||
|
subsystem: infra
|
||||||
|
tags: [s3, minio, aws-sdk, object-storage, docker, presigned-urls]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires: []
|
||||||
|
provides:
|
||||||
|
- "S3 storage service (uploadImage, deleteImage, getImageUrl, withImageUrl, withImageUrls)"
|
||||||
|
- "MinIO in Docker Compose (dev and prod) with automatic bucket creation"
|
||||||
|
- "S3 environment variable configuration"
|
||||||
|
affects: [17-02, 17-03, image-routes, image-service, mcp-tools]
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added: ["@aws-sdk/client-s3@3.1024.0", "@aws-sdk/s3-request-presigner@3.1024.0", "MinIO (quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z)"]
|
||||||
|
patterns: ["S3Client singleton with forcePathStyle", "Presigned URL injection via withImageUrl/withImageUrls helpers", "Docker Compose init container for bucket creation"]
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created: ["src/server/services/storage.service.ts", "tests/services/storage.service.test.ts"]
|
||||||
|
modified: ["docker-compose.yml", "docker-compose.dev.yml", ".env.example"]
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Private bucket with presigned URLs (1h default, configurable via S3_PRESIGN_EXPIRY)"
|
||||||
|
- "MinIO pinned to quay.io RELEASE.2025-09-07T16-13-09Z (last stable before archival)"
|
||||||
|
- "No console port exposed in production compose"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "S3 storage functions are pure async functions, no HTTP awareness"
|
||||||
|
- "withImageUrl/withImageUrls helpers enrich records with presigned imageUrl field"
|
||||||
|
- "Docker init container pattern using mc CLI for bucket setup"
|
||||||
|
|
||||||
|
requirements-completed: [IMG-01, IMG-04]
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: 2min
|
||||||
|
completed: 2026-04-05
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 17 Plan 01: S3 Storage Service and MinIO Infrastructure Summary
|
||||||
|
|
||||||
|
**S3 storage abstraction with uploadImage/deleteImage/getImageUrl using @aws-sdk/client-s3, plus MinIO in Docker Compose with automatic bucket creation**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 2 min
|
||||||
|
- **Started:** 2026-04-05T10:14:02Z
|
||||||
|
- **Completed:** 2026-04-05T10:16:24Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files modified:** 7
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
- Storage service wrapping @aws-sdk/client-s3 with forcePathStyle for MinIO compatibility
|
||||||
|
- Presigned URL helpers (withImageUrl, withImageUrls) for enriching API responses
|
||||||
|
- MinIO in both Docker Compose files with mc init container for automatic bucket creation
|
||||||
|
- S3 environment variable documentation in .env.example
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Install S3 SDK and create storage service** - `f845f87` (feat)
|
||||||
|
2. **Task 2: Add MinIO to Docker Compose and update env config** - `88f988c` (chore)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
- `src/server/services/storage.service.ts` - S3 storage abstraction with 5 exported functions
|
||||||
|
- `tests/services/storage.service.test.ts` - 8 unit tests with mocked S3Client
|
||||||
|
- `docker-compose.dev.yml` - Added MinIO + minio-init with fixed dev credentials
|
||||||
|
- `docker-compose.yml` - Added MinIO + minio-init with env var credentials, removed uploads volume
|
||||||
|
- `.env.example` - Added S3 configuration section
|
||||||
|
- `package.json` - Added @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner
|
||||||
|
- `bun.lock` - Updated lockfile
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
- Private bucket with presigned URLs (no public-read) for security
|
||||||
|
- 1-hour presigned URL expiry default, configurable via S3_PRESIGN_EXPIRY env var
|
||||||
|
- No console port (9001) exposed in production compose, only API port (9000)
|
||||||
|
- Dev compose uses fixed minioadmin/minioadmin credentials for simplicity
|
||||||
|
- Production compose removed uploads volume (replaced by MinIO object storage)
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None - plan executed exactly as written.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
None
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
None - no external service configuration required. MinIO starts automatically via Docker Compose.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
- Storage service ready for Plan 02 (image route refactoring) to call uploadImage/deleteImage/getImageUrl
|
||||||
|
- withImageUrl/withImageUrls helpers ready for API response enrichment
|
||||||
|
- Docker Compose MinIO available for integration testing
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 17-object-storage*
|
||||||
|
*Completed: 2026-04-05*
|
||||||
Reference in New Issue
Block a user