Files

500 lines
14 KiB
Markdown
Raw Permalink Normal View History

# AGENTS.md HMS Licht & Ton Build & Test Guide
> **Projekt:** hms-licht-ton (ID 30)
> **Stack:** Nuxt 3 (Frontend) + FastAPI (Backend) + PostgreSQL + Redis
> **Deployment:** Coolify (Docker) auf coolify-01
>
> **DESIGN-RICHTLINIEN:** `docs/design-rules.md` VERBINDLICH für alle Erweiterungen!
> Jeder KI-Agent MUSS diese Regeln vor der Implementierung lesen und einhalten.
---
## 1. Build & Test Commands
### 1.1 Frontend (Nuxt 3)
```bash
# Install dependencies
cd frontend && npm ci
# Development server (http://localhost:3000)
cd frontend && npm run dev
# Production build
cd frontend && npm run build
# Preview production build
cd frontend && npm run preview
# Generate static site (SSG pages)
cd frontend && npm run generate
# Unit tests (Vitest)
cd frontend && npx vitest run --reporter verbose
# Watch mode
cd frontend && npx vitest
# Coverage report
cd frontend && npx vitest run --coverage
# E2E tests (Playwright)
cd frontend && npx playwright test
# Specific E2E test
cd frontend && npx playwright test --grep 'Mietkatalog'
# Lint
cd frontend && npm run lint
# Type check
cd frontend && npm run typecheck
```
### 1.2 Backend (FastAPI)
```bash
# Install dependencies
cd backend && pip install -r requirements.txt
# Development server (http://localhost:8000)
cd backend && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Run all tests
cd backend && python -m pytest tests/ -v
# Run with coverage
cd backend && python -m pytest tests/ -v --cov=app --cov-report=term-missing
# Specific test file
cd backend && python -m pytest tests/test_equipment_router.py -v
# Specific test
cd backend && python -m pytest tests/test_rentman_import.py::test_paginated_import -v
# Database migrations
cd backend && alembic upgrade head
cd backend && alembic revision --autogenerate -m "description"
# Seed admin user
cd backend && python -m app.scripts.seed_admin
```
### 1.3 Docker / Full Stack
```bash
# Build all containers
docker compose build
# Start all services
docker compose up -d
# View logs
docker compose logs -f backend
docker compose logs -f frontend
# Health check
curl -s http://localhost:8000/api/health
# Stop all services
docker compose down
# Reset volumes (DESTRUCTIVE)
docker compose down -v
```
### 1.4 Integration Tests (Full Stack)
```bash
# Start backend + DB + Redis
docker compose up -d backend postgres redis
# Wait for health
curl -s http://localhost:8000/api/health | grep ok
# Run backend tests
cd backend && python -m pytest tests/ -v
# Start frontend
docker compose up -d frontend
# Run E2E tests
cd frontend && npx playwright test
```
---
## 2. Test Rules (MANDATORY)
### 2.1 TDD Principle
- **Write tests first, then implementation.** Tests define the contract.
- Tests MUST be written before or alongside the implementation code.
- Never commit code without corresponding tests.
- Coverage target: **>= 80%** for all modules.
### 2.2 Do NOT Modify Tests
- **Never modify existing tests to make them pass.**
- If a test fails, fix the implementation, not the test.
- Tests are the source of truth for expected behavior.
- If a test is genuinely wrong, flag it in a PR and explain why.
- Only the original test author or a reviewer may modify tests.
### 2.3 Test File Naming
**Frontend:**
- Unit tests: `frontend/tests/unit/*.test.ts`
- E2E tests: `frontend/tests/e2e/*.spec.ts`
- Fixtures: `frontend/tests/fixtures/*`
- Mocks: `frontend/tests/mocks/*`
**Backend:**
- Unit/Integration tests: `backend/tests/test_*.py`
- Fixtures: `backend/tests/conftest.py`
- Factories: `backend/tests/factories.py`
- Mocks: `backend/tests/mocks/`
### 2.4 Test Categories
| Category | Tool | Scope | When to Run |
|----------|------|-------|-------------|
| Unit | Vitest / Pytest | Functions, composables, stores, services | Every commit |
| Component | Vitest + Vue Test Utils | Vue components, props, emits | Every commit |
| Integration | Pytest + TestClient | API endpoints, DB operations | Every commit |
| E2E | Playwright | Full page flows, forms, navigation | Pre-merge, nightly |
| Smoke | curl scripts | API health, endpoints | Post-deploy |
### 2.5 Mocking Rules
- **Rentman API:** Always mock in tests. Never call live Rentman API.
- Use `unittest.mock.patch` or `responses` library
- Mock `GET /equipment` with paginated test data
- Mock `POST /projectrequests` with fake response IDs
- **SMTP:** Always mock email sending in tests.
- Mock `aiosmtplib.send` to capture sent emails
- Verify email content, not actual delivery
- **Database:** Use SQLite in-memory or test PostgreSQL instance.
- Never run tests against production database
- Use separate test database: `DATABASE_URL=sqlite+aiosqlite:///test.db`
---
## 3. Coding Conventions
### 3.1 Frontend (Vue 3 + TypeScript)
```typescript
// Use Composition API with <script setup>
<script setup lang="ts">
import { ref, computed } from 'vue'
// Props with TypeScript types
const props = defineProps<{
item: EquipmentItem
showBadge?: boolean
}>()
// Emits with TypeScript types
const emit = defineEmits<{
'add-to-cart': [item: EquipmentItem]
'click': [id: number]
}>()
// Refs with types
const loading = ref(false)
const error = ref<string | null>(null)
// Computed
const totalPrice = computed(() => items.value.reduce((sum, i) => sum + i.price, 0))
</script>
```
**Rules:**
- Use `<script setup lang="ts">` always
- Use Composition API (not Options API)
- Use Pinia for global state
- Use `useFetch` / `useAsyncData` for SSR data fetching
- Use Tailwind utility classes (no custom CSS unless necessary)
- Use design tokens (CSS variables) for colors, spacing, radius
- Components: PascalCase filenames (`EquipmentCard.vue`)
- Pages: kebab-case filenames (`mietkatalog/[id].vue`)
- Composables: `use` prefix (`useEquipment.ts`)
- Stores: `stores/*.ts` with Pinia defineStore
### 3.2 Backend (Python + FastAPI)
```python
# Use async/await always
async def get_equipment_list(
search: str | None = None,
category: str | None = None,
page: int = 1,
page_size: int = 20,
db: AsyncSession = Depends(get_db),
) -> PaginatedResponse[EquipmentItem]:
...
# Pydantic schemas for all input/output
class EquipmentItem(BaseModel):
id: int
name: str
category: str | None = None
rental_price: Decimal | None = None
available: bool = True
# Type hints everywhere
def calculate_reference_number() -> str:
year = datetime.now().year
random_num = random.randint(1, 99999)
return f"HMS-{year}-{random_num:05d}"
```
**Rules:**
- PEP 8 style (line length 100)
- async/await for all I/O operations (DB, Redis, API calls, SMTP)
- Pydantic v2 for all schemas (input validation, output serialization)
- Type hints on all functions and methods
- Routers in `routers/`, services in `services/`, models in `models/`
- Config via `pydantic-settings` (BaseSettings class)
- Database: SQLAlchemy async with `asyncpg` driver
- No raw SQL in routers (use SQLAlchemy ORM or service layer)
- Error handling: HTTPException with proper status codes
### 3.3 Naming Conventions
| Type | Frontend | Backend |
|------|----------|--------|
| Files | kebab-case (`mietkatalog.vue`) | snake_case (`rentman_import.py`) |
| Components | PascalCase (`EquipmentCard`) | |
| Functions | camelCase (`getEquipmentList`) | snake_case (`get_equipment_list`) |
| Variables | camelCase (`equipmentList`) | snake_case (`equipment_list`) |
| Constants | UPPER_SNAKE (`API_BASE_URL`) | UPPER_SNAKE (`RENTMAN_API_TOKEN`) |
| Classes | PascalCase (`EquipmentItem`) | PascalCase (`EquipmentItem`) |
| CSS | kebab-case (`.equipment-card`) | |
| DB Tables | | snake_case (`equipment_cache`) |
| API Routes | kebab-case (`/api/rental-requests`) | kebab-case (`/api/rental-requests`) |
### 3.4 Git Conventions
- Branch naming: `feature/T01-frontend-foundation`, `fix/equipment-search`
- Commit messages: Conventional Commits
- `feat: add equipment search filter`
- `fix: correct date validation in rental request`
- `test: add equipment router tests`
- `docs: update architecture.md`
- `refactor: extract email service`
- `chore: update dependencies`
- PR: Squash merge, one PR per task
- Never commit secrets (.env, credentials)
---
## 4. Environment Variables
### 4.1 Required (.env)
```bash
# Rentman
RENTMAN_API_TOKEN=your_token_here
# Auth
JWT_SECRET=your_jwt_secret_here
# Database
DATABASE_URL=postgresql+asyncpg://hms:password@localhost:5432/hms
# Redis
REDIS_URL=redis://localhost:6379/0
# SMTP
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=user@example.com
SMTP_PASSWORD=your_password
SMTP_FROM=info@hms-licht-ton.de
# Frontend
NUXT_PUBLIC_API_BASE=http://localhost:8000/api
```
### 4.2 Optional
```bash
# Admin seeding
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change_me_in_production
# CORS
CORS_ORIGINS=https://hms.media-on.de
```
---
## 5. Task Dependencies
```
T01 (Frontend Foundation) ─────┬──> T02 (Static Pages)
├──> T06 (Mietkatalog Frontend) ──> T07 (Cart/Mietanfrage)
T03 (Backend Core) ────────────┼──> T04 (Rentman Integration)
├──> T05 (Email/Contact/Rental Backend)
├──> T06 (Mietkatalog Frontend)
T08 (Docker/CI/CD) ── depends on ALL ──>
```
**Parallel execution:**
- T01 and T03 can start simultaneously (no shared dependencies)
- T02 starts after T01
- T04 starts after T03
- T06 starts after T01 AND T03
- T05 starts after T03 AND T04
- T07 starts after T01 AND T06
- T08 starts after ALL other tasks
---
## 6. Quality Gates
### 6.1 Per-Task Gate
Before a task is marked complete:
- [ ] All test_spec.commands pass
- [ ] Coverage >= target (80%)
- [ ] All acceptance_criteria verified
- [ ] Build succeeds (npm run build / pip install)
- [ ] No linting errors
- [ ] No type errors
### 6.2 Pre-Merge Gate
- [ ] All task tests pass
- [ ] E2E tests pass
- [ ] Docker build succeeds
- [ ] No secrets in code
- [ ] Code review approved
### 6.3 Pre-Deploy Gate
- [ ] All E2E tests pass
- [ ] Health check returns 200
- [ ] Environment variables set in Coolify
- [ ] Domain DNS configured
- [ ] TLS certificate active
---
## 7. Forbidden Patterns
### 7.1 Frontend
- ❌ Options API (`export default { data() { ... } }`)
- ❌ Hardcoded colors (use CSS variables / Tailwind config)
- ❌ Inline styles (use Tailwind classes)
-`localStorage` direct access in components (use Pinia store with persist plugin)
- ❌ Fetching in `mounted()` (use `useAsyncData` / `useFetch` for SSR)
-`any` type (use proper TypeScript types)
- ❌ Console.log in production code
- ❌ Large inline SVG (use separate component files)
### 7.2 Backend
- ❌ Sync I/O in async context (no `requests.get`, use `httpx.AsyncClient`)
- ❌ Raw SQL in routers (use service layer + SQLAlchemy ORM)
- ❌ Hardcoded secrets (use env vars / pydantic-settings)
-`print()` in production code (use `logging`)
- ❌ Missing type hints
- ❌ Missing Pydantic validation (all inputs must be validated)
- ❌ Direct Rentman API calls without going through service layer
- ❌ Missing error handling (no bare `except:`)
- ❌ Synchronous database operations (use async SQLAlchemy)
---
## 8. Project Structure Summary
```
hms-licht-ton/
├── frontend/ (Nuxt 3 + Tailwind CSS)
│ ├── components/ (Vue 3 SFCs)
│ ├── pages/ (File-based routing)
│ ├── stores/ (Pinia stores)
│ ├── composables/ (useXxx composables)
│ ├── layouts/ (Nuxt layouts)
│ ├── assets/ (CSS, images, SVG)
│ ├── tests/ (Vitest + Playwright)
│ └── nuxt.config.ts
├── backend/ (FastAPI + SQLAlchemy + Redis)
│ ├── app/
│ │ ├── main.py
│ │ ├── config.py
│ │ ├── database.py
│ │ ├── models/ (SQLAlchemy models)
│ │ ├── schemas/ (Pydantic schemas)
│ │ ├── routers/ (API endpoints)
│ │ ├── services/ (Business logic)
│ │ └── cache.py (Redis client)
│ ├── tests/ (Pytest)
│ ├── alembic/ (Migrations)
│ └── Dockerfile
├── docs/ (Architecture, requirements, UI design)
├── docker-compose.yml (4 services)
├── .env.example
├── .forgejo/ (CI/CD workflows)
├── AGENTS.md (This file)
└── README.md
```
---
## 9. Key References
- **Architecture:** `docs/architecture.md`
- **Task Graph:** `docs/task_graph.json`
- **Requirements:** `docs/requirements.md`
- **UI Design:** `docs/ui_design.md`
- **Component Inventory:** `docs/component_inventory.md`
- **Rentman API Skills:** `rentman-api-operations` + `rentman-domain-basics` (load before API calls)
- **Rentman Python Client:** `from usr.plugins.rentman.helpers.rentman import RentmanAPI`
---
## 10. Emergency Procedures
### 10.1 Backend Down
1. Check `docker compose logs backend`
2. Check `docker compose ps` (is it running?)
3. Check `curl http://localhost:8000/api/health`
4. If DB issue: `docker compose restart postgres`
5. If Redis issue: `docker compose restart redis`
6. If app crash: `docker compose restart backend`
### 10.2 Frontend Down
1. Check `docker compose logs frontend`
2. Check `docker compose ps`
3. `docker compose restart frontend`
4. If build issue: `cd frontend && npm run build` (check errors)
### 10.3 Rentman API Unreachable
1. Check `RENTMAN_API_TOKEN` in env vars
2. Test token: `curl -H "Authorization: Bearer $TOKEN" https://api.rentman.net/equipment`
3. If expired: Generate new token in Rentman UI
4. Cached equipment still serves from PostgreSQL + Redis
### 10.4 Database Reset (DESTRUCTIVE)
```bash
docker compose down -v
docker compose up -d
cd backend && alembic upgrade head
python -m app.scripts.seed_admin
```
---
## 11. Handoff
- **AGENTS.md status:** COMPLETE
- **All build commands documented:** YES
- **Test rules documented:** YES
- **Conventions documented:** YES
- **Quality gates defined:** YES
- **Ready for implementation:** YES (after Plan Mode transition to `implementation_allowed`)