@jini-ai/admin 0.3.10 → 0.4.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 (399) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +71 -37
  3. package/dist/agent-plugins/adapters/http.d.ts +7 -0
  4. package/dist/agent-plugins/adapters/http.js +15 -0
  5. package/dist/agent-plugins/adapters/memory.d.ts +8 -0
  6. package/dist/agent-plugins/adapters/memory.js +25 -0
  7. package/dist/agent-plugins/agent-plugins.module.d.ts +51 -0
  8. package/dist/agent-plugins/agent-plugins.module.js +6 -0
  9. package/dist/agent-plugins/conformance/agent-plugins-api.conformance.d.ts +12 -0
  10. package/dist/agent-plugins/conformance/agent-plugins-api.conformance.js +47 -0
  11. package/dist/agent-plugins/controllers/agent-plugin-files.controller.d.ts +20 -0
  12. package/dist/agent-plugins/controllers/agent-plugin-files.controller.js +43 -0
  13. package/dist/agent-plugins/controllers/agent-plugins.controller.d.ts +25 -0
  14. package/dist/agent-plugins/controllers/agent-plugins.controller.js +91 -0
  15. package/dist/agent-plugins/index.d.ts +9 -0
  16. package/dist/agent-plugins/index.js +9 -0
  17. package/dist/agent-plugins/messages.en.d.ts +23 -0
  18. package/dist/agent-plugins/messages.en.js +14 -0
  19. package/dist/agent-plugins/models.d.ts +57 -0
  20. package/dist/agent-plugins/models.js +2 -0
  21. package/dist/agent-plugins/package-file-tree.d.ts +111 -0
  22. package/dist/agent-plugins/package-file-tree.js +188 -0
  23. package/dist/agent-plugins/ports.d.ts +18 -0
  24. package/dist/agent-plugins/ports.js +3 -0
  25. package/dist/agent-plugins/react/components/AgentPluginFileContent.d.ts +5 -0
  26. package/dist/agent-plugins/react/components/AgentPluginFileContent.js +9 -0
  27. package/dist/agent-plugins/react/components/AgentPluginFileTree.d.ts +9 -0
  28. package/dist/agent-plugins/react/components/AgentPluginFileTree.js +7 -0
  29. package/dist/agent-plugins/react/components/AgentPluginInspector.d.ts +3 -0
  30. package/dist/agent-plugins/react/components/AgentPluginInspector.js +11 -0
  31. package/dist/agent-plugins/react/components/AgentPluginListPanel.d.ts +6 -0
  32. package/dist/agent-plugins/react/components/AgentPluginListPanel.js +10 -0
  33. package/dist/agent-plugins/react/components/AgentPluginRow.d.ts +5 -0
  34. package/dist/agent-plugins/react/components/AgentPluginRow.js +8 -0
  35. package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.d.ts +90 -0
  36. package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.js +74 -0
  37. package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.d.ts +67 -0
  38. package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.js +50 -0
  39. package/dist/agent-plugins/react/hooks/AgentPluginRow.hooks.d.ts +55 -0
  40. package/dist/agent-plugins/react/hooks/AgentPluginRow.hooks.js +6 -0
  41. package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.d.ts +64 -0
  42. package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.js +39 -0
  43. package/dist/agent-plugins/react/hooks/AgentPluginsPorts.hooks.d.ts +7 -0
  44. package/dist/agent-plugins/react/hooks/AgentPluginsPorts.hooks.js +10 -0
  45. package/dist/agent-plugins/react/hooks/MarketplaceTab.hooks.d.ts +6 -0
  46. package/dist/agent-plugins/react/hooks/MarketplaceTab.hooks.js +3 -0
  47. package/dist/agent-plugins/react/index.d.ts +245 -0
  48. package/dist/agent-plugins/react/index.js +13 -0
  49. package/dist/agent-plugins/react/pages/AgentPluginsPage.d.ts +4 -0
  50. package/dist/agent-plugins/react/pages/AgentPluginsPage.js +12 -0
  51. package/dist/agent-plugins/react/tabs/DownloadedTab.d.ts +4 -0
  52. package/dist/agent-plugins/react/tabs/DownloadedTab.js +5 -0
  53. package/dist/agent-plugins/react/tabs/InstalledTab.d.ts +4 -0
  54. package/dist/agent-plugins/react/tabs/InstalledTab.js +5 -0
  55. package/dist/agent-plugins/react/tabs/MarketplaceTab.d.ts +4 -0
  56. package/dist/agent-plugins/react/tabs/MarketplaceTab.js +10 -0
  57. package/dist/agent-plugins/rules.d.ts +33 -0
  58. package/dist/agent-plugins/rules.js +51 -0
  59. package/dist/browser/index.d.ts +1 -0
  60. package/dist/browser/index.js +1 -0
  61. package/dist/browser/navigation.d.ts +19 -4
  62. package/dist/browser/navigation.js +8 -8
  63. package/dist/browser/shell-navigation.d.ts +12 -0
  64. package/dist/browser/shell-navigation.js +16 -0
  65. package/dist/contracts/credential-management.d.ts +8 -0
  66. package/dist/contracts/credential-management.js +3 -0
  67. package/dist/contracts/media-picker.d.ts +17 -0
  68. package/dist/contracts/media-picker.js +5 -0
  69. package/dist/contracts/playground-render-target.d.ts +18 -0
  70. package/dist/contracts/playground-render-target.js +3 -0
  71. package/dist/core/entities/rules.d.ts +138 -0
  72. package/dist/core/entities/rules.js +344 -0
  73. package/dist/core/gated/types.d.ts +8 -4
  74. package/dist/core/index.d.ts +4 -0
  75. package/dist/core/index.js +1 -0
  76. package/dist/core/manifest/rules.d.ts +24 -6
  77. package/dist/core/manifest/rules.js +12 -11
  78. package/dist/core/module/controller-store.d.ts +22 -0
  79. package/dist/core/module/controller-store.js +32 -0
  80. package/dist/core/module/create-admin.d.ts +41 -0
  81. package/dist/core/module/create-admin.js +187 -0
  82. package/dist/core/module/define-admin-module.d.ts +4 -0
  83. package/dist/core/module/define-admin-module.js +5 -0
  84. package/dist/core/module/index.d.ts +7 -0
  85. package/dist/core/module/index.js +4 -0
  86. package/dist/core/module/token.d.ts +19 -0
  87. package/dist/core/module/token.js +4 -0
  88. package/dist/core/module/types.d.ts +79 -0
  89. package/dist/core/module/types.js +2 -0
  90. package/dist/core/permissions/rules.d.ts +4 -1
  91. package/dist/core/permissions/rules.js +1 -1
  92. package/dist/core/ports/analytics.d.ts +1 -1
  93. package/dist/core/ports/auth.d.ts +2 -2
  94. package/dist/core/ports/comments.d.ts +9 -6
  95. package/dist/core/ports/database.d.ts +13 -10
  96. package/dist/core/ports/entities.d.ts +302 -0
  97. package/dist/core/ports/entities.js +47 -0
  98. package/dist/core/ports/forms.d.ts +19 -7
  99. package/dist/core/ports/identity.d.ts +42 -17
  100. package/dist/core/ports/index.d.ts +2 -0
  101. package/dist/core/ports/integrations.d.ts +9 -4
  102. package/dist/core/ports/media.d.ts +16 -7
  103. package/dist/core/ports/members.d.ts +7 -3
  104. package/dist/core/ports/menus.d.ts +43 -0
  105. package/dist/core/ports/menus.js +43 -0
  106. package/dist/core/ports/plugins.d.ts +3 -2
  107. package/dist/core/ports/recovery.d.ts +10 -6
  108. package/dist/core/ports/redirects.d.ts +17 -7
  109. package/dist/core/ports/seo.d.ts +12 -6
  110. package/dist/core/ports/shell.d.ts +41 -0
  111. package/dist/core/ports/shell.js +2 -0
  112. package/dist/core/ports/workspace.d.ts +3 -3
  113. package/dist/core/routing/rules.d.ts +17 -4
  114. package/dist/core/routing/rules.js +4 -4
  115. package/dist/core/transport/errors.d.ts +13 -4
  116. package/dist/core/transport/errors.js +4 -4
  117. package/dist/core/transport/http.d.ts +26 -16
  118. package/dist/core/transport/http.js +59 -21
  119. package/dist/core/transport/types.d.ts +26 -14
  120. package/dist/core/transport/types.js +9 -7
  121. package/dist/media/adapters/http.d.ts +27 -0
  122. package/dist/media/adapters/http.js +44 -0
  123. package/dist/media/adapters/memory.d.ts +11 -0
  124. package/dist/media/adapters/memory.js +139 -0
  125. package/dist/media/conformance/media-api.conformance.d.ts +7 -0
  126. package/dist/media/conformance/media-api.conformance.js +69 -0
  127. package/dist/media/controllers/edit-media.controller.d.ts +24 -0
  128. package/dist/media/controllers/edit-media.controller.js +69 -0
  129. package/dist/media/controllers/library.controller.d.ts +47 -0
  130. package/dist/media/controllers/library.controller.js +173 -0
  131. package/dist/media/controllers/providers.controller.d.ts +30 -0
  132. package/dist/media/controllers/providers.controller.js +76 -0
  133. package/dist/media/html-attributes.d.ts +82 -0
  134. package/dist/media/html-attributes.js +204 -0
  135. package/dist/media/index.d.ts +12 -0
  136. package/dist/media/index.js +9 -0
  137. package/dist/media/media.module.d.ts +83 -0
  138. package/dist/media/media.module.js +43 -0
  139. package/dist/media/messages.en.d.ts +24 -0
  140. package/dist/media/messages.en.js +24 -0
  141. package/dist/media/models.d.ts +72 -0
  142. package/dist/media/models.js +2 -0
  143. package/dist/media/ports.d.ts +75 -0
  144. package/dist/media/ports.js +7 -0
  145. package/dist/media/react/components/EditMediaPanel.d.ts +3 -0
  146. package/dist/media/react/components/EditMediaPanel.js +10 -0
  147. package/dist/media/react/components/MediaCard.d.ts +5 -0
  148. package/dist/media/react/components/MediaCard.js +17 -0
  149. package/dist/media/react/components/MediaDialog.d.ts +3 -0
  150. package/dist/media/react/components/MediaDialog.js +8 -0
  151. package/dist/media/react/components/MediaGrid.d.ts +4 -0
  152. package/dist/media/react/components/MediaGrid.js +8 -0
  153. package/dist/media/react/components/MediaIcons.d.ts +14 -0
  154. package/dist/media/react/components/MediaIcons.js +39 -0
  155. package/dist/media/react/components/MediaLightbox.d.ts +5 -0
  156. package/dist/media/react/components/MediaLightbox.js +12 -0
  157. package/dist/media/react/components/MediaPicker.d.ts +3 -0
  158. package/dist/media/react/components/MediaPicker.js +10 -0
  159. package/dist/media/react/components/MediaPurgeDialog.d.ts +4 -0
  160. package/dist/media/react/components/MediaPurgeDialog.js +9 -0
  161. package/dist/media/react/components/UploadButton.d.ts +3 -0
  162. package/dist/media/react/components/UploadButton.js +8 -0
  163. package/dist/media/react/hooks/EditMediaPanel.hooks.d.ts +84 -0
  164. package/dist/media/react/hooks/EditMediaPanel.hooks.js +105 -0
  165. package/dist/media/react/hooks/LibraryTab.hooks.d.ts +103 -0
  166. package/dist/media/react/hooks/LibraryTab.hooks.js +164 -0
  167. package/dist/media/react/hooks/MediaCard.hooks.d.ts +79 -0
  168. package/dist/media/react/hooks/MediaCard.hooks.js +63 -0
  169. package/dist/media/react/hooks/MediaDialog.hooks.d.ts +10 -0
  170. package/dist/media/react/hooks/MediaDialog.hooks.js +20 -0
  171. package/dist/media/react/hooks/MediaGrid.hooks.d.ts +28 -0
  172. package/dist/media/react/hooks/MediaGrid.hooks.js +6 -0
  173. package/dist/media/react/hooks/MediaLightbox.hooks.d.ts +27 -0
  174. package/dist/media/react/hooks/MediaLightbox.hooks.js +64 -0
  175. package/dist/media/react/hooks/MediaPage.hooks.d.ts +68 -0
  176. package/dist/media/react/hooks/MediaPage.hooks.js +68 -0
  177. package/dist/media/react/hooks/MediaPicker.hooks.d.ts +26 -0
  178. package/dist/media/react/hooks/MediaPicker.hooks.js +25 -0
  179. package/dist/media/react/hooks/MediaPorts.hooks.d.ts +9 -0
  180. package/dist/media/react/hooks/MediaPorts.hooks.js +10 -0
  181. package/dist/media/react/hooks/MediaPurgeDialog.hooks.d.ts +22 -0
  182. package/dist/media/react/hooks/MediaPurgeDialog.hooks.js +6 -0
  183. package/dist/media/react/hooks/ProvidersTab.hooks.d.ts +55 -0
  184. package/dist/media/react/hooks/ProvidersTab.hooks.js +124 -0
  185. package/dist/media/react/hooks/UploadButton.hooks.d.ts +48 -0
  186. package/dist/media/react/hooks/UploadButton.hooks.js +118 -0
  187. package/dist/media/react/index.d.ts +373 -0
  188. package/dist/media/react/index.js +73 -0
  189. package/dist/media/react/pages/MediaPage.d.ts +4 -0
  190. package/dist/media/react/pages/MediaPage.js +9 -0
  191. package/dist/media/react/tabs/LibraryTab.d.ts +4 -0
  192. package/dist/media/react/tabs/LibraryTab.js +14 -0
  193. package/dist/media/react/tabs/ProvidersTab.d.ts +4 -0
  194. package/dist/media/react/tabs/ProvidersTab.js +10 -0
  195. package/dist/media/rules.d.ts +80 -0
  196. package/dist/media/rules.js +127 -0
  197. package/dist/media/styles.d.ts +4 -0
  198. package/dist/media/styles.js +5 -0
  199. package/dist/playground/adapters/http.d.ts +8 -0
  200. package/dist/playground/adapters/http.js +4 -0
  201. package/dist/playground/adapters/memory.d.ts +10 -0
  202. package/dist/playground/adapters/memory.js +30 -0
  203. package/dist/playground/conformance/playground-api.conformance.d.ts +6 -0
  204. package/dist/playground/conformance/playground-api.conformance.js +37 -0
  205. package/dist/playground/controllers/playground.controller.d.ts +16 -0
  206. package/dist/playground/controllers/playground.controller.js +21 -0
  207. package/dist/playground/index.d.ts +7 -0
  208. package/dist/playground/index.js +5 -0
  209. package/dist/playground/messages.en.d.ts +9 -0
  210. package/dist/playground/messages.en.js +2 -0
  211. package/dist/playground/models.d.ts +4 -0
  212. package/dist/playground/models.js +2 -0
  213. package/dist/playground/playground.module.d.ts +31 -0
  214. package/dist/playground/playground.module.js +5 -0
  215. package/dist/playground/ports.d.ts +5 -0
  216. package/dist/playground/ports.js +2 -0
  217. package/dist/playground/react/components/Canvas.d.ts +3 -0
  218. package/dist/playground/react/components/Canvas.js +9 -0
  219. package/dist/playground/react/hooks/Canvas.hooks.d.ts +7 -0
  220. package/dist/playground/react/hooks/Canvas.hooks.js +18 -0
  221. package/dist/playground/react/hooks/PlaygroundPage.hooks.d.ts +8 -0
  222. package/dist/playground/react/hooks/PlaygroundPage.hooks.js +2 -0
  223. package/dist/playground/react/hooks/PlaygroundPorts.hooks.d.ts +4 -0
  224. package/dist/playground/react/hooks/PlaygroundPorts.hooks.js +6 -0
  225. package/dist/playground/react/index.d.ts +136 -0
  226. package/dist/playground/react/index.js +10 -0
  227. package/dist/playground/react/pages/PlaygroundPage.d.ts +4 -0
  228. package/dist/playground/react/pages/PlaygroundPage.js +11 -0
  229. package/dist/playground/react/tabs/CanvasTab.d.ts +4 -0
  230. package/dist/playground/react/tabs/CanvasTab.js +5 -0
  231. package/dist/playground/rules.d.ts +4 -0
  232. package/dist/playground/rules.js +2 -0
  233. package/dist/react/OverlayHost.d.ts +3 -0
  234. package/dist/react/OverlayHost.hooks.d.ts +9 -0
  235. package/dist/react/OverlayHost.hooks.js +9 -0
  236. package/dist/react/OverlayHost.js +7 -0
  237. package/dist/react/bind-react.d.ts +46 -0
  238. package/dist/react/bind-react.js +28 -0
  239. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.d.ts +7 -1
  240. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.js +2 -2
  241. package/dist/react/components/ConfirmButton/ConfirmButton.js +1 -1
  242. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts +17 -3
  243. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js +3 -3
  244. package/dist/react/components/ConfirmDialog/ConfirmDialog.js +5 -5
  245. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.d.ts +6 -2
  246. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.js +7 -8
  247. package/dist/react/components/RowMenu/RowMenu.d.ts +5 -1
  248. package/dist/react/components/RowMenu/RowMenu.hooks.d.ts +8 -2
  249. package/dist/react/components/RowMenu/RowMenu.hooks.js +4 -4
  250. package/dist/react/components/RowMenu/RowMenu.js +6 -6
  251. package/dist/react/components/Sidebar.d.ts +1 -1
  252. package/dist/react/components/Sidebar.js +103 -7
  253. package/dist/react/entities/EntityCell.d.ts +10 -0
  254. package/dist/react/entities/EntityCell.js +18 -0
  255. package/dist/react/entities/EntityDetail.d.ts +3 -0
  256. package/dist/react/entities/EntityDetail.js +21 -0
  257. package/dist/react/entities/EntityEdit.d.ts +13 -0
  258. package/dist/react/entities/EntityEdit.js +45 -0
  259. package/dist/react/entities/EntityField.d.ts +20 -0
  260. package/dist/react/entities/EntityField.js +31 -0
  261. package/dist/react/entities/EntityIndex.d.ts +3 -0
  262. package/dist/react/entities/EntityIndex.js +10 -0
  263. package/dist/react/entities/EntityList.d.ts +7 -0
  264. package/dist/react/entities/EntityList.js +52 -0
  265. package/dist/react/entities/contribution.d.ts +26 -0
  266. package/dist/react/entities/contribution.js +78 -0
  267. package/dist/react/entities/index.d.ts +10 -0
  268. package/dist/react/entities/index.js +7 -0
  269. package/dist/react/entities/rules.d.ts +179 -0
  270. package/dist/react/entities/rules.js +224 -0
  271. package/dist/react/entities/types.d.ts +45 -0
  272. package/dist/react/entities/types.js +5 -0
  273. package/dist/react/entities/use-entity-edit.d.ts +35 -0
  274. package/dist/react/entities/use-entity-edit.js +98 -0
  275. package/dist/react/entities/use-entity-read.d.ts +22 -0
  276. package/dist/react/entities/use-entity-read.js +27 -0
  277. package/dist/react/hooks/use-nav-sections.d.ts +12 -3
  278. package/dist/react/hooks/use-nav-sections.js +14 -14
  279. package/dist/react/hooks/use-sidebar-rail.d.ts +7 -1
  280. package/dist/react/hooks/use-sidebar-rail.js +11 -11
  281. package/dist/react/index.d.ts +3 -1
  282. package/dist/react/index.js +5 -2
  283. package/dist/react/kit/Kit.hooks.d.ts +13 -0
  284. package/dist/react/kit/Kit.hooks.js +10 -0
  285. package/dist/react/kit/Native.hooks.d.ts +38 -0
  286. package/dist/react/kit/Native.hooks.js +65 -0
  287. package/dist/react/kit/index.d.ts +12 -0
  288. package/dist/react/kit/index.js +21 -0
  289. package/dist/react/kit/native.d.ts +3 -0
  290. package/dist/react/kit/native.js +21 -0
  291. package/dist/react/kit/types.d.ts +40 -0
  292. package/dist/react/kit/types.js +2 -0
  293. package/dist/react/overlay.d.ts +36 -0
  294. package/dist/react/overlay.js +35 -0
  295. package/dist/react/overlays.d.ts +38 -0
  296. package/dist/react/overlays.js +46 -0
  297. package/dist/react/shell/AdminShell.d.ts +9 -0
  298. package/dist/react/shell/AdminShell.hooks.d.ts +15 -0
  299. package/dist/react/shell/AdminShell.hooks.js +27 -0
  300. package/dist/react/shell/AdminShell.js +46 -0
  301. package/dist/react/shell/index.d.ts +7 -0
  302. package/dist/react/shell/index.js +5 -0
  303. package/dist/react/shell/model.d.ts +25 -0
  304. package/dist/react/shell/model.js +29 -0
  305. package/dist/react/shell/theme-ports.d.ts +28 -0
  306. package/dist/react/shell/theme-ports.js +2 -0
  307. package/dist/react/shell/types.d.ts +99 -0
  308. package/dist/react/shell/types.js +2 -0
  309. package/dist/react/shell/use-admin-shell-session.d.ts +13 -0
  310. package/dist/react/shell/use-admin-shell-session.js +81 -0
  311. package/dist/react/shell/use-admin-theme.d.ts +16 -0
  312. package/dist/react/shell/use-admin-theme.js +57 -0
  313. package/dist/react/types.d.ts +6 -4
  314. package/dist/react/types.js +2 -2
  315. package/dist/react/use-controller.d.ts +16 -0
  316. package/dist/react/use-controller.js +18 -0
  317. package/dist/security/adapters/http.d.ts +16 -0
  318. package/dist/security/adapters/http.js +94 -0
  319. package/dist/security/adapters/memory.d.ts +15 -0
  320. package/dist/security/adapters/memory.js +60 -0
  321. package/dist/security/conformance/security-api.conformance.d.ts +10 -0
  322. package/dist/security/conformance/security-api.conformance.js +48 -0
  323. package/dist/security/controllers/access-tokens.controller.d.ts +44 -0
  324. package/dist/security/controllers/access-tokens.controller.js +112 -0
  325. package/dist/security/controllers/other-credentials.controller.d.ts +30 -0
  326. package/dist/security/controllers/other-credentials.controller.js +74 -0
  327. package/dist/security/controllers/root-key.controller.d.ts +35 -0
  328. package/dist/security/controllers/root-key.controller.js +90 -0
  329. package/dist/security/index.d.ts +9 -0
  330. package/dist/security/index.js +9 -0
  331. package/dist/security/messages.en.d.ts +12 -0
  332. package/dist/security/messages.en.js +2 -0
  333. package/dist/security/models.d.ts +112 -0
  334. package/dist/security/models.js +2 -0
  335. package/dist/security/ports.d.ts +58 -0
  336. package/dist/security/ports.js +5 -0
  337. package/dist/security/react/components/CredentialEditor.d.ts +3 -0
  338. package/dist/security/react/components/CredentialEditor.js +8 -0
  339. package/dist/security/react/hooks/AccessTokensTab.hooks.d.ts +94 -0
  340. package/dist/security/react/hooks/AccessTokensTab.hooks.js +36 -0
  341. package/dist/security/react/hooks/CredentialEditor.hooks.d.ts +49 -0
  342. package/dist/security/react/hooks/CredentialEditor.hooks.js +14 -0
  343. package/dist/security/react/hooks/RootKeyTab.hooks.d.ts +29 -0
  344. package/dist/security/react/hooks/RootKeyTab.hooks.js +19 -0
  345. package/dist/security/react/hooks/SecurityPage.hooks.d.ts +17 -0
  346. package/dist/security/react/hooks/SecurityPage.hooks.js +12 -0
  347. package/dist/security/react/hooks/SecurityPorts.hooks.d.ts +9 -0
  348. package/dist/security/react/hooks/SecurityPorts.hooks.js +6 -0
  349. package/dist/security/react/index.d.ts +215 -0
  350. package/dist/security/react/index.js +10 -0
  351. package/dist/security/react/pages/SecurityPage.d.ts +4 -0
  352. package/dist/security/react/pages/SecurityPage.js +10 -0
  353. package/dist/security/react/tabs/AccessTokensTab.d.ts +4 -0
  354. package/dist/security/react/tabs/AccessTokensTab.js +10 -0
  355. package/dist/security/react/tabs/RootKeyTab.d.ts +4 -0
  356. package/dist/security/react/tabs/RootKeyTab.js +9 -0
  357. package/dist/security/rules.d.ts +57 -0
  358. package/dist/security/rules.js +63 -0
  359. package/dist/security/security.module.d.ts +45 -0
  360. package/dist/security/security.module.js +5 -0
  361. package/dist/source-control/adapters/http.d.ts +6 -0
  362. package/dist/source-control/adapters/http.js +13 -0
  363. package/dist/source-control/adapters/memory.d.ts +9 -0
  364. package/dist/source-control/adapters/memory.js +35 -0
  365. package/dist/source-control/conformance/source-control-api.conformance.d.ts +10 -0
  366. package/dist/source-control/conformance/source-control-api.conformance.js +48 -0
  367. package/dist/source-control/controllers/source-control.controller.d.ts +26 -0
  368. package/dist/source-control/controllers/source-control.controller.js +70 -0
  369. package/dist/source-control/index.d.ts +8 -0
  370. package/dist/source-control/index.js +6 -0
  371. package/dist/source-control/messages.en.d.ts +11 -0
  372. package/dist/source-control/messages.en.js +2 -0
  373. package/dist/source-control/models.d.ts +70 -0
  374. package/dist/source-control/models.js +2 -0
  375. package/dist/source-control/ports.d.ts +23 -0
  376. package/dist/source-control/ports.js +3 -0
  377. package/dist/source-control/react/components/SourceControlCredentialFields.d.ts +5 -0
  378. package/dist/source-control/react/components/SourceControlCredentialFields.js +8 -0
  379. package/dist/source-control/react/components/SourceControlProviderRow.d.ts +5 -0
  380. package/dist/source-control/react/components/SourceControlProviderRow.js +7 -0
  381. package/dist/source-control/react/hooks/ProvidersTab.hooks.d.ts +45 -0
  382. package/dist/source-control/react/hooks/ProvidersTab.hooks.js +20 -0
  383. package/dist/source-control/react/hooks/SourceControlCredentialFields.hooks.d.ts +43 -0
  384. package/dist/source-control/react/hooks/SourceControlCredentialFields.hooks.js +9 -0
  385. package/dist/source-control/react/hooks/SourceControlPage.hooks.d.ts +17 -0
  386. package/dist/source-control/react/hooks/SourceControlPage.hooks.js +5 -0
  387. package/dist/source-control/react/hooks/SourceControlPorts.hooks.d.ts +9 -0
  388. package/dist/source-control/react/hooks/SourceControlPorts.hooks.js +6 -0
  389. package/dist/source-control/react/index.d.ts +156 -0
  390. package/dist/source-control/react/index.js +10 -0
  391. package/dist/source-control/react/pages/SourceControlPage.d.ts +4 -0
  392. package/dist/source-control/react/pages/SourceControlPage.js +11 -0
  393. package/dist/source-control/react/tabs/ProvidersTab.d.ts +4 -0
  394. package/dist/source-control/react/tabs/ProvidersTab.js +10 -0
  395. package/dist/source-control/rules.d.ts +32 -0
  396. package/dist/source-control/rules.js +35 -0
  397. package/dist/source-control/source-control.module.d.ts +36 -0
  398. package/dist/source-control/source-control.module.js +6 -0
  399. package/package.json +207 -4
@@ -0,0 +1,60 @@
1
+ import { START_FRESH_CONFIRMATION } from '../rules.js';
2
+ /** Fake backend: retains only read models, never credential material. */
3
+ export function createMemorySecurityApi({ providers = [], rows = [] }, _optional = {}) {
4
+ let items = rows.map(r => Object.freeze({ ...r }));
5
+ let sequence = 0;
6
+ function store(kind) {
7
+ function project(id, patch, providerId, initial) {
8
+ const now = new Date().toISOString();
9
+ return Object.freeze({ kind, id, providerId, label: patch.label ?? initial?.label ?? '', configured: true, isDefault: kind === 'custom' ? false : patch.isDefault ?? initial?.isDefault ?? !items.some(r => r.kind === kind && r.providerId === providerId), createdAt: initial?.createdAt ?? now, updatedAt: now,
10
+ ...(kind === 'custom' ? { category: patch.category ?? initial?.category ?? 'general', baseUrl: patch.baseUrl ?? initial?.baseUrl ?? '', additionalHosts: Object.freeze([...(patch.additionalHosts ?? initial?.additionalHosts ?? [])]), ...((patch.username !== undefined ? patch.username : patch.connection?.username ?? initial?.username) ? { username: (patch.username !== undefined ? patch.username : patch.connection?.username ?? initial?.username) } : {}) } : {}),
11
+ });
12
+ }
13
+ function check(label, providerId, id) { if (items.some(r => r.kind === kind && r.id !== id && (kind === 'custom' || r.providerId === providerId) && r.label.toLowerCase() === label.toLowerCase()))
14
+ throw new Error('Duplicate label'); }
15
+ function insert(row) {
16
+ if (row.isDefault)
17
+ items = items.map(r => r.kind === kind && r.providerId === row.providerId ? Object.freeze({ ...r, isDefault: false }) : r);
18
+ items = [...items.filter(r => !(r.kind === kind && r.id === row.id)), row];
19
+ return row;
20
+ }
21
+ return {
22
+ async list(_r, o = {}) { o.signal?.throwIfAborted(); return Object.freeze(items.filter(r => r.kind === kind)); },
23
+ async create(input, o = {}) { o.signal?.throwIfAborted(); if (!Object.values(input.connection).some(v => v.trim()) || !input.label.trim())
24
+ throw new Error('Incomplete credential'); const providerId = kind === 'custom' ? '' : input.connection.providerId ?? ''; check(input.label, providerId); return insert(project(`credential-${++sequence}`, input, providerId)); },
25
+ async update({ id, patch }, o = {}) { o.signal?.throwIfAborted(); const old = items.find(r => r.id === id && r.kind === kind); if (!old)
26
+ throw new Error('Credential not found'); check(patch.label ?? old.label, old.providerId, id); return insert(project(id, patch, old.providerId, old)); },
27
+ async remove({ id }, o = {}) { o.signal?.throwIfAborted(); const old = items.find(r => r.id === id && r.kind === kind); items = items.filter(r => !(r.id === id && r.kind === kind)); if (old?.isDefault) {
28
+ const next = items.filter(r => r.kind === kind && r.providerId === old.providerId).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))[0];
29
+ if (next)
30
+ insert(Object.freeze({ ...next, isDefault: true }));
31
+ } },
32
+ };
33
+ }
34
+ return { async providers(_r, o = {}) { o.signal?.throwIfAborted(); return providers; }, publish: store('publish'), sourceControl: store('source-control'), custom: store('custom') };
35
+ }
36
+ export function createMemoryOtherCredentials({ rows = [] }, _optional = {}) {
37
+ let items = rows.map(row => Object.freeze({ ...row }));
38
+ return {
39
+ async list({ store }, o = {}) { o.signal?.throwIfAborted(); return items.filter(r => r.store === store); },
40
+ async replace({ store, id, token }, o = {}) { o.signal?.throwIfAborted(); const row = items.find(r => r.store === store && r.id === id); if (!row?.supportsReplace || !token.trim())
41
+ throw new Error('Replacement unavailable'); items = items.map(r => r === row ? Object.freeze({ ...r, configured: true, updatedAt: new Date().toISOString() }) : r); },
42
+ async remove({ store, id }, o = {}) { o.signal?.throwIfAborted(); items = items.filter(r => r.store !== store || r.id !== id); },
43
+ };
44
+ }
45
+ export function createMemoryRootKey({ status = { active: false, source: 'none', state: 'missing', keyFilePath: '/memory/key', runtimeMode: 'local' }, preview = { removes: 0, affectedWebhooks: [], detail: 'Remove saved credentials and create a new root key.', runtimeMode: 'local' } }, _optional = {}) {
46
+ let current = Object.freeze({ ...status });
47
+ function activate(outcome) { current = Object.freeze({ ...current, active: true, state: 'active', source: 'file', fingerprint: 'memory-fingerprint' }); return { outcome, fingerprint: 'memory-fingerprint', keyFilePath: current.keyFilePath, runtimeMode: current.runtimeMode }; }
48
+ return {
49
+ async status(_r, o = {}) { o.signal?.throwIfAborted(); return current; },
50
+ async generate(_r, o = {}) { o.signal?.throwIfAborted(); if (current.active)
51
+ return { ...activate('already-active') }; if (current.state !== 'missing')
52
+ throw new Error('Key dependent data'); return activate('created'); },
53
+ async importToken({ token }, o = {}) { o.signal?.throwIfAborted(); if (!/^[0-9a-f]{64}$/i.test(token))
54
+ throw new Error('Invalid token'); return { ...activate('unlocked'), resealed: 0 }; },
55
+ async previewStartFresh(_r, o = {}) { o.signal?.throwIfAborted(); return preview; },
56
+ async startFresh({ confirm }, o = {}) { o.signal?.throwIfAborted(); if (confirm !== START_FRESH_CONFIRMATION)
57
+ throw new Error('Confirmation required'); return { ...activate('started-fresh'), discarded: preview.removes, kept: 0, affectedWebhooks: preview.affectedWebhooks, restorePointId: 'memory-restore-point' }; },
58
+ };
59
+ }
60
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1,10 @@
1
+ import type { SecurityApiPort } from '../ports.js';
2
+ import type { CredentialProvider } from '../models.js';
3
+ /** Use a disposable backend: this contract creates, updates and removes credentials. */
4
+ export declare function runSecurityApiConformance({ createApi, provider }: {
5
+ createApi: (required: Record<string, never>, optional?: Record<string, never>) => SecurityApiPort | Promise<SecurityApiPort>;
6
+ provider: CredentialProvider;
7
+ }, _optional?: {}): Promise<{
8
+ passed: number;
9
+ }>;
10
+ //# sourceMappingURL=security-api.conformance.d.ts.map
@@ -0,0 +1,48 @@
1
+ import { credentialStore } from '../rules.js';
2
+ /** Use a disposable backend: this contract creates, updates and removes credentials. */
3
+ export async function runSecurityApiConformance({ createApi, provider }, _optional = {}) {
4
+ const api = await createApi({}), target = credentialStore({ api, kind: provider.kind });
5
+ let passed = 0;
6
+ function check(value, message) { if (!value)
7
+ throw new Error(`Security contract: ${message}`); passed++; }
8
+ const suffix = `${Date.now()}-${Math.random()}`;
9
+ const secret = `contract-secret-${suffix}`;
10
+ const connection = { providerId: provider.id, [provider.tokenField]: secret, ...Object.fromEntries(provider.fields.filter(f => f.name !== provider.tokenField).map(f => [f.name, 'test-value'])) };
11
+ const ids = [];
12
+ try {
13
+ const a = await target.create({ label: `First ${suffix}`, connection }, {});
14
+ ids.push(a.id);
15
+ check(a.configured, 'create produces configured summary');
16
+ check(!JSON.stringify(a).includes(secret), 'create cannot return secret');
17
+ const b = await target.create({ label: `Second ${suffix}`, connection }, {});
18
+ ids.push(b.id);
19
+ const renamed = await target.update({ id: a.id, patch: { label: `Renamed ${suffix}` } }, {});
20
+ check(renamed.id === a.id && renamed.label === `Renamed ${suffix}`, 'metadata update preserves identity');
21
+ const replaced = await target.update({ id: a.id, patch: { connection } }, {});
22
+ check(!JSON.stringify(replaced).includes(secret), 'replacement cannot return secret');
23
+ await target.update({ id: b.id, patch: { isDefault: true } }, {});
24
+ const listed = await target.list({}, {});
25
+ check(listed.filter(r => r.providerId === provider.id && r.isDefault).length === 1 && listed.find(r => r.id === b.id)?.isDefault === true, 'one server-owned default');
26
+ await target.remove({ id: b.id }, {});
27
+ const remaining = await target.list({}, {});
28
+ check(!remaining.some(r => r.id === b.id) && remaining.some(r => r.providerId === provider.id && r.isDefault), 'remove promotes remaining connection');
29
+ await target.remove({ id: b.id }, {});
30
+ check(true, 'remove is idempotent');
31
+ const abort = new AbortController();
32
+ abort.abort();
33
+ let refused = false;
34
+ try {
35
+ await target.create({ label: `Aborted ${suffix}`, connection }, { signal: abort.signal });
36
+ }
37
+ catch {
38
+ refused = true;
39
+ }
40
+ check(refused && !(await target.list({}, {})).some(r => r.label === `Aborted ${suffix}`), 'aborted mutation writes nothing');
41
+ }
42
+ finally {
43
+ for (const id of ids)
44
+ await target.remove({ id }, {});
45
+ }
46
+ return { passed };
47
+ }
48
+ //# sourceMappingURL=security-api.conformance.js.map
@@ -0,0 +1,44 @@
1
+ import type { SecurityApiPort } from '../ports.js';
2
+ import type { CredentialSummary, CredentialProvider, CredentialDraft, CredentialKind, CredentialCategory } from '../models.js';
3
+ export declare function createAccessTokensController({ api, permissions }: {
4
+ api: SecurityApiPort;
5
+ permissions?: readonly string[];
6
+ }, _optional?: {}): {
7
+ getSnapshot: () => Readonly<{
8
+ rows: readonly CredentialSummary[];
9
+ providers: readonly CredentialProvider[];
10
+ draft: CredentialDraft | null;
11
+ loading: boolean;
12
+ saving: boolean;
13
+ error: string | null;
14
+ errors: Readonly<Record<string, string>>;
15
+ query: string;
16
+ category: CredentialCategory | "all";
17
+ }>;
18
+ subscribe: ({ listener }: {
19
+ listener: () => void;
20
+ }) => () => void;
21
+ load: (_required: Record<string, never>, _optional?: {}) => Promise<void>;
22
+ begin: ({ row, kind, providerId }: {
23
+ row?: CredentialSummary;
24
+ kind?: CredentialKind;
25
+ providerId?: string;
26
+ }, _optional?: {}) => void;
27
+ save: (_required: Record<string, never>, _optional?: {}) => Promise<boolean>;
28
+ setDraft({ patch }: {
29
+ patch: Partial<Omit<CredentialDraft, "kind" | "id" | "providerId">>;
30
+ }, _optional?: {}): void;
31
+ cancel(_required: Record<string, never>, _optional?: {}): void;
32
+ filter({ query, category }: {
33
+ query?: string;
34
+ category?: CredentialCategory | "all";
35
+ }, _optional?: {}): void;
36
+ remove({ row }: {
37
+ row: CredentialSummary;
38
+ }, _optional?: {}): Promise<boolean>;
39
+ makeDefault({ row }: {
40
+ row: CredentialSummary;
41
+ }, _optional?: {}): Promise<boolean>;
42
+ dispose(_required?: Record<string, never>, _optional?: {}): void;
43
+ };
44
+ //# sourceMappingURL=access-tokens.controller.d.ts.map
@@ -0,0 +1,112 @@
1
+ import { createControllerStore } from '../../core/module/controller-store.js';
2
+ import { blankCredentialDraft, buildCredentialPatch, credentialStore, validateCredentialDraft, writePermission, credentialLabel } from '../rules.js';
3
+ export function createAccessTokensController({ api, permissions = [] }, _optional = {}) {
4
+ const grants = new Set(permissions);
5
+ const store = createControllerStore({ initial: { rows: [], providers: [], draft: null, loading: false, saving: false, error: null, errors: {}, query: '', category: 'all' } });
6
+ let generation = 0;
7
+ const allowed = (kind) => !store.signal.aborted && grants.has('security.read') && grants.has(writePermission({ kind }));
8
+ async function load(_required, _optional = {}) {
9
+ if (store.signal.aborted || !grants.has('security.read'))
10
+ return;
11
+ const ticket = ++generation;
12
+ store.set({ patch: { loading: true } });
13
+ // Independent stores retain their own successful results; one unavailable store cannot hide the rest.
14
+ const kinds = ['publish', 'source-control', 'custom'];
15
+ const tasks = kinds.map(async (kind) => {
16
+ try {
17
+ const rows = await credentialStore({ api, kind }).list({}, { signal: store.signal });
18
+ if (ticket === generation) {
19
+ const errors = { ...store.getSnapshot().errors };
20
+ delete errors[kind];
21
+ store.set({ patch: { rows: Object.freeze([...store.getSnapshot().rows.filter(r => r.kind !== kind), ...rows]), errors } });
22
+ }
23
+ }
24
+ catch {
25
+ if (ticket === generation)
26
+ store.set({ patch: { errors: { ...store.getSnapshot().errors, [kind]: 'Credential store unavailable' } } });
27
+ }
28
+ });
29
+ tasks.push((async () => { try {
30
+ const providers = await api.providers({}, { signal: store.signal });
31
+ if (ticket === generation)
32
+ store.set({ patch: { providers, error: null } });
33
+ }
34
+ catch {
35
+ if (ticket === generation)
36
+ store.set({ patch: { error: 'Provider catalog unavailable' } });
37
+ } })());
38
+ await Promise.all(tasks);
39
+ if (ticket === generation)
40
+ store.set({ patch: { loading: false } });
41
+ }
42
+ function begin({ row, kind, providerId }, _optional = {}) {
43
+ const k = row?.kind ?? kind ?? 'custom';
44
+ if (!allowed(k) || store.getSnapshot().saving)
45
+ return;
46
+ const draft = row ? { ...blankCredentialDraft({ kind: row.kind, providerId: row.providerId }), id: row.id, label: credentialLabel({ row, providers: store.getSnapshot().providers }), category: row.category ?? (row.kind === 'publish' ? 'hosting' : row.kind === 'source-control' ? 'source-control' : 'general'), baseUrl: row.baseUrl ?? '', additionalHosts: row.additionalHosts?.join('\n') ?? '', username: row.username ?? '' } : blankCredentialDraft({ kind: k, ...(providerId ? { providerId } : {}) });
47
+ store.set({ patch: { draft, error: null } });
48
+ }
49
+ async function save(_required, _optional = {}) {
50
+ const state = store.getSnapshot(), draft = state.draft;
51
+ if (!draft || !allowed(draft.kind) || state.saving)
52
+ return false;
53
+ const error = validateCredentialDraft({ draft, rows: state.rows, providers: state.providers });
54
+ if (error) {
55
+ store.set({ patch: { error } });
56
+ return false;
57
+ }
58
+ const patch = buildCredentialPatch({ draft, providers: state.providers });
59
+ const target = credentialStore({ api, kind: draft.kind });
60
+ store.set({ patch: { saving: true, error: null } });
61
+ try {
62
+ const row = draft.id ? await target.update({ id: draft.id, patch }, { signal: store.signal }) : await target.create(patch, { signal: store.signal });
63
+ // Clear accepted secrets before any later read can fail. A successful save must never leave a saved secret visible.
64
+ store.set({ patch: { draft: null, rows: Object.freeze([...store.getSnapshot().rows.filter(r => !(r.kind === row.kind && r.id === row.id)), row]) } });
65
+ // First-create default assignment can change siblings; the server owns that invariant.
66
+ await load({});
67
+ return !store.signal.aborted;
68
+ }
69
+ catch {
70
+ store.set({ patch: { error: 'Unable to save credential' } });
71
+ return false;
72
+ }
73
+ finally {
74
+ store.set({ patch: { saving: false } });
75
+ }
76
+ }
77
+ async function write({ row, remove }) {
78
+ if (!allowed(row.kind) || store.getSnapshot().saving)
79
+ return false;
80
+ store.set({ patch: { saving: true, error: null } });
81
+ try {
82
+ const target = credentialStore({ api, kind: row.kind });
83
+ if (remove)
84
+ await target.remove({ id: row.id }, { signal: store.signal });
85
+ else
86
+ await target.update({ id: row.id, patch: { isDefault: true } }, { signal: store.signal });
87
+ // Remove/default can promote another row. Refetch rather than duplicating server promotion rules.
88
+ await load({});
89
+ return !store.signal.aborted;
90
+ }
91
+ catch {
92
+ store.set({ patch: { error: 'Unable to update credential' } });
93
+ return false;
94
+ }
95
+ finally {
96
+ store.set({ patch: { saving: false } });
97
+ }
98
+ }
99
+ return {
100
+ getSnapshot: store.getSnapshot, subscribe: store.subscribe, load, begin, save,
101
+ setDraft({ patch }, _optional = {}) { const draft = store.getSnapshot().draft; if (draft && allowed(draft.kind) && !store.getSnapshot().saving)
102
+ store.set({ patch: { draft: { ...draft, ...patch } } }); },
103
+ cancel(_required, _optional = {}) { if (!store.getSnapshot().saving)
104
+ store.set({ patch: { draft: null, error: null } }); },
105
+ filter({ query, category }, _optional = {}) { store.set({ patch: { ...(query !== undefined ? { query } : {}), ...(category ? { category } : {}) } }); },
106
+ remove({ row }, _optional = {}) { return write({ row, remove: true }); },
107
+ makeDefault({ row }, _optional = {}) { if (row.kind === 'custom')
108
+ return Promise.resolve(false); return write({ row, remove: false }); },
109
+ dispose(_required = {}, _optional = {}) { generation++; store.dispose(); },
110
+ };
111
+ }
112
+ //# sourceMappingURL=access-tokens.controller.js.map
@@ -0,0 +1,30 @@
1
+ import type { OtherCredentialsPort } from '../ports.js';
2
+ import type { OtherCredentialSummary } from '../models.js';
3
+ export declare function createOtherCredentialsController({ api, permissions }: {
4
+ api: OtherCredentialsPort;
5
+ permissions?: readonly string[];
6
+ }, _optional?: {}): {
7
+ getSnapshot: () => Readonly<{
8
+ rows: readonly OtherCredentialSummary[];
9
+ drafts: Readonly<Record<string, string>>;
10
+ errors: Readonly<Record<string, string>>;
11
+ loading: boolean;
12
+ saving: boolean;
13
+ }>;
14
+ subscribe: ({ listener }: {
15
+ listener: () => void;
16
+ }) => () => void;
17
+ load: (_required: Record<string, never>, _optional?: {}) => Promise<void>;
18
+ setDraft({ key, token }: {
19
+ key: string;
20
+ token: string;
21
+ }, _optional?: {}): void;
22
+ replace({ row }: {
23
+ row: OtherCredentialSummary;
24
+ }, _optional?: {}): Promise<boolean>;
25
+ remove({ row }: {
26
+ row: OtherCredentialSummary;
27
+ }, _optional?: {}): Promise<boolean>;
28
+ dispose(_required?: Record<string, never>, _optional?: {}): void;
29
+ };
30
+ //# sourceMappingURL=other-credentials.controller.d.ts.map
@@ -0,0 +1,74 @@
1
+ import { createControllerStore } from '../../core/module/controller-store.js';
2
+ import { OTHER_STORES, otherWritePermission } from '../rules.js';
3
+ export function createOtherCredentialsController({ api, permissions = [] }, _optional = {}) {
4
+ const grants = new Set(permissions);
5
+ let generation = 0;
6
+ const store = createControllerStore({ initial: { rows: [], drafts: {}, errors: {}, loading: false, saving: false } });
7
+ async function read(id, ticket) {
8
+ try {
9
+ const rows = await api.list({ store: id }, { signal: store.signal });
10
+ if (ticket === generation) {
11
+ const errors = { ...store.getSnapshot().errors };
12
+ delete errors[id];
13
+ store.set({ patch: { rows: [...store.getSnapshot().rows.filter(r => r.store !== id), ...rows], errors } });
14
+ }
15
+ }
16
+ catch {
17
+ if (ticket === generation)
18
+ store.set({ patch: { errors: { ...store.getSnapshot().errors, [id]: 'Credential store unavailable' } } });
19
+ }
20
+ }
21
+ async function load(_required, _optional = {}) {
22
+ if (store.signal.aborted || !grants.has('security.read'))
23
+ return;
24
+ const ticket = ++generation;
25
+ store.set({ patch: { loading: true } });
26
+ await Promise.all(OTHER_STORES.map(id => read(id, ticket)));
27
+ if (ticket === generation)
28
+ store.set({ patch: { loading: false } });
29
+ }
30
+ // One serial lane: whole-map media writes must read only after the previous write/refetch settled.
31
+ // This is tab-local; cross-session races still require a server concurrency check.
32
+ let lane = Promise.resolve();
33
+ function write(row, remove) {
34
+ if (store.signal.aborted || !grants.has('security.read') || !grants.has(otherWritePermission({ store: row.store })) || (!remove && !row.supportsReplace))
35
+ return Promise.resolve(false);
36
+ const token = store.getSnapshot().drafts[`${row.store}:${row.id}`]?.trim() ?? '';
37
+ if (!remove && !token)
38
+ return Promise.resolve(false);
39
+ const run = lane.then(async () => {
40
+ if (store.signal.aborted)
41
+ return false;
42
+ store.set({ patch: { saving: true } });
43
+ try {
44
+ if (remove)
45
+ await api.remove({ store: row.store, id: row.id }, { signal: store.signal });
46
+ else
47
+ await api.replace({ store: row.store, id: row.id, token }, { signal: store.signal });
48
+ const drafts = { ...store.getSnapshot().drafts };
49
+ delete drafts[`${row.store}:${row.id}`];
50
+ store.set({ patch: { drafts } });
51
+ await read(row.store, generation);
52
+ return !store.signal.aborted;
53
+ }
54
+ catch {
55
+ store.set({ patch: { errors: { ...store.getSnapshot().errors, [row.store]: 'Unable to update credential' } } });
56
+ return false;
57
+ }
58
+ finally {
59
+ store.set({ patch: { saving: false } });
60
+ }
61
+ });
62
+ lane = run.then(() => undefined);
63
+ return run;
64
+ }
65
+ return {
66
+ getSnapshot: store.getSnapshot, subscribe: store.subscribe, load,
67
+ setDraft({ key, token }, _optional = {}) { if (!store.signal.aborted && !store.getSnapshot().saving)
68
+ store.set({ patch: { drafts: { ...store.getSnapshot().drafts, [key]: token } } }); },
69
+ replace({ row }, _optional = {}) { return write(row, false); },
70
+ remove({ row }, _optional = {}) { return write(row, true); },
71
+ dispose(_required = {}, _optional = {}) { generation++; store.dispose(); },
72
+ };
73
+ }
74
+ //# sourceMappingURL=other-credentials.controller.js.map
@@ -0,0 +1,35 @@
1
+ import type { RootKeyPort } from '../ports.js';
2
+ import type { RootKeyStatus, RootKeyPreview } from '../models.js';
3
+ export declare function createRootKeyController({ api, permissions }: {
4
+ api: RootKeyPort;
5
+ permissions?: readonly string[];
6
+ }, _optional?: {}): {
7
+ getSnapshot: () => Readonly<{
8
+ status: RootKeyStatus | null;
9
+ preview: RootKeyPreview | null;
10
+ token: string;
11
+ confirm: string;
12
+ loading: boolean;
13
+ saving: boolean;
14
+ error: string | null;
15
+ result: string | null;
16
+ confirming: boolean;
17
+ }>;
18
+ subscribe: ({ listener }: {
19
+ listener: () => void;
20
+ }) => () => void;
21
+ load: (_required: Record<string, never>, _optional?: {}) => Promise<void>;
22
+ setToken({ value }: {
23
+ value: string;
24
+ }, _optional?: {}): void;
25
+ setConfirm({ value }: {
26
+ value: string;
27
+ }, _optional?: {}): void;
28
+ generate(_required: Record<string, never>, _optional?: {}): Promise<boolean>;
29
+ importToken(_required: Record<string, never>, _optional?: {}): Promise<boolean>;
30
+ preview(_required: Record<string, never>, _optional?: {}): Promise<boolean>;
31
+ startFresh(_required: Record<string, never>, _optional?: {}): Promise<boolean>;
32
+ cancel(_required: Record<string, never>, _optional?: {}): void;
33
+ dispose(_required?: Record<string, never>, _optional?: {}): void;
34
+ };
35
+ //# sourceMappingURL=root-key.controller.d.ts.map
@@ -0,0 +1,90 @@
1
+ import { createControllerStore } from '../../core/module/controller-store.js';
2
+ import { ROOT_KEY_PERMISSION, START_FRESH_CONFIRMATION, isRootKeyLocked } from '../rules.js';
3
+ export function createRootKeyController({ api, permissions = [] }, _optional = {}) {
4
+ const granted = permissions.includes(ROOT_KEY_PERMISSION);
5
+ const store = createControllerStore({ initial: { status: null, preview: null, token: '', confirm: '', loading: false, saving: false, error: null, result: null, confirming: false } });
6
+ let generation = 0;
7
+ const allowed = () => granted && !store.signal.aborted;
8
+ async function load(_required, _optional = {}) {
9
+ if (!allowed())
10
+ return;
11
+ const ticket = ++generation;
12
+ store.set({ patch: { loading: true } });
13
+ try {
14
+ const status = await api.status({}, { signal: store.signal });
15
+ if (ticket === generation)
16
+ store.set({ patch: { status, error: null } });
17
+ }
18
+ catch {
19
+ if (ticket === generation)
20
+ store.set({ patch: { error: 'Root key status unavailable' } });
21
+ }
22
+ finally {
23
+ if (ticket === generation)
24
+ store.set({ patch: { loading: false } });
25
+ }
26
+ }
27
+ async function execute(run, result) {
28
+ if (!allowed() || store.getSnapshot().saving)
29
+ return false;
30
+ store.set({ patch: { saving: true, error: null } });
31
+ try {
32
+ const response = await run();
33
+ store.set({ patch: { token: '', confirm: '', preview: null, confirming: false, result: response.affectedWebhooks?.length ? `${result} Update receivers: ${response.affectedWebhooks.map(w => `${w.label} (${w.targetUrl})`).join(', ')}` : result } });
34
+ await load({});
35
+ return !store.signal.aborted;
36
+ }
37
+ catch {
38
+ store.set({ patch: { error: 'Recovery refused. Check the host key configuration.' } });
39
+ return false;
40
+ }
41
+ finally {
42
+ store.set({ patch: { saving: false } });
43
+ }
44
+ }
45
+ return {
46
+ getSnapshot: store.getSnapshot, subscribe: store.subscribe, load,
47
+ setToken({ value }, _optional = {}) { if (allowed() && !store.getSnapshot().saving)
48
+ store.set({ patch: { token: value } }); },
49
+ setConfirm({ value }, _optional = {}) { if (allowed() && !store.getSnapshot().saving)
50
+ store.set({ patch: { confirm: value } }); },
51
+ generate(_required, _optional = {}) {
52
+ const status = store.getSnapshot().status;
53
+ // No rotate/replace: replacing an active key would orphan every secret sealed under it.
54
+ if (!status || status.active || status.state !== 'missing')
55
+ return Promise.resolve(false);
56
+ return execute(() => api.generate({}, { signal: store.signal }), 'Root key ready');
57
+ },
58
+ importToken(_required, _optional = {}) { const token = store.getSnapshot().token.trim(); return token && isRootKeyLocked({ status: store.getSnapshot().status }) ? execute(() => api.importToken({ token }, { signal: store.signal }), 'Unlocked. Saved credentials work again.') : Promise.resolve(false); },
59
+ async preview(_required, _optional = {}) {
60
+ if (!allowed() || !isRootKeyLocked({ status: store.getSnapshot().status }) || store.getSnapshot().saving || store.getSnapshot().loading)
61
+ return false;
62
+ const ticket = ++generation;
63
+ store.set({ patch: { loading: true, preview: null, confirm: '', error: null } });
64
+ try {
65
+ const preview = await api.previewStartFresh({}, { signal: store.signal });
66
+ if (ticket !== generation || !allowed())
67
+ return false;
68
+ store.set({ patch: { preview, confirming: true } });
69
+ return true;
70
+ }
71
+ catch {
72
+ if (ticket === generation)
73
+ store.set({ patch: { error: 'Recovery preview unavailable' } });
74
+ return false;
75
+ }
76
+ finally {
77
+ if (ticket === generation)
78
+ store.set({ patch: { loading: false } });
79
+ }
80
+ },
81
+ startFresh(_required, _optional = {}) { const state = store.getSnapshot(); if (!isRootKeyLocked({ status: state.status }) || !state.preview || !state.confirming || state.confirm !== START_FRESH_CONFIRMATION)
82
+ return Promise.resolve(false); return execute(() => api.startFresh({ confirm: state.confirm }, { signal: store.signal }), 'Done. Re-enter removed credentials.'); },
83
+ cancel(_required, _optional = {}) { if (!store.getSnapshot().saving) {
84
+ generation++;
85
+ store.set({ patch: { confirming: false, preview: null, confirm: '', loading: false } });
86
+ } },
87
+ dispose(_required = {}, _optional = {}) { generation++; store.dispose(); },
88
+ };
89
+ }
90
+ //# sourceMappingURL=root-key.controller.js.map
@@ -0,0 +1,9 @@
1
+ export { securityModule } from './security.module.js';
2
+ export * from './models.js';
3
+ export * from './ports.js';
4
+ export * from './rules.js';
5
+ export { securityMessagesEn } from './messages.en.js';
6
+ export { createAccessTokensController } from './controllers/access-tokens.controller.js';
7
+ export { createOtherCredentialsController } from './controllers/other-credentials.controller.js';
8
+ export { createRootKeyController } from './controllers/root-key.controller.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,9 @@
1
+ export { securityModule } from './security.module.js';
2
+ export * from './models.js';
3
+ export * from './ports.js';
4
+ export * from './rules.js';
5
+ export { securityMessagesEn } from './messages.en.js';
6
+ export { createAccessTokensController } from './controllers/access-tokens.controller.js';
7
+ export { createOtherCredentialsController } from './controllers/other-credentials.controller.js';
8
+ export { createRootKeyController } from './controllers/root-key.controller.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,12 @@
1
+ export declare const securityMessagesEn: {
2
+ readonly security: "Secrets";
3
+ readonly accessTokens: "Access tokens";
4
+ readonly rootKey: "Root key";
5
+ readonly denied: "Permission denied";
6
+ readonly loading: "Loading credentials…";
7
+ readonly remove: "Remove credential";
8
+ readonly replace: "Replace";
9
+ readonly save: "Save";
10
+ readonly cancel: "Cancel";
11
+ };
12
+ //# sourceMappingURL=messages.en.d.ts.map
@@ -0,0 +1,2 @@
1
+ export const securityMessagesEn = { security: 'Secrets', accessTokens: 'Access tokens', rootKey: 'Root key', denied: 'Permission denied', loading: 'Loading credentials…', remove: 'Remove credential', replace: 'Replace', save: 'Save', cancel: 'Cancel' };
2
+ //# sourceMappingURL=messages.en.js.map