Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

refactor: check using weighted graph#2816

Merged
yissellokta merged 57 commits into
mainopenfga/openfga:mainfrom
check-wgopenfga/openfga:check-wgCopy head branch name to clipboard
Feb 24, 2026
Merged

refactor: check using weighted graph#2816
yissellokta merged 57 commits into
mainopenfga/openfga:mainfrom
check-wgopenfga/openfga:check-wgCopy head branch name to clipboard

Conversation

@elbuo8

@elbuo8 elbuo8 commented Nov 19, 2025

Copy link
Copy Markdown
Member

Description

What problem is being solved?

How is it being solved?

What changes are made to solve it?

References

Review Checklist

  • I have clicked on "allow edits by maintainers".
  • I have added documentation for new/changed functionality in this PR or in a PR to openfga.dev [Provide a link to any relevant PRs in the references section above]
  • The correct base branch is being used, if not main
  • I have added tests to validate that the change in functionality is working as expected

Summary by CodeRabbit

  • New Features

    • V2 authorization check engine with pluggable strategies (including recursive and weight‑2) and model-graph resolver.
    • Support for contextual tuples in checks and list operations.
    • Experimental weighted-graph check and optional background shadow validation.
  • Tests

    • Large expansion of unit/integration tests covering new strategies, recursive flows, iterators, and contextual tuple behavior.
    • Test framework updated to exercise contextual modes.
  • Bug Fixes / Changes

    • Simplified invariant cache key composition (may affect existing cache keys).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Nov 19, 2025

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds a new weighted-graph authorization check subsystem: request/response modeling, a pluggable Resolver with Default/Recursive/Weight2/bottom-up strategies, iterator utilities, a modelgraph package with cached resolver, server integration behind experimental flags, and extensive unit tests and mocks.

Changes

Cohort / File(s) Summary
Configuration & Dependencies
\.golangci\.yaml, go\.mod
Disabled gocritic.ifElseChain in linter config; updated github.com/openfga/language/pkg/go requirement version.
Test Assets
assets/tests/consolidated_1_1_tests.yaml
Removed multiple invalidated test cases and replaced with explanatory comments.
Core Check Engine & API
internal/check/check.go, internal/check/interface.go, internal/check/mock_resolver.go
Introduces Resolver and Config public types, ResolveCheck entrypoint, CheckResolver/Strategy interfaces, and a gomock-based MockCheckResolver; implements planning/caching/strategy wiring.
Bottom-up Resolution Engine
internal/check/bottom_up.go, internal/check/bottom_up_test.go
New streaming, multi-stage bottom-up evaluator with union/intersection/difference resolvers, iterator builders, batching, error propagation and panic guards; comprehensive tests.
Strategies: Default / Recursive / Weight2
internal/check/default.go, internal/check/default_test.go, internal/check/recursive.go, internal/check/recursive_test.go, internal/check/weight2.go, internal/check/weight2_test.go, internal/check/strategies.go
Adds DefaultStrategy (concurrent pool), Recursive (multi-hop BFS traversal), Weight2 (two-producer intersection), planner-backed strategy keys/configs, and extensive tests.
Request / Response Modeling
internal/check/request.go, internal/check/request_test.go, internal/check/response.go
Adds Request type with validation, invariant/cache key derivation, contextual tuple indexing by user/object, cloning; Response/ResponseMsg/ResponseCacheEntry types and tests.
Tuple Filters
internal/check/filters.go
Adds condition-based and uniqueness tuple filters used by iterators.
Iterator Utilities & Message Types
internal/iterator/message.go, internal/iterator/channel.go, internal/iterator/concat.go, internal/iterator/merge.go, internal/iterator/filter.go, internal/iterator/skip.go
New Msg/ValueMsg types, channel bridge (ToChannel/FromChannel/Drain), Concat, Merge (deduped merge), Filtered iterator with FilterFunc, and SkipTo helper; Stop/head semantics refined.
Iterator Tests
internal/iterator/*_test.go
Comprehensive tests for channel, concat, merge, filter, skip and stream behaviors with cancellation/error scenarios.
Stream / Fan-in adjustments
internal/iterator/stream.go, internal/iterator/fan_in.go, internal/iterator/stream_test.go
Moved Msg type to message.go, replaced manual drain with Drain calls, simplified SkipToTargetObject, removed duplicate Drain from fan_in; adjusted tests.
Concurrency
internal/concurrency/concurrency.go
Added exported sentinel ErrShortCircuit.
Model Graph & Resolver
internal/modelgraph/model.go, internal/modelgraph/resolver.go, internal/modelgraph/*_test.go
New AuthorizationModelGraph wrapper with condition evaluables, traversal/flattening and recursion helpers; AuthorizationModelGraphResolver with caching/TTL and datastore integration; tests added.
Planner Mocks
internal/mocks/mock_planner.go
Generated gomock implementations for planner.Manager and planner.Selector.
Legacy Graph Updates
internal/graph/resolve_check_request.go, internal/graph/weight_two_resolver_test.go
Added objectType/userType accessors to ResolveCheckRequest; relaxed Stop() mock expectations in tests.
Server Integration & Flags
pkg/server/server.go, pkg/server/check.go, pkg/server/config/config.go
Added authzModelGraphResolver to Server, new experimental flags weighted_graph_check and shadow_weighted_graph_check, new v2Check and shadowV2Check flows and shadow comparison execution.
Check Command & Error Mapping
pkg/server/commands/check.go, pkg/server/commands/errors.go
New CheckQueryV2 builder/Execute path wiring into the Resolver; updated error handling to map check-related errors and added new public error types (InvalidTupleError, InvalidRelationError, ThrottledError).
Storage: Cache & Tuple Mapping
pkg/storage/cache.go, pkg/storage/tuple_mappers.go, pkg/storage/cache_test.go
Changed invariant cache key composition (write now uses AuthorizationModelID only); extracted MapUserset/MapTTU public functions and delegated mappers; tests updated to reflect key format.
Integration Test Harness
tests/check/check.go, tests/check/check_test.go, tests/check/check_userset.go
Added contextual-tuples mode to tests, modelgraph initialization in test setup, RunMatrixTests signature/name changes, propagation of contextual tuples into Check/List requests, and new error-code fields on assertions; added TestContextualTuplesMemory entrypoint.
Removed / Adjusted Tests
internal/graph/cached_resolver_test.go, internal/graph/resolve_check_request_test.go, assets/tests/...
Removed or relaxed several unit and asset test cases; some assertions removed or converted to comments.

Sequence Diagram

sequenceDiagram
    actor Client
    participant Server
    participant CheckQueryV2
    participant Resolver
    participant ModelGraph
    participant Strategy
    participant BottomUp
    participant Datastore

    Client->>Server: CheckRequest
    Server->>CheckQueryV2: Execute(ctx, req)
    CheckQueryV2->>ModelGraph: Ensure/Resolve model graph
    ModelGraph-->>CheckQueryV2: AuthorizationModelGraph
    CheckQueryV2->>Resolver: New(Config) / ResolveCheck(ctx, Request)
    Resolver->>ModelGraph: Validate tuple types & build edges
    Resolver->>Strategy: Select & Execute strategy (Default/Recursive/Weight2)
    alt Default / Weight2 uses BottomUp
        Strategy->>BottomUp: resolve rewrites / unions / operators
        BottomUp->>Datastore: Read tuples / ReadStartingWithUser
        Datastore-->>BottomUp: TupleKeys stream
        BottomUp-->>Resolver: Streamed ResponseMsgs (allowed/error)
        Resolver-->>Strategy: Aggregated Response
    else Recursive strategy
        Strategy->>Resolver: ResolveCheck per discovered ID (BFS)
        Resolver->>Datastore: Read tuples per ID
        Datastore-->>Resolver: Tuple streams
        Resolver-->>Strategy: Responses aggregated with visited tracking
    end
    Strategy-->>Resolver: Final Response
    Resolver-->>CheckQueryV2: Response
    CheckQueryV2-->>Server: CheckResponse
    Server-->>Client: CheckResponse
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Areas requiring extra attention:

  • internal/check/bottom_up.go — complex streaming, backpressure, merge/intersection/difference logic and panic/error propagation.
  • internal/check/recursive.go — concurrency, visited-set correctness, multi-hop traversal termination/cancellation.
  • internal/check/request.go & pkg/storage/cache.go — invariant/cache key changes and contextual tuple indexing/cloning semantics.
  • internal/iterator/* — correctness of Drain/ToChannel/FromChannel/Concat/Merge/Filter Stop/Head behavior under cancellation and errors.
  • internal/modelgraph/* — flattening/recursion heuristics and condition evaluable wiring.
  • pkg/server integration and new experimental flag paths (v2Check/shadowV2Check) — ensure safe fallback and no regression of existing check flows.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • adriantam
  • senojj
  • poovamraj

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.38% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: check using weighted graph' directly describes the main change across the PR: a comprehensive refactoring of the authorization check system to use weighted graph-based resolution instead of the previous typesystem-based approach.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch check-wg

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@socket-security

socket-security Bot commented Nov 19, 2025

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedgithub.com/​openfga/​language/​pkg/​go@​v0.2.0-beta.2.0.20251027165255-0f8f255e5f6c ⏵ v0.2.0-beta.2.0.20251202173232-1e8bf16f1dce100 +1100100100100

View full report

@elbuo8

elbuo8 commented Nov 19, 2025

Copy link
Copy Markdown
Member Author

@claude

@github-actions

This comment has been minimized.

@elbuo8 elbuo8 added the Skip-Changelog Indicates that a PR does not need a changelog entry label Nov 19, 2025
github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

@codecov

codecov Bot commented Nov 20, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.45083% with 249 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.00%. Comparing base (e04bde9) to head (a7103ef).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/check/check.go 91.45% 34 Missing and 17 partials ⚠️
internal/check/bottom_up.go 89.63% 22 Missing and 14 partials ⚠️
internal/iterator/channel.go 62.97% 27 Missing and 3 partials ⚠️
pkg/server/check.go 44.00% 26 Missing and 2 partials ⚠️
internal/check/request.go 88.19% 13 Missing and 13 partials ⚠️
internal/check/recursive.go 90.06% 13 Missing and 6 partials ⚠️
internal/modelgraph/model.go 88.43% 6 Missing and 5 partials ⚠️
internal/iterator/merge.go 88.47% 5 Missing and 4 partials ⚠️
internal/check/default.go 92.48% 5 Missing and 2 partials ⚠️
pkg/server/commands/errors.go 50.00% 3 Missing and 3 partials ⚠️
... and 8 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2816      +/-   ##
==========================================
- Coverage   90.27%   90.00%   -0.27%     
==========================================
  Files         169      186      +17     
  Lines       17665    19776    +2111     
==========================================
+ Hits        15946    17798    +1852     
- Misses       1134     1318     +184     
- Partials      585      660      +75     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@elbuo8

elbuo8 commented Dec 2, 2025

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Dec 2, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

♻️ Duplicate comments (2)
internal/iterator/channel.go (1)

33-41: Error handling loop continues on persistent errors.

When the iterator returns a non-terminal error (not IterIsDoneOrCancelled), the error is sent through the channel but the loop continues. If the underlying iterator consistently fails, this could flood the channel with error messages.

internal/check/check.go (1)

800-822: Consider deduplicating contextual and database tuples.

Contextual tuples are prepended to database tuples without deduplication. If the same tuple exists in both sources, it will be processed twice, which could lead to redundant condition evaluations and wasted computation.

The BuildUniqueTupleKeyFilter only deduplicates based on visited usersets during graph traversal, not between the two tuple sources.

🧹 Nitpick comments (29)
.golangci.yaml (1)

31-33: Verify necessity of disabling ifElseChain linter check.

Disabling the ifElseChain check indicates the new check engine uses complex if-else structures. While sometimes necessary, this often signals code that could benefit from refactoring (e.g., using switch statements, polymorphism, or strategy patterns) for better readability and maintainability. Ensure this is intentional and that alternative patterns have been considered.

internal/concurrency/concurrency.go (1)

3-13: Consider documenting ErrShortCircuit for future callers

The sentinel error itself is fine, but since it’s exported it would benefit from a brief Go-style comment describing when callers should return or check for this error (e.g., to short‑circuit concurrent work).

assets/tests/consolidated_1_1_tests.yaml (1)

2758-2812: Invalid test is correctly disabled; consider relocating it

Commenting out the exclusion_between_userset_and_type test with an explanation is safe and keeps the suite aligned with current semantics. To avoid long‑term drift, consider moving this scenario into a dedicated “invalid model / unsupported patterns” test or documentation section instead of leaving a large commented block inline.

pkg/storage/tuple_mappers.go (1)

72-83: Exported mapping helpers preserve behavior; add brief docs

MapUserset correctly mirrors the previous userset mapping logic (including the guard on missing relations), and MapTTU simply returns the user string, so existing mapper behavior is preserved. Since these helpers are now exported, consider:

  • Adding short Go‑style comments explaining what each expects (e.g., that MapUserset is intended for tuples whose user is a userset and may return an error otherwise, and that t must be non‑nil).
  • Optionally noting that MapTTU currently never returns an error but uses the (string, error) shape for consistency and potential future validation.

Also applies to: 114-120

internal/iterator/message.go (1)

5-8: Clean message types for iterator results.

The Msg struct provides a clear way to transmit iterator results and errors through channels. The note at line 6 acknowledges that Iter could be made generic if needed in the future.

Consider making Msg generic now to avoid a breaking change later:

-type Msg struct {
-	Iter storage.Iterator[string] // NOTE: This could be made completely generic if needed
+type Msg[T any] struct {
+	Iter storage.Iterator[T]
 	Err  error
 }

However, this can be deferred if string iterators are the only use case for now.

internal/iterator/skip.go (1)

9-33: Logic is correct, but consider performance for large skips.

The SkipTo function correctly advances the iterator to the target value using lexicographic comparison and properly handles context cancellation and iterator completion.

For iterators with many elements to skip, this linear scan could be inefficient. If the underlying iterator supports seeking or batch operations, consider optimizing for large skip distances. However, for typical use cases with sorted tuples, this implementation should be adequate.

tests/check/check_test.go (1)

76-80: Track: Commented-out test code needs follow-up.

The TODO comment indicates tests need deprecation before the weighted graph check can be enabled for the full test suite. Consider creating a tracking issue to ensure this doesn't get forgotten.

Would you like me to open an issue to track enabling the weighted graph check tests after the necessary deprecations?

internal/check/default_test.go (1)

26-27: Remove unused gomock controller at test function level.

The ctrl created at line 26-27 is never used since each subtest creates its own controller (line 204-205). This is harmless but creates unnecessary allocation.

 func TestDefaultUserset(t *testing.T) {
 	t.Cleanup(func() {
 		goleak.VerifyNone(t)
 	})
-	ctrl := gomock.NewController(t)
-	defer ctrl.Finish()

 	storeID := ulid.Make().String()
pkg/server/server.go (1)

895-897: Add TTL configuration option for authzModelGraphResolver to align with cache settings pattern.

The hardcoded 168-hour TTL should be configurable. The codebase already has established patterns for cache TTL configuration (e.g., WithCheckQueryCacheTTL, WithCheckIteratorCacheTTL). The authzModelGraphResolver should use a similar configurable option rather than hardcoding the value, especially since the TODO acknowledges this need.

Regarding lifecycle management: AuthorizationModelGraphResolver has no Close() or Stop() methods and does not own the cache (it's passed in via s.sharedDatastoreResources.CheckCache), so no cleanup in Server.Close() is required.

internal/iterator/merge_test.go (1)

15-23: Consider adding goroutine leak detection for consistency.

The concat_test.go file uses goleak.VerifyNone(t) for detecting goroutine leaks. For consistency across the iterator test suite, consider adding the same here.

 func TestMergedIterator(t *testing.T) {
+	t.Cleanup(func() {
+		goleak.VerifyNone(t)
+	})
+
 	compareFn := func(a, b string) int {

You'll also need to add the import:

import "go.uber.org/goleak"
internal/iterator/concat.go (1)

82-85: Consider using a sentinel error for unsupported Head operation.

Using a plain fmt.Errorf makes it harder for callers to programmatically check for this specific condition. A sentinel error would allow errors.Is() checks.

+var ErrHeadNotSupported = errors.New("head() not supported on concat iterator")
+
 func (c *concatIterator[T]) Head(_ context.Context) (T, error) {
 	var zero T
-	return zero, fmt.Errorf("head() not supported on concat iterator")
+	return zero, ErrHeadNotSupported
 }
internal/check/filters.go (1)

17-23: Potential nil map access and O(n) lookup on every tuple.

Two concerns:

  1. slices.Contains(conditions, ...) is O(n) per tuple. If conditions is large and many tuples are processed, consider using a map[string]struct{} for O(1) lookups.
  2. model.GetConditions()[t.GetCondition().GetName()] may return nil if the condition name exists in conditions but not in the model's condition map, which could cause issues in EvaluateTupleCondition.

Consider converting conditions to a set for better performance:

-func evaluateCondition(ctx context.Context, model *modelgraph.AuthorizationModelGraph, conditions []string, t *openfgav1.TupleKey, reqCtx *structpb.Struct) (bool, error) {
-	if !slices.Contains(conditions, t.GetCondition().GetName()) {
+func evaluateCondition(ctx context.Context, model *modelgraph.AuthorizationModelGraph, conditionsSet map[string]struct{}, t *openfgav1.TupleKey, reqCtx *structpb.Struct) (bool, error) {
+	if _, ok := conditionsSet[t.GetCondition().GetName()]; !ok {
 		return false, nil
 	}

The set conversion can happen once in BuildConditionTupleKeyFilter rather than on every filter invocation.

internal/iterator/filter_test.go (1)

239-253: Shared seenTuples state may cause flaky tests.

The seenTuples sync.Map and uniqueFilter are defined at the test function level but used by both_filters_applied sub-test. Since this map accumulates state, running this test multiple times or in parallel could cause unexpected behavior. Consider moving the map initialization inside the sub-test.

 func TestFilter_MultipleFilters(t *testing.T) {
 	conditionFilter := func(_ OperationType, tupleKey *openfgav1.TupleKey) (bool, error) {
 		return tupleKey.GetCondition().GetName() == "condition1", nil
 	}
 
-	seenTuples := &sync.Map{}
-	//nolint:unparam
-	uniqueFilter := func(_ OperationType, tupleKey *openfgav1.TupleKey) (bool, error) {
-		key := tuple.TupleKeyToString(tupleKey)
-		if _, exists := seenTuples.LoadOrStore(key, struct{}{}); exists {
-			return false, nil
-		}
-		return true, nil
-	}
-
 	t.Run("both_filters_applied", func(t *testing.T) {
+		seenTuples := &sync.Map{}
+		uniqueFilter := func(_ OperationType, tupleKey *openfgav1.TupleKey) (bool, error) {
+			key := tuple.TupleKeyToString(tupleKey)
+			if _, exists := seenTuples.LoadOrStore(key, struct{}{}); exists {
+				return false, nil
+			}
+			return true, nil
+		}
+
 		tuples := []*openfgav1.TupleKey{
internal/check/weight2_test.go (2)

411-412: Misleading comment: MaxTimes(3) does not mean "any number of calls".

The comment states "Allow any number of calls" but MaxTimes(3) limits expectations to at most 3 calls. Either update the comment to be accurate or use AnyTimes() if truly unlimited calls are intended.

 		mockDatastore.EXPECT().ReadStartingWithUser(gomock.Any(), storeID, gomock.Any(), gomock.Any()).
-			MaxTimes(3). // Allow any number of calls
+			MaxTimes(3). // Allow up to 3 calls (members, public_restricted, restricted)
 			DoAndReturn(func(ctx context.Context, sID string, filter storage.ReadStartingWithUserFilter, opts storage.ReadStartingWithUserOptions) (storage.TupleIterator, error) {

867-869: Same misleading comment pattern.

 		mockDatastore.EXPECT().ReadStartingWithUser(gomock.Any(), storeID, gomock.Any(), gomock.Any()).
-			MaxTimes(3). // Allow any number of calls
+			MaxTimes(3). // Allow up to 3 calls (members, public_restricted, restricted)
 			DoAndReturn(func(ctx context.Context, sID string, filter storage.ReadStartingWithUserFilter, opts storage.ReadStartingWithUserOptions) (storage.TupleIterator, error) {
internal/check/bottom_up_test.go (2)

1721-1722: Misleading comment: MaxTimes(3) limits to at most 3 calls.

 		mockDatastore.EXPECT().ReadStartingWithUser(gomock.Any(), storeID, gomock.Any(), gomock.Any()).
-			MaxTimes(3). // Allow any number of calls
+			MaxTimes(3). // Allow up to 3 calls for viewer, editor, commenter
 			DoAndReturn(func(ctx context.Context, sID string, filter storage.ReadStartingWithUserFilter, opts storage.ReadStartingWithUserOptions) (storage.TupleIterator, error) {

1838-1839: Same misleading comment pattern.

 		mockDatastore.EXPECT().ReadStartingWithUser(gomock.Any(), storeID, gomock.Any(), gomock.Any()).
-			MaxTimes(3). // Allow any number of calls
+			MaxTimes(3). // Allow up to 3 calls for viewer, editor, commenter
 			DoAndReturn(func(ctx context.Context, sID string, filter storage.ReadStartingWithUserFilter, opts storage.ReadStartingWithUserOptions) (storage.TupleIterator, error) {
pkg/server/check.go (1)

187-189: Consider bounding shadow check concurrency.

The shadow v2 check launches an unbounded goroutine for each request when the feature flag is enabled. Under high load, this could consume excessive resources. Consider using a semaphore or worker pool to limit concurrent shadow checks.

internal/iterator/merge.go (1)

30-52: Minor: initialize() sets flag before completion.

The initialized flag is set to true (line 34) before fetching values from either iterator. If an error occurs during initialization, subsequent calls to initialize() will return nil, potentially leaving the iterator in a partially initialized state.

Consider setting initialized = true after successful initialization:

 func (m *MergedIterator[T]) initialize(ctx context.Context) error {
 	if m.initialized {
 		return nil
 	}
-	m.initialized = true

 	// Fetch first value from iter1
 	current, err := m.iter1.Next(ctx)
 	if err != nil && !errors.Is(err, storage.ErrIteratorDone) {
 		return err
 	}
 	m.hasNext1 = !errors.Is(err, storage.ErrIteratorDone)
 	m.current1 = current

 	// Fetch first value from iter2
 	current2, err2 := m.iter2.Next(ctx)
 	if err2 != nil && !errors.Is(err2, storage.ErrIteratorDone) {
 		return err2
 	}
 	m.hasNext2 = !errors.Is(err2, storage.ErrIteratorDone)
 	m.current2 = current2
+
+	m.initialized = true
 	return nil
 }
internal/iterator/channel.go (1)

133-146: Stop() doesn't await Drain() completion.

The Stop() method calls Drain(c.source) (line 145) but discards the returned *sync.WaitGroup. This means Stop() returns before the channel is fully drained and nested iterators are stopped. Consider waiting for drain completion or documenting this as intentional fire-and-forget behavior.

 func (c *channelIterator) Stop() {
 	if c.stopped {
 		return
 	}

 	c.stopped = true
 	if c.current != nil {
 		c.current.Stop()
 		c.current = nil
 	}

 	// Drain remaining messages and stop their iterators
-	Drain(c.source)
+	if wg := Drain(c.source); wg != nil {
+		wg.Wait()
+	}
 }
internal/check/default.go (1)

96-130: Consider documenting the buffer size choice.

The responsesChan buffer size of 100 is hardcoded. While the comment mentions it "needs to be buffered to prevent out of order closed events," a brief explanation of why 100 specifically (or making it proportional to concurrencyLimit) would help future maintainers.

-	responsesChan := make(chan ResponseMsg, 100) // needs to be buffered to prevent out of order closed events
+	// Buffer size should accommodate in-flight responses from concurrent workers to prevent
+	// blocking when the consumer is processing a successful result. Using concurrencyLimit
+	// as a baseline ensures workers won't block waiting to send responses.
+	responsesChan := make(chan ResponseMsg, s.concurrencyLimit)
internal/check/strategies.go (1)

10-55: Inconsistent export naming for plan configurations.

weight2Plan is unexported (lowercase) while DefaultPlan, DefaultRecursivePlan, and RecursivePlan are exported. If weight2Plan is intentionally package-private, this is fine, but it creates an inconsistency in the API surface.

If this should be exported for consistency:

-var weight2Plan = &planner.PlanConfig{
+var Weight2Plan = &planner.PlanConfig{
internal/check/weight2.go (2)

15-17: Unused constants BaseIndex and DifferenceIndex.

These constants are defined but not used anywhere in this file. If they're intended for use elsewhere, consider moving them to a shared location or removing them if unused.


69-74: Redundant context cancellation.

The caller (Userset/TTU) doesn't create a cancellable context before calling execute. While defer cancel() is defensive, consider whether the caller should own context cancellation for consistency, or document why execute creates its own cancellation scope.

pkg/server/commands/check.go (1)

85-95: Consider validating required dependencies.

NewCheckQuery only sets a default logger. If Execute is called without setting model, datastore, or planner, it may cause nil pointer dereferences or unexpected behavior downstream. Consider either:

  1. Requiring critical dependencies as constructor parameters
  2. Adding validation in Execute before proceeding
 func NewCheckQuery(opts ...CheckQueryV2Option) *CheckQueryV2 {
 	q := &CheckQueryV2{
 		logger: logger.NewNoopLogger(),
 	}
 
 	for _, opt := range opts {
 		opt(q)
 	}
 
 	return q
 }
+
+func (q *CheckQueryV2) validate() error {
+	if q.model == nil {
+		return errors.New("model is required")
+	}
+	if q.datastore == nil {
+		return errors.New("datastore is required")
+	}
+	return nil
+}
internal/check/recursive.go (1)

189-192: Goroutine leak if context is cancelled before pool.Wait completes.

The goroutine that closes responsesChan runs independently. If the parent context is cancelled and recursiveMatch returns early (line 197), this goroutine continues to run until pool.Wait() completes, which could be delayed if goroutines are blocked.

Consider using a select with context cancellation in the wait goroutine:

 go func() {
-	_ = pool.Wait()
-	close(responsesChan)
+	done := make(chan struct{})
+	go func() {
+		_ = pool.Wait()
+		close(done)
+	}()
+	<-done
+	close(responsesChan)
 }()
internal/modelgraph/model.go (2)

14-16: Consider adding sentinel error wrapping for better diagnostics.

ErrGraphError is generic and used in multiple places. Consider wrapping with additional context where it's returned, or defining more specific errors.


54-71: Consider more specific error for "edge not found for user type".

When no edge matches the userType, the method returns a generic ErrGraphError. A more specific error would help callers distinguish between "node not found", "no edges from node", and "no edge matching user type".

tests/check/check.go (1)

126-129: Skipping tests on model graph failure may hide real issues.

Using t.Skipf when modelgraph.New fails means tests silently pass if there's a model graph construction bug. Consider using t.Fatalf to fail the test explicitly, or log a warning if intentionally skipping unsupported models.

 			_, err := modelgraph.New(model)
 			if err != nil {
-				t.Skipf("modelgraph.New failed: %v", err)
+				t.Fatalf("modelgraph.New failed: %v", err)
 			}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5564c54 and 77c1f85.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (51)
  • .golangci.yaml (1 hunks)
  • assets/tests/consolidated_1_1_tests.yaml (1 hunks)
  • go.mod (1 hunks)
  • internal/check/bottom_up.go (1 hunks)
  • internal/check/bottom_up_test.go (1 hunks)
  • internal/check/check.go (1 hunks)
  • internal/check/default.go (1 hunks)
  • internal/check/default_test.go (1 hunks)
  • internal/check/filters.go (1 hunks)
  • internal/check/interface.go (1 hunks)
  • internal/check/mock_resolver.go (1 hunks)
  • internal/check/recursive.go (1 hunks)
  • internal/check/recursive_test.go (1 hunks)
  • internal/check/request.go (1 hunks)
  • internal/check/request_test.go (1 hunks)
  • internal/check/response.go (1 hunks)
  • internal/check/strategies.go (1 hunks)
  • internal/check/weight2.go (1 hunks)
  • internal/check/weight2_test.go (1 hunks)
  • internal/concurrency/concurrency.go (1 hunks)
  • internal/graph/resolve_check_request.go (6 hunks)
  • internal/graph/weight_two_resolver_test.go (13 hunks)
  • internal/iterator/channel.go (1 hunks)
  • internal/iterator/channel_test.go (1 hunks)
  • internal/iterator/concat.go (1 hunks)
  • internal/iterator/concat_test.go (1 hunks)
  • internal/iterator/fan_in.go (0 hunks)
  • internal/iterator/filter.go (1 hunks)
  • internal/iterator/filter_test.go (1 hunks)
  • internal/iterator/merge.go (1 hunks)
  • internal/iterator/merge_test.go (1 hunks)
  • internal/iterator/message.go (1 hunks)
  • internal/iterator/skip.go (1 hunks)
  • internal/iterator/skip_test.go (1 hunks)
  • internal/iterator/stream.go (2 hunks)
  • internal/iterator/stream_test.go (0 hunks)
  • internal/mocks/mock_planner.go (1 hunks)
  • internal/modelgraph/model.go (1 hunks)
  • internal/modelgraph/model_test.go (1 hunks)
  • internal/modelgraph/resolver.go (1 hunks)
  • internal/modelgraph/resolver_test.go (1 hunks)
  • pkg/server/check.go (3 hunks)
  • pkg/server/commands/check.go (1 hunks)
  • pkg/server/commands/errors.go (3 hunks)
  • pkg/server/config/config.go (1 hunks)
  • pkg/server/server.go (3 hunks)
  • pkg/storage/cache.go (1 hunks)
  • pkg/storage/tuple_mappers.go (3 hunks)
  • tests/check/check.go (9 hunks)
  • tests/check/check_test.go (4 hunks)
  • tests/check/check_userset.go (2 hunks)
💤 Files with no reviewable changes (2)
  • internal/iterator/stream_test.go
  • internal/iterator/fan_in.go
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-07-02T18:00:27.063Z
Learnt from: senojj
Repo: openfga/openfga PR: 2538
File: pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go:710-712
Timestamp: 2025-07-02T18:00:27.063Z
Learning: In the OpenFGA shared iterator implementation (pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go), multiple state loads within the same iteration cycle are intentional to observe state changes made by other goroutines. The design prioritizes real-time state visibility over consistency within a single iteration, which is appropriate for shared iterator architecture where multiple goroutines update shared state.

Applied to files:

  • internal/iterator/merge_test.go
  • internal/graph/weight_two_resolver_test.go
  • internal/iterator/message.go
  • internal/iterator/filter_test.go
  • internal/check/bottom_up.go
  • internal/iterator/channel_test.go
  • internal/iterator/merge.go
  • internal/iterator/concat.go
  • internal/iterator/channel.go
  • internal/iterator/filter.go
  • internal/iterator/concat_test.go
  • internal/check/bottom_up_test.go
  • internal/iterator/skip.go
  • internal/iterator/stream.go
📚 Learning: 2025-07-29T19:18:31.430Z
Learnt from: senojj
Repo: openfga/openfga PR: 2590
File: pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go:298-303
Timestamp: 2025-07-29T19:18:31.430Z
Learning: In the OpenFGA shared iterator implementation (pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go), the cleanup functions use CompareAndDelete to atomically check and remove items from the internal storage maps. The counters (sf.internalStorage.ctr and sharedIteratorCount) are only decremented when CompareAndDelete returns true, ensuring that metrics are decremented exactly once per item removal. If CompareAndDelete returns false, it means another cleanup call already removed the item and decremented the counters, preventing double-decrementing and metric drift.

Applied to files:

  • internal/iterator/merge_test.go
  • internal/check/bottom_up.go
  • internal/iterator/merge.go
  • internal/iterator/channel.go
  • internal/iterator/filter.go
📚 Learning: 2025-07-02T18:10:58.517Z
Learnt from: senojj
Repo: openfga/openfga PR: 2538
File: pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go:722-722
Timestamp: 2025-07-02T18:10:58.517Z
Learning: In the OpenFGA shared iterator implementation (pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go), the background fetching in fetchAndWait method intentionally uses context.Background() instead of propagating the request context. This design allows the shared background fetching to continue serving all iterator clones even when individual request contexts are cancelled, which is appropriate for the shared iterator architecture.

Applied to files:

  • internal/iterator/merge_test.go
  • internal/check/bottom_up.go
  • internal/iterator/merge.go
  • internal/iterator/concat.go
  • internal/iterator/channel.go
  • internal/check/recursive.go
  • internal/iterator/concat_test.go
  • internal/iterator/skip.go
📚 Learning: 2025-10-16T19:02:25.959Z
Learnt from: senojj
Repo: openfga/openfga PR: 2746
File: pkg/server/commands/reverseexpand/pipeline.go:428-510
Timestamp: 2025-10-16T19:02:25.959Z
Learning: In pkg/server/commands/reverseexpand/pipeline.go, the pipeline uses an indirect context cancellation pattern: when Pipeline::Build's returned iter.Seq is terminated early, the pipeline context is canceled, causing resolvers to stop consuming from sequences, which triggers deferred cleanup (cancel + Stop) in the query function. This means handleDirectEdge and handleTTUEdge can use context.Background() because cancellation propagates through the iteration protocol rather than direct context threading.

Applied to files:

  • internal/check/bottom_up.go
  • internal/check/recursive.go
📚 Learning: 2025-06-20T18:39:47.718Z
Learnt from: adriantam
Repo: openfga/openfga PR: 2518
File: pkg/typesystem/weighted_graph.go:130-134
Timestamp: 2025-06-20T18:39:47.718Z
Learning: In the OpenFGA typesystem weighted graph implementation, when processing edges for intersection operations, the system is designed to gracefully handle disconnected edges by skipping them (returning empty IntersectionEdges{} with nil error) rather than returning explicit errors. This allows list objects to continue operating as a no-op when encountering unexpected edge conditions, supporting graceful degradation of the authorization system.

Applied to files:

  • internal/check/bottom_up.go
  • internal/modelgraph/model_test.go
  • internal/check/weight2.go
  • internal/check/check.go
  • internal/modelgraph/model.go
📚 Learning: 2025-06-20T18:39:39.926Z
Learnt from: adriantam
Repo: openfga/openfga PR: 2518
File: pkg/typesystem/weighted_graph.go:99-104
Timestamp: 2025-06-20T18:39:39.926Z
Learning: In the OpenFGA typesystem's GetEdgesForIntersection method, when direct edges are disconnected (lowestWeight == 0 && edgeNum != 0), the method should return empty IntersectionEdges{} rather than an error. This allows list objects to skip over the edge and become a no-op, providing graceful handling of disconnected edges instead of failing the entire operation.

Applied to files:

  • internal/check/bottom_up.go
  • internal/check/check.go
  • internal/modelgraph/model.go
📚 Learning: 2025-10-16T21:29:53.682Z
Learnt from: senojj
Repo: openfga/openfga PR: 2746
File: pkg/server/commands/reverseexpand/pipeline.go:463-505
Timestamp: 2025-10-16T21:29:53.682Z
Learning: In TTU (tuple-to-userset) edges within OpenFGA authorization models, the target of a tupleset edge cannot be a userset (i.e., cannot be of the form `type#relation`). The target must be just a type. Therefore, when building userFilter entries for TTU edge queries in `handleTTUEdge`, the `Relation` field is correctly left empty.

Applied to files:

  • internal/check/default_test.go
  • assets/tests/consolidated_1_1_tests.yaml
  • internal/check/recursive_test.go
  • internal/check/check.go
  • pkg/server/commands/check.go
  • internal/check/weight2_test.go
📚 Learning: 2025-07-02T18:10:35.417Z
Learnt from: senojj
Repo: openfga/openfga PR: 2538
File: pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go:725-732
Timestamp: 2025-07-02T18:10:35.417Z
Learning: In the OpenFGA shared iterator implementation (pkg/storage/storagewrappers/sharediterator/shared_iterator_datastore.go), the `s.fetching.Swap(true)` atomic operation acts as a guard to ensure only one goroutine can enter the fetch routine and update the shared state at any time. This prevents race conditions in state updates without requiring explicit locking, as only the goroutine that sees the previous fetching value as false gets to proceed with the fetch operation.

Applied to files:

  • internal/iterator/filter.go
🧬 Code graph analysis (27)
internal/iterator/merge_test.go (3)
pkg/storage/tuple_iterators.go (2)
  • NewStaticIterator (236-238)
  • ErrIteratorDone (13-13)
internal/iterator/merge.go (1)
  • Merge (22-28)
internal/mocks/mock_iterator.go (1)
  • NewMockIterator (32-36)
pkg/server/server.go (1)
internal/modelgraph/resolver.go (2)
  • AuthorizationModelGraphResolver (22-26)
  • NewResolver (28-34)
internal/graph/weight_two_resolver_test.go (3)
internal/iterator/message.go (1)
  • Msg (5-8)
internal/iterator/stream.go (1)
  • NewStream (20-25)
internal/mocks/mock_iterator.go (1)
  • NewMockIterator (32-36)
internal/iterator/message.go (1)
pkg/storage/tuple_iterators.go (1)
  • Iterator (17-30)
internal/iterator/filter_test.go (3)
internal/iterator/filter.go (1)
  • NewFilteredIterator (123-133)
pkg/tuple/tuple.go (3)
  • NewTupleKeyWithCondition (172-182)
  • TupleKeyToString (351-357)
  • NewTupleKey (164-170)
pkg/storage/tuple_iterators.go (2)
  • NewStaticTupleKeyIterator (136-143)
  • ErrIteratorDone (13-13)
internal/iterator/channel_test.go (4)
internal/iterator/message.go (1)
  • Msg (5-8)
internal/mocks/mock_iterator.go (1)
  • NewMockIterator (32-36)
internal/iterator/channel.go (2)
  • Drain (11-26)
  • ToChannel (28-45)
pkg/storage/tuple_iterators.go (3)
  • Iterator (17-30)
  • ErrIteratorDone (13-13)
  • IterIsDoneOrCancelled (544-546)
internal/iterator/merge.go (1)
pkg/storage/tuple_iterators.go (2)
  • Iterator (17-30)
  • ErrIteratorDone (13-13)
internal/iterator/concat.go (1)
pkg/storage/tuple_iterators.go (2)
  • Iterator (17-30)
  • ErrIteratorDone (13-13)
internal/iterator/skip_test.go (3)
pkg/storage/tuple_iterators.go (2)
  • NewStaticIterator (236-238)
  • ErrIteratorDone (13-13)
internal/iterator/skip.go (1)
  • SkipTo (9-33)
internal/mocks/mock_iterator.go (1)
  • NewMockIterator (32-36)
internal/check/default_test.go (7)
pkg/testutils/testutils.go (1)
  • MustTransformDSLToProtoWithID (163-168)
internal/check/mock_resolver.go (2)
  • MockCheckResolver (22-26)
  • NewMockCheckResolver (34-38)
internal/check/response.go (1)
  • Response (7-9)
pkg/tuple/tuple.go (2)
  • NewTupleKey (164-170)
  • GetRelation (325-328)
internal/check/request.go (3)
  • Request (24-42)
  • NewRequest (105-179)
  • RequestParams (44-51)
pkg/storage/tuple_iterators.go (1)
  • NewStaticTupleKeyIterator (136-143)
internal/check/default.go (1)
  • NewDefault (32-38)
pkg/server/check.go (6)
pkg/server/config/config.go (2)
  • ExperimentalWeightedGraphCheck (107-107)
  • ExperimentalShadowWeightedGraphCheck (106-106)
pkg/server/server.go (1)
  • Server (161-244)
internal/modelgraph/model.go (1)
  • ErrInvalidModel (16-16)
internal/cachecontroller/cache_controller.go (1)
  • CacheController (58-70)
pkg/server/commands/check.go (2)
  • NewCheckQuery (85-95)
  • WithCheckQueryV2Datastore (37-41)
pkg/server/commands/errors.go (1)
  • CheckCommandErrorToServerError (54-97)
internal/iterator/channel.go (3)
internal/iterator/message.go (2)
  • Msg (5-8)
  • ValueMsg (10-13)
pkg/storage/tuple_iterators.go (3)
  • Iterator (17-30)
  • IterIsDoneOrCancelled (544-546)
  • ErrIteratorDone (13-13)
internal/concurrency/concurrency.go (1)
  • TrySendThroughChannel (26-33)
internal/mocks/mock_planner.go (2)
internal/planner/interface.go (1)
  • Selector (6-9)
internal/planner/config.go (1)
  • PlanConfig (5-42)
internal/modelgraph/model_test.go (2)
pkg/testutils/testutils.go (1)
  • MustTransformDSLToProtoWithID (163-168)
internal/modelgraph/model.go (1)
  • ErrGraphError (14-14)
internal/graph/resolve_check_request.go (1)
pkg/tuple/tuple.go (4)
  • GetType (318-321)
  • IsObjectRelation (331-333)
  • GetRelation (325-328)
  • ToObjectRelationString (337-339)
tests/check/check_userset.go (1)
pkg/tuple/tuple.go (2)
  • Tuple (14-14)
  • User (103-103)
internal/check/check.go (9)
pkg/storage/cache.go (1)
  • InMemoryCache (58-67)
internal/planner/interface.go (2)
  • Manager (12-15)
  • Selector (6-9)
internal/check/default.go (1)
  • NewDefault (32-38)
internal/check/weight2.go (1)
  • NewWeight2 (25-31)
internal/check/request.go (1)
  • Request (24-42)
internal/check/response.go (3)
  • Response (7-9)
  • ResponseCacheEntry (21-24)
  • ResponseMsg (15-19)
internal/graph/graph.go (1)
  • DirectEdge (49-49)
internal/iterator/concat.go (1)
  • Concat (16-21)
internal/iterator/filter.go (1)
  • FilterFunc (22-22)
internal/check/request.go (3)
internal/check/check.go (3)
  • New (63-86)
  • ErrValidation (33-33)
  • CacheKeyPrefix (29-29)
pkg/tuple/tuple.go (9)
  • GetType (318-321)
  • ToObjectRelationString (337-339)
  • GetRelation (325-328)
  • IsObjectRelation (331-333)
  • IsTypedWildcard (396-399)
  • IsValidUser (381-387)
  • From (38-40)
  • SplitObject (280-289)
  • SplitObjectRelation (305-314)
pkg/storage/cache.go (2)
  • WriteInvariantCheckCacheKey (411-437)
  • CheckCacheKeyParams (381-387)
pkg/server/commands/check.go (3)
internal/check/request.go (2)
  • NewRequest (105-179)
  • RequestParams (44-51)
pkg/tuple/tuple.go (1)
  • ConvertCheckRequestTupleKeyToTupleKey (115-121)
internal/check/check.go (2)
  • New (63-86)
  • Config (37-48)
internal/check/weight2_test.go (8)
internal/mocks/mock_storage.go (1)
  • NewMockOpenFGADatastore (721-725)
pkg/storage/storage.go (2)
  • ReadStartingWithUserFilter (289-303)
  • ReadStartingWithUserOptions (133-136)
pkg/storage/tuple_iterators.go (3)
  • NewStaticTupleIterator (126-133)
  • NewStaticTupleKeyIterator (136-143)
  • TupleIterator (32-32)
pkg/tuple/tuple.go (3)
  • Tuple (14-14)
  • NewTupleKey (164-170)
  • User (103-103)
pkg/testutils/testutils.go (1)
  • MustTransformDSLToProtoWithID (163-168)
internal/modelgraph/model.go (1)
  • New (25-44)
internal/check/weight2.go (1)
  • NewWeight2 (25-31)
internal/check/request.go (2)
  • NewRequest (105-179)
  • RequestParams (44-51)
internal/iterator/concat_test.go (3)
pkg/storage/tuple_iterators.go (3)
  • Iterator (17-30)
  • ErrIteratorDone (13-13)
  • IterIsDoneOrCancelled (544-546)
internal/mocks/mock_iterator.go (1)
  • NewMockIterator (32-36)
internal/iterator/concat.go (1)
  • Concat (16-21)
internal/check/default.go (8)
internal/check/request.go (1)
  • Request (24-42)
pkg/storage/tuple_iterators.go (1)
  • TupleKeyIterator (34-34)
internal/modelgraph/model.go (1)
  • ErrGraphError (14-14)
internal/check/interface.go (1)
  • CheckResolver (12-15)
internal/check/response.go (2)
  • Response (7-9)
  • ResponseMsg (15-19)
internal/concurrency/concurrency.go (1)
  • TrySendThroughChannel (26-33)
pkg/tuple/tuple.go (4)
  • SplitObjectRelation (305-314)
  • NewTupleKey (164-170)
  • ToObjectRelationString (337-339)
  • GetRelation (325-328)
internal/check/check.go (1)
  • ErrPanicRequest (34-34)
internal/check/bottom_up_test.go (10)
pkg/storage/storage.go (3)
  • ReadStartingWithUserFilter (289-303)
  • ReadStartingWithUserOptions (133-136)
  • ConsistencyOptions (109-111)
pkg/storage/tuple_iterators.go (3)
  • NewStaticTupleIterator (126-133)
  • Iterator (17-30)
  • TupleIterator (32-32)
pkg/testutils/testutils.go (1)
  • MustTransformDSLToProtoWithID (163-168)
internal/check/request.go (2)
  • NewRequest (105-179)
  • RequestParams (44-51)
pkg/tuple/tuple.go (2)
  • NewTupleKey (164-170)
  • Tuple (14-14)
internal/iterator/message.go (1)
  • Msg (5-8)
internal/mocks/mock_iterator.go (1)
  • NewMockIterator (32-36)
internal/iterator/channel.go (1)
  • FromChannel (148-152)
internal/concurrency/concurrency.go (1)
  • NewPool (16-22)
internal/iterator/stream.go (1)
  • NewStream (20-25)
internal/check/filters.go (3)
internal/modelgraph/model.go (1)
  • AuthorizationModelGraph (18-23)
internal/condition/eval/eval.go (1)
  • EvaluateTupleCondition (27-86)
internal/iterator/filter.go (3)
  • FilterFunc (22-22)
  • OperationType (12-12)
  • OperationHead (16-16)
internal/iterator/skip.go (1)
pkg/storage/tuple_iterators.go (2)
  • Iterator (17-30)
  • IterIsDoneOrCancelled (544-546)
internal/iterator/stream.go (2)
internal/iterator/channel.go (1)
  • Drain (11-26)
pkg/storage/tuple_iterators.go (1)
  • IterIsDoneOrCancelled (544-546)
internal/check/mock_resolver.go (2)
internal/check/request.go (1)
  • Request (24-42)
internal/check/response.go (1)
  • Response (7-9)
🪛 GitHub Actions: Pull Request
internal/check/check.go

[error] 440-440: Step: golangci-lint run -v -c .golangci.yaml. Error: stdversion: sync.Go requires go1.25 or later (file is go1.24) (govet)

🪛 GitHub Check: lint
internal/check/request_test.go

[failure] 598-598:
unnecessary trailing newline (whitespace)

internal/check/check.go

[failure] 456-456:
stdversion: sync.Go requires go1.25 or later (file is go1.24) (govet)


[failure] 440-440:
stdversion: sync.Go requires go1.25 or later (file is go1.24) (govet)

internal/check/request.go

[failure] 96-96:
avoid direct access to proto field t.Condition.Name, use t.GetCondition().GetName() instead (protogetter)


[failure] 95-95:
avoid direct access to proto field t.Condition, use t.GetCondition() instead (protogetter)

Comment thread internal/check/bottom_up.go
Comment thread internal/check/bottom_up.go Outdated
Comment thread internal/check/bottom_up.go
Comment thread internal/check/bottom_up.go
Comment thread internal/check/check.go Outdated
Comment thread internal/iterator/filter.go
Comment thread internal/iterator/merge.go
Comment thread internal/modelgraph/resolver.go
Comment thread internal/modelgraph/resolver.go
Comment thread pkg/server/check.go
@senojj
senojj requested a review from Vic-Dev February 24, 2026 16:33

@justincoh justincoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the near future I would love to see doc.go files in these internal packages like check and iterator. They are complex and it'd be nice to have a contextual entry point

@yissellokta
yissellokta enabled auto-merge (squash) February 24, 2026 17:53
@yissellokta
yissellokta merged commit bc23ba9 into main Feb 24, 2026
26 of 28 checks passed
@yissellokta
yissellokta deleted the check-wg branch February 24, 2026 17:56
@senojj senojj self-assigned this Feb 24, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Apr 7, 2026
4 tasks
fredrikaverpil added a commit to fredrikaverpil/openfga that referenced this pull request Jul 12, 2026
Add support for exporting logs via OTLP, allowing integration with any
OpenTelemetry-compatible backend (Grafana Loki, Datadog, GCP Cloud
Logging, etc.).

When log.otlp.enabled is set, logs are exported via OTLP in addition to
stdout. The otelzap bridge attaches span context (trace ID, span ID) to
each log record, enabling log-trace correlation in backends that
support it.

Configuration mirrors the trace configuration shape: the standard OTel
env vars (OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, OTEL_EXPORTER_OTLP_ENDPOINT)
only answer where logs are sent, while the explicit OpenFGA flag
(log.otlp.enabled / --log-otlp-enabled / OPENFGA_LOG_OTLP_ENABLED)
answers whether to export at all — so a cluster that injects the
generic endpoint variable for tracing does not silently start exporting
logs on upgrade.

zap's production sampling is applied outside the tee, so the keep/drop
decision is made once, before fan-out: stdout and OTLP receive the same
deterministically sampled stream and collector egress stays bounded
during log storms.

Changes:
- Add otelzap bridge core backed by an OTLP log provider
  (internal/telemetry/logging.go)
- Add WithOTELCore logger option that tees log entries to the bridge.
  The bridge core is capped to the configured log level, the stdout
  core strips the bridge-only context field via contextFilterCore, and
  the sampler wraps the tee (pkg/logger/logger.go)
- Attach the context field in the *WithContext logging methods only
  when an OTEL core is configured, and use those methods in the gRPC
  logging interceptor so the bridge can extract span context
  (pkg/middleware/logging/logging.go)
- Add config: log.otlp.enabled, log.otlp.endpoint, log.otlp.tls.enabled
  with OPENFGA_LOG_OTLP_* env vars and OTEL_EXPORTER_OTLP_* endpoint
  fallbacks (pkg/server/config/config.go, cmd/run/, .config-schema.json)

feat: add potential v2 breaking change logs for Expand and ListUsers (openfga#3182)
release: update changelog for release 1.18.1 (openfga#3188)
release: Update changelog to prep for 1.18.1 release (openfga#3186)
test: fix flaky TestV2CheckWithIteratorCache_HigherConsistencyBypassesCache (openfga#3061)

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Merge commit from fork

* test reproducing ListUsers report

* implement fix

* additional test with 3 operands
fix: match IPv4-mapped IPv6 addresses in the in_cidr condition (openfga#3181)

Signed-off-by: kanywst <niwatakuma@icloud.com>
fix: use deterministic proto marshaling for stored authorization models (openfga#3171)
chore: create draft release and publish after provenance succeeds for immutable tags/releases (openfga#3178)
docs: fix changelog entry (openfga#3177)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
feat: add v2Check logs for resolution breaking change (openfga#3149)
feat: BatchCheck uses v2Check when ExperimentalWeightedGraphCheck is enabled (openfga#3154)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore: update changelog to add CVE identifiers for recent fixes (openfga#3176)
chore: update todo comment string in migration guide (openfga#3175)
release: update changelog for release `v1.18.0` (openfga#3174)

Co-authored-by: adriantam <adrian.tam@okta.com>
Merge commit from fork

* fix(authn): require issuer and audience when OIDC authn is enabled

Enforce configuration authn.oidc.audience and authn.oidc.issuer when
`authn.method` is set to `oidc`.

* fixed based on code review feedback

* fix: adding comments + test case on empty space for audience

* update based on code review feedback

* Update CHANGELOG.md

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>

* update changelog

* Update CHANGELOG.md

---------

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Merge commit from fork

* fix(mysql): collate identifier columns as utf8mb4_bin

* fix: add operator note to changelog

* fix: move tests to shared storage

* fix: separate migrations for each table

* fix: add runbook for migrations

* fix: set lock_wait_timeout

* fix: add docker instructions

* fix: add docker instructions

* fix: combine the migrations back into one, fix documentation for this

* fix: include details about table copy and

* Update CHANGELOG.md

Co-authored-by: Adrian Tam <adrian.tam@okta.com>

---------

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
fix: use constant-time comparison for preshared key authentication (openfga#3168)
chore(deps): bump the dependencies group with 2 updates (openfga#3166)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
chore(deps): bump the dependencies group with 2 updates (openfga#3167)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
release: update changelog for release `v1.17.1` (openfga#3165)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore: bump grpc-health-probe to v0.4.52 (openfga#3164)

Co-authored-by: Saad Hussain <saad.hussain@okta.com>
docs: update caching docs (openfga#3163)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: continuation token deserializer - handle `|` in type names (openfga#3152)
chore(deps): bump the dependencies group across 1 directory with 13 updates (openfga#3162)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
chore(deps): bump the dependencies group across 1 directory with 10 updates (openfga#3156)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
fix: use query start time as iterator cache entry LastModified to prevent stale-read survival (openfga#3155)
chore(deps): bump grpc-ecosystem/grpc-health-probe from v0.4.50 to v0.4.51 in the dependencies group (openfga#3157)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
chore: Bump go toolchain to 1.26.4 (openfga#3159)
fix: prevent v2Check from falling back for throttling and validation (openfga#3150)
ci: make pr benchmark comparisons less fragile (openfga#3153)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
release: update changelog for release `v1.17.0` (openfga#3151)

Co-authored-by: Vic-Dev <vmichellej@gmail.com>
refactor: redesign cache key generation, making it more secure and consistent (openfga#3148)
feat: add configurable trace sampler with ParentBased support (openfga#3072)
release: update changelog for release `v1.16.1` (openfga#3147)
chore: update grpc-health-probe to latest to addres std lib CVEs (openfga#3146)
fix: skip v2Check weight2 pruning if iterator is unordered (openfga#3145)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore: add concurrency-group to PR-related CI steps (openfga#3140)
docs: move OIDC JWKS refresh entry from v1.15.1 to v1.16.0 (openfga#3142)
fix: when v2Check is primary algorithm, fix fallback condition and emit metrics (openfga#3141)
release: update changelog for release `v1.16.0` (openfga#3139)
Merge commit from fork

* fix: Standardize cache key generation everywhere

* Revert "fix: Standardize cache key generation everywhere"

This reverts commit ce60c6f9ae48a310a4dea2b824b5993520c8ba1c.

* length-encoded approach

* Revert "length-encoded approach"

This reverts commit b94637c187c57a2d3f3904247267bbc8ad21a41a.

* implement Hexer() and use in some cache keys

* appendConditionsHash -> generateConditionsHash

* mv Hexer -> BuildKey

* BuildKey -> BuildCacheKey

refactor to BuildCacheKey on each individual prefix component to remove collision risk

* make v2 cacheKey functions the standard

* make cache key prefixes consistent

* generateConditionsHash -> generateConditionsString

* delimit condition name string

* remove extra empty check

* relocate and reuse existing userTypeRestrictions function

* replace hashing of conditions for brevity

* fix tests

* cleanup, add test file

* remove unused slice capacity

* make prefix treatments consistent

* add nil-byte separator in object ids

* hash user type restrictions for brevity

* update comment string, use nil-byte separator for future-proofing

* remove call to xxhash.new

* adjustments for performance, consistency, and interface ergonomics.

* make condition hash generation more efficient.

* add clarifying comments for size caluculations

* fix builder growth calculations to match original intentions

* update outdated comment

* don't hash potentially zero values

* Revert "don't hash potentially zero values"

This reverts commit 2ad6c5b796bc20a82c1414c5146c3c708330eefa.

* add condition key separator unconditionally

* patch test expectations for new key structure

* export V2IteratorCachePrefix, use in tests

---------

Co-authored-by: justin <justin.cohen@okta.com>
Co-authored-by: Joshua Jones <joshua.jones@okta.com>
fix: unintentional zeroing of slice values by setting slice to nil (openfga#3135)
increase the check v2 trace information fidelity (openfga#3134)
feat: add datastore ping and ping retry configurations (openfga#3113)
fix: prevent v2Check strategies returning spurious false on context cancellation (openfga#3128)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix(authn/oidc): refresh JWKS on unknown kid to handle key rotation (openfga#3101)
fix: v2Check falls back to v1 on errors (openfga#3126)
fix: don't cache false results from cancelled-context goroutines in v2Check (openfga#3125)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
make union cache key unique by including the node input's label (openfga#3117)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Saad Hussain <saad.hussain@okta.com>
fix: shadow v2check and check use the same trace (openfga#3118)
fix: bump go toolchain version to 1.26.3 (openfga#3115)
chore: add more spans/attributes to v1 and v2 Check (openfga#3116)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: add matches attribute to shadowv2Check and Check spans (openfga#3114)
fix: use the same `request_id` for shadow traces in v2Check (openfga#3110)
release: update changelog for release `v1.15.1` (openfga#3112)
feat: reuse MySQL container across tests (openfga#3042)
fix: close all channels opened thus far, before return on error (openfga#3111)
chore: Add more spans/attributes to v2Check (openfga#3102)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: ensure acquired limiter token is released on throttle context cancelation (openfga#3106)
fix: cancel context before waiting on worker pool in ResolveUnionEdges (openfga#3105)
fix: replace golang.org/x/exp/maps with stdlib maps to resolve govet inline errors (openfga#3104)
fix: v2Check EdgeCacheKey collisions (openfga#3097)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: expose context errors when they can be the potential cause of an underlying datastore error (openfga#3096)
chore(deps): bump the dependencies group across 1 directory with 2 updates (openfga#3093)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: move subproblem cache lookup from ResolveUnionEdges into ResolveUnion (openfga#3095)
chore(deps): bump the dependencies group with 4 updates (openfga#3092)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: error handler panic (openfga#3091)
release: update changelog for release `v1.15.0` (openfga#3090)
chore(deps): bump the dependencies group across 1 directory with 4 updates (openfga#3087)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: v2Check correctly uses query cache even when cache controller is disabled (openfga#3086)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore(deps): bump the dependencies group across 1 directory with 7 updates (openfga#3081)

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump github.com/jackc/pgx/v5 from 5.9.1 to 5.9.2 (openfga#3085)

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump grpc-ecosystem/grpc-health-probe from v0.4.47 to v0.4.48 in the dependencies group across 1 directory (openfga#3065)

Signed-off-by: dependabot[bot] <support@github.com>
feat: try to use UDS internally between HTTP server and gRPC server (openfga#2937)
feat: add jitter to internal cache TTLs to prevent thundering herd effects (openfga#3033)

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
list objects pipeline edge pruning (openfga#3075)
update toolchain go to 1.26.2 to address stdlib CVEs (openfga#3084)
chore: add store ID and datastore query/item count to shadowV2Check log (openfga#3073)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
CI speed up (openfga#3062)

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Co-authored-by: Joshua Jones <joshua.jones@okta.com>
Add tracing to v2 Check planner strategy selection (openfga#3077)
fix: v2Check honours `check-query-cache-enabled` flag (openfga#3070)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
feat: reuse PostgreSQL container across tests (openfga#3018)
chore: fix reporter links in changelog (openfga#3069)
release: update changelog for release `v1.14.2` (openfga#3068)
fix: add null byte delimiter in contextual tuple cache keys and validation in v2Check (openfga#3064)
release: update changelog for release `v1.14.1` (openfga#3060)
chore(deps): bump the dependencies group across 1 directory with 7 updates (openfga#3056)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
fix: use a baseURL for AuthZEN configuration endpoint (openfga#3057)
chore: replace docker with moby (openfga#3047)
Iterator Cache V2: Storage Wrapper Pattern with Lock-Free Design (openfga#3016)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
test: fix flaky condition test (openfga#3058)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
chore(deps): bump the dependencies group across 1 directory with 6 updates (openfga#3045)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
chore(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp from 1.41.0 to 1.43.0 (openfga#3054)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
feat: add graceful shutdown timeout configuration (openfga#2976)
chore: update changelog to reflect playground off-by-default behavior (openfga#3053)
chore: decouple Error() and Unwrap() (openfga#3051)
perf: remove `fmt` from cache key generation (openfga#3006)
perf: enhancements for list objects (openfga#3043)
chore: remove stale notice file (openfga#3050)
docs: update 1.14.0 for CVE fix (openfga#3046)
feat: Add datastore throttling & concurrency limiting to v2Check (openfga#3035)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
release: update changelog for release `v1.14.0` (openfga#3040)
batch check cache (openfga#3025)
Merge commit from fork

Also prevent enabling playground when the server requires authentication
feat: add stats on tuple iterator query (openfga#3030)
fix: remove unnecessary non-deterministic test (openfga#3038)
remove unnecessary import (openfga#3032)
perf: improve the intersection algorithm, reducing latency and memory use (openfga#3031)
fix: ListObjects pipeline algorithm enhancements and fix for potential deadlock (openfga#3028)
chore: Also update openfga/helm-charts in release script (openfga#3010)
chore: update CICD to enforce GRPC healthprobe changes (openfga#2990)
fix: SQL `TupleOperation` serialization and `pgx.ErrNoRows` error handling (openfga#3014)
docs: update changelog for CVE-2026-33729 (openfga#3017)
chore: output the diff after running keep-a-changelog (openfga#3015)
chore(deps): bump the dependencies group across 1 directory with 11 updates (openfga#2998)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
chore(deps): bump the dependencies group across 1 directory with 10 updates (openfga#2999)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
release: update changelog for release `v1.13.1` (openfga#3002)
Merge commit from fork

* strip unicode control characters, encode context key length in cache key

* add cache_key tests to ensure we escape control characters and encode context key length

* run linter

* docs: update changelog

* Apply suggestion from @adriantam

Co-authored-by: Adrian Tam <adrian.tam@okta.com>

* Apply suggestion from @adriantam

Co-authored-by: Adrian Tam <adrian.tam@okta.com>

---------

Co-authored-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Saad Hussain <saad.h@outlook.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
release: update changelog for release `v1.13.0` (openfga#2997)
refactor: Separate caches for v1 and v2 Check (openfga#2968)

Co-authored-by: Justin Cohen <justincoh@gmail.com>
docs: fix typos in comments (openfga#2972)

Signed-off-by: Artem Muterko <artem@sopho.tech>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
observability: aggregate message statistics for each list-objects sender into a single span (openfga#2993)

Co-authored-by: Justin Cohen <justincoh@gmail.com>
fix: capture panics in pipeline's base resolver, and return as errors. (openfga#2994)
docs: fix typos in RELEASES.md and Makefile (openfga#2980)

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
AuthZen v1.0 Implementation (openfga#2875)

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rokibul Hasan <mdrokibulhasan@appscode.com>
Signed-off-by: Vihang Mehta <vihang@gimletlabs.ai>
Co-authored-by: Karl Persson <kalle.persson92@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Maria Ines Parnisari <maria.inesparnisari@okta.com>
Co-authored-by: Rokibul Hasan <mdrokibulhasan18@gmail.com>
Co-authored-by: José Padilla <jose.padilla@okta.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
Co-authored-by: Vihang Mehta <vihang@gimletlabs.ai>
Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
release: update changelog for release `v1.12.1` (openfga#2992)
chore(deps): bump google.golang.org/grpc from 1.79.1 to 1.79.3 (openfga#2988)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
chore: enforce minor version upgrade rule (openfga#2978)

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
perf: tuple validation performance tweaks (openfga#2984)
fix: support URI schemes in OTLP endpoint configuration (openfga#2981)
refactor: remove custom pipes and replace with channels (openfga#2977)
chore(docs): added caching  docs (openfga#2664)

Co-authored-by: Saad Hussain <saad.hussain@okta.com>
release: update changelog for release `v1.12.0` (openfga#2974)
chore: update toolchain go to 1.26.1 (openfga#2975)
fix: update toolchain go to 1.25.8 to address stdlib CVEs (openfga#2971)
fix: correct swapped format args in DecodeParameterType error message (openfga#2961)

Signed-off-by: Artem Muterko <artem@sopho.tech>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
perf: small tweaks to tuple validation functions (openfga#2963)

Co-authored-by: Vic-Dev <vmichellej@gmail.com>
test: add tests for condition parameter type any with complex context structures (openfga#2959)

Signed-off-by: Artem Muterko <artem@sopho.tech>
test: add functional test for ReadAssertions API endpoint (openfga#2960)

Signed-off-by: Artem Muterko <artem@sopho.tech>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
make configurable the maximum received grpc message size (openfga#2952)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
fix: set ExperimentalPipelineListObjects in experimentals by default (openfga#2957)

fix: `cache_item_count` metric overcounting (openfga#2950)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
chore(deps): bump the dependencies group across 1 directory with 7 updates (openfga#2953)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
refactor: Make shadowV2Check final log clearer (openfga#2946)

Move telemetry package to internal/telemetry (openfga#2938)

Signed-off-by: Oleksandr Shestopal <ar.shestopal-oshegithub@gmail.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
chore(deps): bump the dependencies group across 1 directory with 3 updates (openfga#2956)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: Resolve race condition in check reducers (openfga#2947)

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
fix: gateway grpc client tls cert rotation (openfga#2951)

Signed-off-by: Shashank Goel <goelshashank13@gmail.com>
fix: disable LO pipeline if ff has it set for a store (openfga#2945)

chore(deps): bump the dependencies group across 1 directory with 4 updates (openfga#2949)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: various random fixes (openfga#2942)

refactor: check using weighted graph (openfga#2816)

Co-authored-by: Yissell Garma <yissell.garma@okta.com>
release: update changelog for release `v1.11.6` (openfga#2939)

feat: enable pipeline algorithm by default (openfga#2921)

add tests to exercise reported bug (openfga#2934)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
refine AGENTS.md to make it more concise with higher value. (openfga#2936)

Co-authored-by: Justin Cohen <justincoh@gmail.com>
migrate grpc dial context to NewClient (openfga#2714)

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
chore(deps): bump filippo.io/edwards25519 from 1.1.0 to 1.1.1 (openfga#2935)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor A cleanup is needed Skip-Changelog Indicates that a PR does not need a changelog entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.