feat: v2 evaluation engine — resolver chain, conditions, resource policies#1
Merged
Conversation
Introduces the PolicyResolver contract for resolver-chain evaluation and implements IdentityPolicyResolver which resolves role-based PolicyStatements (Allow/Deny) from subject assignments, with support for both global and scoped contexts.
…ver chain BoundaryPolicyResolver reads boundaries from BoundaryStore and produces Deny statements for permissions outside the ceiling, wiring into the DefaultEvaluator's resolver chain alongside IdentityPolicyResolver. Unskips all Task 2.1 boundary tests across CacheInvalidationTest, CachedBoundaryLookupTest, EvaluationPipelineTest, and SecurityTest.
…trait Introduces ResourcePolicy model, EloquentResourcePolicyStore, ResourcePolicyResolver, and completes the HasResourcePolicies trait with attachPolicy/detachPolicy methods. Wires the resolver into the chain and adds 15 feature tests covering attach, detach, type-level vs instance-level policy retrieval, and condition hydration.
Moves Sanctum personal access token ability checking out of the evaluator core and into a dedicated SanctumPolicyResolver that produces Deny statements for permissions not covered by the current token's abilities. Supports wildcard ability patterns and the '*' full-access bypass. Unskips and implements all 11 Sanctum-related tests.
- Fix stale error message in ExplainCommand referencing policy-engine.explain (now policy-engine.trace) - Add Conditions namespace to approved list in ArchitectureTest - Fix resolver arch test: split into PolicyResolver (4 resolvers) and ScopeResolver (ModelScopeResolver) checks - Convert consecutive // comment blocks to /* */ block syntax across 4 test files to satisfy arch rule
…ver system Narrow mixed types from array access and config() calls to satisfy PHPStan level 9 strict typing. Fixes 45 errors spanning condition evaluators, document parser/importer, cached evaluator, resolvers, service provider, and Eloquent stores.
Widen parser method param types from array<string, mixed> to array<mixed> so PHPStan on PHP 8.4 (where json_decode returns mixed values) accepts the calls. Add targeted @var annotations for constructor arguments.
…m source Widen parser method param types so PHPStan on PHP 8.4 accepts json_decode output. Rename v1/v2 method names and comments to indexed/keyed terminology throughout document system.
Pest v3's Laravel plugin doesn't support Laravel 13, causing CI failures on the Laravel 13 matrix. Upgrade pest, pest-plugin-laravel, and pest-plugin-mutate from ^3.0 to ^4.0.
The large-scale benchmark (10K users, 500 groups) exhausts MySQL container memory on CI runners, crashing the server mid-run and failing all subsequent tests with "MySQL server has gone away". Benchmarks are now in their own Pest group and excluded from all CI jobs. Run on-demand with: vendor/bin/pest --group=benchmark
Reduce InnoDB buffer pool to 64M, disable performance schema, binary logging, and mysqlx. Use tmpfs for datadir to avoid disk I/O pressure on runners.
MySQL 8.4 OOMs on GitHub Actions runners despite memory tuning. MariaDB is wire-compatible, lighter on memory, and uses the same pdo_mysql driver.
MariaDB lacks functional index support needed by migration 0006. Reverting to MySQL 8.4 with aggressive memory tuning to address the OOM issue: performance-schema=OFF, 64M buffer pool, no binlog, tmpfs datadir.
Merge docker-compose.test.yml into docker-compose.yml and remove the unused Dockerfile. Revert from MariaDB back to MySQL 8.4 with memory tuning (performance-schema=OFF, 64M buffer pool, no binlog, tmpfs datadir) to test whether OOM is resolved.
MySQL 8.4 consistently OOMs on GitHub Actions runners. Remove it from the test matrix, docker-compose, and supported databases. Bump checkout to v6 and cache to v5 for Node.js 24 support.
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
Redesigns the evaluation layer around the universal authorization question: given this principal wants to perform this action on this resource in this context, is it allowed?
PolicyResolverimplementations. Each resolver producesPolicyStatements; the evaluator collects, filters, and applies deny-wins across all sources.attribute_equals,attribute_in,time_between,ip_range,environment_equals) and a pluggable registry for custom types.resource_policiestable,HasResourcePoliciestrait, andResourcePolicyResolver.Principalcarries subject attributes,Resourcecarries target attributes,Contextcarries scope + environment data. All available to condition evaluators.$user->can('posts.update')works exactly as before. New capabilities (resource, environment, conditions) are opt-in via trailing parameters.Key changes
Evaluatorcontract collapses to singleevaluate(EvaluationRequest): EvaluationResultIdentityPolicyResolver,BoundaryPolicyResolver,ResourcePolicyResolver,SanctumPolicyResolverHasResourcePoliciestraitexplainkey →trace, newresolversarrayStats
Test plan