Skip to content

feat(policy): DSPX-2541 add GetKeyMappingsByFqns API#3632

Closed
alkalescent wants to merge 2 commits into
mainfrom
DSPX-2541-key-mappings-api
Closed

feat(policy): DSPX-2541 add GetKeyMappingsByFqns API#3632
alkalescent wants to merge 2 commits into
mainfrom
DSPX-2541-key-mappings-api

Conversation

@alkalescent

@alkalescent alkalescent commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Proposed Changes

  • Add GetKeyMappingsByFqns, a narrow client-side key-split read API on the attributes service: proto, regenerated protocol/go, handler, DB projection, and tests, all in one PR (per repo convention for adding an RPC, e.g. 4c3d53d).
  • Per requested attribute value FQN it returns the attribute rule and the effective KAS keys, resolved server-side with value > definition > namespace precedence over the SimpleKasKey model (mirroring sdk/granter.go newGranterFromService). Replaces the full attribute+value graph that GetAttributeValuesByFqns returns for the encrypt/splits path.

Part of DSPX-2541. The companion GetEntitleableAttributesByFqns API is a stacked follow-up. Deprecating GetAttributeValuesByFqns and the SDK/decisioning migrations are tracked separately.

Limitation: values configured only with legacy KeyAccessServer grants (no kas_keys) return an empty key set; kas_keys is the forward model.

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

  • go test ./service/policy/db/ -run TestResolveEffectiveKasKeys
  • go test ./service/integration/ -run TestAttributesSuite/Test_GetKeyMappingsByFqns
  • golangci-lint run ./policy/db/... ./policy/attributes/... — 0 issues.

Related

Add a narrow client-side key-split read API to the attributes service: proto, regenerated protocol/go, handler, DB projection, and tests in one PR. Per requested attribute value FQN it returns the attribute rule and the effective KAS keys, resolved with value > definition > namespace precedence over the SimpleKasKey model (mirroring sdk/granter.go). Replaces the full attribute+value graph returned by GetAttributeValuesByFqns for the encrypt/splits path.

Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@coderabbitai

coderabbitai Bot commented Jun 17, 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: 8de5f999-3ffe-44aa-b9d5-7d778161936c

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-2541-key-mappings-api

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.

@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 adds a new, optimized API endpoint, GetKeyMappingsByFqns, to the attributes service. This change is designed to streamline the client-side encryption flow by providing only the necessary information for building key splits, specifically the governing attribute rule and the effective KAS keys. The implementation includes the necessary protocol definitions, service handlers, database projections, and robust testing to ensure correct key resolution precedence.

Highlights

  • New API Endpoint: Introduced the GetKeyMappingsByFqns API endpoint to provide a narrow, client-side read path for key-split construction.
  • Server-Side Key Resolution: Implemented server-side logic to resolve effective KAS keys using a value > definition > namespace precedence model.
  • Documentation and Testing: Updated gRPC documentation and added comprehensive unit and integration tests to verify the new API and key resolution logic.
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.

Ignored Files
  • Ignored by pattern: docs/openapi/**/* (1)
    • docs/openapi/policy/attributes/attributes.openapi.yaml
  • Ignored by pattern: protocol/**/* (3)
    • protocol/go/policy/attributes/attributes.pb.go
    • protocol/go/policy/attributes/attributes_grpc.pb.go
    • protocol/go/policy/attributes/attributesconnect/attributes.connect.go
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.


New API for keys so bright, Resolving splits with all our might. From value down to namespace deep, The secrets safe we vow to keep.

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.

@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 a new GetKeyMappingsByFqns RPC endpoint to the AttributesService to support client-side key split construction by returning only the governing attribute rule and effective KAS keys. The implementation includes protobuf updates, database resolution logic with value-definition-namespace precedence, and corresponding unit and integration tests. Feedback suggests improving structured logging in the service handler by using slog.Any instead of string formatting, and adding explicit nil checks in the key resolution logic for defensive programming and readability.

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.


mappings, err := s.dbClient.GetKeyMappingsByFqns(ctx, req.Msg)
if err != nil {
return nil, db.StatusifyError(ctx, s.logger, err, db.ErrTextGetRetrievalFailed, slog.String("fqns", fmt.Sprintf("%v", req.Msg.GetFqns())))

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 fmt.Sprintf("%v", ...) to log a slice of strings in slog is inefficient and prevents structured log formatters (like JSON) from outputting it as a proper array. Use slog.Any instead to log the slice directly.

Suggested change
return nil, db.StatusifyError(ctx, s.logger, err, db.ErrTextGetRetrievalFailed, slog.String("fqns", fmt.Sprintf("%v", req.Msg.GetFqns())))
return nil, db.StatusifyError(ctx, s.logger, err, db.ErrTextGetRetrievalFailed, slog.Any("fqns", req.Msg.GetFqns()))

Comment on lines +239 to +250
func resolveEffectiveKasKeys(value *policy.Value, attr *policy.Attribute) []*policy.SimpleKasKey {
if keys := value.GetKasKeys(); len(keys) > 0 {
return keys
}
if keys := attr.GetKasKeys(); len(keys) > 0 {
return keys
}
if keys := attr.GetNamespace().GetKasKeys(); len(keys) > 0 {
return keys
}
return 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

While protobuf generated getters are nil-safe, explicitly checking for nil values before accessing their properties is highly recommended for defensive programming and readability. This is especially important here because value can be nil when allow_traversal is enabled, and explicit checks make this business logic clear to future maintainers who might otherwise refactor the code to use direct field access (which would panic on nil).

func resolveEffectiveKasKeys(value *policy.Value, attr *policy.Attribute) []*policy.SimpleKasKey {
	if value != nil {
		if keys := value.GetKasKeys(); len(keys) > 0 {
			return keys
		}
	}
	if attr != nil {
		if keys := attr.GetKasKeys(); len(keys) > 0 {
			return keys
		}
		if ns := attr.GetNamespace(); ns != nil {
			if keys := ns.GetKasKeys(); len(keys) > 0 {
				return keys
			}
		}
	}
	return nil
}

@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 198.070109ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 430.33655ms
Throughput 232.38 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.834394556s
Average Latency 446.62552ms
Throughput 111.52 requests/second

…ingsByFqns

make connect-wrapper-generate (go run ./sdk/codegen) regenerates sdk/sdkconnect from protocol/go; the new RPC adds a wrapper method that CI's generated-code freshness check requires to be committed.

Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@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 143.326216ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 359.512845ms
Throughput 278.15 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 35.756637928s
Average Latency 355.600752ms
Throughput 139.83 requests/second

@alkalescent

Copy link
Copy Markdown
Contributor Author

Combined into a single PR #3634 (both narrow attribute read APIs), per discussion: they edit the same files, match the repo convention of bundling related RPCs (4c3d53d), and release as one protocol/go version.

@alkalescent alkalescent deleted the DSPX-2541-key-mappings-api branch June 17, 2026 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:db DB component comp:policy Policy Configuration ( attributes, subject mappings, resource mappings, kas registry) docs Documentation size/s

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant