feat: remove scope inheritance, add do-block form for scope options#2
Merged
C-Sinclair merged 1 commit intomainfrom Apr 21, 2026
Merged
Conversation
- Remove `inherits` option and positional-list arg from the scope DSL. - Remove `:inherits` field from AshGrant.Dsl.Scope struct. - Simplify Info.resolve_scope_filter/3 and resolve_write_scope_filter/3 to direct lookups (no parent walking). - Remove inheritance-aware DSL resolution from AddArgumentResolvers. - Move `inherits` from positional arg to a removed concept so the 2-arg + do-block form works: `scope :name, expr(...) do description ... end`. - Migrate all test resources and guides to inline combined filters with `and`. - Update usage-rules.md, README, CHANGELOG, and migration guide.
C-Sinclair
added a commit
that referenced
this pull request
Apr 21, 2026
Resolves conflicts from two changes landed on main: - #2 removed scope inheritance (no impact here — grants don't use scope inheritance; tests still combine conditions inline with `and`). - #4 broke the compile-time cycle between resource and domain by removing the MergeDomainConfig transformer and the ValidateResolverPresent transformer, moving resolver-merge logic into AshGrant.Info.resolver/1 at runtime and turning ValidateResolverPresent into a verifier. Adjustments to this branch: - Dropped lib/ash_grant/transformers/validate_resolver_present.ex — the file was deleted on main (replaced by a verifier). My earlier explicit before?/after? guards in that file were no longer needed. - Reintegrated NormalizeGrants and SynthesizeGrantsResolver into the new transformer list (main-first ordering, no references to the now-gone MergeDomainConfig). - Added ValidateGrantReferences to the verifier list alongside the new ValidateResolverPresent and ValidateScopes verifiers. - Cleaned before?/after? in NormalizeGrants and SynthesizeGrantsResolver to reference only transformers that still exist. Full suite still green (1089 tests, 1 pre-existing unrelated failure). Credo clean on all new files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes
inheritsfrom the scope DSL and enables a do-block form for settingdescription(and any future scope option):Breaking change:
inheritsis gone. The old positional form (scope :own_draft, [:own], expr(status == :draft)) and the keyword form (scope :name, expr(...), inherits: [:parent]) no longer compile. Write each scope as one expression:Why: scope inheritance added hidden coupling (child behaviour depended on parent filters that might live in a different module), interacted awkwardly with
write:and argument-based scopes, and — becauseinheritswas an optional positional arg — blockedscopefrom supporting Spark do-blocks at all. Inlining withandis mechanically trivial, reads plainly, and shows up straight inAshGrant.explain/4.Domain-level scope merging is unchanged — a resource still sees scopes defined on its domain. Only scope-to-scope inheritance is removed.
Net change
Net −191 LoC across lib/. Info's
resolve_scope_filter/3is now a direct lookup;AddArgumentResolverslost the recursive DSL-state walker.Docs
usage-rules.md: scope entity section updated, inheritance rule replaced with "combine inline" DO.README.md,guides/scopes.md,guides/authorization-patterns.md,guides/scope-naming-convention.md,guides/getting-started.md,guides/advanced-patterns.md: removed inheritance references, updated examples.guides/migration.md: new section explaining the removal and migration path.CHANGELOG.md(Unreleased): breaking change + added do-block form.Test plan
mix compile --warnings-as-errorscleanmix test— 1045 tests pass (1 pre-existing failure indefault_field_policies_test.exs, unrelated)mix format --check-formattedcleanmix credo— only pre-existing non-blocking suggestionstest/ash_grant/scope_dsl_test.exs