ui-syncup 0.3.13 → 0.4.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1047) hide show
  1. package/.agents/skills/ai-spec-workflow/SKILL.md +58 -0
  2. package/.agents/skills/ai-spec-workflow/references/AI_SPECIFICATION_WORKFLOW.md +1434 -0
  3. package/.agents/skills/ai-spec-workflow/references/templates/design-template.md +729 -0
  4. package/.agents/skills/ai-spec-workflow/references/templates/requirements-template.md +179 -0
  5. package/.agents/skills/ai-spec-workflow/references/templates/tasks-template.md +501 -0
  6. package/.agents/skills/animation-designer/SKILL.md +688 -0
  7. package/.agents/skills/animation-designer/manifest.yaml +44 -0
  8. package/.agents/skills/brainstorming/SKILL.md +54 -0
  9. package/.agents/skills/contract-driven-ui/SKILL.md +270 -0
  10. package/.agents/skills/dispatching-parallel-agents/SKILL.md +180 -0
  11. package/.agents/skills/executing-plans/SKILL.md +76 -0
  12. package/.agents/skills/executing-specs/SKILL.md +53 -0
  13. package/.agents/skills/finishing-a-development-branch/SKILL.md +200 -0
  14. package/.agents/skills/github-workflow-automation/SKILL.md +846 -0
  15. package/.agents/skills/react-best-practices/AGENTS.md +2249 -0
  16. package/.agents/skills/react-best-practices/README.md +123 -0
  17. package/.agents/skills/react-best-practices/SKILL.md +121 -0
  18. package/.agents/skills/react-best-practices/metadata.json +15 -0
  19. package/.agents/skills/react-best-practices/rules/_sections.md +46 -0
  20. package/.agents/skills/react-best-practices/rules/_template.md +28 -0
  21. package/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  22. package/.agents/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  23. package/.agents/skills/react-best-practices/rules/async-api-routes.md +38 -0
  24. package/.agents/skills/react-best-practices/rules/async-defer-await.md +80 -0
  25. package/.agents/skills/react-best-practices/rules/async-dependencies.md +36 -0
  26. package/.agents/skills/react-best-practices/rules/async-parallel.md +28 -0
  27. package/.agents/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  28. package/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  29. package/.agents/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  30. package/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  31. package/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  32. package/.agents/skills/react-best-practices/rules/bundle-preload.md +50 -0
  33. package/.agents/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  34. package/.agents/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  35. package/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  36. package/.agents/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  37. package/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  38. package/.agents/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  39. package/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  40. package/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
  41. package/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  42. package/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
  43. package/.agents/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  44. package/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  45. package/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  46. package/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  47. package/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
  48. package/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  49. package/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  50. package/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  51. package/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  52. package/.agents/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  53. package/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  54. package/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  55. package/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  56. package/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  57. package/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  58. package/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  59. package/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
  60. package/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  61. package/.agents/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  62. package/.agents/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  63. package/.agents/skills/react-best-practices/rules/server-cache-react.md +26 -0
  64. package/.agents/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
  65. package/.agents/skills/react-best-practices/rules/server-serialization.md +38 -0
  66. package/.agents/skills/react-ui-patterns/SKILL.md +289 -0
  67. package/.agents/skills/receiving-code-review/SKILL.md +213 -0
  68. package/.agents/skills/requesting-code-review/SKILL.md +105 -0
  69. package/.agents/skills/requesting-code-review/code-reviewer.md +146 -0
  70. package/.agents/skills/reviewing-code/SKILL.md +28 -0
  71. package/.agents/skills/shadcn/SKILL.md +240 -0
  72. package/.agents/skills/shadcn/agents/openai.yml +5 -0
  73. package/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
  74. package/.agents/skills/shadcn/assets/shadcn.png +0 -0
  75. package/.agents/skills/shadcn/cli.md +255 -0
  76. package/.agents/skills/shadcn/customization.md +202 -0
  77. package/.agents/skills/shadcn/evals/evals.json +47 -0
  78. package/.agents/skills/shadcn/mcp.md +94 -0
  79. package/.agents/skills/shadcn/rules/base-vs-radix.md +306 -0
  80. package/.agents/skills/shadcn/rules/composition.md +195 -0
  81. package/.agents/skills/shadcn/rules/forms.md +192 -0
  82. package/.agents/skills/shadcn/rules/icons.md +101 -0
  83. package/.agents/skills/shadcn/rules/styling.md +162 -0
  84. package/.agents/skills/steering-creation/SKILL.md +221 -0
  85. package/.agents/skills/steering-creation/references/STEERING_CREATION_INSTRUCTION.md +850 -0
  86. package/.agents/skills/subagent-driven-development/SKILL.md +240 -0
  87. package/.agents/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
  88. package/.agents/skills/subagent-driven-development/implementer-prompt.md +78 -0
  89. package/.agents/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  90. package/.agents/skills/systematic-debugging/CREATION-LOG.md +119 -0
  91. package/.agents/skills/systematic-debugging/SKILL.md +296 -0
  92. package/.agents/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  93. package/.agents/skills/systematic-debugging/condition-based-waiting.md +115 -0
  94. package/.agents/skills/systematic-debugging/defense-in-depth.md +122 -0
  95. package/.agents/skills/systematic-debugging/find-polluter.sh +63 -0
  96. package/.agents/skills/systematic-debugging/root-cause-tracing.md +169 -0
  97. package/.agents/skills/systematic-debugging/test-academic.md +14 -0
  98. package/.agents/skills/systematic-debugging/test-pressure-1.md +58 -0
  99. package/.agents/skills/systematic-debugging/test-pressure-2.md +68 -0
  100. package/.agents/skills/systematic-debugging/test-pressure-3.md +69 -0
  101. package/.agents/skills/test-driven-development/SKILL.md +371 -0
  102. package/.agents/skills/test-driven-development/testing-anti-patterns.md +299 -0
  103. package/.agents/skills/using-git-worktrees/SKILL.md +217 -0
  104. package/.agents/skills/using-superpowers/SKILL.md +87 -0
  105. package/.agents/skills/verification-before-completion/SKILL.md +139 -0
  106. package/.agents/skills/web-design-guidelines/SKILL.md +36 -0
  107. package/.agents/skills/writing-plans/SKILL.md +116 -0
  108. package/.agents/skills/writing-skills/SKILL.md +655 -0
  109. package/.agents/skills/writing-skills/anthropic-best-practices.md +1150 -0
  110. package/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  111. package/.agents/skills/writing-skills/graphviz-conventions.dot +172 -0
  112. package/.agents/skills/writing-skills/persuasion-principles.md +187 -0
  113. package/.agents/skills/writing-skills/render-graphs.js +168 -0
  114. package/.agents/skills/writing-skills/testing-skills-with-subagents.md +384 -0
  115. package/.ai/steering/product.md +51 -0
  116. package/.ai/steering/structure.md +275 -0
  117. package/.ai/steering/tech.md +188 -0
  118. package/.claude/agents/database-architect.md +96 -0
  119. package/.claude/agents/deployment-pipeline-architect.md +122 -0
  120. package/.claude/agents/nextjs-expert.md +69 -0
  121. package/.claude/agents/ui-design-expert.md +106 -0
  122. package/.claudeignore +69 -0
  123. package/.dockerignore +8 -0
  124. package/.env.development +86 -0
  125. package/.env.example +171 -0
  126. package/.env.production +139 -0
  127. package/.env.test +58 -0
  128. package/.gitattributes +2 -0
  129. package/.github/ISSUE_TEMPLATE/bug_report.yml +33 -0
  130. package/.github/ISSUE_TEMPLATE/feature_request.yml +20 -0
  131. package/.github/PULL_REQUEST_TEMPLATE.md +23 -0
  132. package/.github/workflows/ci.yml +64 -0
  133. package/.github/workflows/release.yml +131 -0
  134. package/.nvmrc +1 -0
  135. package/.releaserc.json +18 -0
  136. package/.vercelignore +73 -0
  137. package/AGENTS.md +544 -0
  138. package/CHANGELOG.md +37 -0
  139. package/CODE_OF_CONDUCT.md +21 -0
  140. package/CONTRIBUTING.md +32 -0
  141. package/Dockerfile +84 -0
  142. package/LICENSE +21 -0
  143. package/README.md +328 -59
  144. package/SECURITY.md +16 -0
  145. package/bun.lock +3853 -0
  146. package/cli/README.md +94 -0
  147. package/cli/bun.lock +306 -0
  148. package/cli/index.ts +96 -0
  149. package/cli/package-lock.json +2157 -0
  150. package/cli/package.json +30 -0
  151. package/cli/src/commands/backup.ts +78 -0
  152. package/cli/src/commands/doctor.ts +82 -0
  153. package/cli/src/commands/init.ts +234 -0
  154. package/cli/src/commands/logs.ts +26 -0
  155. package/cli/src/commands/open.ts +23 -0
  156. package/cli/src/commands/remove.ts +44 -0
  157. package/cli/src/commands/restart.ts +21 -0
  158. package/cli/src/commands/restore.ts +90 -0
  159. package/cli/src/commands/start.ts +26 -0
  160. package/cli/src/commands/status.ts +25 -0
  161. package/cli/src/commands/stop.ts +20 -0
  162. package/cli/src/commands/upgrade.ts +28 -0
  163. package/cli/src/lib/docker.ts +40 -0
  164. package/cli/src/lib/env.ts +42 -0
  165. package/cli/src/lib/ui.ts +43 -0
  166. package/cli/tsconfig.json +13 -0
  167. package/cli/tsup.config.ts +12 -0
  168. package/components.json +24 -0
  169. package/docker/README.md +430 -0
  170. package/docker/compose.dev-minio.yml +30 -0
  171. package/docker/compose.dev.yml +39 -0
  172. package/docker/compose.local.yml +84 -0
  173. package/docker/compose.yml +153 -0
  174. package/docs/VERSIONING.md +117 -0
  175. package/docs/database/DRIZZLE_COMMANDS_EXPLAINED.md +1779 -0
  176. package/docs/database/DRIZZLE_ZOD_POSTGRESQL_INSTRUCTION.md +646 -0
  177. package/docs/database/MIGRATION_BEST_PRACTICES.md +601 -0
  178. package/docs/database/MIGRATION_ROLLBACK.md +1080 -0
  179. package/docs/database/MIGRATION_SYSTEM.md +165 -0
  180. package/docs/database/MIGRATION_TROUBLESHOOTING.md +881 -0
  181. package/docs/development/ENVIRONMENT_CONFIG.md +896 -0
  182. package/docs/development/LOCAL_DEVELOPMENT.md +456 -0
  183. package/docs/development/REMOTE_DATABASE_SETUP.md +786 -0
  184. package/docs/development/STORAGE_SETUP.md +207 -0
  185. package/docs/development/SUPABASE_LOCAL_SETUP.md +178 -0
  186. package/docs/development/TESTING.md +714 -0
  187. package/docs/feature-architectures/LOADING_ARCHITECTURE.md +343 -0
  188. package/docs/feature-architectures/NOTIFICATION_ARCHITECTURE.md +858 -0
  189. package/docs/feature-architectures/RATE_LIMIT_RESET.md +147 -0
  190. package/docs/feature-architectures/RBAC.md +1132 -0
  191. package/docs/feature-architectures/RESOURCE_LIMITS.md +69 -0
  192. package/docs/feature-architectures/SECURITY.md +284 -0
  193. package/docs/feature-architectures/WORKSPACES.md +278 -0
  194. package/docs/plans/admin-setup-wizard-routing-plan.md +623 -0
  195. package/drizzle/0000_purple_wilson_fisk.sql +360 -0
  196. package/drizzle/0001_drop_instance_public_url.sql +1 -0
  197. package/drizzle/meta/0000_snapshot.json +3118 -0
  198. package/drizzle/meta/_journal.json +20 -0
  199. package/drizzle.config.ts +13 -0
  200. package/eslint.config.mjs +44 -0
  201. package/install.sh +180 -0
  202. package/next.config.ts +91 -0
  203. package/package.json +128 -22
  204. package/playwright.config.ts +70 -0
  205. package/postcss.config.mjs +7 -0
  206. package/public/file.svg +1 -0
  207. package/public/globe.svg +1 -0
  208. package/public/logo.svg +11 -0
  209. package/public/next.svg +1 -0
  210. package/public/playground/CPM-101/as-is-image.jpg +0 -0
  211. package/public/playground/CPM-101/to-be-image.jpg +0 -0
  212. package/public/playground/TEST-1/LinkedIn-skeleton-screen.png +0 -0
  213. package/public/playground/TEST-1/https___dev-to-uploads.s3.amazonaws.com_uploads_articles_vuahe90ka1mkx9aepmea.webp +0 -0
  214. package/public/playground/TEST-1/linkedin_skeletonscreen.jpg +0 -0
  215. package/public/vercel.svg +1 -0
  216. package/public/window.svg +1 -0
  217. package/scripts/__tests__/migrate.integration.test.ts +642 -0
  218. package/scripts/__tests__/migrate.property.test.ts +1714 -0
  219. package/scripts/__tests__/migrate.test.ts +536 -0
  220. package/scripts/admin-reset-password.ts +114 -0
  221. package/scripts/check-email-queue.ts +99 -0
  222. package/scripts/check-sessions.ts +50 -0
  223. package/scripts/db-pull-data.sh +73 -0
  224. package/scripts/force-verify-email.sh +13 -0
  225. package/scripts/migrate.ts +693 -0
  226. package/scripts/process-email-queue.ts +26 -0
  227. package/scripts/reset-db.ts +47 -0
  228. package/scripts/reset-rate-limit.sh +26 -0
  229. package/scripts/reset-remote-db.sql +31 -0
  230. package/scripts/retry-failed-emails.ts +67 -0
  231. package/scripts/seed.ts +605 -0
  232. package/scripts/setup-monitoring.sh +440 -0
  233. package/scripts/sync-migration-tracking.ts +113 -0
  234. package/scripts/test-ci-error-handling.sh +237 -0
  235. package/scripts/test-ci-workflow.sh +200 -0
  236. package/scripts/test-migration.sh +151 -0
  237. package/scripts/validate-env.ts +25 -0
  238. package/scripts/validate-migration-system.ts +566 -0
  239. package/scripts/verify-ci-status-reporting.sh +206 -0
  240. package/scripts/verify-user-email.sql +22 -0
  241. package/scripts/verify-vercel-integration.ts +292 -0
  242. package/seed_data.md +54 -0
  243. package/src/app/(protected)/(team)/(routes)/[projectSlug]/error.tsx +89 -0
  244. package/src/app/(protected)/(team)/(routes)/[projectSlug]/loading.tsx +101 -0
  245. package/src/app/(protected)/(team)/(routes)/[projectSlug]/page.tsx +91 -0
  246. package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/README.md +192 -0
  247. package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/error.tsx +58 -0
  248. package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/loading.tsx +14 -0
  249. package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/not-found.tsx +47 -0
  250. package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/page.tsx +91 -0
  251. package/src/app/(protected)/(team)/projects/page.tsx +16 -0
  252. package/src/app/(protected)/(team)/team/settings/(section)/instance/page.tsx +52 -0
  253. package/src/app/(protected)/(team)/team/settings/(section)/integrations/loading.tsx +5 -0
  254. package/src/app/(protected)/(team)/team/settings/(section)/integrations/page.tsx +23 -0
  255. package/src/app/(protected)/(team)/team/settings/(section)/members/loading.tsx +5 -0
  256. package/src/app/(protected)/(team)/team/settings/(section)/members/page.tsx +35 -0
  257. package/src/app/(protected)/(team)/team/settings/layout.tsx +72 -0
  258. package/src/app/(protected)/(team)/team/settings/loading.tsx +5 -0
  259. package/src/app/(protected)/(team)/team/settings/page.tsx +71 -0
  260. package/src/app/(protected)/dev/auth/README.md +151 -0
  261. package/src/app/(protected)/dev/auth/page.tsx +590 -0
  262. package/src/app/(protected)/layout.test.tsx +209 -0
  263. package/src/app/(protected)/layout.tsx +28 -0
  264. package/src/app/(protected)/onboarding/page.tsx +27 -0
  265. package/src/app/(protected)/settings/integrations/page.tsx +23 -0
  266. package/src/app/(protected)/settings/layout.tsx +26 -0
  267. package/src/app/(protected)/settings/notifications/page.tsx +26 -0
  268. package/src/app/(protected)/settings/other/page.tsx +23 -0
  269. package/src/app/(protected)/settings/page.tsx +23 -0
  270. package/src/app/(protected)/settings/preferences/page.tsx +23 -0
  271. package/src/app/(protected)/settings/security/page.tsx +37 -0
  272. package/src/app/(public)/forgot-password/page.tsx +20 -0
  273. package/src/app/(public)/invite/project/[token]/error.tsx +50 -0
  274. package/src/app/(public)/invite/project/[token]/loading.tsx +39 -0
  275. package/src/app/(public)/invite/project/[token]/page.tsx +156 -0
  276. package/src/app/(public)/layout.tsx +9 -0
  277. package/src/app/(public)/privacy-policy/page.tsx +12 -0
  278. package/src/app/(public)/reset-password/page.tsx +37 -0
  279. package/src/app/(public)/setup/__tests__/page.test.tsx +30 -0
  280. package/src/app/(public)/setup/page.tsx +17 -0
  281. package/src/app/(public)/share/issue/[token]/page.tsx +51 -0
  282. package/src/app/(public)/sign-in/page.tsx +55 -0
  283. package/src/app/(public)/sign-up/page.tsx +23 -0
  284. package/src/app/(public)/verify-email/page.tsx +22 -0
  285. package/src/app/(public)/verify-email-confirm/page.tsx +40 -0
  286. package/src/app/api/auth/[...all]/route.ts +6 -0
  287. package/src/app/api/auth/delete-account/route.ts +134 -0
  288. package/src/app/api/auth/dev/force-verify/route.ts +180 -0
  289. package/src/app/api/auth/dev/reset-rate-limit/route.ts +144 -0
  290. package/src/app/api/auth/dev/sessions/route.ts +172 -0
  291. package/src/app/api/auth/forgot-password/__tests__/forgot-password.property.test.ts +397 -0
  292. package/src/app/api/auth/forgot-password/route.ts +277 -0
  293. package/src/app/api/auth/logout/route.ts +115 -0
  294. package/src/app/api/auth/me/route.ts +123 -0
  295. package/src/app/api/auth/providers/__tests__/route.test.ts +236 -0
  296. package/src/app/api/auth/providers/route.ts +119 -0
  297. package/src/app/api/auth/resend-verification/route.ts +262 -0
  298. package/src/app/api/auth/reset-password/__tests__/reset-password.property.test.ts +493 -0
  299. package/src/app/api/auth/reset-password/__tests__/route.test.ts +284 -0
  300. package/src/app/api/auth/reset-password/route.ts +251 -0
  301. package/src/app/api/auth/verify-email/route.ts +232 -0
  302. package/src/app/api/example-cors/route.ts +61 -0
  303. package/src/app/api/health/route.ts +14 -0
  304. package/src/app/api/invite/project/[token]/__tests__/accept-invitation.integration.test.ts +348 -0
  305. package/src/app/api/invite/project/[token]/decline/route.ts +99 -0
  306. package/src/app/api/invite/project/[token]/route.ts +269 -0
  307. package/src/app/api/issues/[issueId]/activities/route.ts +213 -0
  308. package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/comments/[commentId]/route.ts +486 -0
  309. package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/comments/route.ts +283 -0
  310. package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/read/route.ts +242 -0
  311. package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/route.ts +534 -0
  312. package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/route.ts +514 -0
  313. package/src/app/api/issues/[issueId]/attachments/[attachmentId]/route.ts +161 -0
  314. package/src/app/api/issues/[issueId]/attachments/route.ts +376 -0
  315. package/src/app/api/issues/[issueId]/route.ts +516 -0
  316. package/src/app/api/notifications/[id]/read/route.ts +131 -0
  317. package/src/app/api/notifications/__tests__/notifications.integration.test.ts +350 -0
  318. package/src/app/api/notifications/read-all/route.ts +72 -0
  319. package/src/app/api/notifications/route.ts +148 -0
  320. package/src/app/api/notifications/unread-count/route.ts +77 -0
  321. package/src/app/api/projects/[id]/activities/route.ts +174 -0
  322. package/src/app/api/projects/[id]/invitations/[invitationId]/resend/route.ts +99 -0
  323. package/src/app/api/projects/[id]/invitations/[invitationId]/route.ts +96 -0
  324. package/src/app/api/projects/[id]/invitations/route.ts +254 -0
  325. package/src/app/api/projects/[id]/issues/route.ts +452 -0
  326. package/src/app/api/projects/[id]/join/route.ts +207 -0
  327. package/src/app/api/projects/[id]/members/[memberId]/route.ts +364 -0
  328. package/src/app/api/projects/[id]/members/me/route.ts +121 -0
  329. package/src/app/api/projects/[id]/members/route.ts +129 -0
  330. package/src/app/api/projects/[id]/route.ts +476 -0
  331. package/src/app/api/projects/route.ts +394 -0
  332. package/src/app/api/setup/admin/route.ts +255 -0
  333. package/src/app/api/setup/complete/__tests__/route.test.ts +60 -0
  334. package/src/app/api/setup/complete/route.ts +244 -0
  335. package/src/app/api/setup/config/route.ts +195 -0
  336. package/src/app/api/setup/export/route.ts +111 -0
  337. package/src/app/api/setup/health/route.ts +74 -0
  338. package/src/app/api/setup/import/route.ts +154 -0
  339. package/src/app/api/setup/status/route.ts +82 -0
  340. package/src/app/api/setup/workspace/route.ts +252 -0
  341. package/src/app/api/teams/[teamId]/export/route.ts +115 -0
  342. package/src/app/api/teams/[teamId]/invitations/[invitationId]/resend/route.ts +132 -0
  343. package/src/app/api/teams/[teamId]/invitations/[invitationId]/route.ts +117 -0
  344. package/src/app/api/teams/[teamId]/invitations/route.ts +363 -0
  345. package/src/app/api/teams/[teamId]/members/[userId]/route.ts +335 -0
  346. package/src/app/api/teams/[teamId]/members/route.ts +184 -0
  347. package/src/app/api/teams/[teamId]/members/search/route.ts +202 -0
  348. package/src/app/api/teams/[teamId]/route.ts +423 -0
  349. package/src/app/api/teams/[teamId]/switch/route.ts +140 -0
  350. package/src/app/api/teams/[teamId]/transfer-ownership/route.ts +212 -0
  351. package/src/app/api/teams/invitations/[token]/accept/route.ts +140 -0
  352. package/src/app/api/teams/invitations/by-id/[id]/accept/route.ts +98 -0
  353. package/src/app/api/teams/invitations/by-id/[id]/decline/route.ts +90 -0
  354. package/src/app/api/teams/route.ts +278 -0
  355. package/src/app/api/uploads/media/route.ts +118 -0
  356. package/src/app/api/uploads/presigned/route.ts +49 -0
  357. package/src/app/api/user/linked-accounts/route.ts +35 -0
  358. package/src/app/email-preview/page.tsx +11 -0
  359. package/src/app/favicon.ico +0 -0
  360. package/src/app/global-error.tsx +21 -0
  361. package/src/app/layout.tsx +50 -0
  362. package/src/app/page.tsx +5 -0
  363. package/src/components/icons/atlassian-icon.tsx +22 -0
  364. package/src/components/icons/index.ts +1 -0
  365. package/src/components/layout/SIDEBAR_LAYOUT_BEST_PRACTICES.md +240 -0
  366. package/src/components/layout/app-shell-header-store.tsx +20 -0
  367. package/src/components/layout/app-shell-skeleton.tsx +89 -0
  368. package/src/components/layout/app-shell-wrapper.tsx +32 -0
  369. package/src/components/layout/app-shell.test.tsx +155 -0
  370. package/src/components/layout/app-shell.tsx +100 -0
  371. package/src/components/shared/headers/app-header-configurator.tsx +42 -0
  372. package/src/components/shared/headers/app-header.tsx +103 -0
  373. package/src/components/shared/headers/header-user-menu.tsx +247 -0
  374. package/src/components/shared/headers/index.ts +44 -0
  375. package/src/components/shared/headers/page-header.tsx +25 -0
  376. package/src/components/shared/notifications/__tests__/notification-bell.test.tsx +159 -0
  377. package/src/components/shared/notifications/__tests__/notification-dropdown.test.tsx +296 -0
  378. package/src/components/shared/notifications/__tests__/notification-item.test.tsx +328 -0
  379. package/src/components/shared/notifications/index.ts +45 -0
  380. package/src/components/shared/notifications/notification-actions.tsx +295 -0
  381. package/src/components/shared/notifications/notification-bell-button.tsx +77 -0
  382. package/src/components/shared/notifications/notification-dropdown.tsx +160 -0
  383. package/src/components/shared/notifications/notification-group-item.tsx +268 -0
  384. package/src/components/shared/notifications/notification-item.tsx +193 -0
  385. package/src/components/shared/notifications/notification-load-more.tsx +50 -0
  386. package/src/components/shared/notifications/notification-panel.tsx +49 -0
  387. package/src/components/shared/notifications/utils.tsx +127 -0
  388. package/src/components/shared/permission-guard/index.ts +1 -0
  389. package/src/components/shared/permission-guard/permission-tooltip.tsx +45 -0
  390. package/src/components/shared/relative-time.tsx +53 -0
  391. package/src/components/shared/section-container.tsx +32 -0
  392. package/src/components/shared/service-status-banner.tsx +121 -0
  393. package/src/components/shared/settings-sidebar/index.ts +2 -0
  394. package/src/components/shared/settings-sidebar/team-setting-aside.tsx +97 -0
  395. package/src/components/shared/settings-sidebar/user-settings-aside.tsx +66 -0
  396. package/src/components/shared/sidebar/app-sidebar.tsx +146 -0
  397. package/src/components/shared/sidebar/index.ts +36 -0
  398. package/src/components/shared/sidebar/sidebar-main.tsx +81 -0
  399. package/src/components/shared/sidebar/sidebar-project.tsx +61 -0
  400. package/src/components/shared/sidebar/sidebar-team-avatar.tsx +126 -0
  401. package/src/components/shared/sidebar/sidebar-team-switcher.tsx +185 -0
  402. package/src/components/shared/sidebar/type.ts +97 -0
  403. package/src/components/ui/alert-dialog.tsx +157 -0
  404. package/src/components/ui/alert.tsx +66 -0
  405. package/src/components/ui/avatar-upload.tsx +147 -0
  406. package/src/components/ui/avatar.tsx +53 -0
  407. package/src/components/ui/badge.tsx +46 -0
  408. package/src/components/ui/breadcrumb.tsx +109 -0
  409. package/src/components/ui/button.tsx +60 -0
  410. package/src/components/ui/card.tsx +92 -0
  411. package/src/components/ui/checkbox.tsx +32 -0
  412. package/src/components/ui/collapsible.tsx +33 -0
  413. package/src/components/ui/command.tsx +184 -0
  414. package/src/components/ui/dialog.tsx +143 -0
  415. package/src/components/ui/dropdown-menu.tsx +257 -0
  416. package/src/components/ui/empty.tsx +104 -0
  417. package/src/components/ui/field.tsx +244 -0
  418. package/src/components/ui/image-cropper-dialog.tsx +167 -0
  419. package/src/components/ui/input.tsx +21 -0
  420. package/src/components/ui/label.tsx +24 -0
  421. package/src/components/ui/optimized-image.tsx +220 -0
  422. package/src/components/ui/pagination.tsx +127 -0
  423. package/src/components/ui/popover.tsx +48 -0
  424. package/src/components/ui/progress.tsx +31 -0
  425. package/src/components/ui/radio-group.tsx +45 -0
  426. package/src/components/ui/scroll-area.tsx +58 -0
  427. package/src/components/ui/select.tsx +187 -0
  428. package/src/components/ui/separator.tsx +28 -0
  429. package/src/components/ui/sheet.tsx +139 -0
  430. package/src/components/ui/sidebar.tsx +733 -0
  431. package/src/components/ui/skeleton.tsx +13 -0
  432. package/src/components/ui/sonner.tsx +40 -0
  433. package/src/components/ui/spinner.tsx +16 -0
  434. package/src/components/ui/switch.tsx +31 -0
  435. package/src/components/ui/table.tsx +116 -0
  436. package/src/components/ui/tabs.tsx +66 -0
  437. package/src/components/ui/textarea.tsx +23 -0
  438. package/src/components/ui/tooltip.tsx +61 -0
  439. package/src/config/__tests__/workspace.property.test.ts +40 -0
  440. package/src/config/auth.ts +62 -0
  441. package/src/config/integrations.ts +126 -0
  442. package/src/config/quotas.ts +20 -0
  443. package/src/config/roles.ts +463 -0
  444. package/src/config/settings-nav.ts +39 -0
  445. package/src/config/team-settings-nav.ts +37 -0
  446. package/src/config/user-settings-nav.ts +42 -0
  447. package/src/config/version.ts +1 -0
  448. package/src/config/workspace.ts +64 -0
  449. package/src/features/annotations/README.md +283 -0
  450. package/src/features/annotations/api/annotations-api.ts +194 -0
  451. package/src/features/annotations/api/comments-api.ts +147 -0
  452. package/src/features/annotations/api/index.ts +71 -0
  453. package/src/features/annotations/api/save-annotation.ts +150 -0
  454. package/src/features/annotations/api/schemas.ts +142 -0
  455. package/src/features/annotations/components/annotated-attachment-view.tsx +576 -0
  456. package/src/features/annotations/components/annotation-action-sheet.tsx +140 -0
  457. package/src/features/annotations/components/annotation-annotations-panel.tsx +213 -0
  458. package/src/features/annotations/components/annotation-box.tsx +539 -0
  459. package/src/features/annotations/components/annotation-canvas.tsx +534 -0
  460. package/src/features/annotations/components/annotation-comment-input.tsx +145 -0
  461. package/src/features/annotations/components/annotation-context-menu.tsx +164 -0
  462. package/src/features/annotations/components/annotation-drawer.tsx +231 -0
  463. package/src/features/annotations/components/annotation-layer.tsx +271 -0
  464. package/src/features/annotations/components/annotation-pin.tsx +318 -0
  465. package/src/features/annotations/components/annotation-popover.tsx +562 -0
  466. package/src/features/annotations/components/annotation-thread-panel.tsx +485 -0
  467. package/src/features/annotations/components/annotation-thread-preview.tsx +195 -0
  468. package/src/features/annotations/components/annotation-toolbar.tsx +244 -0
  469. package/src/features/annotations/components/keyboard-shortcuts-modal.tsx +79 -0
  470. package/src/features/annotations/docs/ANNOTATIONS_ARCHITECTURE.md +67 -0
  471. package/src/features/annotations/docs/ANNOTATION_SAVE_ARCHITECTURE.md +422 -0
  472. package/src/features/annotations/docs/ANNOTATION_SAVE_FEATURE.md +408 -0
  473. package/src/features/annotations/docs/BOX_ANNOTATION_GUIDE.md +542 -0
  474. package/src/features/annotations/docs/NEXTSTEP.md +28 -0
  475. package/src/features/annotations/docs/STALE_CLOSURE_FIX.md +344 -0
  476. package/src/features/annotations/docs/UNDO_REDO_QUICK_START.md +545 -0
  477. package/src/features/annotations/docs/local_first_canvas_autosave_architecture.md +674 -0
  478. package/src/features/annotations/examples/complete-example.tsx +266 -0
  479. package/src/features/annotations/examples/save-annotation-example.tsx +309 -0
  480. package/src/features/annotations/hooks/__tests__/use-annotation-permissions.property.test.tsx +493 -0
  481. package/src/features/annotations/hooks/index.ts +36 -0
  482. package/src/features/annotations/hooks/use-annotation-batch-save.ts +109 -0
  483. package/src/features/annotations/hooks/use-annotation-comments.ts +353 -0
  484. package/src/features/annotations/hooks/use-annotation-drafts.ts +137 -0
  485. package/src/features/annotations/hooks/use-annotation-edit-state.ts +99 -0
  486. package/src/features/annotations/hooks/use-annotation-history-tracker.ts +159 -0
  487. package/src/features/annotations/hooks/use-annotation-integration.ts +916 -0
  488. package/src/features/annotations/hooks/use-annotation-permissions.ts +210 -0
  489. package/src/features/annotations/hooks/use-annotation-popover.ts +175 -0
  490. package/src/features/annotations/hooks/use-annotation-save.ts +208 -0
  491. package/src/features/annotations/hooks/use-annotation-tools.ts +237 -0
  492. package/src/features/annotations/hooks/use-annotations-with-history.ts +332 -0
  493. package/src/features/annotations/hooks/use-auto-save.ts +94 -0
  494. package/src/features/annotations/index.ts +111 -0
  495. package/src/features/annotations/types/annotation.ts +201 -0
  496. package/src/features/annotations/types/index.ts +28 -0
  497. package/src/features/annotations/utils/history-manager.ts +73 -0
  498. package/src/features/annotations/utils/index.ts +2 -0
  499. package/src/features/annotations/utils/map-attachments-to-threads.ts +28 -0
  500. package/src/features/annotations/utils/position-comment-input.ts +136 -0
  501. package/src/features/annotations/utils/re-sequence-labels.ts +92 -0
  502. package/src/features/annotations/utils/validate-annotation-label.ts +120 -0
  503. package/src/features/auth/api/types.ts +101 -0
  504. package/src/features/auth/components/__tests__/role-gate.test.tsx +448 -0
  505. package/src/features/auth/components/__tests__/social-login-buttons.test.tsx +313 -0
  506. package/src/features/auth/components/auth-card.tsx +36 -0
  507. package/src/features/auth/components/forgot-password-form.tsx +115 -0
  508. package/src/features/auth/components/index.ts +14 -0
  509. package/src/features/auth/components/invite-code-input.tsx +155 -0
  510. package/src/features/auth/components/invited-user-form.tsx +309 -0
  511. package/src/features/auth/components/onboarding-form.tsx +195 -0
  512. package/src/features/auth/components/password-strength-indicator.tsx +113 -0
  513. package/src/features/auth/components/reset-password-form.tsx +138 -0
  514. package/src/features/auth/components/role-gate.tsx +124 -0
  515. package/src/features/auth/components/self-registration-choice.tsx +153 -0
  516. package/src/features/auth/components/sign-in-form.tsx +159 -0
  517. package/src/features/auth/components/sign-up-form.tsx +158 -0
  518. package/src/features/auth/components/social-login-buttons.tsx +219 -0
  519. package/src/features/auth/hooks/__tests__/use-onboarding.test.tsx +109 -0
  520. package/src/features/auth/hooks/__tests__/use-session.test.tsx +160 -0
  521. package/src/features/auth/hooks/index.ts +15 -0
  522. package/src/features/auth/hooks/use-accept-invitation.ts +194 -0
  523. package/src/features/auth/hooks/use-delete-account.ts +86 -0
  524. package/src/features/auth/hooks/use-force-verify.ts +89 -0
  525. package/src/features/auth/hooks/use-forgot-password.ts +144 -0
  526. package/src/features/auth/hooks/use-link-account.ts +78 -0
  527. package/src/features/auth/hooks/use-linked-accounts.ts +88 -0
  528. package/src/features/auth/hooks/use-onboarding.ts +159 -0
  529. package/src/features/auth/hooks/use-resend-verification.ts +139 -0
  530. package/src/features/auth/hooks/use-reset-password.ts +151 -0
  531. package/src/features/auth/hooks/use-reset-rate-limit.ts +56 -0
  532. package/src/features/auth/hooks/use-self-registration.ts +202 -0
  533. package/src/features/auth/hooks/use-session.ts +81 -0
  534. package/src/features/auth/hooks/use-sessions.ts +59 -0
  535. package/src/features/auth/hooks/use-sign-in.ts +234 -0
  536. package/src/features/auth/hooks/use-sign-out.ts +88 -0
  537. package/src/features/auth/hooks/use-sign-up.ts +194 -0
  538. package/src/features/auth/hooks/use-unlink-account.ts +100 -0
  539. package/src/features/auth/hooks/use-verify-email-token.ts +125 -0
  540. package/src/features/auth/index.ts +75 -0
  541. package/src/features/auth/screens/forgot-password-screen.tsx +33 -0
  542. package/src/features/auth/screens/index.ts +7 -0
  543. package/src/features/auth/screens/onboarding-screen.tsx +49 -0
  544. package/src/features/auth/screens/reset-password-screen.tsx +33 -0
  545. package/src/features/auth/screens/sign-in-screen.tsx +61 -0
  546. package/src/features/auth/screens/sign-up-screen.tsx +37 -0
  547. package/src/features/auth/screens/verify-email-confirm-screen.tsx +286 -0
  548. package/src/features/auth/screens/verify-email-screen.tsx +146 -0
  549. package/src/features/auth/types/index.ts +14 -0
  550. package/src/features/auth/utils/__tests__/validators.test.ts +331 -0
  551. package/src/features/auth/utils/password-strength.ts +129 -0
  552. package/src/features/auth/utils/validators.ts +124 -0
  553. package/src/features/email-preview/actions/render-email.ts +21 -0
  554. package/src/features/email-preview/screens/email-preview-screen.tsx +81 -0
  555. package/src/features/folder-scaffold-template/index.ts +0 -0
  556. package/src/features/instance-settings/components/index.ts +6 -0
  557. package/src/features/instance-settings/components/instance-settings-form.tsx +180 -0
  558. package/src/features/instance-settings/components/instance-status-display.tsx +158 -0
  559. package/src/features/instance-settings/index.ts +7 -0
  560. package/src/features/instance-settings/screens/index.ts +5 -0
  561. package/src/features/instance-settings/screens/instance-settings-screen.tsx +59 -0
  562. package/src/features/issues/README.md +330 -0
  563. package/src/features/issues/api/create-issue.ts +19 -0
  564. package/src/features/issues/api/delete-issue.ts +27 -0
  565. package/src/features/issues/api/get-issue-activities.ts +58 -0
  566. package/src/features/issues/api/get-issue-details.ts +25 -0
  567. package/src/features/issues/api/get-project-issues-server.ts +44 -0
  568. package/src/features/issues/api/get-project-issues.ts +21 -0
  569. package/src/features/issues/api/index.ts +44 -0
  570. package/src/features/issues/api/update-issue.ts +31 -0
  571. package/src/features/issues/api/upload-attachment.ts +81 -0
  572. package/src/features/issues/components/activity-timeline.tsx +440 -0
  573. package/src/features/issues/components/canvas-state-indicator.tsx +90 -0
  574. package/src/features/issues/components/centered-canvas-view.tsx +739 -0
  575. package/src/features/issues/components/image-selector.tsx +123 -0
  576. package/src/features/issues/components/image-upload-zone.tsx +262 -0
  577. package/src/features/issues/components/infinite-canvas-background.tsx +163 -0
  578. package/src/features/issues/components/inline-editable-select.tsx +173 -0
  579. package/src/features/issues/components/inline-editable-text.tsx +225 -0
  580. package/src/features/issues/components/inline-editable-textarea.tsx +219 -0
  581. package/src/features/issues/components/inline-editable-user-select.tsx +202 -0
  582. package/src/features/issues/components/issue-deletion-dialog.tsx +142 -0
  583. package/src/features/issues/components/issue-details-panel.tsx +101 -0
  584. package/src/features/issues/components/issues-create-dialog.tsx +578 -0
  585. package/src/features/issues/components/issues-list-filter.tsx +312 -0
  586. package/src/features/issues/components/issues-list.tsx +151 -0
  587. package/src/features/issues/components/issues-priority-badge.tsx +77 -0
  588. package/src/features/issues/components/issues-status-badge.tsx +100 -0
  589. package/src/features/issues/components/metadata-section.tsx +389 -0
  590. package/src/features/issues/components/optimized-attachment-view.tsx +528 -0
  591. package/src/features/issues/components/optimized-image.tsx +257 -0
  592. package/src/features/issues/components/panel-header.tsx +186 -0
  593. package/src/features/issues/components/preload.ts +31 -0
  594. package/src/features/issues/components/priority-selector.tsx +101 -0
  595. package/src/features/issues/components/responsive-issue-layout-skeleton.tsx +139 -0
  596. package/src/features/issues/components/responsive-issue-layout.tsx +617 -0
  597. package/src/features/issues/components/status-selector.tsx +320 -0
  598. package/src/features/issues/components/type-selector.tsx +102 -0
  599. package/src/features/issues/components/upload-progress-overlay.tsx +35 -0
  600. package/src/features/issues/components/uploaded-image-preview.tsx +173 -0
  601. package/src/features/issues/components/workflow-control.tsx +318 -0
  602. package/src/features/issues/components/zoom-controls.tsx +150 -0
  603. package/src/features/issues/config/index.ts +47 -0
  604. package/src/features/issues/config/options.ts +323 -0
  605. package/src/features/issues/config/workflow.ts +102 -0
  606. package/src/features/issues/docs/ARCHITECTURE_DIAGRAM.md +321 -0
  607. package/src/features/issues/docs/BACKEND_ARCHITECTURE.md +194 -0
  608. package/src/features/issues/docs/IMAGE_COMPONENTS_ARCHITECTURE.md +363 -0
  609. package/src/features/issues/docs/IMAGE_COMPONENTS_IMPORTS.md +412 -0
  610. package/src/features/issues/docs/IMPLEMENTATION_CHECKLIST.md +210 -0
  611. package/src/features/issues/docs/ROUTE_SETUP_COMPLETE.md +242 -0
  612. package/src/features/issues/hooks/index.ts +78 -0
  613. package/src/features/issues/hooks/use-canvas-transform.ts +255 -0
  614. package/src/features/issues/hooks/use-create-issue.ts +28 -0
  615. package/src/features/issues/hooks/use-elastic-scroll.ts +296 -0
  616. package/src/features/issues/hooks/use-issue-activities.ts +71 -0
  617. package/src/features/issues/hooks/use-issue-delete.ts +84 -0
  618. package/src/features/issues/hooks/use-issue-details.ts +70 -0
  619. package/src/features/issues/hooks/use-issue-filters.ts +50 -0
  620. package/src/features/issues/hooks/use-issue-update.ts +93 -0
  621. package/src/features/issues/hooks/use-keyboard-shortcuts.ts +104 -0
  622. package/src/features/issues/hooks/use-optimized-image.ts +228 -0
  623. package/src/features/issues/hooks/use-project-issues.ts +14 -0
  624. package/src/features/issues/index.ts +65 -0
  625. package/src/features/issues/screens/issue-details-screen.tsx +207 -0
  626. package/src/features/issues/screens/issue-details-skeletons.tsx +295 -0
  627. package/src/features/issues/screens/issue-share-screen.tsx +56 -0
  628. package/src/features/issues/types/index.ts +48 -0
  629. package/src/features/issues/types/issue.ts +291 -0
  630. package/src/features/issues/utils/filter-issues.ts +141 -0
  631. package/src/features/issues/utils/index.ts +14 -0
  632. package/src/features/legal/index.ts +1 -0
  633. package/src/features/legal/screens/privacy-policy-screen.tsx +307 -0
  634. package/src/features/notifications/api/get-notifications.ts +58 -0
  635. package/src/features/notifications/api/get-unread-count.ts +37 -0
  636. package/src/features/notifications/api/index.ts +35 -0
  637. package/src/features/notifications/api/mark-all-as-read.ts +37 -0
  638. package/src/features/notifications/api/mark-as-read.ts +41 -0
  639. package/src/features/notifications/api/types.ts +109 -0
  640. package/src/features/notifications/hooks/__tests__/use-notification-subscription.test.ts +206 -0
  641. package/src/features/notifications/hooks/index.ts +28 -0
  642. package/src/features/notifications/hooks/use-mark-all-as-read.ts +106 -0
  643. package/src/features/notifications/hooks/use-mark-as-read.ts +106 -0
  644. package/src/features/notifications/hooks/use-notification-subscription.ts +244 -0
  645. package/src/features/notifications/hooks/use-notification-toast.ts +161 -0
  646. package/src/features/notifications/hooks/use-notifications.ts +80 -0
  647. package/src/features/notifications/hooks/use-unread-count.ts +60 -0
  648. package/src/features/notifications/index.ts +48 -0
  649. package/src/features/notifications/utils/group-notifications.ts +152 -0
  650. package/src/features/notifications/utils/index.ts +9 -0
  651. package/src/features/projects/api/create-invitation.ts +45 -0
  652. package/src/features/projects/api/create-project.ts +64 -0
  653. package/src/features/projects/api/delete-project.ts +50 -0
  654. package/src/features/projects/api/get-project-activities.ts +43 -0
  655. package/src/features/projects/api/get-project-members.ts +53 -0
  656. package/src/features/projects/api/get-project.ts +49 -0
  657. package/src/features/projects/api/get-projects.ts +61 -0
  658. package/src/features/projects/api/index.ts +27 -0
  659. package/src/features/projects/api/join-project.ts +52 -0
  660. package/src/features/projects/api/leave-project.ts +51 -0
  661. package/src/features/projects/api/list-invitations.ts +36 -0
  662. package/src/features/projects/api/remove-member.ts +60 -0
  663. package/src/features/projects/api/resend-invitation.ts +36 -0
  664. package/src/features/projects/api/revoke-invitation.ts +36 -0
  665. package/src/features/projects/api/types.ts +286 -0
  666. package/src/features/projects/api/update-member-role.ts +70 -0
  667. package/src/features/projects/api/update-project.ts +69 -0
  668. package/src/features/projects/components/__tests__/project-detail-activity-feed.test.tsx +106 -0
  669. package/src/features/projects/components/__tests__/project-invitation-dialog.test.tsx +211 -0
  670. package/src/features/projects/components/__tests__/project-member-manager-dialog.test.tsx +254 -0
  671. package/src/features/projects/components/index.ts +21 -0
  672. package/src/features/projects/components/project-actions.tsx +248 -0
  673. package/src/features/projects/components/project-create-dialog.tsx +410 -0
  674. package/src/features/projects/components/project-detail-activity-feed.tsx +206 -0
  675. package/src/features/projects/components/project-detail-header.tsx +103 -0
  676. package/src/features/projects/components/project-detail-overview.tsx +128 -0
  677. package/src/features/projects/components/project-icon-selector.test.tsx +49 -0
  678. package/src/features/projects/components/project-icon-selector.tsx +76 -0
  679. package/src/features/projects/components/project-invitation-dialog.tsx +368 -0
  680. package/src/features/projects/components/project-issues.tsx +128 -0
  681. package/src/features/projects/components/project-leave-button.tsx +69 -0
  682. package/src/features/projects/components/project-list-card.tsx +246 -0
  683. package/src/features/projects/components/project-list-filters.tsx +320 -0
  684. package/src/features/projects/components/project-member-manager-dialog.tsx +419 -0
  685. package/src/features/projects/components/project-settings-dialog.tsx +204 -0
  686. package/src/features/projects/components/project-stats.tsx +46 -0
  687. package/src/features/projects/components/project-title-section.tsx +78 -0
  688. package/src/features/projects/config/icons.ts +91 -0
  689. package/src/features/projects/hooks/index.ts +28 -0
  690. package/src/features/projects/hooks/use-create-invitation.ts +83 -0
  691. package/src/features/projects/hooks/use-create-project.ts +77 -0
  692. package/src/features/projects/hooks/use-delete-project.ts +84 -0
  693. package/src/features/projects/hooks/use-join-project.ts +43 -0
  694. package/src/features/projects/hooks/use-leave-project.ts +84 -0
  695. package/src/features/projects/hooks/use-project-activities.ts +39 -0
  696. package/src/features/projects/hooks/use-project-filters.ts +86 -0
  697. package/src/features/projects/hooks/use-project-invitations.ts +66 -0
  698. package/src/features/projects/hooks/use-project-members.ts +57 -0
  699. package/src/features/projects/hooks/use-project.ts +67 -0
  700. package/src/features/projects/hooks/use-projects.ts +49 -0
  701. package/src/features/projects/hooks/use-recent-projects.ts +58 -0
  702. package/src/features/projects/hooks/use-remove-member.ts +89 -0
  703. package/src/features/projects/hooks/use-resend-invitation.ts +68 -0
  704. package/src/features/projects/hooks/use-revoke-invitation.ts +71 -0
  705. package/src/features/projects/hooks/use-team-member-suggestions.ts +133 -0
  706. package/src/features/projects/hooks/use-update-member-role.ts +92 -0
  707. package/src/features/projects/hooks/use-update-project.ts +88 -0
  708. package/src/features/projects/index.ts +91 -0
  709. package/src/features/projects/screens/index.ts +3 -0
  710. package/src/features/projects/screens/invitation-acceptance-screen.tsx +320 -0
  711. package/src/features/projects/screens/project-detail-screen-wrapper.tsx +47 -0
  712. package/src/features/projects/screens/project-detail-screen.tsx +661 -0
  713. package/src/features/projects/screens/projects-list-screen.tsx +161 -0
  714. package/src/features/projects/types/index.ts +59 -0
  715. package/src/features/projects/utils/format-helpers.ts +16 -0
  716. package/src/features/projects/utils/index.ts +2 -0
  717. package/src/features/projects/utils/role-helpers.ts +25 -0
  718. package/src/features/setup/api/complete-setup.ts +21 -0
  719. package/src/features/setup/api/create-admin.ts +21 -0
  720. package/src/features/setup/api/create-first-workspace.ts +21 -0
  721. package/src/features/setup/api/get-instance-status.ts +12 -0
  722. package/src/features/setup/api/get-service-health.ts +12 -0
  723. package/src/features/setup/api/index.ts +44 -0
  724. package/src/features/setup/api/save-instance-config.ts +21 -0
  725. package/src/features/setup/api/types.ts +122 -0
  726. package/src/features/setup/components/__tests__/setup-wizard-ui.test.tsx +362 -0
  727. package/src/features/setup/components/admin-account-step.tsx +205 -0
  728. package/src/features/setup/components/first-workspace-step.tsx +120 -0
  729. package/src/features/setup/components/index.ts +9 -0
  730. package/src/features/setup/components/instance-config-step.tsx +107 -0
  731. package/src/features/setup/components/mail-config-step.tsx +205 -0
  732. package/src/features/setup/components/sample-data-step.tsx +131 -0
  733. package/src/features/setup/components/service-health-step.tsx +180 -0
  734. package/src/features/setup/components/service-status-badge.tsx +50 -0
  735. package/src/features/setup/components/setup-progress.tsx +103 -0
  736. package/src/features/setup/components/setup-wizard.tsx +169 -0
  737. package/src/features/setup/hooks/index.ts +12 -0
  738. package/src/features/setup/hooks/use-complete-setup.ts +23 -0
  739. package/src/features/setup/hooks/use-create-admin.ts +25 -0
  740. package/src/features/setup/hooks/use-create-first-workspace.ts +24 -0
  741. package/src/features/setup/hooks/use-instance-status.ts +21 -0
  742. package/src/features/setup/hooks/use-save-instance-config.ts +23 -0
  743. package/src/features/setup/hooks/use-service-health.ts +21 -0
  744. package/src/features/setup/hooks/use-setup-wizard.ts +152 -0
  745. package/src/features/setup/hooks/use-workspace-mode.ts +19 -0
  746. package/src/features/setup/index.ts +30 -0
  747. package/src/features/setup/screens/index.ts +1 -0
  748. package/src/features/setup/screens/setup-screen.tsx +40 -0
  749. package/src/features/setup/types/index.ts +69 -0
  750. package/src/features/setup/utils/index.ts +78 -0
  751. package/src/features/team-settings/components/index.ts +39 -0
  752. package/src/features/team-settings/components/loading-states.tsx +296 -0
  753. package/src/features/team-settings/components/permission-guard.tsx +23 -0
  754. package/src/features/team-settings/components/settings-card.tsx +22 -0
  755. package/src/features/team-settings/components/settings-context-provider.tsx +51 -0
  756. package/src/features/team-settings/components/settings-error-boundary.tsx +366 -0
  757. package/src/features/team-settings/components/settings-navigation.tsx +87 -0
  758. package/src/features/team-settings/components/settings-section.tsx +23 -0
  759. package/src/features/team-settings/components/team-danger-zone.tsx +275 -0
  760. package/src/features/team-settings/components/team-information-form.tsx +116 -0
  761. package/src/features/team-settings/components/team-invitations-list.tsx +463 -0
  762. package/src/features/team-settings/components/team-members-list.tsx +342 -0
  763. package/src/features/team-settings/components/team-permission-guard.tsx +56 -0
  764. package/src/features/team-settings/components/team-setting-integrations.tsx +27 -0
  765. package/src/features/team-settings/components/team-setting-member.tsx +28 -0
  766. package/src/features/team-settings/components/team-settings-general.tsx +131 -0
  767. package/src/features/team-settings/components/transfer-ownership-modal.tsx +164 -0
  768. package/src/features/team-settings/components/unauthorized-access.tsx +52 -0
  769. package/src/features/team-settings/hooks/__tests__/use-team-settings.test.tsx +139 -0
  770. package/src/features/team-settings/hooks/index.ts +1 -0
  771. package/src/features/team-settings/hooks/use-team-settings.ts +148 -0
  772. package/src/features/team-settings/hooks/use-transfer-ownership.ts +45 -0
  773. package/src/features/team-settings/index.ts +25 -0
  774. package/src/features/team-settings/screens/index.ts +1 -0
  775. package/src/features/team-settings/screens/team-settings-screen.tsx +33 -0
  776. package/src/features/team-settings/types/index.ts +78 -0
  777. package/src/features/team-settings/utils/index.ts +6 -0
  778. package/src/features/team-settings/utils/mock-data.ts +40 -0
  779. package/src/features/teams/api/cancel-invitation.ts +25 -0
  780. package/src/features/teams/api/create-invitation.ts +28 -0
  781. package/src/features/teams/api/create-team.ts +14 -0
  782. package/src/features/teams/api/delete-team.ts +19 -0
  783. package/src/features/teams/api/get-invitations.ts +25 -0
  784. package/src/features/teams/api/get-team-members.ts +25 -0
  785. package/src/features/teams/api/get-team.ts +13 -0
  786. package/src/features/teams/api/get-teams.ts +19 -0
  787. package/src/features/teams/api/index.ts +49 -0
  788. package/src/features/teams/api/leave-team.ts +22 -0
  789. package/src/features/teams/api/remove-member.ts +25 -0
  790. package/src/features/teams/api/resend-invitation.ts +26 -0
  791. package/src/features/teams/api/switch-team.ts +13 -0
  792. package/src/features/teams/api/types.ts +122 -0
  793. package/src/features/teams/api/update-member-roles.ts +28 -0
  794. package/src/features/teams/api/update-team.ts +17 -0
  795. package/src/features/teams/components/create-team-dialog.tsx +105 -0
  796. package/src/features/teams/hooks/__tests__/cache-invalidation.property.test.tsx +268 -0
  797. package/src/features/teams/hooks/index.ts +35 -0
  798. package/src/features/teams/hooks/use-can-manage-members.ts +21 -0
  799. package/src/features/teams/hooks/use-can-manage-team.ts +21 -0
  800. package/src/features/teams/hooks/use-cancel-invitation.ts +52 -0
  801. package/src/features/teams/hooks/use-create-invitation.ts +59 -0
  802. package/src/features/teams/hooks/use-create-team.ts +38 -0
  803. package/src/features/teams/hooks/use-delete-team.ts +43 -0
  804. package/src/features/teams/hooks/use-invitations.ts +31 -0
  805. package/src/features/teams/hooks/use-leave-team.ts +43 -0
  806. package/src/features/teams/hooks/use-remove-member.ts +58 -0
  807. package/src/features/teams/hooks/use-resend-invitation.ts +52 -0
  808. package/src/features/teams/hooks/use-switch-team.ts +41 -0
  809. package/src/features/teams/hooks/use-team-members.ts +31 -0
  810. package/src/features/teams/hooks/use-team-permissions.ts +102 -0
  811. package/src/features/teams/hooks/use-team.ts +30 -0
  812. package/src/features/teams/hooks/use-teams.ts +26 -0
  813. package/src/features/teams/hooks/use-update-member-roles.ts +64 -0
  814. package/src/features/teams/hooks/use-update-team.ts +47 -0
  815. package/src/features/teams/index.ts +111 -0
  816. package/src/features/user-settings/actions/set-password.ts +63 -0
  817. package/src/features/user-settings/api/index.ts +16 -0
  818. package/src/features/user-settings/components/__tests__/security-settings.test.tsx +125 -0
  819. package/src/features/user-settings/components/delete-account-dialog.tsx +185 -0
  820. package/src/features/user-settings/components/index.ts +13 -0
  821. package/src/features/user-settings/components/integrations-list.tsx +152 -0
  822. package/src/features/user-settings/components/notification-preferences.tsx +112 -0
  823. package/src/features/user-settings/components/other-settings.tsx +126 -0
  824. package/src/features/user-settings/components/password-section.tsx +297 -0
  825. package/src/features/user-settings/components/security-settings.tsx +184 -0
  826. package/src/features/user-settings/components/user-preferences.tsx +146 -0
  827. package/src/features/user-settings/hooks/index.ts +8 -0
  828. package/src/features/user-settings/hooks/use-notification-preferences.ts +65 -0
  829. package/src/features/user-settings/hooks/use-user-preferences.ts +52 -0
  830. package/src/features/user-settings/index.ts +22 -0
  831. package/src/features/user-settings/screens/index.ts +11 -0
  832. package/src/features/user-settings/screens/integrations-screen.tsx +24 -0
  833. package/src/features/user-settings/screens/notifications-screen.tsx +29 -0
  834. package/src/features/user-settings/screens/other-settings-screen.tsx +24 -0
  835. package/src/features/user-settings/screens/setting-preferences-screen.tsx +24 -0
  836. package/src/features/user-settings/screens/user-settings-screen.tsx +23 -0
  837. package/src/features/user-settings/types/index.ts +42 -0
  838. package/src/features/user-settings/utils/index.ts +8 -0
  839. package/src/hooks/use-long-press.ts +196 -0
  840. package/src/hooks/use-media-upload.ts +95 -0
  841. package/src/hooks/use-mobile.ts +19 -0
  842. package/src/hooks/use-team.ts +32 -0
  843. package/src/instrumentation.ts +14 -0
  844. package/src/lib/__tests__/auth-config.test.ts +166 -0
  845. package/src/lib/__tests__/config.test.ts +42 -0
  846. package/src/lib/__tests__/db.test.ts +101 -0
  847. package/src/lib/__tests__/env.property.test.ts +197 -0
  848. package/src/lib/__tests__/env.test.ts +177 -0
  849. package/src/lib/__tests__/health-check.test.ts +87 -0
  850. package/src/lib/__tests__/oauth-errors.test.ts +184 -0
  851. package/src/lib/__tests__/oauth-redirect.test.ts +224 -0
  852. package/src/lib/__tests__/oauth-scopes.test.ts +268 -0
  853. package/src/lib/__tests__/storage.test.ts +58 -0
  854. package/src/lib/__tests__/url-validator.test.ts +232 -0
  855. package/src/lib/api-client.ts +93 -0
  856. package/src/lib/auth-client.ts +5 -0
  857. package/src/lib/auth-config.ts +146 -0
  858. package/src/lib/auth.ts +209 -0
  859. package/src/lib/config.ts +228 -0
  860. package/src/lib/cors.ts +96 -0
  861. package/src/lib/date.ts +16 -0
  862. package/src/lib/db.ts +88 -0
  863. package/src/lib/env.ts +489 -0
  864. package/src/lib/feedback.ts +29 -0
  865. package/src/lib/health-check.ts +229 -0
  866. package/src/lib/logger.ts +204 -0
  867. package/src/lib/oauth-errors.ts +138 -0
  868. package/src/lib/performance.ts +367 -0
  869. package/src/lib/query-server.ts +35 -0
  870. package/src/lib/query.tsx +43 -0
  871. package/src/lib/resend.ts +36 -0
  872. package/src/lib/security-headers.ts +165 -0
  873. package/src/lib/setup-status.ts +34 -0
  874. package/src/lib/storage.ts +150 -0
  875. package/src/lib/supabase-client.ts +58 -0
  876. package/src/lib/testing/test-db.ts +75 -0
  877. package/src/lib/url-validator.ts +168 -0
  878. package/src/lib/utils.ts +6 -0
  879. package/src/mocks/README.md +42 -0
  880. package/src/mocks/activity.fixtures.ts +281 -0
  881. package/src/mocks/annotation.fixtures.ts +325 -0
  882. package/src/mocks/attachment.fixtures.ts +80 -0
  883. package/src/mocks/email.fixtures.ts +61 -0
  884. package/src/mocks/index.ts +33 -0
  885. package/src/mocks/issue.fixtures.ts +364 -0
  886. package/src/mocks/landing.fixtures.ts +118 -0
  887. package/src/mocks/notification.fixtures.ts +111 -0
  888. package/src/mocks/project-activity.fixtures.ts +69 -0
  889. package/src/mocks/project-invitation.fixtures.ts +95 -0
  890. package/src/mocks/project-member.fixtures.ts +93 -0
  891. package/src/mocks/project.fixtures.ts +249 -0
  892. package/src/mocks/settings.fixtures.ts +56 -0
  893. package/src/mocks/share.fixtures.ts +48 -0
  894. package/src/mocks/team-member.fixtures.ts +147 -0
  895. package/src/mocks/team.fixtures.ts +35 -0
  896. package/src/mocks/user-settings.fixtures.ts +77 -0
  897. package/src/mocks/user.fixtures.ts +21 -0
  898. package/src/providers/theme-provider.tsx +11 -0
  899. package/src/proxy/__tests__/proxy-setup-gate.test.ts +43 -0
  900. package/src/proxy.ts +169 -0
  901. package/src/server/annotations/__tests__/annotation-limit.property.test.ts +291 -0
  902. package/src/server/annotations/__tests__/attachment-deletion-cascade.property.test.ts +385 -0
  903. package/src/server/annotations/__tests__/comment-delete-authorization.property.test.ts +419 -0
  904. package/src/server/annotations/__tests__/sanitize.property.test.ts +302 -0
  905. package/src/server/annotations/annotation-service.ts +305 -0
  906. package/src/server/annotations/comment-service.ts +288 -0
  907. package/src/server/annotations/index.ts +61 -0
  908. package/src/server/annotations/permission-utils.ts +125 -0
  909. package/src/server/annotations/sanitize.ts +134 -0
  910. package/src/server/annotations/types.ts +161 -0
  911. package/src/server/audit/audit-service.ts +85 -0
  912. package/src/server/audit/index.ts +11 -0
  913. package/src/server/audit/types.ts +75 -0
  914. package/src/server/auth/__tests__/README.md +368 -0
  915. package/src/server/auth/__tests__/account-linking.integration.test.ts +410 -0
  916. package/src/server/auth/__tests__/auth-integration.test.ts +811 -0
  917. package/src/server/auth/__tests__/cookies.test.ts +337 -0
  918. package/src/server/auth/__tests__/login.property.test.ts +428 -0
  919. package/src/server/auth/__tests__/oauth-integration.test.ts +555 -0
  920. package/src/server/auth/__tests__/password.test.ts +194 -0
  921. package/src/server/auth/__tests__/rate-limiter.test.ts +450 -0
  922. package/src/server/auth/__tests__/rbac.test.ts +474 -0
  923. package/src/server/auth/__tests__/session.test.ts +599 -0
  924. package/src/server/auth/__tests__/signup.property.test.ts +224 -0
  925. package/src/server/auth/__tests__/token-encryption.test.ts +171 -0
  926. package/src/server/auth/__tests__/tokens.test.ts +476 -0
  927. package/src/server/auth/__tests__/verify-email.property.test.ts +372 -0
  928. package/src/server/auth/cookies.ts +184 -0
  929. package/src/server/auth/password.ts +94 -0
  930. package/src/server/auth/rate-limiter.ts +257 -0
  931. package/src/server/auth/rbac.ts +1168 -0
  932. package/src/server/auth/session.ts +392 -0
  933. package/src/server/auth/token-encryption.ts +201 -0
  934. package/src/server/auth/tokens.ts +397 -0
  935. package/src/server/db/schema/account.ts +21 -0
  936. package/src/server/db/schema/annotation-read-status.ts +57 -0
  937. package/src/server/db/schema/better-auth-verifications.ts +27 -0
  938. package/src/server/db/schema/email-jobs.ts +24 -0
  939. package/src/server/db/schema/index.ts +20 -0
  940. package/src/server/db/schema/instance-settings.ts +42 -0
  941. package/src/server/db/schema/issue-activities.ts +97 -0
  942. package/src/server/db/schema/issue-attachments.ts +101 -0
  943. package/src/server/db/schema/issues.ts +139 -0
  944. package/src/server/db/schema/notifications.ts +119 -0
  945. package/src/server/db/schema/project-activities.ts +116 -0
  946. package/src/server/db/schema/project-invitations.ts +34 -0
  947. package/src/server/db/schema/project-members.ts +29 -0
  948. package/src/server/db/schema/projects.ts +46 -0
  949. package/src/server/db/schema/sessions.ts +17 -0
  950. package/src/server/db/schema/team-invitations.ts +22 -0
  951. package/src/server/db/schema/team-members.ts +18 -0
  952. package/src/server/db/schema/teams.ts +15 -0
  953. package/src/server/db/schema/user-roles.ts +14 -0
  954. package/src/server/db/schema/users.ts +17 -0
  955. package/src/server/db/schema/verification-tokens.ts +15 -0
  956. package/src/server/email/README.md +258 -0
  957. package/src/server/email/__tests__/client.property.test.ts +218 -0
  958. package/src/server/email/__tests__/payload.property.test.ts +205 -0
  959. package/src/server/email/__tests__/queue.test.ts +407 -0
  960. package/src/server/email/__tests__/render-template.test.tsx +172 -0
  961. package/src/server/email/client.ts +70 -0
  962. package/src/server/email/index.ts +20 -0
  963. package/src/server/email/providers/console-provider.ts +43 -0
  964. package/src/server/email/providers/index.ts +5 -0
  965. package/src/server/email/providers/resend-provider.ts +59 -0
  966. package/src/server/email/providers/smtp-provider.ts +65 -0
  967. package/src/server/email/queue.ts +365 -0
  968. package/src/server/email/render-template.tsx +117 -0
  969. package/src/server/email/templates/layout.tsx +66 -0
  970. package/src/server/email/templates/ownership-transfer-email.tsx +75 -0
  971. package/src/server/email/templates/password-reset-email.tsx +72 -0
  972. package/src/server/email/templates/project-invitation-email.tsx +70 -0
  973. package/src/server/email/templates/security-alert-email.tsx +161 -0
  974. package/src/server/email/templates/team-invitation-email.tsx +68 -0
  975. package/src/server/email/templates/verification-email.tsx +61 -0
  976. package/src/server/email/templates/welcome-email.tsx +60 -0
  977. package/src/server/email/worker.ts +182 -0
  978. package/src/server/issues/activity-service.ts +422 -0
  979. package/src/server/issues/attachment-service.ts +379 -0
  980. package/src/server/issues/index.ts +68 -0
  981. package/src/server/issues/issue-service.ts +569 -0
  982. package/src/server/issues/types.ts +233 -0
  983. package/src/server/notifications/__tests__/notification-service.integration.test.ts +405 -0
  984. package/src/server/notifications/index.ts +13 -0
  985. package/src/server/notifications/notification-service.ts +526 -0
  986. package/src/server/notifications/types.ts +234 -0
  987. package/src/server/projects/__tests__/activity-logging.integration.test.ts +319 -0
  988. package/src/server/projects/__tests__/invitation-email.integration.test.ts +258 -0
  989. package/src/server/projects/__tests__/invitation-service.integration.test.ts +651 -0
  990. package/src/server/projects/__tests__/member-service.property.test.ts +397 -0
  991. package/src/server/projects/__tests__/project-service.property.test.ts +116 -0
  992. package/src/server/projects/activity-service.ts +548 -0
  993. package/src/server/projects/index.ts +11 -0
  994. package/src/server/projects/invitation-service.ts +773 -0
  995. package/src/server/projects/member-service.ts +458 -0
  996. package/src/server/projects/project-service.ts +491 -0
  997. package/src/server/projects/schemas.ts +310 -0
  998. package/src/server/projects/types.ts +166 -0
  999. package/src/server/projects/utils.ts +128 -0
  1000. package/src/server/setup/__tests__/health-check.property.test.ts +70 -0
  1001. package/src/server/setup/__tests__/sample-data.property.test.ts +82 -0
  1002. package/src/server/setup/__tests__/setup.property.test.ts +95 -0
  1003. package/src/server/setup/health-check-service.ts +294 -0
  1004. package/src/server/setup/index.ts +35 -0
  1005. package/src/server/setup/sample-data-service.ts +233 -0
  1006. package/src/server/setup/setup-service.ts +229 -0
  1007. package/src/server/setup/types.ts +96 -0
  1008. package/src/server/teams/__tests__/export.property.test.ts +542 -0
  1009. package/src/server/teams/__tests__/get-members.integration.test.ts +105 -0
  1010. package/src/server/teams/__tests__/invitation-flow.integration.test.ts +402 -0
  1011. package/src/server/teams/__tests__/invitations.property.test.ts +235 -0
  1012. package/src/server/teams/__tests__/member-management-flow.integration.test.ts +306 -0
  1013. package/src/server/teams/__tests__/members.property.test.ts +180 -0
  1014. package/src/server/teams/__tests__/ownership-transfer.property.test.ts +173 -0
  1015. package/src/server/teams/__tests__/resource-limits.property.test.ts +382 -0
  1016. package/src/server/teams/__tests__/team-context-management.integration.test.ts +396 -0
  1017. package/src/server/teams/__tests__/team-context.property.test.ts +854 -0
  1018. package/src/server/teams/__tests__/team-creation-flow.integration.test.ts +310 -0
  1019. package/src/server/teams/__tests__/team-creation.property.test.ts +280 -0
  1020. package/src/server/teams/errors.ts +396 -0
  1021. package/src/server/teams/export-service.ts +383 -0
  1022. package/src/server/teams/index.ts +10 -0
  1023. package/src/server/teams/invitation-service.ts +708 -0
  1024. package/src/server/teams/member-service.ts +334 -0
  1025. package/src/server/teams/resource-limits.ts +211 -0
  1026. package/src/server/teams/slug.ts +58 -0
  1027. package/src/server/teams/team-context.ts +648 -0
  1028. package/src/server/teams/team-service.ts +660 -0
  1029. package/src/server/teams/types.ts +81 -0
  1030. package/src/server/teams/validation.ts +209 -0
  1031. package/src/styles/globals.css +160 -0
  1032. package/src/types/deployment.ts +39 -0
  1033. package/supabase/config.toml +357 -0
  1034. package/supabase/seed.sql +480 -0
  1035. package/tests/e2e/.gitkeep +0 -0
  1036. package/tests/e2e/QUICK_START.md +98 -0
  1037. package/tests/e2e/README.md +301 -0
  1038. package/tests/e2e/auth.spec.ts +583 -0
  1039. package/tests/e2e/global-setup.ts +23 -0
  1040. package/tests/e2e/global-teardown.ts +23 -0
  1041. package/tests/e2e/helpers/auth-helpers.ts +310 -0
  1042. package/tests/e2e/helpers/test-fixtures.ts +286 -0
  1043. package/tests/e2e/smoke-test.spec.ts +330 -0
  1044. package/tsconfig.json +48 -0
  1045. package/vitest.config.ts +50 -0
  1046. package/vitest.setup.ts +56 -0
  1047. package/dist/index.js +0 -778
@@ -0,0 +1,1132 @@
1
+ # Role-Based Access Control (RBAC) Documentation
2
+
3
+ ## Overview
4
+
5
+ UI SyncUp uses a comprehensive Role-Based Access Control (RBAC) system to manage user permissions across teams and projects. This document explains the role hierarchy, permissions model, and how to use the RBAC utilities in your code.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Role Hierarchy](#role-hierarchy)
10
+ - [Architecture](#architecture)
11
+ - [Permissions Model](#permissions-model)
12
+ - [Usage Examples](#usage-examples)
13
+ - [API Reference](#api-reference)
14
+ - [Best Practices](#best-practices)
15
+ - [Security Considerations](#security-considerations)
16
+
17
+ ---
18
+
19
+ ## Architecture
20
+
21
+ ### Role Storage (Single Source of Truth)
22
+
23
+ UI SyncUp uses a **consolidated role storage** pattern where each resource type has a single source of truth:
24
+
25
+ | Resource Type | Table | Columns |
26
+ |---------------|-------|---------|
27
+ | **Team** | `team_members` | `managementRole`, `operationalRole` |
28
+ | **Project** | `project_members` | `role` |
29
+
30
+ This ensures:
31
+ - ✅ No data inconsistency between tables
32
+ - ✅ Single write location for role changes
33
+ - ✅ Simpler permission queries
34
+ - ✅ Clear ownership of role data
35
+
36
+ ### Permission Resolution
37
+
38
+ ```
39
+ hasPermission(userId, permission, resourceType, resourceId)
40
+
41
+ ├── resourceType = "project"
42
+ │ └── Query project_members → Check role permissions
43
+
44
+ └── resourceType = "team"
45
+ └── Query team_members → Check management + operational role permissions
46
+ ```
47
+
48
+
49
+ ## Role Hierarchy
50
+
51
+ ### Team Roles (Two-Tier Hierarchy)
52
+
53
+ Team roles are split into **management roles** (control team settings) and **operational roles** (determine content access).
54
+
55
+ #### Management Roles
56
+
57
+ | Role | Description |
58
+ |------|-------------|
59
+ | **TEAM_OWNER** | Full control over team and members. Can transfer ownership and delete team. Must also have an operational role. |
60
+ | **TEAM_ADMIN** | Manage team members, projects, and integrations. Cannot delete team or transfer ownership. Must also have an operational role. |
61
+
62
+ #### Operational Roles (Determine Access)
63
+
64
+ | Role | Level | Description |
65
+ |------|-------|-------------|
66
+ | **TEAM_EDITOR** | 3 | Create and manage issues and annotations. Automatically assigned when user becomes PROJECT_OWNER or PROJECT_EDITOR. |
67
+ | **TEAM_MEMBER** | 2 | View projects and comment on issues. Can be assigned to projects. |
68
+ | **TEAM_VIEWER** | 1 | View-only access to projects and issues. No modifications. |
69
+
70
+ #### Role Combinations
71
+
72
+ Users have **one management role** (optional) + **one operational role** (required):
73
+
74
+ - `TEAM_OWNER` + `TEAM_EDITOR` → Owner who creates issues
75
+ - `TEAM_OWNER` + `TEAM_MEMBER` → Owner who only manages
76
+ - `TEAM_ADMIN` + `TEAM_VIEWER` → Admin with read-only
77
+ - `TEAM_EDITOR` (no management) → Designer/QA
78
+ - `TEAM_MEMBER` (no management) → Developer
79
+
80
+ ### Project Roles
81
+
82
+ Use project roles to define permissions for specific projects.
83
+
84
+ | Role | Level | Description |
85
+ |------|-------|-------------|
86
+ | **PROJECT_OWNER** | 4 | Full control over project and its issues. Can manage project members. |
87
+ | **PROJECT_EDITOR** | 3 | Create and manage issues and annotations. Cannot manage project settings. |
88
+ | **PROJECT_DEVELOPER** | 2 | Update issue status and comment. Typical developer workflow. |
89
+ | **PROJECT_VIEWER** | 1 | View-only access to project and issues. No modifications. |
90
+
91
+ ### Role Hierarchy Rules
92
+
93
+ 1. **Management roles are separate from operational roles** - TEAM_OWNER/ADMIN control settings, operational roles control content access
94
+ 2. **Users must have both a management role AND an operational role** if they need both capabilities
95
+
96
+ 4. **Higher operational roles inherit lower role permissions** (EDITOR > MEMBER > VIEWER)
97
+ 5. **Team roles do not automatically grant project roles** - users must be explicitly assigned to projects
98
+ 6. **Project roles only apply to that specific project** - they don't grant access to other projects
99
+ 7. **TEAM_OWNER and TEAM_ADMIN can access team settings** regardless of their operational role
100
+
101
+ ---
102
+
103
+ ## Permissions Model
104
+
105
+ ### Permission Categories
106
+
107
+ Permissions are organized into four categories:
108
+
109
+ 1. **Team Permissions** - Control team-level operations
110
+ 2. **Project Permissions** - Control project-level operations
111
+ 3. **Issue Permissions** - Control issue management
112
+ 4. **Annotation Permissions** - Control annotation management
113
+
114
+ ### Team Permissions
115
+
116
+ | Permission | Description | Roles |
117
+ |------------|-------------|-------|
118
+ | `team:view` | View team details and members | All team roles |
119
+ | `team:update` | Update team settings | OWNER, ADMIN |
120
+ | `team:delete` | Delete the team | OWNER only |
121
+ | `team:manage_members` | Add/remove team members | OWNER, ADMIN |
122
+
123
+ | `team:manage_settings` | Manage team settings | OWNER, ADMIN |
124
+ | `team:transfer_ownership` | Transfer team ownership | OWNER only |
125
+
126
+ ### Project Permissions
127
+
128
+ | Permission | Description | Roles |
129
+ |------------|-------------|-------|
130
+ | `project:view` | View project details | All roles |
131
+ | `project:create` | Create new projects | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR |
132
+ | `project:update` | Update project settings | TEAM_OWNER, TEAM_ADMIN, PROJECT_OWNER |
133
+ | `project:delete` | Delete the project | TEAM_OWNER, TEAM_ADMIN, PROJECT_OWNER |
134
+ | `project:manage_members` | Add/remove project members | TEAM_OWNER, TEAM_ADMIN, PROJECT_OWNER |
135
+ | `project:manage_settings` | Manage project settings | TEAM_OWNER, TEAM_ADMIN, PROJECT_OWNER |
136
+
137
+ ### Issue Permissions
138
+
139
+ | Permission | Description | Roles |
140
+ |------------|-------------|-------|
141
+ | `issue:view` | View issues | All roles |
142
+ | `issue:create` | Create new issues | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR, PROJECT_OWNER, PROJECT_EDITOR |
143
+ | `issue:update` | Update issue details and status | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR, PROJECT_OWNER, PROJECT_EDITOR, PROJECT_DEVELOPER |
144
+ | `issue:delete` | Delete issues | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR, PROJECT_OWNER, PROJECT_EDITOR |
145
+ | `issue:assign` | Assign issues to users | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR, PROJECT_OWNER, PROJECT_EDITOR |
146
+ | `issue:comment` | Comment on issues | All roles except VIEWER |
147
+
148
+ ### Annotation Permissions
149
+
150
+ | Permission | Description | Roles |
151
+ |------------|-------------|-------|
152
+ | `annotation:view` | View annotations | All roles |
153
+ | `annotation:create` | Create new annotations | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR, PROJECT_OWNER, PROJECT_EDITOR |
154
+ | `annotation:update` | Update annotations | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR, PROJECT_OWNER, PROJECT_EDITOR |
155
+ | `annotation:delete` | Delete annotations | TEAM_OWNER, TEAM_ADMIN, TEAM_EDITOR, PROJECT_OWNER, PROJECT_EDITOR |
156
+ | `annotation:comment` | Comment on annotations | All roles except VIEWER |
157
+
158
+ ---
159
+
160
+
161
+
162
+ ---
163
+
164
+ ## Usage Examples
165
+
166
+ ### Assigning Roles
167
+
168
+ ```typescript
169
+ import { assignRole, TEAM_ROLES, PROJECT_ROLES } from '@/server/auth/rbac';
170
+
171
+ // Assign team owner role
172
+ await assignRole({
173
+ userId: 'user_123',
174
+ role: TEAM_ROLES.TEAM_OWNER,
175
+ resourceType: 'team',
176
+ resourceId: 'team_456',
177
+ });
178
+
179
+ // Assign project editor role
180
+ await assignRole({
181
+ userId: 'user_789',
182
+ role: PROJECT_ROLES.PROJECT_EDITOR,
183
+ resourceType: 'project',
184
+ resourceId: 'project_abc',
185
+ });
186
+
187
+ // Assign multiple roles at once (transactional)
188
+ await assignRoles([
189
+ {
190
+ userId: 'user_123',
191
+ role: TEAM_ROLES.TEAM_OWNER,
192
+ resourceType: 'team',
193
+ resourceId: 'team_456',
194
+ },
195
+ {
196
+ userId: 'user_123',
197
+ role: PROJECT_ROLES.PROJECT_OWNER,
198
+ resourceType: 'project',
199
+ resourceId: 'project_abc',
200
+ },
201
+ ]);
202
+ ```
203
+
204
+ ### Checking Permissions
205
+
206
+ ```typescript
207
+ import { hasPermission, PERMISSIONS } from '@/server/auth/rbac';
208
+
209
+ // Check if user can create issues in a project
210
+ const canCreate = await hasPermission({
211
+ userId: 'user_123',
212
+ permission: PERMISSIONS.ISSUE_CREATE,
213
+ resourceId: 'project_456',
214
+ resourceType: 'project',
215
+ });
216
+
217
+ if (canCreate) {
218
+ // Allow issue creation
219
+ } else {
220
+ // Show error message
221
+ }
222
+
223
+ // Check multiple permissions
224
+ import { hasAllPermissions, hasAnyPermission } from '@/server/auth/rbac';
225
+
226
+ // User must have ALL permissions
227
+ const canManageProject = await hasAllPermissions(
228
+ 'user_123',
229
+ [PERMISSIONS.PROJECT_UPDATE, PERMISSIONS.PROJECT_MANAGE_MEMBERS],
230
+ 'project_456',
231
+ 'project'
232
+ );
233
+
234
+ // User must have ANY permission
235
+ const canInteract = await hasAnyPermission(
236
+ 'user_123',
237
+ [PERMISSIONS.ISSUE_CREATE, PERMISSIONS.ISSUE_COMMENT],
238
+ 'project_456',
239
+ 'project'
240
+ );
241
+ ```
242
+
243
+ ### Requiring Permissions (Guards)
244
+
245
+ ```typescript
246
+ import { requirePermission, requireRole } from '@/server/auth/rbac';
247
+
248
+ // In API route handler
249
+ export async function POST(request: Request) {
250
+ const session = await getSession();
251
+ const { projectId } = await request.json();
252
+
253
+ // Throw error if user doesn't have permission
254
+ await requirePermission({
255
+ userId: session.userId,
256
+ permission: PERMISSIONS.ISSUE_CREATE,
257
+ resourceId: projectId,
258
+ resourceType: 'project',
259
+ });
260
+
261
+ // Continue with issue creation...
262
+ }
263
+
264
+ // Require specific role
265
+ await requireRole(
266
+ session.userId,
267
+ TEAM_ROLES.TEAM_ADMIN,
268
+ 'team',
269
+ teamId
270
+ );
271
+ ```
272
+
273
+ ### Querying User Roles
274
+
275
+ ```typescript
276
+ import {
277
+ getUserRoles,
278
+ getUserTeamRoles,
279
+ getUserProjectRoles,
280
+ getHighestTeamRole,
281
+ getHighestProjectRole,
282
+ } from '@/server/auth/rbac';
283
+
284
+ // Get all roles for a user
285
+ const allRoles = await getUserRoles('user_123');
286
+
287
+ // Get team roles
288
+ const teamRoles = await getUserTeamRoles('user_123', 'team_456');
289
+
290
+ // Get project roles
291
+ const projectRoles = await getUserProjectRoles('user_123', 'project_789');
292
+
293
+ // Get highest role (for display purposes)
294
+ const highestTeamRole = await getHighestTeamRole('user_123', 'team_456');
295
+ // Returns: 'TEAM_OWNER' | 'TEAM_ADMIN' | ... | null
296
+
297
+ const highestProjectRole = await getHighestProjectRole('user_123', 'project_789');
298
+ // Returns: 'PROJECT_OWNER' | 'PROJECT_EDITOR' | ... | null
299
+ ```
300
+
301
+
302
+
303
+ ### Updating Roles
304
+
305
+ ```typescript
306
+ import { updateRole, removeRole, demoteWithOwnershipTransfer, getOwnedProjects } from '@/server/auth/rbac';
307
+
308
+ // Upgrade user's role (always safe)
309
+ await updateRole(
310
+ 'user_123',
311
+ TEAM_ROLES.TEAM_MEMBER, // old role
312
+ TEAM_ROLES.TEAM_EDITOR, // new role
313
+ 'team',
314
+ 'team_456'
315
+ );
316
+
317
+ // Demote user (may fail if they're PROJECT_OWNER)
318
+ try {
319
+ await updateRole(
320
+ 'user_123',
321
+ TEAM_ROLES.TEAM_EDITOR, // old role
322
+ TEAM_ROLES.TEAM_VIEWER, // new role
323
+ 'team',
324
+ 'team_456'
325
+ );
326
+ } catch (error) {
327
+ if (error.message.includes('DEMOTION_BLOCKED')) {
328
+ // User is PROJECT_OWNER, need to transfer ownership first
329
+ const ownedProjects = await getOwnedProjects('user_123');
330
+ console.log('User owns projects:', ownedProjects);
331
+ // Show UI to select new owners
332
+ }
333
+ }
334
+
335
+ // Safe demotion with ownership transfer
336
+ await demoteWithOwnershipTransfer(
337
+ 'user_123',
338
+ 'team_456',
339
+ 'TEAM_VIEWER',
340
+ {
341
+ 'project_1': 'user_789', // Transfer project_1 to user_789
342
+ 'project_2': 'user_789', // Transfer project_2 to user_789
343
+ }
344
+ );
345
+
346
+ // Remove a role
347
+ await removeRole({
348
+ userId: 'user_123',
349
+ role: PROJECT_ROLES.PROJECT_EDITOR,
350
+ resourceType: 'project',
351
+ resourceId: 'project_789',
352
+ });
353
+ ```
354
+
355
+ ---
356
+
357
+ ## API Reference
358
+
359
+ ### Role Assignment Functions
360
+
361
+ #### `assignRole(assignment: RoleAssignment): Promise<UserRole>`
362
+
363
+ Assign a role to a user for a specific resource.
364
+
365
+ **Parameters:**
366
+ - `assignment.userId` - User ID
367
+ - `assignment.role` - Role to assign (from `TEAM_ROLES` or `PROJECT_ROLES`)
368
+ - `assignment.resourceType` - Resource type (`'team'` or `'project'`)
369
+ - `assignment.resourceId` - Resource ID
370
+
371
+ **Returns:** Created user role record
372
+
373
+ **Throws:** Error if role is invalid or doesn't match resource type
374
+
375
+ ---
376
+
377
+ #### `assignRoles(assignments: RoleAssignment[]): Promise<UserRole[]>`
378
+
379
+ Assign multiple roles to a user at once (transactional).
380
+
381
+ **Parameters:**
382
+ - `assignments` - Array of role assignments
383
+
384
+ **Returns:** Array of created user role records
385
+
386
+ ---
387
+
388
+ #### `removeRole(assignment: RoleAssignment): Promise<boolean>`
389
+
390
+ Remove a role from a user.
391
+
392
+ **Parameters:**
393
+ - `assignment` - Role assignment to remove
394
+
395
+ **Returns:** `true` if role was removed, `false` if it didn't exist
396
+
397
+ ---
398
+
399
+ #### `updateRole(userId, oldRole, newRole, resourceType, resourceId): Promise<void>`
400
+
401
+ Update a user's role for a resource (atomic operation).
402
+
403
+ **Parameters:**
404
+ - `userId` - User ID
405
+ - `oldRole` - Current role to remove
406
+ - `newRole` - New role to assign
407
+ - `resourceType` - Resource type
408
+ - `resourceId` - Resource ID
409
+
410
+ ---
411
+
412
+ ### Role Query Functions
413
+
414
+ #### `getUserRoles(userId: string): Promise<UserRole[]>`
415
+
416
+ Get all roles for a user across all resources.
417
+
418
+ ---
419
+
420
+ #### `getUserTeamRoles(userId: string, teamId: string): Promise<UserRole[]>`
421
+
422
+ Get all team roles for a user in a specific team.
423
+
424
+ ---
425
+
426
+ #### `getUserProjectRoles(userId: string, projectId: string): Promise<UserRole[]>`
427
+
428
+ Get all project roles for a user in a specific project.
429
+
430
+ ---
431
+
432
+ #### `getHighestTeamRole(userId: string, teamId: string): Promise<TeamRole | null>`
433
+
434
+ Get the highest team role for a user in a team (based on hierarchy).
435
+
436
+ ---
437
+
438
+ #### `getHighestProjectRole(userId: string, projectId: string): Promise<ProjectRole | null>`
439
+
440
+ Get the highest project role for a user in a project (based on hierarchy).
441
+
442
+ ---
443
+
444
+ #### `hasRole(userId, role, resourceType, resourceId): Promise<boolean>`
445
+
446
+ Check if a user has a specific role.
447
+
448
+ ---
449
+
450
+ ### Permission Check Functions
451
+
452
+ #### `hasPermission(check: PermissionCheck): Promise<boolean>`
453
+
454
+ Check if a user has a specific permission for a resource.
455
+
456
+ **Parameters:**
457
+ - `check.userId` - User ID
458
+ - `check.permission` - Permission to check (from `PERMISSIONS`)
459
+ - `check.resourceId` - Resource ID
460
+ - `check.resourceType` - Resource type (optional)
461
+
462
+ **Returns:** `true` if user has the permission
463
+
464
+ **Implementation Details:**
465
+ - For team resources, this function checks **both** the `user_roles` table and the `team_members` table
466
+ - This ensures team roles stored in `team_members` (e.g., from team creation) are correctly recognized
467
+ - The function checks both management roles (`TEAM_OWNER`, `TEAM_ADMIN`) and operational roles (`TEAM_EDITOR`, `TEAM_MEMBER`, `TEAM_VIEWER`)
468
+
469
+
470
+ ---
471
+
472
+ #### `hasAnyPermission(userId, permissions, resourceId, resourceType?): Promise<boolean>`
473
+
474
+ Check if a user has any of the specified permissions.
475
+
476
+ ---
477
+
478
+ #### `hasAllPermissions(userId, permissions, resourceId, resourceType?): Promise<boolean>`
479
+
480
+ Check if a user has all of the specified permissions.
481
+
482
+ ---
483
+
484
+ #### `getUserPermissions(userId, resourceId, resourceType?): Promise<Permission[]>`
485
+
486
+ Get all permissions for a user in a resource (deduplicated).
487
+
488
+ ---
489
+
490
+ ### Authorization Guard Functions
491
+
492
+ #### `requirePermission(check: PermissionCheck): Promise<void>`
493
+
494
+ Require a user to have a specific permission, or throw an error.
495
+
496
+ **Throws:** Error if user doesn't have the permission
497
+
498
+ ---
499
+
500
+ #### `requireRole(userId, role, resourceType, resourceId): Promise<void>`
501
+
502
+ Require a user to have a specific role, or throw an error.
503
+
504
+ **Throws:** Error if user doesn't have the role
505
+
506
+ ---
507
+
508
+
509
+
510
+ ### Project Ownership Functions
511
+
512
+ #### `getOwnedProjects(userId: string): Promise<string[]>`
513
+
514
+ Get all projects where a user is PROJECT_OWNER.
515
+
516
+ **Returns:** Array of project IDs
517
+
518
+ **Use case:** Check before demoting a user from TEAM_EDITOR
519
+
520
+ ---
521
+
522
+ #### `demoteWithOwnershipTransfer(userId, teamId, newOperationalRole, projectOwnershipTransfers): Promise<void>`
523
+
524
+ Safely demote a user from TEAM_EDITOR while transferring their project ownerships.
525
+
526
+ **Parameters:**
527
+ - `userId` - User ID to demote
528
+ - `teamId` - Team ID
529
+ - `newOperationalRole` - New role (`'TEAM_VIEWER'` or `'TEAM_MEMBER'`)
530
+ - `projectOwnershipTransfers` - Map of `projectId -> newOwnerId`
531
+
532
+ **Throws:** Error if any owned project is missing a transfer target
533
+
534
+ **Example:**
535
+ ```typescript
536
+ await demoteWithOwnershipTransfer(
537
+ 'user_123',
538
+ 'team_456',
539
+ 'TEAM_VIEWER',
540
+ {
541
+ 'project_1': 'user_789',
542
+ 'project_2': 'user_789',
543
+ }
544
+ );
545
+ ```
546
+
547
+ ---
548
+
549
+ ## Best Practices
550
+
551
+ ### 1. Always Use Server-Side Checks
552
+
553
+ **❌ Don't rely on client-side role checks for security:**
554
+
555
+ ```typescript
556
+ // BAD: Client-side only
557
+ 'use client';
558
+ export function DeleteButton() {
559
+ const { user } = useSession();
560
+ if (user.role !== 'TEAM_OWNER') return null;
561
+ return <button onClick={deleteTeam}>Delete</button>;
562
+ }
563
+ ```
564
+
565
+ **✅ Always enforce permissions on the server:**
566
+
567
+ ```typescript
568
+ // GOOD: Server-side enforcement
569
+ export async function DELETE(request: Request) {
570
+ const session = await getSession();
571
+
572
+ await requirePermission({
573
+ userId: session.userId,
574
+ permission: PERMISSIONS.TEAM_DELETE,
575
+ resourceId: teamId,
576
+ resourceType: 'team',
577
+ });
578
+
579
+ // Proceed with deletion
580
+ }
581
+ ```
582
+
583
+ ### 2. Use Permission Checks, Not Role Checks
584
+
585
+ **❌ Don't check roles directly in business logic:**
586
+
587
+ ```typescript
588
+ // BAD: Tightly coupled to roles
589
+ if (userRole === 'TEAM_OWNER' || userRole === 'TEAM_ADMIN') {
590
+ // Allow action
591
+ }
592
+ ```
593
+
594
+ **✅ Check permissions instead:**
595
+
596
+ ```typescript
597
+ // GOOD: Flexible and maintainable
598
+ const canManage = await hasPermission({
599
+ userId,
600
+ permission: PERMISSIONS.TEAM_MANAGE_MEMBERS,
601
+ resourceId: teamId,
602
+ resourceType: 'team',
603
+ });
604
+
605
+ if (canManage) {
606
+ // Allow action
607
+ }
608
+ ```
609
+
610
+ ### 3. Use Guards for API Routes
611
+
612
+ **✅ Use `requirePermission` for cleaner API routes:**
613
+
614
+ ```typescript
615
+ export async function POST(request: Request) {
616
+ const session = await getSession();
617
+ const { projectId, title, description } = await request.json();
618
+
619
+ // Guard: throws error if permission denied
620
+ await requirePermission({
621
+ userId: session.userId,
622
+ permission: PERMISSIONS.ISSUE_CREATE,
623
+ resourceId: projectId,
624
+ resourceType: 'project',
625
+ });
626
+
627
+ // Continue with issue creation
628
+ const issue = await createIssue({ projectId, title, description });
629
+ return Response.json(issue);
630
+ }
631
+ ```
632
+
633
+ ### 4. Batch Role Assignments
634
+
635
+ **✅ Use `assignRoles` for multiple assignments:**
636
+
637
+ ```typescript
638
+ // GOOD: Single transaction
639
+ await assignRoles([
640
+ { userId, role: TEAM_ROLES.TEAM_OWNER, resourceType: 'team', resourceId: teamId },
641
+ { userId, role: PROJECT_ROLES.PROJECT_OWNER, resourceType: 'project', resourceId: projectId },
642
+ ]);
643
+
644
+ // BAD: Multiple transactions
645
+ await assignRole({ userId, role: TEAM_ROLES.TEAM_OWNER, resourceType: 'team', resourceId: teamId });
646
+ await assignRole({ userId, role: PROJECT_ROLES.PROJECT_OWNER, resourceType: 'project', resourceId: projectId });
647
+ ```
648
+
649
+
650
+
651
+ ### 6. Log Permission Denials
652
+
653
+ **✅ The RBAC utilities automatically log permission denials:**
654
+
655
+ ```typescript
656
+ // Logs are automatically created when permissions are denied
657
+ await requirePermission({
658
+ userId: session.userId,
659
+ permission: PERMISSIONS.TEAM_DELETE,
660
+ resourceId: teamId,
661
+ resourceType: 'team',
662
+ });
663
+ // If denied, logs: rbac.permission_denied with context
664
+ ```
665
+
666
+ ### 7. Handle PROJECT_OWNER Demotion Edge Case
667
+
668
+ **✅ Always check for project ownership before demoting:**
669
+
670
+ ```typescript
671
+ // BAD: Direct demotion without checking
672
+ await updateRole(userId, 'TEAM_EDITOR', 'TEAM_VIEWER', 'team', teamId);
673
+ // May fail if user is PROJECT_OWNER
674
+
675
+ // GOOD: Check first, then handle appropriately
676
+ const ownedProjects = await getOwnedProjects(userId);
677
+
678
+ if (ownedProjects.length > 0) {
679
+ // Show UI to transfer ownership
680
+ return {
681
+ error: 'OWNERSHIP_TRANSFER_REQUIRED',
682
+ projects: ownedProjects,
683
+ message: `User owns ${ownedProjects.length} project(s). Transfer ownership first.`,
684
+ };
685
+ }
686
+
687
+ // Safe to demote
688
+ await updateRole(userId, 'TEAM_EDITOR', 'TEAM_VIEWER', 'team', teamId);
689
+
690
+ // Or use the safe helper
691
+ await demoteWithOwnershipTransfer(userId, teamId, 'TEAM_VIEWER', {
692
+ 'project_1': newOwnerId,
693
+ 'project_2': newOwnerId,
694
+ });
695
+ ```
696
+
697
+ ---
698
+
699
+ ## Security Considerations
700
+
701
+ ### 1. Never Trust Client Input
702
+
703
+ Always validate user permissions on the server, even if the client UI hides certain actions.
704
+
705
+ ### 2. Use Transactions for Role Changes
706
+
707
+ When changing roles that affect quotas, use transactions to ensure consistency:
708
+
709
+ ```typescript
710
+ await db.transaction(async (tx) => {
711
+ await removeRole({ userId, role: oldRole, resourceType, resourceId });
712
+ await assignRole({ userId, role: newRole, resourceType, resourceId });
713
+ });
714
+ ```
715
+
716
+ ### 3. Audit Role Changes
717
+
718
+ All role assignments and removals are automatically logged with structured logging:
719
+
720
+ ```typescript
721
+ // Logs include:
722
+ // - eventType: 'rbac.assign_role.success' | 'rbac.remove_role.success'
723
+ // - userId, role, resourceType, resourceId
724
+ // - timestamp, requestId
725
+ ```
726
+
727
+ ### 4. Validate Resource Ownership
728
+
729
+ Before checking permissions, verify that the resource exists and belongs to the team:
730
+
731
+ ```typescript
732
+ // Verify project belongs to team
733
+ const project = await getProject(projectId);
734
+ if (project.teamId !== teamId) {
735
+ throw new Error('Project not found');
736
+ }
737
+
738
+ // Then check permissions
739
+ await requirePermission({
740
+ userId: session.userId,
741
+ permission: PERMISSIONS.PROJECT_UPDATE,
742
+ resourceId: projectId,
743
+ resourceType: 'project',
744
+ });
745
+ ```
746
+
747
+ ### 5. Rate Limit Role Changes
748
+
749
+ Implement rate limiting for role assignment endpoints to prevent abuse:
750
+
751
+ ```typescript
752
+ // Limit role changes to 10 per minute per team
753
+ await checkRateLimit(`role-changes:${teamId}`, 10, 60000);
754
+ ```
755
+
756
+ ---
757
+
758
+ ## Integration with Authentication
759
+
760
+ The RBAC system integrates seamlessly with the authentication system:
761
+
762
+ ### 1. Default Roles on Verification
763
+
764
+ When a user verifies their email, default roles are assigned:
765
+
766
+ ```typescript
767
+ // In email verification handler
768
+ await verifyEmail(token);
769
+
770
+ // Assign default roles (currently none, user must create/join team)
771
+ // This will be updated when team creation is implemented
772
+ ```
773
+
774
+ ### 2. Session Data Includes Roles
775
+
776
+ The session object includes user roles for quick access:
777
+
778
+ ```typescript
779
+ const session = await getSession();
780
+ // session.user.roles = [
781
+ // { role: 'TEAM_OWNER', resourceType: 'team', resourceId: 'team_123' },
782
+ // { role: 'PROJECT_EDITOR', resourceType: 'project', resourceId: 'project_456' },
783
+ // ]
784
+ ```
785
+
786
+ ### 3. Client-Side Role Checks
787
+
788
+ Use the `useSession` hook to access roles in client components:
789
+
790
+ ```typescript
791
+ 'use client';
792
+ import { useSession } from '@/features/auth/hooks/use-session';
793
+
794
+ export function TeamSettings() {
795
+ const { data: session } = useSession();
796
+
797
+ const isTeamOwner = session?.user.roles.some(
798
+ r => r.role === 'TEAM_OWNER' && r.resourceId === teamId
799
+ );
800
+
801
+ return (
802
+ <div>
803
+ {isTeamOwner && <DangerZone />}
804
+ </div>
805
+ );
806
+ }
807
+ ```
808
+
809
+ ---
810
+
811
+ ## Testing RBAC
812
+
813
+ ### Unit Tests
814
+
815
+ Test individual RBAC functions with mock data:
816
+
817
+ ```typescript
818
+ import { assignRole, hasPermission, TEAM_ROLES, PERMISSIONS } from '@/server/auth/rbac';
819
+
820
+ test('team owner has all permissions', async () => {
821
+ await assignRole({
822
+ userId: 'user_123',
823
+ role: TEAM_ROLES.TEAM_OWNER,
824
+ resourceType: 'team',
825
+ resourceId: 'team_456',
826
+ });
827
+
828
+ const canDelete = await hasPermission({
829
+ userId: 'user_123',
830
+ permission: PERMISSIONS.TEAM_DELETE,
831
+ resourceId: 'team_456',
832
+ resourceType: 'team',
833
+ });
834
+
835
+ expect(canDelete).toBe(true);
836
+ });
837
+ ```
838
+
839
+ ### Integration Tests
840
+
841
+ Test RBAC with real database and API routes:
842
+
843
+ ```typescript
844
+ test('POST /api/issues requires issue:create permission', async () => {
845
+ // Create user with viewer role (no create permission)
846
+ await assignRole({
847
+ userId: 'user_123',
848
+ role: PROJECT_ROLES.PROJECT_VIEWER,
849
+ resourceType: 'project',
850
+ resourceId: 'project_456',
851
+ });
852
+
853
+ // Attempt to create issue
854
+ const response = await fetch('/api/issues', {
855
+ method: 'POST',
856
+ body: JSON.stringify({ projectId: 'project_456', title: 'Test' }),
857
+ });
858
+
859
+ expect(response.status).toBe(403);
860
+ });
861
+ ```
862
+
863
+ ### Property-Based Tests
864
+
865
+ Test RBAC properties with random inputs:
866
+
867
+ ```typescript
868
+ import fc from 'fast-check';
869
+
870
+ test('Property: Resource usage is tracked correctly', () => {
871
+ fc.assert(
872
+ fc.asyncProperty(
873
+ fc.uuid(),
874
+ fc.uuid(),
875
+ async (userId, teamId) => {
876
+ const usageBefore = await getTeamUsage(teamId);
877
+
878
+ // Check quotas
879
+ const result = await checkResourceLimit(teamId, 'members');
880
+
881
+ expect(result).toBeDefined();
882
+ expect(result.allowed).toBeDefined();
883
+ }
884
+ )
885
+ );
886
+ });
887
+ ```
888
+
889
+ ---
890
+
891
+ ## Troubleshooting
892
+
893
+ ### Common Issues
894
+
895
+ #### 1. Permission Denied Errors
896
+
897
+ **Problem:** User gets permission denied even though they should have access.
898
+
899
+ **Solution:**
900
+ - Check if user has the correct role assigned
901
+ - Verify the resource ID matches
902
+ - Check if the role has the required permission in `ROLE_PERMISSIONS`
903
+ - Review logs for `rbac.permission_denied` events
904
+
905
+ ```typescript
906
+ // Debug: Check user's roles and permissions
907
+ const roles = await getUserRoles(userId);
908
+ console.log('User roles:', roles);
909
+
910
+ const permissions = await getUserPermissions(userId, resourceId, 'project');
911
+ console.log('User permissions:', permissions);
912
+ ```
913
+
914
+ #### 2. Resource Quota Exceeded
915
+
916
+ **Problem:** Cannot assign role because team has reached resource quotas.
917
+
918
+ **Solution:**
919
+ - Check current usage: `await getTeamUsage(teamId)`
920
+ - Verify team's quotas in environment variables
921
+ - Increase instance limits if valid
922
+ - Remove unused members or resources
923
+
924
+ #### 3. Role Assignment Fails
925
+
926
+ **Problem:** `assignRole` throws an error.
927
+
928
+ **Solution:**
929
+ - Verify role exists in `ALL_ROLES`
930
+ - Check resource type matches role type (team role for team resource, project role for project resource)
931
+ - Ensure resource exists in database
932
+ - Check database constraints (foreign keys, unique constraints)
933
+
934
+ ---
935
+
936
+ ## Migration Guide
937
+
938
+ ### From Mock Roles to Real RBAC
939
+
940
+ If you're migrating from mock role checks to the real RBAC system:
941
+
942
+ 1. **Replace hardcoded role checks:**
943
+
944
+ ```typescript
945
+ // Before
946
+ if (user.role === 'admin') { ... }
947
+
948
+ // After
949
+ const canManage = await hasPermission({
950
+ userId: user.id,
951
+ permission: PERMISSIONS.TEAM_MANAGE_MEMBERS,
952
+ resourceId: teamId,
953
+ resourceType: 'team',
954
+ });
955
+ ```
956
+
957
+ 2. **Update session data structure:**
958
+
959
+ ```typescript
960
+ // Before
961
+ session.user.role = 'admin';
962
+
963
+ // After
964
+ session.user.roles = [
965
+ { role: 'TEAM_ADMIN', resourceType: 'team', resourceId: 'team_123' }
966
+ ];
967
+ ```
968
+
969
+ 3. **Add permission checks to API routes:**
970
+
971
+ ```typescript
972
+ // Add to all protected API routes
973
+ await requirePermission({
974
+ userId: session.userId,
975
+ permission: PERMISSIONS.ISSUE_CREATE,
976
+ resourceId: projectId,
977
+ resourceType: 'project',
978
+ });
979
+ ```
980
+
981
+ ---
982
+
983
+ ## Two-Tier Role System Examples
984
+
985
+ ### Creating Team Owners
986
+
987
+ ```typescript
988
+ // Owner who creates content
989
+ await assignRoles([
990
+ { userId, role: 'TEAM_OWNER', resourceType: 'team', resourceId: teamId },
991
+ { userId, role: 'TEAM_EDITOR', resourceType: 'team', resourceId: teamId },
992
+ ]);
993
+
994
+ // Owner who only manages
995
+ await assignRoles([
996
+ { userId, role: 'TEAM_OWNER', resourceType: 'team', resourceId: teamId },
997
+ { userId, role: 'TEAM_VIEWER', resourceType: 'team', resourceId: teamId },
998
+ ]);
999
+ ```
1000
+
1001
+ ### Creating Team Admins
1002
+
1003
+ ```typescript
1004
+ // Admin who creates content
1005
+ await assignRoles([
1006
+ { userId, role: 'TEAM_ADMIN', resourceType: 'team', resourceId: teamId },
1007
+ { userId, role: 'TEAM_EDITOR', resourceType: 'team', resourceId: teamId },
1008
+ ]);
1009
+
1010
+ // Admin who only manages (free)
1011
+ await assignRoles([
1012
+ { userId, role: 'TEAM_ADMIN', resourceType: 'team', resourceId: teamId },
1013
+ { userId, role: 'TEAM_MEMBER', resourceType: 'team', resourceId: teamId },
1014
+ ]);
1015
+ ```
1016
+
1017
+ ### Creating Regular Team Members
1018
+
1019
+ ```typescript
1020
+ // Designer/QA
1021
+ await assignRole({
1022
+ userId,
1023
+ role: 'TEAM_EDITOR',
1024
+ resourceType: 'team',
1025
+ resourceId: teamId,
1026
+ });
1027
+
1028
+ // Developer (free)
1029
+ await assignRole({
1030
+ userId,
1031
+ role: 'TEAM_MEMBER',
1032
+ resourceType: 'team',
1033
+ resourceId: teamId,
1034
+ });
1035
+
1036
+ // Stakeholder (free)
1037
+ await assignRole({
1038
+ userId,
1039
+ role: 'TEAM_VIEWER',
1040
+ resourceType: 'team',
1041
+ resourceId: teamId,
1042
+ });
1043
+ ```
1044
+
1045
+ ### Querying Two-Tier Roles
1046
+
1047
+ ```typescript
1048
+ // Get management role
1049
+ const managementRole = await getManagementRole(userId, teamId);
1050
+ // Returns: 'TEAM_OWNER' | 'TEAM_ADMIN' | null
1051
+
1052
+ // Get operational role
1053
+ const operationalRole = await getOperationalRole(userId, teamId);
1054
+ // Returns: 'TEAM_EDITOR' | 'TEAM_MEMBER' | 'TEAM_VIEWER' | null
1055
+
1056
+ // Check if user is owner
1057
+ const isOwner = managementRole === 'TEAM_OWNER';
1058
+
1059
+
1060
+ ```
1061
+
1062
+ ### Auto-Promotion to TEAM_EDITOR
1063
+
1064
+ ```typescript
1065
+ // When assigning PROJECT_OWNER or PROJECT_EDITOR
1066
+ await assignRole({
1067
+ userId,
1068
+ role: 'PROJECT_OWNER',
1069
+ resourceType: 'project',
1070
+ resourceId: projectId,
1071
+ });
1072
+
1073
+ // Auto-promote to TEAM_EDITOR
1074
+ await autoPromoteToEditor(userId, teamId);
1075
+
1076
+ // Or use ensureOperationalRole for more control
1077
+ await ensureOperationalRole(userId, teamId, 'TEAM_EDITOR');
1078
+ // Only upgrades if current role is lower, never downgrades
1079
+ ```
1080
+
1081
+ ---
1082
+
1083
+ ## FAQ
1084
+
1085
+ ### Q: Can a user have only a management role without an operational role?
1086
+ **A:** Technically yes (database allows it), but the UI should always assign both. A user with only TEAM_OWNER would have no content access permissions.
1087
+
1088
+ ### Q: Can a user have multiple operational roles?
1089
+ **A:** No. Users should have exactly one operational role (EDITOR, MEMBER, or VIEWER) per team.
1090
+
1091
+ ### Q: What happens if I assign PROJECT_OWNER to a user with TEAM_VIEWER?
1092
+ **A:** The `autoPromoteToEditor()` function will upgrade them to TEAM_EDITOR.
1093
+
1094
+ ### Q: Can I downgrade a TEAM_EDITOR to TEAM_MEMBER?
1095
+ **A:** Yes, but you must do it explicitly using `updateRole()`. Auto-promotion only upgrades, never downgrades. **Important:** If the user is a PROJECT_OWNER on any projects, the demotion will be blocked. You must transfer project ownership first using `demoteWithOwnershipTransfer()`.
1096
+
1097
+
1098
+ **A:** Assign them TEAM_OWNER (management) + TEAM_VIEWER or TEAM_MEMBER (operational, both free).
1099
+
1100
+ ### Q: Why separate management and operational roles?
1101
+ **A:** This allows flexible team management where owners/admins can manage settings without paying for a seat if they don't create content.
1102
+
1103
+ ### Q: What happens if I try to demote a PROJECT_OWNER from TEAM_EDITOR?
1104
+ **A:** The system will block the demotion and throw an error listing all projects where the user is owner. You must use `demoteWithOwnershipTransfer()` to transfer ownership to other users first. This prevents orphaned projects without owners.
1105
+
1106
+ ### Q: How do I check if a user can be safely demoted?
1107
+ **A:** Use `getOwnedProjects(userId)` to check if they own any projects. If the array is empty, demotion is safe. If not, you need to transfer ownership first.
1108
+
1109
+ ---
1110
+
1111
+ ## Related Documentation
1112
+
1113
+ - [Authentication System](./SECURITY.md) - User authentication and session management
1114
+ - [Resource Limits & Quotas](./RESOURCE_LIMITS.md) - Resource usage and limits
1115
+ - [Product Overview](./.ai/steering/product.md) - Product features and user roles
1116
+ - [API Documentation](./API.md) - API endpoints and authentication
1117
+
1118
+ ---
1119
+
1120
+ ## Support
1121
+
1122
+ For questions or issues with RBAC:
1123
+
1124
+ 1. Check this documentation first
1125
+ 2. Review the [Product Overview](./.ai/steering/product.md) for role definitions
1126
+ 3. Check logs for `rbac.*` events
1127
+ 4. Review the source code in `src/config/roles.ts` and `src/server/auth/rbac.ts`
1128
+
1129
+ ---
1130
+
1131
+ **Last Updated:** November 19, 2025
1132
+ **Version:** 2.0.0 (Two-Tier Role System)