Palo Alto Networks Prisma AIRS - AI Model Security

Scan and govern AI models with Palo Alto Networks Prisma AIRS AI Supply Chain Security: model scans, evaluations, violations, labels, model groups, and security rules.

Cloud Security · Palo Alto Networks - Prisma AIRs AI Security

Details

IDPalo Alto Networks Prisma AIRS - AI Model Security
ProviderPalo Alto Networks
CategoryCloud Security
From Version6.10.0
Docker Imagedemisto/python3:3.12.14.12343672

README

Scan and govern AI models with Palo Alto Networks Prisma AIRS AI Supply Chain Security: model scans, evaluations, violations, labels, model groups, and security rules.
This integration was integrated and tested with Palo Alto Networks Prisma AIRS - AI Supply Chain Security.

Configure Palo Alto Networks Prisma AIRS - AI Supply Chain Security in Cortex

Parameter Description Required
Server URL   True
API Client ID   True
API Client Secret   True
Tenant Services Group ID Default Tenant Services Group ID to use for API calls. Example: 1234567890. True
Trust any certificate (not secure)   False
Use system proxy settings   False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

prisma-airs-model-security-scans-list


List all model security scans.

Base Command

prisma-airs-model-security-scans-list

Input

Argument Name Description Required
limit The maximum number of scans to return. Default is 50. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityScan.uuid String The scan UUID.
PrismaAIRs.ModelSecurityScan.model_uri String The model URI that was scanned.
PrismaAIRs.ModelSecurityScan.eval_outcome String The evaluation outcome (ALLOWED, BLOCKED).
PrismaAIRs.ModelSecurityScan.source_type String The source type (HUGGING_FACE, LOCAL, etc.).
PrismaAIRs.ModelSecurityScan.security_group_uuid String The security group UUID.
PrismaAIRs.ModelSecurityScan.security_group_name String The security group name.
PrismaAIRs.ModelSecurityScan.scan_origin String The scan origin.
PrismaAIRs.ModelSecurityScan.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityScan.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityScan.created_by String The user who created the scan.

prisma-airs-model-security-scans-create


Create a new model security scan to check a model for supply chain security issues. Scan is asynchronous - use scans-get to poll for completion.

Base Command

prisma-airs-model-security-scans-create

Input

Argument Name Description Required
model_uri The model URI (HuggingFace URL like https://huggingface.co/microsoft/DialoGPT-medium or local path). Required
security_group_uuid The security group UUID to use for scanning. Required
scan_origin The scan origin identifier. Possible values are: MODEL_SECURITY_SDK, MODEL_SECURITY_API, MODEL_SECURITY_FRONTEND, HUGGING_FACE. Default is MODEL_SECURITY_API. Optional
model_name The model name (optional metadata). Optional
model_author The model author (optional metadata). Optional
model_version The model version (optional metadata). Optional
labels The labels to tag the scan, as a JSON array of key/value objects, e.g. [{“key”: “env”, “value”: “prod”}, {“key”: “team”, “value”: “ml”}]. Keys (<=128 chars) and values (<=256 chars) must match ^[a-zA-Z0-9_-]+$. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityScanCreate.uuid String The scan UUID.
PrismaAIRs.ModelSecurityScanCreate.labels Unknown The labels (key/value pairs) applied to the scan.
PrismaAIRs.ModelSecurityScanCreate.model_uri String The model URI that was scanned.
PrismaAIRs.ModelSecurityScanCreate.security_group_uuid String The security group UUID used for scanning.
PrismaAIRs.ModelSecurityScanCreate.security_group_name String The security group name.
PrismaAIRs.ModelSecurityScanCreate.scan_origin String The scan origin.
PrismaAIRs.ModelSecurityScanCreate.eval_outcome String The evaluation outcome (PENDING initially, then ALLOWED/BLOCKED).
PrismaAIRs.ModelSecurityScanCreate.source_type String The model source type.
PrismaAIRs.ModelSecurityScanCreate.owner String The scan owner.
PrismaAIRs.ModelSecurityScanCreate.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityScanCreate.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityScanCreate.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityScanCreate.rules_passed Number The number of rules that passed.
PrismaAIRs.ModelSecurityScanCreate.rules_failed Number The number of rules that failed.
PrismaAIRs.ModelSecurityScanCreate.total_rules Number The total number of rules evaluated.

prisma-airs-model-security-scans-get


Get model security scan status and results. Use this to poll scan completion after scans-create.

Base Command

prisma-airs-model-security-scans-get

Input

Argument Name Description Required
uuid The scan UUID to retrieve. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityScanGet.uuid String The scan UUID.
PrismaAIRs.ModelSecurityScanGet.model_uri String The model URI that was scanned.
PrismaAIRs.ModelSecurityScanGet.security_group_uuid String The security group UUID used for scanning.
PrismaAIRs.ModelSecurityScanGet.security_group_name String The security group name.
PrismaAIRs.ModelSecurityScanGet.scan_origin String The scan origin.
PrismaAIRs.ModelSecurityScanGet.eval_outcome String The evaluation outcome (PENDING/ALLOWED/BLOCKED).
PrismaAIRs.ModelSecurityScanGet.source_type String The model source type.
PrismaAIRs.ModelSecurityScanGet.owner String The scan owner.
PrismaAIRs.ModelSecurityScanGet.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityScanGet.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityScanGet.created_by String The user who created the scan.
PrismaAIRs.ModelSecurityScanGet.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityScanGet.model_version_uuid String The model version UUID.
PrismaAIRs.ModelSecurityScanGet.enabled_rule_count_snapshot Number The snapshot of enabled rules count at scan time.
PrismaAIRs.ModelSecurityScanGet.scanner_version String The scanner version used.
PrismaAIRs.ModelSecurityScanGet.time_started Date The scan start time in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityScanGet.total_files_scanned Number The total files scanned.
PrismaAIRs.ModelSecurityScanGet.total_files_skipped Number The total files skipped.
PrismaAIRs.ModelSecurityScanGet.rules_passed Number The number of rules that passed.
PrismaAIRs.ModelSecurityScanGet.rules_failed Number The number of rules that failed.
PrismaAIRs.ModelSecurityScanGet.total_rules Number The total number of rules evaluated.
PrismaAIRs.ModelSecurityScanGet.error_code String The error code if scan failed.
PrismaAIRs.ModelSecurityScanGet.error_message String The error message if scan failed.
PrismaAIRs.ModelSecurityScanGet.model_formats Unknown The model file formats detected.

prisma-airs-model-security-scans-violations


Get rule violations for a model security scan. Shows detailed information about which security rules failed and why.

Base Command

prisma-airs-model-security-scans-violations

Input

Argument Name Description Required
uuid The scan UUID to retrieve violations for. Required
limit The maximum number of violations to return. Default is 50. Optional
offset The offset for pagination. Default is 0. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityViolation.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityViolation.violations.uuid String The violation UUID.
PrismaAIRs.ModelSecurityViolation.violations.rule_name String The security rule name that failed.
PrismaAIRs.ModelSecurityViolation.violations.rule_description String The security rule description.
PrismaAIRs.ModelSecurityViolation.violations.description String The violation description.
PrismaAIRs.ModelSecurityViolation.violations.rule_instance_state String The rule instance state (BLOCKING/ALLOWING).
PrismaAIRs.ModelSecurityViolation.violations.file String The file path where violation was found.
PrismaAIRs.ModelSecurityViolation.violations.threat String The threat type.
PrismaAIRs.ModelSecurityViolation.violations.threat_description String The threat description.
PrismaAIRs.ModelSecurityViolation.violations.module String The module where threat was found.
PrismaAIRs.ModelSecurityViolation.violations.operator String The operator involved in violation.
PrismaAIRs.ModelSecurityViolation.violations.hash String The hash of the violating file.
PrismaAIRs.ModelSecurityViolation.violations.rule_instance_uuid String The rule instance UUID.
PrismaAIRs.ModelSecurityViolation.violations.created_at Date The violation creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityViolation.violations.updated_at Date The violation last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityViolation.violations.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityViolation.total_items Number The total number of violations available.
PrismaAIRs.ModelSecurityViolation.limit Number The limit used for pagination.
PrismaAIRs.ModelSecurityViolation.offset Number The offset used for pagination.

prisma-airs-model-security-labels-keys


Get distinct label keys across all model security scans. Use for discovering available labels for filtering/organization.

Base Command

prisma-airs-model-security-labels-keys

Input

Argument Name Description Required
limit The maximum number of label keys to return. Default is 50. Optional
offset The offset for pagination. Default is 0. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityLabelKeys.keys Unknown The list of distinct label keys.
PrismaAIRs.ModelSecurityLabelKeys.total_items Number The total number of label keys available.
PrismaAIRs.ModelSecurityLabelKeys.limit Number The limit used for pagination.
PrismaAIRs.ModelSecurityLabelKeys.offset Number The offset used for pagination.

prisma-airs-model-security-labels-values


Get distinct values for a specific label key across all model security scans. Use to discover what values exist for a given label.

Base Command

prisma-airs-model-security-labels-values

Input

Argument Name Description Required
key The label key to get values for. Required
limit The maximum number of label values to return. Default is 50. Optional
offset The offset for pagination. Default is 0. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityLabelValues.key String The label key.
PrismaAIRs.ModelSecurityLabelValues.values Unknown The list of distinct label values.
PrismaAIRs.ModelSecurityLabelValues.total_items Number The total number of label values available.
PrismaAIRs.ModelSecurityLabelValues.limit Number The limit used for pagination.
PrismaAIRs.ModelSecurityLabelValues.offset Number The offset used for pagination.

prisma-airs-model-security-labels-add


Add labels to a model security scan for organization and filtering. Labels are key-value pairs.

Base Command

prisma-airs-model-security-labels-add

Input

Argument Name Description Required
scan_uuid The scan UUID to add labels to. Required
labels The labels to add as JSON array (e.g., ‘[{“key”:”env”,”value”:”prod”}]’). Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityLabelsAdd.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityLabelsAdd.labels_added Unknown The labels that were added.
PrismaAIRs.ModelSecurityLabelsAdd.success Boolean Whether the operation succeeded.

prisma-airs-model-security-labels-set


Set labels on a model security scan, replacing all existing labels. Use this to completely update scan labels.

Base Command

prisma-airs-model-security-labels-set

Input

Argument Name Description Required
scan_uuid The scan UUID to set labels on. Required
labels The labels to set as JSON array (e.g., ‘[{“key”:”env”,”value”:”staging”}]’). Replaces all existing labels. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityLabelsSet.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityLabelsSet.labels_set Unknown The labels that were set.
PrismaAIRs.ModelSecurityLabelsSet.success Boolean Whether the operation succeeded.

prisma-airs-model-security-labels-delete


Delete labels from a model security scan by key. Removes specific labels while preserving others.

Base Command

prisma-airs-model-security-labels-delete

Input

Argument Name Description Required
scan_uuid The scan UUID to delete labels from. Required
keys A comma-separated list of label keys to delete (e.g., “env,team”). Alternatively, a JSON array. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityLabelsDelete.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityLabelsDelete.keys_deleted Unknown The label keys that were deleted.
PrismaAIRs.ModelSecurityLabelsDelete.success Boolean Whether the operation succeeded.

prisma-airs-model-security-scans-evaluation


Get a single rule evaluation by UUID. Retrieves detailed information about how a specific rule was evaluated during a scan.

Base Command

prisma-airs-model-security-scans-evaluation

Input

Argument Name Description Required
uuid The evaluation UUID to retrieve. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityEvaluation.uuid String The evaluation UUID.
PrismaAIRs.ModelSecurityEvaluation.scan_uuid String The scan UUID this evaluation belongs to.
PrismaAIRs.ModelSecurityEvaluation.rule_instance_uuid String The rule instance UUID.
PrismaAIRs.ModelSecurityEvaluation.rule_name String The security rule name.
PrismaAIRs.ModelSecurityEvaluation.rule_description String The security rule description.
PrismaAIRs.ModelSecurityEvaluation.result String The evaluation result (PASSED/FAILED/ERROR).
PrismaAIRs.ModelSecurityEvaluation.violation_count Number The number of violations found.
PrismaAIRs.ModelSecurityEvaluation.rule_instance_state String The rule instance state (BLOCKING/ALLOWING/DISABLED).
PrismaAIRs.ModelSecurityEvaluation.created_at Date The evaluation creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityEvaluation.updated_at Date The evaluation last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityEvaluation.tsg_id String The tenant Service Group ID.

prisma-airs-model-security-scans-violation


Get a single violation by UUID. Retrieves detailed information about a specific security rule violation found during a scan.

Base Command

prisma-airs-model-security-scans-violation

Input

Argument Name Description Required
uuid The violation UUID to retrieve. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityViolationDetail.uuid String The violation UUID.
PrismaAIRs.ModelSecurityViolationDetail.rule_name String The security rule name that failed.
PrismaAIRs.ModelSecurityViolationDetail.rule_description String The security rule description.
PrismaAIRs.ModelSecurityViolationDetail.description String The violation description.
PrismaAIRs.ModelSecurityViolationDetail.rule_instance_state String The rule instance state (BLOCKING/ALLOWING).
PrismaAIRs.ModelSecurityViolationDetail.file String The file path where violation was found.
PrismaAIRs.ModelSecurityViolationDetail.threat String The threat type.
PrismaAIRs.ModelSecurityViolationDetail.threat_description String The threat description.
PrismaAIRs.ModelSecurityViolationDetail.module String The module where threat was found.
PrismaAIRs.ModelSecurityViolationDetail.operator String The operator involved in violation.
PrismaAIRs.ModelSecurityViolationDetail.hash String The hash of the violating file.
PrismaAIRs.ModelSecurityViolationDetail.rule_instance_uuid String The rule instance UUID.
PrismaAIRs.ModelSecurityViolationDetail.created_at Date The violation creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityViolationDetail.updated_at Date The violation last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityViolationDetail.tsg_id String The tenant Service Group ID.

prisma-airs-model-security-scans-files


Get files for a scan. Lists all files that were scanned within a model, showing file structure and scan results.

Base Command

prisma-airs-model-security-scans-files

Input

Argument Name Description Required
scan_uuid The scan UUID to retrieve files for. Required
limit The maximum number of files to return. Default is 50. Optional
offset The offset for pagination. Default is 0. Optional
sort_field The sort by field (path, type). Optional
sort_dir The sort direction (asc, desc). Optional
type The file type to filter results by (FILE, DIRECTORY). Optional
result The scan result to filter results by (SUCCESS, FAILURE). Optional
query_path The path prefix to filter files by. Default is /. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityFiles.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityFiles.files.uuid String The file entry UUID.
PrismaAIRs.ModelSecurityFiles.files.path String The file path within model.
PrismaAIRs.ModelSecurityFiles.files.parent_path String The parent directory path.
PrismaAIRs.ModelSecurityFiles.files.type String The file type (FILE, DIRECTORY).
PrismaAIRs.ModelSecurityFiles.files.result String The scan result (SUCCESS, FAILURE).
PrismaAIRs.ModelSecurityFiles.files.model_version_uuid String The model version UUID.
PrismaAIRs.ModelSecurityFiles.files.blob_id String The blob storage identifier.
PrismaAIRs.ModelSecurityFiles.files.formats Unknown The model formats detected.
PrismaAIRs.ModelSecurityFiles.files.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityFiles.files.created_at Date The file entry creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityFiles.files.updated_at Date The file entry last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityFiles.files.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityFiles.total_items Number The total number of files available.
PrismaAIRs.ModelSecurityFiles.limit Number The limit used for pagination.
PrismaAIRs.ModelSecurityFiles.offset Number The offset used for pagination.

prisma-airs-model-security-scans-evaluations


Get rule evaluations for a scan. Lists all rule evaluations showing which security rules passed, failed, or had errors.

Base Command

prisma-airs-model-security-scans-evaluations

Input

Argument Name Description Required
scan_uuid The scan UUID to retrieve evaluations for. Required
limit The maximum number of evaluations to return. Default is 50. Optional
offset The offset for pagination. Default is 0. Optional
sort_field The sort by field (created_at, updated_at). Optional
sort_order The sort order (asc, desc). Optional
result The evaluation result to filter results by (PASSED, FAILED, ERROR). Optional
rule_instance_uuid The rule instance UUID to filter results by. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityEvaluations.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityEvaluations.evaluations.uuid String The rule evaluation UUID.
PrismaAIRs.ModelSecurityEvaluations.evaluations.scan_uuid String The scan UUID.
PrismaAIRs.ModelSecurityEvaluations.evaluations.rule_name String The security rule name (e.g., Pickle Scan, Malware Scan).
PrismaAIRs.ModelSecurityEvaluations.evaluations.result String The evaluation result (PASSED, FAILED, ERROR).
PrismaAIRs.ModelSecurityEvaluations.evaluations.violation_count Number The number of violations detected by this rule.
PrismaAIRs.ModelSecurityEvaluations.evaluations.rule_instance_state String The rule instance state (BLOCKING, MONITORING).
PrismaAIRs.ModelSecurityEvaluations.evaluations.rule_instance_uuid String The rule instance UUID that performed the evaluation.
PrismaAIRs.ModelSecurityEvaluations.evaluations.rule_description String The rule description.
PrismaAIRs.ModelSecurityEvaluations.evaluations.created_at Date The evaluation creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityEvaluations.evaluations.updated_at Date The evaluation last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityEvaluations.evaluations.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityEvaluations.total_items Number The total number of evaluations available.
PrismaAIRs.ModelSecurityEvaluations.limit Number The limit used for pagination.
PrismaAIRs.ModelSecurityEvaluations.offset Number The offset used for pagination.

prisma-airs-model-security-models-list


List Model Security model catalog entries (aggregate over their scanned versions). Read-only.

Base Command

prisma-airs-model-security-models-list

Input

Argument Name Description Required
limit The maximum number of models to return. Default is 50. Optional
skip The number of records to skip from the start (pagination offset). Optional
search_query The search query (matches model UUID or name). Optional
sort_field The field to sort by. Possible values are: created_at, updated_at. Optional
sort_order The sort order. Possible values are: asc, desc. Optional
latest_version_outcomes A comma-separated list of latest-version evaluation outcomes to filter by (e.g., PASSED,FAILED). Optional
latest_version_formats A comma-separated list of latest-version model formats to filter by. Optional
latest_version_source_types A comma-separated list of latest-version source types to filter by (e.g., HUGGING_FACE,S3). Optional
start_time The earliest model creation datetime (ISO 8601); only models created on or after this time are returned. Optional
end_time The latest model creation datetime (ISO 8601); only models created on or before this time are returned. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityModel.uuid String The model UUID.
PrismaAIRs.ModelSecurityModel.name String The model name.
PrismaAIRs.ModelSecurityModel.latest_version_uuid String The UUID of the model’s latest version.
PrismaAIRs.ModelSecurityModel.latest_version_revision String The revision label of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_outcome String The evaluation outcome of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_formats Unknown The model formats of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_source_types Unknown The source types of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_scan_time Date The scan time of the latest version, in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityModel.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityModel.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).

prisma-airs-model-security-models-get


Get a single Model Security model by UUID. Read-only.

Base Command

prisma-airs-model-security-models-get

Input

Argument Name Description Required
uuid The model UUID. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityModel.uuid String The model UUID.
PrismaAIRs.ModelSecurityModel.name String The model name.
PrismaAIRs.ModelSecurityModel.latest_version_uuid String The UUID of the model’s latest version.
PrismaAIRs.ModelSecurityModel.latest_version_revision String The revision label of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_fingerprint String The fingerprint of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_hf_commit_sha String The Hugging Face commit SHA of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_outcome String The evaluation outcome of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_formats Unknown The model formats of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_source_types Unknown The source types of the latest version.
PrismaAIRs.ModelSecurityModel.latest_version_scan_time Date The scan time of the latest version, in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityModel.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityModel.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).

prisma-airs-model-security-models-versions


List the versions (revisions) of a Model Security model. Read-only.

Base Command

prisma-airs-model-security-models-versions

Input

Argument Name Description Required
model_uuid The model UUID whose versions to list. Required
limit The maximum number of versions to return. Default is 50. Optional
skip The number of records to skip from the start (pagination offset). Optional
sort_order The sort order. Possible values are: asc, desc. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityModelVersion.uuid String The model version UUID.
PrismaAIRs.ModelSecurityModelVersion.model_uuid String The parent model UUID.
PrismaAIRs.ModelSecurityModelVersion.revision String The revision label.
PrismaAIRs.ModelSecurityModelVersion.file_count Number The number of files in the version.
PrismaAIRs.ModelSecurityModelVersion.license String The model license.
PrismaAIRs.ModelSecurityModelVersion.model_formats Unknown The model formats.
PrismaAIRs.ModelSecurityModelVersion.source_types Unknown The source types.
PrismaAIRs.ModelSecurityModelVersion.last_eval_outcome String The latest evaluation outcome.
PrismaAIRs.ModelSecurityModelVersion.latest_scan_time Date The latest scan time in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityModelVersion.hf_model_name String The Hugging Face model name.
PrismaAIRs.ModelSecurityModelVersion.hf_organization String The Hugging Face organization.

prisma-airs-model-security-models-version-get


Get a single Model Security model version by UUID. Read-only.

Base Command

prisma-airs-model-security-models-version-get

Input

Argument Name Description Required
uuid The model version UUID. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityModelVersion.uuid String The model version UUID.
PrismaAIRs.ModelSecurityModelVersion.model_uuid String The parent model UUID.
PrismaAIRs.ModelSecurityModelVersion.revision String The revision label.
PrismaAIRs.ModelSecurityModelVersion.fingerprint String The version fingerprint.
PrismaAIRs.ModelSecurityModelVersion.file_count Number The number of files in the version.
PrismaAIRs.ModelSecurityModelVersion.license String The model license.
PrismaAIRs.ModelSecurityModelVersion.model_formats Unknown The model formats.
PrismaAIRs.ModelSecurityModelVersion.source_types Unknown The source types.
PrismaAIRs.ModelSecurityModelVersion.last_eval_outcome String The latest evaluation outcome.
PrismaAIRs.ModelSecurityModelVersion.latest_scan_time Date The latest scan time in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityModelVersion.hf_model_name String The Hugging Face model name.
PrismaAIRs.ModelSecurityModelVersion.hf_organization String The Hugging Face organization.
PrismaAIRs.ModelSecurityModelVersion.hf_commit_sha String The Hugging Face commit SHA.
PrismaAIRs.ModelSecurityModelVersion.hf_commit_title String The Hugging Face commit title.
PrismaAIRs.ModelSecurityModelVersion.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityModelVersion.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).

prisma-airs-model-security-models-files


List the files of a Model Security model version. Read-only.

Base Command

prisma-airs-model-security-models-files

Input

Argument Name Description Required
model_version_uuid The model version UUID whose files to list. Required
limit The maximum number of files to return. Default is 50. Optional
skip The number of records to skip from the start (pagination offset). Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityModelFile.uuid String The file UUID.
PrismaAIRs.ModelSecurityModelFile.path String The file path within the model tree.
PrismaAIRs.ModelSecurityModelFile.parent_path String The parent directory path.
PrismaAIRs.ModelSecurityModelFile.type String The entry type (e.g., FILE).
PrismaAIRs.ModelSecurityModelFile.result String The scan result for the file.
PrismaAIRs.ModelSecurityModelFile.formats Unknown The detected file formats.
PrismaAIRs.ModelSecurityModelFile.model_version_uuid String The parent model version UUID.
PrismaAIRs.ModelSecurityModelFile.scan_uuid String The associated scan UUID.

prisma-airs-model-security-groups-list


List all model security groups.

Base Command

prisma-airs-model-security-groups-list

Input

Argument Name Description Required
limit The maximum number of security groups to return. Default is 50. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityGroup.uuid String The security group UUID.
PrismaAIRs.ModelSecurityGroup.name String The security group name.
PrismaAIRs.ModelSecurityGroup.description String The security group description.
PrismaAIRs.ModelSecurityGroup.source_type String The source type (HUGGING_FACE, LOCAL, S3, GCS, AZURE).
PrismaAIRs.ModelSecurityGroup.state String The group state (ACTIVE, PENDING).
PrismaAIRs.ModelSecurityGroup.is_tombstone Boolean Whether the group is marked for deletion.
PrismaAIRs.ModelSecurityGroup.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroup.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroup.tsg_id String The tenant Service Group ID.

prisma-airs-model-security-groups-get


Get model security group details by UUID.

Base Command

prisma-airs-model-security-groups-get

Input

Argument Name Description Required
uuid The security group UUID. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityGroupGet.uuid String The security group UUID.
PrismaAIRs.ModelSecurityGroupGet.name String The security group name.
PrismaAIRs.ModelSecurityGroupGet.description String The security group description.
PrismaAIRs.ModelSecurityGroupGet.source_type String The source type (HUGGING_FACE, LOCAL, S3, GCS, AZURE).
PrismaAIRs.ModelSecurityGroupGet.state String The group state (ACTIVE, PENDING).
PrismaAIRs.ModelSecurityGroupGet.is_tombstone Boolean Whether the group is marked for deletion.
PrismaAIRs.ModelSecurityGroupGet.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroupGet.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroupGet.tsg_id String The tenant Service Group ID.

prisma-airs-model-security-groups-create


Create a new model security group for scanning models from a specific source type.

Base Command

prisma-airs-model-security-groups-create

Input

Argument Name Description Required
name The security group name. Required
source_type The model source type. Possible values are: HUGGING_FACE, LOCAL, S3, GCS, AZURE. Required
description The security group description. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityGroupAdd.uuid String The UUID of the created security group.
PrismaAIRs.ModelSecurityGroupAdd.name String The name of the created security group.
PrismaAIRs.ModelSecurityGroupAdd.description String The description of the created security group.
PrismaAIRs.ModelSecurityGroupAdd.source_type String The source type (HUGGING_FACE, LOCAL, S3, GCS, AZURE).
PrismaAIRs.ModelSecurityGroupAdd.state String The group state (PENDING initially, becomes ACTIVE after configuration).
PrismaAIRs.ModelSecurityGroupAdd.is_tombstone Boolean Whether the group is marked for deletion.
PrismaAIRs.ModelSecurityGroupAdd.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroupAdd.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroupAdd.tsg_id String The tenant Service Group ID.

prisma-airs-model-security-groups-delete


Delete a security group. Removes a security group that is no longer needed.

Base Command

prisma-airs-model-security-groups-delete

Input

Argument Name Description Required
uuid The security group UUID to delete. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityGroupDelete.uuid String The UUID of deleted security group.
PrismaAIRs.ModelSecurityGroupDelete.deleted Boolean Whether the deletion succeeded.

prisma-airs-model-security-groups-update


Update an existing security group. Updates the name and/or description of a security group.

Base Command

prisma-airs-model-security-groups-update

Input

Argument Name Description Required
uuid The security group UUID to update. Required
name The new name for the security group. Optional
description The new description for the security group. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityGroupUpdate.uuid String The UUID of the updated security group.
PrismaAIRs.ModelSecurityGroupUpdate.name String The updated security group name.
PrismaAIRs.ModelSecurityGroupUpdate.description String The updated security group description.
PrismaAIRs.ModelSecurityGroupUpdate.source_type String The model source type (HUGGING_FACE, LOCAL, S3, GCS, AZURE).
PrismaAIRs.ModelSecurityGroupUpdate.state String The group state after update.
PrismaAIRs.ModelSecurityGroupUpdate.is_tombstone Boolean Whether the group is marked for deletion.
PrismaAIRs.ModelSecurityGroupUpdate.created_at Date The creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroupUpdate.updated_at Date The last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityGroupUpdate.tsg_id String The tenant Service Group ID.

prisma-airs-model-security-rules-list


List all model security rules.

Base Command

prisma-airs-model-security-rules-list

Input

Argument Name Description Required
limit The maximum number of security rules to return. Default is 50. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityRule.uuid String The security rule UUID.
PrismaAIRs.ModelSecurityRule.name String The security rule name.
PrismaAIRs.ModelSecurityRule.description String The security rule description.
PrismaAIRs.ModelSecurityRule.rule_type String The rule type (ARTIFACT, METADATA).
PrismaAIRs.ModelSecurityRule.compatible_sources Unknown The compatible source types for this rule.
PrismaAIRs.ModelSecurityRule.default_state String The default state (DISABLED, ALLOWING, BLOCKING).

prisma-airs-model-security-rules-get


Get model security rule details by UUID. Returns full rule definition including description, remediation steps, and editable fields.

Base Command

prisma-airs-model-security-rules-get

Input

Argument Name Description Required
uuid The rule UUID to retrieve. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityRuleGet.uuid String The rule UUID.
PrismaAIRs.ModelSecurityRuleGet.name String The rule name.
PrismaAIRs.ModelSecurityRuleGet.description String The rule description.
PrismaAIRs.ModelSecurityRuleGet.rule_type String The rule type (ARTIFACT, METADATA, etc).
PrismaAIRs.ModelSecurityRuleGet.compatible_sources Unknown The compatible source types for this rule.
PrismaAIRs.ModelSecurityRuleGet.default_state String The default state (DISABLED, ALLOWING, BLOCKING).
PrismaAIRs.ModelSecurityRuleGet.remediation_description String The remediation description.
PrismaAIRs.ModelSecurityRuleGet.remediation_steps Unknown The remediation steps.
PrismaAIRs.ModelSecurityRuleGet.remediation_url String The remediation reference URL.
PrismaAIRs.ModelSecurityRuleGet.editable_fields Unknown The editable fields configuration.
PrismaAIRs.ModelSecurityRuleGet.constant_values Unknown The constant values for this rule.
PrismaAIRs.ModelSecurityRuleGet.default_values Unknown The default values for editable fields.

prisma-airs-model-security-rule-instances-list


List rule instances for a security group. Rule instances are rules that have been applied to a security group with specific state (DISABLED/ALLOWING/BLOCKING) and optional field customizations.

Base Command

prisma-airs-model-security-rule-instances-list

Input

Argument Name Description Required
security_group_uuid The security group UUID to list rule instances for. Required
limit The maximum number of rule instances to return. Default is 50. Optional
offset The offset for pagination. Default is 0. Optional
security_rule_uuid The security rule UUID to filter results by. Optional
state The rule state to filter results by. Possible values are: DISABLED, ALLOWING, BLOCKING. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityRuleInstance.security_group_uuid String The security group UUID.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.uuid String The rule instance UUID.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.security_group_uuid String The security group UUID this instance belongs to.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.security_rule_uuid String The security rule UUID.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.state String The rule instance state (DISABLED/ALLOWING/BLOCKING).
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.rule_name String The security rule name.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.rule_type String The security rule type.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.rule_description String The security rule description.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.created_at Date The rule instance creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.updated_at Date The rule instance last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityRuleInstance.rule_instances.field_values Unknown The custom field values for this rule instance.
PrismaAIRs.ModelSecurityRuleInstance.total_items Number The total number of rule instances available.
PrismaAIRs.ModelSecurityRuleInstance.limit Number The limit used for pagination.
PrismaAIRs.ModelSecurityRuleInstance.offset Number The offset used for pagination.

prisma-airs-model-security-rule-instances-update


Update a rule instance within a security group. Use this to enable/disable rules or customize rule field values.

Base Command

prisma-airs-model-security-rule-instances-update

Input

Argument Name Description Required
security_group_uuid The security group UUID. Required
rule_instance_uuid The rule instance UUID to update. Required
state The new state for the rule instance. Possible values are: DISABLED, ALLOWING, BLOCKING. Optional
field_values The custom field values as JSON string. Optional

Context Output

Path Type Description
PrismaAIRs.ModelSecurityRuleInstanceUpdate.uuid String The rule instance UUID.
PrismaAIRs.ModelSecurityRuleInstanceUpdate.security_group_uuid String The security group UUID this instance belongs to.
PrismaAIRs.ModelSecurityRuleInstanceUpdate.security_rule_uuid String The security rule UUID.
PrismaAIRs.ModelSecurityRuleInstanceUpdate.state String The rule instance state (DISABLED/ALLOWING/BLOCKING).
PrismaAIRs.ModelSecurityRuleInstanceUpdate.rule_name String The security rule name.
PrismaAIRs.ModelSecurityRuleInstanceUpdate.rule_type String The security rule type.
PrismaAIRs.ModelSecurityRuleInstanceUpdate.rule_description String The security rule description.
PrismaAIRs.ModelSecurityRuleInstanceUpdate.created_at Date The rule instance creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityRuleInstanceUpdate.updated_at Date The rule instance last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityRuleInstanceUpdate.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityRuleInstanceUpdate.field_values Unknown The custom field values for this rule instance.

prisma-airs-model-security-rule-instances-get


Get a single rule instance within a security group. Retrieves detailed configuration of a specific rule instance.

Base Command

prisma-airs-model-security-rule-instances-get

Input

Argument Name Description Required
security_group_uuid The security group UUID. Required
rule_instance_uuid The rule instance UUID to retrieve. Required

Context Output

Path Type Description
PrismaAIRs.ModelSecurityRuleInstanceGet.uuid String The rule instance UUID.
PrismaAIRs.ModelSecurityRuleInstanceGet.security_group_uuid String The security group UUID this instance belongs to.
PrismaAIRs.ModelSecurityRuleInstanceGet.security_rule_uuid String The security rule UUID.
PrismaAIRs.ModelSecurityRuleInstanceGet.state String The rule instance state (DISABLED/ALLOWING/BLOCKING).
PrismaAIRs.ModelSecurityRuleInstanceGet.rule_name String The security rule name.
PrismaAIRs.ModelSecurityRuleInstanceGet.rule_type String The security rule type.
PrismaAIRs.ModelSecurityRuleInstanceGet.rule_description String The security rule description.
PrismaAIRs.ModelSecurityRuleInstanceGet.created_at Date The rule instance creation timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityRuleInstanceGet.updated_at Date The rule instance last update timestamp in ISO 8601 format (e.g., 2024-01-15T12:34:56Z).
PrismaAIRs.ModelSecurityRuleInstanceGet.tsg_id String The tenant Service Group ID.
PrismaAIRs.ModelSecurityRuleInstanceGet.field_values Unknown The custom field values for this rule instance.

Configuration parameters

  • url — Server URL (required)
  • credentials — API Client ID (required)
  • tsg_id — Tenant Services Group ID (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (28)

  • prisma-airs-model-security-groups-create

    Create a new model security group for scanning models from a specific source type.

  • prisma-airs-model-security-groups-delete

    Delete a security group. Removes a security group that is no longer needed.

  • prisma-airs-model-security-groups-get

    Get model security group details by UUID.

  • prisma-airs-model-security-groups-list

    List all model security groups.

  • prisma-airs-model-security-groups-update

    Update an existing security group. Updates the name and/or description of a security group.

  • prisma-airs-model-security-labels-add

    Add labels to a model security scan for organization and filtering. Labels are key-value pairs.

  • prisma-airs-model-security-labels-delete

    Delete labels from a model security scan by key. Removes specific labels while preserving others.

  • prisma-airs-model-security-labels-keys

    Get distinct label keys across all model security scans. Use for discovering available labels for filtering/organization.

  • prisma-airs-model-security-labels-set

    Set labels on a model security scan, replacing all existing labels. Use this to completely update scan labels.

  • prisma-airs-model-security-labels-values

    Get distinct values for a specific label key across all model security scans. Use to discover what values exist for a given label.

  • prisma-airs-model-security-models-files

    List the files of a Model Security model version. Read-only.

  • prisma-airs-model-security-models-get

    Get a single Model Security model by UUID. Read-only.

  • prisma-airs-model-security-models-list

    List Model Security model catalog entries (aggregate over their scanned versions). Read-only.

  • prisma-airs-model-security-models-version-get

    Get a single Model Security model version by UUID. Read-only.

  • prisma-airs-model-security-models-versions

    List the versions (revisions) of a Model Security model. Read-only.

  • prisma-airs-model-security-rule-instances-get

    Get a single rule instance within a security group. Retrieves detailed configuration of a specific rule instance.

  • prisma-airs-model-security-rule-instances-list

    List rule instances for a security group. Rule instances are rules that have been applied to a security group with specific state (DISABLED/ALLOWING/BLOCKING) and optional field customizations.

  • prisma-airs-model-security-rule-instances-update

    Update a rule instance within a security group. Use this to enable/disable rules or customize rule field values.

  • prisma-airs-model-security-rules-get

    Get model security rule details by UUID. Returns full rule definition including description, remediation steps, and editable fields.

  • prisma-airs-model-security-rules-list

    List all model security rules.

  • prisma-airs-model-security-scans-create

    Create a new model security scan to check a model for supply chain security issues. Scan is asynchronous - use scans-get to poll for completion.

  • prisma-airs-model-security-scans-evaluation

    Get a single rule evaluation by UUID. Retrieves detailed information about how a specific rule was evaluated during a scan.

  • prisma-airs-model-security-scans-evaluations

    Get rule evaluations for a scan. Lists all rule evaluations showing which security rules passed, failed, or had errors.

  • prisma-airs-model-security-scans-files

    Get files for a scan. Lists all files that were scanned within a model, showing file structure and scan results.

  • prisma-airs-model-security-scans-get

    Get model security scan status and results. Use this to poll scan completion after scans-create.

  • prisma-airs-model-security-scans-list

    List all model security scans.

  • prisma-airs-model-security-scans-violation

    Get a single violation by UUID. Retrieves detailed information about a specific security rule violation found during a scan.

  • prisma-airs-model-security-scans-violations

    Get rule violations for a model security scan. Shows detailed information about which security rules failed and why.

"""Unit tests for the Prisma AIRs AI Model Security integration."""

import json
from unittest.mock import Mock, patch

import pytest
from PrismaAIRsModelSecurity import (
    Client,
    model_security_groups_create_command,
    model_security_groups_delete_command,
    model_security_groups_get_command,
    model_security_groups_list_command,
    model_security_groups_update_command,
    model_security_labels_add_command,
    model_security_labels_delete_command,
    model_security_labels_keys_command,
    model_security_labels_set_command,
    model_security_labels_values_command,
    model_security_models_files_command,
    model_security_models_get_command,
    model_security_models_list_command,
    model_security_models_version_get_command,
    model_security_models_versions_command,
    model_security_rule_instances_get_command,
    model_security_rule_instances_list_command,
    model_security_rule_instances_update_command,
    model_security_rules_get_command,
    model_security_rules_list_command,
    model_security_scans_create_command,
    model_security_scans_evaluation_command,
    model_security_scans_evaluations_command,
    model_security_scans_files_command,
    model_security_scans_get_command,
    model_security_scans_list_command,
    model_security_scans_violation_command,
    model_security_scans_violations_command,
)


@pytest.fixture
def mock_client() -> Client:
    """Create a mock Prisma AIRs client scoped to the Model Security plane."""
    return Client(
        base_url="https://api.sase.paloaltonetworks.com",
        client_id="test_client_id",
        client_secret="test_client_secret",
        tsg_id="1234567890",
        verify=False,
        proxy=False,
        headers={},
    )


class TestModelSecurity:
    """Test cases for Prisma AIRs AI Model Security commands."""

    @patch.object(Client, "http_request")
    def test_model_security_scans_list_command(self, mock_http: Mock, mock_client: Client) -> None:
        """Test model security scans list command.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "scans": [
                {
                    "uuid": "550e8400-e29b-41d4-a716-446655440000",
                    "model_uri": "hf://org/model-name",
                    "eval_outcome": "ALLOWED",
                    "source_type": "HUGGING_FACE",
                    "security_group_uuid": "group-uuid-123",
                    "security_group_name": "hf-strict",
                    "scan_origin": "CLI",
                    "created_at": "2024-01-01T00:00:00Z",
                    "updated_at": "2024-01-01T00:10:00Z",
                    "created_by": "user@example.com",
                }
            ],
            "pagination": {"total_items": 1},
        }

        args = {"limit": "10"}
        result = model_security_scans_list_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityScan"
        assert len(result.outputs) == 1
        assert result.outputs[0]["uuid"] == "550e8400-e29b-41d4-a716-446655440000"
        assert result.outputs[0]["model_uri"] == "hf://org/model-name"
        assert result.outputs[0]["eval_outcome"] == "ALLOWED"

    @patch.object(Client, "http_request")
    def test_model_security_groups_list_command(self, mock_http: Mock, mock_client: Client) -> None:
        """Test model security groups list command.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "security_groups": [
                {
                    "uuid": "group-uuid-123",
                    "name": "hf-strict",
                    "description": "Block unsafe Hugging Face models",
                    "source_type": "HUGGING_FACE",
                    "state": "ACTIVE",
                    "is_tombstone": False,
                    "created_at": "2024-01-01T00:00:00Z",
                    "updated_at": "2024-01-15T00:00:00Z",
                    "tsg_id": "1234567890",
                }
            ],
            "pagination": {"total_items": 1},
        }

        args = {"limit": "10"}
        result = model_security_groups_list_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityGroup"
        assert len(result.outputs) == 1
        assert result.outputs[0]["uuid"] == "group-uuid-123"
        assert result.outputs[0]["name"] == "hf-strict"
        assert result.outputs[0]["source_type"] == "HUGGING_FACE"

    @patch.object(Client, "http_request")
    def test_model_security_models_list_command(self, mock_http: Mock, mock_client: Client) -> None:
        """models-list parses the catalog, forwards filters, and hits the data plane.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "models": [
                {
                    "uuid": "550e8400-e29b-41d4-a716-446655440000",
                    "name": "org/llama",
                    "latest_version_uuid": "660e8400-e29b-41d4-a716-446655440000",
                    "latest_version_revision": "main",
                    "latest_version_outcome": "PASSED",
                    "latest_version_formats": ["safetensors"],
                    "latest_version_source_types": ["HUGGING_FACE"],
                    "latest_version_scan_time": "2024-01-01T00:00:00Z",
                    "created_at": "2024-01-01T00:00:00Z",
                    "updated_at": "2024-01-02T00:00:00Z",
                }
            ],
            "pagination": {"total_items": 1},
        }

        args = {"limit": "10", "search_query": "llama", "latest_version_outcomes": "PASSED,FAILED"}
        result = model_security_models_list_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityModel"
        assert len(result.outputs) == 1
        assert result.outputs[0]["uuid"] == "550e8400-e29b-41d4-a716-446655440000"
        assert result.outputs[0]["name"] == "org/llama"
        assert result.outputs[0]["latest_version_outcome"] == "PASSED"

        _, kwargs = mock_http.call_args
        assert kwargs["method"] == "GET"
        assert kwargs["url_suffix"] == "/v1/models"
        assert kwargs["use_model_sec_data"] is True
        assert kwargs["params"]["search_query"] == "llama"
        assert kwargs["params"]["latest_version_outcomes"] == ["PASSED", "FAILED"]

    @patch.object(Client, "http_request")
    def test_model_security_models_get_command(self, mock_http: Mock, mock_client: Client) -> None:
        """models-get returns a single model keyed by uuid on the data plane.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "uuid": "550e8400-e29b-41d4-a716-446655440000",
            "name": "org/model",
            "latest_version_uuid": "660e8400-e29b-41d4-a716-446655440000",
            "latest_version_outcome": "PASSED",
        }

        result = model_security_models_get_command(mock_client, {"uuid": "550e8400-e29b-41d4-a716-446655440000"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityModel"
        assert result.outputs["uuid"] == "550e8400-e29b-41d4-a716-446655440000"
        assert result.outputs["name"] == "org/model"

        _, kwargs = mock_http.call_args
        assert kwargs["method"] == "GET"
        assert kwargs["url_suffix"] == "/v1/models/550e8400-e29b-41d4-a716-446655440000"
        assert kwargs["use_model_sec_data"] is True

    @patch.object(Client, "http_request")
    def test_model_security_models_versions_command(self, mock_http: Mock, mock_client: Client) -> None:
        """models-versions lists a model's versions on the data plane.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "model_versions": [
                {
                    "uuid": "660e8400-e29b-41d4-a716-446655440000",
                    "model_uuid": "550e8400-e29b-41d4-a716-446655440000",
                    "revision": "main",
                    "file_count": 12,
                    "last_eval_outcome": "PASSED",
                }
            ],
            "pagination": {"total_items": 1},
        }

        args = {"model_uuid": "550e8400-e29b-41d4-a716-446655440000", "sort_order": "desc"}
        result = model_security_models_versions_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityModelVersion"
        assert len(result.outputs) == 1
        assert result.outputs[0]["uuid"] == "660e8400-e29b-41d4-a716-446655440000"
        assert result.outputs[0]["file_count"] == 12

        _, kwargs = mock_http.call_args
        assert kwargs["url_suffix"] == "/v1/models/550e8400-e29b-41d4-a716-446655440000/model-versions"
        assert kwargs["use_model_sec_data"] is True
        assert kwargs["params"]["sort_order"] == "desc"

    @patch.object(Client, "http_request")
    def test_model_security_models_version_get_command(self, mock_http: Mock, mock_client: Client) -> None:
        """models-version-get returns a single version keyed by uuid on the data plane.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "uuid": "660e8400-e29b-41d4-a716-446655440000",
            "model_uuid": "550e8400-e29b-41d4-a716-446655440000",
            "revision": "main",
            "last_eval_outcome": "PASSED",
        }

        result = model_security_models_version_get_command(mock_client, {"uuid": "660e8400-e29b-41d4-a716-446655440000"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityModelVersion"
        assert result.outputs["uuid"] == "660e8400-e29b-41d4-a716-446655440000"
        assert result.outputs["revision"] == "main"

        _, kwargs = mock_http.call_args
        assert kwargs["url_suffix"] == "/v1/model-versions/660e8400-e29b-41d4-a716-446655440000"
        assert kwargs["use_model_sec_data"] is True

    @patch.object(Client, "http_request")
    def test_model_security_models_files_command(self, mock_http: Mock, mock_client: Client) -> None:
        """models-files lists a version's files on the data plane.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "files": [
                {
                    "uuid": "770e8400-e29b-41d4-a716-446655440000",
                    "path": "/model.safetensors",
                    "type": "FILE",
                    "result": "SUCCESS",
                    "formats": ["safetensors"],
                    "model_version_uuid": "660e8400-e29b-41d4-a716-446655440000",
                }
            ],
            "pagination": {"total_items": 1},
        }

        args = {"model_version_uuid": "660e8400-e29b-41d4-a716-446655440000", "limit": "50"}
        result = model_security_models_files_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityModelFile"
        assert len(result.outputs) == 1
        assert result.outputs[0]["path"] == "/model.safetensors"
        assert result.outputs[0]["result"] == "SUCCESS"

        _, kwargs = mock_http.call_args
        assert kwargs["url_suffix"] == "/v1/model-versions/660e8400-e29b-41d4-a716-446655440000/files"
        assert kwargs["use_model_sec_data"] is True

    @patch.object(Client, "http_request")
    def test_model_security_rules_list_command(self, mock_http: Mock, mock_client: Client) -> None:
        """Test model security rules list command.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "rules": [
                {
                    "uuid": "rule-uuid-123",
                    "name": "Pickle Scan",
                    "description": "Detect unsafe pickle operations",
                    "rule_type": "ARTIFACT",
                    "compatible_sources": ["HUGGING_FACE", "LOCAL"],
                    "default_state": "BLOCKING",
                }
            ],
            "pagination": {"total_items": 1},
        }

        args = {"limit": "10"}
        result = model_security_rules_list_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityRule"
        assert len(result.outputs) == 1
        assert result.outputs[0]["uuid"] == "rule-uuid-123"
        assert result.outputs[0]["name"] == "Pickle Scan"
        assert result.outputs[0]["rule_type"] == "ARTIFACT"

    @patch.object(Client, "http_request")
    def test_model_security_rules_get_full_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-rules-get parses remediation + editable fields into RuleGet context.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "uuid": "r-1",
            "name": "PII Rule",
            "rule_type": "PII",
            "compatible_sources": ["S3", "GCS"],
            "default_state": "BLOCKING",
            "remediation": {"description": "fix it", "steps": ["a", "b"], "url": "https://example.com"},
            "editable_fields": ["state"],
            "constant_values": {"x": 1},
            "default_values": {"y": 2},
        }

        result = model_security_rules_get_command(mock_client, {"uuid": "r-1"})

        _, kwargs = mock_http.call_args
        assert kwargs["url_suffix"] == "/v1/security-rules/r-1"
        assert kwargs["use_model_sec_mgmt"] is True
        assert result.outputs["uuid"] == "r-1"
        assert result.outputs["remediation_steps"] == ["a", "b"]
        assert result.outputs["editable_fields"] == ["state"]

    @patch.object(Client, "http_request")
    def test_model_security_scans_get_full(self, mock_http: Mock, mock_client: Client) -> None:
        """scans-get parses eval_summary + error + model_formats branches.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "uuid": "s-1",
            "eval_outcome": "BLOCKED",
            "eval_summary": {"rules_passed": 3, "rules_failed": 1, "total_rules": 4},
            "error_code": "E1",
            "error_message": "bad",
            "model_formats": ["safetensors"],
        }

        result = model_security_scans_get_command(mock_client, {"uuid": "s-1"})

        _, kwargs = mock_http.call_args
        assert kwargs["url_suffix"] == "/v1/scans/s-1"
        assert kwargs["use_model_sec_data"] is True
        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityScanGet"
        assert result.outputs["rules_failed"] == 1
        assert result.outputs["error_code"] == "E1"

    @patch.object(Client, "http_request")
    def test_model_security_labels_delete_full(self, mock_http: Mock, mock_client: Client) -> None:
        """labels-delete sends a DELETE and writes ModelSecurityLabelsDelete.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {}

        result = model_security_labels_delete_command(mock_client, {"scan_uuid": "s-1", "keys": "env,team"})

        _, kwargs = mock_http.call_args
        assert kwargs["method"] == "DELETE"
        assert kwargs["params"]["keys"] == ["env", "team"]
        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityLabelsDelete"
        assert result.outputs["keys_deleted"] == ["env", "team"]

    def test_model_security_labels_delete_validates(self, mock_client: Client) -> None:
        """labels-delete requires scan_uuid and keys.

        Args:
            mock_client: Mock client fixture.
        """
        with pytest.raises(ValueError, match="scan_uuid is required"):
            model_security_labels_delete_command(mock_client, {})
        with pytest.raises(ValueError, match="keys is required"):
            model_security_labels_delete_command(mock_client, {"scan_uuid": "s-1"})

    @patch.object(Client, "http_request")
    def test_model_security_rules_get_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-rules-get writes to its own query context, separate from list.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "r-1", "name": "PII Rule"}

        result = model_security_rules_get_command(mock_client, {"uuid": "r-1"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityRuleGet"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "r-1"

    @patch.object(Client, "http_request")
    def test_model_security_scans_create_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-scans-create writes to its own action context, separate from list/get.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "scan-1", "status": "PENDING"}

        result = model_security_scans_create_command(mock_client, {"model_uri": "hf://bert", "security_group_uuid": "sg-1"})

        # scan_origin defaults to MODEL_SECURITY_API when not provided.
        assert mock_http.call_args.kwargs["json_data"]["scan_origin"] == "MODEL_SECURITY_API"
        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityScanCreate"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "scan-1"

    @patch.object(Client, "http_request")
    def test_model_security_scans_create_scan_origin_override(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-scans-create passes an explicit scan_origin through to the request body.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "scan-2", "status": "PENDING"}

        model_security_scans_create_command(
            mock_client,
            {"model_uri": "hf://bert", "security_group_uuid": "sg-1", "scan_origin": "HUGGING_FACE"},
        )

        assert mock_http.call_args.kwargs["json_data"]["scan_origin"] == "HUGGING_FACE"

    @patch.object(Client, "http_request")
    def test_model_security_scans_create_with_labels(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-scans-create passes labels through and echoes them in context.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        labels = [{"key": "env", "value": "prod"}, {"key": "team", "value": "ml"}]
        mock_http.return_value = {"uuid": "scan-3", "status": "PENDING", "labels": labels}

        result = model_security_scans_create_command(
            mock_client,
            {"model_uri": "hf://bert", "security_group_uuid": "sg-1", "labels": json.dumps(labels)},
        )

        assert mock_http.call_args.kwargs["json_data"]["labels"] == labels
        assert result.outputs["labels"] == labels

    def test_model_security_scans_create_invalid_labels(self, mock_client: Client) -> None:
        """model-security-scans-create rejects malformed labels.

        Args:
            mock_client: Mock client fixture.
        """
        with pytest.raises(ValueError, match="labels must be a valid JSON array"):
            model_security_scans_create_command(
                mock_client, {"model_uri": "hf://bert", "security_group_uuid": "sg-1", "labels": "not-json"}
            )
        with pytest.raises(ValueError, match="each with 'key' and 'value'"):
            model_security_scans_create_command(
                mock_client,
                {"model_uri": "hf://bert", "security_group_uuid": "sg-1", "labels": '[{"key": "env"}]'},
            )

    @patch.object(Client, "http_request")
    def test_model_security_scans_get_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-scans-get writes to its own query context, separate from list/create.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "scan-1", "status": "DONE"}

        result = model_security_scans_get_command(mock_client, {"uuid": "scan-1"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityScanGet"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "scan-1"

    @patch.object(Client, "http_request")
    def test_model_security_scans_evaluation_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-scans-evaluation returns a single evaluation keyed by uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "e-1", "result": "PASS"}

        result = model_security_scans_evaluation_command(mock_client, {"uuid": "e-1"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityEvaluation"
        assert result.outputs_key_field == "uuid"

    @patch.object(Client, "http_request")
    def test_model_security_scans_violation_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-scans-violation returns a single violation keyed by uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "v-1", "severity": "HIGH"}

        result = model_security_scans_violation_command(mock_client, {"uuid": "v-1"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityViolationDetail"
        assert result.outputs_key_field == "uuid"

    @patch.object(Client, "http_request")
    def test_model_security_labels_keys_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-labels-keys returns the global key snapshot (no key field).

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"keys": ["env", "team"], "pagination": {"total_items": 2}}

        result = model_security_labels_keys_command(mock_client, {})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityLabelKeys"
        assert result.outputs_key_field is None
        assert result.outputs["keys"] == ["env", "team"]

    @patch.object(Client, "http_request")
    def test_model_security_groups_get_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-groups-get writes to its own query context.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "g-1", "name": "grp"}

        result = model_security_groups_get_command(mock_client, {"uuid": "g-1"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityGroupGet"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "g-1"

    @patch.object(Client, "http_request")
    def test_model_security_groups_create_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-groups-create writes to the Add action context.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "g-1", "name": "grp"}

        result = model_security_groups_create_command(mock_client, {"name": "grp", "source_type": "HUGGING_FACE"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityGroupAdd"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "g-1"

    @patch.object(Client, "http_request")
    def test_model_security_groups_update_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-groups-update writes to the Update action context.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"uuid": "g-1", "name": "grp-renamed"}

        result = model_security_groups_update_command(mock_client, {"uuid": "g-1", "name": "grp-renamed"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityGroupUpdate"
        assert result.outputs_key_field == "uuid"

    @patch.object(Client, "http_request")
    def test_model_security_groups_delete_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-groups-delete writes the Delete confirmation context.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = None

        result = model_security_groups_delete_command(mock_client, {"uuid": "g-1"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityGroupDelete"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "g-1"
        assert result.outputs["deleted"] is True

    def test_model_security_groups_delete_requires_uuid(self, mock_client: Client) -> None:
        """model-security-groups-delete raises when uuid is missing.

        Args:
            mock_client: Mock client fixture.
        """
        with pytest.raises(ValueError, match="uuid is required"):
            model_security_groups_delete_command(mock_client, {})

    @patch.object(Client, "http_request")
    def test_model_security_rule_instances_list_command(self, mock_http: Mock, mock_client: Client) -> None:
        """model-security-rule-instances-list returns instances under the base key.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"rule_instances": [{"uuid": "ri-1"}], "pagination": {"total_items": 1}}

        result = model_security_rule_instances_list_command(mock_client, {"security_group_uuid": "sg-1"})

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityRuleInstance"
        assert result.outputs_key_field == "uuid"

    @patch.object(Client, "http_request")
    def test_labels_add_accumulates_by_scan_uuid(self, mock_http: Mock, mock_client: Client) -> None:
        """labels-add keys context by scan_uuid so repeated runs accumulate distinct scan entries.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {}
        args = {"scan_uuid": "scan-1", "labels": '[{"key": "env", "value": "prod"}]'}

        result = model_security_labels_add_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityLabelsAdd"
        assert result.outputs_key_field == "scan_uuid"
        assert result.outputs["scan_uuid"] == "scan-1"
        # The DT-keyed context path is what makes repeated runs accumulate instead of overwrite.
        context = result.to_context()["EntryContext"]
        assert "PrismaAIRs.ModelSecurityLabelsAdd(val.scan_uuid && val.scan_uuid == obj.scan_uuid)" in context

    @patch.object(Client, "http_request")
    def test_labels_set_accumulates_by_scan_uuid(self, mock_http: Mock, mock_client: Client) -> None:
        """labels-set keys context by scan_uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {}
        args = {"scan_uuid": "scan-2", "labels": '[{"key": "env", "value": "staging"}]'}

        result = model_security_labels_set_command(mock_client, args)

        assert result.outputs_key_field == "scan_uuid"
        assert result.outputs["scan_uuid"] == "scan-2"

    @patch.object(Client, "http_request")
    def test_labels_delete_accumulates_by_scan_uuid(self, mock_http: Mock, mock_client: Client) -> None:
        """labels-delete keys context by scan_uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = None
        args = {"scan_uuid": "scan-3", "keys": "env,team"}

        result = model_security_labels_delete_command(mock_client, args)

        assert result.outputs_key_field == "scan_uuid"
        assert result.outputs["scan_uuid"] == "scan-3"
        assert result.outputs["keys_deleted"] == ["env", "team"]

    @patch.object(Client, "http_request")
    def test_labels_values_accumulates_by_key(self, mock_http: Mock, mock_client: Client) -> None:
        """labels-values keys context by the queried label key.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"values": ["prod", "staging"], "pagination": {"total_items": 2}}
        args = {"key": "env"}

        result = model_security_labels_values_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityLabelValues"
        assert result.outputs_key_field == "key"
        assert result.outputs["key"] == "env"
        context = result.to_context()["EntryContext"]
        assert "PrismaAIRs.ModelSecurityLabelValues(val.key && val.key == obj.key)" in context

    @patch.object(Client, "http_request")
    def test_rule_instances_get_uses_own_keyed_context(self, mock_http: Mock, mock_client: Client) -> None:
        """rule-instances-get writes to its own context key, keyed by the instance uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "uuid": "ri-1",
            "security_group_uuid": "sg-1",
            "security_rule_uuid": "sr-1",
            "state": "BLOCKING",
            "rule": {"name": "PII", "rule_type": "dlp"},
        }
        args = {"security_group_uuid": "sg-1", "rule_instance_uuid": "ri-1"}

        result = model_security_rule_instances_get_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityRuleInstanceGet"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "ri-1"
        context = result.to_context()["EntryContext"]
        assert "PrismaAIRs.ModelSecurityRuleInstanceGet(val.uuid && val.uuid == obj.uuid)" in context

    @patch.object(Client, "http_request")
    def test_rule_instances_update_uses_own_keyed_context(self, mock_http: Mock, mock_client: Client) -> None:
        """rule-instances-update writes to its own context key, keyed by the instance uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {
            "uuid": "ri-2",
            "security_group_uuid": "sg-1",
            "security_rule_uuid": "sr-1",
            "state": "DISABLED",
            "rule": {"name": "PII", "rule_type": "dlp"},
        }
        args = {"security_group_uuid": "sg-1", "rule_instance_uuid": "ri-2", "state": "DISABLED"}

        result = model_security_rule_instances_update_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityRuleInstanceUpdate"
        assert result.outputs_key_field == "uuid"
        assert result.outputs["uuid"] == "ri-2"
        # Verify it does NOT pollute the list/get context keys
        context = result.to_context()["EntryContext"]
        assert "PrismaAIRs.ModelSecurityRuleInstanceUpdate(val.uuid && val.uuid == obj.uuid)" in context

    @patch.object(Client, "http_request")
    def test_scans_violations_accumulates_by_scan_uuid(self, mock_http: Mock, mock_client: Client) -> None:
        """scans-violations (list) keys its per-scan wrapper by scan_uuid (not the missing top-level uuid).

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"violations": [{"uuid": "v-1"}], "pagination": {"total_items": 1}}
        args = {"uuid": "scan-1"}

        result = model_security_scans_violations_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityViolation"
        assert result.outputs_key_field == "scan_uuid"
        assert result.outputs["scan_uuid"] == "scan-1"
        context = result.to_context()["EntryContext"]
        assert "PrismaAIRs.ModelSecurityViolation(val.scan_uuid && val.scan_uuid == obj.scan_uuid)" in context

    @patch.object(Client, "http_request")
    def test_scans_evaluations_accumulates_by_scan_uuid(self, mock_http: Mock, mock_client: Client) -> None:
        """scans-evaluations (list) keys its per-scan wrapper by scan_uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"evaluations": [{"uuid": "e-1"}], "pagination": {"total_items": 1}}
        args = {"scan_uuid": "scan-2"}

        result = model_security_scans_evaluations_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityEvaluations"
        assert result.outputs_key_field == "scan_uuid"
        assert result.outputs["scan_uuid"] == "scan-2"

    @patch.object(Client, "http_request")
    def test_scans_files_accumulates_by_scan_uuid(self, mock_http: Mock, mock_client: Client) -> None:
        """scans-files (list) keys its per-scan wrapper by scan_uuid.

        Args:
            mock_http: Mocked http_request method.
            mock_client: Mock client fixture.
        """
        mock_http.return_value = {"files": [{"uuid": "f-1"}], "pagination": {"total_items": 1}}
        args = {"scan_uuid": "scan-3"}

        result = model_security_scans_files_command(mock_client, args)

        assert result.outputs_prefix == "PrismaAIRs.ModelSecurityFiles"
        assert result.outputs_key_field == "scan_uuid"
        assert result.outputs["scan_uuid"] == "scan-3"