Skip to content

test: cross-SDK key-mapping split parity (scaffold)#541

Draft
alkalescent wants to merge 2 commits into
mainfrom
DSPX-2541-key-mapping-parity
Draft

test: cross-SDK key-mapping split parity (scaffold)#541
alkalescent wants to merge 2 commits into
mainfrom
DSPX-2541-key-mapping-parity

Conversation

@alkalescent

Copy link
Copy Markdown
Contributor

What

Scaffolds the cross-SDK parity test requested for the new narrow attribute read APIs (opentdf/platform): proving a go SDK that resolves key splits via GetKeyMappingsByFqns produces the same TDF key-access split structure as a previous released go SDK (which walks the full attribute set), and that the two containers cross-decrypt.

Changes

  • tdfs.py: new key_mapping_resolution platform feature (gates the test; TODO: pin the exact platform release that ships GetKeyMappingsByFqns — currently guarded at >= 0.14.0 conservatively).
  • test_abac_key_mapping_parity.py: test_key_mapping_split_parity_value_level — encrypts the same plaintext with a new (main/sha) and a previous released go SDK over a value-level keyed attribute, then compares split structure (key-access objects grouped by split id → set of (kas_url, kid)) and cross-decrypts.

Status — DRAFT, not yet validated end-to-end

This cannot pass until both land and a build is available, so it skips otherwise:

Validated here only at the unit level: syntax + ruff. It has not been run against a live stack.

Follow-ups

  • Pin key_mapping_resolution to the real release version once #3634 ships.
  • Extend coverage to definition- and namespace-level mapped keys and any_of/hierarchy rules across distinct KASes; this needs key_assign_attribute / key_assign_namespace helpers added to otdfctl.py (today only key_assign_value exists) and multi-KAS keyed fixtures.

Add a key_mapping_resolution platform feature gate and a parity test asserting a
go SDK that resolves key splits via GetKeyMappingsByFqns produces the same TDF
key-access split structure as a previous released go SDK, with cross-decrypt.

Covers value-level mapped keys; definition/namespace levels and any_of/hierarchy
across distinct KASes are TODO (need key_assign_attribute/key_assign_namespace
otdfctl helpers). Skips until the platform exposes the RPC and a new go SDK build
is present alongside a released one.

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

coderabbitai Bot commented Jun 30, 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 00fc2a2d-5225-478b-9a4b-69e9176c6bbb

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-mapping-parity

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the "key_mapping_resolution" feature flag gated on platform version 0.14.0 and adds a cross-SDK parity test to verify that the new GetKeyMappingsByFqns RPC produces the same key-access split structure as previous released SDKs. The feedback suggests defining the missing attribute_with_different_kids fixture to avoid a test failure, sorting the released SDK versions to ensure deterministic selection, and using a deep byte-by-byte comparison (shallow=False) in filecmp.cmp to prevent false positives.

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 xtest/test_abac_key_mapping_parity.py Outdated
Comment on lines +53 to +57
def test_key_mapping_split_parity_value_level(
attribute_with_different_kids: Attribute,
pt_file: Path,
tmp_dir: Path,
):

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.

high

The test function test_key_mapping_split_parity_value_level requests a fixture named attribute_with_different_kids, but this fixture is not defined anywhere in the codebase (including xtest/fixtures/attributes.py or other loaded fixture plugins). Running this test will result in a FixtureLookupError from pytest. Please define this fixture in xtest/fixtures/attributes.py or ensure it is imported correctly.

Comment on lines +44 to +50
def _go_sdk_pair() -> tuple[tdfs.SDK, tdfs.SDK]:
go = tdfs.all_versions_of("go")
new = next((s for s in go if not s.is_released()), None)
prev = next((s for s in go if s.is_released()), None)
if new is None or prev is None:
pytest.skip("requires both a new (main/sha) and a previous released go SDK build")
return new, prev

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

In _go_sdk_pair(), next((s for s in go if s.is_released()), None) is used to retrieve a released version of the Go SDK. Since os.listdir (used by tdfs.all_versions_of) returns directory entries in an arbitrary order, this will non-deterministically select any released version present in the directory. To ensure deterministic and correct test behavior, the released versions should be sorted (e.g., by semantic version) to consistently select the latest released version.

def _go_sdk_pair() -> tuple[tdfs.SDK, tdfs.SDK]:
    go = tdfs.all_versions_of("go")
    new = next((s for s in go if not s.is_released()), None)
    released = [s for s in go if s.is_released()]
    prev = None
    if released:
        released.sort(key=lambda s: tdfs._parse_semver(s.version) or (0, 0, 0), reverse=True)
        prev = released[0]
    if new is None or prev is None:
        pytest.skip("requires both a new (main/sha) and a previous released go SDK build")
    return new, prev

Comment on lines +75 to +78
for ct, decrypt_sdk in ((new_ct, prev_sdk), (prev_ct, new_sdk)):
rt = tmp_dir / f"{ct.stem}.untdf"
decrypt_sdk.decrypt(ct, rt, "ztdf")
assert filecmp.cmp(pt_file, rt)

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

By default, filecmp.cmp uses a shallow comparison (shallow=True), which only compares the os.stat signature (size, mtime, etc.) of the files. In fast-running test environments where files are created and modified rapidly, this can lead to false positives due to identical stat metadata. It is safer to use shallow=False to force a byte-by-byte content comparison.

Suggested change
for ct, decrypt_sdk in ((new_ct, prev_sdk), (prev_ct, new_sdk)):
rt = tmp_dir / f"{ct.stem}.untdf"
decrypt_sdk.decrypt(ct, rt, "ztdf")
assert filecmp.cmp(pt_file, rt)
for ct, decrypt_sdk in ((new_ct, prev_sdk), (prev_ct, new_sdk)):
rt = tmp_dir / f"{ct.stem}.untdf"
decrypt_sdk.decrypt(ct, rt, "ztdf")
assert filecmp.cmp(pt_file, rt, shallow=False)

The server now resolves legacy grants inside GetKeyMappingsByFqns (grants with a
cached key are converted to keys), so the parity story covers grant-configured
policy too. Broaden the parity test from a single-KAS multi-KID case to also
cover two-KAS ANY_OF (share) and multi-value ALL_OF (split), which exercise the
rule-driven combine logic through the new resolution path. Document that legacy
grants auto-convert to mapped keys on key_management platforms, so a dedicated
legacy-grant-only case remains a TODO.

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

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant