availsync 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (460) hide show
  1. package/.adal/skills/stripe-best-practices/SKILL.md +42 -0
  2. package/.adal/skills/stripe-best-practices/references/billing.md +36 -0
  3. package/.adal/skills/stripe-best-practices/references/connect.md +48 -0
  4. package/.adal/skills/stripe-best-practices/references/payments.md +79 -0
  5. package/.adal/skills/stripe-best-practices/references/security.md +109 -0
  6. package/.adal/skills/stripe-best-practices/references/treasury.md +16 -0
  7. package/.adal/skills/stripe-projects/SKILL.md +139 -0
  8. package/.adal/skills/upgrade-stripe/SKILL.md +185 -0
  9. package/.agents/skills/stripe-best-practices/SKILL.md +42 -0
  10. package/.agents/skills/stripe-best-practices/references/billing.md +36 -0
  11. package/.agents/skills/stripe-best-practices/references/connect.md +48 -0
  12. package/.agents/skills/stripe-best-practices/references/payments.md +79 -0
  13. package/.agents/skills/stripe-best-practices/references/security.md +109 -0
  14. package/.agents/skills/stripe-best-practices/references/treasury.md +16 -0
  15. package/.agents/skills/stripe-projects/SKILL.md +139 -0
  16. package/.agents/skills/upgrade-stripe/SKILL.md +185 -0
  17. package/.augment/skills/stripe-best-practices/SKILL.md +42 -0
  18. package/.augment/skills/stripe-best-practices/references/billing.md +36 -0
  19. package/.augment/skills/stripe-best-practices/references/connect.md +48 -0
  20. package/.augment/skills/stripe-best-practices/references/payments.md +79 -0
  21. package/.augment/skills/stripe-best-practices/references/security.md +109 -0
  22. package/.augment/skills/stripe-best-practices/references/treasury.md +16 -0
  23. package/.augment/skills/stripe-projects/SKILL.md +139 -0
  24. package/.augment/skills/upgrade-stripe/SKILL.md +185 -0
  25. package/.bob/skills/stripe-best-practices/SKILL.md +42 -0
  26. package/.bob/skills/stripe-best-practices/references/billing.md +36 -0
  27. package/.bob/skills/stripe-best-practices/references/connect.md +48 -0
  28. package/.bob/skills/stripe-best-practices/references/payments.md +79 -0
  29. package/.bob/skills/stripe-best-practices/references/security.md +109 -0
  30. package/.bob/skills/stripe-best-practices/references/treasury.md +16 -0
  31. package/.bob/skills/stripe-projects/SKILL.md +139 -0
  32. package/.bob/skills/upgrade-stripe/SKILL.md +185 -0
  33. package/.claude/settings.local.json +7 -0
  34. package/.claude/skills/stripe-best-practices/SKILL.md +42 -0
  35. package/.claude/skills/stripe-best-practices/references/billing.md +36 -0
  36. package/.claude/skills/stripe-best-practices/references/connect.md +48 -0
  37. package/.claude/skills/stripe-best-practices/references/payments.md +79 -0
  38. package/.claude/skills/stripe-best-practices/references/security.md +109 -0
  39. package/.claude/skills/stripe-best-practices/references/treasury.md +16 -0
  40. package/.claude/skills/stripe-projects/SKILL.md +139 -0
  41. package/.claude/skills/upgrade-stripe/SKILL.md +185 -0
  42. package/.codebuddy/skills/stripe-best-practices/SKILL.md +42 -0
  43. package/.codebuddy/skills/stripe-best-practices/references/billing.md +36 -0
  44. package/.codebuddy/skills/stripe-best-practices/references/connect.md +48 -0
  45. package/.codebuddy/skills/stripe-best-practices/references/payments.md +79 -0
  46. package/.codebuddy/skills/stripe-best-practices/references/security.md +109 -0
  47. package/.codebuddy/skills/stripe-best-practices/references/treasury.md +16 -0
  48. package/.codebuddy/skills/stripe-projects/SKILL.md +139 -0
  49. package/.codebuddy/skills/upgrade-stripe/SKILL.md +185 -0
  50. package/.commandcode/skills/stripe-best-practices/SKILL.md +42 -0
  51. package/.commandcode/skills/stripe-best-practices/references/billing.md +36 -0
  52. package/.commandcode/skills/stripe-best-practices/references/connect.md +48 -0
  53. package/.commandcode/skills/stripe-best-practices/references/payments.md +79 -0
  54. package/.commandcode/skills/stripe-best-practices/references/security.md +109 -0
  55. package/.commandcode/skills/stripe-best-practices/references/treasury.md +16 -0
  56. package/.commandcode/skills/stripe-projects/SKILL.md +139 -0
  57. package/.commandcode/skills/upgrade-stripe/SKILL.md +185 -0
  58. package/.continue/skills/stripe-best-practices/SKILL.md +42 -0
  59. package/.continue/skills/stripe-best-practices/references/billing.md +36 -0
  60. package/.continue/skills/stripe-best-practices/references/connect.md +48 -0
  61. package/.continue/skills/stripe-best-practices/references/payments.md +79 -0
  62. package/.continue/skills/stripe-best-practices/references/security.md +109 -0
  63. package/.continue/skills/stripe-best-practices/references/treasury.md +16 -0
  64. package/.continue/skills/stripe-projects/SKILL.md +139 -0
  65. package/.continue/skills/upgrade-stripe/SKILL.md +185 -0
  66. package/.cortex/skills/stripe-best-practices/SKILL.md +42 -0
  67. package/.cortex/skills/stripe-best-practices/references/billing.md +36 -0
  68. package/.cortex/skills/stripe-best-practices/references/connect.md +48 -0
  69. package/.cortex/skills/stripe-best-practices/references/payments.md +79 -0
  70. package/.cortex/skills/stripe-best-practices/references/security.md +109 -0
  71. package/.cortex/skills/stripe-best-practices/references/treasury.md +16 -0
  72. package/.cortex/skills/stripe-projects/SKILL.md +139 -0
  73. package/.cortex/skills/upgrade-stripe/SKILL.md +185 -0
  74. package/.crush/skills/stripe-best-practices/SKILL.md +42 -0
  75. package/.crush/skills/stripe-best-practices/references/billing.md +36 -0
  76. package/.crush/skills/stripe-best-practices/references/connect.md +48 -0
  77. package/.crush/skills/stripe-best-practices/references/payments.md +79 -0
  78. package/.crush/skills/stripe-best-practices/references/security.md +109 -0
  79. package/.crush/skills/stripe-best-practices/references/treasury.md +16 -0
  80. package/.crush/skills/stripe-projects/SKILL.md +139 -0
  81. package/.crush/skills/upgrade-stripe/SKILL.md +185 -0
  82. package/.env.example +20 -0
  83. package/.factory/skills/stripe-best-practices/SKILL.md +42 -0
  84. package/.factory/skills/stripe-best-practices/references/billing.md +36 -0
  85. package/.factory/skills/stripe-best-practices/references/connect.md +48 -0
  86. package/.factory/skills/stripe-best-practices/references/payments.md +79 -0
  87. package/.factory/skills/stripe-best-practices/references/security.md +109 -0
  88. package/.factory/skills/stripe-best-practices/references/treasury.md +16 -0
  89. package/.factory/skills/stripe-projects/SKILL.md +139 -0
  90. package/.factory/skills/upgrade-stripe/SKILL.md +185 -0
  91. package/.goose/skills/stripe-best-practices/SKILL.md +42 -0
  92. package/.goose/skills/stripe-best-practices/references/billing.md +36 -0
  93. package/.goose/skills/stripe-best-practices/references/connect.md +48 -0
  94. package/.goose/skills/stripe-best-practices/references/payments.md +79 -0
  95. package/.goose/skills/stripe-best-practices/references/security.md +109 -0
  96. package/.goose/skills/stripe-best-practices/references/treasury.md +16 -0
  97. package/.goose/skills/stripe-projects/SKILL.md +139 -0
  98. package/.goose/skills/upgrade-stripe/SKILL.md +185 -0
  99. package/.iflow/skills/stripe-best-practices/SKILL.md +42 -0
  100. package/.iflow/skills/stripe-best-practices/references/billing.md +36 -0
  101. package/.iflow/skills/stripe-best-practices/references/connect.md +48 -0
  102. package/.iflow/skills/stripe-best-practices/references/payments.md +79 -0
  103. package/.iflow/skills/stripe-best-practices/references/security.md +109 -0
  104. package/.iflow/skills/stripe-best-practices/references/treasury.md +16 -0
  105. package/.iflow/skills/stripe-projects/SKILL.md +139 -0
  106. package/.iflow/skills/upgrade-stripe/SKILL.md +185 -0
  107. package/.junie/skills/stripe-best-practices/SKILL.md +42 -0
  108. package/.junie/skills/stripe-best-practices/references/billing.md +36 -0
  109. package/.junie/skills/stripe-best-practices/references/connect.md +48 -0
  110. package/.junie/skills/stripe-best-practices/references/payments.md +79 -0
  111. package/.junie/skills/stripe-best-practices/references/security.md +109 -0
  112. package/.junie/skills/stripe-best-practices/references/treasury.md +16 -0
  113. package/.junie/skills/stripe-projects/SKILL.md +139 -0
  114. package/.junie/skills/upgrade-stripe/SKILL.md +185 -0
  115. package/.kilocode/skills/stripe-best-practices/SKILL.md +42 -0
  116. package/.kilocode/skills/stripe-best-practices/references/billing.md +36 -0
  117. package/.kilocode/skills/stripe-best-practices/references/connect.md +48 -0
  118. package/.kilocode/skills/stripe-best-practices/references/payments.md +79 -0
  119. package/.kilocode/skills/stripe-best-practices/references/security.md +109 -0
  120. package/.kilocode/skills/stripe-best-practices/references/treasury.md +16 -0
  121. package/.kilocode/skills/stripe-projects/SKILL.md +139 -0
  122. package/.kilocode/skills/upgrade-stripe/SKILL.md +185 -0
  123. package/.kiro/skills/stripe-best-practices/SKILL.md +42 -0
  124. package/.kiro/skills/stripe-best-practices/references/billing.md +36 -0
  125. package/.kiro/skills/stripe-best-practices/references/connect.md +48 -0
  126. package/.kiro/skills/stripe-best-practices/references/payments.md +79 -0
  127. package/.kiro/skills/stripe-best-practices/references/security.md +109 -0
  128. package/.kiro/skills/stripe-best-practices/references/treasury.md +16 -0
  129. package/.kiro/skills/stripe-projects/SKILL.md +139 -0
  130. package/.kiro/skills/upgrade-stripe/SKILL.md +185 -0
  131. package/.kode/skills/stripe-best-practices/SKILL.md +42 -0
  132. package/.kode/skills/stripe-best-practices/references/billing.md +36 -0
  133. package/.kode/skills/stripe-best-practices/references/connect.md +48 -0
  134. package/.kode/skills/stripe-best-practices/references/payments.md +79 -0
  135. package/.kode/skills/stripe-best-practices/references/security.md +109 -0
  136. package/.kode/skills/stripe-best-practices/references/treasury.md +16 -0
  137. package/.kode/skills/stripe-projects/SKILL.md +139 -0
  138. package/.kode/skills/upgrade-stripe/SKILL.md +185 -0
  139. package/.mcpjam/skills/stripe-best-practices/SKILL.md +42 -0
  140. package/.mcpjam/skills/stripe-best-practices/references/billing.md +36 -0
  141. package/.mcpjam/skills/stripe-best-practices/references/connect.md +48 -0
  142. package/.mcpjam/skills/stripe-best-practices/references/payments.md +79 -0
  143. package/.mcpjam/skills/stripe-best-practices/references/security.md +109 -0
  144. package/.mcpjam/skills/stripe-best-practices/references/treasury.md +16 -0
  145. package/.mcpjam/skills/stripe-projects/SKILL.md +139 -0
  146. package/.mcpjam/skills/upgrade-stripe/SKILL.md +185 -0
  147. package/.mux/skills/stripe-best-practices/SKILL.md +42 -0
  148. package/.mux/skills/stripe-best-practices/references/billing.md +36 -0
  149. package/.mux/skills/stripe-best-practices/references/connect.md +48 -0
  150. package/.mux/skills/stripe-best-practices/references/payments.md +79 -0
  151. package/.mux/skills/stripe-best-practices/references/security.md +109 -0
  152. package/.mux/skills/stripe-best-practices/references/treasury.md +16 -0
  153. package/.mux/skills/stripe-projects/SKILL.md +139 -0
  154. package/.mux/skills/upgrade-stripe/SKILL.md +185 -0
  155. package/.neovate/skills/stripe-best-practices/SKILL.md +42 -0
  156. package/.neovate/skills/stripe-best-practices/references/billing.md +36 -0
  157. package/.neovate/skills/stripe-best-practices/references/connect.md +48 -0
  158. package/.neovate/skills/stripe-best-practices/references/payments.md +79 -0
  159. package/.neovate/skills/stripe-best-practices/references/security.md +109 -0
  160. package/.neovate/skills/stripe-best-practices/references/treasury.md +16 -0
  161. package/.neovate/skills/stripe-projects/SKILL.md +139 -0
  162. package/.neovate/skills/upgrade-stripe/SKILL.md +185 -0
  163. package/.nixpacksignore +14 -0
  164. package/.openhands/skills/stripe-best-practices/SKILL.md +42 -0
  165. package/.openhands/skills/stripe-best-practices/references/billing.md +36 -0
  166. package/.openhands/skills/stripe-best-practices/references/connect.md +48 -0
  167. package/.openhands/skills/stripe-best-practices/references/payments.md +79 -0
  168. package/.openhands/skills/stripe-best-practices/references/security.md +109 -0
  169. package/.openhands/skills/stripe-best-practices/references/treasury.md +16 -0
  170. package/.openhands/skills/stripe-projects/SKILL.md +139 -0
  171. package/.openhands/skills/upgrade-stripe/SKILL.md +185 -0
  172. package/.pi/skills/stripe-best-practices/SKILL.md +42 -0
  173. package/.pi/skills/stripe-best-practices/references/billing.md +36 -0
  174. package/.pi/skills/stripe-best-practices/references/connect.md +48 -0
  175. package/.pi/skills/stripe-best-practices/references/payments.md +79 -0
  176. package/.pi/skills/stripe-best-practices/references/security.md +109 -0
  177. package/.pi/skills/stripe-best-practices/references/treasury.md +16 -0
  178. package/.pi/skills/stripe-projects/SKILL.md +139 -0
  179. package/.pi/skills/upgrade-stripe/SKILL.md +185 -0
  180. package/.pochi/skills/stripe-best-practices/SKILL.md +42 -0
  181. package/.pochi/skills/stripe-best-practices/references/billing.md +36 -0
  182. package/.pochi/skills/stripe-best-practices/references/connect.md +48 -0
  183. package/.pochi/skills/stripe-best-practices/references/payments.md +79 -0
  184. package/.pochi/skills/stripe-best-practices/references/security.md +109 -0
  185. package/.pochi/skills/stripe-best-practices/references/treasury.md +16 -0
  186. package/.pochi/skills/stripe-projects/SKILL.md +139 -0
  187. package/.pochi/skills/upgrade-stripe/SKILL.md +185 -0
  188. package/.qoder/skills/stripe-best-practices/SKILL.md +42 -0
  189. package/.qoder/skills/stripe-best-practices/references/billing.md +36 -0
  190. package/.qoder/skills/stripe-best-practices/references/connect.md +48 -0
  191. package/.qoder/skills/stripe-best-practices/references/payments.md +79 -0
  192. package/.qoder/skills/stripe-best-practices/references/security.md +109 -0
  193. package/.qoder/skills/stripe-best-practices/references/treasury.md +16 -0
  194. package/.qoder/skills/stripe-projects/SKILL.md +139 -0
  195. package/.qoder/skills/upgrade-stripe/SKILL.md +185 -0
  196. package/.qwen/skills/stripe-best-practices/SKILL.md +42 -0
  197. package/.qwen/skills/stripe-best-practices/references/billing.md +36 -0
  198. package/.qwen/skills/stripe-best-practices/references/connect.md +48 -0
  199. package/.qwen/skills/stripe-best-practices/references/payments.md +79 -0
  200. package/.qwen/skills/stripe-best-practices/references/security.md +109 -0
  201. package/.qwen/skills/stripe-best-practices/references/treasury.md +16 -0
  202. package/.qwen/skills/stripe-projects/SKILL.md +139 -0
  203. package/.qwen/skills/upgrade-stripe/SKILL.md +185 -0
  204. package/.roo/skills/stripe-best-practices/SKILL.md +42 -0
  205. package/.roo/skills/stripe-best-practices/references/billing.md +36 -0
  206. package/.roo/skills/stripe-best-practices/references/connect.md +48 -0
  207. package/.roo/skills/stripe-best-practices/references/payments.md +79 -0
  208. package/.roo/skills/stripe-best-practices/references/security.md +109 -0
  209. package/.roo/skills/stripe-best-practices/references/treasury.md +16 -0
  210. package/.roo/skills/stripe-projects/SKILL.md +139 -0
  211. package/.roo/skills/upgrade-stripe/SKILL.md +185 -0
  212. package/.trae/skills/stripe-best-practices/SKILL.md +42 -0
  213. package/.trae/skills/stripe-best-practices/references/billing.md +36 -0
  214. package/.trae/skills/stripe-best-practices/references/connect.md +48 -0
  215. package/.trae/skills/stripe-best-practices/references/payments.md +79 -0
  216. package/.trae/skills/stripe-best-practices/references/security.md +109 -0
  217. package/.trae/skills/stripe-best-practices/references/treasury.md +16 -0
  218. package/.trae/skills/stripe-projects/SKILL.md +139 -0
  219. package/.trae/skills/upgrade-stripe/SKILL.md +185 -0
  220. package/.vibe/skills/stripe-best-practices/SKILL.md +42 -0
  221. package/.vibe/skills/stripe-best-practices/references/billing.md +36 -0
  222. package/.vibe/skills/stripe-best-practices/references/connect.md +48 -0
  223. package/.vibe/skills/stripe-best-practices/references/payments.md +79 -0
  224. package/.vibe/skills/stripe-best-practices/references/security.md +109 -0
  225. package/.vibe/skills/stripe-best-practices/references/treasury.md +16 -0
  226. package/.vibe/skills/stripe-projects/SKILL.md +139 -0
  227. package/.vibe/skills/upgrade-stripe/SKILL.md +185 -0
  228. package/.windsurf/skills/stripe-best-practices/SKILL.md +42 -0
  229. package/.windsurf/skills/stripe-best-practices/references/billing.md +36 -0
  230. package/.windsurf/skills/stripe-best-practices/references/connect.md +48 -0
  231. package/.windsurf/skills/stripe-best-practices/references/payments.md +79 -0
  232. package/.windsurf/skills/stripe-best-practices/references/security.md +109 -0
  233. package/.windsurf/skills/stripe-best-practices/references/treasury.md +16 -0
  234. package/.windsurf/skills/stripe-projects/SKILL.md +139 -0
  235. package/.windsurf/skills/upgrade-stripe/SKILL.md +185 -0
  236. package/.zencoder/skills/stripe-best-practices/SKILL.md +42 -0
  237. package/.zencoder/skills/stripe-best-practices/references/billing.md +36 -0
  238. package/.zencoder/skills/stripe-best-practices/references/connect.md +48 -0
  239. package/.zencoder/skills/stripe-best-practices/references/payments.md +79 -0
  240. package/.zencoder/skills/stripe-best-practices/references/security.md +109 -0
  241. package/.zencoder/skills/stripe-best-practices/references/treasury.md +16 -0
  242. package/.zencoder/skills/stripe-projects/SKILL.md +139 -0
  243. package/.zencoder/skills/upgrade-stripe/SKILL.md +185 -0
  244. package/AUDIT.md +95 -0
  245. package/BLOCKERS.md +0 -0
  246. package/COOLIFY.md +51 -0
  247. package/MCP_SETUP.md +23 -0
  248. package/PRODUCTION_CHECKLIST.md +246 -0
  249. package/README.md +47 -0
  250. package/ROADMAP.md +91 -0
  251. package/docs/superpowers/plans/2026-05-11-availsync-frontend-sales-flow.md +2445 -0
  252. package/frontend/.env.example +2 -0
  253. package/frontend/app/admin/layout.tsx +13 -0
  254. package/frontend/app/admin/page.tsx +747 -0
  255. package/frontend/app/app/activity/page.tsx +257 -0
  256. package/frontend/app/app/agents/[agentId]/page.tsx +21 -0
  257. package/frontend/app/app/agents/page.tsx +1155 -0
  258. package/frontend/app/app/audit/page.tsx +225 -0
  259. package/frontend/app/app/availability/page.tsx +840 -0
  260. package/frontend/app/app/holds/page.tsx +262 -0
  261. package/frontend/app/app/layout.tsx +19 -0
  262. package/frontend/app/app/onboarding/page.tsx +10 -0
  263. package/frontend/app/app/onboarding/verify/page.tsx +309 -0
  264. package/frontend/app/app/page.tsx +508 -0
  265. package/frontend/app/app/settings/page.tsx +399 -0
  266. package/frontend/app/app/work/page.tsx +426 -0
  267. package/frontend/app/changelog/page.tsx +93 -0
  268. package/frontend/app/checkout/page.tsx +25 -0
  269. package/frontend/app/docs/api/page.tsx +157 -0
  270. package/frontend/app/docs/page.tsx +296 -0
  271. package/frontend/app/docs/pilot/page.tsx +127 -0
  272. package/frontend/app/docs/quickstart/page.tsx +318 -0
  273. package/frontend/app/docs/reliability/page.tsx +78 -0
  274. package/frontend/app/docs/sdk/node/page.tsx +166 -0
  275. package/frontend/app/globals.css +57 -0
  276. package/frontend/app/icon.png +0 -0
  277. package/frontend/app/layout.tsx +87 -0
  278. package/frontend/app/login/page.tsx +14 -0
  279. package/frontend/app/page.tsx +47 -0
  280. package/frontend/app/pricing/page.tsx +66 -0
  281. package/frontend/app/privacy/page.tsx +52 -0
  282. package/frontend/app/robots.ts +26 -0
  283. package/frontend/app/security/page.tsx +74 -0
  284. package/frontend/app/signup/page.tsx +14 -0
  285. package/frontend/app/sitemap.ts +14 -0
  286. package/frontend/app/terms/page.tsx +51 -0
  287. package/frontend/components/brand/AvailsyncLogo.tsx +56 -0
  288. package/frontend/components/checkout/CheckoutClient.tsx +100 -0
  289. package/frontend/components/dashboard/AgentForm.tsx +59 -0
  290. package/frontend/components/dashboard/AppShell.tsx +291 -0
  291. package/frontend/components/dashboard/AvailabilityChecker.tsx +117 -0
  292. package/frontend/components/dashboard/AvailabilityWindowForm.tsx +40 -0
  293. package/frontend/components/dashboard/HoldForm.tsx +133 -0
  294. package/frontend/components/dashboard/MetricCard.tsx +10 -0
  295. package/frontend/components/login/LoginForm.tsx +95 -0
  296. package/frontend/components/marketing/AgentCoordinationStory.tsx +1530 -0
  297. package/frontend/components/marketing/Faq.tsx +41 -0
  298. package/frontend/components/marketing/Hero.tsx +73 -0
  299. package/frontend/components/marketing/HowItWorks.tsx +28 -0
  300. package/frontend/components/marketing/ObserveModeTeaser.tsx +41 -0
  301. package/frontend/components/marketing/PricingTeaser.tsx +23 -0
  302. package/frontend/components/marketing/ProblemSolution.tsx +36 -0
  303. package/frontend/components/marketing/SiteFooter.tsx +59 -0
  304. package/frontend/components/marketing/SiteHeader.tsx +45 -0
  305. package/frontend/components/marketing/UseCases.tsx +27 -0
  306. package/frontend/components/onboarding/OnboardingClient.tsx +278 -0
  307. package/frontend/components/pricing/PricingCards.tsx +65 -0
  308. package/frontend/components/privacy/CookieConsent.tsx +230 -0
  309. package/frontend/components/privacy/CookieSettingsButton.tsx +15 -0
  310. package/frontend/components/seo/JsonLd.tsx +10 -0
  311. package/frontend/components/signup/SignupForm.tsx +55 -0
  312. package/frontend/components/ui/Badge.tsx +23 -0
  313. package/frontend/components/ui/Button.tsx +37 -0
  314. package/frontend/components/ui/Card.tsx +11 -0
  315. package/frontend/components/ui/ConfirmDialog.tsx +77 -0
  316. package/frontend/components/ui/EmptyState.tsx +24 -0
  317. package/frontend/components/ui/Input.tsx +14 -0
  318. package/frontend/components/ui/KeyDisplay.tsx +49 -0
  319. package/frontend/components/ui/Select.tsx +14 -0
  320. package/frontend/components/ui/Skeleton.tsx +24 -0
  321. package/frontend/components/ui/Tabs.tsx +19 -0
  322. package/frontend/components/ui/Textarea.tsx +14 -0
  323. package/frontend/components/ui/Toast.tsx +78 -0
  324. package/frontend/components/waitlist/WaitlistDialog.tsx +128 -0
  325. package/frontend/lib/api.ts +1282 -0
  326. package/frontend/lib/billing.ts +6 -0
  327. package/frontend/lib/cookieConsent.ts +113 -0
  328. package/frontend/lib/format.ts +16 -0
  329. package/frontend/lib/plans.ts +62 -0
  330. package/frontend/lib/schemas.ts +108 -0
  331. package/frontend/lib/seo.ts +376 -0
  332. package/frontend/lib/setupGuides.ts +630 -0
  333. package/frontend/lib/storage.ts +30 -0
  334. package/frontend/next-env.d.ts +6 -0
  335. package/frontend/next.config.mjs +13 -0
  336. package/frontend/package-lock.json +14409 -0
  337. package/frontend/package.json +41 -0
  338. package/frontend/playwright.config.ts +20 -0
  339. package/frontend/postcss.config.mjs +8 -0
  340. package/frontend/public/.gitkeep +0 -0
  341. package/frontend/public/brand/availsync-logo-board.png +0 -0
  342. package/frontend/public/brand/availsync-logo-dark.png +0 -0
  343. package/frontend/public/brand/availsync-mark-dark.png +0 -0
  344. package/frontend/public/brand/availsync-wordmark-dark.png +0 -0
  345. package/frontend/public/marketing/hero-agent-coordination.png +0 -0
  346. package/frontend/tailwind.config.ts +53 -0
  347. package/frontend/tests/smoke.spec.ts +89 -0
  348. package/frontend/tsconfig.json +23 -0
  349. package/jest.config.js +7 -0
  350. package/nixpacks.toml +11 -0
  351. package/package.json +53 -0
  352. package/packages/mcp/LICENSE +21 -0
  353. package/packages/mcp/README.md +60 -0
  354. package/packages/mcp/jest.config.cjs +8 -0
  355. package/packages/mcp/package.json +54 -0
  356. package/packages/mcp/src/helpers.ts +38 -0
  357. package/packages/mcp/src/index.test.ts +60 -0
  358. package/packages/mcp/src/index.ts +387 -0
  359. package/packages/mcp/tsconfig.json +20 -0
  360. package/packages/mcp/tsconfig.test.json +12 -0
  361. package/packages/node/LICENSE +21 -0
  362. package/packages/node/README.md +120 -0
  363. package/packages/node/jest.config.cjs +8 -0
  364. package/packages/node/package.json +46 -0
  365. package/packages/node/src/index.test.ts +360 -0
  366. package/packages/node/src/index.ts +402 -0
  367. package/packages/node/tsconfig.json +20 -0
  368. package/packages/node/tsconfig.test.json +12 -0
  369. package/plan.md +923 -0
  370. package/skills/stripe-best-practices/SKILL.md +42 -0
  371. package/skills/stripe-best-practices/references/billing.md +36 -0
  372. package/skills/stripe-best-practices/references/connect.md +48 -0
  373. package/skills/stripe-best-practices/references/payments.md +79 -0
  374. package/skills/stripe-best-practices/references/security.md +109 -0
  375. package/skills/stripe-best-practices/references/treasury.md +16 -0
  376. package/skills/stripe-projects/SKILL.md +139 -0
  377. package/skills/upgrade-stripe/SKILL.md +185 -0
  378. package/skills-lock.json +20 -0
  379. package/src/core/availability.ts +178 -0
  380. package/src/core/conflict.ts +209 -0
  381. package/src/core/work.ts +490 -0
  382. package/src/db/client.ts +17 -0
  383. package/src/db/migrations/001_init.sql +88 -0
  384. package/src/db/migrations/002_stripe.sql +2 -0
  385. package/src/db/migrations/003_workspace_auth.sql +19 -0
  386. package/src/db/migrations/004_agent_mcp_status.sql +2 -0
  387. package/src/db/migrations/005_hold_event_actor.sql +4 -0
  388. package/src/db/migrations/006_agent_activity.sql +35 -0
  389. package/src/db/migrations/007_work_coordination.sql +60 -0
  390. package/src/db/migrations/008_work_claim_leases.sql +20 -0
  391. package/src/db/migrations/009_billing_subscription_state.sql +23 -0
  392. package/src/db/migrations/010_agent_api_key_prefix.sql +10 -0
  393. package/src/db/migrations/011_org_verified_and_work_event_retention.sql +11 -0
  394. package/src/db/migrations/012_agent_enforcement_mode.sql +12 -0
  395. package/src/db/migrations/013_support_tickets.sql +21 -0
  396. package/src/db/migrations/014_paid_plan_waitlist.sql +23 -0
  397. package/src/db/migrations/015_agent_last_seen.sql +2 -0
  398. package/src/db/migrations.ts +164 -0
  399. package/src/db/run-migrations.ts +13 -0
  400. package/src/index.ts +183 -0
  401. package/src/lib/activity.ts +137 -0
  402. package/src/lib/apiKeys.ts +32 -0
  403. package/src/lib/appInfo.ts +26 -0
  404. package/src/lib/billingConfig.ts +3 -0
  405. package/src/lib/env.ts +75 -0
  406. package/src/lib/logger.ts +8 -0
  407. package/src/lib/plans.ts +204 -0
  408. package/src/mcp/server.js +5 -0
  409. package/src/mcp/server.ts +350 -0
  410. package/src/middleware/auth.ts +342 -0
  411. package/src/middleware/requestId.ts +16 -0
  412. package/src/routes/account.ts +168 -0
  413. package/src/routes/activity.ts +126 -0
  414. package/src/routes/admin.ts +514 -0
  415. package/src/routes/audit.ts +68 -0
  416. package/src/routes/auth.ts +203 -0
  417. package/src/routes/availability.ts +325 -0
  418. package/src/routes/billing.ts +406 -0
  419. package/src/routes/conflicts.ts +131 -0
  420. package/src/routes/holds.ts +437 -0
  421. package/src/routes/mcp.ts +57 -0
  422. package/src/routes/metrics.ts +39 -0
  423. package/src/routes/onboarding.ts +273 -0
  424. package/src/routes/orgs.ts +981 -0
  425. package/src/routes/preferences.ts +132 -0
  426. package/src/routes/session.ts +16 -0
  427. package/src/routes/support.ts +77 -0
  428. package/src/routes/value.ts +186 -0
  429. package/src/routes/waitlist.ts +63 -0
  430. package/src/routes/work.ts +1578 -0
  431. package/src/server.ts +36 -0
  432. package/src/types/index.ts +109 -0
  433. package/tests/integration/activity.route.test.ts +103 -0
  434. package/tests/integration/admin.route.test.ts +143 -0
  435. package/tests/integration/agent-keys.route.test.ts +237 -0
  436. package/tests/integration/availability.route.test.ts +125 -0
  437. package/tests/integration/billing.route.test.ts +393 -0
  438. package/tests/integration/conflicts.route.test.ts +131 -0
  439. package/tests/integration/flows.test.ts +154 -0
  440. package/tests/integration/helpers.ts +134 -0
  441. package/tests/integration/holds.route.test.ts +185 -0
  442. package/tests/integration/metrics.route.test.ts +100 -0
  443. package/tests/integration/onboarding.verify.route.test.ts +163 -0
  444. package/tests/integration/preferences.route.test.ts +53 -0
  445. package/tests/integration/session.route.test.ts +97 -0
  446. package/tests/integration/system.route.test.ts +92 -0
  447. package/tests/integration/value.route.test.ts +235 -0
  448. package/tests/integration/work.route.test.ts +745 -0
  449. package/tests/setup.ts +4 -0
  450. package/tests/smoke.sh +62 -0
  451. package/tests/unit/auth.test.ts +114 -0
  452. package/tests/unit/availability.test.ts +149 -0
  453. package/tests/unit/conflict.test.ts +118 -0
  454. package/tests/unit/env.test.ts +69 -0
  455. package/tests/unit/migrations.test.ts +135 -0
  456. package/tests/unit/request-id.test.ts +37 -0
  457. package/tmp-mobile-agents.png +0 -0
  458. package/tmp-next-mobile.err.log +10 -0
  459. package/tmp-next-mobile.log +5 -0
  460. package/tsconfig.json +16 -0
@@ -0,0 +1,132 @@
1
+ import express from 'express';
2
+ import { z } from 'zod';
3
+ import pool from '../db/client';
4
+ import { log } from '../lib/logger';
5
+ import {
6
+ canAccessAgent,
7
+ requireWorkspaceOrAgent,
8
+ type AnyAuthenticatedRequest,
9
+ } from '../middleware/auth';
10
+
11
+ const router = express.Router();
12
+
13
+ const PreferencesSchema = z.object({
14
+ buffer_minutes_after: z.number().int().min(0).max(120).optional(),
15
+ buffer_minutes_before: z.number().int().min(0).max(120).optional(),
16
+ focus_blocks: z
17
+ .array(
18
+ z.object({
19
+ weekday: z.number().int().min(0).max(6),
20
+ start_time: z.string().regex(/^\d{2}:\d{2}$/),
21
+ end_time: z.string().regex(/^\d{2}:\d{2}$/),
22
+ }),
23
+ )
24
+ .max(20)
25
+ .optional(),
26
+ priority_over_agents: z.array(z.string().uuid()).max(50).optional(),
27
+ booking_window_days: z.number().int().min(1).max(365).optional(),
28
+ allow_back_to_back: z.boolean().optional(),
29
+ });
30
+
31
+ async function ensureOrgAgent(agentId: string, orgId: string): Promise<boolean> {
32
+ const result = await pool.query('SELECT 1 FROM agents WHERE id = $1 AND org_id = $2', [
33
+ agentId,
34
+ orgId,
35
+ ]);
36
+ return result.rows.length > 0;
37
+ }
38
+
39
+ router.get('/preferences/:agent_id', requireWorkspaceOrAgent, async (req, res) => {
40
+ const authReq = req as AnyAuthenticatedRequest;
41
+ const agentId = z.string().uuid().safeParse(req.params.agent_id);
42
+ if (!agentId.success) {
43
+ return res.status(400).json({ error: 'validation_error', details: agentId.error.flatten() });
44
+ }
45
+
46
+ try {
47
+ if (!(await ensureOrgAgent(agentId.data, authReq.org.id))) {
48
+ return res.status(403).json({ error: 'forbidden', message: 'Agent is outside your org' });
49
+ }
50
+ if (!canAccessAgent(authReq, agentId.data)) {
51
+ return res.status(403).json({ error: 'forbidden', message: 'Agent key cannot act for another agent' });
52
+ }
53
+
54
+ const preferences = await pool.query('SELECT * FROM agent_preferences WHERE agent_id = $1', [
55
+ agentId.data,
56
+ ]);
57
+ return res.json({ preferences: preferences.rows[0] });
58
+ } catch (err) {
59
+ log.error('[preferences] unexpected error', { error: (err as Error).message });
60
+ return res.status(500).json({ error: 'internal_error', message: 'An unexpected error occurred' });
61
+ }
62
+ });
63
+
64
+ router.put('/preferences/:agent_id', requireWorkspaceOrAgent, async (req, res) => {
65
+ const agentId = z.string().uuid().safeParse(req.params.agent_id);
66
+ if (!agentId.success) {
67
+ return res.status(400).json({ error: 'validation_error', details: agentId.error.flatten() });
68
+ }
69
+
70
+ const parsed = PreferencesSchema.safeParse(req.body);
71
+ if (!parsed.success) {
72
+ return res.status(422).json({ error: 'validation_error', details: parsed.error.flatten() });
73
+ }
74
+
75
+ const authReq = req as AnyAuthenticatedRequest;
76
+
77
+ try {
78
+ if (!(await ensureOrgAgent(agentId.data, authReq.org.id))) {
79
+ return res.status(403).json({ error: 'forbidden', message: 'Agent is outside your org' });
80
+ }
81
+ if (!canAccessAgent(authReq, agentId.data)) {
82
+ return res.status(403).json({ error: 'forbidden', message: 'Agent key cannot act for another agent' });
83
+ }
84
+
85
+ const existing = await pool.query('SELECT * FROM agent_preferences WHERE agent_id = $1', [
86
+ agentId.data,
87
+ ]);
88
+ const merged = {
89
+ ...existing.rows[0],
90
+ ...parsed.data,
91
+ };
92
+
93
+ const updated = await pool.query(
94
+ `INSERT INTO agent_preferences (
95
+ agent_id,
96
+ buffer_minutes_after,
97
+ buffer_minutes_before,
98
+ focus_blocks,
99
+ priority_over_agents,
100
+ booking_window_days,
101
+ allow_back_to_back,
102
+ updated_at
103
+ )
104
+ VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())
105
+ ON CONFLICT (agent_id) DO UPDATE SET
106
+ buffer_minutes_after = EXCLUDED.buffer_minutes_after,
107
+ buffer_minutes_before = EXCLUDED.buffer_minutes_before,
108
+ focus_blocks = EXCLUDED.focus_blocks,
109
+ priority_over_agents = EXCLUDED.priority_over_agents,
110
+ booking_window_days = EXCLUDED.booking_window_days,
111
+ allow_back_to_back = EXCLUDED.allow_back_to_back,
112
+ updated_at = NOW()
113
+ RETURNING *`,
114
+ [
115
+ agentId.data,
116
+ merged.buffer_minutes_after ?? 15,
117
+ merged.buffer_minutes_before ?? 0,
118
+ JSON.stringify(merged.focus_blocks ?? []),
119
+ JSON.stringify(merged.priority_over_agents ?? []),
120
+ merged.booking_window_days ?? 30,
121
+ merged.allow_back_to_back ?? false,
122
+ ],
123
+ );
124
+
125
+ return res.json({ preferences: updated.rows[0] });
126
+ } catch (err) {
127
+ log.error('[preferences] unexpected error', { error: (err as Error).message });
128
+ return res.status(500).json({ error: 'internal_error', message: 'An unexpected error occurred' });
129
+ }
130
+ });
131
+
132
+ export default router;
@@ -0,0 +1,16 @@
1
+ import express from 'express';
2
+ import { requireWorkspaceSession, type WorkspaceAuthenticatedRequest } from '../middleware/auth';
3
+
4
+ const router = express.Router();
5
+
6
+ router.get('/session', requireWorkspaceSession, (req, res) => {
7
+ const authenticatedReq = req as WorkspaceAuthenticatedRequest;
8
+ const { password_hash: _passwordHash, ...user } = authenticatedReq.user;
9
+
10
+ return res.json({
11
+ org: authenticatedReq.org,
12
+ user,
13
+ });
14
+ });
15
+
16
+ export default router;
@@ -0,0 +1,77 @@
1
+ import express from 'express';
2
+ import { z } from 'zod';
3
+ import pool from '../db/client';
4
+ import { requireWorkspaceSession, type WorkspaceAuthenticatedRequest } from '../middleware/auth';
5
+ import { log } from '../lib/logger';
6
+ import { billingUpgradesEnabled } from '../lib/billingConfig';
7
+
8
+ const router = express.Router();
9
+
10
+ const TicketCreateSchema = z.object({
11
+ email: z.string().email().max(240),
12
+ subject: z.string().trim().min(3).max(160),
13
+ category: z.enum(['billing', 'setup', 'sdk', 'agent_error', 'bug', 'other']),
14
+ message: z.string().trim().min(10).max(5000),
15
+ context: z.record(z.string(), z.unknown()).optional(),
16
+ });
17
+
18
+ router.post('/support/tickets', requireWorkspaceSession, async (req, res) => {
19
+ const authReq = req as WorkspaceAuthenticatedRequest;
20
+ if (authReq.org.plan === 'free') {
21
+ return res.status(402).json({
22
+ error: 'plan_limit_reached',
23
+ limit_type: 'support_tickets',
24
+ plan: authReq.org.plan,
25
+ upgrade_plan: 'individual',
26
+ message: billingUpgradesEnabled()
27
+ ? 'Support tickets are available on paid plans.'
28
+ : 'Support tickets are available on paid plans. Paid upgrades are currently waitlist-only.',
29
+ });
30
+ }
31
+
32
+ const parsed = TicketCreateSchema.safeParse(req.body);
33
+ if (!parsed.success) {
34
+ return res.status(400).json({ error: 'validation_error', details: parsed.error.flatten() });
35
+ }
36
+
37
+ try {
38
+ const context = {
39
+ source: 'dashboard_support',
40
+ submitted_path: typeof parsed.data.context?.path === 'string' ? parsed.data.context.path : undefined,
41
+ user_agent: req.header('user-agent')?.slice(0, 240),
42
+ app_url: typeof parsed.data.context?.app_url === 'string' ? parsed.data.context.app_url : undefined,
43
+ };
44
+
45
+ const result = await pool.query(
46
+ `INSERT INTO support_tickets (
47
+ org_id,
48
+ user_id,
49
+ email,
50
+ subject,
51
+ category,
52
+ message,
53
+ plan,
54
+ context
55
+ )
56
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
57
+ RETURNING id, org_id, user_id, email, subject, category, message, status, priority, plan, context, created_at, updated_at`,
58
+ [
59
+ authReq.org.id,
60
+ authReq.user.id,
61
+ parsed.data.email,
62
+ parsed.data.subject,
63
+ parsed.data.category,
64
+ parsed.data.message,
65
+ authReq.org.plan,
66
+ JSON.stringify(context),
67
+ ],
68
+ );
69
+
70
+ return res.status(201).json({ ticket: result.rows[0] });
71
+ } catch (err) {
72
+ log.error('[support] create ticket error', { error: (err as Error).message, org_id: authReq.org.id });
73
+ return res.status(500).json({ error: 'internal_error', message: 'An unexpected error occurred' });
74
+ }
75
+ });
76
+
77
+ export default router;
@@ -0,0 +1,186 @@
1
+ import express from 'express';
2
+ import pool from '../db/client';
3
+ import { requireWorkspaceSession, type WorkspaceAuthenticatedRequest } from '../middleware/auth';
4
+ import { log } from '../lib/logger';
5
+
6
+ const router = express.Router();
7
+
8
+ const REAL_ACTIVITY_FILTER = `
9
+ NOT (
10
+ activity_type LIKE 'setup_test%'
11
+ OR activity_type IN ('verification_run', 'connection_test')
12
+ OR COALESCE(metadata->>'source', '') IN ('setup_test', 'onboarding_verification')
13
+ )
14
+ `;
15
+
16
+ const REAL_WORK_EVENT_FILTER = `
17
+ COALESCE(metadata->>'source', '') NOT IN ('setup_test', 'onboarding_verification')
18
+ `;
19
+
20
+ function nextBestAction(input: {
21
+ verified_at: Date | null;
22
+ agents_count: number;
23
+ latest_real_activity_at: Date | null;
24
+ errors_7d: number;
25
+ quiet_agents: number;
26
+ never_connected_agents: number;
27
+ }) {
28
+ if (!input.verified_at) return 'run_verification';
29
+ if (input.agents_count === 0 || !input.latest_real_activity_at) return 'connect_first_agent';
30
+ if (input.errors_7d > 0) return 'review_errors';
31
+ if (input.quiet_agents > 0 || input.never_connected_agents > 0) return 'check_inactive_agents';
32
+ return 'none';
33
+ }
34
+
35
+ router.get('/value/health', requireWorkspaceSession, async (req, res) => {
36
+ const authReq = req as WorkspaceAuthenticatedRequest;
37
+
38
+ try {
39
+ const [summary, agents] = await Promise.all([
40
+ pool.query(
41
+ `WITH window AS (
42
+ SELECT NOW() AS ends_at, NOW() - INTERVAL '7 days' AS starts_at
43
+ ),
44
+ real_activity AS (
45
+ SELECT *
46
+ FROM agent_activity_events
47
+ WHERE org_id = $1
48
+ AND ${REAL_ACTIVITY_FILTER}
49
+ ),
50
+ work_value AS (
51
+ SELECT
52
+ COUNT(*) FILTER (WHERE event_type = 'blocked')::int AS blocked_work_runs_7d,
53
+ COUNT(*) FILTER (WHERE event_type = 'shadow_blocked')::int AS would_have_blocked_runs_7d
54
+ FROM work_claim_events, window
55
+ WHERE org_id = $1
56
+ AND event_type IN ('blocked', 'shadow_blocked')
57
+ AND created_at >= window.starts_at
58
+ AND ${REAL_WORK_EVENT_FILTER}
59
+ ),
60
+ calendar_value AS (
61
+ SELECT COUNT(*)::int AS calendar_conflicts_7d
62
+ FROM hold_events, window
63
+ WHERE org_id = $1
64
+ AND event_type IN ('conflict_won', 'conflict_lost', 'superseded')
65
+ AND created_at >= window.starts_at
66
+ )
67
+ SELECT
68
+ (SELECT starts_at FROM window) AS starts_at,
69
+ (SELECT ends_at FROM window) AS ends_at,
70
+ (SELECT blocked_work_runs_7d FROM work_value) AS blocked_work_runs_7d,
71
+ (SELECT would_have_blocked_runs_7d FROM work_value) AS would_have_blocked_runs_7d,
72
+ (SELECT calendar_conflicts_7d FROM calendar_value) AS calendar_conflicts_7d,
73
+ ((SELECT blocked_work_runs_7d FROM work_value) + (SELECT calendar_conflicts_7d FROM calendar_value))::int AS conflicts_prevented_7d,
74
+ (SELECT COUNT(*)::int FROM real_activity, window WHERE created_at >= window.starts_at) AS api_calls_7d,
75
+ (SELECT COUNT(*)::int FROM real_activity, window WHERE status = 'error' AND created_at >= window.starts_at) AS errors_7d,
76
+ (SELECT MAX(created_at) FROM real_activity) AS latest_real_activity_at,
77
+ (SELECT verified_at FROM orgs WHERE id = $1) AS verified_at,
78
+ (SELECT COUNT(*)::int FROM agents WHERE org_id = $1) AS agents_count`,
79
+ [authReq.org.id],
80
+ ),
81
+ pool.query(
82
+ `WITH real_activity AS (
83
+ SELECT *
84
+ FROM agent_activity_events
85
+ WHERE org_id = $1
86
+ AND ${REAL_ACTIVITY_FILTER}
87
+ ),
88
+ agent_stats AS (
89
+ SELECT
90
+ agents.id AS agent_id,
91
+ agents.name,
92
+ agents.last_seen_at,
93
+ agents.mcp_last_seen_at,
94
+ (SELECT MAX(created_at) FROM real_activity WHERE agent_id = agents.id) AS last_activity_at,
95
+ (SELECT MAX(created_at) FROM real_activity WHERE agent_id = agents.id AND status = 'success') AS last_success_at,
96
+ (SELECT MAX(created_at) FROM real_activity WHERE agent_id = agents.id AND status = 'error') AS last_error_at,
97
+ (
98
+ SELECT error_code
99
+ FROM real_activity
100
+ WHERE agent_id = agents.id
101
+ AND status = 'error'
102
+ ORDER BY created_at DESC
103
+ LIMIT 1
104
+ ) AS last_error_code
105
+ FROM agents
106
+ WHERE agents.org_id = $1
107
+ )
108
+ SELECT
109
+ agent_id,
110
+ name,
111
+ last_seen_at,
112
+ last_activity_at,
113
+ last_success_at,
114
+ last_error_at,
115
+ last_error_code,
116
+ CASE
117
+ WHEN mcp_last_seen_at IS NULL THEN 'offline'
118
+ WHEN mcp_last_seen_at > NOW() - INTERVAL '2 minutes' THEN 'online'
119
+ WHEN mcp_last_seen_at > NOW() - INTERVAL '15 minutes' THEN 'recent'
120
+ ELSE 'offline'
121
+ END AS mcp_status,
122
+ CASE
123
+ WHEN last_error_at IS NOT NULL AND (last_success_at IS NULL OR last_error_at > last_success_at) THEN 'error'
124
+ WHEN last_activity_at IS NULL AND mcp_last_seen_at IS NULL AND last_seen_at IS NULL THEN 'never_connected'
125
+ WHEN GREATEST(COALESCE(last_activity_at, 'epoch'::timestamptz), COALESCE(mcp_last_seen_at, 'epoch'::timestamptz), COALESCE(last_seen_at, 'epoch'::timestamptz)) < NOW() - INTERVAL '3 days' THEN 'quiet'
126
+ ELSE 'healthy'
127
+ END AS status
128
+ FROM agent_stats
129
+ ORDER BY
130
+ CASE
131
+ WHEN last_error_at IS NOT NULL AND (last_success_at IS NULL OR last_error_at > last_success_at) THEN 0
132
+ WHEN last_activity_at IS NULL AND mcp_last_seen_at IS NULL AND last_seen_at IS NULL THEN 1
133
+ WHEN GREATEST(COALESCE(last_activity_at, 'epoch'::timestamptz), COALESCE(mcp_last_seen_at, 'epoch'::timestamptz), COALESCE(last_seen_at, 'epoch'::timestamptz)) < NOW() - INTERVAL '3 days' THEN 2
134
+ ELSE 3
135
+ END,
136
+ name ASC`,
137
+ [authReq.org.id],
138
+ ),
139
+ ]);
140
+
141
+ const summaryRow = summary.rows[0];
142
+ const quietAgents = agents.rows.filter((agent) => agent.status === 'quiet').length;
143
+ const neverConnectedAgents = agents.rows.filter((agent) => agent.status === 'never_connected').length;
144
+
145
+ return res.json({
146
+ window: {
147
+ starts_at: summaryRow.starts_at.toISOString(),
148
+ ends_at: summaryRow.ends_at.toISOString(),
149
+ days: 7,
150
+ },
151
+ summary: {
152
+ conflicts_prevented_7d: summaryRow.conflicts_prevented_7d,
153
+ blocked_work_runs_7d: summaryRow.blocked_work_runs_7d,
154
+ would_have_blocked_runs_7d: summaryRow.would_have_blocked_runs_7d,
155
+ calendar_conflicts_7d: summaryRow.calendar_conflicts_7d,
156
+ api_calls_7d: summaryRow.api_calls_7d,
157
+ errors_7d: summaryRow.errors_7d,
158
+ latest_real_activity_at: summaryRow.latest_real_activity_at?.toISOString() ?? null,
159
+ },
160
+ agent_health: agents.rows.map((agent) => ({
161
+ agent_id: agent.agent_id,
162
+ name: agent.name,
163
+ status: agent.status,
164
+ last_seen_at: agent.last_seen_at?.toISOString() ?? null,
165
+ last_activity_at: agent.last_activity_at?.toISOString() ?? null,
166
+ last_success_at: agent.last_success_at?.toISOString() ?? null,
167
+ last_error_at: agent.last_error_at?.toISOString() ?? null,
168
+ last_error_code: agent.last_error_code ?? null,
169
+ mcp_status: agent.mcp_status,
170
+ })),
171
+ next_best_action: nextBestAction({
172
+ verified_at: summaryRow.verified_at,
173
+ agents_count: summaryRow.agents_count,
174
+ latest_real_activity_at: summaryRow.latest_real_activity_at,
175
+ errors_7d: summaryRow.errors_7d,
176
+ quiet_agents: quietAgents,
177
+ never_connected_agents: neverConnectedAgents,
178
+ }),
179
+ });
180
+ } catch (err) {
181
+ log.error('[value] health error', { error: (err as Error).message });
182
+ return res.status(500).json({ error: 'internal_error', message: 'An unexpected error occurred' });
183
+ }
184
+ });
185
+
186
+ export default router;
@@ -0,0 +1,63 @@
1
+ import express from 'express';
2
+ import { z } from 'zod';
3
+ import pool from '../db/client';
4
+ import { authenticateWorkspaceSession } from '../middleware/auth';
5
+ import { log } from '../lib/logger';
6
+
7
+ const router = express.Router();
8
+
9
+ const WaitlistCreateSchema = z.object({
10
+ email: z.string().trim().email().max(240),
11
+ plan: z.enum(['individual', 'team']),
12
+ source: z.enum(['pricing', 'settings', 'checkout', 'plan_limit', 'other']).optional().default('pricing'),
13
+ message: z.string().trim().max(1000).optional().default(''),
14
+ context: z.record(z.string(), z.unknown()).optional(),
15
+ });
16
+
17
+ router.post('/waitlist', async (req, res) => {
18
+ const parsed = WaitlistCreateSchema.safeParse(req.body);
19
+ if (!parsed.success) {
20
+ return res.status(400).json({ error: 'validation_error', details: parsed.error.flatten() });
21
+ }
22
+
23
+ try {
24
+ const workspace = await authenticateWorkspaceSession(req);
25
+ const context = {
26
+ source: 'paid_plan_waitlist',
27
+ submitted_path: typeof parsed.data.context?.path === 'string' ? parsed.data.context.path : undefined,
28
+ app_url: typeof parsed.data.context?.app_url === 'string' ? parsed.data.context.app_url : undefined,
29
+ user_agent: req.header('user-agent')?.slice(0, 240),
30
+ };
31
+
32
+ const result = await pool.query(
33
+ `INSERT INTO paid_plan_waitlist (
34
+ org_id,
35
+ user_id,
36
+ email,
37
+ plan,
38
+ source,
39
+ message,
40
+ context
41
+ )
42
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
43
+ RETURNING id, org_id, user_id, email, plan, source, message, status, context, created_at, updated_at`,
44
+ [
45
+ workspace?.org.id ?? null,
46
+ workspace?.user.id ?? null,
47
+ parsed.data.email,
48
+ parsed.data.plan,
49
+ parsed.data.source,
50
+ parsed.data.message,
51
+ JSON.stringify(context),
52
+ ],
53
+ );
54
+
55
+ return res.status(201).json({ lead: result.rows[0] });
56
+ } catch (err) {
57
+ log.error('[waitlist] create lead error', { error: (err as Error).message });
58
+ return res.status(500).json({ error: 'internal_error', message: 'An unexpected error occurred' });
59
+ }
60
+ });
61
+
62
+ export default router;
63
+