76853452f6
include AGENTS guidance updates, plan doc replacements, and utility script changes left in working tree
5.9 KiB
5.9 KiB
Python Environment
MUST use uv for dependency management and virtual environment execution.
- All Python commands:
uv run <command> - Add dependencies:
uv add <package> - All dependencies declared in
pyproject.toml
Code Quality Checks
Git pre-commit hook enforces code quality before commit.
Pre-commit hook automatically runs on backend/ directory:
ruff check- code style and lintingbasedpyright- type checking with error level
If any error detected, commit is rejected. Fix errors before committing. Do not bypass or weaken checks (no ignores, disables, or config relaxations). Resolve the underlying issues.
Logging
MUST use project logger for all runtime logging.
- Use project logger from
backend/src/core/logging/* - Prohibit: print(), logging.info/warning/error directly
- Required: structured logging with context
- Log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
HTTP API Standards
MUST follow RESTful conventions and RFC 7807 for error responses.
- Errors must use
application/problem+jsonwith RFC 7807 fields - No custom response envelopes for HTTP APIs
- Request and response validation must use Pydantic models
Environment Variables
Backend env access MUST go through backend/src/core/config/settings.py.
- Only use
Settings()/configfromcore.config.settings - Do not call
os.environ,os.getenv,dotenv, or manual parsing in backend runtime code - Tests can set env vars via
monkeypatch.setenv, and should read values viaSettings()unless the test is explicitly validating env plumbing - Canonical principle: one source of truth per setting; no duplicate/derived env vars in backend code
TDD First Policy
Principle: tests before implementation.
Coverage Requirements
- Minimum coverage: 80%
- Required test types:
- Unit: isolated functions, utilities, components
- Integration: API endpoints, database operations
- E2E: critical user flows (Playwright)
Limited Exceptions
- Docs-only changes (README, comments, formatting) may skip integration/E2E
- Non-runtime config changes may skip E2E if no behavior changes
- Any runtime code change requires unit + integration + E2E
- If an exception is used, record the reason in the PR/test notes
Mandatory TDD Workflow
- Write tests (RED) - they must fail
- Run tests - confirm failure
- Implement minimal code (GREEN) - only to pass
- Run tests - confirm success
- Refactor (IMPROVE)
- Verify coverage - must be 80%+
Enforcement
- Must use the
tdd-guideagent for new features - Do not write implementation before tests
- Do not lower coverage requirements
- Must include unit, integration, and E2E tests
Database Development Rules
Core Principle
- Supabase: authentication (JWT source of truth)
- Backend: business authorization (service layer)
- SQLAlchemy ORM: data access layer (async + asyncpg, service_role connection)
Architecture
Use schemas / repository / service pattern:
schemas.py— Pydantic modelsrepository.py— CRUD only, no auth, no commit (only flush), must receive session (never create session/engine)service.py— authorization + business logic + transaction boundary (must commit/rollback)dependencies.py— DI (get_db,get_current_user)
Auth & Data Access
- Backend must verify JWT signature and expiration (not just decode)
- Extract
user_idfrom JWTsubclaim - Backend connects with service_role (bypasses RLS)
owner_idalways derived from JWT, never from client- Scope queries by owner/org; public access must be explicit
- service_role key is backend-only; never expose credentials
- Prohibit calling Supabase Admin API (service_role key) from repository/service layers
Migrations
- Alembic is the single source of truth for schema migrations
- ORM model changes →
alembic revision --autogenerate - Raw SQL (policies, triggers, functions) →
op.execute() - Migrations must be reversible; no reliance on generated IDs
Enum Storage Convention
Store enum names (strings), not integer values.
- Use
VARCHAR(20)+CHECKconstraint in database - Use Python
Enumclass withstrbase in code - Benefits: debugging readability, easy to add new values without data migration, ORM-friendly
# Correct
class AgentType(str, Enum):
INTENT_RECOGNITION = "INTENT_RECOGNITION"
TASK_EXECUTION = "TASK_EXECUTION"
RESULT_REPORTING = "RESULT_REPORTING"
# Migration
ALTER TABLE user_agents ADD CONSTRAINT chk_agent_type
CHECK (agent_type IN ('INTENT_RECOGNITION', 'TASK_EXECUTION', 'RESULT_REPORTING'));
RLS Guidance
- Backend does not rely on RLS for correctness (uses service_role), but RLS is mandatory as a defensive boundary for tables in PostgREST-exposed schemas.
- Mandatory default: any new business table in
publicmust enable RLS in the same Alembic migration. - The same migration must create policies covering
SELECT/INSERT/UPDATE/DELETE(minimum requirement). - Recommended default policy set for
anon, authenticated: deny all operations first, then open explicit access only when required. alembic_versionmust not be exposed toanonorauthenticated.
Exemption Rule (strict)
- Exemptions are allowed only when a new
publictable is guaranteed not to be exposed to PostgREST clients. - Exemptions must be explicit in the migration file with rationale and verification notes (why safe, how exposure is prevented).
- If exposure is uncertain, do not exempt: enable defensive RLS by default.
Migration Acceptance Checklist (RLS)
- New
publicbusiness table hasALTER TABLE ... ENABLE ROW LEVEL SECURITYin migration - Policies for
SELECT/INSERT/UPDATE/DELETEare present in migration - Policy target roles are explicit (
anon,authenticated, or both) - Downgrade path is reversible and does not silently weaken intended production security
- Any exemption is documented with clear non-exposure evidence