Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions xtest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,13 @@ def pytest_configure(config: pytest.Config) -> None:
# If the user passed --sdks-encrypt / --sdks-decrypt explicitly, their
# tokens win and we skip the resolution step entirely.
need_resolve = (
(not config.getoption("--sdks-encrypt") and scenario.sdks.encrypt)
or (not config.getoption("--sdks-decrypt") and scenario.sdks.decrypt)
)
not config.getoption("--sdks-encrypt") and scenario.sdks.encrypt
) or (not config.getoption("--sdks-decrypt") and scenario.sdks.decrypt)
if need_resolve:
try:
tokens = scenario_to_pytest_sdks(scenario, installed_json_for(scenario_path))
tokens = scenario_to_pytest_sdks(
scenario, installed_json_for(scenario_path)
)
except FileNotFoundError as e:
raise pytest.UsageError(str(e)) from e
if not config.getoption("--sdks-encrypt") and tokens["encrypt"]:
Expand Down
185 changes: 185 additions & 0 deletions xtest/scenarios/FEATURES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# KAS Preview Features in Scenario Files

This guide documents how to configure KAS preview settings via the `features` dict in scenario YAML files.

## Overview

The `features` dict in a `KasPin` allows scenario authors to enable platform preview settings for specific KAS instances. Features are written to the generated `opentdf.yaml` as `services.kas.preview.<key>: <value>`.

**Important:** Available preview settings depend on the platform version and may include experimental features in PRs. This guide provides common examples but is not exhaustive.

## Basic Usage

```yaml
instance:
kas:
km1:
source: { ref: "pr:3537" }
mode: key_management
features:
hybrid_tdf_enabled: true # Enable ML-KEM wrapping
```

## Precedence Rules

Features are applied in order (last wins):

1. **Template defaults** — from `opentdf-kas-mode.yaml` shipped with the platform
2. **Mode-based auto-enables** — e.g., `key_management` mode sets `ec_tdf_enabled: true`
3. **User features** — specified in scenario YAML (override previous layers)

This allows you to override mode defaults when needed for testing.

## Common Preview Settings

These examples represent common settings as of 2026-06. Check your platform version's documentation for the complete list.

### `ec_tdf_enabled`

Enables elliptic-curve wrapping for TDF encryption.

- **Auto-enabled:** `key_management` mode
- **When to use:** Testing EC wrapping on standard KAS instances
- **Example:**
```yaml
kas:
alpha:
source: { ref: "v0.15.0" }
mode: standard
features:
ec_tdf_enabled: true
```

### `hybrid_tdf_enabled`

Enables hybrid post-quantum wrapping (ML-KEM).

- **Auto-enabled:** Never (requires explicit opt-in)
- **When to use:** Testing ML-KEM encryption scenarios
- **Example:**
```yaml
kas:
km1:
source: { ref: "pr:3537" }
mode: key_management
features:
hybrid_tdf_enabled: true # Required for mlkem:768 / mlkem:1024
```

### `key_management`

Enables the managed key registry and key provisioning APIs.

- **Auto-enabled:** `key_management` mode
- **When to use:** Rarely needed explicitly (mode handles it)
- **Example (disabling on key_management KAS for testing):**
```yaml
kas:
km1:
mode: key_management
features:
key_management: false # Override mode default
```

## Example Scenarios

### ML-KEM Encryption Testing

```yaml
instance:
kas:
km1:
source: { ref: "pr:3537" }
mode: key_management
features:
hybrid_tdf_enabled: true # Accept ML-KEM wrapped KAOs
km2:
source: { ref: "pr:3537" }
mode: key_management
features:
hybrid_tdf_enabled: true
```

### EC Wrapping on Standard KAS

```yaml
instance:
kas:
alpha:
source: { ref: "v0.15.0" }
mode: standard
features:
ec_tdf_enabled: true # Enable EC without key management
```

### Disabling Mode Auto-Enables

```yaml
instance:
kas:
km1:
mode: key_management
features:
ec_tdf_enabled: false # Override mode's auto-enable for testing
```

## Experimental Features in PRs

Platform PRs may introduce experimental preview settings not listed here. Use the same syntax:

```yaml
kas:
alpha:
source: { ref: "pr:9999" }
mode: standard
features:
experimental_new_feature: true
```

The scenario framework applies all features without validation, making it forward-compatible with new settings.

## Instance-Level Features

The `Instance.features` dict is reserved for future use. Currently, only per-KAS features are supported:

```yaml
instance:
features: {} # Reserved, not implemented
kas:
km1:
features:
hybrid_tdf_enabled: true # Use this instead
```

## Verification

After running `otdf-local instance init` and `otdf-local up`, verify the generated config:

```bash
grep -A 5 "preview:" instances/<name>/kas/km1/opentdf.yaml
```

Expected output for a `key_management` KAS with `hybrid_tdf_enabled: true`:

```yaml
preview:
ec_tdf_enabled: true
hybrid_tdf_enabled: true
key_management: true
```

## Troubleshooting

### Feature not appearing in config

1. Check the scenario YAML syntax (YAML indentation matters)
2. Verify `otdf-local instance init` ran without errors
3. Check if the feature exists in your platform version

### Feature value overridden

Remember precedence: user features override mode defaults. If a mode auto-enables a feature and you don't want it, explicitly set it to `false`.

### Unknown feature

Platform versions vary in which preview settings they support. Experimental PRs may have settings not in stable releases. The framework applies all features without validation for forward compatibility.
75 changes: 75 additions & 0 deletions xtest/scenarios/pure-mlkem.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
apiVersion: opentdf.io/v1alpha1
kind: Scenario
metadata:
id: pure-mlkem
name: pure-mlkem
title: "Pure ML-KEM (mlkem:768 / mlkem:1024) — platform PR #3537"
created: "2026-05-29"
instance:
apiVersion: opentdf.io/v1alpha1
kind: Instance
metadata:
name: pure-mlkem
platform:
source:
ref: pr:3537
ports:
base: 8080
kas:
alpha: { source: { ref: "pr:3537" }, mode: standard }
beta: { source: { ref: "pr:3537" }, mode: standard }
gamma: { source: { ref: "pr:3537" }, mode: standard }
delta: { source: { ref: "pr:3537" }, mode: standard }
km1:
source: { ref: "pr:3537" }
mode: key_management
features:
hybrid_tdf_enabled: true # Required for ML-KEM wrapping
km2:
source: { ref: "pr:3537" }
mode: key_management
features:
hybrid_tdf_enabled: true # Required for ML-KEM wrapping
sdks:
encrypt:
- sdk: go
version: refs--pull--3537--head
decrypt:
- sdk: go
version: refs--pull--3537--head
suite:
targets:
- test_pqc.py::test_mlkem_768_roundtrip
- test_pqc.py::test_mlkem_1024_roundtrip
containers:
- ztdf
expected: |
Platform built from PR #3537 accepts mlkem:768 and mlkem:1024 managed-key
registrations on km1 and km2 (kids m1 / m2). KAS instances km1 and km2 have
`hybrid_tdf_enabled: true` in their preview settings to accept ML-KEM wrapped
KAOs. Encrypt with go@pr:3537 produces a single KAO whose wrappedKey exceeds
the raw ML-KEM ciphertext (>1088 / >1568 bytes). Decrypt with go@pr:3537
succeeds and round-trips the plaintext.
actual: |
Both test_mlkem_768_roundtrip and test_mlkem_1024_roundtrip PASS end-to-end
with go@refs--pull--3537--head encrypt + decrypt against PR #3537 platform
(head 08ab3a0a, "refactor(ocrypto): encode pure ML-KEM keys as SPKI/PKCS#8
with NIST OIDs"). Observed: KAS Registry accepts algorithm enum 20/21,
emits SPKI/PKCS#8 PEMs of the expected sizes (mlkem:768 ≥ 1184B encap key,
mlkem:1024 ≥ 1568B). The KAO `type` field is "wrapped" (the existing
generic type), NOT "mlkem-wrapped" as some PR notes hint — algorithm is
disambiguated via key registry / kid, not a new KAO type. Test assertion
was relaxed to accept either; revisit if the PR later adds a distinct type.

Decrypt with non-PR clients (Java, JS, older Go) not yet observed — those
SDKs aren't installed in this scenario. Add them to sdks.decrypt and rerun
to answer the "can older clients decrypt mlkem?" question empirically.

Setup notes (one-time per PR worktree):
1. Symlinked xtest/platform and xtest/sdk/go/dist → DSPX-3302-02-platform-installer
worktree (uv-tool-installed otdf-sdk-mgr/otdf-local anchor to that worktree).
2. Seeded PR worktree with kas-*.pem + keys/ + opentdf.yaml from main
(PR source tree ships templates but not generated keys; init-temp-keys.sh
would generate them properly).
3. Set PLATFORM_VERSION=0.17.0 (override; PR build reports version "0.9.0")
and OTDFCTL_HEADS='["refs--pull--3537--head"]' for the test invocation.
2 changes: 2 additions & 0 deletions xtest/schema/instance.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"additionalProperties": {
"type": "boolean"
},
"description": "KAS preview settings to enable. Keys are preview setting names (without the 'services.kas.preview.' prefix); values are booleans. Available settings depend on the platform version and may include experimental features in PRs. User-specified features override mode-based defaults.",
"title": "Features",
"type": "object"
},
Expand Down Expand Up @@ -224,6 +225,7 @@
"additionalProperties": {
"type": "boolean"
},
"description": "Reserved for future use. Instance-level feature defaults are not currently implemented. Use per-KAS features in the kas dict instead.",
"title": "Features",
"type": "object"
},
Expand Down
2 changes: 2 additions & 0 deletions xtest/schema/scenario.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"additionalProperties": {
"type": "boolean"
},
"description": "Reserved for future use. Instance-level feature defaults are not currently implemented. Use per-KAS features in the kas dict instead.",
"title": "Features",
"type": "object"
},
Expand Down Expand Up @@ -102,6 +103,7 @@
"additionalProperties": {
"type": "boolean"
},
"description": "KAS preview settings to enable. Keys are preview setting names (without the 'services.kas.preview.' prefix); values are booleans. Available settings depend on the platform version and may include experimental features in PRs. User-specified features override mode-based defaults.",
"title": "Features",
"type": "object"
},
Expand Down
5 changes: 5 additions & 0 deletions xtest/tdfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ def __init__(self, **kwargs: dict[str, Any]):
if any(a.startswith("mlkem:") for a in algs):
self.features.add("mechanism-mlkem")

# Pure ML-KEM (non-hybrid) added by platform PR #3537. Tentatively v0.17.0;
# bump when the release target is finalized.
if self.semver >= (0, 17, 0):
self.features.add("mechanism-mlkem")

print(f"PLATFORM_VERSION '{v}' supports [{', '.join(self.features)}]")

def skip_if_unsupported(self, *features: feature_type):
Expand Down
Loading