open-loam 0.1.1 → 0.3.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 (287) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +148 -8
  3. data/LICENSE +1 -1
  4. data/README.md +27 -25
  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/open_loam/event_log_prune_job.rb +15 -0
  8. data/app/jobs/{loam → open_loam}/event_redelivery_sweep_job.rb +4 -4
  9. data/app/jobs/{loam → open_loam}/webhook_delivery_job.rb +17 -8
  10. data/app/models/open_loam/api_token.rb +63 -0
  11. data/app/models/{loam → open_loam}/audit_record.rb +3 -3
  12. data/app/models/{loam → open_loam}/auth_attempt.rb +5 -5
  13. data/app/models/{loam → open_loam}/business_rule.rb +10 -10
  14. data/app/models/{loam → open_loam}/business_rule_run.rb +5 -5
  15. data/app/models/{loam → open_loam}/comment.rb +9 -9
  16. data/app/models/{loam → open_loam}/config.rb +7 -7
  17. data/app/models/{loam → open_loam}/custom_field_value.rb +5 -5
  18. data/app/models/{loam → open_loam}/dashboard_widget.rb +5 -5
  19. data/app/models/open_loam/dictionary.rb +20 -0
  20. data/app/models/{loam → open_loam}/dictionary_entry.rb +7 -7
  21. data/app/models/{loam → open_loam}/event_delivery.rb +4 -4
  22. data/app/models/open_loam/event_record.rb +42 -0
  23. data/app/models/{loam → open_loam}/field_definition.rb +8 -8
  24. data/app/models/{loam → open_loam}/inbound_webhook_delivery.rb +4 -4
  25. data/app/models/{loam → open_loam}/inbound_webhook_source.rb +13 -13
  26. data/app/models/{loam → open_loam}/membership.rb +6 -6
  27. data/app/models/{loam → open_loam}/mfa_credential.rb +8 -8
  28. data/app/models/{loam → open_loam}/notification.rb +10 -10
  29. data/app/models/{loam → open_loam}/pending_action.rb +70 -26
  30. data/app/models/{loam → open_loam}/perspective.rb +5 -5
  31. data/app/models/{loam → open_loam}/progress_job.rb +7 -7
  32. data/app/models/{loam → open_loam}/record_lock.rb +5 -5
  33. data/app/models/{loam → open_loam}/scheduled_job.rb +7 -7
  34. data/app/models/open_loam/search_token.rb +9 -0
  35. data/app/models/{loam → open_loam}/sso_identity.rb +4 -4
  36. data/app/models/open_loam/sso_provider.rb +66 -0
  37. data/app/models/open_loam/tenant.rb +20 -0
  38. data/app/models/{loam → open_loam}/translation.rb +5 -5
  39. data/app/models/open_loam/webhook_endpoint.rb +39 -0
  40. data/app/views/{loam → open_loam}/attachments/_attachments.html.erb +1 -1
  41. data/app/views/{loam → open_loam}/comments/_comments.html.erb +1 -1
  42. data/app/views/{loam → open_loam}/custom_fields/_fields.html.erb +6 -2
  43. data/lib/generators/{loam → open_loam}/entity/entity_generator.rb +9 -9
  44. data/lib/generators/{loam → open_loam}/entity/templates/api_controller.rb +2 -1
  45. data/lib/generators/{loam → open_loam}/entity/templates/controller.rb +32 -22
  46. data/lib/generators/{loam → open_loam}/entity/templates/entity_test.rb +12 -12
  47. data/lib/generators/{loam → open_loam}/entity/templates/migration.rb +5 -5
  48. data/lib/generators/{loam → open_loam}/entity/templates/model.rb +10 -10
  49. data/lib/generators/{loam → open_loam}/entity/templates/policy.rb +1 -1
  50. data/lib/generators/{loam → open_loam}/entity/templates/views/_form.html.erb +8 -5
  51. data/lib/generators/{loam → open_loam}/entity/templates/views/deleted.html.erb +7 -7
  52. data/lib/generators/open_loam/entity/templates/views/edit.html.erb +3 -0
  53. data/lib/generators/open_loam/entity/templates/views/index.html.erb +94 -0
  54. data/lib/generators/open_loam/entity/templates/views/new.html.erb +3 -0
  55. data/lib/generators/open_loam/entity/templates/views/show.html.erb +38 -0
  56. data/lib/generators/{loam → open_loam}/install/install_generator.rb +58 -47
  57. data/lib/generators/open_loam/install/templates/AGENTS.md +345 -0
  58. data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_controller.rb +2 -2
  59. data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_index.html.erb +1 -1
  60. data/lib/generators/open_loam/install/templates/admin/api_tokens_controller.rb +48 -0
  61. data/lib/generators/{loam → open_loam}/install/templates/admin/api_tokens_index.html.erb +23 -0
  62. data/lib/generators/{loam → open_loam}/install/templates/admin/base_controller.rb +101 -38
  63. data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_controller.rb +7 -7
  64. data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_form.html.erb +2 -2
  65. data/lib/generators/{loam → open_loam}/install/templates/admin/comments_controller.rb +4 -4
  66. data/lib/generators/{loam → open_loam}/install/templates/admin/configs_controller.rb +9 -9
  67. data/lib/generators/open_loam/install/templates/admin/dashboard_controller.rb +12 -0
  68. data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_controller.rb +5 -5
  69. data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_controller.rb +5 -5
  70. data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_form.html.erb +1 -1
  71. data/lib/generators/{loam → open_loam}/install/templates/admin/dictionary_entries_controller.rb +2 -2
  72. data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_controller.rb +5 -5
  73. data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_index.html.erb +1 -1
  74. data/lib/generators/{loam → open_loam}/install/templates/admin/events_controller.rb +7 -5
  75. data/lib/generators/{loam → open_loam}/install/templates/admin/features_controller.rb +9 -9
  76. data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_controller.rb +5 -5
  77. data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_new.html.erb +2 -2
  78. data/lib/generators/open_loam/install/templates/admin/history_controller.rb +64 -0
  79. data/lib/generators/{loam → open_loam}/install/templates/admin/history_index.html.erb +2 -2
  80. data/lib/generators/{loam → open_loam}/install/templates/admin/imports_controller.rb +25 -13
  81. data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_controller.rb +7 -7
  82. data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_new.html.erb +2 -4
  83. data/lib/generators/open_loam/install/templates/admin/layout.html.erb +76 -0
  84. data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_controller.rb +11 -6
  85. data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_controller.rb +5 -3
  86. data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_controller.rb +3 -3
  87. data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_index.html.erb +2 -2
  88. data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_controller.rb +3 -3
  89. data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_controller.rb +13 -7
  90. data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_index.html.erb +1 -1
  91. data/lib/generators/open_loam/install/templates/admin/progress_jobs_controller.rb +23 -0
  92. data/lib/generators/{loam → open_loam}/install/templates/admin/progress_jobs_index.html.erb +1 -1
  93. data/lib/generators/{loam → open_loam}/install/templates/admin/record_locks_controller.rb +4 -4
  94. data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_controller.rb +7 -7
  95. data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_form.html.erb +1 -1
  96. data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_index.html.erb +1 -1
  97. data/lib/generators/{loam → open_loam}/install/templates/admin/search_controller.rb +7 -5
  98. data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_controller.rb +33 -34
  99. data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_controller.rb +6 -6
  100. data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_form.html.erb +2 -2
  101. data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_index.html.erb +8 -1
  102. data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_controller.rb +7 -5
  103. data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_new.html.erb +1 -1
  104. data/lib/generators/{loam → open_loam}/install/templates/admin/translations_controller.rb +7 -7
  105. data/lib/generators/{loam → open_loam}/install/templates/admin/translations_index.html.erb +3 -3
  106. data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_controller.rb +4 -4
  107. data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_index.html.erb +1 -1
  108. data/lib/generators/{loam → open_loam}/install/templates/admin.css +1 -1
  109. data/lib/generators/open_loam/install/templates/api_base_controller.rb +127 -0
  110. data/lib/generators/{loam → open_loam}/install/templates/guardrails_test.rb +17 -17
  111. data/lib/generators/open_loam/install/templates/import_job.rb +38 -0
  112. data/lib/generators/{loam → open_loam}/install/templates/inbound_webhooks_controller.rb +4 -4
  113. data/lib/generators/{loam → open_loam}/install/templates/initializer.rb +87 -75
  114. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_api_tokens.rb +15 -0
  115. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_audit_records.rb +14 -0
  116. 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
  117. 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
  118. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_comments.rb +13 -0
  119. data/lib/generators/{loam/install/templates/migrations/create_loam_configs.rb → open_loam/install/templates/migrations/create_open_loam_configs.rb} +7 -7
  120. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_custom_field_values.rb +19 -0
  121. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dashboard_widgets.rb +12 -0
  122. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dictionaries.rb +11 -0
  123. 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
  124. 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
  125. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_event_records.rb +13 -0
  126. 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
  127. data/lib/generators/{loam/install/templates/migrations/create_loam_inbound_webhooks.rb → open_loam/install/templates/migrations/create_open_loam_inbound_webhooks.rb} +9 -10
  128. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_memberships.rb +11 -0
  129. 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
  130. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_notifications.rb +15 -0
  131. 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
  132. data/lib/generators/{loam/install/templates/migrations/create_loam_perspectives.rb → open_loam/install/templates/migrations/create_open_loam_perspectives.rb} +5 -5
  133. 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
  134. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_record_locks.rb +16 -0
  135. 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
  136. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_search_tokens.rb +18 -0
  137. data/lib/generators/{loam/install/templates/migrations/create_loam_sso_providers.rb → open_loam/install/templates/migrations/create_open_loam_sso_providers.rb} +15 -12
  138. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_tenants.rb +9 -0
  139. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_translations.rb +15 -0
  140. data/lib/generators/open_loam/install/templates/migrations/create_open_loam_webhook_endpoints.rb +13 -0
  141. data/lib/generators/{loam → open_loam}/install/templates/migrations/create_users.rb +1 -1
  142. data/lib/generators/{loam → open_loam}/install/templates/user.rb +5 -5
  143. data/lib/generators/{loam → open_loam}/primary_key_options.rb +23 -23
  144. data/lib/open-loam.rb +2 -2
  145. data/lib/{loam → open_loam}/attachable.rb +4 -4
  146. data/lib/{loam → open_loam}/auditable.rb +23 -23
  147. data/lib/{loam → open_loam}/auth_throttle.rb +20 -12
  148. data/lib/{loam → open_loam}/base32.rb +1 -1
  149. data/lib/{loam → open_loam}/bulk.rb +7 -7
  150. data/lib/{loam → open_loam}/business_rules/actions.rb +7 -7
  151. data/lib/{loam → open_loam}/business_rules/condition.rb +5 -5
  152. data/lib/{loam → open_loam}/business_rules.rb +19 -19
  153. data/lib/{loam → open_loam}/commentable.rb +6 -6
  154. data/lib/{loam → open_loam}/configs.rb +19 -19
  155. data/lib/{loam → open_loam}/cron.rb +2 -2
  156. data/lib/{loam → open_loam}/csv.rb +2 -2
  157. data/lib/{loam → open_loam}/current.rb +5 -5
  158. data/lib/{loam → open_loam}/custom_field_index.rb +33 -30
  159. data/lib/{loam → open_loam}/custom_fields.rb +17 -17
  160. data/lib/{loam → open_loam}/dashboard.rb +5 -5
  161. data/lib/{loam → open_loam}/dictionaries.rb +12 -12
  162. data/lib/{loam → open_loam}/durable_events.rb +19 -19
  163. data/lib/{loam → open_loam}/encryptable.rb +39 -34
  164. data/lib/{loam → open_loam}/encryption/cipher.rb +3 -3
  165. data/lib/{loam → open_loam}/encryption/key_provider.rb +19 -3
  166. data/lib/{loam → open_loam}/encryption.rb +58 -15
  167. data/lib/open_loam/engine.rb +65 -0
  168. data/lib/{loam → open_loam}/enrichers.rb +5 -5
  169. data/lib/{loam → open_loam}/errors.rb +20 -10
  170. data/lib/{loam → open_loam}/eval.rb +2 -2
  171. data/lib/open_loam/event_log.rb +77 -0
  172. data/lib/{loam → open_loam}/event_stream.rb +14 -14
  173. data/lib/{loam → open_loam}/eventful.rb +12 -12
  174. data/lib/{loam → open_loam}/events.rb +5 -5
  175. data/lib/{loam → open_loam}/export.rb +12 -12
  176. data/lib/{loam → open_loam}/features.rb +15 -15
  177. data/lib/{loam → open_loam}/generated_key.rb +6 -6
  178. data/lib/{loam → open_loam}/import.rb +12 -15
  179. data/lib/{loam → open_loam}/inbound_webhooks.rb +19 -18
  180. data/lib/{loam → open_loam}/lifecycle.rb +54 -25
  181. data/lib/{loam/locales/loam.en.yml → open_loam/locales/open_loam.en.yml} +5 -5
  182. data/lib/{loam → open_loam}/mcp/server.rb +9 -9
  183. data/lib/{loam → open_loam}/mcp.rb +31 -22
  184. data/lib/{loam → open_loam}/notifications.rb +5 -5
  185. data/lib/{loam → open_loam}/open_api.rb +16 -16
  186. data/lib/open_loam/outbound_url.rb +100 -0
  187. data/lib/{loam → open_loam}/overrides.rb +10 -10
  188. data/lib/{loam → open_loam}/pending_actions.rb +9 -9
  189. data/lib/{loam → open_loam}/permissions.rb +8 -8
  190. data/lib/{loam → open_loam}/perspectives.rb +9 -9
  191. data/lib/{loam → open_loam}/policy.rb +21 -8
  192. data/lib/{loam → open_loam}/progress.rb +6 -6
  193. data/lib/{loam → open_loam}/record_locks.rb +9 -9
  194. data/lib/{loam → open_loam}/scheduler.rb +20 -20
  195. data/lib/{loam → open_loam}/search/driver.rb +3 -3
  196. data/lib/{loam → open_loam}/search/like_driver.rb +5 -5
  197. data/lib/{loam → open_loam}/search/token_driver.rb +16 -16
  198. data/lib/{loam → open_loam}/search.rb +5 -5
  199. data/lib/{loam → open_loam}/searchable.rb +22 -22
  200. data/lib/{loam → open_loam}/soft_deletable.rb +10 -10
  201. data/lib/{loam → open_loam}/sso/claims.rb +1 -1
  202. data/lib/{loam → open_loam}/sso/fake_provider.rb +1 -1
  203. data/lib/open_loam/sso/http_client.rb +51 -0
  204. data/lib/{loam → open_loam}/sso/oidc_provider.rb +2 -2
  205. data/lib/{loam → open_loam}/sso.rb +39 -18
  206. data/lib/{loam → open_loam}/telemetry.rb +6 -6
  207. data/lib/{loam → open_loam}/tenant_record.rb +10 -10
  208. data/lib/{loam → open_loam}/test_helpers.rb +4 -4
  209. data/lib/{loam → open_loam}/totp.rb +3 -3
  210. data/lib/{loam → open_loam}/translatable.rb +24 -24
  211. data/lib/{loam → open_loam}/undo.rb +11 -11
  212. data/lib/open_loam/version.rb +3 -0
  213. data/lib/{loam → open_loam}/webhooks.rb +4 -4
  214. data/lib/{loam → open_loam}/widgets.rb +9 -9
  215. data/lib/{loam → open_loam}/workflow.rb +45 -45
  216. data/lib/open_loam.rb +124 -0
  217. data/lib/tasks/open_loam.rake +203 -0
  218. data/lib/tasks/{loam_eval.rake → open_loam_eval.rake} +7 -7
  219. data/lib/tasks/open_loam_mcp.rake +20 -0
  220. metadata +247 -242
  221. data/app/models/loam/api_token.rb +0 -40
  222. data/app/models/loam/dictionary.rb +0 -20
  223. data/app/models/loam/search_token.rb +0 -9
  224. data/app/models/loam/sso_provider.rb +0 -35
  225. data/app/models/loam/tenant.rb +0 -20
  226. data/app/models/loam/webhook_endpoint.rb +0 -26
  227. data/lib/generators/loam/entity/templates/views/edit.html.erb +0 -3
  228. data/lib/generators/loam/entity/templates/views/index.html.erb +0 -90
  229. data/lib/generators/loam/entity/templates/views/new.html.erb +0 -3
  230. data/lib/generators/loam/entity/templates/views/show.html.erb +0 -36
  231. data/lib/generators/loam/install/templates/AGENTS.md +0 -341
  232. data/lib/generators/loam/install/templates/admin/api_tokens_controller.rb +0 -30
  233. data/lib/generators/loam/install/templates/admin/dashboard_controller.rb +0 -10
  234. data/lib/generators/loam/install/templates/admin/history_controller.rb +0 -38
  235. data/lib/generators/loam/install/templates/admin/layout.html.erb +0 -76
  236. data/lib/generators/loam/install/templates/admin/progress_jobs_controller.rb +0 -19
  237. data/lib/generators/loam/install/templates/api_base_controller.rb +0 -90
  238. data/lib/generators/loam/install/templates/import_job.rb +0 -25
  239. data/lib/generators/loam/install/templates/migrations/create_loam_api_tokens.rb +0 -15
  240. data/lib/generators/loam/install/templates/migrations/create_loam_audit_records.rb +0 -14
  241. data/lib/generators/loam/install/templates/migrations/create_loam_comments.rb +0 -13
  242. data/lib/generators/loam/install/templates/migrations/create_loam_custom_field_values.rb +0 -19
  243. data/lib/generators/loam/install/templates/migrations/create_loam_dashboard_widgets.rb +0 -12
  244. data/lib/generators/loam/install/templates/migrations/create_loam_dictionaries.rb +0 -11
  245. data/lib/generators/loam/install/templates/migrations/create_loam_memberships.rb +0 -11
  246. data/lib/generators/loam/install/templates/migrations/create_loam_notifications.rb +0 -15
  247. data/lib/generators/loam/install/templates/migrations/create_loam_record_locks.rb +0 -16
  248. data/lib/generators/loam/install/templates/migrations/create_loam_search_tokens.rb +0 -18
  249. data/lib/generators/loam/install/templates/migrations/create_loam_tenants.rb +0 -9
  250. data/lib/generators/loam/install/templates/migrations/create_loam_translations.rb +0 -15
  251. data/lib/generators/loam/install/templates/migrations/create_loam_webhook_endpoints.rb +0 -13
  252. data/lib/loam/engine.rb +0 -57
  253. data/lib/loam/sso/http_client.rb +0 -42
  254. data/lib/loam/version.rb +0 -3
  255. data/lib/loam.rb +0 -122
  256. data/lib/tasks/loam.rake +0 -171
  257. data/lib/tasks/loam_mcp.rake +0 -20
  258. /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_edit.html.erb +0 -0
  259. /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_index.html.erb +0 -0
  260. /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_new.html.erb +0 -0
  261. /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_edit.html.erb +0 -0
  262. /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_index.html.erb +0 -0
  263. /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_index.html.erb +0 -0
  264. /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_index.html.erb +0 -0
  265. /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_edit.html.erb +0 -0
  266. /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_index.html.erb +0 -0
  267. /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_new.html.erb +0 -0
  268. /data/lib/generators/{loam → open_loam}/install/templates/admin/features_index.html.erb +0 -0
  269. /data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_index.html.erb +0 -0
  270. /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_new.html.erb +0 -0
  271. /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_preview.html.erb +0 -0
  272. /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_summary.html.erb +0 -0
  273. /data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_index.html.erb +0 -0
  274. /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_activated.html.erb +0 -0
  275. /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_new.html.erb +0 -0
  276. /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_show.html.erb +0 -0
  277. /data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_index.html.erb +0 -0
  278. /data/lib/generators/{loam → open_loam}/install/templates/admin/pagination.rb +0 -0
  279. /data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_index.html.erb +0 -0
  280. /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_edit.html.erb +0 -0
  281. /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_new.html.erb +0 -0
  282. /data/lib/generators/{loam → open_loam}/install/templates/admin/search_index.html.erb +0 -0
  283. /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_mfa_challenge.html.erb +0 -0
  284. /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_new.html.erb +0 -0
  285. /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_edit.html.erb +0 -0
  286. /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_new.html.erb +0 -0
  287. /data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_new.html.erb +0 -0
@@ -0,0 +1,203 @@
1
+ namespace :open_loam do
2
+ desc "Re-run every OpenLoam.on_tenant_created callback for every existing tenant (idempotent)"
3
+ task sync: :environment do
4
+ synced = OpenLoam.sync_tenants!
5
+ puts "open_loam:sync — ran #{OpenLoam.tenant_created_callbacks.size} tenant callback(s) across #{synced} tenant(s)."
6
+ end
7
+
8
+ namespace :openapi do
9
+ # Write the OpenAPI 3.1 document + a Markdown rendering to disk, for CI or
10
+ # publishing. Introspection only — no server, no network.
11
+ #
12
+ # bin/rails open_loam:openapi:export
13
+ desc "Export the API's OpenAPI JSON + Markdown to doc/"
14
+ task export: :environment do
15
+ require "json"
16
+ dir = ENV["DIR"].presence || "doc"
17
+ FileUtils.mkdir_p(dir)
18
+ File.write(File.join(dir, "openapi.json"), JSON.pretty_generate(OpenLoam::OpenApi.document))
19
+ File.write(File.join(dir, "openapi.md"), OpenLoam::OpenApi.markdown)
20
+ puts "open_loam:openapi:export — wrote #{dir}/openapi.json and #{dir}/openapi.md."
21
+ end
22
+ end
23
+
24
+ namespace :scheduler do
25
+ # Fire every due recurring job once. Wire to system cron, every minute:
26
+ # * * * * * cd /app && bin/rails open_loam:scheduler:tick
27
+ # The claim is atomic, so running this from several hosts never double-fires
28
+ # a job (Postgres SKIP LOCKED; SQLite serializes the single-process claim).
29
+ desc "Enqueue every due OpenLoam::ScheduledJob (run from cron)"
30
+ task tick: :environment do
31
+ fired = OpenLoam::Scheduler.tick
32
+ puts "open_loam:scheduler:tick — fired #{fired} scheduled job(s)."
33
+ end
34
+ end
35
+
36
+ namespace :index do
37
+ # Rebuild the custom-field read-model index (OpenLoam::CustomFieldIndex) for every
38
+ # entity with custom fields, in every tenant. Run once after enabling it so
39
+ # existing rows are projected; new/updated records index themselves on save.
40
+ #
41
+ # bin/rails open_loam:index:reindex
42
+ desc "Rebuild the custom-field read-model index for every model in every tenant"
43
+ task reindex: :environment do
44
+ Rails.application.eager_load!
45
+ models = OpenLoam::TenantRecord.descendants.select do |model|
46
+ model.name.present? && model.respond_to?(:custom_field_definitions)
47
+ end
48
+
49
+ tenants = 0
50
+ OpenLoam::Tenant.find_each do |tenant|
51
+ OpenLoam.as_tenant(tenant) { models.each { |model| OpenLoam::CustomFieldIndex.reindex(model) } }
52
+ tenants += 1
53
+ end
54
+ puts "open_loam:index:reindex — rebuilt #{models.size} model(s) across #{tenants} tenant(s)."
55
+ end
56
+
57
+ # Report custom-field index coverage (indexed vs expected) per model/field
58
+ # per tenant — the trust signal for whether the index is complete or drifting.
59
+ #
60
+ # bin/rails open_loam:index:coverage
61
+ desc "Report custom-field index coverage per model/field per tenant"
62
+ task coverage: :environment do
63
+ Rails.application.eager_load!
64
+ models = OpenLoam::TenantRecord.descendants.select do |model|
65
+ model.name.present? && model.respond_to?(:custom_field_definitions)
66
+ end
67
+
68
+ OpenLoam::Tenant.find_each do |tenant|
69
+ OpenLoam.as_tenant(tenant) do
70
+ models.each do |model|
71
+ model.custom_field_definitions.find_each do |definition|
72
+ c = OpenLoam::CustomFieldIndex.coverage(model, definition.name)
73
+ flag = c[:complete] ? "ok" : "GAP"
74
+ puts " [#{flag}] #{tenant.slug} #{model.name}.#{definition.name}: #{c[:indexed]}/#{c[:expected]} indexed"
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ namespace :search do
83
+ # Rebuild the active driver's search index for every searchable model in
84
+ # every tenant. Needed once after switching to a driver that keeps an index
85
+ # (OpenLoam::Search::TokenDriver): existing rows have no tokens until reindexed,
86
+ # while new and updated records index themselves on save. A no-op under the
87
+ # default LikeDriver (its reindex does nothing), so it is always safe to run.
88
+ #
89
+ # bin/rails open_loam:search:reindex
90
+ desc "Rebuild the search index for every searchable model in every tenant"
91
+ task reindex: :environment do
92
+ Rails.application.eager_load!
93
+ models = OpenLoam::TenantRecord.descendants.select do |model|
94
+ model.name.present? && model.respond_to?(:open_loam_searchable?) && model.open_loam_searchable?
95
+ end
96
+
97
+ tenants = 0
98
+ OpenLoam::Tenant.find_each do |tenant|
99
+ OpenLoam.as_tenant(tenant) { models.each { |model| OpenLoam::Search.reindex(model) } }
100
+ tenants += 1
101
+ end
102
+ puts "open_loam:search:reindex — rebuilt #{models.size} model(s) across #{tenants} tenant(s) using #{OpenLoam::Search.driver}."
103
+ end
104
+ end
105
+
106
+ namespace :sso do
107
+ # Domain ownership can only be granted from OUTSIDE the tenant: the manager
108
+ # who typed the domain is the party this check exists to constrain. Confirm
109
+ # ownership out of band (DNS TXT, a signed request from the domain's
110
+ # operator, an existing contract) BEFORE running this.
111
+ #
112
+ # bin/rails open_loam:sso:verify_domain[42]
113
+ desc "Mark an SSO provider's domain as proven-owned (operator only)"
114
+ task :verify_domain, %i[provider_id] => :environment do |_task, args|
115
+ provider = OpenLoam::SsoProvider.unscoped.find(args[:provider_id])
116
+ tenant = OpenLoam::Tenant.find(provider.tenant_id)
117
+ OpenLoam.as_tenant(tenant) { provider.verify_domain! }
118
+ puts "open_loam:sso:verify_domain — #{provider.domain} verified for tenant #{tenant.slug} (provider #{provider.id})."
119
+ end
120
+
121
+ desc "Revoke an SSO provider's domain verification"
122
+ task :unverify_domain, %i[provider_id] => :environment do |_task, args|
123
+ provider = OpenLoam::SsoProvider.unscoped.find(args[:provider_id])
124
+ tenant = OpenLoam::Tenant.find(provider.tenant_id)
125
+ OpenLoam.as_tenant(tenant) { provider.update!(domain_verified_at: nil) }
126
+ puts "open_loam:sso:unverify_domain — #{provider.domain} is no longer verified."
127
+ end
128
+
129
+ desc "List SSO providers and their domain-verification state"
130
+ task providers: :environment do
131
+ OpenLoam::SsoProvider.unscoped.order(:domain).each do |provider|
132
+ state = provider.domain_verified? ? "verified #{provider.domain_verified_at.to_fs(:db)}" : "UNVERIFIED"
133
+ puts format("%-6s %-30s tenant=%-6s %s", provider.id, provider.domain, provider.tenant_id, state)
134
+ end
135
+ end
136
+ end
137
+
138
+ namespace :encryption do
139
+ # Rotate a tenant's encrypted data under the current key: read each record's
140
+ # encrypted fields (old key) and re-seal them (new key), one record at a
141
+ # time. The version tag in the stored format means old and new ciphertext
142
+ # coexist, so this can run incrementally without downtime. Each record is an
143
+ # ordinary audited "[encrypted]" update.
144
+ #
145
+ # bin/rails open_loam:encryption:rotate[Customer,42]
146
+ desc "Re-encrypt a model's encrypted fields for one tenant (rotation step)"
147
+ task :rotate, %i[model tenant_id] => :environment do |_task, args|
148
+ model = fetch_encryptable_model(args[:model])
149
+ tenant = OpenLoam::Tenant.find(args[:tenant_id])
150
+
151
+ count = 0
152
+ OpenLoam.as_tenant(tenant) do
153
+ each_record(model) do |record|
154
+ record.open_loam_reencrypt!
155
+ count += 1
156
+ end
157
+ end
158
+ puts "open_loam:encryption:rotate — re-encrypted #{count} #{model.name} record(s) in tenant #{tenant.slug}."
159
+ end
160
+
161
+ # Decrypt and print one tenant's encrypted fields, e.g. for a GDPR data
162
+ # export or a migration. OPERATIONAL CAUTION: this prints plaintext PII to
163
+ # stdout — run it only where that output is safe (never into shared logs or
164
+ # a shell history that syncs), and only for a tenant you are authorized to
165
+ # export.
166
+ #
167
+ # bin/rails open_loam:encryption:decrypt_dump[Customer,42]
168
+ desc "Print decrypted encrypted-field values for one tenant (GDPR export; handle with care)"
169
+ task :decrypt_dump, %i[model tenant_id] => :environment do |_task, args|
170
+ require "json"
171
+ model = fetch_encryptable_model(args[:model])
172
+ tenant = OpenLoam::Tenant.find(args[:tenant_id])
173
+ fields = model.open_loam_encrypted_attributes
174
+
175
+ OpenLoam.as_tenant(tenant) do
176
+ each_record(model) do |record|
177
+ row = { id: record.id }.merge(fields.index_with { |field| record.public_send(field) })
178
+ puts row.to_json
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ # Resolve a model name to a class that actually uses OpenLoam::Encryptable — a typo
186
+ # or a plain model should fail loudly, not silently dump/rotate nothing.
187
+ def fetch_encryptable_model(name)
188
+ # Force the app's classes (and OpenLoam::TenantRecord, required lazily via the
189
+ # active_record on_load hook) to load before we constantize a model name.
190
+ Rails.application.eager_load!
191
+ model = name.to_s.constantize
192
+ unless model.respond_to?(:open_loam_encrypted_attributes) && model.open_loam_encrypted_attributes.any?
193
+ abort "#{name} does not `include OpenLoam::Encryptable` with any `encrypts` fields."
194
+ end
195
+ model
196
+ end
197
+
198
+ # Iterate every record, soft-deleted ones included (a GDPR export must not miss
199
+ # data hidden in the recycle bin), staying inside the current tenant scope.
200
+ def each_record(model, &block)
201
+ scope = model.respond_to?(:with_deleted) ? model.with_deleted : model.all
202
+ scope.find_each(&block)
203
+ end
@@ -1,23 +1,23 @@
1
1
  require "json"
2
2
  require "fileutils"
3
3
 
4
- namespace :loam do
4
+ namespace :open_loam do
5
5
  # Score the app's current test suite as a golden-task eval result and record it
6
- # under ai/benchmark_runs/ (L-303). Run this in a Loam app AFTER an agent (or
6
+ # under ai/benchmark_runs/ (L-303). Run this in a OpenLoam app AFTER an agent (or
7
7
  # you) has implemented a golden task:
8
8
  #
9
- # bin/rails "loam:eval[2]" # task 2, tests only
10
- # bin/rails "loam:eval[2,tenancy_leak:unscoped]" # note an invariant breach
9
+ # bin/rails "open_loam:eval[2]" # task 2, tests only
10
+ # bin/rails "open_loam:eval[2,tenancy_leak:unscoped]" # note an invariant breach
11
11
  #
12
12
  # Exits non-zero if the task did not pass, so it drops straight into CI.
13
- desc "Score the current test suite as a golden-task eval result (loam:eval[task,violation,violation,...])"
13
+ desc "Score the current test suite as a golden-task eval result (open_loam:eval[task,violation,violation,...])"
14
14
  task :eval, [ :task ] => :environment do |_task, args|
15
15
  task_id = args[:task] || "unspecified"
16
16
  violations = args.extras # any positional args after the task id are violations
17
17
 
18
18
  output = `bin/rails test 2>&1`
19
- summary = Loam::Eval.parse_summary(output)
20
- card = Loam::Eval.scorecard(task: task_id, summary: summary, violations: violations)
19
+ summary = OpenLoam::Eval.parse_summary(output)
20
+ card = OpenLoam::Eval.scorecard(task: task_id, summary: summary, violations: violations)
21
21
 
22
22
  dir = Rails.root.join("ai", "benchmark_runs")
23
23
  FileUtils.mkdir_p(dir)
@@ -0,0 +1,20 @@
1
+ require "logger"
2
+
3
+ namespace :open_loam do
4
+ namespace :mcp do
5
+ # Serve the OpenLoam MCP server over stdio. Point an MCP client (Claude Code,
6
+ # Cursor, Codex) at `bin/rails open_loam:mcp:serve` with OPEN_LOAM_MCP_TOKEN set to a
7
+ # OpenLoam API token — the agent then acts as that token's user, in that tenant.
8
+ #
9
+ # stdout carries JSON-RPC only; every log is sent to stderr so it can't
10
+ # corrupt the stream.
11
+ desc "Serve the OpenLoam MCP server over stdio (auth via OPEN_LOAM_MCP_TOKEN)"
12
+ task serve: :environment do
13
+ Rails.logger = Logger.new($stderr)
14
+ ActiveRecord::Base.logger = Rails.logger
15
+ $stdout.sync = true
16
+
17
+ OpenLoam::Mcp::Server.new.run
18
+ end
19
+ end
20
+ end