brut 0.14.0 → 0.16.0.pre

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 (569) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +10 -0
  4. data/Dockerfile.dx +3 -6
  5. data/Gemfile.lock +1 -1
  6. data/brut-css/package-lock.json +2 -2
  7. data/brut-css/package.json +1 -1
  8. data/brut-js/package-lock.json +2 -2
  9. data/brut-js/package.json +1 -1
  10. data/brut-js/specs/Toast.spec.js +34 -0
  11. data/brut-js/src/I18nTranslation.js +3 -0
  12. data/brut-js/src/Message.js +9 -3
  13. data/brut-js/src/RichString.js +4 -1
  14. data/brut-js/src/Toast.js +102 -0
  15. data/brut-js/src/index.js +3 -0
  16. data/brutrb.com/.vitepress/config.mjs +4 -3
  17. data/brutrb.com/brut-js.md +1 -0
  18. data/brutrb.com/deployment.md +23 -9
  19. data/brutrb.com/jobs.md +107 -7
  20. data/brutrb.com/recipes/dev-env-secrets.md +87 -0
  21. data/brutrb.com/roadmap.md +2 -7
  22. data/docs/404.html +3 -3
  23. data/docs/adrs.html +7 -7
  24. data/docs/ai.html +7 -7
  25. data/docs/api/Brut/BackEnd/SeedData.html +1 -1
  26. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +1 -1
  27. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +1 -1
  28. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +1 -1
  29. data/docs/api/Brut/BackEnd/Sidekiq.html +1 -1
  30. data/docs/api/Brut/BackEnd/Validators/FormValidator.html +1 -1
  31. data/docs/api/Brut/BackEnd/Validators.html +1 -1
  32. data/docs/api/Brut/BackEnd.html +1 -1
  33. data/docs/api/Brut/CLI/App.html +1 -1
  34. data/docs/api/Brut/CLI/AppRunner.html +1 -1
  35. data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +1 -1
  36. data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +1 -1
  37. data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +1 -1
  38. data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +1 -1
  39. data/docs/api/Brut/CLI/Apps/BuildAssets.html +1 -1
  40. data/docs/api/Brut/CLI/Apps/DB/Create.html +1 -1
  41. data/docs/api/Brut/CLI/Apps/DB/Drop.html +1 -1
  42. data/docs/api/Brut/CLI/Apps/DB/Migrate.html +1 -1
  43. data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +1 -1
  44. data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +1 -1
  45. data/docs/api/Brut/CLI/Apps/DB/Seed.html +1 -1
  46. data/docs/api/Brut/CLI/Apps/DB/Status.html +1 -1
  47. data/docs/api/Brut/CLI/Apps/DB.html +1 -1
  48. data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +1 -1
  49. data/docs/api/Brut/CLI/Apps/DeployBase.html +1 -1
  50. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +1 -1
  51. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +1 -1
  52. data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +1 -1
  53. data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +1 -1
  54. data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +1 -1
  55. data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +1 -1
  56. data/docs/api/Brut/CLI/Apps/Scaffold/DbModel.html +1 -1
  57. data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +1 -1
  58. data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +1 -1
  59. data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +1 -1
  60. data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +1 -1
  61. data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +1 -1
  62. data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +1 -1
  63. data/docs/api/Brut/CLI/Apps/Scaffold.html +1 -1
  64. data/docs/api/Brut/CLI/Apps/Test/Audit.html +1 -1
  65. data/docs/api/Brut/CLI/Apps/Test/E2e.html +1 -1
  66. data/docs/api/Brut/CLI/Apps/Test/JS.html +1 -1
  67. data/docs/api/Brut/CLI/Apps/Test/Run.html +1 -1
  68. data/docs/api/Brut/CLI/Apps/Test.html +1 -1
  69. data/docs/api/Brut/CLI/Apps.html +1 -1
  70. data/docs/api/Brut/CLI/Command.html +1 -1
  71. data/docs/api/Brut/CLI/Error.html +1 -1
  72. data/docs/api/Brut/CLI/ExecutionResults/Result.html +1 -1
  73. data/docs/api/Brut/CLI/ExecutionResults.html +1 -1
  74. data/docs/api/Brut/CLI/Executor.html +1 -1
  75. data/docs/api/Brut/CLI/InvalidOption.html +1 -1
  76. data/docs/api/Brut/CLI/Options.html +1 -1
  77. data/docs/api/Brut/CLI/Output.html +1 -1
  78. data/docs/api/Brut/CLI/SystemExecError.html +1 -1
  79. data/docs/api/Brut/CLI.html +1 -1
  80. data/docs/api/Brut/FactoryBot.html +1 -1
  81. data/docs/api/Brut/Framework/App.html +1 -1
  82. data/docs/api/Brut/Framework/Config.html +1 -1
  83. data/docs/api/Brut/Framework/Container.html +1 -1
  84. data/docs/api/Brut/Framework/Error.html +1 -1
  85. data/docs/api/Brut/Framework/Errors/AbstractMethod.html +1 -1
  86. data/docs/api/Brut/Framework/Errors/Bug.html +1 -1
  87. data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +1 -1
  88. data/docs/api/Brut/Framework/Errors/MissingParameter.html +1 -1
  89. data/docs/api/Brut/Framework/Errors/NoClassForPath.html +1 -1
  90. data/docs/api/Brut/Framework/Errors/NotFound.html +1 -1
  91. data/docs/api/Brut/Framework/Errors/NotImplemented.html +1 -1
  92. data/docs/api/Brut/Framework/Errors.html +1 -1
  93. data/docs/api/Brut/Framework/FussyTypeEnforcement.html +1 -1
  94. data/docs/api/Brut/Framework/MCP.html +1 -1
  95. data/docs/api/Brut/Framework/ProjectEnvironment.html +1 -1
  96. data/docs/api/Brut/Framework.html +1 -1
  97. data/docs/api/Brut/FrontEnd/AssetPathResolver.html +1 -1
  98. data/docs/api/Brut/FrontEnd/Component/Helpers.html +1 -1
  99. data/docs/api/Brut/FrontEnd/Component.html +1 -1
  100. data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +1 -1
  101. data/docs/api/Brut/FrontEnd/Components/FormTag.html +1 -1
  102. data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +1 -1
  103. data/docs/api/Brut/FrontEnd/Components/Input.html +1 -1
  104. data/docs/api/Brut/FrontEnd/Components/Inputs/ButtonTag.html +1 -1
  105. data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +1 -1
  106. data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +1 -1
  107. data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +1 -1
  108. data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +1 -1
  109. data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +1 -1
  110. data/docs/api/Brut/FrontEnd/Components/Inputs.html +1 -1
  111. data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +1 -1
  112. data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +37 -18
  113. data/docs/api/Brut/FrontEnd/Components/TimeTag.html +1 -1
  114. data/docs/api/Brut/FrontEnd/Components/Traceparent.html +1 -1
  115. data/docs/api/Brut/FrontEnd/Components.html +1 -1
  116. data/docs/api/Brut/FrontEnd/CsrfProtector.html +1 -1
  117. data/docs/api/Brut/FrontEnd/Download.html +1 -1
  118. data/docs/api/Brut/FrontEnd/Flash.html +1 -1
  119. data/docs/api/Brut/FrontEnd/Form.html +1 -1
  120. data/docs/api/Brut/FrontEnd/Forms/Button.html +1 -1
  121. data/docs/api/Brut/FrontEnd/Forms/ButtonInputDefinition.html +1 -1
  122. data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +1 -1
  123. data/docs/api/Brut/FrontEnd/Forms/Input/Color.html +1 -1
  124. data/docs/api/Brut/FrontEnd/Forms/Input/TimeOfDay.html +1 -1
  125. data/docs/api/Brut/FrontEnd/Forms/Input.html +1 -1
  126. data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +1 -1
  127. data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +1 -1
  128. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +1 -1
  129. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +1 -1
  130. data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +1 -1
  131. data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +1 -1
  132. data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +1 -1
  133. data/docs/api/Brut/FrontEnd/Forms.html +1 -1
  134. data/docs/api/Brut/FrontEnd/GenericResponse.html +1 -1
  135. data/docs/api/Brut/FrontEnd/Handler.html +1 -1
  136. data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +1 -1
  137. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +1 -1
  138. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +1 -1
  139. data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +1 -1
  140. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +1 -1
  141. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +1 -1
  142. data/docs/api/Brut/FrontEnd/Handlers.html +1 -1
  143. data/docs/api/Brut/FrontEnd/HandlingResults.html +1 -1
  144. data/docs/api/Brut/FrontEnd/HttpMethod.html +1 -1
  145. data/docs/api/Brut/FrontEnd/HttpStatus.html +1 -1
  146. data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +1 -1
  147. data/docs/api/Brut/FrontEnd/Layout.html +171 -3
  148. data/docs/api/Brut/FrontEnd/Middleware.html +1 -1
  149. data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +1 -1
  150. data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +1 -1
  151. data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +1 -1
  152. data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +1 -1
  153. data/docs/api/Brut/FrontEnd/Middlewares.html +1 -1
  154. data/docs/api/Brut/FrontEnd/Page.html +1 -1
  155. data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +1 -1
  156. data/docs/api/Brut/FrontEnd/Pages.html +1 -1
  157. data/docs/api/Brut/FrontEnd/RequestContext.html +1 -1
  158. data/docs/api/Brut/FrontEnd/RouteHook.html +1 -1
  159. data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +1 -1
  160. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +1 -1
  161. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +1 -1
  162. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +1 -1
  163. data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +1 -1
  164. data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +1 -1
  165. data/docs/api/Brut/FrontEnd/RouteHooks.html +1 -1
  166. data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +1 -1
  167. data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +1 -1
  168. data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +1 -1
  169. data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +1 -1
  170. data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +1 -1
  171. data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +1 -1
  172. data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +1 -1
  173. data/docs/api/Brut/FrontEnd/Routing/Route.html +1 -1
  174. data/docs/api/Brut/FrontEnd/Routing.html +1 -1
  175. data/docs/api/Brut/FrontEnd/Session.html +1 -1
  176. data/docs/api/Brut/FrontEnd.html +1 -1
  177. data/docs/api/Brut/I18n/BaseMethods.html +1 -1
  178. data/docs/api/Brut/I18n/ForBackEnd.html +1 -1
  179. data/docs/api/Brut/I18n/ForCLI.html +1 -1
  180. data/docs/api/Brut/I18n/ForHTML.html +1 -1
  181. data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +1 -1
  182. data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +1 -1
  183. data/docs/api/Brut/I18n.html +1 -1
  184. data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +1 -1
  185. data/docs/api/Brut/Instrumentation/Methods/ClassMethods.html +1 -1
  186. data/docs/api/Brut/Instrumentation/Methods.html +1 -1
  187. data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +1 -1
  188. data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +1 -1
  189. data/docs/api/Brut/Instrumentation/OpenTelemetry.html +1 -1
  190. data/docs/api/Brut/Instrumentation.html +1 -1
  191. data/docs/api/Brut/RubocopConfig.html +1 -1
  192. data/docs/api/Brut/SinatraHelpers/ClassMethods.html +1 -1
  193. data/docs/api/Brut/SinatraHelpers.html +1 -1
  194. data/docs/api/Brut/SpecSupport/ClockSupport.html +1 -1
  195. data/docs/api/Brut/SpecSupport/ComponentSupport.html +1 -1
  196. data/docs/api/Brut/SpecSupport/E2ETestServer.html +1 -1
  197. data/docs/api/Brut/SpecSupport/E2eSupport.html +1 -1
  198. data/docs/api/Brut/SpecSupport/EnhancedNode.html +1 -1
  199. data/docs/api/Brut/SpecSupport/FlashSupport.html +1 -1
  200. data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +1 -1
  201. data/docs/api/Brut/SpecSupport/GeneralSupport.html +1 -1
  202. data/docs/api/Brut/SpecSupport/HandlerSupport.html +1 -1
  203. data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +1 -1
  204. data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +1 -1
  205. data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +1 -1
  206. data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +1 -1
  207. data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +1 -1
  208. data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +1 -1
  209. data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +1 -1
  210. data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +1 -1
  211. data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +1 -1
  212. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +1 -1
  213. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +1 -1
  214. data/docs/api/Brut/SpecSupport/Matchers.html +1 -1
  215. data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +1 -1
  216. data/docs/api/Brut/SpecSupport/RSpecSetup.html +1 -1
  217. data/docs/api/Brut/SpecSupport/SessionSupport.html +1 -1
  218. data/docs/api/Brut/SpecSupport.html +1 -1
  219. data/docs/api/Brut.html +1 -1
  220. data/docs/api/Clock.html +1 -1
  221. data/docs/api/ModuleName.html +1 -1
  222. data/docs/api/RichString.html +1 -1
  223. data/docs/api/SemanticLogger/Appender/Async.html +1 -1
  224. data/docs/api/Sequel/Extensions/BrutInstrumentation.html +1 -1
  225. data/docs/api/Sequel/Extensions/BrutMigrations.html +1 -1
  226. data/docs/api/Sequel/Extensions.html +1 -1
  227. data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +1 -1
  228. data/docs/api/Sequel/Plugins/CreatedAt.html +1 -1
  229. data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +1 -1
  230. data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +1 -1
  231. data/docs/api/Sequel/Plugins/ExternalId.html +1 -1
  232. data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +1 -1
  233. data/docs/api/Sequel/Plugins/FindBang.html +1 -1
  234. data/docs/api/Sequel/Plugins.html +1 -1
  235. data/docs/api/Sequel.html +1 -1
  236. data/docs/api/_index.html +1 -1
  237. data/docs/api/file.README.html +1 -1
  238. data/docs/api/index.html +1 -1
  239. data/docs/api/method_list.html +157 -141
  240. data/docs/api/top-level-namespace.html +1 -1
  241. data/docs/assets/adrs.md.YglbWtQe.js +1 -0
  242. data/docs/assets/adrs.md.YglbWtQe.lean.js +1 -0
  243. data/docs/assets/ai.md.ChLnvDAX.js +1 -0
  244. data/docs/assets/ai.md.ChLnvDAX.lean.js +1 -0
  245. data/docs/assets/{app.BDtsVxyd.js → app.Dm7v_ouO.js} +1 -1
  246. data/docs/assets/{assets.md.7C3HWkga.js → assets.md.BEF6Oz6K.js} +2 -2
  247. data/docs/assets/assets.md.BEF6Oz6K.lean.js +1 -0
  248. data/docs/assets/{brut-js.md.B4GYxQVw.js → brut-js.md.BMz0X1Rz.js} +2 -2
  249. data/docs/assets/brut-js.md.BMz0X1Rz.lean.js +1 -0
  250. data/docs/assets/business-logic.md.DbuaOYGU.js +1 -0
  251. data/docs/assets/business-logic.md.DbuaOYGU.lean.js +1 -0
  252. data/docs/assets/chunks/@localSearchIndexroot.BiNFswvo.js +1 -0
  253. data/docs/assets/chunks/VPLocalSearchBox.DQK6jQou.js +8 -0
  254. data/docs/assets/chunks/framework.C4nOkCZI.js +18 -0
  255. data/docs/assets/chunks/{theme.DZKmijwi.js → theme.BuExsdM9.js} +2 -2
  256. data/docs/assets/{cli.md.CjsktgFz.js → cli.md.DDMar_51.js} +2 -2
  257. data/docs/assets/cli.md.DDMar_51.lean.js +1 -0
  258. data/docs/assets/{components.md.rMhQ0WdZ.js → components.md.Dfd3w6UW.js} +5 -5
  259. data/docs/assets/components.md.Dfd3w6UW.lean.js +1 -0
  260. data/docs/assets/{configuration.md.BK42Yjp_.js → configuration.md.DTYoV2Ea.js} +2 -2
  261. data/docs/assets/configuration.md.DTYoV2Ea.lean.js +1 -0
  262. data/docs/assets/{css.md.CltvJqAa.js → css.md.K5rOCOQY.js} +2 -2
  263. data/docs/assets/css.md.K5rOCOQY.lean.js +1 -0
  264. data/docs/assets/{custom-element-tests.md.B_rbta32.js → custom-element-tests.md.DiLe-eFw.js} +2 -2
  265. data/docs/assets/custom-element-tests.md.DiLe-eFw.lean.js +1 -0
  266. data/docs/assets/{database-access.md.gnluu54N.js → database-access.md.Dc8l2Plf.js} +2 -2
  267. data/docs/assets/database-access.md.Dc8l2Plf.lean.js +1 -0
  268. data/docs/assets/{database-schema.md.LpmBPVEU.js → database-schema.md.BJ_JhXmO.js} +2 -2
  269. data/docs/assets/database-schema.md.BJ_JhXmO.lean.js +1 -0
  270. data/docs/assets/{deployment.md.BLseERGV.js → deployment.md.C1u5ep0g.js} +2 -2
  271. data/docs/assets/deployment.md.C1u5ep0g.lean.js +1 -0
  272. data/docs/assets/{dev-environment.md.DRH2D2-O.js → dev-environment.md.B1S9p5ZK.js} +2 -2
  273. data/docs/assets/{dev-environment.md.DRH2D2-O.lean.js → dev-environment.md.B1S9p5ZK.lean.js} +1 -1
  274. data/docs/assets/{dir-structure.md.CWir1pic.js → dir-structure.md.D1T2kGwj.js} +2 -2
  275. data/docs/assets/dir-structure.md.D1T2kGwj.lean.js +1 -0
  276. data/docs/assets/doc-conventions.md.CDnWaEFg.js +1 -0
  277. data/docs/assets/doc-conventions.md.CDnWaEFg.lean.js +1 -0
  278. data/docs/assets/{end-to-end-tests.md.DzqRpZ43.js → end-to-end-tests.md.BJJdNDYL.js} +2 -2
  279. data/docs/assets/end-to-end-tests.md.BJJdNDYL.lean.js +1 -0
  280. data/docs/assets/{features.md.DPFXsy0z.js → features.md.BDWxnyNO.js} +2 -2
  281. data/docs/assets/features.md.BDWxnyNO.lean.js +1 -0
  282. data/docs/assets/{flash-and-session.md.nPvUpnUx.js → flash-and-session.md.CUsMxoNl.js} +2 -2
  283. data/docs/assets/flash-and-session.md.CUsMxoNl.lean.js +1 -0
  284. data/docs/assets/{form-constraints.md.KTv5cdR4.js → form-constraints.md.KlfXSKm2.js} +2 -2
  285. data/docs/assets/form-constraints.md.KlfXSKm2.lean.js +1 -0
  286. data/docs/assets/{forms.md.v9qIbmUM.js → forms.md.DEkmJUvb.js} +3 -3
  287. data/docs/assets/forms.md.DEkmJUvb.lean.js +1 -0
  288. data/docs/assets/{getting-started.md.DTOl4c2g.js → getting-started.md.DO-4eoGW.js} +4 -4
  289. data/docs/assets/getting-started.md.DO-4eoGW.lean.js +1 -0
  290. data/docs/assets/{handlers.md.h84MMB1R.js → handlers.md.C5tUwmmo.js} +2 -2
  291. data/docs/assets/handlers.md.C5tUwmmo.lean.js +1 -0
  292. data/docs/assets/{hooks.md.Jmb5VOLA.js → hooks.md.CoiYCKRc.js} +2 -2
  293. data/docs/assets/hooks.md.CoiYCKRc.lean.js +1 -0
  294. data/docs/assets/{i18n.md.BAm9t9JJ.js → i18n.md.DxkCKhUw.js} +2 -2
  295. data/docs/assets/i18n.md.DxkCKhUw.lean.js +1 -0
  296. data/docs/assets/{index.md.Bn9e0sRJ.js → index.md.DnphWyQd.js} +1 -1
  297. data/docs/assets/{index.md.Bn9e0sRJ.lean.js → index.md.DnphWyQd.lean.js} +1 -1
  298. data/docs/assets/{instrumentation.md._lNSriEZ.js → instrumentation.md.BcxjC4jd.js} +2 -2
  299. data/docs/assets/instrumentation.md.BcxjC4jd.lean.js +1 -0
  300. data/docs/assets/{javascript.md.DzrMxUmI.js → javascript.md.D6fxhaQb.js} +2 -2
  301. data/docs/assets/javascript.md.D6fxhaQb.lean.js +1 -0
  302. data/docs/assets/jobs.md.Bc7Y1YpK.js +1 -0
  303. data/docs/assets/jobs.md.Bc7Y1YpK.lean.js +1 -0
  304. data/docs/assets/{keyword-injection.md.95Zgh2eN.js → keyword-injection.md.CqLnnzIz.js} +2 -2
  305. data/docs/assets/keyword-injection.md.CqLnnzIz.lean.js +1 -0
  306. data/docs/assets/layouts.md.HEbeK7Jr.js +68 -0
  307. data/docs/assets/layouts.md.HEbeK7Jr.lean.js +1 -0
  308. data/docs/assets/lsp.md.bE9dW8n9.js +1 -0
  309. data/docs/assets/lsp.md.bE9dW8n9.lean.js +1 -0
  310. data/docs/assets/{markdown-examples.md.CCFEQO44.js → markdown-examples.md.BPmtHlc-.js} +2 -2
  311. data/docs/assets/markdown-examples.md.BPmtHlc-.lean.js +1 -0
  312. data/docs/assets/{middleware.md.Czz_UlJN.js → middleware.md.BhOIsg59.js} +2 -2
  313. data/docs/assets/middleware.md.BhOIsg59.lean.js +1 -0
  314. data/docs/assets/overview.md.BpWAgPFH.js +1 -0
  315. data/docs/assets/overview.md.BpWAgPFH.lean.js +1 -0
  316. data/docs/assets/{pages.md.B7Hc-i6H.js → pages.md.B3sQXpEd.js} +2 -2
  317. data/docs/assets/pages.md.B3sQXpEd.lean.js +1 -0
  318. data/docs/assets/{recipes_alternate-layouts.md.BwEytl59.js → recipes_alternate-layouts.md.C1QzVkA7.js} +2 -2
  319. data/docs/assets/recipes_alternate-layouts.md.C1QzVkA7.lean.js +1 -0
  320. data/docs/assets/{recipes_authentication.md.nwO6F7Ou.js → recipes_authentication.md.CyvoIW82.js} +2 -2
  321. data/docs/assets/recipes_authentication.md.CyvoIW82.lean.js +1 -0
  322. data/docs/assets/{recipes_custom-flash.md.CrQbI5eH.js → recipes_custom-flash.md.6gFqf2uL.js} +2 -2
  323. data/docs/assets/recipes_custom-flash.md.6gFqf2uL.lean.js +1 -0
  324. data/docs/assets/{recipes_form-errors.md.Bv5RCKqH.js → recipes_form-errors.md.B5ptSzMO.js} +2 -2
  325. data/docs/assets/recipes_form-errors.md.B5ptSzMO.lean.js +1 -0
  326. data/docs/assets/{recipes_indexed-forms.md.CstYyOSo.js → recipes_indexed-forms.md.BYYQGW2C.js} +2 -2
  327. data/docs/assets/recipes_indexed-forms.md.BYYQGW2C.lean.js +1 -0
  328. data/docs/assets/{recipes_migrations.md.CTcnWDJF.js → recipes_migrations.md.Cid7-3cu.js} +2 -2
  329. data/docs/assets/recipes_migrations.md.Cid7-3cu.lean.js +1 -0
  330. data/docs/assets/{recipes_text-field-component.md.H4wLAK0Z.js → recipes_text-field-component.md.VhOsCtKI.js} +2 -2
  331. data/docs/assets/recipes_text-field-component.md.VhOsCtKI.lean.js +1 -0
  332. data/docs/assets/roadmap.md.CJsbUmK_.js +1 -0
  333. data/docs/assets/roadmap.md.CJsbUmK_.lean.js +1 -0
  334. data/docs/assets/{routes.md.BD6y2i-f.js → routes.md.C1dgIBtD.js} +2 -2
  335. data/docs/assets/routes.md.C1dgIBtD.lean.js +1 -0
  336. data/docs/assets/security.md.Jn4SY1uK.js +1 -0
  337. data/docs/assets/security.md.Jn4SY1uK.lean.js +1 -0
  338. data/docs/assets/{seed-data.md.BvFZlqIk.js → seed-data.md.UZW0WxYN.js} +2 -2
  339. data/docs/assets/seed-data.md.UZW0WxYN.lean.js +1 -0
  340. data/docs/assets/space-time-continuum.md.D9rYGDFH.js +1 -0
  341. data/docs/assets/space-time-continuum.md.D9rYGDFH.lean.js +1 -0
  342. data/docs/assets/{tutorial.md.BM40jnoq.js → tutorial.md.BX6f6l00.js} +2 -2
  343. data/docs/assets/tutorial.md.BX6f6l00.lean.js +1 -0
  344. data/docs/assets/{tutorials_01-intro.md.B4sUBY3X.js → tutorials_01-intro.md.CzZ3kpF_.js} +2 -2
  345. data/docs/assets/{tutorials_01-intro.md.B4sUBY3X.lean.js → tutorials_01-intro.md.CzZ3kpF_.lean.js} +1 -1
  346. data/docs/assets/{tutorials_02-dialog.md.CPNK1SC_.js → tutorials_02-dialog.md.D2vSjDVf.js} +2 -2
  347. data/docs/assets/{tutorials_02-dialog.md.CPNK1SC_.lean.js → tutorials_02-dialog.md.D2vSjDVf.lean.js} +1 -1
  348. data/docs/assets/{unit-tests.md.DUGrnLj5.js → unit-tests.md.vDsdBbO_.js} +2 -2
  349. data/docs/assets/unit-tests.md.vDsdBbO_.lean.js +1 -0
  350. data/docs/assets/why.md.4WpxdrQ2.js +1 -0
  351. data/docs/assets/why.md.4WpxdrQ2.lean.js +1 -0
  352. data/docs/assets.html +7 -7
  353. data/docs/brut-js/api/AjaxSubmit.html +2 -2
  354. data/docs/brut-js/api/AjaxSubmit.js.html +2 -2
  355. data/docs/brut-js/api/Autosubmit.html +2 -2
  356. data/docs/brut-js/api/Autosubmit.js.html +2 -2
  357. data/docs/brut-js/api/BaseCustomElement.html +2 -2
  358. data/docs/brut-js/api/BaseCustomElement.js.html +2 -2
  359. data/docs/brut-js/api/BrutCustomElements.html +3 -3
  360. data/docs/brut-js/api/BufferedLogger.html +2 -2
  361. data/docs/brut-js/api/ConfirmSubmit.html +2 -2
  362. data/docs/brut-js/api/ConfirmSubmit.js.html +2 -2
  363. data/docs/brut-js/api/ConfirmationDialog.html +2 -2
  364. data/docs/brut-js/api/ConfirmationDialog.js.html +2 -2
  365. data/docs/brut-js/api/ConstraintViolationMessage.html +2 -2
  366. data/docs/brut-js/api/ConstraintViolationMessage.js.html +2 -2
  367. data/docs/brut-js/api/ConstraintViolationMessages.html +2 -2
  368. data/docs/brut-js/api/ConstraintViolationMessages.js.html +2 -2
  369. data/docs/brut-js/api/CopyToClipboard.html +2 -2
  370. data/docs/brut-js/api/CopyToClipboard.js.html +2 -2
  371. data/docs/brut-js/api/Form.html +2 -2
  372. data/docs/brut-js/api/Form.js.html +2 -2
  373. data/docs/brut-js/api/I18nTranslation.html +2 -2
  374. data/docs/brut-js/api/I18nTranslation.js.html +5 -2
  375. data/docs/brut-js/api/LocaleDetection.html +2 -2
  376. data/docs/brut-js/api/LocaleDetection.js.html +2 -2
  377. data/docs/brut-js/api/Logger.html +2 -2
  378. data/docs/brut-js/api/Logger.js.html +2 -2
  379. data/docs/brut-js/api/Message.html +2 -2
  380. data/docs/brut-js/api/Message.js.html +11 -5
  381. data/docs/brut-js/api/PrefixedLogger.html +2 -2
  382. data/docs/brut-js/api/RichString.html +9 -9
  383. data/docs/brut-js/api/RichString.js.html +6 -3
  384. data/docs/brut-js/api/Tabs.html +2 -2
  385. data/docs/brut-js/api/Tabs.js.html +2 -2
  386. data/docs/brut-js/api/Toast.html +270 -0
  387. data/docs/brut-js/api/Toast.js.html +153 -0
  388. data/docs/brut-js/api/Tracing.html +2 -2
  389. data/docs/brut-js/api/Tracing.js.html +2 -2
  390. data/docs/brut-js/api/external-CustomElementRegistry.html +3 -3
  391. data/docs/brut-js/api/external-Performance.html +3 -3
  392. data/docs/brut-js/api/external-Promise.html +3 -3
  393. data/docs/brut-js/api/external-ValidityState.html +3 -3
  394. data/docs/brut-js/api/external-Window.html +4 -4
  395. data/docs/brut-js/api/external-fetch.html +3 -3
  396. data/docs/brut-js/api/global.html +3 -3
  397. data/docs/brut-js/api/index.html +2 -2
  398. data/docs/brut-js/api/index.js.html +5 -2
  399. data/docs/brut-js/api/module-testing.html +2 -2
  400. data/docs/brut-js/api/testing.AssetMetadata.html +2 -2
  401. data/docs/brut-js/api/testing.AssetMetadataLoader.html +2 -2
  402. data/docs/brut-js/api/testing.CustomElementTest.html +2 -2
  403. data/docs/brut-js/api/testing.DOMCreator.html +2 -2
  404. data/docs/brut-js/api/testing_AssetMetadata.js.html +2 -2
  405. data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +2 -2
  406. data/docs/brut-js/api/testing_CustomElementTest.js.html +2 -2
  407. data/docs/brut-js/api/testing_DOMCreator.js.html +2 -2
  408. data/docs/brut-js/api/testing_index.js.html +2 -2
  409. data/docs/brut-js.html +8 -8
  410. data/docs/business-logic.html +7 -7
  411. data/docs/cli.html +7 -7
  412. data/docs/components.html +10 -10
  413. data/docs/configuration.html +7 -7
  414. data/docs/css.html +7 -7
  415. data/docs/custom-element-tests.html +7 -7
  416. data/docs/database-access.html +7 -7
  417. data/docs/database-schema.html +7 -7
  418. data/docs/deployment.html +7 -7
  419. data/docs/dev-environment.html +7 -7
  420. data/docs/dir-structure.html +7 -7
  421. data/docs/doc-conventions.html +7 -7
  422. data/docs/end-to-end-tests.html +7 -7
  423. data/docs/features.html +7 -7
  424. data/docs/flash-and-session.html +7 -7
  425. data/docs/form-constraints.html +7 -7
  426. data/docs/forms.html +8 -8
  427. data/docs/getting-started.html +9 -9
  428. data/docs/handlers.html +7 -7
  429. data/docs/hashmap.json +1 -1
  430. data/docs/hooks.html +7 -7
  431. data/docs/i18n.html +7 -7
  432. data/docs/index.html +6 -6
  433. data/docs/instrumentation.html +7 -7
  434. data/docs/javascript.html +7 -7
  435. data/docs/jobs.html +7 -7
  436. data/docs/keyword-injection.html +7 -7
  437. data/docs/layouts.html +42 -12
  438. data/docs/lsp.html +7 -7
  439. data/docs/markdown-examples.html +7 -7
  440. data/docs/middleware.html +7 -7
  441. data/docs/overview.html +7 -7
  442. data/docs/pages.html +7 -7
  443. data/docs/recipes/alternate-layouts.html +8 -8
  444. data/docs/recipes/authentication.html +7 -7
  445. data/docs/recipes/custom-flash.html +8 -8
  446. data/docs/recipes/form-errors.html +7 -7
  447. data/docs/recipes/indexed-forms.html +7 -7
  448. data/docs/recipes/migrations.html +7 -7
  449. data/docs/recipes/text-field-component.html +7 -7
  450. data/docs/roadmap.html +7 -7
  451. data/docs/routes.html +7 -7
  452. data/docs/security.html +7 -7
  453. data/docs/seed-data.html +7 -7
  454. data/docs/space-time-continuum.html +7 -7
  455. data/docs/tutorial.html +7 -7
  456. data/docs/tutorials/01-intro.html +7 -7
  457. data/docs/tutorials/02-dialog.html +7 -7
  458. data/docs/unit-tests.html +7 -7
  459. data/docs/why.html +7 -7
  460. data/dx/bash_customizations +3 -4
  461. data/dx/build.pre +15 -0
  462. data/lib/brut/cli/apps/heroku_container_based_deploy.rb +41 -15
  463. data/lib/brut/cli/apps/test.rb +2 -0
  464. data/lib/brut/framework/container.rb +6 -4
  465. data/lib/brut/framework/mcp.rb +1 -1
  466. data/lib/brut/version.rb +1 -1
  467. data/mkbrut/Gemfile.lock +2 -2
  468. data/mkbrut/lib/mkbrut/add_segment.rb +38 -0
  469. data/mkbrut/lib/mkbrut/add_segment_options.rb +22 -0
  470. data/mkbrut/lib/mkbrut/app.rb +7 -2
  471. data/mkbrut/lib/mkbrut/base.rb +1 -0
  472. data/mkbrut/lib/mkbrut/cli.rb +90 -8
  473. data/mkbrut/lib/mkbrut/ops/insert_code_in_method.rb +19 -7
  474. data/mkbrut/lib/mkbrut/ops/insert_into_file.rb +36 -0
  475. data/mkbrut/lib/mkbrut/ops/prism_parsing_op.rb +14 -2
  476. data/mkbrut/lib/mkbrut/ops.rb +1 -0
  477. data/mkbrut/lib/mkbrut/segments/bare_bones.rb +8 -0
  478. data/mkbrut/lib/mkbrut/segments/demo.rb +8 -0
  479. data/mkbrut/lib/mkbrut/segments/heroku.rb +23 -3
  480. data/mkbrut/lib/mkbrut/segments/sidekiq.rb +136 -1
  481. data/mkbrut/lib/mkbrut/segments.rb +1 -1
  482. data/mkbrut/lib/mkbrut/version.rb +1 -1
  483. data/mkbrut/lib/mkbrut.rb +2 -0
  484. data/mkbrut/templates/Base/.gitignore +3 -0
  485. data/mkbrut/templates/Base/Dockerfile.dx +18 -21
  486. data/mkbrut/templates/Base/Gemfile.erb +1 -1
  487. data/mkbrut/templates/Base/bin/run +107 -67
  488. data/mkbrut/templates/Base/bin/run.run +4 -0
  489. data/mkbrut/templates/Base/bin/setup +32 -1
  490. data/mkbrut/templates/Base/dx/bash_customizations +0 -4
  491. data/mkbrut/templates/Base/package.json.erb +1 -1
  492. data/mkbrut/templates/segments/Heroku/deploy/Dockerfile +15 -15
  493. data/mkbrut/templates/segments/Heroku/deploy/heroku_config.rb +5 -4
  494. data/mkbrut/templates/segments/Sidekiq/app/boot_sidekiq.rb +2 -0
  495. data/mkbrut/templates/segments/Sidekiq/app/config/sidekiq.yml +4 -0
  496. data/mkbrut/templates/segments/Sidekiq/app/src/back_end/jobs/app_job.rb +3 -0
  497. data/mkbrut/templates/segments/Sidekiq/app/src/back_end/jobs/example_job.rb +12 -0
  498. data/mkbrut/templates/segments/Sidekiq/app/src/back_end/segments/sidekiq_segment.rb +56 -0
  499. data/mkbrut/templates/segments/Sidekiq/bin/run.sidekiq +4 -0
  500. data/mkbrut/templates/segments/Sidekiq/specs/back_end/jobs/example_job.spec.rb +5 -0
  501. data/mkbrut/templates/segments/Sidekiq/specs/integration/sidekiq_works.spec.rb +38 -0
  502. metadata +131 -116
  503. data/docs/assets/adrs.md.BxjHi9-8.js +0 -1
  504. data/docs/assets/adrs.md.BxjHi9-8.lean.js +0 -1
  505. data/docs/assets/ai.md.Cy9GWnER.js +0 -1
  506. data/docs/assets/ai.md.Cy9GWnER.lean.js +0 -1
  507. data/docs/assets/assets.md.7C3HWkga.lean.js +0 -1
  508. data/docs/assets/brut-js.md.B4GYxQVw.lean.js +0 -1
  509. data/docs/assets/business-logic.md.BY4hGy0m.js +0 -1
  510. data/docs/assets/business-logic.md.BY4hGy0m.lean.js +0 -1
  511. data/docs/assets/chunks/@localSearchIndexroot.BWVzhs5N.js +0 -1
  512. data/docs/assets/chunks/VPLocalSearchBox.DCJk5nAW.js +0 -8
  513. data/docs/assets/chunks/framework.1L-BeKqY.js +0 -18
  514. data/docs/assets/cli.md.CjsktgFz.lean.js +0 -1
  515. data/docs/assets/components.md.rMhQ0WdZ.lean.js +0 -1
  516. data/docs/assets/configuration.md.BK42Yjp_.lean.js +0 -1
  517. data/docs/assets/css.md.CltvJqAa.lean.js +0 -1
  518. data/docs/assets/custom-element-tests.md.B_rbta32.lean.js +0 -1
  519. data/docs/assets/database-access.md.gnluu54N.lean.js +0 -1
  520. data/docs/assets/database-schema.md.LpmBPVEU.lean.js +0 -1
  521. data/docs/assets/deployment.md.BLseERGV.lean.js +0 -1
  522. data/docs/assets/dir-structure.md.CWir1pic.lean.js +0 -1
  523. data/docs/assets/doc-conventions.md.DOkAuXlt.js +0 -1
  524. data/docs/assets/doc-conventions.md.DOkAuXlt.lean.js +0 -1
  525. data/docs/assets/end-to-end-tests.md.DzqRpZ43.lean.js +0 -1
  526. data/docs/assets/features.md.DPFXsy0z.lean.js +0 -1
  527. data/docs/assets/flash-and-session.md.nPvUpnUx.lean.js +0 -1
  528. data/docs/assets/form-constraints.md.KTv5cdR4.lean.js +0 -1
  529. data/docs/assets/forms.md.v9qIbmUM.lean.js +0 -1
  530. data/docs/assets/getting-started.md.DTOl4c2g.lean.js +0 -1
  531. data/docs/assets/handlers.md.h84MMB1R.lean.js +0 -1
  532. data/docs/assets/hooks.md.Jmb5VOLA.lean.js +0 -1
  533. data/docs/assets/i18n.md.BAm9t9JJ.lean.js +0 -1
  534. data/docs/assets/instrumentation.md._lNSriEZ.lean.js +0 -1
  535. data/docs/assets/javascript.md.DzrMxUmI.lean.js +0 -1
  536. data/docs/assets/jobs.md.S-2amAYp.js +0 -1
  537. data/docs/assets/jobs.md.S-2amAYp.lean.js +0 -1
  538. data/docs/assets/keyword-injection.md.95Zgh2eN.lean.js +0 -1
  539. data/docs/assets/layouts.md.CVGl9xIO.js +0 -38
  540. data/docs/assets/layouts.md.CVGl9xIO.lean.js +0 -1
  541. data/docs/assets/lsp.md.Dn1rIiW0.js +0 -1
  542. data/docs/assets/lsp.md.Dn1rIiW0.lean.js +0 -1
  543. data/docs/assets/markdown-examples.md.CCFEQO44.lean.js +0 -1
  544. data/docs/assets/middleware.md.Czz_UlJN.lean.js +0 -1
  545. data/docs/assets/overview.md.DlKiRRG_.js +0 -1
  546. data/docs/assets/overview.md.DlKiRRG_.lean.js +0 -1
  547. data/docs/assets/pages.md.B7Hc-i6H.lean.js +0 -1
  548. data/docs/assets/recipes_alternate-layouts.md.BwEytl59.lean.js +0 -1
  549. data/docs/assets/recipes_authentication.md.nwO6F7Ou.lean.js +0 -1
  550. data/docs/assets/recipes_blank-layouts.md.fyAUJyJR.js +0 -15
  551. data/docs/assets/recipes_blank-layouts.md.fyAUJyJR.lean.js +0 -1
  552. data/docs/assets/recipes_custom-flash.md.CrQbI5eH.lean.js +0 -1
  553. data/docs/assets/recipes_form-errors.md.Bv5RCKqH.lean.js +0 -1
  554. data/docs/assets/recipes_indexed-forms.md.CstYyOSo.lean.js +0 -1
  555. data/docs/assets/recipes_migrations.md.CTcnWDJF.lean.js +0 -1
  556. data/docs/assets/recipes_text-field-component.md.H4wLAK0Z.lean.js +0 -1
  557. data/docs/assets/roadmap.md.C6PRi0DX.js +0 -1
  558. data/docs/assets/roadmap.md.C6PRi0DX.lean.js +0 -1
  559. data/docs/assets/routes.md.BD6y2i-f.lean.js +0 -1
  560. data/docs/assets/security.md.C0G_AZR-.js +0 -1
  561. data/docs/assets/security.md.C0G_AZR-.lean.js +0 -1
  562. data/docs/assets/seed-data.md.BvFZlqIk.lean.js +0 -1
  563. data/docs/assets/space-time-continuum.md.xl44xDos.js +0 -1
  564. data/docs/assets/space-time-continuum.md.xl44xDos.lean.js +0 -1
  565. data/docs/assets/tutorial.md.BM40jnoq.lean.js +0 -1
  566. data/docs/assets/unit-tests.md.DUGrnLj5.lean.js +0 -1
  567. data/docs/assets/why.md.C-hk5xgJ.js +0 -1
  568. data/docs/assets/why.md.C-hk5xgJ.lean.js +0 -1
  569. data/docs/recipes/blank-layouts.html +0 -43
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brut
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.16.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Bryant Copeland
@@ -591,6 +591,7 @@ files:
591
591
  - brut-js/specs/Message.spec.js
592
592
  - brut-js/specs/SpecHelper.js
593
593
  - brut-js/specs/Tabs.spec.js
594
+ - brut-js/specs/Toast.spec.js
594
595
  - brut-js/specs/config/asset_metadata.json
595
596
  - brut-js/src/AjaxSubmit.js
596
597
  - brut-js/src/Autosubmit.js
@@ -607,6 +608,7 @@ files:
607
608
  - brut-js/src/Message.js
608
609
  - brut-js/src/RichString.js
609
610
  - brut-js/src/Tabs.js
611
+ - brut-js/src/Toast.js
610
612
  - brut-js/src/Tracing.js
611
613
  - brut-js/src/appForTestingOnly.js
612
614
  - brut-js/src/index.js
@@ -704,6 +706,7 @@ files:
704
706
  - brutrb.com/recipes/alternate-layouts.md
705
707
  - brutrb.com/recipes/authentication.md
706
708
  - brutrb.com/recipes/custom-flash.md
709
+ - brutrb.com/recipes/dev-env-secrets.md
707
710
  - brutrb.com/recipes/form-errors.md
708
711
  - brutrb.com/recipes/indexed-forms.md
709
712
  - brutrb.com/recipes/migrations.md
@@ -959,132 +962,130 @@ files:
959
962
  - docs/assets/DevEnvironment.DaFcVfwP.png
960
963
  - docs/assets/LogoStop.Gb3tDhL1.png
961
964
  - docs/assets/OverviewMetro.DUS-5fUZ.png
962
- - docs/assets/adrs.md.BxjHi9-8.js
963
- - docs/assets/adrs.md.BxjHi9-8.lean.js
964
- - docs/assets/ai.md.Cy9GWnER.js
965
- - docs/assets/ai.md.Cy9GWnER.lean.js
966
- - docs/assets/app.BDtsVxyd.js
967
- - docs/assets/assets.md.7C3HWkga.js
968
- - docs/assets/assets.md.7C3HWkga.lean.js
965
+ - docs/assets/adrs.md.YglbWtQe.js
966
+ - docs/assets/adrs.md.YglbWtQe.lean.js
967
+ - docs/assets/ai.md.ChLnvDAX.js
968
+ - docs/assets/ai.md.ChLnvDAX.lean.js
969
+ - docs/assets/app.Dm7v_ouO.js
970
+ - docs/assets/assets.md.BEF6Oz6K.js
971
+ - docs/assets/assets.md.BEF6Oz6K.lean.js
969
972
  - docs/assets/basic-form-with-violations.Cv6Y9-Q_.png
970
973
  - docs/assets/basic-form.DbHnu0oW.png
971
- - docs/assets/brut-js.md.B4GYxQVw.js
972
- - docs/assets/brut-js.md.B4GYxQVw.lean.js
973
- - docs/assets/business-logic.md.BY4hGy0m.js
974
- - docs/assets/business-logic.md.BY4hGy0m.lean.js
975
- - docs/assets/chunks/@localSearchIndexroot.BWVzhs5N.js
976
- - docs/assets/chunks/VPLocalSearchBox.DCJk5nAW.js
977
- - docs/assets/chunks/framework.1L-BeKqY.js
978
- - docs/assets/chunks/theme.DZKmijwi.js
979
- - docs/assets/cli.md.CjsktgFz.js
980
- - docs/assets/cli.md.CjsktgFz.lean.js
981
- - docs/assets/components.md.rMhQ0WdZ.js
982
- - docs/assets/components.md.rMhQ0WdZ.lean.js
983
- - docs/assets/configuration.md.BK42Yjp_.js
984
- - docs/assets/configuration.md.BK42Yjp_.lean.js
985
- - docs/assets/css.md.CltvJqAa.js
986
- - docs/assets/css.md.CltvJqAa.lean.js
987
- - docs/assets/custom-element-tests.md.B_rbta32.js
988
- - docs/assets/custom-element-tests.md.B_rbta32.lean.js
989
- - docs/assets/database-access.md.gnluu54N.js
990
- - docs/assets/database-access.md.gnluu54N.lean.js
991
- - docs/assets/database-schema.md.LpmBPVEU.js
992
- - docs/assets/database-schema.md.LpmBPVEU.lean.js
993
- - docs/assets/deployment.md.BLseERGV.js
994
- - docs/assets/deployment.md.BLseERGV.lean.js
974
+ - docs/assets/brut-js.md.BMz0X1Rz.js
975
+ - docs/assets/brut-js.md.BMz0X1Rz.lean.js
976
+ - docs/assets/business-logic.md.DbuaOYGU.js
977
+ - docs/assets/business-logic.md.DbuaOYGU.lean.js
978
+ - docs/assets/chunks/@localSearchIndexroot.BiNFswvo.js
979
+ - docs/assets/chunks/VPLocalSearchBox.DQK6jQou.js
980
+ - docs/assets/chunks/framework.C4nOkCZI.js
981
+ - docs/assets/chunks/theme.BuExsdM9.js
982
+ - docs/assets/cli.md.DDMar_51.js
983
+ - docs/assets/cli.md.DDMar_51.lean.js
984
+ - docs/assets/components.md.Dfd3w6UW.js
985
+ - docs/assets/components.md.Dfd3w6UW.lean.js
986
+ - docs/assets/configuration.md.DTYoV2Ea.js
987
+ - docs/assets/configuration.md.DTYoV2Ea.lean.js
988
+ - docs/assets/css.md.K5rOCOQY.js
989
+ - docs/assets/css.md.K5rOCOQY.lean.js
990
+ - docs/assets/custom-element-tests.md.DiLe-eFw.js
991
+ - docs/assets/custom-element-tests.md.DiLe-eFw.lean.js
992
+ - docs/assets/database-access.md.Dc8l2Plf.js
993
+ - docs/assets/database-access.md.Dc8l2Plf.lean.js
994
+ - docs/assets/database-schema.md.BJ_JhXmO.js
995
+ - docs/assets/database-schema.md.BJ_JhXmO.lean.js
996
+ - docs/assets/deployment.md.C1u5ep0g.js
997
+ - docs/assets/deployment.md.C1u5ep0g.lean.js
995
998
  - docs/assets/dev-env-protocol.DysDAtnz.png
996
- - docs/assets/dev-environment.md.DRH2D2-O.js
997
- - docs/assets/dev-environment.md.DRH2D2-O.lean.js
998
- - docs/assets/dir-structure.md.CWir1pic.js
999
- - docs/assets/dir-structure.md.CWir1pic.lean.js
1000
- - docs/assets/doc-conventions.md.DOkAuXlt.js
1001
- - docs/assets/doc-conventions.md.DOkAuXlt.lean.js
1002
- - docs/assets/end-to-end-tests.md.DzqRpZ43.js
1003
- - docs/assets/end-to-end-tests.md.DzqRpZ43.lean.js
1004
- - docs/assets/features.md.DPFXsy0z.js
1005
- - docs/assets/features.md.DPFXsy0z.lean.js
1006
- - docs/assets/flash-and-session.md.nPvUpnUx.js
1007
- - docs/assets/flash-and-session.md.nPvUpnUx.lean.js
1008
- - docs/assets/form-constraints.md.KTv5cdR4.js
1009
- - docs/assets/form-constraints.md.KTv5cdR4.lean.js
1010
- - docs/assets/forms.md.v9qIbmUM.js
1011
- - docs/assets/forms.md.v9qIbmUM.lean.js
1012
- - docs/assets/getting-started.md.DTOl4c2g.js
1013
- - docs/assets/getting-started.md.DTOl4c2g.lean.js
1014
- - docs/assets/handlers.md.h84MMB1R.js
1015
- - docs/assets/handlers.md.h84MMB1R.lean.js
1016
- - docs/assets/hooks.md.Jmb5VOLA.js
1017
- - docs/assets/hooks.md.Jmb5VOLA.lean.js
1018
- - docs/assets/i18n.md.BAm9t9JJ.js
1019
- - docs/assets/i18n.md.BAm9t9JJ.lean.js
1020
- - docs/assets/index.md.Bn9e0sRJ.js
1021
- - docs/assets/index.md.Bn9e0sRJ.lean.js
999
+ - docs/assets/dev-environment.md.B1S9p5ZK.js
1000
+ - docs/assets/dev-environment.md.B1S9p5ZK.lean.js
1001
+ - docs/assets/dir-structure.md.D1T2kGwj.js
1002
+ - docs/assets/dir-structure.md.D1T2kGwj.lean.js
1003
+ - docs/assets/doc-conventions.md.CDnWaEFg.js
1004
+ - docs/assets/doc-conventions.md.CDnWaEFg.lean.js
1005
+ - docs/assets/end-to-end-tests.md.BJJdNDYL.js
1006
+ - docs/assets/end-to-end-tests.md.BJJdNDYL.lean.js
1007
+ - docs/assets/features.md.BDWxnyNO.js
1008
+ - docs/assets/features.md.BDWxnyNO.lean.js
1009
+ - docs/assets/flash-and-session.md.CUsMxoNl.js
1010
+ - docs/assets/flash-and-session.md.CUsMxoNl.lean.js
1011
+ - docs/assets/form-constraints.md.KlfXSKm2.js
1012
+ - docs/assets/form-constraints.md.KlfXSKm2.lean.js
1013
+ - docs/assets/forms.md.DEkmJUvb.js
1014
+ - docs/assets/forms.md.DEkmJUvb.lean.js
1015
+ - docs/assets/getting-started.md.DO-4eoGW.js
1016
+ - docs/assets/getting-started.md.DO-4eoGW.lean.js
1017
+ - docs/assets/handlers.md.C5tUwmmo.js
1018
+ - docs/assets/handlers.md.C5tUwmmo.lean.js
1019
+ - docs/assets/hooks.md.CoiYCKRc.js
1020
+ - docs/assets/hooks.md.CoiYCKRc.lean.js
1021
+ - docs/assets/i18n.md.DxkCKhUw.js
1022
+ - docs/assets/i18n.md.DxkCKhUw.lean.js
1023
+ - docs/assets/index.md.DnphWyQd.js
1024
+ - docs/assets/index.md.DnphWyQd.lean.js
1022
1025
  - docs/assets/initial-home-page.DNIaYmgP.png
1023
- - docs/assets/instrumentation.md._lNSriEZ.js
1024
- - docs/assets/instrumentation.md._lNSriEZ.lean.js
1025
- - docs/assets/javascript.md.DzrMxUmI.js
1026
- - docs/assets/javascript.md.DzrMxUmI.lean.js
1027
- - docs/assets/jobs.md.S-2amAYp.js
1028
- - docs/assets/jobs.md.S-2amAYp.lean.js
1029
- - docs/assets/keyword-injection.md.95Zgh2eN.js
1030
- - docs/assets/keyword-injection.md.95Zgh2eN.lean.js
1031
- - docs/assets/layouts.md.CVGl9xIO.js
1032
- - docs/assets/layouts.md.CVGl9xIO.lean.js
1033
- - docs/assets/lsp.md.Dn1rIiW0.js
1034
- - docs/assets/lsp.md.Dn1rIiW0.lean.js
1035
- - docs/assets/markdown-examples.md.CCFEQO44.js
1036
- - docs/assets/markdown-examples.md.CCFEQO44.lean.js
1037
- - docs/assets/middleware.md.Czz_UlJN.js
1038
- - docs/assets/middleware.md.Czz_UlJN.lean.js
1026
+ - docs/assets/instrumentation.md.BcxjC4jd.js
1027
+ - docs/assets/instrumentation.md.BcxjC4jd.lean.js
1028
+ - docs/assets/javascript.md.D6fxhaQb.js
1029
+ - docs/assets/javascript.md.D6fxhaQb.lean.js
1030
+ - docs/assets/jobs.md.Bc7Y1YpK.js
1031
+ - docs/assets/jobs.md.Bc7Y1YpK.lean.js
1032
+ - docs/assets/keyword-injection.md.CqLnnzIz.js
1033
+ - docs/assets/keyword-injection.md.CqLnnzIz.lean.js
1034
+ - docs/assets/layouts.md.HEbeK7Jr.js
1035
+ - docs/assets/layouts.md.HEbeK7Jr.lean.js
1036
+ - docs/assets/lsp.md.bE9dW8n9.js
1037
+ - docs/assets/lsp.md.bE9dW8n9.lean.js
1038
+ - docs/assets/markdown-examples.md.BPmtHlc-.js
1039
+ - docs/assets/markdown-examples.md.BPmtHlc-.lean.js
1040
+ - docs/assets/middleware.md.BhOIsg59.js
1041
+ - docs/assets/middleware.md.BhOIsg59.lean.js
1039
1042
  - docs/assets/new-post-editor.DrHr-5oh.png
1040
1043
  - docs/assets/new-post-home-page.Bm34lyMg.png
1041
- - docs/assets/overview.md.DlKiRRG_.js
1042
- - docs/assets/overview.md.DlKiRRG_.lean.js
1043
- - docs/assets/pages.md.B7Hc-i6H.js
1044
- - docs/assets/pages.md.B7Hc-i6H.lean.js
1045
- - docs/assets/recipes_alternate-layouts.md.BwEytl59.js
1046
- - docs/assets/recipes_alternate-layouts.md.BwEytl59.lean.js
1047
- - docs/assets/recipes_authentication.md.nwO6F7Ou.js
1048
- - docs/assets/recipes_authentication.md.nwO6F7Ou.lean.js
1049
- - docs/assets/recipes_blank-layouts.md.fyAUJyJR.js
1050
- - docs/assets/recipes_blank-layouts.md.fyAUJyJR.lean.js
1051
- - docs/assets/recipes_custom-flash.md.CrQbI5eH.js
1052
- - docs/assets/recipes_custom-flash.md.CrQbI5eH.lean.js
1053
- - docs/assets/recipes_form-errors.md.Bv5RCKqH.js
1054
- - docs/assets/recipes_form-errors.md.Bv5RCKqH.lean.js
1055
- - docs/assets/recipes_indexed-forms.md.CstYyOSo.js
1056
- - docs/assets/recipes_indexed-forms.md.CstYyOSo.lean.js
1057
- - docs/assets/recipes_migrations.md.CTcnWDJF.js
1058
- - docs/assets/recipes_migrations.md.CTcnWDJF.lean.js
1059
- - docs/assets/recipes_text-field-component.md.H4wLAK0Z.js
1060
- - docs/assets/recipes_text-field-component.md.H4wLAK0Z.lean.js
1061
- - docs/assets/roadmap.md.C6PRi0DX.js
1062
- - docs/assets/roadmap.md.C6PRi0DX.lean.js
1063
- - docs/assets/routes.md.BD6y2i-f.js
1064
- - docs/assets/routes.md.BD6y2i-f.lean.js
1065
- - docs/assets/security.md.C0G_AZR-.js
1066
- - docs/assets/security.md.C0G_AZR-.lean.js
1067
- - docs/assets/seed-data.md.BvFZlqIk.js
1068
- - docs/assets/seed-data.md.BvFZlqIk.lean.js
1044
+ - docs/assets/overview.md.BpWAgPFH.js
1045
+ - docs/assets/overview.md.BpWAgPFH.lean.js
1046
+ - docs/assets/pages.md.B3sQXpEd.js
1047
+ - docs/assets/pages.md.B3sQXpEd.lean.js
1048
+ - docs/assets/recipes_alternate-layouts.md.C1QzVkA7.js
1049
+ - docs/assets/recipes_alternate-layouts.md.C1QzVkA7.lean.js
1050
+ - docs/assets/recipes_authentication.md.CyvoIW82.js
1051
+ - docs/assets/recipes_authentication.md.CyvoIW82.lean.js
1052
+ - docs/assets/recipes_custom-flash.md.6gFqf2uL.js
1053
+ - docs/assets/recipes_custom-flash.md.6gFqf2uL.lean.js
1054
+ - docs/assets/recipes_form-errors.md.B5ptSzMO.js
1055
+ - docs/assets/recipes_form-errors.md.B5ptSzMO.lean.js
1056
+ - docs/assets/recipes_indexed-forms.md.BYYQGW2C.js
1057
+ - docs/assets/recipes_indexed-forms.md.BYYQGW2C.lean.js
1058
+ - docs/assets/recipes_migrations.md.Cid7-3cu.js
1059
+ - docs/assets/recipes_migrations.md.Cid7-3cu.lean.js
1060
+ - docs/assets/recipes_text-field-component.md.VhOsCtKI.js
1061
+ - docs/assets/recipes_text-field-component.md.VhOsCtKI.lean.js
1062
+ - docs/assets/roadmap.md.CJsbUmK_.js
1063
+ - docs/assets/roadmap.md.CJsbUmK_.lean.js
1064
+ - docs/assets/routes.md.C1dgIBtD.js
1065
+ - docs/assets/routes.md.C1dgIBtD.lean.js
1066
+ - docs/assets/security.md.Jn4SY1uK.js
1067
+ - docs/assets/security.md.Jn4SY1uK.lean.js
1068
+ - docs/assets/seed-data.md.UZW0WxYN.js
1069
+ - docs/assets/seed-data.md.UZW0WxYN.lean.js
1069
1070
  - docs/assets/spa.qejUdp-5.png
1070
- - docs/assets/space-time-continuum.md.xl44xDos.js
1071
- - docs/assets/space-time-continuum.md.xl44xDos.lean.js
1071
+ - docs/assets/space-time-continuum.md.D9rYGDFH.js
1072
+ - docs/assets/space-time-continuum.md.D9rYGDFH.lean.js
1072
1073
  - docs/assets/style.B1z60PPQ.css
1073
1074
  - docs/assets/styled-form-with-server-side-violations.Bjxd8Dpv.png
1074
1075
  - docs/assets/styled-form-with-violations.Bv_sa9tg.png
1075
1076
  - docs/assets/styled-home-page-with-posts.Dd4kG89D.png
1076
1077
  - docs/assets/styled-home-page.BzdI7dWz.png
1077
- - docs/assets/tutorial.md.BM40jnoq.js
1078
- - docs/assets/tutorial.md.BM40jnoq.lean.js
1079
- - docs/assets/tutorials_01-intro.md.B4sUBY3X.js
1080
- - docs/assets/tutorials_01-intro.md.B4sUBY3X.lean.js
1081
- - docs/assets/tutorials_02-dialog.md.CPNK1SC_.js
1082
- - docs/assets/tutorials_02-dialog.md.CPNK1SC_.lean.js
1083
- - docs/assets/unit-tests.md.DUGrnLj5.js
1084
- - docs/assets/unit-tests.md.DUGrnLj5.lean.js
1078
+ - docs/assets/tutorial.md.BX6f6l00.js
1079
+ - docs/assets/tutorial.md.BX6f6l00.lean.js
1080
+ - docs/assets/tutorials_01-intro.md.CzZ3kpF_.js
1081
+ - docs/assets/tutorials_01-intro.md.CzZ3kpF_.lean.js
1082
+ - docs/assets/tutorials_02-dialog.md.D2vSjDVf.js
1083
+ - docs/assets/tutorials_02-dialog.md.D2vSjDVf.lean.js
1084
+ - docs/assets/unit-tests.md.vDsdBbO_.js
1085
+ - docs/assets/unit-tests.md.vDsdBbO_.lean.js
1085
1086
  - docs/assets/welcome-to-brut.VSWzl17-.png
1086
- - docs/assets/why.md.C-hk5xgJ.js
1087
- - docs/assets/why.md.C-hk5xgJ.lean.js
1087
+ - docs/assets/why.md.4WpxdrQ2.js
1088
+ - docs/assets/why.md.4WpxdrQ2.lean.js
1088
1089
  - docs/assets/workspace-protocol.C0gXsoDb.png
1089
1090
  - docs/brut-css/brut.css
1090
1091
  - docs/brut-css/brut.max.css
@@ -1149,6 +1150,8 @@ files:
1149
1150
  - docs/brut-js/api/RichString.js.html
1150
1151
  - docs/brut-js/api/Tabs.html
1151
1152
  - docs/brut-js/api/Tabs.js.html
1153
+ - docs/brut-js/api/Toast.html
1154
+ - docs/brut-js/api/Toast.js.html
1152
1155
  - docs/brut-js/api/Tracing.html
1153
1156
  - docs/brut-js/api/Tracing.js.html
1154
1157
  - docs/brut-js/api/external-CustomElementRegistry.html
@@ -1213,7 +1216,6 @@ files:
1213
1216
  - docs/pages.html
1214
1217
  - docs/recipes/alternate-layouts.html
1215
1218
  - docs/recipes/authentication.html
1216
- - docs/recipes/blank-layouts.html
1217
1219
  - docs/recipes/custom-flash.html
1218
1220
  - docs/recipes/form-errors.html
1219
1221
  - docs/recipes/indexed-forms.html
@@ -1232,6 +1234,7 @@ files:
1232
1234
  - docs/why.html
1233
1235
  - dx/bash_customizations
1234
1236
  - dx/build
1237
+ - dx/build.pre
1235
1238
  - dx/docker-compose.env
1236
1239
  - dx/dx.sh.lib
1237
1240
  - dx/exec
@@ -1405,6 +1408,8 @@ files:
1405
1408
  - mkbrut/dx
1406
1409
  - mkbrut/exe/mkbrut
1407
1410
  - mkbrut/lib/mkbrut.rb
1411
+ - mkbrut/lib/mkbrut/add_segment.rb
1412
+ - mkbrut/lib/mkbrut/add_segment_options.rb
1408
1413
  - mkbrut/lib/mkbrut/app.rb
1409
1414
  - mkbrut/lib/mkbrut/app_id.rb
1410
1415
  - mkbrut/lib/mkbrut/app_name.rb
@@ -1422,6 +1427,7 @@ files:
1422
1427
  - mkbrut/lib/mkbrut/ops/base_op.rb
1423
1428
  - mkbrut/lib/mkbrut/ops/copy_file.rb
1424
1429
  - mkbrut/lib/mkbrut/ops/insert_code_in_method.rb
1430
+ - mkbrut/lib/mkbrut/ops/insert_into_file.rb
1425
1431
  - mkbrut/lib/mkbrut/ops/insert_route.rb
1426
1432
  - mkbrut/lib/mkbrut/ops/mkdir.rb
1427
1433
  - mkbrut/lib/mkbrut/ops/prism_parsing_op.rb
@@ -1490,6 +1496,7 @@ files:
1490
1496
  - mkbrut/templates/Base/bin/dev
1491
1497
  - mkbrut/templates/Base/bin/release
1492
1498
  - mkbrut/templates/Base/bin/run
1499
+ - mkbrut/templates/Base/bin/run.run
1493
1500
  - mkbrut/templates/Base/bin/scaffold
1494
1501
  - mkbrut/templates/Base/bin/setup
1495
1502
  - mkbrut/templates/Base/bin/startup-message
@@ -1544,6 +1551,14 @@ files:
1544
1551
  - mkbrut/templates/segments/Heroku/deploy/Dockerfile
1545
1552
  - mkbrut/templates/segments/Heroku/deploy/docker-entrypoint
1546
1553
  - mkbrut/templates/segments/Heroku/deploy/heroku_config.rb
1554
+ - mkbrut/templates/segments/Sidekiq/app/boot_sidekiq.rb
1555
+ - mkbrut/templates/segments/Sidekiq/app/config/sidekiq.yml
1556
+ - mkbrut/templates/segments/Sidekiq/app/src/back_end/jobs/app_job.rb
1557
+ - mkbrut/templates/segments/Sidekiq/app/src/back_end/jobs/example_job.rb
1558
+ - mkbrut/templates/segments/Sidekiq/app/src/back_end/segments/sidekiq_segment.rb
1559
+ - mkbrut/templates/segments/Sidekiq/bin/run.sidekiq
1560
+ - mkbrut/templates/segments/Sidekiq/specs/back_end/jobs/example_job.spec.rb
1561
+ - mkbrut/templates/segments/Sidekiq/specs/integration/sidekiq_works.spec.rb
1547
1562
  - specs/brut/front_end/forms/input.spec.rb
1548
1563
  - specs/brut/front_end/forms/radio_button_group_input.spec.rb
1549
1564
  - specs/brut/front_end/forms/select_input.spec.rb
@@ -1576,7 +1591,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1576
1591
  - !ruby/object:Gem::Version
1577
1592
  version: '0'
1578
1593
  requirements: []
1579
- rubygems_version: 3.7.1
1594
+ rubygems_version: 3.7.2
1580
1595
  specification_version: 4
1581
1596
  summary: Web Framework Built around Ruby, Web Standards, Simplicity, and Object-Orientation
1582
1597
  test_files: []
@@ -1 +0,0 @@
1
- import{_ as a,c as r,o as t,ag as d}from"./chunks/framework.1L-BeKqY.js";const _=JSON.parse('{"title":"Architecture Decision Records","description":"","frontmatter":{},"headers":[],"relativePath":"adrs.md","filePath":"adrs.md"}'),s={name:"adrs.md"};function l(o,e,i,c,n,h){return t(),r("div",null,e[0]||(e[0]=[d('<h1 id="architecture-decision-records" tabindex="-1">Architecture Decision Records <a class="header-anchor" href="#architecture-decision-records" aria-label="Permalink to &quot;Architecture Decision Records&quot;">​</a></h1><p>The decisions here aren&#39;t <em>all</em> the architectural decisions I made, but are some of them, and mostly hold up.</p><p><code>adrs.cloud</code> is a Brut app.</p><ul><li><a href="https://adrs.cloud/shared_adrs/padr_b6920f0df907886b8a9207e9e2c9c2a2" target="_blank" rel="noreferrer">Rely on Web Standards and MDN Baseline</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_57f2397009a8aaf2c6083813ca588d73" target="_blank" rel="noreferrer">The Core Abstraction is the Plain Old Class</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_cdfcbe6b116b80a4f3d53fb3a6ed44b2" target="_blank" rel="noreferrer">Pages and Forms are First-Class Abstractions…not REST</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_01810ba90a92ec6c081a81affe212fb2" target="_blank" rel="noreferrer">Sequel will provide the data layer and its models will only model the database</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_f318e74925cb3e9d7e0eda329d085c4a" target="_blank" rel="noreferrer">There will be no controllers. Purpose-built classes will support pages, forms, and components.</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_e7078d29f00710848ebbe43aea6094a6" target="_blank" rel="noreferrer">Brut will not provider mailers, cloud storage, or background jobs</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_03b5cf8e34bb7900a38f6de27e50adaa" target="_blank" rel="noreferrer">Requiring files should not execute code</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_9529a5ada671254b5e5865b45abde92d" target="_blank" rel="noreferrer">Phlex will be used for HTML templating</a></li><li><a href="https://adrs.cloud/shared_adrs/padr_724a65340d734970ea222593a4a2760f" target="_blank" rel="noreferrer">RSpec is the default testing framework</a></li></ul>',4)]))}const p=a(s,[["render",l]]);export{_ as __pageData,p as default};
@@ -1 +0,0 @@
1
- import{_ as a,c as r,o as t,ag as d}from"./chunks/framework.1L-BeKqY.js";const _=JSON.parse('{"title":"Architecture Decision Records","description":"","frontmatter":{},"headers":[],"relativePath":"adrs.md","filePath":"adrs.md"}'),s={name:"adrs.md"};function l(o,e,i,c,n,h){return t(),r("div",null,e[0]||(e[0]=[d("",4)]))}const p=a(s,[["render",l]]);export{_ as __pageData,p as default};
@@ -1 +0,0 @@
1
- import{_ as t,c as o,o as a,ag as i}from"./chunks/framework.1L-BeKqY.js";const b=JSON.parse('{"title":"AI Declaration and Notes","description":"","frontmatter":{},"headers":[],"relativePath":"ai.md","filePath":"ai.md"}'),s={name:"ai.md"};function r(n,e,l,d,h,c){return a(),o("div",null,e[0]||(e[0]=[i('<h1 id="ai-declaration-and-notes" tabindex="-1">AI Declaration and Notes <a class="header-anchor" href="#ai-declaration-and-notes" aria-label="Permalink to &quot;AI Declaration and Notes&quot;">​</a></h1><p>LLMs and AI tools are a current fact of life. We feel it&#39;s important to be realistic and up front about how they affect this project.</p><h2 id="levels-of-ai-use" tabindex="-1">Levels of AI Use <a class="header-anchor" href="#levels-of-ai-use" aria-label="Permalink to &quot;Levels of AI Use&quot;">​</a></h2><p>I created <a href="https://declare-ai.org/" target="_blank" rel="noreferrer">declare-ai.org</a> to allow precise documentation of how AI is used in a project. It defines four levels of AI use:</p><ol><li>No involvement at all.</li><li>Non-create assistance, such as the completions GitHub Copilot may make while you are typing.</li><li>Creative assistance, where an AI generated a large amount of code that you then modified. An example would be using a tool like Cursor to write code for your review.</li><li>Completely Produced by an AI, for example if you used Stable Diffusion to create your icon.</li></ol><h2 id="code" tabindex="-1">Code <a class="header-anchor" href="#code" aria-label="Permalink to &quot;Code&quot;">​</a></h2><p>The entirety of Brut&#39;s codebase could be grouped into three parts:</p><ul><li>The library code developers use. This is, roughly, the code in <code>lib</code>, <code>brut-js/src</code>, and <code>brut-css/src</code>.</li><li>Tests of the library code.</li><li>Tools used to manage the library code, such as what&#39;s in <code>bin/</code>, <code>brut-js/bin</code>, <code>brut-css/bin</code>, etc.</li></ul><h3 id="library-code-should-be-written-by-a-person" tabindex="-1">Library Code Should Be Written By a Person <a class="header-anchor" href="#library-code-should-be-written-by-a-person" aria-label="Permalink to &quot;Library Code Should Be Written By a Person&quot;">​</a></h3><p>We want the library code written by a person, i.e. it should have level 1 AI assistance: none. As of this writing—June 17, 2025—all library code was written by a person.</p><p>If some code is level 2—non-creative assistance—that is probably fine.</p><h3 id="tests-should-not-be-totally-written-by-ai" tabindex="-1">Tests Should Not Be Totally Written by AI <a class="header-anchor" href="#tests-should-not-be-totally-written-by-ai" aria-label="Permalink to &quot;Tests Should Not Be Totally Written by AI&quot;">​</a></h3><p>As of this writing—June 17, 2025—the library has no automated tests. The <code>adrs.cloud</code> app serves as the test suite.</p><p>That said, as tests are developed, they must never be written entirely by an AI without human review (level 4). Our preference is that all tests comply with level 1 or level 2, however we are open to creative assistance for tests as might be provided by a tool like Cursor.</p><p>In any case, the author of a test should understand it and the maintainers must be able to understand and modify all tests without the use of AI tools.</p><h3 id="management-tools-should-not-be-totally-written-by-ai" tabindex="-1">Management Tools Should Not Be Totally Written by AI <a class="header-anchor" href="#management-tools-should-not-be-totally-written-by-ai" aria-label="Permalink to &quot;Management Tools Should Not Be Totally Written by AI&quot;">​</a></h3><p>Like tests, management tools must be comprehensible by a person and the creator of the code must understand it. That said, some of the tools were created with level 3 AI assistance, and we expect these tools may continue to be created this way.</p><p>Nevertheless, this code must be reviewed and understood by a person.</p><h2 id="documentation" tabindex="-1">Documentation <a class="header-anchor" href="#documentation" aria-label="Permalink to &quot;Documentation&quot;">​</a></h2><p>We strive to have all documentation written by a real person. None of this documentation, or the API documentation, is produced by a machine, although spelling and grammar corrections will certainly have been suggested by automated tools.</p><p>We expect an LLM to be able to digest this documentation and source code and provide alternate analysis of how Brut works and how to use it. We hope such analysis is correct and useful, however that cannot be guaranteed, so this documentation is the second best source of truth, the source code being the best.</p><h2 id="logos" tabindex="-1">Logos <a class="header-anchor" href="#logos" aria-label="Permalink to &quot;Logos&quot;">​</a></h2><p>While the various logos look like someone typed &quot;make me a logo in the style of the Washington, DC Metro&quot;, if you look closely, you will see the telltale sings that they were made by a person…a person who is not a professional designer.</p><p>As such, these are all Level 1.</p><h2 id="ai-information-about-brut-should-be-viewed-with-skepticism" tabindex="-1">AI Information about Brut Should Be Viewed with Skepticism <a class="header-anchor" href="#ai-information-about-brut-should-be-viewed-with-skepticism" aria-label="Permalink to &quot;AI Information about Brut Should Be Viewed with Skepticism&quot;">​</a></h2><ul><li><strong>Answers from an LLM about Brut are likely incorrect.</strong> LLMs will certainly not have been trained on information about Brut, since it is new.</li><li><strong>Code Completions of Brut Code are suspect.</strong> I have observed that e.g. GitHub CoPilot is capable for properly completing Brut code if there is enough context, but it is not capable of, say, creating a component from scratch. <strong>Review all Code Completions Carefully</strong>.</li></ul>',26)]))}const p=t(s,[["render",r]]);export{b as __pageData,p as default};
@@ -1 +0,0 @@
1
- import{_ as t,c as o,o as a,ag as i}from"./chunks/framework.1L-BeKqY.js";const b=JSON.parse('{"title":"AI Declaration and Notes","description":"","frontmatter":{},"headers":[],"relativePath":"ai.md","filePath":"ai.md"}'),s={name:"ai.md"};function r(n,e,l,d,h,c){return a(),o("div",null,e[0]||(e[0]=[i("",26)]))}const p=t(s,[["render",r]]);export{b as __pageData,p as default};
@@ -1 +0,0 @@
1
- import{_ as e,c as a,o as i,ag as t}from"./chunks/framework.1L-BeKqY.js";const u=JSON.parse('{"title":"Assets","description":"","frontmatter":{},"headers":[],"relativePath":"assets.md","filePath":"assets.md"}'),n={name:"assets.md"};function o(h,s,l,r,p,d){return i(),a("div",null,s[0]||(s[0]=[t("",39)]))}const k=e(n,[["render",o]]);export{u as __pageData,k as default};
@@ -1 +0,0 @@
1
- import{_ as t,c as a,o as s,ag as o}from"./chunks/framework.1L-BeKqY.js";const i="/assets/spa.qejUdp-5.png",m=JSON.parse('{"title":"BrutJS","description":"","frontmatter":{},"headers":[],"relativePath":"brut-js.md","filePath":"brut-js.md"}'),n={name:"brut-js.md"};function r(l,e,d,h,c,p){return s(),a("div",null,e[0]||(e[0]=[o("",35)]))}const g=t(n,[["render",r]]);export{m as __pageData,g as default};
@@ -1 +0,0 @@
1
- import{_ as o,c as a,o as s,ag as t}from"./chunks/framework.1L-BeKqY.js";const m=JSON.parse('{"title":"Business or Domain Logic","description":"","frontmatter":{},"headers":[],"relativePath":"business-logic.md","filePath":"business-logic.md"}'),n={name:"business-logic.md"};function i(c,e,r,d,l,u){return s(),a("div",null,e[0]||(e[0]=[t('<h1 id="business-or-domain-logic" tabindex="-1">Business or Domain Logic <a class="header-anchor" href="#business-or-domain-logic" aria-label="Permalink to &quot;Business or Domain Logic&quot;">​</a></h1><p>Since business and domain logic is not required, nor encouraged, to go in your data models, where does it go?</p><p>It can go anywhere you like - Brut is not currently prescriptive.</p><h2 id="overview" tabindex="-1">Overview <a class="header-anchor" href="#overview" aria-label="Permalink to &quot;Overview&quot;">​</a></h2><p>It&#39;s recommended that you place classes in <code>app/src/back_end</code>. Any directory created in there will be auto-loaded by Brut/Zeitwerk based on its rules. This means that classes in any directory in <code>app/src/back_end</code> should not be namespaced.</p><p>For example, if you have <em>commands</em> and <em>queries</em>, you may want them in <code>app/src/back_end/commands</code> and <code>app/src/back_end/queries</code>, respectively. In this case, <code>NewOrganizationCommand</code> would go in <code>app/src/back_end/commands/new_organization_command.rb</code> and <code>AccountQuery</code> would go in <code>app/src/back_end/queries/account_query.rb</code></p><p>Or, you could could organize them into <code>app/src/back_end/business_logic/commands</code> and <code>app/src/back_end/business_logic/queries</code>. In that case, <code>Commands::NewOrganization</code> would be expected in <code>app/src/back_end/business_logic/commands/new_organization.rb</code> and <code>Queries::Account</code> would be expected in <code>app/src/back_end/business_logic/queries/account.rb</code>.</p><p>How you organize it is up to you.</p><h2 id="testing" tabindex="-1">Testing <a class="header-anchor" href="#testing" aria-label="Permalink to &quot;Testing&quot;">​</a></h2><p>Tests can be written using RSpec in the usual way. Spec files should be in <code>specs/back_end/path/to/class.spec.rb</code>. Note that Brut expects Spec files to end in <code>.spec.rb</code> and <em>not</em><code>_spec.rb</code>.</p><p>There is nothing special about the tests for your domain logic. Write them however you need to.</p><h2 id="recomended-practices" tabindex="-1">Recomended Practices <a class="header-anchor" href="#recomended-practices" aria-label="Permalink to &quot;Recomended Practices&quot;">​</a></h2><p>This could be an entire series of books. The main recommendation is to take a light approach and don&#39;t immediately install complex frameworks or libraries unless you know you need them.</p><p>Something somewhere in your business logic will need to interface with your front-end. The simplest way to do that is to allow form objects to be passed into your back-end. The second simplest way is to pass form values into your back-end.</p><p>You are strongly discouraged from having your front-end locate data models and pass those to your back-end. This can be done while prototyping and for fast iteration on a concept, but generally you do not want to query your database from your handlers or pages just to pass the results into a back-end class.</p><p>Exposing data models to the front-end is generally OK, as that is sometimes what you need to do.</p><h2 id="technical-notes" tabindex="-1">Technical Notes <a class="header-anchor" href="#technical-notes" aria-label="Permalink to &quot;Technical Notes&quot;">​</a></h2><div class="important custom-block github-alert"><p class="custom-block-title">IMPORTANT</p><p>Technical Notes are for deeper understanding and debugging. While we will try to keep them up-to-date with changes to Brut&#39;s internals, the source code is always more correct.</p></div><p><em>Last Updated May 7, 2025</em></p><p>Creating universal abstractions from business logic is difficult. Brut is unlikely to do this. If it does, it will be after much analysis of exsiting patterns and <em>only</em> if it helps avoid mistakes and increases developer throughput.</p>',20)]))}const h=o(n,[["render",i]]);export{m as __pageData,h as default};
@@ -1 +0,0 @@
1
- import{_ as o,c as a,o as s,ag as t}from"./chunks/framework.1L-BeKqY.js";const m=JSON.parse('{"title":"Business or Domain Logic","description":"","frontmatter":{},"headers":[],"relativePath":"business-logic.md","filePath":"business-logic.md"}'),n={name:"business-logic.md"};function i(c,e,r,d,l,u){return s(),a("div",null,e[0]||(e[0]=[t("",20)]))}const h=o(n,[["render",i]]);export{m as __pageData,h as default};