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,319 +0,0 @@
1
- # Gateway Worker Specification
2
-
3
- > **Status: SPECIFICATION ONLY - NOT YET IMPLEMENTED**
4
- >
5
- > This document describes the planned Gateway Worker for subdomain routing and
6
- > authentication. The current implementation only includes the API Worker
7
- > (`api.gitspace.sh`) for user/subdomain management. The Gateway Worker
8
- > described here is Phase 2 of the platform architecture.
9
-
10
- ## Overview
11
-
12
- A Cloudflare Worker that sits in front of all user subdomains (`*.{user}.gitspace.sh`), providing:
13
- - Authentication via gitspace.sh GitHub OAuth
14
- - Authorization for shared services
15
- - Routing to appropriate Cloudflare Tunnels
16
-
17
- ## Why Not Cloudflare Access?
18
-
19
- Cloudflare Access:
20
- - Uses its own identity providers (separate OAuth flows)
21
- - Policies configured per-app in dashboard, not programmatically
22
- - Can't query our D1 database for ACL/invites
23
- - Can't validate our signed tokens
24
-
25
- We need:
26
- - Single identity across all gitspace.sh subdomains
27
- - Programmatic access control via our API
28
- - Custom authorization logic (invites, ACL, port sharing)
29
- - Portable session (one login works everywhere)
30
-
31
- ## Architecture
32
-
33
- ```
34
- ┌─────────────────────────────────────────────────────────────────────┐
35
- │ Cloudflare Edge │
36
- │ │
37
- │ Request: app.username.gitspace.sh │
38
- │ │ │
39
- │ ▼ │
40
- │ ┌────────────────────────────────────────────────────────────┐ │
41
- │ │ Gateway Worker │ │
42
- │ │ │ │
43
- │ │ 1. Parse: owner=username, service=app │ │
44
- │ │ 2. Validate session cookie (JWT signed by gitspace.sh) │ │
45
- │ │ 3. Check authorization (D1 query) │ │
46
- │ │ 4. Route to tunnel │ │
47
- │ │ │ │
48
- │ └────────────────────────────────────────────────────────────┘ │
49
- │ │ │
50
- │ ▼ │
51
- │ ┌──────────────────────────────────────────────────────────────┐ │
52
- │ │ Cloudflare Tunnel → User's Machine │ │
53
- │ └──────────────────────────────────────────────────────────────┘ │
54
- └─────────────────────────────────────────────────────────────────────┘
55
- ```
56
-
57
- ## URL Structure
58
-
59
- ```
60
- {service}.{owner}.gitspace.sh
61
-
62
- Examples:
63
- username.gitspace.sh → relay (default, terminal access)
64
- app.username.gitspace.sh → localhost:3000
65
- api.username.gitspace.sh → localhost:8080
66
- preview.username.gitspace.sh → localhost:5173
67
- ```
68
-
69
- ## Data Model
70
-
71
- ```sql
72
- -- Services (ports exposed under a subdomain)
73
- CREATE TABLE services (
74
- id TEXT PRIMARY KEY,
75
- subdomain_id TEXT REFERENCES subdomains(id),
76
- name TEXT NOT NULL, -- 'app', 'api', '' (root = relay)
77
- local_port INTEGER NOT NULL, -- 3000, 8080, 4480 (relay)
78
- visibility TEXT DEFAULT 'owner', -- 'public', 'owner', 'shared'
79
- created_at INTEGER,
80
- updated_at INTEGER,
81
-
82
- UNIQUE(subdomain_id, name)
83
- );
84
-
85
- -- Service access grants (for visibility='shared')
86
- CREATE TABLE service_access (
87
- id TEXT PRIMARY KEY,
88
- service_id TEXT REFERENCES services(id),
89
- user_id TEXT REFERENCES users(id), -- GitHub-authenticated user
90
- invite_token_hash TEXT, -- Alternative: invite-based access
91
- expires_at INTEGER,
92
- created_at INTEGER
93
- );
94
- ```
95
-
96
- ## Authentication
97
-
98
- ### Session Token (JWT)
99
-
100
- Issued by gitspace.sh after GitHub OAuth:
101
-
102
- ```typescript
103
- interface SessionToken {
104
- sub: string; // gitspace.sh user ID
105
- github_id: string; // GitHub user ID
106
- github_username: string;
107
- iat: number;
108
- exp: number;
109
- }
110
- ```
111
-
112
- Cookie settings:
113
- ```
114
- __gitspace_session=<jwt>
115
- Domain=.gitspace.sh // Works for all subdomains
116
- HttpOnly=true
117
- Secure=true
118
- SameSite=Lax
119
- ```
120
-
121
- ### Auth Flow
122
-
123
- **First visit (no session):**
124
- 1. User visits `app.username.gitspace.sh`
125
- 2. Gateway Worker: no valid session cookie
126
- 3. Redirect → `gitspace.sh/login?redirect=https://app.username.gitspace.sh`
127
- 4. User authenticates with GitHub
128
- 5. gitspace.sh sets session cookie on `.gitspace.sh`
129
- 6. Redirect back to original URL
130
- 7. Gateway Worker validates session, checks authorization
131
-
132
- **Return visit (has session):**
133
- 1. User visits `app.username.gitspace.sh`
134
- 2. Gateway Worker: session cookie present
135
- 3. Validate JWT signature and expiry
136
- 4. Query D1: does this user have access?
137
- 5. Forward to tunnel
138
-
139
- **Invite link (no login required):**
140
- 1. User visits `app.username.gitspace.sh?invite=xxx`
141
- 2. Gateway Worker: validate invite signature (Ed25519)
142
- 3. Valid → forward to tunnel
143
- 4. Optionally prompt to "claim" by logging in
144
-
145
- ## Authorization Logic
146
-
147
- ```typescript
148
- async function checkAccess(
149
- user: SessionUser | null,
150
- service: Service,
151
- inviteToken: string | null
152
- ): Promise<boolean> {
153
- // Public services: anyone
154
- if (service.visibility === 'public') {
155
- return true;
156
- }
157
-
158
- // Valid invite token: allow
159
- if (inviteToken && await validateInvite(inviteToken, service)) {
160
- return true;
161
- }
162
-
163
- // Must be logged in from here
164
- if (!user) {
165
- return false;
166
- }
167
-
168
- // Owner: always has access to their own services
169
- const subdomain = await getSubdomain(service.subdomain_id);
170
- if (subdomain.user_id === user.id) {
171
- return true;
172
- }
173
-
174
- // Shared: check access grants
175
- if (service.visibility === 'shared') {
176
- const grant = await getAccessGrant(service.id, user.id);
177
- return grant !== null && (grant.expires_at === null || grant.expires_at > Date.now());
178
- }
179
-
180
- return false;
181
- }
182
- ```
183
-
184
- ## Gateway Worker Implementation
185
-
186
- ```typescript
187
- // worker-gateway/src/index.ts
188
- export default {
189
- async fetch(request: Request, env: Env): Promise<Response> {
190
- const url = new URL(request.url);
191
- const host = url.hostname;
192
-
193
- // Parse subdomain: app.username.gitspace.sh
194
- const parsed = parseHost(host);
195
- if (!parsed) {
196
- return new Response('Invalid hostname', { status: 400 });
197
- }
198
-
199
- const { owner, serviceName } = parsed;
200
-
201
- // Lookup service in D1
202
- const service = await env.DB.prepare(`
203
- SELECT s.*, sub.user_id as owner_user_id, sub.tunnel_id
204
- FROM services s
205
- JOIN subdomains sub ON s.subdomain_id = sub.id
206
- WHERE sub.subdomain = ? AND s.name = ?
207
- `).bind(owner, serviceName || '').first();
208
-
209
- if (!service) {
210
- return new Response('Service not found', { status: 404 });
211
- }
212
-
213
- // Get session from cookie
214
- const sessionToken = getSessionCookie(request);
215
- const user = sessionToken ? await validateSession(sessionToken, env) : null;
216
-
217
- // Get invite from query param
218
- const inviteToken = url.searchParams.get('invite');
219
-
220
- // Check authorization
221
- const hasAccess = await checkAccess(user, service, inviteToken);
222
-
223
- if (!hasAccess) {
224
- // No session? Redirect to login
225
- if (!user) {
226
- const loginUrl = new URL('https://gitspace.sh/login');
227
- loginUrl.searchParams.set('redirect', request.url);
228
- return Response.redirect(loginUrl.toString(), 302);
229
- }
230
-
231
- // Has session but not authorized
232
- return new Response('Access denied', { status: 403 });
233
- }
234
-
235
- // Forward to tunnel
236
- // The tunnel is already configured with ingress rules
237
- // We just need to pass through the request
238
- return fetch(request);
239
- }
240
- }
241
- ```
242
-
243
- ## CLI Commands
244
-
245
- ```bash
246
- # Share a port as a service
247
- gssh share port 3000 --as app
248
- # Creates: app.username.gitspace.sh → localhost:3000
249
-
250
- # Share with specific user
251
- gssh share port 3000 --as app --with alice
252
- # Adds alice to service_access
253
-
254
- # Make public (no auth required)
255
- gssh share port 3000 --as app --public
256
-
257
- # List shared services
258
- gssh share list
259
- # app.username.gitspace.sh → :3000 (owner-only)
260
- # api.username.gitspace.sh → :8080 (shared: alice, bob)
261
- # preview.username.gitspace.sh → :5173 (public)
262
-
263
- # Stop sharing
264
- gssh share remove app
265
-
266
- # Grant access to existing service
267
- gssh share grant app --to bob
268
-
269
- # Revoke access
270
- gssh share revoke app --from bob
271
- ```
272
-
273
- ## Tunnel Configuration
274
-
275
- When a user shares a port, the tunnel ingress is updated:
276
-
277
- ```yaml
278
- ingress:
279
- - hostname: username.gitspace.sh
280
- service: http://localhost:4480 # relay
281
- - hostname: "*.username.gitspace.sh"
282
- service: http://localhost:4480 # default to relay
283
- - hostname: app.username.gitspace.sh
284
- service: http://localhost:3000 # specific service
285
- - service: http_status:404
286
- ```
287
-
288
- The Gateway Worker handles auth BEFORE the request reaches the tunnel.
289
-
290
- ## Migration Path
291
-
292
- ### Phase 1 (Current)
293
- - Relay-level auth only (signed messages + challenge-response)
294
- - No Gateway Worker
295
-
296
- ### Phase 2 (This Spec)
297
- - Deploy Gateway Worker
298
- - Session cookies via gitspace.sh OAuth
299
- - Owner-only access (prove you own the GitHub account)
300
-
301
- ### Phase 3 (Future)
302
- - Invite system for sharing with others
303
- - Service-level access grants
304
- - Port sharing CLI commands
305
-
306
- ## Security Considerations
307
-
308
- 1. **Session tokens** - Signed by gitspace.sh, validated at edge
309
- 2. **Invite tokens** - Ed25519 signed by service owner, time-limited
310
- 3. **Cookie scope** - `.gitspace.sh` allows SSO across all subdomains
311
- 4. **HTTPS only** - All traffic through Cloudflare, TLS enforced
312
- 5. **No secrets in Worker** - Only public keys for signature validation
313
-
314
- ## Open Questions
315
-
316
- 1. **Wildcard routing** - How to handle `*.username.gitspace.sh` efficiently?
317
- 2. **WebSocket support** - Gateway Worker must handle WS upgrade
318
- 3. **Rate limiting** - Per-user or per-service limits?
319
- 4. **Audit logging** - Track access for security/debugging?