@k2b/cloud 0.6.0-rc.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 (540) hide show
  1. package/README.md +98 -0
  2. package/package.json +128 -0
  3. package/public/logo.svg +1 -0
  4. package/scripts/app-favicon.test.ts +49 -0
  5. package/scripts/app-favicon.ts +51 -0
  6. package/scripts/build.ts +205 -0
  7. package/scripts/preload.ts +164 -0
  8. package/scripts/sync-recovery-smoke.ts +200 -0
  9. package/src/_internal/app-favicon.ts +2 -0
  10. package/src/_internal/app-presentation.ts +61 -0
  11. package/src/_internal/app-workspace-state.ts +24 -0
  12. package/src/_internal/bounded-json.ts +47 -0
  13. package/src/_internal/build-metadata.ts +9 -0
  14. package/src/_internal/capabilities.ts +1118 -0
  15. package/src/_internal/define-app.ts +801 -0
  16. package/src/_internal/heartbeat.ts +167 -0
  17. package/src/_internal/help-catalog.ts +241 -0
  18. package/src/_internal/help.ts +95 -0
  19. package/src/_internal/nats-connection.ts +34 -0
  20. package/src/_internal/page-responses.ts +40 -0
  21. package/src/_internal/process-sync.ts +117 -0
  22. package/src/_internal/readiness.ts +3 -0
  23. package/src/_internal/registry-validation.ts +136 -0
  24. package/src/_internal/registry-watch.ts +52 -0
  25. package/src/_internal/registry.ts +338 -0
  26. package/src/_internal/runtime-compatibility.ts +64 -0
  27. package/src/_internal/runtime-context.ts +84 -0
  28. package/src/_internal/runtime-watcher.ts +78 -0
  29. package/src/_internal/static-assets.ts +86 -0
  30. package/src/_internal/status-preserving-ssr.ts +49 -0
  31. package/src/access/PermissionEditor.tsx +486 -0
  32. package/src/access/ResourceApiKeys.tsx +271 -0
  33. package/src/access/messages.ts +121 -0
  34. package/src/access/ui.ts +16 -0
  35. package/src/account/Avatar.tsx +28 -0
  36. package/src/account/EntitySearch.tsx +363 -0
  37. package/src/account/avatar-upload-dialog.tsx +197 -0
  38. package/src/account/avatar-upload.ts +149 -0
  39. package/src/account/ui.ts +3 -0
  40. package/src/ai/admin.ts +47 -0
  41. package/src/ai/approval-routes.ts +130 -0
  42. package/src/ai/approvals.ts +139 -0
  43. package/src/ai/assistant-models.ts +61 -0
  44. package/src/ai/attachments.ts +40 -0
  45. package/src/ai/browser.ts +92 -0
  46. package/src/ai/capabilities.ts +714 -0
  47. package/src/ai/capability-execution.ts +151 -0
  48. package/src/ai/chat/blocks.render.test.tsx +1108 -0
  49. package/src/ai/chat/blocks.tsx +730 -0
  50. package/src/ai/chat/builtin-tools.tsx +428 -0
  51. package/src/ai/chat/capability-table.tsx +87 -0
  52. package/src/ai/chat/composer-adapter.ts +169 -0
  53. package/src/ai/chat/file-tools.tsx +81 -0
  54. package/src/ai/chat/message-actions.tsx +370 -0
  55. package/src/ai/chat/message-utils.ts +479 -0
  56. package/src/ai/chat/messages.ts +43 -0
  57. package/src/ai/chat/presentation.tsx +395 -0
  58. package/src/ai/chat/primitives.tsx +3 -0
  59. package/src/ai/chat/tool-disclosure.tsx +41 -0
  60. package/src/ai/chat/turn-navigator-utils.ts +28 -0
  61. package/src/ai/chat/turn-navigator.tsx +164 -0
  62. package/src/ai/chat/user-message.tsx +149 -0
  63. package/src/ai/chat/visual-tools.tsx +435 -0
  64. package/src/ai/chat/web-tools.tsx +202 -0
  65. package/src/ai/chat-task-contracts.ts +113 -0
  66. package/src/ai/chat-tasks.ts +952 -0
  67. package/src/ai/client/controller.ts +1211 -0
  68. package/src/ai/client/file-source.ts +95 -0
  69. package/src/ai/client/live-connection.ts +140 -0
  70. package/src/ai/client/projection.ts +178 -0
  71. package/src/ai/client/transport.ts +111 -0
  72. package/src/ai/compaction.ts +182 -0
  73. package/src/ai/credentials.ts +124 -0
  74. package/src/ai/default-tool-contracts.ts +108 -0
  75. package/src/ai/default-tools.ts +127 -0
  76. package/src/ai/enrich.ts +280 -0
  77. package/src/ai/executor.ts +1624 -0
  78. package/src/ai/fetch-file-tool.ts +313 -0
  79. package/src/ai/file-context.ts +92 -0
  80. package/src/ai/file-media-type.ts +28 -0
  81. package/src/ai/file-mount.ts +16 -0
  82. package/src/ai/file-tools.ts +566 -0
  83. package/src/ai/files-store.ts +390 -0
  84. package/src/ai/firecrawl-tools.ts +305 -0
  85. package/src/ai/grids-skill.ts +126 -0
  86. package/src/ai/http.ts +265 -0
  87. package/src/ai/index.ts +337 -0
  88. package/src/ai/kit-skill.ts +22 -0
  89. package/src/ai/limits.ts +5 -0
  90. package/src/ai/live-events.ts +289 -0
  91. package/src/ai/live-messages.ts +45 -0
  92. package/src/ai/live-outbox.ts +102 -0
  93. package/src/ai/live-routes.ts +412 -0
  94. package/src/ai/live.ts +2 -0
  95. package/src/ai/maintenance.ts +302 -0
  96. package/src/ai/markdown-pdf-tool.ts +95 -0
  97. package/src/ai/memories.ts +605 -0
  98. package/src/ai/memory-learning-runs.ts +222 -0
  99. package/src/ai/memory-learning.ts +619 -0
  100. package/src/ai/memory-tool.ts +120 -0
  101. package/src/ai/memory-workflow-evidence.ts +158 -0
  102. package/src/ai/migrate.ts +2082 -0
  103. package/src/ai/model-access-migrate.ts +30 -0
  104. package/src/ai/model-access.ts +191 -0
  105. package/src/ai/personal-agent.ts +6 -0
  106. package/src/ai/prefs.ts +72 -0
  107. package/src/ai/project-tool.ts +94 -0
  108. package/src/ai/projects-routes.ts +277 -0
  109. package/src/ai/projects.ts +902 -0
  110. package/src/ai/protocol.ts +279 -0
  111. package/src/ai/provider.ts +73 -0
  112. package/src/ai/public-projection.ts +25 -0
  113. package/src/ai/resource-markers.ts +31 -0
  114. package/src/ai/resource-refs.ts +70 -0
  115. package/src/ai/routes.ts +1131 -0
  116. package/src/ai/runtime-tools.ts +39 -0
  117. package/src/ai/runtime.ts +544 -0
  118. package/src/ai/settings.ts +529 -0
  119. package/src/ai/short-id.ts +45 -0
  120. package/src/ai/skill-catalog.ts +73 -0
  121. package/src/ai/skill-format.ts +145 -0
  122. package/src/ai/skill-seeds.ts +430 -0
  123. package/src/ai/skill-tool.ts +81 -0
  124. package/src/ai/skills-routes.ts +143 -0
  125. package/src/ai/skills.ts +934 -0
  126. package/src/ai/solid.ts +27 -0
  127. package/src/ai/store.ts +3113 -0
  128. package/src/ai/stream.ts +308 -0
  129. package/src/ai/structured-runs.ts +66 -0
  130. package/src/ai/structured.ts +186 -0
  131. package/src/ai/system-prompt.ts +170 -0
  132. package/src/ai/task-prompt.ts +22 -0
  133. package/src/ai/timeline.ts +148 -0
  134. package/src/ai/tool-audit.ts +177 -0
  135. package/src/ai/tool-result-budget.ts +16 -0
  136. package/src/ai/tools.ts +155 -0
  137. package/src/ai/types.ts +967 -0
  138. package/src/ai/ui.tsx +39 -0
  139. package/src/ai/usage-migrate.ts +81 -0
  140. package/src/ai/usage.ts +315 -0
  141. package/src/ai/validate.ts +54 -0
  142. package/src/ai/vision-tool.ts +79 -0
  143. package/src/api/accounts-entities.ts +174 -0
  144. package/src/api/admin-ai-projects.ts +74 -0
  145. package/src/api/admin-ai-skills.ts +76 -0
  146. package/src/api/admin-ai-usage.ts +42 -0
  147. package/src/api/admin-core-settings.ts +508 -0
  148. package/src/api/admin-identity.ts +148 -0
  149. package/src/api/admin-lifecycle.ts +206 -0
  150. package/src/api/admin-linux-identities.ts +66 -0
  151. package/src/api/announcements.ts +131 -0
  152. package/src/api/app-approval.ts +129 -0
  153. package/src/api/apps.ts +51 -0
  154. package/src/api/auth/schemas.ts +54 -0
  155. package/src/api/auth.ts +370 -0
  156. package/src/api/capabilities.ts +658 -0
  157. package/src/api/help-messages.ts +19 -0
  158. package/src/api/help.ts +78 -0
  159. package/src/api/index.ts +108 -0
  160. package/src/api/mcp.ts +744 -0
  161. package/src/api/me-rail.ts +45 -0
  162. package/src/api/me.ts +753 -0
  163. package/src/api/search/schemas.ts +79 -0
  164. package/src/api/search.bench.ts +185 -0
  165. package/src/api/search.ts +407 -0
  166. package/src/api/sync-ops.ts +79 -0
  167. package/src/api/widgets.ts +143 -0
  168. package/src/browser/CloudResourceSearch.behavior.test.tsx +74 -0
  169. package/src/browser/CloudResourceSearch.tsx +791 -0
  170. package/src/browser/app-approval-vault.ts +305 -0
  171. package/src/browser/app-approval.ts +234 -0
  172. package/src/browser/live-websocket.ts +268 -0
  173. package/src/browser/locale-preference.ts +25 -0
  174. package/src/browser/notification-target.ts +27 -0
  175. package/src/browser/notification-timeout.ts +14 -0
  176. package/src/browser/notifications.ts +181 -0
  177. package/src/browser/resource-clipboard.ts +70 -0
  178. package/src/browser/resource-picker.tsx +39 -0
  179. package/src/browser/resource-search-messages.ts +55 -0
  180. package/src/browser/resource-search.ts +27 -0
  181. package/src/capabilities/client.ts +149 -0
  182. package/src/capabilities/response.ts +39 -0
  183. package/src/capabilities/server.ts +215 -0
  184. package/src/capabilities/signals.ts +4 -0
  185. package/src/capabilities/testing.ts +12 -0
  186. package/src/capabilities/types.ts +32 -0
  187. package/src/cli/access.ts +499 -0
  188. package/src/cli/account.ts +382 -0
  189. package/src/cli/admin/account-administration.ts +45 -0
  190. package/src/cli/admin/account-categories.ts +49 -0
  191. package/src/cli/admin/ai-usage.ts +118 -0
  192. package/src/cli/admin/app-sign-in.ts +49 -0
  193. package/src/cli/admin/data.ts +343 -0
  194. package/src/cli/admin/documentation.ts +34 -0
  195. package/src/cli/admin/gateway.ts +155 -0
  196. package/src/cli/admin/index.ts +61 -0
  197. package/src/cli/admin/instance.ts +250 -0
  198. package/src/cli/admin/jobs.ts +223 -0
  199. package/src/cli/admin/legal.ts +122 -0
  200. package/src/cli/admin/linux.ts +53 -0
  201. package/src/cli/admin/logs.ts +324 -0
  202. package/src/cli/admin/metrics.ts +142 -0
  203. package/src/cli/admin/nats.ts +167 -0
  204. package/src/cli/admin/notifications.ts +516 -0
  205. package/src/cli/admin/shared.ts +113 -0
  206. package/src/cli/admin/sync.ts +188 -0
  207. package/src/cli/admin/telemetry.ts +314 -0
  208. package/src/cli/admin/webhooks.ts +222 -0
  209. package/src/cli/admin/workflows.ts +367 -0
  210. package/src/cli/apps.ts +40 -0
  211. package/src/cli/capabilities.ts +239 -0
  212. package/src/cli/commands.ts +604 -0
  213. package/src/cli/index.ts +61 -0
  214. package/src/cli/locale.ts +31 -0
  215. package/src/cli/output.ts +58 -0
  216. package/src/clients/core.ts +20 -0
  217. package/src/config/env.ts +54 -0
  218. package/src/config/index.ts +6 -0
  219. package/src/contracts/account-categories.ts +62 -0
  220. package/src/contracts/announcements.ts +121 -0
  221. package/src/contracts/app-approval.ts +197 -0
  222. package/src/contracts/app.ts +162 -0
  223. package/src/contracts/capabilities.ts +484 -0
  224. package/src/contracts/index.ts +14 -0
  225. package/src/contracts/notification-live.ts +66 -0
  226. package/src/contracts/notification-types.ts +235 -0
  227. package/src/contracts/posix.ts +69 -0
  228. package/src/contracts/profile.ts +85 -0
  229. package/src/contracts/rail-preferences.ts +53 -0
  230. package/src/contracts/registry.ts +110 -0
  231. package/src/contracts/resource-clipboard.ts +33 -0
  232. package/src/contracts/settings-types.ts +98 -0
  233. package/src/contracts/shared.ts +408 -0
  234. package/src/contracts/user-notifications.ts +101 -0
  235. package/src/contracts/widgets.ts +183 -0
  236. package/src/desktop/index.ts +704 -0
  237. package/src/desktop/solid.tsx +938 -0
  238. package/src/index.ts +58 -0
  239. package/src/server/actor.ts +41 -0
  240. package/src/server/api/index.ts +2 -0
  241. package/src/server/api/respond.ts +96 -0
  242. package/src/server/api-client.ts +54 -0
  243. package/src/server/app-context.ts +39 -0
  244. package/src/server/help.ts +187 -0
  245. package/src/server/index.ts +89 -0
  246. package/src/server/locale.ts +55 -0
  247. package/src/server/middleware/auth.ts +386 -0
  248. package/src/server/middleware/index.ts +28 -0
  249. package/src/server/middleware/invocation.ts +55 -0
  250. package/src/server/middleware/middleware.ts +65 -0
  251. package/src/server/middleware/openapi.ts +126 -0
  252. package/src/server/middleware/rate-limit.ts +125 -0
  253. package/src/server/middleware/request-logger.ts +41 -0
  254. package/src/server/middleware/route-template.ts +46 -0
  255. package/src/server/middleware/runtime.ts +22 -0
  256. package/src/server/middleware/settings.ts +55 -0
  257. package/src/server/middleware/validator.ts +49 -0
  258. package/src/server/middleware/workload.ts +22 -0
  259. package/src/server/ratelimit.ts +151 -0
  260. package/src/server/request-cookies.ts +18 -0
  261. package/src/server/services/access.ts +644 -0
  262. package/src/server/services/freeipa/client.ts +137 -0
  263. package/src/server/services/freeipa/index.ts +9 -0
  264. package/src/server/services/freeipa/session.ts +123 -0
  265. package/src/server/services/freeipa/test-certificates.ts +44 -0
  266. package/src/server/services/freeipa/tls.ts +44 -0
  267. package/src/server/services/freeipa/transport.ts +116 -0
  268. package/src/server/services/freeipa/util.ts +59 -0
  269. package/src/server/services/geo.ts +198 -0
  270. package/src/server/services/index.ts +48 -0
  271. package/src/server/services/pagination.ts +22 -0
  272. package/src/server/services/services.ts +13 -0
  273. package/src/server/time.ts +33 -0
  274. package/src/services/account-category-policy.ts +51 -0
  275. package/src/services/account-lifecycle/audit.ts +41 -0
  276. package/src/services/account-lifecycle/index.ts +940 -0
  277. package/src/services/account-lifecycle/ipa-backfill.ts +152 -0
  278. package/src/services/account-lifecycle/notification-sender.ts +13 -0
  279. package/src/services/account-lifecycle/scheduler.ts +506 -0
  280. package/src/services/account-model.ts +22 -0
  281. package/src/services/accounts/app.ts +1671 -0
  282. package/src/services/accounts/authz.ts +44 -0
  283. package/src/services/accounts/avatar.ts +120 -0
  284. package/src/services/accounts/base-group.ts +11 -0
  285. package/src/services/accounts/base-user.ts +46 -0
  286. package/src/services/accounts/duplicate-emails.ts +82 -0
  287. package/src/services/accounts/entities.ts +622 -0
  288. package/src/services/accounts/group-sql.ts +106 -0
  289. package/src/services/accounts/groups.ts +272 -0
  290. package/src/services/accounts/index.ts +14 -0
  291. package/src/services/accounts/ipa-data.ts +66 -0
  292. package/src/services/accounts/lifecycle.ts +2 -0
  293. package/src/services/accounts/local-groups.ts +499 -0
  294. package/src/services/accounts/model.ts +129 -0
  295. package/src/services/accounts/notification-sender.ts +31 -0
  296. package/src/services/accounts/posix.ts +386 -0
  297. package/src/services/accounts/request-policy.ts +11 -0
  298. package/src/services/accounts/switching.ts +126 -0
  299. package/src/services/accounts/users.ts +745 -0
  300. package/src/services/announcements/index.ts +224 -0
  301. package/src/services/app-approval.ts +498 -0
  302. package/src/services/audit/index.ts +438 -0
  303. package/src/services/auth-flows/index.ts +15 -0
  304. package/src/services/auth-flows/ipa.ts +197 -0
  305. package/src/services/auth-flows/magic-link.ts +185 -0
  306. package/src/services/auth-flows/notification-sender.ts +10 -0
  307. package/src/services/auth-flows/password-reset.ts +268 -0
  308. package/src/services/auth-flows/proxy-return.ts +49 -0
  309. package/src/services/document-extraction.ts +148 -0
  310. package/src/services/freeipa-config.ts +179 -0
  311. package/src/services/gateway.ts +186 -0
  312. package/src/services/identity/constants.ts +18 -0
  313. package/src/services/identity/index.ts +52 -0
  314. package/src/services/identity/invocation-actor.ts +120 -0
  315. package/src/services/identity/invocation-authority.ts +53 -0
  316. package/src/services/identity/invocation-operations.ts +15 -0
  317. package/src/services/identity/invocation-token.ts +276 -0
  318. package/src/services/identity/key-config.ts +41 -0
  319. package/src/services/identity/key-ring.ts +530 -0
  320. package/src/services/identity/metrics.ts +29 -0
  321. package/src/services/identity/routes.ts +18 -0
  322. package/src/services/identity/runtime-config.ts +88 -0
  323. package/src/services/identity/session-token.ts +152 -0
  324. package/src/services/identity/signer-refresh.ts +44 -0
  325. package/src/services/identity/workload-auth.ts +64 -0
  326. package/src/services/index.ts +187 -0
  327. package/src/services/ipa/auth.ts +216 -0
  328. package/src/services/ipa/connection.ts +57 -0
  329. package/src/services/ipa/effective-groups.ts +70 -0
  330. package/src/services/ipa/groups.ts +722 -0
  331. package/src/services/ipa/guard.ts +17 -0
  332. package/src/services/ipa/index.ts +17 -0
  333. package/src/services/ipa/posix.ts +19 -0
  334. package/src/services/ipa/profile.ts +132 -0
  335. package/src/services/ipa/runtime.ts +28 -0
  336. package/src/services/ipa/search.ts +154 -0
  337. package/src/services/ipa/service-account.ts +15 -0
  338. package/src/services/ipa/sync-planning.ts +100 -0
  339. package/src/services/ipa/sync.ts +862 -0
  340. package/src/services/ipa/users.ts +806 -0
  341. package/src/services/legal-consent.ts +76 -0
  342. package/src/services/logging/index.ts +477 -0
  343. package/src/services/logging/redaction.ts +20 -0
  344. package/src/services/logging/trace.ts +1231 -0
  345. package/src/services/mandates/index.ts +855 -0
  346. package/src/services/mandates/policy.ts +85 -0
  347. package/src/services/network-security.ts +31 -0
  348. package/src/services/notifications/batches.ts +722 -0
  349. package/src/services/notifications/browser.ts +252 -0
  350. package/src/services/notifications/catalog.ts +113 -0
  351. package/src/services/notifications/channels.ts +104 -0
  352. package/src/services/notifications/dispatcher.ts +139 -0
  353. package/src/services/notifications/email.ts +118 -0
  354. package/src/services/notifications/index.ts +633 -0
  355. package/src/services/notifications/live.ts +50 -0
  356. package/src/services/notifications/observability.ts +407 -0
  357. package/src/services/notifications/platform.ts +421 -0
  358. package/src/services/notifications/runtime.ts +120 -0
  359. package/src/services/notifications/user.ts +248 -0
  360. package/src/services/notifications/web-push-transport.ts +135 -0
  361. package/src/services/oauth-tokens.ts +209 -0
  362. package/src/services/outbox.ts +187 -0
  363. package/src/services/pdf/gotenberg.ts +290 -0
  364. package/src/services/pdf/index.ts +43 -0
  365. package/src/services/pdf/markdown.ts +209 -0
  366. package/src/services/pdf/template-preview.ts +122 -0
  367. package/src/services/postgres.ts +76 -0
  368. package/src/services/providers/index.ts +27 -0
  369. package/src/services/providers/local/auth.ts +51 -0
  370. package/src/services/providers/local/index.ts +4 -0
  371. package/src/services/providers/local/users.ts +263 -0
  372. package/src/services/rail-preferences.ts +27 -0
  373. package/src/services/runtime-lifecycle.ts +191 -0
  374. package/src/services/secrets.ts +10 -0
  375. package/src/services/service-account-credentials.ts +891 -0
  376. package/src/services/service-accounts.ts +184 -0
  377. package/src/services/session/index.ts +236 -0
  378. package/src/services/session/test-fixture.ts +18 -0
  379. package/src/services/session/user.ts +144 -0
  380. package/src/services/settings/api.ts +61 -0
  381. package/src/services/settings/app.ts +86 -0
  382. package/src/services/settings/core-settings.ts +796 -0
  383. package/src/services/settings/crypto.ts +69 -0
  384. package/src/services/settings/defaults.ts +374 -0
  385. package/src/services/settings/index.ts +215 -0
  386. package/src/services/settings/namespace.ts +9 -0
  387. package/src/services/settings/snapshot.ts +49 -0
  388. package/src/services/settings/store.ts +241 -0
  389. package/src/services/settings/templates.ts +4 -0
  390. package/src/services/sync-ops.ts +403 -0
  391. package/src/services/topic-cursor.ts +22 -0
  392. package/src/services/weather/forecast.ts +323 -0
  393. package/src/services/weather/geo.ts +119 -0
  394. package/src/services/weather/index.ts +67 -0
  395. package/src/services/weather/location.ts +24 -0
  396. package/src/services/weather/locations.ts +133 -0
  397. package/src/services/weather/migrate.ts +45 -0
  398. package/src/services/weather/settings.ts +66 -0
  399. package/src/services/weather/short-id.ts +57 -0
  400. package/src/services/weather/types.ts +61 -0
  401. package/src/services/weather/ui.ts +50 -0
  402. package/src/services/webauthn.ts +385 -0
  403. package/src/shared/account-action-notice.ts +70 -0
  404. package/src/shared/account-display.ts +15 -0
  405. package/src/shared/account-session.ts +15 -0
  406. package/src/shared/ai-platform-prompt.ts +134 -0
  407. package/src/shared/ai-usage.ts +49 -0
  408. package/src/shared/app-presentation.ts +48 -0
  409. package/src/shared/app-url.ts +12 -0
  410. package/src/shared/branding.ts +14 -0
  411. package/src/shared/capability-messages.ts +70 -0
  412. package/src/shared/email-html.ts +54 -0
  413. package/src/shared/format.ts +91 -0
  414. package/src/shared/help.ts +68 -0
  415. package/src/shared/icons.ts +400 -0
  416. package/src/shared/index.ts +54 -0
  417. package/src/shared/locale.ts +48 -0
  418. package/src/shared/login-method.ts +44 -0
  419. package/src/shared/markdown/client.ts +130 -0
  420. package/src/shared/markdown/extensions/code.ts +105 -0
  421. package/src/shared/markdown/extensions/guided-help.ts +100 -0
  422. package/src/shared/markdown/extensions/images.ts +79 -0
  423. package/src/shared/markdown/extensions/info-blocks.ts +97 -0
  424. package/src/shared/markdown/extensions/katex.ts +120 -0
  425. package/src/shared/markdown/extensions/links.ts +43 -0
  426. package/src/shared/markdown/extensions/mark.ts +48 -0
  427. package/src/shared/markdown/extensions/sub-sup.ts +60 -0
  428. package/src/shared/markdown/extensions/tables.ts +109 -0
  429. package/src/shared/markdown/extensions/task-list.ts +53 -0
  430. package/src/shared/markdown/formula.ts +1187 -0
  431. package/src/shared/markdown/index.ts +193 -0
  432. package/src/shared/markdown/shared.ts +36 -0
  433. package/src/shared/mock-cover.ts +130 -0
  434. package/src/shared/network-address.ts +106 -0
  435. package/src/shared/redirect.ts +56 -0
  436. package/src/shared/template-rendering.ts +140 -0
  437. package/src/shared/theme.ts +68 -0
  438. package/src/shared/time.ts +13 -0
  439. package/src/ssr/AdminLayout.tsx +53 -0
  440. package/src/ssr/AdminSidebar.tsx +50 -0
  441. package/src/ssr/AppLaunchpad.island.tsx +236 -0
  442. package/src/ssr/AppWorkspaceController.island.tsx +21 -0
  443. package/src/ssr/BrowserNotifications.island.tsx +135 -0
  444. package/src/ssr/GlobalAnnouncements.island.tsx +142 -0
  445. package/src/ssr/GlobalSearchDialog.behavior.test.tsx +96 -0
  446. package/src/ssr/GlobalSearchDialog.tsx +35 -0
  447. package/src/ssr/GlobalSearchHelpDialog.tsx +104 -0
  448. package/src/ssr/GlobalSearchTrigger.island.tsx +55 -0
  449. package/src/ssr/HotkeysHelpRail.island.tsx +55 -0
  450. package/src/ssr/Layout.render.test.tsx +148 -0
  451. package/src/ssr/Layout.tsx +292 -0
  452. package/src/ssr/LayoutBreadcrumbs.island.tsx +44 -0
  453. package/src/ssr/LayoutFooter.tsx +22 -0
  454. package/src/ssr/LayoutHeader.tsx +81 -0
  455. package/src/ssr/LayoutHelp.tsx +869 -0
  456. package/src/ssr/LayoutPreferences.island.tsx +36 -0
  457. package/src/ssr/LayoutRail.tsx +58 -0
  458. package/src/ssr/MinimalLayout.tsx +46 -0
  459. package/src/ssr/PageError.tsx +29 -0
  460. package/src/ssr/ProfilePreferences.island.tsx +92 -0
  461. package/src/ssr/RailApps.island.tsx +61 -0
  462. package/src/ssr/RailEditor.tsx +293 -0
  463. package/src/ssr/RegisteredHelpDocuments.island.tsx +3 -0
  464. package/src/ssr/TimezoneCookie.island.tsx +23 -0
  465. package/src/ssr/admin-active-link.ts +47 -0
  466. package/src/ssr/admin-navigation.ts +78 -0
  467. package/src/ssr/app-appearance.ts +23 -0
  468. package/src/ssr/app-navigation.ts +41 -0
  469. package/src/ssr/help-messages.ts +104 -0
  470. package/src/ssr/index.ts +14 -0
  471. package/src/ssr/islands/SearchBar.island.tsx +80 -0
  472. package/src/ssr/islands/index.ts +16 -0
  473. package/src/ssr/layout-context.ts +17 -0
  474. package/src/ssr/layout-help-markdown.ts +9 -0
  475. package/src/ssr/layout-help-navigation.ts +24 -0
  476. package/src/ssr/layout-help-url.ts +5 -0
  477. package/src/ssr/layout-runtime.ts +22 -0
  478. package/src/ssr/page-error-messages.ts +25 -0
  479. package/src/ssr/platform-messages.ts +135 -0
  480. package/src/ssr/preference-controller.ts +44 -0
  481. package/src/ssr/profile-preferences-messages.ts +29 -0
  482. package/src/ssr/rail-context.ts +21 -0
  483. package/src/ssr/rail-messages.ts +66 -0
  484. package/src/ssr/rail-navigation.ts +60 -0
  485. package/src/ssr/runtime.ts +31 -0
  486. package/src/ssr/url-filter.ts +127 -0
  487. package/src/styles/base-popover.css +36 -0
  488. package/src/styles/effects.css +851 -0
  489. package/src/styles/global.css +268 -0
  490. package/src/styles/input.css +58 -0
  491. package/src/styles/tokens.css +230 -0
  492. package/src/styles/utilities-buttons.css +405 -0
  493. package/src/styles/utilities-data.css +33 -0
  494. package/src/styles/utilities-feedback.css +232 -0
  495. package/src/styles/utilities-layout.css +603 -0
  496. package/src/styles/utilities-markdown-editor.css +525 -0
  497. package/src/styles/utilities-markdown-table.css +234 -0
  498. package/src/styles/utilities-navigation.css +1054 -0
  499. package/src/types/ambient.d.ts +24 -0
  500. package/src/workflows/ai/index.ts +17 -0
  501. package/src/workflows/ai/runtime.ts +286 -0
  502. package/src/workflows/ai/store.ts +314 -0
  503. package/src/workflows/ai/types.ts +111 -0
  504. package/src/workflows/ai-actions.ts +269 -0
  505. package/src/workflows/authoring.ts +88 -0
  506. package/src/workflows/builtins.ts +193 -0
  507. package/src/workflows/contracts.ts +280 -0
  508. package/src/workflows/definition.ts +334 -0
  509. package/src/workflows/editor.ts +113 -0
  510. package/src/workflows/index.ts +71 -0
  511. package/src/workflows/language/binder.ts +45 -0
  512. package/src/workflows/language/canonical.ts +29 -0
  513. package/src/workflows/language/compiler.ts +396 -0
  514. package/src/workflows/language/expressions.ts +34 -0
  515. package/src/workflows/language/index.ts +20 -0
  516. package/src/workflows/language/references.ts +55 -0
  517. package/src/workflows/language/schema.ts +134 -0
  518. package/src/workflows/language/strict-yaml.ts +131 -0
  519. package/src/workflows/manifest.ts +24 -0
  520. package/src/workflows/module.ts +12 -0
  521. package/src/workflows/runtime/coordinator.ts +115 -0
  522. package/src/workflows/runtime/executor.ts +1003 -0
  523. package/src/workflows/runtime/index.ts +60 -0
  524. package/src/workflows/runtime/instant.ts +8 -0
  525. package/src/workflows/runtime/ports.ts +213 -0
  526. package/src/workflows/runtime/schedule.ts +203 -0
  527. package/src/workflows/runtime/trigger.ts +37 -0
  528. package/src/workflows/runtime/wake.ts +13 -0
  529. package/src/workflows/store/actions.ts +438 -0
  530. package/src/workflows/store/budget.ts +145 -0
  531. package/src/workflows/store/definitions.ts +345 -0
  532. package/src/workflows/store/events.ts +383 -0
  533. package/src/workflows/store/index.ts +107 -0
  534. package/src/workflows/store/observability.ts +594 -0
  535. package/src/workflows/store/runs.ts +975 -0
  536. package/src/workflows/store/transaction.ts +23 -0
  537. package/src/workflows/store/worker.ts +439 -0
  538. package/src/workflows/testing/conformance.ts +72 -0
  539. package/src/workflows/testing/index.ts +11 -0
  540. package/src/workflows/testing/process-fixtures.ts +275 -0
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Resolving which admin sidebar link is the current one.
3
+ *
4
+ * Kept out of the sidebar component so it can be tested without a JSX runtime,
5
+ * and because the rule is subtle enough to deserve its own tests.
6
+ */
7
+
8
+ const asUrl = (path: string): URL => new URL(`http://admin.local${path}`);
9
+
10
+ /**
11
+ * Whether a link covers the current path at all. A section link stays lit on
12
+ * its sub-pages, which is why this is a prefix test rather than equality.
13
+ *
14
+ * Settings tabs live on one path and differ only by query parameter, so they
15
+ * compare that instead.
16
+ */
17
+ const matches = (currentPath: string, href: string): boolean => {
18
+ const current = asUrl(currentPath);
19
+ const target = asUrl(href);
20
+ if (target.pathname === "/admin/settings") {
21
+ return current.pathname === "/admin/settings" && current.searchParams.get("tab") === target.searchParams.get("tab");
22
+ }
23
+ return current.pathname === target.pathname || current.pathname.startsWith(`${target.pathname}/`);
24
+ };
25
+
26
+ /**
27
+ * The most specific link covering the current path, or null if none does.
28
+ *
29
+ * Prefix matching applied per link lights up every ancestor: the observability
30
+ * overview at `/admin/observability` matched all of `/admin/observability/*`,
31
+ * so it stayed highlighted next to the page actually open. Comparing
32
+ * candidates and keeping the longest resolves that generically — including for
33
+ * `/admin` itself, which previously needed its own exact-match exception.
34
+ */
35
+ export const activeAdminHref = (currentPath: string, hrefs: readonly string[]): string | null => {
36
+ let best: string | null = null;
37
+ let bestLength = -1;
38
+ for (const href of hrefs) {
39
+ if (!matches(currentPath, href)) continue;
40
+ const length = asUrl(href).pathname.length;
41
+ if (length > bestLength) {
42
+ best = href;
43
+ bestLength = length;
44
+ }
45
+ }
46
+ return best;
47
+ };
@@ -0,0 +1,78 @@
1
+ import { normalizeRedirectTo } from "../shared";
2
+ import { platformMessages } from "./platform-messages";
3
+ import type { RuntimeContext } from "./runtime";
4
+
5
+ export type AdminLink = { href: string; icon: string; label: string };
6
+ export type AdminGroup = { label: string; links: AdminLink[] };
7
+
8
+ const normalizeAdminHref = (href: string | undefined): string | undefined => {
9
+ const normalized = normalizeRedirectTo(href);
10
+ return normalized === "/admin" || normalized?.startsWith("/admin/") ? normalized : undefined;
11
+ };
12
+
13
+ export const buildAdminGroups = (apps: readonly RuntimeContext["apps"][number][], locale = "en"): AdminGroup[] => {
14
+ const t = platformMessages.resolve([locale]).t;
15
+ const settingsLinks: AdminLink[] = [
16
+ { href: "/admin/settings?tab=general", icon: "ti-app-window", label: t.general },
17
+ { href: "/admin/settings?tab=mail", icon: "ti-mail", label: "Mail" },
18
+ { href: "/admin/settings?tab=pdf-rendering", icon: "ti-file-type-pdf", label: t.pdfRendering },
19
+ { href: "/admin/settings?tab=email-templates", icon: "ti-template", label: t.emailTemplates },
20
+ { href: "/admin/settings?tab=security", icon: "ti-shield-lock", label: t.security },
21
+ { href: "/admin/settings?tab=legal", icon: "ti-file-text", label: t.legal },
22
+ ];
23
+ const aiLinks: AdminLink[] = [
24
+ { href: "/admin/settings?tab=ai-general", icon: "ti-adjustments", label: t.general },
25
+ { href: "/admin/settings?tab=ai-providers", icon: "ti-sparkles", label: t.providers },
26
+ { href: "/admin/settings?tab=ai-usage", icon: "ti-chart-histogram", label: t.aiUsage },
27
+ { href: "/admin/settings?tab=ai-skills", icon: "ti-wand", label: t.skills },
28
+ { href: "/admin/settings?tab=ai-projects", icon: "ti-folders", label: t.projects },
29
+ { href: "/admin/settings?tab=ai-jobs", icon: "ti-activity", label: t.backgroundJobs },
30
+ ];
31
+ const contributedApps = apps
32
+ .map((app) => ({
33
+ app,
34
+ groups: (app.adminNav ?? [])
35
+ .map((group) => ({
36
+ label: group.label,
37
+ links: group.links.flatMap((link) => {
38
+ const href = normalizeAdminHref(link.href);
39
+ return href ? [{ href, icon: link.icon.replace(/^ti\s+/, ""), label: link.label }] : [];
40
+ }),
41
+ }))
42
+ .filter((group) => group.links.length > 0),
43
+ }))
44
+ .sort((a, b) => a.app.name.localeCompare(b.app.name));
45
+
46
+ const appsWithGroups = new Set(contributedApps.filter(({ groups }) => groups.length > 0).map(({ app }) => app.id));
47
+ const appLinks = apps
48
+ .filter((app) => !appsWithGroups.has(app.id))
49
+ .flatMap((app) => {
50
+ const href = normalizeAdminHref(app.adminHref);
51
+ return href ? [{ href, icon: app.icon.replace(/^ti\s+/, ""), label: app.name }] : [];
52
+ })
53
+ .sort((a, b) => a.label.localeCompare(b.label));
54
+
55
+ return [
56
+ {
57
+ label: t.general,
58
+ links: [
59
+ { href: "/admin", icon: "ti-dashboard", label: t.overview },
60
+ { href: "/admin/announcements", icon: "ti-speakerphone", label: t.announcements },
61
+ ],
62
+ },
63
+ ...contributedApps.flatMap(({ groups }) => groups),
64
+ {
65
+ label: t.userManagement,
66
+ links: [
67
+ { href: "/admin/settings?tab=user", icon: "ti-login", label: t.accountSignIn },
68
+ { href: "/admin/settings?tab=registration", icon: "ti-user-plus", label: t.accountRegistration },
69
+ { href: "/admin/settings?tab=linux", icon: "ti-terminal-2", label: t.linuxAccess },
70
+ { href: "/admin/settings?tab=account-operations", icon: "ti-tool", label: t.accountOperations },
71
+ { href: "/admin/settings?tab=freeipa", icon: "ti-building-fortress", label: "FreeIPA" },
72
+ ],
73
+ },
74
+ { label: t.ai, links: aiLinks },
75
+ { label: t.settings, links: settingsLinks },
76
+ ...(appLinks.length > 0 ? [{ label: t.appAdmin, links: appLinks }] : []),
77
+ ];
78
+ };
@@ -0,0 +1,23 @@
1
+ import type { AppAppearance } from "../contracts/app";
2
+ import { resolveRuntimeRoute } from "./app-navigation";
3
+ import type { RuntimeContext } from "./runtime";
4
+
5
+ const isHexColor = (value: string | undefined): value is `#${string}` => /^#[0-9a-f]{6}$/i.test(value ?? "");
6
+ const clampStrength = (value: number | undefined, fallback: number): number =>
7
+ Number.isFinite(value) ? Math.max(0, Math.min(100, value ?? fallback)) : fallback;
8
+
9
+ export const appAppearanceStyle = (appearance: AppAppearance | undefined): string | undefined => {
10
+ if (!isHexColor(appearance?.accent)) return undefined;
11
+ const from = isHexColor(appearance.background?.from) ? appearance.background.from : appearance.accent;
12
+ const to = isHexColor(appearance.background?.to) ? appearance.background.to : from;
13
+ const via = isHexColor(appearance.background?.via) ? appearance.background.via : "#ffffff";
14
+ const angle = Number.isFinite(appearance.background?.angle) ? Math.max(0, Math.min(360, appearance.background?.angle ?? 135)) : 135;
15
+ const strength = clampStrength(appearance.background?.strength, 20);
16
+ const darkStrength = Math.round(strength / 2);
17
+ return `--app-accent:${appearance.accent};--app-canvas-from:${from};--app-canvas-via:${via};--app-canvas-to:${to};--app-canvas-angle:${angle}deg;--app-canvas-strength:${strength}%;--app-canvas-dark-strength:${darkStrength}%`;
18
+ };
19
+
20
+ export const appAccentStyle = (accent: string | undefined): string | undefined =>
21
+ isHexColor(accent) ? `--app-accent:${accent}` : undefined;
22
+
23
+ export const resolveCurrentApp = (apps: RuntimeContext["apps"], pathname: string) => resolveRuntimeRoute(apps, pathname)?.app;
@@ -0,0 +1,41 @@
1
+ import type { RuntimeAppMeta } from "../contracts/app";
2
+ import { hasRole, type User } from "../contracts/shared";
3
+
4
+ export type VisibleNavigationApp = RuntimeAppMeta & {
5
+ nav: NonNullable<RuntimeAppMeta["nav"]>;
6
+ };
7
+
8
+ export type RuntimeRouteMatch = {
9
+ app: RuntimeAppMeta;
10
+ prefix: string;
11
+ };
12
+
13
+ /** Resolves the app owning the most specific registered prefix for a path. */
14
+ export const resolveRuntimeRoute = (apps: readonly RuntimeAppMeta[], pathname: string): RuntimeRouteMatch | undefined => {
15
+ const path = pathname.split(/[?#]/, 1)[0] || "/";
16
+ return apps
17
+ .flatMap((app) => app.routes.map((prefix) => ({ app, prefix })))
18
+ .filter(({ prefix }) => prefix === "/" || path === prefix || path.startsWith(`${prefix}/`))
19
+ .sort((a, b) => b.prefix.length - a.prefix.length)[0];
20
+ };
21
+
22
+ /** True when a path is owned by an app other than the current caller. */
23
+ export const hasDedicatedRuntimeRoute = (apps: readonly RuntimeAppMeta[], pathname: string, currentAppId: string): boolean => {
24
+ const match = resolveRuntimeRoute(apps, pathname);
25
+ return !!match && match.app.id !== currentAppId;
26
+ };
27
+
28
+ /** Apps rendered in the navigation for a given authenticated user. */
29
+ export const visibleNavigationApps = (apps: readonly RuntimeAppMeta[], user: User | undefined): VisibleNavigationApp[] =>
30
+ apps.filter(
31
+ (app): app is VisibleNavigationApp =>
32
+ !!app.nav &&
33
+ app.nav.section !== "hidden" &&
34
+ (!app.nav.requiresAuth || !!user) &&
35
+ (!app.nav.requiresRoles ||
36
+ (!!user &&
37
+ app.nav.requiresRoles.some((role) => {
38
+ if (role === "guest") return user.profile === "guest";
39
+ return hasRole(user, role);
40
+ }))),
41
+ );
@@ -0,0 +1,104 @@
1
+ import { i18n } from "@k2b/stdlib";
2
+
3
+ /** Shared Help chrome only. Applications own article translations in their Help declaration. */
4
+ export const helpMessages = i18n.define({
5
+ baseLocale: "en",
6
+ messages: {
7
+ en: {
8
+ shortcuts: "Shortcuts",
9
+ shortcutsDescription: "Keyboard actions for the current page.",
10
+ shortcutsIntro: "Shortcuts follow the current app and view. This list updates automatically.",
11
+ searchHelp: "Search help",
12
+ section: "Section",
13
+ help: "Help",
14
+ description: "Guides, workflows, and shortcuts",
15
+ searchDescription: "Find a task, concept, or shortcut.",
16
+ previousTopic: "Previous topic",
17
+ nextTopic: "Next topic",
18
+ topicNavigation: "Help topic navigation",
19
+ back: "Back",
20
+ backToHelp: "Back to help",
21
+ backToTopics: "Back to help topics",
22
+ actions: "Help actions",
23
+ copied: "Copied",
24
+ helpCopied: "Help copied as Markdown",
25
+ copyAllHelp: "Copy all help as Markdown",
26
+ articleCopied: "Article copied as Markdown",
27
+ copyArticle: "Copy article as Markdown",
28
+ openWindow: "Open help in a new browser window",
29
+ openFullPage: "Open full-page help",
30
+ closeHelp: "Close help",
31
+ close: "Close",
32
+ heading: "How can we help?",
33
+ headingDescription: "Find a task, concept, or shortcut for the current app.",
34
+ preparing: "Preparing…",
35
+ copyAllShort: "Copy all as Markdown",
36
+ copyAllFailed: ({ message }: { message: string }) => `Could not copy all help: ${message}`,
37
+ searchPlaceholder: "Search help…",
38
+ startHere: "Start here",
39
+ allTopics: "All topics",
40
+ results: ({ count }: { count: number }) => `${count} ${count === 1 ? "result" : "results"}`,
41
+ noResults: "No help topic matches this search.",
42
+ copyMarkdown: "Copy Markdown",
43
+ loading: "Loading help…",
44
+ loadFailed: "Could not load this topic",
45
+ tryAgain: "Try again",
46
+ onThisPage: "On this page",
47
+ articleCopiedAnnouncement: "Article copied as Markdown.",
48
+ allCopiedAnnouncement: "All help copied as Markdown.",
49
+ searchFailed: "Help could not be searched. Try again.",
50
+ requestFailed: "Help could not be loaded. Try again.",
51
+ invalidDocument: "Help server returned an invalid document",
52
+ loadFallback: "Could not load help",
53
+ copyFallback: "Could not copy help",
54
+ },
55
+ de: {
56
+ shortcuts: "Tastaturkürzel",
57
+ shortcutsDescription: "Tastaturaktionen für die aktuelle Seite.",
58
+ shortcutsIntro: "Die Tastaturkürzel richten sich nach der aktuellen App und Ansicht. Diese Liste wird automatisch aktualisiert.",
59
+ searchHelp: "Hilfe durchsuchen",
60
+ section: "Abschnitt",
61
+ help: "Hilfe",
62
+ description: "Anleitungen, Abläufe und Tastaturkürzel",
63
+ searchDescription: "Finde eine Aufgabe, ein Konzept oder ein Tastaturkürzel.",
64
+ previousTopic: "Vorheriges Thema",
65
+ nextTopic: "Nächstes Thema",
66
+ topicNavigation: "Navigation durch Hilfethemen",
67
+ back: "Zurück",
68
+ backToHelp: "Zurück zur Hilfe",
69
+ backToTopics: "Zurück zu den Hilfethemen",
70
+ actions: "Hilfeaktionen",
71
+ copied: "Kopiert",
72
+ helpCopied: "Hilfe als Markdown kopiert",
73
+ copyAllHelp: "Gesamte Hilfe als Markdown kopieren",
74
+ articleCopied: "Artikel als Markdown kopiert",
75
+ copyArticle: "Artikel als Markdown kopieren",
76
+ openWindow: "Hilfe in einem neuen Browserfenster öffnen",
77
+ openFullPage: "Hilfe als ganze Seite öffnen",
78
+ closeHelp: "Hilfe schließen",
79
+ close: "Schließen",
80
+ heading: "Wobei brauchst du Hilfe?",
81
+ headingDescription: "Finde eine Aufgabe, ein Konzept oder ein Tastaturkürzel für die aktuelle App.",
82
+ preparing: "Wird vorbereitet…",
83
+ copyAllShort: "Alles als Markdown kopieren",
84
+ copyAllFailed: ({ message }) => `Die gesamte Hilfe konnte nicht kopiert werden: ${message}`,
85
+ searchPlaceholder: "Hilfe durchsuchen…",
86
+ startHere: "Hier starten",
87
+ allTopics: "Alle Themen",
88
+ results: ({ count }) => i18n.plural(count, "de", { one: "1 Ergebnis", other: `${count} Ergebnisse` }),
89
+ noResults: "Kein Hilfethema passt zu dieser Suche.",
90
+ copyMarkdown: "Markdown kopieren",
91
+ loading: "Hilfe wird geladen…",
92
+ loadFailed: "Dieses Thema konnte nicht geladen werden",
93
+ tryAgain: "Erneut versuchen",
94
+ onThisPage: "Auf dieser Seite",
95
+ articleCopiedAnnouncement: "Artikel als Markdown kopiert.",
96
+ allCopiedAnnouncement: "Gesamte Hilfe als Markdown kopiert.",
97
+ searchFailed: "Die Hilfe konnte nicht durchsucht werden. Versuche es erneut.",
98
+ requestFailed: "Die Hilfe konnte nicht geladen werden. Versuche es erneut.",
99
+ invalidDocument: "Der Hilfeserver hat ein ungültiges Dokument zurückgegeben",
100
+ loadFallback: "Die Hilfe konnte nicht geladen werden",
101
+ copyFallback: "Die Hilfe konnte nicht kopiert werden",
102
+ },
103
+ },
104
+ });
@@ -0,0 +1,14 @@
1
+ // Server-only exports (these transitively import bun:sql via services)
2
+ // Do NOT import from this barrel in .island.tsx or .client.tsx files!
3
+
4
+ export { default as AdminLayout } from "./AdminLayout";
5
+ export { hasDedicatedRuntimeRoute, resolveRuntimeRoute, visibleNavigationApps } from "./app-navigation";
6
+ export { default as Layout } from "./Layout";
7
+ export {
8
+ default as MinimalLayout,
9
+ type MinimalLayoutPreferencePosition,
10
+ type MinimalLayoutProps,
11
+ } from "./MinimalLayout";
12
+ export { getLocalizedRuntimeContext, getRuntimeContext, type RuntimeContext } from "./runtime";
13
+ export type { UrlFilterField } from "./url-filter";
14
+ export { createUrlFilter, flag, list, oneOf, page, text } from "./url-filter";
@@ -0,0 +1,80 @@
1
+ import { TextInput, useLocale } from "@k2b/ui";
2
+ import { createEffect, createSignal, onMount } from "solid-js";
3
+ import { platformMessages } from "../platform-messages";
4
+
5
+ type SearchBarProps = {
6
+ action?: string;
7
+ value?: string;
8
+ param?: string;
9
+ pageParam?: string;
10
+ placeholder?: string;
11
+ ariaLabel?: string;
12
+ };
13
+
14
+ /** Search bar that filters content via URL query parameter. */
15
+ export default function SearchBar(props: SearchBarProps = {}) {
16
+ const locale = useLocale();
17
+ const t = () => platformMessages.resolve([locale()]).t;
18
+ const param = props.param ?? "search";
19
+ const pageParam = props.pageParam ?? "page";
20
+ const [query, setQuery] = createSignal(props.value ?? "");
21
+
22
+ createEffect(() => {
23
+ if (props.value !== undefined) {
24
+ setQuery(props.value);
25
+ }
26
+ });
27
+
28
+ onMount(() => {
29
+ if (props.value !== undefined) return;
30
+ const fallback = new URLSearchParams(window.location.search).get(param) ?? "";
31
+ setQuery(fallback);
32
+ });
33
+
34
+ const handleSubmit = (e: Event): void => {
35
+ e.preventDefault();
36
+ const current = new URL(window.location.href);
37
+ const url = props.action ? new URL(props.action, window.location.origin) : current;
38
+ const value = query().trim();
39
+
40
+ if (value.length > 0) {
41
+ url.searchParams.set(param, value);
42
+ } else {
43
+ url.searchParams.delete(param);
44
+ }
45
+ url.searchParams.delete(pageParam);
46
+
47
+ window.location.href = url.toString();
48
+ };
49
+
50
+ const handleClear = (): void => {
51
+ const current = new URL(window.location.href);
52
+ const url = props.action ? new URL(props.action, window.location.origin) : current;
53
+
54
+ url.searchParams.delete(param);
55
+ url.searchParams.delete(pageParam);
56
+
57
+ window.location.href = url.toString();
58
+ };
59
+
60
+ return (
61
+ <form onSubmit={handleSubmit} role="search" class="w-full">
62
+ <TextInput
63
+ name={param}
64
+ type="search"
65
+ placeholder={props.placeholder ?? `${t().search}…`}
66
+ aria-label={props.ariaLabel ?? t().search}
67
+ icon="ti ti-search"
68
+ activeIcon="ti ti-search"
69
+ value={query}
70
+ onValueChange={setQuery}
71
+ clearable
72
+ clearLabel={t().clearSearch}
73
+ onClear={handleClear}
74
+ />
75
+ <button type="submit" class="hidden">
76
+ {t().search}
77
+ </button>
78
+ </form>
79
+ );
80
+ }
@@ -0,0 +1,16 @@
1
+ export { default as SearchBar } from "./SearchBar.island";
2
+
3
+ import { AppLaunchpadButton, AppLaunchpadProvider } from "../AppLaunchpad.island";
4
+ import { LayoutHelpDocuments, LayoutHelpPage } from "../LayoutHelp";
5
+
6
+ export type { AppLaunchpadApp, AppLaunchpadLegalLink } from "../AppLaunchpad.island";
7
+ export { AppLaunchpadButton, AppLaunchpadProvider, openAppLaunchpad, setAppLaunchpadContext } from "../AppLaunchpad.island";
8
+ export type { LayoutHelpDocumentsProps, LayoutHelpPageProps } from "../LayoutHelp";
9
+ export { LayoutHelpDocuments, LayoutHelpPage, openLayoutHelpDialog } from "../LayoutHelp";
10
+
11
+ export const Layout = {
12
+ HelpDocuments: LayoutHelpDocuments,
13
+ HelpPage: LayoutHelpPage,
14
+ AppLaunchpadButton,
15
+ AppLaunchpadProvider,
16
+ };
@@ -0,0 +1,17 @@
1
+ import type { RailPreferences } from "../contracts/rail-preferences";
2
+ import type { User } from "../contracts/shared";
3
+ import type { LayoutAnnouncementsState } from "../server/middleware/settings";
4
+ import type { RuntimeContext } from "./runtime";
5
+
6
+ export type LayoutContext = {
7
+ get(key: "user"): User | undefined;
8
+ get(key: "railPreferences"): RailPreferences | undefined;
9
+ get(key: "page"): { theme?: "light" | "dark" };
10
+ get(key: "runtime"): RuntimeContext;
11
+ get(key: "announcements"): LayoutAnnouncementsState | undefined;
12
+ /** Every application settings snapshot includes Core's app metadata. */
13
+ get(key: "settings"): Record<string, any>;
14
+ req: { raw: { headers: Headers; url: string } };
15
+ };
16
+
17
+ export type MinimalLayoutContext = Pick<LayoutContext, "get" | "req">;
@@ -0,0 +1,9 @@
1
+ import type { HelpDocumentManifest, HelpDocumentPayload } from "@k2b/cloud/shared";
2
+
3
+ type MarkdownHelpDocument = Pick<HelpDocumentManifest, "title" | "description"> & Pick<HelpDocumentPayload, "markdown">;
4
+
5
+ export const formatHelpDocumentMarkdown = (document: MarkdownHelpDocument) =>
6
+ [`# ${document.title.trim()}`, document.description?.trim(), document.markdown.trim()].filter(Boolean).join("\n\n") + "\n";
7
+
8
+ export const formatHelpBundleMarkdown = (documents: readonly MarkdownHelpDocument[]) =>
9
+ documents.map((document) => formatHelpDocumentMarkdown(document).trimEnd()).join("\n\n") + "\n";
@@ -0,0 +1,24 @@
1
+ import type { HelpDocumentManifest } from "@k2b/cloud/shared";
2
+
3
+ type HelpArticleSession = { articleScrollTop: number };
4
+ type HelpArticleScroller = { scrollTop: number };
5
+ type HelpArticleHeading = { focus: (options?: FocusOptions) => void };
6
+
7
+ export const adjacentHelpDocuments = (documents: readonly HelpDocumentManifest[], activeId: string | null) => {
8
+ const index = documents.findIndex((document) => document.id === activeId);
9
+ if (index < 0) return { previous: null, next: null };
10
+
11
+ return {
12
+ previous: documents[index - 1] ?? null,
13
+ next: documents[index + 1] ?? null,
14
+ };
15
+ };
16
+
17
+ export const resetHelpArticleScroll = (session: HelpArticleSession, scroller?: HelpArticleScroller) => {
18
+ session.articleScrollTop = 0;
19
+ if (scroller) scroller.scrollTop = 0;
20
+ };
21
+
22
+ export const focusHelpArticleHeading = (heading?: HelpArticleHeading) => {
23
+ heading?.focus({ preventScroll: true });
24
+ };
@@ -0,0 +1,5 @@
1
+ /** Build a canonical, reload-safe URL on an app-owned Help route. */
2
+ export const layoutHelpTopicHref = (pageBase: string, topicId: string | null) => {
3
+ const base = pageBase.endsWith("/") ? pageBase.slice(0, -1) : pageBase;
4
+ return topicId ? `${base}/${encodeURIComponent(topicId)}` : base;
5
+ };
@@ -0,0 +1,22 @@
1
+ export type LayoutBreadcrumb = {
2
+ title: string;
3
+ href?: string;
4
+ };
5
+
6
+ export type LayoutUpdate = {
7
+ title?: string;
8
+ breadcrumbs?: LayoutBreadcrumb[];
9
+ };
10
+
11
+ export const LAYOUT_UPDATE_EVENT = "cloud:layout:update";
12
+
13
+ export const layout = {
14
+ update(update: LayoutUpdate) {
15
+ if (typeof window === "undefined") return;
16
+
17
+ const title = update.title ?? update.breadcrumbs?.at(-1)?.title;
18
+ if (title) document.title = title;
19
+
20
+ window.dispatchEvent(new CustomEvent<LayoutUpdate>(LAYOUT_UPDATE_EVENT, { detail: update }));
21
+ },
22
+ };
@@ -0,0 +1,25 @@
1
+ import { i18n } from "@k2b/stdlib";
2
+
3
+ export const pageErrorMessages = i18n.define({
4
+ baseLocale: "en",
5
+ messages: {
6
+ en: {
7
+ forbidden: "Access denied",
8
+ forbiddenDescription: "Your account does not have permission to open this page.",
9
+ notFound: "Page not found",
10
+ notFoundDescription: "This page is unavailable or the link is no longer valid.",
11
+ failed: "Could not open this page",
12
+ failedDescription: "Please try again later.",
13
+ home: "Go to home page",
14
+ },
15
+ de: {
16
+ forbidden: "Zugriff verweigert",
17
+ forbiddenDescription: "Dein Konto hat keine Berechtigung, diese Seite zu öffnen.",
18
+ notFound: "Seite nicht gefunden",
19
+ notFoundDescription: "Diese Seite ist nicht verfügbar oder der Link ist nicht mehr gültig.",
20
+ failed: "Seite konnte nicht geöffnet werden",
21
+ failedDescription: "Bitte versuche es später erneut.",
22
+ home: "Zur Startseite",
23
+ },
24
+ },
25
+ });
@@ -0,0 +1,135 @@
1
+ import { i18n } from "@k2b/stdlib";
2
+
3
+ export const platformMessages = i18n.define({
4
+ baseLocale: "en",
5
+ messages: {
6
+ en: {
7
+ admin: "Admin",
8
+ platformAdministration: "Platform administration.",
9
+ start: "Start",
10
+ overview: "Overview",
11
+ general: "General",
12
+ announcements: "Announcements",
13
+ ai: "AI",
14
+ settings: "Settings",
15
+ appAdmin: "App administration",
16
+ userManagement: "Accounts & sign-in",
17
+ accountSignIn: "Sign-in",
18
+ accountRegistration: "Registration & requests",
19
+ accountOperations: "Operations",
20
+ linuxAccess: "Linux identities",
21
+ pdfRendering: "PDF rendering",
22
+ emailTemplates: "Email templates",
23
+ security: "Security",
24
+ legal: "Legal",
25
+ providers: "Providers",
26
+ skills: "Skills",
27
+ projects: "Projects",
28
+ aiUsage: "Usage",
29
+ backgroundJobs: "Background jobs",
30
+ apps: "Apps",
31
+ openApps: "Open apps",
32
+ home: "Home",
33
+ profile: "Profile",
34
+ displayName: "display name",
35
+ firstName: "first name",
36
+ lastName: "last name",
37
+ profileIncomplete: ({ fields }: { fields: string }) => `Your profile is incomplete. Missing: ${fields}.`,
38
+ accountExpired: "Your account has expired.",
39
+ accountExpires: ({ date }: { date: string }) => `Your account expires on ${date}.`,
40
+ guestAccountExpires: ({ date }: { date: string }) => `Your guest account expires on ${date}.`,
41
+ passwordExpired: "Your password has expired. Sign out and in again to change it.",
42
+ passwordExpires: ({ date }: { date: string }) => `Your password expires on ${date}.`,
43
+ newNotification: "New notification",
44
+ relatedItemReady: "A related item is ready.",
45
+ open: "Open",
46
+ dismissNotification: "Dismiss notification",
47
+ light: "Light",
48
+ dark: "Dark",
49
+ account: "Account",
50
+ login: "Login",
51
+ latestPlatformUpdates: "Latest platform updates",
52
+ gotIt: "Got it",
53
+ dismissBanner: "Dismiss banner",
54
+ searchTags: "Search tags",
55
+ searchTagsDescription: ({ tag }: { tag: string }) => `Use ${tag} to narrow your search. You can combine text and multiple tags.`,
56
+ tags: "Tags",
57
+ noAppSearchTags: "No app-specific search tags are available.",
58
+ openGlobalSearch: "Open global search",
59
+ globalSearchDescription: "Search across apps, pages, files, and items.",
60
+ searchShortcut: "Search (⌘/Ctrl+K)",
61
+ openShortcutHelp: "Open shortcut help",
62
+ shortcutHelpDescription: "Open help, guides, and keyboard shortcuts.",
63
+ openHelp: "Open help",
64
+ helpShortcut: "Help (Shift+/)",
65
+ signIn: "Sign in",
66
+ menu: "Menu",
67
+ search: "Search",
68
+ clearSearch: "Clear search",
69
+ },
70
+ de: {
71
+ admin: "Verwaltung",
72
+ platformAdministration: "Plattform verwalten.",
73
+ start: "Start",
74
+ overview: "Übersicht",
75
+ general: "Allgemein",
76
+ announcements: "Ankündigungen",
77
+ ai: "KI",
78
+ settings: "Einstellungen",
79
+ appAdmin: "App-Verwaltung",
80
+ userManagement: "Accounts & Anmeldung",
81
+ accountSignIn: "Anmeldung",
82
+ accountRegistration: "Registrierung & Anfragen",
83
+ accountOperations: "Betrieb",
84
+ linuxAccess: "Linux-Identitäten",
85
+ pdfRendering: "PDF-Erstellung",
86
+ emailTemplates: "E-Mail-Vorlagen",
87
+ security: "Sicherheit",
88
+ legal: "Rechtliches",
89
+ providers: "Anbieter",
90
+ skills: "Skills",
91
+ projects: "Projekte",
92
+ aiUsage: "Nutzung",
93
+ backgroundJobs: "Hintergrundaufgaben",
94
+ apps: "Apps",
95
+ openApps: "Apps öffnen",
96
+ home: "Start",
97
+ profile: "Profil",
98
+ displayName: "Anzeigename",
99
+ firstName: "Vorname",
100
+ lastName: "Nachname",
101
+ profileIncomplete: ({ fields }) => `Dein Profil ist unvollständig. Es fehlen: ${fields}.`,
102
+ accountExpired: "Dein Konto ist abgelaufen.",
103
+ accountExpires: ({ date }) => `Dein Konto läuft am ${date} ab.`,
104
+ guestAccountExpires: ({ date }) => `Dein Gastkonto läuft am ${date} ab.`,
105
+ passwordExpired: "Dein Passwort ist abgelaufen. Melde dich ab und erneut an, um es zu ändern.",
106
+ passwordExpires: ({ date }) => `Dein Passwort läuft am ${date} ab.`,
107
+ newNotification: "Neue Benachrichtigung",
108
+ relatedItemReady: "Ein zugehöriger Inhalt ist verfügbar.",
109
+ open: "Öffnen",
110
+ dismissNotification: "Benachrichtigung ausblenden",
111
+ light: "Hell",
112
+ dark: "Dunkel",
113
+ account: "Konto",
114
+ login: "Anmelden",
115
+ latestPlatformUpdates: "Neuigkeiten zur Plattform",
116
+ gotIt: "Verstanden",
117
+ dismissBanner: "Banner ausblenden",
118
+ searchTags: "Such-Tags",
119
+ searchTagsDescription: ({ tag }) => `Verwende ${tag} für eine gezieltere Suche. Text und mehrere Tags lassen sich kombinieren.`,
120
+ tags: "Tags",
121
+ noAppSearchTags: "Keine app-spezifischen Such-Tags verfügbar.",
122
+ openGlobalSearch: "Globale Suche öffnen",
123
+ globalSearchDescription: "Apps, Seiten, Dateien und weitere Inhalte durchsuchen.",
124
+ searchShortcut: "Suchen (⌘/Strg+K)",
125
+ openShortcutHelp: "Tastaturhilfe öffnen",
126
+ shortcutHelpDescription: "Hilfe, Anleitungen und Tastaturkürzel öffnen.",
127
+ openHelp: "Hilfe öffnen",
128
+ helpShortcut: "Hilfe (Umschalt+/)",
129
+ signIn: "Anmelden",
130
+ menu: "Menü",
131
+ search: "Suchen",
132
+ clearSearch: "Suche leeren",
133
+ },
134
+ },
135
+ });