prizmkit 1.1.51 → 1.1.53

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.1.51",
3
- "bundledAt": "2026-05-23T15:07:50.298Z",
4
- "bundledFrom": "70092bb"
2
+ "frameworkVersion": "1.1.53",
3
+ "bundledAt": "2026-05-24T05:20:15.152Z",
4
+ "bundledFrom": "156de40"
5
5
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.51",
2
+ "version": "1.1.53",
3
3
  "skills": {
4
4
  "prizm-kit": {
5
5
  "description": "Full-lifecycle dev toolkit. Covers spec-driven development, Prizm context docs, code quality, debugging, deployment, and knowledge management.",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "prizmkit-deploy"
3
- description: "Universal deployment gateway for any PrizmKit project. Discovers project type and target (SSH server, Vercel, Docker, etc.), then routes: full automation for SSH Linux with PM2 + Nginx + blue/green switching, guided setup for cloud platforms, or safe documentation fallback for unsupported targets. Also operates existing deployments: status, logs, restart, rollback, health checks, history. Trigger on: 'deploy', 'deploy my app', 'help me deploy', 'ship it', 'take this live', 'deploy to Vercel', 'deploy to my server', 'how do I deploy this', any deployment or hosting question."
3
+ description: "Universal deployment gateway for any PrizmKit project. Discovers project type and target (SSH server, Vercel, Docker, etc.), then routes: full automation for SSH Linux with PM2 + Nginx + blue/green switching, guided setup for cloud platforms, or safe documentation fallback for unsupported targets. Also operates existing deployments: status, logs, restart, rollback, health checks, history, validate. Use this skill whenever the user asks about deployment, hosting, going live, or server operations. Triggers on: 'deploy', 'ship it', 'take this live', 'deploy to Vercel', 'deploy to my server', 'check deploy status', 'view logs', 'restart app', 'rollback', 'how do I deploy this', any deployment or hosting question."
4
4
  ---
5
5
 
6
6
  # PrizmKit Deploy — Universal Deployment Gateway
@@ -73,26 +73,12 @@ If headless mode and no target can be determined, exit with `NEEDS_INPUT` listin
73
73
 
74
74
  Based on detected target, route the rest of the session:
75
75
 
76
- ```
77
- SSH Linux server → §SSH Deployment Path (full automation)
78
- bootstrap, configure, deploy, operate
79
- First-version: PM2 + Nginx + blue/green
80
-
81
- Vercel / Netlify → §Cloud Platform Deployment Path (guided)
82
- detect CLI tools, walk through deploy commands,
83
- generate deploy.md with platform-specific steps
84
-
85
- Docker → §Docker Deployment Path (guided)
86
- detect Dockerfile/Compose, build image,
87
- container lifecycle (run, stop, logs, restart)
88
-
89
- Unsupported → §Unsupported Deployment Fallback
90
- generate deploy.md with detected info,
91
- record missing adapter gap,
92
- provide manual deployment checklist
93
- ```
76
+ 1. **SSH Linux server** → §SSH Deployment Path — full automation: bootstrap, configure, deploy, operate. First-version adapter: PM2 + Nginx + blue/green.
77
+ 2. **Vercel / Netlify** → §Cloud Platform Deployment Path guided: detect CLI tools, walk through deploy commands, generate deploy.md. Details in `references/cloud-platform-deploy.md`.
78
+ 3. **Docker** → §Docker Deployment Path — guided: detect Dockerfile/Compose, build image, container lifecycle. Details in `references/docker-deploy.md`.
79
+ 4. **Unsupported** §Unsupported Deployment Fallback — generate deploy.md, record adapter gap, provide manual checklist.
94
80
 
95
- The SSH path is fully documented in the sections below. Cloud and Docker paths follow the same discovery and documentation patterns but use platform CLIs instead of SSH + PM2.
81
+ Cloud and Docker paths follow the same discovery and documentation patterns but use platform CLIs instead of SSH + PM2.
96
82
 
97
83
  **Compatibility check before routing to SSH**: The SSH adapter (PM2 + Nginx + blue/green) requires a Node.js project — verify `package.json` exists. Non-Node.js projects (Go, Rust, Python) targeting a Linux server route to Unsupported Fallback with a note: "Adapter gap: PM2 adapter requires Node.js."
98
84
 
@@ -101,18 +87,11 @@ The SSH path is fully documented in the sections below. Cloud and Docker paths f
101
87
  When the deployment target or project type isn't covered by any adapter, don't fail silently. Instead:
102
88
 
103
89
  1. **Detect what you can**: project language, framework, build/start commands, env vars, port usage, database dependencies.
104
- 2. **Generate `.prizmkit/deploy/deploy.md`**: human-readable deployment guide with:
105
- - Prerequisites (tools, accounts, versions)
106
- - Environment variables table (detected from code scan)
107
- - Build and start instructions
108
- - Health check suggestions
109
- - Platform-specific tips if the target is partially recognized
110
- 3. **Record the adapter gap**: write a note in deploy.md and deploy-history identifying what's missing (e.g., "Adapter needed: Python/FastAPI on systemd", "Adapter needed: Go binary deployment").
90
+ 2. **Generate `.prizmkit/deploy/deploy.md`**: human-readable deployment guide with prerequisites, environment variables table, build/start instructions, health check suggestions.
91
+ 3. **Record the adapter gap**: write a note in deploy.md and deploy-history identifying what's missing (e.g., "Adapter needed: Python/FastAPI on systemd").
111
92
  4. **Provide a manual checklist**: concrete steps the user can follow to deploy manually.
112
93
  5. **Offer to generate CI/CD config**: if `.github/workflows/` exists or the user wants one, generate a basic deploy workflow.
113
94
 
114
- This ensures every deployment request produces useful output, even when full automation isn't available yet.
115
-
116
95
  ## Mode Detection
117
96
 
118
97
  Detect invocation mode from the user's initial message. The mode determines what you're allowed to do:
@@ -124,9 +103,9 @@ Detect invocation mode from the user's initial message. The mode determines what
124
103
  - Production requires explicit user confirmation before execution.
125
104
 
126
105
  **Headless mode** (invoked via `--headless` flag, pipeline, or script):
127
- - Must never wait for user input or prompt — unattended shells timing out on a prompt blocks pipelines silently.
106
+ - Never wait for user input — unattended shells that time out on a prompt block pipelines silently without visible errors, so exit with clear status codes instead.
128
107
  - May ONLY target `dev` or `test` environments.
129
- - If `--env production` in headless mode: exit immediately with `ENVIRONMENT_DENIED — production deployment requires interactive mode`.
108
+ - If `--env production` in headless mode: exit immediately with `ENVIRONMENT_DENIED — production deployment requires interactive mode`, because production deploys must never happen without human oversight.
130
109
  - If required info is missing, exit with `NEEDS_INPUT` and write pending questions to `.prizmkit/deploy/pending-input.json`.
131
110
  - May only perform actions already authorized by `deploy.config.json`.
132
111
 
@@ -164,16 +143,34 @@ All artifacts live under `.prizmkit/deploy/`:
164
143
  pending-input.json # pending questions for headless mode resume
165
144
  deploy-history/
166
145
  <deployment-id>.json # one per deploy/rollback/event
167
- deploy-scripts/ # future — currently unused, place for PrizmKit-managed deploy scripts and templates
146
+ deploy-scripts/ # future — PrizmKit-managed deploy scripts
168
147
  secrets.enc.json # optional, encrypted local secrets
169
148
  secrets.local.json # optional, plaintext secrets (must be gitignored)
170
149
  ```
171
150
 
172
- The full `deploy.config.json` schema is documented in `references/deploy-config-schema.md`. Read it when writing or validating config.
151
+ Read `references/deploy-config-schema.md` when writing or validating `deploy.config.json`. Read `references/deploy-history-schema.md` when writing history records.
152
+
153
+ ## SSH Deployment Path
154
+
155
+ The following sections define the SSH deployment adapter — the only fully-automated path. Route here when Discovery determines the target is a Linux server with SSH access.
156
+
157
+ ### SSH: Deployment Mode Selection
173
158
 
174
- ## SSH Deployment Path (Full Automation)
159
+ After Discovery routes to SSH, **before** entering the configuration wizard, ask the user how they want to deploy.
175
160
 
176
- The following sections — Server Model through Multi-App Coordination — define the SSH deployment adapter. This is the only fully-automated path in the first version. Route here when Discovery determines the target is a Linux server with SSH access.
161
+ **First question:**
162
+ > "你想怎么部署到服务器?"
163
+ > - **A. 直接上传(快速上手)** — 本地构建,传到服务器启动。适合第一次部署。
164
+ > - **B. CI/CD 自动部署(推荐)** — 配置 GitHub Actions,以后 `git push` 自动部署。
165
+
166
+ **If user chooses CI/CD, second question:**
167
+ > "CI/CD 有两种模式:"
168
+ > - **Push 模式** — GitHub Actions runner 编译,SCP 传到服务器。服务器压力小。
169
+ > - **Pull 模式** — 服务器自己拉代码编译。配置更简单但需 Deploy Key。
170
+
171
+ For detailed mode descriptions and the full Push/Pull comparison table, read `references/deployment-modes.md`.
172
+
173
+ **Config field:** `deployStrategy` in `deploy.config.json` — `"direct-upload"`, `"ci-cd-push"`, or `"ci-cd-pull"`. Existing configs without this field default to `"ci-cd-pull"` for backward compatibility.
177
174
 
178
175
  ### SSH: Server Model
179
176
 
@@ -181,7 +178,7 @@ Servers are generic SSH targets. A server is valid if it:
181
178
  - Can be reached over SSH.
182
179
  - Provides a Linux shell.
183
180
  - Can install or has Node.js, npm, PM2, Nginx, Git.
184
- - Can access the configured Git repository.
181
+ - Can access the configured Git repository (Pull mode only).
185
182
 
186
183
  Server-side directory layout:
187
184
  ```
@@ -199,48 +196,46 @@ SSH roles: `bootstrapUser` (usually root, for initial setup) and `runtimeUser` (
199
196
 
200
197
  ### SSH: First-Run Configuration Wizard
201
198
 
202
- When `.prizmkit/deploy/deploy.config.json` does not exist, enter configuration wizard. The flow is: **collect → validate → confirm → persist**.
199
+ When `.prizmkit/deploy/deploy.config.json` does not exist, enter configuration wizard. Flow: **deployment mode collect → validate → confirm → persist**.
200
+
201
+ **Before any questions:** ask deployment mode (see §SSH: Deployment Mode Selection). This determines required steps:
202
+
203
+ | Step | Direct Upload | CI/CD Push | CI/CD Pull |
204
+ |------|:---:|:---:|:---:|
205
+ | SSH Server Discovery | Required | Required | Required |
206
+ | Repository Access | Skipped | Skipped | Required |
207
+ | Application Configuration | Required | Required | Required |
208
+ | Environment Variables | Required | Required | Required |
209
+ | Persist Configuration | Required | Required | Required |
203
210
 
204
211
  #### Step 1: SSH Server Discovery
205
212
 
206
213
  Ask for and validate:
207
214
  - **Server host and port** (e.g., `43.161.221.171:22`)
208
- - **Bootstrap user** (usually `root`) — used for initial package install and user creation
215
+ - **Bootstrap user** (usually `root`) — for initial package install and user creation
209
216
  - **Runtime user** (recommend `deploy`) — app runs as this user, never root
210
217
  - **Auth method** — SSH key path or agent
211
218
 
212
219
  Validate immediately: `ssh <bootstrapUser>@<host> 'echo OK'`. If that fails, nothing else matters — stop and fix connectivity first.
213
220
 
214
- #### Step 2: Repository Access
221
+ #### Step 2: Repository Access (CI/CD Pull mode only)
215
222
 
216
- Ask for and validate:
217
- - **Git URL** (e.g., `git@github.com:owner/repo.git`)
218
- - **Branch** (e.g., `master`)
219
- - **Auth strategy** — prefer read-only Deploy Key
223
+ Only needed when `deployStrategy` is `"ci-cd-pull"` — the server needs to `git pull` code. Skip for `"direct-upload"` (no Git on server) and `"ci-cd-push"` (GitHub Actions handles checkout).
224
+
225
+ Ask for: Git URL, branch, auth strategy (prefer read-only Deploy Key).
220
226
 
221
227
  If using Deploy Key:
222
228
  1. Generate ed25519 key on server: `sudo -u <runtimeUser> ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""`
223
- 2. Show the public key to the user with explicit instruction: "Add this to GitHub Deploy Keys (read-only)"
224
- 3. Wait for user confirmation, then verify: attempt a git clone as runtime user
229
+ 2. Show public key to user: "Add this to GitHub Deploy Keys (read-only)"
230
+ 3. Wait for confirmation, then verify: attempt a git clone as runtime user
225
231
 
226
232
  #### Step 3: Application Configuration
227
233
 
228
- For each app, collect:
229
- - **id** — short name (e.g., `web`)
230
- - **path** — relative path within repo
231
- - **packageManager** — npm / yarn / pnpm
232
- - **installCommand** — `npm ci` / `yarn install` etc.
233
- - **buildCommand** — `npm run build` etc.
234
- - **startCommand** — `npm run start` etc.
235
- - **ports** — blue/green port pair (default 3101/3102)
236
- - **healthChecks** — list of `{ name, url, expectedStatus[] }`
234
+ For each app, collect: id, path, packageManager, installCommand, buildCommand, startCommand, blue/green port pair (default 3101/3102), healthChecks.
237
235
 
238
236
  #### Step 4: Environment Variables
239
237
 
240
- - Scan source code for `process.env.<VAR>` references.
241
- - Ask user for each required value.
242
- - Identify which are secrets (API keys, tokens) vs. non-secrets (URLs, anon keys).
243
- - Ask about secret storage strategy (see Secrets Management below).
238
+ Scan source code for `process.env.<VAR>` references. Ask user for each required value. Identify secrets vs non-secrets. Ask about secret storage strategy (see §Secrets Management).
244
239
 
245
240
  #### Step 5: Persist Configuration
246
241
 
@@ -248,7 +243,7 @@ Write `deploy.config.json` with all collected values and `validated: {}` stubs f
248
243
 
249
244
  ### SSH: Bootstrap Flow
250
245
 
251
- Before first deployment, bootstrap the server. Present a plan to the user showing every privileged action before executing anything.
246
+ Before first deployment, bootstrap the server. Present a plan showing every privileged action before executing anything.
252
247
 
253
248
  **Always-run preflight:**
254
249
  ```
@@ -256,18 +251,9 @@ locale-gen en_US.UTF-8 # fix locale warnings on bare Ubuntu
256
251
  apt-get update -qq # refresh package list
257
252
  ```
258
253
 
259
- **Check-and-install (idempotent):**
260
- - **Node.js**: check `node --version`. If missing or too old, install via NodeSource. Use v22 LTS if v25 not available — that's fine for most projects.
261
- - **npm**: verify separately from node (`which npm`). On minimal installs, npm may be a separate package.
262
- - **PM2**: `npm install -g pm2` if missing.
263
- - **Nginx**: `apt-get install -y nginx` if missing.
264
- - **Git**: `apt-get install -y git` if missing.
254
+ **Check-and-install (idempotent):** Node.js, npm, PM2, Nginx, Git. Use v22 LTS if v25 not available.
265
255
 
266
- **Detect port conflicts before starting Nginx:**
267
- ```
268
- ss -tlnp | grep :80 || true
269
- ```
270
- If port 80/443 is occupied, report what's using it and ask how to resolve.
256
+ **Detect port conflicts:** `ss -tlnp | grep :80 || true`. If port 80/443 is occupied, report and ask how to resolve.
271
257
 
272
258
  **User and directory setup:**
273
259
  ```
@@ -281,104 +267,119 @@ chown -R <runtimeUser>:<runtimeUser> /var/www/<project>
281
267
  env PATH=$PATH:/usr/bin pm2 startup systemd -u <runtimeUser> --hp /home/<runtimeUser>
282
268
  ```
283
269
 
284
- **Deploy key (if strategy is deploy-key):**
270
+ **Deploy key (Pull mode only):**
285
271
  ```
286
272
  sudo -u <runtimeUser> ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
287
273
  sudo -u <runtimeUser> ssh-keyscan -H github.com >> ~/.ssh/known_hosts
288
274
  ```
289
275
 
276
+ **Security baseline (firewall):** After core tools are installed, ask whether to configure ufw. If user agrees, read `references/firewall-setup.md` for the full interactive flow and rule templates.
277
+
278
+ **Database setup:** If Discovery detected database drivers, ask whether to install the database on the server. If user agrees, read `references/database-setup.md` for platform-specific setup commands and security notes.
279
+
290
280
  After each bootstrap step, record the result. Bootstrap operations must be idempotent. Back up any existing config files before modifying them.
291
281
 
282
+ ### SSH: Direct Upload Deployment
283
+
284
+ When `deployStrategy` is `"direct-upload"`, the AI builds locally and transfers artifacts to the server. No Git operations on the server. Full procedure in `references/direct-upload.md`.
285
+
286
+ ### SSH: CI/CD Pipeline Configuration
287
+
288
+ When `deployStrategy` is `"ci-cd-push"` or `"ci-cd-pull"`, generate `.github/workflows/deploy.yml` with the appropriate workflow template. Both modes share the same trigger and secrets. Full YAML templates in `references/ci-cd-workflows.md`.
289
+
290
+ After generating the workflow, verify: the first `git push` to the configured branch will trigger the first deployment. Monitor the GitHub Actions run and report results.
291
+
292
+ ### SSH: DNS Guidance
293
+
294
+ Before SSL, check if the user has a domain pointing to the server.
295
+
296
+ 1. Ask: "你有没有域名要绑定到这个项目?" If no domain → skip DNS + SSL, note in deploy.md.
297
+ 2. Check DNS: `dig +short <domain> A`. If resolved → proceed to SSL.
298
+ 3. If not resolved: show the user DNS setup instructions. Full procedure in `references/dns-setup.md`.
299
+
300
+ ### SSH: SSL/HTTPS Configuration
301
+
302
+ Once DNS is confirmed pointing to the server, configure HTTPS via Let's Encrypt.
303
+
304
+ 1. Detect cloud vendor via metadata endpoints.
305
+ 2. If cloud vendor detected, ask: Let's Encrypt (recommended) or cloud vendor certificate.
306
+ 3. Install certbot and request certificate.
307
+ 4. Verify auto-renewal with `certbot renew --dry-run`.
308
+
309
+ Full procedure in `references/ssl-setup.md`.
310
+
292
311
  ### SSH: Deployment Execution Flow
293
312
 
294
313
  Pipeline runs in strict order. Each group must complete before the next begins. If any step before traffic switch fails, STOP — do not touch the live version.
295
314
 
315
+ **Pre-flight — Change Summary:** Show what will be deployed using `git log --oneline <last-deployed-commit>..HEAD`. If first deployment, show last 5 commits. If no new commits, warn "没有新的代码变更。确定要重新部署吗?"
316
+
296
317
  **Group 1 — Pre-flight & Prepare:**
297
318
  - Verify SSH, runtime user, tools, deploy key, port availability.
298
319
  - Generate `releaseId`: `YYYYMMDD-<short-commit-sha>`. Create `releases/<releaseId>`.
299
320
  - Determine target color: read `activeColor` from `shared/deploy-metadata.json` and use the opposite. If first deploy (no metadata, no `current` symlink), default to blue (port 3101).
300
321
 
301
322
  **Group 2 — Fetch & Build:**
302
- - `git clone <repoUrl> --branch <branch> releases/<releaseId>` as runtime user.
303
- - `cd releases/<releaseId> && <installCommand>` as runtime user.
304
- - Copy `.env.production` from `shared/` into release dir BEFORE build `NEXT_PUBLIC_*` vars are baked at build time.
305
- - Run `<buildCommand>`. If build fails: STOP.
323
+
324
+ - **CI/CD Pull mode** (server-side build): git clone → install → copy `.env.production` before build (NEXT_PUBLIC_* vars are baked at build time) → build. If build fails: STOP.
325
+ - **CI/CD Push mode** (runner-side build): extract tarball, skip install/build.
326
+ - **Direct-upload mode**: build was already done locally and SCP'd. Skip this group.
306
327
 
307
328
  **Group 3 — Stage & Health Check:**
308
- - Start new version on the inactive port via PM2: `pm2 start npm --name <project>-<app>-<color> -- run start -- -p <inactivePort>`.
329
+ - Start new version on inactive port via PM2: `pm2 start npm --name <project>-<app>-<color> -- run start -- -p <inactivePort>`.
309
330
  - PM2 process naming: `<project>-<app>-<color>` (e.g., `prizm-ideas-web-green`).
310
- - Wait 3-5 seconds, run health checks against new port. If any fails: STOP. Do NOT switch traffic. Record failure.
331
+ - Wait 3-5 seconds, run health checks against new port. If any fails: STOP, do NOT switch traffic.
311
332
 
312
333
  **Group 4 — Switch & Verify:**
313
334
  - Update Nginx upstream to new port. Run `nginx -t` — abort on failure.
314
335
  - `systemctl reload nginx`. Update `current` symlink to new release.
315
336
  - Write `shared/deploy-metadata.json` with new `activeColor`, `activePort`, `lastReleaseId`.
316
- - Run health checks against public endpoint. If any fails: rollback immediately (switch Nginx back, restart old PM2).
337
+ - Run health checks against public endpoint. If any fails: rollback immediately.
317
338
 
318
339
  **Group 5 — Cleanup & Record:**
319
340
  - Stop old PM2 process. Remove oldest releases beyond `releaseRetention` count. `pm2 save`.
320
- - Write deploy-history JSON to `.prizmkit/deploy/deploy-history/<releaseId>.json` (schema: `references/deploy-history-schema.md`).
321
- - Update `deploy.config.json` with new validation status.
341
+ - Write deploy-history JSON. Update `deploy.config.json` validation status.
342
+
343
+ **Post-deploy — Completion Summary:** Output a summary (project, URL, version, duration, health status) and append to deploy.md. If `deployStrategy` is `"direct-upload"`, offer CI/CD upgrade (see §SSH: Post-Deploy CI/CD Upgrade).
322
344
 
323
345
  ### SSH: Blue/Green PM2 + Nginx Strategy
324
346
 
325
- The active color (blue or green) maps to a port:
326
- - Blue: port 3101 (default)
327
- - Green: port 3102 (default)
347
+ - Blue: port 3101 (default), Green: port 3102 (default).
348
+ - Active color persisted in `/var/www/<project>/shared/deploy-metadata.json`.
349
+ - PM2 process naming: `<project>-<app>-<color>` (deterministic, never reuse old release IDs).
350
+ - Nginx config must include: `# PrizmKit Managed: <project> — DO NOT EDIT MANUALLY`.
351
+ - Before modifying any Nginx config lacking this marker, ask for user confirmation.
352
+ - Always `nginx -t` before `systemctl reload nginx`.
328
353
 
329
- Active color is persisted in `/var/www/<project>/shared/deploy-metadata.json`. If metadata is missing, rediscover from Nginx `proxy_pass` directive or from running PM2 processes.
354
+ See `references/nginx-blue-green.md` for the full Nginx config template and traffic switch procedure.
330
355
 
331
- PM2 process naming: `<project>-<app>-<color>` (deterministic, never reuse old release IDs in names).
356
+ ### SSH: Rollback
332
357
 
333
- Nginx config must include the PrizmKit managed marker:
334
- ```
335
- # PrizmKit Managed: <project> — DO NOT EDIT MANUALLY
336
- ```
358
+ Two triggers: **automatic** (health check failure after traffic switch) and **manual** (`/prizmkit-deploy rollback --app <id> [--to <releaseId>]`).
337
359
 
338
- Before modifying any Nginx config that lacks this marker, ask for user confirmation.
360
+ Steps: identify target release → verify build exists → start PM2 on its port → update Nginx upstream `nginx -t` reload health checks → write rollback event. Do NOT delete the failed release or its logs — preserve for debugging.
339
361
 
340
- Always `nginx -t` before `systemctl reload nginx`. If syntax check fails, abort.
362
+ If no previous release exists, rollback is not possible state this clearly.
341
363
 
342
- ### SSH: Rollback
364
+ ### SSH: Operations Commands
343
365
 
344
- Two rollback triggers:
345
- 1. **Automatic**: health check failure after traffic switch → roll back immediately.
346
- 2. **Manual**: `/prizmkit-deploy rollback --app <id> [--to <releaseId>]`
366
+ **status:** `pm2 list` as runtime user + active release, active color/port, last deploy timestamp.
347
367
 
348
- Rollback steps:
349
- 1. Identify target release: `--to <releaseId>` or discover previous release from deploy history.
350
- 2. Verify target release directory exists and has a valid build.
351
- 3. Determine which port the target release used (from deploy history or release metadata).
352
- 4. Start the target PM2 process on its port (if not already running).
353
- 5. Update Nginx upstream to target port, run `nginx -t`, reload.
354
- 6. Run health checks against the restored version.
355
- 7. Write a rollback event to deploy history.
356
- 8. Do NOT delete the failed release or its logs — preserve for debugging.
368
+ **logs --app \<id\>:** `pm2 logs <process-name> --lines 100` as runtime user.
357
369
 
358
- If no previous release exists (first deployment), rollback is not possible state this clearly.
370
+ **restart --app \<id\>:** identify active PM2 process `pm2 restart` wait health checks.
359
371
 
360
- ### SSH: Operations Commands
372
+ **health --app \<id\>:** run all configured health checks, report pass/fail for each.
361
373
 
362
- #### status
363
- SSH to server and run `pm2 list` as runtime user. Also show:
364
- - Active release (from `current` symlink target)
365
- - Active color/port (from `deploy-metadata.json`)
366
- - Last deploy timestamp
374
+ **history:** list `.prizmkit/deploy/deploy-history/` events chronologically.
367
375
 
368
- #### logs --app <id>
369
- SSH to server and run `pm2 logs <process-name> --lines 100` as runtime user.
376
+ ### SSH: Post-Deploy CI/CD Upgrade
370
377
 
371
- #### restart --app <id>
372
- 1. Identify the active PM2 process for the app.
373
- 2. Run `pm2 restart <process-name>` as runtime user.
374
- 3. Wait for process to come online.
375
- 4. Run health checks to verify recovery.
378
+ After a successful direct-upload deployment, proactively offer CI/CD setup:
376
379
 
377
- #### health --app <id>
378
- Run all configured health checks for the app against the public endpoint. Report pass/fail for each.
380
+ > "部署成功。要不要顺手帮你配置 CI/CD 自动部署?以后 `git push` 就自动上线。"
379
381
 
380
- #### history
381
- Read `.prizmkit/deploy/deploy-history/` directory, list events chronologically. Show event type, release ID, commit SHA, timestamp, status.
382
+ If user agrees, ask push vs pull, then configure accordingly. If Pull mode: set up deploy key. If Push mode: add GitHub Actions secrets. Generate `deploy.yml` from `references/ci-cd-workflows.md`, update `deployStrategy` in config, write upgrade event to history.
382
383
 
383
384
  ## Environment Policy
384
385
 
@@ -387,7 +388,7 @@ Read `.prizmkit/deploy/deploy-history/` directory, list events chronologically.
387
388
  | Interactive | Allowed | Allowed | Allowed (requires confirmation) |
388
389
  | Headless | Allowed | Allowed | **REJECTED** — exits with ENVIRONMENT_DENIED |
389
390
 
390
- This is non-negotiable. Even if config allows it, headless must reject production.
391
+ Headless must reject production because production deploys require human oversight — an unattended pipeline timing out mid-deploy can leave the site in a broken state with no one monitoring.
391
392
 
392
393
  ## Secrets Management
393
394
 
@@ -407,7 +408,7 @@ Deploy history records secret presence metadata only (e.g., `{"SUPABASE_SERVICE_
407
408
  When deploying to a server that already has deployment assets:
408
409
 
409
410
  1. Detect: existing `/var/www/<project>` directory, existing PM2 processes with similar names, Nginx config referencing the same domain/IP, port conflicts.
410
- 2. Report findings to the user and ask for takeover decision:
411
+ 2. Report findings and ask for takeover decision:
411
412
  - **Take over and backup**: Back up existing config, then proceed.
412
413
  - **Coexist**: Use different directory/ports/process names.
413
414
  - **Manual resolve**: Stop and let the user handle it.
@@ -417,23 +418,15 @@ When deploying to a server that already has deployment assets:
417
418
 
418
419
  - First Nginx config creation or update of a non-PrizmKit block requires user confirmation.
419
420
  - Subsequent updates to PrizmKit-managed blocks (`# PrizmKit Managed:` marker) may proceed automatically.
420
- - Managed marker format: `# PrizmKit Managed: <project> — DO NOT EDIT MANUALLY`
421
- - Always run `nginx -t` before reload.
422
- - If a server block exists without the managed marker, ask before modifying.
421
+ - Always `nginx -t` before reload.
423
422
 
424
- See `references/nginx-blue-green.md` for the full Nginx config template, traffic switch procedure, and active port rediscovery technique.
423
+ See `references/nginx-blue-green.md` for the full Nginx config template.
425
424
 
426
425
  ### SSH: Bootstrap Safety Rules
427
426
 
428
- Before executing privileged bootstrap work, generate an action plan listing:
429
- - Packages to install/upgrade
430
- - Users/groups to create/modify
431
- - SSH keys to create
432
- - Nginx config to create/modify
433
- - Directories and permissions to change
434
- - Services that may be restarted
427
+ Before executing privileged bootstrap work, generate an action plan listing: packages, users/groups, SSH keys, Nginx config, directories/permissions, services that may be restarted.
435
428
 
436
- Execution rules:
429
+ Rules:
437
430
  - User gives one explicit approval for the entire bootstrap plan.
438
431
  - If the plan changes during execution, pause and ask again.
439
432
  - Bootstrap operations must be idempotent.
@@ -444,53 +437,32 @@ Execution rules:
444
437
  ### SSH: Multi-App Coordination
445
438
 
446
439
  An all-app deploy creates one release group. Rules:
447
- - Pre-traffic phases (fetch, install, build, stage) must complete for ALL selected apps before ANY app switches traffic.
448
- - If any app fails before traffic switch, NO app switches traffic. Staged processes are stopped, live system unchanged.
449
- - If any app fails after traffic switch, default: group rollback (all apps in the release group roll back).
440
+ - Pre-traffic phases must complete for ALL selected apps before ANY app switches traffic.
441
+ - If any app fails before traffic switch, NO app switches traffic. Staged processes stopped, live system unchanged.
442
+ - If any app fails after traffic switch, default: group rollback.
450
443
  - Single-app deploys (`--app <id>`) do not affect unrelated apps.
451
444
 
452
445
  ## Validation
453
446
 
454
- Validation is mandatory before production deploy. Check:
455
- - SSH connectivity and user permissions
456
- - Required tools present (node, npm, git, pm2, nginx)
457
- - Repository reachability and branch existence
458
- - Ports availability
459
- - Required env vars present
460
- - Nginx config syntax
461
- - Health check routes accessible
447
+ Validation is mandatory before production deploy. Check: SSH connectivity, required tools (node, npm, git, pm2, nginx), repository reachability, port availability, required env vars, Nginx config syntax, health check routes accessible.
462
448
 
463
449
  Persist validation in `deploy.config.json` under each section's `validated` field.
464
450
 
465
451
  ## Adapter Paths
466
452
 
467
- After Discovery routes to a deployment target, read the corresponding reference file for execution details:
453
+ After Discovery routes to a deployment target, read the corresponding reference:
468
454
 
469
455
  | Target | Reference | Mode |
470
456
  |--------|-----------|------|
471
- | SSH Linux server | SSH sections below (Server Model through Multi-App) | Full automation |
457
+ | SSH Linux server | SSH sections in this file | Full automation |
472
458
  | Vercel, Netlify, Fly.io | `references/cloud-platform-deploy.md` | Guided CLI |
473
459
  | Docker / Docker Compose | `references/docker-deploy.md` | Guided build + run |
474
- | Unrecognized target | Deployment Discovery Step 4 | Documented fallback |
475
-
476
- The SSH path is documented inline below because it is the fully-automated adapter and the model needs its instructions in every SSH deployment session. Cloud and Docker paths are in references because they're loaded only when Discovery routes to them.
460
+ | Unrecognized target | §Deployment Discovery Step 4 | Documented fallback |
477
461
 
478
462
  ## Deploy History Record Schema
479
463
 
480
- Each deployment, rollback, or significant event writes a record to `.prizmkit/deploy/deploy-history/<id>.json`. The full schema is in `references/deploy-history-schema.md` read it when writing history records.
481
-
482
- Never record raw secret values in history — presence metadata only.
483
-
484
- ## Implementation Notes from Live Validation
464
+ Each deployment, rollback, or significant event writes a record to `.prizmkit/deploy/deploy-history/<id>.json`. Full schema in `references/deploy-history-schema.md`. Never record raw secret values in history — presence metadata only.
485
465
 
486
- These findings from PrizmIdeas first deployment should guide your behavior:
466
+ ## Implementation Notes
487
467
 
488
- 1. **Detect port conflicts before installing Nginx.** Check what's on port 80/443 and ask before stopping anything.
489
- 2. **Verify npm separately from node.** Minimal Node installs may not bundle npm.
490
- 3. **Fix locale on bare Ubuntu.** Run `locale-gen en_US.UTF-8` early to avoid perl warnings in apt.
491
- 4. **Deploy key workflow is inherently interactive.** Generate key → wait for user to add to GitHub → verify. Headless mode cannot complete this.
492
- 5. **`pm2 startup` needs explicit PATH.** Always use `env PATH=$PATH:/usr/bin pm2 startup ...`.
493
- 6. **Persist deploy metadata on server.** Write `activeColor`, `activePort`, `lastReleaseId`, `lastDeployTimestamp` to `shared/deploy-metadata.json`.
494
- 7. **Detect first deployment.** If no `current` symlink and no PM2 process for the app, skip rollback safety checks and use blue (3101) as initial color.
495
- 8. **Build-time env vars.** Copy `.env.production` before `npm run build`, not after. `NEXT_PUBLIC_*` vars are baked at build time.
496
- 9. **Node.js version flexibility.** Default to v22 LTS if v25 is unavailable. Most frameworks tolerate a minor version diff.
468
+ Live validation findings from the first PrizmKit deployment are in `references/live-validation-notes.md`. Read when troubleshooting bootstrap or deploy issues these cover port conflict detection, npm verification, locale fixes, deploy key interactivity, PM2 PATH handling, and build-time env var timing.
@@ -0,0 +1,115 @@
1
+ # CI/CD Workflow Templates
2
+
3
+ Read this file when `deployStrategy` is `ci-cd-push` or `ci-cd-pull`.
4
+
5
+ ## Shared Configuration
6
+
7
+ **Secrets** (add to GitHub repository Settings → Secrets and variables → Actions):
8
+ - `SSH_HOST` — server IP/hostname
9
+ - `SSH_USER` — runtime user (e.g., `deploy`)
10
+ - `SSH_KEY` — SSH private key
11
+ - `SSH_PORT` — SSH port (default 22)
12
+
13
+ **Shared trigger:**
14
+ ```yaml
15
+ on:
16
+ push:
17
+ branches: [<branch>]
18
+ paths-ignore:
19
+ - '.prizmkit/**'
20
+ - 'docs/**'
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Push Mode Workflow (`ci-cd-push`)
26
+
27
+ Build happens on GitHub Actions runner. Only built artifacts are transferred to the server.
28
+
29
+ ```yaml
30
+ name: Deploy to Production (Push)
31
+
32
+ on:
33
+ push:
34
+ branches: [<branch>]
35
+
36
+ jobs:
37
+ deploy:
38
+ runs-on: ubuntu-latest
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+
42
+ - uses: actions/setup-node@v4
43
+ with:
44
+ node-version: 20
45
+
46
+ - name: Install & Build
47
+ run: |
48
+ npm ci
49
+ npm run build
50
+
51
+ - name: Package & Transfer
52
+ run: |
53
+ RELEASE_ID=$(date +%Y%m%d)-$(git rev-parse --short HEAD)
54
+ tar czf deploy-$RELEASE_ID.tar.gz \
55
+ <build-output-dir>/ node_modules/ package.json package-lock.json
56
+ scp -P ${{ secrets.SSH_PORT }} deploy-$RELEASE_ID.tar.gz \
57
+ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/<project>/releases/
58
+
59
+ - name: Deploy on Server
60
+ uses: appleboy/ssh-action@v1
61
+ with:
62
+ host: ${{ secrets.SSH_HOST }}
63
+ username: ${{ secrets.SSH_USER }}
64
+ key: ${{ secrets.SSH_KEY }}
65
+ port: ${{ secrets.SSH_PORT }}
66
+ script: |
67
+ cd /var/www/<project>
68
+ RELEASE_ID=$(date +%Y%m%d)-$(git rev-parse --short HEAD)
69
+ mkdir -p releases/$RELEASE_ID
70
+ tar xzf releases/deploy-$RELEASE_ID.tar.gz -C releases/$RELEASE_ID
71
+ rm releases/deploy-$RELEASE_ID.tar.gz
72
+ # PM2 start, health check, Nginx switch (same as manual flow)
73
+ ```
74
+
75
+ **Key difference from Pull:** the runner checks out code, installs, builds, and only transmits the result. The server doesn't need Git or build tools — just Node.js runtime and PM2.
76
+
77
+ ---
78
+
79
+ ## Pull Mode Workflow (`ci-cd-pull`)
80
+
81
+ GitHub Actions runner only triggers the server. The server does all the work.
82
+
83
+ ```yaml
84
+ name: Deploy to Production (Pull)
85
+
86
+ on:
87
+ push:
88
+ branches: [<branch>]
89
+
90
+ jobs:
91
+ deploy:
92
+ runs-on: ubuntu-latest
93
+ steps:
94
+ - name: Trigger Server Deploy
95
+ uses: appleboy/ssh-action@v1
96
+ with:
97
+ host: ${{ secrets.SSH_HOST }}
98
+ username: ${{ secrets.SSH_USER }}
99
+ key: ${{ secrets.SSH_KEY }}
100
+ port: ${{ secrets.SSH_PORT }}
101
+ script: |
102
+ cd /var/www/<project>
103
+ RELEASE_ID=$(date +%Y%m%d)-$(git rev-parse --short HEAD)
104
+ mkdir -p releases/$RELEASE_ID
105
+ git clone <repoUrl> --branch <branch> releases/$RELEASE_ID
106
+ cd releases/$RELEASE_ID
107
+ npm ci
108
+ cp ../shared/.env.production .
109
+ npm run build
110
+ # PM2 start, health check, Nginx switch
111
+ ```
112
+
113
+ **Key difference from Push:** the workflow is simpler (one step: SSH + run script), but the server needs Git, full build toolchain, and must be able to reach the repo.
114
+
115
+ After generating the workflow, verify: the first `git push` to the configured branch will trigger the first deployment. Monitor the GitHub Actions run and report results.
@@ -0,0 +1,46 @@
1
+ # Database Setup
2
+
3
+ Read this file when Discovery detected a database driver and the user wants AI-assisted database installation on the server.
4
+
5
+ ## Entry condition
6
+
7
+ During Discovery Step 1 (Project Detection), database drivers were already scanned. If a driver was detected, ask after bootstrap tools are installed:
8
+
9
+ > "检测到项目使用了 <PostgreSQL/MySQL/Redis>,需要帮你在服务器上安装配置吗?"
10
+ > - **需要** → 继续数据库安装
11
+ > - **不需要** → 跳过,记录到 deploy.md,标注"数据库需用户自行配置"
12
+
13
+ ## PostgreSQL setup
14
+
15
+ ```
16
+ apt-get install -y postgresql postgresql-contrib
17
+ sudo -u postgres psql -c "CREATE DATABASE <project>;"
18
+ sudo -u postgres psql -c "CREATE USER <project> WITH PASSWORD '<random-password>';"
19
+ sudo -u postgres psql -c "GRANT ALL ON DATABASE <project> TO <project>;"
20
+ ```
21
+
22
+ - Generate a secure random password (32 chars, alphanumeric + symbols).
23
+ - Write the connection string to `.prizmkit/deploy/secrets.local.json`: `DATABASE_URL=postgresql://<project>:<password>@localhost:5432/<project>`.
24
+ - In deploy.md, write: "PostgreSQL 已安装,连接信息已记录到 `.prizmkit/deploy/secrets.local.json`(不提交到 git)".
25
+
26
+ ## MySQL setup (future)
27
+
28
+ Similar flow. Not implemented in first version — if project uses MySQL, direct user to documentation fallback.
29
+
30
+ ## Redis setup
31
+
32
+ ```
33
+ apt-get install -y redis-server
34
+ redis-cli CONFIG SET requirepass "<random-password>"
35
+ redis-cli CONFIG REWRITE
36
+ ```
37
+
38
+ - Bind to localhost only (modify `/etc/redis/redis.conf` if needed).
39
+ - Write `REDIS_URL=redis://:<password>@localhost:6379` to `.prizmkit/deploy/secrets.local.json`.
40
+
41
+ ## Security notes
42
+
43
+ - Never write database passwords to deploy.md, because deploy.md may be committed to git and passwords would leak.
44
+ - Passwords stored in `.prizmkit/deploy/secrets.local.json` (gitignored).
45
+ - Default: database binds to localhost, no external access, because most indie projects only need local connections.
46
+ - Record a `"database-setup"` event in deploy history (presence metadata only, no passwords).
@@ -9,6 +9,7 @@ This file is the machine-readable deployment configuration. Always read it befor
9
9
  "version": 1,
10
10
  "project": "project-name",
11
11
  "deploymentMode": "ssh",
12
+ "deployStrategy": "direct-upload|ci-cd-push|ci-cd-pull",
12
13
  "defaults": { ... },
13
14
  "environments": { ... },
14
15
  "servers": [ ... ],
@@ -0,0 +1,50 @@
1
+ # Deployment Mode Details
2
+
3
+ Read this file when the user needs a detailed comparison of deployment modes during mode selection. SKILL.md contains the routing logic; this file has the full descriptions.
4
+
5
+ ## Mode A — Direct Upload
6
+
7
+ 1. Local build on the user's machine.
8
+ 2. SCP built output + `node_modules` + `.env.production` to server.
9
+ 3. PM2 start → health check → Nginx switch.
10
+ 4. After success: offer to upgrade to CI/CD.
11
+ 5. Bypasses: deploy key, git clone on server, server-side build.
12
+
13
+ Best for: first-time deployment, getting something live fast, low-spec servers.
14
+
15
+ ## Mode B1 — CI/CD Push
16
+
17
+ 1. Generate `.github/workflows/deploy.yml`: checkout → install → build → SCP tarball → SSH restart.
18
+ 2. Add GitHub Secrets: `SSH_HOST`, `SSH_USER`, `SSH_KEY`, `SSH_PORT`.
19
+ 3. First deploy triggered by push to configured branch.
20
+ 4. Server only needs Node.js runtime + PM2 — no git, no build tools needed.
21
+ 5. GitHub Actions runner handles the heavy lifting.
22
+
23
+ Best for: low-spec servers, heavy build processes, projects with large dependencies.
24
+
25
+ ## Mode B2 — CI/CD Pull
26
+
27
+ 1. Configure deploy key on server → add to GitHub.
28
+ 2. Generate `.github/workflows/deploy.yml`: triggers SSH command on server.
29
+ 3. Server-side deploy script: `git pull` → install → build → PM2 restart → health check.
30
+ 4. Server needs full build toolchain (Node.js, npm, git).
31
+ 5. Simpler workflow file, heavier server load.
32
+
33
+ Best for: simple setup, servers with sufficient CPU/RAM, projects where build is fast.
34
+
35
+ ## Comparison
36
+
37
+ | 对比 | Push 模式 | Pull 模式 |
38
+ |------|----------|----------|
39
+ | 构建位置 | GitHub Actions runner | 服务器本地 |
40
+ | 服务器压力 | 低(只运行应用) | 高(编译+运行) |
41
+ | 配置复杂度 | 中(需 SCP 传产物) | 低(只需 SSH 触发脚本) |
42
+ | 适合场景 | 服务器配置低、编译重 | 部署简单优先、服务器性能充裕 |
43
+ | Deploy Key 需要 | 不需要 | 需要 |
44
+ | 产物传输 | SCP tarball | git pull(仅增量) |
45
+
46
+ ## Common ground between all modes
47
+
48
+ - Same PM2 + Nginx blue/green strategy.
49
+ - Same health check and traffic switch procedure.
50
+ - Same ops commands (status/logs/restart/rollback).
@@ -0,0 +1,26 @@
1
+ # Direct Upload Deployment
2
+
3
+ Read this file when `deployStrategy` is `"direct-upload"`. The AI handles the build locally and transfers built artifacts to the server. No Git operations on the server.
4
+
5
+ ## Build phase (local)
6
+
7
+ 1. Run `<buildCommand>` locally (e.g., `npm run build`) in the project root.
8
+ 2. Identify the build output directory: `.next/` for Next.js, `dist/` for Vite, `build/` for CRA.
9
+ 3. Prepare a deployment tarball containing: build output + `node_modules/` + `package.json` + `package-lock.json` + any runtime config files.
10
+
11
+ ## Transfer phase (SCP)
12
+
13
+ ```
14
+ scp -P <port> deploy-<releaseId>.tar.gz <runtimeUser>@<host>:/var/www/<project>/releases/
15
+ ssh <runtimeUser>@<host> "cd /var/www/<project>/releases && mkdir <releaseId> && tar xzf deploy-<releaseId>.tar.gz -C <releaseId>"
16
+ ```
17
+
18
+ ## Server-side setup
19
+
20
+ 1. Copy `.env.production` from `shared/` into the release directory (or SCP it alongside the tarball if first deploy).
21
+ 2. No `npm install` needed — `node_modules` was transferred directly.
22
+ 3. Start PM2 on the inactive port. Health checks and traffic switch follow the standard flow (Groups 3-5 in SKILL.md).
23
+
24
+ ## Why transfer node_modules
25
+
26
+ Direct upload is optimized for "fast first deploy." Re-running `npm ci` on a low-spec server can be slow. Transferring pre-built artifacts means the server only needs to run the app.
@@ -0,0 +1,42 @@
1
+ # DNS Setup Guidance
2
+
3
+ Read this file when the user has a domain for their project but DNS is not yet pointing to the server.
4
+
5
+ ## Step 1 — Check DNS resolution
6
+
7
+ ```
8
+ dig +short <domain> A
9
+ ```
10
+
11
+ If it resolves to the server IP: DNS is already configured, proceed to SSL (`references/ssl-setup.md`).
12
+ If not: continue below.
13
+
14
+ ## Step 2 — DNS setup guidance
15
+
16
+ ```
17
+ 域名 <example.com> 还未指向服务器 <服务器IP>。
18
+
19
+ 请在 DNS 服务商(如阿里云、Cloudflare、Namecheap)添加以下记录:
20
+
21
+ Type: A
22
+ Name: @
23
+ Value: <服务器IP>
24
+ TTL: 600
25
+
26
+ 如果要同时支持 www 子域名:
27
+ Type: A
28
+ Name: www
29
+ Value: <服务器IP>
30
+
31
+ 配置完成后回复"好了",我继续检查并配 SSL 证书。
32
+ ```
33
+
34
+ ## Step 3 — Verify after user confirmation
35
+
36
+ - Re-run `dig +short <domain> A` to confirm resolution.
37
+ - If still not resolved: warn about DNS propagation delay (can take up to 48 hours, usually 5-30 minutes). Offer to wait or continue without SSL for now.
38
+ - Once confirmed: proceed to SSL (`references/ssl-setup.md`).
39
+
40
+ ## Edge case — IP-only deployment
41
+
42
+ If user has no domain: skip DNS + SSL sections. Generate a note in deploy.md: "项目通过 IP 访问,未配置域名和 HTTPS。建议购买域名后运行 `/prizmkit-deploy setup-ssl`。"
@@ -0,0 +1,37 @@
1
+ # Firewall Setup (UFW)
2
+
3
+ Read this file when the user wants AI-assisted firewall configuration during bootstrap.
4
+
5
+ ## Flow
6
+
7
+ 1. After core tools are installed, ask the user:
8
+ > "是否需要帮你配置防火墙(ufw)?只开放必要的端口,提高服务器安全性。"
9
+
10
+ 2. If user declines: skip, record to deploy config.
11
+
12
+ 3. If user agrees, ask which additional ports to open (beyond SSH/HTTP/HTTPS):
13
+ > "默认只开放 SSH(22)、HTTP(80)、HTTPS(443)。蓝绿部署预览端口(3101/3102)要不要也开放?如果需要其他端口(如数据库远程管理),可以一起列出来。"
14
+
15
+ 4. Collect ports, then ask:
16
+ > "防火墙规则已整理好。是我直接上去改,还是你自己来?"
17
+ > - **A. 你帮我改** — AI 执行 ufw 命令
18
+ > - **B. 我自己改** — 输出规则清单,用户手工执行
19
+
20
+ ## Planned rules (output before executing)
21
+
22
+ ```
23
+ ufw default deny incoming
24
+ ufw default allow outgoing
25
+ ufw allow 22/tcp # SSH
26
+ ufw allow 80/tcp # HTTP
27
+ ufw allow 443/tcp # HTTPS
28
+ ufw allow 3101/tcp # blue preview (user-approved)
29
+ ufw allow 3102/tcp # green preview (user-approved)
30
+ ufw --force enable
31
+ ```
32
+
33
+ ## Rules for automatic execution
34
+
35
+ - Check `ufw status` first — if rules already exist, append only missing rules, don't overwrite.
36
+ - Never `ufw reset` unless explicitly asked, because it wipes custom rules the user may have configured manually.
37
+ - Record a `"security-baseline"` event in deploy history with the rule list, so future sessions can detect existing configuration.
@@ -0,0 +1,21 @@
1
+ # Implementation Notes from Live Validation
2
+
3
+ These findings from the first PrizmKit deployment (PrizmIdeas) guide edge-case handling. Read when troubleshooting bootstrap or deploy issues.
4
+
5
+ 1. **Detect port conflicts before installing Nginx.** Check what's on port 80/443 and ask before stopping anything, because overwriting an existing web server without confirmation can break unrelated services.
6
+
7
+ 2. **Verify npm separately from node.** Minimal Node installs may not bundle npm. Run `which npm` after installing Node, because `node --version` succeeding doesn't guarantee npm is available.
8
+
9
+ 3. **Fix locale on bare Ubuntu.** Run `locale-gen en_US.UTF-8` early to avoid perl warnings in apt. This is safe to run unconditionally even if locale is already configured.
10
+
11
+ 4. **Deploy key workflow is inherently interactive.** Generate key → wait for user to add to GitHub → verify. Headless mode cannot complete this because it requires the user to paste the key into GitHub's UI.
12
+
13
+ 5. **`pm2 startup` needs explicit PATH.** Always use `env PATH=$PATH:/usr/bin pm2 startup ...`, because the pm2 binary may not be on root's default PATH.
14
+
15
+ 6. **Persist deploy metadata on server.** Write `activeColor`, `activePort`, `lastReleaseId`, `lastDeployTimestamp` to `shared/deploy-metadata.json`, because subsequent deploys and rollbacks depend on knowing the current active slot.
16
+
17
+ 7. **Detect first deployment.** If no `current` symlink and no PM2 process for the app, skip rollback safety checks and use blue (3101) as initial color.
18
+
19
+ 8. **Build-time env vars.** Copy `.env.production` before `npm run build`, not after. `NEXT_PUBLIC_*` vars are baked at build time and won't be picked up if the .env is added later.
20
+
21
+ 9. **Node.js version flexibility.** Default to v22 LTS if v25 is unavailable. Most frameworks tolerate a minor version diff, and v22 has broader package compatibility.
@@ -0,0 +1,56 @@
1
+ # SSL/HTTPS Configuration (Let's Encrypt + Certbot)
2
+
3
+ Read this file when DNS is confirmed pointing to the server and SSL needs to be configured.
4
+
5
+ ## Step 1 — Detect cloud vendor
6
+
7
+ ```
8
+ # Try metadata endpoints to detect cloud vendor
9
+ curl -s --connect-timeout 2 http://100.100.100.200/latest/meta-data/ && echo "ALIBABA"
10
+ curl -s --connect-timeout 2 http://metadata.tencentyun.com/latest/meta-data/ && echo "TENCENT"
11
+ curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ && echo "AWS/GCP/AZURE"
12
+ ```
13
+ Also check `/etc/hostname` for vendor patterns.
14
+
15
+ ## Step 2 — Choose SSL strategy
16
+
17
+ - **Cloud vendor detected** → ask user:
18
+ > "检测到服务器运行在 <云厂商>。用哪种 SSL 方案?"
19
+ > - **A. Let's Encrypt 免费证书(推荐)** — 一行命令永久自动续期,最省心
20
+ > - **B. <云厂商> 自有证书** — 需手动下载配置,1年有效期需手动续期
21
+ >
22
+ > 选 A 我直接帮你搞定;选 B 你需要在云控制台下载证书后告诉我路径。
23
+ - **No cloud vendor / unknown** → use certbot directly, no choice needed.
24
+
25
+ ## Step 3 — Certbot install & certificate request
26
+
27
+ ```
28
+ # Install certbot (idempotent)
29
+ which certbot || apt-get install -y certbot python3-certbot-nginx
30
+
31
+ # Request certificate
32
+ certbot --nginx -d <domain> -d www.<domain> --non-interactive --agree-tos --email <user-email>
33
+ ```
34
+
35
+ **Collect from user before running:**
36
+ - Email address (Let's Encrypt expiry notifications)
37
+ - Confirm domain list (e.g., `example.com, www.example.com`)
38
+
39
+ ## Step 4 — Verify auto-renewal
40
+
41
+ ```
42
+ systemctl status certbot.timer
43
+ certbot renew --dry-run
44
+ ```
45
+ If timer is inactive, enable it: `systemctl enable --now certbot.timer`.
46
+
47
+ ## Step 5 — Record
48
+
49
+ - Write SSL configuration summary to deploy.md: certificate paths, auto-renewal status, expiry date.
50
+ - Record a `"ssl-setup"` event in deploy history.
51
+
52
+ ## Edge cases
53
+
54
+ - **DNS not yet propagated** → certbot challenge fails. Tell user to wait and retry: `/prizmkit-deploy setup-ssl`.
55
+ - **Existing certificate found** → check expiry date (`certbot certificates`). If expiring within 30 days, warn. Otherwise skip.
56
+ - **Port 80/443 occupied by non-Nginx process** → report and ask how to resolve before proceeding.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.1.51",
3
+ "version": "1.1.53",
4
4
  "description": "Create a new PrizmKit-powered project with clean initialization — no framework dev files, just what you need.",
5
5
  "type": "module",
6
6
  "bin": {