crewforth 0.0.1 → 3.0.0-rc.2
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/CHANGELOG.md +3805 -0
- package/LICENSE +21 -0
- package/README.md +37 -7
- package/VERSION +1 -0
- package/adopt.sh +1739 -0
- package/bin/cli.js +497 -0
- package/kit/AGENT_TEMPLATE.md +92 -0
- package/kit/CLAUDE.md +228 -0
- package/kit/README.md +107 -0
- package/kit/agents/crew-backend-expert.md +95 -0
- package/kit/agents/crew-commit-agent.md +96 -0
- package/kit/agents/crew-database-expert.md +84 -0
- package/kit/agents/crew-devops-expert.md +82 -0
- package/kit/agents/crew-frontend-expert.md +85 -0
- package/kit/agents/crew-performance-expert.md +78 -0
- package/kit/agents/crew-planner.md +60 -0
- package/kit/agents/crew-privacy-agent.md +71 -0
- package/kit/agents/crew-review-agent.md +95 -0
- package/kit/agents/crew-security-expert.md +73 -0
- package/kit/agents/crew-session-manager.md +77 -0
- package/kit/agents/crew-test-expert.md +64 -0
- package/kit/eval/doctor.sh +639 -0
- package/kit/eval/gate-report.sh +137 -0
- package/kit/eval/golden-holdout.txt +53 -0
- package/kit/eval/golden-routing.txt +199 -0
- package/kit/eval/lib/crew-env.sh +14 -0
- package/kit/eval/lib/settings-json.awk +154 -0
- package/kit/eval/lib/skill-listing.awk +43 -0
- package/kit/eval/lib/star.sh +70 -0
- package/kit/eval/parser-conformance.sh +612 -0
- package/kit/eval/preflight.sh +186 -0
- package/kit/eval/routing-eval.sh +209 -0
- package/kit/eval/scan-skill.sh +162 -0
- package/kit/eval/smoke-test.sh +6736 -0
- package/kit/eval/update-guard.sh +81 -0
- package/kit/eval/utilization.sh +130 -0
- package/kit/hooks/board-sync.sh +106 -0
- package/kit/hooks/board.sh +962 -0
- package/kit/hooks/commit-msg +49 -0
- package/kit/hooks/context-usage.sh +353 -0
- package/kit/hooks/floor-blocklist.txt +124 -0
- package/kit/hooks/guard-bash.sh +1433 -0
- package/kit/hooks/guard-commit-scan.sh +511 -0
- package/kit/hooks/guard-write.sh +513 -0
- package/kit/hooks/pre-commit +577 -0
- package/kit/hooks/route-hint.sh +185 -0
- package/kit/hooks/secret-blocklist.txt +82 -0
- package/kit/hooks/session-guard.sh +149 -0
- package/kit/hooks/session-rehydrate.sh +41 -0
- package/kit/hooks/session-stats.sh +252 -0
- package/kit/hooks/session-update-check.sh +236 -0
- package/kit/hooks/skill-trust.sh +163 -0
- package/kit/hooks/trace-blocklist.txt +53 -0
- package/kit/settings.json +132 -0
- package/kit/skills/a11y/SKILL.md +44 -0
- package/kit/skills/adr/SKILL.md +74 -0
- package/kit/skills/api-design/SKILL.md +50 -0
- package/kit/skills/automode-policy/SKILL.md +91 -0
- package/kit/skills/automode-policy/references/policy.json +13 -0
- package/kit/skills/automode-policy/scripts/apply.sh +84 -0
- package/kit/skills/automode-policy/scripts/check.sh +102 -0
- package/kit/skills/backend-architecture/SKILL.md +103 -0
- package/kit/skills/brainstorm/SKILL.md +47 -0
- package/kit/skills/ci-pipeline/SKILL.md +38 -0
- package/kit/skills/commit-message/SKILL.md +82 -0
- package/kit/skills/commit-message/references/examples.md +8 -0
- package/kit/skills/confidence-check/SKILL.md +86 -0
- package/kit/skills/crew-board/SKILL.md +55 -0
- package/kit/skills/crew-brainstorm/SKILL.md +19 -0
- package/kit/skills/crew-code-review/SKILL.md +151 -0
- package/kit/skills/crew-code-review/references/history-search.md +19 -0
- package/kit/skills/crew-code-review/references/panel-mode.md +32 -0
- package/kit/skills/crew-code-review/references/receiving.md +23 -0
- package/kit/skills/crew-doctor/SKILL.md +46 -0
- package/kit/skills/crew-gates/SKILL.md +25 -0
- package/kit/skills/crew-handoff/SKILL.md +14 -0
- package/kit/skills/crew-plan/SKILL.md +18 -0
- package/kit/skills/crew-review/SKILL.md +26 -0
- package/kit/skills/crew-ship/SKILL.md +19 -0
- package/kit/skills/crew-skill/SKILL.md +62 -0
- package/kit/skills/crew-studio/SKILL.md +129 -0
- package/kit/skills/crew-update/SKILL.md +43 -0
- package/kit/skills/db-migration/SKILL.md +120 -0
- package/kit/skills/db-migration/references/backup-restore.md +33 -0
- package/kit/skills/db-migration/references/raw-sql.md +30 -0
- package/kit/skills/db-migration/references/tool-matrix.md +35 -0
- package/kit/skills/dependency-audit/SKILL.md +61 -0
- package/kit/skills/dependency-upgrade/SKILL.md +82 -0
- package/kit/skills/deploy/SKILL.md +100 -0
- package/kit/skills/deploy/references/proxy-ssl.md +56 -0
- package/kit/skills/deploy/references/rollback.md +18 -0
- package/kit/skills/deploy/references/scripts.md +9 -0
- package/kit/skills/deploy/references/topology-a.md +128 -0
- package/kit/skills/deploy/references/topology-b.md +44 -0
- package/kit/skills/docs-writer/SKILL.md +53 -0
- package/kit/skills/docs-writer/references/coauthoring.md +34 -0
- package/kit/skills/eval-grader/SKILL.md +75 -0
- package/kit/skills/eval-grader/references/method.md +51 -0
- package/kit/skills/frontend/SKILL.md +56 -0
- package/kit/skills/frontend/references/verify-contract.md +41 -0
- package/kit/skills/frontend-design/SKILL.md +71 -0
- package/kit/skills/frontend-design/references/design-review.md +34 -0
- package/kit/skills/frontend-rn-expo/SKILL.md +25 -0
- package/kit/skills/handoff/SKILL.md +71 -0
- package/kit/skills/handoff/references/cold-reader.md +51 -0
- package/kit/skills/i18n-integrity/SKILL.md +31 -0
- package/kit/skills/incident-runbook/SKILL.md +40 -0
- package/kit/skills/incident-runbook/references/postmortem.md +16 -0
- package/kit/skills/iterate/SKILL.md +40 -0
- package/kit/skills/mcp-builder/SKILL.md +54 -0
- package/kit/skills/mcp-builder/references/building.md +71 -0
- package/kit/skills/observability/SKILL.md +50 -0
- package/kit/skills/performance/SKILL.md +38 -0
- package/kit/skills/performance/references/bottlenecks.md +10 -0
- package/kit/skills/privacy-compliance/SKILL.md +75 -0
- package/kit/skills/red-team/SKILL.md +48 -0
- package/kit/skills/reflect/SKILL.md +57 -0
- package/kit/skills/release/SKILL.md +44 -0
- package/kit/skills/security-scan/SKILL.md +99 -0
- package/kit/skills/security-scan/references/ai-agents.md +107 -0
- package/kit/skills/security-scan/references/fronts.md +99 -0
- package/kit/skills/security-scan/references/prompting.md +23 -0
- package/kit/skills/security-scan/references/reporting.md +75 -0
- package/kit/skills/security-scan/references/verify.md +131 -0
- package/kit/skills/sonarqube-check/SKILL.md +108 -0
- package/kit/skills/sonarqube-check/references/local-engines.md +32 -0
- package/kit/skills/sonarqube-check/references/stand-up-server.md +25 -0
- package/kit/skills/spec-planning/SKILL.md +92 -0
- package/kit/skills/systematic-debugging/SKILL.md +57 -0
- package/kit/skills/systematic-debugging/references/techniques.md +44 -0
- package/kit/skills/teamboard/SKILL.md +88 -0
- package/kit/skills/teamboard/references/setup.md +37 -0
- package/kit/skills/testing/SKILL.md +49 -0
- package/kit/skills/testing/references/flaky-triage.md +51 -0
- package/kit/skills/threat-model/SKILL.md +57 -0
- package/kit/skills/threat-model/references/interview.md +51 -0
- package/kit/skills/threat-model/references/schema.md +42 -0
- package/kit/skills/token-budget/SKILL.md +51 -0
- package/kit/skills/trace-scan/SKILL.md +43 -0
- package/kit/skills/worktree/SKILL.md +40 -0
- package/kit/studio/README.md +266 -0
- package/kit/studio/ensure-node.sh +471 -0
- package/kit/studio/package.json +14 -0
- package/kit/studio/server/hooks/studio-gate.sh +169 -0
- package/kit/studio/server/index.js +902 -0
- package/kit/studio/server/lib/crew-env.js +11 -0
- package/kit/studio/server/lib/fleet.js +146 -0
- package/kit/studio/server/lib/graph.js +533 -0
- package/kit/studio/server/lib/instance.js +135 -0
- package/kit/studio/server/lib/kit-telemetry.js +182 -0
- package/kit/studio/server/lib/kit.js +158 -0
- package/kit/studio/server/lib/palette.js +118 -0
- package/kit/studio/server/lib/peers.js +72 -0
- package/kit/studio/server/lib/permissions.js +150 -0
- package/kit/studio/server/lib/projects.js +294 -0
- package/kit/studio/server/lib/roster.js +191 -0
- package/kit/studio/server/lib/session.js +309 -0
- package/kit/studio/server/lib/terminal.js +91 -0
- package/kit/studio/server/lib/transcript.js +100 -0
- package/kit/studio/web/app.js +1098 -0
- package/kit/studio/web/canvas.js +1179 -0
- package/kit/studio/web/chat.js +543 -0
- package/kit/studio/web/index.html +86 -0
- package/kit/studio/web/md.js +110 -0
- package/kit/studio/web/storage-migrate.js +23 -0
- package/kit/studio/web/style.css +1453 -0
- package/package.json +46 -8
- package/start.sh +764 -0
- package/bin/crewforth.js +0 -10
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: db-migration
|
|
3
|
+
description: |
|
|
4
|
+
Apply schema migrations safely: detect the tool, classify the change by risk, gate destructive ones behind
|
|
5
|
+
approval, back up in prod, preview-apply-verify, roll back on failure.
|
|
6
|
+
Use when a schema change is about to be applied to any environment.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Database Migration
|
|
10
|
+
|
|
11
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
12
|
+
Trigger phrases: "migration", "schema change", "update database", "add column", "create table", "alter table", "add a column to", "adding a column to", "drop a column", "rename the table", "change the column type", "backfill"
|
|
13
|
+
|
|
14
|
+
A migration is very often a **one-way gate**: once applied, going back is expensive or impossible
|
|
15
|
+
unless it was planned for. That is why the heart of the flow is not running a command, but **classifying
|
|
16
|
+
the change by risk class before it passes through the gate** — let the safe one flow through, stop and
|
|
17
|
+
get approval for the destructive one, and keep a rollback path ready in every case. The skill works with
|
|
18
|
+
all common ORM/migration tools.
|
|
19
|
+
|
|
20
|
+
> **Crewforth adaptation (local, .claude/):** Engine and tool come from `CLAUDE.md ## Stack` or repo detection
|
|
21
|
+
> (`backend-architecture`). `crew-database-expert` applies it; **a destructive migration requires explicit approval (§4.5)**, commit/push with explicit approval (§4.4). Authorization/IDOR
|
|
22
|
+
> impact → **crew-security-expert**; personal-data retention → **crew-privacy-agent**. §4 Prohibitions apply.
|
|
23
|
+
|
|
24
|
+
## Checklist
|
|
25
|
+
- [ ] Tool detected, pending migrations listed
|
|
26
|
+
- [ ] Every change classified (additive / destructive / ambiguous)
|
|
27
|
+
- [ ] Destructive/ambiguous changes approved by the user
|
|
28
|
+
- [ ] Backup taken (mandatory in prod, verified)
|
|
29
|
+
- [ ] Preview (dry-run) shown and approved
|
|
30
|
+
- [ ] Applied, schema verified post-apply
|
|
31
|
+
- [ ] Rollback path (tool or backup) ready
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 1. Detect the tool
|
|
36
|
+
|
|
37
|
+
Determine the tool from the file trace; if none is found, fall back to **raw SQL mode** (below); if several are found, ask the user.
|
|
38
|
+
|
|
39
|
+
| Trace | Tool |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `prisma/schema.prisma` | Prisma |
|
|
42
|
+
| `knexfile.{js,ts}` | Knex |
|
|
43
|
+
| `.sequelizerc` / `config/config.json` + `models/` | Sequelize |
|
|
44
|
+
| `data-source.ts` (typeorm) / `ormconfig.ts` | TypeORM |
|
|
45
|
+
| `drizzle.config.ts` | Drizzle |
|
|
46
|
+
| `alembic.ini` / `alembic/` | Alembic |
|
|
47
|
+
| `manage.py` + `django` dependency | Django |
|
|
48
|
+
| `db/migrate/` + `rails` in Gemfile | Rails |
|
|
49
|
+
| `Microsoft.EntityFrameworkCore` in `*.csproj` + `Migrations/` | EF Core |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2. Classify the change — the heart of the flow
|
|
54
|
+
|
|
55
|
+
Extract the SQL to be applied (the "Preview" column in the matrix below) and place it into one of three classes:
|
|
56
|
+
|
|
57
|
+
| Class | Example operations | How it is handled |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| **Additive** (safe) | `CREATE TABLE`, nullable/defaulted `ADD COLUMN`, `CREATE INDEX`, non-destructive `ADD CONSTRAINT`, seed `INSERT` | Proceed in the normal flow |
|
|
60
|
+
| **Destructive** (dangerous) | `DROP TABLE/COLUMN/INDEX/CONSTRAINT`, `ALTER COLUMN … TYPE`, `TRUNCATE`, `DELETE` without WHERE, `RENAME` (breaks references) | **Always the approval gate** (below) |
|
|
61
|
+
| **Ambiguous** (human judgment) | `ALTER COLUMN`, `ADD COLUMN NOT NULL` without a default (blows up on a populated table), `UPDATE`, mixed migration | **Treat as destructive**, warn and ask |
|
|
62
|
+
|
|
63
|
+
**Approval gate (destructive/ambiguous):** list the operations one by one, show the environment and the target, wait for explicit approval. Even if "run" was said in the general flow, this gate requires separate approval.
|
|
64
|
+
```
|
|
65
|
+
WARNING — this migration contains a destructive operation:
|
|
66
|
+
· DROP COLUMN "legacy_email" (table: users)
|
|
67
|
+
· ALTER COLUMN "status" TYPE integer (table: orders)
|
|
68
|
+
CANNOT BE UNDONE without a backup. Target: production (myapp_db @ db.example.com)
|
|
69
|
+
Continue? (yes / no)
|
|
70
|
+
```
|
|
71
|
+
If rejected, stop immediately and propose a safer path (e.g. a new column + background copy instead of changing the type).
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 3. Backup (mandatory in prod)
|
|
76
|
+
|
|
77
|
+
Back up before any migration; it cannot be skipped in prod, and can be skipped in dev with approval. Then verify
|
|
78
|
+
**the backup was created and is not empty** — otherwise abort:
|
|
79
|
+
```bash
|
|
80
|
+
[ -s "$BACKUP_FILE" ] || { echo "ERROR: Backup empty/not created — migration aborted."; exit 1; }
|
|
81
|
+
```
|
|
82
|
+
Backup + restore + post-apply verify commands **per engine** (PostgreSQL · MySQL · SQLite):
|
|
83
|
+
**`references/backup-restore.md`** — read the one for your database, not all three.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 4. Tool × life-cycle matrix
|
|
88
|
+
|
|
89
|
+
Once classification and backup are complete: **Preview → (approval) → Apply → Verify**.
|
|
90
|
+
|
|
91
|
+
Per-tool commands for those four steps and for rollback — Prisma, Knex, Sequelize, TypeORM, Drizzle, Alembic, Django, Rails, EF Core: **`references/tool-matrix.md`**. Look up the one the project uses.
|
|
92
|
+
|
|
93
|
+
**Rules:** **Always** show the preview before applying and get it approved (if the tool does not support a dry-run, treat the migration file itself as the preview). A destructive migration is not applied without passing the approval gate (§2). Show the full apply output; if there is an error, roll back.
|
|
94
|
+
|
|
95
|
+
**Additional post-apply verification** — compare against the expected schema using your engine's inspect command (`references/backup-restore.md`).
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 5. Rollback
|
|
100
|
+
|
|
101
|
+
First the tool-specific rollback (last column of the matrix); if that fails, restore from the backup (per-engine
|
|
102
|
+
restore command in **`references/backup-restore.md`**); then re-verify. If neither works, warn the user with the full error detail.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## No tool — raw SQL mode
|
|
107
|
+
|
|
108
|
+
If no tool is detected, manage numbered up/down files (every `up` has a `down`, each SQL inside `BEGIN`/`COMMIT`)
|
|
109
|
+
with a `_migrations` tracking table. Full pattern + example + the apply loop: **`references/raw-sql.md`**.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Invariant rules
|
|
114
|
+
1. **Classify first** — additive/destructive/ambiguous; treat the ambiguous as destructive.
|
|
115
|
+
2. **Destructive = human approval** — a separate gate even in an automated flow.
|
|
116
|
+
3. **Prod backup mandatory** — no apply without a verified backup.
|
|
117
|
+
4. **Preview on by default** — opting out requires an explicit request.
|
|
118
|
+
5. **Always verify after applying.**
|
|
119
|
+
6. **Rollback path always ready** — tool or backup.
|
|
120
|
+
7. **Show the target** — DB name/host/environment, before applying.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Backup & restore — per engine
|
|
2
|
+
|
|
3
|
+
Take the backup **before** any migration (mandatory in prod; dev may skip with approval), then verify it is
|
|
4
|
+
non-empty or abort. Rollback order: the tool-specific rollback first (matrix, last column) → if it fails, restore
|
|
5
|
+
from this backup → re-verify. Read **only the section for your database**.
|
|
6
|
+
|
|
7
|
+
## PostgreSQL
|
|
8
|
+
```bash
|
|
9
|
+
# backup — compressed full dump
|
|
10
|
+
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME -F c -f backup_$(date +%Y%m%d_%H%M%S).dump
|
|
11
|
+
# restore (rollback)
|
|
12
|
+
pg_restore -h $DB_HOST -U $DB_USER -d $DB_NAME --clean --if-exists $BACKUP_FILE
|
|
13
|
+
# post-apply verify
|
|
14
|
+
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "\d $TABLE"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## MySQL
|
|
18
|
+
```bash
|
|
19
|
+
# backup
|
|
20
|
+
mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME > backup_$(date +%Y%m%d_%H%M%S).sql
|
|
21
|
+
# restore (rollback)
|
|
22
|
+
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME < $BACKUP_FILE
|
|
23
|
+
# post-apply verify
|
|
24
|
+
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME -e "DESCRIBE $TABLE;"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## SQLite
|
|
28
|
+
```bash
|
|
29
|
+
# backup
|
|
30
|
+
sqlite3 $DB_PATH ".backup 'backup_$(date +%Y%m%d_%H%M%S).db'"
|
|
31
|
+
# restore (rollback)
|
|
32
|
+
cp $BACKUP_FILE $DB_PATH
|
|
33
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# No tool — raw SQL mode
|
|
2
|
+
|
|
3
|
+
If no migration tool is detected, manage numbered up/down files; every `up` has a `down`, and every SQL runs
|
|
4
|
+
inside `BEGIN`/`COMMIT`.
|
|
5
|
+
```
|
|
6
|
+
migrations/001_create_users.up.sql + 001_create_users.down.sql
|
|
7
|
+
```
|
|
8
|
+
```sql
|
|
9
|
+
-- 001_create_users.up.sql
|
|
10
|
+
BEGIN;
|
|
11
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
12
|
+
id SERIAL PRIMARY KEY,
|
|
13
|
+
email VARCHAR(255) NOT NULL UNIQUE,
|
|
14
|
+
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
15
|
+
);
|
|
16
|
+
COMMIT;
|
|
17
|
+
-- 001_create_users.down.sql
|
|
18
|
+
BEGIN;
|
|
19
|
+
DROP TABLE IF EXISTS users;
|
|
20
|
+
COMMIT;
|
|
21
|
+
```
|
|
22
|
+
Keep the applied ones in a tracking table; run only those with no record:
|
|
23
|
+
```bash
|
|
24
|
+
psql … -c "CREATE TABLE IF NOT EXISTS _migrations(id SERIAL PRIMARY KEY, name TEXT UNIQUE, applied_at TIMESTAMP DEFAULT NOW())"
|
|
25
|
+
for f in migrations/*.up.sql; do
|
|
26
|
+
n=$(basename "$f" .up.sql)
|
|
27
|
+
[ "$(psql … -tAc "SELECT count(*) FROM _migrations WHERE name='$n'")" = 0 ] || continue
|
|
28
|
+
psql … -f "$f" && psql … -c "INSERT INTO _migrations(name) VALUES('$n')"
|
|
29
|
+
done
|
|
30
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Tool × life-cycle commands
|
|
2
|
+
|
|
3
|
+
Find your tool's row and use it. A project has one migration tool; the other eight rows are noise at the
|
|
4
|
+
moment you are running a migration, which is why they are here rather than in `SKILL.md`.
|
|
5
|
+
|
|
6
|
+
The sequence itself — **Preview → (approval) → Apply → Verify** — and the rule that a destructive migration
|
|
7
|
+
never skips the approval gate live in `SKILL.md`. This file only says which command spells each step.
|
|
8
|
+
|
|
9
|
+
| Tool | Status | Preview (dry-run) | Apply | Verify | Roll back |
|
|
10
|
+
|---|---|---|---|---|---|
|
|
11
|
+
| Prisma | `migrate status` | `migrate diff … --script` | `migrate deploy` | `migrate status` | `migrate resolve --rolled-back` + backup |
|
|
12
|
+
| Knex | `migrate:status` | `migrate:latest --dry-run` | `migrate:latest` | `migrate:status` | `migrate:rollback` |
|
|
13
|
+
| Sequelize | `db:migrate:status` | read the migration file | `db:migrate` | `db:migrate:status` | `db:migrate:undo` |
|
|
14
|
+
| TypeORM | `migration:show` | read the pending file | `migration:run` | `migration:show` | `migration:revert` |
|
|
15
|
+
| Drizzle | `drizzle-kit status` | `generate` → inspect SQL | `drizzle-kit push` | `drizzle-kit status` | `drizzle-kit drop` (prefer backup) |
|
|
16
|
+
| Alembic | `current` + `history` | `upgrade head --sql` | `upgrade head` | `current` (=head) | `downgrade -1` |
|
|
17
|
+
| Django | `showmigrations` | `sqlmigrate <app> <name>` | `migrate` | `showmigrations` ([X]) | `migrate <app> <previous>` |
|
|
18
|
+
| Rails | `db:migrate:status` | read the migration file | `db:migrate` | `db:migrate:status` (up) | `db:rollback STEP=1` |
|
|
19
|
+
| EF Core | `migrations list` | `migrations script` | `database update` | `migrations list` | `database update <previous>` |
|
|
20
|
+
|
|
21
|
+
Invocation prefix: `npx …` for the Node tools, the project's Python environment for Alembic and Django,
|
|
22
|
+
`dotnet ef …` for EF Core.
|
|
23
|
+
|
|
24
|
+
## Where a preview does not exist
|
|
25
|
+
|
|
26
|
+
Sequelize, TypeORM and Rails have no true dry-run. **Treat the migration file itself as the preview** — read
|
|
27
|
+
it out and get it approved before applying. "The tool cannot preview" is not a reason to skip the gate; it is
|
|
28
|
+
a reason the preview is manual.
|
|
29
|
+
|
|
30
|
+
## Rollback is not a substitute for the backup
|
|
31
|
+
|
|
32
|
+
Every `Roll back` command above reverses *schema* intent. None of them restores data a destructive migration
|
|
33
|
+
already dropped. That is what the mandatory production backup is for — see `references/backup-restore.md`.
|
|
34
|
+
Drizzle's entry says "prefer backup" for exactly this reason, and the same caution applies to the others
|
|
35
|
+
whenever the migration touched data rather than only structure.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dependency-audit
|
|
3
|
+
description: |
|
|
4
|
+
Dependency risk assessment, read-only: known CVEs, deprecated packages, licence compliance, maintenance
|
|
5
|
+
status, lockfile integrity, and a justification for every new dependency. Acting on it is dependency-upgrade.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Dependency Audit
|
|
9
|
+
|
|
10
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
11
|
+
Trigger phrases: "dependency audit", "npm audit", "package security", "CVE", "license", "deprecated package", "still maintained", "no longer maintained", "unmaintained", "third party library", "supply chain"
|
|
12
|
+
|
|
13
|
+
**This skill only reports.** It changes no manifest and no lockfile — bringing dependencies current is
|
|
14
|
+
[[dependency-upgrade]], which classifies each move by risk and verifies the build. Keeping the two apart keeps
|
|
15
|
+
this one safe to run any time, on any branch, including one you are only inspecting.
|
|
16
|
+
|
|
17
|
+
## Audit axes
|
|
18
|
+
1. **Known vulnerabilities (CVE):** audit appropriate to the ecosystem
|
|
19
|
+
```bash
|
|
20
|
+
npm audit --production # Node
|
|
21
|
+
dotnet list package --vulnerable # .NET (cannot be combined with --deprecated/--outdated)
|
|
22
|
+
pip-audit # Python
|
|
23
|
+
```
|
|
24
|
+
2. **License compliance:** flag licenses incompatible with the project such as copyleft/GPL (a risk in commercial closed source).
|
|
25
|
+
3. **Maintenance status:** abandoned / long-unmaintained / single-maintainer packages, and packages the registry
|
|
26
|
+
itself marks **deprecated** — `dotnet list package --deprecated`, `npm view <pkg> deprecated`. A deprecated
|
|
27
|
+
package is not a version problem: no bump fixes it, it needs a replacement.
|
|
28
|
+
4. **Transitive dependencies:** also scan vulnerabilities in indirect dependencies.
|
|
29
|
+
5. **Lockfile integrity:** lockfile committed and consistent with the manifest; versions pinned.
|
|
30
|
+
6. **Justification for new dependencies:** is it actually needed? Don't add a heavy package for a single small function (supply-chain surface).
|
|
31
|
+
7. **Install-time execution:** does any dependency run code during installation — `preinstall`/`install`/
|
|
32
|
+
`postinstall` scripts — and `prepare`, which runs only for a git, link or folder dependency and never for a
|
|
33
|
+
registry tarball — a build hook, or a setup step that fetches at install time? This is the mechanism the recent
|
|
34
|
+
registry compromises actually used: the malicious version does not have to be imported, only installed, so a
|
|
35
|
+
CVE feed and a code review both miss it. Ask two things: which packages declare such a script, and whether
|
|
36
|
+
the project can install without them at all (`npm ci --ignore-scripts`; for Python the control is refusing source
|
|
37
|
+
distributions, `pip install --only-binary=:all:`, optionally with `--require-hashes` — a wheel has no install
|
|
38
|
+
hook, an sdist does; or a vendored, pre-built artefact). A package that cannot install without running code is not disqualified —
|
|
39
|
+
it is a package whose publisher you are trusting with arbitrary execution on every machine and every runner,
|
|
40
|
+
which is a decision, not a default.
|
|
41
|
+
8. **Publisher concentration — read it from the registry, not from the repository.** "Many contributors" on a
|
|
42
|
+
forge says who can open a pull request; it does not say who can publish. The number that matters is who holds
|
|
43
|
+
the publish right on the registry (`npm owner ls <pkg>` · for PyPI the package JSON's `ownership.roles`,
|
|
44
|
+
NOT the self-reported `info.maintainer` field · the equivalent ACL for the ecosystem in use) — and whether the
|
|
45
|
+
PUBLISH PATH itself is challenged, which is not the same as "the account has 2FA": npm's `auth-only` 2FA mode
|
|
46
|
+
does not gate `npm publish`, and a granular token with bypass-2FA publishes with no second factor, while on
|
|
47
|
+
PyPI 2FA has been mandatory for every account since 2024 so the real question there is Trusted Publisher
|
|
48
|
+
versus a long-lived API token. A widely-used
|
|
49
|
+
package whose registry ACL is one unprotected account is a single compromised credential away from every
|
|
50
|
+
build that installs it, whatever the contributor graph looks like.
|
|
51
|
+
|
|
52
|
+
## Output
|
|
53
|
+
Severity-sorted list: `package · version · issue (CVE/license/maintenance) · upgrade path`.
|
|
54
|
+
|
|
55
|
+
## DoD
|
|
56
|
+
- 0 known HIGH/CRITICAL vulnerabilities; licenses compliant; lockfile consistent; every new package justified.
|
|
57
|
+
- **Every axis resolves to one of three states, and the third is a real answer:** *assessed-clean*,
|
|
58
|
+
*assessed-flagged*, or *not assessable here — and why*. An axis that was skipped because the tool is missing,
|
|
59
|
+
the registry was unreachable, or the ecosystem has no equivalent is reported as unassessed, never folded into
|
|
60
|
+
the clean count. A report that cannot tell "nothing found" from "nobody looked" is the failure this skill
|
|
61
|
+
exists to prevent, and the sibling `security-scan` already holds the same rule.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dependency-upgrade
|
|
3
|
+
description: |
|
|
4
|
+
Bring dependencies current without breaking the build: find what is vulnerable, deprecated or behind,
|
|
5
|
+
classify each target version by risk, apply what is safe, verify, and roll back what is not.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Dependency Upgrade
|
|
9
|
+
|
|
10
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
11
|
+
Trigger phrases: "upgrade dependencies", "outdated packages", "bump versions", "update packages", "keep dependencies current"
|
|
12
|
+
|
|
13
|
+
## When
|
|
14
|
+
Staying on current versions as an ongoing practice, or reacting to a CVE. [[dependency-audit]] tells you what is
|
|
15
|
+
wrong; this decides what to do about it and does it. It **mutates the manifest and the lockfile**, so it carries
|
|
16
|
+
the same shape as [[db-migration]]: detect the tool, classify by risk, gate the dangerous class behind approval,
|
|
17
|
+
apply, verify, roll back on red.
|
|
18
|
+
|
|
19
|
+
## 1 — Ask the three separate questions
|
|
20
|
+
They are three different problems with three different answers, and the tooling keeps them separate too.
|
|
21
|
+
|
|
22
|
+
| Question | Node | .NET | Python |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| What has a **known CVE**? | `npm audit --json` | `dotnet list package --vulnerable` | `pip-audit` |
|
|
25
|
+
| What is **deprecated**? | `npm view <pkg> deprecated` | `dotnet list package --deprecated` | registry / project notes |
|
|
26
|
+
| What is simply **behind**? | `npm outdated --json` | `dotnet list package --outdated` | `pip list --outdated` |
|
|
27
|
+
|
|
28
|
+
> The three `dotnet list package` flags **cannot be combined** — it is three separate runs, not one.
|
|
29
|
+
|
|
30
|
+
**Deprecated is not an upgrade.** No version bump fixes it; the package needs a replacement, which is a design
|
|
31
|
+
change with its own review — never fold it into a routine bump.
|
|
32
|
+
|
|
33
|
+
## 2 — Classify every target version before touching anything
|
|
34
|
+
The risk is not "how old is it", it is "how far does the jump go".
|
|
35
|
+
|
|
36
|
+
| Class | Rule | Approval |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| **Security patch** | fixes a known CVE, within the current major | Do it first, on its own commit — it is the one upgrade whose delay has a cost |
|
|
39
|
+
| **Patch** (`x.y.Z`) | bugfix only | Apply, batched |
|
|
40
|
+
| **Minor** (`x.Y.z`) | additive, backward compatible **by promise** | Apply, batched, only if the suite is green afterwards |
|
|
41
|
+
| **Major** (`X.y.z`) | breaking by definition | **Never automatic.** Read the changelog/migration guide, one package per commit, and say what breaks |
|
|
42
|
+
| **Pinned / transitive-only** | pinned deliberately, or not a direct dependency | Leave it. Find out *why* it is pinned before unpinning |
|
|
43
|
+
|
|
44
|
+
Semver is a promise, not a guarantee: a minor that breaks you is a bug in the package, and your suite is the
|
|
45
|
+
only thing that will tell you. That is why the verify step below is not optional.
|
|
46
|
+
|
|
47
|
+
## 3 — Apply
|
|
48
|
+
- **Group by class, one commit per group** — a patch batch and a major are not the same change and must not
|
|
49
|
+
share a commit. A single commit mixing forty bumps is unreviewable and unrevertable.
|
|
50
|
+
- **Preview first.** `npm audit fix --dry-run` before `npm audit fix`. Never reach for `npm audit fix --force`
|
|
51
|
+
without saying so out loud: it installs **semver-major** upgrades, which is precisely how this task breaks a
|
|
52
|
+
build while claiming to be a security fix.
|
|
53
|
+
- **The lockfile is part of the change.** Commit it with the manifest; a manifest bump without its lockfile is
|
|
54
|
+
a change nobody else reproduces ([[dependency-audit]] axis 5).
|
|
55
|
+
- Never hand-edit a lockfile. Let the tool regenerate it.
|
|
56
|
+
|
|
57
|
+
## 4 — Verify, then decide
|
|
58
|
+
Nothing counts as upgraded until it is observed working — install, build, full test suite, and the project's
|
|
59
|
+
quality gate. Run the app's real entry path if the change touches runtime, not just unit tests ([[testing]]).
|
|
60
|
+
|
|
61
|
+
- Green → keep it.
|
|
62
|
+
- Red → **roll back this group** (`git checkout -- <manifest> <lockfile>` then reinstall), then either pin, split
|
|
63
|
+
the batch to find the culprit, or move that package to its own major-upgrade task. Do not "fix forward" a
|
|
64
|
+
routine bump; that turns maintenance into an unplanned feature.
|
|
65
|
+
- Re-run [[dependency-audit]] afterwards: an upgrade can introduce a new transitive CVE.
|
|
66
|
+
|
|
67
|
+
## 5 — Continuous, without an autonomous loop
|
|
68
|
+
"Always current" is a **cadence**, not an agent that runs by itself — Crewforth has no timed or self-triggering
|
|
69
|
+
loops, because every mutation here needs an approval a loop cannot give. Continuity comes from somewhere that
|
|
70
|
+
already has a human gate at the end:
|
|
71
|
+
- A scheduled CI job running the step-1 commands and failing on HIGH/CRITICAL ([[ci-pipeline]]).
|
|
72
|
+
- Or a bot (Renovate / Dependabot) opening one PR per group — Crewforth does not reimplement it; the value added
|
|
73
|
+
is the policy above deciding which PRs merge on green and which need a human to read a changelog.
|
|
74
|
+
- Either way the PR passes through the ordinary gates: build, tests, [[security-scan]], review, approval.
|
|
75
|
+
|
|
76
|
+
## DoD
|
|
77
|
+
- Vulnerable, deprecated and outdated were asked as three separate questions, with the command output shown.
|
|
78
|
+
- Every applied upgrade is classed patch / minor / major, and no major went in automatically or unexplained.
|
|
79
|
+
- Security fixes landed first and separately.
|
|
80
|
+
- Manifest and lockfile moved together; no lockfile was hand-edited.
|
|
81
|
+
- Build + full suite were observed green after the change, or the group was rolled back and named.
|
|
82
|
+
- Deprecated packages are reported as replacement work, not silently bumped.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy
|
|
3
|
+
description: |
|
|
4
|
+
Ship a build reversibly — to a host you manage or a platform that manages it. Pick the topology first, keep
|
|
5
|
+
the previous version reachable, gate on health, roll back without rebuilding. Use when shipping anywhere
|
|
6
|
+
users can reach.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Deploy
|
|
10
|
+
|
|
11
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
12
|
+
Trigger phrases: "deploy", "push to the server", "to the server", "onto the server", "build on the server", "install on the VPS", "ship it to the server", "go to production", "to production", "go live"
|
|
13
|
+
|
|
14
|
+
A deploy has a single idea, and it does not depend on where you are deploying: **make the new version live in a
|
|
15
|
+
way you can undo.** Keep the previous version reachable until the new one has proved itself; if it fails the
|
|
16
|
+
health gate, go back to the old one and nobody notices.
|
|
17
|
+
|
|
18
|
+
**Two topologies implement that idea differently, and mixing them is where deploys go wrong.** On a host you
|
|
19
|
+
manage, "reversible" means the previous release still sits on disk and the swap is a pointer you can move back.
|
|
20
|
+
On a platform that manages the host for you, "reversible" means the previous *artefact* is still addressable and
|
|
21
|
+
you re-point the environment at it — you do not rebuild it. Phase 0 picks the branch; everything after follows.
|
|
22
|
+
|
|
23
|
+
> **Crewforth adaptation (local, .claude/):** Any backend runtime (Docker recommended). **Deploy requires explicit
|
|
24
|
+
> approval (§4.4)**; a backup before every swap and a health gate after are mandatory. If `.deploy.yml` carries server
|
|
25
|
+
> credentials it goes into `.gitignore`. §4 Prohibitions apply.
|
|
26
|
+
|
|
27
|
+
## Phase 0 — Which topology
|
|
28
|
+
Answer before anything else, because the rest of the skill forks here. Ask if it is not obvious; do not infer it
|
|
29
|
+
from the language or the framework.
|
|
30
|
+
|
|
31
|
+
| | **A · Self-managed host** | **B · Managed platform** |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| You have | SSH to a machine you own or rent | an API/CLI, and no shell on the box |
|
|
34
|
+
| A release is | a directory on that host | an immutable artefact (image digest, build id, bundle) |
|
|
35
|
+
| "Deploy" means | put the files in place and restart | promote an existing artefact to an environment |
|
|
36
|
+
| Rollback means | move the pointer back to the previous directory | re-point the environment at the previous artefact |
|
|
37
|
+
| Owned by | **`references/topology-a.md`** (phases 1–5) | **`references/topology-b.md`** (phases B1–B4) |
|
|
38
|
+
|
|
39
|
+
Signals for B: the platform builds from a push, or the runtime is described as containers/functions/dynos/pods
|
|
40
|
+
that you do not administer. Signals for A: you are given a host, a user and a port. A Kubernetes cluster is B
|
|
41
|
+
when a controller reconciles it from a manifest, and A only if you are genuinely hand-placing files on nodes.
|
|
42
|
+
|
|
43
|
+
**If both are in play** — a managed platform in front, a self-managed worker behind — run the branches
|
|
44
|
+
separately and gate each on its own health check. One approval does not cover two topologies.
|
|
45
|
+
|
|
46
|
+
## Checklist (A · self-managed host)
|
|
47
|
+
- [ ] Topology decided (Phase 0)
|
|
48
|
+
- [ ] Runtime + deploy method determined
|
|
49
|
+
- [ ] Config taken from `.deploy.yml`/the user, SSH verified
|
|
50
|
+
- [ ] Reverse proxy + (if there is a domain) SSL in place
|
|
51
|
+
- [ ] Running version backed up to `releases/`
|
|
52
|
+
- [ ] User approved the deploy, new version deployed
|
|
53
|
+
- [ ] Health gate passed (otherwise automatic rollback performed)
|
|
54
|
+
- [ ] If requested, single-command scripts (`deploy.sh` / `adopt.sh`) generated
|
|
55
|
+
|
|
56
|
+
## Checklist (B · managed platform)
|
|
57
|
+
- [ ] Topology decided (Phase 0)
|
|
58
|
+
- [ ] Artefact built once and addressed immutably (digest / build id, not a moving tag)
|
|
59
|
+
- [ ] Which artefact is in which environment is recorded
|
|
60
|
+
- [ ] Config and secrets injected per environment, not baked into the artefact
|
|
61
|
+
- [ ] User approved the promotion to this environment
|
|
62
|
+
- [ ] Health gate passed from OUTSIDE — not the platform's own status
|
|
63
|
+
- [ ] Previous artefact still addressable, and the migration question settled before the deploy
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## The phases — read ONE branch
|
|
68
|
+
|
|
69
|
+
Phase 0 picked it; loading both is the mistake this skill opens with.
|
|
70
|
+
|
|
71
|
+
- **A · self-managed host** → **`references/topology-a.md`**: runtime/method detection, `.deploy.yml` + SSH,
|
|
72
|
+
reverse proxy and SSL, the backup-then-swap for Docker and bare-metal, the health gate, the rollback.
|
|
73
|
+
- **B · managed platform** → **`references/topology-b.md`**: build once and address it immutably, promote
|
|
74
|
+
without rebuilding, health-gate from outside the platform, roll back by re-pointing.
|
|
75
|
+
|
|
76
|
+
The invariant rules at the end of this file hold on both, and they are the half that must not be read from a
|
|
77
|
+
reference file: they are what an approval is checked against.
|
|
78
|
+
|
|
79
|
+
## Single-command scripts (optional)
|
|
80
|
+
|
|
81
|
+
After a successful deploy, **ask** whether to generate project-specific `deploy.sh` / `adopt.sh` (single-command
|
|
82
|
+
deploy/update). Derive the steps from the real project (package.json / Dockerfile / Makefile / compose), never a
|
|
83
|
+
generic template. Full guidance + what each script contains: **`references/scripts.md`**.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Invariant rules
|
|
88
|
+
These hold on BOTH branches; where the mechanism differs, the rule does not.
|
|
89
|
+
0. **The topology is decided, not assumed** — Phase 0, once, out loud. Everything downstream depends on it.
|
|
90
|
+
1. **No deploy without approval** — show the method/host/domain/port plan, wait for approval.
|
|
91
|
+
2. **Always back up before the swap** — timestamped into `releases/`; if the backup fails, abort.
|
|
92
|
+
3. **Always a health gate after the swap** — HTTP + process; if it doesn't pass, automatic rollback.
|
|
93
|
+
4. **Keep the last 3 versions** — don't delete them all.
|
|
94
|
+
5. **Don't deploy to prod without knowing the target** — host/deploy_path/domain must be approved.
|
|
95
|
+
6. **Verify SSH first** — if you can't connect, fail fast.
|
|
96
|
+
7. **Don't expose the port directly** — the app binds to `127.0.0.1`, outward only through the proxy.
|
|
97
|
+
8. **SSL is mandatory when there's a domain** — always set it up unless `ssl` is explicitly `false`.
|
|
98
|
+
9. **Never rebuild to roll back** (B) — promote the previous artefact. A rebuild is a different artefact.
|
|
99
|
+
10. **The platform's own status is not the health gate** (B) — verify from where a user stands.
|
|
100
|
+
11. **Rolling back code does not roll back a migration** — settle the schema question before the deploy.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Reverse proxy and SSL — the file contents
|
|
2
|
+
|
|
3
|
+
Read the half you need. A deploy uses Nginx **or** Caddy, never both, and the two paths differ most exactly
|
|
4
|
+
where it matters: Caddy obtains and renews the certificate itself, Nginx needs Certbot wired up separately.
|
|
5
|
+
|
|
6
|
+
The decision — which proxy is installed, whether SSL applies at all, and that the app binds only to
|
|
7
|
+
`127.0.0.1` — stays in `SKILL.md`. This file is what to write once that is settled.
|
|
8
|
+
|
|
9
|
+
## Nginx
|
|
10
|
+
|
|
11
|
+
Site config:
|
|
12
|
+
|
|
13
|
+
```nginx
|
|
14
|
+
server {
|
|
15
|
+
listen 80;
|
|
16
|
+
server_name DOMAIN;
|
|
17
|
+
location / {
|
|
18
|
+
proxy_pass http://127.0.0.1:APP_PORT;
|
|
19
|
+
proxy_http_version 1.1;
|
|
20
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
21
|
+
proxy_set_header Connection 'upgrade';
|
|
22
|
+
proxy_set_header Host $host;
|
|
23
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
24
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
25
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Link it into `sites-enabled` with `ln -s`, then `nginx -t && systemctl reload nginx`. Run `nginx -t` before
|
|
31
|
+
the reload every time — a reload on a broken config takes the site down, and the test costs nothing.
|
|
32
|
+
|
|
33
|
+
### SSL on the Nginx path
|
|
34
|
+
|
|
35
|
+
Skip entirely when `ssl: false` or there is no domain. **Never attempt SSL on a bare IP** — a certificate
|
|
36
|
+
authority cannot issue for one, and the attempt burns rate-limited quota on the domain you will use later.
|
|
37
|
+
|
|
38
|
+
Verify DNS resolves to this host *first*, or Certbot's challenge fails in a way that looks like a proxy fault:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
dig +short $DOMAIN # must equal $HOST
|
|
42
|
+
certbot --nginx -d $DOMAIN --non-interactive --agree-tos -m admin@$DOMAIN
|
|
43
|
+
systemctl enable certbot.timer # automatic renewal — without this the site breaks in 90 days
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Caddy
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
DOMAIN {
|
|
50
|
+
reverse_proxy 127.0.0.1:APP_PORT
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`systemctl reload caddy`. Caddy handles the certificate and its renewal on its own — no Certbot, no timer, no
|
|
55
|
+
separate SSL step. If the domain does not yet resolve, Caddy will retry rather than fail loudly, so check
|
|
56
|
+
`journalctl -u caddy` when a fresh domain serves plain HTTP longer than expected.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Phase 5 — Rollback (run on health-gate failure)
|
|
2
|
+
|
|
3
|
+
Undo the swap: put the most recent version in `releases/` back into `current`, restart the service, repeat the
|
|
4
|
+
health gate (Phase 4).
|
|
5
|
+
```bash
|
|
6
|
+
LATEST=$(ssh -i $SSH_KEY $USER@$HOST "ls -dt $DEPLOY_PATH/releases/*/ 2>/dev/null | head -1")
|
|
7
|
+
[ -z "$LATEST" ] && { echo "ERROR: no backup — rollback impossible"; exit 1; }
|
|
8
|
+
ssh -i $SSH_KEY $USER@$HOST "
|
|
9
|
+
mkdir -p $DEPLOY_PATH/current
|
|
10
|
+
rsync -a --delete ${LATEST%/}/ $DEPLOY_PATH/current/ # atomic swap — no 'rm -rf' (guard-safe)
|
|
11
|
+
{ docker rm -f $APP 2>/dev/null && docker run -d --name $APP --restart unless-stopped \
|
|
12
|
+
-p 127.0.0.1:$APP_PORT:$APP_PORT $APP:previous; } \
|
|
13
|
+
|| systemctl restart $APP || pm2 restart $APP
|
|
14
|
+
"
|
|
15
|
+
```
|
|
16
|
+
> **Note:** Rollback uses `rsync --delete` instead of `rm -rf` so `guard-bash` (the local `rm -rf` block) doesn't
|
|
17
|
+
> block the automatic rollback. The deploy verbs (`ssh`/`rsync`/`docker`) pass through the approval gate via
|
|
18
|
+
> `settings.json` `permissions.ask` — they run with approval, not silently.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Single-command scripts (optional)
|
|
2
|
+
|
|
3
|
+
After a successful deploy, **ask:** "Shall I generate `deploy.sh` and `adopt.sh` so you can deploy/update with a single command in the future?"
|
|
4
|
+
|
|
5
|
+
If you generate them, **don't use a generic template** — analyze the actual project (package.json scripts / Dockerfile / Makefile / docker-compose / `.env.example`) and derive the exact build+start steps. Two scripts:
|
|
6
|
+
- **`deploy.sh`** — first-time setup + deploy: load config · verify SSH · proxy + SSL · back up to `releases/` · project-specific build · transfer · dependencies · start · health gate with retries · rollback on failure.
|
|
7
|
+
- **`adopt.sh`** — quick update: config · backup · code sync · (if needed) build/dependencies · restart · health gate · rollback on failure.
|
|
8
|
+
|
|
9
|
+
Rules: `chmod +x`; if `.deploy.yml` carries credentials, ask about `.gitignore`; don't overwrite an existing script without approval (show a diff); no hardcoded credentials — always read from `.deploy.yml`; comment and explain every project-specific decision.
|