openship 0.1.0 → 0.1.1

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 (531) hide show
  1. package/.env.example +19 -3
  2. package/CONTRIBUTING.md +69 -19
  3. package/LICENSE +661 -0
  4. package/README.md +304 -108
  5. package/apps/api/Dockerfile +6 -8
  6. package/apps/api/package.json +25 -21
  7. package/apps/api/src/app.ts +46 -3
  8. package/apps/api/src/config/env.ts +81 -7
  9. package/apps/api/src/lib/auth-mode.ts +42 -0
  10. package/apps/api/src/lib/auth.ts +105 -0
  11. package/apps/api/src/lib/cache.ts +128 -0
  12. package/apps/api/src/lib/cloud-auth-proxy.ts +310 -0
  13. package/apps/api/src/lib/cloud-client.ts +103 -0
  14. package/apps/api/src/lib/compose-parser.ts +138 -0
  15. package/apps/api/src/lib/controller-helpers.ts +90 -0
  16. package/apps/api/src/lib/email-templates.ts +94 -0
  17. package/apps/api/src/lib/encryption.ts +102 -0
  18. package/apps/api/src/lib/local-user.ts +65 -0
  19. package/apps/api/src/lib/mail.ts +48 -0
  20. package/apps/api/src/lib/notifications.ts +195 -0
  21. package/apps/api/src/lib/openship-cloud.ts +101 -0
  22. package/apps/api/src/lib/resources.ts +96 -0
  23. package/apps/api/src/lib/screenshots.ts +189 -0
  24. package/apps/api/src/lib/ssh-manager.ts +369 -0
  25. package/apps/api/src/lib/ssl-scheduler.ts +109 -0
  26. package/apps/api/src/lib/stack-detector.ts +708 -0
  27. package/apps/api/src/lib/system-debug.ts +10 -0
  28. package/apps/api/src/middleware/auth.ts +49 -13
  29. package/apps/api/src/middleware/error-handler.ts +23 -3
  30. package/apps/api/src/middleware/index.ts +2 -0
  31. package/apps/api/src/middleware/internal-auth.ts +40 -0
  32. package/apps/api/src/middleware/local-only.ts +20 -0
  33. package/apps/api/src/middleware/rate-limiter.ts +9 -0
  34. package/apps/api/src/modules/analytics/analytics.controller.ts +111 -0
  35. package/apps/api/src/modules/analytics/analytics.routes.ts +29 -0
  36. package/apps/api/src/modules/analytics/analytics.schema.ts +37 -0
  37. package/apps/api/src/modules/analytics/analytics.service.ts +264 -0
  38. package/apps/api/src/modules/auth/auth.routes.ts +233 -6
  39. package/apps/api/src/modules/billing/billing.routes.ts +8 -0
  40. package/apps/api/src/modules/cloud/cloud.controller.ts +225 -0
  41. package/apps/api/src/modules/cloud/cloud.routes.ts +40 -0
  42. package/apps/api/src/modules/deployments/build.service.ts +791 -0
  43. package/apps/api/src/modules/deployments/deployment-lifecycle.ts +138 -0
  44. package/apps/api/src/modules/deployments/deployment.controller.ts +324 -16
  45. package/apps/api/src/modules/deployments/deployment.routes.ts +33 -7
  46. package/apps/api/src/modules/deployments/deployment.schema.ts +37 -5
  47. package/apps/api/src/modules/deployments/deployment.service.ts +178 -11
  48. package/apps/api/src/modules/deployments/preflight.ts +280 -0
  49. package/apps/api/src/modules/deployments/prepare.service.ts +252 -0
  50. package/apps/api/src/modules/deployments/session-manager.ts +283 -0
  51. package/apps/api/src/modules/deployments/ssl.service.ts +73 -0
  52. package/apps/api/src/modules/domains/domain.controller.ts +59 -7
  53. package/apps/api/src/modules/domains/domain.routes.ts +20 -5
  54. package/apps/api/src/modules/domains/domain.schema.ts +35 -0
  55. package/apps/api/src/modules/domains/domain.service.ts +375 -9
  56. package/apps/api/src/modules/github/github.auth.ts +397 -0
  57. package/apps/api/src/modules/github/github.controller.ts +387 -0
  58. package/apps/api/src/modules/github/github.local-auth.ts +251 -0
  59. package/apps/api/src/modules/github/github.routes.ts +50 -0
  60. package/apps/api/src/modules/github/github.schema.ts +52 -0
  61. package/apps/api/src/modules/github/github.service.ts +592 -0
  62. package/apps/api/src/modules/github/github.types.ts +158 -0
  63. package/apps/api/src/modules/github/github.webhook.ts +186 -0
  64. package/apps/api/src/modules/github/index.ts +16 -0
  65. package/apps/api/src/modules/health/health.routes.ts +35 -0
  66. package/apps/api/src/modules/projects/project.controller.ts +481 -12
  67. package/apps/api/src/modules/projects/project.routes.ts +63 -6
  68. package/apps/api/src/modules/projects/project.schema.ts +104 -6
  69. package/apps/api/src/modules/projects/project.service.ts +502 -11
  70. package/apps/api/src/modules/settings/settings.controller.ts +55 -0
  71. package/apps/api/src/modules/settings/settings.routes.ts +25 -0
  72. package/apps/api/src/modules/settings/settings.service.ts +49 -0
  73. package/apps/api/src/modules/system/filesystem.controller.ts +66 -0
  74. package/apps/api/src/modules/system/index.ts +1 -0
  75. package/apps/api/src/modules/system/server-check.controller.ts +475 -0
  76. package/apps/api/src/modules/system/setup-session.ts +255 -0
  77. package/apps/api/src/modules/system/setup.controller.ts +128 -0
  78. package/apps/api/src/modules/system/system.routes.ts +42 -0
  79. package/apps/api/src/modules/webhooks/webhook.controller.ts +57 -15
  80. package/apps/api/src/modules/webhooks/webhook.routes.ts +11 -8
  81. package/apps/api/src/modules/webhooks/webhook.service.ts +46 -5
  82. package/apps/api/src/modules/webhooks/webhook.types.ts +35 -0
  83. package/apps/api/tsconfig.json +3 -1
  84. package/apps/cli/package.json +8 -10
  85. package/apps/cli/tsconfig.json +2 -1
  86. package/apps/dashboard/Dockerfile +4 -6
  87. package/apps/dashboard/components.json +20 -0
  88. package/apps/dashboard/next-env.d.ts +6 -0
  89. package/apps/dashboard/next.config.mjs +11 -1
  90. package/apps/dashboard/package.json +25 -13
  91. package/apps/dashboard/postcss.config.mjs +5 -0
  92. package/apps/dashboard/public/android-chrome-192x192.png +0 -0
  93. package/apps/dashboard/public/android-chrome-512x512.png +0 -0
  94. package/apps/dashboard/public/apple-touch-icon.png +0 -0
  95. package/apps/dashboard/public/favicon-16x16.png +0 -0
  96. package/apps/dashboard/public/favicon-32x32.png +0 -0
  97. package/apps/dashboard/public/favicon.ico +0 -0
  98. package/apps/dashboard/public/site.webmanifest +19 -0
  99. package/apps/dashboard/src/app/(auth)/forgot-password/page.tsx +114 -0
  100. package/apps/dashboard/src/app/(auth)/layout.tsx +18 -3
  101. package/apps/dashboard/src/app/(auth)/login/page.tsx +215 -6
  102. package/apps/dashboard/src/app/(auth)/providers.tsx +34 -0
  103. package/apps/dashboard/src/app/(auth)/register/page.tsx +171 -5
  104. package/apps/dashboard/src/app/(auth)/reset-password/page.tsx +172 -0
  105. package/apps/dashboard/src/app/(auth)/verify-email/page.tsx +190 -0
  106. package/apps/dashboard/src/app/(dashboard)/(deployment)/build/[id]/page.tsx +162 -0
  107. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/BuildSummary.tsx +166 -0
  108. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DnsConfiguration.tsx +119 -0
  109. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DomainSettings.tsx +291 -0
  110. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Header.tsx +71 -0
  111. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Sidebar.tsx +270 -0
  112. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/SkeletonLoader.tsx +87 -0
  113. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/page.tsx +169 -0
  114. package/apps/dashboard/src/app/(dashboard)/(deployment)/layout.tsx +7 -0
  115. package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +1 -8
  116. package/apps/dashboard/src/app/(dashboard)/deployments/components/CommitDetailsModal.tsx +240 -0
  117. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentCard.tsx +121 -0
  118. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentHeader.tsx +89 -0
  119. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentMenu.tsx +182 -0
  120. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsContent.tsx +324 -0
  121. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsFilters.tsx +99 -0
  122. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsList.tsx +31 -0
  123. package/apps/dashboard/src/app/(dashboard)/deployments/components/EmptyState.tsx +101 -0
  124. package/apps/dashboard/src/app/(dashboard)/deployments/components/LoadingSkeleton.tsx +57 -0
  125. package/apps/dashboard/src/app/(dashboard)/deployments/components/ProjectFilter.tsx +109 -0
  126. package/apps/dashboard/src/app/(dashboard)/deployments/components/index.ts +9 -0
  127. package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +9 -3
  128. package/apps/dashboard/src/app/(dashboard)/deployments/types.ts +44 -0
  129. package/apps/dashboard/src/app/(dashboard)/deployments/utils.ts +176 -0
  130. package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +1 -6
  131. package/apps/dashboard/src/app/(dashboard)/integrations/page.tsx +321 -0
  132. package/apps/dashboard/src/app/(dashboard)/layout.tsx +22 -32
  133. package/apps/dashboard/src/app/(dashboard)/library/components/ConnectPrompt.tsx +187 -0
  134. package/apps/dashboard/src/app/(dashboard)/library/components/LibrarySidebar.tsx +147 -0
  135. package/apps/dashboard/src/app/(dashboard)/library/components/LoadingSkeleton.tsx +39 -0
  136. package/apps/dashboard/src/app/(dashboard)/library/components/LocalProjects.tsx +548 -0
  137. package/apps/dashboard/src/app/(dashboard)/library/components/RepositoryList.tsx +292 -0
  138. package/apps/dashboard/src/app/(dashboard)/library/components/TemplateGrid.tsx +36 -0
  139. package/apps/dashboard/src/app/(dashboard)/library/components/UrlImport.tsx +74 -0
  140. package/apps/dashboard/src/app/(dashboard)/library/page.tsx +121 -0
  141. package/apps/dashboard/src/app/(dashboard)/library/types.ts +26 -0
  142. package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +1 -6
  143. package/apps/dashboard/src/app/(dashboard)/page.tsx +485 -0
  144. package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/layout.tsx +22 -0
  145. package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/page.tsx +286 -0
  146. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/AdvancedSettings.tsx +235 -0
  147. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/BuildSettings.tsx +174 -0
  148. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeleteConfirmationDialog.tsx +45 -0
  149. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeletionModal.tsx +95 -0
  150. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/Deployments.tsx +11 -0
  151. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DomainSettings.tsx +523 -0
  152. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/EnvironmentSettings.tsx +246 -0
  153. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GeneralSettings.tsx +93 -0
  154. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitInfo.tsx +261 -0
  155. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitSettings.tsx +391 -0
  156. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/LogsSettings.tsx +133 -0
  157. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectNotFound.tsx +95 -0
  158. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectsBottomNavigation.tsx +62 -0
  159. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ResourceSettings.tsx +333 -0
  160. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingSection.tsx +66 -0
  161. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingsNavigation.tsx +27 -0
  162. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SleepModeSettings.tsx +134 -0
  163. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProductionUrl.tsx +25 -0
  164. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectIdentity.tsx +159 -0
  165. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectInfo.tsx +58 -0
  166. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/SkeletonLoader.tsx +170 -0
  167. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/StatsCards.tsx +33 -0
  168. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TopPaths.tsx +56 -0
  169. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TrafficChart.tsx +157 -0
  170. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/index.ts +14 -0
  171. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/LogsActions.tsx +52 -0
  172. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/ServerLogs.tsx +249 -0
  173. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/TerminalLogs.tsx +682 -0
  174. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/logs.css +127 -0
  175. package/apps/dashboard/src/app/(dashboard)/projects/components/DeploymentCard.tsx +73 -0
  176. package/apps/dashboard/src/app/(dashboard)/projects/components/ProjectCard.tsx +330 -0
  177. package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +326 -4
  178. package/apps/dashboard/src/app/(dashboard)/providers.tsx +23 -0
  179. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/components-tab.tsx +329 -0
  180. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/overview-tab.tsx +229 -0
  181. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/terminal-tab.tsx +38 -0
  182. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/page.tsx +437 -0
  183. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/checking-state.tsx +15 -0
  184. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/choose-mode.tsx +54 -0
  185. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/component-row.tsx +65 -0
  186. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/error-banner.tsx +13 -0
  187. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/installing-panel.tsx +227 -0
  188. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/results-panel.tsx +90 -0
  189. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/setup-header.tsx +56 -0
  190. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/types.ts +13 -0
  191. package/apps/dashboard/src/app/(dashboard)/servers/new/page.tsx +666 -0
  192. package/apps/dashboard/src/app/(dashboard)/servers/page.tsx +283 -0
  193. package/apps/dashboard/src/app/(dashboard)/settings/_components/BuildPreferences.tsx +110 -0
  194. package/apps/dashboard/src/app/(dashboard)/settings/_components/CloudConnection.tsx +147 -0
  195. package/apps/dashboard/src/app/(dashboard)/settings/_components/InstanceInfo.tsx +54 -0
  196. package/apps/dashboard/src/app/(dashboard)/settings/_components/ServerConnection.tsx +407 -0
  197. package/apps/dashboard/src/app/(dashboard)/settings/_components/SettingsSection.tsx +32 -0
  198. package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +62 -3
  199. package/apps/dashboard/src/app/auth/callback/close/page.tsx +23 -0
  200. package/apps/dashboard/src/app/auth/callback/install/page.tsx +40 -0
  201. package/apps/dashboard/src/app/authorize/page.tsx +137 -0
  202. package/apps/dashboard/src/app/globals.css +57 -3
  203. package/apps/dashboard/src/app/layout.tsx +43 -3
  204. package/apps/dashboard/src/components/auth-shell.tsx +66 -0
  205. package/apps/dashboard/src/components/deployments/types.ts +44 -0
  206. package/apps/dashboard/src/components/global-deployments/index.ts +17 -0
  207. package/apps/dashboard/src/components/i18n-provider.tsx +100 -0
  208. package/apps/dashboard/src/components/import-project/BuildSettings.tsx +376 -0
  209. package/apps/dashboard/src/components/import-project/BuildSkeleton.tsx +161 -0
  210. package/apps/dashboard/src/components/import-project/BuildTerminal.tsx +358 -0
  211. package/apps/dashboard/src/components/import-project/ComposeServices.tsx +455 -0
  212. package/apps/dashboard/src/components/import-project/DeploymentProcessing.tsx +510 -0
  213. package/apps/dashboard/src/components/import-project/DockerSettings.tsx +64 -0
  214. package/apps/dashboard/src/components/import-project/EnvironmentVariables.tsx +481 -0
  215. package/apps/dashboard/src/components/import-project/Frameworks.tsx +90 -0
  216. package/apps/dashboard/src/components/import-project/ProjectSettings.tsx +160 -0
  217. package/apps/dashboard/src/components/import-project/types.ts +82 -0
  218. package/apps/dashboard/src/components/integrations/GithubPermissionModal.tsx +173 -0
  219. package/apps/dashboard/src/components/language-switcher.tsx +36 -0
  220. package/apps/dashboard/src/components/logo.tsx +13 -0
  221. package/apps/dashboard/src/components/network-error-handler.tsx +27 -0
  222. package/apps/dashboard/src/components/oauth-buttons.tsx +81 -0
  223. package/apps/dashboard/src/components/overview/ActivityChart.tsx +247 -0
  224. package/apps/dashboard/src/components/overview/ApiRequestsCard.tsx +111 -0
  225. package/apps/dashboard/src/components/overview/CreditsCard.tsx +137 -0
  226. package/apps/dashboard/src/components/overview/DeploymentsChart.tsx +195 -0
  227. package/apps/dashboard/src/components/overview/EmptyState.tsx +126 -0
  228. package/apps/dashboard/src/components/overview/LoadingSkeleton.tsx +92 -0
  229. package/apps/dashboard/src/components/overview/OverviewHeader.tsx +74 -0
  230. package/apps/dashboard/src/components/overview/OverviewHeroChart.tsx +344 -0
  231. package/apps/dashboard/src/components/overview/ProjectsCard.tsx +134 -0
  232. package/apps/dashboard/src/components/overview/QuickLinks.tsx +119 -0
  233. package/apps/dashboard/src/components/overview/SandboxesCard.tsx +150 -0
  234. package/apps/dashboard/src/components/overview/StatsGrid.tsx +166 -0
  235. package/apps/dashboard/src/components/overview/TokenUsageChart.tsx +206 -0
  236. package/apps/dashboard/src/components/overview/UsageStats.tsx +79 -0
  237. package/apps/dashboard/src/components/overview/index.ts +30 -0
  238. package/apps/dashboard/src/components/overview/types.ts +116 -0
  239. package/apps/dashboard/src/components/page-header.tsx +25 -0
  240. package/apps/dashboard/src/components/project-settings/ServerSideSwitch.jsx +60 -0
  241. package/apps/dashboard/src/components/shared/AlertBox.tsx +39 -0
  242. package/apps/dashboard/src/components/shared/CTASection.tsx +45 -0
  243. package/apps/dashboard/src/components/shared/ErrorState.tsx +176 -0
  244. package/apps/dashboard/src/components/shared/FeatureCard.tsx +20 -0
  245. package/apps/dashboard/src/components/shared/MDXComponents.tsx +24 -0
  246. package/apps/dashboard/src/components/shared/MachineSettingsModal.tsx +286 -0
  247. package/apps/dashboard/src/components/shared/Modal.tsx +39 -0
  248. package/apps/dashboard/src/components/shared/OTPInput.tsx +122 -0
  249. package/apps/dashboard/src/components/shared/PageHero.tsx +21 -0
  250. package/apps/dashboard/src/components/shared/PlatformFeatureCard.tsx +27 -0
  251. package/apps/dashboard/src/components/shared/StatCard.tsx +14 -0
  252. package/apps/dashboard/src/components/shared/ValueCard.tsx +20 -0
  253. package/apps/dashboard/src/components/shared/index.ts +8 -0
  254. package/apps/dashboard/src/components/sidebar.tsx +282 -0
  255. package/apps/dashboard/src/components/theme-provider.tsx +96 -0
  256. package/apps/dashboard/src/components/toast.tsx +106 -0
  257. package/apps/dashboard/src/components/ui/CustomCursor.tsx +107 -0
  258. package/apps/dashboard/src/components/ui/CustomSelect.tsx +126 -0
  259. package/apps/dashboard/src/components/ui/DropdownMenu.tsx +174 -0
  260. package/apps/dashboard/src/components/ui/FileIcon.jsx +59 -0
  261. package/apps/dashboard/src/components/ui/IconPickerModal.tsx +273 -0
  262. package/apps/dashboard/src/components/ui/InfoBanner.jsx +39 -0
  263. package/apps/dashboard/src/components/ui/Logo.tsx +14 -0
  264. package/apps/dashboard/src/components/ui/Modal.tsx +117 -0
  265. package/apps/dashboard/src/components/ui/PageContainer.tsx +12 -0
  266. package/apps/dashboard/src/components/ui/SectionContainer.jsx +7 -0
  267. package/apps/dashboard/src/components/ui/SlidingToggle.tsx +128 -0
  268. package/apps/dashboard/src/components/ui/Toast.tsx +29 -0
  269. package/apps/dashboard/src/components/ui/button.tsx +58 -0
  270. package/apps/dashboard/src/components/ui/card.tsx +60 -0
  271. package/apps/dashboard/src/components/ui/input.tsx +20 -0
  272. package/apps/dashboard/src/components/ui/label.tsx +19 -0
  273. package/apps/dashboard/src/components/ui/select.tsx +10 -0
  274. package/apps/dashboard/src/components/ui/textarea.tsx +9 -0
  275. package/apps/dashboard/src/constants/lang-colors.ts +25 -0
  276. package/apps/dashboard/src/constants/mock.ts +38 -0
  277. package/apps/dashboard/src/context/AuthContext.tsx +91 -0
  278. package/apps/dashboard/src/context/CloudContext.tsx +275 -0
  279. package/apps/dashboard/src/context/DeploymentContext.tsx +71 -0
  280. package/apps/dashboard/src/context/GitHubContext.tsx +288 -0
  281. package/apps/dashboard/src/context/ModalContext.tsx +300 -0
  282. package/apps/dashboard/src/context/NetworkContext.tsx +32 -0
  283. package/apps/dashboard/src/context/ProjectSettingsContext.tsx +727 -0
  284. package/apps/dashboard/src/context/ToastContext.tsx +129 -0
  285. package/apps/dashboard/src/context/deployment/index.ts +3 -0
  286. package/apps/dashboard/src/context/deployment/types.ts +183 -0
  287. package/apps/dashboard/src/context/deployment/useDeploymentBuild.ts +547 -0
  288. package/apps/dashboard/src/context/deployment/useDeploymentConfig.ts +176 -0
  289. package/apps/dashboard/src/hooks/useBuildConnection.ts +334 -0
  290. package/apps/dashboard/src/hooks/useMonitorStream.ts +146 -0
  291. package/apps/dashboard/src/hooks/useProjectData.ts +110 -0
  292. package/apps/dashboard/src/hooks/useSSEConnection.ts +465 -0
  293. package/apps/dashboard/src/hooks/useSSEStream.ts +309 -0
  294. package/apps/dashboard/src/hooks/useSessions.ts +104 -0
  295. package/apps/dashboard/src/hooks/useSetupStream.ts +223 -0
  296. package/apps/dashboard/src/i18n/dictionaries/ar.json +218 -0
  297. package/apps/dashboard/src/i18n/dictionaries/en.json +218 -0
  298. package/apps/dashboard/src/i18n/index.ts +16 -0
  299. package/apps/dashboard/src/lib/api/ai.ts +22 -0
  300. package/apps/dashboard/src/lib/api/auth.ts +13 -0
  301. package/apps/dashboard/src/lib/api/client.ts +199 -0
  302. package/apps/dashboard/src/lib/api/cloud.ts +15 -0
  303. package/apps/dashboard/src/lib/api/deploy.ts +58 -0
  304. package/apps/dashboard/src/lib/api/domains.ts +13 -0
  305. package/apps/dashboard/src/lib/api/endpoints.ts +129 -0
  306. package/apps/dashboard/src/lib/api/github.ts +31 -0
  307. package/apps/dashboard/src/lib/api/icons.ts +12 -0
  308. package/apps/dashboard/src/lib/api/index.ts +41 -0
  309. package/apps/dashboard/src/lib/api/projects.ts +153 -0
  310. package/apps/dashboard/src/lib/api/sandbox.ts +14 -0
  311. package/apps/dashboard/src/lib/api/settings.ts +21 -0
  312. package/apps/dashboard/src/lib/api/system.ts +159 -0
  313. package/apps/dashboard/src/lib/auth-client.ts +54 -0
  314. package/apps/dashboard/src/lib/country.ts +25 -0
  315. package/apps/dashboard/src/lib/server/api.ts +140 -0
  316. package/apps/dashboard/src/lib/server/session.ts +103 -0
  317. package/apps/dashboard/src/lib/sseClient.ts +241 -0
  318. package/apps/dashboard/src/lib/sseMessageProcessors.ts +323 -0
  319. package/apps/dashboard/src/lib/utils.ts +6 -0
  320. package/apps/dashboard/src/proxy.ts +46 -0
  321. package/apps/dashboard/src/styles/Toast.module.css +92 -0
  322. package/apps/dashboard/src/styles/fonts.css +93 -0
  323. package/apps/dashboard/src/styles/theme.css +336 -0
  324. package/apps/dashboard/src/types/research.ts +42 -0
  325. package/apps/dashboard/src/utils/SSEParser.js +150 -0
  326. package/apps/dashboard/src/utils/authWindow.ts +143 -0
  327. package/apps/dashboard/src/utils/codeTheme.ts +127 -0
  328. package/apps/dashboard/src/utils/colors.json +2810 -0
  329. package/apps/dashboard/src/utils/date.ts +121 -0
  330. package/apps/dashboard/src/utils/deployment.ts +128 -0
  331. package/apps/dashboard/src/utils/deploymentPhaseDetector.ts +232 -0
  332. package/apps/dashboard/src/utils/extToLang.js +103 -0
  333. package/apps/dashboard/src/utils/github.ts +62 -0
  334. package/apps/dashboard/src/utils/icons.js +46 -0
  335. package/apps/dashboard/src/utils/repoSlug.ts +110 -0
  336. package/apps/dashboard/src/utils/research-api.ts +163 -0
  337. package/apps/dashboard/src/utils/suggestions.ts +84 -0
  338. package/apps/dashboard/src/utils/theme.js +1 -0
  339. package/apps/dashboard/src/utils/ui-helpers.tsx +30 -0
  340. package/apps/dashboard/src/utils/upload.js +12 -0
  341. package/apps/dashboard/tsconfig.json +27 -5
  342. package/apps/desktop/forge.config.json +36 -0
  343. package/apps/desktop/package.json +26 -0
  344. package/apps/desktop/scripts/dev.mjs +58 -0
  345. package/apps/desktop/src/main/index.ts +675 -0
  346. package/apps/desktop/src/main/types/desktop.d.ts +33 -0
  347. package/apps/desktop/src/preload/index.ts +88 -0
  348. package/apps/desktop/src/renderer/index.html +462 -0
  349. package/apps/desktop/src/renderer/onboarding.js +511 -0
  350. package/apps/desktop/src/renderer/styles.css +1139 -0
  351. package/apps/desktop/tsconfig.json +17 -0
  352. package/apps/web/.source/browser.ts +13 -0
  353. package/apps/web/.source/dynamic.ts +8 -0
  354. package/apps/web/.source/server.ts +22 -0
  355. package/apps/web/.source/source.config.mjs +20 -0
  356. package/apps/web/Dockerfile +4 -6
  357. package/apps/web/content/blog/how-ai-builds-work.mdx +55 -0
  358. package/apps/web/content/blog/introducing-openship.mdx +46 -0
  359. package/apps/web/content/blog/self-hosting-cost-breakdown.mdx +59 -0
  360. package/apps/web/content/docs/_meta.json +14 -0
  361. package/apps/web/content/docs/api.mdx +98 -0
  362. package/apps/web/content/docs/cli.mdx +80 -0
  363. package/apps/web/content/docs/first-deployment.mdx +56 -0
  364. package/apps/web/content/docs/index.mdx +27 -0
  365. package/apps/web/content/docs/installation.mdx +65 -0
  366. package/apps/web/content/docs/quickstart.mdx +45 -0
  367. package/apps/web/next-env.d.ts +6 -0
  368. package/apps/web/next.config.mjs +16 -2
  369. package/apps/web/package.json +19 -12
  370. package/apps/web/postcss.config.mjs +5 -0
  371. package/apps/web/public/android-chrome-192x192.png +0 -0
  372. package/apps/web/public/android-chrome-512x512.png +0 -0
  373. package/apps/web/public/apple-touch-icon.png +0 -0
  374. package/apps/web/public/favicon-16x16.png +0 -0
  375. package/apps/web/public/favicon-32x32.png +0 -0
  376. package/apps/web/public/favicon.ico +0 -0
  377. package/apps/web/public/site.webmanifest +1 -0
  378. package/apps/web/source.config.ts +17 -0
  379. package/apps/web/src/app/(marketing)/layout.tsx +7 -22
  380. package/apps/web/src/app/blog/[...slug]/page.tsx +247 -0
  381. package/apps/web/src/app/blog/blog.css +575 -0
  382. package/apps/web/src/app/blog/layout.tsx +50 -0
  383. package/apps/web/src/app/blog/page.tsx +235 -0
  384. package/apps/web/src/app/docs/[[...slug]]/page.tsx +67 -0
  385. package/apps/web/src/app/docs/layout.tsx +62 -0
  386. package/apps/web/src/app/docs/toc-theme.css +71 -0
  387. package/apps/web/src/app/download/page.tsx +396 -0
  388. package/apps/web/src/app/globals.css +20 -3
  389. package/apps/web/src/app/layout.tsx +57 -3
  390. package/apps/web/src/app/page.tsx +47 -6
  391. package/apps/web/src/app/robots.ts +15 -0
  392. package/apps/web/src/app/sitemap.ts +35 -0
  393. package/apps/web/src/components/blog/share-sidebar.tsx +81 -0
  394. package/apps/web/src/components/blog/writer-sidebar.tsx +81 -0
  395. package/apps/web/src/components/landing/ai-native.tsx +169 -0
  396. package/apps/web/src/components/landing/backups.tsx +139 -0
  397. package/apps/web/src/components/landing/cdn.tsx +109 -0
  398. package/apps/web/src/components/landing/coming-soon.tsx +180 -0
  399. package/apps/web/src/components/landing/dark-section.tsx +166 -0
  400. package/apps/web/src/components/landing/dashboard.tsx +407 -0
  401. package/apps/web/src/components/landing/developer-experience.tsx +224 -0
  402. package/apps/web/src/components/landing/dns-domains.tsx +146 -0
  403. package/apps/web/src/components/landing/download-button.tsx +151 -0
  404. package/apps/web/src/components/landing/features/ai-visual.tsx +48 -0
  405. package/apps/web/src/components/landing/features/cloud-visual.tsx +44 -0
  406. package/apps/web/src/components/landing/features/git-visual.tsx +61 -0
  407. package/apps/web/src/components/landing/features/index.tsx +642 -0
  408. package/apps/web/src/components/landing/features/infra-visual.tsx +69 -0
  409. package/apps/web/src/components/landing/features/rollback-visual.tsx +42 -0
  410. package/apps/web/src/components/landing/features/ssl-visual.tsx +41 -0
  411. package/apps/web/src/components/landing/features/stacks-visual.tsx +54 -0
  412. package/apps/web/src/components/landing/final-cta.tsx +116 -0
  413. package/apps/web/src/components/landing/footer.tsx +145 -0
  414. package/apps/web/src/components/landing/hero.tsx +110 -0
  415. package/apps/web/src/components/landing/how-it-works.tsx +210 -0
  416. package/apps/web/src/components/landing/index.ts +21 -0
  417. package/apps/web/src/components/landing/mail-server.tsx +122 -0
  418. package/apps/web/src/components/landing/navbar.tsx +199 -0
  419. package/apps/web/src/components/landing/no-lockin.tsx +185 -0
  420. package/apps/web/src/components/landing/open-source-cta.tsx +151 -0
  421. package/apps/web/src/components/landing/portability.tsx +190 -0
  422. package/apps/web/src/components/landing/pricing.tsx +263 -0
  423. package/apps/web/src/components/landing/scaling.tsx +209 -0
  424. package/apps/web/src/components/landing/why-openship.tsx +291 -0
  425. package/apps/web/src/hooks/use-gsap-scroll.ts +158 -0
  426. package/apps/web/src/hooks/use-platform.ts +86 -0
  427. package/apps/web/src/lib/source.ts +12 -0
  428. package/apps/web/src/styles/fonts.css +84 -0
  429. package/apps/web/src/styles/landing.css +951 -0
  430. package/apps/web/src/styles/theme.css +227 -0
  431. package/apps/web/tsconfig.json +8 -3
  432. package/bun.lock +3260 -0
  433. package/docker-compose.yml +3 -0
  434. package/docs/screenshots/.gitkeep +0 -0
  435. package/docs/screenshots/screen.png +0 -0
  436. package/openship.code-workspace +7 -0
  437. package/package.json +23 -9
  438. package/packages/adapters/docs/ARCHITECTURE.md +160 -0
  439. package/packages/adapters/docs/BUILD-PIPELINE.md +171 -0
  440. package/packages/adapters/docs/CLOUD.md +239 -0
  441. package/packages/adapters/docs/EXECUTOR.md +174 -0
  442. package/packages/adapters/docs/LOG-STREAMING.md +175 -0
  443. package/packages/adapters/docs/SYSTEM.md +191 -0
  444. package/packages/adapters/package.json +14 -9
  445. package/packages/adapters/src/index.ts +144 -4
  446. package/packages/adapters/src/infra/cloud.ts +42 -0
  447. package/packages/adapters/src/infra/index.ts +9 -0
  448. package/packages/adapters/src/infra/noop.ts +27 -0
  449. package/packages/adapters/src/infra/traefik.ts +297 -0
  450. package/packages/adapters/src/infra/types.ts +36 -0
  451. package/packages/adapters/src/platform.ts +255 -0
  452. package/packages/adapters/src/runtime/bare.ts +567 -0
  453. package/packages/adapters/src/runtime/build-pipeline.ts +237 -0
  454. package/packages/adapters/src/runtime/cloud.ts +791 -0
  455. package/packages/adapters/src/runtime/deploy-pipeline.ts +146 -0
  456. package/packages/adapters/src/runtime/docker.ts +443 -0
  457. package/packages/adapters/src/runtime/index.ts +69 -0
  458. package/packages/adapters/src/runtime/local-build.ts +112 -0
  459. package/packages/adapters/src/runtime/transfer.ts +82 -0
  460. package/packages/adapters/src/runtime/types.ts +138 -0
  461. package/packages/adapters/src/system/catalog.ts +188 -0
  462. package/packages/adapters/src/system/checks.ts +228 -0
  463. package/packages/adapters/src/system/components.ts +45 -0
  464. package/packages/adapters/src/system/debug.ts +18 -0
  465. package/packages/adapters/src/system/environment.ts +168 -0
  466. package/packages/adapters/src/system/errors.ts +34 -0
  467. package/packages/adapters/src/system/executor.ts +600 -0
  468. package/packages/adapters/src/system/index.ts +58 -0
  469. package/packages/adapters/src/system/installer.ts +310 -0
  470. package/packages/adapters/src/system/setup.ts +442 -0
  471. package/packages/adapters/src/system/state.ts +96 -0
  472. package/packages/adapters/src/system/types.ts +116 -0
  473. package/packages/adapters/src/toolchain/catalog.ts +439 -0
  474. package/packages/adapters/src/toolchain/checks.ts +181 -0
  475. package/packages/adapters/src/toolchain/index.ts +38 -0
  476. package/packages/adapters/src/toolchain/installer.ts +189 -0
  477. package/packages/adapters/src/toolchain/types.ts +84 -0
  478. package/packages/adapters/src/types.ts +277 -0
  479. package/packages/adapters/tsconfig.json +3 -1
  480. package/packages/core/package.json +9 -9
  481. package/packages/core/src/constants.ts +44 -1
  482. package/packages/core/src/index.ts +2 -0
  483. package/packages/core/src/stacks.ts +778 -0
  484. package/packages/core/src/system.ts +111 -0
  485. package/packages/core/src/types.ts +22 -1
  486. package/packages/core/src/utils.ts +8 -0
  487. package/packages/core/tsconfig.json +3 -1
  488. package/packages/db/drizzle/0000_init.sql +231 -0
  489. package/packages/db/drizzle/0001_add_server_name.sql +1 -0
  490. package/packages/db/drizzle/meta/_journal.json +20 -0
  491. package/packages/db/drizzle.config.ts +10 -0
  492. package/packages/db/package.json +26 -14
  493. package/packages/db/src/client.ts +119 -0
  494. package/packages/db/src/index.ts +57 -8
  495. package/packages/db/src/repos/account.repo.ts +92 -0
  496. package/packages/db/src/repos/deployment.repo.ts +168 -0
  497. package/packages/db/src/repos/domain.repo.ts +102 -0
  498. package/packages/db/src/repos/git-installation.repo.ts +95 -0
  499. package/packages/db/src/repos/index.ts +43 -0
  500. package/packages/db/src/repos/instance-settings.repo.ts +43 -0
  501. package/packages/db/src/repos/project.repo.ts +159 -0
  502. package/packages/db/src/repos/session.repo.ts +82 -0
  503. package/packages/db/src/repos/settings.repo.ts +51 -0
  504. package/packages/db/src/repos/user.repo.ts +94 -0
  505. package/packages/db/src/schema/auth.ts +56 -0
  506. package/packages/db/src/schema/deployment.ts +87 -0
  507. package/packages/db/src/schema/domain.ts +46 -0
  508. package/packages/db/src/schema/github.ts +24 -0
  509. package/packages/db/src/schema/index.ts +6 -0
  510. package/packages/db/src/schema/project.ts +117 -0
  511. package/packages/db/src/schema/settings.ts +103 -0
  512. package/packages/db/tsconfig.json +3 -1
  513. package/packages/ui/package.json +17 -17
  514. package/packages/ui/src/components/status-dot.tsx +1 -1
  515. package/packages/ui/tsconfig.json +7 -2
  516. package/pnpm-workspace.yaml +0 -1
  517. package/{tooling/tsconfig/base.json → tsconfig.base.json} +0 -1
  518. package/turbo.json +4 -0
  519. package/apps/api/src/modules/auth/auth.controller.ts +0 -26
  520. package/apps/api/src/modules/auth/auth.schema.ts +0 -12
  521. package/apps/api/src/modules/auth/auth.service.ts +0 -23
  522. package/apps/dashboard/src/app/page.tsx +0 -6
  523. package/apps/web/src/app/(marketing)/docs/page.tsx +0 -10
  524. package/packages/adapters/src/base-adapter.ts +0 -49
  525. package/packages/adapters/src/docker-adapter.ts +0 -43
  526. package/packages/adapters/src/oblien-adapter.ts +0 -46
  527. package/packages/adapters/src/registry.ts +0 -22
  528. package/packages/db/prisma/schema.prisma +0 -160
  529. package/tooling/tsconfig/nextjs.json +0 -10
  530. package/tooling/tsconfig/node.json +0 -10
  531. package/tooling/tsconfig/package.json +0 -7
@@ -50,9 +50,12 @@ services:
50
50
  NODE_ENV: production
51
51
  PORT: 4000
52
52
  CLOUD_MODE: "false"
53
+ DEPLOY_MODE: docker
53
54
  DATABASE_URL: postgresql://openship:openship@postgres:5432/openship
54
55
  REDIS_URL: redis://redis:6379
55
56
  JWT_SECRET: change-me-in-production
57
+ BETTER_AUTH_SECRET: change-me-in-production # used for session signing
58
+ TRUSTED_ORIGINS: http://localhost:3001,http://localhost:3000
56
59
  depends_on:
57
60
  - postgres
58
61
  - redis
File without changes
Binary file
@@ -0,0 +1,7 @@
1
+ {
2
+ "folders": [
3
+ {
4
+ "path": "."
5
+ }
6
+ ]
7
+ }
package/package.json CHANGED
@@ -1,31 +1,45 @@
1
1
  {
2
2
  "name": "openship",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Open-source, self-hostable deployment platform",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/oblien/openship.git"
9
9
  },
10
+ "workspaces": [
11
+ "apps/*",
12
+ "packages/*"
13
+ ],
10
14
  "scripts": {
11
15
  "build": "turbo run build",
12
16
  "dev": "turbo run dev",
17
+ "dev:api": "turbo run dev --filter=@repo/api...",
18
+ "dev:saas": "turbo run dev:saas --filter=@repo/api --filter=@repo/dashboard --concurrency=10",
19
+ "dev:dashboard": "turbo run dev --filter=@repo/dashboard",
20
+ "dev:desktop": "turbo run dev --filter=@repo/desktop",
21
+ "dev:web": "turbo run dev --filter=@repo/web",
22
+ "dev:all": "turbo run dev",
13
23
  "lint": "turbo run lint",
14
24
  "test": "turbo run test",
15
25
  "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
16
- "db:generate": "turbo run db:generate --filter=openship-db",
17
- "db:push": "turbo run db:push --filter=openship-db",
18
- "db:migrate": "turbo run db:migrate --filter=openship-db",
26
+ "db:generate": "turbo run db:generate --filter=@repo/db",
27
+ "db:push": "turbo run db:push --filter=@repo/db",
28
+ "db:migrate": "turbo run db:migrate --filter=@repo/db",
19
29
  "clean": "turbo run clean && rm -rf node_modules"
20
30
  },
21
31
  "devDependencies": {
22
- "openship-tsconfig": "workspace:*",
23
- "prettier": "^3.2.0",
24
- "turbo": "^2.0.0",
25
- "typescript": "^5.4.0"
32
+ "prettier": "^3.8.1",
33
+ "turbo": "^2.8.14",
34
+ "typescript": "^5.9.3"
26
35
  },
27
- "packageManager": "pnpm@9.0.0",
36
+ "packageManager": "bun@1.3.10",
28
37
  "engines": {
29
38
  "node": ">=20.0.0"
39
+ },
40
+ "dependencies": {
41
+ "@octokit/auth-oauth-device": "^8.0.3",
42
+ "api": "^6.1.3",
43
+ "oblien": "^2.1.7"
30
44
  }
31
45
  }
@@ -0,0 +1,160 @@
1
+ # Platform Architecture
2
+
3
+ > `@repo/adapters` — the abstraction layer between Openship's API and the underlying infrastructure.
4
+
5
+ ## Three Deployment Targets
6
+
7
+ The same codebase runs in three completely different environments. The `createPlatform()` factory resolves the correct combination at startup based on config.
8
+
9
+ ```
10
+ ┌────────────────┬──────────────────────┬──────────────────────────┬─────────────────────┐
11
+ │ │ cloud (Oblien) │ selfhosted │ desktop │
12
+ ├────────────────┼──────────────────────┼──────────────────────────┼─────────────────────┤
13
+ │ Runtime │ CloudRuntime │ DockerRuntime or │ BareRuntime │
14
+ │ │ (pure API calls) │ BareRuntime │ (local executor) │
15
+ ├────────────────┼──────────────────────┼──────────────────────────┼─────────────────────┤
16
+ │ Routing │ CloudInfraProvider │ TraefikProvider │ NoopInfraProvider │
17
+ │ │ (pure API calls) │ (writes YAML via exec) │ (silent no-op) │
18
+ ├────────────────┼──────────────────────┼──────────────────────────┼─────────────────────┤
19
+ │ SSL │ CloudInfraProvider │ TraefikProvider (ACME) │ NoopInfraProvider │
20
+ │ │ (pure API calls) │ (file ops via exec) │ (no-op) │
21
+ ├────────────────┼──────────────────────┼──────────────────────────┼─────────────────────┤
22
+ │ System │ null │ SystemManager │ null │
23
+ │ │ (no RCE at all) │ (checks + installers) │ (no setup needed) │
24
+ ├────────────────┼──────────────────────┼──────────────────────────┼─────────────────────┤
25
+ │ Executor │ null │ LocalExecutor or │ null │
26
+ │ │ (nothing executes) │ SshExecutor (shared) │ (BareRuntime owns) │
27
+ ├────────────────┼──────────────────────┼──────────────────────────┼─────────────────────┤
28
+ │ ssh2 loaded? │ NO │ Only if SSH config set │ NO │
29
+ └────────────────┴──────────────────────┴──────────────────────────┴─────────────────────┘
30
+ ```
31
+
32
+ ## Three Layers
33
+
34
+ Each layer has a single responsibility. They are composed by the Platform, never used directly.
35
+
36
+ ### 1. Runtime — build/deploy/stop lifecycle
37
+
38
+ | Class | Transport | Use Case |
39
+ |---|---|---|
40
+ | `DockerRuntime` | dockerode (socket / SSH / TLS) | Self-hosted with Docker |
41
+ | `BareRuntime` | `CommandExecutor` (local or SSH) | Self-hosted bare metal, desktop |
42
+ | `CloudRuntime` | HTTP API calls (Oblien SDK) | Oblien cloud |
43
+
44
+ - Docker has its **own** SSH transport via dockerode — separate from the shared executor
45
+ - Bare uses the **shared** executor for everything (git, npm, nohup, kill, PID files)
46
+ - Cloud makes **zero** local calls — pure API stubs
47
+
48
+ ### 2. Infra — routing + SSL
49
+
50
+ | Class | Transport | Use Case |
51
+ |---|---|---|
52
+ | `TraefikProvider` | `CommandExecutor` (dual-path) | Self-hosted |
53
+ | `CloudInfraProvider` | HTTP API calls (Oblien SDK) | Oblien cloud |
54
+ | `NoopInfraProvider` | Nothing | Desktop / dev |
55
+
56
+ - Traefik writes YAML config files to a watched directory via the executor
57
+ - SSL is Traefik's built-in ACME resolver — cert info read via the executor
58
+ - The executor enables Traefik config to be written on the local machine OR a remote server via SSH
59
+
60
+ ### 3. System — prerequisite checks + server setup
61
+
62
+ | Class | Transport | Use Case |
63
+ |---|---|---|
64
+ | `SystemManager` | `CommandExecutor` | Self-hosted only |
65
+ | _null_ | — | Cloud and Desktop (no setup needed) |
66
+
67
+ - Checks: docker, traefik, git, node, bun — all via executor
68
+ - Installers: automated install scripts with real-time log streaming
69
+ - State: cached in `SetupStateStore` (file or DB), 24h auto-reverification
70
+ - Feature gating: `requireFeature("deploy")` reads cached state (free on hot paths)
71
+
72
+ ## File Map
73
+
74
+ ```
75
+ src/
76
+ ├── types.ts # Shared types: configs, CommandExecutor, SshConfig
77
+ ├── platform.ts # Factory + singleton (createPlatform, getPlatform)
78
+ ├── index.ts # Barrel exports
79
+
80
+ ├── runtime/
81
+ │ ├── types.ts # RuntimeAdapter interface, RuntimeCapability
82
+ │ ├── docker.ts # DockerRuntime (dockerode)
83
+ │ ├── bare.ts # BareRuntime (executor-based)
84
+ │ ├── cloud.ts # CloudRuntime (API stubs)
85
+ │ └── index.ts # Factory + re-exports
86
+
87
+ ├── infra/
88
+ │ ├── types.ts # RoutingProvider, SslProvider interfaces
89
+ │ ├── traefik.ts # Traefik file provider (dual-path via executor)
90
+ │ ├── cloud.ts # Cloud infra (API stubs)
91
+ │ └── noop.ts # No-op (desktop/dev)
92
+
93
+ └── system/
94
+ ├── types.ts # SystemLog, ComponentStatus, InstallerConfig, etc.
95
+ ├── executor.ts # LocalExecutor, SshExecutor, createExecutor()
96
+ ├── state.ts # SetupStateStore interface, FileStateStore
97
+ ├── checks.ts # Component health checks (all via executor)
98
+ ├── installer.ts # Component installers (all via executor)
99
+ ├── setup.ts # SystemManager orchestrator
100
+ └── index.ts # Barrel exports
101
+ ```
102
+
103
+ ## How It's Wired
104
+
105
+ ```
106
+ ┌─────────────────────────────────────────────────────────────────┐
107
+ │ API (apps/api) │
108
+ │ │
109
+ │ app.ts: bootstrapPlatform() │
110
+ │ │ │
111
+ │ ▼ │
112
+ │ controller-helpers.ts: resolveConfig() → initPlatform() │
113
+ │ platform() → getPlatform() │
114
+ │ │
115
+ │ service code: const { runtime, routing, ssl } = platform() │
116
+ │ await runtime.build(config, onLog) │
117
+ │ await routing.registerRoute({ domain, ... }) │
118
+ │ await ssl.provisionCert(domain) │
119
+ └─────────────────────────────────────────────────────────────────┘
120
+
121
+
122
+ ┌─────────────────────────────────────────────────────────────────┐
123
+ │ @repo/adapters │
124
+ │ │
125
+ │ createPlatform(config) ─┬─ "cloud" → CloudRuntime │
126
+ │ │ + CloudInfraProvider │
127
+ │ │ + system: null │
128
+ │ │ + executor: null │
129
+ │ │ │
130
+ │ ├─ "selfhosted" → Docker/BareRuntime │
131
+ │ │ + TraefikProvider │
132
+ │ │ + SystemManager │
133
+ │ │ + executor ─┐ │
134
+ │ │ │ │
135
+ │ │ ┌───────────────────────┘ │
136
+ │ │ │ shared across: │
137
+ │ │ │ • BareRuntime (if bare mode) │
138
+ │ │ │ • TraefikProvider │
139
+ │ │ │ • SystemManager │
140
+ │ │ │ • checks.ts + installer.ts │
141
+ │ │ │
142
+ │ └─ "desktop" → BareRuntime (own) │
143
+ │ + NoopInfraProvider │
144
+ │ + system: null │
145
+ │ + executor: null │
146
+ └─────────────────────────────────────────────────────────────────┘
147
+ ```
148
+
149
+ ## Environment Variables
150
+
151
+ | Variable | Values | Effect |
152
+ |---|---|---|
153
+ | `CLOUD_MODE` | `true` / `false` | Force cloud target (overrides DEPLOY_MODE) |
154
+ | `DEPLOY_MODE` | `docker` / `bare` / `cloud` / `desktop` | Select runtime + target |
155
+
156
+ Resolution priority in `resolveConfig()`:
157
+ 1. `CLOUD_MODE=true` or `DEPLOY_MODE=cloud` → `target: "cloud"`
158
+ 2. `DEPLOY_MODE=desktop` → `target: "desktop"`
159
+ 3. Everything else → `target: "selfhosted"` + `runtime: DEPLOY_MODE`
160
+ 4. Default (nothing set) → `target: "selfhosted"`, `runtime: "docker"`
@@ -0,0 +1,171 @@
1
+ # Build Pipeline & Process Management
2
+
3
+ > How builds run, how processes are tracked, and how cleanup works across all runtimes.
4
+
5
+ ## Build Flow
6
+
7
+ All three runtimes implement `build()` but with completely different transports:
8
+
9
+ ```
10
+ build.service.ts
11
+
12
+ │ Creates BuildLogger (single source of truth for all log emission)
13
+ │ Creates logCallback → pushes to logs[] + SSE broadcast
14
+
15
+
16
+ runtime.build(config, logger)
17
+
18
+ ├─ CloudRuntime → Oblien API: workspace.build() + execAndStream()
19
+ ├─ BareRuntime → executor.streamExec() through runBuildPipeline()
20
+ └─ DockerRuntime → (stub — Docker builds via Dockerfile)
21
+ ```
22
+
23
+ ## BuildLogger — Single Source of Truth
24
+
25
+ Every log emission goes through `BuildLogger`. No adapter creates `LogEntry` objects with step metadata directly.
26
+
27
+ ```typescript
28
+ class BuildLogger {
29
+ log(message: string, level?) // Plain log line
30
+ step(step, status, message) // Step lifecycle event (stepper UI)
31
+ runStep(step, label, fn) // Run a step: emit running → execute → completed/failed
32
+ get callback(): LogCallback // Pass to exec functions for raw output streaming
33
+ }
34
+ ```
35
+
36
+ ### Who calls what
37
+
38
+ | Caller | Method | Purpose |
39
+ |---|---|---|
40
+ | `runBuildPipeline()` | `logger.runStep("clone", ...)` | Step events for clone/install/build |
41
+ | `runBuildPipeline()` | `logger.log(...)` | Pipeline status messages |
42
+ | `build.service.ts` | `logger.step("deploy", ...)` | Deploy phase step events |
43
+ | `build.service.ts` | `logger.log(...)` | Deploy status messages |
44
+ | `executor.streamExec()` | `logger.callback` (raw `LogCallback`) | stdout/stderr lines from shell commands |
45
+ | `cloud.ts execAndStream()` | raw `LogCallback` | Oblien exec output chunks |
46
+
47
+ ## Shared Build Pipeline
48
+
49
+ `runBuildPipeline()` is used by `BareRuntime` and would be used by `DockerRuntime` when it supports builds. `CloudRuntime` has its own build flow via the Oblien API.
50
+
51
+ ```
52
+ runBuildPipeline(env, config, logger)
53
+
54
+ ├─ Step: clone
55
+ │ env.exec(`git clone --branch ${branch} --depth 1 ${repo} .`, logger.callback)
56
+
57
+ ├─ Step: install
58
+ │ env.exec(`npm install` / `yarn` / `pnpm install`, logger.callback)
59
+
60
+ ├─ Step: build (if buildCommand configured)
61
+ │ env.exec(buildCommand, logger.callback)
62
+
63
+ └─ Returns { status: "deploying" | "failed", durationMs }
64
+ ```
65
+
66
+ The `BuildEnvironment` abstraction decouples the pipeline from the executor:
67
+
68
+ ```typescript
69
+ interface BuildEnvironment {
70
+ projectDir: string;
71
+ exec(command: string, onLog: LogCallback): Promise<void>;
72
+ }
73
+ ```
74
+
75
+ BareRuntime wires it to `this.executor.streamExec()`. A future Docker build could wire it to `docker exec`.
76
+
77
+ ## Process Management (Bare Runtime)
78
+
79
+ ### Deploy — setsid for proper process groups
80
+
81
+ ```
82
+ deploy(config)
83
+
84
+ │ setsid nohup npm start >> logfile 2>&1 &
85
+ │ echo $!
86
+ │ │
87
+ │ └─ PID captured → written to .pids/{deploymentId}.pid
88
+
89
+ └─ setsid makes npm the process group leader
90
+ so all child processes belong to the same PGID
91
+ ```
92
+
93
+ ### Stop — kill the entire tree
94
+
95
+ ```
96
+ stop(containerId)
97
+
98
+ │ 1. Read PID from .pids/{containerId}.pid
99
+ │ 2. kill -- -${pid} ← SIGTERM the entire process group
100
+ │ (fallback: kill ${pid} if group kill not supported)
101
+ │ 3. Wait up to 10s for graceful shutdown
102
+ │ 4. kill -9 -- -${pid} ← SIGKILL the group if still alive
103
+
104
+ └─ This ensures child processes (e.g., node spawned by npm)
105
+ are cleaned up too — no orphans
106
+ ```
107
+
108
+ ### PID Tracking
109
+
110
+ ```
111
+ ${workDir}/
112
+ .pids/
113
+ {deploymentId}.pid ← contains the PID as plain text
114
+ .logs/
115
+ {deploymentId}.log ← stdout + stderr from the process
116
+ ```
117
+
118
+ All PID operations go through the executor:
119
+ - `readPid()` → `executor.readFile(pidFile)`
120
+ - `writePid()` → `executor.writeFile(pidFile, pid)`
121
+ - `isAlive()` → `executor.exec("kill -0 ${pid}")`
122
+
123
+ This means PID management works identically on local and remote (SSH) servers.
124
+
125
+ ### Build Cancellation
126
+
127
+ ```
128
+ cancelBuild(sessionId)
129
+
130
+ │ Read PID from .pids/build-{sessionId}.pid
131
+ │ kill -- -${pid} ← kill entire build process group
132
+
133
+ └─ Kills git clone, npm install, or whatever is running
134
+ ```
135
+
136
+ ## Resource Configuration
137
+
138
+ ```typescript
139
+ interface ResourceConfig {
140
+ cpuCores: number; // Fractional cores (e.g., 0.5, 1, 2)
141
+ memoryMb: number; // Memory in megabytes
142
+ }
143
+
144
+ // Defaults
145
+ DEFAULT_RESOURCE_CONFIG = { cpuCores: 0.5, memoryMb: 512 } // runtime
146
+ DEFAULT_BUILD_RESOURCE_CONFIG = { cpuCores: 2, memoryMb: 4096 } // build
147
+ ```
148
+
149
+ - Cloud: `cpuCores` passed directly to Oblien SDK (fractional, e.g., 0.5)
150
+ - Docker: used for container resource limits
151
+ - Bare: informational only (OS manages resources)
152
+
153
+ ## Error Handling
154
+
155
+ Build failures cascade cleanly:
156
+
157
+ ```
158
+ Pipeline step fails (e.g., npm install exits non-zero)
159
+
160
+ ├─ executor.streamExec returns { code: non-zero }
161
+ ├─ BuildEnvironment.exec throws Error
162
+ ├─ runBuildPipeline catches → logger.step(step, "failed", message)
163
+ ├─ Returns { status: "failed" }
164
+
165
+
166
+ build.service.ts
167
+ ├─ Updates deployment status to "failed"
168
+ ├─ Persists logs to DB via finishBuildSession()
169
+ ├─ Broadcasts failure via SSE
170
+ └─ Sends failure notification email
171
+ ```
@@ -0,0 +1,239 @@
1
+ # Cloud Architecture
2
+
3
+ > How Openship connects to Oblien cloud infrastructure — same pipeline, two auth paths.
4
+
5
+ ## Overview
6
+
7
+ Openship runs in two modes. Both use the **exact same** `CloudRuntime` and build/deploy pipeline. The only difference is how the Oblien SDK client gets authenticated:
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────────────────┐
11
+ │ CloudRuntime(client) │
12
+ │ │
13
+ │ build() → provisionBuildWorkspace → runBuildPipeline → deploy() │
14
+ │ stop() / start() / restart() / destroy() │
15
+ │ logs / metrics / domain management │
16
+ │ │
17
+ │ Doesn't know or care HOW the Oblien client was authenticated. │
18
+ └────────────────────────────┬────────────────────────────────────────────┘
19
+
20
+ ┌──────────────┴──────────────┐
21
+ │ │
22
+ ┌──────────▼──────────┐ ┌───────────▼───────────┐
23
+ │ SaaS (CLOUD_MODE) │ │ Local (!CLOUD_MODE) │
24
+ │ │ │ │
25
+ │ Master credentials │ │ Namespace token │
26
+ │ clientId + secret │ │ from stored session │
27
+ │ │ │ │
28
+ │ new Oblien({ │ │ new Oblien({ │
29
+ │ clientId, │ │ token │
30
+ │ clientSecret │ │ }) │
31
+ │ }) │ │ │
32
+ │ │ │ Scoped to user's │
33
+ │ Full platform │ │ namespace (os-{uid}) │
34
+ │ access │ │ 30min TTL │
35
+ └─────────────────────┘ └────────────────────────┘
36
+ ```
37
+
38
+ ## Mode 1: SaaS (`CLOUD_MODE=true`)
39
+
40
+ When Openship runs as the hosted SaaS platform (api.openship.io):
41
+
42
+ ```
43
+ Server startup
44
+ → initPlatform({ target: "cloud", cloudClientId, cloudClientSecret })
45
+ → new Oblien({ clientId, clientSecret }) ← master creds from env
46
+ → CloudRuntime(client) ← singleton, stays for process lifetime
47
+ → build.service.ts uses platform().runtime directly
48
+ ```
49
+
50
+ The SaaS also exposes a token endpoint for local instances:
51
+
52
+ ```
53
+ POST /api/cloud/token (requires auth)
54
+ → ensureNamespace(userId) ← creates os-{userId} namespace if needed
55
+ → client.tokens.create({ scope: "namespace", namespace, ttl: 1800 })
56
+ → { token, namespace, expiresAt }
57
+ ```
58
+
59
+ ### Key files
60
+
61
+ | File | Purpose |
62
+ |---|---|
63
+ | `apps/api/src/lib/openship-cloud.ts` | `ensureNamespace()` + `issueNamespaceToken()` |
64
+ | `apps/api/src/modules/cloud/cloud.controller.ts` | `getToken()` handler |
65
+ | `apps/api/src/modules/cloud/cloud.routes.ts` | `cloudSaasRoutes` → `POST /token` |
66
+
67
+ ## Mode 2: Local (`CLOUD_MODE=false`)
68
+
69
+ When Openship runs locally (desktop app, self-hosted, CLI):
70
+
71
+ ### Step 1: User connects their Openship Cloud account
72
+
73
+ ```
74
+ Dashboard Settings page
75
+ → user enters email + password
76
+ → POST /api/cloud/connect
77
+ → Local API proxies login to api.openship.io/api/auth/sign-in/email
78
+ → Receives session token
79
+ → Encrypts + stores in user_settings.cloud_session_token
80
+ ```
81
+
82
+ ### Step 2: Deploy to cloud
83
+
84
+ ```
85
+ build.service.ts → executeBuildAndDeploy()
86
+ → detects !CLOUD_MODE && target === "cloud"
87
+ → getCloudToken(userId)
88
+ → reads encrypted session from DB
89
+ → POST api.openship.io/api/cloud/token (with Bearer session)
90
+ → receives namespace-scoped Oblien token (cached in memory, 30min TTL)
91
+ → createPlatform({ target: "cloud", cloudToken: result.token })
92
+ → new Oblien({ token }) ← namespace-scoped
93
+ → CloudRuntime(client) ← per-deploy instance
94
+ → same build() → same deploy() → same everything
95
+ ```
96
+
97
+ ### Key files
98
+
99
+ | File | Purpose |
100
+ |---|---|
101
+ | `apps/api/src/lib/cloud-client.ts` | `connectCloud()`, `disconnectCloud()`, `isCloudConnected()`, `getCloudToken()` |
102
+ | `apps/api/src/modules/cloud/cloud.controller.ts` | `connect()`, `disconnect()`, `status()` handlers |
103
+ | `apps/api/src/modules/cloud/cloud.routes.ts` | `cloudLocalRoutes` → `POST /connect`, `POST /disconnect`, `GET /status` |
104
+ | `apps/dashboard/src/app/(dashboard)/settings/page.tsx` | Cloud connection UI |
105
+ | `apps/dashboard/src/lib/api/cloud.ts` | `cloudApi` client-side helpers |
106
+
107
+ ## Auth Flow Diagram
108
+
109
+ ```
110
+ LOCAL MODE — full round trip:
111
+
112
+ ┌──────────────┐ POST /api/cloud/connect
113
+ │ Dashboard │ ──────────────────────────────▶ ┌──────────────┐
114
+ │ Settings │ { email, password } │ Local API │
115
+ │ │ │ │
116
+ │ │ { connected: true } │ cloud │
117
+ │ │ ◀────────────────────────────────│ controller │
118
+ └──────────────┘ └──────┬───────┘
119
+
120
+ POST /api/auth/sign-in │
121
+ { email, password } │
122
+
123
+ ┌──────────────┐
124
+ │ Openship │
125
+ │ Cloud SaaS │
126
+ │ │
127
+ │ Returns │
128
+ │ session token│
129
+ └──────────────┘
130
+
131
+ encrypt(token) │
132
+ store in DB │
133
+
134
+ ┌──────────────┐
135
+ │ user_settings│
136
+ │ cloud_session│
137
+ │ _token (enc) │
138
+ └──────────────┘
139
+
140
+
141
+ DEPLOY TIME:
142
+
143
+ ┌──────────────┐ ┌──────────────┐
144
+ │ build.service│ ── getCloudToken(userId) ──────▶ │ cloud-client │
145
+ │ │ │ │
146
+ │ │ │ 1. read DB │
147
+ │ │ │ 2. decrypt │
148
+ │ │ { token, namespace } │ 3. POST /api │
149
+ │ │ ◀────────────────────────────────│ /cloud │
150
+ └──────┬───────┘ │ /token │
151
+ │ └──────┬───────┘
152
+ │ createPlatform({ │
153
+ │ target: "cloud", ▼
154
+ │ cloudToken: token ┌──────────────────────────┐
155
+ │ }) │ Openship Cloud SaaS │
156
+ │ │ │
157
+ ▼ │ ensureNamespace(userId) │
158
+ ┌──────────────┐ │ issueNamespaceToken() │
159
+ │ CloudRuntime │ │ │
160
+ │ │ │ Returns Oblien namespace │
161
+ │ new Oblien({ │ │ token (30min TTL) │
162
+ │ token │ └──────────────────────────┘
163
+ │ }) │
164
+ │ │
165
+ │ build() │──────▶ Oblien API (workspaces, runtime, deploy...)
166
+ │ deploy() │
167
+ └──────────────┘
168
+ ```
169
+
170
+ ## Namespace Model
171
+
172
+ Each user gets an isolated Oblien namespace:
173
+
174
+ - **Slug**: `os-{userId}`
175
+ - **Creation**: Idempotent — 409 on duplicate is caught, existing namespace fetched
176
+ - **Cached**: In-memory `Map<userId, slug>` on SaaS server
177
+
178
+ The namespace token gives full access to everything in that namespace:
179
+ - Create/manage workspaces
180
+ - Build & deploy
181
+ - Domain management
182
+ - Logs & metrics
183
+
184
+ ## Security
185
+
186
+ | Concern | Approach |
187
+ |---|---|
188
+ | Cloud session at rest | AES-256 encrypted via `encrypt()`/`decrypt()` in `encryption.ts` |
189
+ | Session in transit | HTTPS only (api.openship.io) |
190
+ | Expired sessions | Auto-cleared on 401 from SaaS API |
191
+ | Namespace tokens | 30min TTL, 5min refresh buffer, in-memory cache only |
192
+ | Token scope | Namespace-scoped — user can only access their own resources |
193
+ | No browser cookies | Session lives server-side in DB, never exposed to dashboard |
194
+
195
+ ## API Endpoints
196
+
197
+ ### SaaS routes (`CLOUD_MODE=true`, mounted at `/api/cloud`)
198
+
199
+ | Method | Path | Handler | Purpose |
200
+ |---|---|---|---|
201
+ | POST | `/token` | `getToken` | Mint namespace-scoped Oblien token |
202
+
203
+ ### Local routes (`CLOUD_MODE=false`, mounted at `/api/cloud`)
204
+
205
+ | Method | Path | Handler | Purpose |
206
+ |---|---|---|---|
207
+ | POST | `/connect` | `connect` | Proxy login → store encrypted session |
208
+ | POST | `/disconnect` | `disconnect` | Clear stored session |
209
+ | GET | `/status` | `status` | Check connection state |
210
+
211
+ ### Dashboard API (`apps/dashboard/src/lib/api/cloud.ts`)
212
+
213
+ ```typescript
214
+ cloudApi.connect(email, password) // POST /api/cloud/connect
215
+ cloudApi.disconnect() // POST /api/cloud/disconnect
216
+ cloudApi.status() // GET /api/cloud/status
217
+ ```
218
+
219
+ ## Route Mounting (`app.ts`)
220
+
221
+ ```typescript
222
+ if (env.CLOUD_MODE) {
223
+ // SaaS: mint tokens for local instances
224
+ app.route("/api/cloud", cloudSaasRoutes);
225
+ } else {
226
+ // Local: manage connection to Openship Cloud
227
+ app.route("/api/cloud", cloudLocalRoutes);
228
+ }
229
+ ```
230
+
231
+ Dynamic imports ensure zero code bleed between modes.
232
+
233
+ ## Database
234
+
235
+ | Table | Column | Type | Purpose |
236
+ |---|---|---|---|
237
+ | `user_settings` | `cloud_session_token` | `text` (nullable) | Encrypted Openship Cloud session |
238
+
239
+ Migration: `packages/db/drizzle/0004_add_cloud_session_token.sql`