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,12 +1,12 @@
1
1
  module Admin
2
2
  # Email + password login for the admin, then (if the user has MFA) a TOTP
3
- # challenge, then the tenant pick. A Loam user can belong to several tenants,
3
+ # challenge, then the tenant pick. A OpenLoam user can belong to several tenants,
4
4
  # so: authenticate → second factor → choose a tenant where they hold a
5
5
  # membership. The second factor runs BEFORE any tenant is chosen, which is why
6
- # the MFA secret is keyed to the user, not a tenant (Loam::MfaCredential).
6
+ # the MFA secret is keyed to the user, not a tenant (OpenLoam::MfaCredential).
7
7
  #
8
8
  # Not a BaseController subclass: everything there assumes an established
9
- # Loam::Current, which is exactly what this controller is trying to build.
9
+ # OpenLoam::Current, which is exactly what this controller is trying to build.
10
10
  class SessionsController < ActionController::Base
11
11
  layout "admin"
12
12
 
@@ -14,17 +14,17 @@ module Admin
14
14
  return redirect_to mfa_challenge_admin_session_path if session[:mfa_pending]
15
15
 
16
16
  @user = authenticated_user
17
- @tenants = @user ? Loam::Membership.tenants_for(@user) : Loam::Tenant.none
17
+ @tenants = @user ? OpenLoam::Membership.tenants_for(@user) : OpenLoam::Tenant.none
18
18
  end
19
19
 
20
20
  def create
21
21
  email = params[:email]
22
22
 
23
- # Rate-limit BEFORE touching the password (Loam::AuthThrottle). Throttle by
23
+ # Rate-limit BEFORE touching the password (OpenLoam::AuthThrottle). Throttle by
24
24
  # the submitted identifier whether or not the account exists, and give the
25
25
  # SAME generic locked response either way — so a lockout can't become an
26
26
  # account-existence oracle.
27
- if Loam::AuthThrottle.locked?(email)
27
+ if OpenLoam::AuthThrottle.locked?(email)
28
28
  @error = throttle_message(email)
29
29
  return render :new, status: :too_many_requests
30
30
  end
@@ -32,20 +32,20 @@ module Admin
32
32
  user = User.authenticate_by(email: email, password: params[:password])
33
33
 
34
34
  if user.nil?
35
- Loam::AuthThrottle.record_failure(email, kind: "password", ip: request.remote_ip)
35
+ OpenLoam::AuthThrottle.record_failure(email, kind: "password", ip: request.remote_ip)
36
36
  # One message for both cases on purpose: saying which half was wrong
37
37
  # tells an attacker which emails exist.
38
38
  @error = "Wrong email or password."
39
39
  return render :new, status: :unauthorized
40
40
  end
41
41
 
42
- Loam::AuthThrottle.clear(email) # a successful login resets the counter
42
+ OpenLoam::AuthThrottle.clear(email) # a successful login resets the counter
43
43
  reset_session # a fresh session id at login: no fixation
44
44
  session[:user_id] = user.id
45
45
 
46
46
  # Password is only the first factor when MFA is active — hold the login in
47
47
  # a "pending" state (no tenant, no access) until the code checks out.
48
- if Loam::MfaCredential.active_for(user)
48
+ if OpenLoam::MfaCredential.active_for(user)
49
49
  session[:mfa_pending] = true
50
50
  redirect_to mfa_challenge_admin_session_path
51
51
  else
@@ -65,20 +65,20 @@ module Admin
65
65
 
66
66
  # A 6-digit TOTP (with drift, several codes valid) is the prime brute-force
67
67
  # target — lock it out on the user's identifier.
68
- if Loam::AuthThrottle.locked?(user.email)
68
+ if OpenLoam::AuthThrottle.locked?(user.email)
69
69
  @user = user
70
70
  @error = throttle_message(user.email)
71
71
  return render :mfa_challenge, status: :too_many_requests
72
72
  end
73
73
 
74
- credential = Loam::MfaCredential.active_for(user)
74
+ credential = OpenLoam::MfaCredential.active_for(user)
75
75
 
76
76
  if credential.verify_totp(params[:code]) || credential.consume_recovery_code(params[:code])
77
- Loam::AuthThrottle.clear(user.email)
77
+ OpenLoam::AuthThrottle.clear(user.email)
78
78
  session.delete(:mfa_pending)
79
79
  complete_authentication(user)
80
80
  else
81
- Loam::AuthThrottle.record_failure(user.email, kind: "totp", ip: request.remote_ip)
81
+ OpenLoam::AuthThrottle.record_failure(user.email, kind: "totp", ip: request.remote_ip)
82
82
  # One generic error — never reveal whether a code was close or a
83
83
  # recovery code was already spent.
84
84
  @user = user
@@ -92,7 +92,7 @@ module Admin
92
92
  # back to password login. The `state` is our CSRF token for the round-trip.
93
93
  def sso_start
94
94
  email = params[:email].to_s
95
- provider = Loam::Sso.provider_for(email: email)
95
+ provider = OpenLoam::Sso.provider_for(email: email)
96
96
 
97
97
  if provider.nil?
98
98
  return redirect_to new_admin_session_path(email: email),
@@ -105,8 +105,8 @@ module Admin
105
105
  session[:sso_provider_id] = provider.id
106
106
  session[:sso_tenant_id] = provider.tenant_id
107
107
 
108
- url = Loam.as_tenant(provider.tenant) do
109
- Loam::Sso.build(provider, redirect_uri: sso_callback_admin_session_url)
108
+ url = OpenLoam.as_tenant(provider.tenant) do
109
+ OpenLoam::Sso.build(provider, redirect_uri: sso_callback_admin_session_url)
110
110
  .authorization_url(state: state, login_hint: email)
111
111
  end
112
112
  redirect_to url, allow_other_host: true
@@ -124,15 +124,15 @@ module Admin
124
124
  return redirect_to new_admin_session_path, alert: "SSO sign-in could not be verified. Please try again."
125
125
  end
126
126
 
127
- tenant = Loam::Tenant.find_by(id: tenant_id)
128
- provider = tenant && Loam.as_tenant(tenant) { Loam::SsoProvider.find_by(id: provider_id) }
127
+ tenant = OpenLoam::Tenant.find_by(id: tenant_id)
128
+ provider = tenant && OpenLoam.as_tenant(tenant) { OpenLoam::SsoProvider.find_by(id: provider_id) }
129
129
  if provider.nil? || !provider.active?
130
130
  return redirect_to new_admin_session_path, alert: "That SSO provider is no longer available."
131
131
  end
132
132
 
133
- user = Loam.as_tenant(tenant) do
134
- claims = Loam::Sso.build(provider, redirect_uri: sso_callback_admin_session_url).exchange(code: params[:code])
135
- Loam::Sso.provision(provider, claims)
133
+ user = OpenLoam.as_tenant(tenant) do
134
+ claims = OpenLoam::Sso.build(provider, redirect_uri: sso_callback_admin_session_url).exchange(code: params[:code])
135
+ OpenLoam::Sso.provision(provider, claims)
136
136
  end
137
137
 
138
138
  reset_session
@@ -141,13 +141,13 @@ module Admin
141
141
 
142
142
  # SSO establishes primary auth; if the user also runs app-side MFA, still
143
143
  # require the second factor (the safe choice — SSO does not waive it).
144
- if Loam::MfaCredential.active_for(user)
144
+ if OpenLoam::MfaCredential.active_for(user)
145
145
  session[:mfa_pending] = true
146
146
  redirect_to mfa_challenge_admin_session_path
147
147
  else
148
148
  complete_authentication(user)
149
149
  end
150
- rescue Loam::Sso::Error
150
+ rescue OpenLoam::Sso::Error
151
151
  # An unverified email, a domain the provider does not own, or any other
152
152
  # provisioning refusal: no session, nothing linked, one generic message.
153
153
  reset_session
@@ -162,7 +162,7 @@ module Admin
162
162
  user = authenticated_user
163
163
  return redirect_to new_admin_session_path if user.nil?
164
164
 
165
- tenant = Loam::Membership.tenants_for(user).find_by(id: params[:tenant_id])
165
+ tenant = OpenLoam::Membership.tenants_for(user).find_by(id: params[:tenant_id])
166
166
 
167
167
  # A tenant the user has no membership in is simply not in that list, so
168
168
  # picking one is impossible rather than merely forbidden.
@@ -173,7 +173,7 @@ module Admin
173
173
 
174
174
  def destroy
175
175
  reset_session
176
- Loam::Current.reset
176
+ OpenLoam::Current.reset
177
177
  redirect_to new_admin_session_path
178
178
  end
179
179
 
@@ -184,7 +184,7 @@ module Admin
184
184
  end
185
185
 
186
186
  def throttle_message(identifier)
187
- minutes = (Loam::AuthThrottle.remaining_lockout(identifier) / 60.0).ceil
187
+ minutes = (OpenLoam::AuthThrottle.remaining_lockout(identifier) / 60.0).ceil
188
188
  "Too many attempts. Try again in about #{[ minutes, 1 ].max} minute(s)."
189
189
  end
190
190
 
@@ -206,11 +206,11 @@ module Admin
206
206
  # SSO knows exactly which tenant to enter (the IdP's), so honor it even for
207
207
  # a multi-tenant user rather than showing the picker.
208
208
  if (sso_tenant_id = session.delete(:sso_tenant_id))
209
- tenant = Loam::Membership.tenants_for(user).find_by(id: sso_tenant_id)
209
+ tenant = OpenLoam::Membership.tenants_for(user).find_by(id: sso_tenant_id)
210
210
  return enter(user, tenant) if tenant
211
211
  end
212
212
 
213
- tenants = Loam::Membership.tenants_for(user)
213
+ tenants = OpenLoam::Membership.tenants_for(user)
214
214
 
215
215
  if tenants.one?
216
216
  enter(user, tenants.first)
@@ -237,11 +237,11 @@ module Admin
237
237
  # resolved in that tenant). If the user's role is on the list and they have
238
238
  # no active credential, they are sent to enrollment before they can work.
239
239
  def mfa_enrollment_required?(user, tenant)
240
- return false if Loam::MfaCredential.active_for(user)
240
+ return false if OpenLoam::MfaCredential.active_for(user)
241
241
 
242
- Loam.as_tenant(tenant) do
243
- role = Loam::Membership.find_by(user_id: user.id)&.role
244
- role.present? && Array(Loam::Configs.get("security.mfa_required_roles", default: [])).include?(role)
242
+ OpenLoam.as_tenant(tenant) do
243
+ role = OpenLoam::Membership.find_by(user_id: user.id)&.role
244
+ role.present? && Array(OpenLoam::Configs.get("security.mfa_required_roles", default: [])).include?(role)
245
245
  end
246
246
  end
247
247
  end
@@ -1,6 +1,6 @@
1
1
  module Admin
2
2
  # Configure this tenant's SSO (OIDC) provider — manager-only, since it governs
3
- # who can sign in and at what role. Tenant-scoped by Loam::SsoProvider's default
3
+ # who can sign in and at what role. Tenant-scoped by OpenLoam::SsoProvider's default
4
4
  # scope, so a manager only ever sees and edits their own tenant's connection.
5
5
  # The client_secret is WRITE-ONLY: it is encrypted at rest and never rendered
6
6
  # back, so editing without retyping it leaves the stored secret untouched.
@@ -10,20 +10,20 @@ module Admin
10
10
 
11
11
  rescue_from JSON::ParserError do |error|
12
12
  flash.now[:alert] = "The group→role map must be valid JSON: #{error.message}"
13
- @provider ||= Loam::SsoProvider.new
13
+ @provider ||= OpenLoam::SsoProvider.new
14
14
  render(@provider.persisted? ? :edit : :new, status: :unprocessable_entity)
15
15
  end
16
16
 
17
17
  def index
18
- @providers = Loam::SsoProvider.order(:domain)
18
+ @providers = OpenLoam::SsoProvider.order(:domain)
19
19
  end
20
20
 
21
21
  def new
22
- @provider = Loam::SsoProvider.new(protocol: "oidc", active: true, jit_role: "employee")
22
+ @provider = OpenLoam::SsoProvider.new(protocol: "oidc", active: true, jit_role: "employee")
23
23
  end
24
24
 
25
25
  def create
26
- @provider = Loam::SsoProvider.new(provider_params)
26
+ @provider = OpenLoam::SsoProvider.new(provider_params)
27
27
  if @provider.save
28
28
  redirect_to admin_sso_providers_path, notice: "SSO provider created."
29
29
  else
@@ -49,7 +49,7 @@ module Admin
49
49
  private
50
50
 
51
51
  def set_provider
52
- @provider = Loam::SsoProvider.find(params[:id])
52
+ @provider = OpenLoam::SsoProvider.find(params[:id])
53
53
  end
54
54
 
55
55
  def provider_params
@@ -2,8 +2,8 @@
2
2
  <p style="color:#b00"><%%= @error || flash[:alert] %></p>
3
3
  <%% end %>
4
4
 
5
- <%# The model is namespaced (Loam::SsoProvider), so an inferred URL/param-scope
6
- would be admin_loam_sso_provider_path / loam_sso_provider[...]. Pin both to
5
+ <%# The model is namespaced (OpenLoam::SsoProvider), so an inferred URL/param-scope
6
+ would be admin_open_loam_sso_provider_path / open_loam_sso_provider[...]. Pin both to
7
7
  the un-namespaced route and the "sso_provider" key the controller permits. %>
8
8
  <%%= form_with model: @provider, scope: :sso_provider,
9
9
  url: (@provider.persisted? ? admin_sso_provider_path(@provider) : admin_sso_providers_path) do |f| %>
@@ -10,18 +10,18 @@ module Admin
10
10
  def create
11
11
  identifier = "#{current_actor.email}:sudo" # a distinct throttle bucket from login
12
12
 
13
- if Loam::AuthThrottle.locked?(identifier)
13
+ if OpenLoam::AuthThrottle.locked?(identifier)
14
14
  @error = "Too many attempts. Try again later."
15
15
  return render :new, status: :too_many_requests
16
16
  end
17
17
 
18
18
  if reauthenticated?
19
- Loam::AuthThrottle.clear(identifier)
19
+ OpenLoam::AuthThrottle.clear(identifier)
20
20
  session[:sudo_at] = Time.now.to_i
21
21
  redirect_to(session.delete(:sudo_return_to).presence || admin_root_path,
22
22
  notice: "Re-authenticated — you can complete the action now.")
23
23
  else
24
- Loam::AuthThrottle.record_failure(identifier, kind: "sudo", ip: request.remote_ip)
24
+ OpenLoam::AuthThrottle.record_failure(identifier, kind: "sudo", ip: request.remote_ip)
25
25
  @error = "That did not verify. Try again."
26
26
  render :new, status: :unauthorized
27
27
  end
@@ -32,9 +32,9 @@ module Admin
32
32
  # If the user has MFA, step-up takes a TOTP code — NOT a recovery code:
33
33
  # recovery codes are single-use and reserved for LOGIN, so a routine sudo
34
34
  # must never silently burn one. Otherwise fall back to the password. Either
35
- # way it is the SAME person in Loam::Current re-confirming.
35
+ # way it is the SAME person in OpenLoam::Current re-confirming.
36
36
  def reauthenticated?
37
- credential = Loam::MfaCredential.active_for(current_actor)
37
+ credential = OpenLoam::MfaCredential.active_for(current_actor)
38
38
  if credential
39
39
  credential.verify_totp(params[:code])
40
40
  else
@@ -7,7 +7,7 @@
7
7
  <p>This action is sensitive, so please re-authenticate.</p>
8
8
 
9
9
  <%%= form_with url: admin_sudo_path, method: :post do |f| %>
10
- <%% if Loam::MfaCredential.active_for(current_actor) %>
10
+ <%% if OpenLoam::MfaCredential.active_for(current_actor) %>
11
11
  <p>
12
12
  <%%= label_tag :code, "Authenticator code" %><br>
13
13
  <%%= text_field_tag :code, nil, autofocus: true, autocomplete: "one-time-code", inputmode: "numeric" %>
@@ -1,7 +1,7 @@
1
1
  module Admin
2
- # Per-record content translations (Loam::Translatable) — manager-only, since
2
+ # Per-record content translations (OpenLoam::Translatable) — manager-only, since
3
3
  # translating content is a privileged edit. Scoped by translatable_type +
4
- # translatable_id; edits each translatable field across Loam.locales. The base
4
+ # translatable_id; edits each translatable field across OpenLoam.locales. The base
5
5
  # (default-locale) value stays on the record itself and is shown read-only for
6
6
  # reference — translations are additive.
7
7
  class TranslationsController < BaseController
@@ -12,9 +12,9 @@ module Admin
12
12
 
13
13
  def update
14
14
  params.require(:translations).to_unsafe_h.each do |field, by_locale|
15
- next unless @record.class.loam_translatable?(field)
15
+ next unless @record.class.open_loam_translatable?(field)
16
16
 
17
- by_locale.each { |locale, value| @record.set_translation(field, locale, value) if Loam.locales.include?(locale) }
17
+ by_locale.each { |locale, value| @record.set_translation(field, locale, value) if OpenLoam.locales.include?(locale) }
18
18
  end
19
19
  redirect_to translate_path, notice: "Translations saved."
20
20
  end
@@ -22,11 +22,11 @@ module Admin
22
22
  private
23
23
 
24
24
  def set_record
25
- model = Loam::Import.allowed_model(params[:translatable_type]) # whitelist: a Loam entity only
26
- raise ActiveRecord::RecordNotFound unless model.include?(Loam::Translatable)
25
+ model = OpenLoam::Import.allowed_model(params[:translatable_type]) # whitelist: a OpenLoam entity only
26
+ raise ActiveRecord::RecordNotFound unless model.include?(OpenLoam::Translatable)
27
27
 
28
28
  @record = model.find(params[:translatable_id])
29
- @fields = model.loam_translatable_attributes
29
+ @fields = model.open_loam_translatable_attributes
30
30
  end
31
31
 
32
32
  def translate_path
@@ -1,14 +1,14 @@
1
1
  <h1>Translations — <%%= @record.class.model_name.human %> #<%%= @record.id %></h1>
2
2
 
3
- <p>Translate content per locale. The base (<%%= Loam.default_locale.upcase %>) value
3
+ <p>Translate content per locale. The base (<%%= OpenLoam.default_locale.upcase %>) value
4
4
  stays on the record; other locales overlay onto it, falling back to the base when
5
5
  empty.</p>
6
6
 
7
7
  <%%= form_with url: translate_path, method: :patch do %>
8
8
  <%% @fields.each do |field| %>
9
9
  <h3><%%= field.humanize %></h3>
10
- <p><em>Base (<%%= Loam.default_locale.upcase %>):</em> <%%= @record.read_attribute(field) %></p>
11
- <%% (Loam.locales - [Loam.default_locale]).each do |locale| %>
10
+ <p><em>Base (<%%= OpenLoam.default_locale.upcase %>):</em> <%%= @record.read_attribute(field) %></p>
11
+ <%% (OpenLoam.locales - [OpenLoam.default_locale]).each do |locale| %>
12
12
  <p>
13
13
  <%%= label_tag "translations[#{field}][#{locale}]", locale.upcase %><br>
14
14
  <%%= text_field_tag "translations[#{field}][#{locale}]", @record.translations_for(field)[locale] %>
@@ -6,15 +6,15 @@ module Admin
6
6
  before_action { require_role!(:manager) }
7
7
 
8
8
  def index
9
- @records = Loam::WebhookEndpoint.order(:event_pattern)
9
+ @records = OpenLoam::WebhookEndpoint.order(:event_pattern)
10
10
  end
11
11
 
12
12
  def new
13
- @record = Loam::WebhookEndpoint.new(active: true)
13
+ @record = OpenLoam::WebhookEndpoint.new(active: true)
14
14
  end
15
15
 
16
16
  def create
17
- @record = Loam::WebhookEndpoint.new(permitted_params)
17
+ @record = OpenLoam::WebhookEndpoint.new(permitted_params)
18
18
 
19
19
  if @record.save
20
20
  redirect_to admin_webhook_endpoints_path
@@ -24,7 +24,7 @@ module Admin
24
24
  end
25
25
 
26
26
  def destroy
27
- Loam::WebhookEndpoint.find(params[:id]).destroy!
27
+ OpenLoam::WebhookEndpoint.find(params[:id]).destroy!
28
28
  redirect_to admin_webhook_endpoints_path
29
29
  end
30
30
 
@@ -28,5 +28,5 @@ domain ("rental."); anything else is one exact event name.</p>
28
28
  </tbody>
29
29
  </table>
30
30
 
31
- <p>Each delivery is signed: <code>X-Loam-Signature: sha256=HMAC-SHA256(secret, body)</code>.
31
+ <p>Each delivery is signed: <code>X-OpenLoam-Signature: sha256=HMAC-SHA256(secret, body)</code>.
32
32
  Recompute it on your side and reject anything that does not match.</p>
@@ -1,4 +1,4 @@
1
- /* Loam admin console — shared styles (extracted from the layout, L-402). */
1
+ /* OpenLoam admin console — shared styles (extracted from the layout, L-402). */
2
2
  body { font-family: system-ui, -apple-system, sans-serif; margin: 2rem; color: #1c1c1a; line-height: 1.5; }
3
3
  h1 { font-size: 1.55rem; margin: 0 0 0.75rem; }
4
4
  h2 { font-size: 1.2rem; margin: 1.25rem 0 0.5rem; }
@@ -3,9 +3,9 @@ module Api
3
3
  #
4
4
  # curl -H "Authorization: Bearer <token>" http://localhost:3000/api/equipment
5
5
  #
6
- # A token identifies one user in one tenant, and `Loam::ApiToken.authenticate`
7
- # establishes both in Loam::Current before any action runs. From that point
8
- # on this is ordinary tenant-scoped Loam code: every query is filtered, every
6
+ # A token identifies one user in one tenant, and `OpenLoam::ApiToken.authenticate`
7
+ # establishes both in OpenLoam::Current before any action runs. From that point
8
+ # on this is ordinary tenant-scoped OpenLoam code: every query is filtered, every
9
9
  # write is audited, every policy applies — the API is not a side door.
10
10
  #
11
11
  # Finding a token is the one lookup that cannot start from a tenant (the
@@ -14,7 +14,7 @@ module Api
14
14
  class BaseController < ActionController::API
15
15
  before_action :authenticate_api_token!
16
16
 
17
- rescue_from Loam::NotAuthorizedError do
17
+ rescue_from OpenLoam::NotAuthorizedError do
18
18
  render json: { error: "forbidden" }, status: :forbidden
19
19
  end
20
20
 
@@ -22,14 +22,14 @@ module Api
22
22
  render json: { error: "not_found" }, status: :not_found
23
23
  end
24
24
 
25
- rescue_from Loam::UnknownCustomFieldError do |error|
25
+ rescue_from OpenLoam::UnknownCustomFieldError do |error|
26
26
  render json: { error: error.message }, status: :unprocessable_entity
27
27
  end
28
28
 
29
29
  private
30
30
 
31
31
  def authenticate_api_token!
32
- @api_token = Loam::ApiToken.authenticate(bearer_token)
32
+ @api_token = OpenLoam::ApiToken.authenticate(bearer_token)
33
33
 
34
34
  render json: { error: "unauthorized" }, status: :unauthorized unless @api_token
35
35
  end
@@ -38,21 +38,21 @@ module Api
38
38
  request.headers["Authorization"].to_s[/\ABearer (.+)\z/, 1]
39
39
  end
40
40
 
41
- def current_tenant = Loam::Current.tenant
42
- def current_actor = Loam::Current.actor
41
+ def current_tenant = OpenLoam::Current.tenant
42
+ def current_actor = OpenLoam::Current.actor
43
43
 
44
44
  def policy_for(record)
45
- Loam::Policy.for(record)
45
+ OpenLoam::Policy.for(record)
46
46
  end
47
47
 
48
48
  def authorize!(policy, action)
49
- raise Loam::NotAuthorizedError unless policy.public_send(action)
49
+ raise OpenLoam::NotAuthorizedError unless policy.public_send(action)
50
50
  end
51
51
 
52
52
  # The JSON shape of an entity: its columns, custom fields included (they
53
53
  # live in the `custom_fields` column that every generated entity carries).
54
54
  #
55
- # Encrypted fields (Loam::Encryptable) are returned DECRYPTED — the caller is
55
+ # Encrypted fields (OpenLoam::Encryptable) are returned DECRYPTED — the caller is
56
56
  # authenticated, tenant-scoped and policy-gated, exactly like the admin show
57
57
  # screen — and their blind-index `<field>_hash` column is dropped, so the
58
58
  # equality-leaking hash never goes over the wire. `record.attributes` alone
@@ -60,17 +60,17 @@ module Api
60
60
  def entity_json(record, enrichments: nil)
61
61
  json = record.attributes
62
62
 
63
- if record.class.respond_to?(:loam_encrypted_attributes)
64
- record.class.loam_encrypted_attributes.each do |name|
63
+ if record.class.respond_to?(:open_loam_encrypted_attributes)
64
+ record.class.open_loam_encrypted_attributes.each do |name|
65
65
  json[name] = record.public_send(name)
66
66
  json.delete("#{name}_hash")
67
67
  end
68
68
  end
69
69
 
70
- # Computed cross-module blocks (Loam::Enrichers), under a separate key so
70
+ # Computed cross-module blocks (OpenLoam::Enrichers), under a separate key so
71
71
  # they're never confused with the record's own columns. An index passes the
72
72
  # batched result (avoiding N+1); a single show computes it here.
73
- enrichments = Loam::Enrichers.enrich(record) if enrichments.nil?
73
+ enrichments = OpenLoam::Enrichers.enrich(record) if enrichments.nil?
74
74
  json["enrichments"] = enrichments if enrichments.present?
75
75
  json
76
76
  end
@@ -1,21 +1,21 @@
1
1
  require "test_helper"
2
2
 
3
- # Structural guardrails. These are not feature tests — they enforce Loam's
3
+ # Structural guardrails. These are not feature tests — they enforce OpenLoam's
4
4
  # invariants on the codebase itself. If one of these fails, an agent (or a
5
5
  # human) stepped outside the conventions.
6
- class LoamGuardrailsTest < ActiveSupport::TestCase
7
- # Models that are legitimately not tenant-scoped. Loam::Config holds both
6
+ class OpenLoamGuardrailsTest < ActiveSupport::TestCase
7
+ # Models that are legitimately not tenant-scoped. OpenLoam::Config holds both
8
8
  # global (tenant_id NULL) and per-tenant override rows, so tenancy is a
9
- # nullable column and resolution lives in vetted gem code (Loam::Configs).
10
- # Loam::MfaCredential belongs to the person, who spans tenants — MFA is
9
+ # nullable column and resolution lives in vetted gem code (OpenLoam::Configs).
10
+ # OpenLoam::MfaCredential belongs to the person, who spans tenants — MFA is
11
11
  # verified at login before any tenant is chosen.
12
- TENANCY_ALLOWLIST = %w[ApplicationRecord User Loam::Tenant Loam::Config Loam::MfaCredential Loam::AuthAttempt].freeze
12
+ TENANCY_ALLOWLIST = %w[ApplicationRecord User OpenLoam::Tenant OpenLoam::Config OpenLoam::MfaCredential OpenLoam::AuthAttempt].freeze
13
13
 
14
14
  # Rails' own engine models (storage, rich text, jobs) are framework
15
15
  # plumbing, not business data — they are out of scope for tenant linting.
16
16
  FRAMEWORK_NAMESPACES = %w[ActiveStorage:: ActionText:: ActionMailbox:: SolidQueue:: SolidCache:: SolidCable::].freeze
17
17
 
18
- test "every app model is tenant-scoped (inherits Loam::TenantRecord)" do
18
+ test "every app model is tenant-scoped (inherits OpenLoam::TenantRecord)" do
19
19
  Rails.application.eager_load!
20
20
 
21
21
  offenders = ActiveRecord::Base.descendants.reject do |model|
@@ -23,20 +23,20 @@ class LoamGuardrailsTest < ActiveSupport::TestCase
23
23
  model.name.nil? ||
24
24
  TENANCY_ALLOWLIST.include?(model.name) ||
25
25
  FRAMEWORK_NAMESPACES.any? { |ns| model.name.start_with?(ns) } ||
26
- model <= Loam::TenantRecord
26
+ model <= OpenLoam::TenantRecord
27
27
  end
28
28
 
29
29
  assert_empty offenders,
30
30
  "These models are NOT tenant-scoped: #{offenders.map(&:name).join(', ')}. " \
31
- "Business models must inherit Loam::TenantRecord (use `rails g loam:entity`). " \
31
+ "Business models must inherit OpenLoam::TenantRecord (use `rails g open_loam:entity`). " \
32
32
  "If a model is intentionally global, add it to TENANCY_ALLOWLIST here — in review, on purpose."
33
33
  end
34
34
 
35
35
  test "touching a tenant-scoped model with no tenant context raises" do
36
- Loam::Current.reset
36
+ OpenLoam::Current.reset
37
37
 
38
- assert_raises(Loam::MissingTenantError) { Loam::AuditRecord.count }
39
- assert_raises(Loam::MissingTenantError) { Loam::Membership.first }
38
+ assert_raises(OpenLoam::MissingTenantError) { OpenLoam::AuditRecord.count }
39
+ assert_raises(OpenLoam::MissingTenantError) { OpenLoam::Membership.first }
40
40
  end
41
41
 
42
42
  test "nobody uses .unscoped outside vetted framework code" do
@@ -64,16 +64,16 @@ class LoamGuardrailsTest < ActiveSupport::TestCase
64
64
  "docs/ and link it, rather than raising the budget."
65
65
  end
66
66
 
67
- test "every Loam::FieldDefinition entity_type resolves to a class that uses Loam::CustomFields" do
67
+ test "every OpenLoam::FieldDefinition entity_type resolves to a class that uses OpenLoam::CustomFields" do
68
68
  Rails.application.eager_load!
69
69
 
70
- offenders = Loam::FieldDefinition.unscoped.distinct.pluck(:entity_type).reject do |entity_type|
70
+ offenders = OpenLoam::FieldDefinition.unscoped.distinct.pluck(:entity_type).reject do |entity_type|
71
71
  klass = entity_type.safe_constantize
72
- klass && klass.include?(Loam::CustomFields)
72
+ klass && klass.include?(OpenLoam::CustomFields)
73
73
  end
74
74
 
75
75
  assert_empty offenders,
76
- "These Loam::FieldDefinition entity_type values don't resolve to a class that " \
77
- "`include Loam::CustomFields`: #{offenders.join(', ')}. Likely a typo when the field was created."
76
+ "These OpenLoam::FieldDefinition entity_type values don't resolve to a class that " \
77
+ "`include OpenLoam::CustomFields`: #{offenders.join(', ')}. Likely a typo when the field was created."
78
78
  end
79
79
  end
@@ -1,20 +1,20 @@
1
- # Runs a CSV import in the background, advancing a Loam::ProgressJob so the admin
2
- # watches it live (L-915). Carries tenant + actor explicitly, like every Loam job.
1
+ # Runs a CSV import in the background, advancing a OpenLoam::ProgressJob so the admin
2
+ # watches it live (L-915). Carries tenant + actor explicitly, like every OpenLoam job.
3
3
  # The per-row summary (created/updated/failed + error rows) is stored on the
4
4
  # ProgressJob's `result` for the summary screen.
5
5
  class ImportJob < ApplicationJob
6
6
  queue_as :default
7
7
 
8
8
  def perform(entity_type:, csv:, mapping:, match_key:, tenant_id:, actor_id:)
9
- tenant = Loam::Tenant.find(tenant_id)
9
+ tenant = OpenLoam::Tenant.find(tenant_id)
10
10
  actor = User.find_by(id: actor_id)
11
- model = Loam::Import.allowed_model(entity_type)
11
+ model = OpenLoam::Import.allowed_model(entity_type)
12
12
 
13
- Loam.as_tenant(tenant, actor: actor) do
13
+ OpenLoam.as_tenant(tenant, actor: actor) do
14
14
  total = [ CSV.parse(csv).size - 1, 0 ].max
15
- progress = Loam::Progress.start(name: "Import #{entity_type}", total: total)
15
+ progress = OpenLoam::Progress.start(name: "Import #{entity_type}", total: total)
16
16
  begin
17
- result = Loam::Import.run(csv, model: model, mapping: mapping, actor: actor, match_key: match_key, progress: progress)
17
+ result = OpenLoam::Import.run(csv, model: model, mapping: mapping, actor: actor, match_key: match_key, progress: progress)
18
18
  progress.update_columns(result: result.to_h)
19
19
  progress.complete!
20
20
  rescue StandardError => error
@@ -1,17 +1,17 @@
1
1
  # Public endpoint that receives webhooks FROM external systems at
2
2
  # /webhooks/:token. No session, no bearer token: the HMAC signature is the auth
3
3
  # (ActionController::API, so there is no CSRF to skip). All the verified,
4
- # replay-resistant work lives in Loam::InboundWebhooks.ingest; this controller
4
+ # replay-resistant work lives in OpenLoam::InboundWebhooks.ingest; this controller
5
5
  # only maps its Result to an HTTP status and never leaks tenant context to the
6
6
  # next request on this thread.
7
7
  class InboundWebhooksController < ActionController::API
8
8
  def receive
9
- result = Loam::InboundWebhooks.ingest(
9
+ result = OpenLoam::InboundWebhooks.ingest(
10
10
  token: params[:token], raw_body: request.raw_post, headers: request.headers
11
11
  )
12
- Rails.logger.info("[loam inbound] #{result.status} #{result.reason}") if result.status >= 400
12
+ Rails.logger.info("[open_loam inbound] #{result.status} #{result.reason}") if result.status >= 400
13
13
  head result.status
14
14
  ensure
15
- Loam::Current.reset
15
+ OpenLoam::Current.reset
16
16
  end
17
17
  end