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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -8
- data/LICENSE +1 -1
- data/README.md +24 -24
- data/app/jobs/{loam → open_loam}/custom_field_reindex_job.rb +6 -6
- data/app/jobs/{loam → open_loam}/event_delivery_job.rb +8 -8
- data/app/jobs/{loam → open_loam}/event_redelivery_sweep_job.rb +4 -4
- data/app/jobs/{loam → open_loam}/webhook_delivery_job.rb +7 -7
- data/app/models/{loam → open_loam}/api_token.rb +7 -7
- data/app/models/{loam → open_loam}/audit_record.rb +3 -3
- data/app/models/{loam → open_loam}/auth_attempt.rb +5 -5
- data/app/models/{loam → open_loam}/business_rule.rb +10 -10
- data/app/models/{loam → open_loam}/business_rule_run.rb +5 -5
- data/app/models/{loam → open_loam}/comment.rb +9 -9
- data/app/models/{loam → open_loam}/config.rb +7 -7
- data/app/models/{loam → open_loam}/custom_field_value.rb +5 -5
- data/app/models/{loam → open_loam}/dashboard_widget.rb +5 -5
- data/app/models/open_loam/dictionary.rb +20 -0
- data/app/models/{loam → open_loam}/dictionary_entry.rb +7 -7
- data/app/models/{loam → open_loam}/event_delivery.rb +4 -4
- data/app/models/{loam → open_loam}/field_definition.rb +8 -8
- data/app/models/{loam → open_loam}/inbound_webhook_delivery.rb +4 -4
- data/app/models/{loam → open_loam}/inbound_webhook_source.rb +13 -13
- data/app/models/{loam → open_loam}/membership.rb +6 -6
- data/app/models/{loam → open_loam}/mfa_credential.rb +8 -8
- data/app/models/{loam → open_loam}/notification.rb +10 -10
- data/app/models/{loam → open_loam}/pending_action.rb +23 -23
- data/app/models/{loam → open_loam}/perspective.rb +5 -5
- data/app/models/{loam → open_loam}/progress_job.rb +7 -7
- data/app/models/{loam → open_loam}/record_lock.rb +5 -5
- data/app/models/{loam → open_loam}/scheduled_job.rb +7 -7
- data/app/models/open_loam/search_token.rb +9 -0
- data/app/models/{loam → open_loam}/sso_identity.rb +4 -4
- data/app/models/{loam → open_loam}/sso_provider.rb +8 -8
- data/app/models/open_loam/tenant.rb +20 -0
- data/app/models/{loam → open_loam}/translation.rb +5 -5
- data/app/models/{loam → open_loam}/webhook_endpoint.rb +6 -6
- data/app/views/{loam → open_loam}/attachments/_attachments.html.erb +1 -1
- data/app/views/{loam → open_loam}/comments/_comments.html.erb +1 -1
- data/app/views/{loam → open_loam}/custom_fields/_fields.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/entity/entity_generator.rb +9 -9
- data/lib/generators/{loam → open_loam}/entity/templates/api_controller.rb +1 -1
- data/lib/generators/{loam → open_loam}/entity/templates/controller.rb +21 -21
- data/lib/generators/{loam → open_loam}/entity/templates/entity_test.rb +12 -12
- data/lib/generators/{loam → open_loam}/entity/templates/migration.rb +5 -5
- data/lib/generators/{loam → open_loam}/entity/templates/model.rb +10 -10
- data/lib/generators/{loam → open_loam}/entity/templates/policy.rb +1 -1
- data/lib/generators/{loam → open_loam}/entity/templates/views/_form.html.erb +4 -4
- data/lib/generators/{loam → open_loam}/entity/templates/views/deleted.html.erb +7 -7
- data/lib/generators/open_loam/entity/templates/views/edit.html.erb +3 -0
- data/lib/generators/open_loam/entity/templates/views/index.html.erb +90 -0
- data/lib/generators/open_loam/entity/templates/views/new.html.erb +3 -0
- data/lib/generators/open_loam/entity/templates/views/show.html.erb +36 -0
- data/lib/generators/{loam → open_loam}/install/install_generator.rb +47 -47
- data/lib/generators/open_loam/install/templates/AGENTS.md +341 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_controller.rb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/api_tokens_controller.rb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/base_controller.rb +38 -38
- data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_form.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/comments_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/admin/configs_controller.rb +9 -9
- data/lib/generators/open_loam/install/templates/admin/dashboard_controller.rb +10 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_form.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/dictionary_entries_controller.rb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/events_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/features_controller.rb +9 -9
- data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_new.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/history_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/history_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/imports_controller.rb +12 -12
- data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_controller.rb +6 -6
- data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_new.html.erb +2 -2
- data/lib/generators/open_loam/install/templates/admin/layout.html.erb +76 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_controller.rb +6 -6
- data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_controller.rb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_controller.rb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_index.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_controller.rb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_index.html.erb +1 -1
- data/lib/generators/open_loam/install/templates/admin/progress_jobs_controller.rb +19 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/progress_jobs_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/record_locks_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_form.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/search_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_controller.rb +32 -32
- data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_controller.rb +6 -6
- data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_form.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_new.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/translations_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/translations_index.html.erb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin.css +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/api_base_controller.rb +15 -15
- data/lib/generators/{loam → open_loam}/install/templates/guardrails_test.rb +17 -17
- data/lib/generators/{loam → open_loam}/install/templates/import_job.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/inbound_webhooks_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/initializer.rb +74 -74
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_api_tokens.rb +15 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_audit_records.rb +14 -0
- 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
- 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
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_comments.rb +13 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_configs.rb → open_loam/install/templates/migrations/create_open_loam_configs.rb} +7 -7
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_custom_field_values.rb +19 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dashboard_widgets.rb +12 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dictionaries.rb +11 -0
- 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
- 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
- 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
- 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
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_memberships.rb +11 -0
- 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
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_notifications.rb +15 -0
- 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
- data/lib/generators/{loam/install/templates/migrations/create_loam_perspectives.rb → open_loam/install/templates/migrations/create_open_loam_perspectives.rb} +5 -5
- 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
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_record_locks.rb +16 -0
- 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
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_search_tokens.rb +18 -0
- 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
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_tenants.rb +9 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_translations.rb +15 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_webhook_endpoints.rb +13 -0
- data/lib/generators/{loam → open_loam}/install/templates/migrations/create_users.rb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/user.rb +5 -5
- data/lib/generators/{loam → open_loam}/primary_key_options.rb +23 -23
- data/lib/open-loam.rb +2 -2
- data/lib/{loam → open_loam}/attachable.rb +4 -4
- data/lib/{loam → open_loam}/auditable.rb +23 -23
- data/lib/{loam → open_loam}/auth_throttle.rb +10 -10
- data/lib/{loam → open_loam}/base32.rb +1 -1
- data/lib/{loam → open_loam}/bulk.rb +7 -7
- data/lib/{loam → open_loam}/business_rules/actions.rb +7 -7
- data/lib/{loam → open_loam}/business_rules/condition.rb +5 -5
- data/lib/{loam → open_loam}/business_rules.rb +19 -19
- data/lib/{loam → open_loam}/commentable.rb +6 -6
- data/lib/{loam → open_loam}/configs.rb +19 -19
- data/lib/{loam → open_loam}/cron.rb +2 -2
- data/lib/{loam → open_loam}/csv.rb +2 -2
- data/lib/{loam → open_loam}/current.rb +5 -5
- data/lib/{loam → open_loam}/custom_field_index.rb +23 -23
- data/lib/{loam → open_loam}/custom_fields.rb +17 -17
- data/lib/{loam → open_loam}/dashboard.rb +5 -5
- data/lib/{loam → open_loam}/dictionaries.rb +12 -12
- data/lib/{loam → open_loam}/durable_events.rb +19 -19
- data/lib/{loam → open_loam}/encryptable.rb +33 -33
- data/lib/{loam → open_loam}/encryption/cipher.rb +3 -3
- data/lib/{loam → open_loam}/encryption/key_provider.rb +3 -3
- data/lib/{loam → open_loam}/encryption.rb +11 -11
- data/lib/open_loam/engine.rb +57 -0
- data/lib/{loam → open_loam}/enrichers.rb +5 -5
- data/lib/{loam → open_loam}/errors.rb +10 -10
- data/lib/{loam → open_loam}/eval.rb +2 -2
- data/lib/{loam → open_loam}/event_stream.rb +14 -14
- data/lib/{loam → open_loam}/eventful.rb +12 -12
- data/lib/{loam → open_loam}/events.rb +5 -5
- data/lib/{loam → open_loam}/export.rb +8 -8
- data/lib/{loam → open_loam}/features.rb +15 -15
- data/lib/{loam → open_loam}/generated_key.rb +6 -6
- data/lib/{loam → open_loam}/import.rb +12 -12
- data/lib/{loam → open_loam}/inbound_webhooks.rb +7 -7
- data/lib/{loam → open_loam}/lifecycle.rb +25 -25
- data/lib/{loam/locales/loam.en.yml → open_loam/locales/open_loam.en.yml} +5 -5
- data/lib/{loam → open_loam}/mcp/server.rb +9 -9
- data/lib/{loam → open_loam}/mcp.rb +21 -21
- data/lib/{loam → open_loam}/notifications.rb +5 -5
- data/lib/{loam → open_loam}/open_api.rb +16 -16
- data/lib/{loam → open_loam}/overrides.rb +10 -10
- data/lib/{loam → open_loam}/pending_actions.rb +9 -9
- data/lib/{loam → open_loam}/permissions.rb +8 -8
- data/lib/{loam → open_loam}/perspectives.rb +9 -9
- data/lib/{loam → open_loam}/policy.rb +6 -6
- data/lib/{loam → open_loam}/progress.rb +6 -6
- data/lib/{loam → open_loam}/record_locks.rb +9 -9
- data/lib/{loam → open_loam}/scheduler.rb +20 -20
- data/lib/{loam → open_loam}/search/driver.rb +3 -3
- data/lib/{loam → open_loam}/search/like_driver.rb +5 -5
- data/lib/{loam → open_loam}/search/token_driver.rb +15 -15
- data/lib/{loam → open_loam}/search.rb +5 -5
- data/lib/{loam → open_loam}/searchable.rb +22 -22
- data/lib/{loam → open_loam}/soft_deletable.rb +10 -10
- data/lib/{loam → open_loam}/sso/claims.rb +1 -1
- data/lib/{loam → open_loam}/sso/fake_provider.rb +1 -1
- data/lib/{loam → open_loam}/sso/http_client.rb +3 -3
- data/lib/{loam → open_loam}/sso/oidc_provider.rb +2 -2
- data/lib/{loam → open_loam}/sso.rb +17 -17
- data/lib/{loam → open_loam}/telemetry.rb +6 -6
- data/lib/{loam → open_loam}/tenant_record.rb +10 -10
- data/lib/{loam → open_loam}/test_helpers.rb +4 -4
- data/lib/{loam → open_loam}/totp.rb +3 -3
- data/lib/{loam → open_loam}/translatable.rb +24 -24
- data/lib/{loam → open_loam}/undo.rb +11 -11
- data/lib/open_loam/version.rb +3 -0
- data/lib/{loam → open_loam}/webhooks.rb +4 -4
- data/lib/{loam → open_loam}/widgets.rb +9 -9
- data/lib/{loam → open_loam}/workflow.rb +45 -45
- data/lib/open_loam.rb +122 -0
- data/lib/tasks/{loam.rake → open_loam.rake} +43 -43
- data/lib/tasks/{loam_eval.rake → open_loam_eval.rake} +7 -7
- data/lib/tasks/open_loam_mcp.rake +20 -0
- metadata +242 -242
- data/app/models/loam/dictionary.rb +0 -20
- data/app/models/loam/search_token.rb +0 -9
- data/app/models/loam/tenant.rb +0 -20
- data/lib/generators/loam/entity/templates/views/edit.html.erb +0 -3
- data/lib/generators/loam/entity/templates/views/index.html.erb +0 -90
- data/lib/generators/loam/entity/templates/views/new.html.erb +0 -3
- data/lib/generators/loam/entity/templates/views/show.html.erb +0 -36
- data/lib/generators/loam/install/templates/AGENTS.md +0 -341
- data/lib/generators/loam/install/templates/admin/dashboard_controller.rb +0 -10
- data/lib/generators/loam/install/templates/admin/layout.html.erb +0 -76
- data/lib/generators/loam/install/templates/admin/progress_jobs_controller.rb +0 -19
- data/lib/generators/loam/install/templates/migrations/create_loam_api_tokens.rb +0 -15
- data/lib/generators/loam/install/templates/migrations/create_loam_audit_records.rb +0 -14
- data/lib/generators/loam/install/templates/migrations/create_loam_comments.rb +0 -13
- data/lib/generators/loam/install/templates/migrations/create_loam_custom_field_values.rb +0 -19
- data/lib/generators/loam/install/templates/migrations/create_loam_dashboard_widgets.rb +0 -12
- data/lib/generators/loam/install/templates/migrations/create_loam_dictionaries.rb +0 -11
- data/lib/generators/loam/install/templates/migrations/create_loam_memberships.rb +0 -11
- data/lib/generators/loam/install/templates/migrations/create_loam_notifications.rb +0 -15
- data/lib/generators/loam/install/templates/migrations/create_loam_record_locks.rb +0 -16
- data/lib/generators/loam/install/templates/migrations/create_loam_search_tokens.rb +0 -18
- data/lib/generators/loam/install/templates/migrations/create_loam_tenants.rb +0 -9
- data/lib/generators/loam/install/templates/migrations/create_loam_translations.rb +0 -15
- data/lib/generators/loam/install/templates/migrations/create_loam_webhook_endpoints.rb +0 -13
- data/lib/loam/engine.rb +0 -57
- data/lib/loam/version.rb +0 -3
- data/lib/loam.rb +0 -122
- data/lib/tasks/loam_mcp.rake +0 -20
- /data/lib/generators/{loam → open_loam}/install/templates/admin/api_tokens_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/features_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_preview.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_summary.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_activated.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_show.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/pagination.rb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/search_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_mfa_challenge.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_new.html.erb +0 -0
|
@@ -1,214 +1,214 @@
|
|
|
1
|
-
#
|
|
1
|
+
# OpenLoam configuration, tenant lifecycle hooks, and domain event subscriptions.
|
|
2
2
|
|
|
3
|
-
# Master key for field encryption at rest (
|
|
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
|
|
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
|
-
#
|
|
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
|
|
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 —
|
|
15
|
+
# own seeding/admin code — OpenLoam does not create memberships for you, because
|
|
16
16
|
# who gets which role is business logic.
|
|
17
|
-
|
|
17
|
+
OpenLoam.default_roles = %w[manager employee]
|
|
18
18
|
|
|
19
|
-
# Locales that CONTENT translations (
|
|
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.
|
|
23
|
-
# a `
|
|
24
|
-
# I18n.locale too, so add `config/locales/
|
|
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
|
-
|
|
26
|
+
OpenLoam.locales = %w[en]
|
|
27
27
|
|
|
28
|
-
# Observability (
|
|
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 ("
|
|
30
|
+
# emit ActiveSupport::Notifications events ("open_loam.span.*") — subscribe to those,
|
|
31
31
|
# or plug a real tracer in here:
|
|
32
32
|
#
|
|
33
|
-
#
|
|
34
|
-
# OpenTelemetry.tracer_provider.tracer("
|
|
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 (
|
|
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 `
|
|
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 (
|
|
41
|
+
# Orthogonal to roles (OpenLoam::Membership) and field-level policies (OpenLoam::Policy).
|
|
42
42
|
#
|
|
43
|
-
#
|
|
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 (
|
|
50
|
-
# one of
|
|
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
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
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
|
|
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 (
|
|
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
|
-
|
|
66
|
+
OpenLoam.broadcast_events = [ "open_loam.notification.", "open_loam.progress." ]
|
|
67
67
|
|
|
68
|
-
# Response enrichers (
|
|
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
|
-
#
|
|
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 (
|
|
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
|
|
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
|
|
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
|
-
#
|
|
87
|
+
# OpenLoam::Search.driver = OpenLoam::Search::TokenDriver
|
|
88
88
|
|
|
89
|
-
# Custom-field read-model index (
|
|
90
|
-
# custom field is index-backed (a typed projection in
|
|
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
|
|
93
|
-
# `
|
|
94
|
-
# `
|
|
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 (
|
|
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
|
|
102
|
-
# be set (same key as the rest of
|
|
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
|
-
#
|
|
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 (
|
|
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
|
|
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
|
-
#
|
|
114
|
+
# OpenLoam::Configs.set("security.mfa_required_roles", ["manager"], scope: :global)
|
|
115
115
|
#
|
|
116
|
-
# Auth rate-limiting / lockout (
|
|
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
|
|
118
|
+
# Tune via OpenLoam::Configs (global or per-tenant):
|
|
119
119
|
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
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 (
|
|
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
|
-
#
|
|
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: `
|
|
135
|
+
# global row: `OpenLoam::Configs.set("billing.currency", "EUR", scope: :global)`.
|
|
136
136
|
|
|
137
|
-
# Feature flags (
|
|
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
|
-
#
|
|
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
|
-
# `
|
|
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
|
-
|
|
152
|
+
OpenLoam.on_tenant_created do |tenant|
|
|
153
153
|
# Seed roles/defaults for a new tenant here. MUST be idempotent —
|
|
154
|
-
# `bin/rails
|
|
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
|
-
#
|
|
157
|
+
# OpenLoam.as_tenant(tenant), so tenant-scoped writes need no extra ceremony.
|
|
158
158
|
#
|
|
159
|
-
# Baseline managed lookup lists (
|
|
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 =
|
|
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
|
|
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
|
-
|
|
169
|
+
OpenLoam::Scheduler.sync_tenant(tenant)
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
-
# Recurring jobs (
|
|
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
|
|
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
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
200
|
-
# Rails.logger.info("[
|
|
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
|
-
#
|
|
208
|
-
#
|
|
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 (
|
|
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
|
|
1
|
+
class CreateOpenLoamAuthAttempts < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
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 :
|
|
9
|
+
add_index :open_loam_auth_attempts, %i[identifier created_at]
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
class
|
|
1
|
+
class CreateOpenLoamBusinessRules < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
4
|
-
t.references :tenant, null: false, foreign_key: { to_table: :
|
|
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 (
|
|
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 :
|
|
14
|
+
add_index :open_loam_business_rules, %i[tenant_id active]
|
|
15
15
|
|
|
16
|
-
create_table :
|
|
17
|
-
t.references :tenant, null: false, foreign_key: { to_table: :
|
|
18
|
-
t.references :business_rule, null: false, foreign_key: { to_table: :
|
|
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.<%=
|
|
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 :
|
|
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
|
|
1
|
+
class CreateOpenLoamConfigs < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
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: :
|
|
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 :
|
|
16
|
-
name: "
|
|
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 :
|
|
19
|
-
name: "
|
|
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
|
data/lib/generators/open_loam/install/templates/migrations/create_open_loam_custom_field_values.rb
ADDED
|
@@ -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
|
data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dashboard_widgets.rb
ADDED
|
@@ -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
|
|
1
|
+
class CreateOpenLoamDictionaryEntries < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
4
|
-
t.references :tenant, null: false, foreign_key: { to_table: :
|
|
5
|
-
t.references :dictionary, null: false, foreign_key: { to_table: :
|
|
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 :
|
|
16
|
-
add_index :
|
|
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
|
|
1
|
+
class CreateOpenLoamEventDeliveries < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
4
|
-
t.references :tenant, null: false, foreign_key: { to_table: :
|
|
5
|
-
t.string :subscriber_key, null: false # a registered
|
|
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 :
|
|
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
|
|
1
|
+
class CreateOpenLoamFieldDefinitions < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
4
|
-
t.references :tenant, null: false, foreign_key: { to_table: :
|
|
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 :
|
|
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
|
|
1
|
+
class CreateOpenLoamInboundWebhooks < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
4
|
-
t.references :tenant, null: false, foreign_key: { to_table: :
|
|
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-
|
|
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 :
|
|
16
|
+
add_index :open_loam_inbound_webhook_sources, :token, unique: true
|
|
17
17
|
|
|
18
|
-
create_table :
|
|
19
|
-
t.references :tenant, null: false, foreign_key: { to_table: :
|
|
20
|
-
t.references :source, null: false, foreign_key: { to_table: :
|
|
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 :
|
|
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
|
|
1
|
+
class CreateOpenLoamMfaCredentials < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :
|
|
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 }<%=
|
|
6
|
-
t.text :totp_secret # encrypted at rest, user-scoped (
|
|
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
|