Skip to content
38 changes: 35 additions & 3 deletions src/managedcleanroom/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,46 @@ Release History
===============

1.0.0b1
++++++
+++++++
* Initial release.

1.0.0b2
++++++
+++++++
* Add frontend commandlets
* Add MSAL device code flow authentication

1.0.0b3
++++++
* Update commands to reflect new API version 2026-03-31-preview
* Update commands to reflect new API version 2026-03-31-preview

1.0.0b4
+++++++
* Updated to latest Frontend API spec from develop branch (2026-03-01-preview)
* Regenerated analytics_frontend_api SDK with updated method signatures
* SDK Changes (internal, transparent to CLI users):
- Method renames: collaboration.list → collaboration.list_get
- Method renames: analytics_dataset_* → analytics_datasets_* (dataset → datasets, plural)
- Method renames: check_consent_document_id_get → consent_document_id_get
- Method renames: set_consent_document_id_put → consent_document_id_put
* BREAKING CHANGE: All frontend API endpoints now require api-version=2026-03-01-preview query parameter
* Added: --api-version parameter to all frontend commands (default: 2026-03-01-preview)
* Updated: SDK client now automatically injects api-version into all API requests
* BREAKING CHANGE: Removed deprecated commands (APIs no longer supported in SDK):
- `az managedcleanroom frontend workloads list`
- `az managedcleanroom frontend analytics deploymentinfo`
- `az managedcleanroom frontend attestation cgs`
- `az managedcleanroom frontend analytics attestationreport cleanroom`
- `az managedcleanroom frontend analytics query vote accept`
- `az managedcleanroom frontend analytics query vote reject`
* BREAKING CHANGE: Consent action values changed from 'accept/reject' to 'enable/disable'
* BREAKING CHANGE: Vote commands consolidated into single unified endpoint
* Added: `az managedcleanroom frontend report` - Comprehensive attestation report (replaces cgs/cleanroom commands)
* Added: `az managedcleanroom frontend oidc set-issuer-url` - Configure OIDC issuer URL
* Added: `az managedcleanroom frontend oidc keys` - Get OIDC signing keys (JWKS)
* Added: `az managedcleanroom frontend analytics dataset queries` - List queries using a specific dataset
* Added: `az managedcleanroom frontend analytics secret set` - Set analytics secrets
* Added: `az managedcleanroom frontend analytics query vote` - Unified vote command with --vote-action parameter
* Updated: Added --active-only filter to collaboration list and show commands
* Updated: Added --pending-only filter to invitation list command
* Updated: Added --scope, --from-seqno, --to-seqno filters to audit event list command
* Updated: Response structures modernized (many list endpoints now return structured objects with value arrays)
15 changes: 12 additions & 3 deletions src/managedcleanroom/azext_managedcleanroom/_frontend_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ def get_frontend_token(cmd):
profile = Profile(cli_ctx=cmd.cli_ctx)
subscription = get_subscription_id(cmd.cli_ctx)

# Priority 0: explicit token via environment variable (for local/test envs only)
# Priority 0: explicit token via environment variable (for local/test envs
# only)
env_token = os.environ.get('MANAGEDCLEANROOM_ACCESS_TOKEN')
if env_token:
logger.warning("Using token from MANAGEDCLEANROOM_ACCESS_TOKEN env var FOR TESTING PURPOSES ONLY")
logger.warning(
"Using token from MANAGEDCLEANROOM_ACCESS_TOKEN env var FOR TESTING PURPOSES ONLY")
from collections import namedtuple
AccessToken = namedtuple('AccessToken', ['token', 'expires_on'])
token_obj = AccessToken(token=env_token, expires_on=0)
Expand Down Expand Up @@ -87,7 +89,7 @@ def set_frontend_config(cmd, endpoint):
endpoint)


def get_frontend_client(cmd, endpoint=None):
def get_frontend_client(cmd, endpoint=None, api_version=None):
"""Create Analytics Frontend API client with Azure authentication

Uses Profile.get_raw_token() to fetch access token from Azure context.
Expand All @@ -96,12 +98,18 @@ def get_frontend_client(cmd, endpoint=None):
:param cmd: CLI command context
:param endpoint: Optional explicit endpoint URL (overrides config)
:type endpoint: str
:param api_version: Optional API version (defaults to 2026-03-01-preview)
:type api_version: str
:return: Configured AnalyticsFrontendAPI client
:raises: CLIError if token fetch fails or endpoint not configured
"""
from .analytics_frontend_api import AnalyticsFrontendAPI
from azure.core.pipeline.policies import BearerTokenCredentialPolicy, SansIOHTTPPolicy

# Use provided api_version or default
if api_version is None:
api_version = '2026-03-01-preview'

api_endpoint = endpoint or get_frontend_config(cmd)
if not api_endpoint:
raise CLIError(
Expand Down Expand Up @@ -172,5 +180,6 @@ def on_request(self, request):
# Return configured client
return AnalyticsFrontendAPI(
endpoint=api_endpoint,
api_version=api_version,
authentication_policy=auth_policy
)
39 changes: 15 additions & 24 deletions src/managedcleanroom/azext_managedcleanroom/_frontend_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,23 @@ def load_frontend_command_table(loader, _):
# Show command at frontend level (requires --collaboration-id)
with loader.command_group('managedcleanroom frontend', custom_command_type=frontend_custom) as g:
g.custom_show_command('show', 'frontend_collaboration_show')

# Workloads commands
with loader.command_group('managedcleanroom frontend workloads', custom_command_type=frontend_custom) as g:
g.custom_command('list', 'frontend_collaboration_workloads_list')
g.custom_show_command('report', 'frontend_collaboration_report_show')

# Analytics commands
with loader.command_group('managedcleanroom frontend analytics', custom_command_type=frontend_custom) as g:
g.custom_show_command('show', 'frontend_collaboration_analytics_show')
g.custom_command(
'deploymentinfo',
'frontend_collaboration_analytics_deploymentinfo')
g.custom_command(
'cleanroompolicy',
'frontend_collaboration_analytics_cleanroompolicy')

# OIDC commands
with loader.command_group('managedcleanroom frontend oidc', custom_command_type=frontend_custom) as g:
g.custom_command(
'set-issuer-url',
'frontend_collaboration_oidc_set_issuer_url')
g.custom_show_command('keys', 'frontend_collaboration_oidc_keys_show')

# Keep issuerinfo for backwards compatibility
with loader.command_group('managedcleanroom frontend oidc issuerinfo', custom_command_type=frontend_custom) as g:
g.custom_show_command(
'show', 'frontend_collaboration_oidc_issuerinfo_show')
Expand All @@ -57,6 +58,9 @@ def load_frontend_command_table(loader, _):
g.custom_command('list', 'frontend_collaboration_dataset_list')
g.custom_show_command('show', 'frontend_collaboration_dataset_show')
g.custom_command('publish', 'frontend_collaboration_dataset_publish')
g.custom_command(
'queries',
'frontend_collaboration_dataset_queries_list')

# Consent commands
with loader.command_group('managedcleanroom frontend consent', custom_command_type=frontend_custom) as g:
Expand All @@ -69,13 +73,7 @@ def load_frontend_command_table(loader, _):
g.custom_show_command('show', 'frontend_collaboration_query_show')
g.custom_command('publish', 'frontend_collaboration_query_publish')
g.custom_command('run', 'frontend_collaboration_query_run')

# Query vote commands
with loader.command_group(
'managedcleanroom frontend analytics query vote',
custom_command_type=frontend_custom) as g:
g.custom_command('accept', 'frontend_collaboration_query_vote_accept')
g.custom_command('reject', 'frontend_collaboration_query_vote_reject')
g.custom_command('vote', 'frontend_collaboration_query_vote')

# Query run history commands
with loader.command_group(
Expand All @@ -97,16 +95,9 @@ def load_frontend_command_table(loader, _):
custom_command_type=frontend_custom) as g:
g.custom_command('list', 'frontend_collaboration_audit_list')

# Attestation commands
with loader.command_group('managedcleanroom frontend attestation', custom_command_type=frontend_custom) as g:
g.custom_command('cgs', 'frontend_collaboration_attestation_cgs')

with loader.command_group(
'managedcleanroom frontend analytics attestationreport',
custom_command_type=frontend_custom) as g:
g.custom_command(
'cleanroom',
'frontend_collaboration_attestation_cleanroom')
# Analytics secrets command
with loader.command_group('managedcleanroom frontend analytics secret', custom_command_type=frontend_custom) as g:
g.custom_command('set', 'frontend_collaboration_analytics_secret_set')

# Configuration and authentication commands
with loader.command_group('managedcleanroom frontend', custom_command_type=frontend_custom) as g:
Expand Down
Loading
Loading