activeadmin-graphql 0.3.1 → 0.3.3
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 -0
- data/app/controllers/active_admin/graphql_controller.rb +19 -4
- data/docs/changelogs/20261010091415_graphql-resource-enabled-default.md +34 -0
- data/docs/changelogs/20261010101500_nonconventional-id-fields.md +16 -2
- data/docs/changelogs/20261010103800_release-0-3-1.md +9 -2
- data/docs/changelogs/20261010110600_graphql-identity-dsl.md +34 -0
- data/docs/changelogs/20261010111800_release-0-3-2.md +46 -0
- data/docs/changelogs/20261012050051_graphql-surface-toggles.md +40 -0
- data/docs/changelogs/20261012064500_graphql-capabilities.md +35 -0
- data/docs/changelogs/20261012113500_release-0-3-3.md +45 -0
- data/docs/graphql-api.md +166 -20
- data/docs/issues/20261010111159_rails-composite-primary-keys-alignment.md +81 -0
- data/docs/issues/20261010111300_partitions-and-shards-support.md +55 -0
- data/docs/issues/20261010111500_graphql-federation-support.md +46 -0
- data/lib/active_admin/graphql/capability.rb +35 -0
- data/lib/active_admin/graphql/capability_definition_dsl.rb +64 -0
- data/lib/active_admin/graphql/integration.rb +19 -1
- data/lib/active_admin/graphql/policy_adapter.rb +94 -0
- data/lib/active_admin/graphql/policy_set_cache.rb +18 -9
- data/lib/active_admin/graphql/resource_capability_dsl.rb +31 -0
- data/lib/active_admin/graphql/resource_capability_maps.rb +59 -0
- data/lib/active_admin/graphql/resource_config.rb +23 -2
- data/lib/active_admin/graphql/resource_definition_dsl.rb +12 -2
- data/lib/active_admin/graphql/resource_identity.rb +98 -0
- data/lib/active_admin/graphql/resource_methods.rb +8 -2
- data/lib/active_admin/graphql/resource_query_proxy/identity.rb +4 -4
- data/lib/active_admin/graphql/resource_query_proxy.rb +5 -4
- data/lib/active_admin/graphql/resource_surface_dsl.rb +48 -0
- data/lib/active_admin/graphql/schema_builder/build.rb +52 -3
- data/lib/active_admin/graphql/schema_builder/mutation_batch.rb +7 -0
- data/lib/active_admin/graphql/schema_builder/mutation_collection.rb +8 -0
- data/lib/active_admin/graphql/schema_builder/mutation_create.rb +1 -0
- data/lib/active_admin/graphql/schema_builder/mutation_member.rb +8 -0
- data/lib/active_admin/graphql/schema_builder/mutation_type_builder.rb +15 -10
- data/lib/active_admin/graphql/schema_builder/mutation_update_destroy.rb +4 -2
- data/lib/active_admin/graphql/schema_builder/query_type.rb +2 -1
- data/lib/active_admin/graphql/schema_builder/query_type_collection.rb +3 -0
- data/lib/active_admin/graphql/schema_builder/query_type_member.rb +5 -2
- data/lib/active_admin/graphql/schema_builder/query_type_policies.rb +9 -63
- data/lib/active_admin/graphql/schema_builder/resources.rb +34 -0
- data/lib/active_admin/graphql/schema_builder/types_object.rb +27 -11
- data/lib/active_admin/graphql/schema_builder/visibility.rb +22 -7
- data/lib/active_admin/graphql/schema_builder/wire.rb +3 -1
- data/lib/active_admin/graphql/schema_field.rb +18 -2
- data/lib/active_admin/graphql/version.rb +1 -1
- data/lib/active_admin/graphql.rb +3 -0
- metadata +17 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 36bec145bd90193ae32e34aa54b7a6ed01dff13a8b104269b771f797262b2480
|
|
4
|
+
data.tar.gz: 82724e08af33a67a1a9146813965e5d836006620ff503099842addcdeaab16cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b9ddc6e9d85447807e5cbbf9d1e5c9b5c87b756eaa8325cb57fe8ce291e221b40e1afd200ddb683a73cba036b83b6eac6f8f5ab3e0ff9788c1864e7f550cc16
|
|
7
|
+
data.tar.gz: 806443d03640f31e48d893998cd9f693bafd5efce162798ff406ed2eee2ad43d7c0c588467b8fbd37fdab4a3a6049a9efcbadffbe337469cac7bc5ff958bf36f
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.3.3 (2026-10-12)
|
|
6
|
+
|
|
7
|
+
- Add `graphql { capability ... }` and namespace `graphql_capabilities` so one named grant can gate many fields, queries, and mutations (RFC 0008).
|
|
8
|
+
- Apply `fields:` capabilities to wired `belongs_to` associations; reject unknown capability field names and named visibility `profiles:` combined with `graphql_capabilities`.
|
|
9
|
+
- Add namespace setting `graphql_resource_enabled_default` (`true` by default) and `graphql { enable! }` so apps can opt resources into the schema instead of opting out with `disable!`.
|
|
10
|
+
- Add namespace toggles for `registered_resource` and `belongs_to` wiring (`graphql_registered_resource_enabled`, `graphql_belongs_to_associations_enabled`; both `true` by default).
|
|
11
|
+
- Add `graphql_policies_enabled` / `graphql_policies_enabled_default` for policy field publishing and per-resource seeds, plus `graphql_policy_adapter` (default `ActiveAdmin::GraphQL::PolicyAdapter`) for payload construction.
|
|
12
|
+
- Add per-resource surface defaults and DSL (`graphql_queries_enabled_default`, `graphql_mutations_enabled_default`, `graphql_run_actions_enabled_default`, plus `enable_*!` / `disable_*!`) so apps can trim list/show, CRUD, run-action, and policy fields without disabling the whole resource.
|
|
13
|
+
- Treat `queries_enabled` as the read surface: omit `registered_resource` union membership when queries are off; fail schema build when `Query` would have no fields.
|
|
14
|
+
|
|
15
|
+
## 0.3.2 (2026-10-10)
|
|
16
|
+
|
|
17
|
+
- Add `graphql { identity ... }` so keyless views can declare GraphQL id columns, optional `separator`, and `encode` / `decode` (RFC 0007).
|
|
18
|
+
- Fail schema build when a registered model has neither a primary key nor an `id` column and no `identity` declaration; set `self.primary_key`, use `identity`, or `graphql { disable! }`.
|
|
19
|
+
|
|
5
20
|
## 0.3.1 (2026-10-10)
|
|
6
21
|
|
|
7
22
|
- Fix GraphQL identity handling for database views and nonconventional primary keys: keep one `id` field, support inferred `id` lookups, reject ambiguous identifiers, and honor attribute filters.
|
|
@@ -51,16 +51,31 @@ module ActiveAdmin
|
|
|
51
51
|
|
|
52
52
|
def graphql_context
|
|
53
53
|
ns = active_admin_namespace
|
|
54
|
-
{
|
|
54
|
+
context = {
|
|
55
55
|
auth: ActiveAdmin::GraphQL::AuthContext.new(
|
|
56
56
|
user: current_active_admin_user,
|
|
57
57
|
namespace: ns
|
|
58
58
|
),
|
|
59
59
|
namespace: ns,
|
|
60
60
|
request: request,
|
|
61
|
-
current_user: current_active_admin_user
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
current_user: current_active_admin_user
|
|
62
|
+
}
|
|
63
|
+
# Named visibility profiles cache a fixed context; per-request capabilities
|
|
64
|
+
# need the live request context (dynamic visibility). Skip the profile key.
|
|
65
|
+
unless ns.graphql_capabilities.respond_to?(:call)
|
|
66
|
+
profile = graphql_visibility_profile_for(ns)
|
|
67
|
+
context[:visibility_profile] = profile if profile
|
|
68
|
+
end
|
|
69
|
+
capabilities = graphql_capabilities_for(ns, context)
|
|
70
|
+
context[:capabilities] = capabilities unless capabilities.nil?
|
|
71
|
+
context
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def graphql_capabilities_for(ns, context)
|
|
75
|
+
hook = ns.graphql_capabilities
|
|
76
|
+
return nil unless hook.respond_to?(:call)
|
|
77
|
+
|
|
78
|
+
ActiveAdmin::GraphQL::Capability.normalize_set(hook.call(context))
|
|
64
79
|
end
|
|
65
80
|
|
|
66
81
|
def graphql_visibility_profile_for(ns)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# GraphQL resource enabled default
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Add namespace setting `graphql_resource_enabled_default`, default `true`, so
|
|
10
|
+
0.3.x behavior stays: turning on the namespace endpoint still includes every
|
|
11
|
+
ActiveRecord resource unless `graphql { disable! }` is set.
|
|
12
|
+
|
|
13
|
+
Apps that want support-style opt-in set the setting to `false`. Then a resource
|
|
14
|
+
enters the schema only when registration runs `graphql { }` or
|
|
15
|
+
`graphql { enable! }`. `disable!` still omits.
|
|
16
|
+
|
|
17
|
+
`ResourceConfig` takes the initial `enabled` flag from the namespace setting.
|
|
18
|
+
Entering a `graphql` block sets `enabled = true` before the block body runs so
|
|
19
|
+
an empty block is a conscious opt-in.
|
|
20
|
+
|
|
21
|
+
## Effects
|
|
22
|
+
|
|
23
|
+
New request specs cover default true, default false without a block, empty
|
|
24
|
+
block, `enable!`, and `disable!`.
|
|
25
|
+
|
|
26
|
+
## Next
|
|
27
|
+
|
|
28
|
+
Folded into 0.3.3 release metadata.
|
|
29
|
+
|
|
30
|
+
## Source
|
|
31
|
+
|
|
32
|
+
CHANGELOG 0.3.3. docs/graphql-api.md namespace settings and per-resource
|
|
33
|
+
DSL. spec/requests/graphql_resource_enabled_default_spec.rb.
|
|
34
|
+
docs/changelogs/20261012113500_release-0-3-3.md.
|
|
@@ -11,7 +11,10 @@ primary key is blank. Object types skip emitting a column field named `id`
|
|
|
11
11
|
(interface owns GraphQL `id`) and expose a single non-`id` primary-key column
|
|
12
12
|
as a readable scalar unless the resource's attribute configuration omits it.
|
|
13
13
|
Models with neither a primary key nor an `id` column fail schema build with an
|
|
14
|
-
`ArgumentError` that asks for `self.primary_key`.
|
|
14
|
+
`ArgumentError` that asks for `self.primary_key`. On 0.3.0 those models could
|
|
15
|
+
still enter the schema with a broken GraphQL `id`. Apps that keep such a
|
|
16
|
+
resource registered must set `self.primary_key` or use `graphql { disable! }`
|
|
17
|
+
so the rest of the namespace schema still builds. Inferred `id` values must be
|
|
15
18
|
unique and non-null; ambiguous member and batched lookups fail closed.
|
|
16
19
|
|
|
17
20
|
Member lookup uses the inferred column while preserving an explicitly
|
|
@@ -21,9 +24,19 @@ entries for distinct records when ActiveRecord has no declared primary key.
|
|
|
21
24
|
Dummy coverage includes SQLite views that project `code AS id` and
|
|
22
25
|
`id AS row_key`, plus a table with an `id` column and no primary key.
|
|
23
26
|
|
|
27
|
+
## Later pass 2026-10-10
|
|
28
|
+
|
|
29
|
+
Downstream check: a database view with neither primary key nor `id` column
|
|
30
|
+
could stay GraphQL-disabled via `graphql { disable! }`. Spec covers that
|
|
31
|
+
escape hatch next to the ArgumentError path.
|
|
32
|
+
|
|
33
|
+
Later the same day: RFC 0007 adds `graphql { identity ... }` so those views
|
|
34
|
+
can stay enabled when columns (and optional separator) are declared. See
|
|
35
|
+
docs/changelogs/20261010110600_graphql-identity-dsl.md.
|
|
36
|
+
|
|
24
37
|
## Next
|
|
25
38
|
|
|
26
|
-
|
|
39
|
+
Core fix shipped in 0.3.1. Identity DSL follow-on is 0.3.2.
|
|
27
40
|
|
|
28
41
|
## Source
|
|
29
42
|
|
|
@@ -32,3 +45,4 @@ Folded into 0.3.1 release metadata. Tag and gem push wait on make release.
|
|
|
32
45
|
`spec/unit/resource_query_proxy_identity_spec.rb`,
|
|
33
46
|
`spec/unit/policy_set_cache_spec.rb`
|
|
34
47
|
- Views: `spec/dummy/db/schema.rb` (`string_id_records`, `alternate_key_records`)
|
|
48
|
+
- Follow-on: docs/changelogs/20261010110600_graphql-identity-dsl.md
|
|
@@ -6,7 +6,11 @@ Andrei Makarov
|
|
|
6
6
|
|
|
7
7
|
## Decisions
|
|
8
8
|
|
|
9
|
-
Cut 0.3.1 after published 0.3.0.
|
|
9
|
+
Cut 0.3.1 after published 0.3.0. User-visible work: GraphQL identity for
|
|
10
|
+
database views and nonconventional primary keys; fail-closed when a model has
|
|
11
|
+
neither a primary key nor an `id` column without configuration; and
|
|
12
|
+
`graphql { identity ... }` (RFC 0007) for keyless views with a virtual
|
|
13
|
+
composite id.
|
|
10
14
|
|
|
11
15
|
CHANGELOG 0.3.1 dated 2026-10-10. Version constant is 0.3.1. Path gem pins in Gemfile.lock and appraisal lockfiles match.
|
|
12
16
|
|
|
@@ -24,9 +28,12 @@ PATH specs for activeadmin-graphql in Gemfile.lock, gemfiles/rails72.gemfile.loc
|
|
|
24
28
|
|
|
25
29
|
## Next
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
0.3.1 tagged and published on RubyGems. Post-tag identity DSL work ships in
|
|
32
|
+
0.3.2; see docs/changelogs/20261010111800_release-0-3-2.md.
|
|
28
33
|
|
|
29
34
|
## Source
|
|
30
35
|
|
|
31
36
|
docs/changelogs/20261010101500_nonconventional-id-fields.md
|
|
37
|
+
docs/changelogs/20261010110600_graphql-identity-dsl.md
|
|
38
|
+
rfcs/0007-graphql-identity.md
|
|
32
39
|
usr/bin/release.rb
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# GraphQL identity DSL (RFC 0007)
|
|
2
|
+
|
|
3
|
+
## Decisions
|
|
4
|
+
|
|
5
|
+
Ship `graphql { identity *columns, separator:, encode:, decode: }` so resources
|
|
6
|
+
without an ActiveRecord primary key and without an `id` column can stay in the
|
|
7
|
+
schema. Prefer resource configuration over forcing `self.primary_key`.
|
|
8
|
+
|
|
9
|
+
Separator form matches HTML admins that use a virtual `id` method such as
|
|
10
|
+
`[entry_type, entry_id, event_type].join(":")`. Without separator, multi-column
|
|
11
|
+
identity keeps the existing composite JSON string.
|
|
12
|
+
|
|
13
|
+
## Effects
|
|
14
|
+
|
|
15
|
+
Schema build, member lookup, mutations that resolve by where/id, and policy
|
|
16
|
+
cache keys go through `ActiveAdmin::GraphQL::ResourceIdentity` when identity is
|
|
17
|
+
configured. Ambiguous matches still fail closed.
|
|
18
|
+
|
|
19
|
+
Dummy coverage: view `alert_events` / model `AlertEvent` with virtual composite
|
|
20
|
+
`id`.
|
|
21
|
+
|
|
22
|
+
## Next
|
|
23
|
+
|
|
24
|
+
Folded into 0.3.2 release metadata (0.3.1 already published without this DSL).
|
|
25
|
+
Tag and gem push wait on make release.
|
|
26
|
+
|
|
27
|
+
## Source
|
|
28
|
+
|
|
29
|
+
rfcs/0007-graphql-identity.md
|
|
30
|
+
docs/changelogs/20261010101500_nonconventional-id-fields.md
|
|
31
|
+
docs/issues/20261010111159_rails-composite-primary-keys-alignment.md
|
|
32
|
+
https://guides.rubyonrails.org/active_record_composite_primary_keys.html
|
|
33
|
+
spec/unit/resource_identity_spec.rb
|
|
34
|
+
spec/requests/graphql_identity_dsl_spec.rb
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Release 0.3.2 metadata
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Cut 0.3.2 after published 0.3.1. User-visible work since the 0.3.1 tag:
|
|
10
|
+
`graphql { identity ... }` (RFC 0007) for keyless views, and schema-build
|
|
11
|
+
error text that names `identity` alongside `self.primary_key` and `disable!`.
|
|
12
|
+
|
|
13
|
+
CHANGELOG 0.3.1 restored to the published one-bullet text. Identity DSL bullets
|
|
14
|
+
live under 0.3.2 dated 2026-10-10.
|
|
15
|
+
|
|
16
|
+
Version constant is 0.3.2. Path gem pins in Gemfile.lock and appraisal
|
|
17
|
+
lockfiles match.
|
|
18
|
+
|
|
19
|
+
Docs-only notes (Rails composite PK alignment, partitions/shards unsupported,
|
|
20
|
+
federation unsupported) stay out of CHANGELOG.md.
|
|
21
|
+
|
|
22
|
+
make release (usr/bin/release.rb) still owns gem build, gem push, git tag, and
|
|
23
|
+
GitHub release. This pass only prepares metadata.
|
|
24
|
+
|
|
25
|
+
## Effects
|
|
26
|
+
|
|
27
|
+
lib/active_admin/graphql/version.rb VERSION is 0.3.2.
|
|
28
|
+
|
|
29
|
+
CHANGELOG identity DSL bullets moved from the post-tag 0.3.1 draft under 0.3.2.
|
|
30
|
+
|
|
31
|
+
PATH specs for activeadmin-graphql in Gemfile.lock,
|
|
32
|
+
gemfiles/rails72.gemfile.lock, gemfiles/rails8ruby4.gemfile.lock, and
|
|
33
|
+
gemfiles/rails8ruby34.gemfile.lock are 0.3.2.
|
|
34
|
+
|
|
35
|
+
## Next
|
|
36
|
+
|
|
37
|
+
Run make release from a clean tree when ready to push the gem and tag 0.3.2.
|
|
38
|
+
|
|
39
|
+
## Source
|
|
40
|
+
|
|
41
|
+
docs/changelogs/20261010110600_graphql-identity-dsl.md
|
|
42
|
+
rfcs/0007-graphql-identity.md
|
|
43
|
+
docs/issues/20261010111159_rails-composite-primary-keys-alignment.md
|
|
44
|
+
docs/issues/20261010111300_partitions-and-shards-support.md
|
|
45
|
+
docs/issues/20261010111500_graphql-federation-support.md
|
|
46
|
+
usr/bin/release.rb
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# GraphQL surface toggles
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Add namespace and per-resource controls for schema surfaces that were always on
|
|
10
|
+
once a resource was enabled. Defaults stay `true` so 0.3.x behavior is
|
|
11
|
+
unchanged.
|
|
12
|
+
|
|
13
|
+
Namespace-only switches: `graphql_registered_resource_enabled`,
|
|
14
|
+
`graphql_belongs_to_associations_enabled`, `graphql_policies_enabled`.
|
|
15
|
+
Policy payloads use `graphql_policy_adapter` (default `PolicyAdapter`).
|
|
16
|
+
Per-resource policy seed is `graphql_policies_enabled_default`.
|
|
17
|
+
|
|
18
|
+
Per-resource seeds from namespace defaults: queries, mutations (CRUD),
|
|
19
|
+
run-actions, and policies. Resource DSL exposes matching `enable_*!` /
|
|
20
|
+
`disable_*!` methods. `queries_enabled` also gates `registered_resource`
|
|
21
|
+
membership. Schema build raises if `Query` would have no fields.
|
|
22
|
+
|
|
23
|
+
## Effects
|
|
24
|
+
|
|
25
|
+
Schema builder skips policy query fields, registered_resource union, belongs_to
|
|
26
|
+
wiring, list/show fields, CRUD mutations, and run-action mutations when the
|
|
27
|
+
matching flag is off. Request specs cover the new settings and DSL, including
|
|
28
|
+
empty-Query rejection and registered_resource gating by queries.
|
|
29
|
+
|
|
30
|
+
## Next
|
|
31
|
+
|
|
32
|
+
Folded into 0.3.3 release metadata.
|
|
33
|
+
|
|
34
|
+
## Source
|
|
35
|
+
|
|
36
|
+
CHANGELOG 0.3.3. docs/graphql-api.md.
|
|
37
|
+
spec/requests/graphql_surface_toggles_spec.rb.
|
|
38
|
+
spec/requests/graphql_policy_surface_spec.rb.
|
|
39
|
+
spec/requests/graphql_query_surface_contract_spec.rb.
|
|
40
|
+
docs/changelogs/20261012113500_release-0-3-3.md.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# GraphQL capabilities
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Add RFC 0008 capability grants. Resource DSL `capability` associates many
|
|
10
|
+
object fields, queries, and mutations with one name. Namespace
|
|
11
|
+
`graphql_capabilities` fills `context[:capabilities]` per request. SchemaField
|
|
12
|
+
checks capability in `visible?` and `authorized?`. Capabilities do not replace
|
|
13
|
+
ActiveAdmin authorization. Subscriptions stay out of scope.
|
|
14
|
+
|
|
15
|
+
## Effects
|
|
16
|
+
|
|
17
|
+
Gated members fail closed without the grant. With `graphql_visibility`,
|
|
18
|
+
introspection omits them. Aggregate run-action resolvers also check
|
|
19
|
+
per-action capability keys (`member_*`, `batch_*`, `collection_*`).
|
|
20
|
+
`belongs_to` association fields honor `fields:` capabilities. Schema build
|
|
21
|
+
rejects unknown capability field names and rejects named visibility profiles
|
|
22
|
+
combined with `graphql_capabilities` (dynamic visibility required).
|
|
23
|
+
|
|
24
|
+
## Next
|
|
25
|
+
|
|
26
|
+
Folded into 0.3.3 release metadata. Follow-ons remain: policy payloads listing
|
|
27
|
+
field capabilities, mutation input attribute maps, and transport gates if
|
|
28
|
+
subscriptions ship later.
|
|
29
|
+
|
|
30
|
+
## Source
|
|
31
|
+
|
|
32
|
+
RFC 0008. CHANGELOG 0.3.3. docs/graphql-api.md. spec/unit/capability_spec.rb,
|
|
33
|
+
spec/unit/capability_dsl_spec.rb, spec/requests/graphql_capabilities_spec.rb,
|
|
34
|
+
spec/requests/graphql_capabilities_edge_spec.rb.
|
|
35
|
+
docs/changelogs/20261012113500_release-0-3-3.md.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Release 0.3.3 metadata
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Cut 0.3.3 after published 0.3.2. User-visible work since the 0.3.2 tag:
|
|
10
|
+
`graphql_resource_enabled_default` and `enable!` opt-in, surface toggles for
|
|
11
|
+
queries, mutations, run-actions, policies, `registered_resource`, and
|
|
12
|
+
`belongs_to`, plus GraphQL capabilities (RFC 0008). Defaults stay `true` so
|
|
13
|
+
0.3.x schema shape is unchanged unless an app opts in to narrower surfaces.
|
|
14
|
+
|
|
15
|
+
CHANGELOG Unreleased bullets moved under 0.3.3 dated 2026-10-12.
|
|
16
|
+
|
|
17
|
+
Version constant is 0.3.3. Path gem pins in Gemfile.lock and appraisal
|
|
18
|
+
lockfiles match.
|
|
19
|
+
|
|
20
|
+
Internal `stringify_attrs` safe-navigation cleanup stays out of CHANGELOG.md.
|
|
21
|
+
|
|
22
|
+
make release (usr/bin/release.rb) still owns gem build, gem push, git tag, and
|
|
23
|
+
GitHub release. This pass only prepares metadata.
|
|
24
|
+
|
|
25
|
+
## Effects
|
|
26
|
+
|
|
27
|
+
lib/active_admin/graphql/version.rb VERSION is 0.3.3.
|
|
28
|
+
|
|
29
|
+
CHANGELOG surface-toggle and capability bullets live under 0.3.3.
|
|
30
|
+
|
|
31
|
+
PATH specs for activeadmin-graphql in Gemfile.lock,
|
|
32
|
+
gemfiles/rails72.gemfile.lock, gemfiles/rails8ruby4.gemfile.lock, and
|
|
33
|
+
gemfiles/rails8ruby34.gemfile.lock are 0.3.3.
|
|
34
|
+
|
|
35
|
+
## Next
|
|
36
|
+
|
|
37
|
+
Run make release from a clean tree when ready to push the gem and tag 0.3.3.
|
|
38
|
+
|
|
39
|
+
## Source
|
|
40
|
+
|
|
41
|
+
docs/changelogs/20261010091415_graphql-resource-enabled-default.md
|
|
42
|
+
docs/changelogs/20261012050051_graphql-surface-toggles.md
|
|
43
|
+
docs/changelogs/20261012064500_graphql-capabilities.md
|
|
44
|
+
rfcs/0008-graphql-capabilities.md
|
|
45
|
+
usr/bin/release.rb
|
data/docs/graphql-api.md
CHANGED
|
@@ -33,6 +33,12 @@ ActiveAdmin.setup do |config|
|
|
|
33
33
|
admin.graphql = true
|
|
34
34
|
# Optional — default is "graphql", i.e. POST /admin/graphql
|
|
35
35
|
# admin.graphql_path = "graphql"
|
|
36
|
+
# Optional — set false so only resources with a graphql block enter the schema
|
|
37
|
+
# admin.graphql_resource_enabled_default = false
|
|
38
|
+
# Optional — trim always-on surfaces for a narrow API
|
|
39
|
+
# admin.graphql_policies_enabled = false
|
|
40
|
+
# admin.graphql_registered_resource_enabled = false
|
|
41
|
+
# admin.graphql_belongs_to_associations_enabled = false
|
|
36
42
|
end
|
|
37
43
|
end
|
|
38
44
|
```
|
|
@@ -45,6 +51,33 @@ Run `bin/rails active_admin:install` or reload routes if needed so
|
|
|
45
51
|
Each namespace inherits these options (defaults in parentheses):
|
|
46
52
|
|
|
47
53
|
* `graphql` — set to `true` to mount the endpoint (`false` by default).
|
|
54
|
+
* `graphql_resource_enabled_default` — whether each registered ActiveRecord
|
|
55
|
+
resource is included in the schema without a `graphql` block (`true` by
|
|
56
|
+
default, matching 0.3.x). Set to `false` for opt-in: only resources that call
|
|
57
|
+
`graphql { }` (or `graphql { enable! }`) appear in the schema. `disable!`
|
|
58
|
+
still omits a resource.
|
|
59
|
+
* `graphql_queries_enabled_default` — seed for per-resource read fields
|
|
60
|
+
(`true` by default): named list/show fields and membership in
|
|
61
|
+
`registered_resource` / `ActiveAdminRegisteredResource`. Set `false` and use
|
|
62
|
+
`enable_queries!` for opt-in reads. Object types may still exist for mutations.
|
|
63
|
+
* `graphql_mutations_enabled_default` — seed for per-resource CRUD mutations
|
|
64
|
+
(`true` by default). Set `false` and use `enable_mutations!` for opt-in writes.
|
|
65
|
+
* `graphql_run_actions_enabled_default` — seed for batch/member/collection
|
|
66
|
+
action mutations (`true` by default).
|
|
67
|
+
* `graphql_policies_enabled` — publish `activeadmin_policies` query fields and
|
|
68
|
+
allow per-object policy fields (`true` by default).
|
|
69
|
+
* `graphql_policies_enabled_default` — seed for per-resource `policies_enabled`
|
|
70
|
+
(`true` by default). Use `enable_policies!` / `disable_policies!` per resource.
|
|
71
|
+
* `graphql_policy_adapter` — class that builds `activeadmin_policies` payloads
|
|
72
|
+
(`ActiveAdmin::GraphQL::PolicyAdapter` by default). Set a subclass (or constant
|
|
73
|
+
`String`) to replace payload logic; the default adapter still honors
|
|
74
|
+
`graphql_policy_actions` / `graphql_policy_action_mapper` /
|
|
75
|
+
`graphql_policy_extra` / `graphql_policy_transform`.
|
|
76
|
+
* `graphql_registered_resource_enabled` — include `registered_resource` and the
|
|
77
|
+
`ActiveAdminRegisteredResource` union when at least one queryable resource
|
|
78
|
+
exists (`true` by default).
|
|
79
|
+
* `graphql_belongs_to_associations_enabled` — wire non-polymorphic `belongs_to`
|
|
80
|
+
fields between registered resource types (`true` by default).
|
|
48
81
|
* `graphql_path` — path segment under the namespace mount (`"graphql"`).
|
|
49
82
|
* `graphql_multiplex_max` — maximum operations per multiplexed JSON array
|
|
50
83
|
request (`20`).
|
|
@@ -70,6 +103,11 @@ Each namespace inherits these options (defaults in parentheses):
|
|
|
70
103
|
default `context[:visibility_profile]` for each HTTP request (symbols accepted).
|
|
71
104
|
* `graphql_schema_visible` — optional `Proc` `(context, meta) -> Boolean` when
|
|
72
105
|
`graphql_visibility` is enabled; see Schema visibility below.
|
|
106
|
+
* `graphql_capabilities` — optional `Proc` `(context) -> Enumerable` of capability
|
|
107
|
+
names for the request (RFC 0008). Normalized into `context[:capabilities]`.
|
|
108
|
+
Cannot be combined with named `graphql_visibility` `profiles:`; schema build
|
|
109
|
+
forces `dynamic: true` and omits `visibility_profile` from the request context
|
|
110
|
+
so introspection uses the live capability set.
|
|
73
111
|
* `graphql_configure_schema` — `Proc` receiving the schema class after build
|
|
74
112
|
(extensions, extra types, and so on).
|
|
75
113
|
|
|
@@ -199,21 +237,90 @@ UI, including any `authorize!` or `authorize_resource!` calls.
|
|
|
199
237
|
|
|
200
238
|
See the ActiveAdmin guide [Authorization adapter](https://activeadmin.info/13-authorization-adapter) for adapter setup; the same rules apply to GraphQL.
|
|
201
239
|
|
|
240
|
+
Policy preflight fields (`activeadmin_policies`, `activeadmin_policies_for`, and
|
|
241
|
+
per-object `activeadmin_policies`) are published when `graphql_policies_enabled`
|
|
242
|
+
is true. Payloads come from `graphql_policy_adapter`. The default
|
|
243
|
+
`ActiveAdmin::GraphQL::PolicyAdapter` asks the authorization adapter which
|
|
244
|
+
actions are allowed and applies the optional `graphql_policy_*` hooks. Assign a
|
|
245
|
+
subclass that implements `policy_set` (and optionally `include_resource?`) to
|
|
246
|
+
replace the payload builder.
|
|
247
|
+
|
|
248
|
+
### Capabilities (RFC 0008)
|
|
249
|
+
|
|
250
|
+
Associate many object fields, queries, and mutations with one named capability
|
|
251
|
+
inside `graphql do`. The same capability name can cover a mixed set of members:
|
|
252
|
+
|
|
253
|
+
```ruby
|
|
254
|
+
ActiveAdmin.register Post do
|
|
255
|
+
graphql do
|
|
256
|
+
capability :pii do
|
|
257
|
+
fields :body
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
capability :editor do
|
|
261
|
+
fields :title
|
|
262
|
+
queries :index, :show
|
|
263
|
+
mutations :create, :update, :destroy
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
capability :publish, member_actions: %i[publish]
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Kwargs (`fields:`, `queries:`, `mutations:`, `member_actions:`,
|
|
272
|
+
`batch_actions:`, `collection_actions:`) work without a block. Query aliases:
|
|
273
|
+
`index` / `list` → collection, `show` → member. Mutation alias: `delete` →
|
|
274
|
+
`destroy`. Run-action sugar builds keys like `member_publish`.
|
|
275
|
+
|
|
276
|
+
Grant capabilities per request with `graphql_capabilities`. Map OAuth scopes or
|
|
277
|
+
roles there; the gem stores a symbol set on `context[:capabilities]`:
|
|
278
|
+
|
|
279
|
+
```ruby
|
|
280
|
+
admin.graphql_capabilities = lambda { |ctx|
|
|
281
|
+
Array(ctx[:current_user]&.oauth_scopes)
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
A gated member fails closed when the capability is missing from that set:
|
|
286
|
+
resolve returns null for the field (graphql-ruby unauthorized field). Enable
|
|
287
|
+
`graphql_visibility` so introspection and validation also omit ungated members.
|
|
288
|
+
`fields:` applies to generated attributes and wired `belongs_to` associations.
|
|
289
|
+
Unknown field names raise at schema build. Capabilities do not replace the
|
|
290
|
+
authorization adapter.
|
|
291
|
+
|
|
292
|
+
Custom `SchemaField` definitions may pass `capability: :name` the same way.
|
|
293
|
+
Do not use named visibility `profiles:` together with `graphql_capabilities`
|
|
294
|
+
(cached profile context ignores per-request grants).
|
|
295
|
+
|
|
202
296
|
## Schema overview
|
|
203
297
|
|
|
204
|
-
|
|
205
|
-
(for example `posts`), plus a
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
298
|
+
With the default surface flags (`true`), the `Query` type includes one
|
|
299
|
+
Relay-style connection field per resource route (for example `posts`), plus a
|
|
300
|
+
singular field for a single record (for example `post`). Optional
|
|
301
|
+
`graphql_field` entries on `register_page` appear here too, plus
|
|
302
|
+
`registered_resource` (returning the `ActiveAdminRegisteredResource` union)
|
|
303
|
+
when at least one queryable resource exists.
|
|
304
|
+
|
|
305
|
+
List and show fields require per-resource `queries_enabled` (seeded from
|
|
306
|
+
`graphql_queries_enabled_default`). Turning queries off still leaves the object
|
|
307
|
+
type available for mutations. `registered_resource` and the union also require
|
|
308
|
+
`graphql_registered_resource_enabled`. Policy preflight fields require
|
|
309
|
+
`graphql_policies_enabled`. Schema build fails when `Query` would have no
|
|
310
|
+
fields: no list/show, no policies, no `registered_resource`, and no page
|
|
311
|
+
`graphql_field`.
|
|
209
312
|
|
|
210
313
|
Every resource object type implements the `ActiveAdminResource` interface
|
|
211
314
|
(`id: ID!`) so clients can share fragments or rely on a common shape.
|
|
315
|
+
Non-polymorphic `belongs_to` fields between registered types are wired when
|
|
316
|
+
`graphql_belongs_to_associations_enabled` is true.
|
|
212
317
|
|
|
213
318
|
The `Mutation` type is present when at least one operation exists: per-resource
|
|
214
|
-
`create_*`, `update_*`, and `delete_*` when those controller actions exist
|
|
215
|
-
`*_batch_action`, `*_member_action`, and
|
|
216
|
-
resource defines the corresponding batch,
|
|
319
|
+
`create_*`, `update_*`, and `delete_*` when those controller actions exist and
|
|
320
|
+
`mutations_enabled` is true, plus `*_batch_action`, `*_member_action`, and
|
|
321
|
+
`*_collection_action` fields when the resource defines the corresponding batch,
|
|
322
|
+
member, or collection actions and `run_actions_enabled` is true. Both flags are
|
|
323
|
+
seeded from the matching namespace defaults.
|
|
217
324
|
|
|
218
325
|
Object type names default to the model name (for example `Post`). Typed input
|
|
219
326
|
objects use assignable columns (see the per-resource section below):
|
|
@@ -229,12 +336,28 @@ GraphQL `id` always comes from `ActiveAdminResource` (`ID!`). An ActiveRecord
|
|
|
229
336
|
`id` column is never added as a second field. When `self.primary_key` is blank
|
|
230
337
|
but the model still has an `id` column (common for database views that project
|
|
231
338
|
`… AS id`), that column supplies the GraphQL `id` value. When the model has
|
|
232
|
-
neither a primary key nor an `id` column,
|
|
233
|
-
`self.primary_key` on the model
|
|
234
|
-
single-column primary key named something other
|
|
235
|
-
its own readable field beside `id`, unless `only`
|
|
236
|
-
inferred `id` column must contain a unique, non-null
|
|
237
|
-
ambiguous member and batched lookups fail instead of
|
|
339
|
+
neither a primary key nor an `id` column, declare GraphQL identity on the
|
|
340
|
+
resource (RFC 0007), set `self.primary_key` on the model, or omit the resource
|
|
341
|
+
with `graphql { disable! }`. A single-column primary key named something other
|
|
342
|
+
than `id` is also exposed as its own readable field beside `id`, unless `only`
|
|
343
|
+
or `exclude` omits it. An inferred `id` column must contain a unique, non-null
|
|
344
|
+
value for every row; ambiguous member and batched lookups fail instead of
|
|
345
|
+
selecting one row.
|
|
346
|
+
|
|
347
|
+
```ruby
|
|
348
|
+
# View with no PK and no id column; virtual identity matches HTML admin.
|
|
349
|
+
ActiveAdmin.register AlertEvent do
|
|
350
|
+
graphql do
|
|
351
|
+
identity :entry_type, :entry_id, :event_type, separator: ":"
|
|
352
|
+
# optional: encode: ->(record) { record.id }, decode: ->(id) { ... }
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
With `separator: ":"`, GraphQL `id` is `entry_type:entry_id:event_type`. Keep
|
|
358
|
+
the model’s `def id` (if any) in the same shape so HTML and GraphQL share
|
|
359
|
+
member ids. Without `separator`, multi-column identity uses the same JSON
|
|
360
|
+
object string as composite ActiveRecord primary keys.
|
|
238
361
|
|
|
239
362
|
### Composite primary keys (Rails 7.1+)
|
|
240
363
|
|
|
@@ -242,8 +365,10 @@ For models with `self.primary_key = [:book_code, :seq]` (and no separate `id`
|
|
|
242
365
|
column), Active Admin treats GraphQL as follows:
|
|
243
366
|
|
|
244
367
|
* `id` on the object type — JSON object string with all key columns in
|
|
245
|
-
model order
|
|
246
|
-
|
|
368
|
+
model order, for example `{"book_code":"CPK","seq":7}`. This is the GraphQL
|
|
369
|
+
wire format. It is not the Rails form/URL underscore packing described in
|
|
370
|
+
the Composite Primary Keys guide (`/books/2_25` with
|
|
371
|
+
`params.extract_value(:id)`).
|
|
247
372
|
* Readable fields — each primary-key column is also exposed as its own field
|
|
248
373
|
(in addition to `id`) so clients can load scalars without parsing JSON.
|
|
249
374
|
* `LibraryEditionWhereInput` (and similar) — either optional `id` (that JSON
|
|
@@ -255,12 +380,20 @@ column), Active Admin treats GraphQL as follows:
|
|
|
255
380
|
inputs (unlike single `id` tables, where the key is omitted from assignable
|
|
256
381
|
attributes).
|
|
257
382
|
|
|
258
|
-
For REST/HTML member routes, `ResourceController#find_resource` must resolve
|
|
383
|
+
For REST/HTML member routes, `ResourceController#find_resource` must resolve
|
|
384
|
+
composite ids from `params[:id]` or from individual primary-key params. Stock
|
|
385
|
+
ActiveAdmin 3.x only passes a single `params[:id]` into `find`; an ActiveAdmin
|
|
386
|
+
fork (or patch) that implements composite-aware `find_resource` keeps the
|
|
387
|
+
admin UI aligned with GraphQL. After decoding the GraphQL JSON `id`, the gem
|
|
388
|
+
uses Rails’ array/tuple conventions for `Relation#find` and
|
|
389
|
+
`where(primary_key => [tuple, …])` as in the guide.
|
|
259
390
|
|
|
260
|
-
The gem ships `ActiveAdmin::PrimaryKey` when the core constant is missing
|
|
391
|
+
The gem ships `ActiveAdmin::PrimaryKey` when the core constant is missing
|
|
392
|
+
(upstream). A fork may define `PrimaryKey` and extended `find_resource` in
|
|
393
|
+
`ResourceController` instead.
|
|
261
394
|
|
|
262
|
-
|
|
263
|
-
|
|
395
|
+
Alignment notes versus the Rails guide:
|
|
396
|
+
`docs/issues/20261010111159_rails-composite-primary-keys-alignment.md`.
|
|
264
397
|
|
|
265
398
|
### Collection query arguments
|
|
266
399
|
|
|
@@ -359,6 +492,7 @@ Inside `ActiveAdmin.register` you can narrow the GraphQL surface:
|
|
|
359
492
|
ActiveAdmin.register Post do
|
|
360
493
|
graphql do
|
|
361
494
|
disable! # omit this resource from the schema
|
|
495
|
+
# identity :entry_type, :entry_id, :event_type, separator: ":" # RFC 0007
|
|
362
496
|
type_name "BlogPost" # GraphQL object / mutation type basename (`graphql_name` alias)
|
|
363
497
|
only :title, :body, :published_at # expose only these attributes on queries
|
|
364
498
|
exclude :internal_score # or `except` / `exclude`
|
|
@@ -378,7 +512,19 @@ ActiveAdmin.register Post do
|
|
|
378
512
|
end
|
|
379
513
|
```
|
|
380
514
|
|
|
515
|
+
* `enable!` — include this resource when `graphql_resource_enabled_default` is
|
|
516
|
+
`false`. An empty `graphql` block has the same effect.
|
|
381
517
|
* `disable!` — resource is not included in Query or Mutation.
|
|
518
|
+
* `enable_queries!` / `disable_queries!` — list/show fields and
|
|
519
|
+
`registered_resource` membership for this resource.
|
|
520
|
+
* `enable_mutations!` / `disable_mutations!` — create/update/delete mutations.
|
|
521
|
+
* `enable_run_actions!` / `disable_run_actions!` — batch/member/collection
|
|
522
|
+
action mutations.
|
|
523
|
+
* `enable_policies!` / `disable_policies!` — object `activeadmin_policies` and
|
|
524
|
+
inclusion in the `activeadmin_policies` resources matrix.
|
|
525
|
+
* `identity` — declare GraphQL id columns (and optional `separator`, `encode`,
|
|
526
|
+
`decode`) when the model has no ActiveRecord primary key and no `id` column
|
|
527
|
+
(RFC 0007).
|
|
382
528
|
* `type_name` (or `graphql_name`) — overrides the default GraphQL type name
|
|
383
529
|
derived from the model (object types, mutations, and Rails enum GraphQL
|
|
384
530
|
types use this basename).
|