@maudecode/kanvil 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/apps/server/.env.example +19 -0
  2. package/apps/server/dist/auth-JcS53IcO.mjs +12424 -0
  3. package/apps/server/dist/{config-CbNqtJEj.mjs → config-D3cAABi7.mjs} +27 -2
  4. package/apps/server/dist/index.mjs +2500 -294
  5. package/apps/server/dist/migrate.mjs +1 -1
  6. package/apps/server/dist/recover.mjs +4 -4
  7. package/apps/server/drizzle/0014_inbox_dismissal.sql +1 -0
  8. package/apps/server/drizzle/0015_notification_categories.sql +14 -0
  9. package/apps/server/drizzle/0016_ticket_resources.sql +19 -0
  10. package/apps/server/drizzle/0017_project_backgrounds.sql +3 -0
  11. package/apps/server/drizzle/0018_delivery_outbox.sql +65 -0
  12. package/apps/server/drizzle/0019_retire_push_deliveries.sql +1 -0
  13. package/apps/server/drizzle/0020_calendar_feeds.sql +16 -0
  14. package/apps/server/drizzle/0021_staged_uploads.sql +14 -0
  15. package/apps/server/drizzle/0022_manual_order.sql +6 -0
  16. package/apps/server/drizzle/0023_workspace_invitations.sql +22 -0
  17. package/apps/server/drizzle/0024_workflow_states.sql +39 -0
  18. package/apps/server/drizzle/0025_workspace_labels.sql +10 -0
  19. package/apps/server/drizzle/0026_public_read.sql +1 -0
  20. package/apps/server/drizzle/0027_custom_fields.sql +16 -0
  21. package/apps/server/drizzle/0028_project_lifecycle.sql +11 -0
  22. package/apps/server/drizzle/0029_ticket_relocation.sql +16 -0
  23. package/apps/server/drizzle/0030_repository_connections.sql +39 -0
  24. package/apps/server/drizzle/0031_repository_providers.sql +3 -0
  25. package/apps/server/drizzle/0032_workspace_ownership.sql +11 -0
  26. package/apps/server/drizzle/0033_import_runs.sql +38 -0
  27. package/apps/server/drizzle/0034_issue_sync.sql +38 -0
  28. package/apps/server/drizzle/0035_account_deletion.sql +9 -0
  29. package/apps/server/drizzle/0036_workspace_roles.sql +16 -0
  30. package/apps/server/drizzle/0037_email_code_owner.sql +14 -0
  31. package/apps/server/drizzle/meta/0014_snapshot.json +4246 -0
  32. package/apps/server/drizzle/meta/0015_snapshot.json +4297 -0
  33. package/apps/server/drizzle/meta/0016_snapshot.json +4443 -0
  34. package/apps/server/drizzle/meta/0017_snapshot.json +4468 -0
  35. package/apps/server/drizzle/meta/0018_snapshot.json +4948 -0
  36. package/apps/server/drizzle/meta/0019_snapshot.json +4826 -0
  37. package/apps/server/drizzle/meta/0020_snapshot.json +4947 -0
  38. package/apps/server/drizzle/meta/0021_snapshot.json +5059 -0
  39. package/apps/server/drizzle/meta/0022_snapshot.json +5094 -0
  40. package/apps/server/drizzle/meta/0023_snapshot.json +5267 -0
  41. package/apps/server/drizzle/meta/0024_snapshot.json +5405 -0
  42. package/apps/server/drizzle/meta/0025_snapshot.json +5474 -0
  43. package/apps/server/drizzle/meta/0026_snapshot.json +5481 -0
  44. package/apps/server/drizzle/meta/0027_snapshot.json +5605 -0
  45. package/apps/server/drizzle/meta/0028_snapshot.json +5699 -0
  46. package/apps/server/drizzle/meta/0029_snapshot.json +5809 -0
  47. package/apps/server/drizzle/meta/0030_snapshot.json +6066 -0
  48. package/apps/server/drizzle/meta/0031_snapshot.json +6074 -0
  49. package/apps/server/drizzle/meta/0032_snapshot.json +6100 -0
  50. package/apps/server/drizzle/meta/0033_snapshot.json +6406 -0
  51. package/apps/server/drizzle/meta/0034_snapshot.json +6698 -0
  52. package/apps/server/drizzle/meta/0035_snapshot.json +6704 -0
  53. package/apps/server/drizzle/meta/0036_snapshot.json +6825 -0
  54. package/apps/server/drizzle/meta/0037_snapshot.json +6825 -0
  55. package/apps/server/drizzle/meta/_journal.json +168 -0
  56. package/apps/web/dist/assets/CompositeItem-BbuEp99X.js +1 -0
  57. package/apps/web/dist/assets/Trans-DJGH63s1.js +1 -0
  58. package/apps/web/dist/assets/abnfDiagram-WEYOIA3C-DTOx8N4B.js +1 -0
  59. package/apps/web/dist/assets/admin-settings-CJG9PMKR.js +1 -0
  60. package/apps/web/dist/assets/arc-Y1ARJVZ4.js +1 -0
  61. package/apps/web/dist/assets/architecture-WOLXFQ4H-DlC3p5z3.js +1 -0
  62. package/apps/web/dist/assets/architectureDiagram-ZHVYKT53-DooN3Z58.js +36 -0
  63. package/apps/web/dist/assets/archive-restore-B6_SsOIP.js +1 -0
  64. package/apps/web/dist/assets/array-BifhSqXX.js +1 -0
  65. package/apps/web/dist/assets/az-AZ-BtrlbgjS.js +1 -0
  66. package/apps/web/dist/assets/az-D-kj4lmf.js +1 -0
  67. package/apps/web/dist/assets/az-DqY__MpS.js +1 -0
  68. package/apps/web/dist/assets/blockDiagram-RJAE7QA3-CD5AgY4U.js +140 -0
  69. package/apps/web/dist/assets/c4Diagram-XDPPPE54-CTDOcLuN.js +38 -0
  70. package/apps/web/dist/assets/channel-BhHvU4I-.js +1 -0
  71. package/apps/web/dist/assets/chunk-2E7WHVMD-D9qnBqTV.js +88 -0
  72. package/apps/web/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  73. package/apps/web/dist/assets/chunk-4EMNKR2T-Kz5JiJ85.js +1 -0
  74. package/apps/web/dist/assets/chunk-55XCU76K-DnKiFpYM.js +1 -0
  75. package/apps/web/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  76. package/apps/web/dist/assets/chunk-7S6XSTFO-CpdNd6Ke.js +2 -0
  77. package/apps/web/dist/assets/chunk-AQDTSKZB-CpyuSWt8.js +72 -0
  78. package/apps/web/dist/assets/chunk-DSNLSHJZ-DTC3y9rb.js +129 -0
  79. package/apps/web/dist/assets/chunk-DUW6YSOI-Dgx8z5s3.js +1 -0
  80. package/apps/web/dist/assets/chunk-HAGFOTED-Bv8PrMYK.js +62 -0
  81. package/apps/web/dist/assets/chunk-HNE4Q36P-CDDJ_yRa.js +1 -0
  82. package/apps/web/dist/assets/chunk-J5ZVWO5B-oDCd-gWO.js +1 -0
  83. package/apps/web/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  84. package/apps/web/dist/assets/chunk-NGNAAXSQ-C2Wy9Xmz.js +136 -0
  85. package/apps/web/dist/assets/chunk-NQOKRVIF-lNtnsWHS.js +213 -0
  86. package/apps/web/dist/assets/chunk-UHW7PFBP-D79ptlTN.js +1 -0
  87. package/apps/web/dist/assets/chunk-VQ5W62QI-B8hWFCiM.js +1 -0
  88. package/apps/web/dist/assets/chunk-WQQL4CDK-DAGuWzS3.js +10 -0
  89. package/apps/web/dist/assets/chunk-XXDRQBXY-CnbRkih_.js +1 -0
  90. package/apps/web/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  91. package/apps/web/dist/assets/chunk-YZO67HFG-C0ptzlKO.js +1 -0
  92. package/apps/web/dist/assets/chunk-ZAUX2LTX-ah8U5xoJ.js +1 -0
  93. package/apps/web/dist/assets/chunk-ZCHMQSOR-DYqATOIZ.js +2 -0
  94. package/apps/web/dist/assets/classDiagram-v2-4MYWR3UA-DYytA-ua.js +217 -0
  95. package/apps/web/dist/assets/core-jXc03Sty.js +1 -0
  96. package/apps/web/dist/assets/corner-left-up-DA7MG5uX.js +1 -0
  97. package/apps/web/dist/assets/cose-bilkent-JH36ORCC-lWVj4msc.js +1 -0
  98. package/apps/web/dist/assets/cynefin-EF2NZ3EQ-Xy6e6m1E.js +1 -0
  99. package/apps/web/dist/assets/cynefinDiagram-WF24UDRP-BYarZJSm.js +62 -0
  100. package/apps/web/dist/assets/cytoscape.esm-BegBNzOV.js +321 -0
  101. package/apps/web/dist/assets/dagre-NK4GIZVX-WLvvUY1o.js +4 -0
  102. package/apps/web/dist/assets/de-DAv77-wP.js +1 -0
  103. package/apps/web/dist/assets/de-DE-Bu_Ko2QA.js +1 -0
  104. package/apps/web/dist/assets/de-UHreLwyV.js +1 -0
  105. package/apps/web/dist/assets/default-D5TdIZQS.js +56 -0
  106. package/apps/web/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
  107. package/apps/web/dist/assets/delivery-settings-BE5MW8U0.js +1 -0
  108. package/apps/web/dist/assets/diagram-CBK3MWTC-D6PtxkLg.js +24 -0
  109. package/apps/web/dist/assets/diagram-I5XIIV2D-DTOKQwIY.js +24 -0
  110. package/apps/web/dist/assets/diagram-ODIL2UCW-BmERt0Xu.js +30 -0
  111. package/apps/web/dist/assets/diagram-PFBEJUXE-WDUe08eD.js +3 -0
  112. package/apps/web/dist/assets/diagram-RJA3I4VV-B2K-NLGG.js +41 -0
  113. package/apps/web/dist/assets/diagram-TYUNFSNR-BLf7PpV7.js +200 -0
  114. package/apps/web/dist/assets/dist-CumnGVmJ.js +1 -0
  115. package/apps/web/dist/assets/ebnfDiagram-V4P3TTPT-DwBUQs9p.js +1 -0
  116. package/apps/web/dist/assets/el-D2ypddWn.js +1 -0
  117. package/apps/web/dist/assets/el-EJnrsyVr.js +1 -0
  118. package/apps/web/dist/assets/el-GR-CpKEps47.js +1 -0
  119. package/apps/web/dist/assets/elk-QONTBCTQ-AuT8PinL.js +27 -0
  120. package/apps/web/dist/assets/ellipsis-D6154JKs.js +1 -0
  121. package/apps/web/dist/assets/en-EnSRisMz.js +1 -0
  122. package/apps/web/dist/assets/en-US-DKYSujv3.js +1 -0
  123. package/apps/web/dist/assets/erDiagram-KYQIGQAA-h--u4Eo6.js +99 -0
  124. package/apps/web/dist/assets/es-B_49BMhR.js +1 -0
  125. package/apps/web/dist/assets/es-D2ScuV-5.js +1 -0
  126. package/apps/web/dist/assets/es-ES-DVkfi7H-.js +1 -0
  127. package/apps/web/dist/assets/eventmodeling-K75KTNOO-CW4hDt1j.js +1 -0
  128. package/apps/web/dist/assets/flowDiagram-IUGLLWBU-BGUscnNP.js +1 -0
  129. package/apps/web/dist/assets/forms-BcD6Wwyv.js +1 -0
  130. package/apps/web/dist/assets/fr-B-WmPGZD.js +1 -0
  131. package/apps/web/dist/assets/fr-C_VpS8u6.js +1 -0
  132. package/apps/web/dist/assets/fr-FR-DkHaEHqi.js +1 -0
  133. package/apps/web/dist/assets/ganttDiagram-R7GPNTJY-CB3lsQvj.js +292 -0
  134. package/apps/web/dist/assets/gitGraph-VSP46ZUC-Hu-kvdCR.js +1 -0
  135. package/apps/web/dist/assets/gitGraphDiagram-PDYL7XHY-DCuY3C1Q.js +106 -0
  136. package/apps/web/dist/assets/graphlib-DS17s2tU.js +1 -0
  137. package/apps/web/dist/assets/hi-CW4rdp_m.js +1 -0
  138. package/apps/web/dist/assets/hi-DvoDcUpL.js +1 -0
  139. package/apps/web/dist/assets/hi-IN-CbUDNSTK.js +1 -0
  140. package/apps/web/dist/assets/highlight-CMydIf9M.js +5 -0
  141. package/apps/web/dist/assets/id-CPASBZ2r.js +1 -0
  142. package/apps/web/dist/assets/id-CvL3yBVr.js +1 -0
  143. package/apps/web/dist/assets/id-ID-DLTkxt2j.js +1 -0
  144. package/apps/web/dist/assets/index-DoqlyejP.js +17 -0
  145. package/apps/web/dist/assets/index-DyQNFS69.css +2 -0
  146. package/apps/web/dist/assets/info-OHQRW6UA-Cc8VwTsk.js +1 -0
  147. package/apps/web/dist/assets/infoDiagram-MVDRKAX5-KIMOx55J.js +2 -0
  148. package/apps/web/dist/assets/init-C-OQMol4.js +1 -0
  149. package/apps/web/dist/assets/invitations-BmpelTJu.js +1 -0
  150. package/apps/web/dist/assets/isSameWeek-2ftYGvBT.js +1 -0
  151. package/apps/web/dist/assets/ishikawaDiagram-HPEHV2GE-CAou726L.js +70 -0
  152. package/apps/web/dist/assets/it-Cd7u97Jd.js +1 -0
  153. package/apps/web/dist/assets/it-DOLotXOj.js +1 -0
  154. package/apps/web/dist/assets/it-IT-CIzq0YwC.js +1 -0
  155. package/apps/web/dist/assets/item-Cq_ZbivE.js +1 -0
  156. package/apps/web/dist/assets/ja-B1iJt9qB.js +1 -0
  157. package/apps/web/dist/assets/ja-JP-CIE4-D-v.js +1 -0
  158. package/apps/web/dist/assets/ja-LkOrjegp.js +1 -0
  159. package/apps/web/dist/assets/journeyDiagram-BOSHW7O7-YbJuPYDH.js +139 -0
  160. package/apps/web/dist/assets/kanban-definition-FNSA4HC5-nuRnm9y8.js +89 -0
  161. package/apps/web/dist/assets/katex-B_JcIwqj.js +257 -0
  162. package/apps/web/dist/assets/ko-DPpXw683.js +1 -0
  163. package/apps/web/dist/assets/ko-KR-DYP5Zae6.js +1 -0
  164. package/apps/web/dist/assets/ko-fmUq1-8W.js +1 -0
  165. package/apps/web/dist/assets/label-settings-B3LsJxhk.js +1 -0
  166. package/apps/web/dist/assets/line-WsxZYwZr.js +1 -0
  167. package/apps/web/dist/assets/linear-C9iwaMOi.js +1 -0
  168. package/apps/web/dist/assets/lucide-DIlszs-T.js +1 -0
  169. package/apps/web/dist/assets/markdown-blocks-Bw26pRKB.js +2 -0
  170. package/apps/web/dist/assets/member-directory-CHKUw0u4.js +1 -0
  171. package/apps/web/dist/assets/mermaid-parser.core-B5c-1CnP.js +7 -0
  172. package/apps/web/dist/assets/mermaid.core-vGVkgzA3.js +44 -0
  173. package/apps/web/dist/assets/mindmap-definition-6OY57UG3-uooJyUak.js +98 -0
  174. package/apps/web/dist/assets/mk-CkaQRpqe.js +1 -0
  175. package/apps/web/dist/assets/mk-LWVrR-T-.js +1 -0
  176. package/apps/web/dist/assets/mk-MK-CpOo5Bd8.js +1 -0
  177. package/apps/web/dist/assets/nl-DiEjqOA8.js +1 -0
  178. package/apps/web/dist/assets/nl-NL-Mu8G8RON.js +1 -0
  179. package/apps/web/dist/assets/nl-ro6hbqo5.js +1 -0
  180. package/apps/web/dist/assets/ordinal-BDEzSJ7C.js +1 -0
  181. package/apps/web/dist/assets/packet-JDAUHWVQ-WJpqlH1d.js +1 -0
  182. package/apps/web/dist/assets/path-fybaL0A-.js +1 -0
  183. package/apps/web/dist/assets/pegDiagram-ECIUJNBX-CUvajD93.js +1 -0
  184. package/apps/web/dist/assets/pie-XZMESJXO-DvandPby.js +1 -0
  185. package/apps/web/dist/assets/pieDiagram-GNMPY74T-CqxeyIaP.js +39 -0
  186. package/apps/web/dist/assets/pl-Bx_fYLKY.js +1 -0
  187. package/apps/web/dist/assets/pl-CauoMfkf.js +1 -0
  188. package/apps/web/dist/assets/pl-PL-DGuxe2Aq.js +1 -0
  189. package/apps/web/dist/assets/preload-helper-BLdHbfdN.js +1 -0
  190. package/apps/web/dist/assets/project-lifecycle-Ba7iRF3u.js +1 -0
  191. package/apps/web/dist/assets/project-settings-CtOWgEam.js +1 -0
  192. package/apps/web/dist/assets/pt-BR-BpOhwoDW.js +1 -0
  193. package/apps/web/dist/assets/pt-BR-D-a7F5zJ.js +1 -0
  194. package/apps/web/dist/assets/pt-BR-DwkMPgq1.js +1 -0
  195. package/apps/web/dist/assets/public-project-CHRjhFIn.js +1 -0
  196. package/apps/web/dist/assets/quadrantDiagram-D57K4MC3-DFjNmaZc.js +7 -0
  197. package/apps/web/dist/assets/radar-ABXABTNO-CJhZF9j2.js +1 -0
  198. package/apps/web/dist/assets/railroad-I3PHUGI6-DZC10oBD.js +1 -0
  199. package/apps/web/dist/assets/railroad-abnf-LNEFI6M7-BUJF2n6u.js +1 -0
  200. package/apps/web/dist/assets/railroad-ebnf-DWYD2UWJ-CG7oB02K.js +1 -0
  201. package/apps/web/dist/assets/railroad-peg-JR7BVNR7-DBCZuZJY.js +1 -0
  202. package/apps/web/dist/assets/railroadDiagram-Y72NRBL7-CvN3poBq.js +1 -0
  203. package/apps/web/dist/assets/requirementDiagram-EQYSW5RA-BEItNirc.js +84 -0
  204. package/apps/web/dist/assets/rolldown-runtime-COiEfhsA.js +1 -0
  205. package/apps/web/dist/assets/rotate-ccw-Bm0ESNH_.js +1 -0
  206. package/apps/web/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
  207. package/apps/web/dist/assets/ru-D-WIMI5_.js +1 -0
  208. package/apps/web/dist/assets/ru-DOaRp00B.js +1 -0
  209. package/apps/web/dist/assets/ru-RU-DrXnqZbV.js +1 -0
  210. package/apps/web/dist/assets/sankeyDiagram-SY24JHO5-DluLIjax.js +40 -0
  211. package/apps/web/dist/assets/search-D94SZwrC.js +85 -0
  212. package/apps/web/dist/assets/send-D9TETK3s.js +1 -0
  213. package/apps/web/dist/assets/sequenceDiagram-BLEHNHQU-ZcwnsNxK.js +169 -0
  214. package/apps/web/dist/assets/settings-Dd9EVxua.js +1 -0
  215. package/apps/web/dist/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
  216. package/apps/web/dist/assets/sliders-horizontal-CiZZFL1o.js +1 -0
  217. package/apps/web/dist/assets/src-BWF7jMDv.js +1 -0
  218. package/apps/web/dist/assets/stateDiagram-v2-A6IESKWZ-DD6vH3rM.js +291 -0
  219. package/apps/web/dist/assets/swimlanes-B3ENRKFQ-pX_qyO4X.js +1 -0
  220. package/apps/web/dist/assets/swimlanesDiagram-AYQRV4AK-CeVsLUsg.js +8 -0
  221. package/apps/web/dist/assets/switch-B_u8n1o6.js +1 -0
  222. package/apps/web/dist/assets/table-DcCLC7fi.js +1 -0
  223. package/apps/web/dist/assets/ticket-detail-C9egaVSf.js +2 -0
  224. package/apps/web/dist/assets/ticket-editor-UlSZgpWF.js +2 -0
  225. package/apps/web/dist/assets/ticket-list-controls-BidzkMOD.js +1 -0
  226. package/apps/web/dist/assets/ticket-list-vNBO8mkk.js +5 -0
  227. package/apps/web/dist/assets/timeline-definition-JXYKGLGB-DLBjAxKq.js +120 -0
  228. package/apps/web/dist/assets/toDate-B3HYxwtT.js +1 -0
  229. package/apps/web/dist/assets/tr-BZEJyY-F.js +1 -0
  230. package/apps/web/dist/assets/tr-DeYojjLx.js +1 -0
  231. package/apps/web/dist/assets/tr-TR-B92YeFW5.js +1 -0
  232. package/apps/web/dist/assets/treeView-D4JQ5SDB-DsJ44q_q.js +1 -0
  233. package/apps/web/dist/assets/treemap-SAJKECNS-BmXoBpVL.js +1 -0
  234. package/apps/web/dist/assets/uk-DACrfgCP.js +1 -0
  235. package/apps/web/dist/assets/uk-UA-DmcDs-MU.js +1 -0
  236. package/apps/web/dist/assets/uk-f8X5q5C_.js +1 -0
  237. package/apps/web/dist/assets/upload-CGpna3R2.js +1 -0
  238. package/apps/web/dist/assets/useQueries-BihXYrAP.js +1 -0
  239. package/apps/web/dist/assets/usecaseDiagram-WPOLBNNX-eU2tr2si.js +328 -0
  240. package/apps/web/dist/assets/vennDiagram-Q3Y3IDCW-CoVTWGNg.js +34 -0
  241. package/apps/web/dist/assets/vi-CSGaJFlR.js +1 -0
  242. package/apps/web/dist/assets/vi-CkqUo4w_.js +1 -0
  243. package/apps/web/dist/assets/vi-VN-DM5JYNuP.js +1 -0
  244. package/apps/web/dist/assets/visual-editor-B6HiiLMg.js +208 -0
  245. package/apps/web/dist/assets/wardley-7MLQ67FV-C6mVVk98.js +1 -0
  246. package/apps/web/dist/assets/wardleyDiagram-IVAIDKWA-m3CeJc7a.js +78 -0
  247. package/apps/web/dist/assets/workspace-settings-CSvVqaL6.js +1 -0
  248. package/apps/web/dist/assets/xychartDiagram-4URNHDU4-Dw6fLaip.js +7 -0
  249. package/apps/web/dist/assets/zh-CN-BdRcimyZ.js +1 -0
  250. package/apps/web/dist/assets/zh-CN-CC7ghLLr.js +1 -0
  251. package/apps/web/dist/assets/zh-CN-CiUOkQXe.js +1 -0
  252. package/apps/web/dist/assets/zh-TW-BH1L9tOt.js +1 -0
  253. package/apps/web/dist/assets/zh-TW-BlIRMi1C.js +1 -0
  254. package/apps/web/dist/assets/zh-TW-Co4UBSfi.js +1 -0
  255. package/apps/web/dist/index.html +14 -8
  256. package/compose.yml +12 -0
  257. package/docs/api.md +285 -10
  258. package/docs/infrastructure.md +2 -2
  259. package/docs/localization.md +25 -0
  260. package/docs/plan.md +28 -10
  261. package/docs/self-hosting.md +44 -5
  262. package/docs/themes.md +1 -1
  263. package/docs/verification.md +1 -1
  264. package/docs/workspaces.md +18 -2
  265. package/package.json +12 -8
  266. package/apps/server/dist/auth-I1XEr0d4.mjs +0 -2931
  267. package/apps/web/dist/assets/CompositeItem-BWPJ5Mol.js +0 -1
  268. package/apps/web/dist/assets/admin-settings-DZqkC6ju.js +0 -1
  269. package/apps/web/dist/assets/date-picker-6H_iwP6t.js +0 -1
  270. package/apps/web/dist/assets/ellipsis-BT172Uvu.js +0 -1
  271. package/apps/web/dist/assets/forms-B4Vg3CPz.js +0 -92
  272. package/apps/web/dist/assets/image-edit-trigger-DGmVtWLC.js +0 -1
  273. package/apps/web/dist/assets/index-C_a21taR.js +0 -50
  274. package/apps/web/dist/assets/index-DM-D_3Sv.css +0 -2
  275. package/apps/web/dist/assets/kbd-tTQGZxaK.js +0 -1
  276. package/apps/web/dist/assets/link-DoIP9KJ6.js +0 -2
  277. package/apps/web/dist/assets/list-order-Bzsrihyr.js +0 -1
  278. package/apps/web/dist/assets/lucide-U995NW8E.js +0 -1
  279. package/apps/web/dist/assets/member-directory-BiCE8DRq.js +0 -1
  280. package/apps/web/dist/assets/popover-BhzZ0U1d.js +0 -1
  281. package/apps/web/dist/assets/project-label-provider-9L7Uts3_.js +0 -1
  282. package/apps/web/dist/assets/project-settings-Q7Q9Reec.js +0 -1
  283. package/apps/web/dist/assets/rotate-ccw-sjyLwLLy.js +0 -1
  284. package/apps/web/dist/assets/settings-B6qD6q1J.js +0 -1
  285. package/apps/web/dist/assets/settings-layout-B-AwUIMu.js +0 -1
  286. package/apps/web/dist/assets/switch-D0nFHj6l.js +0 -1
  287. package/apps/web/dist/assets/table-CYZiwo9g.js +0 -1
  288. package/apps/web/dist/assets/ticket-detail-B-3vbHSB.js +0 -2
  289. package/apps/web/dist/assets/ticket-editor-C3d8TZIT.js +0 -1
  290. package/apps/web/dist/assets/ticket-list-LtGGOnwN.js +0 -5
  291. package/apps/web/dist/assets/ticket-tags-2rdmkcJV.js +0 -1
  292. package/apps/web/dist/assets/upload-DXPRzAaa.js +0 -1
  293. package/apps/web/dist/assets/useNavigate-DFohfUD3.js +0 -1
  294. package/apps/web/dist/assets/workspace-settings-D3tCm1vH.js +0 -1
@@ -0,0 +1,25 @@
1
+ # Languages
2
+
3
+ The web and native apps read in 21 languages: Azərbaycan dili (`az-AZ`), Deutsch (`de-DE`), Ελληνικά (`el-GR`), English (`en-US`), Español (`es-ES`), Français (`fr-FR`), हिन्दी (`hi-IN`), Bahasa Indonesia (`id-ID`), Italiano (`it-IT`), 日本語 (`ja-JP`), 한국어 (`ko-KR`), Македонски (`mk-MK`), Nederlands (`nl-NL`), Polski (`pl-PL`), Português (Brasil) (`pt-BR`), Русский (`ru-RU`), Türkçe (`tr-TR`), Українська (`uk-UA`), Tiếng Việt (`vi-VN`), 简体中文 (`zh-CN`), and 繁體中文 (`zh-TW`).
4
+
5
+ Choose one under **Settings → Preferences → Language** on the web or **Settings → Language** in the native app. **System default** follows the browser's or device's preferred languages: an exact match, then the same language (Traditional Chinese scripts and regions choose `zh-TW`), then English. The web choice belongs to the browser and also applies to the sign-in page; the native choice belongs to the device. Signing out or changing servers keeps it.
6
+
7
+ Only presentation changes. API values, saved filters and views, URLs, ticket content, names, keys, and identifiers stay as they are. Dates, times, numbers, relative times, calendar month and weekday names, and the first day of the week follow the interface language; **Week starts on** defaults to **Language default** and can still be set to Sunday, Monday, or Saturday. Error codes the server explains in English (`forbidden`, `not_found`, `version_conflict`, `claim_conflict`, `rate_limited`, and others listed in `translatedErrors`) read in the interface language; any other server message is shown as sent. Client-side validation messages come from Zod's catalog for the language. Rendered Markdown and ticket titles take their direction from their own text, so right-to-left content stays readable in any language.
8
+
9
+ The server, MCP tools, notifications it sends, and the API documentation stay in English.
10
+
11
+ ## Catalogs
12
+
13
+ `packages/contracts/src/i18n` holds the locale list (`locales`, `localeDetails`), the i18next instance, `applyLocale`, the formatters (`formatDate`, `dateFormat`, `formatNumber`, `formatRelativeTime`, `firstWeekday`), and one directory per locale. Each directory has the same sections: `common` (contract values and generic actions shared by web and native), `shell`, `ticket`, `detail`, `settings`, and `admin` for the web, and `native` for the native app. English (`en-US`) is the source and the fallback for any missing key; other catalogs load only when chosen.
14
+
15
+ Contract label tables such as `stateLabels`, `priorityLabels`, `kindLabels`, `difficultyLabels`, `roleLabels`, `permissionLabels`, `relationChoices`, and `eventLabels` read the active language each time an entry is read, so web and native share one wording and the server keeps English. `apps/web/src/lib/locale.tsx` and `apps/mobile/src/locale.tsx` save the choice, load the catalog (and on the web the calendar wording), and remount the app below `LocaleRoot` when the language changes.
16
+
17
+ ## Adding strings
18
+
19
+ Call `t("section.group.key", values)` from `@kanvil/contracts/i18n` and add the English text to that section in `en-US`, then to every other locale. Write complete sentences with `{{placeholders}}`; never join translated fragments. Use `{{label, lowercase}}` where English lowercases a label mid-sentence. Plurals use i18next keys with `count`: English has `_one` and `_other`, and each locale has exactly the categories its plural rules use (for example Russian `_one`, `_few`, `_many`, `_other`; Japanese only `_other`). Text with embedded elements uses `Trans` with named tags such as `<link>`. Text built at module load must read the language at render time instead.
20
+
21
+ `pnpm check` runs `packages/contracts/src/i18n/i18n.test.ts`, which fails when a locale lacks or adds a key, has the wrong plural categories, changes a placeholder or tag, or leaves a value empty, and checks the locale resolution, fallback, label, format, and error behavior.
22
+
23
+ ## Adding a locale
24
+
25
+ Add its identifier to `locales` with its name and CLDR first weekday in `localeDetails`, a directory with every section, a loader in `catalogs`, its Zod messages in `validation`, and its calendar wording in `apps/web/src/lib/locale.tsx`. The catalog test then requires every key and plural form.
package/docs/plan.md CHANGED
@@ -10,7 +10,7 @@ Judge the product by how reliably agents can discover work, obtain complete cont
10
10
 
11
11
  Build a self-hosted ticketing system with web and native mobile apps, local login, PocketID-compatible OIDC, a documented HTTP API, durable realtime events, and MCP tools.
12
12
 
13
- Start with a fresh workspace and native ticket storage. Kaneo compatibility, data import, and changes to T3 Code or Factory are outside this project. External consumers receive documented interfaces and example clients maintained in this repository.
13
+ Start with a fresh workspace and native ticket storage. Projects export to a versioned JSON bundle and import from one into a new project through a previewed, restart-safe run; sources from other trackers translate into that bundle. Kaneo compatibility beyond such import sources and changes to T3 Code or Factory are outside this project. External consumers receive documented interfaces and example clients maintained in this repository.
14
14
 
15
15
  Use established libraries and the smallest implementation that meets the acceptance criteria. Each ticket operation, permission check, validation rule, and event write has one shared implementation across HTTP and MCP. Web and mobile share contracts and client logic while using platform-appropriate rendering and navigation.
16
16
 
@@ -30,9 +30,13 @@ Pin the latest stable compatible releases during implementation. Reuse existing
30
30
 
31
31
  - First-owner setup, account management, local login, logout, and account recovery.
32
32
  - Closed public registration by default.
33
- - Local email/password and OIDC login available on web and mobile.
33
+ - Local email/password and OIDC login available on web and mobile, plus optional GitHub, Google, and Discord sign-in for linked accounts and emailed sign-in and password-reset codes when SMTP is configured.
34
34
  - PocketID setup through discovery URL, client ID, server-held secret, and documented callback URLs.
35
35
  - Explicit account linking and consistent project authorization across login methods.
36
+ - Custom workspace roles with granular, server-enforced actions, assigned through the member editor and capped by the assigning member's own role and credential scopes.
37
+ - Workspace owners who transfer ownership to another active administrator and delete the workspace after a reviewed impact summary, a recent sign-in, and a typed confirmation.
38
+ - Account deletion by the person or an instance administrator after a reviewed impact summary, a recent sign-in, and a typed email: it removes every way to sign in or act as the account and its personal details, and keeps shared history attributed to a `Deleted account` tombstone.
39
+ - Expiring, revocable email invitations to a workspace or selected projects, accepted once by the account with the invited address; they never open registration.
36
40
  - Secure mobile session storage and tested browser-to-app authentication callbacks.
37
41
  - Revocable credentials with project and operation scopes for unattended consumers.
38
42
  - Authenticated and permission-filtered HTTP, realtime, attachment, and MCP access.
@@ -41,12 +45,16 @@ Validate PocketID mobile login and MCP client authentication early. These checks
41
45
 
42
46
  ## Ticket operations
43
47
 
44
- - Projects and stable ticket keys with permanent links.
48
+ - Projects and stable ticket keys with permanent links. Project administrators archive and restore projects, move them to another workspace they administer with a reviewed access, label, and follow preview, and delete them after a reviewed impact summary; ticket keys never change or get reused.
45
49
  - Titles, Markdown descriptions, acceptance criteria, and attachments.
46
- - Status, priority, kind, difficulty, scopes, labels, and assignment.
50
+ - Status, priority, kind, difficulty, scopes, labels (per project or shared across a workspace), and assignment.
51
+ - Per-project workflow states that administrators add, rename, recolor, reorder, recategorize, and delete with an explicit reassignment. Each maps to one canonical status, which every open, closed, readiness, claim, and filter rule reads, so status-only clients keep working.
52
+ - Typed project custom fields (text, number, date, checkbox, select, and multi-select) that administrators define, order, and edit with required rules and defaults. Definitions are versioned and server-validated; removing a used option needs an explicit destination for its values, so nothing is erased silently.
47
53
  - Parent/child relationships, blockers, related tickets, and duplicate references.
48
- - Comments, activity history, subscriptions, archiving, and deletion behavior.
49
- - Search, filtering, sorting, pagination, and bulk edits.
54
+ - Comments, activity history, subscriptions, duplication, archiving, and deletion behavior.
55
+ - Versioned JSON export of a project's tickets and a previewed import into a new project that resumes after interruption without duplicates and notifies no one.
56
+ - Read-only Linear, Jira (Cloud and Data Center), Trello, Plane, PLANKA, and Kaneo import sources that translate a team, project, or board into the same bundle and disclose what Kanvil cannot hold.
57
+ - Workspace search across projects, tickets, comments, and activity with a results page; any-of and none-of property filters shared by lists, search, and saved views; sorting, pagination, and bulk edits.
50
58
  - Optimistic concurrency checks that prevent silent overwrites.
51
59
  - Idempotent writes that remain safe when a client retries a request.
52
60
 
@@ -79,15 +87,25 @@ Deliver reference consumers and contract tests within Kanvil. External applicati
79
87
 
80
88
  ## Web and mobile
81
89
 
82
- - Web list with readable wrapping titles, adjustable columns, filters, selection, bulk actions, and keyboard navigation.
83
- - Ticket detail view containing requirements, relationships, discussion, attachments, activity, and supplied evidence.
84
- - Project settings, account settings, and notification preferences.
90
+ - Web list with readable wrapping titles, adjustable columns, filters, selection, keyboard navigation, a preview sheet that shows the full ticket detail over the list and opens from every ticket reference in the app, shared public views included, and atomic bulk actions for status, priority, assignee, kind, difficulty, labels (replace or clear), due date (set or clear), archiving or restoring, and deletion. Mixed selections show as mixed, never as the first row's value. Each status section selects as a whole.
91
+ - A server-kept manual order for tickets within a project and projects within a workspace: an explicit Manual sort in the URL and saved views, with drag and drop, keyboard moves, and menu commands across the list, board, and planning views.
92
+ - Project planning view with complete Planned (backlog) and Archived groups, moving planned work to To do, restoring archived tickets, and a way back to active work.
93
+ - Start and due dates on tickets, with read-only Calendar (month) and Timeline (six-week) layouts of a project's filtered tickets, period navigation and Today, and project calendar feeds that administrators share and revoke as iCalendar links. Drag-to-reschedule and dependency editing on the timeline stay out of scope.
94
+ - Ticket detail view containing requirements, relationships, editable links, discussion, attachments, activity, and supplied evidence.
95
+ - Read-only public links that project administrators turn on and off under Project settings, showing anyone with the link the project's unarchived tickets and their requirements, properties, labels, dates, and relationships, without people, discussion, attachments, or coordination details.
96
+ - Ticket composer that can target any writable project and stay open to create several tickets in a row.
97
+ - Custom fields edit through one property component in the composer, detail sidebar, list cells (shown from the Display menu), board cards, and selection toolbar, filter through the shared filter picker, and read on native ticket screens.
98
+ - Comment mentions: typing `@` in a comment offers the project's members and inserts a `mention:` link that renders as "@Name"; mentioned members are notified even when they do not follow the ticket, and the Inbox has a Mentions view.
99
+ - Inbox that opens an update's ticket in the same preview sheet, with its discussion and reply composer, and marks entries read or unread, dismisses them, clears read entries, and marks all read, from the keyboard as well.
100
+ - Home overview of your assigned work, recent activity, and project progress, with a complete My work list across the workspace's projects grouped by due date or project.
101
+ - One settings navigation for account, current workspace, projects, and instance administration (shown only where the server grants access), including personal and notification preferences: Inbox and push, personal channels (email, ntfy, Gotify, signed webhooks) routed per workspace or project, per-category flags, and a due-soon reminder lead, with overdue notices. Project administrators send ticket activity to signed webhooks, Slack, Discord, Mattermost, or Telegram. One outbox delivers all of them. Project administrators also connect GitHub, Gitea, and GitLab repositories through one set of operations and one settings form, with self-managed instance URLs for Gitea and GitLab: signed webhooks attach verified branch, pull request, and issue links to the tickets they name and can move those tickets to a mapped workflow state through the normal versioned update; the outbox checks access and posts optional link comments. Issue sync keeps tickets and issues in step both ways under label-scoped rules that administrators preview before applying; links that lose their labels or change on both sides stop for a reviewed reconciliation, and ambiguous issue creations are never repeated. The `?` help and the `⌘K` palette read one action catalog, so labels and keys match.
85
102
  - Native mobile lists and navigation, ticket editing, comments, attachments, deep links, and notifications.
86
103
  - Live updates while connected, recovery after disconnection, cached reading, and locally saved drafts.
87
104
  - Shared client operations, validation, formatting, design tokens, and status presentation rules.
105
+ - The web and native interfaces in 21 languages from shared catalogs, with a per-browser or per-device language choice; dates, numbers, and the first weekday follow it while API values and ticket content stay unchanged ([languages](localization.md)).
88
106
  - Accessible controls, responsive layouts, useful loading/error states, and explicit connection status.
89
107
 
90
- Start with Markdown editing and an established renderer. Rich-text editing remains an optional scope decision. Defer automatic submission of offline edits and custom workflow designers. Optional external storage, search, and broker adapters are described in [infrastructure](infrastructure.md); the default deployment still requires only PostgreSQL.
108
+ Start with Markdown editing and an established renderer. Markdown fields carry a formatting toolbar with shortcuts, and people who can write a ticket toggle its description and acceptance checklists in place; the stored text stays canonical Markdown. The web app adds an optional Visual mode (Tiptap) to the same fields: formatting and `/` block menus, tables, checklists, highlighted code, Mermaid diagrams, mentions, and inline images and files that use the attachment service, staged until a new ticket exists. Visual mode reads and writes the same Markdown string and leaves text it cannot represent exactly, such as raw HTML or footnotes, in the Markdown editor. Rendered Markdown highlights code, draws Mermaid diagrams in strict mode, and shows embedded images; links to other sites stay links, so viewing a ticket contacts no third party. Native apps keep reading and editing the canonical Markdown. Defer automatic submission of offline edits and visual workflow designers; workflow states are edited as a list in project settings. Optional external storage, search, and broker adapters are described in [infrastructure](infrastructure.md); the default deployment still requires only PostgreSQL.
91
109
 
92
110
  ## Self-hosting and verification
93
111
 
@@ -1,6 +1,6 @@
1
1
  # Self-hosting
2
2
 
3
- Kanvil runs as one application service and PostgreSQL 18. Tickets, comments, authentication, durable events, and attachment bytes live in PostgreSQL. PocketID is optional; local login remains available alongside OIDC.
3
+ Kanvil runs as one application service and PostgreSQL 18. Tickets, comments, authentication, durable events, and attachment bytes live in PostgreSQL. PocketID is optional; local login remains available alongside OIDC, GitHub, Google, Discord, and emailed codes.
4
4
 
5
5
  ## Install from npm
6
6
 
@@ -123,15 +123,54 @@ services:
123
123
 
124
124
  Native devices must also trust that authority. Never mount the authority's private key.
125
125
 
126
+ ## GitHub, Google, and Discord
127
+
128
+ Each built-in provider turns on when both of its values are set, and appears on the web and native sign-in screens and in account settings in that order, after the OIDC provider. Register the matching callback URL with each provider's OAuth app:
129
+
130
+ ```text
131
+ https://kanvil.example.com/api/auth/callback/github
132
+ https://kanvil.example.com/api/auth/callback/google
133
+ https://kanvil.example.com/api/auth/callback/discord
134
+ ```
135
+
136
+ ```dotenv
137
+ GITHUB_CLIENT_ID=
138
+ GITHUB_CLIENT_SECRET=
139
+ GOOGLE_CLIENT_ID=
140
+ GOOGLE_CLIENT_SECRET=
141
+ DISCORD_CLIENT_ID=
142
+ DISCORD_CLIENT_SECRET=
143
+ ```
144
+
145
+ These providers only sign in accounts that linked them: sign in another way, then link the provider in account settings. They never create an account or claim one with the same email, whatever **Automatically create users from SSO** says, and the provider must have verified the email. GitHub and Google sign-in uses state and PKCE; Discord uses state. Google's ID token is checked against Google's signing keys, issuer, audience, and age, and posted ID tokens are refused.
146
+
147
+ ## Email codes and password reset
148
+
149
+ With `SMTP_URL` and `SMTP_FROM` set and password sign-in enabled, the sign-in screens offer **Email me a sign-in code** and **Forgot password?**. Both email a six-digit code and a link that opens the page the request started on, such as an invitation, with that code filled in. A code works once, expires after 10 minutes, and is discarded after three wrong attempts. Asking again while a code is valid mails the same code and restarts its 10 minutes, so a resend never invalidates a code already received; codes are stored encrypted with `BETTER_AUTH_SECRET`. Codes reach existing, enabled accounts only: an unknown, disabled, or deleted address gets the same answer and no email, and each address receives at most three codes per 15 minutes per application process (an email the relay refuses does not count). Resetting a password signs out every session of the account. Deleting an account or changing its address discards its outstanding codes, and an account under a ban cannot use a code, whenever it was issued.
150
+
151
+ The first code sign-in to an account whose email was never verified removes the account's password, linked providers, and sessions before signing in, so access that predates proof of the mailbox does not carry over. Accounts created by an administrator start unverified; a password reset verifies the email without removing anything.
152
+
153
+ Better Auth also limits these endpoints per client IP when `NODE_ENV=production` (three requests per minute for sending codes). Behind a reverse proxy, forward the client address in `X-Forwarded-For`.
154
+
126
155
  ## Instance administration
127
156
 
128
- Administrators can edit the instance name and description, manage accounts, and configure local/S3 file storage, PostgreSQL/Elasticsearch search, and PostgreSQL/RabbitMQ event delivery in Administration. See [optional infrastructure](infrastructure.md) for deployment variables, adapter interfaces, recovery behavior, and S3 backup requirements. OIDC, public URL, and push credentials remain deployment settings.
157
+ Administrators can edit the instance name and description, manage accounts, review every workspace with its administrators and member/project counts (Administration → Workspaces) and manage its members without joining it, and configure local/S3 file storage, PostgreSQL/Elasticsearch search, and PostgreSQL/RabbitMQ event delivery in Administration. See [optional infrastructure](infrastructure.md) for deployment variables, adapter interfaces, recovery behavior, and S3 backup requirements. OIDC, public URL, and push credentials remain deployment settings.
158
+
159
+ ## Optional outbound notifications
160
+
161
+ People can add notification channels in Settings → Notifications (ntfy, Gotify, a signed webhook, or email), and project administrators can send ticket activity to Slack, Discord, Mattermost, Telegram, or a signed webhook from Project settings → Integrations. Nothing is sent until someone configures a channel or destination; see [the API reference](api.md#notification-channels-and-project-destinations) for routing, signing, retries, and health.
162
+
163
+ - Email channels need an SMTP relay: set `SMTP_URL` (for example `smtp://user:password@mail.example.com:587`, or `smtps://` for implicit TLS) and `SMTP_FROM` (for example `Kanvil <kanvil@example.com>`). Without them the email option is hidden.
164
+ - Outbound HTTP refuses loopback and private-network addresses. Set `KANVIL_DELIVERY_ALLOW_PRIVATE=true` when channels must reach services on your own network, such as a LAN ntfy or Gotify. Only enable it when everyone who can add a channel or destination may reach those hosts.
165
+ - Project administrators can also connect GitHub, Gitea, and GitLab repositories under Project settings → Integrations. The code host must reach `KANVIL_URL` to deliver webhooks; set `KANVIL_GITHUB_API_URL` for GitHub Enterprise Server. Gitea and GitLab connections name their own instance URL; a self-managed instance on a loopback or private address also needs `KANVIL_DELIVERY_ALLOW_PRIVATE=true`. See [repository connections](api.md#repository-connections).
166
+ - Workspace writers can import Linear teams, Jira, Plane, and Kaneo projects, and Trello and PLANKA boards with their own credentials, which are never stored. The server must reach `api.linear.app`, `api.trello.com`, or the tracker's site; a self-hosted Jira, Plane, PLANKA, or Kaneo on a private network needs `KANVIL_DELIVERY_ALLOW_PRIVATE=true`. Plane and Kaneo limit requests per minute, so reading a large project can take minutes: let a reverse proxy keep `/api/v1/workspaces/*/imports/source` open that long. See [export and import](api.md#export-and-import).
167
+ - Channel and destination settings and repository tokens and webhook secrets, including signing secrets, are encrypted with a key derived from `BETTER_AUTH_SECRET`. Keep that secret with your backups; without it the saved settings cannot be decrypted and must be entered again.
129
168
 
130
169
  ## Optional mobile push
131
170
 
132
171
  Set `KANVIL_PUSH_ENABLED=true` to enable the Expo push transport. If the Expo project has push access-token security enabled, also set its server-held `EXPO_ACCESS_TOKEN`. Recreate the app after changing configuration. A signed mobile build must contain the public Expo project ID and have APNs/FCM credentials configured; see [mobile setup](mobile.md). Accounts opt in through Settings and register each device separately.
133
172
 
134
- Push is disabled by default. Ticket storage, login, Inbox, realtime, and MCP work without Expo services. Push messages use a generic update notice and ticket identifiers, without ticket titles, descriptions, comments, or evidence. The database outbox commits with each subscribed event, checks current account/project/session/subscription access before every send, retries failures, and checks Expo receipts. Expired login sessions and explicit session revocation remove their device registrations. A failed or interrupted transport may deliver duplicates; queued notices expire after one day. Delivery status is available in the `push_deliveries` table. Backups contain device tokens, so protect them alongside authentication state.
173
+ Push is disabled by default. Setting `KANVIL_PUSH_ENABLED=false` again also stops sends to devices registered earlier; their queued notices end as `push_disabled`. Ticket storage, login, Inbox, realtime, and MCP work without Expo services. Push messages use a generic update or mention notice and ticket identifiers, without ticket titles, descriptions, comments, or evidence. The database outbox commits with each subscribed event, checks current account/project/session/subscription access before every send (a mention needs no subscription), retries failures, and checks Expo receipts. Expired login sessions and explicit session revocation remove their device registrations. A failed or interrupted transport may deliver duplicates; queued notices expire after one day. Delivery status is available in the `deliveries` table. Backups contain device tokens, so protect them alongside authentication state.
135
174
 
136
175
  ## Backup
137
176
 
@@ -187,7 +226,7 @@ Check login, tickets, attachment downloads, and consumer access before deleting
187
226
 
188
227
  Administration → Authentication controls **Email and password sign-in** and **Automatically create users from SSO** independently. Defaults keep password sign-in enabled and SSO provisioning disabled. Public email signup is always closed. Changes apply to subsequent authentication requests without restarting; sessions and scoped credentials keep their existing lifecycle.
189
228
 
190
- Before disabling password sign-in, configure OIDC and explicitly link the acting administrator's provider account in User settings. A binding must match the configured provider's issuer and client ID; relink the administrator after changing either. New SSO users require a provider-verified email and receive the ordinary user role with no workspace or project membership. A matching local email requires explicit account linking. Existing linked users can sign in with provisioning disabled. While password sign-in is disabled, users must retain at least one binding for the configured provider; enable password sign-in before unlinking the last one.
229
+ Disabling password sign-in also turns off email codes and password reset. Before disabling it, configure OIDC and explicitly link the acting administrator's provider account in User settings. A binding must match the configured provider's issuer and client ID; relink the administrator after changing either. New SSO users require a provider-verified email and receive the ordinary user role with no workspace or project membership. A matching local email requires explicit account linking. Existing linked users can sign in with provisioning disabled. While password sign-in is disabled, users must retain at least one binding for the configured provider; enable password sign-in before unlinking the last one.
191
230
 
192
231
  ## Account recovery
193
232
 
@@ -197,7 +236,7 @@ A host operator can replace an existing account's local password:
197
236
  docker compose exec app node dist/recover.mjs --email admin@example.com
198
237
  ```
199
238
 
200
- The password is entered privately. For local source development, use `pnpm account:recover --email admin@example.com`. The command uses Better Auth's password format and revokes that account's sessions. Its role, linked OIDC account, and API credentials are retained. Revoke agent credentials separately if an account was compromised. Passwords are never accepted as command-line arguments.
239
+ The password is entered privately. For local source development, use `pnpm account:recover --email admin@example.com`. The command uses Better Auth's password format and revokes that account's sessions. Its role, linked OIDC account, and API credentials are retained. Revoke agent credentials separately if an account was compromised. A deleted account cannot be recovered: its tombstone has no address to match. Passwords are never accepted as command-line arguments.
201
240
 
202
241
  Password recovery alone does not enable password sign-in. If the IdP is unavailable, a host operator can recover an active administrator and explicitly re-enable password sign-in with `--enable-password-sign-in` on the same recovery command. For example, `pnpm account:recover --email admin@example.com --enable-password-sign-in` for source development, or append that flag to the Docker command above. This updates the persisted policy and revokes the recovered account's sessions atomically, without restarting. Sign in locally, repair the deployment's OIDC settings, verify linking and SSO login, then disable passwords again in Administration. Keep host access and an active local administrator recovery account available.
203
242
 
package/docs/themes.md CHANGED
@@ -33,6 +33,6 @@ Old built-in selections resolve to the corresponding named palette. The former d
33
33
 
34
34
  Tickets are grouped into collapsible status sections with counts. Ordering applies within each status. All matching tickets are shown, with no pagination or Load more controls.
35
35
 
36
- Ticket lists default to Compact rows. **Display → Row spacing → Comfortable** adds room without hiding titles or labels. **Display → Label display → All labels** shows every full label and scope inline, wrapping as needed. Property visibility, row spacing, and label display are personal browser preferences. Search, filters, and ordering remain shareable through the URL and saved views. Touch controls retain their larger targets on phones.
36
+ Ticket lists default to Compact rows. **Display → Row spacing → Comfortable** adds room without hiding titles or labels. **Display → Label display → All labels** shows every full label and scope inline, wrapping as needed. Property visibility, row spacing, label display, and grouping are personal browser preferences, also under **Settings → Preferences** with the first day of the week for date pickers and the sidebar state on launch. Both places change the same values; **Reset preferences** restores the defaults. Search, filters, and ordering remain shareable through the URL and saved views. Touch controls retain their larger targets on phones.
37
37
 
38
38
  The ticket list uses one view/action toolbar under the location bar. The project name appears once in the location bar, beside its settings cog. Open the magnifying glass for search and the view dropdown for saved views, saving the current filter, deleting a selected saved view, or selecting all displayed tickets. On narrow screens, metadata shares a line instead of repeating property headings. Label/scope previews show two tags on wider layouts and one on narrow layouts; opening a preview reveals every full tag. Ticket titles remain unclipped.
@@ -34,7 +34,7 @@ No physical-device installation or runtime validation has been performed. Androi
34
34
 
35
35
  Real APNs/FCM delivery and notification-tap routing remain unvalidated. They require an Expo project and authorized push/signing configuration. Push is optional and disabled by default; ticket storage, login, Inbox, realtime, and MCP work without it.
36
36
 
37
- The reference mirror refreshes a full project snapshot when changes arrive. It is an example of consistent recovery, not an execution scheduler. Apps retain explicit local drafts; offline edits are not automatically submitted. Rich-text editing, custom workflow designers, and separate search/message-broker services remain outside the agreed initial scope.
37
+ The reference mirror refreshes a full project snapshot when changes arrive. It is an example of consistent recovery, not an execution scheduler. Apps retain explicit local drafts; offline edits are not automatically submitted. Custom workflow designers and separate search/message-broker services remain outside the agreed initial scope; the web Visual editor stores canonical Markdown.
38
38
 
39
39
  ## Interface redesign
40
40
 
@@ -2,14 +2,26 @@
2
2
 
3
3
  A Kanvil instance hosts accounts and deployment settings. Workspaces group projects and have their own name, URL key, and members. Personal settings belong to the account. Instance administrators can administer every workspace and project; workspace administrators cannot administer the instance or other workspaces.
4
4
 
5
- Workspace roles reuse the existing Read only, Can edit, and Admin roles. Workspace-visible projects inherit workspace roles. Private projects require explicit project membership, except that workspace administrators can manage all projects in their workspace. Explicit project roles override inherited roles, except for workspace administrators. A person with only project membership can see that project and its workspace identity without receiving workspace-wide access.
5
+ Every workspace starts with the Read only, Can edit, and Admin roles. Administrators add custom roles under Workspace settings → Roles, each a chosen set of actions: edit tickets, delete tickets, manage projects, members, invitations, sharing, or the workspace. Members get any of them through the same member editor, on the workspace or on one project. Nobody grants an action their own role lacks, only administrators grant Admin, and a role held by anyone is deleted only after choosing the role its members move to. Clients show what the server reports a role allows, never what its name suggests. Workspace-visible projects inherit workspace roles. Private projects require explicit project membership, except that workspace administrators can manage all projects in their workspace; a custom role never reaches private projects through the workspace. Explicit project roles override inherited roles, except for workspace administrators. A person with only project membership can see that project and its workspace identity without receiving workspace-wide access.
6
6
 
7
- Removing workspace membership also removes that person's explicit memberships in the workspace's projects. Keep at least one workspace administrator. Project-scoped API keys remain bounded to their configured projects and cannot administer an entire workspace. Ticket and project prefixes remain unique across the instance, preserving existing links and key-based API lookups.
7
+ Workspace administrators can also invite an email address that has no access yet. An invitation fixes its role and covers either the whole workspace or selected projects, and its link works once, before it expires, for the account with that email. Kanvil account emails are set by instance administrators or verified by the OIDC provider, and people cannot change their own, so the email match identifies the recipient. Accepting checks again that the sender still administers the workspace, grants only the invited access to projects that still exist, and keeps any higher role the person already has. Invitations follow the instance's sign-in policy: they never create an account or open registration. The link is emailed when SMTP is configured and can always be copied from the dialog shown after sending; resending replaces it.
8
+
9
+ A project moves to another workspace only when the caller administers both. Direct project members keep their roles; access inherited from the old workspace ends and the destination's applies, which the move preview lists person by person. See [the API reference](api.md#project-lifecycle).
10
+
11
+ Every workspace has one owner, an active administrator. The owner, or an instance administrator, transfers ownership to another active administrator and deletes the workspace; the previous owner stays an administrator. The owner cannot be removed, demoted, disabled, or have their account deleted until ownership moves, so a workspace never loses its owner silently. Deleting a workspace needs a sign-in within the last 15 minutes and the typed URL key, lists every project and what goes with it first, and refuses while any ticket is claimed. Its projects are deleted as project deletion does, its memberships, invitations, and shared labels go, and accounts stay. See [the API reference](api.md#workspace-ownership-and-deletion).
12
+
13
+ When ownership was introduced, each existing workspace went to its earliest-created active administrator member, ties broken by account ID. A workspace without one has no owner until an instance administrator transfers it to an active administrator.
14
+
15
+ Removing workspace membership also removes that person's explicit memberships in the workspace's projects. Keep at least one workspace administrator. Project-scoped API keys remain bounded to their configured projects and cannot administer an entire workspace. Ticket and project prefixes remain unique across the instance. A project administrator can change a prefix and move tickets between writable projects of one workspace; earlier prefixes stay reserved and earlier keys keep resolving, so existing links and key-based API lookups keep working without reaching past current access.
8
16
 
9
17
  Existing projects are assigned to a default workspace and remain private. Existing project membership is retained; only instance administrators gain workspace administration automatically. Existing API calls that omit a workspace choose an accessible writable workspace; when none exists, project creation creates a personal workspace for the caller. New web-created projects select their workspace explicitly and offer workspace or private access.
10
18
 
11
19
  Workspace operations use the same operation registry, authorization, transaction lock, idempotency receipts, and HTTP/MCP implementations as projects. Realtime visibility continues to derive from accessible projects, so revoked membership stops event delivery. Workspace changes invalidate project consumers through project events; an empty workspace also refreshes in browser queries on focus.
12
20
 
21
+ Workspace administrators can define labels every project in the workspace uses, beside each project's own labels. Projects show workspace labels read-only in their label settings; renaming or deleting one updates every project's tickets and saved views together. See [the API reference](api.md) for conflict and adoption rules.
22
+
23
+ Anyone who can read a project can export its tickets as JSON from the project's settings. Workspace writers import such a file, or a Linear team, a Jira, Plane, or Kaneo project, or a Trello or PLANKA board, into a new project from the workspace's settings. For a tracker, connect with what it asks for (an API key or token, a site address, or a PLANKA password), which is used only while the form reads the source and is never saved, then pick the team, project, or board and whether to include comments. The preview lists what maps, what changes, and what the import leaves out before anything is written, and the import continues in the background, resuming after a restart. See [Export and import](api.md#export-and-import).
24
+
13
25
  Project icons can use a bundled, searchable open-source icon collection or a normalized image upload. Uploaded bytes use the existing blob storage adapter and authenticated project access. Referenced icons must remain excluded from orphan cleanup, and backup/restore retains them with other blob objects.
14
26
 
15
27
  ## Verification
@@ -17,5 +29,9 @@ Project icons can use a bundled, searchable open-source icon collection or a nor
17
29
  - Upgrade populated databases without widening private project access or changing ticket identifiers.
18
30
  - Test workspace and private-project isolation, inherited versus explicit roles, scoped API keys, removal, last-admin guards, and idempotent writes through the shared domain.
19
31
  - Exercise workspace discovery through HTTP and MCP and access revocation through realtime replay and image routes.
32
+ - Test shared label catalogs, access-filtered counts, cross-project renames and deletions, claims, and same-name adoption.
33
+ - Test ownership transfer, owner removal, demotion, and account-disable guards, concurrent transfer and removal, and workspace deletion previews, blockers, recent sign-in, and tombstones.
34
+ - Test invitation creation, resend, revocation, expiry, email mismatch, sender demotion, concurrent acceptance, and the acceptance page.
35
+ - Test custom roles: seeded roles on upgraded memberships, granular actions, credential ceilings, grants beyond the actor, immediate revocation, stale edits, reserved names, deletion with reassignment, private projects, and owner and last-administrator guards.
20
36
  - Test workspace switching, deep links, settings navigation, member search and role changes, icon selection/upload/removal, and account administration in browser workflows.
21
37
  - Review light/dark desktop and phone layouts with real content. Keep publication separate from local verification.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maudecode/kanvil",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Open-source, self-hosted ticketing for agents and people.",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -26,23 +26,27 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@aws-sdk/client-s3": "3.1152.0",
29
- "@better-auth/api-key": "1.7.8",
30
- "@better-auth/cimd": "1.7.8",
31
- "@better-auth/drizzle-adapter": "1.7.8",
32
- "@better-auth/expo": "1.7.8",
33
- "@better-auth/mcp": "1.7.8",
29
+ "@better-auth/api-key": "1.7.10",
30
+ "@better-auth/cimd": "1.7.10",
31
+ "@better-auth/drizzle-adapter": "1.7.10",
32
+ "@better-auth/expo": "1.7.10",
33
+ "@better-auth/mcp": "1.7.10",
34
34
  "@hono/node-server": "2.1.5",
35
35
  "@hono/zod-openapi": "1.6.3",
36
- "@iconify-json/lucide": "1.2.144",
36
+ "@iconify-json/lucide": "1.2.145",
37
37
  "@inquirer/password": "5.2.3",
38
38
  "@modelcontextprotocol/server": "2.3.1",
39
39
  "amqplib": "2.2.0",
40
- "better-auth": "1.7.8",
40
+ "better-auth": "1.7.10",
41
41
  "drizzle-orm": "0.45.4",
42
42
  "expo-server-sdk": "7.2.0",
43
43
  "hono": "4.13.13",
44
+ "i18next": "26.5.2",
44
45
  "jose": "6.2.12",
46
+ "mdast-util-from-markdown": "2.1.0",
47
+ "nodemailer": "10.1.2",
45
48
  "pg": "8.23.1",
49
+ "turndown": "7.2.4",
46
50
  "zod": "4.6.7"
47
51
  }
48
52
  }