@pleri/olam-cli 0.1.70 → 0.1.72

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.
Files changed (241) hide show
  1. package/dist/commands/create.d.ts.map +1 -1
  2. package/dist/commands/create.js +2 -0
  3. package/dist/commands/create.js.map +1 -1
  4. package/dist/commands/runbooks.d.ts +13 -0
  5. package/dist/commands/runbooks.d.ts.map +1 -0
  6. package/dist/commands/runbooks.js +189 -0
  7. package/dist/commands/runbooks.js.map +1 -0
  8. package/dist/commands/world-snapshot.d.ts +1 -0
  9. package/dist/commands/world-snapshot.d.ts.map +1 -1
  10. package/dist/commands/world-snapshot.js +126 -1
  11. package/dist/commands/world-snapshot.js.map +1 -1
  12. package/dist/commands/worldspec/compile.d.ts +20 -0
  13. package/dist/commands/worldspec/compile.d.ts.map +1 -0
  14. package/dist/commands/worldspec/compile.js +130 -0
  15. package/dist/commands/worldspec/compile.js.map +1 -0
  16. package/dist/commands/worldspec/index.d.ts +12 -0
  17. package/dist/commands/worldspec/index.d.ts.map +1 -0
  18. package/dist/commands/worldspec/index.js +23 -0
  19. package/dist/commands/worldspec/index.js.map +1 -0
  20. package/dist/commands/worldspec/init.d.ts +15 -0
  21. package/dist/commands/worldspec/init.d.ts.map +1 -0
  22. package/dist/commands/worldspec/init.js +166 -0
  23. package/dist/commands/worldspec/init.js.map +1 -0
  24. package/dist/commands/worldspec/schema.d.ts +11 -0
  25. package/dist/commands/worldspec/schema.d.ts.map +1 -0
  26. package/dist/commands/worldspec/schema.js +55 -0
  27. package/dist/commands/worldspec/schema.js.map +1 -0
  28. package/dist/commands/worldspec/validate.d.ts +15 -0
  29. package/dist/commands/worldspec/validate.d.ts.map +1 -0
  30. package/dist/commands/worldspec/validate.js +66 -0
  31. package/dist/commands/worldspec/validate.js.map +1 -0
  32. package/dist/exit-codes.d.ts +32 -0
  33. package/dist/exit-codes.d.ts.map +1 -1
  34. package/dist/exit-codes.js +32 -0
  35. package/dist/exit-codes.js.map +1 -1
  36. package/dist/image-digests.json +5 -5
  37. package/dist/index.js +4379 -897
  38. package/dist/index.js.map +1 -1
  39. package/dist/mcp-server.js +1252 -286
  40. package/host-cp/src/global-config-source.mjs +71 -0
  41. package/host-cp/src/listening-server-poller.mjs +1 -1
  42. package/host-cp/src/plan-orchestrator.mjs +20 -1
  43. package/host-cp/src/port-bridge-manager.mjs +1 -1
  44. package/host-cp/src/server.mjs +46 -7
  45. package/package.json +4 -2
  46. package/dist/__tests__/audit-publish-deps-contract.test.d.ts +0 -26
  47. package/dist/__tests__/audit-publish-deps-contract.test.d.ts.map +0 -1
  48. package/dist/__tests__/audit-publish-deps-contract.test.js +0 -86
  49. package/dist/__tests__/audit-publish-deps-contract.test.js.map +0 -1
  50. package/dist/__tests__/auth-status.test.d.ts +0 -2
  51. package/dist/__tests__/auth-status.test.d.ts.map +0 -1
  52. package/dist/__tests__/auth-status.test.js +0 -291
  53. package/dist/__tests__/auth-status.test.js.map +0 -1
  54. package/dist/__tests__/auth-upgrade.test.d.ts +0 -9
  55. package/dist/__tests__/auth-upgrade.test.d.ts.map +0 -1
  56. package/dist/__tests__/auth-upgrade.test.js +0 -397
  57. package/dist/__tests__/auth-upgrade.test.js.map +0 -1
  58. package/dist/__tests__/bootstrap-tag-mcp-auth.test.d.ts +0 -22
  59. package/dist/__tests__/bootstrap-tag-mcp-auth.test.d.ts.map +0 -1
  60. package/dist/__tests__/bootstrap-tag-mcp-auth.test.js +0 -63
  61. package/dist/__tests__/bootstrap-tag-mcp-auth.test.js.map +0 -1
  62. package/dist/__tests__/cli-mcp-revoke.test.d.ts +0 -8
  63. package/dist/__tests__/cli-mcp-revoke.test.d.ts.map +0 -1
  64. package/dist/__tests__/cli-mcp-revoke.test.js +0 -124
  65. package/dist/__tests__/cli-mcp-revoke.test.js.map +0 -1
  66. package/dist/__tests__/config.test.d.ts +0 -2
  67. package/dist/__tests__/config.test.d.ts.map +0 -1
  68. package/dist/__tests__/config.test.js +0 -95
  69. package/dist/__tests__/config.test.js.map +0 -1
  70. package/dist/__tests__/create-app-urls.test.d.ts +0 -2
  71. package/dist/__tests__/create-app-urls.test.d.ts.map +0 -1
  72. package/dist/__tests__/create-app-urls.test.js +0 -102
  73. package/dist/__tests__/create-app-urls.test.js.map +0 -1
  74. package/dist/__tests__/docker-host.test.d.ts +0 -14
  75. package/dist/__tests__/docker-host.test.d.ts.map +0 -1
  76. package/dist/__tests__/docker-host.test.js +0 -109
  77. package/dist/__tests__/docker-host.test.js.map +0 -1
  78. package/dist/__tests__/enter.test.d.ts +0 -2
  79. package/dist/__tests__/enter.test.d.ts.map +0 -1
  80. package/dist/__tests__/enter.test.js +0 -90
  81. package/dist/__tests__/enter.test.js.map +0 -1
  82. package/dist/__tests__/help-output.test.d.ts +0 -2
  83. package/dist/__tests__/help-output.test.d.ts.map +0 -1
  84. package/dist/__tests__/help-output.test.js +0 -74
  85. package/dist/__tests__/help-output.test.js.map +0 -1
  86. package/dist/__tests__/host-cp-gh-token.test.d.ts +0 -9
  87. package/dist/__tests__/host-cp-gh-token.test.d.ts.map +0 -1
  88. package/dist/__tests__/host-cp-gh-token.test.js +0 -129
  89. package/dist/__tests__/host-cp-gh-token.test.js.map +0 -1
  90. package/dist/__tests__/host-cp.test.d.ts +0 -9
  91. package/dist/__tests__/host-cp.test.d.ts.map +0 -1
  92. package/dist/__tests__/host-cp.test.js +0 -335
  93. package/dist/__tests__/host-cp.test.js.map +0 -1
  94. package/dist/__tests__/image-presence.test.d.ts +0 -2
  95. package/dist/__tests__/image-presence.test.d.ts.map +0 -1
  96. package/dist/__tests__/image-presence.test.js +0 -44
  97. package/dist/__tests__/image-presence.test.js.map +0 -1
  98. package/dist/__tests__/install-root.test.d.ts +0 -2
  99. package/dist/__tests__/install-root.test.d.ts.map +0 -1
  100. package/dist/__tests__/install-root.test.js +0 -119
  101. package/dist/__tests__/install-root.test.js.map +0 -1
  102. package/dist/__tests__/keys.test.d.ts +0 -9
  103. package/dist/__tests__/keys.test.d.ts.map +0 -1
  104. package/dist/__tests__/keys.test.js +0 -145
  105. package/dist/__tests__/keys.test.js.map +0 -1
  106. package/dist/__tests__/logs.test.d.ts +0 -9
  107. package/dist/__tests__/logs.test.d.ts.map +0 -1
  108. package/dist/__tests__/logs.test.js +0 -124
  109. package/dist/__tests__/logs.test.js.map +0 -1
  110. package/dist/__tests__/mcp-import.test.d.ts +0 -11
  111. package/dist/__tests__/mcp-import.test.d.ts.map +0 -1
  112. package/dist/__tests__/mcp-import.test.js +0 -134
  113. package/dist/__tests__/mcp-import.test.js.map +0 -1
  114. package/dist/__tests__/protocol-version.test.d.ts +0 -2
  115. package/dist/__tests__/protocol-version.test.d.ts.map +0 -1
  116. package/dist/__tests__/protocol-version.test.js +0 -170
  117. package/dist/__tests__/protocol-version.test.js.map +0 -1
  118. package/dist/__tests__/ps.test.d.ts +0 -2
  119. package/dist/__tests__/ps.test.d.ts.map +0 -1
  120. package/dist/__tests__/ps.test.js +0 -172
  121. package/dist/__tests__/ps.test.js.map +0 -1
  122. package/dist/__tests__/registry-allowlist.test.d.ts +0 -2
  123. package/dist/__tests__/registry-allowlist.test.d.ts.map +0 -1
  124. package/dist/__tests__/registry-allowlist.test.js +0 -129
  125. package/dist/__tests__/registry-allowlist.test.js.map +0 -1
  126. package/dist/__tests__/services.test.d.ts +0 -8
  127. package/dist/__tests__/services.test.d.ts.map +0 -1
  128. package/dist/__tests__/services.test.js +0 -185
  129. package/dist/__tests__/services.test.js.map +0 -1
  130. package/dist/__tests__/status-app-urls.test.d.ts +0 -2
  131. package/dist/__tests__/status-app-urls.test.d.ts.map +0 -1
  132. package/dist/__tests__/status-app-urls.test.js +0 -125
  133. package/dist/__tests__/status-app-urls.test.js.map +0 -1
  134. package/dist/__tests__/upgrade-gh-token-contract.test.d.ts +0 -19
  135. package/dist/__tests__/upgrade-gh-token-contract.test.d.ts.map +0 -1
  136. package/dist/__tests__/upgrade-gh-token-contract.test.js +0 -63
  137. package/dist/__tests__/upgrade-gh-token-contract.test.js.map +0 -1
  138. package/dist/__tests__/upgrade.test.d.ts +0 -9
  139. package/dist/__tests__/upgrade.test.d.ts.map +0 -1
  140. package/dist/__tests__/upgrade.test.js +0 -586
  141. package/dist/__tests__/upgrade.test.js.map +0 -1
  142. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts +0 -6
  143. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts.map +0 -1
  144. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js +0 -26
  145. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js.map +0 -1
  146. package/dist/commands/__tests__/begin.test.d.ts +0 -7
  147. package/dist/commands/__tests__/begin.test.d.ts.map +0 -1
  148. package/dist/commands/__tests__/begin.test.js +0 -72
  149. package/dist/commands/__tests__/begin.test.js.map +0 -1
  150. package/dist/commands/__tests__/bootstrap.test.d.ts +0 -2
  151. package/dist/commands/__tests__/bootstrap.test.d.ts.map +0 -1
  152. package/dist/commands/__tests__/bootstrap.test.js +0 -370
  153. package/dist/commands/__tests__/bootstrap.test.js.map +0 -1
  154. package/dist/commands/__tests__/carry-uncommitted.test.d.ts +0 -14
  155. package/dist/commands/__tests__/carry-uncommitted.test.d.ts.map +0 -1
  156. package/dist/commands/__tests__/carry-uncommitted.test.js +0 -83
  157. package/dist/commands/__tests__/carry-uncommitted.test.js.map +0 -1
  158. package/dist/commands/__tests__/clean.test.d.ts +0 -9
  159. package/dist/commands/__tests__/clean.test.d.ts.map +0 -1
  160. package/dist/commands/__tests__/clean.test.js +0 -105
  161. package/dist/commands/__tests__/clean.test.js.map +0 -1
  162. package/dist/commands/__tests__/crystallize.test.d.ts +0 -2
  163. package/dist/commands/__tests__/crystallize.test.d.ts.map +0 -1
  164. package/dist/commands/__tests__/crystallize.test.js +0 -133
  165. package/dist/commands/__tests__/crystallize.test.js.map +0 -1
  166. package/dist/commands/__tests__/diagnose.test.d.ts +0 -9
  167. package/dist/commands/__tests__/diagnose.test.d.ts.map +0 -1
  168. package/dist/commands/__tests__/diagnose.test.js +0 -108
  169. package/dist/commands/__tests__/diagnose.test.js.map +0 -1
  170. package/dist/commands/__tests__/openHostCpUrl.test.d.ts +0 -2
  171. package/dist/commands/__tests__/openHostCpUrl.test.d.ts.map +0 -1
  172. package/dist/commands/__tests__/openHostCpUrl.test.js +0 -63
  173. package/dist/commands/__tests__/openHostCpUrl.test.js.map +0 -1
  174. package/dist/commands/__tests__/refresh.test.d.ts +0 -13
  175. package/dist/commands/__tests__/refresh.test.d.ts.map +0 -1
  176. package/dist/commands/__tests__/refresh.test.js +0 -170
  177. package/dist/commands/__tests__/refresh.test.js.map +0 -1
  178. package/dist/commands/__tests__/status.test.d.ts +0 -8
  179. package/dist/commands/__tests__/status.test.d.ts.map +0 -1
  180. package/dist/commands/__tests__/status.test.js +0 -62
  181. package/dist/commands/__tests__/status.test.js.map +0 -1
  182. package/dist/commands/__tests__/stop.test.d.ts +0 -5
  183. package/dist/commands/__tests__/stop.test.d.ts.map +0 -1
  184. package/dist/commands/__tests__/stop.test.js +0 -30
  185. package/dist/commands/__tests__/stop.test.js.map +0 -1
  186. package/dist/commands/__tests__/update.test.d.ts +0 -7
  187. package/dist/commands/__tests__/update.test.d.ts.map +0 -1
  188. package/dist/commands/__tests__/update.test.js +0 -224
  189. package/dist/commands/__tests__/update.test.js.map +0 -1
  190. package/dist/commands/__tests__/upgrade.all-three.test.d.ts +0 -19
  191. package/dist/commands/__tests__/upgrade.all-three.test.d.ts.map +0 -1
  192. package/dist/commands/__tests__/upgrade.all-three.test.js +0 -80
  193. package/dist/commands/__tests__/upgrade.all-three.test.js.map +0 -1
  194. package/dist/commands/__tests__/upgrade.compose-path.test.d.ts +0 -20
  195. package/dist/commands/__tests__/upgrade.compose-path.test.d.ts.map +0 -1
  196. package/dist/commands/__tests__/upgrade.compose-path.test.js +0 -140
  197. package/dist/commands/__tests__/upgrade.compose-path.test.js.map +0 -1
  198. package/dist/commands/__tests__/upgrade.history.test.d.ts +0 -15
  199. package/dist/commands/__tests__/upgrade.history.test.d.ts.map +0 -1
  200. package/dist/commands/__tests__/upgrade.history.test.js +0 -199
  201. package/dist/commands/__tests__/upgrade.history.test.js.map +0 -1
  202. package/dist/commands/__tests__/upgrade.lock.test.d.ts +0 -15
  203. package/dist/commands/__tests__/upgrade.lock.test.d.ts.map +0 -1
  204. package/dist/commands/__tests__/upgrade.lock.test.js +0 -253
  205. package/dist/commands/__tests__/upgrade.lock.test.js.map +0 -1
  206. package/dist/commands/__tests__/upgrade.olam-tag.test.d.ts +0 -21
  207. package/dist/commands/__tests__/upgrade.olam-tag.test.d.ts.map +0 -1
  208. package/dist/commands/__tests__/upgrade.olam-tag.test.js +0 -114
  209. package/dist/commands/__tests__/upgrade.olam-tag.test.js.map +0 -1
  210. package/dist/commands/__tests__/upgrade.poll.test.d.ts +0 -14
  211. package/dist/commands/__tests__/upgrade.poll.test.d.ts.map +0 -1
  212. package/dist/commands/__tests__/upgrade.poll.test.js +0 -136
  213. package/dist/commands/__tests__/upgrade.poll.test.js.map +0 -1
  214. package/dist/commands/__tests__/upgrade.recreate.test.d.ts +0 -17
  215. package/dist/commands/__tests__/upgrade.recreate.test.d.ts.map +0 -1
  216. package/dist/commands/__tests__/upgrade.recreate.test.js +0 -83
  217. package/dist/commands/__tests__/upgrade.recreate.test.js.map +0 -1
  218. package/dist/commands/__tests__/upgrade.rollback.test.d.ts +0 -12
  219. package/dist/commands/__tests__/upgrade.rollback.test.d.ts.map +0 -1
  220. package/dist/commands/__tests__/upgrade.rollback.test.js +0 -255
  221. package/dist/commands/__tests__/upgrade.rollback.test.js.map +0 -1
  222. package/dist/commands/__tests__/upgrade.sha-capture.test.d.ts +0 -12
  223. package/dist/commands/__tests__/upgrade.sha-capture.test.d.ts.map +0 -1
  224. package/dist/commands/__tests__/upgrade.sha-capture.test.js +0 -63
  225. package/dist/commands/__tests__/upgrade.sha-capture.test.js.map +0 -1
  226. package/dist/commands/__tests__/upgrade.smoke.test.d.ts +0 -19
  227. package/dist/commands/__tests__/upgrade.smoke.test.d.ts.map +0 -1
  228. package/dist/commands/__tests__/upgrade.smoke.test.js +0 -87
  229. package/dist/commands/__tests__/upgrade.smoke.test.js.map +0 -1
  230. package/dist/commands/__tests__/upgrade.swap.test.d.ts +0 -19
  231. package/dist/commands/__tests__/upgrade.swap.test.d.ts.map +0 -1
  232. package/dist/commands/__tests__/upgrade.swap.test.js +0 -312
  233. package/dist/commands/__tests__/upgrade.swap.test.js.map +0 -1
  234. package/dist/commands/__tests__/world-upgrade.test.d.ts +0 -8
  235. package/dist/commands/__tests__/world-upgrade.test.d.ts.map +0 -1
  236. package/dist/commands/__tests__/world-upgrade.test.js +0 -73
  237. package/dist/commands/__tests__/world-upgrade.test.js.map +0 -1
  238. package/dist/lib/__tests__/symlink-reconcile.test.d.ts +0 -2
  239. package/dist/lib/__tests__/symlink-reconcile.test.d.ts.map +0 -1
  240. package/dist/lib/__tests__/symlink-reconcile.test.js +0 -106
  241. package/dist/lib/__tests__/symlink-reconcile.test.js.map +0 -1
@@ -1,74 +0,0 @@
1
- // A3 (Phase A — fresh-install self-bootstrap): `olam --help` hides the
2
- // `crystallize` command unless PLERI is configured (env var or pleri block
3
- // in .olam/config.yaml). Command stays callable regardless — A1's runtime
4
- // gate handles the skip path.
5
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
- import * as fs from 'node:fs';
7
- import * as os from 'node:os';
8
- import * as path from 'node:path';
9
- import { Command } from 'commander';
10
- import { registerCrystallize } from '../commands/crystallize.js';
11
- import { isPleriConfigured } from '../pleri-config.js';
12
- function buildProgram(hidden) {
13
- const program = new Command();
14
- program.name('olam').description('test').version('0.0.0');
15
- registerCrystallize(program, { hidden });
16
- return program;
17
- }
18
- describe('crystallize visibility in `olam --help`', () => {
19
- it('omits crystallize from help output when registered with hidden: true', () => {
20
- const program = buildProgram(true);
21
- const help = program.helpInformation();
22
- expect(help).not.toMatch(/\bcrystallize\b/);
23
- });
24
- it('shows crystallize in help output when registered with hidden: false', () => {
25
- const program = buildProgram(false);
26
- const help = program.helpInformation();
27
- expect(help).toMatch(/\bcrystallize\b/);
28
- });
29
- it('keeps crystallize callable even when hidden (does not error on unknown command)', async () => {
30
- // commander treats hidden commands the same way for parsing — they
31
- // simply aren't listed in help output. Verify the parser still
32
- // recognizes the command and would dispatch its action.
33
- const program = buildProgram(true);
34
- // commander.commands is the public list. It includes the hidden one.
35
- expect(program.commands.map((c) => c.name())).toContain('crystallize');
36
- });
37
- });
38
- describe('isPleriConfigured', () => {
39
- let tmpDir;
40
- let originalPleriUrl;
41
- beforeEach(() => {
42
- originalPleriUrl = process.env.PLERI_BASE_URL;
43
- delete process.env.PLERI_BASE_URL;
44
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'olam-pleri-detect-'));
45
- });
46
- afterEach(() => {
47
- if (originalPleriUrl !== undefined) {
48
- process.env.PLERI_BASE_URL = originalPleriUrl;
49
- }
50
- else {
51
- delete process.env.PLERI_BASE_URL;
52
- }
53
- fs.rmSync(tmpDir, { recursive: true, force: true });
54
- });
55
- it('returns true when PLERI_BASE_URL is set in env', () => {
56
- process.env.PLERI_BASE_URL = 'https://pleri.example.com';
57
- expect(isPleriConfigured(tmpDir)).toBe(true);
58
- });
59
- it('returns false when neither env nor config has pleri', () => {
60
- expect(isPleriConfigured(tmpDir)).toBe(false);
61
- });
62
- it('returns false when config dir does not exist', () => {
63
- expect(isPleriConfigured('/tmp/no-such-dir-' + Date.now())).toBe(false);
64
- });
65
- it('returns true when config.yaml has a top-level pleri: block', () => {
66
- fs.writeFileSync(path.join(tmpDir, 'config.yaml'), 'project: test\npleri:\n base_url: https://pleri.example.com\n');
67
- expect(isPleriConfigured(tmpDir)).toBe(true);
68
- });
69
- it('returns false when pleri: line is commented out', () => {
70
- fs.writeFileSync(path.join(tmpDir, 'config.yaml'), 'project: test\n# pleri:\n# base_url: https://pleri.example.com\n');
71
- expect(isPleriConfigured(tmpDir)).toBe(false);
72
- });
73
- });
74
- //# sourceMappingURL=help-output.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"help-output.test.js","sourceRoot":"","sources":["../../src/__tests__/help-output.test.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- /**
2
- * Unit tests for captureGhToken and updated buildComposeEnv (GH_TOKEN injection).
3
- *
4
- * Isolated from host-cp.test.ts because these tests mock node:child_process
5
- * (spawnSync) — the mock is file-scoped and would otherwise break the pure-
6
- * function tests in the sibling file.
7
- */
8
- export {};
9
- //# sourceMappingURL=host-cp-gh-token.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"host-cp-gh-token.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/host-cp-gh-token.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1,129 +0,0 @@
1
- /**
2
- * Unit tests for captureGhToken and updated buildComposeEnv (GH_TOKEN injection).
3
- *
4
- * Isolated from host-cp.test.ts because these tests mock node:child_process
5
- * (spawnSync) — the mock is file-scoped and would otherwise break the pure-
6
- * function tests in the sibling file.
7
- */
8
- import { describe, it, expect, vi, afterEach } from 'vitest';
9
- // Mock external packages that don't exist in the test environment.
10
- vi.mock('dockerode', () => ({ default: vi.fn() }));
11
- vi.mock('@olam/adapters', () => ({
12
- auditPortsForZombies: vi.fn(),
13
- PortHeldByZombieError: class PortHeldByZombieError extends Error {
14
- },
15
- }));
16
- vi.mock('@olam/core/src/util/open-url.js', () => ({ openUrl: vi.fn() }));
17
- vi.mock('../context.js', () => ({ loadContext: vi.fn() }));
18
- vi.mock('../output.js', () => ({
19
- printError: vi.fn(),
20
- printSuccess: vi.fn(),
21
- printInfo: vi.fn(),
22
- printHeader: vi.fn(),
23
- printWarning: vi.fn(),
24
- }));
25
- // Mock node:child_process before importing the module under test so
26
- // spawnSync is replaceable per-test.
27
- const mockSpawnSync = vi.fn();
28
- vi.mock('node:child_process', async (importOriginal) => {
29
- const mod = await importOriginal();
30
- return { ...mod, spawnSync: mockSpawnSync };
31
- });
32
- // Import AFTER the mocks are registered.
33
- const { captureGhToken, buildComposeEnv } = await import('../commands/host-cp.js');
34
- afterEach(() => {
35
- vi.clearAllMocks();
36
- });
37
- // ── captureGhToken ────────────────────────────────────────────────
38
- describe('captureGhToken', () => {
39
- it('returns the token when gh auth token exits 0 with output', () => {
40
- mockSpawnSync.mockReturnValue({
41
- status: 0,
42
- stdout: 'ghp_abc123\n',
43
- stderr: '',
44
- });
45
- expect(captureGhToken()).toBe('ghp_abc123');
46
- expect(mockSpawnSync).toHaveBeenCalledWith('gh', ['auth', 'token'], expect.objectContaining({
47
- encoding: 'utf-8',
48
- }));
49
- });
50
- it('returns null when gh auth token exits non-zero (not authenticated)', () => {
51
- mockSpawnSync.mockReturnValue({
52
- status: 1,
53
- stdout: '',
54
- stderr: 'not logged in\n',
55
- });
56
- expect(captureGhToken()).toBeNull();
57
- });
58
- it('returns null when gh exits 0 but stdout is empty (edge case)', () => {
59
- mockSpawnSync.mockReturnValue({
60
- status: 0,
61
- stdout: '',
62
- stderr: '',
63
- });
64
- expect(captureGhToken()).toBeNull();
65
- });
66
- it('returns null when gh exits 0 but stdout is only whitespace', () => {
67
- mockSpawnSync.mockReturnValue({
68
- status: 0,
69
- stdout: ' \n',
70
- stderr: '',
71
- });
72
- expect(captureGhToken()).toBeNull();
73
- });
74
- it('returns null when spawnSync throws (gh not installed)', () => {
75
- mockSpawnSync.mockImplementation(() => {
76
- throw new Error('spawn gh ENOENT');
77
- });
78
- expect(captureGhToken()).toBeNull();
79
- });
80
- it('strips trailing newline from token', () => {
81
- mockSpawnSync.mockReturnValue({
82
- status: 0,
83
- stdout: 'ghs_token_value\n',
84
- stderr: '',
85
- });
86
- expect(captureGhToken()).toBe('ghs_token_value');
87
- });
88
- });
89
- // ── buildComposeEnv — GH_TOKEN extension ─────────────────────────
90
- describe('buildComposeEnv with ghToken', () => {
91
- // OLAM_CLI_VERSION is now added unconditionally (read from
92
- // packages/cli/package.json). Use toMatchObject + has-key/lacks-key
93
- // assertions to keep these tests focused on the auth/token contract
94
- // without coupling to the version string.
95
- it('includes GH_TOKEN when provided alongside auth secret', () => {
96
- const env = buildComposeEnv('auth-secret-value', 'ghp_abc123');
97
- expect(env).toMatchObject({
98
- OLAM_AUTH_SECRET: 'auth-secret-value',
99
- GH_TOKEN: 'ghp_abc123',
100
- });
101
- });
102
- it('includes GH_TOKEN when auth secret is null', () => {
103
- const env = buildComposeEnv(null, 'ghp_abc123');
104
- expect(env).toMatchObject({ GH_TOKEN: 'ghp_abc123' });
105
- expect(env).not.toHaveProperty('OLAM_AUTH_SECRET');
106
- });
107
- it('omits GH_TOKEN when ghToken is null', () => {
108
- const env = buildComposeEnv('auth-secret-value', null);
109
- expect(env).toMatchObject({ OLAM_AUTH_SECRET: 'auth-secret-value' });
110
- expect(env).not.toHaveProperty('GH_TOKEN');
111
- });
112
- it('omits GH_TOKEN when ghToken is undefined (backward-compat)', () => {
113
- const env = buildComposeEnv('auth-secret-value');
114
- expect(env).toMatchObject({ OLAM_AUTH_SECRET: 'auth-secret-value' });
115
- expect(env).not.toHaveProperty('GH_TOKEN');
116
- });
117
- it('omits GH_TOKEN when ghToken is empty string', () => {
118
- const env = buildComposeEnv(null, '');
119
- expect(env).not.toHaveProperty('GH_TOKEN');
120
- expect(env).not.toHaveProperty('OLAM_AUTH_SECRET');
121
- });
122
- it('returns no auth/token keys when both are null/undefined', () => {
123
- for (const env of [buildComposeEnv(null, null), buildComposeEnv(null)]) {
124
- expect(env).not.toHaveProperty('OLAM_AUTH_SECRET');
125
- expect(env).not.toHaveProperty('GH_TOKEN');
126
- }
127
- });
128
- });
129
- //# sourceMappingURL=host-cp-gh-token.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"host-cp-gh-token.test.js","sourceRoot":"","sources":["../../src/__tests__/host-cp-gh-token.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE7D,mEAAmE;AACnE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACnD,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/B,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC7B,qBAAqB,EAAE,MAAM,qBAAsB,SAAQ,KAAK;KAAG;CACpE,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACzE,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7B,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE;IACrB,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE;IAClB,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;IACpB,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE;CACtB,CAAC,CAAC,CAAC;AAEJ,oEAAoE;AACpE,qCAAqC;AACrC,MAAM,aAAa,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACrD,MAAM,GAAG,GAAG,MAAM,cAAc,EAAuC,CAAC;IACxE,OAAO,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEH,yCAAyC;AACzC,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAEnF,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,aAAa,EAAE,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,qEAAqE;AAErE,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,aAAa,CAAC,eAAe,CAAC;YAC5B,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,cAAc;YACtB,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,CAAC,aAAa,CAAC,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,gBAAgB,CAAC;YAC1F,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,aAAa,CAAC,eAAe,CAAC;YAC5B,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,iBAAiB;SAC1B,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,aAAa,CAAC,eAAe,CAAC;YAC5B,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,aAAa,CAAC,eAAe,CAAC;YAC5B,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE;YACpC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,aAAa,CAAC,eAAe,CAAC;YAC5B,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,mBAAmB;YAC3B,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,oEAAoE;AAEpE,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,2DAA2D;IAC3D,oEAAoE;IACpE,oEAAoE;IACpE,0CAA0C;IAC1C,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,GAAG,GAAG,eAAe,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QAC/D,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC;YACxB,gBAAgB,EAAE,mBAAmB;YACrC,QAAQ,EAAE,YAAY;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,GAAG,GAAG,eAAe,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,GAAG,GAAG,eAAe,CAAC,mBAAmB,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,KAAK,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACvE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;YACnD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,9 +0,0 @@
1
- /**
2
- * Phase F-2-D (D1+D2+D3): unit tests for host-cp.ts pure helpers.
3
- *
4
- * Covers token + PID file management. Docker-dependent paths
5
- * (findHostCpContainer, probeHealth, handleStart, etc.) are integration-
6
- * tested in M5 dogfood (D5) against a live docker daemon.
7
- */
8
- export {};
9
- //# sourceMappingURL=host-cp.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"host-cp.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/host-cp.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1,335 +0,0 @@
1
- /**
2
- * Phase F-2-D (D1+D2+D3): unit tests for host-cp.ts pure helpers.
3
- *
4
- * Covers token + PID file management. Docker-dependent paths
5
- * (findHostCpContainer, probeHealth, handleStart, etc.) are integration-
6
- * tested in M5 dogfood (D5) against a live docker daemon.
7
- */
8
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
9
- import * as fs from 'node:fs';
10
- import * as os from 'node:os';
11
- import * as path from 'node:path';
12
- import { writeToken, readToken, removeToken, writePid, readPid, removePid, readAuthSecret, authSecretPath, buildComposeEnv, readR2Credentials, r2CredentialsPath, SIDECAR_PULL_SERVICE, } from '../commands/host-cp.js';
13
- let tmpHome;
14
- let originalHome;
15
- beforeEach(() => {
16
- tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'olam-host-cp-test-'));
17
- originalHome = process.env.OLAM_HOME;
18
- process.env.OLAM_HOME = tmpHome;
19
- });
20
- afterEach(() => {
21
- if (originalHome === undefined)
22
- delete process.env.OLAM_HOME;
23
- else
24
- process.env.OLAM_HOME = originalHome;
25
- fs.rmSync(tmpHome, { recursive: true, force: true });
26
- });
27
- // ── writeToken / readToken / removeToken ─────────────────────────
28
- describe('writeToken', () => {
29
- it('writes a 64-char hex token', () => {
30
- const token = writeToken();
31
- expect(token).toMatch(/^[0-9a-f]{64}$/);
32
- });
33
- it('writes to ~/.olam/host-cp.token by default', () => {
34
- writeToken();
35
- const filePath = path.join(tmpHome, 'host-cp.token');
36
- expect(fs.existsSync(filePath)).toBe(true);
37
- });
38
- it('sets file mode 0600', () => {
39
- writeToken();
40
- const filePath = path.join(tmpHome, 'host-cp.token');
41
- const mode = fs.statSync(filePath).mode & 0o777;
42
- expect(mode).toBe(0o600);
43
- });
44
- it('creates the parent directory if missing', () => {
45
- fs.rmSync(tmpHome, { recursive: true, force: true });
46
- writeToken();
47
- expect(fs.existsSync(path.join(tmpHome, 'host-cp.token'))).toBe(true);
48
- });
49
- it('overwrites existing token (each start regenerates)', () => {
50
- const t1 = writeToken();
51
- const t2 = writeToken();
52
- expect(t1).not.toBe(t2);
53
- expect(readToken()).toBe(t2);
54
- });
55
- it('produces fresh entropy across calls', () => {
56
- const tokens = new Set();
57
- for (let i = 0; i < 10; i++) {
58
- tokens.add(writeToken());
59
- }
60
- expect(tokens.size).toBe(10);
61
- });
62
- });
63
- describe('readToken', () => {
64
- it('returns null when token file is absent', () => {
65
- expect(readToken()).toBeNull();
66
- });
67
- it('returns the written value (stripped of trailing whitespace)', () => {
68
- const written = writeToken();
69
- expect(readToken()).toBe(written);
70
- });
71
- });
72
- describe('removeToken', () => {
73
- it('returns true when removing an existing token', () => {
74
- writeToken();
75
- expect(removeToken()).toBe(true);
76
- expect(readToken()).toBeNull();
77
- });
78
- it('returns false when the token file is absent', () => {
79
- expect(removeToken()).toBe(false);
80
- });
81
- it('is idempotent (second call returns false)', () => {
82
- writeToken();
83
- expect(removeToken()).toBe(true);
84
- expect(removeToken()).toBe(false);
85
- });
86
- });
87
- // ── writePid / readPid / removePid ────────────────────────────────
88
- describe('writePid', () => {
89
- it('writes the PID number as a string', () => {
90
- writePid(12345);
91
- const filePath = path.join(tmpHome, 'host-cp.pid');
92
- expect(fs.readFileSync(filePath, 'utf-8').trim()).toBe('12345');
93
- });
94
- it('uses mode 0644 (world-readable; not secret like the token)', () => {
95
- writePid(12345);
96
- const filePath = path.join(tmpHome, 'host-cp.pid');
97
- const mode = fs.statSync(filePath).mode & 0o777;
98
- expect(mode).toBe(0o644);
99
- });
100
- it('overwrites existing PID', () => {
101
- writePid(1);
102
- writePid(2);
103
- expect(readPid()).toBe(2);
104
- });
105
- });
106
- describe('readPid', () => {
107
- it('returns null when PID file is absent', () => {
108
- expect(readPid()).toBeNull();
109
- });
110
- it('returns the parsed number', () => {
111
- writePid(99999);
112
- expect(readPid()).toBe(99999);
113
- });
114
- it('returns null for non-numeric content (corruption defense)', () => {
115
- fs.writeFileSync(path.join(tmpHome, 'host-cp.pid'), 'not-a-number');
116
- expect(readPid()).toBeNull();
117
- });
118
- });
119
- describe('removePid', () => {
120
- it('returns true when removing an existing PID file', () => {
121
- writePid(1);
122
- expect(removePid()).toBe(true);
123
- expect(readPid()).toBeNull();
124
- });
125
- it('returns false when the PID file is absent', () => {
126
- expect(removePid()).toBe(false);
127
- });
128
- });
129
- // ── readAuthSecret + buildComposeEnv ─────────────────────────────
130
- //
131
- // Regression: `docker compose up -d` recreated host-cp with an empty
132
- // OLAM_AUTH_SECRET because the operator's shell didn't export it,
133
- // silently breaking every credentials/* call against auth-service.
134
- // `olam host-cp start` now reads the secret from ~/.olam/auth-secret
135
- // and passes it via spawn env — these tests lock the shape in.
136
- describe('readAuthSecret', () => {
137
- it('returns null when ~/.olam/auth-secret does not exist', () => {
138
- expect(readAuthSecret()).toBeNull();
139
- });
140
- it('returns the file contents (trimmed) when the file exists', () => {
141
- fs.mkdirSync(tmpHome, { recursive: true });
142
- fs.writeFileSync(authSecretPath(), 'Xt7pDfjdj-7fA0HALipPpGRRWomCJPvZ_pywxvkDkYs\n');
143
- expect(readAuthSecret()).toBe('Xt7pDfjdj-7fA0HALipPpGRRWomCJPvZ_pywxvkDkYs');
144
- });
145
- it('treats empty / whitespace-only files as null', () => {
146
- // A 0-byte file would round-trip to compose as an empty env var,
147
- // which is exactly the silent-failure mode the helper exists to
148
- // prevent. Caller (handleStart) prints a warning when this returns
149
- // null instead of dropping the operator into the empty-secret
150
- // footgun.
151
- fs.mkdirSync(tmpHome, { recursive: true });
152
- fs.writeFileSync(authSecretPath(), '');
153
- expect(readAuthSecret()).toBeNull();
154
- fs.writeFileSync(authSecretPath(), ' \n\n');
155
- expect(readAuthSecret()).toBeNull();
156
- });
157
- it('honors OLAM_HOME so tests do not stomp on the real ~/.olam', () => {
158
- fs.mkdirSync(tmpHome, { recursive: true });
159
- fs.writeFileSync(authSecretPath(), 'sentinel-value-for-test');
160
- expect(readAuthSecret()).toBe('sentinel-value-for-test');
161
- expect(authSecretPath()).toBe(path.join(tmpHome, 'auth-secret'));
162
- });
163
- });
164
- describe('buildComposeEnv', () => {
165
- // OLAM_CLI_VERSION is environment-derived (read from packages/cli/package.json
166
- // at runtime) and added unconditionally to the env. Use toMatchObject so the
167
- // existing assertions stay focused on the auth/secret/token contract while
168
- // tolerating the new key. A separate assertion below pins the version shape.
169
- it('emits OLAM_AUTH_SECRET when a non-empty secret is provided', () => {
170
- const env = buildComposeEnv('Xt7pDfjdj-7fA0HALipPpGRRWomCJPvZ_pywxvkDkYs');
171
- expect(env).toMatchObject({
172
- OLAM_AUTH_SECRET: 'Xt7pDfjdj-7fA0HALipPpGRRWomCJPvZ_pywxvkDkYs',
173
- });
174
- });
175
- it('returns no OLAM_AUTH_SECRET key when the secret is null', () => {
176
- // We deliberately omit the env var (rather than setting it to "")
177
- // so process.env can still win if the caller has already exported
178
- // it — caller code prints the loud warning when readAuthSecret
179
- // returns null.
180
- expect(buildComposeEnv(null)).not.toHaveProperty('OLAM_AUTH_SECRET');
181
- });
182
- it('returns no OLAM_AUTH_SECRET key when the secret is empty', () => {
183
- // Defensive: this branch is unreachable in practice because
184
- // readAuthSecret already returns null for empty files, but the
185
- // helper must be safe to call with any string.
186
- expect(buildComposeEnv('')).not.toHaveProperty('OLAM_AUTH_SECRET');
187
- });
188
- it('always emits OLAM_CLI_VERSION (semver) from the bundled package.json', () => {
189
- const env = buildComposeEnv('Xt7pDfjdj-7fA0HALipPpGRRWomCJPvZ_pywxvkDkYs');
190
- expect(env.OLAM_CLI_VERSION).toMatch(/^\d+\.\d+\.\d+/);
191
- });
192
- });
193
- // ── readR2Credentials + r2CredentialsPath ────────────────────────
194
- describe('r2CredentialsPath', () => {
195
- it('returns path under OLAM_HOME', () => {
196
- expect(r2CredentialsPath()).toBe(path.join(tmpHome, 'r2-credentials.json'));
197
- });
198
- });
199
- const VALID_CREDS = {
200
- account_id: 'abc123',
201
- bucket: 'olam-test-artifacts',
202
- access_key_id: 'key-id',
203
- secret_access_key: 'secret',
204
- public_url_base: 'https://pub-abc.r2.dev',
205
- };
206
- describe('readR2Credentials', () => {
207
- it('returns null when the file is absent', () => {
208
- expect(readR2Credentials()).toBeNull();
209
- });
210
- it('returns parsed credentials when the file is valid JSON', () => {
211
- fs.mkdirSync(tmpHome, { recursive: true });
212
- fs.writeFileSync(r2CredentialsPath(), JSON.stringify(VALID_CREDS));
213
- expect(readR2Credentials()).toEqual(VALID_CREDS);
214
- });
215
- it('returns null for empty / whitespace-only files', () => {
216
- fs.mkdirSync(tmpHome, { recursive: true });
217
- fs.writeFileSync(r2CredentialsPath(), '');
218
- expect(readR2Credentials()).toBeNull();
219
- fs.writeFileSync(r2CredentialsPath(), ' \n\n');
220
- expect(readR2Credentials()).toBeNull();
221
- });
222
- it('returns null for malformed JSON', () => {
223
- fs.mkdirSync(tmpHome, { recursive: true });
224
- fs.writeFileSync(r2CredentialsPath(), '{not valid json');
225
- expect(readR2Credentials()).toBeNull();
226
- });
227
- it('returns null when a required field is missing', () => {
228
- fs.mkdirSync(tmpHome, { recursive: true });
229
- const { public_url_base: _dropped, ...partial } = VALID_CREDS;
230
- fs.writeFileSync(r2CredentialsPath(), JSON.stringify(partial));
231
- expect(readR2Credentials()).toBeNull();
232
- });
233
- it('returns null when a field has the wrong type', () => {
234
- fs.mkdirSync(tmpHome, { recursive: true });
235
- fs.writeFileSync(r2CredentialsPath(), JSON.stringify({ ...VALID_CREDS, account_id: 42 }));
236
- expect(readR2Credentials()).toBeNull();
237
- });
238
- it('honors OLAM_HOME so tests do not stomp on the real ~/.olam', () => {
239
- fs.mkdirSync(tmpHome, { recursive: true });
240
- fs.writeFileSync(r2CredentialsPath(), JSON.stringify(VALID_CREDS));
241
- const result = readR2Credentials();
242
- expect(result).not.toBeNull();
243
- expect(result?.account_id).toBe('abc123');
244
- expect(r2CredentialsPath()).toBe(path.join(tmpHome, 'r2-credentials.json'));
245
- });
246
- });
247
- // ── OLAM_HOME override ─────────────────────────────────────────────
248
- describe('OLAM_HOME env override', () => {
249
- it('writeToken honors OLAM_HOME (verified by tmpdir setup above)', () => {
250
- writeToken();
251
- expect(fs.existsSync(path.join(tmpHome, 'host-cp.token'))).toBe(true);
252
- // Sanity: the real ~/.olam should NOT have been touched.
253
- const realHome = path.join(os.homedir(), '.olam', 'host-cp.token');
254
- if (fs.existsSync(realHome)) {
255
- // If it exists from a real `olam host-cp start` it predates the
256
- // test; can't assert absence. Just assert tmpHome is the active
257
- // path via the file we just wrote.
258
- // (Earlier mode/length assertions already cover correctness.)
259
- }
260
- });
261
- });
262
- // ── Regression: bootstrap compose-pull bare-name Docker Hub failure ──
263
- //
264
- // Bug: `olam bootstrap` succeeded at pulling 3 images by digest (step 2),
265
- // then `olam host-cp start` ran `docker compose pull` against a compose.yaml
266
- // that had `image: olam-host-cp:latest` (bare, no registry prefix). Docker
267
- // tried to pull from Docker Hub → "pull access denied for olam-host-cp,
268
- // repository does not exist". Root cause: compose.yaml used a bare image
269
- // name AND the pull command pulled all services instead of just the sidecar.
270
- //
271
- // Fix (PR #302):
272
- // 1. compose.yaml: `image: ghcr.io/pleri/olam-host-cp:latest` (registry-prefixed)
273
- // 2. host-cp start: pull only SIDECAR_PULL_SERVICE (`docker-socket-proxy`)
274
- // 3. bootstrap: tag digest-pulled image as `ghcr.io/pleri/olam-host-cp:latest`
275
- //
276
- // These tests lock both invariants so future drift is caught at test time.
277
- describe('SIDECAR_PULL_SERVICE regression guard', () => {
278
- it('names the sidecar, not the host-cp image', () => {
279
- // The pre-pull in handleStart must target only the third-party sidecar.
280
- // If this were empty or omitted, `docker compose pull` would pull ALL
281
- // services — including olam-host-cp, bypassing bootstrap's digest pin.
282
- expect(SIDECAR_PULL_SERVICE).toBe('docker-socket-proxy');
283
- });
284
- it('does not reference the olam-host-cp image', () => {
285
- // Guard against accidental reversion to a bare pull that drags in
286
- // the host-cp service. The host-cp image is already digest-pinned
287
- // by `olam bootstrap`; a compose pull for it would hit the registry
288
- // and potentially pull a different layer than what was verified.
289
- expect(SIDECAR_PULL_SERVICE).not.toMatch(/host.?cp/i);
290
- expect(SIDECAR_PULL_SERVICE).not.toMatch(/olam/i);
291
- });
292
- });
293
- describe('compose.yaml image field guard', () => {
294
- // The compose.yaml lives in packages/host-cp/; from packages/cli the
295
- // path resolves one level up.
296
- const composeYamlPath = path.resolve(process.cwd(), '../host-cp/compose.yaml');
297
- it('compose.yaml exists at the expected path', () => {
298
- expect(fs.existsSync(composeYamlPath)).toBe(true);
299
- });
300
- it('host-cp service image has a fully-qualified registry prefix', () => {
301
- // Bare image names (e.g. `olam-host-cp:latest` without a registry)
302
- // cause Docker to query Docker Hub, which returns "pull access denied"
303
- // for private/non-existent repos. The image MUST be registry-prefixed
304
- // (e.g. `ghcr.io/pleri/olam-host-cp:latest`) so that:
305
- // a) `docker compose up` finds it locally after `olam bootstrap` tags it
306
- // b) If a pull IS attempted, it targets GHCR (not Docker Hub)
307
- const yaml = fs.readFileSync(composeYamlPath, 'utf-8');
308
- // Extract the image: line that immediately follows `container_name: olam-host-cp`.
309
- // We match the section between `container_name: olam-host-cp` and the next service.
310
- const hostCpSection = yaml.match(/container_name: olam-host-cp[\s\S]*?(?=\n \w|\nnetworks:|\z)/)?.[0] ?? '';
311
- const imageMatch = hostCpSection.match(/^\s*image:\s*(.+)$/m);
312
- expect(imageMatch).not.toBeNull();
313
- const imageRef = imageMatch[1].trim();
314
- // Must contain a dot-separated registry hostname (ghcr.io, docker.io, etc.)
315
- expect(imageRef).toMatch(/^[a-z0-9][\w.-]+\.[a-z]{2,}\//);
316
- expect(imageRef).toContain('olam-host-cp');
317
- });
318
- it('bootstrap tag target for host-cp matches compose.yaml image field', () => {
319
- // bootstrap.ts step 3b tags the digest-pulled image as `${registry}/olam-host-cp:latest`.
320
- // compose.yaml's `image:` field must use the same canonical name so
321
- // `docker compose up` finds the locally-tagged image and doesn't re-pull.
322
- const yaml = fs.readFileSync(composeYamlPath, 'utf-8');
323
- const hostCpSection = yaml.match(/container_name: olam-host-cp[\s\S]*?(?=\n \w|\nnetworks:|\z)/)?.[0] ?? '';
324
- const imageMatch = hostCpSection.match(/^\s*image:\s*(.+)$/m);
325
- expect(imageMatch).not.toBeNull();
326
- const composeImage = imageMatch[1].trim();
327
- // bootstrap.ts hard-codes the tag as `${registry}/olam-host-cp:latest`
328
- // where registry defaults to 'ghcr.io/pleri' (from image-digests.json).
329
- // The compose.yaml image field must match this pattern.
330
- const registryPrefix = composeImage.replace(/\/olam-host-cp.*$/, '');
331
- const expectedTag = `${registryPrefix}/olam-host-cp:latest`;
332
- expect(composeImage).toBe(expectedTag);
333
- });
334
- });
335
- //# sourceMappingURL=host-cp.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"host-cp.test.js","sourceRoot":"","sources":["../../src/__tests__/host-cp.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=image-presence.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"image-presence.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/image-presence.test.ts"],"names":[],"mappings":""}