@toa.io/extensions.configuration 1.0.0-alpha.272 → 1.0.0-alpha.274

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 (522) hide show
  1. package/CHANGELOG.md +210 -0
  2. package/components/configuration.values/manifest.toa.yaml +158 -0
  3. package/components/configuration.values/source/create.ts +56 -0
  4. package/components/configuration.values/source/fetch.ts +24 -0
  5. package/components/configuration.values/source/get.ts +33 -0
  6. package/components/configuration.values/source/lib/map.test.ts +34 -0
  7. package/components/configuration.values/source/lib/map.ts +34 -0
  8. package/components/configuration.values/source/lib/resolve.ts +54 -0
  9. package/components/configuration.values/source/list.ts +19 -0
  10. package/components/configuration.values/tsconfig.json +9 -0
  11. package/cucumber.js +8 -0
  12. package/features/site/_app/immutable/asset.js +1 -0
  13. package/features/site/index.html +6 -0
  14. package/features/steps/UI.ts +88 -0
  15. package/features/steps/tsconfig.json +9 -0
  16. package/features/ui.feature +85 -0
  17. package/package.json +14 -7
  18. package/readme.md +160 -47
  19. package/schemas/annotation.cos.yaml +29 -1
  20. package/schemas/manifest.cos.yaml +9 -3
  21. package/source/Aspect.test.ts +84 -8
  22. package/source/Aspect.ts +59 -5
  23. package/source/Client.test.ts +104 -0
  24. package/source/Client.ts +258 -0
  25. package/source/Composition.ts +57 -0
  26. package/source/Factory.ts +28 -5
  27. package/source/Secret.test.ts +29 -0
  28. package/source/Secret.ts +29 -0
  29. package/source/UI.ts +197 -0
  30. package/source/configuration.test.ts +92 -39
  31. package/source/configuration.ts +30 -11
  32. package/source/const.ts +17 -0
  33. package/source/deployment.test.ts +80 -1
  34. package/source/deployment.ts +73 -24
  35. package/source/epoch.test.ts +26 -0
  36. package/source/epoch.ts +21 -0
  37. package/source/index.ts +2 -1
  38. package/transpiled/Aspect.d.ts +18 -4
  39. package/transpiled/Aspect.js +47 -3
  40. package/transpiled/Aspect.js.map +1 -1
  41. package/transpiled/Aspect.test.js +59 -9
  42. package/transpiled/Aspect.test.js.map +1 -1
  43. package/transpiled/Client.d.ts +61 -0
  44. package/transpiled/Client.js +173 -0
  45. package/transpiled/Client.js.map +1 -0
  46. package/transpiled/Client.test.d.ts +1 -0
  47. package/transpiled/Client.test.js +77 -0
  48. package/transpiled/Client.test.js.map +1 -0
  49. package/transpiled/Composition.d.ts +14 -0
  50. package/transpiled/Composition.js +43 -0
  51. package/transpiled/Composition.js.map +1 -0
  52. package/transpiled/Factory.d.ts +8 -2
  53. package/transpiled/Factory.js +17 -2
  54. package/transpiled/Factory.js.map +1 -1
  55. package/transpiled/Secret.d.ts +13 -0
  56. package/transpiled/Secret.js +26 -0
  57. package/transpiled/Secret.js.map +1 -0
  58. package/transpiled/Secret.test.d.ts +1 -0
  59. package/transpiled/Secret.test.js +26 -0
  60. package/transpiled/Secret.test.js.map +1 -0
  61. package/transpiled/UI.d.ts +25 -0
  62. package/transpiled/UI.js +186 -0
  63. package/transpiled/UI.js.map +1 -0
  64. package/transpiled/configuration.d.ts +7 -2
  65. package/transpiled/configuration.js +31 -13
  66. package/transpiled/configuration.js.map +1 -1
  67. package/transpiled/configuration.test.js +84 -37
  68. package/transpiled/configuration.test.js.map +1 -1
  69. package/transpiled/const.d.ts +11 -0
  70. package/transpiled/const.js +14 -0
  71. package/transpiled/const.js.map +1 -0
  72. package/transpiled/deployment.d.ts +10 -4
  73. package/transpiled/deployment.js +57 -21
  74. package/transpiled/deployment.js.map +1 -1
  75. package/transpiled/deployment.test.js +60 -0
  76. package/transpiled/deployment.test.js.map +1 -1
  77. package/transpiled/epoch.d.ts +2 -0
  78. package/transpiled/epoch.js +21 -0
  79. package/transpiled/epoch.js.map +1 -0
  80. package/transpiled/epoch.test.d.ts +1 -0
  81. package/transpiled/epoch.test.js +22 -0
  82. package/transpiled/epoch.test.js.map +1 -0
  83. package/transpiled/index.d.ts +2 -1
  84. package/transpiled/index.js +4 -1
  85. package/transpiled/index.js.map +1 -1
  86. package/transpiled/tsconfig.tsbuildinfo +1 -1
  87. package/ui/.agents/skills/antcn/SKILL.md +91 -0
  88. package/ui/.agents/skills/antcn/references/analytics.md +78 -0
  89. package/ui/.agents/skills/antcn/references/bridge.md +41 -0
  90. package/ui/.agents/skills/antcn/references/clipboard.md +23 -0
  91. package/ui/.agents/skills/antcn/references/dismissable.md +75 -0
  92. package/ui/.agents/skills/antcn/references/dropdown.md +153 -0
  93. package/ui/.agents/skills/antcn/references/fragments.md +29 -0
  94. package/ui/.agents/skills/antcn/references/fullscreen.md +157 -0
  95. package/ui/.agents/skills/antcn/references/geo.md +27 -0
  96. package/ui/.agents/skills/antcn/references/globals.md +31 -0
  97. package/ui/.agents/skills/antcn/references/grammatical-form.md +69 -0
  98. package/ui/.agents/skills/antcn/references/hints.md +44 -0
  99. package/ui/.agents/skills/antcn/references/hold.md +34 -0
  100. package/ui/.agents/skills/antcn/references/iam.md +117 -0
  101. package/ui/.agents/skills/antcn/references/input-form.md +34 -0
  102. package/ui/.agents/skills/antcn/references/locale.md +66 -0
  103. package/ui/.agents/skills/antcn/references/net.md +33 -0
  104. package/ui/.agents/skills/antcn/references/panel.md +44 -0
  105. package/ui/.agents/skills/antcn/references/passkeys.md +27 -0
  106. package/ui/.agents/skills/antcn/references/payments.md +99 -0
  107. package/ui/.agents/skills/antcn/references/realtime.md +69 -0
  108. package/ui/.agents/skills/antcn/references/scrollable.md +39 -0
  109. package/ui/.agents/skills/antcn/references/selector.md +71 -0
  110. package/ui/.agents/skills/antcn/references/shake.md +36 -0
  111. package/ui/.agents/skills/antcn/references/share.md +28 -0
  112. package/ui/.agents/skills/antcn/references/shell.md +139 -0
  113. package/ui/.agents/skills/antcn/references/stack.md +53 -0
  114. package/ui/.agents/skills/antcn/references/system.md +149 -0
  115. package/ui/.agents/skills/antcn/references/taptap.md +28 -0
  116. package/ui/.agents/skills/antcn/references/tools.md +68 -0
  117. package/ui/.agents/skills/antcn/references/transmission.md +96 -0
  118. package/ui/.agents/skills/shadcn-svelte/SKILL.md +227 -0
  119. package/ui/.agents/skills/shadcn-svelte/agents/openai.yml +5 -0
  120. package/ui/.agents/skills/shadcn-svelte/assets/shadcn-svelte-small.png +0 -0
  121. package/ui/.agents/skills/shadcn-svelte/assets/shadcn-svelte.png +0 -0
  122. package/ui/.agents/skills/shadcn-svelte/cli.md +166 -0
  123. package/ui/.agents/skills/shadcn-svelte/customization.md +213 -0
  124. package/ui/.agents/skills/shadcn-svelte/evals/evals.json +47 -0
  125. package/ui/.agents/skills/shadcn-svelte/rules/composition.md +244 -0
  126. package/ui/.agents/skills/shadcn-svelte/rules/forms.md +234 -0
  127. package/ui/.agents/skills/shadcn-svelte/rules/icons.md +107 -0
  128. package/ui/.agents/skills/shadcn-svelte/rules/styling.md +195 -0
  129. package/ui/.agents/skills/svas/SKILL.md +169 -0
  130. package/ui/.agents/skills/svas/references/patterns.md +95 -0
  131. package/ui/.agents/skills/svintl/SKILL.md +176 -0
  132. package/ui/.claude/settings.json +15 -0
  133. package/ui/.codex/hooks.json +15 -0
  134. package/ui/.cursor/hooks.json +11 -0
  135. package/ui/.env.example +1 -0
  136. package/ui/.prettierrc +9 -0
  137. package/ui/.vscode/extensions.json +7 -0
  138. package/ui/.vscode/settings.json +27 -0
  139. package/ui/AGENTS.md +51 -0
  140. package/ui/architecture.md +390 -0
  141. package/ui/components.json +20 -0
  142. package/ui/eslint.config.js +152 -0
  143. package/ui/features/base.ts +2 -0
  144. package/ui/features/boot.feature +5 -0
  145. package/ui/features/steps/authentication.ts +34 -0
  146. package/ui/features/steps/navigaton.ts +37 -0
  147. package/ui/features/steps/typing.ts +24 -0
  148. package/ui/package-lock.json +8173 -0
  149. package/ui/package.json +76 -0
  150. package/ui/playwright.config.ts +13 -0
  151. package/ui/skills-lock.json +30 -0
  152. package/ui/src/@/configuration/index.ts +1 -0
  153. package/ui/src/@/configuration/svc/create.ts +29 -0
  154. package/ui/src/@/configuration/svc/index.ts +3 -0
  155. package/ui/src/@/configuration/svc/net/Configuration.ts +18 -0
  156. package/ui/src/@/configuration/svc/net/index.ts +2 -0
  157. package/ui/src/@/configuration/svc/net/interface.ts +35 -0
  158. package/ui/src/@/configuration/svc/store.ts +14 -0
  159. package/ui/src/@/configuration/ui/Configurations.svelte +85 -0
  160. package/ui/src/@/configuration/ui/Configurations.ts +5 -0
  161. package/ui/src/@/configuration/ui/Create.svelte +64 -0
  162. package/ui/src/@/configuration/ui/Create.ts +7 -0
  163. package/ui/src/@/configuration/ui/Form.svelte +75 -0
  164. package/ui/src/@/configuration/ui/Form.ts +79 -0
  165. package/ui/src/@/configuration/ui/Row.svelte +44 -0
  166. package/ui/src/@/configuration/ui/Row.ts +9 -0
  167. package/ui/src/@/configuration/ui/Value.svelte +33 -0
  168. package/ui/src/@/configuration/ui/Value.ts +6 -0
  169. package/ui/src/@/configuration/ui/index.ts +9 -0
  170. package/ui/src/@/configuration/ui/intl/built.js +38 -0
  171. package/ui/src/@/configuration/ui/intl/context.yaml +51 -0
  172. package/ui/src/@/configuration/ui/intl/en-US.yaml +21 -0
  173. package/ui/src/@/configuration/ui/intl/index.ts +9 -0
  174. package/ui/src/@/configuration/ui/intl/types.ts +31 -0
  175. package/ui/src/@/configuration/ui/read.test.ts +75 -0
  176. package/ui/src/@/configuration/ui/read.ts +102 -0
  177. package/ui/src/@/configuration/ui/ui.test.ts +69 -0
  178. package/ui/src/@/configuration/ui/ui.ts +115 -0
  179. package/ui/src/@/iam/index.ts +1 -0
  180. package/ui/src/@/iam/rc.ts +22 -0
  181. package/ui/src/@/iam/svc/authenticated.ts +17 -0
  182. package/ui/src/@/iam/svc/basic.ts +23 -0
  183. package/ui/src/@/iam/svc/index.ts +10 -0
  184. package/ui/src/@/iam/svc/logout.ts +5 -0
  185. package/ui/src/@/iam/svc/named.ts +16 -0
  186. package/ui/src/@/iam/svc/net/Echo.ts +9 -0
  187. package/ui/src/@/iam/svc/net/basic/index.ts +1 -0
  188. package/ui/src/@/iam/svc/net/basic/interface.ts +15 -0
  189. package/ui/src/@/iam/svc/net/federation/index.ts +1 -0
  190. package/ui/src/@/iam/svc/net/federation/interface.ts +12 -0
  191. package/ui/src/@/iam/svc/net/index.ts +6 -0
  192. package/ui/src/@/iam/svc/net/interface.ts +17 -0
  193. package/ui/src/@/iam/svc/net/otp/index.ts +1 -0
  194. package/ui/src/@/iam/svc/net/otp/interface.ts +14 -0
  195. package/ui/src/@/iam/svc/net/passkeys/index.ts +1 -0
  196. package/ui/src/@/iam/svc/net/passkeys/interface.ts +12 -0
  197. package/ui/src/@/iam/svc/oidc/apple.ts +47 -0
  198. package/ui/src/@/iam/svc/oidc/authenticate.ts +62 -0
  199. package/ui/src/@/iam/svc/oidc/google.ts +45 -0
  200. package/ui/src/@/iam/svc/oidc/hello.ts +82 -0
  201. package/ui/src/@/iam/svc/oidc/index.ts +3 -0
  202. package/ui/src/@/iam/svc/oidc/nonce.ts +5 -0
  203. package/ui/src/@/iam/svc/oidc/providers.ts +28 -0
  204. package/ui/src/@/iam/svc/oidc/standard.ts +28 -0
  205. package/ui/src/@/iam/svc/otp.ts +18 -0
  206. package/ui/src/@/iam/svc/passkeys/create.ts +20 -0
  207. package/ui/src/@/iam/svc/passkeys/index.ts +2 -0
  208. package/ui/src/@/iam/svc/passkeys/login.ts +21 -0
  209. package/ui/src/@/iam/svc/store.ts +36 -0
  210. package/ui/src/@/iam/svc/sync.ts +18 -0
  211. package/ui/src/@/iam/svc/transfer.ts +11 -0
  212. package/ui/src/@/iam/svc/update.ts +8 -0
  213. package/ui/src/@/iam/ui/AccountLike.ts +4 -0
  214. package/ui/src/@/iam/ui/Authenticated.svelte +37 -0
  215. package/ui/src/@/iam/ui/Authenticated.ts +10 -0
  216. package/ui/src/@/iam/ui/Authentication.svelte +50 -0
  217. package/ui/src/@/iam/ui/Authentication.ts +9 -0
  218. package/ui/src/@/iam/ui/Authorized.svelte +32 -0
  219. package/ui/src/@/iam/ui/Authorized.ts +65 -0
  220. package/ui/src/@/iam/ui/Card.svelte +14 -0
  221. package/ui/src/@/iam/ui/Card.ts +7 -0
  222. package/ui/src/@/iam/ui/Refresh.svelte +39 -0
  223. package/ui/src/@/iam/ui/credentials/Credentials.svelte +26 -0
  224. package/ui/src/@/iam/ui/credentials/Credentials.ts +5 -0
  225. package/ui/src/@/iam/ui/credentials/Provider.svelte +24 -0
  226. package/ui/src/@/iam/ui/credentials/Provider.ts +5 -0
  227. package/ui/src/@/iam/ui/credentials/index.ts +1 -0
  228. package/ui/src/@/iam/ui/credentials/passkeys/Key.svelte +42 -0
  229. package/ui/src/@/iam/ui/credentials/passkeys/Key.ts +29 -0
  230. package/ui/src/@/iam/ui/credentials/passkeys/Manager.svelte +83 -0
  231. package/ui/src/@/iam/ui/credentials/passkeys/Manager.ts +5 -0
  232. package/ui/src/@/iam/ui/credentials/passkeys/Passkeys.svelte +39 -0
  233. package/ui/src/@/iam/ui/credentials/passkeys/Summary.svelte +27 -0
  234. package/ui/src/@/iam/ui/credentials/passkeys/Summary.ts +5 -0
  235. package/ui/src/@/iam/ui/credentials/passkeys/index.ts +1 -0
  236. package/ui/src/@/iam/ui/credentials/providers.ts +15 -0
  237. package/ui/src/@/iam/ui/credentials/transfer/Qr.svelte +24 -0
  238. package/ui/src/@/iam/ui/credentials/transfer/Qr.ts +3 -0
  239. package/ui/src/@/iam/ui/credentials/transfer/Transfer.svelte +48 -0
  240. package/ui/src/@/iam/ui/credentials/transfer/Transfer.ts +5 -0
  241. package/ui/src/@/iam/ui/credentials/transfer/index.ts +1 -0
  242. package/ui/src/@/iam/ui/index.ts +3 -0
  243. package/ui/src/@/iam/ui/intl/built.js +79 -0
  244. package/ui/src/@/iam/ui/intl/context.yaml +91 -0
  245. package/ui/src/@/iam/ui/intl/en-US.yaml +64 -0
  246. package/ui/src/@/iam/ui/intl/index.ts +10 -0
  247. package/ui/src/@/iam/ui/intl/types.ts +70 -0
  248. package/ui/src/@/iam/ui/oidc/Authentication.svelte +16 -0
  249. package/ui/src/@/iam/ui/oidc/Authentication.ts +5 -0
  250. package/ui/src/@/iam/ui/oidc/Button.svelte +36 -0
  251. package/ui/src/@/iam/ui/oidc/Button.ts +11 -0
  252. package/ui/src/@/iam/ui/oidc/Refresh.svelte +16 -0
  253. package/ui/src/@/iam/ui/oidc/icons/Apple.svelte +19 -0
  254. package/ui/src/@/iam/ui/oidc/icons/Google.svelte +31 -0
  255. package/ui/src/@/iam/ui/oidc/icons/index.ts +11 -0
  256. package/ui/src/@/iam/ui/oidc/index.ts +2 -0
  257. package/ui/src/@/iam/ui/passkey/Authentication.svelte +64 -0
  258. package/ui/src/@/iam/ui/passkey/Authentication.ts +8 -0
  259. package/ui/src/@/iam/ui/passkey/Create.svelte +53 -0
  260. package/ui/src/@/iam/ui/passkey/Create.ts +7 -0
  261. package/ui/src/@/iam/ui/passkey/Login.svelte +29 -0
  262. package/ui/src/@/iam/ui/passkey/Refresh.svelte +29 -0
  263. package/ui/src/@/iam/ui/passkey/index.ts +2 -0
  264. package/ui/src/@/iam/ui/password/Authentication.svelte +19 -0
  265. package/ui/src/@/iam/ui/password/Authentication.ts +8 -0
  266. package/ui/src/@/iam/ui/password/Form.svelte +151 -0
  267. package/ui/src/@/iam/ui/password/Form.ts +6 -0
  268. package/ui/src/@/iam/ui/password/Password.svelte +39 -0
  269. package/ui/src/@/iam/ui/password/Password.ts +6 -0
  270. package/ui/src/@/iam/ui/password/Refresh.svelte +5 -0
  271. package/ui/src/@/iam/ui/password/index.ts +2 -0
  272. package/ui/src/@/net/index.ts +1 -0
  273. package/ui/src/@/net/svc/index.ts +3 -0
  274. package/ui/src/@/net/svc/origin.ts +8 -0
  275. package/ui/src/@/net/svc/query.test.ts +45 -0
  276. package/ui/src/@/net/svc/query.ts +25 -0
  277. package/ui/src/@/passkeys/index.ts +1 -0
  278. package/ui/src/@/passkeys/svc/add.ts +15 -0
  279. package/ui/src/@/passkeys/svc/create.ts +58 -0
  280. package/ui/src/@/passkeys/svc/credentials/convert.ts +32 -0
  281. package/ui/src/@/passkeys/svc/credentials/create.ts +34 -0
  282. package/ui/src/@/passkeys/svc/credentials/get.ts +14 -0
  283. package/ui/src/@/passkeys/svc/credentials/index.ts +3 -0
  284. package/ui/src/@/passkeys/svc/credentials/key.ts +10 -0
  285. package/ui/src/@/passkeys/svc/get.ts +10 -0
  286. package/ui/src/@/passkeys/svc/index.ts +6 -0
  287. package/ui/src/@/passkeys/svc/net/CreationResponse.ts +15 -0
  288. package/ui/src/@/passkeys/svc/net/Passkey.ts +8 -0
  289. package/ui/src/@/passkeys/svc/net/RequestResponse.ts +12 -0
  290. package/ui/src/@/passkeys/svc/net/challenges/Options.ts +21 -0
  291. package/ui/src/@/passkeys/svc/net/challenges/index.ts +2 -0
  292. package/ui/src/@/passkeys/svc/net/challenges/interface.ts +16 -0
  293. package/ui/src/@/passkeys/svc/net/index.ts +4 -0
  294. package/ui/src/@/passkeys/svc/net/interface.ts +29 -0
  295. package/ui/src/@/passkeys/svc/remove.ts +13 -0
  296. package/ui/src/@/passkeys/svc/request.ts +50 -0
  297. package/ui/src/@/passkeys/svc/store.ts +13 -0
  298. package/ui/src/@/passkeys/svc/supported.ts +1 -0
  299. package/ui/src/@/passkeys/ui/aaguid.json +150 -0
  300. package/ui/src/@/realtime/events.ts +1 -0
  301. package/ui/src/@/realtime/index.ts +1 -0
  302. package/ui/src/@/realtime/rc.ts +13 -0
  303. package/ui/src/@/realtime/svc/connect.ts +67 -0
  304. package/ui/src/@/realtime/svc/events.ts +17 -0
  305. package/ui/src/@/realtime/svc/index.ts +5 -0
  306. package/ui/src/@/realtime/svc/net/Message.ts +6 -0
  307. package/ui/src/@/realtime/svc/net/index.ts +2 -0
  308. package/ui/src/@/realtime/svc/net/interface.ts +13 -0
  309. package/ui/src/@/realtime/svc/reset.ts +5 -0
  310. package/ui/src/@/realtime/svc/status.ts +12 -0
  311. package/ui/src/@/realtime/svc/store.ts +30 -0
  312. package/ui/src/@/realtime/svc/time.ts +15 -0
  313. package/ui/src/app.d.ts +20 -0
  314. package/ui/src/app.html +13 -0
  315. package/ui/src/config/index.ts +70 -0
  316. package/ui/src/lib/assets/favicon.svg +1 -0
  317. package/ui/src/lib/components/clipboard/Clipboard.svelte +63 -0
  318. package/ui/src/lib/components/clipboard/Clipboard.ts +12 -0
  319. package/ui/src/lib/components/clipboard/index.ts +1 -0
  320. package/ui/src/lib/components/dismissable/Dismissable.svelte +81 -0
  321. package/ui/src/lib/components/dismissable/Dismissable.ts +7 -0
  322. package/ui/src/lib/components/dismissable/index.ts +1 -0
  323. package/ui/src/lib/components/dropdown/Back.svelte +14 -0
  324. package/ui/src/lib/components/dropdown/Back.ts +3 -0
  325. package/ui/src/lib/components/dropdown/Content.svelte +76 -0
  326. package/ui/src/lib/components/dropdown/Content.ts +13 -0
  327. package/ui/src/lib/components/dropdown/Context.ts +18 -0
  328. package/ui/src/lib/components/dropdown/Group.svelte +24 -0
  329. package/ui/src/lib/components/dropdown/Group.ts +8 -0
  330. package/ui/src/lib/components/dropdown/GroupContext.ts +15 -0
  331. package/ui/src/lib/components/dropdown/Item.svelte +31 -0
  332. package/ui/src/lib/components/dropdown/Item.ts +5 -0
  333. package/ui/src/lib/components/dropdown/Layer.svelte +11 -0
  334. package/ui/src/lib/components/dropdown/Layer.ts +7 -0
  335. package/ui/src/lib/components/dropdown/Root.svelte +88 -0
  336. package/ui/src/lib/components/dropdown/Root.ts +6 -0
  337. package/ui/src/lib/components/dropdown/Separator.svelte +13 -0
  338. package/ui/src/lib/components/dropdown/Separator.ts +5 -0
  339. package/ui/src/lib/components/dropdown/Trigger.svelte +33 -0
  340. package/ui/src/lib/components/dropdown/Trigger.ts +5 -0
  341. package/ui/src/lib/components/dropdown/index.ts +8 -0
  342. package/ui/src/lib/components/fullscreen/Fullscreen.svelte +97 -0
  343. package/ui/src/lib/components/fullscreen/Fullscreen.ts +18 -0
  344. package/ui/src/lib/components/fullscreen/Overlay.svelte +15 -0
  345. package/ui/src/lib/components/fullscreen/Overlay.ts +7 -0
  346. package/ui/src/lib/components/fullscreen/index.ts +2 -0
  347. package/ui/src/lib/components/hold/Hold.svelte +133 -0
  348. package/ui/src/lib/components/hold/Hold.ts +23 -0
  349. package/ui/src/lib/components/hold/index.ts +1 -0
  350. package/ui/src/lib/components/scrollable/Scrollable.svelte +49 -0
  351. package/ui/src/lib/components/scrollable/Scrollable.ts +117 -0
  352. package/ui/src/lib/components/scrollable/index.ts +2 -0
  353. package/ui/src/lib/components/shake/Shake.svelte +62 -0
  354. package/ui/src/lib/components/shake/Shake.ts +7 -0
  355. package/ui/src/lib/components/shake/index.ts +1 -0
  356. package/ui/src/lib/components/share/Share.svelte +58 -0
  357. package/ui/src/lib/components/share/Share.ts +9 -0
  358. package/ui/src/lib/components/share/index.ts +1 -0
  359. package/ui/src/lib/components/shell/Attention.svelte +11 -0
  360. package/ui/src/lib/components/shell/Attention.ts +6 -0
  361. package/ui/src/lib/components/shell/Header.svelte +18 -0
  362. package/ui/src/lib/components/shell/Header.ts +7 -0
  363. package/ui/src/lib/components/shell/Screen.svelte +28 -0
  364. package/ui/src/lib/components/shell/Screen.ts +11 -0
  365. package/ui/src/lib/components/shell/Sticky.svelte +23 -0
  366. package/ui/src/lib/components/shell/Sticky.ts +8 -0
  367. package/ui/src/lib/components/shell/Underlay.svelte +21 -0
  368. package/ui/src/lib/components/shell/Underlay.ts +6 -0
  369. package/ui/src/lib/components/shell/index.ts +6 -0
  370. package/ui/src/lib/components/shell/nav/Actions.svelte +31 -0
  371. package/ui/src/lib/components/shell/nav/Actions.ts +16 -0
  372. package/ui/src/lib/components/shell/nav/Back.svelte +20 -0
  373. package/ui/src/lib/components/shell/nav/Back.ts +9 -0
  374. package/ui/src/lib/components/shell/nav/Bar.svelte +24 -0
  375. package/ui/src/lib/components/shell/nav/Bar.ts +3 -0
  376. package/ui/src/lib/components/shell/nav/Button.svelte +64 -0
  377. package/ui/src/lib/components/shell/nav/Button.ts +7 -0
  378. package/ui/src/lib/components/shell/nav/Nav.svelte +62 -0
  379. package/ui/src/lib/components/shell/nav/Nav.ts +35 -0
  380. package/ui/src/lib/components/shell/nav/Return.svelte +29 -0
  381. package/ui/src/lib/components/shell/nav/Return.ts +15 -0
  382. package/ui/src/lib/components/shell/nav/Sections.svelte +58 -0
  383. package/ui/src/lib/components/shell/nav/Sections.ts +6 -0
  384. package/ui/src/lib/components/shell/nav/Toolbar.svelte +73 -0
  385. package/ui/src/lib/components/shell/nav/Toolbar.ts +3 -0
  386. package/ui/src/lib/components/shell/nav/history.ts +36 -0
  387. package/ui/src/lib/components/shell/nav/index.ts +5 -0
  388. package/ui/src/lib/components/shell/nav/store.ts +24 -0
  389. package/ui/src/lib/components/ui/alert/alert-action.svelte +20 -0
  390. package/ui/src/lib/components/ui/alert/alert-description.svelte +23 -0
  391. package/ui/src/lib/components/ui/alert/alert-title.svelte +23 -0
  392. package/ui/src/lib/components/ui/alert/alert.svelte +43 -0
  393. package/ui/src/lib/components/ui/alert/index.ts +17 -0
  394. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +27 -0
  395. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +27 -0
  396. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte +32 -0
  397. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte +17 -0
  398. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte +23 -0
  399. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
  400. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte +20 -0
  401. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte +17 -0
  402. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte +7 -0
  403. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte +17 -0
  404. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte +7 -0
  405. package/ui/src/lib/components/ui/alert-dialog/alert-dialog.svelte +7 -0
  406. package/ui/src/lib/components/ui/alert-dialog/index.ts +40 -0
  407. package/ui/src/lib/components/ui/badge/badge.svelte +49 -0
  408. package/ui/src/lib/components/ui/badge/index.ts +2 -0
  409. package/ui/src/lib/components/ui/button/button.svelte +82 -0
  410. package/ui/src/lib/components/ui/button/index.ts +17 -0
  411. package/ui/src/lib/components/ui/button-group/button-group-separator.svelte +23 -0
  412. package/ui/src/lib/components/ui/button-group/button-group-text.svelte +28 -0
  413. package/ui/src/lib/components/ui/button-group/button-group.svelte +46 -0
  414. package/ui/src/lib/components/ui/button-group/index.ts +15 -0
  415. package/ui/src/lib/components/ui/card/card-action.svelte +23 -0
  416. package/ui/src/lib/components/ui/card/card-content.svelte +20 -0
  417. package/ui/src/lib/components/ui/card/card-description.svelte +20 -0
  418. package/ui/src/lib/components/ui/card/card-footer.svelte +20 -0
  419. package/ui/src/lib/components/ui/card/card-header.svelte +23 -0
  420. package/ui/src/lib/components/ui/card/card-title.svelte +20 -0
  421. package/ui/src/lib/components/ui/card/card.svelte +22 -0
  422. package/ui/src/lib/components/ui/card/index.ts +25 -0
  423. package/ui/src/lib/components/ui/checkbox/checkbox.svelte +39 -0
  424. package/ui/src/lib/components/ui/checkbox/index.ts +6 -0
  425. package/ui/src/lib/components/ui/collapsible/collapsible-content.svelte +7 -0
  426. package/ui/src/lib/components/ui/collapsible/collapsible-trigger.svelte +7 -0
  427. package/ui/src/lib/components/ui/collapsible/collapsible.svelte +20 -0
  428. package/ui/src/lib/components/ui/collapsible/index.ts +13 -0
  429. package/ui/src/lib/components/ui/input/index.ts +7 -0
  430. package/ui/src/lib/components/ui/input/input.svelte +48 -0
  431. package/ui/src/lib/components/ui/input-otp/index.ts +15 -0
  432. package/ui/src/lib/components/ui/input-otp/input-otp-group.svelte +20 -0
  433. package/ui/src/lib/components/ui/input-otp/input-otp-separator.svelte +27 -0
  434. package/ui/src/lib/components/ui/input-otp/input-otp-slot.svelte +31 -0
  435. package/ui/src/lib/components/ui/input-otp/input-otp.svelte +23 -0
  436. package/ui/src/lib/components/ui/item/index.ts +34 -0
  437. package/ui/src/lib/components/ui/item/item-actions.svelte +20 -0
  438. package/ui/src/lib/components/ui/item/item-content.svelte +23 -0
  439. package/ui/src/lib/components/ui/item/item-description.svelte +23 -0
  440. package/ui/src/lib/components/ui/item/item-footer.svelte +20 -0
  441. package/ui/src/lib/components/ui/item/item-group.svelte +21 -0
  442. package/ui/src/lib/components/ui/item/item-header.svelte +20 -0
  443. package/ui/src/lib/components/ui/item/item-media.svelte +42 -0
  444. package/ui/src/lib/components/ui/item/item-separator.svelte +19 -0
  445. package/ui/src/lib/components/ui/item/item-title.svelte +20 -0
  446. package/ui/src/lib/components/ui/item/item.svelte +61 -0
  447. package/ui/src/lib/components/ui/kbd/index.ts +10 -0
  448. package/ui/src/lib/components/ui/kbd/kbd-group.svelte +20 -0
  449. package/ui/src/lib/components/ui/kbd/kbd.svelte +23 -0
  450. package/ui/src/lib/components/ui/label/index.ts +7 -0
  451. package/ui/src/lib/components/ui/label/label.svelte +20 -0
  452. package/ui/src/lib/components/ui/progress/index.ts +7 -0
  453. package/ui/src/lib/components/ui/progress/progress.svelte +27 -0
  454. package/ui/src/lib/components/ui/select/index.ts +37 -0
  455. package/ui/src/lib/components/ui/select/select-content.svelte +45 -0
  456. package/ui/src/lib/components/ui/select/select-group-heading.svelte +21 -0
  457. package/ui/src/lib/components/ui/select/select-group.svelte +17 -0
  458. package/ui/src/lib/components/ui/select/select-item.svelte +40 -0
  459. package/ui/src/lib/components/ui/select/select-label.svelte +20 -0
  460. package/ui/src/lib/components/ui/select/select-portal.svelte +7 -0
  461. package/ui/src/lib/components/ui/select/select-scroll-down-button.svelte +20 -0
  462. package/ui/src/lib/components/ui/select/select-scroll-up-button.svelte +20 -0
  463. package/ui/src/lib/components/ui/select/select-separator.svelte +18 -0
  464. package/ui/src/lib/components/ui/select/select-trigger.svelte +29 -0
  465. package/ui/src/lib/components/ui/select/select.svelte +11 -0
  466. package/ui/src/lib/components/ui/separator/index.ts +7 -0
  467. package/ui/src/lib/components/ui/separator/separator.svelte +23 -0
  468. package/ui/src/lib/components/ui/spinner/index.ts +1 -0
  469. package/ui/src/lib/components/ui/spinner/spinner.svelte +18 -0
  470. package/ui/src/lib/components/ui/tabs/index.ts +18 -0
  471. package/ui/src/lib/components/ui/tabs/tabs-content.svelte +17 -0
  472. package/ui/src/lib/components/ui/tabs/tabs-list.svelte +40 -0
  473. package/ui/src/lib/components/ui/tabs/tabs-trigger.svelte +23 -0
  474. package/ui/src/lib/components/ui/tabs/tabs.svelte +19 -0
  475. package/ui/src/lib/components/ui/textarea/index.ts +7 -0
  476. package/ui/src/lib/components/ui/textarea/textarea.svelte +22 -0
  477. package/ui/src/lib/intl/bcp.ts +25 -0
  478. package/ui/src/lib/intl/built.js +18 -0
  479. package/ui/src/lib/intl/context.yaml +18 -0
  480. package/ui/src/lib/intl/en-US.yaml +6 -0
  481. package/ui/src/lib/intl/index.ts +65 -0
  482. package/ui/src/lib/intl/types.ts +19 -0
  483. package/ui/src/lib/tools/ago.ts +10 -0
  484. package/ui/src/lib/tools/assert.ts +3 -0
  485. package/ui/src/lib/tools/cap.ts +5 -0
  486. package/ui/src/lib/tools/clicks.ts +25 -0
  487. package/ui/src/lib/tools/contextmenu.ts +19 -0
  488. package/ui/src/lib/tools/convert.ts +32 -0
  489. package/ui/src/lib/tools/currency.test.ts +10 -0
  490. package/ui/src/lib/tools/currency.ts +55 -0
  491. package/ui/src/lib/tools/date.test.ts +21 -0
  492. package/ui/src/lib/tools/date.ts +35 -0
  493. package/ui/src/lib/tools/delay.ts +7 -0
  494. package/ui/src/lib/tools/image.ts +39 -0
  495. package/ui/src/lib/tools/index.ts +20 -0
  496. package/ui/src/lib/tools/location.ts +41 -0
  497. package/ui/src/lib/tools/metronome.ts +11 -0
  498. package/ui/src/lib/tools/mq.ts +84 -0
  499. package/ui/src/lib/tools/onsubmit.ts +21 -0
  500. package/ui/src/lib/tools/random.ts +15 -0
  501. package/ui/src/lib/tools/search.ts +25 -0
  502. package/ui/src/lib/tools/timeout.ts +26 -0
  503. package/ui/src/lib/tools/transition.ts +207 -0
  504. package/ui/src/lib/tools/types.ts +3 -0
  505. package/ui/src/lib/tools/uuid.test.ts +28 -0
  506. package/ui/src/lib/tools/uuid.ts +9 -0
  507. package/ui/src/lib/typeset.css +502 -0
  508. package/ui/src/lib/utils.ts +12 -0
  509. package/ui/src/routes/(private)/+layout.svelte +112 -0
  510. package/ui/src/routes/(private)/+page.svelte +7 -0
  511. package/ui/src/routes/(private)/[component]/+page.svelte +77 -0
  512. package/ui/src/routes/+layout.svelte +25 -0
  513. package/ui/src/routes/+layout.ts +14 -0
  514. package/ui/src/routes/layout.css +232 -0
  515. package/ui/static/robots.txt +3 -0
  516. package/ui/svelte.config.js +36 -0
  517. package/ui/tools/feat.js +43 -0
  518. package/ui/tools/hooks/README.md +13 -0
  519. package/ui/tools/hooks/guard-intl.sh +40 -0
  520. package/ui/tools/shad.js +7 -0
  521. package/ui/tsconfig.json +20 -0
  522. package/ui/vite.config.ts +8 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,216 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.0.0-alpha.274](https://github.com/toa-io/toa/compare/v1.0.0-alpha.273...v1.0.0-alpha.274) (2026-09-02)
7
+
8
+
9
+ * Configuration is served by a component, followed live, and kept per epoch (#1017) ([b05997d](https://github.com/toa-io/toa/commit/b05997d3adb784f238a222cb46878b23859339a2)), closes [#1017](https://github.com/toa-io/toa/issues/1017)
10
+
11
+
12
+ ### Features
13
+
14
+ * **configuration:** drop the label from the epoch ([4baaff5](https://github.com/toa-io/toa/commit/4baaff5b22d00719142a65d56b50a1b100b29fbd))
15
+
16
+
17
+ ### BREAKING CHANGES
18
+
19
+ * a secret configuration value is an object, not a string;
20
+ read it with `unwrap()`.
21
+
22
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
23
+
24
+ * test(configuration): wait for the second round rather than assume it
25
+
26
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
27
+
28
+ * refactor(configuration)!: read a secret with its own unwrap
29
+
30
+ Component code depends on no Toa package, so a secret is read as
31
+ `context.configuration.apiKey.unwrap()` and the helper in `@toa.io/generic`
32
+ goes. A value a component reads as a secret is therefore given as a reference:
33
+ `identity.basic` no longer defaults `pepper` to `''`, the development context
34
+ and the feature harness give the token keys, the federation client secret and
35
+ the signing key as references, and the harness has a step for the secrets a
36
+ scenario refers to. CONTRIBUTING states the rule.
37
+ * `identity.basic` `pepper` has no default; a value read as a
38
+ secret must be given as a `$NAME` reference.
39
+
40
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
41
+
42
+ * feat(configuration): list the configurations
43
+
44
+ `configuration.values.list` returns every component's configuration for its
45
+ deployed epoch, by component name, and `GET /configuration/values/` serves it
46
+ behind `system:configuration:get`.
47
+
48
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
49
+
50
+ * fix(exposition): write a value in YAML the way its toJSON says
51
+
52
+ A redacted secret in a reply was dumped as an empty object; it is written as
53
+ `<REDACTED>`, as JSON and msgpack already write it.
54
+
55
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
56
+
57
+ * test(configuration): a secret is an object, and stays redacted in a reply
58
+
59
+ A component with `{ a: 1, b: $SECRET_B }` returns its configuration as
60
+ `{ a: 1, b: '<REDACTED>' }` and the secret itself through `unwrap()`. The reply
61
+ step also accepts a reply as a caller across a process boundary receives it,
62
+ since a call within the process hands the object over as it is.
63
+
64
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
65
+
66
+ * chore(schemas): bump the dependencies
67
+
68
+ ajv 8.18.0 to 8.20.0, ajv-formats 2.1.1 to 3.0.1, better-ajv-errors 1.2.0
69
+ to 2.0.3, fast-glob 3.2.12 to 3.3.3 and js-yaml 4.3.1 to 5.4.1 — the version
70
+ exposition already uses. The three majors keep the CommonJS entry points this
71
+ library calls: ajv-formats as a function, better-ajv-errors as .default, and
72
+ js-yaml's load.
73
+
74
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
75
+
76
+ * feat(configuration)!: serve the schema with the value
77
+
78
+ GET /configuration/values/:component/ answers { configuration, schema, epoch }
79
+ where it answered with the configuration alone, and list carries the schema of
80
+ every component. Nothing reads a configuration without needing to know what it
81
+ is checked against, and the schema was only ever on the values service.
82
+
83
+ An epoch the deployment does not know has no schema; the value stored for it
84
+ is still returned.
85
+
86
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
87
+
88
+ * feat(configuration): publish a configuration UI
89
+
90
+ The values service serves a page at /.configuration on port 8003, out of the
91
+ directory ui builds: the configured components, a screen per component showing
92
+ what it holds now, and a dialog creating the next one. Reading needs
93
+ system:configuration:get and creating needs system:configuration:create.
94
+
95
+ A configuration is immutable, so the dialog opens on the current value and what
96
+ is left out of it is left out of the component. The editor takes YAML, the
97
+ schema is applied before anything is sent, and a secret is a reference the page
98
+ never shows.
99
+
100
+ The page is always published: the annotation is the per-component values map
101
+ and has nowhere to carry a switch.
102
+
103
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
104
+
105
+ * feat(introspection): link a component to its configuration
106
+
107
+ A card carrying @toa.io/extensions.configuration reads that extension as a link
108
+ to the configuration UI rather than as a name, and configuration joins the
109
+ namespaces the runtime provides, so its components band under System.
110
+
111
+ Deployed, both pages sit behind the same ingress and the path alone is right;
112
+ locally each console has its own port.
113
+
114
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
115
+
116
+ * feat(introspection): scroll the map, zoom with a modifier
117
+
118
+ The map was grabbed to move and zoomed with a bare wheel, which is neither what
119
+ a page does nor what the wheel does anywhere else. A plain scroll now pans on
120
+ both axes and the wheel scales only with the modifier held — a trackpad pinch
121
+ arrives as one of those on every platform.
122
+
123
+ A card's own scrollable box keeps its wheel, in both paths.
124
+
125
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
126
+
127
+ * refactor(introspection): centre the filter in the header
128
+
129
+ The sides take equal space, which is what leaves the filter between them.
130
+ Neither side may shrink under what it holds, or the tabs run out from under
131
+ their side and across the filter, and the filter across the sign-out button;
132
+ the title gives way instead.
133
+
134
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
135
+
136
+ * fix(configuration): connect the UI to the values service
137
+
138
+ The page was declared as a dependency from inside `open`, and a connector connects
139
+ what it depends on before `open` runs — so the server was constructed and never
140
+ listened. Nothing caught it: the UI feature builds the server itself.
141
+
142
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
143
+
144
+ * feat(configuration)!: reserve resources in the annotation
145
+
146
+ The values service deploys like any other and must state what it may take, but the
147
+ annotation is a map of component ids and had nowhere to put it — so `toa env` failed
148
+ for every context using configuration unless it declared a context-wide `resources`.
149
+
150
+ `resources` is now the service's own, read the way `introspection` and `realtime` read
151
+ theirs. A component actually named `resources` is written `default.resources`, which is
152
+ what its id is anyway.
153
+
154
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
155
+
156
+ * feat(configuration): follow the system colour scheme
157
+
158
+ The dark tokens were behind a `.dark` class nothing sets, and the `dark:` variant was
159
+ pointed at that class too — so a component's own dark styling never applied either.
160
+ Both now key off `prefers-color-scheme`, and `color-scheme` hands the native chrome
161
+ the same answer.
162
+
163
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
164
+
165
+ * feat(introspection): follow the system colour scheme
166
+
167
+ The dark tokens were behind a `.dark` class nothing sets, and the `dark:` variant was
168
+ pointed at that class too — so a component's own dark styling never applied either.
169
+ Both now key off `prefers-color-scheme`, and `color-scheme` hands the native chrome
170
+ the same answer.
171
+
172
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
173
+
174
+ * feat(configuration): present a change as an edit of what is there
175
+
176
+ A configuration is immutable and creating one replaces the whole of it, but the dialog
177
+ opens on the current value and the page never shows an older one — so what the reader
178
+ does is edit. The words follow: Edit rather than New, Update rather than Create, and
179
+ the paragraph explaining the model goes, along with the field's label, which the title
180
+ above it already said.
181
+
182
+ The editor also stayed as wide as its longest line — `field-sizing: content` sizes to
183
+ content, and no `max-width` clamps that — so a long value painted outside the dialog.
184
+ It is fixed now, the dialog takes the width the screen has rather than a fixed step,
185
+ and the band held for errors no longer leaves a gap when there are none.
186
+
187
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
188
+
189
+ * feat(configuration): mark a component that keeps a secret
190
+
191
+ A key after the name on the row, wherever the configuration holds a reference, however
192
+ deep. The predicate reads the same lines the value screen renders, so the two cannot
193
+ disagree about what counts as a secret.
194
+
195
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
196
+
197
+ * feat(configuration): lead back to the list from the title
198
+
199
+ Every address ends in a slash, so the way up is the address itself on the list and one
200
+ level above it on a component's screen — which holds wherever the page is mounted.
201
+
202
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
203
+
204
+
205
+
206
+
207
+
208
+ # [1.0.0-alpha.273](https://github.com/toa-io/toa/compare/v1.0.0-alpha.272...v1.0.0-alpha.273) (2026-09-02)
209
+
210
+ **Note:** Version bump only for package @toa.io/extensions.configuration
211
+
212
+
213
+
214
+
215
+
6
216
  # [1.0.0-alpha.272](https://github.com/toa-io/toa/compare/v1.0.0-alpha.271...v1.0.0-alpha.272) (2026-09-01)
7
217
 
8
218
  **Note:** Version bump only for package @toa.io/extensions.configuration
@@ -0,0 +1,158 @@
1
+ namespace: configuration
2
+ name: values
3
+
4
+ # One document per configuration created. Documents are immutable: a change is a new
5
+ # document, and the latest one for a component and an epoch is the last created.
6
+ # What every component's epoch, schema and defaults are, the service is told on
7
+ # deployment (`TOA_CONFIGURATION_VALUES`). A created object is published as the
8
+ # prototype's `created` event.
9
+
10
+ entity:
11
+ schema:
12
+ type: object
13
+ properties:
14
+ component:
15
+ type: string
16
+ epoch:
17
+ type: string
18
+ configuration:
19
+ type: object
20
+ originator:
21
+ type: string
22
+ required:
23
+ - component
24
+ - epoch
25
+ - configuration
26
+ - originator
27
+ index:
28
+ lookup:
29
+ component: asc
30
+ epoch: asc
31
+ _created: desc
32
+
33
+ operations:
34
+ # the latest configuration of a component: created, else deployed defaults, else none
35
+ get:
36
+ query: false
37
+ input:
38
+ type: object
39
+ properties:
40
+ component:
41
+ type: string
42
+ epoch:
43
+ type: string
44
+ required:
45
+ - component
46
+ # the value and the schema it is checked against, so a caller can show and check it
47
+ output:
48
+ type: object
49
+ nullable: true
50
+ properties:
51
+ configuration:
52
+ type: object
53
+ schema:
54
+ type: object
55
+ epoch:
56
+ type: string
57
+ required:
58
+ - configuration
59
+ - epoch
60
+ # the same for many at once, as the aspects of one process ask
61
+ fetch:
62
+ query: false
63
+ input:
64
+ type: array
65
+ items:
66
+ type: object
67
+ properties:
68
+ component:
69
+ type: string
70
+ epoch:
71
+ type: string
72
+ required:
73
+ - component
74
+ - epoch
75
+ output:
76
+ type: array
77
+ items:
78
+ type: object
79
+ properties:
80
+ component:
81
+ type: string
82
+ epoch:
83
+ type: string
84
+ configuration:
85
+ type: object
86
+ nullable: true
87
+ created:
88
+ type: integer
89
+ required:
90
+ - component
91
+ - epoch
92
+ - configuration
93
+ - created
94
+ # every component's configuration for its deployed epoch, by component name
95
+ list:
96
+ query: false
97
+ output:
98
+ type: array
99
+ items:
100
+ type: object
101
+ properties:
102
+ component:
103
+ type: string
104
+ epoch:
105
+ type: string
106
+ schema:
107
+ type: object
108
+ configuration:
109
+ type: object
110
+ required:
111
+ - component
112
+ - epoch
113
+ - schema
114
+ - configuration
115
+ create:
116
+ query: false
117
+ input:
118
+ type: object
119
+ properties:
120
+ component:
121
+ type: string
122
+ configuration:
123
+ type: object
124
+ originator:
125
+ type: object
126
+ properties:
127
+ id:
128
+ type: string
129
+ required:
130
+ - id
131
+ required:
132
+ - component
133
+ - configuration
134
+ - originator
135
+ errors:
136
+ - UNKNOWN_COMPONENT
137
+ - INVALID_CONFIGURATION
138
+
139
+ exposition:
140
+ isolated: true
141
+ /:
142
+ GET:
143
+ io:output: true
144
+ auth:role: system:configuration:get
145
+ endpoint: list
146
+ /:component:
147
+ map:segments:
148
+ component: component
149
+ GET:
150
+ io:output: true
151
+ auth:role: system:configuration:get
152
+ endpoint: get
153
+ POST:
154
+ io:output: [id, epoch]
155
+ auth:rule:
156
+ role: system:configuration:create
157
+ delegate: originator
158
+ endpoint: create
@@ -0,0 +1,56 @@
1
+ import * as schemas from '@toa.io/schemas'
2
+ import { entry } from './lib/map'
3
+ import type { Schema } from '@toa.io/schemas'
4
+
5
+ export async function transition (input: Input, object: Entity): Promise<Entity | Error> {
6
+ const known = entry(input.component)
7
+
8
+ if (known === undefined)
9
+ return new UnknownComponentError(input.component)
10
+
11
+ // the schema fills its defaults, so what is stored is whole
12
+ const configuration = structuredClone(input.configuration)
13
+
14
+ const schema: Schema<any> = schemas.schema(known.schema)
15
+
16
+ try {
17
+ schema.validate(configuration)
18
+ } catch (error) {
19
+ return new InvalidConfigurationError((error as Error).message)
20
+ }
21
+
22
+ object.component = input.component
23
+ object.epoch = known.epoch
24
+ object.configuration = configuration
25
+ object.originator = input.originator.id
26
+
27
+ return object
28
+ }
29
+
30
+ class UnknownComponentError extends Error {
31
+ public readonly code = 'UNKNOWN_COMPONENT'
32
+
33
+ public constructor (component: string) {
34
+ super(`Component '${component}' is not configured`)
35
+ }
36
+ }
37
+
38
+ class InvalidConfigurationError extends Error {
39
+ public readonly code = 'INVALID_CONFIGURATION'
40
+ }
41
+
42
+ interface Input {
43
+ component: string
44
+ configuration: object
45
+ originator: {
46
+ id: string
47
+ }
48
+ }
49
+
50
+ interface Entity {
51
+ id: string
52
+ component: string
53
+ epoch: string
54
+ configuration: object
55
+ originator: string
56
+ }
@@ -0,0 +1,24 @@
1
+ import { resolve, type Context } from './lib/resolve'
2
+
3
+ export async function computation (input: Pair[], context: Context): Promise<Fetched[]> {
4
+ return await Promise.all(input.map(async ({ component, epoch }) => {
5
+ const value = await resolve(context, component, epoch)
6
+
7
+ return {
8
+ component,
9
+ epoch,
10
+ configuration: value === null ? null : value.configuration,
11
+ created: value === null ? 0 : value.created
12
+ }
13
+ }))
14
+ }
15
+
16
+ interface Pair {
17
+ component: string
18
+ epoch: string
19
+ }
20
+
21
+ interface Fetched extends Pair {
22
+ configuration: object | null
23
+ created: number
24
+ }
@@ -0,0 +1,33 @@
1
+ import { entry } from './lib/map'
2
+ import { resolve, type Context } from './lib/resolve'
3
+
4
+ /**
5
+ * The latest configuration of a component, with the schema it is checked against. The
6
+ * schema is the deployment's, so an epoch the deployment does not know has none — the
7
+ * value is still what was stored for it.
8
+ */
9
+ export async function computation (input: Input, context: Context): Promise<Item | null> {
10
+ const value = await resolve(context, input.component, input.epoch)
11
+
12
+ if (value === null)
13
+ return null
14
+
15
+ const known = entry(input.component)
16
+
17
+ return {
18
+ configuration: value.configuration,
19
+ schema: known?.schema,
20
+ epoch: input.epoch ?? known!.epoch
21
+ }
22
+ }
23
+
24
+ interface Input {
25
+ component: string
26
+ epoch?: string
27
+ }
28
+
29
+ interface Item {
30
+ configuration: object
31
+ schema?: object
32
+ epoch: string
33
+ }
@@ -0,0 +1,34 @@
1
+ import { VARIABLE, components, entry } from './map'
2
+
3
+ afterEach(() => {
4
+ delete process.env[VARIABLE]
5
+ })
6
+
7
+ it('should be empty without the variable', () => {
8
+ expect(entry('a.b')).toBeUndefined()
9
+ })
10
+
11
+ it('should read the variable', () => {
12
+ const values = { 'a.b': { epoch: 'e', schema: { type: 'object' }, defaults: { foo: 1 } } }
13
+
14
+ process.env[VARIABLE] = JSON.stringify(values)
15
+
16
+ expect(entry('a.b')).toStrictEqual(values['a.b'])
17
+ expect(entry('a.c')).toBeUndefined()
18
+ })
19
+
20
+ it('should follow the variable', () => {
21
+ process.env[VARIABLE] = JSON.stringify({ 'a.b': { epoch: 'e1', schema: {} } })
22
+
23
+ expect(entry('a.b')?.epoch).toStrictEqual('e1')
24
+
25
+ process.env[VARIABLE] = JSON.stringify({ 'a.b': { epoch: 'e2', schema: {} } })
26
+
27
+ expect(entry('a.b')?.epoch).toStrictEqual('e2')
28
+ })
29
+
30
+ it('should list the components by name', () => {
31
+ process.env[VARIABLE] = JSON.stringify({ 'b.two': { epoch: 'e', schema: {} }, 'a.one': { epoch: 'e', schema: {} } })
32
+
33
+ expect(components()).toStrictEqual(['a.one', 'b.two'])
34
+ })
@@ -0,0 +1,34 @@
1
+ /** What the deployment told the service about every configured component. */
2
+ export function entry (component: string): Entry | undefined {
3
+ return read()[component]
4
+ }
5
+
6
+ /** The configured components, by name. */
7
+ export function components (): string[] {
8
+ return Object.keys(read()).sort()
9
+ }
10
+
11
+ function read (): Values {
12
+ const source = process.env[VARIABLE] ?? '{}'
13
+
14
+ // read again once the variable changes, as it does between scenarios of one process
15
+ if (source !== parsed) {
16
+ values = JSON.parse(source) as Values
17
+ parsed = source
18
+ }
19
+
20
+ return values
21
+ }
22
+
23
+ let parsed: string | null = null
24
+ let values: Values = {}
25
+
26
+ export const VARIABLE = 'TOA_CONFIGURATION_VALUES'
27
+
28
+ export interface Entry {
29
+ epoch: string
30
+ schema: object
31
+ defaults?: object
32
+ }
33
+
34
+ export type Values = Record<string, Entry>
@@ -0,0 +1,54 @@
1
+ import { entry } from './map'
2
+
3
+ /**
4
+ * The latest configuration created for the component and the epoch; the deployed
5
+ * defaults when none was; `null` when the epoch is not the one deployed.
6
+ */
7
+ export async function resolve (context: Context, component: string, epoch?: string): Promise<Value | null> {
8
+ const known = entry(component)
9
+
10
+ epoch ??= known?.epoch
11
+
12
+ if (epoch === undefined)
13
+ return null
14
+
15
+ // one query per pair, so that a component's latest is never behind another's newer ones
16
+ const query: Query = {
17
+ criteria: `component=="${component}";epoch=="${epoch}"`,
18
+ sort: ['_created:desc'],
19
+ limit: 1
20
+ }
21
+
22
+ const objects = await context.local.enumerate({ query })
23
+
24
+ if (objects.length > 0)
25
+ return { configuration: objects[0].configuration, created: objects[0]._created }
26
+
27
+ if (known !== undefined && known.epoch === epoch)
28
+ return { configuration: known.defaults ?? {}, created: 0 }
29
+
30
+ return null
31
+ }
32
+
33
+ /** A configuration and when it was created; `0` for the deployed defaults. */
34
+ export interface Value {
35
+ configuration: object
36
+ created: number
37
+ }
38
+
39
+ export interface Context {
40
+ local: {
41
+ enumerate: (request: { query: Query }) => Promise<Stored[]>
42
+ }
43
+ }
44
+
45
+ interface Query {
46
+ criteria: string
47
+ sort: string[]
48
+ limit: number
49
+ }
50
+
51
+ interface Stored {
52
+ configuration: object
53
+ _created: number
54
+ }
@@ -0,0 +1,19 @@
1
+ import { components, entry } from './lib/map'
2
+ import { resolve, type Context } from './lib/resolve'
3
+
4
+ /** The configuration of every component for its deployed epoch, by component name. */
5
+ export async function computation (_: null, context: Context): Promise<Item[]> {
6
+ return await Promise.all(components().map(async (component) => {
7
+ const { epoch, schema } = entry(component)!
8
+ const value = await resolve(context, component, epoch)
9
+
10
+ return { component, epoch, schema, configuration: value!.configuration }
11
+ }))
12
+ }
13
+
14
+ interface Item {
15
+ component: string
16
+ epoch: string
17
+ schema: object
18
+ configuration: object
19
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./operations",
5
+ },
6
+ "include": [
7
+ "source"
8
+ ]
9
+ }
package/cucumber.js ADDED
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ default: {
3
+ paths: ['features/**/*.feature'],
4
+ requireModule: ['ts-node/register'],
5
+ require: ['./features/**/*.ts'],
6
+ failFast: true
7
+ }
8
+ }
@@ -0,0 +1 @@
1
+ export const hashed = true
@@ -0,0 +1,6 @@
1
+ <!doctype html>
2
+ <!-- stands in for what `ui` builds; the scenarios are about the server, not the page -->
3
+ <html lang="en">
4
+ <head><title>fixture</title></head>
5
+ <body>the page</body>
6
+ </html>