Files
motovaultpro/docs/redesign/PHASE-03-FILESYSTEM-STORAGE.md
Eric Gullickson 046c66fc7d Redesign
2025-11-01 21:27:42 -05:00

119 lines
3.2 KiB
Markdown

# 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}}
}
```