231 lines
7.8 KiB
Markdown
231 lines
7.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
This is a cloud photo and video storage service with a React frontend (SPA hosted in S3) and a Python FastAPI backend. The project uses S3 for file storage and starts with SQLite for metadata, with a migration path to PostgreSQL.
|
|
|
|
**Primary Language:** Russian (comments and documentation may be in Russian)
|
|
|
|
## Tech Stack
|
|
|
|
### Backend
|
|
- **Framework:** FastAPI (ASGI)
|
|
- **ORM:** SQLAlchemy 2.x (async) with Alembic migrations
|
|
- **Database:** SQLite (MVP) → PostgreSQL (future)
|
|
- **S3 SDK:** boto3 or aioboto3
|
|
- **Authentication:** JWT (access + refresh tokens)
|
|
- **Background Tasks:** Redis + RQ (recommended for thumbnail generation)
|
|
- **Testing:** pytest + httpx
|
|
- **Linting/Formatting:** ruff + black (or ruff format)
|
|
|
|
### Frontend
|
|
- **Framework:** React
|
|
- **UI Library:** Material UI (MUI)
|
|
- **Build Tool:** Vite
|
|
- **Deployment:** Static files in `static/` folder → S3 hosting
|
|
|
|
### Infrastructure
|
|
- **File Storage:** S3 or S3-compatible (MinIO for development)
|
|
- **Queue:** Redis (for background workers)
|
|
|
|
## Architecture Principles
|
|
|
|
### Layered Architecture (Clean Architecture)
|
|
The backend follows strict separation of concerns:
|
|
|
|
- **`api/`** - Routes, schemas, dependencies, auth middleware
|
|
- **`services/`** - Business logic (upload, library, share management)
|
|
- **`repositories/`** - Data access layer (CRUD operations)
|
|
- **`infra/`** - S3 client, database session factory, config, background tasks
|
|
- **`domain/`** - Domain models and interfaces (as needed)
|
|
|
|
### Code Quality Standards
|
|
- **SOLID principles** are mandatory
|
|
- **DRY (Don't Repeat Yourself)**
|
|
- **Docstrings required** for all public methods/classes and main services
|
|
- **Minimal code comments** - prefer self-documenting code and docstrings
|
|
- **Stable API contract** - maintain OpenAPI/Swagger compatibility
|
|
|
|
### Security Requirements
|
|
- Never store passwords in plaintext - use argon2id or bcrypt
|
|
- All S3 access must use pre-signed URLs with short TTL
|
|
- Validate all input with Pydantic
|
|
- Check asset ownership in all endpoints
|
|
- CORS must be strictly configured
|
|
- CSRF protection for cookie-based auth
|
|
|
|
## Planned Project Structure
|
|
|
|
```
|
|
repo/
|
|
backend/
|
|
src/
|
|
app/
|
|
api/
|
|
v1/ # API routes versioned
|
|
services/ # Business logic layer
|
|
repositories/ # Data access layer
|
|
infra/ # Infrastructure (S3, DB, config)
|
|
domain/ # Domain models
|
|
main.py # Application entry point
|
|
alembic/ # Database migrations
|
|
tests/
|
|
pyproject.toml
|
|
Dockerfile
|
|
frontend/
|
|
src/
|
|
public/
|
|
vite.config.js
|
|
package.json
|
|
static/ # Build output (deployed to S3)
|
|
docker-compose.yml
|
|
```
|
|
|
|
## Data Model
|
|
|
|
### Core Entities
|
|
|
|
**users**: User accounts (id, email, password_hash, created_at, updated_at, is_active)
|
|
|
|
**assets**: Media files with metadata
|
|
- Type: photo | video
|
|
- Status: uploading | ready | failed | deleted
|
|
- Includes: original_filename, content_type, size_bytes, sha256, captured_at
|
|
- S3 keys: storage_key_original, storage_key_thumb
|
|
- Soft delete support via deleted_at
|
|
|
|
**shares**: Public/private sharing links
|
|
- Links to either a single asset or album
|
|
- Supports expiration (expires_at) and revocation (revoked_at)
|
|
- Optional password protection
|
|
|
|
**albums** (v1): Logical grouping of assets
|
|
|
|
**tags** (v1): Tagging system for assets
|
|
|
|
## S3 Storage Structure
|
|
|
|
- **Bucket:** Private, access only via pre-signed URLs
|
|
- **Original files:** `u/{user_id}/o/{yyyy}/{mm}/{asset_id}{ext}`
|
|
- **Thumbnails:** `u/{user_id}/t/{yyyy}/{mm}/{asset_id}.jpg`
|
|
- **Video posters (v1):** `u/{user_id}/p/{yyyy}/{mm}/{asset_id}.jpg`
|
|
|
|
## Upload Flow
|
|
|
|
1. Frontend requests `POST /api/v1/uploads/create` with file metadata
|
|
2. Backend returns pre-signed URL or multipart upload credentials
|
|
3. Frontend uploads file directly to S3
|
|
4. Frontend calls `POST /api/v1/uploads/{asset_id}/finalize`
|
|
5. Backend saves metadata and enqueues thumbnail generation task
|
|
|
|
## API Structure
|
|
|
|
Base path: `/api/v1`
|
|
|
|
### Authentication
|
|
- `POST /api/v1/auth/register`
|
|
- `POST /api/v1/auth/login`
|
|
- `POST /api/v1/auth/logout`
|
|
- `GET /api/v1/auth/me`
|
|
|
|
### Assets (Library)
|
|
- `GET /api/v1/assets` - List with cursor-based pagination
|
|
- `GET /api/v1/assets/{asset_id}`
|
|
- `DELETE /api/v1/assets/{asset_id}` - Soft delete
|
|
- `POST /api/v1/assets/{asset_id}/restore`
|
|
- `DELETE /api/v1/assets/{asset_id}/purge` - Hard delete from trash
|
|
|
|
### Upload
|
|
- `POST /api/v1/uploads/create`
|
|
- `POST /api/v1/uploads/{asset_id}/finalize`
|
|
|
|
### Access URLs
|
|
- `GET /api/v1/assets/{asset_id}/download-url?kind=original|thumb`
|
|
- `GET /api/v1/assets/{asset_id}/stream-url` - For video
|
|
|
|
### Shares
|
|
- `POST /api/v1/shares` - Create share link
|
|
- `GET /api/v1/shares/{token}`
|
|
- `GET /api/v1/shares/{token}/download-url?asset_id=&kind=`
|
|
- `POST /api/v1/shares/{token}/revoke`
|
|
|
|
## Environment Variables
|
|
|
|
Key backend environment variables (see [tech_spec_cloud_media_storage.md](tech_spec_cloud_media_storage.md) section 13 for full list):
|
|
|
|
- `APP_ENV=dev|prod`
|
|
- `DATABASE_URL=sqlite+aiosqlite:///./app.db` (or PostgreSQL connection string)
|
|
- `S3_ENDPOINT_URL` - For MinIO or custom S3-compatible storage
|
|
- `S3_REGION`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`
|
|
- `MEDIA_BUCKET` - S3 bucket name
|
|
- `SIGNED_URL_TTL_SECONDS=600`
|
|
- `JWT_SECRET`, `JWT_ACCESS_TTL_SECONDS`, `JWT_REFRESH_TTL_SECONDS`
|
|
- `MAX_UPLOAD_SIZE_BYTES` - File size limit
|
|
- `CORS_ORIGINS` - Allowed frontend origins
|
|
|
|
## Database Migrations
|
|
|
|
- All schema changes MUST go through Alembic migrations
|
|
- No raw SQL in application code (except migrations)
|
|
- Schema must be compatible with both SQLite (MVP) and PostgreSQL
|
|
- UUID stored as TEXT in SQLite, native UUID in PostgreSQL
|
|
|
|
## Development Workflow (When Implemented)
|
|
|
|
### Backend Development
|
|
Expected commands once backend is set up:
|
|
- Start server: `uvicorn app.main:app --reload`
|
|
- Run tests: `pytest`
|
|
- Create migration: `alembic revision --autogenerate -m "description"`
|
|
- Apply migrations: `alembic upgrade head`
|
|
- Format code: `ruff format .` or `black .`
|
|
- Lint: `ruff check .`
|
|
|
|
### Frontend Development
|
|
Expected commands once frontend is set up:
|
|
- Install dependencies: `npm install`
|
|
- Dev server: `npm run dev`
|
|
- Build for production: `npm run build` (outputs to `static/`)
|
|
- Lint: `npm run lint`
|
|
|
|
### Docker Compose (Development)
|
|
Recommended setup: `docker-compose up` to start:
|
|
- Backend service
|
|
- MinIO (S3-compatible storage)
|
|
- Redis (for background tasks)
|
|
- PostgreSQL (when migrating from SQLite)
|
|
|
|
## MVP Acceptance Criteria
|
|
|
|
- User registration and authentication working
|
|
- Upload photo and video files (including batch upload of 100+ files)
|
|
- Library displays thumbnails for photos
|
|
- Photo/video viewer works in browser
|
|
- Soft delete to trash with restore capability
|
|
- Public share links work without authentication
|
|
- SQLite database with migration path to PostgreSQL ready
|
|
|
|
## Implementation Phases
|
|
|
|
1. **Foundation:** FastAPI skeleton, DB config, migrations, auth
|
|
2. **Assets:** CRUD for assets, library listing with pagination, trash management
|
|
3. **Frontend MVP:** Login, library grid, upload dialog, viewer, trash UI
|
|
4. **Thumbnails:** Background generation and display
|
|
5. **Shares:** Create and access share links, shared view UI
|
|
|
|
## Important Notes
|
|
|
|
- This project follows **Clean Architecture** - respect layer boundaries
|
|
- All file access goes through **pre-signed S3 URLs**, never direct access
|
|
- Use **cursor-based pagination** for listing endpoints
|
|
- **Thumbnails reduce bandwidth** - originals loaded only on demand
|
|
- For large files, use **S3 multipart upload**
|
|
- Background tasks via **Redis + RQ** for thumbnail/poster generation
|
|
- Support both **inline** (MVP acceptable) and **background** thumbnail generation
|
|
|
|
## Reference Documentation
|
|
|
|
For detailed technical requirements, see [tech_spec_cloud_media_storage.md](tech_spec_cloud_media_storage.md).
|