lcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1676) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/skills/lcp-custom-field/SKILL.md +205 -0
  3. data/.claude/skills/lcp-getting-started/SKILL.md +332 -0
  4. data/.claude/skills/lcp-host-binding/SKILL.md +287 -0
  5. data/.claude/skills/lcp-model/SKILL.md +185 -0
  6. data/.claude/skills/lcp-permissions/SKILL.md +176 -0
  7. data/.claude/skills/lcp-presenter/SKILL.md +194 -0
  8. data/.claude/skills/lcp-workflow/SKILL.md +281 -0
  9. data/CHANGELOG.md +69 -0
  10. data/MIT-LICENSE +20 -0
  11. data/README.md +28 -0
  12. data/Rakefile +17 -0
  13. data/app/assets/javascripts/lcp_ruby/application.js +58 -0
  14. data/app/assets/javascripts/lcp_ruby/controllers/advanced_filter_controller.js +1521 -0
  15. data/app/assets/javascripts/lcp_ruby/controllers/approval_actions_controller.js +24 -0
  16. data/app/assets/javascripts/lcp_ruby/controllers/array_input_controller.js +156 -0
  17. data/app/assets/javascripts/lcp_ruby/controllers/batch_select_controller.js +405 -0
  18. data/app/assets/javascripts/lcp_ruby/controllers/cascading_selects_controller.js +436 -0
  19. data/app/assets/javascripts/lcp_ruby/controllers/char_counter_controller.js +28 -0
  20. data/app/assets/javascripts/lcp_ruby/controllers/clipboard_controller.js +62 -0
  21. data/app/assets/javascripts/lcp_ruby/controllers/conditional_rendering_controller.js +178 -0
  22. data/app/assets/javascripts/lcp_ruby/controllers/confirm_dialog_controller.js +131 -0
  23. data/app/assets/javascripts/lcp_ruby/controllers/custom_fields_manage_controller.js +80 -0
  24. data/app/assets/javascripts/lcp_ruby/controllers/dialog_controller.js +421 -0
  25. data/app/assets/javascripts/lcp_ruby/controllers/dialog_nested_controller.js +182 -0
  26. data/app/assets/javascripts/lcp_ruby/controllers/direct_upload_controller.js +100 -0
  27. data/app/assets/javascripts/lcp_ruby/controllers/drawer_controller.js +205 -0
  28. data/app/assets/javascripts/lcp_ruby/controllers/dropdown_controller.js +160 -0
  29. data/app/assets/javascripts/lcp_ruby/controllers/export_dialog_controller.js +15 -0
  30. data/app/assets/javascripts/lcp_ruby/controllers/field_picker_controller.js +290 -0
  31. data/app/assets/javascripts/lcp_ruby/controllers/file_upload_controller.js +135 -0
  32. data/app/assets/javascripts/lcp_ruby/controllers/filter_auto_submit_controller.js +46 -0
  33. data/app/assets/javascripts/lcp_ruby/controllers/filter_dirty_controller.js +94 -0
  34. data/app/assets/javascripts/lcp_ruby/controllers/form_actions_controller.js +68 -0
  35. data/app/assets/javascripts/lcp_ruby/controllers/form_handling_controller.js +67 -0
  36. data/app/assets/javascripts/lcp_ruby/controllers/import_dialog_controller.js +142 -0
  37. data/app/assets/javascripts/lcp_ruby/controllers/import_mapper_controller.js +322 -0
  38. data/app/assets/javascripts/lcp_ruby/controllers/index_sortable_controller.js +388 -0
  39. data/app/assets/javascripts/lcp_ruby/controllers/inline_create_controller.js +137 -0
  40. data/app/assets/javascripts/lcp_ruby/controllers/kanban_board_controller.js +290 -0
  41. data/app/assets/javascripts/lcp_ruby/controllers/menu_controller.js +19 -0
  42. data/app/assets/javascripts/lcp_ruby/controllers/nested_forms_controller.js +261 -0
  43. data/app/assets/javascripts/lcp_ruby/controllers/responsive_sidebar_controller.js +161 -0
  44. data/app/assets/javascripts/lcp_ruby/controllers/responsive_top_nav_controller.js +394 -0
  45. data/app/assets/javascripts/lcp_ruby/controllers/saved_filters_controller.js +129 -0
  46. data/app/assets/javascripts/lcp_ruby/controllers/search_controller.js +82 -0
  47. data/app/assets/javascripts/lcp_ruby/controllers/selection_controller.js +33 -0
  48. data/app/assets/javascripts/lcp_ruby/controllers/sidebar_controller.js +83 -0
  49. data/app/assets/javascripts/lcp_ruby/controllers/sidebar_toggle_controller.js +66 -0
  50. data/app/assets/javascripts/lcp_ruby/controllers/slider_controller.js +26 -0
  51. data/app/assets/javascripts/lcp_ruby/controllers/submenu_controller.js +55 -0
  52. data/app/assets/javascripts/lcp_ruby/controllers/tom_select_controller.js +168 -0
  53. data/app/assets/javascripts/lcp_ruby/controllers/tree_index_controller.js +106 -0
  54. data/app/assets/javascripts/lcp_ruby/controllers/tree_reparent_controller.js +182 -0
  55. data/app/assets/javascripts/lcp_ruby/controllers/tree_select_controller.js +119 -0
  56. data/app/assets/javascripts/lcp_ruby/controllers/ui_components_controller.js +135 -0
  57. data/app/assets/javascripts/lcp_ruby/controllers/zone_tabs_controller.js +66 -0
  58. data/app/assets/javascripts/lcp_ruby/dev_toolbar.js +494 -0
  59. data/app/assets/javascripts/lcp_ruby/i18n.js.erb +29 -0
  60. data/app/assets/javascripts/lcp_ruby/lucide_init.js +24 -0
  61. data/app/assets/javascripts/lcp_ruby/stimulus_bootstrap.js +7 -0
  62. data/app/assets/javascripts/lcp_ruby/utils.js +119 -0
  63. data/app/assets/javascripts/lcp_ruby/xhr_fetch.js +411 -0
  64. data/app/assets/stylesheets/lcp_ruby/application.css +1940 -0
  65. data/app/assets/stylesheets/lcp_ruby/dev_toolbar.css +355 -0
  66. data/app/controllers/concerns/lcp_ruby/dialog_rendering.rb +167 -0
  67. data/app/controllers/concerns/lcp_ruby/form_action_execution.rb +249 -0
  68. data/app/controllers/concerns/lcp_ruby/page_authorization.rb +105 -0
  69. data/app/controllers/concerns/lcp_ruby/zone_resolution.rb +199 -0
  70. data/app/controllers/lcp_ruby/actions_controller.rb +481 -0
  71. data/app/controllers/lcp_ruby/application_controller.rb +59 -0
  72. data/app/controllers/lcp_ruby/approval_tasks_controller.rb +98 -0
  73. data/app/controllers/lcp_ruby/auth/base_controller.rb +58 -0
  74. data/app/controllers/lcp_ruby/auth/callbacks_controller.rb +103 -0
  75. data/app/controllers/lcp_ruby/auth/passwords_controller.rb +15 -0
  76. data/app/controllers/lcp_ruby/auth/registrations_controller.rb +37 -0
  77. data/app/controllers/lcp_ruby/auth/sessions_controller.rb +112 -0
  78. data/app/controllers/lcp_ruby/custom_fields_controller.rb +370 -0
  79. data/app/controllers/lcp_ruby/dev_toolbar_controller.rb +197 -0
  80. data/app/controllers/lcp_ruby/dialogs_controller.rb +199 -0
  81. data/app/controllers/lcp_ruby/health_controller.rb +23 -0
  82. data/app/controllers/lcp_ruby/impersonation_controller.rb +32 -0
  83. data/app/controllers/lcp_ruby/landing_controller.rb +49 -0
  84. data/app/controllers/lcp_ruby/metrics_controller.rb +17 -0
  85. data/app/controllers/lcp_ruby/resources_controller.rb +2218 -0
  86. data/app/controllers/lcp_ruby/saved_filters_controller.rb +221 -0
  87. data/app/helpers/lcp_ruby/condition_helper.rb +87 -0
  88. data/app/helpers/lcp_ruby/dashboard_helper.rb +45 -0
  89. data/app/helpers/lcp_ruby/dev_toolbar_helper.rb +17 -0
  90. data/app/helpers/lcp_ruby/dialog_helper.rb +27 -0
  91. data/app/helpers/lcp_ruby/display/card_helper.rb +317 -0
  92. data/app/helpers/lcp_ruby/display_helper.rb +63 -0
  93. data/app/helpers/lcp_ruby/display_template_helper.rb +100 -0
  94. data/app/helpers/lcp_ruby/form_helper.rb +1020 -0
  95. data/app/helpers/lcp_ruby/grouped_query_helper.rb +107 -0
  96. data/app/helpers/lcp_ruby/i18n_payload_helper.rb +197 -0
  97. data/app/helpers/lcp_ruby/layout_helper.rb +832 -0
  98. data/app/helpers/lcp_ruby/link_through_helper.rb +29 -0
  99. data/app/helpers/lcp_ruby/oidc_button_helper.rb +59 -0
  100. data/app/helpers/lcp_ruby/search_helper.rb +31 -0
  101. data/app/helpers/lcp_ruby/tree_helper.rb +140 -0
  102. data/app/helpers/lcp_ruby/view_slot_helper.rb +33 -0
  103. data/app/models/lcp_ruby/user.rb +61 -0
  104. data/app/views/layouts/lcp_ruby/application.html.erb +168 -0
  105. data/app/views/layouts/lcp_ruby/auth.html.erb +170 -0
  106. data/app/views/lcp_ruby/auth/callbacks/failure.html.erb +18 -0
  107. data/app/views/lcp_ruby/auth/mailer/reset_password_instructions.html.erb +9 -0
  108. data/app/views/lcp_ruby/auth/passwords/edit.html.erb +34 -0
  109. data/app/views/lcp_ruby/auth/passwords/new.html.erb +24 -0
  110. data/app/views/lcp_ruby/auth/registrations/edit.html.erb +48 -0
  111. data/app/views/lcp_ruby/auth/registrations/new.html.erb +46 -0
  112. data/app/views/lcp_ruby/auth/sessions/new.html.erb +55 -0
  113. data/app/views/lcp_ruby/auth/shared/_links.html.erb +13 -0
  114. data/app/views/lcp_ruby/custom_fields/_manage_row.html.erb +82 -0
  115. data/app/views/lcp_ruby/custom_fields/manage.html.erb +47 -0
  116. data/app/views/lcp_ruby/dialogs/_dialog_composite_frame.html.erb +87 -0
  117. data/app/views/lcp_ruby/dialogs/_dialog_frame.html.erb +60 -0
  118. data/app/views/lcp_ruby/dialogs/_dialog_show_frame.html.erb +14 -0
  119. data/app/views/lcp_ruby/dialogs/_show_secret.html.erb +10 -0
  120. data/app/views/lcp_ruby/dialogs/_success.html.erb +1 -0
  121. data/app/views/lcp_ruby/errors/not_found.html.erb +5 -0
  122. data/app/views/lcp_ruby/menu_renderers/_user_menu.html.erb +51 -0
  123. data/app/views/lcp_ruby/menu_renderers/_user_menu_panel.html.erb +32 -0
  124. data/app/views/lcp_ruby/navigation/_auto_top.html.erb +16 -0
  125. data/app/views/lcp_ruby/navigation/_both_sidebar.html.erb +1 -0
  126. data/app/views/lcp_ruby/navigation/_both_top.html.erb +1 -0
  127. data/app/views/lcp_ruby/navigation/_impersonation_banner.html.erb +14 -0
  128. data/app/views/lcp_ruby/navigation/_item_content.html.erb +23 -0
  129. data/app/views/lcp_ruby/navigation/_link_or_button.html.erb +51 -0
  130. data/app/views/lcp_ruby/navigation/_mobile_header.html.erb +23 -0
  131. data/app/views/lcp_ruby/navigation/_panel_item.html.erb +32 -0
  132. data/app/views/lcp_ruby/navigation/_sidebar.html.erb +38 -0
  133. data/app/views/lcp_ruby/navigation/_sidebar_item.html.erb +38 -0
  134. data/app/views/lcp_ruby/navigation/_sidebar_toggle.html.erb +32 -0
  135. data/app/views/lcp_ruby/navigation/_top.html.erb +26 -0
  136. data/app/views/lcp_ruby/navigation/_top_item.html.erb +112 -0
  137. data/app/views/lcp_ruby/navigation/_widget_item.html.erb +14 -0
  138. data/app/views/lcp_ruby/resources/_action_button.html.erb +138 -0
  139. data/app/views/lcp_ruby/resources/_advanced_filter.html.erb +55 -0
  140. data/app/views/lcp_ruby/resources/_api_status_banner.html.erb +11 -0
  141. data/app/views/lcp_ruby/resources/_association_list.html.erb +132 -0
  142. data/app/views/lcp_ruby/resources/_audit_history.html.erb +66 -0
  143. data/app/views/lcp_ruby/resources/_batch_toolbar.html.erb +54 -0
  144. data/app/views/lcp_ruby/resources/_filter_form.html.erb +57 -0
  145. data/app/views/lcp_ruby/resources/_form.html.erb +73 -0
  146. data/app/views/lcp_ruby/resources/_form_action_button.html.erb +20 -0
  147. data/app/views/lcp_ruby/resources/_form_action_dropdown_item.html.erb +17 -0
  148. data/app/views/lcp_ruby/resources/_form_actions.html.erb +38 -0
  149. data/app/views/lcp_ruby/resources/_form_section.html.erb +235 -0
  150. data/app/views/lcp_ruby/resources/_grid_page.html.erb +17 -0
  151. data/app/views/lcp_ruby/resources/_grouped_index.html.erb +61 -0
  152. data/app/views/lcp_ruby/resources/_inline_create_form.html.erb +50 -0
  153. data/app/views/lcp_ruby/resources/_json_items_list.html.erb +77 -0
  154. data/app/views/lcp_ruby/resources/_json_nested_fields.html.erb +30 -0
  155. data/app/views/lcp_ruby/resources/_kanban_card.html.erb +31 -0
  156. data/app/views/lcp_ruby/resources/_kanban_card_body.html.erb +17 -0
  157. data/app/views/lcp_ruby/resources/_kanban_column.html.erb +33 -0
  158. data/app/views/lcp_ruby/resources/_kanban_column_header.html.erb +10 -0
  159. data/app/views/lcp_ruby/resources/_kanban_index.html.erb +17 -0
  160. data/app/views/lcp_ruby/resources/_nested_field_cell.html.erb +33 -0
  161. data/app/views/lcp_ruby/resources/_nested_fields.html.erb +26 -0
  162. data/app/views/lcp_ruby/resources/_nested_row_content.html.erb +65 -0
  163. data/app/views/lcp_ruby/resources/_scope_filters.html.erb +71 -0
  164. data/app/views/lcp_ruby/resources/_semantic_index_page.html.erb +162 -0
  165. data/app/views/lcp_ruby/resources/_semantic_page.html.erb +121 -0
  166. data/app/views/lcp_ruby/resources/_show_sections.html.erb +128 -0
  167. data/app/views/lcp_ruby/resources/_table_index.html.erb +169 -0
  168. data/app/views/lcp_ruby/resources/_tile_card.html.erb +26 -0
  169. data/app/views/lcp_ruby/resources/_tile_card_body.html.erb +19 -0
  170. data/app/views/lcp_ruby/resources/_tiles_index.html.erb +15 -0
  171. data/app/views/lcp_ruby/resources/_transition_button.html.erb +33 -0
  172. data/app/views/lcp_ruby/resources/_tree_index.html.erb +61 -0
  173. data/app/views/lcp_ruby/resources/_view_switcher.html.erb +24 -0
  174. data/app/views/lcp_ruby/resources/edit.html.erb +9 -0
  175. data/app/views/lcp_ruby/resources/index.html.erb +80 -0
  176. data/app/views/lcp_ruby/resources/new.html.erb +9 -0
  177. data/app/views/lcp_ruby/resources/show.html.erb +37 -0
  178. data/app/views/lcp_ruby/shared/_breadcrumbs.html.erb +15 -0
  179. data/app/views/lcp_ruby/shared/_custom_partial_error.html.erb +3 -0
  180. data/app/views/lcp_ruby/shared/_flash_messages.html.erb +19 -0
  181. data/app/views/lcp_ruby/slots/index/_advanced_filter.html.erb +3 -0
  182. data/app/views/lcp_ruby/slots/index/_collection_actions.html.erb +50 -0
  183. data/app/views/lcp_ruby/slots/index/_manage_all.html.erb +4 -0
  184. data/app/views/lcp_ruby/slots/index/_pagination_footer.html.erb +71 -0
  185. data/app/views/lcp_ruby/slots/index/_predefined_filters.html.erb +8 -0
  186. data/app/views/lcp_ruby/slots/index/_saved_filters.html.erb +87 -0
  187. data/app/views/lcp_ruby/slots/index/_search.html.erb +52 -0
  188. data/app/views/lcp_ruby/slots/index/_search_parameter.html.erb +72 -0
  189. data/app/views/lcp_ruby/slots/index/_sort_dropdown.html.erb +21 -0
  190. data/app/views/lcp_ruby/slots/index/_summary_bar.html.erb +22 -0
  191. data/app/views/lcp_ruby/slots/index/_view_switcher.html.erb +1 -0
  192. data/app/views/lcp_ruby/slots/show/_approval_status.html.erb +8 -0
  193. data/app/views/lcp_ruby/slots/show/_back_to_list.html.erb +1 -0
  194. data/app/views/lcp_ruby/slots/show/_copy_url.html.erb +5 -0
  195. data/app/views/lcp_ruby/slots/show/_single_actions.html.erb +4 -0
  196. data/app/views/lcp_ruby/slots/show/_view_switcher.html.erb +1 -0
  197. data/app/views/lcp_ruby/widgets/_approval_status.html.erb +150 -0
  198. data/app/views/lcp_ruby/widgets/_chart.html.erb +36 -0
  199. data/app/views/lcp_ruby/widgets/_embed.html.erb +13 -0
  200. data/app/views/lcp_ruby/widgets/_kpi_card.html.erb +29 -0
  201. data/app/views/lcp_ruby/widgets/_list.html.erb +17 -0
  202. data/app/views/lcp_ruby/widgets/_presenter_zone.html.erb +84 -0
  203. data/app/views/lcp_ruby/widgets/_record_show_zone.html.erb +11 -0
  204. data/app/views/lcp_ruby/widgets/_text.html.erb +3 -0
  205. data/app/views/lcp_ruby/widgets/_workflow_graph.html.erb +32 -0
  206. data/app/views/lcp_ruby/zones/_custom_zone.html.erb +16 -0
  207. data/app/views/lcp_ruby/zones/_error.html.erb +5 -0
  208. data/app/views/lcp_ruby/zones/_zone_frame.html.erb +25 -0
  209. data/app/views/lcp_ruby/zones/_zone_search.html.erb +20 -0
  210. data/config/locales/cs.yml +859 -0
  211. data/config/locales/en.yml +731 -0
  212. data/config/routes.rb +119 -0
  213. data/docs/README.md +225 -0
  214. data/docs/architecture.md +212 -0
  215. data/docs/feature-catalog.md +763 -0
  216. data/docs/feature-catalog.yml +20911 -0
  217. data/docs/getting-started.md +1187 -0
  218. data/docs/guides/action-buttons.md +537 -0
  219. data/docs/guides/adding-locale.md +353 -0
  220. data/docs/guides/api-backed-models.md +478 -0
  221. data/docs/guides/attachments.md +399 -0
  222. data/docs/guides/auditing.md +333 -0
  223. data/docs/guides/batch-actions.md +342 -0
  224. data/docs/guides/composite-pages.md +1290 -0
  225. data/docs/guides/computed-fields.md +350 -0
  226. data/docs/guides/conditional-rendering.md +832 -0
  227. data/docs/guides/custom-actions.md +238 -0
  228. data/docs/guides/custom-fields.md +439 -0
  229. data/docs/guides/custom-renderers.md +234 -0
  230. data/docs/guides/custom-types.md +274 -0
  231. data/docs/guides/dashboards.md +504 -0
  232. data/docs/guides/debugging/README.md +38 -0
  233. data/docs/guides/debugging/controllers.md +147 -0
  234. data/docs/guides/debugging/data.md +165 -0
  235. data/docs/guides/debugging/metadata.md +143 -0
  236. data/docs/guides/debugging/models.md +126 -0
  237. data/docs/guides/debugging/permissions.md +147 -0
  238. data/docs/guides/debugging/presenters.md +151 -0
  239. data/docs/guides/developer-tools.md +418 -0
  240. data/docs/guides/dialogs.md +392 -0
  241. data/docs/guides/display-types.md +1430 -0
  242. data/docs/guides/eager-loading.md +230 -0
  243. data/docs/guides/event-handlers.md +135 -0
  244. data/docs/guides/export.md +305 -0
  245. data/docs/guides/extensibility.md +761 -0
  246. data/docs/guides/groups.md +220 -0
  247. data/docs/guides/hierarchical-authorization.md +427 -0
  248. data/docs/guides/host-application.md +556 -0
  249. data/docs/guides/host-controller-integration.md +473 -0
  250. data/docs/guides/impersonation.md +83 -0
  251. data/docs/guides/import.md +165 -0
  252. data/docs/guides/inherited-permissions.md +459 -0
  253. data/docs/guides/menu.md +373 -0
  254. data/docs/guides/monitoring.md +254 -0
  255. data/docs/guides/oidc-setup.md +399 -0
  256. data/docs/guides/permission-source.md +205 -0
  257. data/docs/guides/permissions.md +364 -0
  258. data/docs/guides/presenters.md +2324 -0
  259. data/docs/guides/record-aliases.md +303 -0
  260. data/docs/guides/rendering-extension-points.md +280 -0
  261. data/docs/guides/role-source.md +288 -0
  262. data/docs/guides/selectbox.md +516 -0
  263. data/docs/guides/sequences.md +291 -0
  264. data/docs/guides/soft-delete.md +460 -0
  265. data/docs/guides/theming.md +129 -0
  266. data/docs/guides/tiles.md +383 -0
  267. data/docs/guides/tree-structures.md +297 -0
  268. data/docs/guides/userstamps.md +288 -0
  269. data/docs/guides/view-groups.md +259 -0
  270. data/docs/guides/view-slots.md +352 -0
  271. data/docs/guides/virtual-columns.md +810 -0
  272. data/docs/guides/workflow.md +692 -0
  273. data/docs/reference/api-backed-models.md +404 -0
  274. data/docs/reference/api-tokens.md +128 -0
  275. data/docs/reference/auditing.md +277 -0
  276. data/docs/reference/boot_lifecycle.md +188 -0
  277. data/docs/reference/cascading_selects.md +189 -0
  278. data/docs/reference/condition-operators.md +445 -0
  279. data/docs/reference/custom-fields.md +483 -0
  280. data/docs/reference/dialogs.md +286 -0
  281. data/docs/reference/doctor.md +168 -0
  282. data/docs/reference/dynamic-references.md +95 -0
  283. data/docs/reference/eager-loading.md +192 -0
  284. data/docs/reference/engine-configuration.md +989 -0
  285. data/docs/reference/export.md +309 -0
  286. data/docs/reference/forms.md +68 -0
  287. data/docs/reference/groups.md +176 -0
  288. data/docs/reference/host-controller-integration.md +342 -0
  289. data/docs/reference/i18n.md +497 -0
  290. data/docs/reference/i18n_check.md +351 -0
  291. data/docs/reference/import.md +260 -0
  292. data/docs/reference/invariant_check.md +216 -0
  293. data/docs/reference/menu.md +985 -0
  294. data/docs/reference/model-dsl.md +1157 -0
  295. data/docs/reference/models.md +2972 -0
  296. data/docs/reference/monitoring.md +222 -0
  297. data/docs/reference/oidc-bearer.md +269 -0
  298. data/docs/reference/oidc.md +407 -0
  299. data/docs/reference/page_filters.md +328 -0
  300. data/docs/reference/pages.md +1375 -0
  301. data/docs/reference/permission-source.md +185 -0
  302. data/docs/reference/permissions.md +715 -0
  303. data/docs/reference/presenter-dsl.md +1719 -0
  304. data/docs/reference/presenters.md +3627 -0
  305. data/docs/reference/role-source.md +227 -0
  306. data/docs/reference/theme-variables.md +139 -0
  307. data/docs/reference/tree-structures.md +374 -0
  308. data/docs/reference/types.md +470 -0
  309. data/docs/reference/view-groups.md +347 -0
  310. data/docs/reference/view-slots.md +228 -0
  311. data/docs/reference/virtual_forms.md +196 -0
  312. data/docs/reference/workflow-approvals.md +387 -0
  313. data/docs/reference/workflow.md +651 -0
  314. data/examples/crm/Gemfile +9 -0
  315. data/examples/crm/Gemfile.lock +417 -0
  316. data/examples/crm/Rakefile +2 -0
  317. data/examples/crm/app/actions/activity/complete.rb +20 -0
  318. data/examples/crm/app/actions/deal/close_won.rb +20 -0
  319. data/examples/crm/app/assets/config/manifest.js +3 -0
  320. data/examples/crm/app/controllers/application_controller.rb +9 -0
  321. data/examples/crm/app/event_handlers/deal/on_stage_change.rb +17 -0
  322. data/examples/crm/app/lcp_services/computed/weighted_deal_value.rb +13 -0
  323. data/examples/crm/app/lcp_services/data_providers/active_contacts_count.rb +14 -0
  324. data/examples/crm/app/lcp_services/data_providers/open_deals_count.rb +14 -0
  325. data/examples/crm/app/lcp_services/data_providers/pending_activities_count.rb +15 -0
  326. data/examples/crm/app/lcp_services/data_providers/pipeline_value.rb +27 -0
  327. data/examples/crm/app/lcp_services/data_providers/won_deals_count.rb +14 -0
  328. data/examples/crm/app/lcp_services/defaults/thirty_days_out.rb +11 -0
  329. data/examples/crm/app/lcp_services/transforms/titlecase.rb +11 -0
  330. data/examples/crm/app/lcp_services/validators/deal_credit_limit.rb +19 -0
  331. data/examples/crm/app/lcp_services/validators/deal_documents_required.rb +17 -0
  332. data/examples/crm/app/renderers/conditional_badge.rb +39 -0
  333. data/examples/crm/bin/rails +4 -0
  334. data/examples/crm/bin/rake +4 -0
  335. data/examples/crm/config/application.rb +31 -0
  336. data/examples/crm/config/boot.rb +2 -0
  337. data/examples/crm/config/database.yml +12 -0
  338. data/examples/crm/config/environment.rb +2 -0
  339. data/examples/crm/config/initializers/lcp_ruby.rb +45 -0
  340. data/examples/crm/config/lcp_ruby/menu.yml +53 -0
  341. data/examples/crm/config/lcp_ruby/models/activity.rb +43 -0
  342. data/examples/crm/config/lcp_ruby/models/city.rb +19 -0
  343. data/examples/crm/config/lcp_ruby/models/company.rb +65 -0
  344. data/examples/crm/config/lcp_ruby/models/contact.rb +62 -0
  345. data/examples/crm/config/lcp_ruby/models/country.rb +22 -0
  346. data/examples/crm/config/lcp_ruby/models/custom_field_definition.rb +60 -0
  347. data/examples/crm/config/lcp_ruby/models/deal.rb +85 -0
  348. data/examples/crm/config/lcp_ruby/models/deal_category.rb +15 -0
  349. data/examples/crm/config/lcp_ruby/models/gapfree_sequence.rb +17 -0
  350. data/examples/crm/config/lcp_ruby/models/region.rb +15 -0
  351. data/examples/crm/config/lcp_ruby/models/saved_filter.rb +50 -0
  352. data/examples/crm/config/lcp_ruby/pages/activity_quick_log.yml +19 -0
  353. data/examples/crm/config/lcp_ruby/pages/company_detail.yml +127 -0
  354. data/examples/crm/config/lcp_ruby/pages/deals_overview.yml +65 -0
  355. data/examples/crm/config/lcp_ruby/permissions/activity.yml +40 -0
  356. data/examples/crm/config/lcp_ruby/permissions/custom_field_definition.yml +16 -0
  357. data/examples/crm/config/lcp_ruby/permissions/deal.yml +54 -0
  358. data/examples/crm/config/lcp_ruby/permissions/default.yml +16 -0
  359. data/examples/crm/config/lcp_ruby/permissions/gapfree_sequence.yml +6 -0
  360. data/examples/crm/config/lcp_ruby/permissions/saved_filter.yml +27 -0
  361. data/examples/crm/config/lcp_ruby/presenters/activity.rb +140 -0
  362. data/examples/crm/config/lcp_ruby/presenters/activity_quick_form.rb +36 -0
  363. data/examples/crm/config/lcp_ruby/presenters/activity_short.rb +16 -0
  364. data/examples/crm/config/lcp_ruby/presenters/activity_tiles.rb +35 -0
  365. data/examples/crm/config/lcp_ruby/presenters/city.rb +53 -0
  366. data/examples/crm/config/lcp_ruby/presenters/company.rb +147 -0
  367. data/examples/crm/config/lcp_ruby/presenters/company_activities_zone.rb +26 -0
  368. data/examples/crm/config/lcp_ruby/presenters/company_archive.rb +37 -0
  369. data/examples/crm/config/lcp_ruby/presenters/company_contacts_zone.rb +22 -0
  370. data/examples/crm/config/lcp_ruby/presenters/company_deals_zone.rb +36 -0
  371. data/examples/crm/config/lcp_ruby/presenters/company_short.rb +21 -0
  372. data/examples/crm/config/lcp_ruby/presenters/company_show_zone.rb +38 -0
  373. data/examples/crm/config/lcp_ruby/presenters/company_sidebar.rb +15 -0
  374. data/examples/crm/config/lcp_ruby/presenters/company_tiles.rb +35 -0
  375. data/examples/crm/config/lcp_ruby/presenters/contact.rb +120 -0
  376. data/examples/crm/config/lcp_ruby/presenters/contact_quick_form.rb +17 -0
  377. data/examples/crm/config/lcp_ruby/presenters/contact_short.rb +20 -0
  378. data/examples/crm/config/lcp_ruby/presenters/contact_tiles.rb +34 -0
  379. data/examples/crm/config/lcp_ruby/presenters/country.rb +44 -0
  380. data/examples/crm/config/lcp_ruby/presenters/custom_fields.rb +124 -0
  381. data/examples/crm/config/lcp_ruby/presenters/deal.rb +181 -0
  382. data/examples/crm/config/lcp_ruby/presenters/deal_category.rb +46 -0
  383. data/examples/crm/config/lcp_ruby/presenters/deal_overview.rb +6 -0
  384. data/examples/crm/config/lcp_ruby/presenters/deal_pipeline.rb +18 -0
  385. data/examples/crm/config/lcp_ruby/presenters/deal_short.rb +25 -0
  386. data/examples/crm/config/lcp_ruby/presenters/deal_tiles.rb +48 -0
  387. data/examples/crm/config/lcp_ruby/presenters/region.rb +42 -0
  388. data/examples/crm/config/lcp_ruby/presenters/save_filter_dialog.rb +17 -0
  389. data/examples/crm/config/lcp_ruby/presenters/saved_filters.rb +93 -0
  390. data/examples/crm/config/lcp_ruby/views/activities.yml +16 -0
  391. data/examples/crm/config/lcp_ruby/views/cities.yml +10 -0
  392. data/examples/crm/config/lcp_ruby/views/companies.yml +14 -0
  393. data/examples/crm/config/lcp_ruby/views/contacts.yml +16 -0
  394. data/examples/crm/config/lcp_ruby/views/countries.yml +8 -0
  395. data/examples/crm/config/lcp_ruby/views/custom_fields.rb +9 -0
  396. data/examples/crm/config/lcp_ruby/views/deal_categories.yml +8 -0
  397. data/examples/crm/config/lcp_ruby/views/deals.yml +19 -0
  398. data/examples/crm/config/lcp_ruby/views/pipeline.yml +10 -0
  399. data/examples/crm/config/lcp_ruby/views/regions.yml +10 -0
  400. data/examples/crm/config/lcp_ruby/views/saved_filters.yml +7 -0
  401. data/examples/crm/config/locales/cs.yml +338 -0
  402. data/examples/crm/config/locales/en.yml +353 -0
  403. data/examples/crm/config/routes.rb +4 -0
  404. data/examples/crm/config/storage.yml +3 -0
  405. data/examples/crm/config.ru +2 -0
  406. data/examples/crm/db/migrate/20260219104942_create_active_storage_tables.active_storage.rb +57 -0
  407. data/examples/crm/db/schema.rb +245 -0
  408. data/examples/crm/db/seeds.rb +1111 -0
  409. data/examples/crm/erd.md +163 -0
  410. data/examples/hr/Gemfile +9 -0
  411. data/examples/hr/Gemfile.lock +419 -0
  412. data/examples/hr/Rakefile +6 -0
  413. data/examples/hr/app/actions/asset/assign_asset.rb +20 -0
  414. data/examples/hr/app/actions/asset/return_asset.rb +20 -0
  415. data/examples/hr/app/actions/candidate/advance.rb +32 -0
  416. data/examples/hr/app/actions/candidate/hire.rb +20 -0
  417. data/examples/hr/app/actions/candidate/reject_candidate.rb +20 -0
  418. data/examples/hr/app/actions/expense_claim/approve.rb +21 -0
  419. data/examples/hr/app/actions/expense_claim/reject.rb +21 -0
  420. data/examples/hr/app/actions/expense_claim/submit.rb +20 -0
  421. data/examples/hr/app/actions/interview/complete_interview.rb +20 -0
  422. data/examples/hr/app/actions/leave_request/approve.rb +21 -0
  423. data/examples/hr/app/actions/leave_request/cancel.rb +20 -0
  424. data/examples/hr/app/actions/leave_request/reject.rb +21 -0
  425. data/examples/hr/app/assets/config/manifest.js +1 -0
  426. data/examples/hr/app/assets/stylesheets/application.css +10 -0
  427. data/examples/hr/app/condition_services/is_own_org_unit.rb +14 -0
  428. data/examples/hr/app/condition_services/is_own_record.rb +20 -0
  429. data/examples/hr/app/controllers/application_controller.rb +15 -0
  430. data/examples/hr/app/event_handlers/asset_assignment/on_create.rb +24 -0
  431. data/examples/hr/app/event_handlers/candidate/on_status_change.rb +18 -0
  432. data/examples/hr/app/event_handlers/leave_request/on_status_change.rb +45 -0
  433. data/examples/hr/app/helpers/application_helper.rb +2 -0
  434. data/examples/hr/app/javascript/application.js +1 -0
  435. data/examples/hr/app/jobs/application_job.rb +7 -0
  436. data/examples/hr/app/lcp_services/computed/employee_tenure.rb +28 -0
  437. data/examples/hr/app/lcp_services/computed/leave_remaining.rb +13 -0
  438. data/examples/hr/app/lcp_services/data_providers/headcount_text.rb +14 -0
  439. data/examples/hr/app/lcp_services/data_providers/open_positions_count.rb +14 -0
  440. data/examples/hr/app/lcp_services/data_providers/pending_expenses_count.rb +14 -0
  441. data/examples/hr/app/lcp_services/data_providers/pending_leaves_count.rb +14 -0
  442. data/examples/hr/app/lcp_services/defaults/current_year.rb +11 -0
  443. data/examples/hr/app/lcp_services/transforms/titlecase.rb +11 -0
  444. data/examples/hr/app/lcp_services/validators/expense_receipt_required.rb +17 -0
  445. data/examples/hr/app/lcp_services/validators/leave_balance_check.rb +37 -0
  446. data/examples/hr/app/models/application_record.rb +3 -0
  447. data/examples/hr/app/views/layouts/application.html.erb +29 -0
  448. data/examples/hr/app/views/pwa/manifest.json.erb +22 -0
  449. data/examples/hr/app/views/pwa/service-worker.js +26 -0
  450. data/examples/hr/bin/brakeman +7 -0
  451. data/examples/hr/bin/bundler-audit +6 -0
  452. data/examples/hr/bin/ci +6 -0
  453. data/examples/hr/bin/dev +2 -0
  454. data/examples/hr/bin/docker-entrypoint +8 -0
  455. data/examples/hr/bin/importmap +4 -0
  456. data/examples/hr/bin/jobs +6 -0
  457. data/examples/hr/bin/kamal +27 -0
  458. data/examples/hr/bin/rails +4 -0
  459. data/examples/hr/bin/rake +4 -0
  460. data/examples/hr/bin/rubocop +8 -0
  461. data/examples/hr/bin/setup +35 -0
  462. data/examples/hr/bin/thrust +5 -0
  463. data/examples/hr/config/application.rb +31 -0
  464. data/examples/hr/config/boot.rb +2 -0
  465. data/examples/hr/config/bundler-audit.yml +5 -0
  466. data/examples/hr/config/cache.yml +16 -0
  467. data/examples/hr/config/ci.rb +20 -0
  468. data/examples/hr/config/credentials.yml.enc +1 -0
  469. data/examples/hr/config/database.yml +36 -0
  470. data/examples/hr/config/deploy.yml +119 -0
  471. data/examples/hr/config/environment.rb +5 -0
  472. data/examples/hr/config/environments/development.rb +66 -0
  473. data/examples/hr/config/environments/production.rb +74 -0
  474. data/examples/hr/config/environments/test.rb +45 -0
  475. data/examples/hr/config/importmap.rb +3 -0
  476. data/examples/hr/config/initializers/assets.rb +7 -0
  477. data/examples/hr/config/initializers/content_security_policy.rb +29 -0
  478. data/examples/hr/config/initializers/filter_parameter_logging.rb +8 -0
  479. data/examples/hr/config/initializers/inflections.rb +16 -0
  480. data/examples/hr/config/initializers/lcp_ruby.rb +18 -0
  481. data/examples/hr/config/lcp_ruby/menu.yml +86 -0
  482. data/examples/hr/config/lcp_ruby/models/announcement.rb +33 -0
  483. data/examples/hr/config/lcp_ruby/models/asset.rb +73 -0
  484. data/examples/hr/config/lcp_ruby/models/asset_assignment.rb +39 -0
  485. data/examples/hr/config/lcp_ruby/models/audit_log.yml +57 -0
  486. data/examples/hr/config/lcp_ruby/models/candidate.rb +68 -0
  487. data/examples/hr/config/lcp_ruby/models/custom_field_definition.rb +60 -0
  488. data/examples/hr/config/lcp_ruby/models/dashboard.rb +17 -0
  489. data/examples/hr/config/lcp_ruby/models/document.rb +38 -0
  490. data/examples/hr/config/lcp_ruby/models/employee.rb +128 -0
  491. data/examples/hr/config/lcp_ruby/models/employee_skill.rb +29 -0
  492. data/examples/hr/config/lcp_ruby/models/expense_claim.rb +70 -0
  493. data/examples/hr/config/lcp_ruby/models/goal.rb +48 -0
  494. data/examples/hr/config/lcp_ruby/models/group.rb +37 -0
  495. data/examples/hr/config/lcp_ruby/models/group_membership.rb +26 -0
  496. data/examples/hr/config/lcp_ruby/models/interview.rb +54 -0
  497. data/examples/hr/config/lcp_ruby/models/job_posting.rb +67 -0
  498. data/examples/hr/config/lcp_ruby/models/leave_balance.rb +31 -0
  499. data/examples/hr/config/lcp_ruby/models/leave_request.rb +52 -0
  500. data/examples/hr/config/lcp_ruby/models/leave_type.rb +35 -0
  501. data/examples/hr/config/lcp_ruby/models/organization_unit.rb +42 -0
  502. data/examples/hr/config/lcp_ruby/models/performance_review.rb +59 -0
  503. data/examples/hr/config/lcp_ruby/models/position.rb +43 -0
  504. data/examples/hr/config/lcp_ruby/models/skill.rb +27 -0
  505. data/examples/hr/config/lcp_ruby/models/training_course.rb +53 -0
  506. data/examples/hr/config/lcp_ruby/models/training_enrollment.rb +35 -0
  507. data/examples/hr/config/lcp_ruby/pages/dashboard.yml +101 -0
  508. data/examples/hr/config/lcp_ruby/permissions/announcement.yml +25 -0
  509. data/examples/hr/config/lcp_ruby/permissions/asset.yml +35 -0
  510. data/examples/hr/config/lcp_ruby/permissions/audit_log.yml +28 -0
  511. data/examples/hr/config/lcp_ruby/permissions/candidate.yml +25 -0
  512. data/examples/hr/config/lcp_ruby/permissions/custom_field_definition.yml +28 -0
  513. data/examples/hr/config/lcp_ruby/permissions/dashboard.yml +25 -0
  514. data/examples/hr/config/lcp_ruby/permissions/default.yml +25 -0
  515. data/examples/hr/config/lcp_ruby/permissions/document.yml +37 -0
  516. data/examples/hr/config/lcp_ruby/permissions/employee.yml +55 -0
  517. data/examples/hr/config/lcp_ruby/permissions/expense_claim.yml +45 -0
  518. data/examples/hr/config/lcp_ruby/permissions/group.yml +27 -0
  519. data/examples/hr/config/lcp_ruby/permissions/job_posting.yml +34 -0
  520. data/examples/hr/config/lcp_ruby/permissions/leave_request.yml +45 -0
  521. data/examples/hr/config/lcp_ruby/permissions/performance_review.yml +42 -0
  522. data/examples/hr/config/lcp_ruby/presenters/announcement.rb +47 -0
  523. data/examples/hr/config/lcp_ruby/presenters/asset.rb +69 -0
  524. data/examples/hr/config/lcp_ruby/presenters/asset_assignment.rb +47 -0
  525. data/examples/hr/config/lcp_ruby/presenters/audit_logs.yml +43 -0
  526. data/examples/hr/config/lcp_ruby/presenters/candidate.rb +71 -0
  527. data/examples/hr/config/lcp_ruby/presenters/custom_fields.rb +124 -0
  528. data/examples/hr/config/lcp_ruby/presenters/dashboard.rb +37 -0
  529. data/examples/hr/config/lcp_ruby/presenters/document.rb +46 -0
  530. data/examples/hr/config/lcp_ruby/presenters/employee.rb +167 -0
  531. data/examples/hr/config/lcp_ruby/presenters/employee_archive.rb +38 -0
  532. data/examples/hr/config/lcp_ruby/presenters/employee_directory.rb +27 -0
  533. data/examples/hr/config/lcp_ruby/presenters/employee_skill.rb +57 -0
  534. data/examples/hr/config/lcp_ruby/presenters/expense_claim.rb +76 -0
  535. data/examples/hr/config/lcp_ruby/presenters/goal.rb +60 -0
  536. data/examples/hr/config/lcp_ruby/presenters/group.rb +48 -0
  537. data/examples/hr/config/lcp_ruby/presenters/interview.rb +59 -0
  538. data/examples/hr/config/lcp_ruby/presenters/job_posting.rb +73 -0
  539. data/examples/hr/config/lcp_ruby/presenters/leave_balance.rb +50 -0
  540. data/examples/hr/config/lcp_ruby/presenters/leave_request.rb +89 -0
  541. data/examples/hr/config/lcp_ruby/presenters/leave_type.rb +52 -0
  542. data/examples/hr/config/lcp_ruby/presenters/organization_unit.rb +56 -0
  543. data/examples/hr/config/lcp_ruby/presenters/performance_review.rb +87 -0
  544. data/examples/hr/config/lcp_ruby/presenters/position.rb +54 -0
  545. data/examples/hr/config/lcp_ruby/presenters/skill.rb +45 -0
  546. data/examples/hr/config/lcp_ruby/presenters/training_course.rb +61 -0
  547. data/examples/hr/config/lcp_ruby/presenters/training_enrollment.rb +49 -0
  548. data/examples/hr/config/lcp_ruby/views/announcements.yml +8 -0
  549. data/examples/hr/config/lcp_ruby/views/asset_assignments.yml +10 -0
  550. data/examples/hr/config/lcp_ruby/views/assets.yml +8 -0
  551. data/examples/hr/config/lcp_ruby/views/audit_logs.yml +8 -0
  552. data/examples/hr/config/lcp_ruby/views/candidates.yml +8 -0
  553. data/examples/hr/config/lcp_ruby/views/custom_fields.yml +8 -0
  554. data/examples/hr/config/lcp_ruby/views/dashboard.yml +6 -0
  555. data/examples/hr/config/lcp_ruby/views/documents.yml +10 -0
  556. data/examples/hr/config/lcp_ruby/views/employee_skills.yml +10 -0
  557. data/examples/hr/config/lcp_ruby/views/employees.yml +14 -0
  558. data/examples/hr/config/lcp_ruby/views/expense_claims.yml +10 -0
  559. data/examples/hr/config/lcp_ruby/views/goals.yml +10 -0
  560. data/examples/hr/config/lcp_ruby/views/groups.yml +8 -0
  561. data/examples/hr/config/lcp_ruby/views/interviews.yml +8 -0
  562. data/examples/hr/config/lcp_ruby/views/job_postings.yml +6 -0
  563. data/examples/hr/config/lcp_ruby/views/leave_balances.yml +10 -0
  564. data/examples/hr/config/lcp_ruby/views/leave_requests.yml +10 -0
  565. data/examples/hr/config/lcp_ruby/views/leave_types.yml +8 -0
  566. data/examples/hr/config/lcp_ruby/views/organization_units.yml +8 -0
  567. data/examples/hr/config/lcp_ruby/views/performance_reviews.yml +10 -0
  568. data/examples/hr/config/lcp_ruby/views/positions.yml +8 -0
  569. data/examples/hr/config/lcp_ruby/views/skills.yml +8 -0
  570. data/examples/hr/config/lcp_ruby/views/training_courses.yml +8 -0
  571. data/examples/hr/config/lcp_ruby/views/training_enrollments.yml +10 -0
  572. data/examples/hr/config/locales/cs.yml +496 -0
  573. data/examples/hr/config/locales/en.yml +740 -0
  574. data/examples/hr/config/locales/sk.yml +496 -0
  575. data/examples/hr/config/puma.rb +42 -0
  576. data/examples/hr/config/queue.yml +18 -0
  577. data/examples/hr/config/recurring.yml +15 -0
  578. data/examples/hr/config/routes.rb +4 -0
  579. data/examples/hr/config/storage.yml +27 -0
  580. data/examples/hr/config.ru +6 -0
  581. data/examples/hr/db/cache_schema.rb +12 -0
  582. data/examples/hr/db/migrate/20260303202825_create_active_storage_tables.active_storage.rb +57 -0
  583. data/examples/hr/db/queue_schema.rb +129 -0
  584. data/examples/hr/db/schema.rb +588 -0
  585. data/examples/hr/db/seeds.rb +932 -0
  586. data/examples/hr/erd.md +396 -0
  587. data/examples/hr/public/400.html +135 -0
  588. data/examples/hr/public/404.html +135 -0
  589. data/examples/hr/public/406-unsupported-browser.html +135 -0
  590. data/examples/hr/public/422.html +135 -0
  591. data/examples/hr/public/500.html +135 -0
  592. data/examples/hr/public/icon.svg +3 -0
  593. data/examples/hr/public/robots.txt +1 -0
  594. data/examples/showcase/Gemfile +15 -0
  595. data/examples/showcase/Gemfile.lock +425 -0
  596. data/examples/showcase/Rakefile +2 -0
  597. data/examples/showcase/app/actions/showcase_batch_task/assign_batch.rb +20 -0
  598. data/examples/showcase/app/actions/showcase_batch_task/close_task.rb +21 -0
  599. data/examples/showcase/app/actions/showcase_condition/approve.rb +20 -0
  600. data/examples/showcase/app/actions/showcase_permission/lock.rb +20 -0
  601. data/examples/showcase/app/assets/config/manifest.js +3 -0
  602. data/examples/showcase/app/assets/stylesheets/application.css +27 -0
  603. data/examples/showcase/app/condition_services/budget_threshold.rb +16 -0
  604. data/examples/showcase/app/condition_services/overdue_check.rb +11 -0
  605. data/examples/showcase/app/controllers/application_controller.rb +2 -0
  606. data/examples/showcase/app/controllers/docs_controller.rb +48 -0
  607. data/examples/showcase/app/controllers/host_inventory_items_managed_controller.rb +90 -0
  608. data/examples/showcase/app/controllers/host_inventory_items_report_controller.rb +39 -0
  609. data/examples/showcase/app/controllers/host_inventory_items_wizard_controller.rb +50 -0
  610. data/examples/showcase/app/data_providers/showcase_amount_provider.rb +52 -0
  611. data/examples/showcase/app/data_providers/weather_station_provider.rb +140 -0
  612. data/examples/showcase/app/event_handlers/showcase_model/on_status_change.rb +17 -0
  613. data/examples/showcase/app/event_handlers/showcase_permission/on_status_change.rb +17 -0
  614. data/examples/showcase/app/event_handlers/showcase_workflow/log_review_exit.rb +16 -0
  615. data/examples/showcase/app/event_handlers/showcase_workflow/notify_reviewers.rb +15 -0
  616. data/examples/showcase/app/event_handlers/showcase_workflow/request_submitted.rb +15 -0
  617. data/examples/showcase/app/lcp_metrics/showcase_metrics.rb +31 -0
  618. data/examples/showcase/app/lcp_services/computed/showcase_score.rb +18 -0
  619. data/examples/showcase/app/lcp_services/computed/showcase_total.rb +13 -0
  620. data/examples/showcase/app/lcp_services/defaults/one_week_from_now.rb +11 -0
  621. data/examples/showcase/app/lcp_services/menu_items/recent_announcements.rb +36 -0
  622. data/examples/showcase/app/lcp_services/virtual_columns/project_health.rb +26 -0
  623. data/examples/showcase/app/model_extensions/lcp_error_log_extension.rb +12 -0
  624. data/examples/showcase/app/models/host_inventory_item.rb +20 -0
  625. data/examples/showcase/app/models/platform_profile.rb +27 -0
  626. data/examples/showcase/app/models/platform_user.rb +5 -0
  627. data/examples/showcase/app/views/docs/show.html.erb +19 -0
  628. data/examples/showcase/app/views/host_inventory_items_report/index.html.erb +61 -0
  629. data/examples/showcase/app/views/host_inventory_items_report/show.html.erb +39 -0
  630. data/examples/showcase/app/views/layouts/docs.html.erb +46 -0
  631. data/examples/showcase/app/views/showcase/menu_renderers/_status_pill.html.erb +17 -0
  632. data/examples/showcase/app/views/showcase_custom/_activity_timeline.html.erb +37 -0
  633. data/examples/showcase/app/views/showcase_custom/_card_index.html.erb +74 -0
  634. data/examples/showcase/app/views/showcase_custom/_detail_show.html.erb +115 -0
  635. data/examples/showcase/app/views/showcase_custom/_location_map.html.erb +29 -0
  636. data/examples/showcase/app/views/showcase_custom/_location_view.html.erb +34 -0
  637. data/examples/showcase/app/views/showcase_custom/_quick_stats.html.erb +50 -0
  638. data/examples/showcase/app/views/showcase_custom/_stats_sidebar.html.erb +42 -0
  639. data/examples/showcase/app/views/showcase_custom/_tags_editor.html.erb +48 -0
  640. data/examples/showcase/bin/rails +4 -0
  641. data/examples/showcase/bin/rake +4 -0
  642. data/examples/showcase/config/application.rb +37 -0
  643. data/examples/showcase/config/boot.rb +2 -0
  644. data/examples/showcase/config/database.yml +12 -0
  645. data/examples/showcase/config/environment.rb +2 -0
  646. data/examples/showcase/config/initializers/devise.rb +5 -0
  647. data/examples/showcase/config/initializers/lcp_ruby.rb +175 -0
  648. data/examples/showcase/config/lcp_ruby/auth.yml +60 -0
  649. data/examples/showcase/config/lcp_ruby/jobs/data_import.yml +7 -0
  650. data/examples/showcase/config/lcp_ruby/jobs/showcase_cleanup.yml +11 -0
  651. data/examples/showcase/config/lcp_ruby/jobs/showcase_event_triggered.yml +11 -0
  652. data/examples/showcase/config/lcp_ruby/jobs/showcase_multi_step.yml +9 -0
  653. data/examples/showcase/config/lcp_ruby/jobs/showcase_webhook.yml +13 -0
  654. data/examples/showcase/config/lcp_ruby/menu.yml +249 -0
  655. data/examples/showcase/config/lcp_ruby/models/_base_document.rb +26 -0
  656. data/examples/showcase/config/lcp_ruby/models/_categorized_document.rb +19 -0
  657. data/examples/showcase/config/lcp_ruby/models/_contactable.rb +20 -0
  658. data/examples/showcase/config/lcp_ruby/models/api_token.rb +23 -0
  659. data/examples/showcase/config/lcp_ruby/models/article.rb +49 -0
  660. data/examples/showcase/config/lcp_ruby/models/article_tag.rb +10 -0
  661. data/examples/showcase/config/lcp_ruby/models/author.rb +16 -0
  662. data/examples/showcase/config/lcp_ruby/models/batch_operation.yml +79 -0
  663. data/examples/showcase/config/lcp_ruby/models/batch_operation_item.yml +45 -0
  664. data/examples/showcase/config/lcp_ruby/models/category.rb +23 -0
  665. data/examples/showcase/config/lcp_ruby/models/comment.rb +21 -0
  666. data/examples/showcase/config/lcp_ruby/models/custom_field_definition.rb +59 -0
  667. data/examples/showcase/config/lcp_ruby/models/department.rb +32 -0
  668. data/examples/showcase/config/lcp_ruby/models/employee.rb +52 -0
  669. data/examples/showcase/config/lcp_ruby/models/employee_emergency_contact.rb +24 -0
  670. data/examples/showcase/config/lcp_ruby/models/employee_profile.rb +18 -0
  671. data/examples/showcase/config/lcp_ruby/models/employee_skill.rb +10 -0
  672. data/examples/showcase/config/lcp_ruby/models/export_log.yml +27 -0
  673. data/examples/showcase/config/lcp_ruby/models/export_profile.yml +37 -0
  674. data/examples/showcase/config/lcp_ruby/models/feature.rb +76 -0
  675. data/examples/showcase/config/lcp_ruby/models/gapfree_sequence.rb +17 -0
  676. data/examples/showcase/config/lcp_ruby/models/group.rb +26 -0
  677. data/examples/showcase/config/lcp_ruby/models/group_membership.rb +21 -0
  678. data/examples/showcase/config/lcp_ruby/models/group_role_mapping.rb +14 -0
  679. data/examples/showcase/config/lcp_ruby/models/host_inventory_item.yml +111 -0
  680. data/examples/showcase/config/lcp_ruby/models/import_profile.rb +30 -0
  681. data/examples/showcase/config/lcp_ruby/models/import_row.rb +32 -0
  682. data/examples/showcase/config/lcp_ruby/models/ingredient_def.rb +11 -0
  683. data/examples/showcase/config/lcp_ruby/models/lcp_error_log.yml +61 -0
  684. data/examples/showcase/config/lcp_ruby/models/page_config.rb +19 -0
  685. data/examples/showcase/config/lcp_ruby/models/permission_config.rb +21 -0
  686. data/examples/showcase/config/lcp_ruby/models/pipeline.rb +15 -0
  687. data/examples/showcase/config/lcp_ruby/models/pipeline_stage.rb +17 -0
  688. data/examples/showcase/config/lcp_ruby/models/platform_profile.rb +104 -0
  689. data/examples/showcase/config/lcp_ruby/models/profile_setting.rb +17 -0
  690. data/examples/showcase/config/lcp_ruby/models/profile_tag.rb +19 -0
  691. data/examples/showcase/config/lcp_ruby/models/project.rb +23 -0
  692. data/examples/showcase/config/lcp_ruby/models/role.rb +24 -0
  693. data/examples/showcase/config/lcp_ruby/models/saved_filter.rb +50 -0
  694. data/examples/showcase/config/lcp_ruby/models/showcase_aggregate.rb +93 -0
  695. data/examples/showcase/config/lcp_ruby/models/showcase_aggregate_company.rb +14 -0
  696. data/examples/showcase/config/lcp_ruby/models/showcase_aggregate_item.rb +25 -0
  697. data/examples/showcase/config/lcp_ruby/models/showcase_announcement.rb +20 -0
  698. data/examples/showcase/config/lcp_ruby/models/showcase_array.rb +45 -0
  699. data/examples/showcase/config/lcp_ruby/models/showcase_attachment.rb +49 -0
  700. data/examples/showcase/config/lcp_ruby/models/showcase_audit_log.yml +44 -0
  701. data/examples/showcase/config/lcp_ruby/models/showcase_audited_record.rb +20 -0
  702. data/examples/showcase/config/lcp_ruby/models/showcase_batch_task.rb +27 -0
  703. data/examples/showcase/config/lcp_ruby/models/showcase_business_unit.rb +26 -0
  704. data/examples/showcase/config/lcp_ruby/models/showcase_condition.rb +24 -0
  705. data/examples/showcase/config/lcp_ruby/models/showcase_condition_category.rb +16 -0
  706. data/examples/showcase/config/lcp_ruby/models/showcase_condition_task.rb +16 -0
  707. data/examples/showcase/config/lcp_ruby/models/showcase_condition_threshold.rb +13 -0
  708. data/examples/showcase/config/lcp_ruby/models/showcase_contact.rb +22 -0
  709. data/examples/showcase/config/lcp_ruby/models/showcase_custom_render.rb +38 -0
  710. data/examples/showcase/config/lcp_ruby/models/showcase_delete_reason.rb +11 -0
  711. data/examples/showcase/config/lcp_ruby/models/showcase_division.rb +31 -0
  712. data/examples/showcase/config/lcp_ruby/models/showcase_extensibility.rb +25 -0
  713. data/examples/showcase/config/lcp_ruby/models/showcase_field.rb +53 -0
  714. data/examples/showcase/config/lcp_ruby/models/showcase_form.rb +23 -0
  715. data/examples/showcase/config/lcp_ruby/models/showcase_form_action.rb +38 -0
  716. data/examples/showcase/config/lcp_ruby/models/showcase_grade.rb +18 -0
  717. data/examples/showcase/config/lcp_ruby/models/showcase_hr_employee.rb +90 -0
  718. data/examples/showcase/config/lcp_ruby/models/showcase_item_class.rb +31 -0
  719. data/examples/showcase/config/lcp_ruby/models/showcase_job_execution.rb +49 -0
  720. data/examples/showcase/config/lcp_ruby/models/showcase_memo.rb +23 -0
  721. data/examples/showcase/config/lcp_ruby/models/showcase_model.rb +74 -0
  722. data/examples/showcase/config/lcp_ruby/models/showcase_organization.rb +31 -0
  723. data/examples/showcase/config/lcp_ruby/models/showcase_permission.rb +30 -0
  724. data/examples/showcase/config/lcp_ruby/models/showcase_person.rb +23 -0
  725. data/examples/showcase/config/lcp_ruby/models/showcase_positioning.rb +19 -0
  726. data/examples/showcase/config/lcp_ruby/models/showcase_quick_note.rb +13 -0
  727. data/examples/showcase/config/lcp_ruby/models/showcase_recipe.rb +17 -0
  728. data/examples/showcase/config/lcp_ruby/models/showcase_report.rb +32 -0
  729. data/examples/showcase/config/lcp_ruby/models/showcase_school_class.rb +17 -0
  730. data/examples/showcase/config/lcp_ruby/models/showcase_search.rb +84 -0
  731. data/examples/showcase/config/lcp_ruby/models/showcase_sequence.rb +46 -0
  732. data/examples/showcase/config/lcp_ruby/models/showcase_soft_delete.rb +30 -0
  733. data/examples/showcase/config/lcp_ruby/models/showcase_soft_delete_item.rb +21 -0
  734. data/examples/showcase/config/lcp_ruby/models/showcase_student.rb +17 -0
  735. data/examples/showcase/config/lcp_ruby/models/showcase_type_default.rb +49 -0
  736. data/examples/showcase/config/lcp_ruby/models/showcase_userstamps.rb +26 -0
  737. data/examples/showcase/config/lcp_ruby/models/showcase_virtual_field.rb +68 -0
  738. data/examples/showcase/config/lcp_ruby/models/showcase_workflow.rb +54 -0
  739. data/examples/showcase/config/lcp_ruby/models/skill.rb +22 -0
  740. data/examples/showcase/config/lcp_ruby/models/tag.rb +16 -0
  741. data/examples/showcase/config/lcp_ruby/models/user.rb +54 -0
  742. data/examples/showcase/config/lcp_ruby/models/weather_station.rb +20 -0
  743. data/examples/showcase/config/lcp_ruby/models/workflow_approval_request.yml +77 -0
  744. data/examples/showcase/config/lcp_ruby/models/workflow_approval_step.yml +56 -0
  745. data/examples/showcase/config/lcp_ruby/models/workflow_approval_task.yml +51 -0
  746. data/examples/showcase/config/lcp_ruby/models/workflow_audit_log.yml +74 -0
  747. data/examples/showcase/config/lcp_ruby/pages/article_detail.yml +32 -0
  748. data/examples/showcase/config/lcp_ruby/pages/author_detail.yml +27 -0
  749. data/examples/showcase/config/lcp_ruby/pages/category_detail.yml +24 -0
  750. data/examples/showcase/config/lcp_ruby/pages/chart_showcase.yml +151 -0
  751. data/examples/showcase/config/lcp_ruby/pages/department_detail.yml +55 -0
  752. data/examples/showcase/config/lcp_ruby/pages/department_explorer.yml +60 -0
  753. data/examples/showcase/config/lcp_ruby/pages/employee_overview.yml +106 -0
  754. data/examples/showcase/config/lcp_ruby/pages/employee_transfer_dialog.yml +24 -0
  755. data/examples/showcase/config/lcp_ruby/pages/hr_turnover_dashboard.yml +288 -0
  756. data/examples/showcase/config/lcp_ruby/pages/main_dashboard.yml +142 -0
  757. data/examples/showcase/config/lcp_ruby/pages/monitoring_dashboard.yml +58 -0
  758. data/examples/showcase/config/lcp_ruby/pages/pipeline_detail.yml +16 -0
  759. data/examples/showcase/config/lcp_ruby/pages/showcase_custom_zones.yml +39 -0
  760. data/examples/showcase/config/lcp_ruby/pages/showcase_form_action_dialog.yml +11 -0
  761. data/examples/showcase/config/lcp_ruby/pages/workflow_request_detail.yml +34 -0
  762. data/examples/showcase/config/lcp_ruby/permissions/api_token.yml +26 -0
  763. data/examples/showcase/config/lcp_ruby/permissions/batch_operation.yml +36 -0
  764. data/examples/showcase/config/lcp_ruby/permissions/custom_field_definition.yml +15 -0
  765. data/examples/showcase/config/lcp_ruby/permissions/default.yml +28 -0
  766. data/examples/showcase/config/lcp_ruby/permissions/export_log.yml +23 -0
  767. data/examples/showcase/config/lcp_ruby/permissions/export_profile.yml +25 -0
  768. data/examples/showcase/config/lcp_ruby/permissions/gapfree_sequence.yml +6 -0
  769. data/examples/showcase/config/lcp_ruby/permissions/group.yml +20 -0
  770. data/examples/showcase/config/lcp_ruby/permissions/group_membership.yml +20 -0
  771. data/examples/showcase/config/lcp_ruby/permissions/group_role_mapping.yml +20 -0
  772. data/examples/showcase/config/lcp_ruby/permissions/host_inventory_item.yml +34 -0
  773. data/examples/showcase/config/lcp_ruby/permissions/import_profile.yml +29 -0
  774. data/examples/showcase/config/lcp_ruby/permissions/import_row.yml +17 -0
  775. data/examples/showcase/config/lcp_ruby/permissions/lcp_error_log.yml +8 -0
  776. data/examples/showcase/config/lcp_ruby/permissions/page_config.yml +15 -0
  777. data/examples/showcase/config/lcp_ruby/permissions/permission_config.yml +15 -0
  778. data/examples/showcase/config/lcp_ruby/permissions/platform_profile.yml +23 -0
  779. data/examples/showcase/config/lcp_ruby/permissions/profile_setting.yml +23 -0
  780. data/examples/showcase/config/lcp_ruby/permissions/profile_tag.yml +23 -0
  781. data/examples/showcase/config/lcp_ruby/permissions/role.yml +20 -0
  782. data/examples/showcase/config/lcp_ruby/permissions/saved_filter.yml +39 -0
  783. data/examples/showcase/config/lcp_ruby/permissions/showcase_announcement.yml +22 -0
  784. data/examples/showcase/config/lcp_ruby/permissions/showcase_audit_log.yml +15 -0
  785. data/examples/showcase/config/lcp_ruby/permissions/showcase_audited_record.yml +15 -0
  786. data/examples/showcase/config/lcp_ruby/permissions/showcase_batch_task.yml +31 -0
  787. data/examples/showcase/config/lcp_ruby/permissions/showcase_condition.yml +54 -0
  788. data/examples/showcase/config/lcp_ruby/permissions/showcase_contact.yml +21 -0
  789. data/examples/showcase/config/lcp_ruby/permissions/showcase_custom_render.yml +21 -0
  790. data/examples/showcase/config/lcp_ruby/permissions/showcase_delete_reason.yml +12 -0
  791. data/examples/showcase/config/lcp_ruby/permissions/showcase_form_action.yml +26 -0
  792. data/examples/showcase/config/lcp_ruby/permissions/showcase_grade.yml +33 -0
  793. data/examples/showcase/config/lcp_ruby/permissions/showcase_job_execution.yml +23 -0
  794. data/examples/showcase/config/lcp_ruby/permissions/showcase_permission.yml +47 -0
  795. data/examples/showcase/config/lcp_ruby/permissions/showcase_quick_note.yml +12 -0
  796. data/examples/showcase/config/lcp_ruby/permissions/showcase_school_class.yml +37 -0
  797. data/examples/showcase/config/lcp_ruby/permissions/showcase_student.yml +43 -0
  798. data/examples/showcase/config/lcp_ruby/permissions/showcase_workflow.yml +34 -0
  799. data/examples/showcase/config/lcp_ruby/permissions/workflow_approval_request.yml +18 -0
  800. data/examples/showcase/config/lcp_ruby/permissions/workflow_approval_step.yml +18 -0
  801. data/examples/showcase/config/lcp_ruby/permissions/workflow_approval_task.yml +18 -0
  802. data/examples/showcase/config/lcp_ruby/permissions/workflow_audit_log.yml +19 -0
  803. data/examples/showcase/config/lcp_ruby/presenters/announcements.rb +59 -0
  804. data/examples/showcase/config/lcp_ruby/presenters/approval_requests.rb +69 -0
  805. data/examples/showcase/config/lcp_ruby/presenters/approval_steps.rb +59 -0
  806. data/examples/showcase/config/lcp_ruby/presenters/approval_tasks.rb +65 -0
  807. data/examples/showcase/config/lcp_ruby/presenters/article_comments_zone.rb +12 -0
  808. data/examples/showcase/config/lcp_ruby/presenters/article_related_zone.rb +15 -0
  809. data/examples/showcase/config/lcp_ruby/presenters/articles.rb +149 -0
  810. data/examples/showcase/config/lcp_ruby/presenters/articles_tiles.rb +30 -0
  811. data/examples/showcase/config/lcp_ruby/presenters/author_articles_zone.rb +12 -0
  812. data/examples/showcase/config/lcp_ruby/presenters/author_show_zone.rb +12 -0
  813. data/examples/showcase/config/lcp_ruby/presenters/authors.rb +39 -0
  814. data/examples/showcase/config/lcp_ruby/presenters/batch_operation_items.yml +45 -0
  815. data/examples/showcase/config/lcp_ruby/presenters/batch_operations.yml +66 -0
  816. data/examples/showcase/config/lcp_ruby/presenters/categories.rb +50 -0
  817. data/examples/showcase/config/lcp_ruby/presenters/category_articles_zone.rb +20 -0
  818. data/examples/showcase/config/lcp_ruby/presenters/category_children_zone.rb +10 -0
  819. data/examples/showcase/config/lcp_ruby/presenters/comment_quick_add_dialog.rb +15 -0
  820. data/examples/showcase/config/lcp_ruby/presenters/custom_fields.rb +124 -0
  821. data/examples/showcase/config/lcp_ruby/presenters/dashboard_employees.rb +16 -0
  822. data/examples/showcase/config/lcp_ruby/presenters/delete_reason_dialog.rb +13 -0
  823. data/examples/showcase/config/lcp_ruby/presenters/departments.rb +55 -0
  824. data/examples/showcase/config/lcp_ruby/presenters/dept_add_employee_dialog.rb +19 -0
  825. data/examples/showcase/config/lcp_ruby/presenters/dept_children_zone.rb +10 -0
  826. data/examples/showcase/config/lcp_ruby/presenters/dept_detail_zone.rb +14 -0
  827. data/examples/showcase/config/lcp_ruby/presenters/dept_employees_zone.rb +16 -0
  828. data/examples/showcase/config/lcp_ruby/presenters/dept_list_selection_zone.rb +19 -0
  829. data/examples/showcase/config/lcp_ruby/presenters/employee_overview_index_zone.rb +36 -0
  830. data/examples/showcase/config/lcp_ruby/presenters/employee_quick_add_dialog.rb +14 -0
  831. data/examples/showcase/config/lcp_ruby/presenters/employee_show_zone.rb +20 -0
  832. data/examples/showcase/config/lcp_ruby/presenters/employee_transfer_form_zone.rb +19 -0
  833. data/examples/showcase/config/lcp_ruby/presenters/employees.rb +165 -0
  834. data/examples/showcase/config/lcp_ruby/presenters/employees_tiles.rb +33 -0
  835. data/examples/showcase/config/lcp_ruby/presenters/export_logs.yml +58 -0
  836. data/examples/showcase/config/lcp_ruby/presenters/export_profiles.yml +70 -0
  837. data/examples/showcase/config/lcp_ruby/presenters/extensibility_quick_edit_dialog.rb +13 -0
  838. data/examples/showcase/config/lcp_ruby/presenters/feature_kanban.rb +30 -0
  839. data/examples/showcase/config/lcp_ruby/presenters/features_card.rb +179 -0
  840. data/examples/showcase/config/lcp_ruby/presenters/features_hub.rb +44 -0
  841. data/examples/showcase/config/lcp_ruby/presenters/features_table.rb +37 -0
  842. data/examples/showcase/config/lcp_ruby/presenters/features_tiles.rb +48 -0
  843. data/examples/showcase/config/lcp_ruby/presenters/group_memberships.rb +54 -0
  844. data/examples/showcase/config/lcp_ruby/presenters/group_role_mappings.rb +48 -0
  845. data/examples/showcase/config/lcp_ruby/presenters/groups.rb +74 -0
  846. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items.rb +99 -0
  847. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items_managed.rb +84 -0
  848. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items_report.rb +40 -0
  849. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items_wizard.rb +76 -0
  850. data/examples/showcase/config/lcp_ruby/presenters/import_profiles.rb +61 -0
  851. data/examples/showcase/config/lcp_ruby/presenters/import_rows.rb +39 -0
  852. data/examples/showcase/config/lcp_ruby/presenters/lcp_error_logs.yml +46 -0
  853. data/examples/showcase/config/lcp_ruby/presenters/my_api_tokens.rb +35 -0
  854. data/examples/showcase/config/lcp_ruby/presenters/my_api_tokens_create_dialog.rb +27 -0
  855. data/examples/showcase/config/lcp_ruby/presenters/my_employee_profile.rb +24 -0
  856. data/examples/showcase/config/lcp_ruby/presenters/my_settings.rb +50 -0
  857. data/examples/showcase/config/lcp_ruby/presenters/page_configs.rb +56 -0
  858. data/examples/showcase/config/lcp_ruby/presenters/permission_configs.rb +58 -0
  859. data/examples/showcase/config/lcp_ruby/presenters/pipeline_edit_zone.rb +11 -0
  860. data/examples/showcase/config/lcp_ruby/presenters/pipeline_stages.rb +51 -0
  861. data/examples/showcase/config/lcp_ruby/presenters/pipeline_stages_zone.rb +11 -0
  862. data/examples/showcase/config/lcp_ruby/presenters/pipelines.rb +40 -0
  863. data/examples/showcase/config/lcp_ruby/presenters/platform_profiles.rb +90 -0
  864. data/examples/showcase/config/lcp_ruby/presenters/projects.rb +58 -0
  865. data/examples/showcase/config/lcp_ruby/presenters/quick_note_dialog.rb +14 -0
  866. data/examples/showcase/config/lcp_ruby/presenters/roles.rb +60 -0
  867. data/examples/showcase/config/lcp_ruby/presenters/save_filter_dialog.rb +17 -0
  868. data/examples/showcase/config/lcp_ruby/presenters/saved_filters.rb +94 -0
  869. data/examples/showcase/config/lcp_ruby/presenters/showcase_aggregate_items.rb +61 -0
  870. data/examples/showcase/config/lcp_ruby/presenters/showcase_aggregates.rb +115 -0
  871. data/examples/showcase/config/lcp_ruby/presenters/showcase_aggregates_tiles.rb +44 -0
  872. data/examples/showcase/config/lcp_ruby/presenters/showcase_amount_kanban.rb +31 -0
  873. data/examples/showcase/config/lcp_ruby/presenters/showcase_arrays.rb +140 -0
  874. data/examples/showcase/config/lcp_ruby/presenters/showcase_attachments.rb +66 -0
  875. data/examples/showcase/config/lcp_ruby/presenters/showcase_audit_logs.rb +46 -0
  876. data/examples/showcase/config/lcp_ruby/presenters/showcase_audited_records.rb +58 -0
  877. data/examples/showcase/config/lcp_ruby/presenters/showcase_batch_tasks.rb +97 -0
  878. data/examples/showcase/config/lcp_ruby/presenters/showcase_batch_tasks_archive.rb +52 -0
  879. data/examples/showcase/config/lcp_ruby/presenters/showcase_business_units.rb +43 -0
  880. data/examples/showcase/config/lcp_ruby/presenters/showcase_conditions.rb +195 -0
  881. data/examples/showcase/config/lcp_ruby/presenters/showcase_contacts.rb +82 -0
  882. data/examples/showcase/config/lcp_ruby/presenters/showcase_custom_render_with.rb +50 -0
  883. data/examples/showcase/config/lcp_ruby/presenters/showcase_custom_sections.rb +88 -0
  884. data/examples/showcase/config/lcp_ruby/presenters/showcase_custom_zones_main.rb +75 -0
  885. data/examples/showcase/config/lcp_ruby/presenters/showcase_divisions.rb +53 -0
  886. data/examples/showcase/config/lcp_ruby/presenters/showcase_extensibility.rb +48 -0
  887. data/examples/showcase/config/lcp_ruby/presenters/showcase_fields_card.rb +34 -0
  888. data/examples/showcase/config/lcp_ruby/presenters/showcase_fields_table.rb +128 -0
  889. data/examples/showcase/config/lcp_ruby/presenters/showcase_fields_tiles.rb +42 -0
  890. data/examples/showcase/config/lcp_ruby/presenters/showcase_form_action_dialog.rb +27 -0
  891. data/examples/showcase/config/lcp_ruby/presenters/showcase_form_actions.rb +132 -0
  892. data/examples/showcase/config/lcp_ruby/presenters/showcase_form_actions_overflow.rb +76 -0
  893. data/examples/showcase/config/lcp_ruby/presenters/showcase_forms.rb +110 -0
  894. data/examples/showcase/config/lcp_ruby/presenters/showcase_grades.rb +38 -0
  895. data/examples/showcase/config/lcp_ruby/presenters/showcase_hr_employees.rb +84 -0
  896. data/examples/showcase/config/lcp_ruby/presenters/showcase_item_classes.rb +120 -0
  897. data/examples/showcase/config/lcp_ruby/presenters/showcase_job_executions.rb +150 -0
  898. data/examples/showcase/config/lcp_ruby/presenters/showcase_memos.rb +96 -0
  899. data/examples/showcase/config/lcp_ruby/presenters/showcase_models.rb +112 -0
  900. data/examples/showcase/config/lcp_ruby/presenters/showcase_organizations.rb +106 -0
  901. data/examples/showcase/config/lcp_ruby/presenters/showcase_people.rb +97 -0
  902. data/examples/showcase/config/lcp_ruby/presenters/showcase_permissions.rb +84 -0
  903. data/examples/showcase/config/lcp_ruby/presenters/showcase_positioning.rb +61 -0
  904. data/examples/showcase/config/lcp_ruby/presenters/showcase_recipes.rb +105 -0
  905. data/examples/showcase/config/lcp_ruby/presenters/showcase_recipes_raw.rb +32 -0
  906. data/examples/showcase/config/lcp_ruby/presenters/showcase_reports.rb +109 -0
  907. data/examples/showcase/config/lcp_ruby/presenters/showcase_school_classes.rb +34 -0
  908. data/examples/showcase/config/lcp_ruby/presenters/showcase_searches.rb +226 -0
  909. data/examples/showcase/config/lcp_ruby/presenters/showcase_sequences.rb +67 -0
  910. data/examples/showcase/config/lcp_ruby/presenters/showcase_soft_delete.rb +88 -0
  911. data/examples/showcase/config/lcp_ruby/presenters/showcase_soft_delete_archive.rb +52 -0
  912. data/examples/showcase/config/lcp_ruby/presenters/showcase_soft_delete_items.rb +47 -0
  913. data/examples/showcase/config/lcp_ruby/presenters/showcase_students.rb +33 -0
  914. data/examples/showcase/config/lcp_ruby/presenters/showcase_type_defaults.rb +92 -0
  915. data/examples/showcase/config/lcp_ruby/presenters/showcase_userstamps.rb +76 -0
  916. data/examples/showcase/config/lcp_ruby/presenters/showcase_virtual_fields.rb +104 -0
  917. data/examples/showcase/config/lcp_ruby/presenters/showcase_workflow_admin.rb +24 -0
  918. data/examples/showcase/config/lcp_ruby/presenters/showcase_workflow_kanban.rb +36 -0
  919. data/examples/showcase/config/lcp_ruby/presenters/showcase_workflows.rb +103 -0
  920. data/examples/showcase/config/lcp_ruby/presenters/tags.rb +35 -0
  921. data/examples/showcase/config/lcp_ruby/presenters/users.rb +61 -0
  922. data/examples/showcase/config/lcp_ruby/presenters/weather_stations.rb +60 -0
  923. data/examples/showcase/config/lcp_ruby/presenters/workflow_audit_logs.rb +76 -0
  924. data/examples/showcase/config/lcp_ruby/presenters/workflow_request_audit_zone.rb +28 -0
  925. data/examples/showcase/config/lcp_ruby/theme.yml +2 -0
  926. data/examples/showcase/config/lcp_ruby/types/currency.yml +15 -0
  927. data/examples/showcase/config/lcp_ruby/types/percentage.yml +16 -0
  928. data/examples/showcase/config/lcp_ruby/types/rating.yml +20 -0
  929. data/examples/showcase/config/lcp_ruby/views/announcements.yml +7 -0
  930. data/examples/showcase/config/lcp_ruby/views/approval_requests.yml +7 -0
  931. data/examples/showcase/config/lcp_ruby/views/approval_steps.yml +7 -0
  932. data/examples/showcase/config/lcp_ruby/views/approval_tasks.yml +7 -0
  933. data/examples/showcase/config/lcp_ruby/views/articles.yml +12 -0
  934. data/examples/showcase/config/lcp_ruby/views/authors.yml +7 -0
  935. data/examples/showcase/config/lcp_ruby/views/batch_operation_items.yml +6 -0
  936. data/examples/showcase/config/lcp_ruby/views/batch_operations.yml +10 -0
  937. data/examples/showcase/config/lcp_ruby/views/categories.yml +9 -0
  938. data/examples/showcase/config/lcp_ruby/views/custom_fields.rb +8 -0
  939. data/examples/showcase/config/lcp_ruby/views/dashboard.yml +10 -0
  940. data/examples/showcase/config/lcp_ruby/views/department_explorer.yml +7 -0
  941. data/examples/showcase/config/lcp_ruby/views/departments.yml +9 -0
  942. data/examples/showcase/config/lcp_ruby/views/employee_overview.yml +7 -0
  943. data/examples/showcase/config/lcp_ruby/views/employees.yml +12 -0
  944. data/examples/showcase/config/lcp_ruby/views/export_logs.yml +7 -0
  945. data/examples/showcase/config/lcp_ruby/views/export_profiles.yml +7 -0
  946. data/examples/showcase/config/lcp_ruby/views/features.yml +19 -0
  947. data/examples/showcase/config/lcp_ruby/views/group_memberships.yml +7 -0
  948. data/examples/showcase/config/lcp_ruby/views/group_role_mappings.yml +7 -0
  949. data/examples/showcase/config/lcp_ruby/views/groups.yml +7 -0
  950. data/examples/showcase/config/lcp_ruby/views/host_inventory_items.yml +16 -0
  951. data/examples/showcase/config/lcp_ruby/views/hr_turnover_dashboard.yml +7 -0
  952. data/examples/showcase/config/lcp_ruby/views/import_profiles.yml +7 -0
  953. data/examples/showcase/config/lcp_ruby/views/import_rows.yml +7 -0
  954. data/examples/showcase/config/lcp_ruby/views/lcp_error_logs.yml +10 -0
  955. data/examples/showcase/config/lcp_ruby/views/monitoring.yml +7 -0
  956. data/examples/showcase/config/lcp_ruby/views/my_api_tokens.rb +9 -0
  957. data/examples/showcase/config/lcp_ruby/views/page_configs.yml +11 -0
  958. data/examples/showcase/config/lcp_ruby/views/permission_configs.yml +11 -0
  959. data/examples/showcase/config/lcp_ruby/views/pipeline_stages.yml +7 -0
  960. data/examples/showcase/config/lcp_ruby/views/pipelines.yml +7 -0
  961. data/examples/showcase/config/lcp_ruby/views/platform_profiles.yml +7 -0
  962. data/examples/showcase/config/lcp_ruby/views/projects.yml +9 -0
  963. data/examples/showcase/config/lcp_ruby/views/roles.yml +7 -0
  964. data/examples/showcase/config/lcp_ruby/views/saved_filters.yml +7 -0
  965. data/examples/showcase/config/lcp_ruby/views/showcase_aggregate_items.yml +7 -0
  966. data/examples/showcase/config/lcp_ruby/views/showcase_aggregates.yml +10 -0
  967. data/examples/showcase/config/lcp_ruby/views/showcase_arrays.yml +7 -0
  968. data/examples/showcase/config/lcp_ruby/views/showcase_attachments.yml +7 -0
  969. data/examples/showcase/config/lcp_ruby/views/showcase_audit_logs.yml +11 -0
  970. data/examples/showcase/config/lcp_ruby/views/showcase_audited_records.yml +10 -0
  971. data/examples/showcase/config/lcp_ruby/views/showcase_batch_tasks.yml +10 -0
  972. data/examples/showcase/config/lcp_ruby/views/showcase_business_units.yml +7 -0
  973. data/examples/showcase/config/lcp_ruby/views/showcase_conditions.yml +7 -0
  974. data/examples/showcase/config/lcp_ruby/views/showcase_contacts.yml +7 -0
  975. data/examples/showcase/config/lcp_ruby/views/showcase_custom_render_with.yml +7 -0
  976. data/examples/showcase/config/lcp_ruby/views/showcase_custom_sections.yml +7 -0
  977. data/examples/showcase/config/lcp_ruby/views/showcase_custom_zones.yml +7 -0
  978. data/examples/showcase/config/lcp_ruby/views/showcase_divisions.yml +9 -0
  979. data/examples/showcase/config/lcp_ruby/views/showcase_extensibility.yml +7 -0
  980. data/examples/showcase/config/lcp_ruby/views/showcase_fields.yml +13 -0
  981. data/examples/showcase/config/lcp_ruby/views/showcase_form_actions.yml +10 -0
  982. data/examples/showcase/config/lcp_ruby/views/showcase_forms.yml +7 -0
  983. data/examples/showcase/config/lcp_ruby/views/showcase_grades.yml +9 -0
  984. data/examples/showcase/config/lcp_ruby/views/showcase_hr_employees.yml +9 -0
  985. data/examples/showcase/config/lcp_ruby/views/showcase_item_classes.yml +7 -0
  986. data/examples/showcase/config/lcp_ruby/views/showcase_job_executions.yml +9 -0
  987. data/examples/showcase/config/lcp_ruby/views/showcase_memos.yml +7 -0
  988. data/examples/showcase/config/lcp_ruby/views/showcase_models.yml +7 -0
  989. data/examples/showcase/config/lcp_ruby/views/showcase_organizations.yml +7 -0
  990. data/examples/showcase/config/lcp_ruby/views/showcase_people.yml +7 -0
  991. data/examples/showcase/config/lcp_ruby/views/showcase_permissions.yml +7 -0
  992. data/examples/showcase/config/lcp_ruby/views/showcase_positioning.yml +7 -0
  993. data/examples/showcase/config/lcp_ruby/views/showcase_recipes.yml +10 -0
  994. data/examples/showcase/config/lcp_ruby/views/showcase_reports.yml +7 -0
  995. data/examples/showcase/config/lcp_ruby/views/showcase_school_classes.yml +7 -0
  996. data/examples/showcase/config/lcp_ruby/views/showcase_searches.yml +7 -0
  997. data/examples/showcase/config/lcp_ruby/views/showcase_sequences.yml +7 -0
  998. data/examples/showcase/config/lcp_ruby/views/showcase_soft_delete.yml +10 -0
  999. data/examples/showcase/config/lcp_ruby/views/showcase_soft_delete_items.yml +8 -0
  1000. data/examples/showcase/config/lcp_ruby/views/showcase_students.yml +9 -0
  1001. data/examples/showcase/config/lcp_ruby/views/showcase_userstamps.yml +7 -0
  1002. data/examples/showcase/config/lcp_ruby/views/showcase_virtual_fields.yml +7 -0
  1003. data/examples/showcase/config/lcp_ruby/views/showcase_workflows.yml +16 -0
  1004. data/examples/showcase/config/lcp_ruby/views/tags.yml +7 -0
  1005. data/examples/showcase/config/lcp_ruby/views/users.yml +7 -0
  1006. data/examples/showcase/config/lcp_ruby/views/weather_stations.yml +7 -0
  1007. data/examples/showcase/config/lcp_ruby/views/workflow_audit_logs.yml +9 -0
  1008. data/examples/showcase/config/lcp_ruby/workflows/showcase_form_action.rb +48 -0
  1009. data/examples/showcase/config/lcp_ruby/workflows/showcase_workflow.rb +199 -0
  1010. data/examples/showcase/config/locales/cs.yml +2818 -0
  1011. data/examples/showcase/config/locales/en.yml +67 -0
  1012. data/examples/showcase/config/locales/lcp_ruby/api_tokens.cs.yml +46 -0
  1013. data/examples/showcase/config/locales/lcp_ruby/api_tokens.en.yml +49 -0
  1014. data/examples/showcase/config/routes.rb +21 -0
  1015. data/examples/showcase/config/storage.yml +3 -0
  1016. data/examples/showcase/config.ru +2 -0
  1017. data/examples/showcase/db/migrate/20260219124321_create_active_storage_tables.active_storage.rb +57 -0
  1018. data/examples/showcase/db/migrate/20260220072723_create_lcp_ruby_users.rb +42 -0
  1019. data/examples/showcase/db/migrate/20260406120000_create_host_inventory_items.rb +32 -0
  1020. data/examples/showcase/db/migrate/20260428134542_add_oidc_columns_to_lcp_ruby_users.rb +13 -0
  1021. data/examples/showcase/db/migrate/20260502120000_create_platform_profiles.rb +19 -0
  1022. data/examples/showcase/db/schema.rb +1222 -0
  1023. data/examples/showcase/db/seeds.rb +3085 -0
  1024. data/examples/showcase/erd.md +567 -0
  1025. data/examples/showcase/test/fixtures/import_articles.csv +4 -0
  1026. data/examples/showcase/test/fixtures/import_employees.csv +4 -0
  1027. data/examples/todo/Gemfile +8 -0
  1028. data/examples/todo/Gemfile.lock +415 -0
  1029. data/examples/todo/Rakefile +2 -0
  1030. data/examples/todo/app/assets/config/manifest.js +1 -0
  1031. data/examples/todo/app/controllers/application_controller.rb +6 -0
  1032. data/examples/todo/app/lcp_services/defaults/one_week_from_now.rb +11 -0
  1033. data/examples/todo/bin/rails +4 -0
  1034. data/examples/todo/bin/rake +4 -0
  1035. data/examples/todo/config/application.rb +31 -0
  1036. data/examples/todo/config/boot.rb +2 -0
  1037. data/examples/todo/config/database.yml +12 -0
  1038. data/examples/todo/config/environment.rb +2 -0
  1039. data/examples/todo/config/lcp_ruby/models/todo_item.yml +67 -0
  1040. data/examples/todo/config/lcp_ruby/models/todo_list.yml +49 -0
  1041. data/examples/todo/config/lcp_ruby/permissions/default.yml +10 -0
  1042. data/examples/todo/config/lcp_ruby/permissions/todo_item.yml +21 -0
  1043. data/examples/todo/config/lcp_ruby/presenters/todo_item.yml +75 -0
  1044. data/examples/todo/config/lcp_ruby/presenters/todo_list.yml +68 -0
  1045. data/examples/todo/config/lcp_ruby/views/todo_items.yml +11 -0
  1046. data/examples/todo/config/lcp_ruby/views/todo_lists.yml +9 -0
  1047. data/examples/todo/config/routes.rb +4 -0
  1048. data/examples/todo/config/storage.yml +3 -0
  1049. data/examples/todo/config.ru +2 -0
  1050. data/examples/todo/db/migrate/20260219103416_create_active_storage_tables.active_storage.rb +57 -0
  1051. data/examples/todo/db/schema.rb +63 -0
  1052. data/examples/todo/db/seeds.rb +24 -0
  1053. data/examples/todo/erd.md +21 -0
  1054. data/exe/lcp +33 -0
  1055. data/lib/generators/lcp_ruby/agent_setup_generator.rb +102 -0
  1056. data/lib/generators/lcp_ruby/api_tokens_generator.rb +102 -0
  1057. data/lib/generators/lcp_ruby/auditing_generator.rb +54 -0
  1058. data/lib/generators/lcp_ruby/background_jobs_generator.rb +61 -0
  1059. data/lib/generators/lcp_ruby/batch_operations_generator.rb +62 -0
  1060. data/lib/generators/lcp_ruby/claude_skills_generator.rb +47 -0
  1061. data/lib/generators/lcp_ruby/custom_fields_generator.rb +54 -0
  1062. data/lib/generators/lcp_ruby/dsl_to_yaml.rb +72 -0
  1063. data/lib/generators/lcp_ruby/entity/color_palette.rb +22 -0
  1064. data/lib/generators/lcp_ruby/entity/field_descriptor.rb +24 -0
  1065. data/lib/generators/lcp_ruby/entity/field_token_parser.rb +101 -0
  1066. data/lib/generators/lcp_ruby/entity/role_discovery.rb +45 -0
  1067. data/lib/generators/lcp_ruby/entity_generator.rb +1104 -0
  1068. data/lib/generators/lcp_ruby/export_generator.rb +71 -0
  1069. data/lib/generators/lcp_ruby/format_support.rb +56 -0
  1070. data/lib/generators/lcp_ruby/gapfree_sequences_generator.rb +64 -0
  1071. data/lib/generators/lcp_ruby/groups_generator.rb +94 -0
  1072. data/lib/generators/lcp_ruby/host_controller_generator.rb +202 -0
  1073. data/lib/generators/lcp_ruby/import_generator.rb +96 -0
  1074. data/lib/generators/lcp_ruby/install_auth_generator.rb +432 -0
  1075. data/lib/generators/lcp_ruby/install_generator.rb +319 -0
  1076. data/lib/generators/lcp_ruby/monitoring_generator.rb +58 -0
  1077. data/lib/generators/lcp_ruby/oidc_role_mappings_generator.rb +60 -0
  1078. data/lib/generators/lcp_ruby/pages_generator.rb +66 -0
  1079. data/lib/generators/lcp_ruby/permission_source_generator.rb +66 -0
  1080. data/lib/generators/lcp_ruby/role_model_generator.rb +73 -0
  1081. data/lib/generators/lcp_ruby/saved_filters_generator.rb +62 -0
  1082. data/lib/generators/lcp_ruby/templates/add_oidc_columns_to_lcp_ruby_users.rb.erb +13 -0
  1083. data/lib/generators/lcp_ruby/templates/agent_setup/agents_md.md +3 -0
  1084. data/lib/generators/lcp_ruby/templates/agent_setup/claude_md.md +12 -0
  1085. data/lib/generators/lcp_ruby/templates/api_tokens/create_dialog.rb +31 -0
  1086. data/lib/generators/lcp_ruby/templates/api_tokens/locales.en.yml +43 -0
  1087. data/lib/generators/lcp_ruby/templates/api_tokens/model.rb +23 -0
  1088. data/lib/generators/lcp_ruby/templates/api_tokens/permissions.yml +30 -0
  1089. data/lib/generators/lcp_ruby/templates/api_tokens/presenter.rb +38 -0
  1090. data/lib/generators/lcp_ruby/templates/api_tokens/view_group.rb +13 -0
  1091. data/lib/generators/lcp_ruby/templates/auditing/model.rb +34 -0
  1092. data/lib/generators/lcp_ruby/templates/auditing/permissions.yml +19 -0
  1093. data/lib/generators/lcp_ruby/templates/auditing/presenter.rb +41 -0
  1094. data/lib/generators/lcp_ruby/templates/auditing/view_group.rb +10 -0
  1095. data/lib/generators/lcp_ruby/templates/background_jobs/model.rb +59 -0
  1096. data/lib/generators/lcp_ruby/templates/background_jobs/permissions.yml +22 -0
  1097. data/lib/generators/lcp_ruby/templates/background_jobs/presenter.rb +82 -0
  1098. data/lib/generators/lcp_ruby/templates/background_jobs/view_group.rb +9 -0
  1099. data/lib/generators/lcp_ruby/templates/batch_operations/item_model.rb +28 -0
  1100. data/lib/generators/lcp_ruby/templates/batch_operations/item_presenter.rb +43 -0
  1101. data/lib/generators/lcp_ruby/templates/batch_operations/model.rb +42 -0
  1102. data/lib/generators/lcp_ruby/templates/batch_operations/permissions.yml +44 -0
  1103. data/lib/generators/lcp_ruby/templates/batch_operations/presenter.rb +61 -0
  1104. data/lib/generators/lcp_ruby/templates/batch_operations/view_group.rb +9 -0
  1105. data/lib/generators/lcp_ruby/templates/create_lcp_ruby_users.rb.erb +50 -0
  1106. data/lib/generators/lcp_ruby/templates/custom_fields/model.rb +60 -0
  1107. data/lib/generators/lcp_ruby/templates/custom_fields/permissions.yml +19 -0
  1108. data/lib/generators/lcp_ruby/templates/custom_fields/presenter.rb +128 -0
  1109. data/lib/generators/lcp_ruby/templates/custom_fields/view_group.rb +9 -0
  1110. data/lib/generators/lcp_ruby/templates/entity/model.rb +42 -0
  1111. data/lib/generators/lcp_ruby/templates/entity/permissions.yml +20 -0
  1112. data/lib/generators/lcp_ruby/templates/entity/presenter.rb +55 -0
  1113. data/lib/generators/lcp_ruby/templates/entity/view_group.rb +8 -0
  1114. data/lib/generators/lcp_ruby/templates/export/export_log_model.rb +30 -0
  1115. data/lib/generators/lcp_ruby/templates/export/export_log_permissions.yml +24 -0
  1116. data/lib/generators/lcp_ruby/templates/export/export_logs_presenter.rb +51 -0
  1117. data/lib/generators/lcp_ruby/templates/export/export_profile_model.rb +28 -0
  1118. data/lib/generators/lcp_ruby/templates/export/export_profile_permissions.yml +26 -0
  1119. data/lib/generators/lcp_ruby/templates/export/export_profiles_presenter.rb +59 -0
  1120. data/lib/generators/lcp_ruby/templates/gapfree_sequences/model.rb +18 -0
  1121. data/lib/generators/lcp_ruby/templates/gapfree_sequences/permissions.yml +19 -0
  1122. data/lib/generators/lcp_ruby/templates/gapfree_sequences/presenter.rb +51 -0
  1123. data/lib/generators/lcp_ruby/templates/gapfree_sequences/view_group.rb +9 -0
  1124. data/lib/generators/lcp_ruby/templates/groups/group_membership_model.rb +17 -0
  1125. data/lib/generators/lcp_ruby/templates/groups/group_model.rb +28 -0
  1126. data/lib/generators/lcp_ruby/templates/groups/group_permissions.yml +19 -0
  1127. data/lib/generators/lcp_ruby/templates/groups/group_presenter.rb +53 -0
  1128. data/lib/generators/lcp_ruby/templates/groups/group_role_mapping_model.rb +15 -0
  1129. data/lib/generators/lcp_ruby/templates/groups/group_view_group.rb +9 -0
  1130. data/lib/generators/lcp_ruby/templates/host_controller/controller.rb.erb +131 -0
  1131. data/lib/generators/lcp_ruby/templates/import/data_import_job.yml +7 -0
  1132. data/lib/generators/lcp_ruby/templates/import/import_profile_model.rb +30 -0
  1133. data/lib/generators/lcp_ruby/templates/import/import_profile_permissions.yml +29 -0
  1134. data/lib/generators/lcp_ruby/templates/import/import_profiles_presenter.rb +57 -0
  1135. data/lib/generators/lcp_ruby/templates/import/import_row_model.rb +32 -0
  1136. data/lib/generators/lcp_ruby/templates/import/import_row_permissions.yml +11 -0
  1137. data/lib/generators/lcp_ruby/templates/import/import_rows_presenter.rb +35 -0
  1138. data/lib/generators/lcp_ruby/templates/install/default_permissions.yml +26 -0
  1139. data/lib/generators/lcp_ruby/templates/install/menu.yml.tt +71 -0
  1140. data/lib/generators/lcp_ruby/templates/install/model.rb +20 -0
  1141. data/lib/generators/lcp_ruby/templates/install/permissions.yml +25 -0
  1142. data/lib/generators/lcp_ruby/templates/install/presenter.rb +44 -0
  1143. data/lib/generators/lcp_ruby/templates/install/view_group.rb +10 -0
  1144. data/lib/generators/lcp_ruby/templates/install_auth/oidc/entra.yml.erb +46 -0
  1145. data/lib/generators/lcp_ruby/templates/install_auth/oidc/generic.yml.erb +55 -0
  1146. data/lib/generators/lcp_ruby/templates/install_auth/oidc/google.yml.erb +42 -0
  1147. data/lib/generators/lcp_ruby/templates/install_auth/oidc/keycloak.yml.erb +45 -0
  1148. data/lib/generators/lcp_ruby/templates/install_auth/oidc/okta.yml.erb +45 -0
  1149. data/lib/generators/lcp_ruby/templates/install_auth/user.rb +36 -0
  1150. data/lib/generators/lcp_ruby/templates/monitoring/model.rb +34 -0
  1151. data/lib/generators/lcp_ruby/templates/monitoring/model_extension.rb +12 -0
  1152. data/lib/generators/lcp_ruby/templates/monitoring/page.yml +49 -0
  1153. data/lib/generators/lcp_ruby/templates/monitoring/permissions.yml +8 -0
  1154. data/lib/generators/lcp_ruby/templates/monitoring/presenter.rb +44 -0
  1155. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/locales.en.yml +15 -0
  1156. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/model.rb +32 -0
  1157. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/permissions.yml +21 -0
  1158. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/presenter.rb +41 -0
  1159. data/lib/generators/lcp_ruby/templates/pages/model.rb +19 -0
  1160. data/lib/generators/lcp_ruby/templates/pages/permissions.yml +19 -0
  1161. data/lib/generators/lcp_ruby/templates/pages/presenter.rb +51 -0
  1162. data/lib/generators/lcp_ruby/templates/pages/view_group.rb +10 -0
  1163. data/lib/generators/lcp_ruby/templates/permission_source/model.rb +21 -0
  1164. data/lib/generators/lcp_ruby/templates/permission_source/permissions.yml +19 -0
  1165. data/lib/generators/lcp_ruby/templates/permission_source/presenter.rb +51 -0
  1166. data/lib/generators/lcp_ruby/templates/permission_source/view_group.rb +10 -0
  1167. data/lib/generators/lcp_ruby/templates/role_model/model.rb +24 -0
  1168. data/lib/generators/lcp_ruby/templates/role_model/permissions.yml +19 -0
  1169. data/lib/generators/lcp_ruby/templates/role_model/presenter.rb +62 -0
  1170. data/lib/generators/lcp_ruby/templates/role_model/view_group.rb +10 -0
  1171. data/lib/generators/lcp_ruby/templates/saved_filters/model.rb +51 -0
  1172. data/lib/generators/lcp_ruby/templates/saved_filters/permissions.yml +44 -0
  1173. data/lib/generators/lcp_ruby/templates/saved_filters/presenter.rb +96 -0
  1174. data/lib/generators/lcp_ruby/templates/saved_filters/save_dialog_presenter.rb +19 -0
  1175. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_model.rb +50 -0
  1176. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_permissions.yml +10 -0
  1177. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_presenter.rb +44 -0
  1178. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_view_group.rb +10 -0
  1179. data/lib/generators/lcp_ruby/templates/workflow_approvals/step_model.rb +36 -0
  1180. data/lib/generators/lcp_ruby/templates/workflow_approvals/step_permissions.yml +10 -0
  1181. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_model.rb +34 -0
  1182. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_permissions.yml +10 -0
  1183. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_presenter.rb +39 -0
  1184. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_view_group.rb +10 -0
  1185. data/lib/generators/lcp_ruby/templates/workflow_audit_log/model.rb +48 -0
  1186. data/lib/generators/lcp_ruby/templates/workflow_audit_log/permissions.yml +10 -0
  1187. data/lib/generators/lcp_ruby/templates/workflow_audit_log/presenter.rb +44 -0
  1188. data/lib/generators/lcp_ruby/templates/workflow_audit_log/view_group.rb +10 -0
  1189. data/lib/generators/lcp_ruby/templates/workflow_definition/model.rb +43 -0
  1190. data/lib/generators/lcp_ruby/templates/workflow_definition/permissions.yml +19 -0
  1191. data/lib/generators/lcp_ruby/templates/workflow_definition/presenter.rb +70 -0
  1192. data/lib/generators/lcp_ruby/templates/workflow_definition/view_group.rb +10 -0
  1193. data/lib/generators/lcp_ruby/workflow_approvals_generator.rb +93 -0
  1194. data/lib/generators/lcp_ruby/workflow_audit_log_generator.rb +54 -0
  1195. data/lib/generators/lcp_ruby/workflow_definition_generator.rb +77 -0
  1196. data/lib/lcp.rb +6 -0
  1197. data/lib/lcp_ruby/actions/action_executor.rb +66 -0
  1198. data/lib/lcp_ruby/actions/action_registry.rb +48 -0
  1199. data/lib/lcp_ruby/actions/api_tokens/revoke.rb +13 -0
  1200. data/lib/lcp_ruby/actions/base_action.rb +79 -0
  1201. data/lib/lcp_ruby/actions/form_action_pipeline.rb +138 -0
  1202. data/lib/lcp_ruby/aggregates/query_builder.rb +6 -0
  1203. data/lib/lcp_ruby/api_tokens/model_extension.rb +41 -0
  1204. data/lib/lcp_ruby/api_tokens/resolver_registry.rb +53 -0
  1205. data/lib/lcp_ruby/api_tokens/token_generator.rb +27 -0
  1206. data/lib/lcp_ruby/api_tokens/verifier.rb +38 -0
  1207. data/lib/lcp_ruby/app_template.rb +181 -0
  1208. data/lib/lcp_ruby/array_query.rb +120 -0
  1209. data/lib/lcp_ruby/asset_copier.rb +62 -0
  1210. data/lib/lcp_ruby/association_fk_type.rb +191 -0
  1211. data/lib/lcp_ruby/association_join_column.rb +28 -0
  1212. data/lib/lcp_ruby/association_options_builder.rb +231 -0
  1213. data/lib/lcp_ruby/auditing/audit_writer.rb +258 -0
  1214. data/lib/lcp_ruby/auditing/contract_validator.rb +95 -0
  1215. data/lib/lcp_ruby/auditing/registry.rb +29 -0
  1216. data/lib/lcp_ruby/auditing/setup.rb +49 -0
  1217. data/lib/lcp_ruby/authentication/audit_subscriber.rb +51 -0
  1218. data/lib/lcp_ruby/authentication/bearer_jwt_verifier.rb +139 -0
  1219. data/lib/lcp_ruby/authentication/devise_setup.rb +47 -0
  1220. data/lib/lcp_ruby/authentication/errors.rb +27 -0
  1221. data/lib/lcp_ruby/authentication/http_fetcher.rb +36 -0
  1222. data/lib/lcp_ruby/authentication/jwks_cache.rb +91 -0
  1223. data/lib/lcp_ruby/authentication/oidc_bearer_resolver.rb +84 -0
  1224. data/lib/lcp_ruby/authentication/omniauth_builder.rb +147 -0
  1225. data/lib/lcp_ruby/authentication/provider.rb +108 -0
  1226. data/lib/lcp_ruby/authentication/provider_registry.rb +227 -0
  1227. data/lib/lcp_ruby/authentication/role_mapper.rb +94 -0
  1228. data/lib/lcp_ruby/authentication/test_support.rb +257 -0
  1229. data/lib/lcp_ruby/authentication/user_resolver.rb +169 -0
  1230. data/lib/lcp_ruby/authentication.rb +40 -0
  1231. data/lib/lcp_ruby/authorization/association_lookup.rb +56 -0
  1232. data/lib/lcp_ruby/authorization/authorization_error.rb +12 -0
  1233. data/lib/lcp_ruby/authorization/cache.rb +89 -0
  1234. data/lib/lcp_ruby/authorization/codes.rb +17 -0
  1235. data/lib/lcp_ruby/authorization/impersonated_user.rb +29 -0
  1236. data/lib/lcp_ruby/authorization/includes_hint.rb +110 -0
  1237. data/lib/lcp_ruby/authorization/inherited_parent_validator.rb +142 -0
  1238. data/lib/lcp_ruby/authorization/invariant_check/configuration.rb +132 -0
  1239. data/lib/lcp_ruby/authorization/invariant_error.rb +15 -0
  1240. data/lib/lcp_ruby/authorization/misconfigured_page_error.rb +30 -0
  1241. data/lib/lcp_ruby/authorization/page_gate.rb +57 -0
  1242. data/lib/lcp_ruby/authorization/permission_evaluator.rb +343 -0
  1243. data/lib/lcp_ruby/authorization/policy_factory.rb +91 -0
  1244. data/lib/lcp_ruby/authorization/runtime_invariant_validator.rb +421 -0
  1245. data/lib/lcp_ruby/authorization/scope_builder.rb +227 -0
  1246. data/lib/lcp_ruby/authorization/scope_resolver.rb +28 -0
  1247. data/lib/lcp_ruby/authorized_controller.rb +44 -0
  1248. data/lib/lcp_ruby/background_jobs/base_handler.rb +113 -0
  1249. data/lib/lcp_ruby/background_jobs/change_handler.rb +17 -0
  1250. data/lib/lcp_ruby/background_jobs/contract.rb +16 -0
  1251. data/lib/lcp_ruby/background_jobs/contract_validator.rb +112 -0
  1252. data/lib/lcp_ruby/background_jobs/declarative/base_action.rb +11 -0
  1253. data/lib/lcp_ruby/background_jobs/declarative/call_webhook_action.rb +174 -0
  1254. data/lib/lcp_ruby/background_jobs/declarative/fire_event_action.rb +24 -0
  1255. data/lib/lcp_ruby/background_jobs/declarative/registry.rb +34 -0
  1256. data/lib/lcp_ruby/background_jobs/declarative/run_scope_action.rb +98 -0
  1257. data/lib/lcp_ruby/background_jobs/declarative/send_notification_action.rb +13 -0
  1258. data/lib/lcp_ruby/background_jobs/definition.rb +134 -0
  1259. data/lib/lcp_ruby/background_jobs/enqueue.rb +83 -0
  1260. data/lib/lcp_ruby/background_jobs/errors.rb +9 -0
  1261. data/lib/lcp_ruby/background_jobs/executor_job.rb +111 -0
  1262. data/lib/lcp_ruby/background_jobs/handler_factory.rb +46 -0
  1263. data/lib/lcp_ruby/background_jobs/host_source.rb +33 -0
  1264. data/lib/lcp_ruby/background_jobs/model_source.rb +93 -0
  1265. data/lib/lcp_ruby/background_jobs/registry.rb +81 -0
  1266. data/lib/lcp_ruby/background_jobs/resolver.rb +29 -0
  1267. data/lib/lcp_ruby/background_jobs/schedule_adapter.rb +14 -0
  1268. data/lib/lcp_ruby/background_jobs/setup.rb +145 -0
  1269. data/lib/lcp_ruby/background_jobs/static_source.rb +19 -0
  1270. data/lib/lcp_ruby/background_jobs/steps_executor.rb +52 -0
  1271. data/lib/lcp_ruby/background_jobs/triggers/event_trigger.rb +97 -0
  1272. data/lib/lcp_ruby/background_jobs/triggers/trigger_installer.rb +20 -0
  1273. data/lib/lcp_ruby/background_jobs/unique_key_builder.rb +31 -0
  1274. data/lib/lcp_ruby/batch_actions/base_service.rb +70 -0
  1275. data/lib/lcp_ruby/batch_actions/batch_action_handler.rb +200 -0
  1276. data/lib/lcp_ruby/batch_actions/custom_action_dispatcher.rb +133 -0
  1277. data/lib/lcp_ruby/batch_actions/destroy_service.rb +37 -0
  1278. data/lib/lcp_ruby/batch_actions/permanently_destroy_service.rb +33 -0
  1279. data/lib/lcp_ruby/batch_actions/restore_service.rb +33 -0
  1280. data/lib/lcp_ruby/batch_actions.rb +5 -0
  1281. data/lib/lcp_ruby/bulk_updater.rb +25 -0
  1282. data/lib/lcp_ruby/cli/docs_command.rb +29 -0
  1283. data/lib/lcp_ruby/cli/examples_command.rb +29 -0
  1284. data/lib/lcp_ruby/cli/new_command.rb +509 -0
  1285. data/lib/lcp_ruby/cli/run_command.rb +155 -0
  1286. data/lib/lcp_ruby/cli/skills_command.rb +54 -0
  1287. data/lib/lcp_ruby/cli.rb +74 -0
  1288. data/lib/lcp_ruby/condition_evaluator.rb +366 -0
  1289. data/lib/lcp_ruby/condition_service_registry.rb +58 -0
  1290. data/lib/lcp_ruby/condition_services/current_user_role.rb +28 -0
  1291. data/lib/lcp_ruby/condition_services/feature_flag.rb +63 -0
  1292. data/lib/lcp_ruby/condition_services/impersonating.rb +24 -0
  1293. data/lib/lcp_ruby/conditions/validator.rb +35 -0
  1294. data/lib/lcp_ruby/configuration.rb +431 -0
  1295. data/lib/lcp_ruby/controller/authentication.rb +118 -0
  1296. data/lib/lcp_ruby/controller/authorization.rb +198 -0
  1297. data/lib/lcp_ruby/controller/bearer_authentication.rb +76 -0
  1298. data/lib/lcp_ruby/controller/crud_helpers.rb +233 -0
  1299. data/lib/lcp_ruby/controller/error_handling.rb +94 -0
  1300. data/lib/lcp_ruby/controller/impersonation.rb +70 -0
  1301. data/lib/lcp_ruby/controller/locale_binding.rb +62 -0
  1302. data/lib/lcp_ruby/controller/path_helpers.rb +125 -0
  1303. data/lib/lcp_ruby/controller/presenter_setup.rb +89 -0
  1304. data/lib/lcp_ruby/controller/search.rb +321 -0
  1305. data/lib/lcp_ruby/controller/view_helpers.rb +105 -0
  1306. data/lib/lcp_ruby/current.rb +13 -0
  1307. data/lib/lcp_ruby/custom_fields/applicator.rb +194 -0
  1308. data/lib/lcp_ruby/custom_fields/contract_validator.rb +77 -0
  1309. data/lib/lcp_ruby/custom_fields/definition_change_handler.rb +21 -0
  1310. data/lib/lcp_ruby/custom_fields/query.rb +112 -0
  1311. data/lib/lcp_ruby/custom_fields/registry.rb +70 -0
  1312. data/lib/lcp_ruby/custom_fields/setup.rb +58 -0
  1313. data/lib/lcp_ruby/custom_fields/utils.rb +40 -0
  1314. data/lib/lcp_ruby/custom_fields.rb +9 -0
  1315. data/lib/lcp_ruby/data_source/api_error_placeholder.rb +47 -0
  1316. data/lib/lcp_ruby/data_source/api_filter_translator.rb +72 -0
  1317. data/lib/lcp_ruby/data_source/api_model_concern.rb +131 -0
  1318. data/lib/lcp_ruby/data_source/api_preloader.rb +44 -0
  1319. data/lib/lcp_ruby/data_source/base.rb +85 -0
  1320. data/lib/lcp_ruby/data_source/cached_wrapper.rb +107 -0
  1321. data/lib/lcp_ruby/data_source/host.rb +71 -0
  1322. data/lib/lcp_ruby/data_source/registry.rb +39 -0
  1323. data/lib/lcp_ruby/data_source/resilient_wrapper.rb +67 -0
  1324. data/lib/lcp_ruby/data_source/rest_json.rb +247 -0
  1325. data/lib/lcp_ruby/data_source/setup.rb +57 -0
  1326. data/lib/lcp_ruby/dev_toolbar.rb +8 -0
  1327. data/lib/lcp_ruby/display/base_renderer.rb +21 -0
  1328. data/lib/lcp_ruby/display/count_badge.rb +11 -0
  1329. data/lib/lcp_ruby/display/icon_badge.rb +17 -0
  1330. data/lib/lcp_ruby/display/renderer_registry.rb +138 -0
  1331. data/lib/lcp_ruby/display/renderers/attachment_link.rb +26 -0
  1332. data/lib/lcp_ruby/display/renderers/attachment_list.rb +32 -0
  1333. data/lib/lcp_ruby/display/renderers/attachment_preview.rb +26 -0
  1334. data/lib/lcp_ruby/display/renderers/avatar.rb +14 -0
  1335. data/lib/lcp_ruby/display/renderers/badge.rb +43 -0
  1336. data/lib/lcp_ruby/display/renderers/boolean_icon.rb +54 -0
  1337. data/lib/lcp_ruby/display/renderers/code.rb +39 -0
  1338. data/lib/lcp_ruby/display/renderers/collection.rb +34 -0
  1339. data/lib/lcp_ruby/display/renderers/color_swatch.rb +25 -0
  1340. data/lib/lcp_ruby/display/renderers/concerns/attachment_helpers.rb +73 -0
  1341. data/lib/lcp_ruby/display/renderers/concerns/workflow_helpers.rb +35 -0
  1342. data/lib/lcp_ruby/display/renderers/copy_code.rb +33 -0
  1343. data/lib/lcp_ruby/display/renderers/currency.rb +14 -0
  1344. data/lib/lcp_ruby/display/renderers/date.rb +17 -0
  1345. data/lib/lcp_ruby/display/renderers/datetime.rb +17 -0
  1346. data/lib/lcp_ruby/display/renderers/email_link.rb +15 -0
  1347. data/lib/lcp_ruby/display/renderers/file_size.rb +11 -0
  1348. data/lib/lcp_ruby/display/renderers/heading.rb +11 -0
  1349. data/lib/lcp_ruby/display/renderers/image.rb +17 -0
  1350. data/lib/lcp_ruby/display/renderers/internal_link.rb +23 -0
  1351. data/lib/lcp_ruby/display/renderers/link.rb +15 -0
  1352. data/lib/lcp_ruby/display/renderers/link_list.rb +90 -0
  1353. data/lib/lcp_ruby/display/renderers/markdown.rb +33 -0
  1354. data/lib/lcp_ruby/display/renderers/number.rb +14 -0
  1355. data/lib/lcp_ruby/display/renderers/percentage.rb +12 -0
  1356. data/lib/lcp_ruby/display/renderers/phone_link.rb +15 -0
  1357. data/lib/lcp_ruby/display/renderers/progress_bar.rb +15 -0
  1358. data/lib/lcp_ruby/display/renderers/rating.rb +15 -0
  1359. data/lib/lcp_ruby/display/renderers/record_link.rb +101 -0
  1360. data/lib/lcp_ruby/display/renderers/relative_date.rb +15 -0
  1361. data/lib/lcp_ruby/display/renderers/rich_text.rb +15 -0
  1362. data/lib/lcp_ruby/display/renderers/text.rb +12 -0
  1363. data/lib/lcp_ruby/display/renderers/truncate.rb +17 -0
  1364. data/lib/lcp_ruby/display/renderers/url_link.rb +22 -0
  1365. data/lib/lcp_ruby/display/renderers/workflow_badge.rb +37 -0
  1366. data/lib/lcp_ruby/display/renderers/workflow_timeline.rb +173 -0
  1367. data/lib/lcp_ruby/display/renderers.rb +3 -0
  1368. data/lib/lcp_ruby/display/text_badge.rb +15 -0
  1369. data/lib/lcp_ruby/dsl/condition_builder.rb +190 -0
  1370. data/lib/lcp_ruby/dsl/dsl_loader.rb +365 -0
  1371. data/lib/lcp_ruby/dsl/field_builder.rb +35 -0
  1372. data/lib/lcp_ruby/dsl/job_builder.rb +92 -0
  1373. data/lib/lcp_ruby/dsl/model_builder.rb +544 -0
  1374. data/lib/lcp_ruby/dsl/presenter_builder.rb +1272 -0
  1375. data/lib/lcp_ruby/dsl/source_location_capture.rb +52 -0
  1376. data/lib/lcp_ruby/dsl/type_builder.rb +88 -0
  1377. data/lib/lcp_ruby/dsl/view_group_builder.rb +92 -0
  1378. data/lib/lcp_ruby/dsl/workflow_builder.rb +319 -0
  1379. data/lib/lcp_ruby/dynamic.rb +7 -0
  1380. data/lib/lcp_ruby/dynamic_references/resolver.rb +154 -0
  1381. data/lib/lcp_ruby/dynamic_references/validator.rb +92 -0
  1382. data/lib/lcp_ruby/embed_providers/base.rb +18 -0
  1383. data/lib/lcp_ruby/embed_providers/grafana.rb +38 -0
  1384. data/lib/lcp_ruby/embed_providers/metabase.rb +37 -0
  1385. data/lib/lcp_ruby/engine.rb +680 -0
  1386. data/lib/lcp_ruby/events/async_handler_job.rb +21 -0
  1387. data/lib/lcp_ruby/events/dispatcher.rb +52 -0
  1388. data/lib/lcp_ruby/events/handler_base.rb +51 -0
  1389. data/lib/lcp_ruby/events/handler_registry.rb +49 -0
  1390. data/lib/lcp_ruby/export/data_generator.rb +158 -0
  1391. data/lib/lcp_ruby/export/export_handler.rb +315 -0
  1392. data/lib/lcp_ruby/export/field_tree_builder.rb +219 -0
  1393. data/lib/lcp_ruby/export/setup.rb +94 -0
  1394. data/lib/lcp_ruby/export/value_formatter.rb +223 -0
  1395. data/lib/lcp_ruby/export.rb +9 -0
  1396. data/lib/lcp_ruby/gem_paths.rb +51 -0
  1397. data/lib/lcp_ruby/generators/entity_menu_writer.rb +258 -0
  1398. data/lib/lcp_ruby/generators/feature_registry.rb +208 -0
  1399. data/lib/lcp_ruby/generators/prerequisites.rb +90 -0
  1400. data/lib/lcp_ruby/grouped_query/builder.rb +206 -0
  1401. data/lib/lcp_ruby/grouped_query/result_wrapper.rb +72 -0
  1402. data/lib/lcp_ruby/grouped_query/row.rb +31 -0
  1403. data/lib/lcp_ruby/groups/change_handler.rb +18 -0
  1404. data/lib/lcp_ruby/groups/contract.rb +42 -0
  1405. data/lib/lcp_ruby/groups/contract_validator.rb +110 -0
  1406. data/lib/lcp_ruby/groups/host_loader.rb +54 -0
  1407. data/lib/lcp_ruby/groups/model_loader.rb +186 -0
  1408. data/lib/lcp_ruby/groups/registry.rb +113 -0
  1409. data/lib/lcp_ruby/groups/setup.rb +129 -0
  1410. data/lib/lcp_ruby/groups/yaml_loader.rb +97 -0
  1411. data/lib/lcp_ruby/hash_utils.rb +42 -0
  1412. data/lib/lcp_ruby/i18n_check/configuration.rb +104 -0
  1413. data/lib/lcp_ruby/i18n_check/heuristics.rb +26 -0
  1414. data/lib/lcp_ruby/i18n_check/key_deriver.rb +136 -0
  1415. data/lib/lcp_ruby/i18n_check/offense.rb +29 -0
  1416. data/lib/lcp_ruby/i18n_check/registry_walker.rb +621 -0
  1417. data/lib/lcp_ruby/i18n_check/reporter.rb +96 -0
  1418. data/lib/lcp_ruby/i18n_check/runner.rb +46 -0
  1419. data/lib/lcp_ruby/i18n_check.rb +15 -0
  1420. data/lib/lcp_ruby/i18n_lint.rb +145 -0
  1421. data/lib/lcp_ruby/import/auto_mapper.rb +98 -0
  1422. data/lib/lcp_ruby/import/field_tree_builder.rb +178 -0
  1423. data/lib/lcp_ruby/import/file_parser.rb +223 -0
  1424. data/lib/lcp_ruby/import/import_dialog_handler.rb +410 -0
  1425. data/lib/lcp_ruby/import/import_job_handler.rb +224 -0
  1426. data/lib/lcp_ruby/import/row_processor.rb +281 -0
  1427. data/lib/lcp_ruby/import/setup.rb +277 -0
  1428. data/lib/lcp_ruby/import/value_coercer.rb +143 -0
  1429. data/lib/lcp_ruby/import.rb +14 -0
  1430. data/lib/lcp_ruby/json_item_wrapper.rb +152 -0
  1431. data/lib/lcp_ruby/kanban/board.rb +28 -0
  1432. data/lib/lcp_ruby/kanban/column.rb +28 -0
  1433. data/lib/lcp_ruby/kanban/default_provider.rb +376 -0
  1434. data/lib/lcp_ruby/kanban/host_provider.rb +94 -0
  1435. data/lib/lcp_ruby/kanban/move_result.rb +52 -0
  1436. data/lib/lcp_ruby/kanban/provider_test_harness.rb +54 -0
  1437. data/lib/lcp_ruby/kanban/swimlane.rb +21 -0
  1438. data/lib/lcp_ruby/menu.rb +46 -0
  1439. data/lib/lcp_ruby/metadata/aggregate_definition.rb +6 -0
  1440. data/lib/lcp_ruby/metadata/association_definition.rb +196 -0
  1441. data/lib/lcp_ruby/metadata/auth_validator.rb +222 -0
  1442. data/lib/lcp_ruby/metadata/configuration_validator.rb +7958 -0
  1443. data/lib/lcp_ruby/metadata/contract_result.rb +9 -0
  1444. data/lib/lcp_ruby/metadata/display_template_definition.rb +77 -0
  1445. data/lib/lcp_ruby/metadata/enum_label_resolver.rb +27 -0
  1446. data/lib/lcp_ruby/metadata/erd_generator.rb +274 -0
  1447. data/lib/lcp_ruby/metadata/event_definition.rb +55 -0
  1448. data/lib/lcp_ruby/metadata/field_definition.rb +267 -0
  1449. data/lib/lcp_ruby/metadata/group_definition.rb +31 -0
  1450. data/lib/lcp_ruby/metadata/i18n_label.rb +29 -0
  1451. data/lib/lcp_ruby/metadata/loader.rb +916 -0
  1452. data/lib/lcp_ruby/metadata/menu_definition.rb +116 -0
  1453. data/lib/lcp_ruby/metadata/menu_item.rb +792 -0
  1454. data/lib/lcp_ruby/metadata/menu_item_resolver.rb +105 -0
  1455. data/lib/lcp_ruby/metadata/model_definition.rb +612 -0
  1456. data/lib/lcp_ruby/metadata/model_hash_merger.rb +88 -0
  1457. data/lib/lcp_ruby/metadata/model_inheritance_resolver.rb +165 -0
  1458. data/lib/lcp_ruby/metadata/page_definition.rb +245 -0
  1459. data/lib/lcp_ruby/metadata/path_template.rb +231 -0
  1460. data/lib/lcp_ruby/metadata/permission_definition.rb +237 -0
  1461. data/lib/lcp_ruby/metadata/permission_merger.rb +81 -0
  1462. data/lib/lcp_ruby/metadata/presenter_definition.rb +689 -0
  1463. data/lib/lcp_ruby/metadata/reserved_names.rb +79 -0
  1464. data/lib/lcp_ruby/metadata/responsive_policy.rb +95 -0
  1465. data/lib/lcp_ruby/metadata/schema_validator.rb +172 -0
  1466. data/lib/lcp_ruby/metadata/validation_definition.rb +69 -0
  1467. data/lib/lcp_ruby/metadata/view_group_definition.rb +208 -0
  1468. data/lib/lcp_ruby/metadata/virtual_column_definition.rb +154 -0
  1469. data/lib/lcp_ruby/metadata/zone_definition.rb +423 -0
  1470. data/lib/lcp_ruby/metrics/collector.rb +123 -0
  1471. data/lib/lcp_ruby/metrics/collector_registry.rb +57 -0
  1472. data/lib/lcp_ruby/metrics/error_recorder.rb +70 -0
  1473. data/lib/lcp_ruby/metrics/fingerprint.rb +33 -0
  1474. data/lib/lcp_ruby/metrics/json_query.rb +47 -0
  1475. data/lib/lcp_ruby/metrics/metric_definitions.rb +105 -0
  1476. data/lib/lcp_ruby/metrics/prometheus_check.rb +9 -0
  1477. data/lib/lcp_ruby/metrics/rate_limiter.rb +99 -0
  1478. data/lib/lcp_ruby/metrics/setup.rb +71 -0
  1479. data/lib/lcp_ruby/metrics/subscriber.rb +126 -0
  1480. data/lib/lcp_ruby/model_factory/aggregate_applicator.rb +14 -0
  1481. data/lib/lcp_ruby/model_factory/api_association_applicator.rb +119 -0
  1482. data/lib/lcp_ruby/model_factory/api_builder.rb +85 -0
  1483. data/lib/lcp_ruby/model_factory/array_type.rb +78 -0
  1484. data/lib/lcp_ruby/model_factory/array_type_applicator.rb +33 -0
  1485. data/lib/lcp_ruby/model_factory/association_applicator.rb +201 -0
  1486. data/lib/lcp_ruby/model_factory/attachment_applicator.rb +160 -0
  1487. data/lib/lcp_ruby/model_factory/auditing_applicator.rb +72 -0
  1488. data/lib/lcp_ruby/model_factory/builder.rb +235 -0
  1489. data/lib/lcp_ruby/model_factory/callback_applicator.rb +63 -0
  1490. data/lib/lcp_ruby/model_factory/computed_applicator.rb +55 -0
  1491. data/lib/lcp_ruby/model_factory/default_applicator.rb +85 -0
  1492. data/lib/lcp_ruby/model_factory/enum_applicator.rb +24 -0
  1493. data/lib/lcp_ruby/model_factory/inherited_parent_validator_applicator.rb +39 -0
  1494. data/lib/lcp_ruby/model_factory/label_method_builder.rb +82 -0
  1495. data/lib/lcp_ruby/model_factory/managed_tracking.rb +71 -0
  1496. data/lib/lcp_ruby/model_factory/positioning_applicator.rb +23 -0
  1497. data/lib/lcp_ruby/model_factory/ransack_applicator.rb +66 -0
  1498. data/lib/lcp_ruby/model_factory/registry.rb +33 -0
  1499. data/lib/lcp_ruby/model_factory/schema_manager.rb +655 -0
  1500. data/lib/lcp_ruby/model_factory/scope_applicator.rb +87 -0
  1501. data/lib/lcp_ruby/model_factory/sequence_applicator.rb +173 -0
  1502. data/lib/lcp_ruby/model_factory/service_accessor_applicator.rb +40 -0
  1503. data/lib/lcp_ruby/model_factory/soft_delete_applicator.rb +141 -0
  1504. data/lib/lcp_ruby/model_factory/transform_applicator.rb +51 -0
  1505. data/lib/lcp_ruby/model_factory/tree_applicator.rb +239 -0
  1506. data/lib/lcp_ruby/model_factory/userstamps_applicator.rb +73 -0
  1507. data/lib/lcp_ruby/model_factory/validation_applicator.rb +319 -0
  1508. data/lib/lcp_ruby/model_factory/virtual_column_applicator.rb +79 -0
  1509. data/lib/lcp_ruby/model_factory/workflow_applicator.rb +141 -0
  1510. data/lib/lcp_ruby/pages/change_handler.rb +15 -0
  1511. data/lib/lcp_ruby/pages/contract_validator.rb +74 -0
  1512. data/lib/lcp_ruby/pages/definition_validator.rb +42 -0
  1513. data/lib/lcp_ruby/pages/filter_form.rb +200 -0
  1514. data/lib/lcp_ruby/pages/filter_form_validator.rb +636 -0
  1515. data/lib/lcp_ruby/pages/registry.rb +133 -0
  1516. data/lib/lcp_ruby/pages/resolver.rb +32 -0
  1517. data/lib/lcp_ruby/pages/scope_context_resolver.rb +37 -0
  1518. data/lib/lcp_ruby/pages/scope_filter_set.rb +57 -0
  1519. data/lib/lcp_ruby/pages/setup.rb +46 -0
  1520. data/lib/lcp_ruby/path_utils.rb +12 -0
  1521. data/lib/lcp_ruby/permissions/change_handler.rb +22 -0
  1522. data/lib/lcp_ruby/permissions/contract_validator.rb +74 -0
  1523. data/lib/lcp_ruby/permissions/definition_validator.rb +119 -0
  1524. data/lib/lcp_ruby/permissions/registry.rb +135 -0
  1525. data/lib/lcp_ruby/permissions/setup.rb +51 -0
  1526. data/lib/lcp_ruby/permissions/source_resolver.rb +56 -0
  1527. data/lib/lcp_ruby/presenter/action_set.rb +236 -0
  1528. data/lib/lcp_ruby/presenter/breadcrumb_builder.rb +183 -0
  1529. data/lib/lcp_ruby/presenter/breadcrumb_path_helper.rb +17 -0
  1530. data/lib/lcp_ruby/presenter/column_set.rb +268 -0
  1531. data/lib/lcp_ruby/presenter/enrichment.rb +136 -0
  1532. data/lib/lcp_ruby/presenter/field_value_resolver.rb +237 -0
  1533. data/lib/lcp_ruby/presenter/includes_resolver/association_dependency.rb +59 -0
  1534. data/lib/lcp_ruby/presenter/includes_resolver/dependency_collector.rb +394 -0
  1535. data/lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb +70 -0
  1536. data/lib/lcp_ruby/presenter/includes_resolver/strategy_resolver.rb +123 -0
  1537. data/lib/lcp_ruby/presenter/includes_resolver.rb +42 -0
  1538. data/lib/lcp_ruby/presenter/layout_builder.rb +467 -0
  1539. data/lib/lcp_ruby/presenter/link_resolver.rb +65 -0
  1540. data/lib/lcp_ruby/presenter/metadata_lookup.rb +28 -0
  1541. data/lib/lcp_ruby/presenter/resolver.rb +25 -0
  1542. data/lib/lcp_ruby/record_aliases/metadata_checker.rb +213 -0
  1543. data/lib/lcp_ruby/record_aliases/setup.rb +212 -0
  1544. data/lib/lcp_ruby/reserved_route_segments.rb +37 -0
  1545. data/lib/lcp_ruby/roles/change_handler.rb +11 -0
  1546. data/lib/lcp_ruby/roles/contract_validator.rb +67 -0
  1547. data/lib/lcp_ruby/roles/registry.rb +89 -0
  1548. data/lib/lcp_ruby/roles/setup.rb +50 -0
  1549. data/lib/lcp_ruby/routing/presenter_routes.rb +104 -0
  1550. data/lib/lcp_ruby/saved_filters/change_handler.rb +13 -0
  1551. data/lib/lcp_ruby/saved_filters/contract_validator.rb +85 -0
  1552. data/lib/lcp_ruby/saved_filters/registry.rb +36 -0
  1553. data/lib/lcp_ruby/saved_filters/resolver.rb +108 -0
  1554. data/lib/lcp_ruby/saved_filters/setup.rb +42 -0
  1555. data/lib/lcp_ruby/saved_filters/stale_field_validator.rb +84 -0
  1556. data/lib/lcp_ruby/schemas/auth.json +208 -0
  1557. data/lib/lcp_ruby/schemas/menu.json +338 -0
  1558. data/lib/lcp_ruby/schemas/model.json +1161 -0
  1559. data/lib/lcp_ruby/schemas/page.json +877 -0
  1560. data/lib/lcp_ruby/schemas/permission.json +454 -0
  1561. data/lib/lcp_ruby/schemas/presenter.json +2274 -0
  1562. data/lib/lcp_ruby/schemas/theme.json +62 -0
  1563. data/lib/lcp_ruby/schemas/type.json +146 -0
  1564. data/lib/lcp_ruby/schemas/view_group.json +163 -0
  1565. data/lib/lcp_ruby/search/custom_field_filter.rb +171 -0
  1566. data/lib/lcp_ruby/search/custom_filter_interceptor.rb +40 -0
  1567. data/lib/lcp_ruby/search/filter_metadata_builder.rb +409 -0
  1568. data/lib/lcp_ruby/search/filter_param_builder.rb +177 -0
  1569. data/lib/lcp_ruby/search/operator_registry.rb +79 -0
  1570. data/lib/lcp_ruby/search/param_sanitizer.rb +25 -0
  1571. data/lib/lcp_ruby/search/parameter_definition.rb +187 -0
  1572. data/lib/lcp_ruby/search/parameterized_scope_applicator.rb +129 -0
  1573. data/lib/lcp_ruby/search/query_builder.rb +143 -0
  1574. data/lib/lcp_ruby/search/query_language_parser.rb +549 -0
  1575. data/lib/lcp_ruby/search/query_language_serializer.rb +193 -0
  1576. data/lib/lcp_ruby/search/quick_search.rb +162 -0
  1577. data/lib/lcp_ruby/search/relative_date_expander.rb +57 -0
  1578. data/lib/lcp_ruby/search_result.rb +70 -0
  1579. data/lib/lcp_ruby/sequences/sequence_manager.rb +51 -0
  1580. data/lib/lcp_ruby/services/accessors/json_field.rb +23 -0
  1581. data/lib/lcp_ruby/services/built_in_accessors.rb +17 -0
  1582. data/lib/lcp_ruby/services/built_in_defaults.rb +22 -0
  1583. data/lib/lcp_ruby/services/built_in_transforms.rb +20 -0
  1584. data/lib/lcp_ruby/services/checker.rb +133 -0
  1585. data/lib/lcp_ruby/services/registry.rb +83 -0
  1586. data/lib/lcp_ruby/skills_installer.rb +73 -0
  1587. data/lib/lcp_ruby/sort/enum_sort_order.rb +38 -0
  1588. data/lib/lcp_ruby/tasks/destroy_order_resolver.rb +57 -0
  1589. data/lib/lcp_ruby/tasks/doctor.rb +294 -0
  1590. data/lib/lcp_ruby/tasks/permission_resolve_formatter.rb +245 -0
  1591. data/lib/lcp_ruby/types/built_in_types.rb +157 -0
  1592. data/lib/lcp_ruby/types/transforms/base_transform.rb +11 -0
  1593. data/lib/lcp_ruby/types/transforms/downcase.rb +11 -0
  1594. data/lib/lcp_ruby/types/transforms/normalize_phone.rb +19 -0
  1595. data/lib/lcp_ruby/types/transforms/normalize_url.rb +16 -0
  1596. data/lib/lcp_ruby/types/transforms/strip.rb +11 -0
  1597. data/lib/lcp_ruby/types/type_definition.rb +112 -0
  1598. data/lib/lcp_ruby/types/type_registry.rb +75 -0
  1599. data/lib/lcp_ruby/url_safety.rb +97 -0
  1600. data/lib/lcp_ruby/user_snapshot.rb +15 -0
  1601. data/lib/lcp_ruby/version.rb +3 -0
  1602. data/lib/lcp_ruby/view_slots/registry.rb +71 -0
  1603. data/lib/lcp_ruby/view_slots/slot_component.rb +22 -0
  1604. data/lib/lcp_ruby/view_slots/slot_context.rb +20 -0
  1605. data/lib/lcp_ruby/virtual_columns/builder.rb +234 -0
  1606. data/lib/lcp_ruby/virtual_columns/collector.rb +186 -0
  1607. data/lib/lcp_ruby/virtual_columns.rb +4 -0
  1608. data/lib/lcp_ruby/virtual_fields/synthetic_marker.rb +17 -0
  1609. data/lib/lcp_ruby/virtual_fields/types/array_of.rb +49 -0
  1610. data/lib/lcp_ruby/virtual_fields/virtual_field.rb +107 -0
  1611. data/lib/lcp_ruby/virtual_fields/virtual_form.rb +144 -0
  1612. data/lib/lcp_ruby/widgets/chart_palette.rb +25 -0
  1613. data/lib/lcp_ruby/widgets/chartkick_check.rb +9 -0
  1614. data/lib/lcp_ruby/widgets/data_resolver.rb +676 -0
  1615. data/lib/lcp_ruby/widgets/date_grouper.rb +54 -0
  1616. data/lib/lcp_ruby/widgets/presenter_zone_resolver.rb +170 -0
  1617. data/lib/lcp_ruby/widgets/record_source_resolver.rb +56 -0
  1618. data/lib/lcp_ruby/widgets/scope_applicator.rb +187 -0
  1619. data/lib/lcp_ruby/workflow/approval/activation_handler.rb +39 -0
  1620. data/lib/lcp_ruby/workflow/approval/approval_definition.rb +117 -0
  1621. data/lib/lcp_ruby/workflow/approval/approver_resolver.rb +98 -0
  1622. data/lib/lcp_ruby/workflow/approval/cleanup_handler.rb +37 -0
  1623. data/lib/lcp_ruby/workflow/approval/contract_validator.rb +96 -0
  1624. data/lib/lcp_ruby/workflow/approval/data_builder.rb +53 -0
  1625. data/lib/lcp_ruby/workflow/approval/discard_handler.rb +51 -0
  1626. data/lib/lcp_ruby/workflow/approval/engine.rb +314 -0
  1627. data/lib/lcp_ruby/workflow/approval/registry.rb +40 -0
  1628. data/lib/lcp_ruby/workflow/approval/resolution_handler.rb +103 -0
  1629. data/lib/lcp_ruby/workflow/approval/setup.rb +138 -0
  1630. data/lib/lcp_ruby/workflow/approval/step_definition.rb +52 -0
  1631. data/lib/lcp_ruby/workflow/approval/step_evaluator.rb +163 -0
  1632. data/lib/lcp_ruby/workflow/approval/system_evaluator.rb +29 -0
  1633. data/lib/lcp_ruby/workflow/approval/task_manager.rb +202 -0
  1634. data/lib/lcp_ruby/workflow/audit_contract_validator.rb +64 -0
  1635. data/lib/lcp_ruby/workflow/audit_registry.rb +24 -0
  1636. data/lib/lcp_ruby/workflow/audit_writer.rb +51 -0
  1637. data/lib/lcp_ruby/workflow/change_handler.rb +14 -0
  1638. data/lib/lcp_ruby/workflow/contract.rb +21 -0
  1639. data/lib/lcp_ruby/workflow/contract_validator.rb +44 -0
  1640. data/lib/lcp_ruby/workflow/errors.rb +12 -0
  1641. data/lib/lcp_ruby/workflow/host_source.rb +19 -0
  1642. data/lib/lcp_ruby/workflow/mermaid_builder.rb +217 -0
  1643. data/lib/lcp_ruby/workflow/model_source.rb +79 -0
  1644. data/lib/lcp_ruby/workflow/registry.rb +113 -0
  1645. data/lib/lcp_ruby/workflow/resolver.rb +32 -0
  1646. data/lib/lcp_ruby/workflow/setup.rb +135 -0
  1647. data/lib/lcp_ruby/workflow/state_definition.rb +59 -0
  1648. data/lib/lcp_ruby/workflow/state_machine.rb +78 -0
  1649. data/lib/lcp_ruby/workflow/static_source.rb +20 -0
  1650. data/lib/lcp_ruby/workflow/transition_action_builder.rb +46 -0
  1651. data/lib/lcp_ruby/workflow/transition_definition.rb +70 -0
  1652. data/lib/lcp_ruby/workflow/transition_executor.rb +140 -0
  1653. data/lib/lcp_ruby/workflow/transition_label_resolver.rb +21 -0
  1654. data/lib/lcp_ruby/workflow/transition_result.rb +20 -0
  1655. data/lib/lcp_ruby/workflow/value_resolver.rb +58 -0
  1656. data/lib/lcp_ruby/workflow/workflow_definition.rb +195 -0
  1657. data/lib/lcp_ruby.rb +764 -0
  1658. data/lib/rubocop/cop/lcp_ruby/no_hardcoded_i18n_string.rb +249 -0
  1659. data/lib/tasks/lcp_ruby.rake +432 -0
  1660. data/lib/tasks/lcp_ruby_assets.rake +37 -0
  1661. data/lib/tasks/lcp_ruby_auth.rake +49 -0
  1662. data/lib/tasks/lcp_ruby_db.rake +76 -0
  1663. data/lib/tasks/lcp_ruby_doctor.rake +20 -0
  1664. data/lib/tasks/lcp_ruby_feature_catalog.rake +61 -0
  1665. data/lib/tasks/lcp_ruby_gapfree_sequences.rake +39 -0
  1666. data/lib/tasks/lcp_ruby_i18n_check.rake +23 -0
  1667. data/lib/tasks/lcp_ruby_i18n_lint.rake +20 -0
  1668. data/lib/tasks/lcp_ruby_invariant_check.rake +72 -0
  1669. data/vendor/assets/javascripts/lcp_ruby/activestorage.min.js +866 -0
  1670. data/vendor/assets/javascripts/lcp_ruby/highlight.min.js +1244 -0
  1671. data/vendor/assets/javascripts/lcp_ruby/lucide.min.js +12 -0
  1672. data/vendor/assets/javascripts/lcp_ruby/stimulus.umd.js +2588 -0
  1673. data/vendor/assets/javascripts/lcp_ruby/tom-select.complete.min.js +444 -0
  1674. data/vendor/assets/stylesheets/lcp_ruby/highlight-github.min.css +12 -0
  1675. data/vendor/assets/stylesheets/lcp_ruby/tom-select.css +412 -0
  1676. metadata +1950 -0
data/config/routes.rb ADDED
@@ -0,0 +1,119 @@
1
+ LcpRuby::Engine.routes.draw do
2
+ # Devise routes are always mounted so URL helpers stay available regardless
3
+ # of mode; controllers gate access via require_session_based_auth!.
4
+ devise_for :users,
5
+ class_name: "LcpRuby::User",
6
+ module: "lcp_ruby/auth",
7
+ path: "auth",
8
+ router_name: :lcp_ruby,
9
+ path_names: {
10
+ sign_in: "login",
11
+ sign_out: "logout",
12
+ sign_up: "register",
13
+ password: "password"
14
+ }
15
+
16
+ # OIDC endpoints — only drawn when at least one :oidc provider is configured
17
+ # in config/lcp_ruby/auth.yml. OmniAuth 2.0 requires POST on the request phase
18
+ # for CSRF protection; the login view initiates provider sign-in via button_to.
19
+ if LcpRuby::Authentication::ProviderRegistry.oidc_enabled?
20
+ scope "auth", controller: "auth/callbacks" do
21
+ provider_constraint = { provider: /[a-z0-9_]+/ }
22
+ post ":provider", action: :passthru, as: :oidc_start, constraints: provider_constraint
23
+ match ":provider/callback", action: :callback, as: :oidc_callback, constraints: provider_constraint, via: %i[get post]
24
+ get "failure", action: :failure, as: :oidc_failure
25
+ end
26
+ end
27
+
28
+ get "lcp_health", to: "health#show", as: :health_check if LcpRuby.configuration.health_check
29
+ get "metrics", to: "metrics#show", as: :metrics if LcpRuby.configuration.metrics_endpoint
30
+
31
+ get "/_dev/metadata", to: "dev_toolbar#metadata", as: :dev_toolbar_metadata
32
+
33
+ get "/", to: "landing#show", as: :landing
34
+
35
+ post "impersonate", to: "impersonation#create", as: :impersonate
36
+ delete "impersonate", to: "impersonation#destroy", as: :stop_impersonate
37
+
38
+ scope "lcp_dialog/:page_name" do
39
+ get "/new", to: "dialogs#new", as: :dialog_new
40
+ post "/", to: "dialogs#create", as: :dialog_create
41
+ get "/:id/edit", to: "dialogs#edit", as: :dialog_edit
42
+ patch "/:id", to: "dialogs#update", as: :dialog_update
43
+ end
44
+
45
+ # Per-presenter routes for presenters with controller: or action_controllers:.
46
+ # Drawn before the catch-all so explicit slug routes take precedence.
47
+ LcpRuby::Routing::PresenterRoutes.draw_custom_controller_routes(self)
48
+
49
+ # Slug constraint rejects asset paths (`favicon.ico`, …) at the routing layer.
50
+ # Format whitelist accepts REST-style suffixes for data formats only.
51
+ # NOTE: do NOT add `\A…\z` anchors to the format regex — Rails embeds it into
52
+ # a larger pattern and the anchors break format extraction. Rails anchors
53
+ # implicitly; the `.jsonp`-style partial-match guard test in
54
+ # spec/integration/asset_route_passthrough_spec.rb keeps that invariant.
55
+ # Asset paths that slip through (e.g. `manifest.json`, slug=manifest) are
56
+ # caught downstream by `rescue_from MetadataError` in ErrorHandling.
57
+ scope ":lcp_slug",
58
+ constraints: { lcp_slug: %r{[^/.]+} },
59
+ format: /(?:json|csv|xml)/ do
60
+ # Saved filters API (must precede /:id to avoid matching "saved-filters" as id)
61
+ scope "saved-filters", as: :saved_filters do
62
+ get "/", to: "saved_filters#index"
63
+ post "/", to: "saved_filters#create"
64
+ patch "/:id", to: "saved_filters#update", as: :update
65
+ delete "/:id", to: "saved_filters#destroy", as: :destroy
66
+ end
67
+
68
+ # Custom fields management (must precede /:id to avoid matching "custom-fields" as id)
69
+ scope "custom-fields", as: :custom_fields do
70
+ get "/", to: "custom_fields#index"
71
+ get "/manage", to: "custom_fields#manage", as: :manage
72
+ patch "/manage", to: "custom_fields#bulk_update", as: :bulk_update
73
+ get "/new", to: "custom_fields#new", as: :new
74
+ post "/", to: "custom_fields#create"
75
+ get "/:id", to: "custom_fields#show", as: :show
76
+ get "/:id/edit", to: "custom_fields#edit", as: :edit
77
+ patch "/:id", to: "custom_fields#update", as: :update
78
+ put "/:id", to: "custom_fields#update"
79
+ delete "/:id", to: "custom_fields#destroy", as: :destroy
80
+ end
81
+
82
+ post "/parse_ql", to: "resources#parse_ql", as: :parse_ql
83
+ get "/filter_fields", to: "resources#filter_fields", as: :filter_fields
84
+ get "/batch_count", to: "resources#batch_count", as: :batch_count
85
+ get "/export_fields", to: "resources#export_fields", as: :export_fields
86
+ get "/export_profiles", to: "resources#export_profiles", as: :export_profiles
87
+ get "/import_fields", to: "resources#import_fields", as: :import_fields
88
+ get "/import_profiles", to: "resources#import_profiles", as: :import_profiles
89
+ post "/batch_selection", to: "resources#batch_selection", as: :batch_selection
90
+ get "/", to: "resources#index", as: :resources
91
+ get "/select_options", to: "resources#select_options", as: :select_options
92
+ get "/inline_create_form", to: "resources#inline_create_form", as: :inline_create_form
93
+ post "/inline_create", to: "resources#inline_create", as: :inline_create
94
+ get "/new", to: "resources#new", as: :new_resource
95
+ post "/", to: "resources#create", as: :create_resource
96
+ post "/evaluate_conditions", to: "resources#evaluate_conditions_new", as: :evaluate_conditions_new
97
+ post "/actions/:action_name", to: "actions#execute_collection", as: :collection_action
98
+ post "/batch_actions/:action_name", to: "actions#execute_batch", as: :batch_action
99
+ post "/:id/transitions/:transition_name", to: "resources#execute_transition", as: :execute_transition
100
+ post "/:id/approval_tasks/:task_id/approve", to: "approval_tasks#approve", as: :approve_approval_task
101
+ post "/:id/approval_tasks/:task_id/reject", to: "approval_tasks#reject", as: :reject_approval_task
102
+ post "/:id/approval_tasks/:task_id/return_task", to: "approval_tasks#return_task", as: :return_task_approval_task
103
+ post "/:id/approval_tasks/:task_id/claim", to: "approval_tasks#claim", as: :claim_approval_task
104
+ post "/:id/approval_tasks/:task_id/delegate", to: "approval_tasks#delegate", as: :delegate_approval_task
105
+ get "/:id", to: "resources#show", as: :resource
106
+ get "/:id/zones/:zone_name", to: "resources#zone", as: :zone_resource
107
+ get "/:id/edit", to: "resources#edit", as: :edit_resource
108
+ patch "/:id", to: "resources#update", as: :update_resource
109
+ put "/:id", to: "resources#update"
110
+ delete "/:id", to: "resources#destroy", as: :destroy_resource
111
+ post "/:id/restore", to: "resources#restore", as: :restore_resource
112
+ delete "/:id/permanently_destroy", to: "resources#permanently_destroy", as: :permanently_destroy_resource
113
+ patch "/:id/reorder", to: "resources#reorder", as: :reorder_resource
114
+ patch "/:id/reparent", to: "resources#reparent", as: :reparent_resource
115
+ patch "/:id/kanban_move", to: "resources#kanban_move", as: :kanban_move_resource
116
+ post "/:id/evaluate_conditions", to: "resources#evaluate_conditions", as: :evaluate_conditions
117
+ post "/:id/actions/:action_name", to: "actions#execute_single", as: :single_action
118
+ end
119
+ end
data/docs/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # LCP Ruby Documentation
2
+
3
+ LCP Ruby is a Rails mountable engine that generates full CRUD information systems from YAML metadata.
4
+
5
+ ## Quick Start
6
+
7
+ - [Getting Started](getting-started.md) — Install, configure, create your first model/presenter/permission
8
+ - **`lcp new my_app`** — interactive CLI to create a new LCP application (database, format, feature preset)
9
+ - **`rails generate lcp_ruby:install`** — add LCP to an existing Rails app
10
+ - **`rails generate lcp_ruby:entity NAME field:type ...`** — scaffold a complete CRUD entity (model + presenter + permissions + view group). See [Getting Started → Scaffolding new entities](getting-started.md#scaffolding-new-entities) and the [design spec](design/entity_generator.md) for the field grammar and worked examples.
11
+ - [Host Application Guide](guides/host-application.md) — Full app bootstrap, optional dependencies (XLSX, charts, metrics), feature generators
12
+
13
+ ## YAML Reference
14
+
15
+ Complete attribute reference for every YAML configuration file:
16
+
17
+ - [Models](reference/models.md) — Fields, validations, associations, scopes, events, display templates, virtual columns, abstract models, inheritance
18
+ - [Types](reference/types.md) — Custom business types (email, phone, url, color, and user-defined)
19
+ - [Presenters](reference/presenters.md) — Index, show, form, search, actions, navigation
20
+ - [Pages](reference/pages.md) — Page YAML format, zones, widget types (kpi_card, text, list, workflow_graph), grid positioning, auto-pages, dialog-only pages, composite pages (semantic layout, tabs, scope_context)
21
+ - [Virtual Forms](reference/virtual_forms.md) — Shared infrastructure for synthetic per-request form-like objects (filter forms, wizards, virtual show, PaaS config UI): VirtualField + VirtualForm + Type::ArrayOf, dispatcher contract, security invariants, GC lifecycle
22
+ - [Page Filters](reference/page_filters.md) — `filter_form:` (value-based, form-syntax fields with cascade + multi) and `scope_filters:` (AR-scope toggles) on dashboards and index composite pages; auto_submit derivation, dirty-state Apply button, `/select_options` fallback chain
23
+ - [Cascading Selects](reference/cascading_selects.md) — `data-lcp-depends-on` contract for child selects, form-level data attributes, forward + reverse cascade, multi-parent UNION, accessibility (aria-busy, polite live region, focus restoration), race semantics
24
+ - [Forms](reference/forms.md) — Form-input renderers shared between presenter forms and synthetic forms: `date_range` paired-date input, `multi_select` cascade activation, i18n keys, cross-links
25
+ - [Dialogs](reference/dialogs.md) — Dialog actions, confirm variants (boolean, role, styled, page-based), routing, virtual model flow
26
+ - [View Groups](reference/view-groups.md) — Navigation menu, view switching, auto-creation
27
+ - [Menu](reference/menu.md) — Configurable navigation: top bar, sidebar, dropdowns, nested submenus, badges, role visibility, responsive modes (overflow_more / hamburger / rail / off-canvas), per-item priority/pin/hide_below, sidebar_toggle marker, mobile header, rail-collapsed flyouts
28
+ - [Custom Fields](reference/custom-fields.md) — Runtime user-defined fields: definitions, types, permissions, querying
29
+ - [Role Source](reference/role-source.md) — DB-backed role model: contract, registry, cache invalidation, generator
30
+ - [Permission Source](reference/permission-source.md) — DB-backed permissions: JSON definitions, registry, cache invalidation, generator
31
+ - [OIDC Authentication](reference/oidc.md) — `auth.yml` provider registry, claim mapping, role source, provisioning, logout modes, redirect_uri override, boot validation rules
32
+ - [Groups](reference/groups.md) — Organizational groups: YAML, DB, host adapter, role mapping, resolution strategies
33
+ - [i18n](reference/i18n.md) — Internationalization: key hierarchy, model/field/enum/menu/action labels, UI framework keys, date formatting
34
+ - [i18n_check](reference/i18n_check.md) — Static-analysis lint for the i18n principle: three passes (DSL AST, YAML schema-driven, boot-time registry), configuration, severity / CI integration, exemption marker
35
+ - [invariant_check](reference/invariant_check.md) — Boot-time validator for permission/page metadata behavioral invariants (AUTH-001..009): custom-scope methods on klass, field_match column, inherits parent resolution, page visible_when shape; severity / CI integration
36
+ - [Permissions](reference/permissions.md) — Roles, CRUD, field access, scopes, record rules
37
+ - [Condition Operators](reference/condition-operators.md) — Shared operator reference for `visible_when`, `record_rules`, `item_classes`, etc. Plus invocation forms (`service:`, `lookup:`)
38
+ - [Dynamic References](reference/dynamic-references.md) — Single source of truth for dotted-string tokens (`current_user.<method>`, `record.<field>`, `current_date`, …) used in scopes, conditions, page `scope_context`, workflow `set_fields`, and field defaults
39
+ - [Auditing](reference/auditing.md) — Change tracking: audit log model, field diffs, JSON/custom field expansion, configuration
40
+ - [Workflow](reference/workflow.md) — State machine: states, transitions, guards, set_fields, readonly_fields, trigger modes, audit log, timeline_states, three definition sources
41
+ - [Workflow Approvals](reference/workflow-approvals.md) — Multi-step approval engine: sequential/parallel strategies, approver types, delegation, bypass, rework
42
+ - [Eager Loading](reference/eager-loading.md) — Auto-detection, manual overrides, strategy resolution, strict_loading
43
+ - [Tree Structures](reference/tree-structures.md) — Declarative tree hierarchies: model options, traversal, reparenting, tree index view
44
+ - [View Slots](reference/view-slots.md) — Extensible page layout injection points: registry, slot names, SlotContext, position ordering
45
+ - [API-Backed Models](reference/api-backed-models.md) — External data sources: REST JSON adapter, host providers, cross-source associations, caching, error handling
46
+ - [Host Controller Integration](reference/host-controller-integration.md) — `bind_to:` connecting LCP metadata to existing AR models, `controller:` / `action_controllers:` per-presenter routing to host controllers, includable `LcpRuby::Controller::*` concerns including `AuthorizedController` (Pundit `verify_authorized` framework guarantee), multi-model authorize helper pattern, `lcp_ruby:host_controller` generator
47
+ - [Monitoring](reference/monitoring.md) — Health check, Prometheus metrics, error log, AS::Notifications events, custom collectors
48
+ - [Export](reference/export.md) — Data export: CSV/XLSX formats, field picker, formatting options, profiles, history, generator
49
+ - [Import](reference/import.md) — Data import: CSV/XLSX upload, column mapping, strategies, nested has_one, profiles, background execution, generator
50
+ - [Theme Variables](reference/theme-variables.md) — All `--lcp-*` CSS custom properties with light/dark values
51
+ - [Engine Configuration](reference/engine-configuration.md) — `LcpRuby.configure` options
52
+ - [Boot / Reload Lifecycle](reference/boot_lifecycle.md) — Engine boot phases, extension hook timing (`on_model_ready`, `on_models_loaded`), dev-mode metadata watcher, `lcp_ruby:ensure_tables` rake + `db:prepare` / `db:setup` / `db:reset` integration, `boot.lcp_ruby` and `reload.lcp_ruby` AS::Notifications events
53
+ - [`lcp_ruby:doctor`](reference/doctor.md) — Health check rake task: install manifest replay, feature state vs. prereqs, environment leaks (`BUNDLE_GEMFILE`, `.envrc`), seeds hygiene; `FORMAT=text|json|summary` and `EXIT_ON=error|warning`; install manifest format and JSON schema for CI consumption
54
+
55
+ ## DSL Reference
56
+
57
+ - [Model DSL](reference/model-dsl.md) — Ruby DSL alternative to YAML for model definitions
58
+ - [Presenter DSL](reference/presenter-dsl.md) — Ruby DSL alternative to YAML for presenter definitions (with inheritance)
59
+ - [Types](reference/types.md#dsl-type-definition) — Ruby DSL for defining custom business types
60
+
61
+ ## Guides
62
+
63
+ - [Presenters](guides/presenters.md) — Step-by-step guide to building presenters (index, show, form, search, actions) with YAML and DSL examples
64
+ - [Selectbox](guides/selectbox.md) — Association select, cascading selects, remote search, multi-select, tree select, scoping, disabled options, legacy records, codelists
65
+ - [Virtual Columns](guides/virtual-columns.md) — Query-time computed columns: declarative aggregates, SQL expressions, JOINs, GROUP BY, services, auto-include, conditional rendering
66
+ - [Computed Fields](guides/computed-fields.md) — Auto-calculated persisted fields: template interpolation, service logic, arithmetic, comparison with virtual columns
67
+ - [Sequence Fields](guides/sequences.md) — Gap-free auto-numbering: scoped counters, format templates, counter management, rake tasks
68
+ - [Extensibility](guides/extensibility.md) — All extension mechanisms: actions, events, transforms, validators, defaults, computed fields, condition services, scopes, model extensions
69
+ - [Conditional Rendering](guides/conditional-rendering.md) — `visible_when`, `disable_when`, `item_classes`: simple, compound (all/any/not), dot-path, dynamic references, collection conditions, lookup value references, DSL builder
70
+ - [Custom Actions](guides/custom-actions.md) — Writing domain-specific operations beyond CRUD
71
+ - [Event Handlers](guides/event-handlers.md) — Responding to lifecycle events and field changes
72
+ - [Custom Types](guides/custom-types.md) — Defining custom business types (percentage, postal_code, slug, hex_color)
73
+ - [View Groups](guides/view-groups.md) — Multi-view navigation and view switcher setup
74
+ - [Menu](guides/menu.md) — Custom navigation menus: dropdowns, nested submenus, sidebar, combined layouts, badges
75
+ - [Renderers](guides/display-types.md) — Visual guide to all built-in renderers (including workflow_timeline, workflow_badge, dot-notation, templates, and collections)
76
+ - [Custom Renderers](guides/custom-renderers.md) — Creating custom renderers for host applications
77
+ - [Attachments](guides/attachments.md) — File upload with Active Storage
78
+ - [Userstamps](guides/userstamps.md) — Automatic created_by / updated_by tracking: setup, name snapshots, presenter display, seeds
79
+ - [Record Aliases & Slug Fields](guides/record-aliases.md) — Human-readable URLs (`/articles/my-slug`), user-context aliases (`/preferences/me`), dynamic shortcuts (`/issues/last`)
80
+ - [Soft Delete](guides/soft-delete.md) — Discard/restore, cascade, archive presenters, permissions
81
+ - [Action Buttons & Pipelines](guides/action-buttons.md) — All button contexts (collection, single, batch, form), form submit buttons, save + transition + action pipelines, show page pipelines
82
+ - [Batch Actions](guides/batch-actions.md) — Multiselect, batch delete/restore, custom batch actions, selection modes
83
+ - [Auditing](guides/auditing.md) — Change tracking: setup, field filtering, JSON expansion, custom writer, show page integration
84
+ - [Workflow](guides/workflow.md) — State machine setup: transitions, guards, readonly fields, events, system triggers, audit logging, workflow renderers, testing
85
+ - [Eager Loading](guides/eager-loading.md) — N+1 prevention, strict_loading, manual overrides
86
+ - [Tree Structures](guides/tree-structures.md) — Declarative tree hierarchies: setup, tree index view, drag-and-drop reparenting, search
87
+ - [Custom Fields](guides/custom-fields.md) — Runtime user-defined fields: enabling, defining, sections, permissions, programmatic access
88
+ - [Role Source](guides/role-source.md) — DB-backed role management: setup, validation, cache, testing
89
+ - [Permission Source](guides/permission-source.md) — DB-backed permission management: runtime editing, JSON definitions, testing
90
+ - [OIDC Setup](guides/oidc-setup.md) — IdP App registration walkthrough, generator, ENV setup options (export / dotenv / encrypted credentials), role mapping, troubleshooting (CSRF, cookie overflow, redirect URI mismatch, hostname consistency)
91
+ - [Groups](guides/groups.md) — Organizational groups: YAML, DB, host adapter, testing
92
+ - [Hierarchical Authorization](guides/hierarchical-authorization.md) — Multi-level parent-child access control (factory → production line → machine → sensor reading)
93
+ - [Permissions](guides/permissions.md) — `extends:` keyword and coverage merge with `_default`: pattern catalog, anti-patterns, decision tree, validator output reference
94
+ - [Inherited Permissions](guides/inherited-permissions.md) — Declarative `inherits_from:` cascade for visibility (read time) and create-time FK validation; bind_to host classes; soft-delete and transitive chains
95
+ - [Impersonation](guides/impersonation.md) — "View as Role X" for testing permissions
96
+ - [Tiles View](guides/tiles.md) — Card grid layout for index pages: tile configuration, sort dropdown, per-page selector, summary bar
97
+ - [Dashboards](guides/dashboards.md) — Standalone grid pages: KPI cards, text widgets, list widgets, presenter zones, landing page
98
+ - [Composite Pages](guides/composite-pages.md) — Record-bound multi-zone pages: semantic layout, tabs, scope_context, per-zone authorization, index composites, composite dialogs, dialog nesting
99
+ - [Dialogs](guides/dialogs.md) — Quick create/edit dialogs, virtual model dialogs, styled/page-based confirms, composite dialogs, dialog nesting
100
+ - [Rendering Extension Points](guides/rendering-extension-points.md) — Custom render blocks vs. view slots: when to use which, available locals, worked examples
101
+ - [View Slots](guides/view-slots.md) — Extending page layouts: custom toolbar buttons, widgets, conditional components, overriding built-ins
102
+ - [API-Backed Models](guides/api-backed-models.md) — Integrating external REST APIs and host-provided data sources: setup, cross-source associations, caching, error handling, testing
103
+ - [Host Controller Integration](guides/host-controller-integration.md) — Connecting LCP to existing host AR models with `bind_to:`, routing presenter slugs to host controllers (`controller:` / `action_controllers:`), includable controller concerns, `lcp_ruby:host_controller` generator
104
+ - [Monitoring](guides/monitoring.md) — Health check, Prometheus + Grafana, error log, custom collectors, testing
105
+ - [Export](guides/export.md) — Data export setup: CSV/XLSX, field selection, profiles, history, permissions
106
+ - [Import](guides/import.md) — Data import setup: CSV/XLSX upload, strategies, nested has_one associations, profiles, permissions
107
+ - [Theming](guides/theming.md) — Dark mode, UI density, border radius, CSS variables, theme persistence
108
+ - [Developer Tools](guides/developer-tools.md) — `lcp_ruby:validate`, `lcp_ruby:erd`, `lcp_ruby:permissions`, `lcp_ruby:create_admin`, `lcp_ruby:i18n_lint` rake tasks + `LcpRuby/NoHardcodedI18nString` RuboCop cop
109
+ - [Adding a Locale](guides/adding-locale.md) — Workflow for adding a new language: engine UI vs host-app domain layers, step-by-step checklist, plural forms, devise, tooling, troubleshooting
110
+
111
+ ## Debugging
112
+
113
+ Practical `rails runner` recipes for inspecting LCP internals at runtime:
114
+
115
+ - [Overview](guides/debugging/README.md) — Entry points, general tips
116
+ - [Models](guides/debugging/models.md) — Columns, validations, scopes, associations, inheritance, schema comparison
117
+ - [Controllers](guides/debugging/controllers.md) — Routing, callbacks, auth chain, Warden vs controller, layout
118
+ - [Permissions](guides/debugging/permissions.md) — Role checks, field access, record rules, condition evaluation
119
+ - [Presenters](guides/debugging/presenters.md) — Columns, layout, actions, search, view groups, tiles
120
+ - [Metadata](guides/debugging/metadata.md) — Loader, registry, boot validation, configuration, workflows, types
121
+ - [Data](guides/debugging/data.md) — DB state, duplicates, custom fields, workflow state, audit logs, seeds verification
122
+
123
+ ## Design Documents
124
+
125
+ Implemented:
126
+
127
+ - [Record Positioning](design/record_positioning.md) — Drag-and-drop reordering of top-level records with the `positioning` gem
128
+ - [External Field Accessors](design/fields_accessors.md) — Virtual fields with `source: external` and `source: { service: }` accessor delegation
129
+ - [Unified Condition Operators](design/unified_condition_operators.md) — Strict condition evaluation, shared 12-operator set across all contexts
130
+ - [Record Rules Action Visibility](design/record_rules_action_visibility.md) — Automatic hiding of edit/destroy buttons based on record_rules
131
+ - [Inline Collection Editor](design/inline_collection_editor.md) — Unified editing for nested associations, JSON arrays, and bulk records: row-scoped conditions, JSON field source, virtual models, sub-sections, presenter-driven manage page
132
+ - [Groups, Roles & Org Structure](design/groups_roles_and_org_structure.md) — Enterprise organizational units, groups, and group-to-role mapping
133
+ - [Model Options Infrastructure](design/model_options_infrastructure.md) — Shared patterns for model-level feature flags (soft_delete, auditing, userstamps, tree)
134
+ - [Userstamps](design/userstamps.md) — Automatic `created_by_id` / `updated_by_id` tracking
135
+ - [Soft Delete](design/soft_delete.md) — Discard/restore support with `discarded_at` timestamp, cascade discard/undiscard, archive presenters
136
+ - [Auditing](design/auditing.md) — Native change tracking and audit trail
137
+ - [Tree Structures](design/tree_structures.md) — Declarative parent-child hierarchies with traversal, cycle detection, and tree index view
138
+ - [Saved Filters & Parameterized Scopes](design/saved_filters.md) — User-persistent named filters with visibility levels, parameterized scopes with typed parameters, generator, CRUD API
139
+ - [Aggregate Columns](design/aggregate_columns.md) — Virtual computed columns (COUNT, SUM, MIN, MAX, AVG) from associated records, custom SQL, service-based aggregates
140
+ - [Virtual Columns](design/virtual_columns.md) — Generalized query extensions: expressions, JOINs, GROUP BY, auto-include, backward-compatible with aggregates
141
+ - [Tiles View](design/tiles_view.md) — Card grid layout for index pages with sort dropdown, per-page selector, and summary bar
142
+ - [Row Styling](design/row_styling.md) — Conditional CSS classes on index rows (tables, trees, tiles) based on field conditions or services
143
+ - [Array Field Type](design/array_field_type.md) — Native array fields with typed items, array-specific operators, and auto-generated scopes
144
+ - [API-Backed Models](design/api_backed_models.md) — External data sources (REST JSON, host adapters): read-only access, cross-source associations, caching, graceful degradation
145
+ - [Pages — Unified Rendering Abstraction](design/composite_pages_v2.md) — Tier 1 + Tier 1b + Tier 2 Phase A: pages, zones, auto-pages, grid layout, widget zones, dashboard convergence, composite pages with semantic layout and tabs
146
+ - [Modal Dialogs](design/modal_dialogs.md) — Dialog actions, virtual model flow, confirm variants, routing, authorization
147
+ - [Dashboards](design/dashboards.md) — Tier 1b: standalone grid pages with KPI cards, text, list widgets, presenter zones
148
+ - [Chart Widget — Multi-Series and Configuration Options](design/chart_widget_multi_series.md) — Multi-series `series:` array, `column` chart type, declarative Chartkick options (legend, stacked, axis titles, value formatting, colors, sort, library escape hatch), Okabe-Ito default palette, empty-state banner, defensive payload guards
149
+ - [Workflow State Machine](design/workflow_state_machine.md) — Metadata-driven state machine: states, transitions, guards, audit log, three definition sources
150
+ - [Background Jobs](design/background_jobs.md) — Async job execution: declarative/class handlers, multi-step jobs, retry, cancellation, triggers, scheduling, three definition sources
151
+ - [Grouped Query Presenter](design/grouped_query_presenter.md) — GROUP BY queries with aggregates, date period grouping, HAVING, row_click drill-through
152
+ - [Nested Menu Dropdowns](design/nested_menu_dropdowns.md) — Sub-groups in top menu and sidebar dropdowns
153
+ - [Responsive Menu](design/responsive-menu.md) — Phase 0–2 implementation: lcp-dropdown primitive (touch/keyboard), top-nav modes (none/wrap/overflow_more/hamburger), sidebar rail + off-canvas, cookie persistence, auto-injected sidebar_toggle, mobile header, rail-collapsed flyouts
154
+ - [Dev Toolbar](design/dev_toolbar.md) — Developer tools overlay for metadata inspection
155
+ - [HR Demo App](design/demo-app-hr.md) — HR management system demo application design
156
+ - [Workflow Renderers](design/workflow_renderers.md) — Built-in workflow visualization: `workflow_timeline` (linear progress), `workflow_badge` (colored status badge), `workflow_graph` (Mermaid.js state diagram), auto-detection
157
+ - [Model Inheritance](design/model_inheritance.md) — Abstract base models and Single Table Inheritance (STI)
158
+ - [Sequence Fields](design/sequences.md) — Gap-free auto-numbering with scoped counters, format templates, and counter management
159
+ - [Deep Filter Enhancements](design/recursive_association_field_picker.md) — Recursive association field picker and recursive condition nesting (AND/OR tree)
160
+ - [Advanced Conditions](design/advanced_conditions.md) — Compound conditions (all/any/not), dynamic value references, dot-path fields, collection quantifiers, value services, lookup value references
161
+ - [Workflow Approvals](design/workflow_approvals.md) — Multi-step approval engine on top of the state machine: steps, strategies, delegation, rework
162
+ - [Context-Aware View Switcher](design/view_switcher_context.md) — View switcher integration with context-aware presenters
163
+ - [Custom Render Blocks](design/custom_render_blocks.md) — Host-app partial delegation: custom sections, custom zones, page-level render_with
164
+ - [Monitoring & Metrics](design/monitoring.md) — Health check, Prometheus metrics, error log, AS::Notifications instrumentation
165
+ - [Export](design/export.md) — Data export: collection/batch export, field picker, formatting, profiles, history
166
+ - [Pagination Footer](design/pagination_footer.md) — Unified pagination bar: per-page selector, record count, styled page links, First/Last toggle
167
+ - [Import](design/import.md) — Server-side data import with file upload, column mapping, strategy selection, association lookup, profiles, background execution
168
+ - [Import Nested has_one](design/import_nested_has_one.md) — Import flat CSV rows into parent + has_one associations: dot-notation mapping, nested_blank_strategy, auto-mapping, permission filtering
169
+ - [Search Parameter Controls](design/search_parameter_controls.md) — Typed filter controls (dropdowns, toggles, ranges) in the presenter search toolbar, generating Ransack `?f[...]` params
170
+ - [Theming](design/theming.md) — Dark mode, CSS custom property system, UI density, border radius, theme persistence, vendor CSS dark variants
171
+ - [Host App Controller Integration](design/host_app_controller_integration.md) — `bind_to:` for existing host AR models (Phase A), controller concern extraction (Phase B1), `controller:` / `action_controllers:` per-presenter routing (Phase B2), `lcp_ruby:host_controller` generator (Phase B3)
172
+ - [bind_to Managed Fields and Associations](design/bind_to_managed_fields_and_associations.md) — Per-item `lcp_managed: true` flag on `fields:` and `associations:` of `bind_to:` models so LCP can additively add columns and declare AR macros on host classes (resolves school audit issue #22 and the deferred `bind_to_associations:` future from the original `bind_to` design)
173
+ - [Association `primary_key`](design/association_primary_key.md) — Per-association override of the target join column so `belongs_to` / `has_many` / `has_one` can join on a business key (`vema_code`, `iso_code`, `sku`) instead of the surrogate `id`; FK column type inferred from the referenced column; Layer B consumers (form selects, cascading selects, tree selects, page parameters [retired in PR 5; replaced by [page filters](reference/page_filters.md)], import/export field trees, virtual columns) updated end-to-end for string business keys
174
+ - [Record Aliases](design/record_aliases.md) — Presenter-level alias resolution (`/preferences/me`, `/issues/last`) and model-level slug fields (`/articles/quarterly-report`): resolve chain, strategies, URL preservation, validation pipeline
175
+ - [Permission `_default` Coverage Merge](design/permissions_default_role_coverage.md) — `extends:` keyword and coverage-merge default for per-model permission YAML files (roles, field_overrides, record_rules inherit from `_default`); pre/post-merge validators; `lcp_ruby:permissions:resolve` rake task
176
+ - [`lcp_ruby:entity` Generator](design/entity_generator.md) — Single-command scaffold of model + presenter + permissions + view group from a CLI field grammar (v1: types/associations, v2: DB constraints + feature flags, v3: sections/renderers/color_map/link/polymorphic). Includes auto-link of belongs_to in index/show, synthetic `position`/`parent_id` fields for `--positioning`/`--tree`, polymorphic skip from index/show, reverse-association post-install hints (and optional `--auto-add-inverses` for DSL targets), and bash-brace-expansion guidance.
177
+ - [Entity Generator `--menu` Flag](design/entity_generator_menu_flag.md) — `rails g lcp_ruby:entity … --menu=[<section>:]ROOT|<DropdownLabel>[:bottom|:right] --menu-icon=<lucide>` writes a `- view_group: <name>` entry into `config/lcp_ruby/menu.yml` at scaffold time above the seeded `# lcp:menu` marker. Pairs with `lcp_ruby:install --menu-layout=top|sidebar|both` (and `lcp new`'s wizard prompt) for marker seeding.
178
+ - [Menu Modes + Auto-Append Polish](design/menu_modes_and_skeleton.md) — `:auto` (default) vs `:strict` mode semantics, auto-append transparency log surfacing every auto-appended view group at boot, B59 cross-presenter dedup, `presenter.menu_position` deprecation info-warning.
179
+ - [Boot / Reload Lifecycle](design/boot_reload_lifecycle.md) — Dev-mode metadata watcher (closes school-audit B1 + B2: permission YAML reload + Duplicate-presenter), `db:prepare` / `db:setup` enhanced with `lcp_ruby:ensure_tables` post-action that idempotently materialises platform tables in topological order (closes B4 — `db:drop && db:prepare && db:seed` works in one process), `reload.lcp_ruby` AS::Notifications event symmetric to `boot.lcp_ruby`. Builds on the `LcpRuby.on_models_loaded` hook and `RELOAD_MUTEX` from authorization hardening v1.
180
+ - [Generator Prerequisites Registry & `lcp_ruby:doctor`](design/generator_prerequisites_registry.md) — Declarative `FeatureRegistry` + `Prerequisites` Thor concern collapse three ad-hoc prereq checks (import/entity/api_tokens) into one source of truth. `lcp new` writes an install manifest; the `lcp_ruby:doctor` rake task replays it and reports feature state, environment leaks, and seed hygiene. `install_auth` now ships the `user.rb` metadata model directly (replacing `api_tokens`' buggy fallback).
181
+
182
+ In Progress:
183
+
184
+ - [Advanced Search & Filter Builder](design/advanced_search.md) — Type-aware quick search, Ransack-based filter builder, custom filter methods, query language (Phase 0–4 implemented)
185
+ - [Page Layouts & View Slots](design/page_layout_and_slots.md) — Extensible page layout system: slot registry (Phase 1 implemented), layout variants (planned)
186
+ - [Multiselect and Batch Actions](design/multiselect_and_batch_infrastructure.md) — Checkbox selection, batch delete/restore/permanently_destroy, selection modes, result logging (infrastructure + batch delete implemented; background execution deferred)
187
+
188
+ Partially Implemented:
189
+ - [Form Submit Actions](design/form_submit_actions.md) — Configurable form submit buttons with redirect, set_fields, pipeline execution, cross-presenter redirect, overflow dropdown (Phase 1–3 implemented)
190
+ - [AJAX Error Handling](design/ajax_error_handling.md) — Graceful error handling for Turbo/fetch requests
191
+ - [~~Workflow & Approvals~~](design/workflow_and_approvals.md) — Outdated, superseded by the two documents above
192
+
193
+ Proposed:
194
+
195
+ - [Agent Affordances](design/agent_affordances.md) — *(Draft)* Make skills + curated docs + an AGENTS.md/CLAUDE.md entrypoint available to AI agents in installed-gem host apps (not just inside this repo)
196
+ - [Cached Aggregates](design/cached_aggregates.md) — Materialized aggregate values with automatic invalidation
197
+ - [Context-Aware Presenters](design/context_aware_presenters.md) — Parent-context-dependent presenter resolution for polymorphic sub-resources
198
+ - [Data Retention](design/data_retention.md) — Automatic purge policies for audit logs, soft-deleted records, and attachments
199
+ - [Derived Associations](design/derived_associations.md) — Computed associations derived from aggregate/virtual columns
200
+ - [Document Management](design/document_management.md) — File-centric document management (versioning, preview, metadata, workflows)
201
+ - [Dynamic Presenters](design/dynamic_presenters.md) — DB-backed presenter overrides (user/role/system personalization layer)
202
+ - [Hub Pages](design/hub_pages.md) — Hero banner + navigation cards landing pages
203
+ - [Import & Export](design/import_export.md) — Data import and export (CSV, Excel, JSON)
204
+ - [Multi-Step Forms](design/multi_step_forms.md) — Wizard-style forms with step navigation
205
+ - [PaaS — AI-Powered App Builder](design/paas.md) — AI agent builds LCP apps from natural language; container management, chat UI, code-server
206
+ - [Workflow Async Completion](design/workflow_async_completion.md) — Declarative `async_completion` on transitions for long-running operations
207
+ - [Scoped Permissions](design/scoped_permissions.md) — Context-dependent permission definitions for polymorphic sub-resources
208
+ - [Timeline View](design/timeline_view.md) — Timeline index layout for chronological data
209
+ - [User Menu](design/user-menu.md) — User menu dropdown (profile, settings, logout)
210
+ - [Chess Demo App](design/demo-app-chess.md) — Chess training academy demo application design
211
+ - [E-Shop Demo App](design/demo-app-eshop.md) — E-shop demo application design
212
+ - [External Database Models](design/external_database_models.md) — External DB tables (read-only and writable), local overlay extensions, cross-DB filtering, feature compatibility, unified presenter
213
+
214
+
215
+ Research:
216
+
217
+ - [Basepack Search Lessons](design/basepack_lessons.md) — Lessons learned from Basepack search system for advanced search design
218
+
219
+ ## Internals
220
+
221
+ - [Architecture](architecture.md) — Module structure, data flow, controllers, views
222
+
223
+ ## Examples
224
+
225
+ - [Example Apps](examples.md) — TODO and CRM app walkthroughs
@@ -0,0 +1,212 @@
1
+ # Architecture
2
+
3
+ ## Overview
4
+
5
+ LCP Ruby is a Rails mountable engine that generates full CRUD information systems from YAML metadata. Models, presenters (UI config), and permissions are defined in YAML files. The engine dynamically builds ActiveRecord models, database tables, controllers, and views at runtime.
6
+
7
+ ## Data Flow
8
+
9
+ ```
10
+ YAML metadata (config/lcp_ruby/)
11
+ ├── types/*.yml → Metadata::Loader → TypeDefinition → TypeRegistry
12
+ ├── models/*.yml → Metadata::Loader → ModelInheritanceResolver → ModelDefinition
13
+ ├── presenters/*.yml → Metadata::Loader → PresenterDefinition
14
+ ├── permissions/*.yml → Metadata::Loader → PermissionDefinition
15
+ ├── jobs/*.yml → Metadata::Loader → BackgroundJobs::Definition
16
+ └── menu.yml → Metadata::Loader → MenuDefinition → MenuItem (with badges)
17
+
18
+ ModelFactory::Builder.build → LcpRuby::Dynamic::<Name>
19
+ (creates AR class + DB table + validations + transforms + associations + scopes)
20
+ (virtual models with table_name: _virtual are skipped — metadata only, no AR class)
21
+ (API models → ApiBuilder creates ActiveModel class, skips DB/AR-specific applicators)
22
+
23
+ LcpRuby.registry.register(name, model_class)
24
+
25
+ DataSource::Setup.apply!(loader) → instantiate adapters, wrap with cache/resilient,
26
+ attach to API model classes, apply cross-source associations
27
+
28
+ CustomFields::Setup.apply!(loader) → contract validation, registry, handlers, accessors, scopes
29
+
30
+ Roles::Setup.apply!(loader) → contract validation, registry, change handler (if role_source == :model)
31
+
32
+ Permissions::Setup.apply!(loader) → contract validation, registry, change handler, definition validator (if permission_source == :model)
33
+
34
+ Groups::Setup.apply!(loader) → YAML/DB/host loader, registry, change handler (if group_source != :none)
35
+
36
+ Auditing::Setup.apply!(loader) → contract validation, registry mark_available! (if any model has auditing: true)
37
+
38
+ Pages::Setup.apply!(loader) → contract validation, registry, change handler, definition validator (if page_source == :model)
39
+ loader.merge_db_pages! → loads DB page definitions, overrides YAML/auto pages, recreates auto-pages
40
+
41
+ BackgroundJobs::Setup.apply!(loader) → contract validation, sources, resolver,
42
+ triggers, schedule sync (if job definitions exist)
43
+
44
+ Export::Setup.apply!(loader) → register export_config virtual model,
45
+ export_dialog page/presenter, ExportHandler event handler
46
+
47
+ Metrics::Setup.apply!(loader) → resolve :auto error_log_enabled, register Prometheus metrics,
48
+ activate AS::Notifications subscriber, discover custom collectors from app/lcp_metrics/
49
+
50
+ ConditionServiceRegistry.discover! → condition services from app/condition_services/
51
+ Services::Registry.discover! → data providers from app/lcp_services/data_providers/
52
+ Display::RendererRegistry.register_built_ins! → 28 built-in renderers + badge renderers
53
+ Display::RendererRegistry.discover! → custom renderers from app/renderers/
54
+ ViewSlots::Registry.register_built_ins! → 11 built-in slot components (toolbar, filters, pagination)
55
+
56
+ Pages::Resolver → slug/name lookup → PageDefinition → zones → presenters
57
+
58
+ Engine routes (/:lcp_slug/*) → ResourcesController
59
+ Dialog routes (/lcp_dialog/:page_name/*) → DialogsController
60
+ (CRUD with Pundit authorization, presenter-driven UI, conditional rendering,
61
+ composite pages with semantic layout, tabs, scope_context scoping)
62
+ ```
63
+
64
+ ## Key Modules
65
+
66
+ | Module | Location | Purpose |
67
+ |--------|----------|---------|
68
+ | `Metadata` | `lib/lcp_ruby/metadata/` | Parses YAML into definition objects (ModelDefinition, PresenterDefinition, etc.). ModelHashMerger + ModelInheritanceResolver handle abstract model inheritance (two-pass load, topological sort, hash merge, abstract exclusion) |
69
+ | `Types` | `lib/lcp_ruby/types/` | TypeRegistry, TypeDefinition, ServiceRegistry, built-in types (email, phone, url, color), transforms (strip, downcase, normalize_url, normalize_phone) |
70
+ | `ModelFactory` | `lib/lcp_ruby/model_factory/` | Builds dynamic AR models: Builder orchestrates SchemaManager, ValidationApplicator, TransformApplicator, AssociationApplicator, VirtualColumnApplicator, ScopeApplicator, PositioningApplicator, UserstampsApplicator, SoftDeleteApplicator, AuditingApplicator, TreeApplicator, SequenceApplicator (gap-free auto-numbering with scoped counters). ApiBuilder builds ActiveModel classes for API-backed models. ApiAssociationApplicator creates cross-source association accessors |
71
+ | `Sequences` | `lib/lcp_ruby/sequences/` | SequenceManager (admin API: set/current/list counter values), `build_scope_key` (scope hash to string key). Counter table via generator (`lcp_ruby:gapfree_sequences`) |
72
+ | `DataSource` | `lib/lcp_ruby/data_source/` | API-backed model infrastructure: Base (contract), RestJson (HTTP adapter), Host (provider delegation), CachedWrapper (Rails.cache TTL), ResilientWrapper (error handling), ApiModelConcern (ActiveModel mixin), ApiFilterTranslator (Ransack→portable filter translation), ApiPreloader (batch N+1 prevention), ApiErrorPlaceholder (graceful degradation), Registry, Setup (boot orchestration) |
73
+ | `VirtualColumns` | `lib/lcp_ruby/virtual_columns/` | Builder: injects SQL subqueries, expressions, JOINs, and GROUP BY into ActiveRecord scopes. Collector: auto-detects needed VCs from presenter metadata per context. Supports declarative aggregates, expression columns, JOIN-based columns, service-based VCs with `:current_user` placeholder, soft-delete filtering, and COALESCE defaults. `Aggregates::QueryBuilder` is a backward-compat alias |
74
+ | `Presenter` | `lib/lcp_ruby/presenter/` | UI layer: Resolver (find by slug), LayoutBuilder (form/show sections + normalize_json_field_section for json_field: sources + sub-section enrichment), ColumnSet (visible columns), ActionSet (visible actions with record_rules integration via action_permitted_for_record?), IncludesResolver (auto-detects and applies eager loading from presenter metadata), FieldValueResolver (dot-path, template, FK, and simple field resolution with permission checks) |
75
+ | `CustomFields` | `lib/lcp_ruby/custom_fields/` | Registry (per-model definition cache), Applicator (dynamic accessors + validations + defaults + stale cleanup), ContractValidator (boot-time model contract checks), Query (DB-portable JSON queries with field name validation), DefinitionChangeHandler (cache invalidation), Setup (shared boot logic with contract validation), Utils (env-aware JSON/numeric parsing) |
76
+ | `Roles` | `lib/lcp_ruby/roles/` | Registry (thread-safe role name cache), ContractValidator (boot-time model contract checks), ChangeHandler (after_commit cache invalidation), Setup (boot orchestration). Only active when `role_source == :model` |
77
+ | `Permissions` | `lib/lcp_ruby/permissions/` | Registry (per-model PermissionDefinition cache), ContractValidator (boot-time model contract checks), ChangeHandler (after_commit cache invalidation + PolicyFactory clear), DefinitionValidator (JSON validation on save), SourceResolver (DB → YAML priority chain), Setup (boot orchestration). Only active when `permission_source == :model` |
78
+ | `Groups` | `lib/lcp_ruby/groups/` | Contract (interface), Registry (thread-safe, delegates to loader), YamlLoader (static groups from YAML), ModelLoader (DB queries), HostLoader (adapter delegation), ContractValidator (group/membership/mapping models), ChangeHandler (after_commit cache invalidation), Setup (boot orchestration by group_source). Integrates with PermissionEvaluator via role_resolution_strategy |
79
+ | `Display` | `lib/lcp_ruby/display/` | BaseRenderer (base class), 28 built-in renderer classes in `renderers/` (incl. WorkflowBadge, WorkflowTimeline), badge renderers (CountBadge, TextBadge, IconBadge), RendererRegistry (registers built-ins + auto-discovers host renderers from `app/renderers/`) |
80
+ | `Authorization` | `lib/lcp_ruby/authorization/` | PolicyFactory (dynamic Pundit policies), PermissionEvaluator (can?, can_for_record? with alias resolution, readable_fields, writable_fields, with optional role validation via Roles::Registry), ScopeBuilder |
81
+ | `Events` | `lib/lcp_ruby/events/` | Dispatcher + HandlerRegistry. Host apps define handlers in `app/event_handlers/` |
82
+ | `Actions` | `lib/lcp_ruby/actions/` | ActionExecutor + ActionRegistry. Host apps define custom actions in `app/actions/` |
83
+ | `Conditions` | `lib/lcp_ruby/condition_evaluator.rb`, `lib/lcp_ruby/condition_service_registry.rb`, `lib/lcp_ruby/dsl/condition_builder.rb` | ConditionEvaluator (strict: 15 operators, raises ConditionError on unknown operator/missing field), ConditionServiceRegistry. Supports compound (all/any/not), dot-path fields, collection quantifiers, dynamic value references (field_ref, current_user, date, service, lookup). DSL via `ConditionBuilder.build` block and `ConditionBuilder.lookup` helper. All condition callers (PermissionEvaluator, ActionSet, views) delegate to ConditionEvaluator. Host apps define condition services in `app/condition_services/` |
84
+ | `Search` | `lib/lcp_ruby/search/` | QuickSearch (type-aware text search), ParamSanitizer (filter param cleanup), FilterParamBuilder (LCP operators to Ransack predicates), OperatorRegistry (type-to-operator mapping), CustomFilterInterceptor (filter_* method detection and interception), CustomFieldFilter (JSON column queries with type casting), FilterMetadataBuilder (permission-aware JSON metadata for the visual filter builder), QueryLanguageParser (recursive descent QL parser), QueryLanguageSerializer (condition tree to QL text), ParameterizedScopeApplicator (typed parameter casting, min/max clamping, filter_*/scope dispatch). Ransack model setup (`ransackable_attributes`, `ransackable_associations`) handled by `ModelFactory::RansackApplicator` at boot |
85
+ | `SavedFilters` | `lib/lcp_ruby/saved_filters/` | Generator-based saved filter model (not hardcoded). SavedFiltersGenerator creates model/presenter/permissions YAML. Presenter config via `saved_filters` block inside `advanced_filter` (enabled, display mode, max_visible_pinned). Visibility: personal/role/group/global with ownership record_rules |
86
+ | `Attachments` | `lib/lcp_ruby/model_factory/attachment_applicator.rb` | Applies Active Storage macros (has_one_attached/has_many_attached), validations (size, content_type, max_files), and variant config to dynamic models |
87
+ | `Positioning` | `lib/lcp_ruby/model_factory/positioning_applicator.rb` | Applies `positioning` gem macro to positioned models; SchemaManager creates unique indices on scope + position columns (except SQLite) |
88
+ | `Auditing` | `lib/lcp_ruby/auditing/` | Registry (available? flag), ContractValidator (audit model contract checks), AuditWriter (field diffs, JSON/custom field expansion, nested changes), Setup (boot orchestration). AuditingApplicator installs AR callbacks on audited models |
89
+ | `UserSnapshot` | `lib/lcp_ruby/user_snapshot.rb` | Captures `{id, email, name, role}` from user objects; used by auditing and userstamps |
90
+ | `BulkUpdater` | `lib/lcp_ruby/bulk_updater.rb` | `tracked_update_all` wrapper with yield hook for post-update callbacks (auditing, events) |
91
+ | `Pages` | `lib/lcp_ruby/pages/` | Resolver (slug/name lookup), ScopeContextResolver (delegates to `LcpRuby::DynamicReferences::Resolver` — see [Dynamic References](reference/dynamic-references.md) for the dotted-string gramatika and depth limits), auto-page creation from presenters, PageDefinition (name, slug, model, layout, dialog_config, zones; composite helpers: `composite?`, `semantic?`, `zones_for_area`, `tab_zones`, `has_tabs?`, `has_sidebar?`, `has_below?`, `grid_template_columns`, `form_zone`, `main_zone`), ZoneDefinition (presenter/widget zones, grid positioning, visible_when, scope_context, label_key, `default_scope`, `width` (1-12), `filters` (`:full`/`:quick`/`:none`), `record_click` (`:navigate`/`:dialog`/`:none`), `submit_redirect` (`:self`), `record_source` (`param` key); predicates: `filterable?`, `filters_quick?`, `filters_full?`, `record_click_navigate?`, `record_click_dialog?`, `record_click_none?`, `form_zone?`, `submit_redirect_self?`, `record_source?`, `record_source_param`). DB-backed pages: ContractValidator (page_config model contract), Registry (thread-safe cache), ChangeHandler (after_commit invalidation), DefinitionValidator (JSON validation on save), Setup (boot orchestration when `page_source == :model`) |
92
+ | `Widgets` | `lib/lcp_ruby/widgets/` | DataResolver (kpi_card aggregate, text i18n, list records, workflow_graph Mermaid diagram, approval_status; accepts scope_context and record; applies default_scope before zone scope), PresenterZoneResolver (scope pipeline: policy_scope → soft_delete → default_scope → zone_scope → scope_context → zone_filters → eager_loading → sort → paginate; returns zone, zone_record_slug in result), RecordSourceResolver (loads single record by ID from URL param; scope pipeline: policy_scope → soft_delete → eager_loading → find_by; returns record, presenter, layout_builder, column_set, field_value_resolver), ScopeApplicator (shared scope/model resolution, policy scope, soft delete filtering, `apply_default_scope`, scope_context WHERE/filter_* application) |
93
+ | `ViewSlots` | `lib/lcp_ruby/view_slots/` | Registry (page+slot component store with position ordering), SlotComponent (immutable value object: name, partial, position, enabled callback), SlotContext (immutable data bag for slot partials: presenter, evaluator, params, records, record, locals). ViewSlotHelper provides `render_slot` for ERB templates. 11 built-in components registered at boot + `approval_status` slot registered dynamically by `Workflow::Approval::Setup` |
94
+ | `BackgroundJobs` | `lib/lcp_ruby/background_jobs/` | Registry (thread-safe, resolver-backed), Definition (value object from YAML/DSL/DB), Setup (boot orchestration with contract validation), ExecutorJob (ActiveJob wrapper with retry/cancellation/timeout), BaseHandler (progress, logging, cancellation API), HandlerFactory (class/declarative/steps routing), StepsExecutor (multi-step sequential), Enqueue (public API with unique key dedup), 4 declarative actions (run_scope, fire_event, call_webhook, send_notification), event triggers, schedule adapter interface. Three sources: StaticSource, ModelSource, HostSource with Resolver priority merge |
95
+ | `GroupedQuery` | `lib/lcp_ruby/grouped_query/` | Builder (GROUP BY + aggregate SELECT + HAVING from presenter config), Row (value object for group rows), ResultWrapper (enum labels, null display). Supports count/sum/avg/min/max, DISTINCT, date period truncation, dot-path JOINs, row_click filter URL generation |
96
+ | `Sort` | `lib/lcp_ruby/sort/` | EnumSortOrder: CASE WHEN SQL for enum definition-order sorting, strategy resolution (definition_order/value). Used by both `apply_sort` (non-grouped) and `apply_grouped_sort` (grouped) |
97
+ | `Export` | `lib/lcp_ruby/export/` | Setup (virtual model + dialog page registration + event handler), ExportHandler (builds query, generates CSV/XLSX, saves profile/history), FieldTreeBuilder (permission-aware field picker tree with association traversal), DataGenerator (CSV with BOM + XLSX via caxlsx), ValueFormatter (enum/date/boolean/decimal formatting options) |
98
+ | `BatchActions` | `lib/lcp_ruby/batch_actions/` | BaseService (shared constructor, `each_record`, `log_item`, `finalize_batch_operation`, message builder), DestroyService (soft/hard delete with per-record permission), RestoreService (undiscard), PermanentlyDestroyService (hard delete discarded), CustomActionDispatcher (per-record iteration vs bulk execution based on `batch_capable?`, with auth checks, error handling, progress callbacks, result log). All services accept `records:, evaluator:, model_definition:, current_user:, batch_operation: nil, &progress` |
99
+ | `JsonItemWrapper` | `lib/lcp_ruby/json_item_wrapper.rb` | ActiveModel wrapper for JSON hash items; dynamic getter/setter per field from ModelDefinition; type coercion (integer, float, boolean); `validate_with_model_rules!` (presence, length, numericality, format); `to_hash` for persistence. Used by `json_field:` + `target_model:` nested sections |
100
+ | `Metrics` | `lib/lcp_ruby/metrics/` | PrometheusCheck (soft dependency), MetricDefinitions (metric constants incl. boot gauges: models/presenters/pages, request metrics with model label, permission_checks_total), Subscriber (AS::Notifications → Prometheus, view_group+model labels on requests, permission.lcp_ruby events, exception excluded from error log context), Collector (base class for host collectors with `subscribe` DSL for AS::Notifications), CollectorRegistry (auto-discovery from `app/lcp_metrics/`, subscription lifecycle), Fingerprint (error normalization), RateLimiter (in-memory throttle), ErrorRecorder (atomic upsert to error log), JsonQuery (portable JSON column queries), Setup (boot orchestration, `:auto` resolution) |
101
+
102
+ ## Controller Stack
103
+
104
+ `ApplicationController` (`app/controllers/lcp_ruby/application_controller.rb`):
105
+ - Inherits from host app's controller (configurable via `parent_controller`)
106
+ - Thin assembler that includes 9 modular concerns from `LcpRuby::Controller::*` (see below)
107
+ - Cross-cutting `instrument_request` around_action for AS::Notifications
108
+
109
+ Includable concerns (`lib/lcp_ruby/controller/`):
110
+ - `ErrorHandling` — `rescue_from MetadataError`, `RecordNotFound`
111
+ - `Authentication` — `current_user`, `effective_user` base impl, Warden integration
112
+ - `PresenterSetup` — resolves presenter + model from `:lcp_slug`, auto-registers ~11 LCP view helpers
113
+ - `Impersonation` — overrides `effective_user` when impersonating
114
+ - `Authorization` — Pundit integration, `current_evaluator`, `policy`, `policy_scope`
115
+ - `PathHelpers` — `resource_path`, `resources_path`, `edit_resource_path`, etc.
116
+ - `ViewHelpers` — sort, breadcrumbs, view group methods
117
+ - `Search` — `apply_advanced_search`, `apply_sort`, filter helpers
118
+ - `CrudHelpers` — `permitted_params`, `set_record`, `setup_show_view_objects`, `setup_index_view_objects`
119
+
120
+ Each concern has dependency guards via `method_defined?` checks in its `included do` block — including in wrong order raises a descriptive error at class load time. Host app controllers can include any subset of these concerns via the `lcp_ruby:host_controller` generator or manually.
121
+
122
+ `ResourcesController` (`app/controllers/lcp_ruby/resources_controller.rb`):
123
+ - Standard CRUD (index/show/new/create/edit/update/destroy)
124
+ - Composite pages: `show` branches on `current_page.composite?` → `load_composite_page` resolves main zone (show or form via `form_zone?`) + delegates to `load_secondary_zones` for sidebar/below/tabs; tab zones are loaded lazily via `zone` action (Turbo Frames). `zone` action at `/:slug/:id/zones/:zone_name` calls `resolve_zone_data` for unified zone dispatch (widget/record_source/presenter). `zone_params(zone)` conditionally permits `qs` (when `zone.filterable?`), `f`/`cf` (when `zone.filters_full?`). Form zones: `update` uses `submit_redirect_self?` to redirect back to show page; on validation error, `load_composite_page_for_form_error` re-renders with dirty VCs. Show-in-dialog: `show` renders `_dialog_show_frame` when `dialog_context?` (`?_dialog=1`)
125
+ - `permitted_params` filters by writable fields + association FK fields
126
+ - `apply_advanced_search` 7-step pipeline: default scope, predefined filter scope, param sanitization, custom filter interception, Ransack query, quick search (`?qs=`), custom field filters (`?cf[...]`)
127
+ - Authorization via Pundit on every action
128
+
129
+ `CustomFieldsController` (`app/controllers/lcp_ruby/custom_fields_controller.rb`):
130
+ - Nested under `/:lcp_slug/custom-fields` for managing custom field definitions
131
+ - Dual context: parent model from `:lcp_slug`, CFD model + generated presenter for views
132
+ - Records scoped by `target_model` from parent URL context (prevents cross-model access)
133
+ - Reuses `lcp_ruby/resources` views via `controller_path` override
134
+ - Separate authorization via `custom_field_definition` permissions
135
+
136
+ `ApprovalTasksController` (`app/controllers/lcp_ruby/approval_tasks_controller.rb`):
137
+ - 5 POST actions: `approve`, `reject`, `return_task`, `claim`, `delegate`
138
+ - Nested under `/:lcp_slug/:id/approval_tasks/:task_id/<action>`
139
+ - Authorizes via `show?` on the record (task-level auth handled by `TaskManager`)
140
+ - Validates task belongs to record's active approval request
141
+ - Rescues `TaskActionError`, `DelegationError` → redirect with alert flash
142
+
143
+ `DialogsController` (`app/controllers/lcp_ruby/dialogs_controller.rb`):
144
+ - Handles dialog-only pages (no slug) at `/lcp_dialog/:page_name/*`
145
+ - Resolves presenter and model from the page definition
146
+ - Supports both persistent models (AR create/update) and virtual models (JsonItemWrapper validation + `dialog_submit` event)
147
+ - Uses `DialogRendering` concern for dialog frame rendering and success responses
148
+ - `DialogRendering` concern also mixed into `ResourcesController` for `?_dialog=1` context detection
149
+
150
+ ## Routing
151
+
152
+ Engine mounts at a configurable path (default `/`). All resources use a slug-based pattern:
153
+ ```
154
+ /:lcp_slug → resources#index
155
+ /:lcp_slug/new → resources#new
156
+ /:lcp_slug/:id → resources#show
157
+ /:lcp_slug/:id/zones/:zone_name → resources#zone (GET, Turbo Frame zone content)
158
+ /:lcp_slug/:id/edit → resources#edit
159
+ /:lcp_slug/filter_fields → resources#filter_fields (GET, JSON filter metadata)
160
+ /:lcp_slug/batch_count → resources#batch_count (GET, JSON count for "select all matching")
161
+ /:lcp_slug/export_fields → resources#export_fields (GET, JSON field tree for picker)
162
+ /:lcp_slug/batch_selection → resources#batch_selection (POST, session token for large ID sets)
163
+ /:lcp_slug/batch_actions/:action_name → actions#execute_batch (POST, batch action dispatch)
164
+ /:lcp_slug/parse_ql → resources#parse_ql (POST, QL text → condition tree)
165
+ /:lcp_slug/:id/approval_tasks/:task_id/<action> → approval_tasks#<action> (POST, 5 actions)
166
+ /:lcp_slug/custom-fields → custom_fields#index
167
+ /:lcp_slug/custom-fields/manage → custom_fields#manage (bulk editor)
168
+ /:lcp_slug/custom-fields/:id → custom_fields#show
169
+ /lcp_dialog/:page_name/new → dialogs#new (dialog-only page)
170
+ /lcp_dialog/:page_name → dialogs#create (POST)
171
+ /lcp_dialog/:page_name/:id/edit → dialogs#edit
172
+ /lcp_dialog/:page_name/:id → dialogs#update (PATCH)
173
+ ```
174
+
175
+ The slug comes from the presenter YAML (e.g., `slug: deals` → `/deals`). Dialog routes use page names instead of slugs.
176
+
177
+ **Custom controller routing.** Presenters can declare `controller: "checkouts"` (full override) or `action_controllers: { new: "wizard#new" }` (per-action override) to route to host app controllers instead of LCP's `ResourcesController`. `LcpRuby::Routing::PresenterRoutes.draw_custom_controller_routes` generates explicit slug-scoped routes for these presenters and is called **before** the catch-all `scope ":lcp_slug"` block. Rails matches top-down so explicit literal-slug routes win. All custom routes set `defaults: { lcp_slug, lcp_presenter }` so existing `set_presenter_and_model` works unchanged. Ancillary routes (saved filters, custom fields, actions, transitions, approval tasks) always remain on LCP controllers. See the [Host Controller Integration reference](reference/host-controller-integration.md).
178
+
179
+ **Connecting to existing host AR models.** A model YAML can declare `bind_to: "::Employee"` to use an existing ActiveRecord class instead of creating a new dynamic model. For `bind_to:` models, both `SchemaManager` and `ModelFactory::Builder` are skipped — the existing class is registered in `LcpRuby.registry` as-is. Optional features can be opt-in via `bind_to_apply: [ransack, scopes, validations, ...]`. See the [Host Controller Integration reference](reference/host-controller-integration.md#bind_to--connecting-to-an-existing-ar-model).
180
+
181
+ ## How Association Selects Work
182
+
183
+ When a form field has `input_type: association_select` (e.g., `todo_list_id`):
184
+ 1. `LayoutBuilder.normalize_section` matches the FK field name against `association.foreign_key` metadata
185
+ 2. Creates a synthetic `FieldDefinition` (type: integer) and attaches the `AssociationDefinition`
186
+ 3. `_form.html.erb` renders a `<select>` populated from the target model's records via `LcpRuby.registry.model_for(assoc.target_model)`
187
+ 4. FK fields bypass the `field_writable?` check (they're permitted separately in the controller)
188
+
189
+ ## Permission System
190
+
191
+ Permissions YAML defines roles with: `crud` list, `fields` (readable/writable), `actions`, `scope`, `presenters`. The `PermissionEvaluator.can?` method maps action aliases (`edit` → `update`, `new` → `create`) before checking the CRUD list. Record-level rules (`record_rules`) can deny specific CRUD operations based on field conditions with role exceptions. `can_for_record?` resolves action aliases and delegates condition evaluation to `ConditionEvaluator.evaluate_any` (all 15 operators, compound/collection/dot-path/lookup). Record rules automatically hide built-in `edit`/`destroy` action buttons on index pages via `ActionSet#action_permitted_for_record?`.
192
+
193
+ ## Test Structure
194
+
195
+ - **Unit tests**: `spec/lib/lcp_ruby/` — test individual subsystems against YAML fixtures in `spec/fixtures/metadata/`
196
+ - **Integration tests**: `spec/integration/` — test full HTTP request cycle using fixtures in `spec/fixtures/integration/{todo,crm}/`
197
+ - **Dummy app**: `spec/dummy/` — minimal Rails app that mounts the engine at `/`
198
+ - **Integration helper**: `spec/support/integration_helper.rb` — provides `load_integration_metadata!` and `stub_current_user` for request specs
199
+ - Each test resets `LcpRuby.reset!` and clears Dynamic constants before running (see `spec_helper.rb`)
200
+
201
+ ### Generator regression coverage
202
+
203
+ Every platform generator's output must pass `ConfigurationValidator` clean (the same validator that `rake lcp_ruby:validate` runs in production). The harness:
204
+
205
+ - **Test harness**: `spec/support/generator_fixture.rb` — `build_minimal_app(tier:)`, `run_generator`, `validate_metadata`. Two tiers: `:tier1` (bare `config/lcp_ruby/` directories) and `:tier2` (tier1 + minimal Rails skeleton for generators that patch host files).
206
+ - **Shared example**: `spec/support/shared_examples/generator_validates_clean.rb` — runs DSL + YAML, supports `prerequisites:`, `args:`, `stub_active_storage:`.
207
+ - **Per-generator coverage**: `spec/lib/generators/lcp_ruby/all_generators_validate_spec.rb` — registry of every shipped generator. Adding a new generator means adding one entry to the `GENERATORS` array.
208
+ - **Preset stack coverage**: `preset_minimal_validate_spec.rb`, `preset_standard_validate_spec.rb`, `preset_full_validate_spec.rb` — run the full generator chain that `lcp new --preset=<name>` would invoke, on a single destination. These catch cross-generator collisions (view group positions, duplicate permission rules) that single-generator specs miss.
209
+ - **Service reference coverage**: `services_coverage_spec.rb` — static-analysis sweep that ensures every `service: <name>` reference in any template resolves to a registered built-in.
210
+ - **CI gate**: `.github/workflows/ci.yml` runs `bundle exec rspec spec/lib/generators spec/lib/lcp_ruby/metadata` on every push and pull request — new specs under `spec/lib/generators/lcp_ruby/` are picked up automatically.
211
+
212
+ Background: see `docs/improve-tasks/aggregated.md` cross-cutting theme #1 ("generator regression") and item C10.