# Backend Domain Rules This file governs `backend/**` only. Keep it minimal, enforceable, and non-duplicative. ## Scope & Precedence - Inherits root `AGENTS.md` and workspace runtime rules. - If rules conflict, apply the stricter one. - Keep backend-only constraints here; do not duplicate root routing logic. ## Runtime & Commands - Python commands must use `uv` (`uv run`, `uv add`). - Backend startup/shutdown must use `./infra/scripts/app.sh`. - Check runtime logs from `./logs/*.log`. ## Code Quality Baseline - Do not bypass lint/type gates (`ruff`, `basedpyright`). - Use project logging (`core.logging`), never `print()` in runtime code. - HTTP errors must follow RFC 7807 (`application/problem+json`). ## Configuration & Secrets - Read env only through `core.config.settings` (`Settings` / `config`). - Do not use `os.getenv`/manual env parsing in backend runtime. - Never hardcode keys/tokens/passwords. ## Architecture Rules - Use `schema -> repository -> service` layering. - Repository: CRUD + query composition only; no auth decisions, no transaction boundary. - Service: authz + business logic + transaction boundary. - `owner_id` must come from verified JWT (`sub`), never from client payload. ## Schema & Contract Rules - Schema-first for new/changed data contracts. - Strong typing required at boundaries (Pydantic/dataclass); avoid weak untyped payload contracts. - Protocol/data contract changes must stay aligned with `docs/protocols/`. ## Database Rules - Supabase Auth is identity source; backend enforces business authorization. - Use service-role DB access only in backend. - Soft delete uses `deleted_at`; reads must exclude deleted records by default. - Alembic is the only schema migration source of truth. ## Agent Runtime & Tools - AG-UI protocol is mandatory for agent loop behavior. - `ToolAgentOutput.result` is the canonical tool result field. - Tool results must be machine-oriented and include IDs/outcomes needed for chaining. ## Tool Schema Rules for Small Models (e.g., qwen3.5-flash) - Prefer `operations: list[OperationModel]` over parallel arrays. - Validate tool args with strict Pydantic models (`extra="forbid"`). - Keep payloads JSON-native (objects/lists), shallow, and deterministic. - Make action-specific required fields explicit and fail with structured errors. - Return per-item outcomes (`success/failed`, identifiers, partial status) for self-correction. - Avoid broad entry-point coercion fallbacks; fix schema/prompt alignment first. - Do not pass provider request fields with `None` values (avoid upstream 400 blocking tool calls). ## Testing - Follow TDD for feature/bugfix work when practical. - Prioritize regression tests for changed logic/contracts. - Real DB tests must use `settings.test.*`; never hardcode test credentials.