6520e88d53
- 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
572 lines
24 KiB
Markdown
572 lines
24 KiB
Markdown
# LeoCRM — AGENTS.md
|
||
|
||
**Projekt:** leocrm
|
||
**Erstellt:** 2026-06-28
|
||
**Status:** Draft — ready for implementation
|
||
|
||
---
|
||
|
||
## 1. Build & Test Commands
|
||
|
||
### Backend (Python / FastAPI)
|
||
|
||
#### Setup
|
||
```bash
|
||
cd backend
|
||
python -m venv .venv
|
||
source .venv/bin/activate
|
||
pip install -e ".[dev]"
|
||
```
|
||
|
||
#### Run Dev Server
|
||
```bash
|
||
cd backend
|
||
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||
```
|
||
|
||
#### Database Migrations (Alembic)
|
||
```bash
|
||
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
|
||
```bash
|
||
cd backend
|
||
python -m pytest -v --tb=short
|
||
```
|
||
|
||
#### Run Specific Test File
|
||
```bash
|
||
cd backend
|
||
python -m pytest tests/test_auth.py -v --tb=short
|
||
```
|
||
|
||
#### Run Tests with Coverage
|
||
```bash
|
||
cd backend
|
||
python -m pytest --cov=app --cov-report=term-missing --cov-report=html
|
||
```
|
||
|
||
#### Run Tests with Grep Filter
|
||
```bash
|
||
cd backend
|
||
python -m pytest -k 'tenant or auth' -v
|
||
```
|
||
|
||
#### Type Checking
|
||
```bash
|
||
cd backend
|
||
mypy app/ --ignore-missing-imports
|
||
```
|
||
|
||
#### Linting
|
||
```bash
|
||
cd backend
|
||
ruff check app/
|
||
ruff format app/
|
||
```
|
||
|
||
### Frontend (React / Vite / TypeScript)
|
||
|
||
#### Setup
|
||
```bash
|
||
cd frontend
|
||
npm install
|
||
```
|
||
|
||
#### Run Dev Server
|
||
```bash
|
||
cd frontend
|
||
npm run dev
|
||
```
|
||
|
||
#### Build Production
|
||
```bash
|
||
cd frontend
|
||
npm run build
|
||
```
|
||
|
||
#### Run All Frontend Tests
|
||
```bash
|
||
cd frontend
|
||
npx vitest run --reporter=verbose
|
||
```
|
||
|
||
#### Run Tests with Coverage
|
||
```bash
|
||
cd frontend
|
||
npx vitest run --coverage
|
||
```
|
||
|
||
#### Run Tests in Watch Mode (dev)
|
||
```bash
|
||
cd frontend
|
||
npx vitest watch
|
||
```
|
||
|
||
#### Type Checking
|
||
```bash
|
||
cd frontend
|
||
npx tsc --noEmit
|
||
```
|
||
|
||
#### Linting
|
||
```bash
|
||
cd frontend
|
||
npx eslint src/ --ext .ts,.tsx
|
||
```
|
||
|
||
### Docker Compose (Full Stack)
|
||
|
||
#### Build All Services
|
||
```bash
|
||
docker compose build
|
||
```
|
||
|
||
#### Start All Services
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
#### View Logs
|
||
```bash
|
||
docker compose logs -f backend
|
||
```
|
||
|
||
#### Stop All Services
|
||
```bash
|
||
docker compose down
|
||
```
|
||
|
||
#### Validate Compose Config
|
||
```bash
|
||
docker compose config --quiet
|
||
```
|
||
|
||
### E2E Tests (Playwright)
|
||
|
||
```bash
|
||
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
|