@bazaar.ai/mcp-human-agents 0.1.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.
Files changed (259) hide show
  1. package/.env.example +15 -0
  2. package/README.md +178 -0
  3. package/dist/mcp-server/src/bin.d.ts +3 -0
  4. package/dist/mcp-server/src/bin.d.ts.map +1 -0
  5. package/dist/mcp-server/src/bin.js +10 -0
  6. package/dist/mcp-server/src/bin.js.map +1 -0
  7. package/dist/mcp-server/src/cli/setup.d.ts +2 -0
  8. package/dist/mcp-server/src/cli/setup.d.ts.map +1 -0
  9. package/dist/mcp-server/src/cli/setup.js +274 -0
  10. package/dist/mcp-server/src/cli/setup.js.map +1 -0
  11. package/dist/mcp-server/src/config/defaults.d.ts +16 -0
  12. package/dist/mcp-server/src/config/defaults.d.ts.map +1 -0
  13. package/dist/mcp-server/src/config/defaults.js +19 -0
  14. package/dist/mcp-server/src/config/defaults.js.map +1 -0
  15. package/dist/mcp-server/src/config/env.d.ts +73 -0
  16. package/dist/mcp-server/src/config/env.d.ts.map +1 -0
  17. package/dist/mcp-server/src/config/env.js +72 -0
  18. package/dist/mcp-server/src/config/env.js.map +1 -0
  19. package/dist/mcp-server/src/config/index.d.ts +3 -0
  20. package/dist/mcp-server/src/config/index.d.ts.map +1 -0
  21. package/dist/mcp-server/src/config/index.js +22 -0
  22. package/dist/mcp-server/src/config/index.js.map +1 -0
  23. package/dist/mcp-server/src/context/generator.d.ts +16 -0
  24. package/dist/mcp-server/src/context/generator.d.ts.map +1 -0
  25. package/dist/mcp-server/src/context/generator.js +61 -0
  26. package/dist/mcp-server/src/context/generator.js.map +1 -0
  27. package/dist/mcp-server/src/context/index.d.ts +3 -0
  28. package/dist/mcp-server/src/context/index.d.ts.map +1 -0
  29. package/dist/mcp-server/src/context/index.js +10 -0
  30. package/dist/mcp-server/src/context/index.js.map +1 -0
  31. package/dist/mcp-server/src/context/templates.d.ts +8 -0
  32. package/dist/mcp-server/src/context/templates.d.ts.map +1 -0
  33. package/dist/mcp-server/src/context/templates.js +41 -0
  34. package/dist/mcp-server/src/context/templates.js.map +1 -0
  35. package/dist/mcp-server/src/git/branch.d.ts +13 -0
  36. package/dist/mcp-server/src/git/branch.d.ts.map +1 -0
  37. package/dist/mcp-server/src/git/branch.js +49 -0
  38. package/dist/mcp-server/src/git/branch.js.map +1 -0
  39. package/dist/mcp-server/src/git/diff.d.ts +10 -0
  40. package/dist/mcp-server/src/git/diff.d.ts.map +1 -0
  41. package/dist/mcp-server/src/git/diff.js +39 -0
  42. package/dist/mcp-server/src/git/diff.js.map +1 -0
  43. package/dist/mcp-server/src/git/index.d.ts +5 -0
  44. package/dist/mcp-server/src/git/index.d.ts.map +1 -0
  45. package/dist/mcp-server/src/git/index.js +16 -0
  46. package/dist/mcp-server/src/git/index.js.map +1 -0
  47. package/dist/mcp-server/src/git/merge.d.ts +6 -0
  48. package/dist/mcp-server/src/git/merge.d.ts.map +1 -0
  49. package/dist/mcp-server/src/git/merge.js +30 -0
  50. package/dist/mcp-server/src/git/merge.js.map +1 -0
  51. package/dist/mcp-server/src/git/worktree.d.ts +11 -0
  52. package/dist/mcp-server/src/git/worktree.d.ts.map +1 -0
  53. package/dist/mcp-server/src/git/worktree.js +38 -0
  54. package/dist/mcp-server/src/git/worktree.js.map +1 -0
  55. package/dist/mcp-server/src/http-wrapper.d.ts +6 -0
  56. package/dist/mcp-server/src/http-wrapper.d.ts.map +1 -0
  57. package/dist/mcp-server/src/http-wrapper.js +85 -0
  58. package/dist/mcp-server/src/http-wrapper.js.map +1 -0
  59. package/dist/mcp-server/src/index.d.ts +2 -0
  60. package/dist/mcp-server/src/index.d.ts.map +1 -0
  61. package/dist/mcp-server/src/index.js +28 -0
  62. package/dist/mcp-server/src/index.js.map +1 -0
  63. package/dist/mcp-server/src/platform-client/client.d.ts +17 -0
  64. package/dist/mcp-server/src/platform-client/client.d.ts.map +1 -0
  65. package/dist/mcp-server/src/platform-client/client.js +68 -0
  66. package/dist/mcp-server/src/platform-client/client.js.map +1 -0
  67. package/dist/mcp-server/src/platform-client/index.d.ts +5 -0
  68. package/dist/mcp-server/src/platform-client/index.d.ts.map +1 -0
  69. package/dist/mcp-server/src/platform-client/index.js +10 -0
  70. package/dist/mcp-server/src/platform-client/index.js.map +1 -0
  71. package/dist/mcp-server/src/platform-client/mock-client.d.ts +28 -0
  72. package/dist/mcp-server/src/platform-client/mock-client.d.ts.map +1 -0
  73. package/dist/mcp-server/src/platform-client/mock-client.js +75 -0
  74. package/dist/mcp-server/src/platform-client/mock-client.js.map +1 -0
  75. package/dist/mcp-server/src/platform-client/polling.d.ts +9 -0
  76. package/dist/mcp-server/src/platform-client/polling.d.ts.map +1 -0
  77. package/dist/mcp-server/src/platform-client/polling.js +40 -0
  78. package/dist/mcp-server/src/platform-client/polling.js.map +1 -0
  79. package/dist/mcp-server/src/platform-client/types.d.ts +2 -0
  80. package/dist/mcp-server/src/platform-client/types.d.ts.map +1 -0
  81. package/dist/mcp-server/src/platform-client/types.js +3 -0
  82. package/dist/mcp-server/src/platform-client/types.js.map +1 -0
  83. package/dist/mcp-server/src/provisioning/authorized-keys.d.ts +14 -0
  84. package/dist/mcp-server/src/provisioning/authorized-keys.d.ts.map +1 -0
  85. package/dist/mcp-server/src/provisioning/authorized-keys.js +48 -0
  86. package/dist/mcp-server/src/provisioning/authorized-keys.js.map +1 -0
  87. package/dist/mcp-server/src/provisioning/cleanup.d.ts +19 -0
  88. package/dist/mcp-server/src/provisioning/cleanup.d.ts.map +1 -0
  89. package/dist/mcp-server/src/provisioning/cleanup.js +96 -0
  90. package/dist/mcp-server/src/provisioning/cleanup.js.map +1 -0
  91. package/dist/mcp-server/src/provisioning/index.d.ts +6 -0
  92. package/dist/mcp-server/src/provisioning/index.d.ts.map +1 -0
  93. package/dist/mcp-server/src/provisioning/index.js +24 -0
  94. package/dist/mcp-server/src/provisioning/index.js.map +1 -0
  95. package/dist/mcp-server/src/provisioning/linux-user.d.ts +15 -0
  96. package/dist/mcp-server/src/provisioning/linux-user.d.ts.map +1 -0
  97. package/dist/mcp-server/src/provisioning/linux-user.js +62 -0
  98. package/dist/mcp-server/src/provisioning/linux-user.js.map +1 -0
  99. package/dist/mcp-server/src/provisioning/privileged.d.ts +40 -0
  100. package/dist/mcp-server/src/provisioning/privileged.d.ts.map +1 -0
  101. package/dist/mcp-server/src/provisioning/privileged.js +123 -0
  102. package/dist/mcp-server/src/provisioning/privileged.js.map +1 -0
  103. package/dist/mcp-server/src/provisioning/ssh-config.d.ts +21 -0
  104. package/dist/mcp-server/src/provisioning/ssh-config.d.ts.map +1 -0
  105. package/dist/mcp-server/src/provisioning/ssh-config.js +161 -0
  106. package/dist/mcp-server/src/provisioning/ssh-config.js.map +1 -0
  107. package/dist/mcp-server/src/provisioning/tmux-session.d.ts +37 -0
  108. package/dist/mcp-server/src/provisioning/tmux-session.d.ts.map +1 -0
  109. package/dist/mcp-server/src/provisioning/tmux-session.js +123 -0
  110. package/dist/mcp-server/src/provisioning/tmux-session.js.map +1 -0
  111. package/dist/mcp-server/src/server.d.ts +3 -0
  112. package/dist/mcp-server/src/server.d.ts.map +1 -0
  113. package/dist/mcp-server/src/server.js +67 -0
  114. package/dist/mcp-server/src/server.js.map +1 -0
  115. package/dist/mcp-server/src/state/gig-store.d.ts +19 -0
  116. package/dist/mcp-server/src/state/gig-store.d.ts.map +1 -0
  117. package/dist/mcp-server/src/state/gig-store.js +52 -0
  118. package/dist/mcp-server/src/state/gig-store.js.map +1 -0
  119. package/dist/mcp-server/src/state/index.d.ts +4 -0
  120. package/dist/mcp-server/src/state/index.d.ts.map +1 -0
  121. package/dist/mcp-server/src/state/index.js +8 -0
  122. package/dist/mcp-server/src/state/index.js.map +1 -0
  123. package/dist/mcp-server/src/state/persistence.d.ts +13 -0
  124. package/dist/mcp-server/src/state/persistence.d.ts.map +1 -0
  125. package/dist/mcp-server/src/state/persistence.js +48 -0
  126. package/dist/mcp-server/src/state/persistence.js.map +1 -0
  127. package/dist/mcp-server/src/state/types.d.ts +15 -0
  128. package/dist/mcp-server/src/state/types.d.ts.map +1 -0
  129. package/dist/mcp-server/src/state/types.js +3 -0
  130. package/dist/mcp-server/src/state/types.js.map +1 -0
  131. package/dist/mcp-server/src/tools/dismiss-human.d.ts +25 -0
  132. package/dist/mcp-server/src/tools/dismiss-human.d.ts.map +1 -0
  133. package/dist/mcp-server/src/tools/dismiss-human.js +78 -0
  134. package/dist/mcp-server/src/tools/dismiss-human.js.map +1 -0
  135. package/dist/mcp-server/src/tools/index.d.ts +9 -0
  136. package/dist/mcp-server/src/tools/index.d.ts.map +1 -0
  137. package/dist/mcp-server/src/tools/index.js +20 -0
  138. package/dist/mcp-server/src/tools/index.js.map +1 -0
  139. package/dist/mcp-server/src/tools/list-humans.d.ts +18 -0
  140. package/dist/mcp-server/src/tools/list-humans.d.ts.map +1 -0
  141. package/dist/mcp-server/src/tools/list-humans.js +35 -0
  142. package/dist/mcp-server/src/tools/list-humans.js.map +1 -0
  143. package/dist/mcp-server/src/tools/message-human.d.ts +10 -0
  144. package/dist/mcp-server/src/tools/message-human.d.ts.map +1 -0
  145. package/dist/mcp-server/src/tools/message-human.js +19 -0
  146. package/dist/mcp-server/src/tools/message-human.js.map +1 -0
  147. package/dist/mcp-server/src/tools/schemas/dismiss-human.schema.d.ts +19 -0
  148. package/dist/mcp-server/src/tools/schemas/dismiss-human.schema.d.ts.map +1 -0
  149. package/dist/mcp-server/src/tools/schemas/dismiss-human.schema.js +22 -0
  150. package/dist/mcp-server/src/tools/schemas/dismiss-human.schema.js.map +1 -0
  151. package/dist/mcp-server/src/tools/schemas/list-humans.schema.d.ts +4 -0
  152. package/dist/mcp-server/src/tools/schemas/list-humans.schema.d.ts.map +1 -0
  153. package/dist/mcp-server/src/tools/schemas/list-humans.schema.js +7 -0
  154. package/dist/mcp-server/src/tools/schemas/list-humans.schema.js.map +1 -0
  155. package/dist/mcp-server/src/tools/schemas/message-human.schema.d.ts +13 -0
  156. package/dist/mcp-server/src/tools/schemas/message-human.schema.d.ts.map +1 -0
  157. package/dist/mcp-server/src/tools/schemas/message-human.schema.js +9 -0
  158. package/dist/mcp-server/src/tools/schemas/message-human.schema.js.map +1 -0
  159. package/dist/mcp-server/src/tools/schemas/summon-human.schema.d.ts +22 -0
  160. package/dist/mcp-server/src/tools/schemas/summon-human.schema.d.ts.map +1 -0
  161. package/dist/mcp-server/src/tools/schemas/summon-human.schema.js +18 -0
  162. package/dist/mcp-server/src/tools/schemas/summon-human.schema.js.map +1 -0
  163. package/dist/mcp-server/src/tools/summon-human.d.ts +31 -0
  164. package/dist/mcp-server/src/tools/summon-human.d.ts.map +1 -0
  165. package/dist/mcp-server/src/tools/summon-human.js +137 -0
  166. package/dist/mcp-server/src/tools/summon-human.js.map +1 -0
  167. package/dist/mcp-server/src/tunnel/client.d.ts +16 -0
  168. package/dist/mcp-server/src/tunnel/client.d.ts.map +1 -0
  169. package/dist/mcp-server/src/tunnel/client.js +100 -0
  170. package/dist/mcp-server/src/tunnel/client.js.map +1 -0
  171. package/dist/mcp-server/src/tunnel/index.d.ts +6 -0
  172. package/dist/mcp-server/src/tunnel/index.d.ts.map +1 -0
  173. package/dist/mcp-server/src/tunnel/index.js +28 -0
  174. package/dist/mcp-server/src/tunnel/index.js.map +1 -0
  175. package/dist/mcp-server/src/utils/errors.d.ts +28 -0
  176. package/dist/mcp-server/src/utils/errors.d.ts.map +1 -0
  177. package/dist/mcp-server/src/utils/errors.js +66 -0
  178. package/dist/mcp-server/src/utils/errors.js.map +1 -0
  179. package/dist/mcp-server/src/utils/exec.d.ts +7 -0
  180. package/dist/mcp-server/src/utils/exec.d.ts.map +1 -0
  181. package/dist/mcp-server/src/utils/exec.js +22 -0
  182. package/dist/mcp-server/src/utils/exec.js.map +1 -0
  183. package/dist/mcp-server/src/utils/ip.d.ts +6 -0
  184. package/dist/mcp-server/src/utils/ip.d.ts.map +1 -0
  185. package/dist/mcp-server/src/utils/ip.js +33 -0
  186. package/dist/mcp-server/src/utils/ip.js.map +1 -0
  187. package/dist/mcp-server/src/utils/logger.d.ts +20 -0
  188. package/dist/mcp-server/src/utils/logger.d.ts.map +1 -0
  189. package/dist/mcp-server/src/utils/logger.js +41 -0
  190. package/dist/mcp-server/src/utils/logger.js.map +1 -0
  191. package/dist/shared/src/contractor.types.d.ts +20 -0
  192. package/dist/shared/src/contractor.types.d.ts.map +1 -0
  193. package/dist/shared/src/contractor.types.js +3 -0
  194. package/dist/shared/src/contractor.types.js.map +1 -0
  195. package/dist/shared/src/gig.types.d.ts +32 -0
  196. package/dist/shared/src/gig.types.d.ts.map +1 -0
  197. package/dist/shared/src/gig.types.js +21 -0
  198. package/dist/shared/src/gig.types.js.map +1 -0
  199. package/dist/shared/src/index.d.ts +5 -0
  200. package/dist/shared/src/index.d.ts.map +1 -0
  201. package/dist/shared/src/index.js +21 -0
  202. package/dist/shared/src/index.js.map +1 -0
  203. package/dist/shared/src/mcp-tool.types.d.ts +45 -0
  204. package/dist/shared/src/mcp-tool.types.d.ts.map +1 -0
  205. package/dist/shared/src/mcp-tool.types.js +3 -0
  206. package/dist/shared/src/mcp-tool.types.js.map +1 -0
  207. package/dist/shared/src/platform-api.types.d.ts +73 -0
  208. package/dist/shared/src/platform-api.types.d.ts.map +1 -0
  209. package/dist/shared/src/platform-api.types.js +3 -0
  210. package/dist/shared/src/platform-api.types.js.map +1 -0
  211. package/package.json +41 -0
  212. package/src/bin.ts +7 -0
  213. package/src/cli/setup.ts +317 -0
  214. package/src/config/defaults.ts +21 -0
  215. package/src/config/env.ts +74 -0
  216. package/src/config/index.ts +2 -0
  217. package/src/context/generator.ts +71 -0
  218. package/src/context/index.ts +6 -0
  219. package/src/context/templates.ts +41 -0
  220. package/src/git/branch.ts +46 -0
  221. package/src/git/diff.ts +34 -0
  222. package/src/git/index.ts +4 -0
  223. package/src/git/merge.ts +36 -0
  224. package/src/git/worktree.ts +42 -0
  225. package/src/http-wrapper.ts +94 -0
  226. package/src/index.ts +32 -0
  227. package/src/platform-client/client.ts +93 -0
  228. package/src/platform-client/index.ts +4 -0
  229. package/src/platform-client/mock-client.ts +92 -0
  230. package/src/platform-client/polling.ts +53 -0
  231. package/src/platform-client/types.ts +9 -0
  232. package/src/provisioning/authorized-keys.ts +52 -0
  233. package/src/provisioning/cleanup.ts +106 -0
  234. package/src/provisioning/index.ts +13 -0
  235. package/src/provisioning/linux-user.ts +66 -0
  236. package/src/provisioning/privileged.ts +128 -0
  237. package/src/provisioning/ssh-config.ts +197 -0
  238. package/src/provisioning/tmux-session.ts +136 -0
  239. package/src/server.ts +111 -0
  240. package/src/state/gig-store.ts +56 -0
  241. package/src/state/index.ts +3 -0
  242. package/src/state/persistence.ts +42 -0
  243. package/src/state/types.ts +14 -0
  244. package/src/tools/dismiss-human.ts +103 -0
  245. package/src/tools/index.ts +9 -0
  246. package/src/tools/list-humans.ts +54 -0
  247. package/src/tools/message-human.ts +28 -0
  248. package/src/tools/schemas/dismiss-human.schema.ts +21 -0
  249. package/src/tools/schemas/list-humans.schema.ts +6 -0
  250. package/src/tools/schemas/message-human.schema.ts +8 -0
  251. package/src/tools/schemas/summon-human.schema.ts +19 -0
  252. package/src/tools/summon-human.ts +180 -0
  253. package/src/tunnel/client.ts +116 -0
  254. package/src/tunnel/index.ts +26 -0
  255. package/src/utils/errors.ts +64 -0
  256. package/src/utils/exec.ts +29 -0
  257. package/src/utils/ip.ts +31 -0
  258. package/src/utils/logger.ts +55 -0
  259. package/tsconfig.json +20 -0
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanupContractor = cleanupContractor;
4
+ const tmux_session_js_1 = require("./tmux-session.js");
5
+ const authorized_keys_js_1 = require("./authorized-keys.js");
6
+ const ssh_config_js_1 = require("./ssh-config.js");
7
+ const linux_user_js_1 = require("./linux-user.js");
8
+ const errors_js_1 = require("../utils/errors.js");
9
+ const logger_js_1 = require("../utils/logger.js");
10
+ const env_js_1 = require("../config/env.js");
11
+ /**
12
+ * Aggressive cleanup sequence for dismissing a contractor.
13
+ * Each step is independent and wrapped in try/catch — partial failures
14
+ * don't prevent the remaining steps from executing.
15
+ *
16
+ * Order matters:
17
+ * 1. Kill tmux session (with warning if connected)
18
+ * 2. Kill all user processes
19
+ * 3. Remove SSH pubkey
20
+ * 4. Remove ForceCommand from sshd_config
21
+ * 5. Reload sshd (happens inside removeForceCommand)
22
+ * 6. Lock the account
23
+ */
24
+ async function cleanupContractor(target) {
25
+ const { username, tmuxSession } = target;
26
+ const failures = [];
27
+ const env = (0, env_js_1.getEnv)();
28
+ logger_js_1.logger.info("Starting contractor cleanup", {
29
+ user: username,
30
+ session: tmuxSession,
31
+ });
32
+ // 1. Kill tmux session
33
+ try {
34
+ await (0, tmux_session_js_1.killSession)(tmuxSession, env.CLEANUP_WARNING_SECONDS);
35
+ }
36
+ catch (error) {
37
+ failures.push(`tmux kill: ${error}`);
38
+ logger_js_1.logger.warn("Cleanup: failed to kill tmux session", {
39
+ user: username,
40
+ error: String(error),
41
+ });
42
+ }
43
+ // 2. Kill all user processes
44
+ try {
45
+ await (0, linux_user_js_1.killUserProcesses)(username);
46
+ }
47
+ catch (error) {
48
+ failures.push(`kill processes: ${error}`);
49
+ logger_js_1.logger.warn("Cleanup: failed to kill user processes", {
50
+ user: username,
51
+ error: String(error),
52
+ });
53
+ }
54
+ // 3. Remove SSH pubkey
55
+ try {
56
+ await (0, authorized_keys_js_1.removeAuthorizedKey)(username);
57
+ }
58
+ catch (error) {
59
+ failures.push(`remove key: ${error}`);
60
+ logger_js_1.logger.warn("Cleanup: failed to remove authorized key", {
61
+ user: username,
62
+ error: String(error),
63
+ });
64
+ }
65
+ // 4. Remove ForceCommand (also reloads sshd)
66
+ try {
67
+ await (0, ssh_config_js_1.removeForceCommand)(username);
68
+ }
69
+ catch (error) {
70
+ failures.push(`remove ForceCommand: ${error}`);
71
+ logger_js_1.logger.warn("Cleanup: failed to remove ForceCommand", {
72
+ user: username,
73
+ error: String(error),
74
+ });
75
+ }
76
+ // 5. Lock account
77
+ try {
78
+ await (0, linux_user_js_1.lockUser)(username);
79
+ }
80
+ catch (error) {
81
+ failures.push(`lock user: ${error}`);
82
+ logger_js_1.logger.warn("Cleanup: failed to lock user", {
83
+ user: username,
84
+ error: String(error),
85
+ });
86
+ }
87
+ if (failures.length > 0) {
88
+ logger_js_1.logger.warn("Cleanup completed with partial failures", {
89
+ user: username,
90
+ failureCount: failures.length,
91
+ });
92
+ throw new errors_js_1.CleanupError(`Cleanup of ${username} had ${failures.length} failures`, failures);
93
+ }
94
+ logger_js_1.logger.info("Cleanup completed successfully", { user: username });
95
+ }
96
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../../../src/provisioning/cleanup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { createUser, lockUser, killUserProcesses } from "./linux-user.js";
2
+ export { writeAuthorizedKey, removeAuthorizedKey } from "./authorized-keys.js";
3
+ export { addForceCommand, removeForceCommand } from "./ssh-config.js";
4
+ export { sessionName, createSession, hasClientsAttached, sessionExists, displayMessage, killSession, getLastActivity, } from "./tmux-session.js";
5
+ export { cleanupContractor, type CleanupTarget } from "./cleanup.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/provisioning/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EACL,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,WAAW,EACX,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanupContractor = exports.getLastActivity = exports.killSession = exports.displayMessage = exports.sessionExists = exports.hasClientsAttached = exports.createSession = exports.sessionName = exports.removeForceCommand = exports.addForceCommand = exports.removeAuthorizedKey = exports.writeAuthorizedKey = exports.killUserProcesses = exports.lockUser = exports.createUser = void 0;
4
+ var linux_user_js_1 = require("./linux-user.js");
5
+ Object.defineProperty(exports, "createUser", { enumerable: true, get: function () { return linux_user_js_1.createUser; } });
6
+ Object.defineProperty(exports, "lockUser", { enumerable: true, get: function () { return linux_user_js_1.lockUser; } });
7
+ Object.defineProperty(exports, "killUserProcesses", { enumerable: true, get: function () { return linux_user_js_1.killUserProcesses; } });
8
+ var authorized_keys_js_1 = require("./authorized-keys.js");
9
+ Object.defineProperty(exports, "writeAuthorizedKey", { enumerable: true, get: function () { return authorized_keys_js_1.writeAuthorizedKey; } });
10
+ Object.defineProperty(exports, "removeAuthorizedKey", { enumerable: true, get: function () { return authorized_keys_js_1.removeAuthorizedKey; } });
11
+ var ssh_config_js_1 = require("./ssh-config.js");
12
+ Object.defineProperty(exports, "addForceCommand", { enumerable: true, get: function () { return ssh_config_js_1.addForceCommand; } });
13
+ Object.defineProperty(exports, "removeForceCommand", { enumerable: true, get: function () { return ssh_config_js_1.removeForceCommand; } });
14
+ var tmux_session_js_1 = require("./tmux-session.js");
15
+ Object.defineProperty(exports, "sessionName", { enumerable: true, get: function () { return tmux_session_js_1.sessionName; } });
16
+ Object.defineProperty(exports, "createSession", { enumerable: true, get: function () { return tmux_session_js_1.createSession; } });
17
+ Object.defineProperty(exports, "hasClientsAttached", { enumerable: true, get: function () { return tmux_session_js_1.hasClientsAttached; } });
18
+ Object.defineProperty(exports, "sessionExists", { enumerable: true, get: function () { return tmux_session_js_1.sessionExists; } });
19
+ Object.defineProperty(exports, "displayMessage", { enumerable: true, get: function () { return tmux_session_js_1.displayMessage; } });
20
+ Object.defineProperty(exports, "killSession", { enumerable: true, get: function () { return tmux_session_js_1.killSession; } });
21
+ Object.defineProperty(exports, "getLastActivity", { enumerable: true, get: function () { return tmux_session_js_1.getLastActivity; } });
22
+ var cleanup_js_1 = require("./cleanup.js");
23
+ Object.defineProperty(exports, "cleanupContractor", { enumerable: true, get: function () { return cleanup_js_1.cleanupContractor; } });
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/provisioning/index.ts"],"names":[],"mappings":";;;AAAA,iDAA0E;AAAjE,2GAAA,UAAU,OAAA;AAAE,yGAAA,QAAQ,OAAA;AAAE,kHAAA,iBAAiB,OAAA;AAChD,2DAA+E;AAAtE,wHAAA,kBAAkB,OAAA;AAAE,yHAAA,mBAAmB,OAAA;AAChD,iDAAsE;AAA7D,gHAAA,eAAe,OAAA;AAAE,mHAAA,kBAAkB,OAAA;AAC5C,qDAQ2B;AAPzB,8GAAA,WAAW,OAAA;AACX,gHAAA,aAAa,OAAA;AACb,qHAAA,kBAAkB,OAAA;AAClB,gHAAA,aAAa,OAAA;AACb,iHAAA,cAAc,OAAA;AACd,8GAAA,WAAW,OAAA;AACX,kHAAA,eAAe,OAAA;AAEjB,2CAAqE;AAA5D,+GAAA,iBAAiB,OAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Create a new Linux user for a contractor.
3
+ * Creates home directory and .ssh directory.
4
+ */
5
+ export declare function createUser(username: string): Promise<void>;
6
+ /**
7
+ * Lock a user account so they can no longer log in.
8
+ */
9
+ export declare function lockUser(username: string): Promise<void>;
10
+ /**
11
+ * Kill all processes owned by a user.
12
+ * Does not throw if user has no processes.
13
+ */
14
+ export declare function killUserProcesses(username: string): Promise<void>;
15
+ //# sourceMappingURL=linux-user.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux-user.d.ts","sourceRoot":"","sources":["../../../../src/provisioning/linux-user.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAehE;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9D;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvE"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createUser = createUser;
4
+ exports.lockUser = lockUser;
5
+ exports.killUserProcesses = killUserProcesses;
6
+ const privileged_js_1 = require("./privileged.js");
7
+ const errors_js_1 = require("../utils/errors.js");
8
+ const logger_js_1 = require("../utils/logger.js");
9
+ /**
10
+ * Create a new Linux user for a contractor.
11
+ * Creates home directory and .ssh directory.
12
+ */
13
+ async function createUser(username) {
14
+ try {
15
+ const u = shellEscape(username);
16
+ await (0, privileged_js_1.runPrivileged)(`useradd -m -s /bin/bash ${u}`);
17
+ await (0, privileged_js_1.runPrivileged)(`mkdir -p /home/${u}/.ssh && ` +
18
+ `chmod 700 /home/${u}/.ssh && ` +
19
+ `chown ${u}:${u} /home/${u}/.ssh`);
20
+ logger_js_1.logger.info("Linux user created", { user: username });
21
+ }
22
+ catch (error) {
23
+ throw new errors_js_1.ProvisioningError(`Failed to create user ${username}: ${error}`);
24
+ }
25
+ }
26
+ /**
27
+ * Lock a user account so they can no longer log in.
28
+ */
29
+ async function lockUser(username) {
30
+ try {
31
+ await (0, privileged_js_1.runPrivileged)(`usermod -L ${shellEscape(username)}`);
32
+ logger_js_1.logger.info("Linux user locked", { user: username });
33
+ }
34
+ catch (error) {
35
+ throw new errors_js_1.ProvisioningError(`Failed to lock user ${username}: ${error}`);
36
+ }
37
+ }
38
+ /**
39
+ * Kill all processes owned by a user.
40
+ * Does not throw if user has no processes.
41
+ */
42
+ async function killUserProcesses(username) {
43
+ try {
44
+ await (0, privileged_js_1.runPrivileged)(`pkill -u ${shellEscape(username)}`);
45
+ logger_js_1.logger.info("Killed processes for user", { user: username });
46
+ }
47
+ catch {
48
+ // pkill returns non-zero if no processes found — that's fine
49
+ logger_js_1.logger.debug("No processes to kill for user", { user: username });
50
+ }
51
+ }
52
+ /**
53
+ * Basic shell escaping to prevent injection.
54
+ * Only allows alphanumeric, hyphen, underscore.
55
+ */
56
+ function shellEscape(value) {
57
+ if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
58
+ throw new errors_js_1.ProvisioningError(`Invalid value for shell command: ${value}`);
59
+ }
60
+ return value;
61
+ }
62
+ //# sourceMappingURL=linux-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux-user.js","sourceRoot":"","sources":["../../../../src/provisioning/linux-user.ts"],"names":[],"mappings":";;AAQA,gCAeC;AAKD,4BASC;AAMD,8CAQC;AAnDD,mDAAgD;AAChD,kDAAuD;AACvD,kDAA4C;AAE5C;;;GAGG;AACI,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,IAAA,6BAAa,EAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,IAAA,6BAAa,EACjB,kBAAkB,CAAC,WAAW;YAC5B,mBAAmB,CAAC,WAAW;YAC/B,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CACpC,CAAC;QACF,kBAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,6BAAiB,CACzB,yBAAyB,QAAQ,KAAK,KAAK,EAAE,CAC9C,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,IAAI,CAAC;QACH,MAAM,IAAA,6BAAa,EAAC,cAAc,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC3D,kBAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,6BAAiB,CACzB,uBAAuB,QAAQ,KAAK,KAAK,EAAE,CAC5C,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IACtD,IAAI,CAAC;QACH,MAAM,IAAA,6BAAa,EAAC,YAAY,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACzD,kBAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,kBAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAGD;;;GAGG;AACH,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,6BAAiB,CACzB,oCAAoC,KAAK,EAAE,CAC5C,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Run a privileged shell command. With sudo enabled, the command
3
+ * is wrapped in `sudo -n bash -c '...'` so multi-step pipelines
4
+ * (`mkdir && chmod && chown`) still execute as root in one go.
5
+ */
6
+ export declare function runPrivileged(command: string): Promise<void>;
7
+ /**
8
+ * Run a shell command as a specific (non-root) user. Used for things
9
+ * like `tmux new-session` where the resulting object must be owned by
10
+ * the contractor, not root, so that the contractor's SSH login can
11
+ * attach to it.
12
+ *
13
+ * `sudo -u user` works whether the caller is root (no sudoers needed)
14
+ * or an unprivileged user with NOPASSWD configured for that target.
15
+ */
16
+ export declare function runAsUser(user: string, command: string): Promise<{
17
+ stdout: string;
18
+ stderr: string;
19
+ }>;
20
+ /**
21
+ * Read a file. Reads always go through Node fs — `/etc/ssh/sshd_config`
22
+ * is world-readable by default, so this rarely needs sudo. If a future
23
+ * deployment locks it down, we can revisit.
24
+ */
25
+ export declare function readPrivilegedFile(path: string): Promise<string>;
26
+ /**
27
+ * Write a file as root, regardless of which mode we're in.
28
+ * In sudo mode, content is piped through `sudo tee` and chmod runs
29
+ * separately.
30
+ */
31
+ export declare function writePrivilegedFile(path: string, content: string, mode?: number): Promise<void>;
32
+ /**
33
+ * Copy a file as root. Used by the sshd_config backup/restore flow.
34
+ */
35
+ export declare function copyPrivilegedFile(src: string, dst: string): Promise<void>;
36
+ /**
37
+ * `chown user:group path` as root.
38
+ */
39
+ export declare function chownPrivileged(owner: string, path: string): Promise<void>;
40
+ //# sourceMappingURL=privileged.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privileged.d.ts","sourceRoot":"","sources":["../../../../src/provisioning/privileged.ts"],"names":[],"mappings":"AA4BA;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlE;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAS7C;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhF;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhF"}
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runPrivileged = runPrivileged;
4
+ exports.runAsUser = runAsUser;
5
+ exports.readPrivilegedFile = readPrivilegedFile;
6
+ exports.writePrivilegedFile = writePrivilegedFile;
7
+ exports.copyPrivilegedFile = copyPrivilegedFile;
8
+ exports.chownPrivileged = chownPrivileged;
9
+ const promises_1 = require("node:fs/promises");
10
+ const exec_js_1 = require("../utils/exec.js");
11
+ const env_js_1 = require("../config/env.js");
12
+ /**
13
+ * Privileged operation helpers.
14
+ *
15
+ * Two modes, controlled by `PROVISIONING_USE_SUDO`:
16
+ *
17
+ * - `false` (default): the MCP server is running as root (e.g. `sudo
18
+ * claude` or a systemd service running as root). All commands and
19
+ * file operations execute directly through Node fs / child_process.
20
+ *
21
+ * - `true`: the MCP server is running as an unprivileged user that
22
+ * has NOPASSWD sudo for the specific commands listed in
23
+ * `human-layer/mcp-server/README.md`. All commands are prefixed
24
+ * with `sudo -n`, and file operations go through `sudo tee` /
25
+ * `sudo cp` so writes work even when the target file is owned by
26
+ * root.
27
+ *
28
+ * Centralising this in one module means the provisioning code stays
29
+ * readable and the sudo decision lives in exactly one place.
30
+ */
31
+ function useSudo() {
32
+ return (0, env_js_1.getEnv)().PROVISIONING_USE_SUDO;
33
+ }
34
+ /**
35
+ * Run a privileged shell command. With sudo enabled, the command
36
+ * is wrapped in `sudo -n bash -c '...'` so multi-step pipelines
37
+ * (`mkdir && chmod && chown`) still execute as root in one go.
38
+ */
39
+ async function runPrivileged(command) {
40
+ if (useSudo()) {
41
+ await (0, exec_js_1.exec)(`sudo -n bash -c ${shQuote(command)}`);
42
+ }
43
+ else {
44
+ await (0, exec_js_1.exec)(command);
45
+ }
46
+ }
47
+ /**
48
+ * Run a shell command as a specific (non-root) user. Used for things
49
+ * like `tmux new-session` where the resulting object must be owned by
50
+ * the contractor, not root, so that the contractor's SSH login can
51
+ * attach to it.
52
+ *
53
+ * `sudo -u user` works whether the caller is root (no sudoers needed)
54
+ * or an unprivileged user with NOPASSWD configured for that target.
55
+ */
56
+ async function runAsUser(user, command) {
57
+ if (!/^[a-zA-Z0-9_-]+$/.test(user)) {
58
+ throw new Error(`Invalid user name: ${user}`);
59
+ }
60
+ // We always go through sudo here. When running as root, no
61
+ // password / NOPASSWD is needed. When running as a regular user,
62
+ // they need NOPASSWD for `sudo -u <target>` (covered by the
63
+ // sudoers template in human-layer/mcp-server/README.md).
64
+ return (0, exec_js_1.exec)(`sudo -n -u ${user} bash -c ${shQuote(command)}`);
65
+ }
66
+ /**
67
+ * Read a file. Reads always go through Node fs — `/etc/ssh/sshd_config`
68
+ * is world-readable by default, so this rarely needs sudo. If a future
69
+ * deployment locks it down, we can revisit.
70
+ */
71
+ async function readPrivilegedFile(path) {
72
+ return (0, promises_1.readFile)(path, "utf-8");
73
+ }
74
+ /**
75
+ * Write a file as root, regardless of which mode we're in.
76
+ * In sudo mode, content is piped through `sudo tee` and chmod runs
77
+ * separately.
78
+ */
79
+ async function writePrivilegedFile(path, content, mode) {
80
+ if (useSudo()) {
81
+ // `tee` writes the file as root; we pipe the content via stdin
82
+ // by base64-encoding it to dodge any quoting hazards.
83
+ const b64 = Buffer.from(content, "utf-8").toString("base64");
84
+ await (0, exec_js_1.exec)(`bash -c ${shQuote(`echo ${b64} | base64 -d | sudo -n tee ${shQuote(path)} > /dev/null`)}`);
85
+ if (typeof mode === "number") {
86
+ await (0, exec_js_1.exec)(`sudo -n chmod ${mode.toString(8)} ${shQuote(path)}`);
87
+ }
88
+ }
89
+ else {
90
+ await (0, promises_1.writeFile)(path, content, mode != null ? { encoding: "utf-8", mode } : { encoding: "utf-8" });
91
+ }
92
+ }
93
+ /**
94
+ * Copy a file as root. Used by the sshd_config backup/restore flow.
95
+ */
96
+ async function copyPrivilegedFile(src, dst) {
97
+ if (useSudo()) {
98
+ await (0, exec_js_1.exec)(`sudo -n cp ${shQuote(src)} ${shQuote(dst)}`);
99
+ }
100
+ else {
101
+ await (0, promises_1.copyFile)(src, dst);
102
+ }
103
+ }
104
+ /**
105
+ * `chown user:group path` as root.
106
+ */
107
+ async function chownPrivileged(owner, path) {
108
+ // shellEscape-style guard to avoid injection through `owner`
109
+ if (!/^[a-zA-Z0-9_.:-]+$/.test(owner)) {
110
+ throw new Error(`Invalid owner spec: ${owner}`);
111
+ }
112
+ if (useSudo()) {
113
+ await (0, exec_js_1.exec)(`sudo -n chown ${owner} ${shQuote(path)}`);
114
+ }
115
+ else {
116
+ await (0, exec_js_1.exec)(`chown ${owner} ${shQuote(path)}`);
117
+ }
118
+ }
119
+ /** Quote a value for safe inclusion in a single-quoted bash string. */
120
+ function shQuote(value) {
121
+ return `'${value.replace(/'/g, "'\\''")}'`;
122
+ }
123
+ //# sourceMappingURL=privileged.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privileged.js","sourceRoot":"","sources":["../../../../src/provisioning/privileged.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Add a ForceCommand block to sshd_config for a contractor.
3
+ *
4
+ * Uses marker comments for deterministic insertion/removal:
5
+ * # BEGIN human-layer:{username}
6
+ * Match User {username}
7
+ * ForceCommand tmux attach -t {session} || tmux new -s {session}
8
+ * AllowTcpForwarding no
9
+ * X11Forwarding no
10
+ * # END human-layer:{username}
11
+ *
12
+ * CRITICAL: This is the highest-risk module in the system.
13
+ * Incorrect sshd_config means locked-out VMs.
14
+ * Always backup, validate with sshd -t, then reload.
15
+ */
16
+ export declare function addForceCommand(username: string, tmuxSession: string, configPath?: string): Promise<void>;
17
+ /**
18
+ * Remove the ForceCommand block for a contractor from sshd_config.
19
+ */
20
+ export declare function removeForceCommand(username: string, configPath?: string): Promise<void>;
21
+ //# sourceMappingURL=ssh-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-config.d.ts","sourceRoot":"","sources":["../../../../src/provisioning/ssh-config.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,UAAU,SAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAuDf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,UAAU,SAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addForceCommand = addForceCommand;
4
+ exports.removeForceCommand = removeForceCommand;
5
+ const privileged_js_1 = require("./privileged.js");
6
+ const errors_js_1 = require("../utils/errors.js");
7
+ const logger_js_1 = require("../utils/logger.js");
8
+ const defaults_js_1 = require("../config/defaults.js");
9
+ /**
10
+ * Add a ForceCommand block to sshd_config for a contractor.
11
+ *
12
+ * Uses marker comments for deterministic insertion/removal:
13
+ * # BEGIN human-layer:{username}
14
+ * Match User {username}
15
+ * ForceCommand tmux attach -t {session} || tmux new -s {session}
16
+ * AllowTcpForwarding no
17
+ * X11Forwarding no
18
+ * # END human-layer:{username}
19
+ *
20
+ * CRITICAL: This is the highest-risk module in the system.
21
+ * Incorrect sshd_config means locked-out VMs.
22
+ * Always backup, validate with sshd -t, then reload.
23
+ */
24
+ async function addForceCommand(username, tmuxSession, configPath = defaults_js_1.SSHD_CONFIG_PATH) {
25
+ const beginMarker = `${defaults_js_1.SSHD_MARKER_PREFIX}${username}`;
26
+ const endMarker = `${defaults_js_1.SSHD_MARKER_SUFFIX}${username}`;
27
+ const block = [
28
+ beginMarker,
29
+ `Match User ${username}`,
30
+ ` ForceCommand tmux attach -t ${tmuxSession} || tmux new -s ${tmuxSession}`,
31
+ " AllowTcpForwarding no",
32
+ " X11Forwarding no",
33
+ endMarker,
34
+ ].join("\n");
35
+ try {
36
+ // Backup current config
37
+ await (0, privileged_js_1.copyPrivilegedFile)(configPath, `${configPath}.bak`);
38
+ // Read current config
39
+ const current = await (0, privileged_js_1.readPrivilegedFile)(configPath);
40
+ // Remove existing block if present (idempotent)
41
+ const cleaned = removeBlock(current, beginMarker, endMarker);
42
+ // Append new block
43
+ const updated = cleaned.trimEnd() + "\n\n" + block + "\n";
44
+ // Write updated config
45
+ await (0, privileged_js_1.writePrivilegedFile)(configPath, updated);
46
+ // Validate with sshd -t
47
+ await validateSshdConfig(configPath);
48
+ // Reload sshd
49
+ await reloadSshd();
50
+ logger_js_1.logger.info("ForceCommand added to sshd_config", {
51
+ user: username,
52
+ session: tmuxSession,
53
+ });
54
+ }
55
+ catch (error) {
56
+ // Attempt to restore backup
57
+ try {
58
+ await (0, privileged_js_1.copyPrivilegedFile)(`${configPath}.bak`, configPath);
59
+ await reloadSshd();
60
+ logger_js_1.logger.warn("Restored sshd_config from backup after error");
61
+ }
62
+ catch (restoreError) {
63
+ logger_js_1.logger.error("CRITICAL: Failed to restore sshd_config backup", {
64
+ error: String(restoreError),
65
+ });
66
+ }
67
+ throw new errors_js_1.SshConfigError(`Failed to add ForceCommand for ${username}: ${error}`);
68
+ }
69
+ }
70
+ /**
71
+ * Remove the ForceCommand block for a contractor from sshd_config.
72
+ */
73
+ async function removeForceCommand(username, configPath = defaults_js_1.SSHD_CONFIG_PATH) {
74
+ const beginMarker = `${defaults_js_1.SSHD_MARKER_PREFIX}${username}`;
75
+ const endMarker = `${defaults_js_1.SSHD_MARKER_SUFFIX}${username}`;
76
+ try {
77
+ await (0, privileged_js_1.copyPrivilegedFile)(configPath, `${configPath}.bak`);
78
+ const current = await (0, privileged_js_1.readPrivilegedFile)(configPath);
79
+ const cleaned = removeBlock(current, beginMarker, endMarker);
80
+ await (0, privileged_js_1.writePrivilegedFile)(configPath, cleaned);
81
+ await validateSshdConfig(configPath);
82
+ await reloadSshd();
83
+ logger_js_1.logger.info("ForceCommand removed from sshd_config", {
84
+ user: username,
85
+ });
86
+ }
87
+ catch (error) {
88
+ try {
89
+ await (0, privileged_js_1.copyPrivilegedFile)(`${configPath}.bak`, configPath);
90
+ await reloadSshd();
91
+ }
92
+ catch {
93
+ logger_js_1.logger.error("CRITICAL: Failed to restore sshd_config backup");
94
+ }
95
+ throw new errors_js_1.SshConfigError(`Failed to remove ForceCommand for ${username}: ${error}`);
96
+ }
97
+ }
98
+ /**
99
+ * Remove a marker-delimited block from config text.
100
+ */
101
+ function removeBlock(content, beginMarker, endMarker) {
102
+ const lines = content.split("\n");
103
+ const result = [];
104
+ let inBlock = false;
105
+ for (const line of lines) {
106
+ if (line.trim() === beginMarker) {
107
+ inBlock = true;
108
+ continue;
109
+ }
110
+ if (line.trim() === endMarker) {
111
+ inBlock = false;
112
+ continue;
113
+ }
114
+ if (!inBlock) {
115
+ result.push(line);
116
+ }
117
+ }
118
+ return result.join("\n");
119
+ }
120
+ /**
121
+ * Validate sshd_config syntax. Throws if invalid.
122
+ */
123
+ async function validateSshdConfig(configPath = defaults_js_1.SSHD_CONFIG_PATH) {
124
+ try {
125
+ await (0, privileged_js_1.runPrivileged)(`sshd -t -f ${configPath}`);
126
+ }
127
+ catch (error) {
128
+ throw new errors_js_1.SshConfigError(`sshd_config validation failed: ${error}`);
129
+ }
130
+ }
131
+ /**
132
+ * Reload sshd to apply config changes.
133
+ *
134
+ * Tries `systemctl reload` first (the systemd path) and falls back to
135
+ * `service ssh reload` for environments without systemd (some WSL2
136
+ * distros, minimal containers).
137
+ */
138
+ async function reloadSshd() {
139
+ try {
140
+ await (0, privileged_js_1.runPrivileged)("systemctl reload sshd");
141
+ return;
142
+ }
143
+ catch {
144
+ /* fall through */
145
+ }
146
+ try {
147
+ await (0, privileged_js_1.runPrivileged)("systemctl reload ssh");
148
+ return;
149
+ }
150
+ catch {
151
+ /* fall through */
152
+ }
153
+ try {
154
+ await (0, privileged_js_1.runPrivileged)("service ssh reload");
155
+ return;
156
+ }
157
+ catch (error) {
158
+ throw new errors_js_1.SshConfigError(`Failed to reload sshd: ${error}`);
159
+ }
160
+ }
161
+ //# sourceMappingURL=ssh-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-config.js","sourceRoot":"","sources":["../../../../src/provisioning/ssh-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Generate a tmux session name for a gig.
3
+ */
4
+ export declare function sessionName(gigId: string): string;
5
+ /**
6
+ * Create a new tmux session **owned by the contractor user** so that
7
+ * sshd's ForceCommand (`tmux attach -t ...`) running as that user can
8
+ * see and attach to it.
9
+ *
10
+ * Without `runAsUser`, a tmux session created by the MCP server (root)
11
+ * is owned by root, and the contractor's later attach silently fails
12
+ * because tmux scopes sessions per-uid via the socket directory.
13
+ */
14
+ export declare function createSession(session: string, workdir: string, user?: string): Promise<void>;
15
+ /**
16
+ * Check if a tmux session has any clients attached.
17
+ * Used to detect if a contractor is currently connected.
18
+ */
19
+ export declare function hasClientsAttached(session: string): Promise<boolean>;
20
+ /**
21
+ * Check if a tmux session exists.
22
+ */
23
+ export declare function sessionExists(session: string): Promise<boolean>;
24
+ /**
25
+ * Send a display message to a tmux session.
26
+ * The message is shown as an overlay for the specified duration.
27
+ */
28
+ export declare function displayMessage(session: string, message: string, durationMs?: number): Promise<boolean>;
29
+ /**
30
+ * Kill a tmux session, optionally showing a warning first.
31
+ */
32
+ export declare function killSession(session: string, warningSeconds?: number): Promise<void>;
33
+ /**
34
+ * Get the last activity time for a session (if detectable).
35
+ */
36
+ export declare function getLastActivity(session: string): Promise<Date | undefined>;
37
+ //# sourceMappingURL=tmux-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux-session.d.ts","sourceRoot":"","sources":["../../../../src/provisioning/tmux-session.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ1E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,SAAS,GAClB,OAAO,CAAC,OAAO,CAAC,CAYlB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,cAAc,SAAI,GACjB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAa3B"}