Files
2026-07-10 23:08:59 +02:00

14 KiB
Raw Permalink Blame 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)

# 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)

# 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

# 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)

# 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)

// 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)

# 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)

# 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

# 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)

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)