activeadmin-graphql 0.4.0 → 0.4.1
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 +15 -3
- data/README.md +2 -2
- data/docs/changelogs/20260818111600_rfc-0002-problems.md +1 -1
- data/docs/changelogs/20260818114000_rfc-as-built-coverage.md +1 -1
- data/docs/changelogs/20260818114700_rfc-design-not-version.md +1 -1
- data/docs/changelogs/20260907141000_advisory-lockfile-refresh.md +1 -1
- data/docs/changelogs/20260921103000_mutation-attribute-allowlists.md +1 -1
- data/docs/changelogs/20260921111000_release-0-3-0.md +1 -1
- data/docs/changelogs/20260921112800_drop-standard-rubocop-direct.md +1 -1
- data/docs/changelogs/20260921120000_graphql-floor-and-activeadmin-4.md +1 -1
- data/docs/changelogs/20261010091415_graphql-resource-enabled-default.md +1 -1
- data/docs/changelogs/20261010103800_release-0-3-1.md +1 -1
- data/docs/changelogs/20261010110600_graphql-identity-dsl.md +4 -0
- data/docs/changelogs/20261010111800_release-0-3-2.md +1 -1
- data/docs/changelogs/20261012050051_graphql-surface-toggles.md +1 -1
- data/docs/changelogs/20261012064500_graphql-capabilities.md +1 -1
- data/docs/changelogs/20261012113500_release-0-3-3.md +1 -1
- data/docs/changelogs/20261012200000_host-customization-hooks.md +5 -1
- data/docs/changelogs/20261013080000_release-0-4-0.md +1 -1
- data/docs/changelogs/20261103145000_release-0-4-1.md +26 -0
- data/docs/graphql-api.md +107 -102
- data/docs/issues/20260907141000_engineering-and-dependency-audit.md +1 -1
- data/docs/issues/20260917123253_ci-drop-automatic-dependency-audit.md +1 -1
- data/docs/issues/20260921103000_mutation-attribute-allowlists.md +1 -1
- data/docs/issues/20260921104400_convention-alignment-audit.md +7 -7
- data/docs/issues/20260921114500_dependency-audit.md +13 -13
- data/docs/issues/20260921115500_file-length-metrics.md +1 -1
- data/docs/issues/20261010111159_rails-composite-primary-keys-alignment.md +13 -13
- data/docs/issues/20261010111300_partitions-and-shards-support.md +3 -3
- data/docs/issues/20261010111500_graphql-federation-support.md +3 -3
- data/docs/issues/20261012200000_host-customization-gaps.md +6 -2
- data/docs/issues/20261103145000_engineering-prose-release-audit.md +39 -0
- data/docs/plan/20260817201500_rfc-starter.md +1 -1
- data/docs/reviews/20261028_engineering-audit-release-preparation.md +24 -0
- data/docs/reviews/20261103145000_engineering-prose-release-audit.md +38 -0
- data/lib/active_admin/graphql/schema_builder/mutation_create.rb +20 -20
- data/lib/active_admin/graphql/schema_builder/mutation_update_destroy.rb +2 -4
- data/lib/active_admin/graphql/schema_builder/query_type_member.rb +1 -4
- data/lib/active_admin/graphql/schema_builder/query_type_registered.rb +1 -4
- data/lib/active_admin/graphql/version.rb +1 -1
- metadata +5 -1
data/docs/graphql-api.md
CHANGED
|
@@ -31,11 +31,11 @@ want:
|
|
|
31
31
|
ActiveAdmin.setup do |config|
|
|
32
32
|
config.namespace :admin do |admin|
|
|
33
33
|
admin.graphql = true
|
|
34
|
-
# Optional
|
|
34
|
+
# Optional - default is "graphql", i.e. POST /admin/graphql
|
|
35
35
|
# admin.graphql_path = "graphql"
|
|
36
|
-
# Optional
|
|
36
|
+
# Optional - set false so only resources with a graphql block enter the schema
|
|
37
37
|
# admin.graphql_resource_enabled_default = false
|
|
38
|
-
# Optional
|
|
38
|
+
# Optional - trim always-on surfaces for a narrow API
|
|
39
39
|
# admin.graphql_policies_enabled = false
|
|
40
40
|
# admin.graphql_registered_resource_enabled = false
|
|
41
41
|
# admin.graphql_belongs_to_associations_enabled = false
|
|
@@ -50,87 +50,87 @@ Run `bin/rails active_admin:install` or reload routes if needed so
|
|
|
50
50
|
|
|
51
51
|
Each namespace inherits these options (defaults in parentheses):
|
|
52
52
|
|
|
53
|
-
* `graphql`
|
|
54
|
-
* `graphql_resource_enabled_default`
|
|
53
|
+
* `graphql` - set to `true` to mount the endpoint (`false` by default).
|
|
54
|
+
* `graphql_resource_enabled_default` - whether each registered ActiveRecord
|
|
55
55
|
resource is included in the schema without a `graphql` block (`true` by
|
|
56
56
|
default, matching 0.3.x). Set to `false` for opt-in: only resources that call
|
|
57
57
|
`graphql { }` (or `graphql { enable! }`) appear in the schema. `disable!`
|
|
58
58
|
still omits a resource.
|
|
59
|
-
* `graphql_queries_enabled_default`
|
|
59
|
+
* `graphql_queries_enabled_default` - seed for per-resource read fields
|
|
60
60
|
(`true` by default): named list/show fields and membership in
|
|
61
61
|
`registered_resource` / `ActiveAdminRegisteredResource`. Set `false` and use
|
|
62
62
|
`enable_queries!` for opt-in reads. Object types may still exist for mutations.
|
|
63
|
-
* `graphql_mutations_enabled_default`
|
|
63
|
+
* `graphql_mutations_enabled_default` - seed for per-resource CRUD mutations
|
|
64
64
|
(`true` by default). Set `false` and use `enable_mutations!` for opt-in writes.
|
|
65
|
-
* `graphql_run_actions_enabled_default`
|
|
65
|
+
* `graphql_run_actions_enabled_default` - seed for batch/member/collection
|
|
66
66
|
action mutations (`true` by default).
|
|
67
|
-
* `graphql_policies_enabled`
|
|
67
|
+
* `graphql_policies_enabled` - publish `activeadmin_policies` query fields and
|
|
68
68
|
allow per-object policy fields (`true` by default).
|
|
69
|
-
* `graphql_policies_enabled_default`
|
|
69
|
+
* `graphql_policies_enabled_default` - seed for per-resource `policies_enabled`
|
|
70
70
|
(`true` by default). Use `enable_policies!` / `disable_policies!` per resource.
|
|
71
|
-
* `graphql_policy_adapter`
|
|
71
|
+
* `graphql_policy_adapter` - class that builds `activeadmin_policies` payloads
|
|
72
72
|
(`ActiveAdmin::GraphQL::PolicyAdapter` by default). Set a subclass (or constant
|
|
73
73
|
`String`) to replace payload logic; the default adapter still honors
|
|
74
74
|
`graphql_policy_actions` / `graphql_policy_action_mapper` /
|
|
75
75
|
`graphql_policy_extra` / `graphql_policy_transform`.
|
|
76
|
-
* `graphql_registered_resource_enabled`
|
|
76
|
+
* `graphql_registered_resource_enabled` - include `registered_resource` and the
|
|
77
77
|
`ActiveAdminRegisteredResource` union when at least one queryable resource
|
|
78
78
|
exists (`true` by default).
|
|
79
|
-
* `graphql_belongs_to_associations_enabled`
|
|
79
|
+
* `graphql_belongs_to_associations_enabled` - wire non-polymorphic `belongs_to`
|
|
80
80
|
fields between registered resource types (`true` by default).
|
|
81
|
-
* `graphql_path`
|
|
82
|
-
* `graphql_multiplex_max`
|
|
81
|
+
* `graphql_path` - path segment under the namespace mount (`"graphql"`).
|
|
82
|
+
* `graphql_multiplex_max` - maximum operations per multiplexed JSON array
|
|
83
83
|
request (`20`).
|
|
84
|
-
* `graphql_max_complexity`
|
|
84
|
+
* `graphql_max_complexity` - passed to graphql-ruby `max_complexity` (`300` by
|
|
85
85
|
default; set a higher value if legitimate queries are rejected). Set to
|
|
86
86
|
`nil` to disable the limit.
|
|
87
|
-
* `graphql_max_depth`
|
|
87
|
+
* `graphql_max_depth` - passed to `max_depth` (`18` by default). Set to `nil`
|
|
88
88
|
to disable.
|
|
89
|
-
* `graphql_batch_action_max_ids`
|
|
89
|
+
* `graphql_batch_action_max_ids` - maximum length of the `ids` argument on
|
|
90
90
|
`*_batch_action` mutations (`5000` by default; set `0` to disable the cap).
|
|
91
|
-
* `graphql_default_page_size` / `graphql_default_max_page_size`
|
|
91
|
+
* `graphql_default_page_size` / `graphql_default_max_page_size` - schema
|
|
92
92
|
connection defaults (`25` / `100`); needed for graphql-ruby complexity scoring
|
|
93
93
|
on connection fields when `max_complexity` is enabled.
|
|
94
|
-
* `graphql_dataloader`
|
|
94
|
+
* `graphql_dataloader` - graphql-ruby dataloader plugin (`nil` = use
|
|
95
95
|
`GraphQL::Dataloader`). Set to `GraphQL::Dataloader::AsyncDataloader` when
|
|
96
96
|
the [`async` gem](https://github.com/socketry/async) is loaded if you want
|
|
97
97
|
parallel I/O from custom `GraphQL::Dataloader::Source` `#fetch` methods.
|
|
98
|
-
* `graphql_visibility`
|
|
98
|
+
* `graphql_visibility` - `nil` by default (no graphql-ruby visibility plugin).
|
|
99
99
|
Set to `true` to use [`GraphQL::Schema::Visibility`](https://graphql-ruby.org/schema/visibility.html)
|
|
100
100
|
with default options, or pass a `Hash` of visibility options (`profiles:`,
|
|
101
|
-
`dynamic:`, `preload:`, `migration_errors:`,
|
|
102
|
-
* `graphql_visibility_profile`
|
|
101
|
+
`dynamic:`, `preload:`, `migration_errors:`, ...).
|
|
102
|
+
* `graphql_visibility_profile` - when using named visibility profiles, optional
|
|
103
103
|
default `context[:visibility_profile]` for each HTTP request (symbols accepted).
|
|
104
|
-
* `graphql_schema_visible`
|
|
104
|
+
* `graphql_schema_visible` - optional `Proc` `(context, meta) -> Boolean` when
|
|
105
105
|
`graphql_visibility` is enabled; see Schema visibility below.
|
|
106
|
-
* `graphql_capabilities`
|
|
106
|
+
* `graphql_capabilities` - optional `Proc` `(context) -> Enumerable` of capability
|
|
107
107
|
names for the request (RFC 0008). Normalized into `context[:capabilities]`.
|
|
108
108
|
Cannot be combined with named `graphql_visibility` `profiles:`; schema build
|
|
109
109
|
forces `dynamic: true` and omits `visibility_profile` from the request context
|
|
110
110
|
so introspection uses the live capability set.
|
|
111
|
-
* `graphql_field_capability_mode_default`
|
|
111
|
+
* `graphql_field_capability_mode_default` - `:omit` or `:null` when a field has a
|
|
112
112
|
capability but no per-field mode (RFC 0009). Default `:omit`.
|
|
113
|
-
* `graphql_field_visible`
|
|
113
|
+
* `graphql_field_visible` - optional `Proc` `(context, meta) -> Boolean` to omit
|
|
114
114
|
fields after capability checks (RFC 0009). Meta includes `graphql_type_name`,
|
|
115
115
|
`field_name`, and `resource` when known.
|
|
116
|
-
* `graphql_run_action_audit`
|
|
116
|
+
* `graphql_run_action_audit` - optional `Proc` `(context, meta) -> void` after
|
|
117
117
|
member-action dry-run, refused preview, or completed run (RFC 0010).
|
|
118
|
-
* `graphql_collection_query_policy`
|
|
118
|
+
* `graphql_collection_query_policy` - optional `Proc` `(context, meta) -> void`
|
|
119
119
|
at the start of collection resolve (RFC 0011). Meta includes `aa_resource`,
|
|
120
120
|
`q`, `scope`, `order`, and `filter`.
|
|
121
|
-
* `graphql_member_action_capability_default`
|
|
121
|
+
* `graphql_member_action_capability_default` - optional capability symbol applied
|
|
122
122
|
to member-action mutation fields when the resource map has no entry (RFC 0012).
|
|
123
|
-
* `graphql_batch_action_capability_default`
|
|
123
|
+
* `graphql_batch_action_capability_default` - same for the aggregate batch-action
|
|
124
124
|
field and per-action authorize checks (RFC 0012).
|
|
125
|
-
* `graphql_collection_action_capability_default`
|
|
125
|
+
* `graphql_collection_action_capability_default` - same for collection-action
|
|
126
126
|
mutation fields (RFC 0012).
|
|
127
|
-
* `graphql_configure_schema`
|
|
127
|
+
* `graphql_configure_schema` - `Proc` receiving the schema class after build
|
|
128
128
|
(extensions, extra types, and so on).
|
|
129
129
|
|
|
130
130
|
### GraphQL::Dataloader
|
|
131
131
|
|
|
132
132
|
The namespace schema calls `schema.use` with the configured dataloader (see
|
|
133
|
-
`graphql_dataloader` above). [graphql-ruby
|
|
133
|
+
`graphql_dataloader` above). [graphql-ruby's
|
|
134
134
|
dataloader](https://graphql-ruby.org/dataloader/overview.html) batches external
|
|
135
135
|
work across sibling fields using Fibers; each HTTP request gets its own
|
|
136
136
|
dataloader instance (available as `context.dataloader` inside resolvers).
|
|
@@ -152,12 +152,12 @@ Global / Relay-style IDs are not generated by Active Admin itself.
|
|
|
152
152
|
### Schema visibility (`GraphQL::Schema::Visibility`)
|
|
153
153
|
|
|
154
154
|
When `graphql_visibility` is set, the namespace schema calls
|
|
155
|
-
`schema.use(GraphQL::Schema::Visibility,
|
|
155
|
+
`schema.use(GraphQL::Schema::Visibility, ...)` so introspection and validation
|
|
156
156
|
respect [visibility](https://graphql-ruby.org/schema/visibility.html).
|
|
157
157
|
|
|
158
158
|
Set `graphql_schema_visible` to a proc that receives the GraphQL `context`
|
|
159
159
|
and a `meta` hash and returns truthy to keep the member visible. The hash
|
|
160
|
-
always includes `:kind`, and often `:graphql_type_name` (the resource
|
|
160
|
+
always includes `:kind`, and often `:graphql_type_name` (the resource's GraphQL
|
|
161
161
|
basename), `:resource` (`ActiveAdmin::Resource`), and other keys:
|
|
162
162
|
|
|
163
163
|
| `kind` | Meaning |
|
|
@@ -165,29 +165,29 @@ basename), `:resource` (`ActiveAdmin::Resource`), and other keys:
|
|
|
165
165
|
| `:resource_interface` | `ActiveAdminResource` interface |
|
|
166
166
|
| `:resource_object` | Resource object type |
|
|
167
167
|
| `:resource_enum` | Rails enum type; `meta` includes `:column` |
|
|
168
|
-
| `:input_object` | Create/update/where/list-filter input; `meta` includes `:role` (`:create_input`,
|
|
168
|
+
| `:input_object` | Create/update/where/list-filter input; `meta` includes `:role` (`:create_input`, ...) |
|
|
169
169
|
| `:registered_resource_union` | `ActiveAdminRegisteredResource` union |
|
|
170
170
|
| `:run_action_payload` | Batch/member/collection action payload type |
|
|
171
171
|
| `:query_registered_resource` | `registered_resource` query field |
|
|
172
172
|
| `:query_collection_field` / `:query_member_field` | Resource list/detail fields; `meta` includes `:field_name` |
|
|
173
173
|
| `:query_page_field` | Custom `register_page` field; `meta` includes `:page` |
|
|
174
|
-
| `:mutation_create`, `:mutation_update`, `:mutation_delete`,
|
|
174
|
+
| `:mutation_create`, `:mutation_update`, `:mutation_delete`, ... | CRUD and action mutations |
|
|
175
175
|
|
|
176
176
|
Root `Query` / `Mutation` fields are defined with
|
|
177
177
|
`ActiveAdmin::GraphQL::SchemaField`, which supports a `visibility:` keyword:
|
|
178
178
|
a metadata `Hash` (same shape as the `meta` argument above) for
|
|
179
179
|
`graphql_schema_visible`, not a graphql-ruby core option. Resource `graphql`
|
|
180
180
|
`configure` blocks use that field class too, so custom fields may pass
|
|
181
|
-
`visibility: {
|
|
181
|
+
`visibility: { ... }` when you want the hook to run.
|
|
182
182
|
|
|
183
183
|
You can also subclass your own `GraphQL::Schema::Object` / `Field` types in
|
|
184
|
-
`graphql_configure_schema` and implement `visible?` there; Active Admin
|
|
184
|
+
`graphql_configure_schema` and implement `visible?` there; Active Admin's
|
|
185
185
|
helpers call `super` first so those implementations compose.
|
|
186
186
|
|
|
187
187
|
Interfaces and unions: graphql-ruby may keep an interface or union visible
|
|
188
188
|
when all members are hidden unless you return `false` from
|
|
189
189
|
`graphql_schema_visible` for `:resource_interface` or `:registered_resource_union`
|
|
190
|
-
(or implement `.visible?` on custom types). See graphql-ruby
|
|
190
|
+
(or implement `.visible?` on custom types). See graphql-ruby's visibility migration
|
|
191
191
|
notes for edge cases.
|
|
192
192
|
|
|
193
193
|
## Making requests
|
|
@@ -200,11 +200,11 @@ Send JSON with `query` and optional `variables`. For
|
|
|
200
200
|
be a JSON array of such objects; the size is limited by `graphql_multiplex_max`.
|
|
201
201
|
|
|
202
202
|
Requests are handled by `ActiveAdmin::GraphqlController` (an engine controller,
|
|
203
|
-
not a generated `Admin
|
|
203
|
+
not a generated `Admin::...` subclass).
|
|
204
204
|
|
|
205
205
|
### CSRF and cookie sessions
|
|
206
206
|
|
|
207
|
-
`GraphqlController` uses Rails
|
|
207
|
+
`GraphqlController` uses Rails' default CSRF protection
|
|
208
208
|
(`protect_from_forgery with: :exception`). Clients that rely on session cookies
|
|
209
209
|
(for example a typical Devise session) must submit a valid CSRF token with each
|
|
210
210
|
`POST`, such as the `authenticity_token` used by the HTML admin. API-style
|
|
@@ -251,6 +251,11 @@ resource model (`authorized?` with the model class, in the same way as
|
|
|
251
251
|
collection queries). They then run the same controller actions and blocks as the
|
|
252
252
|
UI, including any `authorize!` or `authorize_resource!` calls.
|
|
253
253
|
|
|
254
|
+
When a record exists but instance-level read is denied, singular member and
|
|
255
|
+
`registered_resource` queries return `null` (same shape as a missing id). Update
|
|
256
|
+
and destroy mutations return the GraphQL error `not found` for the same case.
|
|
257
|
+
Class-level denials still raise `not authorized ...`.
|
|
258
|
+
|
|
254
259
|
See the ActiveAdmin guide [Authorization adapter](https://activeadmin.info/13-authorization-adapter) for adapter setup; the same rules apply to GraphQL.
|
|
255
260
|
|
|
256
261
|
Policy preflight fields (`activeadmin_policies`, `activeadmin_policies_for`, and
|
|
@@ -286,7 +291,7 @@ end
|
|
|
286
291
|
|
|
287
292
|
Kwargs (`fields:`, `queries:`, `mutations:`, `member_actions:`,
|
|
288
293
|
`batch_actions:`, `collection_actions:`) work without a block. Query aliases:
|
|
289
|
-
`index` / `list`
|
|
294
|
+
`index` / `list` -> collection, `show` -> member. Mutation alias: `delete` ->
|
|
290
295
|
`destroy`. Run-action sugar builds keys like `member_publish`.
|
|
291
296
|
|
|
292
297
|
Grant capabilities per request with `graphql_capabilities`. Map OAuth scopes or
|
|
@@ -364,7 +369,7 @@ omit `created_at` and `updated_at`.
|
|
|
364
369
|
GraphQL `id` always comes from `ActiveAdminResource` (`ID!`). An ActiveRecord
|
|
365
370
|
`id` column is never added as a second field. When `self.primary_key` is blank
|
|
366
371
|
but the model still has an `id` column (common for database views that project
|
|
367
|
-
|
|
372
|
+
`... AS id`), that column supplies the GraphQL `id` value. When the model has
|
|
368
373
|
neither a primary key nor an `id` column, declare GraphQL identity on the
|
|
369
374
|
resource (RFC 0007), set `self.primary_key` on the model, or omit the resource
|
|
370
375
|
with `graphql { disable! }`. A single-column primary key named something other
|
|
@@ -384,7 +389,7 @@ end
|
|
|
384
389
|
```
|
|
385
390
|
|
|
386
391
|
With `separator: ":"`, GraphQL `id` is `entry_type:entry_id:event_type`. Keep
|
|
387
|
-
the model
|
|
392
|
+
the model's `def id` (if any) in the same shape so HTML and GraphQL share
|
|
388
393
|
member ids. Without `separator`, multi-column identity uses the same JSON
|
|
389
394
|
object string as composite ActiveRecord primary keys.
|
|
390
395
|
|
|
@@ -393,19 +398,19 @@ object string as composite ActiveRecord primary keys.
|
|
|
393
398
|
For models with `self.primary_key = [:book_code, :seq]` (and no separate `id`
|
|
394
399
|
column), Active Admin treats GraphQL as follows:
|
|
395
400
|
|
|
396
|
-
* `id` on the object type
|
|
401
|
+
* `id` on the object type - JSON object string with all key columns in
|
|
397
402
|
model order, for example `{"book_code":"CPK","seq":7}`. This is the GraphQL
|
|
398
403
|
wire format. It is not the Rails form/URL underscore packing described in
|
|
399
404
|
the Composite Primary Keys guide (`/books/2_25` with
|
|
400
405
|
`params.extract_value(:id)`).
|
|
401
|
-
* Readable fields
|
|
406
|
+
* Readable fields - each primary-key column is also exposed as its own field
|
|
402
407
|
(in addition to `id`) so clients can load scalars without parsing JSON.
|
|
403
|
-
* `LibraryEditionWhereInput` (and similar)
|
|
408
|
+
* `LibraryEditionWhereInput` (and similar) - either optional `id` (that JSON
|
|
404
409
|
string) or every primary-key column; `id` remains required when there is
|
|
405
410
|
only one key column.
|
|
406
|
-
* Singular query field
|
|
411
|
+
* Singular query field - pass the JSON `id`, pass `where`, or pass one
|
|
407
412
|
GraphQL argument per primary-key column.
|
|
408
|
-
* Create mutations
|
|
413
|
+
* Create mutations - composite key attributes stay included in create
|
|
409
414
|
inputs (unlike single `id` tables, where the key is omitted from assignable
|
|
410
415
|
attributes).
|
|
411
416
|
|
|
@@ -414,8 +419,8 @@ composite ids from `params[:id]` or from individual primary-key params. Stock
|
|
|
414
419
|
ActiveAdmin 3.x only passes a single `params[:id]` into `find`; an ActiveAdmin
|
|
415
420
|
fork (or patch) that implements composite-aware `find_resource` keeps the
|
|
416
421
|
admin UI aligned with GraphQL. After decoding the GraphQL JSON `id`, the gem
|
|
417
|
-
uses Rails
|
|
418
|
-
`where(primary_key => [tuple,
|
|
422
|
+
uses Rails' array/tuple conventions for `Relation#find` and
|
|
423
|
+
`where(primary_key => [tuple, ...])` as in the guide.
|
|
419
424
|
|
|
420
425
|
The gem ships `ActiveAdmin::PrimaryKey` when the core constant is missing
|
|
421
426
|
(upstream). A fork may define `PrimaryKey` and extended `find_resource` in
|
|
@@ -428,18 +433,18 @@ Alignment notes versus the Rails guide:
|
|
|
428
433
|
|
|
429
434
|
These align with REST index parameters where possible:
|
|
430
435
|
|
|
431
|
-
* `filter`
|
|
432
|
-
predicates as JSON
|
|
433
|
-
* `scope`
|
|
436
|
+
* `filter` - optional `PostListFilterInput` with `scope`, `order`, `q` (Ransack
|
|
437
|
+
predicates as JSON - kept as JSON because predicate keys are open-ended), and the nested parent id when `belongs_to` applies.
|
|
438
|
+
* `scope` - menu scope id (string); still accepted on the field for backward
|
|
434
439
|
compatibility.
|
|
435
|
-
* `q`
|
|
436
|
-
* `order`
|
|
437
|
-
* Parent foreign key
|
|
440
|
+
* `q` - Ransack predicates (JSON object).
|
|
441
|
+
* `order` - index sort string (for example `id_desc`).
|
|
442
|
+
* Parent foreign key - when the resource uses `belongs_to`, the parent param
|
|
438
443
|
(for example `user_id`) stays available on the connection field as today.
|
|
439
444
|
|
|
440
445
|
### Singular query arguments
|
|
441
446
|
|
|
442
|
-
* `where`
|
|
447
|
+
* `where` - `PostWhereInput` with required `id` (single-key tables) or,
|
|
443
448
|
for composite keys, `id` (JSON) and/or each key column; optional parent ids for
|
|
444
449
|
nested resources.
|
|
445
450
|
* Legacy `id` / parent arguments behave as before (composite models also accept
|
|
@@ -449,12 +454,12 @@ These align with REST index parameters where possible:
|
|
|
449
454
|
|
|
450
455
|
Typical names for a `Post` resource:
|
|
451
456
|
|
|
452
|
-
* `create_post(input: PostCreateInput!)`
|
|
457
|
+
* `create_post(input: PostCreateInput!)` - attribute fields match assignable
|
|
453
458
|
columns minus `created_at` / `updated_at` unless listed in `permit_params`
|
|
454
459
|
(and the nested parent param when `belongs_to` is configured).
|
|
455
460
|
* `update_post(where: PostWhereInput!, input: PostUpdateInput!)`
|
|
456
|
-
* `delete_post(where: PostWhereInput!)`
|
|
457
|
-
* `destroy_post(where: PostWhereInput!)`
|
|
461
|
+
* `delete_post(where: PostWhereInput!)` - kept for existing clients.
|
|
462
|
+
* `destroy_post(where: PostWhereInput!)` - Rails / ActiveAdmin action name; same resolver as `delete_post`.
|
|
458
463
|
|
|
459
464
|
Nested resources require the parent id on `where`, `input`, or list `filter`
|
|
460
465
|
when the association is required.
|
|
@@ -465,39 +470,39 @@ If you are updating clients that targeted an older embedded GraphQL integration
|
|
|
465
470
|
|
|
466
471
|
* Rails enum GraphQL names use an `Enum` infix (for example `PostEnumStatus`, not `PostStatus`). Update persisted operations, codegen, and fragments to match; see Rails enum columns below.
|
|
467
472
|
|
|
468
|
-
* CRUD mutations use typed `input` and `where` arguments (`PostCreateInput`, `PostWhereInput`,
|
|
473
|
+
* CRUD mutations use typed `input` and `where` arguments (`PostCreateInput`, `PostWhereInput`, ...), not a single loose `attributes` JSON object and bare `id` on update/delete. List/detail fields may use `where` / `filter` input objects; legacy scalar arguments on fields are unchanged where still exposed.
|
|
469
474
|
|
|
470
|
-
* `registered_resource(path:
|
|
475
|
+
* `registered_resource(path: ...)`, batch `inputs`, and member/collection `params` use `[ActiveAdminKeyValuePair!]` (a list of `{ key, value }` strings), not arbitrary JSON objects. Express maps as list items; duplicate keys keep the last value. Ransack `q` (on list `filter` / field args) stays a JSON object.
|
|
471
476
|
|
|
472
|
-
These rules match the current schema described in this guide. The core `activeadmin` gem
|
|
477
|
+
These rules match the current schema described in this guide. The core `activeadmin` gem's `UPGRADING.md` may only mention them if you use a fork that references this extension.
|
|
473
478
|
|
|
474
479
|
### `registered_resource` query
|
|
475
480
|
|
|
476
481
|
`registered_resource(type_name: String!, id: ID!, path: [ActiveAdminKeyValuePair!])`
|
|
477
482
|
returns `ActiveAdminRegisteredResource`, the union of all resource object types in
|
|
478
|
-
the namespace. Pass nested parent route params as ordered `path: [{ key: "user_id", value: "1" },
|
|
483
|
+
the namespace. Pass nested parent route params as ordered `path: [{ key: "user_id", value: "1" }, ...]`
|
|
479
484
|
(same keys as REST path segments). Resolve with inline fragments on concrete types.
|
|
480
485
|
|
|
481
|
-
`ActiveAdminKeyValuePair` is `{ key: String!, value: String! }`
|
|
486
|
+
`ActiveAdminKeyValuePair` is `{ key: String!, value: String! }` - flat strings only, like query/form fields.
|
|
482
487
|
|
|
483
488
|
### Batch, member, and collection actions
|
|
484
489
|
|
|
485
490
|
For a route key of `posts`, fields look like:
|
|
486
491
|
|
|
487
|
-
* `posts_batch_action(batch_action: String!, ids: [ID!]!, inputs: [ActiveAdminKeyValuePair!],
|
|
492
|
+
* `posts_batch_action(batch_action: String!, ids: [ID!]!, inputs: [ActiveAdminKeyValuePair!], ...)` -
|
|
488
493
|
runs the registered batch action; `inputs` is converted to `batch_action_inputs` (flat key/value map)
|
|
489
494
|
like the HTML form. Omitted when batch actions are disabled or none are registered.
|
|
490
|
-
* `posts_member_action(action: String!, id: ID!, params: [ActiveAdminKeyValuePair!],
|
|
495
|
+
* `posts_member_action(action: String!, id: ID!, params: [ActiveAdminKeyValuePair!], ...)` -
|
|
491
496
|
aggregate field: pick the `member_action` by `action` string (same as today).
|
|
492
|
-
* One GraphQL field per registered action
|
|
497
|
+
* One GraphQL field per registered action - `{plural}_member_{action_name}` with
|
|
493
498
|
underscores (e.g. `posts_member_publish`, `posts_member_append_title_bang`): same
|
|
494
499
|
`id`, `params`, and parent ids as the aggregate field, without an `action:` argument.
|
|
495
|
-
Use `graphql { member_action_mutation(:publish) {
|
|
496
|
-
`resolve`, and extra `arguments {
|
|
497
|
-
* `posts_collection_action(action: String!, params: [ActiveAdminKeyValuePair!],
|
|
500
|
+
Use `graphql { member_action_mutation(:publish) { ... } }` to set return type,
|
|
501
|
+
`resolve`, and extra `arguments { ... }` for that action only.
|
|
502
|
+
* `posts_collection_action(action: String!, params: [ActiveAdminKeyValuePair!], ...)` -
|
|
498
503
|
aggregate collection actions by name.
|
|
499
504
|
* Per collection action: `{plural}_collection_{action_name}` (e.g.
|
|
500
|
-
`posts_collection_posts_count`). Configure with `collection_action_mutation(:posts_count) {
|
|
505
|
+
`posts_collection_posts_count`). Configure with `collection_action_mutation(:posts_count) { ... }`.
|
|
501
506
|
|
|
502
507
|
Action names are validated against registered definitions; arbitrary controller
|
|
503
508
|
methods are not exposed.
|
|
@@ -541,27 +546,27 @@ ActiveAdmin.register Post do
|
|
|
541
546
|
end
|
|
542
547
|
```
|
|
543
548
|
|
|
544
|
-
* `enable!`
|
|
549
|
+
* `enable!` - include this resource when `graphql_resource_enabled_default` is
|
|
545
550
|
`false`. An empty `graphql` block has the same effect.
|
|
546
|
-
* `disable!`
|
|
547
|
-
* `enable_queries!` / `disable_queries!`
|
|
551
|
+
* `disable!` - resource is not included in Query or Mutation.
|
|
552
|
+
* `enable_queries!` / `disable_queries!` - list/show fields and
|
|
548
553
|
`registered_resource` membership for this resource.
|
|
549
|
-
* `enable_mutations!` / `disable_mutations!`
|
|
550
|
-
* `enable_run_actions!` / `disable_run_actions!`
|
|
554
|
+
* `enable_mutations!` / `disable_mutations!` - create/update/delete mutations.
|
|
555
|
+
* `enable_run_actions!` / `disable_run_actions!` - batch/member/collection
|
|
551
556
|
action mutations.
|
|
552
|
-
* `enable_policies!` / `disable_policies!`
|
|
557
|
+
* `enable_policies!` / `disable_policies!` - object `activeadmin_policies` and
|
|
553
558
|
inclusion in the `activeadmin_policies` resources matrix.
|
|
554
|
-
* `identity`
|
|
559
|
+
* `identity` - declare GraphQL id columns (and optional `separator`, `encode`,
|
|
555
560
|
`decode`) when the model has no ActiveRecord primary key and no `id` column
|
|
556
561
|
(RFC 0007).
|
|
557
|
-
* `type_name` (or `graphql_name`)
|
|
562
|
+
* `type_name` (or `graphql_name`) - overrides the default GraphQL type name
|
|
558
563
|
derived from the model (object types, mutations, and Rails enum GraphQL
|
|
559
564
|
types use this basename).
|
|
560
|
-
* `only` / `except` (or `exclude`)
|
|
565
|
+
* `only` / `except` (or `exclude`) - restrict columns on object types. These
|
|
561
566
|
names also cap mutation inputs. This is not ActiveAdmin `only:` / `except:`
|
|
562
567
|
for controller actions (`action_item only: :show`). The primary key remains
|
|
563
568
|
readable as `id`.
|
|
564
|
-
* `permit_params` (or `permit`)
|
|
569
|
+
* `permit_params` (or `permit`) - restrict create and update input keys without
|
|
565
570
|
hiding query fields, same name as ActiveAdmin HTML `permit_params`. Nested
|
|
566
571
|
`create` / `update` blocks replace that shared list for one operation and
|
|
567
572
|
may set `resolve`. Names outside `only` / `except` are dropped. A static HTML
|
|
@@ -569,7 +574,7 @@ end
|
|
|
569
574
|
unset. A request-time HTML `permit_params` block is not copied. With no list
|
|
570
575
|
set, mutation inputs omit `created_at` and `updated_at`. Empty `permit_params`
|
|
571
576
|
yields an input with no column arguments.
|
|
572
|
-
* `configure`
|
|
577
|
+
* `configure` - `field` and resolver methods are evaluated on the generated
|
|
573
578
|
object type class.
|
|
574
579
|
|
|
575
580
|
### Run action return types (batch / member / collection mutations)
|
|
@@ -578,8 +583,8 @@ Return type and optional resolver for each kind live together on
|
|
|
578
583
|
`ActiveAdmin::GraphQL::RunActionMutationConfig` (`payload_type`, `resolve_proc`),
|
|
579
584
|
exposed through the DSL in a graphql-ruby-like way.
|
|
580
585
|
|
|
581
|
-
Use a `GraphQL::Schema::Object` subclass
|
|
582
|
-
`ActiveAdmin::GraphQL::RunActionPayload`
|
|
586
|
+
Use a `GraphQL::Schema::Object` subclass - typically subclass
|
|
587
|
+
`ActiveAdmin::GraphQL::RunActionPayload` - then add fields and resolver methods.
|
|
583
588
|
The mutation object passed to field methods is always
|
|
584
589
|
`RunActionPayload::Result` (`ok`, `status`, `location`, `body`).
|
|
585
590
|
|
|
@@ -614,7 +619,7 @@ graphql do
|
|
|
614
619
|
end
|
|
615
620
|
```
|
|
616
621
|
|
|
617
|
-
Call the named field as `posts_member_send_invoice(id: "...", note: "
|
|
622
|
+
Call the named field as `posts_member_send_invoice(id: "...", note: "...")`. Extra
|
|
618
623
|
arguments are merged with `params` for the controller and passed as keyword args
|
|
619
624
|
to a custom `resolve` block. With `dry_run: true`, the field gains a Boolean
|
|
620
625
|
`dry_run` argument: preview runs first, dry-run returns without
|
|
@@ -632,7 +637,7 @@ Custom mutations in `graphql_configure_schema` may use
|
|
|
632
637
|
return without calling `resolve`; without `preview`, dry-run still calls
|
|
633
638
|
`resolve` with `dry_run: true`.
|
|
634
639
|
|
|
635
|
-
With no symbol argument, `member_action_mutation {
|
|
640
|
+
With no symbol argument, `member_action_mutation { ... }` configures only the
|
|
636
641
|
aggregate `posts_member_action` field. With a symbol, it configures the
|
|
637
642
|
per-action field `posts_member_<name>`.
|
|
638
643
|
|
|
@@ -648,7 +653,7 @@ One-shot aliases (same underlying config):
|
|
|
648
653
|
| `batch_action_run_action_payload_type(MyType)` | Same as `batch_action_mutation { type(MyType) }`. |
|
|
649
654
|
| `member_action_run_action_payload_type(MyType)` | Same as `member_action_mutation { type(MyType) }`. |
|
|
650
655
|
| `collection_action_run_action_payload_type(MyType)` | Same as `collection_action_mutation { type(MyType) }`. |
|
|
651
|
-
| `resolve_batch_action {
|
|
656
|
+
| `resolve_batch_action { ... }` | Same as `batch_action_mutation { resolve { ... } }` (and likewise for member/collection). |
|
|
652
657
|
|
|
653
658
|
Per-kind `type` wins over `run_action_payload_type`; any unset kind falls back
|
|
654
659
|
to `run_action_payload_type`, then `ActiveAdminRunActionPayload`. Set
|
|
@@ -667,16 +672,16 @@ replace the Ruby body that loads data or runs a mutation (similar in spirit to
|
|
|
667
672
|
overriding `find_resource` / `find_collection` rather than inventing new field
|
|
668
673
|
names):
|
|
669
674
|
|
|
670
|
-
| DSL method | Replaces default
|
|
675
|
+
| DSL method | Replaces default ... |
|
|
671
676
|
|------------|-------------------|
|
|
672
|
-
| `resolve_index` (alias `resolve_collection`) | List connection resolver; must return an `ActiveRecord::Relation` (or compatible). Receives `proxy`, `context`, `auth`, `aa_resource`, `graph_params`, and the list field arguments (`filter`, `scope`, `q`, `order`, parent ids,
|
|
677
|
+
| `resolve_index` (alias `resolve_collection`) | List connection resolver; must return an `ActiveRecord::Relation` (or compatible). Receives `proxy`, `context`, `auth`, `aa_resource`, `graph_params`, and the list field arguments (`filter`, `scope`, `q`, `order`, parent ids, ...). |
|
|
673
678
|
| `resolve_show` (alias `resolve_member`) | Singular field and `registered_resource` for this resource; must return a record or `nil`. Receives `proxy`, `id`, `graph_params`, and for the generated `post` field also `where` / `id_argument` when present. |
|
|
674
|
-
| `resolve_create` | After class-level create authorization: build and persist. Receives `proxy`, `input`, `attributes` (assignable slice), `context`, `auth`, `aa_resource`. Must return the created record; instance-level `authorized?` runs
|
|
679
|
+
| `resolve_create` | After class-level create authorization: build and persist inside a nested transaction. Receives `proxy`, `input`, `attributes` (assignable slice), `context`, `auth`, `aa_resource`. Must return the created record; instance-level `authorized?` runs before the transaction commits, so a denied hook persist rolls back when the hook shared that transaction. |
|
|
675
680
|
| `resolve_update` | After load and update authorization: apply changes. Receives `record`, `input`, `attributes`, plus `proxy`, `context`, `auth`, `aa_resource`. Must return the updated record. |
|
|
676
681
|
| `resolve_destroy` | After destroy authorization: delete or archive. Receives `record`, `proxy`, `context`, `auth`, `aa_resource`. Default is `record.destroy!`. |
|
|
677
|
-
| `resolve_batch_action` | Batch mutation; receives `batch_action`, `ids`, `inputs` (string-key `Hash` after converting GraphQL key/value list), `proxy`,
|
|
678
|
-
| `resolve_member_action` | Member-action mutation; receives `action`, `id`, `params` (string-key `Hash`), `proxy`,
|
|
679
|
-
| `resolve_collection_action` | Collection-action mutation; receives `action`, `params` (string-key `Hash`), `proxy`,
|
|
682
|
+
| `resolve_batch_action` | Batch mutation; receives `batch_action`, `ids`, `inputs` (string-key `Hash` after converting GraphQL key/value list), `proxy`, ... Default calls `ResourceQueryProxy#run_batch_action`. |
|
|
683
|
+
| `resolve_member_action` | Member-action mutation; receives `action`, `id`, `params` (string-key `Hash`), `proxy`, ... |
|
|
684
|
+
| `resolve_collection_action` | Collection-action mutation; receives `action`, `params` (string-key `Hash`), `proxy`, ... |
|
|
680
685
|
|
|
681
686
|
Standard authorization checks around each field or mutation still run; hooks
|
|
682
687
|
are for customizing how data is fetched or saved, not for skipping policy.
|
|
@@ -688,16 +693,16 @@ exposed as GraphQL enums. Each enum type is named
|
|
|
688
693
|
|
|
689
694
|
`{GraphQLTypeBasename}Enum{ColumnNameInPascalCase}`
|
|
690
695
|
|
|
691
|
-
where `GraphQLTypeBasename` is the resource
|
|
696
|
+
where `GraphQLTypeBasename` is the resource's GraphQL type name (from `type_name`
|
|
692
697
|
or the model name), and `ColumnNameInPascalCase` is the database attribute in
|
|
693
|
-
PascalCase (for example `notification_channel`
|
|
698
|
+
PascalCase (for example `notification_channel` -> `NotificationChannel`).
|
|
694
699
|
|
|
695
700
|
Examples:
|
|
696
701
|
|
|
697
|
-
* `User` + column `notification_channel`
|
|
698
|
-
* `UserNotification` + column `channel`
|
|
702
|
+
* `User` + column `notification_channel` -> `UserEnumNotificationChannel`
|
|
703
|
+
* `UserNotification` + column `channel` -> `UserNotificationEnumChannel`
|
|
699
704
|
|
|
700
|
-
Think of `PostEnumStatus` as the enum for `Post
|
|
705
|
+
Think of `PostEnumStatus` as the enum for `Post`'s `status` attribute, not as a
|
|
701
706
|
single merged word like `PostStatus`. Putting `Enum` immediately after the
|
|
702
707
|
resource basename (instead of a suffix such as `PostStatusEnum`) keeps the
|
|
703
708
|
basename and column distinct when both are camelized. That avoids the duplicates
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Participants
|
|
4
4
|
|
|
5
|
-
Andrei Makarov
|
|
5
|
+
Andrei Makarov (@amkisko)
|
|
6
6
|
|
|
7
7
|
## Decisions
|
|
8
8
|
|
|
@@ -22,12 +22,6 @@ GraphqlController logs namespace, operation name, and error_count without the qu
|
|
|
22
22
|
|
|
23
23
|
ResourceMethods lives in lib/active_admin/graphql/resource_methods.rb.
|
|
24
24
|
|
|
25
|
-
## Effects
|
|
26
|
-
|
|
27
|
-
First pass used create_only. Second pass replaced it after a convention check against graphql-ruby 2.6.7, Rails 8.1 nested_attributes update_only, upsert_all update_only, and ActiveAdmin 3.5.2 permit_params.
|
|
28
|
-
|
|
29
|
-
bundle exec rspec spec/requests/graphql_mutation_permit_params_spec.rb: 8 examples, 0 failures after the rename.
|
|
30
|
-
|
|
31
25
|
## Findings
|
|
32
26
|
|
|
33
27
|
Severity high. Confidence high. Location SchemaBuilder TypesInputs default create and update inputs. Why it matters: extra-field write of created_at on create, observed in spec/requests/graphql_mutation_permit_params_spec.rb. Evidence kind observed. Security disposition confirmed. Smallest credible fix: graphql { permit_params :title, :body } in the host app. Deeper fix: omit created_at and updated_at from default mutation inputs in a later RFC, matching ActiveAdmin generators/boilerplate.rb assignable_attributes.
|
|
@@ -46,6 +40,12 @@ Severity low. Confidence high. Location GraphqlController, no request correlatio
|
|
|
46
40
|
|
|
47
41
|
Severity low. Confidence high. Location lib/active_admin/graphql/integration.rb line count 176. Why it matters: file is above the 150 line preference. Evidence kind observed. Smallest credible fix: extract ResourceMethods. Not done this pass.
|
|
48
42
|
|
|
43
|
+
## Effects
|
|
44
|
+
|
|
45
|
+
First pass used create_only. Second pass replaced it after a convention check against graphql-ruby 2.6.7, Rails 8.1 nested_attributes update_only, upsert_all update_only, and ActiveAdmin 3.5.2 permit_params.
|
|
46
|
+
|
|
47
|
+
bundle exec rspec spec/requests/graphql_mutation_permit_params_spec.rb: 8 examples, 0 failures after the rename.
|
|
48
|
+
|
|
49
49
|
## Next
|
|
50
50
|
|
|
51
51
|
Findings from the 2026-09-21 audit pass are addressed except replacing CRUD return types with graphql-ruby payload objects, which would break RFC 0004 field types. Keep RFC 0006 Proposed. 0.3.0 metadata includes the graphql 2.6.9 floor and ActiveAdmin 4 Rails 8 matrix; tag and gem push wait on make release.
|
|
@@ -4,7 +4,7 @@ Full audit: recon, security, freshness, ecosystem. Depth reached: full for hot-p
|
|
|
4
4
|
|
|
5
5
|
## Participants
|
|
6
6
|
|
|
7
|
-
Andrei Makarov
|
|
7
|
+
Andrei Makarov (@amkisko)
|
|
8
8
|
|
|
9
9
|
## Decisions
|
|
10
10
|
|
|
@@ -20,18 +20,6 @@ Stay on ActiveAdmin 3.5.2. It is the latest stable on RubyGems. 4.0.0.beta23 (20
|
|
|
20
20
|
|
|
21
21
|
Do not reverse the 2026-09-17 choice to keep bundle-audit off test.yml. The on-demand workflow remains the gate. Makefile still has no audit target that mirrors that workflow.
|
|
22
22
|
|
|
23
|
-
## Effects
|
|
24
|
-
|
|
25
|
-
ruby-advisory-db update: 1245 advisories, last updated 2026-09-16 10:35:37 -0400, commit 44784c295391577f25d198a9205eae4ba73ec4da.
|
|
26
|
-
|
|
27
|
-
bundle-audit check failed on all four lockfiles with GHSA-rmxg-5p3r-j6hh (graphql 2.6.7, solution >= 2.6.9). No other scanner matches.
|
|
28
|
-
|
|
29
|
-
bundle outdated --strict on the root Gemfile listed 16 outdated specs. graphql 2.6.7 vs 2.6.10 is the only outdated hot-path direct runtime gem.
|
|
30
|
-
|
|
31
|
-
Libyears from Gemfile.lock vs RubyGems stable (compact-graph band: about 10 low, about 100 medium): 124 locked packages, 27 outdated, total lag 17.94 years, average 0.145 years per package, 6 packages one major behind (arbre, inherited_resources, json, marcel, diff-lcs, rubocop-capybara). Coverage floor in config/polyrun_coverage.yml is 85 percent line. No upgrade spike was run this pass.
|
|
32
|
-
|
|
33
|
-
No person-facing surface in this pass.
|
|
34
|
-
|
|
35
23
|
## Findings
|
|
36
24
|
|
|
37
25
|
Tier hot path direct. Kind security. Severity high. Confidence high. Package graphql 2.6.7. Why it matters: Marshal.load of unauthenticated parser cache files is RCE when parse_file runs. Evidence kind observed (bundle-audit, GHSA text, repo grep with no parse_file). Sources: GHSA-rmxg-5p3r-j6hh, ruby-advisory-db. Smallest fix: lock 2.6.10 and gemspec >= 2.6.9. Deeper fix: none. Status: CI graphs affected; this library execute path not_affected. Disposition: upgrade. Next: apply when confirmed.
|
|
@@ -52,6 +40,18 @@ Tier dev/test. Kind freshness. Severity low. Confidence high. json 2.21.2 vs 3.0
|
|
|
52
40
|
|
|
53
41
|
Tier automation. Kind automation gap. Severity low. Confidence high. Why it matters: Dependabot bundler directory / does not refresh gemfiles/*.gemfile.lock. scorecard.yml still pins actions/checkout 9c091bb (v7.0.0) while test.yml uses 3d3c42e5 (v7.0.1). ossf/scorecard-action 4eaacf05 is v2.4.3; v2.4.4 exists. mschilde/auto-label-merge-conflicts is commented as master. Makefile has no audit target. Evidence kind observed (workflow files, dependabot.yml). Smallest fix: optional action SHA refresh via Dependabot; keep appraisal locks in the on-demand audit. Do not put advisory scanners back on test.yml.
|
|
54
42
|
|
|
43
|
+
## Effects
|
|
44
|
+
|
|
45
|
+
ruby-advisory-db update: 1245 advisories, last updated 2026-09-16 10:35:37 -0400, commit 44784c295391577f25d198a9205eae4ba73ec4da.
|
|
46
|
+
|
|
47
|
+
bundle-audit check failed on all four lockfiles with GHSA-rmxg-5p3r-j6hh (graphql 2.6.7, solution >= 2.6.9). No other scanner matches.
|
|
48
|
+
|
|
49
|
+
bundle outdated --strict on the root Gemfile listed 16 outdated specs. graphql 2.6.7 vs 2.6.10 is the only outdated hot-path direct runtime gem.
|
|
50
|
+
|
|
51
|
+
Libyears from Gemfile.lock vs RubyGems stable (compact-graph band: about 10 low, about 100 medium): 124 locked packages, 27 outdated, total lag 17.94 years, average 0.145 years per package, 6 packages one major behind (arbre, inherited_resources, json, marcel, diff-lcs, rubocop-capybara). Coverage floor in config/polyrun_coverage.yml is 85 percent line. No upgrade spike was run this pass.
|
|
52
|
+
|
|
53
|
+
No person-facing surface in this pass.
|
|
54
|
+
|
|
55
55
|
## Next
|
|
56
56
|
|
|
57
57
|
Wait for a Rails release that includes rails/rails#58601. Then drop the development json < 3 pin and bundle update json. Leave marcel 2 and diff-lcs 2 alone until those parents move.
|