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,214 +1,214 @@
1
- # Loam configuration, tenant lifecycle hooks, and domain event subscriptions.
1
+ # OpenLoam configuration, tenant lifecycle hooks, and domain event subscriptions.
2
2
 
3
- # Master key for field encryption at rest (Loam::Encryptable). Per-tenant keys
3
+ # Master key for field encryption at rest (OpenLoam::Encryptable). Per-tenant keys
4
4
  # are derived from it via HKDF, so it must be STABLE and SECRET — never commit it.
5
- # Set LOAM_MASTER_KEY in the environment (or wire Rails.application.credentials)
5
+ # Set OPEN_LOAM_MASTER_KEY in the environment (or wire Rails.application.credentials)
6
6
  # to a high-entropy value, e.g. `SecureRandom.hex(32)`. Only apps that actually
7
7
  # `encrypts` a field need it; encryption raises a clear error if it is missing.
8
8
  #
9
- # Loam::Encryption.master_key = ENV.fetch("LOAM_MASTER_KEY")
9
+ # OpenLoam::Encryption.master_key = ENV.fetch("OPEN_LOAM_MASTER_KEY")
10
10
  #
11
11
  # Rotating the key without re-encrypting orphans existing ciphertext — see
12
- # `bin/rails loam:encryption:rotate[Model,tenant_id]`.
12
+ # `bin/rails open_loam:encryption:rotate[Model,tenant_id]`.
13
13
 
14
14
  # Roles every tenant of this app is expected to have. A registry read by your
15
- # own seeding/admin code — Loam does not create memberships for you, because
15
+ # own seeding/admin code — OpenLoam does not create memberships for you, because
16
16
  # who gets which role is business logic.
17
- Loam.default_roles = %w[manager employee]
17
+ OpenLoam.default_roles = %w[manager employee]
18
18
 
19
- # Locales that CONTENT translations (Loam::Translatable) may be authored in — the
19
+ # Locales that CONTENT translations (OpenLoam::Translatable) may be authored in — the
20
20
  # admin's language switcher and the per-record Translations screen offer these.
21
21
  # The first is the base/default; the rest overlay onto it. This is for user data
22
- # (a product name), NOT developer UI strings — those stay Rails i18n. Loam ships
23
- # a `loam.*` base locale (English) for its own chrome; the admin switcher sets
24
- # I18n.locale too, so add `config/locales/loam.pl.yml` (etc.) to translate the UI
22
+ # (a product name), NOT developer UI strings — those stay Rails i18n. OpenLoam ships
23
+ # a `open_loam.*` base locale (English) for its own chrome; the admin switcher sets
24
+ # I18n.locale too, so add `config/locales/open_loam.pl.yml` (etc.) to translate the UI
25
25
  # for each locale you list here.
26
- Loam.locales = %w[en]
26
+ OpenLoam.locales = %w[en]
27
27
 
28
- # Observability (Loam::Telemetry). By default Loam wraps its async hot paths
28
+ # Observability (OpenLoam::Telemetry). By default OpenLoam wraps its async hot paths
29
29
  # (scheduler tick, durable event delivery, inbound webhook ingest) in spans that
30
- # emit ActiveSupport::Notifications events ("loam.span.*") — subscribe to those,
30
+ # emit ActiveSupport::Notifications events ("open_loam.span.*") — subscribe to those,
31
31
  # or plug a real tracer in here:
32
32
  #
33
- # Loam::Telemetry.backend = ->(name, attributes, work) do
34
- # OpenTelemetry.tracer_provider.tracer("loam").in_span(name, attributes: attributes.transform_keys(&:to_s)) { work.call }
33
+ # OpenLoam::Telemetry.backend = ->(name, attributes, work) do
34
+ # OpenTelemetry.tracer_provider.tracer("open_loam").in_span(name, attributes: attributes.transform_keys(&:to_s)) { work.call }
35
35
  # end
36
36
 
37
- # Feature-string permissions (Loam::Permissions) — a finer capability layer under
37
+ # Feature-string permissions (OpenLoam::Permissions) — a finer capability layer under
38
38
  # the coarse role. Deny-by-default; `*` grants everything, a trailing `.*` is a
39
- # prefix ("equipment.*"). Check with `Loam.can?("equipment.edit")`,
39
+ # prefix ("equipment.*"). Check with `OpenLoam.can?("equipment.edit")`,
40
40
  # `require_permission!("...")` in a controller, or the `can?` view helper.
41
- # Orthogonal to roles (Loam::Membership) and field-level policies (Loam::Policy).
41
+ # Orthogonal to roles (OpenLoam::Membership) and field-level policies (OpenLoam::Policy).
42
42
  #
43
- # Loam::Permissions.configure do
43
+ # OpenLoam::Permissions.configure do
44
44
  # role :admin, allow: "*"
45
45
  # role :manager, allow: %w[equipment.* billing.read]
46
46
  # role :clerk, allow: %w[equipment.read]
47
47
  # end
48
48
 
49
- # Customization WITHOUT forking (Loam::Overrides): disable or replace an entry in
50
- # one of Loam's keyed registries (:widgets, :broadcast_events). A stale override
49
+ # Customization WITHOUT forking (OpenLoam::Overrides): disable or replace an entry in
50
+ # one of OpenLoam's keyed registries (:widgets, :broadcast_events). A stale override
51
51
  # (a key that no longer exists) is warned about at boot by `check!`, so a
52
52
  # typo'd override is visible instead of silently doing nothing.
53
53
  #
54
- # Loam::Overrides.disable(:widgets, "open_progress") # drop a built-in widget
55
- # Loam::Overrides.replace(:widgets, "audit_recent") { |actor| { kind: "count", value: 0 } }
56
- # Loam::Overrides.disable(:broadcast_events, "loam.progress.") # stop pushing it over SSE
54
+ # OpenLoam::Overrides.disable(:widgets, "open_progress") # drop a built-in widget
55
+ # OpenLoam::Overrides.replace(:widgets, "audit_recent") { |actor| { kind: "count", value: 0 } }
56
+ # OpenLoam::Overrides.disable(:broadcast_events, "open_loam.progress.") # stop pushing it over SSE
57
57
  #
58
- # BOUNDARY: this is only for Loam's in-gem registries. Override a VIEW, CONTROLLER,
58
+ # BOUNDARY: this is only for OpenLoam's in-gem registries. Override a VIEW, CONTROLLER,
59
59
  # or ROUTE the standard Rails way (create a file at the same path to shadow the
60
60
  # engine's, or `prepend` a module) — not here.
61
61
 
62
- # Events pushed live to the browser over SSE (Loam::EventStream). Default off; the
62
+ # Events pushed live to the browser over SSE (OpenLoam::EventStream). Default off; the
63
63
  # notification pattern is enabled here so the admin bell increments without a
64
64
  # reload. Add patterns (e.g. "billing.") to stream domain events to live widgets —
65
65
  # nothing reaches the browser unless it matches a pattern here (security posture).
66
- Loam.broadcast_events = [ "loam.notification.", "loam.progress." ]
66
+ OpenLoam.broadcast_events = [ "open_loam.notification.", "open_loam.progress." ]
67
67
 
68
- # Response enrichers (Loam::Enrichers): attach a computed block onto ANOTHER
68
+ # Response enrichers (OpenLoam::Enrichers): attach a computed block onto ANOTHER
69
69
  # module's entity in admin/API responses, with no foreign-key coupling — billing
70
70
  # can annotate an Equipment without Equipment knowing billing exists. Pass a
71
71
  # `batch:` resolver (array -> { id => value }) so an index stays one query, not N.
72
72
  #
73
- # Loam::Enrichers.register("Equipment", key: "outstanding_balance", batch: ->(equipments) do
73
+ # OpenLoam::Enrichers.register("Equipment", key: "outstanding_balance", batch: ->(equipments) do
74
74
  # totals = Invoice.where(equipment_id: equipments.map(&:id)).group(:equipment_id).sum(:balance)
75
75
  # equipments.map(&:id).index_with { |id| totals.fetch(id, 0) }
76
76
  # end)
77
77
 
78
- # Search backend (Loam::Search). The default is a substring LIKE — portable and
78
+ # Search backend (OpenLoam::Search). The default is a substring LIKE — portable and
79
79
  # zero-setup. Opt into the word-level TokenDriver (also portable, no external
80
- # service: it keeps a normalized-token index in loam_search_tokens) for
80
+ # service: it keeps a normalized-token index in open_loam_search_tokens) for
81
81
  # order-independent, whole-word matching. `searchable_by` and every
82
82
  # `Model.search(q)` call site are UNCHANGED — only this line differs; an external
83
83
  # engine (Meilisearch/Elasticsearch) is a third driver behind the same seam.
84
- # After switching, backfill existing rows once with `bin/rails loam:search:reindex`
84
+ # After switching, backfill existing rows once with `bin/rails open_loam:search:reindex`
85
85
  # (new and updated records index themselves on save).
86
86
  #
87
- # Loam::Search.driver = Loam::Search::TokenDriver
87
+ # OpenLoam::Search.driver = OpenLoam::Search::TokenDriver
88
88
 
89
- # Custom-field read-model index (Loam::CustomFieldIndex). Filtering/sorting on a
90
- # custom field is index-backed (a typed projection in loam_custom_field_values)
89
+ # Custom-field read-model index (OpenLoam::CustomFieldIndex). Filtering/sorting on a
90
+ # custom field is index-backed (a typed projection in open_loam_custom_field_values)
91
91
  # instead of a per-row JSON scan. Records project themselves on save; backfill
92
- # existing data once with `bin/rails loam:index:reindex` (or
93
- # `Loam::CustomFieldIndex.reindex(Model)`). Query with
94
- # `Loam::CustomFieldIndex.filter(Model, field_key, op, value)` — the generated
92
+ # existing data once with `bin/rails open_loam:index:reindex` (or
93
+ # `OpenLoam::CustomFieldIndex.reindex(Model)`). Query with
94
+ # `OpenLoam::CustomFieldIndex.filter(Model, field_key, op, value)` — the generated
95
95
  # entity index routes a `cf_field`/`cf_op`/`cf_value` filter through it.
96
96
 
97
- # Single sign-on (Loam::Sso). OIDC is shipped end-to-end: configure a per-tenant
97
+ # Single sign-on (OpenLoam::Sso). OIDC is shipped end-to-end: configure a per-tenant
98
98
  # provider under /admin/sso_providers (issuer, client_id, client_secret, email
99
99
  # domain, default JIT role). Home-realm discovery routes a user to their tenant's
100
100
  # IdP by email domain; a verified identity is JIT-provisioned or linked to an
101
- # existing User. The client_secret is encrypted at rest, so LOAM_MASTER_KEY must
102
- # be set (same key as the rest of Loam::Encryptable). SAML and SCIM are documented
101
+ # existing User. The client_secret is encrypted at rest, so OPEN_LOAM_MASTER_KEY must
102
+ # be set (same key as the rest of OpenLoam::Encryptable). SAML and SCIM are documented
103
103
  # seams (see docs/_foundation/overview.md). Nothing to register here for real OIDC.
104
104
  #
105
105
  # In tests, inject the offline fake so the flow never hits the network:
106
106
  #
107
- # Loam::Sso.builder = ->(record, redirect_uri) { Loam::Sso::FakeProvider.new(record, redirect_uri: redirect_uri) }
107
+ # OpenLoam::Sso.builder = ->(record, redirect_uri) { OpenLoam::Sso::FakeProvider.new(record, redirect_uri: redirect_uri) }
108
108
 
109
- # Roles that MUST use two-factor auth (Loam::MfaCredential). At login, a user
109
+ # Roles that MUST use two-factor auth (OpenLoam::MfaCredential). At login, a user
110
110
  # whose role in the chosen tenant is on this list and who has not enrolled is
111
- # sent to set MFA up before they can work. Resolved via Loam::Configs, so it can
111
+ # sent to set MFA up before they can work. Resolved via OpenLoam::Configs, so it can
112
112
  # be a global default or a per-tenant override; empty means MFA is optional.
113
113
  #
114
- # Loam::Configs.set("security.mfa_required_roles", ["manager"], scope: :global)
114
+ # OpenLoam::Configs.set("security.mfa_required_roles", ["manager"], scope: :global)
115
115
  #
116
- # Auth rate-limiting / lockout (Loam::AuthThrottle) guards failed password/TOTP/
116
+ # Auth rate-limiting / lockout (OpenLoam::AuthThrottle) guards failed password/TOTP/
117
117
  # sudo attempts. Defaults: lock after 10 failures within a 15-minute window.
118
- # Tune via Loam::Configs (global or per-tenant):
118
+ # Tune via OpenLoam::Configs (global or per-tenant):
119
119
  #
120
- # Loam::Configs.set("security.max_auth_attempts", 5, scope: :global)
121
- # Loam::Configs.set("security.auth_window_minutes", 10, scope: :global)
120
+ # OpenLoam::Configs.set("security.max_auth_attempts", 5, scope: :global)
121
+ # OpenLoam::Configs.set("security.auth_window_minutes", 10, scope: :global)
122
122
  #
123
123
  # Rack::Attack (with a cache store) is the production-scale path across multiple
124
124
  # processes; the built-in DB counter is the portable single-process default.
125
125
 
126
- # App-wide setting defaults (Loam::Configs). A key resolves override → global
126
+ # App-wide setting defaults (OpenLoam::Configs). A key resolves override → global
127
127
  # row → this declared default, so declaring one here needs no migration and no
128
128
  # row — a tenant reads the default until someone overrides it in the admin
129
129
  # Settings screen (/admin/configs). Values keep their type (bool/number/string/
130
130
  # hash), and a per-tenant override never leaks to another tenant.
131
131
  #
132
- # Loam.config_defaults = { "billing.currency" => "USD", "billing.net_terms" => 30 }
132
+ # OpenLoam.config_defaults = { "billing.currency" => "USD", "billing.net_terms" => 30 }
133
133
  #
134
134
  # To change the company-wide baseline at runtime (not per tenant), write a
135
- # global row: `Loam::Configs.set("billing.currency", "EUR", scope: :global)`.
135
+ # global row: `OpenLoam::Configs.set("billing.currency", "EUR", scope: :global)`.
136
136
 
137
- # Feature flags (Loam::Features). Declare known capabilities and their default
137
+ # Feature flags (OpenLoam::Features). Declare known capabilities and their default
138
138
  # state; a flag with no row resolves to its declared default, and managers flip
139
139
  # a tenant's override at /admin/features. A flag gates a CAPABILITY (is this on
140
140
  # for the tenant), orthogonal to roles/policies, which gate a PERSON.
141
141
  #
142
- # Loam.feature_defaults = {
142
+ # OpenLoam.feature_defaults = {
143
143
  # "beta_dashboard" => { default: false, description: "New dashboard, rolled out per tenant." }
144
144
  # }
145
145
  #
146
146
  # In a controller: `require_feature!(:beta_dashboard)` (404s when off); in a
147
147
  # view: `<%% if feature_on?(:beta_dashboard) %>`. Flip app-wide with
148
- # `Loam::Features.enable(:beta_dashboard, scope: :global)`.
148
+ # `OpenLoam::Features.enable(:beta_dashboard, scope: :global)`.
149
149
 
150
150
  # What a brand-new tenant gets for free. Registered at file scope on purpose:
151
151
  # inside `to_prepare` this would re-register on every code reload.
152
- Loam.on_tenant_created do |tenant|
152
+ OpenLoam.on_tenant_created do |tenant|
153
153
  # Seed roles/defaults for a new tenant here. MUST be idempotent —
154
- # `bin/rails loam:sync` re-runs these for every existing tenant, which is how
154
+ # `bin/rails open_loam:sync` re-runs these for every existing tenant, which is how
155
155
  # a default added in a later release reaches tenants that already exist.
156
156
  # Use find_or_create_by!, never create!. The block runs inside
157
- # Loam.as_tenant(tenant), so tenant-scoped writes need no extra ceremony.
157
+ # OpenLoam.as_tenant(tenant), so tenant-scoped writes need no extra ceremony.
158
158
  #
159
- # Baseline managed lookup lists (Loam::Dictionary) — a FieldDefinition of type
159
+ # Baseline managed lookup lists (OpenLoam::Dictionary) — a FieldDefinition of type
160
160
  # "dictionary" can then point a custom field at the key, rendering a select:
161
161
  #
162
- # severity = Loam::Dictionary.find_or_create_by!(key: "damage_severity") { |d| d.name = "Damage severity" }
162
+ # severity = OpenLoam::Dictionary.find_or_create_by!(key: "damage_severity") { |d| d.name = "Damage severity" }
163
163
  # [%w[minor Minor], %w[major Major], %w[critical Critical]].each_with_index do |(value, label), i|
164
164
  # severity.entries.find_or_create_by!(value: value) { |e| e.label = label; e.position = i }
165
165
  # end
166
166
 
167
- # Materialize the registered tenant-scope schedules (see Loam::Scheduler.register
167
+ # Materialize the registered tenant-scope schedules (see OpenLoam::Scheduler.register
168
168
  # below) as rows for this tenant. A no-op until you register one.
169
- Loam::Scheduler.sync_tenant(tenant)
169
+ OpenLoam::Scheduler.sync_tenant(tenant)
170
170
  end
171
171
 
172
- # Recurring jobs (Loam::Scheduler). Register default schedules here at file scope;
172
+ # Recurring jobs (OpenLoam::Scheduler). Register default schedules here at file scope;
173
173
  # on_tenant_created materializes the tenant-scope ones per tenant. A "tenant" job
174
- # is enqueued with `tenant_id:` (establish it with Loam.as_tenant); a "system" job
174
+ # is enqueued with `tenant_id:` (establish it with OpenLoam.as_tenant); a "system" job
175
175
  # runs once with no tenant. job_class MUST be a real ActiveJob (validated — never
176
176
  # arbitrary code). Wire the runner to system cron, every minute:
177
177
  #
178
- # * * * * * cd /path/to/app && bin/rails loam:scheduler:tick
178
+ # * * * * * cd /path/to/app && bin/rails open_loam:scheduler:tick
179
179
  #
180
180
  # The claim is atomic, so running it from several hosts never double-fires a job.
181
181
  #
182
- # Loam::Scheduler.register(key: "nightly_digest", name: "Nightly digest",
182
+ # OpenLoam::Scheduler.register(key: "nightly_digest", name: "Nightly digest",
183
183
  # job_class: "DigestJob", schedule: "0 7 * * *", scope: "tenant")
184
184
  #
185
185
  # Only ALLOWLISTED job classes are schedulable (a registered one, or one listed
186
186
  # here) — so a tenant admin can't schedule ActiveStorage::PurgeJob or a mailer:
187
187
  #
188
- # Loam.schedulable_jobs = %w[DigestJob ReindexJob]
188
+ # OpenLoam.schedulable_jobs = %w[DigestJob ReindexJob]
189
189
 
190
190
  # Domain event subscriptions. Subscribe to a single event or a whole domain
191
191
  # (trailing dot = prefix). Register them here at file scope, not inside
192
192
  # `to_prepare`: subscriptions are global, so a reload would add a second copy
193
193
  # of each one and every event would be handled twice.
194
194
  #
195
- # Loam::Events.subscribe("billing.subscription.renewed") do |name, payload|
195
+ # OpenLoam::Events.subscribe("billing.subscription.renewed") do |name, payload|
196
196
  # BillingMailer.renewal_receipt(payload[:id]).deliver_later
197
197
  # end
198
198
  #
199
- # Loam::Events.subscribe("rental.") do |name, payload|
200
- # Rails.logger.info("[loam event] #{name} #{payload.inspect}")
199
+ # OpenLoam::Events.subscribe("rental.") do |name, payload|
200
+ # Rails.logger.info("[open_loam event] #{name} #{payload.inspect}")
201
201
  # end
202
202
  #
203
203
  # Event -> in-app notification is the intended pattern for telling someone
204
204
  # something. The subscriber runs in the publisher's tenant context, so the
205
205
  # notification lands in the right tenant with no extra ceremony:
206
206
  #
207
- # Loam::Events.subscribe("rental.damage_report.approve") do |_name, payload|
208
- # Loam::Notifications.notify_role(:manager, title: "Damage report approved")
207
+ # OpenLoam::Events.subscribe("rental.damage_report.approve") do |_name, payload|
208
+ # OpenLoam::Notifications.notify_role(:manager, title: "Damage report approved")
209
209
  # end
210
210
 
211
- # Business rules (Loam::BusinessRule) are the admin-editable cousin of the
211
+ # Business rules (OpenLoam::BusinessRule) are the admin-editable cousin of the
212
212
  # subscriptions above: a manager declares, per tenant, WHEN a condition holds on
213
213
  # a triggering record THEN run a fixed vocabulary of safe actions (notify,
214
214
  # emit_event, set_field, block_transition). The condition is DATA — a
@@ -0,0 +1,15 @@
1
+ class CreateOpenLoamApiTokens < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_api_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.references :user, null: false, foreign_key: true<%= open_loam_type_option %>
6
+ t.string :token, null: false
7
+ t.string :label
8
+ t.datetime :last_used_at
9
+ t.timestamps
10
+ end
11
+ # Tokens are looked up before a tenant is known, so the uniqueness that
12
+ # matters is global.
13
+ add_index :open_loam_api_tokens, :token, unique: true
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ class CreateOpenLoamAuditRecords < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_audit_records<%= 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 :auditable_type, null: false
6
+ t.<%= open_loam_key_column_type %> :auditable_id<%= open_loam_key_limit_option %>, null: false
7
+ t.string :action, null: false
8
+ t.<%= open_loam_key_column_type %> :actor_id<%= open_loam_key_limit_option %>
9
+ t.text :changeset
10
+ t.timestamps
11
+ end
12
+ add_index :open_loam_audit_records, %i[tenant_id auditable_type auditable_id]
13
+ end
14
+ end
@@ -1,11 +1,11 @@
1
- class CreateLoamAuthAttempts < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamAuthAttempts < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_auth_attempts<%= loam_id_option %> do |t|
3
+ create_table :open_loam_auth_attempts<%= open_loam_id_option %> do |t|
4
4
  t.string :identifier, null: false # the submitted login (normalized), NOT tenant-scoped
5
5
  t.string :kind, null: false # password / totp / recovery / sudo
6
6
  t.string :ip # nullable; for an optional per-ip throttle
7
7
  t.timestamps
8
8
  end
9
- add_index :loam_auth_attempts, %i[identifier created_at]
9
+ add_index :open_loam_auth_attempts, %i[identifier created_at]
10
10
  end
11
11
  end
@@ -1,29 +1,29 @@
1
- class CreateLoamBusinessRules < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamBusinessRules < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_business_rules<%= 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_business_rules<%= 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 :entity_type # the entity this rule watches (nil = event-only)
7
- t.string :trigger, null: false # an event pattern (Loam::Events.pattern_matches?)
7
+ t.string :trigger, null: false # an event pattern (OpenLoam::Events.pattern_matches?)
8
8
  t.json :condition, null: false, default: {} # a safe condition tree (data, never code)
9
9
  t.json :actions, null: false, default: [] # an ordered list of typed action descriptors
10
10
  t.boolean :active, null: false, default: true
11
11
  t.integer :priority, null: false, default: 0
12
12
  t.timestamps
13
13
  end
14
- add_index :loam_business_rules, %i[tenant_id active]
14
+ add_index :open_loam_business_rules, %i[tenant_id active]
15
15
 
16
- create_table :loam_business_rule_runs<%= loam_id_option %> do |t|
17
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
18
- t.references :business_rule, null: false, foreign_key: { to_table: :loam_business_rules }<%= loam_type_option %>
16
+ create_table :open_loam_business_rule_runs<%= open_loam_id_option %> do |t|
17
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
18
+ t.references :business_rule, null: false, foreign_key: { to_table: :open_loam_business_rules }<%= open_loam_type_option %>
19
19
  t.string :subject_type
20
- t.<%= loam_key_column_type %> :subject_id<%= loam_key_limit_option %>
20
+ t.<%= open_loam_key_column_type %> :subject_id<%= open_loam_key_limit_option %>
21
21
  t.string :event_name
22
22
  t.boolean :matched, null: false, default: false
23
23
  t.json :actions_taken, null: false, default: []
24
24
  t.text :error
25
25
  t.timestamps
26
26
  end
27
- add_index :loam_business_rule_runs, %i[tenant_id business_rule_id created_at]
27
+ add_index :open_loam_business_rule_runs, %i[tenant_id business_rule_id created_at]
28
28
  end
29
29
  end
@@ -0,0 +1,13 @@
1
+ class CreateOpenLoamComments < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_comments<%= 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 :commentable_type, null: false
6
+ t.<%= open_loam_key_column_type %> :commentable_id<%= open_loam_key_limit_option %>, null: false
7
+ t.references :author, null: false, foreign_key: { to_table: :users }<%= open_loam_type_option %>
8
+ t.text :body, null: false
9
+ t.timestamps
10
+ end
11
+ add_index :open_loam_comments, %i[tenant_id commentable_type commentable_id]
12
+ end
13
+ end
@@ -1,10 +1,10 @@
1
- class CreateLoamConfigs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamConfigs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_configs<%= loam_id_option %> do |t|
3
+ create_table :open_loam_configs<%= open_loam_id_option %> do |t|
4
4
  t.string :key, null: false
5
5
  # Nullable: a NULL tenant_id is the GLOBAL row; a set one is a per-tenant
6
6
  # override. So this is NOT a tenant-scoped table.
7
- t.references :tenant, null: true, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
7
+ t.references :tenant, null: true, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
8
8
  # Any JSON-able value under one key. Nullable on purpose: row existence is
9
9
  # the "is it set" signal, and JSON null is itself a storable value.
10
10
  t.json :value_json
@@ -12,10 +12,10 @@ class CreateLoamConfigs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STR
12
12
  end
13
13
 
14
14
  # One global row per key (partial: only where there is no tenant).
15
- add_index :loam_configs, :key, unique: true, where: "tenant_id IS NULL",
16
- name: "index_loam_configs_global_key"
15
+ add_index :open_loam_configs, :key, unique: true, where: "tenant_id IS NULL",
16
+ name: "index_open_loam_configs_global_key"
17
17
  # One override row per key per tenant.
18
- add_index :loam_configs, %i[key tenant_id], unique: true,
19
- name: "index_loam_configs_on_key_and_tenant"
18
+ add_index :open_loam_configs, %i[key tenant_id], unique: true,
19
+ name: "index_open_loam_configs_on_key_and_tenant"
20
20
  end
21
21
  end
@@ -0,0 +1,19 @@
1
+ class CreateOpenLoamCustomFieldValues < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_custom_field_values<%= 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 :indexable_type, null: false
6
+ t.<%= open_loam_key_column_type %> :indexable_id<%= open_loam_key_limit_option %>, null: false
7
+ t.string :field_key, null: false
8
+ t.text :value_text # canonical string form (contains/present/eq)
9
+ t.decimal :value_number # integer/decimal fields (range queries)
10
+ t.boolean :value_boolean # boolean fields
11
+ t.datetime :value_datetime # date/datetime fields
12
+ t.timestamps
13
+ end
14
+ add_index :open_loam_custom_field_values, %i[indexable_type indexable_id field_key],
15
+ unique: true, name: "index_open_loam_cfv_unique"
16
+ add_index :open_loam_custom_field_values, %i[tenant_id indexable_type field_key value_text], name: "index_open_loam_cfv_text"
17
+ add_index :open_loam_custom_field_values, %i[tenant_id indexable_type field_key value_number], name: "index_open_loam_cfv_number"
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ class CreateOpenLoamDashboardWidgets < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_dashboard_widgets<%= 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 :widget_key, null: false # a registered OpenLoam::Widgets key
6
+ t.integer :position, null: false, default: 0
7
+ t.boolean :active, null: false, default: true
8
+ t.timestamps
9
+ end
10
+ add_index :open_loam_dashboard_widgets, %i[tenant_id widget_key], unique: true
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ class CreateOpenLoamDictionaries < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_dictionaries<%= 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 :key, null: false # the code the field def / API references (e.g. "damage_severity")
6
+ t.string :name, null: false # human label for the list
7
+ t.timestamps
8
+ end
9
+ add_index :open_loam_dictionaries, %i[tenant_id key], unique: true
10
+ end
11
+ end
@@ -1,8 +1,8 @@
1
- class CreateLoamDictionaryEntries < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamDictionaryEntries < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_dictionary_entries<%= loam_id_option %> do |t|
4
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
5
- t.references :dictionary, null: false, foreign_key: { to_table: :loam_dictionaries }<%= loam_type_option %>
3
+ create_table :open_loam_dictionary_entries<%= 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.references :dictionary, null: false, foreign_key: { to_table: :open_loam_dictionaries }<%= open_loam_type_option %>
6
6
  t.string :value, null: false # the stored code
7
7
  t.string :label, null: false # display text
8
8
  t.string :color # optional hex
@@ -12,7 +12,7 @@ class CreateLoamDictionaryEntries < ActiveRecord::Migration[<%= ActiveRecord::VE
12
12
  t.boolean :active, null: false, default: true
13
13
  t.timestamps
14
14
  end
15
- add_index :loam_dictionary_entries, %i[dictionary_id value], unique: true
16
- add_index :loam_dictionary_entries, %i[tenant_id dictionary_id position]
15
+ add_index :open_loam_dictionary_entries, %i[dictionary_id value], unique: true
16
+ add_index :open_loam_dictionary_entries, %i[tenant_id dictionary_id position]
17
17
  end
18
18
  end
@@ -1,8 +1,8 @@
1
- class CreateLoamEventDeliveries < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamEventDeliveries < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_event_deliveries<%= loam_id_option %> do |t|
4
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
5
- t.string :subscriber_key, null: false # a registered Loam::DurableEvents subscriber
3
+ create_table :open_loam_event_deliveries<%= 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 :subscriber_key, null: false # a registered OpenLoam::DurableEvents subscriber
6
6
  t.string :event_name, null: false
7
7
  t.json :payload, null: false # JSON-scalar event payload
8
8
  t.string :status, null: false, default: "pending" # pending | delivered | dead
@@ -12,6 +12,6 @@ class CreateLoamEventDeliveries < ActiveRecord::Migration[<%= ActiveRecord::VERS
12
12
  t.datetime :delivered_at
13
13
  t.timestamps
14
14
  end
15
- add_index :loam_event_deliveries, %i[tenant_id status next_attempt_at]
15
+ add_index :open_loam_event_deliveries, %i[tenant_id status next_attempt_at]
16
16
  end
17
17
  end
@@ -1,7 +1,7 @@
1
- class CreateLoamFieldDefinitions < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamFieldDefinitions < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_field_definitions<%= 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_field_definitions<%= 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
6
6
  t.string :name, null: false
7
7
  t.string :field_type, null: false
@@ -10,6 +10,6 @@ class CreateLoamFieldDefinitions < ActiveRecord::Migration[<%= ActiveRecord::VER
10
10
  t.json :config, null: false, default: {} # type-specific settings (e.g. a dictionary field's key)
11
11
  t.timestamps
12
12
  end
13
- add_index :loam_field_definitions, %i[tenant_id entity_type name], unique: true, name: "index_loam_field_definitions_on_tenant_entity_name"
13
+ add_index :open_loam_field_definitions, %i[tenant_id entity_type name], unique: true, name: "index_open_loam_field_definitions_on_tenant_entity_name"
14
14
  end
15
15
  end
@@ -1,11 +1,11 @@
1
- class CreateLoamInboundWebhooks < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamInboundWebhooks < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_inbound_webhook_sources<%= 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_inbound_webhook_sources<%= 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 :token, null: false # unguessable URL id: /webhooks/:token
7
7
  t.string :secret, null: false # HMAC key (authenticates the call)
8
- t.string :signature_header, null: false, default: "X-Loam-Signature"
8
+ t.string :signature_header, null: false, default: "X-OpenLoam-Signature"
9
9
  t.string :delivery_id_header # optional: external delivery-id for dedupe
10
10
  t.string :timestamp_header # optional: enables the freshness window
11
11
  t.integer :timestamp_tolerance # seconds; nil = default 300
@@ -13,11 +13,11 @@ class CreateLoamInboundWebhooks < ActiveRecord::Migration[<%= ActiveRecord::VERS
13
13
  t.boolean :active, null: false, default: true
14
14
  t.timestamps
15
15
  end
16
- add_index :loam_inbound_webhook_sources, :token, unique: true
16
+ add_index :open_loam_inbound_webhook_sources, :token, unique: true
17
17
 
18
- create_table :loam_inbound_webhook_deliveries<%= loam_id_option %> do |t|
19
- t.references :tenant, null: false, foreign_key: { to_table: :loam_tenants }<%= loam_type_option %>
20
- t.references :source, null: false, foreign_key: { to_table: :loam_inbound_webhook_sources }<%= loam_type_option %>
18
+ create_table :open_loam_inbound_webhook_deliveries<%= open_loam_id_option %> do |t|
19
+ t.references :tenant, null: false, foreign_key: { to_table: :open_loam_tenants }<%= open_loam_type_option %>
20
+ t.references :source, null: false, foreign_key: { to_table: :open_loam_inbound_webhook_sources }<%= open_loam_type_option %>
21
21
  t.string :external_id, null: false # delivery-id header, or a body hash
22
22
  t.string :event_name, null: false
23
23
  t.string :status, null: false, default: "received"
@@ -26,6 +26,6 @@ class CreateLoamInboundWebhooks < ActiveRecord::Migration[<%= ActiveRecord::VERS
26
26
  t.timestamps
27
27
  end
28
28
  # The idempotency ledger: a replayed (source, external_id) can't be inserted twice.
29
- add_index :loam_inbound_webhook_deliveries, %i[source_id external_id], unique: true
29
+ add_index :open_loam_inbound_webhook_deliveries, %i[source_id external_id], unique: true
30
30
  end
31
31
  end
@@ -0,0 +1,11 @@
1
+ class CreateOpenLoamMemberships < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_memberships<%= 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.references :user, null: false, foreign_key: true<%= open_loam_type_option %>
6
+ t.string :role, null: false
7
+ t.timestamps
8
+ end
9
+ add_index :open_loam_memberships, %i[tenant_id user_id], unique: true
10
+ end
11
+ end
@@ -1,9 +1,9 @@
1
- class CreateLoamMfaCredentials < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
1
+ class CreateOpenLoamMfaCredentials < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
2
  def change
3
- create_table :loam_mfa_credentials<%= loam_id_option %> do |t|
3
+ create_table :open_loam_mfa_credentials<%= open_loam_id_option %> do |t|
4
4
  # Per USER, not per tenant — MFA belongs to the person (no tenant_id).
5
- t.references :user, null: false, foreign_key: { to_table: :users }, index: { unique: true }<%= loam_type_option %>
6
- t.text :totp_secret # encrypted at rest, user-scoped (Loam::Encryptable)
5
+ t.references :user, null: false, foreign_key: { to_table: :users }, index: { unique: true }<%= open_loam_type_option %>
6
+ t.text :totp_secret # encrypted at rest, user-scoped (OpenLoam::Encryptable)
7
7
  t.text :recovery_codes # JSON: [{ digest, used_at }], codes stored hashed
8
8
  t.datetime :activated_at # nil until the user confirms a live code
9
9
  t.bigint :last_totp_step # last accepted TOTP timestep — rejects replays
@@ -0,0 +1,15 @@
1
+ class CreateOpenLoamNotifications < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table :open_loam_notifications<%= 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.references :user, null: false, foreign_key: true<%= open_loam_type_option %>
6
+ t.string :title, null: false
7
+ t.text :body
8
+ t.datetime :read_at
9
+ t.string :source_type
10
+ t.<%= open_loam_key_column_type %> :source_id<%= open_loam_key_limit_option %>
11
+ t.timestamps
12
+ end
13
+ add_index :open_loam_notifications, %i[tenant_id user_id read_at]
14
+ end
15
+ end