create-dwy 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +6 -15
- package/package.json +3 -3
- package/src/create.js +61 -37
- package/src/sync.js +206 -61
- package/templates/claude-global/CLAUDE.md +92 -0
- package/templates/claude-global/rules/dwy-android-core.md +610 -0
- package/templates/claude-global/rules/dwy-api-design.md +110 -0
- package/templates/claude-global/rules/dwy-db-migration.md +46 -0
- package/templates/claude-global/rules/dwy-flutter-core.md +564 -0
- package/templates/claude-global/rules/dwy-flutter-network.md +222 -0
- package/templates/claude-global/rules/dwy-flutter-router.md +97 -0
- package/templates/claude-global/rules/dwy-flutter-testing.md +94 -0
- package/templates/claude-global/rules/dwy-git-commit-convention.md +82 -0
- package/templates/claude-global/rules/dwy-git-security.md +53 -0
- package/templates/claude-global/rules/dwy-payload-limits.md +178 -0
- package/templates/claude-global/rules/{prefer-open-source.md → dwy-prefer-open-source.md} +4 -0
- package/templates/claude-global/rules/dwy-project-structure.md +181 -0
- package/templates/claude-global/rules/{python-code-style.md → dwy-python-core.md} +292 -358
- package/templates/claude-global/rules/dwy-python-fastapi.md +272 -0
- package/templates/claude-global/rules/dwy-python-orm.md +61 -0
- package/templates/claude-global/rules/{backend-security.md → dwy-python-security.md} +99 -72
- package/templates/claude-global/rules/dwy-python-testing.md +53 -0
- package/templates/claude-global/rules/{server-security.md → dwy-server-security.md} +1 -2
- package/templates/claude-global/rules/dwy-tdd-development.md +70 -0
- package/templates/claude-global/rules/dwy-tech-stack.md +60 -0
- package/templates/claude-global/rules/dwy-vue-api.md +146 -0
- package/templates/claude-global/rules/{vue-code-style.md → dwy-vue-core.md} +338 -152
- package/templates/claude-global/rules/dwy-vue-pinia.md +75 -0
- package/templates/claude-global/rules/dwy-vue-testing.md +102 -0
- package/templates/claude-global/skills/dwy-deploy-audit/SKILL.md +481 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-data.md +117 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-network.md +74 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-runtime.md +184 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_base.sh +39 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_capacity.sh +278 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_db.sh +122 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_docker.sh +249 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_env.sh +64 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_https.sh +60 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_logs.sh +209 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_nginx.sh +92 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_resilience.sh +157 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_secrets.sh +327 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_services.sh +77 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_ssh.sh +56 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/run_all.sh +105 -0
- package/templates/claude-global/skills/dwy-docker/SKILL.md +187 -0
- package/templates/claude-global/skills/dwy-docker/references/ask-templates.md +142 -0
- package/templates/claude-global/skills/dwy-docker/references/templates.md +479 -0
- package/templates/claude-global/skills/dwy-docker/references/version-rules.md +76 -0
- package/templates/claude-global/skills/dwy-docker/scripts/query_dockerhub.py +204 -0
- package/templates/claude-global/skills/dwy-docker/scripts/scan_images.sh +185 -0
- package/templates/claude-global/skills/dwy-eapi/SKILL.md +433 -0
- package/templates/claude-global/skills/dwy-eapi/references/tasks-integration-guide.md +387 -0
- package/templates/claude-global/skills/dwy-ekit/SKILL.md +85 -0
- package/templates/claude-global/skills/dwy-ekit/references/data.md +135 -0
- package/templates/claude-global/skills/dwy-ekit/references/form.md +68 -0
- package/templates/claude-global/skills/dwy-ekit/references/request.md +183 -0
- package/templates/claude-global/skills/dwy-ekit/references/ui.md +109 -0
- package/templates/claude-global/skills/{dwy-frontend-eui → dwy-eui}/SKILL.md +129 -15
- package/templates/claude-global/skills/dwy-eui/references/eui-design-guide.md +257 -0
- package/templates/claude-global/skills/dwy-eui/references/eui-integration-guide.md +302 -0
- package/templates/claude-global/skills/dwy-eui/references/eui-landing-design-guide.md +437 -0
- package/templates/claude-global/skills/dwy-fullstack-scaffold/SKILL.md +214 -0
- package/templates/claude-global/skills/dwy-mirror-source/SKILL.md +275 -0
- package/templates/claude-global/skills/dwy-mirror-source/references/dockerfile-snippets.md +228 -0
- package/templates/claude-global/skills/dwy-mirror-source/references/mirror-providers.md +150 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/__pycache__/check_mirrors.cpython-313.pyc +0 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/apply_mirrors.py +666 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/check_mirrors.py +868 -0
- package/templates/claude-global/skills/dwy-pentest/SKILL.md +344 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__init__.py +1 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/__init__.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/config.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/executor.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/severity.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/validator.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/config.py +109 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/executor.py +157 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/severity.py +96 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/validator.py +113 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_auth.py +289 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_recon.py +217 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_report.py +343 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_scan.py +205 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_ssl.py +208 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_vuln.py +205 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_web.py +330 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pyproject.toml +14 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/setup_tools.sh +97 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/uv.lock +415 -0
- package/templates/claude-global/skills/{dwy-release → dwy-publish}/SKILL.md +42 -18
- package/templates/claude-global/skills/dwy-vue-core/SKILL.md +890 -0
- package/templates/project/backend/.dwy.hbs +5 -0
- package/templates/project/backend/.python-version +1 -0
- package/templates/project/backend/CLAUDE.md.hbs +40 -0
- package/templates/project/{web/backend → backend}/alembic/script.py.mako +2 -0
- package/templates/project/{web/backend → backend}/alembic.ini.hbs +0 -1
- package/templates/project/backend/deploy.sh.hbs +18 -0
- package/templates/project/{web → backend}/docker-compose.prod.yml.hbs +1 -1
- package/templates/project/{web/backend → backend}/pyproject.toml.hbs +4 -5
- package/templates/project/{web/backend → backend}/src/app/config.py.hbs +1 -1
- package/templates/project/backend/src/app/database.py +10 -0
- package/templates/project/backend/src/app/dependencies.py +5 -0
- package/templates/project/{web/backend → backend}/src/app/main.py.hbs +3 -3
- package/templates/project/backend/src/app/models/base.py +5 -0
- package/templates/project/web/CLAUDE.md.hbs +29 -36
- package/templates/project/web/{frontend → apps/web}/index.html.hbs +1 -0
- package/templates/project/web/{frontend → apps/web}/package.json.hbs +4 -3
- package/templates/project/web/apps/web/src/App.vue +9 -0
- package/templates/project/web/apps/web/src/api/client.ts +5 -0
- package/templates/project/web/apps/web/src/composables/.gitkeep +0 -0
- package/templates/project/web/apps/web/src/layouts/DefaultLayout.vue +8 -0
- package/templates/project/web/{frontend → apps/web}/src/router/index.ts +1 -1
- package/templates/project/web/{frontend → apps/web}/src/stores/auth.ts +4 -2
- package/templates/project/web/apps/web/src/style.css +2 -0
- package/templates/project/web/apps/web/src/types/router.d.ts +8 -0
- package/templates/project/web/apps/web/src/views/HomeView.vue +8 -0
- package/templates/project/web/apps/web/tsconfig.app.json +18 -0
- package/templates/project/web/apps/web/tsconfig.json +6 -0
- package/templates/project/web/{frontend → apps/web}/vite.config.ts.hbs +7 -1
- package/templates/project/web/package.json.hbs +16 -0
- package/templates/project/web/packages/.gitkeep +0 -0
- package/templates/project/web/pnpm-workspace.yaml +3 -0
- package/templates/claude-global/hooks/post-sync-claude-global.sh +0 -72
- package/templates/claude-global/rules/agent-team-execution.md +0 -138
- package/templates/claude-global/rules/agent-team-patterns.md +0 -157
- package/templates/claude-global/rules/git-commit-convention.md +0 -106
- package/templates/claude-global/rules/git-security.md +0 -144
- package/templates/claude-global/skills/dwy-backend-base/SKILL.md +0 -279
- package/templates/claude-global/skills/dwy-frontend-core/SKILL.md +0 -181
- package/templates/project/web/.claude/commands/deploy.md +0 -4
- package/templates/project/web/backend/src/app/models/base.py +0 -5
- package/templates/project/web/deploy.sh.hbs +0 -113
- package/templates/project/web/frontend/src/App.vue +0 -3
- package/templates/project/web/frontend/src/api/client.ts +0 -13
- package/templates/project/web/frontend/src/style.css +0 -1
- package/templates/project/web/frontend/src/views/HomeView.vue +0 -5
- package/templates/project/web/frontend/tsconfig.app.json +0 -14
- package/templates/project/web/frontend/tsconfig.json +0 -4
- /package/templates/{project/web/backend → claude-global/skills/dwy-pentest/scripts}/.python-version +0 -0
- /package/templates/project/{web/backend → backend}/Dockerfile +0 -0
- /package/templates/project/{web/backend → backend}/alembic/env.py.hbs +0 -0
- /package/templates/{claude-global/skills → project/backend/alembic/versions}/.gitkeep +0 -0
- /package/templates/project/{web → backend}/docker-compose.dev.yml.hbs +0 -0
- /package/templates/project/{web/backend → backend}/src/app/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/models/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/routers/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/routers/health.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/schemas/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/services/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/tests/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/tests/conftest.py.hbs +0 -0
- /package/templates/project/{web/backend/alembic/versions → mobile}/.gitkeep +0 -0
- /package/templates/project/web/{frontend → apps/web}/src/components/.gitkeep +0 -0
- /package/templates/project/web/{frontend → apps/web}/src/main.ts +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# 数据载荷三层长度限制规则
|
|
2
|
+
|
|
3
|
+
防止大文本 DoS、内存耗尽、带宽滥用。所有涉及用户输入 / HTTP 请求体 / 文件上传的场景必须遵循三层限制,单层失守即高风险。
|
|
4
|
+
|
|
5
|
+
本文件是"长度 / 大小 / 数量"规则的**唯一权威源**。其他规则文件(`dwy-server-security.md`、`dwy-python-security.md`)的对应章节只做引用,不重复定义。
|
|
6
|
+
|
|
7
|
+
## 为什么需要三层
|
|
8
|
+
|
|
9
|
+
- **前端 = UX 边界**:给用户即时反馈,避免无效输入浪费带宽和后端算力
|
|
10
|
+
- **网关 = 流量边界**:Nginx / CDN / 负载均衡层拦截异常大请求,保护后端不被打满
|
|
11
|
+
- **后端 = 业务边界**:字段级严格校验,阻断绕过前端的恶意请求
|
|
12
|
+
- 三层职责不可互相替代。只靠前端易被绕过;只靠后端流量先耗在 TCP/TLS 握手和解析上;只靠网关无法挡住"多个小字段组合起来刚好达到 body 上限"的攻击
|
|
13
|
+
|
|
14
|
+
三层数字必须对齐:**前端 maxlength ≤ 后端 max_length**,**后端字段累加加冗余 ≤ 网关 client_max_body_size**。
|
|
15
|
+
|
|
16
|
+
## 第一层:前端输入限制
|
|
17
|
+
|
|
18
|
+
### 强制规则
|
|
19
|
+
|
|
20
|
+
- 所有 `<input type="text">` / `<input type="search">` / `<textarea>` 必须设 `maxlength` 属性
|
|
21
|
+
- `@dwydev/eui` 的 `EInput` / `ETextarea` / 可搜索 `ESelect` / 可输入 `ETag` 必须传 `maxlength` prop
|
|
22
|
+
- 富文本编辑器(tiptap / quill 等)必须配置字符数上限,超出禁止输入
|
|
23
|
+
- 文件选择控件必须在前端预校验大小和 MIME 类型(`accept` 属性 + JS 二次校验)
|
|
24
|
+
- 批量操作前端必须做分页 / 分批,不允许一次性超过 items 上限
|
|
25
|
+
- 表单校验层必须用 zod `.max()` 再补一道,防粘贴 / 脚本绕过 HTML `maxlength`
|
|
26
|
+
|
|
27
|
+
### 禁止事项
|
|
28
|
+
|
|
29
|
+
- 禁止 `EInput` / `ETextarea` 不带 `maxlength` 上线
|
|
30
|
+
- 禁止富文本编辑器无字符上限
|
|
31
|
+
- 禁止"前端不限制,全部让后端兜底"
|
|
32
|
+
- 禁止大文件(>10MB)走普通 API 中转
|
|
33
|
+
|
|
34
|
+
### 示例
|
|
35
|
+
|
|
36
|
+
```vue
|
|
37
|
+
<!-- ✅ 正确 -->
|
|
38
|
+
<EInput v-model="form.title" :maxlength="100" show-word-limit />
|
|
39
|
+
<ETextarea v-model="form.desc" :maxlength="500" show-word-limit />
|
|
40
|
+
|
|
41
|
+
<!-- ❌ 违规 -->
|
|
42
|
+
<EInput v-model="form.title" />
|
|
43
|
+
<ETextarea v-model="form.desc" />
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
配套 zod schema(vee-validate):
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { z } from 'zod'
|
|
50
|
+
|
|
51
|
+
const schema = z.object({
|
|
52
|
+
title: z.string().max(100),
|
|
53
|
+
desc: z.string().max(500),
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 第二层:网关 / 部署限制
|
|
58
|
+
|
|
59
|
+
### 强制规则
|
|
60
|
+
|
|
61
|
+
- Nginx `client_max_body_size` 必须显式配置,不允许使用默认值
|
|
62
|
+
- 无文件上传业务时:全局 `client_max_body_size 1m`,**禁止** > `10m`
|
|
63
|
+
- 有上传业务时:针对上传路径单独放宽(如 `location /api/upload` 设 `20m`),**禁止**全局放宽
|
|
64
|
+
- 上传大文件(>10MB)必须走对象存储直传(MinIO / S3 预签名 URL),**禁止**走 API 中转
|
|
65
|
+
- CDN / 负载均衡层的 body 限制和超时必须与 Nginx 数字对齐
|
|
66
|
+
|
|
67
|
+
### 示例
|
|
68
|
+
|
|
69
|
+
```nginx
|
|
70
|
+
# server 块 — 全局默认
|
|
71
|
+
client_max_body_size 1m;
|
|
72
|
+
client_body_timeout 10s;
|
|
73
|
+
client_header_timeout 10s;
|
|
74
|
+
|
|
75
|
+
# 仅上传路径放宽
|
|
76
|
+
location /api/upload {
|
|
77
|
+
client_max_body_size 20m;
|
|
78
|
+
proxy_pass http://127.0.0.1:8000;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 违规检测
|
|
83
|
+
|
|
84
|
+
- Nginx 配置缺少 `client_max_body_size` 或值 > `10m` 但业务不是文件上传
|
|
85
|
+
- 大文件上传路由走 API 中转而非对象存储直传
|
|
86
|
+
- CDN 和 Nginx 的 body 上限不一致
|
|
87
|
+
|
|
88
|
+
## 第三层:后端数据校验
|
|
89
|
+
|
|
90
|
+
### 强制规则
|
|
91
|
+
|
|
92
|
+
- Pydantic 每个 `str` 字段必须 `max_length`
|
|
93
|
+
- Pydantic 每个 `list` 字段必须 `max_length`(限制数组元素数量)
|
|
94
|
+
- `Query()` / `Path()` / `Header()` 参数同样必须 `max_length`
|
|
95
|
+
- FastAPI 路由必须显式声明 Pydantic schema,**禁止** `data: dict` / `data: Any`
|
|
96
|
+
- 分页 `page_size` 必须有 `le`(默认 `le=100`)
|
|
97
|
+
- 后端不信任网关,必须在中间件做 request body 大小二次兜底(超出直接 413)
|
|
98
|
+
- 图片上传除文件大小外,**必须**校验实际像素尺寸(Pillow `image.size`),防 decompression bomb
|
|
99
|
+
- 文件大小后端二次校验,不信任前端声明的 `Content-Length`
|
|
100
|
+
|
|
101
|
+
### 示例
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from pydantic import BaseModel, Field
|
|
105
|
+
|
|
106
|
+
# ✅ 正确
|
|
107
|
+
class UserCreate(BaseModel):
|
|
108
|
+
name: str = Field(max_length=32)
|
|
109
|
+
title: str = Field(max_length=100)
|
|
110
|
+
desc: str = Field(max_length=500)
|
|
111
|
+
tags: list[str] = Field(max_length=20)
|
|
112
|
+
|
|
113
|
+
class ListParams(BaseModel):
|
|
114
|
+
page: int = Field(default=1, ge=1)
|
|
115
|
+
page_size: int = Field(default=20, ge=1, le=100)
|
|
116
|
+
|
|
117
|
+
# ❌ 违规
|
|
118
|
+
@router.post("/users")
|
|
119
|
+
async def create_user(data: dict): ...
|
|
120
|
+
|
|
121
|
+
class BadParams(BaseModel):
|
|
122
|
+
page_size: int = 20 # 无 le,攻击者可传 999999
|
|
123
|
+
name: str # 无 max_length
|
|
124
|
+
tags: list[str] # 无 max_length
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
> 说明:格式校验(`EmailStr` / 手机号 `pattern` / `HttpUrl` / 数字 `ge` / `le` 的数值范围)不是长度议题,仍归属 `dwy-python-security.md` §四,本文件不重复。
|
|
128
|
+
|
|
129
|
+
## 统一尺寸参考表
|
|
130
|
+
|
|
131
|
+
三层数字必须对齐。下表为全局默认,项目 CLAUDE.md 可为特殊业务覆盖个别字段(须显式说明原因)。
|
|
132
|
+
|
|
133
|
+
| 场景 | 前端 maxlength | 后端 max_length | 网关 / 上传 |
|
|
134
|
+
|------|---------------|----------------|-------------|
|
|
135
|
+
| 用户名 | 32 | 32 | — |
|
|
136
|
+
| 邮箱 | 254 | 254(RFC 5321) | — |
|
|
137
|
+
| 密码(输入框) | 128 | 128 | — |
|
|
138
|
+
| 手机号 | 20 | 20 | — |
|
|
139
|
+
| 标题 / 短名称 | 100 | 100 | — |
|
|
140
|
+
| 描述 / 摘要 | 500 | 500 | — |
|
|
141
|
+
| 正文 / 评论 | 2000 | 2000 | — |
|
|
142
|
+
| 富文本(HTML 串) | 100 KB | 100 KB | 走 body_size |
|
|
143
|
+
| 搜索关键词 | 100 | 100 | — |
|
|
144
|
+
| URL 字段 | 2048 | 2048 | — |
|
|
145
|
+
| JSON body(默认) | — | 中间件兜底 1 MB | `client_max_body_size 1m` |
|
|
146
|
+
| 图片上传(直发 API) | 前端预检 5 MB | 5 MB + 像素 `<= 8000×8000` | 上传路径 `10m` |
|
|
147
|
+
| 通用小文件上传 | 前端预检 10 MB | 10 MB | 上传路径 `20m` |
|
|
148
|
+
| 大文件(>10 MB) | — | — | 走对象存储直传,不过 API |
|
|
149
|
+
| 批量接口 items | UI 分批 | `max_length=100` | — |
|
|
150
|
+
| 查询分页 page_size | — | `le=100` | — |
|
|
151
|
+
|
|
152
|
+
### 边界原则
|
|
153
|
+
|
|
154
|
+
- 前端 `maxlength` ≤ 后端 `max_length`(前端更严,UX 明确)
|
|
155
|
+
- 后端所有字段 `max_length` 总和加冗余 ≤ 网关 `client_max_body_size`
|
|
156
|
+
- 超出表中范围的业务必须在项目 CLAUDE.md 中显式记录并说明原因
|
|
157
|
+
|
|
158
|
+
## 全局禁止事项
|
|
159
|
+
|
|
160
|
+
- 禁止任一层以"无限制"上线
|
|
161
|
+
- 禁止三层数字互相冲突(例如前端 1000 但后端 100)
|
|
162
|
+
- 禁止只靠前端 `maxlength` 而后端不校验
|
|
163
|
+
- 禁止只靠后端 `max_length` 而前端不限
|
|
164
|
+
- 禁止只靠网关 `client_max_body_size` 而无字段级 `max_length`
|
|
165
|
+
|
|
166
|
+
## 违规检测
|
|
167
|
+
|
|
168
|
+
发现以下任一情况,立即停止并提示用户:
|
|
169
|
+
|
|
170
|
+
1. `.vue` 文件中 `EInput` / `ETextarea` 没有 `maxlength`
|
|
171
|
+
2. 富文本组件(tiptap / quill)未配置字符上限
|
|
172
|
+
3. Pydantic `BaseModel` 有 `str` 字段但未设 `max_length`
|
|
173
|
+
4. Pydantic `BaseModel` 有 `list` 字段但未设 `max_length`
|
|
174
|
+
5. FastAPI 路由以 `dict` / `Any` 作为 body 参数
|
|
175
|
+
6. 分页参数无 `le` 上限
|
|
176
|
+
7. Nginx 配置缺失 `client_max_body_size`,或值 > `10m` 但业务不是文件上传
|
|
177
|
+
8. 上传 > 10MB 文件走 API 中转而非对象存储直传
|
|
178
|
+
9. 图片上传仅校验文件大小而不校验像素尺寸
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 后端/前端/Flutter/Monorepo 项目目录结构模板(按项目入口文件触发)
|
|
3
|
+
paths:
|
|
4
|
+
- "**/package.json"
|
|
5
|
+
- "**/pyproject.toml"
|
|
6
|
+
- "**/pubspec.yaml"
|
|
7
|
+
- "**/pnpm-workspace.yaml"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 项目目录结构模板
|
|
11
|
+
|
|
12
|
+
AI 创建文件时**必须**遵循以下目录结构,不得自造目录名或层级。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 一、后端项目(FastAPI)
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
backend/
|
|
20
|
+
├── src/app/
|
|
21
|
+
│ ├── __init__.py
|
|
22
|
+
│ ├── main.py # FastAPI 应用入口 + lifespan
|
|
23
|
+
│ ├── config.py # 继承 eapi BaseSettings
|
|
24
|
+
│ ├── database.py # create_async_engine_factory + create_session_factory
|
|
25
|
+
│ ├── dependencies.py # FastAPI Depends(get_db, get_current_user)
|
|
26
|
+
│ ├── exceptions.py # 项目级异常(继承 eapi AppError)
|
|
27
|
+
│ ├── validators.py # 输入校验工具(防注入等)
|
|
28
|
+
│ ├── models/ # SQLAlchemy ORM 模型
|
|
29
|
+
│ │ ├── __init__.py
|
|
30
|
+
│ │ ├── user.py # 每个实体一个文件
|
|
31
|
+
│ │ └── ...
|
|
32
|
+
│ ├── schemas/ # Pydantic v2 请求/响应模型
|
|
33
|
+
│ │ ├── __init__.py
|
|
34
|
+
│ │ ├── user.py # UserCreate, UserUpdate, UserResponse
|
|
35
|
+
│ │ └── ...
|
|
36
|
+
│ ├── routers/ # FastAPI 路由(按业务域拆分)
|
|
37
|
+
│ │ ├── __init__.py
|
|
38
|
+
│ │ ├── auth.py # 认证端点
|
|
39
|
+
│ │ ├── user.py # 每个业务域一个文件
|
|
40
|
+
│ │ └── ...
|
|
41
|
+
│ ├── services/ # 业务逻辑层
|
|
42
|
+
│ │ ├── __init__.py
|
|
43
|
+
│ │ ├── auth.py
|
|
44
|
+
│ │ ├── user.py # 与 router 同名,一一对应
|
|
45
|
+
│ │ └── ...
|
|
46
|
+
│ ├── tasks.py # ARQ 任务注册(@register 装饰器)
|
|
47
|
+
│ └── worker.py # ARQ Worker 入口
|
|
48
|
+
├── alembic/ # 数据库迁移
|
|
49
|
+
│ ├── versions/ # 迁移文件
|
|
50
|
+
│ ├── env.py
|
|
51
|
+
│ └── alembic.ini
|
|
52
|
+
├── scripts/ # 初始化/运维脚本
|
|
53
|
+
│ ├── init_db.py # 初始化数据库表结构
|
|
54
|
+
│ └── seed_admin.py # 创建初始管理员
|
|
55
|
+
├── tests/
|
|
56
|
+
│ ├── conftest.py # pytest fixtures(SQLite 内存库、mock)
|
|
57
|
+
│ ├── test_auth.py # 与 routers/ 同名
|
|
58
|
+
│ └── ...
|
|
59
|
+
├── pyproject.toml # UV 依赖配置
|
|
60
|
+
├── Dockerfile.dev # 开发容器(--reload)
|
|
61
|
+
├── Dockerfile.prod # 生产容器(只读、non-root)
|
|
62
|
+
├── .env.example # 环境变量模板
|
|
63
|
+
└── TEST_CASES.md # 测试用例清单
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**强制规则:**
|
|
67
|
+
- 分层:`routers → schemas → services → models → database`,不可跨层调用
|
|
68
|
+
- services 层抛 eapi 异常(AppError 子类),**不抛 HTTPException**
|
|
69
|
+
- routers 层只做参数接收和 response 包装,**不写业务逻辑**
|
|
70
|
+
- models/ schemas/ routers/ services/ 四个目录内文件按业务域一一对应
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 二、前端项目(Vue 3)
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
frontend/
|
|
78
|
+
├── src/
|
|
79
|
+
│ ├── main.ts # createApp + 插件注册
|
|
80
|
+
│ ├── App.vue # 根组件
|
|
81
|
+
│ ├── router/
|
|
82
|
+
│ │ └── index.ts # Vue Router 配置 + 守卫
|
|
83
|
+
│ ├── stores/ # Pinia Setup Store
|
|
84
|
+
│ │ ├── auth.ts # 认证状态
|
|
85
|
+
│ │ └── ...
|
|
86
|
+
│ ├── api/ # HTTP 客户端(按业务域拆分)
|
|
87
|
+
│ │ ├── client.ts # ekit createRequest() 实例
|
|
88
|
+
│ │ ├── auth.ts # 登录/注册接口
|
|
89
|
+
│ │ ├── user.ts # 用户接口
|
|
90
|
+
│ │ └── ...
|
|
91
|
+
│ ├── views/ # 页面级组件(路由对应)
|
|
92
|
+
│ │ ├── LoginView.vue
|
|
93
|
+
│ │ ├── DashboardView.vue
|
|
94
|
+
│ │ └── ...
|
|
95
|
+
│ ├── components/ # 共享 UI 组件(非页面级)
|
|
96
|
+
│ ├── composables/ # Vue 3 组合式函数(use* 前缀)
|
|
97
|
+
│ ├── utils/ # 纯工具函数
|
|
98
|
+
│ └── index.css # Tailwind CSS 入口
|
|
99
|
+
├── tests/
|
|
100
|
+
│ ├── api/
|
|
101
|
+
│ ├── stores/
|
|
102
|
+
│ ├── router/
|
|
103
|
+
│ └── utils/
|
|
104
|
+
├── package.json
|
|
105
|
+
├── vite.config.ts
|
|
106
|
+
├── tsconfig.json
|
|
107
|
+
├── Dockerfile # 生产构建(多阶段)
|
|
108
|
+
└── TEST_CASES.md
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**强制规则:**
|
|
112
|
+
- views/ 放页面组件(路由直接引用),components/ 放复用组件
|
|
113
|
+
- api/ 每个文件对应后端一个 router 模块,保持命名一致
|
|
114
|
+
- stores/ 统一 Setup Store 写法(`export const useXxxStore = defineStore('xxx', () => {...})`)
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 三、Flutter 项目
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
lib/
|
|
122
|
+
├── main.dart # runApp + ProviderScope
|
|
123
|
+
├── app.dart # MaterialApp.router + GoRouter
|
|
124
|
+
├── core/
|
|
125
|
+
│ ├── config/
|
|
126
|
+
│ │ └── env.dart # 环境配置
|
|
127
|
+
│ ├── network/
|
|
128
|
+
│ │ ├── dio_client.dart # Dio 实例 + 拦截器
|
|
129
|
+
│ │ └── api_response.dart # 统一响应模型(对齐 eapi 格式)
|
|
130
|
+
│ ├── storage/
|
|
131
|
+
│ │ └── secure_storage.dart
|
|
132
|
+
│ ├── theme/
|
|
133
|
+
│ │ └── app_theme.dart # ThemeData + 设计 tokens
|
|
134
|
+
│ └── utils/
|
|
135
|
+
├── features/ # 按功能模块拆分(feature-first)
|
|
136
|
+
│ └── {feature_name}/
|
|
137
|
+
│ ├── data/
|
|
138
|
+
│ │ ├── {feature}_repository.dart # Repository 实现
|
|
139
|
+
│ │ └── {feature}_dto.dart # 数据传输对象
|
|
140
|
+
│ ├── domain/
|
|
141
|
+
│ │ └── {feature}_entity.dart # 领域实体
|
|
142
|
+
│ └── presentation/
|
|
143
|
+
│ ├── {feature}_page.dart # 页面
|
|
144
|
+
│ ├── {feature}_provider.dart # Riverpod Provider
|
|
145
|
+
│ └── widgets/ # 功能内专属 Widget
|
|
146
|
+
├── shared/
|
|
147
|
+
│ ├── providers/ # 全局 Provider(auth, theme)
|
|
148
|
+
│ ├── widgets/ # 跨功能共享 Widget
|
|
149
|
+
│ └── models/ # 共享数据模型
|
|
150
|
+
test/
|
|
151
|
+
├── features/
|
|
152
|
+
│ └── {feature_name}/
|
|
153
|
+
└── core/
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**强制规则:**
|
|
157
|
+
- features/ 按功能模块拆分,每个模块自包含 data/domain/presentation
|
|
158
|
+
- core/ 放全局基础设施(网络、存储、主题),不放业务代码
|
|
159
|
+
- shared/ 放跨功能共享的 provider/widget/model
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 四、Monorepo 项目结构(pnpm workspace)
|
|
164
|
+
|
|
165
|
+
当项目包含前端 + 后端时,使用 monorepo:
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
project-root/
|
|
169
|
+
├── backend/ # FastAPI 后端(上述第一节结构)
|
|
170
|
+
├── frontend/ # Vue 前端(上述第二节结构)
|
|
171
|
+
├── mobile/ # Flutter 移动端(上述第三节结构,独立管理)
|
|
172
|
+
├── docker-compose.dev.yml # 开发环境
|
|
173
|
+
├── docker-compose.prod.yml # 生产环境
|
|
174
|
+
├── dev.sh # 一键启动脚本
|
|
175
|
+
├── pnpm-workspace.yaml # pnpm monorepo 配置
|
|
176
|
+
├── package.json # 根 package.json(scripts)
|
|
177
|
+
├── CLAUDE.md # 项目规范
|
|
178
|
+
└── .env.example # 全局环境变量模板
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**注意:** Flutter 项目(mobile/)不纳入 pnpm workspace,独立用 `flutter pub get` 管理依赖。
|