2026-03-23 17:57:24 +08:00
# Backend Domain Rules
2026-02-27 15:22:42 +08:00
2026-03-23 17:57:24 +08:00
This file governs `backend/**` only. Keep it minimal, enforceable, and non-duplicative.
2026-02-27 15:22:42 +08:00
2026-03-23 17:57:24 +08:00
## Scope & Precedence
2026-03-12 16:41:45 +08:00
2026-03-23 17:57:24 +08:00
- 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.
2026-03-12 16:41:45 +08:00
2026-03-23 17:57:24 +08:00
## Runtime & Commands
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
- Python commands must use `uv` (`uv run` , `uv add` ).
- Backend startup/shutdown must use `./infra/scripts/app.sh` .
- Check runtime logs from `./logs/*.log` .
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
## Code Quality Baseline
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
- 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` ).
2026-02-24 16:38:30 +08:00
2026-03-27 14:04:49 +08:00
## HTTP Error Contract (Must)
- Backend must construct error payload using RFC7807 fields plus stable extension fields: `code` and optional `params` .
- `code` must be machine-readable `UPPER_SNAKE_CASE` ; do not use free-text `detail` as the only contract.
- Error code registry source of truth: `docs/protocols/common/http-error-codes.md` .
- Any create/modify/deprecate of error codes must update `docs/protocols/common/http-error-codes.md` in the same change.
- Keep response media type as `application/problem+json` .
- Long-term layering target: HTTP transport details stay in routers/global handlers; service/repository/dependencies should raise domain errors (`ApiProblemError` or domain-specific exceptions), not `HTTPException` .
- When refactoring existing code, prefer replacing `HTTPException` in service/repository/dependencies with `ApiProblemError` while preserving status/code semantics.
2026-03-23 17:57:24 +08:00
## Configuration & Secrets
2026-02-24 16:38:30 +08:00
2026-03-23 17:57:24 +08:00
- 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.
2026-02-24 16:38:30 +08:00
2026-03-23 17:57:24 +08:00
## Architecture Rules
2026-02-24 16:38:30 +08:00
2026-03-23 17:57:24 +08:00
- 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.
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
## Schema & Contract Rules
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
- 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/` .
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
## Database Rules
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
- 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.
2026-03-25 12:36:31 +08:00
- Database migrations use `./infra/scripts/dev-migrate.sh` :
- `migrate` - run migrations only
- `init-data` - seed data only
- `bootstrap` - migrate + init-data
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
## Agent Runtime & Tools
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
- 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.
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
## Tool Schema Rules for Small Models (e.g., qwen3.5-flash)
2026-02-05 15:13:06 +08:00
2026-03-23 17:57:24 +08:00
- 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).
2026-03-17 12:18:09 +08:00
## Testing
2026-03-23 17:57:24 +08:00
- 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.