open-loam 0.1.0 → 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 +48 -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,16 +1,16 @@
1
- class CreateLoamPendingActions < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamPendingActions < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_pending_actions<%= loam_id_option %> do |t|
4
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
5
- t.<%= loam_key_column_type %> :actor_id<%= loam_key_limit_option %> # who staged it (the proposer)
3
+ create_table :open_loam_pending_actions<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
+ t.<%= open_loam_key_column_type %> :actor_id<%= open_loam_key_limit_option %> # who staged it (the proposer)
6
6
  t.string :status, null: false, default: "pending"
7
7
  t.string :action_type, null: false # create / update / destroy
8
8
  t.string :target_type # the model being mutated
9
- t.<%= loam_key_column_type %> :target_id<%= loam_key_limit_option %> # null for a staged create
9
+ t.<%= open_loam_key_column_type %> :target_id<%= open_loam_key_limit_option %> # null for a staged create
10
10
  t.text :changeset # encrypted JSON of the proposed changes
11
11
  t.text :summary, null: false # human-readable description
12
12
  t.string :idempotency_key, null: false # keyed HMAC; same proposal collapses to one row
13
- t.<%= loam_key_column_type %> :reviewed_by_id<%= loam_key_limit_option %> # the approving/rejecting manager
13
+ t.<%= open_loam_key_column_type %> :reviewed_by_id<%= open_loam_key_limit_option %> # the approving/rejecting manager
14
14
  t.datetime :reviewed_at
15
15
  t.text :result # execution outcome, or "rejected: <reason>"
16
16
  t.text :error # execution failure message
@@ -19,8 +19,8 @@ class CreateLoamPendingActions < ActiveRecord::Migration[<%= ActiveRecord::VERSI
19
19
  # One row per distinct proposal per tenant.
20
20
  # Only ONE PENDING row per proposal per tenant — a rejected/executed row with
21
21
  # the same key may coexist, so a rejected proposal can be re-staged later.
22
- add_index :loam_pending_actions, %i[tenant_id idempotency_key], unique: true,
23
- where: "status = 'pending'", name: "index_loam_pending_actions_pending_key"
24
- add_index :loam_pending_actions, %i[tenant_id status]
22
+ add_index :open_loam_pending_actions, %i[tenant_id idempotency_key], unique: true,
23
+ where: "status = 'pending'", name: "index_open_loam_pending_actions_pending_key"
24
+ add_index :open_loam_pending_actions, %i[tenant_id status]
25
25
  end
26
26
  end
@@ -1,10 +1,10 @@
1
- class CreateLoamPerspectives < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamPerspectives < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_perspectives<%= loam_id_option %> do |t|
4
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
3
+ create_table :open_loam_perspectives<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
5
  t.string :entity_type, null: false # which entity this view is for
6
6
  t.string :name, null: false # human label
7
- t.<%= loam_key_column_type %> :owner_id<%= loam_key_limit_option %> # the user who owns a private view
7
+ t.<%= open_loam_key_column_type %> :owner_id<%= open_loam_key_limit_option %> # the user who owns a private view
8
8
  t.string :visibility, null: false, default: "private" # private / role / tenant
9
9
  t.string :role # set when visibility is "role"
10
10
  t.boolean :is_default, null: false, default: false
@@ -12,6 +12,6 @@ class CreateLoamPerspectives < ActiveRecord::Migration[<%= ActiveRecord::VERSION
12
12
  t.integer :lock_version, null: false, default: 0 # optimistic locking
13
13
  t.timestamps
14
14
  end
15
- add_index :loam_perspectives, %i[tenant_id entity_type]
15
+ add_index :open_loam_perspectives, %i[tenant_id entity_type]
16
16
  end
17
17
  end
@@ -1,7 +1,7 @@
1
- class CreateLoamProgressJobs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamProgressJobs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_progress_jobs<%= loam_id_option %> do |t|
4
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
3
+ create_table :open_loam_progress_jobs<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
5
  t.string :key # optional caller-chosen id (e.g. "reindex:Gadget")
6
6
  t.string :name, null: false # human label
7
7
  t.string :status, null: false, default: "running" # running / completed / failed / cancelled
@@ -9,12 +9,12 @@ class CreateLoamProgressJobs < ActiveRecord::Migration[<%= ActiveRecord::VERSION
9
9
  t.integer :completed, null: false, default: 0
10
10
  t.text :message # latest status line
11
11
  t.text :error # set when failed
12
- t.<%= loam_key_column_type %> :actor_id<%= loam_key_limit_option %> # who started it
12
+ t.<%= open_loam_key_column_type %> :actor_id<%= open_loam_key_limit_option %> # who started it
13
13
  t.datetime :started_at
14
14
  t.datetime :finished_at
15
15
  t.json :result # structured result for a finished job (e.g. an import summary)
16
16
  t.timestamps # updated_at is the heartbeat
17
17
  end
18
- add_index :loam_progress_jobs, %i[tenant_id status]
18
+ add_index :open_loam_progress_jobs, %i[tenant_id status]
19
19
  end
20
20
  end
@@ -0,0 +1,16 @@
1
+ class CreateOpenLoamRecordLocks < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_record_locks<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
+ t.string :lockable_type, null: false
6
+ t.<%= open_loam_key_column_type %> :lockable_id<%= open_loam_key_limit_option %>, null: false
7
+ t.references :locked_by, null: false, foreign_key: { to_table: :users }<%= open_loam_type_option %>
8
+ t.string :token, null: false
9
+ t.datetime :expires_at, null: false # TTL; an expired lock is treated as free
10
+ t.timestamps # updated_at is the heartbeat
11
+ end
12
+ # One advisory lock per record.
13
+ add_index :open_loam_record_locks, %i[tenant_id lockable_type lockable_id], unique: true,
14
+ name: "index_open_loam_record_locks_on_lockable"
15
+ end
16
+ end
@@ -1,7 +1,7 @@
1
- class CreateLoamScheduledJobs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamScheduledJobs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_scheduled_jobs<%= loam_id_option %> do |t|
4
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
3
+ create_table :open_loam_scheduled_jobs<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
5
  t.string :key, null: false # unique per tenant
6
6
  t.string :name, null: false
7
7
  t.string :job_class, null: false # a whitelisted ActiveJob class name
@@ -14,7 +14,7 @@ class CreateLoamScheduledJobs < ActiveRecord::Migration[<%= ActiveRecord::VERSIO
14
14
  t.boolean :active, null: false, default: true
15
15
  t.timestamps
16
16
  end
17
- add_index :loam_scheduled_jobs, %i[tenant_id key], unique: true
18
- add_index :loam_scheduled_jobs, %i[active next_run_at locked_until]
17
+ add_index :open_loam_scheduled_jobs, %i[tenant_id key], unique: true
18
+ add_index :open_loam_scheduled_jobs, %i[active next_run_at locked_until]
19
19
  end
20
20
  end
@@ -0,0 +1,18 @@
1
+ class CreateOpenLoamSearchTokens < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_search_tokens<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
+ t.string :searchable_type, null: false # the entity class name (e.g. "Gadget")
6
+ t.<%= open_loam_key_column_type %> :searchable_id<%= open_loam_key_limit_option %>, null: false # the record it indexes
7
+ t.string :token, null: false # one normalized word
8
+ end
9
+ # The match subquery filters by (tenant, type, token); index maintenance
10
+ # deletes by (tenant, type, record). One index each — no timestamps: these
11
+ # are plumbing rows written with insert_all/delete_all.
12
+ #
13
+ # Shipped even though the default LikeDriver never uses it, so switching to
14
+ # OpenLoam::Search::TokenDriver is a one-line initializer change, not a migration.
15
+ add_index :open_loam_search_tokens, %i[tenant_id searchable_type token]
16
+ add_index :open_loam_search_tokens, %i[tenant_id searchable_type searchable_id]
17
+ end
18
+ end
@@ -1,7 +1,7 @@
1
- class CreateLoamSsoProviders < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamSsoProviders < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_sso_providers<%= loam_id_option %> do |t|
4
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
3
+ create_table :open_loam_sso_providers<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
5
  t.string :name, null: false
6
6
  t.string :protocol, null: false, default: "oidc" # "oidc" shipped; "saml" is a seam
7
7
  t.string :issuer # OIDC discovery base (.well-known)
@@ -9,26 +9,26 @@ class CreateLoamSsoProviders < ActiveRecord::Migration[<%= ActiveRecord::VERSION
9
9
  t.text :client_secret # ENCRYPTED at rest (tenant-scoped key)
10
10
  t.string :domain, null: false # email domain for home-realm discovery
11
11
  t.string :jit_role, null: false, default: "employee" # role for JIT-provisioned users
12
- t.json :group_role_map, null: false, default: {} # IdP group -> Loam role (first match wins)
12
+ t.json :group_role_map, null: false, default: {} # IdP group -> OpenLoam role (first match wins)
13
13
  t.boolean :active, null: false, default: true
14
14
  t.timestamps
15
15
  end
16
16
  # HRD resolves a provider by email domain, cross-tenant, before login — so the
17
17
  # domain is globally unique (one owning IdP per domain).
18
- add_index :loam_sso_providers, :domain, unique: true
19
- add_index :loam_sso_providers, %i[tenant_id active]
18
+ add_index :open_loam_sso_providers, :domain, unique: true
19
+ add_index :open_loam_sso_providers, %i[tenant_id active]
20
20
 
21
21
  # The durable link between an external identity (provider + subject) and a
22
22
  # local User — the primary lookup on callback (email can change at the IdP,
23
23
  # `sub` does not).
24
- create_table :loam_sso_identities<%= loam_id_option %> do |t|
25
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
26
- t.references :sso_provider, null: false, foreign_key: { to_table: :loam_sso_providers }<%= loam_type_option %>
27
- t.<%= loam_key_column_type %> :user_id<%= loam_key_limit_option %>, null: false # the local User this identity belongs to
24
+ create_table :open_loam_sso_identities<%= open_loam_id_option %> do |t|
25
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
26
+ t.references :sso_provider, null: false, foreign_key: { to_table: :open_loam_sso_providers }<%= open_loam_type_option %>
27
+ t.<%= open_loam_key_column_type %> :user_id<%= open_loam_key_limit_option %>, null: false # the local User this identity belongs to
28
28
  t.string :sub, null: false # the IdP's stable subject identifier
29
29
  t.timestamps
30
30
  end
31
- add_index :loam_sso_identities, %i[sso_provider_id sub], unique: true
32
- add_index :loam_sso_identities, :user_id
31
+ add_index :open_loam_sso_identities, %i[sso_provider_id sub], unique: true
32
+ add_index :open_loam_sso_identities, :user_id
33
33
  end
34
34
  end
@@ -0,0 +1,9 @@
1
+ class CreateOpenLoamTenants < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_tenants<%= open_loam_id_option %> do |t|
4
+ t.string :name, null: false
5
+ t.string :slug, null: false, index: { unique: true }
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ class CreateOpenLoamTranslations < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_translations<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
+ t.string :translatable_type, null: false
6
+ t.<%= open_loam_key_column_type %> :translatable_id<%= open_loam_key_limit_option %>, null: false
7
+ t.string :locale, null: false # "en", "de", "pl"
8
+ t.string :field, null: false # the translated attribute
9
+ t.text :value # the per-locale content
10
+ t.timestamps
11
+ end
12
+ add_index :open_loam_translations, %i[translatable_type translatable_id locale field],
13
+ unique: true, name: "index_open_loam_translations_unique"
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class CreateOpenLoamWebhookEndpoints < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_webhook_endpoints<%= open_loam_id_option %> do |t|
4
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
5
+ t.string :url, null: false
6
+ t.string :event_pattern, null: false
7
+ t.string :secret, null: false
8
+ t.boolean :active, null: false, default: true
9
+ t.timestamps
10
+ end
11
+ add_index :open_loam_webhook_endpoints, %i[tenant_id active]
12
+ end
13
+ end
@@ -1,6 +1,6 @@
1
1
  class CreateUsers < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :users<%= loam_id_option %> do |t|
3
+ create_table :users<%= open_loam_id_option %> do |t|
4
4
  t.string :name, null: false
5
5
  t.string :email, null: false
6
6
  t.string :password_digest, null: false
@@ -1,15 +1,15 @@
1
1
  # Minimal actor model. Deliberately NOT tenant-scoped: a user can belong to
2
- # many tenants via Loam::Membership (role is per tenant). Swap in your real
3
- # auth (Devise, OmniAuth, SSO) later — Loam only needs an `id` and, for the
2
+ # many tenants via OpenLoam::Membership (role is per tenant). Swap in your real
3
+ # auth (Devise, OmniAuth, SSO) later — OpenLoam only needs an `id` and, for the
4
4
  # bundled admin login, something that answers `authenticate_by`.
5
5
  class User < ApplicationRecord
6
- # Loam's foreign keys point at this table, so its key has to be generated
6
+ # OpenLoam's foreign keys point at this table, so its key has to be generated
7
7
  # the same way theirs are when the app does not use integer keys.
8
- include Loam::GeneratedKey
8
+ include OpenLoam::GeneratedKey
9
9
 
10
10
  has_secure_password
11
11
 
12
- has_many :loam_memberships, class_name: "Loam::Membership"
12
+ has_many :open_loam_memberships, class_name: "OpenLoam::Membership"
13
13
 
14
14
  validates :name, presence: true
15
15
  validates :email, presence: true, uniqueness: true
@@ -1,8 +1,8 @@
1
- module Loam
1
+ module OpenLoam
2
2
  module Generators
3
- # Shared primary-key shaping for `loam:install` and `loam:entity`.
3
+ # Shared primary-key shaping for `open_loam:install` and `open_loam:entity`.
4
4
  #
5
- # Loam's migrations used to spell every key `bigint` — implicitly in
5
+ # OpenLoam's migrations used to spell every key `bigint` — implicitly in
6
6
  # `create_table`, and explicitly in `t.references` and the polymorphic
7
7
  # `*_id` columns. In an app whose own tables use string or uuid keys the
8
8
  # foreign keys then do not line up with the tables they point at, and every
@@ -10,7 +10,7 @@ module Loam
10
10
  #
11
11
  # The key type is taken from, in order: an explicit --primary-key-type, the
12
12
  # host app's own `config.generators` setting (so an app that already told
13
- # Rails what its keys look like does not have to tell Loam separately), and
13
+ # Rails what its keys look like does not have to tell OpenLoam separately), and
14
14
  # bigint as the Rails default.
15
15
  #
16
16
  # The templates ask for the *rendered fragment* rather than the type, so
@@ -34,15 +34,15 @@ module Loam
34
34
 
35
35
  private
36
36
 
37
- def loam_key_type
38
- @loam_key_type ||= begin
37
+ def open_loam_key_type
38
+ @open_loam_key_type ||= begin
39
39
  requested = (options[:primary_key_type] || host_app_primary_key_type).to_s
40
40
  requested = "bigint" if requested.empty?
41
41
 
42
42
  unless SUPPORTED.include?(requested)
43
43
  raise Thor::Error,
44
- "Unsupported --primary-key-type #{requested.inspect}. Loam generates #{SUPPORTED.join(', ')}. " \
45
- "A key type Loam does not know how to size would produce migrations that look right and " \
44
+ "Unsupported --primary-key-type #{requested.inspect}. OpenLoam generates #{SUPPORTED.join(', ')}. " \
45
+ "A key type OpenLoam does not know how to size would produce migrations that look right and " \
46
46
  "do not line up with your tables."
47
47
  end
48
48
 
@@ -60,40 +60,40 @@ module Loam
60
60
  nil
61
61
  end
62
62
 
63
- def loam_key_limit
63
+ def open_loam_key_limit
64
64
  return options[:key_limit].to_i if options[:key_limit]
65
65
 
66
- loam_key_type == :string ? DEFAULT_STRING_LIMIT : nil
66
+ open_loam_key_type == :string ? DEFAULT_STRING_LIMIT : nil
67
67
  end
68
68
 
69
69
  # Appended to `create_table :x` — "" for bigint, so the default path is
70
70
  # byte-for-byte what it was.
71
- def loam_id_option
72
- return "" if loam_key_type == :bigint
71
+ def open_loam_id_option
72
+ return "" if open_loam_key_type == :bigint
73
73
 
74
- "#{loam_key_fragment.sub('type:', 'id:')}"
74
+ "#{open_loam_key_fragment.sub('type:', 'id:')}"
75
75
  end
76
76
 
77
77
  # Appended inside `t.references :x, ...`.
78
- def loam_type_option
79
- return "" if loam_key_type == :bigint
78
+ def open_loam_type_option
79
+ return "" if open_loam_key_type == :bigint
80
80
 
81
- loam_key_fragment
81
+ open_loam_key_fragment
82
82
  end
83
83
 
84
84
  # The bare column type for a polymorphic or un-constrained `*_id`, which
85
85
  # cannot use t.references.
86
- def loam_key_column_type
87
- loam_key_type
86
+ def open_loam_key_column_type
87
+ open_loam_key_type
88
88
  end
89
89
 
90
- def loam_key_limit_option
91
- loam_key_limit ? ", limit: #{loam_key_limit}" : ""
90
+ def open_loam_key_limit_option
91
+ open_loam_key_limit ? ", limit: #{open_loam_key_limit}" : ""
92
92
  end
93
93
 
94
- def loam_key_fragment
95
- fragment = ", type: :#{loam_key_type}"
96
- fragment += ", limit: #{loam_key_limit}" if loam_key_limit
94
+ def open_loam_key_fragment
95
+ fragment = ", type: :#{open_loam_key_type}"
96
+ fragment += ", limit: #{open_loam_key_limit}" if open_loam_key_limit
97
97
  fragment
98
98
  end
99
99
  end
data/lib/open-loam.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # Bundler auto-requires the gem's name ("open-loam") on load. The library's
2
- # entry point and whole namespace are `loam` / `Loam::` — the gem is only
2
+ # entry point and whole namespace are `open_loam` / `OpenLoam::` — the gem is only
3
3
  # *distributed* as open-loam (the plain `loam` name is taken on RubyGems). This
4
4
  # shim bridges the two so `gem "open-loam"` works with the default require.
5
- require_relative "loam"
5
+ require_relative "open_loam"
@@ -1,10 +1,10 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Files on a record, via ActiveStorage:
3
3
  #
4
4
  # equipment.files.attach(io: File.open(path), filename: "manual.pdf")
5
5
  # equipment.files.each { |file| url_for(file) }
6
6
  #
7
- # KNOWN BOUNDARY: ActiveStorage blobs live in global tables that Loam does
7
+ # KNOWN BOUNDARY: ActiveStorage blobs live in global tables that OpenLoam does
8
8
  # NOT tenant-scope. The association is scoped (a record only ever lists its
9
9
  # own files, and the record is tenant-scoped), but a signed blob URL is a
10
10
  # bearer capability: whoever holds the link can fetch the file, with no
@@ -15,8 +15,8 @@ module Loam
15
15
 
16
16
  included do
17
17
  unless respond_to?(:has_many_attached)
18
- raise Loam::Error,
19
- "#{name} includes Loam::Attachable but ActiveStorage is not available. " \
18
+ raise OpenLoam::Error,
19
+ "#{name} includes OpenLoam::Attachable but ActiveStorage is not available. " \
20
20
  "Run `bin/rails active_storage:install && bin/rails db:migrate`, or remove the include " \
21
21
  "(this app was probably generated with --skip-active-storage)."
22
22
  end
@@ -1,6 +1,6 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Audit-by-default. Included in every generated entity: create/update/destroy
3
- # writes a Loam::AuditRecord tagged with tenant + actor + changeset. "Who
3
+ # writes a OpenLoam::AuditRecord tagged with tenant + actor + changeset. "Who
4
4
  # changed the excavator's price, and when" is answered structurally, not by
5
5
  # remembering to log.
6
6
  module Auditable
@@ -9,54 +9,54 @@ module Loam
9
9
  IGNORED_ATTRIBUTES = %w[updated_at created_at].freeze
10
10
 
11
11
  included do
12
- after_create { loam_audit("create") }
13
- after_update { loam_audit(loam_audit_action) if loam_audit_changes.any? }
14
- after_destroy { loam_audit("destroy") }
12
+ after_create { open_loam_audit("create") }
13
+ after_update { open_loam_audit(open_loam_audit_action) if open_loam_audit_changes.any? }
14
+ after_destroy { open_loam_audit("destroy") }
15
15
  end
16
16
 
17
17
  private
18
18
 
19
- # Relabel the audit that the save inside the block writes. Loam::SoftDeletable
19
+ # Relabel the audit that the save inside the block writes. OpenLoam::SoftDeletable
20
20
  # uses this to record a soft-delete (an UPDATE) as "soft_delete"/"restore"
21
21
  # rather than the "update" it would otherwise be — one audit path, reused,
22
22
  # not a second one to keep in sync.
23
- def loam_audit_as(action)
24
- previous = @loam_audit_action
25
- @loam_audit_action = action
23
+ def open_loam_audit_as(action)
24
+ previous = @open_loam_audit_action
25
+ @open_loam_audit_action = action
26
26
  yield
27
27
  ensure
28
- @loam_audit_action = previous
28
+ @open_loam_audit_action = previous
29
29
  end
30
30
 
31
- def loam_audit_action
32
- @loam_audit_action || "update"
31
+ def open_loam_audit_action
32
+ @open_loam_audit_action || "update"
33
33
  end
34
34
 
35
- def loam_audit(action)
36
- Loam::AuditRecord.create!(
35
+ def open_loam_audit(action)
36
+ OpenLoam::AuditRecord.create!(
37
37
  auditable_type: self.class.name,
38
38
  auditable_id: id,
39
39
  action: action,
40
- actor_id: Loam::Current.actor&.id,
41
- changeset: action == "destroy" ? {} : loam_audit_changes
40
+ actor_id: OpenLoam::Current.actor&.id,
41
+ changeset: action == "destroy" ? {} : open_loam_audit_changes
42
42
  )
43
43
  end
44
44
 
45
- def loam_audit_changes
45
+ def open_loam_audit_changes
46
46
  changes = saved_changes.except(*IGNORED_ATTRIBUTES)
47
- loam_redact_encrypted(changes)
47
+ open_loam_redact_encrypted(changes)
48
48
  end
49
49
 
50
50
  # The audit trail must record the FACT that an encrypted field changed, never
51
51
  # its value — neither the plaintext nor the ciphertext (a ciphertext still
52
52
  # leaks length and, over time, correlations). So an encrypted column's change
53
53
  # becomes "[encrypted]", and its blind-index sibling is dropped entirely.
54
- # A no-op for models without Loam::Encryptable.
55
- def loam_redact_encrypted(changes)
56
- return changes unless self.class.respond_to?(:loam_encrypted_attributes)
54
+ # A no-op for models without OpenLoam::Encryptable.
55
+ def open_loam_redact_encrypted(changes)
56
+ return changes unless self.class.respond_to?(:open_loam_encrypted_attributes)
57
57
 
58
- encrypted = self.class.loam_encrypted_attributes.map(&:to_s)
59
- hash_columns = self.class.loam_searchable_encrypted_attributes.map { |name| "#{name}_hash" }
58
+ encrypted = self.class.open_loam_encrypted_attributes.map(&:to_s)
59
+ hash_columns = self.class.open_loam_searchable_encrypted_attributes.map { |name| "#{name}_hash" }
60
60
 
61
61
  changes.each_with_object({}) do |(column, values), redacted|
62
62
  next if hash_columns.include?(column)
@@ -1,12 +1,12 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Rate-limiting + lockout for authentication, to blunt online brute-force of
3
3
  # passwords and (especially) 6-digit TOTP codes. A DB-backed counter keyed by
4
4
  # the submitted identifier: after N failures within a window, the identifier is
5
5
  # locked; a success clears the counter.
6
6
  #
7
- # Loam::AuthThrottle.locked?(email) # refuse if true
8
- # Loam::AuthThrottle.record_failure(email, kind: "password", ip: request.ip)
9
- # Loam::AuthThrottle.clear(email) # on success
7
+ # OpenLoam::AuthThrottle.locked?(email) # refuse if true
8
+ # OpenLoam::AuthThrottle.record_failure(email, kind: "password", ip: request.ip)
9
+ # OpenLoam::AuthThrottle.clear(email) # on success
10
10
  #
11
11
  # PER-IDENTIFIER is the primary defense (an attacker targets one account /
12
12
  # code). A per-ip throttle to blunt spraying across accounts is a clean
@@ -15,7 +15,7 @@ module Loam
15
15
  # (needs a cache store + a gem); this DB counter is the portable,
16
16
  # single-process-correct prototype.
17
17
  #
18
- # Thresholds come from Loam::Configs (per-tenant-overridable, but read globally
18
+ # Thresholds come from OpenLoam::Configs (per-tenant-overridable, but read globally
19
19
  # here at the auth layer with sane defaults):
20
20
  # security.max_auth_attempts (default 10)
21
21
  # security.auth_window_minutes (default 15) — failures counted in this window
@@ -24,15 +24,15 @@ module Loam
24
24
  module_function
25
25
 
26
26
  def max_attempts
27
- Loam::Configs.get("security.max_auth_attempts", default: 10).to_i
27
+ OpenLoam::Configs.get("security.max_auth_attempts", default: 10).to_i
28
28
  end
29
29
 
30
30
  def window
31
- Loam::Configs.get("security.auth_window_minutes", default: 15).to_i.minutes
31
+ OpenLoam::Configs.get("security.auth_window_minutes", default: 15).to_i.minutes
32
32
  end
33
33
 
34
34
  def lockout
35
- Loam::Configs.get("security.auth_lockout_minutes", default: 15).to_i.minutes
35
+ OpenLoam::Configs.get("security.auth_lockout_minutes", default: 15).to_i.minutes
36
36
  end
37
37
 
38
38
  # Log a failed attempt. Recorded for ANY submitted identifier — existing or
@@ -41,7 +41,7 @@ module Loam
41
41
  identifier = normalize(identifier)
42
42
  return if identifier.blank?
43
43
 
44
- Loam::AuthAttempt.create!(identifier: identifier, kind: kind.to_s, ip: ip)
44
+ OpenLoam::AuthAttempt.create!(identifier: identifier, kind: kind.to_s, ip: ip)
45
45
  end
46
46
 
47
47
  # Locked if there are >= max failures within the window. Old attempts age out
@@ -73,7 +73,7 @@ module Loam
73
73
  end
74
74
 
75
75
  def attempts(identifier)
76
- Loam::AuthAttempt.where(identifier: normalize(identifier))
76
+ OpenLoam::AuthAttempt.where(identifier: normalize(identifier))
77
77
  end
78
78
 
79
79
  def normalize(identifier)
@@ -1,4 +1,4 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # RFC 4648 Base32 — the encoding authenticator apps expect for a TOTP secret.
3
3
  # Ruby ships Base64 but not Base32, and this is ~15 lines, so no dependency.
4
4
  # No padding on encode (authenticators don't want it); decode ignores case,
@@ -1,11 +1,11 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Datatable bulk actions over selected records — policy-checked PER record and
3
3
  # tenant-scoped. The ids are resolved THROUGH the tenant scope
4
4
  # (`model.where(id: ids)`), so a forged cross-tenant id is simply not found —
5
5
  # a bulk op can never reach another tenant's rows.
6
6
  #
7
- # Loam::Bulk.soft_delete(Equipment, params[:ids])
8
- # Loam::Bulk.set_field(Equipment, params[:ids], field: "status", value: "retired")
7
+ # OpenLoam::Bulk.soft_delete(Equipment, params[:ids])
8
+ # OpenLoam::Bulk.set_field(Equipment, params[:ids], field: "status", value: "retired")
9
9
  #
10
10
  # Returns the number of records actually affected (a record the actor may not
11
11
  # touch, or an id from another tenant, is silently skipped).
@@ -32,7 +32,7 @@ module Loam
32
32
  end
33
33
 
34
34
  # A relation for "export selected" — tenant-scoped, so it composes with
35
- # Loam::Export.csv and can't leak another tenant's rows.
35
+ # OpenLoam::Export.csv and can't leak another tenant's rows.
36
36
  def selected(model, ids)
37
37
  model.where(id: Array(ids))
38
38
  end
@@ -40,20 +40,20 @@ module Loam
40
40
  def each_permitted(model, ids)
41
41
  count = 0
42
42
  selected(model, ids).find_each do |record|
43
- count += 1 if yield(record, Loam::Policy.for(record))
43
+ count += 1 if yield(record, OpenLoam::Policy.for(record))
44
44
  end
45
45
  count
46
46
  end
47
47
 
48
48
  def writable_column?(model, field)
49
- model.column_names.include?(field) && Loam::Import::PLUMBING.exclude?(field) && !workflow_column?(model, field)
49
+ model.column_names.include?(field) && OpenLoam::Import::PLUMBING.exclude?(field) && !workflow_column?(model, field)
50
50
  end
51
51
 
52
52
  # A workflow status column may ONLY change through a transition (role-gated).
53
53
  # Skip it here so a bulk set-field can't self-"approve" (the model guard is
54
54
  # the backstop; this keeps the bulk op a clean no-op rather than an error).
55
55
  def workflow_column?(model, field)
56
- model.respond_to?(:loam_workflow) && model.loam_workflow&.column == field
56
+ model.respond_to?(:open_loam_workflow) && model.open_loam_workflow&.column == field
57
57
  end
58
58
  end
59
59
  end