Files
track/AGENTS.md
openhands 42a67bfa3a docs: 新增 AGENTS.md —— 记录本地起环境、测试踩坑与已知待修问题
刻意只写验证过的事实:
- 本机装 PG + 必须覆盖 DATABASE_URL/MOM_DB_*/SECRET_KEY 才能起服务
- TestClient 与异步引擎跨事件循环冲突会伪装成随机 500,
  改用 httpx.AsyncClient + ASGITransport 单循环
- 实测确认读接口大面积未鉴权(含匿名可导出个人工时台账)
- 「管理员角色」规则的后端唯一事实来源是 app/core/roles.py
2026-09-21 02:28:47 +00:00

3.7 KiB
Raw Blame History

AGENTS.md

本仓库Track 生产流转系统)的工作笔记。仅在验证过之后才写入,避免传谣。

架构速览

  • backend/ FastAPI + SQLAlchemy 2.x(async) + AlembicPostgreSQL。
  • frontend/ React 19 + Vite + antd + Tailwind。路由见 src/App.tsx 管理端菜单见 src/components/layout/AdminLayout.tsxMENU 数组)。
  • 登录不走 Track 自己的用户表,而是只读 MOM(KCGL) 的 sys_user sys_user.username"真实姓名/登录账号"login()WHERE username LIKE '%/<账号>' 匹配,display_name/ 拆解得到。 MOM 连接配置在 app/core/mom_database.py(同步 psycopg2 引擎)。

本地起环境(关键,踩过的坑都在这)

  1. 本机没有 Postgres 时需要先装(容器内 sudo 可用): sudo -n apt-get install -y --fix-missing postgresql postgresql-contrib 然后 sudo -n pg_ctlcluster 17 main start。 本仓库不使用 pgvector无需额外扩展。
  2. 数据库端口与生产默认值不同,必须用环境变量覆盖:
    • DATABASE_URL=postgresql+asyncpg://track:track_prod_2026@127.0.0.1:5432/track_production
    • MOM_DB_HOST=127.0.0.1MOM_DB_PORT=5432
    • SECRET_KEY=<≥32 字符>DEBUG=false 时配置项会拒绝默认 SECRET_KEY (见 app/core/config.py 的校验),不设会直接 import 失败。
  3. 迁移:cd backend && python3 -m alembic upgrade head(没有全局 alembic 命令, 要用 python3 -m alembic)。校验纯 SQL 用 alembic upgrade head --sql
  4. 前端 proxy 指向 Docker 服务名 backend:8000。本机跑要么把 127.0.0.1 backend 写进 /etc/hosts,要么直接给 VITE_API_BASE_URL=http://localhost:<port>/api/v1 绕过 proxy。 注意 dev server 由 basicSsl 起 HTTPS跨域需要后端 CORS_ORIGINS 加上 https://localhost:1420

测试的坑(重要)

  • 不要用 starlette.testclient.TestClient 测异步 SQLAlchemy 应用。 它每个请求新建事件循环,而引擎是模块级单例、池里挂着 asyncpg 连接, 跨循环复用会报 got Future attached to a different loop,表现为随机 500。 正确做法:httpx.AsyncClient(transport=httpx.ASGITransport(app=app)) 并在单个 asyncio.run() 里跑完全部请求。生产 uvicorn 单循环无此问题。
  • 仓库目前没有 pytest 基建,也没有前端测试脚本。

已知的待修问题(截至 1.0应用 分支)

  • 读接口大面积未鉴权(已实测,非推测):无 token 直接 200 的包括 /api/v1/users/、全部 /api/v1/dashboard/*(含 people-history/export —— 匿名即可批量导出个人工时台账)、 /api/v1/analytics/*/api/v1/screen/*/api/v1/orders/。 写操作和 /api/v1/tasks/api/v1/products 是有鉴权的。 新增接口请统一用 app/core/deps.pyrequire_admin / require_roles
  • 「管理员角色」这份规则此前散在 4 处(后端 task_serviceproducts.py 内联、 前端 constants/task.tsAdminProductsPage 内联),已因此出过事故。 后端唯一事实来源是 app/core/roles.py,前端用 constants/task.ts::isAdminRole 新增判断不要手写 === 比较。
  • task_logs.task_id 是 NOT NULL 外键,只能挂任务,不是通用审计。通用审计是 audit_logs(本轮新增,由 app/core/audit_middleware.py 自动采集)。

约定

  • 时间统一北京时间(app/core/time_utils.py),库里存 timestamptz。
  • 中文枚举标签尽量由服务端下发(如审计接口的 module_label/action_label 避免前端再抄一份映射开始漂移。
  • 本仓库的提交信息用中文,说明「为什么」而非「改了什么」。