happy2 0.0.5

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 (373) hide show
  1. package/README.md +82 -0
  2. package/package.json +74 -0
  3. package/packages/happy2-server/Dockerfile +18 -0
  4. package/packages/happy2-server/README.md +418 -0
  5. package/packages/happy2-server/bin/happy2.js +3 -0
  6. package/packages/happy2-server/dist/cli.d.ts +3 -0
  7. package/packages/happy2-server/dist/cli.d.ts.map +1 -0
  8. package/packages/happy2-server/dist/cli.js +44 -0
  9. package/packages/happy2-server/dist/cli.js.map +1 -0
  10. package/packages/happy2-server/dist/index.d.ts +24 -0
  11. package/packages/happy2-server/dist/index.d.ts.map +1 -0
  12. package/packages/happy2-server/dist/index.js +22 -0
  13. package/packages/happy2-server/dist/index.js.map +1 -0
  14. package/packages/happy2-server/dist/modules/agents/builtin-images.d.ts +8 -0
  15. package/packages/happy2-server/dist/modules/agents/builtin-images.d.ts.map +1 -0
  16. package/packages/happy2-server/dist/modules/agents/builtin-images.js +283 -0
  17. package/packages/happy2-server/dist/modules/agents/builtin-images.js.map +1 -0
  18. package/packages/happy2-server/dist/modules/agents/command.d.ts +3 -0
  19. package/packages/happy2-server/dist/modules/agents/command.d.ts.map +1 -0
  20. package/packages/happy2-server/dist/modules/agents/command.js +7 -0
  21. package/packages/happy2-server/dist/modules/agents/command.js.map +1 -0
  22. package/packages/happy2-server/dist/modules/agents/daemon.d.ts +106 -0
  23. package/packages/happy2-server/dist/modules/agents/daemon.d.ts.map +1 -0
  24. package/packages/happy2-server/dist/modules/agents/daemon.js +522 -0
  25. package/packages/happy2-server/dist/modules/agents/daemon.js.map +1 -0
  26. package/packages/happy2-server/dist/modules/agents/docker.d.ts +51 -0
  27. package/packages/happy2-server/dist/modules/agents/docker.d.ts.map +1 -0
  28. package/packages/happy2-server/dist/modules/agents/docker.js +256 -0
  29. package/packages/happy2-server/dist/modules/agents/docker.js.map +1 -0
  30. package/packages/happy2-server/dist/modules/agents/docker.test.d.ts +2 -0
  31. package/packages/happy2-server/dist/modules/agents/docker.test.d.ts.map +1 -0
  32. package/packages/happy2-server/dist/modules/agents/docker.test.js +155 -0
  33. package/packages/happy2-server/dist/modules/agents/docker.test.js.map +1 -0
  34. package/packages/happy2-server/dist/modules/agents/index.d.ts +5 -0
  35. package/packages/happy2-server/dist/modules/agents/index.d.ts.map +1 -0
  36. package/packages/happy2-server/dist/modules/agents/index.js +4 -0
  37. package/packages/happy2-server/dist/modules/agents/index.js.map +1 -0
  38. package/packages/happy2-server/dist/modules/agents/service.d.ts +140 -0
  39. package/packages/happy2-server/dist/modules/agents/service.d.ts.map +1 -0
  40. package/packages/happy2-server/dist/modules/agents/service.js +1283 -0
  41. package/packages/happy2-server/dist/modules/agents/service.js.map +1 -0
  42. package/packages/happy2-server/dist/modules/auth/cloudflare-access.d.ts +15 -0
  43. package/packages/happy2-server/dist/modules/auth/cloudflare-access.d.ts.map +1 -0
  44. package/packages/happy2-server/dist/modules/auth/cloudflare-access.js +49 -0
  45. package/packages/happy2-server/dist/modules/auth/cloudflare-access.js.map +1 -0
  46. package/packages/happy2-server/dist/modules/auth/crypto.d.ts +4 -0
  47. package/packages/happy2-server/dist/modules/auth/crypto.d.ts.map +1 -0
  48. package/packages/happy2-server/dist/modules/auth/crypto.js +31 -0
  49. package/packages/happy2-server/dist/modules/auth/crypto.js.map +1 -0
  50. package/packages/happy2-server/dist/modules/auth/crypto.test.d.ts +2 -0
  51. package/packages/happy2-server/dist/modules/auth/crypto.test.d.ts.map +1 -0
  52. package/packages/happy2-server/dist/modules/auth/crypto.test.js +11 -0
  53. package/packages/happy2-server/dist/modules/auth/crypto.test.js.map +1 -0
  54. package/packages/happy2-server/dist/modules/auth/email.d.ts +3 -0
  55. package/packages/happy2-server/dist/modules/auth/email.d.ts.map +1 -0
  56. package/packages/happy2-server/dist/modules/auth/email.js +22 -0
  57. package/packages/happy2-server/dist/modules/auth/email.js.map +1 -0
  58. package/packages/happy2-server/dist/modules/auth/metadata.d.ts +5 -0
  59. package/packages/happy2-server/dist/modules/auth/metadata.d.ts.map +1 -0
  60. package/packages/happy2-server/dist/modules/auth/metadata.js +28 -0
  61. package/packages/happy2-server/dist/modules/auth/metadata.js.map +1 -0
  62. package/packages/happy2-server/dist/modules/auth/metadata.test.d.ts +2 -0
  63. package/packages/happy2-server/dist/modules/auth/metadata.test.d.ts.map +1 -0
  64. package/packages/happy2-server/dist/modules/auth/metadata.test.js +10 -0
  65. package/packages/happy2-server/dist/modules/auth/metadata.test.js.map +1 -0
  66. package/packages/happy2-server/dist/modules/auth/methods.d.ts +10 -0
  67. package/packages/happy2-server/dist/modules/auth/methods.d.ts.map +1 -0
  68. package/packages/happy2-server/dist/modules/auth/methods.js +21 -0
  69. package/packages/happy2-server/dist/modules/auth/methods.js.map +1 -0
  70. package/packages/happy2-server/dist/modules/auth/methods.test.d.ts +2 -0
  71. package/packages/happy2-server/dist/modules/auth/methods.test.d.ts.map +1 -0
  72. package/packages/happy2-server/dist/modules/auth/methods.test.js +16 -0
  73. package/packages/happy2-server/dist/modules/auth/methods.test.js.map +1 -0
  74. package/packages/happy2-server/dist/modules/auth/oidc.d.ts +9 -0
  75. package/packages/happy2-server/dist/modules/auth/oidc.d.ts.map +1 -0
  76. package/packages/happy2-server/dist/modules/auth/oidc.js +68 -0
  77. package/packages/happy2-server/dist/modules/auth/oidc.js.map +1 -0
  78. package/packages/happy2-server/dist/modules/auth/service.d.ts +44 -0
  79. package/packages/happy2-server/dist/modules/auth/service.d.ts.map +1 -0
  80. package/packages/happy2-server/dist/modules/auth/service.js +208 -0
  81. package/packages/happy2-server/dist/modules/auth/service.js.map +1 -0
  82. package/packages/happy2-server/dist/modules/auth/tokens.d.ts +21 -0
  83. package/packages/happy2-server/dist/modules/auth/tokens.d.ts.map +1 -0
  84. package/packages/happy2-server/dist/modules/auth/tokens.js +79 -0
  85. package/packages/happy2-server/dist/modules/auth/tokens.js.map +1 -0
  86. package/packages/happy2-server/dist/modules/automation/repository.d.ts +127 -0
  87. package/packages/happy2-server/dist/modules/automation/repository.d.ts.map +1 -0
  88. package/packages/happy2-server/dist/modules/automation/repository.js +821 -0
  89. package/packages/happy2-server/dist/modules/automation/repository.js.map +1 -0
  90. package/packages/happy2-server/dist/modules/collaboration/repository.d.ts +839 -0
  91. package/packages/happy2-server/dist/modules/collaboration/repository.d.ts.map +1 -0
  92. package/packages/happy2-server/dist/modules/collaboration/repository.js +5795 -0
  93. package/packages/happy2-server/dist/modules/collaboration/repository.js.map +1 -0
  94. package/packages/happy2-server/dist/modules/collaboration/repository.test.d.ts +2 -0
  95. package/packages/happy2-server/dist/modules/collaboration/repository.test.d.ts.map +1 -0
  96. package/packages/happy2-server/dist/modules/collaboration/repository.test.js +620 -0
  97. package/packages/happy2-server/dist/modules/collaboration/repository.test.js.map +1 -0
  98. package/packages/happy2-server/dist/modules/collaboration/types.d.ts +243 -0
  99. package/packages/happy2-server/dist/modules/collaboration/types.d.ts.map +1 -0
  100. package/packages/happy2-server/dist/modules/collaboration/types.js +8 -0
  101. package/packages/happy2-server/dist/modules/collaboration/types.js.map +1 -0
  102. package/packages/happy2-server/dist/modules/config/defaults.d.ts +8 -0
  103. package/packages/happy2-server/dist/modules/config/defaults.d.ts.map +1 -0
  104. package/packages/happy2-server/dist/modules/config/defaults.js +70 -0
  105. package/packages/happy2-server/dist/modules/config/defaults.js.map +1 -0
  106. package/packages/happy2-server/dist/modules/config/defaults.test.d.ts +2 -0
  107. package/packages/happy2-server/dist/modules/config/defaults.test.d.ts.map +1 -0
  108. package/packages/happy2-server/dist/modules/config/defaults.test.js +27 -0
  109. package/packages/happy2-server/dist/modules/config/defaults.test.js.map +1 -0
  110. package/packages/happy2-server/dist/modules/config/environment.d.ts +4 -0
  111. package/packages/happy2-server/dist/modules/config/environment.d.ts.map +1 -0
  112. package/packages/happy2-server/dist/modules/config/environment.js +92 -0
  113. package/packages/happy2-server/dist/modules/config/environment.js.map +1 -0
  114. package/packages/happy2-server/dist/modules/config/loader.d.ts +5 -0
  115. package/packages/happy2-server/dist/modules/config/loader.d.ts.map +1 -0
  116. package/packages/happy2-server/dist/modules/config/loader.js +251 -0
  117. package/packages/happy2-server/dist/modules/config/loader.js.map +1 -0
  118. package/packages/happy2-server/dist/modules/config/loader.test.d.ts +2 -0
  119. package/packages/happy2-server/dist/modules/config/loader.test.d.ts.map +1 -0
  120. package/packages/happy2-server/dist/modules/config/loader.test.js +108 -0
  121. package/packages/happy2-server/dist/modules/config/loader.test.js.map +1 -0
  122. package/packages/happy2-server/dist/modules/config/paths.d.ts +7 -0
  123. package/packages/happy2-server/dist/modules/config/paths.d.ts.map +1 -0
  124. package/packages/happy2-server/dist/modules/config/paths.js +15 -0
  125. package/packages/happy2-server/dist/modules/config/paths.js.map +1 -0
  126. package/packages/happy2-server/dist/modules/config/paths.test.d.ts +2 -0
  127. package/packages/happy2-server/dist/modules/config/paths.test.d.ts.map +1 -0
  128. package/packages/happy2-server/dist/modules/config/paths.test.js +22 -0
  129. package/packages/happy2-server/dist/modules/config/paths.test.js.map +1 -0
  130. package/packages/happy2-server/dist/modules/config/runtime.d.ts +6 -0
  131. package/packages/happy2-server/dist/modules/config/runtime.d.ts.map +1 -0
  132. package/packages/happy2-server/dist/modules/config/runtime.js +14 -0
  133. package/packages/happy2-server/dist/modules/config/runtime.js.map +1 -0
  134. package/packages/happy2-server/dist/modules/config/type.d.ts +88 -0
  135. package/packages/happy2-server/dist/modules/config/type.d.ts.map +1 -0
  136. package/packages/happy2-server/dist/modules/config/type.js +2 -0
  137. package/packages/happy2-server/dist/modules/config/type.js.map +1 -0
  138. package/packages/happy2-server/dist/modules/database.d.ts +105 -0
  139. package/packages/happy2-server/dist/modules/database.d.ts.map +1 -0
  140. package/packages/happy2-server/dist/modules/database.js +583 -0
  141. package/packages/happy2-server/dist/modules/database.js.map +1 -0
  142. package/packages/happy2-server/dist/modules/drizzle.d.ts +11 -0
  143. package/packages/happy2-server/dist/modules/drizzle.d.ts.map +1 -0
  144. package/packages/happy2-server/dist/modules/drizzle.js +31 -0
  145. package/packages/happy2-server/dist/modules/drizzle.js.map +1 -0
  146. package/packages/happy2-server/dist/modules/files/lock.d.ts +3 -0
  147. package/packages/happy2-server/dist/modules/files/lock.d.ts.map +1 -0
  148. package/packages/happy2-server/dist/modules/files/lock.js +83 -0
  149. package/packages/happy2-server/dist/modules/files/lock.js.map +1 -0
  150. package/packages/happy2-server/dist/modules/files/media.d.ts +18 -0
  151. package/packages/happy2-server/dist/modules/files/media.d.ts.map +1 -0
  152. package/packages/happy2-server/dist/modules/files/media.js +352 -0
  153. package/packages/happy2-server/dist/modules/files/media.js.map +1 -0
  154. package/packages/happy2-server/dist/modules/files/provider.d.ts +130 -0
  155. package/packages/happy2-server/dist/modules/files/provider.d.ts.map +1 -0
  156. package/packages/happy2-server/dist/modules/files/provider.js +448 -0
  157. package/packages/happy2-server/dist/modules/files/provider.js.map +1 -0
  158. package/packages/happy2-server/dist/modules/files/quota.d.ts +58 -0
  159. package/packages/happy2-server/dist/modules/files/quota.d.ts.map +1 -0
  160. package/packages/happy2-server/dist/modules/files/quota.js +180 -0
  161. package/packages/happy2-server/dist/modules/files/quota.js.map +1 -0
  162. package/packages/happy2-server/dist/modules/files/routes.test.d.ts +2 -0
  163. package/packages/happy2-server/dist/modules/files/routes.test.d.ts.map +1 -0
  164. package/packages/happy2-server/dist/modules/files/routes.test.js +163 -0
  165. package/packages/happy2-server/dist/modules/files/routes.test.js.map +1 -0
  166. package/packages/happy2-server/dist/modules/files/scanner.d.ts +27 -0
  167. package/packages/happy2-server/dist/modules/files/scanner.d.ts.map +1 -0
  168. package/packages/happy2-server/dist/modules/files/scanner.js +66 -0
  169. package/packages/happy2-server/dist/modules/files/scanner.js.map +1 -0
  170. package/packages/happy2-server/dist/modules/files/storage.d.ts +95 -0
  171. package/packages/happy2-server/dist/modules/files/storage.d.ts.map +1 -0
  172. package/packages/happy2-server/dist/modules/files/storage.js +855 -0
  173. package/packages/happy2-server/dist/modules/files/storage.js.map +1 -0
  174. package/packages/happy2-server/dist/modules/files/storage.test.d.ts +2 -0
  175. package/packages/happy2-server/dist/modules/files/storage.test.d.ts.map +1 -0
  176. package/packages/happy2-server/dist/modules/files/storage.test.js +170 -0
  177. package/packages/happy2-server/dist/modules/files/storage.test.js.map +1 -0
  178. package/packages/happy2-server/dist/modules/integrations/index.d.ts +6 -0
  179. package/packages/happy2-server/dist/modules/integrations/index.d.ts.map +1 -0
  180. package/packages/happy2-server/dist/modules/integrations/index.js +6 -0
  181. package/packages/happy2-server/dist/modules/integrations/index.js.map +1 -0
  182. package/packages/happy2-server/dist/modules/integrations/repository.d.ts +136 -0
  183. package/packages/happy2-server/dist/modules/integrations/repository.d.ts.map +1 -0
  184. package/packages/happy2-server/dist/modules/integrations/repository.js +1229 -0
  185. package/packages/happy2-server/dist/modules/integrations/repository.js.map +1 -0
  186. package/packages/happy2-server/dist/modules/integrations/repository.test.d.ts +2 -0
  187. package/packages/happy2-server/dist/modules/integrations/repository.test.d.ts.map +1 -0
  188. package/packages/happy2-server/dist/modules/integrations/repository.test.js +345 -0
  189. package/packages/happy2-server/dist/modules/integrations/repository.test.js.map +1 -0
  190. package/packages/happy2-server/dist/modules/integrations/routes.test.d.ts +2 -0
  191. package/packages/happy2-server/dist/modules/integrations/routes.test.d.ts.map +1 -0
  192. package/packages/happy2-server/dist/modules/integrations/routes.test.js +161 -0
  193. package/packages/happy2-server/dist/modules/integrations/routes.test.js.map +1 -0
  194. package/packages/happy2-server/dist/modules/integrations/secrets.d.ts +19 -0
  195. package/packages/happy2-server/dist/modules/integrations/secrets.d.ts.map +1 -0
  196. package/packages/happy2-server/dist/modules/integrations/secrets.js +69 -0
  197. package/packages/happy2-server/dist/modules/integrations/secrets.js.map +1 -0
  198. package/packages/happy2-server/dist/modules/integrations/ssrf.d.ts +32 -0
  199. package/packages/happy2-server/dist/modules/integrations/ssrf.d.ts.map +1 -0
  200. package/packages/happy2-server/dist/modules/integrations/ssrf.js +185 -0
  201. package/packages/happy2-server/dist/modules/integrations/ssrf.js.map +1 -0
  202. package/packages/happy2-server/dist/modules/integrations/ssrf.test.d.ts +2 -0
  203. package/packages/happy2-server/dist/modules/integrations/ssrf.test.d.ts.map +1 -0
  204. package/packages/happy2-server/dist/modules/integrations/ssrf.test.js +56 -0
  205. package/packages/happy2-server/dist/modules/integrations/ssrf.test.js.map +1 -0
  206. package/packages/happy2-server/dist/modules/integrations/transport.d.ts +21 -0
  207. package/packages/happy2-server/dist/modules/integrations/transport.d.ts.map +1 -0
  208. package/packages/happy2-server/dist/modules/integrations/transport.js +108 -0
  209. package/packages/happy2-server/dist/modules/integrations/transport.js.map +1 -0
  210. package/packages/happy2-server/dist/modules/integrations/transport.test.d.ts +2 -0
  211. package/packages/happy2-server/dist/modules/integrations/transport.test.d.ts.map +1 -0
  212. package/packages/happy2-server/dist/modules/integrations/transport.test.js +66 -0
  213. package/packages/happy2-server/dist/modules/integrations/transport.test.js.map +1 -0
  214. package/packages/happy2-server/dist/modules/integrations/types.d.ts +155 -0
  215. package/packages/happy2-server/dist/modules/integrations/types.d.ts.map +1 -0
  216. package/packages/happy2-server/dist/modules/integrations/types.js +26 -0
  217. package/packages/happy2-server/dist/modules/integrations/types.js.map +1 -0
  218. package/packages/happy2-server/dist/modules/operations/export-worker.d.ts +16 -0
  219. package/packages/happy2-server/dist/modules/operations/export-worker.d.ts.map +1 -0
  220. package/packages/happy2-server/dist/modules/operations/export-worker.js +56 -0
  221. package/packages/happy2-server/dist/modules/operations/export-worker.js.map +1 -0
  222. package/packages/happy2-server/dist/modules/operations/repository.d.ts +215 -0
  223. package/packages/happy2-server/dist/modules/operations/repository.d.ts.map +1 -0
  224. package/packages/happy2-server/dist/modules/operations/repository.js +2011 -0
  225. package/packages/happy2-server/dist/modules/operations/repository.js.map +1 -0
  226. package/packages/happy2-server/dist/modules/operations/repository.test.d.ts +2 -0
  227. package/packages/happy2-server/dist/modules/operations/repository.test.d.ts.map +1 -0
  228. package/packages/happy2-server/dist/modules/operations/repository.test.js +610 -0
  229. package/packages/happy2-server/dist/modules/operations/repository.test.js.map +1 -0
  230. package/packages/happy2-server/dist/modules/operations/types.d.ts +144 -0
  231. package/packages/happy2-server/dist/modules/operations/types.d.ts.map +1 -0
  232. package/packages/happy2-server/dist/modules/operations/types.js +9 -0
  233. package/packages/happy2-server/dist/modules/operations/types.js.map +1 -0
  234. package/packages/happy2-server/dist/modules/realtime/events.d.ts +99 -0
  235. package/packages/happy2-server/dist/modules/realtime/events.d.ts.map +1 -0
  236. package/packages/happy2-server/dist/modules/realtime/events.js +173 -0
  237. package/packages/happy2-server/dist/modules/realtime/events.js.map +1 -0
  238. package/packages/happy2-server/dist/modules/realtime/index.d.ts +4 -0
  239. package/packages/happy2-server/dist/modules/realtime/index.d.ts.map +1 -0
  240. package/packages/happy2-server/dist/modules/realtime/index.js +4 -0
  241. package/packages/happy2-server/dist/modules/realtime/index.js.map +1 -0
  242. package/packages/happy2-server/dist/modules/realtime/local.d.ts +37 -0
  243. package/packages/happy2-server/dist/modules/realtime/local.d.ts.map +1 -0
  244. package/packages/happy2-server/dist/modules/realtime/local.js +181 -0
  245. package/packages/happy2-server/dist/modules/realtime/local.js.map +1 -0
  246. package/packages/happy2-server/dist/modules/realtime/local.test.d.ts +2 -0
  247. package/packages/happy2-server/dist/modules/realtime/local.test.d.ts.map +1 -0
  248. package/packages/happy2-server/dist/modules/realtime/local.test.js +186 -0
  249. package/packages/happy2-server/dist/modules/realtime/local.test.js.map +1 -0
  250. package/packages/happy2-server/dist/modules/realtime/pubsub.d.ts +26 -0
  251. package/packages/happy2-server/dist/modules/realtime/pubsub.d.ts.map +1 -0
  252. package/packages/happy2-server/dist/modules/realtime/pubsub.js +7 -0
  253. package/packages/happy2-server/dist/modules/realtime/pubsub.js.map +1 -0
  254. package/packages/happy2-server/dist/modules/request/database-idempotency.d.ts +15 -0
  255. package/packages/happy2-server/dist/modules/request/database-idempotency.d.ts.map +1 -0
  256. package/packages/happy2-server/dist/modules/request/database-idempotency.js +141 -0
  257. package/packages/happy2-server/dist/modules/request/database-idempotency.js.map +1 -0
  258. package/packages/happy2-server/dist/modules/request/idempotency-hook.d.ts +12 -0
  259. package/packages/happy2-server/dist/modules/request/idempotency-hook.d.ts.map +1 -0
  260. package/packages/happy2-server/dist/modules/request/idempotency-hook.js +98 -0
  261. package/packages/happy2-server/dist/modules/request/idempotency-hook.js.map +1 -0
  262. package/packages/happy2-server/dist/modules/request/idempotency.d.ts +146 -0
  263. package/packages/happy2-server/dist/modules/request/idempotency.d.ts.map +1 -0
  264. package/packages/happy2-server/dist/modules/request/idempotency.js +312 -0
  265. package/packages/happy2-server/dist/modules/request/idempotency.js.map +1 -0
  266. package/packages/happy2-server/dist/modules/request/idempotency.test.d.ts +2 -0
  267. package/packages/happy2-server/dist/modules/request/idempotency.test.d.ts.map +1 -0
  268. package/packages/happy2-server/dist/modules/request/idempotency.test.js +191 -0
  269. package/packages/happy2-server/dist/modules/request/idempotency.test.js.map +1 -0
  270. package/packages/happy2-server/dist/modules/request/index.d.ts +5 -0
  271. package/packages/happy2-server/dist/modules/request/index.d.ts.map +1 -0
  272. package/packages/happy2-server/dist/modules/request/index.js +5 -0
  273. package/packages/happy2-server/dist/modules/request/index.js.map +1 -0
  274. package/packages/happy2-server/dist/modules/request/rate-limit.d.ts +100 -0
  275. package/packages/happy2-server/dist/modules/request/rate-limit.d.ts.map +1 -0
  276. package/packages/happy2-server/dist/modules/request/rate-limit.js +239 -0
  277. package/packages/happy2-server/dist/modules/request/rate-limit.js.map +1 -0
  278. package/packages/happy2-server/dist/modules/request/rate-limit.test.d.ts +2 -0
  279. package/packages/happy2-server/dist/modules/request/rate-limit.test.d.ts.map +1 -0
  280. package/packages/happy2-server/dist/modules/request/rate-limit.test.js +123 -0
  281. package/packages/happy2-server/dist/modules/request/rate-limit.test.js.map +1 -0
  282. package/packages/happy2-server/dist/modules/schema.d.ts +31454 -0
  283. package/packages/happy2-server/dist/modules/schema.d.ts.map +1 -0
  284. package/packages/happy2-server/dist/modules/schema.js +1081 -0
  285. package/packages/happy2-server/dist/modules/schema.js.map +1 -0
  286. package/packages/happy2-server/dist/modules/workspace/index.d.ts +3 -0
  287. package/packages/happy2-server/dist/modules/workspace/index.d.ts.map +1 -0
  288. package/packages/happy2-server/dist/modules/workspace/index.js +3 -0
  289. package/packages/happy2-server/dist/modules/workspace/index.js.map +1 -0
  290. package/packages/happy2-server/dist/modules/workspace/service.d.ts +54 -0
  291. package/packages/happy2-server/dist/modules/workspace/service.d.ts.map +1 -0
  292. package/packages/happy2-server/dist/modules/workspace/service.js +997 -0
  293. package/packages/happy2-server/dist/modules/workspace/service.js.map +1 -0
  294. package/packages/happy2-server/dist/modules/workspace/types.d.ts +58 -0
  295. package/packages/happy2-server/dist/modules/workspace/types.d.ts.map +1 -0
  296. package/packages/happy2-server/dist/modules/workspace/types.js +11 -0
  297. package/packages/happy2-server/dist/modules/workspace/types.js.map +1 -0
  298. package/packages/happy2-server/dist/routes/agents.d.ts +5 -0
  299. package/packages/happy2-server/dist/routes/agents.d.ts.map +1 -0
  300. package/packages/happy2-server/dist/routes/agents.js +225 -0
  301. package/packages/happy2-server/dist/routes/agents.js.map +1 -0
  302. package/packages/happy2-server/dist/routes/auth.d.ts +5 -0
  303. package/packages/happy2-server/dist/routes/auth.d.ts.map +1 -0
  304. package/packages/happy2-server/dist/routes/auth.js +128 -0
  305. package/packages/happy2-server/dist/routes/auth.js.map +1 -0
  306. package/packages/happy2-server/dist/routes/automation.d.ts +6 -0
  307. package/packages/happy2-server/dist/routes/automation.d.ts.map +1 -0
  308. package/packages/happy2-server/dist/routes/automation.js +315 -0
  309. package/packages/happy2-server/dist/routes/automation.js.map +1 -0
  310. package/packages/happy2-server/dist/routes/basic.d.ts +3 -0
  311. package/packages/happy2-server/dist/routes/basic.d.ts.map +1 -0
  312. package/packages/happy2-server/dist/routes/basic.js +5 -0
  313. package/packages/happy2-server/dist/routes/basic.js.map +1 -0
  314. package/packages/happy2-server/dist/routes/collaboration.d.ts +7 -0
  315. package/packages/happy2-server/dist/routes/collaboration.d.ts.map +1 -0
  316. package/packages/happy2-server/dist/routes/collaboration.js +1285 -0
  317. package/packages/happy2-server/dist/routes/collaboration.js.map +1 -0
  318. package/packages/happy2-server/dist/routes/files.d.ts +9 -0
  319. package/packages/happy2-server/dist/routes/files.d.ts.map +1 -0
  320. package/packages/happy2-server/dist/routes/files.js +397 -0
  321. package/packages/happy2-server/dist/routes/files.js.map +1 -0
  322. package/packages/happy2-server/dist/routes/integrations.d.ts +6 -0
  323. package/packages/happy2-server/dist/routes/integrations.d.ts.map +1 -0
  324. package/packages/happy2-server/dist/routes/integrations.js +486 -0
  325. package/packages/happy2-server/dist/routes/integrations.js.map +1 -0
  326. package/packages/happy2-server/dist/routes/operations.d.ts +5 -0
  327. package/packages/happy2-server/dist/routes/operations.d.ts.map +1 -0
  328. package/packages/happy2-server/dist/routes/operations.js +588 -0
  329. package/packages/happy2-server/dist/routes/operations.js.map +1 -0
  330. package/packages/happy2-server/dist/routes/operations.test.d.ts +2 -0
  331. package/packages/happy2-server/dist/routes/operations.test.d.ts.map +1 -0
  332. package/packages/happy2-server/dist/routes/operations.test.js +106 -0
  333. package/packages/happy2-server/dist/routes/operations.test.js.map +1 -0
  334. package/packages/happy2-server/dist/routes/sync.d.ts +6 -0
  335. package/packages/happy2-server/dist/routes/sync.d.ts.map +1 -0
  336. package/packages/happy2-server/dist/routes/sync.js +549 -0
  337. package/packages/happy2-server/dist/routes/sync.js.map +1 -0
  338. package/packages/happy2-server/dist/routes/workspace.d.ts +5 -0
  339. package/packages/happy2-server/dist/routes/workspace.d.ts.map +1 -0
  340. package/packages/happy2-server/dist/routes/workspace.js +240 -0
  341. package/packages/happy2-server/dist/routes/workspace.js.map +1 -0
  342. package/packages/happy2-server/dist/runner.d.ts +3 -0
  343. package/packages/happy2-server/dist/runner.d.ts.map +1 -0
  344. package/packages/happy2-server/dist/runner.js +30 -0
  345. package/packages/happy2-server/dist/runner.js.map +1 -0
  346. package/packages/happy2-server/dist/server.d.ts +32 -0
  347. package/packages/happy2-server/dist/server.d.ts.map +1 -0
  348. package/packages/happy2-server/dist/server.js +284 -0
  349. package/packages/happy2-server/dist/server.js.map +1 -0
  350. package/packages/happy2-server/dist/standalone.d.ts +13 -0
  351. package/packages/happy2-server/dist/standalone.d.ts.map +1 -0
  352. package/packages/happy2-server/dist/standalone.js +99 -0
  353. package/packages/happy2-server/dist/standalone.js.map +1 -0
  354. package/packages/happy2-server/dist/web/assets/figtree-latin-wght-normal-D_ZTVpCC.woff2 +0 -0
  355. package/packages/happy2-server/dist/web/assets/happy-otter-Q2O_g-DT.png +0 -0
  356. package/packages/happy2-server/dist/web/assets/index-COvbX8JP.css +2 -0
  357. package/packages/happy2-server/dist/web/assets/index-DdpugxMO.js +57 -0
  358. package/packages/happy2-server/dist/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  359. package/packages/happy2-server/dist/web/assets/onboarding-CRUpq9xl.png +0 -0
  360. package/packages/happy2-server/dist/web/index.html +13 -0
  361. package/packages/happy2-server/drizzle/0000_initial.sql +13 -0
  362. package/packages/happy2-server/drizzle/0001_accounts_profiles_files.sql +42 -0
  363. package/packages/happy2-server/drizzle/0002_file_visibility_and_uploader.sql +5 -0
  364. package/packages/happy2-server/drizzle/0003_collaboration.sql +565 -0
  365. package/packages/happy2-server/drizzle/0004_collaboration_expansion.sql +1099 -0
  366. package/packages/happy2-server/drizzle/0005_ai_agents.sql +85 -0
  367. package/packages/happy2-server/drizzle/0006_rig_global_event_queue.sql +10 -0
  368. package/packages/happy2-server/drizzle/0007_rename_server_identity.sql +3 -0
  369. package/packages/happy2-server/drizzle/0008_agent_message_streaming.sql +47 -0
  370. package/packages/happy2-server/drizzle/0009_chat_workspace_binding_lookup.sql +2 -0
  371. package/packages/happy2-server/drizzle/0010_rig_secret_assignments.sql +21 -0
  372. package/packages/happy2-server/drizzle/meta/_journal.json +83 -0
  373. package/packages/happy2-server/happy2.example.toml +104 -0
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Happy (2)
2
+
3
+ Happy (2) is a desktop work and coding app that evolves by adopting itself. This
4
+ pnpm monorepo delivers its shared Solid UI through a web app and an Electron
5
+ desktop app. Happy (2) is desktop-only; its UI must not assume mobile use or adapt
6
+ for mobile viewports.
7
+
8
+ ## Packages
9
+
10
+ - `happy2-app` contains the shared Solid component and its tests.
11
+ - `happy2-web` imports `happy2-app` and creates a browser build.
12
+ - `happy2-desktop` imports `happy2-app` in an Electron renderer and builds its
13
+ Electron main process with Vite.
14
+ - `happy2-server` is the Fastify server and authentication-service package.
15
+ - The root `happy2` package bundles the server and built web app into the complete
16
+ distributable.
17
+ - `happy2-gym` is the isolated end-to-end testing environment. Its server harness runs
18
+ black-box HTTP tests against disposable in-memory server instances; see
19
+ [`packages/happy2-gym/README.md`](packages/happy2-gym/README.md) for usage.
20
+
21
+ ## Requirements
22
+
23
+ - Node.js 24 or later (required by Portless)
24
+ - pnpm 10.28 or later
25
+
26
+ TypeScript is on the v7 release line throughout the workspace.
27
+
28
+ ## Commands
29
+
30
+ ```sh
31
+ pnpm install
32
+ pnpm dev # Server + web app on stable Portless URLs
33
+ pnpm dev:desktop # Electron app connected to the server from pnpm dev
34
+ pnpm --dir packages/happy2-gym test # Server end-to-end tests
35
+ pnpm check # Type-check, test, and build every package
36
+ ```
37
+
38
+ `pnpm build` emits browser files to `packages/happy2-web/dist` and an Electron renderer
39
+ plus main process to `packages/happy2-desktop/dist`. Start the latter after building
40
+ with `pnpm --filter happy2-desktop start`.
41
+
42
+ `pnpm dev` runs the server and web app through Portless with interleaved logs.
43
+ The main checkout uses `https://happy2.localhost` and
44
+ `https://happy2-api.localhost`; linked worktrees automatically receive unique
45
+ branch-prefixed hostnames. The generated development TOML, database, files,
46
+ keys, and password pepper stay under `.context/dev` in each workspace.
47
+
48
+ With `pnpm dev` running, start `pnpm dev:desktop` in another terminal. It resolves
49
+ the same workspace-specific `happy2-api` URL and passes it to the Electron
50
+ renderer. Portless assigns the renderer an available workspace-specific port;
51
+ set `PORT=xxxx` only when you need to choose it explicitly.
52
+
53
+ Start only a local server with `pnpm dev:server`. Without a TOML file it enables
54
+ self-service password registration and login, creates its SQLite database under
55
+ `packages/happy2-server`, and generates durable local JWT keys plus password pepper in
56
+ `packages/happy2-server/.env` on first start. Pass `--config path/to/happy2.toml` (or
57
+ set `HAPPY2_CONFIG`) to override the defaults; copy the example TOML before
58
+ production deployment. See the server package README for deployment and auth
59
+ configuration.
60
+
61
+ ## Publishing
62
+
63
+ Authenticate with npm once using `pnpm login`, then publish the all-in-one `happy2`
64
+ from a clean, up-to-date `main` branch:
65
+
66
+ ```sh
67
+ pnpm release 0.1.0
68
+ ```
69
+
70
+ The release command also accepts semantic version bumps such as `patch`,
71
+ `minor`, and `major`. It checks the branch, working tree, and npm
72
+ authentication; runs the full workspace check; creates the release commit and
73
+ tag; previews the package; pushes to `main`; and publishes it publicly. If
74
+ publishing is interrupted after the tag is created, rerun the command with the
75
+ exact version to resume safely.
76
+
77
+ ## Working convention
78
+
79
+ “Sync to main” means to commit the current work, rebase it onto the latest
80
+ `origin/main`, and push the resulting `HEAD` to `main` without force. If `main`
81
+ advances or the push is rejected, fetch and rebase again before retrying. Never
82
+ force-push `main`.
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "happy2",
3
+ "version": "0.0.5",
4
+ "description": "Happy (2) desktop web app and server bundle",
5
+ "bin": {
6
+ "happy2": "packages/happy2-server/bin/happy2.js"
7
+ },
8
+ "files": [
9
+ "packages/happy2-server/bin/happy2.js",
10
+ "packages/happy2-server/dist",
11
+ "packages/happy2-server/drizzle",
12
+ "packages/happy2-server/happy2.example.toml",
13
+ "packages/happy2-server/README.md",
14
+ "packages/happy2-server/Dockerfile"
15
+ ],
16
+ "type": "module",
17
+ "main": "./packages/happy2-server/dist/index.js",
18
+ "types": "./packages/happy2-server/dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./packages/happy2-server/dist/index.d.ts",
22
+ "default": "./packages/happy2-server/dist/index.js"
23
+ }
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "engines": {
29
+ "node": ">=24.0.0",
30
+ "pnpm": ">=10.28.1"
31
+ },
32
+ "dependencies": {
33
+ "@fastify/cors": "^11.3.0",
34
+ "@fastify/http-proxy": "^11.5.0",
35
+ "@fastify/multipart": "^10.1.0",
36
+ "@fastify/static": "^10.1.0",
37
+ "@libsql/client": "^0.17.4",
38
+ "@paralleldrive/cuid2": "^3.3.0",
39
+ "@slopus/rig": "^0.0.17",
40
+ "drizzle-orm": "^0.45.2",
41
+ "fastify": "^5.8.2",
42
+ "jose": "^6.1.3",
43
+ "nodemailer": "^7.0.13",
44
+ "sharp": "^0.35.3",
45
+ "smol-toml": "^1.4.2",
46
+ "thumbhash": "^0.1.1"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^26.1.1",
50
+ "concurrently": "^10.0.3",
51
+ "oxfmt": "^0.57.0",
52
+ "oxlint": "^1.73.0",
53
+ "portless": "^0.15.1",
54
+ "tsx": "^4.21.0",
55
+ "typescript": "^7.0.2"
56
+ },
57
+ "scripts": {
58
+ "dev": "node scripts/dev.mjs",
59
+ "dev:web": "pnpm --filter happy2-web dev",
60
+ "dev:desktop": "node scripts/dev-desktop.mjs",
61
+ "dev:server": "pnpm --dir packages/happy2-server dev",
62
+ "start": "node packages/happy2-server/dist/runner.js",
63
+ "build": "pnpm -r --if-present build && VITE_HAPPY2_SERVER_URL='/' pnpm --filter happy2-web exec vite build --outDir ../happy2-server/dist/web --emptyOutDir false",
64
+ "test": "pnpm -r --if-present test",
65
+ "test:watch": "pnpm -r --parallel --if-present test:watch",
66
+ "typecheck": "tsc --project tsconfig.json && pnpm -r --if-present typecheck",
67
+ "format": "oxfmt --write scripts tsconfig.json && pnpm -r --if-present format",
68
+ "format:check": "oxfmt --check scripts tsconfig.json && pnpm -r --if-present format:check",
69
+ "lint": "oxlint scripts && pnpm -r --if-present lint",
70
+ "check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test && pnpm build",
71
+ "release": "tsx scripts/release.ts",
72
+ "clean": "pnpm -r --if-present clean"
73
+ }
74
+ }
@@ -0,0 +1,18 @@
1
+ # Build from the repository root:
2
+ # docker build -f packages/happy2-server/Dockerfile -t slopus/happy2 .
3
+ FROM node:22-bookworm-slim AS build
4
+ WORKDIR /workspace
5
+ RUN corepack enable
6
+ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
7
+ COPY packages/happy2-server/package.json packages/happy2-server/package.json
8
+ RUN pnpm install --frozen-lockfile
9
+ COPY packages/happy2-server packages/happy2-server
10
+ RUN pnpm --filter happy2-server build:server \
11
+ && pnpm --filter happy2-server --prod deploy /app
12
+
13
+ FROM node:22-bookworm-slim
14
+ ENV NODE_ENV=production
15
+ WORKDIR /app
16
+ COPY --from=build /app ./
17
+ EXPOSE 3000
18
+ ENTRYPOINT ["node", "dist/cli.js"]
@@ -0,0 +1,418 @@
1
+ # `happy2-server`
2
+
3
+ `happy2-server` is the Fastify backend for deployments that run one service
4
+ (`server.role = "all"`), a dedicated authentication service (`"auth"`), or an
5
+ API-side token validator (`"api"`). All useful backend endpoints are versioned
6
+ under `/v0`; the backend's `/` remains only a small service-status response.
7
+
8
+ ## Run
9
+
10
+ ```sh
11
+ # Published backend package
12
+ npx happy2-server --config ./happy2.toml
13
+
14
+ # Published all-in-one web app and API on http://127.0.0.1:3000
15
+ npx happy2
16
+
17
+ # Development, with reload and no configuration file:
18
+ pnpm dev:server
19
+
20
+ # Locally built backend:
21
+ cp packages/happy2-server/happy2.example.toml happy2.toml
22
+ pnpm --filter happy2-server build
23
+ pnpm --filter happy2-server start -- --config ../../happy2.toml
24
+
25
+ # Locally built complete package:
26
+ pnpm build
27
+ pnpm start -- --config ./happy2.toml
28
+ ```
29
+
30
+ The all-in-one `happy2` executable starts the API on an ephemeral loopback port, serves the
31
+ packaged SPA on the configured public port, and streams `/v0` requests through
32
+ an internal reverse proxy. The web app therefore uses one origin for normal
33
+ HTTP, uploads, and server-sent events. The configured `trusted_proxy_hops`
34
+ continues to describe only proxies outside Happy (2); the private loopback hop is
35
+ handled internally.
36
+
37
+ Without a TOML file, the package starts an `all`-role app on `127.0.0.1:3000`
38
+ with SQLite, self-service password registration, and generated JWT/pepper
39
+ material. Database, files, generated secrets, agent workspaces, and Rig runtime
40
+ state live under `.happy2` in the invoking directory. Add `.happy2` to the
41
+ project's ignore rules and preserve it as private application state. The
42
+ package starts its bundled `@slopus/rig` executable with a private Rig home under
43
+ `.happy2/rig` by default, containing configuration, runtime settings, session
44
+ state, socket, and token. Set `RIG_HOME` to an absolute path to relocate it. The
45
+ package never connects to the user's global Rig daemon. Provide
46
+ `--config /path/to/happy2.toml` or
47
+ `HAPPY2_CONFIG=/path/to/happy2.toml` to override the defaults.
48
+
49
+ Clients can discover the selected authentication method at `GET /v0/auth/methods`.
50
+ The response includes the server role and one `method` value: `password`,
51
+ `magic_link`, `oidc`, `cloudflare_access`, or `null` in validation-only API mode. Password responses
52
+ also report `signupEnabled`; OIDC responses report `oidcProvider`.
53
+
54
+ ## Profiles and avatar files
55
+
56
+ Authentication creates an inactive account. `POST /v0/me/createProfile` (with the
57
+ temporary bearer token) creates the product-level User profile—first name,
58
+ optional last name, username, optional email, and optional phone—and activates
59
+ the account. `GET /v0/me` reads the active profile and
60
+ `POST /v0/me/updateProfile` replaces its editable state. Product routes reject
61
+ accounts that do not yet have an active profile.
62
+
63
+ `POST /v0/me/uploadAvatarFile` accepts one multipart image after profile
64
+ creation. Its required `visibility` field is `public` or `private`. Images over
65
+ 2048px on either side or 10 MB are rejected. The server records the uploader,
66
+ stores an unguessable CUID2-backed file record plus a JPEG file, converts the
67
+ image to a 1024×1024 JPEG, and records a ThumbHash.
68
+
69
+ `POST /v0/me/updateAvatar` takes a `fileId` and accepts only a public file the
70
+ current user uploaded. Public files are fetched directly with
71
+ `GET /v0/files/:fileId` plus the normal bearer header; they do not use signed
72
+ URLs. Private files are fetched using a five-minute signed URL produced by
73
+ `POST /v0/files/:fileId/createSignedUrl`.
74
+
75
+ The server applies the bundled Drizzle SQLite migrations at startup. `file:`
76
+ database URLs are suitable when all replicas share one local filesystem with
77
+ SQLite locking. For independently deployed auth and API services, configure a
78
+ shared `libsql:`/`https:` SQLite endpoint and, if needed, set its auth-token
79
+ environment variable named by `database.auth_token_env`.
80
+
81
+ Build the image from the repository root:
82
+
83
+ ```sh
84
+ docker build -f packages/happy2-server/Dockerfile -t slopus/happy2 .
85
+ docker run --rm -p 3000:3000 -v "$PWD/happy2.toml:/app/happy2.toml:ro" slopus/happy2 --config /app/happy2.toml
86
+ ```
87
+
88
+ Mount a writable directory containing `happy2.toml` when using generated key
89
+ material, because the adjacent `.env` file is the durable key store.
90
+
91
+ ## Authentication
92
+
93
+ Choose exactly one of password, magic-link, OIDC, or Cloudflare Access in `happy2.toml`; startup
94
+ rejects configurations that enable more than one method. Clients can learn the
95
+ selected method from `GET /v0/auth/methods`.
96
+
97
+ - Password registration is disabled unless `signup_enabled` is true. Every
98
+ password has its own random salt; a server-wide password pepper is also used.
99
+ - Magic-link SMTP credentials are exclusively `EMAIL_SMTP_HOST`,
100
+ `EMAIL_SMTP_PORT`, `EMAIL_SMTP_USER`, and `EMAIL_SMTP_PASSWORD` environment
101
+ variables. The configured `redirect_url` should be the desktop app’s link
102
+ handler; it submits the token to `POST /v0/auth/magic-link/verify`.
103
+ - OIDC uses discovery, PKCE, a nonce, and remote JWKS validation. Provider
104
+ secrets are referenced by environment-variable name in TOML.
105
+ - Cloudflare Access validates the signed `Cf-Access-Jwt-Assertion` that Access
106
+ forwards after its policy permits the request. It uses the Access application
107
+ session rather than issuing a Happy (2) bearer token.
108
+
109
+ ### Cloudflare Access
110
+
111
+ Cloudflare Access can provide all interactive authentication for a deployment.
112
+ Create a **Self-hosted** HTTP application for the public Happy (2) hostname,
113
+ attach the intended Access policy and identity providers, then configure this
114
+ as the only enabled method:
115
+
116
+ ```toml
117
+ [auth.password]
118
+ enabled = false
119
+
120
+ [auth.magic_link]
121
+ enabled = false
122
+
123
+ [auth.cloudflare_access]
124
+ enabled = true
125
+ team_domain = "https://your-team.cloudflareaccess.com"
126
+ # Zero Trust → Access controls → Applications → your application →
127
+ # Additional settings → Application Audience (AUD) Tag.
128
+ audience = "your-access-application-aud-tag"
129
+ ```
130
+
131
+ The server fetches the signing keys from the configured team domain and accepts
132
+ only an RS256 application assertion whose issuer and audience match this
133
+ configuration. It requires the Access JWT's `type`, `sub`, `email`, and expiry
134
+ claims, then maps the `(team domain, sub)` identity to a Happy (2) account.
135
+ As with the other methods, a newly authenticated account cannot use product
136
+ routes until it has an active profile.
137
+
138
+ Do not expose the origin directly. Use Cloudflare Tunnel or a network firewall
139
+ that allows only Cloudflare to reach it; otherwise a captured valid assertion
140
+ could be replayed directly to the origin until it expires. Happy (2) validates
141
+ the assertion itself and deliberately does not trust identity headers or the
142
+ `CF_Authorization` cookie. Cloudflare's browser/logout flow owns the session;
143
+ use `https://your-happy-host/cdn-cgi/access/logout` to end it. Consequently,
144
+ `POST /v0/auth/refresh` does not apply and `POST /v0/auth/logout` returns
145
+ `cloudflare_access_manages_session`.
146
+
147
+ The web bundle must be served from the protected hostname so browser requests,
148
+ SSE, and the `CF_Authorization` cookie share one origin. To run the Electron
149
+ desktop shell against that deployed bundle, start it with:
150
+
151
+ ```sh
152
+ HAPPY2_SERVER_URL="https://happy.example.com" pnpm --filter happy2-desktop start
153
+ ```
154
+
155
+ Electron loads the protected hostname in its own browser session, so Access
156
+ performs its normal redirect before Happy (2) renders. Do not point the bundled
157
+ local renderer at this hostname: that cross-origin arrangement cannot safely
158
+ reuse Cloudflare's HttpOnly application cookie.
159
+
160
+ On initial startup, external environment values win. If an auth-capable server
161
+ has no JWT private key configured, it generates a 3072-bit RS256 key pair and
162
+ adds base64-encoded `HAPPY2_JWT_PRIVATE_KEY_B64` and
163
+ `HAPPY2_JWT_PUBLIC_KEY_B64` to the `.env` file beside its TOML file. It likewise
164
+ adds `HAPPY2_PASSWORD_PEPPER` when password auth is enabled. Preserve that file
165
+ as a secret; replacing it invalidates existing passwords and sessions. You may
166
+ instead supply those variables through the deployment environment or mount PEM
167
+ key files via the `jwt` config.
168
+
169
+ Sessions are signed JWTs with a 30-day default lifetime and a stable `sid`.
170
+ `POST /v0/auth/refresh` re-signs the same session ID and advances the database
171
+ expiry. All authenticated requests check the shared SQLite session row, so a
172
+ missing, expired, or revoked row is rejected regardless of JWT validity.
173
+
174
+ ## Collaboration API
175
+
176
+ The API is HTTP-only. Durable reads and actions use JSON GET/POST endpoints;
177
+ live hints, typing, presence, and WebRTC signaling use Server-Sent Events. All
178
+ product routes require an active User profile. An `auth`-role server does not
179
+ serve collaboration routes; `all` and `api` roles do.
180
+
181
+ The main route groups are:
182
+
183
+ | Area | Route families |
184
+ | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
185
+ | Chats | `/v0/chats`, `createDirectMessage`, `createGroupDirectMessage`, `createChannel`, and channel update/archive/unarchive/delete actions |
186
+ | Membership and policy | chat join/leave/add/remove/set-role actions, member lists, posting policy, retention policy, topic, and owner transfer |
187
+ | Messages | history and message reads; send/edit/delete/forward actions; revision history; read receipts and unread state |
188
+ | Replies and threads | `quotedMessageId` creates an explicit reply in the main timeline; thread send/list/subscription/read actions maintain a separate timeline |
189
+ | Message organization | reactions, custom emoji, pins, chat and user bookmarks, scheduled messages, notifications, stars, and per-user ordering |
190
+ | Discovery | contacts, directories, files, thread inbox, calls, and fuzzy global search across visible users, channels, and messages |
191
+ | Files | streaming and resumable uploads, upload state/cancel/complete, ranged downloads, image/video previews, deletion, and signed URLs |
192
+ | Presence and calls | durable user status/DND preferences, ephemeral presence and typing, call lifecycle, and ephemeral WebRTC signaling |
193
+ | Sync | state, paginated server/chat differences, consumer acknowledgement, compaction/reset, and SSE hints |
194
+ | Operations | audit logs, access telemetry, bans, reports/actions, data-export jobs, backup records, retention runs, and server/user administration |
195
+ | Integrations | bots, scoped API credentials, credential-authenticated posting, incoming/outgoing webhooks, slash commands, and delivery queues |
196
+ | Automation | scheduled messages plus schedule, durable event, authenticated webhook, outgoing-webhook, bot-message, and moderation automations |
197
+
198
+ ## AI agents
199
+
200
+ `POST /v0/chats/createAgent` requires a display name and unique username. It
201
+ creates an ordinary `User` with `kind = "agent"`, records the creating user, and
202
+ opens a normal two-member direct message with it. There is no agent-specific
203
+ chat kind. Creation is rejected until an administrator has built and selected a
204
+ ready default image.
205
+ Agents share the normal user profile, username, sender, directory, mention, and
206
+ typing paths; only their Rig execution bindings are agent-specific. The product
207
+ server—not the desktop or web client—creates and controls Rig sessions over its
208
+ authenticated Unix socket. Configure `[agents]` with the socket, token, Rig
209
+ executable, and server-owned `default_cwd`; clients cannot select filesystem
210
+ paths.
211
+
212
+ The server seeds immutable `Daycare Minimal` and `Daycare Full` definitions from
213
+ the pinned upstream Daycare runtime Dockerfiles. Both use Ubuntu 24.04; Full adds
214
+ the Python, Rust, and Go toolchains. Administrators use
215
+ `GET /v0/admin/agentImages`, `GET /v0/admin/agentImages/:imageId`,
216
+ `POST /v0/admin/agentImages/:imageId/buildImage`,
217
+ `POST /v0/admin/agentImages/createImage`, and
218
+ `POST /v0/admin/agentImages/:imageId/setDefaultImage` to list concise build
219
+ summaries, inspect a definition's Dockerfile and latest build log, build a
220
+ built-in or custom persisted Dockerfile, and select a ready default. List rows
221
+ include a best-effort 0–100 step percentage and the last non-empty log line;
222
+ detail responses include the Dockerfile, log, and an explicit truncation flag.
223
+ Definitions and content-derived tags never change. Builds are leased in SQLite,
224
+ resume after server restart, use the administrator host's active Docker context,
225
+ and publish durable `agent-images` sync hints over the existing SSE connection.
226
+ Docker output is persisted in 500 ms batches so progress remains live without
227
+ turning every process chunk into a SQLite transaction. The latest attempt's log
228
+ is capped at two million characters and retries begin a fresh log.
229
+
230
+ Each agent is rooted at `default_cwd/agents/<agent-user-id>`. Direct/private
231
+ conversations get separate `users/<human-user-id>/home` and
232
+ `users/<human-user-id>/workspace` directories below that root, preventing one
233
+ person's files and context from leaking into another's. The server starts one
234
+ long-lived container with a read-only root filesystem, writable tmpfs mounts at
235
+ `/tmp`, `/run`, `/var/tmp`, and `/var/run`, 1 GiB `/dev/shm`, init enabled, and
236
+ only the private home and workspace mounted read-write at `/home` and
237
+ `/workspace`. It then creates the Rig session with Rig's built-in existing
238
+ container configuration and `/workspace` working directory. For now, only
239
+ top-level messages in exact two-user DMs invoke Rig. Agents may be ordinary
240
+ members of group DMs and channels—including multiple agents in one channel—but
241
+ those conversations remain dormant until mention-based collaboration is
242
+ implemented.
243
+
244
+ The workspace file API is available to any chat that has exactly one connected
245
+ Rig environment. It resolves the persisted `agent_rig_bindings.cwd` host path,
246
+ which is the directory mounted into that environment at `/workspace`; it never
247
+ creates a separate directory from the chat ID. A current chat member can read
248
+ its file-tree snapshot from `GET /v0/chats/:chatId/workspace`. An unconnected or
249
+ ambiguous chat returns `404`, and public-channel discovery alone never reveals
250
+ workspace contents. Paths are canonical `@pierre/trees` input (directory paths
251
+ end in `/`), absolute server paths are never returned, and directory symlinks
252
+ are listed without being traversed.
253
+
254
+ The first request lazily creates a process-local partial index and starts its
255
+ recursive monitor before reading the root. Adaptive preload returns at most
256
+ 2,500 paths, 192 KiB of encoded path data, three levels, and 128 inspected
257
+ directories. A directory with more than 400 direct children remains collapsed.
258
+ The default-deferred basenames are `.git`, `.next`, `.pnpm`, `.turbo`, `.yarn`,
259
+ `.cache`, `build`, `coverage`, `dist`, `node_modules`, `target`, and `vendor`.
260
+ These entries are visible and fully accessible; the preload simply does not
261
+ descend into them. `unloadedDirectories` identifies every visible directory
262
+ whose children still need to be loaded.
263
+
264
+ `GET /v0/chats/:chatId/workspace?directory=<canonical-directory>` pages one
265
+ directory's direct children, including the root when `directory` is empty. The
266
+ default page is 250 entries, callers may request up to 1,000, and an adaptive
267
+ 128 KiB path-data ceiling can end a page earlier. `nextCursor` continues the
268
+ same directory; a filesystem change invalidates it with `409
269
+ workspace_cursor_stale`. All entries—including hidden files and the contents of
270
+ `.git/`—remain reachable through these pages.
271
+
272
+ Directory listings use a per-workspace LRU capped at 20,000 entries. Chats
273
+ connected to the same mounted host directory share one index and monitor. At
274
+ most 8 partial indexes stay warm; cooling an older index releases its directory
275
+ and Git caches but keeps its lightweight monitor active, and the next request
276
+ warms it again. Git status initializes and refreshes in the background, so a
277
+ cold tree response does not wait for Git. Responses expose `gitStatusPending`
278
+ and a process-local `revision`; completion publishes the same
279
+ `workspace.changed` SSE invalidation as a filesystem mutation. File changes are
280
+ coalesced for 20 ms,
281
+ invalidate only affected directory-cache branches when the watcher supplies a
282
+ path, and cause clients to reconcile through the HTTP snapshot. Successful
283
+ responses provide a private, revalidated `ETag`, allowing an unchanged
284
+ reconciliation to return no body over a slow connection. All indexes and
285
+ monitors close with the server.
286
+
287
+ If the configured socket is unavailable, Happy (2) runs `rig daemon start` without
288
+ a shell and passes the configured socket and token paths through Rig's standard
289
+ environment variables. User turns are ordinary chat messages. The message and
290
+ its durable `agent_turns` outbox row commit in one SQLite transaction; leased
291
+ workers then serialize turns per agent and chat and resume them after restart.
292
+ At startup the server enables Rig's durable global event queue when necessary.
293
+ It consumes the queue through one resumable global SSE connection and a numeric
294
+ cursor persisted in SQLite; it never polls the queue or opens per-session event
295
+ streams. Agent work is broadcast through the ordinary typing-presence event,
296
+ and persisted replies use the agent `User` as sender, update human unread
297
+ counts, and then publish normal sync hints. Agent users never accumulate unread
298
+ counters, receipts, or notifications. Applied Rig events are trimmed in batches
299
+ after 1,000 updates or one day. Remote clients use the same chat and sync APIs as
300
+ local clients and never need access to Rig itself.
301
+
302
+ Rig remains the source of truth for agent secret registrations and values.
303
+ Administrators use `GET /v0/admin/agentSecrets`,
304
+ `POST /v0/admin/agentSecrets/createSecret`, and
305
+ `POST /v0/admin/agentSecrets/:secretId/deleteSecret` through Happy (2); list and
306
+ mutation responses contain only the Rig ID, description, and environment-variable
307
+ names. Secret values are forwarded once to Rig and are never persisted in the
308
+ Happy (2) database or returned to a client. Happy (2) stores only assignments,
309
+ managed through the `attachToAgent`, `detachFromAgent`, `attachToChannel`, and
310
+ `detachFromChannel` actions. An agent assignment applies to every Rig session for
311
+ that agent; a channel assignment applies to every agent Rig session bound to that
312
+ channel. The union is reconciled before each turn and when Happy (2) starts, while
313
+ Rig still requires the model to select the needed bundle IDs on each shell command.
314
+ All secret-management routes require server-admin permission and publish durable
315
+ `agent-secrets` sync hints.
316
+
317
+ Channels are `public_channel` or `private_channel`. Direct chats support both
318
+ exact two-user DMs and membership-exact group DMs. Public channels can be
319
+ discovered and read by every active server member, but posting requires joining.
320
+ Private channels and DMs require current membership. Channel owners remain
321
+ canonical through leave, removal, role changes, and account deletion. The first
322
+ active profile is a server administrator. Administrators can change the server
323
+ profile and retention defaults, manage user titles/roles, inspect durable
324
+ last-access times, ban or delete users, moderate content and files, and send
325
+ audited automated messages.
326
+
327
+ `POST /v0/files/upload` streams one file to storage and returns a stable CUID2
328
+ file ID. Large clients use `createUpload`, ordered `appendUpload` calls, and
329
+ `completeUpload`; completion is replay-safe across a process crash. JPEG, PNG,
330
+ WebP, GIF, MP4, and WebM signatures are recognized, metadata is probed with
331
+ bounded work, previews/posters are tracked as derivatives, and downloads support
332
+ byte ranges. Storage and malware scanning are provider interfaces. Quota is
333
+ reserved while bytes are staged, rejected content is quarantined, scan results
334
+ are durable, and periodic maintenance releases abandoned reservations and
335
+ staging artifacts.
336
+
337
+ A file is visible to its uploader, through an explicit unexpired user/chat/server
338
+ grant, as a public profile or custom-emoji asset, or through a live message the
339
+ requester can currently read. Forwarding creates a destination attachment grant
340
+ without promoting the file globally. Deleting or expiring the last visible
341
+ message reference removes that derived access. The files directory and previews
342
+ use the same authorization query, so private-channel and DM attachments do not
343
+ leak.
344
+
345
+ Message sends accept an optional `clientMutationId`; retries by the same user in
346
+ the same chat return the originally committed message. A send may contain text,
347
+ attachment file IDs, `quotedMessageId`, `threadRootMessageId`, and a bounded
348
+ self-destruction duration. Deletion and expiry leave syncable tombstones rather
349
+ than hard-deleting message identity, remove searchable/revision plaintext, and
350
+ recompute thread projections. `after_read` destruction uses a send-time receipt
351
+ roster, so users who join later cannot block expiry.
352
+
353
+ HTTP write actions also accept `Idempotency-Key`. Keys are isolated by the
354
+ authenticated principal and concrete action path, conflicting payload reuse is
355
+ rejected, and completed responses survive restart. Request limiting and realtime
356
+ fanout use local adapter implementations; Redis-backed implementations can be
357
+ added without making process-local state authoritative.
358
+
359
+ ## Sync protocol
360
+
361
+ The protocol adapts Telegram's independent update sequences, state snapshots,
362
+ and paginated differences, as described in its official
363
+ [Working with Updates](https://core.telegram.org/api/updates),
364
+ [`updates.getState`](https://core.telegram.org/method/updates.getState), and
365
+ [`updates.getDifference`](https://core.telegram.org/method/updates.getDifference)
366
+ documentation.
367
+
368
+ Happy (2) has two durable cursor levels:
369
+
370
+ - A database-generation ID and server-wide `sequence` identify durable objects
371
+ that changed for reconnect discovery.
372
+ - Every chat has an independent `pts`. Messages, reactions, tombstones, thread
373
+ activity, topics, and membership-visible changes advance that chat's `pts`.
374
+
375
+ Cursors are decimal strings in JSON, never JSON numbers; the current server
376
+ rejects cursor values outside its safe-integer operating range. Every mutation
377
+ allocates the common sequence, changes domain rows, advances affected chat
378
+ cursors, and appends update pointers in one database transaction. Pubsub happens
379
+ only after commit. The local pubsub implementation is intentionally replaceable
380
+ by a Redis adapter and is allowed to drop, duplicate, reorder, or coalesce events.
381
+
382
+ 1. `GET /v0/sync/state` returns `{protocolVersion, generation, sequence}`. On a
383
+ new installation this is a baseline, not the beginning of retained history.
384
+ 2. `POST /v0/sync/getDifference` takes the last stored
385
+ `state: {generation, sequence}`, optional fixed `untilSequence`, and `limit`.
386
+ It returns changed chat summaries with
387
+ their latest `pts`, removed private-chat IDs, changed global areas, an
388
+ intermediate state, and the fixed target state. A slice is repeated with its
389
+ intermediate cursor and the same target until complete.
390
+ 3. For every changed chat, `POST /v0/chats/:chatId/getDifference` takes the
391
+ cached `state: {membershipEpoch, pts}`. It returns ordered pointers plus
392
+ current message projections/tombstones. A changed membership epoch or pruned
393
+ cursor returns a reset/too-long result; the client discards that cached chat
394
+ and fetches current history.
395
+ 4. The client advances its common cursor in the same local transaction that
396
+ stores pending target `pts` values. It advances a chat cursor only with the
397
+ corresponding projections/tombstones. Duplicate projections are safe.
398
+ 5. `POST /v0/sync/acknowledge` records a per-user, per-device durable consumer
399
+ cursor. Compaction honors active acknowledgements and retention windows. A
400
+ cursor older than retained history receives an explicit reset with the
401
+ minimum recoverable sequence rather than an incomplete difference.
402
+
403
+ For a chat update with `ptsCount`, clients use the Telegram rule:
404
+
405
+ ```text
406
+ localPts + ptsCount == update.pts apply it
407
+ localPts + ptsCount > update.pts ignore the duplicate
408
+ localPts + ptsCount < update.pts stop and fetch the difference
409
+ ```
410
+
411
+ `GET /v0/sync/events` is a deliberately lossy SSE stream. It first subscribes,
412
+ then emits `ready` with current durable state. `sync` events only hint at a newer
413
+ server sequence/chat `pts`; clients never advance a durable cursor from SSE.
414
+ `typing`, `presence`, and `call.signal` are ephemeral and never enter a
415
+ difference. Heartbeats include a fresh database state and revalidate the session,
416
+ so another local instance's commit, a missed publish, ban, or logout is detected.
417
+ Every reconnect runs the HTTP difference flow; `Last-Event-ID` is not a sync
418
+ cursor.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import "../dist/runner.js";
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../sources/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { TokenService } from "./modules/auth/tokens.js";
4
+ import { loadRuntimeConfig } from "./modules/config/runtime.js";
5
+ import { Database } from "./modules/database.js";
6
+ import { buildServer } from "./server.js";
7
+ const { values } = parseArgs({
8
+ options: { config: { type: "string" } },
9
+ });
10
+ const configPath = values.config ?? process.env.HAPPY2_CONFIG;
11
+ const { config } = await loadRuntimeConfig(configPath);
12
+ const database = new Database(config.database.url, config.database.authTokenEnv ? process.env[config.database.authTokenEnv] : undefined);
13
+ await database.migrate();
14
+ const app = await buildServer(config, { database, tokens: await TokenService.create(config) });
15
+ let cleanupPromise;
16
+ const cleanup = () => {
17
+ cleanupPromise ??= (async () => {
18
+ try {
19
+ await app.close();
20
+ }
21
+ finally {
22
+ database.close();
23
+ }
24
+ })();
25
+ return cleanupPromise;
26
+ };
27
+ try {
28
+ await app.listen({ host: config.server.host, port: config.server.port });
29
+ const stop = () => {
30
+ void cleanup().catch((error) => {
31
+ app.log.error(error);
32
+ process.exitCode = 1;
33
+ });
34
+ };
35
+ process.once("SIGHUP", stop);
36
+ process.once("SIGINT", stop);
37
+ process.once("SIGTERM", stop);
38
+ }
39
+ catch (error) {
40
+ app.log.error(error);
41
+ await cleanup().catch((cleanupError) => app.log.error(cleanupError));
42
+ process.exitCode = 1;
43
+ }
44
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../sources/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;CAC1C,CAAC,CAAC;AACH,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AAC9D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;AACvD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CACzB,MAAM,CAAC,QAAQ,CAAC,GAAG,EACnB,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CACvF,CAAC;AACF,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;AACzB,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC/F,IAAI,cAAyC,CAAC;AAC9C,MAAM,OAAO,GAAG,GAAG,EAAE;IACjB,cAAc,KAAK,CAAC,KAAK,IAAI,EAAE;QAC3B,IAAI,CAAC;YACD,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;gBAAS,CAAC;YACP,QAAQ,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;IACL,CAAC,CAAC,EAAE,CAAC;IACL,OAAO,cAAc,CAAC;AAC1B,CAAC,CAAC;AACF,IAAI,CAAC;IACD,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,GAAG,EAAE;QACd,KAAK,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACpC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACb,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,MAAM,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,YAAqB,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACzB,CAAC"}