Skip to content

feat(ers): add direct entitlement support to the claims ERS + bdd tests for the feature#3671

Draft
elizabethhealy wants to merge 1 commit into
mainfrom
dspx-1311-direct-entitlements
Draft

feat(ers): add direct entitlement support to the claims ERS + bdd tests for the feature#3671
elizabethhealy wants to merge 1 commit into
mainfrom
dspx-1311-direct-entitlements

Conversation

@elizabethhealy

Copy link
Copy Markdown
Member

Proposed Changes

Checklist

  • I have added or updated unit tests
  • I have added or updated integration tests (if appropriate)
  • I have added or updated documentation

Testing Instructions

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request implements direct entitlement support within the Entity Resolution Service. By allowing entitlements to be embedded directly within claims, the system gains more flexibility in authorization decisions. The changes include logic to parse these entitlements, a configuration toggle to control the feature, and a suite of BDD tests to ensure correct behavior under various scenarios.

Highlights

  • Direct Entitlement Support: Added support for parsing and resolving direct entitlements from claims in the Entity Resolution Service.
  • Configuration: Introduced a configurable 'allow_direct_entitlements' flag to enable or disable this feature.
  • Testing: Added comprehensive unit tests and BDD integration tests to verify direct entitlement evaluation and configuration toggling.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


Claims now hold a secret key, / Direct entitlements, wild and free. / With a toggle set to true, / The system knows just what to do, / And checks the path for you and me.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

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.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5f834f8b-09fe-4bd4-9323-ab1d76be6ec4

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dspx-1311-direct-entitlements

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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces support for direct entitlements within the claims-based entity resolution service, allowing the platform to parse and evaluate direct entitlements (attribute value FQNs and actions) from entity claims when configured. It includes updates to service registration, configuration decoding, unit tests, and BDD scenarios. The review feedback suggests improving error handling by replacing log.Fatalf with panic during service registration to prevent abrupt process termination and allow proper cleanup, which also enables removing the unused "log" import. Additionally, it recommends adding a nil check for the claims map to safely handle empty structs.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 3 to 16
import (
"context"
"errors"
"fmt"
"log"
"log/slog"
"strconv"
"strings"

"connectrpc.com/connect"
"github.com/go-viper/mapstructure/v2"
"github.com/lestrrat-go/jwx/v2/jwt"
"github.com/opentdf/platform/protocol/go/entity"
entityresolutionV2 "github.com/opentdf/platform/protocol/go/entityresolution/v2"

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.

medium

The "log" package is no longer needed if we replace log.Fatalf with panic in RegisterClaimsERS. We can clean up the imports by removing it.

Suggested change
import (
"context"
"errors"
"fmt"
"log"
"log/slog"
"strconv"
"strings"
"connectrpc.com/connect"
"github.com/go-viper/mapstructure/v2"
"github.com/lestrrat-go/jwx/v2/jwt"
"github.com/opentdf/platform/protocol/go/entity"
entityresolutionV2 "github.com/opentdf/platform/protocol/go/entityresolution/v2"
import (
"context"
"errors"
"fmt"
"log/slog"
"strconv"
"strings"
"connectrpc.com/connect"
"github.com/go-viper/mapstructure/v2"
"github.com/lestrrat-go/jwx/v2/jwt"
"github.com/opentdf/platform/protocol/go/entity"
entityresolutionV2 "github.com/opentdf/platform/protocol/go/entityresolution/v2"

Comment on lines +38 to 49
func RegisterClaimsERS(cfg config.ServiceConfig, logger *logger.Logger) (EntityResolutionServiceV2, serviceregistry.HandlerServer) {
var inputConfig ClaimsConfig
if err := mapstructure.Decode(cfg, &inputConfig); err != nil {
logger.Error("failed to decode claims entity resolution configuration", slog.Any("error", err))
log.Fatalf("Failed to decode claims entity resolution configuration: %v", err)
}
claimsSVC := EntityResolutionServiceV2{
logger: logger,
allowDirectEntitlements: inputConfig.AllowDirectEntitlements,
}
return claimsSVC, nil
}

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.

medium

Using log.Fatalf inside a service registration function is discouraged. It abruptly terminates the process via os.Exit(1), which prevents deferred cleanup functions from running and bypasses structured logging (printing directly to stderr in standard log format instead of structured JSON). Since the error is already logged via logger.Error, we should use panic to halt initialization gracefully if configuration decoding fails.

Suggested change
func RegisterClaimsERS(cfg config.ServiceConfig, logger *logger.Logger) (EntityResolutionServiceV2, serviceregistry.HandlerServer) {
var inputConfig ClaimsConfig
if err := mapstructure.Decode(cfg, &inputConfig); err != nil {
logger.Error("failed to decode claims entity resolution configuration", slog.Any("error", err))
log.Fatalf("Failed to decode claims entity resolution configuration: %v", err)
}
claimsSVC := EntityResolutionServiceV2{
logger: logger,
allowDirectEntitlements: inputConfig.AllowDirectEntitlements,
}
return claimsSVC, nil
}
func RegisterClaimsERS(cfg config.ServiceConfig, logger *logger.Logger) (EntityResolutionServiceV2, serviceregistry.HandlerServer) {
var inputConfig ClaimsConfig
if err := mapstructure.Decode(cfg, &inputConfig); err != nil {
logger.Error("failed to decode claims entity resolution configuration", slog.Any("error", err))
panic(fmt.Errorf("failed to decode claims entity resolution configuration: %w", err))
}
claimsSVC := EntityResolutionServiceV2{
logger: logger,
allowDirectEntitlements: inputConfig.AllowDirectEntitlements,
}
return claimsSVC, nil
}

Comment on lines +194 to +199
func parseDirectEntitlementsFromClaims(entityStruct *structpb.Struct) ([]*entityresolutionV2.DirectEntitlement, error) {
if entityStruct == nil {
return nil, nil
}
claims := entityStruct.AsMap()
rawEntitlements, ok := claims["direct_entitlements"]

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.

medium

If entityStruct is empty (e.g., &structpb.Struct{}), entityStruct.AsMap() will return nil. While reading from a nil map is safe in Go and returns the zero value, it is safer and more explicit to add a nil check for claims to prevent any future refactoring issues or confusion.

Suggested change
func parseDirectEntitlementsFromClaims(entityStruct *structpb.Struct) ([]*entityresolutionV2.DirectEntitlement, error) {
if entityStruct == nil {
return nil, nil
}
claims := entityStruct.AsMap()
rawEntitlements, ok := claims["direct_entitlements"]
func parseDirectEntitlementsFromClaims(entityStruct *structpb.Struct) ([]*entityresolutionV2.DirectEntitlement, error) {
if entityStruct == nil {
return nil, nil
}
claims := entityStruct.AsMap()
if claims == nil {
return nil, nil
}
rawEntitlements, ok := claims["direct_entitlements"]

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Govulncheck found vulnerabilities ⚠️

The following modules have known vulnerabilities:

  • examples
  • otdfctl
  • sdk
  • service
  • lib/fixtures
  • tests-bdd

See the workflow run for details.

@github-actions

Copy link
Copy Markdown
Contributor
Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 173.969871ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 83.740891ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 353.835483ms
Throughput 282.62 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 40.245440399s
Average Latency 401.12682ms
Throughput 124.24 requests/second

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant