vibecarbon 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +110 -663
- package/README.md +4 -4
- package/carbon/.env.example +11 -0
- package/carbon/backup/compose-backup.sh +8 -0
- package/carbon/docker-compose.yml +11 -0
- package/carbon/ha/primary-init.sql +10 -2
- package/carbon/k8s/base/backup/cronjob.yaml +9 -0
- package/carbon/k8s/base/repl-gateway/kustomization.yaml +11 -0
- package/carbon/k8s/base/repl-gateway/repl-gateway.yaml +92 -0
- package/carbon/k8s/values/supabase.values.yaml +6 -1
- package/carbon/src/client/lib/supabase.ts +41 -0
- package/carbon/src/client/locales/de.json +27 -12
- package/carbon/src/client/locales/en.json +30 -15
- package/carbon/src/client/locales/es.json +27 -12
- package/carbon/src/client/locales/fr.json +27 -12
- package/carbon/src/client/locales/pt.json +27 -12
- package/carbon/src/client/pages/Checkout.tsx +1 -1
- package/carbon/src/server/billing/providers/paddle.ts +21 -2
- package/carbon/src/server/billing/providers/polar.ts +14 -0
- package/carbon/src/server/index.ts +12 -9
- package/carbon/src/server/lib/client-ip.ts +68 -0
- package/carbon/src/server/lib/env.ts +20 -6
- package/carbon/src/server/lib/rate-limiter.ts +11 -65
- package/carbon/src/server/lib/supabase.ts +10 -4
- package/carbon/src/server/middleware/requireOrgRole.ts +76 -0
- package/carbon/src/server/middleware/requirePlan.ts +64 -34
- package/carbon/src/server/middleware/requireSuperAdmin.ts +26 -0
- package/carbon/src/server/routes/v1/admin/contact.ts +5 -20
- package/carbon/src/server/routes/v1/admin/jobs.ts +6 -20
- package/carbon/src/server/routes/v1/admin/newsletter.ts +26 -23
- package/carbon/src/server/routes/v1/auth.ts +5 -2
- package/carbon/src/server/routes/v1/billing.ts +24 -64
- package/carbon/src/server/routes/v1/index.ts +8 -1
- package/carbon/src/server/routes/v1/newsletter.ts +18 -12
- package/carbon/src/server/routes/v1/theme.ts +36 -15
- package/carbon/supabase/migrations/00003_pg_cron.sql +2 -2
- package/carbon/supabase/migrations/00004_contact_newsletter.sql +24 -14
- package/carbon/tests/component/supabase-env-guard.test.ts +54 -0
- package/carbon/tests/integration/server/middleware/rate-limit-ip-spoof.test.ts +48 -0
- package/carbon/tests/integration/server/middleware/require-plan.test.ts +101 -0
- package/carbon/tests/integration/server/routes/admin-newsletter.test.ts +93 -0
- package/carbon/tests/integration/server/routes/billing-subscription-idor.test.ts +92 -0
- package/carbon/tests/integration/server/routes/newsletter-unsubscribe.test.ts +65 -0
- package/carbon/tests/integration/server/routes/theme-validation.test.ts +66 -0
- package/carbon/tests/unit/server/client-ip.test.ts +76 -0
- package/carbon/tests/unit/server/env-bool.test.ts +63 -0
- package/carbon/tests/unit/server/paddle-webhook.test.ts +57 -0
- package/carbon/tests/unit/server/polar-webhook.test.ts +63 -0
- package/carbon/tests/unit/server/supabase-client.test.ts +30 -0
- package/carbon/volumes/db/wal-archive.sh +36 -0
- package/package.json +2 -2
- package/src/backup.js +0 -2
- package/src/cli.js +16 -0
- package/src/deploy.js +16 -5
- package/src/destroy.js +78 -0
- package/src/failover.js +118 -237
- package/src/lib/command.js +19 -1
- package/src/lib/deploy/compose/ha.js +180 -102
- package/src/lib/deploy/compose/index.js +63 -20
- package/src/lib/deploy/image.js +19 -23
- package/src/lib/deploy/k8s/ha/index.js +397 -150
- package/src/lib/deploy/k8s/k3s.js +65 -14
- package/src/lib/deploy/orchestrator.js +176 -6
- package/src/lib/deploy/remote-build.js +8 -1
- package/src/lib/deploy/replication.js +540 -0
- package/src/lib/deploy/state.js +62 -5
- package/src/lib/deploy/utils.js +30 -2
- package/src/lib/deploy/wireguard.js +146 -0
- package/src/lib/host-keys.js +120 -5
- package/src/lib/iac/index.js +57 -23
- package/src/lib/licensing/gate.js +59 -0
- package/src/lib/licensing/index.js +1 -1
- package/src/lib/licensing/tiers.js +6 -5
- package/src/lib/prod-confirm.js +65 -0
- package/src/lib/providers/hetzner-s3.js +85 -0
- package/src/lib/ssh.js +35 -35
- package/src/restore.js +102 -14
- package/src/scale.js +4 -2
- package/src/status.js +122 -0
- package/src/upgrade.js +0 -4
- package/carbon/ha/activate-standby.sh +0 -52
- package/carbon/ha/standby-init.sh +0 -74
- package/carbon/src/server/lib/request.ts +0 -34
- package/src/lib/pod-backups.js +0 -53
package/src/lib/deploy/image.js
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { execFileSync } from 'node:child_process';
|
|
16
|
+
import { knownHostsPathForKey } from '../host-keys.js';
|
|
17
|
+
import { shEscape } from '../shell.js';
|
|
16
18
|
|
|
17
19
|
const LOCAL_REGISTRY_PREFIX = 'vibecarbon-local';
|
|
18
20
|
|
|
@@ -146,36 +148,30 @@ function defaultTimestamp() {
|
|
|
146
148
|
* `gzip -1` is universally present and dominant cost is network, not CPU.
|
|
147
149
|
*
|
|
148
150
|
* `pipefail` so a docker-save / gzip failure isn't masked by ssh's exit code.
|
|
149
|
-
* `StrictHostKeyChecking=accept-new` matches the convention used elsewhere
|
|
150
|
-
* in vibecarbon's ssh paths: trust-on-first-use, error on host-key change.
|
|
151
151
|
*
|
|
152
152
|
* @param {{tag: string, sshTarget: string, sshKey?: string}} args
|
|
153
153
|
*/
|
|
154
154
|
export function sideloadCompose({ tag, sshTarget, sshKey }) {
|
|
155
|
-
// SSH options mirror remote-build.js's wrapper
|
|
156
|
-
// *
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
// update the entry). iter-perfwave4 hit exactly this on first run.
|
|
155
|
+
// SSH options mirror remote-build.js's wrapper + the compose deploy path:
|
|
156
|
+
// * Host-key pinned per-env (knownHostsPathForKey), NOT /dev/null + no.
|
|
157
|
+
// accept-new TOFU's an ephemeral/recycled Hetzner IP but rejects a
|
|
158
|
+
// changed key for an already-pinned host (MITM on an established env
|
|
159
|
+
// fails). GlobalKnownHostsFile=/dev/null ignores the system file; the
|
|
160
|
+
// operator's ~/.ssh/known_hosts is never touched (a stale entry there
|
|
161
|
+
// would otherwise reject a recycled IP — iter-perfwave4 hit this).
|
|
163
162
|
// * BatchMode=yes per feedback_ssh_batchmode_required.md (PR 1T):
|
|
164
|
-
// fast-fail rather than hang on interactive password prompt
|
|
165
|
-
// key fails.
|
|
163
|
+
// fast-fail rather than hang on interactive password prompt.
|
|
166
164
|
// * ConnectTimeout=30: bound the network half of dial; sideload's own
|
|
167
165
|
// stream is unbounded (limited by docker save throughput).
|
|
168
|
-
const sshFlags = [
|
|
169
|
-
|
|
170
|
-
'
|
|
171
|
-
|
|
172
|
-
'
|
|
173
|
-
'-o',
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
];
|
|
178
|
-
if (sshKey) sshFlags.unshift('-i', sshKey);
|
|
166
|
+
const sshFlags = ['-o', 'StrictHostKeyChecking=accept-new'];
|
|
167
|
+
if (sshKey) {
|
|
168
|
+
// shEscape the known_hosts assignment so a project dir with spaces can't
|
|
169
|
+
// split the argument in the bash -c string below.
|
|
170
|
+
sshFlags.push('-o', shEscape(`UserKnownHostsFile=${knownHostsPathForKey(sshKey)}`));
|
|
171
|
+
sshFlags.push('-o', 'GlobalKnownHostsFile=/dev/null');
|
|
172
|
+
}
|
|
173
|
+
sshFlags.push('-o', 'BatchMode=yes', '-o', 'ConnectTimeout=30');
|
|
174
|
+
if (sshKey) sshFlags.unshift('-i', shEscape(sshKey));
|
|
179
175
|
const cmd = `set -o pipefail && docker save ${tag} | gzip -1 | ssh ${sshFlags.join(' ')} ${sshTarget} 'gunzip | docker load'`;
|
|
180
176
|
// Capture stdio rather than inheriting it: ssh's "Permanently added" host-
|
|
181
177
|
// key warning + `docker load`'s "Loaded image:" success line both bypass
|