"description":"Nuxt 3 project setup with Tailwind CSS, design tokens (CSS custom properties for A0 Dark Theme + Orange accent), base layout (AppHeader sticky with mobile burger, AppFooter 4-column), HmsLogo SVG component, robots.txt (Disallow all), error page (404/500), and global meta tags (noindex/nofollow/noarchive/nosnippet, OpenGraph, JSON-LD LocalBusiness on home). Includes nuxt.config.ts with routeRules (SSG/SSR strategy), tailwind.config.ts with custom theme, app.vue, layouts/default.vue, server middleware for noindex headers, and all shared components: LoadingSkeleton, EmptyState, ErrorState, LegalContentPage, SpeakerIcon.",
"expected_results":"Build succeeds. All Vitest tests pass. Playwright E2E for header/footer/404 pass. robots.txt contains 'Disallow: /'. Home page HTML contains noindex meta tag. Home page HTML contains JSON-LD LocalBusiness schema. Non-existent route returns 404 page with home link.",
"test_files":[
"frontend/tests/unit/Layout.test.ts",
"frontend/tests/unit/DesignTokens.test.ts",
"frontend/tests/e2e/header-footer.spec.ts",
"frontend/tests/e2e/error-pages.spec.ts",
"frontend/tests/e2e/meta-robots.spec.ts"
],
"coverage_target":80
},
"acceptance_criteria":[
"npm run build exits with code 0",
"AppHeader is sticky (position: sticky) and contains nav items: Home, Referenzen, Mietkatalog, Kontakt",
"AppHeader mobile burger menu opens/closes on click, items have min 44px touch targets",
"expected_results":"Build succeeds. All Vitest tests pass. Playwright E2E for all static pages pass. Home page contains hero headline and 8 service cards. Referenzen page loads gallery with 9 images and filter chips. Kontakt page has form with required fields and privacy checkbox. Legal pages contain correct legal text. Contact form validates: empty email blocked, no privacy consent blocked.",
"test_files":[
"frontend/tests/unit/HomePage.test.ts",
"frontend/tests/unit/ReferenzenPage.test.ts",
"frontend/tests/unit/KontaktPage.test.ts",
"frontend/tests/e2e/home.spec.ts",
"frontend/tests/e2e/referenzen.spec.ts",
"frontend/tests/e2e/kontakt.spec.ts",
"frontend/tests/e2e/legal-pages.spec.ts"
],
"coverage_target":80
},
"acceptance_criteria":[
"Home page renders hero with headline containing 'Veranstaltungstechnik'",
"GET /api/equipment/categories returns 200 with array of category strings",
"GET /api/equipment/{id} returns 200 with full equipment detail for valid ID",
"GET /api/equipment/999999 returns 404",
"Redis caches equipment list (second call faster than first)",
"All 6 DB models defined with correct columns and indexes",
"Alembic migration generates all tables successfully"
]
},
{
"id":"T04",
"title":"Rentman Integration: Import Service + Request Service + Admin Auth & Sync",
"description":"Complete Rentman integration: (1) Import service (rentman_import.py) using RentmanAPI Python client, paginated GET /equipment (limit=100, iterate offset until data empty), upsert into equipment_cache, invalidate Redis cache, sync_log entries. (2) Request service (rentman_request.py) with POST /projectrequests + POST /projectrequests/{id}/projectrequestequipment, retry queue with exponential backoff (max 3 retries), admin notification on failure. (3) Admin auth: JWT login (auth_service.py, python-jose, HS256, HttpOnly cookie), admin router (POST /api/admin/login, GET /api/admin/me, POST /api/admin/sync, GET /api/admin/sync-status, GET /api/admin/sync-log). (4) Auth schemas, admin_user model seeding script, rate limiting for login endpoint.",
"expected_results":"All tests pass with >=80% coverage. Contact POST with valid data returns 200. Contact POST with invalid email returns 422. Contact POST without privacy consent returns 422. Rental request POST with valid data returns 201 with reference_number. Rental request with date_end before date_start returns 422. Email service mock sends correct emails. Rate limiting blocks 6th request within 60s.",
"test_files":[
"backend/tests/test_contact_router.py",
"backend/tests/test_rental_router.py",
"backend/tests/test_email_service.py",
"backend/tests/test_rate_limiting.py"
],
"coverage_target":80
},
"acceptance_criteria":[
"POST /api/contact with valid data returns 200 and saves to contacts table",
"POST /api/contact with invalid email returns 422",
"POST /api/contact with privacy_consent=false returns 422",
"POST /api/contact triggers email to info@hms-licht-ton.de",
"POST /api/rental-requests with valid data returns 201 with reference_number (format HMS-YYYY-NNNNN)",
"POST /api/rental-requests with date_end < date_start returns 422",
"POST /api/rental-requests with empty items array returns 422",
"POST /api/rental-requests saves to rental_requests and rental_request_items tables",
"expected_results":"Build succeeds. All Vitest tests pass. Playwright E2E for mietkatalog pass. Mietkatalog page SSR-renders equipment cards in HTML (not just client JS). Search filters results in real-time. Category filter works. Sort changes order. Detail page shows specs and add-to-cart. Non-existent ID shows 404-style error with link back to catalog.",
"expected_results":"Build succeeds. All Vitest tests pass. Playwright E2E for cart and mietanfrage pass. Cart persists in localStorage across page reloads. Adding item updates header counter. Mietanfrage form validates required fields. Submit sends POST /api/rental-requests and shows success with reference_number. Empty cart on mietanfrage shows redirect suggestion.",
"test_files":[
"frontend/tests/unit/CartStore.test.ts",
"frontend/tests/unit/WarenkorbPage.test.ts",
"frontend/tests/unit/MietanfragePage.test.ts",
"frontend/tests/e2e/cart.spec.ts",
"frontend/tests/e2e/mietanfrage.spec.ts"
],
"coverage_target":80
},
"acceptance_criteria":[
"Adding equipment to cart from detail page updates header counter badge",
"Cart items persist in localStorage across page reloads",
"Warenkorb page shows items with quantity steppers and remove buttons",
"Removing all items shows empty state with link to /mietkatalog",
"Header cart icon shows counter (0 when empty, N when items added)",
"CartDrawer opens on mobile as bottom-sheet, on desktop as side panel",
"Mietanfrage page shows cart overview (read-only items with quantities)",
"Mietanfrage form has: event_name*, date_start*, date_end*, location*, contact_name*, contact_email*, message",
"Mietanfrage form blocks submit with validation errors for missing required fields",
"Mietanfrage form blocks submit when date_end < date_start",
"Mietanfrage submit shows 'submitting' state (spinner, disabled fields)",
"Successful submit shows success page with reference_number and 'Zurück zur Startseite' button",
"Failed submit shows error state with retry button",
"Navigating to /mietanfrage with empty cart shows 'Keine Artikel ausgewählt' with link to /mietkatalog",
"expected_results":"Dockerfiles build without errors. docker-compose.yml is valid YAML and passes docker compose config. .env.example contains all required env vars. CI/CD pipeline has test and build steps. README contains setup and deployment instructions.",