kampodra 0.8.4 → 0.8.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kampodra",
3
- "version": "0.8.4",
3
+ "version": "0.8.7",
4
4
  "description": "Registry-free deployment CLI for single-VM container stacks over SSH (Podman + kamal-proxy)",
5
5
  "license": "AGPL-3.0",
6
6
  "type": "module",
@@ -8,10 +8,10 @@
8
8
  "kampodra": "bin/kampodra.js"
9
9
  },
10
10
  "optionalDependencies": {
11
- "@kampodra/darwin-arm64": "0.8.4",
12
- "@kampodra/darwin-x64": "0.8.4",
13
- "@kampodra/linux-arm64": "0.8.4",
14
- "@kampodra/linux-x64": "0.8.4"
11
+ "@kampodra/darwin-arm64": "0.8.7",
12
+ "@kampodra/darwin-x64": "0.8.7",
13
+ "@kampodra/linux-arm64": "0.8.7",
14
+ "@kampodra/linux-x64": "0.8.7"
15
15
  },
16
16
  "engines": {
17
17
  "node": ">=20"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: kampodra
3
- description: "Operates the kampodra CLI, a kamal-alternative that deploys containers or binaries to Linux VMs over SSH with podman and kamal-proxy — no registry in the image path, zero-downtime by default. Use when deploying or rolling back a release, running the standby-update bluegreen flow (deploy to the idle color then flip), recovering an interrupted rolling deploy, reading deploy logs/status, pushing or diffing remote env files, generating env from a schema, managing instance profiles, listing or verifying backups, planning a restore, managing DNS records on OCI or GCP, staging golden images, running tenant database migrations, sampling VM metrics, or preparing and wiping VMs. Triggers: deploy, rollback, podman, kamal-proxy, SSH, env, metrics, backup, DNS, gcp, gcloud, oci, bluegreen, flip, migrate, VM, Alpine."
3
+ description: "Operates the kampodra CLI, a kamal-alternative that deploys containers or binaries to Linux VMs over SSH with podman and kamal-proxy — no registry in the image path, zero-downtime by default. Use when deploying or rolling back a release, running the standby-update bluegreen flow (deploy to the idle color then flip), recovering an interrupted rolling deploy, reading deploy logs/status, pushing or diffing remote env files, generating env from a schema, managing instance profiles, listing or verifying backups, planning a restore, managing DNS records on OCI or GCP, staging golden images, running tenant database migrations, sampling VM metrics, preparing or wiping VMs, or running read-only database queries and snapshots (sqlite, MariaDB, self-hosted libsql/sqld). Triggers: deploy, rollback, podman, kamal-proxy, SSH, env, metrics, backup, DNS, gcp, gcloud, oci, bluegreen, flip, migrate, VM, Alpine, db query, db snapshot, libsql, sqld, mariadb, sqlite."
4
4
  license: AGPL-3.0
5
5
  compatibility: Requires podman, ssh, and git locally; the target VM needs a Linux userland (Alpine or Ubuntu 24.04) with podman and kamal-proxy (vm-prepare installs them). Cloud families authenticate through the provider CLI itself (oci or gcloud).
6
6
  metadata:
@@ -90,6 +90,7 @@ A leftover shadow must be converged before the next `--rolling` deploy. `--drain
90
90
  | Operation | Behavior | Guard |
91
91
  |---|---|---|
92
92
  | `vm-wipe` | Stops/disables services, removes project containers, prunes images, deletes env/stamp/state | `--yes` REQUIRED; `--keep-data` spares the data dir; `--force` overrides a services-mismatch refusal (wrong host?) |
93
+ | `vm gc --apply` | Deletes ONLY stale scratch/scripts/residues from the typed sweep inventory | Dry run by default; hard-coded never-touch allowlists (tenant data, live chains, kampodra helpers, OS, build contexts, owner decisions); podman strictly report-only; in-use candidates blocked |
93
94
  | `backup restore-plan <object>` | PRINTS the documented recovery sequence | Never executes anything |
94
95
  | `backup verify <file>` | Read-only: uploads to VM scratch files and runs the VM's `restore-verify` | Never writes into the data dir |
95
96
  | `deploy prune` | Removes old sha-tagged images (keeps running + ts-rollback + newest N) | `--dry-run` prints exact commands first |
@@ -97,6 +98,51 @@ A leftover shadow must be converged before the next `--rolling` deploy. `--drain
97
98
  | `env push` | Overwrites the remote env file atomically | Preview first with `env diff <local-file>` (exit 1 = differs) |
98
99
  | `vm-prepare` | Mutates a bare host (packages, sshd, services) | Idempotent; safe to re-run |
99
100
 
101
+ ## Read-only database access (db)
102
+
103
+ `kampodra db query` (one SELECT/WITH → rows on stdout) and
104
+ `kampodra db snapshot` (verified consistent copy, 0600) over ssh, three
105
+ engines behind `--engine auto` (flag > the VM env file's
106
+ KAMPODRA_DB_ENGINE > file magic):
107
+
108
+ - **sqlite** — `--db` is the file's path; rows as flat JSON; snapshot via
109
+ `sqlite3 .backup` (consistent).
110
+ - **mariadb** — `--db` is the schema NAME; creds ride the VM env file
111
+ (KAMPODRA_DB_NAME/HOST/USER/PASSWORD via `kampodra env set`), staged to
112
+ a 0600 defaults file, never argv; snapshot = mariadb-dump
113
+ --single-transaction with a "Dump completed" tail gate. Prefer a
114
+ read-only role (GRANT SELECT) for agent queries — `db grant-ro`
115
+ provisions it (mariadb executes; postgres prints the SQL). Podman
116
+ container deployments (the estate's shape): no host client needed —
117
+ tools run via `podman exec` in-container, and snapshots take the
118
+ PHYSICAL form (in-container mariabackup → prepare → tar, gated on the
119
+ control files; restore with mariabackup --copy-back).
120
+ - **postgres** — same env-file contract as mariadb; PGPASSFILE staged
121
+ 0600; pg_dump MVCC-consistent with a completeness tail gate.
122
+ - **libsql (self-hosted sqld)** — no --db needed; KAMPODRA_DB_URL
123
+ (default localhost:8080) + optional KAMPODRA_DB_TOKEN, staged to a 0600
124
+ header file; rows as flat JSON (same shape as sqlite); snapshot needs
125
+ KAMPODRA_DB_PATH and gates on PRAGMA integrity_check.
126
+
127
+ Server engines on their own VM: `--db-host` / profile `dbHost` moves the
128
+ flows' ssh to the DB VM (its env file carries the creds). TSV engines
129
+ emit string values (batch text has no types); file engines emit typed
130
+ JSON.
131
+
132
+ `kampodra db grant-ro --db <schema>` provisions the read-only role:
133
+ mariadb executes end-to-end (random password, env keys written on the
134
+ VM, password never printed); `--engine postgres` prints the ready SQL.
135
+
136
+ The gate rejects non-SELECT/WITH statements (exit 2) BEFORE any ssh on
137
+ every engine — a rejected statement costs zero round-trips.
138
+
139
+ ```
140
+ kampodra db query --db /data/root.db --sql "SELECT count(*) FROM org" --profile prod
141
+ kampodra db query --db esellar --sql "SELECT id, total FROM pos_order LIMIT 5" # mariadb, after env set
142
+ kampodra db snapshot --db esellar --out ./esellar.sql
143
+ kampodra db snapshot --out ./app.db # libsql, after env set
144
+ ```
145
+
100
146
  ## Gotchas
101
147
 
102
148
  - Defaults are GENERIC placeholders (`app`, `/etc/kampodra/env`, `app-backups`, `/up`), not your app's names — commit a `kampodra.json` before the first deploy against a new tree, or check `config print`.
@@ -17,6 +17,7 @@ CLI source (`internal/command/*.go`). When this file and `kampodra <command>
17
17
  - [backup](#backup) (list / download / verify / restore-plan)
18
18
  - [vm-prepare](#vm-prepare)
19
19
  - [vm-wipe](#vm-wipe)
20
+ - [vm gc](#vm-gc)
20
21
  - [metrics](#metrics)
21
22
  - [dns](#dns) (records / add / rm)
22
23
  - [migrate](#migrate)
@@ -355,6 +356,33 @@ running, it refuses (`--force` to mean it — wrong host?). Individual step
355
356
  failures are tolerated and reported, not fatal.
356
357
  Example: `kampodra vm-wipe --profile prod --yes --keep-data`
357
358
 
359
+ ## vm gc
360
+
361
+ Dry-run-by-default VM garbage sweep: a typed inventory of every host
362
+ artifact (scratch / stale-script / residue / kampodra-helper / os-session
363
+ / os / infra / tenant-data / live / owner-decision / unknown), with
364
+ `--apply` deleting ONLY the stale classes. Built so agents never hand-roll
365
+ `find | rm` sweeps over raw ssh again — the never-touch allowlists are
366
+ enforced in code, twice (classification + per-command validation).
367
+
368
+ | Flag | Type | Default |
369
+ |---|---|---|
370
+ | `--apply` | bool | `false` — delete the stale classes found by the sweep |
371
+ | `--host` | string | `""` |
372
+ | `--profile` | string | `""` |
373
+ | `--ssh-key` | string | `""` |
374
+
375
+ - NEVER touched: OS paths + podman storage, the live artifact/web/backup
376
+ chains, kampodra's own helpers (`/tmp/kampodra-*`), OS session dirs,
377
+ live build contexts (scratch dirs holding a Dockerfile), cutover db
378
+ snapshots beside the data dir, `/root` pre-op safety snapshots.
379
+ - Tenant data routes from the project's `dataDir` (zero knowledge fails
380
+ closed to report-only); podman is strictly report-only; candidates in
381
+ use by a live process or container bind mount are BLOCKED.
382
+ - `/opt` and `/home`: unrecognized content is report-only; only stale
383
+ `.sh` scripts are deletable there.
384
+ Example: `kampodra vm gc --profile prod --apply`
385
+
358
386
  ## metrics
359
387
 
360
388
  One-shot VM snapshot over SSH (load, memory, disk breakdown, containers, top
@@ -415,8 +443,11 @@ Tenant db migrations over SSH, applied THROUGH the repo checkout ON the VM
415
443
  (the app's own script, path from the `migrateScript` config — default
416
444
  `scripts/migrate-db.ts`; no parallel implementation; runs via `pnpm exec
417
445
  tsx`). Order: root.db first
418
- (`root/root.db` preferred, legacy flat `root.db` honored), then `tenant_*.db`
419
- sorted, bounded-parallel. Preconditions are probed in one round-trip and fail
446
+ (`root/root.db` preferred, legacy flat `root.db` honored), then the support
447
+ + billing class dbs (`support/support.db`, `billing/billing.db` — their own
448
+ `-dir` pairings in binary mode), then `tenant_*.db`
449
+ sorted, bounded-parallel. A db file matching no known class is an explicit
450
+ warned skip. Preconditions are probed in one round-trip and fail
420
451
  closed: repo root (must contain the migrate script), pnpm, tenant data dir.
421
452
 
422
453
  | Flag | Type | Default |