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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +458 -0
- data/LICENSE +21 -0
- data/README.md +292 -0
- data/SECURITY.md +14 -0
- data/THIRD_PARTY_NOTICES.md +19 -0
- data/app/assets/builds/rails_ai_admin.LICENSE.txt +55 -0
- data/app/assets/builds/rails_ai_admin.css +345 -0
- data/app/assets/builds/rails_ai_admin.js +33 -0
- data/app/controllers/rails_ai_admin/application_controller.rb +255 -0
- data/app/controllers/rails_ai_admin/assistant_controller.rb +164 -0
- data/app/controllers/rails_ai_admin/audit_controller.rb +16 -0
- data/app/controllers/rails_ai_admin/collection_jobs_controller.rb +33 -0
- data/app/controllers/rails_ai_admin/collection_operations_controller.rb +79 -0
- data/app/controllers/rails_ai_admin/custom_controller.rb +26 -0
- data/app/controllers/rails_ai_admin/dashboard_controller.rb +17 -0
- data/app/controllers/rails_ai_admin/exports_controller.rb +31 -0
- data/app/controllers/rails_ai_admin/files_controller.rb +37 -0
- data/app/controllers/rails_ai_admin/imports_controller.rb +41 -0
- data/app/controllers/rails_ai_admin/mcp_controller.rb +81 -0
- data/app/controllers/rails_ai_admin/mcp_tokens_controller.rb +45 -0
- data/app/controllers/rails_ai_admin/operations_controller.rb +105 -0
- data/app/controllers/rails_ai_admin/references_controller.rb +16 -0
- data/app/controllers/rails_ai_admin/resources_controller.rb +290 -0
- data/app/controllers/rails_ai_admin/search_controller.rb +39 -0
- data/app/controllers/rails_ai_admin/selections_controller.rb +95 -0
- data/app/controllers/rails_ai_admin/surfaces_controller.rb +122 -0
- data/app/helpers/rails_ai_admin/dashboard_helper.rb +28 -0
- data/app/helpers/rails_ai_admin/fields_helper.rb +242 -0
- data/app/helpers/rails_ai_admin/filters_helper.rb +40 -0
- data/app/helpers/rails_ai_admin/history_helper.rb +36 -0
- data/app/helpers/rails_ai_admin/navigation_helper.rb +54 -0
- data/app/helpers/rails_ai_admin/tool_views_helper.rb +48 -0
- data/app/jobs/rails_ai_admin/assistant_turn_job.rb +15 -0
- data/app/jobs/rails_ai_admin/collections/execution_job.rb +12 -0
- data/app/jobs/rails_ai_admin/outbox/delivery_job.rb +13 -0
- data/app/models/rails_ai_admin/application_record.rb +8 -0
- data/app/models/rails_ai_admin/audit_event.rb +12 -0
- data/app/models/rails_ai_admin/batch_item.rb +8 -0
- data/app/models/rails_ai_admin/operation_run.rb +20 -0
- data/app/models/rails_ai_admin/selection.rb +9 -0
- data/app/models/rails_ai_admin/selection_item.rb +9 -0
- data/app/models/rails_ai_admin/work_item.rb +18 -0
- data/app/views/layouts/rails_ai_admin/application.html.erb +49 -0
- data/app/views/layouts/rails_ai_admin/frame.html.erb +5 -0
- data/app/views/layouts/rails_ai_admin/status.html.erb +13 -0
- data/app/views/rails_ai_admin/assistant/_ask.html.erb +16 -0
- data/app/views/rails_ai_admin/assistant/_transcript.html.erb +45 -0
- data/app/views/rails_ai_admin/assistant/frame.html.erb +1 -0
- data/app/views/rails_ai_admin/assistant/index.html.erb +14 -0
- data/app/views/rails_ai_admin/assistant/show.html.erb +44 -0
- data/app/views/rails_ai_admin/audit/index.html.erb +40 -0
- data/app/views/rails_ai_admin/collection_jobs/index.html.erb +5 -0
- data/app/views/rails_ai_admin/collection_jobs/show.html.erb +24 -0
- data/app/views/rails_ai_admin/collection_operations/confirmation.html.erb +25 -0
- data/app/views/rails_ai_admin/collection_operations/failure.html.erb +10 -0
- data/app/views/rails_ai_admin/collection_operations/new.html.erb +11 -0
- data/app/views/rails_ai_admin/dashboard/index.html.erb +33 -0
- data/app/views/rails_ai_admin/fields/_index.html.erb +1 -0
- data/app/views/rails_ai_admin/fields/_input.html.erb +21 -0
- data/app/views/rails_ai_admin/fields/_reference.html.erb +1 -0
- data/app/views/rails_ai_admin/fields/_reference_picker.html.erb +14 -0
- data/app/views/rails_ai_admin/fields/_row.html.erb +27 -0
- data/app/views/rails_ai_admin/fields/_show.html.erb +1 -0
- data/app/views/rails_ai_admin/imports/new.html.erb +34 -0
- data/app/views/rails_ai_admin/mcp_tokens/index.html.erb +33 -0
- data/app/views/rails_ai_admin/operations/confirmation.html.erb +32 -0
- data/app/views/rails_ai_admin/operations/failure.html.erb +5 -0
- data/app/views/rails_ai_admin/operations/form.html.erb +13 -0
- data/app/views/rails_ai_admin/resources/_associations.html.erb +12 -0
- data/app/views/rails_ai_admin/resources/_errors.html.erb +14 -0
- data/app/views/rails_ai_admin/resources/_recovery.html.erb +5 -0
- data/app/views/rails_ai_admin/resources/confirm_destroy.html.erb +11 -0
- data/app/views/rails_ai_admin/resources/edit.html.erb +1 -0
- data/app/views/rails_ai_admin/resources/form.html.erb +16 -0
- data/app/views/rails_ai_admin/resources/history.html.erb +27 -0
- data/app/views/rails_ai_admin/resources/index.html.erb +88 -0
- data/app/views/rails_ai_admin/resources/new.html.erb +1 -0
- data/app/views/rails_ai_admin/resources/show.html.erb +12 -0
- data/app/views/rails_ai_admin/search/index.html.erb +20 -0
- data/app/views/rails_ai_admin/selections/confirm_destroy.html.erb +13 -0
- data/app/views/rails_ai_admin/selections/destroyed.html.erb +15 -0
- data/app/views/rails_ai_admin/selections/show.html.erb +19 -0
- data/app/views/rails_ai_admin/shared/_input_fields.html.erb +23 -0
- data/app/views/rails_ai_admin/shared/_navigation.html.erb +8 -0
- data/app/views/rails_ai_admin/shared/_session.html.erb +5 -0
- data/app/views/rails_ai_admin/statuses/show.html.erb +4 -0
- data/app/views/rails_ai_admin/surfaces/_operation_review.html.erb +43 -0
- data/app/views/rails_ai_admin/surfaces/show.html.erb +4 -0
- data/config/locales/en.yml +549 -0
- data/config/routes.rb +64 -0
- data/db/assistant_migrate/20261103000001_create_rails_ai_admin_assistant.rb +138 -0
- data/db/assistant_migrate/20261112000001_upgrade_rails_ai_admin_assistant_to_ruby_llm_2_2.rb +102 -0
- data/db/assistant_migrate/20261114000001_add_streaming_and_access_tokens_to_rails_ai_admin_assistant.rb +29 -0
- data/db/migrate/20261029000001_create_rails_ai_admin_execution_tables.rb +35 -0
- data/db/migrate/20261029000002_add_callback_warning_to_rails_ai_admin_runs.rb +7 -0
- data/db/migrate/20261030000003_create_rails_ai_admin_work_items.rb +26 -0
- data/db/migrate/20261030000004_create_rails_ai_admin_selections.rb +28 -0
- data/db/migrate/20261030000005_create_rails_ai_admin_collection_runs.rb +41 -0
- data/db/migrate/20261113000001_add_record_index_to_rails_ai_admin_audit_events.rb +8 -0
- data/lib/generators/rails_ai_admin/assistant/assistant_generator.rb +25 -0
- data/lib/generators/rails_ai_admin/assistant/templates/admin_assistant.rb +18 -0
- data/lib/generators/rails_ai_admin/engine_migrations.rb +42 -0
- data/lib/generators/rails_ai_admin/install/engine_mounts.rb +19 -0
- data/lib/generators/rails_ai_admin/install/install_generator.rb +53 -0
- data/lib/generators/rails_ai_admin/install/templates/access_test.rb +17 -0
- data/lib/generators/rails_ai_admin/install/templates/admin_context.rb +25 -0
- data/lib/generators/rails_ai_admin/install/templates/admin_policy_adapter.rb +28 -0
- data/lib/generators/rails_ai_admin/install/templates/example_admin.rb +10 -0
- data/lib/generators/rails_ai_admin/install/templates/initializer.rb +7 -0
- data/lib/generators/rails_ai_admin/override/override_generator.rb +46 -0
- data/lib/generators/rails_ai_admin/resource/resource_generator.rb +88 -0
- data/lib/rails_ai_admin/assistant/continuation.rb +33 -0
- data/lib/rails_ai_admin/assistant/coordinator.rb +306 -0
- data/lib/rails_ai_admin/assistant/records.rb +71 -0
- data/lib/rails_ai_admin/assistant/runtime.rb +49 -0
- data/lib/rails_ai_admin/assistant/tools.rb +477 -0
- data/lib/rails_ai_admin/assistant/transcript.rb +140 -0
- data/lib/rails_ai_admin/assistant.rb +50 -0
- data/lib/rails_ai_admin/authorization/access.rb +296 -0
- data/lib/rails_ai_admin/authorization/adapter.rb +92 -0
- data/lib/rails_ai_admin/authorization/pundit_adapter.rb +195 -0
- data/lib/rails_ai_admin/collections/claim.rb +91 -0
- data/lib/rails_ai_admin/collections/contract.rb +113 -0
- data/lib/rails_ai_admin/collections/dispatcher.rb +126 -0
- data/lib/rails_ai_admin/collections/queries.rb +79 -0
- data/lib/rails_ai_admin/collections/result.rb +15 -0
- data/lib/rails_ai_admin/collections/runner.rb +208 -0
- data/lib/rails_ai_admin/configuration.rb +178 -0
- data/lib/rails_ai_admin/context.rb +29 -0
- data/lib/rails_ai_admin/doctor.rb +301 -0
- data/lib/rails_ai_admin/engine.rb +24 -0
- data/lib/rails_ai_admin/error.rb +16 -0
- data/lib/rails_ai_admin/field.rb +625 -0
- data/lib/rails_ai_admin/fields/association.rb +188 -0
- data/lib/rails_ai_admin/fields/computation.rb +43 -0
- data/lib/rails_ai_admin/fields/dependency_graph.rb +45 -0
- data/lib/rails_ai_admin/fields/file_value.rb +23 -0
- data/lib/rails_ai_admin/fields/hook_signatures.rb +18 -0
- data/lib/rails_ai_admin/fields/projection.rb +78 -0
- data/lib/rails_ai_admin/fields/registry.rb +48 -0
- data/lib/rails_ai_admin/fields/scalar_schema.rb +49 -0
- data/lib/rails_ai_admin/fields/type.rb +50 -0
- data/lib/rails_ai_admin/forms/plan.rb +90 -0
- data/lib/rails_ai_admin/input_schema.rb +76 -0
- data/lib/rails_ai_admin/integrations/propose_operation.rb +150 -0
- data/lib/rails_ai_admin/integrations/tool_views.rb +367 -0
- data/lib/rails_ai_admin/mcp.rb +130 -0
- data/lib/rails_ai_admin/navigation/list_state.rb +194 -0
- data/lib/rails_ai_admin/navigation/menu.rb +31 -0
- data/lib/rails_ai_admin/navigation/settings.rb +28 -0
- data/lib/rails_ai_admin/operation.rb +120 -0
- data/lib/rails_ai_admin/operations/default_handlers.rb +17 -0
- data/lib/rails_ai_admin/operations/execution_context.rb +38 -0
- data/lib/rails_ai_admin/operations/form_intent.rb +69 -0
- data/lib/rails_ai_admin/operations/registry.rb +80 -0
- data/lib/rails_ai_admin/operations/result.rb +21 -0
- data/lib/rails_ai_admin/operations/runner.rb +633 -0
- data/lib/rails_ai_admin/operations/runner_fingerprint.rb +12 -0
- data/lib/rails_ai_admin/outbox/delivery_context.rb +51 -0
- data/lib/rails_ai_admin/outbox/dispatcher.rb +189 -0
- data/lib/rails_ai_admin/outbox/registry.rb +36 -0
- data/lib/rails_ai_admin/outbox/request_digest.rb +42 -0
- data/lib/rails_ai_admin/outbox/writer.rb +43 -0
- data/lib/rails_ai_admin/presentation/association_panel.rb +90 -0
- data/lib/rails_ai_admin/presentation/audit_log.rb +63 -0
- data/lib/rails_ai_admin/presentation/csv_export.rb +85 -0
- data/lib/rails_ai_admin/presentation/csv_import.rb +142 -0
- data/lib/rails_ai_admin/presentation/dashboard.rb +122 -0
- data/lib/rails_ai_admin/presentation/history.rb +46 -0
- data/lib/rails_ai_admin/presentation/index_settings.rb +77 -0
- data/lib/rails_ai_admin/presentation/outcomes.rb +44 -0
- data/lib/rails_ai_admin/presentation/status.rb +40 -0
- data/lib/rails_ai_admin/prune.rb +61 -0
- data/lib/rails_ai_admin/queries/list.rb +162 -0
- data/lib/rails_ai_admin/queries/named_scope.rb +65 -0
- data/lib/rails_ai_admin/record_version.rb +40 -0
- data/lib/rails_ai_admin/registry.rb +45 -0
- data/lib/rails_ai_admin/request_log_filter.rb +24 -0
- data/lib/rails_ai_admin/resource.rb +249 -0
- data/lib/rails_ai_admin/resource_identity.rb +15 -0
- data/lib/rails_ai_admin/schema_suggestions.rb +105 -0
- data/lib/rails_ai_admin/selections/builder.rb +162 -0
- data/lib/rails_ai_admin/templates/catalog.rb +84 -0
- data/lib/rails_ai_admin/templates/inspector.rb +94 -0
- data/lib/rails_ai_admin/templates/metadata.rb +48 -0
- data/lib/rails_ai_admin/templates/safe_paths.rb +30 -0
- data/lib/rails_ai_admin/test_kit.rb +103 -0
- data/lib/rails_ai_admin/version.rb +5 -0
- data/lib/rails_ai_admin/work.rb +48 -0
- data/lib/rails_ai_admin.rb +112 -0
- data/lib/tasks/rails_ai_admin.rake +58 -0
- metadata +328 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7042f0c3064d4167940e117fd383145a5895c30b994d278af6027356c0cf0c0f
|
|
4
|
+
data.tar.gz: b10059058a63f1db272d5d70094056647f9136efb461072d29a1c64d37a4f158
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8c1982280acc535eda89d0e4f82992fe0e337880f60839777ede4294100b1345c7719e378cba727d0d1913a8e77b5aca92801c500cd84fad367b4ca4dddf16aa
|
|
7
|
+
data.tar.gz: a0b82dd63d10aa94bae4550de5331cebd4a5834b6d624a7c32f3e9e60276cd2995aa778126f2f1898b3934ec9e504d74239a0e4b75a5b25c15e3f93f89b04f70
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-11-13)
|
|
4
|
+
|
|
5
|
+
First Public Preview. Requires Ruby 3.3 or newer, Rails 8.0.5.2 or newer
|
|
6
|
+
below 8.2 and SQLite or PostgreSQL. Use Rails 8.1.4.1 or newer on the 8.1
|
|
7
|
+
series and keep `json` below 3 on Rails 8.0. Native admin works without AI.
|
|
8
|
+
|
|
9
|
+
Preview limits include association sorting, polymorphic writes, nested child
|
|
10
|
+
forms and separate attach/detach grants. Collection selections cover at most
|
|
11
|
+
100 explicitly selected targets. Chat has a per-person daily message limit.
|
|
12
|
+
Token and cost budgets, automatic conversation retention and native-provider
|
|
13
|
+
and live failure-recovery verification are open. Live provider evidence
|
|
14
|
+
covers an earlier build via OpenRouter. English ships with the engine. A
|
|
15
|
+
human screen-reader pass remains open. APIs, templates and storage may
|
|
16
|
+
change across 0.x releases. See the [upgrade guide](docs/site/_reference/upgrading.md)
|
|
17
|
+
for existing development hosts.
|
|
18
|
+
|
|
19
|
+
### Changes
|
|
20
|
+
|
|
21
|
+
- Give Admin Chat a scrollable conversation and a persistent composer, with
|
|
22
|
+
keyboard shortcuts, live reply following and inline tool and review cards.
|
|
23
|
+
Update the offline demo to stream readable tool summaries and confirm reviewed
|
|
24
|
+
changes in the same conversation.
|
|
25
|
+
- Refine the overview, navigation, list controls, tables and forms in light and
|
|
26
|
+
dark mode. Bound list searches so wide records scroll inside their table region.
|
|
27
|
+
|
|
28
|
+
- MCP server: with `config.mcp = true` (on top of the assistant setup),
|
|
29
|
+
`POST <admin>/mcp` serves the admin Chat tools to agents such as Claude Code or
|
|
30
|
+
Cursor over MCP's Streamable HTTP transport. People issue, list and revoke
|
|
31
|
+
personal access tokens on an MCP access page (shown once, stored as SHA-256,
|
|
32
|
+
bound to owner, tenant and security version and re-resolved through
|
|
33
|
+
`resolve_job` on every request). Proposals return a `review_url` the person
|
|
34
|
+
confirms in the admin. New assistant migration
|
|
35
|
+
`add_streaming_and_access_tokens_to_rails_ai_admin_assistant`; `mcp` is a
|
|
36
|
+
reserved resource key.
|
|
37
|
+
- Streaming: admin Chat replies stream into the conversation as they are
|
|
38
|
+
written (saved on the turn under its lease and polled), and chat text is now
|
|
39
|
+
escaped before formatting so model markup never renders as links or images.
|
|
40
|
+
- Admin Chat: resources may declare `assistant_changes :create, :update,
|
|
41
|
+
:destroy`, and a new `propose_change` tool turns a model's suggestion into a
|
|
42
|
+
review showing before → after (creates included); only the person's
|
|
43
|
+
confirmation writes, as that person, with a version check and audit. A new
|
|
44
|
+
`record_history` tool reads audited changes behind `view_history?`. Record
|
|
45
|
+
and list pages offer "Ask the assistant", which starts a chat with a
|
|
46
|
+
server-checked `Context:` line. `describe_resource` lists allowed changes;
|
|
47
|
+
the prompt is version 3; the offline evaluation set has 23 questions.
|
|
48
|
+
- Dashboard widgets: `dashboard { metric :drafts, scope: :drafts; trend
|
|
49
|
+
:created_at, days: 30 }` adds counts over granted list tabs and daily trend
|
|
50
|
+
charts (inline SVG with a data table) to the overview, through the list's
|
|
51
|
+
policy relation and field read grants.
|
|
52
|
+
- CSV import: with `import_records?` and the create grant, an Import CSV page
|
|
53
|
+
checks a file without writing, then creates one record per valid row through
|
|
54
|
+
the native create operation (own policy check, validations and audit), and
|
|
55
|
+
lists the rows it could not create. Columns match writable create fields by
|
|
56
|
+
label or name; exported files import back. `config.import_limit` (default
|
|
57
|
+
500) bounds a file.
|
|
58
|
+
- Audit log: `<admin>/audit` lists the tenant's audit events across records for
|
|
59
|
+
resources granting `view_audit_log?(context:, resource:)`, filterable by
|
|
60
|
+
resource, change, outcome and actor, with field names under current grants.
|
|
61
|
+
- Association panels offer "Add <child>" when the actor may create a child with a
|
|
62
|
+
writable reference back to the parent. New forms accept
|
|
63
|
+
`prefill[<belongs_to>]=<key>` for writable references to visible targets;
|
|
64
|
+
other prefills are ignored.
|
|
65
|
+
- `files` fields edit `has_many_attached` attachments: remove ticked files and add
|
|
66
|
+
new uploads without replacing the list, with per-file `accept`/`max_size` and a
|
|
67
|
+
`max_files` bound (default 20). Removed blobs are purged after commit; the
|
|
68
|
+
record is touched and audited; show pages render a gallery whose downloads
|
|
69
|
+
name their attachment and are checked like single files.
|
|
70
|
+
- `bin/demo` now adds articles, tags and summaries to the demo host by default
|
|
71
|
+
(`--plain` leaves them out): every field type, cover and gallery images, rich
|
|
72
|
+
text, tags, history, the audit log, CSV export and import (with a sample file),
|
|
73
|
+
bulk delete and overview metrics and trends for articles and orders. `json` and `rich_text` fields stay off list pages unless declared
|
|
74
|
+
`index: true`. The selection page no longer shows raw record versions, and
|
|
75
|
+
rich-text and many-to-many inputs are named by their visible label instead of
|
|
76
|
+
a `<label for>` that pointed at a non-form element.
|
|
77
|
+
- Search everything: a header search box (shown when the actor may search at
|
|
78
|
+
least one menu resource) opens `<admin>/search`, which runs each resource's own
|
|
79
|
+
list search and shows up to five records per resource through their show
|
|
80
|
+
grants. **Breaking:** `search` is now a reserved resource key.
|
|
81
|
+
- The overview shows record counts for resources whose list opts into exact
|
|
82
|
+
counts, with the list's bound. Dark mode already follows the system setting.
|
|
83
|
+
- Associations: `has_one :profile` shows a record's single child as a panel,
|
|
84
|
+
with the same grants as `has_many` panels. A `references :tags` field edits a
|
|
85
|
+
`has_many`/`:through`/HABTM list through `tag_ids=`: checkboxes for up to 100
|
|
86
|
+
visible targets (a search picker beyond), only currently visible targets may be
|
|
87
|
+
added, hidden stored targets are always kept, a changed list touches the record
|
|
88
|
+
so its version advances and the audit names the field, and CSV, Chat and show
|
|
89
|
+
pages label targets through their own grants.
|
|
90
|
+
- Rich text: a `rich_text` field edits a `has_rich_text` attribute with Trix from
|
|
91
|
+
the host's Action Text assets (loaded only on forms that need it; file
|
|
92
|
+
attachments refused). Show pages sanitize the stored HTML; lists, CSV and
|
|
93
|
+
Chat use plain text; audit names the field when the content changes.
|
|
94
|
+
- File uploads: a `file` field for a `has_one_attached` attachment, with
|
|
95
|
+
`accept:` content types and `max_size:` (default 10 MB). Uploads become new
|
|
96
|
+
blobs only for fields the actor may write; the Runner accepts only new,
|
|
97
|
+
unattached blobs that fit; refused writes purge them; a remove box clears an
|
|
98
|
+
optional file; audit names the field. Downloads go through
|
|
99
|
+
`<admin>/<resource>/<id>/files/<field>` with the record's scope, show grant
|
|
100
|
+
and field read grant, streamed with a sandboxed CSP; only raster images show
|
|
101
|
+
inline. Form recovery skips chosen files instead of failing.
|
|
102
|
+
- Bulk delete: a fixed selection offers "Delete the N selected records" when the
|
|
103
|
+
resource allows `destroy` and the actor may delete at least one of them. After
|
|
104
|
+
a review page, each record is deleted on its own through the native destroy
|
|
105
|
+
operation (own policy check, version, transaction and audit); records that
|
|
106
|
+
cannot be deleted are kept and listed with the reason. A changed selection
|
|
107
|
+
deletes nothing. `Selections::Builder#revalidate` now yields current records
|
|
108
|
+
to a block.
|
|
109
|
+
- CSV export: a default-deny `export_records?(context:, resource:)` grant (Pundit:
|
|
110
|
+
`export_records?`) adds an Export CSV button that POSTs the current search,
|
|
111
|
+
list tab, filters and sort to `<admin>/<resource>/exports`. Rows and columns
|
|
112
|
+
follow the index, show and read grants; references export their labels;
|
|
113
|
+
formula-like text is neutralized; `config.export_limit` (default 10,000)
|
|
114
|
+
bounds a file, and each export is audited.
|
|
115
|
+
- Record History: with a new default-deny `view_history?(context:, resource:,
|
|
116
|
+
record:)` grant (Pundit: `view_history?`), a record's page links to
|
|
117
|
+
`<admin>/<resource>/<id>/history`, its audit trail newest first (50 per
|
|
118
|
+
page): time, change, changed fields named only when currently readable or
|
|
119
|
+
writable, actor and origin. Rejected writes now record their target, so a
|
|
120
|
+
lost edit appears as "Not saved". A context adapter may answer
|
|
121
|
+
`actor_labels(context:, actor_refs:)` to show names. New engine migration
|
|
122
|
+
`add_record_index_to_rails_ai_admin_audit_events`.
|
|
123
|
+
- New field types: `time` (time of day), `email` (mailto link), `url` (only
|
|
124
|
+
http/https addresses become links), `json` (indented editing and display on
|
|
125
|
+
json/jsonb columns) and write-only `password` for `has_secure_password`. No
|
|
126
|
+
read grant reveals a password; an empty box keeps the current one; audit
|
|
127
|
+
names the field; input digests store a keyed hash of it. Schema suggestions
|
|
128
|
+
offer `email`, `url`, `time` and `json` from column types and names.
|
|
129
|
+
**Breaking:** a registered field type named `email`, `url`, `time`, `json` or
|
|
130
|
+
`password` must be renamed, because those keys are now built in.
|
|
131
|
+
- Models no longer need a `lock_version` column. Without one, `updated_at`
|
|
132
|
+
carries the record version (whole microseconds), compared after a row-locked
|
|
133
|
+
load inside the write transaction; forms, intents, selections, collection
|
|
134
|
+
items and Work delivery all use it. `updated_at` then cannot be a writable
|
|
135
|
+
field, and doctor reports `version=lock_version`, `version=updated_at` or
|
|
136
|
+
`version=missing` instead of `lock_version=true/false`.
|
|
137
|
+
- Framework I18n: every page heading, button, notice, status page, field
|
|
138
|
+
validation message, Chat message and script message reads
|
|
139
|
+
`config/locales/en.yml` (`rails_ai_admin.*`), and `<html lang>` follows
|
|
140
|
+
`I18n.locale`. A new Translations guide shows how to add a locale. The
|
|
141
|
+
English text is unchanged, except that the collection job backlog hint now
|
|
142
|
+
renders the queue name as code instead of escaped `<code>` text. Host
|
|
143
|
+
layout overrides keep working; their script messages stay English until
|
|
144
|
+
they add `data-raa-messages` to `<body>`.
|
|
145
|
+
- Security regression sweep (RAA-0210): every state-changing engine route,
|
|
146
|
+
including Surface and Chat routes, rejects a missing CSRF token without a
|
|
147
|
+
side effect; unwritable, framework and tenant attributes are never mass
|
|
148
|
+
assigned; record text and request values are escaped on every page; list
|
|
149
|
+
and selection pages keep a constant query count as rows grow.
|
|
150
|
+
- Reference inputs past 100 targets keep the typed key input and add a search
|
|
151
|
+
box that fills it. `GET <admin>/<target>/references/search?q=` returns at
|
|
152
|
+
most 20 `{id, label}` results through the target's own policy relation,
|
|
153
|
+
search grants and per-record show grant, plus an exact key match; filters
|
|
154
|
+
use the same picker (RAA-030).
|
|
155
|
+
- Dependencies are on their latest releases: minitest 6.1.0, prism 2.1.0,
|
|
156
|
+
Bundler 4.0.24, jekyll-vitepress-theme 1.12.0, Host B esbuild 0.28.2, and
|
|
157
|
+
CI on ruby/setup-ruby v1.338.0 and Node 26. Ruby 4.0.9 and Rails 8.1.4.1
|
|
158
|
+
were already current; the Rails 8.0 lock stays on 8.0.5.2 and json 2.x.
|
|
159
|
+
- Admin Chat runs on RubyLLM 2.2.0 and now requires it (`>= 2.2.0, < 3`).
|
|
160
|
+
RubyLLM 2.2 broke Chat on the old 2.1 schema: a new
|
|
161
|
+
`upgrade_rails_ai_admin_assistant_to_ruby_llm_2_2` migration adds its claim,
|
|
162
|
+
phase, provider call id and usage columns and its queued-message and
|
|
163
|
+
chat-file tables, skipping what a host already has. The provider context is
|
|
164
|
+
bound before a turn's message is saved, since RubyLLM 2.2 builds its chat
|
|
165
|
+
then, and usage ownership uses `RubyLLM.with_owner`.
|
|
166
|
+
- `bin/demo` copies the packaged session/SQLite host to `tmp/demo`, seeds it
|
|
167
|
+
and serves it on 127.0.0.1 until Ctrl-C; `--assistant` adds admin Chat and a
|
|
168
|
+
review Surface against an offline fake provider in `script/demo`.
|
|
169
|
+
- Schema suggestions and doctor's sensitivity check treat `admin` and
|
|
170
|
+
`superuser` name parts as authority, so `users.admin` is no longer offered
|
|
171
|
+
as an editable field.
|
|
172
|
+
- A ten-minute quickstart guide goes from a Rails 8 app with the
|
|
173
|
+
authentication generator to a working Users admin, then to editing. The
|
|
174
|
+
generated `AdminContext` and `AdminPolicyAdapter` stay closed but carry a
|
|
175
|
+
commented, working example for that kind of app.
|
|
176
|
+
- `rails_ai_admin:resource Model --fields name:text points` writes the named
|
|
177
|
+
schema suggestions as active (still readonly) fields, titles the resource by
|
|
178
|
+
the first text field, and refuses a field the schema would not suggest or a
|
|
179
|
+
type that differs from it.
|
|
180
|
+
- Generator output links the guides in the source repository instead of
|
|
181
|
+
local `docs/` paths the gem does not ship, and the Chat generator names the
|
|
182
|
+
supported ruby_llm range. The overview no longer calls Chat, Surfaces and
|
|
183
|
+
associations later milestones (RAA-026).
|
|
184
|
+
- Support Ruby 3.3+ and Rails 8.0.5.2+ (was Ruby 4.0.9+ and Rails 8.1.4.1+).
|
|
185
|
+
A CI compatibility job runs the engine suite on Ruby 3.3 and 4.0 with Rails
|
|
186
|
+
8.0 and 8.1, on SQLite and PostgreSQL. Engine migrations declare
|
|
187
|
+
`Migration[8.0]` (the same schema on 8.1); `json >= 2.13` is a dependency so
|
|
188
|
+
override headers reject duplicate keys on json 2.x too; doctor reports a
|
|
189
|
+
Rails 8.1 below the patched 8.1.4.1.
|
|
190
|
+
- The install and assistant generators keep an engine migration the host
|
|
191
|
+
already has, even with `--force`. Rails would otherwise remove a changed
|
|
192
|
+
one and copy it under a new timestamp, so an already-run migration ran
|
|
193
|
+
again.
|
|
194
|
+
- `ruby_llm` and `rails_tool_views` are no longer runtime dependencies, so a
|
|
195
|
+
conventional install pulls no AI code. Hosts that enable `config.assistant`
|
|
196
|
+
or `config.surfaces` add the gem themselves; boot checks the supported range
|
|
197
|
+
(`Configuration::OPTIONAL_GEMS`) (RAA-026).
|
|
198
|
+
- Make daily use pleasant (audit 2026-11-10). Model validation messages reach
|
|
199
|
+
the page for writable fields (`config.validation_messages = :generic` keeps
|
|
200
|
+
"is invalid"), and a field type's `valid?` may return a message (RAA-011).
|
|
201
|
+
Timestamps use a native `datetime-local` input in the context zone and display
|
|
202
|
+
as "30 Oct 2026 01:30 UTC" inside `<time>`; an unchanged save keeps stored
|
|
203
|
+
fractions of a second; long text keeps line breaks (RAA-015). Required fields
|
|
204
|
+
carry `required`, `aria-required` and a marker; readonly values are no longer
|
|
205
|
+
`<output>` live regions (RAA-023). Pages have specific titles and headings,
|
|
206
|
+
Cancel on edit returns to the record, the fixed "Development preview" became
|
|
207
|
+
`config.environment_label`, a `session_links` partial holds the signed-in
|
|
208
|
+
user, and a signed-out page visit redirects to `authentication_path` with
|
|
209
|
+
`return_to` (RAA-024). Lists put search beside the heading, fold filters into
|
|
210
|
+
`<details>`, add a page select-all and an Edit link per row (RAA-025). Codes
|
|
211
|
+
become sentences on forms, failure pages and job tables (RAA-027). Search is
|
|
212
|
+
trimmed and states its match mode; doctor names the fields it counts and gives
|
|
213
|
+
index advice that matches the SQL (RAA-021, RAA-026). Empty values sort last
|
|
214
|
+
(RAA-028); the collection review uses labels and formatting (RAA-029); only
|
|
215
|
+
canonical ids address a record (RAA-022); `/jobs` follows its menu grant
|
|
216
|
+
(RAA-030). Strings touched here moved to `config/locales/en.yml`.
|
|
217
|
+
- Make the assistant more trustworthy (audit 2026-11-10, partial). Searches
|
|
218
|
+
cover the whole policy relation unless the model names a granted scope, and
|
|
219
|
+
accept `sort`/`direction`; every result reports `applied_scope` and
|
|
220
|
+
`applied_sort`, and `describe_resource` lists scopes, sortable fields and each
|
|
221
|
+
search field's match mode (RAA-007, RAA-021). A new `count_records` tool
|
|
222
|
+
answers "how many" with the capped index count. Tool values are typed JSON
|
|
223
|
+
(null, booleans, integers, exact decimals, ISO times, `{value, label}`
|
|
224
|
+
selects, `{id, label, resource}` references); `PROMPT_VERSION` is 2
|
|
225
|
+
(RAA-017). Retryable provider failures schedule their own retry and the chat
|
|
226
|
+
shows "Retrying (n of 3)" (RAA-008). Activity lines come from the stored
|
|
227
|
+
tool result (RAA-018). A short assistant note precedes a new message after
|
|
228
|
+
an unanswered one (RAA-030). `config.assistant_daily_message_limit`
|
|
229
|
+
(default 100 per actor per 24 hours) is the minimal spend guard.
|
|
230
|
+
Review Surfaces show the proposed visible changes, offer **Dismiss** (which
|
|
231
|
+
expires the intent and tells the chat once), return to the chat after either
|
|
232
|
+
action, and get rails_tool_views' Stimulus controller from the admin bundle
|
|
233
|
+
(RAA-019).
|
|
234
|
+
- Unbreak ordinary flows (audit 2026-11-10). A list page leaves out an in-scope
|
|
235
|
+
row whose `show` is denied and says so instead of returning 404 for the whole
|
|
236
|
+
page; `TestKit.assert_scope_matches_show` finds the disagreement (RAA-001). An
|
|
237
|
+
association panel's "View all" link carries the new `scope=_none` list state so
|
|
238
|
+
the child's default tab no longer hides children the panel showed (RAA-006).
|
|
239
|
+
"Capture selection" with nothing ticked returns to the list with a notice,
|
|
240
|
+
duplicate ids collapse, and the button stays disabled until a row is ticked
|
|
241
|
+
(RAA-013). A delete blocked by a foreign key or `restrict_with_error` returns
|
|
242
|
+
the new `RESTRICTED` code with the model's reason instead of "Conflict… open a
|
|
243
|
+
fresh form" (RAA-012). Form pages no longer write: they issue a signed form
|
|
244
|
+
reference that becomes the intent on first submit or recovery, and
|
|
245
|
+
`rails_ai_admin:prune` removes expired unused intents and selections (RAA-005,
|
|
246
|
+
ADR 0025). Boot and doctor report a rails_tool_views `parent_controller` that
|
|
247
|
+
does not resolve when Surfaces are on (RAA-009). Job pages say when work is
|
|
248
|
+
waiting for a worker, doctor reports a backlog, and `config.queue_name`
|
|
249
|
+
makes the `rails_ai_admin` queue name configurable (RAA-020). Error summaries use
|
|
250
|
+
a sentence per result code with the code as secondary text.
|
|
251
|
+
- Stop silent data changes from conventional forms (audit 2026-11-10):
|
|
252
|
+
blank or whitespace-only text is stored as null in a nullable field and
|
|
253
|
+
rejected with "cannot be blank" when the field is `required` or
|
|
254
|
+
`nullable: false` (RAA-002, RAA-003); decimals honour the column's precision
|
|
255
|
+
and scale, or new `precision:`/`scale:` options, reject extra digits instead
|
|
256
|
+
of rounding and display padded to the scale (RAA-004, RAA-014); impossible
|
|
257
|
+
date-times such as `2026-02-30T10:00` are rejected (RAA-010); NUL and other
|
|
258
|
+
control characters are rejected in text input, with tab and line breaks
|
|
259
|
+
still allowed in `textarea` (RAA-016). The admin layout disables Turbo hover
|
|
260
|
+
prefetch so hovering a link no longer prepares an intent (RAA-005).
|
|
261
|
+
`required: true` now also rejects a null value.
|
|
262
|
+
- Reconcile the association/Chat branch with remote main, retaining the standalone
|
|
263
|
+
assistant proposal API and its explicit `assistant: true` opt-in. Admin Chat
|
|
264
|
+
now honors that flag too; native Surface permission alone grants no proposal.
|
|
265
|
+
- Fence assistant message persistence atomically against the current turn lease,
|
|
266
|
+
including late provider answers/tool calls and stale-worker cleanup. Recovery
|
|
267
|
+
removes abandoned placeholders without dropping billed usage.
|
|
268
|
+
- Fix Chat search pagination independently of native page size; byte-truncated
|
|
269
|
+
results return `next_offset` so omitted records remain reachable.
|
|
270
|
+
- Distinguish `.dev` builds from approved alpha/beta/RC versions in release checks;
|
|
271
|
+
published prereleases need versioned changelog/docs metadata and owner approval.
|
|
272
|
+
- Pin packaged consumers to Rails 8.1.4.1, discard stale generated locks and
|
|
273
|
+
verify installed candidate metadata and all files before acceptance. The
|
|
274
|
+
release checker rejects host Rails pins below the runtime floor.
|
|
275
|
+
- Raise the Rails dependency floor to 8.1.4.1 and refresh affected Ruby lockfiles
|
|
276
|
+
(Rails, Addressable, Loofah, Nokogiri and rails-html-sanitizer).
|
|
277
|
+
|
|
278
|
+
- Add opt-in admin Chat (`config.assistant`, ADR 0022). The
|
|
279
|
+
`rails_ai_admin:assistant` generator adds Engine-owned chat, message and turn
|
|
280
|
+
tables and a closed `AdminAssistant` adapter whose `llm_context(context:)`
|
|
281
|
+
returns a per-request `RubyLLM::Context`; global RubyLLM settings are never
|
|
282
|
+
read or changed, and conventional hosts load no RubyLLM code.
|
|
283
|
+
- Add the default-deny `assistant?(context:, resource:)` grant (Pundit:
|
|
284
|
+
`assistant?`). Read tools (`list_resources`, `describe_resource`,
|
|
285
|
+
`search_records`, `get_record`) apply every current grant and return bounded
|
|
286
|
+
JSON with fixed error codes.
|
|
287
|
+
- Add `propose_operation`, which prepares an `origin: assistant` intent and
|
|
288
|
+
shows the existing review Surface in the conversation. The human's Surface
|
|
289
|
+
confirmation writes once and admits one continuation turn in the same
|
|
290
|
+
transaction.
|
|
291
|
+
- Add a persistent per-chat turn inbox: keyed admission, strict ordering,
|
|
292
|
+
leases with fencing, a once-only human message, reconciliation of an answer
|
|
293
|
+
persisted before a crash, retry, Stop and archive, plus
|
|
294
|
+
`rails_ai_admin:assistant:scan`/`drain`. Doctor reports the assistant setup
|
|
295
|
+
without calling the adapter or a provider.
|
|
296
|
+
- Fix `describe_resource` omitting the allowed values of an operation's `enum`
|
|
297
|
+
input. A live model guessed `triaged` for the triage `decision` and needed two
|
|
298
|
+
rejected proposals before trying `triage`; it now receives the choices.
|
|
299
|
+
|
|
300
|
+
- Add `belongs_to` reference fields. A reference is labelled and linked only
|
|
301
|
+
through the target resource's current relation, show grant and title, and an
|
|
302
|
+
index loads each reference column with one query. Missing, foreign and hidden
|
|
303
|
+
targets render the same `Customer #42` placeholder. Forms offer up to 100
|
|
304
|
+
visible targets (else a typed key); the Runner rejects a changed reference the
|
|
305
|
+
actor cannot see, keeps an unchanged one and maps a foreign-key race to
|
|
306
|
+
CONFLICT. References filter by `eq`; they cannot search or sort yet.
|
|
307
|
+
- Add readonly `has_many` show-page panels read through the child resource's
|
|
308
|
+
index grant, policy relation and a readable reference field, with a filtered
|
|
309
|
+
"View all" link while that field is filter-granted.
|
|
310
|
+
- Add `Field#column`; reads, writes, list queries, audit field names and doctor
|
|
311
|
+
checks now distinguish a field's name from its column. Doctor adds an
|
|
312
|
+
`associations:<resource>` reflection check.
|
|
313
|
+
- Add the `field_reference` and `resource_associations` override entries
|
|
314
|
+
(catalog now 29). **Review overrides:** `resource_show` advances to revision 3
|
|
315
|
+
and `field_form` to revision 2.
|
|
316
|
+
- The resource generator suggests a declared non-polymorphic, non-sensitive
|
|
317
|
+
`belongs_to` as a commented `belongs_to` field; tenant-like references
|
|
318
|
+
(account, tenant, organization, workspace, company, team) and other key
|
|
319
|
+
columns stay omitted.
|
|
320
|
+
- `rake build` names the package from `RailsAiAdmin::VERSION`, and
|
|
321
|
+
`rake release:check` reports release readiness without publishing.
|
|
322
|
+
|
|
323
|
+
- Merge Dependabot updates after verification: actions/checkout 7.0.1 and
|
|
324
|
+
actions/setup-node 7.1.0 (still SHA-pinned), jekyll-vitepress-theme 1.11.0,
|
|
325
|
+
esbuild 0.28.2 (prebuilt bundle rebuilt) and Minitest 6.0.6. Minitest 6
|
|
326
|
+
extracted `minitest/mock`, so `minitest-mock` is now a development dependency
|
|
327
|
+
and the packaged hosts pin Minitest `~> 6.0`.
|
|
328
|
+
- Add assistant operation proposals: `operation ..., assistant: true` and the
|
|
329
|
+
on-demand `Integrations::ProposeOperation` RubyLLM tool, which preflights an
|
|
330
|
+
`assistant`-origin intent and presents the review Surface; only the human's
|
|
331
|
+
Surface confirmation executes. Tool-call replays are idempotent.
|
|
332
|
+
- Record open rails_tool_views integration findings DEP-008..012.
|
|
333
|
+
- Add opt-in admin review Surfaces on the host-owned rails_tool_views runtime:
|
|
334
|
+
`config.surfaces`, `operation ..., surface: true`, admin-owned endpoints with an
|
|
335
|
+
explicit `raa:` Scope and a constant `raa_operation_review` component. A
|
|
336
|
+
Surface confirms the same native intent once through the shared Runner;
|
|
337
|
+
completed reviews need the receipt grant. Host settings are never changed.
|
|
338
|
+
- Add index table settings: declared columns, a default sort applied only while
|
|
339
|
+
granted, page sizes of 1..100 and exact counts bounded at 10,000 (no
|
|
340
|
+
tenant-global estimates). Cells no longer split words and compact values stay
|
|
341
|
+
on one line, so wide tables scroll (resource_index revision 5).
|
|
342
|
+
- Add gemspec homepage and source/changelog/bug-tracker metadata.
|
|
343
|
+
- Add typed list filters: `filterable:` fields with eq/gte/lte by scalar type, a
|
|
344
|
+
separate default-deny `:filter` field grant (Pundit `filterable_fields`),
|
|
345
|
+
contract-coerced Arel-bound values, canonical nested filter list hints and a
|
|
346
|
+
native filter form (resource_index revision 4). Doctor reviews unindexed
|
|
347
|
+
filterable columns. **Breaking:** TestKit field snapshots and
|
|
348
|
+
`assert_field_grants` now require a `filter` group.
|
|
349
|
+
- Update rack to 3.2.8 for GHSA-2j8w-xcrc-x985, GHSA-5v64-555j-wjxm,
|
|
350
|
+
GHSA-p8x9-v4hv-2w4g and GHSA-wvg4-6p58-3gh3.
|
|
351
|
+
- Add named list scopes: bounded index tabs with an optional default that are
|
|
352
|
+
intersected with the policy relation by primary key, need an independent
|
|
353
|
+
default-deny `named_scopes` grant (Pundit `permitted_named_scopes`), travel in
|
|
354
|
+
list hints and render as current-grant tabs (resource_index revision 3).
|
|
355
|
+
- Require Ruby 4.0.9 or newer; development, RuboCop and every CI job use the
|
|
356
|
+
`.ruby-version` pin (4.0.9) instead of a Ruby 3.4/4.0 matrix.
|
|
357
|
+
- Establish the implementation baseline from the reviewed v0.3 development plan.
|
|
358
|
+
- Add an isolated, default-deny Engine with explicit resources and scalar fields.
|
|
359
|
+
- Add synchronous CRUD intents with identity/input/version/expiry binding, current
|
|
360
|
+
authorization, atomic receipts/audit, replay protection and callback outcome checks.
|
|
361
|
+
- Add conventional pages, bounded search/sort, readonly resource aliases, prebuilt
|
|
362
|
+
Turbo/Stimulus assets and request-local log redaction.
|
|
363
|
+
- Add closed installation/resource generators, basic doctor/TestKit, a packaged
|
|
364
|
+
session/SQLite consumer, database contracts and local public documentation.
|
|
365
|
+
- Add the optional explicit Pundit adapter, a distinct packaged Devise/PostgreSQL
|
|
366
|
+
host, Propshaft and Sprockets/jsbundling variants, real development reload and
|
|
367
|
+
process crash/response-loss recovery probes. Keep host product SDK settings intact.
|
|
368
|
+
- Add schema-only commented field suggestions, preserved default-deny install
|
|
369
|
+
scaffolds and actual-route preflight checks. Expand doctor metadata diagnostics
|
|
370
|
+
and host TestKit policy/field-grant assertions; run generated anonymous tests in
|
|
371
|
+
both packaged consumers.
|
|
372
|
+
- Add registered member Operations with typed pure preflight, native human
|
|
373
|
+
confirmation, independent input/receipt authority and guarded versioned writes.
|
|
374
|
+
- Add atomic outbox intents, fresh delivery authority, bounded leases/fencing,
|
|
375
|
+
stable request fingerprints, explicit unknown outcomes and pending-work scans.
|
|
376
|
+
Keep delivery outcomes separate from committed business receipts.
|
|
377
|
+
|
|
378
|
+
- Restrict scalar projection and record titles to model attributes before invoking
|
|
379
|
+
getters, preventing accidental mutating-method calls during readonly display.
|
|
380
|
+
Normal attribute getter overrides remain trusted host code.
|
|
381
|
+
|
|
382
|
+
- Add immutable fixed selections with independent default-deny grants, canonical
|
|
383
|
+
target/version manifests, native capture/preview and fresh revalidation.
|
|
384
|
+
- Bind operation/selection identity to the physical table and primary-key contract,
|
|
385
|
+
preventing stale references from changing meaning after a model remapping.
|
|
386
|
+
|
|
387
|
+
- Add asynchronous fixed-manifest collection operations with one parent approval,
|
|
388
|
+
current collection/record grants, leased item transactions, fenced receipts,
|
|
389
|
+
bounded recovery, partial cancellation and native job/result controls.
|
|
390
|
+
- Select rails_tool_views 1.0.2, close DEP-001/DEP-006 and verify the released
|
|
391
|
+
installer preserves an existing custom mount without route restoration.
|
|
392
|
+
|
|
393
|
+
- Add a reloadable scalar field-type registry with pure normalization/validation,
|
|
394
|
+
intersected JSON Schemas, plain-text formatting and trusted field partials.
|
|
395
|
+
Bind plugin versions/schema to operation, selection and Work fingerprints.
|
|
396
|
+
- Add fixed Select labels, a readonly scalar shorthand and disabled placeholders
|
|
397
|
+
for unavailable selections. Respect per-record field denial before rendering.
|
|
398
|
+
- Accept typed Date/Time operation proposals during confirmation/replay without
|
|
399
|
+
freezing caller-owned temporal values; preserve timestamp microseconds in hooks
|
|
400
|
+
and native forms, and reject nonfinite decimals.
|
|
401
|
+
- Exercise custom fields in both packaged consumers and initialize domain fixture
|
|
402
|
+
schema before transactional request tests so fresh databases are deterministic.
|
|
403
|
+
|
|
404
|
+
- Add bounded readonly computed fields with declared dependency graphs, recursive
|
|
405
|
+
read grants, immutable scalar snapshots and fresh versioned host computations.
|
|
406
|
+
- Share cached row projections and formatted titles across pages, selections and
|
|
407
|
+
jobs; block physical-getter writes and reject fabricated virtual previews.
|
|
408
|
+
- Verify graph/size/time bounds, dependency denial, current result projection,
|
|
409
|
+
query counts, stale contracts and actual computation reload in packaged hosts.
|
|
410
|
+
|
|
411
|
+
- Add individual template overrides with a public catalog, deterministic source/
|
|
412
|
+
context headers, exclusive Unicode-preserving copies and non-destructive reruns.
|
|
413
|
+
- Add bounded doctor diagnostics for stale/manual/invalid override metadata without
|
|
414
|
+
evaluating ERB. Keep host-body review separate from source metadata agreement.
|
|
415
|
+
- Add independent new/edit wrappers for GET/validation/conflict and default field
|
|
416
|
+
display partials; verify standard host view precedence and live template reload.
|
|
417
|
+
|
|
418
|
+
- Add per-view resource presentation masks, global hidden fields, plain help text
|
|
419
|
+
and authorized readonly context in bounded tab/panel form plans. Keep write-only
|
|
420
|
+
prefills blank and enforce fresh create/edit masks in the shared Runner.
|
|
421
|
+
- Add progressive keyboard tabs, native invalid-control revelation, error-summary
|
|
422
|
+
focus/links and collision-free help/error IDs. Preserve hidden-panel FormData.
|
|
423
|
+
- Add the field-row override and advance changed form context revisions to 2.
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
- Preserve open generic forms on explicitly marked session/CSRF failures and add
|
|
427
|
+
manual reauthentication recovery with a fresh CSRF form, current editable fields
|
|
428
|
+
and the same unconsumed intent. Bound recovery to one hour and require Save.
|
|
429
|
+
- Keep snapshots in the open DOM only; preserve edits while recovery waits and
|
|
430
|
+
reject stale/completed/foreign intents without reissuing or replaying a write.
|
|
431
|
+
- Add the recovery partial/host login-path setting, private response handshake and
|
|
432
|
+
revision 3 new/edit/shared-form contracts. Verify actual Devise timeout recovery.
|
|
433
|
+
|
|
434
|
+
- Preserve structured resource list hints through CRUD, member review, selections
|
|
435
|
+
and collection job controls without accepting arbitrary redirect URLs.
|
|
436
|
+
- Add authorized sortable headers, stable pagination/return links and bounded
|
|
437
|
+
same-filter empty-page recovery. Revalidate stale settings with a visible fallback.
|
|
438
|
+
- Carry Unicode list hints through open-tab recovery using a bounded ASCII codec;
|
|
439
|
+
retain the original business intent and fresh hidden security fields.
|
|
440
|
+
- Reject malformed search/page encodings and control searches before database
|
|
441
|
+
serialization. Declare the already-resolved base64 codec as a direct dependency.
|
|
442
|
+
|
|
443
|
+
- Add public host CustomController entry points for current Context, scoped Access,
|
|
444
|
+
shared Runner, mounted routes and layout CSP nonce without replacing host helpers.
|
|
445
|
+
- Add eight fixed minimal status kinds with HTML/Turbo reload, anti-enumeration,
|
|
446
|
+
status-template plain fallback and two individual override catalog entries.
|
|
447
|
+
- Add packaged Order CRUD and a host-owned review workbench sharing the native
|
|
448
|
+
operation/intent, plus real controller/operation reload and browser recovery proof.
|
|
449
|
+
- Return CONFLICT for unique-index rejection with full transaction rollback. Isolate
|
|
450
|
+
temporary mounted-route probes so randomized tests use the real host prefix.
|
|
451
|
+
|
|
452
|
+
- Add static resource menu groups, plain labels, fixed decorative icons, ordering
|
|
453
|
+
and `navigation false`, built per request from current index grants. Hiding a
|
|
454
|
+
menu entry grants or revokes nothing and leaves approval/Selection identity intact.
|
|
455
|
+
- Add the resource_navigation partial (catalog now 27 entries) and advance the
|
|
456
|
+
layout/dashboard contracts to revisions 3/2; legacy visible_resources is kept.
|
|
457
|
+
- Reject an unusable fallback menu label at registration instead of making every
|
|
458
|
+
admin page unavailable at render time.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andy Wang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|