feat: 实现密码重置功能与用户搜索API,优化注册登录流程
- 新增忘记密码页面与重置密码确认流程(前端+后端) - 修复注册验证码页登录跳转路由 - 新增用户搜索API(按邮箱查询) - 简化infra脚本,统一为app.sh - 补充密码重置与用户API测试覆盖 - 更新runtime文档与AGENTS配置
This commit is contained in:
+80
-14
@@ -1,3 +1,7 @@
|
||||
# Backend Development Rules
|
||||
|
||||
This document defines Python/FastAPI backend development constraints.
|
||||
|
||||
## Python Environment
|
||||
|
||||
**MUST use uv for dependency management and virtual environment execution.**
|
||||
@@ -43,11 +47,10 @@ Do not bypass or weaken checks (no ignores, disables, or config relaxations). Re
|
||||
- Tests can set env vars via `monkeypatch.setenv`, and should read values via `Settings()` 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.**
|
||||
## TDD Workflow
|
||||
|
||||
### Coverage Requirements
|
||||
|
||||
- Minimum coverage: 80%
|
||||
- Required test types:
|
||||
- Unit: isolated functions, utilities, components
|
||||
@@ -55,12 +58,14 @@ Do not bypass or weaken checks (no ignores, disables, or config relaxations). Re
|
||||
- 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
|
||||
|
||||
1. Write tests (RED) - they must fail
|
||||
2. Run tests - confirm failure
|
||||
3. Implement minimal code (GREEN) - only to pass
|
||||
@@ -69,19 +74,80 @@ Do not bypass or weaken checks (no ignores, disables, or config relaxations). Re
|
||||
6. Verify coverage - must be 80%+
|
||||
|
||||
### Enforcement
|
||||
|
||||
- Must use the `tdd-guide` agent for new features
|
||||
- Do not write implementation before tests
|
||||
- Do not lower coverage requirements
|
||||
- Must include unit, integration, and E2E tests
|
||||
|
||||
## Code Style
|
||||
|
||||
### Immutability
|
||||
|
||||
**ALWAYS create new objects, NEVER mutate.**
|
||||
|
||||
```python
|
||||
# WRONG: Mutation
|
||||
def update_user(user, name):
|
||||
user["name"] = name
|
||||
return user
|
||||
|
||||
# CORRECT: Immutability
|
||||
def update_user(user, name):
|
||||
return {**user, "name": name}
|
||||
```
|
||||
|
||||
### File Organization
|
||||
|
||||
- Many small files over few large files
|
||||
- 200-400 lines typical, 800 max per file
|
||||
- Extract utilities from large components
|
||||
|
||||
### Error Handling
|
||||
|
||||
Always handle errors comprehensively:
|
||||
|
||||
```python
|
||||
try:
|
||||
result = risky_operation()
|
||||
return result
|
||||
except Exception as exc:
|
||||
logger.exception("Operation failed")
|
||||
raise RuntimeError("Detailed user-friendly message") from exc
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
### Mandatory Security Checks
|
||||
|
||||
Before ANY commit:
|
||||
- [ ] No hardcoded secrets (API keys, passwords, tokens)
|
||||
- [ ] All user inputs validated (use Pydantic)
|
||||
- [ ] SQL injection prevention (parameterized queries)
|
||||
- [ ] Authentication/authorization verified
|
||||
|
||||
### Secret Management
|
||||
|
||||
```python
|
||||
# NEVER: Hardcoded secrets
|
||||
api_key = "sk-proj-xxxxx"
|
||||
|
||||
# ALWAYS: Environment variables
|
||||
api_key = os.environ.get("OPENAI_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError("OPENAI_API_KEY not configured")
|
||||
```
|
||||
|
||||
## Database Development Rules
|
||||
|
||||
### Core Principle
|
||||
### Architecture
|
||||
|
||||
- **Supabase**: authentication (JWT source of truth)
|
||||
- **Backend**: business authorization (service layer)
|
||||
- **SQLAlchemy ORM**: data access layer (async + asyncpg, service_role connection)
|
||||
|
||||
### Architecture
|
||||
### Code Organization
|
||||
|
||||
Use `schemas / repository / service` pattern:
|
||||
- `schemas.py` — Pydantic models
|
||||
- `repository.py` — CRUD only, no auth, no commit (only flush), must receive session (never create session/engine)
|
||||
@@ -89,6 +155,7 @@ Use `schemas / repository / service` pattern:
|
||||
- `dependencies.py` — DI (`get_db`, `get_current_user`)
|
||||
|
||||
### Auth & Data Access
|
||||
|
||||
- Backend must verify JWT signature and expiration (not just decode)
|
||||
- Extract `user_id` from JWT `sub` claim
|
||||
- Backend connects with **service_role** (bypasses RLS)
|
||||
@@ -98,31 +165,28 @@ Use `schemas / repository / service` pattern:
|
||||
- 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)` + `CHECK` constraint in database
|
||||
- Use Python `Enum` class with `str` base in code
|
||||
- Benefits: debugging readability, easy to add new values without data migration, ORM-friendly
|
||||
|
||||
```python
|
||||
# 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
|
||||
### RLS Policy
|
||||
|
||||
- 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 `public` must enable RLS in the same Alembic migration.
|
||||
- The same migration must create policies covering `SELECT/INSERT/UPDATE/DELETE` (minimum requirement).
|
||||
@@ -130,11 +194,13 @@ ALTER TABLE user_agents ADD CONSTRAINT chk_agent_type
|
||||
- `alembic_version` must not be exposed to `anon` or `authenticated`.
|
||||
|
||||
#### Exemption Rule (strict)
|
||||
|
||||
- Exemptions are allowed only when a new `public` table 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).
|
||||
- Exemptions must be explicit in the migration file with rationale and verification notes.
|
||||
- If exposure is uncertain, do not exempt: enable defensive RLS by default.
|
||||
|
||||
#### Migration Acceptance Checklist (RLS)
|
||||
#### Migration Checklist
|
||||
|
||||
- [ ] New `public` business table has `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` in migration
|
||||
- [ ] Policies for `SELECT/INSERT/UPDATE/DELETE` are present in migration
|
||||
- [ ] Policy target roles are explicit (`anon`, `authenticated`, or both)
|
||||
|
||||
Reference in New Issue
Block a user