Skip to content

feat(policy)!: DSPX-2998 add namespace fields to resource mapping protos - #3565

Merged
alkalescent merged 5 commits into
mainfrom
DSPX-2998-optional-namespace-resource-mappings
Jun 10, 2026
Merged

feat(policy)!: DSPX-2998 add namespace fields to resource mapping protos#3565
alkalescent merged 5 commits into
mainfrom
DSPX-2998-optional-namespace-resource-mappings

Conversation

@alkalescent

@alkalescent alkalescent commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Proposed Changes

First PR in a stacked series for DSPX-2998 (Resource Mappings & Resource Mapping Groups should be optionally namespaced). This PR adds the proto contract only; the service implementation and otdfctl/migration support follow in stacked PRs.

  • Add a hydrated policy.Namespace namespace field to the ResourceMapping message.
  • Add optional namespace_id / namespace_fqn to CreateResourceMappingRequest and UpdateResourceMappingRequest.
  • Add optional namespace_id / namespace_fqn filters to ListResourceMappingsRequest, and namespace_fqn parity to ListResourceMappingGroupsRequest (which already had namespace_id).
  • Regenerate protocol/go, OpenAPI/gRPC docs, and SDK connect wrappers.
  • Add proto validation unit tests for the new fields.

This mirrors the namespacing pattern established for Registered Resources (#3110/#3111/#3165). Adding optional fields is wire-compatible; marked ! per the RR proto-PR convention.

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 test ./policy/resourcemapping/...

Related

Summary by CodeRabbit

  • New Features

    • Resource mapping APIs now support optional namespace ownership and filtering by namespace ID or FQN; group creation requires an explicit namespace identifier (ID or FQN).
  • Documentation

    • API and protocol docs updated to describe new namespace fields, request parameters, filtering, and tightened validation semantics; example/description formatting improved.
  • Tests

    • Added validation tests for namespace ID/FQN formats and mutual-exclusion/requirement rules.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: bd6c16fb-6dbf-4acc-a871-bf674d181071

📥 Commits

Reviewing files that changed from the base of the PR and between 063b3b7 and b8879a8.

⛔ Files ignored due to path filters (2)
  • protocol/go/policy/objects.pb.go is excluded by !**/*.pb.go
  • protocol/go/policy/resourcemapping/resource_mapping.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (13)
  • docs/grpc/index.html
  • docs/openapi/authorization/authorization.openapi.yaml
  • docs/openapi/policy/actions/actions.openapi.yaml
  • docs/openapi/policy/attributes/attributes.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/subjectmapping/subject_mapping.openapi.yaml
  • docs/openapi/policy/unsafe/unsafe.openapi.yaml
  • service/policy/objects.proto
  • service/policy/resourcemapping/resource_mapping.proto
  • service/policy/resourcemapping/resource_mapping_test.go
 _______________________________________________________________________________________________________________________________________________
< Costly tools don't produce better designs. Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits. >
 -----------------------------------------------------------------------------------------------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
📝 Walkthrough

Walkthrough

Adds optional namespace ownership to ResourceMapping, extends resourcemapping requests with namespaceId/namespaceFqn and one-of validation, tightens UUID/URI validation, updates OpenAPI/gRPC docs, and adds tests covering valid/invalid namespace inputs and mutual-exclusion rules.

Changes

Namespace Ownership for Resource Mappings

Layer / File(s) Summary
ResourceMapping Message Definition
service/policy/objects.proto
ResourceMapping gains optional namespace field documenting how an owning namespace may be set independently of the mapped attribute's namespace.
Request Validation and Anchored UUIDs
service/policy/resourcemapping/resource_mapping.proto
Adds oneof validation for namespace_id/namespace_fqn, switches namespace_id validation to string.uuid = true, standardizes namespace_fqn as a non-empty URI, and anchors CEL UUID regexes for group/attribute IDs.
OpenAPI Schema Additions
docs/openapi/policy/*, docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml
Adds namespace property to policy.ResourceMapping across multiple OpenAPI files; resourcemapping OpenAPI adds namespaceId/namespaceFqn fields, oneOf ownership contract for group create, and filters for list operations.
gRPC Documentation & OpenAPI Formatting
docs/grpc/index.html, docs/openapi/authorization/authorization.openapi.yaml, docs/openapi/policy/{objects,subjectmapping}/*.openapi.yaml
Updates gRPC HTML to document new namespace fields and adjusts minor OpenAPI description formatting (blank lines/rewrap) without schema shape changes beyond namespace additions.
Namespace Validation Tests
service/policy/resourcemapping/resource_mapping_test.go
Adds tests validating namespace UUID/URI formats, mutual-exclusion (oneof) errors, required-one-of behavior on group creation, and acceptance on updates/lists.

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • elizabethhealy
  • jakedoublev

"🐇 I hopped through proto and spec tonight,
adding namespaces snug and right.
UUIDs and URIs now checked with care,
docs and tests aligned to pair.
A rabbit cheers — validations take flight!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding namespace fields to resource mapping protos, with DSPX-2998 reference and breaking-change marker.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DSPX-2998-optional-namespace-resource-mappings

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:policy Policy Configuration ( attributes, subject mappings, resource mappings, kas registry) docs Documentation size/s labels Jun 4, 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 introduces optional namespace support for Resource Mappings and Resource Mapping Groups. By adding namespace fields to the proto definitions, the system gains the ability to associate resources with specific namespaces, facilitating better organization and filtering. This change is wire-compatible and serves as the foundational proto contract for upcoming service-level implementations.

Highlights

  • Namespace Support: Added optional namespace fields (namespace_id and namespace_fqn) to ResourceMapping and related request objects.
  • Validation: Implemented CEL-based validation for the new namespace fields to ensure correct UUID and URI formats.
  • Testing: Added comprehensive unit tests to verify the validation logic for the new namespace fields across various request types.
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/**/* (9)
    • docs/openapi/authorization/authorization.openapi.yaml
    • docs/openapi/policy/actions/actions.openapi.yaml
    • docs/openapi/policy/attributes/attributes.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/subjectmapping/subject_mapping.openapi.yaml
    • docs/openapi/policy/unsafe/unsafe.openapi.yaml
  • Ignored by pattern: protocol/**/* (2)
    • protocol/go/policy/objects.pb.go
    • protocol/go/policy/resourcemapping/resource_mapping.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.


The namespace fields now take their place, / To bring some order to the space. / With validation strict and tight, / The resource mappings look just right.

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.

@github-actions

github-actions Bot commented Jun 4, 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 174.848884ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 420.918235ms
Throughput 237.58 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.571321978s
Average Latency 444.515427ms
Throughput 112.18 requests/second

@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 optional namespace fields (namespace_id and namespace_fqn) to several resource mapping messages and requests, along with updating the generated documentation and adding unit tests. The review feedback highlights a validation issue where the regular expressions used for UUID validation on namespace_id lack start (^) and end ($) anchors, which allows partial substring matches. Adding these anchors is recommended to ensure strict UUID validation.

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/resourcemapping/resource_mapping.proto Outdated
Comment thread service/policy/resourcemapping/resource_mapping.proto Outdated
Comment thread service/policy/resourcemapping/resource_mapping.proto Outdated
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 5, 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 191.195649ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 432.547787ms
Throughput 231.19 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.90737253s
Average Latency 447.193123ms
Throughput 111.34 requests/second

@alkalescent
alkalescent marked this pull request as ready for review June 5, 2026 17:52
@alkalescent
alkalescent requested review from a team as code owners June 5, 2026 17:52

@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 `@service/policy/resourcemapping/resource_mapping_test.go`:
- Around line 170-183: In Test_ListResourceMappingGroupsRequest_NamespaceFilters
add the missing negative-case for NamespaceId by creating a request with an
invalid NamespaceId (e.g., not-a-uuid) while leaving NamespaceFqn valid, call
v.Validate(req) and assert an error contains the UUID validation message
(errMessageOptionalUUID); likewise, update the complementary test in this file
that currently asserts invalid NamespaceId to also assert the invalid
NamespaceFqn path by creating a request with NamespaceFqn set to a non-URI and
asserting v.Validate(req) returns an error containing errMessageOptionalURI —
use the same validator call (v.Validate) and error assertion pattern as the
existing NamespaceFqn negative test to keep consistency.
🪄 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: c4c063d1-0d91-4792-86c0-31c127626604

📥 Commits

Reviewing files that changed from the base of the PR and between 79ab34f and 36ba6c5.

⛔ Files ignored due to path filters (2)
  • protocol/go/policy/objects.pb.go is excluded by !**/*.pb.go
  • protocol/go/policy/resourcemapping/resource_mapping.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (13)
  • docs/grpc/index.html
  • docs/openapi/authorization/authorization.openapi.yaml
  • docs/openapi/policy/actions/actions.openapi.yaml
  • docs/openapi/policy/attributes/attributes.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/subjectmapping/subject_mapping.openapi.yaml
  • docs/openapi/policy/unsafe/unsafe.openapi.yaml
  • service/policy/objects.proto
  • service/policy/resourcemapping/resource_mapping.proto
  • service/policy/resourcemapping/resource_mapping_test.go

Comment thread service/policy/resourcemapping/resource_mapping_test.go
@github-actions

github-actions Bot commented Jun 5, 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 191.136879ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 451.208992ms
Throughput 221.63 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 46.355194581s
Average Latency 461.725437ms
Throughput 107.86 requests/second

Comment thread service/policy/resourcemapping/resource_mapping.proto Outdated
Comment thread service/policy/resourcemapping/resource_mapping.proto Outdated
alkalescent added a commit that referenced this pull request Jun 8, 2026
Implement the service side of optional namespacing for resource mappings:

- Add a migration adding a nullable namespace_id (FK to attribute_namespaces,
  ON DELETE CASCADE) plus an index to resource_mappings.
- Resolve a mapping's owning namespace from namespace_id/namespace_fqn or its
  group; a grouped mapping must share the group's namespace.
- Remove the constraint forcing the mapped attribute value into the group's
  namespace, allowing mappings to cross namespaces to the values they map.
- Hydrate the namespace on get/list responses and add namespace_id/namespace_fqn
  filters to ListResourceMappings, plus namespace_fqn to ListResourceMappingGroups.
- Enforce a namespace on create when namespaced_policy is enabled (namespace_id,
  namespace_fqn, or group_id satisfies it).
- Update/extend integration tests for the new behavior.

Stacked on the proto PR (#3565).

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

github-actions Bot commented Jun 8, 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 188.78654ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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.696497ms
Throughput 240.56 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.17151156s
Average Latency 440.618794ms
Throughput 113.20 requests/second

Comment thread service/policy/resourcemapping/resource_mapping.proto
elizabethhealy
elizabethhealy previously approved these changes Jun 9, 2026
@alkalescent
alkalescent enabled auto-merge June 9, 2026 16:10
@alkalescent
alkalescent added this pull request to the merge queue Jun 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 9, 2026
@alkalescent
alkalescent added this pull request to the merge queue Jun 9, 2026
Add an optional owning namespace to resource mappings, mirroring the
namespacing already present on registered resources:

- ResourceMapping gains a hydrated policy.Namespace field.
- Create/UpdateResourceMappingRequest gain optional namespace_id and
  namespace_fqn.
- ListResourceMappingsRequest gains optional namespace_id/namespace_fqn
  filters; ListResourceMappingGroupsRequest gains namespace_fqn parity.

Regenerated protocol/go, OpenAPI/gRPC docs, and SDK wrappers. Adds proto
validation unit tests for the new fields.

Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
Address review feedback on the resource mapping protos:

- Switch namespace_id/namespace_fqn validation to the house
  buf.validate.message.oneof + string.uuid/string.uri pattern (matching
  subject_mapping/registered_resources), making the two mutually exclusive.
- Add namespace_fqn to CreateResourceMappingGroupRequest (oneof required) and
  UpdateResourceMappingGroupRequest (oneof optional).
- Regenerate protocol/go + docs; update/extend proto validation unit tests.

Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
Cover the invalid-UUID path for namespace_id on CreateResourceMappingGroup
validation, and invalid namespace_id/namespace_fqn on UpdateResourceMappingGroup,
per review feedback.

Signed-off-by: Krish Suchak <suchak.krish@gmail.com>
@alkalescent
alkalescent force-pushed the DSPX-2998-optional-namespace-resource-mappings branch from a8fa30f to b8879a8 Compare June 10, 2026 16:09
@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 195.896822ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

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

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 420.551298ms
Throughput 237.78 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 45.039953279s
Average Latency 448.375101ms
Throughput 111.01 requests/second

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

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":401,"request":{"method":"PATCH","url":"https://api.github.com/repos/opentdf/platform/issues/comments/4624798213","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- review_stack_entry_start -->\n\n[![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/opentdf/platform/pull/3565?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)\n\n<!-- review_stack_entry_end -->\n<!-- This is an auto-generated comment: failure by coderabbit.ai -->\n\n> [!CAUTION]\n> ## Review failed\n> \n> Failed to post review comments\n\n<!-- end of auto-generated comment: failure by coderabbit.ai -->\n\n<!-- walkthrough_start -->\n\n<details>\n<summary>📝 Walkthrough</summary>\n\n## Walkthrough\n\nAdds optional namespace ownership to ResourceMapping, extends resourcemapping requests with `namespaceId`/`namespaceFqn` and one-of validation, tightens UUID/URI validation, updates OpenAPI/gRPC docs, and adds tests covering valid/invalid namespace inputs and mutual-exclusion rules.\n\n## Changes\n\n**Namespace Ownership for Resource Mappings**\n\n|Layer / File(s)|Summary|\n|---|---|\n|**ResourceMapping Message Definition** <br> `service/policy/objects.proto`|`ResourceMapping` gains optional `namespace` field documenting how an owning namespace may be set independently of the mapped attribute's namespace.|\n|**Request Validation and Anchored UUIDs** <br> `service/policy/resourcemapping/resource_mapping.proto`|Adds `oneof` validation for `namespace_id`/`namespace_fqn`, switches `namespace_id` validation to `string.uuid = true`, standardizes `namespace_fqn` as a non-empty URI, and anchors CEL UUID regexes for group/attribute IDs.|\n|**OpenAPI Schema Additions** <br> `docs/openapi/policy/*`, `docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml`|Adds `namespace` property to `policy.ResourceMapping` across multiple OpenAPI files; resourcemapping OpenAPI adds `namespaceId`/`namespaceFqn` fields, `oneOf` ownership contract for group create, and filters for list operations.|\n|**gRPC Documentation & OpenAPI Formatting** <br> `docs/grpc/index.html`, `docs/openapi/authorization/authorization.openapi.yaml`, `docs/openapi/policy/{objects,subjectmapping}/*.openapi.yaml`|Updates gRPC HTML to document new namespace fields and adjusts minor OpenAPI description formatting (blank lines/rewrap) without schema shape changes beyond namespace additions.|\n|**Namespace Validation Tests** <br> `service/policy/resourcemapping/resource_mapping_test.go`|Adds tests validating namespace UUID/URI formats, mutual-exclusion (`oneof`) errors, required-one-of behavior on group creation, and acceptance on updates/lists.|\n\n🎯 3 (Moderate) | ⏱️ ~20 minutes\n\n## Suggested reviewers\n\n- elizabethhealy\n- jakedoublev\n\n> \"🐇 I hopped through proto and spec tonight,  \n> adding namespaces snug and right.  \n> UUIDs and URIs now checked with care,  \n> docs and tests aligned to pair.  \n> A rabbit cheers — validations take flight!\"\n\n</details>\n\n<!-- walkthrough_end -->\n<!-- pre_merge_checks_walkthrough_start -->\n\n<details>\n<summary>🚥 Pre-merge checks | ✅ 4 | ❌ 1</summary>\n\n### ❌ Failed checks (1 warning)\n\n|     Check name     | Status     | Explanation                                                                          | Resolution                                                                         |\n| :----------------: | :--------- | :----------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- |\n| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |\n\n<details>\n<summary>✅ Passed checks (4 passed)</summary>\n\n|         Check name         | Status   | Explanation                                                                                                                                                                                     |\n| :------------------------: | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|      Description Check     | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled.                                                                                                                                     |\n|         Title check        | ✅ Passed | The title clearly identifies the main change as adding namespace fields to resource mapping protos, which aligns with the comprehensive changeset across proto files, OpenAPI specs, and tests. |\n|     Linked Issues check    | ✅ Passed | Check skipped because no linked issues were found for this pull request.                                                                                                                        |\n| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request.                                                                                                                        |\n\n</details>\n\n<sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub>\n\n</details>\n\n<!-- pre_merge_checks_walkthrough_end -->\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>📝 Generate docstrings</summary>\n\n- [ ] <!-- {\"checkboxId\": \"7962f53c-55bc-4827-bfbf-6a18da830691\"} --> Create stacked PR\n- [ ] <!-- {\"checkboxId\": \"3e1879ae-f29b-4d0d-8e06-d12b7ba33d98\"} --> Commit on current branch\n\n</details>\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n- [ ] <!-- {\"checkboxId\": \"6ba7b810-9dad-11d1-80b4-00c04fd430c8\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Commit unit tests in branch `DSPX-2998-optional-namespace-resource-mappings`\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n<!-- This is an auto-generated comment: resource warnings by coderabbit.ai -->\n\n> [!WARNING]\n> ## Review ran into problems\n> \n> <details>\n> <summary>🔥 Problems</summary>\n> \n> Git: Failed to clone repository. Please run the `@coderabbitai full review` command to re-trigger a full review. If the issue persists, set `path_filters` to include or exclude specific files.\n> \n> </details>\n\n<!-- end of auto-generated comment: resource warnings by coderabbit.ai -->\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=opentdf/platform&utm_content=3565)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n<!-- internal state start -->\n\n\n<!-- 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= -->\n\n<!-- internal state end -->"},"request":{"retryCount":1,"signal":{}}},"response":{"url":"https://api.github.com/repos/opentdf/platform/issues/comments/4624798213","status":401,"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset","connection":"close","content-security-policy":"default-src 'none'","content-type":"application/json; charset=utf-8","date":"Wed, 10 Jun 2026 16:17:15 GMT","referrer-policy":"origin-when-cross-origin, strict-origin-when-cross-origin","server":"github.com","strict-transport-security":"max-age=31536000; includeSubdomains; preload","vary":"Accept-Encoding, Accept, X-Requested-With","x-content-type-options":"nosniff","x-frame-options":"deny","x-github-media-type":"github.v3; format=json","x-github-request-id":"2C2E:251E7C:533E24B:1394F729:6A298E0A","x-xss-protection":"0"},"data":{"message":"Requires authentication","documentation_url":"https://docs.github.com/rest","status":"401"}}}

Comment thread service/policy/resourcemapping/resource_mapping.proto

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

Loo

@alkalescent
alkalescent added this pull request to the merge queue Jun 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 10, 2026
@alkalescent
alkalescent added this pull request to the merge queue Jun 10, 2026
Merged via the queue into main with commit e4a04ed Jun 10, 2026
39 of 40 checks passed
@alkalescent
alkalescent deleted the DSPX-2998-optional-namespace-resource-mappings branch June 10, 2026 20:01
alkalescent added a commit that referenced this pull request Jun 15, 2026
Implement the service side of optional namespacing for resource mappings:

- Add a migration adding a nullable namespace_id (FK to attribute_namespaces,
  ON DELETE CASCADE) plus an index to resource_mappings.
- Resolve a mapping's owning namespace from namespace_id/namespace_fqn or its
  group; a grouped mapping must share the group's namespace.
- Remove the constraint forcing the mapped attribute value into the group's
  namespace, allowing mappings to cross namespaces to the values they map.
- Hydrate the namespace on get/list responses and add namespace_id/namespace_fqn
  filters to ListResourceMappings, plus namespace_fqn to ListResourceMappingGroups.
- Enforce a namespace on create when namespaced_policy is enabled (namespace_id,
  namespace_fqn, or group_id satisfies it).
- Update/extend integration tests for the new behavior.

Stacked on the proto PR (#3565).

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

Copy link
Copy Markdown
Contributor

/backport

@opentdf-automation

Copy link
Copy Markdown
Contributor

Created backport PR for release/service/v0.11:

Please cherry-pick the changes locally and resolve any conflicts.

git fetch origin backport-3565-to-release/service/v0.11
git worktree add --checkout .worktree/backport-3565-to-release/service/v0.11 backport-3565-to-release/service/v0.11
cd .worktree/backport-3565-to-release/service/v0.11
git reset --hard HEAD^
git cherry-pick -x e4a04ed6ee04a346a00a49d3c1f381295f9e9443
git push --force-with-lease

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants