open-loam 0.1.1 → 0.2.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 (273) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -8
  3. data/LICENSE +1 -1
  4. data/README.md +24 -24
  5. data/app/jobs/{loam → open_loam}/custom_field_reindex_job.rb +6 -6
  6. data/app/jobs/{loam → open_loam}/event_delivery_job.rb +8 -8
  7. data/app/jobs/{loam → open_loam}/event_redelivery_sweep_job.rb +4 -4
  8. data/app/jobs/{loam → open_loam}/webhook_delivery_job.rb +7 -7
  9. data/app/models/{loam → open_loam}/api_token.rb +7 -7
  10. data/app/models/{loam → open_loam}/audit_record.rb +3 -3
  11. data/app/models/{loam → open_loam}/auth_attempt.rb +5 -5
  12. data/app/models/{loam → open_loam}/business_rule.rb +10 -10
  13. data/app/models/{loam → open_loam}/business_rule_run.rb +5 -5
  14. data/app/models/{loam → open_loam}/comment.rb +9 -9
  15. data/app/models/{loam → open_loam}/config.rb +7 -7
  16. data/app/models/{loam → open_loam}/custom_field_value.rb +5 -5
  17. data/app/models/{loam → open_loam}/dashboard_widget.rb +5 -5
  18. data/app/models/open_loam/dictionary.rb +20 -0
  19. data/app/models/{loam → open_loam}/dictionary_entry.rb +7 -7
  20. data/app/models/{loam → open_loam}/event_delivery.rb +4 -4
  21. data/app/models/{loam → open_loam}/field_definition.rb +8 -8
  22. data/app/models/{loam → open_loam}/inbound_webhook_delivery.rb +4 -4
  23. data/app/models/{loam → open_loam}/inbound_webhook_source.rb +13 -13
  24. data/app/models/{loam → open_loam}/membership.rb +6 -6
  25. data/app/models/{loam → open_loam}/mfa_credential.rb +8 -8
  26. data/app/models/{loam → open_loam}/notification.rb +10 -10
  27. data/app/models/{loam → open_loam}/pending_action.rb +23 -23
  28. data/app/models/{loam → open_loam}/perspective.rb +5 -5
  29. data/app/models/{loam → open_loam}/progress_job.rb +7 -7
  30. data/app/models/{loam → open_loam}/record_lock.rb +5 -5
  31. data/app/models/{loam → open_loam}/scheduled_job.rb +7 -7
  32. data/app/models/open_loam/search_token.rb +9 -0
  33. data/app/models/{loam → open_loam}/sso_identity.rb +4 -4
  34. data/app/models/{loam → open_loam}/sso_provider.rb +8 -8
  35. data/app/models/open_loam/tenant.rb +20 -0
  36. data/app/models/{loam → open_loam}/translation.rb +5 -5
  37. data/app/models/{loam → open_loam}/webhook_endpoint.rb +6 -6
  38. data/app/views/{loam → open_loam}/attachments/_attachments.html.erb +1 -1
  39. data/app/views/{loam → open_loam}/comments/_comments.html.erb +1 -1
  40. data/app/views/{loam → open_loam}/custom_fields/_fields.html.erb +2 -2
  41. data/lib/generators/{loam → open_loam}/entity/entity_generator.rb +9 -9
  42. data/lib/generators/{loam → open_loam}/entity/templates/api_controller.rb +1 -1
  43. data/lib/generators/{loam → open_loam}/entity/templates/controller.rb +21 -21
  44. data/lib/generators/{loam → open_loam}/entity/templates/entity_test.rb +12 -12
  45. data/lib/generators/{loam → open_loam}/entity/templates/migration.rb +5 -5
  46. data/lib/generators/{loam → open_loam}/entity/templates/model.rb +10 -10
  47. data/lib/generators/{loam → open_loam}/entity/templates/policy.rb +1 -1
  48. data/lib/generators/{loam → open_loam}/entity/templates/views/_form.html.erb +4 -4
  49. data/lib/generators/{loam → open_loam}/entity/templates/views/deleted.html.erb +7 -7
  50. data/lib/generators/open_loam/entity/templates/views/edit.html.erb +3 -0
  51. data/lib/generators/open_loam/entity/templates/views/index.html.erb +90 -0
  52. data/lib/generators/open_loam/entity/templates/views/new.html.erb +3 -0
  53. data/lib/generators/open_loam/entity/templates/views/show.html.erb +36 -0
  54. data/lib/generators/{loam → open_loam}/install/install_generator.rb +47 -47
  55. data/lib/generators/open_loam/install/templates/AGENTS.md +341 -0
  56. data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_controller.rb +2 -2
  57. data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_index.html.erb +1 -1
  58. data/lib/generators/{loam → open_loam}/install/templates/admin/api_tokens_controller.rb +1 -1
  59. data/lib/generators/{loam → open_loam}/install/templates/admin/base_controller.rb +38 -38
  60. data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_controller.rb +7 -7
  61. data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_form.html.erb +2 -2
  62. data/lib/generators/{loam → open_loam}/install/templates/admin/comments_controller.rb +4 -4
  63. data/lib/generators/{loam → open_loam}/install/templates/admin/configs_controller.rb +9 -9
  64. data/lib/generators/open_loam/install/templates/admin/dashboard_controller.rb +10 -0
  65. data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_controller.rb +5 -5
  66. data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_controller.rb +5 -5
  67. data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_form.html.erb +1 -1
  68. data/lib/generators/{loam → open_loam}/install/templates/admin/dictionary_entries_controller.rb +2 -2
  69. data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_controller.rb +5 -5
  70. data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_index.html.erb +1 -1
  71. data/lib/generators/{loam → open_loam}/install/templates/admin/events_controller.rb +5 -5
  72. data/lib/generators/{loam → open_loam}/install/templates/admin/features_controller.rb +9 -9
  73. data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_controller.rb +5 -5
  74. data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_new.html.erb +2 -2
  75. data/lib/generators/{loam → open_loam}/install/templates/admin/history_controller.rb +7 -7
  76. data/lib/generators/{loam → open_loam}/install/templates/admin/history_index.html.erb +1 -1
  77. data/lib/generators/{loam → open_loam}/install/templates/admin/imports_controller.rb +12 -12
  78. data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_controller.rb +6 -6
  79. data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_new.html.erb +2 -2
  80. data/lib/generators/open_loam/install/templates/admin/layout.html.erb +76 -0
  81. data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_controller.rb +6 -6
  82. data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_controller.rb +3 -3
  83. data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_controller.rb +3 -3
  84. data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_index.html.erb +2 -2
  85. data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_controller.rb +3 -3
  86. data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_controller.rb +7 -7
  87. data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_index.html.erb +1 -1
  88. data/lib/generators/open_loam/install/templates/admin/progress_jobs_controller.rb +19 -0
  89. data/lib/generators/{loam → open_loam}/install/templates/admin/progress_jobs_index.html.erb +1 -1
  90. data/lib/generators/{loam → open_loam}/install/templates/admin/record_locks_controller.rb +4 -4
  91. data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_controller.rb +7 -7
  92. data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_form.html.erb +1 -1
  93. data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_index.html.erb +1 -1
  94. data/lib/generators/{loam → open_loam}/install/templates/admin/search_controller.rb +5 -5
  95. data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_controller.rb +32 -32
  96. data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_controller.rb +6 -6
  97. data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_form.html.erb +2 -2
  98. data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_controller.rb +5 -5
  99. data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_new.html.erb +1 -1
  100. data/lib/generators/{loam → open_loam}/install/templates/admin/translations_controller.rb +7 -7
  101. data/lib/generators/{loam → open_loam}/install/templates/admin/translations_index.html.erb +3 -3
  102. data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_controller.rb +4 -4
  103. data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_index.html.erb +1 -1
  104. data/lib/generators/{loam → open_loam}/install/templates/admin.css +1 -1
  105. data/lib/generators/{loam → open_loam}/install/templates/api_base_controller.rb +15 -15
  106. data/lib/generators/{loam → open_loam}/install/templates/guardrails_test.rb +17 -17
  107. data/lib/generators/{loam → open_loam}/install/templates/import_job.rb +7 -7
  108. data/lib/generators/{loam → open_loam}/install/templates/inbound_webhooks_controller.rb +4 -4
  109. data/lib/generators/{loam → open_loam}/install/templates/initializer.rb +74 -74
  110. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_api_tokens.rb +15 -0
  111. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_audit_records.rb +14 -0
  112. data/lib/generators/{loam/install/templates/migrations/create_loam_auth_attempts.rb → open_loam/install/templates/migrations/create_open_loam_auth_attempts.rb} +3 -3
  113. data/lib/generators/{loam/install/templates/migrations/create_loam_business_rules.rb → open_loam/install/templates/migrations/create_open_loam_business_rules.rb} +10 -10
  114. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_comments.rb +13 -0
  115. data/lib/generators/{loam/install/templates/migrations/create_loam_configs.rb → open_loam/install/templates/migrations/create_open_loam_configs.rb} +7 -7
  116. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_custom_field_values.rb +19 -0
  117. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dashboard_widgets.rb +12 -0
  118. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dictionaries.rb +11 -0
  119. data/lib/generators/{loam/install/templates/migrations/create_loam_dictionary_entries.rb → open_loam/install/templates/migrations/create_open_loam_dictionary_entries.rb} +6 -6
  120. data/lib/generators/{loam/install/templates/migrations/create_loam_event_deliveries.rb → open_loam/install/templates/migrations/create_open_loam_event_deliveries.rb} +5 -5
  121. data/lib/generators/{loam/install/templates/migrations/create_loam_field_definitions.rb → open_loam/install/templates/migrations/create_open_loam_field_definitions.rb} +4 -4
  122. data/lib/generators/{loam/install/templates/migrations/create_loam_inbound_webhooks.rb → open_loam/install/templates/migrations/create_open_loam_inbound_webhooks.rb} +9 -9
  123. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_memberships.rb +11 -0
  124. data/lib/generators/{loam/install/templates/migrations/create_loam_mfa_credentials.rb → open_loam/install/templates/migrations/create_open_loam_mfa_credentials.rb} +4 -4
  125. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_notifications.rb +15 -0
  126. data/lib/generators/{loam/install/templates/migrations/create_loam_pending_actions.rb → open_loam/install/templates/migrations/create_open_loam_pending_actions.rb} +9 -9
  127. data/lib/generators/{loam/install/templates/migrations/create_loam_perspectives.rb → open_loam/install/templates/migrations/create_open_loam_perspectives.rb} +5 -5
  128. data/lib/generators/{loam/install/templates/migrations/create_loam_progress_jobs.rb → open_loam/install/templates/migrations/create_open_loam_progress_jobs.rb} +5 -5
  129. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_record_locks.rb +16 -0
  130. data/lib/generators/{loam/install/templates/migrations/create_loam_scheduled_jobs.rb → open_loam/install/templates/migrations/create_open_loam_scheduled_jobs.rb} +5 -5
  131. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_search_tokens.rb +18 -0
  132. data/lib/generators/{loam/install/templates/migrations/create_loam_sso_providers.rb → open_loam/install/templates/migrations/create_open_loam_sso_providers.rb} +12 -12
  133. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_tenants.rb +9 -0
  134. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_translations.rb +15 -0
  135. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_webhook_endpoints.rb +13 -0
  136. data/lib/generators/{loam → open_loam}/install/templates/migrations/create_users.rb +1 -1
  137. data/lib/generators/{loam → open_loam}/install/templates/user.rb +5 -5
  138. data/lib/generators/{loam → open_loam}/primary_key_options.rb +23 -23
  139. data/lib/open-loam.rb +2 -2
  140. data/lib/{loam → open_loam}/attachable.rb +4 -4
  141. data/lib/{loam → open_loam}/auditable.rb +23 -23
  142. data/lib/{loam → open_loam}/auth_throttle.rb +10 -10
  143. data/lib/{loam → open_loam}/base32.rb +1 -1
  144. data/lib/{loam → open_loam}/bulk.rb +7 -7
  145. data/lib/{loam → open_loam}/business_rules/actions.rb +7 -7
  146. data/lib/{loam → open_loam}/business_rules/condition.rb +5 -5
  147. data/lib/{loam → open_loam}/business_rules.rb +19 -19
  148. data/lib/{loam → open_loam}/commentable.rb +6 -6
  149. data/lib/{loam → open_loam}/configs.rb +19 -19
  150. data/lib/{loam → open_loam}/cron.rb +2 -2
  151. data/lib/{loam → open_loam}/csv.rb +2 -2
  152. data/lib/{loam → open_loam}/current.rb +5 -5
  153. data/lib/{loam → open_loam}/custom_field_index.rb +23 -23
  154. data/lib/{loam → open_loam}/custom_fields.rb +17 -17
  155. data/lib/{loam → open_loam}/dashboard.rb +5 -5
  156. data/lib/{loam → open_loam}/dictionaries.rb +12 -12
  157. data/lib/{loam → open_loam}/durable_events.rb +19 -19
  158. data/lib/{loam → open_loam}/encryptable.rb +33 -33
  159. data/lib/{loam → open_loam}/encryption/cipher.rb +3 -3
  160. data/lib/{loam → open_loam}/encryption/key_provider.rb +3 -3
  161. data/lib/{loam → open_loam}/encryption.rb +11 -11
  162. data/lib/open_loam/engine.rb +57 -0
  163. data/lib/{loam → open_loam}/enrichers.rb +5 -5
  164. data/lib/{loam → open_loam}/errors.rb +10 -10
  165. data/lib/{loam → open_loam}/eval.rb +2 -2
  166. data/lib/{loam → open_loam}/event_stream.rb +14 -14
  167. data/lib/{loam → open_loam}/eventful.rb +12 -12
  168. data/lib/{loam → open_loam}/events.rb +5 -5
  169. data/lib/{loam → open_loam}/export.rb +8 -8
  170. data/lib/{loam → open_loam}/features.rb +15 -15
  171. data/lib/{loam → open_loam}/generated_key.rb +6 -6
  172. data/lib/{loam → open_loam}/import.rb +12 -12
  173. data/lib/{loam → open_loam}/inbound_webhooks.rb +7 -7
  174. data/lib/{loam → open_loam}/lifecycle.rb +25 -25
  175. data/lib/{loam/locales/loam.en.yml → open_loam/locales/open_loam.en.yml} +5 -5
  176. data/lib/{loam → open_loam}/mcp/server.rb +9 -9
  177. data/lib/{loam → open_loam}/mcp.rb +21 -21
  178. data/lib/{loam → open_loam}/notifications.rb +5 -5
  179. data/lib/{loam → open_loam}/open_api.rb +16 -16
  180. data/lib/{loam → open_loam}/overrides.rb +10 -10
  181. data/lib/{loam → open_loam}/pending_actions.rb +9 -9
  182. data/lib/{loam → open_loam}/permissions.rb +8 -8
  183. data/lib/{loam → open_loam}/perspectives.rb +9 -9
  184. data/lib/{loam → open_loam}/policy.rb +6 -6
  185. data/lib/{loam → open_loam}/progress.rb +6 -6
  186. data/lib/{loam → open_loam}/record_locks.rb +9 -9
  187. data/lib/{loam → open_loam}/scheduler.rb +20 -20
  188. data/lib/{loam → open_loam}/search/driver.rb +3 -3
  189. data/lib/{loam → open_loam}/search/like_driver.rb +5 -5
  190. data/lib/{loam → open_loam}/search/token_driver.rb +15 -15
  191. data/lib/{loam → open_loam}/search.rb +5 -5
  192. data/lib/{loam → open_loam}/searchable.rb +22 -22
  193. data/lib/{loam → open_loam}/soft_deletable.rb +10 -10
  194. data/lib/{loam → open_loam}/sso/claims.rb +1 -1
  195. data/lib/{loam → open_loam}/sso/fake_provider.rb +1 -1
  196. data/lib/{loam → open_loam}/sso/http_client.rb +3 -3
  197. data/lib/{loam → open_loam}/sso/oidc_provider.rb +2 -2
  198. data/lib/{loam → open_loam}/sso.rb +17 -17
  199. data/lib/{loam → open_loam}/telemetry.rb +6 -6
  200. data/lib/{loam → open_loam}/tenant_record.rb +10 -10
  201. data/lib/{loam → open_loam}/test_helpers.rb +4 -4
  202. data/lib/{loam → open_loam}/totp.rb +3 -3
  203. data/lib/{loam → open_loam}/translatable.rb +24 -24
  204. data/lib/{loam → open_loam}/undo.rb +11 -11
  205. data/lib/open_loam/version.rb +3 -0
  206. data/lib/{loam → open_loam}/webhooks.rb +4 -4
  207. data/lib/{loam → open_loam}/widgets.rb +9 -9
  208. data/lib/{loam → open_loam}/workflow.rb +45 -45
  209. data/lib/open_loam.rb +122 -0
  210. data/lib/tasks/{loam.rake → open_loam.rake} +43 -43
  211. data/lib/tasks/{loam_eval.rake → open_loam_eval.rake} +7 -7
  212. data/lib/tasks/open_loam_mcp.rake +20 -0
  213. metadata +242 -242
  214. data/app/models/loam/dictionary.rb +0 -20
  215. data/app/models/loam/search_token.rb +0 -9
  216. data/app/models/loam/tenant.rb +0 -20
  217. data/lib/generators/loam/entity/templates/views/edit.html.erb +0 -3
  218. data/lib/generators/loam/entity/templates/views/index.html.erb +0 -90
  219. data/lib/generators/loam/entity/templates/views/new.html.erb +0 -3
  220. data/lib/generators/loam/entity/templates/views/show.html.erb +0 -36
  221. data/lib/generators/loam/install/templates/AGENTS.md +0 -341
  222. data/lib/generators/loam/install/templates/admin/dashboard_controller.rb +0 -10
  223. data/lib/generators/loam/install/templates/admin/layout.html.erb +0 -76
  224. data/lib/generators/loam/install/templates/admin/progress_jobs_controller.rb +0 -19
  225. data/lib/generators/loam/install/templates/migrations/create_loam_api_tokens.rb +0 -15
  226. data/lib/generators/loam/install/templates/migrations/create_loam_audit_records.rb +0 -14
  227. data/lib/generators/loam/install/templates/migrations/create_loam_comments.rb +0 -13
  228. data/lib/generators/loam/install/templates/migrations/create_loam_custom_field_values.rb +0 -19
  229. data/lib/generators/loam/install/templates/migrations/create_loam_dashboard_widgets.rb +0 -12
  230. data/lib/generators/loam/install/templates/migrations/create_loam_dictionaries.rb +0 -11
  231. data/lib/generators/loam/install/templates/migrations/create_loam_memberships.rb +0 -11
  232. data/lib/generators/loam/install/templates/migrations/create_loam_notifications.rb +0 -15
  233. data/lib/generators/loam/install/templates/migrations/create_loam_record_locks.rb +0 -16
  234. data/lib/generators/loam/install/templates/migrations/create_loam_search_tokens.rb +0 -18
  235. data/lib/generators/loam/install/templates/migrations/create_loam_tenants.rb +0 -9
  236. data/lib/generators/loam/install/templates/migrations/create_loam_translations.rb +0 -15
  237. data/lib/generators/loam/install/templates/migrations/create_loam_webhook_endpoints.rb +0 -13
  238. data/lib/loam/engine.rb +0 -57
  239. data/lib/loam/version.rb +0 -3
  240. data/lib/loam.rb +0 -122
  241. data/lib/tasks/loam_mcp.rake +0 -20
  242. /data/lib/generators/{loam → open_loam}/install/templates/admin/api_tokens_index.html.erb +0 -0
  243. /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_edit.html.erb +0 -0
  244. /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_index.html.erb +0 -0
  245. /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_new.html.erb +0 -0
  246. /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_edit.html.erb +0 -0
  247. /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_index.html.erb +0 -0
  248. /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_index.html.erb +0 -0
  249. /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_index.html.erb +0 -0
  250. /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_edit.html.erb +0 -0
  251. /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_index.html.erb +0 -0
  252. /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_new.html.erb +0 -0
  253. /data/lib/generators/{loam → open_loam}/install/templates/admin/features_index.html.erb +0 -0
  254. /data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_index.html.erb +0 -0
  255. /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_new.html.erb +0 -0
  256. /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_preview.html.erb +0 -0
  257. /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_summary.html.erb +0 -0
  258. /data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_index.html.erb +0 -0
  259. /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_activated.html.erb +0 -0
  260. /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_new.html.erb +0 -0
  261. /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_show.html.erb +0 -0
  262. /data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_index.html.erb +0 -0
  263. /data/lib/generators/{loam → open_loam}/install/templates/admin/pagination.rb +0 -0
  264. /data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_index.html.erb +0 -0
  265. /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_edit.html.erb +0 -0
  266. /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_new.html.erb +0 -0
  267. /data/lib/generators/{loam → open_loam}/install/templates/admin/search_index.html.erb +0 -0
  268. /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_mfa_challenge.html.erb +0 -0
  269. /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_new.html.erb +0 -0
  270. /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_edit.html.erb +0 -0
  271. /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_index.html.erb +0 -0
  272. /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_new.html.erb +0 -0
  273. /data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_new.html.erb +0 -0
@@ -1,8 +1,8 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Base class for every tenant-scoped model. Inheriting from it is what makes
3
- # a model a "Loam entity":
3
+ # a model a "OpenLoam entity":
4
4
  #
5
- # * every query is scoped to Loam::Current.tenant via default_scope
5
+ # * every query is scoped to OpenLoam::Current.tenant via default_scope
6
6
  # * building/creating a record assigns the current tenant automatically
7
7
  # * touching the model with NO tenant in context raises MissingTenantError
8
8
  #
@@ -12,24 +12,24 @@ module Loam
12
12
  class TenantRecord < ActiveRecord::Base
13
13
  self.abstract_class = true
14
14
 
15
- # Generates the key when it is not an integer (see Loam::GeneratedKey).
16
- include Loam::GeneratedKey
15
+ # Generates the key when it is not an integer (see OpenLoam::GeneratedKey).
16
+ include OpenLoam::GeneratedKey
17
17
 
18
- belongs_to :tenant, class_name: "Loam::Tenant"
18
+ belongs_to :tenant, class_name: "OpenLoam::Tenant"
19
19
 
20
- default_scope { where(tenant_id: Loam.tenant!.id) }
20
+ default_scope { where(tenant_id: OpenLoam.tenant!.id) }
21
21
 
22
22
  validates :tenant_id, presence: true
23
23
 
24
24
  before_validation on: :create do
25
- self.tenant_id ||= Loam.tenant!.id
25
+ self.tenant_id ||= OpenLoam.tenant!.id
26
26
  end
27
27
 
28
28
  # Guardrail for writes: a record can never be saved into a foreign tenant.
29
29
  before_save do
30
- if tenant_id != Loam.tenant!.id
30
+ if tenant_id != OpenLoam.tenant!.id
31
31
  raise MissingTenantError, "Attempted to write #{self.class.name} into tenant #{tenant_id} " \
32
- "while Loam::Current.tenant is #{Loam.tenant!.id}"
32
+ "while OpenLoam::Current.tenant is #{OpenLoam.tenant!.id}"
33
33
  end
34
34
  end
35
35
  end
@@ -1,15 +1,15 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Mixed into ActiveSupport::TestCase by the install generator.
3
3
  module TestHelpers
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- setup { Loam::Current.reset }
8
- teardown { Loam::Current.reset }
7
+ setup { OpenLoam::Current.reset }
8
+ teardown { OpenLoam::Current.reset }
9
9
  end
10
10
 
11
11
  def with_tenant(tenant, actor: nil, &block)
12
- Loam.as_tenant(tenant, actor: actor, &block)
12
+ OpenLoam.as_tenant(tenant, actor: actor, &block)
13
13
  end
14
14
  end
15
15
  end
@@ -3,7 +3,7 @@ require "securerandom"
3
3
  require "uri"
4
4
  require "erb"
5
5
 
6
- module Loam
6
+ module OpenLoam
7
7
  # RFC 6238 time-based one-time passwords — the shipped second factor.
8
8
  # HMAC-SHA1, 30-second step, 6 digits, ±1 step of drift tolerance (so a code
9
9
  # entered a few seconds either side of a boundary still verifies). Hand-rolled
@@ -17,7 +17,7 @@ module Loam
17
17
  # A fresh random secret, base32-encoded for authenticator apps. 20 bytes
18
18
  # (160 bits) is the RFC-recommended size for SHA1.
19
19
  def self.generate_secret(bytes: 20)
20
- Loam::Base32.encode(SecureRandom.random_bytes(bytes))
20
+ OpenLoam::Base32.encode(SecureRandom.random_bytes(bytes))
21
21
  end
22
22
 
23
23
  # True if `code` is valid for `secret` right now.
@@ -44,7 +44,7 @@ module Loam
44
44
 
45
45
  # The HOTP code for a given step counter (RFC 4226 dynamic truncation).
46
46
  def self.code_at(secret, counter, digits: DIGITS)
47
- hmac = OpenSSL::HMAC.digest("SHA1", Loam::Base32.decode(secret), [counter].pack("Q>"))
47
+ hmac = OpenSSL::HMAC.digest("SHA1", OpenLoam::Base32.decode(secret), [counter].pack("Q>"))
48
48
  offset = hmac.bytes.last & 0x0f
49
49
  truncated = hmac[offset, 4].unpack1("N") & 0x7fffffff
50
50
  (truncated % (10**digits)).to_s.rjust(digits, "0")
@@ -1,32 +1,32 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Per-record, per-locale translations of DATA fields — a product name, a
3
3
  # category label — distinct from Rails i18n (developer UI strings, still
4
4
  # Rails-native and out of scope here).
5
5
  #
6
- # class Equipment < Loam::TenantRecord
7
- # include Loam::Translatable
6
+ # class Equipment < OpenLoam::TenantRecord
7
+ # include OpenLoam::Translatable
8
8
  # translates :name, :description
9
9
  # end
10
10
  #
11
11
  # READ OVERLAY: the field reader returns the translation for the CURRENT locale
12
- # (Loam.locale) when one exists, else the record's own COLUMN value — the base
12
+ # (OpenLoam.locale) when one exists, else the record's own COLUMN value — the base
13
13
  # is the fallback and stays authoritative for the default locale:
14
14
  #
15
- # equipment.name # => overlay for Loam.locale, else base
15
+ # equipment.name # => overlay for OpenLoam.locale, else base
16
16
  # equipment.name(locale: "de") # => explicit locale, else base
17
17
  # equipment.set_translation(:name, "de", "Bagger")
18
18
  # equipment.translations_for(:name) # => { "de" => "Bagger", ... }
19
19
  #
20
20
  # Writes still go through the ordinary `name=` writer to the base column, so
21
- # translations are purely additive rows in loam_translations — the base value
21
+ # translations are purely additive rows in open_loam_translations — the base value
22
22
  # is never overwritten or lost.
23
23
  module Translatable
24
24
  extend ActiveSupport::Concern
25
25
 
26
26
  included do
27
- class_attribute :loam_translatable_attributes, default: [].freeze, instance_writer: false
27
+ class_attribute :open_loam_translatable_attributes, default: [].freeze, instance_writer: false
28
28
 
29
- has_many :loam_translations, class_name: "Loam::Translation",
29
+ has_many :open_loam_translations, class_name: "OpenLoam::Translation",
30
30
  as: :translatable, dependent: :delete_all
31
31
  end
32
32
 
@@ -35,54 +35,54 @@ module Loam
35
35
  names = names.map(&:to_s)
36
36
 
37
37
  # An encrypted field must NOT be translatable: a translation row would
38
- # store its PLAINTEXT in loam_translations, recreating exactly the leak
39
- # Loam::Encryptable closes (same posture as searchable_by's refusal).
40
- if respond_to?(:loam_encrypted_attributes)
41
- conflict = names & loam_encrypted_attributes
38
+ # store its PLAINTEXT in open_loam_translations, recreating exactly the leak
39
+ # OpenLoam::Encryptable closes (same posture as searchable_by's refusal).
40
+ if respond_to?(:open_loam_encrypted_attributes)
41
+ conflict = names & open_loam_encrypted_attributes
42
42
  if conflict.any?
43
- raise Loam::Error,
43
+ raise OpenLoam::Error,
44
44
  "#{name}: cannot `translates` encrypted field(s) #{conflict.join(', ')} — " \
45
45
  "a translation would store plaintext. Encrypted data is not translatable."
46
46
  end
47
47
  end
48
48
 
49
- self.loam_translatable_attributes = (loam_translatable_attributes + names).freeze
49
+ self.open_loam_translatable_attributes = (open_loam_translatable_attributes + names).freeze
50
50
 
51
51
  names.each do |field|
52
52
  # The overlay reader. `read_attribute` (not super) is the base value,
53
53
  # so it works regardless of AR's lazy attribute-method definition.
54
54
  define_method(field) do |locale: nil|
55
- loam_translation_value(field, locale) || read_attribute(field)
55
+ open_loam_translation_value(field, locale) || read_attribute(field)
56
56
  end
57
57
  end
58
58
  end
59
59
 
60
- def loam_translatable?(field)
61
- loam_translatable_attributes.include?(field.to_s)
60
+ def open_loam_translatable?(field)
61
+ open_loam_translatable_attributes.include?(field.to_s)
62
62
  end
63
63
  end
64
64
 
65
65
  # The stored translation for a field in a locale (default: the current one),
66
66
  # or nil when there is none.
67
- def loam_translation_value(field, locale = nil)
68
- locale = (locale || Loam.locale).to_s
67
+ def open_loam_translation_value(field, locale = nil)
68
+ locale = (locale || OpenLoam.locale).to_s
69
69
  return nil if locale.blank?
70
70
 
71
- loam_translations.detect { |t| t.field == field.to_s && t.locale == locale }&.value
71
+ open_loam_translations.detect { |t| t.field == field.to_s && t.locale == locale }&.value
72
72
  end
73
73
 
74
74
  def set_translation(field, locale, value)
75
- raise Loam::Error, "#{field} is not translatable on #{self.class.name}" unless self.class.loam_translatable?(field)
75
+ raise OpenLoam::Error, "#{field} is not translatable on #{self.class.name}" unless self.class.open_loam_translatable?(field)
76
76
 
77
- row = loam_translations.find_or_initialize_by(field: field.to_s, locale: locale.to_s)
77
+ row = open_loam_translations.find_or_initialize_by(field: field.to_s, locale: locale.to_s)
78
78
  row.value = value
79
79
  row.save!
80
- loam_translations.reset
80
+ open_loam_translations.reset
81
81
  value
82
82
  end
83
83
 
84
84
  def translations_for(field)
85
- loam_translations.select { |t| t.field == field.to_s }.to_h { |t| [ t.locale, t.value ] }
85
+ open_loam_translations.select { |t| t.field == field.to_s }.to_h { |t| [ t.locale, t.value ] }
86
86
  end
87
87
  end
88
88
  end
@@ -1,6 +1,6 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Undo/redo built ON the audit trail (L-704). Every change already records a
3
- # Loam::AuditRecord with its changeset; undoing one applies the inverse and
3
+ # OpenLoam::AuditRecord with its changeset; undoing one applies the inverse and
4
4
  # writes a NEW audit record — so the inverse is itself undoable, and "redo" is
5
5
  # just undoing that undo entry. No separate command log to keep in sync.
6
6
  #
@@ -12,11 +12,11 @@ module Loam
12
12
  # * encrypted fields — the audit stores "[encrypted]", never the old value,
13
13
  # so there is nothing to revert to;
14
14
  # * the workflow column — a direct write is blocked by the transition gate
15
- # (Loam::Workflow), so state is undone by performing the reverse TRANSITION,
15
+ # (OpenLoam::Workflow), so state is undone by performing the reverse TRANSITION,
16
16
  # not here;
17
17
  # * fields the actor's role may not write (when a policy is supplied).
18
18
  module Undo
19
- class NotUndoableError < Loam::Error; end
19
+ class NotUndoableError < OpenLoam::Error; end
20
20
 
21
21
  IGNORE = %w[id lock_version created_at updated_at].freeze
22
22
 
@@ -53,7 +53,7 @@ module Loam
53
53
 
54
54
  def revert_fields(record, audit, policy)
55
55
  ensure_latest!(audit)
56
- workflow_column = record.class.respond_to?(:loam_workflow) ? record.class.loam_workflow&.column.to_s : nil
56
+ workflow_column = record.class.respond_to?(:open_loam_workflow) ? record.class.open_loam_workflow&.column.to_s : nil
57
57
 
58
58
  updates = {}
59
59
  (audit.changeset || {}).each do |field, values|
@@ -69,10 +69,10 @@ module Loam
69
69
  raise NotUndoableError, "nothing revertable in this change" if updates.empty?
70
70
 
71
71
  # Relabel this save's audit as "undo" so the history reads legibly (and the
72
- # entry is itself undoable = redo). loam_audit_as is the same hook
72
+ # entry is itself undoable = redo). open_loam_audit_as is the same hook
73
73
  # SoftDeletable uses for soft_delete/restore.
74
- if record.respond_to?(:loam_audit_as, true)
75
- record.send(:loam_audit_as, "undo") { record.update!(updates) }
74
+ if record.respond_to?(:open_loam_audit_as, true)
75
+ record.send(:open_loam_audit_as, "undo") { record.update!(updates) }
76
76
  else
77
77
  record.update!(updates)
78
78
  end
@@ -92,7 +92,7 @@ module Loam
92
92
  # The audit must be the record's most recent update/undo — else undoing it
93
93
  # would overwrite newer edits. Tenant-scoped via AuditRecord's default scope.
94
94
  def ensure_latest!(audit)
95
- latest = Loam::AuditRecord
95
+ latest = OpenLoam::AuditRecord
96
96
  .where(auditable_type: audit.auditable_type, auditable_id: audit.auditable_id, action: %w[update undo])
97
97
  .order(:id).last
98
98
  return if latest.nil? || latest.id == audit.id
@@ -105,7 +105,7 @@ module Loam
105
105
  # restore. Never AuditRecord#auditable, which is unscoped.
106
106
  def load_record(audit)
107
107
  klass = audit.auditable_type.safe_constantize
108
- raise NotUndoableError, "unknown type #{audit.auditable_type.inspect}" unless klass.is_a?(Class) && klass < Loam::TenantRecord
108
+ raise NotUndoableError, "unknown type #{audit.auditable_type.inspect}" unless klass.is_a?(Class) && klass < OpenLoam::TenantRecord
109
109
 
110
110
  scope = klass.respond_to?(:with_deleted) ? klass.with_deleted : klass.all
111
111
  record = scope.find_by(id: audit.auditable_id)
@@ -120,7 +120,7 @@ module Loam
120
120
  end
121
121
 
122
122
  def ensure_current_tenant!(audit)
123
- raise NotUndoableError, "not in this tenant" unless audit.tenant_id == Loam.tenant!.id
123
+ raise NotUndoableError, "not in this tenant" unless audit.tenant_id == OpenLoam.tenant!.id
124
124
  end
125
125
  end
126
126
  end
@@ -0,0 +1,3 @@
1
+ module OpenLoam
2
+ VERSION = "0.2.0"
3
+ end
@@ -1,12 +1,12 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Domain events, delivered over HTTP to whoever asked for them.
3
3
  #
4
- # One global subscriber listens to every Loam event and, in the tenant the
4
+ # One global subscriber listens to every OpenLoam event and, in the tenant the
5
5
  # event was published in, enqueues a delivery per matching active endpoint.
6
6
  # Matching happens at dispatch time rather than at subscribe time because
7
7
  # endpoints are data: a tenant can add one from the admin without a reboot.
8
8
  module Webhooks
9
- # Wired once from Loam::Engine. Idempotent: subscribing twice would deliver
9
+ # Wired once from OpenLoam::Engine. Idempotent: subscribing twice would deliver
10
10
  # every event twice.
11
11
  def self.subscribe!
12
12
  @subscription ||= Events.subscribe_all { |event_name, payload| dispatch(event_name, payload) }
@@ -22,7 +22,7 @@ module Loam
22
22
  # and scalars by convention, never records.
23
23
  deliverable = payload.transform_keys(&:to_s)
24
24
 
25
- Loam.as_tenant(tenant) do
25
+ OpenLoam.as_tenant(tenant) do
26
26
  WebhookEndpoint.active.each do |endpoint|
27
27
  next unless endpoint.matches?(event_name)
28
28
 
@@ -1,9 +1,9 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # A registry of dashboard widgets — small, module-provided tiles (a metric, a
3
3
  # short list) shown on the admin home. A widget is a DATA PROVIDER plus a
4
4
  # title and an optional role filter; it never renders arbitrary code:
5
5
  #
6
- # Loam::Widgets.register(key: "open_rentals", title: "Open rentals", roles: %w[manager]) do |actor|
6
+ # OpenLoam::Widgets.register(key: "open_rentals", title: "Open rentals", roles: %w[manager]) do |actor|
7
7
  # { kind: "count", value: Rental.where(status: "open").count } # tenant-scoped query
8
8
  # end
9
9
  #
@@ -37,33 +37,33 @@ module Loam
37
37
  # can't see it (so its data is never computed), otherwise
38
38
  # { key, title, data } — or { key, title, error: } when the provider raises.
39
39
  def resolve(key, actor:, role:)
40
- return nil if Loam::Overrides.disabled?(:widgets, key) # customization without forking
40
+ return nil if OpenLoam::Overrides.disabled?(:widgets, key) # customization without forking
41
41
 
42
42
  widget = find(key)
43
43
  return nil unless widget&.visible_to?(role)
44
44
 
45
- provider = Loam::Overrides.replacement(:widgets, key) || widget.provider
45
+ provider = OpenLoam::Overrides.replacement(:widgets, key) || widget.provider
46
46
  { key: widget.key, title: widget.title, data: provider.call(actor) }
47
47
  rescue StandardError => error
48
48
  { key: widget&.key, title: widget&.title, error: error.message }
49
49
  end
50
50
 
51
- # The widgets every Loam app starts with — registered at boot from the
51
+ # The widgets every OpenLoam app starts with — registered at boot from the
52
52
  # engine, so a fresh install has a useful default dashboard.
53
53
  def register_builtins!
54
54
  register(key: "audit_recent", title: "Recent activity") do |_actor|
55
- items = Loam::AuditRecord.order(created_at: :desc).limit(8)
55
+ items = OpenLoam::AuditRecord.order(created_at: :desc).limit(8)
56
56
  .map { |a| "#{a.action} #{a.auditable_type} ##{a.auditable_id}" }
57
57
  { kind: "list", items: items }
58
58
  end
59
59
  register(key: "notifications_unread", title: "Unread notifications") do |actor|
60
- { kind: "count", value: Loam::Notification.unread.where(user_id: actor&.id).count }
60
+ { kind: "count", value: OpenLoam::Notification.unread.where(user_id: actor&.id).count }
61
61
  end
62
62
  register(key: "pending_approvals", title: "Pending approvals", roles: %w[manager]) do |_actor|
63
- { kind: "count", value: Loam::PendingAction.pending.count }
63
+ { kind: "count", value: OpenLoam::PendingAction.pending.count }
64
64
  end
65
65
  register(key: "open_progress", title: "Running tasks") do |_actor|
66
- { kind: "count", value: Loam::ProgressJob.where(status: "running").count }
66
+ { kind: "count", value: OpenLoam::ProgressJob.where(status: "running").count }
67
67
  end
68
68
  end
69
69
 
@@ -1,9 +1,9 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Declarative state machine for a tenant-scoped entity: the states a record
3
3
  # can be in, the legal moves between them, and who may make each move.
4
4
  #
5
- # class PurchaseOrder < Loam::TenantRecord
6
- # include Loam::Workflow
5
+ # class PurchaseOrder < OpenLoam::TenantRecord
6
+ # include OpenLoam::Workflow
7
7
  #
8
8
  # workflow :status, initial: "draft" do
9
9
  # state "draft"
@@ -18,14 +18,14 @@ module Loam
18
18
  # order.submit! # draft -> pending_approval, publishes
19
19
  # # "<domain>.purchase_order.submit"
20
20
  # order.workflow_transitions_available # => [:approve] for a manager, [] for anyone else
21
- # PurchaseOrder.loam_workflow # the frozen definition, for agents and admin UI
21
+ # PurchaseOrder.open_loam_workflow # the frozen definition, for agents and admin UI
22
22
  #
23
23
  # What this buys over hand-rolled `if status == "draft"`: an illegal move
24
24
  # raises instead of silently writing a bad value, the roles that may move a
25
25
  # record are declared in one readable place instead of scattered across
26
26
  # controllers, and the whole machine is introspectable.
27
27
  #
28
- # The state change itself is an ordinary attribute write, so Loam::Auditable
28
+ # The state change itself is an ordinary attribute write, so OpenLoam::Auditable
29
29
  # records it like any other change — a workflow adds no second audit trail.
30
30
  module Workflow
31
31
  extend ActiveSupport::Concern
@@ -99,22 +99,22 @@ module Loam
99
99
 
100
100
  included do
101
101
  # nil until `workflow` is called; inherited by subclasses.
102
- class_attribute :loam_workflow, instance_writer: false, default: nil
102
+ class_attribute :open_loam_workflow, instance_writer: false, default: nil
103
103
 
104
104
  # THE gate: the workflow column may only change through a transition
105
- # (loam_perform_transition!), which enforces from-state and role. A direct
105
+ # (open_loam_perform_transition!), which enforces from-state and role. A direct
106
106
  # write — the edit form, Bulk.set_field, an import, a business-rule
107
107
  # set_field — would otherwise let a member self-"approve", skipping the
108
108
  # transition's roles:. Closing it here closes ALL paths at once. Creation
109
109
  # (the initial state) is exempt (`on: :update`).
110
- validate :loam_workflow_column_only_via_transition, on: :update
110
+ validate :open_loam_workflow_column_only_via_transition, on: :update
111
111
  end
112
112
 
113
113
  class_methods do
114
114
  # The DSL. `initial:` defaults to the first declared state.
115
115
  def workflow(column, initial: nil, &block)
116
116
  definition = Builder.new(column, initial).build(&block)
117
- self.loam_workflow = definition
117
+ self.open_loam_workflow = definition
118
118
 
119
119
  before_validation on: :create do
120
120
  self[definition.column] = definition.initial if self[definition.column].blank?
@@ -125,29 +125,29 @@ module Loam
125
125
  validates definition.column,
126
126
  inclusion: { in: definition.states, message: "is not one of: #{definition.states.join(', ')}" }
127
127
 
128
- include loam_workflow_module(definition)
128
+ include open_loam_workflow_module(definition)
129
129
  end
130
130
 
131
131
  # Transition and predicate methods live in their own module rather than
132
132
  # on the class, so an app can override `submit!` and still call `super`.
133
- def loam_workflow_module(definition)
133
+ def open_loam_workflow_module(definition)
134
134
  model = self
135
135
 
136
136
  Module.new do
137
137
  definition.transitions.each_value do |transition|
138
- define_method("#{transition.name}!") { loam_perform_transition!(transition) }
138
+ define_method("#{transition.name}!") { open_loam_perform_transition!(transition) }
139
139
  end
140
140
 
141
141
  definition.states.each do |state|
142
142
  predicate = "#{state}?"
143
- next unless model.loam_workflow_predicate_free?(predicate)
143
+ next unless model.open_loam_workflow_predicate_free?(predicate)
144
144
 
145
145
  # A state predicate must never shadow a real column: DamageReport
146
146
  # has both a workflow state "approved" and an `approved` boolean
147
147
  # column, and `record.approved?` has to stay the column's. The
148
148
  # column check happens at CALL time, not class-load time — at load
149
149
  # the schema may not be readable yet (fresh CI database, db:create),
150
- # and a load-time decision made Loam behave differently on CI than
150
+ # and a load-time decision made OpenLoam behave differently on CI than
151
151
  # on a warmed-up dev machine.
152
152
  define_method(predicate) do
153
153
  if self.class.columns_hash.key?(state)
@@ -162,41 +162,41 @@ module Loam
162
162
 
163
163
  # Explicitly defined methods still win — only truly free names get a
164
164
  # workflow predicate. Column collisions are handled inside the predicate
165
- # itself (see loam_workflow_module), where the schema is reliably known.
166
- def loam_workflow_predicate_free?(predicate)
165
+ # itself (see open_loam_workflow_module), where the schema is reliably known.
166
+ def open_loam_workflow_predicate_free?(predicate)
167
167
  !method_defined?(predicate) && !private_method_defined?(predicate)
168
168
  end
169
169
  end
170
170
 
171
171
  # Transition names that are legal right now: from this record's state, for
172
- # the actor in Loam::Current. Never raises — an admin screen asks this to
172
+ # the actor in OpenLoam::Current. Never raises — an admin screen asks this to
173
173
  # decide which buttons to render.
174
174
  def workflow_transitions_available
175
- role = loam_workflow_role
175
+ role = open_loam_workflow_role
176
176
 
177
- self.class.loam_workflow.transitions_from(loam_workflow_state)
177
+ self.class.open_loam_workflow.transitions_from(open_loam_workflow_state)
178
178
  .select { |transition| transition.roles.empty? || transition.roles.include?(role) }
179
179
  .map(&:name)
180
180
  end
181
181
 
182
- def loam_workflow_state
183
- self[self.class.loam_workflow.column].to_s
182
+ def open_loam_workflow_state
183
+ self[self.class.open_loam_workflow.column].to_s
184
184
  end
185
185
 
186
186
  private
187
187
 
188
- def loam_workflow_column_only_via_transition
189
- return unless self.class.loam_workflow
188
+ def open_loam_workflow_column_only_via_transition
189
+ return unless self.class.open_loam_workflow
190
190
 
191
- column = self.class.loam_workflow.column
191
+ column = self.class.open_loam_workflow.column
192
192
  return unless attribute_changed?(column)
193
- return if @loam_in_transition
193
+ return if @open_loam_in_transition
194
194
 
195
195
  errors.add(column, "can only change through a workflow transition, not a direct write")
196
196
  end
197
197
 
198
- def loam_perform_transition!(transition)
199
- from = loam_workflow_state
198
+ def open_loam_perform_transition!(transition)
199
+ from = open_loam_workflow_state
200
200
 
201
201
  unless transition.from.include?(from)
202
202
  raise InvalidTransitionError,
@@ -204,53 +204,53 @@ module Loam
204
204
  "but this record is #{from.inspect}"
205
205
  end
206
206
 
207
- loam_authorize_transition!(transition)
207
+ open_loam_authorize_transition!(transition)
208
208
 
209
- self[self.class.loam_workflow.column] = transition.to
209
+ self[self.class.open_loam_workflow.column] = transition.to
210
210
  begin
211
- @loam_in_transition = true # tells the guard THIS column change is blessed
211
+ @open_loam_in_transition = true # tells the guard THIS column change is blessed
212
212
  save!
213
213
  ensure
214
- @loam_in_transition = false
214
+ @open_loam_in_transition = false
215
215
  end
216
216
 
217
- Loam::Events.publish(
218
- "#{loam_workflow_event_domain}.#{model_name.param_key}.#{transition.name}",
217
+ OpenLoam::Events.publish(
218
+ "#{open_loam_workflow_event_domain}.#{model_name.param_key}.#{transition.name}",
219
219
  id: id, from: from, to: transition.to
220
220
  )
221
221
 
222
222
  self
223
223
  end
224
224
 
225
- def loam_authorize_transition!(transition)
225
+ def open_loam_authorize_transition!(transition)
226
226
  return if transition.roles.empty?
227
227
 
228
228
  allowed = transition.roles.join(", ")
229
- unless Loam::Current.actor
229
+ unless OpenLoam::Current.actor
230
230
  raise NotAuthorizedError,
231
231
  "#{self.class.name}##{transition.name}! is restricted to #{allowed}, but there is no actor in " \
232
- "Loam::Current — wrap the call in Loam.as_tenant(tenant, actor: user) { ... }"
232
+ "OpenLoam::Current — wrap the call in OpenLoam.as_tenant(tenant, actor: user) { ... }"
233
233
  end
234
234
 
235
- return if transition.roles.include?(loam_workflow_role)
235
+ return if transition.roles.include?(open_loam_workflow_role)
236
236
 
237
237
  raise NotAuthorizedError,
238
238
  "#{self.class.name}##{transition.name}! is restricted to #{allowed}; " \
239
- "this actor's role is #{loam_workflow_role.inspect}"
239
+ "this actor's role is #{open_loam_workflow_role.inspect}"
240
240
  end
241
241
 
242
- # Role resolution deliberately goes through Loam::Policy: "your role" means
242
+ # Role resolution deliberately goes through OpenLoam::Policy: "your role" means
243
243
  # exactly one thing — your membership role in the current tenant — here, in
244
244
  # policies, and in the admin.
245
- def loam_workflow_role
246
- actor = Loam::Current.actor
247
- actor && Loam::Policy.new(actor, self).role
245
+ def open_loam_workflow_role
246
+ actor = OpenLoam::Current.actor
247
+ actor && OpenLoam::Policy.new(actor, self).role
248
248
  end
249
249
 
250
250
  # Transitions publish into the model's own event domain when it has one
251
- # (Loam::Eventful), so workflow events sit beside the lifecycle events.
252
- def loam_workflow_event_domain
253
- self.class.respond_to?(:loam_event_domain) ? self.class.loam_event_domain : "app"
251
+ # (OpenLoam::Eventful), so workflow events sit beside the lifecycle events.
252
+ def open_loam_workflow_event_domain
253
+ self.class.respond_to?(:open_loam_event_domain) ? self.class.open_loam_event_domain : "app"
254
254
  end
255
255
  end
256
256
  end