Skip to content

feat(sdk): resolve key splits via GetKeyMappingsByFqns#3699

Merged
alkalescent merged 6 commits into
mainfrom
DSPX-2541-sdk-granter
Jul 2, 2026
Merged

feat(sdk): resolve key splits via GetKeyMappingsByFqns#3699
alkalescent merged 6 commits into
mainfrom
DSPX-2541-sdk-granter

Conversation

@alkalescent

@alkalescent alkalescent commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Proposed Changes

Switch the SDK granter to resolve key splits through the new GetKeyMappingsByFqns RPC instead of walking the full attribute set from GetAttributeValuesByFqns.

  • newGranterFromService now calls GetKeyMappingsByFqns and feeds the returned per-value rule + effective KAS keys (server-side value > definition > namespace precedence) into the existing split planner.
  • Fallbacks preserve behavior:
    • Values that return no mapped keys (e.g. legacy-grant-only policy) fall back per-value to GetAttributeValuesByFqns.
    • Older platforms that do not expose the RPC (Unimplemented) fall back entirely.
  • Adds TestReasonerKeyMappingFallback covering both fallback paths; existing reasoner tests now exercise the new path (mapped keys) and the fallback (grants) and still pass.

Stack

Depends on #3634 (proto + generated + sdkconnect wrapper). Base is the #3634 branch; rebase onto main and bump sdk/go.mod to the released protocol/go once #3634 merges.

Follow-up

An xtest in opentdf/tests will prove the new go SDK produces the same TDF key splits as a previous released SDK (cross-SDK parity).

Summary by CodeRabbit

  • New Features

    • Prefer server-side key mappings (value → definition → namespace) when resolving grants into planning inputs.
    • Automatically cache and reuse mapped wrapping keys for consistent planning.
    • Fall back to full attribute-based resolution for legacy or unmapped values, including when mapping data is unavailable.
  • Bug Fixes

    • Ensure correct planning when key-mapping responses are unimplemented or omit requested entries.
    • Maintain consistent behavior for policies that mix mapped-key values and legacy grant-based values.
  • Tests

    • Added scenarios covering fallback for unimplemented/empty/partial mapping responses.
    • Added coverage for mixed mapping and legacy grant inputs producing the expected combined plan.

@alkalescent alkalescent requested review from a team as code owners June 30, 2026 22:03
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@alkalescent, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 39b6f792-7098-48ee-9626-655fc099164e

📥 Commits

Reviewing files that changed from the base of the PR and between daceec5 and 673d69d.

📒 Files selected for processing (1)
  • sdk/granter_test.go
📝 Walkthrough

Walkthrough

The granter now prefers server-side key mappings, falls back to attribute-based grants when mappings are unavailable or incomplete, and centralizes the legacy grant-resolution path. Tests cover unimplemented, empty, and mixed mapping cases.

Changes

Granter Key Mapping Fallback

Layer / File(s) Summary
Key mapping fallback implementation
sdk/granter.go
newGranterFromService now calls GetKeyMappingsByFqns first, fills grant and map tables from mapped keys, and falls back to GetAttributeValuesByFqns for unmapped FQNs or an Unimplemented response. The attribute-resolution flow is extracted into addGrantsFromAttributeValues.
Tests for key mapping and fallback
sdk/granter_test.go
Mocks add GetKeyMappingsByFqns support and key precedence handling, plus client variants for unimplemented and empty responses. New tests verify fallback behavior and combined mapped-plus-legacy grant planning.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: dmihalcik-virtru, elizabethhealy

Poem

A rabbit hops through FQN trees,
Sniffing keys upon the breeze.
If mappings pause or vanish away,
Old grants still guide the path today,
Hoppy caches shimmer, safe and sound 🐇🔑

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main SDK change: resolving key splits through GetKeyMappingsByFqns.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DSPX-2541-sdk-granter

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.

@github-actions github-actions Bot added comp:sdk A software development kit, including library, for client applications and inter-service communicati size/m labels Jun 30, 2026
@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 optimizes the SDK's key split resolution process by migrating from a full attribute value walk to a more direct RPC-based approach. It introduces a new service call while maintaining backward compatibility through strategic fallbacks, ensuring that existing grant-based policies and older platform versions continue to function correctly.

Highlights

  • RPC Integration: Updated the SDK granter to utilize the new GetKeyMappingsByFqns RPC for resolving key splits, improving efficiency over the previous attribute walking method.
  • Fallback Mechanisms: Implemented robust fallback logic to handle cases where no mapped keys are returned or when communicating with older platforms that do not support the new RPC.
  • Testing: Added TestReasonerKeyMappingFallback to ensure parity between the new RPC path and legacy fallback paths.
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.


The granter now calls out with speed, / To fetch the keys that we all need. / If old platforms fail to comply, / The fallback path will satisfy.

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 refactors newGranterFromService in sdk/granter.go to resolve KAS grants using the more efficient GetKeyMappingsByFqns endpoint, falling back to GetAttributeValuesByFqns for older platforms or unconfigured keys. It also adds corresponding unit tests to verify this fallback behavior. The review feedback identifies potential nil pointer dereference panics when handling RPC response maps, suggests iterating over the requested FQNs to ensure all are processed or properly fell back, and recommends returning zero-value structs on error paths to follow Go best practices.

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 thread sdk/granter.go
Comment thread sdk/granter.go
@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 200.571784ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 415.675606ms
Throughput 240.57 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 45.55854733s
Average Latency 454.583836ms
Throughput 109.75 requests/second

@alkalescent alkalescent force-pushed the DSPX-2541-attribute-read-apis branch from a40a66d to 3239ed4 Compare June 30, 2026 22:41
@alkalescent alkalescent requested review from a team as code owners June 30, 2026 22:41
@alkalescent alkalescent force-pushed the DSPX-2541-sdk-granter branch from d00f147 to 5968161 Compare June 30, 2026 22:54
@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 170.546494ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 373.843637ms
Throughput 267.49 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 37.873487134s
Average Latency 376.864736ms
Throughput 132.02 requests/second

Base automatically changed from DSPX-2541-attribute-read-apis to main July 1, 2026 17:24
Switch newGranterFromService to resolve effective KAS keys through the new
GetKeyMappingsByFqns RPC (server-side value > definition > namespace precedence).
Values that return no mapped keys (legacy-grant-only) fall back per-value to
GetAttributeValuesByFqns, and older platforms that do not expose the RPC
(Unimplemented) fall back entirely, so behavior is preserved for un-migrated
policy and older servers. Adds fallback parity unit tests.

Signed-off-by: Krish Suchak <[email protected]>
@alkalescent alkalescent force-pushed the DSPX-2541-sdk-granter branch from 5968161 to 132f66f Compare July 2, 2026 13:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sdk/granter.go`:
- Around line 432-435: The grant aggregation in
GetKeyMappingsByFqns/GetFqnKeyMappings only processes entries returned by the
response map, so requested FQNs that are missing or empty can be skipped
entirely. Update the loop that builds grants/fallback to iterate over the
original fqns list, normalize each key the same way, and for each requested FQN
either map it from the response or add it to fallback when the mapping is absent
or empty. Add a test covering a successful RPC with an empty response map for a
requested FQN to verify the granter still falls back correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6b162f14-812e-430d-a865-1a59b75d0470

📥 Commits

Reviewing files that changed from the base of the PR and between 4277e96 and 132f66f.

📒 Files selected for processing (2)
  • sdk/granter.go
  • sdk/granter_test.go

Comment thread sdk/granter.go
@github-actions

github-actions Bot commented Jul 2, 2026

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 159.979648ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 354.298947ms
Throughput 282.25 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 35.136951508s
Average Latency 350.169185ms
Throughput 142.30 requests/second

@github-actions

github-actions Bot commented Jul 2, 2026

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 225.406656ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 412.440312ms
Throughput 242.46 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 45.954682842s
Average Latency 458.066836ms
Throughput 108.80 requests/second

- iterate requested FQNs (not the response map) in newGranterFromService so a
  value omitted from GetKeyMappingsByFqns falls back instead of being dropped;
  rely on nil-safe protobuf getters (no redundant present/nil guard)
- return granter{} on error paths
- test the FQN-omitted-from-response fallback path

Signed-off-by: Krish Suchak <[email protected]>
@alkalescent alkalescent force-pushed the DSPX-2541-sdk-granter branch from eb23dff to a1b8636 Compare July 2, 2026 14:31
@github-actions

github-actions Bot commented Jul 2, 2026

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 166.378139ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 361.131475ms
Throughput 276.91 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 37.397845845s
Average Latency 371.930776ms
Throughput 133.70 requests/second

@alkalescent alkalescent enabled auto-merge July 2, 2026 15:12

@c-r33d c-r33d 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.

I don't see any issues. Are there any tests that mix grants and mappings together? I looked through the old granter_test.go code and don't really see any. Do you think it would be useful to add at least one test where we have 2 fqns with mappings and 2 with grant only?

c-r33d
c-r33d previously approved these changes Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

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 207.688004ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 599.947783ms
Throughput 166.68 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.817000758s
Average Latency 446.399468ms
Throughput 111.56 requests/second

Comment thread sdk/granter_test.go Outdated
c-r33d
c-r33d previously approved these changes Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

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 164.448777ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 361.66234ms
Throughput 276.50 requests/second

TDF3 Benchmark Results:

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

Comment thread sdk/granter.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sdk/granter_test.go`:
- Around line 914-918: The test is deduplicating the grant plan by KAS, which
hides duplicate mapped-key entries and lost split IDs. Update the assertion in
the granter test to validate the full `plan` shape instead of `maps.Keys(got)`,
or at minimum assert per-entry counts and that mapped-key items carry the
expected non-empty split IDs using the relevant plan-building logic in
`granter_test.go`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 98ea7c93-3151-4e0d-a44c-6afadf64b7cc

📥 Commits

Reviewing files that changed from the base of the PR and between e206b32 and daceec5.

📒 Files selected for processing (2)
  • sdk/granter.go
  • sdk/granter_test.go

Comment thread sdk/granter_test.go Outdated
@github-actions

github-actions Bot commented Jul 2, 2026

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 213.943187ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 425.886045ms
Throughput 234.80 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 46.207143174s
Average Latency 460.049862ms
Throughput 108.21 requests/second

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jul 2, 2026

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.151212ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 456.497317ms
Throughput 219.06 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 45.563089899s
Average Latency 454.232291ms
Throughput 109.74 requests/second

@github-actions

github-actions Bot commented Jul 2, 2026

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.

@alkalescent alkalescent added this pull request to the merge queue Jul 2, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 2, 2026
@alkalescent alkalescent added this pull request to the merge queue Jul 2, 2026
Merged via the queue into main with commit 7a2320b Jul 2, 2026
77 of 80 checks passed
@alkalescent alkalescent deleted the DSPX-2541-sdk-granter branch July 2, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:sdk A software development kit, including library, for client applications and inter-service communicati size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants