Files
leocrm-bot 3cc0b2e1b4 phase2: architecture, task_graph v2.1.0, AGENTS.md, quality gates, security review
- architecture.md (2019 lines): 73/73 v1 features, RLS policies, CORS, auth rate limiting, v2 FKs removed
- task_graph.json v2.1.0: 14 tasks (7 v1 + 7 v2), 143 features, 298 ACs, all dict test_specs
- AGENTS.md: 14 tasks mapped, T07a/T07b split, v1/v2 phase plan
- Quality gate reviews: Round 1, 2, 3 (all passed)
- Security review: APPROVED_WITH_CONCERNS (0 critical, 7 major, 8 minor)
- Architecture feasibility review: FEASIBLE_WITH_RISKS (3 critical fixed, 5 major fixed)
- All 3 critical issues from feasibility review resolved
- All pre-implementation security items addressed
2026-06-28 23:07:29 +02:00

24 KiB
Raw Permalink Blame History

LeoCRM — AGENTS.md

Projekt: leocrm Erstellt: 2026-06-28 Status: Draft — ready for implementation


1. Build & Test Commands

Backend (Python / FastAPI)

Setup

cd backend
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Run Dev Server

cd backend
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Database Migrations (Alembic)

cd backend
# Generate migration after model changes
alembic revision --autogenerate -m "description"
# Apply migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1

Run All Backend Tests

cd backend
python -m pytest -v --tb=short

Run Specific Test File

cd backend
python -m pytest tests/test_auth.py -v --tb=short

Run Tests with Coverage

cd backend
python -m pytest --cov=app --cov-report=term-missing --cov-report=html

Run Tests with Grep Filter

cd backend
python -m pytest -k 'tenant or auth' -v

Type Checking

cd backend
mypy app/ --ignore-missing-imports

Linting

cd backend
ruff check app/
ruff format app/

Frontend (React / Vite / TypeScript)

Setup

cd frontend
npm install

Run Dev Server

cd frontend
npm run dev

Build Production

cd frontend
npm run build

Run All Frontend Tests

cd frontend
npx vitest run --reporter=verbose

Run Tests with Coverage

cd frontend
npx vitest run --coverage

Run Tests in Watch Mode (dev)

cd frontend
npx vitest watch

Type Checking

cd frontend
npx tsc --noEmit

Linting

cd frontend
npx eslint src/ --ext .ts,.tsx

Docker Compose (Full Stack)

Build All Services

docker compose build

Start All Services

docker compose up -d

View Logs

docker compose logs -f backend

Stop All Services

docker compose down

Validate Compose Config

docker compose config --quiet

E2E Tests (Playwright)

cd e2e
npx playwright install
npx playwright test

2. Test Rules

TDD (Test-Driven Development)

  • Red-Green-Refactor: Write failing test first → implement minimum code to pass → refactor.
  • Every new endpoint gets a test BEFORE implementation.
  • Every bug fix starts with a reproduction test.

Coverage Targets

Layer Coverage Target Measured By
Backend Core (app/core/) 85% pytest-cov
Backend Models+Services 85% pytest-cov
Backend Routes 85% pytest-cov
Backend Plugins 80% pytest-cov
Frontend Components 75% vitest coverage
Frontend Plugin UI 70% vitest coverage
E2E (critical paths) 100% of defined specs Playwright

Test File Structure

Backend

backend/tests/
├── conftest.py              — Fixtures: test client, test DB, auth helpers, seed data
├── test_auth.py             — Auth endpoints, RBAC, password reset
├── test_tenant.py           — Tenant isolation, cross-tenant access
├── test_companies.py        — Company CRUD, search, filter, pagination, soft-delete
├── test_contacts.py         — Contact CRUD, N:M links, GDPR delete
├── test_import_export.py   — CSV import/export, XLSX export, dry-run preview
├── test_plugins.py          — Plugin lifecycle, event bus, migrations
├── test_dms.py             — DMS folders, files, upload, shares, permissions
├── test_calendar.py        — Entries, recurrence, kanban, ICS, resources
├── test_mail.py            — Accounts, IMAP sync, send, threading, rules, PGP
├── test_tags.py            — Tag CRUD, assignment, bulk
├── test_notifications.py   — Notification CRUD, unread count
├── test_health.py          — Health endpoint
├── test_ai_copilot.py      — KI-Copilot API, RBAC enforcement, history
├── test_workflows.py       — Workflow CRUD, instances, approval/rejection, event triggers
├── test_monitoring.py     — Extended health, Prometheus metrics, alerting
└── test_performance.py    — 200k seed, list <500ms, FTS <500ms, streaming export

Frontend

frontend/src/__tests__/
├── components/             — UI component unit tests (Button, Input, Modal, Table, etc.)
├── features/               — Feature integration tests (CompanyList, ContactForm, etc.)
├── hooks/                 — Custom hook tests (useDebounce, usePagination, etc.)
├── plugins/               — Plugin UI tests (DMS, Calendar, Mail, Tags)
└── search/                — Global search tests

E2E

e2e/
├── auth.spec.ts            — Login → logout flow
├── company-crud.spec.ts    — Create → edit → delete company
├── contact-crud.spec.ts    — Create → link to company → delete
├── search.spec.ts          — Global search
└── plugin-toggle.spec.ts   — Activate/deactivate plugin

Test Conventions

  • Test names: test_<action>_<condition>_<expected_result> (e.g., test_login_with_invalid_credentials_returns_401)
  • Test structure: Arrange → Act → Assert (AAA pattern)
  • Fixtures: Use conftest.py for shared fixtures. No fixture duplication across files.
  • Test DB: Use in-memory or ephemeral PostgreSQL (via testcontainers or pytest-postgresql). NEVER test against production DB.
  • Mocking: Mock external services (SMTP, IMAP, OnlyOffice) in tests. Use unittest.mock.AsyncMock for async mocks.
  • Assertions: Use pytest's native assert for backend, expect() from @testing-library/jest-dom for frontend.
  • No flaky tests: Tests must be deterministic. Use explicit waits, not sleeps.
  • Test isolation: Each test must be independent. No test depends on another test's side effects.

Don't Modify Tests Rule

  • NEVER modify existing tests to make them pass. If a test fails, fix the code, not the test.
  • Exception: If the test itself is wrong (testing incorrect behavior), document why and get approval before changing.
  • Test files are owned by the QA process, not the implementer.

3. Conventions

Backend Structure

backend/app/
├── main.py                 — FastAPI app entry point, lifespan, middleware registration
├── config.py               — Pydantic Settings (reads from env vars)
├── deps.py                 — FastAPI dependency injection (auth, db, tenant, permissions)
├── core/                   — Core infrastructure (cross-cutting concerns)
│   ├── db/                 — SQLAlchemy engine, session factory, base model
│   ├── tenant.py           — TenantMixin, ORM auto-filter, tenant context
│   ├── auth.py             — Session auth, password hashing (bcrypt), RBAC
│   ├── event_bus.py        — Async in-process event bus
│   ├── service_container.py — DI container
│   ├── storage.py          — File storage (local/S3)
│   ├── cache.py            — Redis cache wrapper
│   ├── jobs.py             — ARQ job queue integration
│   ├── notifications.py    — Notification service
│   └── audit.py            — Audit log middleware
├── models/                 — SQLAlchemy ORM models (one file per domain)
├── schemas/                — Pydantic schemas (request/response, one file per domain)
├── services/               — Business logic (one file per domain)
├── routes/                  — FastAPI routers (one file per domain)
├── plugins/                — Plugin system
│   ├── registry.py         — Plugin discovery, registration
│   ├── manifest.py         — Plugin manifest Pydantic schema
│   ├── lifecycle.py        — Install/activate/deactivate/uninstall
│   ├── migrations.py       — Plugin DB migration runner
│   ├── ui_registry.py      — Plugin UI component registration
│   └── builtins/           — Built-in plugins
│       ├── dms/            — DMS plugin
│       ├── calendar/       — Calendar plugin
│       ├── mail/           — Mail plugin
│       └── tags/           — Tags plugin
└── utils/                  — Shared utilities (validation, export, import)

Backend Naming Conventions

  • Files: snake_case.py (e.g., company_service.py)
  • Classes: PascalCase (e.g., CompanyService, CompanyModel)
  • Functions/Methods: snake_case (e.g., get_company_by_id)
  • Constants: UPPER_SNAKE_CASE (e.g., SESSION_TIMEOUT_HOURS)
  • Models: <Entity>Model suffix or just <Entity> (e.g., Company, Contact)
  • Schemas: <Entity>Create, <Entity>Update, <Entity>Read, <Entity>List (Pydantic)
  • Services: <Entity>Service (e.g., CompanyService)
  • Routers: <entity>_router variable, file name <entity>_router.py
  • Tests: test_<domain>.py (e.g., test_companies.py)

Backend Code Conventions

  • Async first: All route handlers and service methods are async def.
  • Type hints: All function signatures have type hints (Python 3.12+ syntax).
  • Docstrings: All public functions/classes have docstrings (Google style).
  • Error handling: Use FastAPI HTTPException with proper status codes. Never raise generic Exception.
  • Validation: Pydantic schemas validate input. Never validate in routes directly.
  • Tenant scoping: Never query without tenant filter (ORM auto-filter handles this, but be aware).
  • UUID: All IDs are UUID. Never use integer auto-increment.
  • Timestamps: All datetime fields are TIMESTAMPTZ. Never use naive datetime.
  • Soft-delete: Use deleted_at IS NULL filter. Never hard-delete without explicit gdpr=true flag.
  • Audit: All mutations must create audit log entries. Use the audit middleware/decorator.

Frontend Structure

frontend/src/
├── main.tsx               — React entry point
├── App.tsx                — Root component, router, providers
├── api/                   — API client (axios), interceptors, endpoint definitions
├── components/            — Shared UI components
│   ├── layout/            — Shell, Sidebar, TopBar, ContentArea
│   ├── ui/               — Button, Input, Select, Modal, Toast, Table, Card, Badge, Avatar
│   └── shared/           — EmptyState, LoadingState, ConfirmDialog, Pagination, Skeleton
├── features/              — Feature modules (one folder per feature)
│   ├── auth/             — Login, PasswordReset
│   ├── companies/        — CompanyList, CompanyDetail, CompanyForm
│   ├── contacts/         — ContactList, ContactDetail, ContactForm
│   ├── settings/         — SettingsTree, ProfileSettings, RoleEditor
│   ├── audit/            — AuditLog
│   ├── dashboard/        — Dashboard
│   └── search/           — GlobalSearch
├── plugins/              — Plugin UI loading framework
│   ├── PluginRegistry.tsx — Fetch manifests, register components
│   └── PluginLoader.tsx   — Dynamic lazy-loading of plugin components
├── hooks/                 — Custom React hooks (useDebounce, usePagination, useAuth, etc.)
├── store/                 — Zustand stores (useAuthStore, useUIStore, useTenantStore)
├── i18n/                  — react-i18next setup + locale files (de.json, en.json)
├── styles/                — Global CSS, design tokens (Tailwind config), accessibility
└── utils/                 — Utilities (format, validation, export, constants)

Frontend Naming Conventions

  • Files: PascalCase.tsx for components (e.g., CompanyList.tsx), camelCase.ts for utilities (e.g., apiClient.ts)
  • Components: PascalCase (e.g., CompanyList, ContactForm)
  • Hooks: use<Feature> (e.g., useDebounce, useAuth)
  • Stores: use<Domain>Store (e.g., useAuthStore, useUIStore)
  • Types/Interfaces: PascalCase (e.g., CompanyData, ContactFormValues)
  • API functions: camelCase (e.g., getCompanies, createContact)
  • Test files: <Component>.test.tsx next to component or in __tests__/ mirror

Frontend Code Conventions

  • TypeScript strict: strict: true in tsconfig.json. No any types.
  • Functional components: Only function components, no class components.
  • Hooks: Custom hooks for reusable logic. No inline hooks in JSX.
  • TanStack Query: Server state via useQuery / useMutation. No manual fetch in components.
  • Zustand: Client state only (UI toggles, theme, active tenant). No server data in Zustand.
  • React Hook Form + Zod: All forms use react-hook-form with zodResolver.
  • Tailwind CSS: No custom CSS files (except global + accessibility). Use Tailwind utility classes.
  • i18n: All user-visible strings go through t() from react-i18next. No hardcoded strings.
  • Accessibility: ARIA attributes on all interactive elements. 44px touch targets. Keyboard navigation.
  • Lazy loading: Plugin components use React.lazy() with Suspense boundaries.

Git Conventions

  • Branch naming: feature/T01-core-infrastructure, fix/auth-tenant-isolation, hotfix/critical-bug
  • Commit messages: Conventional Commits format:
    • feat(core): implement auth system with session-based login
    • fix(dms): resolve folder permission bypass on move
    • test(mail): add IMAP sync integration tests
    • refactor(calendar): extract recurrence engine to separate module
    • docs(architecture): update ADR-03 with plugin lifecycle details
  • PR titles: [T01] Core Infrastructure + Multi-Tenant + Auth System
  • Branch from: main (or feature branch for sub-features)
  • Merge strategy: Squash merge to main after review + CI passes

4. Task-Zuweisung (Subagenten pro Task)

Phasen-Plan

v1 Core Phases (Phase 3 — Implementation)

Phase Tasks Parallel Subagent Profile Description
1 T01 No implementation_engineer Foundation: Core, Auth, Multi-Tenant, RLS, Rate Limiting
2 T02, T03 Yes (2 agents) implementation_engineer ×2 Core entities + Plugin framework parallel
3 T07a, T09 Yes (2 agents) implementation_engineer ×2 Frontend Shell+Auth+UI Library + KI-Copilot/Workflow parallel
4 T07b No implementation_engineer Frontend Feature Pages (Companies, Contacts, Settings, Dashboard, Search)
5 T10 No implementation_engineer Monitoring, Performance, Doku, Environment Config

v2 Plugin Phases (nach v1 Deployment)

Phase Tasks Parallel Subagent Profile Description
6 T04, T05, T06, T11 Yes (4 agents) implementation_engineer ×4 DMS, Calendar, Mail, Tags+Permissions backends parallel
7 T08a, T08b, T08c Yes (3 agents) implementation_engineer ×3 Frontend DMS+Tags, Calendar, Mail+Search parallel

Task-to-Subagent Mapping

Task ID Title Subagent Dependencies Phase Scope
T01 Core Infrastructure + Multi-Tenant + Auth implementation_engineer 1 v1
T02 Company + Contact + Import/Export implementation_engineer T01 2 v1
T03 Plugin System Framework implementation_engineer T01 2 v1
T07a Frontend SPA — Shell, Auth, Routing, i18n, UI Library implementation_engineer T01 3 v1
T07b Frontend SPA — Companies, Contacts, Settings, Dashboard, Search implementation_engineer T01, T02, T07a 4 v1
T09 KI-Copilot + Workflow Engine implementation_engineer T01, T02 3 v1
T10 Monitoring + Performance + Doku + Env Config implementation_engineer T01, T02 5 v1
T04 DMS Plugin Backend implementation_engineer T01, T03 6 v2
T05 Calendar Plugin Backend implementation_engineer T01, T03 6 v2
T06 Mail Plugin Backend implementation_engineer T01, T03 6 v2
T11 Tags + Permissions + Entity Links Backend implementation_engineer T01, T03 6 v2
T08a Frontend DMS + Tags + Permissions UI implementation_engineer T04, T07b 7 v2
T08b Frontend Calendar UI implementation_engineer T05, T07b 7 v2
T08c Frontend Mail + Global Search UI implementation_engineer T06, T07b 7 v2

Parallelization Notes

v1 Phases:

  • Phase 2: T02 (Company/Contact) and T03 (Plugin Framework) are independent after T01 — safe to run in parallel.
  • Phase 3: T07a (Frontend Shell+Auth+UI Library) depends only on T01. T09 (KI/Workflow) depends on T01+T02. Both can run in parallel if API contracts are frozen.
  • Phase 4: T07b (Frontend Feature Pages) depends on T07a (UI library, routing, auth) + T02 (company/contact API). Must run after T07a.
  • Phase 5: T10 (Monitoring+Doku) depends on T01+T02. Can run parallel with T07b.

v2 Phases (after v1 deployment):

  • Phase 6: T04 (DMS), T05 (Calendar), T06 (Mail), T11 (Tags+Perm) all depend on T01+T03 — safe to run in parallel.
  • Phase 7: T08a/T08b/T08c depend on T07b + respective backend (T04/T05/T06) — safe to run in parallel.

Block Rules

  • Block = max 3 Tasks per implementation block.
  • After each block: quality_reviewer review → block_compactor → context_compactor → User checkpoint.
  • quality_reviewer and release_auditor do NOT count toward the 3-task limit.
  • After 3 blocks (9 tasks): release_auditor runs full audit.
  • Token budget: ~3000 tokens per task. If tool result >5000 tokens: context_compactor.

5. Forbidden Patterns

Backend Forbidden

  • SQLite: No SQLite as database. PostgreSQL 16 only (ADR-01).
  • Jinja2: No server-side HTML rendering. API-only backend (ADR-03).
  • Cross-Tenant Data Access: No query without tenant_id filter. ORM auto-filter must not be bypassed.
  • Plaintext Passwords: Passwords must be bcrypt-hashed (cost=12). Never store or log plaintext.
  • JWT Tokens: No JWT auth in v1. Session-based auth with HttpOnly cookies only (ADR-05).
  • Naive Datetime: All datetime fields must be timezone-aware (TIMESTAMPTZ). Never use datetime.now() without tz.
  • Integer IDs: All primary keys are UUID. Never use auto-increment integer IDs.
  • Hard-Delete without GDPR flag: Companies/Contacts use soft-delete. Hard-delete only with explicit ?gdpr=true.
  • Manual Tenant Filter: Never manually add .filter(Tenant.id == x) in services. The ORM auto-filter handles this.
  • Sync I/O in Routes: All route handlers are async def. Never use blocking I/O (use asyncpg, aiofiles, etc.).
  • Raw SQL without Tenant Check: Any raw SQL query must explicitly include tenant_id filter.
  • Secrets in Code: No hardcoded secrets. All secrets via environment variables.
  • Unvalidated Input: All request bodies validated by Pydantic schemas. Never trust raw request data.
  • Missing Audit Log: All create/update/delete operations must create audit log entries.
  • Plugin Tables without tenant_id: All plugin-created tables must include tenant_id column. The migration validator enforces this.

Frontend Forbidden

  • Class Components: No class components. Functional components with hooks only.
  • Inline Styles: No style={{}} props. Use Tailwind utility classes.
  • Hardcoded Strings: No user-visible hardcoded strings. Use t() from i18n.
  • Manual Fetch in Components: No fetch() or axios calls in components. Use TanStack Query hooks.
  • Server Data in Zustand: Zustand is for client state only. Server data goes in TanStack Query.
  • any Types: No any type. Use proper TypeScript types.
  • Missing ARIA Attributes: All interactive elements must have ARIA labels.
  • Touch Targets < 44px: All buttons/links must have minimum 44px touch target.
  • Direct DOM Manipulation: No document.getElementById() or querySelector() in components. Use React refs.
  • Unsafe HTML Rendering: No dangerouslySetInnerHTML without sanitization. Mail bodies must be sanitized (DOMPurify equivalent).

Deployment Forbidden

  • Running as Root in Container: Containers run as non-root user (app:app).
  • Exposed DB Port in Production: PostgreSQL port (5432) must not be exposed externally in production.
  • No Health Check: All services must have Docker health checks configured.
  • No Volume for Storage: File storage must use a named volume, not ephemeral container storage.
  • Secrets in docker-compose.yml: No secrets in compose file. Use .env file or Docker secrets.

6. Quality Gates

Per-Task Quality Gate

Before a task is marked complete:

  1. All test_spec commands must pass.
  2. Coverage target must be met (measured by pytest-cov / vitest coverage).
  3. TypeScript compiles without errors (tsc --noEmit).
  4. Linting passes (ruff for backend, eslint for frontend).
  5. Build succeeds (Vite build for frontend, no build step for backend).
  6. No forbidden patterns detected.
  7. All acceptance criteria verified as testable.

Phase Gate (after each phase)

  1. All tasks in the phase pass their quality gates.
  2. quality_reviewer subagent reviews the phase output.
  3. No critical issues from quality_reviewer.
  4. Block compactor saves progress.
  5. User checkpoint before next phase.

Release Gate (before v1 deployment)

  1. All 7 v1 tasks complete (T01, T02, T03, T07a, T07b, T09, T10).
  2. release_auditor runs full audit.
  3. Docker Compose builds and starts successfully.
  4. Health endpoint returns 200.
  5. E2E tests (Playwright) pass.
  6. All forbidden patterns checked.

v2 Release Gate (before v2 plugin deployment)

  1. All 7 v2 tasks complete (T04, T05, T06, T11, T08a, T08b, T08c).
  2. release_auditor runs full audit.
  3. All plugin backends + frontends pass quality gates.
  4. Plugin install/activate/deactivate lifecycle tested.
  5. All forbidden patterns checked.

7. Environment Setup

Development Environment

Variable Value Purpose
POSTGRES_HOST localhost (dev) / postgres (docker) Database host
POSTGRES_PORT 5432 Database port
POSTGRES_DB leocrm Database name
POSTGRES_USER leocrm Database user
POSTGRES_PASSWORD (from .env) Database password
REDIS_URL redis://localhost:6379/0 Redis for cache + sessions + jobs
LEOCRM_SECRET_KEY (min 32 chars) Session signing secret
SESSION_TIMEOUT_HOURS 8 Session expiry
MAIL_ENCRYPTION_KEY (32-byte hex) AES-256 key for mail credentials
STORAGE_BACKEND local (dev) / s3 (prod) File storage backend
STORAGE_PATH /data/leocrm/storage Local storage path
ONLYOFFICE_URL http://onlyoffice:80 OnlyOffice document server
LOG_LEVEL INFO Logging level

Test Environment

  • Test DB: Ephemeral PostgreSQL (pytest-postgresql or testcontainers).
  • Test Redis: Ephemeral or fakeredis.
  • External services (IMAP, SMTP, OnlyOffice): Mocked via unittest.mock.AsyncMock.
  • Test fixtures in conftest.py provide: test client, authenticated client (per role), seeded data.

8. Architecture Reference

Full architecture details: architecture.md

Full task graph with test specs: task_graph.json

Key ADRs:

  • ADR-01: PostgreSQL 16 (not SQLite)
  • ADR-02: ARQ (not Celery)
  • ADR-03: Built-in plugins with manifest (not dynamic pip-install)
  • ADR-04: TanStack Query (not Redux)
  • ADR-05: Session-based auth (not JWT)
  • ADR-06: Soft-delete with deleted_at column

Handoff

  • AGENTS.md status: COMPLETE
  • task_graph.json status: COMPLETE (14 tasks: 7 v1 + 7 v2, all with test_spec, 143 features covered, v1/v2 separated, v2.1.0)
  • architecture.md status: COMPLETE (73/73 v1 features referenced, v2 sections marked)
  • Ready for v1 implementation: YES (pending quality_reviewer review + plan_mode transition to implementation_allowed)
  • v2 implementation: After v1 deployment, separate phase