@optima-chat/dev-skills 0.3.0 → 0.4.0

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.
@@ -114,47 +114,186 @@ sshpass -p "$CI_PASSWORD" ssh -o StrictHostKeyChecking=no ${CI_USER}@${CI_HOST}
114
114
 
115
115
  ### 1. Stage 环境(environment = "stage")
116
116
 
117
- **访问方式**: AWS RDS 直连(需要配置)
117
+ **访问方式**: 通过 EC2 SSH 隧道访问 RDS(通过 Infisical 获取密钥)
118
+
119
+ **前置条件**:
120
+ 1. 获取 `optima-ec2-key` SSH 密钥文件(联系 xbfool)
121
+ 2. 保存到 `~/.ssh/optima-ec2-key` 并设置权限: `chmod 600 ~/.ssh/optima-ec2-key`
118
122
 
119
123
  **步骤**:
120
124
  ```bash
121
125
  # IMPORTANT: 使用单行命令
122
126
 
123
- # GitHub Variables 获取 RDS 配置
124
- STAGE_DB_HOST=$(gh variable get STAGE_DB_HOST -R Optima-Chat/optima-dev-skills)
125
- STAGE_DB_PASSWORD=$(gh variable get STAGE_DB_PASSWORD -R Optima-Chat/optima-dev-skills)
127
+ # 1. 获取 Infisical 配置
128
+ INFISICAL_URL=$(gh variable get INFISICAL_URL -R Optima-Chat/optima-dev-skills)
129
+ INFISICAL_CLIENT_ID=$(gh variable get INFISICAL_CLIENT_ID -R Optima-Chat/optima-dev-skills)
130
+ INFISICAL_CLIENT_SECRET=$(gh variable get INFISICAL_CLIENT_SECRET -R Optima-Chat/optima-dev-skills)
131
+ INFISICAL_PROJECT_ID=$(gh variable get INFISICAL_PROJECT_ID -R Optima-Chat/optima-dev-skills)
132
+
133
+ # 2. 获取 Infisical Access Token
134
+ INFISICAL_TOKEN=$(curl -s -X POST "${INFISICAL_URL}/api/v1/auth/universal-auth/login" \
135
+ -H "Content-Type: application/json" \
136
+ -d "{\"clientId\": \"${INFISICAL_CLIENT_ID}\", \"clientSecret\": \"${INFISICAL_CLIENT_SECRET}\"}" \
137
+ | python3 -c "import sys, json; print(json.load(sys.stdin)['accessToken'])")
138
+
139
+ # 3. 从 Infisical 获取数据库配置(以 commerce-backend 为例)
140
+ curl -s "${INFISICAL_URL}/api/v3/secrets/raw?workspaceId=${INFISICAL_PROJECT_ID}&environment=staging&secretPath=/infrastructure" \
141
+ -H "Authorization: Bearer ${INFISICAL_TOKEN}" | python3 -c "
142
+ import sys, json
143
+ secrets = {s['secretKey']: s['secretValue'] for s in json.load(sys.stdin)['secrets']}
144
+ print(f\"DATABASE_HOST={secrets['DATABASE_HOST']}\")
145
+ print(f\"COMMERCE_DB_USER={secrets['COMMERCE_DB_USER']}\")
146
+ print(f\"COMMERCE_DB_PASSWORD={secrets['COMMERCE_DB_PASSWORD']}\")
147
+ " > /tmp/stage_db_config.sh && source /tmp/stage_db_config.sh
148
+
149
+ # 4. 建立 SSH 隧道到 Stage EC2,通过隧道访问 RDS
150
+ ssh -i ~/.ssh/optima-ec2-key -f -N -L 15432:${DATABASE_HOST}:5432 ec2-user@54.179.132.102
151
+
152
+ # 5. 通过本地端口 15432 连接到 RDS
153
+ PGPASSWORD="${COMMERCE_DB_PASSWORD}" psql -h localhost -p 15432 -U "${COMMERCE_DB_USER}" -d optima_stage_commerce -c "SELECT COUNT(*) FROM products"
154
+
155
+ # 6. 关闭 SSH 隧道(可选)
156
+ pkill -f "ssh.*15432:${DATABASE_HOST}:5432"
157
+ ```
158
+
159
+ **完整示例(四个服务)**:
160
+ ```bash
161
+ # commerce-backend
162
+ # 使用 COMMERCE_DB_USER, COMMERCE_DB_PASSWORD, 数据库: optima_stage_commerce
163
+
164
+ # user-auth
165
+ # 使用 AUTH_DB_USER, AUTH_DB_PASSWORD, 数据库: optima_stage_auth
126
166
 
127
- # 执行查询
128
- PGPASSWORD="$STAGE_DB_PASSWORD" psql -h "$STAGE_DB_HOST" -U commerce -d commerce -c "SELECT COUNT(*) FROM products"
167
+ # mcp-host
168
+ # 使用 MCP_DB_USER, MCP_DB_PASSWORD, 数据库: optima_stage_mcp
169
+
170
+ # agentic-chat
171
+ # 使用 CHAT_DB_USER, CHAT_DB_PASSWORD, 数据库: optima_stage_chat
129
172
  ```
130
173
 
131
- **数据库配置**(需要设置 GitHub Variables):
132
- - `STAGE_DB_HOST` - RDS 端点
133
- - `STAGE_DB_PASSWORD` - 数据库密码
134
- - 每个服务可能有独立的数据库
174
+ **数据库配置映射**:
175
+ - `commerce-backend`:
176
+ - 数据库: `optima_stage_commerce`
177
+ - 用户: Infisical `COMMERCE_DB_USER`
178
+ - 密码: Infisical `COMMERCE_DB_PASSWORD`
179
+
180
+ - `user-auth`:
181
+ - 数据库: `optima_stage_auth`
182
+ - 用户: Infisical `AUTH_DB_USER`
183
+ - 密码: Infisical `AUTH_DB_PASSWORD`
184
+
185
+ - `mcp-host`:
186
+ - 数据库: `optima_stage_mcp`
187
+ - 用户: Infisical `MCP_DB_USER`
188
+ - 密码: Infisical `MCP_DB_PASSWORD`
189
+
190
+ - `agentic-chat`:
191
+ - 数据库: `optima_stage_chat`
192
+ - 用户: Infisical `CHAT_DB_USER`
193
+ - 密码: Infisical `CHAT_DB_PASSWORD`
194
+
195
+ **说明**:
196
+ - Infisical 配置从 GitHub Variables 获取
197
+ - 数据库密钥从 Infisical 动态获取(项目: optima-secrets, 环境: staging, 路径: /infrastructure)
198
+ - DATABASE_HOST: `optima-prod-postgres.ctg866o0ehac.ap-southeast-1.rds.amazonaws.com`
199
+ - Stage EC2 IP: `54.179.132.102`
200
+ - SSH 隧道: 本地端口 `15432` → EC2 → RDS `5432`
201
+ - Stage 和 Prod 共享同一个 RDS 实例,通过不同的数据库名隔离
135
202
 
136
203
  ### 2. Prod 环境(environment = "prod")
137
204
 
138
- **访问方式**: AWS RDS 直连(⚠️ 只读用户)
205
+ **访问方式**: 通过 EC2 SSH 隧道访问 RDS(通过 Infisical 获取密钥)
206
+
207
+ **前置条件**:
208
+ 1. 获取 `optima-ec2-key` SSH 密钥文件(联系 xbfool)
209
+ 2. 保存到 `~/.ssh/optima-ec2-key` 并设置权限: `chmod 600 ~/.ssh/optima-ec2-key`
139
210
 
140
211
  **步骤**:
141
212
  ```bash
142
213
  # IMPORTANT: 使用单行命令
143
- # ⚠️ 生产环境只允许只读查询
214
+ # ⚠️ 生产环境谨慎操作
215
+
216
+ # 1. 获取 Infisical 配置
217
+ INFISICAL_URL=$(gh variable get INFISICAL_URL -R Optima-Chat/optima-dev-skills)
218
+ INFISICAL_CLIENT_ID=$(gh variable get INFISICAL_CLIENT_ID -R Optima-Chat/optima-dev-skills)
219
+ INFISICAL_CLIENT_SECRET=$(gh variable get INFISICAL_CLIENT_SECRET -R Optima-Chat/optima-dev-skills)
220
+ INFISICAL_PROJECT_ID=$(gh variable get INFISICAL_PROJECT_ID -R Optima-Chat/optima-dev-skills)
221
+
222
+ # 2. 获取 Infisical Access Token
223
+ INFISICAL_TOKEN=$(curl -s -X POST "${INFISICAL_URL}/api/v1/auth/universal-auth/login" \
224
+ -H "Content-Type: application/json" \
225
+ -d "{\"clientId\": \"${INFISICAL_CLIENT_ID}\", \"clientSecret\": \"${INFISICAL_CLIENT_SECRET}\"}" \
226
+ | python3 -c "import sys, json; print(json.load(sys.stdin)['accessToken'])")
227
+
228
+ # 3. 从 Infisical 获取数据库配置(以 commerce-backend 为例)
229
+ curl -s "${INFISICAL_URL}/api/v3/secrets/raw?workspaceId=${INFISICAL_PROJECT_ID}&environment=prod&secretPath=/infrastructure" \
230
+ -H "Authorization: Bearer ${INFISICAL_TOKEN}" | python3 -c "
231
+ import sys, json
232
+ secrets = {s['secretKey']: s['secretValue'] for s in json.load(sys.stdin)['secrets']}
233
+ print(f\"DATABASE_HOST={secrets['DATABASE_HOST']}\")
234
+ print(f\"COMMERCE_DB_USER={secrets['COMMERCE_DB_USER']}\")
235
+ print(f\"COMMERCE_DB_PASSWORD={secrets['COMMERCE_DB_PASSWORD']}\")
236
+ " > /tmp/prod_db_config.sh && source /tmp/prod_db_config.sh
237
+
238
+ # 4. 建立 SSH 隧道到 Prod EC2,通过隧道访问 RDS
239
+ ssh -i ~/.ssh/optima-ec2-key -f -N -L 15433:${DATABASE_HOST}:5432 ec2-user@18.136.25.239
240
+
241
+ # 5. 通过本地端口 15433 连接到 RDS
242
+ PGPASSWORD="${COMMERCE_DB_PASSWORD}" psql -h localhost -p 15433 -U "${COMMERCE_DB_USER}" -d optima_commerce -c "SELECT COUNT(*) FROM products"
243
+
244
+ # 6. 关闭 SSH 隧道(可选)
245
+ pkill -f "ssh.*15433:${DATABASE_HOST}:5432"
246
+ ```
247
+
248
+ **完整示例(四个服务)**:
249
+ ```bash
250
+ # commerce-backend
251
+ # 使用 COMMERCE_DB_USER, COMMERCE_DB_PASSWORD, 数据库: optima_commerce
252
+
253
+ # user-auth
254
+ # 使用 AUTH_DB_USER, AUTH_DB_PASSWORD, 数据库: optima_auth
144
255
 
145
- # 从 GitHub Variables 获取 RDS 配置
146
- PROD_DB_HOST=$(gh variable get PROD_DB_HOST -R Optima-Chat/optima-dev-skills)
147
- PROD_DB_PASSWORD=$(gh variable get PROD_DB_PASSWORD -R Optima-Chat/optima-dev-skills)
256
+ # mcp-host
257
+ # 使用 MCP_DB_USER, MCP_DB_PASSWORD, 数据库: optima_mcp
148
258
 
149
- # 执行查询(只读)
150
- PGPASSWORD="$PROD_DB_PASSWORD" psql -h "$PROD_DB_HOST" -U commerce_readonly -d commerce -c "SELECT COUNT(*) FROM products"
259
+ # agentic-chat
260
+ # 使用 CHAT_DB_USER, CHAT_DB_PASSWORD, 数据库: optima_chat
151
261
  ```
152
262
 
263
+ **数据库配置映射**:
264
+ - `commerce-backend`:
265
+ - 数据库: `optima_commerce`
266
+ - 用户: Infisical `COMMERCE_DB_USER`
267
+ - 密码: Infisical `COMMERCE_DB_PASSWORD`
268
+
269
+ - `user-auth`:
270
+ - 数据库: `optima_auth`
271
+ - 用户: Infisical `AUTH_DB_USER`
272
+ - 密码: Infisical `AUTH_DB_PASSWORD`
273
+
274
+ - `mcp-host`:
275
+ - 数据库: `optima_mcp`
276
+ - 用户: Infisical `MCP_DB_USER`
277
+ - 密码: Infisical `MCP_DB_PASSWORD`
278
+
279
+ - `agentic-chat`:
280
+ - 数据库: `optima_chat`
281
+ - 用户: Infisical `CHAT_DB_USER`
282
+ - 密码: Infisical `CHAT_DB_PASSWORD`
283
+
284
+ **说明**:
285
+ - Infisical 配置从 GitHub Variables 获取
286
+ - 数据库密钥从 Infisical 动态获取(项目: optima-secrets, 环境: prod, 路径: /infrastructure)
287
+ - DATABASE_HOST: `optima-prod-postgres.ctg866o0ehac.ap-southeast-1.rds.amazonaws.com`
288
+ - Prod EC2 IP: `18.136.25.239`
289
+ - SSH 隧道: 本地端口 `15433` → EC2 → RDS `5432` (注意 Prod 用 15433,Stage 用 15432)
290
+ - Stage 和 Prod 共享同一个 RDS 实例,通过不同的数据库名隔离
291
+
153
292
  **⚠️ 生产环境安全规则**:
154
- 1. **只使用只读用户** (`commerce_readonly`, `userauth_readonly`)
155
- 2. **禁止 INSERT/UPDATE/DELETE**
156
- 3. **谨慎使用 SELECT***,优先指定列名
157
- 4. **添加 LIMIT** 防止查询过多数据
293
+ 1. **谨慎操作** - 生产数据库,避免误操作
294
+ 2. **避免 DELETE/UPDATE** - 除非明确需要
295
+ 3. **使用 LIMIT** - 防止查询过多数据
296
+ 4. **不查敏感数据** - 避免查询密码、密钥等
158
297
 
159
298
  ## 安全注意事项
160
299
 
@@ -23,7 +23,12 @@
23
23
  "Bash(npm install:*)",
24
24
  "Bash(optima-dev-skills:*)",
25
25
  "Bash(gh variable set:*)",
26
- "Bash(npm publish:*)"
26
+ "Bash(npm publish:*)",
27
+ "Bash(curl -s \"https://secrets.optima.onl/api/v3/secrets/raw?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=staging&secretPath=/infrastructure\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
28
+ "Bash(python3:*)",
29
+ "Bash(curl -s \"https://secrets.optima.onl/api/v1/folders?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=prod\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
30
+ "Bash(curl -s \"https://secrets.optima.onl/api/v3/secrets/raw?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=prod&secretPath=/infrastructure\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
31
+ "Bash(gh api:*)"
27
32
  ],
28
33
  "deny": [],
29
34
  "ask": []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optima-chat/dev-skills",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Claude Code Skills for Optima development team - cross-environment collaboration tools",
5
5
  "main": "index.js",
6
6
  "bin": {