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
- module Loam
1
+ module OpenLoam
2
2
  # A read-model projection of ONE custom field of ONE record into typed,
3
3
  # INDEXED columns — so filtering/sorting/searching on a custom field is
4
4
  # index-backed instead of a per-row JSON extraction over the `custom_fields`
5
5
  # column (which can't be indexed and full-scans at scale). One row per
6
- # (record, custom field); maintained by Loam::CustomFieldIndex from the
7
- # Loam::CustomFields save/destroy hooks. Tenant-scoped.
6
+ # (record, custom field); maintained by OpenLoam::CustomFieldIndex from the
7
+ # OpenLoam::CustomFields save/destroy hooks. Tenant-scoped.
8
8
  #
9
9
  # The value is written into the column matching the field's declared type
10
10
  # (value_number / value_boolean / value_datetime) AND always into value_text
11
11
  # (its string form) for text ops (contains/present) and canonical equality.
12
- class CustomFieldValue < Loam::TenantRecord
13
- self.table_name = "loam_custom_field_values"
12
+ class CustomFieldValue < OpenLoam::TenantRecord
13
+ self.table_name = "open_loam_custom_field_values"
14
14
 
15
15
  validates :indexable_type, :indexable_id, :field_key, presence: true
16
16
  validates :field_key, uniqueness: { scope: %i[indexable_type indexable_id] }
@@ -1,12 +1,12 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # A tenant's dashboard layout: which registered widgets appear, in what order.
3
3
  # A manager arranges these on the Dashboard settings screen; the dashboard
4
- # renders the active ones by position (see Loam::Dashboard). Tenant-scoped and
4
+ # renders the active ones by position (see OpenLoam::Dashboard). Tenant-scoped and
5
5
  # audited.
6
- class DashboardWidget < Loam::TenantRecord
7
- self.table_name = "loam_dashboard_widgets"
6
+ class DashboardWidget < OpenLoam::TenantRecord
7
+ self.table_name = "open_loam_dashboard_widgets"
8
8
 
9
- include Loam::Auditable
9
+ include OpenLoam::Auditable
10
10
 
11
11
  validates :widget_key, presence: true, uniqueness: { scope: :tenant_id }
12
12
 
@@ -0,0 +1,20 @@
1
+ module OpenLoam
2
+ # A per-tenant managed lookup list — a named set of entries (e.g.
3
+ # "damage_severity" → minor/major/critical). Admins curate the values without a
4
+ # code deploy, and a OpenLoam::FieldDefinition of type "dictionary" can point a
5
+ # custom field at one. Tenant-scoped and audited like every OpenLoam entity; see
6
+ # OpenLoam::Dictionaries for the read API.
7
+ class Dictionary < OpenLoam::TenantRecord
8
+ self.table_name = "open_loam_dictionaries"
9
+
10
+ include OpenLoam::Auditable
11
+
12
+ has_many :entries, class_name: "OpenLoam::DictionaryEntry",
13
+ foreign_key: :dictionary_id, dependent: :delete_all
14
+
15
+ validates :key, presence: true, uniqueness: { scope: :tenant_id }
16
+ validates :name, presence: true
17
+
18
+ normalizes :key, with: ->(key) { key.to_s.strip.presence }
19
+ end
20
+ end
@@ -1,15 +1,15 @@
1
- module Loam
2
- # One option in a Loam::Dictionary: a stored `value` (the code that lands in a
1
+ module OpenLoam
2
+ # One option in a OpenLoam::Dictionary: a stored `value` (the code that lands in a
3
3
  # record) plus display metadata (label, color, icon), an ordering `position`,
4
4
  # a `is_default` flag, and an `active` switch (a retired option stops being
5
5
  # offered without deleting the historical values already stored). Tenant-scoped
6
6
  # and audited.
7
- class DictionaryEntry < Loam::TenantRecord
8
- self.table_name = "loam_dictionary_entries"
7
+ class DictionaryEntry < OpenLoam::TenantRecord
8
+ self.table_name = "open_loam_dictionary_entries"
9
9
 
10
- include Loam::Auditable
10
+ include OpenLoam::Auditable
11
11
 
12
- belongs_to :dictionary, class_name: "Loam::Dictionary"
12
+ belongs_to :dictionary, class_name: "OpenLoam::Dictionary"
13
13
 
14
14
  validates :value, presence: true, uniqueness: { scope: :dictionary_id }
15
15
  validates :label, presence: true
@@ -25,7 +25,7 @@ module Loam
25
25
  # A within-request edit must not read a stale cached list (the cache also
26
26
  # resets per request, so this only matters when a write and a read share one).
27
27
  def clear_dictionary_cache
28
- Loam::Dictionaries.clear_cache
28
+ OpenLoam::Dictionaries.clear_cache
29
29
  end
30
30
  end
31
31
  end
@@ -1,14 +1,14 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # One durable delivery of one event to one persistent subscriber
3
- # (see Loam::DurableEvents). The ROW is the durable record of intent: it is
3
+ # (see OpenLoam::DurableEvents). The ROW is the durable record of intent: it is
4
4
  # committed in the event's tenant at publish time, and the background job is
5
5
  # only an accelerator. If the job is lost, the sweep re-enqueues from this row.
6
6
  #
7
7
  # Lifecycle: pending -> delivered (handler ran) | dead (handler removed, or
8
8
  # MAX_ATTEMPTS exhausted). A pending row with next_attempt_at in the future is
9
9
  # simply waiting out its backoff.
10
- class EventDelivery < Loam::TenantRecord
11
- self.table_name = "loam_event_deliveries"
10
+ class EventDelivery < OpenLoam::TenantRecord
11
+ self.table_name = "open_loam_event_deliveries"
12
12
 
13
13
  STATUSES = %w[pending delivered dead].freeze
14
14
 
@@ -1,12 +1,12 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Runtime declaration of a migration-free field on a tenant-scoped entity —
3
3
  # "entity_type Equipment gets a field called serial_number of type string,
4
4
  # writable by managers only." Tenant-scoped like everything else: a field
5
5
  # defined in one tenant is invisible to another's records of the same
6
6
  # entity_type, and definitions are the ONLY way values in an entity's
7
- # `custom_fields` json column get read/written (see Loam::CustomFields).
8
- class FieldDefinition < Loam::TenantRecord
9
- self.table_name = "loam_field_definitions"
7
+ # `custom_fields` json column get read/written (see OpenLoam::CustomFields).
8
+ class FieldDefinition < OpenLoam::TenantRecord
9
+ self.table_name = "open_loam_field_definitions"
10
10
 
11
11
  FIELD_TYPES = %w[string text integer decimal boolean date datetime dictionary].freeze
12
12
 
@@ -17,15 +17,15 @@ module Loam
17
17
 
18
18
  # Field-level READ gate for the runtime field, mirroring writable_roles: an
19
19
  # empty readable_roles means any member may read it; otherwise only the listed
20
- # roles. Used by Loam::CustomFieldIndex (so a filter can't be an oracle on a
21
- # restricted field) and Loam::Policy#custom_field_readable?.
20
+ # roles. Used by OpenLoam::CustomFieldIndex (so a filter can't be an oracle on a
21
+ # restricted field) and OpenLoam::Policy#custom_field_readable?.
22
22
  def readable_by?(role)
23
23
  roles = readable_roles
24
24
  roles.blank? || (role.present? && roles.map(&:to_sym).include?(role.to_sym))
25
25
  end
26
26
 
27
27
  # The `config` json holds type-specific settings. For a "dictionary" field it
28
- # carries the key of the Loam::Dictionary whose entries populate the select.
28
+ # carries the key of the OpenLoam::Dictionary whose entries populate the select.
29
29
  def dictionary_key
30
30
  config.is_a?(Hash) ? config["dictionary"] : nil
31
31
  end
@@ -40,7 +40,7 @@ module Loam
40
40
  def dictionary_key_resolves
41
41
  if dictionary_key.blank?
42
42
  errors.add(:dictionary_key, "is required for a dictionary field")
43
- elsif Loam::Dictionaries.get(dictionary_key).nil?
43
+ elsif OpenLoam::Dictionaries.get(dictionary_key).nil?
44
44
  errors.add(:dictionary_key, "must name an existing dictionary in this tenant")
45
45
  end
46
46
  end
@@ -1,12 +1,12 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # One received inbound webhook. Two jobs: an idempotency ledger (a unique
3
3
  # (source_id, external_id) index turns a replayed delivery into a no-op) and an
4
4
  # audit/payload store — the raw body is kept here so an event subscriber reads
5
5
  # it, keeping the published event payload scalar-clean (ids only).
6
- class InboundWebhookDelivery < Loam::TenantRecord
7
- self.table_name = "loam_inbound_webhook_deliveries"
6
+ class InboundWebhookDelivery < OpenLoam::TenantRecord
7
+ self.table_name = "open_loam_inbound_webhook_deliveries"
8
8
 
9
- belongs_to :source, class_name: "Loam::InboundWebhookSource", inverse_of: :deliveries
9
+ belongs_to :source, class_name: "OpenLoam::InboundWebhookSource", inverse_of: :deliveries
10
10
 
11
11
  validates :external_id, presence: true
12
12
  # (source_id, external_id) uniqueness is enforced by a DB index — the ledger
@@ -1,27 +1,27 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # A registered external system allowed to POST webhooks INTO this tenant — the
3
- # inbound sibling of Loam::WebhookEndpoint (which delivers events OUT). The
3
+ # inbound sibling of OpenLoam::WebhookEndpoint (which delivers events OUT). The
4
4
  # `token` is the unguessable URL id (`/webhooks/:token`) that identifies the
5
5
  # source; the `secret` is the HMAC key that AUTHENTICATES each call. Identity is
6
6
  # not authority: rotating either is supported from the admin.
7
7
  #
8
- # On a verified delivery, Loam publishes `event_name` onto the domain event bus
9
- # with a reference to the stored Loam::InboundWebhookDelivery, so durable
10
- # subscribers (Loam::DurableEvents) react — the payload itself lives on the row.
11
- class InboundWebhookSource < Loam::TenantRecord
12
- self.table_name = "loam_inbound_webhook_sources"
8
+ # On a verified delivery, OpenLoam publishes `event_name` onto the domain event bus
9
+ # with a reference to the stored OpenLoam::InboundWebhookDelivery, so durable
10
+ # subscribers (OpenLoam::DurableEvents) react — the payload itself lives on the row.
11
+ class InboundWebhookSource < OpenLoam::TenantRecord
12
+ self.table_name = "open_loam_inbound_webhook_sources"
13
13
 
14
- DEFAULT_SIGNATURE_HEADER = "X-Loam-Signature".freeze
14
+ DEFAULT_SIGNATURE_HEADER = "X-OpenLoam-Signature".freeze
15
15
  DEFAULT_TOLERANCE = 300 # seconds
16
16
 
17
- has_many :deliveries, class_name: "Loam::InboundWebhookDelivery",
17
+ has_many :deliveries, class_name: "OpenLoam::InboundWebhookDelivery",
18
18
  foreign_key: :source_id, dependent: :destroy, inverse_of: :source
19
19
 
20
20
  validates :name, presence: true
21
21
  validates :token, presence: true, uniqueness: true
22
22
  validates :secret, presence: true
23
23
  validates :event_name, presence: true,
24
- format: { with: Loam::Events::NAME_FORMAT, message: "must follow domain.thing.happened" }
24
+ format: { with: OpenLoam::Events::NAME_FORMAT, message: "must follow domain.thing.happened" }
25
25
 
26
26
  scope :active, -> { where(active: true) }
27
27
 
@@ -32,9 +32,9 @@ module Loam
32
32
  self.active = true if active.nil?
33
33
  end
34
34
 
35
- # THE blessed cross-tenant lookup (see Loam::ApiToken.authenticate): a public
35
+ # THE blessed cross-tenant lookup (see OpenLoam::ApiToken.authenticate): a public
36
36
  # inbound request arrives with no tenant context — the token in the URL is how
37
- # it discovers its tenant. Establishes Loam::Current.tenant (never an actor:
37
+ # it discovers its tenant. Establishes OpenLoam::Current.tenant (never an actor:
38
38
  # the sender is a machine, not a user) and returns the ACTIVE source, or nil.
39
39
  def self.resolve(raw_token)
40
40
  return nil if raw_token.blank?
@@ -42,7 +42,7 @@ module Loam
42
42
  source = unscoped.find_by(token: raw_token)
43
43
  return nil unless source&.active?
44
44
 
45
- Loam::Current.tenant = source.tenant
45
+ OpenLoam::Current.tenant = source.tenant
46
46
  source
47
47
  end
48
48
 
@@ -1,27 +1,27 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Connects an actor (the host app's User) to a tenant with a role. Roles are
3
3
  # plain strings ("manager", "employee", ...) — policies interpret them.
4
4
  # Tenant-scoped like everything else: asking for someone's role always means
5
5
  # "their role in the CURRENT tenant".
6
- class Membership < Loam::TenantRecord
7
- self.table_name = "loam_memberships"
6
+ class Membership < OpenLoam::TenantRecord
7
+ self.table_name = "open_loam_memberships"
8
8
 
9
9
  belongs_to :user
10
10
 
11
11
  validates :role, presence: true
12
12
  validates :user_id, uniqueness: { scope: :tenant_id }
13
13
 
14
- # The other blessed cross-tenant lookup (see Loam::ApiToken.authenticate).
14
+ # The other blessed cross-tenant lookup (see OpenLoam::ApiToken.authenticate).
15
15
  # "Which tenants may this person enter?" is asked at login, before any
16
16
  # tenant is chosen, so it cannot be answered from inside one — which is why
17
17
  # it lives in the gem rather than in host app code, where reaching across
18
18
  # tenants is a guardrail failure.
19
19
  #
20
- # Returns a Loam::Tenant relation, so callers can order/filter it further.
20
+ # Returns a OpenLoam::Tenant relation, so callers can order/filter it further.
21
21
  def self.tenants_for(user)
22
22
  user_id = user.respond_to?(:id) ? user.id : user
23
23
 
24
- Loam::Tenant.where(id: unscoped.where(user_id: user_id).select(:tenant_id)).order(:name)
24
+ OpenLoam::Tenant.where(id: unscoped.where(user_id: user_id).select(:tenant_id)).order(:name)
25
25
  end
26
26
  end
27
27
  end
@@ -1,21 +1,21 @@
1
1
  require "bcrypt"
2
2
 
3
- module Loam
3
+ module OpenLoam
4
4
  # A user's multi-factor credential: a TOTP secret plus single-use recovery
5
5
  # codes. Deliberately NOT tenant-scoped — MFA belongs to the PERSON, who spans
6
6
  # tenants, and the second-factor challenge runs at login BEFORE any tenant is
7
- # chosen. So the secret is encrypted under a USER-scoped key (Loam::Encryptable
7
+ # chosen. So the secret is encrypted under a USER-scoped key (OpenLoam::Encryptable
8
8
  # `scope:`), which decrypts in any tenant and with no tenant at all — the whole
9
9
  # reason a per-tenant key would be a lockout bug here.
10
10
  class MfaCredential < ApplicationRecord
11
- include Loam::GeneratedKey
12
- self.table_name = "loam_mfa_credentials"
11
+ include OpenLoam::GeneratedKey
12
+ self.table_name = "open_loam_mfa_credentials"
13
13
 
14
14
  RECOVERY_CODE_COUNT = 10
15
15
 
16
16
  belongs_to :user
17
17
 
18
- include Loam::Encryptable
18
+ include OpenLoam::Encryptable
19
19
  encrypts :totp_secret, scope: ->(credential) { "user/#{credential.user_id}" }
20
20
 
21
21
  # Recovery codes are stored HASHED (BCrypt), never in the clear: [{ "digest",
@@ -46,7 +46,7 @@ module Loam
46
46
  # if the code is wrong. The old secret stays valid until this succeeds, so a
47
47
  # half-finished re-enrollment never downgrades an active credential.
48
48
  def activate_with!(candidate_secret, code)
49
- step = Loam::Totp.matching_step(candidate_secret, code)
49
+ step = OpenLoam::Totp.matching_step(candidate_secret, code)
50
50
  return nil unless step
51
51
 
52
52
  self.totp_secret = candidate_secret
@@ -66,7 +66,7 @@ module Loam
66
66
  return false unless activated?
67
67
 
68
68
  with_lock do
69
- step = Loam::Totp.matching_step(totp_secret, code)
69
+ step = OpenLoam::Totp.matching_step(totp_secret, code)
70
70
  if step && (last_totp_step.nil? || step > last_totp_step)
71
71
  update!(last_totp_step: step)
72
72
  true
@@ -100,7 +100,7 @@ module Loam
100
100
  end
101
101
 
102
102
  def provisioning_uri(issuer:)
103
- Loam::Totp.provisioning_uri(totp_secret, account: user.email, issuer: issuer)
103
+ OpenLoam::Totp.provisioning_uri(totp_secret, account: user.email, issuer: issuer)
104
104
  end
105
105
 
106
106
  private
@@ -1,15 +1,15 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # One in-app message for one recipient (`user`) in one tenant. The same
3
3
  # person in two tenants has two separate inboxes — like everything else in
4
- # Loam, "your notifications" always means "in the current tenant".
4
+ # OpenLoam, "your notifications" always means "in the current tenant".
5
5
  #
6
- # Plumbing, not business data: not audited, the same way Loam::AuditRecord
7
- # isn't. It IS evented, though — creating one publishes "loam.notification.created"
8
- # (carrying the recipient's user_id) so Loam::EventStream can push it to that
6
+ # Plumbing, not business data: not audited, the same way OpenLoam::AuditRecord
7
+ # isn't. It IS evented, though — creating one publishes "open_loam.notification.created"
8
+ # (carrying the recipient's user_id) so OpenLoam::EventStream can push it to that
9
9
  # user's browser and the bell updates live. Created through
10
- # Loam::Notifications.notify, read through the admin bell.
11
- class Notification < Loam::TenantRecord
12
- self.table_name = "loam_notifications"
10
+ # OpenLoam::Notifications.notify, read through the admin bell.
11
+ class Notification < OpenLoam::TenantRecord
12
+ self.table_name = "open_loam_notifications"
13
13
 
14
14
  belongs_to :user
15
15
 
@@ -18,9 +18,9 @@ module Loam
18
18
  scope :unread, -> { where(read_at: nil) }
19
19
 
20
20
  # The one signal the real-time bell listens for. Only id + recipient ride the
21
- # event (Loam::Events also stamps tenant_id); no message content is broadcast.
21
+ # event (OpenLoam::Events also stamps tenant_id); no message content is broadcast.
22
22
  after_create_commit do
23
- Loam::Events.publish("loam.notification.created", id: id, user_id: user_id)
23
+ OpenLoam::Events.publish("open_loam.notification.created", id: id, user_id: user_id)
24
24
  end
25
25
 
26
26
  # What the notification is about, if anything (source_type/source_id) —
@@ -1,21 +1,21 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # A staged mutation awaiting human approval. When a caller runs under
3
- # confirm-mode (an MCP tool acting for an AI agent — see Loam.mutation_mode), a
3
+ # confirm-mode (an MCP tool acting for an AI agent — see OpenLoam.mutation_mode), a
4
4
  # write is staged HERE as a preview instead of committing; a manager approves
5
- # or rejects, and only approval executes it. This is Loam's thesis made
5
+ # or rejects, and only approval executes it. This is OpenLoam's thesis made
6
6
  # concrete: agent-triggered writes are gate-able.
7
7
  #
8
- # The approval gate IS a workflow (Loam::Workflow): pending → (manager) approve
8
+ # The approval gate IS a workflow (OpenLoam::Workflow): pending → (manager) approve
9
9
  # / reject → executed / failed. "Who may approve" lives in one declarative,
10
- # role-gated place. The proposed changes are encrypted at rest (Loam::Encryptable),
10
+ # role-gated place. The proposed changes are encrypted at rest (OpenLoam::Encryptable),
11
11
  # because a staged change to an encrypted target field would otherwise sit here
12
12
  # — and in this row's own audit — as plaintext, reopening the leak L-901 closed.
13
- class PendingAction < Loam::TenantRecord
14
- self.table_name = "loam_pending_actions"
13
+ class PendingAction < OpenLoam::TenantRecord
14
+ self.table_name = "open_loam_pending_actions"
15
15
 
16
- include Loam::Auditable
17
- include Loam::Encryptable
18
- include Loam::Workflow
16
+ include OpenLoam::Auditable
17
+ include OpenLoam::Encryptable
18
+ include OpenLoam::Workflow
19
19
 
20
20
  belongs_to :actor, class_name: "User", optional: true
21
21
  belongs_to :reviewer, class_name: "User", foreign_key: :reviewed_by_id, optional: true
@@ -96,7 +96,7 @@ module Loam
96
96
  # write; the record ends "executed" or "failed". Executes as `by`, so the
97
97
  # TARGET's audit names the approving human — the person owns the change.
98
98
  def approve!(by:)
99
- Loam.as_tenant(tenant, actor: by) do
99
+ OpenLoam.as_tenant(tenant, actor: by) do
100
100
  reject_self_approval!(by)
101
101
  self.reviewed_by_id = by.id
102
102
  self.reviewed_at = Time.current
@@ -107,7 +107,7 @@ module Loam
107
107
  end
108
108
 
109
109
  def reject!(by:, reason: nil)
110
- Loam.as_tenant(tenant, actor: by) do
110
+ OpenLoam.as_tenant(tenant, actor: by) do
111
111
  self.reviewed_by_id = by.id
112
112
  self.reviewed_at = Time.current
113
113
  self.result = [ "rejected", reason.presence ].compact.join(": ")
@@ -126,9 +126,9 @@ module Loam
126
126
  # withdrawal, not a segregation-of-duties concern.)
127
127
  def reject_self_approval!(by)
128
128
  return unless by.id == actor_id
129
- return if Loam::Configs.get("approvals.allow_self_approve", default: false)
129
+ return if OpenLoam::Configs.get("approvals.allow_self_approve", default: false)
130
130
 
131
- raise Loam::NotAuthorizedError, "self-approval is not permitted; a different person must approve this change"
131
+ raise OpenLoam::NotAuthorizedError, "self-approval is not permitted; a different person must approve this change"
132
132
  end
133
133
 
134
134
  # Execution AND its status/result recording share ONE transaction with the
@@ -163,7 +163,7 @@ module Loam
163
163
  target.respond_to?(:soft_delete!) ? target.soft_delete! : target.destroy!
164
164
  "deleted #{target_type}##{target_id}"
165
165
  else
166
- raise Loam::Error, "unknown action_type #{action_type.inspect}"
166
+ raise OpenLoam::Error, "unknown action_type #{action_type.inspect}"
167
167
  end
168
168
  end
169
169
 
@@ -178,31 +178,31 @@ module Loam
178
178
  end
179
179
 
180
180
  def encrypted_target_fields
181
- return [] unless target_class.respond_to?(:loam_encrypted_attributes)
181
+ return [] unless target_class.respond_to?(:open_loam_encrypted_attributes)
182
182
 
183
- target_class.loam_encrypted_attributes.map(&:to_s)
183
+ target_class.open_loam_encrypted_attributes.map(&:to_s)
184
184
  end
185
185
 
186
186
  # Set while a workflow transition is performing its save, so the validation
187
187
  # below can tell a legitimate status move from a direct assignment.
188
- def loam_perform_transition!(transition)
189
- @loam_status_via_transition = true
188
+ def open_loam_perform_transition!(transition)
189
+ @open_loam_status_via_transition = true
190
190
  super
191
191
  ensure
192
- @loam_status_via_transition = false
192
+ @open_loam_status_via_transition = false
193
193
  end
194
194
 
195
195
  def status_changes_only_through_a_transition
196
196
  return unless will_save_change_to_status?
197
- return if @loam_status_via_transition
197
+ return if @open_loam_status_via_transition
198
198
 
199
199
  errors.add(:status, "may only change through an approval transition (approve!/reject!), not a direct write")
200
200
  end
201
201
 
202
202
  def status_starts_at_the_initial_state
203
- return if status == self.class.loam_workflow.initial
203
+ return if status == self.class.open_loam_workflow.initial
204
204
 
205
- errors.add(:status, "must start at #{self.class.loam_workflow.initial.inspect} — a staged action begins pending")
205
+ errors.add(:status, "must start at #{self.class.open_loam_workflow.initial.inspect} — a staged action begins pending")
206
206
  end
207
207
  end
208
208
  end
@@ -1,4 +1,4 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # A saved view of an entity's admin index — which columns show, active filters,
3
3
  # sort, and page size — that a user can name, make their default, or share.
4
4
  #
@@ -7,15 +7,15 @@ module Loam
7
7
  # * "role" — everyone with the named membership role in the tenant.
8
8
  # * "tenant" — everyone in the tenant.
9
9
  # A private view is invisible to others by construction (see
10
- # Loam::Perspectives.visible_to), not merely by a permission check.
10
+ # OpenLoam::Perspectives.visible_to), not merely by a permission check.
11
11
  #
12
12
  # Tenant-scoped like everything else, and audited. Optimistic-locked
13
13
  # (lock_version) so two people editing a shared view don't silently clobber
14
14
  # each other — the admin controller rescues ActiveRecord::StaleObjectError.
15
- class Perspective < Loam::TenantRecord
16
- self.table_name = "loam_perspectives"
15
+ class Perspective < OpenLoam::TenantRecord
16
+ self.table_name = "open_loam_perspectives"
17
17
 
18
- include Loam::Auditable
18
+ include OpenLoam::Auditable
19
19
 
20
20
  VISIBILITIES = %w[private role tenant].freeze
21
21
 
@@ -1,4 +1,4 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Progress of a long-running job (a bulk import, a reindex, a report) so the
3
3
  # admin can watch it live instead of guessing. Tenant-scoped; a job started in
4
4
  # one tenant is only visible and streamable there.
@@ -7,11 +7,11 @@ module Loam
7
7
  # ticks) and the audit trail would fill with noise. The terminal status and
8
8
  # any error are captured on the row itself, which is the summary that matters.
9
9
  #
10
- # Each meaningful change publishes `loam.progress.updated` (broadcastable → SSE)
11
- # carrying only id/percent/status — no record contents. See Loam::Progress for
10
+ # Each meaningful change publishes `open_loam.progress.updated` (broadcastable → SSE)
11
+ # carrying only id/percent/status — no record contents. See OpenLoam::Progress for
12
12
  # the entry point.
13
- class ProgressJob < Loam::TenantRecord
14
- self.table_name = "loam_progress_jobs"
13
+ class ProgressJob < OpenLoam::TenantRecord
14
+ self.table_name = "open_loam_progress_jobs"
15
15
 
16
16
  STATUSES = %w[running completed failed cancelled].freeze
17
17
  STALE_AFTER = 5.minutes
@@ -93,11 +93,11 @@ module Loam
93
93
  self
94
94
  end
95
95
 
96
- # Only ever id/percent/status leave the server (Loam::Events stamps tenant_id
96
+ # Only ever id/percent/status leave the server (OpenLoam::Events stamps tenant_id
97
97
  # for the SSE deliverable filter; the frame's safe_payload drops everything
98
98
  # else).
99
99
  def broadcast
100
- Loam::Events.publish("loam.progress.updated", id: id, percent: percent, status: status)
100
+ OpenLoam::Events.publish("open_loam.progress.updated", id: id, percent: percent, status: status)
101
101
  end
102
102
  end
103
103
  end
@@ -1,12 +1,12 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # An advisory "someone is editing this" lock on a record — the COURTESY layer.
3
3
  # The real guarantee against a silent clobber is optimistic locking
4
- # (lock_version, see Loam::RecordLocks docs); this only warns the second
4
+ # (lock_version, see OpenLoam::RecordLocks docs); this only warns the second
5
5
  # editor. One lock per record, with a TTL: an expired lock is treated as free,
6
6
  # and re-acquiring as the same holder extends it (a heartbeat). Plumbing, so
7
- # not audited — like Loam::ApiToken.
8
- class RecordLock < Loam::TenantRecord
9
- self.table_name = "loam_record_locks"
7
+ # not audited — like OpenLoam::ApiToken.
8
+ class RecordLock < OpenLoam::TenantRecord
9
+ self.table_name = "open_loam_record_locks"
10
10
 
11
11
  belongs_to :locked_by, class_name: "User"
12
12
 
@@ -1,16 +1,16 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # A recurring job that runs on a schedule (cron or interval). Tenant-scoped:
3
3
  # a "tenant"-scope schedule enqueues its job in this tenant on schedule; a
4
4
  # "system"-scope schedule enqueues once with no tenant context. Audited on
5
5
  # config changes (not per run — runs are tracked by last_run_at/next_run_at).
6
6
  #
7
7
  # SECURITY: job_class is validated to be a known ActiveJob (see
8
- # Loam::Scheduler.resolve_job_class) at save AND at enqueue — a scheduler that
8
+ # OpenLoam::Scheduler.resolve_job_class) at save AND at enqueue — a scheduler that
9
9
  # constantized and ran arbitrary user input would be a code-execution hole.
10
- class ScheduledJob < Loam::TenantRecord
11
- self.table_name = "loam_scheduled_jobs"
10
+ class ScheduledJob < OpenLoam::TenantRecord
11
+ self.table_name = "open_loam_scheduled_jobs"
12
12
 
13
- include Loam::Auditable
13
+ include OpenLoam::Auditable
14
14
 
15
15
  SCOPES = %w[tenant system].freeze
16
16
  LOCK_TTL = 5.minutes # how long a claim holds a due job before another tick may retry it
@@ -26,11 +26,11 @@ module Loam
26
26
  # The next fire time strictly after `from`, in this job's timezone (UTC when
27
27
  # unset). Stored in next_run_at as UTC.
28
28
  def compute_next_run(from = Time.current)
29
- Loam::Cron.next_after(schedule, from: from, zone: timezone.presence || "UTC")
29
+ OpenLoam::Cron.next_after(schedule, from: from, zone: timezone.presence || "UTC")
30
30
  end
31
31
 
32
32
  def job_class_constant
33
- Loam::Scheduler.resolve_job_class(job_class)
33
+ OpenLoam::Scheduler.resolve_job_class(job_class)
34
34
  end
35
35
 
36
36
  private
@@ -0,0 +1,9 @@
1
+ module OpenLoam
2
+ # The word-level search index maintained by OpenLoam::Search::TokenDriver: one row
3
+ # per (record, token), tenant-scoped like every OpenLoam entity. Plumbing — not
4
+ # audited, not soft-deletable. Only the TokenDriver reads or writes it; under
5
+ # the default LikeDriver this table simply stays empty.
6
+ class SearchToken < OpenLoam::TenantRecord
7
+ self.table_name = "open_loam_search_tokens"
8
+ end
9
+ end
@@ -1,12 +1,12 @@
1
- module Loam
1
+ module OpenLoam
2
2
  # Links an external IdP identity (a provider's stable `sub`) to a local User.
3
3
  # The durable key SSO callbacks resolve on — an email can change at the IdP,
4
4
  # `sub` does not. Tenant-scoped (created and read inside the provider's tenant).
5
- class SsoIdentity < Loam::TenantRecord
6
- self.table_name = "loam_sso_identities"
5
+ class SsoIdentity < OpenLoam::TenantRecord
6
+ self.table_name = "open_loam_sso_identities"
7
7
 
8
8
  belongs_to :user
9
- belongs_to :sso_provider, class_name: "Loam::SsoProvider"
9
+ belongs_to :sso_provider, class_name: "OpenLoam::SsoProvider"
10
10
 
11
11
  validates :sub, presence: true, uniqueness: { scope: :sso_provider_id }
12
12
  end