Files
hms-licht-ton/AGENTS.md
2026-07-10 23:08:59 +02:00

500 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`)