Redesign
This commit is contained in:
118
docs/redesign/PHASE-03-FILESYSTEM-STORAGE.md
Normal file
118
docs/redesign/PHASE-03-FILESYSTEM-STORAGE.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Phase 3: Filesystem Storage Migration
|
||||
|
||||
## Agent Assignment
|
||||
**Primary Agent:** storage-agent
|
||||
**Duration:** 30-40 minutes
|
||||
|
||||
## Prerequisites
|
||||
- None (can start immediately)
|
||||
|
||||
## Objectives
|
||||
1. Create filesystem storage adapter
|
||||
2. Replace MinIO adapter with filesystem
|
||||
3. Update documents feature to use filesystem
|
||||
4. Verify document upload/download works
|
||||
|
||||
## Step-by-Step Instructions
|
||||
|
||||
### Step 1: Create Filesystem Adapter
|
||||
Create `backend/src/core/storage/adapters/filesystem.adapter.ts`:
|
||||
|
||||
```typescript
|
||||
import { StorageService } from '../storage.service';
|
||||
import * as fs from 'fs/promises';
|
||||
import * as path from 'path';
|
||||
import { createReadStream } from 'fs';
|
||||
|
||||
export class FilesystemAdapter implements StorageService {
|
||||
private basePath: string;
|
||||
|
||||
constructor(basePath: string = '/app/data/documents') {
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
async putObject(bucket: string, key: string, body: Buffer, contentType?: string): Promise<void> {
|
||||
const filePath = path.join(this.basePath, key);
|
||||
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
||||
await fs.writeFile(filePath, body);
|
||||
}
|
||||
|
||||
async getObjectStream(bucket: string, key: string): Promise<NodeJS.ReadableStream> {
|
||||
const filePath = path.join(this.basePath, key);
|
||||
return createReadStream(filePath);
|
||||
}
|
||||
|
||||
async deleteObject(bucket: string, key: string): Promise<void> {
|
||||
const filePath = path.join(this.basePath, key);
|
||||
await fs.unlink(filePath);
|
||||
}
|
||||
|
||||
async headObject(bucket: string, key: string): Promise<any> {
|
||||
const filePath = path.join(this.basePath, key);
|
||||
const stats = await fs.stat(filePath);
|
||||
return { size: stats.size, lastModified: stats.mtime };
|
||||
}
|
||||
|
||||
async getSignedUrl(bucket: string, key: string): Promise<string> {
|
||||
// Not needed for filesystem, return direct path
|
||||
return `/api/documents/download/${key}`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Update Storage Service Factory
|
||||
Modify `backend/src/core/storage/storage.service.ts`:
|
||||
|
||||
```typescript
|
||||
import { FilesystemAdapter } from './adapters/filesystem.adapter';
|
||||
|
||||
export function getStorageService(): StorageService {
|
||||
// Always use filesystem adapter
|
||||
return new FilesystemAdapter('/app/data/documents');
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Verify Documents Feature
|
||||
No changes needed to documents.controller.ts - it uses StorageService interface.
|
||||
|
||||
Storage keys will be filesystem paths:
|
||||
`documents/{userId}/{vehicleId}/{documentId}/{filename}`
|
||||
|
||||
### Step 4: Test Document Upload
|
||||
```bash
|
||||
# Rebuild backend
|
||||
cd backend && npm run build
|
||||
|
||||
# Restart backend
|
||||
docker compose restart mvp-backend
|
||||
|
||||
# Test upload (requires authentication)
|
||||
curl -X POST https://admin.motovaultpro.com/api/documents \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@test.pdf" \
|
||||
-F "vehicleId=123"
|
||||
|
||||
# Verify file exists
|
||||
docker compose exec mvp-backend ls -la /app/data/documents/
|
||||
```
|
||||
|
||||
## Validation Criteria
|
||||
- [ ] FilesystemAdapter created
|
||||
- [ ] getStorageService returns FilesystemAdapter
|
||||
- [ ] Document upload works
|
||||
- [ ] Document download works
|
||||
- [ ] Files stored in /app/data/documents/
|
||||
- [ ] No MinIO references in code
|
||||
|
||||
**Validation Command:**
|
||||
```bash
|
||||
grep -r "minio\|MinIO" backend/src/ | wc -l
|
||||
# Expected: 0
|
||||
```
|
||||
|
||||
## Update EXECUTION-STATE.json
|
||||
```json
|
||||
{
|
||||
"phases": {"3": {"status": "completed", "validation_passed": true}}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user