Skip to content

feat(policy): DSPX-2754 dynamic attribute value entitlement mappings#3568

Draft
alkalescent wants to merge 8 commits into
mainfrom
DSPX-2754-dynamic-attribute-values-impl
Draft

feat(policy): DSPX-2754 dynamic attribute value entitlement mappings#3568
alkalescent wants to merge 8 commits into
mainfrom
DSPX-2754-dynamic-attribute-values-impl

Conversation

@alkalescent
Copy link
Copy Markdown
Contributor

@alkalescent alkalescent commented Jun 4, 2026

Important

Depends on #3580 (protocol-first). This PR adds a new protocol/go package, so the per-module go mod tidy CI check stays red until #3580 merges and protocol/go is released. Sequence: merge #3580 → release protocol/go → rebase this branch and bump sdk/service go.mod → CI goes green.

Proposed Changes

Implements the DefinitionValueEntitlementMapping policy primitive end to end (the model chosen by the DSPX-2754 spike / ADR 0005). It raises entitlement authority from a concrete AttributeValue to the AttributeDefinition: a single mapping entitles dynamically-requested values by comparing the requested resource value segment against the entity representation at decision time, instead of pre-provisioning a value + subject mapping per discrete ID (MRNs, account IDs, etc.).

Design highlights (improving on the reference spike):

  • Dedicated operator + resolver (DynamicValueOperatorEnum: RESOURCE_VALUE_IN / RESOURCE_VALUE_IN_CONTAINS, DefinitionValueResolver) so dynamic operators stay isolated from static subject-mapping operators and the schema honestly expresses "dynamic".
  • Optional static SubjectConditionSet pre-gate (normal static semantics, no field overload) to support compound "entity attribute AND resource value" conditions.
  • No-coexistence enforced both directions between value-level subject mappings and dynamic mappings on the same definition.
  • HIERARCHY rejected; canonicalized (case/whitespace) value comparison.
  • Dynamic values are first-class in decisioning: they flow into the same entitlements map and ANY_OF / ALL_OF rule layer as static values (manifest stays a list of attribute FQNs).

Wiring: proto + generated code + SDK client; DB migration + sqlc + CRUD; dedicated DefinitionValueEntitlementMappingService; decision-time evaluator; PDP load/merge with synthetic-value support; and authz cache. Replaces the throwaway spike package and ports its tests. GetEntitlements intentionally does not enumerate dynamic values (high-cardinality, resource-scoped).

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

  • cd service && go build ./...
  • cd service && go test ./internal/subjectmappingbuiltin/... ./internal/access/v2/... ./authorization/v2/...
  • cd service && golangci-lint run ./internal/subjectmappingbuiltin/... ./internal/access/v2/ ./authorization/v2/ ./policy/db/ ./policy/definitionvalueentitlement/
  • DB-layer CRUD and end-to-end GetDecision verification require a live Postgres/platform and are not included here.

Related

Implement the DefinitionValueEntitlementMapping primitive end to end: a
definition-scoped mapping that entitles dynamically-requested attribute values
by comparing the requested resource value segment against the entity
representation at decision time, instead of pre-provisioning a value + subject
mapping per discrete value.

Design (per ADR 0005, improving on the reference spike):
- A dedicated DynamicValueOperatorEnum (RESOURCE_VALUE_IN / _IN_CONTAINS) and
  DefinitionValueResolver, so operators stay isolated from static subject
  mapping operators and the schema honestly expresses 'dynamic'.
- An optional static SubjectConditionSet pre-gate (normal static semantics) to
  support compound 'entity attribute AND resource value' conditions.
- No-coexistence enforcement (both directions) between value-level subject
  mappings and dynamic mappings on the same definition.
- HIERARCHY rejected; canonicalized (case/space) value comparison.

Wiring: proto + generated code + SDK client, DB migration + sqlc + CRUD,
dedicated DefinitionValueEntitlementMappingService, decision-time evaluator,
PDP load/merge, synthetic-value support, and authz cache. Replaces the
throwaway spike package; ports its tests.

Refs: DSPX-2754, virtru-corp/adr#266
Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

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: f0685568-ef66-4b2e-8899-a9b207cecf6e

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-2754-dynamic-attribute-values-impl

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.

@github-actions github-actions Bot added comp:db DB component comp:policy Policy Configuration ( attributes, subject mappings, resource mappings, kas registry) comp:sdk A software development kit, including library, for client applications and inter-service communicati comp:authorization docs Documentation size/xl labels Jun 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 4, 2026

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

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

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 405.58654ms
Throughput 246.56 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 46.591212655s
Average Latency 463.808555ms
Throughput 107.32 requests/second

@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 a new policy primitive, DefinitionValueEntitlementMapping, which enables dynamic entitlement mappings at the attribute definition level. This allows for more flexible and scalable authorization by comparing resource values against entity attributes at decision time, rather than relying on pre-provisioned static mappings. The change includes a full end-to-end implementation, including protocol definitions, service logic, database persistence, and integration into the existing policy decision point.

Highlights

  • New Policy Primitive: Introduced the DefinitionValueEntitlementMapping primitive to support dynamic attribute value entitlement at the definition level.
  • Dynamic Evaluation Logic: Added DynamicValueOperatorEnum and DefinitionValueResolver to allow for dynamic comparison of resource values against entity attributes at decision time.
  • Service and Persistence: Implemented a dedicated CRUD service, database migrations, and SQLC queries to manage the new entitlement mappings.
  • PDP Integration: Integrated dynamic mapping evaluation into the Policy Decision Point (PDP) and added caching to maintain performance.
  • Validation and Safety: Enforced no-coexistence rules to prevent conflicts between static value-level subject mappings and new dynamic mappings on the same definition.
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/**/* (21)
    • docs/openapi/authorization/authorization.openapi.yaml
    • docs/openapi/authorization/v2/authorization.openapi.yaml
    • docs/openapi/common/common.openapi.yaml
    • docs/openapi/entity/entity.openapi.yaml
    • docs/openapi/entityresolution/entity_resolution.openapi.yaml
    • docs/openapi/entityresolution/v2/entity_resolution.openapi.yaml
    • docs/openapi/kas/kas.openapi.yaml
    • docs/openapi/policy/actions/actions.openapi.yaml
    • docs/openapi/policy/attributes/attributes.openapi.yaml
    • docs/openapi/policy/definitionvalueentitlement/definition_value_entitlement.openapi.yaml
    • docs/openapi/policy/kasregistry/key_access_server_registry.openapi.yaml
    • docs/openapi/policy/keymanagement/key_management.openapi.yaml
    • docs/openapi/policy/namespaces/namespaces.openapi.yaml
    • docs/openapi/policy/objects.openapi.yaml
    • docs/openapi/policy/obligations/obligations.openapi.yaml
    • docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
    • docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml
    • docs/openapi/policy/selectors.openapi.yaml
    • docs/openapi/policy/subjectmapping/subject_mapping.openapi.yaml
    • docs/openapi/policy/unsafe/unsafe.openapi.yaml
    • docs/openapi/wellknownconfiguration/wellknown_configuration.openapi.yaml
  • Ignored by pattern: protocol/**/* (4)
    • protocol/go/policy/definitionvalueentitlement/definition_value_entitlement.pb.go
    • protocol/go/policy/definitionvalueentitlement/definition_value_entitlement_grpc.pb.go
    • protocol/go/policy/definitionvalueentitlement/definitionvalueentitlementconnect/definition_value_entitlement.connect.go
    • protocol/go/policy/objects.pb.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.


Dynamic rules now take the stage, No longer static on the page. From definition, values flow, To let the right permissions grow.

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.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

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 implements Definition Value Entitlement Mappings (DSPX-2754), which move entitlement authority from concrete attribute values to the attribute definition level. The changes span SDK client generation, caching, PDP evaluation, database storage, and a new gRPC service. The review feedback is highly constructive and identifies several critical issues that should be addressed: a potential data race hazard in the gRPC service, possible nil pointer dereferences in both the PDP evaluator and the database client, a bug in error handling that could return nil values, incorrect type formatting in cache errors, and a redundant database index in the migration script.

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 service/policy/definitionvalueentitlement/definition_value_entitlement.go Outdated
Comment thread service/authorization/v2/cache.go Outdated
Comment thread service/internal/access/v2/helpers.go Outdated
Comment thread service/policy/db/definition_value_entitlement_mappings.go Outdated
Comment thread service/policy/db/definition_value_entitlement_mappings.go Outdated
- Reverse HIERARCHY guard: reject UnsafeUpdateAttribute rule change to
  HIERARCHY when the definition has a dynamic value entitlement mapping
  (symmetric with the create-time guard).
- PDP decision test: ANY_OF permit / ALL_OF deny when a resource carries two
  dynamic values under one definition and the entity is entitled to one.
- Integration tests (testcontainers): CRUD, optional static gate, HIERARCHY
  rejection, no-coexistence both directions, reverse rule guard, list.

Refs: DSPX-3498, DSPX-2754
Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

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

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 429.531288ms
Throughput 232.81 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.331230891s
Average Latency 441.164371ms
Throughput 112.79 requests/second

…ervice

Move the DefinitionValueEntitlementMapping CRUD RPCs/messages from a dedicated
service+package into the existing policy.subjectmapping package / SubjectMappingService.

A brand-new proto package added an import path absent from the released
protocol/go, which broke the per-module 'go mod tidy' CI check (that step does not
use the go workspace). Reusing the already-published subjectmapping package removes
the new import path so go mod tidy passes in a single PR, and drops the long
dedicated package name. The object name DefinitionValueEntitlementMapping is kept.

Refs: DSPX-3498, DSPX-2754
Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

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

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 452.432409ms
Throughput 221.03 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 47.779208084s
Average Latency 475.780561ms
Throughput 104.65 requests/second

Rename the primitive from DefinitionValueEntitlementMapping to DynamicValueMapping
(shorter, drops redundant 'Entitlement' per SubjectMapping/ResourceMapping convention,
avoids overloading the authz 'entitlement' term). The upstream ADR #266 noted names are
subject to change during implementation.

Restore the dedicated service: DynamicValueMappingService in its own
policy.dynamicvaluemapping package (un-folded from SubjectMappingService), with its own
SDK client. DynamicValueResolver + DynamicValueOperatorEnum round out the type family.
DB tables/queries/files renamed to dynamic_value_mapping(s). ADR 0005 updated with the
rename note.

NOTE: this adds a new protocol/go package, so per-module 'go mod tidy' will fail until
protocol/go is released with it (intended; see the protocol-first split).

Refs: DSPX-3498, DSPX-2754
Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

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

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 411.672475ms
Throughput 242.91 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 43.358428704s
Average Latency 431.654544ms
Throughput 115.32 requests/second

Mirror the proto validation fix from #3580 (namespace oneof, min_len:1 + uri on FQN
fields, direct uuid/uri rules) so the consumer branch stays in sync.

Refs: DSPX-2754, DSPX-3498
Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

⚠️ 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

github-actions Bot commented Jun 5, 2026

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

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

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 444.671341ms
Throughput 224.89 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 45.347542117s
Average Latency 451.731513ms
Throughput 110.26 requests/second

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

Labels

comp:authorization comp:db DB component comp:policy Policy Configuration ( attributes, subject mappings, resource mappings, kas registry) comp:sdk A software development kit, including library, for client applications and inter-service communicati docs Documentation size/xl

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants