create-dwy 0.8.0 → 0.9.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.
Files changed (98) hide show
  1. package/package.json +1 -1
  2. package/src/create.js +50 -3
  3. package/src/utils.js +8 -0
  4. package/templates/claude-global/CLAUDE.md +81 -6
  5. package/templates/claude-global/rules/dwy-postgres.md +89 -0
  6. package/templates/claude-global/rules/dwy-python-backend.md +492 -0
  7. package/templates/claude-global/rules/dwy-python-core.md +94 -634
  8. package/templates/claude-global/rules/dwy-python-testing.md +115 -13
  9. package/templates/claude-global/rules/dwy-redis.md +88 -0
  10. package/templates/claude-global/rules/dwy-vue-core.md +341 -645
  11. package/templates/claude-global/rules/dwy-vue-pinia.md +47 -34
  12. package/templates/claude-global/rules/dwy-vue-testing.md +120 -55
  13. package/templates/claude-global/skills/dwy-deploy-audit/references/checks-network.md +1 -1
  14. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_nginx.sh +1 -1
  15. package/templates/claude-global/skills/dwy-dolphindb/SKILL.md +22 -15
  16. package/templates/claude-global/skills/dwy-dolphindb/evals/evals.json +23 -0
  17. package/templates/claude-global/skills/dwy-dolphindb/references/dolphindb-rules.md +100 -1
  18. package/templates/claude-global/skills/dwy-ekit/SKILL.md +142 -276
  19. package/templates/claude-global/skills/dwy-eui/SKILL.md +264 -182
  20. package/templates/claude-global/skills/dwy-fullstack-scaffold/SKILL.md +117 -129
  21. package/templates/claude-global/skills/dwy-git-commit/SKILL.md +125 -0
  22. package/templates/claude-global/skills/dwy-publish/SKILL.md +1 -1
  23. package/templates/claude-global/{rules/dwy-tech-stack.md → skills/dwy-tech-stack/SKILL.md} +4 -3
  24. package/templates/project/fullstack-monorepo/CLAUDE.md.hbs +81 -0
  25. package/templates/project/fullstack-monorepo/_env.example.hbs +24 -0
  26. package/templates/project/fullstack-monorepo/_gitignore +37 -0
  27. package/templates/project/fullstack-monorepo/backend/.python-version +1 -0
  28. package/templates/project/fullstack-monorepo/backend/CLAUDE.md.hbs +68 -0
  29. package/templates/project/fullstack-monorepo/backend/Dockerfile.dev +23 -0
  30. package/templates/project/fullstack-monorepo/backend/alembic/env.py.hbs +68 -0
  31. package/templates/project/fullstack-monorepo/backend/alembic/script.py.mako +26 -0
  32. package/templates/project/fullstack-monorepo/backend/alembic.ini.hbs +43 -0
  33. package/templates/project/fullstack-monorepo/backend/packages/dwy-shared/pyproject.toml +16 -0
  34. package/templates/project/fullstack-monorepo/backend/packages/dwy-shared/src/dwy_shared/__init__.py +12 -0
  35. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/pyproject.toml.hbs +20 -0
  36. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/src/{{scopePrefix}}_{{initialDomain}}/__init__.py.hbs +40 -0
  37. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/src/{{scopePrefix}}_{{initialDomain}}/config.py +9 -0
  38. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/src/{{scopePrefix}}_{{initialDomain}}/models.py.hbs +17 -0
  39. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/src/{{scopePrefix}}_{{initialDomain}}/protocols.py +14 -0
  40. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/src/{{scopePrefix}}_{{initialDomain}}/router.py.hbs +22 -0
  41. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/src/{{scopePrefix}}_{{initialDomain}}/schemas.py +21 -0
  42. package/templates/project/fullstack-monorepo/backend/packages/{{scopePrefix}}-{{initialDomain}}/src/{{scopePrefix}}_{{initialDomain}}/service.py +11 -0
  43. package/templates/project/fullstack-monorepo/backend/pyproject.toml.hbs +84 -0
  44. package/templates/project/fullstack-monorepo/backend/src/app/__init__.py +3 -0
  45. package/templates/project/fullstack-monorepo/backend/src/app/config.py.hbs +21 -0
  46. package/templates/project/fullstack-monorepo/backend/src/app/exceptions.py +26 -0
  47. package/templates/project/fullstack-monorepo/backend/src/app/factories.py +16 -0
  48. package/templates/project/fullstack-monorepo/backend/src/app/infra/__init__.py +1 -0
  49. package/templates/project/fullstack-monorepo/backend/src/app/main.py.hbs +65 -0
  50. package/templates/project/fullstack-monorepo/backend/src/app/middleware/__init__.py +1 -0
  51. package/templates/project/fullstack-monorepo/backend/tests/__init__.py +0 -0
  52. package/templates/project/fullstack-monorepo/backend/tests/conftest.py.hbs +42 -0
  53. package/templates/project/fullstack-monorepo/dev.sh.hbs +83 -0
  54. package/templates/project/fullstack-monorepo/docker-compose.dev.yml.hbs +36 -0
  55. package/templates/project/fullstack-monorepo/frontend/CLAUDE.md.hbs +35 -0
  56. package/templates/project/fullstack-monorepo/frontend/Dockerfile +18 -0
  57. package/templates/project/fullstack-monorepo/frontend/_npmrc +3 -0
  58. package/templates/project/fullstack-monorepo/frontend/apps/web/index.html.hbs +13 -0
  59. package/templates/project/fullstack-monorepo/frontend/apps/web/package.json.hbs +31 -0
  60. package/templates/project/fullstack-monorepo/frontend/apps/web/src/App.vue.hbs +10 -0
  61. package/templates/project/fullstack-monorepo/frontend/apps/web/src/api/client.ts.hbs +11 -0
  62. package/templates/project/fullstack-monorepo/frontend/apps/web/src/features/{{initialDomain}}/.gitkeep +0 -0
  63. package/templates/project/fullstack-monorepo/frontend/apps/web/src/index.css +12 -0
  64. package/templates/project/fullstack-monorepo/frontend/apps/web/src/main.ts +17 -0
  65. package/templates/project/fullstack-monorepo/frontend/apps/web/src/router/index.ts.hbs +24 -0
  66. package/templates/project/fullstack-monorepo/frontend/apps/web/src/stores/.gitkeep +0 -0
  67. package/templates/project/fullstack-monorepo/frontend/apps/web/src/types/.gitkeep +0 -0
  68. package/templates/project/fullstack-monorepo/frontend/apps/web/src/views/HomeView.vue.hbs +36 -0
  69. package/templates/project/fullstack-monorepo/frontend/apps/web/tsconfig.json +7 -0
  70. package/templates/project/fullstack-monorepo/frontend/apps/web/vite.config.ts.hbs +27 -0
  71. package/templates/project/fullstack-monorepo/frontend/nginx.conf +11 -0
  72. package/templates/project/fullstack-monorepo/frontend/package.json.hbs +13 -0
  73. package/templates/project/fullstack-monorepo/frontend/packages/core/package.json.hbs +15 -0
  74. package/templates/project/fullstack-monorepo/frontend/packages/core/src/index.ts +3 -0
  75. package/templates/project/fullstack-monorepo/frontend/packages/features/{{initialDomain}}/package.json.hbs +14 -0
  76. package/templates/project/fullstack-monorepo/frontend/packages/features/{{initialDomain}}/src/index.ts.hbs +16 -0
  77. package/templates/project/fullstack-monorepo/frontend/packages/features/{{initialDomain}}/src/pages/IndexPage.vue.hbs +9 -0
  78. package/templates/project/fullstack-monorepo/frontend/packages/ui/package.json.hbs +15 -0
  79. package/templates/project/fullstack-monorepo/frontend/packages/ui/src/index.ts +3 -0
  80. package/templates/project/fullstack-monorepo/frontend/pnpm-workspace.yaml.hbs +23 -0
  81. package/templates/project/fullstack-monorepo/frontend/tsconfig.base.json.hbs +23 -0
  82. package/templates/claude-global/rules/dwy-api-design.md +0 -110
  83. package/templates/claude-global/rules/dwy-git-commit-convention.md +0 -82
  84. package/templates/claude-global/rules/dwy-git-security.md +0 -53
  85. package/templates/claude-global/rules/dwy-payload-limits.md +0 -186
  86. package/templates/claude-global/rules/dwy-prefer-open-source.md +0 -32
  87. package/templates/claude-global/rules/dwy-project-structure.md +0 -181
  88. package/templates/claude-global/rules/dwy-python-fastapi.md +0 -272
  89. package/templates/claude-global/rules/dwy-python-orm.md +0 -61
  90. package/templates/claude-global/rules/dwy-python-security.md +0 -636
  91. package/templates/claude-global/rules/dwy-server-security.md +0 -518
  92. package/templates/claude-global/rules/dwy-vue-api.md +0 -146
  93. package/templates/claude-global/skills/dwy-ekit/references/data.md +0 -135
  94. package/templates/claude-global/skills/dwy-ekit/references/form.md +0 -68
  95. package/templates/claude-global/skills/dwy-ekit/references/request.md +0 -183
  96. package/templates/claude-global/skills/dwy-ekit/references/ui.md +0 -109
  97. package/templates/claude-global/skills/dwy-vue-core/SKILL.md +0 -890
  98. /package/templates/{claude-global/commands → project/fullstack-monorepo/backend/alembic/versions}/.gitkeep +0 -0
@@ -1,518 +0,0 @@
1
- ---
2
- description: 服务器/容器/Nginx/SSH/CORS/部署安全规范
3
- paths:
4
- - "**/docker-compose*.yml"
5
- - "**/Dockerfile*"
6
- - "**/nginx*.conf"
7
- - "**/deploy*.sh"
8
- - "**/.env.example"
9
- ---
10
-
11
- # 服务器安全部署规则
12
-
13
- 所有项目部署到云服务器时必须遵循以下规则。如果任何操作违反这些规则,必须**立即提示用户并获得明确确认**后才能继续。
14
-
15
- ## 一、端口与网络隔离
16
-
17
- ### 强制规则
18
- - 数据库(PostgreSQL/MySQL/Redis 等)**禁止暴露到宿主机端口**,仅通过 Docker 内部网络访问
19
- - 后端应用端口绑定 `127.0.0.1`,不允许 `0.0.0.0`
20
- - 仅 Nginx/反向代理的 80/443 端口绑定 `0.0.0.0`
21
-
22
- ### docker-compose 示例
23
- ```yaml
24
- # ✅ 正确
25
- backend:
26
- ports:
27
- - "127.0.0.1:{port}:{port}"
28
-
29
- db:
30
- # 不写 ports,仅内部网络
31
-
32
- # ❌ 违规 — 需要提示用户
33
- db:
34
- ports:
35
- - "{db_port}:{db_port}"
36
- backend:
37
- ports:
38
- - "{port}:{port}"
39
- ```
40
-
41
- ## 二、防火墙
42
-
43
- ### 强制规则
44
- - 生产服务器**必须启用防火墙**(ufw 或 iptables)
45
- - **只开放业务必需端口**,其余全部关闭
46
-
47
- ### 最小端口策略
48
-
49
- | 端口 | 用途 | 开放方式 |
50
- |------|------|---------|
51
- | 80 | HTTP(Nginx) | `ufw allow 80/tcp` |
52
- | 443 | HTTPS(Nginx) | `ufw allow 443/tcp` |
53
- | SSH 非标端口 | SSH 远程管理 | `ufw allow {ssh_port}/tcp` |
54
-
55
- **禁止开放的端口:**
56
- - 5432(PostgreSQL)
57
- - 6379(Redis)
58
- - 9000(MinIO)
59
- - 8000-9999(后端应用)
60
-
61
- ### 配置示例
62
- ```bash
63
- ufw default deny incoming
64
- ufw default allow outgoing
65
- ufw allow 80/tcp
66
- ufw allow 443/tcp
67
- ufw allow {ssh_port}/tcp
68
- ufw enable
69
- ```
70
-
71
- ### 违规检测
72
- 如果在部署脚本或命令中发现 `ufw allow 5432` 等数据库端口开放命令,必须立即提示用户。
73
-
74
- ## 三、凭证与密钥管理
75
-
76
- ### 强制规则
77
- - **禁止在代码中硬编码**数据库密码、API Key、Secret 等凭证
78
- - 所有凭证通过 `.env` 文件或环境变量注入
79
- - `.env` 文件必须在 `.gitignore` 中排除
80
- - 数据库密码最少 24 位,包含大小写字母和数字
81
- - 提供 `.env.example` 模板文件(仅含占位符,不含真实值)
82
-
83
- ### 违规检测
84
- 如果在代码中发现以下内容,必须提示用户:
85
- - 硬编码的数据库连接字符串含真实密码
86
- - API Key 出现在非 `.env` 文件中
87
- - SSH 密码、私钥路径出现在代码或文档中
88
-
89
- ## 四、Nginx 安全配置
90
-
91
- ### 核心原则
92
- **只开放业务必需的路径和方法,其余一律拒绝。**
93
-
94
- ### 强制规则
95
-
96
- 每个项目的 Nginx 配置必须包含以下安全基线(具体路径、端口、超时时间根据项目在项目级 CLAUDE.md 中配置):
97
-
98
- **1. 频率限制(http 块)**
99
- ```nginx
100
- limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
101
- limit_req_zone $binary_remote_addr zone=login_limit:10m rate=3r/m;
102
- limit_req_zone $binary_remote_addr zone=page_limit:10m rate=30r/s;
103
- limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
104
- ```
105
-
106
- 注意:`limit_req_zone` 和 `limit_conn_zone` **必须放在 `http` 块**,不能放在 `server` 块。
107
-
108
- **2. 安全响应头(server 块)**
109
- ```nginx
110
- add_header X-Frame-Options "SAMEORIGIN" always;
111
- add_header X-Content-Type-Options "nosniff" always;
112
- add_header X-XSS-Protection "1; mode=block" always;
113
- add_header Referrer-Policy "strict-origin-when-cross-origin" always;
114
- add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" always;
115
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
116
- ```
117
-
118
- **3. HTTPS 强制(server 块)**
119
- ```nginx
120
- # HTTP → HTTPS 重定向
121
- server {
122
- listen 80;
123
- server_name example.com;
124
- return 301 https://$server_name$request_uri;
125
- }
126
- ```
127
-
128
- 生产环境**必须启用 HTTPS**,使用 certbot 自动续期:
129
- ```bash
130
- certbot --nginx -d example.com
131
- ```
132
-
133
- **4. 全局限制(server 块)**
134
- ```nginx
135
- client_body_timeout 10s;
136
- client_header_timeout 10s;
137
- limit_conn conn_limit 20;
138
- ```
139
-
140
- **5. 敏感文件屏蔽(最高优先级)**
141
- ```nginx
142
- location ~ /\. {
143
- deny all;
144
- return 404;
145
- }
146
-
147
- location ~* \.(env|git|xlsx|sql|log|bak|dump|tar|gz|zip|csv)$ {
148
- deny all;
149
- return 404;
150
- }
151
- ```
152
-
153
- **6. API 路径最小化**
154
- ```nginx
155
- location /api {
156
- limit_except GET POST {
157
- deny all;
158
- }
159
- limit_req zone=api_limit burst=20 nodelay;
160
- # proxy_pass 等具体配置由项目决定
161
- }
162
- ```
163
-
164
- **7. 登录接口专用限流**
165
- ```nginx
166
- location /api/auth/login {
167
- limit_req zone=login_limit burst=5 nodelay;
168
- proxy_pass http://127.0.0.1:{backend_port};
169
- proxy_set_header Host $host;
170
- proxy_set_header X-Real-IP $remote_addr;
171
- }
172
- ```
173
-
174
- **8. 攻击路径屏蔽**
175
- ```nginx
176
- location ~ ^/(admin|phpmyadmin|wp-admin|cgi-bin|actuator|console|debug|\.well-known/security\.txt) {
177
- deny all;
178
- return 404;
179
- }
180
- ```
181
-
182
- **9. 扫描器 User-Agent 屏蔽(http 块)**
183
- ```nginx
184
- map $http_user_agent $is_scanner {
185
- default 0;
186
- ~*sqlmap 1;
187
- ~*nmap 1;
188
- ~*nikto 1;
189
- ~*dirbuster 1;
190
- ~*gobuster 1;
191
- ~*masscan 1;
192
- ~*zgrab 1;
193
- ~*python-requests 1;
194
- }
195
-
196
- # 在 server 块中
197
- if ($is_scanner) {
198
- return 403;
199
- }
200
- ```
201
-
202
- ### 违规检测
203
- 如果 Nginx 配置中出现以下情况,必须提示用户:
204
- - 缺少 `limit_req` 频率限制
205
- - API 路径允许 PUT/DELETE 但业务不需要
206
- - 缺少 `location ~ /\.` 敏感文件屏蔽
207
- - 使用 `proxy_pass` 但未设置 `proxy_connect_timeout`
208
- - 生产环境未启用 HTTPS
209
- - 缺少登录接口专用限流
210
-
211
- ### 部署后必须验证
212
- ```bash
213
- # 1. 敏感文件返回 404
214
- curl -s -o /dev/null -w "%{http_code}" http://{server}/.git/config
215
- curl -s -o /dev/null -w "%{http_code}" http://{server}/.env
216
-
217
- # 2. 安全头存在
218
- curl -sI https://{server}/ | grep -i "x-frame-options"
219
- curl -sI https://{server}/ | grep -i "x-content-type-options"
220
- curl -sI https://{server}/ | grep -i "strict-transport-security"
221
-
222
- # 3. 非法方法被拒绝
223
- curl -s -o /dev/null -w "%{http_code}" -X DELETE http://{server}/api/health
224
-
225
- # 4. 攻击路径被屏蔽
226
- curl -s -o /dev/null -w "%{http_code}" http://{server}/phpmyadmin
227
-
228
- # 5. 扫描器 UA 被拒绝
229
- curl -s -o /dev/null -w "%{http_code}" -A "sqlmap/1.0" http://{server}/
230
-
231
- # 6. 登录限流生效
232
- for i in {1..10}; do curl -s -o /dev/null -w "%{http_code}\n" -X POST http://{server}/api/auth/login; done
233
-
234
- # 7. 正常服务可用
235
- curl -s http://{server}/api/health
236
- ```
237
-
238
- ## 五、Docker 容器安全
239
-
240
- ### 强制规则
241
- - Dockerfile **必须使用非 root 用户**运行应用
242
- - 必须创建 `.dockerignore` 排除 `.env`、`.git`、`cache/`、`__pycache__`
243
- - Python 项目设置 `ENV PYTHONUNBUFFERED=1`
244
- - Node.js 项目设置 `ENV NODE_ENV=production`
245
- - **使用最小化基础镜像**(`python:3.11-slim`,不用 `python:3.11`)
246
- - **禁止在镜像中安装不必要的工具**(ssh、telnet、curl 等调试工具生产不需要)
247
- - 容器文件系统**建议只读挂载**(`read_only: true`),需要写入的目录用 `tmpfs` 或 volume
248
-
249
- ### Dockerfile 安全示例
250
- ```dockerfile
251
- FROM python:3.11-slim
252
-
253
- # 只安装必要的编译依赖,安装后清理
254
- RUN apt-get update && apt-get install -y --no-install-recommends gcc \
255
- && rm -rf /var/lib/apt/lists/*
256
-
257
- WORKDIR /app
258
- COPY pyproject.toml .
259
- RUN pip install --no-cache-dir .
260
-
261
- COPY src/ src/
262
-
263
- # 创建非 root 用户
264
- RUN useradd -m appuser
265
- USER appuser
266
-
267
- CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
268
- ```
269
-
270
- ## 六、CORS 配置
271
-
272
- ### 强制规则
273
- - **禁止生产环境使用 `*` 通配符**
274
- - 必须明确列出允许的域名/IP
275
- - 通过环境变量配置,便于不同环境切换
276
-
277
- ```
278
- # ✅ 正确 — 明确列出
279
- ALLOWED_ORIGINS=["https://example.com","https://www.example.com"]
280
-
281
- # ❌ 违规
282
- ALLOWED_ORIGINS=*
283
- ```
284
-
285
- ## 七、数据安全
286
-
287
- ### 强制规则
288
- - 手机号在返回前必须脱敏(如 `138****5678`)
289
- - 身份证号在返回前必须脱敏(如 `420***********1234`)
290
- - 查询日志中的 PII(姓名、手机号等)建议加密存储
291
- - 数据源文件(Excel/CSV 等)不可通过 Web 直接访问
292
- - 数据库数据仅通过应用层访问,不暴露数据库管理端口
293
-
294
- ## 八、Git 仓库安全
295
-
296
- ### 强制规则
297
- `.gitignore` 必须包含:
298
- ```
299
- .env
300
- *.env
301
- __pycache__/
302
- *.pyc
303
- node_modules/
304
- dist/
305
- *.log
306
- ```
307
-
308
- ### 违规检测
309
- 如果发现以下文件被 `git add`,必须立即阻止并提示用户:
310
- - `.env` 文件
311
- - 含真实密码/密钥的配置文件
312
- - SSH 私钥文件
313
- - 数据库备份文件(`.sql`、`.dump`)
314
- - 含敏感数据的原始数据文件(`.xlsx`、`.csv`)
315
-
316
- ## 九、SSH 安全
317
-
318
- ### 强制规则
319
- - **禁止密码登录**,仅允许密钥认证
320
- - **禁止 root 密码登录**(`PermitRootLogin prohibit-password` 或 `without-password`)
321
- - **禁止使用默认 22 端口**,改为非标端口(如 66)
322
- - SSH 私钥文件(`id_rsa`、`id_ed25519` 等)**禁止出现在代码仓库、文档、聊天记录中**
323
- - 服务器 IP、SSH 端口、用户名**禁止写入代码仓库**(包括 README、部署文档)
324
-
325
- ### 违规检测
326
- 如果在任何文件中发现以下内容,必须立即提示用户:
327
- - SSH 连接命令含完整 IP + 端口 + 用户名
328
- - 服务器凭证信息(IP、端口、密码、密钥路径)
329
- - `sshd_config` 中 `PasswordAuthentication yes`
330
-
331
- ### 安全基线配置(`/etc/ssh/sshd_config`)
332
- ```
333
- Port 66 # 非标端口
334
- PermitRootLogin prohibit-password # 禁止 root 密码登录
335
- PasswordAuthentication no # 禁止所有密码登录
336
- PubkeyAuthentication yes # 启用密钥认证
337
- MaxAuthTries 3 # 最大尝试次数
338
- LoginGraceTime 30 # 登录超时 30 秒
339
- ```
340
-
341
- ### 配合 fail2ban
342
- 服务器**必须配置** fail2ban 防暴力破解:
343
- ```
344
- # /etc/fail2ban/jail.local
345
- [sshd]
346
- enabled = true
347
- port = 66
348
- maxretry = 5
349
- bantime = 3600
350
-
351
- # Nginx 暴力请求封禁
352
- [nginx-limit-req]
353
- enabled = true
354
- filter = nginx-limit-req
355
- logpath = /var/log/nginx/error.log
356
- maxretry = 10
357
- bantime = 600
358
- ```
359
-
360
- ### 部署操作规范
361
- - 通过 SSH 连接服务器时,连接信息从本地 `~/.ssh/config` 读取,不在命令行暴露
362
- - 推荐在 `~/.ssh/config` 中配置 Host 别名:
363
- ```
364
- Host myserver
365
- HostName <ip>
366
- Port <port>
367
- User root
368
- IdentityFile ~/.ssh/id_rsa
369
- ```
370
- - 部署脚本中使用 `ssh myserver` 而非完整连接命令
371
-
372
- ## 十、系统安全加固
373
-
374
- ### 自动安全更新
375
- 生产服务器**必须启用自动安全更新**:
376
- ```bash
377
- apt install -y unattended-upgrades
378
- dpkg-reconfigure -plow unattended-upgrades
379
- ```
380
-
381
- ### 文件权限
382
- | 文件 | 权限 | 命令 |
383
- |------|------|------|
384
- | `.env` | 600(仅所有者读写) | `chmod 600 .env` |
385
- | SSH 私钥 | 600 | `chmod 600 ~/.ssh/id_*` |
386
- | `authorized_keys` | 644 | `chmod 644 ~/.ssh/authorized_keys` |
387
- | 应用目录 | 755 | `chmod 755 /opt/myapp` |
388
-
389
- **禁止出现 777 权限。** 如果在部署脚本中发现 `chmod 777`,必须立即提示用户。
390
-
391
- ### 日志监控
392
- 生产服务器必须定期检查以下日志:
393
- ```bash
394
- # SSH 登录记录
395
- journalctl -u sshd --since "1 hour ago"
396
-
397
- # Nginx 错误日志
398
- tail -100 /var/log/nginx/error.log
399
-
400
- # 被 fail2ban 封禁的 IP
401
- fail2ban-client status sshd
402
-
403
- # Docker 容器日志
404
- docker compose logs --tail 100 backend
405
- ```
406
-
407
- ## 十一、数据持久化与防删除
408
-
409
- ### 核心原则
410
- **所有业务数据必须通过 Docker Named Volume 持久化。任何可能导致数据丢失的操作,必须提前说明原因并获得用户确认。**
411
-
412
- ### 强制规则 — Docker Volume
413
-
414
- - 数据库容器**必须挂载 Named Volume**到数据目录
415
- - **禁止使用匿名卷或仅容器内存储**
416
- - 重启策略必须设为 `unless-stopped` 或 `always`
417
-
418
- ```yaml
419
- # ✅ 正确 — Named Volume 持久化
420
- db:
421
- volumes:
422
- - dbdata:/var/lib/postgresql/data
423
- restart: unless-stopped
424
-
425
- volumes:
426
- dbdata:
427
-
428
- # ❌ 违规 — 数据在容器内,删除即丢失
429
- db:
430
- # 没有 volumes 配置
431
- ```
432
-
433
- ### 危险操作清单
434
-
435
- 以下命令**执行前必须停止、说明原因、说明影响、等待用户确认**:
436
-
437
- | 命令 | 风险等级 | 后果 |
438
- |---|---|---|
439
- | `docker compose down -v` | **致命** | 删除所有 Volume,数据永久丢失 |
440
- | `docker volume rm <name>` | **致命** | 删除指定 Volume,数据永久丢失 |
441
- | `docker volume prune` | **致命** | 删除所有未使用的 Volume |
442
- | `docker system prune -a --volumes` | **致命** | 清除所有镜像、容器、Volume |
443
- | `rm -rf /var/lib/docker/volumes/` | **致命** | 删除所有 Docker 数据 |
444
- | `DROP TABLE` / `DROP DATABASE` | **致命** | 删除数据库表或整个数据库 |
445
- | `DELETE FROM <table>` 无 WHERE | **高危** | 清空整张表数据 |
446
- | `TRUNCATE TABLE` | **高危** | 清空表数据且无法回滚 |
447
- | `rm -rf` 含数据目录 | **高危** | 删除文件系统数据 |
448
- | `git clean -fdx` | **高危** | 删除所有未跟踪文件(含数据文件) |
449
-
450
- ### 违规处理
451
- 当 AI 需要执行以上任何操作时,必须:
452
-
453
- 1. **立即停止**,不执行该命令
454
- 2. **说明原因**:为什么需要执行这个操作
455
- 3. **说明影响**:会删除哪些数据、多少条记录
456
- 4. **提供替代方案**(如有):是否有不删除数据的方式达到目的
457
- 5. **等待用户明确回复"确认"**后才能执行
458
-
459
- ### 备份
460
- 生产环境**必须配置定期备份**:
461
- ```bash
462
- # PostgreSQL 每日备份(建议 cron 每天凌晨执行)
463
- docker exec <db_container> pg_dump -U <user> <database> > backup_$(date +%Y%m%d).sql
464
-
465
- # 备份文件不得放在 Web 可访问目录
466
- # 建议放在 /var/backups/ 下,定期清理超过 30 天的备份
467
- find /var/backups/ -name "backup_*.sql" -mtime +30 -delete
468
- ```
469
-
470
- ## 十二、部署后检查清单
471
-
472
- 每次部署完成后,必须执行以下验证:
473
-
474
- ```bash
475
- # 1. 防火墙状态
476
- ufw status | grep -E "80|443|{ssh_port}"
477
-
478
- # 2. 数据库端口不可外部访问
479
- timeout 3 nc -z {server_ip} 5432 && echo "FAIL" || echo "PASS"
480
- timeout 3 nc -z {server_ip} 6379 && echo "FAIL" || echo "PASS"
481
-
482
- # 3. 后端端口不可外部直连
483
- timeout 3 nc -z {server_ip} {backend_port} && echo "FAIL" || echo "PASS"
484
-
485
- # 4. 敏感文件不可下载
486
- curl -s -o /dev/null -w "%{http_code}" https://{server}/.git/config # 必须 404
487
- curl -s -o /dev/null -w "%{http_code}" https://{server}/.env # 必须 404
488
-
489
- # 5. HTTPS 工作正常
490
- curl -sI https://{server}/ | grep "strict-transport-security" # 必须有输出
491
-
492
- # 6. 安全头完整
493
- curl -sI https://{server}/ | grep -i "x-frame-options"
494
- curl -sI https://{server}/ | grep -i "x-content-type-options"
495
- curl -sI https://{server}/ | grep -i "content-security-policy"
496
-
497
- # 7. 非法方法被拒绝
498
- curl -s -o /dev/null -w "%{http_code}" -X DELETE https://{server}/api/health # 必须 403/405
499
-
500
- # 8. Volume 存在且数据完整
501
- docker volume ls | grep {volume_name} # 必须存在
502
-
503
- # 9. fail2ban 运行中
504
- fail2ban-client status sshd
505
-
506
- # 10. 正常服务可用
507
- curl -s https://{server}/api/health # 必须返回 200
508
- ```
509
-
510
- ## 十三、违规处理流程
511
-
512
- 当 AI 检测到操作违反以上任何规则时:
513
-
514
- 1. **立即停止**当前操作
515
- 2. **明确告知**用户违反了哪条规则
516
- 3. **说明风险**(可能导致的安全后果)
517
- 4. **等待用户确认**后才能继续执行
518
- 5. 如果用户坚持违规操作,在代码中添加 `# SECURITY WARNING: 用户已确认此操作` 注释
@@ -1,146 +0,0 @@
1
- ---
2
- description: Vue 前端网络层(ekit createRequest + 拦截器插件)
3
- paths:
4
- - "**/api/**/*.ts"
5
- - "**/api/**/*.vue"
6
- - "**/api/client.ts"
7
- ---
8
-
9
- # Vue 前端网络层规范
10
-
11
- ## 六、API 请求规范
12
-
13
- ### 强制规则
14
-
15
- - API 文件按**业务域拆分**(`api/user.ts`、`api/exam.ts`)
16
- - 每个 API 函数**独立导出**,不使用 default export
17
- - 请求参数和响应使用**类型标注**
18
- - **禁止**在组件中直接创建 axios 实例或调用 `fetch`
19
-
20
- ### API 文件结构
21
-
22
- ```typescript
23
- // api/user.ts
24
- import request from '@/utils/request'
25
- import type { UserInfo, UserCreate, UserUpdate } from '@/types/user'
26
-
27
- export function getUsers(params?: { page?: number; page_size?: number }) {
28
- return request.get<{ items: UserInfo[]; total: number }>('/users', { params })
29
- }
30
-
31
- export function getUser(id: number) {
32
- return request.get<UserInfo>(`/users/${id}`)
33
- }
34
-
35
- export function createUser(data: UserCreate) {
36
- return request.post<UserInfo>('/users', data)
37
- }
38
-
39
- export function updateUser(id: number, data: UserUpdate) {
40
- return request.put<UserInfo>(`/users/${id}`, data)
41
- }
42
-
43
- export function deleteUser(id: number) {
44
- return request.delete(`/users/${id}`)
45
- }
46
- ```
47
-
48
- ### 请求实例配置
49
-
50
- ```typescript
51
- // utils/request.ts
52
- import axios from 'axios'
53
-
54
- const request = axios.create({
55
- baseURL: '/api',
56
- timeout: 30000,
57
- })
58
-
59
- // Token 注入
60
- request.interceptors.request.use((config) => {
61
- const token = localStorage.getItem('token')
62
- if (token) {
63
- config.headers.Authorization = `Bearer ${token}`
64
- }
65
- return config
66
- })
67
-
68
- // 401 处理
69
- request.interceptors.response.use(
70
- (response) => response,
71
- (error) => {
72
- if (error.response?.status === 401) {
73
- localStorage.removeItem('token')
74
- window.location.href = '/login'
75
- }
76
- return Promise.reject(error)
77
- },
78
- )
79
-
80
- export default request
81
- ```
82
-
83
- ### 禁止的写法
84
-
85
- ```typescript
86
- // ❌ 在组件中直接调用
87
- const res = await axios.get('/api/users')
88
-
89
- // ✅ 通过 API 模块调用
90
- import { getUsers } from '@/api/user'
91
- const res = await getUsers()
92
-
93
- // ❌ API 函数使用 default export
94
- export default { getUsers, createUser }
95
-
96
- // ✅ 每个函数独立导出
97
- export function getUsers() { ... }
98
- export function createUser() { ... }
99
- ```
100
-
101
- ---
102
-
103
- ## 网络层规范(ekit 统一方案)
104
-
105
- ### Vue 前端
106
-
107
- **唯一方式:** ekit `createRequest()` + 插件。
108
-
109
- ```typescript
110
- // api/client.ts
111
- import { createRequest } from '@dwydev/ekit'
112
-
113
- export const request = createRequest({
114
- baseURL: import.meta.env.VITE_API_BASE_URL,
115
- plugins: [
116
- tokenPlugin(), // 注入 Authorization header
117
- refreshTokenPlugin(), // 401 自动刷新
118
- unwrapPlugin(), // 解包响应 → data
119
- ],
120
- })
121
-
122
- // api/user.ts — 按业务域拆分
123
- export function getUsers(params: { page: number; page_size: number }) {
124
- return request.get('/users', { params })
125
- }
126
-
127
- export function createUser(data: UserCreate) {
128
- return request.post('/users', data)
129
- }
130
- ```
131
-
132
- **禁止:** `axios.create()`、`fetch()`、`new XMLHttpRequest()`
133
-
134
- ### 响应解包
135
-
136
- 前端的解包逻辑必须与后端 eapi response 格式对齐:
137
-
138
- ```
139
- 后端返回: { code: "SUCCESS", message: "success", data: {...}, timestamp: ... }
140
- ↓ unwrap
141
- 前端拿到: {...} (直接是 data 的内容)
142
- ```
143
-
144
- 分页响应解包后拿到 `{ items, total, page, page_size }`(保持 snake_case 对齐后端 JSON)。
145
-
146
- 业务失败时(`code !== "SUCCESS"`),unwrapPlugin 抛出的 HttpError 携带 `businessCode` 和 `apiResponse`。业务 catch 中用 `isApiBusinessError(err)` 做类型守卫后按 `err.businessCode` 分支(如 `NOT_FOUND` / `VALIDATION_ERROR` / `PERMISSION_DENIED`);`VALIDATION_ERROR` 场景可用 `extractValidationErrors(err)` 直接给 vee-validate 的 `setErrors` 回填。