From f3cf056cd282392e39aa9daf58b7d5a29f61db64 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sun, 13 Sep 2026 11:50:38 +0800 Subject: [PATCH] =?UTF-8?q?docs(README):=20=E8=A1=A5=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E9=93=81=E5=BE=8B=E2=80=94=E2=80=94CRUD=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=86=99=E7=AB=AF=E7=82=B9=E4=B8=8D=E6=B3=A8=E5=86=8C=E6=9D=83?= =?UTF-8?q?=E9=99=90(=E5=AE=9E=E6=B5=8B=E6=8A=93=E6=B4=9E0fbd0ca);load=5Fp?= =?UTF-8?q?ath=E6=B3=A8=E9=87=8A=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a2b1715..efe011d 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,9 @@ voucher/ │ ├── invalidate_form.ui # 作废弹窗表单 │ └── api/ # 薄封装 dspy(零 import,委托 init.py 注册函数) ├── scripts/ -│ ├── load_path.py # RBAC 注册(logined 全路径逐个精确配) +│ ├── load_path.py # RBAC 注册(logined;CRUD 目录只注册 index.ui+get_* 只读, +│ │ # 生成的 add/update/delete 写端点不注册——裸 sor.C/U/D 绕过 +│ │ # 全部业务校验,未注册即 403,写操作只走 api/ 有校验端点) │ └── seed_welcome_voucher.py # WELCOME400 种子(幂等) ├── i18n/{zh,en,jp,ko}/msg.txt # key=value 格式(merge_i18n 消费) └── pyproject.toml # packages = ["voucher", "voucher.rules"] @@ -126,6 +128,7 @@ cd - dspy 薄封装返回 dict(框架自动序列化),**禁 json.dumps 双重序列化**(Pitfall 38)。 - datetime 字段回前端必须 str 化(`_jsonable_instance`),框架 json.dumps 无 default=str。 - 弹窗表单 submited 事件的 params 是 **Response 对象**,要 `await resp.json()` 后再 widgetBuild(form.js dispatch 原始 resp)。 +- **【安全铁律】CRUD 生成的 add/update/delete dspy 不注册权限**:它们是裸 sor.C/U/D,绕过发券引擎原子占额/流水审计只读/org 隔离/状态守卫。只注册 index.ui + get_* 只读;写操作只走 wwwroot/api/ 有校验端点。2026-09-12 实测抓洞:统一注册四件套时 update/delete_voucher_usage_log.dspy 登录态 200 可篡改审计流水(已修,commit 0fbd0ca)。 ## 仓库