@bongos/core 1.20.14 → 1.20.16

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.
@@ -372,24 +372,6 @@ t('healthzCmd hits the instance port /healthz', () => {
372
372
  assert.match(P.healthzCmd(coTenant), /127\.0\.0\.1:3003\/healthz/);
373
373
  });
374
374
 
375
- t('dedicatedUserData bakes createdb + migrate + first-version seed into cloud-init (task 2119: dedicated must not diverge)', () => {
376
- const ud = P.dedicatedUserData(coTenant);
377
- assert.match(ud, /^#cloud-config/);
378
- assert.match(ud, /createdb mercury/);
379
- assert.match(ud, /MEDUSA_GDS_ONLY=1/);
380
- // the seed rides cloud-init too, so a dedicated droplet also comes up able to take tasks
381
- assert.match(ud, /INSERT INTO versions/, 'seed baked into cloud-init');
382
- // it must be its OWN runcmd line AFTER migrate (the schema must exist first)
383
- const lines = ud.split('\n');
384
- const iMig = lines.findIndex((l) => /migrate\.sh/.test(l));
385
- const iSeed = lines.findIndex((l) => /INSERT INTO versions/.test(l));
386
- assert.ok(iMig >= 0 && iSeed > iMig, 'seed line comes after the migrate line');
387
- // the seed line is a valid bash -lc "…" item: single-quoted -c arg, NO double quotes to break the YAML scalar
388
- const seedLine = lines[iSeed];
389
- assert.match(seedLine, /- \[ bash, -lc, "psql .*" \]/, 'well-formed cloud-init runcmd item');
390
- assert.doesNotMatch(seedLine.replace(/^.*-lc, "/, '').replace(/" \]$/, ''), /"/, 'the seed command carries no inner double quotes');
391
- });
392
-
393
375
  console.log('\nport allocation:');
394
376
 
395
377
  t('nextFreePort skips reserved + taken, returns the lowest free ≥ base', () => {
@@ -440,7 +422,6 @@ function recorder({ apply = false } = {}) {
440
422
  },
441
423
  exec: (cmd) => { cmds.push(cmd); return { ok: true, stdout: '' }; },
442
424
  writeFile: (p) => { writes.push(p); return { ok: true }; },
443
- doApi: null,
444
425
  // Stub the DNS token-scope preflight (task 1980) so the composition stays hermetic
445
426
  // (no real CF call). Default: reachable; a test overrides it to exercise the block.
446
427
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'example.com' }),
@@ -1323,29 +1304,6 @@ await ta('provisionInstance is idempotent: an already-active instance is a no-op
1323
1304
  assert.equal(cmds.length, 0, 'no commands run for an active instance');
1324
1305
  });
1325
1306
 
1326
- await ta('provisionInstance(dedicated) does NOT run local createdb/migrate/seed (they ride cloud-init)', async () => {
1327
- const { deps, cmds } = recorder();
1328
- await P.provisionInstance({ ...coTenant, hosting_shape: 'dedicated', tier: 's-2vcpu-4gb' }, deps);
1329
- assert.ok(!cmds.some((c) => /createdb/.test(c)), 'dedicated does not run createdb locally');
1330
- assert.ok(!cmds.some((c) => /INSERT INTO versions/.test(c)), 'dedicated does not run the version seed locally (it rides cloud-init)');
1331
- });
1332
-
1333
- await ta('dedicatedUserData bakes the nightly backup: unit files (b64) + dir + timer enable (task 2213)', async () => {
1334
- const inst = { ...coTenant, hosting_shape: 'dedicated' };
1335
- const cloudInit = P.dedicatedUserData(inst);
1336
- // the two unit files land via write_files (base64, so no YAML block-scalar escaping)
1337
- assert.match(cloudInit, /write_files:/);
1338
- assert.match(cloudInit, new RegExp('path: ' + reEsc(P.backupServicePath(inst))));
1339
- assert.match(cloudInit, new RegExp('path: ' + reEsc(P.backupTimerPath(inst))));
1340
- assert.match(cloudInit, /encoding: b64/);
1341
- // the base64 content round-trips to a real unit carrying the right DB
1342
- const b64 = cloudInit.match(/content: ([A-Za-z0-9+/=]+)/)[1];
1343
- assert.match(Buffer.from(b64, 'base64').toString('utf8'), /Environment=GDS_BACKUP_DB=mercury/);
1344
- // and the dir is created + the timer enabled on first boot
1345
- assert.match(cloudInit, /install -d -o appsvc -g \$\(id -gn appsvc\) -m 0750 \/var\/backups\/gds/);
1346
- assert.match(cloudInit, /enable --now mercury mercury-db-backup\.timer/);
1347
- });
1348
-
1349
1307
  console.log('\nDNS UPSERT composition (P4, CONFIG override):');
1350
1308
 
1351
1309
  // A recorder that also captures each exec's env (so we can assert the DNS hook env).
@@ -1359,7 +1317,7 @@ function dnsRecorder({ apply = false } = {}) {
1359
1317
  clearReleasedDomains: async (_db, id) => { cleared.push(id); },
1360
1318
  },
1361
1319
  exec: (cmd, opts) => { cmds.push(cmd); envs.push(opts && opts.env); return { ok: true, stdout: '' }; },
1362
- writeFile: () => ({ ok: true }), doApi: null,
1320
+ writeFile: () => ({ ok: true }),
1363
1321
  // Preflight (task 1980) stubbed reachable so --apply DNS tests reach the step-5
1364
1322
  // behavior they assert (the preflight itself is covered by its own test below).
1365
1323
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'example.com' }),
@@ -1499,7 +1457,7 @@ await ta('cmdRunIntents (--apply) claims → provisions → resolves the intent
1499
1457
  claimNextOAuthManifest: async () => null,
1500
1458
  resolveOAuthManifest: async () => {},
1501
1459
  },
1502
- exec: () => ({ ok: true }), writeFile: () => ({ ok: true }), doApi: null,
1460
+ exec: () => ({ ok: true }), writeFile: () => ({ ok: true }),
1503
1461
  };
1504
1462
  const r = await P.cmdRunIntents(deps);
1505
1463
  assert.equal(r.ran, 1);
@@ -1589,10 +1547,8 @@ await ta('placeManifestCreds (--apply): converts, rewrites web.env with the cred
1589
1547
  assert.ok(cmds.some((c) => /\/healthz/.test(c)), 'probes healthz');
1590
1548
  });
1591
1549
 
1592
- await ta('placeManifestCreds rejects a dedicated droplet (no post-hoc exec path) and creds-less rows', async () => {
1550
+ await ta('placeManifestCreds rejects a creds-less row', async () => {
1593
1551
  const deps = { apply: true, log: () => {}, exec: () => ({ ok: true }), writeFile: () => ({}) };
1594
- const ded = await P.placeManifestCreds({ ...coTenant, hosting_shape: 'dedicated', domain: 'd.example.com' }, { github_code: 'C' }, deps);
1595
- assert.equal(ded.ok, false); assert.match(ded.error, /dedicated/);
1596
1552
  const noCode = await P.placeManifestCreds({ ...coTenant, domain: 'm.example.com' }, {}, deps);
1597
1553
  assert.equal(noCode.ok, false); assert.match(noCode.error, /no github_code/);
1598
1554
  });
@@ -1690,9 +1646,9 @@ await ta('a PRE-conversion failure stays retryable — the narrowing spared the
1690
1646
  apply: true, privileged: false, log: () => {}, sleep: async () => {},
1691
1647
  db: {}, exec: () => ({ ok: true, stdout: '' }), writeFile: () => ({ ok: true }),
1692
1648
  provisioning: {
1693
- claimNextOAuthManifest: async () => (claims++ === 0 ? { id: 22, instance_id: 1, github_code: 'C', attempts: 1 } : null),
1694
- // dedicated shape → placeManifestCreds refuses BEFORE converting (codeSpent absent)
1695
- getInstanceById: async () => ({ ...coTenant, hosting_shape: 'dedicated', domain: 'd.example.com' }),
1649
+ // no github_code → placeManifestCreds refuses BEFORE converting (codeSpent absent)
1650
+ claimNextOAuthManifest: async () => (claims++ === 0 ? { id: 22, instance_id: 1, github_code: null, attempts: 1 } : null),
1651
+ getInstanceById: async () => ({ ...coTenant, domain: 'd.example.com' }),
1696
1652
  resolveOAuthManifest: async (_db, _id, status, patch = {}) => { resolves.push({ status, patch }); },
1697
1653
  recordEvent: async () => {},
1698
1654
  },
@@ -1772,7 +1728,6 @@ function privRecorder({ apply = false } = {}) {
1772
1728
  provisioning: { setInstanceStatus: async () => {}, recordEvent: async () => {} },
1773
1729
  exec: (cmd) => { cmds.push(cmd); return { ok: true, stdout: '' }; },
1774
1730
  writeFile: (p, _body, opts) => { writes.push({ p, opts: opts || {} }); return { ok: true }; },
1775
- doApi: null,
1776
1731
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'example.com' }),
1777
1732
  checkCaddyWiring: () => null,
1778
1733
  };
@@ -1822,36 +1777,6 @@ await ta('teardownInstance(privileged): systemctl + rm-under-/etc are sudo-prefi
1822
1777
  assert.ok(idx(/daemon-reload/) < idx(/reset-failed/), 'reset-failed after the reload that forgets the file — reset first and the stopped unit could fail again');
1823
1778
  });
1824
1779
 
1825
- await ta('teardownInstance(dedicated): no systemd steps at all, so no reset-failed either (its own droplet)', async () => {
1826
- const { deps, cmds } = recorder();
1827
- await P.teardownInstance({ ...coTenant, hosting_shape: 'dedicated', droplet_id: 9 }, deps);
1828
- assert.ok(!cmds.some((c) => /reset-failed|daemon-reload|disable --now/.test(c)), cmds.join(' | '));
1829
- });
1830
-
1831
- // F6 (task 1002718): main() builds deps.doApi on first READ, so a caller must only read it
1832
- // on a path that really calls DigitalOcean — a throwing getter proves the others never do.
1833
- function doApiTripwire(deps) {
1834
- Object.defineProperty(deps, 'doApi', { get() { throw new Error('read deps.doApi on a path that makes no DO call'); } });
1835
- return deps;
1836
- }
1837
-
1838
- await ta('teardownInstance(dedicated, no droplet_id) under --apply never reads deps.doApi (F6)', async () => {
1839
- const { deps } = recorder({ apply: true });
1840
- await P.teardownInstance({ ...coTenant, hosting_shape: 'dedicated', droplet_id: null }, doApiTripwire(deps));
1841
- });
1842
-
1843
- await ta('provisionInstance(co-tenant) under --apply never reads deps.doApi (F6)', async () => {
1844
- const { deps } = recorder({ apply: true });
1845
- const r = await P.provisionInstance(coTenant, doApiTripwire(deps));
1846
- assert.ok(!/deps\.doApi/.test(String(r && r.error)), String(r && r.error));
1847
- });
1848
-
1849
- t('main() constructs the DO client lazily — no DO_API_TOKEN needed until a DO call (F6)', () => {
1850
- const src = readFileSync(new URL('../scripts/gds/provision.js', import.meta.url), 'utf8');
1851
- assert.match(src, /get doApi\(\)/, 'deps.doApi is a getter');
1852
- assert.ok(!/doApi:\s*DoApi \? new DoApi/.test(src), 'no eager construction at deps build');
1853
- });
1854
-
1855
1780
  await ta('teardownInstance(default): NO sudo (bare, unchanged)', async () => {
1856
1781
  const { deps, cmds } = recorder();
1857
1782
  await P.teardownInstance(coTenant, deps);
@@ -1914,7 +1839,6 @@ await ta('provisionInstance(co-tenant, remote): box steps use the box `exec`, bu
1914
1839
  controlExec: (cmd) => { control.push(cmd); return { ok: true, stdout: '' }; },
1915
1840
  writeFile: () => ({ ok: true }),
1916
1841
  controlWriteFile: () => ({ ok: true }),
1917
- doApi: null,
1918
1842
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'example.com' }),
1919
1843
  checkCaddyWiring: () => null,
1920
1844
  };
@@ -1946,7 +1870,6 @@ await ta('provisionInstance(standalone, remote): EVERY box step runs control-pla
1946
1870
  controlExec: (cmd, opts) => { control.push(cmd); if (opts && opts.env) dnsEnvs.push({ cmd, env: opts.env }); return { ok: true, stdout: '' }; },
1947
1871
  writeFile: (p) => { boxWrites.push(p); return { ok: true }; }, // the REMOTE writer
1948
1872
  controlWriteFile: (p) => { controlWrites.push(p); return { ok: true }; }, // the control-plane writer
1949
- doApi: null,
1950
1873
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'cloudbongos.com' }),
1951
1874
  checkCaddyWiring: () => null,
1952
1875
  };
@@ -1986,7 +1909,7 @@ await ta('provisionInstance(standalone, remote, --apply): FAILS LOUD when the co
1986
1909
  db: { query: async () => ({ rows: [] }) },
1987
1910
  provisioning: { setInstanceStatus: async () => {}, recordEvent: async () => {} },
1988
1911
  exec: () => ({ ok: true, stdout: '' }), controlExec: () => ({ ok: true, stdout: '' }),
1989
- writeFile: () => ({ ok: true }), controlWriteFile: () => ({ ok: true }), doApi: null,
1912
+ writeFile: () => ({ ok: true }), controlWriteFile: () => ({ ok: true }),
1990
1913
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'cloudbongos.com' }),
1991
1914
  checkCaddyWiring: () => null,
1992
1915
  };
@@ -2006,7 +1929,7 @@ await ta('teardownInstance(standalone, remote): tears down on the CONTROL PLANE
2006
1929
  provisioning: { setInstanceStatus: async () => {}, recordEvent: async () => {} },
2007
1930
  exec: (cmd) => { box.push(cmd); return { ok: true }; },
2008
1931
  controlExec: (cmd) => { control.push(cmd); return { ok: true }; },
2009
- writeFile: () => ({ ok: true }), controlWriteFile: () => ({ ok: true }), doApi: null,
1932
+ writeFile: () => ({ ok: true }), controlWriteFile: () => ({ ok: true }),
2010
1933
  };
2011
1934
  await P.teardownInstance({ ...coTenant, hosting_shape: 'cloud-host' }, deps);
2012
1935
  assert.ok(control.some((c) => /systemctl disable --now mercury/.test(c)), 'disable runs on the control plane');
@@ -2231,7 +2154,6 @@ function attachRecorder({ apply = false, envBody = WEB_ENV_ON_BOX } = {}) {
2231
2154
  return { ok: true, stdout: '' };
2232
2155
  },
2233
2156
  writeFile: (p, body) => { writes.push({ path: p, body }); return { ok: true }; },
2234
- doApi: null,
2235
2157
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'cloudbongos.com' }),
2236
2158
  checkCaddyWiring: () => null,
2237
2159
  };
@@ -2441,14 +2363,6 @@ await ta('domainAttachInstance: instance no longer active → clean no-op (provi
2441
2363
  }
2442
2364
  });
2443
2365
 
2444
- await ta('domainAttachInstance: dedicated is not automated — ok:false with guidance, box untouched', async () => {
2445
- const { deps, cmds } = attachRecorder();
2446
- const r = await P.domainAttachInstance({ ...activeStandalone, hosting_shape: 'dedicated' }, deps);
2447
- assert.equal(r.ok, false);
2448
- assert.match(r.error, /dedicated/);
2449
- assert.equal(cmds.length, 0);
2450
- });
2451
-
2452
2366
  await ta('domainAttachInstance(--apply): a DNS preflight failure returns ok:false — never THROWS (a throw would flip the ACTIVE instance to error in the drain loop)', async () => {
2453
2367
  const savedHook = P.CONFIG.dnsHook; P.CONFIG.dnsHook = '/opt/infra/box-dns-cloudflare.sh';
2454
2368
  try {
@@ -2478,7 +2392,7 @@ await ta('cmdRunIntents (--apply) routes a domain-attach intent to the attach le
2478
2392
  // the attach leg patches web.env IN PLACE, so a `cat` must return a real file
2479
2393
  // — an empty one is a deliberate refusal (task 1003237)
2480
2394
  exec: (cmd) => ({ ok: true, stdout: /\bcat\b.*web\.env/.test(String(cmd)) ? 'PORT=3010\n' : '' }),
2481
- writeFile: () => ({ ok: true }), doApi: null,
2395
+ writeFile: () => ({ ok: true }),
2482
2396
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'cloudbongos.com' }),
2483
2397
  checkCaddyWiring: () => null,
2484
2398
  };
@@ -2503,7 +2417,7 @@ await ta('cmdRunIntents (--apply): an UNKNOWN intent action never falls through
2503
2417
  resolveOAuthManifest: async () => {},
2504
2418
  },
2505
2419
  exec: (c) => { cmds.push(c); return { ok: true }; },
2506
- writeFile: () => ({ ok: true }), doApi: null,
2420
+ writeFile: () => ({ ok: true }),
2507
2421
  };
2508
2422
  const r = await P.cmdRunIntents(deps);
2509
2423
  assert.equal(r.errors, 1, 'surfaced as an error, not silently executed');
@@ -2541,7 +2455,6 @@ function truthRecorder({ healthzFails = false } = {}) {
2541
2455
  return { ok: true, stdout: '' };
2542
2456
  },
2543
2457
  writeFile: () => ({ ok: true }),
2544
- doApi: null,
2545
2458
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'cloudbongos.com' }),
2546
2459
  checkCaddyWiring: () => null,
2547
2460
  getGithubToken: async () => null,
@@ -2615,7 +2528,7 @@ await ta('F19: a RETIRED intent records its reason on the instance without chang
2615
2528
  recordEvent: async () => {},
2616
2529
  claimNextOAuthManifest: async () => null, resolveOAuthManifest: async () => {},
2617
2530
  },
2618
- exec: () => ({ ok: true }), writeFile: () => ({ ok: true }), doApi: null,
2531
+ exec: () => ({ ok: true }), writeFile: () => ({ ok: true }),
2619
2532
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'z' }),
2620
2533
  checkCaddyWiring: () => null,
2621
2534
  };
@@ -2641,7 +2554,7 @@ await ta('F19: a NON-final failure re-pends the intent and writes nothing on the
2641
2554
  recordEvent: async () => {},
2642
2555
  claimNextOAuthManifest: async () => null, resolveOAuthManifest: async () => {},
2643
2556
  },
2644
- exec: () => ({ ok: true }), writeFile: () => ({ ok: true }), doApi: null,
2557
+ exec: () => ({ ok: true }), writeFile: () => ({ ok: true }),
2645
2558
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'z' }),
2646
2559
  checkCaddyWiring: () => null,
2647
2560
  };
@@ -3114,10 +3027,10 @@ t('dbRoleGrantsCmd: runs on the INSTANCE db and grants forward too — the migra
3114
3027
  assert.match(c, /GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO %I/);
3115
3028
  });
3116
3029
 
3117
- t('BOTH role commands render with NO double quote — they have to survive a YAML double-quoted cloud-init scalar', () => {
3030
+ t('the role + seed commands render with NO double quote — they must survive `bash -s` over SSH unchanged', () => {
3118
3031
  const dq = String.fromCharCode(34);
3119
- for (const c of [P.dbRoleCmd(coTenant, { password: 'pw_ABC-123' }), P.dbRoleGrantsCmd(coTenant)]) {
3120
- assert.ok(!c.includes(dq), `a double-quoted identifier silently truncates the cloud-init line: ${c}`);
3032
+ for (const c of [P.dbRoleCmd(coTenant, { password: 'pw_ABC-123' }), P.dbRoleGrantsCmd(coTenant), P.seedFirstVersionCmd(coTenant)]) {
3033
+ assert.ok(!c.includes(dq), `a double-quoted identifier would need escaping on the remote shell: ${c}`);
3121
3034
  }
3122
3035
  });
3123
3036
 
@@ -3184,38 +3097,6 @@ t('webEnvBody: a CO-LOCATED instance (co-tenant or standalone) carries PGPOOL_MA
3184
3097
  assert.match(withCred, /^PGUSER=bongos-mercury$/m);
3185
3098
  });
3186
3099
 
3187
- t('webEnvBody: a DEDICATED droplet has its own Postgres — no PGPOOL_MAX line, pg keeps its default', () => {
3188
- const b = P.webEnvBody({ ...coTenant, hosting_shape: 'dedicated' });
3189
- assert.doesNotMatch(b, /^PGPOOL_MAX=/m);
3190
- assert.match(b, /^PGDATABASE=mercury$/m);
3191
- });
3192
-
3193
- t('dedicatedUserData: the droplet runs the SAME account + role steps, in the same order around the migrate', () => {
3194
- const ud = P.dedicatedUserData(coTenant);
3195
- const at = (needle) => ud.indexOf(needle);
3196
- assert.ok(at('useradd --system') > -1, 'the droplet creates the account too');
3197
- assert.ok(at('usermod -aG $(id -gn appsvc)') > -1);
3198
- assert.ok(at('useradd --system') < at('createdb mercury'), 'account before the DB');
3199
- assert.ok(at('migrate.sh') < at('CREATE ROLE %I'), 'the role grants must follow the migrate that created the tables');
3200
- assert.ok(at('CREATE ROLE %I') < at('GRANT ALL ON ALL TABLES'), 'role before its grants');
3201
- });
3202
-
3203
- t('dedicatedUserData: NEVER bakes a password into cloud-init — DO retains user-data and serves it back', () => {
3204
- const ud = P.dedicatedUserData(coTenant);
3205
- // The dollar-quoted password literal dbRoleCmd uses. Its absence is the assertion.
3206
- assert.ok(!ud.includes('$p$'), 'a credential in user-data is a permanent copy we cannot lock down');
3207
- assert.match(ud, /CREATE ROLE %I WITH LOGIN\$f\$/, 'the role is still created, password-less (single-tenant droplet)');
3208
- assert.match(ud, /REVOKE CONNECT ON DATABASE %I FROM PUBLIC/, 'and PUBLIC still loses CONNECT');
3209
- });
3210
-
3211
- t('dbRoleCmd(peerOnly): omits the PASSWORD clause entirely, and REFUSES a password', () => {
3212
- const c = P.dbRoleCmd(coTenant, { peerOnly: true });
3213
- assert.ok(!/PASSWORD/.test(c), 'no PASSWORD clause at all — not an empty one');
3214
- assert.match(c, /CREATE ROLE %I WITH LOGIN\$f\$/);
3215
- assert.match(c, /ALTER DATABASE %I OWNER TO %I/, 'ownership and the revoke are unchanged');
3216
- assert.throws(() => P.dbRoleCmd(coTenant, { peerOnly: true, password: 'pw_ABC' }), /peerOnly takes no password/);
3217
- });
3218
-
3219
3100
  t('dbRoleCmdShown: the label the runner logs names every effect and carries NO password', () => {
3220
3101
  const pw = P.generateDbPassword();
3221
3102
  const real = P.dbRoleCmd(coTenant, { password: pw });
@@ -68,13 +68,11 @@ test('accountPlaneGap: a SILENT failure still names a cause — an empty stderr
68
68
  assert.match(gap, /failed \(Command failed: sh -c\)/, 'falls through the empty Buffer to the message');
69
69
  });
70
70
 
71
- test('accountPreflight: a dedicated droplet skips it, and a dry run asks the box nothing', () => {
71
+ test('accountPreflight: a dry run asks the box nothing', () => {
72
72
  const cmds = [];
73
73
  const rec = (c) => { cmds.push(c); return isRoot(); };
74
- assert.equal(accountPreflight({ exec: rec, apply: true, log: () => {}, shape: 'dedicated' }), null);
75
- assert.deepEqual(cmds, [], 'cloud-init creates that account as root — nothing to ask');
76
74
  const lines = [];
77
- assert.equal(accountPreflight({ exec: rec, apply: false, log: (m) => lines.push(m), shape: 'co-tenant' }), null);
75
+ assert.equal(accountPreflight({ exec: rec, apply: false, log: (m) => lines.push(m) }), null);
78
76
  assert.deepEqual(cmds, [], 'a dry run changes nothing and asks nothing');
79
77
  assert.match(lines.join('\n'), /would probe/, 'the plan says the probe is coming, rather than printing step 1c as though it works');
80
78
  });
@@ -100,7 +98,6 @@ function harness({ noRoot = false } = {}) {
100
98
  },
101
99
  exec,
102
100
  writeFile: (p) => { writes.push(p); return { ok: true }; },
103
- doApi: null,
104
101
  checkDnsTokenScope: async () => ({ reachable: true, zone: 'example.com' }),
105
102
  checkCaddyWiring: () => null,
106
103
  getGithubToken: async () => null,
@@ -14,7 +14,7 @@
14
14
  // erase and the catalog forget succeeded, so a failure leaves a row the runner can retry
15
15
  // • the dump erase matches the nightly filename EXACTLY, so `test` never erases `test-nk`
16
16
  // • each shape erases where its data lives (cloud-host: control plane; co-tenant: the
17
- // co-hosting box; dedicated: nothing — its droplet went whole)
17
+ // co-hosting box)
18
18
  // • a dry run erases nothing and deletes nothing; an invalid slug is refused before any command
19
19
  //
20
20
  // Hermetic: recorded executors, a fake db, a fake catalog port. No shell, no Postgres.
@@ -69,7 +69,6 @@ function rig({ apply = true, privileged = false, failOn = null, catalogThrows =
69
69
  },
70
70
  exec: record('box'), controlExec: record('control'),
71
71
  writeFile: () => ({ ok: true }), controlWriteFile: () => ({ ok: true }),
72
- doApi: { deleteDroplet: async (id) => { events.push({ where: 'do', cmd: `delete-droplet ${id}` }); } },
73
72
  projectCatalog: catalog ? {
74
73
  forgetOwnedProject: async (target, opts) => {
75
74
  events.push({ where: 'catalog', cmd: 'forget', target, pool: opts && opts.pool });
@@ -137,14 +136,6 @@ await ta('co-tenant: the erase runs on the co-hosting box, there is no per-proje
137
136
  assert.ok(!r.cmds('control').some((x) => /dropdb/.test(x)));
138
137
  });
139
138
 
140
- await ta('dedicated: its droplet went whole, so nothing is erased by command — the catalog and the row still go', async () => {
141
- const r = rig();
142
- const res = await D.disconnectInstance({ ...lantern, hosting_shape: 'dedicated', droplet_id: 9 }, r.deps);
143
- assert.equal(res.ok, true);
144
- assert.ok(!r.events.some((e) => /dropdb|rm -rf|userdel|find /.test(e.cmd || '')), r.events.map((e) => e.cmd).join('\n'));
145
- assert.ok(r.at((e) => e.cmd === 'forget') >= 0 && r.at((e) => e.cmd === 'delete-row') >= 0);
146
- });
147
-
148
139
  console.log('\nthe dump erase is exact:');
149
140
 
150
141
  t('the nightly filename matches, and a project whose name merely STARTS with this one\'s does not', () => {
@@ -20,7 +20,7 @@
20
20
  // address), and the event text says which one was actually observed
21
21
  // • a project that stays down is ok:true — a truthful observation for the card,
22
22
  // not a failure to retry four more times
23
- // • the state gate is a clean no-op; dedicated is refused with the command
23
+ // • the state gate is a clean no-op
24
24
  // • cmdRunIntents routes 'restart' to this leg
25
25
  //
26
26
  // Run: node tests/provision_restart.mjs
@@ -64,7 +64,6 @@ function recorder({ apply = true, healthzFails = false, privileged = false, rest
64
64
  },
65
65
  exec,
66
66
  writeFile: writer('box'), controlWriteFile: writer('control'),
67
- doApi: null,
68
67
  };
69
68
  return { deps, cmds, writes, events, probes, cleared, logs };
70
69
  }
@@ -160,14 +159,6 @@ await ta('every non-active state is a clean no-op, not an error — a raced tear
160
159
  }
161
160
  });
162
161
 
163
- await ta('a dedicated droplet is refused with the exact command, and nothing is run', async () => {
164
- const { deps, cmds } = recorder();
165
- const r = await P.restartInstance({ ...activeStandalone, hosting_shape: 'dedicated' }, deps);
166
- assert.equal(r.ok, false);
167
- assert.match(r.error, /systemctl restart spike/);
168
- assert.equal(cmds.length, 0);
169
- });
170
-
171
162
  await ta('dry-run runs no real work and observes nothing', async () => {
172
163
  const { deps, writes } = recorder({ apply: false });
173
164
  const r = await P.restartInstance(activeStandalone, deps);
@@ -212,7 +203,7 @@ await ta("cmdRunIntents (--apply) routes 'restart' to restartInstance and resolv
212
203
  claimNextOAuthManifest: async () => null, resolveOAuthManifest: async () => {},
213
204
  },
214
205
  exec: (cmd) => { cmds.push(cmd); return /healthz/.test(cmd) ? { ok: true, stdout: '{}' } : { ok: true, stdout: '' }; },
215
- writeFile: () => ({ ok: true }), doApi: null,
206
+ writeFile: () => ({ ok: true }),
216
207
  };
217
208
  const r = await P.cmdRunIntents(deps);
218
209
  assert.equal(r.errors, 0, JSON.stringify(r));
@@ -235,7 +226,7 @@ await ta('cmdRunIntents (--apply): a restart that throws re-pends and never mark
235
226
  claimNextOAuthManifest: async () => null, resolveOAuthManifest: async () => {},
236
227
  },
237
228
  exec: (cmd) => { if (/systemctl restart/.test(cmd)) throw new Error('Command failed: sudo systemctl restart spike'); return { ok: true, stdout: '' }; },
238
- writeFile: () => ({ ok: true }), doApi: null,
229
+ writeFile: () => ({ ok: true }),
239
230
  };
240
231
  const r = await P.cmdRunIntents(deps);
241
232
  assert.equal(r.errors, 1);
@@ -15,7 +15,7 @@
15
15
  // the intent and never flips a healthy ACTIVE instance to 'error' (ADR 0190)
16
16
  // • the verify asks the instance's own manifest whether it READ the values, and
17
17
  // records only what it earned (true / false / unknown)
18
- // • the state gate is a clean no-op; dedicated is refused with guidance
18
+ // • the state gate is a clean no-op
19
19
  // • cmdRunIntents routes 'settings-apply' to this leg
20
20
  //
21
21
  // Run: node tests/provision_settings_apply.mjs
@@ -193,7 +193,6 @@ function recorder({ apply = false, envBody = LIVE_ENV, readFails = false, health
193
193
  // a standalone must land on the CONTROL-PLANE writer (task 2074 routing) —
194
194
  // both writers record, tagged, so the choice is asserted, not assumed
195
195
  writeFile: writer('box'), controlWriteFile: writer('control'),
196
- doApi: null,
197
196
  };
198
197
  return { deps, cmds, writes, events, probes, cleared, logs };
199
198
  }
@@ -304,17 +303,6 @@ await ta('the state gate: any non-active status is a clean no-op — ok:true noo
304
303
  }
305
304
  });
306
305
 
307
- await ta('the shape refusal: dedicated → ok:false with guidance naming the values + file; box untouched', async () => {
308
- const { deps, cmds, writes } = recorder({ apply: true });
309
- const r = await P.settingsApplyInstance({ ...activeStandalone, hosting_shape: 'dedicated' }, deps);
310
- assert.equal(r.ok, false);
311
- assert.match(r.error, /dedicated/);
312
- assert.match(r.error, new RegExp(`${NEUTRAL_PREFIX}_PLATFORM_VISIBILITY=gated`), 'the operator is told exactly what to set');
313
- assert.match(r.error, /\/etc\/spike\/web\.env/);
314
- assert.equal(cmds.length, 0);
315
- assert.equal(writes.length, 0);
316
- });
317
-
318
306
  console.log('\nthe control plane\'s own row — the platform pushes a setting to itself (task 1004334):');
319
307
 
320
308
  const U = require('../scripts/gds/provision-units.js');
@@ -505,7 +493,7 @@ await ta("cmdRunIntents (--apply) routes a 'settings-apply' intent to the leg, w
505
493
  resolveOAuthManifest: async () => {},
506
494
  },
507
495
  exec: (cmd) => { cmds.push(cmd); return /\bcat /.test(cmd) ? { ok: true, stdout: LIVE_ENV } : /instance/.test(cmd) ? { ok: true, stdout: manifestWith({ platformVisibility: 'gated', joinability: 'open', visibility: 'public' }) } : { ok: true, stdout: '{"ok":true}' }; },
508
- writeFile: (p, body) => { writes.push(body); return { ok: true }; }, doApi: null,
496
+ writeFile: (p, body) => { writes.push(body); return { ok: true }; },
509
497
  };
510
498
  const r = await P.cmdRunIntents(deps);
511
499
  assert.equal(r.ran, 1);
@@ -533,7 +521,7 @@ await ta('cmdRunIntents (--apply): a FAILED restart on attempt 1 re-pends the in
533
521
  if (/systemctl restart/.test(cmd)) throw new Error('Command failed: sudo systemctl restart spike');
534
522
  return { ok: true, stdout: '' };
535
523
  },
536
- writeFile: () => ({ ok: true }), doApi: null,
524
+ writeFile: () => ({ ok: true }),
537
525
  };
538
526
  const r = await P.cmdRunIntents(deps);
539
527
  assert.equal(r.errors, 1);
@@ -544,27 +532,27 @@ await ta('cmdRunIntents (--apply): a FAILED restart on attempt 1 re-pends the in
544
532
  assert.equal(statusWrites.length, 0, 'a healthy ACTIVE instance is never marked broken over a settings push');
545
533
  });
546
534
 
547
- await ta('cmdRunIntents (--apply): a dedicated refusal RETIRES at the cap with the reason on the instance and NO status change', async () => {
535
+ await ta('cmdRunIntents (--apply): a refused push (no web.env to patch) RETIRES at the cap with the reason on the instance and NO status change', async () => {
548
536
  let claims = 0; const resolved = []; const statusWrites = [];
549
537
  const deps = {
550
538
  apply: true, log: () => {}, sleep: async () => {},
551
539
  db: { query: async () => ({ rows: [] }) },
552
540
  provisioning: {
553
541
  claimNextIntent: async () => (claims++ === 0 ? { id: 13, instance_id: 18, action: 'settings-apply', attempts: P.MAX_INTENT_ATTEMPTS } : null),
554
- getInstanceById: async () => ({ ...activeStandalone, hosting_shape: 'dedicated' }),
542
+ getInstanceById: async () => activeStandalone, // exec reads back nothing → "cannot read web.env" refusal
555
543
  resolveIntent: async (_db, id, state, err) => { resolved.push({ id, state, err }); },
556
544
  setInstanceStatus: async (_db, _id, s, patch) => { statusWrites.push({ s, patch }); },
557
545
  recordEvent: async () => {},
558
546
  claimNextOAuthManifest: async () => null, resolveOAuthManifest: async () => {},
559
547
  },
560
- exec: () => ({ ok: true }), writeFile: () => ({ ok: true }), doApi: null,
548
+ exec: () => ({ ok: true }), writeFile: () => ({ ok: true }),
561
549
  };
562
550
  const r = await P.cmdRunIntents(deps);
563
551
  assert.equal(r.errors, 1);
564
552
  assert.equal(resolved[0].state, 'error');
565
553
  assert.equal(statusWrites.length, 1);
566
554
  assert.equal(statusWrites[0].s, 'active', 'a healthy instance is never marked broken over a refused push');
567
- assert.match(statusWrites[0].patch.error_note, /dedicated/);
555
+ assert.match(statusWrites[0].patch.error_note, /cannot read/);
568
556
  });
569
557
 
570
558
  console.log('\nrenamedEnvCarry — the prelaunch password carried on the box (task 1004395):');
@@ -51,7 +51,6 @@ function rig({ apply = true, privileged = false, hookThrows = false } = {}) {
51
51
  return { ok: true, stdout: '' };
52
52
  },
53
53
  writeFile: () => ({ ok: true }), controlWriteFile: () => ({ ok: true }),
54
- doApi: { deleteDroplet: async (id) => { events.push({ where: 'do', cmd: `delete ${id}` }); } },
55
54
  };
56
55
  const on = (where) => events.filter((e) => e.where === where).map((e) => e.cmd);
57
56
  const hookCalls = () => events.filter((e) => e.cmd === HOOK);
@@ -98,14 +97,6 @@ await ta('privileged: the rm under /etc and the reload are sudo-prefixed', async
98
97
  });
99
98
  });
100
99
 
101
- await ta('dedicated: no Caddy steps — the droplet (and its Caddy) is deleted whole', async () => {
102
- await withHook(HOOK, async () => {
103
- const r = rig();
104
- await P.teardownInstance({ ...lantern, hosting_shape: 'dedicated', droplet_id: 9 }, r.deps);
105
- assert.ok(!r.events.some((e) => /caddy/.test(e.cmd || '')), r.events.map((e) => e.cmd).join(' | '));
106
- });
107
- });
108
-
109
100
  console.log('\nthe DNS leg:');
110
101
 
111
102
  await ta('the hostname is parked at the blackhole through the release env, from the control plane, before the row reads torn_down', async () => {
@@ -121,15 +112,6 @@ await ta('the hostname is parked at the blackhole through the release env, from
121
112
  });
122
113
  });
123
114
 
124
- await ta('dedicated: its hostname is parked too — the droplet IP it pointed at is gone', async () => {
125
- await withHook(HOOK, async () => {
126
- const r = rig();
127
- await P.teardownInstance({ ...lantern, hosting_shape: 'dedicated', droplet_id: 9 }, r.deps);
128
- assert.equal(r.hookCalls().length, 1);
129
- assert.equal(r.hookCalls()[0].where, 'control');
130
- });
131
- });
132
-
133
115
  await ta('best-effort: a hook that throws is logged and the row still reaches torn_down', async () => {
134
116
  await withHook(HOOK, async () => {
135
117
  const r = rig({ hookThrows: true });
@@ -218,7 +200,7 @@ await ta('the row keeps its domain and port, and a revive re-UPSERTs the SAME ho
218
200
  exec: () => ({ ok: true, stdout: '' }),
219
201
  controlExec: (cmd, opts) => { if (cmd === HOOK) dns.push(opts.env); return { ok: true, stdout: '' }; },
220
202
  writeFile: () => ({ ok: true }), controlWriteFile: (p) => { writes.push(p); return { ok: true }; },
221
- doApi: null, checkDnsTokenScope: async () => ({ reachable: true, zone: 'cloudbongos.com' }),
203
+ checkDnsTokenScope: async () => ({ reachable: true, zone: 'cloudbongos.com' }),
222
204
  });
223
205
  assert.ok(dns.some((env) => env.BOX_HOSTNAME === 'lantern.cloudbongos.com' && env.BOX_IP === '198.51.100.20'), JSON.stringify(dns));
224
206
  assert.ok(writes.some((p) => p.endsWith('/lantern.caddy')), writes.join(' | '));