rails_ai_admin 0.1.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 (193) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +458 -0
  3. data/LICENSE +21 -0
  4. data/README.md +292 -0
  5. data/SECURITY.md +14 -0
  6. data/THIRD_PARTY_NOTICES.md +19 -0
  7. data/app/assets/builds/rails_ai_admin.LICENSE.txt +55 -0
  8. data/app/assets/builds/rails_ai_admin.css +345 -0
  9. data/app/assets/builds/rails_ai_admin.js +33 -0
  10. data/app/controllers/rails_ai_admin/application_controller.rb +255 -0
  11. data/app/controllers/rails_ai_admin/assistant_controller.rb +164 -0
  12. data/app/controllers/rails_ai_admin/audit_controller.rb +16 -0
  13. data/app/controllers/rails_ai_admin/collection_jobs_controller.rb +33 -0
  14. data/app/controllers/rails_ai_admin/collection_operations_controller.rb +79 -0
  15. data/app/controllers/rails_ai_admin/custom_controller.rb +26 -0
  16. data/app/controllers/rails_ai_admin/dashboard_controller.rb +17 -0
  17. data/app/controllers/rails_ai_admin/exports_controller.rb +31 -0
  18. data/app/controllers/rails_ai_admin/files_controller.rb +37 -0
  19. data/app/controllers/rails_ai_admin/imports_controller.rb +41 -0
  20. data/app/controllers/rails_ai_admin/mcp_controller.rb +81 -0
  21. data/app/controllers/rails_ai_admin/mcp_tokens_controller.rb +45 -0
  22. data/app/controllers/rails_ai_admin/operations_controller.rb +105 -0
  23. data/app/controllers/rails_ai_admin/references_controller.rb +16 -0
  24. data/app/controllers/rails_ai_admin/resources_controller.rb +290 -0
  25. data/app/controllers/rails_ai_admin/search_controller.rb +39 -0
  26. data/app/controllers/rails_ai_admin/selections_controller.rb +95 -0
  27. data/app/controllers/rails_ai_admin/surfaces_controller.rb +122 -0
  28. data/app/helpers/rails_ai_admin/dashboard_helper.rb +28 -0
  29. data/app/helpers/rails_ai_admin/fields_helper.rb +242 -0
  30. data/app/helpers/rails_ai_admin/filters_helper.rb +40 -0
  31. data/app/helpers/rails_ai_admin/history_helper.rb +36 -0
  32. data/app/helpers/rails_ai_admin/navigation_helper.rb +54 -0
  33. data/app/helpers/rails_ai_admin/tool_views_helper.rb +48 -0
  34. data/app/jobs/rails_ai_admin/assistant_turn_job.rb +15 -0
  35. data/app/jobs/rails_ai_admin/collections/execution_job.rb +12 -0
  36. data/app/jobs/rails_ai_admin/outbox/delivery_job.rb +13 -0
  37. data/app/models/rails_ai_admin/application_record.rb +8 -0
  38. data/app/models/rails_ai_admin/audit_event.rb +12 -0
  39. data/app/models/rails_ai_admin/batch_item.rb +8 -0
  40. data/app/models/rails_ai_admin/operation_run.rb +20 -0
  41. data/app/models/rails_ai_admin/selection.rb +9 -0
  42. data/app/models/rails_ai_admin/selection_item.rb +9 -0
  43. data/app/models/rails_ai_admin/work_item.rb +18 -0
  44. data/app/views/layouts/rails_ai_admin/application.html.erb +49 -0
  45. data/app/views/layouts/rails_ai_admin/frame.html.erb +5 -0
  46. data/app/views/layouts/rails_ai_admin/status.html.erb +13 -0
  47. data/app/views/rails_ai_admin/assistant/_ask.html.erb +16 -0
  48. data/app/views/rails_ai_admin/assistant/_transcript.html.erb +45 -0
  49. data/app/views/rails_ai_admin/assistant/frame.html.erb +1 -0
  50. data/app/views/rails_ai_admin/assistant/index.html.erb +14 -0
  51. data/app/views/rails_ai_admin/assistant/show.html.erb +44 -0
  52. data/app/views/rails_ai_admin/audit/index.html.erb +40 -0
  53. data/app/views/rails_ai_admin/collection_jobs/index.html.erb +5 -0
  54. data/app/views/rails_ai_admin/collection_jobs/show.html.erb +24 -0
  55. data/app/views/rails_ai_admin/collection_operations/confirmation.html.erb +25 -0
  56. data/app/views/rails_ai_admin/collection_operations/failure.html.erb +10 -0
  57. data/app/views/rails_ai_admin/collection_operations/new.html.erb +11 -0
  58. data/app/views/rails_ai_admin/dashboard/index.html.erb +33 -0
  59. data/app/views/rails_ai_admin/fields/_index.html.erb +1 -0
  60. data/app/views/rails_ai_admin/fields/_input.html.erb +21 -0
  61. data/app/views/rails_ai_admin/fields/_reference.html.erb +1 -0
  62. data/app/views/rails_ai_admin/fields/_reference_picker.html.erb +14 -0
  63. data/app/views/rails_ai_admin/fields/_row.html.erb +27 -0
  64. data/app/views/rails_ai_admin/fields/_show.html.erb +1 -0
  65. data/app/views/rails_ai_admin/imports/new.html.erb +34 -0
  66. data/app/views/rails_ai_admin/mcp_tokens/index.html.erb +33 -0
  67. data/app/views/rails_ai_admin/operations/confirmation.html.erb +32 -0
  68. data/app/views/rails_ai_admin/operations/failure.html.erb +5 -0
  69. data/app/views/rails_ai_admin/operations/form.html.erb +13 -0
  70. data/app/views/rails_ai_admin/resources/_associations.html.erb +12 -0
  71. data/app/views/rails_ai_admin/resources/_errors.html.erb +14 -0
  72. data/app/views/rails_ai_admin/resources/_recovery.html.erb +5 -0
  73. data/app/views/rails_ai_admin/resources/confirm_destroy.html.erb +11 -0
  74. data/app/views/rails_ai_admin/resources/edit.html.erb +1 -0
  75. data/app/views/rails_ai_admin/resources/form.html.erb +16 -0
  76. data/app/views/rails_ai_admin/resources/history.html.erb +27 -0
  77. data/app/views/rails_ai_admin/resources/index.html.erb +88 -0
  78. data/app/views/rails_ai_admin/resources/new.html.erb +1 -0
  79. data/app/views/rails_ai_admin/resources/show.html.erb +12 -0
  80. data/app/views/rails_ai_admin/search/index.html.erb +20 -0
  81. data/app/views/rails_ai_admin/selections/confirm_destroy.html.erb +13 -0
  82. data/app/views/rails_ai_admin/selections/destroyed.html.erb +15 -0
  83. data/app/views/rails_ai_admin/selections/show.html.erb +19 -0
  84. data/app/views/rails_ai_admin/shared/_input_fields.html.erb +23 -0
  85. data/app/views/rails_ai_admin/shared/_navigation.html.erb +8 -0
  86. data/app/views/rails_ai_admin/shared/_session.html.erb +5 -0
  87. data/app/views/rails_ai_admin/statuses/show.html.erb +4 -0
  88. data/app/views/rails_ai_admin/surfaces/_operation_review.html.erb +43 -0
  89. data/app/views/rails_ai_admin/surfaces/show.html.erb +4 -0
  90. data/config/locales/en.yml +549 -0
  91. data/config/routes.rb +64 -0
  92. data/db/assistant_migrate/20261103000001_create_rails_ai_admin_assistant.rb +138 -0
  93. data/db/assistant_migrate/20261112000001_upgrade_rails_ai_admin_assistant_to_ruby_llm_2_2.rb +102 -0
  94. data/db/assistant_migrate/20261114000001_add_streaming_and_access_tokens_to_rails_ai_admin_assistant.rb +29 -0
  95. data/db/migrate/20261029000001_create_rails_ai_admin_execution_tables.rb +35 -0
  96. data/db/migrate/20261029000002_add_callback_warning_to_rails_ai_admin_runs.rb +7 -0
  97. data/db/migrate/20261030000003_create_rails_ai_admin_work_items.rb +26 -0
  98. data/db/migrate/20261030000004_create_rails_ai_admin_selections.rb +28 -0
  99. data/db/migrate/20261030000005_create_rails_ai_admin_collection_runs.rb +41 -0
  100. data/db/migrate/20261113000001_add_record_index_to_rails_ai_admin_audit_events.rb +8 -0
  101. data/lib/generators/rails_ai_admin/assistant/assistant_generator.rb +25 -0
  102. data/lib/generators/rails_ai_admin/assistant/templates/admin_assistant.rb +18 -0
  103. data/lib/generators/rails_ai_admin/engine_migrations.rb +42 -0
  104. data/lib/generators/rails_ai_admin/install/engine_mounts.rb +19 -0
  105. data/lib/generators/rails_ai_admin/install/install_generator.rb +53 -0
  106. data/lib/generators/rails_ai_admin/install/templates/access_test.rb +17 -0
  107. data/lib/generators/rails_ai_admin/install/templates/admin_context.rb +25 -0
  108. data/lib/generators/rails_ai_admin/install/templates/admin_policy_adapter.rb +28 -0
  109. data/lib/generators/rails_ai_admin/install/templates/example_admin.rb +10 -0
  110. data/lib/generators/rails_ai_admin/install/templates/initializer.rb +7 -0
  111. data/lib/generators/rails_ai_admin/override/override_generator.rb +46 -0
  112. data/lib/generators/rails_ai_admin/resource/resource_generator.rb +88 -0
  113. data/lib/rails_ai_admin/assistant/continuation.rb +33 -0
  114. data/lib/rails_ai_admin/assistant/coordinator.rb +306 -0
  115. data/lib/rails_ai_admin/assistant/records.rb +71 -0
  116. data/lib/rails_ai_admin/assistant/runtime.rb +49 -0
  117. data/lib/rails_ai_admin/assistant/tools.rb +477 -0
  118. data/lib/rails_ai_admin/assistant/transcript.rb +140 -0
  119. data/lib/rails_ai_admin/assistant.rb +50 -0
  120. data/lib/rails_ai_admin/authorization/access.rb +296 -0
  121. data/lib/rails_ai_admin/authorization/adapter.rb +92 -0
  122. data/lib/rails_ai_admin/authorization/pundit_adapter.rb +195 -0
  123. data/lib/rails_ai_admin/collections/claim.rb +91 -0
  124. data/lib/rails_ai_admin/collections/contract.rb +113 -0
  125. data/lib/rails_ai_admin/collections/dispatcher.rb +126 -0
  126. data/lib/rails_ai_admin/collections/queries.rb +79 -0
  127. data/lib/rails_ai_admin/collections/result.rb +15 -0
  128. data/lib/rails_ai_admin/collections/runner.rb +208 -0
  129. data/lib/rails_ai_admin/configuration.rb +178 -0
  130. data/lib/rails_ai_admin/context.rb +29 -0
  131. data/lib/rails_ai_admin/doctor.rb +301 -0
  132. data/lib/rails_ai_admin/engine.rb +24 -0
  133. data/lib/rails_ai_admin/error.rb +16 -0
  134. data/lib/rails_ai_admin/field.rb +625 -0
  135. data/lib/rails_ai_admin/fields/association.rb +188 -0
  136. data/lib/rails_ai_admin/fields/computation.rb +43 -0
  137. data/lib/rails_ai_admin/fields/dependency_graph.rb +45 -0
  138. data/lib/rails_ai_admin/fields/file_value.rb +23 -0
  139. data/lib/rails_ai_admin/fields/hook_signatures.rb +18 -0
  140. data/lib/rails_ai_admin/fields/projection.rb +78 -0
  141. data/lib/rails_ai_admin/fields/registry.rb +48 -0
  142. data/lib/rails_ai_admin/fields/scalar_schema.rb +49 -0
  143. data/lib/rails_ai_admin/fields/type.rb +50 -0
  144. data/lib/rails_ai_admin/forms/plan.rb +90 -0
  145. data/lib/rails_ai_admin/input_schema.rb +76 -0
  146. data/lib/rails_ai_admin/integrations/propose_operation.rb +150 -0
  147. data/lib/rails_ai_admin/integrations/tool_views.rb +367 -0
  148. data/lib/rails_ai_admin/mcp.rb +130 -0
  149. data/lib/rails_ai_admin/navigation/list_state.rb +194 -0
  150. data/lib/rails_ai_admin/navigation/menu.rb +31 -0
  151. data/lib/rails_ai_admin/navigation/settings.rb +28 -0
  152. data/lib/rails_ai_admin/operation.rb +120 -0
  153. data/lib/rails_ai_admin/operations/default_handlers.rb +17 -0
  154. data/lib/rails_ai_admin/operations/execution_context.rb +38 -0
  155. data/lib/rails_ai_admin/operations/form_intent.rb +69 -0
  156. data/lib/rails_ai_admin/operations/registry.rb +80 -0
  157. data/lib/rails_ai_admin/operations/result.rb +21 -0
  158. data/lib/rails_ai_admin/operations/runner.rb +633 -0
  159. data/lib/rails_ai_admin/operations/runner_fingerprint.rb +12 -0
  160. data/lib/rails_ai_admin/outbox/delivery_context.rb +51 -0
  161. data/lib/rails_ai_admin/outbox/dispatcher.rb +189 -0
  162. data/lib/rails_ai_admin/outbox/registry.rb +36 -0
  163. data/lib/rails_ai_admin/outbox/request_digest.rb +42 -0
  164. data/lib/rails_ai_admin/outbox/writer.rb +43 -0
  165. data/lib/rails_ai_admin/presentation/association_panel.rb +90 -0
  166. data/lib/rails_ai_admin/presentation/audit_log.rb +63 -0
  167. data/lib/rails_ai_admin/presentation/csv_export.rb +85 -0
  168. data/lib/rails_ai_admin/presentation/csv_import.rb +142 -0
  169. data/lib/rails_ai_admin/presentation/dashboard.rb +122 -0
  170. data/lib/rails_ai_admin/presentation/history.rb +46 -0
  171. data/lib/rails_ai_admin/presentation/index_settings.rb +77 -0
  172. data/lib/rails_ai_admin/presentation/outcomes.rb +44 -0
  173. data/lib/rails_ai_admin/presentation/status.rb +40 -0
  174. data/lib/rails_ai_admin/prune.rb +61 -0
  175. data/lib/rails_ai_admin/queries/list.rb +162 -0
  176. data/lib/rails_ai_admin/queries/named_scope.rb +65 -0
  177. data/lib/rails_ai_admin/record_version.rb +40 -0
  178. data/lib/rails_ai_admin/registry.rb +45 -0
  179. data/lib/rails_ai_admin/request_log_filter.rb +24 -0
  180. data/lib/rails_ai_admin/resource.rb +249 -0
  181. data/lib/rails_ai_admin/resource_identity.rb +15 -0
  182. data/lib/rails_ai_admin/schema_suggestions.rb +105 -0
  183. data/lib/rails_ai_admin/selections/builder.rb +162 -0
  184. data/lib/rails_ai_admin/templates/catalog.rb +84 -0
  185. data/lib/rails_ai_admin/templates/inspector.rb +94 -0
  186. data/lib/rails_ai_admin/templates/metadata.rb +48 -0
  187. data/lib/rails_ai_admin/templates/safe_paths.rb +30 -0
  188. data/lib/rails_ai_admin/test_kit.rb +103 -0
  189. data/lib/rails_ai_admin/version.rb +5 -0
  190. data/lib/rails_ai_admin/work.rb +48 -0
  191. data/lib/rails_ai_admin.rb +112 -0
  192. data/lib/tasks/rails_ai_admin.rake +58 -0
  193. metadata +328 -0
data/README.md ADDED
@@ -0,0 +1,292 @@
1
+ # Rails AI Admin
2
+
3
+ A self-hosted Rails admin engine with explicitly registered resources and one
4
+ policy-checked, audited execution boundary for conventional CRUD.
5
+
6
+ **0.1.0 Public Preview.** Current code supplies conventional CRUD with everyday
7
+ field types (text, numbers, dates, times, email, URL, JSON, write-only passwords,
8
+ Active Storage files and Action Text rich text), `belongs_to` references,
9
+ many-to-many `references` lists, readonly `has_many`/`has_one` panels, registered
10
+ field types and partials, CSV export and import, record history, the audit log,
11
+ dashboard metrics and trends, bulk delete, a search across resources, synchronous member operations, fixed Selection previews, bounded
12
+ asynchronous collection operations, opt-in admin review Surfaces and a durable
13
+ outbox for one declared post-commit effect. Opt-in admin Chat streams replies and
14
+ turns proposals into review Surfaces. An optional MCP endpoint exposes the same
15
+ grant-filtered tools. Native-provider verification, token and cost budgets,
16
+ nested and polymorphic association writes and broader job-center workflows
17
+ remain open. The
18
+ [development plan](docs/development-plan.md) describes the target product, not the
19
+ supported feature set.
20
+
21
+ The engine supports custom policy adapters and an optional Pundit adapter with
22
+ explicit policy mappings per resource. The host owns authentication, tenants,
23
+ policies and domain data. Missing context or policy grants deny access. Generic writes require a record version
24
+ (`lock_version`, or else `updated_at`) and the same Active Record connection pool for domain records,
25
+ operation receipts, audit and Work items. Resources with irreversible callback
26
+ effects should remain readonly until their host boundary is redesigned and tested.
27
+
28
+ See [Field Types](docs/site/_core_features/field-types.md) for custom normalization,
29
+ validation, fixed Select labels and authorized form/index/show partials. Plugins
30
+ refine a core scalar; they do not grant access. [Computed Fields](docs/site/_core_features/computed-fields.md)
31
+ derive readonly values from declared, currently readable scalar dependencies.
32
+ Neither API exposes arbitrary model methods.
33
+
34
+ Use [Template Overrides](docs/site/_advanced/template-overrides.md) to copy one
35
+ public presentation template and review source/context drift with doctor. Host
36
+ overrides remain trusted Rails code and must preserve the execution boundary.
37
+
38
+ Build ordinary host-owned Rails pages with the public
39
+ [Custom Controller and Status API](docs/site/_advanced/custom-controllers.md).
40
+ Scoped Access and the shared Runner preserve the execution boundary; host routes,
41
+ layouts and partials remain ordinary Rails. The native-session packaged consumer
42
+ includes an Order review workbench that shares its operation with native pages.
43
+
44
+ Link records with [Associations](docs/site/_core_features/associations.md):
45
+ references and child lists resolve through each target resource's own grants,
46
+ so an association never shows or attaches a record its policy hides.
47
+
48
+ Group, label, order or hide sidebar and Overview entries with
49
+ [Resource Navigation](docs/site/_core_features/resource-navigation.md). The menu
50
+ follows current index grants; hiding an entry changes no direct authorization.
51
+
52
+ ## Develop
53
+
54
+ To see the admin before installing it anywhere, run the demo. It copies the
55
+ packaged session/SQLite host to `tmp/demo`, seeds sample data and serves it on
56
+ 127.0.0.1 only; Ctrl-C stops it:
57
+
58
+ ```sh
59
+ bin/demo --assistant # everything, incl. admin Chat and MCP against an offline fake model (no key)
60
+ bin/demo # everything except admin Chat and MCP
61
+ # then open http://127.0.0.1:3917/login and click "Sign in as Admin"
62
+ # Open Assistant → New conversation and send: search articles for upgrading
63
+ ```
64
+
65
+ Follow the [demo walkthrough](docs/site/_getting_started/demo.md#ai-chat-and-mcp)
66
+ to try streamed replies, record links and a change that you review in Chat.
67
+
68
+ ```sh
69
+ bundle install
70
+ bundle exec rake test
71
+ bundle exec rake build
72
+ ```
73
+
74
+ The build creates `pkg/rails_ai_admin-<version>.gem` (currently `0.1.0`); it
75
+ does not publish. `bundle exec rake release:check` reports release readiness, and
76
+ [RELEASING.md](RELEASING.md) lists the next release's open gates and procedure. The
77
+ [ten-minute quickstart](docs/site/_getting_started/quickstart.md) goes from an app
78
+ with Rails 8 sign-in to a working, policy-checked Users admin. The
79
+ [installation guide](docs/site/_getting_started/getting-started.md) covers other
80
+ hosts and adding a local build or development checkout. Then run:
81
+
82
+ ```sh
83
+ bin/rails generate rails_ai_admin:install
84
+ bin/rails db:migrate
85
+ bin/rails generate rails_ai_admin:resource Customer
86
+ bin/rails rails_ai_admin:doctor
87
+ ```
88
+
89
+ Installation stays closed: the generated `AdminContext` returns nil and the
90
+ `AdminPolicyAdapter` stub denies all actions/fields. The install generator also
91
+ provides an unregistered `ExampleAdmin` and an anonymous HTTP test at
92
+ `test/rails_ai_admin/access_test.rb`. These are starting points, not a working
93
+ authentication integration.
94
+
95
+ The resource generator keeps only a readonly ID enabled and leaves the resource
96
+ unregistered. When model schema is available, it adds commented scalar field
97
+ suggestions for review. It does not sample records; sensitive/encrypted fields,
98
+ foreign keys and polymorphic type columns, STI inheritance columns,
99
+ `lock_version`, authority-like names such as role/permission/security_version,
100
+ and unsupported types are excluded from suggestions. A declared non-polymorphic
101
+ `belongs_to` is suggested as a commented `belongs_to` field.
102
+ Missing models or unavailable table metadata still leave the safe readonly scaffold.
103
+ Implement host authentication and explicit policies, then review fields and
104
+ register class-name strings in the initializer.
105
+
106
+ ```ruby
107
+ RailsAiAdmin.configure do |config|
108
+ config.context_adapter = "AdminContext"
109
+ config.authorization_adapter = "AdminPolicyAdapter"
110
+ config.resources = ["CustomerAdmin"]
111
+ end
112
+ ```
113
+
114
+ ```ruby
115
+ class CustomerAdmin < RailsAiAdmin::Resource
116
+ model "Customer"
117
+ key :customers
118
+ title :name
119
+
120
+ fields do
121
+ id :id
122
+ text :name, required: true, nullable: false,
123
+ searchable: :prefix, sortable: true
124
+ end
125
+ end
126
+ ```
127
+
128
+ Run the generated anonymous request test before and after adapting the host:
129
+
130
+ ```sh
131
+ bin/rails test test/rails_ai_admin/access_test.rb
132
+ ```
133
+
134
+ Doctor reports obviously incompatible public zero-argument constructors/signatures, schema,
135
+ field-type review hints, sortable-index and sensitive-declaration findings,
136
+ and default autoload-path diagnostics. Its metadata cannot prove authentication
137
+ or authorization. `TestKit` provides separate anonymous-context, action, tenant
138
+ and exact field-grant assertions; field-grant snapshots are not an AI exposure
139
+ report. See the [host verification guide](docs/site/_advanced/host-verification.md).
140
+
141
+ Resources can also declare named index tabs with `scopes`. Each tab needs its own
142
+ default-deny `named_scopes` grant and can only narrow the policy relation; see
143
+ the [Named Scopes guide](docs/site/_core_features/named-scopes.md). Fields can opt
144
+ into typed exact/range filters with `filterable:`, behind a separate default-deny
145
+ `:filter` field grant; see the [Typed Filters guide](docs/site/_core_features/typed-filters.md).
146
+ An `index` block chooses columns, a default sort, page size and an optional
147
+ bounded count; see the [Index Tables guide](docs/site/_core_features/index-tables.md).
148
+
149
+ The resource declaration grants no permission. See the runnable host contract
150
+ examples in the [configuration guide](docs/site/_getting_started/configuration.md).
151
+ Use one static-path engine mount whose final helper name is `rails_ai_admin`,
152
+ with no HTTP-verb restriction. Run installation inside the target Rails app; its
153
+ loaded routes are checked before writing, including drawn files and namespace
154
+ prefixes. Other helper names, dynamic path parameters and multiple mounts are
155
+ rejected. Admin CSS/ESM are
156
+ prebuilt in the gem, so a host does not need Node to compile them. No provider key,
157
+ AI table or provider call is required for conventional mode.
158
+
159
+ ## Custom Operations and Follow-Up Delivery
160
+
161
+ Register a `RailsAiAdmin::Operation` on a resource for a synchronous member command.
162
+ Its native input form leads to input-bound preflight and a separate human
163
+ confirmation, using the same Runner/receipt/audit transaction as CRUD. Operation
164
+ inputs, committed-receipt reads and follow-up delivery have independent grants;
165
+ ordinary editable-field permissions do not grant them. Successful custom receipt
166
+ replay compares its already bound schema/input digest, not current input grants;
167
+ failed or changed replay input returns a generic conflict without field errors.
168
+ See the
169
+ [Operation guide](docs/site/_core_features/operations.md).
170
+
171
+ `RailsAiAdmin::Work` reuses the input DSL for post-commit delivery. Registered
172
+ `config.work_handlers` persist bounded payload/digest intent through
173
+ `context.outbox.enqueue`. Work performs one declared `context.effect(request:)`
174
+ using a stable downstream delivery key and a dedicated digest of its plain JSON
175
+ wire request. Typed values must be serialized first; normalized key collisions,
176
+ nonfinite floats and unsupported objects are rejected. Ordinary Active Record
177
+ writes in Work/effect execution are guarded, while trusted Ruby remains outside
178
+ a sandbox. A successful business result does not
179
+ mean the effect finished. Outbox auto-dispatch defaults to false; the host must
180
+ schedule `rails_ai_admin:work:scan` or bounded `work:drain` recovery. Optional
181
+ after-commit enqueue is only an accelerator.
182
+
183
+ The default exact record-version policy stops delivery after later record edits.
184
+ Unknown non-idempotent effects require reconciliation rather than automatic
185
+ retry. Leases/fencing and persistent payloads do not establish downstream
186
+ exactly-once execution. Read the [Durable Outbox guide](docs/site/_advanced/durable-outbox.md)
187
+ before enabling a real transport. Preflight's Active Record write guard is not a
188
+ trusted-Ruby sandbox, and operation duration checks do not hard-interrupt Ruby/SQL.
189
+ Global operations, CRUD handler replacement and AI/Surface dispatch remain
190
+ unavailable; complete release Gates remain open.
191
+
192
+ ## Review Surfaces
193
+
194
+ Hosts that already use rails_tool_views can set `config.surfaces = true` and mark
195
+ member operations `surface: true`. A native review can then be saved as a
196
+ persistent Surface that confirms the same intent once, through admin-owned
197
+ endpoints that leave the host's rails_tool_views settings untouched. Operations
198
+ marked `assistant: true` can also be proposed by an assistant through the
199
+ on-demand `raa_propose_operation` RubyLLM tool; only the user's Surface
200
+ confirmation executes them. See the
201
+ [Review Surfaces guide](docs/site/_advanced/review-surfaces.md).
202
+
203
+ ## Admin Assistant
204
+
205
+ Hosts that load ruby_llm can run `bin/rails generate rails_ai_admin:assistant`
206
+ and set `config.assistant = true`. The assistant reads records through each
207
+ admin's current grants plus a default-deny `assistant?` grant, reads audited
208
+ record history, and answers questions asked from a record or list page. It
209
+ cannot change data: a suggested create, update, delete (for resources that
210
+ declare `assistant_changes`) or business operation opens a review Surface with
211
+ before → after values, and only the person's confirmation writes it, once, as
212
+ that person, with a version check and an audit event. Creates are reviewed too.
213
+ Replies stream as they are written. With `config.mcp = true`, outside agents
214
+ (Claude Code, Cursor) use the same tools through an MCP endpoint under personal
215
+ access tokens, and their proposals wait for confirmation in the admin. Turns run in jobs through a leased inbox that
216
+ recovers after crashes without repeating messages. Provider settings come from
217
+ your own adapter, never from global RubyLLM configuration. See the
218
+ [Admin Assistant guide](docs/site/_advanced/admin-assistant.md).
219
+
220
+ ## Fixed Selection Previews
221
+
222
+ A default-deny `export_records?` grant adds an Export CSV button for the current list
223
+ (same rows, columns and values as the pages; audited and bounded by `export_limit`).
224
+ A default-deny `view_history?` grant adds a record History page listing its audited
225
+ changes (fields named only when currently readable or writable).
226
+
227
+ A separate default-deny `select_records?` grant enables native index checkboxes
228
+ and a no-JavaScript preview of up to 100 explicit targets. `Selections::Builder`
229
+ captures exact canonical IDs/versions and revalidates ownership, security version,
230
+ expiry, resource contract and current record/field grants. Newly matching records
231
+ or same-count replacements cannot expand a captured manifest. Labels are freshly
232
+ projected; only IDs/versions/positions and parent binding metadata are persisted.
233
+
234
+ Capture is not operation approval and creates no OperationRun, business audit,
235
+ Work item or job. See [Fixed Selections](docs/site/_core_features/selections.md).
236
+
237
+ ## Asynchronous Collection Operations
238
+
239
+ Register an `Operation` with `scope: :collection` to apply its per-record handler
240
+ to a fixed Selection of at most 100 targets. Native input, pure review and explicit
241
+ **Confirm and queue** create one approved parent with durable child intents/items;
242
+ admission performs no domain mutation. Each worker attempt rebuilds current host
243
+ authority and commits a target change, audit, receipt, optional outbox and item
244
+ completion in one transaction. Public member execution cannot execute child intents.
245
+
246
+ Items commit independently. Cancellation stops remaining uncommitted items and
247
+ preserves committed changes and their Work. Approval expiry controls admission;
248
+ a separate execution deadline bounds the admitted run. Job receipts use separate
249
+ current receipt grants; cancellation needs its own `cancel_operation?` grant.
250
+ The parent stores bounded typed input once, so exclude credentials and secrets.
251
+
252
+ `collection_auto_dispatch` defaults to false. The host supplies `resolve_job`, a
253
+ persistent queue and recurring `rails_ai_admin:collections:scan` (or bounded
254
+ `collections:drain`); after-commit enqueue only accelerates recovery. Read
255
+ [Collection Operations](docs/site/_core_features/collection-operations.md) before
256
+ enabling workers. All-filtered/10,000-target manifests, global operations, a full
257
+ job center and retention remain planned; this bounded slice does not close the
258
+ full roadmap or release Gates.
259
+
260
+ ## Read the Contracts
261
+
262
+ - [Architecture](ARCHITECTURE.md), [public contract](docs/reference/public-contract.md)
263
+ and [operation semantics](docs/reference/operations.md).
264
+ - [Resources and fields](docs/site/_core_features/resources-and-fields.md),
265
+ [host verification](docs/site/_advanced/host-verification.md) and
266
+ [data/security boundaries](docs/site/_advanced/data-and-security.md).
267
+ - [Compatibility evidence](COMPATIBILITY.md), [roadmap](ROADMAP.md) and
268
+ [dependency integration constraints](docs/reference/dependency-contracts.md).
269
+
270
+ An independent [Devise/Pundit/PostgreSQL consumer](spec_hosts/devise_postgres)
271
+ exercises UUID tickets, verified tenant memberships, development reload and
272
+ fresh-process crash/replay using the built gem. Its Propshaft/jsbundling and
273
+ Sprockets/jsbundling modes are asset variants of one consumer. See the
274
+ [Pundit/Devise guide](docs/site/_advanced/pundit-and-devise.md) and
275
+ [host verification guide](docs/site/_advanced/host-verification.md). The engine
276
+ does not provide accounts or login routes. The fixture's separate product Chat
277
+ and Surface remain host-owned, beside its opt-in admin Chat.
278
+
279
+ Changing a resource's policy mapping changes its operation fingerprint. Reopen
280
+ existing development forms if their old intents are invalidated.
281
+
282
+ The Jekyll/RDoc site lives under `docs/site/`. Install its separate bundle, then
283
+ run `docs/site/bin/build.sh`. See [Releasing](RELEASING.md) for the Pages setup
284
+ and versioned builds.
285
+
286
+ Local automated checks and internal review do not establish production readiness,
287
+ independent security review, real-provider behavior or user acceptance. Release
288
+ gates remain in the plan; publishing requires explicit maintainer approval.
289
+
290
+ Licensed under [MIT](LICENSE). Dependencies retain their own licenses in
291
+ [third-party notices](THIRD_PARTY_NOTICES.md). Read [SECURITY.md](SECURITY.md) before
292
+ reporting a vulnerability and [CONTRIBUTING.md](CONTRIBUTING.md) before contributing.
data/SECURITY.md ADDED
@@ -0,0 +1,14 @@
1
+ # Security policy
2
+
3
+ 0.1.0 is a Public Preview. Review the limitations in CHANGELOG.md and deploy
4
+ behind your host application's authentication and network controls. Verify
5
+ tenant scopes and action and field grants before granting access.
6
+
7
+ Report suspected vulnerabilities privately to wangyaodi@gmail.com. Include the
8
+ affected version, minimal synthetic reproduction, impact and suggested fix.
9
+ Do not open a public issue containing exploit details or sensitive data. Reports
10
+ are reviewed by the maintainer; no response-time SLA is currently offered.
11
+
12
+ Authentication and policies belong to the host. A logged-in actor alone grants
13
+ no resource access. Trusted Ruby extensions are not sandboxed. See the threat
14
+ model and public contract for the supported transaction and privacy boundaries.
@@ -0,0 +1,19 @@
1
+ # Third-party notices
2
+
3
+ Original project code is MIT licensed. No competitor source or assets are copied.
4
+ Runtime dependencies retain their own notices in their distributed packages:
5
+
6
+ | Dependency | License | Source |
7
+ | --- | --- | --- |
8
+ | Rails | MIT | https://github.com/rails/rails |
9
+ | rails_tool_views | MIT | https://github.com/yorzi/rails_tool_views |
10
+ | RubyLLM | MIT | https://github.com/crmne/ruby_llm |
11
+ | Turbo / turbo-rails | MIT | https://github.com/hotwired/turbo-rails |
12
+ | Stimulus / stimulus-rails | MIT | https://github.com/hotwired/stimulus-rails |
13
+
14
+ The prebuilt ESM contains Turbo 8.0.23, Stimulus 3.2.2 and the rails_tool_views 1.0.2
15
+ Stimulus controller. Their complete notices
16
+ ship in `app/assets/builds/rails_ai_admin.LICENSE.txt`, generated from the sources
17
+ recorded in `frontend/licenses/README.md`. The host needs no Node build for these
18
+ assets. Dependency installation and license declarations do not prove a security
19
+ audit or grant rights to third-party trademarks.
@@ -0,0 +1,55 @@
1
+ Turbo 8.0.23
2
+ Copyright (c) 37signals
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ Stimulus 3.2.2
24
+ # MIT License
25
+
26
+ Copyright © 2021 Basecamp, LLC.
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
29
+
30
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
31
+
32
+ The Software is provided "as is," without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
33
+
34
+ rails_tool_views 1.0.2 (Stimulus controller)
35
+ MIT License
36
+
37
+ Copyright (c) 2026 Andy Wang
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining a copy
40
+ of this software and associated documentation files (the "Software"), to deal
41
+ in the Software without restriction, including without limitation the rights
42
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43
+ copies of the Software, and to permit persons to whom the Software is
44
+ furnished to do so, subject to the following conditions:
45
+
46
+ The above copyright notice and this permission notice shall be included in all
47
+ copies or substantial portions of the Software.
48
+
49
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
55
+ SOFTWARE.