gitspace 0.2.0-rc.2 → 0.2.0-rc.21

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 (316) hide show
  1. package/README.md +68 -38
  2. package/package.json +36 -25
  3. package/.claude/settings.local.json +0 -21
  4. package/.gitspace/bundle.json +0 -50
  5. package/.gitspace/select/01-status.sh +0 -40
  6. package/.gitspace/setup/01-install-deps.sh +0 -12
  7. package/.gitspace/setup/02-typecheck.sh +0 -16
  8. package/AGENTS.md +0 -439
  9. package/CLAUDE.md +0 -1
  10. package/bun.lock +0 -647
  11. package/docs/CONNECTION.md +0 -623
  12. package/docs/GATEWAY-WORKER.md +0 -319
  13. package/docs/GETTING-STARTED.md +0 -448
  14. package/docs/GITSPACE-PLATFORM.md +0 -1819
  15. package/docs/INFRASTRUCTURE.md +0 -1347
  16. package/docs/PROTOCOL.md +0 -619
  17. package/docs/QUICKSTART.md +0 -174
  18. package/docs/RELAY.md +0 -327
  19. package/docs/REMOTE-DESIGN.md +0 -549
  20. package/docs/ROADMAP.md +0 -564
  21. package/docs/SITE_DOCS_FIGMA_MAKE.md +0 -1167
  22. package/docs/STACK-DESIGN.md +0 -588
  23. package/docs/UNIFIED_ARCHITECTURE.md +0 -292
  24. package/experiments/pty-benchmark.ts +0 -148
  25. package/experiments/pty-latency.ts +0 -100
  26. package/experiments/router/client.ts +0 -199
  27. package/experiments/router/protocol.ts +0 -74
  28. package/experiments/router/router.ts +0 -217
  29. package/experiments/router/session.ts +0 -180
  30. package/experiments/router/test.ts +0 -133
  31. package/experiments/socket-bandwidth.ts +0 -77
  32. package/homebrew/gitspace.rb +0 -45
  33. package/landing-page/ATTRIBUTIONS.md +0 -3
  34. package/landing-page/README.md +0 -11
  35. package/landing-page/bun.lock +0 -801
  36. package/landing-page/guidelines/Guidelines.md +0 -61
  37. package/landing-page/index.html +0 -37
  38. package/landing-page/package.json +0 -90
  39. package/landing-page/postcss.config.mjs +0 -15
  40. package/landing-page/public/_redirects +0 -1
  41. package/landing-page/public/favicon.png +0 -0
  42. package/landing-page/src/app/App.tsx +0 -53
  43. package/landing-page/src/app/components/figma/ImageWithFallback.tsx +0 -27
  44. package/landing-page/src/app/components/ui/accordion.tsx +0 -66
  45. package/landing-page/src/app/components/ui/alert-dialog.tsx +0 -157
  46. package/landing-page/src/app/components/ui/alert.tsx +0 -66
  47. package/landing-page/src/app/components/ui/aspect-ratio.tsx +0 -11
  48. package/landing-page/src/app/components/ui/avatar.tsx +0 -53
  49. package/landing-page/src/app/components/ui/badge.tsx +0 -46
  50. package/landing-page/src/app/components/ui/breadcrumb.tsx +0 -109
  51. package/landing-page/src/app/components/ui/button.tsx +0 -57
  52. package/landing-page/src/app/components/ui/calendar.tsx +0 -75
  53. package/landing-page/src/app/components/ui/card.tsx +0 -92
  54. package/landing-page/src/app/components/ui/carousel.tsx +0 -241
  55. package/landing-page/src/app/components/ui/chart.tsx +0 -353
  56. package/landing-page/src/app/components/ui/checkbox.tsx +0 -32
  57. package/landing-page/src/app/components/ui/collapsible.tsx +0 -33
  58. package/landing-page/src/app/components/ui/command.tsx +0 -177
  59. package/landing-page/src/app/components/ui/context-menu.tsx +0 -252
  60. package/landing-page/src/app/components/ui/dialog.tsx +0 -135
  61. package/landing-page/src/app/components/ui/drawer.tsx +0 -132
  62. package/landing-page/src/app/components/ui/dropdown-menu.tsx +0 -257
  63. package/landing-page/src/app/components/ui/form.tsx +0 -168
  64. package/landing-page/src/app/components/ui/hover-card.tsx +0 -44
  65. package/landing-page/src/app/components/ui/input-otp.tsx +0 -77
  66. package/landing-page/src/app/components/ui/input.tsx +0 -21
  67. package/landing-page/src/app/components/ui/label.tsx +0 -24
  68. package/landing-page/src/app/components/ui/menubar.tsx +0 -276
  69. package/landing-page/src/app/components/ui/navigation-menu.tsx +0 -168
  70. package/landing-page/src/app/components/ui/pagination.tsx +0 -127
  71. package/landing-page/src/app/components/ui/popover.tsx +0 -48
  72. package/landing-page/src/app/components/ui/progress.tsx +0 -31
  73. package/landing-page/src/app/components/ui/radio-group.tsx +0 -45
  74. package/landing-page/src/app/components/ui/resizable.tsx +0 -56
  75. package/landing-page/src/app/components/ui/scroll-area.tsx +0 -58
  76. package/landing-page/src/app/components/ui/select.tsx +0 -189
  77. package/landing-page/src/app/components/ui/separator.tsx +0 -28
  78. package/landing-page/src/app/components/ui/sheet.tsx +0 -139
  79. package/landing-page/src/app/components/ui/sidebar.tsx +0 -726
  80. package/landing-page/src/app/components/ui/skeleton.tsx +0 -13
  81. package/landing-page/src/app/components/ui/slider.tsx +0 -63
  82. package/landing-page/src/app/components/ui/sonner.tsx +0 -25
  83. package/landing-page/src/app/components/ui/switch.tsx +0 -31
  84. package/landing-page/src/app/components/ui/table.tsx +0 -116
  85. package/landing-page/src/app/components/ui/tabs.tsx +0 -66
  86. package/landing-page/src/app/components/ui/textarea.tsx +0 -18
  87. package/landing-page/src/app/components/ui/toggle-group.tsx +0 -73
  88. package/landing-page/src/app/components/ui/toggle.tsx +0 -47
  89. package/landing-page/src/app/components/ui/tooltip.tsx +0 -61
  90. package/landing-page/src/app/components/ui/use-mobile.ts +0 -21
  91. package/landing-page/src/app/components/ui/utils.ts +0 -6
  92. package/landing-page/src/components/docs/DocsContent.tsx +0 -718
  93. package/landing-page/src/components/docs/DocsSidebar.tsx +0 -84
  94. package/landing-page/src/components/landing/CTA.tsx +0 -59
  95. package/landing-page/src/components/landing/Comparison.tsx +0 -84
  96. package/landing-page/src/components/landing/FaultyTerminal.tsx +0 -424
  97. package/landing-page/src/components/landing/Features.tsx +0 -201
  98. package/landing-page/src/components/landing/Hero.tsx +0 -142
  99. package/landing-page/src/components/landing/Pricing.tsx +0 -140
  100. package/landing-page/src/components/landing/Roadmap.tsx +0 -86
  101. package/landing-page/src/components/landing/Security.tsx +0 -81
  102. package/landing-page/src/components/landing/TerminalWindow.tsx +0 -27
  103. package/landing-page/src/components/landing/UseCases.tsx +0 -55
  104. package/landing-page/src/components/landing/Workflow.tsx +0 -101
  105. package/landing-page/src/components/layout/DashboardNavbar.tsx +0 -37
  106. package/landing-page/src/components/layout/Footer.tsx +0 -55
  107. package/landing-page/src/components/layout/LandingNavbar.tsx +0 -82
  108. package/landing-page/src/components/ui/badge.tsx +0 -39
  109. package/landing-page/src/components/ui/breadcrumb.tsx +0 -115
  110. package/landing-page/src/components/ui/button.tsx +0 -57
  111. package/landing-page/src/components/ui/card.tsx +0 -79
  112. package/landing-page/src/components/ui/mock-terminal.tsx +0 -68
  113. package/landing-page/src/components/ui/separator.tsx +0 -28
  114. package/landing-page/src/lib/utils.ts +0 -6
  115. package/landing-page/src/main.tsx +0 -10
  116. package/landing-page/src/pages/Dashboard.tsx +0 -133
  117. package/landing-page/src/pages/DocsPage.tsx +0 -79
  118. package/landing-page/src/pages/LandingPage.tsx +0 -31
  119. package/landing-page/src/pages/TerminalView.tsx +0 -106
  120. package/landing-page/src/styles/fonts.css +0 -0
  121. package/landing-page/src/styles/index.css +0 -3
  122. package/landing-page/src/styles/tailwind.css +0 -4
  123. package/landing-page/src/styles/theme.css +0 -181
  124. package/landing-page/vite.config.ts +0 -19
  125. package/npm/darwin-arm64/bin/gssh +0 -0
  126. package/npm/darwin-arm64/package.json +0 -20
  127. package/scripts/build.ts +0 -298
  128. package/scripts/release.ts +0 -140
  129. package/src/__tests__/test-utils.ts +0 -298
  130. package/src/commands/__tests__/serve-messages.test.ts +0 -190
  131. package/src/commands/access.ts +0 -298
  132. package/src/commands/add.ts +0 -452
  133. package/src/commands/auth.ts +0 -364
  134. package/src/commands/connect.ts +0 -287
  135. package/src/commands/directory.ts +0 -16
  136. package/src/commands/host.ts +0 -396
  137. package/src/commands/identity.ts +0 -184
  138. package/src/commands/list.ts +0 -200
  139. package/src/commands/relay.ts +0 -315
  140. package/src/commands/remove.ts +0 -241
  141. package/src/commands/serve.ts +0 -1493
  142. package/src/commands/share.ts +0 -456
  143. package/src/commands/status.ts +0 -125
  144. package/src/commands/switch.ts +0 -353
  145. package/src/commands/tmux.ts +0 -317
  146. package/src/core/__tests__/access.test.ts +0 -240
  147. package/src/core/access.ts +0 -277
  148. package/src/core/bundle.ts +0 -342
  149. package/src/core/config.ts +0 -510
  150. package/src/core/git.ts +0 -317
  151. package/src/core/github.ts +0 -151
  152. package/src/core/identity.ts +0 -631
  153. package/src/core/linear.ts +0 -225
  154. package/src/core/shell.ts +0 -161
  155. package/src/core/trusted-relays.ts +0 -315
  156. package/src/index.ts +0 -810
  157. package/src/lib/remote-session/index.ts +0 -7
  158. package/src/lib/remote-session/protocol.ts +0 -267
  159. package/src/lib/remote-session/session-handler.ts +0 -581
  160. package/src/lib/remote-session/workspace-scanner.ts +0 -167
  161. package/src/lib/tmux-lite/README.md +0 -81
  162. package/src/lib/tmux-lite/cli.ts +0 -796
  163. package/src/lib/tmux-lite/crypto/__tests__/helpers/handshake-runner.ts +0 -349
  164. package/src/lib/tmux-lite/crypto/__tests__/helpers/mock-relay.ts +0 -291
  165. package/src/lib/tmux-lite/crypto/__tests__/helpers/test-identities.ts +0 -142
  166. package/src/lib/tmux-lite/crypto/__tests__/integration/authorization.integration.test.ts +0 -339
  167. package/src/lib/tmux-lite/crypto/__tests__/integration/e2e-communication.integration.test.ts +0 -477
  168. package/src/lib/tmux-lite/crypto/__tests__/integration/error-handling.integration.test.ts +0 -499
  169. package/src/lib/tmux-lite/crypto/__tests__/integration/handshake.integration.test.ts +0 -371
  170. package/src/lib/tmux-lite/crypto/__tests__/integration/security.integration.test.ts +0 -573
  171. package/src/lib/tmux-lite/crypto/access-control.test.ts +0 -512
  172. package/src/lib/tmux-lite/crypto/access-control.ts +0 -320
  173. package/src/lib/tmux-lite/crypto/frames.test.ts +0 -262
  174. package/src/lib/tmux-lite/crypto/frames.ts +0 -141
  175. package/src/lib/tmux-lite/crypto/handshake.ts +0 -894
  176. package/src/lib/tmux-lite/crypto/identity.test.ts +0 -220
  177. package/src/lib/tmux-lite/crypto/identity.ts +0 -286
  178. package/src/lib/tmux-lite/crypto/index.ts +0 -51
  179. package/src/lib/tmux-lite/crypto/invites.test.ts +0 -381
  180. package/src/lib/tmux-lite/crypto/invites.ts +0 -215
  181. package/src/lib/tmux-lite/crypto/keyexchange.ts +0 -435
  182. package/src/lib/tmux-lite/crypto/keys.test.ts +0 -58
  183. package/src/lib/tmux-lite/crypto/keys.ts +0 -47
  184. package/src/lib/tmux-lite/crypto/secretbox.test.ts +0 -169
  185. package/src/lib/tmux-lite/crypto/secretbox.ts +0 -124
  186. package/src/lib/tmux-lite/handshake-handler.ts +0 -451
  187. package/src/lib/tmux-lite/protocol.test.ts +0 -307
  188. package/src/lib/tmux-lite/protocol.ts +0 -266
  189. package/src/lib/tmux-lite/relay-client.ts +0 -506
  190. package/src/lib/tmux-lite/server.ts +0 -1250
  191. package/src/lib/tmux-lite/shell-integration.sh +0 -37
  192. package/src/lib/tmux-lite/terminal-queries.test.ts +0 -54
  193. package/src/lib/tmux-lite/terminal-queries.ts +0 -49
  194. package/src/relay/__tests__/e2e-flow.test.ts +0 -1284
  195. package/src/relay/__tests__/helpers/auth.ts +0 -354
  196. package/src/relay/__tests__/helpers/ports.ts +0 -51
  197. package/src/relay/__tests__/protocol-validation.test.ts +0 -265
  198. package/src/relay/authorization.ts +0 -303
  199. package/src/relay/embedded-assets.generated.d.ts +0 -15
  200. package/src/relay/identity.ts +0 -352
  201. package/src/relay/index.ts +0 -57
  202. package/src/relay/pipes.test.ts +0 -427
  203. package/src/relay/pipes.ts +0 -195
  204. package/src/relay/protocol.ts +0 -804
  205. package/src/relay/registries.test.ts +0 -437
  206. package/src/relay/registries.ts +0 -593
  207. package/src/relay/server.test.ts +0 -1323
  208. package/src/relay/server.ts +0 -1092
  209. package/src/relay/signing.ts +0 -238
  210. package/src/relay/types.ts +0 -69
  211. package/src/serve/client-session-manager.ts +0 -622
  212. package/src/serve/daemon.ts +0 -497
  213. package/src/serve/pty-session.ts +0 -236
  214. package/src/serve/types.ts +0 -169
  215. package/src/shared/components/Flow.tsx +0 -453
  216. package/src/shared/components/Flow.tui.tsx +0 -343
  217. package/src/shared/components/Flow.web.tsx +0 -442
  218. package/src/shared/components/Inbox.tsx +0 -446
  219. package/src/shared/components/Inbox.tui.tsx +0 -262
  220. package/src/shared/components/Inbox.web.tsx +0 -329
  221. package/src/shared/components/MachineList.tsx +0 -187
  222. package/src/shared/components/MachineList.tui.tsx +0 -161
  223. package/src/shared/components/MachineList.web.tsx +0 -210
  224. package/src/shared/components/ProjectList.tsx +0 -176
  225. package/src/shared/components/ProjectList.tui.tsx +0 -109
  226. package/src/shared/components/ProjectList.web.tsx +0 -143
  227. package/src/shared/components/SpacesBrowser.tsx +0 -332
  228. package/src/shared/components/SpacesBrowser.tui.tsx +0 -163
  229. package/src/shared/components/SpacesBrowser.web.tsx +0 -221
  230. package/src/shared/components/index.ts +0 -103
  231. package/src/shared/hooks/index.ts +0 -16
  232. package/src/shared/hooks/useNavigation.ts +0 -226
  233. package/src/shared/index.ts +0 -122
  234. package/src/shared/providers/LocalMachineProvider.ts +0 -425
  235. package/src/shared/providers/MachineProvider.ts +0 -165
  236. package/src/shared/providers/RemoteMachineProvider.ts +0 -444
  237. package/src/shared/providers/index.ts +0 -26
  238. package/src/shared/types.ts +0 -145
  239. package/src/tui/adapters.ts +0 -120
  240. package/src/tui/app.tsx +0 -1816
  241. package/src/tui/components/Terminal.tsx +0 -580
  242. package/src/tui/hooks/index.ts +0 -35
  243. package/src/tui/hooks/useAppState.ts +0 -314
  244. package/src/tui/hooks/useDaemonStatus.ts +0 -174
  245. package/src/tui/hooks/useInboxTUI.ts +0 -113
  246. package/src/tui/hooks/useRemoteMachines.ts +0 -209
  247. package/src/tui/index.ts +0 -24
  248. package/src/tui/state.ts +0 -299
  249. package/src/tui/terminal-bracketed-paste.test.ts +0 -45
  250. package/src/tui/terminal-bracketed-paste.ts +0 -47
  251. package/src/types/bundle.ts +0 -112
  252. package/src/types/config.ts +0 -89
  253. package/src/types/errors.ts +0 -206
  254. package/src/types/identity.ts +0 -284
  255. package/src/types/workspace-fuzzy.ts +0 -49
  256. package/src/types/workspace.ts +0 -151
  257. package/src/utils/bun-socket-writer.ts +0 -80
  258. package/src/utils/deps.ts +0 -127
  259. package/src/utils/fuzzy-match.ts +0 -125
  260. package/src/utils/logger.ts +0 -127
  261. package/src/utils/markdown.ts +0 -254
  262. package/src/utils/onboarding.ts +0 -229
  263. package/src/utils/prompts.ts +0 -114
  264. package/src/utils/run-commands.ts +0 -112
  265. package/src/utils/run-scripts.ts +0 -142
  266. package/src/utils/sanitize.ts +0 -98
  267. package/src/utils/secrets.ts +0 -122
  268. package/src/utils/shell-escape.ts +0 -40
  269. package/src/utils/utf8.ts +0 -79
  270. package/src/utils/workspace-state.ts +0 -47
  271. package/src/web/README.md +0 -73
  272. package/src/web/bun.lock +0 -575
  273. package/src/web/eslint.config.js +0 -23
  274. package/src/web/index.html +0 -16
  275. package/src/web/package.json +0 -37
  276. package/src/web/public/vite.svg +0 -1
  277. package/src/web/src/App.tsx +0 -604
  278. package/src/web/src/assets/react.svg +0 -1
  279. package/src/web/src/components/Terminal.tsx +0 -207
  280. package/src/web/src/hooks/useRelayConnection.ts +0 -224
  281. package/src/web/src/hooks/useTerminal.ts +0 -699
  282. package/src/web/src/index.css +0 -55
  283. package/src/web/src/lib/crypto/__tests__/web-terminal.test.ts +0 -1158
  284. package/src/web/src/lib/crypto/frames.ts +0 -205
  285. package/src/web/src/lib/crypto/handshake.ts +0 -396
  286. package/src/web/src/lib/crypto/identity.ts +0 -128
  287. package/src/web/src/lib/crypto/keyexchange.ts +0 -246
  288. package/src/web/src/lib/crypto/relay-signing.ts +0 -53
  289. package/src/web/src/lib/invite.ts +0 -58
  290. package/src/web/src/lib/storage/identity-store.ts +0 -94
  291. package/src/web/src/main.tsx +0 -10
  292. package/src/web/src/types/identity.ts +0 -45
  293. package/src/web/tsconfig.app.json +0 -28
  294. package/src/web/tsconfig.json +0 -7
  295. package/src/web/tsconfig.node.json +0 -26
  296. package/src/web/vite.config.ts +0 -31
  297. package/todo-security.md +0 -92
  298. package/tsconfig.json +0 -23
  299. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite +0 -0
  300. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite-shm +0 -0
  301. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite-wal +0 -0
  302. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite +0 -0
  303. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite-shm +0 -0
  304. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite-wal +0 -0
  305. package/worker/bun.lock +0 -237
  306. package/worker/package.json +0 -22
  307. package/worker/schema.sql +0 -96
  308. package/worker/src/handlers/auth.ts +0 -451
  309. package/worker/src/handlers/subdomains.ts +0 -376
  310. package/worker/src/handlers/user.ts +0 -98
  311. package/worker/src/index.ts +0 -70
  312. package/worker/src/middleware/auth.ts +0 -152
  313. package/worker/src/services/cloudflare.ts +0 -609
  314. package/worker/src/types.ts +0 -96
  315. package/worker/tsconfig.json +0 -15
  316. package/worker/wrangler.toml +0 -26
@@ -1,236 +0,0 @@
1
- // @ts-nocheck - Uses Bun-specific APIs (Bun.Terminal)
2
- /**
3
- * PTY session wrapper for remote terminal access
4
- *
5
- * Wraps Bun.Terminal to provide:
6
- * - Encrypted frame I/O using session keys
7
- * - Resize handling with SIGWINCH
8
- * - Clean lifecycle management
9
- */
10
-
11
- import { createFrame, openFrame } from "../lib/tmux-lite/crypto/frames.js";
12
- import { decodeControl, type SessionCtrl } from "../lib/tmux-lite/protocol.js";
13
- import type { SessionKeys } from "../types/identity.js";
14
- import { STREAM_ID } from "./types.js";
15
-
16
- // ============================================================================
17
- // Types
18
- // ============================================================================
19
-
20
- /** PTY session options */
21
- export interface PTYSessionOptions {
22
- /** Shell to spawn (default: $SHELL or /bin/bash) */
23
- shell?: string;
24
- /** Working directory */
25
- cwd?: string;
26
- /** Environment variables */
27
- env?: Record<string, string>;
28
- /** Initial terminal columns */
29
- cols?: number;
30
- /** Initial terminal rows */
31
- rows?: number;
32
- /** Session encryption keys */
33
- sessionKeys: SessionKeys;
34
- /** Callback for encrypted output data */
35
- onData: (encrypted: Buffer) => void;
36
- /** Callback when PTY exits */
37
- onClose: (exitCode: number) => void;
38
- }
39
-
40
- // ============================================================================
41
- // PTYSession Class
42
- // ============================================================================
43
-
44
- /**
45
- * Manages a PTY session with encrypted I/O
46
- *
47
- * @example
48
- * ```typescript
49
- * const pty = new PTYSession({
50
- * sessionKeys,
51
- * onData: (encrypted) => relay.send(connectionId, encrypted),
52
- * onClose: (code) => console.log(`Exit: ${code}`),
53
- * });
54
- *
55
- * // Write encrypted input from client
56
- * pty.write(encryptedFrame);
57
- *
58
- * // Handle resize
59
- * pty.resize(120, 40);
60
- *
61
- * // Clean up
62
- * pty.close();
63
- * ```
64
- */
65
- export class PTYSession {
66
- private terminal: ReturnType<typeof Bun.Terminal> | null = null;
67
- private proc: ReturnType<typeof Bun.spawn> | null = null;
68
- private sendKey: Uint8Array;
69
- private receiveKey: Uint8Array;
70
- private onData: (encrypted: Buffer) => void;
71
- private onClose: (exitCode: number) => void;
72
- private closed = false;
73
-
74
- constructor(options: PTYSessionOptions) {
75
- this.sendKey = options.sessionKeys.sendKey;
76
- this.receiveKey = options.sessionKeys.receiveKey;
77
- this.onData = options.onData;
78
- this.onClose = options.onClose;
79
-
80
- const shell = options.shell ?? process.env.SHELL ?? "/bin/bash";
81
- const cwd = options.cwd ?? process.env.HOME ?? "/";
82
- const cols = options.cols ?? 80;
83
- const rows = options.rows ?? 24;
84
-
85
- // Build environment
86
- const env: Record<string, string> = {
87
- ...process.env as Record<string, string>,
88
- ...options.env,
89
- TERM: "xterm-256color",
90
- SPACES_REMOTE: "true",
91
- };
92
-
93
- // Create PTY terminal
94
- this.terminal = new Bun.Terminal({
95
- cols,
96
- rows,
97
- data: (_term: unknown, data: Uint8Array) => {
98
- if (this.closed) return;
99
-
100
- // Encrypt and send output
101
- const frame = createFrame(STREAM_ID.DATA, data, this.sendKey);
102
- this.onData(frame);
103
- },
104
- });
105
-
106
- // Spawn shell process
107
- this.proc = Bun.spawn([shell], {
108
- terminal: this.terminal,
109
- cwd,
110
- env,
111
- });
112
-
113
- // Handle process exit
114
- this.proc.exited.then((code) => {
115
- if (!this.closed) {
116
- this.closed = true;
117
- this.onClose(code);
118
- }
119
- });
120
- }
121
-
122
- /**
123
- * Get the process ID
124
- */
125
- get pid(): number | undefined {
126
- return this.proc?.pid;
127
- }
128
-
129
- /**
130
- * Check if session is closed
131
- */
132
- get isClosed(): boolean {
133
- return this.closed;
134
- }
135
-
136
- /**
137
- * Write encrypted input data to PTY
138
- *
139
- * Decrypts the frame and writes plaintext to stdin.
140
- *
141
- * @param encryptedFrame - Encrypted frame from client
142
- * @returns True if write succeeded, false on decryption failure
143
- */
144
- write(encryptedFrame: Buffer | Uint8Array): boolean {
145
- if (this.closed || !this.terminal) return false;
146
-
147
- const result = openFrame(Buffer.from(encryptedFrame), this.receiveKey);
148
- if (!result) {
149
- console.warn("[pty-session] Failed to decrypt input frame");
150
- return false;
151
- }
152
-
153
- // Check stream ID
154
- if (result.streamId === STREAM_ID.CONTROL) {
155
- // Handle control message
156
- this.handleControlMessage(result.data);
157
- return true;
158
- }
159
-
160
- // Write data to PTY stdin
161
- this.terminal.write(result.data);
162
- return true;
163
- }
164
-
165
- /**
166
- * Handle control messages (resize, etc.)
167
- * Uses tmux-lite SessionCtrl format for consistency
168
- */
169
- private handleControlMessage(data: Buffer): void {
170
- try {
171
- const msg = decodeControl(data) as SessionCtrl;
172
-
173
- switch (msg.type) {
174
- case "resize":
175
- this.resize(msg.cols, msg.rows);
176
- break;
177
- case "detach":
178
- // Detach is handled at a higher level, ignore here
179
- break;
180
- case "attach-init":
181
- // attach-init doesn't apply to PTYSession (already started)
182
- break;
183
- default:
184
- console.warn("[pty-session] Unknown control message:", msg);
185
- }
186
- } catch (e) {
187
- console.warn("[pty-session] Invalid control message:", e);
188
- }
189
- }
190
-
191
- /**
192
- * Resize the PTY
193
- *
194
- * @param cols - Number of columns
195
- * @param rows - Number of rows
196
- */
197
- resize(cols: number, rows: number): void {
198
- if (this.closed || !this.terminal || !this.proc) return;
199
-
200
- try {
201
- this.terminal.resize(cols, rows);
202
- // Send SIGWINCH to process group so child processes get it
203
- try {
204
- process.kill(-this.proc.pid, "SIGWINCH");
205
- } catch {
206
- // Fallback to direct signal if process group fails
207
- try {
208
- process.kill(this.proc.pid, "SIGWINCH");
209
- } catch {
210
- // Process may have exited
211
- }
212
- }
213
- } catch (e) {
214
- console.warn("[pty-session] Resize failed:", e);
215
- }
216
- }
217
-
218
- /**
219
- * Close the PTY session
220
- *
221
- * Kills the process and cleans up resources.
222
- */
223
- close(): void {
224
- if (this.closed) return;
225
- this.closed = true;
226
-
227
- try {
228
- this.proc?.kill();
229
- } catch {
230
- // Already exited
231
- }
232
-
233
- this.terminal = null;
234
- this.proc = null;
235
- }
236
- }
@@ -1,169 +0,0 @@
1
- /**
2
- * Types for the gssh serve command
3
- *
4
- * Defines configuration, session state, and events for the machine-side daemon.
5
- */
6
-
7
- import type { PTYSession } from "./pty-session.js";
8
- import type { Identity, SessionKeys, AccessType } from "../types/identity.js";
9
- import type { AccessControlList } from "../lib/tmux-lite/crypto/access-control.js";
10
- import { FrameType } from "../lib/tmux-lite/protocol.js";
11
-
12
- // ============================================================================
13
- // Permission Helpers
14
- // ============================================================================
15
-
16
- /**
17
- * Check if an access type grants write permission (terminal input)
18
- *
19
- * Only 'full' access allows writing to the terminal.
20
- * 'session-invite' is read-only.
21
- */
22
- export function canWrite(accessType: AccessType | undefined): boolean {
23
- return accessType === 'full';
24
- }
25
-
26
- /**
27
- * Check if an access type grants management permission
28
- *
29
- * Management includes: create/kill sessions, delete workspaces, etc.
30
- * Only 'full' access allows management operations.
31
- */
32
- export function canManage(accessType: AccessType | undefined): boolean {
33
- return accessType === 'full';
34
- }
35
-
36
- /**
37
- * Check if a client can attach to a specific session
38
- *
39
- * - 'full' access can attach to any session
40
- * - 'session-invite' can only attach to the specific session they were invited to
41
- */
42
- export function canAttachSession(
43
- accessType: AccessType | undefined,
44
- grantedSessionId: string | undefined,
45
- targetSessionId: string
46
- ): boolean {
47
- if (accessType === 'full') return true;
48
- if (accessType === 'session-invite') {
49
- return grantedSessionId === targetSessionId;
50
- }
51
- return false;
52
- }
53
-
54
- // ============================================================================
55
- // Configuration Types
56
- // ============================================================================
57
-
58
- /** Configuration for the serve command */
59
- export interface ServeOptions {
60
- /** Relay WebSocket URL */
61
- relay: string;
62
- /** Machine identity for authentication */
63
- identity: Identity;
64
- /** Access control list for authorized clients */
65
- accessList: AccessControlList;
66
- /** Shell to spawn (default: $SHELL or /bin/bash) */
67
- shell?: string;
68
- /** Extra environment variables for PTY sessions */
69
- env?: Record<string, string>;
70
- /** Handshake timeout in milliseconds (default: 30000) */
71
- handshakeTimeoutMs?: number;
72
- }
73
-
74
- // ============================================================================
75
- // Session Types
76
- // ============================================================================
77
-
78
- /** State of a client session */
79
- export type ClientSessionState = "handshaking" | "browsing" | "attached" | "closed";
80
-
81
- /** Client session data */
82
- export interface ClientSession {
83
- /** Unique connection ID from relay */
84
- connectionId: string;
85
- /** Current session state */
86
- state: ClientSessionState;
87
- /** When handshake started (Unix ms) */
88
- handshakeStartedAt: number;
89
- /** PTY session (created after attach_session) - legacy, use tmuxSocket instead */
90
- ptySession?: PTYSession;
91
- /** tmux-lite session socket connection */
92
- tmuxSocket?: Awaited<ReturnType<typeof Bun.connect>>;
93
- /** Buffered writer for tmux-lite socket (Bun sockets can partially write under backpressure) */
94
- tmuxSocketWriter?: {
95
- write(data: Buffer | Uint8Array | ArrayBuffer): void;
96
- flush(): void;
97
- clear(): void;
98
- };
99
- /** Path to tmux-lite session socket */
100
- sessionSocketPath?: string;
101
- /** Session encryption keys */
102
- sessionKeys?: SessionKeys;
103
- /** Granted access type */
104
- accessType?: AccessType;
105
- /** Session ID for session-invite access */
106
- sessionId?: string;
107
- /** Peer's identity ID */
108
- peerIdentityId?: string;
109
- /** Attached tmux-lite session ID (when state === "attached") */
110
- attachedSessionId?: string;
111
- /** True if waiting for initial resize before sending attach-init */
112
- waitingForResize?: boolean;
113
- /** Buffer for incomplete frames from tmux-lite socket */
114
- frameBuffer?: Buffer;
115
- }
116
-
117
- // ============================================================================
118
- // Stream IDs (for encrypted relay framing)
119
- // ============================================================================
120
- //
121
- // Stream IDs align with FrameType from tmux-lite protocol:
122
- // - DATA (0) = FrameType.PTY: raw terminal bytes
123
- // - CONTROL (1) = FrameType.CONTROL: JSON control messages (resize, detach, etc.)
124
- //
125
- // See src/lib/tmux-lite/protocol.ts for SessionCtrl/SessionEvent types.
126
-
127
- /** Stream IDs for frame routing - aligned with FrameType */
128
- export const STREAM_ID = {
129
- /** Terminal data stream (same as FrameType.PTY) */
130
- DATA: FrameType.PTY,
131
- /** Control messages (same as FrameType.CONTROL) */
132
- CONTROL: FrameType.CONTROL,
133
- } as const;
134
-
135
- // ============================================================================
136
- // Event Types
137
- // ============================================================================
138
-
139
- /** Events emitted by the serve daemon */
140
- export type ServeEvent =
141
- | { type: "client_connected"; connectionId: string }
142
- | { type: "client_authenticated"; connectionId: string; identityId: string; accessType: AccessType; sessionId?: string }
143
- | { type: "client_disconnected"; connectionId: string; reason: string }
144
- | { type: "relay_connected" }
145
- | { type: "relay_disconnected"; code: number; reason: string }
146
- | { type: "relay_reconnecting"; attempt: number }
147
- | { type: "error"; connectionId?: string; error: Error };
148
-
149
- /** Event handler for serve events */
150
- export type ServeEventHandler = (event: ServeEvent) => void;
151
-
152
- // ============================================================================
153
- // Relay Protocol Types
154
- // ============================================================================
155
-
156
- /** Envelope for messages from relay (includes routing info) */
157
- export interface RelayEnvelope {
158
- /** Connection ID for routing */
159
- connectionId: string;
160
- /** Raw message data */
161
- data: Uint8Array;
162
- }
163
-
164
- /** Handshake message envelope */
165
- export interface HandshakeMessageEnvelope {
166
- type: "handshake";
167
- phase: "client_hello" | "server_hello" | "client_auth" | "server_auth";
168
- data: unknown;
169
- }